Plato on Github
Report Home
lib/bob.js
Maintainability
74.53
Lines of code
141
Difficulty
35.35
Estimated Errors
1.00
Function weight
By Complexity
By SLOC
"use strict"; import async from 'async'; import config from './config.js'; import jazz from 'jazz'; import p from 'path'; import runner from './runner.js'; import task from './task.js'; import util from 'util'; class Bob { /** * Constructor for initialising Bob. * * @param {Object} opts: optional * - appDir: directory where the userland application calls Bob from * - bobDir: directory where Bob's installation is located * - appName: name of the userland application (retrieved from its package.json) * - appVersion: version value of the userland application (retrieved from its package.json) * - bobMode: either `human` or `robot`, when you are a robot - you have to declare yourself :-] * - quiet: when true, only display task name and command, but without the command output */ constructor(opts) { this.opts = opts; } /** * Bob is goin' to work! * Execute specified tasks * * @param {Array} taskNames: an array of task names * @param {Function} cb: standard cb(err, result) callback */ build(taskNames, cb) { const EXEC_OPTS = { cwd: this.opts.appDir, quiet: this.opts.quiet, maxBuffer: this.opts.maxBufferInKb * 1024 }; const self = this; this._init(taskNames, (err, settings) => { if (err) { cb(err); } else { self._commands(taskNames, settings, (err, commands) => { if (err) { cb(err); } else { runner.execSeries(commands, EXEC_OPTS, cb); } }); } }); } /** * Load Bob task files and application config file, and install optional dependencies, all in parallel. * * @param {Array} taskNames: an array of task names * @param {Function} cb: standard cb(err, result) callback */ _init(taskNames, cb) { const self = this; function loadTask(cb) { task.load(taskNames, p.join(self.opts.bobDir, 'conf', 'tasks'), cb); } function loadConfig(cb) { config.load(taskNames, self.opts.appDir, cb); } async.parallel({ bobTasks: loadTask, appConfig: loadConfig }, cb); } /** * Prepare commands to execute. * * @param {Array} taskNames: an array of task names * @param {Object} settings: tasks and application configs * @param {Function} cb: standard cb(err, result) callback */ _commands(taskNames, settings, cb) { const TPL_PARAMS = { app: this.opts.appDir, bob: this.opts.bobDir, name: this.opts.appName, tmp: this.opts.tmpDir, version: this.opts.appVersion }; const bobTasks = settings.bobTasks, bobMode = this.opts.bobMode, self = this; const commands = []; taskNames.forEach((taskName) => { self._taskTypeNames(taskName, settings).forEach((taskTypeName) => { const taskType = bobTasks[taskName].types[taskTypeName]; Object.keys(taskType).forEach((key) => { if (typeof taskType[key] === 'object') { taskType[key] = taskType[key][bobMode]; } }); taskType.preOpts = taskType.preOpts || taskType.opts; // strip undefined and null from command elements const elems = [taskType.bin, taskType.preOpts, taskType.args, taskType.postOpts].filter(elem => elem); commands.push({ format: util.format(elems.join(' ')), meta: { task: taskName, type: taskTypeName } }); }); }); const jobs = []; commands.forEach((command) => { jobs.push((cb) => { jazz.compile(command.format).process(TPL_PARAMS, (result) => { command.exec = result; delete command.format; cb(null, command); }); }); }); async.parallel(jobs, cb); } _taskTypeNames(taskName, settings) { // NOTE: allow multiple types in application config let taskTypeNames = (settings.appConfig[taskName] && settings.appConfig[taskName].type) ? settings.appConfig[taskName].type : settings.bobTasks[taskName].default; if (!Array.isArray(taskTypeNames)) { taskTypeNames = [taskTypeNames]; } return taskTypeNames; } } export { Bob as default };