@aventara/prisma7-adapter 0.1.0-pilot.0 → 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 +39 -28
  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
@@ -2,65 +2,42 @@ import type { PrismaResourceSurface } from "./capability-surface.interface.js";
2
2
  import type { PrismaSchemaField } from "./schema-facts.interface.js";
3
3
  import { type PrismaDiscoveryDiagnostic, type PrismaScalarMapping } from "./vocabulary.dictionary.js";
4
4
  /**
5
- * T-5 / C-809 — one Prisma column, answered in Aventara's words.
6
- *
7
5
  * # Four answers, no fifth, and no guess
8
6
  *
9
7
  * The outcome is a closed union because every way this can end is a decision
10
8
  * somebody has to be able to read back:
11
9
  *
12
10
  * - `scalar` — the Prisma type name had a row in the dictionary's total table.
13
- * - `enum` — the written type is an enum `enums.ts` confirms. It is **not** a
14
- * third field kind: C-810 has exactly two, and an enum-backed column is a
15
- * ScalarField. `enum.mapper.ts`'s `projectEnumBackedColumn` is where that
16
- * becomes a field type ref.
17
- * - `excluded` — PSL declares the column and the 🟢 types do not expose it. This
18
- * is the scalar half of C-808's existence gate, and the reason travels with it:
19
- * an exclusion nobody can explain is indistinguishable from a bug.
11
+ * - `enum` — the written type is an enum `enums.ts` confirms. `enum.mapper.ts`'s
12
+ * `projectEnumBackedColumn` is where that becomes a field type ref.
13
+ * - `excluded` — PSL declares the column and the 🟢 types do not expose it.
20
14
  * - `unmapped` — a type name in neither table. A **diagnostic**, never a silent
21
- * drop and never a nearest-neighbour guess (C-809).
15
+ * drop and never a nearest-neighbour guess.
22
16
  *
23
17
  * # Why `format` is emitted here at all — and why so little of it is
24
18
  *
25
- * T-3.1's table says `format?` is `CFG`, "policy, not discovery". Spec §6.1 says
26
- * UUID "is a string scalar plus passive format metadata **when the adapter can
27
- * prove the format**"; §18.3's discovery mapping says "scalar type → stable
28
- * framework scalar + optional format"; C-809 says "native types normalize to the
29
- * nearest stable scalar plus optional format"; and `AdapterScalarField.format?`
30
- * exists **[CORE]**, which would be a member with no producer if discovery never
31
- * emitted one. Three specification statements and a type beat one plan line, so
32
- * discovery does emit `format` — and T-3.1's row is corrected to `PSL` + `CFG`
33
- * in `vocabulary.dictionary.ts`.
34
- *
35
19
  * What the plan row was *right* about is that most of what looks like a format is
36
- * policy. `format` is **enforced**: `normalizeScalarFieldValue` turns
37
- * `format: "uuid"` into a `V1003` rejection of request input **[CORE,
20
+ * policy. `format` is **enforced**: `normalizeScalarFieldValue` turns `format:
21
+ * "uuid"` into a `V1003` rejection of request input **[CORE,
38
22
  * `runtime/scalar-runtime.ts`]**. So the bar for discovering one is not "the
39
23
  * schema suggests it" but "the column itself rejects what Aventara would then
40
- * reject". That admits `@db.Uuid` — PostgreSQL's `uuid` column refuses
41
- * `'not-a-uuid'` where `text` accepts it **[RUN8 — 2026-09-28, postgres:18]** —
42
- * and it excludes `@default(uuid())`, which T-5 also named: on a `text` column
43
- * only *generated* values are UUIDs and a client may legally write any string, so
44
- * emitting the format there would make Aventara refuse writes the database
45
- * accepts. That intent belongs in `FrameworkScalarFieldConfig.format` **[CORE]**,
24
+ * reject". That intent belongs in `FrameworkScalarFieldConfig.format` **[CORE]**,
46
25
  * which the Contract compiler already layers over the adapter's value.
47
26
  *
48
- * It follows that no `format` is emitted for either Phase 8 schema, whose only
49
- * UUID column is `Author.id String @default(uuid())` with no native type. That is
50
- * the correct answer, not a gap.
27
+ * That is the correct answer, not a gap.
51
28
  *
52
29
  * # Nothing here branches on a provider
53
30
  *
54
- * `@db.Uuid` is unwritable on SQLite, so the SQLite schema simply never carries
55
- * it and the same table gives the same right answer on both engines without a
56
- * provider arm (T-3.1 invariant 6).
31
+ * `@db.Uuid` is unwritable on SQLite, so the SQLite schema simply never carries it
32
+ * and the same table gives the same right answer on both engines without a
33
+ * provider arm.
57
34
  */
