@aventara/prisma7-adapter 0.1.0-pilot.3 → 0.1.0-pilot.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 +2 -2
@@ -5,63 +5,15 @@ import type { PrismaProvider } from "../provider/provider-profile.js";
5
5
  import type { PrismaEntityAbsence } from "./existence.gate.js";
6
6
  import { type PrismaCli } from "./prisma-cli.resolver.js";
7
7
  import type { PrismaReaderExemption } from "./reader-crosscheck.js";
8
- /**
9
- * Nothing under `execution/`, and nothing in `discovery/artifact.loader.ts`,
10
- * imports it; the package's build `exclude` keeps `src/generate/**` out of `dist`
11
- * entirely, so a deployed application never carries `typescript`, a PSL reader or
12
- * a child process.
13
- *
14
- * **The order is fixed, and each step earns its place:**
15
- *
16
- * 1. **The pinned `prisma` major**. PSL's grammar and the generated client's shape
17
- * are version-bound; a major this reader has never seen must stop the build
18
- * rather than produce a wrong `AdapterModel` from a grammar nobody read.
19
- * 2. **`@prisma/client/runtime/client` resolves**. This one is first among equals,
20
- * because its failure is *silent*: every generated file opens `// @ts-nocheck`,
21
- * so with the runtime unresolvable a TypeScript program over the generated tree
22
- * reports **zero** diagnostics while `FieldRef` degrades to its uninstantiated
23
- * form and `JsonValue` stops being a union — flipping a types-derived
24
- * nullability from `true` to `false` with nothing anywhere to say so
25
- * **[RUN8]**. The guard is therefore a module *resolution*, never a diagnostic
26
- * count: a diagnostic count is exactly the instrument that reads clean in this
27
- * failure.
28
- * 3. **`prisma generate`**, run by this step itself. The two sources must describe
29
- * one instant; a client generated by some earlier command may describe an older
30
- * schema, and nothing downstream could tell.
31
- * 4. **Both sources read in that same run** — PSL for the semantic model, the 🟢
32
- * generated types for the capability surface and for existence.
33
- * 5. **The structural checks, in that order.** The existence gate first, because
34
- * it decides *which* entities exist and a cross-check of an entity nobody
35
- * admitted is noise; then the reader-versus-reader cross-check
36
- * (`reader-crosscheck.ts`), which answers the reverse direction the gate hands
37
- * it and every other fact both sources carry. Its findings stop the step; its
38
- * two documented exemptions are reported and carried out on the result.
39
- * 6. **Emit** one TypeScript module.
40
- *
41
- * **The two readers fail differently, and the step keeps them different.** A PSL
42
- * `unhandled` entry means *I located a token I do not model*: there is a
43
- * construct, a spelling and a site to report, so they are aggregated and reported
44
- * together. A types-reader failure means *I cannot read the surface at all*: there
45
- * is nothing to record, so it throws. Inventing an `unhandled` vocabulary for the
46
- * type surface would be a second parallel representation of "something went wrong"
47
- * for no gain.
48
- */
49
- /** The `prisma` major this reader's grammar was written against. */
8
+ /** The Prisma major this package generates for. */
50
9
  export declare const PINNED_PRISMA_MAJOR = 7;
10
+ /** Thrown when the generate step refuses; the message says why and what to change. */
51
11
  export declare class PrismaGenerateStepError extends Error {
52
12
  readonly name = "PrismaGenerateStepError";
53
13
  }
54
14
  /**
55
- * What composition produces: the three halves the artifact carries.
56
- *
57
- * They are composed together and emitted apart. The `model` is core's — hashed
58
- * and Contract-bound — while `translation` is the adapter's Prisma addressing and
59
- * `referentialActions` is what the schema's resolved `@relation(onDelete:)` and
60
- * `@relation(onUpdate:)` arguments say. Neither of the latter two is part of the
61
- * model, so both stay out of the hash: a `@@unique(name:)` rename must not move
62
- * the Contract identity, and core has no referential-action vocabulary for a
63
- * Contract to carry. All three come from one pass over one field list, so they
64
- * cannot disagree about which identifiers or which edges exist.
15
+ * What composition produces: the model, Prisma addressing, referential actions
16
+ * and create requirements the artifact carries.
65
17
  */
