@dokploy/trpc-openapi

中文文档
0.0.19发布于 2026/04/12MITTypeScriptESM + CJS近 30 天下载 1.5万

tRPC 打开API

中文使用文档
文档目录14 节
  1. 打开API 支持 tRPC 主题 🧩
  2. 自定义( Dokploy- style)
  3. 使用量
  4. 所需资源
  5. HTTP 请求
  6. 路径参数
  7. 查询参数
  8. 请求机构
  9. 自定义信头
  10. HTTP 回复
  11. 授权
  12. 实例
  13. 类型
  14. 许可证

trpc- to- openapi 读取



打开API 支持 tRPC 主题 🧩

  • 对tRPC ^11.1.0的支持
  • 您的 tRPC 程序的简单 REST 端点 .
  • 适合逐步收养.
  • 支持所有 OpenAPI 版本.

说明: 这个项目是分叉一分叉,完全归功于原作者. 看来原作者放弃了这个项目,所以我计划在不久的将来增加新的功能.

自定义( Dokploy- style)

此分叉增加了以下行为( 灵感来自 多克宝利:

  1. 默认需要可选输入和输出参数 – 在生成的OpenAPI文档中,可选输入/输出参数按需要处理.
  2. .meta 对所有程序都是可选的 - 无程序 .meta({ openapi: ... }) 仍然以默认的 OpenAPI 元数据(从程序类型、从程序路径、, enabled: true, (中文(简体) ), protect: true) (中文(简体) ).
  3. 两面旗 meta.openapi数字 :
    • override - 当 true,只提供 openapi 对象被使用(没有合并默认值).
    • additional - 当 true,默认值先应用,然后应用 openapi 数值在上方合并.

使用量

1. 安装 trpc-to-openapi。 。 。 .

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

2. 添加 OpenApiMeta 给你的TRPC实例.

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

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

3. 启用 openapi 支持一个程序.

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}!` };
    }),

  getStatus: t.procedure
    .meta({ /* 👉 */ openapi: { method: 'GET', path: '/status' } })
    .output(z.object({ status: z.string() }))
    .query(() => {
      return { status: 'healthy' };
    });
});

4. 生成 OpenAPI 文档.

import { generateOpenApiDocument } from 'trpc-to-openapi';

import { appRouter } from '../appRouter';
import { UserSchema, ProductSchema } from '../schemas';

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

5. 增加一个 trpc-to-openapi 操作员到你的应用程序.

我们目前支持适配器 Express, (中文(简体) ), Next.js, (中文(简体) ), Fastify, (中文(简体) ), Nuxt 打开 Node:HTTP。 。 。 .

Fetch, (中文(简体) ), Cloudflare Workers 更快的TM,PR受到欢迎.

没有支持 AWS lambdas

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

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

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

server.listen(3000);

6. 利润

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

const statusRes = await fetch('http://localhost:3000/status', { method: 'GET' });
const statusBody = await statusRes.json(); /* { status: 'healthy' } */

所需资源

同伴依赖性 :

  • tRPC 服务器 v11 (@trpc/server)必须安装.
  • Zod v4 (中文(简体) )zod@^4.0.0)必须安装.

支持 OpenAPI 的程序如下: 必须 事实 :

  • 一个 output 解析器已存在并使用 Zod 审定.
  • 如果一个 input 解析器存在, 它必须使用 Zod 审定.
  • 查询 input 解析器( 当当前) 延伸 Object<{ [string]: String | Number | BigInt | Date }> 或者说 Void。 。 。 .
  • 变异 input 解析器( 当当前) 延伸 Object<{ [string]: AnyType }> 或者说 Void。 。 。 .
  • meta.openapi.method 实值 GET, (中文(简体) ), POST, (中文(简体) ), PATCH, (中文(简体) ), PUT 或者说 DELETE。 。 。 .
  • meta.openapi.path 是一个字符串,从 /。 。 。 .
  • meta.openapi.path 参数(当存在时)存在于 input 解析为 String | Number | BigInt | Date

请注意:

  • 数据 transformers (例如: superjson)被忽略.
  • 被轻视了.
  • 修行是无相相相.

HTTP 请求

程序a GET编号 :DELETE 方法将通过 URL 接受输入 query parametersA. 程序与 POST编号 :PATCH编号 :PUT 方法将通过 request body 带有 application/json 内容类型.

路径参数

一个程序可以通过URL路径参数接受一组输入. 您可以在 OpenAPI 程序中使用输入名称周围的圆括号作为路径段添加路径参数 meta.openapi.path 字段.

查询参数

查询路径参数输入总是被接受为 string。该图书馆将试图 胁迫 框中以下原始类型的输入值: number, (中文(简体) ), boolean, (中文(简体) ), bigint 财务报告和审定财务报表 date。如果您希望支持诸如 object, (中文(简体) ), array 请使用 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/Lily?greeting=Hello' /* 👈 */, {
  method: 'GET',
});
const body = await res.json(); /* { greeting: 'Hello Lily!' } */

请求机构

// 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/Lily' /* 👈 */, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ greeting: 'Hello' }),
});
const body = await res.json(); /* { greeting: 'Hello Lily!' } */

自定义信头

任何自定义标题都可以在 meta.openapi.requestHeaders 财务报告和审定财务报表 meta.openapi.responseHeaders zod 对象计划, 这些标题将不会被验证 。 请考虑使用 授权 用于一等的 OpenAPI 认证/安全支持.

HTTP 回复

状态代码将 200 以默认方式处理任何成功的请求。 如果出现错误,则状态代码将来自抛出 TRPCError 或退到 500。 。 。 .

您可以使用 responseMeta 函数.

请看 此处错误状态代码。 。 。 .

授权

要创建受保护的终点,请添加 protect: true 页:1 meta.openapi 每个 tRPC 程序的对象。 默认情况下,您可以使用 createContext 函数使用 Authorization 带有 Bearer 计划。 如果您想要使用不同的/ 附加方法( 如自定义信头或 cookie) 认证请求, 您可以通过指定来覆盖 securitySchemes 对象.

探索a 此处完整示例。 。 。 .

服务器

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

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

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

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}!` };
    }),
});

