import { mkdir, writeFile } from "node:fs/promises"; import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; import { getApiRouterProcedures, getProcedureInputSchemaMetadata, getProcedureMethod, getProcedurePublicApiOperation, getProcedurePublicApiPermit, } from "../app/services/api-router-introspection.server"; import { apiRouter } from "../app/services/api-router.server"; const generatedFile = join( dirname(fileURLToPath(import.meta.url)), "../../../packages/protocol/src/builder-api/__generated__/server-only-router-operation-metadata.ts" ); const procedures = getApiRouterProcedures(apiRouter); const metadata = Object.fromEntries( Object.entries(procedures).flatMap(([path, procedure]) => { const id = path; const operation = getProcedurePublicApiOperation(procedure); if (operation === undefined) { return []; } if ( typeof operation !== "object" || operation === null || "command" in operation === false || "client" in operation === false ) { throw new Error(`Invalid public API operation metadata for api.${path}.`); } const method = getProcedureMethod(procedure); const permit = getProcedurePublicApiPermit(procedure); if (method === undefined) { throw new Error(`Missing public API method for api.${path}.`); } if (typeof permit !== "string") { throw new Error(`Missing public API permit for api.${path}.`); } const inputSchemaMetadata = getProcedureInputSchemaMetadata(procedure); return [ [ id, { id, command: operation.command, method, path: `api.${path}`, client: operation.client, permit, invalidatesNamespaces: "invalidatesNamespaces" in operation ? operation.invalidatesNamespaces : undefined, inputSchema: inputSchemaMetadata.inputJsonSchema, }, ], ]; }) ); await mkdir(dirname(generatedFile), { recursive: true }); await writeFile( generatedFile, `// This file is generated by apps/builder/scripts/generate-server-only-api-metadata.ts. // Do not edit manually. import type { InputJsonSchema, PublicApiOperationNamespace, PublicApiOperationPermit, } from "../runtime-contracts"; export const serverOnlyRouterOperationMetadata = ${JSON.stringify( metadata, undefined, 2 )} as const satisfies Record< string, { id: string; command: string; method: "query" | "mutation"; path: string; client: string; permit: PublicApiOperationPermit; invalidatesNamespaces?: readonly PublicApiOperationNamespace[]; inputSchema: InputJsonSchema; } >; ` );