关于 prisma-next-contract
面向 Prisma Next 的数据契约编写技能,涵盖 PSL 和 TypeScript builder 两种方式。它指导模型、字段、关系、约束及扩展的修改,并区分契约编辑与迁移、查询任务。
主要功能
- 01使用 PSL 或 TypeScript 编写契约
- 02生成并验证契约产物
- 03编辑模型、字段和关系
- 04定义索引、枚举和值对象
- 05配置扩展
适用场景
- 01添加或修改模型、字段
- 02定义关系与约束
- 03配置扩展类型
- 04排查契约生成诊断
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ prisma/ prisma-next --skill prisma-next-contract安装后在 Claude Code 中输入/prisma-next-contract确认已加载。
详细介绍
Prisma Next — 契约编写
编辑你的数据契约。其余工作交给 Prisma。
数据契约是数据层的唯一事实来源。你编辑契约源文件——contract.prisma(PSL,规范表层)或 contract.ts(TypeScript 构建器)——框架会据此生成类型、迁移和运行时配置。用户模型分为三步:
- 编辑数据契约。
- 系统为你规划迁移。(
prisma-next-migrations) - 如果需要数据迁移,编辑
migration.ts并执行。(prisma-next-migrations)
在第 1 步中,Agent 每次编辑契约后都会运行 prisma-next contract emit(或者安装 Vite 插件,让打包器在保存时运行该命令——参见 prisma-next-build)。Emit 会通过 façade 根据 prisma-next.config.ts 中 contract: 的文件扩展名所选定的 provider 读取契约源文件,然后在同一目录下写入两个产物:
contract.json— 规范的、经过内容哈希处理的 Contract IR。规划器、运行时和db verify会读取此文件。contract.d.ts— 从中导入Contract时,运行时和各 lane 会传递的精确 TypeScript 类型。
这两个文件都是生成的产物。编辑源文件;切勿编辑 JSON 或 .d.ts 文件。
适用场景
- 用户想要添加、更改或移除模型、字段或关系。
- 用户想要添加索引、唯一约束、枚举或值对象(复合类型)。
- 用户想要添加命名空间块(Postgres 模式)或跨契约外键。
- 用户想要在模型上设置
@@control或配置defaultControlPolicy。 - 用户想要使用扩展中的自定义类型(
pgvector.Vector(length: 1536)、cipherstash.EncryptedString({...}))。 - 用户想要通过
prisma-next.config.ts中的extensions: [...]安装或配置扩展,包括@prisma-next/extension-supabase。 - 用户正在切换契约编写源(PSL ↔ TypeScript 构建器)。
- 用户在运行
contract emit时收到PN-CLI-4002、PN-CLI-4003或PN-CLI-4011。 - 用户提到:schema、字段、模型、属性、prisma schema、PSL、contract.prisma、contract.ts、contract.json、contract.d.ts、contract emit、façade 导入、
@prisma-next/postgres/config、@prisma-next/postgres/contract-builder、扩展、pgvector、cipherstash、postgis、paradedb、supabase、命名空间、跨空间 FK、@@control、枚举、值对象、验证、回调、软删除、paranoid、作用域。(最后一组应转到下文的 Prisma Next 尚不支持的功能。)
不适用场景
- 用户想要将契约更改应用到数据库 →
prisma-next-migrations。 - 用户想要针对契约编写查询 →
prisma-next-queries。 - 用户想要配置
db.ts(运行时入口、中间件、环境配置)→prisma-next-runtime。 - 用户想要配置 Vite / 打包器集成 →
prisma-next-build。 - 用户想要首次设置 Prisma Next →
prisma-next-quickstart。 - 用户想要深入了解单个结构化错误信封 →
prisma-next-debug。 - 用户想要提交缺失功能请求 →
prisma-next-feedback。
核心概念
- 用户编写的代码只能从
@prisma-next/<target>门面导入。 对于 Postgres 应用:@prisma-next/postgres/config、@prisma-next/postgres/contract-builder、@prisma-next/postgres/control、@prisma-next/postgres/runtime。Mongo 的布局相同(@prisma-next/mongo/config、@prisma-next/mongo/contract-builder、@prisma-next/mongo/runtime)。每个扩展都会发布自己的门面:@prisma-next/extension-pgvector/control、@prisma-next/extension-postgis/control、@prisma-next/extension-paradedb/control。用户代码绝不能深入使用@prisma-next/cli/*、@prisma-next/family-*、@prisma-next/target-*、@prisma-next/adapter-*、@prisma-next/driver-*或@prisma-next/sql-contract-*。 门面会封装好 family / target / adapter / driver 的连接配置。参见 常见陷阱 #4。 - Contract 源文件。 框架会读取并降级为规范 Contract IR 的文件。有两种形式,二者都是一等形式:
contract.prisma(PSL) — 具有 schema 风格的 DSL。适用于典型应用和使用 Prisma 的棕地项目。通过contract: './<path>/contract.prisma'接入——defineConfig门面会检测.prisma扩展名,并路由到 PSL 提供程序。contract.ts(TypeScript 构建器) — 使用@prisma-next/postgres/contract-builder(或@prisma-next/mongo/contract-builder)中的defineContract({...}, ({ field, model, rel, type }) => ({...}))以编程方式编写。通过contract: './<path>/contract.ts'接入——门面会检测.ts扩展名,并路由到 TS 提供程序。当你需要以编程方式组合(每租户变体、生成字段),或需要 PSL 尚无法表达的结构(例如注册参数化扩展类型——参见 pgvector 的 Contract)时使用。
prisma-next.config.ts。 用于连接 Contract 源文件、数据库连接、迁移目录和已安装的扩展。使用@prisma-next/postgres/config(或@prisma-next/mongo/config)中的defineConfig({...})。门面接受四个字段:contract(路径字符串——.prisma或.ts)、db({ connection?: string })、extensions(控制描述符数组)、migrations({ dir?: string })。contract.json的输出路径会根据contract自动推导(例如,./src/prisma/contract.prisma→./src/prisma/contract.json)。- Emit 流程。
prisma-next contract emit --config <path>?会读取prisma-next.config.ts,调用门面选定的提供程序,验证生成的 Contract,然后将contract.json+contract.d.ts原子写入与源文件相同的目录。 - 扩展命名空间。 扩展会提供带命名空间的构造器(
pgvector.Vector(length: 1536)、cipherstash.EncryptedString({equality: true}))和辅助预设。通过在两个位置添加描述符来安装扩展——两个字段都命名为extensions,但这两个接口使用不同类型和形状的描述符:- 在配置中(门面和核心):
extensions: [pgvector]— 从@prisma-next/extension-<name>/control导入的 control 描述符数组。 - 在 TS 构建器的
defineContract中(仅编写contract.ts时):extensions: { pgvector }— 从@prisma-next/extension-<name>/pack导入的 pack 描述符记录。
- 在配置中(门面和核心):
- Contract 空间。 每个生成 Contract 的包都有自己的 Contract 空间——包根目录下的
prisma-next.config.ts、Contract 源文件、与源文件同目录生成的产物,以及migrations/目录。磁盘上有两种有意设计的布局,取决于 Contract 空间属于使用它的应用,还是属于 Contract 空间包(扩展、内部聚合根包等):- 应用布局(构建应用时使用)。仓库根目录下的
prisma-next.config.ts;src/prisma/contract.{prisma,ts};同目录下的src/prisma/contract.{json,d.ts};同目录下的src/prisma/db.ts;迁移文件位于migrations/app/<timestamp>_<slug>/。app/段是使用该空间的应用的空间 ID;扩展空间 ID 则位于由扩展包管理的同级migrations/<extension-space-id>/目录中。examples/prisma-next-demo使用这种布局。目前prisma-next init生成的布局有所不同(仓库根目录下的prisma/...)——这是一个缺陷(TML-2532);每条命令实际预期使用的规范布局即为此布局。 - Contract 空间包布局(发布 Contract 空间包时使用——例如扩展、内部 monorepo 包)。包根目录下的
prisma-next.config.ts;直接位于src/contract.{prisma,ts}(没有prisma/子目录);同目录下的src/contract.{json,d.ts};迁移文件直接位于migrations/<timestamp>_<slug>/(没有<space-id>段——该包本身就是一个独立空间)。详见.cursor/rules/contract-space-package-layout.mdc和 ADR 212。 两种布局都允许defineConfig的contract:路径指向源文件;框架会据此推导其他所有内容(生成输出、迁移根目录)。选择与当前构建内容匹配的布局并保持一致——不要混用。
- 应用布局(构建应用时使用)。仓库根目录下的
可用于路由的诊断代码
prisma-next contract emit 会返回带有稳定代码的结构化错误;应根据 code 分支处理,而不是依据消息文本。
| 代码 | 含义 | 后续操作 |
|---|---|---|
PN-CLI-4002 缺少 Contract 配置 | prisma-next.config.ts 中未设置 contract。 | 在 @prisma-next/postgres/config 的 defineConfig({...}) 中添加 contract: './src/prisma/contract.prisma'(应用布局)或 './src/contract.prisma'(contract-space-package 布局);.ts 源文件也同理。 |
PN-CLI-4003 Contract 验证失败 | 已加载源文件,但 Contract IR 未通过结构验证。 | 查看 meta.diagnostics / meta.issues,找出有问题的模型/字段,修复源文件后重新生成。 |
PN-CLI-4011 配置中缺少扩展包 | Contract 使用了带命名空间的构造器(例如 pgvector.Vector(...)),但配置中的 extensions 未列出匹配的描述符。meta.missingExtensions 会列出缺少的扩展。 | 安装该包,导入其控制描述符(import pgvector from '@prisma-next/extension-pgvector/control'),并将其添加到 prisma-next.config.ts 的 extensions: [...] 中。 |
工作流 — 阅读 Contract 的真实来源
概念:每次更改 Contract,都应先定位源文件。配置是权威依据——阅读 prisma-next.config.ts,找到 contract: 字段(门面下的路径字符串),然后打开它指向的文件。同一字段还会告知已安装的 extensions: [...]。
cat prisma-next.config.ts
如果 contract: 以 .prisma 结尾,源文件就是 PSL;如果以 .ts 结尾,源文件就是 TS 构建器。如果缺少 prisma-next.config.ts,请转到 prisma-next-quickstart。
工作流 — 编辑模型 / 字段 / 关系(PSL)
概念:PSL 模型会映射为表(Mongo 中则为集合);字段会映射为列;@relation(...) 用于声明外键一侧。只在拥有关系的一侧添加关系——框架会自动推导反向引用。
model User {
id Int @id @default(autoincrement())
email String @unique
}
model Post {
id Int @id @default(autoincrement())
title String
authorId Int
author User @relation(fields: [authorId], references: [id], onDelete: Cascade)
@@unique([title, authorId])
@@index([authorId])
}
然后运行 pnpm prisma-next contract emit(或使用 Vite 插件——参见 prisma-next-build)。通过 onDelete / onUpdate 显式指定级联行为;默认值为 Restrict。
@@index 还接受 expression:(替代字段列表)、where:(部分索引谓词)、unique:、type:/options:(目标注册的访问方法),以及 name: 或 map:(二者只能选其一):
@@index(expression: "lower(email)", name: "users_email_lower")
@@index([authorId], where: "(archived_at IS NULL)", name: "posts_author_active")
name: 声明受管理的索引(物理名称为 <name>_<8-hex hash>,重命名计划为 ALTER INDEX … RENAME);map: 则按原样采用精确的物理名称(适用于 infer 捕获的对象——将它与 SQL 正文结合使用时会发出警告,因为漂移检测会逐字节比较编写的文本与 Postgres 重新打印的文本)。expression: 必须配合 name: 或 map: 使用。TS 构建器通过 constraints.index([cols.x], {...}) / constraints.index({ expression, ... }) 提供对应功能——参见 packages/2-sql/2-authoring/contract-ts/README.md。
用于重复类型的 PSL 别名可在顶层 types {} 块中定义:
types {
Email = String
}
model User {
id Int @id @default(autoincrement())
email Email @unique
}
注意:SQL 解释器不支持标量列表(例如 String[])和隐式 Prisma-ORM 多对多关系(双方都有列表导航属性但没有联结模型)——请改用联结模型。支持复合/可嵌入类型(模型中使用 type Address { ... } 和 address Address):解释器会将其映射为领域中的 valueObjects,并将其存储为 jsonb 列。参见下文的 工作流 — 值对象。
工作流 — 编辑模型 / 字段 / 关系(TS 构建器)
概念:同一个模型,不同的编写方式。该门面将 defineContract、field、model、rel 重新导出,并将 family/target 包作为 @prisma-next/postgres/family 和 @prisma-next/postgres/target 的默认导出。使用回调重载(defineContract({...}, ({ field, model, rel, type }) => ({...})))即可使用更高层级的辅助函数(field.text()、field.id.uuidv7String()、field.temporal.createdAt()、type.sql.String(35))。
import sqlFamily from '@prisma-next/postgres/family';
import { defineContract } from '@prisma-next/postgres/contract-builder';
import postgresPack from '@prisma-next/postgres/target';
export const contract = defineContract(
{
family: sqlFamily,
target: postgresPack,
},
({ field, model }) => ({
models: {
User: model('User', {
fields: {
id: field.id.uuidv7String(),
email: field.text().unique(),
createdAt: field.temporal.createdAt(),
},
}).sql({ table: 'app_user' }),
},
}),
);
然后运行 pnpm prisma-next contract emit。field.<scalar>() 辅助函数仅在回调重载中可用;在回调外仅有 field.column(...)、field.generated(...)、field.namedType(...)。
对于 Mongo,将所有 @prisma-next/postgres/* 导入替换为 @prisma-next/mongo/*。Mongo 构建器还提供 index 和 valueObject。
工作流 — 添加扩展类型标量(pgvector)
概念:扩展提供一个命名空间(pgvector.*)和两种描述符类型——用于配置门面的 control 描述符,以及用于 TS 构建器的 pack 描述符。在 defineConfig.extensions 中注册 control 描述符(数组形式)。如果使用 TS 构建器编写,还要在 defineContract.extensions 中注册 pack 描述符(记录形式)。然后在 contract 中引用带命名空间的构造器。
prisma-next.config.ts:
import pgvector from '@prisma-next/extension-pgvector/control';
import { defineConfig } from '@prisma-next/postgres/config';
export default defineConfig({
contract: './src/prisma/contract.prisma',
extensions: [pgvector],
});
src/prisma/contract.prisma:
model Document {
id Int @id @default(autoincrement())
content String
embedding pgvector.Vector(length: 1536)
}
运行 Emit。命名类型降级会将 vector(1536) 放到列上,而 contract.d.ts 中的类型映射则包含正确的 TS 类型。
如果引用 pgvector.* 却未在配置中注册 pack,Emit 会以 PN-CLI-4011 失败,并包含 meta.missingExtensions: ['pgvector']。信封中的 fix 文本为 "Add the missing extension descriptors to extensions in prisma-next.config.ts"——该字段名与门面一致。
有关单扩展和多扩展设置的规范示例,请阅读 examples/multi-extension-monorepo/app/prisma-next.config.ts 和 examples/prisma-next-postgis-demo/prisma-next.config.ts。
工作流 — 多态(@@discriminator / @@base)
概念(SQL 目标):一个基模型声明判别字段;每个变体模型声明其基模型和判别值。变体通过**是否设置 @@map(...)**来选择 STI 还是 MTI:不设置 @@map 表示变体继承基模型的表(单表继承);@@map("variant_table") 表示变体拥有自己的表,并通过主键进行 1:1 关联(多表继承)。
model Task {
id Int @id @default(autoincrement())
title String
type String
@@discriminator(type)
@@map("tasks")
}
// STI variant — shares the `tasks` table.
model Bug {
severity String
@@base(Task, "bug")
}
// MTI variant — joins to `tasks` via PK; carries its own `features` table.
model Feature {
priority Int
@@base(Task, "feature")
@@map("features")
}
如有疑问,请对照解释器测试验证多态语法:packages/2-sql/2-authoring/contract-psl/test/interpreter.polymorphism.test.ts。
Mongo 没有 schema 层,因此 Mongo 上的多态通过 TS 构建器中模型上的显式 discriminator 字段建模(参见 @prisma-next/mongo/contract-builder);@@base / @@discriminator PSL 属性仅适用于 SQL。
查询变体属于运行时问题——请参阅 prisma-next-queries。
工作流 — 值对象(复合类型)
概念:type Foo { ... } 块声明值对象形状。解释器会将它们降级为 contract domain 中的 valueObjects,并将其存储为 jsonb 列。支持嵌套值对象引用。
type Address {
street String
city String
zip String?
country String
}
model User {
id String @id @default(uuid())
email String
address Address?
}
生成的 contract.json 包含带字段描述符的 domain.namespaces.<ns>.valueObjects.Address,而 address 列在 storage 中的取值为 codecId: "pg/jsonb@1" / nativeType: "jsonb"。
规范示例:examples/prisma-next-demo/src/prisma/contract.prisma。
工作流 — 枚举
概念:PSL enum 块用于声明领域枚举:一个命名值集,通过声明的编解码器存储(@@type("pg/text@1") → text 列),并由规划器生成的 CHECK 约束强制执行。每个成员通过 Name = "value" 映射到数据库值。在同一契约中的任何模型里,都可以将枚举名称用作字段类型。
enum user_type {
@@type("pg/text@1")
admin = "admin"
user = "user"
}
model User {
id String @id @default(uuid())
kind user_type
}
规范示例:examples/prisma-next-demo/src/prisma/contract.prisma。
工作流 — 命名空间(Postgres 模式)
概念:将模型放入 namespace <name> { ... } 块中,以便将其置于非默认的 Postgres 模式中。不属于任何块的模型会放入隐式默认命名空间。
namespace public {
model Profile {
id String @id @default(uuid())
username String
userId String @unique
@@map("profile")
}
}
规范示例:examples/supabase/src/contract.prisma。
工作流 — 跨契约外键
概念:关系字段可以使用 <space>:<namespace>.<Model> 形式引用其他契约空间中的模型。契约还支持在 types {} 块中声明顶层命名类型别名,其基础是字段所用的相同裸类型位置构造器。@db.X(args) 通道已移除:将 @db.X 改写为 X,将 @db.X(args) 改写为 X(args);其余用法会报错,并提供明确诊断,指出替代写法。
types {
AuthUserId = Uuid
}
namespace public {
model Profile {
id String @id @default(uuid())
username String
userId AuthUserId @unique
user supabase:auth.AuthUser @relation(fields: [userId], references: [id], onDelete: Cascade)
@@map("profile")
}
}
supabase:auth.AuthUser 表示契约空间 supabase 中命名空间 auth 的模型 AuthUser。目标空间由已注册的扩展包提供(此处为 @prisma-next/extension-supabase/pack)。
规范示例:examples/supabase/src/contract.prisma。
工作流 — @@control(控制策略)
概念:模型上的 @@control(<policy>) 用于设置 Prisma 是否在迁移中管理该表的 DDL。参数是位置型小写字面量,可选值为 managed、tolerated、external 或 observed。
model AuditLog {
id Int @id
message String
@@control(observed)
}
可以通过 prismaContract(path, { defaultControlPolicy }) 上的 defaultControlPolicy 设置契约级默认值。有关控制策略对 DDL 规划的影响,请参阅 prisma-next-migrations。
工作流 — @prisma-next/extension-supabase
概念:Supabase 扩展提供 supabase 契约空间(将 auth / storage 模式作为 external 表,并提供平台角色),以及自己的角色优先运行时工厂。它不提供 /control 子路径,因此无法通过面向用户的 defineConfig({ extensions: [...] }) 外观注册,而是通过底层配置中的 extensions 接入。完整的实践模式请参阅 examples/supabase。
prisma-next.config.ts(与示例一致):
import supabasePack from '@prisma-next/extension-supabase/pack';
import { defineConfig } from '@prisma-next/cli/config-types';
// ... other low-level imports
export default defineConfig({
// ...
extensions: [supabasePack],
});
db.ts 不使用标准的 postgres() 工厂 — Supabase 应用通过 @prisma-next/extension-supabase/runtime 中的 supabase() 工厂构建客户端(角色优先:asUser(jwt) / asAnon() / asServiceRole(),JWT 验证、RLS)。该运行时以及 RLS 策略编写(policy_select / @@rls)由 prisma-next-supabase 介绍;如需了解配置接入以外的内容,请加载它。
导出子路径:@prisma-next/extension-supabase/pack、@prisma-next/extension-supabase/runtime、@prisma-next/extension-supabase/contract。规范示例:examples/supabase。
工作流 — 棕地内省
概念:从现有数据库提取契约源,并以此为基础继续操作。prisma-next contract infer --db <url> 会读取实时模式并写入 contract.prisma 文件。该命令到此为止 — 接下来分别执行 contract emit,以及(当模式与固定哈希匹配时)db sign。
pnpm prisma-next contract infer --db $DATABASE_URL --output ./src/prisma/contract.prisma
pnpm prisma-next contract emit
常见陷阱
- 编辑后忘记重新生成。
contract.json和contract.d.ts会过时;下游类型检查和migration plan会看到旧结构。请重新生成,或安装 Vite 插件(prisma-next-build)。 - 编辑生成的文件。
contract.json和contract.d.ts是生成的文件;下次生成时,对它们所做的编辑会被覆盖。请编辑源文件。 - TS 构建器使用了错误的工厂函数/导入路径。
defineContract、field、model、rel来自@prisma-next/postgres/contract-builder(或@prisma-next/mongo/contract-builder)。在回调重载之外,可用的字段构造函数有field.column(...)、field.generated(...)、field.namedType(...)。 - 在用户代码中引入内部包。 用户编写的文件(
prisma-next.config.ts、contract.ts、db.ts、控制客户端)只从@prisma-next/<target>/<subpath>和@prisma-next/extension-<name>/<subpath>导入。来自@prisma-next/cli/*、@prisma-next/family-*、@prisma-next/target-*、@prisma-next/adapter-*、@prisma-next/driver-*或@prisma-next/sql-contract-*的导入属于框架内部导入——门面会为你组合这些内容。如果你的目标缺少所需的门面子路径,请参阅 Prisma Next 目前尚不支持的功能,并通过prisma-next-feedback提交反馈。规范示例见examples/multi-extension-monorepo/app/prisma-next.config.ts和examples/prisma-next-postgis-demo/prisma-next.config.ts。 - 混淆配置中的
extensions与 TS 构建器中的extensions。 两者使用相同的扩展包,有两个不同的接口,字段名相同但结构不同:defineConfig({ extensions: [pgvector] })(来自@prisma-next/extension-<name>/control的控制描述符数组)与defineContract({ extensions: { pgvector } })(来自@prisma-next/extension-<name>/pack的扩展包描述符记录)。 - 重命名字段并期望规划器检测到变更。 Prisma Next 不提供契约内的重命名提示;规划器会将其视为破坏性删除并新增。执行
migration plan后手动编辑migration.ts(参见prisma-next-migrations),或使用先保留、后删除的两次迁移模式。
Prisma Next 目前尚不支持的功能
- 契约内重命名提示。 不支持
@@rename(old: ..., new: ...)或类似功能。请使用 常见陷阱 #6 中的变通方案。如需请求正式支持重命名,请通过prisma-next-feedback提交反馈。 - 模型验证。 不提供声明式的
@validates(...)接口。请在应用代码中验证(arktype)。如需请求在契约中加入声明式验证,请通过prisma-next-feedback提交反馈。 - 生命周期回调(
beforeSave、afterCreate等)。不支持。请使用中间件(prisma-next-runtime)或应用代码。如需请求生命周期回调,请通过prisma-next-feedback提交反馈。 - 软删除/
paranoid: true。 不内置软删除列。请添加可空的deletedAt DateTime?,并在查询中显式过滤(或在中间件中处理)。如需请求内置软删除,请通过prisma-next-feedback提交反馈。 - 作用域/默认过滤器。 不支持 ActiveRecord 风格的作用域。请自行组合查询辅助函数。如需请求作用域,请通过
prisma-next-feedback提交反馈。 - 隐式 Prisma-ORM 多对多关系。 不支持双方都带列表导航但没有显式联结模型的关系。请显式编写联结模型。如需请求隐式 M2M,请通过
prisma-next-feedback提交反馈。
参考
- 运行
pnpm prisma-next contract --help查看当前命令。 - PSL 的功能范围及解释器接受的内容:
packages/2-sql/2-authoring/contract-psl/README.md。 - TS 构建器的功能范围及回调辅助工具词汇:
packages/2-sql/2-authoring/contract-ts/README.md。 - 布局(
contract.prisma、contract.json、contract.d.ts和migrations/的存放位置):- 应用布局(
src/prisma/...+migrations/app/...)——examples/prisma-next-demo展示的布局;使用该布局的是规范形态的消费应用。 - Contract-space-package 布局(直接放置
src/contract.{prisma,ts},migrations/<timestamp>_<slug>/中不含 space-id 段)——适用于扩展和聚合根包,详见.cursor/rules/contract-space-package-layout.mdc和 ADR 212。
- 应用布局(
检查清单
- 阅读了
prisma-next.config.ts,并确定了契约源(以.prisma或.ts结尾的路径字符串)和已安装的extensions: [...]。 - 所有用户编写的导入都解析为
@prisma-next/<target>/<subpath>(例如@prisma-next/postgres/config)或@prisma-next/extension-<name>/<subpath>。用户文件中没有从@prisma-next/cli/*、@prisma-next/family-*、@prisma-next/target-*、@prisma-next/adapter-*、@prisma-next/driver-*或@prisma-next/sql-contract-*导入。 - 编辑的是契约源(
contract.prisma或contract.ts),而非生成的产物。 - 对于新的扩展命名空间:已添加包,导入其控制描述符(
@prisma-next/extension-<name>/control),将其添加到defineConfig({...})中的extensions: [...](若使用 TS 构建器,还需将匹配的 pack 描述符添加到defineContract({extensions: {...}}))。 - 对于重命名:在运行
migration plan后手动编辑了migration.ts(或使用先保留再删除的双迁移模式)——Prisma Next 目前没有重命名提示。 - 编辑后运行了
pnpm prisma-next contract emit(或让 Vite 插件在保存时重新生成)。 - 确认
contract.json和contract.d.ts已在源文件旁更新。 - 没有手动编辑
contract.json/contract.d.ts。 - 没有杜撰缺失的功能(验证、回调、软删除、作用域、契约内重命名提示)——已将用户引导至 Prisma Next 目前尚未实现的功能 和
prisma-next-feedback。