@aventara/prisma7-adapter 0.1.0-pilot.1 → 0.1.0-pilot.2

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 (79) hide show
  1. package/README.md +33 -20
  2. package/dist/discovery/artifact.loader.d.ts +6 -2
  3. package/dist/discovery/artifact.loader.js +12 -57
  4. package/dist/discovery/capability-surface.interface.d.ts +29 -40
  5. package/dist/discovery/capability-surface.interface.js +0 -12
  6. package/dist/discovery/capability.deriver.d.ts +10 -40
  7. package/dist/discovery/capability.deriver.js +0 -179
  8. package/dist/discovery/client-shape.verifier.d.ts +13 -0
  9. package/dist/discovery/client-shape.verifier.js +93 -0
  10. package/dist/discovery/discovery-artifact.interface.d.ts +55 -30
  11. package/dist/discovery/enum.mapper.d.ts +6 -14
  12. package/dist/discovery/enum.mapper.js +1 -2
  13. package/dist/discovery/field.mapper.d.ts +49 -63
  14. package/dist/discovery/field.mapper.js +0 -161
  15. package/dist/discovery/identifier.mapper.d.ts +38 -77
  16. package/dist/discovery/identifier.mapper.js +0 -64
  17. package/dist/discovery/model.discoverer.d.ts +18 -35
  18. package/dist/discovery/model.discoverer.js +66 -141
  19. package/dist/discovery/operations.deriver.d.ts +10 -38
  20. package/dist/discovery/operations.deriver.js +0 -40
  21. package/dist/discovery/scalar.mapper.d.ts +12 -35
  22. package/dist/discovery/scalar.mapper.js +0 -8
  23. package/dist/discovery/schema-facts.interface.d.ts +26 -25
  24. package/dist/discovery/schema-facts.interface.js +0 -10
  25. package/dist/discovery/schema.reader.d.ts +53 -64
  26. package/dist/discovery/schema.reader.js +0 -174
  27. package/dist/discovery/types.reader.d.ts +0 -4
  28. package/dist/discovery/types.reader.js +2 -177
  29. package/dist/discovery/vocabulary.dictionary.d.ts +36 -75
  30. package/dist/discovery/vocabulary.dictionary.js +2 -152
  31. package/dist/errors/error.normalizer.d.ts +85 -135
  32. package/dist/errors/error.normalizer.js +1 -70
  33. package/dist/errors/prisma-error.reader.d.ts +53 -68
  34. package/dist/errors/prisma-error.reader.js +0 -91
  35. package/dist/execution/first-variant.emulator.d.ts +11 -22
  36. package/dist/execution/first-variant.emulator.js +0 -142
  37. package/dist/execution/operation.executor.d.ts +12 -19
  38. package/dist/execution/operation.executor.js +0 -92
  39. package/dist/execution/result.shaper.d.ts +22 -31
  40. package/dist/execution/result.shaper.js +0 -24
  41. package/dist/execution/transaction.executor.d.ts +36 -73
  42. package/dist/generate/artifact.emitter.d.ts +27 -27
  43. package/dist/generate/artifact.emitter.js +30 -13
  44. package/dist/generate/declared-support.reader.d.ts +11 -11
  45. package/dist/generate/declared-support.reader.js +0 -12
  46. package/dist/generate/discovery.bin.js +0 -10
  47. package/dist/generate/discovery.cli.js +0 -55
  48. package/dist/generate/existence.gate.d.ts +26 -32
  49. package/dist/generate/existence.gate.js +0 -6
  50. package/dist/generate/index.d.ts +10 -12
  51. package/dist/generate/index.js +0 -42
  52. package/dist/generate/node-version.guard.js +0 -12
  53. package/dist/generate/prisma-cli.resolver.d.ts +9 -11
  54. package/dist/generate/prisma-cli.resolver.js +0 -13
  55. package/dist/generate/prisma.generate.d.ts +49 -65
  56. package/dist/generate/prisma.generate.js +13 -123
  57. package/dist/generate/reader-crosscheck.d.ts +36 -60
  58. package/dist/generate/reader-crosscheck.js +5 -41
  59. package/dist/prisma-client.interface.d.ts +14 -19
  60. package/dist/prisma-client.interface.js +0 -6
  61. package/dist/prisma.adapter.d.ts +9 -17
  62. package/dist/prisma.adapter.js +11 -53
  63. package/dist/provider/provider-profile.d.ts +6 -23
  64. package/dist/provider/provider-profile.js +0 -64
  65. package/dist/translation/identifier.addressing.d.ts +15 -22
  66. package/dist/translation/identifier.addressing.js +0 -10
  67. package/dist/translation/mutation.translator.d.ts +19 -43
  68. package/dist/translation/mutation.translator.js +1 -209
  69. package/dist/translation/operation.translator.d.ts +36 -63
  70. package/dist/translation/operation.translator.js +1 -51
  71. package/dist/translation/order-pagination.translator.d.ts +24 -31
  72. package/dist/translation/order-pagination.translator.js +0 -43
  73. package/dist/translation/projection.translator.d.ts +25 -58
  74. package/dist/translation/projection.translator.js +0 -27
  75. package/dist/translation/scalar.conversion.d.ts +15 -26
  76. package/dist/translation/scalar.conversion.js +1 -129
  77. package/dist/translation/where.translator.d.ts +17 -28
  78. package/dist/translation/where.translator.js +0 -83
  79. package/package.json +3 -3
