prisma-next-migrations

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Prisma Next — Migration Authoring

Prisma Next — 迁移编写

Edit your data contract. Prisma Next plans the migration. You fill in any data transforms.
The three-step user model:
  1. You edit your data contract. (
    prisma-next-contract
    )
  2. Prisma Next plans the migration for you. ← this skill
  3. If a data transform is needed, you edit
    migration.ts
    and self-emit.
    ← this skill
Once the contract changes, you choose how the change reaches the database. This skill covers the two paths (
db update
and
migration plan
+
migrate
), the migration-package contract, the
migration.ts
authoring API, and the failure modes you recover from without leaving the loop.
编辑你的数据契约。Prisma Next为你规划迁移。你只需填充必要的数据转换逻辑。
三步用户模型:
  1. 你编辑数据契约
    prisma-next-contract
  2. Prisma Next为你规划迁移 ← 本技能覆盖内容
  3. 若需要数据转换,你编辑
    migration.ts
    并自行生成(self-emit)
    ← 本技能覆盖内容
契约变更后,你可以选择将变更应用到数据库的方式。本技能涵盖两种路径(
db update
migration plan
+
migrate
)、迁移包契约、
migration.ts
编写API,以及无需跳出流程即可恢复的故障模式。

When to Use

适用场景

  • User edited the contract and wants to apply the change to the DB.
  • User wants to author a migration with a data transform.
  • User wants to run pending migrations against a local DB.
  • User hit
    MIGRATION.HASH_MISMATCH
    ,
    PN-MIG-2001
    (unfilled placeholder), or a partially-applied migration.
  • User mentions: migrate, migration, db push, db update,
    prisma migrate dev
    ,
    prisma migrate deploy
    , drift, hash mismatch, data backfill
    .
  • 用户编辑了契约,想要将变更应用到数据库。
  • 用户想要编写包含数据转换的迁移。
  • 用户想要在本地数据库上运行待处理的迁移。
  • 用户遇到
    MIGRATION.HASH_MISMATCH
    PN-MIG-2001
    (未填充占位符)或部分应用的迁移故障。
  • 用户提及:migrate、migration、db push、db update、
    prisma migrate dev
    prisma migrate deploy
    、drift、hash mismatch、data backfill。

When Not to Use

不适用场景

  • User wants to know what migrations will run on deploy / on merge, or to manage refs and invariants →
    prisma-next-migration-review
    .
  • User wants to edit the contract →
    prisma-next-contract
    .
  • User wants a deeper read of a single structured error envelope →
    prisma-next-debug
    .
  • 用户想了解部署/合并时将运行哪些迁移,或管理引用和不变量 → 使用
    prisma-next-migration-review
  • 用户想编辑契约 → 使用
    prisma-next-contract
  • 用户想深入解读单个结构化错误包 → 使用
    prisma-next-debug

Key Concepts

