home / skills / doanchienthangdev / omgkit / prisma

This skill helps you build robust database layers with Prisma by guiding schema design, migrations, and type-safe queries.

npx playbooks add skill doanchienthangdev/omgkit --skill prisma

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
3.6 KB
---
name: Developing with Prisma
description: The agent implements Prisma ORM for type-safe database access with schema design, migrations, and queries. Use when building database layers, designing relational schemas, implementing type-safe queries, or managing database migrations.
---

# Developing with Prisma

## Quick Start

```prisma
// 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
  posts     Post[]
  createdAt DateTime @default(now())
  @@index([email])
}

model Post {
  id       String @id @default(cuid())
  title    String
  authorId String
  author   User   @relation(fields: [authorId], references: [id])
}
```

```bash
npx prisma migrate dev --name init
npx prisma generate
```

## Features

| Feature | Description | Guide |
|---------|-------------|-------|
| Schema Design | Declarative data modeling with relations | Define models, relations, indexes in schema.prisma |
| Type-Safe Queries | Auto-generated TypeScript types | Use `findMany`, `findUnique`, `create`, `update` |
| Migrations | Version-controlled schema changes | `prisma migrate dev` for development, `deploy` for production |
| Relations | One-to-one, one-to-many, many-to-many | Use `include` or `select` to load related data |
| Transactions | ACID operations across multiple queries | Use `$transaction` for atomic operations |
| Raw Queries | Execute raw SQL when needed | Use `$queryRaw` for complex queries |

## Common Patterns

### Repository with Pagination

```typescript
async function findUsers(page = 1, limit = 20, where?: Prisma.UserWhereInput) {
  const [data, total] = await prisma.$transaction([
    prisma.user.findMany({ where, skip: (page - 1) * limit, take: limit, include: { profile: true } }),
    prisma.user.count({ where }),
  ]);
  return { data, pagination: { page, limit, total, totalPages: Math.ceil(total / limit) } };
}
```

### Interactive Transaction

```typescript
async function createOrder(userId: string, items: { productId: string; qty: number }[]) {
  return prisma.$transaction(async (tx) => {
    let total = 0;
    for (const item of items) {
      const product = await tx.product.update({
        where: { id: item.productId },
        data: { stock: { decrement: item.qty } },
      });
      if (product.stock < 0) throw new Error(`Insufficient stock: ${product.name}`);
      total += product.price * item.qty;
    }
    return tx.order.create({ data: { userId, total, items: { create: items } } });
  });
}
```

### Cursor-Based Pagination

```typescript
async function getPaginatedPosts(cursor?: string, take = 20) {
  const posts = await prisma.post.findMany({
    take: take + 1,
    ...(cursor && { skip: 1, cursor: { id: cursor } }),
    orderBy: { createdAt: 'desc' },
  });
  const hasMore = posts.length > take;
  return { data: hasMore ? posts.slice(0, -1) : posts, nextCursor: hasMore ? posts[take - 1].id : null };
}
```

## Best Practices

| Do | Avoid |
|----|-------|
| Use `select` to fetch only needed fields | Exposing Prisma Client directly in APIs |
| Create indexes for frequently queried fields | Skipping migrations in production |
| Use transactions for multi-table operations | Ignoring N+1 query problems |
| Run migrations in CI/CD pipelines | Hardcoding connection strings |
| Use connection pooling in production | Using raw queries unless necessary |
| Validate input before database operations | Using implicit many-to-many for complex joins |
| Seed development databases consistently | Ignoring transaction isolation levels |

Overview

This skill implements Prisma ORM for type-safe database access, schema design, migrations, and query patterns in JavaScript/TypeScript projects. It provides practical examples for models, relations, pagination, transactions, and raw queries to speed up building reliable data layers. Use it to design relational schemas, generate a typed client, and manage migrations across environments.

How this skill works

The skill shows how to declare models, relations, and indexes in schema.prisma, then run Prisma commands to migrate and generate the client. It demonstrates common query patterns (findMany, create, update), transaction flows ($transaction), and when to use raw SQL ($queryRaw). Examples include pagination strategies, interactive transactions, and cursor-based APIs with type-safe responses.

When to use it

  • Building a new database layer with strong type safety
  • Designing relational data models and indexes before coding business logic
  • Implementing pagination, filtering, and efficient queries in APIs
  • Coordinating multi-step changes with ACID transactions
  • Managing schema migrations for development and production

Best practices

  • Use select to fetch only required fields and avoid overfetching
  • Keep Prisma Client out of public API internals; wrap DB access behind repository/service layers
  • Run migrations in CI/CD and avoid skipping migrations in production
  • Use transactions ($transaction) for multi-table operations and to prevent partial writes
  • Create indexes for frequent query patterns and validate inputs before DB operations
  • Prefer connection pooling in production and avoid raw queries unless necessary

Example use cases

  • Initialize schema.prisma with User and Post models, run migrate and generate to bootstrap a project
  • Implement page-based or cursor-based pagination for list endpoints using findMany and cursor patterns
  • Create an interactive order flow that decrements stock and creates orders inside a $transaction callback
  • Write repository functions that return typed results with pagination metadata and total counts
  • Execute complex analytics via $queryRaw for performance-critical SQL not covered by the client

FAQ

How do I run migrations during development vs production?

Use prisma migrate dev locally for iterative development; use prisma migrate deploy in CI/CD or production to apply already-generated migration files.

When should I use raw SQL with Prisma?

Use $queryRaw for complex queries or performance-critical operations not expressible with the client, but prefer the typed client for safety and maintainability.