@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.
- package/dist/exports/provider.d.mts +5 -0
- package/dist/exports/provider.d.mts.map +1 -1
- package/dist/exports/provider.mjs +5 -3
- package/dist/exports/provider.mjs.map +1 -1
- package/dist/index.d.mts +27 -3
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/{interpreter-DCiVHDlW.mjs → interpreter-D0vfRJ7f.mjs} +136 -29
- package/dist/interpreter-D0vfRJ7f.mjs.map +1 -0
- package/package.json +12 -10
- package/src/derive-json-schema.ts +31 -19
- package/src/exports/index.ts +5 -0
- package/src/interpreter.ts +186 -10
- package/src/provider.ts +4 -0
- package/dist/interpreter-DCiVHDlW.mjs.map +0 -1
|
@@ -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,
|
|
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-
|
|
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":";;;;;;;
|
|
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 {
|
|
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
|
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/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-
|
|
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
|
-
|
|
19
|
-
|
|
20
|
-
items
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
-
...
|
|
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
|
-
...
|
|
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: {
|
|
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: {
|
|
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-
|
|
1094
|
+
//# sourceMappingURL=interpreter-D0vfRJ7f.mjs.map
|