1
0
Files
DiAL/src/server/helpers.ts

67 lines
1.8 KiB
TypeScript

import type { ApiErrorResponse, CheckFailure, CheckResult, HealthResponse, RuntimeMode } from "../shared/api";
import type { StoredCheckResult } from "./checker/types";
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): CheckResult {
let failure: CheckFailure | null = null;
if (row.failure) {
try {
failure = JSON.parse(row.failure) as CheckFailure;
} catch {
console.warn(`无法解析 failure 数据: target_id=${row.target_id}, timestamp=${row.timestamp}`);
failure = null;
}
}
return {
durationMs: row.duration_ms,
failure,
matched: row.matched === 1,
statusDetail: row.status_detail,
timestamp: row.timestamp,
};
}