#!/usr/bin/env node import fs from "node:fs"; import path from "node:path"; import { fileURLToPath } from "node:url"; import { computeBaseConfigSchemaResponse } from "../src/config/schema-base.js"; import { formatGeneratedModule } from "./lib/format-generated-module.mjs"; const GENERATED_BY = "scripts/generate-base-config-schema.ts"; const DEFAULT_OUTPUT_PATH = "src/config/schema.base.generated.ts"; const REPO_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); function readIfExists(filePath: string): string | null { try { return fs.readFileSync(filePath, "utf8"); } catch { return null; } } function formatTypeScriptModule(source: string, outputPath: string): string { return formatGeneratedModule(source, { repoRoot: REPO_ROOT, outputPath, errorLabel: "base config schema", }); } export function renderBaseConfigSchemaModule(params?: { generatedAt?: string }): string { const payload = computeBaseConfigSchemaResponse({ generatedAt: params?.generatedAt ?? new Date().toISOString(), }); return formatTypeScriptModule( `// Auto-generated by ${GENERATED_BY}. Do not edit directly. import type { BaseConfigSchemaResponse } from "./schema-base.js"; export const GENERATED_BASE_CONFIG_SCHEMA = ${JSON.stringify(payload, null, 2)} as const satisfies BaseConfigSchemaResponse; `, DEFAULT_OUTPUT_PATH, ); } export function writeBaseConfigSchemaModule(params?: { repoRoot?: string; outputPath?: string; check?: boolean; }): { changed: boolean; wrote: boolean; outputPath: string } { const repoRoot = path.resolve(params?.repoRoot ?? REPO_ROOT); const outputPath = path.resolve(repoRoot, params?.outputPath ?? DEFAULT_OUTPUT_PATH); const current = readIfExists(outputPath); const generatedAt = current?.match(/generatedAt:\s*"([^"]+)"/u)?.[1] ?? current?.match(/"generatedAt":\s*"([^"]+)"/u)?.[1] ?? new Date().toISOString(); const next = renderBaseConfigSchemaModule({ generatedAt }); const changed = current !== next; if (params?.check) { return { changed, wrote: false, outputPath }; } if (changed) { fs.writeFileSync(outputPath, next, "utf8"); } return { changed, wrote: changed, outputPath }; } const args = new Set(process.argv.slice(2)); if (args.has("--check") && args.has("--write")) { throw new Error("Use either --check or --write, not both."); } if (import.meta.url === new URL(process.argv[1] ?? "", "file://").href) { const result = writeBaseConfigSchemaModule({ check: args.has("--check") }); if (result.changed) { if (args.has("--check")) { console.error( `[base-config-schema] stale generated output at ${path.relative(process.cwd(), result.outputPath)}`, ); process.exitCode = 1; } else { console.log(`[base-config-schema] wrote ${path.relative(process.cwd(), result.outputPath)}`); } } }