#!/usr/bin/env node import { access, mkdir, writeFile } from 'node:fs/promises' import { spawnSync } from 'node:child_process' import path from 'node:path' const OUT_DIR = path.resolve('src/api/generated') const LOCAL_CANDIDATES = [ path.resolve('../backend/openapi.json'), path.resolve('openapi.local.json'), ] const REMOTE_CANDIDATES = [ 'http://localhost:8000/api/v1/openapi.json', 'http://localhost:8080/api/v1/openapi.json', ] async function firstReadable(paths) { for (const candidate of paths) { try { await access(candidate) return candidate } catch { continue } } return null } async function main() { let specPath = await firstReadable(LOCAL_CANDIDATES) if (!specPath) { for (const url of REMOTE_CANDIDATES) { try { const response = await fetch(url) if (!response.ok) continue const spec = await response.json() const localCopy = path.resolve('openapi.local.json') await writeFile(localCopy, JSON.stringify(spec, null, 2)) specPath = localCopy console.log(`api:generate: fetched OpenAPI schema from ${url}`) break } catch { continue } } } if (!specPath) { console.error( 'api:generate: no OpenAPI schema found.\n' + 'Start the backend (docker compose up api) or place the schema at ../backend/openapi.json,\n' + 'then re-run "npm run api:generate". The hand-written client in src/api stays the source of truth until then.', ) process.exit(1) } await mkdir(OUT_DIR, { recursive: true }) const result = spawnSync( 'npx', ['openapi-typescript', specPath, '--output', path.join(OUT_DIR, 'schema.d.ts')], { stdio: 'inherit' }, ) process.exit(result.status ?? 1) } main().catch((error) => { console.error(error) process.exit(1) })