@aventara/prisma7-adapter 0.1.0-pilot.2 → 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.
Files changed (48) hide show
  1. package/README.md +22 -22
  2. package/dist/discovery/artifact.loader.d.ts +2 -7
  3. package/dist/discovery/artifact.loader.js +4 -0
  4. package/dist/discovery/capability-surface.interface.d.ts +2 -66
  5. package/dist/discovery/capability.deriver.d.ts +2 -47
  6. package/dist/discovery/discovery-artifact.interface.d.ts +34 -155
  7. package/dist/discovery/discovery-artifact.interface.js +1 -1
  8. package/dist/discovery/enum.mapper.d.ts +0 -24
  9. package/dist/discovery/field.mapper.d.ts +3 -114
  10. package/dist/discovery/field.mapper.js +6 -6
  11. package/dist/discovery/identifier.mapper.d.ts +4 -84
  12. package/dist/discovery/model.discoverer.d.ts +2 -69
  13. package/dist/discovery/operations.deriver.d.ts +0 -36
  14. package/dist/discovery/scalar.mapper.d.ts +1 -32
  15. package/dist/discovery/scalar.mapper.js +2 -2
  16. package/dist/discovery/schema-facts.interface.d.ts +3 -83
  17. package/dist/discovery/schema.reader.d.ts +0 -133
  18. package/dist/discovery/types.reader.d.ts +1 -9
  19. package/dist/discovery/types.reader.js +7 -7
  20. package/dist/discovery/vocabulary.dictionary.d.ts +6 -133
  21. package/dist/discovery/vocabulary.dictionary.js +2 -2
  22. package/dist/errors/error.normalizer.d.ts +5 -168
  23. package/dist/errors/prisma-error.reader.d.ts +1 -93
  24. package/dist/execution/first-variant.emulator.d.ts +5 -28
  25. package/dist/execution/operation.executor.d.ts +1 -62
  26. package/dist/execution/result.shaper.d.ts +0 -56
  27. package/dist/execution/transaction.executor.d.ts +0 -98
  28. package/dist/generate/artifact.emitter.d.ts +1 -35
  29. package/dist/generate/artifact.emitter.js +26 -43
  30. package/dist/generate/declared-support.reader.d.ts +0 -20
  31. package/dist/generate/discovery.cli.d.ts +0 -4
  32. package/dist/generate/existence.gate.d.ts +3 -37
  33. package/dist/generate/index.d.ts +4 -57
  34. package/dist/generate/prisma-cli.resolver.d.ts +0 -22
  35. package/dist/generate/prisma.generate.d.ts +14 -83
  36. package/dist/generate/reader-crosscheck.d.ts +3 -88
  37. package/dist/generate/reader-crosscheck.js +4 -4
  38. package/dist/prisma-client.interface.d.ts +5 -25
  39. package/dist/prisma.adapter.d.ts +21 -22
  40. package/dist/provider/provider-profile.d.ts +6 -14
  41. package/dist/translation/identifier.addressing.d.ts +0 -38
  42. package/dist/translation/mutation.translator.d.ts +5 -51
  43. package/dist/translation/operation.translator.d.ts +1 -102
  44. package/dist/translation/order-pagination.translator.d.ts +1 -47
  45. package/dist/translation/projection.translator.d.ts +1 -46
  46. package/dist/translation/scalar.conversion.d.ts +0 -64
  47. package/dist/translation/where.translator.d.ts +0 -52
  48. package/package.json +3 -2
@@ -1,66 +1,13 @@
1
1
  import type { AdapterLifecycleTrait, BuiltInScalar, PaginationCapability, RelationFilterCapability, RelationMutationDirective, ScalarFilterOperator, ScalarFormat, ScalarMutationDirective } from "@aventara/core";
2
- /**
3
- * # It is data, not conditionals
4
- *
5
- * # Every entry names its source class (invariant 1)
6
- *
7
- * `VOCABULARY` carries one row per Aventara fact with its source code — `PSL`,
8
- * `TYPE`, `RUN`, `DRIVER` or `CFG`. `VocabularyEntry.sources` is a **non-empty**
9
- * tuple, so "an entry with no source" is a compile error rather than a silent
10
- * default.
11
- *
12
- * # `@default` is matched, never parsed (invariant 5)
13
- *
14
- * `PRISMA_DEFAULT_TABLE` is looked up with the raw text the PSL reader carried
15
- * across unchanged. `dbgenerated("gen_random_uuid()")` is a **key**, not an
16
- * expression: the day this module evaluates one, the reader behind it has become a
17
- * parser and needs a different decision. An unmatched form falls back to
18
- * `PRISMA_UNMATCHED_DEFAULT_TRAITS` **plus** a recorded unknown that fails the
19
- * generate step — never an inferred trait.
20
- *
21
- * `@db.*` is matched the same way, by its **exact written spelling**
22
- * (`PRISMA_NATIVE_FORMATS`). `@db.Decimal(10, 2)` matches no key and therefore
23
- * proves no format, which is the right answer arrived at without splitting an
24
- * argument list.
25
- *
26
- * # This dictionary proposes no `CONTEXT.md` term
27
- *
28
- * It is adapter-internal data, not framework vocabulary. Its job is the opposite:
29
- * no Prisma term reaches `AdapterModel` (invariant 2) — `AtLeast`,
30
- * `WhereUniqueInput`, `FieldRef`, `@@map`, `take`/`skip` all die here.
31
- */
32
- /**
33
- * `PSL` — `schema.prisma` · `TYPE` — the 🟢 generated types ·
34
- * `RUN` — observed runtime behaviour · `DRIVER` — the configured Prisma driver
35
- * adapter · `CFG` — framework configuration, which is policy and not discovery.
36
- */
37
2
  export type VocabularySource = "PSL" | "TYPE" | "RUN" | "DRIVER" | "CFG";