核心概念

  • db update
    (quick path).
    Reads the emitted contract, diffs against the live DB, applies the change. Optional
    --dry-run
    prints the plan without executing. Interactive destructive-op confirmation (or
    -y
    to auto-accept). Writes no migration directory. Operations needing data transforms are not handled by this path —
    db update
    excludes the
    data
    operation class entirely and short-circuits where a data transform would be required. Use only against a database that has no shared history with anyone else (your local dev DB).
  • migration plan
    (formal path).
    Reads the emitted contract, diffs against the head of the on-disk migration graph, writes a new migration package under
    migrations/app/<YYYYMMDDTHHMM>_<snake_slug>/
    . If any operation needs a data transform, the package's
    migration.ts
    contains
    placeholder(...)
    calls you fill in.
  • The
    app/
    segment in migration paths is the consuming application's contract-space id.
    Every migration you author lives under
    migrations/app/
    . Extensions your contract depends on get their own sibling directories (
    migrations/<extension-space-id>/
    ) — those are managed by the extension package and you don't write into them. The
    app/
    segment lands automatically the first time you run
    migration plan
    /
    db init
    against an app-level config.
  • Migration package files (inside each
    migrations/app/<dir>/
    ):
    • migration.json
      — manifest (metadata +
      migrationHash
      ).
    • ops.json
      — canonical operation list. Content-addressed;
      migrationHash
      is computed over this.
    • end-contract.json
      and
      end-contract.d.ts
      — the contract this migration ends at, imported by
      migration.ts
      for type-safe data transforms.
    • migration.ts
      — TypeScript authoring source, framework-rendered by
      migration plan
      (or
      migration new
      ). You edit specific holes in it (see Fill a placeholder below) and re-emit
      ops.json
      /
      migration.json
      by running it.
  • Self-emit. Running
    node migrations/app/<dir>/migration.ts
    regenerates
    ops.json
    and
    migration.json
    from the (possibly edited) TS source. This is the only supported way to update an existing migration package after edits.
  • migration.ts
    shape.
    Framework-rendered. A class extending
    Migration
    (re-exported by
    @prisma-next/target-postgres/migration
    in the rendered import line — see the framing block below), with an
    operations
    getter that returns an array of factory-call values. The file ends with
    MigrationCLI.run(import.meta.url, M)
    so executing it self-emits.
  • placeholder(slot)
    .
    A sentinel the planner emits into the rendered
    migration.ts
    (imported from
    @prisma-next/target-postgres/migration
    on the framework-managed import line) wherever a data transform is needed. Calling
    placeholder(...)
    at emit time throws
    PN-MIG-2001
    Unfilled migration placeholder. The user replaces the
    () => placeholder(...)
    arrow with a real query-plan closure, then self-emits.
  • this.dataTransform(endContract, name, { check, run })
    .
    The data-transform factory.
    check
    is a rowset query whose presence-of-any-row signals "work remains";
    run
    is one or more mutation queries that perform the backfill. Both are lazy closures returning query-plans built against
    endContract
    . The runner wraps
    check
    as
    EXISTS(...)
    for precheck and
    NOT EXISTS(...)
    for postcheck, so the same closure asserts both "there is work" and "the work is done".
  • pendingPlaceholders
    .
    A boolean field on the JSON result of
    migration plan
    .
    true
    means the package was written but contains unfilled placeholders —
    migrate
    will throw
    PN-MIG-2001
    until you edit
    migration.ts
    and self-emit.
  • migrationHash
    .
    Content-addressed identity of a migration package.
    MIGRATION.HASH_MISMATCH
    fires when the stored hash in
    migration.json
    disagrees with the hash recomputed from the on-disk files (almost always: someone edited
    migration.ts
    without self-emitting).
  • Marker. A single row in the
    prisma_contract.marker
    table that records "this database is at contract hash X for space Y". Each successful migration advances the marker as part of the same transaction as the DDL.
    db sign
    writes the marker from the current contract hash, but only after a schema-verification pass succeeds (it will not sign a database whose live schema disagrees with the contract).
  • Apply runs in a transaction. Each migration runs inside
    BEGIN ... COMMIT
    . On any failure mid-migration, Postgres rolls the migration back; the marker stays at the previous migration's
    to
    hash. The database is not left in a half-applied state for ordinary DDL + data-transform sequences.
  • Operation classes. Every operation declares an
    operationClass
    :
    additive
    ,
    widening
    ,
    data
    , or
    destructive
    . The CLI surfaces these in the plan preview and in JSON output. There is no
    long-running
    class and the framework does not emit
    CREATE INDEX CONCURRENTLY
    — operations stay transactional.
  • db update
    (快速路径)
    :读取生成的契约,与实时数据库对比差异,应用变更。可选
    --dry-run
    参数可打印计划但不执行。对破坏性操作会进行交互式确认(或使用
    -y
    自动确认)。不会生成迁移目录。需要数据转换的操作不会通过此路径处理——
    db update
    完全排除
    data
    操作类,在需要数据转换时直接终止。仅适用于无共享历史的数据库(如你的本地开发数据库)。
  • migration plan
    (正式路径)
    :读取生成的契约,与磁盘上迁移图的最新版本对比差异,在
    migrations/app/<YYYYMMDDTHHMM>_<snake_slug>/
    下生成新的迁移包。若任何操作需要数据转换,包内的
    migration.ts
    会包含
    placeholder(...)
    调用,需你自行填充。
  • 迁移路径中的
    app/
    段是消费应用的契约空间ID
    :你编写的所有迁移都位于
    migrations/app/
    下。你的契约依赖的扩展会有自己的同级目录(
    migrations/<extension-space-id>/
    )——这些由扩展包管理,你无需写入。首次针对应用级配置运行
    migration plan
    /
    db init
    时,
    app/
    段会自动生成。
  • 迁移包文件(每个
    migrations/app/<dir>/
    目录下):
    • migration.json
      — 清单文件(元数据 +
      migrationHash
      )。
    • ops.json
      — 标准操作列表,基于内容寻址;
      migrationHash
      通过此文件计算得出。
    • end-contract.json
      end-contract.d.ts
      — 迁移最终达成的契约,供
      migration.ts
      导入以实现类型安全的数据转换。
    • migration.ts
      — TypeScript编写源文件,由
      migration plan
      (或
      migration new
      框架生成。你需要编辑其中特定的空白部分(见下文「填充占位符」),并通过运行该文件重新生成
      ops.json
      /
      migration.json
  • 自行生成(Self-emit):运行
    node migrations/app/<dir>/migration.ts
    会根据(可能已编辑的)TS源文件重新生成
    ops.json
    migration.json
    。这是编辑后更新现有迁移包的唯一支持方式。
  • migration.ts
    结构
    :由框架生成。一个继承自
    Migration
    的类(在生成的导入行中从
    @prisma-next/target-postgres/migration
    重新导出——见下方框架代码块),包含一个
    operations
    getter,返回工厂调用值的数组。文件末尾包含
    MigrationCLI.run(import.meta.url, M)
    ,执行时会自行生成文件。
  • placeholder(slot)
    :当需要数据转换时,规划器会在生成的
    migration.ts
    中插入的标记(从框架管理的导入行中的
    @prisma-next/target-postgres/migration
    导入)。在生成时调用
    placeholder(...)
    会抛出
    PN-MIG-2001
    未填充迁移占位符错误。用户需要将
    () => placeholder(...)
    箭头函数替换为真实的查询计划闭包,然后自行生成。
  • this.dataTransform(endContract, name, { check, run })
    :数据转换工厂。
    check
    是一个行集查询,只要存在任何行就表示「仍有工作待完成」;
    run
    是一个或多个执行回填的突变查询。两者都是返回基于
    endContract
    构建的查询计划的延迟闭包。运行器会将
    check
    包装为
    EXISTS(...)
    用于预检查,包装为
    NOT EXISTS(...)
    用于后检查,因此同一个闭包可同时断言「存在待处理工作」和「工作已完成」。
  • pendingPlaceholders
    migration plan
    的JSON结果中的布尔字段。
    true
    表示迁移包已生成但包含未填充的占位符——在你编辑
    migration.ts
    并自行生成之前,
    migrate
    会抛出
    PN-MIG-2001
    错误。
  • migrationHash
    :迁移包的内容寻址标识。当
    migration.json
    中存储的哈希与从磁盘文件重新计算的哈希不一致时,会触发
    MIGRATION.HASH_MISMATCH
    (几乎总是因为有人编辑了
    migration.ts
    但未自行生成)。
  • 标记(Marker)
    prisma_contract.marker
    表中的单行记录,用于记录「此数据库在空间Y下的契约哈希为X」。每次成功的迁移都会在同一事务中更新标记,作为DDL操作的一部分。
    db sign
    会从当前契约哈希写入标记,但仅在架构验证通过后执行(如果实时架构与契约不一致,不会签署数据库)。
  • 事务中应用:每个迁移都在
    BEGIN ... COMMIT
    事务中运行。迁移过程中任何失败都会触发Postgres回滚;标记会保留在之前迁移的
    to
    哈希值。对于普通DDL + 数据转换序列,数据库不会处于部分应用的状态。
  • 操作类:每个操作都会声明一个
    operationClass
    additive
    widening
    data
    destructive
    。CLI会在计划预览和JSON输出中显示这些类型。没有
    long-running
    类,框架也不会生成
    CREATE INDEX CONCURRENTLY
    ——操作始终保持事务性。

migration.ts
is framework-rendered, not hand-authored

migration.ts
由框架生成,而非手动编写

Files under
migrations/<space-id>/<timestamp>/migration.ts
(for your own app,
<space-id>
is always
app/
) are rendered for you by the framework —
prisma-next migration plan
writes a populated package whenever the contract changes, and
prisma-next migration new
writes an empty scaffold when you want to author operations directly. You do not write these files from scratch. You edit specific holes the framework leaves behind — chiefly replacing
placeholder("<slot>")
sentinels with real
this.dataTransform({ check, run })
closures — then self-emit.
The imports at the top of the rendered file currently point at
@prisma-next/target-postgres/migration
. The user-facing
@prisma-next/postgres
façade does not currently re-export this surface, so the rendered import deliberately reaches into the target package directly. Linear ticket TML-2526 tracks closing that gap; once it lands, the renderer (and this skill) will switch to
@prisma-next/postgres/migration
in one step.
Until then, treat the rendered import line as framework-managed:
  • Leave it where it is. Don't rewrite it to a different
    @prisma-next/<…>
    path; the framework's renderer is the authoritative shape and any change you make by hand will be reverted (and may trip
    MIGRATION.HASH_MISMATCH
    ) the next time the package is re-rendered or self-emitted.
  • If you need an additional symbol (e.g.
    dataTransform
    ,
    setNotNull
    ,
    rawSql
    ) to fill in a placeholder, add it to the existing rendered import line rather than introducing a second import from a different
    @prisma-next/...
    subpath.
  • The "user code imports only from
    @prisma-next/<target>
    " convention applies to your own modules (queries, runtime setup, contract authoring). The framework-rendered
    migration.ts
    scaffold is the framework's surface, not yours; the rule is suspended for that one file.
