@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.
- package/README.md +39 -28
- package/dist/discovery/artifact.loader.d.ts +6 -2
- package/dist/discovery/artifact.loader.js +12 -57
- package/dist/discovery/capability-surface.interface.d.ts +29 -40
- package/dist/discovery/capability-surface.interface.js +0 -12
- package/dist/discovery/capability.deriver.d.ts +10 -40
- package/dist/discovery/capability.deriver.js +0 -179
- package/dist/discovery/client-shape.verifier.d.ts +13 -0
- package/dist/discovery/client-shape.verifier.js +93 -0
- package/dist/discovery/discovery-artifact.interface.d.ts +55 -30
- package/dist/discovery/enum.mapper.d.ts +6 -14
- package/dist/discovery/enum.mapper.js +1 -2
- package/dist/discovery/field.mapper.d.ts +49 -63
- package/dist/discovery/field.mapper.js +0 -161
- package/dist/discovery/identifier.mapper.d.ts +38 -77
- package/dist/discovery/identifier.mapper.js +0 -64
- package/dist/discovery/model.discoverer.d.ts +18 -35
- package/dist/discovery/model.discoverer.js +66 -141
- package/dist/discovery/operations.deriver.d.ts +10 -38
- package/dist/discovery/operations.deriver.js +0 -40
- package/dist/discovery/scalar.mapper.d.ts +12 -35
- package/dist/discovery/scalar.mapper.js +0 -8
- package/dist/discovery/schema-facts.interface.d.ts +26 -25
- package/dist/discovery/schema-facts.interface.js +0 -10
- package/dist/discovery/schema.reader.d.ts +53 -64
- package/dist/discovery/schema.reader.js +0 -174
- package/dist/discovery/types.reader.d.ts +0 -4
- package/dist/discovery/types.reader.js +2 -177
- package/dist/discovery/vocabulary.dictionary.d.ts +36 -75
- package/dist/discovery/vocabulary.dictionary.js +2 -152
- package/dist/errors/error.normalizer.d.ts +85 -135
- package/dist/errors/error.normalizer.js +1 -70
- package/dist/errors/prisma-error.reader.d.ts +53 -68
- package/dist/errors/prisma-error.reader.js +0 -91
- package/dist/execution/first-variant.emulator.d.ts +11 -22
- package/dist/execution/first-variant.emulator.js +0 -142
- package/dist/execution/operation.executor.d.ts +12 -19
- package/dist/execution/operation.executor.js +0 -92
- package/dist/execution/result.shaper.d.ts +22 -31
- package/dist/execution/result.shaper.js +0 -24
- package/dist/execution/transaction.executor.d.ts +36 -73
- package/dist/generate/artifact.emitter.d.ts +27 -27
- package/dist/generate/artifact.emitter.js +30 -13
- package/dist/generate/declared-support.reader.d.ts +11 -11
- package/dist/generate/declared-support.reader.js +0 -12
- package/dist/generate/discovery.bin.js +0 -10
- package/dist/generate/discovery.cli.js +0 -55
- package/dist/generate/existence.gate.d.ts +26 -32
- package/dist/generate/existence.gate.js +0 -6
- package/dist/generate/index.d.ts +10 -12
- package/dist/generate/index.js +0 -42
- package/dist/generate/node-version.guard.js +0 -12
- package/dist/generate/prisma-cli.resolver.d.ts +9 -11
- package/dist/generate/prisma-cli.resolver.js +0 -13
- package/dist/generate/prisma.generate.d.ts +49 -65
- package/dist/generate/prisma.generate.js +13 -123
- package/dist/generate/reader-crosscheck.d.ts +36 -60
- package/dist/generate/reader-crosscheck.js +5 -41
- package/dist/prisma-client.interface.d.ts +14 -19
- package/dist/prisma-client.interface.js +0 -6
- package/dist/prisma.adapter.d.ts +9 -17
- package/dist/prisma.adapter.js +11 -53
- package/dist/provider/provider-profile.d.ts +6 -23
- package/dist/provider/provider-profile.js +0 -64
- package/dist/translation/identifier.addressing.d.ts +15 -22
- package/dist/translation/identifier.addressing.js +0 -10
- package/dist/translation/mutation.translator.d.ts +19 -43
- package/dist/translation/mutation.translator.js +1 -209
- package/dist/translation/operation.translator.d.ts +36 -63
- package/dist/translation/operation.translator.js +1 -51
- package/dist/translation/order-pagination.translator.d.ts +24 -31
- package/dist/translation/order-pagination.translator.js +0 -43
- package/dist/translation/projection.translator.d.ts +25 -58
- package/dist/translation/projection.translator.js +0 -27
- package/dist/translation/scalar.conversion.d.ts +15 -26
- package/dist/translation/scalar.conversion.js +1 -129
- package/dist/translation/where.translator.d.ts +17 -28
- package/dist/translation/where.translator.js +0 -83
- 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.
|
|
14
|
-
*
|
|
15
|
-
*
|
|
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
|
|
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
|
-
*
|
|
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
|
|
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
|
-
*
|
|
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
|
-
*
|
|
56
|
-
* provider arm
|
|
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
|
|
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
|
|
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
|
-
*
|
|
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
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
/**
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
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
|
-
/**
|
|
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
|
|
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
|
|
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
|
-
*
|
|
134
|
-
*
|
|
135
|
-
*
|
|
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
|
|
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
|
-
*
|
|
12
|
-
*
|
|
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
|
-
*
|
|
21
|
-
* 2. a wrapped field attribute (`@default(uuid())` on the line below `id String
|
|
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
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
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
|
|
45
|
+
* downstream, never parsed.
|
|
51
46
|
* - `@db.*` is kept **as written** and never parsed. It is the only proof
|
|
52
|
-
* discovery accepts for `format
|
|
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
|
-
*
|
|
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
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
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.
|
|
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
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
144
|
-
*
|
|
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;
|