38
3
  export type VocabularyEntry = {
39
4
  readonly fact: string;
40
- /** Non-empty by construction: invariant 1 is enforced by the type, not by a comment. */
41
5
  readonly sources: readonly [VocabularySource, ...VocabularySource[]];
42
6
  readonly rule: string;
43
7
  };
44
- /**
45
- * So the source is `PSL` **and** `CFG`: discovery emits what the provider's own
46
- * column type proves, configuration owns everything else. `scalar.mapper.ts`'s
47
- * header carries the full argument.
48
- */
49
8
  export declare const VOCABULARY: readonly VocabularyEntry[];
50
- /**
51
- * The closed set of ways a mapper refuses. It is dictionary data because a
52
- * refusal is the dictionary's own answer: a construct it has no word for.
53
- */
54
- export type PrismaDiscoveryDiagnosticCode =
55
- /** A Prisma type name in neither PRISMA_SCALAR_TABLE nor `enums.ts`. */
56
- "unmapped-prisma-type"
57
- /**
58
- * PSL declares it, the 🟢 types do not expose it: omitted, with the reason said
59
- * out loud.
60
- */
61
- | "not-exposed"
62
- /** PSL and `enums.ts` disagree about an enum's members or their order. */
63
- | "enum-diverged";
9
+ /** The closed set of ways a mapper refuses. */
10
+ export type PrismaDiscoveryDiagnosticCode = "unmapped-prisma-type" | "not-exposed" | "enum-diverged";
64
11
  export type PrismaDiscoveryDiagnostic = {
65
12
  readonly code: PrismaDiscoveryDiagnosticCode;
66
13
  /** Written for the engineer who has to fix the schema, naming the entity it is about. */
@@ -71,39 +18,13 @@ export type PrismaScalarMapping = {
71
18
  readonly format?: ScalarFormat;
72
19
  };
73
20
  export type PrismaScalarTable = Readonly<Record<string, PrismaScalarMapping>>;
74
- /**
75
- * Total and 1:1 over `BUILT_IN_SCALARS` **[CORE]**. There is no default arm: a
76
- * Prisma type name absent from this table is a diagnostic, not a guess.
77
- *
78
- * **No row carries a `format`**, and that is the point: a format is a property of
79
- * a *column*, not of a Prisma *type name*. `String` alone proves nothing, so the
80
- * one thing that can prove something — the native column type — is a separate
81
- * lookup (`PRISMA_NATIVE_FORMATS`).
82
- */
21
+ /** Total and 1:1 over `BUILT_IN_SCALARS` **[CORE]**. */
83
22
  export declare const PRISMA_SCALAR_TABLE: PrismaScalarTable;
84
23
  /**
85
24
  * The only `@db.*` spellings that **prove** a format, matched by exact written
86
25
  * spelling and never parsed.
87
- *
88
- * The bar for a row here is not "the name suggests a format". It is: **the column
89
- * type itself rejects the values `format` would later reject.** `format` is
90
- * enforced, not decorative — `normalizeScalarFieldValue` turns `format: "uuid"`
91
- * into a `V1003` rejection of request input **[CORE,
92
- * `runtime/scalar-runtime.ts`]** — so a row that is merely probable would have
93
- * Aventara refuse writes the database accepts.
94
- *
95
- * `@db.Uuid` clears that bar: PostgreSQL's `uuid` column rejects `'not-a-uuid'`
96
- * (`ERROR: invalid input syntax for type uuid`) where a `text` column takes it
97
- * **[RUN8 — 2026-09-28, `aventara-postgres`, postgres:18]**.
98
- *
99
- * That intent belongs in `FrameworkScalarFieldConfig.format` **[CORE]**, which the
100
- * Contract compiler already applies over the adapter's value.
101
- *
102
- * `@db.Decimal(10, 2)` and `@db.VarChar(255)` are absent because they prove no
103
- * *format*; they carry precision and width, which Aventara has no word for.
104
26
  */
105
27
  export declare const PRISMA_NATIVE_FORMATS: Readonly<Record<string, ScalarFormat>>;
106
- /** Whether a row was exercised against 7.10.0 or is carried forward unproven. */
107
28
  export type PrismaEvidence = "RUN8" | "UNVERIFIED";
108
29
  export type PrismaDefaultRow = {
109
30
  /**
@@ -119,13 +40,6 @@ export type PrismaDefaultRow = {
119
40
  readonly traits: readonly AdapterLifecycleTrait[];
120
41
  readonly evidence: PrismaEvidence;
121
42
  };
122
- /**
123
- * This table states the answer rather than half of it, so no consumer has to
124
- * remember to add the other half.
125
- *
126
- * The lookup that walks this table lives with the lifecycle projection, where it
127
- * can be driven red; this pass owns the data only.
128
- */
129
43
  export declare const PRISMA_DEFAULT_TABLE: readonly PrismaDefaultRow[];
130
44
  /**
131
45
  * Any other text — `"BRONZE"`, `"x"`, `sequence()`, `nanoid()`, a spelling added
@@ -138,42 +52,12 @@ export declare const PRISMA_UNMATCHED_DEFAULT_TRAITS: readonly AdapterLifecycleT
138
52
  /**
139
53
  * The dictionary's other half: the point at which Prisma's spelling stops and
140
54
  * Aventara's begins.
141
- *
142
- * **One untyped `PRISMA_RENAMES` became six typed tables.** The single
143
- * `Record<string, string>` could not make a mistake a compile error: a rename to a
144
- * word core does not have, or a Prisma key nobody decided about, both typechecked.
145
- * Each table below is keyed on the Prisma spelling and valued in the ONE Aventara
146
- * vocabulary that spelling can land in, so `"arrayContains"` misspelt fails to
147
- * compile. The table had no consumer, so nothing was broken by splitting it.
148
- *
149
- * `null` is a value, not an omission: it means **recognised, and Aventara has no
150
- * word for it** — the nested bulk writes, `distinct`, Prisma's `set` assignment.
151
- *
152
- * This is the vocabulary half only.
153
- */
154
- /**
155
- * `<Kind>Filter` / `<Kind>NullableFilter` / `Json[Nullable]Filter` keys.
156
- *
157
- * Total and 1:1 over `ScalarFilterOperator` **[CORE]** at 7.10.0, measured over
158
- * both generated clients: 23 Prisma keys, 23 Aventara operators, no survivor on
159
- * either side.
160
55
  */
56
+ /** `<Kind>Filter` / `<Kind>NullableFilter` / `Json[Nullable]Filter` keys. */
161
57
  export declare const PRISMA_FILTER_OPERATORS: Readonly<Record<string, ScalarFilterOperator>>;
162
- /**
163
- * `[Nullable]ScalarRelationFilter` and `ListRelationFilter` keys.
164
- *
165
- * `nested` and `null` are **not** keys of any filter input — they are read off the
166
- * edge's own `where` argument and off the edge's nullability — so they are absent
167
- * here by construction rather than by omission.
168
- */
58
+ /** `[Nullable]ScalarRelationFilter` and `ListRelationFilter` keys. */
169
59
  export declare const PRISMA_RELATION_FILTERS: Readonly<Record<string, RelationFilterCapability>>;
170
- /**
171
- * `<Kind>FieldUpdateOperationsInput` and `<M><Stage><field>Input` keys.
172
- *
173
- * `set` is `null` because plain assignment is not a directive in Aventara: the
174
- * value is written directly, and `ScalarMutationDirective` has no `$set`
175
- * **[CORE]**.
176
- */
60
+ /** `<Kind>FieldUpdateOperationsInput` and `<M><Stage><field>Input` keys. */
177
61
  export declare const PRISMA_SCALAR_DIRECTIVES: Readonly<Record<string, ScalarMutationDirective | null>>;
178
62
  /**
179
63
  * `<M>Update<edge>Without<M>NestedInput` / `<M>Create<edge>…NestedInput` keys.
@@ -205,15 +89,4 @@ export type ObservedValueShape = {
205
89
  readonly engines: readonly string[];
206
90
  readonly evidence: PrismaEvidence;
207
91
  };
208
- /**
209
- * Identical through both driver adapters, so the representation is not
210
- * driver-dependent *between these two engines* — which is a narrower claim than
211
- * "not driver-dependent", and the narrower one is what was measured.
212
- *
213
- * A row is `RUN8` only where a read-back value was actually asserted. `String`,
214
- * `Boolean`, `Int` and `Float` were written into a row and never read back under
215
- * assertion, so they stay `[UNVERIFIED]`: a plausible value shape is not an
216
- * observed one, and this table exists precisely so that nobody has to guess which
217
- * is which.
218
- */
219
92
  export declare const OBSERVED_VALUE_SHAPES: readonly ObservedValueShape[];
@@ -7,7 +7,7 @@ export const VOCABULARY = [
7
7
  {
8
8
  fact: "nullable",
9
9
  sources: ["PSL"],
10
- rule: "Never TYPE (invariant 4): `JsonValue` contains `null` because JSON null is a value, so a types-derived nullable is wrong for every Json field.",
10
+ rule: "Never TYPE: `JsonValue` contains `null` because JSON null is a value, so a types-derived nullable is wrong for every Json field.",
11
11
  },
12
12
  {
13
13
  fact: "list",
@@ -32,7 +32,7 @@ export const VOCABULARY = [
32
32
  {
33
33
  fact: "relation pairing",
34
34
  sources: ["PSL"],
35
- rule: '`@relation("Mentorship")` on both sides is the only pairing evidence; the name appears nowhere on the 🟢 surface.',
35
+ rule: '`@relation("Mentorship")` on both sides is the only pairing evidence; the name appears nowhere in the generated client.',
36
36
  },
37
37
  {
38
38
  fact: "lifecycle traits",
@@ -1,130 +1,5 @@
1
1
  import { FrameworkError, type OperationErrorCode, type OperationIdentity } from "@aventara/core";
2
2
  import { type PrismaConstraintSubject } from "./prisma-error.reader.js";
3
- /**
4
- * The table's keys are P-codes, which are **7.x's** error surface. Prisma 8
5
- * replaced them with dotted `NAMESPACE.SUBCODE` codes, so a Prisma 8 adapter
6
- * re-maps this module rather than patching it. `error.normalizer.spec.ts` reads
7
- * `@prisma/client`'s own `package.json` and fails if the installed major is not
8
- * `7`, so the bound is enforced rather than described.
9
- *
10
- * ## Every code in the table was induced, not inherited
11
- *
12
- * Nothing here rests on documentation. Each rule was produced by throwing a real
13
- * statement at a real engine on this repository's own schema, on
14
- * `@prisma/adapter-better-sqlite3` and `@prisma/adapter-pg`, both 7.10.0. The
15
- * measured payloads, inlined because the source measurement lives outside the
16
- * repository:
17
- *
18
- * ```text
19
- * P2002 author.create duplicate @unique email
20
- * sqlite meta = { driverAdapterError: { name: "DriverAdapterError", cause: {
21
- * originalCode: "SQLITE_CONSTRAINT_UNIQUE",
22
- * originalMessage: "UNIQUE constraint failed: Author.email",
23
- * kind: "UniqueConstraintViolation",
24
- * constraint: { fields: ["email"] }, table: "Author" } },
25
- * modelName: "Author" }
26
- * pg meta = { driverAdapterError: { name: "DriverAdapterError", cause: {
27
- * originalCode: "23505",
28
- * originalMessage: "duplicate key value violates unique constraint \"Author_email_key\"",
29
- * kind: "UniqueConstraintViolation",
30
- * constraint: { index: "Author_email_key" }, table: "Author" } },
31
- * modelName: "Author" }
32
- *
33
- * P2002 author.create violating @@unique([tenantId, handle])
34
- * sqlite constraint: { fields: ["tenantId", "handle"] }
35
- * pg constraint: { index: "Author_tenantId_handle_key" }
36
- *
37
- * P2003 post.create with an authorId that does not exist
38
- * sqlite meta = { modelName: "Post", driverAdapterError: { cause: {
39
- * originalCode: "SQLITE_CONSTRAINT_FOREIGNKEY",
40
- * originalMessage: "FOREIGN KEY constraint failed",
41
- * kind: "ForeignKeyConstraintViolation",
42
- * constraint: { foreignKey: {} } } } }
43
- * pg constraint: { index: "Post_authorId_fkey" }, originalCode "23503"
44
- *
45
- * P2025 author.update / author.delete on a missing unique selector
46
- * both meta = { modelName: "Author", operation: "an update" }
47
- * both meta = { modelName: "Author", operation: "a delete" }
48
- *
49
- * P2025 nested connect whose target does not exist (create, update, upsert)
50
- * both meta = { modelName: "Post", model: "Author",
51
- * relation: "AuthorToPost", relationType: "one-to-many",
52
- * operation: "a nested connect",
53
- * neededFor: "inline the relation on 'Post' record(s)" }
54
- *
55
- * P2014 author.update with posts.set [] (or posts.disconnect) while a post
56
- * still requires that author
57
- * both meta = { modelName: "Author", relation: "AuthorToPost",
58
- * modelA: "Post", modelB: "Author" }
59
- *
60
- * P2018 author.update with posts.connect to a missing post
61
- * sqlite meta = { modelName: "Author", expectedRows: 1,
62
- * relation: "AuthorToPost", relationType: "one-to-many" }
63
- *
64
- * P2034 two SERIALIZABLE transactions, both reading then both writing
65
- * pg meta = { modelName: "Author", driverAdapterError: { cause: {
66
- * originalCode: "40001",
67
- * originalMessage: "could not serialize access due to concurrent update",
68
- * kind: "TransactionWriteConflict" } } }
69
- * ```
70
- *
71
- * ## Two inherited claims that the measurement refutes
72
- *
73
- * 1. It is **absent from every payload above**; the identifiers are internal rule
74
- * names, not a `meta` key. What 7.10.0 actually emits is two different *key
75
- * sets*, and the discriminant is the presence of `meta.relation` (with
76
- * `meta.model`): present → the failure is about a relation reference; absent →
77
- * the record the call selected was not there.
78
- *
79
- * Also unobserved: the `{}` meta that `expectNonEmpty` was expected to carry.
80
- * `findUniqueOrThrow` and `findFirstOrThrow` both report `{ modelName, operation:
81
- * "a query" }`, so no empty-meta P2025 was produced by any statement tried here.
82
- * Either arm classifies identically under the rule above (no `relation` → root
83
- * record), so the rule is safe either way, but the shape itself stays unverified.
84
- *
85
- * Three distinct situations used to answer the one `A2008 CONFLICT`. Coarse but
86
- * correct, so nothing provisional ever reached the wire and the discriminant was
87
- * purely additive. The observed surface each decision rests on is this:
88
- *
89
- * | Situation | Code | `meta` keys observed | Structurally separable? |
90
- * |---|---|---|---| | Uniqueness violation | `P2002` | `modelName`,
91
- * `driverAdapterError` | **Yes** — distinct P-code; `cause.kind` is
92
- * `"UniqueConstraintViolation"`; `cause.constraint` is `{fields}` (SQLite) or
93
- * `{index}` (PostgreSQL) | | Write conflict / deadlock | `P2034` | `modelName`,
94
- * `driverAdapterError` | **Yes** from a constraint violation — distinct P-code;
95
- * `cause.kind` is `"TransactionWriteConflict"`; **no** `constraint` at all. **No**
96
- * from each other: `cause.originalCode` is `40001` for a write conflict and
97
- * `40P01` for a deadlock, and that field is provider-owned and never crosses the
98
- * boundary | | Lost-row race | *none* | *none* | **Yes, trivially** — there is no
99
- * provider error behind it: it is a zero-row count in a sequence the framework
100
- * manufactured, and it is raised in `execution/first-variant.emulator.ts`, never
101
- * here |
102
- *
103
- * The two provider-backed ones differ by P-code; `driverAdapterError.cause.kind`
104
- * is a second, independent witness.
105
- *
106
- * **A write conflict and a deadlock share `A2013` deliberately.** Both arrive as
107
- * `P2034` with identical `meta` keys, differing only in a provider-owned
108
- * `originalCode` (`40001` versus `40P01`) that never crosses the boundary. They
109
- * are not separable at this seam, so one outcome is the only honest answer;
110
- * splitting them later would need a discriminant that does not exist.
111
- * `describePrismaConflict` is the recorded surface, and `PrismaConstraintSubject`
112
- * records that the two engines do not agree on *which* identifier they can name —
113
- * a uniqueness discriminant that promised the caller the constraint's name would
114
- * be unsatisfiable on SQLite.
115
- *
116
- * **No Prisma path observed here threw a non-`Error`.** Every induced failure
117
- * arrived as a `PrismaClientKnownRequestError`, which extends `Error` (`error
118
- * instanceof Error` was asserted true for all of them), and the one non-Prisma
119
- * failure the engines produced — `better-sqlite3` refusing a missing directory —
120
- * was a `TypeError`. The adapter half is discharged here: `prismaOutcomeFailure`
121
- * returns a `FrameworkError`, so every failure this module originates is an
122
- * `Error` subclass, enforced by a spec.
123
- *
124
- * What keeps it from leaking is this module's own rule: the cause is framework
125
- * text, and the reader never reads `message` at all, so there is no provider
126
- * string in scope to forward.
127
- */
128
3
  /** The three answers a Prisma failure can get. */
129
4
  export type PrismaErrorClassification = {
130
5
  readonly kind: "absence";
@@ -134,62 +9,24 @@ export type PrismaErrorClassification = {
134
9
  } | {
135
10
  readonly kind: "unclassified";
136
11
  };
137
- /**
138
- * When a code is a `null` result rather than a failure.
139
- *
140
- * `subject` is the measured `meta` shape that may be forgiven. The same P2025
141
- * reaches `update.unique` for a second reason — a nested `connect` whose target is
142
- * missing — and that one is a caller error about the *arguments*, not an absent
143
- * record. `"root-record"` means `meta` carries no relation reference; the
144
- * single-member union says that is the one shape measured, and leaves room for a
145
- * second if one is ever observed.
146
- */
147
12
  type PrismaAbsenceRule = {
148
13
  readonly variants: readonly `${string}.${string}`[];
149
14
  readonly subject: "root-record";
150
15
  };
151
16
  type PrismaErrorRule = {
152
- /**
153
- * The outcome this code answers. Typed as core's own `OperationErrorCode`, so the
154
- * adapter cannot widen the code space — a code the table does not contain has no
155
- * rule at all.
156
- */
17
+ /** The outcome this code answers. */
157
18
  readonly outcome: OperationErrorCode;
158
19
  readonly absence?: PrismaAbsenceRule;
159
20
  };
160
- /** One closed table, scoped to `@prisma/client` 7.x. */
161
21
  export type PrismaErrorTable = Readonly<Record<string, PrismaErrorRule>>;
162
- /**
163
- * The installed-major this table is written against. The spec asserts the
164
- * installed `@prisma/client` agrees.
165
- */
22
+ /** The installed-major this table is written against. */
166
23
  export declare const PRISMA_ERROR_TABLE_MAJOR = "7";
167
- /**
168
- * Every code here was induced above. Adding a row later is additive and costs
169
- * nothing; shipping a wrong one is not recoverable.
170
- */
24
+ /** Every code here was induced above. */
171
25
  export declare const PRISMA_ERROR_TABLE: PrismaErrorTable;
172
- /**
173
- * Classifies one failed Prisma call.
174
- *
175
- * `error` is `unknown` and stays `unknown`: the reader is the only thing that
176
- * touches it, and the rules see nothing but measured facts.
177
- */
26
+ /** Classifies one failed Prisma call. */
178
27
  export declare function classifyPrismaError(error: unknown, operation: Pick<OperationIdentity, "family" | "variant">): PrismaErrorClassification;
179
- /**
180
- * The deliberate failure an `outcome` classification stands for.
181
- *
182
- * The cause carries framework text and nothing else: no issues, and that is now
183
- * the **rule** rather than an absence. And no provider text, because a deliberate
184
- * outcome's top-level `cause.message` is forwarded verbatim. Nothing read off the
185
- * Prisma error reaches this value.
186
- */
28
+ /** The deliberate failure an `outcome` classification stands for. */
187
29
  export declare function prismaOutcomeFailure(code: OperationErrorCode): FrameworkError;
188
- /**
189
- * **Server-side only.** Every field is provider-owned, so this value never reaches
190
- * a `cause` — which is why it is a separate function and not a field on
191
- * `PrismaErrorClassification`: nothing can carry it onto the wire by accident.
192
- */
193
30
  export type PrismaConflictSubject = {
194
31
  readonly code: string;
195
32
  readonly model: string | undefined;
@@ -1,72 +1,3 @@
1
- /**
2
- * The total read of one hostile value.
3
- *
4
- * Everything on the failure path arrives as `unknown`. `@prisma/client` 7.10.0
5
- * raises `PrismaClientKnownRequestError`, whose `meta` is typed `Record<string,
6
- * unknown>` and is **not** a discriminated union, so a reader that trusts the type
7
- * would be reading a shape nobody promised. Worse, the value need not come from
8
- * Prisma at all: a developer callback, a driver, or a proxy can hand the adapter
9
- * anything.
10
- *
11
- * So this module reads structurally and defensively, under two rules it never
12
- * relaxes — the same totality discipline as core's diagnostics reporter, which
13
- * also observes values it cannot vouch for:
14
- *
15
- * 1. **No accessor is ever invoked.** Every read goes through
16
- * `Object.getOwnPropertyDescriptor` and takes `descriptor.value`. An accessor
17
- * descriptor yields `undefined` and its getter is never called, so a
18
- * booby-trapped property cannot run code, mutate state, or throw from inside
19
- * the adapter's failure path.
20
- * 2. **Nothing escapes.** Every reflective call is guarded, because a Proxy may
21
- * throw from its `getOwnPropertyDescriptor` or `ownKeys` trap, and a reader
22
- * that throws while classifying a failure would replace a legible outcome with
23
- * an illegible one.
24
- *
25
- * Reading only *own* properties is deliberate rather than incidental: 7.10.0
26
- * carries `code` and `meta` as own data properties (observed own keys:
27
- * `["code","meta","clientVersion","name"]`), so the own read is sufficient for
28
- * every real error, and a `code` that exists only as an inherited accessor is
29
- * precisely the case rule 1 refuses to touch.
30
- *
31
- * ## What this module does NOT read
32
- *
33
- * `message` is never read. At 7.10.0 a `PrismaClientKnownRequestError` message is
34
- * not a sentence — it is a rendered call site. Measured verbatim on this
35
- * repository's own schema:
36
- *
37
- * ```text
38
- * Invalid `client.author.create()` invocation in
39
- * /home/.../packages/prisma7-adapter/src/errors/__probe__.spec.ts:50:18
40
- *
41
- * 49 await capture("P2002 duplicate email", () =>
42
- * → 50 client.author.create(
43
- * Unique constraint failed on the fields: (`email`)
44
- * ```
45
- *
46
- * That single string carries an absolute file path, a source excerpt and the
47
- * violated constraint. The cheapest guarantee is not to read the message at all,
48
- * so the leak has no source; the raw error still reaches core's diagnostics sink,
49
- * which is server-side and may carry it.
50
- *
51
- * Everything below is scoped to `@prisma/client` **7.x**. Prisma 8 replaced
52
- * P-codes with dotted `NAMESPACE.SUBCODE` codes, which makes a Prisma 8 adapter a
53
- * re-map of this module rather than a patch to it.
54
- */
55
- /**
56
- * The violated constraint as 7.10.0's driver adapters actually report it, at
57
- * `meta.driverAdapterError.cause.constraint`.
58
- *
59
- * The arms are **provider-shaped, measured on both engines**, not guessed:
60
- *
61
- * | Engine | Unique (P2002) | Foreign key (P2003) |
62
- * |-----------------------------------|-------------------------------|-------------------------|
63
- * | `@prisma/adapter-better-sqlite3` | `{ fields: ["email"] }` | `{ foreignKey: {}
64
- * }` | | `@prisma/adapter-pg` | `{ index: "Author_email_key" }` | `{ index:
65
- * "Post_authorId_fkey" }` |
66
- *
67
- * It is therefore **not a string**, and the two engines do not agree on which
68
- * identifier they can name — SQLite names columns, PostgreSQL names the index.
69
- */
70
1
  export type PrismaConstraintSubject = {
71
2
  readonly kind: "fields";
72
3
  readonly fields: readonly string[];
@@ -78,23 +9,9 @@ export type PrismaConstraintSubject = {
78
9
  } | {
79
10
  readonly kind: "unreadable";
80
11
  };
81
- /**
82
- * Everything the normalizer is allowed to know about one failed call.
83
- *
84
- * Narrow and flat on purpose: a classification rule reads these fields and
85
- * nothing else, so no rule can reach back into the raw value and no rule
86
- * can depend on a shape this module has not measured.
87
- */
12
+ /** Everything the normalizer is allowed to know about one failed call. */
88
13
  export type PrismaErrorFacts = {
89
- /**
90
- * The P-code, when it is an own string property. A missing or non-string `code`
91
- * leaves this `undefined`, which the table answers as `unclassified` — never as a
92
- * guess.
93
- */
94
14
  readonly code: string | undefined;
95
- /**
96
- * The own, enumerable key names of `meta`, in the order 7.10.0 wrote them.
97
- */
98
15
  readonly metaKeys: readonly string[];
99
16
  /** `meta.modelName` — the Prisma model the failure occurred on. */
100
17
  readonly modelName: string | undefined;
@@ -107,15 +24,6 @@ export type PrismaErrorFacts = {
107
24
  readonly relatedModel: string | undefined;
108
25
  /** `meta.driverAdapterError.cause.constraint`, read structurally. */
109
26
  readonly constraint: PrismaConstraintSubject | undefined;
110
- /**
111
- * `meta.target` — **read so that it is measured, depended on by nothing**.
112
- *
113
- * It was induced on both engines here and **`target` was absent from every
114
- * payload** — P2002 (single and compound unique), P2003, P2025 (three shapes),
115
- * P2018 and P2034, on SQLite and on PostgreSQL. The docs are stale; the installed
116
- * package governs. This field exists so the next reader sees that measured, and
117
- * does not "fix" the code to match the documentation.
118
- */
119
27
  readonly legacyTarget: readonly string[] | undefined;
120
28
  };
121
29
  /**
@@ -2,41 +2,18 @@ import { FrameworkError } from "@aventara/core";
2
2
  import type { PrismaIdentifierAddress } from "../discovery/discovery-artifact.interface.js";
3
3
  import type { PrismaCall } from "../translation/operation.translator.js";
4
4
  /**
5
- * The lost-row conflict: the read selected a row and the re-asserted write matched
6
- * none, so **nothing was written** and a retry may succeed.
7
- *
8
- * `A2014 STALE_SELECTION`, and this is the only place that names it.
5
+ * The lost-row conflict: the read selected a row and the re-asserted write
6
+ * matched none, so **nothing was written** and a retry may succeed.
9
7
  */
10
8
  export declare function lostRowConflict(): FrameworkError;
11
- /**
12
- * Issues one of the emulation's two statements.
13
- */
9
+ /** Issues one of the emulation's two statements. */
14
10
  export type FirstVariantIssuer = (call: PrismaCall, step: "read" | "write") => Promise<unknown>;
15
- /**
16
- * How the emulation's two statements are issued, and against which client.
17
- *
18
- * An earlier draft of this module took the two separately — a `unit` that opened a
19
- * transaction and an `issue` already bound to a client — and the standalone case
20
- * then opened a transaction whose two statements ran on the **root** client,
21
- * outside it: the emulation would have looked atomic and been nothing of the kind,
22
- * and no assertion about the issued `where` would have noticed. Making the unit
23
- * the thing that hands out the issuer removes the gap rather than documenting it.
24
- *
25
- * This module therefore never sees a Prisma client, a provider name or a
26
- * transaction; it sees one issuer, already in the right unit.
27
- */
11
+ /** How the emulation's two statements are issued, and against which client. */
28
12
  export type FirstVariantEmulation = {
29
- /** The translated plan's two steps: the read, then the write template. */
30
13
  readonly steps: readonly PrismaCall[];
31
14
  /** The Resource's recorded Prisma addressing, for the write's identifier. */
32
15
  readonly identifiers: readonly PrismaIdentifierAddress[];
33
- /**
34
- * Opens the one adapter-internal unit and runs `work` inside it.
35
- *
36
- * Standalone this opens an interactive transaction and the issuer it yields is
37
- * scoped to it; inside a plan it runs `work` against the outer transaction client,
38
- * so the emulated steps roll back **with** the plan rather than independently.
39
- */
16
+ /** Opens the one adapter-internal unit and runs `work` inside it. */
40
17
  readonly inUnit: <T>(work: (issue: FirstVariantIssuer) => Promise<T>) => Promise<T>;
41
18
  };
42
19
  /** A plan that is not the two-step shape this module manufactures. */
@@ -1,80 +1,19 @@
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, type PrismaTransactionOptions } from "../prisma-client.interface.js";
4
- /**
5
- * Translation is pure and lives in `translation/operation.translator.ts`; this
6
- * module owns the three things that need a client and nothing else:
7
- *
8
- * 1. **Reaching the delegate.** See {@link delegateKeyOf} — the one derivation in
9
- * this package, and the one place it is made.
10
- * 2. **Classifying a failure.** The closed P-code table in
11
- * `errors/error.normalizer.ts` answers `absence` → `null`, `outcome` → a
12
- * deliberate `FrameworkError`, or `unclassified` → propagate, so core's
13
- * `AdapterBoundary` reports `A3001` with core's own text and sends the raw
14
- * error to diagnostics. The adapter never guesses a code it did not measure.
15
- * 3. **Shaping the answer.** `execution/result.shaper.ts` places every `$count`
16
- * envelope, converts every returned value to the runtime form core's output
17
- * validator accepts and reads the number a count variant owes; which of its
18
- * three entry points runs is the *variant's* `result` row in the dispatch
19
- * table, not a guess from the shape Prisma returned. The shaper is handed the
20
- * model and the Resource as well as the plan, because the scalar a returned
21
- * value belongs to is a fact of the model and not of the value.
22
- *
23
- * `scope: "root"` is the adapter's own `execute`. `scope: "transaction"` is what
24
- * `Adapter.transaction`'s callback hands core: the same code over a transaction
25
- * client. The scope decides exactly one thing — whether a first-style emulation
26
- * opens its own interactive transaction or reuses the one already open — and a
27
- * transaction-scoped executor closes over the transaction client only, so the root
28
- * client is unreachable from inside it.
29
- *
30
- * All three value crossings read ONE table, `translation/scalar.conversion.ts`: a
31
- * write's data through `mutation.translator.ts`, a filter operand through
32
- * `where.translator.ts`, and a returned row through `execution/result.shaper.ts`.
33
- * None of them is converted here. Converting at this seam would have put the
34
- * scalar table in a fourth place and hidden the gap from the module that owns it.
35
- *
36
- * **Core's output validation runs after this module, and strips.** For a
37
- * projection-carrying variant `planReadOperation` sets `materialize: true` and
38
- * `materializeRecord` ends in `Object.fromEntries(plan.requested…)` **[CORE]**, so
39
- * a spare key the adapter returned would be removed before the validator saw it.
40
- * That is why the emulator's own return value is asserted directly in
41
- * `first-variant.emulator.spec.ts` as well as end-to-end here: an end-to-end
42
- * assertion about extra keys cannot fail on that path.
43
- */
44
4
  /** A call the executor cannot issue against the client it was given. */
45
5
  export declare class PrismaExecutionError extends Error {
46
6
  readonly name = "PrismaExecutionError";
47
7
  }
48
8
  export type PrismaExecutionScope = "root" | "transaction";
49
9
  export type PrismaOperationExecutorDependencies = {
50
- /**
51
- * The client in force: the application's own client at `"root"` scope, the
52
- * transaction client inside a plan.
53
- */
54
10
  readonly client: PrismaDelegateHost;
55
11
  readonly model: AdapterModel;
56
12
  /** The generate-time translation table (Prisma addressing per Resource). */
57
13
  readonly translation: Readonly<Record<string, PrismaResourceTranslation>>;
58
14
  readonly scope: PrismaExecutionScope;
59
- /** Adapter-owned, never Aventara public configuration. */
60
15
  readonly transactionOptions?: PrismaTransactionOptions;
61
16
  };
62
- /**
63
- * Prisma's delegate property for a model.
64
- *
65
- * **Derived, and that is a recorded residual rather than a comfortable choice.**
66
- * The authoritative token is readable — `generated/<engine>/models/<M>.ts`, a 🟢
67
- * file, writes it as the extension key: `GetSelect<{ … },
68
- * ExtArgs["result"]["author"]>` for model `Author` — but `types.reader.ts` reads
69
- * the 🟢 files for *capability* facts and does not record it, and the client
70
- * property itself is declared only in `internal/class.ts`, which that reader
71
- * refuses by design. So the rule applied here is Prisma's own: lower-case the
72
- * first character and nothing else. `operation.executor.spec.ts` asserts the
73
- * derivation against the real generated client for **every** model in the schema,
74
- * so it is observed for this repository's six models; a model name whose Prisma
75
- * property does not follow the rule would be caught there and not in production.
76
- * The clean owner of the fact is the generate-time translation table, beside
77
- * `identifierKeys`, and that is left as a pointer rather than taken here.
78
- */
17
+ /** Prisma's delegate property for a model. */
79
18
  export declare function delegateKeyOf(model: string): string;
80
19
  export declare function createPrismaOperationExecutor<M extends AdapterModel>(dependencies: PrismaOperationExecutorDependencies): AdapterOperationExecutor<M>;