@prisma/orm-mongo 8.0.0-rc.22-dev.15 → 8.0.0-rc.23
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/dist/{mongo-static-vnC5E2_h-CVOMWNhR.mjs → mongo-static-tgXxFQ8j-DK8QCuk8.mjs} +3 -3
- package/dist/mongo-static-tgXxFQ8j-DK8QCuk8.mjs.map +1 -0
- package/dist/runtime.mjs +1 -1
- package/dist/runtime.mjs.map +1 -1
- package/dist/static.mjs +1 -1
- package/package.json +8 -8
- package/skills/prisma-8/SKILL.md +1 -1
- package/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.22-to-8.0.0-rc.23/instructions.md +480 -0
- package/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.22-to-8.0.0-rc.23/scripts/mongo-index-names/mongo-index-names.ts +317 -0
- package/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.22-to-8.0.0-rc.23/instructions.md +410 -0
- package/dist/mongo-static-vnC5E2_h-CVOMWNhR.mjs.map +0 -1
package/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.22-to-8.0.0-rc.23/instructions.md
ADDED
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
---
|
|
2
|
+
from: "8.0.0-rc.22"
|
|
3
|
+
to: "8.0.0-rc.23"
|
|
4
|
+
changes:
|
|
5
|
+
- id: temporal-polyfill-is-a-peer-dependency-of-mysql
|
|
6
|
+
summary: |
|
|
7
|
+
`temporal-polyfill` is now a required peer dependency of `@prisma/orm-target-mysql` and `@prisma/orm-mysql`. The target's control entry imports it. An extension pack that peers the target does not declare it; the application supplies it. npm, pnpm and bun install it automatically. An extension package that installs with Yarn and loads the target's control entry in its tests or tooling must add `temporal-polyfill` (`^1.0.4`) to its `devDependencies`.
|
|
8
|
+
detection:
|
|
9
|
+
glob: "**/yarn.lock"
|
|
10
|
+
contains:
|
|
11
|
+
- "@prisma/orm-mysql@"
|
|
12
|
+
- "@prisma/orm-target-mysql@"
|
|
13
|
+
anyMatch: true
|
|
14
|
+
- id: mysql-create-namespace-moved-to-target-types
|
|
15
|
+
summary: |
|
|
16
|
+
`mysqlCreateNamespace` and `MysqlDatabase` moved from the MySQL target's `/target/control` entry to its `/target/types` entry, as PostgreSQL's and SQLite's are in theirs. The control entry loads `temporal-polyfill`, so code that is not control-plane code no longer has to load it to name a namespace. An import of either from `/target/control` fails to compile.
|
|
17
|
+
detection:
|
|
18
|
+
glob: "**/*.ts"
|
|
19
|
+
contains:
|
|
20
|
+
- "mysqlCreateNamespace"
|
|
21
|
+
- "MysqlDatabase"
|
|
22
|
+
anyMatch: true
|
|
23
|
+
- id: temporal-polyfill-is-a-peer-dependency-of-sqlite
|
|
24
|
+
summary: |
|
|
25
|
+
`temporal-polyfill` is now a required peer dependency of `@prisma/orm-target-sqlite` and `@prisma/orm-sqlite`. The target's control entry imports it. An extension pack that peers the target does not declare it; the application supplies it. npm, pnpm and bun install it automatically. An extension package that installs with Yarn and loads the target's control entry in its tests or tooling must add `temporal-polyfill` (`^1.0.4`) to its `devDependencies`.
|
|
26
|
+
detection:
|
|
27
|
+
glob: "**/yarn.lock"
|
|
28
|
+
contains:
|
|
29
|
+
- "@prisma/orm-sqlite@"
|
|
30
|
+
- "@prisma/orm-target-sqlite@"
|
|
31
|
+
anyMatch: true
|
|
32
|
+
- id: sqlite-create-namespace-moved-to-target-types
|
|
33
|
+
summary: |
|
|
34
|
+
`sqliteCreateNamespace` and `SqliteUnboundDatabase` moved from the SQLite target's `/target/control` entry to its `/target/types` entry, as PostgreSQL's `postgresCreateNamespace` is in its `/target/types`. The control entry loads `temporal-polyfill`, so code that is not control-plane code no longer has to load it to name a namespace. An import of either from `/target/control` fails to compile.
|
|
35
|
+
detection:
|
|
36
|
+
glob: "**/*.ts"
|
|
37
|
+
contains:
|
|
38
|
+
- "sqliteCreateNamespace"
|
|
39
|
+
- "SqliteUnboundDatabase"
|
|
40
|
+
anyMatch: true
|
|
41
|
+
- id: psl-renamed-postgres-scalar-types
|
|
42
|
+
summary: |
|
|
43
|
+
In a Prisma 8 schema on PostgreSQL, `SmallInt`, `BigIntNumber`, `Numeric`, `UnboundedInt`, `Real`, `VarChar` and `VarBit` are deprecated and report `PSL_DEPRECATED_SCALAR_NAME` as a warning. Write the convenience call that gives the same type instead: `Int(storage: int2)`, `BigInt(as: number)`, `Decimal(precision: p, scale: s)`, `BigInt(storage: numeric)`, `Float(storage: float4)` and `String(storage: varchar, length: n)`; `VarBit` has no convenience type and becomes `Varbit`. The contract does not change. A Prisma 7 schema, which has a `datasource` block, is not affected.
|
|
44
|
+
detection:
|
|
45
|
+
glob: "**/*.prisma"
|
|
46
|
+
matches:
|
|
47
|
+
- '(?<![\s\S])(?![\s\S]*(?<![\w$])datasource[ \t]+\w+[ \t]*\{)[\s\S]*\n[ \t]+[A-Za-z_]\w*[ \t]+(?:=[ \t]*)?(?:SmallInt|BigIntNumber|Numeric|UnboundedInt|Real|VarChar|VarBit)(?![\w$])'
|
|
48
|
+
- id: ts-renamed-postgres-scalar-helpers
|
|
49
|
+
summary: |
|
|
50
|
+
In a TypeScript contract on PostgreSQL, `type.SmallInt()`, `type.BigIntNumber()`, `type.Numeric(...)`, `type.UnboundedInt()`, `type.Real()`, `type.VarChar(...)` and `type.VarBit(...)` are deprecated. They still compile and give no warning, and they are removed together with the deprecated schema names. Call the convenience helper that gives the same type instead, such as `type.String({ storage: 'varchar', length: 64 })` for `type.VarChar(64)`, or `type.Varbit(n)` for `type.VarBit(n)`.
|
|
51
|
+
detection:
|
|
52
|
+
glob: "**/*.{ts,mts,cts,tsx}"
|
|
53
|
+
matches:
|
|
54
|
+
- '(?<![\w$])type\.(?:SmallInt|BigIntNumber|Numeric|UnboundedInt|Real|VarChar|VarBit)\('
|
|
55
|
+
- id: ts-renamed-postgres-column-helpers
|
|
56
|
+
summary: |
|
|
57
|
+
The PostgreSQL column helpers `int8Column` and `numericColumn` are renamed to `int8BigIntColumn` and `numericStringColumn`, after the explicit types they give (`Int8BigInt` and `NumericString`). The old names are removed. The contract does not change.
|
|
58
|
+
detection:
|
|
59
|
+
glob: "**/*.{ts,mts,cts,tsx}"
|
|
60
|
+
matches:
|
|
61
|
+
- 'import[ \t]+(?:type[ \t]+)?\{[^}]*(?<![\w$])(?:int8Column|numericColumn)(?![\w$])[^}]*\}[ \t]*from[ \t]*[''"](?:@prisma/orm-postgres/adapter/column-types|@internal/adapter-postgres/column-types)[''"]'
|
|
62
|
+
- id: ts-renamed-postgres-type-groupings
|
|
63
|
+
summary: |
|
|
64
|
+
`@internal/target-postgres/control` exports `postgresExplicitTypes`, every explicit PostgreSQL type, and `postgresScalarTypes`, which holds the explicit types, the convenience types such as `Int` and `String`, and the deprecated aliases. They replace `postgresScalarAuthoringTypes`, `postgresNativeAuthoringTypes` and `postgresScalarAndNativeTypeConstructors`, which are removed.
|
|
65
|
+
detection:
|
|
66
|
+
glob: "**/*.{ts,mts,cts,tsx}"
|
|
67
|
+
matches:
|
|
68
|
+
- '(?<![\w$])(?:postgresScalarAuthoringTypes|postgresNativeAuthoringTypes|postgresScalarAndNativeTypeConstructors)(?![\w$])'
|
|
69
|
+
- id: pack-declares-extension-unbound
|
|
70
|
+
summary: |
|
|
71
|
+
A pack that declares a Postgres extension must declare it in the unbound namespace, and no two packs may declare the same extension. A composed pack that declares an extension in a named namespace, such as `public`, is refused when a command loads the configuration, with `CONTRACT.PACK_CONTRIBUTION_INVALID`. Declare it with `extension('<name>', { namespace: unbound })` from the Postgres contract builder, or `namespace unbound { extension <name> {} }` in PSL, re-emit the pack's contract, and plan two migrations: one from the old head to the new one, which has no operations, and one from the empty contract to the new head, which creates the extension with no schema named.
|
|
72
|
+
detection:
|
|
73
|
+
glob: "**/*.{ts,mts,cts,prisma}"
|
|
74
|
+
matches:
|
|
75
|
+
- '\bextension\((?![^)]*namespace:\s*unbound\b)[^)]*\)'
|
|
76
|
+
- '^(?:(?:"(?:[^"\\\n]|\\.)*"|//[^\n]*(?:\n|$)|[^{}"/]|/(?!/))|\{(?:(?:"(?:[^"\\\n]|\\.)*"|//[^\n]*(?:\n|$)|[^{}"/]|/(?!/))|\{(?:"(?:[^"\\\n]|\\.)*"|//[^\n]*(?:\n|$)|[^{}"/]|/(?!/))*\})*\})*?\bextension\s+[A-Za-z_][\w-]*\s*\{'
|
|
77
|
+
- '\bnamespace\s+(?!unbound\b)[A-Za-z_][\w-]*\s*\{(?:(?:"(?:[^"\\\n]|\\.)*"|//[^\n]*(?:\n|$)|[^{}"/]|/(?!/))|\{(?:"(?:[^"\\\n]|\\.)*"|//[^\n]*(?:\n|$)|[^{}"/]|/(?!/))*\})*?\bextension\s+[A-Za-z_][\w-]*\s*\{'
|
|
78
|
+
- id: mongo-index-name-required
|
|
79
|
+
summary: |
|
|
80
|
+
`MongoIndex` and `MongoIndexInput` (from `@prisma/orm-family-mongo/contract`) and `MongoSchemaIndex` and `MongoSchemaIndexOptions` (from `@prisma/orm-family-mongo/schema-ir`) have a required `name`, the name MongoDB stores the index under. `MongoSchemaIndex.id` is the name, where it was the keys. `MONGO_INDEX_OPTION_KEYS` and `indexLookupKey` leave the name out. `defaultMongoIndexName` moved from `@prisma/orm-family-mongo/query-ast/control` to `@prisma/orm-family-mongo/contract`, and `buildIndexOpId(verb, collection, name)` takes the index name in place of the keys.
|
|
81
|
+
detection:
|
|
82
|
+
glob: "**/*.{ts,mts,cts,tsx}"
|
|
83
|
+
matches:
|
|
84
|
+
- '\bnew\s+(?:MongoIndex|MongoSchemaIndex)\s*\('
|
|
85
|
+
- '\b(?:MongoIndexInput|MongoSchemaIndexOptions)\b'
|
|
86
|
+
- '\b(?:defaultMongoIndexName|buildIndexOpId)\b'
|
|
87
|
+
- id: mongo-index-calls-take-name
|
|
88
|
+
summary: |
|
|
89
|
+
`CreateIndexCall` and `DropIndexCall` (from `@prisma/orm-mongo/target/control`) take a third argument, `IndexCallOptions`: the index's `name` and its `createIndex` options. `schemaIndexToCreateIndexOptions` returns them with the name. `createIndex` and `dropIndex` (from `@prisma/orm-mongo/target/migration`) create and drop the index named `options.name`, or the name after the keys when it is missing. `createIndex` has two prechecks: no index with that name, and none with the same keys and options. `dropIndex` checks the name, keys and options before, and the name after. Labels name the index: `Create index email_1 on users (email:1)`.
|
|
90
|
+
detection:
|
|
91
|
+
glob: "**/*.{ts,mts,cts,tsx}"
|
|
92
|
+
matches:
|
|
93
|
+
- '\bnew\s+(?:CreateIndexCall|DropIndexCall)\s*\('
|
|
94
|
+
- '\bschemaIndexToCreateIndexOptions\b'
|
|
95
|
+
- id: mongo-build-refusal-index-name-duplicate
|
|
96
|
+
summary: |
|
|
97
|
+
The MongoDB contract builder's `BuildRefusal` type, from `@prisma/orm-family-mongo/contract-ts/contract-builder`, has the kind `indexNameDuplicate`, for two indexes of one collection with one name. The builder takes every index's name from its `options.name` and throws for an index without one. Call `nameIndexes(definition)`, from the same entry point, before `mergeRedundantIndexes` and the builder, to name each unnamed index after its stored keys, as Prisma 8 PSL and TypeScript do. `mergeRedundantIndexes` now merges only indexes with the same name.
|
|
98
|
+
detection:
|
|
99
|
+
glob: "**/*.{ts,mts,cts,tsx}"
|
|
100
|
+
matches:
|
|
101
|
+
- '\bBuildRefusal\b'
|
|
102
|
+
- '\bbuildMongoContractFromDefinition\b'
|
|
103
|
+
- '\bmergeRedundantIndexes\b'
|
|
104
|
+
- id: mongo-build-refusal-index-duplicate-restored
|
|
105
|
+
summary: |
|
|
106
|
+
The MongoDB contract builder's `BuildRefusal` type, exported from `@prisma/orm-family-mongo/contract-ts/contract-builder`, has the kind `indexDuplicate` again. The builder no longer merges indexes; it refuses two identical indexes in one collection. To merge identical and redundant indexes before building, as Prisma 8 PSL and TypeScript do, call `mergeRedundantIndexes` from the same entry point.
|
|
107
|
+
detection:
|
|
108
|
+
glob: "**/*.{ts,mts,cts,tsx}"
|
|
109
|
+
matches:
|
|
110
|
+
- '\bBuildRefusal\b'
|
|
111
|
+
- '\bbuildMongoContractFromDefinition\b'
|
|
112
|
+
- id: mongo-execution-context-checks-contract-requirements
|
|
113
|
+
summary: |
|
|
114
|
+
`createMongoExecutionContext` from `@prisma/orm-mongo/family-runtime` refuses a contract its stack cannot serve: `RUNTIME.CONTRACT_FAMILY_MISMATCH` for a contract of another family, `RUNTIME.CONTRACT_TARGET_MISMATCH` for another target, and `RUNTIME.MISSING_EXTENSION_PACK` for a contract that requires an extension pack the stack does not hold. The MongoDB adapter's runtime descriptor now encodes with the codecs of every extension in the stack, so an extension's codec `toWire` runs on writes.
|
|
115
|
+
detection:
|
|
116
|
+
glob: "**/*.{ts,mts,cts,tsx,js,mjs,cjs,jsx}"
|
|
117
|
+
matches:
|
|
118
|
+
- '\bcreateMongoExecutionContext\b'
|
|
119
|
+
- '\bMongoRuntimeExtensionDescriptor\b'
|
|
120
|
+
- id: mongo-codecs-declared-once
|
|
121
|
+
summary: |
|
|
122
|
+
A MongoDB target, adapter or extension descriptor declares each codec once, as a codec descriptor in `types.codecTypes.codecDescriptors`, as a Postgres extension does. The `codecs()` slot that returned a `MongoCodecRegistry` is gone from `MongoStaticContributions`, `MongoRuntimeTargetDescriptor`, `MongoRuntimeAdapterDescriptor` and `MongoRuntimeExtensionDescriptor`. The runtime, the adapter and the migration runner take each codec from its descriptor with `assembleMongoCodecRegistry`. Build a descriptor from a codec with `mongoCodecDescriptor` from `@prisma/orm-family-mongo/codec`.
|
|
123
|
+
detection:
|
|
124
|
+
glob: "**/*.{ts,mts,cts,tsx,js,mjs,cjs,jsx}"
|
|
125
|
+
matches:
|
|
126
|
+
- '\bMongoRuntime(?:Extension|Target|Adapter)Descriptor\b(?:<[^<>]{0,200}>)?\s{0,20}(?:=>?|\{\s{0,20}return)\s{0,20}\(?\s{0,20}\{(?:[^{}]|\{(?:[^{}]|\{(?:[^{}]|\{[^{}]{0,500}\}){0,500}\}){0,500}\}){0,500}?\bcodecs\s{0,20}[:(]'
|
|
127
|
+
- '\bfamilyId\s{0,20}:\s{0,20}[''"]mongo[''"](?:[^{}]|\{(?:[^{}]|\{(?:[^{}]|\{[^{}]{0,500}\}){0,500}\}){0,500}\}){0,500}?\bcodecs\s{0,20}[:(]'
|
|
128
|
+
- '\bcodecs\s{0,20}[:(](?:[^{}]|\{(?:[^{}]|\{(?:[^{}]|\{[^{}]{0,500}\}){0,500}\}){0,500}\}){0,500}?\bfamilyId\s{0,20}:\s{0,20}[''"]mongo[''"]'
|
|
129
|
+
- '(?<![\s\S])(?=[\s\S]*?\b(?:newMongoCodecRegistry|MongoCodecRegistry)\b)[\s\S]*?\{(?:(?!\bfamilyId\s{0,20}:\s{0,20}[''"](?!mongo[''"]))(?:[^{}]|\{(?:[^{}]|\{(?:[^{}]|\{[^{}]{0,500}\}){0,500}\}){0,500}\})){0,500}?(?:\.\.\.(?:(?!\bfamilyId\s{0,20}:\s{0,20}[''"](?!mongo[''"]))(?:[^{}]|\{(?:[^{}]|\{(?:[^{}]|\{[^{}]{0,500}\}){0,500}\}){0,500}\})){0,500}?\bcodecs\s{0,20}(?::\s{0,20}(?:(?:async\s{1,20})?(?:\([^()]{0,200}\)|[\w$]{1,100})\s{0,20}=>|function\b|newMongoCodecRegistry\b(?!\s{0,20}\())|\([^()]{0,200}\)\s{0,20}(?::[^{};]{0,200})?\{(?:[^{}]|\{(?:[^{}]|\{[^{}]{0,500}\}){0,500}\}){0,500}\})|\bcodecs\s{0,20}(?::\s{0,20}(?:(?:async\s{1,20})?(?:\([^()]{0,200}\)|[\w$]{1,100})\s{0,20}=>|function\b|newMongoCodecRegistry\b(?!\s{0,20}\())|\([^()]{0,200}\)\s{0,20}(?::[^{};]{0,200})?\{(?:[^{}]|\{(?:[^{}]|\{[^{}]{0,500}\}){0,500}\}){0,500}\})(?:(?!\bfamilyId\s{0,20}:\s{0,20}[''"](?!mongo[''"]))(?:[^{}]|\{(?:[^{}]|\{(?:[^{}]|\{[^{}]{0,500}\}){0,500}\}){0,500}\})){0,500}?\.\.\.)(?:(?!\bfamilyId\s{0,20}:\s{0,20}[''"](?!mongo[''"]))(?:[^{}]|\{(?:[^{}]|\{(?:[^{}]|\{[^{}]{0,500}\}){0,500}\}){0,500}\})){0,500}?\}'
|
|
130
|
+
- id: mongo-standard-codecs-removed
|
|
131
|
+
summary: |
|
|
132
|
+
`mongoStandardCodecs` and `buildStandardCodecRegistry` are gone from `@prisma/orm-mongo/target/codecs`. The target declares its codecs once, in `mongoCodecDescriptors`. A registry of them is `assembleMongoCodecRegistry([mongoRuntimeTarget])`, with `assembleMongoCodecRegistry` from `@prisma/orm-family-mongo/codec` and the target from `@prisma/orm-mongo/target/runtime`.
|
|
133
|
+
detection:
|
|
134
|
+
glob: "**/*.{ts,mts,cts,tsx,js,mjs,cjs,jsx}"
|
|
135
|
+
matches:
|
|
136
|
+
- '\b(?:mongoStandardCodecs|buildStandardCodecRegistry)\b'
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
# 8.0.0-rc.22 → 8.0.0-rc.23 — Extension author upgrade instructions
|
|
140
|
+
|
|
141
|
+
## Order of the steps
|
|
142
|
+
|
|
143
|
+
No change in this guide comes with a script. Make the changes below in any order, with two exceptions:
|
|
144
|
+
|
|
145
|
+
1. A pack that declares a Postgres extension declares it in the unbound namespace first, then re-emits its contract, then plans its two new migrations (`pack-declares-extension-unbound`).
|
|
146
|
+
2. Code that builds a MongoDB contract from a definition names its indexes, then merges them, then builds (`mongo-build-refusal-index-name-duplicate`, `mongo-build-refusal-index-duplicate-restored`).
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
## MySQL: `temporal-polyfill` is a peer dependency, and `mysqlCreateNamespace` moved
|
|
150
|
+
|
|
151
|
+
### `temporal-polyfill-is-a-peer-dependency-of-mysql`
|
|
152
|
+
|
|
153
|
+
For each Yarn project that `detection` matches, add `"temporal-polyfill": "^1.0.4"` to `devDependencies` in the `package.json` that installs `@prisma/orm-target-mysql` or `@prisma/orm-mysql`, then reinstall. Without it, a test or script that loads the target's control entry fails because Node.js cannot find the package `temporal-polyfill`.
|
|
154
|
+
|
|
155
|
+
### `mysql-create-namespace-moved-to-target-types`
|
|
156
|
+
|
|
157
|
+
In each file that `detection` matches, change the module of an import of `mysqlCreateNamespace` or `MysqlDatabase` from the target's control entry to its types entry, keeping the rest of the import:
|
|
158
|
+
|
|
159
|
+
| Before | After |
|
|
160
|
+
| --- | --- |
|
|
161
|
+
| `@prisma/orm-target-mysql/target/control` | `@prisma/orm-target-mysql/target/types` |
|
|
162
|
+
| `@prisma/orm-mysql/target/control` | `@prisma/orm-mysql/target/types` |
|
|
163
|
+
|
|
164
|
+
If the import also names other symbols from the control entry, split it into two imports. Nothing else changes: the function and the class are the same.
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
## SQLite: `temporal-polyfill` is a peer dependency, and `sqliteCreateNamespace` moved
|
|
168
|
+
|
|
169
|
+
### `temporal-polyfill-is-a-peer-dependency-of-sqlite`
|
|
170
|
+
|
|
171
|
+
For each Yarn project that `detection` matches, add `"temporal-polyfill": "^1.0.4"` to `devDependencies` in the `package.json` that installs `@prisma/orm-target-sqlite` or `@prisma/orm-sqlite`, then reinstall. Without it, a test or script that loads the target's control entry fails because Node.js cannot find the package `temporal-polyfill`.
|
|
172
|
+
|
|
173
|
+
### `sqlite-create-namespace-moved-to-target-types`
|
|
174
|
+
|
|
175
|
+
In each file that `detection` matches, change the module of an import of `sqliteCreateNamespace` or `SqliteUnboundDatabase` from the target's control entry to its types entry, keeping the rest of the import:
|
|
176
|
+
|
|
177
|
+
| Before | After |
|
|
178
|
+
| --- | --- |
|
|
179
|
+
| `@prisma/orm-target-sqlite/target/control` | `@prisma/orm-target-sqlite/target/types` |
|
|
180
|
+
| `@prisma/orm-sqlite/target/control` | `@prisma/orm-sqlite/target/types` |
|
|
181
|
+
|
|
182
|
+
If the import also names other symbols from the control entry, split it into two imports. Nothing else changes: the function and the type are the same.
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
## PostgreSQL's integer, decimal, float and text types are convenience types
|
|
186
|
+
|
|
187
|
+
On PostgreSQL, `Int`, `BigInt`, `Float`, `Decimal`, `String`, `Boolean` and `Bytes` are now convenience types, as `DateTime` already is. Each is named for what a field means, and its optional `storage` argument (and `as`, for `BigInt`) chooses an explicit type named after the database type. Written bare, each gives the same type as before, so schemas that use these names need no change.
|
|
188
|
+
|
|
189
|
+
The explicit types took the database's names. Seven old names stay for one release line as deprecated aliases: they give the same codec and the same contract, and `prisma contract emit` and the editor report a warning where one is written.
|
|
190
|
+
|
|
191
|
+
### `psl-renamed-postgres-scalar-types`
|
|
192
|
+
|
|
193
|
+
Rewrite each field or `types {}` alias written with an old name, keeping its other arguments and attributes:
|
|
194
|
+
|
|
195
|
+
| Before | After | Explicit type it gives |
|
|
196
|
+
| --- | --- | --- |
|
|
197
|
+
| `SmallInt` | `Int(storage: int2)` | `Int2` |
|
|
198
|
+
| `BigIntNumber` | `BigInt(as: number)` | `Int8Number` |
|
|
199
|
+
| `Numeric` | `Decimal` | `NumericString` |
|
|
200
|
+
| `Numeric(p)` | `Decimal(precision: p)` | `NumericString(p)` |
|
|
201
|
+
| `Numeric(p, s)` | `Decimal(precision: p, scale: s)` | `NumericString(p, s)` |
|
|
202
|
+
| `UnboundedInt` | `BigInt(storage: numeric)` | `NumericBigInt` |
|
|
203
|
+
| `Real` | `Float(storage: float4)` | `Float4` |
|
|
204
|
+
| `VarChar` | `String(storage: varchar)` | `Varchar` |
|
|
205
|
+
| `VarChar(n)` | `String(storage: varchar, length: n)` | `Varchar(n)` |
|
|
206
|
+
| `VarBit` | `Varbit` | `Varbit` |
|
|
207
|
+
| `VarBit(n)` | `Varbit(n)` | `Varbit(n)` |
|
|
208
|
+
|
|
209
|
+
`VarBit` has no convenience type, so its replacement is the explicit type. For the others, writing the explicit type in the last column instead is equally correct; it is the same type, and both emit the same contract. The warning names the explicit type because it is the exact replacement for the old name.
|
|
210
|
+
|
|
211
|
+
```prisma
|
|
212
|
+
model Account {
|
|
213
|
+
id Int @id
|
|
214
|
+
visits Int(storage: int2) // was SmallInt
|
|
215
|
+
rank BigInt(as: number) // was BigIntNumber
|
|
216
|
+
price Decimal(precision: 10, scale: 2) // was Numeric(10, 2)
|
|
217
|
+
code String(storage: varchar, length: 12) // was VarChar(12)
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Rewrite only Prisma 8 schemas whose config uses the PostgreSQL target, including the `contract.prisma` copies in migration folders. The detection cannot tell which target a schema is for, so it also matches SQLite's `BigIntNumber` and MySQL's `VarChar`; a match in a project whose `prisma.config.ts` uses the SQLite or MySQL target needs no change. Update comments and documentation that name the old types the same way. Re-emit the contract with `prisma contract emit`: it is byte for byte the same as before.
|
|
222
|
+
|
|
223
|
+
### `ts-renamed-postgres-scalar-helpers`
|
|
224
|
+
|
|
225
|
+
Rewrite only in contracts on PostgreSQL:
|
|
226
|
+
|
|
227
|
+
```ts
|
|
228
|
+
field.column(type.Int({ storage: 'int2' })); // was type.SmallInt()
|
|
229
|
+
field.column(type.BigInt({ as: 'number' })); // was type.BigIntNumber()
|
|
230
|
+
field.column(type.Decimal({ precision: 10, scale: 2 })); // was type.Numeric(10, 2)
|
|
231
|
+
field.column(type.BigInt({ storage: 'numeric' })); // was type.UnboundedInt()
|
|
232
|
+
field.column(type.Float({ storage: 'float4' })); // was type.Real()
|
|
233
|
+
field.column(type.String({ storage: 'varchar', length: 64 })); // was type.VarChar(64)
|
|
234
|
+
field.column(type.Varbit(16)); // was type.VarBit(16)
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
The explicit helpers `type.Int2()`, `type.Int8Number()`, `type.NumericString(10, 2)`, `type.NumericBigInt()`, `type.Float4()` and `type.Varchar(64)` give the same types.
|
|
238
|
+
|
|
239
|
+
The old helpers still compile, and nothing warns where they are called. They are removed in the same release as the deprecated schema names, so rewrite them now.
|
|
240
|
+
|
|
241
|
+
### `ts-renamed-postgres-column-helpers`
|
|
242
|
+
|
|
243
|
+
The detection matches a file that imports `int8Column` or `numericColumn` from `@prisma/orm-postgres/adapter/column-types` or `@internal/adapter-postgres/column-types`. In that file, rename the import and every use of the imported name. Each column helper is named after the explicit type it gives:
|
|
244
|
+
|
|
245
|
+
```ts
|
|
246
|
+
import { int8BigIntColumn, numericStringColumn } from '@prisma/orm-postgres/adapter/column-types';
|
|
247
|
+
|
|
248
|
+
field.column(int8BigIntColumn); // was int8Column
|
|
249
|
+
field.column(numericStringColumn(10, 2)); // was numericColumn(10, 2)
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### `ts-renamed-postgres-type-groupings`
|
|
253
|
+
|
|
254
|
+
Replace the removed exports of `@internal/target-postgres/control`:
|
|
255
|
+
|
|
256
|
+
| Before | After |
|
|
257
|
+
| --- | --- |
|
|
258
|
+
| `postgresScalarAndNativeTypeConstructors` | `postgresScalarTypes` |
|
|
259
|
+
| `postgresScalarAuthoringTypes` | `postgresScalarTypes` |
|
|
260
|
+
| `postgresNativeAuthoringTypes` | `postgresExplicitTypes` |
|
|
261
|
+
|
|
262
|
+
`postgresScalarTypes` holds every name `postgresScalarAuthoringTypes` held, including `Int`, `String`, `Decimal` and the other convenience types. It is not the target's whole `type` namespace: the namespaced `sql.*`, `temporal.*` and `pg.enum`, and the generated-ID aliases such as `UuidString`, are not in it. A test that needs them uses `assembleAuthoringContributions([...]).type`, which already holds every PostgreSQL type; a test that spread a removed export under that namespace can drop the spread.
|
|
263
|
+
|
|
264
|
+
`postgresExplicitTypes` holds only explicit types. Code that looked up `VarChar`, `Numeric`, `SmallInt` or `Real` in `postgresNativeAuthoringTypes` uses `Varchar`, `NumericString`, `Int2` or `Float4` in it.
|
|
265
|
+
|
|
266
|
+
After the rewrite, check that a schema that uses `Int` and `String` still reads with the namespace the code builds.
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
## A pack declares its extension in the unbound namespace
|
|
270
|
+
|
|
271
|
+
```typescript
|
|
272
|
+
import { defineContract, extension, unbound } from '@prisma/orm-postgres/contract-builder';
|
|
273
|
+
|
|
274
|
+
export const contract = defineContract({
|
|
275
|
+
entities: [extension('vector', { namespace: unbound })],
|
|
276
|
+
});
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### `pack-declares-extension-unbound`
|
|
280
|
+
|
|
281
|
+
1. In the pack's contract source, pass `{ namespace: unbound }` to `extension(...)`, importing `unbound` from `@prisma/orm-postgres/contract-builder`. In a PSL contract, move the `extension` block into `namespace unbound { ... }`.
|
|
282
|
+
2. Run `prisma contract emit` in the pack.
|
|
283
|
+
3. Plan two migrations. The first goes from the old head to the new one and has no operations, because the extension a database already has is found through the search path. The second goes from the empty contract to the new head and creates the extension without `WITH SCHEMA`, so a new database takes it in one step. Today `prisma migration plan` reads and writes the migrations of a project's own space under `migrations/app/`, while a pack keeps its migrations directly under `migrations/`, so plan through a temporary copy. Issue TML-3473 tracks removing these steps:
|
|
284
|
+
1. Copy the pack's migration directories and `migrations/refs/` into a new `migrations/app/` directory.
|
|
285
|
+
2. Run `prisma migration plan --from <old head hash> --name <name>`, where the old head hash is the `hash` in `migrations/refs/head.json`. It writes the new migration to `migrations/app/<timestamp>_<name>/` and the new contract snapshot to `migrations/snapshots/<new hash>/`.
|
|
286
|
+
3. Run `prisma migration plan --from @empty --name <other name>`. It writes the migration from the empty contract to `migrations/app/<timestamp>_<other name>/`.
|
|
287
|
+
4. Move both new directories from `migrations/app/` to `migrations/`, then delete `migrations/app/`.
|
|
288
|
+
5. In each moved `migration.ts`, change each import of `../../snapshots/` to `../snapshots/`.
|
|
289
|
+
6. Set `hash` in `migrations/refs/head.json` to the new contract hash, the `to` of the new migrations' `migration.json`, and keep its `invariants`.
|
|
290
|
+
4. Add both new migrations' `migration.json` and `ops.json` to the migrations the pack's control descriptor lists.
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
## MongoDB indexes carry their names
|
|
294
|
+
|
|
295
|
+
Every MongoDB index has a required name, migrations create and drop each index by that name, and the contract builder no longer merges indexes on its own.
|
|
296
|
+
|
|
297
|
+
### `mongo-index-name-required`
|
|
298
|
+
|
|
299
|
+
Give every index you construct a name:
|
|
300
|
+
|
|
301
|
+
```ts
|
|
302
|
+
// before
|
|
303
|
+
new MongoIndex({ keys: [{ field: 'email', direction: 1 }], unique: true });
|
|
304
|
+
new MongoSchemaIndex({ keys: [{ field: 'email', direction: 1 }], unique: true });
|
|
305
|
+
// after
|
|
306
|
+
new MongoIndex({ name: 'email_1', keys: [{ field: 'email', direction: 1 }], unique: true });
|
|
307
|
+
new MongoSchemaIndex({ name: 'email_1', keys: [{ field: 'email', direction: 1 }], unique: true });
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
`defaultMongoIndexName(keys)` gives the name MongoDB gives an index created without one. Import it from `@prisma/orm-family-mongo/contract`:
|
|
311
|
+
|
|
312
|
+
```ts
|
|
313
|
+
// before
|
|
314
|
+
import { defaultMongoIndexName } from '@prisma/orm-family-mongo/query-ast/control';
|
|
315
|
+
// after
|
|
316
|
+
import { defaultMongoIndexName } from '@prisma/orm-family-mongo/contract';
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
Code that looked up an index of the schema IR by `id` with its keys, such as `'email:1'`, looks it up by name. Code that builds an operation id calls `buildIndexOpId('create', 'users', 'email_1')`.
|
|
320
|
+
|
|
321
|
+
### `mongo-index-calls-take-name`
|
|
322
|
+
|
|
323
|
+
```ts
|
|
324
|
+
// before
|
|
325
|
+
new CreateIndexCall('users', keys, { unique: true });
|
|
326
|
+
new DropIndexCall('users', keys);
|
|
327
|
+
// after
|
|
328
|
+
new CreateIndexCall('users', keys, { name: 'email_1', unique: true });
|
|
329
|
+
new DropIndexCall('users', keys, { name: 'email_1', unique: true });
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
Give `DropIndexCall` every option the index has, not only its name: its precheck requires an index with that name, those keys and exactly those options. Code that matches an operation's checks by position reads `createIndex`'s content check at `precheck[1]`; `precheck[0]` checks the name.
|
|
333
|
+
|
|
334
|
+
### `mongo-build-refusal-index-name-duplicate`
|
|
335
|
+
|
|
336
|
+
Code that switches over every `refusal.kind` handles `indexNameDuplicate`:
|
|
337
|
+
|
|
338
|
+
```typescript
|
|
339
|
+
switch (refusal.kind) {
|
|
340
|
+
case 'indexNameDuplicate':
|
|
341
|
+
return `${refusal.key.model}: another index of collection ${refusal.collection} is named ${refusal.name}`;
|
|
342
|
+
// ...
|
|
343
|
+
}
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
Code that calls `buildMongoContractFromDefinition` names its indexes first:
|
|
347
|
+
|
|
348
|
+
```ts
|
|
349
|
+
const named = nameIndexes(definition);
|
|
350
|
+
const { definition: merged } = mergeRedundantIndexes(named, codecLookup, dataTypes);
|
|
351
|
+
const built = buildMongoContractFromDefinition(merged, codecLookup, dataTypes);
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
A source that reads a schema with its own naming rule, such as the Prisma 6 reader, sets `options.name` on each index itself.
|
|
355
|
+
|
|
356
|
+
### `mongo-build-refusal-index-duplicate-restored`
|
|
357
|
+
|
|
358
|
+
Code that switches over every `refusal.kind` must handle `indexDuplicate`:
|
|
359
|
+
|
|
360
|
+
```typescript
|
|
361
|
+
switch (refusal.kind) {
|
|
362
|
+
case 'indexDuplicate':
|
|
363
|
+
return `${refusal.key.model}: an identical index already exists`;
|
|
364
|
+
// ...
|
|
365
|
+
}
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
Code that builds a definition with `buildMongoContractFromDefinition` and relied on the builder merging indexes calls `mergeRedundantIndexes(definition, codecLookup, dataTypes)` first and builds its `definition`. Call `nameIndexes` before `mergeRedundantIndexes`, as the example under `mongo-build-refusal-index-name-duplicate` shows.
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
## MongoDB execution contexts check the contract against the stack
|
|
372
|
+
|
|
373
|
+
### `mongo-execution-context-checks-contract-requirements`
|
|
374
|
+
|
|
375
|
+
1. Where code calls `createMongoExecutionContext({ contract, stack })` with a contract that requires extension packs, build the stack with those packs: `createMongoExecutionStack({ target, adapter, extensions: [myPack] })`.
|
|
376
|
+
2. A MongoDB extension's codecs now encode values on writes as well as decode them on reads. Check that each codec's `toWire` returns the form the database stores, and that `fromWire` reads that form back.
|
|
377
|
+
|
|
378
|
+
### `mongo-codecs-declared-once`
|
|
379
|
+
|
|
380
|
+
Replace the `codecs()` slot of a MongoDB descriptor with one codec descriptor per codec, shared by the pack and the runtime descriptor:
|
|
381
|
+
|
|
382
|
+
```typescript
|
|
383
|
+
import { mongoCodec, mongoCodecDescriptor } from '@prisma/orm-family-mongo/codec';
|
|
384
|
+
|
|
385
|
+
const shoutCodec = mongoCodec({ typeId: 'shout/text@1', dataType: shoutText, toWire, fromWire, fromDataTypeValue });
|
|
386
|
+
|
|
387
|
+
const shoutMeta = {
|
|
388
|
+
kind: 'extension',
|
|
389
|
+
id: 'shout',
|
|
390
|
+
familyId: 'mongo',
|
|
391
|
+
targetId: 'mongo',
|
|
392
|
+
version: '0.0.1',
|
|
393
|
+
dataTypes: [shoutText],
|
|
394
|
+
types: { codecTypes: { codecDescriptors: [mongoCodecDescriptor(shoutCodec, { traits: ['equality'] })] } },
|
|
395
|
+
} as const;
|
|
396
|
+
|
|
397
|
+
export const shoutRuntime: MongoRuntimeExtensionDescriptor<'mongo'> = {
|
|
398
|
+
...shoutMeta,
|
|
399
|
+
create: () => ({ familyId: 'mongo', targetId: 'mongo' }),
|
|
400
|
+
};
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
1. For each codec the `codecs()` registry held, add `mongoCodecDescriptor(codec, { traits })` to `types.codecTypes.codecDescriptors`, with the traits the pack declared for it. If the pack already lists a hand-written descriptor for the codec, replace it with this one.
|
|
404
|
+
2. Delete `codecs` from the descriptor.
|
|
405
|
+
3. Make the runtime and control descriptors spread the same metadata as the pack, so all three list the same descriptors and `dataTypes`.
|
|
406
|
+
|
|
407
|
+
### `mongo-standard-codecs-removed`
|
|
408
|
+
|
|
409
|
+
1. Replace `buildStandardCodecRegistry()` with `assembleMongoCodecRegistry([mongoRuntimeTarget])`.
|
|
410
|
+
2. Replace a read of `mongoStandardCodecs` with the registry: `registry.get(codecId)` for one codec, `[...registry]` for all of them, or with `mongoCodecDescriptors` where only the codec ids or metadata are needed.
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mongo-static-vnC5E2_h-CVOMWNhR.mjs","names":[],"sources":["../../../../3-targets/mongo/9-facade/dist/mongo-static-vnC5E2_h.mjs"],"sourcesContent":["import mongoRuntimeAdapter from \"@internal/adapter-mongo/runtime\";\nimport { mongoRaw } from \"@internal/mongo-orm\";\nimport { createMongoExecutionContext, createMongoExecutionStack, enumMemberCodecFor } from \"@internal/mongo-runtime\";\nimport mongoRuntimeTarget from \"@internal/target-mongo/runtime\";\nimport { validateContractOnce } from \"@internal/contract/validate-once\";\nimport { MongoContractSerializer } from \"@internal/family-mongo/ir\";\nimport { buildNamespacedEnums } from \"@internal/contract/enum-accessor\";\nimport { UNBOUND_NAMESPACE_ID } from \"@internal/framework-components/ir\";\nimport { mongoQuery } from \"@internal/mongo-query-builder\";\nimport { assertDefined } from \"@internal/utils/assertions\";\n//#region package.json\nvar version = \"8.0.0-rc.22-dev.15\";\n//#endregion\n//#region src/static/contract-from-json.ts\nconst serializer = new MongoContractSerializer();\nconst validator = `${mongoRuntimeTarget.targetId}@${version}`;\n/**\n* Validates an emitted Mongo `contract.json` and returns it as the contract type the application\n* names, ready to pass to `mongo({ contract })` and `mongoStatic({ contract })`. Clients built from\n* the result do not validate it again.\n*\n* The returned value's top level is frozen; its nested objects are not. Do not change `json` or the\n* returned value after the call: clients built from the value later do not validate it again.\n*\n* @example\n* ```ts\n* import type { Contract } from './contract.d';\n* import contractJson from './contract.json' with { type: 'json' };\n*\n* export const contract = contractFromJson<Contract>(contractJson);\n* ```\n*/\nfunction contractFromJson(json) {\n\treturn validateContractOnce(json, validator, (input) => serializer.deserializeContract(input));\n}\nfunction validateMongoContract(contract) {\n\treturn contractFromJson(contract);\n}\n//#endregion\n//#region src/static/mongo-static.ts\nfunction buildMongoStaticContext(contract, stack) {\n\tconst context = createMongoExecutionContext({\n\t\tcontract,\n\t\tstack\n\t});\n\tconst enums = Object.freeze(buildNamespacedEnums(context.contract.domain, enumMemberCodecFor(context.codecs)))[UNBOUND_NAMESPACE_ID];\n\tassertDefined(enums, \"the unbound namespace always exists on a mongo builder output\");\n\treturn {\n\t\tcontext,\n\t\tcontract,\n\t\tenums,\n\t\tquery: mongoQuery({ context }),\n\t\traw: mongoRaw({ context })\n\t};\n}\n/**\n* The query surfaces of a Mongo client without a driver: `query`, `raw` and `enums`. Use it where\n* loading `mongodb` is not wanted.\n*\n* @example\n* ```ts\n* const { enums } = mongoStatic({ contract: contractFromJson<Contract>(contractJson) });\n* ```\n*/\nfunction mongoStatic(options) {\n\tconst stack = createMongoExecutionStack({\n\t\ttarget: mongoRuntimeTarget,\n\t\tadapter: mongoRuntimeAdapter,\n\t\textensions: options.extensions ?? []\n\t});\n\treturn buildMongoStaticContext(validateMongoContract(options.contract), stack);\n}\n//#endregion\nexport { validateMongoContract as i, mongoStatic as n, contractFromJson as r, buildMongoStaticContext as t };\n\n//# sourceMappingURL=mongo-static-vnC5E2_h.mjs.map"],"mappings":";;;;;;;;;;;AAWA,IAAI,UAAU;AAGd,MAAM,aAAa,IAAI,wBAAwB;AAC/C,MAAM,YAAY,GAAG,mBAAmB,SAAS,GAAG;;;;;;;;;;;;;;;;;AAiBpD,SAAS,iBAAiB,MAAM;CAC/B,OAAO,qBAAqB,MAAM,YAAY,UAAU,WAAW,oBAAoB,KAAK,CAAC;AAC9F;AACA,SAAS,sBAAsB,UAAU;CACxC,OAAO,iBAAiB,QAAQ;AACjC;AAGA,SAAS,wBAAwB,UAAU,OAAO;CACjD,MAAM,UAAU,4BAA4B;EAC3C;EACA;CACD,CAAC;CACD,MAAM,QAAQ,OAAO,OAAO,qBAAqB,QAAQ,SAAS,QAAQ,mBAAmB,QAAQ,MAAM,CAAC,CAAC,CAAC,CAAC;CAC/G,cAAc,OAAO,+DAA+D;CACpF,OAAO;EACN;EACA;EACA;EACA,OAAO,WAAW,EAAE,QAAQ,CAAC;EAC7B,KAAK,SAAS,EAAE,QAAQ,CAAC;CAC1B;AACD;;;;;;;;;;AAUA,SAAS,YAAY,SAAS;CAC7B,MAAM,QAAQ,0BAA0B;EACvC,QAAQ;EACR,SAAS;EACT,YAAY,QAAQ,cAAc,CAAC;CACpC,CAAC;CACD,OAAO,wBAAwB,sBAAsB,QAAQ,QAAQ,GAAG,KAAK;AAC9E"}
|