@prisma-next/mongo-contract-psl 0.14.0-dev.3 → 0.14.0-dev.30

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.
@@ -1 +1 @@
1
- {"version":3,"file":"provider.d.mts","names":[],"sources":["../../src/provider.ts"],"mappings":";;;UAOiB,oBAAA;EAAA,SACN,MAAM;AAAA;AAAA,iBAGD,aAAA,CAAc,UAAA,UAAoB,OAAA,GAAU,oBAAA,GAAuB,cAAc"}
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-Cj1vigKn.mjs";
1
+ import { t as interpretPslDocumentToMongoContract } from "../interpreter-CDnf61pR.mjs";
2
+ import { buildSymbolTable, rangeToPslSpan } from "@prisma-next/psl-parser";
3
+ import { ifDefined } from "@prisma-next/utils/defined";
2
4
  import { notOk, ok } from "@prisma-next/utils/result";
3
- import { parsePslDocument } from "@prisma-next/psl-parser";
4
5
  import { readFile } from "node:fs/promises";
5
- import { ifDefined } from "@prisma-next/utils/defined";
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,13 +40,21 @@ 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
- document: parsePslDocument({
35
- schema,
36
- sourceId: schemaPath
37
- }),
51
+ symbolTable,
52
+ sourceFile,
53
+ sourceId: schemaPath,
54
+ seedDiagnostics: [...mapParseDiagnostics(parseDiagnostics, sourceFile, schemaPath), ...mapParseDiagnostics(symbolTableDiagnostics, sourceFile, schemaPath)],
38
55
  scalarTypeDescriptors: context.scalarTypeDescriptors,
39
- codecLookup: context.codecLookup
56
+ codecLookup: context.codecLookup,
57
+ authoringContributions: context.authoringContributions
40
58
  });
41
59
  if (!interpreted.ok) return interpreted;
42
60
  return ok(interpreted.value);
