Skip to content

Commit

Permalink
feat: new “extend” method for makeServicePlugin
Browse files Browse the repository at this point in the history
## API

```
import { makeServicePlugin } from ‘feathers-vuex’
import { feathersClient } from ‘./feathers-client.js’

class Todo { /* truncated */ }

makeServicePlugin({
  Model: Todo,
  service: feathersClient.service(‘todos’),
  extend({ store, module }) {
    // Listen to other parts of the store
    store.watch(/* truncated */)

    return {
      state: {},
      getters: {},
      mutations: {},
      actions: {}
    }
  }
})

The old options for customizing the store are still fully functional.  The `module` object in the options contains the default state, getters, mutations, and actions merged with the ones provided in the options.  They are made available in case this is useful; however, they do not need to be returned  `extend` method’s return object.  The object returned from `extend` will be merged over the top of the ones in `module`.

As a result of this change, the following options are now deprecated in the `makeServicePlugin` method:

- state
- getters
- mutations
- actions

## History and Relevance

Up until now, `makeServicePlugin` and `makeAuthPlugin` have supported passing `state`, `getters`, `mutations`, and `actions` as keys in the options as shown here:

![Screen Shot 2020-10-29 at 1 14 15 PM](https://user-images.githubusercontent.com/128857/97621627-c8637380-19e8-11eb-9523-98a485440ef0.jpg)

This is nice and clean until you need access to the `store` variable to access APIs like `store.watch` (when you want a clean way to define related logic between multiple vuex modules).

This issue specifically showed up when I wanted a purely-logical, non-template-based method of watching for authentication from Auth0.  Up until now, I have always used the “Gateway Component” pattern that has a conditional in it for if auth is present, then put the majority of the app logic in a child component.  As shown in the above example, this extra logic can now live inside the same module as the rest of the service and vuex plugin definition.
  • Loading branch information
marshallswain committed Oct 29, 2020
1 parent 8d399fa commit 4c8a627
Show file tree
Hide file tree
Showing 5 changed files with 285 additions and 103 deletions.
32 changes: 21 additions & 11 deletions src/service-module/make-service-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,37 @@ eslint
@typescript-eslint/explicit-function-return-type: 0,
@typescript-eslint/no-explicit-any: 0
*/
import _pick from 'lodash/pick'
import _merge from 'lodash/merge'
import makeDefaultState from './service-module.state'
import makeGetters from './service-module.getters'
import makeMutations from './service-module.mutations'
import makeActions from './service-module.actions'
import { Service } from '@feathersjs/feathers'
import { MakeServicePluginOptions } from './types'
import { Store } from 'vuex'

export default function makeServiceModule(
service: Service<any>,
options: MakeServicePluginOptions
options: MakeServicePluginOptions,
store: Store<any>
) {
const defaultState = makeDefaultState(options)
const defaultGetters = makeGetters()
const defaultMutations = makeMutations()
const defaultActions = makeActions(service)

return {
const defaults = {
namespaced: true,
state: Object.assign({}, defaultState, options.state),
getters: Object.assign({}, defaultGetters, options.getters),
mutations: Object.assign({}, defaultMutations, options.mutations),
actions: Object.assign({}, defaultActions, options.actions)
state: makeDefaultState(options),
getters: makeGetters(),
mutations: makeMutations(),
actions: makeActions(service)
}
const fromOptions = _pick(options, [
'state',
'getters',
'mutations',
'actions'
])
const merged = _merge({}, defaults, fromOptions)
const extended = options.extend({ store, module: merged })
const finalModule = _merge({}, merged, extended)

return finalModule
}
18 changes: 16 additions & 2 deletions src/service-module/make-service-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@ eslint
@typescript-eslint/explicit-function-return-type: 0,
@typescript-eslint/no-explicit-any: 0
*/
import { FeathersVuexOptions, MakeServicePluginOptions } from './types'
import {
FeathersVuexOptions,
MakeServicePluginOptions,
ServicePluginExtendOptions
} from './types'

import makeServiceModule from './make-service-module'
import { globalModels, prepareAddModel } from './global-models'
import enableServiceEvents from './service-module.events'
Expand All @@ -13,6 +18,14 @@ import _get from 'lodash/get'
interface ServiceOptionsDefaults {
servicePath: string
namespace: string
extend: (
options: ServicePluginExtendOptions
) => {
state: any
getters: any
mutations: any
actions: any
}
state: {}
getters: {}
mutations: {}
Expand All @@ -25,6 +38,7 @@ interface ServiceOptionsDefaults {
const defaults: ServiceOptionsDefaults = {
namespace: '', // The namespace for the Vuex module. Will generally be derived from the service.path, service.name, when available. Otherwise, it must be provided here, explicitly.
servicePath: '',
extend: ({ module }) => module, // for custom plugin (replaces state, getters, mutations, and actions)
state: {}, // for custom state
getters: {}, // for custom getters
mutations: {}, // for custom mutations
Expand Down Expand Up @@ -91,7 +105,7 @@ export default function prepareMakeServicePlugin(
return store => {
// (1^) Create and register the Vuex module
options.namespace = makeNamespace(namespace, servicePath, nameStyle)
const module = makeServiceModule(service, options)
const module = makeServiceModule(service, options, store)
// Don't preserve state if reinitialized (prevents state pollution in SSR)
store.registerModule(options.namespace, module, { preserveState: false })

Expand Down
1 change: 1 addition & 0 deletions src/service-module/service-module.state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ export default function makeDefaultState(options: MakeServicePluginOptions) {
'instanceDefaults',
'setupInstance',
'handleEvents',
'extend',
'state',
'getters',
'mutations',
Expand Down
14 changes: 14 additions & 0 deletions src/service-module/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ export interface HandleEvents {
removed?: Function
}

export interface ServicePluginExtendOptions {
store: Store<any>
module: any
}

export interface MakeServicePluginOptions {
Model: any
service: Service<any>
Expand Down Expand Up @@ -64,6 +69,15 @@ export interface MakeServicePluginOptions {
instanceDefaults?: () => {}
setupInstance?: (data: any, { models, store }) => {}
handleEvents?: HandleEvents

extend?: (
options: ServicePluginExtendOptions
) => {
state?: any
getters?: any
mutations?: any
actions?: any
}
state?: {}
getters?: {}
mutations?: {}
Expand Down
Loading

0 comments on commit 4c8a627

Please sign in to comment.