Add support for ES6 style async boot scripts
This commit is contained in:
parent
39b885f9fb
commit
51326091b2
|
@ -305,17 +305,24 @@ function runScripts(app, list, callback) {
|
|||
|
||||
async.eachSeries(functions, function(f, done) {
|
||||
debug('Running script %s', f.path);
|
||||
if (f.func.length >= 2) {
|
||||
debug('Starting async function %s', f.path);
|
||||
f.func(app, function(err) {
|
||||
debug('Async function finished %s', f.path);
|
||||
done(err);
|
||||
});
|
||||
} else {
|
||||
debug('Starting sync function %s', f.path);
|
||||
f.func(app);
|
||||
debug('Sync function finished %s', f.path);
|
||||
done();
|
||||
var cb = function(err) {
|
||||
debug('Async function finished %s', f.path);
|
||||
done(err);
|
||||
// Make sure done() isn't called twice, e.g. if a script returns a
|
||||
// thenable object and also calls the passed callback.
|
||||
cb = null;
|
||||
};
|
||||
try {
|
||||
var result = f.func(app, cb);
|
||||
if (result && typeof result.then === 'function') {
|
||||
result.then(function() { cb(); }, cb);
|
||||
} else if (f.func.length < 2) {
|
||||
debug('Sync function finished %s', f.path);
|
||||
done();
|
||||
}
|
||||
} catch (err) {
|
||||
debug('Sync function failed %s', f.path, err);
|
||||
done(err);
|
||||
}
|
||||
}, callback);
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"browserify": "^4.1.8",
|
||||
"bluebird": "^3.1.1",
|
||||
"chai": "^1.10.0",
|
||||
"coffee-script": "^1.8.0",
|
||||
"coffeeify": "^0.7.0",
|
||||
|
|
|
@ -265,6 +265,8 @@ describe('executor', function() {
|
|||
'barLoaded',
|
||||
'barSyncLoaded',
|
||||
'fooLoaded',
|
||||
'promiseLoaded',
|
||||
'thenableLoaded',
|
||||
'barStarted',
|
||||
]);
|
||||
|
||||
|
@ -275,9 +277,15 @@ describe('executor', function() {
|
|||
'barLoaded',
|
||||
'barSyncLoaded',
|
||||
'fooLoaded',
|
||||
'promiseLoaded',
|
||||
'thenableLoaded',
|
||||
'barStarted',
|
||||
'barFinished',
|
||||
'barSyncExecuted',
|
||||
'promiseStarted',
|
||||
'promiseFinished',
|
||||
'thenableStarted',
|
||||
'thenableFinished',
|
||||
'umdLoaded',
|
||||
]);
|
||||
done();
|
||||
|
@ -292,9 +300,15 @@ describe('executor', function() {
|
|||
'barLoaded',
|
||||
'barSyncLoaded',
|
||||
'fooLoaded',
|
||||
'promiseLoaded',
|
||||
'thenableLoaded',
|
||||
'barStarted',
|
||||
'barFinished',
|
||||
'barSyncExecuted',
|
||||
'promiseStarted',
|
||||
'promiseFinished',
|
||||
'thenableStarted',
|
||||
'thenableFinished',
|
||||
'umdLoaded',
|
||||
]);
|
||||
done();
|
||||
|
@ -305,7 +319,7 @@ describe('executor', function() {
|
|||
function(done) {
|
||||
var options = {
|
||||
app: app,
|
||||
appRootDir: path.join(__dirname, './fixtures/simple-app'),
|
||||
appRootDir: SIMPLE_APP,
|
||||
scriptExtensions: ['.customjs', '.customjs2'],
|
||||
};
|
||||
boot.execute(app, boot.compile(options), function(err) {
|
||||
|
@ -317,44 +331,84 @@ describe('executor', function() {
|
|||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('for mixins', function() {
|
||||
var options;
|
||||
beforeEach(function() {
|
||||
appdir.writeFileSync('custom-mixins/example.js',
|
||||
'module.exports = ' +
|
||||
'function(Model, options) {}');
|
||||
describe('with boot script returning a rejected promise', function() {
|
||||
before(function() {
|
||||
// Tell simple-app/boot/reject.js to return a rejected promise
|
||||
process.rejectPromise = true;
|
||||
});
|
||||
|
||||
appdir.writeFileSync('custom-mixins/time-stamps.js',
|
||||
'module.exports = ' +
|
||||
'function(Model, options) {}');
|
||||
after(function() {
|
||||
delete process.rejectPromise;
|
||||
});
|
||||
|
||||
appdir.writeConfigFileSync('custom-mixins/time-stamps.json', {
|
||||
name: 'Timestamping',
|
||||
});
|
||||
it('receives rejected promise as callback error',
|
||||
function(done) {
|
||||
boot.execute(app, simpleAppInstructions(), function(err) {
|
||||
expect(err).to.exist.and.be.an.instanceOf(Error)
|
||||
.with.property('message', 'reject');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
options = {
|
||||
appRootDir: appdir.PATH,
|
||||
};
|
||||
describe('with boot script throwing an error', function() {
|
||||
before(function() {
|
||||
// Tell simple-app/boot/throw.js to throw an error
|
||||
process.throwError = true;
|
||||
});
|
||||
|
||||
after(function() {
|
||||
delete process.throwError;
|
||||
});
|
||||
|
||||
it('receives thrown error as callback errors',
|
||||
function(done) {
|
||||
boot.execute(app, simpleAppInstructions(), function(err) {
|
||||
expect(err).to.exist.and.be.an.instanceOf(Error)
|
||||
.with.property('message', 'throw');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('for mixins', function() {
|
||||
var options;
|
||||
beforeEach(function() {
|
||||
appdir.writeFileSync('custom-mixins/example.js',
|
||||
'module.exports = ' +
|
||||
'function(Model, options) {}');
|
||||
|
||||
appdir.writeFileSync('custom-mixins/time-stamps.js',
|
||||
'module.exports = ' +
|
||||
'function(Model, options) {}');
|
||||
|
||||
appdir.writeConfigFileSync('custom-mixins/time-stamps.json', {
|
||||
name: 'Timestamping',
|
||||
});
|
||||
|
||||
it('defines mixins from instructions - using `mixinDirs`', function() {
|
||||
options.mixinDirs = ['./custom-mixins'];
|
||||
boot(app, options);
|
||||
options = {
|
||||
appRootDir: appdir.PATH,
|
||||
};
|
||||
});
|
||||
|
||||
var modelBuilder = app.registry.modelBuilder;
|
||||
var registry = modelBuilder.mixins.mixins;
|
||||
expect(Object.keys(registry)).to.eql(['Example', 'Timestamping']);
|
||||
});
|
||||
it('defines mixins from instructions - using `mixinDirs`', function() {
|
||||
options.mixinDirs = ['./custom-mixins'];
|
||||
boot(app, options);
|
||||
|
||||
it('defines mixins from instructions - using `mixinSources`', function() {
|
||||
options.mixinSources = ['./custom-mixins'];
|
||||
boot(app, options);
|
||||
var modelBuilder = app.registry.modelBuilder;
|
||||
var registry = modelBuilder.mixins.mixins;
|
||||
expect(Object.keys(registry)).to.eql(['Example', 'Timestamping']);
|
||||
});
|
||||
|
||||
var modelBuilder = app.registry.modelBuilder;
|
||||
var registry = modelBuilder.mixins.mixins;
|
||||
expect(Object.keys(registry)).to.eql(['Example', 'Timestamping']);
|
||||
});
|
||||
it('defines mixins from instructions - using `mixinSources`', function() {
|
||||
options.mixinSources = ['./custom-mixins'];
|
||||
boot(app, options);
|
||||
|
||||
var modelBuilder = app.registry.modelBuilder;
|
||||
var registry = modelBuilder.mixins.mixins;
|
||||
expect(Object.keys(registry)).to.eql(['Example', 'Timestamping']);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
// Copyright IBM Corp. 2017. All Rights Reserved.
|
||||
// Node module: loopback-boot
|
||||
// This file is licensed under the MIT License.
|
||||
// License text available at https://opensource.org/licenses/MIT
|
||||
|
||||
var Promise = require('bluebird');
|
||||
|
||||
process.bootFlags.push('promiseLoaded');
|
||||
module.exports = function(app) {
|
||||
process.bootFlags.push('promiseStarted');
|
||||
return Promise.resolve({
|
||||
then: function(onFulfill, onReject) {
|
||||
process.nextTick(function() {
|
||||
process.bootFlags.push('promiseFinished');
|
||||
onFulfill();
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
|
@ -0,0 +1,12 @@
|
|||
// Copyright IBM Corp. 2017. All Rights Reserved.
|
||||
// Node module: loopback-boot
|
||||
// This file is licensed under the MIT License.
|
||||
// License text available at https://opensource.org/licenses/MIT
|
||||
|
||||
var Promise = require('bluebird');
|
||||
|
||||
module.exports = function(app) {
|
||||
if (process.rejectPromise) {
|
||||
return Promise.reject(new Error('reject'));
|
||||
}
|
||||
};
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright IBM Corp. 2017. All Rights Reserved.
|
||||
// Node module: loopback-boot
|
||||
// This file is licensed under the MIT License.
|
||||
// License text available at https://opensource.org/licenses/MIT
|
||||
|
||||
process.bootFlags.push('thenableLoaded');
|
||||
module.exports = function(app) {
|
||||
process.bootFlags.push('thenableStarted');
|
||||
return {
|
||||
then: function(onFulfill, onReject) {
|
||||
process.nextTick(function() {
|
||||
process.bootFlags.push('thenableFinished');
|
||||
onFulfill();
|
||||
});
|
||||
},
|
||||
};
|
||||
};
|
|
@ -0,0 +1,10 @@
|
|||
// Copyright IBM Corp. 2017. All Rights Reserved.
|
||||
// Node module: loopback-boot
|
||||
// This file is licensed under the MIT License.
|
||||
// License text available at https://opensource.org/licenses/MIT
|
||||
|
||||
module.exports = function(app) {
|
||||
if (process.throwError) {
|
||||
throw new Error('throw');
|
||||
}
|
||||
};
|
Loading…
Reference in New Issue