@aventara/prisma7-adapter 1.0.0-rc.1 → 1.0.0-rc.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/CHANGELOG.md +418 -0
  2. package/README.md +101 -24
  3. package/dist/discovery/artifact.loader.d.ts +8 -3
  4. package/dist/discovery/artifact.loader.js +6 -1
  5. package/dist/discovery/capability.deriver.d.ts +7 -7
  6. package/dist/discovery/capability.deriver.js +51 -8
  7. package/dist/discovery/client-shape.verifier.d.ts +0 -5
  8. package/dist/discovery/client-shape.verifier.js +1 -1
  9. package/dist/discovery/discovery-artifact.interface.d.ts +16 -4
  10. package/dist/discovery/discovery-artifact.interface.js +1 -1
  11. package/dist/discovery/enum.mapper.d.ts +4 -3
  12. package/dist/discovery/field.mapper.d.ts +8 -10
  13. package/dist/discovery/identifier.mapper.d.ts +3 -2
  14. package/dist/discovery/installed-client.locator.d.ts +14 -0
  15. package/dist/discovery/installed-client.locator.js +43 -0
  16. package/dist/discovery/model.discoverer.d.ts +6 -2
  17. package/dist/discovery/model.discoverer.js +22 -2
  18. package/dist/discovery/operations.deriver.d.ts +1 -1
  19. package/dist/discovery/scalar.mapper.d.ts +3 -2
  20. package/dist/discovery/schema-facts.interface.d.ts +10 -0
  21. package/dist/discovery/schema.reader.d.ts +2 -1
  22. package/dist/discovery/schema.reader.js +37 -5
  23. package/dist/discovery/vocabulary.dictionary.d.ts +6 -5
  24. package/dist/errors/back-reference.locator.d.ts +25 -0
  25. package/dist/errors/back-reference.locator.js +100 -0
  26. package/dist/errors/bigint-binding.locator.d.ts +7 -0
  27. package/dist/errors/bigint-binding.locator.js +27 -0
  28. package/dist/errors/error.normalizer.d.ts +42 -5
  29. package/dist/errors/error.normalizer.js +77 -2
  30. package/dist/errors/held-link.locator.d.ts +7 -0
  31. package/dist/errors/held-link.locator.js +66 -0
  32. package/dist/errors/prisma-error.reader.d.ts +4 -0
  33. package/dist/errors/prisma-error.reader.js +2 -0
  34. package/dist/execution/first-variant.emulator.d.ts +2 -1
  35. package/dist/execution/operation.executor.d.ts +9 -2
  36. package/dist/execution/operation.executor.js +40 -11
  37. package/dist/execution/result.shaper.d.ts +0 -6
  38. package/dist/execution/result.shaper.js +0 -5
  39. package/dist/execution/scoped-cursor.resolver.d.ts +11 -0
  40. package/dist/execution/scoped-cursor.resolver.js +47 -0
  41. package/dist/execution/transaction.executor.d.ts +7 -2
  42. package/dist/execution/transaction.executor.js +2 -0
  43. package/dist/generate/artifact.emitter.d.ts +12 -1
  44. package/dist/generate/artifact.emitter.js +56 -2
  45. package/dist/generate/computed-fields.import.d.ts +5 -0
  46. package/dist/generate/computed-fields.import.js +52 -0
  47. package/dist/generate/declared-support.reader.d.ts +3 -2
  48. package/dist/generate/discovery.cli.d.ts +3 -1
  49. package/dist/generate/discovery.cli.js +16 -4
  50. package/dist/generate/existence.gate.d.ts +2 -1
  51. package/dist/generate/index.d.ts +6 -0
  52. package/dist/generate/index.js +2 -0
  53. package/dist/generate/prisma-cli.resolver.d.ts +2 -1
  54. package/dist/generate/prisma.generate.d.ts +9 -0
  55. package/dist/generate/prisma.generate.js +91 -7
  56. package/dist/generate/reader-crosscheck.d.ts +5 -4
  57. package/dist/index.d.ts +1 -0
  58. package/dist/index.js +1 -0
  59. package/dist/prisma-adapter.description.d.ts +42 -0
  60. package/dist/prisma-adapter.description.js +36 -0
  61. package/dist/prisma-client.interface.d.ts +2 -1
  62. package/dist/prisma.adapter.d.ts +6 -5
  63. package/dist/prisma.adapter.js +43 -28
  64. package/dist/provider/provider-profile.d.ts +21 -4
  65. package/dist/provider/provider-profile.js +21 -0
  66. package/dist/translation/identifier.addressing.d.ts +5 -4
  67. package/dist/translation/json-null.sentinel.d.ts +7 -0
  68. package/dist/translation/json-null.sentinel.js +17 -0
  69. package/dist/translation/mutation.translator.d.ts +4 -3
  70. package/dist/translation/mutation.translator.js +23 -4
  71. package/dist/translation/operation.translator.d.ts +15 -3
  72. package/dist/translation/operation.translator.js +54 -8
  73. package/dist/translation/order-pagination.translator.d.ts +23 -3
  74. package/dist/translation/order-pagination.translator.js +15 -0
  75. package/dist/translation/scalar.conversion.d.ts +0 -2
  76. package/dist/translation/where.translator.d.ts +3 -2
  77. package/dist/translation/where.translator.js +160 -18
  78. package/package.json +16 -16
