랭킹으로 돌아가기

trpc/trpc-openapi

TypeScriptnpmjs.com/package/trpc-openapi

OpenAPI support for tRPC 🧩

openapiswaggertrpcnodejsresttypescript
스타 성장
스타
2.3k
포크
198
주간 성장
이슈
61
5001k1.5k2k
25년 9월25년 12월26년 4월26년 7월
아티팩트npmnpm install trpc-openapi
README

[!NOTE]

Repo is archived due to not having maintainers - feel free to contact us if you want to take over maintenance.

Otherwise, we might reintroduce trpc-openapi to the world as a paid package.

For now, look at https://www.npmjs.com/package/trpc-to-openapi for an alternative


trpc-openapi

trpc-openapi



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


OpenAPI support for tRPC 🧩

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

Usage

1. Install trpc-openapi.

# npm
npm install trpc-openapi
# yarn
yarn add trpc-openapi

2. Add OpenApiMeta to your tRPC instance.

import { initTRPC } from '@trpc/server';
import { OpenApiMeta } from 'trpc-openapi';

const t = initTRPC.meta<OpenApiMeta>().create(); /* 👈 */

3. Enable openapi support for a procedure.

export const appRouter = 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';

/* 👇 */
export const openApiDocument = generateOpenApiDocument(appRouter, {
  title: 'tRPC OpenAPI',
  version: '1.0.0',
  baseUrl: 'http://localhost:3000',
});

5. Add an trpc-openapi handler to your app.

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

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

import http from 'http';
import { createOpenApiHttpHandler } from 'trpc-openapi';

import { appRouter } from '../appRouter';

const server = http.createServer(createOpenApiHttpHandler({ router: appRouter })); /* 👈 */

server.listen(3000);

6. Profit 🤑

// client.ts
const res = await fetch('http://localhost:3000/say-hello?name=James', { method: 'GET' });
const body = await res.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 following must be true:

  • Both input and output parsers are present AND use Zod validation.
  • Query input parsers extend Object<{ [string]: String | Number | BigInt | Date }> or Void.
  • Mutation input parsers extend Object<{ [string]: AnyType }> or Void.
  • meta.openapi.method is GET, POST, PATCH, PUT or DELETE.
  • meta.openapi.path is a string starting with /.
  • meta.openapi.path parameters exist in input parser as String | Number | BigInt | Date

Please note:

  • Data transformers (such as superjson) are ignored.
  • Trailing slashes are ignored.
  • Routing is case-insensitive.

HTTP Requests

Procedures with a GET/DELETE method will accept inputs via URL query parameters. Procedures with a POST/PATCH/PUT method will accept inputs via the request body with a application/json or application/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 the meta.openapi.path field.

Query parameters

Query & path parameter inputs are always accepted as a string. This library will attempt to coerce your input values to the following primitive types out of the box: number, boolean, bigint and date. If you wish to support others such as object, array etc. please use z.preprocess().

// Router
export const appRouter = 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}!` };
    });
});

// Client
const res = await fetch('http://localhost:3000/say-hello/James?greeting=Hello' /* 👈 */, {
  method: 'GET',
});
const body = await res.json(); /* { greeting: 'Hello James!' } */

Request body

// Router
export const appRouter = 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}!` };
    });
});

// Client
const res = await fetch('http://localhost:3000/say-hello/James' /* 👈 */, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ greeting: 'Hello' }),
});
const body = await res.json(); /* { greeting: 'Hello James!' } */

Custom headers

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

HTTP Responses

Status codes will be 200 by default for any successful requests. In the case of an error, the status code will be derived from the thrown TRPCError or fallback to 500.

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

Please see error status codes here.

Authorization

To create protected endpoints, add protect: true to the meta.openapi object of each tRPC procedure. By default, you can then authenticate each request with the createContext function using the Authorization header with the Bearer scheme. If you wish to authenticate requests using a different/additional methods (such as custom headers, or cookies) this can be overwritten by specifying securitySchemes object.

Explore a complete example here.

Server

import { TRPCError, initTRPC } from '@trpc/server';
import { OpenApiMeta } from 'trpc-openapi';

type User = { id: string; name: string };

const users: User[] = [
  {
    id: 'usr_123',
    name: 'James',
  },
];

export type Context = { user: User | null };

export const createContext = async ({ req, res }): Promise<Context> => {
  let user: User | null = null;
  if (req.headers.authorization) {
    const userId = req.headers.authorization.split(' ')[1];
    user = users.find((_user) => _user.id === userId);
  }
  return { user };
};

const t = initTRPC.context<Context>().meta<OpenApiMeta>().create();

export const appRouter = 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) {
        throw new TRPCError({ message: 'User not found', code: 'UNAUTHORIZED' });
      }
      return { greeting: `Hello ${ctx.user.name}!` };
    }),
});

Client

const res = await fetch('http://localhost:3000/say-hello', {
  method: 'GET',
  headers: { Authorization: 'Bearer usr_123' } /* 👈 */,
});
const body = await res.json(); /* { greeting: 'Hello James!' } */

Examples

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

With Express

Please see full example here.

import { createExpressMiddleware } from '@trpc/server/adapters/express';
import express from 'express';
import { createOpenApiExpressMiddleware } from 'trpc-openapi';

import { appRouter } from '../appRouter';

const app = express();

app.use('/api/trpc', createExpressMiddleware({ router: appRouter }));
app.use('/api', createOpenApiExpressMiddleware({ router: appRouter })); /* 👈 */

app.listen(3000);

With Next.js

