From a56e94ba8ecb3ddadb582b51702624c8ca3f9e26 Mon Sep 17 00:00:00 2001 From: yyh <92089059+lyzno1@users.noreply.github.com> Date: Wed, 14 Jan 2026 21:13:14 +0800 Subject: [PATCH] feat: add .agent/skills symlink and orpc-contract-first skill (#30968) --- .agent/skills | 1 + .claude/skills/orpc-contract-first/SKILL.md | 46 +++++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 120000 .agent/skills create mode 100644 .claude/skills/orpc-contract-first/SKILL.md diff --git a/.agent/skills b/.agent/skills new file mode 120000 index 0000000000..454b8427cd --- /dev/null +++ b/.agent/skills @@ -0,0 +1 @@ +../.claude/skills \ No newline at end of file diff --git a/.claude/skills/orpc-contract-first/SKILL.md b/.claude/skills/orpc-contract-first/SKILL.md new file mode 100644 index 0000000000..4e3bfc7a37 --- /dev/null +++ b/.claude/skills/orpc-contract-first/SKILL.md @@ -0,0 +1,46 @@ +--- +name: orpc-contract-first +description: Guide for implementing oRPC contract-first API patterns in Dify frontend. Triggers when creating new API contracts, adding service endpoints, integrating TanStack Query with typed contracts, or migrating legacy service calls to oRPC. Use for all API layer work in web/contract and web/service directories. +--- + +# oRPC Contract-First Development + +## Project Structure + +``` +web/contract/ +├── base.ts # Base contract (inputStructure: 'detailed') +├── router.ts # Router composition & type exports +├── marketplace.ts # Marketplace contracts +└── console/ # Console contracts by domain + ├── system.ts + └── billing.ts +``` + +## Workflow + +1. **Create contract** in `web/contract/console/{domain}.ts` + - Import `base` from `../base` and `type` from `@orpc/contract` + - Define route with `path`, `method`, `input`, `output` + +2. **Register in router** at `web/contract/router.ts` + - Import directly from domain file (no barrel files) + - Nest by API prefix: `billing: { invoices, bindPartnerStack }` + +3. **Create hooks** in `web/service/use-{domain}.ts` + - Use `consoleQuery.{group}.{contract}.queryKey()` for query keys + - Use `consoleClient.{group}.{contract}()` for API calls + +## Key Rules + +- **Input structure**: Always use `{ params, query?, body? }` format +- **Path params**: Use `{paramName}` in path, match in `params` object +- **Router nesting**: Group by API prefix (e.g., `/billing/*` → `billing: {}`) +- **No barrel files**: Import directly from specific files +- **Types**: Import from `@/types/`, use `type()` helper + +## Type Export + +```typescript +export type ConsoleInputs = InferContractRouterInputs +```