@aventara/prisma7-adapter 0.1.0-pilot.3 → 0.1.0-pilot.4
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/README.md +22 -22
- package/dist/discovery/artifact.loader.d.ts +2 -7
- package/dist/discovery/artifact.loader.js +4 -0
- package/dist/discovery/capability-surface.interface.d.ts +2 -66
- package/dist/discovery/capability.deriver.d.ts +2 -47
- package/dist/discovery/discovery-artifact.interface.d.ts +34 -155
- package/dist/discovery/discovery-artifact.interface.js +1 -1
- package/dist/discovery/enum.mapper.d.ts +0 -24
- package/dist/discovery/field.mapper.d.ts +3 -114
- package/dist/discovery/field.mapper.js +6 -6
- package/dist/discovery/identifier.mapper.d.ts +4 -84
- package/dist/discovery/model.discoverer.d.ts +2 -69
- package/dist/discovery/operations.deriver.d.ts +0 -36
- package/dist/discovery/scalar.mapper.d.ts +1 -32
- package/dist/discovery/scalar.mapper.js +2 -2
- package/dist/discovery/schema-facts.interface.d.ts +3 -83
- package/dist/discovery/schema.reader.d.ts +0 -133
- package/dist/discovery/types.reader.d.ts +1 -9
- package/dist/discovery/types.reader.js +7 -7
- package/dist/discovery/vocabulary.dictionary.d.ts +6 -133
- package/dist/discovery/vocabulary.dictionary.js +2 -2
- package/dist/errors/error.normalizer.d.ts +5 -168
- package/dist/errors/prisma-error.reader.d.ts +1 -93
- package/dist/execution/first-variant.emulator.d.ts +5 -28
- package/dist/execution/operation.executor.d.ts +1 -62
- package/dist/execution/result.shaper.d.ts +0 -56
- package/dist/execution/transaction.executor.d.ts +0 -98
- package/dist/generate/artifact.emitter.d.ts +1 -35
- package/dist/generate/artifact.emitter.js +26 -43
- package/dist/generate/declared-support.reader.d.ts +0 -20
- package/dist/generate/discovery.cli.d.ts +0 -4
- package/dist/generate/existence.gate.d.ts +3 -37
- package/dist/generate/index.d.ts +4 -57
- package/dist/generate/prisma-cli.resolver.d.ts +0 -22
- package/dist/generate/prisma.generate.d.ts +14 -83
- package/dist/generate/reader-crosscheck.d.ts +3 -88
- package/dist/generate/reader-crosscheck.js +4 -4
- package/dist/prisma-client.interface.d.ts +5 -25
- package/dist/prisma.adapter.d.ts +21 -22
- package/dist/provider/provider-profile.d.ts +6 -14
- package/dist/translation/identifier.addressing.d.ts +0 -38
- package/dist/translation/mutation.translator.d.ts +5 -51
- package/dist/translation/operation.translator.d.ts +1 -102
- package/dist/translation/order-pagination.translator.d.ts +1 -47
- package/dist/translation/projection.translator.d.ts +1 -46
- package/dist/translation/scalar.conversion.d.ts +0 -64
- package/dist/translation/where.translator.d.ts +0 -52
- package/package.json +2 -2
|
@@ -1,61 +1,5 @@
|
|
|
1
1
|
import type { AdapterModel } from "@aventara/core";
|
|
2
2
|
import type { PrismaProjectionPlan } from "../translation/projection.translator.js";
|
|
3
|
-
/**
|
|
4
|
-
* **The envelope is the adapter's to build, not core's.** `output-validator.ts`
|
|
5
|
-
* accepts exactly `["count"]` or `["data","count"]` for a relation whose plan
|
|
6
|
-
* carries the `$count` reducer, and rejects any key outside the projection — which
|
|
7
|
-
* includes Prisma's own `_count` **[CORE, runtime/output-validator.ts]**. So
|
|
8
|
-
* Prisma's answer `{ id, posts: [...], _count: { posts: 3 } }` must leave here as
|
|
9
|
-
* `{ id, posts: { data: [...], count: 3 } }`, with `_count` gone.
|
|
10
|
-
*
|
|
11
|
-
* | nested select | shape | this module | |---|---|---| | `["id","title"]` | array
|
|
12
|
-
* | returns Prisma's rows, values converted | | `["$count"]` | `{ count }` | reads
|
|
13
|
-
* `_count.<edge>`; no rows were selected | | `["id","$count"]` | `{ data, count }`
|
|
14
|
-
* | pairs the rows with `_count.<edge>` |
|
|
15
|
-
*
|
|
16
|
-
* The same validator that rejects a spare key also checks every projected scalar's
|
|
17
|
-
* runtime form, and a decimal must be core's own `Decimal` **[CORE,
|
|
18
|
-
* output-validator.ts → `normalizeScalarFieldValue`]**. Prisma returns an object
|
|
19
|
-
* whose constructor is `Decimal2`, so before this conversion existed every read of
|
|
20
|
-
* a decimal column failed core's output validation and the caller was told `A3000`
|
|
21
|
-
* — measured through `createFramework(...).execute(...)` on both engines
|
|
22
|
-
* (2026-10-02). The conversion itself belongs to
|
|
23
|
-
* `translation/scalar.conversion.ts`, the one table that knows how each scalar
|
|
24
|
-
* crosses the boundary in either direction; this module owns only *which field a
|
|
25
|
-
* returned value belongs to*.
|
|
26
|
-
*
|
|
27
|
-
* **It answers that from the discovered model, not from the value.** The shaper
|
|
28
|
-
* walks a row against `AdapterModel`: a key that names a scalar field converts
|
|
29
|
-
* under that field's scalar, a key that names a relation recurses into the edge's
|
|
30
|
-
* TARGET Resource, and a key the model does not know passes through for core to
|
|
31
|
-
* accept or reject. Sniffing the runtime shape instead would be wrong in both
|
|
32
|
-
* directions at once — a `Decimal2` and a `Json` document are both objects, and a
|
|
33
|
-
* `Json` column holding the string `"12.5"` is indistinguishable from a decimal
|
|
34
|
-
* string, so the first `Json` column holding numeric text would quietly come back
|
|
35
|
-
* as a `Decimal`.
|
|
36
|
-
*
|
|
37
|
-
* The plan is still what places a `$count` envelope, and only that. The two are
|
|
38
|
-
* complementary and neither can do the other's job: the plan records only the
|
|
39
|
-
* edges that need reshaping (so it cannot drive a walk that must reach every
|
|
40
|
-
* scalar), and the model does not know which edges requested a reducer (so it
|
|
41
|
-
* cannot place an envelope).
|
|
42
|
-
*
|
|
43
|
-
* **Cardinality is never assumed.** `AdapterOperation` carries no plan, and the
|
|
44
|
-
* arguments the plan is reconstructed from do not say whether an edge is to-one or
|
|
45
|
-
* to-many. So recursion is driven by the value Prisma actually returned — an array
|
|
46
|
-
* is shaped elementwise, a record is shaped as one row, `null` passes through —
|
|
47
|
-
* which is total without knowing the cardinality at all.
|
|
48
|
-
*
|
|
49
|
-
* Nothing here invents a number. A missing or non-numeric `_count` entry for a
|
|
50
|
-
* planned reducer is a translation/driver disagreement, and it raises rather than
|
|
51
|
-
* defaulting to `0`: a wrong count that validates is worse than a loud failure,
|
|
52
|
-
* because core would forward it to the caller as fact.
|
|
53
|
-
*
|
|
54
|
-
* **Nothing Prisma returned is written into.** A row is copied only when some
|
|
55
|
-
* value in it actually changed, so a result needing no conversion and no envelope
|
|
56
|
-
* comes back by identity.
|
|
57
|
-
*/
|
|
58
|
-
/** What a Prisma result must be read against: the model, the Resource, the plan. */
|
|
59
3
|
export type PrismaRowShaping = {
|
|
60
4
|
/** The discovered model: field kinds, scalars, relation targets. */
|
|
61
5
|
readonly model: AdapterModel;
|
|
@@ -1,110 +1,12 @@
|
|
|
1
1
|
import type { AdapterModel, AdapterOperationExecutor } from "@aventara/core";
|
|
2
2
|
import type { PrismaResourceTranslation } from "../discovery/discovery-artifact.interface.js";
|
|
3
3
|
import type { PrismaDelegateHost, PrismaTransactionOptions } from "../prisma-client.interface.js";
|
|
4
|
-
/**
|
|
5
|
-
* The body is one `client.$transaction(async (tx) => work(scopedExecutorFor(tx)),
|
|
6
|
-
* options)`. Everything interesting about this module is what it deliberately does
|
|
7
|
-
* **not** do, so each omission is recorded here rather than left to be
|
|
8
|
-
* rediscovered.
|
|
9
|
-
*
|
|
10
|
-
* Prisma's array form — `$transaction` applied to a list of prepared calls —
|
|
11
|
-
* cannot honour a plan at all. An Aventara plan is **sequential by contract**:
|
|
12
|
-
* operation *n* may carry a `$ref` resolved from operation *n − 1*'s final data,
|
|
13
|
-
* and core resolves it between calls, so the second call's arguments do not exist
|
|
14
|
-
* until the first has answered. The array form takes every call up front. It is
|
|
15
|
-
* therefore a framework invariant and not a preference, and it is protected twice:
|
|
16
|
-
* {@link PrismaDelegateHost} declares `$transaction` in its callback form only, so
|
|
17
|
-
* the array overload is not *representable* through the seam this adapter holds,
|
|
18
|
-
* and `transaction.executor.spec.ts` asserts both that every call this adapter
|
|
19
|
-
* makes passes a function and that the array form's own opening token occurs
|
|
20
|
-
* nowhere in `src` (that spec assembles the token rather than writing it, for the
|
|
21
|
-
* same reason this sentence does not quote it).
|
|
22
|
-
*
|
|
23
|
-
* `scopedExecutorFor` closes over the callback's `tx` and nothing else, so no plan
|
|
24
|
-
* operation can reach the client this module was constructed with — there is no
|
|
25
|
-
* path to it from the value core is handed.
|
|
26
|
-
*
|
|
27
|
-
* Core throws a private frozen abort sentinel out of `work` after it has recorded
|
|
28
|
-
* a failing operation, and recognises the rejection **by `===` alone**.
|
|
29
|
-
*
|
|
30
|
-
* **Induced, not assumed** (2026-10-02, PostgreSQL 18): a write inside a
|
|
31
|
-
* transaction, the backend terminated from a second connection, a frozen sentinel
|
|
32
|
-
* thrown from the callback. Prisma's `ROLLBACK` failed — `prisma:client rollback
|
|
33
|
-
* attempt 1/1 failed: '{}'` appears under `DEBUG=prisma*` — and the value the
|
|
34
|
-
* caller received was still that sentinel, by identity, carrying nothing about the
|
|
35
|
-
* rollback at all. Two consequences, both deliberate: core's `A3002`-on-rollback-
|
|
36
|
-
* failure branch is **unreachable with this adapter** (it stays for adapters whose
|
|
37
|
-
* provider reports the failure), and this adapter never claims a rollback
|
|
38
|
-
* succeeded, because it cannot observe that it did. A commit failure is different:
|
|
39
|
-
* it is thrown from inside the same `try` and rejects like a callback throw.
|
|
40
|
-
*
|
|
41
|
-
* They are provider concepts: core's `Adapter.transaction(work)` carries no
|
|
42
|
-
* options and must not grow any, so they are set once at `createPrismaAdapter({
|
|
43
|
-
* transactionOptions })` and are not part of Aventara's public configuration.
|
|
44
|
-
* Prisma's own defaults stand when they are absent — `maxWait` 2000 ms, `timeout`
|
|
45
|
-
* 5000 ms **[PKG, `runtime/client.d.ts`]** — and the supported isolation levels
|
|
46
|
-
* come from the provider profile, which discovered them, rather than from a table
|
|
47
|
-
* written here.
|
|
48
|
-
*
|
|
49
|
-
* The options are **not** forwarded to the scoped executor. At `"transaction"`
|
|
50
|
-
* scope `operation.executor.ts` never opens a transaction, so an option passed
|
|
51
|
-
* there would be dead configuration that reads as if it did something.
|
|
52
|
-
*
|
|
53
|
-
* Induced against PostgreSQL 18 on `@prisma/client` 7.10.0, 2026-10-02 (the
|
|
54
|
-
* assertions live in `conformance/postgres.conformance.spec.ts`):
|
|
55
|
-
*
|
|
56
|
-
* ```text
|
|
57
|
-
* timeout 1 ms, a query issued after expiry
|
|
58
|
-
* P2028 meta = { modelName: "Author", operation: "query", timeout: 1, timeTaken: 66 }
|
|
59
|
-
* timeout 1 ms, no query after the sleep — the COMMIT is what fails
|
|
60
|
-
* P2028 meta = { operation: "commit", timeout: 1, timeTaken: 62 }
|
|
61
|
-
* maxWait 1 ms with the one connection already held by another transaction
|
|
62
|
-
* P2028 meta = {} <- EMPTY
|
|
63
|
-
* isolationLevel: "Bogus"
|
|
64
|
-
* P2023 meta = { providedIsolationLevel: "Bogus" } <- NOT P2028
|
|
65
|
-
* ```
|
|
66
|
-
*
|
|
67
|
-
* The table above is the `isolationLevel` arm only as far as a **malformed** level
|
|
68
|
-
* goes. A level that IS one of Prisma's five and is simply unsupported by the
|
|
69
|
-
* provider reaches the transaction manager and raises a `meta`-carrying `P2028` of
|
|
70
|
-
* its own, measured on both engines (2026-10-02):
|
|
71
|
-
*
|
|
72
|
-
* ```text
|
|
73
|
-
* isolationLevel: "Snapshot" (a SQL Server level; one of Prisma's five)
|
|
74
|
-
* P2028 meta = { isolationLevel: "SNAPSHOT" }
|
|
75
|
-
* ```
|
|
76
|
-
*
|
|
77
|
-
* So of the seven `P2028` classes in 7.10.0 — `TransactionManagerError` plus
|
|
78
|
-
* `nt`/`un`/`cn`/`fr`/`pn`/`Me`/`dn` **[PKG, `runtime/client.js`]** — the
|
|
79
|
-
* separable-by-`meta` set is **three**: the transaction-timeout expiry carries `{
|
|
80
|
-
* operation, timeout, timeTaken }`, the unsupported isolation level carries `{
|
|
81
|
-
* isolationLevel }`, and the acquisition timeout carries nothing and is separable
|
|
82
|
-
* *by* that emptiness from the other two. An earlier revision of this comment
|
|
83
|
-
* withdrew the claim outright; it was measured on the wrong input, and
|
|
84
|
-
* `conformance/postgres.conformance.spec.ts` and
|
|
85
|
-
* `conformance/sqlite.conformance.spec.ts` both assert the corrected fact.
|
|
86
|
-
*
|
|
87
|
-
* A `P2028` that ends the transaction rejects out of `$transaction` itself, is not
|
|
88
|
-
* core's sentinel, and core's own `infrastructureFailure` answers `A3002`. A
|
|
89
|
-
* `P2028` raised by a *delegate call* inside the callback is a different route: it
|
|
90
|
-
* is unclassified by the closed table, so core's `AdapterBoundary` attributes
|
|
91
|
-
* `A3001` to that operation. `A3002` is therefore the answer for the failure that
|
|
92
|
-
* ends the transaction, not a uniform answer for the code — recorded here because
|
|
93
|
-
* the difference is invisible from the table alone.
|
|
94
|
-
*/
|
|
95
4
|
export type PrismaTransactionExecutorDependencies = {
|
|
96
|
-
/** The client the transaction is opened on: the application's own. */
|
|
97
5
|
readonly client: PrismaDelegateHost;
|
|
98
6
|
readonly model: AdapterModel;
|
|
99
7
|
/** The generate-time translation table (Prisma addressing per Resource). */
|
|
100
8
|
readonly translation: Readonly<Record<string, PrismaResourceTranslation>>;
|
|
101
|
-
/** Adapter-owned, never Aventara public configuration. */
|
|
102
9
|
readonly transactionOptions?: PrismaTransactionOptions;
|
|
103
10
|
};
|
|
104
|
-
/**
|
|
105
|
-
* `Adapter<M>["transaction"]` without the optionality: the adapter mounts it
|
|
106
|
-
* exactly when the discovered model declares `transactions: "interactive"`, so the
|
|
107
|
-
* function itself is total.
|
|
108
|
-
*/
|
|
109
11
|
export type PrismaTransactionRunner<M extends AdapterModel> = <T>(work: (executor: AdapterOperationExecutor<M>) => Promise<T>) => Promise<T>;
|
|
110
12
|
export declare function createPrismaTransactionExecutor<M extends AdapterModel>(dependencies: PrismaTransactionExecutorDependencies): PrismaTransactionRunner<M>;
|
|
@@ -1,40 +1,6 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type PrismaAdapterModel, type PrismaClientShape, type PrismaCreateRequirementTable, type PrismaReferentialActionTable, type PrismaTranslationTable } from "../discovery/discovery-artifact.interface.js";
|
|
2
2
|
import type { PrismaProvider } from "../provider/provider-profile.js";
|
|
3
|
-
/**
|
|
4
|
-
* It predates the ADR and loses to it, for a reason the ADR states plainly:
|
|
5
|
-
* `resolveJsonModule` widens `"string"` to `string`, so a JSON model carries no
|
|
6
|
-
* literals, and carrying them would take a second emitted `.d.ts` beside the data
|
|
7
|
-
* — two emissions from one source, which can drift. One module written `as const
|
|
8
|
-
* satisfies AdapterModel` makes the value and the type the same expression, so
|
|
9
|
-
* drift is not merely detectable but unrepresentable.
|
|
10
|
-
*
|
|
11
|
-
* The emitted module is still passive, serializable, introspectable, hashable and
|
|
12
|
-
* free of runtime callbacks. It contains three `const` bindings and no executable
|
|
13
|
-
* statement; `discovery.model` and `discovery.translation` *reference* their
|
|
14
|
-
* bindings rather than restating them, so there is exactly one representation of
|
|
15
|
-
* each half in the file.
|
|
16
|
-
*
|
|
17
|
-
* **Three halves, and the seam between them is deliberate.** `model` is what core
|
|
18
|
-
* consumes: canonicalized, digested into `modelHash`, and compiled into the
|
|
19
|
-
* Contract. `translation` is Prisma addressing — which key a `WhereUniqueInput`
|
|
20
|
-
* answers to for each identifier. `referentialActions` is what deleting a parent
|
|
21
|
-
* row does to its children, resolved. Both of the latter sit BESIDE the model
|
|
22
|
-
* precisely because they must not reach the hash: a `@@unique(name:)` rename
|
|
23
|
-
* carries no semantic content, and inside the model it would change the Contract
|
|
24
|
-
* identity and force every generated client to be regenerated for nothing; a
|
|
25
|
-
* referential action is not part of the model at all, and inside it the action
|
|
26
|
-
* would reach the compiled Contract and the ClientContract, which have no word for
|
|
27
|
-
* one.
|
|
28
|
-
*
|
|
29
|
-
* **Determinism.** The model text is the canonical JSON core already uses for
|
|
30
|
-
* Contract identity, re-indented — not `JSON.stringify` over whatever key order
|
|
31
|
-
* the readers happened to build. So two generate runs over one schema emit
|
|
32
|
-
* byte-identical modules, and `modelHash` is a digest of exactly the bytes the
|
|
33
|
-
* module carries, computed by the same `computeModelHash` the runtime loader
|
|
34
|
-
* checks it with. One hash function, one canonicalization, both halves.
|
|
35
|
-
*/
|
|
36
3
|
export type PrismaArtifactEmission = {
|
|
37
|
-
/** e.g. `"7.10.0"`; only the major is fenced at load. */
|
|
38
4
|
readonly prismaVersion: string;
|
|
39
5
|
readonly provider: PrismaProvider;
|
|
40
6
|
readonly model: PrismaAdapterModel;
|
|
@@ -1,48 +1,32 @@
|
|
|
1
1
|
import { canonicalizeJson } from "@aventara/core";
|
|
2
2
|
import { computeModelHash } from "../discovery/artifact.loader.js";
|
|
3
|
+
import { DISCOVERY_ARTIFACT_FORMAT, } from "../discovery/discovery-artifact.interface.js";
|
|
3
4
|
const BANNER = [
|
|
4
|
-
"// biome-ignore-all format: generated output
|
|
5
|
+
"// biome-ignore-all format: generated output",
|
|
5
6
|
"// biome-ignore-all lint: generated output",
|
|
6
7
|
"/* !!! Generated by @aventara/prisma7-adapter's generate step. Do not edit. !!! */",
|
|
7
8
|
"/* Regenerate with `aventara-prisma7-generate`. */",
|
|
8
9
|
];
|
|
9
10
|
const TRANSLATION_DOC = [
|
|
10
11
|
"/**",
|
|
11
|
-
" * Prisma addressing
|
|
12
|
-
" *",
|
|
13
|
-
" * `
|
|
14
|
-
" *
|
|
15
|
-
" * a compound, or `@@id`/`@@unique`'s `name:` where one replaces it. Computed",
|
|
16
|
-
' * once here and MATCHED at runtime, never re-derived — `members.join("_")` is',
|
|
17
|
-
" * wrong for every named criterion. A key wraps its members iff `members.length",
|
|
18
|
-
" * > 1`.",
|
|
19
|
-
" *",
|
|
20
|
-
" * This half is adapter-private. It is excluded from `modelHash` by",
|
|
21
|
-
" * construction, so a DB-side rename never moves the Contract identity.",
|
|
12
|
+
" * Prisma addressing per Resource: for each identifier, the key a",
|
|
13
|
+
" * `WhereUniqueInput` accepts — the field name for a single column, the members",
|
|
14
|
+
" * joined with `_` for a compound, or the `name:` of `@@id`/`@@unique` where",
|
|
15
|
+
" * one is given. Not part of `modelHash`.",
|
|
22
16
|
" */",
|
|
23
17
|
];
|
|
24
18
|
const REFERENTIAL_ACTIONS_DOC = [
|
|
25
19
|
"/**",
|
|
26
|
-
" * The
|
|
27
|
-
" *",
|
|
28
|
-
" *
|
|
29
|
-
" * ones that declare `@relation(fields: …)`, which is the only side PSL lets",
|
|
30
|
-
" * carry an action. Each edge reads in ONE direction, and reversing it is",
|
|
31
|
-
" * silent:",
|
|
20
|
+
" * The schema's referential actions, per Resource: the relation fields that",
|
|
21
|
+
" * declare `@relation(fields: …)`, each with its resolved `onDelete` and",
|
|
22
|
+
" * `onUpdate`. An edge under Resource `R` reads:",
|
|
32
23
|
" *",
|
|
33
|
-
" * deleting a `target` row does `onDelete` to rows of
|
|
24
|
+
" * deleting a `target` row does `onDelete` to rows of `R`.",
|
|
34
25
|
" *",
|
|
35
|
-
' * So "what does deleting an `X` do?" is answered by
|
|
36
|
-
' *
|
|
37
|
-
" *
|
|
38
|
-
" *",
|
|
39
|
-
" * Both members are resolved: an absent PSL argument is not a third state but",
|
|
40
|
-
" * Prisma's measured effective default (`set-null` where every foreign-key",
|
|
41
|
-
" * scalar is optional, `restrict` otherwise, `cascade` on update). An action the",
|
|
42
|
-
" * reader cannot name fails the generate step instead of reaching this table.",
|
|
43
|
-
" *",
|
|
44
|
-
" * Excluded from `modelHash` by construction: the hash digests the model, and a",
|
|
45
|
-
" * referential action is not part of the model.",
|
|
26
|
+
' * So "what does deleting an `X` do?" is answered by every edge whose',
|
|
27
|
+
' * `target` is `"X"`, under the Resource that holds it. An action the schema',
|
|
28
|
+
" * leaves out is Prisma's default: `set-null` where every foreign-key field is",
|
|
29
|
+
" * optional, `restrict` otherwise, `cascade` on update. Not part of `modelHash`.",
|
|
46
30
|
" */",
|
|
47
31
|
];
|
|
48
32
|
const CLIENT_DOC = [
|
|
@@ -51,8 +35,8 @@ const CLIENT_DOC = [
|
|
|
51
35
|
" * delegate for, and that model's field references (`prisma.<model>.fields`).",
|
|
52
36
|
" *",
|
|
53
37
|
" * `createPrismaAdapter` reads the same facts off the client it is given and",
|
|
54
|
-
" * refuses to start when they differ
|
|
55
|
-
" * regenerated without this artifact.
|
|
38
|
+
" * refuses to start when they differ: the schema changed and the client was",
|
|
39
|
+
" * regenerated without this artifact. Not part of `modelHash`.",
|
|
56
40
|
" */",
|
|
57
41
|
];
|
|
58
42
|
const CREATE_REQUIREMENTS_DOC = [
|
|
@@ -62,21 +46,15 @@ const CREATE_REQUIREMENTS_DOC = [
|
|
|
62
46
|
" * the scalar fields holding its reference — and which a nested create",
|
|
63
47
|
" * reached through its `inverse` gets from the parent.",
|
|
64
48
|
" *",
|
|
65
|
-
" *
|
|
66
|
-
" *
|
|
67
|
-
" *
|
|
49
|
+
" * Every create is checked against it and a missing value is answered as",
|
|
50
|
+
" * `A2004`/`V1000` at its path, before the database is reached. Not part of",
|
|
51
|
+
" * `modelHash`.",
|
|
68
52
|
" */",
|
|
69
53
|
];
|
|
70
54
|
const MODEL_DOC = [
|
|
71
55
|
"/**",
|
|
72
|
-
" *
|
|
73
|
-
" *
|
|
74
|
-
" *",
|
|
75
|
-
" * `as const satisfies AdapterModel` is load-bearing. `as const` keeps every",
|
|
76
|
-
" * resource key, field key and enum member a literal type, which is what",
|
|
77
|
-
" * `EffectiveFieldKey` narrows on downstream; `satisfies` checks the shape",
|
|
78
|
-
" * without widening it. Drop either half and the model still *runs* while",
|
|
79
|
-
" * every narrowing keyed on it silently degrades to `string`.",
|
|
56
|
+
" * What the schema and the generated client agreed on: the model Aventara",
|
|
57
|
+
" * compiles its Contracts from.",
|
|
80
58
|
" */",
|
|
81
59
|
];
|
|
82
60
|
const DISCOVERY_DOC = [
|
|
@@ -109,6 +87,11 @@ export async function emitDiscoveryArtifactModule(emission) {
|
|
|
109
87
|
"",
|
|
110
88
|
...DISCOVERY_DOC,
|
|
111
89
|
"export const discovery = {",
|
|
90
|
+
"\t/**",
|
|
91
|
+
"\t * The artifact's format. A TypeScript error naming this property means this",
|
|
92
|
+
"\t * file is out of date: regenerate it.",
|
|
93
|
+
"\t */",
|
|
94
|
+
`\tregenerate_with_aventara_prepare: ${DISCOVERY_ARTIFACT_FORMAT},`,
|
|
112
95
|
`\tprismaVersion: ${JSON.stringify(emission.prismaVersion)},`,
|
|
113
96
|
`\tprovider: ${JSON.stringify(emission.provider)},`,
|
|
114
97
|
`\tmodelHash: ${JSON.stringify(modelHash)},`,
|
|
@@ -1,18 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* What this adapter **declares** it supports, read from its own manifest — the one
|
|
3
|
-
* place the fact is stated.
|
|
4
|
-
*
|
|
5
|
-
* The generate step needs two of those facts at run time: the `prisma` range, to
|
|
6
|
-
* decide whether a `prisma` CLI it found may run, and the `typescript` range, to
|
|
7
|
-
* name in the sentence that refuses a compiler with no classic API. Both are
|
|
8
|
-
* `peerDependencies` entries. Reading them here rather than restating them as
|
|
9
|
-
* literals is what keeps the refusal sentences, the version check and the
|
|
10
|
-
* published manifest from drifting apart.
|
|
11
|
-
*
|
|
12
|
-
* The manifest is two directories up from this module wherever it runs:
|
|
13
|
-
* `src/generate/` under the specs, `dist/generate/` in a consumer's install,
|
|
14
|
-
* `.generate/generate/` under this package's own `generate` script.
|
|
15
|
-
*/
|
|
16
1
|
export type DeclaredSupport = {
|
|
17
2
|
/** `peerDependencies.prisma`: the Prisma CLI versions the readers were written against. */
|
|
18
3
|
readonly prisma: string;
|
|
@@ -24,10 +9,5 @@ export declare function readDeclaredSupport(): DeclaredSupport;
|
|
|
24
9
|
* Whether `version` satisfies `range`, for the range forms a peer declaration
|
|
25
10
|
* here uses: space-separated comparators (`>=5.5.0 <7`), each `^`, `>=`, `>`,
|
|
26
11
|
* `<=`, `<`, `=` or bare, with missing minor and patch read as `0`.
|
|
27
|
-
*
|
|
28
|
-
* Only a plain release can satisfy: a pre-release (`8.0.0-rc.20`) never does,
|
|
29
|
-
* which is semver's own rule for a range whose comparators carry no pre-release
|
|
30
|
-
* tag. A range in any other form is a defect in this package's manifest, so it
|
|
31
|
-
* throws rather than answering a guess.
|
|
32
12
|
*/
|
|
33
13
|
export declare function satisfiesDeclaredRange(version: string, range: string): boolean;
|
|
@@ -9,10 +9,6 @@ export type PrismaGenerateCliOptions = {
|
|
|
9
9
|
/**
|
|
10
10
|
* The flags, parsed. Exported so a case can drive it without a child process:
|
|
11
11
|
* the parse is the only judgement this file makes, and the rest is the step's.
|
|
12
|
-
*
|
|
13
|
-
* `--flag value` only. `--flag=value` is deliberately not accepted, because
|
|
14
|
-
* accepting both spellings means two code paths over one fact for a binary whose
|
|
15
|
-
* entire surface is five required flags.
|
|
16
12
|
*/
|
|
17
13
|
export declare function parsePrismaGenerateArguments(argv: readonly string[]): PrismaGenerateCliOptions;
|
|
18
14
|
/**
|
|
@@ -1,50 +1,16 @@
|
|
|
1
1
|
import type { PrismaCapabilitySurface } from "../discovery/capability-surface.interface.js";
|
|
2
2
|
import type { PrismaSchemaFacts, PrismaSchemaSite } from "../discovery/schema-facts.interface.js";
|
|
3
|
-
/**
|
|
4
|
-
* An entity enters the `AdapterModel` iff the 🟢 generated types expose it. The
|
|
5
|
-
* gate is strictly stronger than any attribute list: it catches `@ignore`,
|
|
6
|
-
* `@@ignore`, preview-feature exclusions, provider drops and `Unsupported(…)`
|
|
7
|
-
* columns with no special case for any of them, because all of them show up the
|
|
8
|
-
* same way — as a name PSL declares and the client does not carry
|
|
9
|
-
* (`Unsupported(…)` confirmed absent from `$Payload.scalars` and from `FieldRefs`
|
|
10
|
-
* at 7.10.0 **[RUN8]**).
|
|
11
|
-
*
|
|
12
|
-
* `@ignore` and `@@ignore` are parsed **anyway**, and that is this module's whole
|
|
13
|
-
* subtlety. They do not drive the gate — the types do. They exist so the gate's
|
|
14
|
-
* report can say *why* an entity is absent rather than emitting the useless
|
|
15
|
-
* "present in schema, absent from client", and so the two outcomes can be told
|
|
16
|
-
* apart:
|
|
17
|
-
*
|
|
18
|
-
* - **Explained** — PSL itself instructed the exclusion. Recorded, reported, and
|
|
19
|
-
* **not fatal**. `@ignore` is a documented Prisma instruction with a deliberate
|
|
20
|
-
* author behind it; stopping the build on it would leave the developer no remedy
|
|
21
|
-
* but to delete the instruction, and an error with no remedy is a defect rather
|
|
22
|
-
* than a fence.
|
|
23
|
-
* - **Unexplained** — nothing in the schema accounts for the absence. **Fatal.**
|
|
24
|
-
* Emitting the entity would hand the framework a Resource the adapter can never
|
|
25
|
-
* execute against; omitting it silently would ship a model that is quietly
|
|
26
|
-
* missing something the developer wrote.
|
|
27
|
-
*
|
|
28
|
-
* This module implements the split above, which is the only reading under which
|
|
29
|
-
* the stated *reason* for the error — "otherwise the adapter hands the framework a
|
|
30
|
-
* Resource it can never execute against" — survives: once the entity is excluded,
|
|
31
|
-
* no such Resource is handed over, and what remains to decide is only whether to
|
|
32
|
-
* stop the build. It is worth stopping for the absence nobody asked for.)
|
|
33
|
-
*
|
|
34
|
-
* The reverse direction — a resource the types expose and PSL does not declare —
|
|
35
|
-
* is a reader inconsistency rather than an existence question, and belongs to
|
|
36
|
-
* `reader-crosscheck.ts`. This module does not answer it.
|
|
37
|
-
*/
|
|
38
3
|
export type PrismaAbsenceKind = "model" | "field";
|
|
39
4
|
/** What PSL said, when PSL said anything. */
|
|
40
5
|
export type PrismaAbsenceExplanation = "@ignore" | "@@ignore";
|
|
6
|
+
/** A schema model or field that was left out because the schema says to ignore it. */
|
|
41
7
|
export type PrismaEntityAbsence = {
|
|
42
8
|
readonly kind: PrismaAbsenceKind;
|
|
43
|
-
/**
|
|
9
|
+
/** The model or field, as `Model` or `Model.field`. */
|
|
44
10
|
readonly entity: string;
|
|
45
11
|
readonly explanation: PrismaAbsenceExplanation | null;
|
|
46
12
|
readonly site: PrismaSchemaSite;
|
|
47
|
-
/**
|
|
13
|
+
/** A sentence describing the absence. */
|
|
48
14
|
readonly message: string;
|
|
49
15
|
};
|
|
50
16
|
export type PrismaExistenceGateResult = {
|
package/dist/generate/index.d.ts
CHANGED
|
@@ -1,59 +1,11 @@
|
|
|
1
1
|
import type { PrismaDriver, PrismaProvider } from "../provider/provider-profile.js";
|
|
2
2
|
import type { PrismaGenerateResult, PrismaGenerateToolchain } from "./prisma.generate.js";
|
|
3
|
-
/**
|
|
4
|
-
* # Why a second entry rather than a second package or a wider `"."`
|
|
5
|
-
*
|
|
6
|
-
* The runtime entry (`"."`) depends on `@aventara/core` and the caller's own
|
|
7
|
-
* generated client, and on nothing else. The generate path needs `typescript` (the
|
|
8
|
-
* types reader builds a real TypeScript program over the generated tree) and
|
|
9
|
-
* `prisma` (the step runs `prisma generate` itself, so that both sources describe
|
|
10
|
-
* one instant). Those two are declared as **optional peer dependencies**, not as
|
|
11
|
-
* dependencies, and the split is what keeps the plan's guarantee that *no
|
|
12
|
-
* compiler, no parser and no Prisma tooling enters the deployed runtime*: a
|
|
13
|
-
* consumer who imports only `"."` never loads a module that names either, and an
|
|
14
|
-
* optional peer is not installed on their behalf.
|
|
15
|
-
*
|
|
16
|
-
* The published build therefore carries both halves and the `exports` map is what
|
|
17
|
-
* separates them. Nothing reachable from `"."` imports anything under `generate/`;
|
|
18
|
-
* `artifact.loader.spec.ts` asserts that from the import graph rather than from
|
|
19
|
-
* this paragraph.
|
|
20
|
-
*
|
|
21
|
-
* # What this entry is for
|
|
22
|
-
*
|
|
23
|
-
* Producing the discovery artifact `createPrismaAdapter({ discovery })` requires,
|
|
24
|
-
* from the consumer's own `schema.prisma` and their own generated client. The
|
|
25
|
-
* `aventara-prisma7-generate` binary (`discovery.cli.ts`) is this function with an
|
|
26
|
-
* argument parser in front of it; this module is the same thing for a consumer who
|
|
27
|
-
* already has a build script and would rather call it.
|
|
28
|
-
*
|
|
29
|
-
* Everything the step itself exposes is re-exported, because the seams are the
|
|
30
|
-
* point: a consumer with an unusual toolchain can supply their own {@link
|
|
31
|
-
* PrismaGenerateToolchain}, and one with their own composition rules can call
|
|
32
|
-
* {@link runPrismaGenerateStep} directly.
|
|
33
|
-
*/
|
|
34
3
|
export { createPrismaModelComposer, PrismaModelCompositionError, } from "../discovery/model.discoverer.js";
|
|
35
4
|
export type { PrismaEntityAbsence } from "./existence.gate.js";
|
|
36
5
|
export type { PrismaComposedArtifact, PrismaGenerateRequest, PrismaGenerateResult, PrismaGenerateToolchain, PrismaModelComposer, } from "./prisma.generate.js";
|
|
37
6
|
export { createPrismaGenerateToolchain, PINNED_PRISMA_MAJOR, PrismaGenerateStepError, runPrismaGenerateStep, } from "./prisma.generate.js";
|
|
38
7
|
export type { PrismaReaderExemption } from "./reader-crosscheck.js";
|
|
39
|
-
/**
|
|
40
|
-
* One engine's generate request, as a consumer states it.
|
|
41
|
-
*
|
|
42
|
-
* `driver` is here and is not on {@link PrismaGenerateRequest} for a reason the
|
|
43
|
-
* step's own header gives: `AdapterModel.transactions` is a **driver** fact that
|
|
44
|
-
* is stamped into the artifact at generate time, while the step itself is
|
|
45
|
-
* forbidden to know a provider or a driver at all — composition is created with a
|
|
46
|
-
* transaction capability and nothing else, so `if (provider === …)` inside
|
|
47
|
-
* discovery is a compile error rather than a convention. This function is the one
|
|
48
|
-
* place the two meet: it resolves the profile and hands composition the single
|
|
49
|
-
* fact it accepts.
|
|
50
|
-
*
|
|
51
|
-
* The declared driver must be the driver the application will construct the
|
|
52
|
-
* adapter with. The two cannot drift silently: an artifact that says
|
|
53
|
-
* `"interactive"` loaded by an adapter whose driver says `"none"` mounts no
|
|
54
|
-
* `transaction`, and core refuses construction with
|
|
55
|
-
* `DISCOVERY_TRANSACTION_CAPABILITY_MISMATCH`.
|
|
56
|
-
*/
|
|
8
|
+
/** One engine's generate request, as a consumer states it. */
|
|
57
9
|
export type PrismaDiscoveryGenerateRequest = {
|
|
58
10
|
/** The `schema.prisma` file, or a Prisma 7 schema folder. */
|
|
59
11
|
readonly schema: string;
|
|
@@ -64,16 +16,11 @@ export type PrismaDiscoveryGenerateRequest = {
|
|
|
64
16
|
readonly driver: PrismaDriver;
|
|
65
17
|
/** Where the emitted TypeScript artifact module is written. */
|
|
66
18
|
readonly artifactFile: string;
|
|
67
|
-
/**
|
|
19
|
+
/** Replaces the step's external effects; omit it to use the installed Prisma and TypeScript. */
|
|
68
20
|
readonly toolchain?: PrismaGenerateToolchain;
|
|
69
21
|
};
|
|
70
22
|
/**
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
* Every decision stays where it already lived. This function resolves the profile
|
|
75
|
-
* and builds the composer; it makes no judgement of its own, which is why there is
|
|
76
|
-
* nothing here to test beyond that it is the wiring the CLI and the repository's
|
|
77
|
-
* own `generate` script both use.
|
|
23
|
+
* Generates the discovery artifact for one schema: what the
|
|
24
|
+
* `aventara-prisma7-generate` command runs.
|
|
78
25
|
*/
|
|
79
26
|
export declare function generatePrismaDiscoveryArtifact(request: PrismaDiscoveryGenerateRequest): Promise<PrismaGenerateResult>;
|
|
@@ -1,25 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `prisma`'s `latest` is a Prisma 8 release candidate, so `npm i prisma` in a
|
|
3
|
-
* Prisma 7 project now installs a CLI this adapter's readers were never written
|
|
4
|
-
* against. Prisma's own upgrade path keeps the Prisma 7 CLI side by side as
|
|
5
|
-
* **`@prisma/prisma7`**, bin `prisma7` — the same CLI under a version-specific
|
|
6
|
-
* name. So, in this order:
|
|
7
|
-
*
|
|
8
|
-
* 1. `@prisma/prisma7` installed → its `prisma7` bin runs, provided the `prisma`
|
|
9
|
-
* it wraps is in the declared range;
|
|
10
|
-
* 2. otherwise `prisma`, **only** when its version is in the adapter's declared
|
|
11
|
-
* range (`peerDependencies.prisma`, read by the caller);
|
|
12
|
-
* 3. otherwise a refusal naming both, with the install command.
|
|
13
|
-
*
|
|
14
|
-
* # Where it looks
|
|
15
|
-
*
|
|
16
|
-
* Each package is looked up first from this module — the adapter's own install,
|
|
17
|
-
* where an optional peer is linked — and then from the project the step runs in
|
|
18
|
-
* (its working directory), where a strict installer such as pnpm leaves a package
|
|
19
|
-
* the adapter does not declare. A found package is followed to its real path, so
|
|
20
|
-
* the `prisma` that `@prisma/prisma7` wraps is the one beside it and not a
|
|
21
|
-
* `prisma` 8 hoisted next to the link.
|
|
22
|
-
*/
|
|
23
1
|
export type PrismaCli = {
|
|
24
2
|
/** The package whose bin runs: `@prisma/prisma7` or `prisma`. */
|
|
25
3
|
readonly package: "@prisma/prisma7" | "prisma";
|