@aventara/prisma7-adapter 0.1.0-pilot.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/LICENSE +91 -0
  2. package/LICENSE-ADDITIONAL-PERMISSION.md +9 -0
  3. package/README.md +564 -0
  4. package/dist/discovery/artifact.loader.d.ts +26 -0
  5. package/dist/discovery/artifact.loader.js +124 -0
  6. package/dist/discovery/capability-surface.interface.d.ts +191 -0
  7. package/dist/discovery/capability-surface.interface.js +13 -0
  8. package/dist/discovery/capability.deriver.d.ts +92 -0
  9. package/dist/discovery/capability.deriver.js +350 -0
  10. package/dist/discovery/discovery-artifact.interface.d.ts +210 -0
  11. package/dist/discovery/discovery-artifact.interface.js +1 -0
  12. package/dist/discovery/enum.mapper.d.ts +59 -0
  13. package/dist/discovery/enum.mapper.js +32 -0
  14. package/dist/discovery/field.mapper.d.ts +244 -0
  15. package/dist/discovery/field.mapper.js +387 -0
  16. package/dist/discovery/identifier.mapper.d.ts +188 -0
  17. package/dist/discovery/identifier.mapper.js +132 -0
  18. package/dist/discovery/model.discoverer.d.ts +108 -0
  19. package/dist/discovery/model.discoverer.js +341 -0
  20. package/dist/discovery/operations.deriver.d.ts +75 -0
  21. package/dist/discovery/operations.deriver.js +92 -0
  22. package/dist/discovery/scalar.mapper.d.ts +81 -0
  23. package/dist/discovery/scalar.mapper.js +51 -0
  24. package/dist/discovery/schema-facts.interface.d.ts +174 -0
  25. package/dist/discovery/schema-facts.interface.js +11 -0
  26. package/dist/discovery/schema.reader.d.ts +162 -0
  27. package/dist/discovery/schema.reader.js +692 -0
  28. package/dist/discovery/types.reader.d.ts +24 -0
  29. package/dist/discovery/types.reader.js +617 -0
  30. package/dist/discovery/vocabulary.dictionary.d.ts +258 -0
  31. package/dist/discovery/vocabulary.dictionary.js +429 -0
  32. package/dist/errors/error.normalizer.d.ts +250 -0
  33. package/dist/errors/error.normalizer.js +135 -0
  34. package/dist/errors/prisma-error.reader.d.ts +144 -0
  35. package/dist/errors/prisma-error.reader.js +167 -0
  36. package/dist/execution/first-variant.emulator.d.ts +64 -0
  37. package/dist/execution/first-variant.emulator.js +205 -0
  38. package/dist/execution/operation.executor.d.ts +87 -0
  39. package/dist/execution/operation.executor.js +210 -0
  40. package/dist/execution/result.shaper.d.ts +103 -0
  41. package/dist/execution/result.shaper.js +141 -0
  42. package/dist/execution/transaction.executor.d.ts +147 -0
  43. package/dist/execution/transaction.executor.js +13 -0
  44. package/dist/generate/artifact.emitter.d.ts +50 -0
  45. package/dist/generate/artifact.emitter.js +105 -0
  46. package/dist/generate/declared-support.reader.d.ts +33 -0
  47. package/dist/generate/declared-support.reader.js +74 -0
  48. package/dist/generate/discovery.bin.d.ts +2 -0
  49. package/dist/generate/discovery.bin.js +15 -0
  50. package/dist/generate/discovery.cli.d.ts +24 -0
  51. package/dist/generate/discovery.cli.js +163 -0
  52. package/dist/generate/existence.gate.d.ts +73 -0
  53. package/dist/generate/existence.gate.js +91 -0
  54. package/dist/generate/index.d.ts +81 -0
  55. package/dist/generate/index.js +65 -0
  56. package/dist/generate/node-version.guard.d.ts +8 -0
  57. package/dist/generate/node-version.guard.js +59 -0
  58. package/dist/generate/prisma-cli.resolver.d.ts +48 -0
  59. package/dist/generate/prisma-cli.resolver.js +95 -0
  60. package/dist/generate/prisma.generate.d.ts +164 -0
  61. package/dist/generate/prisma.generate.js +278 -0
  62. package/dist/generate/reader-crosscheck.d.ts +156 -0
  63. package/dist/generate/reader-crosscheck.js +202 -0
  64. package/dist/index.d.ts +5 -0
  65. package/dist/index.js +1 -0
  66. package/dist/prisma-client.interface.d.ts +48 -0
  67. package/dist/prisma-client.interface.js +9 -0
  68. package/dist/prisma.adapter.d.ts +55 -0
  69. package/dist/prisma.adapter.js +105 -0
  70. package/dist/provider/provider-profile.d.ts +53 -0
  71. package/dist/provider/provider-profile.js +91 -0
  72. package/dist/translation/identifier.addressing.d.ts +80 -0
  73. package/dist/translation/identifier.addressing.js +30 -0
  74. package/dist/translation/mutation.translator.d.ts +115 -0
  75. package/dist/translation/mutation.translator.js +580 -0
  76. package/dist/translation/operation.translator.d.ts +273 -0
  77. package/dist/translation/operation.translator.js +377 -0
  78. package/dist/translation/order-pagination.translator.d.ts +86 -0
  79. package/dist/translation/order-pagination.translator.js +159 -0
  80. package/dist/translation/projection.translator.d.ts +115 -0
  81. package/dist/translation/projection.translator.js +151 -0
  82. package/dist/translation/scalar.conversion.d.ts +101 -0
  83. package/dist/translation/scalar.conversion.js +221 -0
  84. package/dist/translation/where.translator.d.ts +79 -0
  85. package/dist/translation/where.translator.js +254 -0
  86. package/package.json +102 -0
