Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings
This repository was archived by the owner on Nov 19, 2024. It is now read-only.
/trpc-openapiPublic archive

OpenAPI support for tRPC 🧩

License

NotificationsYou must be signed in to change notification settings

trpc/trpc-openapi

Repository files navigation


trpc-openapi

trpc-openapi



trpc-openapi is maintained by ProsePilot - simple, fast and free onlinewriting tools.


OpenAPI support fortRPC 🧩

  • Easy REST endpoints for your tRPC procedures.
  • Perfect for incremental adoption.
  • OpenAPI version 3.0.3.

Usage

1. Installtrpc-openapi.

# npmnpm install trpc-openapi# yarnyarn add trpc-openapi

2. AddOpenApiMeta to your tRPC instance.

import{initTRPC}from'@trpc/server';import{OpenApiMeta}from'trpc-openapi';constt=initTRPC.meta<OpenApiMeta>().create();/* 👈 */

3. Enableopenapi support for a procedure.

exportconstappRouter=t.router({sayHello:t.procedure.meta({/* 👉 */openapi:{method:'GET',path:'/say-hello'}}).input(z.object({name:z.string()})).output(z.object({greeting:z.string()})).query(({ input})=>{return{greeting:`Hello${input.name}!`};});});

4. Generate an OpenAPI document.

import{generateOpenApiDocument}from'trpc-openapi';import{appRouter}from'../appRouter';/* 👇 */exportconstopenApiDocument=generateOpenApiDocument(appRouter,{title:'tRPC OpenAPI',version:'1.0.0',baseUrl:'http://localhost:3000',});

5. Add antrpc-openapi handler to your app.

We currently support adapters forExpress,Next.js,Serverless,Fastify,Nuxt &Node:HTTP.

Fetch,Cloudflare Workers & more soon™, PRs are welcomed 🙌.

importhttpfrom'http';import{createOpenApiHttpHandler}from'trpc-openapi';import{appRouter}from'../appRouter';constserver=http.createServer(createOpenApiHttpHandler({router:appRouter}));/* 👈 */server.listen(3000);

6. Profit 🤑

// client.tsconstres=awaitfetch('http://localhost:3000/say-hello?name=James',{method:'GET'});constbody=awaitres.json();/* { greeting: 'Hello James!' } */

Requirements

Peer dependencies:

  • tRPC Server v10 (@trpc/server) must be installed.
  • Zod v3 (zod@^3.14.4) must be installed (recommended^3.20.0).

For a procedure to support OpenAPI the followingmust be true:

  • Bothinput andoutput parsers are present AND useZod validation.
  • Queryinput parsers extendObject<{ [string]: String | Number | BigInt | Date }> orVoid.
  • Mutationinput parsers extendObject<{ [string]: AnyType }> orVoid.
  • meta.openapi.method isGET,POST,PATCH,PUT orDELETE.
  • meta.openapi.path is a string starting with/.
  • meta.openapi.path parameters exist ininput parser asString | Number | BigInt | Date

Please note:

  • Datatransformers (such assuperjson) are ignored.
  • Trailing slashes are ignored.
  • Routing is case-insensitive.

HTTP Requests

Procedures with aGET/DELETE method will accept inputs via URLquery parameters. Procedures with aPOST/PATCH/PUT method will accept inputs via therequest body with aapplication/json orapplication/x-www-form-urlencoded content type.

Path parameters

A procedure can accept a set of inputs via URL path parameters. You can add a path parameter to any OpenAPI procedure by using curly brackets around an input name as a path segment in themeta.openapi.path field.

Query parameters

Query & path parameter inputs are always accepted as astring. This library will attempt tocoerce your input values to the following primitive types out of the box:number,boolean,bigint anddate. If you wish to support others such asobject,array etc. please usez.preprocess().

// RouterexportconstappRouter=t.router({sayHello:t.procedure.meta({openapi:{method:'GET',path:'/say-hello/{name}'/* 👈 */}}).input(z.object({name:z.string()/* 👈 */,greeting:z.string()})).output(z.object({greeting:z.string()})).query(({ input})=>{return{greeting:`${input.greeting}${input.name}!`};});});// Clientconstres=awaitfetch('http://localhost:3000/say-hello/James?greeting=Hello'/* 👈 */,{method:'GET',});constbody=awaitres.json();/* { greeting: 'Hello James!' } */

Request body

// RouterexportconstappRouter=t.router({sayHello:t.procedure.meta({openapi:{method:'POST',path:'/say-hello/{name}'/* 👈 */}}).input(z.object({name:z.string()/* 👈 */,greeting:z.string()})).output(z.object({greeting:z.string()})).mutation(({ input})=>{return{greeting:`${input.greeting}${input.name}!`};});});// Clientconstres=awaitfetch('http://localhost:3000/say-hello/James'/* 👈 */,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({greeting:'Hello'}),});constbody=awaitres.json();/* { greeting: 'Hello James!' } */

Custom headers

Any custom headers can be specified in themeta.openapi.headers array, these headers will not be validated on request. Please consider usingAuthorization for first-class OpenAPI auth/security support.

HTTP Responses

Status codes will be200 by default for any successful requests. In the case of an error, the status code will be derived from the thrownTRPCError or fallback to500.

You can modify the status code or headers for any response using theresponseMeta function.

Please seeerror status codes here.

Authorization

