@prisma/orm-mongo 8.0.0-rc.4-dev.17 → 8.0.0-rc.5-dev.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +11 -10
- package/skills/prisma-8/SKILL.md +84 -0
- package/skills/prisma-8/references/build.md +142 -0
- package/skills/prisma-8/references/contract.md +417 -0
- package/skills/prisma-8/references/debug.md +141 -0
- package/skills/prisma-8/references/feedback.md +251 -0
- package/skills/prisma-8/references/migration-review.md +224 -0
- package/skills/prisma-8/references/migrations.md +519 -0
- package/skills/prisma-8/references/queries-mongo.md +236 -0
- package/skills/prisma-8/references/queries-postgres.md +415 -0
- package/skills/prisma-8/references/queries.md +168 -0
- package/skills/prisma-8/references/quickstart.md +326 -0
- package/skills/prisma-8/references/runtime.md +344 -0
- package/skills/prisma-8/references/supabase.md +244 -0
- package/skills/prisma-8/references/upgrade-app.md +101 -0
- package/skills/prisma-8/references/upgrade-extension.md +105 -0
- package/skills/prisma-8/upgrading/app/upgrades/0.10-to-0.11/instructions.md +56 -0
- package/skills/prisma-8/upgrading/app/upgrades/0.11-to-0.12/instructions.md +381 -0
- package/skills/prisma-8/upgrading/app/upgrades/0.11-to-0.12/re-emit-closed-mongo-contracts.ts +202 -0
- package/skills/prisma-8/upgrading/app/upgrades/0.11-to-0.12/re-emit-domain-namespaced-contracts.ts +201 -0
- package/skills/prisma-8/upgrading/app/upgrades/0.11-to-0.12/re-emit-postgres-public-default.ts +198 -0
- package/skills/prisma-8/upgrading/app/upgrades/0.11-to-0.12/strip-migration-labels-hints.ts +340 -0
- package/skills/prisma-8/upgrading/app/upgrades/0.12-to-0.13/instructions.md +339 -0
- package/skills/prisma-8/upgrading/app/upgrades/0.12-to-0.13/re-emit-mti-variant-link-columns.ts +229 -0
- package/skills/prisma-8/upgrading/app/upgrades/0.13-to-0.14/instructions.md +543 -0
- package/skills/prisma-8/upgrading/app/upgrades/0.13-to-0.14/migration-op-factories-to-methods.ts +290 -0
- package/skills/prisma-8/upgrading/app/upgrades/0.13-to-0.14/uuid-preset-rename.ts +43 -0
- package/skills/prisma-8/upgrading/app/upgrades/0.14-to-0.15/instructions.md +359 -0
- package/skills/prisma-8/upgrading/app/upgrades/0.15-to-0.16/instructions.md +173 -0
- package/skills/prisma-8/upgrading/app/upgrades/0.16-to-0.17/instructions.md +805 -0
- package/skills/prisma-8/upgrading/app/upgrades/0.16-to-0.17/strip-sha256-hash-prefixes.ts +382 -0
- package/skills/prisma-8/upgrading/app/upgrades/0.17-to-8.0.0-rc.1/instructions.md +72 -0
- package/skills/prisma-8/upgrading/app/upgrades/0.7-to-0.8/instructions.md +8 -0
- package/skills/prisma-8/upgrading/app/upgrades/0.8-to-0.9/instructions.md +36 -0
- package/skills/prisma-8/upgrading/app/upgrades/0.8-to-0.9/strip-inline-contracts.ts +226 -0
- package/skills/prisma-8/upgrading/app/upgrades/0.9-to-0.10/instructions.md +86 -0
- package/skills/prisma-8/upgrading/app/upgrades/0.9-to-0.10/stamp-storage-types-kind.ts +360 -0
- package/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.1-to-8.0.0-rc.2/instructions.md +588 -0
- package/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.2-to-8.0.0-rc.3/instructions.md +5 -0
- package/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.3-to-8.0.0-rc.4/instructions.md +158 -0
- package/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.4-to-8.0.0-rc.5/instructions.md +42 -0
- package/skills/prisma-8/upgrading/extension/upgrades/0.10-to-0.11/instructions.md +276 -0
- package/skills/prisma-8/upgrading/extension/upgrades/0.11-to-0.12/instructions.md +738 -0
- package/skills/prisma-8/upgrading/extension/upgrades/0.11-to-0.12/migrate-contract-testing-imports.ts +97 -0
- package/skills/prisma-8/upgrading/extension/upgrades/0.11-to-0.12/regenerate-extension-public-baseline.ts +223 -0
- package/skills/prisma-8/upgrading/extension/upgrades/0.11-to-0.12/strip-migration-labels-hints.ts +340 -0
- package/skills/prisma-8/upgrading/extension/upgrades/0.12-to-0.13/instructions.md +266 -0
- package/skills/prisma-8/upgrading/extension/upgrades/0.13-to-0.14/instructions.md +522 -0
- package/skills/prisma-8/upgrading/extension/upgrades/0.13-to-0.14/migration-op-factories-to-methods.ts +290 -0
- package/skills/prisma-8/upgrading/extension/upgrades/0.13-to-0.14/uuid-preset-rename.ts +43 -0
- package/skills/prisma-8/upgrading/extension/upgrades/0.14-to-0.15/instructions.md +803 -0
- package/skills/prisma-8/upgrading/extension/upgrades/0.15-to-0.16/instructions.md +219 -0
- package/skills/prisma-8/upgrading/extension/upgrades/0.16-to-0.17/instructions.md +731 -0
- package/skills/prisma-8/upgrading/extension/upgrades/0.16-to-0.17/strip-sha256-hash-prefixes.ts +382 -0
- package/skills/prisma-8/upgrading/extension/upgrades/0.17-to-8.0.0-rc.1/instructions.md +194 -0
- package/skills/prisma-8/upgrading/extension/upgrades/0.7-to-0.8/instructions.md +8 -0
- package/skills/prisma-8/upgrading/extension/upgrades/0.8-to-0.9/instructions.md +57 -0
- package/skills/prisma-8/upgrading/extension/upgrades/0.8-to-0.9/strip-inline-contracts.ts +226 -0
- package/skills/prisma-8/upgrading/extension/upgrades/0.9-to-0.10/instructions.md +150 -0
- package/skills/prisma-8/upgrading/extension/upgrades/0.9-to-0.10/stamp-storage-types-kind.ts +360 -0
- package/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.1-to-8.0.0-rc.2/instructions.md +746 -0
- package/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.2-to-8.0.0-rc.3/instructions.md +5 -0
- package/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.3-to-8.0.0-rc.4/instructions.md +137 -0
- package/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.4-to-8.0.0-rc.5/instructions.md +129 -0
|
@@ -0,0 +1,543 @@
|
|
|
1
|
+
---
|
|
2
|
+
from: "0.13"
|
|
3
|
+
to: "0.14"
|
|
4
|
+
changes:
|
|
5
|
+
- id: uuid-preset-rename
|
|
6
|
+
summary: |
|
|
7
|
+
The uuid field presets are renamed: `field.uuid()` → `field.uuidString()`,
|
|
8
|
+
`field.id.uuidv4()` → `field.id.uuidv4String()`, `field.id.uuidv7()` →
|
|
9
|
+
`field.id.uuidv7String()`. These names now describe the storage encoding
|
|
10
|
+
(char(36) string). Postgres-native uuid storage uses the new
|
|
11
|
+
`field.uuidNative()` / `field.id.uuidv4Native()` / `field.id.uuidv7Native()`
|
|
12
|
+
presets from `@internal/postgres/contract-builder`.
|
|
13
|
+
detection:
|
|
14
|
+
glob: "**/*.ts"
|
|
15
|
+
contains:
|
|
16
|
+
- "field.uuid()"
|
|
17
|
+
- "field.id.uuidv4()"
|
|
18
|
+
- "field.id.uuidv7()"
|
|
19
|
+
anyMatch: true
|
|
20
|
+
script: uuid-preset-rename.ts
|
|
21
|
+
- id: qualify-flat-builder-accessors
|
|
22
|
+
summary: |
|
|
23
|
+
The builder-layer flat accessors are removed: the query builder and ORM client now
|
|
24
|
+
expose per-namespace facets only, and the Postgres facade exposes the qualified
|
|
25
|
+
surface. Code that builds queries against a Postgres (multi-namespace) contract must
|
|
26
|
+
name the namespace the table/model is declared in: `db.sql.<table>` becomes
|
|
27
|
+
`db.sql.<namespace>.<table>` and `db.orm.<Model>` becomes
|
|
28
|
+
`db.orm.<namespace>.<Model>` (for a standard single-schema Postgres project the
|
|
29
|
+
namespace is `public`). Code that calls the builder outputs directly migrates the
|
|
30
|
+
same way: `sql.<table>` → `sql.<namespace>.<table>`, `orm.<Model>` →
|
|
31
|
+
`orm.<namespace>.<Model>`. SQLite and Mongo projects are unaffected — their
|
|
32
|
+
single-namespace facade keeps flat `db.sql.<table>` / `db.orm.<Model>` working. There
|
|
33
|
+
is no codemod: the correct namespace is the one each table/model is declared in, which
|
|
34
|
+
is call-site-specific.
|
|
35
|
+
detection:
|
|
36
|
+
glob: "**/*.{ts,tsx}"
|
|
37
|
+
contains:
|
|
38
|
+
- "db.sql."
|
|
39
|
+
- "db.orm."
|
|
40
|
+
anyMatch: true
|
|
41
|
+
- id: sql-runtime-base-class-naming
|
|
42
|
+
summary: |
|
|
43
|
+
`@internal/sql-runtime` now exports `abstract class SqlRuntimeBase` (previously
|
|
44
|
+
`SqlRuntime`) — the family-layer subclass seam. Target classes are now named with
|
|
45
|
+
`Impl` suffix: `PostgresRuntimeImpl` and `SqliteRuntimeImpl`. The bare names
|
|
46
|
+
`PostgresRuntime` and `SqliteRuntime` are now interfaces — the correct types to
|
|
47
|
+
depend on in extension and app code. App code using the facade factories
|
|
48
|
+
(`postgres(...)`, `sqlite(...)`) is unaffected.
|
|
49
|
+
detection:
|
|
50
|
+
glob: "**/*.{ts,tsx}"
|
|
51
|
+
contains:
|
|
52
|
+
- "SqlRuntime"
|
|
53
|
+
- "PostgresRuntime"
|
|
54
|
+
- "SqliteRuntime"
|
|
55
|
+
anyMatch: true
|
|
56
|
+
- id: create-runtime-removed
|
|
57
|
+
summary: |
|
|
58
|
+
`createRuntime` is removed from `@internal/sql-runtime`. Use the target
|
|
59
|
+
factory (`postgres(...)` / `sqlite(...)`) or construct the target class
|
|
60
|
+
directly: `new PostgresRuntimeImpl({...})` from `@internal/postgres/runtime`,
|
|
61
|
+
`new SqliteRuntimeImpl({...})` from `@internal/sqlite/runtime`. App code
|
|
62
|
+
using the facade factories (`postgres(...)`, `sqlite(...)`) is unaffected.
|
|
63
|
+
detection:
|
|
64
|
+
glob: "**/*.{ts,tsx}"
|
|
65
|
+
contains:
|
|
66
|
+
- "createRuntime"
|
|
67
|
+
- id: migration-op-factories-to-methods
|
|
68
|
+
summary: |
|
|
69
|
+
The bare migration op factory functions are removed from
|
|
70
|
+
`@internal/postgres/migration`. Replace each import and call-site with
|
|
71
|
+
the corresponding method on `this` inside your `Migration` subclass. The
|
|
72
|
+
option shapes changed from positional arguments to a single options object.
|
|
73
|
+
detection:
|
|
74
|
+
glob: "**/migration.ts"
|
|
75
|
+
contains:
|
|
76
|
+
- "from '@internal/postgres/migration'"
|
|
77
|
+
- "from '@internal/target-postgres/migration'"
|
|
78
|
+
anyMatch: true
|
|
79
|
+
script: migration-op-factories-to-methods.ts
|
|
80
|
+
- id: postgres-contract-serializer
|
|
81
|
+
summary: |
|
|
82
|
+
`SqlContractSerializer` (from `@internal/family-sql/ir`) can no longer
|
|
83
|
+
deserialize Postgres contracts. The family serializer has an empty entries
|
|
84
|
+
registry and now rejects the `type` key that every Postgres namespace carries.
|
|
85
|
+
Any migration file or app code that calls
|
|
86
|
+
`new SqlContractSerializer().deserializeContract(postgresContractJson)` must
|
|
87
|
+
switch to `new PostgresContractSerializer()` imported from
|
|
88
|
+
`@internal/target-postgres/runtime`.
|
|
89
|
+
detection:
|
|
90
|
+
glob: "**/*.{ts,tsx}"
|
|
91
|
+
contains:
|
|
92
|
+
- "SqlContractSerializer"
|
|
93
|
+
- id: enum-becomes-domain-concept
|
|
94
|
+
summary: |
|
|
95
|
+
The PSL `enum` keyword now authors the domain enum (a text-class column whose
|
|
96
|
+
value set is enforced by a CHECK constraint) — the native Postgres
|
|
97
|
+
`CREATE TYPE … AS ENUM` semantics are gone. An `enum` block must carry
|
|
98
|
+
`@@type("<codec-id>")` (e.g. `@@type("pg/text@1")`), members map to database
|
|
99
|
+
values with `Name = "value"` (a bare member name defaults to itself where the
|
|
100
|
+
codec accepts it), and `@map` on members is removed — the member value IS the
|
|
101
|
+
mapping. The transitional `enum2` keyword is retired; rename those blocks to
|
|
102
|
+
`enum` (emitted contract is identical). The TS authoring equivalent is
|
|
103
|
+
`enumType(name, codecRef, ...member(name, value))` from
|
|
104
|
+
`@internal/postgres/contract-builder` returned under the contract's `enums`
|
|
105
|
+
key; the old native `enumType(name, values[])` / `enumColumn` from
|
|
106
|
+
`@internal/adapter-postgres/column-types` are deleted. Databases that
|
|
107
|
+
already carry a native enum type need a one-time converting migration (alter
|
|
108
|
+
column to text USING ::text, add the value-set CHECK, DROP TYPE) — `contract
|
|
109
|
+
infer` refuses native enum types by design and names them in its diagnostic.
|
|
110
|
+
detection:
|
|
111
|
+
glob: "**/*.prisma"
|
|
112
|
+
contains:
|
|
113
|
+
- "enum "
|
|
114
|
+
- "enum2 "
|
|
115
|
+
anyMatch: true
|
|
116
|
+
- id: generated-models-export-removed
|
|
117
|
+
summary: |
|
|
118
|
+
The generated `contract.d.ts` no longer emits the flat top-level
|
|
119
|
+
`export type Models`. Models resolve per-namespace from the domain plane:
|
|
120
|
+
replace a reference to the generated `Models` with
|
|
121
|
+
`Contract['domain']['namespaces']['<namespace>']['models']` (use `public`
|
|
122
|
+
for a standard single-schema Postgres project, `__unbound__` for SQLite or
|
|
123
|
+
Mongo). Re-emit the contract to drop the export.
|
|
124
|
+
detection:
|
|
125
|
+
glob: "**/*.{ts,tsx}"
|
|
126
|
+
contains:
|
|
127
|
+
- "Models"
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
<!--
|
|
131
|
+
TML-2867: codec-routed DDL defaults. The migration planner now resolves each plan
|
|
132
|
+
operation lazily (operations are `Promise<Op>[]`), and DDL execute steps carry a
|
|
133
|
+
`params` array. The example migration fixtures (`prisma-8-demo`,
|
|
134
|
+
`prisma-8-postgis-demo`) were regenerated to reflect the added `params` field.
|
|
135
|
+
No user-side API change. Incidental substrate diff only.
|
|
136
|
+
-->
|
|
137
|
+
|
|
138
|
+
<!--
|
|
139
|
+
TML-2852: the enum read surface. `enumType`-authored enums become first-class in
|
|
140
|
+
application code — an enum-restricted field's value union flows into the static
|
|
141
|
+
read/write types of both query lanes, `db.enums.<namespace>.<Name>` exposes the
|
|
142
|
+
enum at runtime (a lane-agnostic facade map), and `ORDER BY` on an enum column
|
|
143
|
+
sorts by declaration order. Purely additive and opt-in: PSL `enum` stays native
|
|
144
|
+
until the cutover, so only `enumType`-authored contracts exercise it, and
|
|
145
|
+
`fixtures:check` is byte-identical for every existing contract. No user-side
|
|
146
|
+
action — the examples/ diff is the new feature's demonstration. Incidental
|
|
147
|
+
substrate diff only.
|
|
148
|
+
|
|
149
|
+
TML-2838: the PGlite-backed example apps (`prisma-8-demo`, `react-router-demo`,
|
|
150
|
+
`supabase`, `bundle-size`, `multi-extension-monorepo`) switched their vitest
|
|
151
|
+
`pool` from `threads` to `forks` and pass `--no-memory-protection-keys`. Running
|
|
152
|
+
PGlite (WebAssembly) across vitest worker threads intermittently aborts on Linux
|
|
153
|
+
with a residual V8 JIT-page race (`jit_page_->allocations_.erase`) that
|
|
154
|
+
`@prisma/dev` 0.24.12 reduced but did not fully eliminate; process-per-fork with
|
|
155
|
+
PKU JIT-hardening disabled removes it. Test-harness only — no runtime, contract,
|
|
156
|
+
or public-API change. Incidental substrate diff only.
|
|
157
|
+
-->
|
|
158
|
+
|
|
159
|
+
# 0.13 → 0.14 — User upgrade instructions
|
|
160
|
+
|
|
161
|
+
## `uuid-preset-rename`
|
|
162
|
+
|
|
163
|
+
The uuid field preset names now include the storage encoding suffix:
|
|
164
|
+
|
|
165
|
+
| Before | After |
|
|
166
|
+
| --- | --- |
|
|
167
|
+
| `field.uuid()` | `field.uuidString()` |
|
|
168
|
+
| `field.id.uuidv4()` | `field.id.uuidv4String()` |
|
|
169
|
+
| `field.id.uuidv7()` | `field.id.uuidv7String()` |
|
|
170
|
+
|
|
171
|
+
These presets store UUIDs as `char(36)` strings and work across all SQL targets. If you want the Postgres-native `uuid` column type instead, use `field.uuidNative()` / `field.id.uuidv4Native()` / `field.id.uuidv7Native()` from `@internal/postgres/contract-builder`.
|
|
172
|
+
|
|
173
|
+
The rename is mechanical. Run the colocated script or apply the following find-and-replace in your `contract.ts` (or wherever you use the field builder):
|
|
174
|
+
|
|
175
|
+
```ts
|
|
176
|
+
// Before
|
|
177
|
+
id: field.id.uuidv7(),
|
|
178
|
+
userId: field.id.uuidv4(),
|
|
179
|
+
externalId: field.uuid(),
|
|
180
|
+
|
|
181
|
+
// After
|
|
182
|
+
id: field.id.uuidv7String(),
|
|
183
|
+
userId: field.id.uuidv4String(),
|
|
184
|
+
externalId: field.uuidString(),
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
No change to `contract.json` — both the old and new preset names emit the same codec (`sql/char@1`), so existing emitted contracts remain valid.
|
|
188
|
+
|
|
189
|
+
## `qualify-flat-builder-accessors`
|
|
190
|
+
|
|
191
|
+
The query builder and ORM client are now **always qualified by namespace**. The flat by-bare-name accessors are gone: there is no `sql.<table>` and no `orm.<Model>` at the builder layer, and the **Postgres** facade exposes the qualified surface (`db.sql` / `db.orm` are the namespace map). You reach a table or model by naming its namespace.
|
|
192
|
+
|
|
193
|
+
Namespace selection separates *which namespace's table* from *the ergonomic shorthand for the single-namespace case*. The builder layer always names the namespace; the single-namespace shorthand is recovered by the facade on targets that have only one namespace (SQLite, Mongo).
|
|
194
|
+
|
|
195
|
+
### Who needs to change code
|
|
196
|
+
|
|
197
|
+
**Postgres projects** that build queries through the facade or the builder outputs. A standard Postgres project keeps its tables and models in the `public` schema, so the namespace to insert is `public`:
|
|
198
|
+
|
|
199
|
+
```ts
|
|
200
|
+
// Before
|
|
201
|
+
const users = await db.sql.user.select('id', 'email').build().execute();
|
|
202
|
+
const alice = await db.orm.User.find({ where: { id } });
|
|
203
|
+
|
|
204
|
+
// After — name the namespace the table/model is declared in (`public` for a standard schema)
|
|
205
|
+
const users = await db.sql.public.user.select('id', 'email').build().execute();
|
|
206
|
+
const alice = await db.orm.public.User.find({ where: { id } });
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
The same rule applies inside a `transaction` (`tx.sql.public.user`, `tx.orm.public.User`), inside a `prepare(...)` callback (`(sql) => sql.public.user…`), and to code that imports the builder outputs directly rather than through the facade (`sql.public.user`, `orm.public.User`). If your Postgres contract declares more than one namespace, name the namespace each table/model actually sits in — `db.sql.auth.user` for a table in the `auth` schema, `db.sql.public.profile` for one in `public`.
|
|
210
|
+
|
|
211
|
+
### Who does **not** need to change anything
|
|
212
|
+
|
|
213
|
+
**SQLite and Mongo projects.** These targets have a single namespace, so their facade still exposes the flat surface — `db.sql.<table>` and `db.orm.<Model>` keep working unchanged. No edits are required.
|
|
214
|
+
|
|
215
|
+
### How to migrate
|
|
216
|
+
|
|
217
|
+
There is no codemod, because the correct namespace is the one each table or model is declared in — a fact that lives at the call site, not in a mechanical rule. For each flagged file:
|
|
218
|
+
|
|
219
|
+
1. If the project's facade is SQLite or Mongo (`sqlite(...)` / `mongo(...)`), leave it unchanged.
|
|
220
|
+
2. If it is Postgres (`postgres(...)`), insert the namespace segment after `.sql` / `.orm` (and on direct `sql` / `orm` builder calls): use `public` for a standard single-schema project, or the specific schema name for each table/model in a multi-schema contract.
|
|
221
|
+
|
|
222
|
+
After migrating, run your project's `pnpm typecheck` (or equivalent) — a missed site is a compile error (`Property '<table>' does not exist on type 'Db<…>'`), so the type checker pins every remaining flat access for you.
|
|
223
|
+
|
|
224
|
+
## `sql-runtime-base-class-naming`
|
|
225
|
+
|
|
226
|
+
The SQL runtime class hierarchy now follows the repo naming convention:
|
|
227
|
+
|
|
228
|
+
- `SqlRuntime` (previously exported) → now `SqlRuntimeBase` (abstract family base)
|
|
229
|
+
- `PostgresRuntime` (previously a class) → now an **interface** (the type to depend on); the concrete class is `PostgresRuntimeImpl`
|
|
230
|
+
- `SqliteRuntime` (previously a class) → now an **interface** (the type to depend on); the concrete class is `SqliteRuntimeImpl`
|
|
231
|
+
|
|
232
|
+
App code using the facade factories (`postgres(...)`, `sqlite(...)`) is unaffected — those return `Runtime` / the interface. Only code that referenced the class names directly needs to change:
|
|
233
|
+
|
|
234
|
+
```ts
|
|
235
|
+
// Before — referencing the class as a type
|
|
236
|
+
import { PostgresRuntime } from '@internal/postgres/runtime';
|
|
237
|
+
function takesRuntime(r: PostgresRuntime) { ... }
|
|
238
|
+
|
|
239
|
+
// After — use the interface (same import path)
|
|
240
|
+
import type { PostgresRuntime } from '@internal/postgres/runtime';
|
|
241
|
+
function takesRuntime(r: PostgresRuntime) { ... }
|
|
242
|
+
|
|
243
|
+
// Before — subclassing
|
|
244
|
+
import { PostgresRuntime } from '@internal/postgres/runtime';
|
|
245
|
+
class MyRuntime extends PostgresRuntime { ... }
|
|
246
|
+
|
|
247
|
+
// After — subclass the Impl
|
|
248
|
+
import { PostgresRuntimeImpl } from '@internal/postgres/runtime';
|
|
249
|
+
class MyRuntime extends PostgresRuntimeImpl { ... }
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
## `create-runtime-removed`
|
|
253
|
+
|
|
254
|
+
`createRuntime` is removed from `@internal/sql-runtime`. App code using the facade factories (`postgres(...)`, `sqlite(...)`) is unaffected — those still return a `Runtime` as before. Only code that imported and called `createRuntime` directly needs to change.
|
|
255
|
+
|
|
256
|
+
Replace direct `createRuntime` calls with the appropriate target class constructor or factory:
|
|
257
|
+
|
|
258
|
+
```ts
|
|
259
|
+
// Before
|
|
260
|
+
import { createRuntime } from '@internal/sql-runtime';
|
|
261
|
+
const runtime = createRuntime({ stackInstance, context, driver, ...opts });
|
|
262
|
+
|
|
263
|
+
// After — use the target factory (recommended for app code)
|
|
264
|
+
import { postgres } from '@internal/postgres';
|
|
265
|
+
const db = postgres({ contract, ...opts });
|
|
266
|
+
// runtime is accessed via db.connect() / db.runtime() etc.
|
|
267
|
+
|
|
268
|
+
// Or construct the target class directly (for advanced/test use)
|
|
269
|
+
import { PostgresRuntimeImpl } from '@internal/postgres/runtime';
|
|
270
|
+
const runtime = new PostgresRuntimeImpl({ adapter: stackInstance.adapter, context, driver, ...opts });
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
The constructor options are identical to what `createRuntime` accepted, except `stackInstance` is not taken: pass `adapter` from `stackInstance.adapter` directly.
|
|
274
|
+
|
|
275
|
+
## `migration-op-factories-to-methods`
|
|
276
|
+
|
|
277
|
+
The bare op factory functions previously exported from `@internal/postgres/migration` (and the deprecated `@internal/target-postgres/migration` alias) are removed. Each function is now a protected method on the `PostgresMigration` base class — call it as `this.<method>(...)` inside your `Migration` subclass body.
|
|
278
|
+
|
|
279
|
+
The option shapes also changed: positional arguments are replaced by a single options object.
|
|
280
|
+
|
|
281
|
+
Remove the bare names from your import and replace each call-site:
|
|
282
|
+
|
|
283
|
+
| Before (bare function) | After (method) |
|
|
284
|
+
| --- | --- |
|
|
285
|
+
| `dropColumn(schema, table, column)` | `this.dropColumn({ schema, table, column })` |
|
|
286
|
+
| `setNotNull(schema, table, column)` | `this.setNotNull({ schema, table, column })` |
|
|
287
|
+
| `setDefault(schema, table, column, defaultSql)` | `this.setDefault({ schema, table, column, defaultSql })` |
|
|
288
|
+
| `addPrimaryKey(schema, table, name, columns)` | `this.addPrimaryKey({ schema, table, constraint: name, columns })` |
|
|
289
|
+
| `addForeignKey(schema, table, { name, columns, references, onDelete })` | `this.addForeignKey({ schema, table, foreignKey: { name, columns, references, onDelete } })` |
|
|
290
|
+
| `addCheckConstraint(schema, table, name, column, values)` | `this.addCheckConstraint({ schema, table, constraint: name, column, values })` |
|
|
291
|
+
| `createIndex(schema, table, indexName, columns)` | `this.createIndex({ schema, table, index: indexName, columns })` |
|
|
292
|
+
| `installExtension({ id, extensionName, invariantId })` | `this.installExtension({ id, extensionName, invariantId })` |
|
|
293
|
+
|
|
294
|
+
Example:
|
|
295
|
+
|
|
296
|
+
```ts
|
|
297
|
+
// Before
|
|
298
|
+
import { addForeignKey, createIndex, dropColumn } from '@internal/postgres/migration';
|
|
299
|
+
|
|
300
|
+
override get operations() {
|
|
301
|
+
return [
|
|
302
|
+
dropColumn('public', 'user', 'legacyName'),
|
|
303
|
+
addForeignKey('public', 'post', {
|
|
304
|
+
name: 'post_userId_fkey',
|
|
305
|
+
columns: ['userId'],
|
|
306
|
+
references: { schema: 'public', table: 'user', columns: ['id'] },
|
|
307
|
+
}),
|
|
308
|
+
createIndex('public', 'post', 'post_userId_idx', ['userId']),
|
|
309
|
+
];
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// After
|
|
313
|
+
import { Migration, MigrationCLI } from '@internal/postgres/migration';
|
|
314
|
+
|
|
315
|
+
override get operations() {
|
|
316
|
+
return [
|
|
317
|
+
this.dropColumn({ schema: 'public', table: 'user', column: 'legacyName' }),
|
|
318
|
+
this.addForeignKey({
|
|
319
|
+
schema: 'public',
|
|
320
|
+
table: 'post',
|
|
321
|
+
foreignKey: {
|
|
322
|
+
name: 'post_userId_fkey',
|
|
323
|
+
columns: ['userId'],
|
|
324
|
+
references: { schema: 'public', table: 'user', columns: ['id'] },
|
|
325
|
+
},
|
|
326
|
+
}),
|
|
327
|
+
this.createIndex({ schema: 'public', table: 'post', index: 'post_userId_idx', columns: ['userId'] }),
|
|
328
|
+
];
|
|
329
|
+
}
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
The colocated script applies this transformation automatically. Run it from your project root:
|
|
333
|
+
|
|
334
|
+
```bash
|
|
335
|
+
pnpm exec tsx .claude/skills/prisma-8/upgrading/app/upgrades/0.13-to-0.14/migration-op-factories-to-methods.ts
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
## `postgres-contract-serializer`
|
|
339
|
+
|
|
340
|
+
`SqlContractSerializer` (from `@internal/family-sql/ir`) now rejects Postgres contracts. The family serializer validates entries against a registry of known entity kinds; it only knows the SQL-family built-ins (`table`, `valueSet`) and has no knowledge of the Postgres-specific `type` key (Postgres enum types). Every Postgres namespace carries `"type": {}` in its `entries`, so the family serializer throws a `ContractValidationError` naming `type` as an unregistered kind.
|
|
341
|
+
|
|
342
|
+
Replace `SqlContractSerializer` with `PostgresContractSerializer` in any migration file or app code that deserializes a Postgres-emitted contract:
|
|
343
|
+
|
|
344
|
+
```ts
|
|
345
|
+
// Before
|
|
346
|
+
import { SqlContractSerializer } from '@internal/family-sql/ir';
|
|
347
|
+
const contract = new SqlContractSerializer().deserializeContract(contractJson) as Contract;
|
|
348
|
+
|
|
349
|
+
// After
|
|
350
|
+
import { PostgresContractSerializer } from '@internal/target-postgres/runtime';
|
|
351
|
+
const contract = new PostgresContractSerializer().deserializeContract(contractJson) as Contract;
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
SQLite and family-only (non-Postgres) contracts are unaffected — their namespaces carry only `table` entries, which the family serializer knows about.
|
|
355
|
+
|
|
356
|
+
## `enum-becomes-domain-concept`
|
|
357
|
+
|
|
358
|
+
The `enum` keyword changed meaning. Before 0.14 a PSL `enum` block authored a **native Postgres enum** (`CREATE TYPE <name> AS ENUM (…)`, columns typed with the named type). Starting at 0.14 the same keyword authors the **domain enum**: the column stores plain values through a declared codec (typically `pg/text@1` → a `text` column) and the value set is enforced by a CHECK constraint the migration planner generates and verifies. The native enum machinery (the `pg/enum@1` codec, native `CREATE TYPE` planning, native-enum introspection adoption) is deleted.
|
|
359
|
+
|
|
360
|
+
### Who needs to change code
|
|
361
|
+
|
|
362
|
+
Any project whose `.prisma` schema contains an `enum` block **without** an `@@type(...)` attribute (the old native form), or with `@map` on members, or whose schema uses the transitional `enum2` keyword. Projects that already author enums with `@@type` + member values (the `enum2`-era shape introduced in 0.13) only need the keyword rename described below — the emitted contract is identical.
|
|
363
|
+
|
|
364
|
+
### 1. Convert the schema syntax
|
|
365
|
+
|
|
366
|
+
```prisma
|
|
367
|
+
// Before — native enum (0.13)
|
|
368
|
+
enum user_type {
|
|
369
|
+
admin
|
|
370
|
+
user
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// After — domain enum (0.14)
|
|
374
|
+
enum user_type {
|
|
375
|
+
@@type("pg/text@1")
|
|
376
|
+
admin = "admin"
|
|
377
|
+
user = "user"
|
|
378
|
+
}
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
Rules:
|
|
382
|
+
|
|
383
|
+
- `@@type("<codec-id>")` is **required**. For string-valued enums use `@@type("pg/text@1")`.
|
|
384
|
+
- Each member maps to its database value with `member = "value"`. Under the native semantics the stored label was the member name, so a faithful conversion sets each value to the member's name (`admin = "admin"`). A member that previously carried `@map("dbvalue")` becomes `member = "dbvalue"` — `@map` on enum members is removed; the member value is the mapping.
|
|
385
|
+
- If your schema uses the transitional `enum2` keyword (added in 0.13), rename `enum2` → `enum`. Nothing else changes — that block shape is exactly what `enum` now means.
|
|
386
|
+
|
|
387
|
+
If you author contracts in TypeScript instead of PSL: the native `enumType(name, values[])` and `enumColumn(...)` helpers from `@internal/adapter-postgres/column-types` are deleted. Author the domain enum with `enumType` + `member` from your target's contract-builder and return it under the `enums` key:
|
|
388
|
+
|
|
389
|
+
```ts
|
|
390
|
+
import { defineContract, enumType, member } from '@internal/postgres/contract-builder';
|
|
391
|
+
|
|
392
|
+
const pgText = { codecId: 'pg/text@1', nativeType: 'text' } as const;
|
|
393
|
+
const UserType = enumType('user_type', pgText, member('admin', 'admin'), member('user', 'user'));
|
|
394
|
+
|
|
395
|
+
export const contract = defineContract({ /* … */ }, ({ field, model }) => ({
|
|
396
|
+
enums: { user_type: UserType },
|
|
397
|
+
models: {
|
|
398
|
+
User: model('User', {
|
|
399
|
+
fields: { /* … */ kind: field.namedType(UserType) },
|
|
400
|
+
}),
|
|
401
|
+
},
|
|
402
|
+
}));
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
Then re-emit: `prisma-next contract emit`. The emitted contract carries the enum as a domain entity plus a storage `valueSet`; the column becomes `pg/text@1` / `text` with a `valueSet` reference and a table-level check entry.
|
|
406
|
+
|
|
407
|
+
### 2. Migrate the database off the native type
|
|
408
|
+
|
|
409
|
+
A database created under 0.13 still has the native enum type and columns typed with it. Author a one-time converting migration — for each native enum type, in order:
|
|
410
|
+
|
|
411
|
+
1. Alter each column off the native type, casting the stored labels: `ALTER TABLE … ALTER COLUMN <col> TYPE text USING <col>::text`.
|
|
412
|
+
2. Add the value-set CHECK constraint the contract now declares (name it as the contract does, e.g. `<table>_<col>_check`).
|
|
413
|
+
3. Drop the native type: `DROP TYPE "<schema>"."<type>"`.
|
|
414
|
+
|
|
415
|
+
Because the contract hash does not change (the schema conversion in step 1 and the emitted contract are the end state), scaffold the migration as a data-only edge on the current hash: `prisma-next migration new --name convert-<type>-to-value-set --from <current-storage-hash>`, give the ALTER op `operationClass: 'data'`, and self-emit by running the scaffolded `migration.ts`. The `DROP TYPE` has no op builder — express it as an inline `rawSql` op.
|
|
416
|
+
|
|
417
|
+
A complete worked example ships in the Prisma Next repo: `examples/prisma-8-demo/migrations/app/20260611T1856_convert_user_type_to_value_set/migration.ts` — three ops (data-class ALTER … USING, `addCheckConstraint`, rawSql `DROP TYPE`), each with pre/postchecks that make replay idempotent.
|
|
418
|
+
|
|
419
|
+
Note: `prisma-next contract infer` **refuses** databases containing native enum types — it names each offending type and points at this conversion. Convert the database first, then infer.
|
|
420
|
+
|
|
421
|
+
### 3. Verify
|
|
422
|
+
|
|
423
|
+
Run `prisma-next db verify` (or your project's test suite) after applying the converting migration: the live schema must now match the contract — `text` column, CHECK constraint present, native type gone.
|
|
424
|
+
|
|
425
|
+
## `generated-models-export-removed`
|
|
426
|
+
|
|
427
|
+
The generated `contract.d.ts` no longer emits the flat top-level `export type Models` (the first-name-wins map of every model across namespaces). Models now resolve per-namespace from the domain plane, matching how the runtime and DSL read them.
|
|
428
|
+
|
|
429
|
+
If your code imported `Models` from the generated contract, read a namespace's models instead:
|
|
430
|
+
|
|
431
|
+
```ts
|
|
432
|
+
// Before
|
|
433
|
+
import type { Contract, Models } from './prisma/contract';
|
|
434
|
+
type UserModel = Models['User'];
|
|
435
|
+
|
|
436
|
+
// After — name the namespace the model is declared in
|
|
437
|
+
import type { Contract } from './prisma/contract';
|
|
438
|
+
type Models = Contract['domain']['namespaces']['public']['models'];
|
|
439
|
+
type UserModel = Models['User'];
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
Use `public` for a standard single-schema Postgres project, or `__unbound__` for SQLite and Mongo. In a multi-schema Postgres contract, name the schema each model is declared in. Re-emit your contract (`prisma-next contract emit`) so the generated `.d.ts` drops the `Models` export; the emitted `contract.json` is unchanged.
|
|
443
|
+
|
|
444
|
+
<!--
|
|
445
|
+
TML-2882: transitional PSL `enum2` block (PR #805). The demo authors `enum2 Priority`
|
|
446
|
+
and a `priority` field; emitted artifacts and migrations regenerate accordingly, and
|
|
447
|
+
the `ValueSetRef` carrier / `StorageValueSet` node tag land in their first persisted
|
|
448
|
+
form. Additive and opt-in: no existing consumer contract changes shape, native `enum`
|
|
449
|
+
is untouched, and re-emit round-trips. No consumer action required; the keyword is
|
|
450
|
+
transitional and is renamed to `enum` at the cutover (TML-2853), which will carry the
|
|
451
|
+
user-facing upgrade entry.
|
|
452
|
+
-->
|
|
453
|
+
|
|
454
|
+
<!--
|
|
455
|
+
TML-2855: member defaults via `@default(member)` (PR #808). The PSL interpreter and
|
|
456
|
+
contract-ts authoring surface now resolve `@default(EnumType.Member)` to a
|
|
457
|
+
`{ kind: 'literal', value: '<dbValue>' }` default. The demo `priority` field gains
|
|
458
|
+
`@default(Priority.Low)` and a new migration (`20260610T2216_set_priority_default`)
|
|
459
|
+
is emitted. Additive and opt-in: only fields that declare `@default(<EnumType>.<Member>)`
|
|
460
|
+
are affected; no existing contract changes shape. No consumer action required; the
|
|
461
|
+
cutover (TML-2853) will carry the user-facing docs.
|
|
462
|
+
-->
|
|
463
|
+
|
|
464
|
+
<!--
|
|
465
|
+
TML-2885: typed domain enum block in emitted contract.d.ts (PR #809). The emitter
|
|
466
|
+
now generates a `domain` block in `contract.d.ts` that exposes each PSL-authored enum
|
|
467
|
+
as a `ContractEnumAccessor<Entry>` with literal `values`, `names`, and `members` types.
|
|
468
|
+
`contract.json` is unchanged — the enum data was already there; this is a types-only
|
|
469
|
+
addition. Consumers that re-emit gain a literal-typed `db.enums.<namespace>.<Name>`
|
|
470
|
+
surface at compile time (e.g. `db.enums.public.Priority.members.Low` resolves to
|
|
471
|
+
`'low'` rather than `string`). Additive — no existing contract shape changes.
|
|
472
|
+
No consumer action required.
|
|
473
|
+
-->
|
|
474
|
+
|
|
475
|
+
<!--
|
|
476
|
+
TML-2886: typed ALTER TABLE … ADD COLUMN via AlterTable DDL IR (PR #813). The
|
|
477
|
+
example migrations that used the bare `addColumn()` helper are updated to
|
|
478
|
+
`this.addColumn(...)` (the method on the `Migration` base class, which now carries
|
|
479
|
+
full column typing via the `col()` builder). The column-attribute order in emitted
|
|
480
|
+
CREATE TABLE SQL changed from `… NOT NULL DEFAULT …` to `… DEFAULT … NOT NULL` as a
|
|
481
|
+
by-product of the AlterTable IR alignment. The example fixture snapshots are
|
|
482
|
+
regenerated accordingly. No user-facing contract or migration format change.
|
|
483
|
+
Incidental substrate diff only.
|
|
484
|
+
-->
|
|
485
|
+
|
|
486
|
+
<!--
|
|
487
|
+
TML-2886 (redo, PR #841): type SQL enum columns via a baked storage column lookup.
|
|
488
|
+
The SQL emitter now generates a top-level `StorageColumnTypes` map keyed
|
|
489
|
+
`[namespace][table][column]`; `FieldOutputTypes`/`FieldInputTypes` are derived from
|
|
490
|
+
it at emit time. The query builder (sql-builder) reads `StorageColumnTypes` directly;
|
|
491
|
+
the ORM still reads `FieldOutputTypes`. `contract.json` and both hashes are
|
|
492
|
+
byte-identical; `FieldOutputTypes` is byte-identical to main. The examples/ diff is
|
|
493
|
+
purely `.d.ts` regeneration (the new `StorageColumnTypes` block added; observable
|
|
494
|
+
types unchanged). No consumer action required. Incidental substrate diff only.
|
|
495
|
+
-->
|
|
496
|
+
|
|
497
|
+
<!--
|
|
498
|
+
#788: enum input types widened to their member union in emitted contract.d.ts (PR
|
|
499
|
+
#797). The emitter now renders an enum-restricted field's input type as the literal
|
|
500
|
+
member union on the write side, matching the existing output side: a `pg/enum@1`
|
|
501
|
+
field's `FieldInputTypes` entry flips from `CodecTypes['pg/enum@1']['input']` (≈
|
|
502
|
+
`string`) to e.g. `'admin' | 'user'`. The example `contract.d.ts` goldens are
|
|
503
|
+
regenerated accordingly. `contract.json` is unchanged — this is a types-only
|
|
504
|
+
addition that makes create/update exhaustiveness-checked. Additive; no existing
|
|
505
|
+
contract shape changes. No consumer action required. Incidental substrate diff only.
|
|
506
|
+
-->
|
|
507
|
+
|
|
508
|
+
<!--
|
|
509
|
+
TML-2853 (PR #829): regenerate the `prisma-8-demo` example migration chain into
|
|
510
|
+
the new value-set representation, recovering work that #817 (the user-facing
|
|
511
|
+
`enum-becomes-domain-concept` cutover, already in main) left undone in the example.
|
|
512
|
+
The committed chain previously created `user_type` as a native `CREATE TYPE … AS ENUM`
|
|
513
|
+
and converted it in a later self-edge migration — a start state the post-cutover
|
|
514
|
+
system can no longer produce. The chain is re-authored as a multi-step incremental
|
|
515
|
+
history in which the initial migration creates `user.kind` as a `text` column with a
|
|
516
|
+
`user_kind_check` CHECK constraint from the start; the native-enum arc and the
|
|
517
|
+
`convert_user_type_to_value_set` self-edge are removed. The remaining incremental
|
|
518
|
+
milestones (displayName, MTI variant link columns, `post.priority` value-set + default)
|
|
519
|
+
are preserved so the chain still demonstrates the incremental migration CLI. Diff is
|
|
520
|
+
`examples/prisma-8-demo/migrations/**` only. No NEW consumer action beyond the
|
|
521
|
+
existing `enum-becomes-domain-concept` entry above. Incidental substrate diff only.
|
|
522
|
+
-->
|
|
523
|
+
|
|
524
|
+
<!--
|
|
525
|
+
TML-2550: per-namespace typed resolution. The emitted contract.d.ts TypeMaps
|
|
526
|
+
(`FieldOutputTypes` / `FieldInputTypes`) now nest by namespace
|
|
527
|
+
(`{ [namespace]: { [model]: { [field] } } }`), so the query builder and ORM client
|
|
528
|
+
resolve each namespace's own columns/fields — fixing same-bare-name models declared
|
|
529
|
+
in more than one namespace. The example contract.d.ts fixtures regenerate to the
|
|
530
|
+
nested shape; a consumer re-emit round-trips. The user-facing always-qualified query
|
|
531
|
+
surface is already covered by `qualify-flat-builder-accessors` above — this slice is
|
|
532
|
+
the type-resolution fix beneath it. No user action: re-emit picks up the new shape.
|
|
533
|
+
Incidental substrate diff only.
|
|
534
|
+
-->
|
|
535
|
+
|
|
536
|
+
<!--
|
|
537
|
+
TML-2916: un-namespaced Postgres models now correctly default to the `public`
|
|
538
|
+
namespace per ADR 223, dropping the spurious empty `__unbound__` storage slot the
|
|
539
|
+
authoring + serializer pipeline was injecting. Example contract.json / contract.d.ts /
|
|
540
|
+
end-contract.* / migration.json files regenerate to drop the `__unbound__` slot;
|
|
541
|
+
migration content hashes update. No user action: re-emit picks up the new shape.
|
|
542
|
+
Incidental substrate diff only.
|
|
543
|
+
-->
|