pot-js
Version:
Process management module
328 lines (246 loc) • 8.64 kB
JavaScript
;
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;
})();