To create protected endpoints, addprotect: true to themeta.openapi object of each tRPC procedure. By default, you can then authenticate each request with thecreateContext function using theAuthorization header with theBearer scheme. If you wish to authenticate requests using a different/additional methods (such as custom headers, or cookies) this can be overwritten by specifyingsecuritySchemes object.

Explore acomplete example here.

Server

import{TRPCError,initTRPC}from'@trpc/server';import{OpenApiMeta}from'trpc-openapi';typeUser={id:string;name:string};constusers:User[]=[{id:'usr_123',name:'James',},];exporttypeContext={user:User|null};exportconstcreateContext=async({ req, res}):Promise<Context>=>{letuser:User|null=null;if(req.headers.authorization){constuserId=req.headers.authorization.split(' ')[1];user=users.find((_user)=>_user.id===userId);}return{ user};};constt=initTRPC.context<Context>().meta<OpenApiMeta>().create();exportconstappRouter=t.router({sayHello:t.procedure.meta({openapi:{method:'GET',path:'/say-hello',protect:true/* 👈 */}}).input(z.void())// no input expected.output(z.object({greeting:z.string()})).query(({ input, ctx})=>{if(!ctx.user){thrownewTRPCError({message:'User not found',code:'UNAUTHORIZED'});}return{greeting:`Hello${ctx.user.name}!`};}),});

Client

constres=awaitfetch('http://localhost:3000/say-hello',{method:'GET',headers:{Authorization:'Bearer usr_123'}/* 👈 */,});constbody=awaitres.json();/* { greeting: 'Hello James!' } */

Examples

For advanced use-cases, please find examples in ourcomplete test suite.

With Express

Please seefull example here.

import{createExpressMiddleware}from'@trpc/server/adapters/express';importexpressfrom'express';import{createOpenApiExpressMiddleware}from'trpc-openapi';import{appRouter}from'../appRouter';constapp=express();app.use('/api/trpc',createExpressMiddleware({router:appRouter}));app.use('/api',createOpenApiExpressMiddleware({router:appRouter}));/* 👈 */app.listen(3000);

With Next.js

Please seefull example here.

// pages/api/[...trpc].tsimport{createOpenApiNextHandler}from'trpc-openapi';import{appRouter}from'../../server/appRouter';exportdefaultcreateOpenApiNextHandler({router:appRouter});

With AWS Lambda

Please seefull example here.

import{createOpenApiAwsLambdaHandler}from'trpc-openapi';import{appRouter}from'./appRouter';exportconstopenApi=createOpenApiAwsLambdaHandler({router:appRouter});

With Fastify

Please seefull example here.

import{fastifyTRPCPlugin}from'@trpc/server/adapters/fastify';importFastifyfrom'fastify';import{fastifyTRPCOpenApiPlugin}from'trpc-openapi';import{appRouter}from'./router';constfastify=Fastify();asyncfunctionmain(){awaitfastify.register(fastifyTRPCPlugin,{router:appRouter});awaitfastify.register(fastifyTRPCOpenApiPlugin,{router:appRouter});/* 👈 */awaitfastify.listen({port:3000});}main();

Types

GenerateOpenApiDocumentOptions

Please seefull typings here.

PropertyTypeDescriptionRequired
titlestringThe title of the API.true
descriptionstringA short description of the API.false
versionstringThe version of the OpenAPI document.true
baseUrlstringThe base URL of the target server.true
docsUrlstringA URL to any external documentation.false
tagsstring[]A list for ordering endpoint groups.false
securitySchemesRecord<string, SecuritySchemeObject>Defaults toAuthorization header withBearer schemefalse

OpenApiMeta

Please seefull typings here.

PropertyTypeDescriptionRequiredDefault
enabledbooleanExposes this procedure totrpc-openapi adapters and on the OpenAPI document.falsetrue
methodHttpMethodHTTP method this endpoint is exposed on. Value can beGET,POST,PATCH,PUT orDELETE.trueundefined
pathstringPathname this endpoint is exposed on. Value must start with/, specify path parameters using{}.trueundefined
protectbooleanRequires this endpoint to use a security scheme.falsefalse
summarystringA short summary of the endpoint included in the OpenAPI document.falseundefined
descriptionstringA verbose description of the endpoint included in the OpenAPI document.falseundefined
tagsstring[]A list of tags used for logical grouping of endpoints in the OpenAPI document.falseundefined
headersParameterObject[]An array of custom headers to add for this endpoint in the OpenAPI document.falseundefined
contentTypesContentType[]A set of content types specified as accepted in the OpenAPI document.false['application/json']
deprecatedbooleanWhether or not to mark an endpoint as deprecatedfalsefalse

CreateOpenApiNodeHttpHandlerOptions

Please seefull typings here.

PropertyTypeDescriptionRequired
routerRouterYour application tRPC router.true
createContextFunctionPasses contextual (ctx) data to procedure resolvers.false
responseMetaFunctionReturns any modifications to statusCode & headers.false
onErrorFunctionCalled if error occurs inside handler.false
maxBodySizenumberMaximum request body size in bytes (default: 100kb).false

Still using tRPC v9? See our.interop() example.

License

Distributed under the MIT License. See LICENSE for more information.

Contact

James Berry - Follow me on Twitter@jlalmes 💚


[8]ページ先頭

©2009-2025 Movatter.jp