UNPKG

zcatalyst-cli

Version:

Command Line Tool for CATALYST

684 lines (683 loc) 35.1 kB
'use strict'; 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;