106 lines
3.1 KiB
JavaScript
106 lines
3.1 KiB
JavaScript
// Copyright IBM Corp. 2016,2019. All Rights Reserved.
|
|
// Node module: loopback-boot
|
|
// This file is licensed under the MIT License.
|
|
// License text available at https://opensource.org/licenses/MIT
|
|
|
|
'use strict';
|
|
|
|
const util = require('util');
|
|
const utils = require('../utils');
|
|
const path = require('path');
|
|
const async = require('async');
|
|
const debug = require('debug')('loopback:boot:script');
|
|
const PluginBase = require('../plugin-base');
|
|
const _ = require('lodash');
|
|
const g = require('../globalize');
|
|
|
|
module.exports = function(options) {
|
|
return new Script(options);
|
|
};
|
|
|
|
function Script(options) {
|
|
PluginBase.call(this, options, 'bootScripts', null);
|
|
}
|
|
|
|
util.inherits(Script, PluginBase);
|
|
|
|
Script.prototype.load = function(context) {
|
|
const options = this.options;
|
|
const appRootDir = options.rootDir;
|
|
// require directories
|
|
let bootDirs = options.bootDirs || []; // precedence
|
|
bootDirs = bootDirs.concat(path.join(appRootDir, 'boot'));
|
|
utils.resolveRelativePaths(bootDirs, appRootDir);
|
|
|
|
let bootScripts = options.bootScripts || [];
|
|
utils.resolveRelativePaths(bootScripts, appRootDir);
|
|
|
|
bootDirs.forEach(function(dir) {
|
|
bootScripts = bootScripts.concat(
|
|
utils.findScripts(dir, options.scriptExtensions),
|
|
);
|
|
const envdir = dir + '/' + options.env;
|
|
bootScripts = bootScripts.concat(
|
|
utils.findScripts(envdir, options.scriptExtensions),
|
|
);
|
|
});
|
|
|
|
// de-dedup boot scripts -ERS
|
|
// https://github.com/strongloop/loopback-boot/issues/64
|
|
bootScripts = _.uniq(bootScripts);
|
|
debug('Boot scripts: %j', bootScripts);
|
|
this.configure(context, bootScripts);
|
|
return bootScripts;
|
|
};
|
|
|
|
Script.prototype.start = function(context, done) {
|
|
const app = context.app;
|
|
const instructions = context.instructions[this.name];
|
|
runScripts(app, instructions, done);
|
|
};
|
|
|
|
function runScripts(app, list, callback) {
|
|
list = list || [];
|
|
const functions = [];
|
|
list.forEach(function(filepath) {
|
|
debug('Requiring script %s', filepath);
|
|
try {
|
|
let exports = require(filepath);
|
|
if (exports.__esModule) exports = exports.default;
|
|
if (typeof exports === 'function') {
|
|
debug('Exported function detected %s', filepath);
|
|
functions.push({
|
|
path: filepath,
|
|
func: exports,
|
|
});
|
|
}
|
|
} catch (err) {
|
|
g.error('Failed loading boot script: %s\n%s', filepath, err.stack);
|
|
throw err;
|
|
}
|
|
});
|
|
|
|
async.eachSeries(functions, function(f, done) {
|
|
debug('Running script %s', f.path);
|
|
let cb = function(err) {
|
|
debug('Async function %s %s', err ? 'failed' : 'finished', 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 = function() {};
|
|
};
|
|
try {
|
|
const 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);
|
|
}
|