Added AI skills
This commit is contained in:
129
.agents/skills/zod/references/parse-avoid-double-validation.md
Normal file
129
.agents/skills/zod/references/parse-avoid-double-validation.md
Normal file
@@ -0,0 +1,129 @@
|
||||
---
|
||||
title: Avoid Double Validation
|
||||
impact: HIGH
|
||||
impactDescription: Parsing the same data twice wastes CPU cycles; in hot paths this adds measurable latency
|
||||
tags: parse, performance, optimization, architecture
|
||||
---
|
||||
|
||||
## Avoid Double Validation
|
||||
|
||||
Once data is validated by Zod, trust the result. Re-validating the same data in multiple layers doubles CPU usage and adds latency. Pass the typed result through your application instead.
|
||||
|
||||
**Incorrect (validating at every layer):**
|
||||
|
||||
```typescript
|
||||
import { z } from 'zod'
|
||||
|
||||
const userSchema = z.object({
|
||||
id: z.string().uuid(),
|
||||
email: z.string().email(),
|
||||
name: z.string(),
|
||||
})
|
||||
|
||||
// Controller validates
|
||||
export async function POST(req: NextRequest) {
|
||||
const body = await req.json()
|
||||
const user = userSchema.parse(body) // First parse
|
||||
return await userService.create(user)
|
||||
}
|
||||
|
||||
// Service validates again
|
||||
const userService = {
|
||||
async create(data: unknown) {
|
||||
const user = userSchema.parse(data) // Second parse - redundant
|
||||
return await userRepository.insert(user)
|
||||
}
|
||||
}
|
||||
|
||||
// Repository validates again
|
||||
const userRepository = {
|
||||
async insert(data: unknown) {
|
||||
const user = userSchema.parse(data) // Third parse - wasteful
|
||||
return await db.users.create({ data: user })
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Correct (validate once, pass typed data):**
|
||||
|
||||
```typescript
|
||||
import { z } from 'zod'
|
||||
|
||||
const userSchema = z.object({
|
||||
id: z.string().uuid(),
|
||||
email: z.string().email(),
|
||||
name: z.string(),
|
||||
})
|
||||
|
||||
type User = z.infer<typeof userSchema>
|
||||
|
||||
// Controller validates at boundary
|
||||
export async function POST(req: NextRequest) {
|
||||
const body = await req.json()
|
||||
|
||||
const result = userSchema.safeParse(body)
|
||||
if (!result.success) {
|
||||
return NextResponse.json({ errors: result.error.issues }, { status: 400 })
|
||||
}
|
||||
|
||||
// Pass validated, typed data
|
||||
return await userService.create(result.data)
|
||||
}
|
||||
|
||||
// Service receives typed data, no re-validation needed
|
||||
const userService = {
|
||||
async create(user: User) {
|
||||
// user is guaranteed to match schema
|
||||
return await userRepository.insert(user)
|
||||
}
|
||||
}
|
||||
|
||||
// Repository receives typed data
|
||||
const userRepository = {
|
||||
async insert(user: User) {
|
||||
return await db.users.create({ data: user })
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**When you might validate at multiple layers:**
|
||||
|
||||
```typescript
|
||||
// Different schemas for different layers
|
||||
const apiUserSchema = z.object({
|
||||
email: z.string().email(),
|
||||
password: z.string().min(8), // Only in API layer
|
||||
})
|
||||
|
||||
const dbUserSchema = z.object({
|
||||
id: z.string().uuid(),
|
||||
email: z.string().email(),
|
||||
passwordHash: z.string(), // Transformed before storage
|
||||
})
|
||||
|
||||
// API validates input format
|
||||
export async function POST(req: NextRequest) {
|
||||
const input = apiUserSchema.parse(await req.json())
|
||||
const user = await userService.create(input)
|
||||
return NextResponse.json(user)
|
||||
}
|
||||
|
||||
// Service transforms and validates for storage
|
||||
const userService = {
|
||||
async create(input: z.infer<typeof apiUserSchema>) {
|
||||
const dbUser = dbUserSchema.parse({
|
||||
id: crypto.randomUUID(),
|
||||
email: input.email,
|
||||
passwordHash: await hash(input.password),
|
||||
})
|
||||
return await userRepository.insert(dbUser)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**When NOT to use this pattern:**
|
||||
- When schemas differ between layers (API vs DB shape)
|
||||
- When data crosses trust boundaries (external service response)
|
||||
- During development when debugging data flow
|
||||
|
||||
Reference: [Zod Performance](https://zod.dev/v4#performance)
|
||||
Reference in New Issue
Block a user