Smithery Logo
MCPsSkillsDocsPricing
Login
Smithery Logo

Accelerating the Agent Economy

Resources

DocumentationPrivacy PolicySystem Status

Company

PricingAboutBlog

Connect

© 2026 Smithery. All rights reserved.

    neversight

    prisma-patterns

    neversight/prisma-patterns
    Coding
    2
    1 installs

    About

    SKILL.md

    Install

    Install via Skills CLI

    or add to your agent
    • Claude Code
      Claude Code
    • Codex
      Codex
    • OpenClaw
      OpenClaw
    • Cursor
      Cursor
    • Amp
      Amp
    • GitHub Copilot
      GitHub Copilot
    • Gemini CLI
      Gemini CLI
    • Kilo Code
      Kilo Code
    • Junie
      Junie
    • Replit
      Replit
    • Windsurf
      Windsurf
    • Cline
      Cline
    • Continue
      Continue
    • OpenCode
      OpenCode
    • OpenHands
      OpenHands
    • Roo Code
      Roo Code
    • Augment
      Augment
    • Goose
      Goose
    • Trae
      Trae
    • Zencoder
      Zencoder
    • Antigravity
      Antigravity
    ├─
    ├─
    └─

    About

    Prisma ORM patterns - use for database access in Next.js, schema design, migrations, transactions, and relations

    SKILL.md

    Prisma ORM Patterns

    Schema Definition

    // prisma/schema.prisma
    generator client {
      provider = "prisma-client-js"
    }
    
    datasource db {
      provider = "postgresql"
      url      = env("DATABASE_URL")
    }
    
    model User {
      id        String   @id @default(cuid())
      email     String   @unique
      name      String?
      createdAt DateTime @default(now()) @map("created_at")
      updatedAt DateTime @updatedAt @map("updated_at")
    
      environments Environment[]
      sessions     Session[]
    
      @@map("users")
    }
    
    model Environment {
      id          String            @id @default(cuid())
      name        String
      description String?
      status      EnvironmentStatus @default(PENDING)
      ownerId     String            @map("owner_id")
      createdAt   DateTime          @default(now()) @map("created_at")
      updatedAt   DateTime          @updatedAt @map("updated_at")
    
      owner User  @relation(fields: [ownerId], references: [id], onDelete: Cascade)
      tags  Tag[]
    
      @@unique([ownerId, name])
      @@index([status])
      @@index([createdAt(sort: Desc)])
      @@map("environments")
    }
    
    model Tag {
      id            String      @id @default(cuid())
      key           String
      value         String
      environmentId String      @map("environment_id")
      createdAt     DateTime    @default(now()) @map("created_at")
    
      environment Environment @relation(fields: [environmentId], references: [id], onDelete: Cascade)
    
      @@unique([environmentId, key])
      @@map("tags")
    }
    
    enum EnvironmentStatus {
      PENDING
      RUNNING
      STOPPED
      FAILED
    }
    

    Prisma Client Setup

    // lib/prisma.ts
    import { PrismaClient } from '@prisma/client'
    
    const globalForPrisma = globalThis as unknown as {
      prisma: PrismaClient | undefined
    }
    
    export const prisma = globalForPrisma.prisma ?? new PrismaClient({
      log: process.env.NODE_ENV === 'development'
        ? ['query', 'error', 'warn']
        : ['error'],
    })
    
    if (process.env.NODE_ENV !== 'production') {
      globalForPrisma.prisma = prisma
    }
    

    Basic CRUD Operations

    // Create
    const environment = await prisma.environment.create({
      data: {
        name: 'dev-env',
        description: 'Development environment',
        ownerId: userId,
      },
    })
    
    // Read
    const environment = await prisma.environment.findUnique({
      where: { id: envId },
    })
    
    const environments = await prisma.environment.findMany({
      where: { status: 'RUNNING' },
      orderBy: { createdAt: 'desc' },
      take: 10,
    })
    
    // Update
    const updated = await prisma.environment.update({
      where: { id: envId },
      data: { status: 'STOPPED' },
    })
    
    // Delete
    await prisma.environment.delete({
      where: { id: envId },
    })
    
    // Upsert
    const env = await prisma.environment.upsert({
      where: { id: envId },
      update: { status: 'RUNNING' },
      create: {
        name: 'new-env',
        ownerId: userId,
      },
    })
    

    Relations

    // Include relations
    const envWithOwner = await prisma.environment.findUnique({
      where: { id: envId },
      include: {
        owner: true,
        tags: true,
      },
    })
    
    // Select specific fields
    const envPartial = await prisma.environment.findUnique({
      where: { id: envId },
      select: {
        id: true,
        name: true,
        owner: {
          select: {
            name: true,
            email: true,
          },
        },
      },
    })
    
    // Nested create
    const envWithTags = await prisma.environment.create({
      data: {
        name: 'tagged-env',
        ownerId: userId,
        tags: {
          create: [
            { key: 'team', value: 'platform' },
            { key: 'tier', value: 'production' },
          ],
        },
      },
      include: { tags: true },
    })
    
    // Connect existing relation
    const env = await prisma.environment.create({
      data: {
        name: 'new-env',
        owner: {
          connect: { id: userId },
        },
      },
    })
    

    Filtering

    // Complex filters
    const environments = await prisma.environment.findMany({
      where: {
        AND: [
          { status: 'RUNNING' },
          {
            OR: [
              { name: { contains: 'prod', mode: 'insensitive' } },
              { tags: { some: { key: 'tier', value: 'production' } } },
            ],
          },
        ],
        createdAt: {
          gte: new Date('2024-01-01'),
        },
        owner: {
          email: { endsWith: '@jetbrains.com' },
        },
      },
    })
    
    // NOT filter
    const nonFailedEnvs = await prisma.environment.findMany({
      where: {
        NOT: { status: 'FAILED' },
      },
    })
    

    Pagination

    // Offset pagination
    async function getEnvironmentsPage(page: number, pageSize: number) {
      const [items, total] = await Promise.all([
        prisma.environment.findMany({
          skip: (page - 1) * pageSize,
          take: pageSize,
          orderBy: { createdAt: 'desc' },
        }),
        prisma.environment.count(),
      ])
    
      return {
        items,
        total,
        page,
        pageSize,
        totalPages: Math.ceil(total / pageSize),
      }
    }
    
    // Cursor pagination
    async function getEnvironmentsCursor(cursor?: string, take: number = 10) {
      const items = await prisma.environment.findMany({
        take: take + 1, // Fetch one extra to check if there's more
        ...(cursor && {
          cursor: { id: cursor },
          skip: 1, // Skip the cursor
        }),
        orderBy: { createdAt: 'desc' },
      })
    
      const hasMore = items.length > take
      const data = hasMore ? items.slice(0, -1) : items
    
      return {
        items: data,
        nextCursor: hasMore ? data[data.length - 1].id : null,
      }
    }
    

    Transactions

    // Interactive transaction
    const result = await prisma.$transaction(async (tx) => {
      // Create environment
      const env = await tx.environment.create({
        data: { name: 'new-env', ownerId: userId },
      })
    
      // Create associated tags
      await tx.tag.createMany({
        data: [
          { key: 'team', value: 'platform', environmentId: env.id },
          { key: 'cost-center', value: '12345', environmentId: env.id },
        ],
      })
    
      // Update user's environment count (if tracking)
      await tx.user.update({
        where: { id: userId },
        data: { environmentCount: { increment: 1 } },
      })
    
      return env
    })
    
    // Sequential transaction (batch)
    const [deletedEnvs, deletedTags] = await prisma.$transaction([
      prisma.environment.deleteMany({ where: { status: 'FAILED' } }),
      prisma.tag.deleteMany({ where: { environment: { status: 'FAILED' } } }),
    ])
    

    Aggregations

    // Count by status
    const statusCounts = await prisma.environment.groupBy({
      by: ['status'],
      _count: { status: true },
    })
    
    // Aggregate functions
    const stats = await prisma.environment.aggregate({
      _count: { id: true },
      _min: { createdAt: true },
      _max: { createdAt: true },
    })
    

    Raw Queries (When Needed)

    // Raw query
    const result = await prisma.$queryRaw<Environment[]>`
      SELECT * FROM environments
      WHERE status = ${status}
      AND created_at > NOW() - INTERVAL '7 days'
    `
    
    // Raw execute
    await prisma.$executeRaw`
      UPDATE environments
      SET status = 'STOPPED'
      WHERE status = 'RUNNING'
      AND updated_at < NOW() - INTERVAL '24 hours'
    `
    

    Migrations

    # Create migration
    npx prisma migrate dev --name add_environment_type
    
    # Apply migrations (production)
    npx prisma migrate deploy
    
    # Reset database (development)
    npx prisma migrate reset
    
    # Generate client
    npx prisma generate
    
    Recommended Servers
    Prisma
    Prisma
    Neon
    Neon
    ThinAir Data
    ThinAir Data
    Repository
    neversight/skills_feed