migrations/<space-id>/<timestamp>/migration.ts
下的文件(对于你自己的应用,
<space-id>
始终为
app/
)由框架为你生成——当契约变更时,
prisma-next migration plan
会生成一个填充好的迁移包;当你想直接编写操作时,
prisma-next migration new
会生成一个空的脚手架。你无需从头编写这些文件。只需编辑框架留下的特定空白部分——主要是将
placeholder("<slot>")
标记替换为真实的
this.dataTransform({ check, run })
闭包——然后自行生成。
生成文件顶部的导入目前指向
@prisma-next/target-postgres/migration
。面向用户的
@prisma-next/postgres
门面目前并未重新导出此接口,因此生成的导入会直接指向目标包。Linear工单TML-2526跟踪此问题的修复;修复完成后,生成器(以及本技能)会一次性切换为
@prisma-next/postgres/migration
在此之前,请将生成的导入行视为框架管理的内容:
  • 保持原样。不要将其重写为其他
    @prisma-next/<…>
    路径;框架生成器是权威来源,你手动进行的任何更改都会在下次重新生成或自行生成包时被还原(可能会触发
    MIGRATION.HASH_MISMATCH
    )。
  • 若需要额外的符号(如
    dataTransform
    setNotNull
    rawSql
    )来填充占位符,请添加到现有的生成导入行中,而非从其他
    @prisma-next/...
    子路径引入第二个导入。
  • 「用户代码仅从
    @prisma-next/<target>
    导入」的约定适用于你自己的模块(查询、运行时设置、契约编写)。框架生成的
    migration.ts
    脚手架是框架的接口,而非你的;此规则对此文件不适用。

Diagnostic codes you route on

需处理的诊断代码

CodeSourceMove
PN-MIG-2001
Unfilled migration placeholder
Throwing
placeholder(...)
at emit time
Open
migration.ts
, replace the named
placeholder("<slot>")
call with the real query closure, self-emit.
PN-MIG-2002
migration.ts not found
Reading a migration packageThe package is malformed. Recover from version control, or run
prisma-next migration new
for a fresh one.
PN-MIG-2003
invalid default export
Loading
migration.ts
The file's default export is not a
Migration
subclass or factory function. Restore the planner-emitted scaffold from version control or re-run
migration plan
for a clean package.
PN-MIG-2005
dataTransform contract mismatch
Building a data-transform query planThe query builder was instantiated with a contract reference different from the
endContract
passed to
this.dataTransform(...)
. Use the
endContract
imported at module scope for both.
MIGRATION.HASH_MISMATCH
Migration package is corrupt
migrate
(or any read of the package)
ops.json
/
migration.json
were edited without self-emitting. Run
node migrations/app/<dir>/migration.ts
to re-emit, then re-apply.
PN-RUN-3002
Hash mismatch
db verify
The marker in
prisma_contract.marker
disagrees with the contract hash. The DB is at a different contract version than the code thinks. Either run a migration forward, or — if the DB is correct and the marker is stale after a manual fix-up — run
db sign
.
PN-RUN-3001
Database not signed
Any command needing a markerThe DB has no marker yet. Run
prisma-next db init --db <url>
to baseline an empty database, or
db update --db <url>
to apply the current contract directly.
代码来源处理方式
PN-MIG-2001
未填充迁移占位符
生成时调用
placeholder(...)
抛出
打开
migration.ts
,将指定的
placeholder("<slot>")
调用替换为真实的查询闭包,然后自行生成。
PN-MIG-2002
未找到migration.ts
读取迁移包时迁移包已损坏。从版本控制恢复,或运行
prisma-next migration new
生成新的包。
PN-MIG-2003
无效默认导出
加载
migration.ts
文件的默认导出不是
Migration
子类或工厂函数。从版本控制恢复规划器生成的脚手架,或重新运行
migration plan
获取干净的包。
PN-MIG-2005
dataTransform契约不匹配
构建数据转换查询计划时查询构建器使用的契约引用与传递给
this.dataTransform(...)
endContract
不一致。使用模块作用域导入的
endContract
进行统一处理。
MIGRATION.HASH_MISMATCH
迁移包已损坏
migrate
(或任何读取包的操作)
ops.json
/
migration.json
被编辑但未自行生成。运行
node migrations/app/<dir>/migration.ts
重新生成,然后重新应用。
PN-RUN-3002
哈希不匹配
db verify
prisma_contract.marker
中的标记与契约哈希不一致。数据库的契约版本与代码预期不符。要么向前运行迁移,要么——如果数据库正确且标记在手动修复后过期——运行
db sign
PN-RUN-3001
数据库未签署
任何需要标记的命令数据库尚无标记。运行
prisma-next db init --db <url>
为空白数据库建立基线,或运行
db update --db <url>
直接应用当前契约。

Decision — which path do you take?

决策——选择哪种路径?

SituationPathWhy
Local dev, schema in flux
db update
Fast, interactive, no migration files.
Shared branch with other developers
migration plan
+
apply
Replayable, reviewable, content-hashed.
Anything reaching production
migration plan
+
apply
Production must run a reviewed, hashed migration.
Adding a column that needs a backfill
migration plan
(writes
placeholder
), edit
migration.ts
, self-emit, then
migrate
db update
does not author data transforms; the formal path does.
Recovering from drift (DB diverged from contract)
db sign
after manual fix, or
migration plan
if PN can plan the fix
Depends on which side is right. See Recover from drift below.
场景路径原因
本地开发,架构频繁变更
db update
快速、交互式,无迁移文件。
与其他开发者共享分支
migration plan
+
apply
可重放、可审核、基于内容哈希。
任何涉及生产环境的操作
migration plan
+
apply
生产环境必须运行经过审核、带哈希的迁移。
添加需要回填的列
migration plan
(生成
placeholder
),编辑
migration.ts
,自行生成,然后
migrate
db update
不支持编写数据转换;正式路径支持。
从架构漂移(数据库与契约不一致)中恢复手动修复后运行
db sign
如果PN可以规划修复则运行
migration plan
取决于哪一方是正确的。见下文「从架构漂移中恢复」。

Workflow —
db update
(quick path)

工作流——
db update
(快速路径)

