import { createConnection } from "node:net"; import { MockAmapAdapter, RealAmapAdapter } from "./amap-adapter.js"; const API_CREDENTIALS = ["Dada/P0A/api/resend", "Dada/P0A/api/amap", "Dada/P0A/admin/pepper"] as const; export async function receiveApiCredentials(input: NodeJS.ReadableStream = process.stdin) { const chunks: Buffer[] = []; for await (const chunk of input) chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)); const payload = Buffer.concat(chunks); try { const parsed = JSON.parse(payload.toString("utf8")) as Record; const names = Object.keys(parsed).sort(); const expected = [...API_CREDENTIALS].sort(); if (names.length !== expected.length || names.some((name, index) => name !== expected[index])) { throw new Error("API credential channel contains an unexpected credential scope."); } if (expected.some((name) => typeof parsed[name] !== "string")) { throw new Error("API credential channel contains an invalid credential value."); } return parsed as Record<(typeof API_CREDENTIALS)[number], string>; } finally { payload.fill(0); for (const chunk of chunks) chunk.fill(0); chunks.length = 0; } } export function initializeApiCredentialClients(credentials: Record<(typeof API_CREDENTIALS)[number], string>) { try { const adminPepper = credentials["Dada/P0A/admin/pepper"]; if (!adminPepper) throw new Error("admin_pepper_not_configured"); return { adminAllowlistPepper: Buffer.from(adminPepper, "utf8"), amap: credentials["Dada/P0A/api/amap"] ? new RealAmapAdapter(credentials["Dada/P0A/api/amap"]) : new MockAmapAdapter(), resendConfigured: Boolean(credentials["Dada/P0A/api/resend"]), }; } finally { for (const name of API_CREDENTIALS) credentials[name] = ""; } } export function attachApiSupervisorControl(pipeName: string, shutdown: () => Promise) { const socket = createConnection(`\\\\.\\pipe\\${pipeName}`); let pending = ""; let connected = false; const pendingStatuses: string[] = []; socket.setEncoding("utf8"); socket.on("connect", () => { connected = true; socket.write("ready\n"); for (const status of pendingStatuses.splice(0)) socket.write(`${status}\n`); }); socket.on("data", (chunk) => { pending += chunk; if (!pending.includes("\n")) return; const [command] = pending.split("\n", 1); pending = ""; if (command === "shutdown") void shutdown().finally(() => socket.end()); }); return { reportStatus(status: "storage_unavailable") { if (socket.destroyed) return; if (connected) socket.write(`${status}\n`); else pendingStatuses.push(status); }, socket, }; }