Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
d5b5a1f
docs(docs): update the Prisma ORM 8 pages for 8.0.0-rc.12
wmadden-electric Sep 24, 2026
88717ab
docs(docs): the CLI is 8.0.0-rc.17, and contract emit also reads the …
wmadden-electric Sep 24, 2026
7d0b972
docs(docs): state the contract header requirement as either line
wmadden-electric Sep 24, 2026
b09dd62
docs(docs): address review: db verify comparison from the code, short…
wmadden-electric Sep 25, 2026
89712ce
docs(docs): fix the reader-review findings on the rc.12 pages
wmadden-electric Sep 25, 2026
d0d974e
docs(docs): title the code blocks 89712ce added
Sep 25, 2026
743de8d
docs(docs): fix the second reader-review round on the rc.12 pages
wmadden-electric Sep 25, 2026
13824cf
Merge the code-block titles into the second reader-review round
wmadden-electric Sep 25, 2026
cc0ef4e
docs(docs): state where migration new starts when there is no db ref
wmadden-electric Sep 25, 2026
007d883
docs(docs): answer the open questions from the ORM source
wmadden-electric Sep 25, 2026
dec6036
docs(docs): migration check belongs in pull-request checks; the deplo…
wmadden-electric Sep 25, 2026
1de640d
docs(docs): say where to report a Supabase contract difference
wmadden-electric Sep 25, 2026
474d1ca
Merge remote-tracking branch 'origin/main' into docs/orm8-8.0.0-rc.12
Sep 25, 2026
6e6c5c4
docs(docs): await the scoped query inside currentName.run()
Sep 25, 2026
8998250
docs(docs): a deploy pipeline runs db migrate alone
wmadden-electric Sep 25, 2026
38a2a26
Merge remote-tracking branch 'bot/docs/orm8-8.0.0-rc.12' into docs/or…
wmadden-electric Sep 25, 2026
16ca57c
docs(docs): warn that a project config inherits db and migrations fro…
wmadden-electric Sep 25, 2026
db8f82c
docs(docs): same scopeUserSelects signature on both middleware pages,…
wmadden-electric Sep 25, 2026
bac83ae
docs(docs): the middleware calls the condition only for a matching SE…
wmadden-electric Sep 25, 2026
937dde6
Merge main into docs/orm8-8.0.0-rc.12
wmadden-electric Sep 25, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/docs/content/docs/(index)/full-stack-tutorial.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ npx prisma migration plan --name add-user-role --from <timestamp>_init
The plan is your change and nothing else. Review it like any other diff, with [`migration show`](/cli/migration-show) or by reading the generated package:

```text no-copy
ALTER TABLE "public"."user" ADD COLUMN "role" text DEFAULT 'member' NOT NULL
ALTER TABLE "public"."User" ADD COLUMN "role" text DEFAULT 'member' NOT NULL
```

Emitting also updated the query types, so surface the new field in the route's typed select in `src/prisma/users.ts`, adding `"role"` to the `.select(...)` list and `role: user.role` to the returned object:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ npx prisma contract infer --output ./src/prisma/contract.prisma

The command writes a first draft of `src/prisma/contract.prisma`.

Open that file and review it before you go on. This is the moment to clean up model names, keep only the tables you want Prisma ORM to know about first, and make the file easier to read.
Open that file and review it before you go on. This is the moment to clean up model names, keep only the tables you want Prisma ORM to know about first, and make the file easier to read. A model's table is the model name exactly as written, so a table such as `User` gets a model with no `@@map`, and a table such as `user` or `user_profile` gets `@@map` with its name. Keep those `@@map` lines when you rename a model, so the table stays the same.

:::note[Temporal types on inferred date and time columns]

