From 03c6b84a391295b04cc124a8c0215c9741824b91 Mon Sep 17 00:00:00 2001 From: imbytecat Date: Sun, 18 Jan 2026 03:51:48 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=20ORPC=20=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E5=AE=89=E5=85=A8=20RPC=20=E5=B1=82=E9=9B=86=E6=88=90?= =?UTF-8?q?=E6=8C=87=E5=8D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加 ORPC 类型安全 RPC 层的完整集成指南,包括合约定义、处理器实现、路由注册及在组件中使用的方法。 --- AGENTS.md | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 2 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 1f401b7..c8365a1 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -11,6 +11,7 @@ This document provides comprehensive guidelines for AI coding agents working in - **Database**: PostgreSQL with Drizzle ORM - **State Management**: TanStack Query - **Routing**: TanStack Router (file-based) +- **RPC**: ORPC (type-safe RPC with contract-first design) - **Build Tool**: Vite - **Linter/Formatter**: Biome @@ -212,9 +213,19 @@ src/ │ ├── schema/ # Drizzle schema definitions │ └── index.ts # Database instance ├── lib/ # Utility functions +├── orpc/ # ORPC (RPC layer) +│ ├── contracts/ # Contract definitions (input/output schemas) +│ ├── handlers/ # Server-side procedure implementations +│ ├── middlewares/ # Middleware (e.g., DB provider) +│ ├── contract.ts # Contract aggregation +│ ├── router.ts # Router composition +│ ├── server.ts # Server instance +│ ├── client.ts # Isomorphic client +│ └── types.ts # Type utilities ├── routes/ # TanStack Router file-based routes │ ├── __root.tsx # Root layout -│ └── index.tsx # Home page +│ ├── index.tsx # Home page +│ └── api/rpc.$.ts # ORPC HTTP endpoint ├── env.ts # Environment variable validation ├── index.ts # Application entry point ├── router.tsx # Router configuration @@ -261,7 +272,52 @@ const myServerFn = createServerFn({ method: 'POST' }) }) ``` +### Creating ORPC Procedures + +**Step 1: Define Contract** (`src/orpc/contracts/my-feature.ts`) +```typescript +import { oc } from '@orpc/contract' +import { z } from 'zod' + +export const myContract = { + get: oc.input(z.object({ id: z.uuid() })).output(mySchema), + create: oc.input(createSchema).output(mySchema), +} +``` + +**Step 2: Implement Handler** (`src/orpc/handlers/my-feature.ts`) +```typescript +import { os } from '@/orpc/server' +import { dbProvider } from '@/orpc/middlewares' + +export const get = os.myFeature.get + .use(dbProvider) + .handler(async ({ context, input }) => { + const item = await context.db.query.myTable.findFirst(...) + return item + }) +``` + +**Step 3: Register in Contract & Router** +```typescript +// src/orpc/contract.ts +export const contract = { + myFeature: myContract, +} + +// src/orpc/router.ts +import * as myFeature from './handlers/my-feature' +export const router = os.router({ myFeature }) +``` + +**Step 4: Use in Component** +```typescript +import { orpc } from '@/orpc' +const query = useSuspenseQuery(orpc.myFeature.get.queryOptions({ id })) +const mutation = useMutation(orpc.myFeature.create.mutationOptions()) +``` + --- -**Last Updated**: 2026-01-17 +**Last Updated**: 2026-01-18 **Project Version**: Based on package.json dependencies