Initial commit
This commit is contained in:
194
skills/upgrading-to-prisma-6/SKILL.md
Normal file
194
skills/upgrading-to-prisma-6/SKILL.md
Normal file
@@ -0,0 +1,194 @@
|
||||
---
|
||||
name: upgrading-to-prisma-6
|
||||
description: Migrate from Prisma 5 to Prisma 6 handling breaking changes including Buffer to Uint8Array, implicit m-n PK changes, NotFoundError to P2025, and reserved keywords. Use when upgrading Prisma, encountering Prisma 6 type errors, or migrating legacy code.
|
||||
allowed-tools: Read, Write, Edit, Grep, Glob
|
||||
version: 1.0.0
|
||||
---
|
||||
|
||||
# Prisma 6 Migration Guide
|
||||
|
||||
This skill guides you through upgrading from Prisma 5 to Prisma 6, handling all breaking changes systematically to prevent runtime failures and type errors.
|
||||
|
||||
---
|
||||
|
||||
<role>
|
||||
This skill teaches Claude how to migrate Prisma 5 codebases to Prisma 6 following the official migration guide, addressing breaking changes in Buffer API, implicit many-to-many relationships, error handling, and reserved keywords.
|
||||
</role>
|
||||
|
||||
<when-to-activate>
|
||||
This skill activates when:
|
||||
- User mentions "Prisma 6", "upgrade Prisma", "migrate to Prisma 6"
|
||||
- Encountering Prisma 6 type errors related to Bytes fields
|
||||
- Working with Prisma migrations or schema changes during upgrades
|
||||
- User reports NotFoundError issues after upgrading
|
||||
- Reserved keyword conflicts appear (`async`, `await`, `using`)
|
||||
</when-to-activate>
|
||||
|
||||
<overview>
|
||||
Prisma 6 introduces four critical breaking changes that require code updates:
|
||||
|
||||
1. **Buffer → Uint8Array**: Bytes fields now use Uint8Array instead of Buffer
|
||||
2. **Implicit m-n PKs**: Many-to-many join tables now use compound primary keys
|
||||
3. **NotFoundError → P2025**: Error class removed, use error code checking
|
||||
4. **Reserved Keywords**: `async`, `await`, `using` are now reserved model/field names
|
||||
|
||||
Attempting to use Prisma 6 without these updates causes type errors, runtime failures, and migration issues.
|
||||
</overview>
|
||||
|
||||
<workflow>
|
||||
## Migration Workflow
|
||||
|
||||
**Phase 1: Pre-Migration Assessment**
|
||||
|
||||
1. Identify all Bytes fields in schema
|
||||
- Use Grep to find `@db.ByteA`, `Bytes` field types
|
||||
- List all files using Buffer operations on Bytes fields
|
||||
|
||||
2. Find implicit many-to-many relationships
|
||||
- Search schema for relation fields without explicit join tables
|
||||
- Identify models with `@relation` without `relationName`
|
||||
|
||||
3. Locate NotFoundError usage
|
||||
- Grep for `NotFoundError` imports and usage
|
||||
- Find error handling that checks error class
|
||||
|
||||
4. Check for reserved keywords
|
||||
- Search schema for models/fields named `async`, `await`, `using`
|
||||
|
||||
**Phase 2: Schema Migration**
|
||||
|
||||
1. Update reserved keywords in schema
|
||||
- Rename any models/fields using reserved words
|
||||
- Update all references in application code
|
||||
|
||||
2. Generate migration for implicit m-n changes
|
||||
- Run `npx prisma migrate dev --name v6-implicit-mn-pks`
|
||||
- Review generated SQL for compound primary key changes
|
||||
|
||||
**Phase 3: Code Migration**
|
||||
|
||||
1. Update Buffer → Uint8Array conversions
|
||||
- Replace `Buffer.from()` with TextEncoder
|
||||
- Replace `.toString()` with TextDecoder
|
||||
- Update type annotations from Buffer to Uint8Array
|
||||
|
||||
2. Update NotFoundError handling
|
||||
- Replace error class checks with P2025 code checks
|
||||
- Use `isPrismaClientKnownRequestError` type guard
|
||||
|
||||
3. Test all changes
|
||||
- Run existing tests
|
||||
- Verify Bytes field operations
|
||||
- Confirm error handling works correctly
|
||||
|
||||
**Phase 4: Validation**
|
||||
|
||||
1. Run TypeScript compiler
|
||||
- Verify no type errors remain
|
||||
- Check all Buffer references resolved
|
||||
|
||||
2. Run database migrations
|
||||
- Apply migrations to test database
|
||||
- Verify compound PKs created correctly
|
||||
|
||||
3. Runtime testing
|
||||
- Test Bytes field read/write operations
|
||||
- Verify error handling catches not-found cases
|
||||
- Confirm implicit m-n queries work
|
||||
</workflow>
|
||||
|
||||
## Quick Reference
|
||||
|
||||
**Breaking Changes Summary:**
|
||||
|
||||
| Change | Before | After |
|
||||
|--------|--------|-------|
|
||||
| Buffer API | `Buffer.from()`, `.toString()` | `TextEncoder`, `TextDecoder` |
|
||||
| Error Handling | `error instanceof NotFoundError` | `error.code === 'P2025'` |
|
||||
| Implicit m-n PK | Auto-increment `id` | Compound PK `(A, B)` |
|
||||
| Reserved Words | `async`, `await`, `using` allowed | Must use `@map()` |
|
||||
|
||||
**Migration Command:**
|
||||
```bash
|
||||
npx prisma migrate dev --name v6-upgrade
|
||||
```
|
||||
|
||||
**Validation Commands:**
|
||||
```bash
|
||||
npx tsc --noEmit
|
||||
npx prisma migrate status
|
||||
npm test
|
||||
```
|
||||
|
||||
<constraints>
|
||||
## Migration Guidelines
|
||||
|
||||
**MUST:**
|
||||
- Backup production database before migration
|
||||
- Test migration in development/staging first
|
||||
- Review auto-generated migration SQL
|
||||
- Update all Buffer operations to TextEncoder/TextDecoder
|
||||
- Replace all NotFoundError checks with P2025 code checks
|
||||
- Run TypeScript compiler to verify no type errors
|
||||
|
||||
**SHOULD:**
|
||||
- Create helper functions for common error checks
|
||||
- Use `@map()` when renaming reserved keywords
|
||||
- Document breaking changes in commit messages
|
||||
- Update team documentation about Prisma 6 patterns
|
||||
|
||||
**NEVER:**
|
||||
- Run migrations directly in production without testing
|
||||
- Skip TypeScript compilation check
|
||||
- Leave Buffer references in code (causes type errors)
|
||||
- Use NotFoundError (removed in Prisma 6)
|
||||
- Use `async`, `await`, `using` as model/field names without `@map()`
|
||||
</constraints>
|
||||
|
||||
<validation>
|
||||
## Post-Migration Validation
|
||||
|
||||
After completing migration:
|
||||
|
||||
1. **TypeScript Compilation:**
|
||||
- Run: `npx tsc --noEmit`
|
||||
- Expected: Zero type errors
|
||||
- If fails: Check remaining Buffer references, NotFoundError usage
|
||||
|
||||
2. **Database Migration Status:**
|
||||
- Run: `npx prisma migrate status`
|
||||
- Expected: All migrations applied
|
||||
- If fails: Apply pending migrations with `npx prisma migrate deploy`
|
||||
|
||||
3. **Runtime Testing:**
|
||||
- Test Bytes field write/read cycle
|
||||
- Verify error handling catches P2025 correctly
|
||||
- Test implicit m-n relationship queries
|
||||
- Confirm no runtime errors in production-like environment
|
||||
|
||||
4. **Performance Check:**
|
||||
- Verify query performance unchanged
|
||||
- Check connection pool behavior
|
||||
- Monitor error rates in logs
|
||||
|
||||
5. **Rollback Readiness:**
|
||||
- Document rollback steps
|
||||
- Keep Prisma 5 migration snapshot
|
||||
- Test rollback procedure in staging
|
||||
</validation>
|
||||
|
||||
## References
|
||||
|
||||
For detailed migration guides and examples:
|
||||
|
||||
- **Breaking Changes Details**: See `references/breaking-changes.md` for complete API migration patterns, SQL examples, and edge cases
|
||||
- **Migration Examples**: See `references/migration-examples.md` for real-world migration scenarios with before/after code
|
||||
- **Migration Checklist**: See `references/migration-checklist.md` for step-by-step migration tasks
|
||||
- **Troubleshooting Guide**: See `references/troubleshooting.md` for common migration issues and solutions
|
||||
|
||||
For framework-specific migration patterns:
|
||||
- **Next.js Integration**: Consult Next.js plugin for App Router-specific Prisma 6 patterns
|
||||
- **Serverless Deployment**: See CLIENT-serverless-config skill for Prisma 6 + Lambda/Vercel
|
||||
|
||||
For error handling patterns:
|
||||
- **Error Code Reference**: See TRANSACTIONS-error-handling skill for comprehensive P-code handling
|
||||
173
skills/upgrading-to-prisma-6/references/breaking-changes.md
Normal file
173
skills/upgrading-to-prisma-6/references/breaking-changes.md
Normal file
@@ -0,0 +1,173 @@
|
||||
# Prisma 6 Breaking Changes - Detailed Reference
|
||||
|
||||
## 1. Buffer → Uint8Array
|
||||
|
||||
**Before (Prisma 5):**
|
||||
```typescript
|
||||
const user = await prisma.user.create({
|
||||
data: {
|
||||
name: 'Alice',
|
||||
data: Buffer.from('hello', 'utf-8')
|
||||
}
|
||||
})
|
||||
|
||||
const text = user.data.toString('utf-8')
|
||||
```
|
||||
|
||||
**After (Prisma 6):**
|
||||
```typescript
|
||||
const encoder = new TextEncoder()
|
||||
const decoder = new TextDecoder()
|
||||
|
||||
const user = await prisma.user.create({
|
||||
data: {
|
||||
name: 'Alice',
|
||||
data: encoder.encode('hello')
|
||||
}
|
||||
})
|
||||
|
||||
const text = decoder.decode(user.data)
|
||||
```
|
||||
|
||||
**Type Changes:**
|
||||
- Schema `Bytes` type now maps to `Uint8Array` instead of `Buffer`
|
||||
- All database binary data returned as `Uint8Array`
|
||||
- `Buffer` methods no longer available on Bytes fields
|
||||
|
||||
**Migration Steps:**
|
||||
1. Find all Buffer operations: `grep -r "Buffer.from\|\.toString(" --include="*.ts" --include="*.js"`
|
||||
2. Replace with TextEncoder/TextDecoder
|
||||
3. Update type annotations: `Buffer` → `Uint8Array`
|
||||
|
||||
## 2. Implicit Many-to-Many Primary Keys
|
||||
|
||||
**Before (Prisma 5):**
|
||||
Implicit m-n join tables had auto-generated integer primary keys.
|
||||
|
||||
**After (Prisma 6):**
|
||||
Implicit m-n join tables use compound primary keys based on foreign keys.
|
||||
|
||||
**Example Schema:**
|
||||
```prisma
|
||||
model Post {
|
||||
id Int @id @default(autoincrement())
|
||||
categories Category[]
|
||||
}
|
||||
|
||||
model Category {
|
||||
id Int @id @default(autoincrement())
|
||||
posts Post[]
|
||||
}
|
||||
```
|
||||
|
||||
**Migration Impact:**
|
||||
- Prisma generates `_CategoryToPost` join table
|
||||
- **Prisma 5**: PK was auto-increment `id`
|
||||
- **Prisma 6**: PK is compound `(A, B)` where A/B are foreign keys
|
||||
|
||||
**Migration:**
|
||||
```sql
|
||||
ALTER TABLE "_CategoryToPost" DROP CONSTRAINT "_CategoryToPost_pkey";
|
||||
ALTER TABLE "_CategoryToPost" ADD CONSTRAINT "_CategoryToPost_AB_pkey" PRIMARY KEY ("A", "B");
|
||||
```
|
||||
|
||||
This migration is auto-generated when running `prisma migrate dev` after upgrading.
|
||||
|
||||
**Action Required:**
|
||||
- Run migration in development
|
||||
- Review generated SQL before production deploy
|
||||
- No code changes needed (Prisma Client handles internally)
|
||||
|
||||
## 3. NotFoundError → P2025 Error Code
|
||||
|
||||
**Before (Prisma 5):**
|
||||
```typescript
|
||||
import { PrismaClient, NotFoundError } from '@prisma/client'
|
||||
|
||||
try {
|
||||
const user = await prisma.user.delete({
|
||||
where: { id: 999 }
|
||||
})
|
||||
} catch (error) {
|
||||
if (error instanceof NotFoundError) {
|
||||
console.log('User not found')
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**After (Prisma 6):**
|
||||
```typescript
|
||||
import { PrismaClient, Prisma } from '@prisma/client'
|
||||
|
||||
try {
|
||||
const user = await prisma.user.delete({
|
||||
where: { id: 999 }
|
||||
})
|
||||
} catch (error) {
|
||||
if (error instanceof Prisma.PrismaClientKnownRequestError) {
|
||||
if (error.code === 'P2025') {
|
||||
console.log('User not found')
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Type Guard Pattern:**
|
||||
```typescript
|
||||
function isNotFoundError(error: unknown): boolean {
|
||||
return (
|
||||
error instanceof Prisma.PrismaClientKnownRequestError &&
|
||||
error.code === 'P2025'
|
||||
)
|
||||
}
|
||||
|
||||
try {
|
||||
const user = await prisma.user.delete({ where: { id: 999 } })
|
||||
} catch (error) {
|
||||
if (isNotFoundError(error)) {
|
||||
console.log('User not found')
|
||||
}
|
||||
throw error
|
||||
}
|
||||
```
|
||||
|
||||
**Migration Steps:**
|
||||
1. Find all NotFoundError usage: `grep -r "NotFoundError" --include="*.ts"`
|
||||
2. Remove NotFoundError imports
|
||||
3. Replace error class checks with P2025 code checks
|
||||
4. Use `Prisma.PrismaClientKnownRequestError` type guard
|
||||
|
||||
## 4. Reserved Keywords
|
||||
|
||||
**Breaking Change:**
|
||||
The following field/model names are now reserved:
|
||||
- `async`
|
||||
- `await`
|
||||
- `using`
|
||||
|
||||
**Before (Prisma 5):**
|
||||
```prisma
|
||||
model Task {
|
||||
id Int @id @default(autoincrement())
|
||||
async Boolean
|
||||
}
|
||||
```
|
||||
|
||||
**After (Prisma 6):**
|
||||
```prisma
|
||||
model Task {
|
||||
id Int @id @default(autoincrement())
|
||||
isAsync Boolean @map("async")
|
||||
}
|
||||
```
|
||||
|
||||
**Migration Steps:**
|
||||
1. Find reserved keywords in schema: `grep -E "^\s*(async|await|using)\s" schema.prisma`
|
||||
2. Rename fields/models with descriptive alternatives
|
||||
3. Use `@map()` to maintain database column names
|
||||
4. Update all application code references
|
||||
|
||||
**Recommended Renames:**
|
||||
- `async` → `isAsync`, `asyncMode`, `asynchronous`
|
||||
- `await` → `awaitStatus`, `pending`, `waitingFor`
|
||||
- `using` → `inUse`, `isActive`, `usage`
|
||||
@@ -0,0 +1,72 @@
|
||||
# Prisma 6 Migration Checklist
|
||||
|
||||
## Pre-Migration
|
||||
|
||||
- [ ] Backup production database
|
||||
- [ ] Create feature branch for migration
|
||||
- [ ] Run existing tests to establish baseline
|
||||
- [ ] Document current Prisma version
|
||||
|
||||
## Schema Assessment
|
||||
|
||||
- [ ] Search for Bytes fields: `grep "Bytes" prisma/schema.prisma`
|
||||
- [ ] Search for implicit m-n relations (no explicit join table)
|
||||
- [ ] Search for reserved keywords: `grep -E "^\s*(async|await|using)\s" prisma/schema.prisma`
|
||||
- [ ] List all models and relations
|
||||
|
||||
## Code Assessment
|
||||
|
||||
- [ ] Find Buffer usage: `grep -r "Buffer\\.from\\|Buffer\\.alloc" --include="*.ts"`
|
||||
- [ ] Find toString on Bytes: `grep -r "\\.toString(" --include="*.ts"`
|
||||
- [ ] Find NotFoundError: `grep -r "NotFoundError" --include="*.ts"`
|
||||
- [ ] Document all locations requiring changes
|
||||
|
||||
## Update Dependencies
|
||||
|
||||
- [ ] Update package.json: `npm install prisma@6 @prisma/client@6`
|
||||
- [ ] Regenerate client: `npx prisma generate`
|
||||
- [ ] Verify TypeScript errors appear (expected)
|
||||
|
||||
## Schema Migration
|
||||
|
||||
- [ ] Rename any reserved keyword fields/models
|
||||
- [ ] Add `@map()` to maintain database compatibility
|
||||
- [ ] Run `npx prisma migrate dev --name v6-upgrade`
|
||||
- [ ] Review generated migration SQL
|
||||
- [ ] Test migration on development database
|
||||
|
||||
## Code Updates: Buffer → Uint8Array
|
||||
|
||||
- [ ] Create TextEncoder/TextDecoder instances
|
||||
- [ ] Replace `Buffer.from(str, 'utf-8')` with `encoder.encode(str)`
|
||||
- [ ] Replace `buffer.toString('utf-8')` with `decoder.decode(uint8array)`
|
||||
- [ ] Update type annotations: `Buffer` → `Uint8Array`
|
||||
- [ ] Handle edge cases (binary data, non-UTF8 encodings)
|
||||
|
||||
## Code Updates: NotFoundError → P2025
|
||||
|
||||
- [ ] Remove `NotFoundError` imports
|
||||
- [ ] Replace `error instanceof NotFoundError` with P2025 checks
|
||||
- [ ] Import `Prisma` from '@prisma/client'
|
||||
- [ ] Use `Prisma.PrismaClientKnownRequestError` type guard
|
||||
- [ ] Create helper functions for common error checks
|
||||
|
||||
## Testing
|
||||
|
||||
- [ ] Run TypeScript compiler: `npx tsc --noEmit`
|
||||
- [ ] Fix any remaining type errors
|
||||
- [ ] Run unit tests
|
||||
- [ ] Run integration tests
|
||||
- [ ] Test Bytes field operations manually
|
||||
- [ ] Test not-found error handling
|
||||
- [ ] Test implicit m-n queries
|
||||
|
||||
## Production Deployment
|
||||
|
||||
- [ ] Review migration SQL one final time
|
||||
- [ ] Plan maintenance window if needed
|
||||
- [ ] Deploy migration: `npx prisma migrate deploy`
|
||||
- [ ] Deploy application code
|
||||
- [ ] Monitor error logs for issues
|
||||
- [ ] Verify Bytes operations work correctly
|
||||
- [ ] Rollback plan ready if needed
|
||||
193
skills/upgrading-to-prisma-6/references/migration-examples.md
Normal file
193
skills/upgrading-to-prisma-6/references/migration-examples.md
Normal file
@@ -0,0 +1,193 @@
|
||||
# Prisma 6 Migration Examples
|
||||
|
||||
## Example 1: Complete Bytes Field Migration
|
||||
|
||||
**Schema:**
|
||||
```prisma
|
||||
model Document {
|
||||
id Int @id @default(autoincrement())
|
||||
content Bytes
|
||||
}
|
||||
```
|
||||
|
||||
**Before (Prisma 5):**
|
||||
```typescript
|
||||
const doc = await prisma.document.create({
|
||||
data: {
|
||||
content: Buffer.from('Important document content', 'utf-8')
|
||||
}
|
||||
})
|
||||
|
||||
console.log(doc.content.toString('utf-8'))
|
||||
```
|
||||
|
||||
**After (Prisma 6):**
|
||||
```typescript
|
||||
const encoder = new TextEncoder()
|
||||
const decoder = new TextDecoder()
|
||||
|
||||
const doc = await prisma.document.create({
|
||||
data: {
|
||||
content: encoder.encode('Important document content')
|
||||
}
|
||||
})
|
||||
|
||||
console.log(decoder.decode(doc.content))
|
||||
```
|
||||
|
||||
**Binary Data (non-text):**
|
||||
```typescript
|
||||
const binaryData = new Uint8Array([0x48, 0x65, 0x6c, 0x6c, 0x6f])
|
||||
|
||||
const doc = await prisma.document.create({
|
||||
data: {
|
||||
content: binaryData
|
||||
}
|
||||
})
|
||||
|
||||
const retrieved = await prisma.document.findUnique({ where: { id: doc.id } })
|
||||
console.log(retrieved.content)
|
||||
```
|
||||
|
||||
## Example 2: NotFoundError Migration
|
||||
|
||||
**Before (Prisma 5):**
|
||||
```typescript
|
||||
import { PrismaClient, NotFoundError } from '@prisma/client'
|
||||
|
||||
async function deleteUser(id: number) {
|
||||
try {
|
||||
const user = await prisma.user.delete({ where: { id } })
|
||||
return { success: true, user }
|
||||
} catch (error) {
|
||||
if (error instanceof NotFoundError) {
|
||||
return { success: false, error: 'User not found' }
|
||||
}
|
||||
throw error
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**After (Prisma 6):**
|
||||
```typescript
|
||||
import { PrismaClient, Prisma } from '@prisma/client'
|
||||
|
||||
async function deleteUser(id: number) {
|
||||
try {
|
||||
const user = await prisma.user.delete({ where: { id } })
|
||||
return { success: true, user }
|
||||
} catch (error) {
|
||||
if (error instanceof Prisma.PrismaClientKnownRequestError) {
|
||||
if (error.code === 'P2025') {
|
||||
return { success: false, error: 'User not found' }
|
||||
}
|
||||
}
|
||||
throw error
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Reusable Helper:**
|
||||
```typescript
|
||||
import { Prisma } from '@prisma/client'
|
||||
|
||||
export function isPrismaNotFoundError(
|
||||
error: unknown
|
||||
): error is Prisma.PrismaClientKnownRequestError {
|
||||
return (
|
||||
error instanceof Prisma.PrismaClientKnownRequestError &&
|
||||
error.code === 'P2025'
|
||||
)
|
||||
}
|
||||
|
||||
async function deleteUser(id: number) {
|
||||
try {
|
||||
const user = await prisma.user.delete({ where: { id } })
|
||||
return { success: true, user }
|
||||
} catch (error) {
|
||||
if (isPrismaNotFoundError(error)) {
|
||||
return { success: false, error: 'User not found' }
|
||||
}
|
||||
throw error
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Example 3: Reserved Keyword Migration
|
||||
|
||||
**Before (Prisma 5):**
|
||||
```prisma
|
||||
model Task {
|
||||
id Int @id @default(autoincrement())
|
||||
async Boolean
|
||||
await String?
|
||||
}
|
||||
```
|
||||
|
||||
**After (Prisma 6):**
|
||||
```prisma
|
||||
model Task {
|
||||
id Int @id @default(autoincrement())
|
||||
isAsync Boolean @map("async")
|
||||
awaitMsg String? @map("await")
|
||||
}
|
||||
```
|
||||
|
||||
**Code Update:**
|
||||
```typescript
|
||||
|
||||
const task = await prisma.task.create({
|
||||
data: {
|
||||
isAsync: true,
|
||||
awaitMsg: 'Waiting for completion'
|
||||
}
|
||||
})
|
||||
|
||||
console.log(task.isAsync)
|
||||
console.log(task.awaitMsg)
|
||||
```
|
||||
|
||||
**Database columns remain unchanged** (`async`, `await`), but TypeScript code uses new names.
|
||||
|
||||
## Example 4: Implicit Many-to-Many Migration
|
||||
|
||||
**Schema:**
|
||||
```prisma
|
||||
model Post {
|
||||
id Int @id @default(autoincrement())
|
||||
title String
|
||||
categories Category[]
|
||||
}
|
||||
|
||||
model Category {
|
||||
id Int @id @default(autoincrement())
|
||||
name String
|
||||
posts Post[]
|
||||
}
|
||||
```
|
||||
|
||||
**Auto-Generated Migration:**
|
||||
```sql
|
||||
ALTER TABLE "_CategoryToPost" DROP CONSTRAINT "_CategoryToPost_pkey";
|
||||
ALTER TABLE "_CategoryToPost" ADD CONSTRAINT "_CategoryToPost_AB_pkey"
|
||||
PRIMARY KEY ("A", "B");
|
||||
```
|
||||
|
||||
**No code changes needed**:
|
||||
```typescript
|
||||
const post = await prisma.post.create({
|
||||
data: {
|
||||
title: 'Hello World',
|
||||
categories: {
|
||||
connect: [{ id: 1 }, { id: 2 }]
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const postWithCategories = await prisma.post.findUnique({
|
||||
where: { id: post.id },
|
||||
include: { categories: true }
|
||||
})
|
||||
```
|
||||
|
||||
**Migration runs automatically** when you run `npx prisma migrate dev` after upgrading to Prisma 6.
|
||||
45
skills/upgrading-to-prisma-6/references/troubleshooting.md
Normal file
45
skills/upgrading-to-prisma-6/references/troubleshooting.md
Normal file
@@ -0,0 +1,45 @@
|
||||
# Prisma 6 Migration Troubleshooting
|
||||
|
||||
## Issue: Type error on Bytes field
|
||||
|
||||
**Error:**
|
||||
```
|
||||
Type 'Buffer' is not assignable to type 'Uint8Array'
|
||||
```
|
||||
|
||||
**Solution:**
|
||||
Replace Buffer operations with TextEncoder/TextDecoder or use Uint8Array directly.
|
||||
|
||||
## Issue: Migration fails with duplicate key
|
||||
|
||||
**Error:**
|
||||
```
|
||||
ERROR: duplicate key value violates unique constraint "_CategoryToPost_AB_unique"
|
||||
```
|
||||
|
||||
**Solution:**
|
||||
Implicit m-n tables may have duplicate entries. Clean data before migration:
|
||||
```sql
|
||||
DELETE FROM "_CategoryToPost" a USING "_CategoryToPost" b
|
||||
WHERE a.ctid < b.ctid AND a."A" = b."A" AND a."B" = b."B";
|
||||
```
|
||||
|
||||
## Issue: NotFoundError import fails
|
||||
|
||||
**Error:**
|
||||
```
|
||||
Module '"@prisma/client"' has no exported member 'NotFoundError'
|
||||
```
|
||||
|
||||
**Solution:**
|
||||
Remove NotFoundError import, use P2025 error code checking instead.
|
||||
|
||||
## Issue: Reserved keyword compilation error
|
||||
|
||||
**Error:**
|
||||
```
|
||||
'async' is a reserved word
|
||||
```
|
||||
|
||||
**Solution:**
|
||||
Rename field in schema with `@map()` to preserve database column name.
|
||||
Reference in New Issue
Block a user