upgrading/extension/upgrades/8.0.0-rc.5-to-8.0.0-rc.6/instructions.md
upgrading/extension/upgrades/8.0.0-rc.5-to-8.0.0-rc.6/instructions.mdBrowse 76 files
6,232 bytes
Token encoding: o200k_base
Snapshot fac8604
from: "8.0.0-rc.5" to: "8.0.0-rc.6" changes:
-
id: postgres-temporal-codec-ids-retired summary: | Five PostgreSQL temporal codec ids were removed with no compatibility aliases. Each native type now has two representation-explicit codecs — one whose application value is a
Temporal.*, one that passes PostgreSQL's own text through unchanged:Retired Temporal replacement Text replacement pg/date@1pg/date-temporal@1(Temporal.PlainDate)pg/date-string@1pg/timestamp@1pg/timestamp-temporal@1(Temporal.PlainDateTime)pg/timestamp-string@1pg/timestamptz@1pg/timestamptz-temporal@1(Temporal.Instant)pg/timestamptz-string@1pg/time@1pg/time-temporal@1(Temporal.PlainTime)pg/time-string@1sql/timestamp@1pg/timestamptz-temporal@1pg/timestamptz-string@1An extension names these ids in more places than a user does. Sweep all of them:
- Column descriptors in an extension contract. A pack that declares its own tables
(
extensionModel(...)with{ codecId, nativeType }column literals) picks the representation on its consumers' behalf. Choose the Temporal id where application code reads the column as a value, and the*Stringid where it should stay text — the Supabase pack'sauthtables took the Temporal id for exactly that reason. descriptor-metaregistrations, control-plane hooks and aggregate matrices. Any table keyed by codec id gains two entries where it had one, or moves its single entry. A parity or coverage table that enumerates ids needs the four new*-string@1ids as well as the four*-temporal@1ones.- Hand-built contracts and test doubles. Deserializing a contract literal that names a retired id now fails validation rather than resolving to something plausible.
- Introspection maps.
date,timestamp,timestamptzandtimemap to the bare PSL names (Date,Timestamp(p),Timestamptz(p),Time(p)), which resolve to the Temporal codecs. The*Stringnames are authoring-only and must claim notargetTypes, or they compete for introspection ownership. - Re-emit any contract your package commits.
build:contract-space(orprisma contract emit) rewritescontract.jsonandcontract.d.ts; commit both. detection: glob: "**/*.{ts,mts,cts,json}" regex: - "pg/(date|timestamp|timestamptz|time)@1" - "sql/timestamp@1" anyMatch: true
- Column descriptors in an extension contract. A pack that declares its own tables
(
-
id: temporal-codecs-require-a-global-and-refuse-a-date summary: | A Temporal-backed codec reads the application's global
Temporalimplementation. Prisma neither bundles nor imports a polyfill, and the check is lazy: registering a pack, validating a contract, resolving a descriptor and constructing a codec instance all succeed with noTemporalin scope. Only invoking one fails, withRUNTIME.TEMPORAL_UNAVAILABLE.Two consequences for an extension:
- Your test suites need the global. If your package exercises a Temporal-backed
column, install a polyfill in a vitest
setupFilesentry (import 'temporal-polyfill/full/global';) and addtemporal-polyfillas a devDependency. For TypeScript to see the same global, add a.d.tsunder your test directory containing/// <reference types="temporal-polyfill/types/global" />— the package's owntemporal-polyfill/globaltypes resolve toexport {}and declare nothing. - Encode is nominally typed now. These codecs check
Symbol.toStringTagand refuse anything that is not their own Temporal type, including aDate, withRUNTIME.ENCODE_FAILEDnaming the codec. If your pack contributes a mutation-default generator or any other value that lands in a Temporal-backed column, it must produce the matchingTemporal.*value — aDateno longer slips through to be serialized asDate.prototype.toString(). detection: glob: "**/*.{ts,mts,cts}" regex: - "pg/(date|timestamp|timestamptz|time)-temporal@1" anyMatch: true
- Your test suites need the global. If your package exercises a Temporal-backed
column, install a polyfill in a vitest
-
id: contract-space-restamp summary: | The emitted contract artifacts embed the toolchain version, which moves to 8.0.0-rc.6. Rebuild the extension's contract space (the package's
build:contract-spacescript) once after upgrading so the emitted artifacts match the installed toolchain. The toolchain also re-released against@prisma/cli-engine@0.2.2(a CLI-side fix with no extension-facing surface). detection: glob: "**/contract.json" contains: - '"version": "8.0.0-rc.5"'
8.0.0-rc.5 → 8.0.0-rc.6 — Extension author upgrade instructions
PostgreSQL temporal representations, for extension authors
There is no codemod: the retired ids map to two replacements each, and which one an extension should name is a judgement about what its consumers do with the column. Sweep by id, decide per site, then re-emit any committed contract artifact.
Four behaviours bear on an extension's own codecs. Writes serialize at full precision and let
PostgreSQL round to the column's declared precision, carries included. A Temporal codec rejects
infinity, years beyond roughly ±271821, and non-ISO DateStyle output, naming the *String type
that reads them losslessly. The driver hands temporal OIDs through as server text rather than
building a Date. And temporal expressions are cast to text before PostgreSQL builds JSON, so a
nested read returns the same text a flat one does.
contract-space-restamp
For every contract.json matched by detection, run the extension package's build:contract-space script (or its emit command) once after upgrading. Beyond the temporal changes above, the only expected diff is the embedded version moving to 8.0.0-rc.6. The toolchain also re-released against @prisma/cli-engine@0.2.2; that change has no extension-facing surface.