Getting Started (अपडेट: 3/6/2026)

Claude Code के साथ Prisma ORM: schema, migration, transaction और test

Claude Code से Prisma ORM: schema, migration review, transactions, seed/test और production checklist.

Claude Code के साथ Prisma ORM: schema, migration, transaction और test

Prisma ORM TypeScript से DB को सुरक्षित तरीके से इस्तेमाल करने वाली typed database layer है। यहschema.prismaमें data model रखता है, Prisma Migrate से SQL migration बनाता है, और Prisma Client से type-safe queries लिखने देता है। Claude Code के साथ यह workflow तेज हो जाता है, लेकिन database design को बिना review के AI पर छोड़ना ठीक नहीं है।

अगर prompt सिर्फ “Prisma CRUD बना दो” है, तो code चल सकता है पर production-ready नहीं होगा। Index छूट सकते हैं,includeबहुत बड़ा हो सकता है, cascade delete जरूरत से ज्यादा खतरनाक हो सकता है, और migration real data पर fail हो सकती है। इस article में blog API के उदाहरण से दिखाया गया है कि Claude Code से schema, migration review, transactions, seed/test और review checklist कैसे बनवाएं।

Official references के लिए Prisma ORM, Prisma Schema, Transactions, और Prisma Migrate देखें। Related ClaudeCodeLab guides: Claude Code getting started, Drizzle ORM, Supabase integration, और Redis caching

Workflow

flowchart LR
  A["Product rules Claude Code को दें"] --> B["schema.prisma design"]
  B --> C["migration.sql generate और review"]
  C --> D["Prisma Client queries"]
  D --> E["seed और tests"]
  E --> F["Production checklist"]

Prisma work को तीन artifacts में बांटें: schema, SQL migration, और TypeScript query code। Claude Code draft बनाए, लेकिन constraints, indexes, delete rules और transaction boundaries को इंसान review करे।

Claude Code prompt

Blog API के लिए Prisma ORM data layer design करें।

Context:
- TypeScript + Prisma ORM + SQLite local, बाद में PostgreSQL migration संभव
- Models: User, Post, Category, Comment, Notification, AuditLog
- Post status string होगा: DRAFT/PUBLISHED/ARCHIVED
- email और slug unique होंगे
- Public listing status, publishedAt, author, category से filter होगी
- Post delete होने पर Comment और join rows cascade delete हों
- User delete अभी Restrict रहे; anonymization अलग migration में बने

Return:
1. prisma/schema.prisma
2. migration SQL review points
3. Prisma Client create/list/publish code
4. seed और test commands
5. production review checklist

Prompt में business rules लिखना जरूरी है। कौन सा data delete हो सकता है, कौन सा नहीं, किस list screen को index चाहिए, और कौन सा operation atomic होना चाहिए, यह स्पष्ट होना चाहिए।

Local setup

{
  "type": "module",
  "scripts": {
    "db:generate": "prisma generate",
    "db:migrate": "prisma migrate dev",
    "db:deploy": "prisma migrate deploy",
    "db:seed": "prisma db seed",
    "dev": "tsx src/demo.ts",
    "test": "vitest run"
  },
  "dependencies": {
    "@prisma/client": "latest",
    "dotenv": "latest"
  },
  "devDependencies": {
    "prisma": "latest",
    "tsx": "latest",
    "typescript": "latest",
    "vitest": "latest"
  }
}
npm install
echo 'DATABASE_URL="file:./dev.db"' > .env
mkdir prisma src
// prisma.config.ts
import "dotenv/config";
import { defineConfig, env } from "prisma/config";

export default defineConfig({
  schema: "prisma/schema.prisma",
  migrations: {
    path: "prisma/migrations",
    seed: "tsx prisma/seed.ts",
  },
  datasource: {
    url: env("DATABASE_URL"),
  },
});

schema.prisma

generator client {
  provider = "prisma-client"
  output   = "../src/generated/prisma"
}

datasource db {
  provider = "sqlite"
}

model User {
  id            String         @id @default(cuid())
  email         String         @unique
  name          String
  role          String         @default("editor")
  posts         Post[]
  comments      Comment[]
  notifications Notification[]
  createdAt     DateTime       @default(now())
  updatedAt     DateTime       @updatedAt

  @@index([role])
}

