@prisma-next/sql-contract-psl 0.14.0-dev.4 → 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.
- package/README.md +11 -7
- package/dist/index.d.mts +7 -3
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{interpreter-B0BsCLKT.mjs → interpreter-kDkm5opL.mjs} +260 -226
- package/dist/interpreter-kDkm5opL.mjs.map +1 -0
- package/dist/provider.d.mts.map +1 -1
- package/dist/provider.mjs +21 -7
- package/dist/provider.mjs.map +1 -1
- package/package.json +12 -12
- package/src/interpreter.ts +139 -322
- package/src/provider.ts +37 -9
- package/src/psl-attribute-parsing.ts +18 -14
- package/src/psl-authoring-arguments.ts +2 -2
- package/src/psl-column-resolution.ts +17 -15
- package/src/psl-field-resolution.ts +28 -20
- package/src/psl-named-type-resolution.ts +250 -0
- package/src/psl-relation-resolution.ts +5 -4
- package/dist/interpreter-B0BsCLKT.mjs.map +0 -1
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { crossRef } from "@prisma-next/contract/types";
|
|
2
|
-
import { hasRegisteredFieldNamespace, instantiateAuthoringEntityType, instantiateAuthoringFieldPreset, instantiateAuthoringTypeConstructor, isAuthoringEntityTypeDescriptor, isAuthoringFieldPresetDescriptor, isAuthoringTypeConstructorDescriptor, validateAuthoringHelperArguments } from "@prisma-next/framework-components/authoring";
|
|
3
|
-
import {
|
|
2
|
+
import { hasRegisteredFieldNamespace, instantiateAuthoringEntityType, instantiateAuthoringFieldPreset, instantiateAuthoringTypeConstructor, isAuthoringEntityTypeDescriptor, isAuthoringFieldPresetDescriptor, isAuthoringPslBlockDescriptor, isAuthoringTypeConstructorDescriptor, validateAuthoringHelperArguments } from "@prisma-next/framework-components/authoring";
|
|
3
|
+
import { keywordPslSpan, nodePslSpan, parseQuotedStringLiteral } from "@prisma-next/psl-parser";
|
|
4
4
|
import { buildSqlContractFromDefinition } from "@prisma-next/sql-contract-ts/contract-builder";
|
|
5
|
+
import { assertDefined, invariant } from "@prisma-next/utils/assertions";
|
|
5
6
|
import { blindCast } from "@prisma-next/utils/casts";
|
|
6
7
|
import { ifDefined } from "@prisma-next/utils/defined";
|
|
7
8
|
import { notOk, ok } from "@prisma-next/utils/result";
|
|
8
|
-
import { getPositionalArgument, parseQuotedStringLiteral } from "@prisma-next/psl-parser";
|
|
9
|
-
import { assertDefined, invariant } from "@prisma-next/utils/assertions";
|
|
10
9
|
//#region src/psl-attribute-parsing.ts
|
|
10
|
+
function getPositionalArgument(attribute, index = 0) {
|
|
11
|
+
return attribute.args.filter((arg) => arg.kind === "positional")[index]?.value;
|
|
12
|
+
}
|
|
11
13
|
function lowerFirst(value) {
|
|
12
14
|
if (value.length === 0) return value;
|
|
13
15
|
return value[0]?.toLowerCase() + value.slice(1);
|
|
@@ -931,7 +933,7 @@ function resolvePslTypeConstructorDescriptor(input) {
|
|
|
931
933
|
*
|
|
932
934
|
* Symmetric with `instantiatePslTypeConstructor` but richer: a field preset can contribute `default`, `executionDefaults`, `id`, `unique`, and `nullable` in addition to the storage-type triple. PSL → typed-args coercion happens here (via `mapPslHelperArgs`) so that `instantiateAuthoringFieldPreset` itself stays typed-input-only and TS keeps its zero-runtime-validation cost.
|
|
933
935
|
*/
|
|
934
|
-
function
|
|
936
|
+
function instantiateFieldPreset(input) {
|
|
935
937
|
const helperPath = input.call.path.join(".");
|
|
936
938
|
const args = mapPslHelperArgs({
|
|
937
939
|
args: input.call.args,
|
|
@@ -970,10 +972,14 @@ function instantiatePslFieldPreset(input) {
|
|
|
970
972
|
}
|
|
971
973
|
}
|
|
972
974
|
function resolveFieldTypeDescriptor(input) {
|
|
975
|
+
if (input.field.malformedType) return {
|
|
976
|
+
ok: false,
|
|
977
|
+
alreadyReported: true
|
|
978
|
+
};
|
|
973
979
|
if (input.field.typeConstructor) {
|
|
974
980
|
const presetDescriptor = getAuthoringFieldPreset(input.authoringContributions, input.field.typeConstructor.path);
|
|
975
981
|
if (presetDescriptor) {
|
|
976
|
-
const instantiated =
|
|
982
|
+
const instantiated = instantiateFieldPreset({
|
|
977
983
|
call: input.field.typeConstructor,
|
|
978
984
|
descriptor: presetDescriptor,
|
|
979
985
|
diagnostics: input.diagnostics,
|
|
@@ -1301,7 +1307,6 @@ function lowerDefaultForField(input) {
|
|
|
1301
1307
|
return { executionDefaults: { onCreate: lowered.value.generated } };
|
|
1302
1308
|
}
|
|
1303
1309
|
function resolveColumnDescriptor(field, enumTypeDescriptors, namedTypeDescriptors, scalarTypeDescriptors) {
|
|
1304
|
-
if (field.typeRef && namedTypeDescriptors.has(field.typeRef)) return namedTypeDescriptors.get(field.typeRef);
|
|
1305
1310
|
if (namedTypeDescriptors.has(field.typeName)) return namedTypeDescriptors.get(field.typeName);
|
|
1306
1311
|
if (enumTypeDescriptors.has(field.typeName)) return enumTypeDescriptors.get(field.typeName);
|
|
1307
1312
|
return scalarTypeDescriptors.get(field.typeName);
|
|
@@ -1309,8 +1314,18 @@ function resolveColumnDescriptor(field, enumTypeDescriptors, namedTypeDescriptor
|
|
|
1309
1314
|
//#endregion
|
|
1310
1315
|
//#region src/psl-field-resolution.ts
|
|
1311
1316
|
function lowerEnumDefaultForField(input) {
|
|
1312
|
-
const
|
|
1313
|
-
|
|
1317
|
+
const positionalEntries = input.defaultAttribute.args.filter((arg) => arg.kind === "positional");
|
|
1318
|
+
const hasNamedEntries = input.defaultAttribute.args.some((arg) => arg.kind === "named");
|
|
1319
|
+
const expressionEntry = positionalEntries[0];
|
|
1320
|
+
if (hasNamedEntries || positionalEntries.length !== 1 || expressionEntry === void 0) {
|
|
1321
|
+
input.diagnostics.push({
|
|
1322
|
+
code: "PSL_INVALID_DEFAULT_FUNCTION_ARGUMENT",
|
|
1323
|
+
message: `Field "${input.modelName}.${input.fieldName}" @default on an enum field expects exactly one positional enum member argument.`,
|
|
1324
|
+
sourceId: input.sourceId,
|
|
1325
|
+
span: input.defaultAttribute.span
|
|
1326
|
+
});
|
|
1327
|
+
return {};
|
|
1328
|
+
}
|
|
1314
1329
|
const raw = expressionEntry.value.trim();
|
|
1315
1330
|
const isQuotedString = /^(['"]).*\1$/.test(raw);
|
|
1316
1331
|
const isFunctionCall = raw.includes("(") && raw.endsWith(")");
|
|
@@ -1414,7 +1429,7 @@ function extractFieldConstraintNames(input) {
|
|
|
1414
1429
|
function collectResolvedFields(input) {
|
|
1415
1430
|
const { model, mapping, enumTypeDescriptors, namedTypeDescriptors, modelNames, compositeTypeNames, composedExtensions, authoringContributions, familyId, targetId, defaultFunctionRegistry, generatorDescriptorById, diagnostics, sourceId, scalarTypeDescriptors, enumHandles } = input;
|
|
1416
1431
|
const resolvedFields = [];
|
|
1417
|
-
for (const field of model.fields) {
|
|
1432
|
+
for (const field of Object.values(model.fields)) {
|
|
1418
1433
|
const isModelField = modelNames.has(field.typeName);
|
|
1419
1434
|
if (field.list && isModelField) continue;
|
|
1420
1435
|
validateFieldAttributes({
|
|
@@ -1534,7 +1549,7 @@ function collectResolvedFields(input) {
|
|
|
1534
1549
|
});
|
|
1535
1550
|
continue;
|
|
1536
1551
|
}
|
|
1537
|
-
const fieldUsesNamedType =
|
|
1552
|
+
const fieldUsesNamedType = namedTypeDescriptors.has(field.typeName);
|
|
1538
1553
|
if (loweredOnCreate && !fieldUsesNamedType) {
|
|
1539
1554
|
const generatedDescriptor = generatorDescriptorById.get(loweredOnCreate.id)?.resolveGeneratedColumnDescriptor?.({ generated: loweredOnCreate });
|
|
1540
1555
|
if (generatedDescriptor) descriptor = generatedDescriptor;
|
|
@@ -1571,6 +1586,7 @@ function collectResolvedFields(input) {
|
|
|
1571
1586
|
field,
|
|
1572
1587
|
columnName: mappedColumnName,
|
|
1573
1588
|
descriptor,
|
|
1589
|
+
nullable: presetContributions?.nullable ?? field.optional,
|
|
1574
1590
|
...ifDefined("defaultValue", fieldDefaultValue),
|
|
1575
1591
|
...ifDefined("executionDefaults", fieldExecutionDefaults),
|
|
1576
1592
|
isId: isIdField || Boolean(presetContributions?.id),
|
|
@@ -1596,7 +1612,7 @@ function buildModelMappings(modelEntries, defaultNamespaceId, diagnostics, sourc
|
|
|
1596
1612
|
span: model.span
|
|
1597
1613
|
});
|
|
1598
1614
|
const fieldColumns = /* @__PURE__ */ new Map();
|
|
1599
|
-
for (const field of model.fields) {
|
|
1615
|
+
for (const field of Object.values(model.fields)) {
|
|
1600
1616
|
const columnName = parseMapName({
|
|
1601
1617
|
attribute: getAttribute(field.attributes, "map"),
|
|
1602
1618
|
defaultValue: field.name,
|
|
@@ -1616,6 +1632,171 @@ function buildModelMappings(modelEntries, defaultNamespaceId, diagnostics, sourc
|
|
|
1616
1632
|
return result;
|
|
1617
1633
|
}
|
|
1618
1634
|
//#endregion
|
|
1635
|
+
//#region src/psl-named-type-resolution.ts
|
|
1636
|
+
function validateNamedTypeAttributes(input) {
|
|
1637
|
+
const [dbNativeTypeAttribute, ...extraDbNativeTypeAttributes] = input.allowDbNativeType ? input.declaration.attributes.filter((attribute) => attribute.name.startsWith("db.")) : [];
|
|
1638
|
+
let hasUnsupportedNamedTypeAttribute = false;
|
|
1639
|
+
for (const extra of extraDbNativeTypeAttributes) {
|
|
1640
|
+
input.diagnostics.push({
|
|
1641
|
+
code: "PSL_INVALID_ATTRIBUTE_ARGUMENT",
|
|
1642
|
+
message: `Named type "${input.declaration.name}" can declare at most one @db.* attribute`,
|
|
1643
|
+
sourceId: input.sourceId,
|
|
1644
|
+
span: extra.span
|
|
1645
|
+
});
|
|
1646
|
+
hasUnsupportedNamedTypeAttribute = true;
|
|
1647
|
+
}
|
|
1648
|
+
for (const attribute of input.declaration.attributes) {
|
|
1649
|
+
if (input.allowDbNativeType && attribute.name.startsWith("db.")) continue;
|
|
1650
|
+
const uncomposedNamespace = checkUncomposedNamespace(attribute.name, input.composedExtensions, {
|
|
1651
|
+
familyId: input.familyId,
|
|
1652
|
+
targetId: input.targetId,
|
|
1653
|
+
authoringContributions: input.authoringContributions
|
|
1654
|
+
});
|
|
1655
|
+
if (uncomposedNamespace) {
|
|
1656
|
+
reportUncomposedNamespace({
|
|
1657
|
+
subjectLabel: `Attribute "@${attribute.name}"`,
|
|
1658
|
+
namespace: uncomposedNamespace,
|
|
1659
|
+
sourceId: input.sourceId,
|
|
1660
|
+
span: attribute.span,
|
|
1661
|
+
diagnostics: input.diagnostics
|
|
1662
|
+
});
|
|
1663
|
+
hasUnsupportedNamedTypeAttribute = true;
|
|
1664
|
+
continue;
|
|
1665
|
+
}
|
|
1666
|
+
input.diagnostics.push({
|
|
1667
|
+
code: "PSL_UNSUPPORTED_NAMED_TYPE_ATTRIBUTE",
|
|
1668
|
+
message: `Named type "${input.declaration.name}" uses unsupported attribute "${attribute.name}"`,
|
|
1669
|
+
sourceId: input.sourceId,
|
|
1670
|
+
span: attribute.span
|
|
1671
|
+
});
|
|
1672
|
+
hasUnsupportedNamedTypeAttribute = true;
|
|
1673
|
+
}
|
|
1674
|
+
return {
|
|
1675
|
+
dbNativeTypeAttribute,
|
|
1676
|
+
hasUnsupportedNamedTypeAttribute
|
|
1677
|
+
};
|
|
1678
|
+
}
|
|
1679
|
+
function resolveNamedTypeDeclarations(input) {
|
|
1680
|
+
const storageTypeEntries = [];
|
|
1681
|
+
const namedTypeDescriptors = /* @__PURE__ */ new Map();
|
|
1682
|
+
for (const declaration of input.declarations) {
|
|
1683
|
+
if (declaration.isConstructor) {
|
|
1684
|
+
const typeConstructor = declaration.typeConstructor;
|
|
1685
|
+
if (typeConstructor === void 0) {
|
|
1686
|
+
input.diagnostics.push({
|
|
1687
|
+
code: "PSL_UNSUPPORTED_NAMED_TYPE_BASE",
|
|
1688
|
+
message: `Named type "${declaration.name}" must declare a base type or constructor`,
|
|
1689
|
+
sourceId: input.sourceId,
|
|
1690
|
+
span: declaration.span
|
|
1691
|
+
});
|
|
1692
|
+
continue;
|
|
1693
|
+
}
|
|
1694
|
+
const { hasUnsupportedNamedTypeAttribute } = validateNamedTypeAttributes({
|
|
1695
|
+
declaration,
|
|
1696
|
+
sourceId: input.sourceId,
|
|
1697
|
+
diagnostics: input.diagnostics,
|
|
1698
|
+
composedExtensions: input.composedExtensions,
|
|
1699
|
+
authoringContributions: input.authoringContributions,
|
|
1700
|
+
allowDbNativeType: false,
|
|
1701
|
+
familyId: input.familyId,
|
|
1702
|
+
targetId: input.targetId
|
|
1703
|
+
});
|
|
1704
|
+
if (hasUnsupportedNamedTypeAttribute) continue;
|
|
1705
|
+
const helperPath = typeConstructor.path.join(".");
|
|
1706
|
+
const descriptor = resolvePslTypeConstructorDescriptor({
|
|
1707
|
+
call: typeConstructor,
|
|
1708
|
+
authoringContributions: input.authoringContributions,
|
|
1709
|
+
composedExtensions: input.composedExtensions,
|
|
1710
|
+
familyId: input.familyId,
|
|
1711
|
+
targetId: input.targetId,
|
|
1712
|
+
diagnostics: input.diagnostics,
|
|
1713
|
+
sourceId: input.sourceId,
|
|
1714
|
+
unsupportedCode: "PSL_UNSUPPORTED_NAMED_TYPE_CONSTRUCTOR",
|
|
1715
|
+
unsupportedMessage: `Named type "${declaration.name}" references unsupported constructor "${helperPath}"`
|
|
1716
|
+
});
|
|
1717
|
+
if (!descriptor) continue;
|
|
1718
|
+
const storageType = instantiatePslTypeConstructor({
|
|
1719
|
+
call: typeConstructor,
|
|
1720
|
+
descriptor,
|
|
1721
|
+
diagnostics: input.diagnostics,
|
|
1722
|
+
sourceId: input.sourceId,
|
|
1723
|
+
entityLabel: `Named type "${declaration.name}"`
|
|
1724
|
+
});
|
|
1725
|
+
if (!storageType) continue;
|
|
1726
|
+
namedTypeDescriptors.set(declaration.name, toNamedTypeFieldDescriptor(declaration.name, storageType));
|
|
1727
|
+
storageTypeEntries.push([declaration.name, {
|
|
1728
|
+
kind: "codec-instance",
|
|
1729
|
+
codecId: storageType.codecId,
|
|
1730
|
+
nativeType: storageType.nativeType,
|
|
1731
|
+
typeParams: storageType.typeParams ?? {}
|
|
1732
|
+
}]);
|
|
1733
|
+
continue;
|
|
1734
|
+
}
|
|
1735
|
+
const baseType = declaration.baseType;
|
|
1736
|
+
if (baseType === void 0) {
|
|
1737
|
+
input.diagnostics.push({
|
|
1738
|
+
code: "PSL_UNSUPPORTED_NAMED_TYPE_BASE",
|
|
1739
|
+
message: `Named type "${declaration.name}" must declare a base type or constructor`,
|
|
1740
|
+
sourceId: input.sourceId,
|
|
1741
|
+
span: declaration.span
|
|
1742
|
+
});
|
|
1743
|
+
continue;
|
|
1744
|
+
}
|
|
1745
|
+
const baseDescriptor = input.enumTypeDescriptors.get(baseType) ?? input.scalarTypeDescriptors.get(baseType);
|
|
1746
|
+
if (!baseDescriptor) {
|
|
1747
|
+
input.diagnostics.push({
|
|
1748
|
+
code: "PSL_UNSUPPORTED_NAMED_TYPE_BASE",
|
|
1749
|
+
message: `Named type "${declaration.name}" references unsupported base type "${baseType}"`,
|
|
1750
|
+
sourceId: input.sourceId,
|
|
1751
|
+
span: declaration.span
|
|
1752
|
+
});
|
|
1753
|
+
continue;
|
|
1754
|
+
}
|
|
1755
|
+
const { dbNativeTypeAttribute, hasUnsupportedNamedTypeAttribute } = validateNamedTypeAttributes({
|
|
1756
|
+
declaration,
|
|
1757
|
+
sourceId: input.sourceId,
|
|
1758
|
+
diagnostics: input.diagnostics,
|
|
1759
|
+
composedExtensions: input.composedExtensions,
|
|
1760
|
+
authoringContributions: input.authoringContributions,
|
|
1761
|
+
allowDbNativeType: true,
|
|
1762
|
+
familyId: input.familyId,
|
|
1763
|
+
targetId: input.targetId
|
|
1764
|
+
});
|
|
1765
|
+
if (hasUnsupportedNamedTypeAttribute) continue;
|
|
1766
|
+
if (dbNativeTypeAttribute) {
|
|
1767
|
+
const descriptor = resolveDbNativeTypeAttribute({
|
|
1768
|
+
attribute: dbNativeTypeAttribute,
|
|
1769
|
+
baseType,
|
|
1770
|
+
baseDescriptor,
|
|
1771
|
+
diagnostics: input.diagnostics,
|
|
1772
|
+
sourceId: input.sourceId,
|
|
1773
|
+
entityLabel: `Named type "${declaration.name}"`
|
|
1774
|
+
});
|
|
1775
|
+
if (!descriptor) continue;
|
|
1776
|
+
namedTypeDescriptors.set(declaration.name, toNamedTypeFieldDescriptor(declaration.name, descriptor));
|
|
1777
|
+
storageTypeEntries.push([declaration.name, {
|
|
1778
|
+
kind: "codec-instance",
|
|
1779
|
+
codecId: descriptor.codecId,
|
|
1780
|
+
nativeType: descriptor.nativeType,
|
|
1781
|
+
typeParams: descriptor.typeParams ?? {}
|
|
1782
|
+
}]);
|
|
1783
|
+
continue;
|
|
1784
|
+
}
|
|
1785
|
+
const descriptor = toNamedTypeFieldDescriptor(declaration.name, baseDescriptor);
|
|
1786
|
+
namedTypeDescriptors.set(declaration.name, descriptor);
|
|
1787
|
+
storageTypeEntries.push([declaration.name, {
|
|
1788
|
+
kind: "codec-instance",
|
|
1789
|
+
codecId: baseDescriptor.codecId,
|
|
1790
|
+
nativeType: baseDescriptor.nativeType,
|
|
1791
|
+
typeParams: {}
|
|
1792
|
+
}]);
|
|
1793
|
+
}
|
|
1794
|
+
return {
|
|
1795
|
+
storageTypes: Object.fromEntries(storageTypeEntries),
|
|
1796
|
+
namedTypeDescriptors
|
|
1797
|
+
};
|
|
1798
|
+
}
|
|
1799
|
+
//#endregion
|
|
1619
1800
|
//#region src/psl-relation-resolution.ts
|
|
1620
1801
|
const REFERENTIAL_ACTION_MAP = {
|
|
1621
1802
|
NoAction: "noAction",
|
|
@@ -1869,32 +2050,11 @@ function buildComposedExtensionPackRefs(target, extensionIds, extensionPackRefs
|
|
|
1869
2050
|
version: "0.0.1"
|
|
1870
2051
|
}]));
|
|
1871
2052
|
}
|
|
1872
|
-
function diagnosticDedupKey(diagnostic) {
|
|
1873
|
-
const span = diagnostic.span;
|
|
1874
|
-
const spanKey = span ? `${span.start.offset}:${span.end.offset}:${span.start.line}:${span.end.line}` : "";
|
|
1875
|
-
return `${diagnostic.code}\u0000${diagnostic.sourceId}\u0000${spanKey}\u0000${diagnostic.message}`;
|
|
1876
|
-
}
|
|
1877
|
-
function dedupeDiagnostics(diagnostics) {
|
|
1878
|
-
const seen = /* @__PURE__ */ new Map();
|
|
1879
|
-
for (const diagnostic of diagnostics) {
|
|
1880
|
-
const key = diagnosticDedupKey(diagnostic);
|
|
1881
|
-
if (!seen.has(key)) seen.set(key, diagnostic);
|
|
1882
|
-
}
|
|
1883
|
-
return [...seen.values()];
|
|
1884
|
-
}
|
|
1885
2053
|
function compareStrings(left, right) {
|
|
1886
2054
|
if (left < right) return -1;
|
|
1887
2055
|
if (left > right) return 1;
|
|
1888
2056
|
return 0;
|
|
1889
2057
|
}
|
|
1890
|
-
function mapParserDiagnostics(document) {
|
|
1891
|
-
return document.diagnostics.map((diagnostic) => ({
|
|
1892
|
-
code: diagnostic.code,
|
|
1893
|
-
message: diagnostic.message,
|
|
1894
|
-
sourceId: diagnostic.sourceId,
|
|
1895
|
-
span: diagnostic.span
|
|
1896
|
-
}));
|
|
1897
|
-
}
|
|
1898
2058
|
/**
|
|
1899
2059
|
* Name of the framework-parser synthesised bucket for top-level
|
|
1900
2060
|
* declarations. Re-declared here so the per-target dispatch does not
|
|
@@ -1956,28 +2116,24 @@ function resolveNamespaceIdForSqlTarget(input) {
|
|
|
1956
2116
|
}
|
|
1957
2117
|
function validateNamespaceBlocksForSqlTarget(input) {
|
|
1958
2118
|
if (input.targetId === "sqlite") {
|
|
1959
|
-
for (const namespace of input.namespaces) {
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
span: namespace.span
|
|
1966
|
-
});
|
|
1967
|
-
}
|
|
2119
|
+
for (const namespace of input.namespaces) input.diagnostics.push({
|
|
2120
|
+
code: "PSL_UNSUPPORTED_NAMESPACE_BLOCK",
|
|
2121
|
+
message: `SQLite does not support \`namespace ${namespace.name} { … }\` blocks (SQLite has no schema concept; declare models at the document top level instead).`,
|
|
2122
|
+
sourceId: input.sourceId,
|
|
2123
|
+
span: nodePslSpan(namespace.node.syntax, input.sourceFile)
|
|
2124
|
+
});
|
|
1968
2125
|
return;
|
|
1969
2126
|
}
|
|
1970
2127
|
if (input.targetId === "postgres") {
|
|
1971
|
-
const
|
|
1972
|
-
const
|
|
1973
|
-
const hasSibling = namedBlocks.some((ns) => ns.name !== "unbound");
|
|
2128
|
+
const hasUnbound = input.namespaces.some((ns) => ns.name === "unbound");
|
|
2129
|
+
const hasSibling = input.namespaces.some((ns) => ns.name !== "unbound");
|
|
1974
2130
|
if (hasUnbound && hasSibling) {
|
|
1975
|
-
const unboundBlock =
|
|
2131
|
+
const unboundBlock = input.namespaces.find((ns) => ns.name === "unbound");
|
|
1976
2132
|
input.diagnostics.push({
|
|
1977
2133
|
code: "PSL_RESERVED_NAMESPACE_NAME",
|
|
1978
2134
|
message: "Namespace \"unbound\" is reserved for the late-binding sentinel mapping and cannot appear alongside other named namespace blocks. Use `namespace unbound { … }` alone (no sibling named namespaces) for late-binding multi-tenant contracts.",
|
|
1979
2135
|
sourceId: input.sourceId,
|
|
1980
|
-
...
|
|
2136
|
+
...unboundBlock !== void 0 ? { span: nodePslSpan(unboundBlock.node.syntax, input.sourceFile) } : {}
|
|
1981
2137
|
});
|
|
1982
2138
|
}
|
|
1983
2139
|
}
|
|
@@ -2017,158 +2173,12 @@ function processEnumDeclarations(input) {
|
|
|
2017
2173
|
enumTypeDescriptors
|
|
2018
2174
|
};
|
|
2019
2175
|
}
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
message: `Named type "${input.declaration.name}" can declare at most one @db.* attribute`,
|
|
2027
|
-
sourceId: input.sourceId,
|
|
2028
|
-
span: extra.span
|
|
2029
|
-
});
|
|
2030
|
-
hasUnsupportedNamedTypeAttribute = true;
|
|
2031
|
-
}
|
|
2032
|
-
for (const attribute of input.declaration.attributes) {
|
|
2033
|
-
if (input.allowDbNativeType && attribute.name.startsWith("db.")) continue;
|
|
2034
|
-
const uncomposedNamespace = checkUncomposedNamespace(attribute.name, input.composedExtensions, {
|
|
2035
|
-
familyId: input.familyId,
|
|
2036
|
-
targetId: input.targetId,
|
|
2037
|
-
authoringContributions: input.authoringContributions
|
|
2038
|
-
});
|
|
2039
|
-
if (uncomposedNamespace) {
|
|
2040
|
-
reportUncomposedNamespace({
|
|
2041
|
-
subjectLabel: `Attribute "@${attribute.name}"`,
|
|
2042
|
-
namespace: uncomposedNamespace,
|
|
2043
|
-
sourceId: input.sourceId,
|
|
2044
|
-
span: attribute.span,
|
|
2045
|
-
diagnostics: input.diagnostics
|
|
2046
|
-
});
|
|
2047
|
-
hasUnsupportedNamedTypeAttribute = true;
|
|
2048
|
-
continue;
|
|
2049
|
-
}
|
|
2050
|
-
input.diagnostics.push({
|
|
2051
|
-
code: "PSL_UNSUPPORTED_NAMED_TYPE_ATTRIBUTE",
|
|
2052
|
-
message: `Named type "${input.declaration.name}" uses unsupported attribute "${attribute.name}"`,
|
|
2053
|
-
sourceId: input.sourceId,
|
|
2054
|
-
span: attribute.span
|
|
2055
|
-
});
|
|
2056
|
-
hasUnsupportedNamedTypeAttribute = true;
|
|
2057
|
-
}
|
|
2058
|
-
return {
|
|
2059
|
-
dbNativeTypeAttribute,
|
|
2060
|
-
hasUnsupportedNamedTypeAttribute
|
|
2061
|
-
};
|
|
2062
|
-
}
|
|
2063
|
-
function resolveNamedTypeDeclarations(input) {
|
|
2064
|
-
const storageTypes = {};
|
|
2065
|
-
const namedTypeDescriptors = /* @__PURE__ */ new Map();
|
|
2066
|
-
for (const declaration of input.declarations) {
|
|
2067
|
-
if (declaration.typeConstructor) {
|
|
2068
|
-
const { hasUnsupportedNamedTypeAttribute } = validateNamedTypeAttributes({
|
|
2069
|
-
declaration,
|
|
2070
|
-
sourceId: input.sourceId,
|
|
2071
|
-
diagnostics: input.diagnostics,
|
|
2072
|
-
composedExtensions: input.composedExtensions,
|
|
2073
|
-
authoringContributions: input.authoringContributions,
|
|
2074
|
-
allowDbNativeType: false,
|
|
2075
|
-
familyId: input.familyId,
|
|
2076
|
-
targetId: input.targetId
|
|
2077
|
-
});
|
|
2078
|
-
if (hasUnsupportedNamedTypeAttribute) continue;
|
|
2079
|
-
const helperPath = declaration.typeConstructor.path.join(".");
|
|
2080
|
-
const typeConstructor = resolvePslTypeConstructorDescriptor({
|
|
2081
|
-
call: declaration.typeConstructor,
|
|
2082
|
-
authoringContributions: input.authoringContributions,
|
|
2083
|
-
composedExtensions: input.composedExtensions,
|
|
2084
|
-
familyId: input.familyId,
|
|
2085
|
-
targetId: input.targetId,
|
|
2086
|
-
diagnostics: input.diagnostics,
|
|
2087
|
-
sourceId: input.sourceId,
|
|
2088
|
-
unsupportedCode: "PSL_UNSUPPORTED_NAMED_TYPE_CONSTRUCTOR",
|
|
2089
|
-
unsupportedMessage: `Named type "${declaration.name}" references unsupported constructor "${helperPath}"`
|
|
2090
|
-
});
|
|
2091
|
-
if (!typeConstructor) continue;
|
|
2092
|
-
const storageType = instantiatePslTypeConstructor({
|
|
2093
|
-
call: declaration.typeConstructor,
|
|
2094
|
-
descriptor: typeConstructor,
|
|
2095
|
-
diagnostics: input.diagnostics,
|
|
2096
|
-
sourceId: input.sourceId,
|
|
2097
|
-
entityLabel: `Named type "${declaration.name}"`
|
|
2098
|
-
});
|
|
2099
|
-
if (!storageType) continue;
|
|
2100
|
-
namedTypeDescriptors.set(declaration.name, toNamedTypeFieldDescriptor(declaration.name, storageType));
|
|
2101
|
-
storageTypes[declaration.name] = {
|
|
2102
|
-
kind: "codec-instance",
|
|
2103
|
-
codecId: storageType.codecId,
|
|
2104
|
-
nativeType: storageType.nativeType,
|
|
2105
|
-
typeParams: storageType.typeParams ?? {}
|
|
2106
|
-
};
|
|
2107
|
-
continue;
|
|
2108
|
-
}
|
|
2109
|
-
if (declaration.baseType === void 0) {
|
|
2110
|
-
input.diagnostics.push({
|
|
2111
|
-
code: "PSL_UNSUPPORTED_NAMED_TYPE_BASE",
|
|
2112
|
-
message: `Named type "${declaration.name}" must declare a base type or constructor`,
|
|
2113
|
-
sourceId: input.sourceId,
|
|
2114
|
-
span: declaration.span
|
|
2115
|
-
});
|
|
2116
|
-
continue;
|
|
2117
|
-
}
|
|
2118
|
-
const { baseType } = declaration;
|
|
2119
|
-
const baseDescriptor = input.enumTypeDescriptors.get(baseType) ?? input.scalarTypeDescriptors.get(baseType);
|
|
2120
|
-
if (!baseDescriptor) {
|
|
2121
|
-
input.diagnostics.push({
|
|
2122
|
-
code: "PSL_UNSUPPORTED_NAMED_TYPE_BASE",
|
|
2123
|
-
message: `Named type "${declaration.name}" references unsupported base type "${baseType}"`,
|
|
2124
|
-
sourceId: input.sourceId,
|
|
2125
|
-
span: declaration.span
|
|
2126
|
-
});
|
|
2127
|
-
continue;
|
|
2128
|
-
}
|
|
2129
|
-
const { dbNativeTypeAttribute, hasUnsupportedNamedTypeAttribute } = validateNamedTypeAttributes({
|
|
2130
|
-
declaration,
|
|
2131
|
-
sourceId: input.sourceId,
|
|
2132
|
-
diagnostics: input.diagnostics,
|
|
2133
|
-
composedExtensions: input.composedExtensions,
|
|
2134
|
-
authoringContributions: input.authoringContributions,
|
|
2135
|
-
allowDbNativeType: true,
|
|
2136
|
-
familyId: input.familyId,
|
|
2137
|
-
targetId: input.targetId
|
|
2138
|
-
});
|
|
2139
|
-
if (hasUnsupportedNamedTypeAttribute) continue;
|
|
2140
|
-
if (dbNativeTypeAttribute) {
|
|
2141
|
-
const descriptor = resolveDbNativeTypeAttribute({
|
|
2142
|
-
attribute: dbNativeTypeAttribute,
|
|
2143
|
-
baseType,
|
|
2144
|
-
baseDescriptor,
|
|
2145
|
-
diagnostics: input.diagnostics,
|
|
2146
|
-
sourceId: input.sourceId,
|
|
2147
|
-
entityLabel: `Named type "${declaration.name}"`
|
|
2148
|
-
});
|
|
2149
|
-
if (!descriptor) continue;
|
|
2150
|
-
namedTypeDescriptors.set(declaration.name, toNamedTypeFieldDescriptor(declaration.name, descriptor));
|
|
2151
|
-
storageTypes[declaration.name] = {
|
|
2152
|
-
kind: "codec-instance",
|
|
2153
|
-
codecId: descriptor.codecId,
|
|
2154
|
-
nativeType: descriptor.nativeType,
|
|
2155
|
-
typeParams: descriptor.typeParams ?? {}
|
|
2156
|
-
};
|
|
2157
|
-
continue;
|
|
2158
|
-
}
|
|
2159
|
-
const descriptor = toNamedTypeFieldDescriptor(declaration.name, baseDescriptor);
|
|
2160
|
-
namedTypeDescriptors.set(declaration.name, descriptor);
|
|
2161
|
-
storageTypes[declaration.name] = {
|
|
2162
|
-
kind: "codec-instance",
|
|
2163
|
-
codecId: baseDescriptor.codecId,
|
|
2164
|
-
nativeType: baseDescriptor.nativeType,
|
|
2165
|
-
typeParams: {}
|
|
2166
|
-
};
|
|
2167
|
-
}
|
|
2168
|
-
return {
|
|
2169
|
-
storageTypes,
|
|
2170
|
-
namedTypeDescriptors
|
|
2171
|
-
};
|
|
2176
|
+
/** Generic top-level blocks are supported only when a composed descriptor claims their keyword. */
|
|
2177
|
+
function composedBlockKeywords(authoringContributions) {
|
|
2178
|
+
const keywords = /* @__PURE__ */ new Set();
|
|
2179
|
+
const descriptors = authoringContributions?.pslBlockDescriptors ?? {};
|
|
2180
|
+
for (const [keyword, value] of Object.entries(descriptors)) if (isAuthoringPslBlockDescriptor(value)) keywords.add(keyword);
|
|
2181
|
+
return keywords;
|
|
2172
2182
|
}
|
|
2173
2183
|
function buildModelNodeFromPsl(input) {
|
|
2174
2184
|
const { model, mapping, sourceId, diagnostics } = input;
|
|
@@ -2208,7 +2218,7 @@ function buildModelNodeFromPsl(input) {
|
|
|
2208
2218
|
let controlPolicyDeclared = false;
|
|
2209
2219
|
let controlPolicy;
|
|
2210
2220
|
const resultBackrelationCandidates = [];
|
|
2211
|
-
for (const field of model.fields) {
|
|
2221
|
+
for (const field of Object.values(model.fields)) {
|
|
2212
2222
|
if (!field.list || !input.modelNames.has(field.typeName)) continue;
|
|
2213
2223
|
const attributesValid = validateNavigationListFieldAttributes({
|
|
2214
2224
|
modelName: model.name,
|
|
@@ -2260,7 +2270,7 @@ function buildModelNodeFromPsl(input) {
|
|
|
2260
2270
|
...ifDefined("relationName", relationName)
|
|
2261
2271
|
});
|
|
2262
2272
|
}
|
|
2263
|
-
const relationAttributes = model.fields.map((field) => ({
|
|
2273
|
+
const relationAttributes = Object.values(model.fields).map((field) => ({
|
|
2264
2274
|
field,
|
|
2265
2275
|
relation: getAttribute(field.attributes, "relation")
|
|
2266
2276
|
})).filter((entry) => Boolean(entry.relation));
|
|
@@ -2331,7 +2341,7 @@ function buildModelNodeFromPsl(input) {
|
|
|
2331
2341
|
});
|
|
2332
2342
|
continue;
|
|
2333
2343
|
}
|
|
2334
|
-
const nullableFieldName = fieldNames.find((name) => model.fields
|
|
2344
|
+
const nullableFieldName = fieldNames.find((name) => model.fields[name]?.optional === true);
|
|
2335
2345
|
if (nullableFieldName !== void 0) {
|
|
2336
2346
|
diagnostics.push({
|
|
2337
2347
|
code: "PSL_INVALID_ATTRIBUTE_ARGUMENT",
|
|
@@ -2736,7 +2746,7 @@ function buildModelNodeFromPsl(input) {
|
|
|
2736
2746
|
fieldName: resolvedField.field.name,
|
|
2737
2747
|
columnName: resolvedField.columnName,
|
|
2738
2748
|
descriptor: resolvedField.descriptor,
|
|
2739
|
-
nullable: resolvedField.
|
|
2749
|
+
nullable: resolvedField.nullable,
|
|
2740
2750
|
...ifDefined("default", resolvedField.defaultValue),
|
|
2741
2751
|
...ifDefined("executionDefaults", resolvedField.executionDefaults),
|
|
2742
2752
|
...ifDefined("enumTypeHandle", enumHandle)
|
|
@@ -2760,7 +2770,7 @@ function buildValueObjects(input) {
|
|
|
2760
2770
|
const compositeTypeNames = new Set(compositeTypes.map((ct) => ct.name));
|
|
2761
2771
|
for (const compositeType of compositeTypes) {
|
|
2762
2772
|
const fields = {};
|
|
2763
|
-
for (const field of compositeType.fields) {
|
|
2773
|
+
for (const field of Object.values(compositeType.fields)) {
|
|
2764
2774
|
if (compositeTypeNames.has(field.typeName)) {
|
|
2765
2775
|
const result = {
|
|
2766
2776
|
type: {
|
|
@@ -2866,7 +2876,7 @@ function collectPolymorphismDeclarations(models, sourceId, diagnostics) {
|
|
|
2866
2876
|
});
|
|
2867
2877
|
continue;
|
|
2868
2878
|
}
|
|
2869
|
-
const discField = model.fields
|
|
2879
|
+
const discField = model.fields[fieldName];
|
|
2870
2880
|
if (discField && discField.typeName !== "String") {
|
|
2871
2881
|
diagnostics.push({
|
|
2872
2882
|
code: "PSL_INVALID_ATTRIBUTE_ARGUMENT",
|
|
@@ -3171,7 +3181,7 @@ function stripStorageOnlyDomainFields(model, fieldNames) {
|
|
|
3171
3181
|
};
|
|
3172
3182
|
}
|
|
3173
3183
|
function interpretPslDocumentToSqlContract(input) {
|
|
3174
|
-
const sourceId = input.
|
|
3184
|
+
const sourceId = input.sourceId;
|
|
3175
3185
|
if (!input.target) return notOk({
|
|
3176
3186
|
summary: "PSL to SQL contract interpretation failed",
|
|
3177
3187
|
diagnostics: [{
|
|
@@ -3188,22 +3198,27 @@ function interpretPslDocumentToSqlContract(input) {
|
|
|
3188
3198
|
sourceId
|
|
3189
3199
|
}]
|
|
3190
3200
|
});
|
|
3191
|
-
const
|
|
3201
|
+
const { topLevel } = input.symbolTable;
|
|
3202
|
+
const sourceFile = input.sourceFile;
|
|
3203
|
+
const namespaceSymbols = Object.values(topLevel.namespaces);
|
|
3204
|
+
const diagnostics = [...input.seedDiagnostics ?? []];
|
|
3192
3205
|
validateNamespaceBlocksForSqlTarget({
|
|
3193
|
-
namespaces:
|
|
3206
|
+
namespaces: namespaceSymbols,
|
|
3194
3207
|
targetId: input.target.targetId,
|
|
3195
3208
|
sourceId,
|
|
3209
|
+
sourceFile,
|
|
3196
3210
|
diagnostics
|
|
3197
3211
|
});
|
|
3198
3212
|
const models = [];
|
|
3199
3213
|
const modelEntries = [];
|
|
3200
3214
|
const modelNamespaceIds = /* @__PURE__ */ new Map();
|
|
3201
|
-
|
|
3215
|
+
const compositeTypes = [];
|
|
3216
|
+
const collectScope = (bucketName, scopeModels, scopeCompositeTypes) => {
|
|
3202
3217
|
const resolvedNamespaceId = resolveNamespaceIdForSqlTarget({
|
|
3203
|
-
bucketName
|
|
3218
|
+
bucketName,
|
|
3204
3219
|
targetId: input.target.targetId
|
|
3205
3220
|
});
|
|
3206
|
-
for (const model of
|
|
3221
|
+
for (const model of scopeModels) {
|
|
3207
3222
|
models.push(model);
|
|
3208
3223
|
modelEntries.push({
|
|
3209
3224
|
model,
|
|
@@ -3211,9 +3226,11 @@ function interpretPslDocumentToSqlContract(input) {
|
|
|
3211
3226
|
});
|
|
3212
3227
|
if (resolvedNamespaceId !== void 0) modelNamespaceIds.set(model.name, resolvedNamespaceId);
|
|
3213
3228
|
}
|
|
3214
|
-
|
|
3229
|
+
for (const compositeType of scopeCompositeTypes) compositeTypes.push(compositeType);
|
|
3230
|
+
};
|
|
3231
|
+
collectScope(UNSPECIFIED_PSL_NAMESPACE_NAME, Object.values(topLevel.models), Object.values(topLevel.compositeTypes));
|
|
3232
|
+
for (const namespace of namespaceSymbols) collectScope(namespace.name, Object.values(namespace.models), Object.values(namespace.compositeTypes));
|
|
3215
3233
|
const defaultNamespaceId = input.target.defaultNamespaceId;
|
|
3216
|
-
const compositeTypes = input.document.ast.namespaces.flatMap((ns) => ns.compositeTypes);
|
|
3217
3234
|
const modelNames = new Set(models.map((model) => model.name));
|
|
3218
3235
|
const compositeTypeNames = new Set(compositeTypes.map((ct) => ct.name));
|
|
3219
3236
|
const composedExtensions = new Set(input.composedExtensionPacks ?? []);
|
|
@@ -3222,17 +3239,34 @@ function interpretPslDocumentToSqlContract(input) {
|
|
|
3222
3239
|
const generatorDescriptors = input.controlMutationDefaults?.generatorDescriptors ?? [];
|
|
3223
3240
|
const generatorDescriptorById = /* @__PURE__ */ new Map();
|
|
3224
3241
|
for (const descriptor of generatorDescriptors) generatorDescriptorById.set(descriptor.id, descriptor);
|
|
3225
|
-
const
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
code: "PSL_ENUM_NAMESPACE_NOT_SUPPORTED",
|
|
3232
|
-
message: `enum "${decl.name}" inside namespace "${ns.name}" is not supported; declare enum at the top level`,
|
|
3242
|
+
const isEnumBlock = (block) => block.keyword === "enum";
|
|
3243
|
+
const legitimateBlockKeywords = composedBlockKeywords(input.authoringContributions);
|
|
3244
|
+
const reportUnsupportedTopLevelBlock = (block) => {
|
|
3245
|
+
diagnostics.push({
|
|
3246
|
+
code: "PSL_UNSUPPORTED_TOP_LEVEL_BLOCK",
|
|
3247
|
+
message: `Unsupported top-level block "${block.keyword}"`,
|
|
3233
3248
|
sourceId,
|
|
3234
|
-
span:
|
|
3249
|
+
span: keywordPslSpan(block.node.syntax, block.keyword, sourceFile)
|
|
3235
3250
|
});
|
|
3251
|
+
};
|
|
3252
|
+
const topLevelEnums = Object.values(topLevel.blocks).filter((block) => {
|
|
3253
|
+
if (!legitimateBlockKeywords.has(block.keyword)) {
|
|
3254
|
+
reportUnsupportedTopLevelBlock(block);
|
|
3255
|
+
return false;
|
|
3256
|
+
}
|
|
3257
|
+
return isEnumBlock(block);
|
|
3258
|
+
}).map((block) => block.block);
|
|
3259
|
+
for (const namespace of namespaceSymbols) for (const block of Object.values(namespace.blocks)) {
|
|
3260
|
+
if (isEnumBlock(block)) {
|
|
3261
|
+
diagnostics.push({
|
|
3262
|
+
code: "PSL_ENUM_NAMESPACE_NOT_SUPPORTED",
|
|
3263
|
+
message: `enum "${block.name}" inside namespace "${namespace.name}" is not supported; declare enum at the top level`,
|
|
3264
|
+
sourceId,
|
|
3265
|
+
span: nodePslSpan(block.node.syntax, sourceFile)
|
|
3266
|
+
});
|
|
3267
|
+
continue;
|
|
3268
|
+
}
|
|
3269
|
+
if (!legitimateBlockKeywords.has(block.keyword)) reportUnsupportedTopLevelBlock(block);
|
|
3236
3270
|
}
|
|
3237
3271
|
const enumResult = processEnumDeclarations({
|
|
3238
3272
|
enumBlocks: topLevelEnums,
|
|
@@ -3253,7 +3287,7 @@ function interpretPslDocumentToSqlContract(input) {
|
|
|
3253
3287
|
const validEnumHandles = { ...enumResult.enumHandles };
|
|
3254
3288
|
const enumHandlesByName = new Map(Object.entries(validEnumHandles));
|
|
3255
3289
|
const namedTypeResult = resolveNamedTypeDeclarations({
|
|
3256
|
-
declarations:
|
|
3290
|
+
declarations: [...Object.values(topLevel.scalars), ...Object.values(topLevel.typeAliases)],
|
|
3257
3291
|
sourceId,
|
|
3258
3292
|
enumTypeDescriptors: allEnumTypeDescriptors,
|
|
3259
3293
|
scalarTypeDescriptors: input.scalarTypeDescriptors,
|
|
@@ -3342,7 +3376,7 @@ function interpretPslDocumentToSqlContract(input) {
|
|
|
3342
3376
|
});
|
|
3343
3377
|
if (diagnostics.length > 0) return notOk({
|
|
3344
3378
|
summary: "PSL to SQL contract interpretation failed",
|
|
3345
|
-
diagnostics
|
|
3379
|
+
diagnostics
|
|
3346
3380
|
});
|
|
3347
3381
|
const contract = buildSqlContractFromDefinition({
|
|
3348
3382
|
target: input.target,
|
|
@@ -3358,7 +3392,7 @@ function interpretPslDocumentToSqlContract(input) {
|
|
|
3358
3392
|
const modelsForPatch = {};
|
|
3359
3393
|
for (const [namespaceId, namespaceSlice] of Object.entries(contract.domain.namespaces)) for (const [modelName, model] of Object.entries(namespaceSlice.models)) {
|
|
3360
3394
|
const coordinate = modelCoordinateKey(namespaceId, modelName);
|
|
3361
|
-
|
|
3395
|
+
invariant(!Object.hasOwn(modelsForPatch, coordinate), `symbol table guarantees coordinate uniqueness; duplicate model "${namespaceId}.${modelName}" reached interpretation`);
|
|
3362
3396
|
modelsForPatch[coordinate] = model;
|
|
3363
3397
|
}
|
|
3364
3398
|
let patchedModels = patchModelDomainFields(modelsForPatch, modelResolvedFields);
|
|
@@ -3384,4 +3418,4 @@ function interpretPslDocumentToSqlContract(input) {
|
|
|
3384
3418
|
//#endregion
|
|
3385
3419
|
export { interpretPslDocumentToSqlContract as t };
|
|
3386
3420
|
|
|
3387
|
-
//# sourceMappingURL=interpreter-
|
|
3421
|
+
//# sourceMappingURL=interpreter-kDkm5opL.mjs.map
|