@prisma-next/sql-contract-psl 0.9.0 → 0.10.0
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 +12 -0
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{interpreter-D_zkd14G.mjs → interpreter-fVwMptxi.mjs} +174 -20
- package/dist/interpreter-fVwMptxi.mjs.map +1 -0
- package/dist/provider.mjs +1 -1
- package/package.json +12 -12
- package/src/interpreter.ts +255 -17
- package/dist/interpreter-D_zkd14G.mjs.map +0 -1
package/src/interpreter.ts
CHANGED
|
@@ -21,6 +21,7 @@ import type {
|
|
|
21
21
|
ControlMutationDefaults,
|
|
22
22
|
MutationDefaultGeneratorDescriptor,
|
|
23
23
|
} from '@prisma-next/framework-components/control';
|
|
24
|
+
import type { Namespace } from '@prisma-next/framework-components/ir';
|
|
24
25
|
import type {
|
|
25
26
|
ParsePslDocumentResult,
|
|
26
27
|
PslAttribute,
|
|
@@ -29,10 +30,12 @@ import type {
|
|
|
29
30
|
PslField,
|
|
30
31
|
PslModel,
|
|
31
32
|
PslNamedTypeDeclaration,
|
|
33
|
+
PslNamespace,
|
|
32
34
|
} from '@prisma-next/psl-parser';
|
|
33
35
|
import {
|
|
34
36
|
isPostgresEnumStorageEntry,
|
|
35
37
|
type PostgresEnumStorageEntry,
|
|
38
|
+
type SqlNamespaceTablesInput,
|
|
36
39
|
type StorageTypeInstance,
|
|
37
40
|
} from '@prisma-next/sql-contract/types';
|
|
38
41
|
import {
|
|
@@ -92,6 +95,16 @@ export interface InterpretPslDocumentToSqlContractInput {
|
|
|
92
95
|
readonly composedExtensionPackRefs?: readonly ExtensionPackRef<'sql', string>[];
|
|
93
96
|
readonly controlMutationDefaults?: ControlMutationDefaults;
|
|
94
97
|
readonly authoringContributions?: AuthoringContributions;
|
|
98
|
+
/**
|
|
99
|
+
* Target-supplied `Namespace` factory threaded into
|
|
100
|
+
* `buildSqlContractFromDefinition` for the contract's
|
|
101
|
+
* `SqlStorage.namespaces` population. Required when the document
|
|
102
|
+
* contains any explicit `namespace { … }` block on Postgres; the
|
|
103
|
+
* single-namespace path (top-level declarations only) stays valid
|
|
104
|
+
* without the factory and falls back to the family
|
|
105
|
+
* `SqlUnboundNamespace` singleton.
|
|
106
|
+
*/
|
|
107
|
+
readonly createNamespace?: (input: SqlNamespaceTablesInput) => Namespace;
|
|
95
108
|
}
|
|
96
109
|
|
|
97
110
|
function buildComposedExtensionPackRefs(
|
|
@@ -160,6 +173,115 @@ function mapParserDiagnostics(document: ParsePslDocumentResult): ContractSourceD
|
|
|
160
173
|
}));
|
|
161
174
|
}
|
|
162
175
|
|
|
176
|
+
/**
|
|
177
|
+
* Name of the framework-parser synthesised bucket for top-level
|
|
178
|
+
* declarations. Re-declared here so the per-target dispatch does not
|
|
179
|
+
* have to import from `@prisma-next/framework-components/psl-ast`
|
|
180
|
+
* (which would cross a layer that the interpreter does not otherwise
|
|
181
|
+
* import from). The value is part of the framework parser's contract;
|
|
182
|
+
* if it changes there, the matching test in this package's
|
|
183
|
+
* `interpreter.diagnostics.test.ts` flips first.
|
|
184
|
+
*/
|
|
185
|
+
const UNSPECIFIED_PSL_NAMESPACE_NAME = '__unspecified__';
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Per-target namespace-block validation: walk the AST's namespace buckets and
|
|
189
|
+
* emit diagnostics for syntactic constructs the target does not accept.
|
|
190
|
+
*
|
|
191
|
+
* - **SQLite** has no schema concept and rejects every explicit
|
|
192
|
+
* `namespace { … }` block. The implicit `__unspecified__` bucket
|
|
193
|
+
* (produced by the parser for top-level declarations outside any
|
|
194
|
+
* block) is the only namespace SQLite accepts.
|
|
195
|
+
* - **Postgres** accepts every explicit block — `namespace unbound { … }`
|
|
196
|
+
* is the late-binding opt-in (lowers to the IR `__unbound__` slot in
|
|
197
|
+
* a follow-on commit), `namespace public { … }` reopen-merges with
|
|
198
|
+
* the implicit bucket, and any other name lowers to a named schema.
|
|
199
|
+
*
|
|
200
|
+
* Storage-side lowering of these buckets to IR namespace slots is not
|
|
201
|
+
* yet wired; this helper closes only the diagnostic surface.
|
|
202
|
+
*/
|
|
203
|
+
/**
|
|
204
|
+
* Per-target namespace lowering: map a PSL AST namespace bucket name to the
|
|
205
|
+
* resolved IR namespace id (the key downstream consumers use against
|
|
206
|
+
* `SqlStorage.namespaces`).
|
|
207
|
+
*
|
|
208
|
+
* - **Postgres**: an explicit `namespace unbound { … }` block lowers
|
|
209
|
+
* to the framework sentinel `__unbound__` — the slot whose binding
|
|
210
|
+
* the connection's `search_path` resolves at runtime. Every other
|
|
211
|
+
* explicit bucket name (e.g. `auth`, `public`) passes through as a
|
|
212
|
+
* named schema id. The implicit `__unspecified__` bucket — top-level
|
|
213
|
+
* declarations outside any `namespace { … }` block — leaves the
|
|
214
|
+
* coordinate unset; downstream consumers treat unset as the
|
|
215
|
+
* late-bound default, and TS / PSL authoring stay byte-identical
|
|
216
|
+
* on single-namespace contracts. (A future round will add a
|
|
217
|
+
* target-default-namespace surface so `__unspecified__` lowers to
|
|
218
|
+
* `public` consistently on both authoring paths.)
|
|
219
|
+
* - **SQLite**: SQLite has no schema concept; every namespace
|
|
220
|
+
* collapses to the late-bound default. The namespace-block
|
|
221
|
+
* validation step (above) has already rejected any explicit
|
|
222
|
+
* `namespace { … }` block on SQLite, so the only bucket the
|
|
223
|
+
* lowering ever sees there is `__unspecified__`.
|
|
224
|
+
*
|
|
225
|
+
* Returns `undefined` for targets / bucket names with no explicit
|
|
226
|
+
* namespaceId to assign — callers leave the model's `namespaceId`
|
|
227
|
+
* slot empty (which means the late-bound default at the `StorageTable`
|
|
228
|
+
* layer; emitted JSON omits the field).
|
|
229
|
+
*/
|
|
230
|
+
function resolveNamespaceIdForSqlTarget(input: {
|
|
231
|
+
readonly bucketName: string;
|
|
232
|
+
readonly targetId: string;
|
|
233
|
+
}): string | undefined {
|
|
234
|
+
if (input.targetId !== 'postgres') {
|
|
235
|
+
return undefined;
|
|
236
|
+
}
|
|
237
|
+
if (input.bucketName === UNSPECIFIED_PSL_NAMESPACE_NAME) {
|
|
238
|
+
return undefined;
|
|
239
|
+
}
|
|
240
|
+
if (input.bucketName === 'unbound') {
|
|
241
|
+
return '__unbound__';
|
|
242
|
+
}
|
|
243
|
+
return input.bucketName;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function validateNamespaceBlocksForSqlTarget(input: {
|
|
247
|
+
readonly namespaces: readonly PslNamespace[];
|
|
248
|
+
readonly targetId: string;
|
|
249
|
+
readonly sourceId: string;
|
|
250
|
+
readonly diagnostics: ContractSourceDiagnostic[];
|
|
251
|
+
}): void {
|
|
252
|
+
if (input.targetId === 'sqlite') {
|
|
253
|
+
for (const namespace of input.namespaces) {
|
|
254
|
+
if (namespace.name === UNSPECIFIED_PSL_NAMESPACE_NAME) {
|
|
255
|
+
continue;
|
|
256
|
+
}
|
|
257
|
+
input.diagnostics.push({
|
|
258
|
+
code: 'PSL_UNSUPPORTED_NAMESPACE_BLOCK',
|
|
259
|
+
message: `SQLite does not support \`namespace ${namespace.name} { … }\` blocks (SQLite has no schema concept; declare models at the document top level instead).`,
|
|
260
|
+
sourceId: input.sourceId,
|
|
261
|
+
span: namespace.span,
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
if (input.targetId === 'postgres') {
|
|
268
|
+
const namedBlocks = input.namespaces.filter((ns) => ns.name !== UNSPECIFIED_PSL_NAMESPACE_NAME);
|
|
269
|
+
const hasUnbound = namedBlocks.some((ns) => ns.name === 'unbound');
|
|
270
|
+
const hasSibling = namedBlocks.some((ns) => ns.name !== 'unbound');
|
|
271
|
+
if (hasUnbound && hasSibling) {
|
|
272
|
+
const unboundBlock = namedBlocks.find((ns) => ns.name === 'unbound');
|
|
273
|
+
input.diagnostics.push({
|
|
274
|
+
code: 'PSL_RESERVED_NAMESPACE_NAME',
|
|
275
|
+
message:
|
|
276
|
+
'Namespace "unbound" is reserved for the late-binding sentinel mapping and cannot appear alongside other named namespace blocks. ' +
|
|
277
|
+
'Use `namespace unbound { … }` alone (no sibling named namespaces) for late-binding multi-tenant contracts.',
|
|
278
|
+
sourceId: input.sourceId,
|
|
279
|
+
...ifDefined('span', unboundBlock?.span),
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
163
285
|
interface ProcessEnumDeclarationsInput {
|
|
164
286
|
readonly enums: readonly PslEnum[];
|
|
165
287
|
readonly sourceId: string;
|
|
@@ -468,6 +590,8 @@ interface BuildModelNodeInput {
|
|
|
468
590
|
readonly scalarTypeDescriptors: ReadonlyMap<string, ColumnDescriptor>;
|
|
469
591
|
readonly sourceId: string;
|
|
470
592
|
readonly diagnostics: ContractSourceDiagnostic[];
|
|
593
|
+
/** Resolved namespace id keyed by model name — used to stamp the target namespace on FKs. */
|
|
594
|
+
readonly modelNamespaceIds: ReadonlyMap<string, string>;
|
|
471
595
|
}
|
|
472
596
|
|
|
473
597
|
interface BuildModelNodeResult {
|
|
@@ -812,16 +936,37 @@ function buildModelNodeFromPsl(input: BuildModelNodeInput): BuildModelNodeResult
|
|
|
812
936
|
continue;
|
|
813
937
|
}
|
|
814
938
|
|
|
815
|
-
|
|
939
|
+
const { typeName: fieldTypeName, typeNamespaceId: fieldTypeNamespaceId } =
|
|
940
|
+
relationAttribute.field;
|
|
941
|
+
const qualifiedTypeName = fieldTypeNamespaceId
|
|
942
|
+
? `${fieldTypeNamespaceId}.${fieldTypeName}`
|
|
943
|
+
: fieldTypeName;
|
|
944
|
+
|
|
945
|
+
if (!input.modelNames.has(fieldTypeName)) {
|
|
816
946
|
diagnostics.push({
|
|
817
947
|
code: 'PSL_INVALID_RELATION_TARGET',
|
|
818
|
-
message: `Relation field "${model.name}.${relationAttribute.field.name}" references unknown model "${
|
|
948
|
+
message: `Relation field "${model.name}.${relationAttribute.field.name}" references unknown model "${qualifiedTypeName}"`,
|
|
819
949
|
sourceId,
|
|
820
950
|
span: relationAttribute.field.span,
|
|
821
951
|
});
|
|
822
952
|
continue;
|
|
823
953
|
}
|
|
824
954
|
|
|
955
|
+
if (fieldTypeNamespaceId !== undefined) {
|
|
956
|
+
const resolvedTargetNamespaceId = input.modelNamespaceIds.get(fieldTypeName);
|
|
957
|
+
const normalizedQualifier =
|
|
958
|
+
fieldTypeNamespaceId === 'unbound' ? '__unbound__' : fieldTypeNamespaceId;
|
|
959
|
+
if (resolvedTargetNamespaceId !== normalizedQualifier) {
|
|
960
|
+
diagnostics.push({
|
|
961
|
+
code: 'PSL_INVALID_RELATION_TARGET',
|
|
962
|
+
message: `Relation field "${model.name}.${relationAttribute.field.name}" references unknown model "${qualifiedTypeName}"`,
|
|
963
|
+
sourceId,
|
|
964
|
+
span: relationAttribute.field.span,
|
|
965
|
+
});
|
|
966
|
+
continue;
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
|
|
825
970
|
const parsedRelation = parseRelationAttribute({
|
|
826
971
|
attribute: relationAttribute.relation,
|
|
827
972
|
modelName: model.name,
|
|
@@ -842,11 +987,11 @@ function buildModelNodeFromPsl(input: BuildModelNodeInput): BuildModelNodeResult
|
|
|
842
987
|
continue;
|
|
843
988
|
}
|
|
844
989
|
|
|
845
|
-
const targetMapping = input.modelMappings.get(
|
|
990
|
+
const targetMapping = input.modelMappings.get(fieldTypeName);
|
|
846
991
|
if (!targetMapping) {
|
|
847
992
|
diagnostics.push({
|
|
848
993
|
code: 'PSL_INVALID_RELATION_TARGET',
|
|
849
|
-
message: `Relation field "${model.name}.${relationAttribute.field.name}" references unknown model "${
|
|
994
|
+
message: `Relation field "${model.name}.${relationAttribute.field.name}" references unknown model "${qualifiedTypeName}"`,
|
|
850
995
|
sourceId,
|
|
851
996
|
span: relationAttribute.field.span,
|
|
852
997
|
});
|
|
@@ -910,12 +1055,14 @@ function buildModelNodeFromPsl(input: BuildModelNodeInput): BuildModelNodeResult
|
|
|
910
1055
|
})
|
|
911
1056
|
: undefined;
|
|
912
1057
|
|
|
1058
|
+
const targetNamespaceId = input.modelNamespaceIds.get(targetMapping.model.name);
|
|
913
1059
|
foreignKeyNodes.push({
|
|
914
1060
|
columns: localColumns,
|
|
915
1061
|
references: {
|
|
916
1062
|
model: targetMapping.model.name,
|
|
917
1063
|
table: targetMapping.tableName,
|
|
918
1064
|
columns: referencedColumns,
|
|
1065
|
+
...ifDefined('namespaceId', targetNamespaceId),
|
|
919
1066
|
},
|
|
920
1067
|
...ifDefined('name', parsedRelation.constraintName),
|
|
921
1068
|
...ifDefined('onDelete', onDelete),
|
|
@@ -1298,9 +1445,61 @@ export function interpretPslDocumentToSqlContract(
|
|
|
1298
1445
|
}
|
|
1299
1446
|
|
|
1300
1447
|
const diagnostics: ContractSourceDiagnostic[] = mapParserDiagnostics(input.document);
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1448
|
+
validateNamespaceBlocksForSqlTarget({
|
|
1449
|
+
namespaces: input.document.ast.namespaces,
|
|
1450
|
+
targetId: input.target.targetId,
|
|
1451
|
+
sourceId,
|
|
1452
|
+
diagnostics,
|
|
1453
|
+
});
|
|
1454
|
+
// Per-target namespace resolution: walk each AST bucket once,
|
|
1455
|
+
// recording every model's resolved `namespaceId` for later threading
|
|
1456
|
+
// into the `ModelNode` build. The resolution rules are target-local
|
|
1457
|
+
// (see `resolveNamespaceIdForSqlTarget`); the flattened model list
|
|
1458
|
+
// remains the input to the rest of the interpreter so non-namespace
|
|
1459
|
+
// concerns stay structurally identical to before.
|
|
1460
|
+
const models: PslModel[] = [];
|
|
1461
|
+
const modelNamespaceIds = new Map<string, string>();
|
|
1462
|
+
for (const namespace of input.document.ast.namespaces) {
|
|
1463
|
+
const resolvedNamespaceId = resolveNamespaceIdForSqlTarget({
|
|
1464
|
+
bucketName: namespace.name,
|
|
1465
|
+
targetId: input.target.targetId,
|
|
1466
|
+
});
|
|
1467
|
+
for (const model of namespace.models) {
|
|
1468
|
+
models.push(model);
|
|
1469
|
+
if (resolvedNamespaceId !== undefined) {
|
|
1470
|
+
modelNamespaceIds.set(model.name, resolvedNamespaceId);
|
|
1471
|
+
}
|
|
1472
|
+
}
|
|
1473
|
+
}
|
|
1474
|
+
// Top-level enums (the __unspecified__ bucket) route to `storageTypes`;
|
|
1475
|
+
// enums inside a named namespace block route to `namespaceTypes[nsId]`.
|
|
1476
|
+
const topLevelEnums = input.document.ast.namespaces
|
|
1477
|
+
.filter((ns) => ns.name === UNSPECIFIED_PSL_NAMESPACE_NAME)
|
|
1478
|
+
.flatMap((ns) => ns.enums);
|
|
1479
|
+
const namedNamespaceEnumsByNsId = new Map<string, readonly PslEnum[]>();
|
|
1480
|
+
for (const ns of input.document.ast.namespaces) {
|
|
1481
|
+
if (ns.name === UNSPECIFIED_PSL_NAMESPACE_NAME || ns.enums.length === 0) {
|
|
1482
|
+
continue;
|
|
1483
|
+
}
|
|
1484
|
+
const resolvedId = resolveNamespaceIdForSqlTarget({
|
|
1485
|
+
bucketName: ns.name,
|
|
1486
|
+
targetId: input.target.targetId,
|
|
1487
|
+
});
|
|
1488
|
+
if (resolvedId === undefined) {
|
|
1489
|
+
continue;
|
|
1490
|
+
}
|
|
1491
|
+
// Read-then-merge so that any future change to the PSL parser (or to
|
|
1492
|
+
// `resolveNamespaceIdForSqlTarget`) that produces two AST entries
|
|
1493
|
+
// resolving to the same `resolvedId` would accumulate their enums
|
|
1494
|
+
// rather than silently dropping the earlier set. Today the parser
|
|
1495
|
+
// already merges duplicate `namespace <name> { … }` blocks into a
|
|
1496
|
+
// single AST entry per name, so this loop sees one `ns` per
|
|
1497
|
+
// resolvedId and the merge degrades to a plain set.
|
|
1498
|
+
const existing = namedNamespaceEnumsByNsId.get(resolvedId) ?? [];
|
|
1499
|
+
namedNamespaceEnumsByNsId.set(resolvedId, [...existing, ...ns.enums]);
|
|
1500
|
+
}
|
|
1501
|
+
|
|
1502
|
+
const compositeTypes = input.document.ast.namespaces.flatMap((ns) => ns.compositeTypes);
|
|
1304
1503
|
const modelNames = new Set(models.map((model) => model.name));
|
|
1305
1504
|
const compositeTypeNames = new Set(compositeTypes.map((ct) => ct.name));
|
|
1306
1505
|
const composedExtensions = new Set(input.composedExtensionPacks ?? []);
|
|
@@ -1312,21 +1511,50 @@ export function interpretPslDocumentToSqlContract(
|
|
|
1312
1511
|
generatorDescriptorById.set(descriptor.id, descriptor);
|
|
1313
1512
|
}
|
|
1314
1513
|
|
|
1514
|
+
const enumEntityDescriptor = getAuthoringEntity(input.authoringContributions, ['enum']);
|
|
1515
|
+
const enumEntityContext = {
|
|
1516
|
+
family: input.target.familyId,
|
|
1517
|
+
target: input.target.targetId,
|
|
1518
|
+
};
|
|
1519
|
+
|
|
1315
1520
|
const enumResult = processEnumDeclarations({
|
|
1316
|
-
enums,
|
|
1521
|
+
enums: topLevelEnums,
|
|
1317
1522
|
sourceId,
|
|
1318
|
-
enumEntityDescriptor
|
|
1319
|
-
entityContext:
|
|
1320
|
-
family: input.target.familyId,
|
|
1321
|
-
target: input.target.targetId,
|
|
1322
|
-
},
|
|
1523
|
+
enumEntityDescriptor,
|
|
1524
|
+
entityContext: enumEntityContext,
|
|
1323
1525
|
diagnostics,
|
|
1324
1526
|
});
|
|
1325
1527
|
|
|
1528
|
+
// Process enums declared in named namespace blocks and collect them into
|
|
1529
|
+
// `namespaceTypes` keyed by the resolved namespace id.
|
|
1530
|
+
const allEnumTypeDescriptors = new Map(enumResult.enumTypeDescriptors);
|
|
1531
|
+
const namespaceEnumStorageTypes: Record<string, Record<string, PostgresEnumStorageEntry>> = {};
|
|
1532
|
+
for (const [nsId, nsEnums] of namedNamespaceEnumsByNsId) {
|
|
1533
|
+
const nsEnumResult = processEnumDeclarations({
|
|
1534
|
+
enums: nsEnums,
|
|
1535
|
+
sourceId,
|
|
1536
|
+
enumEntityDescriptor,
|
|
1537
|
+
entityContext: enumEntityContext,
|
|
1538
|
+
diagnostics,
|
|
1539
|
+
});
|
|
1540
|
+
for (const [name, descriptor] of nsEnumResult.enumTypeDescriptors) {
|
|
1541
|
+
allEnumTypeDescriptors.set(name, descriptor);
|
|
1542
|
+
}
|
|
1543
|
+
const nsEntries: Record<string, PostgresEnumStorageEntry> = {};
|
|
1544
|
+
for (const [name, entry] of Object.entries(nsEnumResult.storageTypes)) {
|
|
1545
|
+
if (isPostgresEnumStorageEntry(entry)) {
|
|
1546
|
+
nsEntries[name] = entry;
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1549
|
+
if (Object.keys(nsEntries).length > 0) {
|
|
1550
|
+
namespaceEnumStorageTypes[nsId] = nsEntries;
|
|
1551
|
+
}
|
|
1552
|
+
}
|
|
1553
|
+
|
|
1326
1554
|
const namedTypeResult = resolveNamedTypeDeclarations({
|
|
1327
1555
|
declarations: input.document.ast.types?.declarations ?? [],
|
|
1328
1556
|
sourceId,
|
|
1329
|
-
enumTypeDescriptors:
|
|
1557
|
+
enumTypeDescriptors: allEnumTypeDescriptors,
|
|
1330
1558
|
scalarTypeDescriptors: input.scalarTypeDescriptors,
|
|
1331
1559
|
composedExtensions,
|
|
1332
1560
|
familyId: input.target.familyId,
|
|
@@ -1354,7 +1582,7 @@ export function interpretPslDocumentToSqlContract(
|
|
|
1354
1582
|
modelMappings,
|
|
1355
1583
|
modelNames,
|
|
1356
1584
|
compositeTypeNames,
|
|
1357
|
-
enumTypeDescriptors:
|
|
1585
|
+
enumTypeDescriptors: allEnumTypeDescriptors,
|
|
1358
1586
|
namedTypeDescriptors: namedTypeResult.namedTypeDescriptors,
|
|
1359
1587
|
composedExtensions,
|
|
1360
1588
|
familyId: input.target.familyId,
|
|
@@ -1365,8 +1593,14 @@ export function interpretPslDocumentToSqlContract(
|
|
|
1365
1593
|
scalarTypeDescriptors: input.scalarTypeDescriptors,
|
|
1366
1594
|
sourceId,
|
|
1367
1595
|
diagnostics,
|
|
1596
|
+
modelNamespaceIds,
|
|
1368
1597
|
});
|
|
1369
|
-
|
|
1598
|
+
const resolvedNamespaceId = modelNamespaceIds.get(model.name);
|
|
1599
|
+
modelNodes.push(
|
|
1600
|
+
resolvedNamespaceId !== undefined
|
|
1601
|
+
? { ...result.modelNode, namespaceId: resolvedNamespaceId }
|
|
1602
|
+
: result.modelNode,
|
|
1603
|
+
);
|
|
1370
1604
|
fkRelationMetadata.push(...result.fkRelationMetadata);
|
|
1371
1605
|
backrelationCandidates.push(...result.backrelationCandidates);
|
|
1372
1606
|
modelResolvedFields.set(model.name, result.resolvedFields);
|
|
@@ -1389,7 +1623,7 @@ export function interpretPslDocumentToSqlContract(
|
|
|
1389
1623
|
|
|
1390
1624
|
const valueObjects = buildValueObjects({
|
|
1391
1625
|
compositeTypes,
|
|
1392
|
-
enumTypeDescriptors:
|
|
1626
|
+
enumTypeDescriptors: allEnumTypeDescriptors,
|
|
1393
1627
|
namedTypeDescriptors: namedTypeResult.namedTypeDescriptors,
|
|
1394
1628
|
scalarTypeDescriptors: input.scalarTypeDescriptors,
|
|
1395
1629
|
composedExtensions,
|
|
@@ -1418,6 +1652,10 @@ export function interpretPslDocumentToSqlContract(
|
|
|
1418
1652
|
),
|
|
1419
1653
|
),
|
|
1420
1654
|
...(Object.keys(storageTypes).length > 0 ? { storageTypes } : {}),
|
|
1655
|
+
...(Object.keys(namespaceEnumStorageTypes).length > 0
|
|
1656
|
+
? { namespaceTypes: namespaceEnumStorageTypes }
|
|
1657
|
+
: {}),
|
|
1658
|
+
...ifDefined('createNamespace', input.createNamespace),
|
|
1421
1659
|
models: modelNodes.map((model) => ({
|
|
1422
1660
|
...model,
|
|
1423
1661
|
...(modelRelations.has(model.modelName)
|