The concept:
db update
resolves the destination (
emitted contract
) against the live DB and applies the difference. Preview with
--dry-run
. Destructive ops prompt interactively unless you pass
-y
or
--no-interactive
. The path excludes operations of the
data
class entirely — if the diff requires a data transform,
db update
fails with a planning error and you switch to
migration plan
to author the transform.
Run after a contract edit:
bash
pnpm prisma-next contract emit
pnpm prisma-next db update --db $DATABASE_URL --dry-run
pnpm prisma-next db update --db $DATABASE_URL
pnpm prisma-next db verify --db $DATABASE_URL
Inspect the JSON output to drive the next move:
bash
pnpm prisma-next db update --db $DATABASE_URL --json
The JSON contains
plan.operations[]
with each
operationClass
, plus (in apply mode)
execution.operationsExecuted
and the post-apply
marker.storageHash
. If the command failed because of destructive operations, the error envelope's
meta.destructiveOperations[]
lists exactly what would have been dropped.
核心逻辑:
db update
将目标(生成的契约)与实时数据库对比,应用差异。使用
--dry-run
预览。破坏性操作会进行交互式提示,除非你传递
-y
--no-interactive
。此路径完全排除
data
类操作——如果差异需要数据转换,
db update
会因规划错误失败,你需要切换到
migration plan
编写转换逻辑。
契约编辑后运行:
bash
pnpm prisma-next contract emit
pnpm prisma-next db update --db $DATABASE_URL --dry-run
pnpm prisma-next db update --db $DATABASE_URL
pnpm prisma-next db verify --db $DATABASE_URL
查看JSON输出以指导下一步操作:
bash
pnpm prisma-next db update --db $DATABASE_URL --json
JSON包含
plan.operations[]
,每个操作带有
operationClass
,此外(在应用模式下)还包含
execution.operationsExecuted
和应用后的
marker.storageHash
。如果命令因破坏性操作失败,错误包的
meta.destructiveOperations[]
会列出将被删除的内容。

Workflow —
migration plan
+
apply
(formal path)

工作流——
migration plan
+
apply
(正式路径)

The concept:
migration plan
writes a new migration package on disk. If the planner needed any data transforms, the package is pending
migration.ts
holds
placeholder(...)
calls until you fill them in.
migrate
runs every pending package in graph order, transactionally.
Plan a change:
bash
pnpm prisma-next contract emit
pnpm prisma-next migration plan --name <snake_slug>
Read the result. The JSON shape exposes the queryable signals:
  • dir
    — the path of the new package (e.g.
    migrations/app/20260515T1200_add_user_email/
    ).
  • pendingPlaceholders
    true
    if
    migration.ts
    still contains
    placeholder(...)
    calls.
  • operations[].operationClass
    — for spotting
    destructive
    and
    data
    ops.
  • preview.statements
    — family-agnostic textual preview.
Inspect the package:
bash
pnpm prisma-next migration show
pnpm prisma-next migration show <dirName-or-migrationHash-prefix>
Fill in any data transforms (see Fill a placeholder), self-emit if you edited
migration.ts
, then:
bash
pnpm prisma-next migrate --db $DATABASE_URL
pnpm prisma-next db verify --db $DATABASE_URL
migrate
runs without prompting — destructive-op confirmation lives on
db update
, not here. Review destructive ops in the plan output or in
migration show
before applying.
核心逻辑:
migration plan
在磁盘上生成新的迁移包。如果规划器需要数据转换,包会处于待处理状态——
migration.ts
包含
placeholder(...)
调用,需你填充。
migrate
会按图顺序事务性地运行所有待处理包。
规划变更:
bash
pnpm prisma-next contract emit
pnpm prisma-next migration plan --name <snake_slug>
查看结果。JSON结构包含可查询的信号:
  • dir
    — 新包的路径(例如
    migrations/app/20260515T1200_add_user_email/
    )。
  • pendingPlaceholders
    — 如果
    migration.ts
    仍包含
    placeholder(...)
    调用,则为
    true
  • operations[].operationClass
    — 用于识别
    destructive
    data
    操作。
  • preview.statements
    — 与数据库无关的文本预览。
查看迁移包:
bash
pnpm prisma-next migration show
pnpm prisma-next migration show <dirName-or-migrationHash-prefix>
填充任何数据转换(见「填充占位符」),如果编辑了
migration.ts
则自行生成,然后:
bash
pnpm prisma-next migrate --db $DATABASE_URL
pnpm prisma-next db verify --db $DATABASE_URL
migrate
运行时不会提示——破坏性操作确认仅在
db update
中存在,此处没有。在应用前,请在计划输出或
migration show
中审核破坏性操作。

Workflow — Fill a placeholder

工作流——填充占位符

The concept: the planner can detect that a data transform is needed (e.g. backfilling a new
NOT NULL
column with no default) but not what it should do. It writes a typed scaffold and stops; you fill the check and run closures with real query plans built against
endContract
, then self-emit.
The scaffold the planner emits looks like:
typescript
// migrations/app/20260515T1200_add_user_name/migration.ts
import endContract from './end-contract.json' with { type: 'json' };
import { Migration, MigrationCLI, addColumn, placeholder } from '@prisma-next/target-postgres/migration';

export default class M extends Migration {
  override get operations() {
    return [
      addColumn('public', 'user', {
        name: 'name',
        typeSql: 'text',
        defaultSql: '',
        nullable: true,
      }),
      this.dataTransform(endContract, 'backfill user.name', {
        check: () => placeholder('backfill user.name:check'),
        run:   () => placeholder('backfill user.name:run'),
      }),
    ];
  }
}

MigrationCLI.run(import.meta.url, M);
Replace both
placeholder(...)
calls with query-plan closures built from
endContract
. The
check
closure must return a rowset query whose presence of any row signals "work remains" — conventionally
<table>.select('id').where(<violation predicate>).limit(1)
. Scalar/aggregate shapes (
count(*)
,
bool_and(...)
) silently break the contract: the runner wraps
check
twice (
EXISTS(...)
for precheck,
NOT EXISTS(...)
for postcheck), and a query that always returns one row makes
EXISTS
always true and
NOT EXISTS
always false.
Build the query builder against
endContract
so the storage hashes line up — using a different contract reference raises
PN-MIG-2005
. The filled-in shape (the rendered scaffold above with
placeholder(...)
calls replaced; if you need an extra factory like
setNotNull
, add it to the existing
@prisma-next/target-postgres/migration
import line rather than authoring a second import). See
prisma-next-queries
for the surrounding
db
setup:
typescript
import endContract from './end-contract.json' with { type: 'json' };
import { Migration, MigrationCLI, addColumn, setNotNull } from '@prisma-next/target-postgres/migration';
import { db } from './db'; // sql({ context: createExecutionContext({ contract: endContract, ... }) })