model Post {
  id          String              @id @default(cuid())
  slug        String              @unique
  title       String
  body        String
  status      String              @default("DRAFT")
  authorId    String
  author      User                @relation(fields: [authorId], references: [id], onDelete: Restrict)
  categories  CategoriesOnPosts[]
  comments    Comment[]
  publishedAt DateTime?
  createdAt   DateTime            @default(now())
  updatedAt   DateTime            @updatedAt

  @@index([authorId])
  @@index([status, publishedAt])
}

model Category {
  id    String              @id @default(cuid())
  slug  String              @unique
  name  String
  posts CategoriesOnPosts[]
}

model CategoriesOnPosts {
  postId     String
  categoryId String
  assignedAt DateTime @default(now())
  post       Post     @relation(fields: [postId], references: [id], onDelete: Cascade)
  category   Category @relation(fields: [categoryId], references: [id], onDelete: Cascade)

  @@id([postId, categoryId])
}

model Comment {
  id        String   @id @default(cuid())
  body      String
  postId    String
  authorId  String
  post      Post     @relation(fields: [postId], references: [id], onDelete: Cascade)
  author    User     @relation(fields: [authorId], references: [id], onDelete: Restrict)
  createdAt DateTime @default(now())

  @@index([postId, createdAt])
  @@index([authorId])
}

model Notification {
  id        String    @id @default(cuid())
  userId    String
  user      User      @relation(fields: [userId], references: [id], onDelete: Cascade)
  type      String
  message   String
  readAt    DateTime?
  createdAt DateTime  @default(now())

  @@index([userId, readAt])
}

model AuditLog {
  id        String   @id @default(cuid())
  action    String
  targetId  String
  metadata  String?
  createdAt DateTime @default(now())

  @@index([action, createdAt])
}

Claude Code से हर index का कारण लिखवाएं। status + publishedAt public post list के लिए है, और postId + createdAt comment list के लिए। बिना real query वाला index maintenance cost है।

Migration review

npx prisma format
npx prisma migrate dev --create-only --name init_blog
# PR में prisma/migrations/*/migration.sql पढ़ें
npx prisma migrate dev
npx prisma generate

Production deploy में:

npx prisma migrate deploy

db pushprototype के लिए ठीक है, production migration workflow नहीं। Existing data परDROP, नयाNOT NULL, unique constraint और cascade change जरूर check करें।

Rollback plan PR में deploy से पहले लिखें। Migration अगर सफल हो चुकी है, तो schema वापस करके नई forward migration बनाना बेहतर है। अगर migration बीच में fail हुई है, तो Prisma के down migration workflow के अनुसार backup verify करें, migrate status चलाएं, reviewed down SQL लगाएं और उसी failed migration को migrate resolve से rolled back mark करें।

npx prisma migrate status
npx prisma migrate resolve --rolled-back "20260603090000_failed_change"

Prisma Client और transaction

// src/db.ts
import { PrismaClient } from "./generated/prisma/client";

const globalForPrisma = globalThis as unknown as { prisma?: PrismaClient };

export const prisma =
  globalForPrisma.prisma ??
  new PrismaClient({
    log: ["warn", "error"],
  });

if (process.env.NODE_ENV !== "production") {
  globalForPrisma.prisma = prisma;
}
// src/posts.ts
import { Prisma } from "./generated/prisma/client";
import { prisma } from "./db";

export async function listPublishedPosts(params: {
  page?: number;
  perPage?: number;
  categorySlug?: string;
  search?: string;
}) {
  const page = Math.max(params.page ?? 1, 1);
  const perPage = Math.min(Math.max(params.perPage ?? 20, 1), 50);

  const where: Prisma.PostWhereInput = {
    status: "PUBLISHED",
    ...(params.categorySlug
      ? { categories: { some: { category: { slug: params.categorySlug } } } }
      : {}),
    ...(params.search
      ? { OR: [{ title: { contains: params.search } }, { body: { contains: params.search } }] }
      : {}),
  };

  const [items, total] = await prisma.$transaction([
    prisma.post.findMany({
      where,
      skip: (page - 1) * perPage,
      take: perPage,
      orderBy: [{ publishedAt: "desc" }, { createdAt: "desc" }],
      select: {
        id: true,
        slug: true,
        title: true,
        publishedAt: true,
        author: { select: { name: true } },
        _count: { select: { comments: true } },
      },
    }),
    prisma.post.count({ where }),
  ]);

  return { items, pagination: { page, perPage, total } };
}

