@prisma-next/sql-contract-psl 0.14.0-dev.5 → 0.14.0-dev.6

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.
@@ -0,0 +1,250 @@
1
+ import type { ContractSourceDiagnostic } from '@prisma-next/config/config-types';
2
+ import type { AuthoringContributions } from '@prisma-next/framework-components/authoring';
3
+ import type { ResolvedAttribute, ScalarSymbol, TypeAliasSymbol } from '@prisma-next/psl-parser';
4
+ import type { StorageTypeInstance } from '@prisma-next/sql-contract/types';
5
+ import {
6
+ type ColumnDescriptor,
7
+ checkUncomposedNamespace,
8
+ instantiatePslTypeConstructor,
9
+ reportUncomposedNamespace,
10
+ resolveDbNativeTypeAttribute,
11
+ resolvePslTypeConstructorDescriptor,
12
+ toNamedTypeFieldDescriptor,
13
+ } from './psl-column-resolution';
14
+
15
+ type NamedTypeSymbol = ScalarSymbol | TypeAliasSymbol;
16
+
17
+ export interface ResolveNamedTypeDeclarationsInput {
18
+ readonly declarations: readonly NamedTypeSymbol[];
19
+ readonly sourceId: string;
20
+ readonly enumTypeDescriptors: ReadonlyMap<string, ColumnDescriptor>;
21
+ readonly scalarTypeDescriptors: ReadonlyMap<string, ColumnDescriptor>;
22
+ readonly composedExtensions: ReadonlySet<string>;
23
+ readonly familyId: string;
24
+ readonly targetId: string;
25
+ readonly authoringContributions: AuthoringContributions | undefined;
26
+ readonly diagnostics: ContractSourceDiagnostic[];
27
+ }
28
+
29
+ function validateNamedTypeAttributes(input: {
30
+ readonly declaration: NamedTypeSymbol;
31
+ readonly sourceId: string;
32
+ readonly diagnostics: ContractSourceDiagnostic[];
33
+ readonly composedExtensions: ReadonlySet<string>;
34
+ readonly authoringContributions: AuthoringContributions | undefined;
35
+ readonly allowDbNativeType: boolean;
36
+ readonly familyId: string;
37
+ readonly targetId: string;
38
+ }): {
39
+ readonly dbNativeTypeAttribute: ResolvedAttribute | undefined;
40
+ readonly hasUnsupportedNamedTypeAttribute: boolean;
41
+ } {
42
+ const dbNativeTypeAttributes = input.allowDbNativeType
43
+ ? input.declaration.attributes.filter((attribute) => attribute.name.startsWith('db.'))
44
+ : [];
45
+ const [dbNativeTypeAttribute, ...extraDbNativeTypeAttributes] = dbNativeTypeAttributes;
46
+ let hasUnsupportedNamedTypeAttribute = false;
47
+
48
+ for (const extra of extraDbNativeTypeAttributes) {
49
+ input.diagnostics.push({
50
+ code: 'PSL_INVALID_ATTRIBUTE_ARGUMENT',
51
+ message: `Named type "${input.declaration.name}" can declare at most one @db.* attribute`,
52
+ sourceId: input.sourceId,
53
+ span: extra.span,
54
+ });
55
+ hasUnsupportedNamedTypeAttribute = true;
56
+ }
57
+
58
+ for (const attribute of input.declaration.attributes) {
59
+ if (input.allowDbNativeType && attribute.name.startsWith('db.')) {
60
+ continue;
61
+ }
62
+
63
+ const uncomposedNamespace = checkUncomposedNamespace(attribute.name, input.composedExtensions, {
64
+ familyId: input.familyId,
65
+ targetId: input.targetId,
66
+ authoringContributions: input.authoringContributions,
67
+ });
68
+ if (uncomposedNamespace) {
69
+ reportUncomposedNamespace({
70
+ subjectLabel: `Attribute "@${attribute.name}"`,
71
+ namespace: uncomposedNamespace,
72
+ sourceId: input.sourceId,
73
+ span: attribute.span,
74
+ diagnostics: input.diagnostics,
75
+ });
76
+ hasUnsupportedNamedTypeAttribute = true;
77
+ continue;
78
+ }
79
+
80
+ input.diagnostics.push({
81
+ code: 'PSL_UNSUPPORTED_NAMED_TYPE_ATTRIBUTE',
82
+ message: `Named type "${input.declaration.name}" uses unsupported attribute "${attribute.name}"`,
83
+ sourceId: input.sourceId,
84
+ span: attribute.span,
85
+ });
86
+ hasUnsupportedNamedTypeAttribute = true;
87
+ }
88
+
89
+ return { dbNativeTypeAttribute, hasUnsupportedNamedTypeAttribute };
90
+ }
91
+
92
+ export function resolveNamedTypeDeclarations(input: ResolveNamedTypeDeclarationsInput): {
93
+ readonly storageTypes: Record<string, StorageTypeInstance>;
94
+ readonly namedTypeDescriptors: Map<string, ColumnDescriptor>;
95
+ } {
96
+ const storageTypeEntries: [string, StorageTypeInstance][] = [];
97
+ const namedTypeDescriptors = new Map<string, ColumnDescriptor>();
98
+
99
+ for (const declaration of input.declarations) {
100
+ if (declaration.isConstructor) {
101
+ const typeConstructor = declaration.typeConstructor;
102
+ if (typeConstructor === undefined) {
103
+ input.diagnostics.push({
104
+ code: 'PSL_UNSUPPORTED_NAMED_TYPE_BASE',
105
+ message: `Named type "${declaration.name}" must declare a base type or constructor`,
106
+ sourceId: input.sourceId,
107
+ span: declaration.span,
108
+ });
109
+ continue;
110
+ }
111
+
112
+ const { hasUnsupportedNamedTypeAttribute } = validateNamedTypeAttributes({
113
+ declaration,
114
+ sourceId: input.sourceId,
115
+ diagnostics: input.diagnostics,
116
+ composedExtensions: input.composedExtensions,
117
+ authoringContributions: input.authoringContributions,
118
+ allowDbNativeType: false,
119
+ familyId: input.familyId,
120
+ targetId: input.targetId,
121
+ });
122
+ if (hasUnsupportedNamedTypeAttribute) {
123
+ continue;
124
+ }
125
+
126
+ const helperPath = typeConstructor.path.join('.');
127
+ const descriptor = resolvePslTypeConstructorDescriptor({
128
+ call: typeConstructor,
129
+ authoringContributions: input.authoringContributions,
130
+ composedExtensions: input.composedExtensions,
131
+ familyId: input.familyId,
132
+ targetId: input.targetId,
133
+ diagnostics: input.diagnostics,
134
+ sourceId: input.sourceId,
135
+ unsupportedCode: 'PSL_UNSUPPORTED_NAMED_TYPE_CONSTRUCTOR',
136
+ unsupportedMessage: `Named type "${declaration.name}" references unsupported constructor "${helperPath}"`,
137
+ });
138
+ if (!descriptor) {
139
+ continue;
140
+ }
141
+
142
+ const storageType = instantiatePslTypeConstructor({
143
+ call: typeConstructor,
144
+ descriptor,
145
+ diagnostics: input.diagnostics,
146
+ sourceId: input.sourceId,
147
+ entityLabel: `Named type "${declaration.name}"`,
148
+ });
149
+ if (!storageType) {
150
+ continue;
151
+ }
152
+
153
+ namedTypeDescriptors.set(
154
+ declaration.name,
155
+ toNamedTypeFieldDescriptor(declaration.name, storageType),
156
+ );
157
+ storageTypeEntries.push([
158
+ declaration.name,
159
+ {
160
+ kind: 'codec-instance',
161
+ codecId: storageType.codecId,
162
+ nativeType: storageType.nativeType,
163
+ typeParams: storageType.typeParams ?? {},
164
+ },
165
+ ]);
166
+ continue;
167
+ }
168
+
169
+ const baseType = declaration.baseType;
170
+ if (baseType === undefined) {
171
+ input.diagnostics.push({
172
+ code: 'PSL_UNSUPPORTED_NAMED_TYPE_BASE',
173
+ message: `Named type "${declaration.name}" must declare a base type or constructor`,
174
+ sourceId: input.sourceId,
175
+ span: declaration.span,
176
+ });
177
+ continue;
178
+ }
179
+
180
+ const baseDescriptor =
181
+ input.enumTypeDescriptors.get(baseType) ?? input.scalarTypeDescriptors.get(baseType);
182
+ if (!baseDescriptor) {
183
+ input.diagnostics.push({
184
+ code: 'PSL_UNSUPPORTED_NAMED_TYPE_BASE',
185
+ message: `Named type "${declaration.name}" references unsupported base type "${baseType}"`,
186
+ sourceId: input.sourceId,
187
+ span: declaration.span,
188
+ });
189
+ continue;
190
+ }
191
+
192
+ const { dbNativeTypeAttribute, hasUnsupportedNamedTypeAttribute } = validateNamedTypeAttributes(
193
+ {
194
+ declaration,
195
+ sourceId: input.sourceId,
196
+ diagnostics: input.diagnostics,
197
+ composedExtensions: input.composedExtensions,
198
+ authoringContributions: input.authoringContributions,
199
+ allowDbNativeType: true,
200
+ familyId: input.familyId,
201
+ targetId: input.targetId,
202
+ },
203
+ );
204
+ if (hasUnsupportedNamedTypeAttribute) {
205
+ continue;
206
+ }
207
+
208
+ if (dbNativeTypeAttribute) {
209
+ const descriptor = resolveDbNativeTypeAttribute({
210
+ attribute: dbNativeTypeAttribute,
211
+ baseType,
212
+ baseDescriptor,
213
+ diagnostics: input.diagnostics,
214
+ sourceId: input.sourceId,
215
+ entityLabel: `Named type "${declaration.name}"`,
216
+ });
217
+ if (!descriptor) {
218
+ continue;
219
+ }
220
+ namedTypeDescriptors.set(
221
+ declaration.name,
222
+ toNamedTypeFieldDescriptor(declaration.name, descriptor),
223
+ );
224
+ storageTypeEntries.push([
225
+ declaration.name,
226
+ {
227
+ kind: 'codec-instance',
228
+ codecId: descriptor.codecId,
229
+ nativeType: descriptor.nativeType,
230
+ typeParams: descriptor.typeParams ?? {},
231
+ },
232
+ ]);
233
+ continue;
234
+ }
235
+
236
+ const descriptor = toNamedTypeFieldDescriptor(declaration.name, baseDescriptor);
237
+ namedTypeDescriptors.set(declaration.name, descriptor);
238
+ storageTypeEntries.push([
239
+ declaration.name,
240
+ {
241
+ kind: 'codec-instance',
242
+ codecId: baseDescriptor.codecId,
243
+ nativeType: baseDescriptor.nativeType,
244
+ typeParams: {},
245
+ },
246
+ ]);
247
+ }
248
+
249
+ return { storageTypes: Object.fromEntries(storageTypeEntries), namedTypeDescriptors };
250
+ }
@@ -1,10 +1,11 @@
1
1
  import type { ContractSourceDiagnostic } from '@prisma-next/config/config-types';