Please see full example here.

// pages/api/[...trpc].ts
import { createOpenApiNextHandler } from 'trpc-openapi';

import { appRouter } from '../../server/appRouter';

export default createOpenApiNextHandler({ router: appRouter });

With AWS Lambda

Please see full example here.

import { createOpenApiAwsLambdaHandler } from 'trpc-openapi';

import { appRouter } from './appRouter';

export const openApi = createOpenApiAwsLambdaHandler({ router: appRouter });

With Fastify

Please see full example here.

import { fastifyTRPCPlugin } from '@trpc/server/adapters/fastify';
import Fastify from 'fastify';
import { fastifyTRPCOpenApiPlugin } from 'trpc-openapi';

import { appRouter } from './router';

const fastify = Fastify();

async function main() {
  await fastify.register(fastifyTRPCPlugin, { router: appRouter });
  await fastify.register(fastifyTRPCOpenApiPlugin, { router: appRouter }); /* 👈 */

  await fastify.listen({ port: 3000 });
}

main();

Types

GenerateOpenApiDocumentOptions

Please see full typings here.

Property Type Description Required
title string The title of the API. true
description string A short description of the API. false
version string The version of the OpenAPI document. true
baseUrl string The base URL of the target server. true
docsUrl string A URL to any external documentation. false
tags string[] A list for ordering endpoint groups. false
securitySchemes Record<string, SecuritySchemeObject> Defaults to Authorization header with Bearer scheme false

OpenApiMeta

Please see full typings here.

Property Type Description Required Default
enabled boolean Exposes this procedure to trpc-openapi adapters and on the OpenAPI document. false true
method HttpMethod HTTP method this endpoint is exposed on. Value can be GET, POST, PATCH, PUT or DELETE. true undefined
path string Pathname this endpoint is exposed on. Value must start with /, specify path parameters using {}. true undefined
protect boolean Requires this endpoint to use a security scheme. false false
summary string A short summary of the endpoint included in the OpenAPI document. false undefined
description string A verbose description of the endpoint included in the OpenAPI document. false undefined
tags string[] A list of tags used for logical grouping of endpoints in the OpenAPI document. false undefined
headers ParameterObject[] An array of custom headers to add for this endpoint in the OpenAPI document. false undefined
contentTypes ContentType[] A set of content types specified as accepted in the OpenAPI document. false ['application/json']
deprecated boolean Whether or not to mark an endpoint as deprecated false false

CreateOpenApiNodeHttpHandlerOptions

Please see full typings here.

Property Type Description Required
router Router Your application tRPC router. true
createContext Function Passes contextual (ctx) data to procedure resolvers. false
responseMeta Function Returns any modifications to statusCode & headers. false
onError Function Called if error occurs inside handler. false
maxBodySize number Maximum 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 💚

관련 저장소
open-webui/open-webui

User-friendly AI Interface (Supports Ollama, OpenAI API, ...)

PythonPyPIOtherollamaollama-webui
openwebui.com
146.3k21.2k
fastapi/fastapi

FastAPI framework, high performance, easy to learn, fast to code, ready for production

PythonPyPIMIT Licensepythonjson
fastapi.tiangolo.com
100.8k9.7k
usebruno/bruno

Opensource IDE For Exploring and Testing API's (lightweight alternative to Postman/Insomnia)

JavaScriptnpmMIT Licenseapi-clientgit
usebruno.com
45.8k2.7k
fastapi/full-stack-fastapi-template

Full stack, modern web application template. Using FastAPI, React, SQLModel, PostgreSQL, Docker, GitHub Actions, automatic HTTPS and more.

TypeScriptnpmMIT Licensepythonjson
44.4k8.8k
OAI/OpenAPI-Specification

The OpenAPI Specification Repository

MarkdownApache License 2.0openapiopenapi-specification
openapis.org
31.1k9.2k
swagger-api/swagger-ui

Swagger UI is a collection of HTML, JavaScript, and CSS assets that dynamically generate beautiful documentation from a Swagger-compliant API.

JavaScriptnpmApache License 2.0swaggerswagger-ui
swagger.io
28.9k9.3k
OpenAPITools/openapi-generator

OpenAPI Generator allows generation of API client libraries (SDK generation), server stubs, documentation and configuration automatically given an OpenAPI Spec (v2, v3)

JavaMavenApache License 2.0rest-apirest-client
openapi-generator.tech
26.6k7.6k
Redocly/redoc

📘 OpenAPI/Swagger-generated API Reference Documentation

TypeScriptnpmMIT Licenseopenapiswagger
redocly.github.io/redoc/
25.8k2.4k
grpc-ecosystem/grpc-gateway

gRPC to JSON proxy generator following the gRPC HTTP spec

GoGo ModulesBSD 3-Clause "New" or "Revised" Licensegogrpc
grpc-ecosystem.github.io/grpc-gateway/
20k2.4k
scalar/scalar

Scalar is an open-source API platform:                                       🌐 Modern REST API Client                                        📖 Beautiful API References                                        ✨ 1st-Class OpenAPI/Swagger Support

TypeScriptnpmMIT Licenseapidocs
scalar.com
15.7k902
swaggo/swag

Automatically generate RESTful API documentation with Swagger 2.0 for Go.

GoGo ModulesMIT Licensegolangswagger
12.9k1.4k
tadata-org/fastapi_mcp

Expose your FastAPI endpoints as Model Context Protocol (MCP) tools, with Auth!

PythonPyPIMIT Licenseaiclaude
fastapi-mcp.tadata.com
12k950