Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/prisma/prisma-next/llms.txt

Use this file to discover all available pages before exploring further.

prisma-next migration plan compares your emitted contract.json against the latest on-disk migration state and produces a new migration package containing all required operations. The command is fully offline — no database connection is needed. It reads the contracts, runs the target’s migration planner to diff the two states, and scaffolds a directory under migrations/ with every artifact pre-attested and ready for version control.

Options

--config
string
Path to prisma-next.config.ts. Defaults to ./prisma-next.config.ts in the current working directory.
--name
string
default:"migration"
Name slug used when creating the migration directory (e.g., --name add-user-email produces migrations/<timestamp>-add-user-email/).
--from
string
Explicit starting contract hash (sha256:<hex>). Overrides automatic detection of the latest migration target and enables branched migration graphs.
--json
boolean
Emit a machine-readable JSON envelope instead of the default TTY output.
-q
boolean
Quiet mode — suppresses all output except errors.
-v
boolean
Verbose output — includes debug info and timings.

What it does

1

Load config and contract

Reads prisma-next.config.ts (or the path given to --config) and loads contract.json from config.contract.output. This is the “to” contract — the destination state the migration must reach.
2

Read existing migrations

Scans config.migrations.dir (default: migrations/) and loads every attested migration package already on disk to reconstruct the current migration graph.
3

Determine the starting point

If --from <hash> is provided, that hash is used as the starting contract. Otherwise the command derives the starting point from the latest migration’s target contract hash.
4

Diff using the target planner

Invokes the target’s migration planner to compare the starting contract against the new contract. The planner produces a list of operations (additive, widening, or destructive) required to advance the schema.
5

Scaffold the migration package

Writes a new directory under migrations/ containing migration.ts, migration.json, ops.json, and contract bookend files. The package is fully attested on creation — there is no draft state on disk.

Output files

Every migration package produced by migration plan contains the following files:
FileDescription
migration.tsEditable migration source. Contains placeholder(...) lambdas for any data transforms the planner could not lower automatically.
migration.jsonFully attested metadata including a content-addressed migrationHash over the planned ops (or over [] when placeholders blocked the planner).
ops.jsonThe planned operations as a JSON array. Empty ([]) when unfilled placeholder() slots prevented the planner from lowering calls.
start-contract.json / start-contract.d.tsContract bookend from the “from” side (included when a starting contract exists).
end-contract.json / end-contract.d.tsContract bookend from the “to” side.

Placeholder slots

When the planner inserts a placeholder(...) lambda into migration.ts, it means a data transform is required that cannot be inferred automatically. The command returns successfully with a pendingPlaceholders envelope — this is a warning, not a failure — and ops.json is written as [].
Applying a migration whose ops.json is [] due to unfilled placeholders will not advance the database to the intended destination hash. The runner’s destination-hash post-check will surface this as a state mismatch.
To resolve placeholder slots:
  1. Open migrations/<dir>/migration.ts and implement the body of each placeholder(...) lambda.
  2. Run node migrations/<dir>/migration.ts to re-emit ops.json and re-attest migration.json with the correct migrationHash.
  3. The script exits with PN-MIG-2001 if any slot is still unfilled.
See self-emit below for full details on the self-emit step.

Branching with --from

By default, migration plan derives the starting contract from the latest migration in your graph. Use --from <hash> to explicitly choose a different ancestor, creating a migration edge from that contract hash instead. This enables branched migration graphs where multiple environments diverge from a common ancestor.
# Create a branch from a specific contract state
prisma-next migration plan --from sha256:abc123... --name backfill-nullable-col
After creating branched migrations, use migration status --ref <name> to visualise which branch each environment is tracking, and migration apply --ref <name> to advance a specific branch.

Self-emitting ops.json

There is no dedicated CLI command for emitting a migration — migrations self-emit. After migration plan scaffolds the package (or after you fill in placeholder() slots), run the migration file directly with Node:
node migrations/<dir>/migration.ts
The scaffolded migration.ts calls MigrationCLI.run(import.meta.url, ...) from @prisma-next/cli/migration-cli (Postgres scaffolds re-export MigrationCLI through @prisma-next/target-postgres/migration). When invoked as the entrypoint, MigrationCLI.run:
  1. Loads prisma-next.config.ts and assembles a ControlStack
  2. Instantiates the migration with the stack so dataTransform and adapter-aware helpers can materialise a real adapter
  3. Serialises operations to ops.json
  4. Writes the content-addressed migrationHash back into migration.json
MigrationCLI.run accepts an optional third argument { argv?, stdout?, stderr? } for in-process testability and returns the exit code as a Promise<number>.

Self-emit flags

--dry-run
boolean
Print the operations that would be written to ops.json without writing any files.
--config
string
Path to prisma-next.config.ts. Defaults to ./prisma-next.config.ts.
Run the self-emit step any time you edit migration.ts — for example, after filling in a placeholder() slot or adjusting a data transform — to keep ops.json and migrationHash in sync.

Examples

prisma-next migration plan

Output format

TTY (no placeholders):
prisma-next migration plan ➜ Plan schema changes from contract diff
  config:     prisma-next.config.ts
  migrations: migrations/

✔ Planned 3 operation(s)  →  migrations/20240115120000-migration/

├─ Create table user_roles [additive]
├─ Add column role_id on users [additive]
└─ Add foreign key users_role_id_fkey on users [additive]

Migration hash: sha256:def456...
TTY (pending placeholders):
⚠ Migration scaffolded with 1 unfilled placeholder(s)
  Fill in the placeholder slot(s) in migration.ts, then run:
  node migrations/20240115120000-migration/migration.ts
JSON output:
{
  "ok": true,
  "migrationDir": "migrations/20240115120000-migration",
  "migrationHash": "sha256:def456...",
  "operations": [
    { "id": "table.user_roles", "label": "Create table user_roles", "operationClass": "additive" }
  ],
  "pendingPlaceholders": []
}

Build docs developers (and LLMs) love