@prisma/orm-family-sql 0.16.0-dev.36

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 (325) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +28 -0
  3. package/dist/ast-BstHjAoG.mjs +325 -0
  4. package/dist/ast-BstHjAoG.mjs.map +1 -0
  5. package/dist/ast-DSuzmsWn.d.mts +287 -0
  6. package/dist/ast-DSuzmsWn.d.mts.map +1 -0
  7. package/dist/authoring-type-constructors-Blqoa2Ua-DyCmD6mp.mjs +316 -0
  8. package/dist/authoring-type-constructors-Blqoa2Ua-DyCmD6mp.mjs.map +1 -0
  9. package/dist/build-contract-DBCz_YSs-DO0wMHai.mjs +778 -0
  10. package/dist/build-contract-DBCz_YSs-DO0wMHai.mjs.map +1 -0
  11. package/dist/builder.d.mts +3 -0
  12. package/dist/builder.mjs +1 -0
  13. package/dist/builder__runtime.d.mts +42 -0
  14. package/dist/builder__runtime.d.mts.map +1 -0
  15. package/dist/builder__runtime.mjs +955 -0
  16. package/dist/builder__runtime.mjs.map +1 -0
  17. package/dist/builder__types.d.mts +3 -0
  18. package/dist/builder__types.mjs +1 -0
  19. package/dist/canonicalization-hooks-CYnW_sGn.d.mts +10 -0
  20. package/dist/canonicalization-hooks-CYnW_sGn.d.mts.map +1 -0
  21. package/dist/canonicalization-hooks-DfIc_lOO.mjs +87 -0
  22. package/dist/canonicalization-hooks-DfIc_lOO.mjs.map +1 -0
  23. package/dist/codec-descriptor-registry-BJVJRftS.mjs +96 -0
  24. package/dist/codec-descriptor-registry-BJVJRftS.mjs.map +1 -0
  25. package/dist/codec-types-MOaceoPi-C5eL2sao.d.mts +116 -0
  26. package/dist/codec-types-MOaceoPi-C5eL2sao.d.mts.map +1 -0
  27. package/dist/config-types-47qB33rW.d.mts +21 -0
  28. package/dist/config-types-47qB33rW.d.mts.map +1 -0
  29. package/dist/config-types-N7PJc6VN.mjs +65 -0
  30. package/dist/config-types-N7PJc6VN.mjs.map +1 -0
  31. package/dist/contract-builder-MvJJrQ-5.d.mts +1306 -0
  32. package/dist/contract-builder-MvJJrQ-5.d.mts.map +1 -0
  33. package/dist/contract-builder-YjMQcvZ1.mjs +1615 -0
  34. package/dist/contract-builder-YjMQcvZ1.mjs.map +1 -0
  35. package/dist/contract-emitter.d.mts +25 -0
  36. package/dist/contract-emitter.d.mts.map +1 -0
  37. package/dist/contract-emitter.mjs +2 -0
  38. package/dist/contract-errors-BCN6RVI5-5IHBF_lg.mjs +9 -0
  39. package/dist/contract-errors-BCN6RVI5-5IHBF_lg.mjs.map +1 -0
  40. package/dist/contract-psl.d.mts +65 -0
  41. package/dist/contract-psl.d.mts.map +1 -0
  42. package/dist/contract-psl.mjs +2 -0
  43. package/dist/contract-psl__provider.d.mts +23 -0
  44. package/dist/contract-psl__provider.d.mts.map +1 -0
  45. package/dist/contract-psl__provider.mjs +105 -0
  46. package/dist/contract-psl__provider.mjs.map +1 -0
  47. package/dist/contract-ts.d.mts +3 -0
  48. package/dist/contract-ts.mjs +4 -0
  49. package/dist/contract-ts__config-types.d.mts +2 -0
  50. package/dist/contract-ts__config-types.mjs +2 -0
  51. package/dist/contract-ts__contract-builder.d.mts +2 -0
  52. package/dist/contract-ts__contract-builder.mjs +3 -0
  53. package/dist/contract-view-BMR5IWk4.mjs +39 -0
  54. package/dist/contract-view-BMR5IWk4.mjs.map +1 -0
  55. package/dist/contract-view-BbWQp6r4.d.mts +61 -0
  56. package/dist/contract-view-BbWQp6r4.d.mts.map +1 -0
  57. package/dist/contract.d.mts +26 -0
  58. package/dist/contract.mjs +17 -0
  59. package/dist/contract__canonicalization-hooks.d.mts +2 -0
  60. package/dist/contract__canonicalization-hooks.mjs +2 -0
  61. package/dist/contract__contract-view.d.mts +2 -0
  62. package/dist/contract__contract-view.mjs +2 -0
  63. package/dist/contract__entity-handle-lowering-hook.d.mts +2 -0
  64. package/dist/contract__entity-handle-lowering-hook.mjs +2 -0
  65. package/dist/contract__entity-kinds.d.mts +2 -0
  66. package/dist/contract__entity-kinds.mjs +2 -0
  67. package/dist/contract__factories.d.mts +2 -0
  68. package/dist/contract__factories.mjs +2 -0
  69. package/dist/contract__foreign-key-materialization.d.mts +2 -0
  70. package/dist/contract__foreign-key-materialization.mjs +2 -0
  71. package/dist/contract__index-naming.d.mts +2 -0
  72. package/dist/contract__index-naming.mjs +2 -0
  73. package/dist/contract__index-type-validation.d.mts +2 -0
  74. package/dist/contract__index-type-validation.mjs +2 -0
  75. package/dist/contract__index-types.d.mts +3 -0
  76. package/dist/contract__index-types.mjs +2 -0
  77. package/dist/contract__pack-types.d.mts +2 -0
  78. package/dist/contract__pack-types.mjs +1 -0
  79. package/dist/contract__referential-action-sql.d.mts +2 -0
  80. package/dist/contract__referential-action-sql.mjs +2 -0
  81. package/dist/contract__resolve-storage-table.d.mts +2 -0
  82. package/dist/contract__resolve-storage-table.mjs +2 -0
  83. package/dist/contract__types.d.mts +11 -0
  84. package/dist/contract__types.mjs +4 -0
  85. package/dist/contract__validators.d.mts +2 -0
  86. package/dist/contract__validators.mjs +3 -0
  87. package/dist/contract__value-set-derivation-hook.d.mts +2 -0
  88. package/dist/contract__value-set-derivation-hook.mjs +2 -0
  89. package/dist/control-B7iS4jv4.mjs +1326 -0
  90. package/dist/control-B7iS4jv4.mjs.map +1 -0
  91. package/dist/control-BHmsZudH.d.mts +948 -0
  92. package/dist/control-BHmsZudH.d.mts.map +1 -0
  93. package/dist/control-adapter-4y1O8Ps3.d.mts +1 -0
  94. package/dist/control-adapter-C99J7aEF-C-17lFY8.d.mts +191 -0
  95. package/dist/control-adapter-C99J7aEF-C-17lFY8.d.mts.map +1 -0
  96. package/dist/db-DhMsmBS--DKENDi3l.d.mts +365 -0
  97. package/dist/db-DhMsmBS--DKENDi3l.d.mts.map +1 -0
  98. package/dist/ddl-types-BMp2bWVS-D1waZJ4n.mjs +153 -0
  99. package/dist/ddl-types-BMp2bWVS-D1waZJ4n.mjs.map +1 -0
  100. package/dist/ddl-types-rrMsf77U-DGctYf-T.d.mts +149 -0
  101. package/dist/ddl-types-rrMsf77U-DGctYf-T.d.mts.map +1 -0
  102. package/dist/diff-B16bL_IR.mjs +13 -0
  103. package/dist/diff-B16bL_IR.mjs.map +1 -0
  104. package/dist/diff-DhlzHOMD.d.mts +104 -0
  105. package/dist/diff-DhlzHOMD.d.mts.map +1 -0
  106. package/dist/dist-C_q1_QR9.mjs +9 -0
  107. package/dist/dist-C_q1_QR9.mjs.map +1 -0
  108. package/dist/dist-DrScXbhq.mjs +414 -0
  109. package/dist/dist-DrScXbhq.mjs.map +1 -0
  110. package/dist/dist-x6jvtkKM.mjs +68 -0
  111. package/dist/dist-x6jvtkKM.mjs.map +1 -0
  112. package/dist/entity-handle-lowering-hook-CIvRKBfa.d.mts +92 -0
  113. package/dist/entity-handle-lowering-hook-CIvRKBfa.d.mts.map +1 -0
  114. package/dist/entity-handle-lowering-hook-DwLIKNiS.mjs +11 -0
  115. package/dist/entity-handle-lowering-hook-DwLIKNiS.mjs.map +1 -0
  116. package/dist/entity-kinds-DKxwKolf-CcsY-iYV.mjs +136 -0
  117. package/dist/entity-kinds-DKxwKolf-CcsY-iYV.mjs.map +1 -0
  118. package/dist/entity-kinds-Dh6VH4uK.d.mts +29 -0
  119. package/dist/entity-kinds-Dh6VH4uK.d.mts.map +1 -0
  120. package/dist/errors-B5g0xWro-mWH2C07F.mjs +9 -0
  121. package/dist/errors-B5g0xWro-mWH2C07F.mjs.map +1 -0
  122. package/dist/errors.d.mts +63 -0
  123. package/dist/errors.d.mts.map +1 -0
  124. package/dist/errors.mjs +2 -0
  125. package/dist/expression-DIf8F4Mc.d.mts +167 -0
  126. package/dist/expression-DIf8F4Mc.d.mts.map +1 -0
  127. package/dist/expression-RUO52bJB.mjs +109 -0
  128. package/dist/expression-RUO52bJB.mjs.map +1 -0
  129. package/dist/factories-B7tA4y9D.d.mts +39 -0
  130. package/dist/factories-B7tA4y9D.d.mts.map +1 -0
  131. package/dist/factories-CDG9zBxC.mjs +77 -0
  132. package/dist/factories-CDG9zBxC.mjs.map +1 -0
  133. package/dist/family.d.mts +13 -0
  134. package/dist/family.mjs +12 -0
  135. package/dist/family__control-adapter.d.mts +3 -0
  136. package/dist/family__control-adapter.mjs +1 -0
  137. package/dist/family__control.d.mts +4 -0
  138. package/dist/family__control.mjs +4 -0
  139. package/dist/family__diff.d.mts +3 -0
  140. package/dist/family__diff.mjs +3 -0
  141. package/dist/family__ir.d.mts +2 -0
  142. package/dist/family__ir.mjs +3 -0
  143. package/dist/family__migration.d.mts +2 -0
  144. package/dist/family__migration.mjs +2 -0
  145. package/dist/family__pack.d.mts +249 -0
  146. package/dist/family__pack.d.mts.map +1 -0
  147. package/dist/family__pack.mjs +18 -0
  148. package/dist/family__pack.mjs.map +1 -0
  149. package/dist/family__psl-infer.d.mts +2 -0
  150. package/dist/family__psl-infer.mjs +2 -0
  151. package/dist/family__runtime.d.mts +3 -0
  152. package/dist/family__runtime.mjs +3 -0
  153. package/dist/family__verify.d.mts +2 -0
  154. package/dist/family__verify.mjs +2 -0
  155. package/dist/foreign-key-BSy9u4O4-BnsOe5Nf.d.mts +85 -0
  156. package/dist/foreign-key-BSy9u4O4-BnsOe5Nf.d.mts.map +1 -0
  157. package/dist/foreign-key-materialization-Ca-wRbmj.d.mts +65 -0
  158. package/dist/foreign-key-materialization-Ca-wRbmj.d.mts.map +1 -0
  159. package/dist/foreign-key-materialization-HI7BIQrG.mjs +72 -0
  160. package/dist/foreign-key-materialization-HI7BIQrG.mjs.map +1 -0
  161. package/dist/index-Bb9U36N4.d.mts +511 -0
  162. package/dist/index-Bb9U36N4.d.mts.map +1 -0
  163. package/dist/index-BgaTJRxj.d.mts +25 -0
  164. package/dist/index-BgaTJRxj.d.mts.map +1 -0
  165. package/dist/index-naming-BZWoh45T.d.mts +62 -0
  166. package/dist/index-naming-BZWoh45T.d.mts.map +1 -0
  167. package/dist/index-naming-BoGBcMmI-DiJAr66H.mjs +108 -0
  168. package/dist/index-naming-BoGBcMmI-DiJAr66H.mjs.map +1 -0
  169. package/dist/index-type-validation-COH4d78M.mjs +17 -0
  170. package/dist/index-type-validation-COH4d78M.mjs.map +1 -0
  171. package/dist/index-type-validation-DN0L2mqm.d.mts +10 -0
  172. package/dist/index-type-validation-DN0L2mqm.d.mts.map +1 -0
  173. package/dist/index-types-CNhHgKHi.d.mts +1 -0
  174. package/dist/index-types-DJQ_xwaE.mjs +40 -0
  175. package/dist/index-types-DJQ_xwaE.mjs.map +1 -0
  176. package/dist/index-types-DPVhsW0v-D-BikM4h.d.mts +31 -0
  177. package/dist/index-types-DPVhsW0v-D-BikM4h.d.mts.map +1 -0
  178. package/dist/interpreter-5WgpL-ax-_nqHLUTr.mjs +3526 -0
  179. package/dist/interpreter-5WgpL-ax-_nqHLUTr.mjs.map +1 -0
  180. package/dist/ir-B3bKMnGQ.d.mts +123 -0
  181. package/dist/ir-B3bKMnGQ.d.mts.map +1 -0
  182. package/dist/ir-I-xciGUH.mjs +36 -0
  183. package/dist/ir-I-xciGUH.mjs.map +1 -0
  184. package/dist/lane-query-builder.d.mts +236 -0
  185. package/dist/lane-query-builder.d.mts.map +1 -0
  186. package/dist/lane-query-builder.mjs +67 -0
  187. package/dist/lane-query-builder.mjs.map +1 -0
  188. package/dist/middleware-B4XbF4d4-tfwBl6mX.d.mts +119 -0
  189. package/dist/middleware-B4XbF4d4-tfwBl6mX.d.mts.map +1 -0
  190. package/dist/middleware-ByRsXxxq.d.mts +1 -0
  191. package/dist/middleware-CMr4CHNz-DHIUdxlm.mjs +80 -0
  192. package/dist/middleware-CMr4CHNz-DHIUdxlm.mjs.map +1 -0
  193. package/dist/migration-CK4oePIo.mjs +44 -0
  194. package/dist/migration-CK4oePIo.mjs.map +1 -0
  195. package/dist/migration-CW0ZJLxP.d.mts +44 -0
  196. package/dist/migration-CW0ZJLxP.d.mts.map +1 -0
  197. package/dist/naming-BwqqVcZy-BgTObIQw.mjs +177 -0
  198. package/dist/naming-BwqqVcZy-BgTObIQw.mjs.map +1 -0
  199. package/dist/naming-jLgdauLi-C84G_UHi.d.mts +133 -0
  200. package/dist/naming-jLgdauLi-C84G_UHi.d.mts.map +1 -0
  201. package/dist/operations.d.mts +2 -0
  202. package/dist/operations.mjs +2 -0
  203. package/dist/orm-client.d.mts +1316 -0
  204. package/dist/orm-client.d.mts.map +1 -0
  205. package/dist/orm-client.mjs +4544 -0
  206. package/dist/orm-client.mjs.map +1 -0
  207. package/dist/pack-types-BcLTpwbv.d.mts +14 -0
  208. package/dist/pack-types-BcLTpwbv.d.mts.map +1 -0
  209. package/dist/plan-BTD8xFfa-Dd_K-A1R.d.mts +45 -0
  210. package/dist/plan-BTD8xFfa-Dd_K-A1R.d.mts.map +1 -0
  211. package/dist/plan-CkpcgUaM.mjs +34 -0
  212. package/dist/plan-CkpcgUaM.mjs.map +1 -0
  213. package/dist/plan-Cm4jaoNM.d.mts +2 -0
  214. package/dist/psl-infer-6je61Z6J.d.mts +119 -0
  215. package/dist/psl-infer-6je61Z6J.d.mts.map +1 -0
  216. package/dist/psl-infer-DGftl-HW.mjs +362 -0
  217. package/dist/psl-infer-DGftl-HW.mjs.map +1 -0
  218. package/dist/query-lane-context-Bz8XJZ45.d.mts +1 -0
  219. package/dist/query-lane-context-DtdVMqoz-C2Tj5QHA.d.mts +94 -0
  220. package/dist/query-lane-context-DtdVMqoz-C2Tj5QHA.d.mts.map +1 -0
  221. package/dist/referential-action-sql-Csd6dA8G.d.mts +12 -0
  222. package/dist/referential-action-sql-Csd6dA8G.d.mts.map +1 -0
  223. package/dist/referential-action-sql-DSqkrySN.mjs +17 -0
  224. package/dist/referential-action-sql-DSqkrySN.mjs.map +1 -0
  225. package/dist/relational-core.d.mts +13 -0
  226. package/dist/relational-core.mjs +8 -0
  227. package/dist/relational-core__ast.d.mts +5 -0
  228. package/dist/relational-core__ast.mjs +5 -0
  229. package/dist/relational-core__codec-descriptor-registry.d.mts +39 -0
  230. package/dist/relational-core__codec-descriptor-registry.d.mts.map +1 -0
  231. package/dist/relational-core__codec-descriptor-registry.mjs +2 -0
  232. package/dist/relational-core__contract-free.d.mts +220 -0
  233. package/dist/relational-core__contract-free.d.mts.map +1 -0
  234. package/dist/relational-core__contract-free.mjs +393 -0
  235. package/dist/relational-core__contract-free.mjs.map +1 -0
  236. package/dist/relational-core__expression.d.mts +2 -0
  237. package/dist/relational-core__expression.mjs +2 -0
  238. package/dist/relational-core__middleware.d.mts +3 -0
  239. package/dist/relational-core__middleware.mjs +2 -0
  240. package/dist/relational-core__plan.d.mts +4 -0
  241. package/dist/relational-core__plan.mjs +2 -0
  242. package/dist/relational-core__query-lane-context.d.mts +3 -0
  243. package/dist/relational-core__query-lane-context.mjs +1 -0
  244. package/dist/relational-core__types.d.mts +3 -0
  245. package/dist/relational-core__types.mjs +1 -0
  246. package/dist/resolve-storage-table-DUwyRJmP.d.mts +21 -0
  247. package/dist/resolve-storage-table-DUwyRJmP.d.mts.map +1 -0
  248. package/dist/resolve-storage-table-DZsfnzeW.mjs +46 -0
  249. package/dist/resolve-storage-table-DZsfnzeW.mjs.map +1 -0
  250. package/dist/runtime-DNewRuec.d.mts +46 -0
  251. package/dist/runtime-DNewRuec.d.mts.map +1 -0
  252. package/dist/runtime-tIHpGCcG.mjs +55 -0
  253. package/dist/runtime-tIHpGCcG.mjs.map +1 -0
  254. package/dist/runtime.d.mts +4 -0
  255. package/dist/runtime.mjs +1606 -0
  256. package/dist/runtime.mjs.map +1 -0
  257. package/dist/schema-differ-DpG_gnur-g5_iks8G.d.mts +47 -0
  258. package/dist/schema-differ-DpG_gnur-g5_iks8G.d.mts.map +1 -0
  259. package/dist/schema-ir.d.mts +2 -0
  260. package/dist/schema-ir.mjs +2 -0
  261. package/dist/schema-ir__naming.d.mts +2 -0
  262. package/dist/schema-ir__naming.mjs +2 -0
  263. package/dist/schema-ir__types.d.mts +3 -0
  264. package/dist/schema-ir__types.mjs +2 -0
  265. package/dist/schema-verify-vtFZbmGq-BNfTr6fU.mjs +222 -0
  266. package/dist/schema-verify-vtFZbmGq-BNfTr6fU.mjs.map +1 -0
  267. package/dist/serialized-index-B96AwqtU-DcqcB4q_.d.mts +26 -0
  268. package/dist/serialized-index-B96AwqtU-DcqcB4q_.d.mts.map +1 -0
  269. package/dist/serialized-index-Dp5_EjXD-DMsw8jf3.mjs +64 -0
  270. package/dist/serialized-index-Dp5_EjXD-DMsw8jf3.mjs.map +1 -0
  271. package/dist/sql-contract-serializer-2oBWuxTe-B9hzBBv1.mjs +171 -0
  272. package/dist/sql-contract-serializer-2oBWuxTe-B9hzBBv1.mjs.map +1 -0
  273. package/dist/sql-execution-plan-CJmsCP7n-DoEpNn7r.d.mts +32 -0
  274. package/dist/sql-execution-plan-CJmsCP7n-DoEpNn7r.d.mts.map +1 -0
  275. package/dist/sql-index-DsI8HAeK-BJsn-jvD.d.mts +72 -0
  276. package/dist/sql-index-DsI8HAeK-BJsn-jvD.d.mts.map +1 -0
  277. package/dist/sql-node-kEz6YFZo-v2F7delx.d.mts +42 -0
  278. package/dist/sql-node-kEz6YFZo-v2F7delx.d.mts.map +1 -0
  279. package/dist/sql-storage-B0QwiTg6-B8DVctJm.d.mts +171 -0
  280. package/dist/sql-storage-B0QwiTg6-B8DVctJm.d.mts.map +1 -0
  281. package/dist/storage-table-BBaAmanc-BwR37LMA.d.mts +130 -0
  282. package/dist/storage-table-BBaAmanc-BwR37LMA.d.mts.map +1 -0
  283. package/dist/storage-table-_LWDmPfv-DFhU2dML.mjs +277 -0
  284. package/dist/storage-table-_LWDmPfv-DFhU2dML.mjs.map +1 -0
  285. package/dist/storage-value-set-BGlj5Uus-CvZD--GG.d.mts +41 -0
  286. package/dist/storage-value-set-BGlj5Uus-CvZD--GG.d.mts.map +1 -0
  287. package/dist/timestamp-now-generator-DRXygu32-DN9Qb1uI.mjs +173 -0
  288. package/dist/timestamp-now-generator-DRXygu32-DN9Qb1uI.mjs.map +1 -0
  289. package/dist/types-BchwQpmO.d.mts +16 -0
  290. package/dist/types-BchwQpmO.d.mts.map +1 -0
  291. package/dist/types-BgkZru_1-H7yfikSQ.mjs +1444 -0
  292. package/dist/types-BgkZru_1-H7yfikSQ.mjs.map +1 -0
  293. package/dist/types-CMMQS6aG.mjs +111 -0
  294. package/dist/types-CMMQS6aG.mjs.map +1 -0
  295. package/dist/types-CuDrWc5v-ISVXBmBs.d.mts +134 -0
  296. package/dist/types-CuDrWc5v-ISVXBmBs.d.mts.map +1 -0
  297. package/dist/types-CvbBw1Jo-3KQdErJY.d.mts +688 -0
  298. package/dist/types-CvbBw1Jo-3KQdErJY.d.mts.map +1 -0
  299. package/dist/types-DIBA80mc-wf5wLmON.d.mts +723 -0
  300. package/dist/types-DIBA80mc-wf5wLmON.d.mts.map +1 -0
  301. package/dist/types-DMxc5KZa.d.mts +1 -0
  302. package/dist/types-Dl20lxky-DC_jdA0T.d.mts +247 -0
  303. package/dist/types-Dl20lxky-DC_jdA0T.d.mts.map +1 -0
  304. package/dist/types-DmhUVq4u-BpqqjPJx.mjs +719 -0
  305. package/dist/types-DmhUVq4u-BpqqjPJx.mjs.map +1 -0
  306. package/dist/types-IqZMLrFC-DtdJNICr.d.mts +426 -0
  307. package/dist/types-IqZMLrFC-DtdJNICr.d.mts.map +1 -0
  308. package/dist/types-TvBZ2Ne9.d.mts +1 -0
  309. package/dist/unique-constraint-jQWfH7dg-zLWtFp99.d.mts +32 -0
  310. package/dist/unique-constraint-jQWfH7dg-zLWtFp99.d.mts.map +1 -0
  311. package/dist/util-DQQgv2j1-D6INZaRG.mjs +34 -0
  312. package/dist/util-DQQgv2j1-D6INZaRG.mjs.map +1 -0
  313. package/dist/validators-C4PItWnf.mjs +0 -0
  314. package/dist/validators-C4PItWnf.mjs.map +1 -0
  315. package/dist/validators-CxeHhHrf.d.mts +206 -0
  316. package/dist/validators-CxeHhHrf.d.mts.map +1 -0
  317. package/dist/value-set-derivation-hook-BhgGVtw0.d.mts +35 -0
  318. package/dist/value-set-derivation-hook-BhgGVtw0.d.mts.map +1 -0
  319. package/dist/value-set-derivation-hook-Di9JZ0X7.mjs +22 -0
  320. package/dist/value-set-derivation-hook-Di9JZ0X7.mjs.map +1 -0
  321. package/dist/verify-E6Dd2vYp-gYwnlhLm.mjs +86 -0
  322. package/dist/verify-E6Dd2vYp-gYwnlhLm.mjs.map +1 -0
  323. package/dist/verify-zDRnw0Rn.d.mts +26 -0
  324. package/dist/verify-zDRnw0Rn.d.mts.map +1 -0
  325. package/package.json +112 -0
