From harness-claude
Executes type-safe Prisma Client queries: findUnique/findMany for reads, create/update/delete/upsert for writes, select fields, include relations. Use for database CRUD operations.
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeThis skill uses the workspace's default tool permissions.
> Query data with Prisma Client findUnique/findMany, create/update/delete, upsert, select, include
Optimizes Prisma queries with select for needed fields, findUnique index hits, batching, and N+1 avoidance. Use for diagnosing slow queries or high database load.
Provides expert guidance on Prisma ORM schema design, migrations, query optimization, relations modeling, and database operations for PostgreSQL, MySQL, SQLite.
Provides expert guidance on Prisma ORM for TypeScript apps: schema design, migrations, Prisma Client queries, relations, edge deployment, and performance optimization.
Share bugs, ideas, or general feedback.
Query data with Prisma Client findUnique/findMany, create/update/delete, upsert, select, include
PrismaClient per request:// lib/prisma.ts
import { PrismaClient } from '@prisma/client';
const globalForPrisma = globalThis as unknown as { prisma: PrismaClient };
export const prisma = globalForPrisma.prisma ?? new PrismaClient();
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma;
findUnique for lookups by @id or @unique fields. Use findFirst when filtering by non-unique fields:const user = await prisma.user.findUnique({ where: { id: userId } });
const admin = await prisma.user.findFirst({ where: { role: 'ADMIN' } });
findMany returns an array. Always paginate large result sets:const users = await prisma.user.findMany({
where: { role: 'USER' },
take: 20,
skip: 0,
orderBy: { createdAt: 'desc' },
});
const names = await prisma.user.findMany({
select: { id: true, name: true, email: true },
});
// Type: { id: string; name: string | null; email: string }[]
include:const userWithPosts = await prisma.user.findUnique({
where: { id: userId },
include: { posts: { where: { published: true }, take: 10 } },
});
const user = await prisma.user.create({
data: { email: 'new@example.com', name: 'New User' },
});
where clause:const updated = await prisma.user.update({
where: { id: userId },
data: { name: 'Updated Name' },
});
const user = await prisma.user.upsert({
where: { email: 'user@example.com' },
create: { email: 'user@example.com', name: 'New' },
update: { name: 'Existing' },
});
delete for single records, deleteMany for bulk:await prisma.user.delete({ where: { id: userId } });
await prisma.post.deleteMany({ where: { authorId: userId } });
const user = await prisma.user.create({
data: {
email: 'author@example.com',
posts: { create: [{ title: 'First Post' }, { title: 'Second Post' }] },
},
include: { posts: true },
});
Prisma Client is auto-generated from the schema and provides full TypeScript types for every query. The generated types enforce that you only pass valid field names, filter operators, and relation includes.
select vs include: These are mutually exclusive at the same level. select returns only the specified fields (plus any nested select/include). include returns all scalar fields plus the specified relations.
findUnique vs findFirst: findUnique can only filter by @id or @unique fields and benefits from Prisma's internal query deduplication (DataLoader batching). findFirst can filter by any field but does not deduplicate.
findUniqueOrThrow / findFirstOrThrow: These variants throw a PrismaClientKnownRequestError with code P2025 instead of returning null. Use them when absence is an error condition.
Nested writes are atomic: create with nested create/connect/connectOrCreate runs in a single implicit transaction. If any nested operation fails, the entire write is rolled back.
Return types narrow automatically: When you use select, the return type includes only the selected fields. This is enforced at the TypeScript level, so your code stays type-safe.
Common mistakes:
findFirst where findUnique would work — loses batching optimizationinclude — each level adds a separate database query. Three levels deep on a list page causes N+1 problemsnull from findUnique — always check or use findUniqueOrThrowupdateMany/deleteMany do not return the affected records — only a counthttps://prisma.io/docs/orm/prisma-client/queries