### GET query procedure parameters structure Source: https://github.com/dtinth/openapi-trpc/blob/main/_autodocs/endpoints.md The structure emitted for GET procedures, where the input is passed as a JSON-encoded query parameter named 'input'. ```json { "parameters": [ { "in": "query", "name": "input", "content": { "application/json": { "schema": } } } ] } ``` -------------------------------- ### Authentication via processOperation Source: https://github.com/dtinth/openapi-trpc/blob/main/_autodocs/endpoints.md Example of using the processOperation callback to inject security requirements into individual operations based on procedure metadata. ```ts processOperation: (op, meta) => { if (meta?.requiresAuth) { op.security = [{ bearerAuth: [] }] } } ``` -------------------------------- ### Path construction logic Source: https://github.com/dtinth/openapi-trpc/blob/main/_autodocs/endpoints.md This snippet demonstrates how the path key is constructed using the pathPrefix and the procedure name. ```ts const key = [ '', ...(options.pathPrefix || '/').split('/').filter(Boolean), procName, ].join('/') ``` -------------------------------- ### Basic OpenAPI document generation Source: https://github.com/dtinth/openapi-trpc/blob/main/_autodocs/api-reference/generate.md Demonstrates how to initialize a tRPC router with operation metadata and generate an OpenAPI document with a custom path prefix. ```ts import { initTRPC } from '@trpc/server' import { z } from 'zod' import { generateOpenAPIDocumentFromTRPCRouter, OperationMeta } from 'openapi-trpc' const t = initTRPC.meta().create() const appRouter = t.router({ greeting: t.router({ sayHello: t.procedure .meta({ summary: 'Greets a person' }) .input(z.object({ name: z.string().describe('Who to greet') })) .output(z.string().describe('The greeting text')) .query(() => 'hello'), createGreeting: t.procedure .input(z.object({ name: z.string() })) .mutation(() => 'ok'), }), }) const doc = generateOpenAPIDocumentFromTRPCRouter(appRouter, { pathPrefix: '/trpc', }) // doc.paths['/trpc/greeting.sayHello'].get (input as ?input= query parameter) // doc.paths['/trpc/greeting.createGreeting'].post (input in requestBody) ``` -------------------------------- ### Create dummy router for tests Source: https://github.com/dtinth/openapi-trpc/blob/main/_autodocs/types.md Creates a dummy tRPC router with a hello.world procedure for testing. Used by src/generate.test.ts and defines the DummyRouter/DummyProcedure types. ```ts export const createDummyRouter = ( t = initTRPC.meta().create(), ) => { return t.router({ hello: t.router({ world: t.procedure .meta({ description: 'ok' }) .input(z.object({ name: z.string() })) .output(z.string()) .query(() => 'hello world'), }), }) } ``` -------------------------------- ### Attaching OpenAPI metadata to procedures Source: https://github.com/dtinth/openapi-trpc/blob/main/_autodocs/api-reference/meta.md Use initTRPC.meta() to initialize the router and attach OpenAPI-specific metadata like summary, description, tags, and deprecated status to procedures. ```ts import { initTRPC } from '@trpc/server' import { z } from 'zod' import { OperationMeta } from 'openapi-trpc' const t = initTRPC.meta().create() const appRouter = t.router({ hello: t.procedure .meta({ summary: 'Say hello', description: 'A greeting procedure.', tags: ['greetings'], deprecated: false, }) .input(z.object({ name: z.string() })) .query(() => 'hi'), }) // The generated operation for /hello will carry // summary, description, tags and deprecated from the meta object. ``` -------------------------------- ### GenerateOpenAPIDocumentOptions interface with pathPrefix and processOperation Source: https://github.com/dtinth/openapi-trpc/blob/main/_autodocs/types.md Defines the options interface for generateOpenAPIDocumentFromTRPCRouter. pathPrefix defaults to '/' (options.pathPrefix || '/'), and processOperation is an optional per-operation post-processor that can mutate or return a replacement operation. The generic M extends OperationMeta and is usually inferred from the router. ```ts export interface GenerateOpenAPIDocumentOptions { pathPrefix?: string processOperation?: ( operation: OpenAPIV3.OperationObject, meta: M | undefined, ) => OpenAPIV3.OperationObject | void } ``` -------------------------------- ### generateOpenAPIDocumentFromTRPCRouter Source: https://github.com/dtinth/openapi-trpc/blob/main/_autodocs/api-reference/generate.md Documentation for the main function `generateOpenAPIDocumentFromTRPCRouter` and its options interface. ```APIDOC ## generateOpenAPIDocumentFromTRPCRouter ### Description Generates an OpenAPI 3.0.0 document from a tRPC v10 router. It inspects the router's procedures and converts them into OpenAPI paths and operations. ### Signature ```ts export function generateOpenAPIDocumentFromTRPCRouter>( inRouter: R, options?: GenerateOpenAPIDocumentOptions> ): OpenAPIV3.Document<{}> ``` ### Parameters - **inRouter** (`R extends Router`) - Required - The tRPC v10 router (result of `t.router({ ... })`). Inspected at runtime through its `_def.procedures` internal structure. Router nesting becomes dotted procedure names. - **options** (`GenerateOpenAPIDocumentOptions>`) - Optional - Options object; may be omitted entirely. See the separate section below and [configuration.md](../configuration.md). ### Return Type `OpenAPIV3.Document<{}>` - A synchronous, plain-data OpenAPI 3.0.0 document of the shape: ```ts { openapi: '3.0.0', info: { title: 'tRPC HTTP-RPC', version: '', }, paths, // OpenAPIV3.PathsObject, one entry per procedure } ``` No `servers`, `components`, `security`, or `securitySchemes` are generated by default. ### Throws - `Error('Expected a ZodObject, received: ' + String(input))` - When a procedure input is not a `ZodObject`, `ZodVoid`, or `ZodOptional` (and not a `ZodArray`). - `Error('Expected a Zod schema, received: ' + String(input))` - When a procedure `.output()` value is not a Zod schema (has no `_def.typeName`). - Any error from a user-supplied `options.processOperation` callback - Propagates unchanged. ### Behavior Summary 1. Query procedures (`procDef.query` truthy) become `get` operations; everything else becomes `post` operations. 2. `operationId` = the dotted procedure name; `tags` defaults to `procName.split('.').slice(0, -1).slice(0, 1)` (the namespace — `[]` when the name has no dot). 3. `OperationMeta` keys set on `procDef.meta` (`deprecated`, `description`, `externalDocs`, `summary`, `tags`) are copied onto the operation when truthy, overriding the default tags if `meta.tags` is set. 4. `options.processOperation?.(op, meta) || op` is applied last and its truthy return value replaces the operation. 5. Only status code `200` is ever emitted in `responses`. 6. `zodToJsonSchema` output has its `$schema` key stripped. ``` -------------------------------- ### Importing openapi-trpc symbols Source: https://github.com/dtinth/openapi-trpc/blob/main/_autodocs/README.md Shows the standard way to import the runtime function and type definitions from the package. ```ts import { generateOpenAPIDocumentFromTRPCRouter } from 'openapi-trpc' // runtime import { GenerateOpenAPIDocumentOptions } from 'openapi-trpc' // type import type { OperationMeta } from 'openapi-trpc' // type ``` -------------------------------- ### Module graph structure Source: https://github.com/dtinth/openapi-trpc/blob/main/_autodocs/README.md Visual representation of the project's file dependencies and export hierarchy. ```text src/index.ts ← package entry point (declares the public API) ├── export type { OperationMeta } from './meta' └── export * from './generate' src/generate.ts ← public: generateOpenAPIDocumentFromTRPCRouter, │ GenerateOpenAPIDocumentOptions │ internal: MetaOf, getZodTypeName, asZodObject, │ asZodType, toJsonSchema ├── imports from './dummyRouter' (internal, tests only) ├── imports from './meta' (allowedOperationKeys, OperationMeta) ├── imports from 'zod' (z, AnyZodObject, ZodType, ZodFirstPartyTypeKind, │ ZodArray, ZodTypeAny) ├── imports from 'openapi-types' (OpenAPIV3) └── imports from '@trpc/server' (RootConfig, Router, RouterDef) src/meta.ts ← public: OperationMeta │ also exports: allowedOperationKeys │ (exported from the module, but NOT re-exported at │ the package entry point — internal for consumers) src/dummyRouter.ts ← internal, used only by src/generate.test.ts and src/generate.ts (as cast targets) exports: createDummyRouter, DummyRouter, DummyProcedure ``` -------------------------------- ### GenerateOpenAPIDocumentOptions Source: https://github.com/dtinth/openapi-trpc/blob/main/etc/openapi-trpc.api.md Configuration options for the `generateOpenAPIDocumentFromTRPCRouter` function. Allows customization of the path prefix and post-processing of operations. ```APIDOC ## GenerateOpenAPIDocumentOptions ### Description Options interface for configuring the OpenAPI document generation process. ### Properties - **pathPrefix** (string) - Optional - A prefix to prepend to all operation paths in the generated OpenAPI document. - **processOperation** (function) - Optional - A callback to process each operation object after generation. Receives the operation object and its metadata, and can return a modified operation object or void. ### Type Signature ```ts export interface GenerateOpenAPIDocumentOptions { pathPrefix?: string; processOperation?: (operation: OpenAPIV3.OperationObject, meta: M | undefined) => OpenAPIV3.OperationObject | void; } ``` ``` -------------------------------- ### Custom meta type and operation processing Source: https://github.com/dtinth/openapi-trpc/blob/main/_autodocs/api-reference/generate.md Shows how to define a custom meta interface for authentication and use the processOperation hook to modify the generated OpenAPI document. ```ts import { initTRPC } from '@trpc/server' import { z } from 'zod' import { generateOpenAPIDocumentFromTRPCRouter, OperationMeta } from 'openapi-trpc' interface AppMeta extends OperationMeta { requiresAuth?: boolean } const t = initTRPC.meta().create() const appRouter = t.router({ public: t.procedure.query(() => null), private: t.procedure.meta({ requiresAuth: true }).query(() => null), }) let doc: ReturnType try { doc = generateOpenAPIDocumentFromTRPCRouter(appRouter, { pathPrefix: '/trpc', processOperation: (op, meta) => { if (meta?.requiresAuth) { op.security = [{ bearerAuth: [] }] } }, }) } catch (err) { // Only plain Error instances are thrown (see errors.md): // 'Expected a ZodObject, received: ...' | 'Expected a Zod schema, received: ...' console.error('Failed to generate the OpenAPI document', err) throw err } ``` -------------------------------- ### Configure router meta type with initTRPC.meta() Source: https://github.com/dtinth/openapi-trpc/blob/main/_autodocs/configuration.md Shows two ways to set up the tRPC router meta type for use with openapi-trpc. Option A uses the stock OperationMeta type; Option B defines a custom interface extending OperationMeta to add extra metadata fields. With Option B, processOperation's meta parameter is typed as the custom interface. ```typescript import { initTRPC } from '@trpc/server' import { OperationMeta } from 'openapi-trpc' // Option A: the stock meta type const t = initTRPC.meta().create() // Option B: your own type — must extend OperationMeta to keep // the five OpenAPI keys recognized by the generator interface AppMeta extends OperationMeta { requiresAuth?: boolean } const t = initTRPC.meta().create() ``` -------------------------------- ### Initialize tRPC with OperationMeta Source: https://github.com/dtinth/openapi-trpc/blob/main/README.md Initialize tRPC with the OperationMeta type from openapi-trpc to enable OpenAPI metadata on procedures. ```ts import { initTRPC } from '@trpc/server' import { OperationMeta } from 'openapi-trpc' const t = initTRPC.meta().create() ``` -------------------------------- ### Generate OpenAPI document from tRPC router Source: https://github.com/dtinth/openapi-trpc/blob/main/README.md Generate an OpenAPI v3 document from a tRPC router. The pathPrefix option sets the base path for the API. ```ts import { generateOpenAPIDocumentFromTRPCRouter } from 'openapi-trpc' import { appRouter } from './router' const doc = generateOpenAPIDocumentFromTRPCRouter(appRouter, { pathPrefix: '/trpc', }) ``` -------------------------------- ### GenerateOpenAPIDocumentOptions interface Source: https://github.com/dtinth/openapi-trpc/blob/main/etc/openapi-trpc.api.md Configuration options for the OpenAPI document generation process, including path prefixing and operation processing. ```ts export interface GenerateOpenAPIDocumentOptions { // (undocumented) pathPrefix?: string; // (undocumented) processOperation?: (operation: OpenAPIV3.OperationObject, meta: M | undefined) => OpenAPIV3.OperationObject | void; } ``` -------------------------------- ### OpenAPI document structure Source: https://github.com/dtinth/openapi-trpc/blob/main/_autodocs/api-reference/generate.md The base structure of the generated OpenAPI 3.0.0 document. ```ts { openapi: '3.0.0', info: { title: 'tRPC HTTP-RPC', version: '', }, paths, // OpenAPIV3.PathsObject, one entry per procedure } ``` -------------------------------- ### OperationMeta interface definition and expanded form Source: https://github.com/dtinth/openapi-trpc/blob/main/_autodocs/types.md Defines the OperationMeta interface, which extends OpenAPIV3.OperationObject by picking allowed operation keys. The expanded version shows the exact fields: deprecated, description, externalDocs, summary, and tags, all optional and typed from OpenAPIV3.OperationObject. Used as the bound for GenerateOpenAPIDocumentOptions and as the meta type for initTRPC.meta().create(). ```ts export interface OperationMeta extends Pick< OpenAPIV3.OperationObject, typeof allowedOperationKeys[number] > {} ``` ```ts export interface OperationMeta { deprecated?: OpenAPIV3.OperationObject['deprecated'] description?: OpenAPIV3.OperationObject['description'] externalDocs?: OpenAPIV3.OperationObject['externalDocs'] summary?: OpenAPIV3.OperationObject['summary'] tags?: OpenAPIV3.OperationObject['tags'] } ``` -------------------------------- ### Handling array inputs Source: https://github.com/dtinth/openapi-trpc/blob/main/_autodocs/api-reference/generate.md Illustrates how ZodArray inputs are processed to produce an array JSON schema instead of a merged object. ```ts const appRouter = t.router({ lookup: t.procedure.input(z.array(z.string())).query(() => null), }) const doc = generateOpenAPIDocumentFromTRPCRouter(appRouter, { pathPrefix: '/trpc' }) // doc.paths['/trpc/lookup'].get.parameters[0].content['application/json'].schema // → { type: 'array', items: { type: 'string' } } ``` -------------------------------- ### Add OpenAPI metadata to a tRPC procedure Source: https://github.com/dtinth/openapi-trpc/blob/main/README.md Add OpenAPI metadata to a tRPC procedure using .meta() and .describe() on Zod fields. The meta object can include deprecated, description, externalDocs, summary, or tags keys. ```ts t.procedure .meta({ summary: '…', description: '…' }) .input( z.object({ id: z.number().describe('…'), /* ... */ }), ) .query(() => { /* … */ }) ``` -------------------------------- ### Define allowedOperationKeys constant Source: https://github.com/dtinth/openapi-trpc/blob/main/_autodocs/types.md Defines the allowed operation metadata keys for the OpenAPI operation object. Exported from src/meta.ts but not re-exported at the entry point; used by OperationMeta and consumed by the meta-to-operation copy loop in src/generate.ts. ```ts export const allowedOperationKeys = defineKeys([ 'deprecated', 'description', 'externalDocs', 'summary', 'tags', ]) ``` -------------------------------- ### Operation Metadata Structure Source: https://github.com/dtinth/openapi-trpc/blob/main/_autodocs/endpoints.md The base structure for every generated operation before metadata and processing are applied. ```json { "operationId": "", "tags": [""], "parameters" | "requestBody": ..., "responses": ... } ``` -------------------------------- ### OperationMeta interface Source: https://github.com/dtinth/openapi-trpc/blob/main/etc/openapi-trpc.api.md Defines the metadata structure for operations, picking allowed keys from the OpenAPIV3 OperationObject. ```ts export interface OperationMeta extends Pick { } ``` -------------------------------- ### OperationMeta Inline-expanded Form Source: https://github.com/dtinth/openapi-trpc/blob/main/_autodocs/api-reference/meta.md An expanded view showing the five optional properties permitted by OperationMeta. ```ts export interface OperationMeta { deprecated?: OpenAPIV3.OperationObject['deprecated'] // per OpenAPI: boolean description?: OpenAPIV3.OperationObject['description'] // per OpenAPI: string externalDocs?: OpenAPIV3.OperationObject['externalDocs'] // per OpenAPI: ExternalDocumentationObject summary?: OpenAPIV3.OperationObject['summary'] // per OpenAPI: string tags?: OpenAPIV3.OperationObject['tags'] // per OpenAPI: Tag[] } ``` -------------------------------- ### JSON Response Schema with Output Source: https://github.com/dtinth/openapi-trpc/blob/main/_autodocs/endpoints.md The structure of the 200 response when a procedure has an output schema, showing the wrapping of the output data. ```json { "200": { "description": "", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": false, "required": ["result"], "properties": { "result": { "type": "object", "additionalProperties": false, "required": ["data"], "properties": { "data": } } } } } } } } ``` -------------------------------- ### Copy allowed operation metadata keys Source: https://github.com/dtinth/openapi-trpc/blob/main/_autodocs/api-reference/meta.md Copies truthy metadata values for each allowed operation key into the generated operationInfo object. Falsy values ('' , false, undefined) are omitted, so metadata tags override the namespace-based default tags computed at src/generate.ts:76. ```ts for (const key of allowedOperationKeys) { const value = procDef.meta?.[key] if (value) { operationInfo[key] = value as any } } ``` -------------------------------- ### Catch errors in consumer code Source: https://github.com/dtinth/openapi-trpc/blob/main/_autodocs/errors.md Use a standard try/catch block to handle errors during document generation. Identify specific issues by checking error message prefixes or using instanceof Error. ```ts import { generateOpenAPIDocumentFromTRPCRouter } from 'openapi-trpc' let doc try { doc = generateOpenAPIDocumentFromTRPCRouter(appRouter, { pathPrefix: '/trpc' }) } catch (err) { if (err instanceof Error && err.message.startsWith('Expected a ZodObject')) { // One of the procedures has a non-object input schema // (e.g. .input(z.string())), or a mixed/conflicting multi-input setup. } else if (err instanceof Error && err.message.startsWith('Expected a Zod schema')) { // One of the procedures has a non-Zod output value (e.g. .output('text')). } else { // Could be a zod merge error or an exception from your own // processOperation callback. } throw err } ``` -------------------------------- ### generateOpenAPIDocumentFromTRPCRouter Source: https://github.com/dtinth/openapi-trpc/blob/main/etc/openapi-trpc.api.md Generates an OpenAPI V3 document from a tRPC router. This is the primary function of the package, allowing users to produce OpenAPI documentation for their tRPC API. ```APIDOC ## generateOpenAPIDocumentFromTRPCRouter ### Description Generates an OpenAPI V3 document from a tRPC router. This function takes a tRPC router and optional configuration options, and returns an OpenAPI document object. ### Method Function ### Signature `generateOpenAPIDocumentFromTRPCRouter>(inRouter: R, options?: GenerateOpenAPIDocumentOptions>): OpenAPIV3.Document<{}>` ### Parameters - **inRouter** (Router) - Required - The tRPC router to convert into an OpenAPI document. - **options** (GenerateOpenAPIDocumentOptions>) - Optional - Configuration options for the generation process. ### Return Value - **OpenAPIV3.Document<{}>** - The generated OpenAPI V3 document. ### Example ```ts import { generateOpenAPIDocumentFromTRPCRouter } from 'openapi-trpc'; import { router } from './router'; const openApiDoc = generateOpenAPIDocumentFromTRPCRouter(router); ``` ``` -------------------------------- ### generateOpenAPIDocumentFromTRPCRouter function Source: https://github.com/dtinth/openapi-trpc/blob/main/etc/openapi-trpc.api.md Generates an OpenAPI V3 document from a provided tRPC router. Requires the router and optional configuration options. ```ts export function generateOpenAPIDocumentFromTRPCRouter>(inRouter: R, options?: GenerateOpenAPIDocumentOptions>): OpenAPIV3.Document<{}>; ``` -------------------------------- ### Define allowedOperationKeys constant Source: https://github.com/dtinth/openapi-trpc/blob/main/_autodocs/api-reference/meta.md Defines the constant array of OpenAPI operation keys that the generator reads from procedure metadata. The defineKeys helper constrains the array to keys of OpenAPIV3.OperationObject, giving the exported constant the type ('deprecated' | 'description' | 'externalDocs' | 'summary' | 'tags')[]. ```ts function defineKeys(keys: T[]): T[] { return keys } export const allowedOperationKeys = defineKeys([ 'deprecated', 'description', 'externalDocs', 'summary', 'tags', ]) ``` -------------------------------- ### Reading metadata in processOperation Source: https://github.com/dtinth/openapi-trpc/blob/main/_autodocs/api-reference/meta.md Define a custom meta interface extending OperationMeta and use the processOperation callback in generateOpenAPIDocumentFromTRPCRouter to dynamically modify the OpenAPI operation based on procedure metadata. ```ts import { generateOpenAPIDocumentFromTRPCRouter } from 'openapi-trpc' interface AppMeta extends OperationMeta { requiresAuth?: boolean } const t = initTRPC.meta().create() // ... build routes, some tagged .meta({ requiresAuth: true }) ... const doc = generateOpenAPIDocumentFromTRPCRouter(t.router({ /* ... */ }), { processOperation: (op, meta) => { // meta is typed AppMeta | undefined here if (meta?.requiresAuth) { op.security = [{ bearerAuth: [] }] } }, }) ``` -------------------------------- ### Extending OperationMeta Source: https://github.com/dtinth/openapi-trpc/blob/main/_autodocs/api-reference/meta.md Pattern for defining a custom interface that extends OperationMeta to include additional non-OpenAPI properties. ```ts import { OperationMeta } from 'openapi-trpc' interface AppMeta extends OperationMeta { requiresAuth?: boolean // extra keys beyond the OpenAPI operation keys } ```