v8.0.0-rc.14
In this release, connect() on the Postgres serverless client returns a connection with db.orm, db.transaction(...) and db.prepare(...), the same members as a postgres() client. A date or time default is stored in one canonical text for each value, so its storage hash no longer depends on how the default was written. The Mongo ORM passes every value it writes, reads or filters on through its field's codec. The Postgres CLI commands now work with date and time defaults on Node 24, which has no Temporal.
The upgrade recipes for this hop: the app recipe and the extension recipe. Each breaking change below names the change id to look for in them.
Breaking changes
-
Serverless
connect()returns a connection, not aRuntime.postgresServerless(...).connect({ url })from@prisma/orm-postgres/serverlessnow returns a connection with the members of apostgres()client exceptconnect. Replaceruntime.query(plan)withdb.runtime().query(plan), and passdb.runtime()wherever theconnect()result was used as a runtime.connect()now opens the database connection before it returns, and rejects withDRIVER.CONNECTION_FAILEDwhen the database cannot be reached. Reads no longer go through a server-side cursor by default. Thecursoroption is nowPostgresCursorOptions,{ batchSize?: number }, so deletecursor: { disabled: true }. Seeserverless-connect-returns-connectionandserverless-cursor-default-offin the app recipe. (#30482)Before:
await using runtime = await db.connect({ url: env.HYPERDRIVE.connectionString }); const rows = await runtime.query(db.sql.public.user.select('id').build());
After:
await using db = await postgres.connect({ url: env.HYPERDRIVE.connectionString }); const rows = await db.runtime().query(db.sql.public.user.select('id').build());
-
A date or time default is stored in its type's canonical form. On Postgres and SQLite,
prisma contract emitstores each date or time default as one text for each value:@default("2024-01-01T01:00:00+01:00")on aDateTimecolumn is stored as"2024-01-01T00:00:00Z". TypeScript contracts store the same text. A default that was not already in that form gets a new storage hash. The database does not change: re-emit, then runprisma db sign, or record an empty migration withprisma migration new.contract emitnow refuses a default that the column's type does not hold, such as an offset on aTimestampcolumn, withPSL_INVALID_DEFAULT_LITERAL. Seedate-time-default-stored-in-canonical-form,date-time-default-refused-textanddate-time-ts-default-stored-in-canonical-formin the app recipe. (#30532)Before, accepted and stored as written:
model Event { id Int @id localAt Timestamp @default("2024-01-01T00:00:00Z") }
After, because a
Timestampcolumn holds no offset:model Event { id Int @id localAt Timestamp @default("2024-01-01T00:00:00") }
-
The Mongo ORM checks every value through its field's codec. A write of a value of the wrong type, of a fraction or an out-of-range number to an
Int32field, of a value outside the field's enum, or ofnullto a required field now fails withRUNTIME.ENCODE_FAILEDnaming the field. Before, some of these were stored as given. A filter expression passed towhere()is encoded the same way, so a filter on anInt64field needs abigint.create()andcreateAll()return the document as stored, decoded like a read, and a nullable field missing from a stored document reads asnull, notundefined. The query builder'smatch()still sends values as given. See themongo-*entries in the app recipe. (#30519)Before:
db.orm.posts.where(MongoFieldFilter.gt('views', Long.fromNumber(5)))
After:
db.orm.posts.where(MongoFieldFilter.gt('views', new MongoParamRef(5n)))
-
temporal-polyfillis a peer dependency of the Postgres packages.@prisma/orm-postgresand@prisma/orm-target-postgresnow declaretemporal-polyfillas a required peer dependency. npm, pnpm and bun install it automatically. A project that installs with Yarn must addtemporal-polyfill(^1.0.4) to its own dependencies. Seetemporal-polyfill-is-a-peer-dependencyin the app recipe. (#30520) -
The toolchain requires
@prisma/cli-engine0.6.2. A project that pins@prisma/cli-engineitself must move the pin from0.6.1to0.6.2. With this engine, hints, warnings and errors print the name of the CLI, as inprisma db migrate, where they used to print a literal{bin}. A script that matches{bin}in the CLI's output must match the CLI name instead. Seeengine-pin-moves-to-0-6-2in the app recipe. (#30503) -
Contract source warnings are diagnostics.
prisma contract emitandprisma contract printreport a source warning, such asPSL_DEPRECATED_SCALAR_NAME, as awarndiagnostic of the result instead of a free-textwarning …line. With--json, it is in thediagnosticsof the result. A script that read the old lines must readdiagnosticsinstead. Seecontract-source-warnings-are-diagnosticsin the app recipe. (#30519) -
Extension authors: Mongo result shapes, insert results and codecs changed.
contractModelToMongoResultShapetakesincludes, a map from relation name to the shape of the included document, instead ofincludeRelationNames.compileMongoQuerytakes the contract's value objects as a fifth argument.InsertOneResultandInsertManyResultcarry the inserted documents as stored, so a Mongo driver of your own must yield them. Themongo/double@1codec'sencodereturns the driver'sDouble, and the other Mongo codecs refuse a value of the wrong type.reportUnknownFieldPresettakes theauthoringContributions. See the extension recipe. (#30519)Before:
contractModelToMongoResultShape(model, { includeRelationNames: ['author'] });
After:
contractModelToMongoResultShape(model, { includes: { author: authorShape }, valueObjects });
Features
- A serverless connection has
db.orm,db.transaction(...)anddb.prepare(...). Inside a request, code written for apostgres()client works on the connection thatpostgres.connect({ url })returns, so a hand-builtorm({ runtime, context })andwithTransaction(runtime, fn)are no longer needed. The serverless client also gainsraw,enumsandnativeEnums. (#30482) postgres()takes acursoroption.postgres({ ..., cursor: { batchSize: 100 } })reads through a server-side cursor in batches, aspostgresServerless()does with the same option. Without the option, reads are buffered. (#30482)- The language server reads a multi-file schema as one project. When
contractinprisma.config.tsnames a pattern such as./*.prisma, files you have not opened contribute their models to the others and receive diagnostics. Before, the server read the pattern as a literal file path. (#30456)
Fixes
- On Node 24, which has no
Temporal,prisma contract emit,db init,db update,contract infer,node migration.ts, the Vite plugin and the language server work on a Postgres schema with a date or time default. Before, they failed with a message that the runtime has no globalTemporalimplementation. (#30520) - A Mongo
Doublefield stores a whole number as a BSONdouble. Before, the write failed withDocument failed validation.ObjectId[],Int64[],Decimal128[]andBinary[]fields can be written, and a query-builder filter that compares with anObjectId,Long,Decimal128orBinarymatches the stored value. (#30519) - Mongo reads decode documents from
include()and composite-type fields through their codecs, so anObjectIdin them reads as a hex string and anInt64as abigint. (#30519) - A Mongo
upsert()whosecreatesets a field that has an update default, such astemporal.updatedAt(), inserts thecreatevalue. Before, the insert got the current time. (#30519) prisma db updateon MongoDB can confirm and apply a destructive change. A validator change that only admits more values, such asJsontoBson, is no longer called destructive. (#30519)- On SQLite, a new
DateTimecolumn's default is the same text the application writes for the same instant, so rows that took the default compare and sort correctly against rows the application wrote. (#30532) - When two namespaces declare models with the same name, each relation points to the model in its own namespace. Before, a relation could point to the same-named model in another namespace. An unknown field type reports one diagnostic instead of two. (#30478)
- A Postgres
policy_*block whose target model is declared outside the block's namespace is stored in the namespace of the table it protects. (#30381) - When
prisma db signrefuses because the database does not match the contract, it offers both ways out: change the database withprisma db update, or change the contract source to describe the database and emit again. It says which one changes the database. (#30438) - The
8.0.0-rc.12to8.0.0-rc.13upgrade guides include a script that renames the default references in migration snapshots, in place of the renaming by hand. (#30453)