@@ -20,16 +20,6 @@ function compare(left, right) {
20
20
  }
21
21
  return 0;
22
22
  }
23
- /**
24
- * Whether `version` satisfies `range`, for the range forms a peer declaration
25
- * here uses: space-separated comparators (`>=5.5.0 <7`), each `^`, `>=`, `>`,
26
- * `<=`, `<`, `=` or bare, with missing minor and patch read as `0`.
27
- *
28
- * Only a plain release can satisfy: a pre-release (`8.0.0-rc.20`) never does,
29
- * which is semver's own rule for a range whose comparators carry no pre-release
30
- * tag. A range in any other form is a defect in this package's manifest, so it
31
- * throws rather than answering a guess.
32
- */
33
23
  export function satisfiesDeclaredRange(version, range) {
34
24
  const release = RELEASE.exec(version);
35
25
  if (release === null) {
@@ -45,8 +35,6 @@ export function satisfiesDeclaredRange(version, range) {
45
35
  .split(/\s+/)
46
36
  .every((comparator) => {
47
37
  const parsed = COMPARATOR.exec(comparator);
48
- // `^0.x` means something narrower than "same major", and no peer here
49
- // declares one, so it is refused with the forms this does not read.
50
38
  if (parsed === null || (parsed[1] === "^" && parsed[2] === "0")) {
51
39
  throw new Error(`the declared range \`${range}\` has a comparator, \`${comparator}\`, that the generate step does not read`);
52
40
  }
@@ -1,15 +1,5 @@
1
1
  #!/usr/bin/env node
2
2
  import { refuseUnsupportedNode } from "./node-version.guard.js";
3
- /**
4
- * `aventara-prisma7-generate`'s entry, what the manifest's `bin` names (F-855). It always runs — no
5
- * `import.meta.main` — and checks this Node against the package's
6
- * `engines.node` before it loads anything else: the program is imported only
7
- * once the guard admits this Node, so an older Node meets one sentence and exit
8
- * 1, never a silent exit 0 or a parse error from a module it cannot run.
9
- *
10
- * A promise chain rather than a top-level `await`, which Node 12 cannot parse:
11
- * this file is read by the Nodes the package does not support.
12
- */
13
3
  if (!refuseUnsupportedNode("aventara-prisma7-generate", new URL("../../package.json", import.meta.url))) {
14
4
  void import("./discovery.cli.js").then((program) => program.runFromProcess());
15
5
  }
@@ -1,40 +1,6 @@
1
1
  import path from "node:path";
2
2
  import { PRISMA_DRIVERS, PRISMA_PROVIDERS, } from "../provider/provider-profile.js";
3
3
  import { generatePrismaDiscoveryArtifact } from "./index.js";
4
- /**
5
- * F-805 — `aventara-prisma7-generate`: the published binary that produces the
6
- * discovery artifact `createPrismaAdapter({ discovery })` requires.
7
- *
8
- * Before this existed, `package.json` declared no `bin`, one `"."` export and
9
- * `files: ["dist"]` over a build that excluded `src/generate/**` — so a consumer
10
- * of the published package could not produce an artifact for their own schema at
11
- * all, and the only artifacts in existence were the two this repository generates
12
- * for its own tests. The package was unusable as published.
13
- *
14
- * # It reads nothing it was not told
15
- *
16
- * Every input is an argument. There is no repository path, no fixture schema, no
17
- * convention-over-configuration search and no tsconfig of this package's: the
18
- * types reader builds its own program over the client directory it is given. That
19
- * is the whole reason this file is a flag parser and `discovery.generate.ts` — the
20
- * repository's own two-engine script — is a separate file that happens to call the
21
- * same function.
22
- *
23
- * `--provider` and `--driver` are required rather than sniffed. The provider is
24
- * stamped into the artifact as a recorded fact, and the driver decides
25
- * `AdapterModel.transactions`, which is a **driver** fact the schema cannot state:
26
- * a `datasource` block names `postgresql`, not whether the application will drive
27
- * it through `@prisma/adapter-pg`. Guessing either would put a guess in the
28
- * artifact; D-804's rule is that the caller declares.
29
- *
30
- * # Failure is a message and an exit code, never a stack
31
- *
32
- * The step's refusals are deliberate, legible and aimed at the person running the
33
- * build — a `prisma` major this reader has never seen, a generated tree whose
34
- * runtime does not resolve, a schema construct the reader does not model. Printing
35
- * a V8 stack trace over them would bury the sentence that says what to do. An
36
- * unexpected error keeps its stack, because that one is a defect.
37
- */
38
4
  const USAGE = `aventara-prisma7-generate — emit a @aventara/prisma7-adapter discovery artifact.
39
5
 
40
6
  Usage:
@@ -69,14 +35,6 @@ const FLAGS = {
69
35
  "--driver": "driver",
70
36
  "--out": "artifactFile",
71
37
  };
72
- /**
73
- * The flags, parsed. Exported so a case can drive it without a child process:
74
- * the parse is the only judgement this file makes, and the rest is the step's.
75
- *
76
- * `--flag value` only. `--flag=value` is deliberately not accepted, because
77
- * accepting both spellings means two code paths over one fact for a binary whose
78
- * entire surface is five required flags.
79
- */
80
38
  export function parsePrismaGenerateArguments(argv) {
81
39
  const seen = {};
82
40
  for (let index = 0; index < argv.length; index += 1) {
@@ -107,8 +65,6 @@ export function parsePrismaGenerateArguments(argv) {
107
65
  if (!PRISMA_DRIVERS.includes(driver)) {
108
66
  throw new PrismaGenerateCliError(`\`--driver ${seen.driver}\` is not one of ${PRISMA_DRIVERS.join(", ")}.`);
109
67
  }
110
- // Resolved against the process's own directory, so every path in the output
111
- // names one place and a relative `--out` lands where the caller meant.
112
68
  return {
113
69
  schema: path.resolve(seen.schema),
114
70
  clientDirectory: path.resolve(seen.clientDirectory),
@@ -129,27 +85,16 @@ async function main(argv) {
129
85
  for (const absence of result.excluded) {
130
86
  process.stdout.write(`excluded: ${absence.message}\n`);
131
87
  }
132
- // Printed every run, because a cross-check whose exemptions are invisible is a
133
- // cross-check nobody can audit.
134
88
  for (const exemption of result.exemptions) {
135
89
  process.stdout.write(`exempt (${exemption.kind}) ${exemption.entity}: ${exemption.reason}\n`);
136
90
  }
137
91
  return 0;
138
92
  }
139
- /**
140
- * Runs `aventara-prisma7-generate` over this process — its arguments, its
141
- * output, its exit code. Called by the bin's entry (`discovery.bin.ts`) once the
142
- * Node guard has admitted this Node; importing this module runs nothing, which
143
- * is what lets the parse be tested without the process exiting.
144
- */
145
93
  export async function runFromProcess() {
146
94
  try {
147
95
  process.exitCode = await main(process.argv.slice(2));
148
96
  }
149
97
  catch (error) {
150
- // A refusal from the step or this parser is a sentence the person running the
151
- // build has to read; a stack trace in front of it is noise. Anything else is
152
- // a defect and keeps its stack.
153
98
  const named = error instanceof PrismaGenerateCliError ||
154
99
  (error instanceof Error &&
155
100
  (error.name === "PrismaGenerateStepError" ||
@@ -1,45 +1,39 @@
1
1
  import type { PrismaCapabilitySurface } from "../discovery/capability-surface.interface.js";
2
2
  import type { PrismaSchemaFacts, PrismaSchemaSite } from "../discovery/schema-facts.interface.js";
3
3
  /**
4
- * T-3.1 invariant 3 / C-808 — **existence is gated by TYPE; attributes come
5
- * from PSL.**
6
- *
7
- * An entity enters the `AdapterModel` iff the 🟢 generated types expose it.
8
- * The gate is strictly stronger than any attribute list: it catches `@ignore`,
4
+ * An entity enters the `AdapterModel` iff the 🟢 generated types expose it. The
5
+ * gate is strictly stronger than any attribute list: it catches `@ignore`,
9
6
  * `@@ignore`, preview-feature exclusions, provider drops and `Unsupported(…)`
10
7
  * columns with no special case for any of them, because all of them show up the
11
8
  * same way — as a name PSL declares and the client does not carry
12
- * (`Unsupported(…)` confirmed absent from `$Payload.scalars` and from
13
- * `FieldRefs` at 7.10.0 **[RUN8]**).
9
+ * (`Unsupported(…)` confirmed absent from `$Payload.scalars` and from `FieldRefs`
10
+ * at 7.10.0 **[RUN8]**).
14
11
  *
15
- * `@ignore` and `@@ignore` are parsed **anyway**, and that is this module's
16
- * whole subtlety. They do not drive the gate — the types do. They exist so the
17
- * gate's report can say *why* an entity is absent rather than emitting the
18
- * useless "present in schema, absent from client", and so the two outcomes can
19
- * be told apart:
12
+ * `@ignore` and `@@ignore` are parsed **anyway**, and that is this module's whole
13
+ * subtlety. They do not drive the gate — the types do. They exist so the gate's
14
+ * report can say *why* an entity is absent rather than emitting the useless
15
+ * "present in schema, absent from client", and so the two outcomes can be told
16
+ * apart:
20
17
  *
21
- * - **Explained** — PSL itself instructed the exclusion. Recorded, reported,
22
- * and **not fatal**. `@ignore` is a documented Prisma instruction with a
23
- * deliberate author behind it; stopping the build on it would leave the
24
- * developer no remedy but to delete the instruction, and an error with no
25
- * remedy is a defect rather than a fence.
26
- * - **Unexplained** — nothing in the schema accounts for the absence.
27
- * **Fatal.** Emitting the entity would hand the framework a Resource the
28
- * adapter can never execute against; omitting it silently would ship a model
29
- * that is quietly missing something the developer wrote.
18
+ * - **Explained** — PSL itself instructed the exclusion. Recorded, reported, and
19
+ * **not fatal**. `@ignore` is a documented Prisma instruction with a deliberate
20
+ * author behind it; stopping the build on it would leave the developer no remedy
21
+ * but to delete the instruction, and an error with no remedy is a defect rather
22
+ * than a fence.
23
+ * - **Unexplained** — nothing in the schema accounts for the absence. **Fatal.**
24
+ * Emitting the entity would hand the framework a Resource the adapter can never
25
+ * execute against; omitting it silently would ship a model that is quietly
26
+ * missing something the developer wrote.
30
27
  *
31
- * (Recorded conflict, for whoever reconciles the plan: Task 3's checklist reads
32
- * "a PSL-only entity is a generate-time error" flatly, while C-808's own proof
33
- * line reads "absent, with the exclusion explained". This module implements the
34
- * split above, which is the only reading under which the stated *reason* for
35
- * the error — "otherwise the adapter hands the framework a Resource it can
36
- * never execute against" — survives: once the entity is excluded, no such
37
- * Resource is handed over, and what remains to decide is only whether to stop
38
- * the build. It is worth stopping for the absence nobody asked for.)
28
+ * This module implements the split above, which is the only reading under which
29
+ * the stated *reason* for the error — "otherwise the adapter hands the framework a
30
+ * Resource it can never execute against" — survives: once the entity is excluded,
31
+ * no such Resource is handed over, and what remains to decide is only whether to
32
+ * stop the build. It is worth stopping for the absence nobody asked for.)
39
33
  *
40
- * The reverse direction — a resource the types expose and PSL does not declare
41
- * — is a reader inconsistency rather than an existence question, and belongs to
42
- * `reader-crosscheck.ts` (Task 6). This module does not answer it.
34
+ * The reverse direction — a resource the types expose and PSL does not declare —
35
+ * is a reader inconsistency rather than an existence question, and belongs to
36
+ * `reader-crosscheck.ts`. This module does not answer it.
43
37
  */
44
38
  export type PrismaAbsenceKind = "model" | "field";
45
39
  /** What PSL said, when PSL said anything. */
@@ -28,12 +28,6 @@ function unexplainedMessage(entity, kind, site) {
28
28
  : "Admitting it would put a field in the Contract that no query, filter or write can ever name";
29
29
  return `\`${entity}\` is declared at ${where(site)} but ${surfaceSays(entity, kind)}, and nothing in the schema explains the absence — there is no ${instruction} on it. ${cost}, and dropping it silently would ship a model quietly missing something the schema declares. ${CAUSES}.`;
30
30
  }
31
- /**
32
- * Runs the gate. Returns what was admitted and what PSL explained away; throws
33
- * {@link PrismaExistenceGateError} listing every unexplained absence at once,
34
- * because fixing them one build at a time is how a schema migration becomes a
35
- * week.
36
- */
37
31
  export function applyExistenceGate(facts, surface) {
38
32
  const admitted = [];
39
33
  const explained = [];
@@ -1,13 +1,11 @@
1
1
  import type { PrismaDriver, PrismaProvider } from "../provider/provider-profile.js";
2
2
  import type { PrismaGenerateResult, PrismaGenerateToolchain } from "./prisma.generate.js";
3
3
  /**
4
- * F-805 — the package's **second published entry**: `@aventara/prisma7-adapter/generate`.
5
- *
6
4
  * # Why a second entry rather than a second package or a wider `"."`
7
5
  *
8
6
  * The runtime entry (`"."`) depends on `@aventara/core` and the caller's own
9
- * generated client, and on nothing else. The generate path needs `typescript`
10
- * (the types reader builds a real TypeScript program over the generated tree) and
7
+ * generated client, and on nothing else. The generate path needs `typescript` (the
8
+ * types reader builds a real TypeScript program over the generated tree) and
11
9
  * `prisma` (the step runs `prisma generate` itself, so that both sources describe
12
10
  * one instant). Those two are declared as **optional peer dependencies**, not as
13
11
  * dependencies, and the split is what keeps the plan's guarantee that *no
@@ -16,9 +14,9 @@ import type { PrismaGenerateResult, PrismaGenerateToolchain } from "./prisma.gen
16
14
  * optional peer is not installed on their behalf.
17
15
  *
18
16
  * The published build therefore carries both halves and the `exports` map is what
19
- * separates them. Nothing reachable from `"."` imports anything under
20
- * `generate/`; `artifact.loader.spec.ts` asserts that from the import graph
21
- * rather than from this paragraph.
17
+ * separates them. Nothing reachable from `"."` imports anything under `generate/`;
18
+ * `artifact.loader.spec.ts` asserts that from the import graph rather than from
19
+ * this paragraph.
22
20
  *
23
21
  * # What this entry is for
24
22
  *
@@ -29,9 +27,9 @@ import type { PrismaGenerateResult, PrismaGenerateToolchain } from "./prisma.gen
29
27
  * already has a build script and would rather call it.
30
28
  *
31
29
  * Everything the step itself exposes is re-exported, because the seams are the
32
- * point: a consumer with an unusual toolchain can supply their own
33
- * {@link PrismaGenerateToolchain}, and one with their own composition rules can
34
- * call {@link runPrismaGenerateStep} directly.
30
+ * point: a consumer with an unusual toolchain can supply their own {@link
31
+ * PrismaGenerateToolchain}, and one with their own composition rules can call
32
+ * {@link runPrismaGenerateStep} directly.
35
33
  */
36
34
  export { createPrismaModelComposer, PrismaModelCompositionError, } from "../discovery/model.discoverer.js";
37
35
  export type { PrismaEntityAbsence } from "./existence.gate.js";
@@ -42,8 +40,8 @@ export type { PrismaReaderExemption } from "./reader-crosscheck.js";
42
40
  * One engine's generate request, as a consumer states it.
43
41
  *
44
42
  * `driver` is here and is not on {@link PrismaGenerateRequest} for a reason the
45
- * step's own header gives: `AdapterModel.transactions` is a **driver** fact (T-2)
46
- * that is stamped into the artifact at generate time, while the step itself is
43
+ * step's own header gives: `AdapterModel.transactions` is a **driver** fact that
44
+ * is stamped into the artifact at generate time, while the step itself is
47
45
  * forbidden to know a provider or a driver at all — composition is created with a
48
46
  * transaction capability and nothing else, so `if (provider === …)` inside
49
47
  * discovery is a compile error rather than a convention. This function is the one
@@ -1,50 +1,8 @@
1
1
  import { createPrismaModelComposer } from "../discovery/model.discoverer.js";
2
2
  import { resolveProviderProfile } from "../provider/provider-profile.js";
3
3
  import { runPrismaGenerateStep } from "./prisma.generate.js";
4
- /**
5
- * F-805 — the package's **second published entry**: `@aventara/prisma7-adapter/generate`.
6
- *
7
- * # Why a second entry rather than a second package or a wider `"."`
8
- *
9
- * The runtime entry (`"."`) depends on `@aventara/core` and the caller's own
10
- * generated client, and on nothing else. The generate path needs `typescript`
11
- * (the types reader builds a real TypeScript program over the generated tree) and
12
- * `prisma` (the step runs `prisma generate` itself, so that both sources describe
13
- * one instant). Those two are declared as **optional peer dependencies**, not as
14
- * dependencies, and the split is what keeps the plan's guarantee that *no
15
- * compiler, no parser and no Prisma tooling enters the deployed runtime*: a
16
- * consumer who imports only `"."` never loads a module that names either, and an
17
- * optional peer is not installed on their behalf.
18
- *
19
- * The published build therefore carries both halves and the `exports` map is what
20
- * separates them. Nothing reachable from `"."` imports anything under
21
- * `generate/`; `artifact.loader.spec.ts` asserts that from the import graph
22
- * rather than from this paragraph.
23
- *
24
- * # What this entry is for
25
- *
26
- * Producing the discovery artifact `createPrismaAdapter({ discovery })` requires,
27
- * from the consumer's own `schema.prisma` and their own generated client. The
28
- * `aventara-prisma7-generate` binary (`discovery.cli.ts`) is this function with an
29
- * argument parser in front of it; this module is the same thing for a consumer who
30
- * already has a build script and would rather call it.
31
- *
32
- * Everything the step itself exposes is re-exported, because the seams are the
33
- * point: a consumer with an unusual toolchain can supply their own
34
- * {@link PrismaGenerateToolchain}, and one with their own composition rules can
35
- * call {@link runPrismaGenerateStep} directly.
36
- */
37
4
  export { createPrismaModelComposer, PrismaModelCompositionError, } from "../discovery/model.discoverer.js";
38
5
  export { createPrismaGenerateToolchain, PINNED_PRISMA_MAJOR, PrismaGenerateStepError, runPrismaGenerateStep, } from "./prisma.generate.js";
39
- /**
40
- * The generate step, wired: provider profile → transaction capability →
41
- * composition → the step.
42
- *
43
- * Every decision stays where it already lived. This function resolves the profile
44
- * and builds the composer; it makes no judgement of its own, which is why there is
45
- * nothing here to test beyond that it is the wiring the CLI and the repository's
46
- * own `generate` script both use.
47
- */
48
6
  export async function generatePrismaDiscoveryArtifact(request) {
49
7
  const profile = resolveProviderProfile({
50
8
  provider: request.provider,
@@ -1,4 +1,3 @@
1
- // biome-ignore lint/style/useNodejsImportProtocol: Node 14.0–14.13.0 resolves no "node:" specifier in an ES module, and this module runs on the Nodes the packages do not support.
2
1
  import { readFileSync } from "fs";
3
2
  function versionOf(text) {
4
3
  const match = /^v?(\d+)\.(\d+)\.(\d+)/.exec(text);
@@ -16,11 +15,6 @@ function compareVersions(left, right) {
16
15
  }
17
16
  return 0;
18
17
  }
19
- /**
20
- * Whether `range` admits `version`. Reads `^x.y.z` (the same major, from the
21
- * floor; majors ≥ 1) and `>=x.y.z`, joined by `||`; anything else throws rather
22
- * than admit or refuse by guess.
23
- */
24
18
  function admits(range, version) {
25
19
  return range.split("||").some((part) => {
26
20
  const comparator = /^\s*(\^|>=)(\d+\.\d+\.\d+)\s*$/.exec(part);
@@ -32,17 +26,11 @@ function admits(range, version) {
32
26
  (comparator[1] === ">=" || version[0] === floor[0]));
33
27
  });
34
28
  }
35
- /** The sentence a bin answers on `version`, or `undefined` when `range` admits it. */
36
29
  export function nodeVersionRefusal(bin, packageName, range, version) {
37
30
  return admits(range, versionOf(version))
38
31
  ? undefined
39
32
  : `${bin}: Node ${version} is not supported; ${packageName} needs Node ${range}.`;
40
33
  }
41
- /**
42
- * Reads the manifest at `manifestUrl`; on a Node its `engines.node` does not
43
- * admit, writes the sentence to stderr, sets exit code 1 and answers `true` —
44
- * the bin then loads nothing else.
45
- */
46
34
  export function refuseUnsupportedNode(bin, manifestUrl) {
47
35
  const manifest = JSON.parse(readFileSync(manifestUrl, "utf8"));
48
36
  const range = manifest.engines === undefined ? undefined : manifest.engines.node;
@@ -1,11 +1,9 @@
1
1
  /**
2
- * D11 — which Prisma CLI the generate step runs.
3
- *
4
- * `prisma`'s `latest` is a Prisma 8 release candidate (plan B32), so `npm i
5
- * prisma` in a Prisma 7 project now installs a CLI this adapter's readers were
6
- * never written against. Prisma's own upgrade path keeps the Prisma 7 CLI side by
7
- * side as **`@prisma/prisma7`**, bin `prisma7` — the same CLI under a
8
- * version-specific name. So, in this order:
2
+ * `prisma`'s `latest` is a Prisma 8 release candidate, so `npm i prisma` in a
3
+ * Prisma 7 project now installs a CLI this adapter's readers were never written
4
+ * against. Prisma's own upgrade path keeps the Prisma 7 CLI side by side as
5
+ * **`@prisma/prisma7`**, bin `prisma7` — the same CLI under a version-specific
6
+ * name. So, in this order:
9
7
  *
10
8
  * 1. `@prisma/prisma7` installed → its `prisma7` bin runs, provided the `prisma`
11
9
  * it wraps is in the declared range;
@@ -17,10 +15,10 @@
17
15
  *
18
16
  * Each package is looked up first from this module — the adapter's own install,
19
17
  * where an optional peer is linked — and then from the project the step runs in
20
- * (its working directory), where a strict installer such as pnpm leaves a
21
- * package the adapter does not declare. A found package is followed to its real
22
- * path, so the `prisma` that `@prisma/prisma7` wraps is the one beside it and not
23
- * a `prisma` 8 hoisted next to the link.
18
+ * (its working directory), where a strict installer such as pnpm leaves a package
19
+ * the adapter does not declare. A found package is followed to its real path, so
20
+ * the `prisma` that `@prisma/prisma7` wraps is the one beside it and not a
21
+ * `prisma` 8 hoisted next to the link.
24
22
  */
25
23
  export type PrismaCli = {
26
24
  /** The package whose bin runs: `@prisma/prisma7` or `prisma`. */
@@ -2,13 +2,6 @@ import { existsSync, readFileSync, realpathSync } from "node:fs";
2
2
  import path from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
4
  import { satisfiesDeclaredRange } from "./declared-support.reader.js";
5
- /**
6
- * The first `node_modules/<name>/package.json` on the way up from each place in
7
- * turn — Node's own lookup order, walked by hand because the manifest is all
8
- * that is wanted: no `exports` map can hide it, and no `NODE_PATH` can answer
9
- * from outside the install (a test runner sets one, and a resolution answered
10
- * through it has produced a false green in this package before).
11
- */
12
5
  function locate(name, searchFrom) {
13
6
  for (const base of searchFrom) {
14
7
  let directory = path.dirname(base.startsWith("file:") ? fileURLToPath(base) : base);
@@ -48,16 +41,10 @@ function binEntry(located, bin) {
48
41
  ? path.join(located.directory, relative)
49
42
  : undefined;
50
43
  }
51
- /**
52
- * The Prisma CLI to run, or why there is none. `searchFrom` holds the places to
53
- * resolve from, in order — a module URL or a path of a file in the directory to
54
- * start from; `range` is the adapter's declared `prisma` range.
55
- */
56
44
  export function resolvePrismaCli(input) {
57
45
  const install = `\`npm i -D "@prisma/prisma7@${input.range}"\``;
58
46
  const prisma7 = locate("@prisma/prisma7", input.searchFrom);
59
47
  if (prisma7 !== undefined) {
60
- // The version is the wrapped CLI's, looked up from beside the wrapper.
61
48
  const wrapped = locate("prisma", [
62
49
  path.join(prisma7.directory, "package.json"),
63
50
  ]);
@@ -1,62 +1,52 @@
1
1
  import type { PrismaCapabilitySurface } from "../discovery/capability-surface.interface.js";
2
- import type { PrismaAdapterModel, PrismaReferentialActionTable, PrismaTranslationTable } from "../discovery/discovery-artifact.interface.js";
2
+ import type { PrismaAdapterModel, PrismaCreateRequirementTable, PrismaReferentialActionTable, PrismaTranslationTable } from "../discovery/discovery-artifact.interface.js";
3
3
  import type { PrismaSchemaFacts } from "../discovery/schema-facts.interface.js";
4
4
  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
8
  /**
9
- * Task 3 — the adapter's **generate step**: a devDependency-only executable and
10
- * the only module that runs `prisma` or spawns a process. Nothing under
11
- * `execution/`, and nothing in `discovery/artifact.loader.ts`, imports it; the
12
- * package's build `exclude` keeps `src/generate/**` out of `dist` entirely, so
13
- * a deployed application never carries `typescript`, a PSL reader or a child
14
- * process.
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.
15
13
  *
16
14
  * **The order is fixed, and each step earns its place:**
17
15
  *
18
- * 1. **The pinned `prisma` major** (C-846). PSL's grammar and the generated
19
- * client's shape are version-bound; a major this reader has never seen must
20
- * stop the build rather than produce a wrong `AdapterModel` from a grammar
21
- * nobody read.
22
- * 2. **`@prisma/client/runtime/client` resolves** (§1.2 item 16). This one is
23
- * first among equals, because its failure is *silent*: every generated file
24
- * opens `// @ts-nocheck`, so with the runtime unresolvable a TypeScript
25
- * program over the generated tree reports **zero** diagnostics while
26
- * `FieldRef` degrades to its uninstantiated form and `JsonValue` stops being
27
- * a union — flipping a types-derived nullability from `true` to `false` with
28
- * nothing anywhere to say so **[RUN8]**. The guard is therefore a module
29
- * *resolution*, never a diagnostic count: a diagnostic count is exactly the
30
- * instrument that reads clean in this failure.
31
- * 3. **`prisma generate`**, run by this step itself. The two sources must
32
- * describe one instant; a client generated by some earlier command may
33
- * describe an older schema, and nothing downstream could tell.
34
- * 4. **Both sources read in that same run** — PSL for the semantic model, the
35
- * 🟢 generated types for the capability surface and for existence.
36
- * 5. **The structural checks, in that order.** The existence gate first (T-3.1
37
- * invariant 3), because it decides *which* entities exist and a cross-check
38
- * of an entity nobody admitted is noise; then the reader-versus-reader
39
- * cross-check (`reader-crosscheck.ts`), which answers the reverse direction
40
- * the gate hands it and every other fact both sources carry. Its findings
41
- * stop the step; its two documented exemptions are reported and carried out
42
- * on the result.
43
- * 6. **Emit** one TypeScript module (ADR 0009).
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.
44
40
  *
45
- * The plan's §9 sketch puts the runtime check *after* `prisma generate`; the
46
- * order above is the brief's, and it is the better one — module resolution
47
- * walks `node_modules` upward from the client directory and does not need the
48
- * directory populated, so nothing is gained by generating output first that the
49
- * step is about to refuse to read.
50
- *
51
- * **The two readers fail differently, and the step keeps them different.** A
52
- * PSL `unhandled` entry means *I located a token I do not model*: there is a
53
- * construct, a spelling and a site to report, so they are aggregated and
54
- * reported together. A types-reader failure means *I cannot read the surface at
55
- * all*: there is nothing to record, so it throws. Inventing an `unhandled`
56
- * vocabulary for the type surface would be a second parallel representation of
57
- * "something went wrong" for no gain.
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.
58
48
  */
59
- /** The `prisma` major this reader's grammar was written against (C-846). */
49
+ /** The `prisma` major this reader's grammar was written against. */
60
50
  export declare const PINNED_PRISMA_MAJOR = 7;
61
51
  export declare class PrismaGenerateStepError extends Error {
62
52
  readonly name = "PrismaGenerateStepError";
@@ -77,14 +67,15 @@ export type PrismaComposedArtifact = {
77
67
  readonly model: PrismaAdapterModel;
78
68
  readonly translation: PrismaTranslationTable;
79
69
  readonly referentialActions: PrismaReferentialActionTable;
70
+ readonly createRequirements: PrismaCreateRequirementTable;
80
71
  };
81
72
  /**
82
73
  * Composition of the two readers' facts into the artifact's two halves.
83
74
  *
84
75
  * It is a parameter rather than a call, because composition is
85
- * `discovery/model.discoverer.ts`'s (Task 6) and this step's job is order and
86
- * refusal over external effects. The step hands over only what it has verified:
87
- * both readers' output, and the resource names the existence gate admitted.
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.
88
79
  */
89
80
  export type PrismaModelComposer = (input: {
90
81
  readonly facts: PrismaSchemaFacts;
@@ -129,18 +120,14 @@ export type PrismaGenerateResult = {
129
120
  /** PSL-only entities the schema itself explained away. */
130
121
  readonly excluded: readonly PrismaEntityAbsence[];
131
122
  /**
132
- * Reader disagreements that are understood — the `Json` nullability one and
133
- * C-815's unexplained `AtLeast` key. Carried out rather than swallowed, so a
134
- * caller can print them and a spec can assert them by name and reason.
123
+ * Carried out rather than swallowed, so a caller can print them and a spec can
124
+ * assert them by name and reason.
135
125
  */
136
126
  readonly exemptions: readonly PrismaReaderExemption[];
137
127
  };
138
128
  /**
139
- * The Prisma CLI this step runs, chosen as D11 states (`prisma-cli.resolver.ts`):
140
- * `@prisma/prisma7`'s `prisma7` when it is installed, else `prisma` when its
141
- * version is in the adapter's declared range, else a refusal naming both. Looked
142
- * up from this package — where an optional peer is linked — and then from the
143
- * project the step runs in.
129
+ * Looked up from this package — where an optional peer is linked — and then from
130
+ * the project the step runs in.
144
131
  */
145
132
  export declare function resolveInstalledPrismaCli(): PrismaCli;
146
133
  /**
@@ -151,13 +138,10 @@ export declare function resolveInstalledPrismaCli(): PrismaCli;
151
138
  */
152
139
  export declare function readInstalledPrismaVersion(): Promise<string>;
153
140
  /**
154
- * Whether `@prisma/client/runtime/client` resolves from inside the generated
155
- * tree — the single question §1.2 item 16 turns on.
156
- *
157
- * Asked as a module resolution, never as a diagnostic count, and asked from a
158
- * file path *inside* `clientDirectory` because resolution walks `node_modules`
159
- * upward from the importer. The directory need not exist yet: resolution is a
160
- * path question, which is what lets this fence run before `prisma generate`.
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`.
161
145
  */
162
146
  export declare function clientRuntimeResolves(clientDirectory: string): boolean;
163
147
  export declare function createPrismaGenerateToolchain(): PrismaGenerateToolchain;