@prisma/orm-family-mongo 8.0.0-rc.18-dev.11 → 8.0.0-rc.18-dev.13

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.
Files changed (100) hide show
  1. package/dist/{authoring-entity-types-8yNXQKSJ-COs9oUJY.mjs → authoring-entity-types-ooM-r2td-r5JwBDd-.mjs} +11 -43
  2. package/dist/authoring-entity-types-ooM-r2td-r5JwBDd-.mjs.map +1 -0
  3. package/dist/{contract-builder-DWne7sJK.mjs → contract-builder-C_-FfTnK.mjs} +3 -3
  4. package/dist/{contract-builder-DWne7sJK.mjs.map → contract-builder-C_-FfTnK.mjs.map} +1 -1
  5. package/dist/{contract-builder-CHodgHxn.d.mts → contract-builder-CyB-7-Eq.d.mts} +2 -2
  6. package/dist/{contract-builder-CHodgHxn.d.mts.map → contract-builder-CyB-7-Eq.d.mts.map} +1 -1
  7. package/dist/contract-prisma6__provider.mjs +2 -2
  8. package/dist/contract-psl.d.mts +2 -21
  9. package/dist/contract-psl.d.mts.map +1 -1
  10. package/dist/contract-psl.mjs +2 -2
  11. package/dist/contract-psl__provider.mjs +2 -2
  12. package/dist/contract-psl__provider.mjs.map +1 -1
  13. package/dist/contract-ts.d.mts +1 -1
  14. package/dist/contract-ts.mjs +1 -1
  15. package/dist/contract-ts__contract-builder.d.mts +1 -1
  16. package/dist/contract-ts__contract-builder.mjs +1 -1
  17. package/dist/contract.d.mts +2 -2
  18. package/dist/contract.mjs +2 -2
  19. package/dist/contract__data-type.d.mts +1 -1
  20. package/dist/contract__data-type.mjs +1 -1
  21. package/dist/{control-BYbEjuQ5.d.mts → control-4JTCKNgO.d.mts} +2 -2
  22. package/dist/{control-BYbEjuQ5.d.mts.map → control-4JTCKNgO.d.mts.map} +1 -1
  23. package/dist/{control-Df3-4ayL.d.mts → control-SoPc-6DA.d.mts} +4 -4
  24. package/dist/{control-Df3-4ayL.d.mts.map → control-SoPc-6DA.d.mts.map} +1 -1
  25. package/dist/{control-BYnFmj1v.mjs → control-Yu_IYcIP.mjs} +4 -4
  26. package/dist/{control-BYnFmj1v.mjs.map → control-Yu_IYcIP.mjs.map} +1 -1
  27. package/dist/{control-adapter-Bh_ZraGM-Djo--Ygg.d.mts → control-adapter-Bh_ZraGM-D3xSqwxa.d.mts} +4 -4
  28. package/dist/{control-adapter-Bh_ZraGM-Djo--Ygg.d.mts.map → control-adapter-Bh_ZraGM-D3xSqwxa.d.mts.map} +1 -1
  29. package/dist/control-adapter-DriGOlGH.d.mts +1 -0
  30. package/dist/dist-BbfUvuqQ.mjs +629 -0
  31. package/dist/dist-BbfUvuqQ.mjs.map +1 -0
  32. package/dist/dist-xk_0xOR-.mjs.map +1 -1
  33. package/dist/family.d.mts +9 -9
  34. package/dist/family.mjs +6 -6
  35. package/dist/family__control-adapter.d.mts +2 -2
  36. package/dist/family__control.d.mts +1 -1
  37. package/dist/family__control.mjs +1 -1
  38. package/dist/family__ir.d.mts +2 -2
  39. package/dist/family__ir.mjs +2 -2
  40. package/dist/family__migration.d.mts +1 -1
  41. package/dist/family__migration.mjs +1 -1
  42. package/dist/family__pack.mjs +2 -2
  43. package/dist/family__pack.mjs.map +1 -1
  44. package/dist/family__runtime.d.mts +2 -2
  45. package/dist/family__runtime.mjs +1 -1
  46. package/dist/family__schema-verify.d.mts +1 -1
  47. package/dist/{field-accessor-CE4JbDIa-CemAdCzH.d.mts → field-accessor-CE4JbDIa-DCI8nD_s.d.mts} +2 -2
  48. package/dist/{field-accessor-CE4JbDIa-CemAdCzH.d.mts.map → field-accessor-CE4JbDIa-DCI8nD_s.d.mts.map} +1 -1
  49. package/dist/{index-D8_oAhb-.d.mts → index-B8HcPJrE.d.mts} +3 -3
  50. package/dist/{index-D8_oAhb-.d.mts.map → index-B8HcPJrE.d.mts.map} +1 -1
  51. package/dist/{index-XFSLz1g-.d.mts → index-BFhyIsHU.d.mts} +2 -2
  52. package/dist/{index-XFSLz1g-.d.mts.map → index-BFhyIsHU.d.mts.map} +1 -1
  53. package/dist/{index-mWfX7vkw.d.mts → index-CMd3fTIb.d.mts} +2 -2
  54. package/dist/{index-mWfX7vkw.d.mts.map → index-CMd3fTIb.d.mts.map} +1 -1
  55. package/dist/{index-C9aUMsc0.d.mts → index-hQxjnY-x.d.mts} +3 -3
  56. package/dist/{index-C9aUMsc0.d.mts.map → index-hQxjnY-x.d.mts.map} +1 -1
  57. package/dist/{index-Dg5hCMsu.d.mts → index-p1mHGKB5.d.mts} +57 -4
  58. package/dist/index-p1mHGKB5.d.mts.map +1 -0
  59. package/dist/{interpreter-Bhe8FSI4-uGNm4vAs.mjs → interpreter-BKBSURkK-B9QVhiLs.mjs} +23 -144
  60. package/dist/interpreter-BKBSURkK-B9QVhiLs.mjs.map +1 -0
  61. package/dist/{ir-iCpQRIJM.d.mts → ir-Cs8SNS0n.d.mts} +3 -3
  62. package/dist/{ir-iCpQRIJM.d.mts.map → ir-Cs8SNS0n.d.mts.map} +1 -1
  63. package/dist/ir-vZWjElPY.mjs.map +1 -1
  64. package/dist/lowering.d.mts +1 -1
  65. package/dist/{migration-BT1gIMTZ.mjs → migration-Bd8GWTeP.mjs} +2 -2
  66. package/dist/{migration-BT1gIMTZ.mjs.map → migration-Bd8GWTeP.mjs.map} +1 -1
  67. package/dist/{migration-BDqwISt7.d.mts → migration-DMXCxDu-.d.mts} +4 -4
  68. package/dist/{migration-BDqwISt7.d.mts.map → migration-DMXCxDu-.d.mts.map} +1 -1
  69. package/dist/{mongo-contract-serializer-DC_DM9_Y-CVJfr1pm.mjs → mongo-contract-serializer-5OphMWx2-DkWnm3kW.mjs} +3 -3
  70. package/dist/{mongo-contract-serializer-DC_DM9_Y-CVJfr1pm.mjs.map → mongo-contract-serializer-5OphMWx2-DkWnm3kW.mjs.map} +1 -1
  71. package/dist/{mongo-contract-view-AnejqfrQ-DYyueW8J.d.mts → mongo-contract-view-AnejqfrQ-CXymmojn.d.mts} +2 -2
  72. package/dist/{mongo-contract-view-AnejqfrQ-DYyueW8J.d.mts.map → mongo-contract-view-AnejqfrQ-CXymmojn.d.mts.map} +1 -1
  73. package/dist/{mongo-contract-view-JZOa0Ry--BZ2GUZQB.mjs → mongo-contract-view-OSrxTeL0-IBirxnYy.mjs} +4 -4
  74. package/dist/{mongo-contract-view-JZOa0Ry--BZ2GUZQB.mjs.map → mongo-contract-view-OSrxTeL0-IBirxnYy.mjs.map} +1 -1
  75. package/dist/{data-type-DuiFEJxB.d.mts → mongo-data-type-BMIRhoZC-COGrnC0Z.d.mts} +2 -2
  76. package/dist/mongo-data-type-BMIRhoZC-COGrnC0Z.d.mts.map +1 -0
  77. package/dist/{data-type-Cl0vtmfh.mjs → mongo-data-type-DJ7W2ota-BnUN7ydW.mjs} +2 -2
  78. package/dist/mongo-data-type-DJ7W2ota-BnUN7ydW.mjs.map +1 -0
  79. package/dist/orm.d.mts +2 -2
  80. package/dist/query-ast.d.mts +1 -1
  81. package/dist/query-ast__control.d.mts +1 -1
  82. package/dist/query-builder.d.mts +2 -2
  83. package/dist/query-builder__contract-free.d.mts +2 -2
  84. package/dist/{runtime-BIOlGVaz.d.mts → runtime-CQUQkK0P.d.mts} +2 -2
  85. package/dist/runtime-CQUQkK0P.d.mts.map +1 -0
  86. package/dist/runtime.d.mts +2 -2
  87. package/dist/schema-ir.d.mts +1 -1
  88. package/dist/{schema-verify-BP6zabY1.d.mts → schema-verify-Bzmg6whi.d.mts} +3 -3
  89. package/dist/{schema-verify-BP6zabY1.d.mts.map → schema-verify-Bzmg6whi.d.mts.map} +1 -1
  90. package/dist/wire.d.mts +1 -1
  91. package/package.json +20 -20
  92. package/dist/authoring-entity-types-8yNXQKSJ-COs9oUJY.mjs.map +0 -1
  93. package/dist/control-adapter-8uWiylj9.d.mts +0 -1
  94. package/dist/data-type-Cl0vtmfh.mjs.map +0 -1
  95. package/dist/data-type-DuiFEJxB.d.mts.map +0 -1
  96. package/dist/dist-CYYrUE3W.mjs +0 -310
  97. package/dist/dist-CYYrUE3W.mjs.map +0 -1
  98. package/dist/index-Dg5hCMsu.d.mts.map +0 -1
  99. package/dist/interpreter-Bhe8FSI4-uGNm4vAs.mjs.map +0 -1
  100. package/dist/runtime-BIOlGVaz.d.mts.map +0 -1
