diff --git a/lib/phases/initializers.js b/lib/phases/initializers.js index 8c35e21..d04857f 100644 --- a/lib/phases/initializers.js +++ b/lib/phases/initializers.js @@ -28,33 +28,79 @@ module.exports = function(options) { if ('string' == typeof options) { options = { dirname: options }; } + + if (Array.isArray(options)) { + options = {dirname: options}; + } + options = options || {}; - var dirname = options.dirname || 'etc/init' + var dirnames = [] , extensions = options.extensions || Object.keys(require.extensions).map(function(ext) { return ext; }) , exts = extensions.map(function(ext) { if ('.' != ext[0]) { return ext; } return ext.slice(1); }) , regex = new RegExp('\\.(' + exts.join('|') + ')$'); - + + if (Array.isArray(options.dirname)) { + dirnames = options.dirname; + } + else{ + dirnames.push(options.dirname || '/etc/init/'); + } + return function initializers(done) { - var dir = path.resolve(dirname); - if (!existsSync(dir)) { return done(); } - - var self = this - , files = fs.readdirSync(dir).sort() - , idx = 0; + + var dirs = [], + files = [], + self = this, + idx = 0; + + dirs = dirnames.filter(function(dirname){ + var folder = path.resolve(dirname); + if (!existsSync(folder)) { + return false; + } + return true; + }).map(function(dirname){ + return path.resolve(dirname);; + }); + + //Sanity check + if (dirs.length !== dirnames.length) { + return done(new Error('One or more directory does not exist')); + } + + files = dirs.map(function(dir){ + return fs.readdirSync(dir).map(function(file){ + return {filename:file, filePath:path.join(dir, file)} + }); + }); + + //Flatten and sort array of array to one level array. + files = [].concat.apply([], files).sort(function(a, b){ + if (a.filename < b.filename) { + return -1; + } + if (a.filename > b.filename) { + return 1; + } + + return 0; + }); + function next(err) { if (err) { return done(err); } - + var file = files[idx++]; // all done if (!file) { return done(); } - - if (regex.test(file)) { + + if (regex.test(file.filename)) { try { - debug('initializer %s', file); - var mod = require(path.join(dir, file)); + + var mod = require(file.filePath); + if (typeof mod == 'function') { var arity = mod.length; if (arity == 1) { diff --git a/test/data/initializers/test-multiple-folders/04_log.js b/test/data/initializers/test-multiple-folders/04_log.js new file mode 100644 index 0000000..dcdda1e --- /dev/null +++ b/test/data/initializers/test-multiple-folders/04_log.js @@ -0,0 +1,3 @@ +module.exports = function() { + this.order.push('04_log'); +}; diff --git a/test/data/initializers/test-multiple-folders/README.md b/test/data/initializers/test-multiple-folders/README.md new file mode 100644 index 0000000..991efa9 --- /dev/null +++ b/test/data/initializers/test-multiple-folders/README.md @@ -0,0 +1 @@ +# Initializers diff --git a/test/phases/initializers.test.js b/test/phases/initializers.test.js index 6ad43f2..17b8eaa 100644 --- a/test/phases/initializers.test.js +++ b/test/phases/initializers.test.js @@ -3,20 +3,20 @@ var initializers = require('../../lib/phases/initializers'); describe('phases/initializers', function() { - + it('should export a setup function', function() { expect(initializers).to.be.a('function'); }); - + describe('phase with string argument', function() { var app = new Object(); app.order = []; - + var error; - + before(function(done) { global.__app = app; - + var phase = initializers(__dirname + '/../data/initializers/test'); phase.call(app, function(err) { error = err; @@ -24,7 +24,7 @@ describe('phases/initializers', function() { return done(); }); }); - + it('should call callback', function() { expect(error).to.be.undefined; }); @@ -35,13 +35,40 @@ describe('phases/initializers', function() { expect(app.order[2]).to.equal('03_require'); }); }); - + + describe('phase with Array argument', function() { + var app = new Object(); + app.order = []; + + var error; + + before(function(done) { + + var phase = initializers([__dirname + '/../data/initializers/test-multiple-folders', __dirname + '/../data/initializers/test']); + phase.call(app, function(err) { + error = err; + return done(); + }); + }); + + it('should call callback', function() { + expect(error).to.be.undefined; + }); + + it('should run initializers in correct order', function() { + expect(app.order).to.have.length(3); + expect(app.order[0]).to.equal('01_async'); + expect(app.order[1]).to.equal('02_sync'); + expect(app.order[2]).to.equal('04_log'); + }); + }); + describe('phase with dirname option', function() { var app = new Object(); app.order = []; - + var error; - + before(function(done) { var phase = initializers({ dirname: __dirname + '/../data/initializers/test' }); phase.call(app, function(err) { @@ -49,23 +76,71 @@ describe('phases/initializers', function() { return done(); }); }); - + it('should call callback', function() { expect(error).to.be.undefined; }); + it('should run initializers in correct order', function() { expect(app.order).to.have.length(2); expect(app.order[0]).to.equal('01_async'); expect(app.order[1]).to.equal('02_sync'); }); }); - + + describe('phase with multiple dirname options', function(){ + var app = new Object(); + app.order = []; + + var error; + + before(function(done) { + var phase = initializers({ dirname: [__dirname + '/../data/initializers/test', __dirname + '/../data/initializers/test-multiple-folders'] }); + phase.call(app, function(err) { + error = err; + return done(); + }); + }); + + it('should call callback', function() { + expect(error).to.be.undefined; + }); + + it('should run initializers in correct order', function() { + expect(app.order).to.have.length(3); + expect(app.order[0]).to.equal('01_async'); + expect(app.order[1]).to.equal('02_sync'); + expect(app.order[2]).to.equal('04_log'); + }); + + describe('error in path, should not be imported', function(){ + var app = new Object(); + app.order = []; + + var error; + + before(function(done) { + var phase = initializers({ dirname: [__dirname + '/../data/initializers/test', __dirname + '/../data/initializers/test-multiple-foldssers'] }); + phase.call(app, function(err) { + error = err; + return done(); + }); + }); + + it('should call callback', function() { + expect(error).to.be.an.instanceOf(Error); + expect(error.message).to.equal('One or more directory does not exist'); + }); + + }); + }); + describe('phase with initializer that calls done with error', function() { var app = new Object(); app.order = []; - + var error; - + before(function(done) { var phase = initializers(__dirname + '/../data/initializers/error-done'); phase.call(app, function(err) { @@ -73,7 +148,7 @@ describe('phases/initializers', function() { return done(); }); }); - + it('should call callback', function() { expect(error).to.be.an.instanceOf(Error); expect(error.message).to.equal('something went wrong'); @@ -82,13 +157,13 @@ describe('phases/initializers', function() { expect(app.order).to.have.length(0); }); }); - + describe('phase with initializer that throws exception', function() { var app = new Object(); app.order = []; - + var error; - + before(function(done) { var phase = initializers(__dirname + '/../data/initializers/error-throw'); phase.call(app, function(err) { @@ -96,7 +171,7 @@ describe('phases/initializers', function() { return done(); }); }); - + it('should call callback', function() { expect(error).to.be.an.instanceOf(Error); expect(error.message).to.equal('something went horribly wrong'); @@ -105,5 +180,5 @@ describe('phases/initializers', function() { expect(app.order).to.have.length(0); }); }); - + });