zcatalyst-cli
Version:
Command Line Tool for CATALYST
203 lines (202 loc) • 11.6 kB
JavaScript
"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 __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var _TunnelServer_contextMap, _TunnelServer_server, _TunnelServer_destroyer, _TunnelServer_repel, _TunnelServer_projectId;
Object.defineProperty(exports, "__esModule", { value: true });
const express_1 = __importDefault(require("express"));
const runtime_store_1 = __importDefault(require("../../runtime-store"));
const error_1 = __importDefault(require("../../error"));
const logger_1 = require("../../util_modules/logger");
const port_resolver_1 = __importDefault(require("../../port-resolver"));
const server_1 = require("../../util_modules/server");
const ansi_colors_1 = require("ansi-colors");
const util_1 = require("util");
const project_1 = require("../../util_modules/project");
const endpoints_1 = require("../../endpoints");
class TunnelServer {
constructor(repel) {
_TunnelServer_contextMap.set(this, {});
_TunnelServer_server.set(this, void 0);
_TunnelServer_destroyer.set(this, void 0);
_TunnelServer_repel.set(this, void 0);
_TunnelServer_projectId.set(this, (0, project_1.getProjectId)());
__classPrivateFieldSet(this, _TunnelServer_repel, repel, "f");
}
isAsyncFn(fnType) {
switch (fnType) {
case 'cron':
case 'event':
case 'job': {
return true;
}
}
return false;
}
send(req, res, status = 200, data, contentType) {
return __awaiter(this, void 0, void 0, function* () {
const body = req.body;
if (this.isAsyncFn(body.function_details.function_type)) {
const tunnelAPI = yield (0, endpoints_1.tunnelAPI)();
yield tunnelAPI.tunnelCallback(status, body.default, data);
return;
}
contentType && res.contentType(contentType);
res.status(status);
res.send(data);
});
}
startServer() {
return __awaiter(this, void 0, void 0, function* () {
const tunnelPortOpt = Number.parseInt(runtime_store_1.default.get('context.port.tunnel'));
if (Number.isNaN(tunnelPortOpt)) {
return;
}
const port = yield port_resolver_1.default.getFreePort(tunnelPortOpt).catch((e) => (0, logger_1.debug)(e));
if (!port || tunnelPortOpt !== port) {
throw new error_1.default(`Port unavailable ${tunnelPortOpt}`, {
exit: 1,
errorId: 'TUNNEL-1',
arg: [ansi_colors_1.bold.red(tunnelPortOpt + ''), (0, ansi_colors_1.bold)('--tunnel')]
});
}
const app = (0, express_1.default)();
app.use(express_1.default.json());
app.all('/', (req, res) => __awaiter(this, void 0, void 0, function* () {
if (req.method !== 'POST') {
res.status(200);
res.send();
return;
}
const body = req.body;
if (!body.function_details ||
!body.function_data ||
(body.function_details.function_type !== 'integration' && !body.default)) {
res.status(400);
res.send();
__classPrivateFieldGet(this, _TunnelServer_repel, "f").write();
__classPrivateFieldGet(this, _TunnelServer_repel, "f").write('Invalid tunnel request: ' + (0, util_1.inspect)(body));
return;
}
if (this.isAsyncFn(body.function_details.function_type)) {
res.status(200);
res.send();
}
try {
__classPrivateFieldGet(this, _TunnelServer_repel, "f").write();
__classPrivateFieldGet(this, _TunnelServer_repel, "f").write((0, ansi_colors_1.bold)(`Received tunnel request from ${body.function_details.function_name}(${body.function_details.function_id})`));
const target = body.function_details.function_id in __classPrivateFieldGet(this, _TunnelServer_contextMap, "f")
? __classPrivateFieldGet(this, _TunnelServer_contextMap, "f")[body.function_details.function_id]
: yield (() => __awaiter(this, void 0, void 0, function* () {
if (__classPrivateFieldGet(this, _TunnelServer_projectId, "f") !== body.function_details.project_id) {
yield this.send(req, res, 403);
__classPrivateFieldGet(this, _TunnelServer_repel, "f").write();
__classPrivateFieldGet(this, _TunnelServer_repel, "f").write('Invalid access: the tunnel is trying to access the functions from a different project');
__classPrivateFieldGet(this, _TunnelServer_repel, "f").write();
__classPrivateFieldGet(this, _TunnelServer_repel, "f").write('[STATUS]');
__classPrivateFieldGet(this, _TunnelServer_repel, "f").write('FORBIDDEN');
return;
}
const namedFn = __classPrivateFieldGet(this, _TunnelServer_contextMap, "f")[body.function_details.function_name];
if (namedFn) {
return namedFn;
}
yield this.send(req, res, 404);
__classPrivateFieldGet(this, _TunnelServer_repel, "f").write();
__classPrivateFieldGet(this, _TunnelServer_repel, "f").write(`The tunneled function ${(0, ansi_colors_1.bold)(body.function_details.function_name)} is not present in local project directory`);
__classPrivateFieldGet(this, _TunnelServer_repel, "f").write();
__classPrivateFieldGet(this, _TunnelServer_repel, "f").write('[STATUS]');
__classPrivateFieldGet(this, _TunnelServer_repel, "f").write('NOT_FOUND');
return;
})).bind(this)();
if (!target) {
return;
}
const fnData = typeof body.function_data === 'string'
? JSON.parse(body.function_data)
: body.function_data;
target.call(false)(fnData);
const errorHandler = (e) => __awaiter(this, void 0, void 0, function* () {
yield this.send(req, res, 500);
(0, logger_1.debug)('Target error: ' + e);
});
target.once('error', errorHandler);
const response = yield new Promise((resolve, reject) => {
target.once('response', (response) => {
target.removeListener('error', errorHandler);
if (!response.Status && !response.status) {
return reject(response);
}
resolve(response);
});
});
yield this.send(req, res, response.status, response.responseBody, response.ContentType);
}
catch (e) {
yield this.send(req, res, 500);
(0, logger_1.debug)(e);
}
}));
return new Promise((res, rej) => {
try {
__classPrivateFieldSet(this, _TunnelServer_server, app.listen(port, 'localhost', () => {
__classPrivateFieldGet(this, _TunnelServer_repel, "f").write();
__classPrivateFieldGet(this, _TunnelServer_repel, "f").write((0, ansi_colors_1.bold)('Tunneling server running on port: ' + (0, ansi_colors_1.green)(port + '')));
res();
}), "f");
__classPrivateFieldSet(this, _TunnelServer_destroyer, new server_1.ConnectionDestroyer(__classPrivateFieldGet(this, _TunnelServer_server, "f")), "f");
__classPrivateFieldGet(this, _TunnelServer_server, "f").on('error', (err) => {
throw new error_1.default('Tunneling server error', {
original: err,
exit: 2
});
});
}
catch (er) {
rej(new error_1.default('Unable to start the tunneling server', {
exit: 2,
original: er
}));
}
});
});
}
addContext(name, target) {
if (!__classPrivateFieldGet(this, _TunnelServer_server, "f")) {
return this;
}
__classPrivateFieldGet(this, _TunnelServer_contextMap, "f")[name] = target;
return this;
}
stopServer() {
var _a;
return __awaiter(this, void 0, void 0, function* () {
if (!__classPrivateFieldGet(this, _TunnelServer_server, "f")) {
return;
}
return (_a = __classPrivateFieldGet(this, _TunnelServer_destroyer, "f")) === null || _a === void 0 ? void 0 : _a.destroy();
});
}
}
exports.default = TunnelServer;
_TunnelServer_contextMap = new WeakMap(), _TunnelServer_server = new WeakMap(), _TunnelServer_destroyer = new WeakMap(), _TunnelServer_repel = new WeakMap(), _TunnelServer_projectId = new WeakMap();