#!/usr/bin/env node /** * cli:derive-external-api-spec * * Reads what a BA tree declares public and emits the scaffolder's spec; * records an approved decision back into `entité.md` in `write` mode. * * Usage: * npx --prefer-offline tsx skills/external-api/cli/derive-external-api-spec/index.ts \ * --spec '{"baRoot":".smartstack/ba","applicationCode":"crm","mode":"check"}' */ import { parseArgs } from 'node:util' import { executeEnvelope, failExecute, printEnvelope } from '../../../lib/output.js' import { readSpecArg } from '../../../lib/spec-arg.js' import { validate } from './validate.js' import { execute } from './execute.js' import { DeriveExternalApiSpecInputSchema, type DeriveReport } from './types.js' const COMMAND = 'derive-external-api-spec' function main(): void { const { values } = parseArgs({ options: { spec: { type: 'string' }, 'spec-file': { type: 'string' } }, strict: true, }) const specSrc = readSpecArg(values) if ('error' in specSrc) { printEnvelope(failExecute(COMMAND, [specSrc.error])) process.exit(1) } let raw: unknown try { raw = JSON.parse(specSrc.raw) } catch (err) { printEnvelope(failExecute(COMMAND, [`--spec is not valid JSON: ${(err as Error).message}`])) process.exit(1) } const validation = validate(raw) if (!validation.valid) { printEnvelope(failExecute(COMMAND, validation.errors)) process.exit(1) } try { const spec = DeriveExternalApiSpecInputSchema.parse(raw) const { report, warnings } = execute(spec) printEnvelope(executeEnvelope(COMMAND, { report, warnings: [...validation.warnings, ...warnings], nextSteps: report.publishedCount === 0 ? ['No entity declares a public API yet. Decide WITH THE USER what a third party needs, then re-run with mode "write" and declarations[].'] : [ 'Feed report.scaffoldSpec to scaffold-external-api (fill appCode / projectPath if they were not supplied).', 'Then boot once so the catalogue seed provider writes its rows, and run audit-dev-external-api.', ], })) } catch (err) { printEnvelope(failExecute(COMMAND, [(err as Error).message])) process.exit(1) } } main()