@prisma/orm-mongo 8.0.0-rc.5 → 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.
Files changed (64) hide show
  1. package/package.json +11 -10
  2. package/skills/prisma-8/SKILL.md +84 -0
  3. package/skills/prisma-8/references/build.md +142 -0
  4. package/skills/prisma-8/references/contract.md +417 -0
  5. package/skills/prisma-8/references/debug.md +141 -0
  6. package/skills/prisma-8/references/feedback.md +251 -0
  7. package/skills/prisma-8/references/migration-review.md +224 -0
  8. package/skills/prisma-8/references/migrations.md +519 -0
  9. package/skills/prisma-8/references/queries-mongo.md +236 -0
  10. package/skills/prisma-8/references/queries-postgres.md +415 -0
  11. package/skills/prisma-8/references/queries.md +168 -0
  12. package/skills/prisma-8/references/quickstart.md +326 -0
  13. package/skills/prisma-8/references/runtime.md +344 -0
  14. package/skills/prisma-8/references/supabase.md +244 -0
  15. package/skills/prisma-8/references/upgrade-app.md +101 -0
  16. package/skills/prisma-8/references/upgrade-extension.md +105 -0
  17. package/skills/prisma-8/upgrading/app/upgrades/0.10-to-0.11/instructions.md +56 -0
  18. package/skills/prisma-8/upgrading/app/upgrades/0.11-to-0.12/instructions.md +381 -0
  19. package/skills/prisma-8/upgrading/app/upgrades/0.11-to-0.12/re-emit-closed-mongo-contracts.ts +202 -0
  20. package/skills/prisma-8/upgrading/app/upgrades/0.11-to-0.12/re-emit-domain-namespaced-contracts.ts +201 -0
  21. package/skills/prisma-8/upgrading/app/upgrades/0.11-to-0.12/re-emit-postgres-public-default.ts +198 -0
  22. package/skills/prisma-8/upgrading/app/upgrades/0.11-to-0.12/strip-migration-labels-hints.ts +340 -0
  23. package/skills/prisma-8/upgrading/app/upgrades/0.12-to-0.13/instructions.md +339 -0
  24. package/skills/prisma-8/upgrading/app/upgrades/0.12-to-0.13/re-emit-mti-variant-link-columns.ts +229 -0
  25. package/skills/prisma-8/upgrading/app/upgrades/0.13-to-0.14/instructions.md +543 -0
  26. package/skills/prisma-8/upgrading/app/upgrades/0.13-to-0.14/migration-op-factories-to-methods.ts +290 -0
  27. package/skills/prisma-8/upgrading/app/upgrades/0.13-to-0.14/uuid-preset-rename.ts +43 -0
  28. package/skills/prisma-8/upgrading/app/upgrades/0.14-to-0.15/instructions.md +359 -0
  29. package/skills/prisma-8/upgrading/app/upgrades/0.15-to-0.16/instructions.md +173 -0
  30. package/skills/prisma-8/upgrading/app/upgrades/0.16-to-0.17/instructions.md +805 -0
  31. package/skills/prisma-8/upgrading/app/upgrades/0.16-to-0.17/strip-sha256-hash-prefixes.ts +382 -0
  32. package/skills/prisma-8/upgrading/app/upgrades/0.17-to-8.0.0-rc.1/instructions.md +72 -0
  33. package/skills/prisma-8/upgrading/app/upgrades/0.7-to-0.8/instructions.md +8 -0
  34. package/skills/prisma-8/upgrading/app/upgrades/0.8-to-0.9/instructions.md +36 -0
  35. package/skills/prisma-8/upgrading/app/upgrades/0.8-to-0.9/strip-inline-contracts.ts +226 -0
  36. package/skills/prisma-8/upgrading/app/upgrades/0.9-to-0.10/instructions.md +86 -0
  37. package/skills/prisma-8/upgrading/app/upgrades/0.9-to-0.10/stamp-storage-types-kind.ts +360 -0
  38. package/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.1-to-8.0.0-rc.2/instructions.md +588 -0
  39. package/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.2-to-8.0.0-rc.3/instructions.md +5 -0
  40. package/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.3-to-8.0.0-rc.4/instructions.md +158 -0
  41. package/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.4-to-8.0.0-rc.5/instructions.md +42 -0
  42. package/skills/prisma-8/upgrading/extension/upgrades/0.10-to-0.11/instructions.md +276 -0
  43. package/skills/prisma-8/upgrading/extension/upgrades/0.11-to-0.12/instructions.md +738 -0
  44. package/skills/prisma-8/upgrading/extension/upgrades/0.11-to-0.12/migrate-contract-testing-imports.ts +97 -0
  45. package/skills/prisma-8/upgrading/extension/upgrades/0.11-to-0.12/regenerate-extension-public-baseline.ts +223 -0
  46. package/skills/prisma-8/upgrading/extension/upgrades/0.11-to-0.12/strip-migration-labels-hints.ts +340 -0
  47. package/skills/prisma-8/upgrading/extension/upgrades/0.12-to-0.13/instructions.md +266 -0
  48. package/skills/prisma-8/upgrading/extension/upgrades/0.13-to-0.14/instructions.md +522 -0
  49. package/skills/prisma-8/upgrading/extension/upgrades/0.13-to-0.14/migration-op-factories-to-methods.ts +290 -0
  50. package/skills/prisma-8/upgrading/extension/upgrades/0.13-to-0.14/uuid-preset-rename.ts +43 -0
  51. package/skills/prisma-8/upgrading/extension/upgrades/0.14-to-0.15/instructions.md +803 -0
  52. package/skills/prisma-8/upgrading/extension/upgrades/0.15-to-0.16/instructions.md +219 -0
  53. package/skills/prisma-8/upgrading/extension/upgrades/0.16-to-0.17/instructions.md +731 -0
  54. package/skills/prisma-8/upgrading/extension/upgrades/0.16-to-0.17/strip-sha256-hash-prefixes.ts +382 -0
  55. package/skills/prisma-8/upgrading/extension/upgrades/0.17-to-8.0.0-rc.1/instructions.md +194 -0
  56. package/skills/prisma-8/upgrading/extension/upgrades/0.7-to-0.8/instructions.md +8 -0
  57. package/skills/prisma-8/upgrading/extension/upgrades/0.8-to-0.9/instructions.md +57 -0
  58. package/skills/prisma-8/upgrading/extension/upgrades/0.8-to-0.9/strip-inline-contracts.ts +226 -0
  59. package/skills/prisma-8/upgrading/extension/upgrades/0.9-to-0.10/instructions.md +150 -0
  60. package/skills/prisma-8/upgrading/extension/upgrades/0.9-to-0.10/stamp-storage-types-kind.ts +360 -0
  61. package/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.1-to-8.0.0-rc.2/instructions.md +746 -0
  62. package/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.2-to-8.0.0-rc.3/instructions.md +5 -0
  63. package/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.3-to-8.0.0-rc.4/instructions.md +137 -0
  64. 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
+ -->