zcatalyst-cli
Version:
Command Line Tool for CATALYST
684 lines (683 loc) • 35.1 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
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) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const child_process_1 = require("child_process");
const error_1 = __importDefault(require("../../error"));
const runtime_store_1 = __importDefault(require("../../runtime-store"));
const constants_1 = require("../../util_modules/constants");
const runtime_1 = __importDefault(require("../../util_modules/constants/lib/runtime"));
const js_1 = require("../../util_modules/js");
const index_1 = require("../../util_modules/logger/index");
const master_1 = __importDefault(require("./lib/master"));
const index_js_1 = __importDefault(require("./lib/java/index.js"));
const index_js_2 = __importDefault(require("./lib/node/index.js"));
const index_js_3 = __importDefault(require("./lib/python/index.js"));
const index_js_4 = __importDefault(require("./lib/web_client/index.js"));
const index_js_5 = __importDefault(require("./lib/appsail/index.js"));
const utils_1 = require("./lib/master/utils");
const container_1 = require("../../util_modules/container");
const index_js_6 = __importDefault(require("./lib/slate/index.js"));
const ansi_colors_1 = require("ansi-colors");
const env_1 = require("../../util_modules/env");
const bioUrl = (details, masterPort, addSpaces) => {
var _a, _b, _c, _d;
const labelMap = {
bio: 'BasicIO',
browserlogic: 'Browser Logic'
};
const label = addSpaces
? ((_a = details.target) === null || _a === void 0 ? void 0 : _a.name) + ''
: `${labelMap[(_b = details.target) === null || _b === void 0 ? void 0 : _b.type]}[${(_c = details.target) === null || _c === void 0 ? void 0 : _c.name}]`;
const printLabel = label + ' '.repeat((addSpaces || label.length) - label.length);
const printUrl = 'http://localhost:' +
(masterPort === -1 ? details.httpPort : masterPort) +
new URL(((_d = details.target) === null || _d === void 0 ? void 0 : _d.url) || '').pathname;
return {
printUrl,
printLabel,
log: () => {
(0, index_1.labeled)(printLabel, printUrl).MESSAGE();
}
};
};
const aioUrl = (details, masterPort, addSpaces) => {
var _a, _b, _c;
const label = addSpaces ? ((_a = details.target) === null || _a === void 0 ? void 0 : _a.name) + '' : `AdvancedIO[${(_b = details.target) === null || _b === void 0 ? void 0 : _b.name}]`;
const printLabel = label + ' '.repeat((addSpaces || label.length) - label.length);
const printUrl = `http://localhost:${masterPort}/server/${(_c = details.target) === null || _c === void 0 ? void 0 : _c.name}/`;
return {
printUrl,
printLabel,
log: () => {
(0, index_1.labeled)(printLabel, printUrl).MESSAGE();
}
};
};
class Server {
constructor() {
this.targetsMap = {
functions: [],
server: [],
client: [],
appSail: [],
slate: []
};
}
_addBasicFnDetails(bioUrlLogs) {
const fnTargets = runtime_store_1.default.get('context.functions.targets', []);
if (fnTargets.length === 0) {
(0, index_1.debug)('No basic functions to add');
}
const httpPort = parseInt(runtime_store_1.default.get('context.port.http.' + constants_1.FN_TYPE.basic), 10);
const debugPort = parseInt(runtime_store_1.default.get('context.port.debug.' + constants_1.FN_TYPE.basic, '-1'), 10);
if (!isNaN(httpPort)) {
fnTargets
.filter((t) => {
var _a;
return t.url !== undefined &&
t.type === constants_1.FN_TYPE.basic &&
!((_a = t.stack) === null || _a === void 0 ? void 0 : _a.startsWith(runtime_1.default.language.python.value));
})
.map((t) => js_1.JS.omit(t, ['zip_stream', 'localFn']))
.forEach((t) => {
const target = {
type: 'functions',
httpPort,
debugPort,
target: t
};
this.targetsMap.functions.push(target);
bioUrlLogs.targs.push(target);
bioUrlLogs.nameMaxLength =
t.name.length > bioUrlLogs.nameMaxLength
? t.name.length
: bioUrlLogs.nameMaxLength;
});
}
}
add(type, target) {
const debugPort = runtime_store_1.default.get(`context.port.debug.${type === 'server' ? 'functions' : type}.${target.name}`, -1);
if (type === 'appsail') {
this.targetsMap.appSail.push({
type,
target: target,
httpPort: undefined,
debugPort: undefined,
isAlive: null,
restarting: false
});
return;
}
if (type === 'slate') {
this.targetsMap.slate.push({
type,
target: target,
httpPort: undefined,
debugPort: undefined,
isAlive: null,
restarting: false
});
return;
}
const httpPort = runtime_store_1.default.get(`context.port.http.${type === 'server' ? 'functions' : type}.${target.name}`, -1);
if (httpPort === -1) {
throw new error_1.default('http port is mandatory for target : ' +
target.name +
' to start advanced server', { exit: 2 });
}
type === 'client'
? this.targetsMap.client.push({
type,
target: target,
httpPort,
debugPort: undefined,
isAlive: null,
restarting: false
})
: this.targetsMap.server.push({
type,
target: target,
httpPort,
debugPort,
isAlive: null,
restarting: false
});
}
startServer(details, masterPort) {
var _a, _b, _c, _d, _e, _f;
return __awaiter(this, void 0, void 0, function* () {
if (details.target === undefined) {
return details;
}
try {
let currentProcess;
switch (details.type) {
case 'appsail': {
currentProcess = yield (0, index_js_5.default)(details);
break;
}
case 'slate': {
currentProcess = yield (0, index_js_6.default)(details);
break;
}
case 'client': {
currentProcess = yield (0, index_js_4.default)(details, masterPort);
break;
}
case 'functions':
case 'server': {
if ((_a = details.target.stack) === null || _a === void 0 ? void 0 : _a.startsWith(runtime_1.default.language.java.value)) {
currentProcess = yield (0, index_js_1.default)(details);
}
else if ((_b = details.target.stack) === null || _b === void 0 ? void 0 : _b.startsWith(runtime_1.default.language.node.value)) {
currentProcess = yield (0, index_js_2.default)(details);
}
else {
currentProcess = yield (0, index_js_3.default)(details);
}
break;
}
default: {
throw new error_1.default('Invalid feature type', { exit: 2 });
}
}
details.process = currentProcess;
currentProcess.on('error', (er) => {
const error = error_1.default.getErrorInstance(er);
const _details = details;
if (_details.target) {
_details.target.valid = false;
_details.target.failure_reason = error;
}
(0, index_1.debug)('Function serve error: ', error);
this.kill(details);
});
currentProcess.on('exit', () => {
details.isAlive = false;
utils_1.serverEvent.emit('child-exit', details);
});
const getTargetName = (target) => {
var _a, _b;
return target.type === 'appsail'
? (_a = target.target) === null || _a === void 0 ? void 0 : _a.name
: (_b = target.target) === null || _b === void 0 ? void 0 : _b.name;
};
'stdout' in currentProcess &&
(env_1.isVsCode
? (_c = currentProcess.stdout) === null || _c === void 0 ? void 0 : _c.on('data', (chunk) => {
const logs = Buffer.isBuffer(chunk)
? chunk.toString().split('\n')
: [chunk];
logs.forEach((logStr) => (0, index_1.log)('info', `[${(0, ansi_colors_1.bold)(getTargetName(details) || details.type)}] ${logStr}`, true));
})
: (_d = currentProcess.stdout) === null || _d === void 0 ? void 0 : _d.pipe(process.stdout));
'stderr' in currentProcess &&
(env_1.isVsCode
? (_e = currentProcess.stderr) === null || _e === void 0 ? void 0 : _e.on('data', (chunk) => {
const logs = Buffer.isBuffer(chunk)
? chunk.toString().split('\n')
: [chunk];
logs.forEach((logStr) => (0, index_1.log)('error', `[${(0, ansi_colors_1.bold)(getTargetName(details) || details.type)}] ${logStr}`, true));
})
: (_f = currentProcess.stderr) === null || _f === void 0 ? void 0 : _f.pipe(process.stderr));
details.isAlive = true;
return new Promise((res) => setTimeout(() => res(details), 100));
}
catch (er) {
const error = 'Unable to start the server: ' + error_1.default.getErrorInstance(er).message;
(0, index_1.debug)('Start server error: ' + er);
if (details.type === 'appsail') {
const target = details.target;
target.validity.valid = false;
(0, index_1.labeled)(`AppSail[${target.name}]`, error).ERROR();
}
else if (details.type === 'client') {
const target = details.target;
target.valid = false;
(0, index_1.labeled)(`WebClient[${details.target}]`, error).ERROR();
}
else if (details.type === 'slate') {
const target = details.target;
target.validity.valid = false;
(0, index_1.labeled)(`Slate[${target.name}]`, error).ERROR();
}
else {
const target = details.target;
target.valid = false;
(0, index_1.labeled)(`${target.type}[${target.name}]`, error).ERROR();
}
return details;
}
});
}
start() {
return __awaiter(this, void 0, void 0, function* () {
const logUrls = {
functions: {
bio: { targs: [], nameMaxLength: 0 },
aio: { targs: [], nameMaxLength: 0 },
browserlogic: { targs: [], nameMaxLength: 0 }
},
appsail: { targs: [], nameMaxLength: 0 },
slate: { targs: [], nameMaxLength: 0 },
client: {}
};
this._addBasicFnDetails(logUrls.functions.bio);
const masterTargets = ['functions', 'client', 'server'].reduce((_masterTargets, targ) => {
if (this.targetsMap[targ]) {
_masterTargets.targets[targ] = this.targetsMap[targ];
_masterTargets.length += this.targetsMap[targ].length;
}
return _masterTargets;
}, {
targets: {},
length: 0
});
const serveTargets = Object.values(masterTargets.targets);
const serveTargetsArr = serveTargets.flat();
const masterPort = runtime_store_1.default.get(`context.port.http.master`, -1);
let startPromise = Promise.resolve();
if (masterTargets.length > 0) {
if (masterPort === -1) {
throw new error_1.default('master port cannot be undefined', { exit: 2 });
}
yield Promise.all(serveTargets.map((targetDetails) => Promise.all(targetDetails.map((details) => {
const _details = details;
return this.startServer(_details, masterPort).then((t) => {
var _a, _b, _c, _d;
const serverDetails = t;
if (!((_a = serverDetails.target) === null || _a === void 0 ? void 0 : _a.valid)) {
return;
}
if (serverDetails.type === 'client') {
logUrls.client = serverDetails;
}
else {
const _details = serverDetails;
const targType = (_b = _details.target) === null || _b === void 0 ? void 0 : _b.type;
logUrls.functions[targType].targs.push(_details);
logUrls.functions[targType].nameMaxLength =
((_c = _details.target) === null || _c === void 0 ? void 0 : _c.name) &&
_details.target.name.length >
logUrls.functions[targType].nameMaxLength
? (_d = _details.target) === null || _d === void 0 ? void 0 : _d.name.length
: logUrls.functions[targType].nameMaxLength;
}
});
}))));
if (serveTargetsArr.length === 0) {
throw new error_1.default('Trying to start master server before other server', {
exit: 2
});
}
this.masterServer =
masterTargets.length > 0
? yield (0, master_1.default)(masterPort, { otherServerDetails: masterTargets.targets })
: undefined;
startPromise = new Promise((res) => {
this.masterServer
? this.masterServer.on('listening', () => {
serveTargetsArr.forEach((targetDetails) => {
var _a;
if (targetDetails.process &&
'send' in targetDetails.process) {
targetDetails.process.send('start');
return;
}
(_a = targetDetails.process) === null || _a === void 0 ? void 0 : _a.emit('start', targetDetails);
utils_1.serverEvent.emit('start', targetDetails);
});
res();
})
: res();
});
}
if (this.targetsMap.appSail.length > 0) {
yield Promise.all(this.targetsMap.appSail.map((targSail) => this.startServer(targSail, -1).then((details) => {
var _a, _b, _c, _d;
const serverDetails = details;
if (!((_a = serverDetails.target) === null || _a === void 0 ? void 0 : _a.validity.valid)) {
return;
}
logUrls.appsail.targs.push(targSail);
logUrls.appsail.nameMaxLength =
((_b = targSail.target) === null || _b === void 0 ? void 0 : _b.name) &&
((_c = targSail.target) === null || _c === void 0 ? void 0 : _c.name.length) > logUrls.appsail.nameMaxLength
? (_d = targSail.target) === null || _d === void 0 ? void 0 : _d.name.length
: logUrls.appsail.nameMaxLength;
})));
}
if (this.targetsMap.slate.length > 0) {
yield Promise.all(this.targetsMap.slate.map((targSlate) => this.startServer(targSlate, -1).then((details) => {
var _a, _b, _c, _d;
const serverDetails = details;
if (!((_a = serverDetails.target) === null || _a === void 0 ? void 0 : _a.validity.valid)) {
return;
}
logUrls.slate.targs.push(targSlate);
logUrls.slate.nameMaxLength =
((_b = targSlate.target) === null || _b === void 0 ? void 0 : _b.name) &&
((_c = targSlate.target) === null || _c === void 0 ? void 0 : _c.name.length) > logUrls.slate.nameMaxLength
? (_d = targSlate.target) === null || _d === void 0 ? void 0 : _d.name.length
: logUrls.slate.nameMaxLength;
})));
}
let loggedEntries = 0;
Object.entries(logUrls).forEach(([targType, logTarg]) => {
var _a;
switch (targType) {
case 'functions': {
const headersDisplayed = {
bio: false,
aio: false,
blo: false
};
Object.entries(logTarg).forEach((x) => {
const [_targType, _logTarg] = x;
if (_logTarg.targs.length === 0) {
return;
}
loggedEntries++;
switch (_targType) {
case 'bio': {
_logTarg.targs.forEach((t) => {
var _a, _b;
const target = t;
if (!((_a = target.target) === null || _a === void 0 ? void 0 : _a.valid)) {
return;
}
if (!((_b = target.target) === null || _b === void 0 ? void 0 : _b.url)) {
throw new error_1.default('Target URL not found', {
exit: 2
});
}
if (headersDisplayed.bio === false) {
(0, index_1.info)();
(0, index_1.info)((0, ansi_colors_1.bold)(' >>>>>>>>>>>>>> Basic I/O <<<<<<<<<<<<< '));
headersDisplayed.bio = true;
}
const _bioUrl = bioUrl(target, masterPort, _logTarg.nameMaxLength);
target.target.local_url = _bioUrl.printUrl;
_bioUrl.log();
});
(0, index_1.info)();
break;
}
case 'aio': {
_logTarg.targs.forEach((t) => {
var _a, _b;
const _target = t;
if (!((_a = _target.target) === null || _a === void 0 ? void 0 : _a.valid)) {
return;
}
if (!((_b = _target.target) === null || _b === void 0 ? void 0 : _b.url)) {
throw new error_1.default('Target URL not found', {
exit: 2
});
}
if (headersDisplayed.aio === false) {
(0, index_1.info)();
(0, index_1.info)((0, ansi_colors_1.bold)(' >>>>>>>>>>>>> Advanced I/O <<<<<<<<<<< '));
headersDisplayed.aio = true;
}
const _aioUrl = aioUrl(_target, masterPort, _logTarg.nameMaxLength);
_target.target.local_url = _aioUrl.printUrl;
_aioUrl.log();
});
(0, index_1.info)();
break;
}
case 'browserlogic': {
_logTarg.targs.forEach((t) => {
var _a, _b;
const target = t;
if (!((_a = target.target) === null || _a === void 0 ? void 0 : _a.valid)) {
return;
}
if (!((_b = target.target) === null || _b === void 0 ? void 0 : _b.url)) {
throw new error_1.default('Target URL not found', {
exit: 2
});
}
if (headersDisplayed.blo === false) {
(0, index_1.info)();
(0, index_1.info)((0, ansi_colors_1.bold)(' >>>>>>>>>>>> Browser Logic <<<<<<<<<< '));
headersDisplayed.blo = true;
}
const bloUrl = bioUrl(target, masterPort, _logTarg.nameMaxLength);
target.target.local_url = bloUrl.printUrl;
bloUrl.log();
});
(0, index_1.info)();
break;
}
}
});
break;
}
case 'appsail': {
const _logTarg = logTarg;
if (_logTarg.targs.length === 0) {
return;
}
loggedEntries++;
let isHeaderDisplayed = false;
_logTarg.targs.forEach((t) => {
const targetSail = t.target;
if (!targetSail.validity.valid) {
return;
}
if (isHeaderDisplayed === false) {
(0, index_1.info)();
(0, index_1.info)((0, ansi_colors_1.bold)(' >>>>>>>>>>>>>> AppSail <<<<<<<<<<<<<< '));
isHeaderDisplayed = true;
}
const targName = targetSail.name + '';
(0, index_1.labeled)(targName +
' '.repeat((_logTarg.nameMaxLength || targName.length) - targName.length), `http://localhost:${targetSail.port.proxy}`).MESSAGE();
});
(0, index_1.info)();
break;
}
case 'client': {
if (Object.keys(logTarg).length === 0) {
return;
}
loggedEntries++;
(0, index_1.info)();
const targApp = logTarg;
const appUrl = `http://localhost:${masterPort}/app/`;
const label = `client[${(_a = targApp.target) === null || _a === void 0 ? void 0 : _a.name}]`;
(0, index_1.info)((0, ansi_colors_1.bold)(' >>>>>>>>>>>>> Web Client <<<<<<<<<<<<'));
(0, index_1.labeled)(label, appUrl).MESSAGE();
if (targApp.target)
targApp.target.local_url = appUrl;
(0, index_1.info)();
break;
}
case 'slate': {
const _logTarg = logTarg;
if (_logTarg.targs.length === 0) {
return;
}
loggedEntries++;
let isHeaderDisplayed = false;
_logTarg.targs.forEach((t) => {
const targetSlate = t.target;
if (!targetSlate.validity.valid) {
return;
}
if (isHeaderDisplayed === false) {
(0, index_1.info)();
(0, index_1.info)((0, ansi_colors_1.bold)(' >>>>>>>>>>>>>> Slate <<<<<<<<<<<<<< '));
isHeaderDisplayed = true;
}
const targName = targetSlate.name + '';
(0, index_1.labeled)(targName +
' '.repeat((_logTarg.nameMaxLength || targName.length) - targName.length), `http://localhost:${targetSlate.port.proxy}`).MESSAGE();
});
(0, index_1.info)();
break;
}
}
});
return loggedEntries > 0
? startPromise
: Promise.reject(new error_1.default('No Resources served', { exit: 1, errorId: 'SERVE-IDX-2' }));
});
}
wait() {
return __awaiter(this, void 0, void 0, function* () {
const masterPort = runtime_store_1.default.get(`context.port.http.master`, -1);
Object.values(this.targetsMap).forEach((details) => {
details.forEach((targetdetails) => {
var _a, _b;
const target = targetdetails.target;
(_a = target.watcher) === null || _a === void 0 ? void 0 : _a.on('preparing', () => __awaiter(this, void 0, void 0, function* () {
var _c;
targetdetails.restarting = true;
(0, container_1.isContainer)()
? (_c = targetdetails.process) === null || _c === void 0 ? void 0 : _c.emit('preparing', targetdetails)
: yield this.kill(targetdetails);
}));
(_b = target.watcher) === null || _b === void 0 ? void 0 : _b.on('compiled', () => __awaiter(this, void 0, void 0, function* () {
yield this.restart(targetdetails);
targetdetails.restarting = false;
if (target.type === constants_1.FN_TYPE.basic || target.type === constants_1.FN_TYPE.browserLogic) {
(0, index_1.labeled)(`functions[${target.name}]`, 'ready!').MESSAGE();
if (!target.url) {
throw new error_1.default('Target URL not found while restarting server', {
exit: 2
});
}
bioUrl(targetdetails, masterPort).log();
}
else if (target.type === constants_1.FN_TYPE.advanced) {
(0, index_1.labeled)(`AdvancedIO[${target.name}]`, 'ready!').MESSAGE();
aioUrl(targetdetails, masterPort).log();
}
setTimeout(() => {
var _a;
(_a = target.watcher) === null || _a === void 0 ? void 0 : _a.emit('next');
}, 1000);
}));
}, this);
});
return new Promise((_res) => {
let isResolved = false;
const res = () => {
isResolved = true;
_res();
};
utils_1.serverEvent.on('child-exit', () => {
if (Object.values(this.targetsMap)
.flat()
.some((targ) => targ.isAlive !== false || targ.restarting)) {
return;
}
if (isResolved)
return;
(0, index_1.info)();
(0, index_1.warning)((0, ansi_colors_1.yellow)('No serve components alive. Initiating catalyst serve shutdown.'));
(0, index_1.info)();
utils_1.serverEvent.emit('stop');
utils_1.serverEvent.removeAllListeners('child-exit');
});
utils_1.serverEvent.once('stop', () => {
['SIGINT', 'SIGTERM'].forEach((sig) => process.removeListener(sig, res));
res();
});
['SIGINT', 'SIGTERM'].forEach((sig) => process.once(sig, res));
});
});
}
kill(target) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
const serverProcess = target.process;
if (!serverProcess) {
throw new error_1.default('Unable to kill. Process empty: ' + ((_a = target.target) === null || _a === void 0 ? void 0 : _a.name), {
exit: 2
});
}
yield new Promise((resolve) => {
if (serverProcess.pid === undefined) {
try {
serverProcess.close(() => resolve());
}
catch (e) {
serverProcess.emit('close', target);
resolve();
}
}
if (serverProcess instanceof child_process_1.ChildProcess) {
if (serverProcess.exitCode === null &&
(serverProcess.signalCode === null ||
!['SIGINT', 'SIGTERM', 'SIGKILL'].includes(serverProcess.signalCode))) {
const signal = serverProcess.spawnfile.includes('python')
? 'SIGTERM'
: 'SIGINT';
serverProcess.kill(signal);
serverProcess.once('close', resolve);
}
else {
resolve();
}
}
});
});
}
restart(target) {
return __awaiter(this, void 0, void 0, function* () {
if (!target.process) {
throw new error_1.default('Process is not defined for this target.', { exit: 2 });
}
if ((0, container_1.isContainer)()) {
target.process.emit('restart', target);
return;
}
yield this.kill(target);
yield this.startServer(target, runtime_store_1.default.get(`context.port.http.master`, -1));
utils_1.serverEvent.emit('restart', target);
});
}
stop() {
return __awaiter(this, void 0, void 0, function* () {
yield Promise.all(Object.values(this.targetsMap).map((details) => Promise.all(details.map((targetdetails) => __awaiter(this, void 0, void 0, function* () {
var _a;
const target = targetdetails.target;
if (!target) {
return;
}
yield ((_a = target.watcher) === null || _a === void 0 ? void 0 : _a.close());
if (targetdetails.process) {
return this.kill(targetdetails);
}
}))))).catch((err) => (0, index_1.debug)('Error stopping the servers: ', err));
if (this.masterServer) {
const masterServer = this.masterServer;
return new Promise((res, rej) => {
masterServer.close((err) => {
if (err) {
(0, index_1.debug)('Error stopping the master server: ', err);
return rej(err);
}
res();
});
});
}
});
}
}
exports.default = Server;