export default class M extends Migration {
  override get operations() {
    return [
      addColumn('public', 'user', {
        name: 'name',
        typeSql: 'text',
        defaultSql: '',
        nullable: true,
      }),
      this.dataTransform(endContract, 'backfill user.name', {
        check: () => db.users.select('id').where((f, fns) => fns.eq(f.name, null)).limit(1),
        run:   () => db.users.update({ name: '' }).where((f, fns) => fns.eq(f.name, null)),
      }),
      setNotNull('public', 'user', 'name'),
    ];
  }
}

MigrationCLI.run(import.meta.url, M);
Self-emit:
bash
node migrations/app/20260515T1200_add_user_name/migration.ts
Self-emit regenerates
ops.json
and recomputes
migrationHash
in
migration.json
. The next
migrate
will see a consistent package.
核心逻辑:规划器可以检测到需要数据转换(例如,回填没有默认值的新
NOT NULL
列),但无法确定具体如何转换。它会生成一个类型化的脚手架并停止;你需要使用基于
endContract
构建的真实查询计划填充
check
run
闭包,然后自行生成。
规划器生成的脚手架如下:
typescript
// migrations/app/20260515T1200_add_user_name/migration.ts
import endContract from './end-contract.json' with { type: 'json' };
import { Migration, MigrationCLI, addColumn, placeholder } from '@prisma-next/target-postgres/migration';

export default class M extends Migration {
  override get operations() {
    return [
      addColumn('public', 'user', {
        name: 'name',
        typeSql: 'text',
        defaultSql: '',
        nullable: true,
      }),
      this.dataTransform(endContract, 'backfill user.name', {
        check: () => placeholder('backfill user.name:check'),
        run:   () => placeholder('backfill user.name:run'),
      }),
    ];
  }
}

MigrationCLI.run(import.meta.url, M);
将两个
placeholder(...)
调用替换为基于
endContract
构建的查询计划闭包。
check
闭包必须返回行集查询,只要存在任何行就表示「仍有工作待完成」——通常为
<table>.select('id').where(<violation predicate>).limit(1)
。标量/聚合形状(如
count(*)
bool_and(...)
)会静默破坏契约:运行器会将
check
包装两次(
EXISTS(...)
用于预检查,
NOT EXISTS(...)
用于后检查),始终返回一行的查询会导致
EXISTS
始终为真,
NOT EXISTS
始终为假。
基于
endContract
构建查询构建器,确保存储哈希一致——使用不同的契约引用会触发
PN-MIG-2005
。填充后的结构(将上述生成的脚手架中的
placeholder(...)
调用替换;如果需要额外的工厂如
setNotNull
,请添加到现有
@prisma-next/target-postgres/migration
导入行中,而非引入第二个导入)。有关
db
设置的详细信息,请查看
prisma-next-queries
typescript
import endContract from './end-contract.json' with { type: 'json' };
import { Migration, MigrationCLI, addColumn, setNotNull } from '@prisma-next/target-postgres/migration';
import { db } from './db'; // sql({ context: createExecutionContext({ contract: endContract, ... }) })

export default class M extends Migration {
  override get operations() {
    return [
      addColumn('public', 'user', {
        name: 'name',
        typeSql: 'text',
        defaultSql: '',
        nullable: true,
      }),
      this.dataTransform(endContract, 'backfill user.name', {
        check: () => db.users.select('id').where((f, fns) => fns.eq(f.name, null)).limit(1),
        run:   () => db.users.update({ name: '' }).where((f, fns) => fns.eq(f.name, null)),
      }),
      setNotNull('public', 'user', 'name'),
    ];
  }
}

MigrationCLI.run(import.meta.url, M);
自行生成:
bash
node migrations/app/20260515T1200_add_user_name/migration.ts
自行生成会重新生成
ops.json
并重新计算
migration.json
中的
migrationHash
。下次
migrate
会识别到一致的迁移包。

Workflow — Author a migration by hand

工作流——手动编写迁移

The concept: the same
Migration
class shape lets you author operations directly when the planner has nothing to plan (a custom data fix, an extension install, a baseline). Even here you don't write the file from scratch —
migration new
renders an empty package for you, and you edit the
operations
getter inside it, then self-emit.
bash
pnpm prisma-next migration new --name <snake_slug>
The factories you can call are re-exported through the same framework-rendered
@prisma-next/target-postgres/migration
import line — add the names you need to that line rather than introducing a second import. Categories (browse with
--help
on the command and by reading the import list):
  • Tables:
    createTable
    ,
    dropTable
    .
  • Columns:
    addColumn
    ,
    dropColumn
    ,
    alterColumnType
    ,
    setNotNull
    ,
    dropNotNull
    ,
    setDefault
    ,
    dropDefault
    .
  • Constraints:
    addPrimaryKey
    ,
    addForeignKey
    ,
    addUnique
    ,
    dropConstraint
    .
  • Indexes:
    createIndex
    ,
    dropIndex
    .
  • Enums:
    createEnumType
    ,
    addEnumValues
    ,
    renameType
    ,
    dropEnumType
    .
  • Dependencies:
    createSchema
    ,
    createExtension
    ,
    installExtension
    .
  • Raw escape hatch:
    rawSql({ id, label, operationClass, target, precheck, execute, postcheck, ... })
    .
  • Data transforms:
    this.dataTransform(endContract, name, { check, run })
    (instance method, not a free factory).
Self-emit (
node migrations/app/<dir>/migration.ts
) after each edit.
核心逻辑:相同的
Migration
类结构允许你在规划器无内容可规划时直接编写操作(如自定义数据修复、扩展安装、基线设置)。即使在此场景下,你也无需从头编写文件——
migration new
会为你生成一个空包,你只需编辑其中的
operations
getter,然后自行生成。
bash
pnpm prisma-next migration new --name <snake_slug>
你可以调用的工厂函数通过相同的框架生成
@prisma-next/target-postgres/migration
导入行重新导出——请将所需的名称添加到该行中,而非引入第二个导入。分类(可通过命令的
--help
或查看导入列表浏览):
  • 表:
    createTable
    dropTable
  • 列:
    addColumn
    dropColumn
    alterColumnType
    setNotNull
    dropNotNull
    setDefault
    dropDefault
  • 约束:
    addPrimaryKey
    addForeignKey
    addUnique
    dropConstraint
  • 索引:
    createIndex
    dropIndex
  • 枚举:
    createEnumType
    addEnumValues
    renameType
    dropEnumType
  • 依赖:
    createSchema
    createExtension
    installExtension
  • 原生SQL出口:
    rawSql({ id, label, operationClass, target, precheck, execute, postcheck, ... })
  • 数据转换:
    this.dataTransform(endContract, name, { check, run })
    (实例方法,而非自由工厂)。
