The Feathers-Pinia Client
Wrap your Feathers Client in pure productivity.
createPiniaClient
The createPiniaClient
utility is the primary utility in Feathers-Pinia. It wraps the Feathers Client and enhances it with additional service methods.
createPiniaClient(feathersClient, {
pinia: nuxt.$pinia,
ssr: !!process.server,
storage: window.localStorage,
// below are configurable per service in the `services` object.
idField: '_id',
syncWithStorage: true || ['itemsById', 'pagination', 'etc'],
whitelist: ['$customLocalParam'],
paramsForServer: ['$customServerParam'],
skipGetIfExists: true,
handleEvents: {}, // HandleEvents<AnyData>
debounceEventsTime: 20,
debounceEventsGuarantee: false,
customSiftOperators: {}, // see sift docs
customFilters: {}, // see custom query filters
// runs for every service
setupInstance: (data = {}, { api, service, servicePath }) => {
if (servicePath.startsWith('my-')) {
Object.defineProperty(data, 'belongsToMe', {
get() {
return true
}
})
}
return data
},
customizeStore(defaultStore) {
// You can directly modify the defaultStore object
defaultStore.globalValue = ref(true)
},
// Service config, keyed by path, See service configuration to
// learn how options are merged with the global config.
services: {
users: {
idField: 'id',
},
contacts: {
whitelist: ['$test'],
// runs after the global setupInstance
setupInstance(data: any, { api, service, servicePath }) {
const withDefaults = useInstanceDefaults({ name: '', age: 0 }, data)
return withDefaults
},
// customize the store for a single service
customizeStore(defaultStore) {
defaultStore.contactsValue = ref(true)
return { otherValue: true } // returned values will be merged, as well
}
},
tasks: {
skipGetIfExists: true,
},
},
})
See the configuration sections, below, for the possible configuration values.
Client Properties
The createPiniaClient
utility returns a wrapped FeathersPinia Client with the following added properties:
pushToStore(data: any, servicePath: string)
pushes data into another service store.defineVirtualProperty(data: any, key: string, getter: Function)
sets up a virtual property on an object.defineVirtualProperties(data: any, virtuals: Record<string, Function>)
sets up many virtual properties on an object.
Learn more about these properties in the Data Modeling guide.
Global Configuration
The pseudo-interface, below, shows possible configuration values with their default values. Values not followed by ?
are required and have no default value.
interface CreatePiniaClientConfig {
idField: string
pinia: Pinia
ssr?: false
storage?: undefined
services?: Record<string, PiniaServiceConfig>
// global and per-service options
syncWithStorage?: undefined
whitelist?: string[]
paramsForServer?: string[]
skipGetIfExists?: true
handleEvents?: HandleEvents<AnyData>
debounceEventsTime?: 20
debounceEventsGuarantee?: false
customSiftOperators?: Record<string, SiftOperator>
setupInstance?: (data = {}, { api, service, servicePath }) => (modifiedData)
customizeStore?: (defaultStore) => modifiedStore
}
Let's take a closer look at each one:
idField {String}
is the attribute on the record that will serve as the unique identifier or "primary key" in the database.pinia {Pinia}
your app's primary Pinia instance. Allows dynamic creation of stores.ssr {Boolean}
indicates if Feathers-Pinia is loading in an SSR environment. Paginated queries made during SSR will be marked withssr: true
. When a matching request is made on the client (whenssr
is false) the store data will clear thessr
flag for that request.storage {Storage}
aStorage
interface. Must be provided to enable storage sync. The most typical option iswindow.localStorage
.services {Record<string, PiniaServiceConfig>}
an object, keyed by service path, which allows passing specific configuration to individual services. See Service Configuration.syncWithStorage
can be set totrue
or to an array of store keys to sync to thestorage
adapter. If set totrue
, the default keys will be used, which are['itemsById', 'pagination']
. See Storage Syncwhitelist
is an array of keys to allow in thefindInStore
queries.paramsForServer
is an array of query keys forfindInStore
to ignore and pass to thefind
action's query.skipGetIfExists {Boolean}
when enabled will cause a.get
request to automatically resolve with the stored record, if one exists. If not, the request will be made as normal.handleEvents {Object}
is an object that lets you customize how realtime events are handled. Each key is a nameof a realtime event handler function:
created
,patched
,updated
, orremoved
. You can provide your own handlerto customize and override individual events. The handler's function signature is
tsfunction eventHandler(data, { service }) { // handle event } const handleEvents = { created: eventHandler, patched: eventHandler, updated: eventHandler, removed: eventHandler, }
debounceEventsTime {Number}
determines how long to wait until flushing a batch of events. Defaults to20
. If no events have been received in a 20 millisecond period, all gathered events will be processed.debounceEventsGuarantee {Boolean}
forces accumulated events to flush everydebounceEventsTime
interval. Off by default.customSiftOperators {Object}
allows passing an object of custom sift operators which are used to query data from the store withfindInStore
anduseFind
. All sift operators are enabled for store queries.customFilters {Object}
allows passing an object of custom query filters. See Custom Query FilterssetupInstance {Function}
a global model function that allows modifying instances from all services. It has the following shape:ts// modify data and return the modified object function setupInstance(data, { app, service, servicePath }) { return data }
customizeStore {Function}
a function that allows modifying the store for all services. Return the modified store or an object to merge into the store.
Service Configuration
interface PiniaServiceConfig {
/**
* The name of the store to use for this service. Defaults to `service:${servicePath}`.
* You can also use storeName to make two services share the same store.
*/
storeName?: string
/**
* Overrides the service used for instance-level service methods, like patch, and remove.
* Useful for "proxy" services. For example: `pages/full` loads the page record with populated
* data, but you want to patch/remove the record through the `pages` service.
*/
instanceServicePath?: string
/**
* The name of the id field for this service. Overrides the global idField.
*/
idField?: string
whitelist?: string[]
paramsForServer?: string[]
skipGetIfExists?: boolean
handleEvents?: HandleEvents<AnyData>
debounceEventsTime?: number
debounceEventsGuarantee?: boolean
setupInstance?: (data: any, utils: SetupInstanceUtils) => any
customizeStore?: (data: ReturnType<typeof useServiceStore>) => Record<string, any>
customSiftOperators?: Record<string, any>
}
interface SetupInstanceUtils {
app?: any
service?: any
servicePath?: string
}
The storeName
and instanceServicePath
options were introduced in Feathers-Pinia 4.2. They are not configurable at the global level.
storeName {String}
is the name of the store to use for this service. Defaults toservice:${servicePath}
. You can also usestoreName
to make two services share the same store.instanceServicePath {String}
overrides the service used for instance-level service methods, likepatch
, andremove
. Useful for "proxy" services. For example:pages/full
loads the page record with populated data, but you want to patch/remove the record through thepages
service.
These options are all configurable at the global and service levels. See descriptions in the global configuration section. Here is a description of how each option is handled when it's also configured globally:
idField
overrides the global valuewhitelist
concatenated with the global valueparamsForServer
concatenated with the global valueskipGetIfExists {Boolean}
overrides the global valuehandleEvents {Object}
overrides the global valuedebounceEventsTime {Number}
overrides the global valuedebounceEventsGuarantee {Boolean}
overrides the global valuecustomSiftOperators {Object}
merged over the global valuesetupInstance {Function}
runs after the global value. The globalsetupInstance
will already have been applied by the time the service-levelsetupInstance
runs.customizeStore {Function}
runs after the globalcustomizeStore
and receives the store data with globally- customized values.