UNPKG

ninjs-lodash

Version:
196 lines (152 loc) 6.66 kB
/** * Child Process Utils */ 'use strict' const _ = require('lodash') const child_process = require("child_process") const libs = require('./libs') const core = require('./core') const config = require('./config') const debug = require('./debug') const CMD_DEFAULTS = _.$('cmd.defaults') const SWITCH_DELIMITER = _.$('cli.switch.delimiter') const SWITCH_DELIMITER_VALS = _.$('cli.switch.delimiters') exports = module.exports = { cwd: _cwd, swargs: swargs, oargs: oargs, cmdstr: cmdstr, exec: exec, execFile: execFile } _.mixin(exports) // ~~~~~ CHILD PROCESS V2 ~~~~~~ // returns cwd with first cli args/settings/options/process.cwd function _cwd(options) { return _.get(options, 'cwd') || _.get(options, 'prefix') || process.cwd() } // returns Array -> cli switch args from object k:v pairs function swargs(obj) { // let mobj = _.merge(_.isPlainObject(obj) ? obj : {}, _.$('jav.sw') || {}) let mobj = _.merge(_.isPlainObject(obj) ? obj : {}, {}) return _.compact(_.map(mobj, (v, k) => { // _.log(`-->${v}<--`) v = _.isArray(v) ? _.join(_.compact(v), ',') : v const vCool = !_.isEmpty(v) || _.isBoolean(v) || _.isNumber(v) return k && vCool ? `--${k}=${v}` : k || vCool ? `--${k || v}` : '' })) || [] } // returns args + cli args function oargs(options) { return _.concat(_.get(options, 'args') || [], swargs(_.get(options, 'sw'))) } // returns String -> cmd + join(args, ' ') function cmdstr(cmd, args) { cmd = cmd && _.isString(cmd) ? cmd : '' args = args && _.isArray(args) ? _.compact(args) : [] if(cmd) args.unshift(cmd) return _.join(args, ' ') } // child_process.exec(command[, options][, callback]) function exec(options, callback) { let cmd = _.get(options, 'cmd') if(!cmd || !_.isString(cmd)) return _.fail('Invalid cmd', callback) let cwd = _cwd(options) let args = oargs(options) let outData = '' let errData = '' cmd = cmdstr(cmd, args) // console.log(`\nExec : ${cmd} ${_.join(args, ' ')} \nCWD : ${cwd}\n`) let child = child_process.exec(cmd, { cwd: cwd }, function() { return _.done({ err: _.trim(errData), result: _.trim(outData) }, callback) }) child.stdout.on('data', function(data) { outData += (_.isBuffer(data) ? data.toString('utf8') : data) }) child.stderr.on('data', function(data) { errData += (_.isBuffer(data) ? data.toString('utf8') : data) }) return child } // child_process.execFile(file[, args][, options][, callback]) function execFile(options, callback) { let cmd = _.get(options, 'cmd') if(!cmd || !_.isString(cmd)) return _.fail('Invalid cmd', callback) let cwd = _cwd(options) let args = oargs(options) let outData = '' let errData = '' let child = child_process.execFile(cmd, args, { cwd: cwd }, function() { return _.done({ err: _.trim(errData), result: _.trim(outData) }, callback) }) child.stdout.on('data', function(data) { outData += (_.isBuffer(data) ? data.toString('utf8') : data) }) child.stderr.on('data', function(data) { errData += (_.isBuffer(data) ? data.toString('utf8') : data) }) return child } // ~~~~~ CHILD PROCESS V1 ~~~~~~ // // child_process.exec(command[, options][, callback]) // function exec(options, callback) { // return cmd(_.assign(options, { type:'exec' } ), _.cb(callback)) // } // // child_process.execFile(file[, args][, options][, callback]) // function execFile(options, callback) { // return cmd(_.assign(options, { type:'execFile' } ), _.cb(callback)) // } // runs exec or exexfile // 'modules.writePaths': { cmd: 'node', args: ['test', 'modules.writePaths'], switches: { dest: _.path.join(TEMP_PATH, 'paths.json') } }, // function cmd(options, callback) { // let opts = _.merge({}, CMD_DEFAULTS, options) // let { cmd='', type='', heads, args=[], lasts, switches={}, switch_del='--' } = opts // let switchDelValid = switch_del && _.isString(switch_del) && _.includes(SWITCH_DELIMITER_VALS, switch_del) ? true : false // let jav = _.jav() // switch_del = switchDelValid ? switch_del : SWITCH_DELIMITER // type = type && _.isString(type) && _.includes(['exec', 'execFile'], type) ? type : 'exec' // // all args -> easier defaults // // cwd> cmd [heads ...] [args...] [lasts....] [--switchk=switchv ...] // heads = heads && _.isArray(heads) ? heads : [] // args = args && _.isArray(args) ? args : [] // lasts = args && _.isArray(lasts) ? lasts : [] // switches = switches && _.isPlainObject(switches) ? _.merge(switches, _.get(jav, 'sw')) || {} : {} // let method = _.get(cproc, type) // // if(!cmd || !_.isString(cmd)) return _.fail('Invalid cmd', callback) // if(!_.isFunction(method)) return _.fail('Invalid type', callback) // args = _.concat(heads, args, lasts) // _.forIn(switches, (v, k) => { // if(!v && !k) return // let arg = v && k ? `--${k}=${v}` : `--${k || v}` // if(arg) args.push(arg) // }) // args = _.compact(args) // let isExec = type === 'exec' // _.assign(opts, { args: args }) // opts = _.omit(opts, ['type', 'heads', 'lasts', 'switches', '']) // // exec does not take args argument like execFile // // -> must join args with ' ' and append to cmd prop to create command // if(isExec) cmd = _.join(_.compact([cmd, _.join(args, ' ')]), ' ') // let cb = (err, stdout, stderr) => { // if(err) return _.fail(err, callback) // _.done({ stdout: stdout, stderr: stderr }, callback) // } // const child = isExec ? _.attempt(method, cmd, opts, cb) : _.attempt(method, cmd, args, opts, cb) // return child // //return _handleChild(child, _.cb(callback)) // } // handles newly created child process via cproc.exec OR cprop.execFile // ** child.on('close', (code) => {}) is basically the only event that is called // ** use stdout/stderr to handle fail/done on 'close' event !!! // function _handleChild(child, callback) { // if(!child) return _.fail('Invalid child process', callback) // if(_.isError(child)) return _.fail(child, callback) // let stdout = '' // let stderr = '' // child.stdout.on('data', function(data) { stdout += data }) // child.stderr.on('data', function(data) { stderr += data }) // child.on('close', function(code) { return _.done(stdout || stderr, callback) }) // child.on('disconnect', function(err) {}) // child.on('error', function(err) { }) // child.on('exit', function(code, signal) { }) // child.on('message', function(message, sendHandle) { }) // return child // }