export async function publishPost(postId: string) {
  return prisma.$transaction(async (tx) => {
    const post = await tx.post.findUnique({
      where: { id: postId },
      select: { id: true, title: true, status: true, authorId: true },
    });

    if (!post) throw new Error("Post not found");
    if (post.status === "PUBLISHED") return post;

    const published = await tx.post.update({
      where: { id: post.id },
      data: { status: "PUBLISHED", publishedAt: new Date() },
      select: { id: true, title: true, status: true, publishedAt: true },
    });

    await tx.notification.create({
      data: {
        userId: post.authorId,
        type: "POST_PUBLISHED",
        message: `${post.title} was published`,
      },
    });

    await tx.auditLog.create({
      data: {
        action: "POST_PUBLISHED",
        targetId: post.id,
        metadata: JSON.stringify({ title: post.title }),
      },
    });

    return published;
  });
}

List और count जैसे independent reads के लिए$transaction([])ठीक है। Publish जैसे operation में post update, notification और audit log साथ होने चाहिए, इसलिए interactive transaction उपयोगी है। Transaction के अंदर email, webhook या slow API call न रखें।

Safe SQL

पहले Prisma Client query इस्तेमाल करें। Reporting के लिए raw SQL सच में चाहिए तो pitfall string concatenation है, जिससे SQL-injection risk बनता है। Prisma की raw query docs tagged templates या Prisma.sql की सलाह देती हैं।

import { Prisma } from "./generated/prisma/client";
import { prisma } from "./db";

export async function topAuthors(limit = 10) {
  return prisma.$queryRaw<
    { authorId: string; postCount: bigint }[]
  >(Prisma.sql`
    SELECT "authorId", COUNT(*) AS "postCount"
    FROM "Post"
    WHERE "status" = ${"PUBLISHED"}
    GROUP BY "authorId"
    ORDER BY "postCount" DESC
    LIMIT ${Math.min(limit, 50)}
  `);
}

Claude Code से हर $queryRawUnsafe का कारण लिखवाएं। Dynamic table या column names चाहिए हों तो human-reviewed allowlist बनाएं।

Seed, test और checklist

// prisma/seed.ts
import { PrismaClient } from "../src/generated/prisma/client";

const prisma = new PrismaClient();

async function main() {
  const user = await prisma.user.upsert({
    where: { email: "editor@example.com" },
    update: { name: "Editor" },
    create: { email: "editor@example.com", name: "Editor", role: "admin" },
  });

  await prisma.post.upsert({
    where: { slug: "claude-code-prisma-demo" },
    update: { status: "PUBLISHED", publishedAt: new Date() },
    create: {
      slug: "claude-code-prisma-demo",
      title: "Claude Code Prisma demo",
      body: "Seeded article for local verification.",
      status: "PUBLISHED",
      publishedAt: new Date(),
      authorId: user.id,
    },
  });
}

main().finally(async () => prisma.$disconnect());
npm run db:migrate -- --name init_blog
npm run db:generate
npm run db:seed
npm run test

Checklist: constraints और indexes real screens से जुड़े हों, SQL destructive न हो, pagination limit हो, transaction short हो, seed दोबारा चल सके, tests rollback या duplicate execution देखें, और production मेंmigrate deployचलाया जाए।

Use cases, pitfalls और CTA

तीन practical use cases हैं: content site का article management, SaaS admin panel, और payment के बाद entitlement देना। Content site में slug और published status अहम हैं। SaaS में हर query tenant-scoped होनी चाहिए। Payment flow में idempotency, audit log और transaction boundary जरूरी हैं।

Masa ने एक छोटी blog API पर यही flow test किया। Claude Code से migration risk पहले लिखवाने पर दो issues जल्दी मिले: cascade delete ज्यादा broad था और public list जरूरत से ज्यादा author fields लौटाती थी। यही सही तरीका है: AI से speed लो, फिर type, SQL और tests से verify करो।

Self-study के लिए /products/ देखें। Team workflow, review prompts और DB migration training के लिए /training/ सही entry point है। Existing schema या AI-generated PR लेकर आने पर discussion सीधे real risks पर शुरू हो सकता है।

#Claude Code #Prisma #ORM #database #TypeScript
मुफ़्त

मुफ़्त PDF: Claude Code cheatsheet

Email डालें और commands, review habits तथा safe workflow वाली एक-page PDF पाएँ.

हम आपका data सुरक्षित रखते हैं और spam नहीं भेजते.

Masa

लेखक के बारे में

Masa

Claude Code workflow और team adoption पर काम करने वाला engineer.