@prisma-next/mongo-contract-psl 0.13.0 → 0.14.0-dev.10
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/exports/provider.d.mts.map +1 -1
- package/dist/exports/provider.mjs +24 -7
- package/dist/exports/provider.mjs.map +1 -1
- package/dist/index.d.mts +7 -3
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{interpreter-CNVgUGau.mjs → interpreter-DCiVHDlW.mjs} +73 -80
- package/dist/interpreter-DCiVHDlW.mjs.map +1 -0
- package/package.json +11 -9
- package/src/interpreter.ts +100 -113
- package/src/provider.ts +36 -6
- package/src/psl-helpers.ts +18 -13
- package/dist/interpreter-CNVgUGau.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.d.mts","names":[],"sources":["../../src/provider.ts"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"provider.d.mts","names":[],"sources":["../../src/provider.ts"],"mappings":";;;UAUiB,oBAAA;EAAA,SACN,MAAM;AAAA;AAAA,iBAgBD,aAAA,CAAc,UAAA,UAAoB,OAAA,GAAU,oBAAA,GAAuB,cAAc"}
|
|
@@ -1,12 +1,22 @@
|
|
|
1
|
-
import { t as interpretPslDocumentToMongoContract } from "../interpreter-
|
|
1
|
+
import { t as interpretPslDocumentToMongoContract } from "../interpreter-DCiVHDlW.mjs";
|
|
2
|
+
import { buildSymbolTable, rangeToPslSpan } from "@prisma-next/psl-parser";
|
|
2
3
|
import { notOk, ok } from "@prisma-next/utils/result";
|
|
3
|
-
import { parsePslDocument } from "@prisma-next/psl-parser";
|
|
4
|
-
import { readFile } from "node:fs/promises";
|
|
5
4
|
import { ifDefined } from "@prisma-next/utils/defined";
|
|
5
|
+
import { readFile } from "node:fs/promises";
|
|
6
|
+
import { parse } from "@prisma-next/psl-parser/syntax";
|
|
6
7
|
//#region src/provider.ts
|
|
8
|
+
function mapParseDiagnostics(diagnostics, sourceFile, sourceId) {
|
|
9
|
+
return diagnostics.map((diagnostic) => ({
|
|
10
|
+
code: diagnostic.code,
|
|
11
|
+
message: diagnostic.message,
|
|
12
|
+
sourceId,
|
|
13
|
+
span: rangeToPslSpan(diagnostic.range, sourceFile)
|
|
14
|
+
}));
|
|
15
|
+
}
|
|
7
16
|
function mongoContract(schemaPath, options) {
|
|
8
17
|
return {
|
|
9
18
|
source: {
|
|
19
|
+
sourceFormat: "psl",
|
|
10
20
|
inputs: [schemaPath],
|
|
11
21
|
load: async (context) => {
|
|
12
22
|
const [absoluteSchemaPath] = context.resolvedInputs;
|
|
@@ -30,11 +40,18 @@ function mongoContract(schemaPath, options) {
|
|
|
30
40
|
}
|
|
31
41
|
});
|
|
32
42
|
}
|
|
43
|
+
const { document, sourceFile, diagnostics: parseDiagnostics } = parse(schema);
|
|
44
|
+
const { table: symbolTable, diagnostics: symbolTableDiagnostics } = buildSymbolTable({
|
|
45
|
+
document,
|
|
46
|
+
sourceFile,
|
|
47
|
+
scalarTypes: [...context.scalarTypeDescriptors.keys()],
|
|
48
|
+
pslBlockDescriptors: context.authoringContributions.pslBlockDescriptors
|
|
49
|
+
});
|
|
33
50
|
const interpreted = interpretPslDocumentToMongoContract({
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
51
|
+
symbolTable,
|
|
52
|
+
sourceFile,
|
|
53
|
+
sourceId: schemaPath,
|
|
54
|
+
seedDiagnostics: [...mapParseDiagnostics(parseDiagnostics, sourceFile, schemaPath), ...mapParseDiagnostics(symbolTableDiagnostics, sourceFile, schemaPath)],
|
|
38
55
|
scalarTypeDescriptors: context.scalarTypeDescriptors,
|
|
39
56
|
codecLookup: context.codecLookup
|
|
40
57
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.mjs","names":[],"sources":["../../src/provider.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport type { ContractConfig } from '@prisma-next/config/config-types';\nimport {
|
|
1
|
+
{"version":3,"file":"provider.mjs","names":[],"sources":["../../src/provider.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport type { ContractConfig, ContractSourceDiagnostic } from '@prisma-next/config/config-types';\nimport { buildSymbolTable, rangeToPslSpan } from '@prisma-next/psl-parser';\nimport type { ParseDiagnostic, SourceFile } from '@prisma-next/psl-parser/syntax';\nimport { parse } from '@prisma-next/psl-parser/syntax';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { notOk, ok } from '@prisma-next/utils/result';\n\nimport { interpretPslDocumentToMongoContract } from './interpreter';\n\nexport interface MongoContractOptions {\n readonly output?: string;\n}\n\nfunction mapParseDiagnostics(\n diagnostics: readonly ParseDiagnostic[],\n sourceFile: SourceFile,\n sourceId: string,\n): ContractSourceDiagnostic[] {\n return diagnostics.map((diagnostic) => ({\n code: diagnostic.code,\n message: diagnostic.message,\n sourceId,\n span: rangeToPslSpan(diagnostic.range, sourceFile),\n }));\n}\n\nexport function mongoContract(schemaPath: string, options?: MongoContractOptions): ContractConfig {\n return {\n source: {\n sourceFormat: 'psl',\n inputs: [schemaPath],\n load: async (context) => {\n const [absoluteSchemaPath] = context.resolvedInputs;\n if (absoluteSchemaPath === undefined) {\n throw new Error(\n 'mongoContract: context.resolvedInputs is empty. The CLI config loader should populate it positional-matched with source.inputs.',\n );\n }\n let schema: string;\n try {\n schema = await readFile(absoluteSchemaPath, 'utf-8');\n } catch (error) {\n const message = String(error);\n return notOk({\n summary: `Failed to read Prisma schema at \"${schemaPath}\"`,\n diagnostics: [\n {\n code: 'PSL_SCHEMA_READ_FAILED',\n message,\n sourceId: schemaPath,\n },\n ],\n meta: { schemaPath, absoluteSchemaPath, cause: message },\n });\n }\n\n const { document, sourceFile, diagnostics: parseDiagnostics } = parse(schema);\n const { table: symbolTable, diagnostics: symbolTableDiagnostics } = buildSymbolTable({\n document,\n sourceFile,\n scalarTypes: [...context.scalarTypeDescriptors.keys()],\n pslBlockDescriptors: context.authoringContributions.pslBlockDescriptors,\n });\n\n // Do not short-circuit on provider-level diagnostics; recovered CST can\n // still produce interpreter diagnostics in the same response.\n const seedDiagnostics = [\n ...mapParseDiagnostics(parseDiagnostics, sourceFile, schemaPath),\n ...mapParseDiagnostics(symbolTableDiagnostics, sourceFile, schemaPath),\n ];\n\n const interpreted = interpretPslDocumentToMongoContract({\n symbolTable,\n sourceFile,\n sourceId: schemaPath,\n seedDiagnostics,\n scalarTypeDescriptors: context.scalarTypeDescriptors,\n codecLookup: context.codecLookup,\n });\n if (!interpreted.ok) {\n return interpreted;\n }\n\n return ok(interpreted.value);\n },\n },\n ...ifDefined('output', options?.output),\n };\n}\n"],"mappings":";;;;;;;AAcA,SAAS,oBACP,aACA,YACA,UAC4B;CAC5B,OAAO,YAAY,KAAK,gBAAgB;EACtC,MAAM,WAAW;EACjB,SAAS,WAAW;EACpB;EACA,MAAM,eAAe,WAAW,OAAO,UAAU;CACnD,EAAE;AACJ;AAEA,SAAgB,cAAc,YAAoB,SAAgD;CAChG,OAAO;EACL,QAAQ;GACN,cAAc;GACd,QAAQ,CAAC,UAAU;GACnB,MAAM,OAAO,YAAY;IACvB,MAAM,CAAC,sBAAsB,QAAQ;IACrC,IAAI,uBAAuB,KAAA,GACzB,MAAM,IAAI,MACR,iIACF;IAEF,IAAI;IACJ,IAAI;KACF,SAAS,MAAM,SAAS,oBAAoB,OAAO;IACrD,SAAS,OAAO;KACd,MAAM,UAAU,OAAO,KAAK;KAC5B,OAAO,MAAM;MACX,SAAS,oCAAoC,WAAW;MACxD,aAAa,CACX;OACE,MAAM;OACN;OACA,UAAU;MACZ,CACF;MACA,MAAM;OAAE;OAAY;OAAoB,OAAO;MAAQ;KACzD,CAAC;IACH;IAEA,MAAM,EAAE,UAAU,YAAY,aAAa,qBAAqB,MAAM,MAAM;IAC5E,MAAM,EAAE,OAAO,aAAa,aAAa,2BAA2B,iBAAiB;KACnF;KACA;KACA,aAAa,CAAC,GAAG,QAAQ,sBAAsB,KAAK,CAAC;KACrD,qBAAqB,QAAQ,uBAAuB;IACtD,CAAC;IASD,MAAM,cAAc,oCAAoC;KACtD;KACA;KACA,UAAU;KACV,iBAAA,CARA,GAAG,oBAAoB,kBAAkB,YAAY,UAAU,GAC/D,GAAG,oBAAoB,wBAAwB,YAAY,UAAU,CAOvD;KACd,uBAAuB,QAAQ;KAC/B,aAAa,QAAQ;IACvB,CAAC;IACD,IAAI,CAAC,YAAY,IACf,OAAO;IAGT,OAAO,GAAG,YAAY,KAAK;GAC7B;EACF;EACA,GAAG,UAAU,UAAU,SAAS,MAAM;CACxC;AACF"}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
import { Contract } from "@prisma-next/contract/types";
|
|
2
|
+
import { SymbolTable } from "@prisma-next/psl-parser";
|
|
2
3
|
import { Result } from "@prisma-next/utils/result";
|
|
3
|
-
import {
|
|
4
|
-
import { ContractSourceDiagnostics } from "@prisma-next/config/config-types";
|
|
4
|
+
import { SourceFile } from "@prisma-next/psl-parser/syntax";
|
|
5
|
+
import { ContractSourceDiagnostic, ContractSourceDiagnostics } from "@prisma-next/config/config-types";
|
|
5
6
|
import { CodecLookup } from "@prisma-next/framework-components/codec";
|
|
6
7
|
|
|
7
8
|
//#region src/interpreter.d.ts
|
|
8
9
|
interface InterpretPslDocumentToMongoContractInput {
|
|
9
|
-
readonly
|
|
10
|
+
readonly symbolTable: SymbolTable;
|
|
11
|
+
readonly sourceFile: SourceFile;
|
|
12
|
+
readonly sourceId: string;
|
|
10
13
|
readonly scalarTypeDescriptors: ReadonlyMap<string, string>;
|
|
11
14
|
readonly codecLookup?: CodecLookup;
|
|
15
|
+
readonly seedDiagnostics?: readonly ContractSourceDiagnostic[];
|
|
12
16
|
}
|
|
13
17
|
declare function interpretPslDocumentToMongoContract(input: InterpretPslDocumentToMongoContractInput): Result<Contract, ContractSourceDiagnostics>;
|
|
14
18
|
//#endregion
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/interpreter.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/interpreter.ts"],"mappings":";;;;;;;;UAkDiB,wCAAA;EAAA,SACN,WAAA,EAAa,WAAA;EAAA,SACb,UAAA,EAAY,UAAA;EAAA,SACZ,QAAA;EAAA,SACA,qBAAA,EAAuB,WAAA;EAAA,SACvB,WAAA,GAAc,WAAA;EAAA,SACd,eAAA,YAA2B,wBAAA;AAAA;AAAA,iBAoxBtB,mCAAA,CACd,KAAA,EAAO,wCAAA,GACN,MAAA,CAAO,QAAA,EAAU,yBAAA"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as interpretPslDocumentToMongoContract } from "./interpreter-
|
|
1
|
+
import { t as interpretPslDocumentToMongoContract } from "./interpreter-DCiVHDlW.mjs";
|
|
2
2
|
export { interpretPslDocumentToMongoContract };
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { computeProfileHash, computeStorageHash } from "@prisma-next/contract/hashing";
|
|
2
2
|
import { crossRef } from "@prisma-next/contract/types";
|
|
3
3
|
import { UNBOUND_NAMESPACE_ID } from "@prisma-next/framework-components/ir";
|
|
4
|
-
import {
|
|
4
|
+
import { MongoIndex, MongoStorage, MongoValidator, applyPolymorphicScopeToMongoIndex, buildMongoNamespace } from "@prisma-next/mongo-contract";
|
|
5
5
|
import { mongoContractCanonicalizationHooks } from "@prisma-next/mongo-contract/canonicalization-hooks";
|
|
6
|
+
import { nodePslSpan, parseQuotedStringLiteral } from "@prisma-next/psl-parser";
|
|
7
|
+
import { blindCast } from "@prisma-next/utils/casts";
|
|
6
8
|
import { notOk, ok } from "@prisma-next/utils/result";
|
|
7
|
-
import {
|
|
9
|
+
import { ifDefined } from "@prisma-next/utils/defined";
|
|
8
10
|
//#region src/derive-json-schema.ts
|
|
9
11
|
function resolveBsonType(codecId, codecLookup) {
|
|
10
12
|
return codecLookup?.targetTypesFor(codecId)?.[0];
|
|
@@ -98,6 +100,9 @@ function derivePolymorphicJsonSchema(baseFields, discriminatorField, variants, v
|
|
|
98
100
|
}
|
|
99
101
|
//#endregion
|
|
100
102
|
//#region src/psl-helpers.ts
|
|
103
|
+
function getPositionalArgument(attr, index = 0) {
|
|
104
|
+
return attr.args.filter((arg) => arg.kind === "positional")[index]?.value;
|
|
105
|
+
}
|
|
101
106
|
function getNamedArgument(attr, name) {
|
|
102
107
|
return attr.args.find((a) => a.kind === "named" && a.name === name)?.value;
|
|
103
108
|
}
|
|
@@ -172,9 +177,9 @@ function parseRelationAttribute(attributes) {
|
|
|
172
177
|
const fields = fieldsArg ? parseFieldList(fieldsArg.value) : void 0;
|
|
173
178
|
const references = referencesArg ? parseFieldList(referencesArg.value) : void 0;
|
|
174
179
|
return {
|
|
175
|
-
...relationName
|
|
176
|
-
...fields
|
|
177
|
-
...references
|
|
180
|
+
...ifDefined("relationName", relationName),
|
|
181
|
+
...ifDefined("fields", fields),
|
|
182
|
+
...ifDefined("references", references)
|
|
178
183
|
};
|
|
179
184
|
}
|
|
180
185
|
function stripQuotes(value) {
|
|
@@ -184,37 +189,23 @@ function stripQuotes(value) {
|
|
|
184
189
|
//#endregion
|
|
185
190
|
//#region src/interpreter.ts
|
|
186
191
|
/**
|
|
187
|
-
*
|
|
188
|
-
*
|
|
189
|
-
* import from `@prisma-next/framework-components/psl-ast`.
|
|
190
|
-
*/
|
|
191
|
-
const UNSPECIFIED_PSL_NAMESPACE_NAME = "__unspecified__";
|
|
192
|
-
/**
|
|
193
|
-
* Mongo FR16c validation: Mongo's authoring DSL exposes the connection's
|
|
194
|
-
* database as the only namespace surface today, so the PSL interpreter
|
|
195
|
-
* rejects every explicit `namespace { … }` block. The implicit
|
|
196
|
-
* `__unspecified__` bucket (top-level declarations) is the only
|
|
197
|
-
* namespace Mongo accepts. `namespace unbound { … }` is rejected too —
|
|
198
|
-
* Mongo has no late-binding namespace concept on the PSL surface (the
|
|
199
|
-
* database name comes from the connection string, not from PSL).
|
|
192
|
+
* Mongo's PSL surface binds the database from the connection string, so every
|
|
193
|
+
* explicit namespace block is invalid, including `namespace unbound { … }`.
|
|
200
194
|
*/
|
|
201
195
|
function validateNamespaceBlocksForMongoTarget(input) {
|
|
202
|
-
for (const namespace of input.namespaces) {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
span: namespace.span
|
|
209
|
-
});
|
|
210
|
-
}
|
|
196
|
+
for (const namespace of input.namespaces) input.diagnostics.push({
|
|
197
|
+
code: "PSL_UNSUPPORTED_NAMESPACE_BLOCK",
|
|
198
|
+
message: `Mongo does not support \`namespace ${namespace.name} { … }\` blocks (the database is bound by the connection string; declare models at the document top level instead).`,
|
|
199
|
+
sourceId: input.sourceId,
|
|
200
|
+
span: nodePslSpan(namespace.node.syntax, input.sourceFile)
|
|
201
|
+
});
|
|
211
202
|
}
|
|
212
203
|
function fkRelationPairKey(declaringModel, targetModel) {
|
|
213
204
|
return `${declaringModel}::${targetModel}`;
|
|
214
205
|
}
|
|
215
206
|
function resolveFieldMappings(model) {
|
|
216
207
|
const pslNameToMapped = /* @__PURE__ */ new Map();
|
|
217
|
-
for (const field of model.fields) {
|
|
208
|
+
for (const field of Object.values(model.fields)) {
|
|
218
209
|
const mapped = getMapName(field.attributes) ?? field.name;
|
|
219
210
|
pslNameToMapped.set(field.name, mapped);
|
|
220
211
|
}
|
|
@@ -226,33 +217,32 @@ function resolveCollectionName(model) {
|
|
|
226
217
|
function mongoCrossRef(modelName) {
|
|
227
218
|
return crossRef(modelName, UNBOUND_NAMESPACE_ID);
|
|
228
219
|
}
|
|
229
|
-
function collectPolymorphismDeclarations(
|
|
220
|
+
function collectPolymorphismDeclarations(models, sourceId, diagnostics) {
|
|
230
221
|
const discriminatorDeclarations = /* @__PURE__ */ new Map();
|
|
231
222
|
const baseDeclarations = /* @__PURE__ */ new Map();
|
|
232
|
-
const
|
|
233
|
-
for (const pslModel of allPslModels) for (const attr of pslModel.attributes) {
|
|
223
|
+
for (const model of models) for (const attr of model.attributes) {
|
|
234
224
|
if (attr.name === "discriminator") {
|
|
235
225
|
const fieldName = getPositionalArgument(attr);
|
|
236
226
|
if (!fieldName) {
|
|
237
227
|
diagnostics.push({
|
|
238
228
|
code: "PSL_INVALID_ATTRIBUTE_ARGUMENT",
|
|
239
|
-
message: `Model "${
|
|
229
|
+
message: `Model "${model.name}" @@discriminator requires a field name argument`,
|
|
240
230
|
sourceId,
|
|
241
231
|
span: attr.span
|
|
242
232
|
});
|
|
243
233
|
continue;
|
|
244
234
|
}
|
|
245
|
-
const discField =
|
|
235
|
+
const discField = model.fields[fieldName];
|
|
246
236
|
if (discField && discField.typeName !== "String") {
|
|
247
237
|
diagnostics.push({
|
|
248
238
|
code: "PSL_INVALID_ATTRIBUTE_ARGUMENT",
|
|
249
|
-
message: `Discriminator field "${fieldName}" on model "${
|
|
239
|
+
message: `Discriminator field "${fieldName}" on model "${model.name}" must be of type String, but is "${discField.typeName}"`,
|
|
250
240
|
sourceId,
|
|
251
241
|
span: attr.span
|
|
252
242
|
});
|
|
253
243
|
continue;
|
|
254
244
|
}
|
|
255
|
-
discriminatorDeclarations.set(
|
|
245
|
+
discriminatorDeclarations.set(model.name, {
|
|
256
246
|
fieldName,
|
|
257
247
|
span: attr.span
|
|
258
248
|
});
|
|
@@ -263,7 +253,7 @@ function collectPolymorphismDeclarations(document, sourceId, diagnostics) {
|
|
|
263
253
|
if (!baseName || !rawValue) {
|
|
264
254
|
diagnostics.push({
|
|
265
255
|
code: "PSL_INVALID_ATTRIBUTE_ARGUMENT",
|
|
266
|
-
message: `Model "${
|
|
256
|
+
message: `Model "${model.name}" @@base requires two arguments: base model name and discriminator value`,
|
|
267
257
|
sourceId,
|
|
268
258
|
span: attr.span
|
|
269
259
|
});
|
|
@@ -273,14 +263,14 @@ function collectPolymorphismDeclarations(document, sourceId, diagnostics) {
|
|
|
273
263
|
if (value === void 0) {
|
|
274
264
|
diagnostics.push({
|
|
275
265
|
code: "PSL_INVALID_ATTRIBUTE_ARGUMENT",
|
|
276
|
-
message: `Model "${
|
|
266
|
+
message: `Model "${model.name}" @@base discriminator value must be a quoted string literal`,
|
|
277
267
|
sourceId,
|
|
278
268
|
span: attr.span
|
|
279
269
|
});
|
|
280
270
|
continue;
|
|
281
271
|
}
|
|
282
|
-
const collectionName = resolveCollectionName(
|
|
283
|
-
baseDeclarations.set(
|
|
272
|
+
const collectionName = resolveCollectionName(model);
|
|
273
|
+
baseDeclarations.set(model.name, {
|
|
284
274
|
baseName,
|
|
285
275
|
value,
|
|
286
276
|
collectionName,
|
|
@@ -294,8 +284,7 @@ function collectPolymorphismDeclarations(document, sourceId, diagnostics) {
|
|
|
294
284
|
};
|
|
295
285
|
}
|
|
296
286
|
function resolvePolymorphism(input) {
|
|
297
|
-
const { discriminatorDeclarations, baseDeclarations, modelNames, sourceId,
|
|
298
|
-
const allPslModels = document.ast.namespaces.flatMap((ns) => ns.models);
|
|
287
|
+
const { discriminatorDeclarations, baseDeclarations, modelNames, sourceId, allModels: allModelViews, indexSpans, modelIndexesByName } = input;
|
|
299
288
|
let patched = input.models;
|
|
300
289
|
let roots = input.roots;
|
|
301
290
|
let collections = input.collections;
|
|
@@ -312,8 +301,8 @@ function resolvePolymorphism(input) {
|
|
|
312
301
|
}
|
|
313
302
|
const model = patched[modelName];
|
|
314
303
|
if (!model) continue;
|
|
315
|
-
const
|
|
316
|
-
const mappedDiscriminatorField =
|
|
304
|
+
const modelView = allModelViews.find((m) => m.name === modelName);
|
|
305
|
+
const mappedDiscriminatorField = modelView ? resolveFieldMappings(modelView).pslNameToMapped.get(decl.fieldName) ?? decl.fieldName : decl.fieldName;
|
|
317
306
|
if (!Object.hasOwn(model.fields, mappedDiscriminatorField)) {
|
|
318
307
|
diagnostics.push({
|
|
319
308
|
code: "PSL_DISCRIMINATOR_FIELD_NOT_FOUND",
|
|
@@ -367,9 +356,9 @@ function resolvePolymorphism(input) {
|
|
|
367
356
|
}
|
|
368
357
|
if (discriminatorDeclarations.has(variantName)) continue;
|
|
369
358
|
const baseModel = patched[baseDecl.baseName];
|
|
370
|
-
const
|
|
371
|
-
if (!
|
|
372
|
-
if (getMapName(
|
|
359
|
+
const variantModelView = allModelViews.find((m) => m.name === variantName);
|
|
360
|
+
if (!variantModelView) continue;
|
|
361
|
+
if (getMapName(variantModelView.attributes) !== void 0 && baseModel && baseDecl.collectionName !== baseModel.storage.collection) {
|
|
373
362
|
diagnostics.push({
|
|
374
363
|
code: "PSL_MONGO_VARIANT_SEPARATE_COLLECTION",
|
|
375
364
|
message: `Mongo variant "${variantName}" cannot use a different collection than its base "${baseDecl.baseName}". Mongo only supports single-collection polymorphism.`,
|
|
@@ -388,7 +377,7 @@ function resolvePolymorphism(input) {
|
|
|
388
377
|
storage: { collection: baseCollection }
|
|
389
378
|
}
|
|
390
379
|
};
|
|
391
|
-
const variantCollectionName = resolveCollectionName(
|
|
380
|
+
const variantCollectionName = resolveCollectionName(variantModelView);
|
|
392
381
|
if (roots[variantCollectionName]?.model === variantName) if (variantCollectionName === baseCollection && baseModel) roots = {
|
|
393
382
|
...roots,
|
|
394
383
|
[variantCollectionName]: mongoCrossRef(baseDecl.baseName)
|
|
@@ -496,21 +485,21 @@ function parseCollation(attr) {
|
|
|
496
485
|
if (!locale) return getNamedArgument(attr, "collationStrength") != null || getNamedArgument(attr, "collationCaseLevel") != null || getNamedArgument(attr, "collationCaseFirst") != null || getNamedArgument(attr, "collationNumericOrdering") != null || getNamedArgument(attr, "collationAlternate") != null || getNamedArgument(attr, "collationMaxVariable") != null || getNamedArgument(attr, "collationBackwards") != null || getNamedArgument(attr, "collationNormalization") != null ? null : void 0;
|
|
497
486
|
const collation = { locale };
|
|
498
487
|
const strength = parseNumericArg(getNamedArgument(attr, "collationStrength"));
|
|
499
|
-
if (strength != null) collation
|
|
488
|
+
if (strength != null) collation.strength = strength;
|
|
500
489
|
const caseLevel = parseBooleanArg(getNamedArgument(attr, "collationCaseLevel"));
|
|
501
|
-
if (caseLevel != null) collation
|
|
490
|
+
if (caseLevel != null) collation.caseLevel = caseLevel;
|
|
502
491
|
const caseFirst = stripQuotesHelper(getNamedArgument(attr, "collationCaseFirst"));
|
|
503
|
-
if (caseFirst != null) collation
|
|
492
|
+
if (caseFirst != null) collation.caseFirst = caseFirst;
|
|
504
493
|
const numericOrdering = parseBooleanArg(getNamedArgument(attr, "collationNumericOrdering"));
|
|
505
|
-
if (numericOrdering != null) collation
|
|
494
|
+
if (numericOrdering != null) collation.numericOrdering = numericOrdering;
|
|
506
495
|
const alternate = stripQuotesHelper(getNamedArgument(attr, "collationAlternate"));
|
|
507
|
-
if (alternate != null) collation
|
|
496
|
+
if (alternate != null) collation.alternate = alternate;
|
|
508
497
|
const maxVariable = stripQuotesHelper(getNamedArgument(attr, "collationMaxVariable"));
|
|
509
|
-
if (maxVariable != null) collation
|
|
498
|
+
if (maxVariable != null) collation.maxVariable = maxVariable;
|
|
510
499
|
const backwards = parseBooleanArg(getNamedArgument(attr, "collationBackwards"));
|
|
511
|
-
if (backwards != null) collation
|
|
500
|
+
if (backwards != null) collation.backwards = backwards;
|
|
512
501
|
const normalization = parseBooleanArg(getNamedArgument(attr, "collationNormalization"));
|
|
513
|
-
if (normalization != null) collation
|
|
502
|
+
if (normalization != null) collation.normalization = normalization;
|
|
514
503
|
return collation;
|
|
515
504
|
}
|
|
516
505
|
function stripQuotesHelper(raw) {
|
|
@@ -530,11 +519,11 @@ function collectIndexes(pslModel, fieldMappings, modelNames, sourceId, diagnosti
|
|
|
530
519
|
const indexes = [];
|
|
531
520
|
let textIndexCount = 0;
|
|
532
521
|
const indexableFieldNames = /* @__PURE__ */ new Set();
|
|
533
|
-
for (const f of pslModel.fields) {
|
|
522
|
+
for (const f of Object.values(pslModel.fields)) {
|
|
534
523
|
if (modelNames.has(f.typeName)) continue;
|
|
535
524
|
indexableFieldNames.add(f.name);
|
|
536
525
|
}
|
|
537
|
-
for (const field of pslModel.fields) {
|
|
526
|
+
for (const field of Object.values(pslModel.fields)) {
|
|
538
527
|
if (modelNames.has(field.typeName)) continue;
|
|
539
528
|
const uniqueAttr = getAttribute(field.attributes, "unique");
|
|
540
529
|
if (!uniqueAttr) continue;
|
|
@@ -742,6 +731,7 @@ function resolveNonRelationField(field, ownerName, compositeTypeNames, scalarTyp
|
|
|
742
731
|
many: true
|
|
743
732
|
} : result;
|
|
744
733
|
}
|
|
734
|
+
if (field.malformedType) return;
|
|
745
735
|
const codecId = resolveFieldCodecId(field, scalarTypeDescriptors);
|
|
746
736
|
if (!codecId) {
|
|
747
737
|
diagnostics.push({
|
|
@@ -765,16 +755,18 @@ function resolveNonRelationField(field, ownerName, compositeTypeNames, scalarTyp
|
|
|
765
755
|
} : result;
|
|
766
756
|
}
|
|
767
757
|
function interpretPslDocumentToMongoContract(input) {
|
|
768
|
-
const {
|
|
769
|
-
const sourceId =
|
|
770
|
-
const diagnostics = [];
|
|
758
|
+
const { symbolTable, sourceFile, scalarTypeDescriptors, codecLookup } = input;
|
|
759
|
+
const sourceId = input.sourceId;
|
|
760
|
+
const diagnostics = [...input.seedDiagnostics ?? []];
|
|
761
|
+
const topLevel = symbolTable.topLevel;
|
|
771
762
|
validateNamespaceBlocksForMongoTarget({
|
|
772
|
-
namespaces:
|
|
763
|
+
namespaces: Object.values(topLevel.namespaces),
|
|
773
764
|
sourceId,
|
|
765
|
+
sourceFile,
|
|
774
766
|
diagnostics
|
|
775
767
|
});
|
|
776
|
-
const allModels =
|
|
777
|
-
const allCompositeTypes =
|
|
768
|
+
const allModels = Object.values(topLevel.models);
|
|
769
|
+
const allCompositeTypes = Object.values(topLevel.compositeTypes);
|
|
778
770
|
const modelNames = new Set(allModels.map((m) => m.name));
|
|
779
771
|
const compositeTypeNames = new Set(allCompositeTypes.map((ct) => ct.name));
|
|
780
772
|
const models = {};
|
|
@@ -789,7 +781,7 @@ function interpretPslDocumentToMongoContract(input) {
|
|
|
789
781
|
const fieldMappings = resolveFieldMappings(pslModel);
|
|
790
782
|
const fields = {};
|
|
791
783
|
const relations = {};
|
|
792
|
-
for (const field of pslModel.fields) {
|
|
784
|
+
for (const field of Object.values(pslModel.fields)) {
|
|
793
785
|
if (isRelationField(field, modelNames)) {
|
|
794
786
|
const relation = parseRelationAttribute(field.attributes);
|
|
795
787
|
if (field.list || !(relation?.fields && relation?.references)) {
|
|
@@ -833,7 +825,7 @@ function interpretPslDocumentToMongoContract(input) {
|
|
|
833
825
|
fields[mappedName] = resolved;
|
|
834
826
|
}
|
|
835
827
|
const isVariantModel = pslModel.attributes.some((attr) => attr.name === "base");
|
|
836
|
-
const hasIdField = pslModel.fields.some((f) => getAttribute(f.attributes, "id") !== void 0);
|
|
828
|
+
const hasIdField = Object.values(pslModel.fields).some((f) => getAttribute(f.attributes, "id") !== void 0);
|
|
837
829
|
if (!isVariantModel) if (!hasIdField) diagnostics.push({
|
|
838
830
|
code: "PSL_MISSING_ID_FIELD",
|
|
839
831
|
message: `Model "${pslModel.name}" has no field with @id attribute. Every model must have exactly one @id field.`,
|
|
@@ -863,7 +855,7 @@ function interpretPslDocumentToMongoContract(input) {
|
|
|
863
855
|
const valueObjects = {};
|
|
864
856
|
for (const compositeType of allCompositeTypes) {
|
|
865
857
|
const fields = {};
|
|
866
|
-
for (const field of compositeType.fields) {
|
|
858
|
+
for (const field of Object.values(compositeType.fields)) {
|
|
867
859
|
const resolved = resolveNonRelationField(field, compositeType.name, compositeTypeNames, scalarTypeDescriptors, sourceId, diagnostics);
|
|
868
860
|
if (!resolved) continue;
|
|
869
861
|
fields[field.name] = resolved;
|
|
@@ -912,12 +904,12 @@ function interpretPslDocumentToMongoContract(input) {
|
|
|
912
904
|
}
|
|
913
905
|
};
|
|
914
906
|
}
|
|
915
|
-
const { discriminatorDeclarations, baseDeclarations } = collectPolymorphismDeclarations(
|
|
907
|
+
const { discriminatorDeclarations, baseDeclarations } = collectPolymorphismDeclarations(allModels, sourceId, diagnostics);
|
|
916
908
|
const polyResult = resolvePolymorphism({
|
|
917
909
|
models,
|
|
918
910
|
roots,
|
|
919
911
|
collections,
|
|
920
|
-
|
|
912
|
+
allModels,
|
|
921
913
|
discriminatorDeclarations,
|
|
922
914
|
baseDeclarations,
|
|
923
915
|
modelNames,
|
|
@@ -945,28 +937,29 @@ function interpretPslDocumentToMongoContract(input) {
|
|
|
945
937
|
}
|
|
946
938
|
const target = "mongo";
|
|
947
939
|
const targetFamily = "mongo";
|
|
948
|
-
const
|
|
940
|
+
const collectionInputs = {};
|
|
949
941
|
for (const [name, coll] of Object.entries(resolvedCollections)) {
|
|
950
|
-
const
|
|
951
|
-
if (coll["indexes"]
|
|
952
|
-
if (coll["validator"]
|
|
953
|
-
if (coll["options"]
|
|
954
|
-
|
|
942
|
+
const raw = {};
|
|
943
|
+
if (coll["indexes"] != null) raw["indexes"] = coll["indexes"];
|
|
944
|
+
if (coll["validator"] != null) raw["validator"] = coll["validator"];
|
|
945
|
+
if (coll["options"] != null) raw["options"] = coll["options"];
|
|
946
|
+
collectionInputs[name] = blindCast(raw);
|
|
955
947
|
}
|
|
948
|
+
const unboundNamespace = buildMongoNamespace({
|
|
949
|
+
id: UNBOUND_NAMESPACE_ID,
|
|
950
|
+
entries: { collection: collectionInputs }
|
|
951
|
+
});
|
|
956
952
|
const storage = new MongoStorage({
|
|
957
953
|
storageHash: computeStorageHash({
|
|
958
954
|
target,
|
|
959
955
|
targetFamily,
|
|
960
956
|
storage: { namespaces: { [UNBOUND_NAMESPACE_ID]: {
|
|
961
957
|
id: UNBOUND_NAMESPACE_ID,
|
|
962
|
-
entries: { collection:
|
|
958
|
+
entries: { collection: unboundNamespace.entries.collection }
|
|
963
959
|
} } },
|
|
964
960
|
...mongoContractCanonicalizationHooks
|
|
965
961
|
}),
|
|
966
|
-
namespaces: { [UNBOUND_NAMESPACE_ID]:
|
|
967
|
-
id: UNBOUND_NAMESPACE_ID,
|
|
968
|
-
entries: { collection: collectionsAsClasses }
|
|
969
|
-
}) }
|
|
962
|
+
namespaces: { [UNBOUND_NAMESPACE_ID]: unboundNamespace }
|
|
970
963
|
});
|
|
971
964
|
const capabilities = {};
|
|
972
965
|
return ok({
|
|
@@ -991,4 +984,4 @@ function interpretPslDocumentToMongoContract(input) {
|
|
|
991
984
|
//#endregion
|
|
992
985
|
export { interpretPslDocumentToMongoContract as t };
|
|
993
986
|
|
|
994
|
-
//# sourceMappingURL=interpreter-
|
|
987
|
+
//# sourceMappingURL=interpreter-DCiVHDlW.mjs.map
|