重要前提
安装AI Skills的关键前提是:必须科学上网,且开启TUN模式,这一点至关重要,直接决定安装能否顺利完成,在此郑重提醒三遍:科学上网,科学上网,科学上网。查看完整安装教程 →
prisma-patterns by ashchupliak/dream-team
npx skills add https://github.com/ashchupliak/dream-team --skill prisma-patterns// 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
}
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
// 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
}
// 创建
const environment = await prisma.environment.create({
data: {
name: 'dev-env',
description: 'Development environment',
ownerId: userId,
},
})
// 读取
const environment = await prisma.environment.findUnique({
where: { id: envId },
})
const environments = await prisma.environment.findMany({
where: { status: 'RUNNING' },
orderBy: { createdAt: 'desc' },
take: 10,
})
// 更新
const updated = await prisma.environment.update({
where: { id: envId },
data: { status: 'STOPPED' },
})
// 删除
await prisma.environment.delete({
where: { id: envId },
})
// 更新或创建
const env = await prisma.environment.upsert({
where: { id: envId },
update: { status: 'RUNNING' },
create: {
name: 'new-env',
ownerId: userId,
},
})
// 包含关联
const envWithOwner = await prisma.environment.findUnique({
where: { id: envId },
include: {
owner: true,
tags: true,
},
})
// 选择特定字段
const envPartial = await prisma.environment.findUnique({
where: { id: envId },
select: {
id: true,
name: true,
owner: {
select: {
name: true,
email: true,
},
},
},
})
// 嵌套创建
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 },
})
// 连接现有关联
const env = await prisma.environment.create({
data: {
name: 'new-env',
owner: {
connect: { id: userId },
},
},
})
// 复杂筛选
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 筛选
const nonFailedEnvs = await prisma.environment.findMany({
where: {
NOT: { status: 'FAILED' },
},
})
// 偏移分页
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),
}
}
// 游标分页
async function getEnvironmentsCursor(cursor?: string, take: number = 10) {
const items = await prisma.environment.findMany({
take: take + 1, // 多取一条以检查是否还有更多
...(cursor && {
cursor: { id: cursor },
skip: 1, // 跳过游标
}),
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,
}
}
// 交互式事务
const result = await prisma.$transaction(async (tx) => {
// 创建环境
const env = await tx.environment.create({
data: { name: 'new-env', ownerId: userId },
})
// 创建关联标签
await tx.tag.createMany({
data: [
{ key: 'team', value: 'platform', environmentId: env.id },
{ key: 'cost-center', value: '12345', environmentId: env.id },
],
})
// 更新用户的环境计数(如果跟踪)
await tx.user.update({
where: { id: userId },
data: { environmentCount: { increment: 1 } },
})
return env
})
// 顺序事务(批量)
const [deletedEnvs, deletedTags] = await prisma.$transaction([
prisma.environment.deleteMany({ where: { status: 'FAILED' } }),
prisma.tag.deleteMany({ where: { environment: { status: 'FAILED' } } }),
])
// 按状态计数
const statusCounts = await prisma.environment.groupBy({
by: ['status'],
_count: { status: true },
})
// 聚合函数
const stats = await prisma.environment.aggregate({
_count: { id: true },
_min: { createdAt: true },
_max: { createdAt: true },
})
// 原始查询
const result = await prisma.$queryRaw<Environment[]>`
SELECT * FROM environments
WHERE status = ${status}
AND created_at > NOW() - INTERVAL '7 days'
`
// 原始执行
await prisma.$executeRaw`
UPDATE environments
SET status = 'STOPPED'
WHERE status = 'RUNNING'
AND updated_at < NOW() - INTERVAL '24 hours'
`
# 创建迁移
npx prisma migrate dev --name add_environment_type
# 应用迁移(生产环境)
npx prisma migrate deploy
# 重置数据库(开发环境)
npx prisma migrate reset
# 生成客户端
npx prisma generate
每周安装次数
51
仓库
GitHub 星标数
4
首次出现时间
2026年1月20日
安全审计
安装于
opencode44
codex41
gemini-cli39
cursor39
github-copilot38
claude-code37
// 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
}
// 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
}
// 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,
},
})
// 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 },
},
},
})
// 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' },
},
})
// 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,
}
}
// 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' } } }),
])
// 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 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'
`
# 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
Weekly Installs
51
Repository
GitHub Stars
4
First Seen
Jan 20, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
opencode44
codex41
gemini-cli39
cursor39
github-copilot38
claude-code37
Node.js 环境配置指南:多环境管理、类型安全与最佳实践
10,500 周安装