@prisma/orm-family-mongo 8.0.0-rc.12-dev.11 → 8.0.0-rc.12-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 (113) hide show
  1. package/dist/{authoring-entity-types-DkFfee0x-CRRHtwhi.mjs → authoring-entity-types-DkFfee0x-DzGu9hUw.mjs} +3 -3
  2. package/dist/{authoring-entity-types-DkFfee0x-CRRHtwhi.mjs.map → authoring-entity-types-DkFfee0x-DzGu9hUw.mjs.map} +1 -1
  3. package/dist/{canonicalization-hooks-BXCTdx8s.mjs → canonicalization-hooks-CRVM-Kqh-Qi-VmEVg.mjs} +2 -2
  4. package/dist/canonicalization-hooks-CRVM-Kqh-Qi-VmEVg.mjs.map +1 -0
  5. package/dist/{config-types-v_AdyJzO.mjs → config-types-x4rKdA0F.mjs} +4 -4
  6. package/dist/{config-types-v_AdyJzO.mjs.map → config-types-x4rKdA0F.mjs.map} +1 -1
  7. package/dist/{contract-builder-C0TMb001.mjs → contract-builder-0eayq5gp.mjs} +6 -6
  8. package/dist/{contract-builder-C0TMb001.mjs.map → contract-builder-0eayq5gp.mjs.map} +1 -1
  9. package/dist/{contract-builder-DVBFIIYp.d.mts → contract-builder-D0Fsm4m-.d.mts} +4 -4
  10. package/dist/{contract-builder-DVBFIIYp.d.mts.map → contract-builder-D0Fsm4m-.d.mts.map} +1 -1
  11. package/dist/contract-prisma6__provider.d.mts +35 -0
  12. package/dist/contract-prisma6__provider.d.mts.map +1 -0
  13. package/dist/contract-prisma6__provider.mjs +1020 -0
  14. package/dist/contract-prisma6__provider.mjs.map +1 -0
  15. package/dist/contract-psl.d.mts +43 -7
  16. package/dist/contract-psl.d.mts.map +1 -1
  17. package/dist/contract-psl.mjs +2 -2
  18. package/dist/contract-psl__provider.mjs +4 -4
  19. package/dist/contract-psl__provider.mjs.map +1 -1
  20. package/dist/contract-ts.d.mts +1 -1
  21. package/dist/contract-ts.mjs +2 -2
  22. package/dist/contract-ts__config-types.mjs +1 -1
  23. package/dist/contract-ts__contract-builder.d.mts +1 -1
  24. package/dist/contract-ts__contract-builder.mjs +1 -1
  25. package/dist/contract.d.mts +3 -3
  26. package/dist/contract.mjs +3 -3
  27. package/dist/contract__canonicalization-hooks.mjs +1 -1
  28. package/dist/contract__entity-kinds.d.mts +1 -1
  29. package/dist/contract__entity-kinds.mjs +1 -1
  30. package/dist/{control-BtmriDhU.mjs → control-BG0O1wDj.mjs} +12 -12
  31. package/dist/control-BG0O1wDj.mjs.map +1 -0
  32. package/dist/{control-9Vd-XWkM.d.mts → control-BXKlnxAS.d.mts} +3 -3
  33. package/dist/{control-9Vd-XWkM.d.mts.map → control-BXKlnxAS.d.mts.map} +1 -1
  34. package/dist/{control-adapter-Bh_ZraGM-7HXImyjy.d.mts → control-adapter-Bh_ZraGM-XeWQ672u.d.mts} +4 -4
  35. package/dist/{control-adapter-Bh_ZraGM-7HXImyjy.d.mts.map → control-adapter-Bh_ZraGM-XeWQ672u.d.mts.map} +1 -1
  36. package/dist/control-adapter-miP7lGv5.d.mts +1 -0
  37. package/dist/{control-C6gTadl8.d.mts → control-zKduRmAA.d.mts} +5 -5
  38. package/dist/{control-C6gTadl8.d.mts.map → control-zKduRmAA.d.mts.map} +1 -1
  39. package/dist/{dist-Dyp05u64.mjs → dist-C_TI9T_n.mjs} +2 -2
  40. package/dist/{dist-Dyp05u64.mjs.map → dist-C_TI9T_n.mjs.map} +1 -1
  41. package/dist/{dist-B4a9eijw.mjs → dist-DsIID5AE.mjs} +87 -41
  42. package/dist/dist-DsIID5AE.mjs.map +1 -0
  43. package/dist/{entity-kinds-FlR_bJNA-D4NYzPhs.mjs → entity-kinds-BFgLffz7-D8WUc2oo.mjs} +3 -3
  44. package/dist/{entity-kinds-FlR_bJNA-D4NYzPhs.mjs.map → entity-kinds-BFgLffz7-D8WUc2oo.mjs.map} +1 -1
  45. package/dist/family.d.mts +9 -9
  46. package/dist/family.mjs +8 -8
  47. package/dist/family__control-adapter.d.mts +2 -2
  48. package/dist/family__control.d.mts +1 -1
  49. package/dist/family__control.mjs +2 -2
  50. package/dist/family__ir.d.mts +2 -2
  51. package/dist/family__ir.mjs +3 -3
  52. package/dist/family__migration.d.mts +1 -1
  53. package/dist/family__migration.mjs +1 -1
  54. package/dist/family__pack.mjs +2 -2
  55. package/dist/family__runtime.d.mts +2 -2
  56. package/dist/family__runtime.mjs +1 -1
  57. package/dist/family__schema-verify.d.mts +1 -1
  58. package/dist/family__schema-verify.mjs +1 -1
  59. package/dist/{field-accessor-DHsAPiW3-iwRb2vC-.d.mts → field-accessor-DHsAPiW3-mw_sFEGx.d.mts} +3 -3
  60. package/dist/{field-accessor-DHsAPiW3-iwRb2vC-.d.mts.map → field-accessor-DHsAPiW3-mw_sFEGx.d.mts.map} +1 -1
  61. package/dist/{index-s1CL1J5A.d.mts → index-BpA_pfO1.d.mts} +4 -4
  62. package/dist/{index-s1CL1J5A.d.mts.map → index-BpA_pfO1.d.mts.map} +1 -1
  63. package/dist/{index-BfSjP_y5.d.mts → index-DJLkZc6k.d.mts} +3 -3
  64. package/dist/{index-BfSjP_y5.d.mts.map → index-DJLkZc6k.d.mts.map} +1 -1
  65. package/dist/{index-D-8mmTbj.d.mts → index-Db33rU3r.d.mts} +3 -3
  66. package/dist/{index-D-8mmTbj.d.mts.map → index-Db33rU3r.d.mts.map} +1 -1
  67. package/dist/{index-B-iG-2je.d.mts → index-XiYJVhuE.d.mts} +3 -3
  68. package/dist/{index-B-iG-2je.d.mts.map → index-XiYJVhuE.d.mts.map} +1 -1
  69. package/dist/{index-BUYcBNdw.d.mts → index-b-S3URri.d.mts} +50 -30
  70. package/dist/index-b-S3URri.d.mts.map +1 -0
  71. package/dist/{interpreter-D1CQbops-C_hzRtYe.mjs → interpreter-DPALasb4-BORWXsN5.mjs} +98 -103
  72. package/dist/interpreter-DPALasb4-BORWXsN5.mjs.map +1 -0
  73. package/dist/{ir-Dun4Br3Q.d.mts → ir-9VhpVaDJ.d.mts} +5 -5
  74. package/dist/{ir-Dun4Br3Q.d.mts.map → ir-9VhpVaDJ.d.mts.map} +1 -1
  75. package/dist/{ir-Ch2aPr7a.mjs → ir-vZWjElPY.mjs} +2 -2
  76. package/dist/{ir-Ch2aPr7a.mjs.map → ir-vZWjElPY.mjs.map} +1 -1
  77. package/dist/lowering.d.mts +1 -1
  78. package/dist/{migration-Cs9Lwv2y.d.mts → migration-9n6DCvlw.d.mts} +5 -5
  79. package/dist/{migration-Cs9Lwv2y.d.mts.map → migration-9n6DCvlw.d.mts.map} +1 -1
  80. package/dist/{migration-BsJgtw77.mjs → migration-DofqFxoZ.mjs} +2 -2
  81. package/dist/{migration-BsJgtw77.mjs.map → migration-DofqFxoZ.mjs.map} +1 -1
  82. package/dist/{mongo-contract-serializer-DC_DM9_Y-MJjsJZwM.mjs → mongo-contract-serializer-DC_DM9_Y-CDk1Veya.mjs} +6 -6
  83. package/dist/{mongo-contract-serializer-DC_DM9_Y-MJjsJZwM.mjs.map → mongo-contract-serializer-DC_DM9_Y-CDk1Veya.mjs.map} +1 -1
  84. package/dist/{mongo-contract-view-AnejqfrQ-nd-SP6W4.d.mts → mongo-contract-view-AnejqfrQ-DLhDjvsh.d.mts} +3 -3
  85. package/dist/{mongo-contract-view-AnejqfrQ-nd-SP6W4.d.mts.map → mongo-contract-view-AnejqfrQ-DLhDjvsh.d.mts.map} +1 -1
  86. package/dist/{mongo-contract-view-JZOa0Ry--BTfPzsVC.mjs → mongo-contract-view-JZOa0Ry--BL8lTjbw.mjs} +3 -3
  87. package/dist/{mongo-contract-view-JZOa0Ry--BTfPzsVC.mjs.map → mongo-contract-view-JZOa0Ry--BL8lTjbw.mjs.map} +1 -1
  88. package/dist/{mongo-value-set-tNn9-pun-dJYx_rVD.d.mts → mongo-value-set-BngSUlOh-BhDGXjM_.d.mts} +3 -3
  89. package/dist/{mongo-value-set-tNn9-pun-dJYx_rVD.d.mts.map → mongo-value-set-BngSUlOh-BhDGXjM_.d.mts.map} +1 -1
  90. package/dist/orm.d.mts +2 -2
  91. package/dist/orm.mjs +3 -3
  92. package/dist/query-ast.d.mts +2 -2
  93. package/dist/query-ast__control.d.mts +2 -2
  94. package/dist/query-builder.d.mts +3 -3
  95. package/dist/query-builder.mjs +1 -1
  96. package/dist/query-builder__contract-free.d.mts +3 -3
  97. package/dist/{runtime-BPRKmAdg.d.mts → runtime-F95l7p-U.d.mts} +3 -3
  98. package/dist/runtime-F95l7p-U.d.mts.map +1 -0
  99. package/dist/runtime.d.mts +1 -1
  100. package/dist/schema-ir.d.mts +1 -1
  101. package/dist/{schema-verify-BQA8oyKJ.d.mts → schema-verify-DehTbLkM.d.mts} +4 -4
  102. package/dist/{schema-verify-BQA8oyKJ.d.mts.map → schema-verify-DehTbLkM.d.mts.map} +1 -1
  103. package/dist/{verify-mongo-schema-B0bMHQW0-DSZhsvrk.mjs → verify-mongo-schema-B0bMHQW0-BuK0Jv5S.mjs} +3 -3
  104. package/dist/{verify-mongo-schema-B0bMHQW0-DSZhsvrk.mjs.map → verify-mongo-schema-B0bMHQW0-BuK0Jv5S.mjs.map} +1 -1
  105. package/dist/wire.d.mts +1 -1
  106. package/package.json +21 -19
  107. package/dist/canonicalization-hooks-BXCTdx8s.mjs.map +0 -1
  108. package/dist/control-BtmriDhU.mjs.map +0 -1
  109. package/dist/control-adapter-Bjc81f8y.d.mts +0 -1
  110. package/dist/dist-B4a9eijw.mjs.map +0 -1
  111. package/dist/index-BUYcBNdw.d.mts.map +0 -1
  112. package/dist/interpreter-D1CQbops-C_hzRtYe.mjs.map +0 -1
  113. package/dist/runtime-BPRKmAdg.d.mts.map +0 -1