@@ -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 { parsePslDocument } from '@prisma-next/psl-parser';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { notOk, ok } from '@prisma-next/utils/result';\nimport { interpretPslDocumentToMongoContract } from './interpreter';\n\nexport interface MongoContractOptions {\n readonly output?: string;\n}\n\nexport function mongoContract(schemaPath: string, options?: MongoContractOptions): ContractConfig {\n return {\n source: {\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 = parsePslDocument({\n schema,\n sourceId: schemaPath,\n });\n\n const interpreted = interpretPslDocumentToMongoContract({\n document,\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":";;;;;;AAWA,SAAgB,cAAc,YAAoB,SAAgD;CAChG,OAAO;EACL,QAAQ;GACN,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;IAOA,MAAM,cAAc,oCAAoC;KACtD,UANe,iBAAiB;MAChC;MACA,UAAU;KACZ,CAGS;KACP,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"}
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 authoringContributions: context.authoringContributions,\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;KACrB,wBAAwB,QAAQ;IAClC,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,16 +1,31 @@
1
- import { Contract } from "@prisma-next/contract/types";
1
+ import { MongoValidator } from "@prisma-next/mongo-contract";
2
+ import { Contract, ContractEnum, ContractField, ContractValueObject } from "@prisma-next/contract/types";
3
+ import { AuthoringContributions } from "@prisma-next/framework-components/authoring";
4
+ import { SymbolTable } from "@prisma-next/psl-parser";
2
5
  import { Result } from "@prisma-next/utils/result";
3
- import { ParsePslDocumentResult } from "@prisma-next/psl-parser";
4
- import { ContractSourceDiagnostics } from "@prisma-next/config/config-types";
6
+ import { SourceFile } from "@prisma-next/psl-parser/syntax";
5
7
  import { CodecLookup } from "@prisma-next/framework-components/codec";
8
+ import { ContractSourceDiagnostic, ContractSourceDiagnostics } from "@prisma-next/config/config-types";
6
9
 
10
+ //#region src/derive-json-schema.d.ts
11
+ declare function deriveJsonSchema(fields: Record<string, ContractField>, valueObjects?: Record<string, ContractValueObject>, codecLookup?: CodecLookup, enums?: Record<string, ContractEnum>): MongoValidator;
12
+ interface PolymorphicVariant {
13
+ readonly discriminatorValue: string;
14
+ readonly fields: Record<string, ContractField>;
15
+ }
16
+ declare function derivePolymorphicJsonSchema(baseFields: Record<string, ContractField>, discriminatorField: string, variants: readonly PolymorphicVariant[], valueObjects?: Record<string, ContractValueObject>, codecLookup?: CodecLookup, enums?: Record<string, ContractEnum>): MongoValidator;
17
+ //#endregion
7
18
  //#region src/interpreter.d.ts
8
19
  interface InterpretPslDocumentToMongoContractInput {
9
- readonly document: ParsePslDocumentResult;
20
+ readonly symbolTable: SymbolTable;
21
+ readonly sourceFile: SourceFile;
22
+ readonly sourceId: string;
10
23
  readonly scalarTypeDescriptors: ReadonlyMap<string, string>;
11
24
  readonly codecLookup?: CodecLookup;
25
+ readonly seedDiagnostics?: readonly ContractSourceDiagnostic[];
26
+ readonly authoringContributions?: AuthoringContributions;
12
27
  }
13
28
  declare function interpretPslDocumentToMongoContract(input: InterpretPslDocumentToMongoContractInput): Result<Contract, ContractSourceDiagnostics>;
14
29
  //#endregion
15
- export { type InterpretPslDocumentToMongoContractInput, interpretPslDocumentToMongoContract };
30
+ export { type InterpretPslDocumentToMongoContractInput, deriveJsonSchema, derivePolymorphicJsonSchema, interpretPslDocumentToMongoContract };
16
31
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/interpreter.ts"],"mappings":";;;;;;;UA8CiB,wCAAA;EAAA,SACN,QAAA,EAAU,sBAAA;EAAA,SACV,qBAAA,EAAuB,WAAA;EAAA,SACvB,WAAA,GAAc,WAAA;AAAA;AAAA,iBAiyBT,mCAAA,CACd,KAAA,EAAO,wCAAA,GACN,MAAA,CAAO,QAAA,EAAU,yBAAA"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/derive-json-schema.ts","../src/interpreter.ts"],"mappings":";;;;;;;;;;iBA6FgB,gBAAA,CACd,MAAA,EAAQ,MAAA,SAAe,aAAA,GACvB,YAAA,GAAe,MAAA,SAAe,mBAAA,GAC9B,WAAA,GAAc,WAAA,EACd,KAAA,GAAQ,MAAA,SAAe,YAAA,IACtB,cAAA;AAAA,UAQc,kBAAA;EAAA,SACN,kBAAA;EAAA,SACA,MAAA,EAAQ,MAAM,SAAS,aAAA;AAAA;AAAA,iBAGlB,2BAAA,CACd,UAAA,EAAY,MAAA,SAAe,aAAA,GAC3B,kBAAA,UACA,QAAA,WAAmB,kBAAA,IACnB,YAAA,GAAe,MAAA,SAAe,mBAAA,GAC9B,WAAA,GAAc,WAAA,EACd,KAAA,GAAQ,MAAA,SAAe,YAAA,IACtB,cAAA;;;UCtDc,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;EAAA,SAC3B,sBAAA,GAAyB,sBAAA;AAAA;AAAA,iBA41BpB,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-Cj1vigKn.mjs";
2
- export { interpretPslDocumentToMongoContract };
1
+ import { n as deriveJsonSchema, r as derivePolymorphicJsonSchema, t as interpretPslDocumentToMongoContract } from "./interpreter-CDnf61pR.mjs";
2
+ export { deriveJsonSchema, derivePolymorphicJsonSchema, interpretPslDocumentToMongoContract };
@@ -1,30 +1,43 @@
1
+ import { MongoIndex, MongoStorage, MongoValidator, applyPolymorphicScopeToMongoIndex, buildMongoNamespace } from "@prisma-next/mongo-contract";
1
2
  import { computeProfileHash, computeStorageHash } from "@prisma-next/contract/hashing";
2
3
  import { crossRef } from "@prisma-next/contract/types";
4
+ import { instantiateAuthoringEntityType, isAuthoringEntityTypeDescriptor } from "@prisma-next/framework-components/authoring";
3
5
  import { UNBOUND_NAMESPACE_ID } from "@prisma-next/framework-components/ir";
4
- import { MongoIndex, MongoStorage, MongoValidator, applyPolymorphicScopeToMongoIndex, buildMongoNamespace } from "@prisma-next/mongo-contract";
5
6
  import { mongoContractCanonicalizationHooks } from "@prisma-next/mongo-contract/canonicalization-hooks";
7
+ import { nodePslSpan, parseQuotedStringLiteral } from "@prisma-next/psl-parser";
6
8
  import { blindCast } from "@prisma-next/utils/casts";
9
+ import { ifDefined } from "@prisma-next/utils/defined";
7
10
  import { notOk, ok } from "@prisma-next/utils/result";
8
- import { getPositionalArgument, parseQuotedStringLiteral } from "@prisma-next/psl-parser";
9
11
  //#region src/derive-json-schema.ts
10
12
  function resolveBsonType(codecId, codecLookup) {
11
13
  return codecLookup?.targetTypesFor(codecId)?.[0];
12
14
  }
13
- function fieldToBsonSchema(field, valueObjects, codecLookup) {
15
+ function fieldToBsonSchema(field, valueObjects, codecLookup, enums) {
14
16
  if (field.type.kind === "scalar") {
15
17
  const bsonType = resolveBsonType(field.type.codecId, codecLookup);
16
18
  if (!bsonType) return void 0;
17
- if ("many" in field && field.many) return {
18
- bsonType: "array",
19
- items: { bsonType }
20
- };
21
- if (field.nullable) return { bsonType: ["null", bsonType] };
22
- return { bsonType };
19
+ const enumValues = field.valueSet?.entityKind === "enum" ? enums?.[field.valueSet.entityName]?.members.map((m) => m.value) ?? null : null;
20
+ if ("many" in field && field.many) {
21
+ const items = { bsonType };
22
+ if (enumValues) items["enum"] = enumValues;
23
+ return {
24
+ bsonType: "array",
25
+ items
26
+ };
27
+ }
28
+ if (field.nullable) {
29
+ const s = { bsonType: ["null", bsonType] };
30
+ if (enumValues) s["enum"] = [...enumValues, null];
31
+ return s;
32
+ }
33
+ const s = { bsonType };
34
+ if (enumValues) s["enum"] = enumValues;
35
+ return s;
23
36
  }
24
37
  if (field.type.kind === "valueObject") {
25
38
  const vo = valueObjects?.[field.type.name];
26
39
  if (!vo) return void 0;
27
- const voSchema = deriveObjectSchema(vo.fields, valueObjects, codecLookup);
40
+ const voSchema = deriveObjectSchema(vo.fields, valueObjects, codecLookup, enums);
28
41
  if ("many" in field && field.many) return {
29
42
  bsonType: "array",
30
43
  items: voSchema
@@ -33,11 +46,11 @@ function fieldToBsonSchema(field, valueObjects, codecLookup) {
33
46
  return voSchema;
34
47
  }
35
48
  }
36
- function deriveObjectSchema(fields, valueObjects, codecLookup) {
49
+ function deriveObjectSchema(fields, valueObjects, codecLookup, enums) {
37
50
  const properties = {};
38
51
  const required = [];
39
52
  for (const [fieldName, field] of Object.entries(fields)) {
40
- const schema = fieldToBsonSchema(field, valueObjects, codecLookup);
53
+ const schema = fieldToBsonSchema(field, valueObjects, codecLookup, enums);
41
54
  if (schema) {
42
55
  properties[fieldName] = schema;
43
56
  if (!field.nullable) required.push(fieldName);
@@ -54,15 +67,15 @@ function deriveObjectSchema(fields, valueObjects, codecLookup) {
54
67
  function isRecord(value) {
55
68
  return typeof value === "object" && value !== null && !Array.isArray(value);
56
69
  }
57
- function deriveJsonSchema(fields, valueObjects, codecLookup) {
70
+ function deriveJsonSchema(fields, valueObjects, codecLookup, enums) {
58
71
  return new MongoValidator({
59
- jsonSchema: deriveObjectSchema(fields, valueObjects, codecLookup),
72
+ jsonSchema: deriveObjectSchema(fields, valueObjects, codecLookup, enums),
60
73
  validationLevel: "strict",
61
74
  validationAction: "error"
62
75
  });
63
76
  }
64
- function derivePolymorphicJsonSchema(baseFields, discriminatorField, variants, valueObjects, codecLookup) {
65
- const baseSchema = deriveObjectSchema(baseFields, valueObjects, codecLookup);
77
+ function derivePolymorphicJsonSchema(baseFields, discriminatorField, variants, valueObjects, codecLookup, enums) {
78
+ const baseSchema = deriveObjectSchema(baseFields, valueObjects, codecLookup, enums);
66
79
  const baseProperties = isRecord(baseSchema["properties"]) ? baseSchema["properties"] : {};
67
80
  const oneOf = [];
68
81
  for (const variant of variants) {
@@ -71,7 +84,7 @@ function derivePolymorphicJsonSchema(baseFields, discriminatorField, variants, v
71
84
  const variantProperties = {};
72
85
  const variantRequired = [discriminatorField];
73
86
  for (const [name, field] of Object.entries(variantOnlyFields)) {
74
- const schema = fieldToBsonSchema(field, valueObjects, codecLookup);
87
+ const schema = fieldToBsonSchema(field, valueObjects, codecLookup, enums);
75
88
  if (schema) {
76
89
  variantProperties[name] = schema;
77
90
  if (!field.nullable) variantRequired.push(name);
@@ -99,6 +112,9 @@ function derivePolymorphicJsonSchema(baseFields, discriminatorField, variants, v
99
112
  }
100
113
  //#endregion
101
114
  //#region src/psl-helpers.ts
115
+ function getPositionalArgument(attr, index = 0) {
116
+ return attr.args.filter((arg) => arg.kind === "positional")[index]?.value;
117
+ }
102
118
  function getNamedArgument(attr, name) {
103
119
  return attr.args.find((a) => a.kind === "named" && a.name === name)?.value;
104
120
  }
@@ -173,9 +189,9 @@ function parseRelationAttribute(attributes) {
173
189
  const fields = fieldsArg ? parseFieldList(fieldsArg.value) : void 0;
174
190
  const references = referencesArg ? parseFieldList(referencesArg.value) : void 0;
175
191
  return {
176
- ...relationName !== void 0 ? { relationName } : {},
177
- ...fields !== void 0 ? { fields } : {},
178
- ...references !== void 0 ? { references } : {}
192
+ ...ifDefined("relationName", relationName),
193
+ ...ifDefined("fields", fields),
194
+ ...ifDefined("references", references)
179
195
  };
180
196
  }
181
197
  function stripQuotes(value) {
@@ -185,37 +201,23 @@ function stripQuotes(value) {
185
201
  //#endregion
186
202
  //#region src/interpreter.ts
187
203
  /**
188
- * Name of the framework-parser synthesised bucket for top-level
189
- * declarations. Re-declared locally so the interpreter does not have to
190
- * import from `@prisma-next/framework-components/psl-ast`.
191
- */
192
- const UNSPECIFIED_PSL_NAMESPACE_NAME = "__unspecified__";
193
- /**
194
- * Mongo FR16c validation: Mongo's authoring DSL exposes the connection's
195
- * database as the only namespace surface today, so the PSL interpreter
196
- * rejects every explicit `namespace { … }` block. The implicit
197
- * `__unspecified__` bucket (top-level declarations) is the only
198
- * namespace Mongo accepts. `namespace unbound { … }` is rejected too —
199
- * Mongo has no late-binding namespace concept on the PSL surface (the
200
- * database name comes from the connection string, not from PSL).
204
+ * Mongo's PSL surface binds the database from the connection string, so every
205
+ * explicit namespace block is invalid, including `namespace unbound { … }`.
201
206
  */
202
207
  function validateNamespaceBlocksForMongoTarget(input) {
203
- for (const namespace of input.namespaces) {
204
- if (namespace.name === UNSPECIFIED_PSL_NAMESPACE_NAME) continue;
205
- input.diagnostics.push({
206
- code: "PSL_UNSUPPORTED_NAMESPACE_BLOCK",
207
- 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).`,
208
- sourceId: input.sourceId,
209
- span: namespace.span
210
- });
211
- }
208
+ for (const namespace of input.namespaces) input.diagnostics.push({
209
+ code: "PSL_UNSUPPORTED_NAMESPACE_BLOCK",
210
+ 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).`,
211
+ sourceId: input.sourceId,
212
+ span: nodePslSpan(namespace.node.syntax, input.sourceFile)
213
+ });
212
214
  }
213
215
  function fkRelationPairKey(declaringModel, targetModel) {
214
216
  return `${declaringModel}::${targetModel}`;
215
217
  }
216
218
  function resolveFieldMappings(model) {
217
219
  const pslNameToMapped = /* @__PURE__ */ new Map();
218
- for (const field of model.fields) {
220
+ for (const field of Object.values(model.fields)) {
219
221
  const mapped = getMapName(field.attributes) ?? field.name;
220
222
  pslNameToMapped.set(field.name, mapped);
221
223
  }
@@ -227,33 +229,32 @@ function resolveCollectionName(model) {
227
229
  function mongoCrossRef(modelName) {
228
230
  return crossRef(modelName, UNBOUND_NAMESPACE_ID);
229
231
  }
230
- function collectPolymorphismDeclarations(document, sourceId, diagnostics) {
232
+ function collectPolymorphismDeclarations(models, sourceId, diagnostics) {
231
233
  const discriminatorDeclarations = /* @__PURE__ */ new Map();
232
234
  const baseDeclarations = /* @__PURE__ */ new Map();
233
- const allPslModels = document.ast.namespaces.flatMap((ns) => ns.models);
234
- for (const pslModel of allPslModels) for (const attr of pslModel.attributes) {
235
+ for (const model of models) for (const attr of model.attributes) {
235
236
  if (attr.name === "discriminator") {
236
237
  const fieldName = getPositionalArgument(attr);
237
238
  if (!fieldName) {
238
239
  diagnostics.push({
239
240
  code: "PSL_INVALID_ATTRIBUTE_ARGUMENT",
240
- message: `Model "${pslModel.name}" @@discriminator requires a field name argument`,
241
+ message: `Model "${model.name}" @@discriminator requires a field name argument`,
241
242
  sourceId,
242
243
  span: attr.span
243
244
  });
244
245
  continue;
245
246
  }
246
- const discField = pslModel.fields.find((f) => f.name === fieldName);
247
+ const discField = model.fields[fieldName];
247
248
  if (discField && discField.typeName !== "String") {
248
249
  diagnostics.push({
249
250
  code: "PSL_INVALID_ATTRIBUTE_ARGUMENT",
250
- message: `Discriminator field "${fieldName}" on model "${pslModel.name}" must be of type String, but is "${discField.typeName}"`,
251
+ message: `Discriminator field "${fieldName}" on model "${model.name}" must be of type String, but is "${discField.typeName}"`,
251
252
  sourceId,
252
253
  span: attr.span
253
254
  });
254
255
  continue;
255
256
  }
256
- discriminatorDeclarations.set(pslModel.name, {
257
+ discriminatorDeclarations.set(model.name, {
257
258
  fieldName,
258
259
  span: attr.span
259
260
  });
@@ -264,7 +265,7 @@ function collectPolymorphismDeclarations(document, sourceId, diagnostics) {
264
265
  if (!baseName || !rawValue) {
265
266
  diagnostics.push({
266
267
  code: "PSL_INVALID_ATTRIBUTE_ARGUMENT",
267
- message: `Model "${pslModel.name}" @@base requires two arguments: base model name and discriminator value`,
268
+ message: `Model "${model.name}" @@base requires two arguments: base model name and discriminator value`,
268
269
  sourceId,
269
270
  span: attr.span
270
271
  });
@@ -274,14 +275,14 @@ function collectPolymorphismDeclarations(document, sourceId, diagnostics) {
274
275
  if (value === void 0) {
275
276
  diagnostics.push({
276
277
  code: "PSL_INVALID_ATTRIBUTE_ARGUMENT",
277
- message: `Model "${pslModel.name}" @@base discriminator value must be a quoted string literal`,
278
+ message: `Model "${model.name}" @@base discriminator value must be a quoted string literal`,
278
279
  sourceId,
279
280
  span: attr.span
280
281
  });
281
282
  continue;
282
283
  }
283
- const collectionName = resolveCollectionName(pslModel);
284
- baseDeclarations.set(pslModel.name, {
284
+ const collectionName = resolveCollectionName(model);
285
+ baseDeclarations.set(model.name, {
285
286
  baseName,
286
287
  value,
287
288
  collectionName,
@@ -295,8 +296,7 @@ function collectPolymorphismDeclarations(document, sourceId, diagnostics) {
295
296
  };
296
297
  }
297
298
  function resolvePolymorphism(input) {
298
- const { discriminatorDeclarations, baseDeclarations, modelNames, sourceId, document, indexSpans, modelIndexesByName } = input;
299
- const allPslModels = document.ast.namespaces.flatMap((ns) => ns.models);
299
+ const { discriminatorDeclarations, baseDeclarations, modelNames, sourceId, allModels: allModelViews, indexSpans, modelIndexesByName } = input;
300
300
  let patched = input.models;
301
301
  let roots = input.roots;
302
302
  let collections = input.collections;
@@ -313,8 +313,8 @@ function resolvePolymorphism(input) {
313
313
  }
314
314
  const model = patched[modelName];
315
315
  if (!model) continue;
316
- const pslModel = allPslModels.find((m) => m.name === modelName);
317
- const mappedDiscriminatorField = pslModel ? resolveFieldMappings(pslModel).pslNameToMapped.get(decl.fieldName) ?? decl.fieldName : decl.fieldName;
316
+ const modelView = allModelViews.find((m) => m.name === modelName);
317
+ const mappedDiscriminatorField = modelView ? resolveFieldMappings(modelView).pslNameToMapped.get(decl.fieldName) ?? decl.fieldName : decl.fieldName;
318
318
  if (!Object.hasOwn(model.fields, mappedDiscriminatorField)) {
319
319
  diagnostics.push({
320
320
  code: "PSL_DISCRIMINATOR_FIELD_NOT_FOUND",
@@ -368,9 +368,9 @@ function resolvePolymorphism(input) {
368
368
  }
369
369
  if (discriminatorDeclarations.has(variantName)) continue;
370
370
  const baseModel = patched[baseDecl.baseName];
371
- const variantPslModel = allPslModels.find((m) => m.name === variantName);
372
- if (!variantPslModel) continue;
373
- if (getMapName(variantPslModel.attributes) !== void 0 && baseModel && baseDecl.collectionName !== baseModel.storage.collection) {
371
+ const variantModelView = allModelViews.find((m) => m.name === variantName);
372
+ if (!variantModelView) continue;
373
+ if (getMapName(variantModelView.attributes) !== void 0 && baseModel && baseDecl.collectionName !== baseModel.storage.collection) {
374
374
  diagnostics.push({
375
375
  code: "PSL_MONGO_VARIANT_SEPARATE_COLLECTION",
376
376
  message: `Mongo variant "${variantName}" cannot use a different collection than its base "${baseDecl.baseName}". Mongo only supports single-collection polymorphism.`,
@@ -389,7 +389,7 @@ function resolvePolymorphism(input) {
389
389
  storage: { collection: baseCollection }
390
390
  }
391
391
  };
392
- const variantCollectionName = resolveCollectionName(variantPslModel);
392
+ const variantCollectionName = resolveCollectionName(variantModelView);
393
393
  if (roots[variantCollectionName]?.model === variantName) if (variantCollectionName === baseCollection && baseModel) roots = {
394
394
  ...roots,
395
395
  [variantCollectionName]: mongoCrossRef(baseDecl.baseName)
@@ -531,11 +531,11 @@ function collectIndexes(pslModel, fieldMappings, modelNames, sourceId, diagnosti
531
531
  const indexes = [];
532
532
  let textIndexCount = 0;
533
533
  const indexableFieldNames = /* @__PURE__ */ new Set();
534
- for (const f of pslModel.fields) {
534
+ for (const f of Object.values(pslModel.fields)) {
535
535
  if (modelNames.has(f.typeName)) continue;
536
536
  indexableFieldNames.add(f.name);
537
537
  }
538
- for (const field of pslModel.fields) {
538
+ for (const field of Object.values(pslModel.fields)) {
539
539
  if (modelNames.has(field.typeName)) continue;
540
540
  const uniqueAttr = getAttribute(field.attributes, "unique");
541
541
  if (!uniqueAttr) continue;
@@ -729,7 +729,7 @@ const MONGO_OBJECT_ID_PSL_TYPE = "ObjectId";
729
729
  function resolveFieldCodecId(field, scalarTypeDescriptors) {
730
730
  return scalarTypeDescriptors.get(field.typeName);
731
731
  }
732
- function resolveNonRelationField(field, ownerName, compositeTypeNames, scalarTypeDescriptors, sourceId, diagnostics) {
732
+ function resolveNonRelationField(field, ownerName, compositeTypeNames, scalarTypeDescriptors, codecIdByEnumName, sourceId, diagnostics) {
733
733
  if (compositeTypeNames.has(field.typeName)) {
734
734
  const result = {
735
735
  type: {
@@ -743,6 +743,28 @@ function resolveNonRelationField(field, ownerName, compositeTypeNames, scalarTyp
743
743
  many: true
744
744
  } : result;
745
745
  }
746
+ const enumCodecId = codecIdByEnumName.get(field.typeName);
747
+ if (enumCodecId !== void 0) {
748
+ const valueSet = {
749
+ plane: "domain",
750
+ entityKind: "enum",
751
+ namespaceId: UNBOUND_NAMESPACE_ID,
752
+ entityName: field.typeName
753
+ };
754
+ const result = {
755
+ type: {
756
+ kind: "scalar",
757
+ codecId: enumCodecId
758
+ },
759
+ nullable: field.optional,
760
+ valueSet
761
+ };
762
+ return field.list ? {
763
+ ...result,
764
+ many: true
765
+ } : result;
766
+ }
767
+ if (field.malformedType) return;
746
768
  const codecId = resolveFieldCodecId(field, scalarTypeDescriptors);
747
769
  if (!codecId) {
748
770
  diagnostics.push({
@@ -765,19 +787,63 @@ function resolveNonRelationField(field, ownerName, compositeTypeNames, scalarTyp
765
787
  many: true
766
788
  } : result;
767
789
  }
790
+ function processEnumDeclarations(input) {
791
+ const builtEnums = {};
792
+ if (input.enumBlocks.length === 0) return builtEnums;
793
+ const enumDescriptor = input.authoringContributions?.entityTypes?.["enum"] !== void 0 && isAuthoringEntityTypeDescriptor(input.authoringContributions.entityTypes["enum"]) ? input.authoringContributions.entityTypes["enum"] : void 0;
794
+ if (!enumDescriptor) {
795
+ for (const decl of input.enumBlocks) input.diagnostics.push({
796
+ code: "PSL_ENUM_MISSING_FACTORY",
797
+ message: `enum "${decl.name}" requires an "enum" entityType factory in the active authoring contributions`,
798
+ sourceId: input.sourceId,
799
+ span: decl.span
800
+ });
801
+ return builtEnums;
802
+ }
803
+ for (const decl of input.enumBlocks) {
804
+ const handle = instantiateAuthoringEntityType("enum", enumDescriptor, [decl], input.entityContext);
805
+ if (handle === void 0 || handle === null) continue;
806
+ builtEnums[decl.name] = {
807
+ codecId: handle.codecId,
808
+ members: handle.enumMembers.map((m) => ({
809
+ name: m.name,
810
+ value: blindCast(m.value)
811
+ }))
812
+ };
813
+ }
814
+ return builtEnums;
815
+ }
768
816
  function interpretPslDocumentToMongoContract(input) {
769
- const { document, scalarTypeDescriptors, codecLookup } = input;
770
- const sourceId = document.ast.sourceId;
771
- const diagnostics = [];
817
+ const { symbolTable, sourceFile, scalarTypeDescriptors, codecLookup } = input;
818
+ const sourceId = input.sourceId;
819
+ const diagnostics = [...input.seedDiagnostics ?? []];
820
+ const topLevel = symbolTable.topLevel;
772
821
  validateNamespaceBlocksForMongoTarget({
773
- namespaces: document.ast.namespaces,
822
+ namespaces: Object.values(topLevel.namespaces),
774
823
  sourceId,
824
+ sourceFile,
775
825
  diagnostics
776
826
  });
777
- const allModels = document.ast.namespaces.flatMap((ns) => ns.models);
778
- const allCompositeTypes = document.ast.namespaces.flatMap((ns) => ns.compositeTypes);
827
+ const allModels = Object.values(topLevel.models);
828
+ const allCompositeTypes = Object.values(topLevel.compositeTypes);
779
829
  const modelNames = new Set(allModels.map((m) => m.name));
780
830
  const compositeTypeNames = new Set(allCompositeTypes.map((ct) => ct.name));
831
+ const builtEnums = processEnumDeclarations({
832
+ enumBlocks: Object.values(topLevel.blocks).filter((b) => b.keyword === "enum").map((b) => b.block),
833
+ sourceId,
834
+ authoringContributions: input.authoringContributions,
835
+ entityContext: {
836
+ family: "mongo",
837
+ target: "mongo",
838
+ ...ifDefined("codecLookup", codecLookup),
839
+ sourceId,
840
+ diagnostics: { push: (d) => {
841
+ diagnostics.push(blindCast(d));
842
+ } }
843
+ },
844
+ diagnostics
845
+ });
846
+ const codecIdByEnumName = new Map(Object.entries(builtEnums).map(([name, e]) => [name, e.codecId]));
781
847
  const models = {};
782
848
  const collections = {};
783
849
  const roots = {};
@@ -790,7 +856,7 @@ function interpretPslDocumentToMongoContract(input) {
790
856
  const fieldMappings = resolveFieldMappings(pslModel);
791
857
  const fields = {};
792
858
  const relations = {};
793
- for (const field of pslModel.fields) {
859
+ for (const field of Object.values(pslModel.fields)) {
794
860
  if (isRelationField(field, modelNames)) {
795
861
  const relation = parseRelationAttribute(field.attributes);
796
862
  if (field.list || !(relation?.fields && relation?.references)) {
@@ -798,7 +864,7 @@ function interpretPslDocumentToMongoContract(input) {
798
864
  modelName: pslModel.name,
799
865
  fieldName: field.name,
800
866
  targetModelName: field.typeName,
801
- ...relation?.relationName !== void 0 ? { relationName: relation.relationName } : {},
867
+ ...ifDefined("relationName", relation?.relationName),
802
868
  cardinality: field.list ? "1:N" : "1:1",
803
869
  field
804
870
  });
@@ -821,20 +887,20 @@ function interpretPslDocumentToMongoContract(input) {
821
887
  declaringModel: pslModel.name,
822
888
  fieldName: field.name,
823
889
  targetModel: field.typeName,
824
- ...relation.relationName !== void 0 ? { relationName: relation.relationName } : {},
890
+ ...ifDefined("relationName", relation.relationName),
825
891
  localFields: localMapped,
826
892
  targetFields: targetMapped
827
893
  });
828
894
  }
829
895
  continue;
830
896
  }
831
- const resolved = resolveNonRelationField(field, pslModel.name, compositeTypeNames, scalarTypeDescriptors, sourceId, diagnostics);
897
+ const resolved = resolveNonRelationField(field, pslModel.name, compositeTypeNames, scalarTypeDescriptors, codecIdByEnumName, sourceId, diagnostics);
832
898
  if (!resolved) continue;
833
899
  const mappedName = fieldMappings.pslNameToMapped.get(field.name) ?? field.name;
834
900
  fields[mappedName] = resolved;
835
901
  }
836
902
  const isVariantModel = pslModel.attributes.some((attr) => attr.name === "base");
837
- const hasIdField = pslModel.fields.some((f) => getAttribute(f.attributes, "id") !== void 0);
903
+ const hasIdField = Object.values(pslModel.fields).some((f) => getAttribute(f.attributes, "id") !== void 0);
838
904
  if (!isVariantModel) if (!hasIdField) diagnostics.push({
839
905
  code: "PSL_MISSING_ID_FIELD",
840
906
  message: `Model "${pslModel.name}" has no field with @id attribute. Every model must have exactly one @id field.`,
@@ -864,8 +930,8 @@ function interpretPslDocumentToMongoContract(input) {
864
930
  const valueObjects = {};
865
931
  for (const compositeType of allCompositeTypes) {
866
932
  const fields = {};
867
- for (const field of compositeType.fields) {
868
- const resolved = resolveNonRelationField(field, compositeType.name, compositeTypeNames, scalarTypeDescriptors, sourceId, diagnostics);
933
+ for (const field of Object.values(compositeType.fields)) {
934
+ const resolved = resolveNonRelationField(field, compositeType.name, compositeTypeNames, scalarTypeDescriptors, codecIdByEnumName, sourceId, diagnostics);
869
935
  if (!resolved) continue;
870
936
  fields[field.name] = resolved;
871
937
  }
@@ -913,12 +979,12 @@ function interpretPslDocumentToMongoContract(input) {
913
979
  }
914
980
  };
915
981
  }
916
- const { discriminatorDeclarations, baseDeclarations } = collectPolymorphismDeclarations(document, sourceId, diagnostics);
982
+ const { discriminatorDeclarations, baseDeclarations } = collectPolymorphismDeclarations(allModels, sourceId, diagnostics);
917
983
  const polyResult = resolvePolymorphism({
918
984
  models,
919
985
  roots,
920
986
  collections,
921
- document,
987
+ allModels,
922
988
  discriminatorDeclarations,
923
989
  baseDeclarations,
924
990
  modelNames,
@@ -941,8 +1007,8 @@ function interpretPslDocumentToMongoContract(input) {
941
1007
  discriminatorValue: value,
942
1008
  fields: resolvedModels[variantName]?.fields ?? {}
943
1009
  }));
944
- coll["validator"] = derivePolymorphicJsonSchema(modelEntry.fields, modelEntry.discriminator.field, variantEntries, valueObjects, codecLookup);
945
- } else coll["validator"] = deriveJsonSchema(modelEntry.fields, valueObjects, codecLookup);
1010
+ coll["validator"] = derivePolymorphicJsonSchema(modelEntry.fields, modelEntry.discriminator.field, variantEntries, valueObjects, codecLookup, builtEnums);
1011
+ } else coll["validator"] = deriveJsonSchema(modelEntry.fields, valueObjects, codecLookup, builtEnums);
946
1012
  }
947
1013
  const target = "mongo";
948
1014
  const targetFamily = "mongo";
@@ -971,13 +1037,15 @@ function interpretPslDocumentToMongoContract(input) {
971
1037
  namespaces: { [UNBOUND_NAMESPACE_ID]: unboundNamespace }
972
1038
  });
973
1039
  const capabilities = {};
1040
+ const hasEnums = Object.keys(builtEnums).length > 0;
974
1041
  return ok({
975
1042
  targetFamily,
976
1043
  target,
977
1044
  roots: polyResult.roots,
978
1045
  domain: { namespaces: { [UNBOUND_NAMESPACE_ID]: {
979
1046
  models: polyResult.models,
980
- ...Object.keys(valueObjects).length > 0 ? { valueObjects } : {}
1047
+ ...Object.keys(valueObjects).length > 0 ? { valueObjects } : {},
1048
+ ...hasEnums ? { enum: builtEnums } : {}
981
1049
  } } },
982
1050
  storage,
983
1051
  extensionPacks: {},
@@ -991,6 +1059,6 @@ function interpretPslDocumentToMongoContract(input) {
991
1059
  });
992
1060
  }
993
1061
  //#endregion
994
- export { interpretPslDocumentToMongoContract as t };
1062
+ export { deriveJsonSchema as n, derivePolymorphicJsonSchema as r, interpretPslDocumentToMongoContract as t };
995
1063
 
996
- //# sourceMappingURL=interpreter-Cj1vigKn.mjs.map
1064
+ //# sourceMappingURL=interpreter-CDnf61pR.mjs.map