diff --git a/apps/content/content/docs/openapi/generator.mdx b/apps/content/content/docs/openapi/generator.mdx index 7608fd3d..5f5c8b07 100644 --- a/apps/content/content/docs/openapi/generator.mdx +++ b/apps/content/content/docs/openapi/generator.mdx @@ -87,12 +87,18 @@ export const router = pub.router({ To generate an OpenAPI specification, you need either the type of the [router](/docs/server/router) you intend to use or the [contract](/docs/contract/builder). ```ts twoslash -import { generateOpenAPI } from '@orpc/openapi' +import { OpenAPIGenerator } from '@orpc/openapi' +import { ZodToJsonSchemaConverter } from '@orpc/zod' import { router } from 'examples/server' import { contract } from 'examples/contract' -const spec = generateOpenAPI({ - router: contract, // both router and contract are supported +const openAPIGenerator = new OpenAPIGenerator({ + schemaConverters: [ + new ZodToJsonSchemaConverter(), + ], +}) + +const spec = await openAPIGenerator.generate(contract /* or router */, { info: { title: 'My App', version: '0.0.0', diff --git a/apps/content/examples/open-api.ts b/apps/content/examples/open-api.ts index 30e551c4..033c7103 100644 --- a/apps/content/examples/open-api.ts +++ b/apps/content/examples/open-api.ts @@ -1,17 +1,22 @@ -import { generateOpenAPI } from '@orpc/openapi' +import { OpenAPIGenerator } from '@orpc/openapi' +import { ZodToJsonSchemaConverter } from '@orpc/zod' import { contract } from 'examples/contract' import { router } from 'examples/server' -export const specFromServerRouter = generateOpenAPI({ - router, +const openAPIGenerator = new OpenAPIGenerator({ + schemaConverters: [ + new ZodToJsonSchemaConverter(), + ], +}) + +export const specFromServerRouter = await openAPIGenerator.generate(router, { info: { title: 'My App', version: '0.0.0', }, }) -export const specFromContractRouter = generateOpenAPI({ - router: contract, +export const specFromContractRouter = await openAPIGenerator.generate(contract, { info: { title: 'My App', version: '0.0.0', diff --git a/packages/next/src/action-form.ts b/packages/next/src/action-form.ts index 1e526786..7aeea4e2 100644 --- a/packages/next/src/action-form.ts +++ b/packages/next/src/action-form.ts @@ -1,5 +1,6 @@ import type { Schema, SchemaInput } from '@orpc/contract' import type { Context, CreateProcedureClientOptions } from '@orpc/server' +import { JSONSerializer } from '@orpc/openapi' import { CompositeSchemaCoercer, OpenAPIPayloadCodec, type PublicOpenAPIPayloadCodec, type SchemaCoercer } from '@orpc/openapi/fetch' import { createProcedureClient, ORPCError, unlazy } from '@orpc/server' import { forbidden, notFound, unauthorized } from 'next/navigation' @@ -21,7 +22,7 @@ export function createFormAction< const formAction = async (input: FormData): Promise => { try { - const codec = opt.payloadCodec ?? new OpenAPIPayloadCodec() + const codec = opt.payloadCodec ?? new OpenAPIPayloadCodec(new JSONSerializer()) const coercer = new CompositeSchemaCoercer(opt.schemaCoercers ?? []) const { default: procedure } = await unlazy(opt.procedure) diff --git a/playgrounds/contract-openapi/src/main.ts b/playgrounds/contract-openapi/src/main.ts index f0f3c84d..237d284d 100644 --- a/playgrounds/contract-openapi/src/main.ts +++ b/playgrounds/contract-openapi/src/main.ts @@ -1,8 +1,8 @@ import { createServer } from 'node:http' -import { generateOpenAPI } from '@orpc/openapi' +import { OpenAPIGenerator } from '@orpc/openapi' import { OpenAPIServerHandler } from '@orpc/openapi/fetch' import { CompositeHandler, ORPCHandler } from '@orpc/server/fetch' -import { ZodCoercer } from '@orpc/zod' +import { ZodCoercer, ZodToJsonSchemaConverter } from '@orpc/zod' import { createServerAdapter } from '@whatwg-node/server' import { contract } from './contract' import { router } from './router' @@ -23,6 +23,12 @@ const orpcHandler = new ORPCHandler(router, { }) const compositeHandler = new CompositeHandler([openAPIHandler, orpcHandler]) +const openAPIGenerator = new OpenAPIGenerator({ + schemaConverters: [ + new ZodToJsonSchemaConverter(), + ], +}) + const server = createServer( createServerAdapter(async (request: Request) => { const url = new URL(request.url) @@ -39,8 +45,7 @@ const server = createServer( } if (url.pathname === '/spec.json') { - const spec = await generateOpenAPI({ - router: contract, + const spec = await openAPIGenerator.generate(contract, { info: { title: 'ORPC Playground', version: '1.0.0', diff --git a/playgrounds/expressjs/src/main.ts b/playgrounds/expressjs/src/main.ts index 53dd322e..fb4f631a 100644 --- a/playgrounds/expressjs/src/main.ts +++ b/playgrounds/expressjs/src/main.ts @@ -1,7 +1,7 @@ -import { generateOpenAPI } from '@orpc/openapi' +import { OpenAPIGenerator } from '@orpc/openapi' import { OpenAPIServerHandler } from '@orpc/openapi/fetch' import { CompositeHandler, ORPCHandler } from '@orpc/server/fetch' -import { ZodCoercer } from '@orpc/zod' +import { ZodCoercer, ZodToJsonSchemaConverter } from '@orpc/zod' import { createServerAdapter } from '@whatwg-node/server' import express from 'express' import { router } from './router' @@ -37,10 +37,14 @@ app.all( }) }), ) +const openAPIGenerator = new OpenAPIGenerator({ + schemaConverters: [ + new ZodToJsonSchemaConverter(), + ], +}) app.get('/spec.json', async (req, res) => { - const spec = await generateOpenAPI({ - router, + const spec = await openAPIGenerator.generate(router, { info: { title: 'ORPC Playground', version: '1.0.0', diff --git a/playgrounds/nextjs/src/app/spec/route.ts b/playgrounds/nextjs/src/app/spec/route.ts index 5d403eac..168c07e3 100644 --- a/playgrounds/nextjs/src/app/spec/route.ts +++ b/playgrounds/nextjs/src/app/spec/route.ts @@ -1,9 +1,16 @@ -import { generateOpenAPI } from '@orpc/openapi' +import { OpenAPIGenerator } from '@orpc/openapi' + +import { ZodToJsonSchemaConverter } from '@orpc/zod' import { router } from '../api/[...rest]/router' +const openAPIGenerator = new OpenAPIGenerator({ + schemaConverters: [ + new ZodToJsonSchemaConverter(), + ], +}) + export async function GET(request: Request) { - const spec = await generateOpenAPI({ - router, + const spec = await openAPIGenerator.generate(router, { info: { title: 'ORPC Playground', version: '1.0.0', diff --git a/playgrounds/openapi/src/main.ts b/playgrounds/openapi/src/main.ts index 29c2a4da..92ba0692 100644 --- a/playgrounds/openapi/src/main.ts +++ b/playgrounds/openapi/src/main.ts @@ -1,8 +1,8 @@ import { createServer } from 'node:http' -import { generateOpenAPI } from '@orpc/openapi' +import { OpenAPIGenerator } from '@orpc/openapi' import { OpenAPIServerHandler } from '@orpc/openapi/fetch' import { CompositeHandler, ORPCHandler } from '@orpc/server/fetch' -import { ZodCoercer } from '@orpc/zod' +import { ZodCoercer, ZodToJsonSchemaConverter } from '@orpc/zod' import { createServerAdapter } from '@whatwg-node/server' import { router } from './router' import './polyfill' @@ -22,6 +22,12 @@ const orpcHandler = new ORPCHandler(router, { }) const compositeHandler = new CompositeHandler([openAPIHandler, orpcHandler]) +const openAPIGenerator = new OpenAPIGenerator({ + schemaConverters: [ + new ZodToJsonSchemaConverter(), + ], +}) + const server = createServer( createServerAdapter(async (request: Request) => { const url = new URL(request.url) @@ -38,8 +44,7 @@ const server = createServer( } if (url.pathname === '/spec.json') { - const spec = await generateOpenAPI({ - router, + const spec = await openAPIGenerator.generate(router, { info: { title: 'ORPC Playground', version: '1.0.0',