@aventara/prisma7-adapter 0.1.0-pilot.3 → 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.
Files changed (55) hide show
  1. package/CHANGELOG.md +190 -0
  2. package/README.md +44 -29
  3. package/dist/discovery/artifact.loader.d.ts +2 -7
  4. package/dist/discovery/artifact.loader.js +8 -1
  5. package/dist/discovery/capability-surface.interface.d.ts +7 -64
  6. package/dist/discovery/capability.deriver.d.ts +2 -47
  7. package/dist/discovery/capability.deriver.js +3 -0
  8. package/dist/discovery/discovery-artifact.interface.d.ts +50 -159
  9. package/dist/discovery/discovery-artifact.interface.js +1 -1
  10. package/dist/discovery/enum.mapper.d.ts +0 -24
  11. package/dist/discovery/field.mapper.d.ts +4 -115
  12. package/dist/discovery/field.mapper.js +7 -7
  13. package/dist/discovery/identifier.mapper.d.ts +4 -84
  14. package/dist/discovery/model.discoverer.d.ts +3 -70
  15. package/dist/discovery/model.discoverer.js +5 -4
  16. package/dist/discovery/operations.deriver.d.ts +2 -37
  17. package/dist/discovery/scalar.mapper.d.ts +1 -32
  18. package/dist/discovery/scalar.mapper.js +2 -2
  19. package/dist/discovery/schema-facts.interface.d.ts +3 -83
  20. package/dist/discovery/schema.reader.d.ts +0 -133
  21. package/dist/discovery/types.reader.d.ts +1 -9
  22. package/dist/discovery/types.reader.js +18 -7
  23. package/dist/discovery/vocabulary.dictionary.d.ts +8 -134
  24. package/dist/discovery/vocabulary.dictionary.js +2 -2
  25. package/dist/errors/error.normalizer.d.ts +5 -168
  26. package/dist/errors/prisma-error.reader.d.ts +1 -93
  27. package/dist/execution/first-variant.emulator.d.ts +5 -28
  28. package/dist/execution/operation.executor.d.ts +3 -63
  29. package/dist/execution/result.shaper.d.ts +0 -56
  30. package/dist/execution/transaction.executor.d.ts +2 -99
  31. package/dist/generate/artifact.emitter.d.ts +1 -35
  32. package/dist/generate/artifact.emitter.js +31 -47
  33. package/dist/generate/declared-support.reader.d.ts +0 -20
  34. package/dist/generate/discovery.cli.d.ts +0 -4
  35. package/dist/generate/existence.gate.d.ts +3 -37
  36. package/dist/generate/index.d.ts +4 -57
  37. package/dist/generate/prisma-cli.resolver.d.ts +0 -22
  38. package/dist/generate/prisma.generate.d.ts +14 -83
  39. package/dist/generate/reader-crosscheck.d.ts +3 -88
  40. package/dist/generate/reader-crosscheck.js +4 -4
  41. package/dist/prisma-client.interface.d.ts +5 -25
  42. package/dist/prisma.adapter.d.ts +21 -22
  43. package/dist/prisma.adapter.js +1 -0
  44. package/dist/provider/provider-profile.d.ts +6 -14
  45. package/dist/translation/identifier.addressing.d.ts +0 -38
  46. package/dist/translation/mutation.translator.d.ts +6 -52
  47. package/dist/translation/mutation.translator.js +1 -1
  48. package/dist/translation/operation.translator.d.ts +3 -103
  49. package/dist/translation/order-pagination.translator.d.ts +2 -48
  50. package/dist/translation/order-pagination.translator.js +1 -1
  51. package/dist/translation/projection.translator.d.ts +1 -46
  52. package/dist/translation/scalar.conversion.d.ts +2 -65
  53. package/dist/translation/scalar.conversion.js +1 -1
  54. package/dist/translation/where.translator.d.ts +0 -52
  55. package/package.json +5 -4
@@ -1,38 +1,5 @@
1
1
  import type { RelationFieldCapabilities, ScalarFieldCapabilities, ScalarFilterOperator } from "@aventara/core";
2
2
  import type { PrismaRelationSurface, PrismaScalarSurface } from "./capability-surface.interface.js";
