index.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. /*!
  2. * use <https://github.com/jonschlinkert/use>
  3. *
  4. * Copyright (c) 2015, 2017, Jon Schlinkert.
  5. * Released under the MIT License.
  6. */
  7. 'use strict';
  8. var utils = require('./utils');
  9. module.exports = function base(app, opts) {
  10. if (!utils.isObject(app) && typeof app !== 'function') {
  11. throw new TypeError('use: expect `app` be an object or function');
  12. }
  13. if (!utils.isObject(opts)) {
  14. opts = {};
  15. }
  16. var prop = utils.isString(opts.prop) ? opts.prop : 'fns';
  17. if (!Array.isArray(app[prop])) {
  18. utils.define(app, prop, []);
  19. }
  20. /**
  21. * Define a plugin function to be passed to use. The only
  22. * parameter exposed to the plugin is `app`, the object or function.
  23. * passed to `use(app)`. `app` is also exposed as `this` in plugins.
  24. *
  25. * Additionally, **if a plugin returns a function, the function will
  26. * be pushed onto the `fns` array**, allowing the plugin to be
  27. * called at a later point by the `run` method.
  28. *
  29. * ```js
  30. * var use = require('use');
  31. *
  32. * // define a plugin
  33. * function foo(app) {
  34. * // do stuff
  35. * }
  36. *
  37. * var app = function(){};
  38. * use(app);
  39. *
  40. * // register plugins
  41. * app.use(foo);
  42. * app.use(bar);
  43. * app.use(baz);
  44. * ```
  45. * @name .use
  46. * @param {Function} `fn` plugin function to call
  47. * @api public
  48. */
  49. utils.define(app, 'use', use);
  50. /**
  51. * Run all plugins on `fns`. Any plugin that returns a function
  52. * when called by `use` is pushed onto the `fns` array.
  53. *
  54. * ```js
  55. * var config = {};
  56. * app.run(config);
  57. * ```
  58. * @name .run
  59. * @param {Object} `value` Object to be modified by plugins.
  60. * @return {Object} Returns the object passed to `run`
  61. * @api public
  62. */
  63. utils.define(app, 'run', function(val) {
  64. if (!utils.isObject(val)) return;
  65. decorate(val);
  66. var self = this || app;
  67. var fns = self[prop];
  68. var len = fns.length;
  69. var idx = -1;
  70. while (++idx < len) {
  71. val.use(fns[idx]);
  72. }
  73. return val;
  74. });
  75. /**
  76. * Call plugin `fn`. If a function is returned push it into the
  77. * `fns` array to be called by the `run` method.
  78. */
  79. function use(fn, options) {
  80. if (typeof fn !== 'function') {
  81. throw new TypeError('.use expects `fn` be a function');
  82. }
  83. var self = this || app;
  84. if (typeof opts.fn === 'function') {
  85. opts.fn.call(self, self, options);
  86. }
  87. var plugin = fn.call(self, self);
  88. if (typeof plugin === 'function') {
  89. var fns = self[prop];
  90. fns.push(plugin);
  91. }
  92. return self;
  93. }
  94. /**
  95. * Ensure the `.use` method exists on `val`
  96. */
  97. function decorate(val) {
  98. if (!val.use || !val.run) {
  99. base(val);
  100. }
  101. }
  102. return app;
  103. };