123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- 'use strict';
- var typeOf = require('kind-of');
- module.exports = function base(app, options) {
- if (typeOf(app) !== 'object' && typeof app !== 'function') {
- throw new TypeError('expected an object or function');
- }
- var opts = typeOf(options) === 'object' ? options : {};
- var prop = typeof opts.prop === 'string' ? opts.prop : 'fns';
- if (!Array.isArray(app[prop])) {
- define(app, prop, []);
- }
-
- define(app, 'use', use);
-
- define(app, 'run', function(val) {
- if (typeOf(val) !== 'object') return;
- if (!val.use || !val.run) {
- define(val, prop, val[prop] || []);
- define(val, 'use', use);
- }
- if (!val[prop] || val[prop].indexOf(base) === -1) {
- val.use(base);
- }
- var self = this || app;
- var fns = self[prop];
- var len = fns.length;
- var idx = -1;
- while (++idx < len) {
- val.use(fns[idx]);
- }
- return val;
- });
-
- function use(type, fn, options) {
- var offset = 1;
- if (typeof type === 'string' || Array.isArray(type)) {
- fn = wrap(type, fn);
- offset++;
- } else {
- options = fn;
- fn = type;
- }
- if (typeof fn !== 'function') {
- throw new TypeError('expected a function');
- }
- var self = this || app;
- var fns = self[prop];
- var args = [].slice.call(arguments, offset);
- args.unshift(self);
- if (typeof opts.hook === 'function') {
- opts.hook.apply(self, args);
- }
- var val = fn.apply(self, args);
- if (typeof val === 'function' && fns.indexOf(val) === -1) {
- fns.push(val);
- }
- return self;
- }
-
- function wrap(type, fn) {
- return function plugin() {
- return this.type === type ? fn.apply(this, arguments) : plugin;
- };
- }
- return app;
- };
- function define(obj, key, val) {
- Object.defineProperty(obj, key, {
- configurable: true,
- writable: true,
- value: val
- });
- }
|