@aventara/prisma7-adapter 0.1.0-pilot.1 → 0.1.0-pilot.3
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 +33 -20
- 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 +4 -3
|
@@ -1,72 +1,9 @@
|
|
|
1
1
|
import { readdirSync, readFileSync, statSync } from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import ts from "typescript";
|
|
4
|
-
/**
|
|
5
|
-
* T-3, source **TYPE** — the reader over the generated client's 🟢 public types.
|
|
6
|
-
*
|
|
7
|
-
* # Rule one: the 🟢 files only
|
|
8
|
-
*
|
|
9
|
-
* The files whose banner reads *"🟢 You can import this file directly"* are the
|
|
10
|
-
* only input. At 7.10.0 that is **9 per generated client** — `browser.ts`,
|
|
11
|
-
* `client.ts`, `commonInputTypes.ts`, `enums.ts`, `models.ts` and one
|
|
12
|
-
* `models/<M>.ts` per model — against **3** marked *"🛑 Under no circumstances
|
|
13
|
-
* should you import this file directly! 🛑"*, all three under `internal/`. Across
|
|
14
|
-
* the two Phase 8 clients: 18 and 6, re-counted on 2026-09-27 rather than
|
|
15
|
-
* inherited.
|
|
16
|
-
*
|
|
17
|
-
* The 🛑 files are excluded **by path**, before anything is opened, because
|
|
18
|
-
* classifying them by their banner would require opening them. The compiler host
|
|
19
|
-
* below refuses a read under `internal/` outright instead of quietly skipping it,
|
|
20
|
-
* and every 🟢 file it opens is checked to carry the 🟢 banner.
|
|
21
|
-
*
|
|
22
|
-
* # Rule two: the written type arguments, never the instantiated reference
|
|
23
|
-
*
|
|
24
|
-
* Token-shaped facts come from the **written syntax** — a
|
|
25
|
-
* `TypeReferenceNode`'s `typeArguments` — resolved one node at a time with
|
|
26
|
-
* `getTypeFromTypeNode`.
|
|
27
|
-
*
|
|
28
|
-
* The shorthand "from the AST rather than from the checker" is
|
|
29
|
-
* self-contradictory, since `getTypeFromTypeNode` **is** a `ts.TypeChecker`
|
|
30
|
-
* method. What matters is *which* checker question is asked. On a string-literal
|
|
31
|
-
* type argument, `getTypeFromTypeNode` answers from that node's own syntax and
|
|
32
|
-
* does not depend on `@prisma/client/runtime/client` resolving. Asking for the
|
|
33
|
-
* type *at* the reference (`getTypeAtLocation` on `FieldRef<"M0", 'String'>`)
|
|
34
|
-
* silently answers with the uninstantiated form when the runtime is unresolvable
|
|
35
|
-
* — and `// @ts-nocheck`, which the generator writes into every file, means a
|
|
36
|
-
* program over a broken install reports **zero** diagnostics while doing it
|
|
37
|
-
* (§1.2 item 16). This reader asks the first question only.
|
|
38
|
-
*
|
|
39
|
-
* This program is deliberately built with `noResolve` and `noLib`, so the
|
|
40
|
-
* broken-install condition is not merely survived, it is **the normal case**:
|
|
41
|
-
* nothing outside the 🟢 files is ever resolved, and the reader still answers.
|
|
42
|
-
*
|
|
43
|
-
* # What this reader does not do
|
|
44
|
-
*
|
|
45
|
-
* It states no provider conditionality of its own. `filterOperands` carries each
|
|
46
|
-
* operator's operand **as written** precisely so no later module has to branch on
|
|
47
|
-
* `provider` to learn a fact the types already state (T-3.1 invariant 6).
|
|
48
|
-
*
|
|
49
|
-
* It also does not decide anything: `resources` is the existence gate's evidence,
|
|
50
|
-
* not the gate. A PSL-only entity is a generate-time error, and the generate step
|
|
51
|
-
* owns that error.
|
|
52
|
-
*
|
|
53
|
-
* # Rule three: a scope is a presence question, never a rule reproduced
|
|
54
|
-
*
|
|
55
|
-
* The bulk-returning projection ceiling and the flat-bulk write stage are read the
|
|
56
|
-
* same way everything else here is read — **is the member in the type?** —
|
|
57
|
-
* against `<M>Select{Create,Update}ManyAndReturn`, their `Include` counterparts and
|
|
58
|
-
* the two bulk write inputs. The *explanation* for which relations survive is
|
|
59
|
-
* foreign-key ownership rather than cardinality; reproducing that explanation as a
|
|
60
|
-
* rule would be a tabulated provider fact (D-802, §18.4) that goes wrong the first
|
|
61
|
-
* time Prisma admits a different set. See `PrismaRelationSurface.bulkSelect`.
|
|
62
|
-
*/
|
|
63
|
-
/** The banner that marks a file as public. */
|
|
64
4
|
const GREEN_BANNER = "You can import this file directly";
|
|
65
|
-
/** The banner that marks a file as private. Never expected to be read. */
|
|
66
5
|
const RED_BANNER = "Under no circumstances should you import this file directly";
|
|
67
|
-
/** The generated tree's private directory, excluded by path. */
|
|
68
6
|
const PRIVATE_DIRECTORY = "internal";
|
|
69
|
-
/** Edge-argument keys that other surface fields already own, so pagination is the residual. */
|
|
70
7
|
const NON_PAGINATION_EDGE_ARGUMENTS = new Set([
|
|
71
8
|
"select",
|
|
72
9
|
"omit",
|
|
@@ -77,14 +14,6 @@ const MANY_WRITE_OPERATION = /^(?:create|update|delete)Many(?:AndReturn)?$/;
|
|
|
77
14
|
export class PrismaTypesReaderError extends Error {
|
|
78
15
|
name = "PrismaTypesReaderError";
|
|
79
16
|
}
|
|
80
|
-
/**
|
|
81
|
-
* The reader's one checker question, exported because it is the distinction the
|
|
82
|
-
* whole reader rests on and therefore has to be testable on its own.
|
|
83
|
-
*
|
|
84
|
-
* Returns each written type argument's type as the checker renders it, so
|
|
85
|
-
* `FieldRef<"M0", 'String'>` answers `['"M0"', '"String"']` — including when
|
|
86
|
-
* `FieldRef` itself does not resolve.
|
|
87
|
-
*/
|
|
88
17
|
export function readWrittenTypeArguments(checker, reference) {
|
|
89
18
|
return (reference.typeArguments ?? []).map((argument) => checker.typeToString(checker.getTypeFromTypeNode(argument)));
|
|
90
19
|
}
|
|
@@ -98,9 +27,6 @@ export function readPrismaCapabilitySurface(clientDirectory) {
|
|
|
98
27
|
const host = createPublicOnlyHost(root, filesRead);
|
|
99
28
|
const program = ts.createProgram({
|
|
100
29
|
rootNames: publicFiles,
|
|
101
|
-
// `noResolve` and `noLib` are the point, not an optimisation: nothing
|
|
102
|
-
// outside the 🟢 files can be pulled in, so the reader's answers cannot
|
|
103
|
-
// depend on a resolvable `@prisma/client/runtime/client`.
|
|
104
30
|
options: {
|
|
105
31
|
noResolve: true,
|
|
106
32
|
noLib: true,
|
|
@@ -119,9 +45,6 @@ export function readPrismaCapabilitySurface(clientDirectory) {
|
|
|
119
45
|
filesRead: [...filesRead],
|
|
120
46
|
};
|
|
121
47
|
}
|
|
122
|
-
/* ------------------------------------------------------------------ *
|
|
123
|
-
* Input: the 🟢 files, and a host that refuses the 🛑 ones *
|
|
124
|
-
* ------------------------------------------------------------------ */
|
|
125
48
|
function listPublicFiles(root) {
|
|
126
49
|
return readdirSync(root, { recursive: true, withFileTypes: true })
|
|
127
50
|
.filter((entry) => entry.isFile() &&
|
|
@@ -137,8 +60,6 @@ function createPublicOnlyHost(root, filesRead) {
|
|
|
137
60
|
const readPublicFile = (fileName) => {
|
|
138
61
|
const resolved = path.resolve(fileName);
|
|
139
62
|
if (!resolved.startsWith(root + path.sep)) {
|
|
140
|
-
// Nothing outside the generated tree is served, so a stray specifier
|
|
141
|
-
// fails loudly rather than widening the input.
|
|
142
63
|
return undefined;
|
|
143
64
|
}
|
|
144
65
|
if (isPrivatePath(root, resolved)) {
|
|
@@ -164,12 +85,6 @@ function createPublicOnlyHost(root, filesRead) {
|
|
|
164
85
|
getCanonicalFileName: (fileName) => fileName,
|
|
165
86
|
useCaseSensitiveFileNames: () => true,
|
|
166
87
|
getNewLine: () => "\n",
|
|
167
|
-
// Existence is the file system's answer, and only for what this host would
|
|
168
|
-
// serve: a public `.ts` file under the root. TypeScript 6 probes
|
|
169
|
-
// `package.json` files under the root even with `noResolve` (plan B4); a
|
|
170
|
-
// host that answered `true` for any path there sent it to `readFile`, which
|
|
171
|
-
// threw `ENOENT`. TypeScript 5.9 never asked, so the old answer was never
|
|
172
|
-
// tested.
|
|
173
88
|
fileExists: (fileName) => {
|
|
174
89
|
const resolved = path.resolve(fileName);
|
|
175
90
|
return (resolved.startsWith(root + path.sep) &&
|
|
@@ -196,30 +111,10 @@ function indexDeclarations(program, publicFiles) {
|
|
|
196
111
|
}
|
|
197
112
|
return index;
|
|
198
113
|
}
|
|
199
|
-
/** The two bulk-returning write calls, in the spelling the generated type names use. */
|
|
200
114
|
const BULK_RETURNING_WRITES = ["CreateManyAndReturn", "UpdateManyAndReturn"];
|
|
201
|
-
/**
|
|
202
|
-
* Whether every one of the declared member sets lists `member`.
|
|
203
|
-
*
|
|
204
|
-
* **Zero sets answer `false`.** `Array.prototype.every` is vacuously true on an
|
|
205
|
-
* empty array, and taking that answer would advertise a scope on a client that
|
|
206
|
-
* declares no bulk-returning projection type at all — over-advertisement by
|
|
207
|
-
* arithmetic, which is C-855's failure mode arriving through a language default.
|
|
208
|
-
*/
|
|
209
115
|
function admittedByEvery(sets, member) {
|
|
210
116
|
return sets.length > 0 && sets.every((names) => names.has(member));
|
|
211
117
|
}
|
|
212
|
-
/**
|
|
213
|
-
* The member names of a projection type, read off the **written** object literal.
|
|
214
|
-
*
|
|
215
|
-
* Two shapes carry one meaning at 7.10.0 and both have to be read: `<M>Select…` is
|
|
216
|
-
* written `GetSelect<{ … }, ExtArgs["result"]["m"]>`, so its members live in the
|
|
217
|
-
* first written type argument, while `<M>Include…` is written as a plain object
|
|
218
|
-
* type. `null` means the client declares no such type — the honest answer for a
|
|
219
|
-
* generator that emits no `*AndReturn` projection, and not the same as a type that
|
|
220
|
-
* is declared and empty (`UserIncludeCreateManyAndReturn` is literally `{}` in
|
|
221
|
-
* this repository, which is a measured `false` per edge rather than an absence).
|
|
222
|
-
*/
|
|
223
118
|
function projectionMembers(index, name) {
|
|
224
119
|
const declaration = index.get(name);
|
|
225
120
|
if (declaration === undefined) {
|
|
@@ -251,7 +146,6 @@ function readBulkSurface(index, model) {
|
|
|
251
146
|
]),
|
|
252
147
|
};
|
|
253
148
|
}
|
|
254
|
-
/** The members of a named declaration, following Prisma's one `…Base` indirection. */
|
|
255
149
|
function membersOf(index, name) {
|
|
256
150
|
const declaration = index.get(name);
|
|
257
151
|
if (declaration === undefined) {
|
|
@@ -263,8 +157,6 @@ function membersOf(index, name) {
|
|
|
263
157
|
if (ts.isTypeLiteralNode(declaration.type)) {
|
|
264
158
|
return declaration.type.members.filter(ts.isPropertySignature);
|
|
265
159
|
}
|
|
266
|
-
// `JsonFilter` is a conditional over `JsonFilterBase`, which is where the
|
|
267
|
-
// operators are actually written. One documented indirection, not a search.
|
|
268
160
|
return membersOf(index, `${name}Base`);
|
|
269
161
|
}
|
|
270
162
|
function memberName(member) {
|
|
@@ -275,13 +167,11 @@ function memberName(member) {
|
|
|
275
167
|
function memberNames(members) {
|
|
276
168
|
return members.map(memberName);
|
|
277
169
|
}
|
|
278
|
-
/** The rightmost identifier of a type reference's name: `Prisma.StringFilter` → `StringFilter`. */
|
|
279
170
|
function referencedName(reference) {
|
|
280
171
|
return ts.isQualifiedName(reference.typeName)
|
|
281
172
|
? reference.typeName.right.text
|
|
282
173
|
: reference.typeName.text;
|
|
283
174
|
}
|
|
284
|
-
/** The first type reference, at any depth, whose name satisfies `accept`. */
|
|
285
175
|
function findReference(node, accept) {
|
|
286
176
|
if (node === undefined) {
|
|
287
177
|
return null;
|
|
@@ -311,9 +201,6 @@ function keysOfReferenced(index, node, accept) {
|
|
|
311
201
|
}
|
|
312
202
|
return memberNames(members);
|
|
313
203
|
}
|
|
314
|
-
/* ------------------------------------------------------------------ *
|
|
315
|
-
* Enums *
|
|
316
|
-
* ------------------------------------------------------------------ */
|
|
317
204
|
function readEnums(program, root) {
|
|
318
205
|
const source = program.getSourceFile(path.join(root, "enums.ts"));
|
|
319
206
|
if (source === undefined) {
|
|
@@ -332,8 +219,6 @@ function readEnums(program, root) {
|
|
|
332
219
|
!ts.isIdentifier(declaration.name)) {
|
|
333
220
|
continue;
|
|
334
221
|
}
|
|
335
|
-
// Property order is the member order. `as const` is what makes it an
|
|
336
|
-
// enum projection rather than a mutable object.
|
|
337
222
|
enums[declaration.name.text] = initializer.expression.properties
|
|
338
223
|
.filter(ts.isPropertyAssignment)
|
|
339
224
|
.map((property) => ts.isIdentifier(property.name) || ts.isStringLiteral(property.name)
|
|
@@ -343,9 +228,6 @@ function readEnums(program, root) {
|
|
|
343
228
|
}
|
|
344
229
|
return enums;
|
|
345
230
|
}
|
|
346
|
-
/* ------------------------------------------------------------------ *
|
|
347
|
-
* Resources *
|
|
348
|
-
* ------------------------------------------------------------------ */
|
|
349
231
|
function readResources(checker, index) {
|
|
350
232
|
const resources = {};
|
|
351
233
|
for (const name of [...index.keys()].sort()) {
|
|
@@ -367,14 +249,8 @@ function readResource(checker, index, model) {
|
|
|
367
249
|
throw new PrismaTypesReaderError(`$${model}Payload's own name literal is ${declaredName}`);
|
|
368
250
|
}
|
|
369
251
|
const where = membersOf(index, `${model}WhereInput`) ?? [];
|
|
370
|
-
// The CHECKED create/update inputs, because the unchecked halves carry no
|
|
371
|
-
// relation edge at all — the foreign-key scalar stands in for it there. Both
|
|
372
|
-
// stages are read, separately: see `PrismaRelationSurface.createMutations`.
|
|
373
252
|
const create = membersOf(index, `${model}CreateInput`) ?? [];
|
|
374
253
|
const update = membersOf(index, `${model}UpdateInput`) ?? [];
|
|
375
|
-
// The UNCHECKED inputs, because they are what the delegate accepts: `data` is
|
|
376
|
-
// `XOR<<M>UpdateInput, <M>UncheckedUpdateInput>`, and only the unchecked half
|
|
377
|
-
// carries the foreign-key scalars and the generated identifiers.
|
|
378
254
|
const uncheckedCreate = membersOf(index, `${model}UncheckedCreateInput`) ?? [];
|
|
379
255
|
const uncheckedUpdate = membersOf(index, `${model}UncheckedUpdateInput`) ?? [];
|
|
380
256
|
const orderBy = membersOf(index, `${model}OrderByWithRelationInput`) ?? [];
|
|
@@ -390,7 +266,6 @@ function readResource(checker, index, model) {
|
|
|
390
266
|
manyWriteArguments: readManyWriteArguments(index, model, operations),
|
|
391
267
|
};
|
|
392
268
|
}
|
|
393
|
-
/** The payload's own `name: "M"` literal — the only authority on a relation's target. */
|
|
394
269
|
function payloadName(checker, payload) {
|
|
395
270
|
const member = payload.find((m) => memberName(m) === "name");
|
|
396
271
|
if (member?.type === undefined) {
|
|
@@ -401,8 +276,6 @@ function payloadName(checker, payload) {
|
|
|
401
276
|
function readScalarFields(checker, index, model, payload, where, uncheckedCreate, uncheckedUpdate, orderBy) {
|
|
402
277
|
const tokens = readFieldRefTokens(checker, index, model);
|
|
403
278
|
const declared = payload.find((m) => memberName(m) === "scalars");
|
|
404
|
-
// `scalars` is written as `GetPayloadResult<{ … }, …>`; the first written type
|
|
405
|
-
// argument is the object, and that is read, not the instantiated result.
|
|
406
279
|
const written = declared?.type;
|
|
407
280
|
const literal = written !== undefined && ts.isTypeReferenceNode(written)
|
|
408
281
|
? written.typeArguments?.[0]
|
|
@@ -430,14 +303,9 @@ function readScalarFields(checker, index, model, payload, where, uncheckedCreate
|
|
|
430
303
|
filters: memberNames(filterMembers),
|
|
431
304
|
filterOperands: Object.fromEntries(filterMembers.map((member) => [
|
|
432
305
|
memberName(member),
|
|
433
|
-
// As WRITTEN. Two engines carry `path` with different operands, and
|
|
434
|
-
// a name set cannot express that (T-3.1 invariant 6).
|
|
435
306
|
member.type?.getText() ?? "",
|
|
436
307
|
])),
|
|
437
308
|
createOperations: readMutationOperations(index, model, "Create", name, uncheckedCreate.get(name)),
|
|
438
|
-
// The question mark, read from the member the line above read its
|
|
439
|
-
// directives from — one member, two facts, so they cannot disagree about
|
|
440
|
-
// whether the column is creatable at all.
|
|
441
309
|
createOptional: uncheckedCreate.get(name)?.questionToken !== undefined,
|
|
442
310
|
updateOperations: readMutationOperations(index, model, "Update", name, uncheckedUpdate.get(name)),
|
|
443
311
|
orderable: order !== undefined,
|
|
@@ -446,23 +314,6 @@ function readScalarFields(checker, index, model, payload, where, uncheckedCreate
|
|
|
446
314
|
}
|
|
447
315
|
return fields;
|
|
448
316
|
}
|
|
449
|
-
/**
|
|
450
|
-
* One mutation input entry, read as the keys of the `…Input` it references.
|
|
451
|
-
*
|
|
452
|
-
* Two reference spellings carry operations and no others do:
|
|
453
|
-
* `<Kind>FieldUpdateOperationsInput` (`set`, and the four arithmetic directives on
|
|
454
|
-
* the numeric kinds) and `<M><Stage><field>Input` (a scalar list's own `set` and
|
|
455
|
-
* `push`). Everything else is a plain value — `Json`'s
|
|
456
|
-
* `JsonNullValueInput | InputJsonValue`, and every create-stage scalar — and
|
|
457
|
-
* answers `[]`.
|
|
458
|
-
*
|
|
459
|
-
* `undefined` in, `null` out: the client exposes no entry for this column at this
|
|
460
|
-
* stage, which is the ONLY evidence of a column that cannot be written. Matching
|
|
461
|
-
* the two spellings by name rather than taking the first `…Input` reference is
|
|
462
|
-
* load-bearing: `JsonNullValueInput` is an `…Input` whose members are null
|
|
463
|
-
* sentinels, and reading those as operations would advertise `DbNull` as a
|
|
464
|
-
* mutation directive.
|
|
465
|
-
*/
|
|
466
317
|
function readMutationOperations(index, model, stage, field, member) {
|
|
467
318
|
if (member === undefined) {
|
|
468
319
|
return null;
|
|
@@ -478,7 +329,6 @@ function readMutationOperations(index, model, stage, field, member) {
|
|
|
478
329
|
}
|
|
479
330
|
return memberNames(members);
|
|
480
331
|
}
|
|
481
|
-
/** `<M>FieldRefs` → field name to scalar token, read from the written type arguments. */
|
|
482
332
|
function readFieldRefTokens(checker, index, model) {
|
|
483
333
|
const members = membersOf(index, `${model}FieldRefs`);
|
|
484
334
|
if (members === null) {
|
|
@@ -523,42 +373,23 @@ function readRelationFields(checker, index, payload, where, create, update, incl
|
|
|
523
373
|
if (targetMembers === null) {
|
|
524
374
|
throw new PrismaTypesReaderError(`${referencedName(targetPayload)} is declared nowhere in the 🟢 types`);
|
|
525
375
|
}
|
|
526
|
-
// `<M>Include`'s entry for this edge names the edge's own argument type, and
|
|
527
|
-
// there are TWO spellings at 7.10.0 — measured 2026-10-02, because matching
|
|
528
|
-
// only the `$` one silently gave every REQUIRED to-one edge an empty argument
|
|
529
|
-
// list: a nullable to-one and a to-many name `<M>$<edge>Args`, while a
|
|
530
|
-
// required to-one names the target's `<T>DefaultArgs`. The difference is real
|
|
531
|
-
// and semantic — `<T>DefaultArgs` carries no `where`, so a required to-one
|
|
532
|
-
// genuinely admits no nested filtering of the returned edge — but
|
|
533
|
-
// `select`/`omit`/`include` are on both, so both have to be read.
|
|
534
376
|
const edge = findReference(include.get(name)?.type, (n) => n.endsWith("Args"));
|
|
535
377
|
const edgeArguments = edge === null
|
|
536
378
|
? []
|
|
537
379
|
: memberNames(membersOf(index, referencedName(edge)) ?? []);
|
|
538
380
|
fields[name] = {
|
|
539
|
-
// The TARGET payload's own `name` literal, not the alias's spelling.
|
|
540
381
|
target: payloadName(checker, targetMembers),
|
|
541
382
|
many,
|
|
542
383
|
nullable,
|
|
543
384
|
filters: keysOfReferenced(index, where.get(name)?.type, (n) => n.endsWith("RelationFilter")),
|
|
544
|
-
// The two stages name their nested inputs differently — the create-stage
|
|
545
|
-
// one is `<T>CreateNested{One,Many}Without<M>Input`, which does NOT end in
|
|
546
|
-
// `NestedInput` — and that is why each predicate is written out rather
|
|
547
|
-
// than one being reused: the stage is identified by the input the client
|
|
548
|
-
// itself references at that stage, not by a tabulated key set.
|
|
549
385
|
createMutations: keysOfReferenced(index, create.get(name)?.type, (n) => CREATE_NESTED_INPUT.test(n)),
|
|
386
|
+
createRequired: create.get(name) !== undefined &&
|
|
387
|
+
create.get(name)?.questionToken === undefined,
|
|
550
388
|
updateMutations: keysOfReferenced(index, update.get(name)?.type, (n) => n.endsWith("NestedInput")),
|
|
551
389
|
edgeArguments,
|
|
552
|
-
// Pagination is the residual of the edge's own args: what neither
|
|
553
|
-
// projection nor predicate already owns. A to-one edge leaves nothing.
|
|
554
390
|
pagination: edgeArguments.filter((argument) => !NON_PAGINATION_EDGE_ARGUMENTS.has(argument)),
|
|
555
391
|
orderable: orderBy.has(name),
|
|
556
392
|
reducers: counted.has(name) ? ["_count"] : [],
|
|
557
|
-
// PRESENCE in the four `*AndReturn` projection types and the two bulk
|
|
558
|
-
// write inputs. No foreign key is looked at and no cardinality is
|
|
559
|
-
// consulted: `many` sits three lines up and is deliberately not read here
|
|
560
|
-
// — a to-one that does not own its FK is absent from these types, and that
|
|
561
|
-
// is a fact about the types, not a rule this reader reproduces.
|
|
562
393
|
bulkSelect: admittedByEvery(bulk.select, name),
|
|
563
394
|
bulkInclude: admittedByEvery(bulk.include, name),
|
|
564
395
|
bulkReducers: admittedByEvery([...bulk.select, ...bulk.include], "_count"),
|
|
@@ -568,11 +399,6 @@ function readRelationFields(checker, index, payload, where, create, update, incl
|
|
|
568
399
|
}
|
|
569
400
|
return fields;
|
|
570
401
|
}
|
|
571
|
-
/**
|
|
572
|
-
* The create-stage nested-write input's name, as 7.10.0 writes it:
|
|
573
|
-
* `<T>CreateNested{One,Many}Without<M>Input`. The update-stage spellings all end
|
|
574
|
-
* in `NestedInput`, so the two never collide.
|
|
575
|
-
*/
|
|
576
402
|
const CREATE_NESTED_INPUT = /CreateNested(?:One|Many)Without.*Input$/;
|
|
577
403
|
function readUniqueKeys(checker, index, model) {
|
|
578
404
|
const declaration = index.get(`${model}WhereUniqueInput`);
|
|
@@ -587,7 +413,6 @@ function readUniqueKeys(checker, index, model) {
|
|
|
587
413
|
const nodes = ts.isUnionTypeNode(keys) ? keys.types : [keys];
|
|
588
414
|
return nodes.map((node) => unquote(checker.typeToString(checker.getTypeFromTypeNode(node))));
|
|
589
415
|
}
|
|
590
|
-
/** `<M>Delegate`'s own methods, in declaration order. */
|
|
591
416
|
function readOperations(index, model) {
|
|
592
417
|
const declaration = index.get(`${model}Delegate`);
|
|
593
418
|
if (declaration === undefined || !ts.isInterfaceDeclaration(declaration)) {
|
|
@@ -1,16 +1,7 @@
|
|
|
1
1
|
import type { AdapterLifecycleTrait, BuiltInScalar, PaginationCapability, RelationFilterCapability, RelationMutationDirective, ScalarFilterOperator, ScalarFormat, ScalarMutationDirective } from "@aventara/core";
|
|
2
2
|
/**
|
|
3
|
-
* T-3.1 — the vocabulary dictionary: where PSL, the 🟢 generated types and the
|
|
4
|
-
* observed runtime meet Aventara's own words.
|
|
5
|
-
*
|
|
6
3
|
* # It is data, not conditionals
|
|
7
4
|
*
|
|
8
|
-
* Every table below is a value a reader can hold beside T-3.1's table and check
|
|
9
|
-
* row by row. Nothing here branches on a provider, a field name or a schema: a
|
|
10
|
-
* module that learns a fact by asking `if (provider === "sqlite")` is tabulating
|
|
11
|
-
* what the sources already state, which is the cover-up C-854 forbids
|
|
12
|
-
* (T-3.1 invariant 6).
|
|
13
|
-
*
|
|
14
5
|
* # Every entry names its source class (invariant 1)
|
|
15
6
|
*
|
|
16
7
|
* `VOCABULARY` carries one row per Aventara fact with its source code — `PSL`,
|
|
@@ -22,8 +13,8 @@ import type { AdapterLifecycleTrait, BuiltInScalar, PaginationCapability, Relati
|
|
|
22
13
|
*
|
|
23
14
|
* `PRISMA_DEFAULT_TABLE` is looked up with the raw text the PSL reader carried
|
|
24
15
|
* across unchanged. `dbgenerated("gen_random_uuid()")` is a **key**, not an
|
|
25
|
-
* expression: the day this module evaluates one, the reader behind it has become
|
|
26
|
-
*
|
|
16
|
+
* expression: the day this module evaluates one, the reader behind it has become a
|
|
17
|
+
* parser and needs a different decision. An unmatched form falls back to
|
|
27
18
|
* `PRISMA_UNMATCHED_DEFAULT_TRAITS` **plus** a recorded unknown that fails the
|
|
28
19
|
* generate step — never an inferred trait.
|
|
29
20
|
*
|
|
@@ -45,25 +36,15 @@ import type { AdapterLifecycleTrait, BuiltInScalar, PaginationCapability, Relati
|
|
|
45
36
|
*/
|
|
46
37
|
export type VocabularySource = "PSL" | "TYPE" | "RUN" | "DRIVER" | "CFG";
|
|
47
38
|
export type VocabularyEntry = {
|
|
48
|
-
/** The Aventara fact, spelled as T-3.1's left column spells it. */
|
|
49
39
|
readonly fact: string;
|
|
50
40
|
/** Non-empty by construction: invariant 1 is enforced by the type, not by a comment. */
|
|
51
41
|
readonly sources: readonly [VocabularySource, ...VocabularySource[]];
|
|
52
42
|
readonly rule: string;
|
|
53
43
|
};
|
|
54
44
|
/**
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
* one that is wrong.** T-3.1 says `format?` is `CFG` — "PSL's `@db.*` is a hint
|
|
59
|
-
* only … policy, not discovery". Spec §6.1 says the opposite in as many words:
|
|
60
|
-
* UUID "is a string scalar plus passive format metadata **when the adapter can
|
|
61
|
-
* prove the format**", §18.3's discovery mapping reads "scalar type → stable
|
|
62
|
-
* framework scalar + optional format", C-809 restates both, T-5 restates them
|
|
63
|
-
* again, and `AdapterScalarField.format?` exists **[CORE]** — a member with no
|
|
64
|
-
* producer if discovery never emits one. So the source is `PSL` **and** `CFG`:
|
|
65
|
-
* discovery emits what the provider's own column type proves, configuration owns
|
|
66
|
-
* everything else. `scalar.mapper.ts`'s header carries the full argument.
|
|
45
|
+
* So the source is `PSL` **and** `CFG`: discovery emits what the provider's own
|
|
46
|
+
* column type proves, configuration owns everything else. `scalar.mapper.ts`'s
|
|
47
|
+
* header carries the full argument.
|
|
67
48
|
*/
|
|
68
49
|
export declare const VOCABULARY: readonly VocabularyEntry[];
|
|
69
50
|
/**
|
|
@@ -71,18 +52,20 @@ export declare const VOCABULARY: readonly VocabularyEntry[];
|
|
|
71
52
|
* refusal is the dictionary's own answer: a construct it has no word for.
|
|
72
53
|
*/
|
|
73
54
|
export type PrismaDiscoveryDiagnosticCode =
|
|
74
|
-
/** A Prisma type name in neither PRISMA_SCALAR_TABLE nor `enums.ts
|
|
55
|
+
/** A Prisma type name in neither PRISMA_SCALAR_TABLE nor `enums.ts`. */
|
|
75
56
|
"unmapped-prisma-type"
|
|
76
|
-
/**
|
|
57
|
+
/**
|
|
58
|
+
* PSL declares it, the 🟢 types do not expose it: omitted, with the reason said
|
|
59
|
+
* out loud.
|
|
60
|
+
*/
|
|
77
61
|
| "not-exposed"
|
|
78
|
-
/** PSL and `enums.ts` disagree about an enum's members or their order
|
|
62
|
+
/** PSL and `enums.ts` disagree about an enum's members or their order. */
|
|
79
63
|
| "enum-diverged";
|
|
80
64
|
export type PrismaDiscoveryDiagnostic = {
|
|
81
65
|
readonly code: PrismaDiscoveryDiagnosticCode;
|
|
82
66
|
/** Written for the engineer who has to fix the schema, naming the entity it is about. */
|
|
83
67
|
readonly message: string;
|
|
84
68
|
};
|
|
85
|
-
/** T-5 — a proven scalar identity, plus a format only where something proves it. */
|
|
86
69
|
export type PrismaScalarMapping = {
|
|
87
70
|
readonly scalar: BuiltInScalar;
|
|
88
71
|
readonly format?: ScalarFormat;
|
|
@@ -90,7 +73,7 @@ export type PrismaScalarMapping = {
|
|
|
90
73
|
export type PrismaScalarTable = Readonly<Record<string, PrismaScalarMapping>>;
|
|
91
74
|
/**
|
|
92
75
|
* Total and 1:1 over `BUILT_IN_SCALARS` **[CORE]**. There is no default arm: a
|
|
93
|
-
* Prisma type name absent from this table is a diagnostic, not a guess
|
|
76
|
+
* Prisma type name absent from this table is a diagnostic, not a guess.
|
|
94
77
|
*
|
|
95
78
|
* **No row carries a `format`**, and that is the point: a format is a property of
|
|
96
79
|
* a *column*, not of a Prisma *type name*. `String` alone proves nothing, so the
|
|
@@ -109,21 +92,18 @@ export declare const PRISMA_SCALAR_TABLE: PrismaScalarTable;
|
|
|
109
92
|
* `runtime/scalar-runtime.ts`]** — so a row that is merely probable would have
|
|
110
93
|
* Aventara refuse writes the database accepts.
|
|
111
94
|
*
|
|
112
|
-
* `@db.Uuid` clears that bar: PostgreSQL's `uuid` column rejects
|
|
113
|
-
*
|
|
114
|
-
*
|
|
95
|
+
* `@db.Uuid` clears that bar: PostgreSQL's `uuid` column rejects `'not-a-uuid'`
|
|
96
|
+
* (`ERROR: invalid input syntax for type uuid`) where a `text` column takes it
|
|
97
|
+
* **[RUN8 — 2026-09-28, `aventara-postgres`, postgres:18]**.
|
|
115
98
|
*
|
|
116
|
-
*
|
|
117
|
-
* narrowed: on a `String` column with no `@db.Uuid` the column is `text`, only
|
|
118
|
-
* *generated* values are UUIDs, and a client may legally supply any string. That
|
|
119
|
-
* intent belongs in `FrameworkScalarFieldConfig.format` **[CORE]**, which the
|
|
99
|
+
* That intent belongs in `FrameworkScalarFieldConfig.format` **[CORE]**, which the
|
|
120
100
|
* Contract compiler already applies over the adapter's value.
|
|
121
101
|
*
|
|
122
102
|
* `@db.Decimal(10, 2)` and `@db.VarChar(255)` are absent because they prove no
|
|
123
103
|
* *format*; they carry precision and width, which Aventara has no word for.
|
|
124
104
|
*/
|
|
125
105
|
export declare const PRISMA_NATIVE_FORMATS: Readonly<Record<string, ScalarFormat>>;
|
|
126
|
-
/** Whether a row was exercised against 7.10.0 or is carried forward unproven
|
|
106
|
+
/** Whether a row was exercised against 7.10.0 or is carried forward unproven. */
|
|
127
107
|
export type PrismaEvidence = "RUN8" | "UNVERIFIED";
|
|
128
108
|
export type PrismaDefaultRow = {
|
|
129
109
|
/**
|
|
@@ -140,19 +120,11 @@ export type PrismaDefaultRow = {
|
|
|
140
120
|
readonly evidence: PrismaEvidence;
|
|
141
121
|
};
|
|
142
122
|
/**
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
* **`traits` is the whole trait set, where T-3.1's table lists only the trait the
|
|
146
|
-
* *argument* adds.** The two are consistent, not contradictory: `DEFAULTED` comes
|
|
147
|
-
* from `@default`'s **presence** (C-808: "`@default` → `DEFAULTED` and, when
|
|
148
|
-
* generator-owned, `GENERATED_ON_CREATE`"), and C-811's acceptance criteria spell
|
|
149
|
-
* the full sets out — `@default(autoincrement())` → `["DEFAULTED",
|
|
150
|
-
* "GENERATED_ON_CREATE"]`, `@default("x")` → `["DEFAULTED"]`. This table states
|
|
151
|
-
* the answer rather than half of it, so no consumer has to remember to add the
|
|
152
|
-
* other half.
|
|
123
|
+
* This table states the answer rather than half of it, so no consumer has to
|
|
124
|
+
* remember to add the other half.
|
|
153
125
|
*
|
|
154
|
-
* The lookup that walks this table lives with the lifecycle projection
|
|
155
|
-
*
|
|
126
|
+
* The lookup that walks this table lives with the lifecycle projection, where it
|
|
127
|
+
* can be driven red; this pass owns the data only.
|
|
156
128
|
*/
|
|
157
129
|
export declare const PRISMA_DEFAULT_TABLE: readonly PrismaDefaultRow[];
|
|
158
130
|
/**
|
|
@@ -167,22 +139,17 @@ export declare const PRISMA_UNMATCHED_DEFAULT_TRAITS: readonly AdapterLifecycleT
|
|
|
167
139
|
* The dictionary's other half: the point at which Prisma's spelling stops and
|
|
168
140
|
* Aventara's begins.
|
|
169
141
|
*
|
|
170
|
-
* **One untyped `PRISMA_RENAMES` became six typed tables
|
|
171
|
-
*
|
|
172
|
-
*
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
*
|
|
176
|
-
* splitting it.
|
|
142
|
+
* **One untyped `PRISMA_RENAMES` became six typed tables.** The single
|
|
143
|
+
* `Record<string, string>` could not make a mistake a compile error: a rename to a
|
|
144
|
+
* word core does not have, or a Prisma key nobody decided about, both typechecked.
|
|
145
|
+
* Each table below is keyed on the Prisma spelling and valued in the ONE Aventara
|
|
146
|
+
* vocabulary that spelling can land in, so `"arrayContains"` misspelt fails to
|
|
147
|
+
* compile. The table had no consumer, so nothing was broken by splitting it.
|
|
177
148
|
*
|
|
178
149
|
* `null` is a value, not an omission: it means **recognised, and Aventara has no
|
|
179
150
|
* word for it** — the nested bulk writes, `distinct`, Prisma's `set` assignment.
|
|
180
|
-
* A key absent from a table is a different thing entirely, and the deriver that
|
|
181
|
-
* reads these refuses rather than dropping it silently, because a silently dropped
|
|
182
|
-
* capability key is how C-855's failure mode begins.
|
|
183
151
|
*
|
|
184
|
-
*
|
|
185
|
-
* — is still Task 9's. This is the vocabulary half only.
|
|
152
|
+
* This is the vocabulary half only.
|
|
186
153
|
*/
|
|
187
154
|
/**
|
|
188
155
|
* `<Kind>Filter` / `<Kind>NullableFilter` / `Json[Nullable]Filter` keys.
|
|
@@ -195,11 +162,9 @@ export declare const PRISMA_FILTER_OPERATORS: Readonly<Record<string, ScalarFilt
|
|
|
195
162
|
/**
|
|
196
163
|
* `[Nullable]ScalarRelationFilter` and `ListRelationFilter` keys.
|
|
197
164
|
*
|
|
198
|
-
* `
|
|
199
|
-
*
|
|
200
|
-
*
|
|
201
|
-
* own `where` argument and off the edge's nullability — so they are absent here by
|
|
202
|
-
* construction rather than by omission.
|
|
165
|
+
* `nested` and `null` are **not** keys of any filter input — they are read off the
|
|
166
|
+
* edge's own `where` argument and off the edge's nullability — so they are absent
|
|
167
|
+
* here by construction rather than by omission.
|
|
203
168
|
*/
|
|
204
169
|
export declare const PRISMA_RELATION_FILTERS: Readonly<Record<string, RelationFilterCapability>>;
|
|
205
170
|
/**
|
|
@@ -207,9 +172,7 @@ export declare const PRISMA_RELATION_FILTERS: Readonly<Record<string, RelationFi
|
|
|
207
172
|
*
|
|
208
173
|
* `set` is `null` because plain assignment is not a directive in Aventara: the
|
|
209
174
|
* value is written directly, and `ScalarMutationDirective` has no `$set`
|
|
210
|
-
* **[CORE]**.
|
|
211
|
-
* Mongo's, and a key the dictionary recognises and never advertises is better than
|
|
212
|
-
* one that makes the deriver throw the day a third provider is added.
|
|
175
|
+
* **[CORE]**.
|
|
213
176
|
*/
|
|
214
177
|
export declare const PRISMA_SCALAR_DIRECTIVES: Readonly<Record<string, ScalarMutationDirective | null>>;
|
|
215
178
|
/**
|
|
@@ -243,15 +206,13 @@ export type ObservedValueShape = {
|
|
|
243
206
|
readonly evidence: PrismaEvidence;
|
|
244
207
|
};
|
|
245
208
|
/**
|
|
246
|
-
*
|
|
247
|
-
*
|
|
248
|
-
*
|
|
249
|
-
* which is a narrower claim than "not driver-dependent", and the narrower one is
|
|
250
|
-
* what was measured.
|
|
209
|
+
* Identical through both driver adapters, so the representation is not
|
|
210
|
+
* driver-dependent *between these two engines* — which is a narrower claim than
|
|
211
|
+
* "not driver-dependent", and the narrower one is what was measured.
|
|
251
212
|
*
|
|
252
213
|
* A row is `RUN8` only where a read-back value was actually asserted. `String`,
|
|
253
214
|
* `Boolean`, `Int` and `Float` were written into a row and never read back under
|
|
254
|
-
* assertion, so they stay `[UNVERIFIED]
|
|
215
|
+
* assertion, so they stay `[UNVERIFIED]`: a plausible value shape is not an
|
|
255
216
|
* observed one, and this table exists precisely so that nobody has to guess which
|
|
256
217
|
* is which.
|
|
257
218
|
*/
|