import type { ApiErrorResponse, CheckFailure, CheckResult, HealthResponse, RuntimeMode } from "../shared/api"; import type { StoredCheckResult } from "./checker/types"; import type { Logger } from "./logger"; import { checkerRegistry } from "./checker/runner"; import { createNoopLogger } from "./logger"; export function createApiError(error: string, status: number): ApiErrorResponse { return { error, status }; } export function createHeaders(mode: RuntimeMode, init: HeadersInit): Headers { const headers = new Headers(init); if (mode === "production") { headers.set("X-Content-Type-Options", "nosniff"); headers.set("Referrer-Policy", "strict-origin-when-cross-origin"); } return headers; } export function createHealthResponse(): HealthResponse { return { ok: true, service: "dial-server", timestamp: new Date().toISOString(), }; } export function formatDuration(ms: number): string { if (ms >= 60000 && ms % 60000 === 0) return `${ms / 60000}m`; if (ms >= 1000 && ms % 1000 === 0) return `${ms / 1000}s`; return `${ms}ms`; } export function jsonResponse( body: unknown, options: { headers?: HeadersInit; mode: RuntimeMode; status?: number }, ): Response { const headers = createHeaders(options.mode, { "Content-Type": "application/json; charset=utf-8", ...options.headers, }); return new Response(JSON.stringify(body), { headers, status: options.status, }); } export function mapCheckResult(row: StoredCheckResult, type: string, logger?: Logger): CheckResult { const log = logger ?? createNoopLogger(); let failure: CheckFailure | null = null; if (row.failure) { try { failure = JSON.parse(row.failure) as CheckFailure; } catch { log.warn({ targetId: row.target_id, timestamp: row.timestamp }, "无法解析 failure 数据"); failure = null; } } let observation: null | Record = null; if (row.observation) { try { observation = JSON.parse(row.observation) as Record; } catch { log.warn({ targetId: row.target_id, timestamp: row.timestamp }, "无法解析 observation 数据"); observation = null; } } let detail: null | string = null; if (observation !== null) { try { const checker = checkerRegistry.get(type); detail = checker.buildDetail(observation); } catch { detail = null; } } return { detail, durationMs: row.duration_ms, failure, matched: row.matched === 1, observation, timestamp: row.timestamp, }; }