@@ -0,0 +1,65 @@
1
+ import { createPrismaModelComposer } from "../discovery/model.discoverer.js";
2
+ import { resolveProviderProfile } from "../provider/provider-profile.js";
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
+ export { createPrismaModelComposer, PrismaModelCompositionError, } from "../discovery/model.discoverer.js";
38
+ 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
+ export async function generatePrismaDiscoveryArtifact(request) {
49
+ const profile = resolveProviderProfile({
50
+ provider: request.provider,
51
+ driver: request.driver,
52
+ });
53
+ return runPrismaGenerateStep({
54
+ schema: request.schema,
55
+ clientDirectory: request.clientDirectory,
56
+ provider: request.provider,
57
+ artifactFile: request.artifactFile,
58
+ composeModel: createPrismaModelComposer({
59
+ transactions: profile.transactions,
60
+ }),
61
+ ...(request.toolchain === undefined
62
+ ? {}
63
+ : { toolchain: request.toolchain }),
64
+ });
65
+ }
@@ -0,0 +1,8 @@
1
+ /** The sentence a bin answers on `version`, or `undefined` when `range` admits it. */
2
+ export declare function nodeVersionRefusal(bin: string, packageName: string, range: string, version: string): string | undefined;
3
+ /**
4
+ * Reads the manifest at `manifestUrl`; on a Node its `engines.node` does not
5
+ * admit, writes the sentence to stderr, sets exit code 1 and answers `true` โ€”
6
+ * the bin then loads nothing else.
7
+ */
8
+ export declare function refuseUnsupportedNode(bin: string, manifestUrl: URL): boolean;
@@ -0,0 +1,59 @@
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
+ import { readFileSync } from "fs";
3
+ function versionOf(text) {
4
+ const match = /^v?(\d+)\.(\d+)\.(\d+)/.exec(text);
5
+ if (match === null) {
6
+ throw new Error(`"${text}" is not a Node version`);
7
+ }
8
+ return [Number(match[1]), Number(match[2]), Number(match[3])];
9
+ }
10
+ function compareVersions(left, right) {
11
+ for (let index = 0; index < 3; index += 1) {
12
+ const difference = left[index] - right[index];
13
+ if (difference !== 0) {
14
+ return difference;
15
+ }
16
+ }
17
+ return 0;
18
+ }
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
+ function admits(range, version) {
25
+ return range.split("||").some((part) => {
26
+ const comparator = /^\s*(\^|>=)(\d+\.\d+\.\d+)\s*$/.exec(part);
27
+ if (comparator === null) {
28
+ throw new Error(`engines.node "${range}": the bin's Node guard reads only "^x.y.z" and ">=x.y.z" joined by "||"`);
29
+ }
30
+ const floor = versionOf(comparator[2]);
31
+ return (compareVersions(version, floor) >= 0 &&
32
+ (comparator[1] === ">=" || version[0] === floor[0]));
33
+ });
34
+ }
35
+ /** The sentence a bin answers on `version`, or `undefined` when `range` admits it. */
36
+ export function nodeVersionRefusal(bin, packageName, range, version) {
37
+ return admits(range, versionOf(version))
38
+ ? undefined
39
+ : `${bin}: Node ${version} is not supported; ${packageName} needs Node ${range}.`;
40
+ }
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
+ export function refuseUnsupportedNode(bin, manifestUrl) {
47
+ const manifest = JSON.parse(readFileSync(manifestUrl, "utf8"));
48
+ const range = manifest.engines === undefined ? undefined : manifest.engines.node;
49
+ if (range === undefined) {
50
+ throw new Error(`${manifest.name} declares no engines.node for its bin's Node guard`);
51
+ }
52
+ const refusal = nodeVersionRefusal(bin, manifest.name, range, process.version);
53
+ if (refusal === undefined) {
54
+ return false;
55
+ }
56
+ process.stderr.write(`${refusal}\n`);
57
+ process.exitCode = 1;
58
+ return true;
59
+ }
@@ -0,0 +1,48 @@
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:
9
+ *
10
+ * 1. `@prisma/prisma7` installed โ†’ its `prisma7` bin runs, provided the `prisma`
11
+ * it wraps is in the declared range;
12
+ * 2. otherwise `prisma`, **only** when its version is in the adapter's declared
13
+ * range (`peerDependencies.prisma`, read by the caller);
14
+ * 3. otherwise a refusal naming both, with the install command.
15
+ *
16
+ * # Where it looks
17
+ *
18
+ * Each package is looked up first from this module โ€” the adapter's own install,
19
+ * 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.
24
+ */
25
+ export type PrismaCli = {
26
+ /** The package whose bin runs: `@prisma/prisma7` or `prisma`. */
27
+ readonly package: "@prisma/prisma7" | "prisma";
28
+ /** The bin's JavaScript entry, run with the current `node`. */
29
+ readonly entry: string;
30
+ /** The `prisma` version that bin is: what the artifact is stamped with. */
31
+ readonly version: string;
32
+ };
33
+ export type PrismaCliResolution = {
34
+ readonly kind: "found";
35
+ readonly cli: PrismaCli;
36
+ } | {
37
+ readonly kind: "refused";
38
+ readonly reason: string;
39
+ };
40
+ /**
41
+ * The Prisma CLI to run, or why there is none. `searchFrom` holds the places to
42
+ * resolve from, in order โ€” a module URL or a path of a file in the directory to
43
+ * start from; `range` is the adapter's declared `prisma` range.
44
+ */
45
+ export declare function resolvePrismaCli(input: {
46
+ readonly searchFrom: readonly string[];
47
+ readonly range: string;
48
+ }): PrismaCliResolution;
@@ -0,0 +1,95 @@
1
+ import { existsSync, readFileSync, realpathSync } from "node:fs";
2
+ import path from "node:path";
3
+ import { fileURLToPath } from "node:url";
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
+ function locate(name, searchFrom) {
13
+ for (const base of searchFrom) {
14
+ let directory = path.dirname(base.startsWith("file:") ? fileURLToPath(base) : base);
15
+ for (;;) {
16
+ if (path.basename(directory) !== "node_modules") {
17
+ const manifest = path.join(directory, "node_modules", name, "package.json");
18
+ if (existsSync(manifest)) {
19
+ const real = realpathSync(manifest);
20
+ return {
21
+ directory: path.dirname(real),
22
+ manifest: JSON.parse(readFileSync(real, "utf8")),
23
+ };
24
+ }
25
+ }
26
+ const parent = path.dirname(directory);
27
+ if (parent === directory) {
28
+ break;
29
+ }
30
+ directory = parent;
31
+ }
32
+ }
33
+ return undefined;
34
+ }
35
+ function versionOf(located) {
36
+ return typeof located.manifest.version === "string"
37
+ ? located.manifest.version
38
+ : "with no version";
39
+ }
40
+ function binEntry(located, bin) {
41
+ const declared = located.manifest.bin;
42
+ const relative = typeof declared === "string"
43
+ ? declared
44
+ : typeof declared === "object" && declared !== null
45
+ ? declared[bin]
46
+ : undefined;
47
+ return typeof relative === "string"
48
+ ? path.join(located.directory, relative)
49
+ : undefined;
50
+ }
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
+ export function resolvePrismaCli(input) {
57
+ const install = `\`npm i -D "@prisma/prisma7@${input.range}"\``;
58
+ const prisma7 = locate("@prisma/prisma7", input.searchFrom);
59
+ if (prisma7 !== undefined) {
60
+ // The version is the wrapped CLI's, looked up from beside the wrapper.
61
+ const wrapped = locate("prisma", [
62
+ path.join(prisma7.directory, "package.json"),
63
+ ]);
64
+ const entry = binEntry(prisma7, "prisma7");
65
+ const version = wrapped === undefined ? undefined : versionOf(wrapped);
66
+ if (entry !== undefined &&
67
+ version !== undefined &&
68
+ satisfiesDeclaredRange(version, input.range)) {
69
+ return {
70
+ kind: "found",
71
+ cli: { package: "@prisma/prisma7", entry, version },
72
+ };
73
+ }
74
+ return {
75
+ kind: "refused",
76
+ reason: `the installed \`@prisma/prisma7\` ${versionOf(prisma7)} does not run a \`prisma\` in this adapter's declared range ${input.range}; install one that does: ${install}.`,
77
+ };
78
+ }
79
+ const prisma = locate("prisma", input.searchFrom);
80
+ if (prisma === undefined) {
81
+ return {
82
+ kind: "refused",
83
+ reason: `neither \`@prisma/prisma7\` nor \`prisma\` is installed where this adapter can resolve it; install the Prisma 7 CLI in this adapter's declared range ${input.range}: \`npm i -D "prisma@${input.range}"\`, or beside a Prisma 8 install ${install}.`,
84
+ };
85
+ }
86
+ const version = versionOf(prisma);
87
+ const entry = binEntry(prisma, "prisma");
88
+ if (!satisfiesDeclaredRange(version, input.range) || entry === undefined) {
89
+ return {
90
+ kind: "refused",
91
+ reason: `the installed \`prisma\` ${version} is outside this adapter's declared range ${input.range}, and \`@prisma/prisma7\` โ€” the Prisma 7 CLI under its own name, bin \`prisma7\` โ€” is not installed beside it; install it: ${install}.`,
92
+ };
93
+ }
94
+ return { kind: "found", cli: { package: "prisma", entry, version } };
95
+ }
@@ -0,0 +1,164 @@
1
+ import type { PrismaCapabilitySurface } from "../discovery/capability-surface.interface.js";
2
+ import type { PrismaAdapterModel, PrismaReferentialActionTable, PrismaTranslationTable } from "../discovery/discovery-artifact.interface.js";
3
+ import type { PrismaSchemaFacts } from "../discovery/schema-facts.interface.js";
4
+ import type { PrismaProvider } from "../provider/provider-profile.js";
5
+ import type { PrismaEntityAbsence } from "./existence.gate.js";
6
+ import { type PrismaCli } from "./prisma-cli.resolver.js";
7
+ import type { PrismaReaderExemption } from "./reader-crosscheck.js";
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.
15
+ *
16
+ * **The order is fixed, and each step earns its place:**
17
+ *
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).
44
+ *
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.
58
+ */
59
+ /** The `prisma` major this reader's grammar was written against (C-846). */
60
+ export declare const PINNED_PRISMA_MAJOR = 7;
61
+ export declare class PrismaGenerateStepError extends Error {
62
+ readonly name = "PrismaGenerateStepError";
63
+ }
64
+ /**
65
+ * What composition produces: the three halves the artifact carries.
66
+ *
67
+ * They are composed together and emitted apart. The `model` is core's โ€” hashed
68
+ * and Contract-bound โ€” while `translation` is the adapter's Prisma addressing and
69
+ * `referentialActions` is what the schema's resolved `@relation(onDelete:)` and
70
+ * `@relation(onUpdate:)` arguments say. Neither of the latter two is part of the
71
+ * model, so both stay out of the hash: a `@@unique(name:)` rename must not move
72
+ * the Contract identity, and core has no referential-action vocabulary for a
73
+ * Contract to carry. All three come from one pass over one field list, so they
74
+ * cannot disagree about which identifiers or which edges exist.
75
+ */
76
+ export type PrismaComposedArtifact = {
77
+ readonly model: PrismaAdapterModel;
78
+ readonly translation: PrismaTranslationTable;
79
+ readonly referentialActions: PrismaReferentialActionTable;
80
+ };
81
+ /**
82
+ * Composition of the two readers' facts into the artifact's two halves.
83
+ *
84
+ * 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.
88
+ */
89
+ export type PrismaModelComposer = (input: {
90
+ readonly facts: PrismaSchemaFacts;
91
+ readonly surface: PrismaCapabilitySurface;
92
+ readonly admitted: readonly string[];
93
+ }) => PrismaComposedArtifact;
94
+ /**
95
+ * The step's external world, in one record.
96
+ *
97
+ * Every member is an effect this package does not own โ€” a child process, a
98
+ * version on disk, a module resolution, a file write โ€” which is why they are
99
+ * injectable: the step's contract is the *order* it performs them in and the
100
+ * points at which it refuses, and neither is observable when the effects are
101
+ * unobservable. {@link createPrismaGenerateToolchain} is the real one.
102
+ */
103
+ export type PrismaGenerateToolchain = {
104
+ readonly installedPrismaVersion: () => Promise<string>;
105
+ readonly clientRuntimeResolves: (clientDirectory: string) => boolean;
106
+ readonly runPrismaGenerate: (schema: string) => Promise<void>;
107
+ readonly readSchema: (location: string) => Promise<PrismaSchemaFacts>;
108
+ readonly readSurface: (clientDirectory: string) => PrismaCapabilitySurface;
109
+ readonly writeArtifact: (file: string, source: string) => Promise<void>;
110
+ };
111
+ export type PrismaGenerateRequest = {
112
+ /** The `schema.prisma` file, or a Prisma 7 schema folder. */
113
+ readonly schema: string;
114
+ /** The generator's `output` directory: the ๐ŸŸข files' root. */
115
+ readonly clientDirectory: string;
116
+ readonly provider: PrismaProvider;
117
+ /** Where the emitted TypeScript artifact module is written. */
118
+ readonly artifactFile: string;
119
+ readonly composeModel: PrismaModelComposer;
120
+ readonly toolchain?: PrismaGenerateToolchain;
121
+ };
122
+ export type PrismaGenerateResult = {
123
+ readonly artifactFile: string;
124
+ /** The emitted module's exact bytes. */
125
+ readonly source: string;
126
+ readonly modelHash: string;
127
+ /** Resource names the ๐ŸŸข types admitted, in PSL declaration order. */
128
+ readonly admitted: readonly string[];
129
+ /** PSL-only entities the schema itself explained away. */
130
+ readonly excluded: readonly PrismaEntityAbsence[];
131
+ /**
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.
135
+ */
136
+ readonly exemptions: readonly PrismaReaderExemption[];
137
+ };
138
+ /**
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.
144
+ */
145
+ export declare function resolveInstalledPrismaCli(): PrismaCli;
146
+ /**
147
+ * The version fence's input: the version of the Prisma CLI this step runs, which
148
+ * is the tool that produces the client and the grammar the PSL reader was
149
+ * written against. (`@prisma/client`'s version is a different fact, fenced at
150
+ * load time against the artifact โ€” see `discovery/artifact.loader.ts`.)
151
+ */
152
+ export declare function readInstalledPrismaVersion(): Promise<string>;
153
+ /**
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`.
161
+ */
162
+ export declare function clientRuntimeResolves(clientDirectory: string): boolean;
163
+ export declare function createPrismaGenerateToolchain(): PrismaGenerateToolchain;
164
+ export declare function runPrismaGenerateStep(request: PrismaGenerateRequest): Promise<PrismaGenerateResult>;