客户端

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

实例

关于先进的使用案例,请在我们的 完整的测试套件。 。 。 .

有快车

请看 此处完整示例。 。 。 .

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

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

const app = express();

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

app.listen(3000);

用 Next.js 应用程序路由器

请看 此处完整示例。 。 。 .

// src/app/[...trpc]/route.ts
import { appRouter } from '~/server/api/root';
import { createContext } from '~/server/api/trpc';
import { type NextRequest } from 'next/server';
import { createOpenApiFetchHandler } from 'trpc-to-openapi';

export const dynamic = 'force-dynamic';

const handler = (req: NextRequest) => {
  // Handle incoming OpenAPI requests
  return createOpenApiFetchHandler({
    endpoint: '/',
    router: appRouter,
    createContext: () => createContext(req),
    req,
  });
};

export {
  handler as GET,
  handler as POST,
  handler as PUT,
  handler as PATCH,
  handler as DELETE,
  handler as OPTIONS,
  handler as HEAD,
};

使用 Next.js 页面路由器

请看 此处完整示例。 。 。 .

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

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

export default createOpenApiNextHandler({ router: appRouter });

使用快捷键

请看 此处完整示例。 。 。 .

import { fastifyTRPCPlugin } from '@trpc/server/adapters/fastify';
import Fastify from 'fastify';
import { fastifyTRPCOpenApiPlugin } from 'trpc-to-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();

类型

生成 OpenApi 文档选项

请看 这里有完整的打字。 。 。 .

财产类型说明需求
titlestringAPI名称.true
descriptionstringAPI简介.false
versionstringOpenAPI文档的版本.true
baseUrlstring目标服务器的基础 URL .true
docsUrlstring外部文档的 URL .false
tagsstring[]命令端点组的列表 .false
securitySchemesRecord<string, SecuritySchemeObject>默认为 Authorization 标题带有 Bearer 计划false
filter(ctx: { metadata: { openapi: NonNullable<OpenApiMeta['openapi']> } & TMeta }) => boolean可选过滤功能包含/排除生成的 OpenAPI 文档中的程序 .false

打开 ApiMeta

请看 这里有完整的打字。 。 。 .

