Files
gh-djankies-claude-configs-…/skills/upgrading-to-prisma-6/references/migration-examples.md
2025-11-29 18:22:25 +08:00

3.9 KiB

Prisma 6 Migration Examples

Example 1: Complete Bytes Field Migration

Schema:

model Document {
  id      Int    @id @default(autoincrement())
  content Bytes
}

Before (Prisma 5):

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):

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):

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):

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):

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:

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):

model Task {
  id    Int     @id @default(autoincrement())
  async Boolean
  await String?
}

After (Prisma 6):

model Task {
  id        Int     @id @default(autoincrement())
  isAsync   Boolean @map("async")
  awaitMsg  String? @map("await")
}

Code Update:


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:

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:

ALTER TABLE "_CategoryToPost" DROP CONSTRAINT "_CategoryToPost_pkey";
ALTER TABLE "_CategoryToPost" ADD CONSTRAINT "_CategoryToPost_AB_pkey"
  PRIMARY KEY ("A", "B");

No code changes needed:

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.