MCPcopy Create free account
hub / github.com/zenstackhq/zenstack / RPCApiSpecGenerator

Class RPCApiSpecGenerator

packages/server/src/api/rpc/openapi.ts:128–765  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

126 * Generates an OpenAPI v3.1 specification for the RPC-style API handler.
127 */
128export 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

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected