@prisma/orm-family-mongo 8.0.0-rc.20-dev.2 → 8.0.0-rc.20-dev.4

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 (123) hide show
  1. package/dist/{authoring-entity-types-UA5sY_Xm-DeYf_cYq.mjs → authoring-entity-types-BEwwEsFI-J0WF36SE.mjs} +8 -6
  2. package/dist/authoring-entity-types-BEwwEsFI-J0WF36SE.mjs.map +1 -0
  3. package/dist/config-types-DYTCUpAs.mjs.map +1 -1
  4. package/dist/contract-builder-d5cf-u9p.mjs +1832 -0
  5. package/dist/contract-builder-d5cf-u9p.mjs.map +1 -0
  6. package/dist/{contract-builder-ClL-xMK2.d.mts → contract-builder-lqaM5w74.d.mts} +489 -94
  7. package/dist/contract-builder-lqaM5w74.d.mts.map +1 -0
  8. package/dist/contract-prisma6__provider.mjs +168 -107
  9. package/dist/contract-prisma6__provider.mjs.map +1 -1
  10. package/dist/contract-psl.d.mts +7 -4
  11. package/dist/contract-psl.d.mts.map +1 -1
  12. package/dist/contract-psl.mjs +1 -1
  13. package/dist/contract-psl__provider.d.mts +5 -1
  14. package/dist/contract-psl__provider.d.mts.map +1 -1
  15. package/dist/contract-psl__provider.mjs +17 -4
  16. package/dist/contract-psl__provider.mjs.map +1 -1
  17. package/dist/contract-ts.d.mts +2 -2
  18. package/dist/contract-ts.mjs +2 -2
  19. package/dist/contract-ts__contract-builder.d.mts +2 -2
  20. package/dist/contract-ts__contract-builder.mjs +2 -2
  21. package/dist/contract.d.mts +3 -3
  22. package/dist/contract.mjs +1 -1
  23. package/dist/contract__data-type.d.mts +2 -15
  24. package/dist/contract__data-type.d.mts.map +1 -1
  25. package/dist/contract__data-type.mjs +2 -2
  26. package/dist/contract__entity-kinds.d.mts +1 -1
  27. package/dist/{control-CvQSMuxa.d.mts → control-B5MQg_2b.d.mts} +5 -5
  28. package/dist/{control-CvQSMuxa.d.mts.map → control-B5MQg_2b.d.mts.map} +1 -1
  29. package/dist/{control-B_pPN58L.mjs → control-Bo6DU4E_.mjs} +71 -13
  30. package/dist/control-Bo6DU4E_.mjs.map +1 -0
  31. package/dist/{control-4pC8N2Rb.d.mts → control-DS-Fx1NE.d.mts} +3 -3
  32. package/dist/{control-4pC8N2Rb.d.mts.map → control-DS-Fx1NE.d.mts.map} +1 -1
  33. package/dist/{control-adapter-Bh_ZraGM--5JDb99k.d.mts → control-adapter-Bh_ZraGM-B4cpVawQ.d.mts} +4 -4
  34. package/dist/{control-adapter-Bh_ZraGM--5JDb99k.d.mts.map → control-adapter-Bh_ZraGM-B4cpVawQ.d.mts.map} +1 -1
  35. package/dist/control-adapter-CbqlnOk6.d.mts +1 -0
  36. package/dist/{dist-B8f-pfcT.mjs → dist-DgMGRQkm.mjs} +7 -7
  37. package/dist/dist-DgMGRQkm.mjs.map +1 -0
  38. package/dist/{dist-gmGbjhmk.mjs → dist-DmE6N0B3.mjs} +2 -2
  39. package/dist/{dist-gmGbjhmk.mjs.map → dist-DmE6N0B3.mjs.map} +1 -1
  40. package/dist/dist-xk_0xOR-.mjs.map +1 -1
  41. package/dist/family.d.mts +10 -10
  42. package/dist/family.mjs +8 -8
  43. package/dist/family__control-adapter.d.mts +2 -2
  44. package/dist/family__control.d.mts +1 -1
  45. package/dist/family__control.mjs +2 -2
  46. package/dist/family__ir.d.mts +2 -2
  47. package/dist/family__ir.mjs +3 -3
  48. package/dist/family__migration.d.mts +1 -1
  49. package/dist/family__migration.mjs +1 -1
  50. package/dist/family__pack.d.mts +1 -1
  51. package/dist/family__pack.mjs +2 -2
  52. package/dist/family__pack.mjs.map +1 -1
  53. package/dist/family__runtime.d.mts +2 -2
  54. package/dist/family__runtime.mjs +1 -1
  55. package/dist/family__schema-verify.d.mts +1 -1
  56. package/dist/family__schema-verify.mjs +1 -1
  57. package/dist/{field-accessor-CmxCw9xP-C6jMngbK.d.mts → field-accessor-CmxCw9xP-C7wBU7aM.d.mts} +3 -3
  58. package/dist/{field-accessor-CmxCw9xP-C6jMngbK.d.mts.map → field-accessor-CmxCw9xP-C7wBU7aM.d.mts.map} +1 -1
  59. package/dist/{index-FeVOOdZ0.d.mts → index-8ml_NVS_.d.mts} +3 -3
  60. package/dist/{index-FeVOOdZ0.d.mts.map → index-8ml_NVS_.d.mts.map} +1 -1
  61. package/dist/{index-BdXzdXGE.d.mts → index-BEE0UxUA.d.mts} +3 -3
  62. package/dist/{index-BdXzdXGE.d.mts.map → index-BEE0UxUA.d.mts.map} +1 -1
  63. package/dist/{index-YY1SU_7o.d.mts → index-CQ1JuHm5.d.mts} +13 -12
  64. package/dist/index-CQ1JuHm5.d.mts.map +1 -0
  65. package/dist/{index-rANtsIZG.d.mts → index-D62lu0tO.d.mts} +3 -3
  66. package/dist/{index-rANtsIZG.d.mts.map → index-D62lu0tO.d.mts.map} +1 -1
  67. package/dist/{index-BhIiYIXu.d.mts → index-Dfilr1Os.d.mts} +6 -6
  68. package/dist/{index-BhIiYIXu.d.mts.map → index-Dfilr1Os.d.mts.map} +1 -1
  69. package/dist/{interpreter-BfHdPd7T-DGqi2_Um.mjs → interpreter-DFYQNoyO--j8HG0mg.mjs} +620 -905
  70. package/dist/interpreter-DFYQNoyO--j8HG0mg.mjs.map +1 -0
  71. package/dist/{ir-DGm0HXbP.mjs → ir-DrSbC_hc.mjs} +2 -2
  72. package/dist/{ir-DGm0HXbP.mjs.map → ir-DrSbC_hc.mjs.map} +1 -1
  73. package/dist/{ir-BLC0t6_x.d.mts → ir-SLc3mVHt.d.mts} +4 -4
  74. package/dist/{ir-BLC0t6_x.d.mts.map → ir-SLc3mVHt.d.mts.map} +1 -1
  75. package/dist/lowering.d.mts +1 -1
  76. package/dist/{migration-YQVmgFU8.d.mts → migration-C9enejJh.d.mts} +5 -5
  77. package/dist/{migration-YQVmgFU8.d.mts.map → migration-C9enejJh.d.mts.map} +1 -1
  78. package/dist/{migration-DnQ7_A_B.mjs → migration-CKa85PF4.mjs} +2 -2
  79. package/dist/{migration-DnQ7_A_B.mjs.map → migration-CKa85PF4.mjs.map} +1 -1
  80. package/dist/{mongo-contract-serializer-Zx1rvil3-BywiKCpn.mjs → mongo-contract-serializer-DAPHJOHU-BjEbQIgp.mjs} +3 -3
  81. package/dist/{mongo-contract-serializer-Zx1rvil3-BywiKCpn.mjs.map → mongo-contract-serializer-DAPHJOHU-BjEbQIgp.mjs.map} +1 -1
  82. package/dist/{mongo-contract-view-AnejqfrQ-Wj_ulq2L.d.mts → mongo-contract-view-AnejqfrQ-DJJ6PwWt.d.mts} +3 -3
  83. package/dist/{mongo-contract-view-AnejqfrQ-Wj_ulq2L.d.mts.map → mongo-contract-view-AnejqfrQ-DJJ6PwWt.d.mts.map} +1 -1
  84. package/dist/{mongo-contract-view-D5yu2LrY-DCAZYJ4q.mjs → mongo-contract-view-x3OCGAk1-DvEhwf_e.mjs} +4 -4
  85. package/dist/{mongo-contract-view-D5yu2LrY-DCAZYJ4q.mjs.map → mongo-contract-view-x3OCGAk1-DvEhwf_e.mjs.map} +1 -1
  86. package/dist/mongo-data-type-Bv8Bd0zu-cnTiyyP0.mjs +33 -0
  87. package/dist/mongo-data-type-Bv8Bd0zu-cnTiyyP0.mjs.map +1 -0
  88. package/dist/{mongo-value-set-DEd7WLCT-B2Ar2GkJ.d.mts → mongo-value-set-BkGaKhbE-86TPJ91m.d.mts} +4 -5
  89. package/dist/mongo-value-set-BkGaKhbE-86TPJ91m.d.mts.map +1 -0
  90. package/dist/orm.d.mts +6 -6
  91. package/dist/orm.d.mts.map +1 -1
  92. package/dist/orm.mjs +2 -2
  93. package/dist/{pack-qw77Jt2G.d.mts → pack-WQox6nGF.d.mts} +4 -2
  94. package/dist/pack-WQox6nGF.d.mts.map +1 -0
  95. package/dist/query-ast.d.mts +2 -2
  96. package/dist/query-ast__control.d.mts +2 -2
  97. package/dist/query-builder.d.mts +2 -2
  98. package/dist/query-builder.mjs +1 -1
  99. package/dist/query-builder__contract-free.d.mts +3 -3
  100. package/dist/{runtime-yZA30qM2.d.mts → runtime-B1uT8PuG.d.mts} +2 -2
  101. package/dist/runtime-B1uT8PuG.d.mts.map +1 -0
  102. package/dist/runtime.d.mts +2 -2
  103. package/dist/schema-ir.d.mts +1 -1
  104. package/dist/{schema-verify-CVOG6EZx.d.mts → schema-verify-BiwnOU7s.d.mts} +4 -4
  105. package/dist/{schema-verify-CVOG6EZx.d.mts.map → schema-verify-BiwnOU7s.d.mts.map} +1 -1
  106. package/dist/{verify-mongo-schema-CeQP5N4k-CNOctppM.mjs → verify-mongo-schema-nsnAhPm8-BgFC6Aop.mjs} +3 -3
  107. package/dist/{verify-mongo-schema-CeQP5N4k-CNOctppM.mjs.map → verify-mongo-schema-nsnAhPm8-BgFC6Aop.mjs.map} +1 -1
  108. package/dist/wire.d.mts +1 -1
  109. package/package.json +20 -20
  110. package/dist/authoring-entity-types-UA5sY_Xm-DeYf_cYq.mjs.map +0 -1
  111. package/dist/contract-builder-BHzQQk70.mjs +0 -965
  112. package/dist/contract-builder-BHzQQk70.mjs.map +0 -1
  113. package/dist/contract-builder-ClL-xMK2.d.mts.map +0 -1
  114. package/dist/control-B_pPN58L.mjs.map +0 -1
  115. package/dist/control-adapter-CndDiTXW.d.mts +0 -1
  116. package/dist/dist-B8f-pfcT.mjs.map +0 -1
  117. package/dist/index-YY1SU_7o.d.mts.map +0 -1
  118. package/dist/interpreter-BfHdPd7T-DGqi2_Um.mjs.map +0 -1
  119. package/dist/mongo-data-type-DzyzU4LF-C1ydFXgE.mjs +0 -53
  120. package/dist/mongo-data-type-DzyzU4LF-C1ydFXgE.mjs.map +0 -1
  121. package/dist/mongo-value-set-DEd7WLCT-B2Ar2GkJ.d.mts.map +0 -1
  122. package/dist/pack-qw77Jt2G.d.mts.map +0 -1
  123. package/dist/runtime-yZA30qM2.d.mts.map +0 -1