3
- /**
4
- * This module accepts `surface` alone, and that is deliberate: dictionary
5
- * invariant 6 says a capability is read from the client's own types and never
6
- * tabulated from a provider row, and the strongest available mechanism for that is
7
- * to make the provider **unrepresentable** rather than merely unread. A
8
- * `PrismaProviderProfile` in this input is a `provider` member one keystroke from
9
- * a branch; with no such member, `if (provider === …)` is a compile error, and the
10
- * three per-engine differences this pass exists to prove — `mode`, `JsonFilter`'s
11
- * ordering operators, and the `path` / `in` / `notIn` operand shapes — have to
12
- * come from the surface because nothing else is in scope.
13
- *
14
- * `mapping` went with them because nothing here reads an Aventara scalar identity
15
- * to answer a capability question.
16
- *
17
- * The answer is read off the recorded operand shape, which is already on the
18
- * surface; the Aventara scalar identity would have been a second, weaker source
19
- * for the same fact. `mapping` stays out.
20
- *
21
- * # Order is canonical, not incidental
22
- *
23
- * Every list is emitted in **core's own union declaration order**, held below as a
24
- * closed ordered array.
25
- *
26
- * # Absent and empty are different answers
27
- *
28
- * `create: []` / `update: []` mean **writable with no directive** — plain
29
- * assignment, which is what `set` alone is. An absent `create` / `update` means
30
- * **not writable**, and core enforces exactly that: `validateScalarMutation`
31
- * answers `V1006` *"is not writable during <stage>"* when the member is
32
- * `undefined` **[CORE, operations/operation-validator-core.ts]**. So the two must
33
- * not be conflated, and the surface's `null` (the client exposes no entry for this
34
- * column at this stage) is the only thing that produces the absent form.
35
- */
36
3
  /** A Prisma spelling that no dictionary table recognises: a build stop, never a drop. */