@@ -0,0 +1,629 @@
1
+ import { t as mongoContractCanonicalizationHooks } from "./canonicalization-hooks-CRVM-Kqh-Qi-VmEVg.mjs";
2
+ import { l as MongoValidator, n as MongoCollationOptions, o as MongoIndex, p as composeMongoEntityKinds } from "./entity-kinds-RooUvcN8-B1AF_ppw.mjs";
3
+ import { t as bsonTypesOfCodec } from "./mongo-data-type-DJ7W2ota-BnUN7ydW.mjs";
4
+ import { structuredError } from "@prisma/orm-framework/utils/structured-error";
5
+ import { IRNodeBase, NamespaceBase, UNBOUND_NAMESPACE_ID, buildNamespacedEntities, buildSingleNamespaceView, freezeNode, hydrateNamespaceEntities } from "@prisma/orm-framework/components/ir";
6
+ import { RelationKeys } from "@prisma/orm-framework/components/runtime";
7
+ import { computeStorageHash } from "@prisma/orm-framework/contract/hashing";
8
+ import { blindCast } from "@prisma/orm-framework/utils/casts";
9
+ import { UNBOUND_DOMAIN_NAMESPACE_ID } from "@prisma/orm-framework/contract/default-namespace";
10
+ import { assertDefined } from "@prisma/orm-framework/utils/assertions";
11
+ //#region ../../../2-mongo-family/1-foundation/mongo-contract/dist/index.mjs
12
+ var MongoUnboundNamespace = class MongoUnboundNamespace extends NamespaceBase {
13
+ static instance = new MongoUnboundNamespace();
14
+ id = UNBOUND_NAMESPACE_ID;
15
+ entries = Object.freeze({ collection: Object.freeze({}) });
16
+ constructor() {
17
+ super();
18
+ Object.defineProperty(this, "kind", {
19
+ value: "mongo-namespace",
20
+ writable: false,
21
+ enumerable: false,
22
+ configurable: true
23
+ });
24
+ freezeNode(this);
25
+ }
26
+ };
27
+ const MONGO_NAMESPACE_KIND = "mongo-namespace";
28
+ var MongoBoundNamespace = class MongoBoundNamespace extends NamespaceBase {
29
+ id;
30
+ entries;
31
+ static fromCollectionsInput(input) {
32
+ const collectionMap = input.entries["collection"];
33
+ const collectionCount = collectionMap !== void 0 ? Object.keys(collectionMap).length : 0;
34
+ const hasUnknownKinds = Object.keys(input.entries).some((kind) => kind !== "collection");
35
+ if (input.id === UNBOUND_NAMESPACE_ID && collectionCount === 0 && !hasUnknownKinds) return MongoUnboundNamespace.instance;
36
+ return new MongoBoundNamespace(input);
37
+ }
38
+ constructor(input) {
39
+ super();
40
+ this.id = input.id;
41
+ const rawEntries = {
42
+ collection: {},
43
+ ...input.entries
44
+ };
45
+ this.entries = Object.freeze(blindCast(hydrateNamespaceEntities(rawEntries, composeMongoEntityKinds(), "carry")));
46
+ Object.defineProperty(this, "kind", {
47
+ value: MONGO_NAMESPACE_KIND,
48
+ writable: false,
49
+ enumerable: false,
50
+ configurable: true
51
+ });
52
+ freezeNode(this);
53
+ }
54
+ get collection() {
55
+ return this.entries.collection ?? Object.freeze({});
56
+ }
57
+ };
58
+ function buildMongoNamespace(input) {
59
+ return MongoBoundNamespace.fromCollectionsInput(input);
60
+ }
61
+ var MongoStorage = class extends IRNodeBase {
62
+ storageHash;
63
+ namespaces;
64
+ constructor(input) {
65
+ super();
66
+ Object.defineProperty(this, "kind", {
67
+ value: "mongo-storage",
68
+ writable: false,
69
+ enumerable: false,
70
+ configurable: true
71
+ });
72
+ this.storageHash = input.storageHash;
73
+ this.namespaces = Object.freeze(input.namespaces);
74
+ freezeNode(this);
75
+ }
76
+ };
77
+ /**
78
+ * Builds a Mongo contract's storage: the unbound namespace holding the collections and value sets, and the storage hash that `db sign` and `db verify` compare. Every Mongo contract source calls this, so they hash storage the same way.
79
+ */
80
+ function buildMongoStorage(input) {
81
+ const hasValueSets = Object.keys(input.valueSets).length > 0;
82
+ const namespace = buildMongoNamespace({
83
+ id: UNBOUND_NAMESPACE_ID,
84
+ entries: {
85
+ collection: input.collections,
86
+ ...hasValueSets ? { valueSet: input.valueSets } : {}
87
+ }
88
+ });
89
+ return new MongoStorage({
90
+ storageHash: computeStorageHash({
91
+ target: "mongo",
92
+ targetFamily: "mongo",
93
+ storage: { namespaces: { [UNBOUND_NAMESPACE_ID]: {
94
+ id: UNBOUND_NAMESPACE_ID,
95
+ entries: {
96
+ collection: namespace.entries.collection,
97
+ ...namespace.entries.valueSet !== void 0 ? { valueSet: namespace.entries.valueSet } : {}
98
+ }
99
+ } } },
100
+ ...mongoContractCanonicalizationHooks
101
+ }),
102
+ namespaces: { [UNBOUND_NAMESPACE_ID]: namespace }
103
+ });
104
+ }
105
+ const MONGO_BUILTIN_KINDS = ["collection"];
106
+ /**
107
+ * Builds the Mongo view: unwraps the sole namespace's built-in `collection` kind
108
+ * to the root, attaches the namespace-keyed `namespace` map, and layers both
109
+ * over the deserialized contract so the result is a structural superset of the
110
+ * contract.
111
+ */
112
+ function buildMongoContractView(contract) {
113
+ const rootAccessors = buildSingleNamespaceView(contract.storage, MONGO_BUILTIN_KINDS);
114
+ const namespace = buildNamespacedEntities(contract.storage, MONGO_BUILTIN_KINDS);
115
+ return {
116
+ ...contract,
117
+ ...rootAccessors,
118
+ namespace
119
+ };
120
+ }
121
+ /** Default storage namespace for Mongo-family contracts at runtime. */
122
+ const defaultMongoStorageNamespaceId = UNBOUND_NAMESPACE_ID;
123
+ /** Default domain namespace for Mongo-family contracts at runtime. */
124
+ const defaultMongoDomainNamespaceId = UNBOUND_DOMAIN_NAMESPACE_ID;
125
+ const DOCUMENT_ID_FIELD = "_id";
126
+ /**
127
+ * The model facts behind a same-space to-one relation's nullability: which side owns the
128
+ * foreign key, and whether each local field is nullable.
129
+ */
130
+ function resolveMongoToOneRelationFields(model, relation) {
131
+ const fields = relation.on.localFields.map((name) => ({
132
+ name,
133
+ nullable: model.fields[name]?.nullable ?? true
134
+ }));
135
+ return {
136
+ ownsForeignKey: !(relation.cardinality === "1:1" && fields.every((field) => field.name === DOCUMENT_ID_FIELD)),
137
+ fields
138
+ };
139
+ }
140
+ /** Whether `relation` stores the related model inside the document, rather than referring to documents elsewhere. */
141
+ function isEmbedRelation(relation) {
142
+ return !("on" in relation) && !("through" in relation);
143
+ }
144
+ function typeKey(kind, name) {
145
+ return `${kind}:${name}`;
146
+ }
147
+ function referencesOf(fields) {
148
+ return Object.values(fields).flatMap((field) => field.type.kind === "valueObject" ? [typeKey("valueObject", field.type.name)] : []);
149
+ }
150
+ /**
151
+ * The recursive groups of value objects and embedded models: each set of types that can reach each other through value-object fields and embed relations (a strongly connected component of that graph), and each type that refers to itself. Maps the {@link typeKey} of every type in such a group to the group's number; a type in no recursive group is absent.
152
+ */
153
+ function recursiveGroupsOf(valueObjects, models) {
154
+ const edges = /* @__PURE__ */ new Map();
155
+ for (const [name, valueObject] of Object.entries(valueObjects)) edges.set(typeKey("valueObject", name), referencesOf(valueObject.fields));
156
+ for (const [name, model] of Object.entries(models)) {
157
+ const embeds = Object.values(model.relations).flatMap((relation) => isEmbedRelation(relation) ? [typeKey("model", relation.to.model)] : []);
158
+ edges.set(typeKey("model", name), [...referencesOf(model.fields), ...embeds]);
159
+ }
160
+ const groups = /* @__PURE__ */ new Map();
161
+ const index = /* @__PURE__ */ new Map();
162
+ const lowLink = /* @__PURE__ */ new Map();
163
+ const stack = [];
164
+ const onStack = /* @__PURE__ */ new Set();
165
+ let nextIndex = 0;
166
+ let nextGroup = 0;
167
+ const visit = (node) => {
168
+ index.set(node, nextIndex);
169
+ lowLink.set(node, nextIndex);
170
+ nextIndex++;
171
+ stack.push(node);
172
+ onStack.add(node);
173
+ for (const target of edges.get(node) ?? []) {
174
+ if (!edges.has(target)) continue;
175
+ if (!index.has(target)) {
176
+ visit(target);
177
+ lowLink.set(node, Math.min(lowLink.get(node) ?? 0, lowLink.get(target) ?? 0));
178
+ } else if (onStack.has(target)) lowLink.set(node, Math.min(lowLink.get(node) ?? 0, index.get(target) ?? 0));
179
+ }
180
+ if (lowLink.get(node) !== index.get(node)) return;
181
+ const members = [];
182
+ let member;
183
+ do {
184
+ member = stack.pop();
185
+ if (member === void 0) break;
186
+ onStack.delete(member);
187
+ members.push(member);
188
+ } while (member !== node);
189
+ const refersToItself = (edges.get(node) ?? []).includes(node);
190
+ if (members.length > 1 || refersToItself) {
191
+ for (const each of members) groups.set(each, nextGroup);
192
+ nextGroup++;
193
+ }
194
+ };
195
+ for (const node of edges.keys()) if (!index.has(node)) visit(node);
196
+ return groups;
197
+ }
198
+ /**
199
+ * `$jsonSchema` has no references, so a type that contains itself, directly or through other types, cannot be described at every depth. The validator describes the type through which a path enters a recursive group in full, and accepts any object for each field below it that refers back into that group. So each group is written out once for each place a document enters it, and no valid document is refused.
200
+ */
201
+ const OPEN_OBJECT = { bsonType: "object" };
202
+ function sourcesFor(input, rootKey) {
203
+ const groups = recursiveGroupsOf(input.valueObjects, input.models);
204
+ const rootGroup = groups.get(rootKey);
205
+ return {
206
+ ...input,
207
+ groups,
208
+ enteredGroups: new Set(rootGroup === void 0 ? [] : [rootGroup])
209
+ };
210
+ }
211
+ function objectSchemaOf(kind, name, shape, sources) {
212
+ const key = typeKey(kind, name);
213
+ const group = sources.groups.get(key);
214
+ if (group !== void 0 && sources.enteredGroups.has(group)) return OPEN_OBJECT;
215
+ return deriveObjectSchema(shape, entering(key, sources));
216
+ }
217
+ /** `sources` with the recursive group of the type `key` entered, if it has one. */
218
+ function entering(key, sources) {
219
+ const group = sources.groups.get(key);
220
+ if (group === void 0 || sources.enteredGroups.has(group)) return sources;
221
+ return {
222
+ ...sources,
223
+ enteredGroups: /* @__PURE__ */ new Set([...sources.enteredGroups, group])
224
+ };
225
+ }
226
+ const NO_RELATIONS = {};
227
+ const NOTHING_INHERITED = {
228
+ fields: {},
229
+ relations: NO_RELATIONS
230
+ };
231
+ /**
232
+ * The `bsonType` keyword for a list of BSON type names: the name itself for one entry, the list for several.
233
+ */
234
+ function bsonTypeKeyword(bsonTypes) {
235
+ const [only, ...rest] = bsonTypes;
236
+ return only !== void 0 && rest.length === 0 ? only : [...bsonTypes];
237
+ }
238
+ function withNull(bsonTypes) {
239
+ return bsonTypes.includes("null") ? bsonTypes : ["null", ...bsonTypes];
240
+ }
241
+ function anyValueSchema(field) {
242
+ if ("many" in field && field.many) return {
243
+ bsonType: field.nullable ? ["null", "array"] : "array",
244
+ items: {}
245
+ };
246
+ return {};
247
+ }
248
+ function fieldToBsonSchema(field, sources) {
249
+ const { lookups, valueObjects, valueSets } = sources;
250
+ if (field.type.kind === "scalar") {
251
+ const bsonTypes = bsonTypesOfCodec(field.type.codecId, lookups);
252
+ if (bsonTypes === void 0) return void 0;
253
+ if (bsonTypes.length === 0) return anyValueSchema(field);
254
+ const bsonType = bsonTypeKeyword(bsonTypes);
255
+ const enumValues = field.valueSet !== void 0 ? valueSets[field.valueSet.entityName]?.values ?? null : null;
256
+ if (field.many) {
257
+ const items = { bsonType: field.many.elementNullable ? ["null", bsonType] : bsonType };
258
+ if (enumValues) items["enum"] = field.many.elementNullable ? [...enumValues, null] : enumValues;
259
+ return {
260
+ bsonType: field.nullable ? ["null", "array"] : "array",
261
+ items
262
+ };
263
+ }
264
+ if (field.nullable) {
265
+ const s = { bsonType: bsonTypeKeyword(withNull(bsonTypes)) };
266
+ if (enumValues) s["enum"] = [...enumValues, null];
267
+ return s;
268
+ }
269
+ const s = { bsonType };
270
+ if (enumValues) s["enum"] = enumValues;
271
+ return s;
272
+ }
273
+ if (field.type.kind === "valueObject") {
274
+ const vo = valueObjects[field.type.name];
275
+ if (!vo) return void 0;
276
+ const voSchema = objectSchemaOf("valueObject", field.type.name, {
277
+ fields: vo.fields,
278
+ relations: NO_RELATIONS
279
+ }, sources);
280
+ if (field.many) return {
281
+ bsonType: field.nullable ? ["null", "array"] : "array",
282
+ items: field.many.elementNullable ? { oneOf: [{ bsonType: "null" }, voSchema] } : voSchema
283
+ };
284
+ if (field.nullable) return { oneOf: [{ bsonType: "null" }, voSchema] };
285
+ return voSchema;
286
+ }
287
+ }
288
+ /**
289
+ * An embedded model is stored inside its owner's document as a closed object (a list of them for `1:N`). The contract does not say whether one must be present, and the ORM creates documents without them, so the property is never required.
290
+ */
291
+ function embedToBsonSchema(relation, sources) {
292
+ const embeddedName = relation.to.model;
293
+ const embedded = sources.models[embeddedName];
294
+ assertDefined(embedded, `Embedded model "${embeddedName}" is missing`);
295
+ const schema = objectSchemaOf("model", embeddedName, embedded, sources);
296
+ return relation.cardinality === "1:N" ? {
297
+ bsonType: "array",
298
+ items: schema
299
+ } : schema;
300
+ }
301
+ /**
302
+ * The properties of `shape`, leaving out the fields and relations `inherited` already describes.
303
+ */
304
+ function propertiesOf(shape, sources, inherited) {
305
+ const properties = {};
306
+ const required = [];
307
+ for (const [fieldName, field] of Object.entries(shape.fields)) {
308
+ if (Object.hasOwn(inherited.fields, fieldName)) continue;
309
+ const schema = fieldToBsonSchema(field, sources);
310
+ if (schema) {
311
+ properties[fieldName] = schema;
312
+ if (!field.nullable) required.push(fieldName);
313
+ }
314
+ }
315
+ for (const [relationName, relation] of Object.entries(shape.relations)) {
316
+ if (Object.hasOwn(inherited.relations, relationName) || !isEmbedRelation(relation)) continue;
317
+ properties[relationName] = embedToBsonSchema(relation, sources);
318
+ }
319
+ return {
320
+ properties,
321
+ required
322
+ };
323
+ }
324
+ function deriveObjectSchema(shape, sources) {
325
+ const { properties, required } = propertiesOf(shape, sources, NOTHING_INHERITED);
326
+ const result = {
327
+ bsonType: "object",
328
+ properties,
329
+ additionalProperties: false
330
+ };
331
+ if (required.length > 0) result["required"] = required.sort();
332
+ return result;
333
+ }
334
+ function isRecord(value) {
335
+ return typeof value === "object" && value !== null && !Array.isArray(value);
336
+ }
337
+ function validatorOf(jsonSchema) {
338
+ return new MongoValidator({
339
+ jsonSchema,
340
+ validationLevel: "strict",
341
+ validationAction: "error"
342
+ });
343
+ }
344
+ function polymorphicSchema(base, discriminatorField, variants, sources) {
345
+ const baseSchema = deriveObjectSchema(base, sources);
346
+ const baseProperties = isRecord(baseSchema["properties"]) ? baseSchema["properties"] : {};
347
+ const oneOf = [];
348
+ for (const variant of variants) {
349
+ const { properties: variantProperties, required } = propertiesOf(variant, entering(typeKey("model", variant.modelName), sources), base);
350
+ oneOf.push({
351
+ properties: {
352
+ ...baseProperties,
353
+ [discriminatorField]: { enum: [variant.discriminatorValue] },
354
+ ...variantProperties
355
+ },
356
+ required: [discriminatorField, ...required].sort(),
357
+ additionalProperties: false
358
+ });
359
+ }
360
+ const jsonSchema = { ...baseSchema };
361
+ delete jsonSchema["additionalProperties"];
362
+ if (oneOf.length > 0) jsonSchema["oneOf"] = oneOf;
363
+ return jsonSchema;
364
+ }
365
+ /**
366
+ * The validator of a root model's collection: the model's fields and embedded models, and for a model with variants one `oneOf` branch per variant.
367
+ */
368
+ function deriveModelValidator(modelName, model, sources) {
369
+ const schemaSources = sourcesFor(sources, typeKey("model", modelName));
370
+ if (!model.discriminator || !model.variants) return validatorOf(deriveObjectSchema(model, schemaSources));
371
+ const variants = Object.entries(model.variants).map(([discriminatorValue, variant]) => {
372
+ const variantModel = sources.models[variant.model];
373
+ assertDefined(variantModel, `Variant model "${variant.model}" of "${modelName}" is missing`);
374
+ return {
375
+ discriminatorValue,
376
+ modelName: variant.model,
377
+ ...variantModel
378
+ };
379
+ });
380
+ return validatorOf(polymorphicSchema(model, model.discriminator.field, variants, schemaSources));
381
+ }
382
+ /**
383
+ * The validator of each collection in `roots`, keyed by collection name, derived from the collection's root model. A root model with variants gets one polymorphic validator covering every variant.
384
+ */
385
+ function deriveCollectionValidators(input) {
386
+ const validators = {};
387
+ for (const [collectionName, root] of Object.entries(input.roots)) {
388
+ const model = input.models[root.model];
389
+ assertDefined(model, `Root model "${root.model}" of collection "${collectionName}" is missing`);
390
+ validators[collectionName] = deriveModelValidator(root.model, model, input);
391
+ }
392
+ return validators;
393
+ }
394
+ const notObjectId = {
395
+ kind: "notObjectId",
396
+ reason: "has no _id field stored as BSON type objectId. MongoDB adds an objectId _id to every document it inserts without one, so a collection validator without it rejects every insert."
397
+ };
398
+ /**
399
+ * Why a root model with `fields` cannot be stored in a collection with a validator, or undefined when it can. The reason leaves out its subject so each authoring surface can lead with its own, as in `Model "User" has no _id field ...`.
400
+ */
401
+ function documentIdRefusalOf(fields, lookups) {
402
+ const id = Object.hasOwn(fields, "_id") ? fields["_id"] : void 0;
403
+ if (id?.type.kind !== "scalar") return notObjectId;
404
+ const bsonTypes = bsonTypesOfCodec(id.type.codecId, lookups);
405
+ if (bsonTypes === void 0) return {
406
+ kind: "unknownCodec",
407
+ reason: `has an _id field whose codec "${id.type.codecId}" has no MongoDB data type, so its BSON type is unknown.`
408
+ };
409
+ return bsonTypes.length === 1 && bsonTypes[0] === "objectId" ? void 0 : notObjectId;
410
+ }
411
+ /**
412
+ * Clustered-collection options (the `clusteredIndex` collection-creation
413
+ * field). Lifted from a `type =` data shape to an AST class extending
414
+ * `IRNodeBase` per FR18.
415
+ *
416
+ * MongoDB requires `key` and `unique` for any clustered collection; the
417
+ * constructor enforces presence by type signature.
418
+ */
419
+ var MongoClusteredCollectionOptions = class extends IRNodeBase {
420
+ kind = "mongo-clustered-collection-options";
421
+ key;
422
+ unique;
423
+ constructor(options) {
424
+ super();
425
+ if (options.name !== void 0) this.name = options.name;
426
+ this.key = options.key;
427
+ this.unique = options.unique;
428
+ freezeNode(this);
429
+ }
430
+ };
431
+ /**
432
+ * Mongo Contract IR node for the per-index option vocabulary (the second
433
+ * argument to `db.collection.createIndex(keys, options)` minus the keys
434
+ * themselves). Lifted from a `type =` data shape to an AST class
435
+ * extending `IRNodeBase` per FR18.
436
+ *
437
+ * Nested `collation` is itself an IR class (`MongoCollationOptions`); the
438
+ * constructor accepts either a class instance or a data literal and
439
+ * normalises to the class form so downstream walks see a uniform IR tree.
440
+ */
441
+ var MongoIndexOptions = class extends IRNodeBase {
442
+ kind = "mongo-index-options";
443
+ constructor(options = {}) {
444
+ super();
445
+ if (options.unique !== void 0) this.unique = options.unique;
446
+ if (options.name !== void 0) this.name = options.name;
447
+ if (options.partialFilterExpression !== void 0) this.partialFilterExpression = options.partialFilterExpression;
448
+ if (options.sparse !== void 0) this.sparse = options.sparse;
449
+ if (options.expireAfterSeconds !== void 0) this.expireAfterSeconds = options.expireAfterSeconds;
450
+ if (options.weights !== void 0) this.weights = options.weights;
451
+ if (options.default_language !== void 0) this.default_language = options.default_language;
452
+ if (options.language_override !== void 0) this.language_override = options.language_override;
453
+ if (options.textIndexVersion !== void 0) this.textIndexVersion = options.textIndexVersion;
454
+ if (options["2dsphereIndexVersion"] !== void 0) this["2dsphereIndexVersion"] = options["2dsphereIndexVersion"];
455
+ if (options.bits !== void 0) this.bits = options.bits;
456
+ if (options.min !== void 0) this.min = options.min;
457
+ if (options.max !== void 0) this.max = options.max;
458
+ if (options.bucketSize !== void 0) this.bucketSize = options.bucketSize;
459
+ if (options.hidden !== void 0) this.hidden = options.hidden;
460
+ if (options.collation !== void 0) this.collation = options.collation instanceof MongoCollationOptions ? options.collation : new MongoCollationOptions(options.collation);
461
+ if (options.wildcardProjection !== void 0) this.wildcardProjection = options.wildcardProjection;
462
+ freezeNode(this);
463
+ }
464
+ };
465
+ /**
466
+ * The storage value set of each enum: its members as the contract holds them, in the form their codec stores.
467
+ */
468
+ function mongoValueSetsOf(enums) {
469
+ const valueSets = {};
470
+ for (const [enumName, { members }] of Object.entries(enums)) valueSets[enumName] = {
471
+ kind: "valueSet",
472
+ values: members.map((member) => member.value)
473
+ };
474
+ return valueSets;
475
+ }
476
+ function isScalarDiscriminatorValue(value) {
477
+ const t = typeof value;
478
+ return t === "string" || t === "number" || t === "boolean";
479
+ }
480
+ function formatValue(value) {
481
+ if (typeof value === "string") return JSON.stringify(value);
482
+ if (value === null) return "null";
483
+ if (Array.isArray(value)) return JSON.stringify(value);
484
+ if (typeof value === "object") return JSON.stringify(value);
485
+ return String(value);
486
+ }
487
+ function applyPolymorphicScopeToMongoIndex(index, scope) {
488
+ if (!isScalarDiscriminatorValue(scope.discriminatorValue)) return {
489
+ kind: "conflict",
490
+ reason: `Variant-scoped indexes require a scalar (string, number, or boolean) discriminator value for field "${scope.discriminatorField}", but received ${formatValue(scope.discriminatorValue)}.`
491
+ };
492
+ const existing = index.partialFilterExpression;
493
+ if (existing && Object.hasOwn(existing, scope.discriminatorField)) {
494
+ const existingValue = existing[scope.discriminatorField];
495
+ if (existingValue === scope.discriminatorValue) return {
496
+ kind: "ok",
497
+ index
498
+ };
499
+ return {
500
+ kind: "conflict",
501
+ reason: `Index partialFilterExpression sets "${scope.discriminatorField}" to ${formatValue(existingValue)}, which conflicts with the variant's discriminator value ${formatValue(scope.discriminatorValue)}.`
502
+ };
503
+ }
504
+ const merged = {
505
+ ...existing ?? {},
506
+ [scope.discriminatorField]: scope.discriminatorValue
507
+ };
508
+ return {
509
+ kind: "ok",
510
+ index: new MongoIndex({
511
+ keys: index.keys,
512
+ ...index.unique !== void 0 && { unique: index.unique },
513
+ ...index.sparse !== void 0 && { sparse: index.sparse },
514
+ ...index.expireAfterSeconds !== void 0 && { expireAfterSeconds: index.expireAfterSeconds },
515
+ partialFilterExpression: merged,
516
+ ...index.wildcardProjection !== void 0 && { wildcardProjection: index.wildcardProjection },
517
+ ...index.collation !== void 0 && { collation: index.collation },
518
+ ...index.weights !== void 0 && { weights: index.weights },
519
+ ...index.default_language !== void 0 && { default_language: index.default_language },
520
+ ...index.language_override !== void 0 && { language_override: index.language_override }
521
+ })
522
+ };
523
+ }
524
+ function formatCrossRef(crossRef) {
525
+ return `${crossRef.namespace}.${crossRef.model}`;
526
+ }
527
+ function storageDeclaresCollection(storage, collectionName) {
528
+ for (const ns of Object.values(storage.namespaces)) if (Object.hasOwn(ns.entries["collection"] ?? {}, collectionName)) return true;
529
+ return false;
530
+ }
531
+ function validateMongoStorage(contract) {
532
+ const errors = [];
533
+ for (const [namespaceId, namespace] of Object.entries(contract.domain.namespaces)) {
534
+ const models = namespace.models;
535
+ for (const [modelName, model] of Object.entries(models)) {
536
+ const qualifiedName = `${namespaceId}:${modelName}`;
537
+ if (model.storage.collection && !storageDeclaresCollection(contract.storage, model.storage.collection)) errors.push(`Model "${qualifiedName}" references collection "${model.storage.collection}" which is not declared under any namespace's collections map`);
538
+ if (model.base) {
539
+ const baseModel = models[model.base.model];
540
+ if (baseModel) {
541
+ const variantCollection = model.storage.collection;
542
+ const baseCollection = baseModel.storage.collection;
543
+ if (variantCollection !== baseCollection) errors.push(`Mongo does not support multi-table inheritance; variant "${qualifiedName}" must share its base's collection ("${baseCollection ?? "(none)"}"), but has "${variantCollection ?? "(none)"}"`);
544
+ }
545
+ }
546
+ for (const [relName, relation] of Object.entries(model.relations ?? {})) {
547
+ const targetModel = models[relation.to.model];
548
+ const targetLabel = formatCrossRef(relation.to);
549
+ if (targetModel?.owner) {
550
+ if (targetModel.owner !== modelName) errors.push(`Embed relation "${relName}" targets "${targetLabel}" which is owned by "${targetModel.owner}", not "${qualifiedName}"`);
551
+ if (targetModel.storage.collection) errors.push(`Embed relation "${relName}" targets "${targetLabel}" which must not have a collection`);
552
+ } else if ("on" in relation && relation.on) {
553
+ for (const localField of relation.on.localFields) if (!(localField in model.fields)) errors.push(`Reference relation "${relName}": localField "${localField}" is not a field on model "${qualifiedName}"`);
554
+ if (targetModel) {
555
+ for (const targetField of relation.on.targetFields) if (!(targetField in targetModel.fields)) errors.push(`Reference relation "${relName}": targetField "${targetField}" is not a field on model "${targetLabel}"`);
556
+ }
557
+ const nullabilityError = toOneRelationNullabilityError(qualifiedName, relName, relation, model);
558
+ if (nullabilityError !== void 0) errors.push(nullabilityError);
559
+ }
560
+ }
561
+ }
562
+ }
563
+ if (errors.length > 0) throw structuredError("CONTRACT.VALIDATION_FAILED", `Contract storage validation failed:\n- ${errors.join("\n- ")}`);
564
+ }
565
+ /**
566
+ * A same-space to-one relation that states `nullable` must agree with its local fields: nullable
567
+ * exactly when one of them is nullable (a field that is not declared counts as nullable). A
568
+ * relation without the flag is left to hydration, which derives it the same way.
569
+ */
570
+ function toOneRelationNullabilityError(qualifiedName, relationName, relation, model) {
571
+ if (!("on" in relation && (relation.cardinality === "1:1" || relation.cardinality === "N:1") && relation.to.space === void 0) || relation.nullable === void 0) return void 0;
572
+ const location = `Relation "${relationName}" on model "${qualifiedName}"`;
573
+ const { ownsForeignKey, fields } = resolveMongoToOneRelationFields(model, relation);
574
+ if (!ownsForeignKey) return relation.nullable ? void 0 : `${location} is required but does not own the foreign key, so nothing in storage guarantees the related document exists`;
575
+ const anyNullable = fields.some((field) => field.nullable);
576
+ if (relation.nullable === anyNullable) return void 0;
577
+ const fieldList = fields.filter((field) => field.nullable !== relation.nullable).map((field) => `"${field.name}"`).join(", ");
578
+ return relation.nullable ? `${location} is nullable but every local field is required (fields ${fieldList})` : `${location} is required but a local field is nullable (fields ${fieldList})`;
579
+ }
580
+ const STORED_JSON_TYPE_NAMES = {
581
+ string: "a string",
582
+ number: "a finite number",
583
+ boolean: "a boolean",
584
+ object: "a JSON object",
585
+ array: "a JSON array"
586
+ };
587
+ /**
588
+ * A collection validator lists an enum's members in their stored forms, so an enum's BSON type must be one whose values JSON holds. Maps each such type to the JSON type of a member's stored form.
589
+ */
590
+ const VALIDATOR_LISTABLE_BSON_TYPES = {
591
+ string: "string",
592
+ int: "number",
593
+ double: "number",
594
+ bool: "boolean",
595
+ object: "object",
596
+ array: "array"
597
+ };
598
+ function storedJsonTypeOf(stored) {
599
+ if (stored === null) return "null";
600
+ if (Array.isArray(stored)) return "array";
601
+ if (typeof stored === "number" && !Number.isFinite(stored)) return "non-finite number";
602
+ return typeof stored;
603
+ }
604
+ function storedText(stored) {
605
+ return typeof stored === "number" || typeof stored === "bigint" ? String(stored) : JSON.stringify(stored);
606
+ }
607
+ /**
608
+ * Why a collection validator cannot list the members of an enum whose codec stores `bsonTypes`, or undefined when it can. Like {@link validatorEnumMemberRefusalOf}, the reason leaves out its subject so each authoring surface can lead with its own, as in `enum "Role" @@type codec "mongo/int64@1" stores BSON type long, ...`.
609
+ */
610
+ function validatorEnumRefusalOf(bsonTypes) {
611
+ const [bsonType, ...otherBsonTypes] = bsonTypes;
612
+ if (bsonType === void 0 || otherBsonTypes.length > 0) return `declares ${bsonTypes.length} BSON types; an enum needs exactly one. Use a codec with one BSON type, such as mongo/string@1.`;
613
+ if (VALIDATOR_LISTABLE_BSON_TYPES[bsonType] === void 0) return `stores BSON type ${bsonType}, which a collection validator cannot list as an enum value. Use a codec whose BSON type is string, int, double, bool, object or array.`;
614
+ }
615
+ /**
616
+ * Why a collection validator cannot list an enum member stored as `stored`, for an enum whose codec stores `bsonTypes`, or undefined when it can. The reason leaves out its subject, as in `enum "Role" member "Admin" is stored as ...`.
617
+ */
618
+ function validatorEnumMemberRefusalOf(bsonTypes, stored) {
619
+ const enumRefusal = validatorEnumRefusalOf(bsonTypes);
620
+ if (enumRefusal !== void 0) return enumRefusal;
621
+ const [bsonType] = bsonTypes;
622
+ const storedJsonType = bsonType === void 0 ? void 0 : VALIDATOR_LISTABLE_BSON_TYPES[bsonType];
623
+ if (storedJsonType === void 0 || storedJsonTypeOf(stored) === storedJsonType) return void 0;
624
+ return `is stored as ${storedText(stored)}, which a collection validator cannot list as a ${bsonType}. A member of a ${bsonType} enum must be ${STORED_JSON_TYPE_NAMES[storedJsonType]}.`;
625
+ }
626
+ //#endregion
627
+ export { validatorEnumMemberRefusalOf as _, RelationKeys as a, buildMongoNamespace as c, defaultMongoStorageNamespaceId as d, deriveCollectionValidators as f, validateMongoStorage as g, resolveMongoToOneRelationFields as h, MongoUnboundNamespace as i, buildMongoStorage as l, mongoValueSetsOf as m, MongoIndexOptions as n, applyPolymorphicScopeToMongoIndex as o, documentIdRefusalOf as p, MongoStorage as r, buildMongoContractView as s, MongoClusteredCollectionOptions as t, defaultMongoDomainNamespaceId as u, validatorEnumRefusalOf as v };
628
+
629
+ //# sourceMappingURL=dist-BbfUvuqQ.mjs.map