| 126 | * Generates an OpenAPI v3.1 specification for the RPC-style API handler. |
| 127 | */ |
| 128 | export class RPCApiSpecGenerator<Schema extends SchemaDef = SchemaDef> { |
| 129 | private specOptions?: OpenApiSpecOptions; |
| 130 | private readonly factory: ZodSchemaFactory<Schema>; |
| 131 | /** |
| 132 | * Schemas extracted from the Zod registry, keyed by their registered ID, with |
| 133 | * all `$ref` values already rewritten to `#/components/schemas/<id>`. |
| 134 | */ |
| 135 | private registrySchemas: Record<string, SchemaObject> = {}; |
| 136 | |
| 137 | constructor(private readonly handlerOptions: RPCApiHandlerOptions<Schema>) { |
| 138 | this.factory = createQuerySchemaFactory(handlerOptions.schema, handlerOptions.queryOptions); |
| 139 | } |
| 140 | |
| 141 | private get schema(): SchemaDef { |
| 142 | return this.handlerOptions.schema; |
| 143 | } |
| 144 | |
| 145 | private get queryOptions() { |
| 146 | return this.handlerOptions?.queryOptions; |
| 147 | } |
| 148 | |
| 149 | generateSpec(options?: OpenApiSpecOptions): OpenAPIV3_1.Document { |
| 150 | this.specOptions = options; |
| 151 | |
| 152 | // Build all model/procedure schemas eagerly and capture the full registry as |
| 153 | // JSON Schema, then transform bare-ID $refs to OpenAPI component paths. |
| 154 | const rawRegistry = this.factory.toJSONSchema(); |
| 155 | this.registrySchemas = this.transformRegistrySchemas(rawRegistry.schemas); |
| 156 | |
| 157 | return { |
| 158 | openapi: '3.1.0', |
| 159 | info: { |
| 160 | title: options?.title ?? DEFAULT_SPEC_TITLE, |
| 161 | version: options?.version ?? DEFAULT_SPEC_VERSION, |
| 162 | ...(options?.description && { description: options.description }), |
| 163 | ...(options?.summary && { summary: options.summary }), |
| 164 | }, |
| 165 | tags: this.generateTags(), |
| 166 | paths: this.generatePaths(), |
| 167 | components: { |
| 168 | schemas: { |
| 169 | ...this.registrySchemas, |
| 170 | ...this.generateSharedSchemas(), |
| 171 | }, |
| 172 | }, |
| 173 | } as OpenAPIV3_1.Document; |
| 174 | } |
| 175 | |
| 176 | /** |
| 177 | * Takes the raw `schemas` map from `z.toJSONSchema(registry)` and: |
| 178 | * 1. Rewrites bare-ID `$ref` values (e.g. `"UserWhereInput"`) to full |
| 179 | * component paths (`"#/components/schemas/UserWhereInput"`). |
| 180 | * 2. Strips the `$schema` keyword from each top-level schema object, as it |
| 181 | * is redundant inside an OpenAPI document. |
| 182 | * 3. Resolves Zod's auto-generated `__shared/$defs/schemaN` aliases. |
| 183 | * When a `__shared/$defs/schemaN` entry is itself a plain `$ref` to a |
| 184 | * named schema, every reference to it is rewritten to point directly at |
| 185 | * the target schema, removing the double indirection. Any remaining |
nothing calls this directly
no outgoing calls
no test coverage detected