docs: extend all 18 AGENTS.md files with comprehensive context, code examples, and recipes
This commit is contained in:
@@ -1,17 +1,144 @@
|
||||
# @repo/api — tRPC Router Definitions
|
||||
# @repo/api -- tRPC v11 Router Definitions
|
||||
|
||||
tRPC routers that call controllers from `@repo/core`. Each procedure validates input and delegates to a controller.
|
||||
## Purpose
|
||||
|
||||
## Rules
|
||||
This package defines all tRPC v11 routers for the monorepo. Each router validates input with Zod and delegates execution to controllers in `@repo/core`. Routers are the **only** entry point for client-side RPC calls. They contain zero business logic.
|
||||
|
||||
- NEVER put business logic in routers — delegate to controllers
|
||||
- Input validation uses Zod schemas
|
||||
- Each domain gets its own router file
|
||||
## Hard Rules
|
||||
|
||||
## Adding a New tRPC Router
|
||||
- **NEVER** put business logic in routers -- always delegate to a controller from `@repo/core`
|
||||
- **NEVER** import from `@repo/core/infrastructure` or any `apps/*` package
|
||||
- Input validation uses Zod schemas inline on each procedure
|
||||
- Each domain gets its own `{domain}.router.ts` file
|
||||
- Use `.query()` for reads (GET-like), `.mutation()` for writes (POST/PUT/DELETE-like)
|
||||
- All procedures call exactly one controller function from `@repo/core`
|
||||
|
||||
1. Create `src/router/{domain}.router.ts`
|
||||
2. Import `router` and `publicProcedure` from `../trpc.js`
|
||||
3. Define procedures (`.query()` for reads, `.mutation()` for writes)
|
||||
4. Each procedure calls a controller from `@repo/core`
|
||||
5. Add router to root `appRouter` in `src/router/index.ts`
|
||||
## File Structure
|
||||
|
||||
```
|
||||
packages/api/
|
||||
src/
|
||||
trpc.ts # tRPC initialization, exports router + publicProcedure
|
||||
router/
|
||||
index.ts # appRouter composition, exports AppRouter type
|
||||
auth.router.ts # Auth domain: signIn, signUp, signOut
|
||||
content.router.ts # Content domain: listArticles, createArticle
|
||||
index.ts # Package entry: re-exports appRouter + AppRouter type
|
||||
package.json
|
||||
AGENTS.md
|
||||
```
|
||||
|
||||
## How Procedures Map to Controllers
|
||||
|
||||
| Procedure type | HTTP equivalent | When to use | Example |
|
||||
|---|---|---|---|
|
||||
| `.query()` | GET | Fetching/reading data | `content.listArticles` |
|
||||
| `.mutation()` | POST/PATCH/DELETE | Creating, updating, deleting data | `auth.signIn`, `content.createArticle` |
|
||||
|
||||
Every procedure follows the same pattern:
|
||||
|
||||
```typescript
|
||||
myProcedure: publicProcedure
|
||||
.input(z.object({ /* Zod schema */ }))
|
||||
.query(async ({ input }) => { // or .mutation()
|
||||
return await myController(input); // delegate to @repo/core controller
|
||||
}),
|
||||
```
|
||||
|
||||
## Existing Routers
|
||||
|
||||
### auth.router.ts
|
||||
|
||||
| Procedure | Type | Input | Controller |
|
||||
|---|---|---|---|
|
||||
| `signIn` | mutation | `{ username: string, password: string }` | `signInController` |
|
||||
| `signUp` | mutation | `{ username: string, password: string, confirmPassword: string }` | `signUpController` |
|
||||
| `signOut` | mutation | `{ sessionId: string }` | `signOutController` |
|
||||
|
||||
### content.router.ts
|
||||
|
||||
| Procedure | Type | Input | Controller |
|
||||
|---|---|---|---|
|
||||
| `listArticles` | query | `{ status?, authorId?, limit?, offset? }` (optional) | `getArticlesController` |
|
||||
| `createArticle` | mutation | `{ title: string, content: string, authorId: string, slug?: string }` | `createArticleController` |
|
||||
|
||||
## Recipe: Adding a New tRPC Router
|
||||
|
||||
This example adds a `comments` domain router with `listComments` (query) and `createComment` (mutation).
|
||||
|
||||
### Step 1: Create the router file
|
||||
|
||||
Create `src/router/comments.router.ts`:
|
||||
|
||||
```typescript
|
||||
import { z } from "zod";
|
||||
import { router, publicProcedure } from "../trpc";
|
||||
import {
|
||||
getCommentsController,
|
||||
createCommentController,
|
||||
} from "@repo/core";
|
||||
|
||||
export const commentsRouter = router({
|
||||
listComments: publicProcedure
|
||||
.input(
|
||||
z
|
||||
.object({
|
||||
articleId: z.string(),
|
||||
limit: z.number().optional(),
|
||||
offset: z.number().optional(),
|
||||
})
|
||||
)
|
||||
.query(async ({ input }) => {
|
||||
return await getCommentsController(input);
|
||||
}),
|
||||
|
||||
createComment: publicProcedure
|
||||
.input(
|
||||
z.object({
|
||||
articleId: z.string(),
|
||||
authorId: z.string(),
|
||||
body: z.string().min(1).max(2000),
|
||||
})
|
||||
)
|
||||
.mutation(async ({ input }) => {
|
||||
return await createCommentController(input);
|
||||
}),
|
||||
});
|
||||
```
|
||||
|
||||
### Step 2: Register in the appRouter
|
||||
|
||||
Edit `src/router/index.ts`:
|
||||
|
||||
```typescript
|
||||
import { router } from "../trpc";
|
||||
import { authRouter } from "./auth.router";
|
||||
import { contentRouter } from "./content.router";
|
||||
import { commentsRouter } from "./comments.router"; // <-- add import
|
||||
|
||||
export const appRouter = router({
|
||||
auth: authRouter,
|
||||
content: contentRouter,
|
||||
comments: commentsRouter, // <-- register here
|
||||
});
|
||||
|
||||
export type AppRouter = typeof appRouter;
|
||||
```
|
||||
|
||||
### Step 3: Verify
|
||||
|
||||
The `AppRouter` type is automatically inferred. Any app using `@repo/api-client` will immediately see `trpc.comments.listComments.useQuery(...)` and `trpc.comments.createComment.useMutation(...)` with full type safety -- no code generation step needed.
|
||||
|
||||
## Dependencies
|
||||
|
||||
| Dependency | Purpose |
|
||||
|---|---|
|
||||
| `@repo/core` | Controllers that contain business logic |
|
||||
| `@trpc/server` | tRPC v11 server-side primitives |
|
||||
| `zod` | Runtime input validation schemas |
|
||||
|
||||
## Cross-References
|
||||
|
||||
- **Controllers live in:** `packages/core/src/interface-adapters/controllers/` -- see `packages/core/AGENTS.md`
|
||||
- **Client consumption:** `packages/api-client/` -- see `packages/api-client/AGENTS.md`
|
||||
- **HTTP endpoint:** `apps/web-next/src/app/api/trpc/[trpc]/route.ts` uses the fetch adapter to serve `appRouter`
|
||||
|
||||
Reference in New Issue
Block a user