关于 orpc-guide
orpc-guide 面向使用 oRPC 的 TypeScript 开发者,介绍框架的核心用法。内容涵盖类型安全的过程与客户端、OpenAPI 支持及多种服务端模式。
主要功能
- 01过程与路由器配置
- 02中间件、上下文与错误处理
- 03OpenAPI 生成与处理器
- 04HTTP、WebSocket 等客户端
- 05流式传输与文件处理
适用场景
- 01使用 oRPC 构建类型安全的 RPC 端点
- 02为 API 添加 OpenAPI 支持
- 03在 SSR 中直接调用过程
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ vcode-sh/ vibe-tools --skill orpc-guide安装后在 Claude Code 中输入/orpc-guide确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/adapters.mdadvanced.mdapi-reference.mdcontract-first.mdhelpers.mdintegrations.mdnestjs.mdopenapi.mdplugins.md详细介绍
oRPC 指南
oRPC 是一个类型安全的 RPC 框架,兼具端到端类型安全和 OpenAPI 兼容性。它支持过程、路由器、中间件、上下文注入、错误处理、文件上传、流式传输(SSE)、服务器操作,以及适用于 20 多种框架适配器的契约优先开发。
范围:本指南专门介绍 oRPC 库(@orpc/* 包)。它不是通用 RPC/gRPC 指南,不适用于仅使用 tRPC 的项目(迁移到 oRPC 的情况除外),也不适用于未使用 oRPC 的通用 TypeScript API 开发。有关从 tRPC 迁移到 oRPC 的信息,请参阅 references/contract-first.md。
快速开始
安装
npm install @orpc/server@latest @orpc/client@latest
如需 OpenAPI 支持,还需安装:
npm install @orpc/openapi@latest
前置条件
- Node.js 18+(推荐 20+)| Bun | Deno | Cloudflare Workers
- 建议使用 strict 模式的 TypeScript 项目
- 支持 Zod、Valibot、ArkType 及任何 Standard Schema 库
定义过程和路由器
import { ORPCError, os } from '@orpc/server'
import * as z from 'zod'
const PlanetSchema = z.object({
id: z.number().int().min(1),
name: z.string(),
description: z.string().optional(),
})
export const listPlanet = os
.input(z.object({
limit: z.number().int().min(1).max(100).optional(),
cursor: z.number().int().min(0).default(0),
}))
.handler(async ({ input }) => {
return [{ id: 1, name: 'Earth' }]
})
export const findPlanet = os
.input(PlanetSchema.pick({ id: true }))
.handler(async ({ input }) => {
return { id: 1, name: 'Earth' }
})
export const createPlanet = os
.$context<{ headers: Headers }>()
.use(({ context, next }) => {
const user = parseJWT(context.headers.get('authorization')?.split(' ')[1])
if (user) return next({ context: { user } })
throw new ORPCError('UNAUTHORIZED')
})
.input(PlanetSchema.omit({ id: true }))
.handler(async ({ input, context }) => {
return { id: 1, name: input.name }
})
export const router = {
planet: { list: listPlanet, find: findPlanet, create: createPlanet },
}
创建服务端(Node.js)
import { createServer } from 'node:http'
import { RPCHandler } from '@orpc/server/node'
import { CORSPlugin } from '@orpc/server/plugins'
import { onError } from '@orpc/server'
const handler = new RPCHandler(router, {
plugins: [new CORSPlugin()],
interceptors: [onError((error) => console.error(error))],
})
const server = createServer(async (req, res) => {
const { matched } = await handler.handle(req, res, {
prefix: '/rpc',
context: { headers: new Headers(req.headers as Record<string, string>) },
})
if (!matched) {
res.statusCode = 404
res.end('Not found')
}
})
server.listen(3000)
创建客户端
import type { RouterClient } from '@orpc/server'
import { createORPCClient } from '@orpc/client'
import { RPCLink } from '@orpc/client/fetch'
const link = new RPCLink({
url: 'http://127.0.0.1:3000/rpc',
headers: { Authorization: 'Bearer token' },
})
const client: RouterClient<typeof router> = createORPCClient(link)
// Fully typed calls
const planets = await client.planet.list({ limit: 10 })
const planet = await client.planet.find({ id: 1 })
服务端客户端(无需 HTTP)
直接调用过程,不产生 HTTP 开销——这对 Next.js、Nuxt、SvelteKit 等框架中的 SSR 至关重要。
import { call, createRouterClient } from '@orpc/server'
// Single procedure call
const result = await call(router.planet.find, { id: 1 }, { context: {} })
// Router client (multiple procedures)
const serverClient = createRouterClient(router, {
context: async () => ({ headers: await headers() }),
})
const planets = await serverClient.planet.list({ limit: 10 })
使用 .callable() 调用单个过程:
const getPlanet = os
.input(z.object({ id: z.string() }))
.handler(async ({ input }) => ({ id: input.id }))
.callable({ context: {} })
const result = await getPlanet({ id: '123' })
完整的服务端调用模式请参阅 references/api-reference.md。
核心概念
过程链
const example = os
.use(middleware) // Apply middleware
.input(z.object({...})) // Validate input (Zod/Valibot/ArkType)
.output(z.object({...})) // Validate output (recommended for perf)
.handler(async ({ input, context }) => { ... }) // Required
.callable() // Make callable as regular function
.actionable() // Server Action compatibility
只有 .handler() 是必需的。其他链式方法均为可选。
路由器
路由器是由过程组成的普通对象。它们可以嵌套,并支持延迟加载:
const router = {
ping: os.handler(async () => 'pong'),
planet: os.lazy(() => import('./planet')), // Code splitting
}
将中间件应用于路由器中的所有过程:
const router = os.use(authMiddleware).router({ ping, pong })
中间件
const authMiddleware = os
.$context<{ headers: Headers }>()
.middleware(async ({ context, next }) => {
const user = await getUser(context.headers)
if (!user) throw new ORPCError('UNAUTHORIZED')
return next({ context: { user } })
})
内置生命周期中间件:onStart、onSuccess、onError、onFinish。
上下文
有两种类型:初始上下文(在创建处理程序时提供)和执行上下文(由中间件在运行时注入)。请参阅 references/api-reference.md。
错误处理
// Normal approach
throw new ORPCError('NOT_FOUND', { message: 'Planet not found' })
// Type-safe approach
const base = os.errors({
NOT_FOUND: { message: 'Not found' },
RATE_LIMITED: { data: z.object({ retryAfter: z.number() }) },
})
警告:ORPCError.data 会发送给客户端。切勿包含敏感信息。
事件迭代器(SSE/流式传输)
const streaming = os
.output(eventIterator(z.object({ message: z.string() })))
.handler(async function* ({ input, lastEventId }) {
while (true) {
yield { message: 'Hello!' }
await new Promise(r => setTimeout(r, 1000))
}
})
文件上传/下载
const upload = os
.input(z.file())
.handler(async ({ input }) => {
console.log(input.name) // File name
return { success: true }
})
对于大于 100MB 的上传,请使用专用上传解决方案或扩展请求体解析器。
内置辅助工具
oRPC 提供常见服务端任务所需的内置辅助工具:
- Cookie:来自
@orpc/server/helpers的getCookie、setCookie、deleteCookie - Cookie 签名:使用
sign、unsign创建防篡改 Cookie - 加密:使用
encrypt、decrypt处理敏感数据(采用 PBKDF2 的 AES-GCM) - 速率限制:
@orpc/experimental-ratelimit,支持 Memory、Redis、Upstash 和 Cloudflare 适配器 - 事件发布:
@orpc/experimental-publisher,用于支持恢复功能的分布式发布/订阅
完整的 API 和示例请参阅 references/helpers.md。
关键规则和限制
- 必须提供处理程序 -
.handler()是过程唯一必需的方法 - 建议指定输出架构 - 显式指定
.output()可提升 TypeScript 性能 - 中间件去重 - oRPC 会自动去重开头的中间件;手动去重时请使用上下文守卫
- 错误数据是公开的 - 切勿在
ORPCError.data中放入敏感信息 - 请求体解析器冲突 - 在 oRPC 中间件之后注册框架请求体解析器(Express、Fastify、Elysia)
- RPCHandler 与 OpenAPIHandler - RPCHandler 使用专有协议(仅供 RPCLink 使用);OpenAPIHandler 与 REST/OpenAPI 兼容
- 延迟加载路由器 - 使用
os.lazy(() => import('./module'))进行代码拆分;使用独立的lazy()可加快类型推断 - SSE 自动重连 - 标准 SSE 客户端会自动重连;使用
lastEventId恢复流 - 文件限制 - 不支持分块上传/可恢复上传;AsyncIteratorObject 不支持 File/Blob
- React Native - Fetch API 存在限制(不支持 File/Blob 和 Event Iterator);请使用
expo/fetch或 RPC JSON Serializer 作为变通方案
处理程序设置模式
所有适配器都遵循此模式:
import { RPCHandler } from '@orpc/server/fetch' // or /node, /fastify, etc.
const handler = new RPCHandler(router, {
plugins: [new CORSPlugin()],
interceptors: [onError((error) => console.error(error))],
})
// Handle request with prefix and context
const { matched, response } = await handler.handle(request, {
prefix: '/rpc',
context: {},
})
客户端设置模式
import { RPCLink } from '@orpc/client/fetch' // HTTP
import { RPCLink } from '@orpc/client/websocket' // WebSocket
import { RPCLink } from '@orpc/client/message-port' // Message Port
常见错误
| 错误代码 | HTTP 状态 | 发生时机 |
|---|---|---|
BAD_REQUEST | 400 | 输入验证失败 |
UNAUTHORIZED | 401 | 缺少身份验证信息或身份验证无效 |
FORBIDDEN | 403 | 权限不足 |
NOT_FOUND | 404 | 未找到资源 |
TIMEOUT | 408 | 请求超时 |
TOO_MANY_REQUESTS | 429 | 请求频率受限 |
INTERNAL_SERVER_ERROR | 500 | 未处理的错误 |
非 ORPCError 异常会自动转换为 INTERNAL_SERVER_ERROR。
参考文件
- API 参考 - 过程、路由器、中间件、上下文、错误、元数据、事件迭代器、服务端操作、文件处理
- 适配器 - 20 多种框架适配器及其配置代码(Next.js、Express、Hono、Fastify、WebSocket、Electron 等)
- 插件 - 所有内置插件(CORS、批处理、重试、压缩、CSRF、验证等)
- OpenAPI - OpenAPI 规范生成、处理程序、路由、输入/输出结构、Scalar UI、OpenAPILink
- 集成 - TanStack Query、React SWR、Pinia Colada、Better Auth、AI SDK、Sentry、Pino、OpenTelemetry
- 高级主题 - 测试、序列化、TypeScript 最佳实践、客户端发布、请求体解析、操场、生态系统
- 契约优先 - 契约优先开发、tRPC 迁移指南、与替代方案的比较
- 辅助工具 - Cookie 管理、签名、加密、频率限制、支持事件恢复的发布器
- NestJS - 使用装饰器、依赖注入和契约优先模式进行 NestJS 集成