58
35
  export type ScalarMappingInput = {
59
36
  /** The PSL model name, carried so a diagnostic can name the column in full. */
60
37
  readonly resource: string;
61
38
  /** PSL — what the column IS. */
62
39
  readonly field: PrismaSchemaField;
63
- /** TYPE — what this client exposes. The existence gate (C-808). */
40
+ /** TYPE — what this client exposes. The existence gate. */
64
41
  readonly surface: PrismaResourceSurface;
65
42
  /** TYPE — `enums.ts`, which is what makes an enum name an enum name. */
66
43
  readonly enums: Readonly<Record<string, readonly string[]>>;
@@ -12,7 +12,6 @@ export function mapPrismaScalarField(input) {
12
12
  };
13
13
  }
14
14
  if (Object.hasOwn(enums, field.type)) {
15
- // C-810: this is a ScalarField whose type ref takes the `enum` arm.
16
15
  return { outcome: "enum", enum: field.type };
17
16
  }
18
17
  const mapping = PRISMA_SCALAR_TABLE[field.type];
@@ -25,8 +24,6 @@ export function mapPrismaScalarField(input) {
25
24
  },
26
25
  };
27
26
  }
28
- // Matched by exact written spelling, never parsed: `@db.Decimal(10, 2)`
29
- // matches no key and therefore proves no format, with no argument list split.
30
27
  const proven = field.native
31
28
  .map((native) => PRISMA_NATIVE_FORMATS[native])
32
29
  .find((format) => format !== undefined);
@@ -35,11 +32,6 @@ export function mapPrismaScalarField(input) {
35
32
  mapping: proven === undefined ? mapping : { ...mapping, format: proven },
36
33
  };
37
34
  }
