@prisma-next/mongo-contract-psl 0.14.0-dev.6 → 0.14.0-dev.61

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.
@@ -3,6 +3,11 @@ import { ContractConfig } from "@prisma-next/config/config-types";
3
3
  //#region src/provider.d.ts
4
4
  interface MongoContractOptions {
5
5
  readonly output?: string;
6
+ /** The target's default codec ids for an `enum` block that omits `@@type`. */
7
+ readonly enumInferenceCodecs?: {
8
+ readonly text: string;
9
+ readonly int: string;
10
+ };
6
11
  }
7
12
  declare function mongoContract(schemaPath: string, options?: MongoContractOptions): ContractConfig;
8
13
  //#endregion
@@ -1 +1 @@
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
+ {"version":3,"file":"provider.d.mts","names":[],"sources":["../../src/provider.ts"],"mappings":";;;UAUiB,oBAAA;EAAA,SACN,MAAA;EADM;EAAA,SAGN,mBAAA;IAAA,SAAiC,IAAA;IAAA,SAAuB,GAAA;EAAA;AAAA;AAAA,iBAgBnD,aAAA,CAAc,UAAA,UAAoB,OAAA,GAAU,oBAAA,GAAuB,cAAc"}
@@ -1,7 +1,7 @@
1
- import { t as interpretPslDocumentToMongoContract } from "../interpreter-DCiVHDlW.mjs";
1
+ import { t as interpretPslDocumentToMongoContract } from "../interpreter-D0vfRJ7f.mjs";
2
2
  import { buildSymbolTable, rangeToPslSpan } from "@prisma-next/psl-parser";
3
- import { notOk, ok } from "@prisma-next/utils/result";
4
3
  import { ifDefined } from "@prisma-next/utils/defined";
4
+ import { notOk, ok } from "@prisma-next/utils/result";
5
5
  import { readFile } from "node:fs/promises";
6
6
  import { parse } from "@prisma-next/psl-parser/syntax";
7
7
  //#region src/provider.ts
@@ -53,7 +53,9 @@ function mongoContract(schemaPath, options) {
53
53
  sourceId: schemaPath,
54
54
  seedDiagnostics: [...mapParseDiagnostics(parseDiagnostics, sourceFile, schemaPath), ...mapParseDiagnostics(symbolTableDiagnostics, sourceFile, schemaPath)],
55
55
  scalarTypeDescriptors: context.scalarTypeDescriptors,
56
- codecLookup: context.codecLookup
56
+ codecLookup: context.codecLookup,
57
+ authoringContributions: context.authoringContributions,
58
+ ...ifDefined("enumInferenceCodecs", options?.enumInferenceCodecs)
57
59
  });
58
60
  if (!interpreted.ok) return interpreted;