package/CHANGELOG.md CHANGED
@@ -1,5 +1,423 @@
1
1
  # @aventara/prisma7-adapter
2
2
 
3
+ ## 1.0.0-rc.10
4
+
5
+ ### Patch Changes
6
+
7
+ - 04bb39a: `engines.node` is now `^22.23.4 || >=24.22.1`, the Node security releases of 2026-10-20 (CVE-2026-105481,
8
+ CVE-2026-105482, CVE-2026-105483, CVE-2026-106069, CVE-2026-106072, CVE-2026-106073, CVE-2026-106074,
9
+ CVE-2026-111497). The bins refuse an older Node in one sentence naming that range.
10
+ - 827ccb6: A listed update (`afterChecks`) no longer refuses an unchanged row on PostgreSQL. The compare-and-swap that holds the
11
+ write to the rows as they were read compares each field by `equals`, and the adapter's `equals` now matches every row
12
+ that reads as the value:
13
+
14
+ - a scalar list a create left out, which Prisma stores as `NULL` and reads as `[]`: an operator object that holds for
15
+ `[]` (`equals: []`, `isEmpty: true`, `hasEvery: []`) holds for that row too, in every filter;
16
+ - a timestamp finer than a millisecond (a `@db.Timestamptz(6)` the database writes), which Prisma reads truncated:
17
+ equality with an instant also holds the instants inside its millisecond.
18
+
19
+ On a `Bytes[]` column, `equals`, `hasEvery` and `hasSome` are no longer offered: Prisma 7.10.1 binds their operand's
20
+ members as base64 text, so they matched other rows than they named. `has` and `isEmpty` remain. Such a column is not
21
+ part of the compare-and-swap.
22
+
23
+ The compare-and-swap takes its fields from what the adapter compares, so an exemption that hides `equals` from callers
24
+ no longer takes a field out of it.
25
+ - 4f0fd29: The Prisma 7 adapter's peer floor is now `^7.10.1` (`prisma`, `@prisma/client`, `@prisma/adapter-pg`,
26
+ `@prisma/adapter-better-sqlite3`). `prisma` 7.10.0 pins `mysql2` 3.15.3 (GHSA-3f6p-5ww8-9rcr, GHSA-rgwj-5xj2-c3m3)
27
+ and, through `@prisma/config`, `deepmerge-ts` 7.1.5 (GHSA-ggr8-5vv4-36mx); 7.10.1 pins `mysql2` 3.24.4 and
28
+ `deepmerge-ts` 8.0.2. `aventara new` and `aventara init` install Prisma at the floor, so new projects get 7.10.1, and
29
+ `aventara init` refuses a project whose Prisma is below it.
30
+ - f52c499: The generate step reads multiSchema's `@@schema("auth")`: a model states its PostgreSQL schema in the discovery
31
+ artifact (`schema`), and the Core Contract carries it. Until now `@@schema` stopped the build. On an enum it is read and
32
+ dropped. A model whose table another service owns is marked `managedElsewhere: true` in the Aventara configuration and
33
+ listed in `prisma.config.ts` as an external table (`experimental.externalTables`, `tables.external`), so neither
34
+ Aventara writes it nor `prisma migrate` changes it.
35
+ - 10341d5: Policy checks, tightened:
36
+
37
+ - Writing a reference field itself (`authorId: "u2"`) is held to the target's read scope, as `$connect` is: the row it
38
+ names must be one the caller may read, or the write is refused (`A4002`). Creates, updates, both branches of an
39
+ upsert and the records of nested writes are all checked. The reference is handed to the adapter as a `$connect` that
40
+ carries the read scope, so the write itself refuses a row outside it, with no extra query; a row that is not there is
41
+ refused the same way. Where Prisma's input takes no relation (`createMany`, `updateMany`, a to-many nested
42
+ `$update`), and where a create writes a reference `null` (left out, the column's default would fill it), one count
43
+ per target Resource asks before the write whether every row named is there and readable. Nothing is asked where that
44
+ Resource is read by everyone, and a `null` reference is not asked about. A record written this way writes its other
45
+ references as links too, so a missing row there answers `A2003` rather than `A2008`.
46
+ - A row a write names to link that is not there is refused (`A4002`) like a row the caller cannot read, wherever the
47
+ target has a scope: a reference field, and a `$connect`, `$set` or `$disconnect` selector. Before, a missing row
48
+ answered the store's `A2008` or `A2003`, which told a caller which rows it cannot read exist. Without a scope, the
49
+ codes are unchanged.
50
+ - An update the engine lists in `afterChecks` now holds a to-one nested `$update` to its row as it was read. A row a
51
+ concurrent write changed in between refuses the write (`A4002`) and rolls it back, with no extra query.
52
+ - A listed `update.many` or `update.count` that changes fewer rows than it read (a concurrent write changed one in
53
+ between) is refused (`A4002`) and rolled back, rather than answering a partial success.
54
+ - The client and agent Contracts leave out an enum that only a Resource managed elsewhere uses. The ClientContract hash
55
+ of an app with such an enum changes.
56
+ - Seven public types write their members out in an editor's hover instead of naming a type no entry exports (`ctx.$sql`,
57
+ a compute stage's context, a pipe's return, `defineResource`'s overlays, a family's variants, the `access` and
58
+ `policy` check, `AvConfigComputedFields.agentExtends`).
59
+
60
+ - 88263a1: On PostgreSQL, a scalar list Prisma stored as `NULL` (a create left it out; it reads as `[]`) now answers every list
61
+ filter as `[]` does, negated ones included: `NOT { tags: { has: "a" } }` (and `hasSome`, `hasEvery`, `isEmpty: false`,
62
+ `equals: [x]`) holds for that row. Inside a relation's `every`, a related row whose list was never written fails
63
+ `every: { tags: { has: "a" } }` as an empty list does, so its parent is no longer kept.
64
+ - Updated dependencies [587dd01]
65
+ - Updated dependencies [d7e7369]
66
+ - Updated dependencies [7ee547b]
67
+ - Updated dependencies [f52c499]
68
+ - Updated dependencies [2907484]
69
+ - Updated dependencies [a6bbdf0]
70
+ - Updated dependencies [3e26549]
71
+ - Updated dependencies [a6bbdf0]
72
+ - Updated dependencies [6f3f6f6]
73
+ - Updated dependencies [04bb39a]
74
+ - Updated dependencies [3fb3333]
75
+ - Updated dependencies [827ccb6]
76
+ - Updated dependencies [7f5abc3]
77
+ - Updated dependencies [88263a1]
78
+ - Updated dependencies [10341d5]
79
+ - Updated dependencies [8129844]
80
+ - Updated dependencies [88263a1]
81
+ - Updated dependencies [3020b5c]
82
+ - Updated dependencies [88263a1]
83
+ - Updated dependencies [88263a1]
84
+ - @aventara/core@1.0.0-rc.10
85
+
86
+ ## 1.0.0-rc.9
87
+
88
+ ### Patch Changes
89
+
90
+ - Updated dependencies [205a379]
91
+ - Updated dependencies [a0bb05e]
92
+ - Updated dependencies [86ab319]
93
+ - Updated dependencies [fdf52e6]
94
+ - @aventara/core@1.0.0-rc.9
95
+
96
+ ## 1.0.0-rc.8
97
+
98
+ 1.0.0-rc.5, rc.6 and rc.7 were tagged but never published; 1.0.0-rc.8 contains everything listed under them and the changes below.
99
+
100
+ ### Patch Changes
101
+
102
+ - 1c8e4ee: The discovery artifact's referential actions say `referenceFields` where they said `references`: in
103
+ `referentialActions.<Resource>.owningEdges[]`, the fields of the Resource itself that hold the reference
104
+ (`@relation(fields: [...])`). The model's relation fields already use `references` for the target's fields
105
+ (`@relation(references: [...])`) and `referenceFields` for these, so the same word meant two different lists in one
106
+ file. The generated `discovery.artifact.ts` changes on the next `aventara:prepare` (it runs on install, build and
107
+ start), and only in those keys: `modelHash` is unchanged, since the referential actions are outside it, and so is the
108
+ prebuilt Contracts file `aventara-build` writes. Code that read `owningEdges[i].references` reads
109
+ `owningEdges[i].referenceFields`.
110
+ - Updated dependencies [1c8e4ee]
111
+ - @aventara/core@1.0.0-rc.8
112
+
113
+ ## 1.0.0-rc.7
114
+
115
+ 1.0.0-rc.5 and 1.0.0-rc.6 were tagged but never published; 1.0.0-rc.7 contains everything listed under them and the changes below.
116
+
117
+ ### Patch Changes
118
+
119
+ - Updated dependencies [f917c1c]
120
+ - @aventara/core@1.0.0-rc.7
121
+
122
+ ## 1.0.0-rc.6
123
+
124
+ 1.0.0-rc.5 was tagged but never published. 1.0.0-rc.6 contains everything listed under 1.0.0-rc.5 and the fix below.
125
+
126
+ ### Patch Changes
127
+
128
+ - Updated dependencies [1cf72e0]
129
+ - @aventara/core@1.0.0-rc.6
130
+
131
+ ## 1.0.0-rc.5
132
+
133
+ ### Patch Changes
134
+
135
+ - 4795ff1: Two additions for policy engines. A Framework without a policy, and every Contract a caller is served, are unchanged.
136
+
137
+ - A policy engine can check a create whose row reaches another Resource through a relation. Discovery now states, on the end of a relation that holds the reference, which of the target's fields its reference fields name, pair by pair (`Note.campaign`: `referenceFields: ["campaignId"]`, `references: ["id"]`). An engine reads them from the model it is built from (a Prisma discovery artifact's `model`) or from `framework.contracts.core`, and asks one `exists` about the row they name: "a player creates a note only in a campaign they play in". Only the adapter's model and the Core Contract carry them. The Application, Client and Agent Contracts, `/_contract`, the MCP tools and every ClientContract hash are unchanged. The discovery artifact's model hash, and so a prebuilt Contracts file's fingerprint, change: regenerate the artifact and rebuild the prebuilt file.
138
+ - `fieldsOf({ access: "write" })` also names the action that writes the record, `action: "create" | "update"` (an upsert's branches each their own, a nested record its directive's), so an engine can lock a field on update and still let a create write it. A read question names none. An engine that ignores it keeps working.
139
+
140
+ - 9e178ca: Fixes for applications that check requests with a policy engine. A Framework without a policy behaves as before.
141
+
142
+ - A cursor on a row the caller cannot read is answered exactly as a cursor on a row that does not exist, at the root and in a to-many relation, whatever values the caller sends beside the identifier. Before, the page started at the hidden row, so it told that the row exists and where its values sort. The Prisma adapter reads the cursor's row under the read scope first: one statement more for a cursor on a readable row, and only that read for one on a row the caller cannot read.
143
+ - A unique update with a nested write (`$create`, `$connect`, …) on a row the caller can read but not change answers `A4002`, as the same update without one does. It answered `A2003`. A row the caller cannot read still answers `A2003`.
144
+ - The `exists` questions a policy asks select the Resource's primary identifier, never another unique field such as a governed `email`.
145
+ - `policy.principal` may answer with a promise. A synchronous principal works as before; a rejection answers `A3000`, as a throw does.
146
+ - `AvConstructionError.message` names the first problem and how many more there are, for example `Aventara framework configuration validation failed: CONFIG_INVALID_TYPE at adapter.execute: adapter.execute must be a function (+2 more)`. `stage` and `diagnostics` are unchanged.
147
+
148
+ ## 1.0.0-rc.4
149
+
150
+ ### Patch Changes
151
+
152
+ - 7c3b65f: Build-time Contracts for serverless and edge cold starts.
153
+
154
+ - New package `@aventara/build`, bin `aventara-build`, a development dependency. It runs `src/aventara.config.ts` and
155
+ `src/aventara.adapter.ts` without a database client, compiles the Contracts with the project's `@aventara/core` and
156
+ writes `src/generated/aventara/contracts.generated.ts` (`aventaraContracts`), which a serverless or edge entry passes
157
+ to `createFramework` as `prebuilt`. A configuration that startup would refuse fails the build with the same
158
+ `CONFIG_…`/`COMPILER_…` diagnostics. `aventara-build --check` writes nothing and exits 1 when the file is missing or
159
+ stale, naming the Resources that changed.
160
+ - `@aventara/prisma7-adapter`: `describePrismaAdapter({ discovery, provider, driver })` states the adapter's passive
161
+ facts (the model, the driver's transaction capability, the referential actions, the computed fields) with no client.
162
+ `createPrismaAdapter({ ...description, client })` builds the adapter from the same facts, and still checks the client
163
+ against the discovery artifact.
164
+ - `@aventara/cli`: the scaffold's `src/aventara.config.ts` exports the configuration as a plain value
165
+ (`export const aventaraConfig = { … } as const`) with no `adapter`. A new `src/aventara.adapter.ts` default-exports
166
+ `describePrismaAdapter(…)`, and `app.module.ts` joins the two:
167
+ `config: { ...aventaraConfig, adapter: await createPrismaAdapter({ ...adapter, client: prisma }) }`. The Nest server
168
+ still compiles its Contracts at startup and passes no `prebuilt`. `aventara:prepare` ends with `&& aventara-build`,
169
+ and `@aventara/build` is an exact development dependency.
170
+
171
+ - 2b1b17e: `aventara-build`'s files no longer land inside a Prisma client generated into `src/generated`.
172
+
173
+ When `aventara init` reuses a project whose Prisma client is generated into `src/generated`, it already puts the
174
+ discovery artifact in `src/aventara/`, because `prisma generate` deletes every file in its output directory that it did
175
+ not write. `aventara-build` still wrote its three files to `src/generated/aventara/`, so each `prisma generate` deleted
176
+ them and the project stopped compiling until the next `aventara:prepare`. Now all of Aventara's generated files are
177
+ in one place.
178
+
179
+ - `@aventara/build`: `aventara-build` writes `resources.generated.ts`, `computed-fields.generated.ts` and
180
+ `contracts.generated.ts` to the directory the configuration imports `aventaraResources` from, so the tree is always
181
+ written where the configuration reads it. A configuration that imports no tree keeps `src/generated/aventara/`.
182
+ The files of a project whose client is generated anywhere else are the same bytes, in the same place.
183
+ - `@aventara/prisma7-adapter`: with `--config`, the artifact imports the computed fields from its sibling,
184
+ `./computed-fields.generated`, wherever `--out` puts it. `--config` is still required for that import and the step
185
+ still checks that the file exists, but the step no longer uses its location. A scaffold's artifact is unchanged.
186
+ - `@aventara/cli`: in that project, `src/aventara.config.ts` imports the tree from `./aventara/resources.generated`,
187
+ and `.gitignore` gets the one `/src/aventara/` line that covers all four files (no separate
188
+ `/src/generated/aventara/contracts.generated.ts` line). The agent skill says where the generated files are in
189
+ both cases.
190
+
191
+ - 3a0dfca: A write the policy checks costs fewer database round trips. What each check decides and refuses is unchanged.
192
+
193
+ - A single-row update or delete carries the caller's scopes inside its own `where` and runs as one statement, with no
194
+ read of its row before it. One that matches nothing still answers `A4002` when the caller can read the row and
195
+ `A2003` when it cannot, with one lookup on that miss only. The Prisma adapter sends it as
196
+ `update({ where: { id, AND: [scope] } })`.
197
+ - A create asks `can({ action: "create", row })` and its `exists` lookups before the insert, without a transaction. A
198
+ transaction around them never closed the race between the lookup and the insert at the database's default
199
+ isolation, and cost a BEGIN and a COMMIT.
200
+ - A transaction opens only when a check after the write may roll it back: an update's after check or move-out, a
201
+ created row held to a write grant, a nested write, or returned rows checked by `exists`. A plain checked create or
202
+ delete is one statement, its interceptors and hooks outside any transaction.
203
+ - The after check asks `can` about the row the update returned, so it reads nothing again. Only a move-out reads the
204
+ changed rows again. An `update.count` runs as the returning `update.many` when the Contract offers it.
205
+
206
+ Round trips per request on PostgreSQL: `create.one` 3 → 1, `delete.unique` 4 → 1, `update.unique` 5 → 3,
207
+ `update.many` 4 → 3, `update.count` 5 → 3. Reads, and a Framework without a policy, are unchanged.
208
+
209
+ - 3813207: The Resource tree and the computed fields come from `aventara-build`.
210
+
211
+ - `@aventara/build`: before it compiles the Contracts, `aventara-build` writes two more files under
212
+ `src/generated/aventara/`. `resources.generated.ts` exports `aventaraResources`: every `defineResource(…)` result
213
+ that the files `src/resources/**/*.resource.ts` export, found by its type (never run), one `resources` tree per
214
+ layer, written as the plain spreads you wrote by hand (`root` always, `application`, `client` and `agent` when some
215
+ Resource has a block for them). Two definitions of one Resource stop the build, naming both. Imports are spelled as
216
+ the project spells its own. `computed-fields.generated.ts` exports `computedFields` and its type `AvComputedFields`:
217
+ which fields the configuration's write compute fills, read off its type after the tree exists, so a fresh install is
218
+ typed right on its first `aventara:prepare`. `--check` covers all three files. `typescript` (`>=5.7.0 <7`) is now a
219
+ peer dependency.
220
+ - `@aventara/prisma7-adapter`: the generate step no longer reads the configuration. With `--config`, the discovery
221
+ artifact imports `computedFields` and `AvComputedFields` from the file `aventara-build` writes beside the
222
+ configuration (`generated/aventara/computed-fields.generated.ts`); a `--config` file that does not exist is still
223
+ refused. `readConfigComputedFields`, `AvPrismaConfigReaderError` and `ConfigComputedFieldsReading` are removed from
224
+ `@aventara/prisma7-adapter/generate`, as are `PrismaGenerateToolchain.readComputedFields` and
225
+ `PrismaGenerateResult.computedFields`.
226
+ - `@aventara/cli`: the scaffold's `src/aventara.config.ts` takes its Resources from the tree,
227
+ `resources: aventaraResources.root`, so a new Resource file needs no configuration edit; the agent skill says so.
228
+
229
+ - Updated dependencies [e3d03a7]
230
+ - Updated dependencies [d10639a]
231
+ - Updated dependencies [f67e68c]
232
+ - Updated dependencies [708556c]
233
+ - Updated dependencies [3a0dfca]
234
+ - Updated dependencies [99169d2]
235
+ - Updated dependencies [0fd2608]
236
+ - Updated dependencies [154e440]
237
+ - Updated dependencies [2fcffdb]
238
+ - @aventara/core@1.0.0-rc.4
239
+
240
+ ## 1.0.0-rc.3
241
+
242
+ ### Patch Changes
243
+
244
+ - b38034d: `aventara-prisma7-generate` refuses a `--provider` that the schema's `datasource` block contradicts, or a block naming
245
+ a provider the adapter does not support, before `prisma generate` runs, so neither the Prisma client nor the artifact
246
+ is written:
247
+
248
+ ```text
249
+ aventara-prisma7-generate: --provider postgresql contradicts the schema's datasource `db` (prisma/schema.prisma:12), which names provider "sqlite"; pass --provider sqlite.
250
+ ```
251
+
252
+ PSL's `postgres` spelling counts as `postgresql`, and a provider that is not a string literal is not compared.
253
+ Before, the flag was taken on trust, and a wrong one wrote the wrong provider into the artifact and the wrong filter
254
+ modes into the Contract.
255
+
256
+ When the file system refuses the artifact file (`--out`), the step says so in one sentence naming the file and why,
257
+ such as
258
+ `the artifact file /app/src/generated/aventara/discovery.artifact.ts (--out) cannot be written: permission denied (EACCES).`,
259
+ and leaves no staged file behind. Before, every such failure except a directory printed a stack trace.
260
+
261
+ - b38034d: On PostgreSQL, a `@unique` value too long for its index (an index row past the B-tree's limit of about 2704 bytes, SQLSTATE
262
+ `54000`) is answered `422 A2004`, not `500 A3001`: one `V1004` issue at `["arguments"]`, as a value too long for its
263
+ column already was. The adapter reads the SQLSTATE, never the message. The issue's message for a value too long now
264
+ reads `The database refused this value: it is longer than the database can hold for its column.`
265
+ (it said `longer than its column can hold`, which an index refusal is not).
266
+ - Updated dependencies [b38034d]
267
+ - Updated dependencies [b38034d]
268
+ - Updated dependencies [b38034d]
269
+ - Updated dependencies [b38034d]
270
+ - Updated dependencies [b38034d]
271
+ - Updated dependencies [b38034d]
272
+ - @aventara/core@1.0.0-rc.3
273
+
274
+ ## 1.0.0-rc.2
275
+
276
+ ### Patch Changes
277
+
278
+ - On Cloudflare D1, a `BigInt` value beyond ±(2^53 − 1) is answered `A2004`, not `A3001`. `@prisma/adapter-d1`
279
+ binds a bigint as a JavaScript number and refuses one beyond that range before the statement runs, written,
280
+ compared in a filter or used in an `$increment`, and Prisma reports it as a database error (`P2039`). The adapter
281
+ answers that refusal as a value the database refused: `422 A2004` with one `V1004` issue, `The database refused
282
+ this value: it is outside the range its column can hold.`, at the value in the arguments (for example
283
+ `["arguments", "where", "views", "gt"]`). Nothing is written by the refused statement. It reads the arguments only
284
+ after the driver refused them, and only for the D1 driver; every other D1 database error stays `A3001`, and so does
285
+ a raw `ctx.$sql` statement binding such a value. Within ±(2^53 − 1) a bigint round-trips exactly on D1.
286
+ In rc.1 the refusal answered `500 A3001`. Measured on 7.10.0 through Miniflare's D1 binding.
287
+ - The README's D1 notes are corrected: D1 is measured in process through Miniflare, where Prisma's client refuses
288
+ an interactive `$transaction` and the D1 driver runs Prisma's implicit transaction for a nested write as single
289
+ statements, so a nested write is not atomic on D1.
290
+ - The optional `typescript` peer range is `>=5.7.0 <7` (it was `>=5.5.0 <7`). Under TypeScript 5.5 and 5.6 a
291
+ variant's stages written inline in `createFramework` are told `unknown` arguments, so `ctx.$args.data` and the
292
+ documented spread pipe `(args) => ({ ...args, data: { ...args.data, title: "t" } })` do not compile; TypeScript 5.7
293
+ and later type them. A project on TypeScript 5.5 or 5.6 upgrades to 5.7 or later.
294
+ - `createPrismaAdapter` checks the installed `@prisma/client`'s major against the discovery artifact's, as the
295
+ README says. It reads the version from `@prisma/client/package.json`, resolved from the adapter's own location and
296
+ then from the working directory, and refuses an artifact generated against another major with
297
+ `AvPrismaDiscoveryArtifactError`. In rc.1 the artifact's version stood in for the installed one when no
298
+ `installedPrismaVersion` was passed, which a scaffolded project never does, so the check compared the artifact with
299
+ itself. Where the version cannot be read (a runtime without Node's module loader, a bundle deployed without
300
+ `@prisma/client`), the adapter starts and emits a warning, code `AVENTARA_PRISMA_VERSION_UNCHECKED`, saying the
301
+ majors were not compared. `installedPrismaVersion` still overrides the version read.
302
+ - `aventara-prisma7-generate` refuses an `--out` inside `--client`, before `prisma generate` runs: exit 1 and one
303
+ sentence naming both paths. Prisma's next `prisma generate` clears the client's directory, so an artifact written
304
+ there was deleted. In rc.1 the step wrote it and exited 0. The same refusal applies to
305
+ `generatePrismaDiscoveryArtifact` and `runPrismaGenerateStep`.
306
+ - `aventara-prisma7-generate` refuses an `--out` that names a directory in one sentence (exit 1), before
307
+ `prisma generate` runs. In rc.1 it ran Prisma and then failed with an `EISDIR` stack trace.
308
+ - A nested write that writes its relation back is answered `A2004`, not `A3001`. Prisma writes a record reached
309
+ through a relation without that relation's other end, so it refuses a post created in `author.posts` that names
310
+ `author` or `authorId`, and a category created in a post's `category` that nests `posts`. The discovery artifact
311
+ now states each relation's other end (`inverse`, paired from the schema by relation name) and no relation writable
312
+ at the `"loopback"` position, so `@aventara/core` refuses such a write before any guard or SQL: `A2004`, `V1012` at
313
+ the field written back. It holds for `$create`, `$connectOrCreate`, `$update` and `$upsert`, to-one and to-many,
314
+ self-relations and one-to-ones. Where a layer hides the relation's other end, its Contract states no pairing and
315
+ Prisma's client is the one that refuses: the adapter answers that refusal as the caller's too, `A2004` with a
316
+ `V1012` issue at the field and the message `The data source refused this nested write: a record written through a
317
+ relation cannot write that relation or its reference fields back.` It reads the arguments only after Prisma
318
+ refused them; every other refusal of Prisma's client stays `A3001`. In rc.1 every case answered `500 A3001`.
319
+ Measured on 7.10.0, SQLite and PostgreSQL. Run `npm run aventara:prepare` to regenerate the artifact: the model's
320
+ hash and every Contract's hash change.
321
+ - The discovery artifact states each relation's reference fields (`referenceFields`, read from the schema's
322
+ `@relation(fields: …)`), on optional and required relations alike, and none on the end that holds no reference.
323
+ So the types leave `categoryId` out of a post created in `Category.posts`, as `@aventara/core` refuses it. Run
324
+ `npm run aventara:prepare` to regenerate the artifact: the model's hash and every Contract's hash change.
325
+ - A `$divide` by zero is answered `A2004`, not `A3001`. It reaches the database as given: PostgreSQL refuses the
326
+ division (`P2039`, `22012`) and the adapter answers `V1004` `The database refused this value: it divides by zero.`;
327
+ SQLite computes NULL and the `NOT NULL` column refuses it (`P2011`), answered `V1004` `The database refused this
328
+ value: the write computes no value for a column that requires one, as a division by zero does.` Both at
329
+ `["arguments"]`, nothing written. `P2011` reaches the adapter only this way: core refuses a `null` for a required
330
+ field and a missing one, and so does Prisma's client before the query. In rc.1 both answered `500 A3001`. Measured
331
+ on 7.10.0 for `Int`, `BigInt`, `Float` and `Decimal`, in `update` and `updateMany`.
332
+ - `null` on a nullable `Json` field is the database NULL, as on every other nullable field. A write of `null`
333
+ (create, update, upsert, bulk, nested, a plan step) is sent as Prisma's `DbNull`; `{ meta: null }` and
334
+ `{ meta: { equals: null } }` are sent as Prisma's `AnyNull` and match every row that reads back `null` (a database
335
+ NULL or a JSON `null` stored by other means), and `{ meta: { not: null } }` matches the other rows. A JSON `null`
336
+ inside a value is sent as written, and so is a `null` beside a `path`: Prisma matches the documents whose value at
337
+ that path is a JSON `null`. In rc.1 a write of `null` stored a JSON `null`, `equals: null` matched only the stored
338
+ JSON nulls, and `{ meta: null }` failed with `500 A3001`. Reads are unchanged. Measured on 7.10.0, SQLite and
339
+ PostgreSQL.
340
+ - A to-one relation filter is sent under Prisma's `is`. `{ category: {} }` matches the rows that have a related row and
341
+ `{ NOT: { category: {} } }` the rows that have none. In rc.1 the empty predicate was sent unwrapped, which Prisma
342
+ reads as no condition: both matched every row, and `Post.delete.count({ where: { NOT: { author: {} } } })` deleted
343
+ every post although each has its required author. A non-empty nested `where` and `null` match what they did.
344
+ - A value the database refuses is answered `A2004`, not `A3001`. Text-match operands and written values reach Prisma
345
+ as given (`%` and `_` are what the engine's `LIKE` makes of them, a column rounds or keeps what it does); when
346
+ PostgreSQL refuses a caller's value, the adapter answers `A2004` with one issue at `["arguments"]` (Prisma's error
347
+ names no column): `V1004` for a value too long for its column (`P2000`), out of its column's range (`P2020`: a
348
+ `Decimal` past its precision, `Number.MAX_VALUE` in a `Float`, an `Int` `$increment` past 2^31) or a `DateTime`
349
+ outside PostgreSQL's range (`P2039`, `22009`); `V1001` for U+0000 in text or `json` (`P2039`, `22021` and `22P05`),
350
+ a lone surrogate in `json` (`P2007`) and a `LIKE` pattern ending in `\` (`P2039`, `22025`). The issue's message
351
+ says which of these the database refused, in core's words and none of the database's (`The database refused this
352
+ value: it is longer than its column can hold.`), not the code's generic text. Inside a plan the
353
+ issue stands at the step (`["operations", i, "args"]`) and the plan rolls back. Every other database failure stays
354
+ `A3001`. In rc.1 each of these answered `500 A3001`. Measured on 7.10.0, SQLite and PostgreSQL; SQLite refused none
355
+ of these values.
356
+ - A field's `not` holding an operator object now means the negation of the whole object, on every field type, on
357
+ both engines, in reads and in bulk writes. `{ f: { not: X } }` matches exactly the rows `{ NOT: { f: X } }` matches:
358
+ a row where `X` is neither true nor false (the column is `NULL`, a `json` `path` is not in the document, a `json`
359
+ value is not the kind the operator reads) matches neither `X` nor `not: X`, as SQL's `NOT` reads it. The adapter
360
+ sends it to Prisma as `NOT` of the field's filter, ANDed with the rest of the `where`, because Prisma's own
361
+ field-level `not` says less (measured on 7.10.0, SQLite and PostgreSQL):
362
+
363
+ - In rc.1, a `json` field's `not` holding operators matched every row on both engines, because Prisma reads that
364
+ `not` as a JSON value to compare the document with. That covers `{ meta: { not: { path: ["label"],
365
+ stringContains: "x" } } }`, `{ meta: { not: { equals: { a: 1 } } } }` and every other operator under it, and an
366
+ `update.many`, `update.count`, `delete.count` or `delete.first` under such a filter wrote or deleted every row
367
+ the rest of the filter allowed.
368
+ - In rc.1, two or more operators under `not` were negated one at a time and ANDed, so
369
+ `{ views: { not: { gt: 2, lte: 5 } } }` matched no row. It now matches the rows outside that range.
370
+ - In rc.1 on PostgreSQL, a `mode` inside `not` (`{ title: { not: { contains: "x", mode: "insensitive" } } }`)
371
+ failed with `A3001`, because Prisma's filter under `not` has no `mode`. It now matches the titles that do not
372
+ contain `x` in any case.
373
+
374
+ The object under `not` is its own level: nothing from the object around it reaches into it. In rc.1 on
375
+ PostgreSQL, `{ title: { mode: "insensitive", not: { contains: "x" } } }` excluded `X` as well as `x`, because Prisma
376
+ applied the outer `mode` inside its own `not`. Core now refuses that filter (`A2004`, `V1001` at the `mode`); write
377
+ `{ title: { not: { contains: "x", mode: "insensitive" } } }`. A plain value under `not` (`{ not: "x" }`,
378
+ `{ not: null }`) is equality negated and is sent as before.
379
+
380
+ - A `json` field's bare value in a filter is equality on both engines: `{ meta: "x" }` and `{ meta: [1, 2] }` are sent
381
+ to Prisma as `{ equals: … }`. In rc.1 they failed with `A3001`, because Prisma's Json filter takes no bare value.
382
+ - Filter modes, measured on each engine. PostgreSQL offers `"default"`, `"sensitive"` and `"insensitive"` on a string
383
+ column and on a `json` value at a `path`; on a whole `json` document it offers `"default"` and `"sensitive"`, because
384
+ Prisma accepts an insensitive `stringContains` there and PostgreSQL then fails (`42883 function lower(jsonb) does not
385
+ exist`, answered `A3001`). That filter is now refused before any query (`A2004`, `V1006` at the `mode`). SQLite, and
386
+ so D1, offers `"default"` only: its `LIKE` folds ASCII case and nothing else, and `equals` folds none, so neither
387
+ promise holds. Every string field with a text operator now offers `mode` (on SQLite with `"default"` alone), and
388
+ `"default"` and `"sensitive"` are sent to Prisma as no `mode` at all. Regenerate the discovery artifact
389
+ (`aventara:prepare`).
390
+ - 9366e16: The discovery artifact names the model's type: it exports `AvModel`, and `model` is declared with it
391
+ (`typeof model` is `AvModel`). A project that emits declarations (Nest's `declaration: true`) now writes that
392
+ name wherever an exported declaration holds the model, instead of the whole model. Over 50 models the scaffold's
393
+ `aventara.config.d.ts` goes from 485 KB to 0.4 KB, and a `buildFramework` / `AppFramework` module from 931 KB to
394
+ 0.6 KB (1.2 MB to 0.6 KB, and 2.4 MB to 22 KB for exported configurations holding typed stages, in the consumer-build
395
+ gate). Regenerate the artifact (`aventara:prepare`, which runs on install, build and start) to get it; Contract bytes
396
+ and hashes are unchanged.
397
+ - New: `aventara-prisma7-generate --config <file>`, optional. Given your Aventara configuration module
398
+ (`src/aventara.config.ts` in a project set up by `aventara`; its `aventaraConfig` export, a function or a value, or
399
+ its default export), the artifact states which fields it computes on create and on update, per layer. They are read
400
+ off the configuration's TypeScript type, never by running it, so nothing connects to a database and no environment
401
+ is needed. The artifact exports them as `computedFields` (type `AvComputedFields`), carries them on `AvModel` so a
402
+ variant's guards, pipes and filters may leave exactly those fields out of a create, and hands them to the framework
403
+ through `discovery.computedFields`, which it compares with the configuration at startup. A configuration that is
404
+ not a literal where a compute stage is written (one annotated with the wide `AvConfig`, a conditional spread) is not
405
+ read: the step prints where, and the artifact states nothing, so those stages may leave any create field out. A
406
+ `--config` file that does not exist, or exports neither `aventaraConfig` nor a default, stops the step.
407
+ `generatePrismaDiscoveryArtifact` and `runPrismaGenerateStep` take the same `config`, and
408
+ `readConfigComputedFields` is exported from `@aventara/prisma7-adapter/generate`.
409
+ - The discovery artifact's format is now 4 (`computedFields` is new): an artifact written before it is refused with
410
+ the regeneration instruction. `aventara:prepare` regenerates it on install, build and start.
411
+ - A transaction that expired (or was closed) under a step is answered `A3002`, as when the COMMIT finds it expired:
412
+ Prisma's `P2028`, raised by the step's own call, is the transaction's failure, at that step (`cause.operation`),
413
+ and the plan rolls back. In rc.1 it was unclassified and answered `500 A3001`, an adapter failure. Measured on
414
+ 7.10.0, SQLite and PostgreSQL.
415
+ - Updated dependencies [9366e16]
416
+ - Updated dependencies [9366e16]
417
+ - Updated dependencies [9366e16]
418
+ - Updated dependencies [9366e16]
419
+ - @aventara/core@1.0.0-rc.2
420
+
3
421
  ## 1.0.0-rc.1
4
422
 
5
423
  ### Patch Changes