66
18
  export type PrismaComposedArtifact = {
67
19
  readonly model: PrismaAdapterModel;
@@ -69,27 +21,15 @@ export type PrismaComposedArtifact = {
69
21
  readonly referentialActions: PrismaReferentialActionTable;
70
22
  readonly createRequirements: PrismaCreateRequirementTable;
71
23
  };
72
- /**
73
- * Composition of the two readers' facts into the artifact's two halves.
74
- *
75
- * It is a parameter rather than a call, because composition is
76
- * `discovery/model.discoverer.ts`'s and this step's job is order and refusal over
77
- * external effects. The step hands over only what it has verified: both readers'
78
- * output, and the resource names the existence gate admitted.
79
- */
24
+ /** Composes the schema's and the generated client's facts into the artifact's contents. */
80
25
  export type PrismaModelComposer = (input: {
81
26
  readonly facts: PrismaSchemaFacts;
82
27
  readonly surface: PrismaCapabilitySurface;
83
28
  readonly admitted: readonly string[];
84
29
  }) => PrismaComposedArtifact;
85
30
  /**
86
- * The step's external world, in one record.
87
- *
88
- * Every member is an effect this package does not own — a child process, a
89
- * version on disk, a module resolution, a file write — which is why they are
90
- * injectable: the step's contract is the *order* it performs them in and the
91
- * points at which it refuses, and neither is observable when the effects are
92
- * unobservable. {@link createPrismaGenerateToolchain} is the real one.
31
+ * The generate step's external effects: running Prisma, reading files and
32
+ * writing the artifact. Replace it only to change how those effects happen.
93
33
  */
94
34
  export type PrismaGenerateToolchain = {
95
35
  readonly installedPrismaVersion: () => Promise<string>;
@@ -99,10 +39,10 @@ export type PrismaGenerateToolchain = {
99
39
  readonly readSurface: (clientDirectory: string) => PrismaCapabilitySurface;
100
40
  readonly writeArtifact: (file: string, source: string) => Promise<void>;
101
41
  };
42
+ /** What {@link runPrismaGenerateStep} needs. */
102
43
  export type PrismaGenerateRequest = {
103
44
  /** The `schema.prisma` file, or a Prisma 7 schema folder. */
104
45
  readonly schema: string;
105
- /** The generator's `output` directory: the 🟢 files' root. */
106
46
  readonly clientDirectory: string;
107
47
  readonly provider: PrismaProvider;
108
48
  /** Where the emitted TypeScript artifact module is written. */
@@ -110,25 +50,17 @@ export type PrismaGenerateRequest = {
110
50
  readonly composeModel: PrismaModelComposer;
111
51
  readonly toolchain?: PrismaGenerateToolchain;
112
52
  };
53
+ /** What {@link runPrismaGenerateStep} produced. */
113
54
  export type PrismaGenerateResult = {
114
55
  readonly artifactFile: string;
115
56
  /** The emitted module's exact bytes. */
116
57
  readonly source: string;
117
58
  readonly modelHash: string;
118
- /** Resource names the 🟢 types admitted, in PSL declaration order. */
119
59
  readonly admitted: readonly string[];
120
60
  /** PSL-only entities the schema itself explained away. */
121
61
  readonly excluded: readonly PrismaEntityAbsence[];
122
- /**
123
- * Carried out rather than swallowed, so a caller can print them and a spec can
124
- * assert them by name and reason.
125
- */
126
62
  readonly exemptions: readonly PrismaReaderExemption[];
127
63
  };
128
- /**
129
- * Looked up from this package — where an optional peer is linked — and then from
130
- * the project the step runs in.
131
- */
132
64
  export declare function resolveInstalledPrismaCli(): PrismaCli;
133
65
  /**
134
66
  * The version fence's input: the version of the Prisma CLI this step runs, which
@@ -137,12 +69,11 @@ export declare function resolveInstalledPrismaCli(): PrismaCli;
137
69
  * load time against the artifact — see `discovery/artifact.loader.ts`.)
138
70
  */
139
71
  export declare function readInstalledPrismaVersion(): Promise<string>;
140
- /**
141
- * Asked as a module resolution, never as a diagnostic count, and asked from a file
142
- * path *inside* `clientDirectory` because resolution walks `node_modules` upward
143
- * from the importer. The directory need not exist yet: resolution is a path
144
- * question, which is what lets this fence run before `prisma generate`.
145
- */
146
72
  export declare function clientRuntimeResolves(clientDirectory: string): boolean;
73
+ /** The toolchain the generate step uses by default: the installed Prisma CLI and TypeScript. */
147
74
  export declare function createPrismaGenerateToolchain(): PrismaGenerateToolchain;
75
+ /**
76
+ * Runs `prisma generate`, reads the schema and the generated client, checks they
77
+ * agree, and writes the discovery artifact.
78
+ */
148
79
  export declare function runPrismaGenerateStep(request: PrismaGenerateRequest): Promise<PrismaGenerateResult>;
@@ -1,86 +1,8 @@
1
1
  import type { PrismaCapabilitySurface } from "../discovery/capability-surface.interface.js";
2
2
  import type { PrismaIdentifierMapping } from "../discovery/identifier.mapper.js";
3
3
  import type { PrismaSchemaFacts, PrismaSchemaModel } from "../discovery/schema-facts.interface.js";
4
- /**
5
- * # It is a self-test of the two readers, not a check on the developer
6
- *
7
- * That framing decides every case in this module. A finding here does not mean
8
- * *your schema is wrong*; it means **one of this adapter's two readers is wrong**,
9
- * or the client it read was generated from a different schema than the one PSL was
10
- * read from. The remedy is never "edit the schema" — it is regenerate, or fix a
11
- * reader.
12
- *
13
- * It follows that the check can only see facts **both** sources carry. That is not
14
- * a gap to be closed by trying harder; it is arithmetic. The honest limit is
15
- * measured below.
16
- *
17
- * # What it cannot see, measured rather than described
18
- *
19
- * | edit | sqlite | postgres | |
20
- * --------------------------------------------------- | ------ | -------- | |
21
- * `@default(uuid())` → `@default(cuid())` | 0 | 0 | | `@default(now())` →
22
- * `@default(dbgenerated("…"))` | 0 | 0 | | `@default(BRONZE)` → `@default(GOLD)` |
23
- * 0 | 0 | | `@relation("Mentorship")` → `@relation("Coaching")` | 0 | 0 |
24
- *
25
- * Every one of them changes what the database does. None of them is visible to a
26
- * cross-check, because none of them reaches the 🟢 surface at all: a `@default`
27
- * argument's *content* and a relation's *name* are PSL-exclusive (the name appears
28
- * nowhere on the generated surface, which is why `field.mapper.ts` pairs edges
29
- * from PSL alone). A fifth class is the mirror image: which filter operators a
30
- * `<Kind>Filter` exposes is 🟢-exclusive, so a reader that under-reads one is
31
- * equally invisible — seeded as the sixth edit in
32
- * `__fixtures__/diverged-surface.ts` and caught by nothing.
33
- *
34
- * **So this module is not a schema-drift detector and must not be trusted as
35
- * one.** Staleness — a developer who edits `schema.prisma` and does not re-run the
36
- * generate step — is prevented by the step *running `prisma generate` itself*, so
37
- * that both sources describe one instant. What survives that ruling catches a
38
- * different failure again: `modelHash` proves the artifact is internally intact
39
- * and the `prismaVersion` major fence catches a client that moved underneath it.
40
- * Neither notices a schema that moved, and neither does this.
41
- *
42
- * # Two exemptions, and both are explanations rather than allowances
43
- *
44
- * A freshly generated pair is not silent, and the two cases where it speaks are
45
- * *understood*:
46
- *
47
- * 1. **`json-null-is-a-value`** — the one disagreement a pristine pair produces on
48
- * both engines. JSON null is a *value*, so `JsonFilterBase` writes `| null`
49
- * operands (`array_starts_with`, `array_ends_with`, and `array_contains` on
50
- * PostgreSQL) on a column PSL declares **required**. A plausible "the operands
51
- * mention null, therefore the column is nullable" rule is right for every other
52
- * scalar and wrong for every `Json` one, which is why nullability comes from
53
- * PSL's `?` and nothing else and why this one is exempted by PSL *type* rather
54
- * than waved through.
55
- *
56
- * Each exemption is **recorded with its reason**, not dropped. A spec can then
57
- * assert both by name and by reason, so an unexplained third disagreement fails
58
- * rather than hiding behind "the pair is clean".
59
- *
60
- * # What belongs to other modules, and is deliberately not restated here
61
- *
62
- * - **A PSL-declared entity the 🟢 types do not expose** is the EXISTENCE GATE's
63
- * answer: it decides admission and whether the absence is explained. This module
64
- * answers only the reverse direction — a type-exclusive resource or field —
65
- * which the gate's own header hands to it.
66
- * - **A `FieldRef` token that disagrees with the written PSL type** is
67
- * `field.mapper.ts`'s, where it *throws*: the two readers describing one field
68
- * two ways is not a schema a Contract can be compiled from. Restating the rule
69
- * here would be two owners for one fact.
70
- * - **A create-optional marker with no PSL cause** is `field.mapper.ts`'s
71
- * `crossCheckCreateOptional`, run by `model.discoverer.ts` where the field
72
- * projections already exist. It needs the projected lifecycle, which this module
73
- * does not compute.
74
- */
75
4
  /** A disagreement about a fact both sources carry: one of the readers is wrong. */
76
- export type PrismaReaderFindingKind =
77
- /** The 🟢 types expose a resource PSL does not declare. */
78
- "resource-exclusive-to-types"
79
- /** The 🟢 types expose a field PSL does not declare on that model. */
80
- | "field-exclusive-to-types"
81
- /** PSL's `?` and the operands the 🟢 filter admits disagree. */
82
- | "nullability"
83
- | "identifier-key"
5
+ export type PrismaReaderFindingKind = "resource-exclusive-to-types" | "field-exclusive-to-types" | "nullability" | "identifier-key"
84
6
  /** An enum is exposed and not declared, declared and not exposed, or its members differ. */
85
7
  | "enum";
86
8
  export type PrismaReaderFinding = {
@@ -94,10 +16,11 @@ export type PrismaReaderFinding = {
94
16
  };
95
17
  /** A disagreement that is understood, and therefore not a finding. */
96
18
  export type PrismaReaderExemptionKind = "json-null-is-a-value" | "nullable-participant-key";
19
+ /** A known, expected difference between the schema and the generated client. */
97
20
  export type PrismaReaderExemption = {
98
21
  readonly kind: PrismaReaderExemptionKind;
99
22
  readonly entity: string;
100
- /** Why the two sources may differ here. Recorded so a spec can assert the reason. */
23
+ /** Why the two may differ here. */
101
24
  readonly reason: string;
102
25
  };
103
26
  export type PrismaReaderCrossCheck = {
@@ -110,14 +33,6 @@ export type PrismaIdentifierKeyFinding = {
110
33
  readonly key: string;
111
34
  readonly reason: string;
112
35
  };
113
- /**
114
- * Exported because it has **two callers that must check one rule**: the generate
115
- * step, through {@link crossCheckReaders}, and `identifier.mapper.spec.ts`, whose
116
- * own cases were written against a local copy while this file did not exist. The
117
- * explanation is re-derived **from PSL**, never taken on the mapping's word —
118
- * otherwise a mapper that invented a nullable participant would clear its own
119
- * exemption.
120
- */
121
36
  export declare function crossCheckIdentifierKeys(declared: PrismaSchemaModel, mapping: PrismaIdentifierMapping, uniqueKeys: readonly string[]): readonly PrismaIdentifierKeyFinding[];
122
37
  /**
123
38
  * The whole cross-check: a pure function of the two readers' output.
@@ -61,7 +61,7 @@ export function crossCheckReaders(facts, surface) {
61
61
  findings.push({
62
62
  kind: "resource-exclusive-to-types",
63
63
  entity: name,
64
- message: `the generated 🟢 types expose a model \`${name}\` that \`schema.prisma\` does not declare. The two readers describe one instant, so this is a stale generated client or a reader defect — the schema cannot have said it.`,
64
+ message: `the generated client's types expose a model \`${name}\` that \`schema.prisma\` does not declare. The two readers describe one instant, so this is a stale generated client or a reader defect — the schema cannot have said it.`,
65
65
  });
66
66
  }
67
67
  for (const model of facts.models) {
@@ -80,7 +80,7 @@ export function crossCheckReaders(facts, surface) {
80
80
  findings.push({
81
81
  kind: "field-exclusive-to-types",
82
82
  entity: `${model.name}.${field}`,
83
- message: `the generated 🟢 types expose \`${model.name}.${field}\` and \`schema.prisma\` declares no such member. A rename seen by only one of the two readers looks exactly like this.`,
83
+ message: `the generated client's types expose \`${model.name}.${field}\` and \`schema.prisma\` declares no such member. A rename seen by only one of the two readers looks exactly like this.`,
84
84
  });
85
85
  }
86
86
  for (const field of model.fields) {
@@ -109,7 +109,7 @@ export function crossCheckReaders(facts, surface) {
109
109
  findings.push({
110
110
  kind: "nullability",
111
111
  entity: `${model.name}.${field.name}`,
112
- message: `\`${model.name}.${field.name}\` is ${field.optional ? "optional" : "required"} in \`schema.prisma\` and the generated 🟢 filter ${typesSayNullable ? `admits \`null\` on [${nullAdmitting.join(", ")}]` : "admits `null` nowhere"}. PSL's \`?\` is the only source of nullability, so the model is built from it either way — this says one of the two readers, or the client, is from a different schema.`,
112
+ message: `\`${model.name}.${field.name}\` is ${field.optional ? "optional" : "required"} in \`schema.prisma\` and the generated client's filter type ${typesSayNullable ? `admits \`null\` on [${nullAdmitting.join(", ")}]` : "admits `null` nowhere"}. PSL's \`?\` is the only source of nullability, so the model is built from it either way — this says one of the two readers, or the client, is from a different schema.`,
113
113
  });
114
114
  }
115
115
  const mapping = mapPrismaIdentifiers(model);
@@ -139,7 +139,7 @@ export function crossCheckReaders(facts, surface) {
139
139
  findings.push({
140
140
  kind: "enum",
141
141
  entity: name,
142
- message: `the generated 🟢 \`enums.ts\` exposes \`${name}\` and \`schema.prisma\` declares no such enum.`,
142
+ message: `the generated client's \`enums.ts\` exposes \`${name}\` and \`schema.prisma\` declares no such enum.`,
143
143
  });
144
144
  }
145
145
  for (const declared of facts.enums) {
@@ -1,38 +1,18 @@
1
1
  import type { PrismaIsolationLevel } from "./provider/provider-profile.js";
2
- /**
3
- * This is the seam that keeps the adapter compilable with no generated client in
4
- * scope and testable with a recording double.
5
- *
6
- * Observed on 2026-09-23 with the real generated client and `tsc -p
7
- * tsconfig.typecheck.json`:
8
- *
9
- * error TS2322: Type 'PrismaClient' is not assignable to type 'HostWithIndex'.
10
- * Index signature for type 'string' is missing in type 'PrismaClient<never,
11
- * GlobalOmitConfig | undefined, DefaultArgs>'.
12
- *
13
- * The same probe with the index signature removed compiled clean. So the public
14
- * constraint declares only `$transaction`, and the delegate index is reached
15
- * through `prismaDelegates()` below — one named seam, in one place, instead of a
16
- * constraint no real client can satisfy.
17
- */
18
- /** Adapter-owned transaction options; never Aventara public configuration. */
2
+ /** Prisma interactive-transaction options. */
19
3
  export type PrismaTransactionOptions = {
20
- /** Prisma's own default is 2000 ms **[PKG, `runtime/client.d.ts`]**. */
21
4
  readonly maxWait?: number;
22
- /** Prisma's own default is 5000 ms **[PKG, `runtime/client.d.ts`]**. */
23
5
  readonly timeout?: number;
24
6
  readonly isolationLevel?: PrismaIsolationLevel;
25
7
  };
26
- /** One Prisma model delegate, as far as the adapter is concerned. */
8
+ /** One Prisma model delegate, such as `prisma.user`. */
27
9
  export type PrismaDelegate = Readonly<Record<string, unknown>>;
28
- /**
29
- * The host the adapter is handed. `$transaction` is declared in its callback form
30
- * only: the array overload is never reached.
31
- */
10
+ /** The Prisma client shape the adapter accepts. */
32
11
  export interface PrismaDelegateHost {
12
+ /** Prisma's interactive `$transaction`. */
33
13
  $transaction<T>(work: (transactional: PrismaDelegateHost) => Promise<T>, options?: PrismaTransactionOptions): Promise<T>;
34
14
  }
35
- /** The delegate index view of a host. */
15
+ /** A Prisma client's model delegates, by name. */
36
16
  export type PrismaDelegateIndex = Readonly<Record<string, PrismaDelegate | undefined>>;
37
17
  /**
38
18
  * The single place the structural gap between a generated client (a class,
@@ -2,26 +2,17 @@ import type { Adapter } from "@aventara/core";
2
2
  import type { PrismaAdapterModel, PrismaDiscoveryArtifact } from "./discovery/discovery-artifact.interface.js";
3
3
  import type { PrismaDelegateHost, PrismaTransactionOptions } from "./prisma-client.interface.js";
4
4
  import { type PrismaDriver, type PrismaProvider } from "./provider/provider-profile.js";
5
- /**
6
- * `TClient` stays generic so a caller's generated client type flows through
7
- * without this package naming it: `client` is the one and only place a Prisma type
8
- * enters the public surface, and it enters as the caller's own parameter.
9
- */
5
+ /** Options for {@link createPrismaAdapter}. */
10
6
  export type PrismaAdapterOptions<TClient extends PrismaDelegateHost, M extends PrismaAdapterModel = PrismaAdapterModel> = {
11
- /** Application-owned, already-constructed client. */
7
+ /** Your constructed Prisma client. */
12
8
  readonly client: TClient;
13
- /**
14
- * The generate-time discovery artifact this adapter loads and checks.
15
- *
16
- * This is the one and only inference site for `M`: the emitted artifact module's
17
- * `model` is a literal type, and `PrismaDiscoveryArtifact<M>` expands to a bare
18
- * `model: M` property so the compiler reads that literal off the argument.
19
- */
9
+ /** The `discovery` export of the generated discovery artifact. */
20
10
  readonly discovery: PrismaDiscoveryArtifact<M>;
21
- /** Declared, never sniffed from client internals. */
11
+ /** The database provider the client was generated for. */
22
12
  readonly provider: PrismaProvider;
13
+ /** The Prisma driver adapter the client is constructed with. */
23
14
  readonly driver: PrismaDriver;
24
- /** Adapter-owned, never Aventara public configuration. */
15
+ /** Options passed to every Prisma interactive transaction. */
25
16
  readonly transactionOptions?: PrismaTransactionOptions;
26
17
  };
27
18
  /**
@@ -36,12 +27,20 @@ export type PrismaAdapterConstruction<TClient extends PrismaDelegateHost, M exte
36
27
  readonly installedPrismaVersion?: string;
37
28
  };
38
29
  /**
39
- * Construction is `async` because core's `Adapter.model` is a settled fact read
40
- * synchronously at framework construction, while *verifying* the artifact is
41
- * asynchronous: `computeModelHash` digests through `globalThis.crypto.subtle`,
42
- * which is a promise-returning API. The artifact itself is already a value in
43
- * hand (`options.discovery`); only its verification has to
44
- * await, so it happens here, once, before an adapter exists — every fence is
45
- * the same fence, moved from the first `discover()` call to construction.
30
+ * Creates the Aventara adapter for a Prisma 7 client, after checking the
31
+ * discovery artifact against the installed Prisma version and against itself.
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * const adapter = await createPrismaAdapter({
36
+ * client: prisma,
37
+ * discovery,
38
+ * provider: "postgresql",
39
+ * driver: "@prisma/adapter-pg",
40
+ * });
41
+ * ```
42
+ *
43
+ * @throws `PrismaDiscoveryArtifactError` when the artifact is stale, corrupt or
44
+ * was generated for another Prisma major; its message says how to regenerate it.
46
45
  */
47
46
  export declare function createPrismaAdapter<TClient extends PrismaDelegateHost, M extends PrismaAdapterModel = PrismaAdapterModel>(options: PrismaAdapterConstruction<TClient, M>): Promise<Adapter<M>>;
@@ -1,28 +1,20 @@
1
1
  import type { TransactionCapability } from "@aventara/core";
2
- /**
3
- * A stored copy of either class would be a second source of truth, which is
4
- * dictionary invariant 6.
5
- *
6
- * Nothing here is inferred at runtime, because nothing here is derived at runtime
7
- * at all.
8
- */
9
2
  export declare const PRISMA_PROVIDERS: readonly ["sqlite", "postgresql"];
3
+ /** The database providers this package supports. */
10
4
  export type PrismaProvider = (typeof PRISMA_PROVIDERS)[number];
11
- /**
12
- * The closed driver set.
13
- */
5
+ /** The closed driver set. */
14
6
  export declare const PRISMA_DRIVERS: readonly ["@prisma/adapter-better-sqlite3", "@prisma/adapter-pg", "@prisma/adapter-d1"];
7
+ /** The Prisma driver adapters this package supports. */
15
8
  export type PrismaDriver = (typeof PRISMA_DRIVERS)[number];
16
- /** The five levels `Prisma.IsolationLevel` admits **[PKG, `runtime/client.d.ts`]**. */
9
+ /** The isolation levels Prisma's `$transaction` accepts. */
17
10
  export type PrismaIsolationLevel = "ReadUncommitted" | "ReadCommitted" | "RepeatableRead" | "Snapshot" | "Serializable";
18
- /** The caller's explicit declaration; never sniffed from client internals. */
19
11
  export type PrismaProviderDeclaration = {
20
12
  readonly provider: PrismaProvider;
21
13
  readonly driver: PrismaDriver;
22
14
  };
23
15
  /**
24
- * The resolved profile. Three members, and three only — see the type comment
25
- * above for what is discovered or derived instead.
16
+ * What a provider and driver pair supports: transactions and isolation
17
+ * levels.
26
18
  */
27
19
  export type PrismaProviderProfile = {
28
20
  readonly provider: PrismaProvider;
@@ -1,42 +1,4 @@
1
1
  import type { PrismaIdentifierAddress } from "../discovery/discovery-artifact.interface.js";
2
- /**
3
- * The one owner of **core's flat identifier → Prisma's addressed
4
- * `<M>WhereUniqueInput`**.
5
- *
6
- * # Why this module exists at all
7
- *
8
- * The rule is three facts, every one of them measured at 7.10.0 and recorded in
9
- * {@link PrismaIdentifierAddress}: the generate-time `key` is matched and never
10
- * re-derived (`members.join("_")` is wrong for every `name:`-renamed criterion), a
11
- * key wraps its members iff `members.length > 1`, and the identifier chosen is the
12
- * first recorded criterion the caller's values complete.
13
- *
14
- * Three copies of a measured rule is three places a later maintainer can fix two
15
- * of, so the rule moved here and the three call sites became three
16
- * *configurations* of it.
17
- *
18
- * # What the call sites still own, and why that is not a leak
19
- *
20
- * Two things differ between them and neither can be collapsed:
21
- *
22
- * - **How complete the values must be.** A unique selector is `"exact"`: core's
23
- * selector carries one identifier and nothing else, so a selector with a spare
24
- * key is not that identifier. A cursor is `"subset"`: `validateCursor` requires
25
- * the cursor's keys to equal the *active ordered scalar fields*, which include a
26
- * complete identifier **plus** every other ordered key, so the identifier is a
27
- * proper subset of what arrives.
28
- * - Passing the conversion in as `emit` keeps the scalar table in the module that
29
- * owns it rather than importing it here.
30
- *
31
- * # No spec file of its own, deliberately
32
- *
33
- * Every branch is exercised through its three callers' specs —
34
- * `order-pagination.translator.spec.ts` (subset, compound wrapping, the "addresses
35
- * no row" refusal), `mutation.translator.spec.ts` (exact, renamed keys, Decimal
36
- * members) and `operation.translator.spec.ts` (exact, at the top level). A fourth
37
- * spec restating them would test this module's three lines twice and the measured
38
- * facts not at all.
39
- */
40
2
  /**
41
3
  * How completely the supplied values must cover a criterion.
42
4
  *
@@ -1,48 +1,5 @@
1
1
  import { type AdapterModel, type OperationIdentity } from "@aventara/core";
2
2
  import type { PrismaIdentifierAddress } from "../discovery/discovery-artifact.interface.js";
3
- /**
4
- * # Pure, and the tables are the module
5
- *
6
- * No client, no database, no provider name.
7
- *
8
- * - {@link SCALAR_DIRECTIVE_TOKENS} over `ScalarMutationDirective`;
9
- * - {@link RELATION_DIRECTIVE_EMISSIONS} over `RelationMutationDirective`;
10
- *
11
- * This module's emission site is {@link emitValue}, which is now a call rather
12
- * than a copy.
13
- *
14
- * Two of core's passes are already keyed that way; this is the third, and the only
15
- * one that names Prisma.
16
- *
17
- * # Refusing is part of honouring (the `where.translator.ts` stance)
18
- *
19
- * The adapter assumes validated input. It still refuses to EMIT a directive the
20
- * discovered model does not advertise for that field and stage, and refuses one
21
- * for which Prisma's nested input at that stage and cardinality has no key at all.
22
- * A directive quietly dropped here would surface as a write that silently did less
23
- * than it was asked to.
24
- *
25
- * `RelationFieldCapabilities` is one record per field with a single `create`
26
- * member **[CORE, adapters/adapter-field.ts]**, so "relation create directives for
27
- * `create.one` and none for `create.many`" is unrepresentable in the model;
28
- * `model.discoverer.ts` composes the permissive `create.one` answer and says so.
29
- * The restriction therefore lives in {@link MUTATION_DATA_SITES}, which is keyed
30
- * by the operation the data belongs to. Measured at 7.10.0 on both engines
31
- * (2026-10-02), a nested relation key in a bulk write is a hard failure, not a
32
- * no-op:
33
- *
34
- * - `post.createMany({ data: [{ title, author: { connect: … } }] })` → *"Argument
35
- * `authorId` is missing."*
36
- * - `post.updateMany({ where, data: { category: { connect: … } } })` → *"Unknown
37
- * argument `category`. Available options are marked with ?."*
38
- *
39
- * # Nothing in the caller's arguments is touched
40
- *
41
- * Every object and array returned is new. The input is read, never written: a
42
- * translator that mutated its argument would corrupt the second attempt of a
43
- * retried operation, which is the one place the bug would not show up in a
44
- * single-shot test.
45
- */
46
3
  /** A mutation the model, the stage or the active operation does not license. */
47
4
  export declare class PrismaMutationTranslationError extends Error {
48
5
  readonly name = "PrismaMutationTranslationError";
@@ -60,12 +17,9 @@ export type PrismaMutationDependencies = {
60
17
  readonly translateWhere: PrismaNestedWhereTranslator;
61
18
  /**
62
19
  * Prisma addressing per Resource, from the generate-time translation table
63
- * (`PrismaDiscoveryArtifact.translation`). Required, because a nested
64
- * `connect` is a `<T>WhereUniqueInput` and core's unique selector is FLAT: a
65
- * compound identifier must be wrapped under its recorded key. Measured on
66
- * both engines (2026-10-02) — the flat form is refused outright:
67
- * *"Argument `connect`: Invalid value provided. Expected
68
- * MetricWhereUniqueInput[], provided Object."*
20
+ * (`PrismaDiscoveryArtifact.translation`). Required, because a nested `connect`
21
+ * is a `<T>WhereUniqueInput` and core's unique selector is FLAT: a compound
22
+ * identifier must be wrapped under its recorded key.
69
23
  */
70
24
  readonly identifiers: Readonly<Record<string, readonly PrismaIdentifierAddress[]>>;
71
25
  };
@@ -81,8 +35,8 @@ export type MutationTranslation = {
81
35
  readonly data: unknown;
82
36
  };
83
37
  /**
84
- * Translates one validated Aventara mutation `data` into the Prisma write argument
85
- * for the named operation and stage.
38
+ * Translates one validated Aventara mutation `data` into the Prisma write
39
+ * argument for the named operation and stage.
86
40
  *
87
41
  * @throws {PrismaMutationTranslationError} rather than emitting a directive the
88
42
  * model does not advertise, one Prisma has no key for at this stage and