Expand Down
12 changes: 6 additions & 6 deletions apps/docs/content/docs/(index)/prisma-orm/from-scratch.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -122,13 +122,13 @@ npx prisma db init
│ database: postgres://****:****@db.prisma.io:5432/postgres?sslmode=require
✔ Applied 2 operation(s) across 1 contract space
App space
├─ Create table "user"
├─ Add unique constraint on "user" (email)
├─ Create table "User"
├─ Add unique constraint on "User" (email)
└─ marker f4e1954fd8bed87828d13c3f1a02164dc9796ef1af76ed6f98184c01263169c5
✔ Advanced ref "db" → f4e1954fd8bed87828d13c3f1a02164dc9796ef1af76ed6f98184c01263169c5
```

It also writes `migrations/app/refs/db.json` and a snapshot of the contract under `migrations/snapshots/`; commit both. If the command fails with `DRIVER.CONNECTION_FAILED`, `DATABASE_URL` in `.env` is wrong or the database is not reachable. A `SECURITY WARNING` about SSL modes comes from the `pg` driver and does not stop the command; change `sslmode=require` to `sslmode=verify-full` in `.env` to silence it.
The `marker` line in the output is the record that signing stores in the database: the hash that identifies the version of the contract the database now matches. `db init` also writes `migrations/app/refs/db.json`, called the `db` ref: a file that records which contract version your development database is at, so that `migration plan` in step 6 knows where to start. The `Advanced ref "db"` line in the output is `db init` writing it. Commit it, together with the snapshot of the contract that `db init` writes under `migrations/snapshots/`. If the command fails with `DRIVER.CONNECTION_FAILED`, `DATABASE_URL` in `.env` is wrong or the database is not reachable. A `SECURITY WARNING` about SSL modes comes from the `pg` driver and does not stop the command; change `sslmode=require` to `sslmode=verify-full` in `.env` to silence it.

## 5. Write and read data

Expand Down Expand Up @@ -215,13 +215,13 @@ npx prisma migration plan --name add_user_phone
```text
✔ Planned baseline + 1 operation(s)
migrations/app/20260917T1457_add_user_phone
└─ Add column "phone" to "user"
└─ Add column "phone" to "User"
from: f4e1954fd8bed87828d13c3f1a02164dc9796ef1af76ed6f98184c01263169c5
to: a8a6806fd2d219065fd4449b295c80626e9123c18bd40847ec3588aa9d565bc9
baseline: migrations/app/20260917T1456_baseline
app space: migrations/app/20260917T1457_add_user_phone
ℹ DDL preview
ALTER TABLE "public"."user" ADD COLUMN "phone" text;
ALTER TABLE "public"."User" ADD COLUMN "phone" text;
```

Two directories appear under `migrations/app/`: a baseline that records the table `db init` created, and your change. The baseline is never applied to this database, because the database is already signed at that state. Each migration directory holds a `migration.ts` you can read and edit; [Generating a migration](/orm/migrations/generating-a-migration) explains the files.
Expand All @@ -235,7 +235,7 @@ npx prisma db migrate --advance-ref db
```text
✔ Applied 1 migration(s) (1 operation(s)) across 1 contract space(s)
App space
├─ Add column "phone" to "user"
├─ Add column "phone" to "User"
└─ marker a8a6806fd2d219065fd4449b295c80626e9123c18bd40847ec3588aa9d565bc9
✔ Advanced ref "db" → a8a6806fd2d219065fd4449b295c80626e9123c18bd40847ec3588aa9d565bc9
```
Expand Down
96 changes: 93 additions & 3 deletions apps/docs/content/docs/cli/configuration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ metaTitle: Prisma ORM CLI configuration
metaDescription: 'Learn how Prisma ORM CLI commands find config, read database URLs, and format output.'
---

Prisma ORM CLI commands read `prisma.config.ts` in your project root. The file has one section per part of the CLI. The Prisma ORM data commands read the `orm` section; the [agent skills commands](/cli/skills) read the `skills` section.
Prisma ORM CLI commands read `prisma.config.ts`, starting in the directory you run them from. The file has one section per part of the CLI. The `contract`, `db`, and `migration` commands read the `orm` section, and the [agent skills commands](/cli/skills) read the `skills` section.

## Config file

Expand All @@ -27,14 +27,104 @@ export default definePrismaConfig({
});
```

For MongoDB projects, import the section helper from `@prisma/orm-mongo/config` instead. `defineConfig` from `@prisma/cli-engine` is the former name of `definePrismaConfig` and still works, so configs scaffolded by earlier release candidates keep evaluating.
For MongoDB projects, import the section helper from `@prisma/orm-mongo/config` instead. Both packages export this helper as `defineConfig`, and the examples on this page rename it to `ormConfig` when they import it.