37
4
  export declare class PrismaCapabilityDerivationError extends Error {
38
5
  readonly name = "PrismaCapabilityDerivationError";
@@ -40,23 +7,11 @@ export declare class PrismaCapabilityDerivationError extends Error {
40
7
  export type ScalarCapabilityInput = {
41
8
  readonly surface: PrismaScalarSurface;
42
9
  };
43
- /**
44
- * A relation's capabilities are answered for the field, not for an operation.
45
- *
46
- * The `operation: "create.one" | "create.many"` parameter this input used to carry
47
- * is **gone**. The scope-qualified members hold both answers at once, so there is
48
- * nothing left to pick and no caller left to pick it.
49
- */
10
+ /** A relation's capabilities are answered for the field, not for an operation. */
50
11
  export type RelationCapabilityInput = {
51
12
  readonly surface: PrismaRelationSurface;
52
13
  };
53
14
  export declare function deriveScalarCapabilities(input: ScalarCapabilityInput): ScalarFieldCapabilities;
54
- /**
55
- * The Prisma operand for each ADVERTISED operator, keyed by the Aventara name.
56
- *
57
- * A deriver that answered operator NAMES alone would report the two engines
58
- * identical where they are not, so the shape is carried beside the capability
59
- * rather than discarded.
60
- */
15
+ /** The Prisma operand for each ADVERTISED operator, keyed by the Aventara name. */
61
16
  export declare function deriveScalarFilterOperands(input: ScalarCapabilityInput): Readonly<Partial<Record<ScalarFilterOperator, string>>>;
62
17
  export declare function deriveRelationCapabilities(input: RelationCapabilityInput): RelationFieldCapabilities;
@@ -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,39 +1,23 @@
1
- import type { Adapter, AdapterResource, EnumDefinition, ScalarRegistry, TransactionCapability } from "@aventara/core";
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
- * A plain `type`, not `interface … extends`: `AdapterModel.resources` is
5
- * self-typed `AdapterResource<this>`, and a nominal `extends` hits TS2430.
6
- */
4
+ /** The adapter model a discovery artifact carries, in Aventara's vocabulary. */
7
5
  export type PrismaAdapterModel = {
6
+ /** The scalar types the schema uses. */
8
7
  readonly scalars: ScalarRegistry;
8
+ /** The schema's enums, by name. */
9
9
  readonly enums: Readonly<Record<string, EnumDefinition>>;
10
+ /** The schema's models, as Resources. */
10
11
  readonly resources: Readonly<Record<string, AdapterResource<PrismaAdapterModel>>>;
12
+ /** Whether the driver supports interactive transactions. */
11
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"]>;
12
19
  };
13
- /**
14
- * One identifier, and the **Prisma addressing key** that reaches it.
15
- *
16
- * `members` is the identifier as core carries it — derived from
17
- * `AdapterResource` rather than restated, so a change to core's identifier type
18
- * is a compile error here. `key` is the same criterion's *Prisma* spelling: the
19
- * key a `WhereUniqueInput` accepts, and the key the generated `AtLeast<…, K>`
20
- * union lists.
21
- *
22
- * The two are different facts, and the whole reason this type exists is that
23
- * they are not derivable from one another. Measured at 7.10.0 (2026-09-29):
24
- *
25
- * - a single-column criterion keys by the field name and does **not** wrap:
26
- * `{ id: "x" }`;
27
- * - a compound keys by its members joined with `_` **in attribute order** and
28
- * does wrap: `@@unique([b, a])` → `{ b_a: { b, a } }`;
29
- * - `name: "X"` **replaces** the positional form on both sides — `}, "id" |
30
- * "altKey">` and `altKey?: Prisma.…CompoundUniqueInput`;
31
- * - `map:` affects neither: it reaches only the 🛑 inline-schema blob.
32
- *
33
- * So `key` is stored at generate time and **matched** at runtime, never
34
- * re-derived: `members.join("_")` is wrong for every named criterion, and
35
- * whether it wraps is `members.length > 1`.
36
- */
20
+ /** One identifier, and the **Prisma addressing key** that reaches it. */
37
21
  export type PrismaIdentifierAddress = {
38
22
  readonly members: AdapterResource<PrismaAdapterModel>["identifiers"][number];
39
23
  readonly key: string;
@@ -42,110 +26,42 @@ export type PrismaIdentifierAddress = {
42
26
  export type PrismaResourceTranslation = {
43
27
  readonly identifierKeys: readonly PrismaIdentifierAddress[];
44
28
  };
45
- /**
46
- * The **translation table**: Prisma addressing for every discovered Resource.
47
- *
48
- * Keyed on `M`'s own resource keys, so a table missing a Resource — or naming
49
- * one the model does not have — is a compile error rather than a runtime
50
- * `undefined` at the first unique read.
51
- *
52
- * It sits **beside** {@link PrismaDiscoveryArtifact.model}, never inside it, and
53
- * that placement is the point: the model is canonicalized, hashed and compiled
54
- * into the Contract, so a Prisma addressing key in it would put a DB-side
55
- * rename into the Contract hash and force every client to be regenerated for a
56
- * change with zero semantic content. This half is adapter-private: the executor
57
- * reads it, core never sees it.
58
- */
29
+ /** The **translation table**: Prisma addressing for every discovered Resource. */
59
30
  export type PrismaTranslationTable<M extends PrismaAdapterModel = PrismaAdapterModel> = {
60
31
  readonly [R in keyof M["resources"]]: PrismaResourceTranslation;
61
32
  };
62
- /**
63
- * A referential action in Aventara's own vocabulary.
64
- *
65
- * Prisma's set — `Cascade | Restrict | NoAction | SetNull | SetDefault` — is the
66
- * SQL-standard set spelled in PascalCase, so a faithful mapping exists and no
67
- * Prisma spelling has to travel with the fact. These words are SQL's own
68
- * (`ON DELETE SET NULL`), which is why the mapping is a rename and not a
69
- * translation: nothing about it is Prisma-shaped, and the next adapter can state
70
- * the same fact without inheriting this one's vocabulary.
71
- *
72
- * It is declared **here**, on the artifact side, rather than beside the PSL
73
- * facts that resolve it: the artifact is what carries the vocabulary off the
74
- * generate step and across the package boundary, and `schema-facts.interface.ts`
75
- * imports it from here so that there is one spelling and the dependency runs
76
- * generate-time → artifact rather than the other way about.
77
- */
33
+ /** A referential action, as `onDelete`/`onUpdate` name it in the schema. */
78
34
  export type PrismaReferentialAction = "cascade" | "restrict" | "no-action" | "set-null" | "set-default";
79
- /**
80
- * One **owning** relation edge's resolved referential actions.
81
- *
82
- * # The direction, which is the whole point of this type
83
- *
84
- * `onDelete` is declared on the **child** — `Kid.parent @relation(…, onDelete:
85
- * Cascade)` — and fires when the **parent** is deleted. PSL enforces that itself:
86
- * `prisma validate` 7.10.0 refuses the action on the other edge, naming the
87
- * opposite field. So an entry under resource `R` reads:
88
- *
89
- * > **deleting a `target` row does `onDelete` to rows of `R`.**
90
- *
91
- * A consumer asking *"what does deleting an `X` do?"* scans every resource's
92
- * {@link PrismaResourceReferentialActions.owningEdges} for `target === "X"` and
93
- * reads the enclosing resource key off the table. It never has to work out which
94
- * side of a pair declared what.
95
- *
96
- * **Reversing that reading is silent.** Nothing in the shape distinguishes
97
- * `resource` from `target`, both are resource names, and a planner built on the
98
- * inverted reading cascades the wrong way with no type error and no runtime
99
- * complaint. That is why the convention is restated here as well as on
100
- * `field.mapper.ts`'s `PrismaRelationEdge`, which is where these values are
101
- * carried out of field projection.
102
- *
103
- * # Both members are resolved, so neither is nullable
104
- *
105
- * An absent `@relation(onDelete:)` is **not** a third state: it is Prisma's
106
- * effective default, measured at 7.10.0 with `prisma migrate diff` and identical
107
- * on `postgresql` and `sqlite` — `SET NULL` when every scalar in `fields:` is
108
- * optional, `RESTRICT` otherwise, and `CASCADE` on update
109
- * (`schema.reader.ts`'s `resolvePrismaReferentialDefaults`). An action the reader
110
- * cannot name is recorded in `unhandled` and fails the generate step, so no
111
- * artifact ever carries an unresolved one.
112
- */
35
+ /** One **owning** relation edge's resolved referential actions. */
113
36
  export type PrismaReferentialEdge = {
114
37
  /** The edge's field name on the enclosing (child) resource. */
115
38
  readonly field: string;
116
39
  /** The resource the edge points AT — the parent, whose deletion fires `onDelete`. */
117
40
  readonly target: string;
41
+ /** Whether the edge holds one related row or many. */
118
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[];
119
48
  /** What deleting a `target` row does to rows of the ENCLOSING resource. */
120
49
  readonly onDelete: PrismaReferentialAction;
121
50
  /** The same for an update of the referenced key. Read independently of `onDelete`. */
122
51
  readonly onUpdate: PrismaReferentialAction;
123
52
  };
124
53
  /**
125
- * One Resource's owning edges, in PSL field-declaration order.
126
- *
127
- * Only **owning** edges appear — the ones that declare `@relation(fields: …)`,
128
- * which is what makes an edge the foreign-key side and the only side PSL lets
129
- * carry an action. A back-reference's actions are its partner's, so an entry for
130
- * it would carry two nulls and no fact; a resource with no owning edge carries an
131
- * empty list, which is itself the answer that deleting anything leaves its rows
132
- * alone.
54
+ * One Resource's owning edges, in schema field order: the relation fields that
55
+ * declare `@relation(fields: …)`. An empty list means deleting rows elsewhere
56
+ * leaves this Resource's rows alone.
133
57
  */
134
58
  export type PrismaResourceReferentialActions = {
59
+ /** The Resource's owning edges, in schema order. */
135
60
  readonly owningEdges: readonly PrismaReferentialEdge[];
136
61
  };
137
62
  /**
138
63
  * The **referential-action table**: every discovered Resource's owning edges,
139
64
  * resolved.
140
- *
141
- * Keyed on `M`'s own resource keys for the reason {@link PrismaTranslationTable}
142
- * is — a resource the model carries and the table forgets is a compile error at
143
- * the generate step rather than a runtime `undefined` — and it sits **beside**
144
- * {@link PrismaDiscoveryArtifact.model} and outside `modelHash` for the reason
145
- * that one does: `modelHash` digests the model, and a referential action is not
146
- * part of the model. Putting it inside would push referential-action vocabulary
147
- * into the compiled Contract and the ClientContract, where core has no word for
148
- * it, and would move the Contract identity of every schema that has a relation.
149
65
  */
150
66
  export type PrismaReferentialActionTable<M extends PrismaAdapterModel = PrismaAdapterModel> = {
151
67
  readonly [R in keyof M["resources"]]: PrismaResourceReferentialActions;
@@ -154,26 +70,15 @@ export type PrismaReferentialActionTable<M extends PrismaAdapterModel = PrismaAd
154
70
  * What the generated Prisma client exposed when the artifact was generated: each
155
71
  * model it has a delegate for, keyed by the model's name, and that model's field
156
72
  * references (`prisma.<model>.fields`) in code-unit order.
157
- *
158
- * It is the artifact's record of the client it was read from, and the runtime
159
- * reads the same two facts off the client it is handed — the delegates the client
160
- * carries, and each one's public `fields`. When they disagree, the schema changed
161
- * and the client was regenerated without the artifact, and the adapter refuses to
162
- * start rather than serve a model that no longer matches. Prisma excludes
163
- * `Unsupported(…)` and `@ignore`d fields and `@@ignore`d models from both the
164
- * generated types and the runtime client, so the two readings agree by
165
- * construction on an unchanged schema.
166
- *
167
- * Beside the model and outside `modelHash`, like the translation table: it
168
- * describes the provider client, not the semantic model.
169
73
  */
170
74
  export type PrismaClientShape = Readonly<Record<string, readonly string[]>>;
171
75
  /**
172
76
  * What a create of each Resource cannot do without, already in core's words
173
77
  * (`Adapter["createRequirements"]`): a column the client must write, or a
174
- * required relation that may instead be written through the scalar fields that
175
- * hold its reference — and the relation's other end, through which a nested
176
- * create supplies it.
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.
177
82
  *
178
83
  * Read at generate time from the generated client's create inputs — the
179
84
  * question marks on `<M>UncheckedCreateInput` and `<M>CreateInput` — and from the
@@ -182,54 +87,40 @@ export type PrismaClientShape = Readonly<Record<string, readonly string[]>>;
182
87
  * model, and the Contract carries no foreign-key detail.
183
88
  */
184
89
  export type PrismaCreateRequirementTable = NonNullable<Adapter["createRequirements"]>;
90
+ /** The current discovery artifact format. */
91
+ export declare const DISCOVERY_ARTIFACT_FORMAT = 2;
185
92
  /**
186
- * One module written `as const satisfies AdapterModel` makes value and type the
187
- * same literal, and makes drift unrepresentable rather than merely detectable.
188
- *
189
- * It is still passive, serializable, introspectable, hashable and free of runtime
190
- * callbacks: a `.ts` module whose only expression is a frozen object literal is
191
- * JSON that carries its own type.
192
- *
193
- * `M` is the reason this type is generic at all. The emitted module's `model` is a
194
- * literal type; if this alias pinned `model` to the general {@link
195
- * PrismaAdapterModel}, every resource key and field key would be erased to
196
- * `string` on the way to `createPrismaAdapter`, `EffectiveFieldKey` would
197
- * degenerate, and core's whole config-typing workstream would buy nothing —
198
- * silently, with no compile error anywhere. `model: M` is a bare property
199
- * position, which is what makes `M` actually infer at the call site;
200
- * `typed-artifact.test-d.ts` is what proves it still does.
201
- *
202
- * The default keeps the unparameterised spelling meaning what it always meant:
203
- * "some Prisma adapter model".
93
+ * The discovery artifact: the module `aventara-prisma7-generate` writes from
94
+ * your schema and generated client. Import its `discovery` export and pass it
95
+ * to `createPrismaAdapter({ discovery })`.
204
96
  */
205
97
  export type PrismaDiscoveryArtifact<M extends PrismaAdapterModel = PrismaAdapterModel> = {
206
- /** e.g. `"7.10.0"`; only the major is fenced. */
98
+ /**
99
+ * The artifact's format. A TypeScript error naming this property means the
100
+ * artifact was written by another version of `@aventara/prisma7-adapter`:
101
+ * regenerate it with `npm run aventara:prepare` (or `aventara-prisma7-generate`).
102
+ */
103
+ readonly regenerate_with_aventara_prepare: typeof DISCOVERY_ARTIFACT_FORMAT;
104
+ /** The Prisma version the artifact was generated with, such as `"7.10.0"`. */
207
105
  readonly prismaVersion: string;
106
+ /** The database provider: `"sqlite"` or `"postgresql"`. */
208
107
  readonly provider: PrismaProvider;
209
108
  /** `sha256:<hex>` of the canonicalized `model` below — and of nothing else. */
210
109
  readonly modelHash: string;
110
+ /** What the schema and the generated client agreed on. */
211
111
  readonly model: M;
212
- /**
213
- * Prisma addressing beside the model, and outside `modelHash` by
214
- * construction: see {@link PrismaTranslationTable}.
215
- */
112
+ /** Prisma addressing per Resource; not part of `modelHash`. */
216
113
  readonly translation: PrismaTranslationTable<M>;
217
114
  /**
218
- * The resolved referential actions, beside the model and outside `modelHash`
219
- * on the same construction: see {@link PrismaReferentialActionTable}.
220
- *
221
- * Direction, because getting it backwards is silent: an entry under resource
222
- * `R` says **deleting a `target` row does `onDelete` to rows of `R`**.
115
+ * The schema's referential actions; not part of `modelHash`. An entry under
116
+ * resource `R` says **deleting a `target` row does `onDelete` to rows of `R`**.
223
117
  */
224
118
  readonly referentialActions: PrismaReferentialActionTable<M>;
225
119
  /**
226
- * The client this artifact was generated against, beside the model and
227
- * outside `modelHash`: see {@link PrismaClientShape}.
120
+ * The models and field references of the client the artifact was generated
121
+ * against; not part of `modelHash`.
228
122
  */
229
123
  readonly client: PrismaClientShape;
230
- /**
231
- * The create requirements, beside the model and outside `modelHash`: see
232
- * {@link PrismaCreateRequirementTable}.
233
- */
124
+ /** What a create of each Resource cannot do without; not part of `modelHash`. */
234
125
  readonly createRequirements: PrismaCreateRequirementTable;
235
126
  };
@@ -1 +1 @@
1
- export {};
1
+ export const DISCOVERY_ARTIFACT_FORMAT = 2;
@@ -1,29 +1,9 @@
1
1
  import type { EnumDefinition } from "@aventara/core";
2
2
  import type { PrismaSchemaEnum } from "./schema-facts.interface.js";
3
3
  import type { PrismaDiscoveryDiagnostic } from "./vocabulary.dictionary.js";
4
- /**
5
- * # Declaration order is semantic, so nothing here sorts
6
- *
7
- * # What a cross-check failure means
8
- *
9
- * `enums.ts` and `schema.prisma` were read in the same instant by the same
10
- * generate step. If they disagree, one of them is stale, and the answer is
11
- * `diverged` — a build stop — rather than a preference for either. The message
12
- * prints both orders because "the enum diverged" without them costs the reader a
13
- * second investigation.
14
- *
15
- * # A member-level `@map` never reaches here, from either side
16
- *
17
- * PSL's reader discards it as bucket 2 (a database name, which Aventara has no
18
- * word for), and the generated `enums.ts` writes the member name on *both* sides
19
- * of a mapped member — `GAMMA: 'GAMMA'`, not `GAMMA: 'g'` **[RUN8 — 2026-09-28,
20
- * prisma 7.10.0]**. So the cross-check compares Aventara identities on both sides,
21
- * and the mapper has nothing to resurrect.
22
- */
23
4
  export type EnumMappingInput = {
24
5
  /** PSL — the source of the values and their order. */
25
6
  readonly declared: PrismaSchemaEnum;
26
- /** TYPE — `enums.ts`'s member list, or `undefined` when the 🟢 types omit the enum entirely. */
27
7
  readonly exposed: readonly string[] | undefined;
28
8
  };
29
9
  export type EnumMappingOutcome = {
@@ -37,10 +17,6 @@ export type EnumMappingOutcome = {
37
17
  readonly outcome: "diverged";
38
18
  readonly diagnostic: PrismaDiscoveryDiagnostic;
39
19
  };
40
- /**
41
- * The `kind` is a literal `"scalar"`, so a third structural kind cannot be
42
- * introduced here without the type changing.
43
- */
44
20
  export type EnumBackedColumn = {
45
21
  readonly kind: "scalar";
46
22
  readonly type: {
@@ -1,95 +1,17 @@
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";
5
5
  import { type PrismaDiscoveryDiagnostic, type PrismaEvidence } from "./vocabulary.dictionary.js";
6
- /**
7
- * # Nullability comes from PSL, and the required `Json` column is why
8
- *
9
- * `nullable` is `PrismaSchemaField.optional` — PSL's `?` — and **nothing else**.
10
- * The type surface cannot answer the question, and the damage is not hypothetical:
11
- * `$MetricPayload.scalars.sJson` resolves to `null | string | number | false |
12
- * true | JsonObject | JsonArray` while PSL says `sJson Json`, required, because
13
- * JSON null is a *value*. The reader's own facts point the same wrong way —
14
- * `JsonFilterBase.array_contains` admits `| null` and `equals` admits
15
- * `JsonNullValueFilter` on that same required column — so a plausible "the
16
- * operands mention null, therefore the column is nullable" rule is wrong for
17
- * **every** `Json` field while being right everywhere else. That is the whole
18
- * reason this rule is stated as a rule rather than left to taste.
19
- *
20
- * # The create-optional marker is a cross-check, never a source
21
- *
22
- * {@link crossCheckCreateOptional} is a separate function that *consumes* this
23
- * projection, and the data flows one way only: the marker never reaches {@link
24
- * projectPrismaField}. `<M>UncheckedCreateInput`'s `?` is **one bit over several
25
- * causes** — `@default(uuid())`, `@default(BRONZE)`, `@default(now())`,
26
- * `@updatedAt`, plain nullability, and a scalar list, which needs no value because
27
- * the empty list is one — and nothing on the 🟢 surface tells them apart. Deriving
28
- * a trait *from* the marker would invert the check into the bug it exists to
29
- * catch: it would make the two readers agree by construction and detect nothing.
30
- *
31
- * # `@default` is matched, never parsed
32
- *
33
- * {@link matchPrismaDefault} walks `PRISMA_DEFAULT_TABLE` over the raw argument
34
- * text the PSL reader carried across unchanged.
35
- *
36
- * The matcher adds **one** discriminant the dictionary's table does not state, and
37
- * it is a shape test rather than a parse: an argument that begins with an
38
- * identifier followed by `(` is a *generator form*, and anything else is a *static
39
- * value*. Both are `DEFAULTED`; only an unrecognised generator form records an
40
- * unknown. The test never reads *inside* the argument, so
41
- * `dbgenerated("gen_random_uuid()")` remains a key and `"a, b // not a comment"`
42
- * remains opaque text.
43
- *
44
- * # A relation carries four members, and the FK is not one of them
45
- *
46
- * `target`, `cardinality`, `nullable`, and `capabilities`. The `@relation(fields:
47
- * […], references: […])` scalars are read, used to identify the FK column and
48
- * check it against the edge's own optionality, and then **discarded**.
49
- * `@relation`'s *name* is not an Aventara concept either, and its referential
50
- * actions are not core's yet, so both travel beside the projection as {@link
51
- * PrismaRelationEdge} rather than inside it: pairing is discovery-internal, and it
52
- * is **PSL-only** — the name appears nowhere on the 🟢 surface, so from the types
53
- * alone `Author` has two `Author` edges with nothing to pair them.
54
- *
55
- * # Two failure vocabularies, kept apart
56
- *
57
- * A **diagnostic** is about the schema: PSL declares a column the 🟢 types do not
58
- * expose, or a Prisma type name in no table. A **throw** is about the readers: the
59
- * two sources disagree about a fact they both state, which no schema can cause and
60
- * no diagnostic vocabulary describes. The types reader draws the same line.
61
- */
62
6
  /** A reader-versus-reader disagreement: not a schema problem, and not recoverable. */
63
7
  export declare class PrismaFieldProjectionError extends Error {
64
8
  readonly name = "PrismaFieldProjectionError";
65
9
  }
66
- /**
67
- * `Omit` rather than a restatement, so the composed field is the core type by
68
- * construction.
69
- */
70
10
  export type ProjectedScalarField = Omit<AdapterScalarField<PrismaAdapterModel>, "capabilities">;
71
11
  export type ProjectedRelationField = Omit<AdapterRelationField<PrismaAdapterModel>, "capabilities">;
72
12
  /**
73
13
  * One relation edge as PSL states it — the pairing evidence and the referential
74
14
  * actions, neither of which the projected field carries.
75
- *
76
- * # Why the actions ride here and not on `AdapterRelationField`
77
- *
78
- * Wiring a referential action into the Contract is a core change and belongs to
79
- * the task that owns core's transaction planner, not to discovery. Until then the
80
- * fact lives where discovery can state it truthfully.
81
- *
82
- * # The lookup is inverted, and the edge is shaped so a consumer need not invert
83
- *
84
- * `onDelete` is declared on the CHILD — `Kid.parent @relation(…, onDelete:
85
- * Cascade)` — and fires when the PARENT is deleted. So an edge reads: **deleting a
86
- * `target` does `onDelete` to rows of `resource`.** A consumer asking "what does
87
- * deleting `X` remove?" filters `target === X && onDelete === "cascade"` and reads
88
- * off `resource`; it does not have to re-derive which side of a pair declared
89
- * what.
90
- *
91
- * `null` on both members means this edge is not the owning side (it declares no
92
- * `fields:`), so the actions are on its partner — never that no action applies.
93
15
  */
94
16
  export type PrismaRelationEdge = {
95
17
  /** The model DECLARING the edge — the child, where an owning edge is concerned. */
@@ -100,11 +22,6 @@ export type PrismaRelationEdge = {
100
22
  readonly cardinality: "one" | "many";
101
23
  /** `@relation("Name")`, or `null` where PSL wrote none. PSL-only. */
102
24
  readonly relationName: string | null;
103
- /**
104
- * What deleting a `target` row does to this `resource` row, resolved (an
105
- * absent PSL argument already carries Prisma's measured default). `null` on a
106
- * non-owning edge.
107
- */
108
25
  readonly onDelete: PrismaReferentialAction | null;
109
26
  /** The same for an update of the referenced key. `null` on a non-owning edge. */
110
27
  readonly onUpdate: PrismaReferentialAction | null;
@@ -115,7 +32,7 @@ export type FieldProjectionInput = {
115
32
  readonly field: PrismaSchemaField;
116
33
  /** The model's other fields: the only way to identify an FK scalar by name. */
117
34
  readonly siblings: readonly PrismaSchemaField[];
118
- /** TYPE — what this client exposes. The existence gate. */
35
+ /** TYPE — what this client exposes. */
119
36
  readonly surface: PrismaResourceSurface;
120
37
  /** TYPE — `enums.ts`, which is what makes an enum name an enum name. */
121
38
  readonly enums: Readonly<Record<string, readonly string[]>>;
@@ -126,7 +43,6 @@ export type FieldProjection = {
126
43
  readonly outcome: "scalar";
127
44
  readonly name: string;
128
45
  readonly field: ProjectedScalarField;
129
- /** Recorded unknowns; a non-empty list FAILS the generate step. */
130
46
  readonly unknowns: readonly PrismaSchemaUnknown[];
131
47
  } | {
132
48
  readonly outcome: "relation";
@@ -158,10 +74,6 @@ export type PrismaDefaultOutcome =
158
74
  readonly form: "unrecognised-generator";
159
75
  readonly traits: readonly AdapterLifecycleTrait[];
160
76
  };
161
- /**
162
- * The argument arrives as opaque text precisely so that this function can be a
163
- * lookup.
164
- */
165
77
  export declare function matchPrismaDefault(argument: string): PrismaDefaultOutcome;
166
78
  /** Why a field is legitimately optional in `<M>UncheckedCreateInput`. */
167
79
  export type CreateOptionalCause = AdapterLifecycleTrait | "nullable"
@@ -192,16 +104,7 @@ export type CreateOptionalCrossCheck = {
192
104
  readonly unexplained: readonly string[];
193
105
  readonly messages: readonly string[];
194
106
  };
195
- /**
196
- * TYPE's only contribution to lifecycle: a check, run in one direction.
197
- *
198
- * Every field the 🟢 `<M>UncheckedCreateInput` marks optional must carry a PSL
199
- * cause. A field the types mark optional with no cause means **one of the two
200
- * readers is wrong** — that is the entire signal, and it is why the marker is
201
- * never read as a trait. Names the types mark that this model does not project
202
- * as a scalar (relation edges) are skipped rather than reported: their
203
- * optionality is structural.
204
- */
107
+ /** TYPE's only contribution to lifecycle: a check, run in one direction. */
205
108
  export declare function crossCheckCreateOptional(input: CreateOptionalCrossCheckInput): CreateOptionalCrossCheck;
206
109
  export type PrismaRelationPair = readonly [
207
110
  PrismaRelationEdge,
@@ -212,19 +115,5 @@ export type PrismaRelationPairing = {
212
115
  /** Edges nothing pairs: a back-reference the schema never declared, or an ambiguity. */
213
116
  readonly unpaired: readonly PrismaRelationEdge[];
214
117
  };
215
- /**
216
- * Pairs each edge with its back-reference, which **only PSL can do**.
217
- *
218
- * An explicit `@relation("Name")` is the pairing evidence, and for the two
219
- * `Author` → `Author` edges it is the *only* evidence: the name appears nowhere
220
- * on the 🟢 surface, so from the types alone there are two self-edges and
221
- * nothing to say they are one relation.
222
- *
223
- * Unnamed edges are paired by the unordered model pair, which is unambiguous
224
- * because PSL requires a name as soon as two relations connect the same two
225
- * models. Where an unordered pair still has more than two edges, they are left
226
- * unpaired rather than guessed: the implicit name Prisma would compute lives in
227
- * the 🛑 runtime data model, and re-deriving it here would be this module
228
- * reimplementing the generator.
229
- */
118
+ /** Pairs each edge with its back-reference, which **only PSL can do**. */
230
119
  export declare function pairPrismaRelationEdges(edges: readonly PrismaRelationEdge[]): PrismaRelationPairing;
@@ -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";
@@ -44,10 +44,10 @@ function assertTokenAgrees(resource, field, token) {
44
44
  const listed = token.endsWith("[]");
45
45
  const base = listed ? token.slice(0, -2) : token;
46
46
  if (base !== field.type) {
47
- throw new PrismaFieldProjectionError(`${resource}.${field.name} is written \`${field.type}\` in schema.prisma and the 🟢 types carry the FieldRef token \`${token}\`. The two readers describe one instant, so this is a stale generated client or a reader defect, not a schema the adapter can translate.`);
47
+ throw new PrismaFieldProjectionError(`${resource}.${field.name} is written \`${field.type}\` in schema.prisma and the generated client's types carry the FieldRef token \`${token}\`. The two readers describe one instant, so this is a stale generated client or a reader defect, not a schema the adapter can translate.`);
48
48
  }
49
49
  if (listed !== field.list) {
50
- throw new PrismaFieldProjectionError(`${resource}.${field.name} is ${field.list ? "a list" : "not a list"} in schema.prisma and the 🟢 types carry the FieldRef token \`${token}\`, which says the opposite.`);
50
+ throw new PrismaFieldProjectionError(`${resource}.${field.name} is ${field.list ? "a list" : "not a list"} in schema.prisma and the generated client's types carry the FieldRef token \`${token}\`, which says the opposite.`);
51
51
  }
52
52
  }
53
53
  const ADAPTER_TRAIT_ORDER = LIFECYCLE_TRAITS.filter((trait) => trait === "DEFAULTED" ||
@@ -138,20 +138,20 @@ function projectRelationField(input) {
138
138
  outcome: "excluded",
139
139
  diagnostic: {
140
140
  code: "not-exposed",
141
- message: `${column} is declared in schema.prisma as an edge to \`${field.type}\` and absent from the generated 🟢 types, so it is omitted: ${field.ignored ? "it carries `@ignore`" : "no schema attribute explains it — a provider drop or a preview-feature exclusion"}.`,
141
+ message: `${column} is declared in schema.prisma as an edge to \`${field.type}\` and absent from the generated client's types, so it is omitted: ${field.ignored ? "it carries `@ignore`" : "no schema attribute explains it — a provider drop or a preview-feature exclusion"}.`,
142
142
  },
143
143
  };
144
144
  }
145
145
  const cardinality = field.list ? "many" : "one";
146
146
  const nullable = cardinality === "many" ? false : field.optional;
147
147
  if (exposed.many !== field.list) {
148
- throw new PrismaFieldProjectionError(`${column} is ${field.list ? "a list" : "a single edge"} in schema.prisma and the 🟢 payload says the opposite.`);
148
+ throw new PrismaFieldProjectionError(`${column} is ${field.list ? "a list" : "a single edge"} in schema.prisma and the generated client's payload type says the opposite.`);
149
149
  }
150
150
  if (exposed.nullable !== nullable) {
151
- throw new PrismaFieldProjectionError(`${column} is ${nullable ? "optional" : "required"} in schema.prisma and the 🟢 payload ${exposed.nullable ? "admits" : "refuses"} \`null\`.`);
151
+ throw new PrismaFieldProjectionError(`${column} is ${nullable ? "optional" : "required"} in schema.prisma and the generated client's payload type ${exposed.nullable ? "admits" : "refuses"} \`null\`.`);
152
152
  }
153
153
  if (exposed.target !== field.type) {
154
- throw new PrismaFieldProjectionError(`${column} targets \`${field.type}\` in schema.prisma and \`${exposed.target}\` on the 🟢 payload.`);
154
+ throw new PrismaFieldProjectionError(`${column} targets \`${field.type}\` in schema.prisma and \`${exposed.target}\` in the generated client's payload type.`);
155
155
  }
156
156
  assertForeignKeyAgrees(column, field, siblings, nullable);
157
157
  return {