#!/usr/bin/env tsx /** * generate-spec — capture the boilerplate's OpenAPI document into a local file. * * Invokes the headless `createOpenApiDocument` factory from `@toolctrl/api` and * writes the result to `packages/api-client-ts/openapi.json`. This file feeds * `@hey-api/openapi-ts` (see `openapi-ts.config.ts`) which then regenerates * `src/generated/`. * * Usage: * pnpm --filter @toolctrl/api-client-ts generate-spec * pnpm --filter @toolctrl/api-client-ts generate-spec -- --check * * `--check` re-runs the generation and exits non-zero if the on-disk * `openapi.json` would change — useful as a CI drift gate. * * Refs: docs/improvement-plan/08-mobile-cli-storybook-sdk/ts-sdk.md */ import { writeFileSync, readFileSync, existsSync } from "node:fs"; import { dirname, resolve } from "node:path"; import { fileURLToPath } from "node:url"; import { createOpenApiDocument } from "@toolctrl/api/openapi"; const here = dirname(fileURLToPath(import.meta.url)); const outputPath = resolve(here, "..", "openapi.json"); function buildSpec(): string { const document = createOpenApiDocument({ routing: { protocol: "https", apiHost: "api.toolctrl.de", } as never, }); return `${JSON.stringify(document, null, 2)}\n`; } function main(): void { const checkMode = process.argv.includes("--check"); const next = buildSpec(); if (checkMode) { if (!existsSync(outputPath)) { process.stderr.write(`openapi.json missing at ${outputPath} — run \`pnpm --filter @toolctrl/api-client-ts generate-spec\`.\n`); process.exit(1); } const current = readFileSync(outputPath, "utf8"); if (current !== next) { process.stderr.write( `openapi.json is stale — the upstream OpenAPI document has changed.\n` + `Run \`pnpm --filter @toolctrl/api-client-ts generate:all\` and commit the result.\n`, ); process.exit(2); } process.stdout.write("openapi.json is in sync with the upstream document.\n"); return; } writeFileSync(outputPath, next, "utf8"); process.stdout.write(`Wrote ${outputPath} (${(next.length / 1024).toFixed(1)} KiB)\n`); } main();