1 | ;
|
2 |
|
3 | var path = require('path');
|
4 | var util = require('util');
|
5 | var async = require('async');
|
6 | var EventEmitter = require('events').EventEmitter;
|
7 | var Klect = require('klect');
|
8 |
|
9 | util.inherits(Bijous, EventEmitter);
|
10 |
|
11 | /**
|
12 | * @callback Bijous~moduleCallback
|
13 | * @desc The callback used when loading modules to tell {@linkcode Bijous} that the module has completed loading.
|
14 | * @param {object=} error - If an error occurs the callback will receive an error object
|
15 | * @param {*=} results - An object used to represent the module after loading
|
16 | */
|
17 |
|
18 | /**
|
19 | * @callback Bijous~module
|
20 | * @desc A module to be loaded by {@linkcode Bijous}. This callback must be the sole export of the node module's
|
21 | * entry-point.
|
22 | * @param {Bijous} context - The {@linkcode Bijous} object that is loading the module
|
23 | * @param {Bijous~moduleCallback} done - The callback that alerts {@linkcode Bijous} the async task is complete.
|
24 | * @example
|
25 | * // We may assume this resides in a file modules/module1/index.js
|
26 | * exports = module.exports = function (context, done) {
|
27 | * done(null, null);
|
28 | * }
|
29 | */
|
30 |
|
31 | /**
|
32 | * An asynchronous module loader. Searches out {@linkcode Bijous~module|modules} and loads them asynchronously.
|
33 | * @class
|
34 | * @param {object=} options
|
35 | * @param {string=} options.cwd - Override the current working directory
|
36 | * @param {object=} options.bundles - Override the [klect]{@link https://github.com/awnist/klect} bundles description
|
37 | * @property {string} cwd - The current working directory, used to find modules. Defaults to the directory the module's
|
38 | * parent resides in
|
39 | * @property {object} bundles - The [klect]{@link https://github.com/awnist/klect} bundles description, used to find
|
40 | * modules. Defaults to {@linkcode Bijous#defaultBundles}
|
41 | * @property {object} modules - An object containing keys that represent results returned by modules when the
|
42 | * {@linkcode Bijous#load} method is called. The keys correspond with the module's filename, not including the
|
43 | * extension. (e.g. modules/module1 would have a key module1 and modules/module2.js would have a key module2)
|
44 | */
|
45 | function Bijous(options) {
|
46 | options = options || {};
|
47 | EventEmitter.call(this);
|
48 |
|
49 | var mod = module.parent;
|
50 |
|
51 | this.cwd = options.cwd || path.dirname(mod.filename);
|
52 | this.bundles = options.bundles || Bijous.defaultBundles;
|
53 | this.modules = {};
|
54 | }
|
55 |
|
56 | /**
|
57 | * Retrieves all modules found for it's bundles or a supplied bundle name
|
58 | * @param {string=} bundle - The name of the bundle that should be used when retrieving modules
|
59 | * @returns {object[]} - An array of [klect]{@link https://github.com/awnist/klect} assets
|
60 | */
|
61 | Bijous.prototype.list = function list(bundle) {
|
62 | var klect = new Klect({ cwd: this.cwd });
|
63 | var assets = klect.gather(this.bundles);
|
64 |
|
65 | if (bundle) { return assets.bundles(bundle); }
|
66 | else { return assets; }
|
67 | };
|
68 |
|
69 | /**
|
70 | * @callback Bijous~loadCallback
|
71 | * @desc Used as a callback override for the {@linkcode Bijous#load} method. If one is specified then error handling
|
72 | * becomes it's responsibility. When one is not specified and an error occurs then the error will be thrown.
|
73 | * @param {object=} error - If an error occurs the callback will receive an error object
|
74 | * @param {*=} results - An array of any objects returned as representations of modules
|
75 | */
|
76 |
|
77 | /**
|
78 | * Requires all modules found for it's bundles or a supplied bundle name, and executes the async callback defined by the
|
79 | * module
|
80 | * @param {string=} bundle - The name of the bundle that should be used when loading modules
|
81 | * @param {Bijous~loadCallback=} callback - A callback method to use when all modules are loaded
|
82 | */
|
83 | Bijous.prototype.load = function load(bundle, callback) {
|
84 | if ('function' === typeof bundle) {
|
85 | callback = bundle;
|
86 | bundle = null;
|
87 | }
|
88 |
|
89 | var modules = this.require(bundle);
|
90 | var moduleKeys = Object.keys(modules);
|
91 | var self = this;
|
92 |
|
93 | var fns = moduleKeys.map(function (key) {
|
94 | return function loadAsset(done) {
|
95 | var cb = function (error, results) {
|
96 | if (results) { self.modules[key] = results; }
|
97 |
|
98 | self.emit('loaded', key, results);
|
99 | done(error, results);
|
100 | };
|
101 |
|
102 | modules[key].call(null, self, cb);
|
103 | };
|
104 | });
|
105 |
|
106 | async.series(fns, function (error, results) {
|
107 | if (callback) { callback(error, results); }
|
108 | else if (error) { throw error; }
|
109 |
|
110 | self.emit('done', self);
|
111 | });
|
112 | };
|
113 |
|
114 | /**
|
115 | * Loads all modules found for it's bundles or a supplied bundle name
|
116 | * @param {string=} bundle - The name of the bundle that should be used when requiring modules
|
117 | * @returns {object} - An object containing keys corresponding with the module's filename, not including the extension.
|
118 | * (e.g. modules/module1 would have a key module1 and modules/module2.js would have a key module2)
|
119 | */
|
120 | Bijous.prototype.require = function req(bundle) {
|
121 | var assets = this.list(bundle);
|
122 | var self = this;
|
123 | var modules = {};
|
124 |
|
125 | assets.files().map(function (file) {
|
126 | var extname = path.extname(file);
|
127 | var basename = path.basename(file, extname);
|
128 |
|
129 | modules[basename] = require(path.join(self.cwd, file));
|
130 | });
|
131 |
|
132 | return modules;
|
133 | };
|
134 |
|
135 | /**
|
136 | * The default bundles definition, confirms to [klect]{@link https://github.com/awnist/klect} bundles
|
137 | */
|
138 | Bijous.defaultBundles = 'modules/*';
|
139 |
|
140 | exports = module.exports = Bijous; |
\ | No newline at end of file |