UNPKG

pot-js

Version:

Process management module

328 lines (246 loc) 8.64 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _child_process = require('child_process'); var _path = require('path'); var _fsExtra = require('fs-extra'); var _isWin = require('./utils/isWin'); var _isWin2 = _interopRequireDefault(_isWin); var _PrepareCli = require('./utils/PrepareCli'); var _workspace = require('./utils/workspace'); var _workspace2 = _interopRequireDefault(_workspace); var _config = require('./Schemas/config'); var _config2 = _interopRequireDefault(_config); var _potLogger = require('pot-logger'); var _lodash = require('lodash'); var _chalk = require('chalk'); var _chalk2 = _interopRequireDefault(_chalk); var _Connection = require('./Connection'); var _Connection2 = _interopRequireDefault(_Connection); var _signalExit = require('signal-exit'); var _signalExit2 = _interopRequireDefault(_signalExit); var _fkill = require('fkill'); var _fkill2 = _interopRequireDefault(_fkill); var _package = require('../package.json'); var _aggregateError = require('aggregate-error'); var _aggregateError2 = _interopRequireDefault(_aggregateError); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } const potjs = { version: _package.version }; const ensureName = options => { if (options.name) { if ((0, _lodash.isNumber)(options.name)) { options.name += ''; } return options; } const cwd = options.cwd; try { var _require = require((0, _path.resolve)(cwd, 'package.json')); const name = _require.name; if (!name) { throw new Error(); } options.name = name; } catch (err) { const sepRegExp = new RegExp(_isWin2.default ? '\\\\' : '/', 'g'); options.name = cwd.replace(sepRegExp, '_'); } }; const ensureWatch = options => { if (!options.watch) { options.watch = { enable: false }; return options; } let watch = options.watch; if (watch === true) { watch = { enable: true }; } options.watch = _extends({ ignoreDotFiles: watch.ignoreDotFiles || options.watchIgnoreDotFiles, dirs: watch.dirs || options.watchDirs }, watch); }; const ensureOptions = (() => { var _ref = _asyncToGenerator(function* () { let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; options.cwd = (0, _path.resolve)(options.cwd); ensureName(options); // TODO: root is deprecated options.baseDir = (0, _path.resolve)(options.cwd, options.root || options.baseDir); // DEPRECATED options.root = options.baseDir; if (options.logsDir !== false) { if (!options.logsDir) { const daemon = options.daemon, name = options.name; options.logsDir = daemon ? yield _workspace2.default.getLogsDir(name) : false; } else { options.logsDir = (0, _path.resolve)(options.baseDir, options.logsDir); } } options.execArgs = [].concat(options.execArgs || []); if (options.inspect === 'true' || options.inspect === true) { options.inspect = '127.0.0.1:9229'; } else if (options.inspect === 'false') { delete options.inspect; } else if ((0, _lodash.isObject)(options.inspect)) { var _options$inspect = options.inspect, _options$inspect$port = _options$inspect.port; const port = _options$inspect$port === undefined ? 9229 : _options$inspect$port; var _options$inspect$host = _options$inspect.host; const host = _options$inspect$host === undefined ? '127.0.0.1' : _options$inspect$host; options.inspect = `${host}:${port}`; } options.events = options.events || {}; if (options.production) { options.env.NODE_ENV = 'production'; } if ((0, _lodash.isUndefined)(options.maxRestarts)) { options.maxRestarts = options.production ? -1 : 0; } ensureWatch(options); return options; }); return function ensureOptions() { return _ref.apply(this, arguments); }; })(); const startMonitorProc = (_ref2) => { let cwd = _ref2.cwd, daemon = _ref2.daemon, env = _ref2.env, name = _ref2.name; const scriptFile = (0, _path.resolve)(__dirname, '../bin/monitor'); const stdio = daemon ? 'ignore' : 'inherit'; const proc = (0, _child_process.fork)(scriptFile, [], { stdio: ['ipc', stdio, stdio], cwd, env: _extends({}, process.env, env) }); proc.originalKill = proc.kill; proc.kill = _asyncToGenerator(function* () { const connection = yield _Connection2.default.getByName(name); if (connection) yield connection.requestStopServer(); }); return proc; }; /* * The final command components: * `{execPath} {...execArgs} {entry} {...args}` */ const getSpawnArgs = options => { const baseDir = options.baseDir, entry = options.entry, execArgs = options.execArgs, args = options.args, inspect = options.inspect; const entryFile = (0, _path.resolve)(baseDir, entry); // throw error if `entryFile` is not exits. require.resolve(entryFile); const spawnArgs = [...execArgs, entryFile, ...args]; if (inspect) { spawnArgs.unshift(`--inspect=${inspect}`); } _potLogger.logger.trace('spawn args', _chalk2.default.gray(spawnArgs.join(' '))); return spawnArgs; }; const connectMonitor = (() => { var _ref4 = _asyncToGenerator(function* (monitorProc, options) { const spawnArgs = getSpawnArgs(options); const daemon = options.daemon; const ppid = monitorProc.pid; _potLogger.logger.debug('monitor pid', _chalk2.default.magenta(ppid)); return new Promise(function (resolve, reject) { const handleMonitorProcMessage = function handleMonitorProcMessage(msg) { if (!(0, _lodash.isObject)(msg)) return; const type = msg.type, payload = msg.payload; if (type === 'start') { _potLogger.logger.trace('monitor started'); monitorProc.disconnect(); monitorProc.removeListener('message', handleMonitorProcMessage); if (daemon) { monitorProc.unref(); } resolve(); } else if (type === 'error') { monitorProc.kill(); const errors = payload.errors; reject(new _aggregateError2.default(errors)); } }; monitorProc.on('message', handleMonitorProcMessage); monitorProc.once('error', function (err) { monitorProc.kill(); reject(err); }); monitorProc.send({ type: 'start', payload: _extends({}, options, { ppid, spawnArgs, potjs }) }); }); }); return function connectMonitor(_x2, _x3) { return _ref4.apply(this, arguments); }; })(); exports.default = (() => { var _ref5 = _asyncToGenerator(function* () { let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; (0, _PrepareCli.prepareRun)(_config2.default, options); let monitorProc; const kill = (() => { var _ref6 = _asyncToGenerator(function* () { if (monitorProc) { yield (0, _fkill2.default)(monitorProc.pid, { tree: true }).catch(_lodash.noop); } }); return function kill() { return _ref6.apply(this, arguments); }; })(); (0, _signalExit2.default)(_asyncToGenerator(function* () { if (!options.daemon) { yield kill(); } process.exit(); })); try { var _ref8 = yield ensureOptions(options); const name = _ref8.name, force = _ref8.force, baseDir = _ref8.baseDir; yield (0, _fsExtra.ensureDir)(baseDir); if (options.logsDir) { _potLogger.logger.trace('logs dir', _chalk2.default.gray(options.logsDir)); } _potLogger.logger.trace('logLevel', options.logLevel); const connection = yield _Connection2.default.getByName(name); if (connection) { if (force) { yield connection.requestStopServer(); } else { yield connection.disconnect(); throw new Error(`"${name}" is running.`); } } monitorProc = startMonitorProc(options); yield connectMonitor(monitorProc, options); } catch (err) { yield kill(); throw err; } return monitorProc; }); function run() { return _ref5.apply(this, arguments); } return run; })();