@aventara/prisma7-adapter 0.1.0-pilot.4 → 1.0.0-rc.0
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/CHANGELOG.md +190 -0
- package/README.md +22 -7
- package/dist/discovery/artifact.loader.js +4 -1
- package/dist/discovery/capability-surface.interface.d.ts +7 -0
- package/dist/discovery/capability.deriver.js +3 -0
- package/dist/discovery/discovery-artifact.interface.d.ts +17 -5
- package/dist/discovery/discovery-artifact.interface.js +1 -1
- package/dist/discovery/field.mapper.d.ts +1 -1
- package/dist/discovery/field.mapper.js +1 -1
- package/dist/discovery/model.discoverer.d.ts +1 -1
- package/dist/discovery/model.discoverer.js +5 -4
- package/dist/discovery/operations.deriver.d.ts +2 -1
- package/dist/discovery/types.reader.js +11 -0
- package/dist/discovery/vocabulary.dictionary.d.ts +2 -1
- package/dist/execution/operation.executor.d.ts +2 -1
- package/dist/execution/transaction.executor.d.ts +2 -1
- package/dist/generate/artifact.emitter.js +7 -6
- package/dist/prisma.adapter.js +1 -0
- package/dist/translation/mutation.translator.d.ts +1 -1
- package/dist/translation/mutation.translator.js +1 -1
- package/dist/translation/operation.translator.d.ts +2 -1
- package/dist/translation/order-pagination.translator.d.ts +1 -1
- package/dist/translation/order-pagination.translator.js +1 -1
- package/dist/translation/scalar.conversion.d.ts +2 -1
- package/dist/translation/scalar.conversion.js +1 -1
- package/package.json +5 -4
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# @aventara/prisma7-adapter
|
|
2
|
+
|
|
3
|
+
## 1.0.0-rc.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- First release candidate of Aventara 1.0. The public API is now considered stable; changes before 1.0.0 are possible
|
|
8
|
+
based on feedback.
|
|
9
|
+
|
|
10
|
+
### Minor Changes
|
|
11
|
+
|
|
12
|
+
- 24ffbab: A nested `$update` or `$delete` through a to-many relation filters plain fields only on Prisma 7, and Aventara now says
|
|
13
|
+
so up front: a relation filter in its `where` — `{ posts: { $update: { where: { category: { name: "x" } }, … } } }`, at
|
|
14
|
+
any depth, under `AND`/`OR`/`NOT` too — is refused with `A2004` / `V1006` before the database is asked, and is a type
|
|
15
|
+
error in `framework.application`, `framework.client`, `appTx`/`clientTx` and the generated client. Before, it reached
|
|
16
|
+
Prisma and fail as `A3001`. A to-one relation's nested filter keeps relation filters. The limit is stated by the adapter
|
|
17
|
+
in the Contract (`nestedWriteFilter: "scalar"`), so the ClientContract hash changes: regenerate the client.
|
|
18
|
+
|
|
19
|
+
### Patch Changes
|
|
20
|
+
|
|
21
|
+
- 24ffbab: Each package ships its `CHANGELOG.md`, so the release notes are in the installed package beside the README.
|
|
22
|
+
- a973e89: A write that sets an optional relation both ways — its reference field and the relation itself, such as `categoryId`
|
|
23
|
+
and `category: { $connect: … }` in the same record — is now refused before it reaches the database, exactly like a
|
|
24
|
+
required relation: `A2004` with a `V1012` issue at the relation, message `Set "categoryId" or "category", not both.`
|
|
25
|
+
Before, the database refused it and the caller received `A3001`. It applies to `create`, `update` and `upsert`, to
|
|
26
|
+
nested writes at any depth, and to each step of a transaction.
|
|
27
|
+
|
|
28
|
+
The discovery artifact now records, for each relation, the fields that hold its reference (`references` on each edge
|
|
29
|
+
of `referentialActions`), and a create requirement no longer repeats them. Regenerate your artifact with
|
|
30
|
+
`npm run aventara:prepare` (or `aventara-prisma7-generate`); an artifact from an earlier version is refused with a
|
|
31
|
+
message that says so. An adapter's `referentialActions` edges carry the same `references` member.
|
|
32
|
+
|
|
33
|
+
- a973e89: With the Prisma adapter, a record that writes one relation through its reference field and another relation directly —
|
|
34
|
+
such as `authorId` beside `category: { $connect: … }` — is now refused before it reaches the database: `A2004` with a
|
|
35
|
+
`V1012` issue at the relation write, message
|
|
36
|
+
`Use relation fields only, or reference fields only, in one record: "authorId" is a reference field and "category" is a relation.`
|
|
37
|
+
Before, Prisma refused it and the caller received `A3001`. Write the record's relations all as relations
|
|
38
|
+
(`author: { $connect: … }, category: { $connect: … }`) or all through their fields (`authorId`, `categoryId`). A
|
|
39
|
+
reference field beside a relation that holds no reference on that side — `mentorId` beside `posts: { $create: … }` on
|
|
40
|
+
an author — is unchanged and still accepted. It applies to `create`, `update` and `upsert`, to nested writes at any
|
|
41
|
+
depth, and to each step of a transaction.
|
|
42
|
+
|
|
43
|
+
The limit is part of the Contract: a Contract whose data source has it carries `referenceWrites: "uniform"`, so the
|
|
44
|
+
Contract hash of every Prisma-backed application changes. Regenerate your discovery artifact
|
|
45
|
+
(`npm run aventara:prepare`) and your generated client (`avclient generate`). An adapter states the limit with
|
|
46
|
+
`referenceWrites: "uniform"` in its model; without it, nothing changes.
|
|
47
|
+
|
|
48
|
+
- Updated dependencies [24ffbab]
|
|
49
|
+
- Updated dependencies [24ffbab]
|
|
50
|
+
- Updated dependencies [24ffbab]
|
|
51
|
+
- Updated dependencies [24ffbab]
|
|
52
|
+
- Updated dependencies [24ffbab]
|
|
53
|
+
- Updated dependencies [24ffbab]
|
|
54
|
+
- Updated dependencies [24ffbab]
|
|
55
|
+
- Updated dependencies [24ffbab]
|
|
56
|
+
- Updated dependencies [24ffbab]
|
|
57
|
+
- Updated dependencies [24ffbab]
|
|
58
|
+
- Updated dependencies [24ffbab]
|
|
59
|
+
- Updated dependencies [24ffbab]
|
|
60
|
+
- Updated dependencies [a973e89]
|
|
61
|
+
- Updated dependencies [1e65e9a]
|
|
62
|
+
- Updated dependencies
|
|
63
|
+
- Updated dependencies [a973e89]
|
|
64
|
+
- Updated dependencies [a973e89]
|
|
65
|
+
- Updated dependencies [1e65e9a]
|
|
66
|
+
- Updated dependencies [1e65e9a]
|
|
67
|
+
- Updated dependencies [24ffbab]
|
|
68
|
+
- Updated dependencies [2d00ad7]
|
|
69
|
+
- Updated dependencies [384a50c]
|
|
70
|
+
- Updated dependencies [d43d1cc]
|
|
71
|
+
- Updated dependencies [3f98749]
|
|
72
|
+
- Updated dependencies [032f792]
|
|
73
|
+
- Updated dependencies [dbe6961]
|
|
74
|
+
- @aventara/core@1.0.0-rc.0
|
|
75
|
+
|
|
76
|
+
## 0.1.0-pilot.4
|
|
77
|
+
|
|
78
|
+
### Patch Changes
|
|
79
|
+
|
|
80
|
+
- f37dcd6: A discovery artifact written by an older version of the adapter now fails the TypeScript build with an error that
|
|
81
|
+
says what to do: `Property 'regenerate_with_aventara_prepare' is missing`. Run `npm run aventara:prepare`
|
|
82
|
+
(or `aventara-prisma7-generate`) to regenerate it. Every newly generated artifact carries the property, and
|
|
83
|
+
`createPrismaAdapter` refuses an out-of-date artifact at startup with the same instruction.
|
|
84
|
+
- f37dcd6: The documentation shipped with the package — the comments an editor shows on hover, and the README — now describes
|
|
85
|
+
what each export does, how to use it, what it returns and what it throws. Notes about how the package was built and
|
|
86
|
+
why are no longer part of what is published.
|
|
87
|
+
|
|
88
|
+
The generate step's error messages name "the generated client's types" in words instead of Prisma's emoji labels.
|
|
89
|
+
|
|
90
|
+
- Updated dependencies [f37dcd6]
|
|
91
|
+
- @aventara/core@0.1.0-pilot.4
|
|
92
|
+
|
|
93
|
+
## 0.1.0-pilot.3
|
|
94
|
+
|
|
95
|
+
### Patch Changes
|
|
96
|
+
|
|
97
|
+
- The manifest declares the adapter's CLI alias, `aventara.adapter.alias: "prisma7"`: the value `aventara new --orm` and `aventara init --orm` take.
|
|
98
|
+
- @aventara/core@0.1.0-pilot.3
|
|
99
|
+
|
|
100
|
+
## 0.1.0-pilot.2
|
|
101
|
+
|
|
102
|
+
### Patch Changes
|
|
103
|
+
|
|
104
|
+
- e69e88d: The published packages are written for the people who use them. The JavaScript ships without comments; the type
|
|
105
|
+
declarations keep their documentation, and it, the error messages, the protocol fixtures' labels and the comments in a
|
|
106
|
+
generated client no longer carry the project's internal development notes.
|
|
107
|
+
- 06ed5d8: A relation write that would leave a child without the parent its required relation demands — `$set: []` or
|
|
108
|
+
`$disconnect` on a to-many whose children require the parent — now answers `A2008` (the same conflict a violated
|
|
109
|
+
reference constraint answers) instead of `A3001`. Nothing is written.
|
|
110
|
+
- 23937f8: A create that lacks a value the database requires is refused as `A2004` with a `V1000` issue at the value's path,
|
|
111
|
+
instead of reaching the database and answering `A3001`. It covers `create.one`, every row of `create.many`, `upsert`'s
|
|
112
|
+
`create` branch, nested `$create` (and `$connectOrCreate`/`$upsert` creates) at any depth, and transaction steps
|
|
113
|
+
(`["operations", i, "args", …]`). A required relation is satisfied by writing it or every scalar that holds its
|
|
114
|
+
reference; a nested create never needs the relation it is created through. Defaults, `@updatedAt`, autoincrement,
|
|
115
|
+
optional and list columns are never required. The check runs after pipes and computed behaviours, so a value they
|
|
116
|
+
supply counts.
|
|
117
|
+
|
|
118
|
+
An adapter states the requirements through the new optional `Adapter.createRequirements`; the Prisma 7 adapter reads
|
|
119
|
+
them from the generated client's create inputs at generate time and records them in the discovery artifact, so the
|
|
120
|
+
artifact must be regenerated (`aventara:prepare`).
|
|
121
|
+
|
|
122
|
+
- 287fc27: A discovery artifact older than the Prisma client is refused at startup. The artifact now records the client it was
|
|
123
|
+
generated from (each model and its field references), and `createPrismaAdapter` — which runs before the application
|
|
124
|
+
listens — compares that record with the client it is given: a model or field added, removed or renamed since the
|
|
125
|
+
artifact was generated stops the server with one sentence naming the difference and `aventara:prepare`. An artifact
|
|
126
|
+
generated by an earlier version carries no record and is refused with the same instruction; a project set up by
|
|
127
|
+
`aventara` regenerates it on install.
|
|
128
|
+
- Updated dependencies [c2a3b7c]
|
|
129
|
+
- Updated dependencies [e69e88d]
|
|
130
|
+
- Updated dependencies [ab58424]
|
|
131
|
+
- Updated dependencies [23937f8]
|
|
132
|
+
- @aventara/core@0.1.0-pilot.2
|
|
133
|
+
|
|
134
|
+
## 0.1.0-pilot.1
|
|
135
|
+
|
|
136
|
+
### Patch Changes
|
|
137
|
+
|
|
138
|
+
- 799346e: The package READMEs (each package's npm page) are rewritten for the people who use the packages. The Prisma 7
|
|
139
|
+
adapter's README now states the actual behaviour of a to-many relation or `$count` projected on
|
|
140
|
+
`update.many`/`create.many`: a validation refusal, `A2004` with `V1008`, before any statement runs (it said `A3001`).
|
|
141
|
+
Every install or run command names the `@pilot` dist-tag.
|
|
142
|
+
- Updated dependencies [a45f8a8]
|
|
143
|
+
- Updated dependencies [799346e]
|
|
144
|
+
- @aventara/core@0.1.0-pilot.1
|
|
145
|
+
|
|
146
|
+
## 0.1.0-pilot.0
|
|
147
|
+
|
|
148
|
+
### Minor Changes
|
|
149
|
+
|
|
150
|
+
- First pilot release of `@aventara/prisma7-adapter`, the Prisma 7 adapter. Peers: `@prisma/client`, `prisma` and the
|
|
151
|
+
driver adapters `^7.10.0`; `typescript` `>=5.5.0 <7` for the generate step. `typescript` and `prisma` are optional
|
|
152
|
+
peers used only by the generate step, so neither enters a deployed install.
|
|
153
|
+
|
|
154
|
+
- **`createPrismaAdapter({ client, discovery, provider, driver, transactionOptions? })`** is the entry point. Your
|
|
155
|
+
application owns the Prisma client, built with a driver adapter; the adapter never builds one, reads a connection
|
|
156
|
+
string or reads an environment variable. `provider` and `driver` are stated by you, and the driver decides whether
|
|
157
|
+
transactions are offered. It is `async` because it verifies the discovery artifact.
|
|
158
|
+
- **Discovery runs at generate time.** `aventara-prisma7-generate` (or the `@aventara/prisma7-adapter/generate`
|
|
159
|
+
export) reads `schema.prisma` and the generated client's types and writes one module, the discovery artifact: the
|
|
160
|
+
model, how each Resource is addressed, its referential actions, a `modelHash` and the Prisma version. At startup the
|
|
161
|
+
adapter checks that the artifact matches its `modelHash` and that the installed `@prisma/client` major is the one it
|
|
162
|
+
was generated against, and stops with an instruction to regenerate otherwise. The artifact is rewritten only when its
|
|
163
|
+
bytes change, and replaced atomically, so a reader never sees a half-written file.
|
|
164
|
+
- **The Contract says what Prisma serves.** `createMany`/`updateMany` results project fewer relations than a read
|
|
165
|
+
(the rule is which side holds the foreign key, not cardinality); the Contract advertises that per argument position,
|
|
166
|
+
and an out-of-position projection or nested write is refused with `A2004` (`V1008` / `V1006`) before any query.
|
|
167
|
+
- **Cascading deletes.** The schema's referential actions are stated to the Framework, so a transaction step that
|
|
168
|
+
depends on rows an earlier step's cascading delete removed is refused before the plan runs (`A2004`/`V1019`).
|
|
169
|
+
- **Conflicts are told apart:** `A2008 CONFLICT` for a uniqueness or reference constraint, `A2013
|
|
170
|
+
CONCURRENT_MODIFICATION` when another operation changed the same state, `A2014 STALE_SELECTION` when the selected
|
|
171
|
+
record changed before the write.
|
|
172
|
+
- **Behaviours to know:**
|
|
173
|
+
- `delete.many` is not offered (Prisma 7 has no `deleteManyAndReturn`); use `delete.count`.
|
|
174
|
+
- `update.first` and `delete.first` are a read followed by a write narrowed to the record the read selected, and are
|
|
175
|
+
not atomic: the record written is one the read selected, or nothing is written and you are told (`A2014`). A
|
|
176
|
+
record that comes to sort first between the two statements is not seen. If firstness at the instant of the write
|
|
177
|
+
matters, select the record yourself and use `update.unique`/`delete.unique`.
|
|
178
|
+
- A serialization failure (`P2034`) is never retried automatically: a retry would re-run your pipeline callbacks.
|
|
179
|
+
Retrying is yours to decide.
|
|
180
|
+
- Whether transactions are offered depends on the driver and is part of the ClientContract hash, so generate the
|
|
181
|
+
client against the deployment's own driver.
|
|
182
|
+
- No raw SQL is ever issued.
|
|
183
|
+
- PostgreSQL and SQLite are supported.
|
|
184
|
+
- Every export has a `default` condition, so a CommonJS project can `require()` it. The manifest declares what the
|
|
185
|
+
adapter supports (providers, drivers, generators), which `@aventara/cli` reads.
|
|
186
|
+
|
|
187
|
+
### Patch Changes
|
|
188
|
+
|
|
189
|
+
- Updated dependencies
|
|
190
|
+
- @aventara/core@0.1.0-pilot.0
|
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ does, what it deliberately does **not** offer, and the two places where a correc
|
|
|
9
9
|
has a weaker guarantee than its name suggests. Everything a consumer has to know is in the body of
|
|
10
10
|
this file; nothing load-bearing is in a footnote.
|
|
11
11
|
|
|
12
|
-
- **Status:**
|
|
12
|
+
- **Status:** release candidate. Two engines are proven — PostgreSQL and SQLite. Every other Prisma provider is
|
|
13
13
|
unmeasured, and this file says so where it matters.
|
|
14
14
|
- **Peer dependencies:** `@prisma/client` `^7.10.0` (required); `prisma`, `@prisma/adapter-better-sqlite3`
|
|
15
15
|
and `@prisma/adapter-pg` `^7.10.0` and `typescript` `>=5.5.0 <7` (optional). 7.10.0 is the version the
|
|
@@ -127,14 +127,15 @@ project's `devDependencies` — if you are generating a Prisma client at all, yo
|
|
|
127
127
|
The step reads two sources in the same instant — the `schema.prisma` text and the generated client's
|
|
128
128
|
own public types — and cross-checks them against each other. What it emits is a TypeScript module
|
|
129
129
|
exporting one `discovery` value with eight members: the canonical `AdapterModel` (scalars, enums,
|
|
130
|
-
Resources with fields, identifiers and available operations, plus the `transactions` capability
|
|
130
|
+
Resources with fields, identifiers and available operations, plus the `transactions` capability and the
|
|
131
|
+
`referenceWrites` limit), the
|
|
131
132
|
Prisma addressing each Resource is reached by, the resolved referential actions per Resource, a record
|
|
132
133
|
of the generated client it was read from (each model and its field references), the create
|
|
133
134
|
requirements per Resource, a `modelHash`, and the `prismaVersion` it was generated against.
|
|
134
135
|
|
|
135
136
|
The create requirements are what a create cannot do without — a column with no default, or a required
|
|
136
|
-
relation, which may be written instead through the scalar fields that hold its reference
|
|
137
|
-
question marks of the generated create inputs. The framework checks every create against them after
|
|
137
|
+
relation, which may be written instead through the scalar fields that hold its reference (the edge's
|
|
138
|
+
`references`, below) — read off the question marks of the generated create inputs. The framework checks every create against them after
|
|
138
139
|
your pipes and computed behaviours have run, and answers a missing value as `A2004` with a `V1000`
|
|
139
140
|
issue at its path (`["arguments", "data", "title"]`, or `["arguments", "data", "author"]` for a
|
|
140
141
|
required relation) instead of letting the database refuse it. A nested create does not need the
|
|
@@ -477,10 +478,10 @@ discovery.referentialActions;
|
|
|
477
478
|
// {
|
|
478
479
|
// Shop: { owningEdges: [] },
|
|
479
480
|
// Item: { owningEdges: [{ field: "shop", target: "Shop",
|
|
480
|
-
// cardinality: "one",
|
|
481
|
+
// cardinality: "one", references: ["shopId"],
|
|
481
482
|
// onDelete: "cascade", onUpdate: "cascade" }] },
|
|
482
483
|
// Clerk: { owningEdges: [{ field: "shop", target: "Shop",
|
|
483
|
-
// cardinality: "one",
|
|
484
|
+
// cardinality: "one", references: ["shopId"],
|
|
484
485
|
// onDelete: "set-null", onUpdate: "cascade" }] },
|
|
485
486
|
// }
|
|
486
487
|
```
|
|
@@ -492,6 +493,20 @@ To answer *"what does deleting a `Shop` do?"*, scan every Resource's `owningEdge
|
|
|
492
493
|
(set-null). Both ends of that sentence are Resource names and nothing in the shape tells them apart, so
|
|
493
494
|
the inverted reading produces no error at all, only a plan that reasons backwards.
|
|
494
495
|
|
|
496
|
+
`references` are the edge's `@relation(fields: […])` — the scalars that hold the reference. A record
|
|
497
|
+
that writes a relation and one of its reference fields both (`shopId` and `shop: { $connect: … }`,
|
|
498
|
+
required relation or optional) is refused before the database is reached: `A2004` with a `V1012` issue
|
|
499
|
+
at the relation, message `Set "shopId" or "shop", not both.` They are also what a required relation may
|
|
500
|
+
be written through instead of the relation itself.
|
|
501
|
+
|
|
502
|
+
Prisma takes one record's relations either all as relation writes or all through their reference
|
|
503
|
+
fields — its checked and unchecked inputs — so every artifact's model states `referenceWrites: "uniform"`,
|
|
504
|
+
and every Contract compiled from it carries the same member. A record that writes `shopId` beside
|
|
505
|
+
another relation's write (`supplier: { $connect: … }`) is refused before the database is reached:
|
|
506
|
+
`A2004` with a `V1012` issue at the relation write. A reference field beside a back-reference (a
|
|
507
|
+
relation that holds no reference on that side, such as a shop's `items`) mixes nothing and is
|
|
508
|
+
accepted.
|
|
509
|
+
|
|
495
510
|
Only **owning** edges appear: PSL forbids the non-owning side of a relation from declaring an action,
|
|
496
511
|
so a back-reference's answer is its partner's and carries no entry of its own. Both actions are
|
|
497
512
|
*resolved* — an absent PSL argument is not a third state but Prisma's effective default (`set-null`
|
|
@@ -499,7 +514,7 @@ where every foreign-key scalar is optional, `restrict` otherwise, `cascade` on u
|
|
|
499
514
|
PostgreSQL and SQLite. An action spelling the reader cannot name stops the generate step rather than reaching
|
|
500
515
|
the artifact.
|
|
501
516
|
|
|
502
|
-
Neither the model nor the compiled Contracts carry a referential action — the
|
|
517
|
+
Neither the model nor the compiled Contracts carry a referential action or a reference field — the edges are beside the
|
|
503
518
|
model and outside `modelHash`, so they move no Contract value and no hash. `createPrismaAdapter` states
|
|
504
519
|
them to core through the adapter's optional `referentialActions` member, translated one to one into core's
|
|
505
520
|
five words (mirroring Prisma's and SQL's actions; direction unchanged):
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { canonicalizeJson } from "@aventara/core";
|
|
1
|
+
import { canonicalizeJson } from "@aventara/core/internal";
|
|
2
2
|
import { DISCOVERY_ARTIFACT_FORMAT, } from "./discovery-artifact.interface.js";
|
|
3
3
|
const HASH_PREFIX = "sha256:";
|
|
4
4
|
const REGENERATION_INSTRUCTION = "Regenerate the discovery artifact — `npm run aventara:prepare` in a project " +
|
|
@@ -63,6 +63,9 @@ function assertArtifactShape(artifact) {
|
|
|
63
63
|
artifact.model.transactions !== "interactive") {
|
|
64
64
|
throw new PrismaDiscoveryArtifactError("The discovery artifact's `model.transactions` is not a transaction capability.");
|
|
65
65
|
}
|
|
66
|
+
if (artifact.model.referenceWrites !== "uniform") {
|
|
67
|
+
throw new PrismaDiscoveryArtifactError("The discovery artifact's `model.referenceWrites` is not `uniform`, which every Prisma model is.");
|
|
68
|
+
}
|
|
66
69
|
}
|
|
67
70
|
export async function loadDiscoveryArtifact(load) {
|
|
68
71
|
const { artifact, installedPrismaVersion } = load;
|
|
@@ -76,6 +76,13 @@ export type PrismaRelationSurface = {
|
|
|
76
76
|
*/
|
|
77
77
|
readonly createRequired: boolean;
|
|
78
78
|
readonly updateMutations: readonly string[];
|
|
79
|
+
/**
|
|
80
|
+
* Whether the update stage's `deleteMany` takes a `<T>ScalarWhereInput` — a filter of
|
|
81
|
+
* the target's scalar fields only, which `updateMany`'s `where` shares. Read off the
|
|
82
|
+
* nested input's own member type; `false` where the input has no `deleteMany` (a
|
|
83
|
+
* to-one edge, whose `update`/`delete` take a full `<T>WhereInput`).
|
|
84
|
+
*/
|
|
85
|
+
readonly scalarNestedWriteFilter: boolean;
|
|
79
86
|
readonly edgeArguments: readonly string[];
|
|
80
87
|
readonly pagination: readonly string[];
|
|
81
88
|
/** The edge is admitted by `<M>OrderByWithRelationInput`. */
|
|
@@ -157,6 +157,9 @@ export function deriveRelationCapabilities(input) {
|
|
|
157
157
|
: {}),
|
|
158
158
|
create: writableIn(directives(surface.createMutations), surface.bulkCreatable),
|
|
159
159
|
update: writableIn(directives(surface.updateMutations), surface.bulkUpdatable),
|
|
160
|
+
...(surface.scalarNestedWriteFilter
|
|
161
|
+
? { nestedWriteFilter: "scalar" }
|
|
162
|
+
: {}),
|
|
160
163
|
};
|
|
161
164
|
}
|
|
162
165
|
function look(table, key, what) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { Adapter,
|
|
1
|
+
import type { Adapter, AdapterModel, EnumDefinition, ScalarRegistry, TransactionCapability } from "@aventara/core";
|
|
2
|
+
import type { AdapterResource } from "@aventara/core/internal";
|
|
2
3
|
import type { PrismaProvider } from "../provider/provider-profile.js";
|
|
3
4
|
/** The adapter model a discovery artifact carries, in Aventara's vocabulary. */
|
|
4
5
|
export type PrismaAdapterModel = {
|
|
@@ -10,6 +11,11 @@ export type PrismaAdapterModel = {
|
|
|
10
11
|
readonly resources: Readonly<Record<string, AdapterResource<PrismaAdapterModel>>>;
|
|
11
12
|
/** Whether the driver supports interactive transactions. */
|
|
12
13
|
readonly transactions: TransactionCapability;
|
|
14
|
+
/**
|
|
15
|
+
* Prisma takes one record's references one way at a time (its checked and
|
|
16
|
+
* unchecked write inputs), so every artifact states `"uniform"`.
|
|
17
|
+
*/
|
|
18
|
+
readonly referenceWrites: NonNullable<AdapterModel["referenceWrites"]>;
|
|
13
19
|
};
|
|
14
20
|
/** One identifier, and the **Prisma addressing key** that reaches it. */
|
|
15
21
|
export type PrismaIdentifierAddress = {
|
|
@@ -34,6 +40,11 @@ export type PrismaReferentialEdge = {
|
|
|
34
40
|
readonly target: string;
|
|
35
41
|
/** Whether the edge holds one related row or many. */
|
|
36
42
|
readonly cardinality: "one" | "many";
|
|
43
|
+
/**
|
|
44
|
+
* The scalar fields of the ENCLOSING resource that hold the reference — the
|
|
45
|
+
* relation's `@relation(fields: […])`, in schema order.
|
|
46
|
+
*/
|
|
47
|
+
readonly references: readonly string[];
|
|
37
48
|
/** What deleting a `target` row does to rows of the ENCLOSING resource. */
|
|
38
49
|
readonly onDelete: PrismaReferentialAction;
|
|
39
50
|
/** The same for an update of the referenced key. Read independently of `onDelete`. */
|
|
@@ -64,9 +75,10 @@ export type PrismaClientShape = Readonly<Record<string, readonly string[]>>;
|
|
|
64
75
|
/**
|
|
65
76
|
* What a create of each Resource cannot do without, already in core's words
|
|
66
77
|
* (`Adapter["createRequirements"]`): a column the client must write, or a
|
|
67
|
-
* required relation
|
|
68
|
-
* hold its reference
|
|
69
|
-
*
|
|
78
|
+
* required relation — which may instead be written through the scalar fields
|
|
79
|
+
* that hold its reference, read off the relation's referential edge
|
|
80
|
+
* (`references`), never restated here — and the relation's other end, through
|
|
81
|
+
* which a nested create supplies it.
|
|
70
82
|
*
|
|
71
83
|
* Read at generate time from the generated client's create inputs — the
|
|
72
84
|
* question marks on `<M>UncheckedCreateInput` and `<M>CreateInput` — and from the
|
|
@@ -76,7 +88,7 @@ export type PrismaClientShape = Readonly<Record<string, readonly string[]>>;
|
|
|
76
88
|
*/
|
|
77
89
|
export type PrismaCreateRequirementTable = NonNullable<Adapter["createRequirements"]>;
|
|
78
90
|
/** The current discovery artifact format. */
|
|
79
|
-
export declare const DISCOVERY_ARTIFACT_FORMAT =
|
|
91
|
+
export declare const DISCOVERY_ARTIFACT_FORMAT = 2;
|
|
80
92
|
/**
|
|
81
93
|
* The discovery artifact: the module `aventara-prisma7-generate` writes from
|
|
82
94
|
* your schema and generated client. Import its `discovery` export and pass it
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const DISCOVERY_ARTIFACT_FORMAT =
|
|
1
|
+
export const DISCOVERY_ARTIFACT_FORMAT = 2;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type AdapterLifecycleTrait, type AdapterRelationField, type AdapterScalarField } from "@aventara/core";
|
|
1
|
+
import { type AdapterLifecycleTrait, type AdapterRelationField, type AdapterScalarField } from "@aventara/core/internal";
|
|
2
2
|
import type { PrismaResourceSurface } from "./capability-surface.interface.js";
|
|
3
3
|
import type { PrismaAdapterModel, PrismaReferentialAction } from "./discovery-artifact.interface.js";
|
|
4
4
|
import type { PrismaSchemaField, PrismaSchemaUnknown } from "./schema-facts.interface.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LIFECYCLE_TRAITS, } from "@aventara/core";
|
|
1
|
+
import { LIFECYCLE_TRAITS, } from "@aventara/core/internal";
|
|
2
2
|
import { projectEnumBackedColumn } from "./enum.mapper.js";
|
|
3
3
|
import { mapPrismaScalarField } from "./scalar.mapper.js";
|
|
4
4
|
import { PRISMA_DEFAULT_TABLE, PRISMA_UNMATCHED_DEFAULT_TRAITS, } from "./vocabulary.dictionary.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { TransactionCapability } from "@aventara/core";
|
|
2
2
|
import type { PrismaComposedArtifact, PrismaModelComposer } from "../generate/prisma.generate.js";
|
|
3
3
|
import type { PrismaCapabilitySurface } from "./capability-surface.interface.js";
|
|
4
4
|
import type { PrismaSchemaFacts } from "./schema-facts.interface.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BUILT_IN_SCALARS, } from "@aventara/core";
|
|
1
|
+
import { BUILT_IN_SCALARS, } from "@aventara/core/internal";
|
|
2
2
|
import { deriveRelationCapabilities, deriveScalarCapabilities, } from "./capability.deriver.js";
|
|
3
3
|
import { mapPrismaEnum } from "./enum.mapper.js";
|
|
4
4
|
import { crossCheckCreateOptional, projectPrismaField, } from "./field.mapper.js";
|
|
@@ -58,12 +58,14 @@ export function discoverPrismaModel(input) {
|
|
|
58
58
|
enums,
|
|
59
59
|
resources,
|
|
60
60
|
transactions: input.transactions,
|
|
61
|
+
referenceWrites: PRISMA_REFERENCE_WRITES,
|
|
61
62
|
},
|
|
62
63
|
translation,
|
|
63
64
|
referentialActions,
|
|
64
65
|
createRequirements: composeCreateRequirements(declared, input.surface, resources),
|
|
65
66
|
};
|
|
66
67
|
}
|
|
68
|
+
const PRISMA_REFERENCE_WRITES = "uniform";
|
|
67
69
|
function composeCreateRequirements(declared, surface, resources) {
|
|
68
70
|
const table = {};
|
|
69
71
|
for (const [name, resource] of Object.entries(resources)) {
|
|
@@ -95,15 +97,13 @@ function composeCreateRequirements(declared, surface, resources) {
|
|
|
95
97
|
if (exposed.relationFields[field.name]?.createRequired !== true) {
|
|
96
98
|
continue;
|
|
97
99
|
}
|
|
98
|
-
|
|
99
|
-
if (orFields.length === 0) {
|
|
100
|
+
if (!owned.some((scalar) => requiredScalars.has(scalar))) {
|
|
100
101
|
continue;
|
|
101
102
|
}
|
|
102
103
|
const inverse = inverseOf(declared, name, field);
|
|
103
104
|
requirements.push({
|
|
104
105
|
kind: "relation",
|
|
105
106
|
relation: field.name,
|
|
106
|
-
orFields,
|
|
107
107
|
...(inverse === undefined ? {} : { inverse }),
|
|
108
108
|
});
|
|
109
109
|
}
|
|
@@ -217,6 +217,7 @@ function composeResource(input) {
|
|
|
217
217
|
field: projection.edge.field,
|
|
218
218
|
target: projection.edge.target,
|
|
219
219
|
cardinality: projection.edge.cardinality,
|
|
220
|
+
references: [...(field.relation?.fields ?? [])],
|
|
220
221
|
onDelete: projection.edge.onDelete,
|
|
221
222
|
onUpdate: projection.edge.onUpdate,
|
|
222
223
|
});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ResourceOperations, TransactionCapability } from "@aventara/core";
|
|
2
|
+
import type { AdapterResource } from "@aventara/core/internal";
|
|
2
3
|
import type { PrismaAdapterModel } from "./discovery-artifact.interface.js";
|
|
3
4
|
type DiscoveredIdentifiers = AdapterResource<PrismaAdapterModel>["identifiers"];
|
|
4
5
|
export type ResourceOperationsInput = {
|
|
@@ -201,6 +201,16 @@ function keysOfReferenced(index, node, accept) {
|
|
|
201
201
|
}
|
|
202
202
|
return memberNames(members);
|
|
203
203
|
}
|
|
204
|
+
function deleteManyTakesScalarWhere(index, node) {
|
|
205
|
+
const input = findReference(node, (n) => n.endsWith("NestedInput"));
|
|
206
|
+
if (input === null) {
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
const deleteMany = (membersOf(index, referencedName(input)) ?? []).find((member) => memberName(member) === "deleteMany");
|
|
210
|
+
return (deleteMany !== undefined &&
|
|
211
|
+
findReference(deleteMany.type, (n) => n.endsWith("ScalarWhereInput")) !==
|
|
212
|
+
null);
|
|
213
|
+
}
|
|
204
214
|
function readEnums(program, root) {
|
|
205
215
|
const source = program.getSourceFile(path.join(root, "enums.ts"));
|
|
206
216
|
if (source === undefined) {
|
|
@@ -386,6 +396,7 @@ function readRelationFields(checker, index, payload, where, create, update, incl
|
|
|
386
396
|
createRequired: create.get(name) !== undefined &&
|
|
387
397
|
create.get(name)?.questionToken === undefined,
|
|
388
398
|
updateMutations: keysOfReferenced(index, update.get(name)?.type, (n) => n.endsWith("NestedInput")),
|
|
399
|
+
scalarNestedWriteFilter: deleteManyTakesScalarWhere(index, update.get(name)?.type),
|
|
389
400
|
edgeArguments,
|
|
390
401
|
pagination: edgeArguments.filter((argument) => !NON_PAGINATION_EDGE_ARGUMENTS.has(argument)),
|
|
391
402
|
orderable: orderBy.has(name),
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { BuiltInScalar, PaginationCapability, RelationFilterCapability, RelationMutationDirective, ScalarFilterOperator, ScalarFormat, ScalarMutationDirective } from "@aventara/core";
|
|
2
|
+
import type { AdapterLifecycleTrait } from "@aventara/core/internal";
|
|
2
3
|
export type VocabularySource = "PSL" | "TYPE" | "RUN" | "DRIVER" | "CFG";
|
|
3
4
|
export type VocabularyEntry = {
|
|
4
5
|
readonly fact: string;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { AdapterModel
|
|
1
|
+
import type { AdapterModel } from "@aventara/core";
|
|
2
|
+
import type { AdapterOperationExecutor } from "@aventara/core/internal";
|
|
2
3
|
import type { PrismaResourceTranslation } from "../discovery/discovery-artifact.interface.js";
|
|
3
4
|
import { type PrismaDelegateHost, type PrismaTransactionOptions } from "../prisma-client.interface.js";
|
|
4
5
|
/** A call the executor cannot issue against the client it was given. */
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { AdapterModel
|
|
1
|
+
import type { AdapterModel } from "@aventara/core";
|
|
2
|
+
import type { AdapterOperationExecutor } from "@aventara/core/internal";
|
|
2
3
|
import type { PrismaResourceTranslation } from "../discovery/discovery-artifact.interface.js";
|
|
3
4
|
import type { PrismaDelegateHost, PrismaTransactionOptions } from "../prisma-client.interface.js";
|
|
4
5
|
export type PrismaTransactionExecutorDependencies = {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { canonicalizeJson } from "@aventara/core";
|
|
1
|
+
import { canonicalizeJson } from "@aventara/core/internal";
|
|
2
2
|
import { computeModelHash } from "../discovery/artifact.loader.js";
|
|
3
3
|
import { DISCOVERY_ARTIFACT_FORMAT, } from "../discovery/discovery-artifact.interface.js";
|
|
4
4
|
const BANNER = [
|
|
@@ -18,8 +18,9 @@ const TRANSLATION_DOC = [
|
|
|
18
18
|
const REFERENTIAL_ACTIONS_DOC = [
|
|
19
19
|
"/**",
|
|
20
20
|
" * The schema's referential actions, per Resource: the relation fields that",
|
|
21
|
-
" * declare `@relation(fields: …)`, each with
|
|
22
|
-
" * `onUpdate`. An edge under
|
|
21
|
+
" * declare `@relation(fields: …)`, each with the fields holding its reference",
|
|
22
|
+
" * (`references`) and its resolved `onDelete` and `onUpdate`. An edge under",
|
|
23
|
+
" * Resource `R` reads:",
|
|
23
24
|
" *",
|
|
24
25
|
" * deleting a `target` row does `onDelete` to rows of `R`.",
|
|
25
26
|
" *",
|
|
@@ -42,9 +43,9 @@ const CLIENT_DOC = [
|
|
|
42
43
|
const CREATE_REQUIREMENTS_DOC = [
|
|
43
44
|
"/**",
|
|
44
45
|
" * What a create of each Resource cannot do without: a field with no default,",
|
|
45
|
-
" * or a required relation, which may instead be written through
|
|
46
|
-
" *
|
|
47
|
-
" * reached through its `inverse` gets from the parent.",
|
|
46
|
+
" * or a required relation, which may instead be written through the fields",
|
|
47
|
+
" * holding its reference (its edge's `references` above) and which a nested",
|
|
48
|
+
" * create reached through its `inverse` gets from the parent.",
|
|
48
49
|
" *",
|
|
49
50
|
" * Every create is checked against it and a missing value is answered as",
|
|
50
51
|
" * `A2004`/`V1000` at its path, before the database is reached. Not part of",
|
package/dist/prisma.adapter.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { AdapterModel, OperationIdentity } from "@aventara/core";
|
|
2
2
|
import type { PrismaIdentifierAddress } from "../discovery/discovery-artifact.interface.js";
|
|
3
3
|
/** A mutation the model, the stage or the active operation does not license. */
|
|
4
4
|
export declare class PrismaMutationTranslationError extends Error {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { advertisedDirectives, } from "@aventara/core";
|
|
1
|
+
import { advertisedDirectives, } from "@aventara/core/internal";
|
|
2
2
|
import { addressIdentifier } from "./identifier.addressing.js";
|
|
3
3
|
import { emitScalarValue } from "./scalar.conversion.js";
|
|
4
4
|
export class PrismaMutationTranslationError extends Error {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { AdapterModel
|
|
1
|
+
import type { AdapterModel } from "@aventara/core";
|
|
2
|
+
import type { AdapterOperation } from "@aventara/core/internal";
|
|
2
3
|
import type { PrismaResourceTranslation } from "../discovery/discovery-artifact.interface.js";
|
|
3
4
|
import { type PrismaProjectionPlan } from "./projection.translator.js";
|
|
4
5
|
/** The `ModelAction` subset this adapter uses. See the header for the exclusions. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { AdapterModel } from "@aventara/core";
|
|
2
2
|
import type { PrismaIdentifierAddress } from "../discovery/discovery-artifact.interface.js";
|
|
3
3
|
/** An order or cursor the discovered model does not license. */
|
|
4
4
|
export declare class PrismaOrderTranslationError extends Error {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { advertisedReducers
|
|
1
|
+
import { advertisedReducers } from "@aventara/core/internal";
|
|
2
2
|
import { addressIdentifier } from "./identifier.addressing.js";
|
|
3
3
|
export class PrismaOrderTranslationError extends Error {
|
|
4
4
|
name = "PrismaOrderTranslationError";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type AdapterModel } from "@aventara/core";
|
|
2
|
+
import type { AdapterField } from "@aventara/core/internal";
|
|
2
3
|
/** A value this adapter will not convert rather than misrepresent. */
|
|
3
4
|
export declare class PrismaScalarConversionError extends Error {
|
|
4
5
|
readonly name = "PrismaScalarConversionError";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aventara/prisma7-adapter",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.0.0-rc.0",
|
|
4
4
|
"license": "SEE LICENSE IN LICENSE",
|
|
5
5
|
"description": "The Prisma 7 adapter for Aventara.",
|
|
6
6
|
"type": "module",
|
|
@@ -26,10 +26,11 @@
|
|
|
26
26
|
},
|
|
27
27
|
"files": [
|
|
28
28
|
"dist",
|
|
29
|
-
"LICENSE-ADDITIONAL-PERMISSION.md"
|
|
29
|
+
"LICENSE-ADDITIONAL-PERMISSION.md",
|
|
30
|
+
"CHANGELOG.md"
|
|
30
31
|
],
|
|
31
32
|
"dependencies": {
|
|
32
|
-
"@aventara/core": "
|
|
33
|
+
"@aventara/core": "1.0.0-rc.0"
|
|
33
34
|
},
|
|
34
35
|
"peerDependencies": {
|
|
35
36
|
"@prisma/adapter-better-sqlite3": "^7.10.0",
|
|
@@ -91,7 +92,7 @@
|
|
|
91
92
|
"typescript-6": "npm:typescript@6.0.3"
|
|
92
93
|
},
|
|
93
94
|
"scripts": {
|
|
94
|
-
"build": "node node_modules/typescript/bin/tsc -p tsconfig.json --removeComments --declaration false && node node_modules/typescript/bin/tsc -p tsconfig.json --emitDeclarationOnly && node ../../scripts/build/declaration-comments.sanitizer.ts dist",
|
|
95
|
+
"build": "node ../../scripts/build/build-output.cleaner.ts dist && node node_modules/typescript/bin/tsc -p tsconfig.json --removeComments --declaration false && node node_modules/typescript/bin/tsc -p tsconfig.json --emitDeclarationOnly && node ../../scripts/build/declaration-comments.sanitizer.ts dist",
|
|
95
96
|
"typecheck": "node node_modules/typescript/bin/tsc -p tsconfig.typecheck.json --noEmit",
|
|
96
97
|
"generate": "node node_modules/typescript/bin/tsc -p tsconfig.generate.json && node .generate/generate/discovery.generate.js && prisma generate --schema src/discovery/__fixtures__/ignore.prisma",
|
|
97
98
|
"db:push": "prisma db push --config prisma.config.sqlite.ts && sh -c 'if [ -n \"$AVENTARA_TEST_POSTGRES_URL\" ]; then prisma db push --config prisma.config.postgres.ts; else echo \"AVENTARA_TEST_POSTGRES_URL is unset: skipping the PostgreSQL schema push\"; fi'",
|