@@ -19,7 +19,7 @@ A plugin return value may contain any of these keys, where `myStateKey` is a nam | |||
}, | |||
components: {}, | |||
wrapComponents: {}, | |||
afterLoad: (system) => {} | |||
afterLoad: (system) => {}, | |||
fn: {}, | |||
} | |||
``` | |||
@@ -366,9 +366,11 @@ const MyWrapComponentPlugin = function(system) { | |||
##### `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 directly to the plugin context. | |||
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 +378,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") | |||