UNPKG

pandora

Version:

A powerful and lightweight application manager for Node.js applications powered by TypeScript.

180 lines 6.12 kB
'use strict'; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const pandora_messenger_1 = require("pandora-messenger"); const LoggerBroker_1 = require("../universal/LoggerBroker"); const os = require("os"); const fs = require("fs"); const path = require("path"); const child_process_1 = require("child_process"); const const_1 = require("../const"); const path_1 = require("path"); const mkdirp = require("mkdirp"); const is = require('is-type-of'); const tmpDir = os.tmpdir(); const pidFile = path.join(tmpDir, 'nodejs_pandora.pid'); const pathDaemonBootstrap = require.resolve('./DaemonBootstrap'); let preparedClient = null; /** * Get messenger client of the daemon * @return {Client} */ function getMessengerClient() { return new pandora_messenger_1.default.Client({ name: const_1.DAEMON_MESSENGER, }); } /** * Determine the daemon is running * @return {Promise<boolean>} */ function isDaemonRunning() { return new Promise((resolve, reject) => { const client = getMessengerClient(); client.once('connect', () => { resolve(true); client.close(); }); client.once('error', err => { resolve(false); }); }); } exports.isDaemonRunning = isDaemonRunning; ; /** * Ensure the daemon is running * @param options * @return {Promise<any>} */ function barrierDaemon(options) { return __awaiter(this, void 0, void 0, function* () { if (!(yield isDaemonRunning())) { return new Promise((resolve, reject) => { startDaemonReal(options, resolve, reject); }); } return Promise.resolve(); }); } exports.barrierDaemon = barrierDaemon; function getDaemonClient(args) { if (preparedClient) return Promise.resolve(preparedClient); return new Promise((resolve, reject) => { const client = pandora_messenger_1.default.getClient({ name: const_1.DAEMON_MESSENGER, }); client.on('connect', () => { preparedClient = client; resolve(client); client.removeListener('error', onError); }); function onError(err) { reject(err); } client.once('error', onError); }); } exports.getDaemonClient = getDaemonClient; /** * Send a message to the daemon, it will start the daemon automatically if that is't running. * @param command * @param args * @param callback * @param timeout * @return {Promise<void>} */ function send(command, args, callback, timeout) { return __awaiter(this, void 0, void 0, function* () { timeout = timeout || 300 * 1000; try { yield barrierDaemon(); const daemonClient = yield getDaemonClient({ extensionPath: args.extensionPath }); daemonClient.send(const_1.SEND_DAEMON_MESSAGE, { command, args }, (err, data) => { if (err) { return callback(err, data); } if (data && data.error) { return callback(data.error, data.data); } return callback(null, data.data); }, timeout); } catch (err) { callback(err); } }); } exports.send = send; /** * Exit the daemon automatically if there not remind any application. * @param code */ function clearCliExit(code) { code = code != null ? code : 0; send('list', {}, (err, data) => { if (data && data.length === 0) { LoggerBroker_1.consoleLogger.info('No application remind, exit the pandora daemon automatically'); preparedClient.once('error', () => { process.exit(code); }); send('exit', {}, (err, data) => { if (err) { LoggerBroker_1.consoleLogger.error(data); process.exit(code); return; } LoggerBroker_1.consoleLogger.info(data); process.exit(code); }); } else { process.exit(code); } }); } exports.clearCliExit = clearCliExit; function startDaemonReal(options, resolve, reject) { options = options || {}; if (is.function(options)) { resolve = options; options = {}; } const args = []; if (/\.ts$/.test(module.filename)) { args.push('-r', 'ts-node/register', '-r', 'nyc-ts-patch'); } args.push(pathDaemonBootstrap); const daemonStdoutPath = LoggerBroker_1.getDaemonStdoutLogPath(); const daemonStdoutDir = path_1.dirname(daemonStdoutPath); mkdirp.sync(daemonStdoutDir); const stdout = fs.openSync(daemonStdoutPath, 'a'); const daemon = child_process_1.spawn(process.execPath, args, { stdio: ['ipc', stdout, stdout], env: Object.assign(process.env, { extensionPath: options.extensionPath }), detached: true, }); daemon.on('exit', function (code, signal) { const err = new Error(`daemon[${daemon.pid}] died unexpectedly with exit code ${code} , signal ${signal}`); reject(err); }); daemon.on('message', function (message) { LoggerBroker_1.consoleLogger.info(`pandora[${daemon.pid}] daemon started successfully.`); if (message === const_1.DAEMON_READY) { fs.writeFileSync(pidFile, daemon.pid); resolve(); } }); return daemon; } //# sourceMappingURL=DaemonHandler.js.map