import { spawn } from "node:child_process"; import { mkdtemp, rename, rm, writeFile } from "node:fs/promises"; import { tmpdir } from "node:os"; import { join } from "node:path"; const baseUrl = process.env.VITE_API_BASE_URL ?? "http://localhost:3000"; const snapshot = "src/shared/api/spec/openapi.json"; const generated = "src/shared/api/generated/schema.d.ts"; const directory = await mkdtemp(join(tmpdir(), "wealth-ledger-openapi-")); const nextSnapshot = join(directory, "openapi.json"); const nextGenerated = join(directory, "schema.d.ts"); try { const response = await fetch(`${baseUrl}/api/docs-json`, { headers: { Accept: "application/json" }, }); if (!response.ok) throw new Error( `OpenAPI sync failed: ${response.status} ${response.statusText}`, ); const document = await response.json(); if (!document || typeof document !== "object") throw new Error("OpenAPI sync failed: endpoint did not return an object"); await writeFile(nextSnapshot, `${JSON.stringify(document, null, 2)}\n`); await new Promise((resolve, reject) => { const child = spawn( "npx", ["--no-install", "openapi-typescript", nextSnapshot, "-o", nextGenerated], { stdio: "inherit", }, ); child.on("error", reject); child.on("exit", (code) => code === 0 ? resolve() : reject(new Error(`openapi-typescript exited with ${code}`)), ); }); await rename(nextSnapshot, snapshot); await rename(nextGenerated, generated); } finally { await rm(directory, { recursive: true, force: true }); }