[`orm init`](/cli/orm-init) writes this file for you. Pass `--config` when your config file is not at `./prisma.config.ts`:
If you set up Prisma ORM 8 with a release candidate before `8.0.0-rc.12`, your config may import `defineConfig` from `@prisma/cli-engine`, the package the `prisma` CLI is built on. `8.0.0-rc.12` requires `@prisma/cli-engine` 0.6.1, which removed that export, so the config fails to load. Rename that import and its call to `definePrismaConfig`, which is the same function under its new name. You can import it from `prisma/config` or from `@prisma/cli-engine`, because `prisma/config` re-exports it. Leave the `defineConfig` import from `@prisma/orm-postgres/config` or `@prisma/orm-mongo/config` as it is: that is the helper for the `orm` section, and its name has not changed.

[`orm init`](/cli/orm-init) writes this file for you. Without `--config`, the CLI looks for `prisma.config.ts` in the directory you run the command from and in the directories above it, as [How the CLI finds the config](#how-the-cli-finds-the-config) explains. Pass `--config` to use a config file in another place, such as a subdirectory:

```npm
npx prisma contract emit --config ./config/prisma.config.ts
```

## How the CLI finds the config

The CLI looks for `prisma.config.ts` in the current directory, or starts from the file you pass to `--config`. It then looks in each parent directory, up to the root of the repository, which is the first directory that has a `.git` entry. If neither the starting directory nor any directory above it has a `.git` entry, the CLI reads only the first file.

The CLI combines the files it finds one section at a time. Inside a section such as `orm`, each top-level key, such as `contract`, `db`, or `migrations`, comes whole from the nearest file that sets it, and the keys nested inside it are not combined. So if a config higher up sets `db.connection` and your project's config sets only `contract`, the CLI uses your `contract` and the other file's `db`. Extensions are the exception: a project config that calls `ormConfig` does not inherit them from a config higher up, even when it leaves `extensions` out. List the extensions your contract uses in each project's own config.

A project inside a larger repository therefore inherits any setting its own config leaves out from a `prisma.config.ts` higher up.

:::warning[More than one project in a repository]

If a `prisma.config.ts` higher up sets `db` or `migrations`, a project config that leaves them out uses that file's database and migrations folder. `db update`, `db migrate` and `db verify` then connect to the other project's database, and `migration plan` writes into the other project's migrations folder, without a warning. Set `db` and `migrations` in every project's own config, or add `parent: false` to it.

:::

To stop a project's config from inheriting anything, add `parent: false` to it. The search then ends at that file:

```typescript title="prisma.config.ts"
import { definePrismaConfig } from "prisma/config";
import { defineConfig as ormConfig } from "@prisma/orm-postgres/config";

export default definePrismaConfig({
parent: false,
orm: ormConfig({
contract: "./prisma/contract.prisma",
}),
});
```

`parent` can also be a path to another config file, which the CLI reads next in place of the one in the parent directory. The path is relative to the directory of the config file that sets it, and it may point outside the repository. After reading that file, the CLI goes on to search the directories above it in the usual way, unless that file sets `parent` too:

```typescript title="prisma.config.ts"
import { definePrismaConfig } from "prisma/config";
import { defineConfig as ormConfig } from "@prisma/orm-postgres/config";

export default definePrismaConfig({
parent: "../shared/prisma.config.ts",
orm: ormConfig({
contract: "./prisma/contract.prisma",
}),
});
```

A relative path in a config file, such as `contract`, `output`, or `migrations.dir`, resolves from the directory of the config file that sets it, not from the directory you run the command in. So `--config ./config/prisma.config.ts` with `contract: "./prisma/contract.prisma"` reads `./config/prisma/contract.prisma`.

## Split the schema across several files

`contract` accepts a glob, a path pattern where `*` matches any file name and `**` matches any number of folders, so one schema can span several `.prisma` files:

```typescript title="prisma.config.ts"
import { definePrismaConfig } from "prisma/config";
import { defineConfig as ormConfig } from "@prisma/orm-postgres/config";

export default definePrismaConfig({
orm: ormConfig({
contract: "./prisma/**/*.prisma",
}),
});
```

`contract emit` builds one contract from every matched file whose first line is `// use prisma-8`. It skips a matched file without that line and does not warn, so the line is what makes a file part of the schema. The Prisma editor extension uses the same rule, so the editor and `contract emit` agree on which files make up the schema. If the glob matches files but none of them starts with the line, `contract emit` fails with `CONTRACT.SOURCE_LOAD_FAILED`, and the error's finding is `PSL_NO_OPTED_IN_SCHEMA_FILES`. If the glob matches no file at all, for example because of a typo in the pattern, the finding is `PSL_NO_SCHEMA_FILES_MATCHED` instead.

A new file joins the schema the next time you run `contract emit`, with no change to the config. The emitted files go in the folder before the first wildcard, here `./prisma/contract.json` and `./prisma/contract.d.ts`.

## Use a Prisma ORM 7 schema

On PostgreSQL, Prisma ORM 8 can read a Prisma ORM 7 `schema.prisma` directly as its contract source, so the two versions can run side by side on the database that Prisma ORM 7 migrates. Wrap the path in `prisma7Schema`:

```typescript title="prisma.config.ts"
import "dotenv/config";
import { definePrismaConfig } from "prisma/config";
import { defineConfig as ormConfig, prisma7Schema } from "@prisma/orm-postgres/config";

export default definePrismaConfig({
orm: ormConfig({
contract: prisma7Schema("prisma/schema.prisma"),
db: {
connection: process.env["DATABASE_URL"]!,
},
}),
});
```

`prisma7Schema` takes one schema file, or a directory of `.prisma` files as Prisma ORM 7 reads it. It reads every `.prisma` file it is given, so these files do not need the `// use prisma-8` first line. `contract emit` writes `contract.json` and `contract.d.ts` into the directory that holds the schema, here `prisma/`, unless you set `output`. Prisma ORM 7 keeps owning the database and its migrations, and you run its commands as `prisma7`, the Prisma ORM 7 CLI that [`orm init --from-prisma7-schema`](/cli/orm-init#on-a-prisma-orm-7-project) installs next to Prisma ORM 8.

Once the config is in place, run `npx prisma contract emit` and then [`npx prisma db sign`](/cli/db-sign). `db sign` checks that the database matches the contract and then records that in the database, without changing your tables. Run both commands again after each Prisma ORM 7 migration, whether you ran `npx prisma7 migrate dev` or `npx prisma7 migrate deploy`, so that the record names the new contract.

`contract emit` fails on any part of the schema that Prisma ORM 8 cannot represent exactly, such as a `view` block, `Unsupported(...)`, or `relationMode = "prisma"`. The error names the file and the line and suggests an edit to the Prisma ORM 7 schema. When that edit would also change the database on the next Prisma ORM 7 migration, the error says so. For example, removing an `Unsupported(...)` field drops its column, so for that field the error suggests adding `@@ignore` to the model instead, which leaves the next Prisma ORM 7 migration empty but removes the model from the Prisma ORM 7 client. Prisma ORM 8 has no views, so for a `view` block the error suggests removing the view or replacing it with a model over the table the view reads. `orm init --from-prisma7-schema` writes this config for you.

## Emit-only config

`contract emit` does not connect to a database, so the `orm` section can omit `db.connection`:
Expand Down
6 changes: 5 additions & 1 deletion apps/docs/content/docs/cli/contract-emit.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ metaDescription: Learn how to emit contract.json and contract.d.ts for Prisma OR

The command is offline. It does not need a database connection.

A Prisma schema source can be one `.prisma` file or a glob that matches several files; see [Split the schema across several files](/cli/configuration#split-the-schema-across-several-files). `contract emit` reads only the `.prisma` files whose first line is `// use prisma-8`, and skips any other file without a warning. When no file starts with that line, it fails with `CONTRACT.SOURCE_LOAD_FAILED` and reports the problem with the code `PSL_NO_OPTED_IN_SCHEMA_FILES`.

## Usage

```npm
Expand All @@ -31,7 +33,9 @@ The command emits:
- `contract.json`, the canonical machine-readable contract
- `contract.d.ts`, the generated TypeScript contract declarations

Do not edit these files by hand. Re-run `contract emit` after changing the contract source or extension pack list.
Do not edit these files by hand. Re-run `contract emit` after changing the contract source or extension pack list. The first emit after you upgrade to `8.0.0-rc.12` reorders the entries in `contract.d.ts` to follow the order in `contract.json`, which needs no change to your code.

When the contract source cannot be read, the command fails with `CONTRACT.SOURCE_LOAD_FAILED` and prints each finding, meaning each problem it found in the source, with the file and line where it knows them. In `--json` output, the findings are the entries of the `envelope.diagnostics` array in the final `result` event, next to `envelope.error`. Each entry has a `code`, a `summary`, and, where known, `where.path` and `where.line`. If an entry's `code` is `CONTRACT.SOURCE_DIAGNOSTIC`, the code of the specific problem, such as `PSL_NO_OPTED_IN_SCHEMA_FILES`, is in its `meta.code`.

## Run it automatically

Expand Down
6 changes: 6 additions & 0 deletions apps/docs/content/docs/cli/contract-infer.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ Inference gives you a starting point, not a finished design. Review:
- defaults, indexes, and constraints
- extension-backed column types

The file starts with `// use prisma-8`, because `contract emit` reads only `.prisma` files that start with that line. Each model is named after its table, and gets `@@map` only when the table name differs from the model name: a table `User` becomes `model User`, and a table `user_profile` becomes `model UserProfile` with `@@map("user_profile")`.

Every column default is written in a form `contract emit` accepts, so you can emit the file without editing it. [Default values](/orm/contract-authoring/psl-syntax#default-values) shows those forms. A list column that allows `NULL` is written `Type[]?`, and a list column that is `NOT NULL` is written `Type[]`.

If you keep an inferred contract in version control, running `contract infer` again after an upgrade can write the same database differently, so review the diff before you commit it.

The command stops at `contract.prisma`. Follow it with the emit and sign steps:

```npm
Expand Down
10 changes: 10 additions & 0 deletions apps/docs/content/docs/cli/db-verify.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,13 @@ npx prisma db verify --db "$DATABASE_URL" --json
| Extension mismatch | The contract requires an extension that is not wired in the config. |

Fix the database or contract, emit again if needed, then verify again.

## How PostgreSQL defaults are compared

When a column default is a literal value, `db verify` reads it as a value before it compares it with your contract, so the casts PostgreSQL adds when it prints the default do not cause a difference. This covers numbers such as `'-1'::integer` and `(5)::smallint`, text and enum values, including an enum value cast to a type in another PostgreSQL schema, `timestamp` values, `true`, `false`, `NULL`, JSON, and lists written as `'{...}'` or `ARRAY[...]`. `db verify` also recognizes `now()`, `clock_timestamp()`, `gen_random_uuid()`, and a sequence default, which it treats as `autoincrement()`.

Any other default is a SQL expression, which you write in your contract as a `sql` default, such as ``@default(sql`(now() + '00:03:00'::interval)`)``. [Default values](/orm/contract-authoring/psl-syntax#default-values) shows how to write one. `db verify` cannot work out whether two SQL expressions give the same value, so it compares their text, ignoring letter case and spaces. PostgreSQL often rewrites an expression when it stores it, for example by adding casts, so write a `sql` default in your contract the way PostgreSQL stores it. To see that form, run `npx prisma contract infer --output ./inferred.prisma` and copy the column's `@default` from that file.

Check constraints and the `WHERE` clause of a partial index are compared more strictly than `sql` defaults: their text must match exactly, including letter case and spaces.

If `db verify` reports a difference in a `timestamptz` value inside a check constraint or a partial index's `WHERE` clause, check whether your contract was inferred before `8.0.0-rc.12` from a server that was not set to UTC. `db verify` reads the database with the time zone set to UTC and dates in ISO format, whatever the server or your database role sets, so a value that your contract has in another time zone no longer matches as text. To fix it, copy the new text from a fresh `npx prisma contract infer --output ./inferred.prisma` into your contract, emit the contract, and run `db sign`.
2 changes: 1 addition & 1 deletion apps/docs/content/docs/cli/global-flags.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ All commands in the unified Prisma CLI accept these flags.
| `--color` / `--no-color` | Force colored output on or off. |
| `--interactive` / `--no-interactive` | Force prompts on or off. |
| `-y`, `--yes` | Accept prompt defaults without asking. |
| `--confirm <token>` | Grant a consent prompt non-interactively by typing its token (repeatable). |
| `--confirm <token>` | Grant a consent prompt in advance by giving its token, so the command does not ask (repeatable). Works in scripts and in an interactive terminal. |
| `--config <path>` | Read this config file instead of `./prisma.config.ts`. |
| `-h`, `--help` | Print the manual for a command: what it does, its options, a workflow where one applies, and examples. |
| `--version` | Print the CLI version and exit. |
Expand Down
Loading
Loading