From d5b5a1fb6625455f7e37985ccede4afb073bd251 Mon Sep 17 00:00:00 2001 From: willbot Date: Thu, 24 Sep 2026 17:30:32 +0200 Subject: [PATCH 01/16] docs(docs): update the Prisma ORM 8 pages for 8.0.0-rc.12 Signed-off-by: willbot Signed-off-by: Will Madden Co-Authored-By: Claude Opus 5.5 --- .../docs/(index)/full-stack-tutorial.mdx | 2 +- .../add-to-existing-project/postgresql.mdx | 2 +- .../docs/(index)/prisma-orm/from-scratch.mdx | 12 ++-- apps/docs/content/docs/cli/configuration.mdx | 70 ++++++++++++++++++- apps/docs/content/docs/cli/contract-emit.mdx | 6 +- apps/docs/content/docs/cli/contract-infer.mdx | 2 + apps/docs/content/docs/cli/db-verify.mdx | 4 ++ apps/docs/content/docs/cli/global-flags.mdx | 2 +- apps/docs/content/docs/cli/migration-new.mdx | 13 +++- apps/docs/content/docs/cli/migration-plan.mdx | 2 + apps/docs/content/docs/cli/orm-init.mdx | 22 +++++- .../guides/deployment/cloudflare-workers.mdx | 2 +- .../content/docs/guides/deployment/docker.mdx | 2 +- .../guides/deployment/pnpm-workspaces.mdx | 4 +- .../docs/guides/deployment/turborepo.mdx | 2 +- .../docs/guides/frameworks/react-router-7.mdx | 2 +- .../docs/guides/frameworks/solid-start.mdx | 2 +- .../switch-to-prisma-orm/from-drizzle.mdx | 2 +- .../switch-to-prisma-orm/from-mongoose.mdx | 4 +- .../switch-to-prisma-orm/from-sql-orms.mdx | 2 + .../guides/upgrade-prisma-orm/mongodb.mdx | 10 +-- .../guides/upgrade-prisma-orm/postgresql.mdx | 19 +++-- .../docs/orm/coming-from-prisma-orm-7.mdx | 32 +++++---- .../orm/contract-authoring/editor-support.mdx | 7 +- .../orm/contract-authoring/psl-syntax.mdx | 66 ++++++++++++++--- .../the-contract-artifact.mdx | 10 +-- .../contract-authoring/the-data-contract.mdx | 6 +- .../typescript-schema-builder.mdx | 23 ++++-- apps/docs/content/docs/orm/core-concepts.mdx | 4 +- .../content/docs/orm/data-modeling/index.mdx | 6 +- .../docs/orm/data-modeling/mongodb.mdx | 2 +- .../docs/orm/extensions/using-extensions.mdx | 10 ++- .../orm/fundamentals/advanced-queries.mdx | 10 ++- .../docs/orm/fundamentals/reading-data.mdx | 2 +- .../orm/fundamentals/relations-and-joins.mdx | 2 +- .../docs/orm/fundamentals/transactions.mdx | 6 +- .../docs/orm/fundamentals/writing-data.mdx | 4 +- .../authoring-custom-middleware.mdx | 24 +++---- .../docs/orm/middleware/built-in-budgets.mdx | 6 +- .../docs/orm/middleware/built-in-cache.mdx | 6 +- .../docs/orm/middleware/built-in-lints.mdx | 18 ++--- .../orm/middleware/how-middleware-works.mdx | 10 +-- .../orm/migrations/applying-a-migration.mdx | 2 +- .../orm/migrations/editing-a-migration.mdx | 20 +++--- .../orm/migrations/generating-a-migration.mdx | 2 + .../orm/migrations/how-migrations-work.mdx | 12 ++-- .../orm/migrations/the-migration-graph.mdx | 2 +- .../docs/content/docs/orm/reference/index.mdx | 2 +- .../content/docs/orm/reference/orm-client.mdx | 63 +++++++++++++++-- .../docs/orm/reference/pipeline-builder.mdx | 2 +- .../docs/orm/reference/raw-queries.mdx | 2 +- .../docs/orm/reference/sql-query-builder.mdx | 22 +++++- .../reference/transactions-and-runtime.mdx | 34 ++++++--- apps/docs/content/docs/orm/release-status.mdx | 6 +- apps/docs/cspell.json | 3 + 55 files changed, 456 insertions(+), 158 deletions(-) diff --git a/apps/docs/content/docs/(index)/full-stack-tutorial.mdx b/apps/docs/content/docs/(index)/full-stack-tutorial.mdx index 17fb5f869e..832f72cf32 100644 --- a/apps/docs/content/docs/(index)/full-stack-tutorial.mdx +++ b/apps/docs/content/docs/(index)/full-stack-tutorial.mdx @@ -219,7 +219,7 @@ npx prisma migration plan --name add-user-role --from _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: diff --git a/apps/docs/content/docs/(index)/prisma-orm/add-to-existing-project/postgresql.mdx b/apps/docs/content/docs/(index)/prisma-orm/add-to-existing-project/postgresql.mdx index 0296fe3c78..7c609dd69f 100644 --- a/apps/docs/content/docs/(index)/prisma-orm/add-to-existing-project/postgresql.mdx +++ b/apps/docs/content/docs/(index)/prisma-orm/add-to-existing-project/postgresql.mdx @@ -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] diff --git a/apps/docs/content/docs/(index)/prisma-orm/from-scratch.mdx b/apps/docs/content/docs/(index)/prisma-orm/from-scratch.mdx index eb1f9e96bb..0e8453f95d 100644 --- a/apps/docs/content/docs/(index)/prisma-orm/from-scratch.mdx +++ b/apps/docs/content/docs/(index)/prisma-orm/from-scratch.mdx @@ -43,7 +43,7 @@ npm install @prisma/orm-postgres dotenv npm install --save-dev prisma tsx typescript ``` -`@prisma/orm-postgres` is the library your code imports, and `prisma` is the command-line tool. `dotenv` loads `.env`, `tsx` runs `index.ts` without a build step, and `typescript` 5.9 or newer is a peer dependency of `@prisma/orm-postgres`. The two Prisma packages have different version numbers (this page was tested with `prisma` 8.0.0-rc.15 and `@prisma/orm-postgres` 8.0.0-rc.11); that is normal, and any two `latest` versions work together. +`@prisma/orm-postgres` is the library your code imports, and `prisma` is the command-line tool. `dotenv` loads `.env`, `tsx` runs `index.ts` without a build step, and `typescript` 5.9 or newer is a peer dependency of `@prisma/orm-postgres`. The two Prisma packages have different version numbers (for example `prisma` 8.0.0-rc.15 and `@prisma/orm-postgres` 8.0.0-rc.12); that is normal, and any two `latest` versions work together. ## 2. Create the config file and `.env` @@ -122,8 +122,8 @@ 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 ``` @@ -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. @@ -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 ``` diff --git a/apps/docs/content/docs/cli/configuration.mdx b/apps/docs/content/docs/cli/configuration.mdx index 6ed4f5a3f6..c96fb8986a 100644 --- a/apps/docs/content/docs/cli/configuration.mdx +++ b/apps/docs/content/docs/cli/configuration.mdx @@ -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 Prisma ORM data commands read the `orm` section; the [agent skills commands](/cli/skills) read the `skills` section. ## Config file @@ -27,14 +27,78 @@ 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. The `defineConfig` you import from `@prisma/orm-postgres/config` or `@prisma/orm-mongo/config` keeps its name. -[`orm init`](/cli/orm-init) writes this file for you. Pass `--config` when your config file is not at `./prisma.config.ts`: +`defineConfig` from `@prisma/cli-engine` was the former name of `definePrismaConfig`, and `@prisma/cli-engine` 0.6.1 removed it. A config scaffolded by an earlier release candidate that imports it fails to load. Import `definePrismaConfig` instead, and call it in place of `defineConfig`. + +[`orm init`](/cli/orm-init) writes this file for you. Pass `--config` when your config file is not in the directory you run the command from: ```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. It merges every `prisma.config.ts` it finds key by key, and where two files set the same key, the one nearest to the starting point wins. + +A project inside a larger repository therefore inherits any setting its own config leaves out from a `prisma.config.ts` higher up. To stop that, add `parent: false` to the project's config. 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` also takes a path, which names the next config file to read instead of the one in the parent directory. + +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, 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", + }), +}); +``` + +Every file the glob matches that starts with `// use prisma-8` becomes part of one schema, and `contract emit` builds one contract from them. A file without that first line is left out without a warning, and if no matched file has it, `contract emit` fails with `PSL_NO_OPTED_IN_SCHEMA_FILES`. A new file joins the schema on the next emit, with no change to the config. The emitted files go in the fixed part of the glob, 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. `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: after each `prisma7 migrate dev` or `prisma7 migrate deploy`, run `npx prisma contract emit` and then `npx prisma db sign`. + +Prisma ORM 8 describes each part of the schema exactly or refuses it. A part it cannot describe, such as a `view` block, `Unsupported(...)`, or `relationMode = "prisma"`, fails `contract emit` with an error that names the file, the line, and a Prisma ORM 7 edit that removes it. [`orm init --from-prisma7-schema`](/cli/orm-init#on-a-prisma-orm-7-project) writes this config for you. + ## Emit-only config `contract emit` does not connect to a database, so the `orm` section can omit `db.connection`: diff --git a/apps/docs/content/docs/cli/contract-emit.mdx b/apps/docs/content/docs/cli/contract-emit.mdx index 4b07f20961..cfebc6b088 100644 --- a/apps/docs/content/docs/cli/contract-emit.mdx +++ b/apps/docs/content/docs/cli/contract-emit.mdx @@ -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 PSL contract source can be one 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 leaves any other file out without a warning. When no file has that line, it fails with `CONTRACT.SOURCE_LOAD_FAILED` and the finding `PSL_NO_OPTED_IN_SCHEMA_FILES`. + ## Usage ```npm @@ -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. `contract.d.ts` lists models, fields, and relations in the same order as `contract.json`. + +When the contract source cannot be read, the command fails with `CONTRACT.SOURCE_LOAD_FAILED`. The terminal prints each finding, and in `--json` output the error carries a `diagnostics` array with one entry per finding: its code, its summary, and, where known, its file and line. ## Run it automatically diff --git a/apps/docs/content/docs/cli/contract-infer.mdx b/apps/docs/content/docs/cli/contract-infer.mdx index 0e267a98b4..f23060c6d5 100644 --- a/apps/docs/content/docs/cli/contract-infer.mdx +++ b/apps/docs/content/docs/cli/contract-infer.mdx @@ -43,6 +43,8 @@ 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`, which `contract emit` needs. 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")`. Each column default is written in a form `contract emit` reads back: a JSON default as a `json` literal, a decimal as a bare number with every digit, and any other SQL expression as a `sql` literal, as [Default values](/orm/contract-authoring/psl-syntax#default-values) describes. A nullable list column is written `Type[]?`. If you keep an inferred contract in version control, running `contract infer` again can print the same database differently than earlier release candidates did; review the diff. + The command stops at `contract.prisma`. Follow it with the emit and sign steps: ```npm diff --git a/apps/docs/content/docs/cli/db-verify.mdx b/apps/docs/content/docs/cli/db-verify.mdx index 852a919c98..bbd5c4bc41 100644 --- a/apps/docs/content/docs/cli/db-verify.mdx +++ b/apps/docs/content/docs/cli/db-verify.mdx @@ -60,3 +60,7 @@ 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 + +`db verify` compares a column default by its value, not by how PostgreSQL prints it, so `'-1'::integer`, `(5)::smallint`, an enum value cast to a type in another schema, a `timestamp` value without a time zone, and an `ARRAY[...]` list all compare equal to the default in your contract. It reads the database with `TimeZone = UTC` and ISO dates, whatever the server or role sets. A contract inferred from a server outside UTC before `8.0.0-rc.12` can therefore show one difference in a `timestamptz` value inside a check constraint or an index predicate. Emit the contract and run `db sign` once to clear it. diff --git a/apps/docs/content/docs/cli/global-flags.mdx b/apps/docs/content/docs/cli/global-flags.mdx index 1409297a7d..efd35ae1c9 100644 --- a/apps/docs/content/docs/cli/global-flags.mdx +++ b/apps/docs/content/docs/cli/global-flags.mdx @@ -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 ` | Grant a consent prompt non-interactively by typing its token (repeatable). | +| `--confirm ` | 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 ` | 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. | diff --git a/apps/docs/content/docs/cli/migration-new.mdx b/apps/docs/content/docs/cli/migration-new.mdx index 86b1d1c668..e3c0b316aa 100644 --- a/apps/docs/content/docs/cli/migration-new.mdx +++ b/apps/docs/content/docs/cli/migration-new.mdx @@ -21,10 +21,21 @@ npx prisma migration new --name split-name | Option | What it does | | --- | --- | | `--name ` | Sets the migration directory name suffix. | -| `--from ` | Sets the starting contract hash. Defaults to the latest migration target. | +| `--from ` | Sets the starting contract: the target hash of an existing migration, or a unique prefix of one. Defaults to the `db` ref, as on [`migration plan`](/cli/migration-plan). A hash on an empty migrations directory, or a prefix that matches more than one migration, is refused. | | `--config ` | Read this config file instead of `./prisma.config.ts`. | | `--json` | Prints a machine-readable result. | +## Where it starts + +Without `--from`, `migration new` picks its starting point the way `migration plan` does: + +- When the `db` ref exists and `migrations/app/` has migrations, it starts from the `db` ref. +- When there are no migrations and no `db` ref, it starts from an empty database. +- When migrations exist but there is no `db` ref, it refuses with `MIGRATION.PLAN_ORIGIN_UNKNOWN`. Pass `--from` with the hash of the migration to build on, or set the ref with [`migration ref`](/cli/migration-ref). `npx prisma migration list` shows the hashes. +- When the `db` ref exists but there are no migrations, it refuses and points you to `migration plan`, which writes the baseline first. + +Before `8.0.0-rc.12`, `migration new` started from the newest migration. Scripts that relied on that should pass `--from`. + ## Examples ```npm diff --git a/apps/docs/content/docs/cli/migration-plan.mdx b/apps/docs/content/docs/cli/migration-plan.mdx index fbb7012412..116deeba78 100644 --- a/apps/docs/content/docs/cli/migration-plan.mdx +++ b/apps/docs/content/docs/cli/migration-plan.mdx @@ -21,6 +21,8 @@ Keep the `db` ref current and you never see the refusal. [`db init`](/cli/db-ini When `migrations/app/` is empty and the `db` ref points at a contract whose snapshot is stored under `migrations/snapshots/`, one `migration plan` run writes a baseline package from nothing to the ref's contract and, when your emitted contract differs from the ref's, a second package with the delta. Expect one or two new directories in `git status`. The baseline is never replayed against a database that already carries a marker, because the runner starts from the marker and only applies edges past it. +When the baseline would contain destructive operations, `migration plan` asks for consent before it writes it, as [`db update`](/cli/db-update) does. In a script, pass `--no-interactive --confirm `. It also warns when planning from the `db` ref would start a second branch in the migration history. + The command is offline. It does not need a database connection. ## Usage diff --git a/apps/docs/content/docs/cli/orm-init.mdx b/apps/docs/content/docs/cli/orm-init.mdx index ecdfd27346..71e1495451 100644 --- a/apps/docs/content/docs/cli/orm-init.mdx +++ b/apps/docs/content/docs/cli/orm-init.mdx @@ -31,6 +31,7 @@ npx prisma@latest orm init --yes --target postgres --authoring psl | `--target ` | Sets the database target. Use `postgres` or `mongodb`. | | `--authoring