@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,731 @@
|
|
|
1
|
+
---
|
|
2
|
+
from: "0.16"
|
|
3
|
+
to: "0.17"
|
|
4
|
+
changes:
|
|
5
|
+
- id: strip-sha256-hash-prefixes
|
|
6
|
+
summary: |
|
|
7
|
+
Content hashes are bare lowercase hex from 0.17 — the `sha256:` prefix is gone from every
|
|
8
|
+
surface (emitted `contract.json` / `contract.d.ts`, migration manifests, refs, CLI output,
|
|
9
|
+
and the database marker/ledger), and framework validators (`coreHash()` / `profileHash()`
|
|
10
|
+
constructors, manifest and contract loaders) reject the legacy prefixed form. Contract hash
|
|
11
|
+
VALUES are unchanged (only the prefix drops; re-emit your pack's committed contract
|
|
12
|
+
artefacts), but `migrationHash` VALUES change because the hashed manifest bytes embed the
|
|
13
|
+
now-bare `from`/`to` strings. Run the colocated codemod over your extension's checked-in
|
|
14
|
+
`migrations/` trees FIRST, before the snapshot-layout migrator in the entries below — the
|
|
15
|
+
0.17 layout migrator accepts only bare-hex trees. The codemod handles both layouts: it
|
|
16
|
+
strips the prefix from every hash literal (manifests, `ops.json`, pre-store sibling
|
|
17
|
+
contract snapshots, store entries under `migrations/snapshots/`, `.d.ts` branded
|
|
18
|
+
literals), maps the empty-tree sentinel `sha256:empty` to `empty`, recomputes each
|
|
19
|
+
`migrationHash`, and repoints `refs/*.json`. Then drop the prefix from any hash literal
|
|
20
|
+
your pack's source, fixtures, or tests hard-code — a prefixed literal now fails validation
|
|
21
|
+
instead of round-tripping. Signed databases your extension maintains (acceptance
|
|
22
|
+
harnesses, reference instances) whose marker/ledger still hold prefixed values report a
|
|
23
|
+
hash mismatch on verify — there is no compatibility shim; re-sign against the regenerated
|
|
24
|
+
contract (`prisma-next db sign`).
|
|
25
|
+
detection:
|
|
26
|
+
glob: "**/*.{json,ts,mts,cts,tsx}"
|
|
27
|
+
contains:
|
|
28
|
+
- 'sha256:'
|
|
29
|
+
anyMatch: true
|
|
30
|
+
script: ./strip-sha256-hash-prefixes.ts
|
|
31
|
+
- id: migration-contract-snapshots-moved-to-content-addressed-store
|
|
32
|
+
summary: |
|
|
33
|
+
Committed migration contract snapshots move from per-package sibling files
|
|
34
|
+
(`start-contract.json` / `start-contract.d.ts` / `end-contract.json` /
|
|
35
|
+
`end-contract.d.ts`) into a single content-addressed store per migrations
|
|
36
|
+
root, at `migrations/snapshots/<hex>/contract.json` + `contract.d.ts`,
|
|
37
|
+
where `<hex>` is the contract's 64-hex storage hash (bare hex after the
|
|
38
|
+
`strip-sha256-hash-prefixes` entry above, which must run first).
|
|
39
|
+
Every distinct contract is stored once, however many migrations
|
|
40
|
+
reference it. An extension source repo keeps the shallow layout — migration
|
|
41
|
+
packages sit directly under `migrations/` (no `app/` segment), so its store
|
|
42
|
+
is `migrations/snapshots/` at the same depth, and every emitted
|
|
43
|
+
`migration.ts` imports its bookend contracts one level up:
|
|
44
|
+
`../snapshots/<hex>/contract.json` / `../snapshots/<hex>/contract.d.ts`
|
|
45
|
+
(a consuming project's `app/`-nested migrations import two levels up,
|
|
46
|
+
`../../snapshots/...` — do not copy that depth into an extension repo).
|
|
47
|
+
This is a clean break: there is no fallback reader for the old sibling-file
|
|
48
|
+
layout, so a committed migrations tree that has not been converted fails to
|
|
49
|
+
load once you upgrade your extension's tooling — `migration plan` /
|
|
50
|
+
`migration new` / `migration check` all read contract snapshots through the
|
|
51
|
+
store only, and a missing store entry fails with
|
|
52
|
+
`MIGRATION.CONTRACT_SNAPSHOT_MISSING` naming the expected hash and path.
|
|
53
|
+
`migration.json` / `ops.json` / `migrationHash` are unaffected — the
|
|
54
|
+
contract snapshot was never part of migration identity, so converting the
|
|
55
|
+
layout changes no migration's hash, and no extension-authoring SPI changes.
|
|
56
|
+
To convert an existing extension repo, run the migrator once from a
|
|
57
|
+
checkout of the `prisma/prisma` repository at (or above) the version
|
|
58
|
+
you're upgrading to, pointed at your extension's migrations root:
|
|
59
|
+
`node scripts/migrate-migrations-layout.mjs <path-to-your-migrations-dir>`.
|
|
60
|
+
Per migration package, it reads `migration.json`, write-if-absents the
|
|
61
|
+
destination contract (and the source contract, when present) into the
|
|
62
|
+
store under the matching hash, rewrites the committed `migration.ts`
|
|
63
|
+
import specifiers, and deletes the four sibling files. It asserts every
|
|
64
|
+
contract's inner `storage.storageHash` against the hash it's filed under
|
|
65
|
+
before writing anything (mismatch aborts the whole run, nothing is
|
|
66
|
+
deleted), and re-verifies every `migrationHash` is unchanged after
|
|
67
|
+
conversion. Run it, review the diff, then typecheck your extension package
|
|
68
|
+
to confirm every rewritten `migration.ts` import resolves.
|
|
69
|
+
detection:
|
|
70
|
+
glob: "**/migration.ts"
|
|
71
|
+
contains:
|
|
72
|
+
- "./start-contract.json"
|
|
73
|
+
- "./end-contract.json"
|
|
74
|
+
- "./start-contract'"
|
|
75
|
+
- "./end-contract'"
|
|
76
|
+
anyMatch: true
|
|
77
|
+
- id: ref-paired-snapshots-moved-to-content-addressed-store
|
|
78
|
+
summary: |
|
|
79
|
+
Ref-paired contract snapshot files (`refs/<name>.contract.json` /
|
|
80
|
+
`refs/<name>.contract.d.ts`) are no longer written or read. A ref is now
|
|
81
|
+
only its pointer file, `refs/<name>.json` (`{ hash, invariants }`); the
|
|
82
|
+
contract it names resolves through the same content-addressed store as
|
|
83
|
+
every migration graph node, `migrations/snapshots/<hex>/contract.json` +
|
|
84
|
+
`contract.d.ts`, by that hash. Your extension repo's `migrations/refs/`
|
|
85
|
+
normally carries only the system `head.json` pointer, which was never
|
|
86
|
+
ref-paired — this only matters if your repo also carries named refs
|
|
87
|
+
(e.g. from testing `ref set` against the extension's own migrations
|
|
88
|
+
root). A pointer whose store entry is missing now fails with
|
|
89
|
+
`MIGRATION.CONTRACT_SNAPSHOT_MISSING` naming the expected hash and path,
|
|
90
|
+
rather than silently falling back to the migration graph. The same
|
|
91
|
+
one-shot migrator that folds per-package sibling snapshots (see the
|
|
92
|
+
entry above) also folds any existing `refs/<name>.contract.json` /
|
|
93
|
+
`refs/<name>.contract.d.ts` pairs: it write-if-absents the pair into the
|
|
94
|
+
store under the sibling pointer's `hash`, then deletes the pair — the
|
|
95
|
+
pointer file itself is read but never written, so it stays
|
|
96
|
+
byte-identical. A `.contract.json` with no sibling pointer, or whose
|
|
97
|
+
inner `storage.storageHash` disagrees with the pointer's `hash`, aborts
|
|
98
|
+
the whole run before anything is written or deleted. Run `node
|
|
99
|
+
scripts/migrate-migrations-layout.mjs <path-to-your-migrations-dir>`
|
|
100
|
+
(same invocation as above; one run folds both migration-package and
|
|
101
|
+
ref-paired snapshots), then review the diff.
|
|
102
|
+
detection:
|
|
103
|
+
glob: "**/refs/*.contract.json"
|
|
104
|
+
anyMatch: true
|
|
105
|
+
- id: extension-packs-key-renamed-to-extensions
|
|
106
|
+
summary: |
|
|
107
|
+
The `extensionPacks` key is renamed to `extensions` across the config
|
|
108
|
+
surface, the SPI, and the contract document. In your extension repo:
|
|
109
|
+
(1) any `prisma.config.ts` (the extension's own contract space, a
|
|
110
|
+
sibling example app, tests) renames `extensionPacks:` to `extensions:` —
|
|
111
|
+
the old key fails loudly with "Config.extensionPacks is no longer
|
|
112
|
+
supported; rename it to Config.extensions"; (2) the provider-API field
|
|
113
|
+
`ContractSourceContext.composedExtensionPacks` is now
|
|
114
|
+
`composedExtensions`; (3) the emitted `contract.json` / `contract.d.ts`
|
|
115
|
+
top-level key is `extensions`, and because the key sits in the
|
|
116
|
+
canonicalized bytes, every contract's `storageHash` / `executionHash` /
|
|
117
|
+
`profileHash` changes. Re-run your contract-space build
|
|
118
|
+
(`build:contract-space` or `prisma-next contract emit`), re-anchor
|
|
119
|
+
`migrations/refs/head.json` and the `migrations/snapshots/<hex>/` store
|
|
120
|
+
to the new hashes, and re-emit `ops.json` / `migration.json` for the
|
|
121
|
+
head migration (its `to` hash changes). Concept-level SPI type names
|
|
122
|
+
(`ExtensionPackRef`, `ControlExtensionDescriptor`,
|
|
123
|
+
`validateExtensionPackRefs`) are unchanged. Also renamed in the same
|
|
124
|
+
release: `contract.source.sourceFormat` → `format`, and the target
|
|
125
|
+
façades' `defineConfig` option `outputPath` → `output`.
|
|
126
|
+
detection:
|
|
127
|
+
glob: "**/*.{ts,json}"
|
|
128
|
+
contains:
|
|
129
|
+
- "extensionPacks"
|
|
130
|
+
- "composedExtensionPacks"
|
|
131
|
+
anyMatch: true
|
|
132
|
+
- id: orm-count-only-mutation-terminals-renamed
|
|
133
|
+
summary: Replace `createCount(...)`, `updateCount(...)`, and `deleteCount()` with `createAndCount(...)`, `updateAndCount(...)`, and `deleteAndCount()` in ORM call sites; arguments, guards, behavior, and `Promise<number>` results are unchanged, and no compatibility aliases remain.
|
|
134
|
+
detection:
|
|
135
|
+
glob: "**/*.{ts,tsx,mts,cts}"
|
|
136
|
+
contains:
|
|
137
|
+
- ".createCount("
|
|
138
|
+
- ".updateCount("
|
|
139
|
+
- ".deleteCount("
|
|
140
|
+
anyMatch: true
|
|
141
|
+
- id: adopt-sql-json-projection-ast-foundations
|
|
142
|
+
summary: Migrate relational AST construction and traversal to explicit JSON projection wrappers, expanded scalar-expression variants, grouped function-source aliases, and codec-preserving forwarded projections.
|
|
143
|
+
detection:
|
|
144
|
+
glob: "**/*.{ts,tsx}"
|
|
145
|
+
contains:
|
|
146
|
+
- "JsonObjectExpr"
|
|
147
|
+
- "JsonArrayAggExpr"
|
|
148
|
+
- "ExprVisitor"
|
|
149
|
+
- "AnyExpression"
|
|
150
|
+
- "FunctionSource.of"
|
|
151
|
+
- "ProjectionItem.of"
|
|
152
|
+
anyMatch: true
|
|
153
|
+
- id: scalar-type-descriptors-channel-removed
|
|
154
|
+
summary: |
|
|
155
|
+
`ComponentMetadata.scalarTypeDescriptors` is retired — the unified authoring type namespace
|
|
156
|
+
is now the single channel for scalar types. If your extension/adapter descriptor declared
|
|
157
|
+
`scalarTypeDescriptors: new Map([['String', 'pg/text@1'], ...])`, move each entry to a
|
|
158
|
+
zero-arg type-constructor contribution in the descriptor's `authoring.type` namespace:
|
|
159
|
+
`String: { kind: 'typeConstructor', output: { codecId: 'pg/text@1', nativeType: 'text' } }`.
|
|
160
|
+
The `nativeType` is now explicit — it was previously derived from the codec's first target
|
|
161
|
+
type, so check the codec manifest for the value to inline. Code that read
|
|
162
|
+
`ControlStack.scalarTypeDescriptors` / `ContractSourceContext.scalarTypeDescriptors` should
|
|
163
|
+
read `stack.scalarTypes` (the scalar type names) or derive the name ->
|
|
164
|
+
`{ codecId, nativeType }` map via `collectScalarTypeConstructors(stack.authoringContributions.type)`
|
|
165
|
+
from `@internal/framework-components/authoring`. `assembleScalarTypeDescriptors` is
|
|
166
|
+
deleted, and `validateScalarTypeCodecIds` now takes the authoring type namespace instead of
|
|
167
|
+
a descriptor map.
|
|
168
|
+
detection:
|
|
169
|
+
glob: "**/*.{ts,mts,cts}"
|
|
170
|
+
contains:
|
|
171
|
+
- "scalarTypeDescriptors"
|
|
172
|
+
- "assembleScalarTypeDescriptors"
|
|
173
|
+
anyMatch: true
|
|
174
|
+
- id: postgres-native-types-move-to-type-position
|
|
175
|
+
summary: |
|
|
176
|
+
PostgreSQL native storage types are authored directly in PSL type position, and the legacy `@db.*` attribute channel is removed. Rewrite `BaseType @db.Type` as `Type` and `BaseType @db.Type(args)` as `Type(args)` in extension schemas and test fixtures, then re-run contract emission. Any remaining `@db.X(args)` fails with `@db.X(args) is no longer supported; use X(args) in type position`, preserving the constructor name and arguments in the suggested replacement. The supported translations are `@db.Char` → `Char`, `@db.VarChar` → `VarChar`, `@db.Numeric` → `Numeric`, `@db.Uuid` → `Uuid`, `@db.Inet` → `Inet`, `@db.SmallInt` → `SmallInt`, `@db.Real` → `Real`, `@db.Timestamp` → `Timestamp`, `@db.Timestamptz` → `Timestamptz`, `@db.Date` → `Date`, `@db.Time` → `Time`, and `@db.Timetz` → `Timetz`; preserve constructor arguments. Rewrite the old native-json spelling `Json @db.Json` as bare `Json`. This source migration preserves native types and supplied type parameters. It also preserves codec ids except for `@db.Date` → `Date`, which rebinds `pg/timestamptz@1` to `pg/date@1`, changes the contract storage hash, and requires re-emission plus re-signing; see the `postgres-date-rebound-to-pg-date` entry below. Separately, apply the `postgres-json-rebound-to-native-json` entry below to old bare `Json` fields that meant jsonb storage.
|
|
177
|
+
detection:
|
|
178
|
+
glob: "**/*.prisma"
|
|
179
|
+
contains:
|
|
180
|
+
- "@db."
|
|
181
|
+
anyMatch: true
|
|
182
|
+
- id: postgres-json-rebound-to-native-json
|
|
183
|
+
summary: |
|
|
184
|
+
On the postgres target the PSL `Json` scalar re-binds from `pg/jsonb@1` / `jsonb` to
|
|
185
|
+
`pg/json@1` / `json`; a new bare `Jsonb` scalar carries `pg/jsonb@1` / `jsonb`
|
|
186
|
+
(`postgresScalarAuthoringTypes` in `@internal/adapter-postgres`). Extension test
|
|
187
|
+
schemas and fixtures that author postgres `Json` fields and mean jsonb storage must
|
|
188
|
+
switch those fields to `Jsonb`; assertions that pin the `Json` name's derived binding
|
|
189
|
+
(e.g. over `collectScalarTypeConstructors(stack.authoringContributions.type)` or
|
|
190
|
+
`stack.scalarTypes`) now expect `Json -> { codecId: 'pg/json@1', nativeType: 'json' }`
|
|
191
|
+
plus the new `Jsonb -> { codecId: 'pg/jsonb@1', nativeType: 'jsonb' }` entry. PSL
|
|
192
|
+
value-object storage columns still emit jsonb (the interpreter now prefers the target's `Jsonb` scalar and falls back to `Json`). The removed `@db.Json` spelling must be rewritten from `Json @db.Json` to bare `Json`; any remaining use fails with migration guidance to use `Json` in type position. SQLite and Mongo `Json` bindings and the TS builder surface (`field.json()`, `jsonbColumn`) are unchanged.
|
|
193
|
+
detection:
|
|
194
|
+
glob: "**/*.{prisma,ts,mts,cts}"
|
|
195
|
+
contains:
|
|
196
|
+
- "Json"
|
|
197
|
+
anyMatch: true
|
|
198
|
+
- id: default-generators-no-longer-set-storage
|
|
199
|
+
summary: |
|
|
200
|
+
`@default(<generator>)` never mutates a column's storage any more — the type position is
|
|
201
|
+
the only storage decider — and the whole generator-storage-override SPI is retired with
|
|
202
|
+
it. Removed surfaces: `MutationDefaultGeneratorDescriptor.resolveGeneratedColumnDescriptor`
|
|
203
|
+
(`@internal/framework-components/control`) — generator descriptors are now
|
|
204
|
+
`{ id, applicableCodecIds?, buildPhases? }` only, and `applicableCodecIds` remains the
|
|
205
|
+
validation channel (`PSL_INVALID_DEFAULT_APPLICABILITY` on mismatch); the transitional
|
|
206
|
+
`baseScalar` marker on `AuthoringTypeConstructorDescriptor` and
|
|
207
|
+
`ScalarTypeConstructorOutput` (`@internal/framework-components/authoring`) — scalar
|
|
208
|
+
type-constructor contributions and the derived scalar view are plain
|
|
209
|
+
`{ codecId, nativeType, typeParams? }` again; and the `@internal/ids` exports
|
|
210
|
+
`resolveBuiltinGeneratedColumnDescriptor` / `GeneratedColumnDescriptor` (the TS spec
|
|
211
|
+
helpers `uuidv4()`, `nanoid()`, … still return `GeneratedColumnSpec` bundling their
|
|
212
|
+
explicit `sql/char@1` column). Packs that registered a generator descriptor with a
|
|
213
|
+
storage-resolution hook must drop the hook; PSL schemas in extension fixtures relying on
|
|
214
|
+
`String @default(uuid()/cuid()/nanoid()/ulid())` producing `character(N)` columns must
|
|
215
|
+
either accept the target String storage (postgres: `pg/text@1` / `text`) or author the
|
|
216
|
+
char storage explicitly in the type position (`Char(36) @default(uuid())`, …), then
|
|
217
|
+
re-emit.
|
|
218
|
+
detection:
|
|
219
|
+
glob: "**/*.{ts,mts,cts,prisma}"
|
|
220
|
+
contains:
|
|
221
|
+
- "resolveGeneratedColumnDescriptor"
|
|
222
|
+
- "resolveBuiltinGeneratedColumnDescriptor"
|
|
223
|
+
- "baseScalar"
|
|
224
|
+
- "@default(uuid("
|
|
225
|
+
- "@default(cuid("
|
|
226
|
+
- "@default(nanoid("
|
|
227
|
+
- "@default(ulid("
|
|
228
|
+
anyMatch: true
|
|
229
|
+
- id: postgres-date-rebound-to-pg-date
|
|
230
|
+
summary: |
|
|
231
|
+
On the postgres target, the bare `Date` type constructor (`postgresNativeAuthoringTypes` in `@internal/adapter-postgres`) re-binds from `pg/timestamptz@1` to the dedicated `pg/date@1` codec. Rewrite the removed `DateTime @db.Date` spelling as `Date`; leaving it unchanged now fails with migration guidance to use `Date` in type position. The stored native type is unchanged (`date`). Extension assertions over `collectScalarTypeConstructors(stack.authoringContributions.type)` now expect `Date -> { codecId: 'pg/date@1', nativeType: 'date' }`. Extension test schemas and fixtures with date columns produce a different codec ref and contract storage hash on re-emit; regenerate committed contract artefacts and update pinned hash or codec-ref literals. Runtime fixtures change shape too:
|
|
232
|
+
`pg/date@1` canonicalizes the JS value as a `Date` at UTC midnight
|
|
233
|
+
(`new Date(Date.UTC(y, m, d))`) instead of passing through the driver's local-midnight
|
|
234
|
+
`Date`, and its JSON form is the bare `YYYY-MM-DD` string, so relation `.include()`
|
|
235
|
+
decode over date columns now succeeds instead of failing with `RUNTIME.DECODE_FAILED`.
|
|
236
|
+
Contracts emitted before the upgrade keep working (`pg/timestamptz@1` still exists).
|
|
237
|
+
detection:
|
|
238
|
+
glob: "**/*.{prisma,ts,mts,cts}"
|
|
239
|
+
regex:
|
|
240
|
+
- '@db\.Date'
|
|
241
|
+
- '\sDate(\s|\?|\[|$)'
|
|
242
|
+
anyMatch: true
|
|
243
|
+
- id: sql-escape-error-class-removed
|
|
244
|
+
summary: |
|
|
245
|
+
The `SqlEscapeError` class is deleted from `@internal/target-postgres` and
|
|
246
|
+
`@internal/target-sqlite` (including its re-export from the postgres/sqlite
|
|
247
|
+
adapter `control` entrypoints). Identifier/literal escaping failures now throw a
|
|
248
|
+
structured envelope with code `CONTRACT.IDENTIFIER_INVALID`. Replace
|
|
249
|
+
`error instanceof SqlEscapeError` with
|
|
250
|
+
`isStructuredError(error) && error.code === 'CONTRACT.IDENTIFIER_INVALID'`
|
|
251
|
+
(`isStructuredError` from `@internal/utils/structured-error`). Message text is
|
|
252
|
+
unchanged.
|
|
253
|
+
detection:
|
|
254
|
+
glob: "**/*.{ts,mts,cts}"
|
|
255
|
+
contains:
|
|
256
|
+
- "SqlEscapeError"
|
|
257
|
+
- id: supabase-error-classes-removed
|
|
258
|
+
summary: |
|
|
259
|
+
The `SupabaseConfigError` and `InvalidJwtError` classes are deleted from
|
|
260
|
+
`@internal/extension-supabase/runtime`. The same failures now throw
|
|
261
|
+
structured envelopes with codes `SUPABASE.CONFIG_INVALID` and
|
|
262
|
+
`SUPABASE.JWT_INVALID`. Replace `error instanceof SupabaseConfigError` with
|
|
263
|
+
`isStructuredError(error) && error.code === 'SUPABASE.CONFIG_INVALID'` and
|
|
264
|
+
`error instanceof InvalidJwtError` with
|
|
265
|
+
`isStructuredError(error) && error.code === 'SUPABASE.JWT_INVALID'`
|
|
266
|
+
(`isStructuredError` from `@internal/utils/structured-error`). Message
|
|
267
|
+
text is unchanged.
|
|
268
|
+
detection:
|
|
269
|
+
glob: "**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}"
|
|
270
|
+
contains:
|
|
271
|
+
- "SupabaseConfigError"
|
|
272
|
+
- "InvalidJwtError"
|
|
273
|
+
anyMatch: true
|
|
274
|
+
|
|
275
|
+
- id: rls-wire-name-helpers-moved-to-sql-schema-ir-naming
|
|
276
|
+
summary: |
|
|
277
|
+
The RLS wire-name helpers moved out of the target-postgres RLS surface into the
|
|
278
|
+
family-shared naming module, with generalized names — the wire-name scheme now serves
|
|
279
|
+
indexes as well as policies. Deleted from
|
|
280
|
+
`@internal/target-postgres/rls-canonicalize`: `formatRlsPolicyWireName`,
|
|
281
|
+
`parseRlsPolicyWireName`, `normalizePredicate`, and the `RlsPolicyWireName` type. Import
|
|
282
|
+
the replacements from `@internal/sql-schema-ir/naming` instead: `formatWireName`,
|
|
283
|
+
`parseWireName`, `normalizeSqlBody`, and `WireName`. Behavior is byte-identical (same
|
|
284
|
+
`<prefix>_<8hex>` format, same all-prefix-on-no-parse contract, same trim +
|
|
285
|
+
whitespace-collapse normalizer). `@internal/target-postgres/rls-canonicalize` still
|
|
286
|
+
exports the RLS-specific surface: `computeContentHash`, `ContentHashParts`,
|
|
287
|
+
`POLICY_OPERATION_PREDICATES`, `RlsPolicyOperation`. The naming module also gains
|
|
288
|
+
`computeIndexContentHash`, `WIRE_NAME_PREFIX_MAX_LENGTH`, and
|
|
289
|
+
`assertWireNamePrefixLength` for packs that construct index wire names.
|
|
290
|
+
detection:
|
|
291
|
+
glob: "**/*.{ts,mts,cts}"
|
|
292
|
+
contains:
|
|
293
|
+
- "formatRlsPolicyWireName"
|
|
294
|
+
- "parseRlsPolicyWireName"
|
|
295
|
+
- "normalizePredicate"
|
|
296
|
+
- "RlsPolicyWireName"
|
|
297
|
+
anyMatch: true
|
|
298
|
+
- id: rls-policy-migration-literal-carries-the-naming-union
|
|
299
|
+
summary: |
|
|
300
|
+
The Postgres RLS policy migration literal spells its name as one union field from 0.17.
|
|
301
|
+
`PostgresRlsPolicyMigrationInput` is deleted from `@internal/target-postgres/types`;
|
|
302
|
+
the parameter `Migration#createRlsPolicy` accepts and the renderer writes is
|
|
303
|
+
`RenderedRlsPolicyLiteral`, which is `PostgresRlsPolicyInput` with absent-valued keys
|
|
304
|
+
omittable — so the flat `name` / `prefix` pair becomes `naming: { kind: "exact", name }`
|
|
305
|
+
or `naming: { kind: "wire", prefix, hash }`. The contract-JSON shape is unchanged and
|
|
306
|
+
keeps its own type, `SerializedRlsPolicy`, hydrated by `policyInputFromSerialized`
|
|
307
|
+
(0.16's `rlsPolicyInputFromFlat`). Pack code constructing `PostgresRlsPolicy` directly
|
|
308
|
+
already passed the `naming` union and is unaffected; pack code that built the flat
|
|
309
|
+
migration literal, or that imported `PostgresRlsPolicyMigrationInput`, must switch to
|
|
310
|
+
`RenderedRlsPolicyLiteral` and the union field. Regenerate any committed migration your
|
|
311
|
+
pack ships that calls `createRlsPolicy` — a 0.16 file fails to compile with
|
|
312
|
+
`Property 'naming' is missing`.
|
|
313
|
+
detection:
|
|
314
|
+
glob: "**/*.{ts,mts,cts}"
|
|
315
|
+
contains:
|
|
316
|
+
- "PostgresRlsPolicyMigrationInput"
|
|
317
|
+
- "rlsPolicyInputFromFlat"
|
|
318
|
+
- "createRlsPolicy"
|
|
319
|
+
anyMatch: true
|
|
320
|
+
- id: sql-index-entities-are-name-identified
|
|
321
|
+
summary: |
|
|
322
|
+
SQL index entities are name-identified from 0.17, at both layers an extension touches.
|
|
323
|
+
Contract IR (`Index` from `@internal/sql-contract/types`): `name` (full physical
|
|
324
|
+
name) and `unique` are required, `prefix` marks a wire name (`name` must parse
|
|
325
|
+
back to `prefix` + 8-hex suffix), and `columns` became optional — exactly one of
|
|
326
|
+
`columns` / `expression` must be set; the constructor and `IndexSchema` validation
|
|
327
|
+
throw on the old shape, so any pack code or test fixture building `indexes: [{ columns:
|
|
328
|
+
[...] }]` must add a real `name` and `unique`. The `index(...)` factory from
|
|
329
|
+
`@internal/sql-contract/factories` is now `index(name, columns, opts?)`. Schema IR
|
|
330
|
+
(`SqlIndexIR` from `@internal/sql-schema-ir/types`): the input requires `name` plus
|
|
331
|
+
explicit `prefix` / `expression` / `where` keys, the diff-tree id is `index:<name>`
|
|
332
|
+
(tuple-derived ids are gone — assertions on `index:<col,col>` ids must switch to the
|
|
333
|
+
name), and `isEqualTo` is mode-selected: both modes compare `unique`/`type` strict,
|
|
334
|
+
`options` loose, `columns` ordered-strict when both sides carry them; an exact-named
|
|
335
|
+
node (no `prefix`) additionally byte-compares `expression`/`where`; a wire-named node
|
|
336
|
+
never compares bodies. Construction sites must supply the real physical name — never a
|
|
337
|
+
placeholder. Re-emit your pack's committed contract space (`build:contract-space` /
|
|
338
|
+
`contract:generate`); storage hashes move for every contract that declares indexes, and
|
|
339
|
+
wire-named index physical names gain the `_<8hex>` content-hash suffix (see the user-skill
|
|
340
|
+
`indexes-are-name-identified` entry for the database-convergence flow — the first
|
|
341
|
+
widening plan is renames-only).
|
|
342
|
+
detection:
|
|
343
|
+
glob: "**/*.{ts,mts,cts}"
|
|
344
|
+
contains:
|
|
345
|
+
- "SqlIndexIR"
|
|
346
|
+
- "indexes: ["
|
|
347
|
+
- "indexes:["
|
|
348
|
+
anyMatch: true
|
|
349
|
+
- id: framework-error-classes-removed
|
|
350
|
+
summary: |
|
|
351
|
+
Three exported framework error classes are deleted: `ConfigFileNotFoundError`
|
|
352
|
+
(from `@internal/config-loader`), `ConfigValidationError` (from
|
|
353
|
+
`@internal/config/config-validation`), and `DomainNamespaceResolutionError`
|
|
354
|
+
(from `@internal/contract/types`). The same failures now throw structured
|
|
355
|
+
envelopes with codes `CONFIG.FILE_NOT_FOUND`, `CONFIG.VALIDATION_FAILED`, and
|
|
356
|
+
`CONTRACT.NAMESPACE_INVALID` respectively. Replace each
|
|
357
|
+
`error instanceof <Class>` with
|
|
358
|
+
`isStructuredError(error) && error.code === '<CODE>'`
|
|
359
|
+
(`isStructuredError` from `@internal/utils/structured-error`). Message
|
|
360
|
+
text is unchanged.
|
|
361
|
+
detection:
|
|
362
|
+
glob: "**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}"
|
|
363
|
+
contains:
|
|
364
|
+
- "ConfigFileNotFoundError"
|
|
365
|
+
- "ConfigValidationError"
|
|
366
|
+
- "DomainNamespaceResolutionError"
|
|
367
|
+
anyMatch: true
|
|
368
|
+
- id: postgres-extension-codecs-require-target-descriptors
|
|
369
|
+
summary: Migrate PostgreSQL-bound extension codecs to the target-owned descriptor protocol and contribute one target-typed descriptor set through runtime and control stacks.
|
|
370
|
+
detection:
|
|
371
|
+
glob: "**/*.{ts,tsx}"
|
|
372
|
+
contains:
|
|
373
|
+
- "extends CodecDescriptorImpl"
|
|
374
|
+
- "CodecDescriptorImpl<"
|
|
375
|
+
- "readonly AnyCodecDescriptor[]"
|
|
376
|
+
anyMatch: true
|
|
377
|
+
- id: rls-policies-gain-exact-names
|
|
378
|
+
summary: |
|
|
379
|
+
RLS policies adopt the same wire/exact identity split as indexes. On
|
|
380
|
+
`PostgresRlsPolicyInput` / `PostgresPolicySchemaNodeInput`, `prefix`, `using`,
|
|
381
|
+
`withCheck` (and the node input's `dependsOn`) change from optional keys to REQUIRED
|
|
382
|
+
keys typed `| undefined` — a hard compile break for every existing construction site
|
|
383
|
+
that omitted them: `new PostgresRlsPolicy({ …, using })` without `withCheck` no longer
|
|
384
|
+
compiles. Fix: state the absent keys explicitly (`withCheck: undefined`,
|
|
385
|
+
`prefix: undefined`, `dependsOn: undefined`). In the serialized policy contract schema
|
|
386
|
+
`prefix` stays optional — its presence means wire-named, absence means
|
|
387
|
+
exact-named (a verbatim adopted physical name). Both constructors now ENFORCE that a
|
|
388
|
+
declared
|
|
389
|
+
`prefix` matches the wire name's parsed prefix: pack code or test fixtures building a
|
|
390
|
+
`PostgresRlsPolicy` / `PostgresPolicySchemaNode` whose `name` is not
|
|
391
|
+
`<prefix>_<8hex>`-shaped while still passing a `prefix` (e.g. `prefix: name` for a
|
|
392
|
+
hand-written legacy name) now throw — omit `prefix` for such names; that is the
|
|
393
|
+
exact-named spelling. Exact-named policy nodes compare by content (`operation` /
|
|
394
|
+
`permissive` strict, `roles` as a deduplicated sorted set, `using` / `withCheck`
|
|
395
|
+
byte-for-byte), so a
|
|
396
|
+
body-drifted same-named exact policy now surfaces as a `not-equal` verify issue and a
|
|
397
|
+
drop + create plan instead of being invisible. PSL policy blocks newly accept
|
|
398
|
+
`@@map("physical name")` to author the exact mode (additive — wire lowering is
|
|
399
|
+
byte-unchanged).
|
|
400
|
+
detection:
|
|
401
|
+
glob: "**/*.{ts,mts,cts,prisma}"
|
|
402
|
+
contains:
|
|
403
|
+
- "PostgresRlsPolicy"
|
|
404
|
+
- "PostgresPolicySchemaNode"
|
|
405
|
+
- "policy_select"
|
|
406
|
+
- "policy_insert"
|
|
407
|
+
- "policy_update"
|
|
408
|
+
- "policy_delete"
|
|
409
|
+
- "policy_all"
|
|
410
|
+
- id: codec-json-projections-must-agree-with-encode-json
|
|
411
|
+
summary: |
|
|
412
|
+
A target codec descriptor's `jsonProjection` hook is now live rather than a placeholder:
|
|
413
|
+
it states, as SQL, the canonical JSON of the codec it belongs to, and the two sides are
|
|
414
|
+
required to agree — the parsed projection must equal `encodeJson(value)`, and
|
|
415
|
+
`decodeJson` of that must return the application value. If your extension contributes a
|
|
416
|
+
PostgreSQL or SQLite codec descriptor whose `jsonProjection` still returns its argument
|
|
417
|
+
unchanged, check that the target's own JSON conversion really is your canonical form; if
|
|
418
|
+
it is not, the projection has to replace that conversion rather than post-process it.
|
|
419
|
+
Where a cast is needed it belongs *inside* the projected expression, so it applies before
|
|
420
|
+
the JSON constructor sees the value — a cast applied to the constructor's result is too
|
|
421
|
+
late, because the value has already been converted. `encodeJson` / `decodeJson` move with
|
|
422
|
+
the projection, in the same change.
|
|
423
|
+
detection:
|
|
424
|
+
glob: "**/*.{ts,tsx}"
|
|
425
|
+
contains:
|
|
426
|
+
- "jsonProjection"
|
|
427
|
+
- "PostgresCodecDescriptor"
|
|
428
|
+
- "SqliteCodecDescriptor"
|
|
429
|
+
anyMatch: true
|
|
430
|
+
- id: pgvector-json-form-is-a-numeric-array
|
|
431
|
+
summary: |
|
|
432
|
+
`pg/vector@1` encodes to and decodes from a JSON numeric array — `[1,2,3]` — where it used
|
|
433
|
+
the string `"[1,2,3]"`. `decodeJson` rejects the string form, because reading a vector's
|
|
434
|
+
text back at double width lands on a different number: a vector's elements are `real`, and
|
|
435
|
+
its text form prints the shortest decimal that round-trips *as a real*. If your extension
|
|
436
|
+
consumes `pg/vector@1` values out of a contract, or models a codec on it, switch to the
|
|
437
|
+
array form. Note the element type: an application value must be exactly representable as a
|
|
438
|
+
32-bit float to round-trip at all.
|
|
439
|
+
detection:
|
|
440
|
+
glob: "**/*.{ts,tsx,json}"
|
|
441
|
+
contains:
|
|
442
|
+
- "pg/vector@1"
|
|
443
|
+
anyMatch: true
|
|
444
|
+
- id: default-literal-value-resolves-through-the-codec-json-channel
|
|
445
|
+
summary: |
|
|
446
|
+
`ExtractCodecTypes` gains a `json` channel beside `input` and `output`, read off a codec's
|
|
447
|
+
declared `encodeJson` return type, and the emitted `DefaultLiteralValue` helper resolves a
|
|
448
|
+
contract's literal default through that channel rather than through the codec's application
|
|
449
|
+
type. A literal default lives in `contract.json`, so it is typed by what the file holds and
|
|
450
|
+
not by what the application receives — the two diverge for any codec whose canonical JSON
|
|
451
|
+
differs from its application value. Re-run your contract-space build
|
|
452
|
+
(`pnpm build:contract-space`, or `prisma-next contract emit`) to regenerate every
|
|
453
|
+
`contract.d.ts`; the alias definition changes in each. A codec that narrows its
|
|
454
|
+
`encodeJson` return type publishes its JSON type through the new channel; one that does not
|
|
455
|
+
keeps the `JsonValue` the base signature promises.
|
|
456
|
+
detection:
|
|
457
|
+
glob: "**/*.{ts,d.ts}"
|
|
458
|
+
contains:
|
|
459
|
+
- "DefaultLiteralValue"
|
|
460
|
+
- "ExtractCodecTypes"
|
|
461
|
+
anyMatch: true
|
|
462
|
+
- id: pg-int8-application-values-are-bigint
|
|
463
|
+
summary: |
|
|
464
|
+
`pg/int8@1` carries `bigint` application values where it carried `number`, and its JSON
|
|
465
|
+
form is decimal text. Extension code that reads an `int8` column, resolves an aggregate to
|
|
466
|
+
that codec, or hand-writes an `int8` literal default must move to `bigint` and to the
|
|
467
|
+
decimal-string JSON spelling. `parsePostgresDefault` changes with it: an introspected
|
|
468
|
+
`int8` default now reads as decimal text across the whole signed 64-bit range, where it
|
|
469
|
+
previously returned a `number` for a safe integer and a string only past 2^53 — if your
|
|
470
|
+
extension compares introspected defaults against contract defaults, that split is gone.
|
|
471
|
+
detection:
|
|
472
|
+
glob: "**/*.{ts,tsx}"
|
|
473
|
+
contains:
|
|
474
|
+
- "pg/int8@1"
|
|
475
|
+
- "parsePostgresDefault"
|
|
476
|
+
anyMatch: true
|
|
477
|
+
- id: extension-column-codecs-must-be-declared-as-target-descriptors
|
|
478
|
+
summary: |
|
|
479
|
+
An extension that contributes a codec used on a *column* must publish its target descriptors
|
|
480
|
+
through `types.codecTypes.codecDescriptors` on the runtime (and control) extension
|
|
481
|
+
descriptor. The renderers resolve a column's JSON projection out of the assembled descriptor
|
|
482
|
+
registry, which is built from that field alone — `codecs()` feeds a different path. A codec
|
|
483
|
+
reachable through `codecs()` but absent from `types.codecTypes.codecDescriptors` now fails at
|
|
484
|
+
lowering with `RUNTIME.PARAM_REF_MISSING_CODEC` naming the codec id, where the renderer
|
|
485
|
+
previously ignored codec identity and emitted the bare column. The failure is deliberate:
|
|
486
|
+
emitting the bare column would produce exactly the uncanonical JSON the projection exists to
|
|
487
|
+
replace. Publish the same target-typed set in both places.
|
|
488
|
+
detection:
|
|
489
|
+
glob: "**/*.{ts,tsx}"
|
|
490
|
+
contains:
|
|
491
|
+
- "codecTypes"
|
|
492
|
+
- "codecs: () =>"
|
|
493
|
+
- "SqlRuntimeExtensionDescriptor"
|
|
494
|
+
anyMatch: true
|
|
495
|
+
- id: contract-infer-emits-full-fidelity
|
|
496
|
+
summary: |
|
|
497
|
+
`contract infer` emits every non-constraint index (expression, partial `where:`,
|
|
498
|
+
unique, `type:`/`options:`) and the RLS surface (`@@rls` natively, every policy as a
|
|
499
|
+
`policy_<operation>` block with `@@map` and verbatim reprinted bodies, `permissive =
|
|
500
|
+
false` for RESTRICTIVE rows). A pack whose contract-space generator runs infer (the
|
|
501
|
+
supabase pattern) sees ADDITIVE movement on its next regeneration: previously omitted
|
|
502
|
+
partial/expression/unique indexes adopt as exact `map:` entries, and `@@rls` no longer
|
|
503
|
+
needs an out-of-band appender — delete any `applyRlsEnablement`-style post-processing
|
|
504
|
+
and regenerate through the checked-in generator; re-emit moves the storage hash. The
|
|
505
|
+
duplicate-index validation keys exact-mode entries by name, so a reference database's
|
|
506
|
+
content-identical twin indexes now validate. An index whose live name is wire-shaped
|
|
507
|
+
and whose hash recomputes against the introspected content re-infers as wire-named
|
|
508
|
+
`name:` — a heuristic: a name that is not wire-shaped, or whose hash does not
|
|
509
|
+
recompute, adopts as exact `map:`.
|
|
510
|
+
detection:
|
|
511
|
+
glob: "**/*.{ts,mts,cts,prisma}"
|
|
512
|
+
contains:
|
|
513
|
+
- "inferPslContract"
|
|
514
|
+
- "contract infer"
|
|
515
|
+
- "@@rls"
|
|
516
|
+
anyMatch: true
|
|
517
|
+
- id: postgres-packages-now-ship-types-pg
|
|
518
|
+
summary: |
|
|
519
|
+
`@internal/postgres`, `@internal/extension-supabase`, and
|
|
520
|
+
`@internal/driver-postgres` re-export `pg` types from their published
|
|
521
|
+
declarations, so each now carries `@types/pg` in `dependencies` instead of
|
|
522
|
+
`devDependencies`. Extension authors previously had to add `@types/pg` to their own
|
|
523
|
+
devDependencies to compile against those declarations — that workaround is now the
|
|
524
|
+
hazard. `pg` ships no types of its own, so a second `@types/pg` copy at a different
|
|
525
|
+
version gives `pg.Client` / `pg.Pool` two identities, and handing your own client or
|
|
526
|
+
pool to a Prisma Next API stops compiling with `Argument of type 'Client' is not
|
|
527
|
+
assignable to parameter of type 'Client'` (`Type 'Client' is missing the following
|
|
528
|
+
properties from type 'Client': connection, setTypeParser, getTypeParser`). Drop
|
|
529
|
+
`@types/pg` from your extension and take it transitively, or pin it to the version
|
|
530
|
+
`@internal/postgres` depends on.
|
|
531
|
+
detection:
|
|
532
|
+
glob: "**/package.json"
|
|
533
|
+
contains:
|
|
534
|
+
- "@types/pg"
|
|
535
|
+
anyMatch: true
|
|
536
|
+
- id: build-against-published-packages-not-workspace-names
|
|
537
|
+
summary: |
|
|
538
|
+
The `@internal/*` packages are gone from the registry. Until 0.17 every
|
|
539
|
+
workspace package published, so a pack could depend on `@internal/contract`,
|
|
540
|
+
`@internal/sql-contract`, `@internal/framework-components` and the rest
|
|
541
|
+
directly — and many do. From 0.17 the published surface is 17 `@prisma/*`
|
|
542
|
+
packages and everything else carries `"private": true` in its manifest, so
|
|
543
|
+
those dependencies no longer resolve anywhere: a stale name fails at install
|
|
544
|
+
time rather than resolving to an outdated artifact left on the registry.
|
|
545
|
+
Build against the platform packages instead: `@prisma/orm-framework` for contract,
|
|
546
|
+
components, errors and the PSL tooling; `@prisma/orm-family-sql` or
|
|
547
|
+
`@prisma/orm-family-mongo` for the family surfaces; `@prisma/orm-target-<db>` for the
|
|
548
|
+
target, adapter and driver your pack extends; `@prisma/orm-toolchain` for the emitter and
|
|
549
|
+
migration tooling. Each internal package became a subpath entrypoint of exactly one of
|
|
550
|
+
those, so the module you imported still exists under a new name — the mapping is one hop
|
|
551
|
+
and the symbols are unchanged. Declare the target shell your pack extends as a peer
|
|
552
|
+
dependency rather than a dependency, so an application cannot end up with two copies of
|
|
553
|
+
the target it is registered against.
|
|
554
|
+
detection:
|
|
555
|
+
glob: "**/package.json"
|
|
556
|
+
contains:
|
|
557
|
+
- '"@internal/'
|
|
558
|
+
anyMatch: true
|
|
559
|
+
---
|
|
560
|
+
|
|
561
|
+
# 0.16 → 0.17 — Extension-author upgrade instructions
|
|
562
|
+
|
|
563
|
+
## `strip-sha256-hash-prefixes`
|
|
564
|
+
|
|
565
|
+
Starting at the 0.17 release, every content hash the framework mints or accepts is bare lowercase hex — the `sha256:` prefix is removed across the board: emitted `contract.json` / `contract.d.ts` (including `StorageHashBase<'…'>` / `ProfileHashBase<'…'>` branded type literals), migration manifests, refs, CLI output, and the marker/ledger tables. The prefix carried no information (the algorithm never varied per hash), and the hash **value** — not an in-band tag — signals a format change. The hash constructors and every loader now reject the legacy prefixed form.
|
|
566
|
+
|
|
567
|
+
Two distinct effects on your pack's checked-in artefacts:
|
|
568
|
+
|
|
569
|
+
- **Contract hashes keep their value.** `storageHash` / `profileHash` are computed over contract content, which never embedded its own hash — only the textual prefix drops.
|
|
570
|
+
- **Migration hash values change.** `migrationHash` is computed over the manifest bytes, which embed the `from` / `to` contract-hash strings; with those now bare, every recomputed `migrationHash` differs from the stored one.
|
|
571
|
+
|
|
572
|
+
### Migrate checked-in `migrations/` trees — before the layout migrator
|
|
573
|
+
|
|
574
|
+
Run the colocated codemod from your extension's repository root, **before** `scripts/migrate-migrations-layout.mjs` (the snapshot-layout entries above) — the 0.17 layout migrator accepts only bare-hex trees:
|
|
575
|
+
|
|
576
|
+
```bash
|
|
577
|
+
pnpm exec tsx ./strip-sha256-hash-prefixes.ts
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
For every on-disk migration package (a `migration.json` with a sibling `ops.json`) it strips the prefix from the manifest's `from` / `to`, from hash literals inside `ops.json`, in pre-store sibling contract snapshots (`*-contract.json`, `*.d.ts`, `migration.ts`), and in content-addressed store entries (`migrations/snapshots/<hex>/contract.json` + `contract.d.ts` — the directory name is the hash's hex and does not change), recomputes `migrationHash` over the bare-hex content, and rewrites `refs/*.json` — repointing refs that held old migration hashes at the recomputed ones, and mapping the empty-tree sentinel `sha256:empty` to `empty`. The edit is format-preserving (only hash literals and the recomputed hash value change) and idempotent: re-running over an already-bare tree makes no further changes.
|
|
581
|
+
|
|
582
|
+
Use `--check` for a dry run that lists files still needing the fix and exits non-zero if any remain:
|
|
583
|
+
|
|
584
|
+
```bash
|
|
585
|
+
pnpm exec tsx ./strip-sha256-hash-prefixes.ts --check
|
|
586
|
+
```
|
|
587
|
+
|
|
588
|
+
### Re-emit committed contract artefacts
|
|
589
|
+
|
|
590
|
+
If your pack commits emitted contract artefacts (a pack contract under `src/contract/`, test fixtures, example spaces), re-emit them the way your pack generates them (`prisma-next contract emit` or your regeneration script). The regenerated files differ only in hash representation — the hash values themselves are unchanged.
|
|
591
|
+
|
|
592
|
+
### Update hash literals your pack hard-codes
|
|
593
|
+
|
|
594
|
+
Sweep your pack's source, fixtures, and tests for `sha256:`-prefixed literals — hand-built contract fixtures, expected `migrationHash` assertions, stub hashes in unit tests. Drop the prefix everywhere; for migration hashes, take the new value from the regenerated manifest, since the value itself changed. Constructing a hash via the framework's `coreHash()` / `profileHash()` constructors with a prefixed string now throws instead of round-tripping.
|
|
595
|
+
|
|
596
|
+
### Database marker/ledger
|
|
597
|
+
|
|
598
|
+
There is no compatibility shim: a database whose marker/ledger rows still hold prefixed values reports a hash mismatch on `prisma-next db verify`. This applies to any signed database your extension maintains — acceptance harnesses, reference instances. Re-sign each against its regenerated contract:
|
|
599
|
+
|
|
600
|
+
```bash
|
|
601
|
+
prisma-next db sign
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
### Validation
|
|
605
|
+
|
|
606
|
+
After the codemod and re-emit, run `pnpm typecheck && pnpm test` in your extension repo, and exercise any flow that loads your migrations — the loader recomputes and verifies each manifest's `migrationHash` on read, so a stale or still-prefixed manifest fails immediately. `git grep -n "sha256:"` over your repository should return no hits in committed artefacts.
|
|
607
|
+
|
|
608
|
+
## `adopt-sql-json-projection-ast-foundations`
|
|
609
|
+
|
|
610
|
+
Relational JSON container AST construction now requires an explicit value-projection variant. Import `NativeJsonValueProjection` from `@internal/sql-relational-core/ast` and wrap every expression that 0.16 code passed directly to `JsonObjectExpr.entry(key, expression)` or `JsonArrayAggExpr.of(expression, ...)`: use `JsonObjectExpr.entry(key, new NativeJsonValueProjection(expression))` and `JsonArrayAggExpr.of(new NativeJsonValueProjection(expression), ...)`. `NativeJsonValueProjection` preserves the pre-0.17 target-native JSON conversion. Use `CodecJsonValueProjection` only when the extension deliberately supplies a `CodecRef` for codec-owned JSON conversion, and use `JsonDocumentProjection` only when the wrapped expression already produces a JSON document.
|
|
611
|
+
|
|
612
|
+
`ExprVisitor<R>` and the `AnyExpression` union now include `FunctionCallExpr` (`kind: 'function-call'`), `CastExpr` (`kind: 'cast'`), and `CaseExpr` (`kind: 'case'`). Add `functionCall`, `cast`, and `case` methods to every visitor object, and add all three discriminants to exhaustive `expr.kind` switches. Binding or rewriting visitors should route these nodes through their normal recursive expression path; restricted visitors such as grouped `HAVING` validators should reject them explicitly when the context does not support them.
|
|
613
|
+
|
|
614
|
+
`FunctionSource.of(fn, args, alias)` now groups alias state so returned-column aliases cannot exist without a table alias. Replace a string third argument such as `FunctionSource.of(fn, args, 'rows')` with `FunctionSource.of(fn, args, { alias: 'rows' })`; when returned-column names are required, pass `{ alias: 'rows', columnAliases: ['value', 'ordinality'] }`. Calls that omit the alias remain unchanged.
|
|
615
|
+
|
|
616
|
+
When an extension forwards an existing `ProjectionItem` through a derived-table or row-number wrapper, preserve its known codec in the reconstructed projection: use `ProjectionItem.of(item.alias, ColumnRef.of(wrapperAlias, item.alias), item.codec)`. Leave the codec undefined only for computed or otherwise unknown projected results. After applying the applicable edits, run the extension's typecheck and tests; update AST-shape fixtures to assert the explicit wrapper nodes and preserved codec metadata.
|
|
617
|
+
## `rls-wire-name-helpers-moved-to-sql-schema-ir-naming`
|
|
618
|
+
|
|
619
|
+
The wire-name mechanics are family-shared from 0.17 (they now serve secondary indexes as well as RLS policies), so the helpers moved from the target-postgres RLS module to `@internal/sql-schema-ir/naming` under generalized names. Apply the mechanical rename:
|
|
620
|
+
|
|
621
|
+
| 0.16 (`@internal/target-postgres/rls-canonicalize`) | 0.17 (`@internal/sql-schema-ir/naming`) |
|
|
622
|
+
| --- | --- |
|
|
623
|
+
| `formatRlsPolicyWireName(prefix, hash)` | `formatWireName(prefix, hash)` |
|
|
624
|
+
| `parseRlsPolicyWireName(name)` | `parseWireName(name)` |
|
|
625
|
+
| `normalizePredicate(sql)` | `normalizeSqlBody(sql)` |
|
|
626
|
+
| `RlsPolicyWireName` (type) | `WireName` (type) |
|
|
627
|
+
|
|
628
|
+
Behavior is byte-identical — same `<prefix>_<8hex>` format and parse pattern, same treat-as-all-prefix contract for names that do not parse, same minimal trim-and-collapse normalizer (still a stability commitment: any change would re-suffix every wire name). `@internal/target-postgres/rls-canonicalize` keeps the RLS-specific exports (`computeContentHash`, `ContentHashParts`, `POLICY_OPERATION_PREDICATES`, `RlsPolicyOperation`); there are no re-export shims for the moved names. The naming module additionally exposes `computeIndexContentHash`, `WIRE_NAME_PREFIX_MAX_LENGTH` (54), and `assertWireNamePrefixLength` — the index-side siblings of the RLS hash assembly.
|
|
629
|
+
|
|
630
|
+
## `sql-index-entities-are-name-identified`
|
|
631
|
+
|
|
632
|
+
Indexes are name-identified end to end. Two SPI layers change shape; take them in order.
|
|
633
|
+
|
|
634
|
+
### Contract IR: `Index` / `IndexSchema`
|
|
635
|
+
|
|
636
|
+
An index entity (`Index` from `@internal/sql-contract/types`; the `indexes: []` array in a `StorageTable`) now requires:
|
|
637
|
+
|
|
638
|
+
- `name: string` — the full physical name, always present.
|
|
639
|
+
- `unique: boolean` — always present.
|
|
640
|
+
- `prefix?: string` — present iff the name is wire-named; the constructor enforces that `name` parses back to `prefix` + an 8-hex suffix.
|
|
641
|
+
- `columns?` xor `expression?` — exactly one must be set; `where?` carries a partial-index predicate. All body strings are opaque SQL, never parsed or escaped.
|
|
642
|
+
|
|
643
|
+
Both the class constructor and the arktype `IndexSchema` reject the 0.16 shape. Contract-space fixtures or pack code that load `indexes: [{ columns: ['email'] }]` through validation fail with a `Contract structural validation failed: storage.namespaces.<ns> …` error whose message contains `indexes[0].name must be a string (was missing)` and `indexes[0].unique must be boolean (was missing)`; constructing the entity directly throws `Index: every index carries a full physical name…`. Add the real physical name and `unique: false`. The `index(...)` convenience factory from `@internal/sql-contract/factories` changed signature accordingly: `index(name, columns, opts?)` (opts: `prefix`, `unique`, `type`, `options`). Packs that lower authored index inputs themselves can reuse `lowerAuthoredIndex` from `@internal/sql-contract/index-naming` — it implements the wire/exact naming rules (default prefix, `name:`-as-prefix, `map:`-as-exact) including the 54-character prefix cap.
|
|
644
|
+
|
|
645
|
+
### Schema IR: `SqlIndexIR`
|
|
646
|
+
|
|
647
|
+
`SqlIndexIRInput` requires `name` and adds explicit `prefix` / `expression` / `where` keys (the package's every-field-required convention: state absence with `undefined`, never by omission), and `columns` became `readonly string[] | undefined` (xor `expression`). The node's diff-tree `id` is now `index:<name>` — the old tuple-derived `index:<col,col>` ids are gone, so any test asserting child ids or diff paths must use the physical name. `isEqualTo` is mode-selected by the receiver: both modes compare `unique` strict, `type` strict, `options` loosely (`String()`-coerced), and `columns` ordered-strict when both sides carry them; an exact-named receiver (`prefix === undefined`) additionally byte-compares `expression ?? ''` and `where ?? ''`; a wire-named receiver never compares bodies. Introspection now captures expression and partial indexes at full fidelity and preserves same-tuple twin indexes — packs must not assume one index per column tuple.
|
|
648
|
+
|
|
649
|
+
### Committed contract spaces
|
|
650
|
+
|
|
651
|
+
Re-emit your pack's contract space with the upgraded toolchain (`build:contract-space`, or your generator script à la `contract:generate`): every contract that declares indexes gets the new entry shape and a new storage hash, and wire-named index physical names gain the `_<8hex>` content-hash suffix. Databases your pack maintains (acceptance harnesses, reference instances) converge via a renames-only widening plan — see the user-skill `indexes-are-name-identified` entry for that flow. Expression and partial indexes are authorable from 0.17 (PSL `@@index(expression:/where:/unique:/type:/name: xor map:)`, TS `constraints.index` with the same matrix); declare them with `name:` for wire names, or `map:` for infer-captured exact names — hand-authoring a body under `map:` warns (`PN_EXACT_NAME_BODY_COMPARISON`) because drift detection byte-compares the authored text against Postgres's reprint. Live indexes you choose not to declare stay tolerated under an `external` control policy. The rules behind all of this — why an index is identified by its name, when the two naming modes apply, and what re-inference does to each — are decided in ADR 243, "Name-identified indexes and exact-name adoption".
|
|
652
|
+
|
|
653
|
+
## `rls-policy-migration-literal-carries-the-naming-union`
|
|
654
|
+
|
|
655
|
+
`PostgresRlsPolicyMigrationInput` is gone. The parameter `Migration#createRlsPolicy` accepts, and the shape `CreatePostgresRlsPolicyCall.renderTypeScript` writes into a generated migration, is now `RenderedRlsPolicyLiteral` — `PostgresRlsPolicyInput` with absent-valued keys omittable, which is how a machine-rendered literal spells absence. The practical difference is the name:
|
|
656
|
+
|
|
657
|
+
| 0.16 | 0.17 |
|
|
658
|
+
| --- | --- |
|
|
659
|
+
| `name: "post_owner_a1b2c3d4", prefix: "post_owner"` | `naming: { kind: "wire", prefix: "post_owner", hash: "a1b2c3d4" }` |
|
|
660
|
+
| `name: "Tenant members can read"` | `naming: { kind: "exact", name: "Tenant members can read" }` |
|
|
661
|
+
|
|
662
|
+
The two flat fields could disagree; the union cannot be written wrong, which is why the migration authoring surface carries it.
|
|
663
|
+
|
|
664
|
+
The stored `contract.json` shape does not change — it stays flat and now has its own type: `SerializedRlsPolicy`, hydrated by `policyInputFromSerialized` (0.16's `rlsPolicyInputFromFlat`, renamed for the boundary it serves). Both are exported from `@internal/target-postgres/types`.
|
|
665
|
+
|
|
666
|
+
Pack code that constructs `PostgresRlsPolicy` directly already passes `naming` and needs no edit. Pack code that builds the migration literal, or that names `PostgresRlsPolicyMigrationInput` in a signature, switches to `RenderedRlsPolicyLiteral`. Regenerate any migration your pack ships that calls `createRlsPolicy`.
|
|
667
|
+
|
|
668
|
+
## `postgres-extension-codecs-require-target-descriptors`
|
|
669
|
+
|
|
670
|
+
For every codec descriptor contributed by a PostgreSQL extension, add `@internal/target-postgres` at the same 0.17 version as the extension's other `@internal/*` packages under `dependencies`. Do not leave it only in `devDependencies`: production descriptor modules and runtime/control stack metadata import and expose this protocol. Import the target API from the lean `@internal/target-postgres/codec-descriptor` subpath, and import `ProjectionExpr` from `@internal/sql-relational-core/ast`.
|
|
671
|
+
|
|
672
|
+
Change a PostgreSQL-bound descriptor that extends `CodecDescriptorImpl<P>` to extend `PostgresCodecDescriptor<P>`. Keep its codec id, traits, target types, `paramsSchema`, factory, output renderer and column helpers unchanged; there is no longer a `meta` / `metaFor` channel to carry alongside, and the descriptor's `nativeTypeFor()` is the only place a native type is declared. Add `protected override nativeType(params: P): string` returning the same trusted PostgreSQL native type spelling the extension already uses, and add `protected override jsonProjection(expression: ProjectionExpr, params: P): ProjectionExpr`.
|
|
673
|
+
|
|
674
|
+
`return expression` is a claim, not a placeholder: the production JSON renderers call `projectJson()` for every column-valued entry they build, so an identity projection asserts that your codec's stored form already *is* its canonical JSON. Write one only where that holds, and where it does not, see `codec-json-projections-must-agree-with-encode-json` below.
|
|
675
|
+
|
|
676
|
+
When the extension contributes a reusable target-neutral SQL descriptor instead of owning its descriptor class, keep the generic descriptor unchanged and wrap it with `postgresCodec(genericDescriptor, { nativeType, jsonProjection })`. Supply the native type and the canonical JSON projection as above. The wrapper delegates the generic descriptor's codec id, literals, parameter schema, factory, renderers and target types, and adds the PostgreSQL discriminant and target methods.
|
|
677
|
+
|
|
678
|
+
Replace broad exported descriptor arrays such as `readonly AnyCodecDescriptor[]` with `definePostgresCodecs([...])`. Use the resulting canonical target-typed set in both runtime and control `types.codecTypes.codecDescriptors`, and return that same set from runtime `codecs()` when the runtime extension SPI requires it. Do not construct independently maintained generic and PostgreSQL descriptor collections. Update exact-type tests that expected `readonly AnyCodecDescriptor[]` to accept `readonly AnyPostgresCodecDescriptor[]`; ordinary descriptors still satisfy `AnyCodecDescriptor` individually.
|
|
679
|
+
|
|
680
|
+
Review every `CodecRef` construction for a parameterized descriptor, including parameter refs, contract/storage fixtures, and test-created refs. Supply `typeParams` with every field required by the target descriptor `paramsSchema`; for example, a `pg/vector@1` ref for a three-element vector must include `typeParams: { length: 3 }`. Do not make a required descriptor parameter optional merely to preserve an invalid unparameterized ref.
|
|
681
|
+
|
|
682
|
+
When a parameterized descriptor intentionally supports an unparameterized column or contract reference, make its parameter type and Standard Schema accept the empty validated parameter object used during representative materialization. Express only genuinely absent fields as optional and preserve the existing unparameterized factory behavior; do not add a hidden default or change the codec encoded representation.
|
|
683
|
+
|
|
684
|
+
After the migration, run the extension package's typecheck, lint, and tests. Verify its public codec ids, factories, column helpers, rendered types, SQL/wire behavior, `encodeJson` / `decodeJson`, runtime/control descriptor membership, and emitted contract behavior are unchanged apart from the descriptor types becoming PostgreSQL-specific.
|
|
685
|
+
|
|
686
|
+
## `postgres-packages-now-ship-types-pg`
|
|
687
|
+
|
|
688
|
+
`@internal/postgres`, `@internal/extension-supabase`, and `@internal/driver-postgres` re-export `pg` types from their published `.d.mts` files, so each declares `@types/pg` under `dependencies` from 0.17. Compiling against those declarations no longer requires your extension to supply `@types/pg` itself.
|
|
689
|
+
|
|
690
|
+
If your extension's `package.json` declares `@types/pg`, act on it. `pg` carries no types of its own, so two `@types/pg` copies in the tree give `pg.Client` and `pg.Pool` two distinct identities. Any call that hands your own client or pool to a Prisma Next API — `new PostgresControlDriver(client)`, a driver `connect: { pool }` — then fails:
|
|
691
|
+
|
|
692
|
+
```text
|
|
693
|
+
Argument of type 'Client' is not assignable to parameter of type 'Client'.
|
|
694
|
+
Type 'Client' is missing the following properties from type 'Client': connection, setTypeParser, getTypeParser
|
|
695
|
+
```
|
|
696
|
+
|
|
697
|
+
The error names the same type on both sides; the two paths under `node_modules/.pnpm/@types+pg@<version>/` in the full message are what identify it.
|
|
698
|
+
|
|
699
|
+
Prefer dropping `@types/pg` from your extension's `devDependencies` and taking it transitively, so its version tracks Prisma Next's. If you keep the entry — because your own code imports `pg` directly and you want the dependency explicit — pin it to the version `@internal/postgres` depends on rather than a range that can resolve elsewhere.
|
|
700
|
+
|
|
701
|
+
## Incidental lint-config bumps
|
|
702
|
+
|
|
703
|
+
Biome `$schema` version alignment in `packages/3-extensions/` (dependabot `dev-deps` group, PR #1058) requires no Prisma Next-specific upgrade action by extension authors.
|
|
704
|
+
|
|
705
|
+
## `codec-json-projections-must-agree-with-encode-json`
|
|
706
|
+
|
|
707
|
+
Slice-2 shipped `jsonProjection` as a typed hook that every descriptor implemented as `return expression`. Those hooks now carry real SQL, and a descriptor's two sides are held to agreeing with each other.
|
|
708
|
+
|
|
709
|
+
The ordering is the part worth internalising, because it is the same in all three shapes it has taken:
|
|
710
|
+
|
|
711
|
+
- a numeric cast to `text` sits inside the projected expression, so it applies before the JSON constructor can render the value as a JSON number;
|
|
712
|
+
- a base64 encoding *replaces* the target's own conversion rather than post-processing it, because the target would otherwise have already emitted its hex form;
|
|
713
|
+
- a widening of a narrow float to a wider one happens before any text rendering, because the printing is what discards precision.
|
|
714
|
+
|
|
715
|
+
In each case a transformation applied to the constructor's output would be too late. If you are authoring a projection, ask what the target does to the value if you do nothing, and whether that is recoverable.
|
|
716
|
+
|
|
717
|
+
Two properties are worth testing against a real database rather than reasoned about, because both turned out to be contingent: whether your form survives a value at the edge of its representation, and whether it depends on a session setting your consumers may not share.
|
|
718
|
+
|
|
719
|
+
## `pgvector-json-form-is-a-numeric-array`
|
|
720
|
+
|
|
721
|
+
The route matters as much as the destination here. Casting a vector's text form to `json` produces an array of numbers and looks correct — but the text prints the shortest decimal that round-trips as a `real`, so reading it at double width yields a different number than the application holds. Widening each element to `float8` before building the array keeps the exact value the `real` denotes.
|
|
722
|
+
|
|
723
|
+
## `default-literal-value-resolves-through-the-codec-json-channel`
|
|
724
|
+
|
|
725
|
+
Before this change the emitted type said a literal default had the codec's *application* type. That was true only while the two coincided. For a codec whose application value is a `bigint` and whose canonical JSON is a decimal string, it described a `bigint` sitting in a file that holds `"0"` — which surfaced as an assignability failure rather than as a wrong-but-quiet type.
|
|
726
|
+
|
|
727
|
+
Regenerating is sufficient; no hand edits to a `contract.d.ts` are needed.
|
|
728
|
+
|
|
729
|
+
## Incidental release version bump to 0.17.0
|
|
730
|
+
|
|
731
|
+
The `chore(release): bump to 0.17.0` commit rewrites every workspace manifest's `version` field and `workspace:` pins, which touches `packages/3-extensions/` manifests. No extension-author action beyond the entries above.
|