* Generates OpenAPI specifications from oRPC routers/contracts. * * @see https://orpc.dev/docs/openapi/openapi-specification OpenAPI Specification Docs
(
router: AnyContractRouter | AnyRouter,
{ customErrorResponseBodySchema, commonSchemas, filter: baseFilter, exclude, ...baseDoc }: OpenAPIGeneratorGenerateOptions = {},
)
| 103 | * @see {@link https://orpc.dev/docs/openapi/openapi-specification OpenAPI Specification Docs} |
| 104 | */ |
| 105 | async generate( |
| 106 | router: AnyContractRouter | AnyRouter, |
| 107 | { customErrorResponseBodySchema, commonSchemas, filter: baseFilter, exclude, ...baseDoc }: OpenAPIGeneratorGenerateOptions = {}, |
| 108 | ): Promise<OpenAPI.Document> { |
| 109 | const filter = baseFilter |
| 110 | ?? (({ contract, path }: TraverseContractProcedureCallbackOptions) => { |
| 111 | return !(exclude?.(contract, path) ?? false) |
| 112 | }) |
| 113 | |
| 114 | const doc: OpenAPI.Document = { |
| 115 | ...clone(baseDoc), |
| 116 | info: baseDoc.info ?? { title: 'API Reference', version: '0.0.0' }, |
| 117 | openapi: '3.1.1', |
| 118 | } as OpenAPI.Document |
| 119 | |
| 120 | const { baseSchemaConvertOptions, undefinedErrorJsonSchema } = await this.#resolveCommonSchemas(doc, commonSchemas) |
| 121 | |
| 122 | const contracts: TraverseContractProcedureCallbackOptions[] = [] |
| 123 | |
| 124 | await resolveContractProcedures({ path: [], router }, (traverseOptions) => { |
| 125 | if (!value(filter, traverseOptions)) { |
| 126 | return |
| 127 | } |
| 128 | |
| 129 | contracts.push(traverseOptions) |
| 130 | }) |
| 131 | |
| 132 | const errors: string[] = [] |
| 133 | |
| 134 | for (const { contract, path } of contracts) { |
| 135 | const stringPath = path.join('.') |
| 136 | |
| 137 | try { |
| 138 | const def = contract['~orpc'] |
| 139 | |
| 140 | const method = toOpenAPIMethod(fallbackContractConfig('defaultMethod', def.route.method)) |
| 141 | const httpPath = toOpenAPIPath(def.route.path ?? toHttpPath(path)) |
| 142 | |
| 143 | let operationObjectRef: OpenAPI.OperationObject |
| 144 | |
| 145 | if (def.route.spec !== undefined && typeof def.route.spec !== 'function') { |
| 146 | operationObjectRef = def.route.spec |
| 147 | } |
| 148 | else { |
| 149 | operationObjectRef = { |
| 150 | operationId: def.route.operationId ?? stringPath, |
| 151 | summary: def.route.summary, |
| 152 | description: def.route.description, |
| 153 | deprecated: def.route.deprecated, |
| 154 | tags: def.route.tags?.map(tag => tag), |
| 155 | } |
| 156 | |
| 157 | await this.#request(doc, operationObjectRef, def, baseSchemaConvertOptions) |
| 158 | await this.#successResponse(doc, operationObjectRef, def, baseSchemaConvertOptions) |
| 159 | await this.#errorResponse(operationObjectRef, def, baseSchemaConvertOptions, undefinedErrorJsonSchema, customErrorResponseBodySchema) |
| 160 | } |
| 161 | |
| 162 | if (typeof def.route.spec === 'function') { |
no test coverage detected