2
2
  import type { AuthoringContributions } from '@prisma-next/framework-components/authoring';
3
- import type { PslAttribute, PslField, PslSpan } from '@prisma-next/psl-parser';
3
+ import type { FieldSymbol, PslSpan, ResolvedAttribute } from '@prisma-next/psl-parser';
4
4
  import type { ReferentialAction } from '@prisma-next/sql-contract/types';
5
5
  import type { RelationNode } from '@prisma-next/sql-contract-ts/contract-builder';
6
6
  import { assertDefined, invariant } from '@prisma-next/utils/assertions';
7
7
  import { ifDefined } from '@prisma-next/utils/defined';
8
+
8
9
  import {
9
10
  getNamedArgument,
10
11
  getPositionalArgumentEntry,
@@ -52,7 +53,7 @@ export type FkRelationMetadata = {
52
53
  export type ModelBackrelationCandidate = {
53
54
  readonly modelName: string;
54
55
  readonly tableName: string;
55
- readonly field: PslField;
56
+ readonly field: FieldSymbol;
56
57
  readonly targetModelName: string;
57
58
  readonly relationName?: string;
58
59
  };
@@ -88,7 +89,7 @@ export function normalizeReferentialAction(input: {
88
89
  }
89
90
 
90
91
  export function parseRelationAttribute(input: {
91
- readonly attribute: PslAttribute;
92
+ readonly attribute: ResolvedAttribute;
92
93
  readonly modelName: string;
93
94
  readonly fieldName: string;
94
95
  readonly sourceId: string;
@@ -334,7 +335,7 @@ export function applyBackrelationCandidates(input: {
334
335
 
335
336
  export function validateNavigationListFieldAttributes(input: {
336
337
  readonly modelName: string;
337
- readonly field: PslField;
338
+ readonly field: FieldSymbol;
338
339
  readonly sourceId: string;
339
340
  readonly composedExtensions: Set<string>;
340
341
  readonly authoringContributions: AuthoringContributions | undefined;