@prisma-next/sql-contract-psl 0.13.0-dev.27 → 0.13.0-dev.29
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 +1 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{interpreter-BT6dEGeD.mjs → interpreter-B0BsCLKT.mjs} +33 -144
- package/dist/interpreter-B0BsCLKT.mjs.map +1 -0
- package/dist/provider.d.mts +1 -1
- package/dist/provider.mjs +1 -1
- package/package.json +12 -12
- package/src/interpreter.ts +36 -204
- package/src/psl-field-resolution.ts +10 -10
- package/dist/interpreter-BT6dEGeD.mjs.map +0 -1
package/dist/provider.d.mts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { ControlPolicy } from "@prisma-next/contract/types";
|
|
2
|
-
import { SqlNamespaceTablesInput } from "@prisma-next/sql-contract/types";
|
|
3
2
|
import { ContractConfig } from "@prisma-next/config/config-types";
|
|
4
3
|
import { ExtensionPackRef, TargetPackRef } from "@prisma-next/framework-components/components";
|
|
5
4
|
import { Namespace } from "@prisma-next/framework-components/ir";
|
|
5
|
+
import { SqlNamespaceTablesInput } from "@prisma-next/sql-contract/types";
|
|
6
6
|
|
|
7
7
|
//#region src/provider.d.ts
|
|
8
8
|
interface PrismaContractOptions {
|
package/dist/provider.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as interpretPslDocumentToSqlContract } from "./interpreter-
|
|
1
|
+
import { t as interpretPslDocumentToSqlContract } from "./interpreter-B0BsCLKT.mjs";
|
|
2
2
|
import { ifDefined } from "@prisma-next/utils/defined";
|
|
3
3
|
import { notOk, ok } from "@prisma-next/utils/result";
|
|
4
4
|
import { parsePslDocument } from "@prisma-next/psl-parser";
|
package/package.json
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma-next/sql-contract-psl",
|
|
3
|
-
"version": "0.13.0-dev.
|
|
3
|
+
"version": "0.13.0-dev.29",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"description": "PSL-to-SQL ContractIR interpreter for Prisma Next",
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@prisma-next/config": "0.13.0-dev.
|
|
10
|
-
"@prisma-next/contract": "0.13.0-dev.
|
|
11
|
-
"@prisma-next/framework-components": "0.13.0-dev.
|
|
12
|
-
"@prisma-next/psl-parser": "0.13.0-dev.
|
|
13
|
-
"@prisma-next/sql-contract": "0.13.0-dev.
|
|
14
|
-
"@prisma-next/sql-contract-ts": "0.13.0-dev.
|
|
15
|
-
"@prisma-next/utils": "0.13.0-dev.
|
|
9
|
+
"@prisma-next/config": "0.13.0-dev.29",
|
|
10
|
+
"@prisma-next/contract": "0.13.0-dev.29",
|
|
11
|
+
"@prisma-next/framework-components": "0.13.0-dev.29",
|
|
12
|
+
"@prisma-next/psl-parser": "0.13.0-dev.29",
|
|
13
|
+
"@prisma-next/sql-contract": "0.13.0-dev.29",
|
|
14
|
+
"@prisma-next/sql-contract-ts": "0.13.0-dev.29",
|
|
15
|
+
"@prisma-next/utils": "0.13.0-dev.29",
|
|
16
16
|
"pathe": "^2.0.3"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
|
-
"@prisma-next/contract-authoring": "0.13.0-dev.
|
|
20
|
-
"@prisma-next/test-utils": "0.13.0-dev.
|
|
21
|
-
"@prisma-next/tsconfig": "0.13.0-dev.
|
|
22
|
-
"@prisma-next/tsdown": "0.13.0-dev.
|
|
19
|
+
"@prisma-next/contract-authoring": "0.13.0-dev.29",
|
|
20
|
+
"@prisma-next/test-utils": "0.13.0-dev.29",
|
|
21
|
+
"@prisma-next/tsconfig": "0.13.0-dev.29",
|
|
22
|
+
"@prisma-next/tsdown": "0.13.0-dev.29",
|
|
23
23
|
"arktype": "^2.2.0",
|
|
24
24
|
"tsdown": "0.22.1",
|
|
25
25
|
"typescript": "5.9.3",
|
package/src/interpreter.ts
CHANGED
|
@@ -14,7 +14,6 @@ import { crossRef } from '@prisma-next/contract/types';
|
|
|
14
14
|
import type {
|
|
15
15
|
AuthoringContributions,
|
|
16
16
|
AuthoringEntityContext,
|
|
17
|
-
AuthoringEntityTypeDescriptor,
|
|
18
17
|
} from '@prisma-next/framework-components/authoring';
|
|
19
18
|
import { instantiateAuthoringEntityType } from '@prisma-next/framework-components/authoring';
|
|
20
19
|
import type { CodecLookup } from '@prisma-next/framework-components/codec';
|
|
@@ -30,19 +29,16 @@ import type {
|
|
|
30
29
|
ParsePslDocumentResult,
|
|
31
30
|
PslAttribute,
|
|
32
31
|
PslCompositeType,
|
|
33
|
-
PslEnum,
|
|
34
32
|
PslExtensionBlock,
|
|
35
33
|
PslField,
|
|
36
34
|
PslModel,
|
|
37
35
|
PslNamedTypeDeclaration,
|
|
38
36
|
PslNamespace,
|
|
39
37
|
} from '@prisma-next/psl-parser';
|
|
40
|
-
import {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
type SqlNamespaceTablesInput,
|
|
45
|
-
type StorageTypeInstance,
|
|
38
|
+
import type {
|
|
39
|
+
SqlModelStorage,
|
|
40
|
+
SqlNamespaceTablesInput,
|
|
41
|
+
StorageTypeInstance,
|
|
46
42
|
} from '@prisma-next/sql-contract/types';
|
|
47
43
|
import {
|
|
48
44
|
buildSqlContractFromDefinition,
|
|
@@ -67,7 +63,6 @@ import {
|
|
|
67
63
|
parseAttributeFieldList,
|
|
68
64
|
parseConstraintMapArgument,
|
|
69
65
|
parseControlPolicyAttribute,
|
|
70
|
-
parseMapName,
|
|
71
66
|
parseObjectLiteralStringMap,
|
|
72
67
|
parseQuotedStringLiteral,
|
|
73
68
|
} from './psl-attribute-parsing';
|
|
@@ -307,104 +302,30 @@ function validateNamespaceBlocksForSqlTarget(input: {
|
|
|
307
302
|
}
|
|
308
303
|
|
|
309
304
|
interface ProcessEnumDeclarationsInput {
|
|
310
|
-
readonly
|
|
311
|
-
readonly sourceId: string;
|
|
312
|
-
readonly enumEntityDescriptor: AuthoringEntityTypeDescriptor | undefined;
|
|
313
|
-
readonly entityContext: AuthoringEntityContext;
|
|
314
|
-
readonly diagnostics: ContractSourceDiagnostic[];
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
function processEnumDeclarations(input: ProcessEnumDeclarationsInput): {
|
|
318
|
-
readonly storageTypes: Record<string, StorageTypeInstance | PostgresEnumStorageEntry>;
|
|
319
|
-
readonly enumTypeDescriptors: Map<string, ColumnDescriptor>;
|
|
320
|
-
} {
|
|
321
|
-
const storageTypes: Record<string, StorageTypeInstance | PostgresEnumStorageEntry> = {};
|
|
322
|
-
const enumTypeDescriptors = new Map<string, ColumnDescriptor>();
|
|
323
|
-
|
|
324
|
-
if (input.enums.length === 0) {
|
|
325
|
-
return { storageTypes, enumTypeDescriptors };
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
if (!input.enumEntityDescriptor) {
|
|
329
|
-
// The PSL `enum X { … }` syntax only resolves when the active
|
|
330
|
-
// pack composition contributes an `enum` entity-type factory (the
|
|
331
|
-
// Postgres target pack does so today via
|
|
332
|
-
// `authoring.entityTypes.enum`). Without the contribution we
|
|
333
|
-
// surface a diagnostic per declaration rather than silently
|
|
334
|
-
// swallowing the syntax.
|
|
335
|
-
for (const enumDeclaration of input.enums) {
|
|
336
|
-
input.diagnostics.push({
|
|
337
|
-
code: 'PSL_UNSUPPORTED_NAMED_TYPE_BASE',
|
|
338
|
-
message: `Enum "${enumDeclaration.name}" requires the active target pack to contribute an enum entity-type helper`,
|
|
339
|
-
sourceId: input.sourceId,
|
|
340
|
-
span: enumDeclaration.span,
|
|
341
|
-
});
|
|
342
|
-
}
|
|
343
|
-
return { storageTypes, enumTypeDescriptors };
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
for (const enumDeclaration of input.enums) {
|
|
347
|
-
const nativeType = parseMapName({
|
|
348
|
-
attribute: getAttribute(enumDeclaration.attributes, 'map'),
|
|
349
|
-
defaultValue: enumDeclaration.name,
|
|
350
|
-
sourceId: input.sourceId,
|
|
351
|
-
diagnostics: input.diagnostics,
|
|
352
|
-
entityLabel: `Enum "${enumDeclaration.name}"`,
|
|
353
|
-
span: enumDeclaration.span,
|
|
354
|
-
});
|
|
355
|
-
const values = enumDeclaration.values.map((value) => value.name);
|
|
356
|
-
const constructed = instantiateAuthoringEntityType(
|
|
357
|
-
'enum',
|
|
358
|
-
input.enumEntityDescriptor,
|
|
359
|
-
[{ name: enumDeclaration.name, nativeType, values }],
|
|
360
|
-
input.entityContext,
|
|
361
|
-
);
|
|
362
|
-
if (!isPostgresEnumStorageEntry(constructed)) {
|
|
363
|
-
input.diagnostics.push({
|
|
364
|
-
code: 'PSL_UNSUPPORTED_NAMED_TYPE_BASE',
|
|
365
|
-
message: `Enum "${enumDeclaration.name}": enum entity-type factory must return a PostgresEnumStorageEntry-shaped value (kind: 'postgres-enum')`,
|
|
366
|
-
sourceId: input.sourceId,
|
|
367
|
-
span: enumDeclaration.span,
|
|
368
|
-
});
|
|
369
|
-
continue;
|
|
370
|
-
}
|
|
371
|
-
const descriptor: ColumnDescriptor = {
|
|
372
|
-
codecId: constructed.codecId,
|
|
373
|
-
nativeType: constructed.nativeType,
|
|
374
|
-
typeRef: enumDeclaration.name,
|
|
375
|
-
};
|
|
376
|
-
enumTypeDescriptors.set(enumDeclaration.name, descriptor);
|
|
377
|
-
storageTypes[enumDeclaration.name] = constructed;
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
return { storageTypes, enumTypeDescriptors };
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
interface ProcessEnum2DeclarationsInput {
|
|
384
|
-
readonly enum2Blocks: readonly PslExtensionBlock[];
|
|
305
|
+
readonly enumBlocks: readonly PslExtensionBlock[];
|
|
385
306
|
readonly sourceId: string;
|
|
386
307
|
readonly authoringContributions: AuthoringContributions | undefined;
|
|
387
308
|
readonly entityContext: AuthoringEntityContext;
|
|
388
309
|
readonly diagnostics: ContractSourceDiagnostic[];
|
|
389
310
|
}
|
|
390
311
|
|
|
391
|
-
function
|
|
312
|
+
function processEnumDeclarations(input: ProcessEnumDeclarationsInput): {
|
|
392
313
|
readonly enumHandles: Record<string, EnumTypeHandle>;
|
|
393
314
|
readonly enumTypeDescriptors: Map<string, ColumnDescriptor>;
|
|
394
315
|
} {
|
|
395
316
|
const enumHandles: Record<string, EnumTypeHandle> = {};
|
|
396
317
|
const enumTypeDescriptors = new Map<string, ColumnDescriptor>();
|
|
397
318
|
|
|
398
|
-
if (input.
|
|
319
|
+
if (input.enumBlocks.length === 0) {
|
|
399
320
|
return { enumHandles, enumTypeDescriptors };
|
|
400
321
|
}
|
|
401
322
|
|
|
402
|
-
const
|
|
403
|
-
if (!
|
|
404
|
-
for (const decl of input.
|
|
323
|
+
const enumDescriptor = getAuthoringEntity(input.authoringContributions, ['enum']);
|
|
324
|
+
if (!enumDescriptor) {
|
|
325
|
+
for (const decl of input.enumBlocks) {
|
|
405
326
|
input.diagnostics.push({
|
|
406
|
-
code: '
|
|
407
|
-
message: `
|
|
327
|
+
code: 'PSL_ENUM_MISSING_FACTORY',
|
|
328
|
+
message: `enum "${decl.name}" requires an "enum" entityType factory in the active authoring contributions`,
|
|
408
329
|
sourceId: input.sourceId,
|
|
409
330
|
span: decl.span,
|
|
410
331
|
});
|
|
@@ -412,17 +333,17 @@ function processEnum2Declarations(input: ProcessEnum2DeclarationsInput): {
|
|
|
412
333
|
return { enumHandles, enumTypeDescriptors };
|
|
413
334
|
}
|
|
414
335
|
|
|
415
|
-
for (const decl of input.
|
|
336
|
+
for (const decl of input.enumBlocks) {
|
|
416
337
|
const handle = instantiateAuthoringEntityType(
|
|
417
|
-
'
|
|
418
|
-
|
|
338
|
+
'enum',
|
|
339
|
+
enumDescriptor,
|
|
419
340
|
[decl],
|
|
420
341
|
input.entityContext,
|
|
421
342
|
);
|
|
422
343
|
|
|
423
344
|
if (handle === undefined || handle === null) continue;
|
|
424
345
|
|
|
425
|
-
const enumHandle = blindCast<EnumTypeHandle, '
|
|
346
|
+
const enumHandle = blindCast<EnumTypeHandle, 'enum factory returns EnumTypeHandle'>(handle);
|
|
426
347
|
enumHandles[decl.name] = enumHandle;
|
|
427
348
|
enumTypeDescriptors.set(decl.name, {
|
|
428
349
|
codecId: enumHandle.codecId,
|
|
@@ -509,10 +430,10 @@ function validateNamedTypeAttributes(input: {
|
|
|
509
430
|
}
|
|
510
431
|
|
|
511
432
|
function resolveNamedTypeDeclarations(input: ResolveNamedTypeDeclarationsInput): {
|
|
512
|
-
readonly storageTypes: Record<string, StorageTypeInstance
|
|
433
|
+
readonly storageTypes: Record<string, StorageTypeInstance>;
|
|
513
434
|
readonly namedTypeDescriptors: Map<string, ColumnDescriptor>;
|
|
514
435
|
} {
|
|
515
|
-
const storageTypes: Record<string, StorageTypeInstance
|
|
436
|
+
const storageTypes: Record<string, StorageTypeInstance> = {};
|
|
516
437
|
const namedTypeDescriptors = new Map<string, ColumnDescriptor>();
|
|
517
438
|
|
|
518
439
|
for (const declaration of input.declarations) {
|
|
@@ -677,7 +598,7 @@ interface BuildModelNodeInput {
|
|
|
677
598
|
readonly diagnostics: ContractSourceDiagnostic[];
|
|
678
599
|
/** Resolved namespace id keyed by model name — used to stamp the target namespace on FKs. */
|
|
679
600
|
readonly modelNamespaceIds: ReadonlyMap<string, string>;
|
|
680
|
-
readonly
|
|
601
|
+
readonly enumHandles?: ReadonlyMap<string, EnumTypeHandle>;
|
|
681
602
|
}
|
|
682
603
|
|
|
683
604
|
interface BuildModelNodeResult {
|
|
@@ -709,7 +630,7 @@ function buildModelNodeFromPsl(input: BuildModelNodeInput): BuildModelNodeResult
|
|
|
709
630
|
diagnostics,
|
|
710
631
|
sourceId,
|
|
711
632
|
scalarTypeDescriptors: input.scalarTypeDescriptors,
|
|
712
|
-
...ifDefined('
|
|
633
|
+
...ifDefined('enumHandles', input.enumHandles),
|
|
713
634
|
});
|
|
714
635
|
|
|
715
636
|
const inlineIdFields = resolvedFields.filter((field) => field.isId);
|
|
@@ -1381,7 +1302,7 @@ function buildModelNodeFromPsl(input: BuildModelNodeInput): BuildModelNodeResult
|
|
|
1381
1302
|
modelName: model.name,
|
|
1382
1303
|
tableName,
|
|
1383
1304
|
fields: resolvedFields.map((resolvedField) => {
|
|
1384
|
-
const enumHandle = input.
|
|
1305
|
+
const enumHandle = input.enumHandles?.get(resolvedField.field.typeName);
|
|
1385
1306
|
return {
|
|
1386
1307
|
fieldName: resolvedField.field.name,
|
|
1387
1308
|
columnName: resolvedField.columnName,
|
|
@@ -1988,33 +1909,6 @@ export function interpretPslDocumentToSqlContract(
|
|
|
1988
1909
|
}
|
|
1989
1910
|
}
|
|
1990
1911
|
const defaultNamespaceId = input.target.defaultNamespaceId;
|
|
1991
|
-
// Top-level enums (the __unspecified__ bucket) route to `storageTypes`;
|
|
1992
|
-
// enums inside a named namespace block route to `namespaceTypes[nsId]`.
|
|
1993
|
-
const topLevelEnums = input.document.ast.namespaces
|
|
1994
|
-
.filter((ns) => ns.name === UNSPECIFIED_PSL_NAMESPACE_NAME)
|
|
1995
|
-
.flatMap((ns) => ns.enums);
|
|
1996
|
-
const namedNamespaceEnumsByNsId = new Map<string, readonly PslEnum[]>();
|
|
1997
|
-
for (const ns of input.document.ast.namespaces) {
|
|
1998
|
-
if (ns.name === UNSPECIFIED_PSL_NAMESPACE_NAME || ns.enums.length === 0) {
|
|
1999
|
-
continue;
|
|
2000
|
-
}
|
|
2001
|
-
const resolvedId = resolveNamespaceIdForSqlTarget({
|
|
2002
|
-
bucketName: ns.name,
|
|
2003
|
-
targetId: input.target.targetId,
|
|
2004
|
-
});
|
|
2005
|
-
if (resolvedId === undefined) {
|
|
2006
|
-
continue;
|
|
2007
|
-
}
|
|
2008
|
-
// Read-then-merge so that any future change to the PSL parser (or to
|
|
2009
|
-
// `resolveNamespaceIdForSqlTarget`) that produces two AST entries
|
|
2010
|
-
// resolving to the same `resolvedId` would accumulate their enums
|
|
2011
|
-
// rather than silently dropping the earlier set. Today the parser
|
|
2012
|
-
// already merges duplicate `namespace <name> { … }` blocks into a
|
|
2013
|
-
// single AST entry per name, so this loop sees one `ns` per
|
|
2014
|
-
// resolvedId and the merge degrades to a plain set.
|
|
2015
|
-
const existing = namedNamespaceEnumsByNsId.get(resolvedId) ?? [];
|
|
2016
|
-
namedNamespaceEnumsByNsId.set(resolvedId, [...existing, ...ns.enums]);
|
|
2017
|
-
}
|
|
2018
1912
|
|
|
2019
1913
|
const compositeTypes = input.document.ast.namespaces.flatMap((ns) => ns.compositeTypes);
|
|
2020
1914
|
const modelNames = new Set(models.map((model) => model.name));
|
|
@@ -2030,65 +1924,25 @@ export function interpretPslDocumentToSqlContract(
|
|
|
2030
1924
|
generatorDescriptorById.set(descriptor.id, descriptor);
|
|
2031
1925
|
}
|
|
2032
1926
|
|
|
2033
|
-
const
|
|
2034
|
-
const enumEntityContext = {
|
|
2035
|
-
family: input.target.familyId,
|
|
2036
|
-
target: input.target.targetId,
|
|
2037
|
-
};
|
|
2038
|
-
|
|
2039
|
-
const enumResult = processEnumDeclarations({
|
|
2040
|
-
enums: topLevelEnums,
|
|
2041
|
-
sourceId,
|
|
2042
|
-
enumEntityDescriptor,
|
|
2043
|
-
entityContext: enumEntityContext,
|
|
2044
|
-
diagnostics,
|
|
2045
|
-
});
|
|
2046
|
-
|
|
2047
|
-
// Process enums declared in named namespace blocks and collect them into
|
|
2048
|
-
// `namespaceTypes` keyed by the resolved namespace id.
|
|
2049
|
-
const allEnumTypeDescriptors = new Map(enumResult.enumTypeDescriptors);
|
|
2050
|
-
const namespaceEnumStorageTypes: Record<string, Record<string, PostgresEnumStorageEntry>> = {};
|
|
2051
|
-
for (const [nsId, nsEnums] of namedNamespaceEnumsByNsId) {
|
|
2052
|
-
const nsEnumResult = processEnumDeclarations({
|
|
2053
|
-
enums: nsEnums,
|
|
2054
|
-
sourceId,
|
|
2055
|
-
enumEntityDescriptor,
|
|
2056
|
-
entityContext: enumEntityContext,
|
|
2057
|
-
diagnostics,
|
|
2058
|
-
});
|
|
2059
|
-
for (const [name, descriptor] of nsEnumResult.enumTypeDescriptors) {
|
|
2060
|
-
allEnumTypeDescriptors.set(name, descriptor);
|
|
2061
|
-
}
|
|
2062
|
-
const nsEntries: Record<string, PostgresEnumStorageEntry> = {};
|
|
2063
|
-
for (const [name, entry] of Object.entries(nsEnumResult.storageTypes)) {
|
|
2064
|
-
if (isPostgresEnumStorageEntry(entry)) {
|
|
2065
|
-
nsEntries[name] = entry;
|
|
2066
|
-
}
|
|
2067
|
-
}
|
|
2068
|
-
if (Object.keys(nsEntries).length > 0) {
|
|
2069
|
-
namespaceEnumStorageTypes[nsId] = nsEntries;
|
|
2070
|
-
}
|
|
2071
|
-
}
|
|
2072
|
-
|
|
2073
|
-
const topLevelEnum2s = input.document.ast.namespaces
|
|
1927
|
+
const topLevelEnums = input.document.ast.namespaces
|
|
2074
1928
|
.filter((ns) => ns.name === UNSPECIFIED_PSL_NAMESPACE_NAME)
|
|
2075
|
-
.flatMap((ns) => namespacePslExtensionBlocks(ns).filter((b) => b.kind === '
|
|
1929
|
+
.flatMap((ns) => namespacePslExtensionBlocks(ns).filter((b) => b.kind === 'enum'));
|
|
2076
1930
|
for (const ns of input.document.ast.namespaces) {
|
|
2077
1931
|
if (ns.name === UNSPECIFIED_PSL_NAMESPACE_NAME) continue;
|
|
2078
|
-
const
|
|
2079
|
-
if (
|
|
2080
|
-
for (const decl of
|
|
1932
|
+
const nsEnums = namespacePslExtensionBlocks(ns).filter((b) => b.kind === 'enum');
|
|
1933
|
+
if (nsEnums.length === 0) continue;
|
|
1934
|
+
for (const decl of nsEnums) {
|
|
2081
1935
|
diagnostics.push({
|
|
2082
|
-
code: '
|
|
2083
|
-
message: `
|
|
1936
|
+
code: 'PSL_ENUM_NAMESPACE_NOT_SUPPORTED',
|
|
1937
|
+
message: `enum "${decl.name}" inside namespace "${ns.name}" is not supported; declare enum at the top level`,
|
|
2084
1938
|
sourceId,
|
|
2085
1939
|
span: decl.span,
|
|
2086
1940
|
});
|
|
2087
1941
|
}
|
|
2088
1942
|
}
|
|
2089
1943
|
|
|
2090
|
-
const
|
|
2091
|
-
|
|
1944
|
+
const enumResult = processEnumDeclarations({
|
|
1945
|
+
enumBlocks: topLevelEnums,
|
|
2092
1946
|
sourceId,
|
|
2093
1947
|
authoringContributions: input.authoringContributions,
|
|
2094
1948
|
entityContext: {
|
|
@@ -2107,30 +1961,11 @@ export function interpretPslDocumentToSqlContract(
|
|
|
2107
1961
|
diagnostics,
|
|
2108
1962
|
});
|
|
2109
1963
|
|
|
2110
|
-
const
|
|
2111
|
-
for (const [name, descriptor] of enum2Result.enumTypeDescriptors) {
|
|
2112
|
-
if (allEnumTypeDescriptors.has(name)) {
|
|
2113
|
-
collidingEnum2Names.add(name);
|
|
2114
|
-
const collision = topLevelEnum2s.find((e) => e.name === name);
|
|
2115
|
-
diagnostics.push({
|
|
2116
|
-
code: 'PSL_ENUM2_DUPLICATE_TYPE_NAME',
|
|
2117
|
-
message: `enum2 "${name}" collides with an existing type name; each type name must be unique`,
|
|
2118
|
-
sourceId,
|
|
2119
|
-
...ifDefined('span', collision?.span),
|
|
2120
|
-
});
|
|
2121
|
-
} else {
|
|
2122
|
-
allEnumTypeDescriptors.set(name, descriptor);
|
|
2123
|
-
}
|
|
2124
|
-
}
|
|
1964
|
+
const allEnumTypeDescriptors = new Map(enumResult.enumTypeDescriptors);
|
|
2125
1965
|
|
|
2126
|
-
const
|
|
2127
|
-
for (const [name, handle] of Object.entries(enum2Result.enumHandles)) {
|
|
2128
|
-
if (!collidingEnum2Names.has(name)) {
|
|
2129
|
-
validEnum2Handles[name] = handle;
|
|
2130
|
-
}
|
|
2131
|
-
}
|
|
1966
|
+
const validEnumHandles: Record<string, EnumTypeHandle> = { ...enumResult.enumHandles };
|
|
2132
1967
|
|
|
2133
|
-
const
|
|
1968
|
+
const enumHandlesByName = new Map(Object.entries(validEnumHandles));
|
|
2134
1969
|
|
|
2135
1970
|
const namedTypeResult = resolveNamedTypeDeclarations({
|
|
2136
1971
|
declarations: input.document.ast.types?.declarations ?? [],
|
|
@@ -2144,7 +1979,7 @@ export function interpretPslDocumentToSqlContract(
|
|
|
2144
1979
|
diagnostics,
|
|
2145
1980
|
});
|
|
2146
1981
|
|
|
2147
|
-
const storageTypes = { ...
|
|
1982
|
+
const storageTypes = { ...namedTypeResult.storageTypes };
|
|
2148
1983
|
|
|
2149
1984
|
const modelMappingsByCoordinate = buildModelMappings(
|
|
2150
1985
|
modelEntries,
|
|
@@ -2194,7 +2029,7 @@ export function interpretPslDocumentToSqlContract(
|
|
|
2194
2029
|
sourceId,
|
|
2195
2030
|
diagnostics,
|
|
2196
2031
|
modelNamespaceIds,
|
|
2197
|
-
...(
|
|
2032
|
+
...(enumHandlesByName.size > 0 ? { enumHandles: enumHandlesByName } : {}),
|
|
2198
2033
|
});
|
|
2199
2034
|
modelNodes.push(
|
|
2200
2035
|
namespaceId !== undefined ? { ...result.modelNode, namespaceId } : result.modelNode,
|
|
@@ -2286,10 +2121,7 @@ export function interpretPslDocumentToSqlContract(
|
|
|
2286
2121
|
),
|
|
2287
2122
|
),
|
|
2288
2123
|
...(Object.keys(storageTypes).length > 0 ? { storageTypes } : {}),
|
|
2289
|
-
...(Object.keys(
|
|
2290
|
-
? { namespaceTypes: namespaceEnumStorageTypes }
|
|
2291
|
-
: {}),
|
|
2292
|
-
...(Object.keys(validEnum2Handles).length > 0 ? { enums: validEnum2Handles } : {}),
|
|
2124
|
+
...(Object.keys(validEnumHandles).length > 0 ? { enums: validEnumHandles } : {}),
|
|
2293
2125
|
...ifDefined('createNamespace', input.createNamespace),
|
|
2294
2126
|
models: stiColumnModelNodes.map((model) => ({
|
|
2295
2127
|
...model,
|
|
@@ -33,7 +33,7 @@ type LoweredFieldDefault = {
|
|
|
33
33
|
readonly executionDefaults?: ExecutionMutationDefaultPhases;
|
|
34
34
|
};
|
|
35
35
|
|
|
36
|
-
function
|
|
36
|
+
function lowerEnumDefaultForField(input: {
|
|
37
37
|
readonly modelName: string;
|
|
38
38
|
readonly fieldName: string;
|
|
39
39
|
readonly defaultAttribute: PslAttribute;
|
|
@@ -52,8 +52,8 @@ function lowerEnum2DefaultForField(input: {
|
|
|
52
52
|
|
|
53
53
|
if (isQuotedString || isFunctionCall) {
|
|
54
54
|
input.diagnostics.push({
|
|
55
|
-
code: '
|
|
56
|
-
message: `Field "${input.modelName}.${input.fieldName}" @default on an
|
|
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
57
|
sourceId: input.sourceId,
|
|
58
58
|
span: input.defaultAttribute.span,
|
|
59
59
|
});
|
|
@@ -64,7 +64,7 @@ function lowerEnum2DefaultForField(input: {
|
|
|
64
64
|
if (!match) {
|
|
65
65
|
const validNames = input.enumHandle.enumMembers.map((m) => m.name).join(', ');
|
|
66
66
|
input.diagnostics.push({
|
|
67
|
-
code: '
|
|
67
|
+
code: 'PSL_ENUM_UNKNOWN_DEFAULT_MEMBER',
|
|
68
68
|
message: `Field "${input.modelName}.${input.fieldName}" @default(${raw}) does not name a member of ${input.enumHandle.enumName}. Valid members: ${validNames}.`,
|
|
69
69
|
sourceId: input.sourceId,
|
|
70
70
|
span: input.defaultAttribute.span,
|
|
@@ -138,7 +138,7 @@ export interface CollectResolvedFieldsInput {
|
|
|
138
138
|
readonly diagnostics: ContractSourceDiagnostic[];
|
|
139
139
|
readonly sourceId: string;
|
|
140
140
|
readonly scalarTypeDescriptors: ReadonlyMap<string, ColumnDescriptor>;
|
|
141
|
-
readonly
|
|
141
|
+
readonly enumHandles?: ReadonlyMap<string, EnumTypeHandle>;
|
|
142
142
|
}
|
|
143
143
|
|
|
144
144
|
const BUILTIN_FIELD_ATTRIBUTE_NAMES: ReadonlySet<string> = new Set([
|
|
@@ -288,7 +288,7 @@ export function collectResolvedFields(input: CollectResolvedFieldsInput): Resolv
|
|
|
288
288
|
diagnostics,
|
|
289
289
|
sourceId,
|
|
290
290
|
scalarTypeDescriptors,
|
|
291
|
-
|
|
291
|
+
enumHandles,
|
|
292
292
|
} = input;
|
|
293
293
|
const resolvedFields: ResolvedField[] = [];
|
|
294
294
|
|
|
@@ -414,14 +414,14 @@ export function collectResolvedFields(input: CollectResolvedFieldsInput): Resolv
|
|
|
414
414
|
});
|
|
415
415
|
continue;
|
|
416
416
|
}
|
|
417
|
-
const
|
|
417
|
+
const enumHandle = enumHandles?.get(field.typeName);
|
|
418
418
|
const loweredDefault: LoweredFieldDefault = defaultAttribute
|
|
419
|
-
?
|
|
420
|
-
?
|
|
419
|
+
? enumHandle
|
|
420
|
+
? lowerEnumDefaultForField({
|
|
421
421
|
modelName: model.name,
|
|
422
422
|
fieldName: field.name,
|
|
423
423
|
defaultAttribute,
|
|
424
|
-
enumHandle
|
|
424
|
+
enumHandle,
|
|
425
425
|
sourceId,
|
|
426
426
|
diagnostics,
|
|
427
427
|
})
|