|
|
|
'use strict';
|
|
|
|
|
|
|
|
const os = require('os');
|
|
|
|
const async = require('async');
|
|
|
|
const winston = require('winston');
|
|
|
|
const nconf = require('nconf');
|
|
|
|
const _ = require('lodash');
|
|
|
|
|
|
|
|
const cacheBuster = require('./cacheBuster');
|
|
|
|
let meta;
|
|
|
|
|
|
|
|
function step(target, callback) {
|
|
|
|
var startTime = Date.now();
|
|
|
|
winston.info('[build] ' + target + ' build started');
|
|
|
|
|
|
|
|
return function (err) {
|
|
|
|
if (err) {
|
|
|
|
winston.error('[build] ' + target + ' build failed');
|
|
|
|
return callback(err);
|
|
|
|
}
|
|
|
|
|
|
|
|
var time = (Date.now() - startTime) / 1000;
|
|
|
|
|
|
|
|
winston.info('[build] ' + target + ' build completed in ' + time + 'sec');
|
|
|
|
callback();
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
var targetHandlers = {
|
|
|
|
'plugin static dirs': function (parallel, callback) {
|
|
|
|
meta.js.linkStatics(callback);
|
|
|
|
},
|
|
|
|
'requirejs modules': function (parallel, callback) {
|
|
|
|
meta.js.buildModules(parallel, callback);
|
|
|
|
},
|
|
|
|
'client js bundle': function (parallel, callback) {
|
|
|
|
meta.js.buildBundle('client', parallel, callback);
|
|
|
|
},
|
|
|
|
'admin js bundle': function (parallel, callback) {
|
|
|
|
meta.js.buildBundle('admin', parallel, callback);
|
|
|
|
},
|
|
|
|
javascript: [
|
|
|
|
'plugin static dirs',
|
|
|
|
'requirejs modules',
|
|
|
|
'client js bundle',
|
|
|
|
'admin js bundle',
|
|
|
|
],
|
|
|
|
'client side styles': function (parallel, callback) {
|
|
|
|
meta.css.buildBundle('client', parallel, callback);
|
|
|
|
},
|
|
|
|
'admin control panel styles': function (parallel, callback) {
|
|
|
|
meta.css.buildBundle('admin', parallel, callback);
|
|
|
|
},
|
|
|
|
styles: [
|
|
|
|
'client side styles',
|
|
|
|
'admin control panel styles',
|
|
|
|
],
|
|
|
|
templates: function (parallel, callback) {
|
|
|
|
meta.templates.compile(callback);
|
|
|
|
},
|
|
|
|
languages: function (parallel, callback) {
|
|
|
|
meta.languages.build(callback);
|
|
|
|
},
|
|
|
|
sounds: function (parallel, callback) {
|
|
|
|
meta.sounds.build(callback);
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
var aliases = {
|
|
|
|
'plugin static dirs': ['staticdirs'],
|
|
|
|
'requirejs modules': ['rjs', 'modules'],
|
|
|
|
'client js bundle': ['clientjs', 'clientscript', 'clientscripts'],
|
|
|
|
'admin js bundle': ['adminjs', 'adminscript', 'adminscripts'],
|
|
|
|
javascript: ['js'],
|
|
|
|
'client side styles': [
|
|
|
|
'clientcss', 'clientless', 'clientstyles', 'clientstyle',
|
|
|
|
],
|
|
|
|
'admin control panel styles': [
|
|
|
|
'admincss', 'adminless', 'adminstyles', 'adminstyle', 'acpcss', 'acpless', 'acpstyles', 'acpstyle',
|
|
|
|
],
|
|
|
|
styles: ['css', 'less', 'style'],
|
|
|
|
templates: ['tpl'],
|
|
|
|
languages: ['lang', 'i18n'],
|
|
|
|
sounds: ['sound'],
|
|
|
|
};
|
|
|
|
|
CLI refactor with commander (#6058)
* CLI refactor with commander
- Modularized the functionality
- All functionality done directly from `./nodebb` now
(still available from `app` for backwards compatibility)
- Moved all CLI code from `./nodebb` to `src/cli`
- Fixed `nodebb.bat` to work from any location, like `./nodebb`, and
also hides command output
- Overwrite some commander methods to add CLI color support
- Added `./nodebb info` for quick info including git hash, NodeBB
version, node version, and some database info
- Refactored `./nodebb reset` to allow multiple resets at once
- Changed `./nodebb restart` to essentially stop and start, as Windows
doesn't support signals
- Added `-l, --log` option which works on `./nodebb start` and `./nodebb
restart` to show logging, like `./nodebb slog`
- Expanded `-d, --dev` option which works on them as well, like
`./nodebb dev`
- Improvements to self-help. `./nodebb build -h` will output all
possible targets
- `./nodebb reset` explains usage better
* Fix some style inconsistencies
* Fix prestart being required before modules installed
* Fix travis failures
* Fix `help` command to output help for subcommands
* Pick steps of the upgrade process to run
* Fix formatting for upgrade help
* Fix web installer
7 years ago
|
|
|
exports.aliases = aliases;
|
|
|
|
|
|
|
|
aliases = Object.keys(aliases).reduce(function (prev, key) {
|
|
|
|
var arr = aliases[key];
|
|
|
|
arr.forEach(function (alias) {
|
|
|
|
prev[alias] = key;
|
|
|
|
});
|
|
|
|
prev[key] = key;
|
|
|
|
return prev;
|
|
|
|
}, {});
|
|
|
|
|
|
|
|
function beforeBuild(targets, callback) {
|
|
|
|
var db = require('../database');
|
|
|
|
require('colors');
|
|
|
|
process.stdout.write(' started'.green + '\n'.reset);
|
|
|
|
|
|
|
|
async.series([
|
|
|
|
function (next) {
|
|
|
|
db.init(next);
|
|
|
|
},
|
|
|
|
function (next) {
|
|
|
|
meta = require('../meta');
|
|
|
|
meta.themes.setupPaths(next);
|
|
|
|
},
|
|
|
|
function (next) {
|
|
|
|
var plugins = require('../plugins');
|
|
|
|
plugins.prepareForBuild(targets, next);
|
|
|
|
},
|
|
|
|
], function (err) {
|
|
|
|
if (err) {
|
|
|
|
winston.error('[build] Encountered error preparing for build', err);
|
|
|
|
return callback(err);
|
|
|
|
}
|
|
|
|
|
|
|
|
callback();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
var allTargets = Object.keys(targetHandlers).filter(function (name) {
|
|
|
|
return typeof targetHandlers[name] === 'function';
|
|
|
|
});
|
|
|
|
function buildTargets(targets, parallel, callback) {
|
|
|
|
var all = parallel ? async.each : async.eachSeries;
|
|
|
|
|
|
|
|
var length = Math.max.apply(Math, targets.map(function (name) {
|
|
|
|
return name.length;
|
|
|
|
}));
|
|
|
|
|
|
|
|
all(targets, function (target, next) {
|
|
|
|
targetHandlers[target](parallel, step(_.padStart(target, length) + ' ', next));
|
|
|
|
}, callback);
|
|
|
|
}
|
|
|
|
|
|
|
|
exports.build = function (targets, options, callback) {
|
|
|
|
if (!callback && typeof options === 'function') {
|
|
|
|
callback = options;
|
|
|
|
options = {};
|
|
|
|
} else if (!options) {
|
|
|
|
options = {};
|
|
|
|
}
|
|
|
|
|
|
|
|
if (targets === true) {
|
|
|
|
targets = allTargets;
|
|
|
|
} else if (!Array.isArray(targets)) {
|
|
|
|
targets = targets.split(',');
|
|
|
|
}
|
|
|
|
|
|
|
|
let series = nconf.get('series') || options.series;
|
|
|
|
if (series === undefined) {
|
|
|
|
// Detect # of CPUs and select strategy as appropriate
|
|
|
|
winston.verbose('[build] Querying CPU core count for build strategy');
|
|
|
|
const cpus = os.cpus();
|
|
|
|
series = cpus.length < 4;
|
|
|
|
winston.verbose('[build] System returned ' + cpus.length + ' cores, opting for ' + (series ? 'series' : 'parallel') + ' build strategy');
|
|
|
|
}
|
|
|
|
|
|
|
|
targets = targets
|
|
|
|
// get full target name
|
|
|
|
.map(function (target) {
|
|
|
|
target = target.toLowerCase().replace(/-/g, '');
|
|
|
|
if (!aliases[target]) {
|
|
|
|
winston.warn('[build] Unknown target: ' + target);
|
|
|
|
if (target.includes(',')) {
|
|
|
|
winston.warn('[build] Are you specifying multiple targets? Separate them with spaces:');
|
|
|
|
winston.warn('[build] e.g. `./nodebb build adminjs tpl`');
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return aliases[target];
|
|
|
|
})
|
|
|
|
// filter nonexistent targets
|
|
|
|
.filter(Boolean);
|
|
|
|
|
|
|
|
// map multitargets to their sets
|
|
|
|
targets = _.uniq(_.flatMap(targets, target => (
|
|
|
|
Array.isArray(targetHandlers[target]) ?
|
|
|
|
targetHandlers[target] :
|
|
|
|
target
|
|
|
|
)));
|
|
|
|
|
|
|
|
winston.verbose('[build] building the following targets: ' + targets.join(', '));
|
|
|
|
|
|
|
|
if (!targets) {
|
|
|
|
winston.info('[build] No valid targets supplied. Aborting.');
|
|
|
|
callback();
|
|
|
|
}
|
|
|
|
|
|
|
|
var startTime;
|
|
|
|
var totalTime;
|
|
|
|
async.series([
|
|
|
|
async.apply(beforeBuild, targets),
|
|
|
|
function (next) {
|
|
|
|
var threads = parseInt(nconf.get('threads'), 10);
|
|
|
|
if (threads) {
|
|
|
|
require('./minifier').maxThreads = threads - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!series) {
|
|
|
|
winston.info('[build] Building in parallel mode');
|
|
|
|
} else {
|
|
|
|
winston.info('[build] Building in series mode');
|
|
|
|
}
|
|
|
|
|
|
|
|
startTime = Date.now();
|
|
|
|
buildTargets(targets, !series, next);
|
|
|
|
},
|
|
|
|
function (next) {
|
|
|
|
totalTime = (Date.now() - startTime) / 1000;
|
|
|
|
cacheBuster.write(next);
|
|
|
|
},
|
|
|
|
], function (err) {
|
|
|
|
if (err) {
|
|
|
|
winston.error('[build] Encountered error during build step', err);
|
|
|
|
return callback(err);
|
|
|
|
}
|
|
|
|
|
|
|
|
winston.info('[build] Asset compilation successful. Completed in ' + totalTime + 'sec.');
|
|
|
|
callback();
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.buildAll = function (callback) {
|
|
|
|
exports.build(allTargets, callback);
|
|
|
|
};
|
|
|
|
|
|
|
|
require('../promisify')(exports);
|