@@ -0,0 +1,1020 @@
1
+ import { o as MongoIndex } from "./entity-kinds-BFgLffz7-D8WUc2oo.mjs";
2
+ import { c as buildMongoExecutionSection, h as validateMongoStorage, p as encodeMongoValueSets, u as buildMongoStorage } from "./dist-DsIID5AE.mjs";
3
+ import { a as pairMongoBackRelations } from "./interpreter-DPALasb4-BORWXsN5.mjs";
4
+ import { isStructuredError } from "@prisma/orm-framework/utils/structured-error";
5
+ import { UNBOUND_NAMESPACE_ID } from "@prisma/orm-framework/components/ir";
6
+ import { crossRef } from "@prisma/orm-framework/contract/types";
7
+ import { computeProfileHash } from "@prisma/orm-framework/contract/hashing";
8
+ import { blindCast } from "@prisma/orm-framework/utils/casts";
9
+ import { readFile, readdir, stat } from "node:fs/promises";
10
+ import { applySpecifierDefaultControlPolicy } from "@prisma/orm-framework/contract/apply-specifier-default-control-policy";
11
+ import { validateContractDomain } from "@prisma/orm-framework/contract/validate-domain";
12
+ import { ArrayLiteralAst, FunctionCallAst, IdentifierAst, StringLiteralExprAst, parse } from "@prisma/orm-framework/psl-parser/syntax";
13
+ import { InternalError } from "@prisma/orm-framework/utils/internal-error";
14
+ import { notOk, ok } from "@prisma/orm-framework/utils/result";
15
+ import { basename, dirname, extname, join, normalize } from "pathe";
16
+ import { resolveToOneRelationNullable } from "@prisma/orm-framework/contract-authoring";
17
+ import { instantiateAuthoringEntityType, isAuthoringEntityTypeDescriptor } from "@prisma/orm-framework/components/authoring";
18
+ import { buildSymbolTable, keywordPslSpan, mapPslDiagnostics, nodePslSpan, readResolvedAttribute, readResolvedAttributes } from "@prisma/orm-framework/psl-parser";
19
+ import { fkRelationPairKey } from "@prisma/orm-framework/psl-parser/interpret";
20
+ import { ifDefined } from "@prisma/orm-framework/utils/defined";
21
+ //#region ../../../2-mongo-family/2-authoring/contract-prisma6/dist/provider.mjs
22
+ function prisma6Diagnostic(code, message, sourceId, span) {
23
+ return {
24
+ code,
25
+ message,
26
+ sourceId,
27
+ ...span !== void 0 ? { span } : {}
28
+ };
29
+ }
30
+ function unsupported(attribute, what, span, ctx) {
31
+ ctx.diagnostics.push(prisma6Diagnostic("PSL.PRISMA6_MONGO_INDEX_ARGUMENT_UNSUPPORTED", `${ctx.owner}: ${ctx.prefix}${attribute.name} ${what}`, ctx.sourceId, span));
32
+ }
33
+ function sortDirection(expression) {
34
+ if (expression === void 0) return void 0;
35
+ const token = IdentifierAst.cast(expression.syntax)?.name();
36
+ return token === "Asc" ? 1 : token === "Desc" ? -1 : void 0;
37
+ }
38
+ /**
39
+ * Reads `sort:` from one index element's or `@unique`'s arguments. `length:` and every other argument are refused: a MongoDB index has no prefix length, and Prisma 6 accepts no other argument there on MongoDB.
40
+ */
41
+ function readSort(attribute, args, ctx) {
42
+ let direction;
43
+ for (const arg of args) {
44
+ const key = arg.name()?.name();
45
+ const span = nodePslSpan(arg.syntax, ctx.sources);
46
+ if (key !== "sort") return unsupported(attribute, key === "length" ? "argument \"length\" is not supported: a MongoDB index has no prefix length. Remove it; Prisma 6 ignores it on MongoDB." : `argument "${key ?? ""}" is not supported.`, span, ctx);
47
+ direction = sortDirection(arg.value());
48
+ if (direction === void 0) return unsupported(attribute, "sort must be Asc or Desc.", span, ctx);
49
+ }
50
+ return { direction };
51
+ }
52
+ function readFields(attribute, expression, span, ctx) {
53
+ const array = expression === void 0 ? void 0 : ArrayLiteralAst.cast(expression.syntax);
54
+ if (array === void 0) return unsupported(attribute, "expects a list of field names.", span, ctx);
55
+ const fields = [];
56
+ for (const element of array.elements()) {
57
+ const name = IdentifierAst.cast(element.syntax)?.name();
58
+ if (name !== void 0) {
59
+ fields.push({
60
+ name,
61
+ direction: void 0
62
+ });
63
+ continue;
64
+ }
65
+ const call = FunctionCallAst.cast(element.syntax);
66
+ const path = call?.path() ?? [];
67
+ const [callee] = path;
68
+ if (path.length > 1) {
69
+ ctx.diagnostics.push(prisma6Diagnostic("PSL.PRISMA6_MONGO_COMPOSITE_INDEX_PATH_UNSUPPORTED", `Index path "${path.join(".")}" reaches into a composite type; indexes on composite-type fields are not supported yet. Index a top-level field or remove the index.`, ctx.sourceId, nodePslSpan(element.syntax, ctx.sources)));
70
+ return;
71
+ }
72
+ if (call === void 0 || callee === void 0) return unsupported(attribute, "expects a list of field names.", nodePslSpan(element.syntax, ctx.sources), ctx);
73
+ const sort = readSort(attribute, call.args(), ctx);
74
+ if (sort === void 0) return void 0;
75
+ fields.push({
76
+ name: callee,
77
+ direction: sort.direction
78
+ });
79
+ }
80
+ return fields;
81
+ }
82
+ /** Reads `@@index`, `@@unique` or `@@fulltext`. `map:` and `name:` are dropped: MongoDB verify never compares index names. */
83
+ function parseIndexAttribute(attribute, ctx) {
84
+ let fields;
85
+ for (const arg of attribute.args) {
86
+ const key = arg.kind === "positional" ? "fields" : arg.name;
87
+ if (key === "map" || key === "name") continue;
88
+ if (key !== "fields") return unsupported(attribute, `argument "${key ?? ""}" is not supported.`, arg.span, ctx);
89
+ fields = readFields(attribute, arg.expression, arg.span, ctx);
90
+ if (fields === void 0) return void 0;
91
+ }
92
+ if (fields === void 0 || fields.length === 0) return unsupported(attribute, "expects a list of field names.", attribute.span, ctx);
93
+ return {
94
+ kind: attribute.name,
95
+ fields,
96
+ span: attribute.span
97
+ };
98
+ }
99
+ /** Reads a field's `@unique`: `sort:` sets the key direction; `map:` and `name:` are dropped. */
100
+ function parseFieldUnique(attribute, fieldName, ctx) {
101
+ let direction;
102
+ for (const arg of attribute.args) {
103
+ const key = arg.kind === "positional" ? void 0 : arg.name;
104
+ if (key === "map" || key === "name") continue;
105
+ if (key === "sort") {
106
+ direction = sortDirection(arg.expression);
107
+ if (direction === void 0) return unsupported(attribute, "sort must be Asc or Desc.", arg.span, ctx);
108
+ continue;
109
+ }
110
+ return unsupported(attribute, key === "length" ? "argument \"length\" is not supported: a MongoDB index has no prefix length. Remove it; Prisma 6 ignores it on MongoDB." : `argument "${key ?? ""}" is not supported.`, arg.span, ctx);
111
+ }
112
+ return {
113
+ kind: "unique",
114
+ fields: [{
115
+ name: fieldName,
116
+ direction
117
+ }],
118
+ span: attribute.span
119
+ };
120
+ }
121
+ const SUMMARY = "Prisma 6 MongoDB schema interpretation failed";
122
+ function stringArgument(attribute) {
123
+ const expression = (attribute.args.find((arg) => arg.kind === "positional") ?? attribute.args.find((arg) => arg.name === "name"))?.expression;
124
+ return expression === void 0 ? void 0 : StringLiteralExprAst.cast(expression.syntax)?.value();
125
+ }
126
+ function requireString(attribute, owner, sourceId, diagnostics) {
127
+ const value = stringArgument(attribute);
128
+ if (value === void 0) diagnostics.push({
129
+ code: "PSL_INVALID_ATTRIBUTE_ARGUMENT",
130
+ message: `${owner}: attribute "@${attribute.name}" expects one string argument.`,
131
+ sourceId,
132
+ span: attribute.span
133
+ });
134
+ return value;
135
+ }
136
+ function attributeText(attribute) {
137
+ const args = attribute.args.map((arg) => arg.kind === "named" ? `${arg.name}: ${arg.value}` : arg.value);
138
+ return args.length === 0 ? `@${attribute.name}` : `@${attribute.name}(${args.join(", ")})`;
139
+ }
140
+ /** `auto()` and `now()` with no arguments; any other `@default` value is `other`. */
141
+ function defaultKind(attribute) {
142
+ const expression = attribute.args.find((arg) => arg.kind === "positional")?.expression;
143
+ const call = expression === void 0 ? void 0 : FunctionCallAst.cast(expression.syntax);
144
+ if (call === void 0 || [...call.args()].length > 0) return "other";
145
+ const path = call.path().join(".");
146
+ return path === "auto" ? "auto" : path === "now" ? "now" : "other";
147
+ }
148
+ function unknownAttribute(owner, attribute, prefix, sourceId) {
149
+ return prisma6Diagnostic("PSL.PRISMA6_MONGO_UNKNOWN_ATTRIBUTE", `${owner}: attribute "${prefix}${attribute.name}" is not supported by the Prisma 6 MongoDB contract source.`, sourceId, attribute.span);
150
+ }
151
+ function interpretPrisma6Documents(input) {
152
+ const { binding } = input;
153
+ const diagnostics = [...input.seedDiagnostics];
154
+ const datasources = [];
155
+ const enumBlocks = [];
156
+ const compositeTypes = [];
157
+ const models = [];
158
+ const ignoredModels = /* @__PURE__ */ new Set();
159
+ const declaredNames = /* @__PURE__ */ new Map();
160
+ const claimName = (kind, name, sourceId, span) => {
161
+ const previous = declaredNames.get(name);
162
+ if (previous === void 0) {
163
+ declaredNames.set(name, sourceId);
164
+ return true;
165
+ }
166
+ diagnostics.push({
167
+ code: "PSL_DUPLICATE_DECLARATION",
168
+ message: `Duplicate declaration of ${kind} "${name}"; first declared in ${basename(previous)}.`,
169
+ sourceId,
170
+ span
171
+ });
172
+ return false;
173
+ };
174
+ for (const { document, sources, sourceFile, sourceId } of input.documents) {
175
+ const { symbolTable, diagnostics: tableDiagnostics } = buildSymbolTable({
176
+ documents: [document],
177
+ sources,
178
+ pslBlockDescriptors: {}
179
+ });
180
+ for (const diagnostic of tableDiagnostics) diagnostics.push({
181
+ code: diagnostic.code,
182
+ message: diagnostic.message,
183
+ sourceId,
184
+ span: sourceFile.rangeToPslSpan(diagnostic.range)
185
+ });
186
+ const unsupported = (keyword, span) => {
187
+ diagnostics.push({
188
+ code: "PSL_UNSUPPORTED_TOP_LEVEL_BLOCK",
189
+ message: `Unsupported top-level block "${keyword}"`,
190
+ sourceId,
191
+ span
192
+ });
193
+ };
194
+ for (const block of Object.values(symbolTable.topLevel.blocks)) switch (block.keyword) {
195
+ case "datasource":
196
+ datasources.push({
197
+ symbol: block,
198
+ sourceId,
199
+ sources
200
+ });
201
+ break;
202
+ case "generator": break;
203
+ case "enum":
204
+ if (claimName("enum", block.name, sourceId, block.span)) enumBlocks.push({
205
+ symbol: block,
206
+ sourceId,
207
+ sources
208
+ });
209
+ break;
210
+ case "view":
211
+ diagnostics.push(prisma6Diagnostic("PSL.PRISMA6_MONGO_VIEW_UNSUPPORTED", `View "${block.name}" is not supported; Prisma 8 has no views on MongoDB. Remove the view from the schema this contract source reads.`, sourceId, keywordPslSpan(block.node.syntax, block.keyword, sources)));
212
+ break;
213
+ default: unsupported(block.keyword, keywordPslSpan(block.node.syntax, block.keyword, sources));
214
+ }
215
+ for (const namespace of Object.values(symbolTable.topLevel.namespaces)) for (const { span } of namespace.declarations) unsupported("namespace", span);
216
+ for (const namedType of Object.values(symbolTable.topLevel.namedTypes)) unsupported("types", namedType.span);
217
+ for (const symbol of Object.values(symbolTable.topLevel.compositeTypes)) if (claimName("type", symbol.name, sourceId, symbol.span)) compositeTypes.push({
218
+ symbol,
219
+ sourceId,
220
+ sources
221
+ });
222
+ for (const symbol of Object.values(symbolTable.topLevel.models)) {
223
+ if (!claimName("model", symbol.name, sourceId, symbol.span)) continue;
224
+ if (symbol.attributes.some((attribute) => attribute.name === "ignore")) ignoredModels.add(symbol.name);
225
+ else models.push({
226
+ symbol,
227
+ sourceId,
228
+ sources
229
+ });
230
+ }
231
+ }
232
+ checkDatasource(datasources, input.documents[0]?.sourceId ?? "schema.prisma", binding, diagnostics);
233
+ const enums = /* @__PURE__ */ new Map();
234
+ for (const located of enumBlocks) {
235
+ const built = buildEnum(located, input, diagnostics);
236
+ if (built !== void 0) enums.set(located.symbol.name, built);
237
+ }
238
+ const modelNames = /* @__PURE__ */ new Set([...models.map((m) => m.symbol.name), ...ignoredModels]);
239
+ const typeContext = {
240
+ binding,
241
+ enums,
242
+ compositeTypeNames: new Set(compositeTypes.map((c) => c.symbol.name)),
243
+ diagnostics
244
+ };
245
+ const valueObjects = {};
246
+ for (const located of compositeTypes) valueObjects[located.symbol.name] = { fields: readCompositeFields(located, typeContext) };
247
+ const builds = /* @__PURE__ */ new Map();
248
+ for (const located of models) builds.set(located.symbol.name, readModel(located, modelNames, ignoredModels, typeContext));
249
+ const foreignKeys = [];
250
+ const invalidFkPairings = [];
251
+ const backRelations = [];
252
+ for (const build of builds.values()) readRelationFields(build, builds, {
253
+ foreignKeys,
254
+ invalidFkPairings,
255
+ backRelations
256
+ }, diagnostics);
257
+ const paired = pairMongoBackRelations({
258
+ foreignKeys,
259
+ candidates: backRelations,
260
+ invalidFkPairings
261
+ });
262
+ diagnostics.push(...mapPslDiagnostics(paired.diagnostics, mergedSources(input.documents)));
263
+ for (const { modelName, fieldName, relation } of paired.relations) {
264
+ const build = builds.get(modelName);
265
+ if (build !== void 0) build.relations[fieldName] = relation;
266
+ }
267
+ const collections = {};
268
+ const roots = {};
269
+ const executionDefaults = [];
270
+ for (const [modelName, build] of builds) {
271
+ const indexes = buildIndexes(build, diagnostics);
272
+ const existing = collections[build.collection];
273
+ collections[build.collection] = { indexes: [...existing?.indexes ?? [], ...indexes] };
274
+ roots[build.collection] = crossRef(modelName, UNBOUND_NAMESPACE_ID);
275
+ for (const { field, phases } of build.executionDefaults) executionDefaults.push({
276
+ ref: {
277
+ namespace: UNBOUND_NAMESPACE_ID,
278
+ entry: build.collection,
279
+ field
280
+ },
281
+ ...phases
282
+ });
283
+ if (!build.hasId) diagnostics.push({
284
+ code: "PSL_MISSING_ID_FIELD",
285
+ message: `Model "${modelName}" has no field with @id attribute. Every model must have exactly one @id field.`,
286
+ sourceId: build.located.sourceId,
287
+ span: build.located.symbol.span
288
+ });
289
+ }
290
+ if (diagnostics.length > 0) return notOk({
291
+ summary: SUMMARY,
292
+ diagnostics
293
+ });
294
+ return ok(assembleContract({
295
+ binding,
296
+ builds,
297
+ collections,
298
+ roots,
299
+ valueObjects,
300
+ enums,
301
+ executionDefaults,
302
+ codecLookup: input.codecLookup
303
+ }));
304
+ }
305
+ function checkDatasource(datasources, fallbackSourceId, binding, diagnostics) {
306
+ const [datasource] = datasources;
307
+ const [namedProvider] = binding.providers;
308
+ if (datasource === void 0) {
309
+ diagnostics.push(prisma6Diagnostic("PSL.PRISMA6_MONGO_PROVIDER_MISMATCH", `No datasource block found; add \`datasource db { provider = "${namedProvider}" }\`.`, fallbackSourceId, void 0));
310
+ return;
311
+ }
312
+ const block = datasource.symbol.block;
313
+ const parameter = block.parameters["provider"];
314
+ let provider;
315
+ if (parameter?.kind === "value") try {
316
+ const parsed = JSON.parse(parameter.raw);
317
+ provider = typeof parsed === "string" ? parsed : void 0;
318
+ } catch {
319
+ provider = void 0;
320
+ }
321
+ if (provider === void 0 || !binding.providers.includes(provider)) diagnostics.push(prisma6Diagnostic("PSL.PRISMA6_MONGO_PROVIDER_MISMATCH", provider === void 0 ? `The datasource block declares no string \`provider\`; this contract source reads Prisma 6 schemas for provider "${namedProvider}".` : `The datasource provider is "${provider}"; this contract source reads Prisma 6 schemas for provider "${namedProvider}".`, datasource.sourceId, parameter === void 0 ? block.span : parameter.span));
322
+ }
323
+ function buildEnum(located, input, diagnostics) {
324
+ const { symbol: block, sourceId, sources } = located;
325
+ for (const attribute of readResolvedAttributes(block.node.attributes(), sources)) {
326
+ if (attribute.name === "map") continue;
327
+ if (attribute.name === "schema") {
328
+ diagnostics.push(schemaUnsupported(`Enum "${block.name}"`, attribute, sourceId));
329
+ continue;
330
+ }
331
+ diagnostics.push(unknownAttribute(`Enum "${block.name}"`, attribute, "@@", sourceId));
332
+ }
333
+ const parameters = {};
334
+ for (const entry of block.node.entries()) {
335
+ const name = entry.key()?.name();
336
+ if (name === void 0) continue;
337
+ let value = name;
338
+ for (const attributeNode of entry.attributes()) {
339
+ const attribute = readResolvedAttribute(attributeNode, sources);
340
+ if (attribute.name === "map") value = requireString(attribute, `Enum member "${block.name}.${name}"`, sourceId, diagnostics) ?? value;
341
+ else diagnostics.push(unknownAttribute(`Enum member "${block.name}.${name}"`, attribute, "@", sourceId));
342
+ }
343
+ parameters[name] = {
344
+ kind: "value",
345
+ raw: JSON.stringify(value),
346
+ span: nodePslSpan(entry.syntax, sources)
347
+ };
348
+ }
349
+ const descriptor = input.authoringContributions.entityTypes["enum"];
350
+ if (descriptor === void 0 || !isAuthoringEntityTypeDescriptor(descriptor)) {
351
+ diagnostics.push({
352
+ code: "PSL_ENUM_MISSING_FACTORY",
353
+ message: `enum "${block.name}" requires an "enum" entityType factory in the active authoring contributions`,
354
+ sourceId,
355
+ span: block.span
356
+ });
357
+ return;
358
+ }
359
+ const context = {
360
+ family: input.binding.target.familyId,
361
+ target: input.binding.target.targetId,
362
+ codecLookup: input.codecLookup,
363
+ sourceId,
364
+ enumInferenceCodecs: {
365
+ text: input.binding.scalarCodecIds.String,
366
+ int: input.binding.scalarCodecIds.Int
367
+ },
368
+ diagnostics: { push: (diagnostic) => {
369
+ diagnostics.push(blindCast(diagnostic));
370
+ } }
371
+ };
372
+ const handle = instantiateAuthoringEntityType("enum", descriptor, [{
373
+ kind: "enum",
374
+ keyword: "enum",
375
+ name: block.name,
376
+ parameters,
377
+ blockAttributes: [],
378
+ attributes: {},
379
+ span: block.span
380
+ }], context);
381
+ if (handle === void 0 || handle === null) return void 0;
382
+ return {
383
+ codecId: handle.codecId,
384
+ members: handle.enumMembers.map((member) => ({
385
+ name: member.name,
386
+ value: member.value
387
+ }))
388
+ };
389
+ }
390
+ function schemaUnsupported(owner, attribute, sourceId) {
391
+ return prisma6Diagnostic("PSL.PRISMA6_MONGO_SCHEMA_UNSUPPORTED", `${owner}: "@@schema" is not supported; a MongoDB contract has one database, bound by the connection string. Remove @@schema.`, sourceId, attribute.span);
392
+ }
393
+ function unsupportedTypeMessage(label, typeName, owner) {
394
+ const base = `${label} has type "${typeName}(...)", which has no Prisma 8 codec, so ${`${owner.kind} "${owner.name}"`} cannot use this contract source while it has the field. Prisma 6 rejects @ignore on an Unsupported field. Removing the field from the schema leaves its stored values in the documents, but the Prisma 6 client no longer reads or writes them.`;
395
+ if (owner.kind === "type") return base;
396
+ return `${base} Adding @@ignore to model "${owner.name}" keeps the model out of the contract, but the model disappears from the Prisma 6 client too, and every relation field in another model that points to it needs @ignore, which removes that field from the Prisma 6 client as well.`;
397
+ }
398
+ /** The field's contract type, or `undefined` after reporting why it has none. */
399
+ function resolveFieldType(field, owner, nativeType, sourceId, ctx) {
400
+ const { binding, diagnostics } = ctx;
401
+ const label = `Field "${owner.name}.${field.name}"`;
402
+ if (field.typeConstructor !== void 0) {
403
+ diagnostics.push(prisma6Diagnostic("PSL.PRISMA6_MONGO_UNSUPPORTED_TYPE", unsupportedTypeMessage(label, field.typeConstructor.path.join("."), owner), sourceId, field.typeConstructor.span));
404
+ return;
405
+ }
406
+ const nativeTypeUnsupported = (attribute) => {
407
+ diagnostics.push(prisma6Diagnostic("PSL.PRISMA6_MONGO_NATIVE_TYPE_UNSUPPORTED", attribute.name === "db.ObjectId" ? `${label}: @db.ObjectId is only supported on a String field, and this field is "${field.typeName}". Remove @db.ObjectId, or change the field type to String.` : `${label}: native type "@${attribute.name}" is not supported by the Prisma 6 MongoDB contract source; only @db.ObjectId is. Remove it: the stored BSON type then follows the field type.`, sourceId, attribute.span));
408
+ };
409
+ const many = field.list ? { many: true } : {};
410
+ if (ctx.compositeTypeNames.has(field.typeName)) {
411
+ if (nativeType !== void 0) return nativeTypeUnsupported(nativeType);
412
+ return {
413
+ type: {
414
+ kind: "valueObject",
415
+ name: field.typeName
416
+ },
417
+ nullable: field.optional,
418
+ ...many
419
+ };
420
+ }
421
+ const enumBuild = ctx.enums.get(field.typeName);
422
+ if (enumBuild !== void 0) {
423
+ if (nativeType !== void 0) return nativeTypeUnsupported(nativeType);
424
+ const valueSet = {
425
+ plane: "domain",
426
+ entityKind: "enum",
427
+ namespaceId: UNBOUND_NAMESPACE_ID,
428
+ entityName: field.typeName
429
+ };
430
+ return {
431
+ type: {
432
+ kind: "scalar",
433
+ codecId: enumBuild.codecId
434
+ },
435
+ nullable: field.optional,
436
+ valueSet,
437
+ ...many
438
+ };
439
+ }
440
+ const scalarCodecId = Object.hasOwn(binding.scalarCodecIds, field.typeName) ? binding.scalarCodecIds[field.typeName] : void 0;
441
+ if (scalarCodecId === void 0) {
442
+ diagnostics.push(prisma6Diagnostic("PSL.PRISMA6_MONGO_UNSUPPORTED_TYPE", `${label} has unknown type "${field.typeName}": it is not a scalar type, an enum, a composite type, or a model. Correct the type name.`, sourceId, field.span));
443
+ return;
444
+ }
445
+ let codecId = scalarCodecId;
446
+ if (nativeType !== void 0) {
447
+ if (nativeType.name !== "db.ObjectId" || field.typeName !== "String") return nativeTypeUnsupported(nativeType);
448
+ codecId = binding.objectIdCodecId;
449
+ }
450
+ return {
451
+ type: {
452
+ kind: "scalar",
453
+ codecId
454
+ },
455
+ nullable: field.optional,
456
+ ...many
457
+ };
458
+ }
459
+ function readCompositeFields(located, ctx) {
460
+ const { symbol, sourceId } = located;
461
+ for (const attribute of symbol.attributes) ctx.diagnostics.push(unknownAttribute(`Type "${symbol.name}"`, attribute, "@@", sourceId));
462
+ const fields = {};
463
+ for (const field of Object.values(symbol.fields)) {
464
+ if (field.malformedType) continue;
465
+ const label = `Field "${symbol.name}.${field.name}"`;
466
+ let nativeType;
467
+ let rejected = false;
468
+ for (const attribute of field.attributes) if (attribute.name.startsWith("db.")) nativeType = attribute;
469
+ else if (attribute.name === "map") {
470
+ ctx.diagnostics.push(prisma6Diagnostic("PSL.PRISMA6_MONGO_COMPOSITE_MAP_UNSUPPORTED", `${label}: @map on a field of a composite type is not supported yet. The stored field keeps the name "${stringArgument(attribute) ?? field.name}", so removing @map renames it in storage; keep the schema as it is until Prisma 8 supports it.`, sourceId, attribute.span));
471
+ rejected = true;
472
+ } else if (attribute.name === "default") {
473
+ ctx.diagnostics.push(defaultUnsupported(label, attribute, sourceId));
474
+ rejected = true;
475
+ } else {
476
+ ctx.diagnostics.push(unknownAttribute(label, attribute, "@", sourceId));
477
+ rejected = true;
478
+ }
479
+ if (rejected) continue;
480
+ const resolved = resolveFieldType(field, {
481
+ kind: "type",
482
+ name: symbol.name
483
+ }, nativeType, sourceId, ctx);
484
+ if (resolved !== void 0) fields[field.name] = resolved;
485
+ }
486
+ return fields;
487
+ }
488
+ function defaultUnsupported(label, attribute, sourceId) {
489
+ return prisma6Diagnostic("PSL.PRISMA6_MONGO_DEFAULT_UNSUPPORTED", `${label}: ${attributeText(attribute)} is not supported. MongoDB has no stored defaults, and Prisma 8 fills only \`now()\` on DateTime fields. Remove the default and set the value when you create documents.`, sourceId, attribute.span);
490
+ }
491
+ function readModel(located, modelNames, ignoredModels, ctx) {
492
+ const { symbol, sourceId, sources } = located;
493
+ const { diagnostics } = ctx;
494
+ const modelLabel = `Model "${symbol.name}"`;
495
+ let collection = symbol.name;
496
+ const build = {
497
+ located,
498
+ collection: symbol.name,
499
+ storedNames: /* @__PURE__ */ new Map(),
500
+ ignoredFields: /* @__PURE__ */ new Set(),
501
+ rejectedFields: /* @__PURE__ */ new Set(),
502
+ fields: {},
503
+ relations: {},
504
+ executionDefaults: [],
505
+ uniqueFields: [],
506
+ modelIndexes: [],
507
+ relationFields: [],
508
+ hasId: false
509
+ };
510
+ const indexContext = {
511
+ owner: modelLabel,
512
+ prefix: "@@",
513
+ sourceId,
514
+ sources,
515
+ diagnostics
516
+ };
517
+ for (const attribute of symbol.attributes) switch (attribute.name) {
518
+ case "map":
519
+ collection = requireString(attribute, modelLabel, sourceId, diagnostics) ?? collection;
520
+ break;
521
+ case "index":
522
+ case "unique":
523
+ case "fulltext": {
524
+ const parsed = parseIndexAttribute({
525
+ ...attribute,
526
+ name: attribute.name
527
+ }, indexContext);
528
+ if (parsed !== void 0) build.modelIndexes.push(parsed);
529
+ break;
530
+ }
531
+ case "id":
532
+ build.hasId = true;
533
+ diagnostics.push(prisma6Diagnostic("PSL.PRISMA6_MONGO_COMPOSITE_ID_UNSUPPORTED", `${modelLabel}: @@id is not supported; a MongoDB document is identified by its "_id" field. Declare the id as \`id String @id @default(auto()) @map("_id") @db.ObjectId\`.`, sourceId, attribute.span));
534
+ break;
535
+ case "schema":
536
+ diagnostics.push(schemaUnsupported(modelLabel, attribute, sourceId));
537
+ break;
538
+ case "ignore": break;
539
+ default: diagnostics.push(unknownAttribute(modelLabel, attribute, "@@", sourceId));
540
+ }
541
+ for (const field of Object.values(symbol.fields)) {
542
+ const reported = diagnostics.length;
543
+ readModelField(field, build, modelNames, ignoredModels, ctx);
544
+ if (diagnostics.length > reported) build.rejectedFields.add(field.name);
545
+ }
546
+ return {
547
+ ...build,
548
+ collection
549
+ };
550
+ }
551
+ function readModelField(field, build, modelNames, ignoredModels, ctx) {
552
+ const { symbol, sourceId, sources } = build.located;
553
+ const { diagnostics, binding } = ctx;
554
+ const label = `Field "${symbol.name}.${field.name}"`;
555
+ const isRelationField = modelNames.has(field.typeName) && field.typeConstructor === void 0;
556
+ if (field.attributes.some((attribute) => attribute.name === "ignore")) {
557
+ build.ignoredFields.add(field.name);
558
+ const unique = field.attributes.find((attribute) => attribute.name === "unique");
559
+ if (unique !== void 0) diagnostics.push(ignoredFieldReferenced(symbol.name, [field.name], `@unique on field "${symbol.name}.${field.name}"`, sourceId, unique.span));
560
+ return;
561
+ }
562
+ if (isRelationField) {
563
+ if (ignoredModels.has(field.typeName)) return;
564
+ let relation;
565
+ for (const attribute of field.attributes) if (attribute.name === "relation") relation = attribute;
566
+ else diagnostics.push(unknownAttribute(label, attribute, "@", sourceId));
567
+ build.relationFields.push({
568
+ field,
569
+ relation
570
+ });
571
+ return;
572
+ }
573
+ let storedName = field.name;
574
+ let nativeType;
575
+ let idAttribute;
576
+ let defaultAttribute;
577
+ let updatedAt;
578
+ for (const attribute of field.attributes) switch (attribute.name) {
579
+ case "map":
580
+ storedName = requireString(attribute, label, sourceId, diagnostics) ?? storedName;
581
+ break;
582
+ case "id":
583
+ idAttribute = attribute;
584
+ break;
585
+ case "default":
586
+ defaultAttribute = attribute;
587
+ break;
588
+ case "updatedAt":
589
+ updatedAt = attribute;
590
+ break;
591
+ case "unique": {
592
+ const parsed = parseFieldUnique(attribute, field.name, {
593
+ owner: label,
594
+ prefix: "@",
595
+ sourceId,
596
+ sources,
597
+ diagnostics
598
+ });
599
+ if (parsed !== void 0) build.uniqueFields.push(parsed);
600
+ break;
601
+ }
602
+ default: if (attribute.name.startsWith("db.")) nativeType = attribute;
603
+ else diagnostics.push(unknownAttribute(label, attribute, "@", sourceId));
604
+ }
605
+ build.storedNames.set(field.name, storedName);
606
+ if (field.malformedType) return;
607
+ const resolved = resolveFieldType(field, {
608
+ kind: "model",
609
+ name: symbol.name
610
+ }, nativeType, sourceId, ctx);
611
+ if (resolved === void 0) return;
612
+ const codecId = resolved.type.kind === "scalar" ? resolved.type.codecId : void 0;
613
+ if (idAttribute !== void 0) {
614
+ build.hasId = true;
615
+ if (codecId !== binding.objectIdCodecId || storedName !== "_id" || field.optional || field.list) {
616
+ diagnostics.push(prisma6Diagnostic("PSL.PRISMA6_MONGO_ID_NOT_OBJECTID", `${label} is the model's @id, but it is not a required ObjectId stored as "_id". Prisma 8 identifies a MongoDB document by an ObjectId "_id"; declare the id as \`${field.name} String @id @default(auto()) @map("_id") @db.ObjectId\`.`, sourceId, idAttribute.span));
617
+ return;
618
+ }
619
+ if (defaultAttribute !== void 0 && defaultKind(defaultAttribute) !== "auto") {
620
+ diagnostics.push(defaultUnsupported(label, defaultAttribute, sourceId));
621
+ return;
622
+ }
623
+ build.fields[storedName] = resolved;
624
+ return;
625
+ }
626
+ const isDateTime = codecId === binding.scalarCodecIds.DateTime && !field.list;
627
+ if (updatedAt !== void 0 && !isDateTime) {
628
+ diagnostics.push(prisma6Diagnostic("PSL.PRISMA6_MONGO_UPDATED_AT_TYPE_UNSUPPORTED", `${label}: @updatedAt is only supported on a DateTime field. Remove @updatedAt and set the value when you write documents.`, sourceId, updatedAt.span));
629
+ return;
630
+ }
631
+ const defaultIsNow = defaultAttribute !== void 0 && defaultKind(defaultAttribute) === "now";
632
+ if (defaultAttribute !== void 0 && (!defaultIsNow || !isDateTime)) {
633
+ diagnostics.push(defaultUnsupported(label, defaultAttribute, sourceId));
634
+ return;
635
+ }
636
+ const generator = {
637
+ kind: "generator",
638
+ id: binding.timestampGeneratorId
639
+ };
640
+ const phases = updatedAt !== void 0 ? {
641
+ onCreate: generator,
642
+ onUpdate: generator
643
+ } : defaultIsNow ? { onCreate: generator } : void 0;
644
+ if (phases !== void 0 && field.optional) {
645
+ const written = updatedAt ?? defaultAttribute;
646
+ diagnostics.push(prisma6Diagnostic("PSL.PRISMA6_MONGO_OPTIONAL_GENERATED_FIELD_UNSUPPORTED", `${label} is optional and its value comes from ${written === void 0 ? "a generator" : attributeText(written)}, which Prisma 8 cannot express on an optional field yet. Make the field required, or remove ${written === void 0 ? "the generator" : attributeText(written)} and set the value when you write documents.`, sourceId, written?.span ?? field.span));
647
+ return;
648
+ }
649
+ build.fields[storedName] = resolved;
650
+ if (phases !== void 0) build.executionDefaults.push({
651
+ field: storedName,
652
+ phases
653
+ });
654
+ }
655
+ function identifierList(attributeArg) {
656
+ const expression = attributeArg.expression;
657
+ const array = expression === void 0 ? void 0 : ArrayLiteralAst.cast(expression.syntax);
658
+ if (array === void 0) return void 0;
659
+ const names = [];
660
+ for (const element of array.elements()) {
661
+ const name = IdentifierAst.cast(element.syntax)?.name();
662
+ if (name === void 0) return void 0;
663
+ names.push(name);
664
+ }
665
+ return names;
666
+ }
667
+ function readRelationArguments(attribute, label, sourceId, diagnostics) {
668
+ let name;
669
+ let fields;
670
+ let references;
671
+ const invalid = (what, span) => {
672
+ diagnostics.push({
673
+ code: "PSL_INVALID_ATTRIBUTE_ARGUMENT",
674
+ message: `${label}: @relation ${what}.`,
675
+ sourceId,
676
+ span
677
+ });
678
+ };
679
+ for (const arg of attribute.args) {
680
+ const key = arg.kind === "positional" ? "name" : arg.name;
681
+ switch (key) {
682
+ case "name": {
683
+ const expression = arg.expression;
684
+ name = expression === void 0 ? void 0 : StringLiteralExprAst.cast(expression.syntax)?.value();
685
+ if (name === void 0) return invalid("name must be a string", arg.span);
686
+ break;
687
+ }
688
+ case "fields":
689
+ fields = identifierList(arg);
690
+ if (fields === void 0) return invalid("fields must be a list of field names", arg.span);
691
+ break;
692
+ case "references":
693
+ references = identifierList(arg);
694
+ if (references === void 0) return invalid("references must be a list of field names", arg.span);
695
+ break;
696
+ case "onDelete":
697
+ case "onUpdate":
698
+ case "map":
699
+ diagnostics.push(prisma6Diagnostic("PSL.PRISMA6_MONGO_REFERENTIAL_ACTION_UNSUPPORTED", key === "map" ? `${label}: @relation argument "map" is not supported; it names a foreign key constraint, and MongoDB has none. Remove "map".` : `${label}: @relation argument "${key}" is not supported; Prisma 8 enforces no referential actions on MongoDB. Remove "${key}" and handle related documents in application code.`, sourceId, arg.span));
700
+ return;
701
+ default: return invalid(`argument "${key ?? ""}" is not supported`, arg.span);
702
+ }
703
+ }
704
+ return {
705
+ name,
706
+ fields,
707
+ references
708
+ };
709
+ }
710
+ function ignoredFieldReferenced(modelName, fieldNames, usedBy, sourceId, span) {
711
+ const one = fieldNames.length === 1;
712
+ const fields = fieldNames.map((name) => `"${modelName}.${name}"`).join(", ");
713
+ return prisma6Diagnostic("PSL.PRISMA6_MONGO_IGNORED_FIELD_REFERENCED", `${one ? "Field" : "Fields"} ${fields} ${one ? "is" : "are"} marked @ignore, but ${usedBy} uses ${one ? "it" : "them"}. Remove @ignore from ${fields}, or remove ${usedBy}.`, sourceId, span);
714
+ }
715
+ function readRelationFields(build, builds, out, diagnostics) {
716
+ const { symbol, sourceId, sources } = build.located;
717
+ for (const { field, relation } of build.relationFields) {
718
+ const label = `Relation field "${symbol.name}.${field.name}"`;
719
+ const reject = () => {
720
+ out.invalidFkPairings.push({
721
+ pairKey: fkRelationPairKey(symbol.name, field.typeName),
722
+ ...ifDefined("relationName", relation === void 0 ? void 0 : stringArgument(relation))
723
+ });
724
+ };
725
+ const args = relation === void 0 ? void 0 : readRelationArguments(relation, label, sourceId, diagnostics);
726
+ if (relation !== void 0 && args === void 0) {
727
+ reject();
728
+ continue;
729
+ }
730
+ const target = builds.get(field.typeName);
731
+ if (target === void 0) continue;
732
+ if (!(args?.fields !== void 0 || args?.references !== void 0)) {
733
+ out.backRelations.push({
734
+ modelName: symbol.name,
735
+ field,
736
+ targetModelName: field.typeName,
737
+ ...ifDefined("relationName", args?.name),
738
+ cardinality: field.list ? "1:N" : "1:1",
739
+ sources
740
+ });
741
+ continue;
742
+ }
743
+ if (field.list) {
744
+ diagnostics.push(prisma6Diagnostic("PSL.PRISMA6_MONGO_LIST_RELATION_UNSUPPORTED", `${label} is a list relation that stores its keys in a list field (a many-to-many relation on MongoDB), which Prisma 8 does not support yet. Remove the relation fields from the schema this contract source reads and keep the key list as a plain field.`, sourceId, relation?.span ?? field.span));
745
+ reject();
746
+ continue;
747
+ }
748
+ const localNames = args?.fields ?? [];
749
+ const targetNames = args?.references ?? [];
750
+ const ignoredLocal = localNames.filter((name) => build.ignoredFields.has(name));
751
+ if (ignoredLocal.length > 0) {
752
+ diagnostics.push(ignoredFieldReferenced(symbol.name, ignoredLocal, `relation field "${symbol.name}.${field.name}"`, sourceId, relation?.span ?? field.span));
753
+ reject();
754
+ continue;
755
+ }
756
+ const ignoredTarget = targetNames.filter((name) => target.ignoredFields.has(name));
757
+ if (ignoredTarget.length > 0) {
758
+ diagnostics.push(ignoredFieldReferenced(target.located.symbol.name, ignoredTarget, `relation field "${symbol.name}.${field.name}"`, sourceId, relation?.span ?? field.span));
759
+ reject();
760
+ continue;
761
+ }
762
+ const localFields = localNames.map((name) => build.storedNames.get(name));
763
+ const targetFields = targetNames.map((name) => target.storedNames.get(name));
764
+ if (localFields.some((name) => name === void 0) || targetFields.some((name) => name === void 0) || localNames.length !== targetNames.length || localNames.length === 0) {
765
+ diagnostics.push({
766
+ code: "PSL_INVALID_ATTRIBUTE_ARGUMENT",
767
+ message: `${label}: @relation fields and references must name the same number of scalar fields of "${symbol.name}" and "${field.typeName}".`,
768
+ sourceId,
769
+ span: relation?.span ?? field.span
770
+ });
771
+ reject();
772
+ continue;
773
+ }
774
+ if (resolveToOneRelationNullable({
775
+ declaredNullable: field.optional,
776
+ localFieldNullability: localNames.map((name) => symbol.fields[name]?.optional === true),
777
+ ownsReference: true
778
+ }).contradiction !== void 0) {
779
+ diagnostics.push({
780
+ code: "PSL_RELATION_NULLABILITY_MISMATCH",
781
+ message: field.optional ? `${label} is optional but every field in @relation(fields: [...]) is required. Make one of those fields optional with "?" or remove "?" from "${field.name}".` : `${label} is required but a field in @relation(fields: [...]) is optional. Add "?" to "${field.name}" or make those fields required.`,
782
+ sourceId,
783
+ span: field.span
784
+ });
785
+ reject();
786
+ continue;
787
+ }
788
+ const local = localFields.filter((name) => name !== void 0);
789
+ const referenced = targetFields.filter((name) => name !== void 0);
790
+ build.relations[field.name] = {
791
+ to: crossRef(field.typeName, UNBOUND_NAMESPACE_ID),
792
+ cardinality: "N:1",
793
+ nullable: field.optional,
794
+ on: {
795
+ localFields: local,
796
+ targetFields: referenced
797
+ }
798
+ };
799
+ out.foreignKeys.push({
800
+ declaringModel: symbol.name,
801
+ targetModel: field.typeName,
802
+ ...ifDefined("relationName", args?.name),
803
+ localFields: local,
804
+ targetFields: referenced
805
+ });
806
+ }
807
+ }
808
+ function buildIndexes(build, diagnostics) {
809
+ const { symbol, sourceId } = build.located;
810
+ const indexes = [];
811
+ let textIndexes = 0;
812
+ const keyFor = (field, text) => ({
813
+ field: build.storedNames.get(field.name) ?? field.name,
814
+ direction: field.direction ?? (text ? "text" : 1)
815
+ });
816
+ for (const attribute of [...build.uniqueFields, ...build.modelIndexes]) {
817
+ const names = attribute.fields.map((field) => field.name);
818
+ const usedBy = build.uniqueFields.includes(attribute) ? `@unique on field "${symbol.name}.${attribute.fields[0]?.name ?? ""}"` : `@@${attribute.kind} on model "${symbol.name}"`;
819
+ const ignored = names.filter((name) => build.ignoredFields.has(name));
820
+ if (ignored.length > 0) {
821
+ diagnostics.push(ignoredFieldReferenced(symbol.name, ignored, usedBy, sourceId, attribute.span));
822
+ continue;
823
+ }
824
+ if (names.some((name) => build.rejectedFields.has(name))) continue;
825
+ const unknown = names.find((name) => !build.storedNames.has(name));
826
+ if (unknown !== void 0) {
827
+ diagnostics.push({
828
+ code: "PSL_INDEX_FIELD_NOT_FOUND",
829
+ message: `Index on model "${symbol.name}" references unknown field "${unknown}"`,
830
+ sourceId,
831
+ span: attribute.span
832
+ });
833
+ continue;
834
+ }
835
+ if (attribute.kind === "fulltext") {
836
+ textIndexes++;
837
+ if (textIndexes > 1) {
838
+ diagnostics.push(prisma6Diagnostic("PSL.PRISMA6_MONGO_TEXT_INDEX_LIMIT", `Model "${symbol.name}" has more than one @@fulltext; MongoDB allows one text index per collection. Merge the fields into one @@fulltext.`, sourceId, attribute.span));
839
+ continue;
840
+ }
841
+ }
842
+ indexes.push(new MongoIndex({
843
+ keys: attribute.fields.map((field) => keyFor(field, attribute.kind === "fulltext")),
844
+ ...attribute.kind === "unique" ? { unique: true } : {}
845
+ }));
846
+ }
847
+ return indexes;
848
+ }
849
+ function assembleContract(input) {
850
+ const target = input.binding.target.targetId;
851
+ const targetFamily = input.binding.target.familyId;
852
+ const builtEnums = {};
853
+ for (const [enumName, built] of input.enums) builtEnums[enumName] = {
854
+ codecId: built.codecId,
855
+ members: built.members.map((member) => ({
856
+ name: member.name,
857
+ value: blindCast(member.value)
858
+ }))
859
+ };
860
+ const collections = {};
861
+ for (const [name, collection] of Object.entries(input.collections)) collections[name] = collection.indexes.length > 0 ? { indexes: collection.indexes } : {};
862
+ const storage = blindCast(buildMongoStorage({
863
+ collections,
864
+ valueSets: encodeMongoValueSets(Object.fromEntries(input.enums), input.codecLookup)
865
+ }));
866
+ const models = {};
867
+ for (const [modelName, build] of input.builds) models[modelName] = {
868
+ fields: build.fields,
869
+ relations: build.relations,
870
+ storage: { collection: build.collection }
871
+ };
872
+ const capabilities = {};
873
+ const execution = buildMongoExecutionSection(input.executionDefaults);
874
+ return {
875
+ targetFamily,
876
+ target,
877
+ roots: input.roots,
878
+ domain: { namespaces: { [UNBOUND_NAMESPACE_ID]: {
879
+ models: blindCast(models),
880
+ ...Object.keys(input.valueObjects).length > 0 ? { valueObjects: input.valueObjects } : {},
881
+ ...Object.keys(builtEnums).length > 0 ? { enum: builtEnums } : {}
882
+ } } },
883
+ storage,
884
+ extensions: {},
885
+ capabilities,
886
+ profileHash: computeProfileHash({
887
+ target,
888
+ targetFamily,
889
+ capabilities
890
+ }),
891
+ meta: {},
892
+ ...execution !== void 0 ? { execution } : {}
893
+ };
894
+ }
895
+ function mergedSources(documents) {
896
+ const [first, ...rest] = documents.map((document) => document.sources);
897
+ if (first === void 0) throw new InternalError("A Prisma 6 schema has at least one document");
898
+ return first.merge(...rest);
899
+ }
900
+ function defaultOutputFromSchemaPath(schemaPath) {
901
+ return join(dirname(schemaPath), "contract.json");
902
+ }
903
+ function mapParseDiagnostics(diagnostics, sourceFile, sourceId) {
904
+ return diagnostics.map((diagnostic) => ({
905
+ code: diagnostic.code,
906
+ message: diagnostic.message,
907
+ sourceId,
908
+ span: sourceFile.rangeToPslSpan(diagnostic.range)
909
+ }));
910
+ }
911
+ /**
912
+ * The files a Prisma 6 schema input names: the file itself, or every regular `.prisma` file under the directory, nested directories and symbolic links included, as Prisma 6 reads a schema directory. Sorted by path so duplicate detection blames the later file deterministically.
913
+ */
914
+ async function listSchemaFiles(absolutePath, displayPath) {
915
+ if (!(await stat(absolutePath)).isDirectory()) return [{
916
+ sourceId: displayPath,
917
+ absolutePath
918
+ }];
919
+ const entries = await readdir(absolutePath, { recursive: true });
920
+ const files = [];
921
+ for (const entry of entries.filter((name) => extname(name) === ".prisma").map((name) => normalize(name)).sort()) {
922
+ const entryPath = join(absolutePath, entry);
923
+ if ((await stat(entryPath)).isFile()) files.push({
924
+ sourceId: join(displayPath, entry),
925
+ absolutePath: entryPath
926
+ });
927
+ }
928
+ return files;
929
+ }
930
+ function readFailure(schemaPath, message, meta) {
931
+ return notOk({
932
+ summary: `Failed to read Prisma 6 schema at "${schemaPath}"`,
933
+ diagnostics: [prisma6Diagnostic("PSL.PRISMA6_MONGO_SCHEMA_READ_FAILED", message, schemaPath, void 0)],
934
+ meta
935
+ });
936
+ }
937
+ /**
938
+ * A `ContractConfig` that reads a Prisma 6 MongoDB `schema.prisma` (a file, or a directory of `.prisma` files) as the contract source.
939
+ */
940
+ function prisma6Contract(schemaPath, options) {
941
+ return {
942
+ source: {
943
+ format: "prisma6",
944
+ inputs: [schemaPath],
945
+ async load(context) {
946
+ const [absolutePath] = context.resolvedInputs;
947
+ if (absolutePath === void 0) throw new InternalError("prisma6Contract: context.resolvedInputs is empty. The CLI config loader should populate it from source.inputs.");
948
+ let files;
949
+ try {
950
+ files = await listSchemaFiles(absolutePath, schemaPath);
951
+ } catch (error) {
952
+ const message = String(error);
953
+ return readFailure(schemaPath, message, {
954
+ schemaPath,
955
+ absolutePath,
956
+ cause: message
957
+ });
958
+ }
959
+ if (files.length === 0) return readFailure(schemaPath, `The schema directory "${schemaPath}" contains no .prisma file.`, {
960
+ schemaPath,
961
+ absolutePath
962
+ });
963
+ const documents = [];
964
+ const seedDiagnostics = [];
965
+ for (const file of files) {
966
+ let schema;
967
+ try {
968
+ schema = await readFile(file.absolutePath, "utf-8");
969
+ } catch (error) {
970
+ const message = String(error);
971
+ return readFailure(file.sourceId, message, {
972
+ schemaPath: file.sourceId,
973
+ absoluteSchemaPath: file.absolutePath,
974
+ cause: message
975
+ });
976
+ }
977
+ const { document, sources, diagnostics } = parse(schema, file.sourceId, { grammar: "prisma7" });
978
+ const sourceFile = sources.sourceFileFor(document.syntax);
979
+ seedDiagnostics.push(...mapParseDiagnostics(diagnostics, sourceFile, file.sourceId));
980
+ documents.push({
981
+ document,
982
+ sources,
983
+ sourceFile,
984
+ sourceId: file.sourceId
985
+ });
986
+ }
987
+ let contract;
988
+ try {
989
+ const interpreted = interpretPrisma6Documents({
990
+ documents,
991
+ seedDiagnostics,
992
+ binding: options.binding,
993
+ authoringContributions: context.authoringContributions,
994
+ codecLookup: context.codecLookup
995
+ });
996
+ if (!interpreted.ok) return interpreted;
997
+ contract = applySpecifierDefaultControlPolicy(interpreted.value, options.defaultControlPolicy);
998
+ validateContractDomain(contract);
999
+ validateMongoStorage(blindCast(contract));
1000
+ } catch (error) {
1001
+ if (!isStructuredError(error)) throw error;
1002
+ return notOk({
1003
+ summary: "Prisma 6 MongoDB schema interpretation failed",
1004
+ diagnostics: [prisma6Diagnostic("PSL.PRISMA6_MONGO_CONTRACT_INVALID", `This schema gives a contract that Prisma 8 rejects, and the Prisma 6 MongoDB contract source has no specific diagnostic for the cause: ${error.message.replace(/\.$/, "")}. This is a bug in Prisma ORM; please report it with this schema.`, schemaPath, void 0)],
1005
+ meta: {
1006
+ schemaPath,
1007
+ code: error.code
1008
+ }
1009
+ });
1010
+ }
1011
+ return ok(contract);
1012
+ }
1013
+ },
1014
+ output: options.output ?? defaultOutputFromSchemaPath(schemaPath)
1015
+ };
1016
+ }
1017
+ //#endregion
1018
+ export { prisma6Contract };
1019
+
1020
+ //# sourceMappingURL=contract-prisma6__provider.mjs.map