/** * generateOpenApi — projects the CLEO operations registry into an OpenAPI 3.1 * document (DHQ-033/057 SDK-projection · T11918 · AC2 · M5/E-API-STANDARD-FOUNDATION * T11769). * * ## Why this exists * * The `/v1` REST gateway routes `POST /v1//` for every entry * in the 413-row {@link OPERATIONS} registry. Downstream task T11920 generates a * typed SDK client; its projection source is an OpenAPI 3.1 spec. Hand-authoring * 413 path objects (and keeping them in lock-step with the registry) is exactly * the drift trap the schema-first SSoT (`inputSchema`/`outputSchema`) was built * to close. This builder DERIVES the whole spec from the single source of truth: * * - paths ← {@link OPERATIONS} (`POST /v1//`) * - requestBody ← {@link getInputContract}(op).schema, else a JSON Schema * synthesised from `def.params` (richest available input shape) * - 200 response ← {@link getOutputContract}(op).dataSchema (hand-authored * {@link OUTPUT_CONTRACTS}, else {@link deriveOutputContract}) * * Because `OperationInputContract.schema` and `OperationOutputContract.dataSchema` * are ALREADY JSON Schema (draft-07) documents, and OpenAPI 3.1's Schema Object * IS a superset of JSON Schema (it adopts the JSON Schema 2020-12 vocabulary), * the schemas embed directly — no zod→OpenAPI conversion pass, no `zod-to-openapi` * dependency. Zod (v4) is the authoring substrate for the contracts upstream; by * the time a schema reaches this builder it is already plain JSON Schema, so this * module stays a zero-runtime-dependency projection over the registry. * * ## Boundary * * Lives in `core/src/runtime` (NOT `contracts`): it reads {@link getOutputContract} * / {@link getInputContract}, which are core-resident bodied resolvers, and it is * itself a bodied runtime helper (the contracts-purity Gate 10 forbids net-new * bodied functions in `contracts`). Import-time side-effect-free: it builds * nothing at module load, only when {@link generateOpenApi} is called. * * @packageDocumentation * @module @cleocode/core/runtime/openapi/generate-openapi * * @see {@link https://spec.openapis.org/oas/v3.1.0 | OpenAPI 3.1.0 Specification} * @see OperationOutputContract — the OUTPUT-side JSON Schema SSoT this projects * @see OperationInputContract — the INPUT-side JSON Schema SSoT this projects * * @epic T11769 * @task T11918 — AC2: zod→OpenAPI 3.1 bridge + `cleo gateway openapi` */ import { type JsonSchema } from '@cleocode/contracts'; /** * OpenAPI 3.1 `info` object — API identity surfaced to SDK generators and docs * tooling. * * @see {@link https://spec.openapis.org/oas/v3.1.0#info-object} */ export interface OpenApiInfo { /** Human-readable API title. */ title: string; /** * Semantic version of the API surface (NOT the package version). The `/v1` * REST gateway is version `1.x`; defaults to `'1.0.0'`. */ version: string; /** Optional one-line summary (OpenAPI 3.1 adds `summary` to the info object). */ summary?: string; /** Optional CommonMark description. */ description?: string; } /** * OpenAPI 3.1 Media Type object — pairs a content type with its schema. * * @see {@link https://spec.openapis.org/oas/v3.1.0#media-type-object} */ export interface OpenApiMediaType { /** The JSON Schema (2020-12 vocabulary) describing the payload. */ schema: JsonSchema; } /** * OpenAPI 3.1 Request Body object. * * @see {@link https://spec.openapis.org/oas/v3.1.0#request-body-object} */ export interface OpenApiRequestBody { /** Content keyed by media type (always `application/json` here). */ content: Record; /** Whether the request body is required (true iff the op has required params). */ required: boolean; /** Optional human description. */ description?: string; } /** * OpenAPI 3.1 Response object. * * @see {@link https://spec.openapis.org/oas/v3.1.0#response-object} */ export interface OpenApiResponse { /** Required CommonMark description of the response. */ description: string; /** Optional content keyed by media type. */ content?: Record; } /** * OpenAPI 3.1 Operation object — one HTTP operation on a path. * * @see {@link https://spec.openapis.org/oas/v3.1.0#operation-object} */ export interface OpenApiOperation { /** Unique, machine-friendly id (`..`) for SDK method naming. */ operationId: string; /** Short summary (the registry `description`). */ summary: string; /** Grouping tags — the canonical domain. */ tags: string[]; /** Request body, omitted when the op declares no input params. */ requestBody?: OpenApiRequestBody; /** Responses keyed by HTTP status code (always at least `'200'`). */ responses: Record; /** * Vendor extension carrying the CQRS gateway (`'query'` | `'mutate'`) this * operation routes through. The clean `/v1//` path omits the * gateway for readability, so the SDK reads this extension to pick the right * dispatch gateway. OpenAPI tooling ignores `x-`-prefixed members it does not * recognise, so emitting it keeps the document valid. */ 'x-cleo-gateway': 'query' | 'mutate'; } /** * OpenAPI 3.1 Path Item object — the set of HTTP operations on one path. The * CLEO `/v1` gateway only routes `POST`, so only `post` is ever populated. * * @see {@link https://spec.openapis.org/oas/v3.1.0#path-item-object} */ export interface OpenApiPathItem { /** The single `POST` operation served at this path. */ post: OpenApiOperation; } /** * A minimal, structurally-typed OpenAPI 3.1 document — exactly the members * {@link generateOpenApi} emits. The `openapi` field is pinned to the `3.1.x` * literal family so consumers can statically assert the version. * * @see {@link https://spec.openapis.org/oas/v3.1.0#openapi-object} */ export interface OpenApiDocument { /** OpenAPI version string — always `'3.1.0'`. */ openapi: '3.1.0'; /** API identity. */ info: OpenApiInfo; /** * The JSON Schema dialect every embedded Schema Object uses, declared once at * the document root per OpenAPI 3.1. The contracts ship draft-07 schemas, * which validate under the 2020-12 dialect OpenAPI 3.1 mandates. */ jsonSchemaDialect: string; /** * Path → path-item map, keyed by `//` (with a * trailing `/` segment for the cross-gateway collision pairs). */ paths: Record; } /** * Options for {@link generateOpenApi}. */ export interface GenerateOpenApiOptions { /** * Semantic version stamped into `info.version`. This is the API-surface * version (the `/v1` gateway), NOT the npm package version. * * @default '1.0.0' */ version?: string; /** * Path prefix prepended to every operation route. The SDK-facing REST surface * is versioned under `/v1` (T11769); each op maps to * `POST //`. * * @default '/v1' */ pathPrefix?: string; } /** * Project the {@link OPERATIONS} registry into a complete OpenAPI 3.1 document. * * Walks every registry entry, mapping each to a `POST` path whose `requestBody` * is the resolved input schema and whose `200` response is the resolved output * schema (`deriveOutputContract` coverage), wrapped in the LAFS envelope. * * Routing: the clean form is `POST //`. Because * the registry has cross-gateway collisions on `/` (the same * pair under both `query` and `mutate`), a colliding entry is disambiguated by * appending its gateway segment (`///`). * Each operation also carries an `x-cleo-gateway` extension so the SDK knows * which CQRS gateway to dispatch through regardless of the path form. * * The number of paths in the returned document equals `OPERATIONS.length` (AC5): * every registry entry gets a unique route (and a unique operationId). * * @param options - {@link GenerateOpenApiOptions} (version, path prefix). * @returns A structurally-valid OpenAPI 3.1 {@link OpenApiDocument}. * * @example * ```ts * const doc = generateOpenApi(); * doc.openapi; // '3.1.0' * Object.keys(doc.paths).length; // === OPERATIONS.length * doc.paths['/v1/tasks/show'].post.operationId; // 'query.tasks.show' * doc.paths['/v1/tasks/show'].post['x-cleo-gateway'];// 'query' * ``` * * @task T11918 — AC1/AC2/AC5 */ export declare function generateOpenApi(options?: GenerateOpenApiOptions): OpenApiDocument; //# sourceMappingURL=generate-openapi.d.ts.map