UNPKG

@geek-fun/serverlessinsight

Version:

Full life cycle cross providers serverless application management for your fast-growing business.

112 lines (111 loc) 4.2 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.stopLocal = exports.servLocal = void 0; const localStack_1 = require("../../types/localStack"); const common_1 = require("../../common"); const node_http_1 = __importDefault(require("node:http")); let localServer; const cleanPathSegments = (pathname) => pathname .split('/') .map((segment) => segment.trim()) .filter((segment) => segment.length > 0); const respondJson = (res, status, body, headers = {}) => { res.writeHead(status, { 'Content-Type': 'application/json', ...headers }); res.end(JSON.stringify(body)); }; const respondRaw = (res, status, body, headers = {}) => { res.writeHead(status, headers); res.end(body); }; const parseRequest = (req) => { const url = new URL(req.url ?? '/', 'http://localhost'); const [routeSegment, identifierSegment, ...rest] = cleanPathSegments(url.pathname); if (!routeSegment) { return undefined; } const kindKey = routeSegment.toUpperCase(); const kind = localStack_1.RouteKind[kindKey]; if (!kind) { return undefined; } const subPath = rest.length > 0 ? `/${rest.join('/')}` : '/'; return { kind, identifier: identifierSegment, url: subPath, method: req.method ?? 'GET', query: Object.fromEntries(url.searchParams.entries()), rawUrl: url.pathname, }; }; const servLocal = async (handlers, iac) => { if (localServer) { common_1.logger.info(`localServer already running on http://localhost:${common_1.SI_LOCALSTACK_SERVER_PORT}`); return; } localServer = node_http_1.default.createServer(async (req, res) => { try { const parsed = parseRequest(req); if (!parsed) { respondJson(res, 404, { error: 'Route not found' }); return; } const route = handlers.find((h) => h.kind === parsed.kind); if (!route) { respondJson(res, 404, { error: `Handler for ${parsed.kind} not registered` }); return; } const outcome = await route.handler(req, parsed, iac); if (!outcome) { respondJson(res, 204, {}); return; } // Raw responses (e.g., from bucket handler) include both Content-Type and Content-Length headers // and the body is already formatted as a string (not a JSON object) const isRawResponse = typeof outcome.body === 'string' && outcome.headers?.['Content-Type'] && outcome.headers?.['Content-Length']; if (isRawResponse) { respondRaw(res, outcome.statusCode, outcome.body, outcome.headers); } else { respondJson(res, outcome.statusCode, outcome.body ?? {}, outcome.headers); } } catch (err) { common_1.logger.error({ err }, 'Local gateway error'); respondJson(res, 500, { error: 'Local gateway failure' }); } }); await new Promise((resolve, reject) => { localServer.listen(common_1.SI_LOCALSTACK_SERVER_PORT, '0.0.0.0', () => { common_1.logger.info(`Local Server listening on http://localhost:${common_1.SI_LOCALSTACK_SERVER_PORT}`); resolve(); }); localServer.once('error', reject); }); }; exports.servLocal = servLocal; const stopLocal = async () => { if (!localServer) { common_1.logger.info('localServer is not running'); return; } await new Promise((resolve, reject) => { localServer.close((err) => { if (err) { common_1.logger.error({ err }, 'Error stopping localServer'); reject(err); } else { localServer = undefined; common_1.logger.info('localServer stopped'); resolve(); } }); }); }; exports.stopLocal = stopLocal;