48 lines
2.5 KiB
TypeScript
48 lines
2.5 KiB
TypeScript
import { collectDns } from "./dns";
|
|
import { evaluateDiagnostics } from "./diagnostics";
|
|
import { collectTls } from "./tls";
|
|
import { collectHttp } from "./http";
|
|
import { normalizeHost, validateResolvedAddresses } from "./policy";
|
|
import { score } from "./score";
|
|
import type { Category, CollectorStatus, InspectionResult } from "./types";
|
|
|
|
function collectorStatus(value: Record<string, unknown>): CollectorStatus {
|
|
const meta = value._meta;
|
|
if (!meta || typeof meta !== "object" || typeof (meta as Record<string, unknown>).status !== "string") return "failed";
|
|
const status = String((meta as Record<string, unknown>).status);
|
|
return status === "ok" || status === "partial" || status === "failed" ? status : "failed";
|
|
}
|
|
|
|
export function buildCompleteness(dns: Record<string, unknown>, tls: Record<string, unknown>, http: Record<string, unknown>) {
|
|
const collectors: Record<Category, CollectorStatus> = {
|
|
dns: collectorStatus(dns),
|
|
tls: collectorStatus(tls),
|
|
http: collectorStatus(http),
|
|
};
|
|
const statuses = Object.values(collectors);
|
|
const complete = statuses.filter((status) => status === "ok").length;
|
|
const issues = [dns, tls, http].flatMap((collector) => {
|
|
const errors = collector._meta && typeof collector._meta === "object" ? (collector._meta as Record<string, unknown>).errors : [];
|
|
return Array.isArray(errors) ? errors.map((error) => typeof error === "object" && error !== null && "message" in error ? String((error as { message?: unknown }).message) : String(error)) : [];
|
|
});
|
|
return {
|
|
status: complete === statuses.length ? "complete" as const : complete === 0 ? "failed" as const : "partial" as const,
|
|
complete,
|
|
total: statuses.length,
|
|
collectors,
|
|
issues: [...new Set(issues)],
|
|
};
|
|
}
|
|
|
|
export async function inspectHost(rawHost: string): Promise<InspectionResult> {
|
|
const host = normalizeHost(rawHost);
|
|
const dns = await collectDns(host);
|
|
const addresses = validateResolvedAddresses([
|
|
...(Array.isArray(dns.a) ? dns.a.filter((value): value is string => typeof value === "string") : []),
|
|
...(Array.isArray(dns.aaaa) ? dns.aaaa.filter((value): value is string => typeof value === "string") : []),
|
|
]);
|
|
const [tls, http] = await Promise.all([collectTls(host, addresses), collectHttp(host)]);
|
|
const findings = evaluateDiagnostics(dns, tls, http);
|
|
return { host, inspectedAt: new Date().toISOString(), addresses, completeness: buildCompleteness(dns, tls, http), dns, tls, http, findings, score: score(findings) };
|
|
}
|