每次编辑后自行生成(
node migrations/app/<dir>/migration.ts
)。

Workflow — Inspect the live schema

工作流——查看实时架构

The concept:
db schema
is read-only and never writes files. It prints the live schema as a tree by default or as JSON with
--json
. Use it during planning and as part of verification.
bash
pnpm prisma-next db schema --db $DATABASE_URL
pnpm prisma-next db schema --db $DATABASE_URL --json > schema.json
There is no built-in filter flag — pipe the JSON through
jq
(or your favourite JSON tool) if you only want one table.
核心逻辑:
db schema
是只读命令,不会写入文件。默认以树形结构打印实时架构,使用
--json
参数可输出JSON格式。可在规划和验证阶段使用。
bash
pnpm prisma-next db schema --db $DATABASE_URL
pnpm prisma-next db schema --db $DATABASE_URL --json > schema.json
没有内置的过滤标志——如果只需要单个表,请将JSON通过
jq
(或你喜欢的JSON工具)处理。

Workflow — Verify contract vs DB

工作流——验证契约与数据库

The concept:
db verify
compares the live schema and the marker against the contract. Three modes:
  • Default — full verification (schema + marker).
  • --marker-only
    — skip schema verification, only check the marker.
  • --schema-only
    — skip marker verification, only check schema satisfies contract.
  • --strict
    adds: schema elements not present in the contract are an error (default is "DB may have extras").
bash
pnpm prisma-next db verify --db $DATABASE_URL
On mismatch, the error envelope names the failure mode (
PN-RUN-3002
hash mismatch,
PN-RUN-3001
marker missing, target mismatch, schema issues with structured paths). Run after any manual fix or any
apply
.
核心逻辑:
db verify
会将实时架构标记与契约进行对比。三种模式:
  • 默认 — 完整验证(架构 + 标记)。
  • --marker-only
    — 跳过架构验证,仅检查标记。
  • --schema-only
    — 跳过标记验证,仅检查架构是否符合契约。
  • --strict
    模式新增:架构中存在契约未包含的元素时视为错误(默认是「数据库可以有额外元素」)。
bash
pnpm prisma-next db verify --db $DATABASE_URL
不匹配时,错误包会指明失败模式(
PN-RUN-3002
哈希不匹配、
PN-RUN-3001
标记缺失、目标不匹配、带结构化路径的架构问题)。在任何手动修复或
apply
操作后运行此命令。

Workflow — Re-sign the marker

工作流——重新签署标记

The concept:
db sign
rewrites the marker to the current contract hash. Use after a manual repair where the DB is the source of truth and the marker is stale.
db sign
performs a schema-verify first and refuses to sign a DB whose schema disagrees with the contract — so a successful sign always means the schema matches and the marker is now correct.
bash
pnpm prisma-next db sign --db $DATABASE_URL
核心逻辑:
db sign
会将标记重写为当前契约哈希。适用于手动修复后,数据库为可信源但标记过期的场景。
db sign
会先执行架构验证,拒绝签署架构与契约不一致的数据库——因此成功签署意味着架构匹配且标记已正确更新。
bash
pnpm prisma-next db sign --db $DATABASE_URL

Workflow — Recover from drift

工作流——从架构漂移中恢复

The concept: drift means
db verify
reports the live DB schema doesn't match what the marker says it should be. Two valid moves, picked by which side is correct:
  • The contract is right; the DB is wrong → run a migration. Either
    db update
    (quick path, dev DB only) or
    migration plan
    +
    apply
    (everywhere else).
  • The DB is right; the contract or marker is wrong → edit the contract to match the DB (see
    prisma-next-contract
    ), emit, then
    db sign
    to refresh the marker.
The diagnostic that reveals which side is right:
bash
pnpm prisma-next db schema --db $DATABASE_URL --json
pnpm prisma-next db verify --db $DATABASE_URL --json
Re-verify after either branch. Stop when
db verify
returns
ok
with no diagnostics.
核心逻辑:架构漂移指
db verify
报告实时数据库架构与标记所示的预期架构不一致。有两种有效操作,取决于哪一方是正确的:
  • 契约正确;数据库错误 → 运行迁移。可选择
    db update
    (快速路径,仅适用于开发数据库)或
    migration plan
    +
    apply
    (其他场景)。
  • 数据库正确;契约或标记错误 → 编辑契约以匹配数据库(见
    prisma-next-contract
    ),生成契约,然后运行
    db sign
    刷新标记。
可通过以下命令判断哪一方正确:
bash
pnpm prisma-next db schema --db $DATABASE_URL --json
pnpm prisma-next db verify --db $DATABASE_URL --json
无论选择哪种分支,恢复后都需重新验证。直到
db verify
返回
ok
且无诊断信息为止。

Workflow — Recover from a partially-applied migration

工作流——从部分应用的迁移中恢复

The concept: each migration applies transactionally, so a mid-migration failure rolls back to the previous successful migration. The marker stays at the previous migration's
to
hash. The diagnostic move is to verify state, fix the failed migration's
migration.ts
, self-emit, and re-apply.
Failures that can leak partial state are limited to: explicit
rawSql(...)
operations that step outside a transaction (e.g. inside an
execute
step that runs against an autocommit driver session), or external side-effects (calls out to other systems from a
run
closure). For ordinary DDL +
this.dataTransform(...)
flows the runner's transaction wrap keeps the database consistent.
Diagnose:
bash
pnpm prisma-next db verify --db $DATABASE_URL --json
pnpm prisma-next db schema --db $DATABASE_URL --json
Fix and re-apply:
bash
node migrations/app/<dir>/migration.ts
pnpm prisma-next migrate --db $DATABASE_URL
If the failure was an out-of-band side-effect that left external systems half-changed, repair those by hand before re-applying.
核心逻辑:每个迁移都在事务中应用,因此迁移过程中的失败会回滚到上一次成功的迁移状态。标记会保留在上一次迁移的
to
哈希值。诊断步骤是验证状态,修复失败迁移的
migration.ts
,自行生成,然后重新应用。
可能导致部分状态泄露的失败仅限于:显式的
rawSql(...)
操作跳出事务(例如,在针对自动提交驱动会话运行的
execute
步骤中),或外部副作用(从
run
闭包调用其他系统)。对于普通DDL +
this.dataTransform(...)
流程,运行器的事务包装会保持数据库一致性。
诊断:
bash
pnpm prisma-next db verify --db $DATABASE_URL --json
pnpm prisma-next db schema --db $DATABASE_URL --json
修复并重新应用:
bash
node migrations/app/<dir>/migration.ts
pnpm prisma-next migrate --db $DATABASE_URL
如果失败是由外部系统的副作用导致其处于半变更状态,请在重新应用前手动修复这些系统。

