v0.13.0
This release makes namespaces a first-class part of the query surface, adds cross-contract foreign keys to the SQL ORM, makes many-to-many a validatable contract shape, introduces a per-object control policy (@@control) that decides what Prisma manages, ships domain enums backed by storage value-sets, and gives the migration CLI a unified graph-tree view across list / log / status / show. Telemetry also flips from opt-in to opt-out. A few changes require a one-time contract re-emit — all are covered by the linked upgrade recipes.
Breaking changes
-
Telemetry is now opt-out — anonymous CLI telemetry is collected by default and you opt out, where previously you opted in. Set
PRISMA_NEXT_DISABLE_TELEMETRY=1(orDO_NOT_TRACK=1) to turn it off. Seedocs/Telemetry.mdfor what is collected and every opt-out signal. (#676) -
MTI variant tables materialize a base-PK link column — a PSL
@@base(Parent, "tag")variant that carries its own@@map(and is therefore stored in its own table) now emits a base-PK link column in storage: the variant table gains a copy of the base table's primary-key column(s), a primary key over them, and a cascading foreign key (ON DELETE CASCADE) referencing the base table's primary key. Previously the variant table held only the variant-specific columns with no primary key and no link to its base. This changes the emittedcontract.json/contract.d.tsand the contract'sstorageHash. Re-emit your contract, then plan and apply the matching migration. Variants that share the base table (no own@@map) are unaffected. See the 0.12→0.13 upgrade recipe. (#669)Before (emitted
contract.json, variant tablebug):"bug": { "columns": { "severity": { "codecId": "pg/text@1", "nullable": false } } }
After:
"bug": { "columns": { "id": { "codecId": "sql/char@1", "nullable": false }, "severity": { "codecId": "pg/text@1", "nullable": false } }, "primaryKey": { "columns": ["id"] }, "foreignKeys": [ { "name": "bug_id_fkey", "columns": ["id"], "references": { "table": "task", "columns": ["id"] }, "onDelete": "cascade" } ] }
-
Contract storage IR moved to a namespace envelope — the SQL/Mongo storage IR is now keyed by namespace (
storage.namespaces.<ns>.entries.<kind>), and cross-references are explicit{ namespace, model }objects indomain. Consumer impact is mechanical: re-emit withprisma-next contract emitto pick up the new shape. No codemod or source change is required, but the contract'sstorageHashchanges, so plan and apply a migration afterward. (#715) -
Extension authors: codec-resolution SPI takes a leading
namespaceId—CodecDescriptorRegistry.codecRefForColumn(table, column)is nowcodecRefForColumn(namespaceId, table, column), and the freecodecRefForStorageColumn(storage, table, column)is nowcodecRefForStorageColumn(storage, namespaceId, table, column)(both in@prisma-next/sql-relational-core). Thread the namespace the table lives in through every call site that stampscodeconto AST nodes. There is no codemod — the right namespace is call-site-specific. See the 0.12→0.13 extension-author recipe. (#715)Before:
const ref = descriptors.codecRefForColumn('document', 'embedding');
After:
const ref = descriptors.codecRefForColumn('public', 'document', 'embedding');
-
Extension authors: empty
typeParamsstripped fromstorage.types— the canonicalizer now omitstypeParamsfromstorage.typesentries when it is an empty object (e.g. atypes { Uuid = String @db.Uuid }named-type alias). Runtime behaviour is unchanged, but the emittedcontract.jsonand itsstorageHashdiffer. If your extension shipped acontract.jsonwith"typeParams": {}, re-emit and re-pin your migration baselines. See the 0.12→0.13 extension-author recipe. (#753)
Features
-
Namespace-aware DSL/ORM surface — the typed query and ORM surface now exposes namespaced accessors so models in different namespaces are addressed explicitly and two same-named tables in different namespaces no longer collide. Additive — existing single-namespace code is unchanged. (#720)
-
Many-to-many is now a validatable contract shape —
N:Mrelations carrying athroughjunction descriptor are now a first-class, validatable part of the contract (they previously failed validation). The ORM runtime surface for M:N —.include()across the junction,some/every/nonefilters, and junction writes — is not wired up yet and lands in a follow-up release; nested M:N mutations currently throw. (#669, #678) -
Cross-contract foreign keys — a relation field can reference a model owned by another contract space (e.g.
supabase:auth.AuthUser), with named-type aliases (types { Uuid = String @db.Uuid }) for database-native column types. The planner and verifier resolve the cross-space reference and emit the foreign key, including cascading deletes. See the 0.12→0.13 upgrade recipe for the authoring pattern. (#745, #752, #756, #765)types { Uuid = String @db.Uuid } namespace public { model Profile { id String @id @default(uuid()) username String userId Uuid @unique user supabase:auth.AuthUser @relation(fields: [userId], references: [id], onDelete: Cascade) @@map("profile") } }
-
Per-object control policy (
@@control) — a model or other contract object can declare whether Prisma manages its schema, and a contract can set adefaultControlPolicy. Migration DDL generation and schema verification react to each object's policy, so you can keep externally-owned objects out of Prisma's managed surface. (#717, #711) -
Domain enums with storage value-sets — enums are now a domain concept backed by storage value-sets. On Postgres,
enumblocks lower to a native enum type (CREATE TYPE … AS ENUM); SQL targets without native enum support approximate the allowed values with check constraints. (#750, #755) -
Unified migration graph view in the CLI —
migration list,log,status, andshownow render the migration history as a consistent graph tree with colored lanes, a--legend, and one schema-locked--jsonshape across the read commands.migrate --showpreviews the migration path read-only before you apply it. (#706, #704, #705, #735, #741, #767) -
Readable per-migration ledger — the migration apply ledger is now a per-migration journal, read back as one flat chronological table by
migration log. (#665, #704) -
db.transaction()on the SQLite facade —@prisma-next/sqlitegains a facade-level transaction API (db.transaction(async (tx) => …)), mirroring the Postgres facade. (#737) -
Declarative SPI for extension-contributed PSL blocks — extensions can declare top-level PSL blocks declaratively, and
contract inferround-trips them through a generic PSL printer. (#753, #754, #757) -
@prisma-next/extension-supabase— a new extension package and anexamples/supabasewalking skeleton that wires a cross-contract foreign key from an app model to Supabase'sauthschema. (#746, #765) -
STI variants can declare their own fields — a PSL
@@base(Parent, "tag")variant with no own@@map(single-table inheritance) may now declare its own scalar fields. Each is materialized as a (nullable) column on the shared base table, and the variant no longer emits a stray shadow table. Previously such a contract failed to emit withreferences non-existent column. Existing contracts re-emit identically. (#669) -
Backward cursor pagination —
OrderByItem.reverse()flips an order-by direction for fetching the previous page. (#671) -
Postgres JSON defaults emit a
::jsonb/::jsoncast — JSON column defaults now carry the explicit cast in generated DDL. (#763)