mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-06-30 19:00:57 +08:00
docs(skills): update Prisma and Zod API patterns for cross-version compatibility (#2336)
* docs(skills): update Prisma and Zod API patterns for cross-version compatibility - skills/prisma-patterns: show both adapter-based and direct PrismaClient initialization side-by-side; update import paths with conditional notes; rewrite version header to be release-agnostic - skills/backend-patterns: fix ZodError.errors -> ZodError.issues - skills/coding-standards: fix ZodError.errors -> ZodError.issues - skills/security-review: fix ZodError.errors -> ZodError.issues These API differences were discovered during implementation of a full-stack health assessment project. The updated code samples show both the new and old API forms so the skill remains useful regardless of which Prisma or Zod version is installed. Closes #2335 * fix(skills): revert Prisma client imports to '@prisma/client' The 'prisma' npm package is the CLI tool, not the runtime client. Using it as an import source would cause compile-time failures on all versions. '@prisma/client' remains the correct import source for the generated PrismaClient and Prisma namespace types. Found by Greptile during PR review.
This commit is contained in:
parent
8c75abf02e
commit
3a46c82b0c
@ -290,7 +290,7 @@ export function errorHandler(error: unknown, req: Request): Response {
|
||||
return NextResponse.json({
|
||||
success: false,
|
||||
error: 'Validation failed',
|
||||
details: error.errors
|
||||
details: error.issues
|
||||
}, { status: 400 })
|
||||
}
|
||||
|
||||
|
||||
@ -324,7 +324,7 @@ export async function POST(request: Request) {
|
||||
return NextResponse.json({
|
||||
success: false,
|
||||
error: 'Validation failed',
|
||||
details: error.errors
|
||||
details: error.issues
|
||||
}, { status: 400 })
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,15 +8,18 @@ metadata:
|
||||
# Prisma Patterns
|
||||
|
||||
Production patterns and non-obvious traps for Prisma ORM in TypeScript backends.
|
||||
Tested against Prisma 5.x and 6.x. Some behaviors differ from Prisma 4.
|
||||
|
||||
Check the Prisma version before applying version-specific patterns:
|
||||
|
||||
```bash
|
||||
npx prisma --version
|
||||
```
|
||||
|
||||
Prisma 5 introduced `relationJoins`, which can load relations via JOIN rather than separate queries depending on query strategy and configuration. The `omit` field modifier and `prisma.$extends` Client Extensions API were also added. Note: `relationJoins` can cause row explosion on large 1:N relations or deep nested `include` — benchmark both approaches when relations may return many rows per parent.
|
||||
> **Check your version before applying patterns.** The Prisma API surface has evolved across major releases:
|
||||
>
|
||||
> ```bash
|
||||
> npx prisma --version
|
||||
> ```
|
||||
>
|
||||
> Notable API differences across versions:
|
||||
> - `relationJoins` can load relations via JOIN rather than separate queries, but may cause row explosion on large 1:N relations or deep `include` — benchmark both approaches
|
||||
> - `omit` field modifier and `prisma.$extends` Client Extensions API were added
|
||||
> - **Newer installs**: the package may be named `prisma` instead of `@prisma/client`; `PrismaClient` may require a driver adapter (e.g. `@prisma/adapter-pg`); `datasource.url` may live in `prisma.config.ts` instead of `schema.prisma`
|
||||
> - CLI commands (`migrate dev`, `migrate deploy`, `generate`) are unchanged across versions
|
||||
|
||||
## When to Activate
|
||||
|
||||
@ -122,19 +125,35 @@ Each `PrismaClient` instance opens its own connection pool. Instantiate once.
|
||||
|
||||
```ts
|
||||
// lib/prisma.ts
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
|
||||
// Option A — adapter-based initialization (required by newer Prisma installs)
|
||||
import { PrismaClient } from '@prisma/client'; // or the generated client path for your setup
|
||||
import { PrismaPg } from '@prisma/adapter-pg';
|
||||
|
||||
function createPrismaClient() {
|
||||
const adapter = new PrismaPg({
|
||||
connectionString: process.env.DATABASE_URL!,
|
||||
});
|
||||
return new PrismaClient({
|
||||
adapter,
|
||||
log: process.env.NODE_ENV === 'development' ? ['query', 'error'] : ['error'],
|
||||
});
|
||||
}
|
||||
|
||||
const globalForPrisma = globalThis as unknown as { prisma?: PrismaClient };
|
||||
|
||||
export const prisma =
|
||||
globalForPrisma.prisma ??
|
||||
new PrismaClient({
|
||||
log: process.env.NODE_ENV === 'development' ? ['query', 'error'] : ['error'],
|
||||
});
|
||||
export const prisma = globalForPrisma.prisma ?? createPrismaClient();
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma;
|
||||
|
||||
// Option B — direct initialization (older installs, no adapter needed)
|
||||
// import { PrismaClient } from '@prisma/client';
|
||||
// export const prisma = globalForPrisma.prisma ?? new PrismaClient({ ... });
|
||||
```
|
||||
|
||||
Use Option A if your Prisma install requires an `adapter` argument in the `PrismaClient` constructor.
|
||||
Use Option B if `new PrismaClient()` works without arguments. Let the compiler tell you which is correct.
|
||||
|
||||
The `globalThis` pattern prevents duplicate instances during hot reload (Next.js, nodemon, ts-node-dev).
|
||||
|
||||
### N+1 Problem
|
||||
@ -192,7 +211,7 @@ await prisma.user.update({ where: { id }, data: { deletedAt: null } }); // resto
|
||||
### Error Handling
|
||||
|
||||
```ts
|
||||
import { Prisma } from '@prisma/client';
|
||||
import { Prisma } from '@prisma/client'; // or the generated client path for your setup
|
||||
|
||||
try {
|
||||
await prisma.user.create({ data: { email } });
|
||||
@ -223,9 +242,19 @@ DATABASE_URL="postgresql://user:pass@host/db?pgbouncer=true&connection_limit=1"
|
||||
```
|
||||
|
||||
```ts
|
||||
// Vercel, AWS Lambda, and similar serverless runtimes: cap pool to 1 per instance
|
||||
// connection_limit and pool_timeout are controlled via DATABASE_URL
|
||||
const prisma = new PrismaClient();
|
||||
// Vercel, AWS Lambda, and similar serverless runtimes:
|
||||
// cap pool to 1 per instance; connection_limit and pool_timeout controlled via DATABASE_URL
|
||||
|
||||
// Adapter-based setup (if your Prisma install requires an adapter):
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import { PrismaPg } from '@prisma/adapter-pg';
|
||||
|
||||
const prisma = new PrismaClient({
|
||||
adapter: new PrismaPg({ connectionString: process.env.DATABASE_URL }),
|
||||
});
|
||||
|
||||
// Direct setup (if your Prisma install does not require an adapter):
|
||||
// const prisma = new PrismaClient();
|
||||
```
|
||||
|
||||
## Anti-Patterns
|
||||
|
||||
@ -67,7 +67,7 @@ export async function createUser(input: unknown) {
|
||||
return await db.users.create(validated)
|
||||
} catch (error) {
|
||||
if (error instanceof z.ZodError) {
|
||||
return { success: false, errors: error.errors }
|
||||
return { success: false, errors: error.issues }
|
||||
}
|
||||
throw error
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user