38
- /**
39
- * The gate's message is built from evidence, never from an assumption: `@ignore`
40
- * is reported only where PSL actually wrote one, because "present in schema,
41
- * absent from client" with a made-up cause is worse than the bare fact.
42
- */
43
35
  function explainAbsence(field, surface) {
44
36
  if (field.ignored) {
45
37
  return "it carries `@ignore`";
@@ -1,17 +1,15 @@
1
1
  /**
2
- * T-3, source **PSL** — the output of the bounded `schema.prisma` reader.
3
- *
4
2
  * Nothing here is imported from `@prisma/client`: these are this adapter's own
5
3
  * facts over schema text, which is what keeps discovery a pure function of plain
6
- * data and unit-testable without a generated client (T-3).
4
+ * data and unit-testable without a generated client.
7
5
  *
8
- * Read `schema.reader.ts`'s header for the boundary these facts are drawn on:
9
- * the reader **locates** tokens and never **evaluates** them.
6
+ * Read `schema.reader.ts`'s header for the boundary these facts are drawn on: the
7
+ * reader **locates** tokens and never **evaluates** them.
10
8
  */
11
9
  import type { PrismaReferentialAction } from "./discovery-artifact.interface.js";
12
10
  /** Where a fact — or an unhandled construct — was found. One-based lines, as `prisma validate` reports them. */
13
11
  export type PrismaSchemaSite = {
14
- /** The schema file as the caller named it; a folder read names each member file (D-802, Prisma 7 folders). */
12
+ /** The schema file as the caller named it; a folder read names each member file. */
15
13
  readonly file: string;
16
14
  readonly line: number;
17
15
  };
@@ -24,13 +22,12 @@ export type PrismaSchemaSite = {
24
22
  * are recognised and deliberately discarded (bucket 2, the reader's explicit
25
23
  * `DISCARDED_ATTRIBUTES` list), because their values appear nowhere on the 🟢
26
24
  * generated surface. Recording them would fail the generate step on any schema
27
- * that maps a column name. `name:` is **not** discarded — see
28
- * {@link PrismaSchemaBlockIdentifier}.
25
+ * that maps a column name. `name:` is **not** discarded — see {@link
26
+ * PrismaSchemaBlockIdentifier}.
29
27
  *
30
28
  * Bucket 3 is recorded rather than dropped because silently dropping an
31
- * unrecognised attribute is how a grammar change becomes wrong output instead of
32
- * a build stop. A non-empty `PrismaSchemaFacts.unhandled` FAILS the generate step
33
- * (T-3.1 invariant 5).
29
+ * unrecognised attribute is how a grammar change becomes wrong output instead of a
30
+ * build stop. A non-empty `PrismaSchemaFacts.unhandled` FAILS the generate step.
34
31
  */
35
32
  export type PrismaSchemaUnknown = {
36
33
  readonly kind: PrismaSchemaUnknownKind;
@@ -56,15 +53,21 @@ export type PrismaSchemaUnknownKind =
56
53
  export type PrismaSchemaFacts = {
57
54
  readonly enums: readonly PrismaSchemaEnum[];
58
55
  readonly models: readonly PrismaSchemaModel[];
59
- /** Attributes and blocks the reader does not recognise at all (a `type`/`view` block, an
60
- * unrecognised argument, any spelling added after 7.10.0). `@map`/`@@map`/`@@index` are
61
- * recognised and deliberately discarded instead, so they never appear here.
62
- * Never silently dropped: a non-empty list FAILS the generate step (T-3.1 invariant 5). */
56
+ /**
57
+ * Attributes and blocks the reader does not recognise at all (a `type`/`view`
58
+ * block, an unrecognised argument, any spelling added after 7.10.0).
59
+ * `@map`/`@@map`/`@@index` are recognised and deliberately discarded instead, so
60
+ * they never appear here. Never silently dropped: a non-empty list FAILS the
61
+ * generate step.
62
+ */
63
63
  readonly unhandled: readonly PrismaSchemaUnknown[];
64
64
  };
65
65
  export type PrismaSchemaEnum = {
66
66
  readonly name: string;
67
- /** Declaration order is semantic (§19.2); a member-level `@map` is discarded (bucket 2), not recorded. */
67
+ /**
68
+ * Declaration order is semantic; a member-level `@map` is discarded (bucket 2),
69
+ * not recorded.
70
+ */
68
71
  readonly values: readonly string[];
69
72
  readonly site: PrismaSchemaSite;
70
73
  };
@@ -117,7 +120,7 @@ export type PrismaSchemaField = {
117
120
  readonly type: string;
118
121
  /** `[]` */
119
122
  readonly list: boolean;
120
- /** `?` — the ONLY source of nullability (T-3.1 invariant 4). */
123
+ /** `?` — the ONLY source of nullability. */
121
124
  readonly optional: boolean;
122
125
  /** `@id` */
123
126
  readonly id: boolean;
@@ -125,16 +128,14 @@ export type PrismaSchemaField = {
125
128
  readonly unique: boolean;
126
129
  /** `@updatedAt` */
127
130
  readonly updatedAt: boolean;
128
- /** `@default(…)`'s argument as RAW TEXT — matched against a table, never parsed (T-3.1 invariant 5). */
131
+ /** `@default(…)`'s argument as RAW TEXT — matched against a table, never parsed. */
129
132
  readonly defaultArgument: string | null;
130
133
  readonly relation: PrismaSchemaRelation | null;
131
134
  /**
132
- * `@db.*` as written, e.g. `@db.Decimal(10, 2)`. Kept verbatim and never
133
- * parsed. A native type is the **only** proof discovery accepts for
134
- * `format` (C-809, spec §6.1 "when the adapter can prove the format");
135
- * configuration may then override it, since `AdapterScalarField.format`
136
- * and `FrameworkScalarFieldConfig.format` are separate members the
137
- * compiler layers.
135
+ * `@db.*` as written, e.g. `@db.Decimal(10, 2)`. Kept verbatim and never parsed. A
136
+ * native type is the **only** proof discovery accepts for `format`; configuration
137
+ * may then override it, since `AdapterScalarField.format` and
138
+ * `FrameworkScalarFieldConfig.format` are separate members the compiler layers.
138
139
  */
139
140
  readonly native: readonly string[];
140
141
  /** `@ignore` */
@@ -144,7 +145,7 @@ export type PrismaSchemaField = {
144
145
  export type PrismaSchemaRelation = {
145
146
  /** `@relation("Name")` — the ONLY evidence pairing a back-reference with its forward reference. */
146
147
  readonly name: string | null;
147
- /** The FK scalar(s); read, used, then discarded (C-813). */
148
+ /** The FK scalar(s); read, used, then discarded. */
148
149
  readonly fields: readonly string[] | null;
149
150
  readonly references: readonly string[] | null;
150
151
  /**
@@ -1,11 +1 @@
1
- /**
2
- * T-3, source **PSL** — the output of the bounded `schema.prisma` reader.
3
- *
4
- * Nothing here is imported from `@prisma/client`: these are this adapter's own
5
- * facts over schema text, which is what keeps discovery a pure function of plain
6
- * data and unit-testable without a generated client (T-3).
7
- *
8
- * Read `schema.reader.ts`'s header for the boundary these facts are drawn on:
9
- * the reader **locates** tokens and never **evaluates** them.
10
- */
11
1
  export {};
@@ -1,39 +1,34 @@
1
1
  import type { PrismaSchemaFacts } from "./schema-facts.interface.js";
2
2
  /**
3
- * T-3, source **PSL** — the bounded `schema.prisma` reader.
4
- *
5
3
  * # The boundary, and why this file is a reader and not a parser
6
4
  *
7
5
  * It **locates** tokens and never **evaluates** them.
8
6
  *
9
7
  * PSL's model body is line-oriented by the language's own rule, not by this
10
- * reader's assumption. Re-measured against `prisma` 7.10.0 on 2026-09-28, all
11
- * four constructs that would let a declaration legally span lines are
12
- * **rejected** with `Error code: P1012` — so the classic regex-parser failure
13
- * cannot occur:
8
+ * reader's assumption. Re-measured against `prisma` 7.10.0 on 2026-09-28, all four
9
+ * constructs that would let a declaration legally span lines are **rejected** with
10
+ * `Error code: P1012` — so the classic regex-parser failure cannot occur:
14
11
  *
15
12
  * 1. a wrapped `@@unique([…])` — the error COUNT is layout-dependent, the
16
13
  * rejection is not. A two-line wrap (`@@unique([x,` / `y])`) gives 2 errors,
17
14
  * both `error: Error validating: This line is not a valid field or attribute
18
15
  * definition.`; a four-line wrap gives 4 — three of that sentence plus one
19
- * `Error validating model "A": This field declaration is invalid. It is
20
- * either missing a name or a type.`
21
- * 2. a wrapped field attribute (`@default(uuid())` on the line below `id String @id`)
22
- * — 1 error, `This line is not a valid field or attribute definition.`
16
+ * `Error validating model "A": This field declaration is invalid. It is either
17
+ * missing a name or a type.`
18
+ * 2. a wrapped field attribute (`@default(uuid())` on the line below `id String
19
+ * @id`) — 1 error, `This line is not a valid field or attribute definition.`
23
20
  * 3. two block attributes on one line (`@@unique([x]) @@index([y])`) — 1 error,
24
21
  * `This line is not a valid field or attribute definition.`
25
22
  * 4. a split field declaration (`id` then `String @id`) — 2 errors, **both**
26
23
  * `Error validating model "A": This field declaration is invalid. It is either
27
24
  * missing a name or a type.`
28
25
  *
29
- * **Correction to the plan's wording (2026-09-28, re-measured, not inherited).**
30
- * The plan and T-3 previously said all four are rejected *with* `P1012 … This
31
- * line is not a valid field or attribute definition`. All four are indeed
32
- * `P1012`, **and the line-oriented conclusion holds unchanged** — the design did
33
- * not move. But case 4 never emits that sentence at all (it emits *"This field
34
- * declaration is invalid. It is either missing a name or a type."* twice), and
35
- * case 1 emits a second, different sentence besides it. The evidence supports the
36
- * rule; the single-sentence attribution does not, and the plan now says so.
26
+ * All four are indeed `P1012`, **and the line-oriented conclusion holds
27
+ * unchanged** — the design did not move. But case 4 never emits that sentence at
28
+ * all (it emits *"This field declaration is invalid. It is either missing a name
29
+ * or a type."* twice), and case 1 emits a second, different sentence besides it.
30
+ * The evidence supports the rule; the single-sentence attribution does not, and
31
+ * the plan now says so.
37
32
  *
38
33
  * Re-running it: `prisma` lives at `packages/prisma7-adapter/node_modules/.bin/
39
34
  * prisma`, not the worktree root. Invoked from the root it silently produces no
@@ -47,9 +42,9 @@ import type { PrismaSchemaFacts } from "./schema-facts.interface.js";
47
42
  * needs a different decision. Hence:
48
43
  *
49
44
  * - `@default`'s argument is kept as **raw text** and matched against a table
50
- * downstream, never parsed (T-3.1 invariant 5).
45
+ * downstream, never parsed.
51
46
  * - `@db.*` is kept **as written** and never parsed. It is the only proof
52
- * discovery accepts for `format` (C-809); configuration overrides it later.
47
+ * discovery accepts for `format`; configuration overrides it later.
53
48
  * - a field's `type` stays the written token — `Grade` is not resolved to the
54
49
  * enum, which is also why a schema **folder** needs no linker (below).
55
50
  * - an attribute is classified three ways, not two (below), and only the third
@@ -60,16 +55,16 @@ import type { PrismaSchemaFacts } from "./schema-facts.interface.js";
60
55
  *
61
56
  * # The three-way classification (corrected 2026-09-28)
62
57
  *
63
- * 1. **recognised and modelled** — `FIELD_ATTRIBUTES`, `BLOCK_ATTRIBUTES`,
64
- * `@db.*` and `RELATION_ARGUMENTS`.
58
+ * 1. **recognised and modelled** — `FIELD_ATTRIBUTES`, `BLOCK_ATTRIBUTES`, `@db.*`
59
+ * and `RELATION_ARGUMENTS`.
65
60
  * 2. **recognised and deliberately discarded**, via the explicit
66
61
  * `DISCARDED_ATTRIBUTES` / `DISCARDED_BLOCK_ATTRIBUTE_ARGUMENTS` lists —
67
- * `@map`, `@@map`, `@@index`, and `@@id`/`@@unique`'s `map:` argument. The
68
- * rule is one line long: an argument is discardable **iff its value appears
69
- * nowhere on the 🟢 surface**. The list being explicit is the point: the
70
- * discard is a decision a reader can see and audit, not an omission. That
71
- * rule is also what took `name:` back OFF this list (2026-09-29): its value
72
- * is a `WhereUniqueInput` key and an `AtLeast` key, so it is carried on
62
+ * `@map`, `@@map`, `@@index`, and `@@id`/`@@unique`'s `map:` argument. The rule
63
+ * is one line long: an argument is discardable **iff its value appears nowhere
64
+ * on the 🟢 surface**. The list being explicit is the point: the discard is a
65
+ * decision a reader can see and audit, not an omission. That rule is also what
66
+ * took `name:` back OFF this list (2026-09-29): its value is a
67
+ * `WhereUniqueInput` key and an `AtLeast` key, so it is carried on
73
68
  * `PrismaSchemaBlockIdentifier`.
74
69
  * 3. **unrecognised** — on neither list, therefore `unhandled`, therefore a build
75
70
  * stop.
@@ -79,51 +74,45 @@ import type { PrismaSchemaFacts } from "./schema-facts.interface.js";
79
74
  * Bucket 2's rule reads "discardable iff the value appears nowhere on the 🟢
80
75
  * surface", and `@relation(onDelete: Cascade)` passes that test: measured at
81
76
  * 7.10.0, `Cascade` reaches nothing but the 🛑 `internal/class.ts` inline-schema
82
- * blob. It is still **not** discardable, and this is the first construct where
83
- * the test and the rule it stands for come apart.
77
+ * blob. It is still **not** discardable, and this is the first construct where the
78
+ * test and the rule it stands for come apart.
84
79
  *
85
80
  * The rule's *reason* was that such attributes configure the database below the
86
81
  * ORM entrypoint and therefore carry no framework meaning. A referential action
87
82
  * fails that reason while passing the test: it changes what a delete **does** —
88
- * rows disappear that the caller never named — which is exactly what a
89
- * transaction planner must reason about before it agrees to run a plan. So
90
- * invisibility on the generated types is *evidence* for "no framework meaning",
91
- * and evidence can be outweighed; it was never the meaning itself. `@map` and
92
- * `@@index` remain discarded because they fail the test AND the reason.
93
- * `@relation`'s `map:` joins them: a foreign-key constraint name is genuinely
94
- * DB-side, and it was bucket 3 until now, which made `@relation(map: …)` — valid
95
- * PSL — a build stop on its own.
96
- *
97
- * Actions are read on both arguments and carried **resolved**: an absent
98
- * argument is not a third state, it is Prisma's effective default, measured
99
- * rather than assumed (see `REFERENTIAL_ACTIONS` and
100
- * `resolvePrismaReferentialDefaults`).
83
+ * rows disappear that the caller never named — which is exactly what a transaction
84
+ * planner must reason about before it agrees to run a plan. So invisibility on the
85
+ * generated types is *evidence* for "no framework meaning", and evidence can be
86
+ * outweighed; it was never the meaning itself. `@map` and `@@index` remain
87
+ * discarded because they fail the test AND the reason. `@relation`'s `map:` joins
88
+ * them: a foreign-key constraint name is genuinely DB-side, and it was bucket 3
89
+ * until now, which made `@relation(map: …)` — valid PSL — a build stop on its own.
90
+ *
91
+ * Actions are read on both arguments and carried **resolved**: an absent argument
92
+ * is not a third state, it is Prisma's effective default, measured rather than
93
+ * assumed (see `REFERENTIAL_ACTIONS` and `resolvePrismaReferentialDefaults`).
101
94
  *
102
95
  * Bucket 2 previously did not exist, and a field-level `@map` landed in
103
96
  * `unhandled`: the framework would have refused to build against any schema that
104
- * maps a column name, which is most real Prisma schemas. It was invisible only
105
- * because both Phase 8 schemas use zero `@map`. The enum **member**-level `@map`
106
- * discard, which T-3's `PrismaSchemaEnum` and Task 3's enum-mapper case already
107
- * required, folds into bucket 2 and stops being a special case.
97
+ * maps a column name, which is most real Prisma schemas.
108
98
  *
109
99
  * # Arguments are located by NAME, never by position (added 2026-09-29)
110
100
  *
111
- * PSL lets the same argument list arrive positionally or named, and lets the
112
- * named arguments come in any order. Measured against `prisma validate` 7.10.0
113
- * and against a generated client on 2026-09-29: `@@unique([b, a])`,
114
- * `@@unique(fields: [b, a])`, `@@unique(name: "k", map: "m", fields: [b, a])`
115
- * and every other permutation are accepted, and the client keys the unnamed ones
116
- * `b_a` and the named ones `k` regardless of the order they were written in. The
117
- * spelling is therefore not a fact about the schema, and a reader that took the
118
- * list to be the FIRST argument read `@@unique(fields: [b, a])` as one member
119
- * called `fields: [b, a]` — silently, with `unhandled` empty — so the generate
120
- * step refused a schema Prisma accepts. ARGUMENT order does not matter; MEMBER
121
- * order inside the list still does, because it is part of the identity and of
122
- * the addressing key.
101
+ * PSL lets the same argument list arrive positionally or named, and lets the named
102
+ * arguments come in any order. Measured against `prisma validate` 7.10.0 and
103
+ * against a generated client on 2026-09-29: `@@unique([b, a])`, `@@unique(fields:
104
+ * [b, a])`, `@@unique(name: "k", map: "m", fields: [b, a])` and every other
105
+ * permutation are accepted, and the client keys the unnamed ones `b_a` and the
106
+ * named ones `k` regardless of the order they were written in. The spelling is
107
+ * therefore not a fact about the schema, and a reader that took the list to be the
108
+ * FIRST argument read `@@unique(fields: [b, a])` as one member called `fields: [b,
109
+ * a]` — silently, with `unhandled` empty — so the generate step refused a schema
110
+ * Prisma accepts. ARGUMENT order does not matter; MEMBER order inside the list
111
+ * still does, because it is part of the identity and of the addressing key.
123
112
  *
124
113
  * The same rule applies to `@relation`, which mixes a positional argument (the
125
- * relation name) with named ones; it was already order-independent and its FK
126
- * read was unaffected.
114
+ * relation name) with named ones; it was already order-independent and its FK read
115
+ * was unaffected.
127
116
  *
128
117
  * A list whose members are not plain field names — `@@unique([a(sort: Desc)])`,
129
118
  * valid PSL at 7.10.0 — cannot be located without evaluating, so it is bucket 3
@@ -139,9 +128,9 @@ import type { PrismaSchemaFacts } from "./schema-facts.interface.js";
139
128
  *
140
129
  * Prisma 7 accepts a folder (`prisma validate --schema <folder>` verified at
141
130
  * 7.10.0). Blocks are file-local and references are by name, so there is no
142
- * cross-file grammar and **no linker**: reading a folder appends each file's
143
- * facts in filename order and nothing is rewritten. Every fact keeps the file and
144
- * line it was written on.
131
+ * cross-file grammar and **no linker**: reading a folder appends each file's facts
132
+ * in filename order and nothing is rewritten. Every fact keeps the file and line
133
+ * it was written on.
145
134
  */
146
135
  export type PrismaSchemaSource = {
147
136
  readonly file: string;