pandora
Version:
A powerful and lightweight application manager for Node.js applications powered by TypeScript.
180 lines • 6.12 kB
JavaScript
;
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