@prisma-next/sql-contract-psl 0.13.0-dev.9 → 0.14.0-dev.1
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/dist/index.d.mts +3 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{interpreter-B_KtZusL.mjs → interpreter-B0BsCLKT.mjs} +110 -96
- package/dist/interpreter-B0BsCLKT.mjs.map +1 -0
- package/dist/provider.d.mts +1 -1
- package/dist/provider.mjs +5 -3
- package/dist/provider.mjs.map +1 -1
- package/package.json +12 -12
- package/src/interpreter.ts +91 -130
- package/src/provider.ts +2 -0
- package/src/psl-column-resolution.ts +1 -1
- package/src/psl-field-resolution.ts +90 -14
- package/dist/interpreter-B_KtZusL.mjs.map +0 -1
|
@@ -1,14 +1,21 @@
|
|
|
1
1
|
import type { ContractSourceDiagnostic } from '@prisma-next/config/config-types';
|
|
2
|
-
import type {
|
|
2
|
+
import type {
|
|
3
|
+
ColumnDefault,
|
|
4
|
+
ColumnDefaultLiteralInputValue,
|
|
5
|
+
ExecutionMutationDefaultPhases,
|
|
6
|
+
} from '@prisma-next/contract/types';
|
|
3
7
|
import type { AuthoringContributions } from '@prisma-next/framework-components/authoring';
|
|
4
8
|
import type {
|
|
5
9
|
ControlMutationDefaultRegistry,
|
|
6
10
|
MutationDefaultGeneratorDescriptor,
|
|
7
11
|
} from '@prisma-next/framework-components/control';
|
|
8
12
|
import type { PslAttribute, PslField, PslModel } from '@prisma-next/psl-parser';
|
|
13
|
+
import type { EnumTypeHandle } from '@prisma-next/sql-contract-ts/contract-builder';
|
|
14
|
+
import { blindCast } from '@prisma-next/utils/casts';
|
|
9
15
|
import { ifDefined } from '@prisma-next/utils/defined';
|
|
10
16
|
import {
|
|
11
17
|
getAttribute,
|
|
18
|
+
getPositionalArgumentEntry,
|
|
12
19
|
lowerFirst,
|
|
13
20
|
parseConstraintMapArgument,
|
|
14
21
|
parseMapName,
|
|
@@ -21,6 +28,61 @@ import {
|
|
|
21
28
|
resolveFieldTypeDescriptor,
|
|
22
29
|
} from './psl-column-resolution';
|
|
23
30
|
|
|
31
|
+
type LoweredFieldDefault = {
|
|
32
|
+
readonly defaultValue?: ColumnDefault;
|
|
33
|
+
readonly executionDefaults?: ExecutionMutationDefaultPhases;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
function lowerEnumDefaultForField(input: {
|
|
37
|
+
readonly modelName: string;
|
|
38
|
+
readonly fieldName: string;
|
|
39
|
+
readonly defaultAttribute: PslAttribute;
|
|
40
|
+
readonly enumHandle: EnumTypeHandle;
|
|
41
|
+
readonly sourceId: string;
|
|
42
|
+
readonly diagnostics: ContractSourceDiagnostic[];
|
|
43
|
+
}): LoweredFieldDefault {
|
|
44
|
+
const expressionEntry = getPositionalArgumentEntry(input.defaultAttribute);
|
|
45
|
+
if (!expressionEntry) {
|
|
46
|
+
return {};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const raw = expressionEntry.value.trim();
|
|
50
|
+
const isQuotedString = /^(['"]).*\1$/.test(raw);
|
|
51
|
+
const isFunctionCall = raw.includes('(') && raw.endsWith(')');
|
|
52
|
+
|
|
53
|
+
if (isQuotedString || isFunctionCall) {
|
|
54
|
+
input.diagnostics.push({
|
|
55
|
+
code: 'PSL_ENUM_DEFAULT_MUST_BE_MEMBER_NAME',
|
|
56
|
+
message: `Field "${input.modelName}.${input.fieldName}" @default on an enum field must name a member (e.g. @default(Low)), not a raw value or function.`,
|
|
57
|
+
sourceId: input.sourceId,
|
|
58
|
+
span: input.defaultAttribute.span,
|
|
59
|
+
});
|
|
60
|
+
return {};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const match = input.enumHandle.enumMembers.find((m) => m.name === raw);
|
|
64
|
+
if (!match) {
|
|
65
|
+
const validNames = input.enumHandle.enumMembers.map((m) => m.name).join(', ');
|
|
66
|
+
input.diagnostics.push({
|
|
67
|
+
code: 'PSL_ENUM_UNKNOWN_DEFAULT_MEMBER',
|
|
68
|
+
message: `Field "${input.modelName}.${input.fieldName}" @default(${raw}) does not name a member of ${input.enumHandle.enumName}. Valid members: ${validNames}.`,
|
|
69
|
+
sourceId: input.sourceId,
|
|
70
|
+
span: input.defaultAttribute.span,
|
|
71
|
+
});
|
|
72
|
+
return {};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
defaultValue: {
|
|
77
|
+
kind: 'literal',
|
|
78
|
+
value: blindCast<
|
|
79
|
+
ColumnDefaultLiteralInputValue,
|
|
80
|
+
'enum member values are codec-validated JsonValue-compatible scalars'
|
|
81
|
+
>(match.value),
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
24
86
|
export type ResolvedField = {
|
|
25
87
|
readonly field: PslField;
|
|
26
88
|
readonly columnName: string;
|
|
@@ -76,6 +138,7 @@ export interface CollectResolvedFieldsInput {
|
|
|
76
138
|
readonly diagnostics: ContractSourceDiagnostic[];
|
|
77
139
|
readonly sourceId: string;
|
|
78
140
|
readonly scalarTypeDescriptors: ReadonlyMap<string, ColumnDescriptor>;
|
|
141
|
+
readonly enumHandles?: ReadonlyMap<string, EnumTypeHandle>;
|
|
79
142
|
}
|
|
80
143
|
|
|
81
144
|
const BUILTIN_FIELD_ATTRIBUTE_NAMES: ReadonlySet<string> = new Set([
|
|
@@ -95,7 +158,7 @@ const BUILTIN_FIELD_ATTRIBUTE_NAMES: ReadonlySet<string> = new Set([
|
|
|
95
158
|
* migrated (so they don't get told to do what they just did).
|
|
96
159
|
*
|
|
97
160
|
* Pairing the suppression predicate with the hint makes each entry
|
|
98
|
-
* self-contained: a future entry for, say, `@id` ↔ `id.
|
|
161
|
+
* self-contained: a future entry for, say, `@id` ↔ `id.uuidv7String()` cannot
|
|
99
162
|
* silently inherit the wrong predicate when added.
|
|
100
163
|
*/
|
|
101
164
|
interface RemovedAttributeRule {
|
|
@@ -225,6 +288,7 @@ export function collectResolvedFields(input: CollectResolvedFieldsInput): Resolv
|
|
|
225
288
|
diagnostics,
|
|
226
289
|
sourceId,
|
|
227
290
|
scalarTypeDescriptors,
|
|
291
|
+
enumHandles,
|
|
228
292
|
} = input;
|
|
229
293
|
const resolvedFields: ResolvedField[] = [];
|
|
230
294
|
|
|
@@ -350,17 +414,27 @@ export function collectResolvedFields(input: CollectResolvedFieldsInput): Resolv
|
|
|
350
414
|
});
|
|
351
415
|
continue;
|
|
352
416
|
}
|
|
353
|
-
const
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
417
|
+
const enumHandle = enumHandles?.get(field.typeName);
|
|
418
|
+
const loweredDefault: LoweredFieldDefault = defaultAttribute
|
|
419
|
+
? enumHandle
|
|
420
|
+
? lowerEnumDefaultForField({
|
|
421
|
+
modelName: model.name,
|
|
422
|
+
fieldName: field.name,
|
|
423
|
+
defaultAttribute,
|
|
424
|
+
enumHandle,
|
|
425
|
+
sourceId,
|
|
426
|
+
diagnostics,
|
|
427
|
+
})
|
|
428
|
+
: lowerDefaultForField({
|
|
429
|
+
modelName: model.name,
|
|
430
|
+
fieldName: field.name,
|
|
431
|
+
defaultAttribute,
|
|
432
|
+
columnDescriptor: descriptor,
|
|
433
|
+
generatorDescriptorById,
|
|
434
|
+
sourceId,
|
|
435
|
+
defaultFunctionRegistry,
|
|
436
|
+
diagnostics,
|
|
437
|
+
})
|
|
364
438
|
: {};
|
|
365
439
|
const loweredOnCreate = loweredDefault.executionDefaults?.onCreate;
|
|
366
440
|
if (field.optional && loweredOnCreate) {
|
|
@@ -374,7 +448,9 @@ export function collectResolvedFields(input: CollectResolvedFieldsInput): Resolv
|
|
|
374
448
|
});
|
|
375
449
|
continue;
|
|
376
450
|
}
|
|
377
|
-
|
|
451
|
+
const fieldUsesNamedType =
|
|
452
|
+
field.typeRef !== undefined || namedTypeDescriptors.has(field.typeName);
|
|
453
|
+
if (loweredOnCreate && !fieldUsesNamedType) {
|
|
378
454
|
const generatorDescriptor = generatorDescriptorById.get(loweredOnCreate.id);
|
|
379
455
|
const generatedDescriptor = generatorDescriptor?.resolveGeneratedColumnDescriptor?.({
|
|
380
456
|
generated: loweredOnCreate,
|