Merge pull request #4059 from shockey/master
Refactor `afterLoad` interface to expose raw plugin context
This commit is contained in:
@@ -19,7 +19,8 @@ A plugin return value may contain any of these keys, where `myStateKey` is a nam
|
||||
},
|
||||
components: {},
|
||||
wrapComponents: {},
|
||||
afterLoad: (system) => {}
|
||||
rootInjects: {},
|
||||
afterLoad: (system) => {},
|
||||
fn: {},
|
||||
}
|
||||
```
|
||||
@@ -364,11 +365,30 @@ const MyWrapComponentPlugin = function(system) {
|
||||
}
|
||||
```
|
||||
|
||||
##### `rootInjects`
|
||||
|
||||
The `rootInjects` interface allows you to inject values at the top level of the system.
|
||||
|
||||
This interface takes an object, which will be merged in with the top-level system object at runtime.
|
||||
|
||||
```js
|
||||
const MyRootInjectsPlugin = function(system) {
|
||||
return {
|
||||
rootInjects: {
|
||||
myConstant: 123,
|
||||
myMethod: (...params) => console.log(...params)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
##### `afterLoad`
|
||||
|
||||
The `afterLoad` plugin method allows you to get a reference to the system after your plugin has been registered with the system.
|
||||
The `afterLoad` plugin method allows you to get a reference to the system after your plugin has been registered.
|
||||
|
||||
This interface is used in the core code to attach methods that are driven by bound selectors or actions directly to the system.
|
||||
This interface is used in the core code to attach methods that are driven by bound selectors or actions. You can also use it to execute logic that requires your plugin to already be ready, for example fetching initial data from a remote endpoint and passing it to an action your plugin creates.
|
||||
|
||||
The plugin context, which is bound to `this`, is undocumented, but below is an example of how to attach a bound action as a top-level method:
|
||||
|
||||
```javascript
|
||||
const MyMethodProvidingPlugin = function() {
|
||||
@@ -376,7 +396,8 @@ const MyMethodProvidingPlugin = function() {
|
||||
afterLoad(system) {
|
||||
// at this point in time, your actions have been bound into the system
|
||||
// so you can do things with them
|
||||
system.myMethod = system.exampleActions.updateFavoriteColor
|
||||
this.rootInjects = this.rootInjects || {}
|
||||
this.rootInjects.myMethod = system.exampleActions.updateFavoriteColor
|
||||
},
|
||||
statePlugins: {
|
||||
example: {
|
||||
|
||||
@@ -6,7 +6,8 @@ import * as specWrapActionReplacements from "./spec-wrap-actions"
|
||||
export default function() {
|
||||
return {
|
||||
afterLoad(system) {
|
||||
system.initOAuth = system.authActions.configureAuth
|
||||
this.rootInjects = this.rootInjects || {}
|
||||
this.rootInjects.initOAuth = system.authActions.configureAuth
|
||||
},
|
||||
statePlugins: {
|
||||
auth: {
|
||||
|
||||
@@ -68,13 +68,11 @@ export default class Store {
|
||||
if(rebuild) {
|
||||
this.buildSystem()
|
||||
}
|
||||
|
||||
if(Array.isArray(plugins)) {
|
||||
plugins.forEach(plugin => {
|
||||
if(plugin.afterLoad) {
|
||||
plugin.afterLoad(this.getSystem())
|
||||
}
|
||||
})
|
||||
|
||||
const needAnotherRebuild = callAfterLoad.call(this.system, plugins, this.getSystem())
|
||||
|
||||
if(needAnotherRebuild) {
|
||||
this.buildSystem()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -328,6 +326,25 @@ function combinePlugins(plugins, toolbox) {
|
||||
return {}
|
||||
}
|
||||
|
||||
function callAfterLoad(plugins, system, { hasLoaded } = {}) {
|
||||
let calledSomething = hasLoaded
|
||||
if(isObject(plugins) && !isArray(plugins)) {
|
||||
if(typeof plugins.afterLoad === "function") {
|
||||
calledSomething = true
|
||||
plugins.afterLoad.call(this, system)
|
||||
}
|
||||
}
|
||||
|
||||
if(isFunc(plugins))
|
||||
return callAfterLoad.call(this, plugins(system), system, { hasLoaded: calledSomething })
|
||||
|
||||
if(isArray(plugins)) {
|
||||
return plugins.map(plugin => callAfterLoad.call(this, plugin, system, { hasLoaded: calledSomething }))
|
||||
}
|
||||
|
||||
return calledSomething
|
||||
}
|
||||
|
||||
// Wraps deepExtend, to account for certain fields, being wrappers.
|
||||
// Ie: we need to convert some fields into arrays, and append to them.
|
||||
// Rather than overwrite
|
||||
|
||||
@@ -684,13 +684,13 @@ describe("bound system", function(){
|
||||
})
|
||||
|
||||
describe("afterLoad", function() {
|
||||
it("should call an plugin's `afterLoad` method after the plugin is loaded", function() {
|
||||
it("should call a plugin's `afterLoad` method after the plugin is loaded", function() {
|
||||
// Given
|
||||
const system = new System({
|
||||
plugins: [
|
||||
{
|
||||
afterLoad(system) {
|
||||
system.wow = system.dogeSelectors.wow
|
||||
this.rootInjects.wow = system.dogeSelectors.wow
|
||||
},
|
||||
statePlugins: {
|
||||
doge: {
|
||||
@@ -705,6 +705,89 @@ describe("bound system", function(){
|
||||
]
|
||||
})
|
||||
|
||||
// When
|
||||
var res = system.getSystem().wow()
|
||||
expect(res).toEqual("so selective")
|
||||
})
|
||||
it("should call a preset plugin's `afterLoad` method after the plugin is loaded", function() {
|
||||
// Given
|
||||
const MyPlugin = {
|
||||
afterLoad(system) {
|
||||
this.rootInjects.wow = system.dogeSelectors.wow
|
||||
},
|
||||
statePlugins: {
|
||||
doge: {
|
||||
selectors: {
|
||||
wow: () => (system) => {
|
||||
return "so selective"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const system = new System({
|
||||
plugins: [
|
||||
[MyPlugin]
|
||||
]
|
||||
})
|
||||
|
||||
// When
|
||||
var res = system.getSystem().wow()
|
||||
expect(res).toEqual("so selective")
|
||||
})
|
||||
it("should call a function preset plugin's `afterLoad` method after the plugin is loaded", function() {
|
||||
// Given
|
||||
const MyPlugin = {
|
||||
afterLoad(system) {
|
||||
this.rootInjects.wow = system.dogeSelectors.wow
|
||||
},
|
||||
statePlugins: {
|
||||
doge: {
|
||||
selectors: {
|
||||
wow: () => (system) => {
|
||||
return "so selective"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const system = new System({
|
||||
plugins: [
|
||||
() => {
|
||||
return [MyPlugin]
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
// When
|
||||
var res = system.getSystem().wow()
|
||||
expect(res).toEqual("so selective")
|
||||
})
|
||||
it("should call a registered plugin's `afterLoad` method after the plugin is loaded", function() {
|
||||
// Given
|
||||
const MyPlugin = {
|
||||
afterLoad(system) {
|
||||
this.rootInjects.wow = system.dogeSelectors.wow
|
||||
},
|
||||
statePlugins: {
|
||||
doge: {
|
||||
selectors: {
|
||||
wow: () => (system) => {
|
||||
return "so selective"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const system = new System({
|
||||
plugins: []
|
||||
})
|
||||
|
||||
system.register([MyPlugin])
|
||||
|
||||
// When
|
||||
var res = system.getSystem().wow()
|
||||
expect(res).toEqual("so selective")
|
||||
|
||||
Reference in New Issue
Block a user