@@ -0,0 +1,4544 @@
1
+ import { t as resolveStorageTable } from "./resolve-storage-table-DZsfnzeW.mjs";
2
+ import { i as isUniqueConstraintViolation } from "./dist-x6jvtkKM.mjs";
3
+ import { C as LiteralExpr, D as OrExpr, F as SubqueryExpr, I as TableSource, L as UpdateAst, O as OrderByItem, P as SelectAst, R as WindowFuncExpr, S as ListExpression, T as NullCheckExpr, V as isWhereExpr, _ as InsertAst, b as JsonArrayAggExpr, c as DeleteAst, f as EqColJoinOn, j as ProjectionItem, k as ParamRef, l as DerivedTableSource, n as AndExpr, o as ColumnRef, p as ExistsExpr, r as BinaryExpr, s as DefaultValueExpr, t as AggregateExpr, v as InsertOnConflict, w as NotExpr, x as JsonObjectExpr, y as JoinAst } from "./types-BgkZru_1-H7yfikSQ.mjs";
4
+ import { t as collectOrderedParamRefs } from "./util-DQQgv2j1-D6INZaRG.mjs";
5
+ import { n as JsonDocumentProjection, r as NativeJsonValueProjection, t as CodecJsonValueProjection } from "./ast-BstHjAoG.mjs";
6
+ import { n as codecRefForStorageColumn } from "./codec-descriptor-registry-BJVJRftS.mjs";
7
+ import { structuredError } from "@prisma/orm-framework/utils/structured-error";
8
+ import { InternalError, assertNever } from "@prisma/orm-framework/utils/internal-error";
9
+ import { domainModelsAtDefaultNamespace } from "@prisma/orm-framework/contract/types";
10
+ import { blindCast, castAs } from "@prisma/orm-framework/utils/casts";
11
+ import { ifDefined } from "@prisma/orm-framework/utils/defined";
12
+ import { assertDefined, invariant } from "@prisma/orm-framework/utils/assertions";
13
+ import { AsyncIterableResult, createMetaBuilder, isRuntimeError, runtimeError } from "@prisma/orm-framework/components/runtime";
14
+ //#region ../../../3-extensions/sql-orm-client/dist/index.mjs
15
+ function ormError(code, message, options) {
16
+ return structuredError(code, message, options);
17
+ }
18
+ function resolveTableForContract(contract, namespaceId, tableName) {
19
+ return resolveStorageTable(contract.storage, tableName, namespaceId);
20
+ }
21
+ function requireStorageTableForContract(contract, namespaceId, tableName) {
22
+ const resolved = resolveTableForContract(contract, namespaceId, tableName);
23
+ if (resolved === void 0) throw ormError("ORM.TABLE_UNKNOWN", `Unknown table "${tableName}"`, { meta: {
24
+ namespaceId,
25
+ tableName
26
+ } });
27
+ return resolved;
28
+ }
29
+ function storageTableForContract(contract, namespaceId, tableName) {
30
+ return requireStorageTableForContract(contract, namespaceId, tableName).table;
31
+ }
32
+ function domainModelNamesInNamespace(contract, namespaceId) {
33
+ const namespace = contract.domain.namespaces[namespaceId];
34
+ return namespace ? Object.keys(namespace.models) : [];
35
+ }
36
+ function domainModelTableInNamespace(contract, namespaceId, modelName) {
37
+ const table = (contract.domain.namespaces[namespaceId]?.models[modelName])?.storage["table"];
38
+ return typeof table === "string" ? table : void 0;
39
+ }
40
+ function tableSourceForContract(contract, namespaceId, tableName, alias) {
41
+ const resolved = requireStorageTableForContract(contract, namespaceId, tableName);
42
+ const effectiveAlias = alias !== void 0 && alias !== tableName ? alias : void 0;
43
+ return TableSource.named(tableName, effectiveAlias, resolved.namespaceId);
44
+ }
45
+ const POLYMORPHIC_DISCRIMINATOR_ALIAS = "__prisma_polymorphic_discriminator";
46
+ function modelsOf(contract, namespaceId) {
47
+ const namespace = contract.domain.namespaces[namespaceId];
48
+ if (namespace === void 0) throw new InternalError(`domain namespace "${namespaceId}" is not present on the contract`);
49
+ return blindCast(namespace.models);
50
+ }
51
+ function metadataCacheKey(namespaceId, modelName) {
52
+ return `${namespaceId}\u0000${modelName}`;
53
+ }
54
+ function modelOf(contract, namespaceId, name) {
55
+ const model = contract.domain.namespaces[namespaceId]?.models[name];
56
+ return model === void 0 ? void 0 : blindCast(model);
57
+ }
58
+ const fieldToColumnCache = /* @__PURE__ */ new WeakMap();
59
+ const columnToFieldCache = /* @__PURE__ */ new WeakMap();
60
+ const polymorphismCache = /* @__PURE__ */ new WeakMap();
61
+ function resolvePolymorphismInfo(contract, namespaceId, modelName) {
62
+ let perContract = polymorphismCache.get(contract);
63
+ if (!perContract) {
64
+ perContract = /* @__PURE__ */ new Map();
65
+ polymorphismCache.set(contract, perContract);
66
+ }
67
+ const cacheKey = metadataCacheKey(namespaceId, modelName);
68
+ if (perContract.has(cacheKey)) return perContract.get(cacheKey);
69
+ const models = modelsOf(contract, namespaceId);
70
+ const model = models[modelName];
71
+ if (!model?.discriminator || !model.variants) {
72
+ perContract.set(cacheKey, void 0);
73
+ return;
74
+ }
75
+ const baseTable = model.storage?.table;
76
+ if (!baseTable) {
77
+ perContract.set(cacheKey, void 0);
78
+ return;
79
+ }
80
+ const discriminatorField = model.discriminator.field;
81
+ const discriminatorColumn = resolveFieldToColumn(contract, namespaceId, modelName, discriminatorField);
82
+ const variants = /* @__PURE__ */ new Map();
83
+ const variantsByValue = /* @__PURE__ */ new Map();
84
+ const mtiVariants = [];
85
+ for (const [variantModelName, variantEntry] of Object.entries(model.variants)) {
86
+ const variantModel = models[variantModelName];
87
+ if (!variantModel) throw new InternalError(`Model "${modelName}" declares variant "${variantModelName}", but that model is missing from the contract`);
88
+ const variantTable = variantModel.storage?.table ?? baseTable;
89
+ const strategy = variantTable === baseTable ? "sti" : "mti";
90
+ const info = {
91
+ modelName: variantModelName,
92
+ value: variantEntry.value,
93
+ table: variantTable,
94
+ strategy
95
+ };
96
+ variants.set(variantModelName, info);
97
+ variantsByValue.set(variantEntry.value, info);
98
+ if (strategy === "mti") mtiVariants.push(info);
99
+ }
100
+ const result = {
101
+ discriminatorField,
102
+ discriminatorColumn,
103
+ baseTable,
104
+ variants,
105
+ variantsByValue,
106
+ mtiVariants
107
+ };
108
+ perContract.set(cacheKey, result);
109
+ return result;
110
+ }
111
+ function resolveFieldToColumn(contract, namespaceId, modelName, fieldName) {
112
+ return getFieldToColumnMap(contract, namespaceId, modelName)[fieldName] ?? fieldName;
113
+ }
114
+ /**
115
+ * Map the fields that an MTI variant contributes to `{ table, column }` refs
116
+ * qualified against the variant's own table — the table the read path joins
117
+ * into the correlated child SELECT. STI variants contribute nothing here:
118
+ * their columns live on the base table and resolve through the ordinary
119
+ * base-table field map. Base fields are intentionally absent so callers can
120
+ * gate variant qualification strictly to variant-owned fields.
121
+ *
122
+ * `baseModelName` is a default-namespace model name, consistent with the rest
123
+ * of this module; namespace context is bound downstream at table resolution.
124
+ *
125
+ * Uncached on purpose: `resolvePolymorphismInfo` already memoizes the variant
126
+ * lookup, and the remaining work is one pass over the variant's field→column
127
+ * map, so a second cache layer would buy nothing.
128
+ */
129
+ function resolveVariantFieldColumns(contract, namespaceId, baseModelName, variantName) {
130
+ const variant = resolvePolymorphismInfo(contract, namespaceId, baseModelName)?.variants.get(variantName);
131
+ const result = {};
132
+ if (variant && variant.strategy === "mti") {
133
+ const variantFieldToColumn = getFieldToColumnMap(contract, namespaceId, variant.modelName);
134
+ for (const [field, column] of Object.entries(variantFieldToColumn)) result[field] = {
135
+ table: variant.table,
136
+ column
137
+ };
138
+ }
139
+ return result;
140
+ }
141
+ function getFieldToColumnMap(contract, namespaceId, modelName) {
142
+ let perContract = fieldToColumnCache.get(contract);
143
+ if (!perContract) {
144
+ perContract = /* @__PURE__ */ new Map();
145
+ fieldToColumnCache.set(contract, perContract);
146
+ }
147
+ const cacheKey = metadataCacheKey(namespaceId, modelName);
148
+ let cached = perContract.get(cacheKey);
149
+ if (cached) return cached;
150
+ const storageFields = modelsOf(contract, namespaceId)[modelName]?.storage?.fields ?? {};
151
+ cached = {};
152
+ for (const [f, s] of Object.entries(storageFields)) if (s?.column) cached[f] = s.column;
153
+ perContract.set(cacheKey, cached);
154
+ return cached;
155
+ }
156
+ function getColumnToFieldMap(contract, namespaceId, modelName) {
157
+ let perContract = columnToFieldCache.get(contract);
158
+ if (!perContract) {
159
+ perContract = /* @__PURE__ */ new Map();
160
+ columnToFieldCache.set(contract, perContract);
161
+ }
162
+ const cacheKey = metadataCacheKey(namespaceId, modelName);
163
+ let cached = perContract.get(cacheKey);
164
+ if (cached) return cached;
165
+ const storageFields = modelsOf(contract, namespaceId)[modelName]?.storage?.fields ?? {};
166
+ cached = {};
167
+ for (const [f, s] of Object.entries(storageFields)) if (s?.column) cached[s.column] = f;
168
+ perContract.set(cacheKey, cached);
169
+ return cached;
170
+ }
171
+ const completeColumnToFieldCache = /* @__PURE__ */ new WeakMap();
172
+ /**
173
+ * Like getColumnToFieldMap but includes identity-mapped fields (where field name equals column
174
+ * name). getColumnToFieldMap only returns explicit remaps; this returns ALL column→field entries.
175
+ */
176
+ function getCompleteColumnToFieldMap(contract, namespaceId, modelName) {
177
+ let perContract = completeColumnToFieldCache.get(contract);
178
+ if (!perContract) {
179
+ perContract = /* @__PURE__ */ new Map();
180
+ completeColumnToFieldCache.set(contract, perContract);
181
+ }
182
+ const cacheKey = metadataCacheKey(namespaceId, modelName);
183
+ let cached = perContract.get(cacheKey);
184
+ if (cached) return cached;
185
+ const storageFields = modelsOf(contract, namespaceId)[modelName]?.storage?.fields ?? {};
186
+ cached = {};
187
+ for (const [f, s] of Object.entries(storageFields)) cached[s?.column ?? f] = f;
188
+ perContract.set(cacheKey, cached);
189
+ return cached;
190
+ }
191
+ function resolveIncludeRelation(contract, namespaceId, baseModelName, relationName, variantName) {
192
+ const polymorphism = resolvePolymorphismInfo(contract, namespaceId, baseModelName);
193
+ const variant = variantName === void 0 ? void 0 : polymorphism?.variants.get(variantName);
194
+ let declaringModelName = baseModelName;
195
+ let localTableName = resolveModelTableName(contract, namespaceId, baseModelName);
196
+ let relation;
197
+ if (variant !== void 0) {
198
+ const candidate = resolveModelRelations(contract, namespaceId, variant.modelName)[relationName];
199
+ if (candidate !== void 0) {
200
+ relation = candidate;
201
+ declaringModelName = variant.modelName;
202
+ localTableName = variant.table;
203
+ }
204
+ }
205
+ relation ??= resolveModelRelations(contract, namespaceId, baseModelName)[relationName];
206
+ if (!relation) throw ormError("ORM.RELATION_UNKNOWN", `Relation '${relationName}' not found on model '${baseModelName}'`, { meta: {
207
+ model: baseModelName,
208
+ relation: relationName
209
+ } });
210
+ const localField = relation.on.localFields[0];
211
+ const targetField = relation.on.targetFields[0];
212
+ if (!localField || !targetField) throw new InternalError(`Relation '${relationName}' on model '${declaringModelName}' has incomplete join metadata (missing localFields or targetFields)`);
213
+ const relatedTableName = resolveModelTableName(contract, relation.toNamespace, relation.to);
214
+ const localColumn = resolveFieldToColumn(contract, namespaceId, declaringModelName, localField);
215
+ const targetColumn = resolveFieldToColumn(contract, relation.toNamespace, relation.to, targetField);
216
+ let through;
217
+ if (relation.through !== void 0) {
218
+ const parentLocalColumns = relation.on.localFields.map((field) => resolveFieldToColumn(contract, namespaceId, declaringModelName, field));
219
+ through = {
220
+ table: relation.through.table,
221
+ namespaceId: relation.through.namespaceId,
222
+ parentColumns: relation.through.parentColumns,
223
+ childColumns: relation.through.childColumns,
224
+ targetColumns: relation.through.targetColumns,
225
+ parentLocalColumns
226
+ };
227
+ }
228
+ return {
229
+ relatedModelName: relation.to,
230
+ relatedNamespaceId: relation.toNamespace,
231
+ relatedTableName,
232
+ localTableName,
233
+ targetColumn,
234
+ localColumn,
235
+ cardinality: relation.cardinality,
236
+ ...ifDefined("through", through)
237
+ };
238
+ }
239
+ function resolveThrough(contract, through) {
240
+ if (!through) return void 0;
241
+ const { table, namespaceId, parentColumns, childColumns, targetColumns } = through;
242
+ const junctionTable = contract.storage.namespaces[namespaceId]?.entries.table?.[table];
243
+ if (!junctionTable) return void 0;
244
+ const fkColumnSet = /* @__PURE__ */ new Set([...parentColumns, ...childColumns]);
245
+ const requiredPayloadColumns = [];
246
+ for (const [colName, col] of Object.entries(junctionTable.columns)) if (!fkColumnSet.has(colName) && !col.nullable && col.default === void 0 && !hasExecutionCreateDefault(contract, namespaceId, table, colName)) requiredPayloadColumns.push(colName);
247
+ return {
248
+ table,
249
+ namespaceId,
250
+ parentColumns,
251
+ childColumns,
252
+ targetColumns,
253
+ requiredPayloadColumns
254
+ };
255
+ }
256
+ function hasExecutionCreateDefault(contract, namespace, table, column) {
257
+ return contract.execution?.mutations.defaults.some((mutationDefault) => mutationDefault.ref.namespace === namespace && mutationDefault.ref.table === table && mutationDefault.ref.column === column && mutationDefault.onCreate !== void 0) ?? false;
258
+ }
259
+ const modelRelationsCache = /* @__PURE__ */ new WeakMap();
260
+ function resolveModelRelations(contract, namespaceId, modelName) {
261
+ let perContract = modelRelationsCache.get(contract);
262
+ if (!perContract) {
263
+ perContract = /* @__PURE__ */ new Map();
264
+ modelRelationsCache.set(contract, perContract);
265
+ }
266
+ const cacheKey = metadataCacheKey(namespaceId, modelName);
267
+ const cached = perContract.get(cacheKey);
268
+ if (cached) return cached;
269
+ const relationMap = modelsOf(contract, namespaceId)[modelName]?.relations ?? {};
270
+ const resolved = {};
271
+ for (const [name, value] of Object.entries(relationMap)) {
272
+ if (!value || typeof value !== "object") continue;
273
+ const rel = blindCast(value);
274
+ const localFields = rel.on?.localFields;
275
+ const targetFields = rel.on?.targetFields;
276
+ if (!rel.to || typeof rel.to !== "object" || typeof rel.to.model !== "string" || !Array.isArray(localFields) || !Array.isArray(targetFields)) continue;
277
+ const through = resolveThrough(contract, rel.through);
278
+ resolved[name] = {
279
+ to: rel.to.model,
280
+ toNamespace: rel.to.namespace,
281
+ cardinality: parseRelationCardinality(rel.cardinality),
282
+ on: {
283
+ localFields: blindCast(localFields),
284
+ targetFields: blindCast(targetFields)
285
+ },
286
+ ...through !== void 0 ? { through } : {}
287
+ };
288
+ }
289
+ perContract.set(cacheKey, resolved);
290
+ return resolved;
291
+ }
292
+ function parseRelationCardinality(value) {
293
+ if (value === "1:1" || value === "N:1" || value === "1:N" || value === "N:M") return value;
294
+ }
295
+ function resolveUpsertConflictColumns(contract, namespaceId, modelName, conflictOn) {
296
+ if (conflictOn && typeof conflictOn === "object") {
297
+ const columns = Object.keys(conflictOn).map((fieldName) => resolveFieldToColumn(contract, namespaceId, modelName, fieldName));
298
+ if (columns.length > 0) return columns;
299
+ }
300
+ return [...storageTableForContract(contract, namespaceId, resolveModelTableName(contract, namespaceId, modelName)).primaryKey?.columns ?? []];
301
+ }
302
+ function resolveModelTableName(contract, namespaceId, modelName) {
303
+ const table = domainModelTableInNamespace(contract, namespaceId, modelName);
304
+ if (table === void 0) throw new InternalError(`Model "${modelName}" has invalid or missing storage.table in namespace "${namespaceId}"`);
305
+ return table;
306
+ }
307
+ function resolvePrimaryKeyColumn(contract, namespaceId, tableName) {
308
+ return resolveTableForContract(contract, namespaceId, tableName)?.table.primaryKey?.columns[0] ?? "id";
309
+ }
310
+ function resolveRowIdentityColumns(contract, namespaceId, tableName) {
311
+ let table;
312
+ try {
313
+ table = storageTableForContract(contract, namespaceId, tableName);
314
+ } catch (error) {
315
+ if (error instanceof Error && error.message.includes("ambiguous")) throw error;
316
+ return [];
317
+ }
318
+ if (table.primaryKey && table.primaryKey.columns.length > 0) return table.primaryKey.columns;
319
+ for (const unique of table.uniques) if (unique.columns.length > 0) return unique.columns;
320
+ return [];
321
+ }
322
+ function assertReturningCapability(contract, action) {
323
+ if (hasContractCapability(contract, "returning")) return;
324
+ throw ormError("ORM.CAPABILITY_MISSING", `${action} requires contract capability "returning"`, { meta: {
325
+ capability: "returning",
326
+ action
327
+ } });
328
+ }
329
+ function hasContractCapability(contract, capability) {
330
+ const capabilities = contract.capabilities;
331
+ const value = capabilities[capability];
332
+ if (capabilityEnabled(value)) return true;
333
+ return Object.values(capabilities).some((targetCapabilities) => {
334
+ if (typeof targetCapabilities !== "object" || targetCapabilities === null) return false;
335
+ return capabilityEnabled(targetCapabilities[capability]);
336
+ });
337
+ }
338
+ function capabilityEnabled(value) {
339
+ if (value === true) return true;
340
+ if (typeof value !== "object" || value === null) return false;
341
+ return Object.values(blindCast(value)).some((flag) => flag === true);
342
+ }
343
+ function isToOneCardinality(cardinality) {
344
+ return cardinality === "1:1" || cardinality === "N:1";
345
+ }
346
+ function createAggregateBuilder(contract, namespaceId, modelName) {
347
+ const fieldToColumn = getFieldToColumnMap(contract, namespaceId, modelName);
348
+ return {
349
+ count() {
350
+ return {
351
+ kind: "aggregate",
352
+ fn: "count"
353
+ };
354
+ },
355
+ sum(field) {
356
+ return createFieldAggregateSelector(fieldToColumn, field, "sum");
357
+ },
358
+ avg(field) {
359
+ return createFieldAggregateSelector(fieldToColumn, field, "avg");
360
+ },
361
+ min(field) {
362
+ return createFieldAggregateSelector(fieldToColumn, field, "min");
363
+ },
364
+ max(field) {
365
+ return createFieldAggregateSelector(fieldToColumn, field, "max");
366
+ }
367
+ };
368
+ }
369
+ function isAggregateSelector(value) {
370
+ if (!value || typeof value !== "object") return false;
371
+ const candidate = value;
372
+ if (candidate.kind !== "aggregate") return false;
373
+ return candidate.fn === "count" || candidate.fn === "sum" || candidate.fn === "avg" || candidate.fn === "min" || candidate.fn === "max";
374
+ }
375
+ function createFieldAggregateSelector(fieldToColumn, field, fn) {
376
+ const fieldName = field;
377
+ return {
378
+ kind: "aggregate",
379
+ fn,
380
+ column: fieldToColumn[fieldName] ?? fieldName
381
+ };
382
+ }
383
+ function normalizeAggregateResult(aggregateSpec, row) {
384
+ const result = {};
385
+ for (const [alias, selector] of Object.entries(aggregateSpec)) {
386
+ const value = row[alias];
387
+ if (value === null) {
388
+ result[alias] = null;
389
+ continue;
390
+ }
391
+ if (value === void 0) {
392
+ result[alias] = selector.fn === "count" ? 0 : null;
393
+ continue;
394
+ }
395
+ if (typeof value === "number") {
396
+ result[alias] = value;
397
+ continue;
398
+ }
399
+ if (typeof value === "bigint") {
400
+ result[alias] = Number(value);
401
+ continue;
402
+ }
403
+ if (typeof value === "string") {
404
+ const numeric = Number(value);
405
+ result[alias] = Number.isNaN(numeric) ? value : numeric;
406
+ continue;
407
+ }
408
+ result[alias] = value;
409
+ }
410
+ return result;
411
+ }
412
+ function mapFieldsToColumns(contract, namespaceId, modelName, fieldNames) {
413
+ const fieldToColumn = getFieldToColumnMap(contract, namespaceId, modelName);
414
+ return fieldNames.map((fieldName) => fieldToColumn[fieldName] ?? fieldName);
415
+ }
416
+ function mapCursorValuesToColumns(contract, namespaceId, modelName, cursorValues) {
417
+ const fieldToColumn = getFieldToColumnMap(contract, namespaceId, modelName);
418
+ const mappedCursor = {};
419
+ for (const [fieldName, value] of Object.entries(cursorValues)) {
420
+ if (value === void 0) continue;
421
+ const columnName = fieldToColumn[fieldName] ?? fieldName;
422
+ mappedCursor[columnName] = value;
423
+ }
424
+ return mappedCursor;
425
+ }
426
+ function stripHiddenMappedFields(contract, namespaceId, modelName, mapped, hiddenColumns) {
427
+ if (hiddenColumns.length === 0) return;
428
+ const columnToField = getColumnToFieldMap(contract, namespaceId, modelName);
429
+ for (const hiddenColumn of hiddenColumns) {
430
+ const fieldName = columnToField[hiddenColumn] ?? hiddenColumn;
431
+ delete mapped[fieldName];
432
+ }
433
+ }
434
+ function mapStorageRowToModelFields(contract, namespaceId, modelName, row) {
435
+ const columnToField = getColumnToFieldMap(contract, namespaceId, modelName);
436
+ if (Object.keys(columnToField).length === 0) return { ...row };
437
+ const mapped = {};
438
+ for (const [columnName, value] of Object.entries(row)) mapped[columnToField[columnName] ?? columnName] = value;
439
+ return mapped;
440
+ }
441
+ const mergedColumnToFieldCache = /* @__PURE__ */ new WeakMap();
442
+ function getMergedColumnToFieldMap(contract, namespaceId, baseModelName, variantModelName, variantTable) {
443
+ const cacheKey = `${namespaceId}:${baseModelName}:${variantModelName}:${variantTable ?? ""}`;
444
+ let perContract = mergedColumnToFieldCache.get(contract);
445
+ if (!perContract) {
446
+ perContract = /* @__PURE__ */ new Map();
447
+ mergedColumnToFieldCache.set(contract, perContract);
448
+ }
449
+ const cached = perContract.get(cacheKey);
450
+ if (cached) return cached;
451
+ const baseMap = getCompleteColumnToFieldMap(contract, namespaceId, baseModelName);
452
+ const variantMap = getCompleteColumnToFieldMap(contract, namespaceId, variantModelName);
453
+ const merged = { ...baseMap };
454
+ for (const [col, field] of Object.entries(variantMap)) if (variantTable) merged[`${variantTable}__${col}`] = field;
455
+ else merged[col] = field;
456
+ perContract.set(cacheKey, merged);
457
+ return merged;
458
+ }
459
+ function mapPolymorphicRow(contract, namespaceId, baseModelName, polyInfo, row, variantName) {
460
+ const discriminatorValue = row[polyInfo.discriminatorColumn] ?? row["__prisma_polymorphic_discriminator"];
461
+ const variant = variantName ? polyInfo.variants.get(variantName) : typeof discriminatorValue === "string" ? polyInfo.variantsByValue.get(discriminatorValue) : void 0;
462
+ if (!variant) {
463
+ const baseMap = getCompleteColumnToFieldMap(contract, namespaceId, baseModelName);
464
+ const mapped = {};
465
+ for (const [col, val] of Object.entries(row)) {
466
+ const field = baseMap[col];
467
+ if (field !== void 0) mapped[field] = val;
468
+ }
469
+ return mapped;
470
+ }
471
+ const mtiTable = variant.strategy === "mti" ? variant.table : void 0;
472
+ const mergedMap = getMergedColumnToFieldMap(contract, namespaceId, baseModelName, variant.modelName, mtiTable);
473
+ const mapped = {};
474
+ for (const [col, val] of Object.entries(row)) {
475
+ const field = mergedMap[col];
476
+ if (field !== void 0) mapped[field] = val;
477
+ }
478
+ return mapped;
479
+ }
480
+ function mapModelDataToStorageRow(contract, namespaceId, modelName, row) {
481
+ const fieldToColumn = getFieldToColumnMap(contract, namespaceId, modelName);
482
+ const mapped = {};
483
+ for (const [fieldName, value] of Object.entries(row)) {
484
+ if (value === void 0) continue;
485
+ const columnName = fieldToColumn[fieldName] ?? fieldName;
486
+ mapped[columnName] = value;
487
+ }
488
+ return mapped;
489
+ }
490
+ function mapResultRows(result, mapper) {
491
+ const generator = async function* () {
492
+ for await (const value of result) yield mapper(value);
493
+ };
494
+ return new AsyncIterableResult(generator());
495
+ }
496
+ async function acquireRuntimeScope(runtime) {
497
+ if (typeof runtime.connection !== "function") return { scope: runtime };
498
+ const connection = await runtime.connection();
499
+ const release = connection.release;
500
+ if (typeof release === "function") return {
501
+ scope: connection,
502
+ release: () => release.call(connection) ?? Promise.resolve()
503
+ };
504
+ return { scope: connection };
505
+ }
506
+ function executeQueryPlan(scope, plan) {
507
+ return scope.execute(plan);
508
+ }
509
+ function deriveParamsFromAst(ast) {
510
+ return { params: collectOrderedParamRefs(ast).map((p) => p.kind === "param-ref" ? p.value : void 0) };
511
+ }
512
+ function resolveTableColumns(contract, namespaceId, tableName) {
513
+ try {
514
+ return Object.keys(storageTableForContract(contract, namespaceId, tableName).columns);
515
+ } catch (error) {
516
+ if (error instanceof Error && error.message.includes("ambiguous")) throw error;
517
+ throw ormError("ORM.TABLE_UNKNOWN", `Unknown table "${tableName}" in SQL ORM query planner`, { meta: {
518
+ namespaceId,
519
+ tableName
520
+ } });
521
+ }
522
+ }
523
+ function buildOrmPlanMeta(contract, annotations) {
524
+ const annotationRecord = annotations !== void 0 && annotations.size > 0 ? Object.freeze(Object.fromEntries(annotations)) : void 0;
525
+ return {
526
+ target: contract.target,
527
+ targetFamily: contract.targetFamily,
528
+ storageHash: contract.storage.storageHash,
529
+ ...ifDefined("profileHash", contract.profileHash),
530
+ ...ifDefined("annotations", annotationRecord),
531
+ lane: "orm-client"
532
+ };
533
+ }
534
+ function buildOrmQueryPlan(contract, ast, params, annotations) {
535
+ return Object.freeze({
536
+ ast,
537
+ params: [...params],
538
+ meta: buildOrmPlanMeta(contract, annotations)
539
+ });
540
+ }
541
+ /**
542
+ * Merges annotations into an existing `SqlQueryPlan`'s
543
+ * `meta.annotations` and returns a new frozen plan.
544
+ *
545
+ * Used by the ORM dispatch path to attach terminal-call annotations to
546
+ * plans produced by mutation compile functions (which don't take
547
+ * annotations as parameters). Reads compile through `compileSelect`-
548
+ * family functions that pass `state.annotations` directly to
549
+ * `buildOrmQueryPlan`; this helper is the alternate path for write
550
+ * terminals where annotations arrive at the call site, not via state.
551
+ *
552
+ * Returns the input plan unchanged when `annotations` is undefined
553
+ * or empty. Reserved framework namespaces (`codecs`, `limit`) on the
554
+ * input plan win over caller-supplied entries under the same key —
555
+ * see the reserved-namespace policy on `defineAnnotation`.
556
+ */
557
+ function mergeAnnotations(plan, annotations) {
558
+ if (annotations === void 0 || annotations.size === 0) return plan;
559
+ const callerEntries = {};
560
+ for (const [namespace, value] of annotations) callerEntries[namespace] = value;
561
+ const mergedAnnotations = Object.freeze({
562
+ ...callerEntries,
563
+ ...plan.meta.annotations ?? {}
564
+ });
565
+ return Object.freeze({
566
+ ...plan,
567
+ meta: Object.freeze({
568
+ ...plan.meta,
569
+ annotations: mergedAnnotations
570
+ })
571
+ });
572
+ }
573
+ function combineWhereExprs(filters) {
574
+ if (filters.length === 0) return;
575
+ if (filters.length === 1) return filters[0];
576
+ return AndExpr.of(filters);
577
+ }
578
+ function toAggregateProjection(contract, namespaceId, tableName, selector) {
579
+ if (selector.fn === "count") return {
580
+ expr: AggregateExpr.count(),
581
+ codec: void 0
582
+ };
583
+ if (!selector.column) throw ormError("ORM.AGGREGATE_SELECTOR_INVALID", `Aggregate selector "${selector.fn}" requires a field`, { meta: { fn: selector.fn } });
584
+ const expr = new AggregateExpr(selector.fn, ColumnRef.of(tableName, selector.column));
585
+ if (selector.fn === "min" || selector.fn === "max") return {
586
+ expr,
587
+ codec: codecRefForStorageColumn(contract.storage, namespaceId, tableName, selector.column)
588
+ };
589
+ return {
590
+ expr,
591
+ codec: void 0
592
+ };
593
+ }
594
+ function validateGroupedComparable(value) {
595
+ switch (value.kind) {
596
+ case "param-ref": throw ormError("ORM.HAVING_EXPRESSION_UNSUPPORTED", "ParamRef is not supported in grouped having expressions", { meta: { kind: value.kind } });
597
+ case "literal":
598
+ case "column-ref":
599
+ case "identifier-ref":
600
+ case "aggregate":
601
+ case "operation": return value;
602
+ case "function-call":
603
+ case "cast":
604
+ case "case": throw ormError("ORM.HAVING_EXPRESSION_UNSUPPORTED", `Unsupported comparable kind in grouped having: "${value.kind}"`, { meta: { kind: value.kind } });
605
+ case "list":
606
+ if (value.values.some((entry) => entry.kind === "param-ref")) throw ormError("ORM.HAVING_EXPRESSION_UNSUPPORTED", "ParamRef is not supported in grouped having expressions", { meta: { kind: "list" } });
607
+ return value;
608
+ default: throw ormError("ORM.HAVING_EXPRESSION_UNSUPPORTED", `Unsupported comparable kind in grouped having: "${value.kind}"`, { meta: { kind: value.kind } });
609
+ }
610
+ }
611
+ function validateGroupedMetricExpr(expr) {
612
+ if (expr.kind !== "aggregate") throw ormError("ORM.HAVING_EXPRESSION_UNSUPPORTED", "groupBy().having() only supports aggregate metric expressions", { meta: { kind: expr.kind } });
613
+ return expr;
614
+ }
615
+ function rejectHavingExpr(expr) {
616
+ throw ormError("ORM.HAVING_EXPRESSION_UNSUPPORTED", `Unsupported grouped having expression kind "${expr.kind}"`, { meta: { kind: expr.kind } });
617
+ }
618
+ function validateGroupedHavingExpr(expr) {
619
+ return expr.accept({
620
+ columnRef: rejectHavingExpr,
621
+ identifierRef: rejectHavingExpr,
622
+ subquery: rejectHavingExpr,
623
+ operation: rejectHavingExpr,
624
+ aggregate: rejectHavingExpr,
625
+ windowFunc: rejectHavingExpr,
626
+ functionCall: rejectHavingExpr,
627
+ cast: rejectHavingExpr,
628
+ case: rejectHavingExpr,
629
+ jsonObject: rejectHavingExpr,
630
+ jsonArrayAgg: rejectHavingExpr,
631
+ literal: rejectHavingExpr,
632
+ param() {
633
+ throw ormError("ORM.HAVING_EXPRESSION_UNSUPPORTED", "ParamRef is not supported in grouped having expressions", { meta: { kind: "param-ref" } });
634
+ },
635
+ preparedParam() {
636
+ throw ormError("ORM.HAVING_EXPRESSION_UNSUPPORTED", "PreparedParamRef is not supported in grouped having expressions", { meta: { kind: "prepared-param-ref" } });
637
+ },
638
+ list: rejectHavingExpr,
639
+ and(expr) {
640
+ return AndExpr.of(expr.exprs.map((child) => validateGroupedHavingExpr(child)));
641
+ },
642
+ or(expr) {
643
+ return OrExpr.of(expr.exprs.map((child) => validateGroupedHavingExpr(child)));
644
+ },
645
+ exists: rejectHavingExpr,
646
+ nullCheck(expr) {
647
+ return new NullCheckExpr(validateGroupedMetricExpr(expr.expr), expr.isNull);
648
+ },
649
+ not(expr) {
650
+ return new NotExpr(validateGroupedHavingExpr(expr.expr));
651
+ },
652
+ binary(expr) {
653
+ return new BinaryExpr(expr.op, validateGroupedMetricExpr(expr.left), validateGroupedComparable(expr.right));
654
+ },
655
+ rawExpr: rejectHavingExpr
656
+ });
657
+ }
658
+ function compileAggregate(contract, namespaceId, tableName, filters, aggregateSpec) {
659
+ const entries = Object.entries(aggregateSpec);
660
+ if (entries.length === 0) throw ormError("ORM.AGGREGATE_SELECTOR_MISSING", "aggregate() requires at least one aggregation selector", { meta: {
661
+ method: "aggregate",
662
+ namespaceId,
663
+ tableName
664
+ } });
665
+ const projection = entries.map(([alias, selector]) => {
666
+ const { expr, codec } = toAggregateProjection(contract, namespaceId, tableName, selector);
667
+ return ProjectionItem.of(alias, expr, codec);
668
+ });
669
+ let ast = SelectAst.from(tableSourceForContract(contract, namespaceId, tableName)).withProjection(projection);
670
+ const where = combineWhereExprs(filters);
671
+ if (where) ast = ast.withWhere(where);
672
+ const { params } = deriveParamsFromAst(ast);
673
+ return buildOrmQueryPlan(contract, ast, params);
674
+ }
675
+ function compileGroupedAggregate(contract, namespaceId, tableName, filters, groupByColumns, aggregateSpec, havingExpr) {
676
+ if (groupByColumns.length === 0) throw ormError("ORM.GROUP_BY_FIELD_MISSING", "groupBy() requires at least one field", { meta: {
677
+ namespaceId,
678
+ tableName
679
+ } });
680
+ const entries = Object.entries(aggregateSpec);
681
+ if (entries.length === 0) throw ormError("ORM.AGGREGATE_SELECTOR_MISSING", "groupBy().aggregate() requires at least one aggregation selector", { meta: {
682
+ method: "groupBy.aggregate",
683
+ namespaceId,
684
+ tableName
685
+ } });
686
+ const projection = [...groupByColumns.map((column) => ProjectionItem.of(column, ColumnRef.of(tableName, column), codecRefForStorageColumn(contract.storage, namespaceId, tableName, column))), ...entries.map(([alias, selector]) => {
687
+ const { expr, codec } = toAggregateProjection(contract, namespaceId, tableName, selector);
688
+ return ProjectionItem.of(alias, expr, codec);
689
+ })];
690
+ let ast = SelectAst.from(tableSourceForContract(contract, namespaceId, tableName)).withProjection(projection).withGroupBy(groupByColumns.map((column) => ColumnRef.of(tableName, column)));
691
+ const where = combineWhereExprs(filters);
692
+ if (where) ast = ast.withWhere(where);
693
+ if (havingExpr) ast = ast.withHaving(validateGroupedHavingExpr(havingExpr));
694
+ const { params } = deriveParamsFromAst(ast);
695
+ return buildOrmQueryPlan(contract, ast, params);
696
+ }
697
+ function buildReturningColumns(contract, namespaceId, tableName, returningColumns) {
698
+ return (returningColumns && returningColumns.length > 0 ? [...returningColumns] : resolveTableColumns(contract, namespaceId, tableName)).map((column) => ProjectionItem.of(column, ColumnRef.of(tableName, column), codecRefForStorageColumn(contract.storage, namespaceId, tableName, column)));
699
+ }
700
+ function toParamAssignments(contract, namespaceId, tableName, values) {
701
+ const assignments = {};
702
+ const table = storageTableForContract(contract, namespaceId, tableName);
703
+ for (const [column, value] of Object.entries(values)) {
704
+ if (!table.columns[column]) throw ormError("ORM.COLUMN_UNKNOWN", `Unknown column "${column}" in table "${tableName}"`, { meta: {
705
+ namespaceId,
706
+ tableName,
707
+ column
708
+ } });
709
+ const codec = codecRefForStorageColumn(contract.storage, namespaceId, tableName, column);
710
+ assignments[column] = ParamRef.of(value, {
711
+ name: column,
712
+ ...ifDefined("codec", codec)
713
+ });
714
+ }
715
+ return { assignments };
716
+ }
717
+ function normalizeInsertRows(contract, namespaceId, tableName, rows) {
718
+ if (rows.length === 0) throw new InternalError("normalizeInsertRows requires at least one row");
719
+ const orderedColumns = [];
720
+ const seenColumns = /* @__PURE__ */ new Set();
721
+ for (const row of rows) for (const column of Object.keys(row)) {
722
+ if (seenColumns.has(column)) continue;
723
+ seenColumns.add(column);
724
+ orderedColumns.push(column);
725
+ }
726
+ const table = storageTableForContract(contract, namespaceId, tableName);
727
+ return { rows: rows.map((row) => {
728
+ if (orderedColumns.length === 0) return {};
729
+ const normalizedRow = {};
730
+ for (const column of orderedColumns) {
731
+ if (Object.hasOwn(row, column)) {
732
+ if (!table.columns[column]) throw ormError("ORM.COLUMN_UNKNOWN", `Unknown column "${column}" in table "${tableName}"`, { meta: {
733
+ namespaceId,
734
+ tableName,
735
+ column
736
+ } });
737
+ const codec = codecRefForStorageColumn(contract.storage, namespaceId, tableName, column);
738
+ normalizedRow[column] = ParamRef.of(row[column], {
739
+ name: column,
740
+ ...ifDefined("codec", codec)
741
+ });
742
+ continue;
743
+ }
744
+ normalizedRow[column] = new DefaultValueExpr();
745
+ }
746
+ return normalizedRow;
747
+ }) };
748
+ }
749
+ function compileInsertReturning(contract, namespaceId, tableName, rows, returningColumns) {
750
+ const { rows: normalizedRows } = normalizeInsertRows(contract, namespaceId, tableName, rows);
751
+ const ast = InsertAst.into(tableSourceForContract(contract, namespaceId, tableName)).withRows(normalizedRows).withReturning(buildReturningColumns(contract, namespaceId, tableName, returningColumns));
752
+ const { params } = deriveParamsFromAst(ast);
753
+ return buildOrmQueryPlan(contract, ast, params);
754
+ }
755
+ function compileInsertCount(contract, namespaceId, tableName, rows) {
756
+ const { rows: normalizedRows } = normalizeInsertRows(contract, namespaceId, tableName, rows);
757
+ const ast = InsertAst.into(tableSourceForContract(contract, namespaceId, tableName)).withRows(normalizedRows);
758
+ const { params } = deriveParamsFromAst(ast);
759
+ return buildOrmQueryPlan(contract, ast, params);
760
+ }
761
+ function stripUndefinedValues(row) {
762
+ const result = {};
763
+ for (const [key, value] of Object.entries(row)) if (value !== void 0) result[key] = value;
764
+ return result;
765
+ }
766
+ function createTableRefRemapper$1(fromTable, toTable) {
767
+ return {
768
+ columnRef: (col) => col.table === fromTable ? ColumnRef.of(toTable, col.column) : col,
769
+ tableSource: (source) => {
770
+ if (source.alias === fromTable) return TableSource.named(source.name, toTable, source.namespaceId);
771
+ if (!source.alias && source.name === fromTable) return TableSource.named(source.name, toTable, source.namespaceId);
772
+ return source;
773
+ },
774
+ eqColJoinOn: (on) => EqColJoinOn.of(on.left.table === fromTable ? ColumnRef.of(toTable, on.left.column) : on.left, on.right.table === fromTable ? ColumnRef.of(toTable, on.right.column) : on.right)
775
+ };
776
+ }
777
+ function buildCountMutationWhere(contract, namespaceId, tableName, filters, variantName, modelName) {
778
+ if (!variantName || !modelName) return combineWhereExprs(filters);
779
+ const polyInfo = resolvePolymorphismInfo(contract, namespaceId, modelName);
780
+ const variant = polyInfo?.variants.get(variantName);
781
+ if (!polyInfo || !variant || variant.strategy !== "mti") return combineWhereExprs(filters);
782
+ const pkColumn = resolvePrimaryKeyColumn(contract, namespaceId, tableName);
783
+ const baseTableRef = `${tableName}__write_filter`;
784
+ const remapper = createTableRefRemapper$1(tableName, baseTableRef);
785
+ const innerFilters = filters.map((filter) => filter.rewrite(remapper));
786
+ const where = combineWhereExprs([BinaryExpr.eq(ColumnRef.of(baseTableRef, pkColumn), ColumnRef.of(tableName, pkColumn)), ...innerFilters]);
787
+ const joinOn = EqColJoinOn.of(ColumnRef.of(baseTableRef, pkColumn), ColumnRef.of(variant.table, pkColumn));
788
+ let subquery = SelectAst.from(TableSource.named(tableName, baseTableRef, namespaceId)).withProjection([ProjectionItem.of("_write_filter", ColumnRef.of(baseTableRef, pkColumn))]).withJoins([JoinAst.inner(tableSourceForContract(contract, namespaceId, variant.table), joinOn)]);
789
+ if (where) subquery = subquery.withWhere(where);
790
+ return ExistsExpr.exists(subquery);
791
+ }
792
+ function groupRowsByColumnSignature(rows) {
793
+ const groups = [];
794
+ let currentKey = "";
795
+ let currentGroup = [];
796
+ for (const rawRow of rows) {
797
+ const row = stripUndefinedValues(rawRow);
798
+ const key = Object.keys(row).sort().join(",");
799
+ if (key !== currentKey || currentGroup.length === 0) {
800
+ if (currentGroup.length > 0) groups.push(currentGroup);
801
+ currentKey = key;
802
+ currentGroup = [row];
803
+ } else currentGroup.push(row);
804
+ }
805
+ if (currentGroup.length > 0) groups.push(currentGroup);
806
+ return groups;
807
+ }
808
+ function compileInsertReturningSplit(contract, namespaceId, tableName, rows, returningColumns) {
809
+ if (rows.length === 0) throw ormError("ORM.MUTATION_DATA_MISSING", "create() requires at least one row", { meta: {
810
+ method: "create",
811
+ namespaceId,
812
+ tableName
813
+ } });
814
+ return groupRowsByColumnSignature(rows).map((group) => compileInsertReturning(contract, namespaceId, tableName, group, returningColumns));
815
+ }
816
+ function compileInsertCountSplit(contract, namespaceId, tableName, rows) {
817
+ if (rows.length === 0) throw ormError("ORM.MUTATION_DATA_MISSING", "createAndCount() requires at least one row", { meta: {
818
+ method: "createAndCount",
819
+ namespaceId,
820
+ tableName
821
+ } });
822
+ return groupRowsByColumnSignature(rows).map((group) => compileInsertCount(contract, namespaceId, tableName, group));
823
+ }
824
+ function compileUpsertReturning(contract, namespaceId, tableName, createValues, updateValues, conflictColumns, returningColumns) {
825
+ const createAssignments = toParamAssignments(contract, namespaceId, tableName, createValues);
826
+ const updateAssignments = Object.keys(updateValues).length > 0 ? toParamAssignments(contract, namespaceId, tableName, updateValues) : void 0;
827
+ const onConflict = updateAssignments ? InsertOnConflict.on(conflictColumns.map((column) => ColumnRef.of(tableName, column))).doUpdateSet(updateAssignments.assignments) : InsertOnConflict.on(conflictColumns.map((column) => ColumnRef.of(tableName, column))).doNothing();
828
+ const ast = InsertAst.into(tableSourceForContract(contract, namespaceId, tableName)).withRows([createAssignments.assignments]).withOnConflict(onConflict).withReturning(buildReturningColumns(contract, namespaceId, tableName, returningColumns));
829
+ const { params } = deriveParamsFromAst(ast);
830
+ return buildOrmQueryPlan(contract, ast, params);
831
+ }
832
+ function compileUpdateReturning(contract, namespaceId, tableName, setValues, filters, returningColumns) {
833
+ const where = combineWhereExprs(filters);
834
+ const { assignments } = toParamAssignments(contract, namespaceId, tableName, setValues);
835
+ let ast = UpdateAst.table(tableSourceForContract(contract, namespaceId, tableName)).withSet(assignments).withReturning(buildReturningColumns(contract, namespaceId, tableName, returningColumns));
836
+ if (where) ast = ast.withWhere(where);
837
+ const { params } = deriveParamsFromAst(ast);
838
+ return buildOrmQueryPlan(contract, ast, params);
839
+ }
840
+ function compileUpdateCount(contract, namespaceId, tableName, setValues, filters, variantName, modelName) {
841
+ const where = buildCountMutationWhere(contract, namespaceId, tableName, filters, variantName, modelName);
842
+ const { assignments } = toParamAssignments(contract, namespaceId, tableName, setValues);
843
+ let ast = UpdateAst.table(tableSourceForContract(contract, namespaceId, tableName)).withSet(assignments);
844
+ if (where) ast = ast.withWhere(where);
845
+ const { params } = deriveParamsFromAst(ast);
846
+ return buildOrmQueryPlan(contract, ast, params);
847
+ }
848
+ function compileDeleteReturning(contract, namespaceId, tableName, filters, returningColumns) {
849
+ const where = combineWhereExprs(filters);
850
+ let ast = DeleteAst.from(tableSourceForContract(contract, namespaceId, tableName)).withReturning(buildReturningColumns(contract, namespaceId, tableName, returningColumns));
851
+ if (where) ast = ast.withWhere(where);
852
+ const { params } = deriveParamsFromAst(ast);
853
+ return buildOrmQueryPlan(contract, ast, params);
854
+ }
855
+ function compileDeleteCount(contract, namespaceId, tableName, filters, variantName, modelName) {
856
+ const where = buildCountMutationWhere(contract, namespaceId, tableName, filters, variantName, modelName);
857
+ let ast = DeleteAst.from(tableSourceForContract(contract, namespaceId, tableName));
858
+ if (where) ast = ast.withWhere(where);
859
+ const { params } = deriveParamsFromAst(ast);
860
+ return buildOrmQueryPlan(contract, ast, params);
861
+ }
862
+ function augmentSelectionForJoinColumns(selectedFields, requiredColumns) {
863
+ if (!selectedFields) return {
864
+ selectedForQuery: selectedFields,
865
+ hiddenColumns: []
866
+ };
867
+ const hiddenColumns = requiredColumns.filter((column) => !selectedFields.includes(column));
868
+ if (hiddenColumns.length === 0) return {
869
+ selectedForQuery: selectedFields,
870
+ hiddenColumns: []
871
+ };
872
+ return {
873
+ selectedForQuery: [...selectedFields, ...hiddenColumns],
874
+ hiddenColumns
875
+ };
876
+ }
877
+ function namespaceCoordinateForSource(source) {
878
+ return source.kind === "table-source" ? source.namespaceId : void 0;
879
+ }
880
+ function bindWhereExpr(contract, expr, namespaceId) {
881
+ return bindWhereExprNode(contract, expr, namespaceId);
882
+ }
883
+ function bindWhereExprNode(contract, expr, namespaceId) {
884
+ return expr.accept({
885
+ columnRef(expr) {
886
+ return bindExpression(contract, expr);
887
+ },
888
+ identifierRef(expr) {
889
+ return expr;
890
+ },
891
+ subquery(expr) {
892
+ return bindExpression(contract, expr);
893
+ },
894
+ operation(expr) {
895
+ return bindExpression(contract, expr);
896
+ },
897
+ aggregate(expr) {
898
+ return bindExpression(contract, expr);
899
+ },
900
+ windowFunc(expr) {
901
+ return bindExpression(contract, expr);
902
+ },
903
+ functionCall(expr) {
904
+ return bindExpression(contract, expr);
905
+ },
906
+ cast(expr) {
907
+ return bindExpression(contract, expr);
908
+ },
909
+ case(expr) {
910
+ return bindExpression(contract, expr);
911
+ },
912
+ jsonObject(expr) {
913
+ return bindExpression(contract, expr);
914
+ },
915
+ jsonArrayAgg(expr) {
916
+ return bindExpression(contract, expr);
917
+ },
918
+ literal(expr) {
919
+ return expr;
920
+ },
921
+ param(expr) {
922
+ return expr;
923
+ },
924
+ preparedParam(expr) {
925
+ return expr;
926
+ },
927
+ list(expr) {
928
+ return bindExpression(contract, expr);
929
+ },
930
+ binary(expr) {
931
+ const left = bindExpression(contract, expr.left);
932
+ const bindingColumn = left.kind === "column-ref" ? left : void 0;
933
+ return new BinaryExpr(expr.op, left, bindComparable(contract, expr.right, bindingColumn, namespaceId));
934
+ },
935
+ and(expr) {
936
+ return AndExpr.of(expr.exprs.map((part) => bindWhereExprNode(contract, part, namespaceId)));
937
+ },
938
+ or(expr) {
939
+ return OrExpr.of(expr.exprs.map((part) => bindWhereExprNode(contract, part, namespaceId)));
940
+ },
941
+ exists(expr) {
942
+ return expr.notExists ? ExistsExpr.notExists(bindSelectAst(contract, expr.subquery)) : ExistsExpr.exists(bindSelectAst(contract, expr.subquery));
943
+ },
944
+ nullCheck(expr) {
945
+ return expr.isNull ? NullCheckExpr.isNull(bindExpression(contract, expr.expr)) : NullCheckExpr.isNotNull(bindExpression(contract, expr.expr));
946
+ },
947
+ not(expr) {
948
+ return new NotExpr(bindWhereExprNode(contract, expr.expr, namespaceId));
949
+ },
950
+ rawExpr(expr) {
951
+ return expr;
952
+ }
953
+ });
954
+ }
955
+ function bindComparable(contract, comparable, bindingColumn, namespaceId) {
956
+ if (comparable.kind === "param-ref" || bindingColumn === void 0) return comparable.kind === "param-ref" ? comparable : comparable.kind === "literal" || comparable.kind === "list" ? comparable : bindExpression(contract, comparable);
957
+ if (comparable.kind === "literal") return createParamRef(contract, bindingColumn, comparable.value, namespaceId);
958
+ if (comparable.kind === "list") return ListExpression.of(comparable.values.map((value) => value.kind === "literal" ? createParamRef(contract, bindingColumn, value.value, namespaceId) : value));
959
+ return bindExpression(contract, comparable);
960
+ }
961
+ function createParamRef(contract, columnRef, value, namespaceId) {
962
+ const resolved = resolveStorageTable(contract.storage, columnRef.table, namespaceId);
963
+ if (resolved === void 0 || !resolved.table.columns[columnRef.column]) throw ormError("ORM.COLUMN_UNKNOWN", `Unknown column "${columnRef.column}" in table "${columnRef.table}"`, { meta: {
964
+ tableName: columnRef.table,
965
+ column: columnRef.column
966
+ } });
967
+ const codec = codecRefForStorageColumn(contract.storage, resolved.namespaceId, columnRef.table, columnRef.column);
968
+ return ParamRef.of(value, codec ? { codec } : void 0);
969
+ }
970
+ function createExpressionBinder(contract) {
971
+ return { select: (ast) => bindSelectAst(contract, ast) };
972
+ }
973
+ function bindExpression(contract, expr) {
974
+ return expr.rewrite(createExpressionBinder(contract));
975
+ }
976
+ function bindProjectionExpr(contract, expr) {
977
+ return expr.kind === "literal" ? expr : bindExpression(contract, expr);
978
+ }
979
+ function bindOrderByItem(contract, orderItem) {
980
+ return new OrderByItem(bindExpression(contract, orderItem.expr), orderItem.dir);
981
+ }
982
+ function bindJoin(contract, join) {
983
+ const namespaceId = namespaceCoordinateForSource(join.source);
984
+ return new JoinAst(join.joinType, bindFromSource(contract, join.source), join.on.kind === "eq-col-join-on" ? join.on : bindWhereExprNode(contract, join.on, namespaceId), join.lateral);
985
+ }
986
+ function bindFromSource(contract, source) {
987
+ if (source.kind === "table-source") return source;
988
+ if (source.kind === "derived-table-source") return DerivedTableSource.as(source.alias, bindSelectAst(contract, source.query));
989
+ return source;
990
+ }
991
+ function bindSelectAst(contract, ast) {
992
+ const namespaceId = ast.from !== void 0 ? namespaceCoordinateForSource(ast.from) : void 0;
993
+ return new SelectAst({
994
+ ...ast.from !== void 0 ? { from: bindFromSource(contract, ast.from) } : {},
995
+ joins: ast.joins?.map((join) => bindJoin(contract, join)),
996
+ projection: ast.projection.map((projection) => new ProjectionItem(projection.alias, bindProjectionExpr(contract, projection.expr), projection.codec)),
997
+ where: ast.where ? bindWhereExprNode(contract, ast.where, namespaceId) : void 0,
998
+ orderBy: ast.orderBy?.map((orderItem) => bindOrderByItem(contract, orderItem)),
999
+ distinct: ast.distinct,
1000
+ distinctOn: ast.distinctOn?.map((expr) => bindExpression(contract, expr)),
1001
+ groupBy: ast.groupBy?.map((expr) => bindExpression(contract, expr)),
1002
+ having: ast.having ? bindWhereExprNode(contract, ast.having, namespaceId) : void 0,
1003
+ limit: ast.limit,
1004
+ offset: ast.offset,
1005
+ selectAllIntent: ast.selectAllIntent
1006
+ });
1007
+ }
1008
+ /**
1009
+ * The rule for which JSON projection variant an include entry carries. Every
1010
+ * site that puts a value into a `json_build_object` or a `json_agg` goes
1011
+ * through here, and the renderers read the variant to decide how the value
1012
+ * reaches JSON.
1013
+ *
1014
+ * - `codec`: the value is a column whose storage codec is known, so the
1015
+ * renderer can ask that codec's descriptor for the projection producing its
1016
+ * canonical JSON. The `CodecRef` is resolved at planning time by
1017
+ * `codecRefForStorageColumn` and carried on the `ProjectionItem` through
1018
+ * every wrap between the column and here.
1019
+ * - `document`: the value is already a JSON document — a nested include's
1020
+ * correlated subquery, a combine branch, or the object a child row set is
1021
+ * aggregated from. Its parts were made canonical at the level that produced
1022
+ * them; this level only nests it.
1023
+ * - `native`: the value has no codec identity. An aggregate is the case that
1024
+ * arises today: `COUNT(*)` and `SUM(col)` are computed, and the aggregate's
1025
+ * own result type is not the column's codec. Native is what a value with no
1026
+ * codec identity means, which is a different thing from defaulting a codec
1027
+ * to identity — that, the project forbids.
1028
+ *
1029
+ * A document never carries a codec and a codec-bearing column is never a
1030
+ * document, so the first two cases cannot both apply.
1031
+ */
1032
+ function jsonEntryProjection(value, identity) {
1033
+ if (identity.codec !== void 0) return new CodecJsonValueProjection(value, identity.codec);
1034
+ if (identity.document === true) return new JsonDocumentProjection(value);
1035
+ return new NativeJsonValueProjection(value);
1036
+ }
1037
+ function buildProjection(contract, namespaceId, tableName, selectedFields, tableRef = tableName) {
1038
+ return (selectedFields !== void 0 ? [...selectedFields] : resolveTableColumns(contract, namespaceId, tableName)).map((column) => ProjectionItem.of(column, ColumnRef.of(tableRef, column), codecRefForStorageColumn(contract.storage, namespaceId, tableName, column)));
1039
+ }
1040
+ function appendUnique(values, value) {
1041
+ if (!values.includes(value)) values.push(value);
1042
+ }
1043
+ function resolvePolymorphicProjectionSelection(contract, namespaceId, modelName, polyInfo, state) {
1044
+ if (state.selectedFields === void 0) return {
1045
+ baseSelectedFields: void 0,
1046
+ selectedMtiColumnsByTable: void 0,
1047
+ needsHiddenDiscriminator: false
1048
+ };
1049
+ const baseTableColumns = new Set(resolveTableColumns(contract, namespaceId, polyInfo.baseTable));
1050
+ const baseFieldToColumn = getFieldToColumnMap(contract, namespaceId, modelName);
1051
+ const variantFieldMaps = Array.from(polyInfo.variants.values(), (variant) => ({
1052
+ variant,
1053
+ columnToField: getCompleteColumnToFieldMap(contract, namespaceId, variant.modelName)
1054
+ }));
1055
+ const baseSelectedFields = [];
1056
+ const selectedMtiColumnsByTable = /* @__PURE__ */ new Map();
1057
+ let hasVariantOwnedSelection = false;
1058
+ for (const selectedField of state.selectedFields) {
1059
+ const baseColumn = baseFieldToColumn[selectedField] ?? (baseTableColumns.has(selectedField) ? selectedField : void 0);
1060
+ if (baseColumn !== void 0) appendUnique(baseSelectedFields, baseColumn);
1061
+ let matchedVariantField = false;
1062
+ for (const { variant, columnToField } of variantFieldMaps) for (const [column, field] of Object.entries(columnToField)) {
1063
+ if (selectedField !== field && selectedField !== column) continue;
1064
+ matchedVariantField = true;
1065
+ hasVariantOwnedSelection = true;
1066
+ if (variant.strategy === "sti") {
1067
+ appendUnique(baseSelectedFields, column);
1068
+ continue;
1069
+ }
1070
+ let selectedColumns = selectedMtiColumnsByTable.get(variant.table);
1071
+ if (selectedColumns === void 0) {
1072
+ selectedColumns = /* @__PURE__ */ new Set();
1073
+ selectedMtiColumnsByTable.set(variant.table, selectedColumns);
1074
+ }
1075
+ selectedColumns.add(column);
1076
+ }
1077
+ if (baseColumn === void 0 && !matchedVariantField) appendUnique(baseSelectedFields, selectedField);
1078
+ }
1079
+ return {
1080
+ baseSelectedFields,
1081
+ selectedMtiColumnsByTable,
1082
+ needsHiddenDiscriminator: state.variantName === void 0 && hasVariantOwnedSelection && !baseSelectedFields.includes(polyInfo.discriminatorColumn)
1083
+ };
1084
+ }
1085
+ function buildHiddenDiscriminatorProjection(contract, namespaceId, polyInfo, tableRef, needed) {
1086
+ if (!needed) return [];
1087
+ return [ProjectionItem.of(POLYMORPHIC_DISCRIMINATOR_ALIAS, ColumnRef.of(tableRef, polyInfo.discriminatorColumn), codecRefForStorageColumn(contract.storage, namespaceId, polyInfo.baseTable, polyInfo.discriminatorColumn))];
1088
+ }
1089
+ function createBoundaryExpr(tableName, entry) {
1090
+ return new BinaryExpr(entry.direction === "asc" ? "gt" : "lt", ColumnRef.of(tableName, entry.column), LiteralExpr.of(entry.value));
1091
+ }
1092
+ function buildLexicographicCursorWhere(tableName, entries) {
1093
+ const branches = entries.map((entry, index) => {
1094
+ const branchExprs = [];
1095
+ for (const prefixEntry of entries.slice(0, index)) branchExprs.push(BinaryExpr.eq(ColumnRef.of(tableName, prefixEntry.column), LiteralExpr.of(prefixEntry.value)));
1096
+ branchExprs.push(createBoundaryExpr(tableName, entry));
1097
+ if (branchExprs.length === 1) {
1098
+ const branch = branchExprs[0];
1099
+ assertDefined(branch, "cursor branch contains its boundary expression");
1100
+ return branch;
1101
+ }
1102
+ return AndExpr.of(branchExprs);
1103
+ });
1104
+ if (branches.length === 1) {
1105
+ const branch = branches[0];
1106
+ assertDefined(branch, "cursor expression contains its single branch");
1107
+ return branch;
1108
+ }
1109
+ return OrExpr.of(branches);
1110
+ }
1111
+ function buildCursorWhere(tableName, orderBy, cursor) {
1112
+ if (!cursor || !orderBy || orderBy.length === 0) return;
1113
+ const entries = [];
1114
+ for (const order of orderBy) {
1115
+ if (order.expr.kind !== "column-ref") continue;
1116
+ const column = order.expr.column;
1117
+ const value = cursor[column];
1118
+ if (value === void 0) throw ormError("ORM.CURSOR_VALUE_MISSING", `Missing cursor value for orderBy column "${column}"`, { meta: { column } });
1119
+ entries.push({
1120
+ column,
1121
+ direction: order.dir,
1122
+ value
1123
+ });
1124
+ }
1125
+ const firstEntry = entries[0];
1126
+ if (entries.length === 1 && firstEntry !== void 0) return createBoundaryExpr(tableName, firstEntry);
1127
+ return buildLexicographicCursorWhere(tableName, entries);
1128
+ }
1129
+ function createTableRefRemapper(fromTable, toTable) {
1130
+ return {
1131
+ columnRef: (col) => col.table === fromTable ? ColumnRef.of(toTable, col.column) : col,
1132
+ tableSource: (source) => {
1133
+ if (source.alias === fromTable) return TableSource.named(source.name, toTable, source.namespaceId);
1134
+ if (!source.alias && source.name === fromTable) return TableSource.named(source.name, toTable, source.namespaceId);
1135
+ return source;
1136
+ },
1137
+ eqColJoinOn: (on) => EqColJoinOn.of(on.left.table === fromTable ? ColumnRef.of(toTable, on.left.column) : on.left, on.right.table === fromTable ? ColumnRef.of(toTable, on.right.column) : on.right)
1138
+ };
1139
+ }
1140
+ function buildStateWhere(contract, tableName, state, options) {
1141
+ const filterTableName = options?.filterTableName;
1142
+ const cursorWhere = buildCursorWhere(filterTableName ?? tableName, state.orderBy, state.cursor);
1143
+ const remappedFilters = filterTableName && filterTableName !== tableName ? state.filters.map((filter) => filter.rewrite(createTableRefRemapper(filterTableName, tableName))) : state.filters;
1144
+ const boundCursorWhere = cursorWhere ? bindWhereExpr(contract, cursorWhere, options?.namespaceId) : void 0;
1145
+ const remappedCursorWhere = boundCursorWhere && filterTableName && filterTableName !== tableName ? boundCursorWhere.rewrite(createTableRefRemapper(filterTableName, tableName)) : boundCursorWhere;
1146
+ return combineWhereExprs(remappedCursorWhere ? [...remappedFilters, remappedCursorWhere] : remappedFilters);
1147
+ }
1148
+ function buildIncludeOrderArtifacts(relationName, rowAlias, childOrderBy) {
1149
+ if (!childOrderBy || childOrderBy.length === 0) return {
1150
+ childOrderBy: void 0,
1151
+ hiddenOrderProjection: [],
1152
+ aggregateOrderBy: void 0
1153
+ };
1154
+ const hiddenOrderProjection = childOrderBy.map((orderItem, index) => ProjectionItem.of(`${relationName}__order_${index}`, orderItem.expr));
1155
+ return {
1156
+ childOrderBy,
1157
+ hiddenOrderProjection,
1158
+ aggregateOrderBy: hiddenOrderProjection.map((projection, index) => {
1159
+ const orderItem = childOrderBy[index];
1160
+ if (!orderItem) throw new InternalError(`Missing include order metadata at index ${index}`);
1161
+ return new OrderByItem(ColumnRef.of(rowAlias, projection.alias), orderItem.dir);
1162
+ })
1163
+ };
1164
+ }
1165
+ /**
1166
+ * Wrap a base SELECT in a `ROW_NUMBER() OVER (PARTITION BY … ORDER BY …) = 1`
1167
+ * filter, implementing Prisma-style `.distinct(cols)` semantics: one
1168
+ * representative row per `(distinctColumnRefs)` group is kept; the rest
1169
+ * are dropped.
1170
+ *
1171
+ * Picking which row survives in each partition is governed by
1172
+ * `rankingOrderBy`. When the caller's `orderBy` doesn't fully order rows
1173
+ * within a partition (e.g. user wrote `.distinct('title')` with no
1174
+ * `orderBy`, or ties in their ordering), the choice is
1175
+ * implementation-defined — matching Prisma's documented nested-distinct
1176
+ * behaviour. Callers that want determinism should pass an `orderBy` that
1177
+ * is total within each partition.
1178
+ *
1179
+ * The wrapper forwards every column of `base.projection` through the
1180
+ * derived alias, so the wrapper's projection is byte-identical in alias
1181
+ * names — making this transparent to any outer query (`json_agg`,
1182
+ * correlated subquery, top-level SELECT) that consumes the SELECT.
1183
+ */
1184
+ function wrapWithRowNumberDedup(options) {
1185
+ const { base, distinctColumnRefs, rankingOrderBy, rankedAlias } = options;
1186
+ const rnAlias = "__prisma_distinct_rn";
1187
+ const effectiveOrderBy = rankingOrderBy.length > 0 ? rankingOrderBy : distinctColumnRefs.map((expr) => OrderByItem.asc(expr));
1188
+ const inner = base.withProjection([...base.projection, ProjectionItem.of(rnAlias, WindowFuncExpr.rowNumber({
1189
+ partitionBy: distinctColumnRefs,
1190
+ orderBy: effectiveOrderBy
1191
+ }))]);
1192
+ return SelectAst.from(DerivedTableSource.as(rankedAlias, inner)).withProjection(base.projection.map((item) => ProjectionItem.of(item.alias, ColumnRef.of(rankedAlias, item.alias), item.codec))).withWhere(BinaryExpr.eq(ColumnRef.of(rankedAlias, rnAlias), LiteralExpr.of(1)));
1193
+ }
1194
+ function localColumnsForRowInclude(include) {
1195
+ return include.through?.parentLocalColumns ?? [include.localColumn];
1196
+ }
1197
+ function resolveParentLocalRefs(parentSource, include, localColumns) {
1198
+ return localColumns.map((column) => {
1199
+ if (include.localTableName === parentSource.baseTableName) return ColumnRef.of(parentSource.tableRef, column);
1200
+ if (parentSource.variantColumnsProjected) return ColumnRef.of(parentSource.tableRef, `${include.localTableName}__${column}`);
1201
+ return ColumnRef.of(include.localTableName, column);
1202
+ });
1203
+ }
1204
+ function resolveChildTableSource(include, parentLocalRefs) {
1205
+ const alias = parentLocalRefs.some((ref) => ref.table === include.relatedTableName) ? `${include.relationName}__child` : void 0;
1206
+ return {
1207
+ alias,
1208
+ tableRef: alias ?? include.relatedTableName
1209
+ };
1210
+ }
1211
+ /**
1212
+ * Recursively build the correlated-subquery projections for the nested
1213
+ * includes attached to a child SELECT. Used by `buildIncludeChildRowsSelect`
1214
+ * to wire depth-2+ aggregates into the inner SELECT at each level.
1215
+ *
1216
+ * Each nested include contributes a single projection item whose
1217
+ * expression is a correlated subquery.
1218
+ */
1219
+ function buildNestedIncludeProjections(contract, parentSource, includes) {
1220
+ return includes.map((nested) => buildCorrelatedIncludeProjection(contract, parentSource, nested).projection);
1221
+ }
1222
+ /**
1223
+ * The aliases a level's nested includes contribute. Each such subquery
1224
+ * projects a JSON document — an object for a scalar include, an array of
1225
+ * objects for a row include — which is what tells the enclosing level to nest
1226
+ * the value rather than convert it.
1227
+ */
1228
+ function documentAliasesOf(nestedProjections) {
1229
+ return new Set(nestedProjections.map((item) => item.alias));
1230
+ }
1231
+ /**
1232
+ * Resolve the MTI variant joins + `variant_table__column` projection for an
1233
+ * include whose target model is polymorphic, mirroring the parent path in
1234
+ * `compileSelectWithIncludes`. The discriminator column and any STI
1235
+ * variant-specific columns live on the base table and reach the row through
1236
+ * the ordinary base-column projection (`buildProjection`); only the MTI
1237
+ * variant tables need a join.
1238
+ *
1239
+ * When the child base table is aliased (self-relations), `buildMtiJoins`
1240
+ * emits a join `ON` against the unaliased base table name, which would fall
1241
+ * out of scope. Remap it to the child alias — the same remap the row builder
1242
+ * already applies to `orderBy`/`where`.
1243
+ */
1244
+ function buildChildPolymorphismJoinsAndProjection(contract, include, childTableAlias, childTableRef) {
1245
+ const polyInfo = resolvePolymorphismInfo(contract, include.relatedNamespaceId, include.relatedModelName);
1246
+ if (!polyInfo) return {
1247
+ joins: [],
1248
+ projection: [],
1249
+ hiddenProjection: [],
1250
+ baseSelectedFields: include.nested.selectedFields
1251
+ };
1252
+ const selection = resolvePolymorphicProjectionSelection(contract, include.relatedNamespaceId, include.relatedModelName, polyInfo, include.nested);
1253
+ const { joins, projection } = buildMtiJoins(contract, include.relatedNamespaceId, polyInfo, include.nested.variantName, selection.selectedMtiColumnsByTable);
1254
+ const hiddenProjection = buildHiddenDiscriminatorProjection(contract, include.relatedNamespaceId, polyInfo, childTableRef, selection.needsHiddenDiscriminator);
1255
+ if (!childTableAlias) return {
1256
+ joins,
1257
+ projection,
1258
+ hiddenProjection,
1259
+ baseSelectedFields: selection.baseSelectedFields
1260
+ };
1261
+ const remapper = createTableRefRemapper(polyInfo.baseTable, childTableRef);
1262
+ return {
1263
+ joins: joins.map((join) => join.rewrite(remapper)),
1264
+ projection,
1265
+ hiddenProjection,
1266
+ baseSelectedFields: selection.baseSelectedFields
1267
+ };
1268
+ }
1269
+ function buildRequiredMtiJoinKeyProjection(contract, include) {
1270
+ const polyInfo = resolvePolymorphismInfo(contract, include.relatedNamespaceId, include.relatedModelName);
1271
+ if (!polyInfo) return [];
1272
+ const mtiTables = new Set(polyInfo.mtiVariants.map((variant) => variant.table));
1273
+ const aliases = /* @__PURE__ */ new Set();
1274
+ const projection = [];
1275
+ for (const nested of include.nested.includes) {
1276
+ if (!mtiTables.has(nested.localTableName)) continue;
1277
+ for (const column of localColumnsForRowInclude(nested)) {
1278
+ const alias = `${nested.localTableName}__${column}`;
1279
+ if (aliases.has(alias)) continue;
1280
+ aliases.add(alias);
1281
+ projection.push(ProjectionItem.of(alias, ColumnRef.of(nested.localTableName, column), codecRefForStorageColumn(contract.storage, include.relatedNamespaceId, nested.localTableName, column)));
1282
+ }
1283
+ }
1284
+ return projection;
1285
+ }
1286
+ function mergeProjectionByAlias(projection, additional) {
1287
+ const aliases = new Set(projection.map((item) => item.alias));
1288
+ const merged = [...projection];
1289
+ for (const item of additional) if (!aliases.has(item.alias)) {
1290
+ aliases.add(item.alias);
1291
+ merged.push(item);
1292
+ }
1293
+ return merged;
1294
+ }
1295
+ /**
1296
+ * Build the correlated WHERE and junction JOIN artifacts for a many-to-many
1297
+ * include. The resulting WHERE correlates the junction to the parent rows
1298
+ * (AND-ed across all column pairs for composite keys). The junction JOIN
1299
+ * connects child rows to the junction via the child columns.
1300
+ */
1301
+ function buildManyToManyJunctionArtifacts(parentLocalRefs, childTableRef, through) {
1302
+ const { table: junctionTable, parentColumns, childColumns, targetColumns, namespaceId } = through;
1303
+ invariant(childColumns.length === targetColumns.length, `M:N junction '${junctionTable}': childColumns (${childColumns.length}) and targetColumns (${targetColumns.length}) must have equal length`);
1304
+ invariant(parentColumns.length === parentLocalRefs.length, `M:N junction '${junctionTable}': parentColumns (${parentColumns.length}) and parentLocalColumns (${parentLocalRefs.length}) must have equal length`);
1305
+ const joinOnPairs = childColumns.map((junctionCol, i) => {
1306
+ const targetCol = targetColumns[i];
1307
+ assertDefined(targetCol, `M:N junction '${junctionTable}': missing target column at index ${i}`);
1308
+ return BinaryExpr.eq(ColumnRef.of(junctionTable, junctionCol), ColumnRef.of(childTableRef, targetCol));
1309
+ });
1310
+ const firstJoinPair = joinOnPairs[0];
1311
+ const joinOn = joinOnPairs.length === 1 && firstJoinPair ? firstJoinPair : AndExpr.of(joinOnPairs);
1312
+ const correlationPairs = parentColumns.map((junctionCol, i) => {
1313
+ const parentLocalRef = parentLocalRefs[i];
1314
+ assertDefined(parentLocalRef, `M:N junction '${junctionTable}': missing parent-local column ref at index ${i}`);
1315
+ return BinaryExpr.eq(ColumnRef.of(junctionTable, junctionCol), parentLocalRef);
1316
+ });
1317
+ const firstCorrelationPair = correlationPairs[0];
1318
+ return {
1319
+ whereExpr: correlationPairs.length === 1 && firstCorrelationPair ? firstCorrelationPair : AndExpr.of(correlationPairs),
1320
+ junctionJoin: JoinAst.inner(TableSource.named(junctionTable, void 0, namespaceId), joinOn, false)
1321
+ };
1322
+ }
1323
+ function buildIncludeChildRowsSelect(contract, parentSource, include) {
1324
+ const childState = include.nested;
1325
+ const parentLocalRefs = resolveParentLocalRefs(parentSource, include, localColumnsForRowInclude(include));
1326
+ const childSource = resolveChildTableSource(include, parentLocalRefs);
1327
+ const childTableAlias = childSource.alias;
1328
+ const childTableRef = childSource.tableRef;
1329
+ const rowsAlias = `${include.relationName}__rows`;
1330
+ const remappedChildOrderBy = childTableAlias && childState.orderBy ? childState.orderBy.map((item) => item.rewrite(createTableRefRemapper(include.relatedTableName, childTableRef))) : childState.orderBy;
1331
+ const { childOrderBy, hiddenOrderProjection, aggregateOrderBy } = buildIncludeOrderArtifacts(include.relationName, rowsAlias, remappedChildOrderBy);
1332
+ const childWhere = buildStateWhere(contract, childTableRef, childState, {
1333
+ filterTableName: include.relatedTableName,
1334
+ namespaceId: include.relatedNamespaceId
1335
+ });
1336
+ let whereExpr;
1337
+ let junctionJoins = [];
1338
+ if (include.through !== void 0) {
1339
+ const artifacts = buildManyToManyJunctionArtifacts(parentLocalRefs, childTableRef, include.through);
1340
+ whereExpr = childWhere ? AndExpr.of([artifacts.whereExpr, childWhere]) : artifacts.whereExpr;
1341
+ junctionJoins = [artifacts.junctionJoin];
1342
+ } else {
1343
+ const parentLocalRef = parentLocalRefs[0];
1344
+ assertDefined(parentLocalRef, `Include '${include.relationName}' has no parent-local column ref`);
1345
+ const joinExpr = BinaryExpr.eq(ColumnRef.of(childTableRef, include.targetColumn), parentLocalRef);
1346
+ whereExpr = childWhere ? AndExpr.of([joinExpr, childWhere]) : joinExpr;
1347
+ }
1348
+ if (childState.distinct !== void 0 && childState.distinct.length > 0 && childState.includes.length > 0) return buildDistinctNonLeafChildRowsSelect({
1349
+ contract,
1350
+ include,
1351
+ childTableAlias,
1352
+ childTableRef,
1353
+ rowsAlias,
1354
+ childOrderBy,
1355
+ hiddenOrderProjection,
1356
+ aggregateOrderBy,
1357
+ whereExpr,
1358
+ junctionJoins
1359
+ });
1360
+ const polyJoinsAndProjection = buildChildPolymorphismJoinsAndProjection(contract, include, childTableAlias, childTableRef);
1361
+ const scalarProjection = buildProjection(contract, include.relatedNamespaceId, include.relatedTableName, polyJoinsAndProjection.baseSelectedFields, childTableRef);
1362
+ const nestedProjections = buildNestedIncludeProjections(contract, {
1363
+ baseTableName: include.relatedTableName,
1364
+ tableRef: childTableRef,
1365
+ variantColumnsProjected: false
1366
+ }, childState.includes);
1367
+ const childProjection = [
1368
+ ...scalarProjection,
1369
+ ...polyJoinsAndProjection.projection,
1370
+ ...polyJoinsAndProjection.hiddenProjection,
1371
+ ...nestedProjections
1372
+ ];
1373
+ let childRows = SelectAst.from(tableSourceForContract(contract, include.relatedNamespaceId, include.relatedTableName, childTableAlias)).withProjection([...childProjection, ...hiddenOrderProjection]).withWhere(whereExpr);
1374
+ if (polyJoinsAndProjection.joins.length > 0) childRows = childRows.withJoins([...polyJoinsAndProjection.joins]);
1375
+ if (junctionJoins.length > 0) childRows = childRows.withJoins(junctionJoins);
1376
+ if (childState.distinctOn && childState.distinctOn.length > 0) {
1377
+ childRows = childRows.withDistinctOn(childState.distinctOn.map((column) => ColumnRef.of(childTableRef, column)));
1378
+ if (childOrderBy) childRows = childRows.withOrderBy(childOrderBy);
1379
+ } else if (childState.distinct && childState.distinct.length > 0) {
1380
+ const rankedAlias = `${include.relationName}__distinct`;
1381
+ childRows = wrapWithRowNumberDedup({
1382
+ base: childRows,
1383
+ distinctColumnRefs: childState.distinct.map((column) => ColumnRef.of(childTableRef, column)),
1384
+ rankingOrderBy: childOrderBy ?? [],
1385
+ rankedAlias
1386
+ });
1387
+ if (childOrderBy) childRows = childRows.withOrderBy(childOrderBy.map((item, index) => new OrderByItem(ColumnRef.of(rankedAlias, `${include.relationName}__order_${index}`), item.dir)));
1388
+ } else if (childOrderBy) childRows = childRows.withOrderBy(childOrderBy);
1389
+ if (childState.limit !== void 0) childRows = childRows.withLimit(childState.limit);
1390
+ if (childState.offset !== void 0) childRows = childRows.withOffset(childState.offset);
1391
+ return {
1392
+ childRows,
1393
+ childProjection,
1394
+ documentAliases: documentAliasesOf(nestedProjections),
1395
+ rowsAlias,
1396
+ aggregateOrderBy
1397
+ };
1398
+ }
1399
+ function buildDistinctNonLeafChildRowsSelect(options) {
1400
+ const { contract, include, childTableAlias, childTableRef, rowsAlias, childOrderBy, hiddenOrderProjection, aggregateOrderBy, whereExpr, junctionJoins } = options;
1401
+ const childState = include.nested;
1402
+ const grandchildJoinColumns = Array.from(new Set(childState.includes.flatMap((nested) => nested.localTableName === include.relatedTableName ? localColumnsForRowInclude(nested) : [])));
1403
+ const { selectedForQuery } = augmentSelectionForJoinColumns(childState.selectedFields, grandchildJoinColumns);
1404
+ const visiblePolyProjection = buildChildPolymorphismJoinsAndProjection(contract, include, childTableAlias, childTableRef);
1405
+ const queryPolyProjection = buildChildPolymorphismJoinsAndProjection(contract, {
1406
+ ...include,
1407
+ nested: {
1408
+ ...childState,
1409
+ selectedFields: selectedForQuery
1410
+ }
1411
+ }, childTableAlias, childTableRef);
1412
+ const innerScalarProjection = buildProjection(contract, include.relatedNamespaceId, include.relatedTableName, queryPolyProjection.baseSelectedFields, childTableRef);
1413
+ const innerMtiProjection = mergeProjectionByAlias(queryPolyProjection.projection, buildRequiredMtiJoinKeyProjection(contract, include));
1414
+ let baseInner = SelectAst.from(tableSourceForContract(contract, include.relatedNamespaceId, include.relatedTableName, childTableAlias)).withProjection([
1415
+ ...innerScalarProjection,
1416
+ ...innerMtiProjection,
1417
+ ...queryPolyProjection.hiddenProjection,
1418
+ ...hiddenOrderProjection
1419
+ ]).withWhere(whereExpr);
1420
+ const distinctExtraJoins = [...queryPolyProjection.joins, ...junctionJoins];
1421
+ if (distinctExtraJoins.length > 0) baseInner = baseInner.withJoins(distinctExtraJoins);
1422
+ const distinctColumns = childState.distinct;
1423
+ if (distinctColumns === void 0 || distinctColumns.length === 0) throw new InternalError("buildDistinctNonLeafChildRowsSelect requires a non-empty `distinct` selection");
1424
+ const rankedAlias = `${include.relationName}__ranked`;
1425
+ let innerSelect = wrapWithRowNumberDedup({
1426
+ base: baseInner,
1427
+ distinctColumnRefs: distinctColumns.map((column) => ColumnRef.of(childTableRef, column)),
1428
+ rankingOrderBy: childOrderBy ?? [],
1429
+ rankedAlias
1430
+ });
1431
+ if (childOrderBy) innerSelect = innerSelect.withOrderBy(childOrderBy.map((item, index) => new OrderByItem(ColumnRef.of(rankedAlias, `${include.relationName}__order_${index}`), item.dir)));
1432
+ if (childState.limit !== void 0) innerSelect = innerSelect.withLimit(childState.limit);
1433
+ if (childState.offset !== void 0) innerSelect = innerSelect.withOffset(childState.offset);
1434
+ const distinctAlias = `${include.relationName}__distinct`;
1435
+ const outerScalarProjection = buildProjection(contract, include.relatedNamespaceId, include.relatedTableName, visiblePolyProjection.baseSelectedFields, distinctAlias);
1436
+ const outerNestedProjections = buildNestedIncludeProjections(contract, {
1437
+ baseTableName: include.relatedTableName,
1438
+ tableRef: distinctAlias,
1439
+ variantColumnsProjected: true
1440
+ }, childState.includes);
1441
+ const outerPolyProjection = visiblePolyProjection.projection.map((proj) => ProjectionItem.of(proj.alias, ColumnRef.of(distinctAlias, proj.alias), proj.codec));
1442
+ const outerHiddenProjection = visiblePolyProjection.hiddenProjection.map((proj) => ProjectionItem.of(proj.alias, ColumnRef.of(distinctAlias, proj.alias), proj.codec));
1443
+ const outerHiddenOrderProjection = hiddenOrderProjection.map((proj) => ProjectionItem.of(proj.alias, ColumnRef.of(distinctAlias, proj.alias), proj.codec));
1444
+ const childProjection = [
1445
+ ...outerScalarProjection,
1446
+ ...outerPolyProjection,
1447
+ ...outerHiddenProjection,
1448
+ ...outerNestedProjections
1449
+ ];
1450
+ return {
1451
+ childRows: SelectAst.from(DerivedTableSource.as(distinctAlias, innerSelect)).withProjection([...childProjection, ...outerHiddenOrderProjection]),
1452
+ childProjection,
1453
+ documentAliases: documentAliasesOf(outerNestedProjections),
1454
+ rowsAlias,
1455
+ aggregateOrderBy
1456
+ };
1457
+ }
1458
+ /**
1459
+ * Build the inner SELECT for a scalar include reducer (`count` /
1460
+ * `sum` / `avg` / `min` / `max`).
1461
+ *
1462
+ * Emits one row containing `json_build_object('value', AGG(...))`
1463
+ * over the child relation correlated to the parent via the FK. The
1464
+ * JSON wrap lets the value flow through the existing include-payload
1465
+ * decoder unchanged (it JSON.parses the column and the scalar branch
1466
+ * pulls `.value` out).
1467
+ *
1468
+ * The refine state's pipeline composes through to the aggregate's
1469
+ * input set: `where` / `orderBy` / `take` / `skip` / `distinct` shape
1470
+ * the rows the aggregate sees, matching the natural compositional
1471
+ * semantic of
1472
+ *
1473
+ * `db.User.include('posts', p => p.where(W).take(N).count()) // ≤ N`
1474
+ *
1475
+ * When `take` / `skip` / `distinct` is set, the aggregate's input
1476
+ * cannot just be the bare correlated table — a top-level `LIMIT` on
1477
+ * the aggregating SELECT only trims the (already one-row) output, not
1478
+ * the rows being aggregated. We therefore wrap the source in a
1479
+ * derived SELECT that materialises the shaped row set, then
1480
+ * aggregate over that. `orderBy` alone (no `take` / `skip` /
1481
+ * `distinct`) is dropped at the SQL level since reordering does not
1482
+ * change which rows are aggregated.
1483
+ */
1484
+ function buildIncludeChildScalarSelect(contract, parentSource, include, scalar) {
1485
+ const parentLocalRefs = resolveParentLocalRefs(parentSource, include, [include.localColumn]);
1486
+ const parentLocalRef = parentLocalRefs[0];
1487
+ assertDefined(parentLocalRef, `Include '${include.relationName}' has no parent-local column ref`);
1488
+ const childSource = resolveChildTableSource(include, parentLocalRefs);
1489
+ const childTableAlias = childSource.alias;
1490
+ const childTableRef = childSource.tableRef;
1491
+ const state = scalar.state;
1492
+ const joinExpr = BinaryExpr.eq(ColumnRef.of(childTableRef, include.targetColumn), parentLocalRef);
1493
+ const childWhere = buildStateWhere(contract, childTableRef, state, {
1494
+ filterTableName: include.relatedTableName,
1495
+ namespaceId: include.relatedNamespaceId
1496
+ });
1497
+ const whereExpr = childWhere ? AndExpr.of([joinExpr, childWhere]) : joinExpr;
1498
+ const remappedOrderBy = childTableAlias && state.orderBy ? state.orderBy.map((item) => item.rewrite(createTableRefRemapper(include.relatedTableName, childTableRef))) : state.orderBy;
1499
+ const hasPagination = state.limit !== void 0 || state.offset !== void 0;
1500
+ const hasDistinct = state.distinct !== void 0 && state.distinct.length > 0 || state.distinctOn !== void 0 && state.distinctOn.length > 0;
1501
+ if (!(hasPagination || hasDistinct)) {
1502
+ const aggregateExpr = buildIncludeAggregateExpr(scalar, childTableRef);
1503
+ const jsonObjectExpr = JsonObjectExpr.fromEntries([JsonObjectExpr.entry("value", jsonEntryProjection(aggregateExpr, {}))]);
1504
+ return SelectAst.from(tableSourceForContract(contract, include.relatedNamespaceId, include.relatedTableName, childTableAlias)).withProjection([ProjectionItem.of(include.relationName, jsonObjectExpr)]).withWhere(whereExpr);
1505
+ }
1506
+ const innerAlias = `${include.relationName}__scalar`;
1507
+ const hiddenOrderProjection = state.distinct !== void 0 && state.distinct.length > 0 && remappedOrderBy !== void 0 && remappedOrderBy.length > 0 ? remappedOrderBy.map((item, index) => ProjectionItem.of(`${include.relationName}__order_${index}`, item.expr)) : [];
1508
+ const innerProjection = [...scalar.column !== void 0 ? [ProjectionItem.of(scalar.column, ColumnRef.of(childTableRef, scalar.column))] : [ProjectionItem.of("__row", LiteralExpr.of(1))], ...hiddenOrderProjection];
1509
+ let inner = SelectAst.from(tableSourceForContract(contract, include.relatedNamespaceId, include.relatedTableName, childTableAlias)).withProjection(innerProjection).withWhere(whereExpr);
1510
+ if (state.distinctOn !== void 0 && state.distinctOn.length > 0) {
1511
+ inner = inner.withDistinctOn(state.distinctOn.map((column) => ColumnRef.of(childTableRef, column)));
1512
+ if (remappedOrderBy !== void 0 && remappedOrderBy.length > 0) inner = inner.withOrderBy(remappedOrderBy);
1513
+ } else if (state.distinct !== void 0 && state.distinct.length > 0) {
1514
+ const rankedAlias = `${include.relationName}__scalar_distinct`;
1515
+ inner = wrapWithRowNumberDedup({
1516
+ base: inner,
1517
+ distinctColumnRefs: state.distinct.map((column) => ColumnRef.of(childTableRef, column)),
1518
+ rankingOrderBy: remappedOrderBy ?? [],
1519
+ rankedAlias
1520
+ });
1521
+ if (remappedOrderBy !== void 0 && remappedOrderBy.length > 0) inner = inner.withOrderBy(remappedOrderBy.map((item, index) => new OrderByItem(ColumnRef.of(rankedAlias, `${include.relationName}__order_${index}`), item.dir)));
1522
+ } else if (remappedOrderBy !== void 0 && remappedOrderBy.length > 0) inner = inner.withOrderBy(remappedOrderBy);
1523
+ if (state.limit !== void 0) inner = inner.withLimit(state.limit);
1524
+ if (state.offset !== void 0) inner = inner.withOffset(state.offset);
1525
+ const outerAggregateExpr = buildIncludeAggregateExpr(scalar, innerAlias);
1526
+ const outerJsonObjectExpr = JsonObjectExpr.fromEntries([JsonObjectExpr.entry("value", jsonEntryProjection(outerAggregateExpr, {}))]);
1527
+ return SelectAst.from(DerivedTableSource.as(innerAlias, inner)).withProjection([ProjectionItem.of(include.relationName, outerJsonObjectExpr)]);
1528
+ }
1529
+ function buildIncludeAggregateExpr(scalar, childTableRef) {
1530
+ if (scalar.fn === "count") return AggregateExpr.count();
1531
+ if (scalar.column === void 0) throw ormError("ORM.AGGREGATE_SELECTOR_INVALID", `Aggregate selector "${scalar.fn}" requires a column`, { meta: { fn: scalar.fn } });
1532
+ const columnRef = ColumnRef.of(childTableRef, scalar.column);
1533
+ switch (scalar.fn) {
1534
+ case "sum": return AggregateExpr.sum(columnRef);
1535
+ case "avg": return AggregateExpr.avg(columnRef);
1536
+ case "min": return AggregateExpr.min(columnRef);
1537
+ case "max": return AggregateExpr.max(columnRef);
1538
+ default: return assertNever(scalar.fn);
1539
+ }
1540
+ }
1541
+ /**
1542
+ * Build the inner SELECT for a `combine({ a, b, ... })` include.
1543
+ *
1544
+ * Each branch produces a self-contained SELECT projecting one row
1545
+ * with one column aliased to the relation name. The branches are
1546
+ * stitched together as cross-joined derived tables (FROM <first>
1547
+ * INNER JOIN <second> ON TRUE ...), and the outer projection packs
1548
+ * them into a single `json_build_object` keyed by branch name. The
1549
+ * resulting subquery emits exactly one row per parent row containing
1550
+ * the combined JSON — embedded as a correlated subquery in the outer
1551
+ * projection.
1552
+ *
1553
+ * Row branches reuse the standalone row-include builder; scalar
1554
+ * branches reuse `buildIncludeChildScalarSelect` — the `{value: ...}`
1555
+ * envelope survives into the combined JSON and the decoder unwraps
1556
+ * it per scalar branch. Distinct/take/skip semantics inside a row
1557
+ * branch fan out naturally because the row builder is invoked with
1558
+ * a synthetic IncludeExpr whose `nested` is the branch's state.
1559
+ */
1560
+ function buildIncludeChildCombineSelect(contract, parentSource, include, branches) {
1561
+ const branchEntries = Object.entries(branches);
1562
+ if (branchEntries.length === 0) throw ormError("ORM.INCLUDE_INVALID", `combine() include "${include.relationName}" has no branches`, { meta: { relation: include.relationName } });
1563
+ const compiledBranches = branchEntries.map(([name, branch]) => ({
1564
+ name,
1565
+ alias: `${include.relationName}__combine__${name}`,
1566
+ select: buildIncludeChildCombineBranchSelect(contract, parentSource, include, branch)
1567
+ }));
1568
+ const jsonObjectExpr = JsonObjectExpr.fromEntries(compiledBranches.map((branch) => JsonObjectExpr.entry(branch.name, jsonEntryProjection(ColumnRef.of(branch.alias, include.relationName), { document: true }))));
1569
+ const [firstBranch, ...restBranches] = compiledBranches;
1570
+ if (!firstBranch) throw new InternalError(`combine() include "${include.relationName}" has no branches`);
1571
+ const joins = restBranches.map((branch) => JoinAst.inner(DerivedTableSource.as(branch.alias, branch.select), AndExpr.true(), false));
1572
+ return SelectAst.from(DerivedTableSource.as(firstBranch.alias, firstBranch.select)).withProjection([ProjectionItem.of(include.relationName, jsonObjectExpr)]).withJoins(joins);
1573
+ }
1574
+ /**
1575
+ * Compile one branch of a `combine({ ... })` into a SelectAst that
1576
+ * projects exactly one row with one column aliased to the parent
1577
+ * relation name. Dispatches to the standalone scalar / row builders
1578
+ * with the branch's state spliced into a synthetic IncludeExpr.
1579
+ */
1580
+ function buildIncludeChildCombineBranchSelect(contract, parentSource, include, branch) {
1581
+ if (branch.kind === "scalar") return buildIncludeChildScalarSelect(contract, parentSource, include, branch.selector);
1582
+ return buildIncludeChildRowsAggregateSelect(contract, parentSource, {
1583
+ ...include,
1584
+ nested: branch.state,
1585
+ scalar: void 0,
1586
+ combine: void 0
1587
+ });
1588
+ }
1589
+ /**
1590
+ * Internal helper: build the inner aggregate SELECT that `json_agg`s
1591
+ * child rows into a single JSON-array column aliased to the relation
1592
+ * name. Used by both the standalone row correlated-subquery path and
1593
+ * by combine's row branches.
1594
+ */
1595
+ function buildIncludeChildRowsAggregateSelect(contract, parentSource, include) {
1596
+ const { childRows, childProjection, documentAliases, rowsAlias, aggregateOrderBy } = buildIncludeChildRowsSelect(contract, parentSource, include);
1597
+ const jsonObjectExpr = JsonObjectExpr.fromEntries(childProjection.map((item) => JsonObjectExpr.entry(item.alias, jsonEntryProjection(ColumnRef.of(rowsAlias, item.alias), {
1598
+ codec: item.codec,
1599
+ document: documentAliases.has(item.alias)
1600
+ }))));
1601
+ return SelectAst.from(DerivedTableSource.as(rowsAlias, childRows)).withProjection([ProjectionItem.of(include.relationName, JsonArrayAggExpr.of(jsonEntryProjection(jsonObjectExpr, { document: true }), "emptyArray", aggregateOrderBy))]);
1602
+ }
1603
+ function buildCorrelatedIncludeProjection(contract, parentSource, include) {
1604
+ if (include.scalar) {
1605
+ const scalarSelect = buildIncludeChildScalarSelect(contract, parentSource, include, include.scalar);
1606
+ return { projection: ProjectionItem.of(include.relationName, SubqueryExpr.of(scalarSelect)) };
1607
+ }
1608
+ if (include.combine) {
1609
+ const combineSelect = buildIncludeChildCombineSelect(contract, parentSource, include, include.combine);
1610
+ return { projection: ProjectionItem.of(include.relationName, SubqueryExpr.of(combineSelect)) };
1611
+ }
1612
+ const aggregateQuery = buildIncludeChildRowsAggregateSelect(contract, parentSource, include);
1613
+ return { projection: ProjectionItem.of(include.relationName, SubqueryExpr.of(aggregateQuery)) };
1614
+ }
1615
+ function buildSelectAst(contract, tableName, state, options) {
1616
+ const namespaceId = options.namespaceId;
1617
+ const projection = [...buildProjection(contract, namespaceId, tableName, state.selectedFields, tableName), ...options.includeProjection ?? []];
1618
+ const where = options.where ?? buildStateWhere(contract, tableName, state, { namespaceId });
1619
+ const usesRowNumberDistinct = state.distinct !== void 0 && state.distinct.length > 0;
1620
+ const fromSource = usesRowNumberDistinct ? DerivedTableSource.as(tableName, buildTopLevelDistinctRankedInner(contract, namespaceId, tableName, state, where)) : tableSourceForContract(contract, namespaceId, tableName);
1621
+ let ast = SelectAst.from(fromSource).withProjection(projection);
1622
+ if (usesRowNumberDistinct) ast = ast.withWhere(BinaryExpr.eq(ColumnRef.of(tableName, "__prisma_distinct_rn"), LiteralExpr.of(1)));
1623
+ else if (where) ast = ast.withWhere(where);
1624
+ if (state.orderBy) ast = ast.withOrderBy(state.orderBy);
1625
+ if (state.selectedFields === void 0) ast = ast.withSelectAllIntent({ table: tableName });
1626
+ if (state.distinctOn && state.distinctOn.length > 0) ast = ast.withDistinctOn(state.distinctOn.map((column) => ColumnRef.of(tableName, column)));
1627
+ if (state.limit !== void 0) ast = ast.withLimit(state.limit);
1628
+ if (state.offset !== void 0) ast = ast.withOffset(state.offset);
1629
+ if (options.joins && options.joins.length > 0) ast = ast.withJoins(options.joins);
1630
+ return ast;
1631
+ }
1632
+ function buildTopLevelDistinctRankedInner(contract, namespaceId, tableName, state, where) {
1633
+ const distinctColumns = state.distinct;
1634
+ if (distinctColumns === void 0 || distinctColumns.length === 0) throw new InternalError("buildTopLevelDistinctRankedInner called without `state.distinct`");
1635
+ const allColsProjection = resolveTableColumns(contract, namespaceId, tableName).map((column) => ProjectionItem.of(column, ColumnRef.of(tableName, column)));
1636
+ const distinctColumnRefs = distinctColumns.map((column) => ColumnRef.of(tableName, column));
1637
+ const rankingOrderBy = state.orderBy && state.orderBy.length > 0 ? state.orderBy : distinctColumnRefs.map((expr) => OrderByItem.asc(expr));
1638
+ let inner = SelectAst.from(tableSourceForContract(contract, namespaceId, tableName)).withProjection([...allColsProjection, ProjectionItem.of("__prisma_distinct_rn", WindowFuncExpr.rowNumber({
1639
+ partitionBy: distinctColumnRefs,
1640
+ orderBy: rankingOrderBy
1641
+ }))]);
1642
+ if (where) inner = inner.withWhere(where);
1643
+ return inner;
1644
+ }
1645
+ function buildMtiJoins(contract, namespaceId, polyInfo, variantName, selectedColumnsByTable) {
1646
+ const joins = [];
1647
+ const projection = [];
1648
+ const pkColumn = resolvePrimaryKeyColumn(contract, namespaceId, polyInfo.baseTable);
1649
+ const variantsToJoin = variantName ? polyInfo.mtiVariants.filter((v) => v.modelName === variantName) : polyInfo.mtiVariants;
1650
+ for (const variant of variantsToJoin) {
1651
+ const joinType = variantName ? "inner" : "left";
1652
+ const joinOn = EqColJoinOn.of(ColumnRef.of(polyInfo.baseTable, pkColumn), ColumnRef.of(variant.table, pkColumn));
1653
+ const join = joinType === "inner" ? JoinAst.inner(tableSourceForContract(contract, namespaceId, variant.table), joinOn) : JoinAst.left(tableSourceForContract(contract, namespaceId, variant.table), joinOn);
1654
+ joins.push(join);
1655
+ const variantColumns = resolveTableColumns(contract, namespaceId, variant.table);
1656
+ const selectedVariantColumns = selectedColumnsByTable?.get(variant.table);
1657
+ for (const col of variantColumns) {
1658
+ if (col === pkColumn) continue;
1659
+ if (selectedColumnsByTable !== void 0 && selectedVariantColumns?.has(col) !== true) continue;
1660
+ const alias = `${variant.table}__${col}`;
1661
+ projection.push(ProjectionItem.of(alias, ColumnRef.of(variant.table, col), codecRefForStorageColumn(contract.storage, namespaceId, variant.table, col)));
1662
+ }
1663
+ }
1664
+ return {
1665
+ joins,
1666
+ projection
1667
+ };
1668
+ }
1669
+ function compileSelect(contract, namespaceId, tableName, state, modelName) {
1670
+ const polyInfo = modelName ? resolvePolymorphismInfo(contract, namespaceId, modelName) : void 0;
1671
+ const selection = polyInfo && modelName ? resolvePolymorphicProjectionSelection(contract, namespaceId, modelName, polyInfo, state) : void 0;
1672
+ const projectionState = selection ? {
1673
+ ...state,
1674
+ selectedFields: selection.baseSelectedFields
1675
+ } : state;
1676
+ const mtiArtifacts = polyInfo && polyInfo.mtiVariants.length > 0 ? buildMtiJoins(contract, namespaceId, polyInfo, state.variantName, selection?.selectedMtiColumnsByTable) : void 0;
1677
+ const hiddenProjection = polyInfo && selection ? buildHiddenDiscriminatorProjection(contract, namespaceId, polyInfo, tableName, selection.needsHiddenDiscriminator) : [];
1678
+ const ast = buildSelectAst(contract, tableName, {
1679
+ ...projectionState,
1680
+ includes: []
1681
+ }, {
1682
+ joins: mtiArtifacts?.joins ?? [],
1683
+ includeProjection: [...mtiArtifacts?.projection ?? [], ...hiddenProjection],
1684
+ namespaceId
1685
+ });
1686
+ const { params } = deriveParamsFromAst(ast);
1687
+ return buildOrmQueryPlan(contract, ast, params, state.annotations);
1688
+ }
1689
+ function compileSelectWithIncludes(contract, namespaceId, tableName, state, modelName) {
1690
+ const includeJoins = [];
1691
+ const includeProjection = [];
1692
+ const topLevelWhere = buildStateWhere(contract, tableName, state, { namespaceId });
1693
+ const polyInfo = modelName ? resolvePolymorphismInfo(contract, namespaceId, modelName) : void 0;
1694
+ const selection = polyInfo && modelName ? resolvePolymorphicProjectionSelection(contract, namespaceId, modelName, polyInfo, state) : void 0;
1695
+ const projectionState = selection ? {
1696
+ ...state,
1697
+ selectedFields: selection.baseSelectedFields
1698
+ } : state;
1699
+ if (polyInfo && selection) {
1700
+ if (polyInfo.mtiVariants.length > 0) {
1701
+ const mtiArtifacts = buildMtiJoins(contract, namespaceId, polyInfo, state.variantName, selection.selectedMtiColumnsByTable);
1702
+ includeJoins.push(...mtiArtifacts.joins);
1703
+ includeProjection.push(...mtiArtifacts.projection);
1704
+ }
1705
+ includeProjection.push(...buildHiddenDiscriminatorProjection(contract, namespaceId, polyInfo, tableName, selection.needsHiddenDiscriminator));
1706
+ }
1707
+ const parentSource = {
1708
+ baseTableName: tableName,
1709
+ tableRef: tableName,
1710
+ variantColumnsProjected: false
1711
+ };
1712
+ for (const include of state.includes) {
1713
+ const artifact = buildCorrelatedIncludeProjection(contract, parentSource, include);
1714
+ includeProjection.push(artifact.projection);
1715
+ }
1716
+ const ast = buildSelectAst(contract, tableName, {
1717
+ ...projectionState,
1718
+ includes: []
1719
+ }, {
1720
+ joins: includeJoins,
1721
+ includeProjection,
1722
+ namespaceId,
1723
+ ...ifDefined("where", topLevelWhere)
1724
+ });
1725
+ const { params } = deriveParamsFromAst(ast);
1726
+ return buildOrmQueryPlan(contract, ast, params, state.annotations);
1727
+ }
1728
+ function emptyState() {
1729
+ return {
1730
+ filters: [],
1731
+ includes: [],
1732
+ orderBy: void 0,
1733
+ cursor: void 0,
1734
+ distinct: void 0,
1735
+ distinctOn: void 0,
1736
+ selectedFields: void 0,
1737
+ limit: void 0,
1738
+ offset: void 0,
1739
+ variantName: void 0,
1740
+ annotations: /* @__PURE__ */ new Map()
1741
+ };
1742
+ }
1743
+ function param(codec, value) {
1744
+ if (codec === void 0) return ParamRef.of(value);
1745
+ return ParamRef.of(value, { codec });
1746
+ }
1747
+ function paramList(codec, values) {
1748
+ return ListExpression.of(values.map((value) => param(codec, value)));
1749
+ }
1750
+ function scalarComparisonMethod(op) {
1751
+ return ((left, codec) => (value) => {
1752
+ if (value === null && (op === "eq" || op === "neq")) return op === "eq" ? NullCheckExpr.isNull(left) : NullCheckExpr.isNotNull(left);
1753
+ return new BinaryExpr(op, left, param(codec, value));
1754
+ });
1755
+ }
1756
+ function listComparisonMethod(op) {
1757
+ return ((left, codec) => (values) => new BinaryExpr(op, left, paramList(codec, values)));
1758
+ }
1759
+ /**
1760
+ * Declares trait requirements and runtime factory for each comparison method.
1761
+ *
1762
+ * - `traits: []` means "no trait required" — always available
1763
+ * - Multi-trait: `traits: ['equality', 'order']` means BOTH traits are required
1764
+ */
1765
+ const COMPARISON_METHODS_META = {
1766
+ eq: {
1767
+ traits: ["equality"],
1768
+ create: scalarComparisonMethod("eq")
1769
+ },
1770
+ neq: {
1771
+ traits: ["equality"],
1772
+ create: scalarComparisonMethod("neq")
1773
+ },
1774
+ in: {
1775
+ traits: ["equality"],
1776
+ create: listComparisonMethod("in")
1777
+ },
1778
+ notIn: {
1779
+ traits: ["equality"],
1780
+ create: listComparisonMethod("notIn")
1781
+ },
1782
+ gt: {
1783
+ traits: ["order"],
1784
+ create: scalarComparisonMethod("gt")
1785
+ },
1786
+ lt: {
1787
+ traits: ["order"],
1788
+ create: scalarComparisonMethod("lt")
1789
+ },
1790
+ gte: {
1791
+ traits: ["order"],
1792
+ create: scalarComparisonMethod("gte")
1793
+ },
1794
+ lte: {
1795
+ traits: ["order"],
1796
+ create: scalarComparisonMethod("lte")
1797
+ },
1798
+ like: {
1799
+ traits: ["textual"],
1800
+ create: scalarComparisonMethod("like")
1801
+ },
1802
+ asc: {
1803
+ traits: ["order"],
1804
+ create: (left) => () => OrderByItem.asc(left)
1805
+ },
1806
+ desc: {
1807
+ traits: ["order"],
1808
+ create: (left) => () => OrderByItem.desc(left)
1809
+ },
1810
+ isNull: {
1811
+ traits: [],
1812
+ create: (left) => () => NullCheckExpr.isNull(left)
1813
+ },
1814
+ isNotNull: {
1815
+ traits: [],
1816
+ create: (left) => () => NullCheckExpr.isNotNull(left)
1817
+ }
1818
+ };
1819
+ function dispatchCollectionRows(options) {
1820
+ const { context, runtime, state, tableName, modelName, namespaceId } = options;
1821
+ const { contract } = context;
1822
+ const polyInfo = resolvePolymorphismInfo(contract, namespaceId, modelName);
1823
+ if (state.includes.length === 0) return mapResultRows(executeQueryPlan(runtime, compileSelect(contract, namespaceId, tableName, state, modelName)), polyInfo ? (rawRow) => blindCast(mapPolymorphicRow(contract, namespaceId, modelName, polyInfo, rawRow, state.variantName)) : (rawRow) => blindCast(mapStorageRowToModelFields(contract, namespaceId, modelName, rawRow)));
1824
+ return dispatchWithIncludes(options);
1825
+ }
1826
+ function dispatchWithIncludes(options) {
1827
+ const { context, runtime, state, tableName, modelName, namespaceId } = options;
1828
+ const { contract } = context;
1829
+ const generator = async function* () {
1830
+ const { scope, release } = await acquireRuntimeScope(runtime);
1831
+ try {
1832
+ const parentRowsRaw = await executeQueryPlan(scope, compileSelectWithIncludes(contract, namespaceId, tableName, state, modelName)).toArray();
1833
+ if (parentRowsRaw.length === 0) return;
1834
+ const polyInfo = resolvePolymorphismInfo(contract, namespaceId, modelName);
1835
+ const parentRows = parentRowsRaw.map((row) => {
1836
+ return {
1837
+ raw: row,
1838
+ mapped: polyInfo ? mapPolymorphicRow(contract, namespaceId, modelName, polyInfo, row, state.variantName) : mapStorageRowToModelFields(contract, namespaceId, modelName, row)
1839
+ };
1840
+ });
1841
+ for (const parent of parentRows) for (const include of state.includes) parent.mapped[include.relationName] = await decodeIncludePayload(contract, context, include, parent.raw[include.relationName]);
1842
+ for (const row of parentRows) yield blindCast(row.mapped);
1843
+ } finally {
1844
+ if (release) await release();
1845
+ }
1846
+ };
1847
+ return new AsyncIterableResult(generator());
1848
+ }
1849
+ /**
1850
+ * Reload the rows a mutation just wrote (create / createAll / update /
1851
+ * updateAll / upsert) through the read-path dispatch, so `.include()`
1852
+ * relations resolve via the exact same correlated-subquery builder,
1853
+ * decoding, and polymorphism mapping a read query uses — there is no
1854
+ * parallel mutation read-back implementation.
1855
+ *
1856
+ * The mutation returns only its identity columns (PK / unique); this
1857
+ * re-selects those rows with the caller's projection + includes, keyed
1858
+ * by `identity IN (...)`. One round-trip regardless of row count or
1859
+ * include depth. The read-back observes the just-written rows because
1860
+ * it runs on the same runtime — and therefore the same transaction —
1861
+ * the mutation ran on.
1862
+ *
1863
+ * Delete read-back does NOT come through here: a parent-anchored
1864
+ * include query can't observe an already-deleted row, so delete reads
1865
+ * its snapshot before issuing the DELETE (see `collection.ts`).
1866
+ */
1867
+ function reloadMutationRowsByIdentities(options) {
1868
+ const { context, runtime, tableName, modelName, namespaceId, identityRows, selectedFields, includes } = options;
1869
+ const { contract } = context;
1870
+ if (identityRows.length === 0) return emptyResult();
1871
+ const identityColumns = resolveRowIdentityColumns(contract, namespaceId, tableName);
1872
+ if (identityColumns.length === 0) throw ormError("ORM.ROW_IDENTITY_MISSING", `Cannot load includes for the mutation result on model "${modelName}": table "${tableName}" has no primary key or unique constraint to key the include read-back on.`, { meta: {
1873
+ model: modelName,
1874
+ table: tableName
1875
+ } });
1876
+ const identityFilter = buildIdentityInFilter(contract, namespaceId, tableName, identityColumns, identityRows);
1877
+ if (!identityFilter) return emptyResult();
1878
+ return dispatchCollectionRows({
1879
+ context,
1880
+ runtime,
1881
+ state: {
1882
+ ...emptyState(),
1883
+ filters: [identityFilter],
1884
+ selectedFields,
1885
+ includes
1886
+ },
1887
+ tableName,
1888
+ modelName,
1889
+ namespaceId
1890
+ });
1891
+ }
1892
+ function emptyResult() {
1893
+ return new AsyncIterableResult((async function* () {})());
1894
+ }
1895
+ function buildIdentityInFilter(contract, namespaceId, tableName, identityColumns, identityRows) {
1896
+ const [singleColumn, ...rest] = identityColumns;
1897
+ if (singleColumn !== void 0 && rest.length === 0) {
1898
+ const values = identityRows.map((row) => row[singleColumn]).filter((value) => value !== void 0);
1899
+ if (values.length === 0) return;
1900
+ return bindWhereExpr(contract, BinaryExpr.in(ColumnRef.of(tableName, singleColumn), ListExpression.fromValues(values)), namespaceId);
1901
+ }
1902
+ if (identityRows.length === 0) return;
1903
+ const tuples = identityRows.map((row) => AndExpr.of(identityColumns.map((column) => BinaryExpr.eq(ColumnRef.of(tableName, column), LiteralExpr.of(row[column])))));
1904
+ return bindWhereExpr(contract, OrExpr.of(tuples), namespaceId);
1905
+ }
1906
+ /**
1907
+ * Decode a single-query include payload from a parent row's raw cell
1908
+ * into the model-shaped value that downstream consumers see. Recurses
1909
+ * through `include.nested.includes` so depth-2+ trees — emitted by the
1910
+ * recursive correlated-subquery builder — are decoded symmetrically.
1911
+ *
1912
+ * The shape produced by the SQL side is one JSON column per top-level
1913
+ * include; values nested inside that JSON are already-parsed JS values
1914
+ * after the outer `JSON.parse`, so `parseIncludedRows` recognises both
1915
+ * the string (top-level) and array (nested) forms.
1916
+ *
1917
+ * Scalar leaves arrive wrapped in a `{ value: <primitive> }` JSON
1918
+ * envelope (see `buildIncludeChildScalarSelect`); the branch below
1919
+ * unwraps that envelope and passes the value straight through. The
1920
+ * empty-relation default is driven by SQL semantics, not the decoder:
1921
+ * `COUNT(*)` over an empty input set is `0`; `SUM` / `AVG` / `MIN` /
1922
+ * `MAX` over an empty input set are SQL `NULL`, which surfaces as
1923
+ * `null` in TS — the documented contract for those reducers.
1924
+ *
1925
+ * Combine descriptors arrive as a JSON object keyed by branch name;
1926
+ * each branch is dispatched to the row or scalar decoder per its
1927
+ * declared shape (see `decodeCombineIncludePayload`).
1928
+ */
1929
+ async function decodeIncludePayload(contract, context, include, raw) {
1930
+ if (include.scalar) return Promise.resolve(decodeScalarIncludePayload(include, include.scalar, raw));
1931
+ if (include.combine) return decodeCombineIncludePayload(contract, context, include, include.combine, raw);
1932
+ const rawChildren = parseIncludedRows(include, raw);
1933
+ const polyInfo = resolvePolymorphismInfo(contract, include.relatedNamespaceId, include.relatedModelName);
1934
+ const mapChildRow = polyInfo ? (childRow) => mapPolymorphicRow(contract, include.relatedNamespaceId, include.relatedModelName, polyInfo, childRow, include.nested.variantName) : (childRow) => mapStorageRowToModelFields(contract, include.relatedNamespaceId, include.relatedModelName, childRow);
1935
+ const mappedChildren = [];
1936
+ for (const childRow of rawChildren) {
1937
+ const decodedChildRow = await decodeIncludedStorageRow(contract, context, include, childRow);
1938
+ const mapped = mapChildRow(decodedChildRow);
1939
+ for (const nestedInclude of include.nested.includes) mapped[nestedInclude.relationName] = await decodeIncludePayload(contract, context, nestedInclude, decodedChildRow[nestedInclude.relationName]);
1940
+ mappedChildren.push(mapped);
1941
+ }
1942
+ return coerceSingleQueryIncludeResult(mappedChildren, include.cardinality);
1943
+ }
1944
+ async function decodeIncludedStorageRow(contract, context, include, row) {
1945
+ const decoded = {};
1946
+ for (const [key, value] of Object.entries(row)) {
1947
+ if (value === null || value === void 0) {
1948
+ decoded[key] = value;
1949
+ continue;
1950
+ }
1951
+ const ref = resolveIncludedColumnRef(contract, include, key);
1952
+ if (!ref) {
1953
+ decoded[key] = value;
1954
+ continue;
1955
+ }
1956
+ const codec = context.contractCodecs.forColumn(include.relatedNamespaceId, ref.table, ref.column);
1957
+ if (!codec) {
1958
+ decoded[key] = value;
1959
+ continue;
1960
+ }
1961
+ decoded[key] = await decodeIncludedColumnValue(ref, context.codecDescriptors.codecRefForColumn(include.relatedNamespaceId, ref.table, ref.column)?.codecId ?? ref.storageColumn.codecId, codec, value);
1962
+ }
1963
+ return decoded;
1964
+ }
1965
+ function resolveIncludedColumnRef(contract, include, key) {
1966
+ const baseColumn = resolveStorageColumn(contract, include.relatedNamespaceId, include.relatedTableName, key);
1967
+ if (baseColumn) return {
1968
+ table: include.relatedTableName,
1969
+ column: key,
1970
+ storageColumn: baseColumn
1971
+ };
1972
+ const polyInfo = resolvePolymorphismInfo(contract, include.relatedNamespaceId, include.relatedModelName);
1973
+ if (!polyInfo) return;
1974
+ for (const variant of polyInfo.mtiVariants) {
1975
+ const prefix = `${variant.table}__`;
1976
+ if (!key.startsWith(prefix)) continue;
1977
+ const column = key.slice(prefix.length);
1978
+ const variantColumn = resolveStorageColumn(contract, include.relatedNamespaceId, variant.table, column);
1979
+ if (variantColumn) return {
1980
+ table: variant.table,
1981
+ column,
1982
+ storageColumn: variantColumn
1983
+ };
1984
+ }
1985
+ }
1986
+ function resolveStorageColumn(contract, namespaceId, tableName, columnName) {
1987
+ return contract.storage.namespaces[namespaceId]?.entries.table?.[tableName]?.columns[columnName];
1988
+ }
1989
+ async function decodeIncludedColumnValue(ref, codecId, codec, value) {
1990
+ if (ref.storageColumn.many === true) {
1991
+ if (!Array.isArray(value)) wrapIncludedDecodeFailure(/* @__PURE__ */ new TypeError(`expected an array from the driver for many-typed column, got ${typeof value}`), ref, codecId);
1992
+ const decoded = [];
1993
+ for (const element of value) {
1994
+ if (element === null || element === void 0) {
1995
+ decoded.push(null);
1996
+ continue;
1997
+ }
1998
+ decoded.push(decodeIncludedJsonValue(ref, codecId, codec, element));
1999
+ }
2000
+ return decoded;
2001
+ }
2002
+ return decodeIncludedJsonValue(ref, codecId, codec, value);
2003
+ }
2004
+ function decodeIncludedJsonValue(ref, codecId, codec, value) {
2005
+ try {
2006
+ return codec.decodeJson(blindCast(value));
2007
+ } catch (error) {
2008
+ if (isRuntimeError(error)) throw error;
2009
+ wrapIncludedDecodeFailure(error, ref, codecId);
2010
+ }
2011
+ }
2012
+ function wrapIncludedDecodeFailure(error, ref, codecId) {
2013
+ const message = error instanceof Error ? error.message : String(error);
2014
+ const wrapped = runtimeError("RUNTIME.DECODE_FAILED", `Failed to decode column ${ref.table}.${ref.column} with codec '${codecId}': ${message}`, {
2015
+ table: ref.table,
2016
+ column: ref.column,
2017
+ codec: codecId
2018
+ });
2019
+ wrapped.cause = error;
2020
+ throw wrapped;
2021
+ }
2022
+ /**
2023
+ * Decode the combine payload produced by `buildIncludeChildCombineSelect`.
2024
+ *
2025
+ * The raw value is a JSON object (already parsed by the SQL layer when
2026
+ * top-level, or already a JS object when nested) whose keys are branch
2027
+ * names. Each branch value is decoded per its declared kind:
2028
+ * - row branch -> recurse via `decodeIncludePayload` with a synthetic
2029
+ * IncludeExpr carrying the branch's state in `nested`. This walks
2030
+ * nested row-level includes the same way a plain row include would.
2031
+ * - scalar branch -> unwrap the `{value: ...}` envelope via the
2032
+ * standalone scalar decoder.
2033
+ *
2034
+ * On a parent with zero matching child rows the correlated subquery
2035
+ * still produces one row (aggregates collapse the empty input to a
2036
+ * single row), so the combine envelope here is always present in the
2037
+ * read path. The
2038
+ * mutation read-back's `assignEmptyMutationIncludes` writes the empty
2039
+ * per-branch shape directly to `parent.mapped[relationName]` for any
2040
+ * parent absent from the read-back result and never enters the decoder,
2041
+ * so a missing or non-object envelope here is always a planner/decoder
2042
+ * bug — `parseCombineEnvelope` throws loudly rather than papering over
2043
+ * it with an empty shape.
2044
+ */
2045
+ async function decodeCombineIncludePayload(contract, context, include, branches, raw) {
2046
+ const parsed = parseCombineEnvelope(include, raw);
2047
+ const result = {};
2048
+ for (const [branchName, branch] of Object.entries(branches)) {
2049
+ const branchRaw = parsed[branchName];
2050
+ if (branch.kind === "rows") result[branchName] = await decodeIncludePayload(contract, context, {
2051
+ ...include,
2052
+ nested: branch.state,
2053
+ scalar: void 0,
2054
+ combine: void 0
2055
+ }, branchRaw);
2056
+ else result[branchName] = decodeScalarIncludePayload(include, branch.selector, branchRaw);
2057
+ }
2058
+ return result;
2059
+ }
2060
+ function parseCombineEnvelope(include, raw) {
2061
+ if (raw === null || raw === void 0) throw new InternalError(`combine() envelope for include "${include.relationName}" is missing (got ${raw === null ? "null" : "undefined"}); the correlated subquery should always produce a JSON object — this indicates a planner or decoder bug.`);
2062
+ const parsed = parseIncludePayload(raw);
2063
+ if (!isPlainObjectEnvelope(parsed)) throw new InternalError(`combine() envelope for include "${include.relationName}" has unexpected shape (expected object, got ${describeEnvelopeShape(parsed)}); this indicates a planner or decoder bug.`);
2064
+ return parsed;
2065
+ }
2066
+ function isPlainObjectEnvelope(value) {
2067
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2068
+ }
2069
+ function describeEnvelopeShape(value) {
2070
+ if (value === null) return "null";
2071
+ if (Array.isArray(value)) return "array";
2072
+ return typeof value;
2073
+ }
2074
+ /**
2075
+ * Pull the primitive scalar value out of the JSON envelope emitted by
2076
+ * the correlated scalar builder.
2077
+ *
2078
+ * Contract: the envelope is always either
2079
+ * - a `{ value: <primitive> }` JSON object (the SQL path), or
2080
+ * - `null` / `undefined` (the mutation read-back's
2081
+ * `assignEmptyMutationIncludes` short-circuit before this decoder
2082
+ * runs, for a parent absent from the read-back result).
2083
+ *
2084
+ * Any other shape — array, primitive, string that JSON-parses to
2085
+ * non-object — indicates a planner / decoder bug, so we throw
2086
+ * loudly naming the include relation rather than soft-handling.
2087
+ * Mirrors `parseCombineEnvelope`'s strict shape gate.
2088
+ *
2089
+ * Values are passed through unchanged — no JS-side `Number()` coercion
2090
+ * and no JS-side empty-relation defaulting. SQL semantics drive the
2091
+ * empty-relation case: `COUNT(*)` over an empty input set is `0`;
2092
+ * `SUM` / `AVG` / `MIN` / `MAX` over an empty input set return SQL
2093
+ * `NULL`, which surfaces as `null` here. The outer `raw === null`
2094
+ * fallback is defensive cover for an empty parent set; in single-query
2095
+ * dispatch the correlated subquery always produces a row, so the inner
2096
+ * envelope's `value` is always set by SQL.
2097
+ */
2098
+ function decodeScalarIncludePayload(include, scalar, raw) {
2099
+ if (raw === null || raw === void 0) return emptyScalarResult(scalar.fn);
2100
+ const parsed = parseIncludePayload(raw);
2101
+ if (!isPlainObjectEnvelope(parsed)) throw new InternalError(`scalar() envelope for include "${include.relationName}" has unexpected shape (expected object, got ${describeEnvelopeShape(parsed)}); this indicates a planner or decoder bug.`);
2102
+ return parsed["value"];
2103
+ }
2104
+ function parseIncludedRows(include, value) {
2105
+ if (value === null || value === void 0) return [];
2106
+ const parsed = parseIncludePayload(value);
2107
+ if (!Array.isArray(parsed)) return [];
2108
+ const rows = [];
2109
+ for (const item of parsed) {
2110
+ if (!isPlainObjectEnvelope(item)) throw new InternalError(`Include row envelope for relation "${include.relationName}" has unexpected shape (expected object, got ${describeEnvelopeShape(item)}); this indicates a planner or decoder bug.`);
2111
+ rows.push({ ...item });
2112
+ }
2113
+ return rows;
2114
+ }
2115
+ function parseIncludePayload(value) {
2116
+ if (typeof value !== "string") return value;
2117
+ try {
2118
+ return JSON.parse(value);
2119
+ } catch {
2120
+ return [];
2121
+ }
2122
+ }
2123
+ function coerceSingleQueryIncludeResult(rows, cardinality) {
2124
+ return isToOneCardinality(cardinality) ? rows[0] ?? null : rows;
2125
+ }
2126
+ function emptyScalarResult(fn) {
2127
+ return fn === "count" ? 0 : null;
2128
+ }
2129
+ function createMutationRowMapper(contract, namespaceId, modelName, variantName) {
2130
+ const polyInfo = resolvePolymorphismInfo(contract, namespaceId, modelName);
2131
+ return polyInfo ? (row) => mapPolymorphicRow(contract, namespaceId, modelName, polyInfo, row, variantName) : (row) => mapStorageRowToModelFields(contract, namespaceId, modelName, row);
2132
+ }
2133
+ function dispatchMutationRows(options) {
2134
+ const { context, runtime, compiled, tableName, modelName, namespaceId, variantName, includes, selectedFields, hiddenColumns, mapRow } = options;
2135
+ const { contract } = context;
2136
+ const mapStorageRow = createMutationRowMapper(contract, namespaceId, modelName, variantName);
2137
+ if (includes.length === 0) return mapResultRows(executeQueryPlan(runtime, compiled), (rawRow) => {
2138
+ const mapped = mapStorageRow(rawRow);
2139
+ if (hiddenColumns.length > 0) stripHiddenMappedFields(contract, namespaceId, modelName, mapped, hiddenColumns);
2140
+ return mapRow(mapped);
2141
+ });
2142
+ const generator = async function* () {
2143
+ const identityRows = await executeQueryPlan(runtime, compiled).toArray();
2144
+ yield* reloadMutationRowsByIdentities({
2145
+ context,
2146
+ runtime,
2147
+ tableName,
2148
+ modelName,
2149
+ namespaceId,
2150
+ identityRows,
2151
+ selectedFields,
2152
+ includes
2153
+ });
2154
+ };
2155
+ return new AsyncIterableResult(generator());
2156
+ }
2157
+ function dispatchSplitMutationRows(options) {
2158
+ const { context, runtime, plans, tableName, modelName, namespaceId, variantName, includes, selectedFields, hiddenColumns, mapRow } = options;
2159
+ const { contract } = context;
2160
+ const mapStorageRow = createMutationRowMapper(contract, namespaceId, modelName, variantName);
2161
+ const generator = async function* () {
2162
+ if (includes.length > 0) {
2163
+ const identityRows = [];
2164
+ for (const plan of plans) identityRows.push(...await executeQueryPlan(runtime, plan).toArray());
2165
+ yield* reloadMutationRowsByIdentities({
2166
+ context,
2167
+ runtime,
2168
+ tableName,
2169
+ modelName,
2170
+ namespaceId,
2171
+ identityRows,
2172
+ selectedFields,
2173
+ includes
2174
+ });
2175
+ return;
2176
+ }
2177
+ for (const plan of plans) for await (const rawRow of executeQueryPlan(runtime, plan)) {
2178
+ const mapped = mapStorageRow(rawRow);
2179
+ if (hiddenColumns.length > 0) stripHiddenMappedFields(contract, namespaceId, modelName, mapped, hiddenColumns);
2180
+ yield mapRow(mapped);
2181
+ }
2182
+ };
2183
+ return new AsyncIterableResult(generator());
2184
+ }
2185
+ async function executeMutationReturningSingleRow(options) {
2186
+ const { context, runtime, compiled, tableName, modelName, namespaceId, variantName, includes, selectedFields, hiddenColumns, mapRow, operation, onMissingRowMessage } = options;
2187
+ const { contract } = context;
2188
+ const mapStorageRow = createMutationRowMapper(contract, namespaceId, modelName, variantName);
2189
+ if (includes.length === 0) {
2190
+ const first = (await executeQueryPlan(runtime, compiled).toArray())[0];
2191
+ if (!first) return null;
2192
+ const mapped = mapStorageRow(first);
2193
+ if (hiddenColumns.length > 0) stripHiddenMappedFields(contract, namespaceId, modelName, mapped, hiddenColumns);
2194
+ return mapRow(mapped);
2195
+ }
2196
+ const identityRows = await executeQueryPlan(runtime, compiled).toArray();
2197
+ if (identityRows.length === 0) return null;
2198
+ for await (const row of reloadMutationRowsByIdentities({
2199
+ context,
2200
+ runtime,
2201
+ tableName,
2202
+ modelName,
2203
+ namespaceId,
2204
+ identityRows,
2205
+ selectedFields,
2206
+ includes
2207
+ })) return row;
2208
+ throw ormError("ORM.MUTATION_ROW_MISSING", onMissingRowMessage, { meta: {
2209
+ operation,
2210
+ model: modelName,
2211
+ tableName
2212
+ } });
2213
+ }
2214
+ function and(...exprs) {
2215
+ return AndExpr.of(exprs);
2216
+ }
2217
+ function or(...exprs) {
2218
+ return OrExpr.of(exprs);
2219
+ }
2220
+ function not(expr) {
2221
+ return expr.not();
2222
+ }
2223
+ function all() {
2224
+ return AndExpr.true();
2225
+ }
2226
+ function shorthandToWhereExpr(context, namespaceId, modelName, filters) {
2227
+ const contract = context.contract;
2228
+ const tableName = resolveModelTableName(contract, namespaceId, modelName);
2229
+ const fieldToColumn = getFieldToColumnMap(contract, namespaceId, modelName);
2230
+ const exprs = [];
2231
+ for (const [fieldName, value] of Object.entries(filters)) {
2232
+ if (value === void 0) continue;
2233
+ const columnName = fieldToColumn[fieldName] ?? fieldName;
2234
+ const left = ColumnRef.of(tableName, columnName);
2235
+ if (value === null) {
2236
+ exprs.push(NullCheckExpr.isNull(left));
2237
+ continue;
2238
+ }
2239
+ assertFieldHasEqualityTrait(context, namespaceId, modelName, fieldName);
2240
+ exprs.push(BinaryExpr.eq(left, LiteralExpr.of(value)));
2241
+ }
2242
+ if (exprs.length === 0) return;
2243
+ return exprs.length === 1 ? exprs[0] : and(...exprs);
2244
+ }
2245
+ function assertFieldHasEqualityTrait(context, namespaceId, modelName, fieldName) {
2246
+ const fieldType = modelOf(context.contract, namespaceId, modelName)?.fields?.[fieldName]?.type;
2247
+ const codecId = fieldType?.kind === "scalar" ? fieldType.codecId : void 0;
2248
+ if (!(codecId ? context.codecDescriptors.descriptorFor(codecId)?.traits ?? [] : []).includes("equality")) throw ormError("ORM.FILTER_UNSUPPORTED", `Shorthand filter on "${modelName}.${fieldName}": field does not support equality comparisons`, { meta: {
2249
+ model: modelName,
2250
+ field: fieldName,
2251
+ trait: "equality"
2252
+ } });
2253
+ }
2254
+ var GroupedCollection = class GroupedCollection {
2255
+ ctx;
2256
+ contract;
2257
+ modelName;
2258
+ tableName;
2259
+ namespaceId;
2260
+ baseFilters;
2261
+ groupByFields;
2262
+ groupByColumns;
2263
+ havingFilters;
2264
+ constructor(ctx, modelName, options) {
2265
+ this.ctx = ctx;
2266
+ this.contract = ctx.context.contract;
2267
+ this.modelName = modelName;
2268
+ this.tableName = options.tableName;
2269
+ this.namespaceId = options.namespaceId;
2270
+ this.baseFilters = options.baseFilters;
2271
+ this.groupByFields = options.groupByFields;
2272
+ this.groupByColumns = options.groupByColumns;
2273
+ this.havingFilters = options.havingFilters;
2274
+ }
2275
+ having(predicate) {
2276
+ const havingExpr = predicate(createHavingBuilder(this.contract, this.namespaceId, this.modelName, this.tableName));
2277
+ return new GroupedCollection(this.ctx, this.modelName, {
2278
+ tableName: this.tableName,
2279
+ namespaceId: this.namespaceId,
2280
+ baseFilters: this.baseFilters,
2281
+ groupByFields: this.groupByFields,
2282
+ groupByColumns: this.groupByColumns,
2283
+ havingFilters: [...this.havingFilters, havingExpr]
2284
+ });
2285
+ }
2286
+ /**
2287
+ * Read terminal: run a grouped aggregate query.
2288
+ *
2289
+ * Accepts an optional `configure` callback that receives a
2290
+ * `MetaBuilder<'read'>` for attaching typed annotations.
2291
+ * Annotations are merged into the compiled plan's `meta.annotations`.
2292
+ */
2293
+ async aggregate(fn, configure) {
2294
+ const aggregateSpec = fn(createAggregateBuilder(this.contract, this.namespaceId, this.modelName));
2295
+ const aggregateEntries = Object.entries(aggregateSpec);
2296
+ if (aggregateEntries.length === 0) throw ormError("ORM.AGGREGATE_SELECTOR_MISSING", "groupBy().aggregate() requires at least one aggregation selector", { meta: {
2297
+ method: "groupBy.aggregate",
2298
+ model: this.modelName
2299
+ } });
2300
+ for (const [alias, selector] of aggregateEntries) if (!isAggregateSelector(selector)) throw ormError("ORM.AGGREGATE_SELECTOR_INVALID", `groupBy().aggregate() selector "${alias}" is invalid`, { meta: {
2301
+ method: "groupBy.aggregate",
2302
+ model: this.modelName,
2303
+ alias
2304
+ } });
2305
+ let annotationsMap;
2306
+ if (configure !== void 0) {
2307
+ const meta = createMetaBuilder("read", "groupBy.aggregate");
2308
+ configure(meta);
2309
+ if (meta.annotations.size > 0) annotationsMap = meta.annotations;
2310
+ }
2311
+ const compiled = mergeAnnotations(compileGroupedAggregate(this.contract, this.namespaceId, this.tableName, this.baseFilters, this.groupByColumns, aggregateSpec, combineWhereExprs(this.havingFilters)), annotationsMap);
2312
+ return (await executeQueryPlan(this.ctx.runtime, compiled).toArray()).map((row) => {
2313
+ const mapped = mapStorageRowToModelFields(this.contract, this.namespaceId, this.modelName, row);
2314
+ for (const [alias, selector] of aggregateEntries) mapped[alias] = coerceAggregateValue(selector.fn, row[alias]);
2315
+ return mapped;
2316
+ });
2317
+ }
2318
+ };
2319
+ function createHavingBuilder(contract, namespaceId, modelName, tableName) {
2320
+ const fieldToColumn = getFieldToColumnMap(contract, namespaceId, modelName);
2321
+ const createMetricExpr = (fn, fieldName) => new AggregateExpr(fn, ColumnRef.of(tableName, fieldToColumn[fieldName] ?? fieldName));
2322
+ return {
2323
+ count() {
2324
+ return createHavingComparisonMethods(AggregateExpr.count());
2325
+ },
2326
+ sum(field) {
2327
+ return createHavingComparisonMethods(createMetricExpr("sum", field));
2328
+ },
2329
+ avg(field) {
2330
+ return createHavingComparisonMethods(createMetricExpr("avg", field));
2331
+ },
2332
+ min(field) {
2333
+ return createHavingComparisonMethods(createMetricExpr("min", field));
2334
+ },
2335
+ max(field) {
2336
+ return createHavingComparisonMethods(createMetricExpr("max", field));
2337
+ }
2338
+ };
2339
+ }
2340
+ function createHavingComparisonMethods(metric) {
2341
+ const buildBinaryExpr = (op, value) => new BinaryExpr(op, metric, LiteralExpr.of(value));
2342
+ return {
2343
+ eq(value) {
2344
+ return buildBinaryExpr("eq", value);
2345
+ },
2346
+ neq(value) {
2347
+ return buildBinaryExpr("neq", value);
2348
+ },
2349
+ gt(value) {
2350
+ return buildBinaryExpr("gt", value);
2351
+ },
2352
+ lt(value) {
2353
+ return buildBinaryExpr("lt", value);
2354
+ },
2355
+ gte(value) {
2356
+ return buildBinaryExpr("gte", value);
2357
+ },
2358
+ lte(value) {
2359
+ return buildBinaryExpr("lte", value);
2360
+ }
2361
+ };
2362
+ }
2363
+ function coerceAggregateValue(fn, value) {
2364
+ if (value === null) return null;
2365
+ if (value === void 0) return fn === "count" ? 0 : null;
2366
+ if (typeof value === "number") return value;
2367
+ if (typeof value === "bigint") return Number(value);
2368
+ if (typeof value === "string") {
2369
+ const numeric = Number(value);
2370
+ return Number.isNaN(numeric) ? value : numeric;
2371
+ }
2372
+ return value;
2373
+ }
2374
+ const aggregateFns = /* @__PURE__ */ new Set([
2375
+ "count",
2376
+ "sum",
2377
+ "avg",
2378
+ "min",
2379
+ "max"
2380
+ ]);
2381
+ function createIncludeScalar(fn, state, column) {
2382
+ return {
2383
+ kind: "includeScalar",
2384
+ fn,
2385
+ state,
2386
+ ...column !== void 0 ? { column } : {}
2387
+ };
2388
+ }
2389
+ function createIncludeCombine(branches) {
2390
+ return {
2391
+ kind: "includeCombine",
2392
+ branches
2393
+ };
2394
+ }
2395
+ function isIncludeScalar(value) {
2396
+ if (typeof value !== "object" || value === null) return false;
2397
+ const candidate = value;
2398
+ return candidate.kind === "includeScalar" && typeof candidate.fn === "string" && aggregateFns.has(candidate.fn) && isCollectionState(candidate.state);
2399
+ }
2400
+ function isIncludeCombine(value) {
2401
+ if (typeof value !== "object" || value === null) return false;
2402
+ const candidate = value;
2403
+ if (candidate.kind !== "includeCombine") return false;
2404
+ if (typeof candidate.branches !== "object" || candidate.branches === null) return false;
2405
+ return true;
2406
+ }
2407
+ function isCollectionStateCarrier(value) {
2408
+ if (typeof value !== "object" || value === null) return false;
2409
+ return isCollectionState(value.state);
2410
+ }
2411
+ function isCollectionState(value) {
2412
+ if (typeof value !== "object" || value === null) return false;
2413
+ const candidate = value;
2414
+ return Array.isArray(candidate.filters) && Array.isArray(candidate.includes);
2415
+ }
2416
+ function hasThrough$1(relation) {
2417
+ return relation.through !== void 0;
2418
+ }
2419
+ function createModelAccessor(context, namespaceId, modelName, variantName) {
2420
+ const contract = context.contract;
2421
+ const fieldToColumn = getFieldToColumnMap(contract, namespaceId, modelName);
2422
+ const tableName = resolveModelTableName(contract, namespaceId, modelName);
2423
+ const modelRelations = resolveModelRelations(contract, namespaceId, modelName);
2424
+ const variantFieldColumns = variantName ? resolveVariantFieldColumns(contract, namespaceId, modelName, variantName) : {};
2425
+ const variantCoordinates = variantName ? {
2426
+ name: variantName,
2427
+ relations: resolveModelRelations(contract, namespaceId, variantName),
2428
+ tableName: resolvePolymorphismInfo(contract, namespaceId, modelName)?.variants.get(variantName)?.table ?? tableName
2429
+ } : void 0;
2430
+ const opsByCodecId = /* @__PURE__ */ new Map();
2431
+ function registerOp(codecId, op) {
2432
+ let existing = opsByCodecId.get(codecId);
2433
+ if (!existing) {
2434
+ existing = [];
2435
+ opsByCodecId.set(codecId, existing);
2436
+ }
2437
+ existing.push(op);
2438
+ }
2439
+ for (const [name, entry] of Object.entries(context.queryOperations.entries())) {
2440
+ const op = [name, entry];
2441
+ const self = entry.self;
2442
+ if (!self) continue;
2443
+ if (self.codecId !== void 0) registerOp(self.codecId, op);
2444
+ else if (self.traits !== void 0) for (const descriptor of context.codecDescriptors.values()) {
2445
+ const descriptorTraits = descriptor.traits;
2446
+ if (self.traits.every((t) => descriptorTraits.includes(t))) registerOp(descriptor.codecId, op);
2447
+ }
2448
+ }
2449
+ return blindCast(new Proxy({}, { get(_target, prop) {
2450
+ if (typeof prop !== "string") return;
2451
+ if (variantCoordinates) {
2452
+ const variantRelation = variantCoordinates.relations[prop];
2453
+ if (variantRelation) return createRelationFilterAccessor(context, namespaceId, variantCoordinates.name, variantCoordinates.tableName, prop, variantRelation);
2454
+ }
2455
+ const relation = modelRelations[prop];
2456
+ if (relation) return createRelationFilterAccessor(context, namespaceId, modelName, tableName, prop, relation);
2457
+ const variantField = variantFieldColumns[prop];
2458
+ const resolvedTable = variantField?.table ?? tableName;
2459
+ const columnName = variantField?.column ?? fieldToColumn[prop] ?? prop;
2460
+ const column = resolveColumn(contract, namespaceId, resolvedTable, columnName);
2461
+ if (!column) return;
2462
+ const traits = context.codecDescriptors.descriptorFor(column.codecId)?.traits ?? [];
2463
+ const operations = opsByCodecId.get(column.codecId) ?? [];
2464
+ const codec = codecRefForStorageColumn(contract.storage, namespaceId, resolvedTable, columnName);
2465
+ return createScalarFieldAccessor(resolvedTable, columnName, column.codecId, column.nullable, codec, traits, operations, context);
2466
+ } }));
2467
+ }
2468
+ function resolveColumn(contract, namespaceId, tableName, columnName) {
2469
+ let table;
2470
+ try {
2471
+ table = storageTableForContract(contract, namespaceId, tableName);
2472
+ } catch {
2473
+ return;
2474
+ }
2475
+ const column = table.columns[columnName];
2476
+ if (!column) return void 0;
2477
+ return {
2478
+ codecId: column.codecId,
2479
+ nullable: column.nullable
2480
+ };
2481
+ }
2482
+ function createScalarFieldAccessor(tableName, columnName, codecId, nullable, codec, traits, operations, context) {
2483
+ const column = ColumnRef.of(tableName, columnName);
2484
+ const comparisonEntries = [];
2485
+ for (const [name, meta] of Object.entries(COMPARISON_METHODS_META)) {
2486
+ if (meta.traits.some((t) => !traits.includes(t))) continue;
2487
+ comparisonEntries.push([name, meta.create(column, codec)]);
2488
+ }
2489
+ const accessor = blindCast({
2490
+ returnType: {
2491
+ codecId,
2492
+ nullable,
2493
+ codec
2494
+ },
2495
+ codec,
2496
+ buildAst: () => column,
2497
+ ...Object.fromEntries(comparisonEntries)
2498
+ });
2499
+ for (const [name, entry] of operations) accessor[name] = createExtensionMethodFactory(accessor, entry, context);
2500
+ return blindCast(accessor);
2501
+ }
2502
+ function createExtensionMethodFactory(selfExpr, entry, context) {
2503
+ return (...args) => {
2504
+ const result = blindCast(entry.impl)(selfExpr, ...args);
2505
+ const returnCodecId = result.returnType.codecId;
2506
+ const returnTraits = context.codecDescriptors.descriptorFor(returnCodecId)?.traits ?? [];
2507
+ if (returnTraits.includes("boolean")) return result.buildAst();
2508
+ const resultAst = result.buildAst();
2509
+ const returnCodec = { codecId: returnCodecId };
2510
+ const methods = {};
2511
+ for (const [resultMethodName, meta] of Object.entries(COMPARISON_METHODS_META)) {
2512
+ if (meta.traits.some((t) => !returnTraits.includes(t))) continue;
2513
+ methods[resultMethodName] = meta.create(resultAst, returnCodec);
2514
+ }
2515
+ return methods;
2516
+ };
2517
+ }
2518
+ function createRelationFilterAccessor(context, parentNamespaceId, parentModelName, parentTableName, relationName, relation) {
2519
+ const relatedTableName = resolveModelTableName(context.contract, relation.toNamespace, relation.to);
2520
+ return {
2521
+ some: (predicate) => buildExistsExpr(context, parentNamespaceId, parentModelName, parentTableName, relatedTableName, relationName, relation, {
2522
+ mode: "some",
2523
+ predicate
2524
+ }),
2525
+ every: (predicate) => buildExistsExpr(context, parentNamespaceId, parentModelName, parentTableName, relatedTableName, relationName, relation, {
2526
+ mode: "every",
2527
+ predicate
2528
+ }),
2529
+ none: (predicate) => buildExistsExpr(context, parentNamespaceId, parentModelName, parentTableName, relatedTableName, relationName, relation, {
2530
+ mode: "none",
2531
+ predicate
2532
+ })
2533
+ };
2534
+ }
2535
+ function buildExistsExpr(context, parentNamespaceId, parentModelName, parentTableName, relatedTableName, relationName, relation, options) {
2536
+ if (hasThrough$1(relation)) return buildManyToManyExistsExpr(context, parentNamespaceId, parentModelName, parentTableName, relatedTableName, relationName, relation, options);
2537
+ const filterPlan = planRelationFilterMode(buildJoinWhere(context.contract, parentNamespaceId, parentModelName, parentTableName, relatedTableName, relation), toRelationWhereExpr(context, relation.toNamespace, relation.to, options.predicate), options.mode);
2538
+ if (filterPlan.kind === "constantTrue") return AndExpr.true();
2539
+ const selectProjectionColumn = firstTargetColumn(context.contract, relation) ?? "id";
2540
+ const subquery = SelectAst.from(tableSourceForContract(context.contract, relation.toNamespace, relatedTableName)).withProjection([ProjectionItem.of("_exists", ColumnRef.of(relatedTableName, selectProjectionColumn))]).withWhere(filterPlan.where);
2541
+ return filterPlan.notExists ? ExistsExpr.notExists(subquery) : ExistsExpr.exists(subquery);
2542
+ }
2543
+ function buildManyToManyExistsExpr(context, parentNamespaceId, parentModelName, parentTableName, relatedTableName, relationName, relation, options) {
2544
+ const { through } = relation;
2545
+ const junctionTable = through.table;
2546
+ const relatedTableAlias = parentNamespaceId === relation.toNamespace && parentTableName === relatedTableName ? `${relationName}__child` : void 0;
2547
+ const relatedTableRef = relatedTableAlias ?? relatedTableName;
2548
+ const junctionJoinOn = buildPairedColumnExprs(junctionTable, through.childColumns, relatedTableRef, through.targetColumns);
2549
+ const parentLocalColumns = relation.on.localFields.map((field) => resolveFieldToColumn(context.contract, parentNamespaceId, parentModelName, field));
2550
+ const filterPlan = planRelationFilterMode(buildPairedColumnExprs(junctionTable, through.parentColumns, parentTableName, parentLocalColumns), remapColumnRefs(relatedTableName, relatedTableRef, toRelationWhereExpr(context, relation.toNamespace, relation.to, options.predicate)), options.mode);
2551
+ if (filterPlan.kind === "constantTrue") return AndExpr.true();
2552
+ const firstTargetCol = firstJoinColumn(through.targetColumns, "targetColumns");
2553
+ const subquery = SelectAst.from(tableSourceForContract(context.contract, relation.toNamespace, relatedTableName, relatedTableAlias)).withJoins([JoinAst.inner(TableSource.named(junctionTable, void 0, through.namespaceId), junctionJoinOn)]).withProjection([ProjectionItem.of("_exists", ColumnRef.of(relatedTableRef, firstTargetCol))]).withWhere(filterPlan.where);
2554
+ return filterPlan.notExists ? ExistsExpr.notExists(subquery) : ExistsExpr.exists(subquery);
2555
+ }
2556
+ function planRelationFilterMode(joinWhere, childWhere, mode) {
2557
+ if (mode === "every") {
2558
+ if (!childWhere) return { kind: "constantTrue" };
2559
+ return {
2560
+ kind: "exists",
2561
+ notExists: true,
2562
+ where: and(joinWhere, not(childWhere))
2563
+ };
2564
+ }
2565
+ if (mode === "none") return {
2566
+ kind: "exists",
2567
+ notExists: true,
2568
+ where: childWhere ? and(joinWhere, childWhere) : joinWhere
2569
+ };
2570
+ return {
2571
+ kind: "exists",
2572
+ notExists: false,
2573
+ where: childWhere ? and(joinWhere, childWhere) : joinWhere
2574
+ };
2575
+ }
2576
+ function remapColumnRefs(tableName, tableRef, expr) {
2577
+ if (!expr || tableName === tableRef) return expr;
2578
+ return expr.rewrite({ columnRef: (column) => column.table === tableName ? ColumnRef.of(tableRef, column.column) : column });
2579
+ }
2580
+ function firstJoinColumn(columns, label) {
2581
+ const first = columns[0];
2582
+ if (!first) throw new InternalError(`Relation metadata is missing ${label}`);
2583
+ return first;
2584
+ }
2585
+ function buildPairedColumnExprs(leftTable, leftColumns, rightTable, rightColumns) {
2586
+ if (leftColumns.length !== rightColumns.length) throw new InternalError(`Relation metadata has mismatched join column counts: ${leftColumns.length} left column(s), ${rightColumns.length} right column(s)`);
2587
+ if (leftColumns.length === 0) throw new InternalError("Relation metadata is missing join columns");
2588
+ const exprs = [];
2589
+ for (let i = 0; i < leftColumns.length; i++) {
2590
+ const left = leftColumns[i];
2591
+ const right = rightColumns[i];
2592
+ if (!left || !right) throw new InternalError(`Relation metadata is missing a join column pair at index ${i}`);
2593
+ exprs.push(BinaryExpr.eq(ColumnRef.of(leftTable, left), ColumnRef.of(rightTable, right)));
2594
+ }
2595
+ if (exprs.length === 1 && exprs[0]) return exprs[0];
2596
+ return and(...exprs);
2597
+ }
2598
+ function toRelationWhereExpr(context, relatedNamespaceId, relatedModelName, predicate) {
2599
+ if (!predicate) return;
2600
+ const accessor = createModelAccessor(context, relatedNamespaceId, relatedModelName);
2601
+ if (typeof predicate === "function") return predicate(accessor);
2602
+ const exprs = [];
2603
+ for (const [fieldName, value] of Object.entries(predicate)) {
2604
+ if (value === void 0) continue;
2605
+ const fieldAccessor = blindCast(accessor)[fieldName];
2606
+ if (!fieldAccessor) throw ormError("ORM.FIELD_UNKNOWN", `Shorthand filter on "${relatedModelName}.${fieldName}": field is not defined on the model`, { meta: {
2607
+ model: relatedModelName,
2608
+ field: fieldName
2609
+ } });
2610
+ if (value === null) {
2611
+ if (!fieldAccessor.isNull) throw new InternalError(`Shorthand filter on "${relatedModelName}.${fieldName}": isNull is unexpectedly missing — this is a bug in trait gating`);
2612
+ exprs.push(fieldAccessor.isNull());
2613
+ continue;
2614
+ }
2615
+ if (!fieldAccessor.eq) throw ormError("ORM.FILTER_UNSUPPORTED", `Shorthand filter on "${relatedModelName}.${fieldName}": field does not support equality comparisons`, { meta: {
2616
+ model: relatedModelName,
2617
+ field: fieldName,
2618
+ trait: "equality"
2619
+ } });
2620
+ exprs.push(fieldAccessor.eq(value));
2621
+ }
2622
+ if (exprs.length === 0) return;
2623
+ return exprs.length === 1 ? exprs[0] : and(...exprs);
2624
+ }
2625
+ function buildJoinWhere(contract, parentNamespaceId, parentModelName, parentTableName, relatedTableName, relation) {
2626
+ const localFields = relation.on?.localFields ?? [];
2627
+ const targetFields = relation.on?.targetFields ?? [];
2628
+ const joinExprs = [];
2629
+ const count = Math.min(localFields.length, targetFields.length);
2630
+ for (let i = 0; i < count; i++) {
2631
+ const localField = localFields[i];
2632
+ const targetField = targetFields[i];
2633
+ if (!localField || !targetField) continue;
2634
+ const localColumn = resolveFieldToColumn(contract, parentNamespaceId, parentModelName, localField);
2635
+ const targetColumn = resolveFieldToColumn(contract, relation.toNamespace, relation.to, targetField);
2636
+ joinExprs.push(BinaryExpr.eq(ColumnRef.of(relatedTableName, targetColumn), ColumnRef.of(parentTableName, localColumn)));
2637
+ }
2638
+ if (joinExprs.length === 0) throw new InternalError("Relation metadata is missing join columns");
2639
+ const firstExpr = joinExprs[0];
2640
+ if (joinExprs.length === 1 && firstExpr !== void 0) return firstExpr;
2641
+ return and(...joinExprs);
2642
+ }
2643
+ function firstTargetColumn(contract, relation) {
2644
+ const firstField = (relation.on?.targetFields)?.[0];
2645
+ if (!firstField) return;
2646
+ return resolveFieldToColumn(contract, relation.toNamespace, relation.to, firstField);
2647
+ }
2648
+ function createRelationMutator() {
2649
+ return {
2650
+ create(data) {
2651
+ return {
2652
+ kind: "create",
2653
+ data: Array.isArray(data) ? [...data] : [data]
2654
+ };
2655
+ },
2656
+ connect(criteria) {
2657
+ return {
2658
+ kind: "connect",
2659
+ criteria: Array.isArray(criteria) ? [...criteria] : [criteria]
2660
+ };
2661
+ },
2662
+ disconnect(criteria) {
2663
+ if (!criteria) return { kind: "disconnect" };
2664
+ return {
2665
+ kind: "disconnect",
2666
+ criteria: [...criteria]
2667
+ };
2668
+ }
2669
+ };
2670
+ }
2671
+ function isRelationMutationDescriptor(value) {
2672
+ if (!value || typeof value !== "object") return false;
2673
+ const candidate = value;
2674
+ if (candidate.kind !== "create" && candidate.kind !== "connect" && candidate.kind !== "disconnect") return false;
2675
+ return true;
2676
+ }
2677
+ function isRelationMutationCallback(value) {
2678
+ return typeof value === "function";
2679
+ }
2680
+ function hasThrough(relation) {
2681
+ return relation.through !== void 0;
2682
+ }
2683
+ function hasNestedMutationCallbacks(contract, namespaceId, modelName, data) {
2684
+ const relationNames = new Set(Object.keys(resolveModelRelations(contract, namespaceId, modelName)));
2685
+ for (const [fieldName, value] of Object.entries(data)) {
2686
+ if (!relationNames.has(fieldName)) continue;
2687
+ if (isRelationMutationCallback(value)) return true;
2688
+ }
2689
+ return false;
2690
+ }
2691
+ async function executeNestedCreateMutation(options) {
2692
+ return withMutationScope(options.runtime, async (scope) => createGraph(scope, options.context, options.namespaceId, options.modelName, options.data));
2693
+ }
2694
+ async function executeNestedUpdateMutation(options) {
2695
+ return withMutationScope(options.runtime, async (scope) => updateFirstGraph(scope, options.context, options.namespaceId, options.modelName, options.filters, options.data));
2696
+ }
2697
+ function buildPrimaryKeyFilterFromRow(contract, namespaceId, modelName, row) {
2698
+ const fieldName = toFieldName(contract, namespaceId, modelName, resolvePrimaryKeyColumn(contract, namespaceId, resolveModelTableName(contract, namespaceId, modelName)));
2699
+ const value = row[fieldName];
2700
+ if (value === void 0) throw new InternalError(`Missing primary key field "${fieldName}" while reloading model "${modelName}"`);
2701
+ return { [fieldName]: value };
2702
+ }
2703
+ async function withMutationScope(runtime, run) {
2704
+ if (typeof runtime.transaction === "function") return runInTransaction(await runtime.transaction(), run);
2705
+ if (typeof runtime.connection === "function") {
2706
+ const connection = await runtime.connection();
2707
+ try {
2708
+ if (typeof connection.transaction === "function") return await runInTransaction(await connection.transaction(), run);
2709
+ return await run(connection);
2710
+ } finally {
2711
+ await connection.release?.();
2712
+ }
2713
+ }
2714
+ return run(runtime);
2715
+ }
2716
+ async function runInTransaction(transaction, run) {
2717
+ try {
2718
+ const result = await run(transaction);
2719
+ if (typeof transaction.commit === "function") await transaction.commit();
2720
+ return result;
2721
+ } catch (error) {
2722
+ if (typeof transaction.rollback === "function") await transaction.rollback();
2723
+ throw error;
2724
+ }
2725
+ }
2726
+ async function createGraph(scope, context, namespaceId, modelName, input) {
2727
+ const contract = context.contract;
2728
+ const parsed = parseMutationInput(contract, namespaceId, modelName, input);
2729
+ const { parentOwned, childOwned, junctionOwned } = partitionByOwnership(parsed.relationMutations);
2730
+ const scalarData = { ...parsed.scalarData };
2731
+ for (const relationMutation of parentOwned) {
2732
+ if (relationMutation.mutation.kind === "disconnect") throw ormError("ORM.RELATION_MUTATION_UNSUPPORTED", "disconnect() is only supported in update() nested mutations", { meta: {
2733
+ kind: "disconnect",
2734
+ relation: relationMutation.relation.relationName
2735
+ } });
2736
+ await applyParentOwnedMutation(scope, context, namespaceId, modelName, scalarData, relationMutation.relation, relationMutation.mutation);
2737
+ }
2738
+ for (const relationMutation of junctionOwned) {
2739
+ if (relationMutation.mutation.kind === "disconnect") throw ormError("ORM.RELATION_MUTATION_UNSUPPORTED", "disconnect() is only supported in update() nested mutations", { meta: {
2740
+ kind: "disconnect",
2741
+ relation: relationMutation.relation.relationName
2742
+ } });
2743
+ await preflightJunctionOwnedCreateMutation(scope, context, relationMutation);
2744
+ }
2745
+ const parentRow = await insertSingleRow(scope, context, namespaceId, modelName, scalarData);
2746
+ for (const relationMutation of childOwned) {
2747
+ if (relationMutation.mutation.kind === "disconnect") throw ormError("ORM.RELATION_MUTATION_UNSUPPORTED", "disconnect() is only supported in update() nested mutations", { meta: {
2748
+ kind: "disconnect",
2749
+ relation: relationMutation.relation.relationName
2750
+ } });
2751
+ await applyChildOwnedMutation(scope, context, namespaceId, modelName, parentRow, relationMutation.relation, relationMutation.mutation);
2752
+ }
2753
+ for (const relationMutation of junctionOwned) await applyJunctionOwnedMutation(scope, context, namespaceId, modelName, parentRow, relationMutation.relation, relationMutation.mutation);
2754
+ return parentRow;
2755
+ }
2756
+ async function updateFirstGraph(scope, context, namespaceId, modelName, filters, input) {
2757
+ const contract = context.contract;
2758
+ const existingRow = await findFirstByFilters(scope, contract, namespaceId, modelName, filters);
2759
+ if (!existingRow) return null;
2760
+ const parsed = parseMutationInput(contract, namespaceId, modelName, input);
2761
+ const { parentOwned, childOwned, junctionOwned } = partitionByOwnership(parsed.relationMutations);
2762
+ const scalarData = { ...parsed.scalarData };
2763
+ for (const relationMutation of parentOwned) await applyParentOwnedMutation(scope, context, namespaceId, modelName, scalarData, relationMutation.relation, relationMutation.mutation);
2764
+ for (const relationMutation of junctionOwned) await preflightJunctionOwnedCreateMutation(scope, context, relationMutation);
2765
+ let parentRow = existingRow;
2766
+ const mappedUpdateData = mapModelDataToStorageRow(contract, namespaceId, modelName, scalarData);
2767
+ if (Object.keys(mappedUpdateData).length > 0) {
2768
+ const tableName = resolveModelTableName(contract, namespaceId, modelName);
2769
+ const appliedUpdateDefaults = context.applyMutationDefaults({
2770
+ op: "update",
2771
+ table: tableName,
2772
+ namespace: namespaceId,
2773
+ values: mappedUpdateData
2774
+ });
2775
+ for (const def of appliedUpdateDefaults) mappedUpdateData[def.column] = def.value;
2776
+ const pkWhere = shorthandToWhereExpr(context, namespaceId, modelName, castAs(buildPrimaryKeyFilterFromRow(contract, namespaceId, modelName, existingRow)));
2777
+ if (!pkWhere) throw new InternalError(`Failed to build primary key filter for model "${modelName}"`);
2778
+ const updatedRaw = (await executeQueryPlan(scope, compileUpdateReturning(contract, namespaceId, tableName, mappedUpdateData, [pkWhere], void 0)).toArray())[0];
2779
+ if (updatedRaw) parentRow = mapStorageRowToModelFields(contract, namespaceId, modelName, updatedRaw);
2780
+ }
2781
+ for (const relationMutation of childOwned) await applyChildOwnedMutation(scope, context, namespaceId, modelName, parentRow, relationMutation.relation, relationMutation.mutation);
2782
+ for (const relationMutation of junctionOwned) await applyJunctionOwnedMutation(scope, context, namespaceId, modelName, parentRow, relationMutation.relation, relationMutation.mutation);
2783
+ return parentRow;
2784
+ }
2785
+ function parseMutationInput(contract, namespaceId, modelName, input) {
2786
+ const scalarData = {};
2787
+ const relationDefinitions = new Map(getRelationDefinitions(contract, namespaceId, modelName).map((relation) => [relation.relationName, relation]));
2788
+ const relationMutations = [];
2789
+ for (const [fieldName, value] of Object.entries(input)) {
2790
+ const relation = relationDefinitions.get(fieldName);
2791
+ if (!relation) {
2792
+ scalarData[fieldName] = value;
2793
+ continue;
2794
+ }
2795
+ if (!isRelationMutationCallback(value)) throw ormError("ORM.RELATION_MUTATION_INVALID", `Relation field "${fieldName}" on model "${modelName}" expects a mutator callback`, { meta: {
2796
+ relation: fieldName,
2797
+ model: modelName,
2798
+ problem: "missing-callback"
2799
+ } });
2800
+ const mutation = value(createRelationMutator());
2801
+ if (!isRelationMutationDescriptor(mutation)) throw ormError("ORM.RELATION_MUTATION_INVALID", `Relation field "${fieldName}" on model "${modelName}" returned an invalid mutation descriptor`, { meta: {
2802
+ relation: fieldName,
2803
+ model: modelName,
2804
+ problem: "invalid-descriptor"
2805
+ } });
2806
+ relationMutations.push({
2807
+ relation,
2808
+ mutation
2809
+ });
2810
+ }
2811
+ return {
2812
+ scalarData,
2813
+ relationMutations
2814
+ };
2815
+ }
2816
+ function partitionByOwnership(relationMutations) {
2817
+ const parentOwned = [];
2818
+ const childOwned = [];
2819
+ const junctionOwned = [];
2820
+ for (const relationMutation of relationMutations) {
2821
+ if (hasThrough(relationMutation.relation)) {
2822
+ junctionOwned.push({
2823
+ relation: relationMutation.relation,
2824
+ mutation: relationMutation.mutation
2825
+ });
2826
+ continue;
2827
+ }
2828
+ if (relationMutation.relation.cardinality === "N:1") {
2829
+ parentOwned.push(relationMutation);
2830
+ continue;
2831
+ }
2832
+ childOwned.push(relationMutation);
2833
+ }
2834
+ return {
2835
+ parentOwned,
2836
+ childOwned,
2837
+ junctionOwned
2838
+ };
2839
+ }
2840
+ async function applyParentOwnedMutation(scope, context, parentNamespaceId, parentModelName, scalarData, relation, mutation) {
2841
+ const contract = context.contract;
2842
+ if (mutation.kind === "disconnect") {
2843
+ for (const localColumn of relation.localColumns) {
2844
+ const parentFieldName = toFieldName(contract, parentNamespaceId, parentModelName, localColumn);
2845
+ scalarData[parentFieldName] = null;
2846
+ }
2847
+ return;
2848
+ }
2849
+ if (mutation.kind === "create") {
2850
+ const row = mutation.data[0];
2851
+ if (!row) throw ormError("ORM.RELATION_MUTATION_INVALID", `create() nested mutation for relation "${relation.relationName}" requires data`, { meta: {
2852
+ kind: "create",
2853
+ relation: relation.relationName,
2854
+ problem: "missing-data"
2855
+ } });
2856
+ copyRelatedValuesToParent(contract, parentNamespaceId, parentModelName, relation, scalarData, await createGraph(scope, context, relation.relatedNamespaceId, relation.relatedModelName, castAs(row)));
2857
+ return;
2858
+ }
2859
+ const criterion = mutation.criteria[0];
2860
+ if (!criterion) throw ormError("ORM.RELATION_MUTATION_INVALID", `connect() nested mutation for relation "${relation.relationName}" requires criterion`, { meta: {
2861
+ kind: "connect",
2862
+ relation: relation.relationName,
2863
+ problem: "missing-criterion"
2864
+ } });
2865
+ const relatedRow = await findRowByCriterion(scope, context, relation.relatedNamespaceId, relation.relatedModelName, castAs(criterion));
2866
+ if (!relatedRow) throw ormError("ORM.RELATION_ROW_MISSING", `connect() nested mutation for relation "${relation.relationName}" did not find a matching row`, { meta: {
2867
+ kind: "connect",
2868
+ relation: relation.relationName
2869
+ } });
2870
+ copyRelatedValuesToParent(contract, parentNamespaceId, parentModelName, relation, scalarData, relatedRow);
2871
+ }
2872
+ function copyRelatedValuesToParent(contract, parentNamespaceId, parentModelName, relation, scalarData, relatedRow) {
2873
+ for (let i = 0; i < relation.localColumns.length; i++) {
2874
+ const localColumn = relation.localColumns[i];
2875
+ const targetColumn = relation.targetColumns[i];
2876
+ if (!localColumn || !targetColumn) continue;
2877
+ const parentFieldName = toFieldName(contract, parentNamespaceId, parentModelName, localColumn);
2878
+ scalarData[parentFieldName] = relatedRow[toFieldName(contract, relation.relatedNamespaceId, relation.relatedModelName, targetColumn)];
2879
+ }
2880
+ }
2881
+ async function applyChildOwnedMutation(scope, context, parentNamespaceId, parentModelName, parentRow, relation, mutation) {
2882
+ const contract = context.contract;
2883
+ const parentValues = readParentColumnValues(contract, parentNamespaceId, parentModelName, relation, parentRow);
2884
+ if (mutation.kind === "create") {
2885
+ for (const childInput of mutation.data) {
2886
+ const payload = { ...castAs(childInput) };
2887
+ for (const [childColumn, parentValue] of parentValues.entries()) {
2888
+ const childFieldName = toFieldName(contract, relation.relatedNamespaceId, relation.relatedModelName, childColumn);
2889
+ payload[childFieldName] = parentValue;
2890
+ }
2891
+ await createGraph(scope, context, relation.relatedNamespaceId, relation.relatedModelName, castAs(payload));
2892
+ }
2893
+ return;
2894
+ }
2895
+ if (mutation.kind === "connect") {
2896
+ for (const criterion of mutation.criteria) {
2897
+ const criterionWhere = shorthandToWhereExpr(context, relation.relatedNamespaceId, relation.relatedModelName, castAs(criterion));
2898
+ if (!criterionWhere) throw ormError("ORM.RELATION_MUTATION_INVALID", `connect() nested mutation for relation "${relation.relationName}" requires non-empty criterion`, { meta: {
2899
+ kind: "connect",
2900
+ relation: relation.relationName,
2901
+ problem: "empty-criterion"
2902
+ } });
2903
+ const setValues = {};
2904
+ for (const [childColumn, parentValue] of parentValues.entries()) setValues[childColumn] = parentValue;
2905
+ await executeUpdateCount(scope, contract, relation.relatedNamespaceId, relation.relatedTableName, setValues, [criterionWhere]);
2906
+ }
2907
+ return;
2908
+ }
2909
+ const setValues = {};
2910
+ for (const childColumn of parentValues.keys()) setValues[childColumn] = null;
2911
+ if (!mutation.criteria || mutation.criteria.length === 0) {
2912
+ const parentJoinWhere = buildChildJoinWhere(relation, parentValues);
2913
+ await executeUpdateCount(scope, contract, relation.relatedNamespaceId, relation.relatedTableName, setValues, [parentJoinWhere]);
2914
+ return;
2915
+ }
2916
+ for (const criterion of mutation.criteria) {
2917
+ const criterionWhere = shorthandToWhereExpr(context, relation.relatedNamespaceId, relation.relatedModelName, castAs(criterion));
2918
+ if (!criterionWhere) throw ormError("ORM.RELATION_MUTATION_INVALID", `disconnect() nested mutation for relation "${relation.relationName}" requires non-empty criterion`, { meta: {
2919
+ kind: "disconnect",
2920
+ relation: relation.relationName,
2921
+ problem: "empty-criterion"
2922
+ } });
2923
+ const parentJoinWhere = buildChildJoinWhere(relation, parentValues);
2924
+ await executeUpdateCount(scope, contract, relation.relatedNamespaceId, relation.relatedTableName, setValues, [and(parentJoinWhere, criterionWhere)]);
2925
+ }
2926
+ }
2927
+ async function applyJunctionOwnedMutation(scope, context, parentNamespaceId, parentModelName, parentRow, relation, mutation) {
2928
+ const contract = context.contract;
2929
+ const parentPkValues = readJunctionParentValues(contract, parentNamespaceId, parentModelName, relation, parentRow);
2930
+ assertJunctionPayloadWritable(relation, mutation.kind);
2931
+ if (mutation.kind === "create") {
2932
+ for (const childInput of mutation.data) await insertJunctionLink(scope, context, relation, parentPkValues, readJunctionTargetValues(contract, relation, await createGraph(scope, context, relation.relatedNamespaceId, relation.relatedModelName, castAs(childInput))), "create");
2933
+ return;
2934
+ }
2935
+ if (mutation.kind === "connect") {
2936
+ for (const criterion of mutation.criteria) await insertJunctionLink(scope, context, relation, parentPkValues, await resolveJunctionTargetValues(scope, context, relation, "connect", criterion), "connect");
2937
+ return;
2938
+ }
2939
+ if (!mutation.criteria || mutation.criteria.length === 0) throw ormError("ORM.RELATION_MUTATION_INVALID", `disconnect() nested mutation for relation "${relation.relationName}" requires criterion`, { meta: {
2940
+ kind: "disconnect",
2941
+ relation: relation.relationName,
2942
+ problem: "missing-criterion"
2943
+ } });
2944
+ for (const criterion of mutation.criteria) await deleteJunctionLink(scope, context, relation, parentPkValues, await resolveJunctionTargetValues(scope, context, relation, "disconnect", criterion));
2945
+ }
2946
+ async function preflightJunctionOwnedCreateMutation(scope, context, relationMutation) {
2947
+ const { relation, mutation } = relationMutation;
2948
+ assertJunctionMetadataShape(relation);
2949
+ assertJunctionPayloadWritable(relation, mutation.kind);
2950
+ if (mutation.kind !== "connect") return;
2951
+ const seenTargetKeys = /* @__PURE__ */ new Set();
2952
+ for (const criterion of mutation.criteria) {
2953
+ const targetValues = await resolveJunctionTargetValues(scope, context, relation, "connect", criterion);
2954
+ const targetKey = JSON.stringify([...targetValues.entries()]);
2955
+ if (seenTargetKeys.has(targetKey)) throw ormError("ORM.RELATION_MUTATION_INVALID", `connect() nested mutation for relation "${relation.relationName}" resolved duplicate junction link targets; remove the duplicate criteria`, { meta: {
2956
+ kind: "connect",
2957
+ relation: relation.relationName,
2958
+ problem: "duplicate-criteria"
2959
+ } });
2960
+ seenTargetKeys.add(targetKey);
2961
+ }
2962
+ }
2963
+ function assertJunctionPayloadWritable(relation, mutationKind) {
2964
+ const through = relation.through;
2965
+ if (mutationKind !== "create" && mutationKind !== "connect" || through.requiredPayloadColumns.length === 0) return;
2966
+ const cols = through.requiredPayloadColumns.map((c) => `\`${c}\``).join(", ");
2967
+ throw ormError("ORM.RELATION_MUTATION_UNSUPPORTED", `Cannot \`${mutationKind}\` on relation \`${relation.relationName}\`: its junction \`${through.table}\` has required column(s) ${cols} the relation API can't populate. Write the \`${through.table}\` junction directly or use the SQL builder.`, { meta: {
2968
+ kind: mutationKind,
2969
+ relation: relation.relationName,
2970
+ reason: "junction-required-columns",
2971
+ junction: through.table
2972
+ } });
2973
+ }
2974
+ async function resolveJunctionTargetValues(scope, context, relation, kind, criterion) {
2975
+ const relatedRow = await findRowByCriterion(scope, context, relation.relatedNamespaceId, relation.relatedModelName, criterion);
2976
+ if (!relatedRow) throw ormError("ORM.RELATION_ROW_MISSING", `${kind}() nested mutation for relation "${relation.relationName}" did not find a matching row`, { meta: {
2977
+ kind,
2978
+ relation: relation.relationName
2979
+ } });
2980
+ return readJunctionTargetValues(context.contract, relation, relatedRow);
2981
+ }
2982
+ function readJunctionParentValues(contract, parentNamespaceId, parentModelName, relation, parentRow) {
2983
+ const values = /* @__PURE__ */ new Map();
2984
+ assertJunctionParentMetadataLength(relation);
2985
+ for (let i = 0; i < relation.through.parentColumns.length; i++) {
2986
+ const junctionColumn = relation.through.parentColumns[i];
2987
+ const parentColumn = relation.localColumns[i];
2988
+ if (junctionColumn === void 0 || parentColumn === void 0) throw new InternalError(`Relation "${relation.relationName}" has incomplete junction metadata for parent columns`);
2989
+ const parentFieldName = toFieldName(contract, parentNamespaceId, parentModelName, parentColumn);
2990
+ const parentValue = parentRow[parentFieldName];
2991
+ if (parentValue === void 0) throw new InternalError(`Nested mutation requires parent field "${parentFieldName}" to be present in returned row`);
2992
+ values.set(junctionColumn, parentValue);
2993
+ }
2994
+ return values;
2995
+ }
2996
+ function readJunctionTargetValues(contract, relation, relatedRow) {
2997
+ const values = /* @__PURE__ */ new Map();
2998
+ assertJunctionTargetMetadataLength(relation);
2999
+ for (let i = 0; i < relation.through.childColumns.length; i++) {
3000
+ const junctionColumn = relation.through.childColumns[i];
3001
+ const targetColumn = relation.through.targetColumns[i];
3002
+ if (junctionColumn === void 0 || targetColumn === void 0) throw new InternalError(`Relation "${relation.relationName}" has incomplete junction metadata for target columns`);
3003
+ const targetFieldName = toFieldName(contract, relation.relatedNamespaceId, relation.relatedModelName, targetColumn);
3004
+ const targetValue = relatedRow[targetFieldName];
3005
+ if (targetValue === void 0) throw new InternalError(`Nested mutation requires target field "${targetFieldName}" to be present in returned row`);
3006
+ values.set(junctionColumn, targetValue);
3007
+ }
3008
+ return values;
3009
+ }
3010
+ function assertJunctionMetadataLength(relation, throughColumnName, throughColumns, pairedColumnName, pairedColumns) {
3011
+ if (throughColumns.length === pairedColumns.length) return;
3012
+ throw new InternalError(`Relation "${relation.relationName}" has invalid junction metadata: ${throughColumnName} has ${throughColumns.length} column(s), but ${pairedColumnName} has ${pairedColumns.length}`);
3013
+ }
3014
+ function assertJunctionParentMetadataLength(relation) {
3015
+ assertJunctionMetadataLength(relation, "parentColumns", relation.through.parentColumns, "localColumns", relation.localColumns);
3016
+ }
3017
+ function assertJunctionTargetMetadataLength(relation) {
3018
+ assertJunctionMetadataLength(relation, "childColumns", relation.through.childColumns, "targetColumns", relation.through.targetColumns);
3019
+ }
3020
+ function assertJunctionMetadataShape(relation) {
3021
+ assertJunctionParentMetadataLength(relation);
3022
+ assertJunctionTargetMetadataLength(relation);
3023
+ }
3024
+ function writeJunctionColumn(junctionRow, through, column, value, relationName) {
3025
+ if (Object.hasOwn(junctionRow, column) && !Object.is(junctionRow[column], value)) throw ormError("ORM.RELATION_MUTATION_INVALID", `Cannot write junction "${through.table}": conflicting values for junction column "${column}"`, { meta: {
3026
+ relation: relationName,
3027
+ junction: through.table,
3028
+ column
3029
+ } });
3030
+ junctionRow[column] = value;
3031
+ }
3032
+ async function insertJunctionLink(scope, context, relation, parentPkValues, targetPkValues, mutationKind) {
3033
+ const through = relation.through;
3034
+ const junctionRow = {};
3035
+ for (const [column, value] of parentPkValues.entries()) writeJunctionColumn(junctionRow, through, column, value, relation.relationName);
3036
+ for (const [column, value] of targetPkValues.entries()) writeJunctionColumn(junctionRow, through, column, value, relation.relationName);
3037
+ const applied = context.applyMutationDefaults({
3038
+ op: "create",
3039
+ table: through.table,
3040
+ namespace: through.namespaceId,
3041
+ values: junctionRow
3042
+ });
3043
+ for (const def of applied) junctionRow[def.column] = def.value;
3044
+ const compiled = compileInsertCount(context.contract, through.namespaceId, through.table, [junctionRow]);
3045
+ try {
3046
+ await executeQueryPlan(scope, compiled).toArray();
3047
+ } catch (error) {
3048
+ if (mutationKind === "connect" && isUniqueConstraintViolation(error)) throw ormError("ORM.RELATION_LINK_DUPLICATE", `connect() nested mutation for relation "${relation.relationName}" violated a unique constraint on junction "${through.table}"; the junction link may already be present`, {
3049
+ meta: {
3050
+ relation: relation.relationName,
3051
+ junction: through.table
3052
+ },
3053
+ cause: error
3054
+ });
3055
+ throw error;
3056
+ }
3057
+ }
3058
+ async function deleteJunctionLink(scope, context, relation, parentPkValues, targetPkValues) {
3059
+ const through = relation.through;
3060
+ const junctionRow = {};
3061
+ for (const [column, value] of parentPkValues.entries()) writeJunctionColumn(junctionRow, through, column, value, relation.relationName);
3062
+ for (const [column, value] of targetPkValues.entries()) writeJunctionColumn(junctionRow, through, column, value, relation.relationName);
3063
+ const exprs = [];
3064
+ for (const [column, value] of Object.entries(junctionRow)) exprs.push(BinaryExpr.eq(ColumnRef.of(through.table, column), LiteralExpr.of(value)));
3065
+ const first = exprs[0];
3066
+ const where = exprs.length === 1 && first !== void 0 ? first : and(...exprs);
3067
+ await executeQueryPlan(scope, compileDeleteCount(context.contract, through.namespaceId, through.table, [where])).toArray();
3068
+ }
3069
+ function readParentColumnValues(contract, parentNamespaceId, parentModelName, relation, parentRow) {
3070
+ const values = /* @__PURE__ */ new Map();
3071
+ for (let i = 0; i < relation.localColumns.length; i++) {
3072
+ const localColumn = relation.localColumns[i];
3073
+ const targetColumn = relation.targetColumns[i];
3074
+ if (!localColumn || !targetColumn) continue;
3075
+ const parentFieldName = toFieldName(contract, parentNamespaceId, parentModelName, localColumn);
3076
+ const parentValue = parentRow[parentFieldName];
3077
+ if (parentValue === void 0) throw new InternalError(`Nested mutation requires parent field "${parentFieldName}" to be present in returned row`);
3078
+ values.set(targetColumn, parentValue);
3079
+ }
3080
+ return values;
3081
+ }
3082
+ function buildChildJoinWhere(relation, childValues) {
3083
+ const exprs = [];
3084
+ for (const [childColumn, parentValue] of childValues.entries()) exprs.push(BinaryExpr.eq(ColumnRef.of(relation.relatedTableName, childColumn), LiteralExpr.of(parentValue)));
3085
+ const first = exprs[0];
3086
+ if (exprs.length === 1 && first !== void 0) return first;
3087
+ return and(...exprs);
3088
+ }
3089
+ async function insertSingleRow(scope, context, namespaceId, modelName, data) {
3090
+ const contract = context.contract;
3091
+ const tableName = resolveModelTableName(contract, namespaceId, modelName);
3092
+ const mappedData = mapModelDataToStorageRow(contract, namespaceId, modelName, data);
3093
+ const applied = context.applyMutationDefaults({
3094
+ op: "create",
3095
+ table: tableName,
3096
+ namespace: namespaceId,
3097
+ values: mappedData
3098
+ });
3099
+ for (const def of applied) mappedData[def.column] = def.value;
3100
+ const firstRow = (await executeQueryPlan(scope, compileInsertReturning(contract, namespaceId, tableName, [mappedData], void 0)).toArray())[0];
3101
+ if (!firstRow) throw ormError("ORM.MUTATION_ROW_MISSING", `Nested create for model "${modelName}" did not return a row`, { meta: {
3102
+ operation: "create",
3103
+ model: modelName,
3104
+ phase: "nested"
3105
+ } });
3106
+ return mapStorageRowToModelFields(contract, namespaceId, modelName, firstRow);
3107
+ }
3108
+ async function findRowByCriterion(scope, context, namespaceId, modelName, criterion) {
3109
+ const contract = context.contract;
3110
+ const whereExpr = shorthandToWhereExpr(context, namespaceId, modelName, castAs(criterion));
3111
+ if (!whereExpr) throw ormError("ORM.RELATION_MUTATION_INVALID", `Nested connect for model "${modelName}" requires non-empty criterion`, { meta: {
3112
+ kind: "connect",
3113
+ model: modelName,
3114
+ problem: "empty-criterion"
3115
+ } });
3116
+ const firstRow = (await executeQueryPlan(scope, compileSelect(contract, namespaceId, resolveModelTableName(contract, namespaceId, modelName), {
3117
+ ...emptyState(),
3118
+ filters: [whereExpr],
3119
+ limit: 1
3120
+ })).toArray())[0];
3121
+ if (!firstRow) return null;
3122
+ return mapStorageRowToModelFields(contract, namespaceId, modelName, firstRow);
3123
+ }
3124
+ async function findFirstByFilters(scope, contract, namespaceId, modelName, filters) {
3125
+ const firstRow = (await executeQueryPlan(scope, compileSelect(contract, namespaceId, resolveModelTableName(contract, namespaceId, modelName), {
3126
+ ...emptyState(),
3127
+ filters,
3128
+ limit: 1
3129
+ })).toArray())[0];
3130
+ if (!firstRow) return null;
3131
+ return mapStorageRowToModelFields(contract, namespaceId, modelName, firstRow);
3132
+ }
3133
+ async function executeUpdateCount(scope, contract, namespaceId, tableName, setValues, filters) {
3134
+ await executeQueryPlan(scope, compileUpdateCount(contract, namespaceId, tableName, setValues, filters)).toArray();
3135
+ }
3136
+ const relationDefsCache = /* @__PURE__ */ new WeakMap();
3137
+ function getRelationDefinitions(contract, namespaceId, modelName) {
3138
+ let perContract = relationDefsCache.get(contract);
3139
+ if (!perContract) {
3140
+ perContract = /* @__PURE__ */ new Map();
3141
+ relationDefsCache.set(contract, perContract);
3142
+ }
3143
+ const cacheKey = `${namespaceId}\u0000${modelName}`;
3144
+ const cached = perContract.get(cacheKey);
3145
+ if (cached) return cached;
3146
+ const relations = resolveModelRelations(contract, namespaceId, modelName);
3147
+ const definitions = Object.entries(relations).map(([relationName, relation]) => ({
3148
+ relationName,
3149
+ relatedModelName: relation.to,
3150
+ relatedNamespaceId: relation.toNamespace,
3151
+ relatedTableName: resolveModelTableName(contract, relation.toNamespace, relation.to),
3152
+ cardinality: relation.cardinality,
3153
+ localColumns: relation.on.localFields.map((f) => resolveFieldToColumn(contract, namespaceId, modelName, f)),
3154
+ targetColumns: relation.on.targetFields.map((f) => resolveFieldToColumn(contract, relation.toNamespace, relation.to, f)),
3155
+ through: relation.through ? {
3156
+ table: relation.through.table,
3157
+ namespaceId: relation.through.namespaceId,
3158
+ parentColumns: relation.through.parentColumns,
3159
+ childColumns: relation.through.childColumns,
3160
+ targetColumns: relation.through.targetColumns,
3161
+ requiredPayloadColumns: relation.through.requiredPayloadColumns
3162
+ } : void 0
3163
+ }));
3164
+ perContract.set(cacheKey, definitions);
3165
+ return definitions;
3166
+ }
3167
+ function toFieldName(contract, namespaceId, modelName, columnName) {
3168
+ return getColumnToFieldMap(contract, namespaceId, modelName)[columnName] ?? columnName;
3169
+ }
3170
+ function normalizeWhereArg(arg, options) {
3171
+ if (arg === void 0) return;
3172
+ if (arg === null) throw ormError("ORM.ARGUMENT_INVALID", "WhereArg cannot be null. Pass undefined or a valid WhereExpr/ToWhereExpr payload.", { meta: { argument: "where" } });
3173
+ if (isToWhereExpr(arg)) return arg.toWhereExpr();
3174
+ if (options?.contract) return bindWhereExpr(options.contract, arg, options.namespaceId);
3175
+ return arg;
3176
+ }
3177
+ function isToWhereExpr(arg) {
3178
+ return typeof arg === "object" && arg !== null && "toWhereExpr" in arg && !isWhereExpr(arg);
3179
+ }
3180
+ function applyCreateDefaults(ctx, namespaceId, tableName, rows) {
3181
+ const defaultValueCache = rows.length > 1 ? /* @__PURE__ */ new Map() : void 0;
3182
+ for (const row of rows) {
3183
+ const applied = ctx.context.applyMutationDefaults({
3184
+ op: "create",
3185
+ table: tableName,
3186
+ namespace: namespaceId,
3187
+ values: row,
3188
+ ...defaultValueCache ? { defaultValueCache } : {}
3189
+ });
3190
+ for (const def of applied) row[def.column] = def.value;
3191
+ }
3192
+ }
3193
+ function applyUpdateDefaults(ctx, namespaceId, tableName, values) {
3194
+ const applied = ctx.context.applyMutationDefaults({
3195
+ op: "update",
3196
+ table: tableName,
3197
+ namespace: namespaceId,
3198
+ values
3199
+ });
3200
+ for (const def of applied) values[def.column] = def.value;
3201
+ }
3202
+ function isToWhereExprInput(value) {
3203
+ return typeof value === "object" && value !== null && "toWhereExpr" in value && typeof value.toWhereExpr === "function";
3204
+ }
3205
+ function isWhereDirectInput(value) {
3206
+ return isWhereExpr(value) && typeof value === "object" && value !== null && "accept" in value && typeof value.accept === "function" || isToWhereExprInput(value);
3207
+ }
3208
+ function isMtiVariantInfo(variant) {
3209
+ return variant?.strategy === "mti";
3210
+ }
3211
+ var Collection = class Collection {
3212
+ /** @internal */
3213
+ ctx;
3214
+ /** @internal */
3215
+ contract;
3216
+ /** @internal */
3217
+ modelName;
3218
+ /** @internal */
3219
+ tableName;
3220
+ /** @internal */
3221
+ namespaceId;
3222
+ /** @internal */
3223
+ state;
3224
+ /** @internal */
3225
+ registry;
3226
+ /** @internal */
3227
+ includeRefinementMode;
3228
+ constructor(ctx, modelName, options) {
3229
+ this.ctx = ctx;
3230
+ this.contract = ctx.context.contract;
3231
+ this.modelName = modelName;
3232
+ this.namespaceId = options.namespaceId;
3233
+ this.tableName = options.tableName ?? resolveModelTableName(this.contract, options.namespaceId, modelName);
3234
+ this.state = options.state ?? emptyState();
3235
+ this.registry = options.registry ?? /* @__PURE__ */ new Map();
3236
+ this.includeRefinementMode = options.includeRefinementMode ?? false;
3237
+ }
3238
+ where(input) {
3239
+ const filter = normalizeWhereArg(typeof input === "function" ? input(createModelAccessor(this.ctx.context, this.namespaceId, this.modelName, this.state.variantName)) : isWhereDirectInput(input) ? input : shorthandToWhereExpr(this.ctx.context, this.namespaceId, this.modelName, input), {
3240
+ contract: this.contract,
3241
+ namespaceId: this.namespaceId
3242
+ });
3243
+ if (!filter) return blindCast(this);
3244
+ return this.#clone({ filters: [...this.state.filters, filter] });
3245
+ }
3246
+ /**
3247
+ * Narrow a polymorphic model to a specific variant. The returned
3248
+ * collection has the variant's row shape and a discriminator filter
3249
+ * is automatically applied. Chaining `.variant(...)` again replaces
3250
+ * the previous variant filter.
3251
+ *
3252
+ * ```typescript
3253
+ * // Read only admin users (STI):
3254
+ * const admins = await db.orm.User.variant('Admin').all();
3255
+ *
3256
+ * // Iterate the rows:
3257
+ * for await (const admin of db.orm.User.variant('Admin').all()) {
3258
+ * console.log(admin.role);
3259
+ * }
3260
+ *
3261
+ * // Insert under a variant — discriminator is injected automatically:
3262
+ * await db.orm.User.variant('Admin').create({ name: 'Ada', role: 'super' });
3263
+ * ```
3264
+ */
3265
+ variant(variantName) {
3266
+ const model = modelOf(this.contract, this.namespaceId, this.modelName);
3267
+ const discriminator = model?.discriminator;
3268
+ const variants = model?.variants;
3269
+ if (!discriminator || !variants) return blindCast(this);
3270
+ const variantEntry = variants[variantName];
3271
+ if (!variantEntry) return blindCast(this);
3272
+ const columnName = resolveFieldToColumn(this.contract, this.namespaceId, this.modelName, discriminator.field);
3273
+ const filter = BinaryExpr.eq(ColumnRef.of(this.tableName, columnName), LiteralExpr.of(variantEntry.value));
3274
+ const filtersWithoutPreviousVariant = this.state.variantName ? this.state.filters.filter((f) => !(f instanceof BinaryExpr && f.left instanceof ColumnRef && f.left.column === columnName && f.left.table === this.tableName)) : this.state.filters;
3275
+ return this.#cloneWithRow({
3276
+ filters: [...filtersWithoutPreviousVariant, filter],
3277
+ variantName
3278
+ });
3279
+ }
3280
+ /**
3281
+ * Eagerly load a related model. The relation appears on every
3282
+ * returned row under its declared name; to-one relations are mapped
3283
+ * to a single object (or `null`), to-many relations to an array.
3284
+ *
3285
+ * An optional refinement callback receives a child collection that
3286
+ * can be further constrained, projected, ordered, paginated, or
3287
+ * reduced to scalars via `count()`/`sum()`/etc. or to multiple
3288
+ * sub-aggregates via `combine()`.
3289
+ *
3290
+ * ```typescript
3291
+ * // Simple include — every user comes back with its posts array:
3292
+ * const users = await db.orm.User.include('posts').all();
3293
+ *
3294
+ * // Refine the related collection:
3295
+ * const withRecent = await db.orm.User.include('posts', (posts) =>
3296
+ * posts.where({ published: true }).orderBy((p) => p.createdAt.desc()).take(5),
3297
+ * ).all();
3298
+ *
3299
+ * // Reduce a to-many relation to a scalar value:
3300
+ * const withCounts = await db.orm.User.include('posts', (posts) => posts.count()).all();
3301
+ *
3302
+ * // Multiple sub-views via combine():
3303
+ * const overview = await db.orm.User.include('posts', (posts) =>
3304
+ * posts.combine({ recent: posts.take(3), total: posts.count() }),
3305
+ * ).all();
3306
+ * ```
3307
+ */
3308
+ include(relationName, refineFn) {
3309
+ const relation = resolveIncludeRelation(this.contract, this.namespaceId, this.modelName, relationName, this.state.variantName);
3310
+ let nestedState = emptyState();
3311
+ let scalarSelector;
3312
+ let combineBranches;
3313
+ if (refineFn) {
3314
+ const refined = refineFn(this.#createCollection(blindCast(relation.relatedModelName), {
3315
+ tableName: relation.relatedTableName,
3316
+ namespaceId: relation.relatedNamespaceId,
3317
+ state: emptyState(),
3318
+ includeRefinementMode: true
3319
+ }));
3320
+ if (isIncludeScalar(refined)) {
3321
+ if (isToOneCardinality(relation.cardinality)) throw ormError("ORM.INCLUDE_UNSUPPORTED", `include('${relationName}') scalar aggregations are only supported for to-many relations`, { meta: {
3322
+ relation: relationName,
3323
+ kind: "scalar"
3324
+ } });
3325
+ scalarSelector = refined;
3326
+ nestedState = refined.state;
3327
+ } else if (isIncludeCombine(refined)) {
3328
+ if (isToOneCardinality(relation.cardinality)) throw ormError("ORM.INCLUDE_UNSUPPORTED", `include('${relationName}') combine() is only supported for to-many relations`, { meta: {
3329
+ relation: relationName,
3330
+ kind: "combine"
3331
+ } });
3332
+ combineBranches = refined.branches;
3333
+ } else if (isCollectionStateCarrier(refined)) nestedState = refined.state;
3334
+ else throw ormError("ORM.INCLUDE_INVALID", `include('${relationName}') refinement must return a collection, include scalar selector, or combine() descriptor`, { meta: { relation: relationName } });
3335
+ }
3336
+ const includeExpr = {
3337
+ relationName,
3338
+ relatedModelName: relation.relatedModelName,
3339
+ relatedNamespaceId: relation.relatedNamespaceId,
3340
+ relatedTableName: relation.relatedTableName,
3341
+ localTableName: relation.localTableName,
3342
+ targetColumn: relation.targetColumn,
3343
+ localColumn: relation.localColumn,
3344
+ cardinality: relation.cardinality,
3345
+ ...ifDefined("through", relation.through),
3346
+ nested: nestedState,
3347
+ scalar: scalarSelector,
3348
+ combine: combineBranches
3349
+ };
3350
+ return this.#cloneWithRow({ includes: [...this.state.includes, includeExpr] });
3351
+ }
3352
+ /**
3353
+ * Project the row down to a subset of scalar fields. Previously
3354
+ * included relations are preserved on the resulting row shape; only
3355
+ * scalar columns are narrowed.
3356
+ *
3357
+ * ```typescript
3358
+ * const summaries = await db.orm.User.select('id', 'email').all();
3359
+ * // typeof summaries[number] === { id: ...; email: ... }
3360
+ *
3361
+ * for await (const row of db.orm.User.select('id', 'email').all()) {
3362
+ * console.log(row.id, row.email);
3363
+ * }
3364
+ * ```
3365
+ */
3366
+ select(...fields) {
3367
+ const selectedFields = mapFieldsToColumns(this.contract, this.namespaceId, this.modelName, fields);
3368
+ return this.#cloneWithRow({ selectedFields });
3369
+ }
3370
+ /**
3371
+ * Append an `ORDER BY` clause. Pass a single selector callback or an
3372
+ * array of callbacks; each receives a typed model accessor whose
3373
+ * columns expose `.asc()` and `.desc()`. Multiple calls append to the
3374
+ * existing list (left-to-right ordering preserved).
3375
+ *
3376
+ * Calling `orderBy(...)` unlocks `cursor(...)` and `distinctOn(...)`,
3377
+ * which both require a defined sort order.
3378
+ *
3379
+ * ```typescript
3380
+ * const newest = await db.orm.User.orderBy((u) => u.createdAt.desc()).all();
3381
+ *
3382
+ * const byName = await db.orm.User
3383
+ * .orderBy([(u) => u.lastName.asc(), (u) => u.firstName.asc()])
3384
+ * .all();
3385
+ * ```
3386
+ */
3387
+ orderBy(selection) {
3388
+ const accessor = createModelAccessor(this.ctx.context, this.namespaceId, this.modelName, this.state.variantName);
3389
+ const nextOrders = (Array.isArray(selection) ? selection : [selection]).map((selector) => selector(accessor));
3390
+ const existing = this.state.orderBy ?? [];
3391
+ return this.#clone({ orderBy: [...existing, ...nextOrders] });
3392
+ }
3393
+ /**
3394
+ * Switch to grouped-aggregate mode. Returns a `GroupedCollection`
3395
+ * whose `.aggregate(...)` terminal produces one row per group with
3396
+ * the chosen key columns plus the requested aggregates.
3397
+ *
3398
+ * ```typescript
3399
+ * const stats = await db.orm.Post
3400
+ * .where({ published: true })
3401
+ * .groupBy('userId')
3402
+ * .aggregate((agg) => ({ count: agg.count(), totalViews: agg.sum('views') }));
3403
+ * // [{ userId: 1, count: 3, totalViews: 120 }, ...]
3404
+ * ```
3405
+ */
3406
+ groupBy(...fields) {
3407
+ const groupByColumns = mapFieldsToColumns(this.contract, this.namespaceId, this.modelName, fields);
3408
+ return new GroupedCollection(this.ctx, this.modelName, {
3409
+ tableName: this.tableName,
3410
+ namespaceId: this.namespaceId,
3411
+ baseFilters: this.state.filters,
3412
+ groupByFields: [...fields],
3413
+ groupByColumns,
3414
+ havingFilters: []
3415
+ });
3416
+ }
3417
+ /**
3418
+ * Scalar reducer — reduces a to-many relation to the number of
3419
+ * related rows. Use inside an `include(...)` refinement callback as
3420
+ * `include(..., (rel) => rel.count())`; throws if called elsewhere.
3421
+ * The parent row's relation field becomes that count instead of an
3422
+ * array.
3423
+ *
3424
+ * ```typescript
3425
+ * const users = await db.orm.User.include('posts', (posts) => posts.count()).all();
3426
+ * // each user row: { ...user, posts: number }
3427
+ * ```
3428
+ */
3429
+ count() {
3430
+ this.#assertIncludeRefinementMode("count()");
3431
+ return createIncludeScalar("count", this.state);
3432
+ }
3433
+ /**
3434
+ * Scalar reducer — reduces a to-many relation to the sum of `field`
3435
+ * across related rows. Returns `null` when there are no related
3436
+ * rows. Use inside an `include(...)` refinement callback; throws if
3437
+ * called elsewhere.
3438
+ *
3439
+ * ```typescript
3440
+ * const users = await db.orm.User.include('posts', (posts) => posts.sum('views')).all();
3441
+ * // each user row: { ...user, posts: number | null }
3442
+ * ```
3443
+ */
3444
+ sum(field) {
3445
+ this.#assertIncludeRefinementMode("sum()");
3446
+ const columnName = resolveFieldToColumn(this.contract, this.namespaceId, this.modelName, field);
3447
+ return createIncludeScalar("sum", this.state, columnName);
3448
+ }
3449
+ /**
3450
+ * Scalar reducer — reduces a to-many relation to the average of
3451
+ * `field` across related rows. Returns `null` when there are no
3452
+ * related rows. Use inside an `include(...)` refinement callback;
3453
+ * throws if called elsewhere.
3454
+ *
3455
+ * ```typescript
3456
+ * const users = await db.orm.User.include('posts', (posts) => posts.avg('views')).all();
3457
+ * // each user row: { ...user, posts: number | null }
3458
+ * ```
3459
+ */
3460
+ avg(field) {
3461
+ this.#assertIncludeRefinementMode("avg()");
3462
+ const columnName = resolveFieldToColumn(this.contract, this.namespaceId, this.modelName, field);
3463
+ return createIncludeScalar("avg", this.state, columnName);
3464
+ }
3465
+ /**
3466
+ * Scalar reducer — reduces a to-many relation to the minimum value
3467
+ * of `field` across related rows. Returns `null` when there are no
3468
+ * related rows. Use inside an `include(...)` refinement callback;
3469
+ * throws if called elsewhere.
3470
+ *
3471
+ * ```typescript
3472
+ * const users = await db.orm.User.include('posts', (posts) => posts.min('views')).all();
3473
+ * ```
3474
+ */
3475
+ min(field) {
3476
+ this.#assertIncludeRefinementMode("min()");
3477
+ const columnName = resolveFieldToColumn(this.contract, this.namespaceId, this.modelName, field);
3478
+ return createIncludeScalar("min", this.state, columnName);
3479
+ }
3480
+ /**
3481
+ * Scalar reducer — reduces a to-many relation to the maximum value
3482
+ * of `field` across related rows. Returns `null` when there are no
3483
+ * related rows. Use inside an `include(...)` refinement callback;
3484
+ * throws if called elsewhere.
3485
+ *
3486
+ * ```typescript
3487
+ * const users = await db.orm.User.include('posts', (posts) => posts.max('views')).all();
3488
+ * ```
3489
+ */
3490
+ max(field) {
3491
+ this.#assertIncludeRefinementMode("max()");
3492
+ const columnName = resolveFieldToColumn(this.contract, this.namespaceId, this.modelName, field);
3493
+ return createIncludeScalar("max", this.state, columnName);
3494
+ }
3495
+ /**
3496
+ * Produce multiple named sub-views of a to-many relation in a
3497
+ * single `include(...)`. Each branch is either another refined
3498
+ * collection (mapped to a row array on the parent) or a scalar
3499
+ * reducer such as `count()`/`sum(...)`. Only valid inside an
3500
+ * `include(...)` refinement callback for to-many relations.
3501
+ *
3502
+ * ```typescript
3503
+ * const users = await db.orm.User.include('posts', (posts) =>
3504
+ * posts.combine({
3505
+ * recent: posts.where({ published: true }).take(3),
3506
+ * total: posts.count(),
3507
+ * averageViews: posts.avg('views'),
3508
+ * }),
3509
+ * ).all();
3510
+ * // each user row: {
3511
+ * // ...user,
3512
+ * // posts: { recent: Post[]; total: number; averageViews: number | null };
3513
+ * // }
3514
+ * ```
3515
+ */
3516
+ combine(spec) {
3517
+ this.#assertIncludeRefinementMode("combine()");
3518
+ const branches = {};
3519
+ for (const [name, value] of Object.entries(spec)) {
3520
+ if (isIncludeScalar(value)) {
3521
+ branches[name] = {
3522
+ kind: "scalar",
3523
+ selector: value
3524
+ };
3525
+ continue;
3526
+ }
3527
+ if (isCollectionStateCarrier(value)) {
3528
+ branches[name] = {
3529
+ kind: "rows",
3530
+ state: value.state
3531
+ };
3532
+ continue;
3533
+ }
3534
+ throw ormError("ORM.INCLUDE_INVALID", `include().combine() branch "${name}" is invalid`, { meta: { branch: name } });
3535
+ }
3536
+ return createIncludeCombine(branches);
3537
+ }
3538
+ /**
3539
+ * Resume pagination from a known cursor position. Requires a prior
3540
+ * `orderBy(...)` so the cursor has a stable basis; provide a value
3541
+ * for every column referenced by the active `orderBy(...)` so each
3542
+ * ordered axis has a defined boundary.
3543
+ *
3544
+ * ```typescript
3545
+ * const page1 = await db.orm.Post
3546
+ * .orderBy((p) => p.createdAt.desc())
3547
+ * .take(20)
3548
+ * .all();
3549
+ *
3550
+ * const last = page1[page1.length - 1]!;
3551
+ * const page2 = await db.orm.Post
3552
+ * .orderBy((p) => p.createdAt.desc())
3553
+ * .cursor({ createdAt: last.createdAt })
3554
+ * .take(20)
3555
+ * .all();
3556
+ * ```
3557
+ */
3558
+ cursor(cursorValues) {
3559
+ const mappedCursor = mapCursorValuesToColumns(this.contract, this.namespaceId, this.modelName, cursorValues);
3560
+ if (Object.keys(mappedCursor).length === 0) return this;
3561
+ return this.#clone({ cursor: mappedCursor });
3562
+ }
3563
+ /**
3564
+ * Emit `SELECT DISTINCT` keyed on the given fields. Replaces any
3565
+ * previous `distinct(...)` / `distinctOn(...)` selection.
3566
+ *
3567
+ * ```typescript
3568
+ * const groups = await db.orm.User.distinct('country', 'role').all();
3569
+ * ```
3570
+ */
3571
+ distinct(...fields) {
3572
+ const distinctFields = mapFieldsToColumns(this.contract, this.namespaceId, this.modelName, fields);
3573
+ return this.#clone({
3574
+ distinct: distinctFields,
3575
+ distinctOn: void 0
3576
+ });
3577
+ }
3578
+ /**
3579
+ * Emit `SELECT DISTINCT ON (fields)` — keep the first row per
3580
+ * distinct key according to the current `orderBy(...)`. Requires a
3581
+ * prior `orderBy(...)`; replaces any previous `distinct(...)` /
3582
+ * `distinctOn(...)` selection.
3583
+ *
3584
+ * ```typescript
3585
+ * // Latest post per user:
3586
+ * const latestPerUser = await db.orm.Post
3587
+ * .orderBy([(p) => p.userId.asc(), (p) => p.createdAt.desc()])
3588
+ * .distinctOn('userId')
3589
+ * .all();
3590
+ * ```
3591
+ */
3592
+ distinctOn(...fields) {
3593
+ const distinctOnFields = mapFieldsToColumns(this.contract, this.namespaceId, this.modelName, fields);
3594
+ return this.#clone({
3595
+ distinct: void 0,
3596
+ distinctOn: distinctOnFields
3597
+ });
3598
+ }
3599
+ /**
3600
+ * Apply `LIMIT n`. Replaces any previous limit set on this collection.
3601
+ *
3602
+ * ```typescript
3603
+ * const firstTen = await db.orm.User.orderBy((u) => u.id.asc()).take(10).all();
3604
+ * ```
3605
+ */
3606
+ take(n) {
3607
+ return this.#clone({ limit: n });
3608
+ }
3609
+ /**
3610
+ * Apply `OFFSET n`. Replaces any previous offset set on this collection.
3611
+ *
3612
+ * ```typescript
3613
+ * const page2 = await db.orm.User
3614
+ * .orderBy((u) => u.id.asc())
3615
+ * .skip(10)
3616
+ * .take(10)
3617
+ * .all();
3618
+ * ```
3619
+ */
3620
+ skip(n) {
3621
+ return this.#clone({ offset: n });
3622
+ }
3623
+ /**
3624
+ * Read terminal: execute the query and stream every matching row.
3625
+ *
3626
+ * The returned `AsyncIterableResult<Row>` is BOTH a thenable that
3627
+ * resolves to `Row[]` (so `await` collects all rows into an array)
3628
+ * AND an async iterable (so `for await` streams rows as they
3629
+ * arrive, without buffering the whole result set in memory). Pick
3630
+ * whichever fits the caller. A single result can only be consumed
3631
+ * once.
3632
+ *
3633
+ * Streaming is the default and the expected execution model. The
3634
+ * only scenarios that fall back to buffering internally before
3635
+ * yielding are drivers that cannot expose a cursor to the
3636
+ * underlying database, and — for queries with `include(...)` —
3637
+ * targets whose SQL dialect supports neither lateral joins nor
3638
+ * correlated subqueries (so child rows cannot be stitched in a
3639
+ * single streaming query). These are implementation details below
3640
+ * the public API; the iteration shape itself is genuinely
3641
+ * streaming whenever the driver and plan allow it.
3642
+ *
3643
+ * ```typescript
3644
+ * // Thenable — collect to an array:
3645
+ * const users = await db.orm.User.all();
3646
+ * for (const user of users) console.log(user.id);
3647
+ *
3648
+ * // Async iterable — stream rows as they arrive:
3649
+ * for await (const user of db.orm.User.all()) {
3650
+ * console.log(user.id);
3651
+ * }
3652
+ * ```
3653
+ *
3654
+ * Accepts an optional `configure` callback that receives a
3655
+ * `MetaBuilder<'read'>` so the caller can attach typed user
3656
+ * annotations to the executed plan. `meta.annotate(...)` enforces
3657
+ * applicability at the type level and at runtime; annotations are
3658
+ * merged into `plan.meta.annotations` at compile time.
3659
+ *
3660
+ * ```typescript
3661
+ * await db.orm.User.all((meta) => meta.annotate(cacheAnnotation({ ttl: 60 })));
3662
+ * ```
3663
+ */
3664
+ all(configure) {
3665
+ return this.#withAnnotationsFromMeta(configure, "all").#dispatch();
3666
+ }
3667
+ async first(filter, configure) {
3668
+ return (await (filter === void 0 ? this : typeof filter === "function" ? this.where(filter) : this.where(filter)).take(1).#withAnnotationsFromMeta(configure, "first").#dispatch().toArray())[0] ?? null;
3669
+ }
3670
+ /**
3671
+ * Read terminal: run an aggregate query (count, sum, avg, min, max)
3672
+ * built via the `AggregateBuilder` callback. Returns one object
3673
+ * with the requested aggregate values keyed by the aliases supplied
3674
+ * in the spec.
3675
+ *
3676
+ * ```typescript
3677
+ * const stats = await db.orm.Post
3678
+ * .where({ published: true })
3679
+ * .aggregate((agg) => ({
3680
+ * total: agg.count(),
3681
+ * averageViews: agg.avg('views'),
3682
+ * maxViews: agg.max('views'),
3683
+ * }));
3684
+ * // { total: 42, averageViews: 17.3, maxViews: 9001 }
3685
+ * ```
3686
+ *
3687
+ * Accepts an optional `configure` callback that receives a
3688
+ * `MetaBuilder<'read'>` for attaching typed annotations.
3689
+ * Annotations are merged into the compiled plan's `meta.annotations`.
3690
+ */
3691
+ async aggregate(fn, configure) {
3692
+ const aggregateSpec = fn(createAggregateBuilder(this.contract, this.namespaceId, this.modelName));
3693
+ const entries = Object.entries(aggregateSpec);
3694
+ if (entries.length === 0) throw ormError("ORM.AGGREGATE_SELECTOR_MISSING", "aggregate() requires at least one aggregation selector", { meta: {
3695
+ method: "aggregate",
3696
+ model: this.modelName
3697
+ } });
3698
+ for (const [alias, selector] of entries) if (!isAggregateSelector(selector)) throw ormError("ORM.AGGREGATE_SELECTOR_INVALID", `aggregate() selector "${alias}" is invalid`, { meta: {
3699
+ method: "aggregate",
3700
+ model: this.modelName,
3701
+ alias
3702
+ } });
3703
+ const annotationsMap = this.#collectAnnotationsFromMeta(configure, "read", "aggregate");
3704
+ const compiled = mergeAnnotations(compileAggregate(this.contract, this.namespaceId, this.tableName, this.state.filters, aggregateSpec), annotationsMap);
3705
+ return normalizeAggregateResult(aggregateSpec, (await executeQueryPlan(this.ctx.runtime, compiled).toArray())[0] ?? {});
3706
+ }
3707
+ async create(data, configure) {
3708
+ assertReturningCapability(this.contract, "create()");
3709
+ const annotationsMap = this.#collectAnnotationsFromMeta(configure, "write", "create");
3710
+ if (hasNestedMutationCallbacks(this.contract, this.namespaceId, this.modelName, blindCast(data))) {
3711
+ const createdRow = await executeNestedCreateMutation({
3712
+ context: this.ctx.context,
3713
+ runtime: this.ctx.runtime,
3714
+ namespaceId: this.namespaceId,
3715
+ modelName: this.modelName,
3716
+ data: blindCast(data)
3717
+ });
3718
+ const pkCriterion = buildPrimaryKeyFilterFromRow(this.contract, this.namespaceId, this.modelName, createdRow);
3719
+ const reloaded = await this.#reloadMutationRowByPrimaryKey(pkCriterion);
3720
+ if (!reloaded) throw ormError("ORM.MUTATION_ROW_MISSING", `create() for model "${this.modelName}" did not return a row`, { meta: {
3721
+ operation: "create",
3722
+ model: this.modelName
3723
+ } });
3724
+ return reloaded;
3725
+ }
3726
+ const created = (await this.#createAllWithAnnotations([blindCast(data)], annotationsMap))[0];
3727
+ if (created) return created;
3728
+ throw ormError("ORM.MUTATION_ROW_MISSING", `create() for model "${this.modelName}" did not return a row`, { meta: {
3729
+ operation: "create",
3730
+ model: this.modelName
3731
+ } });
3732
+ }
3733
+ /**
3734
+ * Write terminal: insert many rows and stream the inserted rows.
3735
+ *
3736
+ * The returned `AsyncIterableResult<Row>` is BOTH a thenable that
3737
+ * resolves to `Row[]` AND an async iterable that streams inserted
3738
+ * rows as they arrive. Use whichever shape fits the caller — but
3739
+ * only consume it once. Streaming is the default; some
3740
+ * driver/plan combinations may still buffer internally before
3741
+ * yielding.
3742
+ *
3743
+ * ```typescript
3744
+ * // Thenable — collect all inserted rows into an array:
3745
+ * const created = await db.orm.User.createAll([
3746
+ * { email: 'a@example.com' },
3747
+ * { email: 'b@example.com' },
3748
+ * ]);
3749
+ *
3750
+ * // Async iterable — stream inserted rows as they arrive:
3751
+ * for await (const row of db.orm.User.createAll(seedUsers)) {
3752
+ * console.log('inserted', row.id);
3753
+ * }
3754
+ * ```
3755
+ *
3756
+ * Accepts an optional `configure` callback that receives a
3757
+ * `MetaBuilder<'write'>` for attaching typed annotations to the
3758
+ * compiled insert plan.
3759
+ */
3760
+ createAll(data, configure) {
3761
+ return this.#createAllWithAnnotations(data, this.#collectAnnotationsFromMeta(configure, "write", "createAll"));
3762
+ }
3763
+ #createAllWithAnnotations(data, annotationsMap) {
3764
+ if (data.length === 0) {
3765
+ const generator = async function* () {};
3766
+ return new AsyncIterableResult(generator());
3767
+ }
3768
+ assertReturningCapability(this.contract, "createAll()");
3769
+ const rows = blindCast(data);
3770
+ const mtiContext = this.#resolveMtiCreateContext();
3771
+ if (mtiContext) return this.#executeMtiCreate(rows, mtiContext);
3772
+ const mappedRows = this.#mapCreateRows(rows);
3773
+ applyCreateDefaults(this.ctx, this.namespaceId, this.tableName, mappedRows);
3774
+ const { selectedForQuery: selectedForInsert, hiddenColumns } = this.#augmentMutationSelection();
3775
+ if (this.contract.capabilities?.["sql"]?.["defaultInInsert"] !== true) {
3776
+ const plans = compileInsertReturningSplit(this.contract, this.namespaceId, this.tableName, mappedRows, selectedForInsert).map((plan) => mergeAnnotations(plan, annotationsMap));
3777
+ return dispatchSplitMutationRows({
3778
+ context: this.ctx.context,
3779
+ runtime: this.ctx.runtime,
3780
+ plans,
3781
+ tableName: this.tableName,
3782
+ modelName: this.modelName,
3783
+ namespaceId: this.namespaceId,
3784
+ variantName: this.state.variantName,
3785
+ includes: this.state.includes,
3786
+ selectedFields: this.state.selectedFields,
3787
+ hiddenColumns,
3788
+ mapRow: (mapped) => blindCast(mapped)
3789
+ });
3790
+ }
3791
+ const compiled = mergeAnnotations(compileInsertReturning(this.contract, this.namespaceId, this.tableName, mappedRows, selectedForInsert), annotationsMap);
3792
+ return dispatchMutationRows({
3793
+ context: this.ctx.context,
3794
+ runtime: this.ctx.runtime,
3795
+ compiled,
3796
+ tableName: this.tableName,
3797
+ modelName: this.modelName,
3798
+ namespaceId: this.namespaceId,
3799
+ variantName: this.state.variantName,
3800
+ includes: this.state.includes,
3801
+ selectedFields: this.state.selectedFields,
3802
+ hiddenColumns,
3803
+ mapRow: (mapped) => blindCast(mapped)
3804
+ });
3805
+ }
3806
+ #assertNotMtiVariant(method) {
3807
+ if (this.#resolveMtiCreateContext()) throw ormError("ORM.OPERATION_UNSUPPORTED", `${method} is not supported for MTI variant "${this.state.variantName}" on model "${this.modelName}". Use createAll() instead.`, { meta: {
3808
+ method,
3809
+ model: this.modelName,
3810
+ variant: this.state.variantName,
3811
+ reason: "mti-variant"
3812
+ } });
3813
+ }
3814
+ #resolveMtiCreateContext() {
3815
+ const variantName = this.state.variantName;
3816
+ if (!variantName) return null;
3817
+ const polyInfo = resolvePolymorphismInfo(this.contract, this.namespaceId, this.modelName);
3818
+ if (!polyInfo) return null;
3819
+ const variant = polyInfo.variants.get(variantName);
3820
+ if (!isMtiVariantInfo(variant)) return null;
3821
+ return {
3822
+ polyInfo,
3823
+ variant,
3824
+ baseFieldToColumn: getFieldToColumnMap(this.contract, this.namespaceId, this.modelName),
3825
+ variantFieldToColumn: getFieldToColumnMap(this.contract, this.namespaceId, variant.modelName),
3826
+ pkColumn: resolvePrimaryKeyColumn(this.contract, this.namespaceId, this.tableName)
3827
+ };
3828
+ }
3829
+ #executeMtiCreate(data, mtiCtx) {
3830
+ const { polyInfo, variant, baseFieldToColumn, variantFieldToColumn, pkColumn } = mtiCtx;
3831
+ const contract = this.contract;
3832
+ const collectionCtx = this.ctx;
3833
+ const runtime = collectionCtx.runtime;
3834
+ const tableName = this.tableName;
3835
+ const modelName = this.modelName;
3836
+ const namespaceId = this.namespaceId;
3837
+ const baseFieldColumns = new Set(Object.values(baseFieldToColumn));
3838
+ const variantFieldColumns = new Set(Object.values(variantFieldToColumn));
3839
+ const mergedFieldToColumn = {
3840
+ ...baseFieldToColumn,
3841
+ ...variantFieldToColumn
3842
+ };
3843
+ const generator = async function* () {
3844
+ for (const row of data) {
3845
+ const allMapped = {};
3846
+ for (const [fieldName, value] of Object.entries(row)) {
3847
+ if (value === void 0) continue;
3848
+ const columnName = mergedFieldToColumn[fieldName] ?? fieldName;
3849
+ allMapped[columnName] = value;
3850
+ }
3851
+ allMapped[polyInfo.discriminatorColumn] = variant.value;
3852
+ const baseRow = {};
3853
+ const variantRow = {};
3854
+ for (const [col, val] of Object.entries(allMapped)) {
3855
+ if (baseFieldColumns.has(col) || col === polyInfo.discriminatorColumn) baseRow[col] = val;
3856
+ if (variantFieldColumns.has(col)) variantRow[col] = val;
3857
+ }
3858
+ yield blindCast(await withMutationScope(runtime, async (scope) => {
3859
+ applyCreateDefaults(collectionCtx, namespaceId, tableName, [baseRow]);
3860
+ const baseCreated = (await executeQueryPlan(scope, compileInsertReturning(contract, namespaceId, tableName, [baseRow], void 0)).toArray())[0];
3861
+ if (!baseCreated) throw ormError("ORM.MUTATION_ROW_MISSING", `MTI base INSERT for model "${modelName}" did not return a row`, { meta: {
3862
+ operation: "create",
3863
+ model: modelName,
3864
+ table: tableName,
3865
+ phase: "mti-base"
3866
+ } });
3867
+ const pkValue = baseCreated[pkColumn];
3868
+ variantRow[pkColumn] = pkValue;
3869
+ applyCreateDefaults(collectionCtx, namespaceId, variant.table, [variantRow]);
3870
+ const variantCreated = (await executeQueryPlan(scope, compileInsertReturning(contract, namespaceId, variant.table, [variantRow], void 0)).toArray())[0];
3871
+ if (!variantCreated) throw ormError("ORM.MUTATION_ROW_MISSING", `MTI variant INSERT for model "${modelName}" into "${variant.table}" did not return a row`, { meta: {
3872
+ operation: "create",
3873
+ model: modelName,
3874
+ table: variant.table,
3875
+ phase: "mti-variant"
3876
+ } });
3877
+ const prefixedVariant = {};
3878
+ for (const [col, val] of Object.entries(variantCreated)) {
3879
+ if (col === pkColumn) continue;
3880
+ prefixedVariant[`${variant.table}__${col}`] = val;
3881
+ }
3882
+ return mapPolymorphicRow(contract, namespaceId, modelName, polyInfo, {
3883
+ ...baseCreated,
3884
+ ...prefixedVariant
3885
+ }, variant.modelName);
3886
+ }));
3887
+ }
3888
+ };
3889
+ return new AsyncIterableResult(generator());
3890
+ }
3891
+ #mapCreateRows(data) {
3892
+ const variantName = this.state.variantName;
3893
+ if (!variantName) return data.map((row) => mapModelDataToStorageRow(this.contract, this.namespaceId, this.modelName, row));
3894
+ const polyInfo = resolvePolymorphismInfo(this.contract, this.namespaceId, this.modelName);
3895
+ if (!polyInfo) return data.map((row) => mapModelDataToStorageRow(this.contract, this.namespaceId, this.modelName, row));
3896
+ const variant = polyInfo.variants.get(variantName);
3897
+ if (!variant) return data.map((row) => mapModelDataToStorageRow(this.contract, this.namespaceId, this.modelName, row));
3898
+ const baseFieldToColumn = getFieldToColumnMap(this.contract, this.namespaceId, this.modelName);
3899
+ const variantFieldToColumn = getFieldToColumnMap(this.contract, this.namespaceId, variant.modelName);
3900
+ const mergedFieldToColumn = {
3901
+ ...baseFieldToColumn,
3902
+ ...variantFieldToColumn
3903
+ };
3904
+ return data.map((row) => {
3905
+ const mapped = {};
3906
+ for (const [fieldName, value] of Object.entries(row)) {
3907
+ if (value === void 0) continue;
3908
+ const columnName = mergedFieldToColumn[fieldName] ?? fieldName;
3909
+ mapped[columnName] = value;
3910
+ }
3911
+ mapped[polyInfo.discriminatorColumn] = variant.value;
3912
+ return mapped;
3913
+ });
3914
+ }
3915
+ /**
3916
+ * Write terminal: insert many rows without materializing the
3917
+ * inserted rows, returning the number of inserted records.
3918
+ *
3919
+ * Prefer `createAll(...)` when you need the returned rows; prefer
3920
+ * this when you only need to know how many rows were inserted (the
3921
+ * compiled plan skips `RETURNING`).
3922
+ *
3923
+ * ```typescript
3924
+ * const inserted = await db.orm.User.createAndCount([
3925
+ * { email: 'a@example.com' },
3926
+ * { email: 'b@example.com' },
3927
+ * ]);
3928
+ * // inserted === 2
3929
+ * ```
3930
+ *
3931
+ * Not supported on MTI variants — use `createAll(...)` instead.
3932
+ */
3933
+ async createAndCount(data, configure) {
3934
+ if (data.length === 0) return 0;
3935
+ this.#assertNotMtiVariant("createAndCount()");
3936
+ const annotationsMap = this.#collectAnnotationsFromMeta(configure, "write", "createAndCount");
3937
+ const rows = blindCast(data);
3938
+ const mappedRows = this.#mapCreateRows(rows);
3939
+ applyCreateDefaults(this.ctx, this.namespaceId, this.tableName, mappedRows);
3940
+ if (this.contract.capabilities?.["sql"]?.["defaultInInsert"] !== true) {
3941
+ const plans = compileInsertCountSplit(this.contract, this.namespaceId, this.tableName, mappedRows).map((plan) => mergeAnnotations(plan, annotationsMap));
3942
+ for (const plan of plans) await executeQueryPlan(this.ctx.runtime, plan).toArray();
3943
+ return data.length;
3944
+ }
3945
+ const compiled = mergeAnnotations(compileInsertCount(this.contract, this.namespaceId, this.tableName, mappedRows), annotationsMap);
3946
+ await executeQueryPlan(this.ctx.runtime, compiled).toArray();
3947
+ return data.length;
3948
+ }
3949
+ /**
3950
+ * Write terminal: insert a row, or update the existing row on
3951
+ * conflict. Returns the resulting row (the inserted one or the
3952
+ * updated/existing one).
3953
+ *
3954
+ * `conflictOn` selects which unique constraint drives the conflict
3955
+ * resolution — omit to use the model's primary key.
3956
+ *
3957
+ * ```typescript
3958
+ * // Insert-or-update on email uniqueness:
3959
+ * await db.orm.User.upsert({
3960
+ * create: { email: 'alice@example.com', name: 'Alice' },
3961
+ * update: { name: 'Alice (updated)' },
3962
+ * conflictOn: { email: 'alice@example.com' },
3963
+ * });
3964
+ *
3965
+ * // Conditional create — `update: {}` keeps the existing row
3966
+ * // unchanged. `conflictOn` must reference the constraint that
3967
+ * // makes the row "already exist"; omit only when the conflict is
3968
+ * // on the primary key. On conflict,
3969
+ * // `ON CONFLICT DO NOTHING RETURNING ...` may return zero rows,
3970
+ * // so a follow-up reload is issued to fetch and return the
3971
+ * // existing row.
3972
+ * await db.orm.User.upsert({
3973
+ * create: { email: 'alice@example.com', name: 'Alice' },
3974
+ * update: {},
3975
+ * conflictOn: { email: 'alice@example.com' },
3976
+ * });
3977
+ * ```
3978
+ *
3979
+ * Not supported on MTI variants.
3980
+ */
3981
+ async upsert(input, configure) {
3982
+ assertReturningCapability(this.contract, "upsert()");
3983
+ this.#assertNotMtiVariant("upsert()");
3984
+ const annotationsMap = this.#collectAnnotationsFromMeta(configure, "write", "upsert");
3985
+ const createValues = this.#mapCreateRows([blindCast(input.create)])[0] ?? {};
3986
+ applyCreateDefaults(this.ctx, this.namespaceId, this.tableName, [createValues]);
3987
+ const updateValues = mapModelDataToStorageRow(this.contract, this.namespaceId, this.modelName, input.update);
3988
+ const hasUpdateValues = Object.keys(updateValues).length > 0;
3989
+ if (hasUpdateValues) applyUpdateDefaults(this.ctx, this.namespaceId, this.tableName, updateValues);
3990
+ const conflictColumns = resolveUpsertConflictColumns(this.contract, this.namespaceId, this.modelName, blindCast(input.conflictOn));
3991
+ if (conflictColumns.length === 0) throw ormError("ORM.ARGUMENT_INVALID", `upsert() for model "${this.modelName}" requires conflict columns`, { meta: {
3992
+ method: "upsert",
3993
+ model: this.modelName
3994
+ } });
3995
+ const { selectedForQuery: selectedForUpsert, hiddenColumns } = this.#augmentMutationSelection();
3996
+ const compiled = mergeAnnotations(compileUpsertReturning(this.contract, this.namespaceId, this.tableName, createValues, updateValues, conflictColumns, selectedForUpsert), annotationsMap);
3997
+ const row = await executeMutationReturningSingleRow({
3998
+ context: this.ctx.context,
3999
+ runtime: this.ctx.runtime,
4000
+ compiled,
4001
+ tableName: this.tableName,
4002
+ modelName: this.modelName,
4003
+ namespaceId: this.namespaceId,
4004
+ variantName: this.state.variantName,
4005
+ includes: this.state.includes,
4006
+ selectedFields: this.state.selectedFields,
4007
+ hiddenColumns,
4008
+ mapRow: (mapped) => blindCast(mapped),
4009
+ operation: "upsert",
4010
+ onMissingRowMessage: `upsert() for model "${this.modelName}" did not return a row`
4011
+ });
4012
+ if (row) return row;
4013
+ if (!hasUpdateValues) {
4014
+ const conflictCriterion = this.#buildUpsertConflictCriterion(createValues, conflictColumns);
4015
+ const existing = await this.#reloadMutationRowByCriterion(conflictCriterion, "upsert conflict");
4016
+ if (existing) return existing;
4017
+ }
4018
+ throw ormError("ORM.MUTATION_ROW_MISSING", `upsert() for model "${this.modelName}" did not return a row`, { meta: {
4019
+ operation: "upsert",
4020
+ model: this.modelName
4021
+ } });
4022
+ }
4023
+ /**
4024
+ * Write terminal: update matching rows and return the first one (or
4025
+ * `null` when no row matched). Requires a prior `.where(...)` —
4026
+ * calling `update(...)` on an unfiltered collection is a type error.
4027
+ *
4028
+ * Related rows can be created or relinked through relation
4029
+ * callbacks on parent/child-owned relations (one-to-one or
4030
+ * one-to-many). The callback receives a mutator exposing
4031
+ * `create(...)`, `connect(...)`, and `disconnect(...)`. Nested
4032
+ * updates against existing related rows, and many-to-many relations
4033
+ * as nested-mutation targets, are not supported through this API.
4034
+ *
4035
+ * ```typescript
4036
+ * // Update one row by id:
4037
+ * const updated = await db.orm.User
4038
+ * .where({ id: 1 })
4039
+ * .update({ name: 'Alice Renamed' });
4040
+ *
4041
+ * // Update + relink — runs as a graph of internal mutations:
4042
+ * await db.orm.User
4043
+ * .where({ id: 1 })
4044
+ * .update({
4045
+ * name: 'Alice',
4046
+ * posts: (posts) => posts.connect([{ id: 5 }]),
4047
+ * });
4048
+ * ```
4049
+ *
4050
+ * Accepts an optional `configure` callback that receives a
4051
+ * `MetaBuilder<'write'>` for attaching typed annotations.
4052
+ *
4053
+ * Note: when the input contains nested-mutation callbacks, the
4054
+ * operation is executed as a graph of internal queries via
4055
+ * `withMutationScope`. In that path, annotations apply to the logical
4056
+ * `update()` call but do not currently flow into each constituent SQL
4057
+ * statement issued for the related rows.
4058
+ */
4059
+ async update(data, configure) {
4060
+ assertReturningCapability(this.contract, "update()");
4061
+ const annotationsMap = this.#collectAnnotationsFromMeta(configure, "write", "update");
4062
+ if (hasNestedMutationCallbacks(this.contract, this.namespaceId, this.modelName, blindCast(data))) {
4063
+ const updatedRow = await executeNestedUpdateMutation({
4064
+ context: this.ctx.context,
4065
+ runtime: this.ctx.runtime,
4066
+ namespaceId: this.namespaceId,
4067
+ modelName: this.modelName,
4068
+ filters: this.state.filters,
4069
+ data: blindCast(data)
4070
+ });
4071
+ if (!updatedRow) return null;
4072
+ const pkCriterion = buildPrimaryKeyFilterFromRow(this.contract, this.namespaceId, this.modelName, updatedRow);
4073
+ return this.#reloadMutationRowByPrimaryKey(pkCriterion);
4074
+ }
4075
+ return withMutationScope(this.ctx.runtime, async (scope) => {
4076
+ const scoped = this.#withRuntime(scope);
4077
+ const identityWhere = await scoped.#findFirstMatchingRowIdentityWhere();
4078
+ if (!identityWhere) return null;
4079
+ return (await scoped.#clone({ filters: [identityWhere] }).#updateAllWithAnnotations(blindCast(data), annotationsMap))[0] ?? null;
4080
+ });
4081
+ }
4082
+ /**
4083
+ * Write terminal: update every matching row and stream the updated
4084
+ * rows. Requires a prior `.where(...)` filter.
4085
+ *
4086
+ * The returned `AsyncIterableResult<Row>` is BOTH a thenable that
4087
+ * resolves to `Row[]` AND an async iterable that streams updated
4088
+ * rows as they arrive. Use whichever fits; a result can only be
4089
+ * consumed once. Streaming is the default; some driver/plan
4090
+ * combinations may still buffer internally before yielding.
4091
+ *
4092
+ * ```typescript
4093
+ * // Thenable — collect updated rows into an array:
4094
+ * const updated = await db.orm.Post
4095
+ * .where({ published: false })
4096
+ * .updateAll({ published: true });
4097
+ *
4098
+ * // Async iterable — stream updated rows as they arrive:
4099
+ * for await (const row of db.orm.Post.where({ draft: true }).updateAll({ draft: false })) {
4100
+ * console.log('published', row.id);
4101
+ * }
4102
+ * ```
4103
+ *
4104
+ * Accepts an optional `configure` callback that receives a
4105
+ * `MetaBuilder<'write'>` for attaching typed annotations.
4106
+ */
4107
+ updateAll(data, configure) {
4108
+ return this.#updateAllWithAnnotations(data, this.#collectAnnotationsFromMeta(configure, "write", "updateAll"));
4109
+ }
4110
+ #updateAllWithAnnotations(data, annotationsMap) {
4111
+ assertReturningCapability(this.contract, "updateAll()");
4112
+ const mappedData = mapModelDataToStorageRow(this.contract, this.namespaceId, this.modelName, data);
4113
+ if (Object.keys(mappedData).length === 0) {
4114
+ const generator = async function* () {};
4115
+ return new AsyncIterableResult(generator());
4116
+ }
4117
+ applyUpdateDefaults(this.ctx, this.namespaceId, this.tableName, mappedData);
4118
+ const { selectedForQuery: selectedForUpdate, hiddenColumns } = this.#augmentMutationSelection();
4119
+ const compiled = mergeAnnotations(compileUpdateReturning(this.contract, this.namespaceId, this.tableName, mappedData, this.state.filters, selectedForUpdate), annotationsMap);
4120
+ return dispatchMutationRows({
4121
+ context: this.ctx.context,
4122
+ runtime: this.ctx.runtime,
4123
+ compiled,
4124
+ tableName: this.tableName,
4125
+ modelName: this.modelName,
4126
+ namespaceId: this.namespaceId,
4127
+ variantName: this.state.variantName,
4128
+ includes: this.state.includes,
4129
+ selectedFields: this.state.selectedFields,
4130
+ hiddenColumns,
4131
+ mapRow: (mapped) => blindCast(mapped)
4132
+ });
4133
+ }
4134
+ /**
4135
+ * Write terminal: update every matching row without returning them,
4136
+ * resolving to the count of rows that were updated. Requires a prior
4137
+ * `.where(...)` filter.
4138
+ *
4139
+ * Prefer `updateAll(...)` when you need the updated rows; prefer
4140
+ * this when you only need the affected-row count.
4141
+ *
4142
+ * ```typescript
4143
+ * const count = await db.orm.Post
4144
+ * .where({ published: false })
4145
+ * .updateAndCount({ published: true });
4146
+ * ```
4147
+ */
4148
+ async updateAndCount(data, configure) {
4149
+ const mappedData = mapModelDataToStorageRow(this.contract, this.namespaceId, this.modelName, data);
4150
+ if (Object.keys(mappedData).length === 0) return 0;
4151
+ applyUpdateDefaults(this.ctx, this.namespaceId, this.tableName, mappedData);
4152
+ const annotationsMap = this.#collectAnnotationsFromMeta(configure, "write", "updateAndCount");
4153
+ const primaryKeyColumn = resolvePrimaryKeyColumn(this.contract, this.namespaceId, this.tableName);
4154
+ const countState = {
4155
+ ...emptyState(),
4156
+ filters: this.state.filters,
4157
+ selectedFields: [primaryKeyColumn],
4158
+ variantName: this.state.variantName
4159
+ };
4160
+ const countCompiled = compileSelect(this.contract, this.namespaceId, this.tableName, countState, this.modelName);
4161
+ const matchingRows = await executeQueryPlan(this.ctx.runtime, countCompiled).toArray();
4162
+ const compiled = mergeAnnotations(compileUpdateCount(this.contract, this.namespaceId, this.tableName, mappedData, this.state.filters, this.state.variantName, this.modelName), annotationsMap);
4163
+ await executeQueryPlan(this.ctx.runtime, compiled).toArray();
4164
+ return matchingRows.length;
4165
+ }
4166
+ /**
4167
+ * Write terminal: delete matching rows and return the first deleted
4168
+ * row (or `null` when no row matched). Requires a prior `.where(...)`
4169
+ * — calling `delete()` on an unfiltered collection is a type error.
4170
+ *
4171
+ * ```typescript
4172
+ * const deleted = await db.orm.User.where({ id: 1 }).delete();
4173
+ * if (deleted) console.log('deleted', deleted.email);
4174
+ * ```
4175
+ *
4176
+ * Accepts an optional `configure` callback that receives a
4177
+ * `MetaBuilder<'write'>` for attaching typed annotations.
4178
+ */
4179
+ async delete(configure) {
4180
+ assertReturningCapability(this.contract, "delete()");
4181
+ const annotationsMap = this.#collectAnnotationsFromMeta(configure, "write", "delete");
4182
+ return withMutationScope(this.ctx.runtime, async (scope) => {
4183
+ const scoped = this.#withRuntime(scope);
4184
+ const identityWhere = await scoped.#findFirstMatchingRowIdentityWhere();
4185
+ if (!identityWhere) return null;
4186
+ return (await scoped.#clone({ filters: [identityWhere] }).#executeDeleteReturning(annotationsMap).toArray())[0] ?? null;
4187
+ });
4188
+ }
4189
+ /**
4190
+ * Write terminal: delete every matching row and stream the deleted
4191
+ * rows. Requires a prior `.where(...)` filter.
4192
+ *
4193
+ * The returned `AsyncIterableResult<Row>` is BOTH a thenable that
4194
+ * resolves to `Row[]` AND an async iterable that streams deleted
4195
+ * rows as they arrive. Use whichever fits; a result can only be
4196
+ * consumed once. Streaming is the default; some driver/plan
4197
+ * combinations may still buffer internally before yielding.
4198
+ *
4199
+ * ```typescript
4200
+ * // Thenable — collect the deleted rows into an array:
4201
+ * const deleted = await db.orm.Post.where({ archived: true }).deleteAll();
4202
+ *
4203
+ * // Async iterable — stream deleted rows as they arrive:
4204
+ * for await (const row of db.orm.Post.where({ archived: true }).deleteAll()) {
4205
+ * console.log('removed', row.id);
4206
+ * }
4207
+ * ```
4208
+ *
4209
+ * Accepts an optional `configure` callback that receives a
4210
+ * `MetaBuilder<'write'>` for attaching typed annotations.
4211
+ */
4212
+ deleteAll(configure) {
4213
+ return blindCast(this).#deleteAllWithAnnotations(this.#collectAnnotationsFromMeta(configure, "write", "deleteAll"));
4214
+ }
4215
+ #deleteAllWithAnnotations(annotationsMap) {
4216
+ assertReturningCapability(this.contract, "deleteAll()");
4217
+ return this.#executeDeleteReturning(annotationsMap);
4218
+ }
4219
+ #executeDeleteReturning(annotationsMap) {
4220
+ if (this.state.includes.length > 0) return this.#executeDeleteReturningWithIncludes(annotationsMap);
4221
+ const { selectedForQuery: selectedForDelete, hiddenColumns } = this.#augmentMutationSelection();
4222
+ const compiled = mergeAnnotations(compileDeleteReturning(this.contract, this.namespaceId, this.tableName, this.state.filters, selectedForDelete), annotationsMap);
4223
+ return dispatchMutationRows({
4224
+ context: this.ctx.context,
4225
+ runtime: this.ctx.runtime,
4226
+ compiled,
4227
+ tableName: this.tableName,
4228
+ modelName: this.modelName,
4229
+ namespaceId: this.namespaceId,
4230
+ variantName: this.state.variantName,
4231
+ includes: this.state.includes,
4232
+ selectedFields: this.state.selectedFields,
4233
+ hiddenColumns,
4234
+ mapRow: (mapped) => blindCast(mapped)
4235
+ });
4236
+ }
4237
+ /**
4238
+ * Delete read-back with includes.
4239
+ *
4240
+ * A parent-anchored single-query include read can't observe a row
4241
+ * that has already been deleted, so this reads the rows together with
4242
+ * their relations BEFORE issuing the DELETE. The snapshot is fully
4243
+ * drained into a plain array with `.toArray()` while the rows still
4244
+ * exist; only then does the DELETE run. The yielded `for..of` walks
4245
+ * that in-memory array, not a live cursor, so nothing reads from the
4246
+ * deleted rows after the fact. Snapshot read and delete share one
4247
+ * `withMutationScope` so they are atomic; the returned relations
4248
+ * reflect the row's state at delete time.
4249
+ */
4250
+ #executeDeleteReturningWithIncludes(annotationsMap) {
4251
+ const collection = this;
4252
+ const generator = async function* () {
4253
+ const snapshot = await withMutationScope(collection.ctx.runtime, async (scope) => {
4254
+ const rows = await dispatchCollectionRows({
4255
+ context: collection.ctx.context,
4256
+ runtime: scope,
4257
+ state: collection.state,
4258
+ tableName: collection.tableName,
4259
+ modelName: collection.modelName,
4260
+ namespaceId: collection.namespaceId
4261
+ }).toArray();
4262
+ await executeQueryPlan(scope, mergeAnnotations(compileDeleteCount(collection.contract, collection.namespaceId, collection.tableName, collection.state.filters, collection.state.variantName, collection.modelName), annotationsMap)).toArray();
4263
+ return rows;
4264
+ });
4265
+ for (const row of snapshot) yield row;
4266
+ };
4267
+ return new AsyncIterableResult(generator());
4268
+ }
4269
+ /**
4270
+ * Write terminal: delete every matching row without returning them,
4271
+ * resolving to the count of rows that were deleted. Requires a prior
4272
+ * `.where(...)` filter.
4273
+ *
4274
+ * Prefer `deleteAll(...)` when you need the deleted rows; prefer
4275
+ * this when you only need the affected-row count.
4276
+ *
4277
+ * ```typescript
4278
+ * const removed = await db.orm.Post.where({ archived: true }).deleteAndCount();
4279
+ * ```
4280
+ */
4281
+ async deleteAndCount(configure) {
4282
+ const annotationsMap = this.#collectAnnotationsFromMeta(configure, "write", "deleteAndCount");
4283
+ const primaryKeyColumn = resolvePrimaryKeyColumn(this.contract, this.namespaceId, this.tableName);
4284
+ const countState = {
4285
+ ...emptyState(),
4286
+ filters: this.state.filters,
4287
+ selectedFields: [primaryKeyColumn],
4288
+ variantName: this.state.variantName
4289
+ };
4290
+ const countCompiled = compileSelect(this.contract, this.namespaceId, this.tableName, countState, this.modelName);
4291
+ const matchingRows = await executeQueryPlan(this.ctx.runtime, countCompiled).toArray();
4292
+ const compiled = mergeAnnotations(compileDeleteCount(this.contract, this.namespaceId, this.tableName, this.state.filters, this.state.variantName, this.modelName), annotationsMap);
4293
+ await executeQueryPlan(this.ctx.runtime, compiled).toArray();
4294
+ return matchingRows.length;
4295
+ }
4296
+ #buildUpsertConflictCriterion(createValues, conflictColumns) {
4297
+ const columnToField = getColumnToFieldMap(this.contract, this.namespaceId, this.modelName);
4298
+ const criterion = {};
4299
+ for (const columnName of conflictColumns) {
4300
+ if (!(columnName in createValues)) throw ormError("ORM.ARGUMENT_INVALID", `upsert() for model "${this.modelName}" requires create value for conflict column "${columnName}"`, { meta: {
4301
+ method: "upsert",
4302
+ model: this.modelName,
4303
+ column: columnName
4304
+ } });
4305
+ const fieldName = columnToField[columnName] ?? columnName;
4306
+ criterion[fieldName] = createValues[columnName];
4307
+ }
4308
+ return criterion;
4309
+ }
4310
+ /**
4311
+ * Shape the projection for a mutation's `RETURNING` clause.
4312
+ *
4313
+ * Without includes, the mutation returns the caller's projection
4314
+ * directly. With includes, it returns only the row identity columns
4315
+ * (PK / unique): those rows are reloaded through the read path
4316
+ * (`reloadMutationRowsByIdentities`), which re-selects the caller's
4317
+ * projection together with the relations, so the `RETURNING` clause
4318
+ * need only carry enough to key that read-back.
4319
+ */
4320
+ #augmentMutationSelection() {
4321
+ if (this.state.includes.length > 0) {
4322
+ const identityColumns = resolveRowIdentityColumns(this.contract, this.namespaceId, this.tableName);
4323
+ if (identityColumns.length === 0) throw ormError("ORM.ROW_IDENTITY_MISSING", `Cannot load includes for the mutation result on model "${this.modelName}": table "${this.tableName}" has no primary key or unique constraint to key the include read-back on.`, { meta: {
4324
+ model: this.modelName,
4325
+ table: this.tableName
4326
+ } });
4327
+ return {
4328
+ selectedForQuery: identityColumns,
4329
+ hiddenColumns: []
4330
+ };
4331
+ }
4332
+ return {
4333
+ selectedForQuery: this.state.selectedFields,
4334
+ hiddenColumns: []
4335
+ };
4336
+ }
4337
+ async #findFirstMatchingRowIdentityWhere() {
4338
+ const identityColumns = resolveRowIdentityColumns(this.contract, this.namespaceId, this.tableName);
4339
+ if (identityColumns.length === 0) throw ormError("ORM.ROW_IDENTITY_MISSING", `update()/delete() on model "${this.modelName}" requires the table to have a primary key or unique constraint`, { meta: {
4340
+ model: this.modelName,
4341
+ table: this.tableName
4342
+ } });
4343
+ const firstRow = await this.#clone({
4344
+ selectedFields: [...identityColumns],
4345
+ includes: []
4346
+ }).first();
4347
+ if (!firstRow) return null;
4348
+ const columnToField = getColumnToFieldMap(this.contract, this.namespaceId, this.modelName);
4349
+ const criterion = {};
4350
+ for (const column of identityColumns) {
4351
+ const fieldName = columnToField[column] ?? column;
4352
+ const value = blindCast(firstRow)[fieldName];
4353
+ if (value === void 0) throw new InternalError(`Missing identity field "${fieldName}" while resolving single-row scope for model "${this.modelName}"`);
4354
+ criterion[fieldName] = value;
4355
+ }
4356
+ return shorthandToWhereExpr(this.ctx.context, this.namespaceId, this.modelName, blindCast(criterion)) ?? null;
4357
+ }
4358
+ async #reloadMutationRowByPrimaryKey(criterion) {
4359
+ return this.#reloadMutationRowByCriterion(criterion, "primary key");
4360
+ }
4361
+ async #reloadMutationRowByCriterion(criterion, criterionLabel) {
4362
+ const whereExpr = shorthandToWhereExpr(this.ctx.context, this.namespaceId, this.modelName, blindCast(criterion));
4363
+ if (!whereExpr) throw new InternalError(`Failed to build ${criterionLabel} filter for mutation result on model "${this.modelName}"`);
4364
+ const resultState = {
4365
+ ...emptyState(),
4366
+ filters: [whereExpr],
4367
+ includes: this.state.includes,
4368
+ selectedFields: this.state.selectedFields,
4369
+ limit: 1
4370
+ };
4371
+ return (await dispatchCollectionRows({
4372
+ context: this.ctx.context,
4373
+ runtime: this.ctx.runtime,
4374
+ state: resultState,
4375
+ tableName: this.tableName,
4376
+ modelName: this.modelName,
4377
+ namespaceId: this.namespaceId
4378
+ }))[0] ?? null;
4379
+ }
4380
+ #assertIncludeRefinementMode(action) {
4381
+ if (this.includeRefinementMode) return;
4382
+ throw ormError("ORM.INCLUDE_INVALID", `${action} is only available inside include() refinement callbacks`, { meta: { action } });
4383
+ }
4384
+ #clone(overrides) {
4385
+ return this.#createSelf({
4386
+ ...this.state,
4387
+ ...overrides
4388
+ });
4389
+ }
4390
+ #withRuntime(runtime) {
4391
+ return blindCast(new (blindCast(this.constructor))({
4392
+ ...this.ctx,
4393
+ runtime
4394
+ }, this.modelName, {
4395
+ tableName: this.tableName,
4396
+ namespaceId: this.namespaceId,
4397
+ state: this.state,
4398
+ registry: this.registry,
4399
+ includeRefinementMode: this.includeRefinementMode
4400
+ }));
4401
+ }
4402
+ #cloneWithRow(overrides) {
4403
+ return this.#createSelf({
4404
+ ...this.state,
4405
+ ...overrides
4406
+ });
4407
+ }
4408
+ #createSelf(state) {
4409
+ return blindCast(new (blindCast(this.constructor))(this.ctx, this.modelName, {
4410
+ tableName: this.tableName,
4411
+ namespaceId: this.namespaceId,
4412
+ state,
4413
+ registry: this.registry,
4414
+ includeRefinementMode: this.includeRefinementMode
4415
+ }));
4416
+ }
4417
+ #createCollection(modelName, options) {
4418
+ return blindCast(new ((this.registry.get(modelName)) ?? (blindCast(Collection)))(this.ctx, modelName, {
4419
+ tableName: options.tableName,
4420
+ namespaceId: options.namespaceId,
4421
+ state: options.state,
4422
+ registry: options.registry ?? this.registry,
4423
+ includeRefinementMode: options.includeRefinementMode ?? this.includeRefinementMode
4424
+ }));
4425
+ }
4426
+ #dispatch() {
4427
+ return dispatchCollectionRows({
4428
+ context: this.ctx.context,
4429
+ runtime: this.ctx.runtime,
4430
+ state: this.state,
4431
+ tableName: this.tableName,
4432
+ modelName: this.modelName,
4433
+ namespaceId: this.namespaceId
4434
+ });
4435
+ }
4436
+ /**
4437
+ * Invokes the user-supplied configurator (if any) against a freshly
4438
+ * constructed read meta builder, and returns a clone whose
4439
+ * `state.annotations` carries the recorded map. Used by read
4440
+ * terminals that flow annotations through state (`all`, `first`).
4441
+ *
4442
+ * Returns the receiver unchanged when no configurator was supplied
4443
+ * or when the configurator did not call `meta.annotate(...)`. The
4444
+ * meta builder's `annotate` method enforces applicability at the
4445
+ * type level and at runtime, so terminal code does not need to
4446
+ * re-validate.
4447
+ */
4448
+ #withAnnotationsFromMeta(configure, terminalName) {
4449
+ if (configure === void 0) return this;
4450
+ const meta = createMetaBuilder("read", terminalName);
4451
+ configure(meta);
4452
+ if (meta.annotations.size === 0) return this;
4453
+ const next = new Map(this.state.annotations);
4454
+ for (const [namespace, value] of meta.annotations) next.set(namespace, value);
4455
+ return blindCast(this.#clone({ annotations: next }));
4456
+ }
4457
+ /**
4458
+ * Invokes the user-supplied configurator (if any) against a freshly
4459
+ * constructed meta builder of the given operation kind, and returns
4460
+ * the recorded annotation map (or `undefined` when empty). Used by
4461
+ * terminals where annotations don't flow through `state` — the
4462
+ * compiled plan is post-wrapped via `mergeAnnotations` instead.
4463
+ * Read terminals `all` and `first` populate `state.annotations`
4464
+ * via `#withAnnotationsFromMeta` instead; `aggregate` uses this
4465
+ * post-wrap path because its compile function doesn't take `state`.
4466
+ * The meta builder's `annotate` method enforces applicability at the
4467
+ * type level and at runtime.
4468
+ */
4469
+ #collectAnnotationsFromMeta(configure, kind, terminalName) {
4470
+ if (configure === void 0) return;
4471
+ const meta = createMetaBuilder(kind, terminalName);
4472
+ configure(meta);
4473
+ return meta.annotations.size === 0 ? void 0 : meta.annotations;
4474
+ }
4475
+ };
4476
+ function orm(options) {
4477
+ const { runtime, collections, context } = options;
4478
+ const contract = context.contract;
4479
+ const ctx = {
4480
+ runtime,
4481
+ context
4482
+ };
4483
+ const collectionRegistry = createCollectionRegistry(contract, collections);
4484
+ function buildCollection(namespaceId, modelName, tableName) {
4485
+ return new (blindCast(collectionRegistry.get(modelName) ?? Collection))(ctx, modelName, {
4486
+ registry: collectionRegistry,
4487
+ namespaceId,
4488
+ ...tableName !== void 0 ? { tableName } : {}
4489
+ });
4490
+ }
4491
+ const namespaceFacets = /* @__PURE__ */ new Map();
4492
+ function namespaceFacet(namespaceId) {
4493
+ const cached = namespaceFacets.get(namespaceId);
4494
+ if (cached) return cached;
4495
+ const facetModelNames = new Set(domainModelNamesInNamespace(contract, namespaceId));
4496
+ const facetCache = /* @__PURE__ */ new Map();
4497
+ const facet = new Proxy({}, { get(_facetTarget, modelProp) {
4498
+ if (typeof modelProp !== "string") return;
4499
+ if (!facetModelNames.has(modelProp)) return;
4500
+ const hit = facetCache.get(modelProp);
4501
+ if (hit) return hit;
4502
+ const collection = buildCollection(namespaceId, modelProp, domainModelTableInNamespace(contract, namespaceId, modelProp));
4503
+ facetCache.set(modelProp, collection);
4504
+ return collection;
4505
+ } });
4506
+ namespaceFacets.set(namespaceId, facet);
4507
+ return facet;
4508
+ }
4509
+ return new Proxy({}, { get(_target, prop) {
4510
+ if (typeof prop !== "string") return;
4511
+ if (!Object.hasOwn(contract.domain.namespaces, prop)) return;
4512
+ return namespaceFacet(prop);
4513
+ } });
4514
+ }
4515
+ function createCollectionRegistry(contract, collections) {
4516
+ const registry = /* @__PURE__ */ new Map();
4517
+ if (!collections) return registry;
4518
+ const models = domainModelsAtDefaultNamespace(contract.domain);
4519
+ for (const [key, collectionClass] of Object.entries(collections)) {
4520
+ if (!collectionClass) continue;
4521
+ if (!isCollectionClass(collectionClass)) throw ormError("ORM.ARGUMENT_INVALID", `Custom collection '${key}' must be a Collection class (constructor), not an instance`, { meta: {
4522
+ method: "orm",
4523
+ argument: "collections",
4524
+ key
4525
+ } });
4526
+ if (!Object.hasOwn(models, key)) throw ormError("ORM.ARGUMENT_INVALID", `No model found for custom collection '${key}'. Available models: ${Object.keys(models).join(", ")}`, { meta: {
4527
+ method: "orm",
4528
+ argument: "collections",
4529
+ key
4530
+ } });
4531
+ registry.set(key, collectionClass);
4532
+ }
4533
+ return registry;
4534
+ }
4535
+ function isCollectionClass(value) {
4536
+ if (typeof value !== "function") return false;
4537
+ const candidate = value;
4538
+ if (!candidate.prototype || typeof candidate.prototype !== "object") return false;
4539
+ return candidate.prototype instanceof Collection;
4540
+ }
4541
+ //#endregion
4542
+ export { Collection, GroupedCollection, all, and, createModelAccessor, emptyState, not, or, orm };
4543
+
4544
+ //# sourceMappingURL=orm-client.mjs.map