You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/architecture docs/subsystems/7. Migration System.md
+10-6Lines changed: 10 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -140,7 +140,7 @@ Additive structure is covered by core operations: create table, add nullable col
140
140
141
141
### `migration plan`
142
142
143
-
`prisma-next migration plan` diffs a `from` contract against the current emitted contract and writes one or two attested migration packages. It is fully offline — no database connection. See [ADR 218](../adrs/ADR%20218%20-%20Refs%20with%20paired%20contract%20snapshots%20and%20universal%20graph-node%20invariant.md).
143
+
`prisma-next migration plan` diffs a `from` contract against a `to` contract and writes one or two attested migration packages. It is fully offline — no database connection. See [ADR 218](../adrs/ADR%20218%20-%20Refs%20with%20paired%20contract%20snapshots%20and%20universal%20graph-node%20invariant.md).
@@ -150,16 +150,20 @@ Additive structure is covered by core operations: create table, add nullable col
150
150
151
151
The from-contract materialises from the ref's paired snapshot (ref-resolved `from`) or from a bundle's `end-contract.json` (hash-resolved `from` on a graph node).
152
152
153
+
**Default `to` resolution:** when `--to` is omitted, the destination is the emitted `contract.json`. When `--to <ref-or-hash>` is supplied, the same [contract-reference grammar](#refs-environment-targets) as `--from` applies (hash / prefix, ref name, migration directory, `<dir>^`, or filesystem path); the resolved contract becomes the planner destination and the source of `end-contract.json` / `.d.ts`. Use `--to <migration-dir>^` to plan a reverse (rollback) edge toward a predecessor state.
When `--to` is omitted, `to_contract` is the emitted contract; when `--to` is supplied, `to_contract` is the resolved destination.
166
+
163
167
Plan-time refuse diagnostics name the resolved hash, list refs pointing at graph nodes, and suggest `--from <reachable-ref>`. Snapshot-missing diagnostics suggest `db update --advance-ref <name>` to repopulate or `ref delete <name>` to clear an orphan pointer.
164
168
165
169
## Authoring Surface
@@ -539,7 +543,7 @@ Top-level verbs:
539
543
540
544
Migration namespace (artifacts and graph):
541
545
542
-
-`prisma-next migration plan [--from <contract>] --name <slug>` — diff contracts and write a fully attested package (`migration.ts` + `migration.json` + `ops.json`) offline. Defaults `--from` to the `db` ref (falls back to greenfield when absent). Re-run `./migration.ts` after filling any `placeholder(...)` slots to rewrite `ops.json` and the `migrationHash`.
546
+
-`prisma-next migration plan [--from <contract>] [--to <contract>] --name <slug>` — diff contracts and write a fully attested package (`migration.ts` + `migration.json` + `ops.json`) offline. Defaults `--from` to the `db` ref (falls back to greenfield when absent) and `--to` to the emitted contract. Both flags accept the full [contract-reference grammar](#refs-environment-targets). Re-run `./migration.ts` after filling any `placeholder(...)` slots to rewrite `ops.json` and the `migrationHash`.
543
547
-`prisma-next migration new [--from <hash> --to <hash>] --name <slug>` — scaffold an empty `migration.ts` for hand-authoring.
544
548
-`prisma-next migration status [--db <url>] [--to <contract>] [--from <contract>]` — path/pending question. Live (uses marker) or offline (uses `--from`).
545
549
-`prisma-next migration log --db <url>` — applied execution history (reads the marker; offline reading of the ledger is also supported).
@@ -590,7 +594,7 @@ Structured diagnostics from plan-time and apply-time checks suggest concrete rec
590
594
|`MIGRATION.HASH_NOT_IN_GRAPH`|`migration plan` or `ref set`: resolved hash not in graph |`migration plan --from <reachable-ref>` (e.g. `--from production`) |
591
595
|`MIGRATION.SNAPSHOT_MISSING`|`migration plan`: ref pointer exists but paired snapshot absent |`db update --advance-ref <name>` to repopulate, or `ref delete <name>` to clear orphan pointer |
592
596
|`MIGRATION.MARKER_MISMATCH`|`migrate`: live marker hash not a graph node (pre-DDL check) |`migration plan --from <graph-tip>`, or `ref set db <marker-hash>` if on-disk graph is canonical |
593
-
|`MIGRATION.PATH_UNREACHABLE`|`migrate`: no path from marker to target in on-disk graph |`migration plan --from <marker-or-reachable> --to <target>` per improved `fix` payload|
597
+
|`MIGRATION.PATH_UNREACHABLE`|`migrate`: no path from marker to target in on-disk graph |Plan the missing edge with `migration plan --from <marker-or-reachable> --to <target> --name <slug>`, then apply with `migrate --to <target>`. For a rollback, use `--to <migration-dir>^` in both steps — the planned reverse edge applies and moves the marker back without editing contract source. Review destructive (`DROP`) ops in the plan before applying. When the space has no on-disk migrations yet, omit `--from` and use `migration plan --to <target> --name <slug>` first.|
594
598
595
599
After plain `migrate`, refresh a stale `db` ref with `db update` (no-op on DB when marker matches) or `migrate --advance-ref db` in the same invocation.
Copy file name to clipboardExpand all lines: packages/1-framework/3-tooling/cli/README.md
+13-9Lines changed: 13 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -932,25 +932,26 @@ The `contract.output` field specifies the path to `contract.json`. This is the c
932
932
933
933
### `prisma-next migration plan`
934
934
935
-
Plan a migration from contract changes. Compares the emitted contract against the latest on-disk migration state and produces a new migration package with the required operations. No database connection is needed — fully offline.
935
+
Plan a migration from contract changes. Compares a starting contract against a destination contract and produces a new migration package with the required operations. No database connection is needed — fully offline.
-`--from <contract>`: Starting contract reference (hash, prefix, ref name, migration directory, `<dir>^`, or filesystem path). Defaults to the `db` ref (greenfield when absent).
945
+
-`--to <contract>`: Destination contract reference (same grammar as `--from`). Defaults to the emitted `contract.json`. Use `--to <migration-dir>^` to plan a rollback toward a predecessor state.
1. Loads config and reads `contract.json` (the "to" contract)
951
+
1. Loads config and resolves the destination contract: `--to <contract>` if provided, otherwise `contract.json`
951
952
2. Reads existing migrations from `config.migrations.dir` (default: `migrations/`)
952
-
3. Determines the starting point: `--from <hash>` if provided, otherwise the latest migration target
953
-
4. Diffs the starting contract against the new contract using the target's migration planner
953
+
3. Determines the starting point: `--from <contract>` if provided, otherwise the `db` ref (greenfield when absent)
954
+
4. Diffs the starting contract against the destination using the target's migration planner
954
955
5. Scaffolds a new migration package: `migration.ts` (containing `placeholder(...)` lambdas for any data transforms), `migration.json` (with a content-addressed `migrationHash` over the planned ops, or over `[]` when the planner could not lower any calls because of placeholders), `ops.json` (the planned ops, or `[]` in the placeholder-blocked case), and contract bookends. The package is **always** fully attested — there is no draft state on disk.
955
956
6. If the plan has unfilled `placeholder(...)` slots, the command returns a successful `pendingPlaceholders` envelope (a warning, not a failure) asking the developer to fill in the slots before re-emitting. The on-disk `ops.json` is `[]` and `migrationHash` is the hash of `(metadata, [])`, so applying the migration as-written will not advance the storage hash to the intended destination — the runner's destination-hash post-check surfaces this as a state mismatch. After filling in the placeholders, run `node migrations/<dir>/migration.ts` to re-emit `ops.json` and the corresponding `migrationHash`. `PN-MIG-2001` is raised only at self-emit time when a slot is still unfilled.
-`migrations/<dir>/start-contract.{json,d.ts}` — bookend from the "from" side (when applicable)
962
963
-`migrations/<dir>/end-contract.{json,d.ts}` — bookend from the "to" side
963
964
964
-
**Branching with `--from`:** Use `--from` to create a migration edge from a specific contract hash instead of the latest migration target. This enables branched migration graphs where multiple environments diverge from a common ancestor.
965
+
**Branching with `--from` and `--to`:** Use `--from` to create a migration edge from a specific contract hash instead of the default starting point. Use `--to` to plan toward any resolved contract — including a rollback via `<migration-dir>^` — instead of the emitted contract. This enables branched migration graphs and arbitrary-target (including reverse) edges without editing contract source.
-`--db <url>`: Database connection string (optional; defaults to `config.db.connection`)
1031
+
-`--to <contract>`: Target contract reference (hash, prefix, ref name, migration directory, `<dir>^`, or filesystem path). When omitted, applies toward the emitted `contract.json`. When `--to` resolves to an on-disk graph node, verification and apply use that bundle's `end-contract.json` — so a planned rollback or other arbitrary-target edge applies without editing contract source.
1030
1032
-`--ref <name>`: Target a named ref from `migrations/refs.json` instead of the current contract hash
1031
1033
-`--config <path>`: Path to `prisma-next.config.ts`
1. Reads migration packages from `config.migrations.dir`. Every package is attested — there is no on-disk draft state. The loader (`readMigrationPackage` in `@prisma-next/migration-tools/io`) rehashes `(metadata, ops)` for each `MigrationPackage` it returns and confirms the result matches the stored `migrationHash`. If a package has been hand-edited or partially written since emit, the load fails with `MIGRATION.HASH_MISMATCH` pointing at the offending directory and asks the developer to re-run `node migrations/<dir>/migration.ts` (or restore from version control).
1038
1040
2. Reconstructs the migration graph from all loaded packages
1039
-
3. Determines the destination hash: from `--ref` (via `refs.json`) or from `contract.json`
1041
+
3. Determines the destination hash and apply contract: from `--to` / `--ref`, or from `contract.json` when neither is supplied
1040
1042
4. Connects to the database and reads the current marker hash
1041
1043
5. Finds the shortest path from the marker hash to the destination using graph pathfinding
1042
1044
6. Executes each pending migration in order using the target's `MigrationRunner`
1043
1045
7. Each migration runs in its own transaction with prechecks, postchecks, and idempotency checks enabled
1044
-
8. After each migration, the runner verifies the schema and updates the marker/ledger
1046
+
8. After each migration, the runner runs the migration's post-checks and verifies the resulting state matches the target contract's storage hash, then updates the marker/ledger
1047
+
1048
+
**Rollback workflow:** When no on-disk edge reaches the target (for example `migrate --to <migration-dir>^`), the command refuses with `MIGRATION.PATH_UNREACHABLE` and suggests planning the missing edge with `migration plan --from <current> --to <target> --name <slug>`, then re-running `migrate --to <target>`. No contract-source edit is required.
1045
1049
1046
1050
**Config requirements:** Requires `driver` and `db.connection` (or `--db`). `migrations.dir` is optional and defaults to `migrations/`.
0 commit comments