Add support for ES6 style async boot scripts

This commit is contained in:
Jürg Lehni 2017-07-29 13:48:28 +02:00 committed by Miroslav Bajtoš
parent 39b885f9fb
commit 51326091b2
No known key found for this signature in database
GPG Key ID: 6F2304BA9361C7E3
7 changed files with 161 additions and 41 deletions

View File

@ -305,18 +305,25 @@ function runScripts(app, list, callback) {
async.eachSeries(functions, function(f, done) { async.eachSeries(functions, function(f, done) {
debug('Running script %s', f.path); debug('Running script %s', f.path);
if (f.func.length >= 2) { var cb = function(err) {
debug('Starting async function %s', f.path);
f.func(app, function(err) {
debug('Async function finished %s', f.path); debug('Async function finished %s', f.path);
done(err); done(err);
}); // Make sure done() isn't called twice, e.g. if a script returns a
} else { // thenable object and also calls the passed callback.
debug('Starting sync function %s', f.path); cb = null;
f.func(app); };
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); debug('Sync function finished %s', f.path);
done(); done();
} }
} catch (err) {
debug('Sync function failed %s', f.path, err);
done(err);
}
}, callback); }, callback);
} }

View File

@ -31,6 +31,7 @@
}, },
"devDependencies": { "devDependencies": {
"browserify": "^4.1.8", "browserify": "^4.1.8",
"bluebird": "^3.1.1",
"chai": "^1.10.0", "chai": "^1.10.0",
"coffee-script": "^1.8.0", "coffee-script": "^1.8.0",
"coffeeify": "^0.7.0", "coffeeify": "^0.7.0",

View File

@ -265,6 +265,8 @@ describe('executor', function() {
'barLoaded', 'barLoaded',
'barSyncLoaded', 'barSyncLoaded',
'fooLoaded', 'fooLoaded',
'promiseLoaded',
'thenableLoaded',
'barStarted', 'barStarted',
]); ]);
@ -275,9 +277,15 @@ describe('executor', function() {
'barLoaded', 'barLoaded',
'barSyncLoaded', 'barSyncLoaded',
'fooLoaded', 'fooLoaded',
'promiseLoaded',
'thenableLoaded',
'barStarted', 'barStarted',
'barFinished', 'barFinished',
'barSyncExecuted', 'barSyncExecuted',
'promiseStarted',
'promiseFinished',
'thenableStarted',
'thenableFinished',
'umdLoaded', 'umdLoaded',
]); ]);
done(); done();
@ -292,9 +300,15 @@ describe('executor', function() {
'barLoaded', 'barLoaded',
'barSyncLoaded', 'barSyncLoaded',
'fooLoaded', 'fooLoaded',
'promiseLoaded',
'thenableLoaded',
'barStarted', 'barStarted',
'barFinished', 'barFinished',
'barSyncExecuted', 'barSyncExecuted',
'promiseStarted',
'promiseFinished',
'thenableStarted',
'thenableFinished',
'umdLoaded', 'umdLoaded',
]); ]);
done(); done();
@ -305,7 +319,7 @@ describe('executor', function() {
function(done) { function(done) {
var options = { var options = {
app: app, app: app,
appRootDir: path.join(__dirname, './fixtures/simple-app'), appRootDir: SIMPLE_APP,
scriptExtensions: ['.customjs', '.customjs2'], scriptExtensions: ['.customjs', '.customjs2'],
}; };
boot.execute(app, boot.compile(options), function(err) { boot.execute(app, boot.compile(options), function(err) {
@ -317,6 +331,47 @@ describe('executor', function() {
done(); done();
}); });
}); });
});
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;
});
after(function() {
delete process.rejectPromise;
});
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();
});
});
});
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() { describe('for mixins', function() {
var options; var options;
@ -356,7 +411,6 @@ describe('executor', function() {
expect(Object.keys(registry)).to.eql(['Example', 'Timestamping']); expect(Object.keys(registry)).to.eql(['Example', 'Timestamping']);
}); });
}); });
});
describe('with PaaS and npm env variables', function() { describe('with PaaS and npm env variables', function() {
beforeEach(function cleanEnvironment() { beforeEach(function cleanEnvironment() {

View File

@ -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();
});
},
});
};

12
test/fixtures/simple-app/boot/reject.js vendored Normal file
View File

@ -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'));
}
};

View File

@ -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();
});
},
};
};

10
test/fixtures/simple-app/boot/throw.js vendored Normal file
View File

@ -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');
}
};