Workflow — Recover from
MIGRATION.HASH_MISMATCH

工作流——从
MIGRATION.HASH_MISMATCH
中恢复

The concept:
migrationHash
is content-addressed. A mismatch means
migration.json
's stored hash disagrees with the hash recomputed from
ops.json
(and metadata). The cause is almost always: someone edited
migration.ts
and forgot to self-emit. The remediation is to self-emit the offending package.
bash
node migrations/app/<dir>/migration.ts
pnpm prisma-next migrate --db $DATABASE_URL
If self-emit itself fails (e.g. the contract has moved on and the operations no longer make sense against
end-contract.json
), the package is stale. Either restore it from version control or delete it and re-plan with
migration plan
.
核心逻辑:
migrationHash
是基于内容寻址的。不匹配意味着
migration.json
中存储的哈希与从
ops.json
(和元数据)重新计算的哈希不一致。原因几乎总是:有人编辑了
migration.ts
但忘记自行生成。修复方法是自行生成有问题的迁移包。
bash
node migrations/app/<dir>/migration.ts
pnpm prisma-next migrate --db $DATABASE_URL
如果自行生成本身失败(例如,契约已变更,操作不再与
end-contract.json
匹配),则迁移包已过期。可从版本控制恢复,或删除后重新运行
migration plan
规划。

Workflow — Resolve a destructive-operation prompt (
db update
only)

工作流——解决破坏性操作提示(仅
db update

The concept: when
db update
would drop columns or tables, it stops and asks before applying. The prompt is
db update
-specific —
migrate
does not prompt and runs whatever the migration package contains, so review the plan or call
migration show
before applying.
When
db update
reports destructive operations interactively, the warning lists them. The prompt is:
Apply destructive changes? This cannot be undone.
Routing:
  • Answer yes if the data is no longer needed.
  • Answer no, then either:
    • Re-shape the migration via
      migration plan
      and hand-edit
      migration.ts
      to preserve the data (e.g. copy-to-new-column, then drop), or
    • Skip the destructive operation by reverting the contract change.
In non-interactive contexts (CI,
--no-interactive
,
--json
), the destructive-op response is returned as a structured error —
meta.destructiveOperations[]
lists what would have been dropped. Re-run with
-y
to auto-accept, or address each operation individually.
核心逻辑:当
db update
将删除列或表时,会停止并询问是否继续。此提示仅针对
db update
——
migrate
不会提示,会直接运行迁移包中的所有操作,因此在应用前请查看计划或调用
migration show
db update
交互式报告破坏性操作时,警告会列出这些操作。提示内容为:
是否应用破坏性变更?此操作不可撤销。
处理方式:
  • 如果数据不再需要,选择是。
  • 如果选择否,可:
    • 通过
      migration plan
      重新规划迁移,并手动编辑
      migration.ts
      以保留数据(例如,复制到新列,然后删除旧列),或
    • 回滚契约变更以跳过破坏性操作。
在非交互式环境(CI、
--no-interactive
--json
)中,破坏性操作的响应会作为结构化错误返回——
meta.destructiveOperations[]
列出将被删除的内容。可添加
-y
参数重新运行以自动确认,或逐个处理每个操作。

Common Pitfalls

常见陷阱

  1. Using
    db update
    against shared or production databases.
    Never. The change leaves no migration history. Use
    migration plan
    +
    apply
    .
  2. Skipping a data transform. Leaving
    placeholder(...)
    in
    migration.ts
    makes the next
    migrate
    throw
    PN-MIG-2001
    . Fill every placeholder slot and self-emit.
  3. Editing
    ops.json
    directly.
    It's the canonical artifact, not the authoring source. Edit
    migration.ts
    , then self-emit.
  4. Forgetting to self-emit after editing
    migration.ts
    .
    The next
    apply
    either uses the stale
    ops.json
    (if you only added comments) or fails with
    MIGRATION.HASH_MISMATCH
    (if you changed operations). Always self-emit.
  5. Aggregate
    check
    closure in
    this.dataTransform
    .
    Returning
    count(*)
    or
    bool_and(...)
    breaks the precheck/postcheck contract — both sides resolve to constants. Use a rowset shape:
    select('id').where(<violation>).limit(1)
    .
  6. Two contract references in one migration. Building a query plan against a different contract than the one passed to
    this.dataTransform(endContract, ...)
    raises
    PN-MIG-2005
    . Always import
    endContract
    once at module scope and use the same reference.
  7. Renaming and expecting the planner to detect it. Prisma Next has no in-contract rename hint today; the planner emits a destructive drop+add. Hand-edit
    migration.ts
    to rewrite the destructive op as a
    rawSql({ ... })
    that issues
    ALTER TABLE ... RENAME COLUMN ...
    (or use the two-migration keep / backfill / drop pattern), then self-emit. See
    prisma-next-contract
    § Edit a field — rename.
  8. Hand-authoring
    migration.ts
    from a blank file, or rewriting the rendered import line.
    Migration files are framework-rendered — let
    prisma-next migration plan
    (or
    migration new
    ) render the package, then edit only the holes the framework leaves for you. The rendered
    @prisma-next/target-postgres/migration
    import is the framework's surface, not a stable user-facing one (TML-2526 tracks moving it to
    @prisma-next/postgres/migration
    ); leave the path alone, and add any extra symbols you need to the existing import line.
  1. 对共享或生产数据库使用
    db update
    :绝对禁止。此变更不会留下迁移历史。请使用
    migration plan
    +
    apply
  2. 跳过数据转换
    migration.ts
    中保留
    placeholder(...)
    会导致下次
    migrate
    抛出
    PN-MIG-2001
    错误。请填充所有占位符并自行生成。
  3. 直接编辑
    ops.json
    :这是标准工件,而非编写源文件。请编辑
    migration.ts
    ,然后自行生成。
  4. 编辑
    migration.ts
    后忘记自行生成
    :下次
    apply
    要么使用过期的
    ops.json
    (如果仅添加了注释),要么因
    MIGRATION.HASH_MISMATCH
    失败(如果更改了操作)。请务必自行生成。
  5. this.dataTransform
    中使用聚合
    check
    闭包
    :返回
    count(*)
    bool_and(...)
    会破坏预检查/后检查契约——两者都会解析为常量。请使用行集形状:
    select('id').where(<violation>).limit(1)
  6. 单个迁移中使用两个契约引用:基于与
    this.dataTransform(endContract, ...)
    不同的契约构建查询计划会触发
    PN-MIG-2005
    。请始终在模块作用域导入一次
    endContract
    并使用相同的引用。
  7. 重命名字段并期望规划器自动检测:Prisma Next目前没有契约内的重命名提示;规划器会生成破坏性的删除+添加操作。请手动编辑
    migration.ts
    ,通过
    rawSql({ ... })
    执行
    ALTER TABLE ... RENAME COLUMN ...
    (或在两次迁移中使用保留/回填/删除模式),然后自行生成。详见
    prisma-next-contract
    § 编辑字段——重命名
  8. 从空白文件手动编写
    migration.ts
    ,或重写生成的导入行
    :迁移文件由框架生成——请让
    prisma-next migration plan
    (或
    migration new
    )生成包,然后仅编辑框架留下的空白部分。生成的
    @prisma-next/target-postgres/migration
    导入是框架的接口,而非稳定的用户接口(TML-2526跟踪将其迁移到
    @prisma-next/postgres/migration
    );请保持路径不变,将所需的额外符号添加到现有导入行中。

