mcpField
O
orpc-guide

orpc-guide

github.com/vcode-sh开发19187 次安装35 周前更新
代码仓库

关于 orpc-guide

orpc-guide 面向使用 oRPC 的 TypeScript 开发者,介绍框架的核心用法。内容涵盖类型安全的过程与客户端、OpenAPI 支持及多种服务端模式。

主要功能

  1. 01过程与路由器配置
  2. 02中间件、上下文与错误处理
  3. 03OpenAPI 生成与处理器
  4. 04HTTP、WebSocket 等客户端
  5. 05流式传输与文件处理

适用场景

  1. 01使用 oRPC 构建类型安全的 RPC 端点
  2. 02为 API 添加 OpenAPI 支持
  3. 03在 SSR 中直接调用过程

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/vcode-sh/vibe-tools --skill orpc-guide

安装后在 Claude Code 中输入/orpc-guide确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
adapters.md
advanced.md
api-reference.md
contract-first.md
helpers.md
integrations.md
nestjs.md
openapi.md
plugins.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。

关键规则和限制

  1. 必须提供处理程序 - .handler() 是过程唯一必需的方法
  2. 建议指定输出架构 - 显式指定 .output() 可提升 TypeScript 性能
  3. 中间件去重 - oRPC 会自动去重开头的中间件;手动去重时请使用上下文守卫
  4. 错误数据是公开的 - 切勿在 ORPCError.data 中放入敏感信息
  5. 请求体解析器冲突 - 在 oRPC 中间件之后注册框架请求体解析器(Express、Fastify、Elysia)
  6. RPCHandler 与 OpenAPIHandler - RPCHandler 使用专有协议(仅供 RPCLink 使用);OpenAPIHandler 与 REST/OpenAPI 兼容
  7. 延迟加载路由器 - 使用 os.lazy(() => import('./module')) 进行代码拆分;使用独立的 lazy() 可加快类型推断
  8. SSE 自动重连 - 标准 SSE 客户端会自动重连;使用 lastEventId 恢复流
  9. 文件限制 - 不支持分块上传/可恢复上传;AsyncIteratorObject 不支持 File/Blob
  10. 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_REQUEST400输入验证失败
UNAUTHORIZED401缺少身份验证信息或身份验证无效
FORBIDDEN403权限不足
NOT_FOUND404未找到资源
TIMEOUT408请求超时
TOO_MANY_REQUESTS429请求频率受限
INTERNAL_SERVER_ERROR500未处理的错误

非 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 集成

评论

支持 Markdown