122 lines
2.6 KiB
JavaScript
122 lines
2.6 KiB
JavaScript
|
/*!
|
||
|
* use <https://github.com/jonschlinkert/use>
|
||
|
*
|
||
|
* Copyright (c) 2015, 2017, Jon Schlinkert.
|
||
|
* Released under the MIT License.
|
||
|
*/
|
||
|
|
||
|
'use strict';
|
||
|
|
||
|
var utils = require('./utils');
|
||
|
|
||
|
module.exports = function base(app, opts) {
|
||
|
if (!utils.isObject(app) && typeof app !== 'function') {
|
||
|
throw new TypeError('use: expect `app` be an object or function');
|
||
|
}
|
||
|
|
||
|
if (!utils.isObject(opts)) {
|
||
|
opts = {};
|
||
|
}
|
||
|
|
||
|
var prop = utils.isString(opts.prop) ? opts.prop : 'fns';
|
||
|
if (!Array.isArray(app[prop])) {
|
||
|
utils.define(app, prop, []);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Define a plugin function to be passed to use. The only
|
||
|
* parameter exposed to the plugin is `app`, the object or function.
|
||
|
* passed to `use(app)`. `app` is also exposed as `this` in plugins.
|
||
|
*
|
||
|
* Additionally, **if a plugin returns a function, the function will
|
||
|
* be pushed onto the `fns` array**, allowing the plugin to be
|
||
|
* called at a later point by the `run` method.
|
||
|
*
|
||
|
* ```js
|
||
|
* var use = require('use');
|
||
|
*
|
||
|
* // define a plugin
|
||
|
* function foo(app) {
|
||
|
* // do stuff
|
||
|
* }
|
||
|
*
|
||
|
* var app = function(){};
|
||
|
* use(app);
|
||
|
*
|
||
|
* // register plugins
|
||
|
* app.use(foo);
|
||
|
* app.use(bar);
|
||
|
* app.use(baz);
|
||
|
* ```
|
||
|
* @name .use
|
||
|
* @param {Function} `fn` plugin function to call
|
||
|
* @api public
|
||
|
*/
|
||
|
|
||
|
utils.define(app, 'use', use);
|
||
|
|
||
|
/**
|
||
|
* Run all plugins on `fns`. Any plugin that returns a function
|
||
|
* when called by `use` is pushed onto the `fns` array.
|
||
|
*
|
||
|
* ```js
|
||
|
* var config = {};
|
||
|
* app.run(config);
|
||
|
* ```
|
||
|
* @name .run
|
||
|
* @param {Object} `value` Object to be modified by plugins.
|
||
|
* @return {Object} Returns the object passed to `run`
|
||
|
* @api public
|
||
|
*/
|
||
|
|
||
|
utils.define(app, 'run', function(val) {
|
||
|
if (!utils.isObject(val)) return;
|
||
|
decorate(val);
|
||
|
|
||
|
var self = this || app;
|
||
|
var fns = self[prop];
|
||
|
var len = fns.length;
|
||
|
var idx = -1;
|
||
|
|
||
|
while (++idx < len) {
|
||
|
val.use(fns[idx]);
|
||
|
}
|
||
|
return val;
|
||
|
});
|
||
|
|
||
|
/**
|
||
|
* Call plugin `fn`. If a function is returned push it into the
|
||
|
* `fns` array to be called by the `run` method.
|
||
|
*/
|
||
|
|
||
|
function use(fn, options) {
|
||
|
if (typeof fn !== 'function') {
|
||
|
throw new TypeError('.use expects `fn` be a function');
|
||
|
}
|
||
|
|
||
|
var self = this || app;
|
||
|
if (typeof opts.fn === 'function') {
|
||
|
opts.fn.call(self, self, options);
|
||
|
}
|
||
|
|
||
|
var plugin = fn.call(self, self);
|
||
|
if (typeof plugin === 'function') {
|
||
|
var fns = self[prop];
|
||
|
fns.push(plugin);
|
||
|
}
|
||
|
return self;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Ensure the `.use` method exists on `val`
|
||
|
*/
|
||
|
|
||
|
function decorate(val) {
|
||
|
if (!val.use || !val.run) {
|
||
|
base(val);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return app;
|
||
|
};
|