- Added telemetry utility to capture application events and metrics. - Integrated PostHog for event tracking with distinct user identification. - Implemented telemetry initialization, event capturing, and shutdown procedures. feat: add UV environment setup for Python management - Created utilities to manage Python installation and configuration. - Implemented network optimization checks for Python installation mirrors. - Added functions to set up managed Python environments with error handling. feat: enhance host API communication with token management - Introduced host API token retrieval and management for secure requests. - Updated host API fetch functions to include token in headers. - Added support for creating event sources with authentication. test: add comprehensive tests for gateway protocol and startup helpers - Implemented unit tests for gateway protocol helpers, event dispatching, and state management. - Added tests for startup recovery strategies and process policies. - Ensured coverage for connection monitoring and restart governance logic.
110 lines
2.8 KiB
TypeScript
110 lines
2.8 KiB
TypeScript
import type { HostApiResult } from '@src/types/runtime';
|
|
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
|
|
export interface HostApiRequest {
|
|
path: string;
|
|
method?: string;
|
|
headers?: Record<string, string>;
|
|
body?: unknown;
|
|
}
|
|
|
|
export interface NormalizedHostApiRequest {
|
|
path: string;
|
|
pathname: string;
|
|
method: string;
|
|
headers: Record<string, string>;
|
|
body: unknown;
|
|
url: URL;
|
|
}
|
|
|
|
export async function parseRawJsonBody<T>(req: IncomingMessage): Promise<T> {
|
|
const chunks: Buffer[] = [];
|
|
for await (const chunk of req) {
|
|
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
}
|
|
|
|
const raw = Buffer.concat(chunks).toString('utf8').trim();
|
|
if (!raw) {
|
|
return {} as T;
|
|
}
|
|
|
|
return JSON.parse(raw) as T;
|
|
}
|
|
|
|
export function normalizeRequest(request: HostApiRequest): NormalizedHostApiRequest {
|
|
const path = String(request.path || '/').trim() || '/';
|
|
|
|
return {
|
|
path,
|
|
pathname: new URL(path, 'http://127.0.0.1').pathname,
|
|
method: String(request.method || 'GET').trim().toUpperCase(),
|
|
headers: request.headers || {},
|
|
body: request.body ?? null,
|
|
url: new URL(path, 'http://127.0.0.1'),
|
|
};
|
|
}
|
|
|
|
export function parseJsonBody<T>(body: unknown): T {
|
|
if (body == null || body === '') {
|
|
return {} as T;
|
|
}
|
|
|
|
if (typeof body === 'string') {
|
|
return JSON.parse(body) as T;
|
|
}
|
|
|
|
return body as T;
|
|
}
|
|
|
|
export function ok<T>(data: T, status = 200): HostApiResult<T> {
|
|
return {
|
|
success: true,
|
|
ok: true,
|
|
status,
|
|
json: data,
|
|
data,
|
|
};
|
|
}
|
|
|
|
export function fail<T = unknown>(status: number, error: string, data?: T): HostApiResult<T> {
|
|
return {
|
|
success: false,
|
|
ok: false,
|
|
status,
|
|
error,
|
|
text: error,
|
|
data,
|
|
};
|
|
}
|
|
|
|
export function setCorsHeaders(res: ServerResponse, origin?: string): void {
|
|
if (origin) {
|
|
res.setHeader('Access-Control-Allow-Origin', origin);
|
|
res.setHeader('Vary', 'Origin');
|
|
} else {
|
|
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
}
|
|
res.setHeader('Access-Control-Allow-Methods', 'GET,POST,PUT,DELETE,OPTIONS');
|
|
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Host-Api-Token');
|
|
}
|
|
|
|
export function requireJsonContentType(req: IncomingMessage): boolean {
|
|
if (req.method === 'GET' || req.method === 'OPTIONS' || req.method === 'HEAD') {
|
|
return true;
|
|
}
|
|
|
|
const contentLength = req.headers['content-length'];
|
|
if (contentLength === '0' || contentLength === undefined) {
|
|
return true;
|
|
}
|
|
|
|
const contentType = req.headers['content-type'] || '';
|
|
return contentType.includes('application/json');
|
|
}
|
|
|
|
export function sendJsonResponse(res: ServerResponse, statusCode: number, payload: unknown): void {
|
|
res.statusCode = statusCode;
|
|
res.setHeader('Content-Type', 'application/json; charset=utf-8');
|
|
res.end(JSON.stringify(payload));
|
|
}
|