59
61
  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, 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"}
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 /** The target's default codec ids for an `enum` block that omits `@@type`. */\n readonly enumInferenceCodecs?: { readonly text: string; readonly int: 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 ...ifDefined('enumInferenceCodecs', options?.enumInferenceCodecs),\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":";;;;;;;AAgBA,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;KAChC,GAAG,UAAU,uBAAuB,SAAS,mBAAmB;IAClE,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,10 +1,28 @@
1
- import { Contract } from "@prisma-next/contract/types";
1
+ import { MongoValidator } from "@prisma-next/mongo-contract";
2
+ import { Contract, ContractField, ContractValueObject, JsonValue } from "@prisma-next/contract/types";
3
+ import { AuthoringContributions } from "@prisma-next/framework-components/authoring";
2
4
  import { SymbolTable } from "@prisma-next/psl-parser";
3
5
  import { Result } from "@prisma-next/utils/result";
4
6
  import { SourceFile } from "@prisma-next/psl-parser/syntax";
5
- import { ContractSourceDiagnostic, ContractSourceDiagnostics } from "@prisma-next/config/config-types";
6
7
  import { CodecLookup } from "@prisma-next/framework-components/codec";
8
+ import { ContractSourceDiagnostic, ContractSourceDiagnostics } from "@prisma-next/config/config-types";
7
9
 
10
+ //#region src/derive-json-schema.d.ts
11
+ /**
12
+ * The permitted values a field's value set restricts it to, keyed by the value set's name — the
13
+ * storage `entries.valueSet` slot. The validator's `enum` keyword is sourced from these, not from
14
+ * `domain.enum`.
15
+ */
16
+ type FieldValueSets = Record<string, {
17
+ readonly values: readonly JsonValue[];
18
+ }>;
19
+ declare function deriveJsonSchema(fields: Record<string, ContractField>, valueObjects?: Record<string, ContractValueObject>, codecLookup?: CodecLookup, valueSets?: FieldValueSets): MongoValidator;
20
+ interface PolymorphicVariant {
21
+ readonly discriminatorValue: string;
22
+ readonly fields: Record<string, ContractField>;
23
+ }
24
+ declare function derivePolymorphicJsonSchema(baseFields: Record<string, ContractField>, discriminatorField: string, variants: readonly PolymorphicVariant[], valueObjects?: Record<string, ContractValueObject>, codecLookup?: CodecLookup, valueSets?: FieldValueSets): MongoValidator;
25
+ //#endregion
8
26
  //#region src/interpreter.d.ts
9
27
  interface InterpretPslDocumentToMongoContractInput {
10
28
  readonly symbolTable: SymbolTable;
@@ -13,8 +31,14 @@ interface InterpretPslDocumentToMongoContractInput {
13
31
  readonly scalarTypeDescriptors: ReadonlyMap<string, string>;
14
32
  readonly codecLookup?: CodecLookup;
15
33
  readonly seedDiagnostics?: readonly ContractSourceDiagnostic[];
34
+ readonly authoringContributions?: AuthoringContributions;
35
+ /** The target's default codec ids for an `enum` block that omits `@@type`. */
36
+ readonly enumInferenceCodecs?: {
37
+ readonly text: string;
38
+ readonly int: string;
39
+ };
16
40
  }
17
41
  declare function interpretPslDocumentToMongoContract(input: InterpretPslDocumentToMongoContractInput): Result<Contract, ContractSourceDiagnostics>;
18
42
  //#endregion
19
- export { type InterpretPslDocumentToMongoContractInput, interpretPslDocumentToMongoContract };
43
+ export { type FieldValueSets, type InterpretPslDocumentToMongoContractInput, deriveJsonSchema, derivePolymorphicJsonSchema, interpretPslDocumentToMongoContract };
20
44
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
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"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/derive-json-schema.ts","../src/interpreter.ts"],"mappings":";;;;;;;;;;;;;;;KASY,cAAA,GAAiB,MAAM;EAAA,SAAoB,MAAA,WAAiB,SAAA;AAAA;AAAA,iBA2FxD,gBAAA,CACd,MAAA,EAAQ,MAAA,SAAe,aAAA,GACvB,YAAA,GAAe,MAAA,SAAe,mBAAA,GAC9B,WAAA,GAAc,WAAA,EACd,SAAA,GAAY,cAAA,GACX,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,SAAA,GAAY,cAAA,GACX,cAAA;;;UC3Cc,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;EDhFmB;EAAA,SCkF5C,mBAAA;IAAA,SAAiC,IAAA;IAAA,SAAuB,GAAA;EAAA;AAAA;AAAA,iBA41BnD,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-DCiVHDlW.mjs";
2
- export { interpretPslDocumentToMongoContract };
1
+ import { n as deriveJsonSchema, r as derivePolymorphicJsonSchema, t as interpretPslDocumentToMongoContract } from "./interpreter-D0vfRJ7f.mjs";
2
+ export { deriveJsonSchema, derivePolymorphicJsonSchema, interpretPslDocumentToMongoContract };
@@ -1,31 +1,45 @@
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 { errorEnumCodecNotInPackStack } from "@prisma-next/errors/control";
5
+ import { instantiateAuthoringEntityType, isAuthoringEntityTypeDescriptor } from "@prisma-next/framework-components/authoring";
3
6
  import { UNBOUND_NAMESPACE_ID } from "@prisma-next/framework-components/ir";
4
- import { MongoIndex, MongoStorage, MongoValidator, applyPolymorphicScopeToMongoIndex, buildMongoNamespace } from "@prisma-next/mongo-contract";
5
7
  import { mongoContractCanonicalizationHooks } from "@prisma-next/mongo-contract/canonicalization-hooks";
6
8
  import { nodePslSpan, parseQuotedStringLiteral } from "@prisma-next/psl-parser";
9
+ import { assertDefined } from "@prisma-next/utils/assertions";
7
10
  import { blindCast } from "@prisma-next/utils/casts";
8
- import { notOk, ok } from "@prisma-next/utils/result";
9
11
  import { ifDefined } from "@prisma-next/utils/defined";
12
+ import { notOk, ok } from "@prisma-next/utils/result";
10
13
  //#region src/derive-json-schema.ts
11
14
  function resolveBsonType(codecId, codecLookup) {
12
15
  return codecLookup?.targetTypesFor(codecId)?.[0];
13
16
  }
14
- function fieldToBsonSchema(field, valueObjects, codecLookup) {
17
+ function fieldToBsonSchema(field, valueObjects, codecLookup, valueSets) {
15
18
  if (field.type.kind === "scalar") {
16
19
  const bsonType = resolveBsonType(field.type.codecId, codecLookup);
17
20
  if (!bsonType) return void 0;
18
- if ("many" in field && field.many) return {
19
- bsonType: "array",
20
- items: { bsonType }
21
- };
22
- if (field.nullable) return { bsonType: ["null", bsonType] };
23
- return { bsonType };
21
+ const enumValues = field.valueSet !== void 0 ? valueSets?.[field.valueSet.entityName]?.values ?? null : null;
22
+ if ("many" in field && field.many) {
23
+ const items = { bsonType };
24
+ if (enumValues) items["enum"] = enumValues;
25
+ return {
26
+ bsonType: "array",
27
+ items
28
+ };
29
+ }
30
+ if (field.nullable) {
31
+ const s = { bsonType: ["null", bsonType] };
32
+ if (enumValues) s["enum"] = [...enumValues, null];
33
+ return s;
34
+ }
35
+ const s = { bsonType };
36
+ if (enumValues) s["enum"] = enumValues;
37
+ return s;
24
38
  }
25
39
  if (field.type.kind === "valueObject") {
26
40
  const vo = valueObjects?.[field.type.name];
27
41
  if (!vo) return void 0;
28
- const voSchema = deriveObjectSchema(vo.fields, valueObjects, codecLookup);
42
+ const voSchema = deriveObjectSchema(vo.fields, valueObjects, codecLookup, valueSets);
29
43
  if ("many" in field && field.many) return {
30
44
  bsonType: "array",
31
45
  items: voSchema
@@ -34,11 +48,11 @@ function fieldToBsonSchema(field, valueObjects, codecLookup) {
34
48
  return voSchema;
35
49
  }
36
50
  }
37
- function deriveObjectSchema(fields, valueObjects, codecLookup) {
51
+ function deriveObjectSchema(fields, valueObjects, codecLookup, valueSets) {
38
52
  const properties = {};
39
53
  const required = [];
40
54
  for (const [fieldName, field] of Object.entries(fields)) {
41
- const schema = fieldToBsonSchema(field, valueObjects, codecLookup);
55
+ const schema = fieldToBsonSchema(field, valueObjects, codecLookup, valueSets);
42
56
  if (schema) {
43
57
  properties[fieldName] = schema;
44
58
  if (!field.nullable) required.push(fieldName);
@@ -55,15 +69,15 @@ function deriveObjectSchema(fields, valueObjects, codecLookup) {
55
69
  function isRecord(value) {
56
70
  return typeof value === "object" && value !== null && !Array.isArray(value);
57
71
  }
58
- function deriveJsonSchema(fields, valueObjects, codecLookup) {
72
+ function deriveJsonSchema(fields, valueObjects, codecLookup, valueSets) {
59
73
  return new MongoValidator({
60
- jsonSchema: deriveObjectSchema(fields, valueObjects, codecLookup),
74
+ jsonSchema: deriveObjectSchema(fields, valueObjects, codecLookup, valueSets),
61
75
  validationLevel: "strict",
62
76
  validationAction: "error"
63
77
  });
64
78
  }
65
- function derivePolymorphicJsonSchema(baseFields, discriminatorField, variants, valueObjects, codecLookup) {
66
- const baseSchema = deriveObjectSchema(baseFields, valueObjects, codecLookup);
79
+ function derivePolymorphicJsonSchema(baseFields, discriminatorField, variants, valueObjects, codecLookup, valueSets) {
80
+ const baseSchema = deriveObjectSchema(baseFields, valueObjects, codecLookup, valueSets);
67
81
  const baseProperties = isRecord(baseSchema["properties"]) ? baseSchema["properties"] : {};
68
82
  const oneOf = [];
69
83
  for (const variant of variants) {
@@ -72,7 +86,7 @@ function derivePolymorphicJsonSchema(baseFields, discriminatorField, variants, v
72
86
  const variantProperties = {};
73
87
  const variantRequired = [discriminatorField];
74
88
  for (const [name, field] of Object.entries(variantOnlyFields)) {
75
- const schema = fieldToBsonSchema(field, valueObjects, codecLookup);
89
+ const schema = fieldToBsonSchema(field, valueObjects, codecLookup, valueSets);
76
90
  if (schema) {
77
91
  variantProperties[name] = schema;
78
92
  if (!field.nullable) variantRequired.push(name);
@@ -189,6 +203,18 @@ function stripQuotes(value) {
189
203
  //#endregion
190
204
  //#region src/interpreter.ts
191
205
  /**
206
+ * Encode an authored enum value to its codec-encoded JSON form via the codec resolved by id from the
207
+ * contract's codec lookup, so a non-identity `encodeJson` (permitted by the `mongoCodec` factory) is
208
+ * respected. Matches the TS builder's `encodeEnumValue`: the lookup is always threaded in production,
209
+ * and a codecId the lookup cannot resolve is a hard error — the enum uses a codec that is not part of
210
+ * the contract's pack stack.
211
+ */
212
+ function encodeEnumValue(value, codecId, codecLookup) {
213
+ const codec = codecLookup.get(codecId);
214
+ if (!codec) throw errorEnumCodecNotInPackStack({ codecId });
215
+ return codec.encodeJson(value);
216
+ }
217
+ /**
192
218
  * Mongo's PSL surface binds the database from the connection string, so every
193
219
  * explicit namespace block is invalid, including `namespace unbound { … }`.
194
220
  */
@@ -717,7 +743,7 @@ const MONGO_OBJECT_ID_PSL_TYPE = "ObjectId";
717
743
  function resolveFieldCodecId(field, scalarTypeDescriptors) {
718
744
  return scalarTypeDescriptors.get(field.typeName);
719
745
  }
720
- function resolveNonRelationField(field, ownerName, compositeTypeNames, scalarTypeDescriptors, sourceId, diagnostics) {
746
+ function resolveNonRelationField(field, ownerName, compositeTypeNames, scalarTypeDescriptors, codecIdByEnumName, sourceId, diagnostics) {
721
747
  if (compositeTypeNames.has(field.typeName)) {
722
748
  const result = {
723
749
  type: {
@@ -731,6 +757,27 @@ function resolveNonRelationField(field, ownerName, compositeTypeNames, scalarTyp
731
757
  many: true
732
758
  } : result;
733
759
  }
760
+ const enumCodecId = codecIdByEnumName.get(field.typeName);
761
+ if (enumCodecId !== void 0) {
762
+ const valueSet = {
763
+ plane: "domain",
764
+ entityKind: "enum",
765
+ namespaceId: UNBOUND_NAMESPACE_ID,
766
+ entityName: field.typeName
767
+ };
768
+ const result = {
769
+ type: {
770
+ kind: "scalar",
771
+ codecId: enumCodecId
772
+ },
773
+ nullable: field.optional,
774
+ valueSet
775
+ };
776
+ return field.list ? {
777
+ ...result,
778
+ many: true
779
+ } : result;
780
+ }
734
781
  if (field.malformedType) return;
735
782
  const codecId = resolveFieldCodecId(field, scalarTypeDescriptors);
736
783
  if (!codecId) {
@@ -754,6 +801,32 @@ function resolveNonRelationField(field, ownerName, compositeTypeNames, scalarTyp
754
801
  many: true
755
802
  } : result;
756
803
  }
804
+ function processEnumDeclarations(input) {
805
+ const builtEnums = {};
806
+ if (input.enumBlocks.length === 0) return builtEnums;
807
+ const enumDescriptor = input.authoringContributions?.entityTypes?.["enum"] !== void 0 && isAuthoringEntityTypeDescriptor(input.authoringContributions.entityTypes["enum"]) ? input.authoringContributions.entityTypes["enum"] : void 0;
808
+ if (!enumDescriptor) {
809
+ for (const decl of input.enumBlocks) input.diagnostics.push({
810
+ code: "PSL_ENUM_MISSING_FACTORY",
811
+ message: `enum "${decl.name}" requires an "enum" entityType factory in the active authoring contributions`,
812
+ sourceId: input.sourceId,
813
+ span: decl.span
814
+ });
815
+ return builtEnums;
816
+ }
817
+ for (const decl of input.enumBlocks) {
818
+ const handle = instantiateAuthoringEntityType("enum", enumDescriptor, [decl], input.entityContext);
819
+ if (handle === void 0 || handle === null) continue;
820
+ builtEnums[decl.name] = {
821
+ codecId: handle.codecId,
822
+ members: handle.enumMembers.map((m) => ({
823
+ name: m.name,
824
+ value: blindCast(m.value)
825
+ }))
826
+ };
827
+ }
828
+ return builtEnums;
829
+ }
757
830
  function interpretPslDocumentToMongoContract(input) {
758
831
  const { symbolTable, sourceFile, scalarTypeDescriptors, codecLookup } = input;
759
832
  const sourceId = input.sourceId;
@@ -769,6 +842,23 @@ function interpretPslDocumentToMongoContract(input) {
769
842
  const allCompositeTypes = Object.values(topLevel.compositeTypes);
770
843
  const modelNames = new Set(allModels.map((m) => m.name));
771
844
  const compositeTypeNames = new Set(allCompositeTypes.map((ct) => ct.name));
845
+ const builtEnums = processEnumDeclarations({
846
+ enumBlocks: Object.values(topLevel.blocks).filter((b) => b.keyword === "enum").map((b) => b.block),
847
+ sourceId,
848
+ authoringContributions: input.authoringContributions,
849
+ entityContext: {
850
+ family: "mongo",
851
+ target: "mongo",
852
+ ...ifDefined("enumInferenceCodecs", input.enumInferenceCodecs),
853
+ ...ifDefined("codecLookup", codecLookup),
854
+ sourceId,
855
+ diagnostics: { push: (d) => {
856
+ diagnostics.push(blindCast(d));
857
+ } }
858
+ },
859
+ diagnostics
860
+ });
861
+ const codecIdByEnumName = new Map(Object.entries(builtEnums).map(([name, e]) => [name, e.codecId]));
772
862
  const models = {};
773
863
  const collections = {};
774
864
  const roots = {};
@@ -789,7 +879,7 @@ function interpretPslDocumentToMongoContract(input) {
789
879
  modelName: pslModel.name,
790
880
  fieldName: field.name,
791
881
  targetModelName: field.typeName,
792
- ...relation?.relationName !== void 0 ? { relationName: relation.relationName } : {},
882
+ ...ifDefined("relationName", relation?.relationName),
793
883
  cardinality: field.list ? "1:N" : "1:1",
794
884
  field
795
885
  });
@@ -812,14 +902,14 @@ function interpretPslDocumentToMongoContract(input) {
812
902
  declaringModel: pslModel.name,
813
903
  fieldName: field.name,
814
904
  targetModel: field.typeName,
815
- ...relation.relationName !== void 0 ? { relationName: relation.relationName } : {},
905
+ ...ifDefined("relationName", relation.relationName),
816
906
  localFields: localMapped,
817
907
  targetFields: targetMapped
818
908
  });
819
909
  }
820
910
  continue;
821
911
  }
822
- const resolved = resolveNonRelationField(field, pslModel.name, compositeTypeNames, scalarTypeDescriptors, sourceId, diagnostics);
912
+ const resolved = resolveNonRelationField(field, pslModel.name, compositeTypeNames, scalarTypeDescriptors, codecIdByEnumName, sourceId, diagnostics);
823
913
  if (!resolved) continue;
824
914
  const mappedName = fieldMappings.pslNameToMapped.get(field.name) ?? field.name;
825
915
  fields[mappedName] = resolved;
@@ -856,7 +946,7 @@ function interpretPslDocumentToMongoContract(input) {
856
946
  for (const compositeType of allCompositeTypes) {
857
947
  const fields = {};
858
948
  for (const field of Object.values(compositeType.fields)) {
859
- const resolved = resolveNonRelationField(field, compositeType.name, compositeTypeNames, scalarTypeDescriptors, sourceId, diagnostics);
949
+ const resolved = resolveNonRelationField(field, compositeType.name, compositeTypeNames, scalarTypeDescriptors, codecIdByEnumName, sourceId, diagnostics);
860
950
  if (!resolved) continue;
861
951
  fields[field.name] = resolved;
862
952
  }
@@ -923,6 +1013,15 @@ function interpretPslDocumentToMongoContract(input) {
923
1013
  });
924
1014
  const resolvedModels = polyResult.models;
925
1015
  const resolvedCollections = polyResult.collections;
1016
+ const storageValueSets = {};
1017
+ const enumEntries = Object.entries(builtEnums);
1018
+ if (enumEntries.length > 0) {
1019
+ assertDefined(codecLookup, "Mongo PSL interpretation requires a codec lookup to encode enum values");
1020
+ for (const [enumName, builtEnum] of enumEntries) storageValueSets[enumName] = {
1021
+ kind: "valueSet",
1022
+ values: builtEnum.members.map((m) => encodeEnumValue(m.value, builtEnum.codecId, codecLookup))
1023
+ };
1024
+ }
926
1025
  for (const [, modelEntry] of Object.entries(resolvedModels)) {
927
1026
  if (modelEntry.base) continue;
928
1027
  const coll = resolvedCollections[modelEntry.storage.collection];
@@ -932,8 +1031,8 @@ function interpretPslDocumentToMongoContract(input) {
932
1031
  discriminatorValue: value,
933
1032
  fields: resolvedModels[variantName]?.fields ?? {}
934
1033
  }));
935
- coll["validator"] = derivePolymorphicJsonSchema(modelEntry.fields, modelEntry.discriminator.field, variantEntries, valueObjects, codecLookup);
936
- } else coll["validator"] = deriveJsonSchema(modelEntry.fields, valueObjects, codecLookup);
1034
+ coll["validator"] = derivePolymorphicJsonSchema(modelEntry.fields, modelEntry.discriminator.field, variantEntries, valueObjects, codecLookup, storageValueSets);
1035
+ } else coll["validator"] = deriveJsonSchema(modelEntry.fields, valueObjects, codecLookup, storageValueSets);
937
1036
  }
938
1037
  const target = "mongo";
939
1038
  const targetFamily = "mongo";
@@ -947,7 +1046,10 @@ function interpretPslDocumentToMongoContract(input) {
947
1046
  }
948
1047
  const unboundNamespace = buildMongoNamespace({
949
1048
  id: UNBOUND_NAMESPACE_ID,
950
- entries: { collection: collectionInputs }
1049
+ entries: {
1050
+ collection: collectionInputs,
1051
+ ...Object.keys(storageValueSets).length > 0 ? { valueSet: storageValueSets } : {}
1052
+ }
951
1053
  });
952
1054
  const storage = new MongoStorage({
953
1055
  storageHash: computeStorageHash({
@@ -955,20 +1057,25 @@ function interpretPslDocumentToMongoContract(input) {
955
1057
  targetFamily,
956
1058
  storage: { namespaces: { [UNBOUND_NAMESPACE_ID]: {
957
1059
  id: UNBOUND_NAMESPACE_ID,
958
- entries: { collection: unboundNamespace.entries.collection }
1060
+ entries: {
1061
+ collection: unboundNamespace.entries.collection,
1062
+ ...unboundNamespace.entries.valueSet !== void 0 ? { valueSet: unboundNamespace.entries.valueSet } : {}
1063
+ }
959
1064
  } } },
960
1065
  ...mongoContractCanonicalizationHooks
961
1066
  }),
962
1067
  namespaces: { [UNBOUND_NAMESPACE_ID]: unboundNamespace }
963
1068
  });
964
1069
  const capabilities = {};
1070
+ const hasEnums = Object.keys(builtEnums).length > 0;
965
1071
  return ok({
966
1072
  targetFamily,
967
1073
  target,
968
1074
  roots: polyResult.roots,
969
1075
  domain: { namespaces: { [UNBOUND_NAMESPACE_ID]: {
970
1076
  models: polyResult.models,
971
- ...Object.keys(valueObjects).length > 0 ? { valueObjects } : {}
1077
+ ...Object.keys(valueObjects).length > 0 ? { valueObjects } : {},
1078
+ ...hasEnums ? { enum: builtEnums } : {}
972
1079
  } } },
973
1080
  storage,
974
1081
  extensionPacks: {},
@@ -982,6 +1089,6 @@ function interpretPslDocumentToMongoContract(input) {
982
1089
  });
983
1090
  }
984
1091
  //#endregion
985
- export { interpretPslDocumentToMongoContract as t };
1092
+ export { deriveJsonSchema as n, derivePolymorphicJsonSchema as r, interpretPslDocumentToMongoContract as t };
986
1093
 
987
- //# sourceMappingURL=interpreter-DCiVHDlW.mjs.map
1094
+ //# sourceMappingURL=interpreter-D0vfRJ7f.mjs.map