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. 01oRPC による型安全な RPC エンドポイントの構築
  2. 02API への OpenAPI 対応の追加
  3. 03SSR でのプロシージャの直接呼び出し

インストール

コマンドをコピーしてターミナルで実行します。

$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 は、エンドツーエンドの型安全性と OpenAPI への準拠を両立する、型安全な RPC フレームワークです。プロシージャ、ルーター、ミドルウェア、コンテキストの注入、エラー処理、ファイルアップロード、ストリーミング(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。

コンテキスト

コンテキストには、ハンドラーの作成時に指定する 初期コンテキスト と、実行時にミドルウェアが注入する 実行コンテキスト の 2 種類があります。詳細は 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 }
  })

100 MB を超えるアップロードには、専用のアップロードソリューションを使用するか、ボディパーサーを拡張してください。

組み込みヘルパー

oRPC には、一般的なサーバータスク向けの組み込みヘルパーがあります。

  • Cookie:@orpc/server/helpers の getCookie、setCookie、deleteCookie
  • Cookie の署名:改ざん防止 Cookie のための sign、unsign
  • 暗号化:機密データ向けの encrypt、decrypt(PBKDF2 を使用した AES-GCM)
  • レート制限:Memory、Redis、Upstash、Cloudflare アダプターを備えた @orpc/experimental-ratelimit
  • イベントの公開:再開をサポートする分散 pub/sub 向けの @orpc/experimental-publisher

API と例の詳細は、references/helpers.md を参照してください。

主なルールと制約

  1. ハンドラーは必須です - プロシージャで必須のメソッドは .handler() だけです
  2. 出力スキーマを推奨します - TypeScript のパフォーマンス向上のため、.output() を明示的に指定してください
  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 とイベントイテレーターには非対応)。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 との統合

コメント