What Prisma Next doesn't do yet

Prisma Next目前未支持的功能

  • Runtime-apply migrations. Prisma Next doesn't apply pending migrations from your app's startup code (the "Drizzle pattern" for serverless / edge). Workaround: run
    prisma-next migrate
    from your deploy pipeline before the app starts. If you need runtime-apply built-in, file a feature request via the
    prisma-next-feedback
    skill.
  • Seeds-as-first-class. Prisma Next doesn't ship a
    prisma db seed
    equivalent. Workaround: write a TypeScript script that imports your
    db
    instance and runs your setup queries; invoke it from
    package.json
    's scripts. If you need first-class seeding, file a feature request via the
    prisma-next-feedback
    skill.
  • Migration squashing. Prisma Next doesn't squash older migrations into a baseline. They accumulate; for very large histories, manual baseline-and-truncate is the path. If you need built-in squashing, file a feature request via the
    prisma-next-feedback
    skill.
  • In-contract rename hints. The planner cannot detect that a field rename is a rename rather than a drop+add. Workaround: hand-edit
    migration.ts
    to issue a
    RENAME COLUMN
    via
    rawSql(...)
    , or use a keep / backfill / drop pattern across two migrations. If you need a contract-level rename hint, file a feature request via the
    prisma-next-feedback
    skill.
  • @prisma-next/postgres
    façade re-export of the migration surface.
    The
    @prisma-next/postgres
    package does not yet re-export the migration authoring API (
    Migration
    ,
    MigrationCLI
    ,
    placeholder
    ,
    addColumn
    ,
    setNotNull
    ,
    dataTransform
    , …). The framework-rendered
    migration.ts
    therefore imports from
    @prisma-next/target-postgres/migration
    directly. Workaround: leave the rendered import where it is — it works, it is what the framework emits, and rewriting it breaks
    migrationHash
    round-tripping. Linear ticket TML-2526 tracks closing the gap; once it lands, the renderer will switch and existing files can be migrated by re-running the renderer. If this gap is biting you, file a follow-up via the
    prisma-next-feedback
    skill referencing TML-2526.
  • 运行时应用迁移:Prisma Next不会从应用启动代码中应用待处理的迁移(适用于无服务器/边缘场景的「Drizzle模式」)。解决方法:在部署管道中,应用启动前运行
    prisma-next migrate
    。如果需要内置的运行时应用功能,请通过
    prisma-next-feedback
    技能提交功能请求。
  • 一等公民的种子数据:Prisma Next没有提供类似
    prisma db seed
    的功能。解决方法:编写TypeScript脚本,导入你的
    db
    实例并运行设置查询;从
    package.json
    的脚本中调用。如果需要一等公民的种子数据功能,请通过
    prisma-next-feedback
    技能提交功能请求。
  • 迁移合并:Prisma Next不会将旧迁移合并为基线。迁移会累积;对于非常长的历史记录,手动建立基线并截断是可行的方法。如果需要内置的合并功能,请通过
    prisma-next-feedback
    技能提交功能请求。
  • 契约内重命名提示:规划器无法检测字段重命名是重命名操作,而非删除+添加操作。解决方法:手动编辑
    migration.ts
    ,通过
    rawSql(...)
    执行
    RENAME COLUMN
    ,或在两次迁移中使用保留/回填/删除模式。如果需要契约级别的重命名提示,请通过
    prisma-next-feedback
    技能提交功能请求。
  • @prisma-next/postgres
    门面重新导出迁移接口
    @prisma-next/postgres
    包目前尚未重新导出迁移编写API(
    Migration
    MigrationCLI
    placeholder
    addColumn
    setNotNull
    dataTransform
    等)。因此框架生成的
    migration.ts
    会直接从
    @prisma-next/target-postgres/migration
    导入。解决方法:保持生成的导入不变——它可以正常工作,是框架生成的内容,重写会破坏
    migrationHash
    的往返一致性。Linear工单TML-2526跟踪此问题的修复;修复完成后,生成器会切换,现有文件可通过重新运行生成器进行迁移。如果此问题影响到你,请通过
    prisma-next-feedback
    技能提交跟进请求并引用TML-2526。

Checklist

检查清单

  • Contract emitted (
    contract.json
    +
    contract.d.ts
    current).
  • Chose the right path:
    db update
    (local dev) vs
    migration plan
    +
    apply
    (anything shared).
  • For
    migration plan
    : ran
    migration show
    to review before apply.
  • Filled every
    placeholder(...)
    in
    migration.ts
    (if any), built against
    endContract
    .
  • check
    closures are rowset queries, not scalar aggregates.
  • Self-emitted (
    node migrations/app/<dir>/migration.ts
    ) after editing the TS.
  • Ran
    migrate
    (or
    db update
    ) and saw it complete.
  • Ran
    db verify
    and got an
    ok
    result with no diagnostics.
  • Did NOT use
    db update
    against a shared or production database.
  • Did NOT edit
    ops.json
    directly.
  • Did NOT skip a destructive-op prompt without inspecting
    meta.destructiveOperations[]
    .
  • 契约已生成(
    contract.json
    +
    contract.d.ts
    为最新版本)。
  • 选择了正确的路径:
    db update
    (本地开发) vs
    migration plan
    +
    apply
    (共享环境)。
  • 对于
    migration plan
    :应用前运行了
    migration show
    进行审核。
  • 填充了
    migration.ts
    中的所有
    placeholder(...)
    (如果有),且基于
    endContract
    构建。
  • check
    闭包是行集查询,而非标量聚合。
  • 编辑TS文件后自行生成(
    node migrations/app/<dir>/migration.ts
    )。
  • 运行了
    migrate
    (或
    db update
    )且完成。
  • 运行了
    db verify
    并得到
    ok
    结果且无诊断信息。
  • 未对共享或生产数据库使用
    db update
  • 未直接编辑
    ops.json
  • 未跳过破坏性操作提示而未查看
    meta.destructiveOperations[]
    。",