@geek-fun/serverlessinsight
Version:
Full life cycle cross providers serverless application management for your fast-growing business.
112 lines (111 loc) • 4.2 kB
JavaScript
;
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;