@@ -0,0 +1,1832 @@
1
+ import { i as MongoCollectionOptions, o as MongoIndex } from "./entity-kinds-BQBtfVet-B-Px7NHp.mjs";
2
+ import { n as codecTypeParamsProblem } from "./mongo-data-type-Bv8Bd0zu-cnTiyyP0.mjs";
3
+ import { M as unsupportedStoredNameReason, S as mongoContractRefusalsOf, g as deriveCollectionValidators, s as applyPolymorphicScopeToMongoIndex, u as buildMongoStorage, w as mongoValueSetsOf } from "./dist-DgMGRQkm.mjs";
4
+ import { t as contractError } from "./contract-errors-BCN6RVI5-kMurtAbI.mjs";
5
+ import { structuredError } from "@prisma/orm-framework/utils/structured-error";
6
+ import { blindCast } from "@prisma/orm-framework/utils/casts";
7
+ import { crossRef } from "@prisma/orm-framework/contract/types";
8
+ import { buildExecutionSection, computeProfileHash } from "@prisma/orm-framework/contract/hashing";
9
+ import { assertDefined } from "@prisma/orm-framework/utils/assertions";
10
+ import { notOk, ok } from "@prisma/orm-framework/utils/result";
11
+ import { bindEnumType, composePackAuthoringNamespace, createEntityHelpersFromNamespace, createFieldHelpersFromNamespace, enumMemberError, enumType as enumType$1, isEnumTypeHandle, member, resolveToOneRelationNullable } from "@prisma/orm-framework/contract-authoring";
12
+ import { applyDiscriminatorRule, assembleDataTypeSupport, assertNoCrossRegistryCollisions, assertTypeAliasesValid, encodeEnumMembers, flushAuthoringWarnings, instantiateAuthoringFieldPreset, validateAuthoringHelperArguments } from "@prisma/orm-framework/components/authoring";
13
+ import { assembleGeneratorFunctions, createGeneratorHelpers } from "@prisma/orm-framework/components/components";
14
+ import { ifDefined } from "@prisma/orm-framework/utils/defined";
15
+ import { canonicalStringify } from "@prisma/orm-framework/utils/canonical-stringify";
16
+ import { extractCodecLookup } from "@prisma/orm-framework/components/control";
17
+ //#region ../../../2-mongo-family/2-authoring/contract-ts/dist/contract-builder.mjs
18
+ function modelFieldKey(model, field) {
19
+ return {
20
+ kind: "field",
21
+ owner: {
22
+ kind: "model",
23
+ name: model
24
+ },
25
+ field
26
+ };
27
+ }
28
+ function valueObjectFieldKey(valueObject, field) {
29
+ return {
30
+ kind: "field",
31
+ owner: {
32
+ kind: "valueObject",
33
+ name: valueObject
34
+ },
35
+ field
36
+ };
37
+ }
38
+ /** The key of a validator refusal: the part of the definition its subject names. */
39
+ function validatorRefusalKey(refusal) {
40
+ switch (refusal.kind) {
41
+ case "embeddedModelHasVariants": return {
42
+ kind: "relation",
43
+ model: refusal.modelName,
44
+ relation: refusal.relationName
45
+ };
46
+ case "enumBsonType":
47
+ case "enumNotListable": return {
48
+ kind: "enum",
49
+ enumName: refusal.enumName
50
+ };
51
+ case "enumMemberNotListable": return {
52
+ kind: "enumMember",
53
+ enumName: refusal.enumName,
54
+ member: refusal.member
55
+ };
56
+ case "fieldBsonType": return {
57
+ kind: "field",
58
+ owner: refusal.owner,
59
+ field: refusal.fieldName
60
+ };
61
+ case "documentId": return modelFieldKey(refusal.modelName, refusal.fieldName);
62
+ }
63
+ }
64
+ function storedNameOf(field) {
65
+ return field.storedName ?? field.fieldName;
66
+ }
67
+ /** The name documents store `fieldName` under, or `fieldName` itself when the fields do not declare it. */
68
+ function storedFieldNameIn(fields, fieldName) {
69
+ const field = fields.find((candidate) => candidate.fieldName === fieldName);
70
+ return field === void 0 ? fieldName : storedNameOf(field);
71
+ }
72
+ function buildContractField(field, namespaceId) {
73
+ const valueSet = field.enumName === void 0 ? void 0 : {
74
+ plane: "domain",
75
+ entityKind: "enum",
76
+ namespaceId,
77
+ entityName: field.enumName
78
+ };
79
+ return {
80
+ type: field.type,
81
+ nullable: field.nullable,
82
+ many: field.many,
83
+ ...ifDefined("valueSet", valueSet)
84
+ };
85
+ }
86
+ function buildFields(fields, namespaceId) {
87
+ return Object.fromEntries(fields.map((field) => [field.fieldName, buildContractField(field, namespaceId)]));
88
+ }
89
+ function buildStorageFields(modelName, fields, refusals) {
90
+ const storageFields = {};
91
+ const fieldsByStoredName = /* @__PURE__ */ new Map();
92
+ for (const field of fields) {
93
+ const { fieldName } = field;
94
+ const key = modelFieldKey(modelName, fieldName);
95
+ const storedName = storedNameOf(field);
96
+ const unsupported = unsupportedStoredNameReason(storedName);
97
+ if (unsupported !== void 0) refusals.push({
98
+ kind: "storedNameUnsupported",
99
+ key,
100
+ reason: unsupported
101
+ });
102
+ const firstField = fieldsByStoredName.get(storedName);
103
+ if (firstField !== void 0) {
104
+ refusals.push({
105
+ kind: "storedNameDuplicate",
106
+ key,
107
+ storedName,
108
+ firstField
109
+ });
110
+ continue;
111
+ }
112
+ fieldsByStoredName.set(storedName, fieldName);
113
+ storageFields[fieldName] = { field: storedName };
114
+ }
115
+ return storageFields;
116
+ }
117
+ function toOneRelationNullable(key, relation, fields, refusals) {
118
+ const ownsForeignKey = relation.cardinality !== "1:1";
119
+ const localFields = [];
120
+ if (ownsForeignKey) for (const fieldName of relation.on.localFields) {
121
+ const localField = fields.find((field) => field.fieldName === fieldName);
122
+ if (localField === void 0) {
123
+ refusals.push({
124
+ kind: "relationLocalFieldUnknown",
125
+ key,
126
+ fieldName
127
+ });
128
+ return relation.nullable ?? false;
129
+ }
130
+ localFields.push(localField);
131
+ }
132
+ const { nullable, contradiction } = resolveToOneRelationNullable({
133
+ declaredNullable: relation.nullable,
134
+ localFieldNullability: localFields.map((localField) => localField.nullable === true),
135
+ ownsReference: ownsForeignKey
136
+ });
137
+ if (contradiction !== void 0) refusals.push({
138
+ kind: "relationNullability",
139
+ key,
140
+ ownsForeignKey,
141
+ contradiction
142
+ });
143
+ return nullable;
144
+ }
145
+ function buildRelation(model, relation, namespaceId, refusals) {
146
+ const to = crossRef(relation.toModel, namespaceId);
147
+ if (relation.on === void 0) return {
148
+ to,
149
+ cardinality: relation.cardinality
150
+ };
151
+ if (relation.cardinality === "1:N") return {
152
+ to,
153
+ cardinality: "1:N",
154
+ on: relation.on
155
+ };
156
+ const key = {
157
+ kind: "relation",
158
+ model: model.modelName,
159
+ relation: relation.relationName
160
+ };
161
+ return {
162
+ to,
163
+ cardinality: relation.cardinality,
164
+ nullable: toOneRelationNullable(key, relation, model.fields, refusals),
165
+ on: relation.on
166
+ };
167
+ }
168
+ function buildValueObjects(valueObjects, namespaceId, refusals) {
169
+ const builtValueObjects = {};
170
+ for (const valueObject of valueObjects ?? []) {
171
+ if (valueObject.name in builtValueObjects) {
172
+ refusals.push({
173
+ kind: "duplicateValueObject",
174
+ key: {
175
+ kind: "valueObject",
176
+ valueObject: valueObject.name
177
+ }
178
+ });
179
+ continue;
180
+ }
181
+ for (const field of valueObject.fields) if (field.storedName !== void 0) refusals.push({
182
+ kind: "valueObjectFieldStoredName",
183
+ key: valueObjectFieldKey(valueObject.name, field.fieldName)
184
+ });
185
+ builtValueObjects[valueObject.name] = { fields: buildFields(valueObject.fields, namespaceId) };
186
+ }
187
+ return builtValueObjects;
188
+ }
189
+ /**
190
+ * Refuses a variant field stored under a name another field of its base is stored under. A variant's documents hold its base's fields too, so the two would overwrite each other, the discriminator included. A variant that restates a base field under the same name restates that field.
191
+ */
192
+ function restatementDifferences(variantField, baseField) {
193
+ const differences = [];
194
+ if (storedNameOf(variantField) !== storedNameOf(baseField)) differences.push("storedName");
195
+ if (canonicalStringify([variantField.type, variantField.enumName]) !== canonicalStringify([baseField.type, baseField.enumName])) differences.push("type");
196
+ if (variantField.nullable !== baseField.nullable) differences.push("nullable");
197
+ if (canonicalStringify(variantField.many) !== canonicalStringify(baseField.many)) differences.push("many");
198
+ return differences;
199
+ }
200
+ /**
201
+ * A variant's documents hold its base's fields too, and its collection's validator is written from the base. A variant field may restate a base field only exactly, and may not take a stored name a different base field uses.
202
+ */
203
+ function checkFieldsAgainstBase(variant, models, refusals) {
204
+ if (variant.base === void 0) return;
205
+ const baseName = variant.base.model;
206
+ const base = models.find((model) => model.modelName === baseName);
207
+ if (base === void 0) return;
208
+ const baseFieldsByName = new Map(base.fields.map((field) => [field.fieldName, field]));
209
+ const baseFieldsByStoredName = new Map(base.fields.map((field) => [storedNameOf(field), field]));
210
+ for (const field of variant.fields) {
211
+ const key = modelFieldKey(variant.modelName, field.fieldName);
212
+ const restated = baseFieldsByName.get(field.fieldName);
213
+ if (restated !== void 0) {
214
+ const differences = restatementDifferences(field, restated);
215
+ if (differences.length > 0) refusals.push({
216
+ kind: "restatedBaseFieldDiffers",
217
+ key,
218
+ baseModel: baseName,
219
+ differences
220
+ });
221
+ continue;
222
+ }
223
+ const storedName = storedNameOf(field);
224
+ const baseField = baseFieldsByStoredName.get(storedName);
225
+ if (baseField === void 0) continue;
226
+ refusals.push({
227
+ kind: "storedNameSharedWithBase",
228
+ key,
229
+ storedName,
230
+ baseModel: baseName,
231
+ baseField: baseField.fieldName
232
+ });
233
+ }
234
+ }
235
+ /**
236
+ * Each model of the contract. `variantValues` holds each accepted variant's discriminator value as its base's field stores it; a base lists those variants.
237
+ */
238
+ function buildModels(input) {
239
+ const { models, variantValues, namespaceId, refusals } = input;
240
+ const builtModels = {};
241
+ for (const model of models) {
242
+ const { modelName } = model;
243
+ if (modelName in builtModels) {
244
+ refusals.push({
245
+ kind: "duplicateModel",
246
+ key: {
247
+ kind: "model",
248
+ model: modelName
249
+ }
250
+ });
251
+ continue;
252
+ }
253
+ checkFieldsAgainstBase(model, models, refusals);
254
+ const storage = {
255
+ ...model.collection ? { collection: model.collection } : {},
256
+ fields: buildStorageFields(modelName, model.fields, refusals),
257
+ ...model.storageRelations ? { relations: model.storageRelations } : {}
258
+ };
259
+ const variants = model.discriminator === void 0 ? void 0 : models.flatMap((variant) => {
260
+ const value = variantValues.get(variant.modelName);
261
+ return variant.base?.model === modelName && value !== void 0 ? [[value, crossRef(variant.modelName, namespaceId)]] : [];
262
+ });
263
+ builtModels[modelName] = {
264
+ fields: buildFields(model.fields, namespaceId),
265
+ relations: Object.fromEntries((model.relations ?? []).map((relation) => [relation.relationName, buildRelation(model, relation, namespaceId, refusals)])),
266
+ storage,
267
+ ...model.owner ? { owner: model.owner } : {},
268
+ ...model.base ? { base: crossRef(model.base.model, namespaceId) } : {},
269
+ ...model.discriminator ? { discriminator: { field: model.discriminator.field } } : {},
270
+ ...variants === void 0 ? {} : { variants: Object.fromEntries(variants) }
271
+ };
272
+ }
273
+ return builtModels;
274
+ }
275
+ function buildRoots(definition, models, namespaceId) {
276
+ if (definition.roots !== void 0) return Object.fromEntries(Object.entries(definition.roots).map(([rootName, modelName]) => [rootName, crossRef(modelName, namespaceId)]));
277
+ const roots = {};
278
+ for (const model of models) {
279
+ if (!model.collection || model.owner || model.base) continue;
280
+ roots[model.collection] = crossRef(model.modelName, namespaceId);
281
+ }
282
+ return roots;
283
+ }
284
+ /**
285
+ * A key-sorted signature of a storage index, used only to find duplicate indexes. `canonicalStringify` refuses class instances such as `MongoIndex`, so this reads their enumerable properties instead.
286
+ */
287
+ function stableStringify(value) {
288
+ if (Array.isArray(value)) return `[${value.map(stableStringify).join(",")}]`;
289
+ if (value && typeof value === "object") return `{${Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, entry]) => `${JSON.stringify(key)}:${stableStringify(entry)}`).join(",")}}`;
290
+ return JSON.stringify(value);
291
+ }
292
+ function storedIndexKey(fields, key) {
293
+ const scope = key.match(/^(.+)\.\$\*\*$/)?.[1];
294
+ if (scope !== void 0) return `${storedFieldNameIn(fields, scope)}.$**`;
295
+ return key === "$**" ? key : storedFieldNameIn(fields, key);
296
+ }
297
+ function toStorageIndex(index, fields) {
298
+ const input = { keys: Object.entries(index.fields).map(([field, direction]) => ({
299
+ field: storedIndexKey(fields, field),
300
+ direction
301
+ })) };
302
+ if (index.options) {
303
+ for (const [key, value] of Object.entries(index.options)) if (value !== void 0) input[key] = value;
304
+ }
305
+ return new MongoIndex(blindCast(input));
306
+ }
307
+ function toStorageCollectionOptions(opts) {
308
+ return new MongoCollectionOptions({
309
+ ...opts.capped ? { capped: {
310
+ size: opts.size ?? 0,
311
+ ...opts.max != null && { max: opts.max }
312
+ } } : {},
313
+ ...ifDefined("storageEngine", opts.storageEngine),
314
+ ...ifDefined("indexOptionDefaults", opts.indexOptionDefaults),
315
+ ...ifDefined("collation", opts.collation),
316
+ ...ifDefined("timeseries", opts.timeseries),
317
+ ...opts.clusteredIndex !== void 0 && { clusteredIndex: opts.clusteredIndex.name !== void 0 ? { name: opts.clusteredIndex.name } : {} },
318
+ ...ifDefined("expireAfterSeconds", opts.expireAfterSeconds),
319
+ ...ifDefined("changeStreamPreAndPostImages", opts.changeStreamPreAndPostImages)
320
+ });
321
+ }
322
+ function findMissingIndexField(index, fields) {
323
+ for (const fieldName of Object.keys(index.fields)) {
324
+ const wildcardMatch = fieldName.match(/^(.+)\.\$\*\*$/);
325
+ const lookupName = wildcardMatch ? wildcardMatch[1] : fieldName;
326
+ if (lookupName === void 0 || lookupName.length === 0) continue;
327
+ if (lookupName === "$**") continue;
328
+ if (!fields.some((field) => field.fieldName === lookupName)) return lookupName;
329
+ }
330
+ }
331
+ function isWildcardKey(key) {
332
+ return key === "$**" || key.endsWith(".$**");
333
+ }
334
+ function isTextIndex(index) {
335
+ return Object.values(index.fields).includes("text");
336
+ }
337
+ /** The first shape rule an index breaks, of those MongoDB enforces when it creates the index. */
338
+ function indexShapeProblem(index) {
339
+ const keys = Object.entries(index.fields);
340
+ const hasWildcard = keys.some(([key]) => isWildcardKey(key));
341
+ const directions = keys.map(([, direction]) => direction);
342
+ const options = index.options ?? {};
343
+ if (hasWildcard && options.unique) return "unique-wildcard";
344
+ if (hasWildcard && directions.some((direction) => [
345
+ "hashed",
346
+ "2d",
347
+ "2dsphere"
348
+ ].includes(String(direction)))) return "wildcard-with-type";
349
+ if (directions.includes("hashed") && keys.length > 1) return "hashed-several-fields";
350
+ if (hasWildcard && options.expireAfterSeconds !== void 0) return "ttl-with-wildcard";
351
+ if (!hasWildcard && options.wildcardProjection !== void 0) return "projection-without-wildcard";
352
+ if (options.collation !== void 0 && !options.collation.locale) return "collation-without-locale";
353
+ }
354
+ function resolveVariantScope(model, modelsByName, variantValues) {
355
+ if (!model.base) return void 0;
356
+ const base = modelsByName.get(model.base.model);
357
+ const discriminatorField = base?.discriminator?.field;
358
+ const discriminatorValue = variantValues.get(model.modelName);
359
+ if (base === void 0 || !discriminatorField || discriminatorValue === void 0) return;
360
+ return {
361
+ discriminatorField: storedFieldNameIn(base.fields, discriminatorField),
362
+ discriminatorValue
363
+ };
364
+ }
365
+ function checkNoCollectionSettings(model, refusals) {
366
+ const key = {
367
+ kind: "collectionSettings",
368
+ model: model.modelName
369
+ };
370
+ if (model.indexes && model.indexes.length > 0) refusals.push({
371
+ kind: "collectionSettingWithoutCollection",
372
+ key,
373
+ setting: "indexes"
374
+ });
375
+ if (model.collectionOptions) refusals.push({
376
+ kind: "collectionSettingWithoutCollection",
377
+ key,
378
+ setting: "collectionOptions"
379
+ });
380
+ if (model.controlPolicy) refusals.push({
381
+ kind: "collectionSettingWithoutCollection",
382
+ key,
383
+ setting: "controlPolicy"
384
+ });
385
+ }
386
+ /** Each collection the models are stored in, with its indexes, options and control policy. Validators are added later. */
387
+ function buildCollections(input) {
388
+ const { models, variantValues, refusals } = input;
389
+ const intermediate = {};
390
+ const declaredIndexOwners = /* @__PURE__ */ new Map();
391
+ const textIndexCollections = /* @__PURE__ */ new Set();
392
+ const modelsByName = new Map(models.map((model) => [model.modelName, model]));
393
+ for (const model of models) {
394
+ const { modelName, collection } = model;
395
+ if (!collection) {
396
+ checkNoCollectionSettings(model, refusals);
397
+ continue;
398
+ }
399
+ const collectionKey = {
400
+ kind: "collectionSettings",
401
+ model: modelName
402
+ };
403
+ const existingCollection = intermediate[collection] ?? {};
404
+ const existingIndexes = existingCollection.indexes ?? [];
405
+ if (existingCollection.options && model.collectionOptions) refusals.push({
406
+ kind: "collectionSettingTwice",
407
+ key: collectionKey,
408
+ setting: "collectionOptions",
409
+ collection
410
+ });
411
+ if (existingCollection.control !== void 0 && model.controlPolicy) refusals.push({
412
+ kind: "collectionSettingTwice",
413
+ key: collectionKey,
414
+ setting: "controlPolicy",
415
+ collection
416
+ });
417
+ const polymorphicScope = resolveVariantScope(model, modelsByName, variantValues);
418
+ const storageIndexes = [];
419
+ (model.indexes ?? []).forEach((written, position) => {
420
+ const key = {
421
+ kind: "index",
422
+ model: modelName,
423
+ position
424
+ };
425
+ const signature = canonicalStringify(written);
426
+ const missingField = findMissingIndexField(written, model.fields);
427
+ if (missingField !== void 0) {
428
+ refusals.push({
429
+ kind: "indexFieldUnknown",
430
+ key,
431
+ fieldName: missingField,
432
+ signature
433
+ });
434
+ return;
435
+ }
436
+ const shapeProblem = indexShapeProblem(written);
437
+ if (shapeProblem !== void 0) {
438
+ refusals.push({
439
+ kind: "indexShape",
440
+ key,
441
+ rule: shapeProblem,
442
+ signature
443
+ });
444
+ return;
445
+ }
446
+ if (isTextIndex(written)) {
447
+ if (textIndexCollections.has(collection)) {
448
+ refusals.push({
449
+ kind: "indexShape",
450
+ key,
451
+ rule: "second-text-index",
452
+ signature
453
+ });
454
+ return;
455
+ }
456
+ textIndexCollections.add(collection);
457
+ }
458
+ const storageIndex = toStorageIndex(written, model.fields);
459
+ const scoped = polymorphicScope === void 0 ? {
460
+ kind: "ok",
461
+ index: storageIndex
462
+ } : applyPolymorphicScopeToMongoIndex(storageIndex, polymorphicScope);
463
+ if (scoped.kind === "conflict") {
464
+ refusals.push({
465
+ kind: "indexScopeConflict",
466
+ key,
467
+ reason: scoped.reason,
468
+ signature
469
+ });
470
+ return;
471
+ }
472
+ const collectionIndexKey = `${collection}:${stableStringify(scoped.index)}`;
473
+ const firstModel = declaredIndexOwners.get(collectionIndexKey);
474
+ if (firstModel !== void 0) {
475
+ refusals.push({
476
+ kind: "indexDuplicate",
477
+ key,
478
+ collection,
479
+ firstModel,
480
+ signature
481
+ });
482
+ return;
483
+ }
484
+ declaredIndexOwners.set(collectionIndexKey, modelName);
485
+ storageIndexes.push(scoped.index);
486
+ });
487
+ const storageOptions = model.collectionOptions ? toStorageCollectionOptions(model.collectionOptions) : void 0;
488
+ const controlPatch = model.controlPolicy !== void 0 ? { control: model.controlPolicy } : {};
489
+ intermediate[collection] = storageIndexes.length > 0 ? {
490
+ ...existingCollection,
491
+ indexes: [...existingIndexes, ...storageIndexes],
492
+ ...storageOptions ? { options: storageOptions } : {},
493
+ ...controlPatch
494
+ } : storageOptions ? {
495
+ ...existingCollection,
496
+ options: storageOptions,
497
+ ...controlPatch
498
+ } : Object.keys(controlPatch).length > 0 ? {
499
+ ...existingCollection,
500
+ ...controlPatch
501
+ } : existingCollection;
502
+ }
503
+ return intermediate;
504
+ }
505
+ /** Each enum with its members as its codec stores them. An enum the builder refuses is left out. */
506
+ function buildEnums(definition, codecLookup, refusals) {
507
+ const builtEnums = {};
508
+ for (const [enumName, handle] of Object.entries(definition.enums ?? {})) {
509
+ const encoded = encodeEnumMembers(handle, codecLookup);
510
+ if (!encoded.ok) {
511
+ for (const problem of encoded.failure) refusals.push({
512
+ kind: "enumMemberProblem",
513
+ key: "member" in problem ? {
514
+ kind: "enumMember",
515
+ enumName,
516
+ member: problem.member
517
+ } : {
518
+ kind: "enum",
519
+ enumName
520
+ },
521
+ enumName: handle.enumName,
522
+ codecId: handle.codecId,
523
+ problem
524
+ });
525
+ continue;
526
+ }
527
+ builtEnums[enumName] = {
528
+ codecId: handle.codecId,
529
+ members: encoded.value
530
+ };
531
+ }
532
+ for (const [enumName, handle] of Object.entries(definition.enums ?? {})) if (enumName !== handle.enumName) refusals.push({
533
+ kind: "enumKeyMismatch",
534
+ key: {
535
+ kind: "enum",
536
+ enumName
537
+ },
538
+ enumName: handle.enumName
539
+ });
540
+ return builtEnums;
541
+ }
542
+ const PHASES = ["onCreate", "onUpdate"];
543
+ function hasExecutionDefaults(field) {
544
+ const phases = field.executionDefaults;
545
+ const calls = field.generatorCalls;
546
+ const values = field.generatedValues;
547
+ return phases?.onCreate !== void 0 || phases?.onUpdate !== void 0 || values?.onCreate !== void 0 || values?.onUpdate !== void 0 || calls?.onCreate !== void 0 || calls?.onUpdate !== void 0;
548
+ }
549
+ /**
550
+ * The phases a field generates: its resolved execution defaults, with the generators its calls resolve to for its codec. Undefined when a call is refused.
551
+ */
552
+ function executionDefaultsOf(field, key, generatorFunctions, refusals) {
553
+ const typeGiven = field.executionDefaults;
554
+ let refused = false;
555
+ for (const phase of PHASES) if (typeGiven?.[phase] !== void 0 && field.generatedValues?.[phase] !== void 0) {
556
+ refusals.push({
557
+ kind: "generatorPhaseSetTwice",
558
+ key,
559
+ phase
560
+ });
561
+ refused = true;
562
+ }
563
+ const written = {
564
+ ...typeGiven,
565
+ ...field.generatedValues
566
+ };
567
+ const calls = field.generatorCalls;
568
+ if (calls === void 0) return refused ? void 0 : written;
569
+ const type = field.type;
570
+ const codecId = type.kind === "scalar" ? type.codecId : void 0;
571
+ const phases = written;
572
+ for (const phase of PHASES) {
573
+ const call = calls[phase];
574
+ if (call === void 0) continue;
575
+ if (written[phase] !== void 0) {
576
+ refusals.push({
577
+ kind: "generatorPhaseSetTwice",
578
+ key,
579
+ phase
580
+ });
581
+ refused = true;
582
+ continue;
583
+ }
584
+ const resolution = type.kind === "scalar" ? generatorFunctions.resolve(call, {
585
+ codecId: type.codecId,
586
+ typeParams: type.typeParams,
587
+ length: void 0
588
+ }) : void 0;
589
+ if (resolution?.ok === true) {
590
+ phases[phase] = resolution.generator;
591
+ continue;
592
+ }
593
+ refused = true;
594
+ refusals.push(resolution?.reason === "unknown-function" ? {
595
+ kind: "generatorUnknown",
596
+ key,
597
+ phase,
598
+ functionName: call.name,
599
+ codecId
600
+ } : {
601
+ kind: "generatorNotApplicable",
602
+ key,
603
+ phase,
604
+ functionName: call.name,
605
+ codecId,
606
+ message: resolution?.reason === "refused" ? resolution.message : void 0
607
+ });
608
+ }
609
+ return refused ? void 0 : phases;
610
+ }
611
+ function checkValueObjectExecutionDefaults(valueObjects, refusals) {
612
+ for (const valueObject of valueObjects ?? []) for (const field of valueObject.fields) if (hasExecutionDefaults(field)) refusals.push({
613
+ kind: "generatedOnValueObject",
614
+ key: valueObjectFieldKey(valueObject.name, field.fieldName)
615
+ });
616
+ }
617
+ function buildExecutionDefaults(input) {
618
+ const { models, generatorFunctions, namespaceId, refusals } = input;
619
+ const collectionByModelName = new Map(models.map((model) => [model.modelName, model.collection]));
620
+ const byRef = /* @__PURE__ */ new Map();
621
+ const defaults = [];
622
+ for (const model of models) {
623
+ const { modelName } = model;
624
+ for (const field of model.fields) {
625
+ if (!hasExecutionDefaults(field)) continue;
626
+ const { fieldName } = field;
627
+ const key = modelFieldKey(modelName, fieldName);
628
+ const phases = executionDefaultsOf(field, key, generatorFunctions, refusals);
629
+ if (phases === void 0) continue;
630
+ if (field.many) {
631
+ refusals.push({
632
+ kind: "generatedList",
633
+ key
634
+ });
635
+ continue;
636
+ }
637
+ if (model.base !== void 0) {
638
+ refusals.push({
639
+ kind: "generatedOnVariant",
640
+ key,
641
+ baseModel: model.base.model,
642
+ collection: model.collection ?? collectionByModelName.get(model.base.model)
643
+ });
644
+ continue;
645
+ }
646
+ const entry = model.collection;
647
+ if (entry === void 0) {
648
+ refusals.push({
649
+ kind: "generatedWithoutCollection",
650
+ key
651
+ });
652
+ continue;
653
+ }
654
+ const storedName = storedNameOf(field);
655
+ const refKey = JSON.stringify([entry, storedName]);
656
+ const phasesKey = canonicalStringify(phases);
657
+ const existing = byRef.get(refKey);
658
+ if (existing !== void 0) {
659
+ if (existing.phasesKey !== phasesKey) refusals.push({
660
+ kind: "generatedConflict",
661
+ key,
662
+ otherModel: existing.modelName,
663
+ otherField: existing.fieldName,
664
+ collection: entry
665
+ });
666
+ continue;
667
+ }
668
+ byRef.set(refKey, {
669
+ modelName,
670
+ fieldName,
671
+ phasesKey
672
+ });
673
+ defaults.push({
674
+ ref: {
675
+ namespace: namespaceId,
676
+ entry,
677
+ field: storedName
678
+ },
679
+ ...phases
680
+ });
681
+ }
682
+ }
683
+ return defaults;
684
+ }
685
+ function generatesNothing(field) {
686
+ const contributed = field.presetContribution?.executionDefaults;
687
+ const calls = field.generatorCalls;
688
+ const values = field.generatedValues;
689
+ return values?.onCreate === void 0 && values?.onUpdate === void 0 && contributed?.onCreate === void 0 && contributed?.onUpdate === void 0 && calls?.onCreate === void 0 && calls?.onUpdate === void 0;
690
+ }
691
+ function checkField(field, key, input) {
692
+ const { type } = field;
693
+ if (field.enumName !== void 0 && !input.declaredEnums.has(field.enumName)) input.refusals.push({
694
+ kind: "enumUnknown",
695
+ key,
696
+ enumName: field.enumName
697
+ });
698
+ if (type.kind === "scalar" && type.typeParams !== void 0) {
699
+ const problem = codecTypeParamsProblem(type.codecId, type.typeParams, input.lookups);
700
+ if (problem !== void 0) input.refusals.push({
701
+ kind: "typeParamsInvalid",
702
+ key,
703
+ problem
704
+ });
705
+ }
706
+ if (field.presetContribution !== void 0 && type.kind === "scalar" && generatesNothing(field)) input.warnings.push({
707
+ kind: "presetWithoutEffect",
708
+ key,
709
+ preset: field.presetContribution.preset,
710
+ codecId: type.codecId
711
+ });
712
+ }
713
+ /**
714
+ * Checks each field of the models and value objects on its own: its enum is declared, its data type accepts its type parameters, and a preset that made it generates a value.
715
+ */
716
+ function checkFields(input) {
717
+ for (const model of input.models) for (const field of model.fields) checkField(field, modelFieldKey(model.modelName, field.fieldName), input);
718
+ for (const valueObject of input.valueObjects ?? []) for (const field of valueObject.fields) checkField(field, valueObjectFieldKey(valueObject.name, field.fieldName), input);
719
+ }
720
+ /**
721
+ * The models with each variant stored in its base's collection: a variant that names no collection takes its base's, and one that names another is refused.
722
+ */
723
+ function inheritVariantCollections(models, refusals) {
724
+ const modelsByName = new Map(models.map((model) => [model.modelName, model]));
725
+ return models.map((model) => {
726
+ if (model.base === void 0) return model;
727
+ const baseCollection = modelsByName.get(model.base.model)?.collection;
728
+ if (baseCollection === void 0) return model;
729
+ if (model.collection === void 0) return {
730
+ ...model,
731
+ collection: baseCollection
732
+ };
733
+ if (model.collection !== baseCollection) refusals.push({
734
+ kind: "variantCollectionDiffers",
735
+ key: {
736
+ kind: "collectionSettings",
737
+ model: model.modelName
738
+ },
739
+ collection: model.collection,
740
+ baseModel: model.base.model,
741
+ baseCollection
742
+ });
743
+ return model;
744
+ });
745
+ }
746
+ function checkVariantShape(model, modelsByName, refusals) {
747
+ if (model.base === void 0) return;
748
+ const key = {
749
+ kind: "base",
750
+ variant: model.modelName
751
+ };
752
+ const baseModel = model.base.model;
753
+ if (model.discriminator !== void 0) refusals.push({
754
+ kind: "discriminatorAndBase",
755
+ key: {
756
+ kind: "discriminator",
757
+ model: model.modelName
758
+ }
759
+ });
760
+ const base = modelsByName.get(baseModel);
761
+ if (base === void 0) {
762
+ refusals.push({
763
+ kind: "baseUnknown",
764
+ key,
765
+ baseModel
766
+ });
767
+ return;
768
+ }
769
+ if (base.discriminator === void 0) {
770
+ refusals.push({
771
+ kind: "baseWithoutDiscriminator",
772
+ key,
773
+ baseModel
774
+ });
775
+ return;
776
+ }
777
+ if (model.base.value === void 0) refusals.push({
778
+ kind: "variantWithoutValue",
779
+ key,
780
+ baseModel
781
+ });
782
+ }
783
+ /** Each variant of `base` with the value its source wrote, in the order of the models. */
784
+ function writtenVariantsOf(base, models) {
785
+ return models.flatMap((model) => model.base?.model === base.modelName && model.base.value !== void 0 ? [{
786
+ key: model.modelName,
787
+ written: model.base.value
788
+ }] : []);
789
+ }
790
+ function decideDiscriminator(input) {
791
+ const { base, models, refusals } = input;
792
+ const discriminator = base.discriminator;
793
+ if (discriminator === void 0 || base.base !== void 0) return /* @__PURE__ */ new Map();
794
+ const key = {
795
+ kind: "discriminator",
796
+ model: base.modelName
797
+ };
798
+ const variantNames = new Set(models.filter((model) => model.base?.model === base.modelName).map((model) => model.modelName));
799
+ for (const listed of discriminator.listedVariants ?? []) if (!variantNames.has(listed)) refusals.push({
800
+ kind: "listedVariantMissing",
801
+ key,
802
+ variant: listed
803
+ });
804
+ if (variantNames.size === 0) refusals.push({
805
+ kind: "discriminatorWithoutVariants",
806
+ key
807
+ });
808
+ const fieldName = discriminator.field;
809
+ const field = base.fields.find((candidate) => candidate.fieldName === fieldName);
810
+ if (field === void 0) {
811
+ refusals.push({
812
+ kind: "discriminatorFieldUnknown",
813
+ key,
814
+ fieldName
815
+ });
816
+ return /* @__PURE__ */ new Map();
817
+ }
818
+ const { type } = field;
819
+ const enumMembers = field.enumName === void 0 ? void 0 : input.enums[field.enumName]?.members.map((member) => member.value);
820
+ const decision = applyDiscriminatorRule({
821
+ field: {
822
+ ref: type.kind === "scalar" ? {
823
+ codecId: type.codecId,
824
+ ...type.typeParams ? { typeParams: blindCast(type.typeParams) } : {}
825
+ } : void 0,
826
+ nullable: field.nullable,
827
+ many: field.many !== false,
828
+ enumMembers
829
+ },
830
+ variants: writtenVariantsOf(base, models),
831
+ subject: `Field "${base.modelName}.${fieldName}"`,
832
+ codecLookup: input.codecLookup,
833
+ dataTypes: input.dataTypes
834
+ });
835
+ for (const refusal of decision.fieldRefusals) refusals.push({
836
+ kind: "discriminatorField",
837
+ key,
838
+ fieldName,
839
+ refusal
840
+ });
841
+ for (const refusal of decision.variantRefusals) refusals.push({
842
+ kind: "discriminatorValue",
843
+ key: {
844
+ kind: "base",
845
+ variant: refusal.key
846
+ },
847
+ baseModel: base.modelName,
848
+ fieldName,
849
+ enumName: field.enumName,
850
+ refusal
851
+ });
852
+ const variantsByValue = /* @__PURE__ */ new Map();
853
+ for (const [variant, value] of decision.values) {
854
+ const firstVariant = variantsByValue.get(value);
855
+ if (firstVariant !== void 0) {
856
+ refusals.push({
857
+ kind: "discriminatorValueDuplicate",
858
+ key: {
859
+ kind: "base",
860
+ variant
861
+ },
862
+ baseModel: base.modelName,
863
+ value,
864
+ firstVariant
865
+ });
866
+ continue;
867
+ }
868
+ variantsByValue.set(value, variant);
869
+ }
870
+ return decision.values;
871
+ }
872
+ /**
873
+ * Checks each base and variant, and decides each variant's discriminator value with the framework's discriminator rule. Returns each accepted variant's value as its base's discriminator field stores it.
874
+ */
875
+ function decidePolymorphism(input) {
876
+ const { models, refusals } = input;
877
+ const modelsByName = new Map(models.map((model) => [model.modelName, model]));
878
+ const values = /* @__PURE__ */ new Map();
879
+ for (const model of models) {
880
+ checkVariantShape(model, modelsByName, refusals);
881
+ for (const [variant, value] of decideDiscriminator({
882
+ ...input,
883
+ base: model
884
+ })) values.set(variant, value);
885
+ }
886
+ return values;
887
+ }
888
+ /** Whether a refusal is about listing an enum in a collection validator, which matters only when collections get validators. */
889
+ function isAboutEnumListing(refusal) {
890
+ return refusal.kind === "enumBsonType" || refusal.kind === "enumNotListable" || refusal.kind === "enumMemberNotListable";
891
+ }
892
+ /**
893
+ * Builds a MongoDB contract from its plain-data definition, with the stack's codecs and data types. Every MongoDB family rule is checked here, and each refusal comes back as data keyed by the part of the definition it is about, for the source to report in its own terms.
894
+ */
895
+ function buildMongoContractFromDefinition(definition, codecLookup, dataTypes) {
896
+ const refusals = [];
897
+ const warnings = (definition.warnings ?? []).map((warning) => ({
898
+ kind: "source",
899
+ warning
900
+ }));
901
+ const namespaceId = definition.target.defaultNamespaceId;
902
+ const lookups = {
903
+ codecLookup,
904
+ dataTypeLookup: dataTypes.lookup
905
+ };
906
+ const generatorFunctions = assembleGeneratorFunctions([definition.target, ...Object.values(definition.extensions ?? {})]);
907
+ const models = inheritVariantCollections(definition.models, refusals);
908
+ const builtEnums = buildEnums(definition, codecLookup, refusals);
909
+ const variantValues = decidePolymorphism({
910
+ models,
911
+ enums: builtEnums,
912
+ codecLookup,
913
+ dataTypes,
914
+ refusals
915
+ });
916
+ const builtModels = buildModels({
917
+ models,
918
+ variantValues,
919
+ namespaceId,
920
+ refusals
921
+ });
922
+ const builtValueObjects = buildValueObjects(definition.valueObjects, namespaceId, refusals);
923
+ checkFields({
924
+ models,
925
+ valueObjects: definition.valueObjects,
926
+ declaredEnums: new Set(Object.keys(definition.enums ?? {})),
927
+ lookups,
928
+ refusals,
929
+ warnings
930
+ });
931
+ const collections = buildCollections({
932
+ models,
933
+ variantValues,
934
+ refusals
935
+ });
936
+ checkValueObjectExecutionDefaults(definition.valueObjects, refusals);
937
+ const executionDefaults = buildExecutionDefaults({
938
+ models,
939
+ generatorFunctions,
940
+ namespaceId,
941
+ refusals
942
+ });
943
+ if (refusals.length > 0) return notOk({
944
+ refusals,
945
+ warnings
946
+ });
947
+ const controlPolicies = {
948
+ collections: Object.fromEntries(Object.entries(collections).map(([name, collection]) => [name, collection.control])),
949
+ defaultControlPolicy: definition.defaultControlPolicy
950
+ };
951
+ const validatorRefusals = mongoContractRefusalsOf({
952
+ models: builtModels,
953
+ valueObjects: builtValueObjects,
954
+ enums: builtEnums,
955
+ lookups,
956
+ controlPolicies
957
+ }).filter((refusal) => definition.writesCollectionValidators || !isAboutEnumListing(refusal));
958
+ if (validatorRefusals.length > 0) return notOk({
959
+ refusals: validatorRefusals.map((refusal) => ({
960
+ kind: "validator",
961
+ key: validatorRefusalKey(refusal),
962
+ refusal
963
+ })),
964
+ warnings
965
+ });
966
+ const storageValueSets = mongoValueSetsOf(builtEnums);
967
+ const validators = definition.writesCollectionValidators ? deriveCollectionValidators({
968
+ models: builtModels,
969
+ lookups,
970
+ valueObjects: builtValueObjects,
971
+ valueSets: storageValueSets,
972
+ controlPolicies
973
+ }) : {};
974
+ const storage = buildMongoStorage({
975
+ namespaceId,
976
+ collections: Object.fromEntries(Object.entries(collections).map(([name, collection]) => [name, {
977
+ ...collection,
978
+ ...ifDefined("validator", validators[name])
979
+ }])),
980
+ valueSets: storageValueSets
981
+ });
982
+ const capabilities = {};
983
+ const execution = buildExecutionSection({
984
+ target: definition.target.targetId,
985
+ targetFamily: definition.target.familyId,
986
+ defaults: executionDefaults
987
+ });
988
+ return ok({
989
+ contract: {
990
+ target: definition.target.targetId,
991
+ targetFamily: definition.target.familyId,
992
+ ...ifDefined("defaultControlPolicy", definition.defaultControlPolicy),
993
+ roots: buildRoots(definition, models, namespaceId),
994
+ domain: { namespaces: { [namespaceId]: {
995
+ models: builtModels,
996
+ ...Object.keys(builtValueObjects).length > 0 ? { valueObjects: builtValueObjects } : {},
997
+ ...Object.keys(builtEnums).length > 0 ? { enum: builtEnums } : {}
998
+ } } },
999
+ storage,
1000
+ capabilities,
1001
+ extensions: definition.extensions ?? {},
1002
+ profileHash: computeProfileHash({
1003
+ target: definition.target.targetId,
1004
+ targetFamily: definition.target.familyId,
1005
+ capabilities
1006
+ }),
1007
+ meta: {},
1008
+ ...ifDefined("execution", execution)
1009
+ },
1010
+ warnings
1011
+ });
1012
+ }
1013
+ function resolveModelName(value) {
1014
+ return typeof value === "string" ? value : value.__name;
1015
+ }
1016
+ function validateTargetPackRef(family, target) {
1017
+ if (family.familyId !== "mongo") throw contractError("CONTRACT.PACK_FAMILY_MISMATCH", `defineContract only accepts Mongo family packs. Received family "${family.familyId}".`, { meta: {
1018
+ packId: family.id,
1019
+ packFamilyId: family.familyId,
1020
+ contractFamilyId: "mongo"
1021
+ } });
1022
+ if (target.familyId !== family.familyId) throw contractError("CONTRACT.PACK_FAMILY_MISMATCH", `target pack "${target.id}" targets family "${target.familyId}" but contract family is "${family.familyId}".`, { meta: {
1023
+ packId: target.id,
1024
+ packFamilyId: target.familyId,
1025
+ contractFamilyId: family.familyId
1026
+ } });
1027
+ }
1028
+ function validateExtensionPackRefs(target, extensions) {
1029
+ for (const packRef of Object.values(extensions ?? {})) {
1030
+ if (packRef.kind !== "extension") throw contractError("CONTRACT.PACK_REF_INVALID", `defineContract only accepts extension pack refs in extensions. Received kind "${packRef.kind}".`, { meta: {
1031
+ packId: packRef.id,
1032
+ kind: packRef.kind
1033
+ } });
1034
+ if (packRef.familyId !== target.familyId) throw contractError("CONTRACT.PACK_FAMILY_MISMATCH", `extension pack "${packRef.id}" targets family "${packRef.familyId}" but contract target family is "${target.familyId}".`, { meta: {
1035
+ packId: packRef.id,
1036
+ packFamilyId: packRef.familyId,
1037
+ contractFamilyId: target.familyId
1038
+ } });
1039
+ if (packRef.targetId && packRef.targetId !== target.targetId) throw contractError("CONTRACT.PACK_TARGET_MISMATCH", `extension pack "${packRef.id}" targets "${packRef.targetId}" but contract target is "${target.targetId}".`, { meta: {
1040
+ packId: packRef.id,
1041
+ packTargetId: packRef.targetId,
1042
+ contractTargetId: target.targetId
1043
+ } });
1044
+ }
1045
+ }
1046
+ function fieldNodes(fields) {
1047
+ return Object.entries(fields).map(([fieldName, builder]) => ({
1048
+ fieldName,
1049
+ ...ifDefined("storedName", builder.__storedName),
1050
+ type: builder.__type,
1051
+ nullable: builder.__nullable,
1052
+ many: builder.__many,
1053
+ ...ifDefined("enumName", builder.__enumHandle?.enumName),
1054
+ ...ifDefined("executionDefaults", builder.__executionDefaults),
1055
+ ...ifDefined("generatorCalls", builder.__generatorCalls),
1056
+ ...ifDefined("presetContribution", builder.__presetContribution)
1057
+ }));
1058
+ }
1059
+ function relationNodes(builder) {
1060
+ return Object.entries(builder.__relations).map(([relationName, relation]) => {
1061
+ const common = {
1062
+ relationName,
1063
+ toModel: relation.__to,
1064
+ nullable: relation.__nullable
1065
+ };
1066
+ return relation.__on === void 0 ? {
1067
+ ...common,
1068
+ cardinality: relation.__cardinality
1069
+ } : {
1070
+ ...common,
1071
+ cardinality: relation.__cardinality,
1072
+ on: relation.__on
1073
+ };
1074
+ });
1075
+ }
1076
+ function modelNode(builder, buildersByName) {
1077
+ const base = builder.__base;
1078
+ const variantValue = base === void 0 ? void 0 : buildersByName.get(base)?.__variants?.[builder.__name]?.value;
1079
+ return {
1080
+ modelName: builder.__name,
1081
+ ...ifDefined("collection", builder.__collection),
1082
+ ...ifDefined("owner", builder.__owner),
1083
+ ...ifDefined("storageRelations", builder.__storageRelations),
1084
+ ...ifDefined("controlPolicy", builder.__controlPolicy),
1085
+ ...ifDefined("collectionOptions", builder.__collectionOptions),
1086
+ ...ifDefined("indexes", builder.__indexes),
1087
+ fields: fieldNodes(builder.__fields),
1088
+ relations: relationNodes(builder),
1089
+ ...builder.__discriminator === void 0 ? {} : { discriminator: {
1090
+ field: builder.__discriminator.field,
1091
+ listedVariants: Object.keys(builder.__variants ?? {})
1092
+ } },
1093
+ ...base === void 0 ? {} : { base: {
1094
+ model: base,
1095
+ value: variantValue === void 0 ? void 0 : {
1096
+ kind: "string",
1097
+ text: variantValue
1098
+ }
1099
+ } }
1100
+ };
1101
+ }
1102
+ function valueObjectNode(builder) {
1103
+ return {
1104
+ name: builder.__name,
1105
+ fields: fieldNodes(builder.__fields)
1106
+ };
1107
+ }
1108
+ /** Turns `defineContract`'s builder objects into the plain-data definition the contract is built from. */
1109
+ function buildContractDefinition(input) {
1110
+ const { target } = input;
1111
+ validateTargetPackRef(input.family, target);
1112
+ validateExtensionPackRefs(target, input.extensions);
1113
+ const builders = Object.values(input.models ?? {});
1114
+ const buildersByName = /* @__PURE__ */ new Map();
1115
+ for (const builder of builders) if (!buildersByName.has(builder.__name)) buildersByName.set(builder.__name, builder);
1116
+ return {
1117
+ target,
1118
+ ...ifDefined("extensions", input.extensions),
1119
+ ...ifDefined("defaultControlPolicy", input.defaultControlPolicy),
1120
+ models: builders.map((builder) => modelNode(builder, buildersByName)),
1121
+ valueObjects: Object.values(input.valueObjects ?? {}).map(valueObjectNode),
1122
+ ...ifDefined("enums", input.enums),
1123
+ ...ifDefined("roots", input.roots === void 0 ? void 0 : Object.fromEntries(Object.entries(input.roots).map(([rootName, model]) => [rootName, resolveModelName(model)]))),
1124
+ writesCollectionValidators: true,
1125
+ warnings: void 0
1126
+ };
1127
+ }
1128
+ const LIST_THE_CODEC_PACK = "List the pack that provides the codec in `extensions` in defineContract.";
1129
+ function codecRefusalError(subject, meta, codecId, refusal) {
1130
+ if (refusal.kind === "unknownCodec") return contractError("CONTRACT.CODEC_DESCRIPTOR_MISSING", `${subject} ${refusal.reason}`, {
1131
+ fix: LIST_THE_CODEC_PACK,
1132
+ meta: {
1133
+ ...meta,
1134
+ codecId
1135
+ }
1136
+ });
1137
+ return contractError("CONTRACT.PACK_CONTRIBUTION_INVALID", `${subject} ${refusal.reason}`, {
1138
+ fix: "Use a codec whose data type is a MongoDB data type, declared with mongoDataType.",
1139
+ meta: {
1140
+ ...meta,
1141
+ codecId,
1142
+ dataType: refusal.dataType,
1143
+ reason: "data-type-not-mongo"
1144
+ }
1145
+ });
1146
+ }
1147
+ function validatorRefusalError(refusal) {
1148
+ switch (refusal.kind) {
1149
+ case "embeddedModelHasVariants": return contractError("CONTRACT.RELATION_INVALID", `Relation "${refusal.modelName}.${refusal.relationName}" ${refusal.reason}`, { meta: {
1150
+ modelName: refusal.modelName,
1151
+ relationName: refusal.relationName,
1152
+ reason: "embedded-model-has-variants"
1153
+ } });
1154
+ case "enumBsonType": return codecRefusalError(`enumType("${refusal.enumName}")`, { enumName: refusal.enumName }, refusal.codecId, refusal.refusal);
1155
+ case "enumNotListable": return contractError("CONTRACT.ENUM_INVALID", `enumType("${refusal.enumName}") codec "${refusal.codecId}" ${refusal.reason}`, { meta: {
1156
+ enumName: refusal.enumName,
1157
+ codecId: refusal.codecId,
1158
+ reason: "not-listable-by-validator"
1159
+ } });
1160
+ case "enumMemberNotListable": return contractError("CONTRACT.ENUM_INVALID", `enumType("${refusal.enumName}") member "${refusal.member}" ${refusal.reason}`, { meta: {
1161
+ enumName: refusal.enumName,
1162
+ member: refusal.member,
1163
+ codecId: refusal.codecId,
1164
+ reason: "member-not-listable-by-validator"
1165
+ } });
1166
+ case "fieldBsonType": {
1167
+ const { owner } = refusal;
1168
+ const label = owner.kind === "model" ? "Model" : "Value object";
1169
+ const ownerMeta = owner.kind === "model" ? { modelName: owner.name } : { valueObjectName: owner.name };
1170
+ return codecRefusalError(`${label} "${owner.name}" field "${refusal.fieldName}"`, {
1171
+ ...ownerMeta,
1172
+ fieldName: refusal.fieldName
1173
+ }, refusal.codecId, refusal.refusal);
1174
+ }
1175
+ case "documentId": return contractError("CONTRACT.COLLECTION_INVALID", `Model "${refusal.modelName}" field "${refusal.fieldName}" ${refusal.reason}`, { meta: {
1176
+ modelName: refusal.modelName,
1177
+ fieldName: refusal.fieldName,
1178
+ collection: refusal.collection,
1179
+ codecId: refusal.codecId,
1180
+ bsonTypes: refusal.forbidden,
1181
+ reason: "document-id-bson-type"
1182
+ } });
1183
+ }
1184
+ }
1185
+ function defaultError(key, reason, message) {
1186
+ return contractError("CONTRACT.DEFAULT_INVALID", `Field "${`${key.owner.name}.${key.field}`}" ${message}`, { meta: {
1187
+ modelName: key.owner.name,
1188
+ fieldName: key.field,
1189
+ reason
1190
+ } });
1191
+ }
1192
+ function ownerMetaOf(key) {
1193
+ return key.owner.kind === "model" ? {
1194
+ modelName: key.owner.name,
1195
+ fieldName: key.field
1196
+ } : {
1197
+ valueObjectName: key.owner.name,
1198
+ fieldName: key.field
1199
+ };
1200
+ }
1201
+ function ownerLabelOf(key) {
1202
+ return `${key.owner.kind === "model" ? "Model" : "Value object"} "${key.owner.name}" field "${key.field}"`;
1203
+ }
1204
+ const INDEX_SHAPE_MESSAGES = {
1205
+ "unique-wildcard": "is unique and has a wildcard key; a unique index cannot use a wildcard.",
1206
+ "wildcard-with-type": "combines a wildcard key with a hashed, 2d or 2dsphere key, which MongoDB does not allow.",
1207
+ "hashed-several-fields": "is hashed on several fields; a hashed index has exactly one field.",
1208
+ "ttl-with-wildcard": "sets expireAfterSeconds on a wildcard index, which MongoDB does not allow.",
1209
+ "projection-without-wildcard": "sets wildcardProjection but has no wildcard key; a wildcard projection needs a wildcard index.",
1210
+ "collation-without-locale": "sets a collation without a locale; a collation needs a locale.",
1211
+ "second-text-index": "is a second text index in its collection; MongoDB allows one text index per collection."
1212
+ };
1213
+ function discriminatorFieldError(refusal) {
1214
+ const field = `Discriminator field "${refusal.key.model}.${refusal.fieldName}"`;
1215
+ const meta = {
1216
+ modelName: refusal.key.model,
1217
+ fieldName: refusal.fieldName
1218
+ };
1219
+ switch (refusal.refusal.kind) {
1220
+ case "optional": return contractError("CONTRACT.ARGUMENT_INVALID", `${field} must be required, but it is optional. Remove .optional().`, { meta: {
1221
+ ...meta,
1222
+ reason: "discriminator-optional"
1223
+ } });
1224
+ case "list": return contractError("CONTRACT.ARGUMENT_INVALID", `${field} must hold one value, but it is a list. Remove .many().`, { meta: {
1225
+ ...meta,
1226
+ reason: "discriminator-list"
1227
+ } });
1228
+ case "not-text": {
1229
+ const { dataType } = refusal.refusal;
1230
+ return contractError("CONTRACT.ARGUMENT_INVALID", `${field} must be text, such as field.string(), but its data type is ${dataType === void 0 ? "not a scalar" : `"${dataType}"`}.`, { meta: {
1231
+ ...meta,
1232
+ dataType,
1233
+ reason: "discriminator-not-text"
1234
+ } });
1235
+ }
1236
+ }
1237
+ }
1238
+ /** The error `defineContract` throws for a refusal of the builder. */
1239
+ function refusalError(refusal) {
1240
+ switch (refusal.kind) {
1241
+ case "duplicateModel": return contractError("CONTRACT.NAME_DUPLICATE", `Duplicate model name "${refusal.key.model}" in defineContract().`, { meta: {
1242
+ kind: "model",
1243
+ name: refusal.key.model
1244
+ } });
1245
+ case "duplicateValueObject": return contractError("CONTRACT.NAME_DUPLICATE", `Duplicate value object name "${refusal.key.valueObject}" in defineContract().`, { meta: {
1246
+ kind: "valueObject",
1247
+ name: refusal.key.valueObject
1248
+ } });
1249
+ case "storedNameUnsupported": return contractError("CONTRACT.ARGUMENT_INVALID", `Model "${refusal.key.owner.name}" field "${refusal.key.field}" ${refusal.reason}. Give it another stored name.`, { meta: {
1250
+ modelName: refusal.key.owner.name,
1251
+ fieldName: refusal.key.field,
1252
+ reason: "stored-name-unsupported"
1253
+ } });
1254
+ case "storedNameDuplicate": return contractError("CONTRACT.NAME_DUPLICATE", `Model "${refusal.key.owner.name}" stores both "${refusal.firstField}" and "${refusal.key.field}" as "${refusal.storedName}".`, { meta: {
1255
+ kind: "field",
1256
+ name: refusal.storedName,
1257
+ first: refusal.firstField,
1258
+ second: refusal.key.field
1259
+ } });
1260
+ case "restatedBaseFieldDiffers": return contractError("CONTRACT.ARGUMENT_INVALID", `Variant model "${refusal.key.owner.name}" restates field "${refusal.key.field}" of its base "${refusal.baseModel}" with a different ${refusal.differences.map(differenceWording).join(" and ")}. A variant's documents are checked against the base's field, so restate it exactly or remove it from the variant.`, { meta: {
1261
+ modelName: refusal.key.owner.name,
1262
+ fieldName: refusal.key.field,
1263
+ baseModel: refusal.baseModel,
1264
+ differences: refusal.differences,
1265
+ reason: "restated-base-field-differs"
1266
+ } });
1267
+ case "storedNameSharedWithBase": return contractError("CONTRACT.NAME_DUPLICATE", `Variant model "${refusal.key.owner.name}" field "${refusal.key.field}" is stored as "${refusal.storedName}", which its base "${refusal.baseModel}" stores field "${refusal.baseField}" under. A variant's documents hold its base's fields too, so give the field another stored name.`, { meta: {
1268
+ kind: "field",
1269
+ name: refusal.storedName,
1270
+ first: `${refusal.baseModel}.${refusal.baseField}`,
1271
+ second: `${refusal.key.owner.name}.${refusal.key.field}`,
1272
+ reason: "stored-name-shared-with-base"
1273
+ } });
1274
+ case "valueObjectFieldStoredName": return contractError("CONTRACT.ARGUMENT_INVALID", `Value object "${refusal.key.owner.name}" field "${refusal.key.field}" sets .mongo({ field }), but a field of a value object is stored under its own name.`, { meta: {
1275
+ valueObjectName: refusal.key.owner.name,
1276
+ fieldName: refusal.key.field,
1277
+ reason: "value-object-field-stored-name"
1278
+ } });
1279
+ case "relationLocalFieldUnknown": {
1280
+ const { model, relation } = refusal.key;
1281
+ return contractError("CONTRACT.RELATION_INVALID", `Relation "${model}.${relation}" joins on local field "${refusal.fieldName}", which model "${model}" does not declare`, { meta: {
1282
+ modelName: model,
1283
+ relationName: relation,
1284
+ fieldName: refusal.fieldName,
1285
+ reason: "local-field-unknown"
1286
+ } });
1287
+ }
1288
+ case "relationNullability": {
1289
+ const { model, relation } = refusal.key;
1290
+ const location = `Relation "${model}.${relation}"`;
1291
+ return contractError("CONTRACT.RELATION_INVALID", !refusal.ownsForeignKey ? `${location} is required but does not own the foreign key, so nothing in storage guarantees the related document exists` : refusal.contradiction === "declared-optional" ? `${location} is optional but every local field it joins on is required` : `${location} is required but a local field it joins on is nullable`, { meta: {
1292
+ modelName: model,
1293
+ relationName: relation,
1294
+ reason: "to-one-nullability-mismatch"
1295
+ } });
1296
+ }
1297
+ case "collectionSettingWithoutCollection": {
1298
+ const modelName = refusal.key.model;
1299
+ const what = refusal.setting === "controlPolicy" ? "it" : "them";
1300
+ return contractError("CONTRACT.COLLECTION_INVALID", `Model "${modelName}" defines ${refusal.setting} but has no collection to attach ${what} to.`, { meta: {
1301
+ modelName,
1302
+ reason: `${refusal.setting}-without-collection`
1303
+ } });
1304
+ }
1305
+ case "collectionSettingTwice": return contractError("CONTRACT.COLLECTION_INVALID", `Collection "${refusal.collection}" has ${refusal.setting} declared by multiple models. Author ${refusal.setting} on a single model per collection.`, { meta: {
1306
+ modelName: refusal.key.model,
1307
+ collection: refusal.collection,
1308
+ reason: `${refusal.setting}-declared-by-multiple-models`
1309
+ } });
1310
+ case "variantCollectionDiffers": return contractError("CONTRACT.COLLECTION_INVALID", `Variant model "${refusal.key.model}" is stored in collection "${refusal.collection}", but its base "${refusal.baseModel}" is stored in "${refusal.baseCollection}". A variant is stored in its base's collection; leave its collection out.`, { meta: {
1311
+ modelName: refusal.key.model,
1312
+ collection: refusal.collection,
1313
+ baseModel: refusal.baseModel,
1314
+ baseCollection: refusal.baseCollection,
1315
+ reason: "variant-collection-differs"
1316
+ } });
1317
+ case "indexFieldUnknown": return contractError("CONTRACT.FIELD_UNKNOWN", `Model "${refusal.key.model}" index ${refusal.signature} references unknown field "${refusal.fieldName}".`, { meta: {
1318
+ modelName: refusal.key.model,
1319
+ fieldName: refusal.fieldName,
1320
+ indexSignature: refusal.signature
1321
+ } });
1322
+ case "indexShape": return contractError("CONTRACT.INDEX_INVALID", `Model "${refusal.key.model}" index ${refusal.signature} ${INDEX_SHAPE_MESSAGES[refusal.rule]}`, { meta: {
1323
+ modelName: refusal.key.model,
1324
+ indexSignature: refusal.signature,
1325
+ reason: refusal.rule
1326
+ } });
1327
+ case "indexScopeConflict": return contractError("CONTRACT.INDEX_INVALID", `Variant model "${refusal.key.model}" index ${refusal.signature} conflicts with discriminator scope: ${refusal.reason}`, { meta: {
1328
+ variantName: refusal.key.model,
1329
+ indexLabel: refusal.signature,
1330
+ reason: refusal.reason
1331
+ } });
1332
+ case "indexDuplicate": return contractError("CONTRACT.NAME_DUPLICATE", `Collection "${refusal.collection}" defines duplicate index ${refusal.signature}. First declared on model "${refusal.firstModel}" and duplicated on model "${refusal.key.model}".`, { meta: {
1333
+ kind: "index",
1334
+ name: refusal.signature,
1335
+ collection: refusal.collection,
1336
+ first: refusal.firstModel,
1337
+ second: refusal.key.model
1338
+ } });
1339
+ case "generatedOnValueObject": return defaultError(refusal.key, "executionDefaults-on-value-object", "has executionDefaults, but it belongs to a value object. Generated values are only supported on model fields.");
1340
+ case "generatorUnknown": {
1341
+ const { owner, field } = refusal.key;
1342
+ return contractError("CONTRACT.DEFAULT_INVALID", `Field "${owner.name}.${field}": no pack in the contract declares the generator function "${refusal.functionName}".`, { meta: {
1343
+ modelName: owner.name,
1344
+ fieldName: field,
1345
+ codecId: refusal.codecId,
1346
+ function: refusal.functionName,
1347
+ reason: "generator-unknown"
1348
+ } });
1349
+ }
1350
+ case "generatorNotApplicable": {
1351
+ const { owner, field } = refusal.key;
1352
+ const subject = `Field "${owner.name}.${field}"`;
1353
+ return contractError("CONTRACT.DEFAULT_INVALID", refusal.message !== void 0 ? `${subject}: ${refusal.message}` : `${subject}: ${refusal.functionName}() does not apply to ${refusal.codecId === void 0 ? "the field's type" : `codec "${refusal.codecId}"`}.`, { meta: {
1354
+ modelName: owner.name,
1355
+ fieldName: field,
1356
+ codecId: refusal.codecId,
1357
+ function: refusal.functionName,
1358
+ reason: "generator-not-applicable"
1359
+ } });
1360
+ }
1361
+ case "generatorPhaseSetTwice": return contractError("CONTRACT.DEFAULT_INVALID", `.${refusal.phase}() is called on a field that already generates a value ${refusal.phase === "onCreate" ? "on create" : "on update"}. Set each phase once, and do not combine .${refusal.phase}() with a field preset, type alias or alias constant that sets it.`, { meta: {
1362
+ modelName: refusal.key.owner.name,
1363
+ fieldName: refusal.key.field,
1364
+ reason: "generator-phase-set-twice",
1365
+ phase: refusal.phase
1366
+ } });
1367
+ case "generatedList": return defaultError(refusal.key, "many-with-executionDefaults", "generates a value on write, so it cannot be a list; remove .many().");
1368
+ case "generatedOnVariant": return defaultError(refusal.key, "executionDefaults-on-variant", `has executionDefaults, but "${refusal.key.owner.name}" is a variant of "${refusal.baseModel}". Execution defaults apply to every document in collection "${refusal.collection}", so declare them on the base model.`);
1369
+ case "generatedWithoutCollection": return defaultError(refusal.key, "executionDefaults-without-collection", "has executionDefaults, but its model has no collection. Generated values are only supported on fields of a model stored in a collection.");
1370
+ case "generatedConflict": return defaultError(refusal.key, "executionDefaults-conflict", `has different executionDefaults than "${refusal.otherModel}.${refusal.otherField}", which is stored in the same collection "${refusal.collection}". Use the same executionDefaults on both models.`);
1371
+ case "typeParamsInvalid": return structuredError("CONTRACT.TYPE_PARAMS_INVALID", refusal.problem.message, { meta: {
1372
+ dataType: refusal.problem.dataType,
1373
+ parameters: refusal.problem.parameters,
1374
+ ...ownerMetaOf(refusal.key)
1375
+ } });
1376
+ case "enumKeyMismatch": return contractError("CONTRACT.ENUM_INVALID", `enum declaration key "${refusal.key.enumName}" must match enumType name "${refusal.enumName}". Aliases are not supported.`, { meta: {
1377
+ enumName: refusal.enumName,
1378
+ declaredKey: refusal.key.enumName,
1379
+ reason: "declaration-key-mismatch"
1380
+ } });
1381
+ case "enumMemberProblem": return enumMemberError({
1382
+ enumName: refusal.enumName,
1383
+ codecId: refusal.codecId
1384
+ }, refusal.problem, "the field");
1385
+ case "enumUnknown": return contractError("CONTRACT.ENUM_UNKNOWN", `${ownerLabelOf(refusal.key)} references enum "${refusal.enumName}" which is not declared in defineContract({ enums: { ... } }).`, { meta: {
1386
+ ...ownerMetaOf(refusal.key),
1387
+ enumName: refusal.enumName
1388
+ } });
1389
+ case "discriminatorValueDuplicate": return contractError("CONTRACT.ARGUMENT_INVALID", `Discriminator value "${refusal.value}" is used by both "${refusal.firstVariant}" and "${refusal.key.variant}" on base model "${refusal.baseModel}".`, { meta: {
1390
+ modelName: refusal.baseModel,
1391
+ value: refusal.value,
1392
+ variants: [refusal.firstVariant, refusal.key.variant],
1393
+ reason: "duplicate-discriminator-value"
1394
+ } });
1395
+ case "discriminatorFieldUnknown": return contractError("CONTRACT.FIELD_UNKNOWN", `Model "${refusal.key.model}" names "${refusal.fieldName}" as its discriminator, but declares no field "${refusal.fieldName}".`, { meta: {
1396
+ modelName: refusal.key.model,
1397
+ fieldName: refusal.fieldName,
1398
+ reason: "discriminator-field-unknown"
1399
+ } });
1400
+ case "discriminatorField": return discriminatorFieldError(refusal);
1401
+ case "discriminatorValue": {
1402
+ const variant = refusal.key.variant;
1403
+ const meta = {
1404
+ modelName: variant,
1405
+ baseModel: refusal.baseModel,
1406
+ fieldName: refusal.fieldName
1407
+ };
1408
+ if (refusal.refusal.kind === "unreadable") return contractError("CONTRACT.ARGUMENT_INVALID", `Variant model "${variant}" has a discriminator value that discriminator field "${refusal.baseModel}.${refusal.fieldName}" cannot hold: ${refusal.refusal.refusal.message}`, { meta: {
1409
+ ...meta,
1410
+ reason: "discriminator-value-unreadable"
1411
+ } });
1412
+ return contractError("CONTRACT.ARGUMENT_INVALID", `Variant model "${variant}" has discriminator value ${JSON.stringify(refusal.refusal.stored)}, which is not a member of enum "${refusal.enumName}", the type of discriminator field "${refusal.baseModel}.${refusal.fieldName}". Use one of: ${refusal.refusal.members.map((member) => JSON.stringify(member)).join(", ")}.`, { meta: {
1413
+ ...meta,
1414
+ reason: "discriminator-value-not-a-member"
1415
+ } });
1416
+ }
1417
+ case "discriminatorAndBase": return contractError("CONTRACT.ARGUMENT_INVALID", `Model "${refusal.key.model}" has both a discriminator and a base. A model is either a base with variants or a variant of one base.`, { meta: {
1418
+ modelName: refusal.key.model,
1419
+ reason: "discriminator-and-base"
1420
+ } });
1421
+ case "discriminatorWithoutVariants": return contractError("CONTRACT.ARGUMENT_INVALID", `Model "${refusal.key.model}" has a discriminator, but no model names it as its base.`, { meta: {
1422
+ modelName: refusal.key.model,
1423
+ reason: "discriminator-without-variants"
1424
+ } });
1425
+ case "listedVariantMissing": return contractError("CONTRACT.ARGUMENT_INVALID", `Model "${refusal.key.model}" lists variant "${refusal.variant}", but no model "${refusal.variant}" names "${refusal.key.model}" as its base.`, { meta: {
1426
+ modelName: refusal.key.model,
1427
+ variant: refusal.variant,
1428
+ reason: "listed-variant-missing"
1429
+ } });
1430
+ case "baseWithoutDiscriminator": return contractError("CONTRACT.ARGUMENT_INVALID", `Model "${refusal.key.variant}" names "${refusal.baseModel}" as its base, but "${refusal.baseModel}" has no discriminator.`, { meta: {
1431
+ modelName: refusal.key.variant,
1432
+ baseModel: refusal.baseModel,
1433
+ reason: "base-without-discriminator"
1434
+ } });
1435
+ case "baseUnknown": return contractError("CONTRACT.ARGUMENT_INVALID", `Model "${refusal.key.variant}" names "${refusal.baseModel}" as its base, but the contract has no model "${refusal.baseModel}".`, { meta: {
1436
+ modelName: refusal.key.variant,
1437
+ baseModel: refusal.baseModel,
1438
+ reason: "base-unknown"
1439
+ } });
1440
+ case "variantWithoutValue": return contractError("CONTRACT.ARGUMENT_INVALID", `Model "${refusal.key.variant}" names "${refusal.baseModel}" as its base, but "${refusal.baseModel}" lists no discriminator value for it.`, { meta: {
1441
+ modelName: refusal.key.variant,
1442
+ baseModel: refusal.baseModel,
1443
+ reason: "variant-without-value"
1444
+ } });
1445
+ case "validator": return validatorRefusalError(refusal.refusal);
1446
+ }
1447
+ }
1448
+ /** A builder warning as `defineContract` reports it. */
1449
+ function authoringWarningOf(warning) {
1450
+ if (warning.kind === "source") return warning.warning;
1451
+ const item = `field "${warning.key.owner.name}.${warning.key.field}"`;
1452
+ return {
1453
+ code: "PN_PRESET_WITHOUT_EFFECT",
1454
+ message: `Field "${warning.key.owner.name}.${warning.key.field}" uses ${warning.preset}(), which generates no value, so the field is stored like any field of codec "${warning.codecId}".`,
1455
+ item,
1456
+ summary: "fields use a preset that generates no value"
1457
+ };
1458
+ }
1459
+ function differenceWording(difference) {
1460
+ switch (difference) {
1461
+ case "storedName": return "stored name";
1462
+ case "type": return "type";
1463
+ case "nullable": return "nullability";
1464
+ case "many": return "list shape";
1465
+ }
1466
+ }
1467
+ const MONGO_RESERVED_HELPER_KEYS = [
1468
+ "field",
1469
+ "gen",
1470
+ "index",
1471
+ "model",
1472
+ "rel",
1473
+ "valueObject"
1474
+ ];
1475
+ function buildFieldPreset(helperPath, descriptor, args) {
1476
+ validateAuthoringHelperArguments(helperPath, descriptor.args, args);
1477
+ const preset = instantiateAuthoringFieldPreset(descriptor, args);
1478
+ const unsupported = [
1479
+ ...preset.default !== void 0 ? ["default"] : [],
1480
+ ...preset.id ? ["id"] : [],
1481
+ ...preset.unique ? ["unique"] : []
1482
+ ];
1483
+ if (unsupported.length > 0) throw contractError("CONTRACT.PACK_CONTRIBUTION_INVALID", `Field preset "${helperPath}" contributes ${unsupported.join(", ")}, which Mongo does not support. Mongo supports presets that set a codec and execution defaults only.`, { meta: {
1484
+ helperPath,
1485
+ reason: "preset-contribution-unsupported",
1486
+ contribution: unsupported
1487
+ } });
1488
+ return createFieldBuilder({
1489
+ type: {
1490
+ kind: "scalar",
1491
+ codecId: preset.descriptor.codecId,
1492
+ ...normalizeOptionalTypeParams(preset.descriptor.typeParams)
1493
+ },
1494
+ nullable: preset.nullable,
1495
+ many: false
1496
+ }, void 0, preset.executionDefaults, void 0, void 0, {
1497
+ preset: helperPath,
1498
+ executionDefaults: preset.executionDefaults
1499
+ });
1500
+ }
1501
+ function composeMongoFieldHelpers(fieldNamespace) {
1502
+ const presetHelpers = createFieldHelpersFromNamespace(fieldNamespace, ({ helperPath, descriptor }) => (...args) => buildFieldPreset(helperPath, descriptor, args));
1503
+ const collisions = Object.keys(presetHelpers).filter((name) => Object.hasOwn(field, name));
1504
+ if (collisions.length > 0) throw contractError("CONTRACT.PACK_CONTRIBUTION_INVALID", `Pack-contributed field preset(s) ${collisions.map((c) => `"${c}"`).join(", ")} collide with the built-in Mongo field helper(s) of the same name.`, { meta: {
1505
+ reason: "core-field-helper-collision",
1506
+ contribution: collisions
1507
+ } });
1508
+ return {
1509
+ ...field,
1510
+ ...presetHelpers
1511
+ };
1512
+ }
1513
+ function stackLookupsOf(components) {
1514
+ const codecLookup = extractCodecLookup(components);
1515
+ assertTypeAliasesValid(composePackAuthoringNamespace(components, "type"), {
1516
+ generatorFunctions: assembleGeneratorFunctions(components),
1517
+ paramsSchemaOf: (codecId) => codecLookup.descriptorFor(codecId)?.paramsSchema,
1518
+ fieldLength: () => void 0
1519
+ });
1520
+ const { support } = assembleDataTypeSupport(components, (codecId) => codecLookup.descriptorFor(codecId)?.dataType);
1521
+ return {
1522
+ codecLookup,
1523
+ dataTypes: support
1524
+ };
1525
+ }
1526
+ function composeMongoAuthoringHelpers(family, target, extensions, lookups) {
1527
+ const components = [
1528
+ family,
1529
+ target,
1530
+ ...Object.values(extensions ?? {})
1531
+ ];
1532
+ const entityNamespace = composePackAuthoringNamespace(components, "entityTypes");
1533
+ const fieldNamespace = composePackAuthoringNamespace(components, "field");
1534
+ assertNoCrossRegistryCollisions({}, fieldNamespace, entityNamespace);
1535
+ const collisions = Object.keys(entityNamespace).filter((name) => MONGO_RESERVED_HELPER_KEYS.includes(name));
1536
+ if (collisions.length > 0) throw contractError("CONTRACT.PACK_CONTRIBUTION_INVALID", `Pack-contributed entity type(s) ${collisions.map((c) => `"${c}"`).join(", ")} collide with the reserved built-in helper key(s) on the Mongo composed helpers surface. Reserved keys: ${MONGO_RESERVED_HELPER_KEYS.map((k) => `"${k}"`).join(", ")}.`, { meta: {
1537
+ reason: "reserved-helper-key-collision",
1538
+ contribution: collisions
1539
+ } });
1540
+ return blindCast({
1541
+ ...createEntityHelpersFromNamespace(entityNamespace, { ctx: {
1542
+ family: family.familyId,
1543
+ target: target.targetId,
1544
+ codecLookup: lookups.codecLookup,
1545
+ dataTypes: lookups.dataTypes
1546
+ } }),
1547
+ field: composeMongoFieldHelpers(fieldNamespace),
1548
+ gen: createGeneratorHelpers(components),
1549
+ index,
1550
+ model,
1551
+ rel,
1552
+ valueObject
1553
+ });
1554
+ }
1555
+ function createFieldBuilder(spec, enumHandle, executionDefaults, storedName, generatorCalls, presetContribution) {
1556
+ function many(options) {
1557
+ return createFieldBuilder({
1558
+ type: spec.type,
1559
+ nullable: spec.nullable,
1560
+ many: { elementNullable: options?.elementsNullable ?? false }
1561
+ }, enumHandle, executionDefaults, storedName, generatorCalls, presetContribution);
1562
+ }
1563
+ function withGeneratorCall(phase, call) {
1564
+ if (generatorCalls?.[phase] !== void 0 || executionDefaults?.[phase] !== void 0) throw contractError("CONTRACT.DEFAULT_INVALID", `.${phase}() is called on a field that already generates a value ${phase === "onCreate" ? "on create" : "on update"}. Set each phase once, and do not combine .${phase}() with a field preset, type alias or alias constant that sets it.`, { meta: {
1565
+ reason: "generator-phase-set-twice",
1566
+ phase
1567
+ } });
1568
+ return createFieldBuilder(spec, enumHandle, blindCast(executionDefaults), storedName, {
1569
+ ...generatorCalls,
1570
+ [phase]: call
1571
+ }, presetContribution);
1572
+ }
1573
+ return {
1574
+ __kind: "field",
1575
+ ...ifDefined("__executionDefaults", executionDefaults),
1576
+ ...ifDefined("__generatorCalls", generatorCalls),
1577
+ ...ifDefined("__presetContribution", presetContribution),
1578
+ onCreate: (call) => withGeneratorCall("onCreate", call),
1579
+ onUpdate: (call) => withGeneratorCall("onUpdate", call),
1580
+ __type: spec.type,
1581
+ __nullable: spec.nullable,
1582
+ __many: spec.many,
1583
+ __enumHandle: blindCast(enumHandle),
1584
+ __storedName: blindCast(storedName),
1585
+ optional: () => createFieldBuilder({
1586
+ type: spec.type,
1587
+ nullable: true,
1588
+ many: spec.many
1589
+ }, enumHandle, executionDefaults, storedName, generatorCalls, presetContribution),
1590
+ many: blindCast(many),
1591
+ mongo: ({ field }) => createFieldBuilder(spec, enumHandle, executionDefaults, field, generatorCalls, presetContribution)
1592
+ };
1593
+ }
1594
+ function normalizeOptionalTypeParams(typeParams) {
1595
+ if (!typeParams) return {};
1596
+ return { typeParams };
1597
+ }
1598
+ function createScalarFieldBuilder(codecId, options) {
1599
+ return createFieldBuilder({
1600
+ type: blindCast({
1601
+ kind: "scalar",
1602
+ codecId,
1603
+ ...normalizeOptionalTypeParams(options?.typeParams)
1604
+ }),
1605
+ nullable: false,
1606
+ many: false
1607
+ });
1608
+ }
1609
+ function vectorField(options) {
1610
+ return createScalarFieldBuilder("mongo/vector@1", options);
1611
+ }
1612
+ const field = {
1613
+ scalar: createScalarFieldBuilder,
1614
+ objectId() {
1615
+ return createScalarFieldBuilder("mongo/objectId@1");
1616
+ },
1617
+ string() {
1618
+ return createScalarFieldBuilder("mongo/string@1");
1619
+ },
1620
+ double() {
1621
+ return createScalarFieldBuilder("mongo/double@1");
1622
+ },
1623
+ int32() {
1624
+ return createScalarFieldBuilder("mongo/int32@1");
1625
+ },
1626
+ bool() {
1627
+ return createScalarFieldBuilder("mongo/bool@1");
1628
+ },
1629
+ date() {
1630
+ return createScalarFieldBuilder("mongo/date@1");
1631
+ },
1632
+ int64() {
1633
+ return createScalarFieldBuilder("mongo/int64@1");
1634
+ },
1635
+ int64Number() {
1636
+ return createScalarFieldBuilder("mongo/int64Number@1");
1637
+ },
1638
+ decimal128() {
1639
+ return createScalarFieldBuilder("mongo/decimal128@1");
1640
+ },
1641
+ binary() {
1642
+ return createScalarFieldBuilder("mongo/binary@1");
1643
+ },
1644
+ json() {
1645
+ return createScalarFieldBuilder("mongo/json@1");
1646
+ },
1647
+ bson() {
1648
+ return createScalarFieldBuilder("mongo/bson@1");
1649
+ },
1650
+ vector: vectorField,
1651
+ valueObject(valueObjectName) {
1652
+ return createFieldBuilder({
1653
+ type: blindCast({
1654
+ kind: "valueObject",
1655
+ name: resolveValueObjectName(valueObjectName)
1656
+ }),
1657
+ nullable: false,
1658
+ many: false
1659
+ });
1660
+ },
1661
+ namedType(handle) {
1662
+ return createFieldBuilder({
1663
+ type: blindCast({
1664
+ kind: "scalar",
1665
+ codecId: handle.codecId
1666
+ }),
1667
+ nullable: false,
1668
+ many: false
1669
+ }, handle);
1670
+ }
1671
+ };
1672
+ function index(fields, options) {
1673
+ return {
1674
+ fields,
1675
+ ...options ? { options } : {}
1676
+ };
1677
+ }
1678
+ function createFieldReference(modelName, fieldName) {
1679
+ return {
1680
+ __kind: "fieldRef",
1681
+ modelName,
1682
+ fieldName
1683
+ };
1684
+ }
1685
+ function isFieldReference(value) {
1686
+ return typeof value === "object" && value !== null && "__kind" in value && value.__kind === "fieldRef";
1687
+ }
1688
+ function resolveValueObjectName(value) {
1689
+ return typeof value === "string" ? value : value.__name;
1690
+ }
1691
+ function normalizeStringList(value) {
1692
+ return typeof value === "string" ? [value] : [...value];
1693
+ }
1694
+ function normalizeTargetField(targetModelName, value) {
1695
+ if (!isFieldReference(value)) return value;
1696
+ if (value.modelName !== targetModelName) throw contractError("CONTRACT.RELATION_INVALID", `Relation target "${targetModelName}" cannot reference field "${value.modelName}.${value.fieldName}".`, { meta: {
1697
+ modelName: targetModelName,
1698
+ reason: "cross-model-field-reference",
1699
+ referencedModel: value.modelName,
1700
+ referencedField: value.fieldName
1701
+ } });
1702
+ return value.fieldName;
1703
+ }
1704
+ function normalizeTargetFields(targetModelName, value) {
1705
+ if (typeof value === "string") return [value];
1706
+ if (isFieldReference(value)) return [normalizeTargetField(targetModelName, value)];
1707
+ return value.map((entry) => normalizeTargetField(targetModelName, entry));
1708
+ }
1709
+ function createRelationBuilder(spec) {
1710
+ return {
1711
+ __kind: "relation",
1712
+ __to: spec.to,
1713
+ __cardinality: spec.cardinality,
1714
+ __on: spec.on,
1715
+ __nullable: spec.nullable
1716
+ };
1717
+ }
1718
+ function createReferenceRelationBuilder(target, cardinality, options, nullable) {
1719
+ const targetModelName = resolveModelName(target);
1720
+ return createRelationBuilder({
1721
+ to: blindCast(targetModelName),
1722
+ cardinality,
1723
+ on: {
1724
+ localFields: blindCast(normalizeStringList(options.from)),
1725
+ targetFields: blindCast(normalizeTargetFields(targetModelName, options.to))
1726
+ },
1727
+ nullable
1728
+ });
1729
+ }
1730
+ function createEmbedRelationBuilder(target, cardinality) {
1731
+ return createRelationBuilder({
1732
+ to: blindCast(resolveModelName(target)),
1733
+ cardinality,
1734
+ on: void 0,
1735
+ nullable: void 0
1736
+ });
1737
+ }
1738
+ function hasOne(target, options) {
1739
+ if (!options) return createEmbedRelationBuilder(target, "1:1");
1740
+ return createReferenceRelationBuilder(target, "1:1", options, true);
1741
+ }
1742
+ function hasMany(target, options) {
1743
+ if (!options) return createEmbedRelationBuilder(target, "1:N");
1744
+ return createReferenceRelationBuilder(target, "1:N", options, void 0);
1745
+ }
1746
+ function belongsTo(target, options) {
1747
+ return createReferenceRelationBuilder(target, "N:1", options, options.optional);
1748
+ }
1749
+ const rel = {
1750
+ belongsTo,
1751
+ hasMany,
1752
+ hasOne
1753
+ };
1754
+ function valueObject(name, input) {
1755
+ return {
1756
+ __kind: "valueObject",
1757
+ __name: name,
1758
+ __fields: input.fields
1759
+ };
1760
+ }
1761
+ function model(name, input) {
1762
+ return {
1763
+ __kind: "model",
1764
+ __name: name,
1765
+ __fields: input.fields,
1766
+ __relations: blindCast(input.relations ?? {}),
1767
+ __indexes: input.indexes,
1768
+ __collectionOptions: input.collectionOptions,
1769
+ __controlPolicy: input.controlPolicy,
1770
+ __collection: blindCast(input.collection),
1771
+ __owner: blindCast(input.owner ? resolveModelName(input.owner) : void 0),
1772
+ __base: blindCast(input.base ? resolveModelName(input.base) : void 0),
1773
+ __storageRelations: blindCast(input.storageRelations),
1774
+ __discriminator: blindCast(input.discriminator ? { field: input.discriminator.field } : void 0),
1775
+ __variants: blindCast(input.discriminator?.variants),
1776
+ ref(fieldName) {
1777
+ return createFieldReference(name, fieldName);
1778
+ }
1779
+ };
1780
+ }
1781
+ function isContractScaffold(value) {
1782
+ if (typeof value !== "object" || value === null) return false;
1783
+ return "family" in value && "target" in value;
1784
+ }
1785
+ function buildContractFromDsl(input, lookups) {
1786
+ const definition = buildContractDefinition(input);
1787
+ const { codecLookup, dataTypes } = lookups ?? stackLookupsOf([
1788
+ input.family,
1789
+ input.target,
1790
+ ...Object.values(input.extensions ?? {})
1791
+ ]);
1792
+ const built = buildMongoContractFromDefinition(definition, codecLookup, dataTypes);
1793
+ flushAuthoringWarnings((built.ok ? built.value.warnings : built.failure.warnings).map(authoringWarningOf));
1794
+ if (!built.ok) {
1795
+ const [first] = built.failure.refusals;
1796
+ assertDefined(first, "a refused build has at least one refusal");
1797
+ throw refusalError(first);
1798
+ }
1799
+ return blindCast(built.value.contract);
1800
+ }
1801
+ /** Implementation. */
1802
+ function buildBoundContract(family, target, definition, factory) {
1803
+ const full = {
1804
+ ...definition,
1805
+ family,
1806
+ target
1807
+ };
1808
+ if (factory !== void 0) {
1809
+ const lookups = stackLookupsOf([
1810
+ family,
1811
+ target,
1812
+ ...Object.values(definition.extensions ?? {})
1813
+ ]);
1814
+ const built = factory(composeMongoAuthoringHelpers(family, target, definition.extensions, lookups));
1815
+ return buildContractFromDsl({
1816
+ ...full,
1817
+ ...ifDefined("models", built.models),
1818
+ ...ifDefined("valueObjects", built.valueObjects),
1819
+ ...ifDefined("roots", built.roots)
1820
+ }, lookups);
1821
+ }
1822
+ return buildContractFromDsl(full);
1823
+ }
1824
+ function defineContract(definition, factory) {
1825
+ if (!isContractScaffold(definition)) throw contractError("CONTRACT.ARGUMENT_INVALID", "defineContract expects a contract definition object. Define your contract with defineContract({ family, target, models, ... }).");
1826
+ if (factory !== void 0) return buildBoundContract(definition.family, definition.target, definition, factory);
1827
+ return buildBoundContract(definition.family, definition.target, definition);
1828
+ }
1829
+ //#endregion
1830
+ export { enumType$1 as a, isEnumTypeHandle as c, rel as d, valueObject as f, defineContract as i, member as l, buildBoundContract as n, field as o, buildMongoContractFromDefinition as r, index as s, bindEnumType as t, model as u };
1831
+
1832
+ //# sourceMappingURL=contract-builder-d5cf-u9p.mjs.map