@aventara/prisma7-adapter 0.1.0-pilot.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 (86) hide show
  1. package/LICENSE +91 -0
  2. package/LICENSE-ADDITIONAL-PERMISSION.md +9 -0
  3. package/README.md +564 -0
  4. package/dist/discovery/artifact.loader.d.ts +26 -0
  5. package/dist/discovery/artifact.loader.js +124 -0
  6. package/dist/discovery/capability-surface.interface.d.ts +191 -0
  7. package/dist/discovery/capability-surface.interface.js +13 -0
  8. package/dist/discovery/capability.deriver.d.ts +92 -0
  9. package/dist/discovery/capability.deriver.js +350 -0
  10. package/dist/discovery/discovery-artifact.interface.d.ts +210 -0
  11. package/dist/discovery/discovery-artifact.interface.js +1 -0
  12. package/dist/discovery/enum.mapper.d.ts +59 -0
  13. package/dist/discovery/enum.mapper.js +32 -0
  14. package/dist/discovery/field.mapper.d.ts +244 -0
  15. package/dist/discovery/field.mapper.js +387 -0
  16. package/dist/discovery/identifier.mapper.d.ts +188 -0
  17. package/dist/discovery/identifier.mapper.js +132 -0
  18. package/dist/discovery/model.discoverer.d.ts +108 -0
  19. package/dist/discovery/model.discoverer.js +341 -0
  20. package/dist/discovery/operations.deriver.d.ts +75 -0
  21. package/dist/discovery/operations.deriver.js +92 -0
  22. package/dist/discovery/scalar.mapper.d.ts +81 -0
  23. package/dist/discovery/scalar.mapper.js +51 -0
  24. package/dist/discovery/schema-facts.interface.d.ts +174 -0
  25. package/dist/discovery/schema-facts.interface.js +11 -0
  26. package/dist/discovery/schema.reader.d.ts +162 -0
  27. package/dist/discovery/schema.reader.js +692 -0
  28. package/dist/discovery/types.reader.d.ts +24 -0
  29. package/dist/discovery/types.reader.js +617 -0
  30. package/dist/discovery/vocabulary.dictionary.d.ts +258 -0
  31. package/dist/discovery/vocabulary.dictionary.js +429 -0
  32. package/dist/errors/error.normalizer.d.ts +250 -0
  33. package/dist/errors/error.normalizer.js +135 -0
  34. package/dist/errors/prisma-error.reader.d.ts +144 -0
  35. package/dist/errors/prisma-error.reader.js +167 -0
  36. package/dist/execution/first-variant.emulator.d.ts +64 -0
  37. package/dist/execution/first-variant.emulator.js +205 -0
  38. package/dist/execution/operation.executor.d.ts +87 -0
  39. package/dist/execution/operation.executor.js +210 -0
  40. package/dist/execution/result.shaper.d.ts +103 -0
  41. package/dist/execution/result.shaper.js +141 -0
  42. package/dist/execution/transaction.executor.d.ts +147 -0
  43. package/dist/execution/transaction.executor.js +13 -0
  44. package/dist/generate/artifact.emitter.d.ts +50 -0
  45. package/dist/generate/artifact.emitter.js +105 -0
  46. package/dist/generate/declared-support.reader.d.ts +33 -0
  47. package/dist/generate/declared-support.reader.js +74 -0
  48. package/dist/generate/discovery.bin.d.ts +2 -0
  49. package/dist/generate/discovery.bin.js +15 -0
  50. package/dist/generate/discovery.cli.d.ts +24 -0
  51. package/dist/generate/discovery.cli.js +163 -0
  52. package/dist/generate/existence.gate.d.ts +73 -0
  53. package/dist/generate/existence.gate.js +91 -0
  54. package/dist/generate/index.d.ts +81 -0
  55. package/dist/generate/index.js +65 -0
  56. package/dist/generate/node-version.guard.d.ts +8 -0
  57. package/dist/generate/node-version.guard.js +59 -0
  58. package/dist/generate/prisma-cli.resolver.d.ts +48 -0
  59. package/dist/generate/prisma-cli.resolver.js +95 -0
  60. package/dist/generate/prisma.generate.d.ts +164 -0
  61. package/dist/generate/prisma.generate.js +278 -0
  62. package/dist/generate/reader-crosscheck.d.ts +156 -0
  63. package/dist/generate/reader-crosscheck.js +202 -0
  64. package/dist/index.d.ts +5 -0
  65. package/dist/index.js +1 -0
  66. package/dist/prisma-client.interface.d.ts +48 -0
  67. package/dist/prisma-client.interface.js +9 -0
  68. package/dist/prisma.adapter.d.ts +55 -0
  69. package/dist/prisma.adapter.js +105 -0
  70. package/dist/provider/provider-profile.d.ts +53 -0
  71. package/dist/provider/provider-profile.js +91 -0
  72. package/dist/translation/identifier.addressing.d.ts +80 -0
  73. package/dist/translation/identifier.addressing.js +30 -0
  74. package/dist/translation/mutation.translator.d.ts +115 -0
  75. package/dist/translation/mutation.translator.js +580 -0
  76. package/dist/translation/operation.translator.d.ts +273 -0
  77. package/dist/translation/operation.translator.js +377 -0
  78. package/dist/translation/order-pagination.translator.d.ts +86 -0
  79. package/dist/translation/order-pagination.translator.js +159 -0
  80. package/dist/translation/projection.translator.d.ts +115 -0
  81. package/dist/translation/projection.translator.js +151 -0
  82. package/dist/translation/scalar.conversion.d.ts +101 -0
  83. package/dist/translation/scalar.conversion.js +221 -0
  84. package/dist/translation/where.translator.d.ts +79 -0
  85. package/dist/translation/where.translator.js +254 -0
  86. package/package.json +102 -0