财产类型说明需求默认
enabledboolean将这一程序曝光到 trpc-to-openapi 适配器和 OpenAPI 文档.falsetrue
methodHttpMethodHTTP方法 此端点被曝光 。 值可以是 GET, (中文(简体) ), POST, (中文(简体) ), PATCH, (中文(简体) ), PUT 或者说 DELETE。 。 。 .trueundefined
pathstring此端点已打开路径名 。 数值必须从 /,使用 {}。 。 。 .trueundefined
protectboolean要求该端点使用安全计划.falsetrue
summarystringOpenAPI文档中包含的终点的简短摘要.falseundefined
descriptionstringOpenAPI文档中包含的终点的动词描述.falseundefined
tagsstring[]OpenAPI 文档中用于逻辑组合端点的标记列表.falseundefined
requestHeadersAnyZodObject一个 Zod 对象计划描述任何自定义头来添加到 OpenAPI 文档中此端点的请求.falseundefined
responseHeadersAnyZodObject一个 Zod 对象计划描述任何自定义头来添加到OpenAPI文档中这个端点的响应.falseundefined
successDescriptionstring用于描述成功响应的字符串 .false'Successful response'
errorResponsesnumber[] | { [key: number]: string }列出错误响应代码或响应代码的对象及其描述,以加入这个端点的响应.falseundefined
contentTypesOpenApiContentType[]OpenAPI 文档中指定的一组内容类型.false['application/json']
deprecatedboolean是否将一个终点标为已贬值falsefalse

创建 OpenApi 节点HttpHandler 选项

请看 这里有完整的打字。 。 。 .

财产类型说明需求
routerRouter您的应用程序 tRPC 路由器 .true
createContextFunction传递背景( E)ctx向程序解决者提供数据.false
responseMetaFunction返回对状态代码和标题的任何修改.false
onErrorFunction处理器内出错时调用 .false
maxBodySizenumber以字节表示的最大请求体积( 默认: 100kb) .false

许可证

根据麻省理工学院的许可证分发。 更多信息见LICENSE.

在 OpenAPI 输出中过滤程序

你可以用这个 filter 选项,从生成的 OpenAPI 文档中选择性地包含或排除程序。 过滤器函数接收带有程序元数据的上下文对象. 返回时 true 包括程序,或 false 将它排除在外.

示例

const appRouter = t.router({
  publicProc: t.procedure
    .meta({ openapi: { method: 'GET', path: '/public' }, isPublic: true })
    .input(z.object({}))
    .output(z.object({ result: z.string() }))
    .query(() => ({ result: 'public' })),
  privateProc: t.procedure
    .meta({ openapi: { method: 'GET', path: '/private' }, isPublic: false })
    .input(z.object({}))
    .output(z.object({ result: z.string() }))
    .query(() => ({ result: 'private' })),
});

// Only include procedures where isPublic is true
const openApiDocument = generateOpenApiDocument(appRouter, {
  ...defaultDocOpts,
  filter: ({ metadata }) => metadata.isPublic === true,
});

// openApiDocument.paths will only include '/public'

也可以通过一个元数据通用到 generateOpenApiDocument 获取过滤器函数中自定义元数据的适当类型:

// Define your custom metadata type
interface MyMeta {
  isPublic: boolean;
}

const openApiDocument = generateOpenApiDocument<MyMeta>(appRouter, {
  ...defaultDocOpts,
  filter: ({ metadata }) => metadata.isPublic === true,
});

版本与发布记录

@dokploy/trpc-openapi 共发布 20 个版本,首次发布于 2024/06/24;过去 12 个月发布了 16 个版本。

版本发布日期距今
0.0.19latest2026/04/127 个月前
0.0.182026/03/197 个月前
0.0.172026/02/288 个月前
0.0.162026/02/258 个月前
0.0.152026/02/258 个月前
0.0.142026/02/248 个月前

其他发布通道:beta → 3.1.0-beta.0。

关于 @dokploy/trpc-openapi 的常见问题

@dokploy/trpc-openapi 是什么?

tRPC 打开API

如何安装 @dokploy/trpc-openapi?

在项目目录运行 npm install @dokploy/trpc-openapi,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:@trpc/server(^11.1.0)、zod(^4.3.6)、zod-openapi(^5.0.1)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@dokploy/trpc-openapi 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@dokploy/trpc-openapi 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@dokploy/trpc-openapi 可以商用吗?

@dokploy/trpc-openapi 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@dokploy/trpc-openapi 的下载量有多少?

根据 npm 官方下载统计,@dokploy/trpc-openapi 在 2026/10/13 – 2026/11/11 这 30 天内被下载 15,273 次,日均约 509 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@dokploy/trpc-openapi 还在维护吗?

最新版本 0.0.19 发布于 2026/04/12(7 个月前);至今共发布 20 个版本,其中过去 12 个月发布了 16 个;首次发布于 2024/06/24。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。