Skip to content

Releases: prisma/orm

v8.0.0-rc.8

v8.0.0-rc.8 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 26 Aug 08:15
5c0e4bd

v8.0.0-rc.8

The toolchain releases against @prisma/cli-engine@0.3.0, which now takes the Management API SDK as a peer dependency, and migration plan no longer plans silently from an empty database when migrations already exist.

The upgrade recipe for this hop: the user recipe.

Breaking changes

  • The engine peer moves to @prisma/cli-engine@0.3.0@prisma/orm-toolchain declares the unified CLI's engine as an exact peer, and this release peers 0.3.0 (up from 0.2.3). The engine's change: @prisma/management-api-sdk moves from a regular dependency to a peer dependency (^1.55.0), supplied by the prisma CLI shell at runtime. Installs assembled by the unified prisma CLI resolve one engine as before; a host that pins the engine itself must move to 0.3.0 and, if it runs the engine outside the CLI shell, install the SDK itself. (prisma/prisma-cli#236)

Features

  • The prisma-8 skill, auto-installed into every project by prisma init, now teaches agents the migration system's real model — plan-from-state with explicit baselines, not a linear chain — so agents stop producing full-create plans against real databases. (#30123)

Fixes

  • migration plan refuses to plan from an empty database when the project already has migrations on disk, instead of silently producing a full-create package that fails against any real database. A structured error explains the situation; planning from baseline remains available as an explicit opt-in. (#30122)
  • Structured errors' docsUrl links now point at docs.prisma.io/docs/orm/v8/... instead of the pre-RC orm/next/... path. (#30126)
  • The language server now canonicalizes Windows file URIs, so schema files configured with Windows paths (D:\project\next.prisma) are recognized as part of the project. (#30121)
  • The dev dist-tag no longer goes stale after a release: a release push to main also publishes a -dev.1 build of the new base, so @dev installs always resolve against the current release's engine pins. (#30125)

v8.0.0-rc.7

v8.0.0-rc.7 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 25 Aug 10:22
1989e28

v8.0.0-rc.7

ORM collection pagination renames to limit/offset, and the toolchain releases against @prisma/cli-engine@0.2.3, the engine whose config loader ships the prisma init scaffold fixes from the unified CLI's rc line.

The upgrade recipe for this hop: the user recipe.

Breaking changes

  • ORM pagination is limit/offset, not take/skip.take(n) and .skip(n) are renamed to .limit(n) and .offset(n) on SQL and Mongo ORM collections, including relation refinements and grouped SQL collections; the old names are removed. Semantics are unchanged. Mongo's lower-level query builder keeps .skip(n) — it names the native $skip pipeline stage, not the collection API. (#30112)

    Before:

    await db.orm.User.orderBy((u) => u.id.asc()).skip(10).take(10).all();

    After:

    await db.orm.User.orderBy((u) => u.id.asc()).offset(10).limit(10).all();
  • The engine peer moves to @prisma/cli-engine@0.2.3@prisma/orm-toolchain declares the unified CLI's engine as an exact peer, and this release peers 0.2.3 (up from 0.2.2). Installs assembled by the unified prisma CLI resolve one engine as before; a host that pins the engine itself must move to 0.2.3. (prisma/prisma-cli#225, prisma/prisma-cli#227)

v8.0.0-rc.6

v8.0.0-rc.6 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 25 Aug 07:03
00ae8e2

v8.0.0-rc.6

PostgreSQL temporal columns move from Date to explicit Temporal-or-text representations, the prisma-8 agent skill ships inside the ORM packages a project installs, prisma orm init hands agent-skills setup to the family-level prisma init, and the toolchain releases against @prisma/cli-engine@0.2.2 — the engine that evaluates prisma.config.ts correctly under pnpm symlink layouts.

The upgrade recipe for this hop: the user recipe.

Breaking changes

  • PostgreSQL temporal columns read as Temporal values or text, never Date — each of date, timestamp(p), timestamptz(p) and time(p) now has two representation-explicit codecs: a Temporal-backed one (the bare PSL spellings Date, Timestamp, Timestamptz, Time select it) and a text one (DateString, TimestampString, TimestamptzString, TimeString). The previous codecs (pg/date@1, pg/timestamp@1, pg/timestamptz@1, pg/time@1, sql/timestamp@1 / field.timestamp()) are removed with no aliases. Pick a representation per column, re-emit every contract, and provide a global Temporal implementation (e.g. import 'temporal-polyfill/full/global') wherever a Temporal-backed column is read. See the migration recipe. (#30073)

    Before:

    occurredAt Timestamptz  // read as Date

    After (read as Temporal.Instant):

    occurredAt Timestamptz

    Or, to keep PostgreSQL's text unchanged:

    occurredAt TimestamptzString
  • prisma orm init no longer installs agent skills — the GitHub fetch (npx skills add) is removed and nothing replaces it inside orm init: agent-skills setup belongs to the family-level prisma init command, which init's next-steps now point to. The --skip-skills flag is removed with the behavior it opted out of, and the skill-install failure exit (code 6) is retired. Scaffolding is otherwise unchanged. (#30097)

  • The engine peer moves to @prisma/cli-engine@0.2.2@prisma/orm-toolchain declares the unified CLI's engine as an exact peer, and this release peers 0.2.2 (up from 0.2.0). Installs assembled by the unified prisma CLI resolve one engine as before; a host that pins the engine itself must move to 0.2.2. The new engine evaluates prisma.config.ts through pnpm symlink layouts that are not realpath'd (prisma/prisma-cli#222) and exports its CI detector (prisma/prisma-cli#224).

Features

  • The prisma-8 skill travels in the npm tarballsskills/prisma-8/ ships inside @prisma/orm-postgres, @prisma/orm-sqlite, and @prisma/orm-mongo, stamped with the package name and version so prisma skills sync can copy it into agent harness directories and detect staleness from the installed packages rather than fetching from GitHub. The two upgrade skills fold into the prisma-8 router as its "upgrading" branch. (#30096)

7.10.0

Choose a tag to compare

@SevInf SevInf released this 25 Aug 12:54
e92bc46

Prisma ORM 7.10.0

Prisma ORM 7.10.0 introduces a compatibility package for running Prisma 7 alongside newer Prisma versions, secures Prisma Studio's local server, and includes fixes across Prisma Client and the PostgreSQL, MariaDB, Neon, SQLite, and Prisma Postgres Serverless adapters.

Highlights

Run Prisma 7 alongside Prisma 8

This release introduces @prisma/prisma7, a compatibility package that lets you retain a matching Prisma 7 CLI and configuration while installing Prisma 8 in the same project.

Once 7.10.0 is released, a side-by-side installation can use:

npm install --save-dev prisma@8 @prisma/prisma7@7.10.0
npm install @prisma/client@7.10.0

Use prisma for the directly installed Prisma 8 CLI and prisma7 for Prisma 7:

npx prisma --version
npx prisma7 --version

npx prisma7 generate
npx prisma7 migrate dev
npx prisma7 db push

Prisma 7 now prefers version-specific configuration files, allowing its configuration to coexist with Prisma 8's prisma.config.* files:

// prisma7.config.ts
import { defineConfig } from '@prisma/prisma7/config'

export default defineConfig({
  schema: 'prisma/schema.prisma',
  migrations: {
    path: 'prisma/migrations',
  },
})

Without an explicit --config option, Prisma 7 searches for:

  1. Root-level prisma7.config.* files.
  2. .config/prisma7.* files.
  3. Existing prisma.config.* files as a backwards-compatible fallback.

The supported extensions are .js, .ts, .mjs, .cjs, .mts, and .cts. An explicit config path always takes precedence:

npx prisma7 generate --config ./custom/prisma7.config.ts

New projects initialized by the Prisma 7 CLI use prisma7.config.ts. Existing projects containing only prisma.config.* continue to work without migration or additional warnings. If a prisma7.config.* file exists but cannot be loaded, Prisma reports the error rather than silently falling back to another configuration.

The prisma7 identity is carried through CLI help, version output, shell completion, initialization, migration, database, and generation guidance. Stable Prisma concepts such as schema.prisma, Prisma Migrate, @prisma/client, and PRISMA_* environment variables remain unchanged.

Together, the separate executable and configuration namespace make it possible to operate Prisma 7 and Prisma 8 side by side without command or config-file collisions.

#29949, #29969, #29994, #30000, #30002, #30020

Prisma Studio security hardening

Prisma Studio's local HTTP server now:

  • Binds explicitly to 127.0.0.1 instead of all network interfaces.
  • Rejects browser requests from origins other than the active localhost or 127.0.0.1 Studio URL.
  • No longer returns wildcard CORS headers.
  • Applies the same protections across Node.js, Bun, and Deno.

This prevents network clients or malicious websites from accessing Studio's database endpoints while Studio is running.

#29890

Prisma Client

  • Fixed P2002 errors from nested writes so meta.modelName identifies the model where the unique constraint violation occurred, including models using @@map and @@schema. #29628
  • Fixed automatically batched findUniqueOrThrow() calls so every missing record rejects with P2025; later misses no longer resolve to undefined. #29654
  • Parameter-chunked statements are now executed atomically in a transaction and rolled back if a later chunk fails. #29771
  • Improved interactive transaction cleanup during $disconnect(), including transactions whose driver-level startup is still in progress. #28768
  • Prevented transaction cleanup failures after a timeout or backend termination from becoming unhandled promise rejections. #29611
  • Fixed fluent relation queries when relation fields are literally named select or include. #29683
  • Fixed handling of Date and Uint8Array values created in other JavaScript realms, such as iframes, jsdom, and Node.js vm contexts. #29177
  • Invalid Date values passed to $queryRaw or $executeRaw now throw PrismaClientValidationError instead of a generic error. #29718
  • Fixed moduleFormat inference for the prisma-client generator in TypeScript projects using module: "node16" or "nodenext". Generated output now follows the nearest package.json type, defaulting to CommonJS when absent. #29712
  • Deserialized Bytes values now own standalone ArrayBuffers rather than exposing unrelated contents from Node.js's shared Buffer pool. This applies to both regular and raw query results. #29701
  • Fixed an incorrect logging context in the remote executor, including Accelerate-backed query execution. #28892

Client extensions and observability

  • Result-extension compute callbacks now receive the current model name as a typed second argument:

    compute(data, modelName) {
      // ...
    }

    The model name is also preserved when multiple extensions compose the same computed field. #29782

  • Improved OpenTelemetry context for remotely executed queries:

    • $on('query') callbacks run within the matching db_query span.
    • Events from one operation share the same trace.
    • Error events are recorded as span exceptions.
    • Log events continue to be emitted when tracing is disabled or their reported span is unavailable.

    #28892

Driver adapters

MariaDB

  • @prisma/adapter-mariadb now accepts an existing mariadb pool. External pools remain caller-owned unless disposeExternalPool: true is supplied. #27992
  • Fixed pooled connection leaks during commit, rollback, and failed transaction startup. Connections are now returned with release() and transaction-specific listeners are removed before reuse. #29612
  • Added support for bracketed IPv6 addresses in both mysql:// and mariadb:// connection strings. #29026
  • Prevented malformed connection strings from exposing embedded passwords in retained debug output and diagnostic reports. #27992

PostgreSQL, Neon, and Prisma Postgres Serverless

  • PostgreSQL deadlocks using SQLSTATE 40P01 are now reported as P2034 transaction write conflicts. #29717
  • PostgreSQL RESTRICT violations using SQLSTATE 23001 are now reported as P2003, preserving an available field or constraint name. #29554
  • @prisma/adapter-pg now preserves database constraint names when reporting unique constraint violations through P2002. #29587
  • Prisma Postgres Serverless now prefers the named constraint for P2002, falling back to parsed field names when no constraint name is available. #29801
  • Fixed Neon HTTP adapter serialization for typed parameters such as Bytes and DateTime. #29747

SQLite

  • @prisma/adapter-better-sqlite3 now converts previously unhandled SQLite result codes into typed database errors instead of exposing raw driver errors.
  • The complete SQLITE_BUSY family is now mapped to socket timeout errors, with numeric extended result codes preserved where available.

#29794

CLI and Migrate

  • prisma generate can now offer to install Prisma's agent skills. The opt-in prompt:

    • Is shown at most once per machine.
    • Is skipped in CI, containers, Git hooks, npm lifecycle scripts, and watch mode.
    • Is skipped when --no-hints is used or Prisma skills are already installed.
    • Times out after 30 seconds.
    • Never causes generation to fail if installation is unsuccessful.

    #29690

  • A globally installed CLI now warns during prisma generate when its version differs from the project's local prisma or @prisma/client, and recommends running the local CLI. The check is best-effort and does not fail generation. #29593

  • prisma version and prisma version --json now include the resolved Prisma CLI package path, making global-versus-local installation issues easier to diagnose. #29573

  • Empty or generator-only schema files now report Schema must contain a datasource block from db pull, db push, and migrate dev, rather than reaching the schema engine and potentially producing inconsistent errors. #29657

  • CLI commands now tolerate corrupt, unreadable, or unwritable command-state files. Invalid state is reinitialized, writes are atomic, and persistence failures fall back to in-memory state. #29609

  • ...

Read more

v8.0.0-rc.5

v8.0.0-rc.5 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 22 Aug 10:48
9b75b95

v8.0.0-rc.5

The ORM command family now ships the unified CLI's command paths directly, the Postgres runtime survives dropped idle connections, aggregation respects the chain it terminates, and the raw lane lets an outer query reuse an inner query's typed return columns.

The upgrade recipe for this hop: the user recipe.

Breaking changes

  • The ORM command family is keyed by the unified CLI's mount paths@prisma/orm-toolchain's command family now publishes the six moved commands under their unified spellings (contract format, db migrate, migration ref list|set|delete, orm init) instead of the retired standalone grammar (format, migrate, ref …, init), and every help example and error remediation names those paths (with the {bin} placeholder instead of a hardcoded binary name). Through the unified prisma CLI nothing moves — these were already the mounted paths — but a host that mounts the family by key, or a script driving the workspace binary with the old spellings, must respell the six commands. (#30102)

    Before:

    prisma migrate --to production
    prisma ref set staging 4cb4256

    After:

    prisma db migrate --to production
    prisma migration ref set staging 4cb4256

Features

  • A row-spec'd raw query exposes .returns, a record of typed column refs, so an outer raw query can reuse an inner query's declared column (for example a CTE's aggregate) instead of restating its codec id. (#30075)

Fixes

  • aggregate() now reduces over exactly the rows a chain's take / skip / cursor / distinct / distinctOn describes, instead of silently reducing over every matching row. (#30067)
  • groupBy() now scopes pre-group pagination to the rows it groups instead of dropping it, and GroupedCollection gained take / skip / orderBy to page the groups themselves. (#30092)
  • The Postgres runtime attaches 'error' listeners to every pool and client it creates or receives, so a dropped idle connection (database restart, pooler timeout, network blip) no longer crashes the process as an uncaught exception. Pools your own code constructs and uses directly still need a listener — see the upgrade recipe. (#30081)
  • The PSL language server recognizes connection errors raised by any bundled copy of vscode-jsonrpc, instead of crashing when a duplicated copy raised them. (#30077)
  • CLI error text interpolates the configured migrations directory instead of assuming the default path. (#30041)
  • orm init's failure messages no longer name retired flags or binaries (--no-skill, --force, prisma-cli init); they point at the flags that exist (--skip-skills, --confirm <directory name>) and the mounted prisma orm init. (#30083)

v8.0.0-rc.4

v8.0.0-rc.4 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 18 Aug 16:26
a21c452

v8.0.0-rc.4

The transition period for the old ORM config is over, and two fixes land for the consolidated prisma CLI stack. Most projects created before rc.2 need the config migration below; projects scaffolded by rc.2+ init need nothing.

The upgrade recipe for this hop: the user recipe.

Breaking changes

  • The deprecated config fallbacks are gone — the CLI no longer reads prisma-next.config.ts and no longer accepts the flat (un-nested) config shape; both now fail loudly instead of warning. The only config read is prisma.config.ts in the envelope shape, and the workspace prisma-next binary is retired — the unified CLI runs the ORM commands at the top level. Rename the file, wrap your ORM options in definePrismaConfig({ orm: ormConfig({ … }) }), and keep import 'dotenv/config' if your config reads process.env. See the user recipe for the exact rewrite. (#30058)

    Before:

    // prisma-next.config.ts
    import { defineConfig } from '@prisma/orm-postgres/config';
    
    export default defineConfig({ contract: './contract.prisma', db: { connection: process.env['DATABASE_URL']! } });

    After:

    // prisma.config.ts
    import 'dotenv/config';
    import { definePrismaConfig } from '@prisma/cli-engine';
    import { defineConfig as ormConfig } from '@prisma/orm-postgres/config';
    
    export default definePrismaConfig({
      orm: ormConfig({ contract: './contract.prisma', db: { connection: process.env['DATABASE_URL']! } }),
    });

Fixes

  • contract emit no longer crashes after writing its artifacts when the project root is a relative path — validateContractDeps() resolves the root before handing it to Node's createRequire(), which requires an absolute path. (#30064)
  • init scaffolds definePrismaConfig, the current name for the config marker in @prisma/cli-engine 0.2.0, instead of the deprecated defineConfig alias. (#30064)

v8.0.0-rc.3

v8.0.0-rc.3 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 18 Aug 10:46
1f4b98a

v8.0.0-rc.3

A single-purpose release: @prisma/orm-toolchain moves its exact @prisma/cli-engine peer from 0.1.1 to 0.2.0, so the unified prisma CLI can ship a release in which every mounted product runs on the one engine version it installs. There are no ORM API changes in this release.

Breaking changes

  • The exact @prisma/cli-engine peer moves to 0.2.0 — engine 0.2.0 adds the credential-refresh exports and structured delegated output that prisma@8.0.0-rc.4 was built against but the registry's engine 0.1.1 does not contain, which is why npx prisma@next currently fails on import. This release pairs with the prisma CLI release that depends on it (8.0.0-rc.5); upgrade both together. No code changes — an operational peer move only. (#30056)

v8.0.0-rc.2

v8.0.0-rc.2 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 17 Aug 13:31
75c9020

v8.0.0-rc.2

This release retires the prisma-next binary in favour of the unified prisma CLI, returns the default aggregates to plain JavaScript numbers with lossless variants beside them, makes CHECK constraints a declared part of the contract, and splits runtime row queries from non-returning writes. Almost every application will need to re-emit its contract and rename its config file, so read the breaking changes before upgrading.

Two upgrade recipes carry the mechanical translations for this hop: the user recipe and the extension-author recipe.

Breaking changes

  • This repository no longer publishes a CLI; the unified prisma CLI replaces it — nothing published ships a prisma-next bin anymore. @prisma/orm-toolchain exposes the orm command family at @prisma/orm-toolchain/cli and no binary, and the database facades forward no launcher. Install @prisma/cli (the prisma-cli distribution, published under next for the v8 line) and replace prisma-next <command> in package scripts and CI with the unified CLI. The config file moves with it: prisma-next.config.ts is deprecated in favour of prisma.config.ts, and the config value is now engine-shaped, with your existing ORM config nested under an orm section. Both the old filename and the flat shape still load, each printing a deprecation warning on stderr, so the rename and the rewrap can land separately. See the user recipe. (#30005)

    Before:

    // prisma-next.config.ts
    import { defineConfig } from '@prisma/orm-postgres/config';
    
    export default defineConfig({ contract: './contract.ts', output: './generated' });

    After:

    // prisma.config.ts
    import { defineConfig } from '@prisma/cli-engine';
    import { defineConfig as ormConfig } from '@prisma/orm-postgres/config';
    
    export default defineConfig({
      orm: ormConfig({ contract: './contract.ts', output: './generated' }),
    });
  • The default aggregates are JavaScript numbers again, with lossless variants beside themcount(), sum() over an integer column, and avg() over an integer column all return number. In 8.0.0-rc.1 they returned a bigint, a bigint or decimal string depending on the column's width, and a decimal string respectively. The lossless results moved to three new operations: countBigInt() returns a bigint, sumBigInt() returns a bigint, and avgDecimal() returns an exact decimal string (PostgreSQL only — SQLite has no decimal type and contributes none). A count() or integer sum() whose value passes ±(2^53 − 1) now raises RUNTIME.DECODE_FAILED rather than returning a rounded number, so move those calls to the BigInt variants where the magnitude is real. Unchanged: min/max, sum/avg over a float column, sum over Decimal, sum over UnboundedInt, and the ORM's having(...) operands. The SQL builder's comparison operands do move, because fns.gt(a, b) types both sides from one codec. The same PR also makes the wide-integer codecs refuse the wrong JavaScript type: a BigInt or UnboundedInt column rejects a number and a BigIntNumber column rejects a bigint, with RUNTIME.ENCODE_FAILED naming the type that arrived, where previously a number was accepted and stringified — which let a fractional value reach an integer column unremarked. See the user recipe. (#29930)

    Before:

    const { total } = await db.User.aggregate((a) => ({ total: a.count() }));
    total === 2n; // bigint
    
    const busy = await db.sql.public.user
      .groupBy('kind')
      .having((_f, fns) => fns.gt(fns.count(), 1n)); // bigint literal

    After:

    const { total } = await db.User.aggregate((a) => ({ total: a.count() }));
    total === 2; // number — countBigInt() returns the bigint
    
    const busy = await db.sql.public.user
      .groupBy('kind')
      .having((_f, fns) => fns.gt(fns.count(), 1)); // plain number literal
  • Which aggregate methods exist is now the contract's answer — the aggregate methods are no longer declared on the ORM and SQL-builder surfaces outright. Each surface is derived from the operation names in the emitted contract.d.ts's AggregateTypes block, so a target or extension can contribute an operation and it appears under its own name with no client change. PostgreSQL now contributes eight operations and SQLite seven. Re-emit your contract with the CLI's contract emit: against a contract with no AggregateTypes block — one authored in code with defineContract(...) and handed straight to the client, or emitted before 8.0.0-rc.1 — every aggregate surface resolves to AggregateOperationsUnavailable, an empty type, and each call becomes a compile error. What this release changes is compile-time only — the separate runtime guard introduced in 8.0.0-rc.1 still stands, rejecting an aggregate whose operation and input codec the composed target does not declare with ORM.AGGREGATE_UNSUPPORTED before the query runs. Separately, count(field) now renders COUNT(<column>) instead of accepting the argument and discarding it, so a call that got past the types — a @ts-expect-error, a count(x as never), or dynamic dispatch — now counts that field's non-null values rather than rows. See the user recipe and the extension-author recipe. (#29922)

  • CHECK constraints are declared in the contract, and introspection now sees all of them — the CHECK shape in contract.json changed from { name, column, valueSet } to { name, prefix, expression }, where expression is the raw SQL predicate and name is a content-addressed wire name (<prefix>_<8hex>, the convention indexes and RLS policies already use). An old-shape contract is rejected on read, so re-emitting is not optional. Three consequences to plan for. Your first migration plan after upgrading drops each old unsuffixed enum constraint and adds the wire-named one, which needs destructive to converge. Every list (many) column gains a declared element-non-null CHECK the planner previously created without declaring. And introspection stopped parsing predicates, so hand-written constraints earlier versions could not see are now visible — and an undeclared check is an extra that db verify --strict reports and a destructive-capable plan drops, so read the first plan for dropCheckConstraint operations naming constraints you wrote yourself, and declare each one you want to keep with @@check(expression: "…", map: "<physical name>"). Two API changes ride along: addCheckConstraint in committed migration files takes an expression instead of a column/values pair, and the typescriptContract options bag now requires createNamespace whenever it passes defaultControlPolicy. An enumType() whose codec is numeric now throws CONTRACT.ENUM_INVALID while the contract is being built rather than failing later at migrate time. See the user recipe and the extension-author recipe. (#29892)

    Before:

    this.addCheckConstraint({ schema, table, constraint, column: 'kind', values: ['admin', 'user'] });

    After:

    this.addCheckConstraint({ schema, table, constraint, expression: `"kind" IN ('admin', 'user')` });
  • Runtime row queries and non-returning writes are separate callsquery() streams rows and execute() resolves { affectedRows }, which is how a write now reports its affected count without a preceding SELECT. Classify each call site by the result it consumes rather than replacing every execute: a select, a returning write, or any plan whose rows are iterated, indexed, or decoded moves to query, while an insert, update, or delete that returns nothing stays on execute and reads affectedRows. Prepared row consumption moves from target.queryPrepared(prepared, params) to prepared.query(target, params). Runtime middleware splits the same way, into beforeQuery / interceptQuery / afterQuery and beforeExecute / interceptExecute / afterExecute with a shared beforeCompile; query interception returns { rows } and execute interception returns { stats }. There is no operation discriminator, compatibility alias, or generic fallback hook. On Mongo, db.query stays the static builder and the row-executing db.execute facade method is gone — build with db.query, then execute through (await db.runtime()).query(plan). See the user recipe. (#29921)

  • raw is a reserved storage namespace — the SQL surface exposes the whole-query raw statement tag as db.sql.raw, so a storage namespace of that name would be unreachable through the builder while the emitted types still promised its tables. Building the client now raises ORM.NAMESPACE_RESERVED naming the namespac...

Read more

v8.0.0-rc.1

v8.0.0-rc.1 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 07 Aug 10:53
a76a6c5

v8.0.0-rc.1

This is the first release on the v8 release-candidate line: releases are now versioned 8.0.0-rc.N instead of 0.x minors. It also makes every aggregate read back through the codec its target declares — count() returns a bigint — splits the SQL driver interface into a row-streaming call and a statistics call, and fixes four defects in query planning, emit, and driver error reporting.

The v8 release-candidate line

Releases are now versioned 8.0.0-rc.1, 8.0.0-rc.2, and so on, with the counter advancing on every release. "The v8 RC" is the product name; the number underneath iterates freely, so there is no promise that the last RC before 8.0.0 final is numbered rc.1. There are no further 0.x minors. The policy is written up in docs/oss/versioning.md. (#29899)

For every package this repository publishes, latest keeps tracking the newest release, RC included. These package names have no pre-v8 stable audience to protect — a bare npm install of one of them was already an early-access install, and still is. The bare prisma package is not published from this repository; its v8 CLI shim lives in prisma/prisma-cli.

Existing installs are not moved onto the RC line by npm update. Lockfiles pin resolved versions, and a ^0.x range can never match a 8.0.0-rc.N pre-release, because pre-releases do not satisfy stable ranges. Only a fresh install, or an explicit version change on your side, lands on the RC.

Development builds move to the same line: every push to main that does not change the root version publishes 8.0.0-rc.X-dev.N under the dev dist-tag.

An RC respin may still contain breaking changes. Until 8.0.0 final ships, the pre-1.0 latitude documented in docs/oss/versioning.md carries over: a new rc.N may remove or rename APIs, change the semantics of existing ones, or change the contract format. Read the breaking-changes section of each release before you upgrade.

Breaking changes

  • Aggregate results carry the codec their target declares — an aggregate is now read back through the codec its target declares for that result rather than through whatever the driver handed over, so aggregate application types change. count() is a bigint on both PostgreSQL and SQLite, at the top level and inside an include, and an empty relation reads 0n. On PostgreSQL, sum over int2/int4 widens to a bigint, while sum(int8) and avg over any integer are numeric and read as exact decimal strings; min/max keep the column's own type, except over varchar, which returns text. On SQLite, sum over an integer column is a bigint and avg is always a number. Sweep your code for equality and arithmetic against an aggregate result (count === 2 is false when count is 2n) and for JSON.stringify over one (it throws on a bigint). having(...) operands are the exception and stay plain numbers — they are compared inside SQL and never cross a codec. Regenerate your contracts (prisma-next contract emit): contract.d.ts gains an AggregateTypes block that both the ORM and the SQL builder resolve result types from, and against an older contract an aggregate resolves to never in the ORM and unknown in the SQL builder. The type is not the only guard: an aggregate whose operation and input codec the composed target does not declare is rejected before the query runs, with the error code ORM.AGGREGATE_UNSUPPORTED. See the upgrade recipe and the extension-author recipe. (#29867)

    Before:

    const rows = await posts.include('comments', (comments) => comments.count()).all();
    rows[0].comments === 2; // number; 0 when the relation is empty

    After:

    const rows = await posts.include('comments', (comments) => comments.count()).all();
    rows[0].comments === 2n; // bigint; 0n when the relation is empty
  • The SQL driver interface splits row streaming from statement statisticsSqlQueryable (exported from @internal/sql-relational-core/ast) is now two methods wide: query() streams rows and execute() returns { affectedRows }. The separate prepared-execution method is gone; a prepared plan is expressed by an optional preparedStatementHandle on the request instead, and a driver branches on whether that property is undefined. Application code, query results, and the contract format are unaffected — this only matters if you implement or wrap SqlQueryable yourself, in which case update your implementation to the two-method shape. There is no upgrade recipe entry for this; the change is the interface itself. (#29907)

    Before:

    interface SqlQueryable {
      execute<Row>(request: SqlExecuteRequest): AsyncIterable<Row>;
      executePrepared<Row>(request: PreparedExecuteRequest): AsyncIterable<Row>;
      query<Row>(sql: string, params?: readonly unknown[]): Promise<SqlQueryResult<Row>>;
    }

    After:

    interface SqlQueryable {
      query<Row>(request: SqlExecuteRequest): AsyncIterable<Row>;
      execute(request: SqlExecuteRequest): Promise<SqlStatementStats>;
    }

Features

  • prisma-next init installs one prisma-8 skill instead of eleven per-workflow skills, and removes the retired skill directories from every agent's install root on each run. Each skill is now installed by name — prisma-8, prisma-next-upgrade, and prisma-8-extension-upgrade — rather than by matching a wildcard against a directory, so a new skill landing beside them is not picked up by accident. (#29853)

Fixes

  • A column, table, or model mapped to a name that is not a bare TypeScript identifier — @map("has space"), @@map("data rows") — now emits a quoted property key in contract.d.ts instead of producing a syntactically invalid file that killed contract emit. String literals in emitted TypeScript also survive control characters and line separators, which previously produced the same failure by a different route. (#29889, #29898)
  • Nested some/every/none predicates over a self-referential relation now keep a distinct SQL alias at every level, so an inner scope no longer shadows the parent it is supposed to correlate against. This covers one-to-one, many-to-one, one-to-many, implicit many-to-many, and explicit-junction many-to-many relations in both directions, and relations whose physical tables share a bare name across namespaces. (#29900)
  • Scalar reducers on a many-to-many include — count(), sum(), avg(), min(), max() — now traverse the junction table instead of emitting a predicate against a foreign-key column that only exists on the junction, so a filtered relation count over a many-to-many relation returns the right number. (#29888)
  • A failed retry of a stale PostgreSQL prepared statement now surfaces a structured error envelope with the code DRIVER.PREPARE_FAILED, carrying the normalized driver error as its cause, instead of an unlabelled failure. (#29907)

v0.17.0

Choose a tag to compare

@github-actions github-actions released this 04 Aug 13:31
689981a

v0.17.0

This is the namespace release: Prisma Next now publishes as 17 packages under the @prisma scope, and an application depends on exactly one database facade. It also completes the structured error-code scheme across every plane, makes relation-loading lossless for big numbers and temporal values, and gives every SQL index and RLS policy an exact, migratable name.

Breaking changes

  • One @prisma package per application — the @prisma-next/* scope is retired; nothing publishes under it again. An application depends on exactly one database facade — @prisma/orm-postgres, @prisma/orm-sqlite, or @prisma/orm-mongo — plus any extension packs it uses (now named @prisma/orm-extension-*); everything else arrives as the facade's exact-pinned dependencies. Regenerating your contract rewrites generated imports to facade entrypoints with no contractHash change. See the 0.16-to-0.17 upgrade recipe and the extension-author recipe. (#29864, #29880, #29883, #29884)

    Before:

    "dependencies": {
      "@prisma-next/postgres": "0.16.0",
      "@prisma-next/framework-components": "0.16.0",
      "@prisma-next/sql-runtime": "0.16.0"
    }

    After:

    "dependencies": {
      "@prisma/orm-postgres": "0.17.0"
    }
  • Every published error is a structured envelope with a dotted code — the four legacy error systems (PN-CLI-4001-style codes, RUNTIME.DECODE_FAILED-style codes, and codeless error classes) consolidate into one scheme: a structural envelope carrying a NAMESPACE.SUBCODE code, recognized by the isStructuredError type predicate instead of instanceof. The ORM, contract-authoring, adapter/target, extension, and framework planes are all swept; legacy error classes (PslFormatError, the Supabase and SQL-escape classes, framework classes) are deleted. Prisma 7's P1001-style codes are not carried over. (#1016, #1021, #1025, #1049, #1053, #1063)

    Before:

    if (error instanceof PslFormatError) {
      report(error.diagnostics);
    }

    After:

    if (isStructuredError(error) && error.code === 'PSL.PARSE_FAILED') {
      report(error.meta.diagnostics);
    }
  • Content hashes are bare hex — the sha256: prefix is gone from every surface (emitted contracts, migration manifests, refs, CLI output, and the database marker), and loaders reject the prefixed form. Contract hash values are unchanged; migrationHash values change. A codemod in the 0.16-to-0.17 recipe converts checked-in migration trees. (#1033)

  • Migration contract snapshots move into a content-addressed store — per-migration sibling snapshot files and ref-paired copies are replaced by a single migrations/snapshots/<hex>/ store per migrations root; every distinct contract is stored once, and migration.ts imports its bookend contracts from the store. This is a clean break with no fallback reader; a one-shot migrator (scripts/migrate-migrations-layout.mjs) converts existing trees and re-verifies every migrationHash unchanged. (#1018, #1024)

  • PostgreSQL native types are authored in type position; the @db.* attribute channel is removed — write the native type directly (VarChar(255), Uuid, Timestamptz) instead of a base type plus @db.* attribute; remaining @db.X(args) usage fails with the exact replacement spelled out. Json re-binds to native json storage, with a new Jsonb scalar for jsonb (what every pre-0.16 Json field meant — switch those fields to keep a byte-identical contract), and Date re-binds to the correct pg/date@1 codec. (#1022, #1036, #1054)

    Before:

    model User {
      id    String @id @db.Uuid
      name  String @db.VarChar(255)
    }

    After:

    model User {
      id    Uuid         @id
      name  VarChar(255)
    }
  • Relation-loading and aggregates are lossless — values read through .include() no longer pass through lossy JSON: every codec gains an explicit lossless JSON form produced inside the database. 64-bit integers arrive as bigint instead of silently rounding, decimals as exact strings, and temporal columns decode correctly. Aggregate result types change accordingly: count() is a bigint, decimal sums are strings. Regenerate your contract after upgrading. (#29844, #1023, #1051)

  • SQL indexes and RLS policies are name-identified — every index and RLS policy carries an exact name in the contract, names travel on the wire, live objects can be adopted by exact name (@@map), and a rename converges by renaming instead of drop-and-recreate. (#1047, #29807, #29865)

  • extensionPacks config key renamed to extensions — in prisma-next.config.ts, the TS builder, client options, and the emitted contract's top-level key. The old key fails loudly. Because the key sits in the hashed contract bytes, all contract hashes change: re-emit and re-anchor migrations per the recipe. Two smaller key renames ride along: contract.source.sourceFormatformat, and the facade defineConfig option outputPathoutput. (#1032)

  • Count-only mutation terminals renamedcreateCount(...) / updateCount(...) / deleteCount() become createAndCount(...) / updateAndCount(...) / deleteAndCount(); behavior and Promise<number> results are unchanged, with no compatibility aliases. (#1044)

Features

  • Expression, partial, and unique indexes are authorable in both PSL and the TypeScript builder. (#1048)
  • contract infer reaches full fidelity — indexes, policy blocks, and @@rls are captured — and signs the database, so introspect-then-verify works end to end on an adopted database. It also infers 1:1 relations from unique indexes. (#29808, #1038)
  • Every error code is documented on an in-repo reference page (221 codes), kept complete by a CI check, and error envelopes carry a docsUrl pointing at their per-code anchor. (#1027, #29806)

Fixes

  • MongoDB write results decode through their type codecs instead of returning raw wire values. (#29879)
  • The Postgres runtime driver serializes queries per pinned client, fixing interleaved-query failures on a shared connection. (#29839)
  • Mixed-case native-enum casts are quoted, so PascalCase enum type names survive Postgres case-folding. (#1034)
  • Driver cursor streaming runs inside an explicit transaction, fixing dropped-portal failures under load. (#1017)
  • Published type declarations name only dependencies a consumer will actually have installed. (#29862)