@@ -0,0 +1,124 @@
1
+ import { canonicalizeJson } from "@aventara/core";
2
+ /**
3
+ * T-3.2 — `discover()`'s whole runtime half.
4
+ *
5
+ * This module builds no TypeScript program, parses no PSL and calls no Prisma
6
+ * tooling, and that is guaranteed by construction rather than by assertion:
7
+ * its transitive import graph is this file, `discovery-artifact.interface.ts`
8
+ * and `@aventara/core`. Nothing under `generate/` is reachable from here, and
9
+ * neither is `typescript`, `prisma`, `@prisma/*`, `node:child_process` or
10
+ * `node:fs`. `artifact.loader.spec.ts` walks that graph from source and fails
11
+ * if a specifier appears that should not.
12
+ *
13
+ * The loader reads no file at all: the artifact arrives as a value, and hashing
14
+ * uses `globalThis.crypto.subtle`, so it needs no import either. It checks the
15
+ * two facts the runtime can still get wrong — that the artifact matches itself
16
+ * (`modelHash`) and that the installed `@prisma/client` major is the one it was
17
+ * generated against (C-846) — and nothing else. The model is derived at
18
+ * generate time from the schema and the generated client read in the same
19
+ * instant and cross-checked there, so the runtime never sees the schema and
20
+ * never asks after it.
21
+ */
22
+ /** The `sha256:<hex>` convention core already uses for Contract identity. */
23
+ const HASH_PREFIX = "sha256:";
24
+ /**
25
+ * A stale or corrupt artifact is answered the way cross-phase invariant 15
26
+ * answers a Contract-hash mismatch: fail hard, and say what to run.
27
+ */
28
+ const REGENERATION_INSTRUCTION = "Regenerate the discovery artifact with the adapter's generate step " +
29
+ "(`aventara-prisma7-generate`) and redeploy it " +
30
+ "alongside the schema and client it was generated from.";
31
+ /** Every artifact failure is this class, and every one of them says how to fix it. */
32
+ export class PrismaDiscoveryArtifactError extends Error {
33
+ constructor(reason) {
34
+ super(`${reason} ${REGENERATION_INSTRUCTION}`);
35
+ this.name = "PrismaDiscoveryArtifactError";
36
+ }
37
+ }
38
+ function hex(digest) {
39
+ return Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("");
40
+ }
41
+ async function sha256(text) {
42
+ const bytes = new TextEncoder().encode(text);
43
+ const digest = await globalThis.crypto.subtle.digest("SHA-256", bytes);
44
+ return `${HASH_PREFIX}${hex(digest)}`;
45
+ }
46
+ /**
47
+ * The identity of a discovered model: one canonicalization, one digest — over
48
+ * the model and **nothing else**. The artifact's `translation` half is Prisma
49
+ * addressing, and hashing it would put a DB-side rename into the Contract
50
+ * identity; its `referentialActions` half is what a delete does below the ORM
51
+ * entrypoint, and hashing it would put a foreign-key action into the Contract
52
+ * identity and into every generated client.
53
+ */
54
+ export async function computeModelHash(model) {
55
+ return sha256(canonicalizeJson(model));
56
+ }
57
+ function isRecord(value) {
58
+ return typeof value === "object" && value !== null && !Array.isArray(value);
59
+ }
60
+ function majorOf(version) {
61
+ const major = /^(\d+)\./.exec(version)?.[1];
62
+ return major;
63
+ }
64
+ /** Shape validation, before any hash is computed over a value that may not have one. */
65
+ function assertArtifactShape(artifact) {
66
+ if (!isRecord(artifact)) {
67
+ throw new PrismaDiscoveryArtifactError("The discovery artifact is not a JSON object.");
68
+ }
69
+ for (const key of ["prismaVersion", "provider", "modelHash"]) {
70
+ if (typeof artifact[key] !== "string") {
71
+ throw new PrismaDiscoveryArtifactError(`The discovery artifact's \`${key}\` is not a string.`);
72
+ }
73
+ }
74
+ if (!isRecord(artifact.model)) {
75
+ throw new PrismaDiscoveryArtifactError("The discovery artifact's `model` is not a JSON object.");
76
+ }
77
+ // The two beside-the-model halves are checked as members, not as content: this
78
+ // function asserts the artifact IS a `PrismaDiscoveryArtifact`, and an
79
+ // assertion that skipped a declared member would be a lie its consumer pays
80
+ // for. Their entries are not walked here — the runtime half hashes and returns
81
+ // the model, the executor reads its own addressing keys, and a cascade planner
82
+ // reads its own edges.
83
+ //
84
+ // `referentialActions` is checked for the same reason as `translation` and with
85
+ // the same consequence: an artifact emitted before the key existed is refused
86
+ // here and regenerated, rather than reaching a planner as `undefined`.
87
+ for (const key of ["translation", "referentialActions"]) {
88
+ if (!isRecord(artifact[key])) {
89
+ throw new PrismaDiscoveryArtifactError(`The discovery artifact's \`${key}\` is not a JSON object.`);
90
+ }
91
+ }
92
+ for (const key of ["scalars", "enums", "resources"]) {
93
+ if (!isRecord(artifact.model[key])) {
94
+ throw new PrismaDiscoveryArtifactError(`The discovery artifact's \`model.${key}\` is not a JSON object.`);
95
+ }
96
+ }
97
+ if (artifact.model.transactions !== "none" &&
98
+ artifact.model.transactions !== "interactive") {
99
+ throw new PrismaDiscoveryArtifactError("The discovery artifact's `model.transactions` is not a transaction capability.");
100
+ }
101
+ }
102
+ /**
103
+ * Validates an artifact and hands back its model **unchanged**.
104
+ *
105
+ * Three checks, in the order that makes each one's failure legible: shape, then
106
+ * the `prismaVersion` major fence (C-846), then `modelHash`.
107
+ */
108
+ export async function loadDiscoveryArtifact(load) {
109
+ const { artifact, installedPrismaVersion } = load;
110
+ assertArtifactShape(artifact);
111
+ const artifactMajor = majorOf(artifact.prismaVersion);
112
+ const installedMajor = majorOf(installedPrismaVersion);
113
+ if (artifactMajor === undefined || installedMajor === undefined) {
114
+ throw new PrismaDiscoveryArtifactError(`A Prisma version is not a major.minor.patch version: the artifact declares \`${artifact.prismaVersion}\` and the installed client reports \`${installedPrismaVersion}\`.`);
115
+ }
116
+ if (artifactMajor !== installedMajor) {
117
+ throw new PrismaDiscoveryArtifactError(`The discovery artifact was generated against Prisma major ${artifactMajor}, and the installed client is major ${installedMajor}. The P-code surface and the generated-client grammar are version-bound (C-846).`);
118
+ }
119
+ const modelHash = await computeModelHash(artifact.model);
120
+ if (modelHash !== artifact.modelHash) {
121
+ throw new PrismaDiscoveryArtifactError("The discovery artifact's `modelHash` does not match its own `model`, so the artifact is corrupt or was edited by hand.");
122
+ }
123
+ return artifact.model;
124
+ }
@@ -0,0 +1,191 @@
1
+ /**
2
+ * T-3, source **TYPE** — the output of the reader over the generated client's
3
+ * 🟢 public types.
4
+ *
5
+ * Nothing here is imported from `@prisma/client`: these are this adapter's own
6
+ * facts over public generated types, which is what keeps discovery a pure
7
+ * function of plain data and unit-testable without a client (T-3).
8
+ *
9
+ * Read `types.reader.ts`'s header for the two rules that give these facts their
10
+ * meaning: only the 🟢 files are opened, and token-shaped facts come from the
11
+ * **written** type arguments rather than from the instantiated reference.
12
+ */
13
+ export type PrismaCapabilitySurface = {
14
+ /** The EXISTENCE GATE: an entity is discoverable iff it appears here (T-3.1 invariant 3). */
15
+ readonly resources: Readonly<Record<string, PrismaResourceSurface>>;
16
+ /** `enums.ts`'s `as const` objects, in property order. */
17
+ readonly enums: Readonly<Record<string, readonly string[]>>;
18
+ };
19
+ export type PrismaResourceSurface = {
20
+ /** `$<M>Payload.scalars` ∪ `<M>FieldRefs`. */
21
+ readonly scalarFields: Readonly<Record<string, PrismaScalarSurface>>;
22
+ readonly relationFields: Readonly<Record<string, PrismaRelationSurface>>;
23
+ /** `AtLeast<…, K>`'s key union — cross-check only; order unused. */
24
+ readonly uniqueKeys: readonly string[];
25
+ /** `<M>Delegate`'s own methods → `ResourceOperations`. */
26
+ readonly operations: readonly string[];
27
+ /** e.g. `updateMany` → `["data", "where", "limit"]`. */
28
+ readonly manyWriteArguments: Readonly<Record<string, readonly string[]>>;
29
+ };
30
+ export type PrismaScalarSurface = {
31
+ /** `FieldRef<"M", 'String'>` — the scalar token, or the enum's name. */
32
+ readonly token: string;
33
+ /** `<Kind>Filter` keys, in Prisma's spelling — NAMES ONLY. */
34
+ readonly filters: readonly string[];
35
+ /**
36
+ * The operand SHAPE per filter key, as written in the generated type — because
37
+ * two engines can carry the same key with different operands, and a name set
38
+ * cannot express that (D-802): `path` is `string[]` on PostgreSQL and `string`
39
+ * on SQLite, and `in`/`notIn` admit `List<Kind>FieldRefInput` on PostgreSQL
40
+ * only. Read, not tabulated — T-3.1 invariant 6.
41
+ */
42
+ readonly filterOperands: Readonly<Record<string, string>>;
43
+ /**
44
+ * `<M>UncheckedCreateInput`'s entry for this field, read as the keys of the
45
+ * `…Input` it references: `[]` for a plain value, and **`null` where the client
46
+ * exposes no entry at all**, which is the only evidence that a column is not
47
+ * creatable.
48
+ *
49
+ * The UNCHECKED input is the source because it is what the delegate accepts:
50
+ * `create`'s argument is `XOR<<M>CreateInput, <M>UncheckedCreateInput>`, and the
51
+ * checked half omits every foreign-key scalar (the relation owns it there). Read
52
+ * from the checked half, `Post.authorId` and `Post.categoryId` come back absent
53
+ * and Aventara would refuse writes Prisma accepts.
54
+ */
55
+ readonly createOperations: readonly string[] | null;
56
+ /**
57
+ * Whether `<M>UncheckedCreateInput` writes this member with a `?`.
58
+ *
59
+ * A **different fact** from {@link createOperations}, which is why both are
60
+ * recorded: `createOperations` answers *what may be written* — the directive
61
+ * keys, `[]` for a plain value and `null` where the client exposes no entry at
62
+ * all — and erases the question mark on the way. `createOptional` answers
63
+ * *whether a value may be omitted*, and nothing else on this surface carries
64
+ * it.
65
+ *
66
+ * It is **one bit over several causes** — `@default(…)`, `@updatedAt`, plain
67
+ * nullability, and a scalar list, which needs no value because the empty list
68
+ * is one — so it is never read as a lifecycle trait. Its only consumer is
69
+ * `field.mapper.ts`'s `crossCheckCreateOptional`, which runs it as a check in
70
+ * one direction: every member the types mark optional must have a PSL cause.
71
+ * Deriving a trait from it would make the two readers agree by construction
72
+ * and detect nothing.
73
+ *
74
+ * `false` where the client exposes no entry for the column at all, which
75
+ * {@link createOperations}`=== null` is the evidence for; the two never
76
+ * disagree about presence because they are read from the same member.
77
+ */
78
+ readonly createOptional: boolean;
79
+ /**
80
+ * `<M>UncheckedUpdateInput`'s entry, read the same way — the keys of
81
+ * `<Kind>FieldUpdateOperationsInput`, or of `<M>Update<field>Input` for a scalar
82
+ * list (`set`, `push`), or `[]` for a plain value (`Json`), or `null` where the
83
+ * client exposes no entry.
84
+ *
85
+ * Measured at 7.10.0 (2026-10-02): reading `<M>UpdateInput` instead under-reports
86
+ * six of the twenty-five scalar columns per engine — `Author.mentorId`,
87
+ * `Metric.authorId`, `Post.authorId`, `Post.categoryId`, `Category.id` and
88
+ * `Post.id` — every one of which `<M>UncheckedUpdateInput` admits.
89
+ */
90
+ readonly updateOperations: readonly string[] | null;
91
+ readonly orderable: boolean;
92
+ /** `SortOrderInput` admitted for this field. */
93
+ readonly nullsOrderable: boolean;
94
+ };
95
+ export type PrismaRelationSurface = {
96
+ /** Read off `$<Target>Payload`'s own `name` literal, never off the alias's spelling. */
97
+ readonly target: string;
98
+ readonly many: boolean;
99
+ readonly nullable: boolean;
100
+ /** `ListRelationFilter` vs `[Nullable]ScalarRelationFilter`. */
101
+ readonly filters: readonly string[];
102
+ /**
103
+ * `<T>CreateNested{One,Many}Without<M>Input` keys — the **create** stage's own
104
+ * nested-write input, read off `<M>CreateInput`'s entry for this edge.
105
+ *
106
+ * A SEPARATE fact from {@link updateMutations}, and the separation is the C-855
107
+ * invariant: the create-stage input carries `create`, `connectOrCreate`,
108
+ * `createMany` (to-many only) and `connect` and nothing else, where the
109
+ * update-stage input carries eight more. Reusing one list for both stages
110
+ * advertises five directives per to-many edge, and two per to-one edge, that
111
+ * Prisma has no key for at the create stage.
112
+ */
113
+ readonly createMutations: readonly string[];
114
+ /** `<T>Update*Without<M>NestedInput` keys — the **update** stage's own input. */
115
+ readonly updateMutations: readonly string[];
116
+ /**
117
+ * `<M>$<edge>Args`'s own member names, as written. The edge's whole argument
118
+ * surface, because four separate capabilities are read off it — pagination,
119
+ * ordering, nested filtering of the returned edge, and projection — and a
120
+ * residual cannot answer the other three.
121
+ */
122
+ readonly edgeArguments: readonly string[];
123
+ /**
124
+ * {@link edgeArguments} minus what projection and predicate already own — a
125
+ * derived projection kept because it is the one a to-one/to-many split reads at
126
+ * a glance: a to-one edge leaves nothing.
127
+ */
128
+ readonly pagination: readonly string[];
129
+ /** The edge is admitted by `<M>OrderByWithRelationInput`. */
130
+ readonly orderable: boolean;
131
+ /** `_count` on `<M>Include` / `<M>CountOutputType`. */
132
+ readonly reducers: readonly string[];
133
+ /**
134
+ * Whether **every** `<M>Select{Create,Update}ManyAndReturn` the client declares
135
+ * lists this edge.
136
+ *
137
+ * # Presence, read. Not foreign-key ownership, computed
138
+ *
139
+ * The *explanation* for which edges survive into a bulk-returning write's
140
+ * projection is foreign-key ownership rather than cardinality — a to-one that
141
+ * does not hold its own FK is absent, which is what the `User`/`Profile`
142
+ * fixture exists to prove. That explanation is **not** the mechanism. The
143
+ * mechanism is this member: the edge is in the type, or it is not.
144
+ *
145
+ * Deriving FK ownership here instead would be a tabulated provider-dependent
146
+ * fact — the shape §18.4 forbids and D-802 exists to prevent — and it would be
147
+ * wrong the first time Prisma changes which relations it admits into the
148
+ * projection, while a presence read simply tells the truth again.
149
+ *
150
+ * **Every**, not *any*: one {@link ProjectionScope} covers both bulk-returning
151
+ * variants, so a scope the adapter advertises must hold in both. At 7.10.0 the
152
+ * two types agree member-for-member on both pilot engines, so the conjunction
153
+ * is currently indistinguishable from either half — `types.reader.spec.ts`
154
+ * asserts that agreement, so the day it stops holding is the day a reader
155
+ * reports it instead of silently picking a side. **Zero declared types answer
156
+ * `false`**, never vacuously `true`: a client with no `*AndReturn` type admits
157
+ * nothing there.
158
+ */
159
+ readonly bulkSelect: boolean;
160
+ /** The {@link bulkSelect} question asked of `<M>Include{Create,Update}ManyAndReturn`. */
161
+ readonly bulkInclude: boolean;
162
+ /**
163
+ * Whether `_count` is listed by every one of those **four** types — the same
164
+ * presence question, asked of the reducer key rather than of the edge.
165
+ *
166
+ * A model-level fact carried on each edge because the capability it qualifies
167
+ * is the edge's: `RelationFieldCapabilities.reducers` says which reducers *this
168
+ * relation* admits, and `_count` is the one projection key all of them are
169
+ * asked for through.
170
+ */
171
+ readonly bulkReducers: boolean;
172
+ /**
173
+ * Whether `<M>CreateManyInput` — the data argument of the bulk create — exposes
174
+ * an entry for this edge.
175
+ *
176
+ * The write-side mirror of {@link bulkSelect}, and read the same way: C-818's
177
+ * rule (*no nested `create`/`connect` inside a top-level `createMany()` or
178
+ * `createManyAndReturn()`*) is a **consequence** of the bulk input carrying no
179
+ * relation member, never a row this adapter keeps.
180
+ */
181
+ readonly bulkCreatable: boolean;
182
+ /**
183
+ * Whether `<M>UpdateManyMutationInput` or `<M>UncheckedUpdateManyInput` exposes
184
+ * an entry for this edge.
185
+ *
186
+ * Both halves, because `updateMany`'s `data` is the `XOR` of them — exactly the
187
+ * reason {@link PrismaScalarSurface.updateOperations} reads the unchecked half:
188
+ * reading one input alone under-reports what the delegate accepts.
189
+ */
190
+ readonly bulkUpdatable: boolean;
191
+ };
@@ -0,0 +1,13 @@
1
+ /**
2
+ * T-3, source **TYPE** — the output of the reader over the generated client's
3
+ * 🟢 public types.
4
+ *
5
+ * Nothing here is imported from `@prisma/client`: these are this adapter's own
6
+ * facts over public generated types, which is what keeps discovery a pure
7
+ * function of plain data and unit-testable without a client (T-3).
8
+ *
9
+ * Read `types.reader.ts`'s header for the two rules that give these facts their
10
+ * meaning: only the 🟢 files are opened, and token-shaped facts come from the
11
+ * **written** type arguments rather than from the instantiated reference.
12
+ */
13
+ export {};
@@ -0,0 +1,92 @@
1
+ import type { RelationFieldCapabilities, ScalarFieldCapabilities, ScalarFilterOperator } from "@aventara/core";
2
+ import type { PrismaRelationSurface, PrismaScalarSurface } from "./capability-surface.interface.js";
3
+ /**
4
+ * T-6 — field capabilities, derived from the generated client's own types.
5
+ *
6
+ * # The input is narrower than T-6 writes it, and the narrowing IS the invariant
7
+ *
8
+ * T-6 spells `ScalarCapabilityInput` as `{ field, surface, mapping, profile }`.
9
+ * This module accepts `surface` alone, and that is deliberate: dictionary
10
+ * invariant 6 says a capability is read from the client's own types and never
11
+ * tabulated from a provider row, and the strongest available mechanism for that is
12
+ * to make the provider **unrepresentable** rather than merely unread. A
13
+ * `PrismaProviderProfile` in this input is a `provider` member one keystroke from
14
+ * a branch; with no such member, `if (provider === …)` is a compile error, and the
15
+ * three per-engine differences this pass exists to prove — `mode`, `JsonFilter`'s
16
+ * ordering operators, and the `path` / `in` / `notIn` operand shapes — have to come
17
+ * from the surface because nothing else is in scope.
18
+ *
19
+ * Dropping `field` has the same effect on C-812: a lifecycle trait cannot grant a
20
+ * capability if no lifecycle trait can be passed. `mapping` went with them because
21
+ * nothing here reads an Aventara scalar identity to answer a capability question.
22
+ *
23
+ * **This is a deviation from T-6 and is reported as one.** It predicted that the
24
+ * `path` question — omit, or translate, where the operand is a JSONPath string —
25
+ * would need `mapping` back. **Task 7 settled it and did not:** see
26
+ * {@link translatable}. The answer is read off the recorded operand shape, which
27
+ * is already on the surface; the Aventara scalar identity would have been a
28
+ * second, weaker source for the same fact. `mapping` stays out.
29
+ *
30
+ * # Order is canonical, not incidental
31
+ *
32
+ * Every list is emitted in **core's own union declaration order**, held below as a
33
+ * closed ordered array. Prisma's declaration order is an input, not a semantic
34
+ * fact, and C-843 wants two generate runs byte-identical; ordering by the Aventara
35
+ * union makes the output independent of how a generator happens to write a member
36
+ * list, while keeping the array reviewable against `contracts/capability.ts`.
37
+ *
38
+ * # Absent and empty are different answers
39
+ *
40
+ * `create: []` / `update: []` mean **writable with no directive** — plain
41
+ * assignment, which is what `set` alone is. An absent `create` / `update` means
42
+ * **not writable**, and core enforces exactly that: `validateScalarMutation`
43
+ * answers `V1006` *"is not writable during <stage>"* when the member is
44
+ * `undefined` **[CORE, operations/operation-validator-core.ts]**. So the two must
45
+ * not be conflated, and the surface's `null` (the client exposes no entry for this
46
+ * column at this stage) is the only thing that produces the absent form.
47
+ */
48
+ /** A Prisma spelling that no dictionary table recognises: a build stop, never a drop. */
49
+ export declare class PrismaCapabilityDerivationError extends Error {
50
+ readonly name = "PrismaCapabilityDerivationError";
51
+ }
52
+ /**
53
+ * T-6's `ScalarCapabilityInput`, narrowed — see this module's header.
54
+ *
55
+ * An object rather than a bare parameter because T-6 names an input type and
56
+ * because a later pass may legitimately add `mapping` back.
57
+ */
58
+ export type ScalarCapabilityInput = {
59
+ readonly surface: PrismaScalarSurface;
60
+ };
61
+ /**
62
+ * A relation's capabilities are answered for the field, not for an operation.
63
+ *
64
+ * The `operation: "create.one" | "create.many"` parameter this input used to carry
65
+ * is **gone**. It existed because C-818's answer differs between the singular and
66
+ * the bulk create and the capability shape had nowhere to put the difference, so
67
+ * composition had to pick one variant's answer and the other was unrepresentable —
68
+ * `model.discoverer.ts` recorded that as an open conflict. The scope-qualified
69
+ * members hold both answers at once, so there is nothing left to pick and no caller
70
+ * left to pick it.
71
+ */
72
+ export type RelationCapabilityInput = {
73
+ readonly surface: PrismaRelationSurface;
74
+ };
75
+ export declare function deriveScalarCapabilities(input: ScalarCapabilityInput): ScalarFieldCapabilities;
76
+ /**
77
+ * The Prisma operand for each ADVERTISED operator, keyed by the Aventara name.
78
+ *
79
+ * T-6's three signatures return core types unchanged, and `ScalarFieldCapabilities`
80
+ * has nowhere to put an operand shape — yet the shape is exactly where two engines
81
+ * differ on keys they both carry (`JsonFilter.path` is `string[]` on one and
82
+ * `string` on the other; `in`/`notIn` admit `List<Kind>FieldRefInput` on one only).
83
+ * A deriver that answered operator NAMES alone would report the two engines
84
+ * identical where they are not, so the shape is carried beside the capability
85
+ * rather than discarded.
86
+ *
87
+ * Keyed by the Aventara operator so Task 7 reads a shape without re-running the
88
+ * rename — and so a provider branch has nothing to be for (§Open question,
89
+ * "How the `path` filter operator is emitted per provider").
90
+ */
91
+ export declare function deriveScalarFilterOperands(input: ScalarCapabilityInput): Readonly<Partial<Record<ScalarFilterOperator, string>>>;
92
+ export declare function deriveRelationCapabilities(input: RelationCapabilityInput): RelationFieldCapabilities;