joist-core 2.3.0 → 2.4.0-next.10

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 (1548) hide show
  1. package/build/BaseEntity.cjs +112 -0
  2. package/build/BaseEntity.cjs.map +1 -0
  3. package/build/BaseEntity.d.cts +73 -0
  4. package/build/BaseEntity.d.cts.map +1 -0
  5. package/build/BaseEntity.d.mts +73 -0
  6. package/build/BaseEntity.d.mts.map +1 -0
  7. package/build/BaseEntity.js +99 -110
  8. package/build/BaseEntity.js.map +1 -1
  9. package/build/Entity.cjs +12 -0
  10. package/build/Entity.cjs.map +1 -0
  11. package/build/Entity.d.cts +42 -0
  12. package/build/Entity.d.cts.map +1 -0
  13. package/build/Entity.d.mts +42 -0
  14. package/build/Entity.d.mts.map +1 -0
  15. package/build/Entity.js +8 -5
  16. package/build/Entity.js.map +1 -1
  17. package/build/EntityFields.cjs +1 -0
  18. package/build/EntityFields.d.cts +36 -0
  19. package/build/EntityFields.d.cts.map +1 -0
  20. package/build/EntityFields.d.mts +36 -0
  21. package/build/EntityFields.d.mts.map +1 -0
  22. package/build/EntityFields.js +1 -3
  23. package/build/EntityManager.cjs +1935 -0
  24. package/build/EntityManager.cjs.map +1 -0
  25. package/build/EntityManager.d.cts +835 -0
  26. package/build/EntityManager.d.cts.map +1 -0
  27. package/build/EntityManager.d.mts +835 -0
  28. package/build/EntityManager.d.mts.map +1 -0
  29. package/build/EntityManager.js +1812 -2211
  30. package/build/EntityManager.js.map +1 -1
  31. package/build/EntityMetadata.cjs +75 -0
  32. package/build/EntityMetadata.cjs.map +1 -0
  33. package/build/EntityMetadata.d.cts +262 -0
  34. package/build/EntityMetadata.d.cts.map +1 -0
  35. package/build/EntityMetadata.d.mts +262 -0
  36. package/build/EntityMetadata.d.mts.map +1 -0
  37. package/build/EntityMetadata.js +31 -48
  38. package/build/EntityMetadata.js.map +1 -1
  39. package/build/EnumMetadata.cjs +1 -0
  40. package/build/EnumMetadata.d.cts +18 -0
  41. package/build/EnumMetadata.d.cts.map +1 -0
  42. package/build/EnumMetadata.d.mts +18 -0
  43. package/build/EnumMetadata.d.mts.map +1 -0
  44. package/build/EnumMetadata.js +1 -3
  45. package/build/IndexManager.cjs +178 -0
  46. package/build/IndexManager.cjs.map +1 -0
  47. package/build/IndexManager.d.cts +36 -0
  48. package/build/IndexManager.d.cts.map +1 -0
  49. package/build/IndexManager.d.mts +36 -0
  50. package/build/IndexManager.d.mts.map +1 -0
  51. package/build/IndexManager.js +169 -218
  52. package/build/IndexManager.js.map +1 -1
  53. package/build/InstanceData.cjs +218 -0
  54. package/build/InstanceData.cjs.map +1 -0
  55. package/build/InstanceData.d.cts +98 -0
  56. package/build/InstanceData.d.cts.map +1 -0
  57. package/build/InstanceData.d.mts +98 -0
  58. package/build/InstanceData.d.mts.map +1 -0
  59. package/build/InstanceData.js +215 -222
  60. package/build/InstanceData.js.map +1 -1
  61. package/build/PluginManager.cjs +89 -0
  62. package/build/PluginManager.cjs.map +1 -0
  63. package/build/PluginManager.d.cts +112 -0
  64. package/build/PluginManager.d.cts.map +1 -0
  65. package/build/PluginManager.d.mts +112 -0
  66. package/build/PluginManager.d.mts.map +1 -0
  67. package/build/PluginManager.js +80 -106
  68. package/build/PluginManager.js.map +1 -1
  69. package/build/RowData.cjs +37 -0
  70. package/build/RowData.cjs.map +1 -0
  71. package/build/RowData.d.cts +53 -0
  72. package/build/RowData.d.cts.map +1 -0
  73. package/build/RowData.d.mts +53 -0
  74. package/build/RowData.d.mts.map +1 -0
  75. package/build/RowData.js +35 -0
  76. package/build/RowData.js.map +1 -0
  77. package/build/_virtual/_rolldown/runtime.cjs +23 -0
  78. package/build/batchloaders/BatchLoader.cjs +49 -0
  79. package/build/batchloaders/BatchLoader.cjs.map +1 -0
  80. package/build/batchloaders/BatchLoader.d.cts +17 -0
  81. package/build/batchloaders/BatchLoader.d.cts.map +1 -0
  82. package/build/batchloaders/BatchLoader.d.mts +17 -0
  83. package/build/batchloaders/BatchLoader.d.mts.map +1 -0
  84. package/build/batchloaders/BatchLoader.js +45 -54
  85. package/build/batchloaders/BatchLoader.js.map +1 -1
  86. package/build/batchloaders/enumCollectionBatchLoader.cjs +66 -0
  87. package/build/batchloaders/enumCollectionBatchLoader.cjs.map +1 -0
  88. package/build/batchloaders/enumCollectionBatchLoader.d.cts +11 -0
  89. package/build/batchloaders/enumCollectionBatchLoader.d.cts.map +1 -0
  90. package/build/batchloaders/enumCollectionBatchLoader.d.mts +11 -0
  91. package/build/batchloaders/enumCollectionBatchLoader.d.mts.map +1 -0
  92. package/build/batchloaders/enumCollectionBatchLoader.js +58 -48
  93. package/build/batchloaders/enumCollectionBatchLoader.js.map +1 -1
  94. package/build/batchloaders/loadBatchLoader.cjs +78 -0
  95. package/build/batchloaders/loadBatchLoader.cjs.map +1 -0
  96. package/build/batchloaders/loadBatchLoader.d.cts +20 -0
  97. package/build/batchloaders/loadBatchLoader.d.cts.map +1 -0
  98. package/build/batchloaders/loadBatchLoader.d.mts +20 -0
  99. package/build/batchloaders/loadBatchLoader.d.mts.map +1 -0
  100. package/build/batchloaders/loadBatchLoader.js +72 -51
  101. package/build/batchloaders/loadBatchLoader.js.map +1 -1
  102. package/build/batchloaders/manyToManyBatchLoader.cjs +78 -0
  103. package/build/batchloaders/manyToManyBatchLoader.cjs.map +1 -0
  104. package/build/batchloaders/manyToManyBatchLoader.d.cts +11 -0
  105. package/build/batchloaders/manyToManyBatchLoader.d.cts.map +1 -0
  106. package/build/batchloaders/manyToManyBatchLoader.d.mts +11 -0
  107. package/build/batchloaders/manyToManyBatchLoader.d.mts.map +1 -0
  108. package/build/batchloaders/manyToManyBatchLoader.js +70 -61
  109. package/build/batchloaders/manyToManyBatchLoader.js.map +1 -1
  110. package/build/batchloaders/oneToManyBatchLoader.cjs +63 -0
  111. package/build/batchloaders/oneToManyBatchLoader.cjs.map +1 -0
  112. package/build/batchloaders/oneToManyBatchLoader.d.cts +11 -0
  113. package/build/batchloaders/oneToManyBatchLoader.d.cts.map +1 -0
  114. package/build/batchloaders/oneToManyBatchLoader.d.mts +11 -0
  115. package/build/batchloaders/oneToManyBatchLoader.d.mts.map +1 -0
  116. package/build/batchloaders/oneToManyBatchLoader.js +58 -48
  117. package/build/batchloaders/oneToManyBatchLoader.js.map +1 -1
  118. package/build/batchloaders/oneToOneBatchLoader.cjs +64 -0
  119. package/build/batchloaders/oneToOneBatchLoader.cjs.map +1 -0
  120. package/build/batchloaders/oneToOneBatchLoader.d.cts +10 -0
  121. package/build/batchloaders/oneToOneBatchLoader.d.cts.map +1 -0
  122. package/build/batchloaders/oneToOneBatchLoader.d.mts +10 -0
  123. package/build/batchloaders/oneToOneBatchLoader.d.mts.map +1 -0
  124. package/build/batchloaders/oneToOneBatchLoader.js +59 -50
  125. package/build/batchloaders/oneToOneBatchLoader.js.map +1 -1
  126. package/build/batchloaders/populateBatchLoader.cjs +155 -0
  127. package/build/batchloaders/populateBatchLoader.cjs.map +1 -0
  128. package/build/batchloaders/populateBatchLoader.d.cts +17 -0
  129. package/build/batchloaders/populateBatchLoader.d.cts.map +1 -0
  130. package/build/batchloaders/populateBatchLoader.d.mts +17 -0
  131. package/build/batchloaders/populateBatchLoader.d.mts.map +1 -0
  132. package/build/batchloaders/populateBatchLoader.js +147 -203
  133. package/build/batchloaders/populateBatchLoader.js.map +1 -1
  134. package/build/batchloaders/recursiveChildrenBatchLoader.cjs +78 -0
  135. package/build/batchloaders/recursiveChildrenBatchLoader.cjs.map +1 -0
  136. package/build/batchloaders/recursiveChildrenBatchLoader.d.cts +10 -0
  137. package/build/batchloaders/recursiveChildrenBatchLoader.d.cts.map +1 -0
  138. package/build/batchloaders/recursiveChildrenBatchLoader.d.mts +10 -0
  139. package/build/batchloaders/recursiveChildrenBatchLoader.d.mts.map +1 -0
  140. package/build/batchloaders/recursiveChildrenBatchLoader.js +71 -72
  141. package/build/batchloaders/recursiveChildrenBatchLoader.js.map +1 -1
  142. package/build/batchloaders/recursiveM2mBatchLoader.cjs +83 -0
  143. package/build/batchloaders/recursiveM2mBatchLoader.cjs.map +1 -0
  144. package/build/batchloaders/recursiveM2mBatchLoader.d.cts +10 -0
  145. package/build/batchloaders/recursiveM2mBatchLoader.d.cts.map +1 -0
  146. package/build/batchloaders/recursiveM2mBatchLoader.d.mts +10 -0
  147. package/build/batchloaders/recursiveM2mBatchLoader.d.mts.map +1 -0
  148. package/build/batchloaders/recursiveM2mBatchLoader.js +76 -79
  149. package/build/batchloaders/recursiveM2mBatchLoader.js.map +1 -1
  150. package/build/batchloaders/recursiveParentsBatchLoader.cjs +65 -0
  151. package/build/batchloaders/recursiveParentsBatchLoader.cjs.map +1 -0
  152. package/build/batchloaders/recursiveParentsBatchLoader.d.cts +10 -0
  153. package/build/batchloaders/recursiveParentsBatchLoader.d.cts.map +1 -0
  154. package/build/batchloaders/recursiveParentsBatchLoader.d.mts +10 -0
  155. package/build/batchloaders/recursiveParentsBatchLoader.d.mts.map +1 -0
  156. package/build/batchloaders/recursiveParentsBatchLoader.js +58 -55
  157. package/build/batchloaders/recursiveParentsBatchLoader.js.map +1 -1
  158. package/build/changes.cjs +221 -0
  159. package/build/changes.cjs.map +1 -0
  160. package/build/changes.d.cts +95 -0
  161. package/build/changes.d.cts.map +1 -0
  162. package/build/changes.d.mts +95 -0
  163. package/build/changes.d.mts.map +1 -0
  164. package/build/changes.js +208 -285
  165. package/build/changes.js.map +1 -1
  166. package/build/config.cjs +295 -0
  167. package/build/config.cjs.map +1 -0
  168. package/build/config.d.cts +277 -0
  169. package/build/config.d.cts.map +1 -0
  170. package/build/config.d.mts +277 -0
  171. package/build/config.d.mts.map +1 -0
  172. package/build/config.js +255 -301
  173. package/build/config.js.map +1 -1
  174. package/build/configure.cjs +324 -0
  175. package/build/configure.cjs.map +1 -0
  176. package/build/configure.d.cts +19 -0
  177. package/build/configure.d.cts.map +1 -0
  178. package/build/configure.d.mts +19 -0
  179. package/build/configure.d.mts.map +1 -0
  180. package/build/configure.js +265 -348
  181. package/build/configure.js.map +1 -1
  182. package/build/dataloaders/fastWhereFilterHash.cjs +140 -0
  183. package/build/dataloaders/fastWhereFilterHash.cjs.map +1 -0
  184. package/build/dataloaders/fastWhereFilterHash.d.cts +18 -0
  185. package/build/dataloaders/fastWhereFilterHash.d.cts.map +1 -0
  186. package/build/dataloaders/fastWhereFilterHash.d.mts +18 -0
  187. package/build/dataloaders/fastWhereFilterHash.d.mts.map +1 -0
  188. package/build/dataloaders/fastWhereFilterHash.js +108 -133
  189. package/build/dataloaders/fastWhereFilterHash.js.map +1 -1
  190. package/build/dataloaders/findByUniqueDataLoader.cjs +58 -0
  191. package/build/dataloaders/findByUniqueDataLoader.cjs.map +1 -0
  192. package/build/dataloaders/findByUniqueDataLoader.d.cts +10 -0
  193. package/build/dataloaders/findByUniqueDataLoader.d.cts.map +1 -0
  194. package/build/dataloaders/findByUniqueDataLoader.d.mts +10 -0
  195. package/build/dataloaders/findByUniqueDataLoader.d.mts.map +1 -0
  196. package/build/dataloaders/findByUniqueDataLoader.js +53 -44
  197. package/build/dataloaders/findByUniqueDataLoader.js.map +1 -1
  198. package/build/dataloaders/findCountDataLoader.cjs +123 -0
  199. package/build/dataloaders/findCountDataLoader.cjs.map +1 -0
  200. package/build/dataloaders/findCountDataLoader.d.cts +19 -0
  201. package/build/dataloaders/findCountDataLoader.d.cts.map +1 -0
  202. package/build/dataloaders/findCountDataLoader.d.mts +19 -0
  203. package/build/dataloaders/findCountDataLoader.d.mts.map +1 -0
  204. package/build/dataloaders/findCountDataLoader.js +112 -109
  205. package/build/dataloaders/findCountDataLoader.js.map +1 -1
  206. package/build/dataloaders/findDataLoader.cjs +365 -0
  207. package/build/dataloaders/findDataLoader.cjs.map +1 -0
  208. package/build/dataloaders/findDataLoader.d.cts +79 -0
  209. package/build/dataloaders/findDataLoader.d.cts.map +1 -0
  210. package/build/dataloaders/findDataLoader.d.mts +79 -0
  211. package/build/dataloaders/findDataLoader.d.mts.map +1 -0
  212. package/build/dataloaders/findDataLoader.js +298 -382
  213. package/build/dataloaders/findDataLoader.js.map +1 -1
  214. package/build/dataloaders/findIdsDataLoader.cjs +82 -0
  215. package/build/dataloaders/findIdsDataLoader.cjs.map +1 -0
  216. package/build/dataloaders/findIdsDataLoader.d.cts +9 -0
  217. package/build/dataloaders/findIdsDataLoader.d.cts.map +1 -0
  218. package/build/dataloaders/findIdsDataLoader.d.mts +9 -0
  219. package/build/dataloaders/findIdsDataLoader.d.mts.map +1 -0
  220. package/build/dataloaders/findIdsDataLoader.js +77 -74
  221. package/build/dataloaders/findIdsDataLoader.js.map +1 -1
  222. package/build/dataloaders/findOrCreateDataLoader.cjs +120 -0
  223. package/build/dataloaders/findOrCreateDataLoader.cjs.map +1 -0
  224. package/build/dataloaders/findOrCreateDataLoader.d.cts +15 -0
  225. package/build/dataloaders/findOrCreateDataLoader.d.cts.map +1 -0
  226. package/build/dataloaders/findOrCreateDataLoader.d.mts +15 -0
  227. package/build/dataloaders/findOrCreateDataLoader.d.mts.map +1 -0
  228. package/build/dataloaders/findOrCreateDataLoader.js +102 -164
  229. package/build/dataloaders/findOrCreateDataLoader.js.map +1 -1
  230. package/build/dataloaders/findPaginatedDataLoader.cjs +98 -0
  231. package/build/dataloaders/findPaginatedDataLoader.cjs.map +1 -0
  232. package/build/dataloaders/findPaginatedDataLoader.d.cts +10 -0
  233. package/build/dataloaders/findPaginatedDataLoader.d.cts.map +1 -0
  234. package/build/dataloaders/findPaginatedDataLoader.d.mts +10 -0
  235. package/build/dataloaders/findPaginatedDataLoader.d.mts.map +1 -0
  236. package/build/dataloaders/findPaginatedDataLoader.js +93 -80
  237. package/build/dataloaders/findPaginatedDataLoader.js.map +1 -1
  238. package/build/dataloaders/lensDataLoader.cjs +178 -0
  239. package/build/dataloaders/lensDataLoader.cjs.map +1 -0
  240. package/build/dataloaders/lensDataLoader.d.cts +15 -0
  241. package/build/dataloaders/lensDataLoader.d.cts.map +1 -0
  242. package/build/dataloaders/lensDataLoader.d.mts +15 -0
  243. package/build/dataloaders/lensDataLoader.d.mts.map +1 -0
  244. package/build/dataloaders/lensDataLoader.js +172 -176
  245. package/build/dataloaders/lensDataLoader.js.map +1 -1
  246. package/build/dataloaders/manyToManyFindDataLoader.cjs +84 -0
  247. package/build/dataloaders/manyToManyFindDataLoader.cjs.map +1 -0
  248. package/build/dataloaders/manyToManyFindDataLoader.d.cts +12 -0
  249. package/build/dataloaders/manyToManyFindDataLoader.d.cts.map +1 -0
  250. package/build/dataloaders/manyToManyFindDataLoader.d.mts +12 -0
  251. package/build/dataloaders/manyToManyFindDataLoader.d.mts.map +1 -0
  252. package/build/dataloaders/manyToManyFindDataLoader.js +76 -70
  253. package/build/dataloaders/manyToManyFindDataLoader.js.map +1 -1
  254. package/build/dataloaders/oneToManyFindDataLoader.cjs +77 -0
  255. package/build/dataloaders/oneToManyFindDataLoader.cjs.map +1 -0
  256. package/build/dataloaders/oneToManyFindDataLoader.d.cts +12 -0
  257. package/build/dataloaders/oneToManyFindDataLoader.d.cts.map +1 -0
  258. package/build/dataloaders/oneToManyFindDataLoader.d.mts +12 -0
  259. package/build/dataloaders/oneToManyFindDataLoader.d.mts.map +1 -0
  260. package/build/dataloaders/oneToManyFindDataLoader.js +71 -67
  261. package/build/dataloaders/oneToManyFindDataLoader.js.map +1 -1
  262. package/build/defaults.cjs +195 -0
  263. package/build/defaults.cjs.map +1 -0
  264. package/build/defaults.d.cts +56 -0
  265. package/build/defaults.d.cts.map +1 -0
  266. package/build/defaults.d.mts +56 -0
  267. package/build/defaults.d.mts.map +1 -0
  268. package/build/defaults.js +171 -271
  269. package/build/defaults.js.map +1 -1
  270. package/build/drivers/Driver.cjs +3 -0
  271. package/build/drivers/Driver.d.cts +51 -0
  272. package/build/drivers/Driver.d.cts.map +1 -0
  273. package/build/drivers/Driver.d.mts +51 -0
  274. package/build/drivers/Driver.d.mts.map +1 -0
  275. package/build/drivers/Driver.js +3 -3
  276. package/build/drivers/EntityWriter.cjs +208 -0
  277. package/build/drivers/EntityWriter.cjs.map +1 -0
  278. package/build/drivers/EntityWriter.d.cts +66 -0
  279. package/build/drivers/EntityWriter.d.cts.map +1 -0
  280. package/build/drivers/EntityWriter.d.mts +66 -0
  281. package/build/drivers/EntityWriter.d.mts.map +1 -0
  282. package/build/drivers/EntityWriter.js +183 -219
  283. package/build/drivers/EntityWriter.js.map +1 -1
  284. package/build/drivers/IdAssigner.cjs +89 -0
  285. package/build/drivers/IdAssigner.cjs.map +1 -0
  286. package/build/drivers/IdAssigner.d.cts +50 -0
  287. package/build/drivers/IdAssigner.d.cts.map +1 -0
  288. package/build/drivers/IdAssigner.d.mts +50 -0
  289. package/build/drivers/IdAssigner.d.mts.map +1 -0
  290. package/build/drivers/IdAssigner.js +80 -124
  291. package/build/drivers/IdAssigner.js.map +1 -1
  292. package/build/drivers/driverApi.cjs +19 -0
  293. package/build/drivers/driverApi.cjs.map +1 -0
  294. package/build/drivers/driverApi.d.cts +22 -0
  295. package/build/drivers/driverApi.d.cts.map +1 -0
  296. package/build/drivers/driverApi.d.mts +22 -0
  297. package/build/drivers/driverApi.d.mts.map +1 -0
  298. package/build/drivers/driverApi.js +18 -0
  299. package/build/drivers/driverApi.js.map +1 -0
  300. package/build/drivers/index.cjs +7 -0
  301. package/build/drivers/index.d.cts +4 -0
  302. package/build/drivers/index.d.mts +4 -0
  303. package/build/drivers/index.js +3 -22
  304. package/build/fields.cjs +127 -0
  305. package/build/fields.cjs.map +1 -0
  306. package/build/fields.d.cts +29 -0
  307. package/build/fields.d.cts.map +1 -0
  308. package/build/fields.d.mts +29 -0
  309. package/build/fields.d.mts.map +1 -0
  310. package/build/fields.js +98 -160
  311. package/build/fields.js.map +1 -1
  312. package/build/flush/FlushLock.cjs +51 -0
  313. package/build/flush/FlushLock.cjs.map +1 -0
  314. package/build/flush/FlushLock.d.cts +29 -0
  315. package/build/flush/FlushLock.d.cts.map +1 -0
  316. package/build/flush/FlushLock.d.mts +29 -0
  317. package/build/flush/FlushLock.d.mts.map +1 -0
  318. package/build/flush/FlushLock.js +51 -0
  319. package/build/flush/FlushLock.js.map +1 -0
  320. package/build/flush/JoinRows.cjs +263 -0
  321. package/build/flush/JoinRows.cjs.map +1 -0
  322. package/build/flush/JoinRows.d.cts +120 -0
  323. package/build/flush/JoinRows.d.cts.map +1 -0
  324. package/build/flush/JoinRows.d.mts +120 -0
  325. package/build/flush/JoinRows.d.mts.map +1 -0
  326. package/build/flush/JoinRows.js +261 -0
  327. package/build/flush/JoinRows.js.map +1 -0
  328. package/build/flush/PendingChanges.cjs +1 -0
  329. package/build/flush/PendingChanges.d.cts +29 -0
  330. package/build/flush/PendingChanges.d.cts.map +1 -0
  331. package/build/flush/PendingChanges.d.mts +29 -0
  332. package/build/flush/PendingChanges.d.mts.map +1 -0
  333. package/build/flush/PendingChanges.js +1 -0
  334. package/build/flush/Todo.cjs +71 -0
  335. package/build/flush/Todo.cjs.map +1 -0
  336. package/build/flush/Todo.d.cts +38 -0
  337. package/build/flush/Todo.d.cts.map +1 -0
  338. package/build/flush/Todo.d.mts +38 -0
  339. package/build/flush/Todo.d.mts.map +1 -0
  340. package/build/flush/Todo.js +67 -0
  341. package/build/flush/Todo.js.map +1 -0
  342. package/build/getProperties.cjs +87 -0
  343. package/build/getProperties.cjs.map +1 -0
  344. package/build/getProperties.d.cts +30 -0
  345. package/build/getProperties.d.cts.map +1 -0
  346. package/build/getProperties.d.mts +30 -0
  347. package/build/getProperties.d.mts.map +1 -0
  348. package/build/getProperties.js +71 -128
  349. package/build/getProperties.js.map +1 -1
  350. package/build/index.cjs +524 -0
  351. package/build/index.cjs.map +1 -0
  352. package/build/index.d.cts +180 -0
  353. package/build/index.d.cts.map +1 -0
  354. package/build/index.d.mts +180 -0
  355. package/build/index.d.mts.map +1 -0
  356. package/build/index.js +171 -292
  357. package/build/index.js.map +1 -1
  358. package/build/json.cjs +79 -0
  359. package/build/json.cjs.map +1 -0
  360. package/build/json.d.cts +76 -0
  361. package/build/json.d.cts.map +1 -0
  362. package/build/json.d.mts +76 -0
  363. package/build/json.d.mts.map +1 -0
  364. package/build/json.js +68 -106
  365. package/build/json.js.map +1 -1
  366. package/build/k.cjs +9 -0
  367. package/build/k.cjs.map +1 -0
  368. package/build/k.d.cts +1 -0
  369. package/build/k.d.mts +1 -0
  370. package/build/k.js +6 -6
  371. package/build/k.js.map +1 -1
  372. package/build/keys.cjs +181 -0
  373. package/build/keys.cjs.map +1 -0
  374. package/build/keys.d.cts +55 -0
  375. package/build/keys.d.cts.map +1 -0
  376. package/build/keys.d.mts +55 -0
  377. package/build/keys.d.mts.map +1 -0
  378. package/build/keys.js +129 -162
  379. package/build/keys.js.map +1 -1
  380. package/build/loading/HintTree.cjs +67 -0
  381. package/build/loading/HintTree.cjs.map +1 -0
  382. package/build/loading/HintTree.d.cts +45 -0
  383. package/build/loading/HintTree.d.cts.map +1 -0
  384. package/build/loading/HintTree.d.mts +45 -0
  385. package/build/loading/HintTree.d.mts.map +1 -0
  386. package/build/loading/HintTree.js +66 -0
  387. package/build/loading/HintTree.js.map +1 -0
  388. package/build/loading/IsLoadedCache.cjs +58 -0
  389. package/build/loading/IsLoadedCache.cjs.map +1 -0
  390. package/build/loading/IsLoadedCache.d.cts +35 -0
  391. package/build/loading/IsLoadedCache.d.cts.map +1 -0
  392. package/build/loading/IsLoadedCache.d.mts +35 -0
  393. package/build/loading/IsLoadedCache.d.mts.map +1 -0
  394. package/build/loading/IsLoadedCache.js +57 -0
  395. package/build/loading/IsLoadedCache.js.map +1 -0
  396. package/build/loading/loadHints.cjs +95 -0
  397. package/build/loading/loadHints.cjs.map +1 -0
  398. package/build/loading/loadHints.d.cts +116 -0
  399. package/build/loading/loadHints.d.cts.map +1 -0
  400. package/build/loading/loadHints.d.mts +116 -0
  401. package/build/loading/loadHints.d.mts.map +1 -0
  402. package/build/loading/loadHints.js +88 -0
  403. package/build/loading/loadHints.js.map +1 -0
  404. package/build/loading/loadLens.cjs +212 -0
  405. package/build/loading/loadLens.cjs.map +1 -0
  406. package/build/loading/loadLens.d.cts +77 -0
  407. package/build/loading/loadLens.d.cts.map +1 -0
  408. package/build/loading/loadLens.d.mts +77 -0
  409. package/build/loading/loadLens.d.mts.map +1 -0
  410. package/build/loading/loadLens.js +201 -0
  411. package/build/loading/loadLens.js.map +1 -0
  412. package/build/loading/withLoaded.cjs +64 -0
  413. package/build/loading/withLoaded.cjs.map +1 -0
  414. package/build/loading/withLoaded.d.cts +65 -0
  415. package/build/loading/withLoaded.d.cts.map +1 -0
  416. package/build/loading/withLoaded.d.mts +65 -0
  417. package/build/loading/withLoaded.d.mts.map +1 -0
  418. package/build/loading/withLoaded.js +61 -0
  419. package/build/loading/withLoaded.js.map +1 -0
  420. package/build/logging/FactoryLogger.cjs +66 -0
  421. package/build/logging/FactoryLogger.cjs.map +1 -0
  422. package/build/logging/FactoryLogger.d.cts +27 -0
  423. package/build/logging/FactoryLogger.d.cts.map +1 -0
  424. package/build/logging/FactoryLogger.d.mts +27 -0
  425. package/build/logging/FactoryLogger.d.mts.map +1 -0
  426. package/build/logging/FactoryLogger.js +58 -73
  427. package/build/logging/FactoryLogger.js.map +1 -1
  428. package/build/logging/FieldLogger.cjs +57 -0
  429. package/build/logging/FieldLogger.cjs.map +1 -0
  430. package/build/logging/FieldLogger.d.cts +32 -0
  431. package/build/logging/FieldLogger.d.cts.map +1 -0
  432. package/build/logging/FieldLogger.d.mts +32 -0
  433. package/build/logging/FieldLogger.d.mts.map +1 -0
  434. package/build/logging/FieldLogger.js +51 -67
  435. package/build/logging/FieldLogger.js.map +1 -1
  436. package/build/logging/ReactionLogger.cjs +93 -0
  437. package/build/logging/ReactionLogger.cjs.map +1 -0
  438. package/build/logging/ReactionLogger.d.cts +37 -0
  439. package/build/logging/ReactionLogger.d.cts.map +1 -0
  440. package/build/logging/ReactionLogger.d.mts +37 -0
  441. package/build/logging/ReactionLogger.d.mts.map +1 -0
  442. package/build/logging/ReactionLogger.js +76 -66
  443. package/build/logging/ReactionLogger.js.map +1 -1
  444. package/build/newEntity.cjs +89 -0
  445. package/build/newEntity.cjs.map +1 -0
  446. package/build/newEntity.d.cts +48 -0
  447. package/build/newEntity.d.cts.map +1 -0
  448. package/build/newEntity.d.mts +48 -0
  449. package/build/newEntity.d.mts.map +1 -0
  450. package/build/newEntity.js +71 -94
  451. package/build/newEntity.js.map +1 -1
  452. package/build/newTestInstance.cjs +539 -0
  453. package/build/newTestInstance.cjs.map +1 -0
  454. package/build/newTestInstance.d.cts +207 -0
  455. package/build/newTestInstance.d.cts.map +1 -0
  456. package/build/newTestInstance.d.mts +207 -0
  457. package/build/newTestInstance.d.mts.map +1 -0
  458. package/build/newTestInstance.js +459 -721
  459. package/build/newTestInstance.js.map +1 -1
  460. package/build/normalizeHints.cjs +58 -0
  461. package/build/normalizeHints.cjs.map +1 -0
  462. package/build/normalizeHints.d.cts +24 -0
  463. package/build/normalizeHints.d.cts.map +1 -0
  464. package/build/normalizeHints.d.mts +24 -0
  465. package/build/normalizeHints.d.mts.map +1 -0
  466. package/build/normalizeHints.js +40 -55
  467. package/build/normalizeHints.js.map +1 -1
  468. package/build/nowUTC.cjs +15 -0
  469. package/build/nowUTC.cjs.map +1 -0
  470. package/build/nowUTC.d.cts +10 -0
  471. package/build/nowUTC.d.cts.map +1 -0
  472. package/build/nowUTC.d.mts +10 -0
  473. package/build/nowUTC.d.mts.map +1 -0
  474. package/build/nowUTC.js +14 -0
  475. package/build/nowUTC.js.map +1 -0
  476. package/build/plugins/ImmutableEntitiesPlugin.cjs +21 -0
  477. package/build/plugins/ImmutableEntitiesPlugin.cjs.map +1 -0
  478. package/build/plugins/ImmutableEntitiesPlugin.d.cts +12 -0
  479. package/build/plugins/ImmutableEntitiesPlugin.d.cts.map +1 -0
  480. package/build/plugins/ImmutableEntitiesPlugin.d.mts +12 -0
  481. package/build/plugins/ImmutableEntitiesPlugin.d.mts.map +1 -0
  482. package/build/plugins/ImmutableEntitiesPlugin.js +19 -20
  483. package/build/plugins/ImmutableEntitiesPlugin.js.map +1 -1
  484. package/build/plugins/PreloadPlugin.cjs +3 -0
  485. package/build/plugins/PreloadPlugin.d.cts +77 -0
  486. package/build/plugins/PreloadPlugin.d.cts.map +1 -0
  487. package/build/plugins/PreloadPlugin.d.mts +77 -0
  488. package/build/plugins/PreloadPlugin.d.mts.map +1 -0
  489. package/build/plugins/PreloadPlugin.js +3 -3
  490. package/build/preloading/JsonAggregatePreloader.cjs +280 -0
  491. package/build/preloading/JsonAggregatePreloader.cjs.map +1 -0
  492. package/build/preloading/JsonAggregatePreloader.d.cts +19 -0
  493. package/build/preloading/JsonAggregatePreloader.d.cts.map +1 -0
  494. package/build/preloading/JsonAggregatePreloader.d.mts +19 -0
  495. package/build/preloading/JsonAggregatePreloader.d.mts.map +1 -0
  496. package/build/preloading/JsonAggregatePreloader.js +270 -320
  497. package/build/preloading/JsonAggregatePreloader.js.map +1 -1
  498. package/build/preloading/canPreload.cjs +19 -0
  499. package/build/preloading/canPreload.cjs.map +1 -0
  500. package/build/preloading/canPreload.d.cts +6 -0
  501. package/build/preloading/canPreload.d.cts.map +1 -0
  502. package/build/preloading/canPreload.d.mts +6 -0
  503. package/build/preloading/canPreload.d.mts.map +1 -0
  504. package/build/preloading/canPreload.js +15 -21
  505. package/build/preloading/canPreload.js.map +1 -1
  506. package/build/preloading/partitionHint.cjs +43 -0
  507. package/build/preloading/partitionHint.cjs.map +1 -0
  508. package/build/preloading/partitionHint.d.cts +8 -0
  509. package/build/preloading/partitionHint.d.cts.map +1 -0
  510. package/build/preloading/partitionHint.d.mts +8 -0
  511. package/build/preloading/partitionHint.d.mts.map +1 -0
  512. package/build/preloading/partitionHint.js +36 -56
  513. package/build/preloading/partitionHint.js.map +1 -1
  514. package/build/queries/ConditionBuilder.cjs +106 -0
  515. package/build/queries/ConditionBuilder.cjs.map +1 -0
  516. package/build/queries/ConditionBuilder.d.cts +31 -0
  517. package/build/queries/ConditionBuilder.d.cts.map +1 -0
  518. package/build/queries/ConditionBuilder.d.mts +31 -0
  519. package/build/queries/ConditionBuilder.d.mts.map +1 -0
  520. package/build/queries/ConditionBuilder.js +105 -0
  521. package/build/queries/ConditionBuilder.js.map +1 -0
  522. package/build/queries/conditions.cjs +15 -0
  523. package/build/queries/conditions.cjs.map +1 -0
  524. package/build/queries/conditions.d.cts +38 -0
  525. package/build/queries/conditions.d.cts.map +1 -0
  526. package/build/queries/conditions.d.mts +38 -0
  527. package/build/queries/conditions.d.mts.map +1 -0
  528. package/build/queries/conditions.js +13 -0
  529. package/build/queries/conditions.js.map +1 -0
  530. package/build/queries/entityQueryUtils.cjs +60 -0
  531. package/build/queries/entityQueryUtils.cjs.map +1 -0
  532. package/build/queries/entityQueryUtils.d.cts +19 -0
  533. package/build/queries/entityQueryUtils.d.cts.map +1 -0
  534. package/build/queries/entityQueryUtils.d.mts +19 -0
  535. package/build/queries/entityQueryUtils.d.mts.map +1 -0
  536. package/build/queries/entityQueryUtils.js +56 -0
  537. package/build/queries/entityQueryUtils.js.map +1 -0
  538. package/build/queries/find/Aliases.cjs +301 -0
  539. package/build/queries/find/Aliases.cjs.map +1 -0
  540. package/build/queries/find/Aliases.d.cts +122 -0
  541. package/build/queries/find/Aliases.d.cts.map +1 -0
  542. package/build/queries/find/Aliases.d.mts +122 -0
  543. package/build/queries/find/Aliases.d.mts.map +1 -0
  544. package/build/queries/find/Aliases.js +293 -0
  545. package/build/queries/find/Aliases.js.map +1 -0
  546. package/build/queries/find/DeferredAlias.cjs +25 -0
  547. package/build/queries/find/DeferredAlias.cjs.map +1 -0
  548. package/build/queries/find/DeferredAlias.d.cts +22 -0
  549. package/build/queries/find/DeferredAlias.d.cts.map +1 -0
  550. package/build/queries/find/DeferredAlias.d.mts +22 -0
  551. package/build/queries/find/DeferredAlias.d.mts.map +1 -0
  552. package/build/queries/find/DeferredAlias.js +22 -0
  553. package/build/queries/find/DeferredAlias.js.map +1 -0
  554. package/build/queries/find/EntityFilter.cjs +27 -0
  555. package/build/queries/find/EntityFilter.cjs.map +1 -0
  556. package/build/queries/find/EntityFilter.d.cts +127 -0
  557. package/build/queries/find/EntityFilter.d.cts.map +1 -0
  558. package/build/queries/find/EntityFilter.d.mts +127 -0
  559. package/build/queries/find/EntityFilter.d.mts.map +1 -0
  560. package/build/queries/find/EntityFilter.js +26 -0
  561. package/build/queries/find/EntityFilter.js.map +1 -0
  562. package/build/queries/find/EntityGraphQLFilter.cjs +52 -0
  563. package/build/queries/find/EntityGraphQLFilter.cjs.map +1 -0
  564. package/build/queries/find/EntityGraphQLFilter.d.cts +59 -0
  565. package/build/queries/find/EntityGraphQLFilter.d.cts.map +1 -0
  566. package/build/queries/find/EntityGraphQLFilter.d.mts +59 -0
  567. package/build/queries/find/EntityGraphQLFilter.d.mts.map +1 -0
  568. package/build/queries/find/EntityGraphQLFilter.js +50 -0
  569. package/build/queries/find/EntityGraphQLFilter.js.map +1 -0
  570. package/build/queries/find/QueryParser.cjs +553 -0
  571. package/build/queries/find/QueryParser.cjs.map +1 -0
  572. package/build/queries/find/QueryParser.collectionJoins.cjs +353 -0
  573. package/build/queries/find/QueryParser.collectionJoins.cjs.map +1 -0
  574. package/build/queries/find/QueryParser.collectionJoins.d.cts +30 -0
  575. package/build/queries/find/QueryParser.collectionJoins.d.cts.map +1 -0
  576. package/build/queries/find/QueryParser.collectionJoins.d.mts +30 -0
  577. package/build/queries/find/QueryParser.collectionJoins.d.mts.map +1 -0
  578. package/build/queries/find/QueryParser.collectionJoins.js +352 -0
  579. package/build/queries/find/QueryParser.collectionJoins.js.map +1 -0
  580. package/build/queries/find/QueryParser.d.cts +192 -0
  581. package/build/queries/find/QueryParser.d.cts.map +1 -0
  582. package/build/queries/find/QueryParser.d.mts +192 -0
  583. package/build/queries/find/QueryParser.d.mts.map +1 -0
  584. package/build/queries/find/QueryParser.js +546 -0
  585. package/build/queries/find/QueryParser.js.map +1 -0
  586. package/build/queries/find/QueryParser.pruning.cjs +115 -0
  587. package/build/queries/find/QueryParser.pruning.cjs.map +1 -0
  588. package/build/queries/find/QueryParser.pruning.d.cts +8 -0
  589. package/build/queries/find/QueryParser.pruning.d.cts.map +1 -0
  590. package/build/queries/find/QueryParser.pruning.d.mts +8 -0
  591. package/build/queries/find/QueryParser.pruning.d.mts.map +1 -0
  592. package/build/queries/find/QueryParser.pruning.js +113 -0
  593. package/build/queries/find/QueryParser.pruning.js.map +1 -0
  594. package/build/queries/find/QueryVisitor.cjs +77 -0
  595. package/build/queries/find/QueryVisitor.cjs.map +1 -0
  596. package/build/queries/find/QueryVisitor.d.cts +24 -0
  597. package/build/queries/find/QueryVisitor.d.cts.map +1 -0
  598. package/build/queries/find/QueryVisitor.d.mts +24 -0
  599. package/build/queries/find/QueryVisitor.d.mts.map +1 -0
  600. package/build/queries/find/QueryVisitor.js +74 -0
  601. package/build/queries/find/QueryVisitor.js.map +1 -0
  602. package/build/queries/find/buildFindQuery.cjs +112 -0
  603. package/build/queries/find/buildFindQuery.cjs.map +1 -0
  604. package/build/queries/find/buildFindQuery.d.cts +24 -0
  605. package/build/queries/find/buildFindQuery.d.cts.map +1 -0
  606. package/build/queries/find/buildFindQuery.d.mts +24 -0
  607. package/build/queries/find/buildFindQuery.d.mts.map +1 -0
  608. package/build/queries/find/buildFindQuery.js +110 -0
  609. package/build/queries/find/buildFindQuery.js.map +1 -0
  610. package/build/queries/find/scopes.cjs +301 -0
  611. package/build/queries/find/scopes.cjs.map +1 -0
  612. package/build/queries/find/scopes.d.cts +188 -0
  613. package/build/queries/find/scopes.d.cts.map +1 -0
  614. package/build/queries/find/scopes.d.mts +188 -0
  615. package/build/queries/find/scopes.d.mts.map +1 -0
  616. package/build/queries/find/scopes.js +296 -0
  617. package/build/queries/find/scopes.js.map +1 -0
  618. package/build/queries/parsedConditions.cjs +21 -0
  619. package/build/queries/parsedConditions.cjs.map +1 -0
  620. package/build/queries/parsedConditions.d.cts +127 -0
  621. package/build/queries/parsedConditions.d.cts.map +1 -0
  622. package/build/queries/parsedConditions.d.mts +127 -0
  623. package/build/queries/parsedConditions.d.mts.map +1 -0
  624. package/build/queries/parsedConditions.js +20 -0
  625. package/build/queries/parsedConditions.js.map +1 -0
  626. package/build/queries/renderConditions.cjs +66 -0
  627. package/build/queries/renderConditions.cjs.map +1 -0
  628. package/build/queries/renderConditions.d.cts +15 -0
  629. package/build/queries/renderConditions.d.cts.map +1 -0
  630. package/build/queries/renderConditions.d.mts +15 -0
  631. package/build/queries/renderConditions.d.mts.map +1 -0
  632. package/build/queries/renderConditions.js +64 -0
  633. package/build/queries/renderConditions.js.map +1 -0
  634. package/build/queries/skipCondition.cjs +14 -0
  635. package/build/queries/skipCondition.cjs.map +1 -0
  636. package/build/queries/skipCondition.d.cts +7 -0
  637. package/build/queries/skipCondition.d.cts.map +1 -0
  638. package/build/queries/skipCondition.d.mts +7 -0
  639. package/build/queries/skipCondition.d.mts.map +1 -0
  640. package/build/queries/skipCondition.js +13 -0
  641. package/build/queries/skipCondition.js.map +1 -0
  642. package/build/queries/sql/AliasAssigner.cjs +35 -0
  643. package/build/queries/sql/AliasAssigner.cjs.map +1 -0
  644. package/build/queries/sql/AliasAssigner.d.cts +13 -0
  645. package/build/queries/sql/AliasAssigner.d.cts.map +1 -0
  646. package/build/queries/sql/AliasAssigner.d.mts +13 -0
  647. package/build/queries/sql/AliasAssigner.d.mts.map +1 -0
  648. package/build/queries/sql/AliasAssigner.js +34 -0
  649. package/build/queries/sql/AliasAssigner.js.map +1 -0
  650. package/build/queries/sql/Expr.cjs +529 -0
  651. package/build/queries/sql/Expr.cjs.map +1 -0
  652. package/build/queries/sql/Expr.d.cts +284 -0
  653. package/build/queries/sql/Expr.d.cts.map +1 -0
  654. package/build/queries/sql/Expr.d.mts +284 -0
  655. package/build/queries/sql/Expr.d.mts.map +1 -0
  656. package/build/queries/sql/Expr.js +512 -0
  657. package/build/queries/sql/Expr.js.map +1 -0
  658. package/build/queries/sql/JoinTree.cjs +72 -0
  659. package/build/queries/sql/JoinTree.cjs.map +1 -0
  660. package/build/queries/sql/JoinTree.d.cts +107 -0
  661. package/build/queries/sql/JoinTree.d.cts.map +1 -0
  662. package/build/queries/sql/JoinTree.d.mts +107 -0
  663. package/build/queries/sql/JoinTree.d.mts.map +1 -0
  664. package/build/queries/sql/JoinTree.js +71 -0
  665. package/build/queries/sql/JoinTree.js.map +1 -0
  666. package/build/queries/sql/Tables.cjs +803 -0
  667. package/build/queries/sql/Tables.cjs.map +1 -0
  668. package/build/queries/sql/Tables.d.cts +322 -0
  669. package/build/queries/sql/Tables.d.cts.map +1 -0
  670. package/build/queries/sql/Tables.d.mts +322 -0
  671. package/build/queries/sql/Tables.d.mts.map +1 -0
  672. package/build/queries/sql/Tables.js +786 -0
  673. package/build/queries/sql/Tables.js.map +1 -0
  674. package/build/queries/sql/custom.cjs +52 -0
  675. package/build/queries/sql/custom.cjs.map +1 -0
  676. package/build/queries/sql/custom.d.cts +85 -0
  677. package/build/queries/sql/custom.d.cts.map +1 -0
  678. package/build/queries/sql/custom.d.mts +85 -0
  679. package/build/queries/sql/custom.d.mts.map +1 -0
  680. package/build/queries/sql/custom.js +49 -0
  681. package/build/queries/sql/custom.js.map +1 -0
  682. package/build/queries/sql/execute.cjs +255 -0
  683. package/build/queries/sql/execute.cjs.map +1 -0
  684. package/build/queries/sql/execute.d.cts +311 -0
  685. package/build/queries/sql/execute.d.cts.map +1 -0
  686. package/build/queries/sql/execute.d.mts +311 -0
  687. package/build/queries/sql/execute.d.mts.map +1 -0
  688. package/build/queries/sql/execute.js +252 -0
  689. package/build/queries/sql/execute.js.map +1 -0
  690. package/build/queries/sql/expressions/arrayAgg.cjs +63 -0
  691. package/build/queries/sql/expressions/arrayAgg.cjs.map +1 -0
  692. package/build/queries/sql/expressions/arrayAgg.d.cts +24 -0
  693. package/build/queries/sql/expressions/arrayAgg.d.cts.map +1 -0
  694. package/build/queries/sql/expressions/arrayAgg.d.mts +24 -0
  695. package/build/queries/sql/expressions/arrayAgg.d.mts.map +1 -0
  696. package/build/queries/sql/expressions/arrayAgg.js +61 -0
  697. package/build/queries/sql/expressions/arrayAgg.js.map +1 -0
  698. package/build/queries/sql/expressions/case.cjs +71 -0
  699. package/build/queries/sql/expressions/case.cjs.map +1 -0
  700. package/build/queries/sql/expressions/case.d.cts +57 -0
  701. package/build/queries/sql/expressions/case.d.cts.map +1 -0
  702. package/build/queries/sql/expressions/case.d.mts +57 -0
  703. package/build/queries/sql/expressions/case.d.mts.map +1 -0
  704. package/build/queries/sql/expressions/case.js +68 -0
  705. package/build/queries/sql/expressions/case.js.map +1 -0
  706. package/build/queries/sql/expressions/coalesce.cjs +25 -0
  707. package/build/queries/sql/expressions/coalesce.cjs.map +1 -0
  708. package/build/queries/sql/expressions/coalesce.d.cts +21 -0
  709. package/build/queries/sql/expressions/coalesce.d.cts.map +1 -0
  710. package/build/queries/sql/expressions/coalesce.d.mts +21 -0
  711. package/build/queries/sql/expressions/coalesce.d.mts.map +1 -0
  712. package/build/queries/sql/expressions/coalesce.js +22 -0
  713. package/build/queries/sql/expressions/coalesce.js.map +1 -0
  714. package/build/queries/sql/expressions/codecs.cjs +126 -0
  715. package/build/queries/sql/expressions/codecs.cjs.map +1 -0
  716. package/build/queries/sql/expressions/codecs.d.cts +11 -0
  717. package/build/queries/sql/expressions/codecs.d.cts.map +1 -0
  718. package/build/queries/sql/expressions/codecs.d.mts +11 -0
  719. package/build/queries/sql/expressions/codecs.d.mts.map +1 -0
  720. package/build/queries/sql/expressions/codecs.js +125 -0
  721. package/build/queries/sql/expressions/codecs.js.map +1 -0
  722. package/build/queries/sql/expressions/expression.cjs +102 -0
  723. package/build/queries/sql/expressions/expression.cjs.map +1 -0
  724. package/build/queries/sql/expressions/expression.d.cts +23 -0
  725. package/build/queries/sql/expressions/expression.d.cts.map +1 -0
  726. package/build/queries/sql/expressions/expression.d.mts +23 -0
  727. package/build/queries/sql/expressions/expression.d.mts.map +1 -0
  728. package/build/queries/sql/expressions/expression.js +97 -0
  729. package/build/queries/sql/expressions/expression.js.map +1 -0
  730. package/build/queries/sql/expressions/greatest.cjs +25 -0
  731. package/build/queries/sql/expressions/greatest.cjs.map +1 -0
  732. package/build/queries/sql/expressions/greatest.d.cts +21 -0
  733. package/build/queries/sql/expressions/greatest.d.cts.map +1 -0
  734. package/build/queries/sql/expressions/greatest.d.mts +21 -0
  735. package/build/queries/sql/expressions/greatest.d.mts.map +1 -0
  736. package/build/queries/sql/expressions/greatest.js +22 -0
  737. package/build/queries/sql/expressions/greatest.js.map +1 -0
  738. package/build/queries/sql/expressions/least.cjs +25 -0
  739. package/build/queries/sql/expressions/least.cjs.map +1 -0
  740. package/build/queries/sql/expressions/least.d.cts +21 -0
  741. package/build/queries/sql/expressions/least.d.cts.map +1 -0
  742. package/build/queries/sql/expressions/least.d.mts +21 -0
  743. package/build/queries/sql/expressions/least.d.mts.map +1 -0
  744. package/build/queries/sql/expressions/least.js +22 -0
  745. package/build/queries/sql/expressions/least.js.map +1 -0
  746. package/build/queries/sql/expressions/nullIf.cjs +27 -0
  747. package/build/queries/sql/expressions/nullIf.cjs.map +1 -0
  748. package/build/queries/sql/expressions/nullIf.d.cts +22 -0
  749. package/build/queries/sql/expressions/nullIf.d.cts.map +1 -0
  750. package/build/queries/sql/expressions/nullIf.d.mts +22 -0
  751. package/build/queries/sql/expressions/nullIf.d.mts.map +1 -0
  752. package/build/queries/sql/expressions/nullIf.js +24 -0
  753. package/build/queries/sql/expressions/nullIf.js.map +1 -0
  754. package/build/queries/sql/expressions/parseExpression.cjs +75 -0
  755. package/build/queries/sql/expressions/parseExpression.cjs.map +1 -0
  756. package/build/queries/sql/expressions/parseExpression.d.cts +19 -0
  757. package/build/queries/sql/expressions/parseExpression.d.cts.map +1 -0
  758. package/build/queries/sql/expressions/parseExpression.d.mts +19 -0
  759. package/build/queries/sql/expressions/parseExpression.d.mts.map +1 -0
  760. package/build/queries/sql/expressions/parseExpression.js +70 -0
  761. package/build/queries/sql/expressions/parseExpression.js.map +1 -0
  762. package/build/queries/sql/expressions/types.cjs +1 -0
  763. package/build/queries/sql/expressions/types.d.cts +114 -0
  764. package/build/queries/sql/expressions/types.d.cts.map +1 -0
  765. package/build/queries/sql/expressions/types.d.mts +114 -0
  766. package/build/queries/sql/expressions/types.d.mts.map +1 -0
  767. package/build/queries/sql/expressions/types.js +1 -0
  768. package/build/queries/sql/keywords.cjs +136 -0
  769. package/build/queries/sql/keywords.cjs.map +1 -0
  770. package/build/queries/sql/keywords.d.cts +18 -0
  771. package/build/queries/sql/keywords.d.cts.map +1 -0
  772. package/build/queries/sql/keywords.d.mts +18 -0
  773. package/build/queries/sql/keywords.d.mts.map +1 -0
  774. package/build/queries/sql/keywords.js +132 -0
  775. package/build/queries/sql/keywords.js.map +1 -0
  776. package/build/queries/sql/query.cjs +1657 -0
  777. package/build/queries/sql/query.cjs.map +1 -0
  778. package/build/queries/sql/query.d.cts +887 -0
  779. package/build/queries/sql/query.d.cts.map +1 -0
  780. package/build/queries/sql/query.d.mts +887 -0
  781. package/build/queries/sql/query.d.mts.map +1 -0
  782. package/build/queries/sql/query.js +1637 -0
  783. package/build/queries/sql/query.js.map +1 -0
  784. package/build/queries/unnest.cjs +62 -0
  785. package/build/queries/unnest.cjs.map +1 -0
  786. package/build/queries/unnest.d.cts +16 -0
  787. package/build/queries/unnest.d.cts.map +1 -0
  788. package/build/queries/unnest.d.mts +16 -0
  789. package/build/queries/unnest.d.mts.map +1 -0
  790. package/build/queries/unnest.js +60 -0
  791. package/build/queries/unnest.js.map +1 -0
  792. package/build/queries/valueFilters.cjs +240 -0
  793. package/build/queries/valueFilters.cjs.map +1 -0
  794. package/build/queries/valueFilters.d.cts +26 -0
  795. package/build/queries/valueFilters.d.cts.map +1 -0
  796. package/build/queries/valueFilters.d.mts +26 -0
  797. package/build/queries/valueFilters.d.mts.map +1 -0
  798. package/build/queries/valueFilters.js +236 -0
  799. package/build/queries/valueFilters.js.map +1 -0
  800. package/build/reactivity/ReactionsManager.cjs +264 -0
  801. package/build/reactivity/ReactionsManager.cjs.map +1 -0
  802. package/build/reactivity/ReactionsManager.d.cts +98 -0
  803. package/build/reactivity/ReactionsManager.d.cts.map +1 -0
  804. package/build/reactivity/ReactionsManager.d.mts +98 -0
  805. package/build/reactivity/ReactionsManager.d.mts.map +1 -0
  806. package/build/reactivity/ReactionsManager.js +263 -0
  807. package/build/reactivity/ReactionsManager.js.map +1 -0
  808. package/build/reactivity/reactiveHints.cjs +328 -0
  809. package/build/reactivity/reactiveHints.cjs.map +1 -0
  810. package/build/reactivity/reactiveHints.d.cts +143 -0
  811. package/build/reactivity/reactiveHints.d.cts.map +1 -0
  812. package/build/reactivity/reactiveHints.d.mts +143 -0
  813. package/build/reactivity/reactiveHints.d.mts.map +1 -0
  814. package/build/reactivity/reactiveHints.js +321 -0
  815. package/build/reactivity/reactiveHints.js.map +1 -0
  816. package/build/relations/AbstractPropertyImpl.cjs +16 -0
  817. package/build/relations/AbstractPropertyImpl.cjs.map +1 -0
  818. package/build/relations/AbstractPropertyImpl.d.cts +11 -0
  819. package/build/relations/AbstractPropertyImpl.d.cts.map +1 -0
  820. package/build/relations/AbstractPropertyImpl.d.mts +11 -0
  821. package/build/relations/AbstractPropertyImpl.d.mts.map +1 -0
  822. package/build/relations/AbstractPropertyImpl.js +13 -13
  823. package/build/relations/AbstractPropertyImpl.js.map +1 -1
  824. package/build/relations/AbstractRelationImpl.cjs +15 -0
  825. package/build/relations/AbstractRelationImpl.cjs.map +1 -0
  826. package/build/relations/AbstractRelationImpl.d.cts +43 -0
  827. package/build/relations/AbstractRelationImpl.d.cts.map +1 -0
  828. package/build/relations/AbstractRelationImpl.d.mts +43 -0
  829. package/build/relations/AbstractRelationImpl.d.mts.map +1 -0
  830. package/build/relations/AbstractRelationImpl.js +12 -17
  831. package/build/relations/AbstractRelationImpl.js.map +1 -1
  832. package/build/relations/AsyncProperty.cjs +75 -0
  833. package/build/relations/AsyncProperty.cjs.map +1 -0
  834. package/build/relations/AsyncProperty.d.cts +40 -0
  835. package/build/relations/AsyncProperty.d.cts.map +1 -0
  836. package/build/relations/AsyncProperty.d.mts +40 -0
  837. package/build/relations/AsyncProperty.d.mts.map +1 -0
  838. package/build/relations/AsyncProperty.js +61 -70
  839. package/build/relations/AsyncProperty.js.map +1 -1
  840. package/build/relations/AsyncReactiveField.cjs +110 -0
  841. package/build/relations/AsyncReactiveField.cjs.map +1 -0
  842. package/build/relations/AsyncReactiveField.d.cts +50 -0
  843. package/build/relations/AsyncReactiveField.d.cts.map +1 -0
  844. package/build/relations/AsyncReactiveField.d.mts +50 -0
  845. package/build/relations/AsyncReactiveField.d.mts.map +1 -0
  846. package/build/relations/AsyncReactiveField.js +97 -116
  847. package/build/relations/AsyncReactiveField.js.map +1 -1
  848. package/build/relations/Collection.cjs +23 -0
  849. package/build/relations/Collection.cjs.map +1 -0
  850. package/build/relations/Collection.d.cts +37 -0
  851. package/build/relations/Collection.d.cts.map +1 -0
  852. package/build/relations/Collection.d.mts +37 -0
  853. package/build/relations/Collection.d.mts.map +1 -0
  854. package/build/relations/Collection.js +14 -11
  855. package/build/relations/Collection.js.map +1 -1
  856. package/build/relations/CustomCollection.cjs +144 -0
  857. package/build/relations/CustomCollection.cjs.map +1 -0
  858. package/build/relations/CustomCollection.d.cts +74 -0
  859. package/build/relations/CustomCollection.d.cts.map +1 -0
  860. package/build/relations/CustomCollection.d.mts +74 -0
  861. package/build/relations/CustomCollection.d.mts.map +1 -0
  862. package/build/relations/CustomCollection.js +138 -162
  863. package/build/relations/CustomCollection.js.map +1 -1
  864. package/build/relations/CustomReference.cjs +142 -0
  865. package/build/relations/CustomReference.cjs.map +1 -0
  866. package/build/relations/CustomReference.d.cts +76 -0
  867. package/build/relations/CustomReference.d.cts.map +1 -0
  868. package/build/relations/CustomReference.d.mts +76 -0
  869. package/build/relations/CustomReference.d.mts.map +1 -0
  870. package/build/relations/CustomReference.js +135 -147
  871. package/build/relations/CustomReference.js.map +1 -1
  872. package/build/relations/EnumCollection.cjs +178 -0
  873. package/build/relations/EnumCollection.cjs.map +1 -0
  874. package/build/relations/EnumCollection.d.cts +86 -0
  875. package/build/relations/EnumCollection.d.cts.map +1 -0
  876. package/build/relations/EnumCollection.d.mts +86 -0
  877. package/build/relations/EnumCollection.d.mts.map +1 -0
  878. package/build/relations/EnumCollection.js +172 -207
  879. package/build/relations/EnumCollection.js.map +1 -1
  880. package/build/relations/LargeCollection.cjs +4 -0
  881. package/build/relations/LargeCollection.d.cts +22 -0
  882. package/build/relations/LargeCollection.d.cts.map +1 -0
  883. package/build/relations/LargeCollection.d.mts +22 -0
  884. package/build/relations/LargeCollection.d.mts.map +1 -0
  885. package/build/relations/LargeCollection.js +4 -3
  886. package/build/relations/LazyField.cjs +140 -0
  887. package/build/relations/LazyField.cjs.map +1 -0
  888. package/build/relations/LazyField.d.cts +51 -0
  889. package/build/relations/LazyField.d.cts.map +1 -0
  890. package/build/relations/LazyField.d.mts +51 -0
  891. package/build/relations/LazyField.d.mts.map +1 -0
  892. package/build/relations/LazyField.js +134 -0
  893. package/build/relations/LazyField.js.map +1 -0
  894. package/build/relations/ManyToManyCollection.cjs +421 -0
  895. package/build/relations/ManyToManyCollection.cjs.map +1 -0
  896. package/build/relations/ManyToManyCollection.d.cts +59 -0
  897. package/build/relations/ManyToManyCollection.d.cts.map +1 -0
  898. package/build/relations/ManyToManyCollection.d.mts +59 -0
  899. package/build/relations/ManyToManyCollection.d.mts.map +1 -0
  900. package/build/relations/ManyToManyCollection.js +411 -471
  901. package/build/relations/ManyToManyCollection.js.map +1 -1
  902. package/build/relations/ManyToManyLargeCollection.cjs +91 -0
  903. package/build/relations/ManyToManyLargeCollection.cjs.map +1 -0
  904. package/build/relations/ManyToManyLargeCollection.d.cts +34 -0
  905. package/build/relations/ManyToManyLargeCollection.d.cts.map +1 -0
  906. package/build/relations/ManyToManyLargeCollection.d.mts +34 -0
  907. package/build/relations/ManyToManyLargeCollection.d.mts.map +1 -0
  908. package/build/relations/ManyToManyLargeCollection.js +85 -118
  909. package/build/relations/ManyToManyLargeCollection.js.map +1 -1
  910. package/build/relations/ManyToOneReference.cjs +364 -0
  911. package/build/relations/ManyToOneReference.cjs.map +1 -0
  912. package/build/relations/ManyToOneReference.d.cts +121 -0
  913. package/build/relations/ManyToOneReference.d.cts.map +1 -0
  914. package/build/relations/ManyToOneReference.d.mts +121 -0
  915. package/build/relations/ManyToOneReference.d.mts.map +1 -0
  916. package/build/relations/ManyToOneReference.js +344 -411
  917. package/build/relations/ManyToOneReference.js.map +1 -1
  918. package/build/relations/OneToManyCollection.cjs +492 -0
  919. package/build/relations/OneToManyCollection.cjs.map +1 -0
  920. package/build/relations/OneToManyCollection.d.cts +69 -0
  921. package/build/relations/OneToManyCollection.d.cts.map +1 -0
  922. package/build/relations/OneToManyCollection.d.mts +69 -0
  923. package/build/relations/OneToManyCollection.d.mts.map +1 -0
  924. package/build/relations/OneToManyCollection.js +480 -579
  925. package/build/relations/OneToManyCollection.js.map +1 -1
  926. package/build/relations/OneToManyLargeCollection.cjs +85 -0
  927. package/build/relations/OneToManyLargeCollection.cjs.map +1 -0
  928. package/build/relations/OneToManyLargeCollection.d.cts +29 -0
  929. package/build/relations/OneToManyLargeCollection.d.cts.map +1 -0
  930. package/build/relations/OneToManyLargeCollection.d.mts +29 -0
  931. package/build/relations/OneToManyLargeCollection.d.mts.map +1 -0
  932. package/build/relations/OneToManyLargeCollection.js +79 -99
  933. package/build/relations/OneToManyLargeCollection.js.map +1 -1
  934. package/build/relations/OneToOneReference.cjs +209 -0
  935. package/build/relations/OneToOneReference.cjs.map +1 -0
  936. package/build/relations/OneToOneReference.d.cts +97 -0
  937. package/build/relations/OneToOneReference.d.cts.map +1 -0
  938. package/build/relations/OneToOneReference.d.mts +97 -0
  939. package/build/relations/OneToOneReference.d.mts.map +1 -0
  940. package/build/relations/OneToOneReference.js +193 -221
  941. package/build/relations/OneToOneReference.js.map +1 -1
  942. package/build/relations/PolymorphicReference.cjs +210 -0
  943. package/build/relations/PolymorphicReference.cjs.map +1 -0
  944. package/build/relations/PolymorphicReference.d.cts +93 -0
  945. package/build/relations/PolymorphicReference.d.cts.map +1 -0
  946. package/build/relations/PolymorphicReference.d.mts +93 -0
  947. package/build/relations/PolymorphicReference.d.mts.map +1 -0
  948. package/build/relations/PolymorphicReference.js +200 -237
  949. package/build/relations/PolymorphicReference.js.map +1 -1
  950. package/build/relations/PropertySymbols.cjs +7 -0
  951. package/build/relations/PropertySymbols.cjs.map +1 -0
  952. package/build/relations/PropertySymbols.d.cts +5 -0
  953. package/build/relations/PropertySymbols.d.cts.map +1 -0
  954. package/build/relations/PropertySymbols.d.mts +5 -0
  955. package/build/relations/PropertySymbols.d.mts.map +1 -0
  956. package/build/relations/PropertySymbols.js +6 -0
  957. package/build/relations/PropertySymbols.js.map +1 -0
  958. package/build/relations/ReactiveField.cjs +114 -0
  959. package/build/relations/ReactiveField.cjs.map +1 -0
  960. package/build/relations/ReactiveField.d.cts +88 -0
  961. package/build/relations/ReactiveField.d.cts.map +1 -0
  962. package/build/relations/ReactiveField.d.mts +88 -0
  963. package/build/relations/ReactiveField.d.mts.map +1 -0
  964. package/build/relations/ReactiveField.js +104 -137
  965. package/build/relations/ReactiveField.js.map +1 -1
  966. package/build/relations/ReactiveGetter.cjs +40 -0
  967. package/build/relations/ReactiveGetter.cjs.map +1 -0
  968. package/build/relations/ReactiveGetter.d.cts +33 -0
  969. package/build/relations/ReactiveGetter.d.cts.map +1 -0
  970. package/build/relations/ReactiveGetter.d.mts +33 -0
  971. package/build/relations/ReactiveGetter.d.mts.map +1 -0
  972. package/build/relations/ReactiveGetter.js +30 -31
  973. package/build/relations/ReactiveGetter.js.map +1 -1
  974. package/build/relations/ReactiveManyToMany.cjs +198 -0
  975. package/build/relations/ReactiveManyToMany.cjs.map +1 -0
  976. package/build/relations/ReactiveManyToMany.d.cts +63 -0
  977. package/build/relations/ReactiveManyToMany.d.cts.map +1 -0
  978. package/build/relations/ReactiveManyToMany.d.mts +63 -0
  979. package/build/relations/ReactiveManyToMany.d.mts.map +1 -0
  980. package/build/relations/ReactiveManyToMany.js +187 -238
  981. package/build/relations/ReactiveManyToMany.js.map +1 -1
  982. package/build/relations/ReactiveManyToManyOtherSide.cjs +148 -0
  983. package/build/relations/ReactiveManyToManyOtherSide.cjs.map +1 -0
  984. package/build/relations/ReactiveManyToManyOtherSide.d.cts +53 -0
  985. package/build/relations/ReactiveManyToManyOtherSide.d.cts.map +1 -0
  986. package/build/relations/ReactiveManyToManyOtherSide.d.mts +53 -0
  987. package/build/relations/ReactiveManyToManyOtherSide.d.mts.map +1 -0
  988. package/build/relations/ReactiveManyToManyOtherSide.js +139 -152
  989. package/build/relations/ReactiveManyToManyOtherSide.js.map +1 -1
  990. package/build/relations/ReactiveReference.cjs +336 -0
  991. package/build/relations/ReactiveReference.cjs.map +1 -0
  992. package/build/relations/ReactiveReference.d.cts +124 -0
  993. package/build/relations/ReactiveReference.d.cts.map +1 -0
  994. package/build/relations/ReactiveReference.d.mts +124 -0
  995. package/build/relations/ReactiveReference.d.mts.map +1 -0
  996. package/build/relations/ReactiveReference.js +321 -385
  997. package/build/relations/ReactiveReference.js.map +1 -1
  998. package/build/relations/ReadOnlyCollection.cjs +18 -0
  999. package/build/relations/ReadOnlyCollection.cjs.map +1 -0
  1000. package/build/relations/ReadOnlyCollection.d.cts +22 -0
  1001. package/build/relations/ReadOnlyCollection.d.cts.map +1 -0
  1002. package/build/relations/ReadOnlyCollection.d.mts +22 -0
  1003. package/build/relations/ReadOnlyCollection.d.mts.map +1 -0
  1004. package/build/relations/ReadOnlyCollection.js +9 -9
  1005. package/build/relations/ReadOnlyCollection.js.map +1 -1
  1006. package/build/relations/RecursiveCollection.cjs +386 -0
  1007. package/build/relations/RecursiveCollection.cjs.map +1 -0
  1008. package/build/relations/RecursiveCollection.d.cts +112 -0
  1009. package/build/relations/RecursiveCollection.d.cts.map +1 -0
  1010. package/build/relations/RecursiveCollection.d.mts +112 -0
  1011. package/build/relations/RecursiveCollection.d.mts.map +1 -0
  1012. package/build/relations/RecursiveCollection.js +367 -427
  1013. package/build/relations/RecursiveCollection.js.map +1 -1
  1014. package/build/relations/RecursiveCycleError.cjs +17 -0
  1015. package/build/relations/RecursiveCycleError.cjs.map +1 -0
  1016. package/build/relations/RecursiveCycleError.d.cts +15 -0
  1017. package/build/relations/RecursiveCycleError.d.cts.map +1 -0
  1018. package/build/relations/RecursiveCycleError.d.mts +15 -0
  1019. package/build/relations/RecursiveCycleError.d.mts.map +1 -0
  1020. package/build/relations/RecursiveCycleError.js +14 -13
  1021. package/build/relations/RecursiveCycleError.js.map +1 -1
  1022. package/build/relations/Reference.cjs +25 -0
  1023. package/build/relations/Reference.cjs.map +1 -0
  1024. package/build/relations/Reference.d.cts +39 -0
  1025. package/build/relations/Reference.d.cts.map +1 -0
  1026. package/build/relations/Reference.d.mts +39 -0
  1027. package/build/relations/Reference.d.mts.map +1 -0
  1028. package/build/relations/Reference.js +15 -14
  1029. package/build/relations/Reference.js.map +1 -1
  1030. package/build/relations/ReferenceSymbols.cjs +7 -0
  1031. package/build/relations/ReferenceSymbols.cjs.map +1 -0
  1032. package/build/relations/ReferenceSymbols.d.cts +5 -0
  1033. package/build/relations/ReferenceSymbols.d.cts.map +1 -0
  1034. package/build/relations/ReferenceSymbols.d.mts +5 -0
  1035. package/build/relations/ReferenceSymbols.d.mts.map +1 -0
  1036. package/build/relations/ReferenceSymbols.js +6 -0
  1037. package/build/relations/ReferenceSymbols.js.map +1 -0
  1038. package/build/relations/Relation.cjs +17 -0
  1039. package/build/relations/Relation.cjs.map +1 -0
  1040. package/build/relations/Relation.d.cts +16 -0
  1041. package/build/relations/Relation.d.cts.map +1 -0
  1042. package/build/relations/Relation.d.mts +16 -0
  1043. package/build/relations/Relation.d.mts.map +1 -0
  1044. package/build/relations/Relation.js +10 -8
  1045. package/build/relations/Relation.js.map +1 -1
  1046. package/build/relations/RelationSymbols.cjs +9 -0
  1047. package/build/relations/RelationSymbols.cjs.map +1 -0
  1048. package/build/relations/RelationSymbols.d.cts +6 -0
  1049. package/build/relations/RelationSymbols.d.cts.map +1 -0
  1050. package/build/relations/RelationSymbols.d.mts +6 -0
  1051. package/build/relations/RelationSymbols.d.mts.map +1 -0
  1052. package/build/relations/RelationSymbols.js +7 -0
  1053. package/build/relations/RelationSymbols.js.map +1 -0
  1054. package/build/relations/hasAsyncMethod.cjs +47 -0
  1055. package/build/relations/hasAsyncMethod.cjs.map +1 -0
  1056. package/build/relations/hasAsyncMethod.d.cts +29 -0
  1057. package/build/relations/hasAsyncMethod.d.cts.map +1 -0
  1058. package/build/relations/hasAsyncMethod.d.mts +29 -0
  1059. package/build/relations/hasAsyncMethod.d.mts.map +1 -0
  1060. package/build/relations/hasAsyncMethod.js +40 -43
  1061. package/build/relations/hasAsyncMethod.js.map +1 -1
  1062. package/build/relations/hasManyDerived.cjs +35 -0
  1063. package/build/relations/hasManyDerived.cjs.map +1 -0
  1064. package/build/relations/hasManyDerived.d.cts +25 -0
  1065. package/build/relations/hasManyDerived.d.cts.map +1 -0
  1066. package/build/relations/hasManyDerived.d.mts +25 -0
  1067. package/build/relations/hasManyDerived.d.mts.map +1 -0
  1068. package/build/relations/hasManyDerived.js +30 -28
  1069. package/build/relations/hasManyDerived.js.map +1 -1
  1070. package/build/relations/hasManyThrough.cjs +29 -0
  1071. package/build/relations/hasManyThrough.cjs.map +1 -0
  1072. package/build/relations/hasManyThrough.d.cts +16 -0
  1073. package/build/relations/hasManyThrough.d.cts.map +1 -0
  1074. package/build/relations/hasManyThrough.d.mts +16 -0
  1075. package/build/relations/hasManyThrough.d.mts.map +1 -0
  1076. package/build/relations/hasManyThrough.js +24 -20
  1077. package/build/relations/hasManyThrough.js.map +1 -1
  1078. package/build/relations/hasOneDerived.cjs +32 -0
  1079. package/build/relations/hasOneDerived.cjs.map +1 -0
  1080. package/build/relations/hasOneDerived.d.cts +15 -0
  1081. package/build/relations/hasOneDerived.d.cts.map +1 -0
  1082. package/build/relations/hasOneDerived.d.mts +15 -0
  1083. package/build/relations/hasOneDerived.d.mts.map +1 -0
  1084. package/build/relations/hasOneDerived.js +27 -20
  1085. package/build/relations/hasOneDerived.js.map +1 -1
  1086. package/build/relations/hasOneThrough.cjs +31 -0
  1087. package/build/relations/hasOneThrough.cjs.map +1 -0
  1088. package/build/relations/hasOneThrough.d.cts +16 -0
  1089. package/build/relations/hasOneThrough.d.cts.map +1 -0
  1090. package/build/relations/hasOneThrough.d.mts +16 -0
  1091. package/build/relations/hasOneThrough.d.mts.map +1 -0
  1092. package/build/relations/hasOneThrough.js +26 -22
  1093. package/build/relations/hasOneThrough.js.map +1 -1
  1094. package/build/relations/hasProperty.cjs +109 -0
  1095. package/build/relations/hasProperty.cjs.map +1 -0
  1096. package/build/relations/hasProperty.d.cts +53 -0
  1097. package/build/relations/hasProperty.d.cts.map +1 -0
  1098. package/build/relations/hasProperty.d.mts +53 -0
  1099. package/build/relations/hasProperty.d.mts.map +1 -0
  1100. package/build/relations/hasProperty.js +90 -95
  1101. package/build/relations/hasProperty.js.map +1 -1
  1102. package/build/relations/index.cjs +99 -0
  1103. package/build/relations/index.d.cts +32 -0
  1104. package/build/relations/index.d.mts +32 -0
  1105. package/build/relations/index.js +31 -97
  1106. package/build/relations/isCascadeDelete.cjs +11 -0
  1107. package/build/relations/isCascadeDelete.cjs.map +1 -0
  1108. package/build/relations/isCascadeDelete.d.cts +7 -0
  1109. package/build/relations/isCascadeDelete.d.cts.map +1 -0
  1110. package/build/relations/isCascadeDelete.d.mts +7 -0
  1111. package/build/relations/isCascadeDelete.d.mts.map +1 -0
  1112. package/build/relations/isCascadeDelete.js +10 -0
  1113. package/build/relations/isCascadeDelete.js.map +1 -0
  1114. package/build/resurrection.cjs +74 -0
  1115. package/build/resurrection.cjs.map +1 -0
  1116. package/build/resurrection.d.cts +13 -0
  1117. package/build/resurrection.d.cts.map +1 -0
  1118. package/build/resurrection.d.mts +13 -0
  1119. package/build/resurrection.d.mts.map +1 -0
  1120. package/build/resurrection.js +48 -69
  1121. package/build/resurrection.js.map +1 -1
  1122. package/build/rules.cjs +227 -0
  1123. package/build/rules.cjs.map +1 -0
  1124. package/build/rules.d.cts +145 -0
  1125. package/build/rules.d.cts.map +1 -0
  1126. package/build/rules.d.mts +145 -0
  1127. package/build/rules.d.mts.map +1 -0
  1128. package/build/rules.js +189 -204
  1129. package/build/rules.js.map +1 -1
  1130. package/build/runtimeConfig.cjs +25 -0
  1131. package/build/runtimeConfig.cjs.map +1 -0
  1132. package/build/runtimeConfig.d.cts +24 -0
  1133. package/build/runtimeConfig.d.cts.map +1 -0
  1134. package/build/runtimeConfig.d.mts +24 -0
  1135. package/build/runtimeConfig.d.mts.map +1 -0
  1136. package/build/runtimeConfig.js +16 -12
  1137. package/build/runtimeConfig.js.map +1 -1
  1138. package/build/serde/TypeInfo.cjs +80 -0
  1139. package/build/serde/TypeInfo.cjs.map +1 -0
  1140. package/build/serde/TypeInfo.d.cts +57 -0
  1141. package/build/serde/TypeInfo.d.cts.map +1 -0
  1142. package/build/serde/TypeInfo.d.mts +57 -0
  1143. package/build/serde/TypeInfo.d.mts.map +1 -0
  1144. package/build/serde/TypeInfo.js +78 -0
  1145. package/build/serde/TypeInfo.js.map +1 -0
  1146. package/build/serde/columns.cjs +63 -0
  1147. package/build/serde/columns.cjs.map +1 -0
  1148. package/build/serde/columns.d.cts +38 -0
  1149. package/build/serde/columns.d.cts.map +1 -0
  1150. package/build/serde/columns.d.mts +38 -0
  1151. package/build/serde/columns.d.mts.map +1 -0
  1152. package/build/serde/columns.js +62 -0
  1153. package/build/serde/columns.js.map +1 -0
  1154. package/build/serde/fieldSerde.cjs +188 -0
  1155. package/build/serde/fieldSerde.cjs.map +1 -0
  1156. package/build/serde/fieldSerde.d.cts +87 -0
  1157. package/build/serde/fieldSerde.d.cts.map +1 -0
  1158. package/build/serde/fieldSerde.d.mts +87 -0
  1159. package/build/serde/fieldSerde.d.mts.map +1 -0
  1160. package/build/serde/fieldSerde.js +182 -0
  1161. package/build/serde/fieldSerde.js.map +1 -0
  1162. package/build/serde/serde.cjs +499 -0
  1163. package/build/serde/serde.cjs.map +1 -0
  1164. package/build/serde/serde.d.cts +248 -0
  1165. package/build/serde/serde.d.cts.map +1 -0
  1166. package/build/serde/serde.d.mts +248 -0
  1167. package/build/serde/serde.d.mts.map +1 -0
  1168. package/build/serde/serde.js +485 -0
  1169. package/build/serde/serde.js.map +1 -0
  1170. package/build/serde/temporal.cjs +57 -0
  1171. package/build/serde/temporal.cjs.map +1 -0
  1172. package/build/serde/temporal.d.cts +44 -0
  1173. package/build/serde/temporal.d.cts.map +1 -0
  1174. package/build/serde/temporal.d.mts +44 -0
  1175. package/build/serde/temporal.d.mts.map +1 -0
  1176. package/build/serde/temporal.js +55 -0
  1177. package/build/serde/temporal.js.map +1 -0
  1178. package/build/serde/temporalMappers.cjs +62 -0
  1179. package/build/serde/temporalMappers.cjs.map +1 -0
  1180. package/build/serde/temporalMappers.d.cts +36 -0
  1181. package/build/serde/temporalMappers.d.cts.map +1 -0
  1182. package/build/serde/temporalMappers.d.mts +36 -0
  1183. package/build/serde/temporalMappers.d.mts.map +1 -0
  1184. package/build/serde/temporalMappers.js +58 -0
  1185. package/build/serde/temporalMappers.js.map +1 -0
  1186. package/build/trusted.cjs +16 -0
  1187. package/build/trusted.cjs.map +1 -0
  1188. package/build/trusted.d.cts +8 -0
  1189. package/build/trusted.d.cts.map +1 -0
  1190. package/build/trusted.d.mts +8 -0
  1191. package/build/trusted.d.mts.map +1 -0
  1192. package/build/trusted.js +8 -8
  1193. package/build/trusted.js.map +1 -1
  1194. package/build/typeMap.cjs +3 -0
  1195. package/build/typeMap.d.cts +88 -0
  1196. package/build/typeMap.d.cts.map +1 -0
  1197. package/build/typeMap.d.mts +88 -0
  1198. package/build/typeMap.d.mts.map +1 -0
  1199. package/build/typeMap.js +3 -3
  1200. package/build/upsert.cjs +175 -0
  1201. package/build/upsert.cjs.map +1 -0
  1202. package/build/upsert.d.cts +42 -0
  1203. package/build/upsert.d.cts.map +1 -0
  1204. package/build/upsert.d.mts +42 -0
  1205. package/build/upsert.d.mts.map +1 -0
  1206. package/build/upsert.js +159 -274
  1207. package/build/upsert.js.map +1 -1
  1208. package/build/utils.cjs +204 -0
  1209. package/build/utils.cjs.map +1 -0
  1210. package/build/utils.d.cts +65 -0
  1211. package/build/utils.d.cts.map +1 -0
  1212. package/build/utils.d.mts +65 -0
  1213. package/build/utils.d.mts.map +1 -0
  1214. package/build/utils.js +123 -192
  1215. package/build/utils.js.map +1 -1
  1216. package/package.json +34 -14
  1217. package/build/AliasAssigner.d.ts +0 -10
  1218. package/build/AliasAssigner.d.ts.map +0 -1
  1219. package/build/AliasAssigner.js +0 -39
  1220. package/build/AliasAssigner.js.map +0 -1
  1221. package/build/Aliases.d.ts +0 -117
  1222. package/build/Aliases.d.ts.map +0 -1
  1223. package/build/Aliases.js +0 -457
  1224. package/build/Aliases.js.map +0 -1
  1225. package/build/BaseEntity.d.ts +0 -68
  1226. package/build/BaseEntity.d.ts.map +0 -1
  1227. package/build/ConditionBuilder.d.ts +0 -29
  1228. package/build/ConditionBuilder.d.ts.map +0 -1
  1229. package/build/ConditionBuilder.js +0 -112
  1230. package/build/ConditionBuilder.js.map +0 -1
  1231. package/build/Entity.d.ts +0 -39
  1232. package/build/Entity.d.ts.map +0 -1
  1233. package/build/EntityFields.d.ts +0 -37
  1234. package/build/EntityFields.d.ts.map +0 -1
  1235. package/build/EntityFields.js.map +0 -1
  1236. package/build/EntityFilter.d.ts +0 -134
  1237. package/build/EntityFilter.d.ts.map +0 -1
  1238. package/build/EntityFilter.js +0 -21
  1239. package/build/EntityFilter.js.map +0 -1
  1240. package/build/EntityGraphQLFilter.d.ts +0 -56
  1241. package/build/EntityGraphQLFilter.d.ts.map +0 -1
  1242. package/build/EntityGraphQLFilter.js +0 -53
  1243. package/build/EntityGraphQLFilter.js.map +0 -1
  1244. package/build/EntityManager.d.ts +0 -740
  1245. package/build/EntityManager.d.ts.map +0 -1
  1246. package/build/EntityMetadata.d.ts +0 -233
  1247. package/build/EntityMetadata.d.ts.map +0 -1
  1248. package/build/EnumMetadata.d.ts +0 -15
  1249. package/build/EnumMetadata.d.ts.map +0 -1
  1250. package/build/EnumMetadata.js.map +0 -1
  1251. package/build/FlushLock.d.ts +0 -26
  1252. package/build/FlushLock.d.ts.map +0 -1
  1253. package/build/FlushLock.js +0 -57
  1254. package/build/FlushLock.js.map +0 -1
  1255. package/build/HintTree.d.ts +0 -42
  1256. package/build/HintTree.d.ts.map +0 -1
  1257. package/build/HintTree.js +0 -64
  1258. package/build/HintTree.js.map +0 -1
  1259. package/build/IndexManager.d.ts +0 -31
  1260. package/build/IndexManager.d.ts.map +0 -1
  1261. package/build/InstanceData.d.ts +0 -79
  1262. package/build/InstanceData.d.ts.map +0 -1
  1263. package/build/IsLoadedCache.d.ts +0 -32
  1264. package/build/IsLoadedCache.d.ts.map +0 -1
  1265. package/build/IsLoadedCache.js +0 -91
  1266. package/build/IsLoadedCache.js.map +0 -1
  1267. package/build/JoinRows.d.ts +0 -117
  1268. package/build/JoinRows.d.ts.map +0 -1
  1269. package/build/JoinRows.js +0 -320
  1270. package/build/JoinRows.js.map +0 -1
  1271. package/build/PendingChanges.d.ts +0 -26
  1272. package/build/PendingChanges.d.ts.map +0 -1
  1273. package/build/PendingChanges.js +0 -3
  1274. package/build/PendingChanges.js.map +0 -1
  1275. package/build/PluginManager.d.ts +0 -102
  1276. package/build/PluginManager.d.ts.map +0 -1
  1277. package/build/QueryParser.collectionJoins.d.ts +0 -27
  1278. package/build/QueryParser.collectionJoins.d.ts.map +0 -1
  1279. package/build/QueryParser.collectionJoins.js +0 -466
  1280. package/build/QueryParser.collectionJoins.js.map +0 -1
  1281. package/build/QueryParser.collectionJoins.test.d.ts +0 -2
  1282. package/build/QueryParser.collectionJoins.test.d.ts.map +0 -1
  1283. package/build/QueryParser.collectionJoins.test.js +0 -772
  1284. package/build/QueryParser.collectionJoins.test.js.map +0 -1
  1285. package/build/QueryParser.d.ts +0 -336
  1286. package/build/QueryParser.d.ts.map +0 -1
  1287. package/build/QueryParser.js +0 -965
  1288. package/build/QueryParser.js.map +0 -1
  1289. package/build/QueryParser.pruning.d.ts +0 -7
  1290. package/build/QueryParser.pruning.d.ts.map +0 -1
  1291. package/build/QueryParser.pruning.js +0 -195
  1292. package/build/QueryParser.pruning.js.map +0 -1
  1293. package/build/QueryParser.pruning.test.d.ts +0 -2
  1294. package/build/QueryParser.pruning.test.d.ts.map +0 -1
  1295. package/build/QueryParser.pruning.test.js +0 -106
  1296. package/build/QueryParser.pruning.test.js.map +0 -1
  1297. package/build/QueryParser.test.d.ts +0 -2
  1298. package/build/QueryParser.test.d.ts.map +0 -1
  1299. package/build/QueryParser.test.js +0 -27
  1300. package/build/QueryParser.test.js.map +0 -1
  1301. package/build/QueryVisitor.d.ts +0 -19
  1302. package/build/QueryVisitor.d.ts.map +0 -1
  1303. package/build/QueryVisitor.js +0 -106
  1304. package/build/QueryVisitor.js.map +0 -1
  1305. package/build/ReactionsManager.d.ts +0 -85
  1306. package/build/ReactionsManager.d.ts.map +0 -1
  1307. package/build/ReactionsManager.js +0 -315
  1308. package/build/ReactionsManager.js.map +0 -1
  1309. package/build/Todo.d.ts +0 -35
  1310. package/build/Todo.d.ts.map +0 -1
  1311. package/build/Todo.js +0 -73
  1312. package/build/Todo.js.map +0 -1
  1313. package/build/batchloaders/BatchLoader.d.ts +0 -14
  1314. package/build/batchloaders/BatchLoader.d.ts.map +0 -1
  1315. package/build/batchloaders/enumCollectionBatchLoader.d.ts +0 -7
  1316. package/build/batchloaders/enumCollectionBatchLoader.d.ts.map +0 -1
  1317. package/build/batchloaders/loadBatchLoader.d.ts +0 -17
  1318. package/build/batchloaders/loadBatchLoader.d.ts.map +0 -1
  1319. package/build/batchloaders/manyToManyBatchLoader.d.ts +0 -7
  1320. package/build/batchloaders/manyToManyBatchLoader.d.ts.map +0 -1
  1321. package/build/batchloaders/oneToManyBatchLoader.d.ts +0 -7
  1322. package/build/batchloaders/oneToManyBatchLoader.d.ts.map +0 -1
  1323. package/build/batchloaders/oneToOneBatchLoader.d.ts +0 -7
  1324. package/build/batchloaders/oneToOneBatchLoader.d.ts.map +0 -1
  1325. package/build/batchloaders/populateBatchLoader.d.ts +0 -13
  1326. package/build/batchloaders/populateBatchLoader.d.ts.map +0 -1
  1327. package/build/batchloaders/recursiveChildrenBatchLoader.d.ts +0 -7
  1328. package/build/batchloaders/recursiveChildrenBatchLoader.d.ts.map +0 -1
  1329. package/build/batchloaders/recursiveM2mBatchLoader.d.ts +0 -7
  1330. package/build/batchloaders/recursiveM2mBatchLoader.d.ts.map +0 -1
  1331. package/build/batchloaders/recursiveParentsBatchLoader.d.ts +0 -7
  1332. package/build/batchloaders/recursiveParentsBatchLoader.d.ts.map +0 -1
  1333. package/build/changes.d.ts +0 -92
  1334. package/build/changes.d.ts.map +0 -1
  1335. package/build/config.d.ts +0 -250
  1336. package/build/config.d.ts.map +0 -1
  1337. package/build/config.test.d.ts +0 -2
  1338. package/build/config.test.d.ts.map +0 -1
  1339. package/build/config.test.js +0 -53
  1340. package/build/config.test.js.map +0 -1
  1341. package/build/configure.d.ts +0 -15
  1342. package/build/configure.d.ts.map +0 -1
  1343. package/build/dataloaders/fastWhereFilterHash.d.ts +0 -15
  1344. package/build/dataloaders/fastWhereFilterHash.d.ts.map +0 -1
  1345. package/build/dataloaders/fastWhereFilterHash.test.d.ts +0 -2
  1346. package/build/dataloaders/fastWhereFilterHash.test.d.ts.map +0 -1
  1347. package/build/dataloaders/fastWhereFilterHash.test.js +0 -59
  1348. package/build/dataloaders/fastWhereFilterHash.test.js.map +0 -1
  1349. package/build/dataloaders/findByUniqueDataLoader.d.ts +0 -7
  1350. package/build/dataloaders/findByUniqueDataLoader.d.ts.map +0 -1
  1351. package/build/dataloaders/findCountDataLoader.d.ts +0 -16
  1352. package/build/dataloaders/findCountDataLoader.d.ts.map +0 -1
  1353. package/build/dataloaders/findDataLoader.d.ts +0 -76
  1354. package/build/dataloaders/findDataLoader.d.ts.map +0 -1
  1355. package/build/dataloaders/findIdsDataLoader.d.ts +0 -6
  1356. package/build/dataloaders/findIdsDataLoader.d.ts.map +0 -1
  1357. package/build/dataloaders/findOrCreateDataLoader.d.ts +0 -13
  1358. package/build/dataloaders/findOrCreateDataLoader.d.ts.map +0 -1
  1359. package/build/dataloaders/findPaginatedDataLoader.d.ts +0 -7
  1360. package/build/dataloaders/findPaginatedDataLoader.d.ts.map +0 -1
  1361. package/build/dataloaders/lensDataLoader.d.ts +0 -12
  1362. package/build/dataloaders/lensDataLoader.d.ts.map +0 -1
  1363. package/build/dataloaders/manyToManyFindDataLoader.d.ts +0 -8
  1364. package/build/dataloaders/manyToManyFindDataLoader.d.ts.map +0 -1
  1365. package/build/dataloaders/oneToManyFindDataLoader.d.ts +0 -8
  1366. package/build/dataloaders/oneToManyFindDataLoader.d.ts.map +0 -1
  1367. package/build/defaults.d.ts +0 -54
  1368. package/build/defaults.d.ts.map +0 -1
  1369. package/build/driverApi.d.ts +0 -19
  1370. package/build/driverApi.d.ts.map +0 -1
  1371. package/build/driverApi.js +0 -17
  1372. package/build/driverApi.js.map +0 -1
  1373. package/build/drivers/Driver.d.ts +0 -26
  1374. package/build/drivers/Driver.d.ts.map +0 -1
  1375. package/build/drivers/Driver.js.map +0 -1
  1376. package/build/drivers/EntityWriter.d.ts +0 -64
  1377. package/build/drivers/EntityWriter.d.ts.map +0 -1
  1378. package/build/drivers/IdAssigner.d.ts +0 -48
  1379. package/build/drivers/IdAssigner.d.ts.map +0 -1
  1380. package/build/drivers/buildRawQuery.d.ts +0 -22
  1381. package/build/drivers/buildRawQuery.d.ts.map +0 -1
  1382. package/build/drivers/buildRawQuery.js +0 -153
  1383. package/build/drivers/buildRawQuery.js.map +0 -1
  1384. package/build/drivers/buildUtils.d.ts +0 -9
  1385. package/build/drivers/buildUtils.d.ts.map +0 -1
  1386. package/build/drivers/buildUtils.js +0 -88
  1387. package/build/drivers/buildUtils.js.map +0 -1
  1388. package/build/drivers/index.d.ts +0 -6
  1389. package/build/drivers/index.d.ts.map +0 -1
  1390. package/build/drivers/index.js.map +0 -1
  1391. package/build/fields.d.ts +0 -26
  1392. package/build/fields.d.ts.map +0 -1
  1393. package/build/getProperties.d.ts +0 -28
  1394. package/build/getProperties.d.ts.map +0 -1
  1395. package/build/index.d.ts +0 -133
  1396. package/build/index.d.ts.map +0 -1
  1397. package/build/json.d.ts +0 -77
  1398. package/build/json.d.ts.map +0 -1
  1399. package/build/k.d.ts +0 -2
  1400. package/build/k.d.ts.map +0 -1
  1401. package/build/keys.d.ts +0 -49
  1402. package/build/keys.d.ts.map +0 -1
  1403. package/build/keywords.d.ts +0 -5
  1404. package/build/keywords.d.ts.map +0 -1
  1405. package/build/keywords.js +0 -124
  1406. package/build/keywords.js.map +0 -1
  1407. package/build/loadHints.d.ts +0 -121
  1408. package/build/loadHints.d.ts.map +0 -1
  1409. package/build/loadHints.js +0 -129
  1410. package/build/loadHints.js.map +0 -1
  1411. package/build/loadLens.d.ts +0 -77
  1412. package/build/loadLens.d.ts.map +0 -1
  1413. package/build/loadLens.js +0 -320
  1414. package/build/loadLens.js.map +0 -1
  1415. package/build/logging/FactoryLogger.d.ts +0 -24
  1416. package/build/logging/FactoryLogger.d.ts.map +0 -1
  1417. package/build/logging/FieldLogger.d.ts +0 -27
  1418. package/build/logging/FieldLogger.d.ts.map +0 -1
  1419. package/build/logging/ReactionLogger.d.ts +0 -27
  1420. package/build/logging/ReactionLogger.d.ts.map +0 -1
  1421. package/build/newEntity.d.ts +0 -45
  1422. package/build/newEntity.d.ts.map +0 -1
  1423. package/build/newTestInstance.d.ts +0 -208
  1424. package/build/newTestInstance.d.ts.map +0 -1
  1425. package/build/normalizeHints.d.ts +0 -23
  1426. package/build/normalizeHints.d.ts.map +0 -1
  1427. package/build/plugins/ImmutableEntitiesPlugin.d.ts +0 -9
  1428. package/build/plugins/ImmutableEntitiesPlugin.d.ts.map +0 -1
  1429. package/build/plugins/PreloadPlugin.d.ts +0 -69
  1430. package/build/plugins/PreloadPlugin.d.ts.map +0 -1
  1431. package/build/plugins/PreloadPlugin.js.map +0 -1
  1432. package/build/preloading/JsonAggregatePreloader.d.ts +0 -16
  1433. package/build/preloading/JsonAggregatePreloader.d.ts.map +0 -1
  1434. package/build/preloading/canPreload.d.ts +0 -3
  1435. package/build/preloading/canPreload.d.ts.map +0 -1
  1436. package/build/preloading/partitionHint.d.ts +0 -5
  1437. package/build/preloading/partitionHint.d.ts.map +0 -1
  1438. package/build/reactiveHints.d.ts +0 -146
  1439. package/build/reactiveHints.d.ts.map +0 -1
  1440. package/build/reactiveHints.js +0 -509
  1441. package/build/reactiveHints.js.map +0 -1
  1442. package/build/relations/AbstractPropertyImpl.d.ts +0 -8
  1443. package/build/relations/AbstractPropertyImpl.d.ts.map +0 -1
  1444. package/build/relations/AbstractRelationImpl.d.ts +0 -41
  1445. package/build/relations/AbstractRelationImpl.d.ts.map +0 -1
  1446. package/build/relations/AsyncProperty.d.ts +0 -36
  1447. package/build/relations/AsyncProperty.d.ts.map +0 -1
  1448. package/build/relations/AsyncReactiveField.d.ts +0 -41
  1449. package/build/relations/AsyncReactiveField.d.ts.map +0 -1
  1450. package/build/relations/Collection.d.ts +0 -33
  1451. package/build/relations/Collection.d.ts.map +0 -1
  1452. package/build/relations/CustomCollection.d.ts +0 -69
  1453. package/build/relations/CustomCollection.d.ts.map +0 -1
  1454. package/build/relations/CustomReference.d.ts +0 -71
  1455. package/build/relations/CustomReference.d.ts.map +0 -1
  1456. package/build/relations/EnumCollection.d.ts +0 -81
  1457. package/build/relations/EnumCollection.d.ts.map +0 -1
  1458. package/build/relations/LargeCollection.d.ts +0 -19
  1459. package/build/relations/LargeCollection.d.ts.map +0 -1
  1460. package/build/relations/LargeCollection.js.map +0 -1
  1461. package/build/relations/ManyToManyCollection.d.ts +0 -52
  1462. package/build/relations/ManyToManyCollection.d.ts.map +0 -1
  1463. package/build/relations/ManyToManyLargeCollection.d.ts +0 -31
  1464. package/build/relations/ManyToManyLargeCollection.d.ts.map +0 -1
  1465. package/build/relations/ManyToOneReference.d.ts +0 -117
  1466. package/build/relations/ManyToOneReference.d.ts.map +0 -1
  1467. package/build/relations/OneToManyCollection.d.ts +0 -62
  1468. package/build/relations/OneToManyCollection.d.ts.map +0 -1
  1469. package/build/relations/OneToManyLargeCollection.d.ts +0 -26
  1470. package/build/relations/OneToManyLargeCollection.d.ts.map +0 -1
  1471. package/build/relations/OneToOneReference.d.ts +0 -93
  1472. package/build/relations/OneToOneReference.d.ts.map +0 -1
  1473. package/build/relations/PolymorphicReference.d.ts +0 -89
  1474. package/build/relations/PolymorphicReference.d.ts.map +0 -1
  1475. package/build/relations/ReactiveField.d.ts +0 -85
  1476. package/build/relations/ReactiveField.d.ts.map +0 -1
  1477. package/build/relations/ReactiveGetter.d.ts +0 -30
  1478. package/build/relations/ReactiveGetter.d.ts.map +0 -1
  1479. package/build/relations/ReactiveManyToMany.d.ts +0 -57
  1480. package/build/relations/ReactiveManyToMany.d.ts.map +0 -1
  1481. package/build/relations/ReactiveManyToManyOtherSide.d.ts +0 -48
  1482. package/build/relations/ReactiveManyToManyOtherSide.d.ts.map +0 -1
  1483. package/build/relations/ReactiveReference.d.ts +0 -119
  1484. package/build/relations/ReactiveReference.d.ts.map +0 -1
  1485. package/build/relations/ReadOnlyCollection.d.ts +0 -19
  1486. package/build/relations/ReadOnlyCollection.d.ts.map +0 -1
  1487. package/build/relations/RecursiveCollection.d.ts +0 -108
  1488. package/build/relations/RecursiveCollection.d.ts.map +0 -1
  1489. package/build/relations/RecursiveCycleError.d.ts +0 -13
  1490. package/build/relations/RecursiveCycleError.d.ts.map +0 -1
  1491. package/build/relations/Reference.d.ts +0 -35
  1492. package/build/relations/Reference.d.ts.map +0 -1
  1493. package/build/relations/Relation.d.ts +0 -14
  1494. package/build/relations/Relation.d.ts.map +0 -1
  1495. package/build/relations/hasAsyncMethod.d.ts +0 -27
  1496. package/build/relations/hasAsyncMethod.d.ts.map +0 -1
  1497. package/build/relations/hasManyDerived.d.ts +0 -22
  1498. package/build/relations/hasManyDerived.d.ts.map +0 -1
  1499. package/build/relations/hasManyThrough.d.ts +0 -10
  1500. package/build/relations/hasManyThrough.d.ts.map +0 -1
  1501. package/build/relations/hasOneDerived.d.ts +0 -12
  1502. package/build/relations/hasOneDerived.d.ts.map +0 -1
  1503. package/build/relations/hasOneThrough.d.ts +0 -10
  1504. package/build/relations/hasOneThrough.d.ts.map +0 -1
  1505. package/build/relations/hasProperty.d.ts +0 -50
  1506. package/build/relations/hasProperty.d.ts.map +0 -1
  1507. package/build/relations/index.d.ts +0 -30
  1508. package/build/relations/index.d.ts.map +0 -1
  1509. package/build/relations/index.js.map +0 -1
  1510. package/build/resurrection.d.ts +0 -10
  1511. package/build/resurrection.d.ts.map +0 -1
  1512. package/build/rules.d.ts +0 -123
  1513. package/build/rules.d.ts.map +0 -1
  1514. package/build/runtimeConfig.d.ts +0 -17
  1515. package/build/runtimeConfig.d.ts.map +0 -1
  1516. package/build/scopes.d.ts +0 -185
  1517. package/build/scopes.d.ts.map +0 -1
  1518. package/build/scopes.js +0 -302
  1519. package/build/scopes.js.map +0 -1
  1520. package/build/serde.d.ts +0 -277
  1521. package/build/serde.d.ts.map +0 -1
  1522. package/build/serde.js +0 -517
  1523. package/build/serde.js.map +0 -1
  1524. package/build/temporal.d.ts +0 -46
  1525. package/build/temporal.d.ts.map +0 -1
  1526. package/build/temporal.js +0 -66
  1527. package/build/temporal.js.map +0 -1
  1528. package/build/temporalMappers.d.ts +0 -25
  1529. package/build/temporalMappers.d.ts.map +0 -1
  1530. package/build/temporalMappers.js +0 -59
  1531. package/build/temporalMappers.js.map +0 -1
  1532. package/build/trusted.d.ts +0 -5
  1533. package/build/trusted.d.ts.map +0 -1
  1534. package/build/typeMap.d.ts +0 -68
  1535. package/build/typeMap.d.ts.map +0 -1
  1536. package/build/typeMap.js.map +0 -1
  1537. package/build/unnest.d.ts +0 -13
  1538. package/build/unnest.d.ts.map +0 -1
  1539. package/build/unnest.js +0 -85
  1540. package/build/unnest.js.map +0 -1
  1541. package/build/upsert.d.ts +0 -42
  1542. package/build/upsert.d.ts.map +0 -1
  1543. package/build/utils.d.ts +0 -60
  1544. package/build/utils.d.ts.map +0 -1
  1545. package/build/withLoaded.d.ts +0 -56
  1546. package/build/withLoaded.d.ts.map +0 -1
  1547. package/build/withLoaded.js +0 -76
  1548. package/build/withLoaded.js.map +0 -1
@@ -1,2312 +1,1913 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.ReadOnlyError = exports.TooManyError = exports.NotFoundError = exports.EntityManager = void 0;
7
- exports.isId = isId;
8
- exports.getEmInternalApi = getEmInternalApi;
9
- exports.getDefaultEntityLimit = getDefaultEntityLimit;
10
- exports.setDefaultEntityLimit = setDefaultEntityLimit;
11
- exports.resetDefaultEntityLimit = resetDefaultEntityLimit;
12
- exports.isKey = isKey;
13
- exports.sameEntity = sameEntity;
14
- exports.sameReference = sameReference;
15
- exports.driverBeforeBegin = driverBeforeBegin;
16
- exports.driverAfterBegin = driverAfterBegin;
17
- exports.driverBeforeCommit = driverBeforeCommit;
18
- exports.driverAfterCommit = driverAfterCommit;
19
- exports.isDefined = isDefined;
20
- exports.setLastNow = setLastNow;
21
- exports.appendStack = appendStack;
22
- exports.createRowFromEntityData = createRowFromEntityData;
23
- const dataloader_1 = __importDefault(require("dataloader"));
24
- const BaseEntity_1 = require("./BaseEntity");
25
- const BatchLoader_1 = require("./batchloaders/BatchLoader");
26
- const defaults_1 = require("./defaults");
27
- const fields_1 = require("./fields");
28
- const IndexManager_1 = require("./IndexManager");
29
- // We alias `Entity => EntityW` to denote "Entity wide" i.e. the non-narrowed Entity
30
- const loadBatchLoader_1 = require("./batchloaders/loadBatchLoader");
31
- const populateBatchLoader_1 = require("./batchloaders/populateBatchLoader");
32
- const config_1 = require("./config");
33
- const configure_1 = require("./configure");
34
- const findByUniqueDataLoader_1 = require("./dataloaders/findByUniqueDataLoader");
35
- const findCountDataLoader_1 = require("./dataloaders/findCountDataLoader");
36
- const findDataLoader_1 = require("./dataloaders/findDataLoader");
37
- const findIdsDataLoader_1 = require("./dataloaders/findIdsDataLoader");
38
- const findOrCreateDataLoader_1 = require("./dataloaders/findOrCreateDataLoader");
39
- const findPaginatedDataLoader_1 = require("./dataloaders/findPaginatedDataLoader");
40
- const Entity_1 = require("./Entity");
41
- const FlushLock_1 = require("./FlushLock");
42
- const index_1 = require("./index");
43
- const IsLoadedCache_1 = require("./IsLoadedCache");
44
- const JoinRows_1 = require("./JoinRows");
45
- const loadHints_1 = require("./loadHints");
46
- const newEntity_1 = require("./newEntity");
47
- const newTestInstance_1 = require("./newTestInstance");
48
- const PluginManager_1 = require("./PluginManager");
49
- const ReactionsManager_1 = require("./ReactionsManager");
50
- const reactiveHints_1 = require("./reactiveHints");
51
- const relations_1 = require("./relations");
52
- const AsyncProperty_1 = require("./relations/AsyncProperty");
53
- const hasAsyncMethod_1 = require("./relations/hasAsyncMethod");
54
- const RecursiveCollection_1 = require("./relations/RecursiveCollection");
55
- const scopes_1 = require("./scopes");
56
- const Todo_1 = require("./Todo");
57
- const trusted_1 = require("./trusted");
58
- const upsert_1 = require("./upsert");
59
- const utils_1 = require("./utils");
60
- // polyfill
1
+ import { BatchLoader } from "./batchloaders/BatchLoader.js";
2
+ import "./relations/Collection.js";
3
+ import { CustomCollection } from "./relations/CustomCollection.js";
4
+ import { CustomReference } from "./relations/CustomReference.js";
5
+ import { deepNormalizeHint } from "./normalizeHints.js";
6
+ import "./batchloaders/recursiveChildrenBatchLoader.js";
7
+ import "./batchloaders/recursiveM2mBatchLoader.js";
8
+ import "./batchloaders/recursiveParentsBatchLoader.js";
9
+ import { RecursiveCycleError } from "./relations/RecursiveCycleError.js";
10
+ import "./relations/RecursiveCollection.js";
11
+ import { followReverseHint } from "./reactivity/reactiveHints.js";
12
+ import { assertLoaded, isLoadedForPopulate } from "./loading/loadHints.js";
13
+ import { AsyncMethodPopulateSecret } from "./relations/hasAsyncMethod.js";
14
+ import { AsyncPropertyImpl } from "./relations/AsyncProperty.js";
15
+ import { getField, setField } from "./fields.js";
16
+ import { keyToNumber, keyToTaggedId, tagId, toTaggedId } from "./keys.js";
17
+ import { PojoRowData } from "./RowData.js";
18
+ import { LazyFieldImpl } from "./relations/LazyField.js";
19
+ import { isLoadedReference } from "./relations/Reference.js";
20
+ import "./batchloaders/manyToManyBatchLoader.js";
21
+ import "./batchloaders/oneToManyBatchLoader.js";
22
+ import { isSelectAllFilter } from "./queries/find/scopes.js";
23
+ import { OneToManyCollection } from "./relations/OneToManyCollection.js";
24
+ import { ManyToOneReferenceImpl } from "./relations/ManyToOneReference.js";
25
+ import "./batchloaders/oneToOneBatchLoader.js";
26
+ import { ReactiveReferenceImpl } from "./relations/ReactiveReference.js";
27
+ import { OneToOneReferenceImpl } from "./relations/OneToOneReference.js";
28
+ import { PolymorphicReferenceImpl } from "./relations/PolymorphicReference.js";
29
+ import "./relations/index.js";
30
+ import { assertNever, fail, failIfAnyRejected, getOrSet, groupBy, hasAnyKey, partition, toArray } from "./utils.js";
31
+ import { newEntity } from "./newEntity.js";
32
+ import "./typeMap.js";
33
+ import { ValidationErrors } from "./rules.js";
34
+ import { getConstructorFromTag, getConstructorFromTaggedId, getMetadataForType } from "./configure.js";
35
+ import { constraintNameToValidationError } from "./config.js";
36
+ import { getBaseAndSelfMetas, getBaseMeta, getBaseSelfAndSubMetas, getMetadata } from "./EntityMetadata.js";
37
+ import { runInTrustedContext } from "./trusted.js";
38
+ import { setAsyncDefaults, setSyncDefaults } from "./defaults.js";
39
+ import "./dataloaders/lensDataLoader.js";
40
+ import { loadLens } from "./loading/loadLens.js";
41
+ import "./logging/FactoryLogger.js";
42
+ import { resetFactoryCreated } from "./newTestInstance.js";
43
+ import { mergeFindOptions } from "./queries/find/EntityFilter.js";
44
+ import { JoinRows } from "./flush/JoinRows.js";
45
+ import { PluginManager } from "./PluginManager.js";
46
+ import { optimizeCollectionJoins } from "./queries/find/QueryParser.collectionJoins.js";
47
+ import { Todo, combineJoinRows, createTodos, getTodo } from "./flush/Todo.js";
48
+ import { findDataLoader } from "./dataloaders/findDataLoader.js";
49
+ import "./drivers/index.js";
50
+ import { FieldLogger, noopFieldLogger } from "./logging/FieldLogger.js";
51
+ import { ReactionLogger } from "./logging/ReactionLogger.js";
52
+ import "./plugins/PreloadPlugin.js";
53
+ import { parseRootQuery } from "./queries/sql/query.js";
54
+ import { upsert } from "./upsert.js";
55
+ import { NoIdError, asConcreteCstr, getRelationEntries, getRelations, setOpts } from "./index.js";
56
+ import "./batchloaders/enumCollectionBatchLoader.js";
57
+ import { loadBatchLoader } from "./batchloaders/loadBatchLoader.js";
58
+ import { populateBatchLoader } from "./batchloaders/populateBatchLoader.js";
59
+ import { findByUniqueDataLoader } from "./dataloaders/findByUniqueDataLoader.js";
60
+ import { findCountDataLoader, mergeCountOptions } from "./dataloaders/findCountDataLoader.js";
61
+ import { findIdsDataLoader } from "./dataloaders/findIdsDataLoader.js";
62
+ import { entityMatches, findOrCreateDataLoader } from "./dataloaders/findOrCreateDataLoader.js";
63
+ import { findPaginatedDataLoader } from "./dataloaders/findPaginatedDataLoader.js";
64
+ import { FlushLock } from "./flush/FlushLock.js";
65
+ import { IndexManager } from "./IndexManager.js";
66
+ import { IsLoadedCache } from "./loading/IsLoadedCache.js";
67
+ import { decodeStatementResult, isMutation, parseStatement } from "./queries/sql/execute.js";
68
+ import { ReactionsManager } from "./reactivity/ReactionsManager.js";
69
+ import { isEntity } from "./Entity.js";
70
+ import { getInstanceData } from "./BaseEntity.js";
71
+ import DataLoader from "dataloader";
72
+ //#region src/EntityManager.ts
61
73
  Symbol.asyncDispose ??= Symbol("Symbol.asyncDispose");
62
74
  function isId(value) {
63
- return value && typeof value === "string";
75
+ return value && typeof value === "string";
64
76
  }
65
77
  /**
66
- * The EntityManager is the primary way nearly all code, i.e. anything that finds/creates/updates/deletes entities,
67
- * will interact with the database.
68
- *
69
- * It acts both an Identity Cache (preventing loading the same row twice into memory as separate entities, and then
70
- * having drift between the two instances) and as a Unit of Work (tracking all changes to entities and then batch
71
- * flushing only the entities that have changed).
72
- *
73
- * Note that the type parameters (C, I, and Entity) will be filled in by codegen with the values specific to your
74
- * application, so you can import your app-specific EntityManager like:
75
- *
76
- * ```ts
77
- * import { EntityManager } from "src/entities";
78
- * ```
79
- *
80
- * @param C The type of your application-specific app-wide/request-wide Context object that will be passed to hooks
81
- * @typeParam C - the application-specific context (typically the request-level context)
82
- * @typeParam Entity - the application's based entity type (i.e. with number ids or string ids)
83
- * @typeParamTX - the application's Transaction type, i.e. `Knex`
84
- */
85
- class EntityManager {
86
- ctx;
87
- driver;
88
- /** When we're flushing, the connection/transaction. */
89
- txn;
90
- entityLimit = defaultEntityLimit;
91
- #entitiesArray = [];
92
- // Incrementally track dirty entities so we don't have to scan `#entityArray` during flush
93
- #maybePendingFlushEntities = new Set();
94
- // Indexes the currently loaded entities by their tagged ids and `toTaggedString` ids (i.e. `a#`). This fixes
95
- // real-world performance issues where `findExistingInstance` scanning `#entities` was an `O(n^2)`.
96
- #entitiesById = new Map();
97
- #entitiesByTag = new Map();
98
- // Provides field-based indexing for entity types with >1000 entities to optimize findWithNewOrChanged
99
- #indexManager = new IndexManager_1.IndexManager();
100
- #isValidating = false;
101
- #pendingPercolate = new Map();
102
- #preloadedRelations = new Map();
103
- /**
104
- * Tracks cascade deletes.
105
- *
106
- * We originally used a beforeDelete lifecycle hook to implement this, but tracking this
107
- * individually allows us to a) recursively cascade deletes even during the 1st iteration
108
- * of our `flush` loop, and b) cascade deletions before we recalc fields & run user hooks,
109
- * so that both see the most accurate state.
110
- */
111
- #pendingDeletes = [];
112
- #hasAnyDeletes = false;
113
- #dataloaders = {};
114
- #batchLoaders = {};
115
- #joinRows = {};
116
- /** Stores any `source -> downstream` reactions to recalc during `em.flush`. */
117
- #rm = new ReactionsManager_1.ReactionsManager(this);
118
- /** Ensures our `em.flush` method is not interrupted. */
119
- #fl = new FlushLock_1.FlushLock();
120
- #hooks = {
121
- beforeBegin: [],
122
- afterBegin: [],
123
- beforeCommit: [],
124
- afterCommit: [],
125
- };
126
- #preloader;
127
- #fieldLogger;
128
- #isLoadedCache = new IsLoadedCache_1.IsLoadedCache();
129
- #merging;
130
- /** Track `a#1`, `a#2`, etc indexes for `em.create`-d entities. */
131
- #createCounter = undefined;
132
- __api;
133
- #isRefreshing = false;
134
- mode = "writes";
135
- constructor(ctx, driverOrOpts) {
136
- const opts = (driverOrOpts.constructor === Object ? driverOrOpts : { driver: driverOrOpts });
137
- this.ctx = ctx;
138
- this.driver = opts.driver ?? opts.em.driver;
139
- this.#preloader = opts.preloadPlugin ?? (opts.em ? opts.em.#preloader : this.driver.defaultPlugins.preloadPlugin);
140
- const pluginManager = new PluginManager_1.PluginManager(this);
141
- if (opts.em) {
142
- this.#hooks = {
143
- beforeBegin: [...opts.em.#hooks.beforeBegin],
144
- afterBegin: [...opts.em.#hooks.afterBegin],
145
- beforeCommit: [...opts.em.#hooks.beforeCommit],
146
- afterCommit: [...opts.em.#hooks.afterCommit],
147
- };
148
- opts.em.__api.pluginManager.cloneTo(pluginManager);
149
- }
150
- // Expose some of our private fields as the EntityManagerInternalApi
151
- const em = this;
152
- this.__api = {
153
- preloader: this.#preloader,
154
- pendingPercolate: this.#pendingPercolate,
155
- mutatedCollections: new Set(),
156
- pendingLoads: new Set(),
157
- hooks: this.#hooks,
158
- rm: this.#rm,
159
- indexManager: this.#indexManager,
160
- isLoadedCache: this.#isLoadedCache,
161
- pluginManager,
162
- markMaybePending(entity) {
163
- em.#maybePendingFlushEntities.add(entity);
164
- },
165
- unmarkMaybePending(entity) {
166
- em.#maybePendingFlushEntities.delete(entity);
167
- },
168
- hasAnyDeletes() {
169
- return em.#hasAnyDeletes;
170
- },
171
- pendingDeleteIds(type) {
172
- return em.#pendingDeletes
173
- .filter((entity) => entity instanceof type && entity.idMaybe !== undefined)
174
- .map((entity) => (0, index_1.keyToNumber)((0, index_1.getMetadata)(entity), entity.id));
175
- },
176
- isMerging(entity) {
177
- return em.#merging?.has(entity) ?? false;
178
- },
179
- joinRows(m2m) {
180
- return (0, utils_1.getOrSet)(em.#joinRows, m2m.joinTableName, () => new JoinRows_1.JoinRows(m2m, em.#rm));
181
- },
182
- /** Returns `a:1.books` if it's in our preload cache. */
183
- getPreloadedRelation(taggedId, fieldName) {
184
- return em.#preloadedRelations.get(taggedId)?.get(fieldName);
185
- },
186
- /** Stores `a:1.books` in our preload cache. */
187
- setPreloadedRelation(taggedId, fieldName, children) {
188
- let map = em.#preloadedRelations.get(taggedId);
189
- if (!map) {
190
- map = new Map();
191
- em.#preloadedRelations.set(taggedId, map);
192
- }
193
- map.set(fieldName, children);
194
- },
195
- get isValidating() {
196
- return em.#isValidating;
197
- },
198
- checkWritesAllowed() {
199
- if (em.mode === "read-only")
200
- throw new ReadOnlyError();
201
- return em.#fl.checkWritesAllowed();
202
- },
203
- get fieldLogger() {
204
- return em.#fieldLogger;
205
- },
206
- clearDataloaders() {
207
- em.#dataloaders = {};
208
- em.#batchLoaders = {};
209
- },
210
- clearPreloadedRelations() {
211
- em.#preloadedRelations = new Map();
212
- },
213
- setIsRefreshing(isRefreshing) {
214
- em.#isRefreshing = isRefreshing;
215
- },
216
- };
217
- }
218
- /** Returns a read-only shallow copy of the currently-loaded entities. */
219
- get entities() {
220
- return [...this.#entitiesArray];
221
- }
222
- /** Returns a list of all pending creates, updates, deletes, and m2m changes that would be flushed. */
223
- get pendingChanges() {
224
- const changes = [];
225
- for (const entity of this.#entitiesArray) {
226
- const op = (0, BaseEntity_1.getInstanceData)(entity).pendingOperation;
227
- switch (op) {
228
- case "insert":
229
- changes.push({ kind: "create", entity });
230
- break;
231
- case "update":
232
- changes.push({ kind: "update", entity });
233
- break;
234
- case "delete":
235
- changes.push({ kind: "delete", entity });
236
- break;
237
- }
238
- }
239
- for (const joinRows of Object.values(this.#joinRows)) {
240
- const todo = joinRows.toTodo();
241
- // Enum m2ms (EnumCollections) aren't entity-to-entity, so skip them here.
242
- if (todo && !todo.m2m.otherEnum) {
243
- for (const row of todo.newRows) {
244
- const entities = Object.values(row.columns);
245
- changes.push({ kind: "m2m", op: "add", joinTableName: todo.m2m.joinTableName, entities });
246
- }
247
- for (const row of todo.deletedRows) {
248
- const entities = Object.values(row.columns);
249
- changes.push({ kind: "m2m", op: "remove", joinTableName: todo.m2m.joinTableName, entities });
250
- }
251
- }
252
- }
253
- return changes;
254
- }
255
- /** Returns a read-only list of the currently-loaded entities of `type`. */
256
- getEntities(type) {
257
- const meta = (0, index_1.getMetadata)(type);
258
- const entities = this.#entitiesByTag.get(meta.tagName) ?? [];
259
- // If we're a subtype, `entities` might have base/other subtypes
260
- return (meta.baseType ? entities.filter((e) => e instanceof type) : entities);
261
- }
262
- getEntity(id) {
263
- // Skip this both for performance + we allow toTaggedString-style `a#1` ids
264
- // assertIdIsTagged(id);
265
- return this.#entitiesById.get(id);
266
- }
267
- async find(type, where, options) {
268
- const { populate, ...rest } = options || {};
269
- const normalized = (0, index_1.mergeFindOptions)(where, rest);
270
- const settings = { where: normalized.where, ...normalized.options };
271
- const result = await (hasPaginationSettings(normalized.options)
272
- ? (0, findPaginatedDataLoader_1.findPaginatedDataLoader)(this, type, settings, populate)
273
- : (0, findDataLoader_1.findDataLoader)(this, type, settings, populate)).catch(function find(err) {
274
- throw appendStack(err, new Error());
275
- });
276
- if (populate) {
277
- await this.populate(result, populate);
278
- }
279
- return result;
280
- }
281
- /** Runs the post-parse find pipeline: plugins mutate the logical AST, then Joist optimizes/prunes before SQL. */
282
- async executeFind(meta, operation, parsed, settings) {
283
- const { checkLimit, findSettings } = this.prepareFind(meta, operation, parsed, settings);
284
- return this.executePreparedFind(meta, operation, parsed, findSettings, checkLimit);
285
- }
286
- /** Executes a query that has already had find hooks and optimizations applied. */
287
- async executePreparedFind(meta, operation, parsed, findSettings, checkLimit) {
288
- const { pluginManager } = getEmInternalApi(this);
289
- const rows = await this.driver.executeFind(this, parsed, findSettings);
290
- // Check by default unless explicitly disabled or the caller removed the LIMIT via `limit: undefined`
291
- const shouldCheck = checkLimit ?? !("limit" in findSettings && findSettings.limit === undefined);
292
- if (shouldCheck && rows.length >= this.entityLimit) {
293
- throw new Error(`Query returned more than ${this.entityLimit} entityLimit rows`);
294
- }
295
- pluginManager.afterFind(meta, operation, rows);
296
- return rows;
297
- }
298
- /**
299
- * Runs pre-SQL find hooks and optimizations against a parsed query.
300
- *
301
- * This allows plugins to see "pre-batched" / "logical" query ASTs, instead of our
302
- * more complicated `_find` batched queries. The flow would be:
303
- *
304
- * - A loader calls `prepareFind(originalQuery)`
305
- * - Plugins inspect/modify the query as/if needed
306
- * - The loader crafts a new, more complicated query that embeds the originalQuery
307
- * - The loader calls `executePreparedFind` with the 2nd query
308
- */
309
- prepareFind(meta, operation, parsed, settings) {
310
- const { checkLimit, ...findSettings } = settings;
311
- const { pluginManager } = getEmInternalApi(this);
312
- // Plugins may mutate the settings object, so return the post-hook version that loaders must reuse.
313
- pluginManager.beforeFind(meta, operation, parsed, findSettings);
314
- (0, index_1.optimizeCollectionJoins)(parsed, settings);
315
- return { checkLimit, findSettings };
316
- }
317
- async findGql(type, where, options) {
318
- if (!options) {
319
- return this.find(type, where);
320
- }
321
- const normalized = { ...options };
322
- if ("limit" in normalized)
323
- normalized.limit = normalized.limit ?? undefined;
324
- if ("offset" in normalized)
325
- normalized.offset = normalized.offset ?? undefined;
326
- return this.find(type, where, normalized);
327
- }
328
- async findOne(type, where, options) {
329
- const list = await this.find(type, where, options);
330
- if (list.length === 0) {
331
- return undefined;
332
- }
333
- else if (list.length === 1) {
334
- return list[0];
335
- }
336
- else {
337
- throw new TooManyError(`Found more than one: ${list.map((e) => e.toString()).join(", ")}`);
338
- }
339
- }
340
- async findOneOrFail(type, where, options) {
341
- const list = await this.find(type, where, options);
342
- if (list.length === 0) {
343
- throw new NotFoundError(`Did not find ${type.name} for given query`);
344
- }
345
- else if (list.length > 1) {
346
- throw new TooManyError(`Found more than one: ${list.map((e) => e.toString()).join(", ")}`);
347
- }
348
- return list[0];
349
- }
350
- async findByUnique(type, where, options = {}) {
351
- const { populate, softDeletes = "exclude" } = options;
352
- const entries = Object.entries(where);
353
- if (entries.length !== 1) {
354
- throw new Error("findByUnique only accepts a single field");
355
- }
356
- const [fieldName, value] = entries[0];
357
- const field = (0, index_1.getMetadata)(type).allFields[fieldName];
358
- const row = await (0, findByUniqueDataLoader_1.findByUniqueDataLoader)(this, type, field, softDeletes)
359
- .load(value)
360
- .catch(function findByUnique(err) {
361
- throw appendStack(err, new Error());
362
- });
363
- if (!row) {
364
- return undefined;
365
- }
366
- else {
367
- const [entity] = this.hydrate(type, [row]);
368
- if (this.#hasAnyDeletes && entity.isDeletedEntity) {
369
- return undefined;
370
- }
371
- if (populate) {
372
- await this.populate(entity, populate);
373
- }
374
- return entity;
375
- }
376
- }
377
- /**
378
- * Returns the count of entities that match the `where` clause.
379
- *
380
- * The `where` clause, and any options.conditions, matches the same syntax
381
- * as `em.find`.
382
- *
383
- * Note: this method is not currently auto-batched, so it will cause N+1s if called in a loop.
384
- */
385
- async findCount(type, where, options = {}) {
386
- const normalized = (0, findCountDataLoader_1.mergeCountOptions)(where, options);
387
- const settings = { where: normalized.where, ...normalized.options };
388
- let count = await (0, findCountDataLoader_1.findCountDataLoader)(this, type, settings).catch(function findCount(err) {
389
- throw appendStack(err, new Error());
390
- });
391
- // If the user is do "count all", we can adjust the number up/down based on
392
- // WIP creates/deletes. We can't do this if the WHERE clause is populated b/c
393
- // then we'd also have to eval each created/deleted entity against the WHERE
394
- // clause before knowing if it should adjust teh amount.
395
- const isSelectAll = (0, scopes_1.isSelectAllFilter)(where, options.conditions);
396
- if (isSelectAll) {
397
- const tagged = this.#entitiesByTag.get((0, index_1.getMetadata)(type).tagName) ?? [];
398
- for (const entity of tagged) {
399
- // Still do an `instanceof` to handle subtypes
400
- if (entity instanceof type) {
401
- if (entity.isNewEntity) {
402
- count++;
403
- }
404
- else if (entity.isDeletedEntity) {
405
- count--;
406
- }
407
- }
408
- }
409
- }
410
- return count;
411
- }
412
- /**
413
- * Returns the IDs of entities that match the `where` clause.
414
- *
415
- * The `where` clause, and any options.conditions, matches the same syntax
416
- * as `em.find`.
417
- */
418
- async findIds(type, where, options = {}) {
419
- const normalized = (0, findCountDataLoader_1.mergeCountOptions)(where, options);
420
- const settings = { where: normalized.where, ...normalized.options };
421
- return (0, findIdsDataLoader_1.findIdsDataLoader)(this, type, settings).catch(function findIds(err) {
422
- throw appendStack(err, new Error());
423
- });
424
- }
425
- async findWithNewOrChanged(type, where, options) {
426
- const { softDeletes = "exclude", populate } = options ?? {};
427
- // Make a copy of `where` because `em.find` will re-write new entities to `-1`, that our `entityMatches` could still match
428
- // ...and also prune `undefined` here, since `em.find` will do it anyway, but `entityMatches` does not.
429
- const copy = Object.fromEntries(Object.entries(where).filter(([, v]) => v !== undefined));
430
- const persisted = await this.find(type, copy, { softDeletes });
431
- const unchanged = persisted.filter((e) => !e.isNewEntity && !e.isDirtyEntity && !e.isDeletedEntity);
432
- const maybeNew = this.filterEntities(type, where).filter((e) => (e.isNewEntity || e.isDirtyEntity) && !e.isDeletedEntity);
433
- const found = [...unchanged, ...maybeNew];
434
- if (populate) {
435
- await this.populate(found, populate);
436
- }
437
- return found;
438
- }
439
- async findOrCreate(type, where, ifNew, upsert, options) {
440
- const { softDeletes = "exclude", populate } = options ?? {};
441
- const entity = await (0, findOrCreateDataLoader_1.findOrCreateDataLoader)(this, type, where, softDeletes)
442
- .load({ ifNew: ifNew, upsert })
443
- .catch(function findOrCreate(err) {
444
- throw appendStack(err, new Error());
445
- });
446
- if (populate) {
447
- await this.populate(entity, populate);
448
- }
449
- return entity;
450
- }
451
- /** Creates a new `type` and marks it as loaded, i.e. we know its collections are all safe to access in memory. */
452
- create(type, opts) {
453
- return this.#doCreate(type, opts, false);
454
- }
455
- /**
456
- * Creates a new `type` but with `opts` that are nullable, to accept partial-update-style input.
457
- *
458
- * Note that `createPartial` doesn't support the full upsert behavior, i.e. this method:
459
- *
460
- * - always creates,
461
- * - does not support relation markers like `op`, `delete`, and `remove`,
462
- * - does not accept deep input, but
463
- * - fields set to `undefined` will be skipped instead of unset
464
- *
465
- * See `upsert` for the upsert/deep upsert behavior.
466
- */
467
- createPartial(type, opts) {
468
- return this.#doCreate(type, opts, true);
469
- }
470
- /**
471
- * Create or updates `type` based on partial-update-style `input`.
472
- *
473
- * This supports upsert behavior, i.e.:
474
- *
475
- * - findOrCreate the primary entity being updated (based on the `id` key being provided),
476
- * - upsert relation markers like `op`, `delete`, and `remove` are supported,
477
- * - deep input is supported, i.e. `{ firstName: "Bob", books: [{ title: "b1" } ] }`, and
478
- * - fields set to `undefined` will be skipped instead of unset
479
- */
480
- upsert(type, input) {
481
- return (0, upsert_1.upsert)(this, type, input);
482
- }
483
- async clone(entityOrArray, opts) {
484
- const { deep = {}, skipIf, skip = {}, postClone } = opts ?? {};
485
- // Keep a list that we can work against synchronously after doing the async find/crawl
486
- const todo = new Set();
487
- const skipMap = new WeakMap();
488
- // 1. Find all entities w/o mutating them yet
489
- await crawl(todo, skipMap, Array.isArray(entityOrArray) ? entityOrArray : [entityOrArray], deep, {
490
- skipIf: skipIf,
491
- skip,
492
- });
493
- // 2. Clone each found entity
494
- const clones = [...todo].map((entity) => {
495
- const skip = skipMap.get(entity) ?? [];
496
- // Use meta.fields to see which fields are derived (i.e. createdAt, updatedAt, initials)
497
- // that only have getters, and so we shouldn't set (createdAt/updatedAt will be initialized
498
- // by `em.register`).
499
- const meta = (0, index_1.getMetadata)(entity);
500
- const copy = Object.fromEntries(Object.values(meta.allFields)
501
- .map((f) => {
502
- if (skip.includes(f.fieldName))
503
- return undefined;
504
- switch (f.kind) {
505
- case "primitive":
506
- if (!f.derived && !f.protected) {
507
- return [f.fieldName, (0, fields_1.getField)(entity, f.fieldName)];
508
- }
509
- else {
510
- return undefined;
511
- }
512
- case "m2o":
513
- case "enum":
514
- if (f.derived) {
515
- return undefined;
516
- }
517
- else {
518
- return [f.fieldName, (0, fields_1.getField)(entity, f.fieldName)];
519
- }
520
- case "poly":
521
- return [f.fieldName, (0, fields_1.getField)(entity, f.fieldName)];
522
- case "primaryKey":
523
- case "o2m":
524
- case "m2m":
525
- case "m2mEnum":
526
- case "o2o":
527
- case "lo2m":
528
- return undefined;
529
- default:
530
- (0, utils_1.assertNever)(f);
531
- }
532
- })
533
- .filter(isDefined));
534
- // Call `new` just like the user would do
535
- // The `asConcreteCstr` is safe b/c we got meta from a concrete/already-instantiated entity
536
- const clone = this.create((0, index_1.asConcreteCstr)(meta.cstr), copy);
537
- return [entity, clone];
538
- });
539
- const entityToClone = new Map(clones);
540
- // 3. Now mutate the m2o relations. We focus on only m2o's because they "own" the field/column,
541
- // and will drive percolation to keep the other-side o2m & o2o updated.
542
- clones.forEach(([, clone]) => {
543
- (0, index_1.getRelationEntries)(clone).forEach(([fieldName, value]) => {
544
- if (value instanceof relations_1.ManyToOneReferenceImpl ||
545
- value instanceof index_1.PolymorphicReferenceImpl ||
546
- value instanceof relations_1.ReactiveReferenceImpl) {
547
- // What's the existing entity? Have we cloned it?
548
- const existingIdOrEntity = (0, fields_1.getField)(clone, fieldName);
549
- // Use O(1) lookup via #entitiesById Map instead of O(N) .find() scan
550
- const existing = (0, Entity_1.isEntity)(existingIdOrEntity) ? existingIdOrEntity : this.getEntity(existingIdOrEntity);
551
- // If we didn't find a loaded entity for this value, assume that it a) itself is not being cloned,
552
- // and b) we don't need to bother telling it about the newly cloned entity
553
- if (existing) {
554
- clone[fieldName].set(entityToClone.get(existing) ?? existing);
555
- }
556
- }
557
- });
558
- });
559
- if (postClone) {
560
- await Promise.all(clones.map(([original, clone]) => postClone(original, clone)));
561
- }
562
- return Array.isArray(entityOrArray)
563
- ? entityOrArray
564
- .filter((original) => entityToClone.has(original))
565
- .map((original) => entityToClone.get(original))
566
- : clones[0]
567
- ? clones[0][1]
568
- : (0, utils_1.fail)("no entities were cloned given the provided options");
569
- }
570
- /**
571
- * Merges multiple source entities into a target entity by updating all references that point
572
- * to the source entities to instead point to the target entity.
573
- *
574
- * This method loads all relations from the source entities, updates any entity that
575
- * references a source entity to reference the target entity instead, and then automatically
576
- * deletes the source entities.
577
- *
578
- * @param target - The entity that will become the target of all merged references
579
- * @param sources - Array of entities whose references will be redirected to the target
580
- * @param opts - Options to control merge behavior
581
- * @param autoDelete - Whether to automatically delete source entities (default: true)
582
- * @returns Promise that resolves when all references have been updated and sources deleted
583
- *
584
- * @example
585
- * // Merge duplicate authors - all books pointing to author2 will now point to author1
586
- * // author2 will be automatically deleted
587
- * await em.merge(author1, [author2]);
588
- *
589
- * @example
590
- * // Merge multiple duplicate publishers into one
591
- * // publisher2 and publisher3 will be automatically deleted
592
- * await em.merge(publisher1, [publisher2, publisher3]);
593
- *
594
- * @example
595
- * // Merge without auto-deleting sources (for custom cleanup logic)
596
- * await em.merge(author1, [author2], { autoDelete: false });
597
- * // Custom logic here...
598
- * em.delete(author2);
599
- */
600
- async merge(target, sources, opts) {
601
- const autoDelete = opts?.autoDelete ?? true;
602
- if (sources.length === 0)
603
- return [];
604
- this.#merging ??= new Set();
605
- // Allow cannotBeUpdated to see that anyone pointed to the new target is allowed to change
606
- this.#merging.add(target);
607
- // Make sure source and target are the same type (Before we call `populate` below which will fail on invalid load hints)
608
- const targetMeta = (0, index_1.getMetadata)(target);
609
- for (const source of sources) {
610
- const sourceMeta = (0, index_1.getMetadata)(source);
611
- if (sourceMeta.type !== targetMeta.type) {
612
- throw new Error(`Cannot merge entities of different types: ${targetMeta.type} and ${sourceMeta.type}`);
613
- }
614
- }
615
- const fields = Object.values(targetMeta.allFields)
616
- .filter((field) => ["o2m", "m2o", "m2m", "o2o"].includes(field.kind))
617
- .map((field) => field.fieldName);
618
- await this.populate(sources, fields);
619
- const changedEntities = [];
620
- for (const source of sources) {
621
- // Find all reverse relations (things that point to this entity)
622
- for (const field of Object.values(targetMeta.allFields)) {
623
- const { kind } = field;
624
- if (kind === "o2m") {
625
- for (const other of source[field.fieldName].get) {
626
- this.#merging.add(other); // Tell ReactionsManager to react to normally-read-only fields
627
- other[field.otherFieldName].set(target);
628
- changedEntities.push(other);
629
- }
630
- }
631
- else if (kind === "o2o") {
632
- const otherField = field.otherMetadata().allFields[field.otherFieldName];
633
- if (otherField.kind === "m2o" && otherField.derived)
634
- continue;
635
- const other = source[field.fieldName].get;
636
- if (other) {
637
- this.#merging.add(other); // Tell ReactionsManager to react to normally-read-only fields
638
- other[field.otherFieldName].set(target);
639
- changedEntities.push(other);
640
- }
641
- }
642
- else if (kind === "m2m") {
643
- for (const other of source[field.fieldName].get) {
644
- this.#merging.add(other); // Tell ReactionsManager to react to normally-read-only fields
645
- const collection = other[field.otherFieldName];
646
- collection.remove(source);
647
- collection.add(target);
648
- changedEntities.push(other);
649
- }
650
- }
651
- else if (kind === "primitive" ||
652
- kind === "primaryKey" ||
653
- kind === "enum" ||
654
- kind === "m2mEnum" ||
655
- kind === "poly" ||
656
- kind === "m2o" ||
657
- kind === "lo2m") {
658
- // These field types don't need merge handling - they're either:
659
- // - primitive values that don't create references (primitive, enum)
660
- // - primary keys that shouldn't be merged
661
- // - forward references that we handle from the reverse side (m2o)
662
- // - large collections that are handled separately (lo2m)
663
- }
664
- else {
665
- (0, utils_1.assertNever)(kind);
666
- }
667
- }
668
- }
669
- // Auto-delete source entities if requested
670
- if (autoDelete) {
671
- for (const source of sources)
672
- this.delete(source);
673
- }
674
- return changedEntities;
675
- }
676
- async load(typeOrId, id, hint) {
677
- // Handle the `typeOrId` overload
678
- let type;
679
- if (typeof typeOrId === "string") {
680
- // This must be a tagged id for the 1st overload to work
681
- type = (0, index_1.getConstructorFromTaggedId)(typeOrId);
682
- id = typeOrId;
683
- }
684
- else {
685
- type = typeOrId;
686
- id = id || (0, utils_1.fail)(`Invalid ${typeOrId.name} id: ${id}`);
687
- }
688
- const meta = (0, index_1.getMetadata)(type);
689
- const taggedId = (0, index_1.toTaggedId)(meta, id);
690
- let entity = this.findExistingInstance(taggedId);
691
- if (!entity) {
692
- await (0, loadBatchLoader_1.loadBatchLoader)(this, meta)
693
- .load({ taggedId, hint })
694
- .catch(function load(err) {
695
- throw appendStack(err, new Error());
696
- });
697
- entity = this.findExistingInstance(taggedId);
698
- }
699
- if (!entity) {
700
- throw new NotFoundError(`${taggedId} was not found`);
701
- }
702
- if (hint) {
703
- await this.populate(entity, hint);
704
- }
705
- if (meta.inheritanceType === "sti" && !(entity instanceof type)) {
706
- throw new Error(`${entity} is ${entity.constructor.name} but should be ${type.name}`);
707
- }
708
- return entity;
709
- }
710
- async loadAll(type, _ids, hint) {
711
- const meta = (0, index_1.getMetadata)(type);
712
- // Use pre-allocated arrays/for loops instead of `.filter`s since this can be a hot spot
713
- const ids = new Array(_ids.length);
714
- const entities = new Array(_ids.length);
715
- let idsToLoad;
716
- let positionsToLoad;
717
- for (let i = 0; i < _ids.length; i++) {
718
- const id = (0, index_1.tagId)(meta, _ids[i]);
719
- ids[i] = id;
720
- const entity = this.findExistingInstance(id);
721
- if (entity) {
722
- entities[i] = entity;
723
- }
724
- else {
725
- (idsToLoad ??= []).push(id);
726
- (positionsToLoad ??= []).push(i);
727
- }
728
- }
729
- if (idsToLoad && idsToLoad.length > 0) {
730
- await (0, loadBatchLoader_1.loadBatchLoader)(this, meta)
731
- .loadAll(idsToLoad.map((id) => ({ taggedId: id, hint })))
732
- .catch(function loadAll(err) {
733
- throw appendStack(err, new Error());
734
- });
735
- for (const i of positionsToLoad) {
736
- entities[i] = this.findExistingInstance(ids[i]);
737
- }
738
- }
739
- let idsNotFound;
740
- for (let i = 0; i < entities.length; i++) {
741
- if (entities[i] === undefined) {
742
- (idsNotFound ??= []).push(ids[i]);
743
- }
744
- }
745
- if (idsNotFound) {
746
- throw new NotFoundError(`${idsNotFound.join(",")} were not found`);
747
- }
748
- const loadedEntities = entities;
749
- if (hint) {
750
- await this.populate(loadedEntities, hint);
751
- }
752
- if (meta.inheritanceType === "sti" && meta.baseType) {
753
- const wrongType = loadedEntities.filter((e) => !(e instanceof meta.cstr));
754
- if (wrongType.length > 0) {
755
- throw new Error(`${wrongType.join(", ")} were not of type ${meta.cstr.name}`);
756
- }
757
- }
758
- return loadedEntities;
759
- }
760
- async loadAllIfExists(type, _ids, hint) {
761
- const meta = (0, index_1.getMetadata)(type);
762
- // Use pre-allocated arrays/for loops instead of `.filter`s since this can be a hot spot
763
- const ids = new Array(_ids.length);
764
- const entities = [];
765
- let idsToLoad;
766
- // Ensure the ids are tagged, and find any not-yet-loaded
767
- for (let i = 0; i < _ids.length; i++) {
768
- const id = (0, index_1.tagId)(meta, _ids[i]);
769
- ids[i] = id;
770
- const entity = this.findExistingInstance(id);
771
- if (entity) {
772
- entities.push(entity);
773
- }
774
- else {
775
- (idsToLoad ??= []).push(id);
776
- }
777
- }
778
- if (idsToLoad && idsToLoad.length > 0) {
779
- await (0, loadBatchLoader_1.loadBatchLoader)(this, meta)
780
- .loadAll(idsToLoad.map((id) => ({ taggedId: id, hint })))
781
- .catch(function loadAllIfExists(err) {
782
- throw appendStack(err, new Error());
783
- });
784
- // Now that everything is loaded, recalc `entities`
785
- entities.length = 0;
786
- for (const id of ids) {
787
- const entity = this.findExistingInstance(id);
788
- if (entity)
789
- entities.push(entity);
790
- }
791
- }
792
- if (hint) {
793
- await this.populate(entities, hint);
794
- }
795
- return entities;
796
- }
797
- async loadLens(entities, fn, populate) {
798
- const result = await (0, index_1.loadLens)(entities, fn);
799
- if (populate) {
800
- await this.populate(result, populate);
801
- }
802
- return result;
803
- }
804
- loadFromQuery(type, rows, populate) {
805
- if (Array.isArray(rows)) {
806
- const entities = this.hydrate(type, rows);
807
- if (populate)
808
- return this.populate(entities, populate);
809
- return entities;
810
- }
811
- else {
812
- return rows.then((rows) => {
813
- const entities = this.hydrate(type, rows);
814
- if (populate)
815
- return this.populate(entities, populate);
816
- return entities;
817
- });
818
- }
819
- }
820
- async loadFromRows(type, rows, populate) {
821
- const entities = this.hydrate(type, rows);
822
- if (populate) {
823
- await this.populate(entities, populate);
824
- }
825
- return entities;
826
- }
827
- async populate(entityOrList, hintOrOpts, fn) {
828
- const { hint: hintOpt, ...opts } = typeof hintOrOpts === "object" && "hint" in hintOrOpts ? hintOrOpts : { hint: hintOrOpts };
829
- // Tell `AsyncMethodImpl.load` to not invoke its function
830
- opts[hasAsyncMethod_1.AsyncMethodPopulateSecret] = true;
831
- // I'm tempted to throw an error here, because at least internal callers should ideally pre-check
832
- // that `list > 0` and `Object.keys(hint).length > 0` before calling `populate`, just as an optimization.
833
- // But since it's a public API, we should just early exit.
834
- const list = (0, utils_1.toArray)(entityOrList).filter((e) => {
835
- // Check `isDeletedAndFlushed` so that pending-delete entities are still populated,
836
- // because their hooks might do `getWithDeleted` calls and expect them to be loaded.
837
- return e !== undefined && !(0, BaseEntity_1.getInstanceData)(e).isDeletedAndFlushed;
838
- });
839
- if (list.length === 0) {
840
- return !fn ? entityOrList : fn(entityOrList);
841
- }
842
- // Avoid building a HintTree/batchloader for persisted entities when everything is already loaded; in the phase 9
843
- // benchmark this moved already-loaded populates from ~1.10ms to ~0.89ms, and nested already-loaded populates from
844
- // ~2.39ms to ~1.94ms.
845
- if (!opts.forceReload && list.every((entity) => !entity.isNewEntity && (0, loadHints_1.isLoadedForPopulate)(entity, hintOpt))) {
846
- return fn ? fn(entityOrList) : entityOrList;
847
- }
848
- const meta = (0, index_1.getMetadata)(list[0]);
849
- if (this.#preloader) {
850
- // If we can preload, prevent promise deadlocking by one large-batch preload populate (which can't have
851
- // intra dependencies), then a 2nd small-batch non-preload populate.
852
- const [preload, non] = this.#preloader.partitionHint(meta, hintOpt);
853
- if (preload) {
854
- const loader = (0, populateBatchLoader_1.populateBatchLoader)(this, meta, preload, "preload", opts);
855
- await loader.loadAll(list.map((entity) => ({ entity, hint: preload }))).catch(function populate(err) {
856
- throw appendStack(err, new Error());
857
- });
858
- }
859
- if (non) {
860
- const loader = (0, populateBatchLoader_1.populateBatchLoader)(this, meta, non, "intermixed", opts);
861
- await loader.loadAll(list.map((entity) => ({ entity, hint: non }))).catch(function populate(err) {
862
- throw appendStack(err, new Error());
863
- });
864
- }
865
- }
866
- else {
867
- const loader = (0, populateBatchLoader_1.populateBatchLoader)(this, meta, hintOpt, "intermixed", opts);
868
- await loader.loadAll(list.map((entity) => ({ entity, hint: hintOpt }))).catch(function populate(err) {
869
- throw appendStack(err, new Error());
870
- });
871
- }
872
- return fn ? fn(entityOrList) : entityOrList;
873
- }
874
- // For debugging EntityManager.populate.test.ts's "can be huge"
875
- // populates: Record<string, number> = {};
876
- /**
877
- * Executes `fn` with a transaction, and automatically calls `flush`/`commit` at the end.
878
- *
879
- * This ensures both any `.find` and `.flush` operations happen within the same
880
- * transaction, which is useful for enforcing cross-table/application-level invariants that
881
- * cannot be enforced with database-level constraints.
882
- */
883
- async transaction(fn) {
884
- return this.driver.transaction(this, async (txn) => {
885
- const result = await fn(txn);
886
- // The lambda may have done some interstitial flushes (that would not
887
- // have committed the transaction), but go ahead and do a final one
888
- // in case they didn't explicitly call flush.
889
- await this.flush();
890
- return result;
891
- });
892
- }
893
- delete(entityOrArray) {
894
- for (const entity of (0, utils_1.toArray)(entityOrArray)) {
895
- // Early return if already deleted.
896
- const alreadyMarked = (0, BaseEntity_1.getInstanceData)(entity).markDeleted();
897
- if (!alreadyMarked)
898
- continue;
899
- // This monotonic flag lets find hot paths skip scanning results until a delete has ever happened in this EM.
900
- this.#hasAnyDeletes = true;
901
- // Any derived fields that read this entity will need recalc-d
902
- this.#rm.queueAllDownstreamFields(entity, "deleted");
903
- // Synchronously unhook the entity if the relations are loaded
904
- getCascadeDeleteRelations(entity).forEach((r) => r.maybeCascadeDelete());
905
- // And queue the cascade deletes
906
- this.#pendingDeletes.push(entity);
907
- }
908
- }
909
- async assignNewIds() {
910
- let pendingEntities = this.entities.filter((e) => e.isNewEntity && !e.isDeletedEntity && !e.idTaggedMaybe);
911
- await this.getLoader("assign-new-ids", "global", async (entities) => {
912
- let todos = (0, Todo_1.createTodos)(entities);
913
- await this.driver.assignNewIds(this, todos);
914
- for (const e of entities)
915
- this.#entitiesById.set(e.idTagged, e);
916
- return entities;
917
- })
918
- .loadMany(pendingEntities)
919
- .catch(function assignNewIds(err) {
920
- throw appendStack(err, new Error());
921
- });
922
- }
923
- /**
924
- * Immediately assigns async defaults to `entities`.
925
- *
926
- * Normally async defaults wait until `em.flush` to run, because their async nature requires
927
- * an `await` / `Promise` to be evaluated, and `em.create` is synchronous.
928
- *
929
- * This `assignDefaults` methods like you move that up, and immediately invoke
930
- * any default logic against the `entities`.
931
- */
932
- async setDefaults(entities) {
933
- return (0, trusted_1.runInTrustedContext)(async () => {
934
- const suppressedTypeErrors = [];
935
- const entitiesByType = (0, utils_1.groupBy)(entities.filter((e) => e.isNewEntity), (e) => (0, index_1.getMetadata)(e));
936
- await (0, defaults_1.setAsyncDefaults)(suppressedTypeErrors, this.ctx, entitiesByType);
937
- });
938
- }
939
- /**
940
- * Flushes the SQL for any changed entities to the database.
941
- *
942
- * If this is run outside of an existing transaction, it will `BEGIN` and `COMMIT`
943
- * a new transaction on every `.flush()` call so that all of the `INSERT`s/etc.
944
- * happen atomically.
945
- *
946
- * If this is run within an existing transaction, i.e. `EntityManager.transaction`,
947
- * then it will only issue `INSERT`s/etc. and defer to the caller to `COMMIT`
948
- * the transaction.
949
- *
950
- * It returns entities that have changed (an entity is considered changed if it has been deleted, inserted, or updated)
951
- */
952
- async flush(flushOptions = {}) {
953
- return (0, trusted_1.runInTrustedContext)(() => this.#flush(flushOptions));
954
- }
955
- async #flush(flushOptions = {}) {
956
- if (this.mode === "read-only")
957
- throw new ReadOnlyError();
958
- const { skipValidation = false } = flushOptions;
959
- this.#fl.startLock();
960
- const allFlushedEntities = new Set();
961
- try {
962
- await this.#fl.allowWrites(async () => {
963
- // Cascade deletes now that we're async (i.e. to keep `em.delete` synchronous).
964
- // Also do this before calling `recalcPendingReactables` to avoid recalculating
965
- // fields on entities that will be deleted (and probably have unset/invalid FKs
966
- // that would NPE their logic anyway).
967
- await this.flushDeletes();
968
- // Recalc before we run hooks, so the hooks will see the latest calculated values.
969
- await this.#rm.recalcPendingReactables("reactables");
970
- });
971
- const createdThenDeleted = new Set();
972
- // We'll only invoke hooks once/entity (the 1st time that entity goes through runHooksOnPendingEntities)
973
- const hooksInvoked = new Set();
974
- // Make sure two AsyncReactiveFields don't ping-pong each other forever
975
- let hookLoops = 0;
976
- let now = getNow();
977
- const suppressedDefaultTypeErrors = [];
978
- // Make a lambda that we can invoke multiple times, if we loop for AsyncReactiveFields
979
- const runHooksOnPendingEntities = async () => {
980
- if (hookLoops++ >= 10)
981
- throw new Error("runHooksOnPendingEntities has ran 10 iterations, aborting");
982
- // Resolve any pending o2m/m2m sets (set() called before load — need to load from DB to diff)
983
- const pendingLoads = [...getEmInternalApi(this).pendingLoads];
984
- if (pendingLoads.length > 0) {
985
- getEmInternalApi(this).pendingLoads.clear();
986
- await Promise.all(pendingLoads.map((collection) => collection.load()));
987
- }
988
- // Any dirty entities we find, even if we skipped firing their hooks on this loop
989
- const pendingFlush = new Set();
990
- // Subset of pendingFlush entities that we will run hooks on
991
- const pendingHooks = new Set();
992
- // Subset of pendingFlush entities that had hooks invoked in a prior `runHooksOnPendingEntities`
993
- const alreadyRanHooks = new Set();
994
- findPendingFlushEntities(this.#maybePendingFlushEntities, hooksInvoked, pendingFlush, pendingHooks, alreadyRanHooks);
995
- // If we're re-looping for AsyncReactiveField, make sure to bump updatedAt
996
- // each time, so that for an INSERT-then-UPDATE the triggers don't think the
997
- // UPDATE forgot to self-bump updatedAt, and then "helpfully" bump it for us.
998
- if (alreadyRanHooks.size > 0) {
999
- maybeBumpUpdatedAt(this.#rm, (0, Todo_1.createTodos)([...alreadyRanHooks]), now);
1000
- }
1001
- // Run hooks in a series of loops until things "settle down"
1002
- while (pendingHooks.size > 0) {
1003
- await this.#fl.allowWrites(async () => {
1004
- let todos = (0, Todo_1.createTodos)([...pendingHooks]);
1005
- await (0, defaults_1.setAsyncDefaults)(suppressedDefaultTypeErrors, this.ctx, Todo_1.Todo.groupInsertsByTypeAndSubType(todos));
1006
- maybeBumpUpdatedAt(this.#rm, todos, now);
1007
- // Run our hooks
1008
- for (const group of maybeSetupHookOrdering(todos)) {
1009
- await beforeCreate(this.ctx, group);
1010
- await beforeUpdate(this.ctx, group);
1011
- await beforeFlush(this.ctx, group);
1012
- }
1013
- // Call `setField` just to get the column marked as dirty if needed.
1014
- // This can come after the hooks, b/c if the hooks read any of these
1015
- // fields, they'd be via the synchronous getter and would not be stale.
1016
- recalcSynchronousDerivedFields(todos);
1017
- // The hooks could have deleted this-loop or prior-loop entities, so re-cascade again.
1018
- // Reactions (the recalc below) can themselves `em.delete` entities, so keep draining
1019
- // until both deletes and recalcs have settled.
1020
- do {
1021
- await this.flushDeletes();
1022
- // The hooks could have changed fields, so recalc again.
1023
- await this.#rm.recalcPendingReactables("reactables");
1024
- } while (this.#pendingDeletes.length > 0);
1025
- // We may have reactables that failed earlier, but will succeed now that hooks have been run and cascade
1026
- // deletes have been processed
1027
- if (this.#rm.hasPendingTypeErrors) {
1028
- await this.#rm.recalcPendingTypeErrors();
1029
- // We need to re-run reactables again if we dirtied something while retrying type errors
1030
- if (this.#rm.needsRecalc("reactables"))
1031
- await this.#rm.recalcPendingReactables("reactables");
1032
- }
1033
- for (const e of pendingHooks)
1034
- hooksInvoked.add(e);
1035
- pendingHooks.clear();
1036
- // See if the hooks mutated any new, not-yet-hooksInvoked entities
1037
- findPendingFlushEntities(this.#maybePendingFlushEntities, hooksInvoked, pendingFlush, pendingHooks, alreadyRanHooks);
1038
- // The final run of recalcPendingReactables could have left us with pending type errors and no entities in
1039
- // pendingHooks. If so, we need to re-run recalcPendingTypeErrors to get those errors to transition into
1040
- // suppressed errors so that we will fail after simpleValidation.
1041
- if (pendingHooks.size === 0 && this.#rm.hasPendingTypeErrors)
1042
- await this.#rm.recalcPendingTypeErrors();
1043
- });
1044
- }
1045
- // We might have invoked hooks that immediately deleted a new entity (weird but allowed);
1046
- // if so, filter it out so that we don't flush it, but keep track for later fixing up
1047
- // it's `#orm.deleted` field.
1048
- return [...pendingFlush].filter((e) => {
1049
- const createThenDelete = e.isDeletedEntity && e.isNewEntity;
1050
- if (createThenDelete)
1051
- createdThenDeleted.add(e);
1052
- return !createThenDelete;
1053
- });
1054
- };
1055
- const { pluginManager } = getEmInternalApi(this);
1056
- const runValidation = async (entityTodos, joinRowTodos, validate) => {
1057
- const changedEntities = entitiesFromTodos(entityTodos, joinRowTodos);
1058
- try {
1059
- this.#isValidating = true;
1060
- await pluginManager.beforeValidate(changedEntities);
1061
- if (validate) {
1062
- // Run simple rules first b/c it includes not-null/required rules, so that then when we run
1063
- // `validateReactiveRules` next, the app's lambdas won't see fundamentally invalid entities & NPE.
1064
- await validateSimpleRules(entityTodos);
1065
- // After we've let any "author is not set" simple rules fail before prematurely throwing
1066
- // the "of course that caused an NPE" `TypeError`s, if all the authors *were* valid/set,
1067
- // and we still have TypeErrors (from derived valeus), they were real, unrelated errors
1068
- // that the user should see.
1069
- if (suppressedDefaultTypeErrors.length > 0)
1070
- throw suppressedDefaultTypeErrors[0];
1071
- await validateReactiveRules(this, this.#rm.logger, entityTodos, joinRowTodos);
1072
- await afterValidation(this.ctx, entityTodos);
1073
- }
1074
- await pluginManager.afterValidate(changedEntities);
1075
- }
1076
- finally {
1077
- this.#isValidating = false;
1078
- }
1079
- };
1080
- // Run hooks (in iterative loops if hooks mutate new entities) on pending entities
1081
- let entitiesToFlush = await runHooksOnPendingEntities();
1082
- for (const e of entitiesToFlush)
1083
- allFlushedEntities.add(e);
1084
- // Recreate todos now that we've run hooks and recalculated fields so know
1085
- // the full set of entities that will be INSERT/UPDATE/DELETE-d in the database.
1086
- let entityTodos = (0, Todo_1.createTodos)(entitiesToFlush);
1087
- let joinRowTodos = (0, Todo_1.combineJoinRows)(this.#joinRows);
1088
- await runValidation(entityTodos, joinRowTodos, !skipValidation);
1089
- this.#rm.throwIfAnySuppressedTypeErrors();
1090
- if (suppressedDefaultTypeErrors.length > 0)
1091
- throw suppressedDefaultTypeErrors[0];
1092
- if (Object.keys(entityTodos).length > 0 || Object.keys(joinRowTodos).length > 0) {
1093
- // The driver will handle the right thing if we're already in an existing transaction.
1094
- await this.driver.transaction(this, async () => {
1095
- do {
1096
- if (Object.keys(entityTodos).length > 0 || Object.keys(joinRowTodos).length > 0) {
1097
- await this.driver.flush(this, entityTodos, joinRowTodos);
1098
- }
1099
- // Now that we've flushed, we can let plugins know what we've done.
1100
- pluginManager.afterWrite(entityTodos, joinRowTodos);
1101
- // And we can look for ReactiveQueries that need to be recalculated
1102
- if (this.#rm.hasPendingReactiveQueries()) {
1103
- // Reset all flushed entities to we only flush net-new changes
1104
- for (const e of entitiesToFlush) {
1105
- if (e.isNewEntity && !e.isDeletedEntity)
1106
- this.#entitiesById.set(e.idTagged, e);
1107
- (0, BaseEntity_1.getInstanceData)(e).resetForRqfLoop();
1108
- }
1109
- // Actually do the recalc
1110
- await this.#fl.allowWrites(async () => {
1111
- await this.#rm.recalcPendingReactables("reactiveQueries");
1112
- // If any ReactiveFields depended on AsyncReactiveFields, go ahead and calc those now
1113
- await this.#rm.recalcPendingReactables("reactables");
1114
- });
1115
- // Advance `now` so that our triggers don't think our UPDATEs are forgetting to self-bump
1116
- // updated_at, and bump it themselves, which could cause a subsequent error.
1117
- now = getNow();
1118
- // See if any RQFs actually changed any entities. If they did, run the hooks on them.
1119
- entitiesToFlush = await runHooksOnPendingEntities();
1120
- for (const e of entitiesToFlush)
1121
- allFlushedEntities.add(e);
1122
- // Recreate `entityTodos` against the only-the-just-changed entities
1123
- entityTodos = (0, Todo_1.createTodos)(entitiesToFlush);
1124
- joinRowTodos = (0, Todo_1.combineJoinRows)(this.#joinRows);
1125
- await runValidation(entityTodos, joinRowTodos, true);
1126
- this.#rm.throwIfAnySuppressedTypeErrors();
1127
- }
1128
- else {
1129
- // Exit the loop
1130
- entityTodos = {};
1131
- }
1132
- } while (Object.keys(entityTodos).length > 0);
1133
- // Run `beforeCommit once right before COMMIT
1134
- await beforeCommit(this.ctx, allFlushedEntities);
1135
- if (this.mode === "in-memory-writes") {
1136
- throw new InMemoryRollbackError();
1137
- }
1138
- });
1139
- // TODO: This is really "after flush" if we're being called from a transaction that
1140
- // is going to make multiple `em.flush()` calls?
1141
- await afterCommit(this.ctx, allFlushedEntities);
1142
- // Update the `#orm` field to reflect the new state
1143
- for (const e of allFlushedEntities) {
1144
- if (e.isNewEntity && !e.isDeletedEntity)
1145
- this.#entitiesById.set(e.idTagged, e);
1146
- (0, BaseEntity_1.getInstanceData)(e).resetAfterFlushed();
1147
- // Reset AsyncQueryProperties since DB state may have changed
1148
- for (const rel of Object.values((0, BaseEntity_1.getInstanceData)(e).relations)) {
1149
- if (rel instanceof AsyncProperty_1.AsyncPropertyImpl)
1150
- rel.resetAfterFlush();
1151
- }
1152
- }
1153
- // Update the joinRows refs to reflect the new state
1154
- for (const joinRow of Object.values(joinRowTodos)) {
1155
- joinRow.resetAfterFlushed();
1156
- }
1157
- const { mutatedCollections } = getEmInternalApi(this);
1158
- for (const o2m of mutatedCollections.values()) {
1159
- o2m.resetAddedRemoved();
1160
- }
1161
- mutatedCollections.clear();
1162
- // Reset the find/preload caches b/c data will have changed in the db
1163
- this.#dataloaders = {};
1164
- this.#batchLoaders = {};
1165
- this.#preloadedRelations = new Map();
1166
- this.#rm.clear();
1167
- }
1168
- // Fixup the `deleted` field on entities that were created then immediately deleted
1169
- for (const e of createdThenDeleted)
1170
- (0, BaseEntity_1.getInstanceData)(e).fixupCreatedThenDeleted();
1171
- this.#merging?.clear();
1172
- return [...allFlushedEntities].sort((a, b) => (0, BaseEntity_1.getInstanceData)(a).entityIndex - (0, BaseEntity_1.getInstanceData)(b).entityIndex);
1173
- }
1174
- catch (e) {
1175
- if (e instanceof RecursiveCollection_1.RecursiveCycleError) {
1176
- const entity = e.entities[0];
1177
- // Look up a custom cycle message — check both the exact field name and its opposite
1178
- // direction, since the cycle may be detected from either side (e.g. walking
1179
- // childrenRecursive during reactive hint reversal when parentsRecursive was configured).
1180
- for (const meta of (0, index_1.getBaseAndSelfMetas)((0, index_1.getMetadata)(entity))) {
1181
- const messageFn = meta.config.__data.cycleMessages[e.fieldName] ??
1182
- meta.config.__data.cycleMessages[entity[e.fieldName]?.otherFieldName];
1183
- if (messageFn) {
1184
- throw new index_1.ValidationErrors([{ entity, message: messageFn(entity, e.entities) }]);
1185
- }
1186
- }
1187
- }
1188
- if (e && typeof e === "object" && "constraint" in e && typeof e.constraint === "string") {
1189
- // node-pg errors use `constraint` to indicate the constraint name
1190
- const message = config_1.constraintNameToValidationError[e.constraint];
1191
- if (message) {
1192
- throw new index_1.ValidationErrors(message);
1193
- }
1194
- }
1195
- if (e instanceof InMemoryRollbackError) {
1196
- return [...allFlushedEntities].sort((a, b) => (0, BaseEntity_1.getInstanceData)(a).entityIndex - (0, BaseEntity_1.getInstanceData)(b).entityIndex);
1197
- }
1198
- throw e;
1199
- }
1200
- finally {
1201
- this.#rm.clearSuppressedTypeErrors();
1202
- this.#fl.releaseLock();
1203
- (0, newTestInstance_1.resetFactoryCreated)();
1204
- }
1205
- }
1206
- /**
1207
- * A very simple toJSON.
1208
- *
1209
- * This is not really meant to be useful, it's to prevent huge/circular output if
1210
- * an EntityManager accidentally ends up getting logged to something like pino that
1211
- * over-zealous toJSONs anything it touches.
1212
- */
1213
- toJSON() {
1214
- return `<EntityManager ${this.entities.length}>`;
1215
- }
1216
- async refresh(param) {
1217
- this.#isRefreshing = true;
1218
- this.#dataloaders = {};
1219
- this.#batchLoaders = {};
1220
- this.#preloadedRelations = new Map();
1221
- const deepLoad = param && "deepLoad" in param && param.deepLoad;
1222
- let todo = param === undefined
1223
- ? this.#entitiesArray
1224
- : Array.isArray(param)
1225
- ? param
1226
- : (0, Entity_1.isEntity)(param)
1227
- ? [param]
1228
- : this.#entitiesArray;
1229
- const done = new Set();
1230
- while (todo.length > 0) {
1231
- const copy = [...todo];
1232
- copy.forEach((e) => done.add(e));
1233
- todo = [];
1234
- // For any non-deleted entity with an id, get its latest data + relations from the database
1235
- const entitiesToRefresh = copy.filter((e) => e.idTaggedMaybe && !e.isDeletedEntity);
1236
- await Promise.all(entitiesToRefresh.map((entity) => {
1237
- // Pass loaded/all relation names as a hint so the preloader can inject JOINs
1238
- const hint = (0, index_1.getRelationEntries)(entity)
1239
- .filter(([_, r]) => deepLoad || r.isLoaded)
1240
- .map(([k]) => k);
1241
- return (0, loadBatchLoader_1.loadBatchLoader)(this, (0, index_1.getMetadata)(entity), true)
1242
- .load({ taggedId: entity.idTagged, hint })
1243
- .catch(function refresh(err) {
1244
- throw appendStack(err, new Error());
1245
- });
1246
- }));
1247
- // Then refresh any loaded relations (the loadBatchLoader only hydrates the entity
1248
- // data, it doesn't get each relation into a loaded state.)
1249
- const [custom, builtin] = (0, utils_1.partition)(entitiesToRefresh
1250
- .filter((e) => !(0, BaseEntity_1.getInstanceData)(e).isDeletedEntity)
1251
- .flatMap((entity) => (0, index_1.getRelations)(entity).filter((r) => deepLoad || r.isLoaded)), isCustomRelation);
1252
- // Call `.load` on builtin relations first, because if we hit an already-loaded custom relation
1253
- // first, it will call `.get` internally, and might access built-in relations that we've not had a
1254
- // chance to `.load()` yet.
1255
- await Promise.all(builtin.map((r) => {
1256
- // If the relation is already loaded, we need to go through .load({ forceReload }), otherwise
1257
- // use preload to avoid the promise.
1258
- if (r.isPreloaded && !r.isLoaded) {
1259
- r.preload();
1260
- return undefined;
1261
- }
1262
- else {
1263
- return r.load({ forceReload: true });
1264
- }
1265
- }));
1266
- await Promise.all(custom.map((r) => r.load({ forceReload: true })));
1267
- // If deep loading, get all entity/entities in the relation and push them on the list
1268
- if (deepLoad) {
1269
- todo.push(
1270
- // We skip recursing into CustomCollections and CustomReferences and PersistedAsyncReferencesImpl for two reasons:
1271
- // 1. It can be tricky to ensure `{ forceReload: true }` is passed all the way through their custom load
1272
- // implementations, and so it's easy to have `.get` accidentally come across a not-yet-loaded collection, and
1273
- // 2. Any custom load functions should use the underlying o2m/m2o/etc relations anyway, so if we crawl/refresh
1274
- // those, then when the user calls `.get` on custom collections/references, they should be talking to always-loaded
1275
- // relations, w/o us having to tackle the tricky bookkeeping problem passing `forceReload` all through their
1276
- // custom load function + any other collections they call.
1277
- ...builtin
1278
- .filter((r) => "get" in r)
1279
- .map((r) => r.get)
1280
- .flatMap((value) => (Array.isArray(value) ? value : [value]))
1281
- .filter((value) => (0, Entity_1.isEntity)(value) && !done.has(value)));
1282
- }
1283
- }
1284
- this.#isRefreshing = false;
1285
- }
1286
- get numberOfEntities() {
1287
- return this.entities.length;
1288
- }
1289
- // Handles our Unit of Work-style look up / deduplication of entity instances.
1290
- // Currently only public for the driver impls
1291
- findExistingInstance(id) {
1292
- return this.#entitiesById.get(id);
1293
- }
1294
- /**
1295
- * Takes a result `row` from a custom query and maps the db values into a new-or-existing domain object for that row.
1296
- *
1297
- * The `overwriteExisting` controls whether `row`'s values should overwrite the existing fields on
1298
- * an entity. By default this is true, as we assume the user calling this means they know the DB has
1299
- * updated values that should be put into the entities. A few internal callers set this to false,
1300
- * i.e. when we're loading collections and have db results that are potentially stale compared to
1301
- * the WIP entity state.
1302
- */
1303
- hydrate(type, rows, options) {
1304
- const maybeBaseMeta = (0, index_1.getMetadata)(type);
1305
- const taggedIdPrefix = `${maybeBaseMeta.tagName}:`;
1306
- const overwriteExisting = options?.overwriteExisting === true;
1307
- let i = 0;
1308
- const entities = new Array(rows.length);
1309
- for (const row of rows) {
1310
- const id = row["id"];
1311
- const taggedId = id === undefined || id === null ? (0, utils_1.fail)("No id column was available") : `${taggedIdPrefix}${id}`;
1312
- // See if this is already in our UoW
1313
- let entity = this.findExistingInstance(taggedId);
1314
- if (!entity) {
1315
- // Look for __class from the driver telling us which subtype to instantiate
1316
- const meta = findConcreteMeta(maybeBaseMeta, row);
1317
- // Pass id as a hint that we're in hydrate mode
1318
- entity = (0, newEntity_1.newEntity)(this, (0, index_1.asConcreteCstr)(meta.cstr), false);
1319
- (0, BaseEntity_1.getInstanceData)(entity).row = row;
1320
- this.#doRegister(entity, taggedId, meta, true);
1321
- }
1322
- else if (overwriteExisting) {
1323
- // Usually if the entity already exists, we don't write over it, but in this case we assume that
1324
- // `EntityManager.refresh` is telling us to explicitly load the latest data.
1325
- // First swap out the old row with the new row
1326
- const instanceData = (0, BaseEntity_1.getInstanceData)(entity);
1327
- instanceData.row = row;
1328
- // And then only refresh the data keys that have already been serde-d from rows
1329
- // (this keeps us from deserializing data out of rows that we don't need).
1330
- const { data } = instanceData;
1331
- const dataKeys = Object.keys(data);
1332
- if (dataKeys.length > 0) {
1333
- const allFields = (0, index_1.getMetadata)(entity).allFields;
1334
- const changedFields = entity.changes.fieldsWithoutRelations;
1335
- if (changedFields.length === 0) {
1336
- for (const fieldName of dataKeys) {
1337
- const serde = allFields[fieldName].serde ?? (0, utils_1.fail)(`Missing serde for ${fieldName}`);
1338
- serde.setOnEntity(data, row);
1339
- }
1340
- }
1341
- else {
1342
- for (const fieldName of dataKeys) {
1343
- const serde = allFields[fieldName].serde ?? (0, utils_1.fail)(`Missing serde for ${fieldName}`);
1344
- serde.setOnEntity(data, row);
1345
- // Make the field look not-dirty
1346
- if (changedFields.includes(fieldName)) {
1347
- instanceData.markFieldClean(fieldName);
1348
- }
1349
- }
1350
- }
1351
- }
1352
- }
1353
- entities[i++] = entity;
1354
- }
1355
- return entities;
1356
- }
1357
- touch(entityOrEntities) {
1358
- for (const entity of (0, utils_1.toArray)(entityOrEntities)) {
1359
- (0, BaseEntity_1.getInstanceData)(entity).markTouched();
1360
- }
1361
- }
1362
- async recalc(entityOrEntities) {
1363
- // Look for async reactive fields
1364
- const relations = (0, utils_1.toArray)(entityOrEntities).flatMap((entity) => Object.values((0, index_1.getMetadata)(entity).allFields)
1365
- .filter((f) => "derived" in f && f.derived === "async")
1366
- .map((field) => entity[field.fieldName]));
1367
- // Use forceReload: true to tell ReactiveReferences to recalc against their full graph
1368
- await Promise.all(relations.map((r) => r.load({ forceReload: true })));
1369
- // And also sync reactive fields
1370
- (0, utils_1.toArray)(entityOrEntities).flatMap((entity) => Object.values((0, index_1.getMetadata)(entity).allFields)
1371
- .filter((f) => "derived" in f && f.derived === "sync")
1372
- .forEach((field) => {
1373
- // This will be a noop if the value is the same
1374
- (0, fields_1.setField)(entity, field.fieldName, entity[field.fieldName]);
1375
- }));
1376
- // `.load()` recalculated the immediate relations, go ahead and recalc any downstream reactables.
1377
- // We'll still defer AsyncReactiveFields to the em.flush loop.
1378
- await this.#rm.recalcPendingReactables("reactables");
1379
- }
1380
- beforeBegin(fn) {
1381
- this.#hooks.beforeBegin.push(fn);
1382
- }
1383
- afterBegin(fn) {
1384
- this.#hooks.afterBegin.push(fn);
1385
- }
1386
- beforeCommit(fn) {
1387
- this.#hooks.beforeCommit.push(fn);
1388
- }
1389
- afterCommit(fn) {
1390
- this.#hooks.afterCommit.push(fn);
1391
- }
1392
- /**
1393
- * Returns an EntityManager-scoped (i.e. request scoped) data loader.
1394
- *
1395
- * @param operation the operation being batched, i.e. `load` or `o2m-load`, to avoid clashing batch keys
1396
- * across fundamentally different operations
1397
- * @param batchKey for a given operation, i.e. `load`, a batch key `Author` to batch all Author loads together
1398
- * @param fn the batch load function, i.e. that will accept all `.load(...)`-d Author ids to load as a single db call
1399
- * @param opts optional DataLoader options
1400
- * @returns a DataLoader scoped to the `operation` + `batchKey` combination
1401
- */
1402
- getLoader(operation, batchKey, fn, opts) {
1403
- // If we wanted to, if not in a transaction, we could potentially do lookups against a global cache,
1404
- // to achieve cross-request batching. Granted we'd need all DataLoaders to have caching disabled, see:
1405
- // https://github.com/joist-orm/joist-orm/issues/629
1406
- const loadersForKind = (this.#dataloaders[operation] ??= {});
1407
- return (0, utils_1.getOrSet)(loadersForKind, batchKey, () => new dataloader_1.default(fn, opts));
1408
- }
1409
- /**
1410
- * Like `getLoader`, but returns a `BatchLoader` where all callers in the same tick
1411
- * share a single `Promise<void>` instead of getting per-key promises.
1412
- *
1413
- * The batch function should write results via side channels (e.g. `setPreloadedRelation`).
1414
- */
1415
- getBatchLoader(operation, batchKey, fn) {
1416
- const loadersForKind = (this.#batchLoaders[operation] ??= {});
1417
- return (0, utils_1.getOrSet)(loadersForKind, batchKey, () => new BatchLoader_1.BatchLoader(fn));
1418
- }
1419
- toString() {
1420
- return "EntityManager";
1421
- }
1422
- /** Recursively cascades any pending deletions. */
1423
- async flushDeletes() {
1424
- let entities = this.#pendingDeletes;
1425
- if (entities.length === 0)
1426
- return;
1427
- this.#pendingDeletes = [];
1428
- let relationsToCleanup = [];
1429
- // Loop if our deletes cascade to other deletes
1430
- while (entities.length > 0) {
1431
- // For cascade delete relations, cascade the delete...
1432
- const p = entities.flatMap(getCascadeDeleteRelations).map((r) => r.load().then(() => r.maybeCascadeDelete()));
1433
- await Promise.all(p);
1434
- // Run the beforeDelete hook before we unhook the entity
1435
- const todos = (0, Todo_1.createTodos)(entities);
1436
- await beforeDelete(this.ctx, todos);
1437
- // For all relations, unhook the entity from the other side; this append path is optimized for
1438
- // large deletes with ~100k relations by avoiding `flatMap` intermediates and `concat` copies.
1439
- for (const entity of entities) {
1440
- const relations = (0, index_1.getRelations)(entity);
1441
- const start = relationsToCleanup.length;
1442
- relationsToCleanup.length += relations.length;
1443
- for (let i = 0; i < relations.length; i++) {
1444
- relationsToCleanup[start + i] = relations[i];
1445
- }
1446
- }
1447
- entities = this.#pendingDeletes;
1448
- this.#pendingDeletes = [];
1449
- }
1450
- // For all relations, unhook the entity from the other side
1451
- await Promise.all(relationsToCleanup.map((r) => r.cleanupOnEntityDeleted()));
1452
- }
1453
- setReactionLogging(arg) {
1454
- this.#rm.setLogger(typeof arg === "boolean" ? (arg ? new index_1.ReactionLogger() : undefined) : arg);
1455
- }
1456
- setFieldLogging(arg) {
1457
- if (arg instanceof index_1.FieldLogger) {
1458
- this.#fieldLogger = arg;
1459
- return;
1460
- }
1461
- const writeFn = getDefaultWriteFn(this.ctx);
1462
- if (typeof arg === "boolean") {
1463
- this.#fieldLogger = arg ? new index_1.FieldLogger([], writeFn) : undefined;
1464
- }
1465
- else if (typeof arg === "string" || Array.isArray(arg)) {
1466
- const specs = Array.isArray(arg) ? arg : [arg];
1467
- const watching = specs.map((spec) => {
1468
- // Regex to match Author.firstName,lastName! pattern
1469
- const regex = /^([^.!]+)(?:\.([^!]*))?(!)?$/;
1470
- const [_, entity, fields, breakpoint] = spec.match(regex) ?? (0, utils_1.fail)(`Unsupported spec ${spec}`);
1471
- const fieldNames = fields?.split(",");
1472
- // Ensure entity is valid, to avoid failing silently
1473
- const meta = (0, configure_1.getMetadataForType)(entity);
1474
- // Ensure the field names are valid, to avoid failing silently
1475
- fieldNames?.forEach((field) => {
1476
- // We could probably check the `kind`, b/c things like o2o/o2m are not supported atm
1477
- if (!meta.allFields[field]) {
1478
- throw new Error(`Field ${field} not found on ${entity}`);
1479
- }
1480
- });
1481
- return { entity, fieldNames, breakpoint: !!breakpoint };
1482
- });
1483
- this.#fieldLogger = new index_1.FieldLogger(watching, writeFn);
1484
- }
1485
- else {
1486
- throw new Error("Unsupported override for setFieldLogging");
1487
- }
1488
- }
1489
- async [Symbol.asyncDispose]() {
1490
- await this.flush();
1491
- }
1492
- /** Returns entities matching the filter using indexed search when available. */
1493
- filterEntities(cstr, where) {
1494
- const meta = (0, index_1.getMetadata)(cstr);
1495
- const entities = this.#entitiesByTag.get(meta.tagName) ?? [];
1496
- // Don't bother filtering if there's no where clause (particularly b/c IndexManager.findMatching
1497
- // really expects there to be at least 1 condition)
1498
- if (Object.entries(where).length === 0) {
1499
- return entities.filter((e) => e instanceof cstr && !e.isDeletedEntity);
1500
- }
1501
- if (this.#indexManager.shouldIndexType(entities.length)) {
1502
- this.#indexManager.enableIndexingForType(meta, entities, where);
1503
- return (this.#indexManager
1504
- .findMatching(meta, entities, where)
1505
- // Still filter by `instanceof cstr` to handle subtyping
1506
- .filter((e) => e instanceof cstr && !e.isDeletedEntity));
1507
- }
1508
- else {
1509
- return entities
1510
- // Still filter by `instanceof cstr` to handle subtyping
1511
- .filter((e) => e instanceof cstr && !e.isDeletedEntity && (0, findOrCreateDataLoader_1.entityMatches)(e, where));
1512
- }
1513
- }
1514
- /**
1515
- * Creates a new EntityManager that shares the same entities as the current one but allows independent changes.
1516
- *
1517
- * This is useful for scenarios where you want to:
1518
- *
1519
- * - Preload data for use as a cache
1520
- * - Make speculative changes that may or may not be committed
1521
- * - Escape a transaction scope
1522
- *
1523
- * The fork will:
1524
- *
1525
- * - Copy all currently loaded entities to the new EntityManager
1526
- * - Copy any loaded relation data to keep `.isLoaded` / `.get` state consistent
1527
- * - Copy and update references to the EntityManager and its entities in the context, which is itself shallowly copied
1528
- *
1529
- * The fork will NOT:
1530
- *
1531
- * - Copy any pending changes (must call .flush() first)
1532
- * - Share any changes made in either EntityManager with the other
1533
- *
1534
- * @param opts options to control the fork behavior
1535
- * - allowPendingChanges - allows the em being forked to have pending changes and forces the resulting em to have
1536
- * `mode` set to "in-memory-writes". Changes to entities in the original em will be copied to the resulting em.
1537
- * Optional. default: false
1538
- *
1539
- * @throws {Error} If called on an EntityManager with pending changes
1540
- * @returns A new EntityManager with copied entity state
1541
- */
1542
- fork(opts = {}) {
1543
- const { allowPendingChanges = false } = opts;
1544
- const oldEm = this;
1545
- // copy the context so that it's distinct between the two ems, and so we can update any references from the old em
1546
- // to the new one later
1547
- const ctx = { ...oldEm.ctx };
1548
- const newEm = new EntityManager(ctx, { em: oldEm });
1549
- if (allowPendingChanges)
1550
- newEm.mode = "in-memory-writes";
1551
- // hydrate (ie, create) each entity from the oldEm in the newEm
1552
- for (const [tag, entities] of oldEm.#entitiesByTag.entries()) {
1553
- // tags are always defined by the base constructor, so we use that as hydrate expects the base class as its argument
1554
- const baseCstr = (0, configure_1.getConstructorFromTag)(tag);
1555
- let rows = new Array(entities.length);
1556
- let i = 0;
1557
- for (const entity of entities) {
1558
- const instanceData = entity.__data;
1559
- if (!allowPendingChanges && instanceData.pendingOperation !== "none") {
1560
- (0, utils_1.fail)("Cannot fork an EntityManager with pending changes");
1561
- }
1562
- else if (instanceData.isNewEntity) {
1563
- // Create blank entities in newEm for each unpersisted entity from oldEm. They will be populated later in the
1564
- // allowPendingChanges step as they should not be present otherwise.
1565
- // (I'd thought we should copy over `InstanceData.createId`, but since we're iterating over `oldEm.#entitiesByTag`
1566
- // in stable as-created order, the `newEm.create` will assign the same/incrementing `createId`s as in oldEm.)
1567
- newEm.create(entity.constructor, {});
1568
- }
1569
- else {
1570
- // We copy the raw row data for each entity to avoid any potential conflict. Then we ensure the correct concrete
1571
- // __class key is set for hydrate to use, if necessary (ie, cti), to actually instantiate the entity.
1572
- rows[i] = createRowFromEntityData(entity);
1573
- i++;
1574
- }
1575
- }
1576
- if (rows.length !== i)
1577
- rows = rows.slice(0, i);
1578
- newEm.hydrate(baseCstr, rows);
1579
- }
1580
- function mapEntity(oldEntity) {
1581
- if (oldEntity.isNewEntity) {
1582
- return newEm.#entitiesById.get(oldEntity.toTaggedString());
1583
- }
1584
- else {
1585
- return newEm.#entitiesById.get(oldEntity.idTagged);
1586
- }
1587
- }
1588
- function mapEntities(v) {
1589
- if (v === undefined)
1590
- return undefined;
1591
- const result = new Array(v.length);
1592
- for (let i = 0; i < v.length; i++)
1593
- result[i] = mapEntity(v[i]);
1594
- return result;
1595
- }
1596
- // If we are allowing pending changes, then we need to copy any changes across to newEm
1597
- if (allowPendingChanges) {
1598
- for (const oldEntity of oldEm.entities) {
1599
- const oldInstanceData = oldEntity.__data;
1600
- if (!(oldInstanceData.isNewEntity || oldInstanceData.isDirtyEntity))
1601
- continue;
1602
- const { originalData: oldOriginalData, data: oldData } = oldInstanceData;
1603
- const newEntity = mapEntity(oldEntity);
1604
- const newInstanceData = newEntity.__data;
1605
- const { data: newData } = newInstanceData;
1606
- // for new entities, anything in `data` is changed and should be copied across. for existing entities, we
1607
- // only care about changed fields, which are enumerated by originalData
1608
- const maybeEntity = (value) => ((0, Entity_1.isEntity)(value) ? mapEntity(value) : value);
1609
- const fields = Object.keys(oldEntity.isNewEntity ? oldData : oldOriginalData);
1610
- for (const field of fields) {
1611
- // copy over originalData so .changes is consistent across ems
1612
- if (field in oldOriginalData)
1613
- newInstanceData.markFieldDirty(field, maybeEntity(oldOriginalData[field]));
1614
- newData[field] = maybeEntity(oldData[field]);
1615
- }
1616
- }
1617
- }
1618
- // import every loaded concrete (ie, not custom) relation into the new em
1619
- for (const oldEntity of oldEm.entities) {
1620
- const newEntity = mapEntity(oldEntity);
1621
- if (oldEntity.isDeletedEntity) {
1622
- // If the old entity was deleted, that should be persisted in the new em
1623
- newEntity.__data.markDeleted();
1624
- // deleted entities will fail if you try to `get` their relations, so skip them since they should be cleared
1625
- // out regardless
1626
- continue;
1627
- }
1628
- const { relations } = oldEntity.__data;
1629
- for (const [field, relation] of Object.entries(relations)) {
1630
- // With lazyRelation, custom relations are inserted into the `relations` map. Custom relations don't
1631
- // store any data, so we can ignore them by checking if the relation implements `import`
1632
- // TODO: add `import` to recursiveCollection
1633
- if (!("import" in relation))
1634
- continue;
1635
- if (oldEntity.isNewEntity) {
1636
- // every relation should be loaded on a new entity, so calling get should be safe
1637
- const oldValue = relation.get;
1638
- if (oldValue === undefined)
1639
- continue;
1640
- if (Array.isArray(oldValue) && oldValue.length === 0)
1641
- continue;
1642
- const newValue = Array.isArray(oldValue) ? mapEntities(oldValue) : mapEntity(oldValue);
1643
- // we may have already copied over the instance data, in which case `setFromOpts` would detect this as
1644
- // the same entity that's already set in data and early exit, so delete ourselves from data first
1645
- delete newEntity.__data.data[field];
1646
- newEntity[field].setFromOpts(newValue);
1647
- }
1648
- else {
1649
- const isLoaded = "_isLoaded" in relation ? relation._isLoaded : relation.isLoaded;
1650
- if (isLoaded)
1651
- newEntity[field].import(relation, mapEntity, mapEntities);
1652
- }
1653
- }
1654
- }
1655
- // Inspect the top level keys in the context and replace any references from oldEm with newEm (ie, ctx.em === newEm)
1656
- // while also replacing any entities from oldEm with their version in newEm (eg, if the user is stored in the
1657
- // context, then `ctx.user.em === newEm`).
1658
- for (const [key, value] of Object.entries(ctx)) {
1659
- if ((0, Entity_1.isEntity)(value) && value.em === oldEm) {
1660
- ctx[key] = mapEntity(value);
1661
- }
1662
- else if (value === oldEm) {
1663
- ctx[key] = newEm;
1664
- }
1665
- }
1666
- return newEm;
1667
- }
1668
- importEntity(source, hint, normalizedHint) {
1669
- if (source.isNewEntity)
1670
- (0, utils_1.fail)("cannot import new entities");
1671
- if (source.isDeletedEntity)
1672
- (0, utils_1.fail)("cannot import deleted entities");
1673
- if (source.isDirtyEntity)
1674
- (0, utils_1.fail)("cannot import dirty entities");
1675
- hint ??= {};
1676
- if (!normalizedHint) {
1677
- (0, index_1.assertLoaded)(source, hint);
1678
- normalizedHint = (0, index_1.deepNormalizeHint)(hint);
1679
- }
1680
- if (source.em === this)
1681
- return source;
1682
- const meta = (0, index_1.getMetadata)(source);
1683
- let result = this.#entitiesById.get(source.idTagged);
1684
- if (!result) {
1685
- const meta = (0, index_1.getMetadata)(source);
1686
- const row = createRowFromEntityData(source);
1687
- result = this.hydrate((0, index_1.getBaseMeta)(meta).cstr, [row])[0];
1688
- }
1689
- for (const [fieldName, subHint] of Object.entries(normalizedHint)) {
1690
- const field = meta.allFields[fieldName];
1691
- const relationOrProp = result[fieldName];
1692
- if (!field) {
1693
- let loadHint = relationOrProp.loadHint ?? (0, utils_1.fail)(`${source}.${fieldName} cannot be imported as it has no loadHint`);
1694
- this.importEntity(source, loadHint);
1695
- }
1696
- else if ("import" in relationOrProp) {
1697
- // Tell our version of the entity (result) to accept/copy the relation state of the source
1698
- relationOrProp.import(source[fieldName], (e) => this.importEntity(e, subHint, subHint), (entities) => {
1699
- if (entities === undefined)
1700
- return undefined;
1701
- const result = new Array(entities.length);
1702
- for (let i = 0; i < entities.length; i++) {
1703
- result[i] = this.importEntity(entities[i], subHint, subHint);
1704
- }
1705
- return result;
1706
- });
1707
- }
1708
- }
1709
- return result;
1710
- }
1711
- addPlugin(plugin) {
1712
- getEmInternalApi(this).pluginManager.addPlugin(plugin);
1713
- }
1714
- getPlugins() {
1715
- return getEmInternalApi(this).pluginManager.plugins;
1716
- }
1717
- get isRefreshing() {
1718
- return this.#isRefreshing;
1719
- }
1720
- get isFlushing() {
1721
- return this.#fl.isFlushing;
1722
- }
1723
- /** Creates a new `type` and marks it as loaded, i.e. we know its collections are all safe to access in memory. */
1724
- #doCreate(type, opts, partial) {
1725
- const entity = (0, newEntity_1.newEntity)(this, type, true);
1726
- // Assign the next `a#1`, `a#2`, etc. id
1727
- const meta = (0, index_1.getMetadata)(type);
1728
- const counter = (this.#createCounter ??= new Map());
1729
- const i = (counter.get(meta.tagName) ?? 0) + 1;
1730
- counter.set(meta.tagName, i);
1731
- (0, BaseEntity_1.getInstanceData)(entity).createId = String(i);
1732
- // Check opts.id for an explicitly-set id
1733
- this.#doRegister(entity, opts.id);
1734
- // Set a default createdAt/updatedAt
1735
- const baseMeta = (0, index_1.getBaseMeta)((0, index_1.getMetadata)(entity));
1736
- if (baseMeta.timestampFields) {
1737
- this.#assignTimestamps(entity, baseMeta);
1738
- }
1739
- // Set the discriminator for STI
1740
- if (baseMeta.inheritanceType === "sti") {
1741
- setStiDiscriminatorValue(baseMeta, entity);
1742
- }
1743
- // api will be undefined during getFakeInstance
1744
- const api = getEmInternalApi(this);
1745
- api?.fieldLogger?.logCreate(entity);
1746
- (0, index_1.setOpts)(entity, opts, { partial, calledFromConstructor: true });
1747
- // Apply any synchronous defaults, after the opts have been applied
1748
- if (!this.fakeInstance) {
1749
- (0, defaults_1.setSyncDefaults)(entity);
1750
- }
1751
- this.#rm.queueAllDownstreamFields(entity, "created");
1752
- return entity;
1753
- }
1754
- #assignTimestamps(entity, baseMeta) {
1755
- const { createdAt, updatedAt } = baseMeta.timestampFields ?? {};
1756
- const { data } = (0, BaseEntity_1.getInstanceData)(entity);
1757
- const now = new Date();
1758
- if (createdAt) {
1759
- const serde = baseMeta.fields[createdAt].serde;
1760
- data[createdAt] = serde.mapFromNow(now);
1761
- }
1762
- if (updatedAt) {
1763
- const serde = baseMeta.fields[updatedAt].serde;
1764
- data[updatedAt] = serde.mapFromNow(now);
1765
- }
1766
- }
1767
- /** Registers a newly-instantiated entity with our EntityManager; only called by #doCreate and hydrate. */
1768
- #doRegister(entity, id, meta, skipDuplicateCheck = false) {
1769
- // Keep our indexes up to date...
1770
- const maybeId = id ?? entity.idTaggedMaybe;
1771
- if (maybeId) {
1772
- if (!skipDuplicateCheck && this.findExistingInstance(maybeId) !== undefined) {
1773
- throw new Error(`Entity ${entity} has a duplicate instance already loaded`);
1774
- }
1775
- this.#entitiesById.set(maybeId, entity);
1776
- }
1777
- else {
1778
- // Also register by the `a#1` style tagged string for new entities
1779
- this.#entitiesById.set(entity.toTaggedString(), entity);
1780
- }
1781
- (0, BaseEntity_1.getInstanceData)(entity).entityIndex = this.#entitiesArray.length;
1782
- this.#entitiesArray.push(entity);
1783
- meta ??= (0, index_1.getMetadata)(entity);
1784
- const set = this.#entitiesByTag.get(meta.tagName) ?? [];
1785
- if (set.length === 0)
1786
- this.#entitiesByTag.set(meta.tagName, set);
1787
- set.push(entity);
1788
- if (this.#entitiesArray.length >= this.entityLimit) {
1789
- const topTypes = [...this.#entitiesByTag.entries()]
1790
- .map(([tag, entities]) => ({ tag, count: entities.length }))
1791
- .sort((a, b) => b.count - a.count)
1792
- .slice(0, 3)
1793
- .map(({ tag, count }) => `${tag}=${count}`)
1794
- .join(", ");
1795
- throw new Error(`More than ${this.entityLimit} entities have been instantiated (top entities: ${topTypes})`);
1796
- }
1797
- }
1798
- }
1799
- exports.EntityManager = EntityManager;
78
+ * The EntityManager is the primary way nearly all code, i.e. anything that finds/creates/updates/deletes entities,
79
+ * will interact with the database.
80
+ *
81
+ * It acts both an Identity Cache (preventing loading the same row twice into memory as separate entities, and then
82
+ * having drift between the two instances) and as a Unit of Work (tracking all changes to entities and then batch
83
+ * flushing only the entities that have changed).
84
+ *
85
+ * Note that the type parameters (C, I, and Entity) will be filled in by codegen with the values specific to your
86
+ * application, so you can import your app-specific EntityManager like:
87
+ *
88
+ * ```ts
89
+ * import { EntityManager } from "src/entities";
90
+ * ```
91
+ *
92
+ * @param C The type of your application-specific app-wide/request-wide Context object that will be passed to hooks
93
+ * @typeParam C - the application-specific context (typically the request-level context)
94
+ * @typeParam Entity - the application's based entity type (i.e. with number ids or string ids)
95
+ * @typeParamTX - the application's Transaction type, i.e. `Knex`
96
+ */
97
+ var EntityManager = class EntityManager {
98
+ ctx;
99
+ driver;
100
+ /** When we're flushing, the connection/transaction. */
101
+ txn;
102
+ entityLimit = defaultEntityLimit;
103
+ #entitiesArray = [];
104
+ #maybePendingFlushEntities = /* @__PURE__ */ new Set();
105
+ #entitiesById = /* @__PURE__ */ new Map();
106
+ #entitiesByTag = /* @__PURE__ */ new Map();
107
+ #indexManager = new IndexManager();
108
+ #isValidating = false;
109
+ #findRestricted = false;
110
+ #pendingPercolate = /* @__PURE__ */ new Map();
111
+ #preloadedRelations = /* @__PURE__ */ new Map();
112
+ /**
113
+ * Tracks cascade deletes.
114
+ *
115
+ * We originally used a beforeDelete lifecycle hook to implement this, but tracking this
116
+ * individually allows us to a) recursively cascade deletes even during the 1st iteration
117
+ * of our `flush` loop, and b) cascade deletions before we recalc fields & run user hooks,
118
+ * so that both see the most accurate state.
119
+ */
120
+ #pendingDeletes = [];
121
+ #hasAnyDeletes = false;
122
+ #dataloaders = {};
123
+ #batchLoaders = {};
124
+ #joinRows = {};
125
+ /** Stores any `source -> downstream` reactions to recalc during `em.flush`. */
126
+ #rm = new ReactionsManager(this);
127
+ /** Ensures our `em.flush` method is not interrupted. */
128
+ #fl = new FlushLock();
129
+ #hooks = {
130
+ beforeBegin: [],
131
+ afterBegin: [],
132
+ beforeCommit: [],
133
+ afterCommit: []
134
+ };
135
+ #preloader;
136
+ #fieldLogger = noopFieldLogger;
137
+ #isLoadedCache = new IsLoadedCache();
138
+ #merging;
139
+ /** Track `a#1`, `a#2`, etc indexes for `em.create`-d entities. */
140
+ #createCounter = void 0;
141
+ __api;
142
+ #isRefreshing = false;
143
+ mode = "writes";
144
+ constructor(ctx, driverOrOpts) {
145
+ const opts = driverOrOpts.constructor === Object ? driverOrOpts : { driver: driverOrOpts };
146
+ this.ctx = ctx;
147
+ this.driver = opts.driver ?? opts.em.driver;
148
+ this.#preloader = opts.preloadPlugin ?? (opts.em ? opts.em.#preloader : this.driver.defaultPlugins.preloadPlugin);
149
+ const pluginManager = new PluginManager(this);
150
+ if (opts.em) {
151
+ this.#hooks = {
152
+ beforeBegin: [...opts.em.#hooks.beforeBegin],
153
+ afterBegin: [...opts.em.#hooks.afterBegin],
154
+ beforeCommit: [...opts.em.#hooks.beforeCommit],
155
+ afterCommit: [...opts.em.#hooks.afterCommit]
156
+ };
157
+ opts.em.__api.pluginManager.cloneTo(pluginManager);
158
+ }
159
+ const em = this;
160
+ this.__api = {
161
+ preloader: this.#preloader,
162
+ pendingPercolate: this.#pendingPercolate,
163
+ mutatedCollections: /* @__PURE__ */ new Set(),
164
+ pendingLoads: /* @__PURE__ */ new Set(),
165
+ hooks: this.#hooks,
166
+ rm: this.#rm,
167
+ indexManager: this.#indexManager,
168
+ isLoadedCache: this.#isLoadedCache,
169
+ pluginManager,
170
+ markMaybePending(entity) {
171
+ em.#maybePendingFlushEntities.add(entity);
172
+ },
173
+ unmarkMaybePending(entity) {
174
+ em.#maybePendingFlushEntities.delete(entity);
175
+ },
176
+ hasAnyDeletes() {
177
+ return em.#hasAnyDeletes;
178
+ },
179
+ pendingDeleteIds(type) {
180
+ return em.#pendingDeletes.filter((entity) => entity instanceof type && entity.idMaybe !== void 0).map((entity) => keyToNumber(getMetadata(entity), entity.id));
181
+ },
182
+ isMerging(entity) {
183
+ return em.#merging?.has(entity) ?? false;
184
+ },
185
+ joinRows(m2m) {
186
+ return getOrSet(em.#joinRows, m2m.joinTableName, () => new JoinRows(m2m, em.#rm));
187
+ },
188
+ /** Returns `a:1.books` if it's in our preload cache. */
189
+ getPreloadedRelation(taggedId, fieldName) {
190
+ return em.#preloadedRelations.get(taggedId)?.get(fieldName);
191
+ },
192
+ /** Stores `a:1.books` in our preload cache. */
193
+ setPreloadedRelation(taggedId, fieldName, children) {
194
+ let map = em.#preloadedRelations.get(taggedId);
195
+ if (!map) {
196
+ map = /* @__PURE__ */ new Map();
197
+ em.#preloadedRelations.set(taggedId, map);
198
+ }
199
+ map.set(fieldName, children);
200
+ },
201
+ get isValidating() {
202
+ return em.#isValidating;
203
+ },
204
+ checkWritesAllowed() {
205
+ if (em.mode === "read-only") throw new ReadOnlyError();
206
+ return em.#fl.checkWritesAllowed();
207
+ },
208
+ get fieldLogger() {
209
+ return em.#fieldLogger;
210
+ },
211
+ clearDataloaders() {
212
+ em.#dataloaders = {};
213
+ em.#batchLoaders = {};
214
+ },
215
+ clearPreloadedRelations() {
216
+ em.#preloadedRelations = /* @__PURE__ */ new Map();
217
+ },
218
+ setIsRefreshing(isRefreshing) {
219
+ em.#isRefreshing = isRefreshing;
220
+ }
221
+ };
222
+ }
223
+ /** Returns a read-only shallow copy of the currently-loaded entities. */
224
+ get entities() {
225
+ return [...this.#entitiesArray];
226
+ }
227
+ /** Returns a list of all pending creates, updates, deletes, and m2m changes that would be flushed. */
228
+ get pendingChanges() {
229
+ const changes = [];
230
+ for (const entity of this.#entitiesArray) switch (getInstanceData(entity).pendingOperation) {
231
+ case "insert":
232
+ changes.push({
233
+ kind: "create",
234
+ entity
235
+ });
236
+ break;
237
+ case "update":
238
+ changes.push({
239
+ kind: "update",
240
+ entity
241
+ });
242
+ break;
243
+ case "delete": changes.push({
244
+ kind: "delete",
245
+ entity
246
+ });
247
+ }
248
+ for (const joinRows of Object.values(this.#joinRows)) {
249
+ const todo = joinRows.toTodo();
250
+ if (todo && !todo.m2m.otherEnum) {
251
+ for (const row of todo.newRows) {
252
+ const entities = Object.values(row.columns);
253
+ changes.push({
254
+ kind: "m2m",
255
+ op: "add",
256
+ joinTableName: todo.m2m.joinTableName,
257
+ entities
258
+ });
259
+ }
260
+ for (const row of todo.deletedRows) {
261
+ const entities = Object.values(row.columns);
262
+ changes.push({
263
+ kind: "m2m",
264
+ op: "remove",
265
+ joinTableName: todo.m2m.joinTableName,
266
+ entities
267
+ });
268
+ }
269
+ }
270
+ }
271
+ return changes;
272
+ }
273
+ /** Returns a read-only list of the currently-loaded entities of `type`. */
274
+ getEntities(type) {
275
+ const meta = getMetadata(type);
276
+ const entities = this.#entitiesByTag.get(meta.tagName) ?? [];
277
+ return meta.baseType ? entities.filter((e) => e instanceof type) : entities;
278
+ }
279
+ getEntity(id) {
280
+ return this.#entitiesById.get(id);
281
+ }
282
+ async find(type, where, options) {
283
+ this.#assertFindAllowed("find");
284
+ const { populate, ...rest } = options || {};
285
+ const normalized = mergeFindOptions(where, rest);
286
+ const settings = {
287
+ where: normalized.where,
288
+ ...normalized.options
289
+ };
290
+ const result = await (hasPaginationSettings(normalized.options) ? findPaginatedDataLoader(this, type, settings, populate) : findDataLoader(this, type, settings, populate)).catch(function find(err) {
291
+ throw appendStack(err, /* @__PURE__ */ new Error());
292
+ });
293
+ if (populate) await this.populate(result, populate);
294
+ return result;
295
+ }
296
+ query(q, options) {
297
+ this.#assertFindAllowed("query");
298
+ const em = this;
299
+ return (async function query() {
300
+ const plan = parseRootQuery(q);
301
+ if (options?.populate && plan.output.kind !== "entity") fail("em.query populate requires an entity selection");
302
+ const { rows } = await em.driver.executeQuery(em, plan.sql, plan.bindings);
303
+ const result = plan.decodeRows(em, rows);
304
+ if (options?.populate) await em.populate(result, options.populate);
305
+ return result;
306
+ })().catch(function query(err) {
307
+ throw appendStack(err, /* @__PURE__ */ new Error());
308
+ });
309
+ }
310
+ execute(statement) {
311
+ const em = this;
312
+ return (async function execute() {
313
+ if (isMutation(statement)) {
314
+ if (em.mode === "read-only") throw new ReadOnlyError();
315
+ if (em.mode === "in-memory-writes") fail("SQL mutations do not support in-memory-writes mode");
316
+ } else em.#assertFindAllowed("execute");
317
+ const plan = parseStatement(statement);
318
+ if (!plan) return {
319
+ rowCount: 0,
320
+ rows: []
321
+ };
322
+ const result = await em.driver.executeQuery(em, plan.sql, plan.bindings);
323
+ return decodeStatementResult(em, plan, result);
324
+ })().catch(function execute(err) {
325
+ throw appendStack(err, /* @__PURE__ */ new Error());
326
+ });
327
+ }
328
+ /** Fails fast if `em.${method}` is called from a regular validation rule, i.e. steers to `config.addCommitRule`. */
329
+ #assertFindAllowed(method) {
330
+ if (this.#findRestricted) throw new Error(`em.${method} cannot be called from a validation rule (added via config.addRule), because rules run before the flush and would query stale, pre-flush data. Use config.addCommitRule instead, which runs after the INSERT/UPDATE/DELETEs are flushed (within the same transaction) and so sees the changed state.`);
331
+ }
332
+ /** Runs the post-parse find pipeline: plugins mutate the logical AST, then Joist optimizes/prunes before SQL. */
333
+ async executeFind(meta, operation, parsed, settings) {
334
+ const { checkLimit, findSettings } = this.prepareFind(meta, operation, parsed, settings);
335
+ return this.executePreparedFind(meta, operation, parsed, findSettings, checkLimit);
336
+ }
337
+ /** Like {@link executeFind}, but returns a {@link RowData}; see {@link executePreparedFindRowData}. */
338
+ async executeFindRowData(meta, operation, parsed, settings) {
339
+ const { checkLimit, findSettings } = this.prepareFind(meta, operation, parsed, settings);
340
+ return this.executePreparedFindRowData(meta, operation, parsed, findSettings, checkLimit);
341
+ }
342
+ /** Executes a query that has already had find hooks and optimizations applied. */
343
+ async executePreparedFind(meta, operation, parsed, findSettings, checkLimit) {
344
+ const { pluginManager } = getEmInternalApi(this);
345
+ const rows = await this.driver.executeFind(this, parsed, findSettings);
346
+ if ((checkLimit ?? !("limit" in findSettings && findSettings.limit === void 0)) && rows.length >= this.entityLimit) throw new Error(`Query returned more than ${this.entityLimit} entityLimit rows`);
347
+ if (pluginManager.hasHook("afterFind")) pluginManager.afterFind(meta, operation, new PojoRowData(rows));
348
+ return rows;
349
+ }
350
+ /**
351
+ * Like {@link executePreparedFind}, but returns a {@link RowData}: lazy wire rows when the
352
+ * driver has `lazyRows` enabled, else classic POJO rows wrapped in a `PojoRowData` — so
353
+ * loaders can hydrate from one shape without caring which the driver provides.
354
+ */
355
+ async executePreparedFindRowData(meta, operation, parsed, findSettings, checkLimit) {
356
+ const { executeFindRowData } = this.driver;
357
+ if (executeFindRowData === void 0) return new PojoRowData(await this.executePreparedFind(meta, operation, parsed, findSettings, checkLimit));
358
+ const { pluginManager } = getEmInternalApi(this);
359
+ const rowData = await executeFindRowData.call(this.driver, this, parsed, findSettings);
360
+ if ((checkLimit ?? !("limit" in findSettings && findSettings.limit === void 0)) && rowData.rowCount >= this.entityLimit) throw new Error(`Query returned more than ${this.entityLimit} entityLimit rows`);
361
+ pluginManager.afterFind(meta, operation, rowData);
362
+ return rowData;
363
+ }
364
+ /**
365
+ * Runs pre-SQL find hooks and optimizations against a parsed query.
366
+ *
367
+ * This allows plugins to see "pre-batched" / "logical" query ASTs, instead of our
368
+ * more complicated `_find` batched queries. The flow would be:
369
+ *
370
+ * - A loader calls `prepareFind(originalQuery)`
371
+ * - Plugins inspect/modify the query as/if needed
372
+ * - The loader crafts a new, more complicated query that embeds the originalQuery
373
+ * - The loader calls `executePreparedFind` with the 2nd query
374
+ */
375
+ prepareFind(meta, operation, parsed, settings) {
376
+ const { checkLimit, ...findSettings } = settings;
377
+ const { pluginManager } = getEmInternalApi(this);
378
+ pluginManager.beforeFind(meta, operation, parsed, findSettings);
379
+ optimizeCollectionJoins(parsed, settings);
380
+ return {
381
+ checkLimit,
382
+ findSettings
383
+ };
384
+ }
385
+ async findGql(type, where, options) {
386
+ if (!options) return this.find(type, where);
387
+ const normalized = { ...options };
388
+ if ("limit" in normalized) normalized.limit = normalized.limit ?? void 0;
389
+ if ("offset" in normalized) normalized.offset = normalized.offset ?? void 0;
390
+ return this.find(type, where, normalized);
391
+ }
392
+ async findOne(type, where, options) {
393
+ const list = await this.find(type, where, options);
394
+ if (list.length === 0) return;
395
+ else if (list.length === 1) return list[0];
396
+ else throw new TooManyError(`Found more than one: ${list.map((e) => e.toString()).join(", ")}`);
397
+ }
398
+ async findOneOrFail(type, where, options) {
399
+ const list = await this.find(type, where, options);
400
+ if (list.length === 0) throw new NotFoundError(`Did not find ${type.name} for given query`);
401
+ else if (list.length > 1) throw new TooManyError(`Found more than one: ${list.map((e) => e.toString()).join(", ")}`);
402
+ return list[0];
403
+ }
404
+ async findByUnique(type, where, options = {}) {
405
+ this.#assertFindAllowed("findByUnique");
406
+ const { populate, softDeletes = "exclude" } = options;
407
+ const entries = Object.entries(where);
408
+ if (entries.length !== 1) throw new Error("findByUnique only accepts a single field");
409
+ const [fieldName, value] = entries[0];
410
+ const field = getMetadata(type).allFields[fieldName];
411
+ const row = await findByUniqueDataLoader(this, type, field, softDeletes).load(value).catch(function findByUnique(err) {
412
+ throw appendStack(err, /* @__PURE__ */ new Error());
413
+ });
414
+ if (!row) return;
415
+ else {
416
+ const [entity] = this.hydrate(type, [row]);
417
+ if (this.#hasAnyDeletes && entity.isDeletedEntity) return;
418
+ if (populate) await this.populate(entity, populate);
419
+ return entity;
420
+ }
421
+ }
422
+ /**
423
+ * Returns the count of entities that match the `where` clause.
424
+ *
425
+ * The `where` clause, and any options.conditions, matches the same syntax
426
+ * as `em.find`.
427
+ *
428
+ * Note: this method is not currently auto-batched, so it will cause N+1s if called in a loop.
429
+ */
430
+ async findCount(type, where, options = {}) {
431
+ this.#assertFindAllowed("findCount");
432
+ const normalized = mergeCountOptions(where, options);
433
+ const settings = {
434
+ where: normalized.where,
435
+ ...normalized.options
436
+ };
437
+ let count = await findCountDataLoader(this, type, settings).catch(function findCount(err) {
438
+ throw appendStack(err, /* @__PURE__ */ new Error());
439
+ });
440
+ if (isSelectAllFilter(where, options.conditions)) {
441
+ const tagged = this.#entitiesByTag.get(getMetadata(type).tagName) ?? [];
442
+ for (const entity of tagged) if (entity instanceof type) {
443
+ if (entity.isNewEntity) count++;
444
+ else if (entity.isDeletedEntity) count--;
445
+ }
446
+ }
447
+ return count;
448
+ }
449
+ /**
450
+ * Returns the IDs of entities that match the `where` clause.
451
+ *
452
+ * The `where` clause, and any options.conditions, matches the same syntax
453
+ * as `em.find`.
454
+ */
455
+ async findIds(type, where, options = {}) {
456
+ this.#assertFindAllowed("findIds");
457
+ const normalized = mergeCountOptions(where, options);
458
+ const settings = {
459
+ where: normalized.where,
460
+ ...normalized.options
461
+ };
462
+ return findIdsDataLoader(this, type, settings).catch(function findIds(err) {
463
+ throw appendStack(err, /* @__PURE__ */ new Error());
464
+ });
465
+ }
466
+ async findWithNewOrChanged(type, where, options) {
467
+ const { softDeletes = "exclude", populate } = options ?? {};
468
+ const copy = Object.fromEntries(Object.entries(where).filter(([, v]) => v !== void 0));
469
+ const unchanged = (await this.find(type, copy, { softDeletes })).filter((e) => !e.isNewEntity && !e.isDirtyEntity && !e.isDeletedEntity);
470
+ const maybeNew = this.filterEntities(type, where).filter((e) => (e.isNewEntity || e.isDirtyEntity) && !e.isDeletedEntity);
471
+ const found = [...unchanged, ...maybeNew];
472
+ if (populate) await this.populate(found, populate);
473
+ return found;
474
+ }
475
+ async findOrCreate(type, where, ifNew, upsert, options) {
476
+ const { softDeletes = "exclude", populate } = options ?? {};
477
+ const entity = await findOrCreateDataLoader(this, type, where, softDeletes).load({
478
+ ifNew,
479
+ upsert
480
+ }).catch(function findOrCreate(err) {
481
+ throw appendStack(err, /* @__PURE__ */ new Error());
482
+ });
483
+ if (populate) await this.populate(entity, populate);
484
+ return entity;
485
+ }
486
+ /** Creates a new `type` and marks it as loaded, i.e. we know its collections are all safe to access in memory. */
487
+ create(type, opts) {
488
+ return this.#doCreate(type, opts, false);
489
+ }
490
+ /**
491
+ * Creates a new `type` but with `opts` that are nullable, to accept partial-update-style input.
492
+ *
493
+ * Note that `createPartial` doesn't support the full upsert behavior, i.e. this method:
494
+ *
495
+ * - always creates,
496
+ * - does not support relation markers like `op`, `delete`, and `remove`,
497
+ * - does not accept deep input, but
498
+ * - fields set to `undefined` will be skipped instead of unset
499
+ *
500
+ * See `upsert` for the upsert/deep upsert behavior.
501
+ */
502
+ createPartial(type, opts) {
503
+ return this.#doCreate(type, opts, true);
504
+ }
505
+ /**
506
+ * Create or updates `type` based on partial-update-style `input`.
507
+ *
508
+ * This supports upsert behavior, i.e.:
509
+ *
510
+ * - findOrCreate the primary entity being updated (based on the `id` key being provided),
511
+ * - upsert relation markers like `op`, `delete`, and `remove` are supported,
512
+ * - deep input is supported, i.e. `{ firstName: "Bob", books: [{ title: "b1" } ] }`, and
513
+ * - fields set to `undefined` will be skipped instead of unset
514
+ */
515
+ upsert(type, input) {
516
+ return upsert(this, type, input);
517
+ }
518
+ async clone(entityOrArray, opts) {
519
+ const { deep = {}, skipIf, skip = {}, postClone } = opts ?? {};
520
+ const todo = /* @__PURE__ */ new Set();
521
+ const skipMap = /* @__PURE__ */ new WeakMap();
522
+ await crawl(todo, skipMap, Array.isArray(entityOrArray) ? entityOrArray : [entityOrArray], deep, {
523
+ skipIf,
524
+ skip
525
+ });
526
+ const deferredRelations = [];
527
+ const clones = [...todo].map((entity) => {
528
+ const skip = skipMap.get(entity) ?? [];
529
+ const meta = getMetadata(entity);
530
+ const copy = Object.fromEntries(Object.values(meta.allFields).map((f) => {
531
+ if (skip.includes(f.fieldName)) return void 0;
532
+ switch (f.kind) {
533
+ case "primitive": if (!f.derived && !f.protected) return [f.fieldName, getField(entity, f.fieldName)];
534
+ else return;
535
+ case "enum": if (f.derived) return;
536
+ else return [f.fieldName, getField(entity, f.fieldName)];
537
+ case "m2o":
538
+ case "poly": {
539
+ if (f.kind === "m2o" && f.derived) return void 0;
540
+ const existingIdOrEntity = getField(entity, f.fieldName);
541
+ const target = isEntity(existingIdOrEntity) ? existingIdOrEntity : this.getEntity(existingIdOrEntity);
542
+ if (target && todo.has(target)) {
543
+ deferredRelations.push([
544
+ entity,
545
+ f.fieldName,
546
+ target
547
+ ]);
548
+ return [f.fieldName, void 0];
549
+ } else return [f.fieldName, existingIdOrEntity];
550
+ }
551
+ case "primaryKey":
552
+ case "o2m":
553
+ case "m2m":
554
+ case "m2mEnum":
555
+ case "o2o":
556
+ case "lo2m": return;
557
+ default: assertNever(f);
558
+ }
559
+ }).filter(isDefined));
560
+ return [entity, this.create(asConcreteCstr(meta.cstr), copy)];
561
+ });
562
+ const entityToClone = new Map(clones);
563
+ clones.forEach(([, clone]) => {
564
+ getRelationEntries(clone).forEach(([fieldName, value]) => {
565
+ if (value instanceof ManyToOneReferenceImpl || value instanceof PolymorphicReferenceImpl || value instanceof ReactiveReferenceImpl) {
566
+ const existingIdOrEntity = getField(clone, fieldName);
567
+ const existing = isEntity(existingIdOrEntity) ? existingIdOrEntity : this.getEntity(existingIdOrEntity);
568
+ if (existing) clone[fieldName].set(entityToClone.get(existing) ?? existing);
569
+ }
570
+ });
571
+ });
572
+ deferredRelations.forEach(([source, fieldName, target]) => {
573
+ entityToClone.get(source)[fieldName].set(entityToClone.get(target));
574
+ });
575
+ if (postClone) await Promise.all(clones.map(([original, clone]) => postClone(original, clone)));
576
+ return Array.isArray(entityOrArray) ? entityOrArray.filter((original) => entityToClone.has(original)).map((original) => entityToClone.get(original)) : clones[0] ? clones[0][1] : fail("no entities were cloned given the provided options");
577
+ }
578
+ /**
579
+ * Merges multiple source entities into a target entity by updating all references that point
580
+ * to the source entities to instead point to the target entity.
581
+ *
582
+ * This method loads all relations from the source entities, updates any entity that
583
+ * references a source entity to reference the target entity instead, and then automatically
584
+ * deletes the source entities.
585
+ *
586
+ * @param target - The entity that will become the target of all merged references
587
+ * @param sources - Array of entities whose references will be redirected to the target
588
+ * @param opts - Options to control merge behavior
589
+ * @param autoDelete - Whether to automatically delete source entities (default: true)
590
+ * @returns Promise that resolves when all references have been updated and sources deleted
591
+ *
592
+ * @example
593
+ * // Merge duplicate authors - all books pointing to author2 will now point to author1
594
+ * // author2 will be automatically deleted
595
+ * await em.merge(author1, [author2]);
596
+ *
597
+ * @example
598
+ * // Merge multiple duplicate publishers into one
599
+ * // publisher2 and publisher3 will be automatically deleted
600
+ * await em.merge(publisher1, [publisher2, publisher3]);
601
+ *
602
+ * @example
603
+ * // Merge without auto-deleting sources (for custom cleanup logic)
604
+ * await em.merge(author1, [author2], { autoDelete: false });
605
+ * // Custom logic here...
606
+ * em.delete(author2);
607
+ */
608
+ async merge(target, sources, opts) {
609
+ const autoDelete = opts?.autoDelete ?? true;
610
+ if (sources.length === 0) return [];
611
+ this.#merging ??= /* @__PURE__ */ new Set();
612
+ this.#merging.add(target);
613
+ const targetMeta = getMetadata(target);
614
+ for (const source of sources) {
615
+ const sourceMeta = getMetadata(source);
616
+ if (sourceMeta.type !== targetMeta.type) throw new Error(`Cannot merge entities of different types: ${targetMeta.type} and ${sourceMeta.type}`);
617
+ }
618
+ const fields = Object.values(targetMeta.allFields).filter((field) => [
619
+ "o2m",
620
+ "m2o",
621
+ "m2m",
622
+ "o2o"
623
+ ].includes(field.kind)).map((field) => field.fieldName);
624
+ await this.populate(sources, fields);
625
+ const changedEntities = [];
626
+ for (const source of sources) for (const field of Object.values(targetMeta.allFields)) {
627
+ const { kind } = field;
628
+ if (kind === "o2m") for (const other of source[field.fieldName].get) {
629
+ this.#merging.add(other);
630
+ other[field.otherFieldName].set(target);
631
+ changedEntities.push(other);
632
+ }
633
+ else if (kind === "o2o") {
634
+ const otherField = field.otherMetadata().allFields[field.otherFieldName];
635
+ if (otherField.kind === "m2o" && otherField.derived) continue;
636
+ const other = source[field.fieldName].get;
637
+ if (other) {
638
+ this.#merging.add(other);
639
+ other[field.otherFieldName].set(target);
640
+ changedEntities.push(other);
641
+ }
642
+ } else if (kind === "m2m") for (const other of source[field.fieldName].get) {
643
+ this.#merging.add(other);
644
+ const collection = other[field.otherFieldName];
645
+ collection.remove(source);
646
+ collection.add(target);
647
+ changedEntities.push(other);
648
+ }
649
+ else if (kind === "primitive" || kind === "primaryKey" || kind === "enum" || kind === "m2mEnum" || kind === "poly" || kind === "m2o" || kind === "lo2m") {} else assertNever(kind);
650
+ }
651
+ if (autoDelete) for (const source of sources) this.delete(source);
652
+ return changedEntities;
653
+ }
654
+ async load(typeOrId, id, hint) {
655
+ let type;
656
+ if (typeof typeOrId === "string") {
657
+ type = getConstructorFromTaggedId(typeOrId);
658
+ id = typeOrId;
659
+ } else {
660
+ type = typeOrId;
661
+ id = id || fail(`Invalid ${typeOrId.name} id: ${id}`);
662
+ }
663
+ const meta = getMetadata(type);
664
+ const taggedId = toTaggedId(meta, id);
665
+ let entity = this.findExistingInstance(taggedId);
666
+ if (!entity) {
667
+ await loadBatchLoader(this, meta).load({
668
+ taggedId,
669
+ hint
670
+ }).catch(function load(err) {
671
+ throw appendStack(err, /* @__PURE__ */ new Error());
672
+ });
673
+ entity = this.findExistingInstance(taggedId);
674
+ }
675
+ if (!entity) throw new NotFoundError(`${taggedId} was not found`);
676
+ if (hint) await this.populate(entity, hint);
677
+ if (meta.inheritanceType === "sti" && !(entity instanceof type)) throw new Error(`${entity} is ${entity.constructor.name} but should be ${type.name}`);
678
+ return entity;
679
+ }
680
+ async loadAll(type, _ids, hint) {
681
+ const meta = getMetadata(type);
682
+ const entities = new Array(_ids.length);
683
+ let idsToLoad;
684
+ let positionsToLoad;
685
+ for (let i = 0; i < _ids.length; i++) {
686
+ const id = tagId(meta, _ids[i]);
687
+ const entity = this.findExistingInstance(id);
688
+ if (entity) entities[i] = entity;
689
+ else {
690
+ (idsToLoad ??= []).push(id);
691
+ (positionsToLoad ??= []).push(i);
692
+ }
693
+ }
694
+ if (idsToLoad) {
695
+ await loadBatchLoader(this, meta).loadAll(idsToLoad.map((id) => ({
696
+ taggedId: id,
697
+ hint
698
+ }))).catch(function loadAll(err) {
699
+ throw appendStack(err, /* @__PURE__ */ new Error());
700
+ });
701
+ let idsNotFound;
702
+ for (let j = 0; j < positionsToLoad.length; j++) {
703
+ const entity = this.findExistingInstance(idsToLoad[j]);
704
+ entities[positionsToLoad[j]] = entity;
705
+ if (entity === void 0) (idsNotFound ??= []).push(idsToLoad[j]);
706
+ }
707
+ if (idsNotFound) throw new NotFoundError(`${idsNotFound.join(",")} were not found`);
708
+ }
709
+ const loadedEntities = entities;
710
+ if (hint) await this.populate(loadedEntities, hint);
711
+ if (meta.inheritanceType === "sti" && meta.baseType) {
712
+ const wrongType = loadedEntities.filter((e) => !(e instanceof meta.cstr));
713
+ if (wrongType.length > 0) throw new Error(`${wrongType.join(", ")} were not of type ${meta.cstr.name}`);
714
+ }
715
+ return loadedEntities;
716
+ }
717
+ async loadAllIfExists(type, _ids, hint) {
718
+ const meta = getMetadata(type);
719
+ const maybeEntities = new Array(_ids.length);
720
+ let idsToLoad;
721
+ let positionsToLoad;
722
+ for (let i = 0; i < _ids.length; i++) {
723
+ const id = tagId(meta, _ids[i]);
724
+ const entity = this.findExistingInstance(id);
725
+ if (entity) maybeEntities[i] = entity;
726
+ else {
727
+ (idsToLoad ??= []).push(id);
728
+ (positionsToLoad ??= []).push(i);
729
+ }
730
+ }
731
+ let entities;
732
+ if (idsToLoad) {
733
+ await loadBatchLoader(this, meta).loadAll(idsToLoad.map((id) => ({
734
+ taggedId: id,
735
+ hint
736
+ }))).catch(function loadAllIfExists(err) {
737
+ throw appendStack(err, /* @__PURE__ */ new Error());
738
+ });
739
+ for (let j = 0; j < positionsToLoad.length; j++) maybeEntities[positionsToLoad[j]] = this.findExistingInstance(idsToLoad[j]);
740
+ entities = [];
741
+ for (const entity of maybeEntities) if (entity !== void 0) entities.push(entity);
742
+ } else entities = maybeEntities;
743
+ if (hint) await this.populate(entities, hint);
744
+ return entities;
745
+ }
746
+ async loadLens(entities, fn, populate) {
747
+ const result = await loadLens(entities, fn);
748
+ if (populate) await this.populate(result, populate);
749
+ return result;
750
+ }
751
+ loadFromQuery(type, rows, populate) {
752
+ if (Array.isArray(rows)) {
753
+ const entities = this.hydrate(type, rows);
754
+ if (populate) return this.populate(entities, populate);
755
+ return entities;
756
+ } else return rows.then((rows) => {
757
+ const entities = this.hydrate(type, rows);
758
+ if (populate) return this.populate(entities, populate);
759
+ return entities;
760
+ });
761
+ }
762
+ async loadFromRows(type, rows, populate) {
763
+ const entities = this.hydrate(type, rows);
764
+ if (populate) await this.populate(entities, populate);
765
+ return entities;
766
+ }
767
+ async populate(entityOrList, hintOrOpts, fn) {
768
+ const { hint: hintOpt, ...opts } = typeof hintOrOpts === "object" && "hint" in hintOrOpts ? hintOrOpts : { hint: hintOrOpts };
769
+ opts[AsyncMethodPopulateSecret] = true;
770
+ const list = toArray(entityOrList).filter((e) => {
771
+ return e !== void 0 && !getInstanceData(e).isDeletedAndFlushed;
772
+ });
773
+ if (list.length === 0) return !fn ? entityOrList : fn(entityOrList);
774
+ if (!opts.forceReload && list.every((entity) => !entity.isNewEntity && isLoadedForPopulate(entity, hintOpt))) return fn ? fn(entityOrList) : entityOrList;
775
+ const meta = getMetadata(list[0]);
776
+ if (this.#preloader) {
777
+ const [preload, non] = this.#preloader.partitionHint(meta, hintOpt);
778
+ if (preload) await populateBatchLoader(this, meta, preload, "preload", opts).loadAll(list.map((entity) => ({
779
+ entity,
780
+ hint: preload
781
+ }))).catch(function populate(err) {
782
+ throw appendStack(err, /* @__PURE__ */ new Error());
783
+ });
784
+ if (non) await populateBatchLoader(this, meta, non, "intermixed", opts).loadAll(list.map((entity) => ({
785
+ entity,
786
+ hint: non
787
+ }))).catch(function populate(err) {
788
+ throw appendStack(err, /* @__PURE__ */ new Error());
789
+ });
790
+ } else await populateBatchLoader(this, meta, hintOpt, "intermixed", opts).loadAll(list.map((entity) => ({
791
+ entity,
792
+ hint: hintOpt
793
+ }))).catch(function populate(err) {
794
+ throw appendStack(err, /* @__PURE__ */ new Error());
795
+ });
796
+ return fn ? fn(entityOrList) : entityOrList;
797
+ }
798
+ /**
799
+ * Executes `fn` with a transaction, and automatically calls `flush`/`commit` at the end.
800
+ *
801
+ * This ensures both any `.find` and `.flush` operations happen within the same
802
+ * transaction, which is useful for enforcing cross-table/application-level invariants that
803
+ * cannot be enforced with database-level constraints.
804
+ */
805
+ async transaction(fn) {
806
+ return this.driver.transaction(this, async (txn) => {
807
+ const result = await fn(txn);
808
+ await this.flush();
809
+ return result;
810
+ });
811
+ }
812
+ delete(entityOrArray) {
813
+ for (const entity of toArray(entityOrArray)) {
814
+ if (!getInstanceData(entity).markDeleted()) continue;
815
+ this.#hasAnyDeletes = true;
816
+ this.#rm.queueAllDownstreamFields(entity, "deleted");
817
+ getCascadeDeleteRelations(entity).forEach((r) => r.maybeCascadeDelete());
818
+ this.#pendingDeletes.push(entity);
819
+ }
820
+ }
821
+ async assignNewIds() {
822
+ let pendingEntities = this.entities.filter((e) => e.isNewEntity && !e.isDeletedEntity && !e.idTaggedMaybe);
823
+ await this.getLoader("assign-new-ids", "global", async (entities) => {
824
+ let todos = createTodos(entities);
825
+ await this.driver.assignNewIds(this, todos);
826
+ for (const e of entities) this.#entitiesById.set(e.idTagged, e);
827
+ return entities;
828
+ }).loadMany(pendingEntities).catch(function assignNewIds(err) {
829
+ throw appendStack(err, /* @__PURE__ */ new Error());
830
+ });
831
+ }
832
+ /**
833
+ * Immediately assigns async defaults to `entities`.
834
+ *
835
+ * Normally async defaults wait until `em.flush` to run, because their async nature requires
836
+ * an `await` / `Promise` to be evaluated, and `em.create` is synchronous.
837
+ *
838
+ * This `assignDefaults` methods like you move that up, and immediately invoke
839
+ * any default logic against the `entities`.
840
+ */
841
+ async setDefaults(entities) {
842
+ return runInTrustedContext(async () => {
843
+ const suppressedTypeErrors = [];
844
+ const entitiesByType = groupBy(entities.filter((e) => e.isNewEntity), (e) => getMetadata(e));
845
+ await setAsyncDefaults(suppressedTypeErrors, this.ctx, entitiesByType);
846
+ });
847
+ }
848
+ /**
849
+ * Flushes the SQL for any changed entities to the database.
850
+ *
851
+ * If this is run outside of an existing transaction, it will `BEGIN` and `COMMIT`
852
+ * a new transaction on every `.flush()` call so that all of the `INSERT`s/etc.
853
+ * happen atomically.
854
+ *
855
+ * If this is run within an existing transaction, i.e. `EntityManager.transaction`,
856
+ * then it will only issue `INSERT`s/etc. and defer to the caller to `COMMIT`
857
+ * the transaction.
858
+ *
859
+ * It returns entities that have changed (an entity is considered changed if it has been deleted, inserted, or updated)
860
+ */
861
+ async flush(flushOptions = {}) {
862
+ return runInTrustedContext(() => this.#flush(flushOptions));
863
+ }
864
+ async #flush(flushOptions = {}) {
865
+ if (this.mode === "read-only") throw new ReadOnlyError();
866
+ const { skipValidation = false } = flushOptions;
867
+ this.#fl.startLock();
868
+ const allFlushedEntities = /* @__PURE__ */ new Set();
869
+ try {
870
+ await this.#fl.allowWrites(async () => {
871
+ await this.flushDeletes();
872
+ await this.#rm.recalcPendingReactables("reactables");
873
+ });
874
+ const createdThenDeleted = /* @__PURE__ */ new Set();
875
+ const hooksInvoked = /* @__PURE__ */ new Set();
876
+ let hookLoops = 0;
877
+ let now = getNow();
878
+ const suppressedDefaultTypeErrors = [];
879
+ const runHooksOnPendingEntities = async () => {
880
+ if (hookLoops++ >= 10) throw new Error("runHooksOnPendingEntities has ran 10 iterations, aborting");
881
+ const pendingLoads = [...getEmInternalApi(this).pendingLoads];
882
+ if (pendingLoads.length > 0) {
883
+ getEmInternalApi(this).pendingLoads.clear();
884
+ await Promise.all(pendingLoads.map((collection) => collection.load()));
885
+ }
886
+ const pendingFlush = /* @__PURE__ */ new Set();
887
+ const pendingHooks = /* @__PURE__ */ new Set();
888
+ const alreadyRanHooks = /* @__PURE__ */ new Set();
889
+ findPendingFlushEntities(this.#maybePendingFlushEntities, hooksInvoked, pendingFlush, pendingHooks, alreadyRanHooks);
890
+ if (alreadyRanHooks.size > 0) maybeBumpUpdatedAt(this.#rm, createTodos(alreadyRanHooks), now);
891
+ while (pendingHooks.size > 0) await this.#fl.allowWrites(async () => {
892
+ let todos = createTodos(pendingHooks);
893
+ await setAsyncDefaults(suppressedDefaultTypeErrors, this.ctx, Todo.groupInsertsByTypeAndSubType(todos));
894
+ maybeBumpUpdatedAt(this.#rm, todos, now);
895
+ for (const group of maybeSetupHookOrdering(todos)) {
896
+ await beforeCreate(this.ctx, group);
897
+ await beforeUpdate(this.ctx, group);
898
+ await beforeFlush(this.ctx, group);
899
+ }
900
+ recalcSynchronousDerivedFields(todos);
901
+ do {
902
+ await this.flushDeletes();
903
+ await this.#rm.recalcPendingReactables("reactables");
904
+ } while (this.#pendingDeletes.length > 0);
905
+ if (this.#rm.hasPendingTypeErrors) {
906
+ await this.#rm.recalcPendingTypeErrors();
907
+ if (this.#rm.needsRecalc("reactables")) await this.#rm.recalcPendingReactables("reactables");
908
+ }
909
+ for (const e of pendingHooks) hooksInvoked.add(e);
910
+ pendingHooks.clear();
911
+ findPendingFlushEntities(this.#maybePendingFlushEntities, hooksInvoked, pendingFlush, pendingHooks, alreadyRanHooks);
912
+ if (pendingHooks.size === 0 && this.#rm.hasPendingTypeErrors) await this.#rm.recalcPendingTypeErrors();
913
+ });
914
+ return [...pendingFlush].filter((e) => {
915
+ const createThenDelete = e.isDeletedEntity && e.isNewEntity;
916
+ if (createThenDelete) createdThenDeleted.add(e);
917
+ return !createThenDelete;
918
+ });
919
+ };
920
+ const { pluginManager } = getEmInternalApi(this);
921
+ const runValidation = async (entityTodos, joinRowTodos, validate) => {
922
+ const changedEntities = entitiesFromTodos(entityTodos, joinRowTodos);
923
+ try {
924
+ this.#isValidating = true;
925
+ await pluginManager.beforeValidate(changedEntities);
926
+ if (validate) {
927
+ this.#findRestricted = true;
928
+ try {
929
+ await validateSimpleRules(entityTodos);
930
+ if (suppressedDefaultTypeErrors.length > 0) throw suppressedDefaultTypeErrors[0];
931
+ await validateReactiveRules(this, this.#rm.logger, entityTodos, joinRowTodos);
932
+ } finally {
933
+ this.#findRestricted = false;
934
+ }
935
+ await afterValidation(this.ctx, entityTodos);
936
+ }
937
+ await pluginManager.afterValidate(changedEntities);
938
+ } finally {
939
+ this.#isValidating = false;
940
+ }
941
+ };
942
+ const runCommitValidation = async (entityTodos, joinRowTodos) => {
943
+ this.#dataloaders = {};
944
+ this.#batchLoaders = {};
945
+ this.#preloadedRelations = /* @__PURE__ */ new Map();
946
+ try {
947
+ this.#isValidating = true;
948
+ await validateSimpleRules(entityTodos, (config) => config.commitRules);
949
+ await validateReactiveRules(this, this.#rm.logger, entityTodos, joinRowTodos, (meta) => meta.reactiveCommitRules);
950
+ } finally {
951
+ this.#isValidating = false;
952
+ }
953
+ };
954
+ const commitRuleTodos = {};
955
+ const commitRuleJoinRowTodos = {};
956
+ const commitRuleSeen = /* @__PURE__ */ new Set();
957
+ function collectCommitRuleTodos(entityTodos, joinRowTodos) {
958
+ if (skipValidation) return;
959
+ for (const todo of Object.values(entityTodos)) {
960
+ if (!todo.metadata.hasCommitRules) continue;
961
+ for (const key of [
962
+ "inserts",
963
+ "updates",
964
+ "deletes"
965
+ ]) for (const e of todo[key]) if (!commitRuleSeen.has(e)) {
966
+ commitRuleSeen.add(e);
967
+ getTodo(commitRuleTodos, e)[key].push(e);
968
+ }
969
+ }
970
+ for (const [table, todo] of Object.entries(joinRowTodos)) {
971
+ if (!todo.m2m.meta.hasCommitRules && !todo.m2m.otherMeta?.hasCommitRules) continue;
972
+ const into = commitRuleJoinRowTodos[table] ??= {
973
+ ...todo,
974
+ newRows: [],
975
+ deletedRows: []
976
+ };
977
+ for (const key of ["newRows", "deletedRows"]) for (const r of todo[key]) if (!commitRuleSeen.has(r)) {
978
+ commitRuleSeen.add(r);
979
+ into[key].push(r);
980
+ }
981
+ }
982
+ }
983
+ let entitiesToFlush = await runHooksOnPendingEntities();
984
+ for (const e of entitiesToFlush) allFlushedEntities.add(e);
985
+ let entityTodos = createTodos(entitiesToFlush);
986
+ let joinRowTodos = combineJoinRows(this.#joinRows);
987
+ await runValidation(entityTodos, joinRowTodos, !skipValidation);
988
+ this.#rm.throwIfAnySuppressedTypeErrors();
989
+ if (suppressedDefaultTypeErrors.length > 0) throw suppressedDefaultTypeErrors[0];
990
+ if (Object.keys(entityTodos).length > 0 || Object.keys(joinRowTodos).length > 0) {
991
+ await this.driver.transaction(this, async () => {
992
+ do {
993
+ if (Object.keys(entityTodos).length > 0 || Object.keys(joinRowTodos).length > 0) {
994
+ await this.driver.flush(this, entityTodos, joinRowTodos);
995
+ collectCommitRuleTodos(entityTodos, joinRowTodos);
996
+ }
997
+ pluginManager.afterWrite(entityTodos, joinRowTodos);
998
+ if (this.#rm.hasPendingReactiveQueries()) {
999
+ for (const e of entitiesToFlush) {
1000
+ if (e.isNewEntity && !e.isDeletedEntity) this.#entitiesById.set(e.idTagged, e);
1001
+ getInstanceData(e).resetForRqfLoop();
1002
+ }
1003
+ await this.#fl.allowWrites(async () => {
1004
+ await this.#rm.recalcPendingReactables("reactiveQueries");
1005
+ await this.#rm.recalcPendingReactables("reactables");
1006
+ });
1007
+ now = getNow();
1008
+ entitiesToFlush = await runHooksOnPendingEntities();
1009
+ for (const e of entitiesToFlush) allFlushedEntities.add(e);
1010
+ entityTodos = createTodos(entitiesToFlush);
1011
+ joinRowTodos = combineJoinRows(this.#joinRows);
1012
+ await runValidation(entityTodos, joinRowTodos, true);
1013
+ this.#rm.throwIfAnySuppressedTypeErrors();
1014
+ } else entityTodos = {};
1015
+ } while (Object.keys(entityTodos).length > 0);
1016
+ if (Object.keys(commitRuleTodos).length > 0 || Object.keys(commitRuleJoinRowTodos).length > 0) {
1017
+ for (const e of allFlushedEntities) if (e.isNewEntity && !e.isDeletedEntity) this.#entitiesById.set(e.idTagged, e);
1018
+ await runCommitValidation(commitRuleTodos, commitRuleJoinRowTodos);
1019
+ }
1020
+ await beforeCommit(this.ctx, allFlushedEntities);
1021
+ if (this.mode === "in-memory-writes") throw new InMemoryRollbackError();
1022
+ });
1023
+ await afterCommit(this.ctx, allFlushedEntities);
1024
+ for (const e of allFlushedEntities) {
1025
+ const instanceData = getInstanceData(e);
1026
+ if (e.isNewEntity && !e.isDeletedEntity) this.#entitiesById.set(e.idTagged, e);
1027
+ instanceData.resetAfterFlushed();
1028
+ const { relations } = instanceData;
1029
+ if (relations) {
1030
+ for (const rel of Object.values(relations)) if (rel instanceof AsyncPropertyImpl || rel instanceof LazyFieldImpl) rel.resetAfterFlush();
1031
+ }
1032
+ }
1033
+ for (const joinRow of Object.values(joinRowTodos)) joinRow.resetAfterFlushed();
1034
+ const { mutatedCollections } = getEmInternalApi(this);
1035
+ for (const o2m of mutatedCollections.values()) o2m.resetAddedRemoved();
1036
+ mutatedCollections.clear();
1037
+ this.#dataloaders = {};
1038
+ this.#batchLoaders = {};
1039
+ this.#preloadedRelations = /* @__PURE__ */ new Map();
1040
+ this.#rm.clear();
1041
+ }
1042
+ for (const e of createdThenDeleted) getInstanceData(e).fixupCreatedThenDeleted();
1043
+ this.#merging?.clear();
1044
+ return [...allFlushedEntities].sort((a, b) => getInstanceData(a).entityIndex - getInstanceData(b).entityIndex);
1045
+ } catch (e) {
1046
+ if (e instanceof RecursiveCycleError) {
1047
+ const entity = e.entities[0];
1048
+ for (const meta of getBaseAndSelfMetas(getMetadata(entity))) {
1049
+ const messageFn = meta.config.__data.cycleMessages[e.fieldName] ?? meta.config.__data.cycleMessages[entity[e.fieldName]?.otherFieldName];
1050
+ if (messageFn) throw new ValidationErrors([{
1051
+ entity,
1052
+ message: messageFn(entity, e.entities)
1053
+ }]);
1054
+ }
1055
+ }
1056
+ const detail = e && typeof e === "object" && "detail" in e && typeof e.detail === "string" ? e.detail : void 0;
1057
+ if (e && typeof e === "object" && "constraint" in e && typeof e.constraint === "string") {
1058
+ const message = constraintNameToValidationError[e.constraint];
1059
+ if (message) {
1060
+ const errors = new ValidationErrors(message);
1061
+ if (detail) errors.message = `${message} — ${detail}`;
1062
+ throw errors;
1063
+ }
1064
+ }
1065
+ if (e instanceof InMemoryRollbackError) return [...allFlushedEntities].sort((a, b) => getInstanceData(a).entityIndex - getInstanceData(b).entityIndex);
1066
+ if (detail && e instanceof Error) e.message = `${e.message} — ${detail}`;
1067
+ throw e;
1068
+ } finally {
1069
+ this.#rm.clearSuppressedTypeErrors();
1070
+ this.#fl.releaseLock();
1071
+ resetFactoryCreated();
1072
+ }
1073
+ }
1074
+ /**
1075
+ * A very simple toJSON.
1076
+ *
1077
+ * This is not really meant to be useful, it's to prevent huge/circular output if
1078
+ * an EntityManager accidentally ends up getting logged to something like pino that
1079
+ * over-zealous toJSONs anything it touches.
1080
+ */
1081
+ toJSON() {
1082
+ return `<EntityManager ${this.entities.length}>`;
1083
+ }
1084
+ async refresh(param) {
1085
+ this.#isRefreshing = true;
1086
+ this.#dataloaders = {};
1087
+ this.#batchLoaders = {};
1088
+ this.#preloadedRelations = /* @__PURE__ */ new Map();
1089
+ const deepLoad = param && "deepLoad" in param && param.deepLoad;
1090
+ let todo = param === void 0 ? this.#entitiesArray : Array.isArray(param) ? param : isEntity(param) ? [param] : this.#entitiesArray;
1091
+ const done = /* @__PURE__ */ new Set();
1092
+ while (todo.length > 0) {
1093
+ const copy = [...todo];
1094
+ copy.forEach((e) => done.add(e));
1095
+ todo = [];
1096
+ const entitiesToRefresh = copy.filter((e) => e.idTaggedMaybe && !e.isDeletedEntity);
1097
+ await Promise.all(entitiesToRefresh.map((entity) => {
1098
+ const hint = getRelationEntries(entity).filter(([_, r]) => deepLoad || r.isLoaded).map(([k]) => k);
1099
+ return loadBatchLoader(this, getMetadata(entity), true).load({
1100
+ taggedId: entity.idTagged,
1101
+ hint
1102
+ }).catch(function refresh(err) {
1103
+ throw appendStack(err, /* @__PURE__ */ new Error());
1104
+ });
1105
+ }));
1106
+ const [custom, builtin] = partition(entitiesToRefresh.filter((e) => !getInstanceData(e).isDeletedEntity).flatMap((entity) => getRelations(entity).filter((r) => deepLoad || r.isLoaded)), isCustomRelation);
1107
+ await Promise.all(builtin.map((r) => {
1108
+ if (r.isPreloaded && !r.isLoaded) {
1109
+ r.preload();
1110
+ return;
1111
+ } else return r.load({ forceReload: true });
1112
+ }));
1113
+ await Promise.all(custom.map((r) => r.load({ forceReload: true })));
1114
+ if (deepLoad) todo.push(...builtin.filter((r) => "get" in r).map((r) => r.get).flatMap((value) => Array.isArray(value) ? value : [value]).filter((value) => isEntity(value) && !done.has(value)));
1115
+ }
1116
+ this.#isRefreshing = false;
1117
+ }
1118
+ get numberOfEntities() {
1119
+ return this.entities.length;
1120
+ }
1121
+ findExistingInstance(id) {
1122
+ return this.#entitiesById.get(id);
1123
+ }
1124
+ /**
1125
+ * Takes a result `row` from a custom query and maps the db values into a new-or-existing domain object for that row.
1126
+ *
1127
+ * The `overwriteExisting` controls whether `row`'s values should overwrite the existing fields on
1128
+ * an entity. By default this is true, as we assume the user calling this means they know the DB has
1129
+ * updated values that should be put into the entities. A few internal callers set this to false,
1130
+ * i.e. when we're loading collections and have db results that are potentially stale compared to
1131
+ * the WIP entity state.
1132
+ */
1133
+ hydrate(type, rows, options) {
1134
+ return this.hydrateFromRowData(type, new PojoRowData(rows), options);
1135
+ }
1136
+ /**
1137
+ * Hydrates a query's `RowData`, running any sidecar reads, and always `finalize`s the result.
1138
+ *
1139
+ * This is the internal API for Joist's find/load loaders: `sidecars` is where reads of
1140
+ * non-entity columns (preload aggregates, `_tags`, found-id checks) belong — they must run
1141
+ * before `finalize`, because compaction drops unretained rows — and the `try/finally`
1142
+ * guarantees a failed hydration or sidecar read still releases the result's unretained
1143
+ * buffers instead of pinning them.
1144
+ */
1145
+ hydrateAndFinalize(type, rowData, opts) {
1146
+ try {
1147
+ const entities = this.hydrateFromRowData(type, rowData, opts);
1148
+ opts?.sidecars?.(entities);
1149
+ return entities;
1150
+ } finally {
1151
+ rowData.finalize?.();
1152
+ }
1153
+ }
1154
+ /**
1155
+ * Like {@link hydrate}, but reads rows from a {@link RowData}, i.e. a driver-produced
1156
+ * lazy query result, instead of an array of POJO rows.
1157
+ *
1158
+ * This is an internal API used by Joist's own find loaders (usually via
1159
+ * {@link hydrateAndFinalize}); rows whose entities are kept (newly created or
1160
+ * overwrite-refreshed) are `retain`-ed on the `RowData` so the caller can later `finalize`
1161
+ * (trim/compact) the result.
1162
+ */
1163
+ hydrateFromRowData(type, rowData, options) {
1164
+ const maybeBaseMeta = getMetadata(type);
1165
+ const overwriteExisting = options?.overwriteExisting === true;
1166
+ const count = rowData.rowCount;
1167
+ const entities = new Array(count);
1168
+ for (let i = 0; i < count; i++) {
1169
+ const id = rowData.get(i, "id");
1170
+ const taggedId = id === void 0 || id === null ? fail("No id column was available") : keyToTaggedId(maybeBaseMeta, id);
1171
+ let entity = this.findExistingInstance(taggedId);
1172
+ if (!entity) {
1173
+ const meta = findConcreteMeta(maybeBaseMeta, rowData, i);
1174
+ entity = newEntity(this, asConcreteCstr(meta.cstr), false);
1175
+ const instanceData = getInstanceData(entity);
1176
+ instanceData.rowData = rowData;
1177
+ instanceData.rowIndex = i;
1178
+ rowData.retain?.(i);
1179
+ instanceData.data["id"] = taggedId;
1180
+ this.#doRegister(entity, taggedId, meta, true);
1181
+ } else if (overwriteExisting) {
1182
+ const instanceData = getInstanceData(entity);
1183
+ instanceData.rowData = rowData;
1184
+ instanceData.rowIndex = i;
1185
+ rowData.retain?.(i);
1186
+ const { data } = instanceData;
1187
+ const dataKeys = Object.keys(data);
1188
+ if (dataKeys.length > ("id" in data ? 1 : 0)) {
1189
+ const allFields = getMetadata(entity).allFields;
1190
+ const changedFields = instanceData.isNewEntity ? entity.changes.fieldsWithoutRelations : Object.keys(instanceData.originalData);
1191
+ for (const fieldName of dataKeys) {
1192
+ if (fieldName === "id") continue;
1193
+ data[fieldName] = (allFields[fieldName].serde ?? fail(`Missing serde for ${fieldName}`)).fromRow(rowData, i);
1194
+ if (changedFields.includes(fieldName)) instanceData.markFieldClean(fieldName);
1195
+ }
1196
+ }
1197
+ }
1198
+ entities[i] = entity;
1199
+ }
1200
+ return entities;
1201
+ }
1202
+ touch(entityOrEntities) {
1203
+ for (const entity of toArray(entityOrEntities)) getInstanceData(entity).markTouched();
1204
+ }
1205
+ async recalc(entityOrEntities, reactionName) {
1206
+ const entities = toArray(entityOrEntities).filter((entity) => !entity.isDeletedEntity);
1207
+ if (reactionName !== void 0) {
1208
+ const reactions = entities.map((entity) => {
1209
+ return getBaseAndSelfMetas(getMetadata(entity)).flatMap((meta) => meta.config.__data.reactions).find((reaction) => reaction.name === reactionName) ?? fail(`Reaction '${reactionName}' not found on ${getMetadata(entity).type}`);
1210
+ });
1211
+ await runInTrustedContext(() => Promise.allSettled(reactions.map((reaction, i) => reaction.fn(entities[i], this.ctx))).then(failIfAnyRejected));
1212
+ await this.#rm.recalcPendingReactables("reactables");
1213
+ return;
1214
+ }
1215
+ const relations = entities.flatMap((entity) => Object.values(getMetadata(entity).allFields).filter((f) => "derived" in f && f.derived === "async").map((field) => entity[field.fieldName]));
1216
+ const results = await Promise.allSettled(relations.map((r) => r.load({ forceReload: true })));
1217
+ const relationsPendingAssignedIds = [];
1218
+ const failures = [];
1219
+ results.forEach((result, i) => {
1220
+ if (result.status === "rejected") {
1221
+ if (result.reason instanceof NoIdError) relationsPendingAssignedIds.push(relations[i]);
1222
+ else failures.push(result.reason);
1223
+ }
1224
+ });
1225
+ if (relationsPendingAssignedIds.length > 0) {
1226
+ await this.assignNewIds();
1227
+ (await Promise.allSettled(relationsPendingAssignedIds.map((r) => r.load({ forceReload: true })))).forEach((result) => {
1228
+ if (result.status === "rejected") failures.push(result.reason);
1229
+ });
1230
+ }
1231
+ if (failures.length > 0) throw failures[0];
1232
+ entities.flatMap((entity) => Object.values(getMetadata(entity).allFields).filter((f) => "derived" in f && f.derived === "sync").forEach((field) => {
1233
+ setField(entity, field.fieldName, entity[field.fieldName]);
1234
+ }));
1235
+ await this.#rm.recalcPendingReactables("reactables");
1236
+ }
1237
+ beforeBegin(fn) {
1238
+ this.#hooks.beforeBegin.push(fn);
1239
+ }
1240
+ afterBegin(fn) {
1241
+ this.#hooks.afterBegin.push(fn);
1242
+ }
1243
+ beforeCommit(fn) {
1244
+ this.#hooks.beforeCommit.push(fn);
1245
+ }
1246
+ afterCommit(fn) {
1247
+ this.#hooks.afterCommit.push(fn);
1248
+ }
1249
+ /**
1250
+ * Returns an EntityManager-scoped (i.e. request scoped) data loader.
1251
+ *
1252
+ * @param operation the operation being batched, i.e. `load` or `o2m-load`, to avoid clashing batch keys
1253
+ * across fundamentally different operations
1254
+ * @param batchKey for a given operation, i.e. `load`, a batch key `Author` to batch all Author loads together
1255
+ * @param fn the batch load function, i.e. that will accept all `.load(...)`-d Author ids to load as a single db call
1256
+ * @param opts optional DataLoader options
1257
+ * @returns a DataLoader scoped to the `operation` + `batchKey` combination
1258
+ */
1259
+ getLoader(operation, batchKey, fn, opts) {
1260
+ const loadersForKind = this.#dataloaders[operation] ??= {};
1261
+ return getOrSet(loadersForKind, batchKey, () => new DataLoader(fn, opts));
1262
+ }
1263
+ /**
1264
+ * Like `getLoader`, but returns a `BatchLoader` where all callers in the same tick
1265
+ * share a single `Promise<void>` instead of getting per-key promises.
1266
+ *
1267
+ * The batch function should write results via side channels (e.g. `setPreloadedRelation`).
1268
+ */
1269
+ getBatchLoader(operation, batchKey, fn) {
1270
+ const loadersForKind = this.#batchLoaders[operation] ??= {};
1271
+ return getOrSet(loadersForKind, batchKey, () => new BatchLoader(fn));
1272
+ }
1273
+ toString() {
1274
+ return "EntityManager";
1275
+ }
1276
+ /** Recursively cascades any pending deletions. */
1277
+ async flushDeletes() {
1278
+ let entities = this.#pendingDeletes;
1279
+ if (entities.length === 0) return;
1280
+ this.#pendingDeletes = [];
1281
+ let relationsToCleanup = [];
1282
+ while (entities.length > 0) {
1283
+ const p = entities.flatMap(getCascadeDeleteRelations).map((r) => r.load().then(() => r.maybeCascadeDelete()));
1284
+ await Promise.all(p);
1285
+ const todos = createTodos(entities);
1286
+ await beforeDelete(this.ctx, todos);
1287
+ for (const entity of entities) {
1288
+ const relations = getRelations(entity);
1289
+ const start = relationsToCleanup.length;
1290
+ relationsToCleanup.length += relations.length;
1291
+ for (let i = 0; i < relations.length; i++) relationsToCleanup[start + i] = relations[i];
1292
+ }
1293
+ entities = this.#pendingDeletes;
1294
+ this.#pendingDeletes = [];
1295
+ }
1296
+ await Promise.all(relationsToCleanup.map((r) => r.cleanupOnEntityDeleted()));
1297
+ }
1298
+ setReactionLogging(arg) {
1299
+ this.#rm.setLogger(typeof arg === "boolean" ? arg ? new ReactionLogger() : void 0 : arg);
1300
+ }
1301
+ setFieldLogging(arg) {
1302
+ if (arg instanceof FieldLogger) {
1303
+ this.#fieldLogger = arg;
1304
+ return;
1305
+ }
1306
+ const writeFn = getDefaultWriteFn(this.ctx);
1307
+ if (typeof arg === "boolean") this.#fieldLogger = arg ? new FieldLogger([], writeFn) : noopFieldLogger;
1308
+ else if (typeof arg === "string" || Array.isArray(arg)) {
1309
+ const watching = (Array.isArray(arg) ? arg : [arg]).map((spec) => {
1310
+ const [_, entity, fields, breakpoint] = spec.match(/^([^.!]+)(?:\.([^!]*))?(!)?$/) ?? fail(`Unsupported spec ${spec}`);
1311
+ const fieldNames = fields?.split(",");
1312
+ const meta = getMetadataForType(entity);
1313
+ fieldNames?.forEach((field) => {
1314
+ if (!meta.allFields[field]) throw new Error(`Field ${field} not found on ${entity}`);
1315
+ });
1316
+ return {
1317
+ entity,
1318
+ fieldNames,
1319
+ breakpoint: !!breakpoint
1320
+ };
1321
+ });
1322
+ this.#fieldLogger = new FieldLogger(watching, writeFn);
1323
+ } else throw new Error("Unsupported override for setFieldLogging");
1324
+ }
1325
+ async [Symbol.asyncDispose]() {
1326
+ await this.flush();
1327
+ }
1328
+ /** Returns entities matching the filter using indexed search when available. */
1329
+ filterEntities(cstr, where) {
1330
+ const meta = getMetadata(cstr);
1331
+ const entities = this.#entitiesByTag.get(meta.tagName) ?? [];
1332
+ if (!hasAnyKey(where)) return entities.filter((e) => e instanceof cstr && !e.isDeletedEntity);
1333
+ if (this.#indexManager.shouldIndexType(entities.length)) {
1334
+ this.#indexManager.enableIndexingForType(meta, entities, where);
1335
+ const result = [];
1336
+ for (const e of this.#indexManager.findMatching(meta, entities, where)) if (e instanceof cstr && !e.isDeletedEntity) result.push(e);
1337
+ return result;
1338
+ } else return entities.filter((e) => e instanceof cstr && !e.isDeletedEntity && entityMatches(e, where));
1339
+ }
1340
+ /**
1341
+ * Creates a new EntityManager that shares the same entities as the current one but allows independent changes.
1342
+ *
1343
+ * This is useful for scenarios where you want to:
1344
+ *
1345
+ * - Preload data for use as a cache
1346
+ * - Make speculative changes that may or may not be committed
1347
+ * - Escape a transaction scope
1348
+ *
1349
+ * The fork will:
1350
+ *
1351
+ * - Copy all currently loaded entities to the new EntityManager
1352
+ * - Copy any loaded relation data to keep `.isLoaded` / `.get` state consistent
1353
+ * - Copy and update references to the EntityManager and its entities in the context, which is itself shallowly copied
1354
+ *
1355
+ * The fork will NOT:
1356
+ *
1357
+ * - Copy any pending changes (must call .flush() first)
1358
+ * - Share any changes made in either EntityManager with the other
1359
+ *
1360
+ * @param opts options to control the fork behavior
1361
+ * - allowPendingChanges - allows the em being forked to have pending changes and forces the resulting em to have
1362
+ * `mode` set to "in-memory-writes". Changes to entities in the original em will be copied to the resulting em.
1363
+ * Optional. default: false
1364
+ *
1365
+ * @throws {Error} If called on an EntityManager with pending changes
1366
+ * @returns A new EntityManager with copied entity state
1367
+ */
1368
+ fork(opts = {}) {
1369
+ const { allowPendingChanges = false } = opts;
1370
+ const oldEm = this;
1371
+ const ctx = { ...oldEm.ctx };
1372
+ const newEm = new EntityManager(ctx, { em: oldEm });
1373
+ if (allowPendingChanges) newEm.mode = "in-memory-writes";
1374
+ for (const [tag, entities] of oldEm.#entitiesByTag.entries()) {
1375
+ const baseCstr = getConstructorFromTag(tag);
1376
+ let rows = new Array(entities.length);
1377
+ let i = 0;
1378
+ for (const entity of entities) {
1379
+ const instanceData = entity.__data;
1380
+ if (!allowPendingChanges && instanceData.pendingOperation !== "none") fail("Cannot fork an EntityManager with pending changes");
1381
+ else if (instanceData.isNewEntity) newEm.create(entity.constructor, {});
1382
+ else {
1383
+ rows[i] = createRowFromEntityData(entity);
1384
+ i++;
1385
+ }
1386
+ }
1387
+ if (rows.length !== i) rows = rows.slice(0, i);
1388
+ newEm.hydrate(baseCstr, rows);
1389
+ }
1390
+ function mapEntity(oldEntity) {
1391
+ if (oldEntity.isNewEntity) return newEm.#entitiesById.get(oldEntity.toTaggedString());
1392
+ else return newEm.#entitiesById.get(oldEntity.idTagged);
1393
+ }
1394
+ function mapEntities(v) {
1395
+ if (v === void 0) return void 0;
1396
+ const result = new Array(v.length);
1397
+ for (let i = 0; i < v.length; i++) result[i] = mapEntity(v[i]);
1398
+ return result;
1399
+ }
1400
+ if (allowPendingChanges) for (const oldEntity of oldEm.entities) {
1401
+ const oldInstanceData = oldEntity.__data;
1402
+ if (!(oldInstanceData.isNewEntity || oldInstanceData.isDirtyEntity)) continue;
1403
+ const { originalData: oldOriginalData, data: oldData } = oldInstanceData;
1404
+ const newInstanceData = mapEntity(oldEntity).__data;
1405
+ const { data: newData } = newInstanceData;
1406
+ const maybeEntity = (value) => isEntity(value) ? mapEntity(value) : value;
1407
+ const fields = Object.keys(oldEntity.isNewEntity ? oldData : oldOriginalData);
1408
+ for (const field of fields) {
1409
+ if (field in oldOriginalData) newInstanceData.markFieldDirty(field, maybeEntity(oldOriginalData[field]));
1410
+ newData[field] = maybeEntity(oldData[field]);
1411
+ }
1412
+ }
1413
+ for (const oldEntity of oldEm.entities) {
1414
+ const newEntity = mapEntity(oldEntity);
1415
+ if (oldEntity.isDeletedEntity) {
1416
+ newEntity.__data.markDeleted();
1417
+ continue;
1418
+ }
1419
+ const { relations } = oldEntity.__data;
1420
+ if (!relations) continue;
1421
+ for (const [field, relation] of Object.entries(relations)) {
1422
+ if (!("import" in relation)) continue;
1423
+ if (oldEntity.isNewEntity) {
1424
+ const oldValue = relation.get;
1425
+ if (oldValue === void 0) continue;
1426
+ if (Array.isArray(oldValue) && oldValue.length === 0) continue;
1427
+ const newValue = Array.isArray(oldValue) ? mapEntities(oldValue) : mapEntity(oldValue);
1428
+ delete newEntity.__data.data[field];
1429
+ newEntity[field].setFromOpts(newValue);
1430
+ } else if ("_isLoaded" in relation ? relation._isLoaded : relation.isLoaded) newEntity[field].import(relation, mapEntity, mapEntities);
1431
+ }
1432
+ }
1433
+ for (const [key, value] of Object.entries(ctx)) if (isEntity(value) && value.em === oldEm) ctx[key] = mapEntity(value);
1434
+ else if (value === oldEm) ctx[key] = newEm;
1435
+ return newEm;
1436
+ }
1437
+ importEntity(source, hint, normalizedHint) {
1438
+ if (source.isNewEntity) fail("cannot import new entities");
1439
+ if (source.isDeletedEntity) fail("cannot import deleted entities");
1440
+ if (source.isDirtyEntity) fail("cannot import dirty entities");
1441
+ hint ??= {};
1442
+ if (!normalizedHint) {
1443
+ assertLoaded(source, hint);
1444
+ normalizedHint = deepNormalizeHint(hint);
1445
+ }
1446
+ if (source.em === this) return source;
1447
+ const meta = getMetadata(source);
1448
+ let result = this.#entitiesById.get(source.idTagged);
1449
+ if (!result) {
1450
+ const meta = getMetadata(source);
1451
+ const row = createRowFromEntityData(source);
1452
+ result = this.hydrate(getBaseMeta(meta).cstr, [row])[0];
1453
+ }
1454
+ for (const [fieldName, subHint] of Object.entries(normalizedHint)) {
1455
+ const field = meta.allFields[fieldName];
1456
+ const relationOrProp = result[fieldName];
1457
+ if (!field) {
1458
+ let loadHint = relationOrProp.loadHint ?? fail(`${source}.${fieldName} cannot be imported as it has no loadHint`);
1459
+ this.importEntity(source, loadHint);
1460
+ } else if ("import" in relationOrProp) relationOrProp.import(source[fieldName], (e) => this.importEntity(e, subHint, subHint), (entities) => {
1461
+ if (entities === void 0) return void 0;
1462
+ const result = new Array(entities.length);
1463
+ for (let i = 0; i < entities.length; i++) result[i] = this.importEntity(entities[i], subHint, subHint);
1464
+ return result;
1465
+ });
1466
+ }
1467
+ return result;
1468
+ }
1469
+ addPlugin(plugin) {
1470
+ getEmInternalApi(this).pluginManager.addPlugin(plugin);
1471
+ }
1472
+ getPlugins() {
1473
+ return getEmInternalApi(this).pluginManager.plugins;
1474
+ }
1475
+ get isRefreshing() {
1476
+ return this.#isRefreshing;
1477
+ }
1478
+ get isFlushing() {
1479
+ return this.#fl.isFlushing;
1480
+ }
1481
+ /** Creates a new `type` and marks it as loaded, i.e. we know its collections are all safe to access in memory. */
1482
+ #doCreate(type, opts, partial) {
1483
+ const entity = newEntity(this, type, true);
1484
+ const meta = getMetadata(type);
1485
+ const counter = this.#createCounter ??= /* @__PURE__ */ new Map();
1486
+ const i = (counter.get(meta.tagName) ?? 0) + 1;
1487
+ counter.set(meta.tagName, i);
1488
+ getInstanceData(entity).createId = String(i);
1489
+ this.#doRegister(entity, opts.id);
1490
+ const baseMeta = getBaseMeta(getMetadata(entity));
1491
+ if (baseMeta.timestampFields) this.#assignTimestamps(entity, baseMeta);
1492
+ if (baseMeta.inheritanceType === "sti") setStiDiscriminatorValue(baseMeta, entity);
1493
+ getEmInternalApi(this)?.fieldLogger.logCreate(entity);
1494
+ setOpts(entity, opts, {
1495
+ partial,
1496
+ calledFromConstructor: true
1497
+ });
1498
+ if (!this.fakeInstance) setSyncDefaults(entity);
1499
+ this.#rm.queueAllDownstreamFields(entity, "created");
1500
+ return entity;
1501
+ }
1502
+ #assignTimestamps(entity, baseMeta) {
1503
+ const { createdAt, updatedAt } = baseMeta.timestampFields ?? {};
1504
+ const { data } = getInstanceData(entity);
1505
+ const now = /* @__PURE__ */ new Date();
1506
+ if (createdAt) data[createdAt] = baseMeta.fields[createdAt].serde.mapFromNow(now);
1507
+ if (updatedAt) data[updatedAt] = baseMeta.fields[updatedAt].serde.mapFromNow(now);
1508
+ }
1509
+ /** Registers a newly-instantiated entity with our EntityManager; only called by #doCreate and hydrate. */
1510
+ #doRegister(entity, id, meta, skipDuplicateCheck = false) {
1511
+ const maybeId = id ?? entity.idTaggedMaybe;
1512
+ if (maybeId) {
1513
+ if (!skipDuplicateCheck && this.findExistingInstance(maybeId) !== void 0) throw new Error(`Entity ${entity} has a duplicate instance already loaded`);
1514
+ this.#entitiesById.set(maybeId, entity);
1515
+ } else this.#entitiesById.set(entity.toTaggedString(), entity);
1516
+ getInstanceData(entity).entityIndex = this.#entitiesArray.length;
1517
+ this.#entitiesArray.push(entity);
1518
+ meta ??= getMetadata(entity);
1519
+ const set = this.#entitiesByTag.get(meta.tagName) ?? [];
1520
+ if (set.length === 0) this.#entitiesByTag.set(meta.tagName, set);
1521
+ set.push(entity);
1522
+ if (this.#entitiesArray.length >= this.entityLimit) {
1523
+ const topTypes = [...this.#entitiesByTag.entries()].map(([tag, entities]) => ({
1524
+ tag,
1525
+ count: entities.length
1526
+ })).sort((a, b) => b.count - a.count).slice(0, 3).map(({ tag, count }) => `${tag}=${count}`).join(", ");
1527
+ throw new Error(`More than ${this.entityLimit} entities have been instantiated (top entities: ${topTypes})`);
1528
+ }
1529
+ }
1530
+ };
1800
1531
  function getEmInternalApi(em) {
1801
- return em["__api"];
1532
+ return em["__api"];
1802
1533
  }
1803
- let defaultEntityLimit = 50_000;
1534
+ let defaultEntityLimit = 5e4;
1804
1535
  function getDefaultEntityLimit() {
1805
- return defaultEntityLimit;
1536
+ return defaultEntityLimit;
1806
1537
  }
1807
1538
  function setDefaultEntityLimit(limit) {
1808
- defaultEntityLimit = limit;
1539
+ defaultEntityLimit = limit;
1809
1540
  }
1810
1541
  function resetDefaultEntityLimit() {
1811
- defaultEntityLimit = 50_000;
1542
+ defaultEntityLimit = 5e4;
1812
1543
  }
1813
1544
  function isKey(k) {
1814
- return typeof k === "string";
1545
+ return typeof k === "string";
1815
1546
  }
1816
1547
  /** Compares `a` to `b`, where `b` might be an id. */
1817
1548
  function sameEntity(a, b) {
1818
- if (a === b) {
1819
- return true;
1820
- }
1821
- // Throw in null handling for findWithNewOrChanged ambivalence
1822
- if (a === undefined || b === undefined || a === null || b === null) {
1823
- return (a === undefined || a === null) && (b === undefined || b === null);
1824
- }
1825
- // If both are entities, return if they are the same reference
1826
- if ((0, Entity_1.isEntity)(a) && (0, Entity_1.isEntity)(b)) {
1827
- return a === b;
1828
- }
1829
- // Otherwise check by ID
1830
- const aId = (0, Entity_1.isEntity)(a) ? a.idTaggedMaybe : a;
1831
- const bId = (0, Entity_1.isEntity)(b) ? b.idTaggedMaybe : b;
1832
- return aId === bId;
1549
+ if (a === b) return true;
1550
+ if (a === void 0 || b === void 0 || a === null || b === null) return (a === void 0 || a === null) && (b === void 0 || b === null);
1551
+ if (isEntity(a) && isEntity(b)) return a === b;
1552
+ return (isEntity(a) ? a.idTaggedMaybe : a) === (isEntity(b) ? b.idTaggedMaybe : b);
1833
1553
  }
1834
1554
  /** Compares the value `a` to `b`, with handling of new entities w/o ids assigned yet. */
1835
1555
  function sameReference(a, b) {
1836
- return sameEntity((0, index_1.isLoadedReference)(a) ? a.get : a.idTaggedMaybe, (0, index_1.isLoadedReference)(b) ? b.get : b.idTaggedMaybe);
1556
+ return sameEntity(isLoadedReference(a) ? a.get : a.idTaggedMaybe, isLoadedReference(b) ? b.get : b.idTaggedMaybe);
1837
1557
  }
1838
1558
  /** Thrown by `findOneOrFail`, 'load' & 'loadAll' if an entity is not found. */
1839
- class NotFoundError extends Error {
1840
- }
1841
- exports.NotFoundError = NotFoundError;
1559
+ var NotFoundError = class extends Error {};
1842
1560
  /** Thrown by `findOne` and `findOneOrFail` if more than one entity is found. */
1843
- class TooManyError extends Error {
1844
- constructor(message) {
1845
- super(message);
1846
- }
1847
- }
1848
- exports.TooManyError = TooManyError;
1561
+ var TooManyError = class extends Error {
1562
+ constructor(message) {
1563
+ super(message);
1564
+ }
1565
+ };
1849
1566
  /**
1850
- * For the entities currently in `todos`, find any reactive validation rules that point
1851
- * from the currently-changed entities back to each rule's originally-defined-in entity,
1852
- * and ensure those entities are added to `todos`.
1853
- */
1854
- async function validateReactiveRules(em, logger, todos, joinRowTodos) {
1855
- logger?.logStartingValidate(em, todos);
1856
- // Use a map of rule -> Set<Entity> so that we only invoke a rule once per entity,
1857
- // even if it was triggered by multiple changed fields.
1858
- const fns = new Map();
1859
- // From the given triggered entities, follow the entity's ReactiveRule back
1860
- // to the reactive rules that need ran, and queue them in the `fn` map
1861
- async function followAndQueue(triggered, rule) {
1862
- if (triggered.length === 0)
1863
- return;
1864
- const found = (await (0, reactiveHints_1.followReverseHint)(rule.name, triggered, rule.path))
1865
- .filter((entity) => !entity.isDeletedEntity)
1866
- .filter((e) => e instanceof rule.cstr);
1867
- let entities = fns.get(rule.fn);
1868
- if (!entities) {
1869
- entities = new Set();
1870
- fns.set(rule.fn, entities);
1871
- }
1872
- logger?.logWalked(triggered, rule, found, "validate");
1873
- found.forEach((entity) => {
1874
- entities.add(entity);
1875
- });
1876
- }
1877
- const p1 = Object.values(todos).flatMap((todo) => {
1878
- const entities = [...todo.inserts, ...todo.updates, ...todo.deletes];
1879
- // Find each statically-declared reactive rule for the given entity type
1880
- const rules = todo.metadata.reactiveRules;
1881
- return rules.map((rule) => {
1882
- // Of all changed entities of this type, how many specifically trigger this rule?
1883
- const triggered = entities.filter((e) => {
1884
- // If the rule is for a different subtype, skip it
1885
- if (!(e instanceof rule.source))
1886
- return false;
1887
- // Any new-or-deleted entity fires every rule (reactiveRules has already filtered out read-only)
1888
- if (e.isNewEntity || e.isDeletedEntity)
1889
- return true;
1890
- // Otherwise see if the changed fields overlaps with the rule's fields
1891
- const changedFields = e.changes.fieldsWithoutRelations;
1892
- for (const field of changedFields) {
1893
- if (rule.fields.includes(field))
1894
- return true;
1895
- }
1896
- return false;
1897
- });
1898
- // From these "triggered" entities, queue the "found"/owner entity to rerun this rule
1899
- return followAndQueue(triggered, rule);
1900
- });
1901
- });
1902
- const p2 = Object.values(joinRowTodos).flatMap((todo) => {
1903
- // For enum m2ms the columns include the enum's numeric id, so keep only the entity values.
1904
- const entities = [...todo.newRows, ...todo.deletedRows].flatMap((jr) => Object.values(jr.columns)).filter(Entity_1.isEntity);
1905
- // The owning-entity side (applies to both entity-to-entity and entity-to-enum m2ms).
1906
- const a = todo.m2m.meta
1907
- .reactiveRules.filter((rule) => rule.fields.includes(todo.m2m.fieldName))
1908
- .map((rule) => {
1909
- const triggered = entities.filter((e) => e instanceof todo.m2m.meta.cstr);
1910
- return followAndQueue(triggered, rule);
1911
- });
1912
- // The "other" side only exists for entity-to-entity m2ms; enums have no reverse field.
1913
- const { otherMeta, otherFieldName } = todo.m2m;
1914
- const b = otherMeta
1915
- ? otherMeta
1916
- .reactiveRules.filter((rule) => rule.fields.includes(otherFieldName))
1917
- .map((rule) => {
1918
- const triggered = entities.filter((e) => e instanceof otherMeta.cstr);
1919
- return followAndQueue(triggered, rule);
1920
- })
1921
- : [];
1922
- return [...a, ...b];
1923
- });
1924
- (0, utils_1.failIfAnyRejected)(await Promise.allSettled([...p1, ...p2]));
1925
- // Now that we've found the fn+entities to run, run them and collect any errors
1926
- const p3 = [...fns.entries()].flatMap(([fn, entities]) => [...entities].map(async (entity) => coerceError(entity, await fn(entity))));
1927
- const errors = (0, utils_1.failIfAnyRejected)(await Promise.allSettled(p3)).flat();
1928
- if (errors.length > 0) {
1929
- throw new index_1.ValidationErrors(errors);
1930
- }
1567
+ * For the entities currently in `todos`, find any reactive validation rules that point
1568
+ * from the currently-changed entities back to each rule's originally-defined-in entity,
1569
+ * and ensure those entities are added to `todos`.
1570
+ */
1571
+ async function validateReactiveRules(em, logger, todos, joinRowTodos, getRules = (meta) => meta.reactiveRules) {
1572
+ logger.logStartingValidate(em, todos);
1573
+ const fns = /* @__PURE__ */ new Map();
1574
+ const walks = [];
1575
+ async function followAndQueue(triggered, rule) {
1576
+ if (triggered.length === 0) return;
1577
+ const found = (await followReverseHint(rule.name, triggered, rule.path)).filter((entity) => !entity.isDeletedEntity).filter((e) => e instanceof rule.cstr);
1578
+ let entities = fns.get(rule.fn);
1579
+ if (!entities) {
1580
+ entities = /* @__PURE__ */ new Set();
1581
+ fns.set(rule.fn, entities);
1582
+ }
1583
+ walks.push({
1584
+ todo: triggered,
1585
+ r: rule,
1586
+ entities: found
1587
+ });
1588
+ found.forEach((entity) => {
1589
+ entities.add(entity);
1590
+ });
1591
+ }
1592
+ const p1 = Object.values(todos).flatMap((todo) => {
1593
+ const rules = getRules(todo.metadata);
1594
+ if (rules.length === 0) return [];
1595
+ const entities = [
1596
+ ...todo.inserts,
1597
+ ...todo.updates,
1598
+ ...todo.deletes
1599
+ ];
1600
+ return rules.map((rule) => {
1601
+ return followAndQueue(entities.filter((e) => {
1602
+ if (!(e instanceof rule.source)) return false;
1603
+ if (e.isNewEntity || e.isDeletedEntity) return true;
1604
+ const { originalData } = getInstanceData(e);
1605
+ for (const field of rule.fields) if (field in originalData) return true;
1606
+ return false;
1607
+ }), rule);
1608
+ });
1609
+ });
1610
+ const p2 = Object.values(joinRowTodos).flatMap((todo) => {
1611
+ const entities = [...todo.newRows, ...todo.deletedRows].flatMap((jr) => Object.values(jr.columns)).filter(isEntity);
1612
+ const a = getRules(todo.m2m.meta).filter((rule) => rule.fields.includes(todo.m2m.fieldName)).map((rule) => {
1613
+ return followAndQueue(entities.filter((e) => e instanceof todo.m2m.meta.cstr), rule);
1614
+ });
1615
+ const { otherMeta, otherFieldName } = todo.m2m;
1616
+ const b = otherMeta ? getRules(otherMeta).filter((rule) => rule.fields.includes(otherFieldName)).map((rule) => {
1617
+ return followAndQueue(entities.filter((e) => e instanceof otherMeta.cstr), rule);
1618
+ }) : [];
1619
+ return [...a, ...b];
1620
+ });
1621
+ failIfAnyRejected(await Promise.allSettled([...p1, ...p2]));
1622
+ logger.logWalks(walks, "validate");
1623
+ const p3 = [...fns.entries()].flatMap(([fn, entities]) => [...entities].map(async (entity) => coerceError(entity, await fn(entity))));
1624
+ const errors = failIfAnyRejected(await Promise.allSettled(p3)).flat();
1625
+ if (errors.length > 0) throw new ValidationErrors(errors);
1931
1626
  }
1932
- // Run *non-reactive* (those with `fields: undefined`) rules of explicitly mutated entities,
1933
- // because even for reactive validations on mutated entities, we defer to addReactiveValidations
1934
- // to mark only the rules that need to run.
1935
- async function validateSimpleRules(todos) {
1936
- const p = Object.values(todos).flatMap(({ inserts, updates }) => {
1937
- return [...inserts, ...updates]
1938
- .filter((e) => !e.isDeletedEntity)
1939
- .flatMap((entity) => {
1940
- const rules = (0, index_1.getBaseAndSelfMetas)((0, index_1.getMetadata)(entity)).flatMap((m) => m.config.__data.rules);
1941
- return rules
1942
- .filter((rule) => rule.hint === undefined)
1943
- .flatMap(async ({ fn }) => coerceError(entity, await fn(entity)));
1944
- });
1945
- });
1946
- const errors = (0, utils_1.failIfAnyRejected)(await Promise.allSettled(p)).flat();
1947
- if (errors.length > 0) {
1948
- throw new index_1.ValidationErrors(errors);
1949
- }
1627
+ async function validateSimpleRules(todos, getRules = (config) => config.rules) {
1628
+ let p = void 0;
1629
+ for (const todoKey in todos) {
1630
+ const { inserts, updates } = todos[todoKey];
1631
+ for (const entities of [inserts, updates]) for (const entity of entities) {
1632
+ if (entity.isDeletedEntity) continue;
1633
+ for (const m of getBaseAndSelfMetas(getMetadata(entity))) for (const rule of getRules(m.config.__data)) {
1634
+ if (rule.hint !== void 0) continue;
1635
+ (p ??= []).push(invokeRule(entity, rule.fn));
1636
+ }
1637
+ }
1638
+ }
1639
+ if (!p) return;
1640
+ const errors = failIfAnyRejected(await Promise.allSettled(p)).flat();
1641
+ if (errors.length > 0) throw new ValidationErrors(errors);
1642
+ }
1643
+ /** Invokes a single validation rule, coercing its result/sync throws into a promise. */
1644
+ async function invokeRule(entity, fn) {
1645
+ return coerceError(entity, await fn(entity));
1950
1646
  }
1951
1647
  function driverBeforeBegin(em, txn) {
1952
- return Promise.all(getEmInternalApi(em).hooks.beforeBegin.map((fn) => fn(em, txn)));
1648
+ return Promise.all(getEmInternalApi(em).hooks.beforeBegin.map((fn) => fn(em, txn)));
1953
1649
  }
1954
1650
  function driverAfterBegin(em, txn) {
1955
- return Promise.all(getEmInternalApi(em).hooks.afterBegin.map((fn) => fn(em, txn)));
1651
+ return Promise.all(getEmInternalApi(em).hooks.afterBegin.map((fn) => fn(em, txn)));
1956
1652
  }
1957
1653
  function driverBeforeCommit(em, txn) {
1958
- return Promise.all(getEmInternalApi(em).hooks.beforeCommit.map((fn) => fn(em, txn)));
1654
+ return Promise.all(getEmInternalApi(em).hooks.beforeCommit.map((fn) => fn(em, txn)));
1959
1655
  }
1960
1656
  function driverAfterCommit(em, txn) {
1961
- return Promise.all(getEmInternalApi(em).hooks.afterCommit.map((fn) => fn(em, txn)));
1657
+ return Promise.all(getEmInternalApi(em).hooks.afterCommit.map((fn) => fn(em, txn)));
1962
1658
  }
1963
1659
  async function runHookOnTodos(ctx, hook, todos, keys) {
1964
- const entities = Object.values(todos).flatMap((todo) => {
1965
- return keys.flatMap((k) => todo[k].filter((e) => k === "deletes" || !e.isDeletedEntity));
1966
- });
1967
- return runHook(ctx, hook, entities);
1660
+ let entities = void 0;
1661
+ for (const todoKey in todos) {
1662
+ const todo = todos[todoKey];
1663
+ if (!metaHasHook(todo.metadata, hook)) continue;
1664
+ for (const k of keys) for (const e of todo[k]) {
1665
+ if (k !== "deletes" && e.isDeletedEntity) continue;
1666
+ (entities ??= []).push(e);
1667
+ }
1668
+ }
1669
+ if (entities) return runHook(ctx, hook, entities);
1670
+ }
1671
+ /** Returns whether `meta`'s base/self/sub hierarchy has any `hook` functions registered. */
1672
+ function metaHasHook(meta, hook) {
1673
+ for (const m of getBaseSelfAndSubMetas(meta)) if (m.config.__data.hooks[hook].length > 0) return true;
1674
+ return false;
1968
1675
  }
1969
1676
  async function runHook(ctx, hook, entities) {
1970
- const p = entities.flatMap((entity) => {
1971
- const hookFns = (0, index_1.getBaseAndSelfMetas)((0, index_1.getMetadata)(entity)).flatMap((m) => m.config.__data.hooks[hook]);
1972
- // Use an explicit `async` here to ensure all hooks are promises, i.e. so that a non-promise
1973
- // hook blowing up doesn't orphan the others .
1974
- return hookFns.map(async (fn) => fn(entity, ctx));
1975
- });
1976
- // Use `allSettled` so that even if 1 hook blows up, we don't orphan other hooks mid-flush
1977
- // (causes weird errors when/if they try to access the EntityManager that has "moved on")
1978
- const results = await Promise.allSettled(p);
1979
- (0, utils_1.failIfAnyRejected)(results);
1677
+ let p = void 0;
1678
+ for (const entity of entities) for (const m of getBaseAndSelfMetas(getMetadata(entity))) for (const fn of m.config.__data.hooks[hook]) (p ??= []).push(invokeHook(fn, entity, ctx));
1679
+ if (!p) return;
1680
+ const results = await Promise.allSettled(p);
1681
+ failIfAnyRejected(results);
1682
+ }
1683
+ /** Invokes a single hook fn, coercing sync throws into rejections. */
1684
+ async function invokeHook(fn, entity, ctx) {
1685
+ return fn(entity, ctx);
1980
1686
  }
1981
1687
  function beforeDelete(ctx, todos) {
1982
- return runHookOnTodos(ctx, "beforeDelete", todos, ["deletes"]);
1688
+ return runHookOnTodos(ctx, "beforeDelete", todos, ["deletes"]);
1983
1689
  }
1984
1690
  function beforeFlush(ctx, todos) {
1985
- return runHookOnTodos(ctx, "beforeFlush", todos, ["inserts", "updates"]);
1691
+ return runHookOnTodos(ctx, "beforeFlush", todos, ["inserts", "updates"]);
1986
1692
  }
1987
1693
  function beforeCreate(ctx, todos) {
1988
- return runHookOnTodos(ctx, "beforeCreate", todos, ["inserts"]);
1694
+ return runHookOnTodos(ctx, "beforeCreate", todos, ["inserts"]);
1989
1695
  }
1990
1696
  function beforeUpdate(ctx, todos) {
1991
- return runHookOnTodos(ctx, "beforeUpdate", todos, ["updates"]);
1697
+ return runHookOnTodos(ctx, "beforeUpdate", todos, ["updates"]);
1992
1698
  }
1993
1699
  function afterValidation(ctx, todos) {
1994
- return runHookOnTodos(ctx, "afterValidation", todos, ["inserts", "updates"]);
1700
+ return runHookOnTodos(ctx, "afterValidation", todos, ["inserts", "updates"]);
1995
1701
  }
1996
1702
  /** Collects changed entities from flush todos, i.e. m2m endpoint entities. */
1997
1703
  function entitiesFromTodos(entityTodos, joinRowTodos) {
1998
- const entities = new Set();
1999
- for (const todo of Object.values(entityTodos)) {
2000
- [...todo.inserts, ...todo.updates, ...todo.deletes].forEach((entity) => entities.add(entity));
2001
- }
2002
- for (const todo of Object.values(joinRowTodos)) {
2003
- [...todo.newRows, ...todo.deletedRows].forEach((row) => {
2004
- // For enum m2ms, a column value is the enum's numeric id rather than an entity.
2005
- Object.values(row.columns).forEach((value) => {
2006
- if ((0, Entity_1.isEntity)(value))
2007
- entities.add(value);
2008
- });
2009
- });
2010
- }
2011
- return [...entities];
1704
+ const entities = /* @__PURE__ */ new Set();
1705
+ for (const todo of Object.values(entityTodos)) for (const list of [
1706
+ todo.inserts,
1707
+ todo.updates,
1708
+ todo.deletes
1709
+ ]) for (const entity of list) entities.add(entity);
1710
+ for (const todo of Object.values(joinRowTodos)) for (const rows of [todo.newRows, todo.deletedRows]) for (const row of rows) for (const value of Object.values(row.columns)) if (isEntity(value)) entities.add(value);
1711
+ return [...entities];
2012
1712
  }
2013
1713
  function beforeCommit(ctx, entities) {
2014
- return runHook(ctx, "beforeCommit", [...entities]);
1714
+ return runHook(ctx, "beforeCommit", [...entities]);
2015
1715
  }
2016
1716
  function afterCommit(ctx, entities) {
2017
- return runHook(ctx, "afterCommit", [...entities]);
1717
+ return runHook(ctx, "afterCommit", [...entities]);
2018
1718
  }
2019
1719
  /** Given a validation rule result `maybeError`, returns a canonical `ValidationError[]`. */
2020
1720
  function coerceError(entity, maybeError) {
2021
- if (maybeError === undefined) {
2022
- return [];
2023
- }
2024
- else if (typeof maybeError === "string") {
2025
- return [{ entity, message: maybeError }];
2026
- }
2027
- else if (Array.isArray(maybeError)) {
2028
- return maybeError.map((e) => {
2029
- if (typeof e === "string") {
2030
- return { entity, message: e };
2031
- }
2032
- else {
2033
- return { entity, ...e };
2034
- }
2035
- });
2036
- }
2037
- else {
2038
- return [{ entity, ...maybeError }];
2039
- }
1721
+ if (maybeError === void 0) return [];
1722
+ else if (typeof maybeError === "string") return [{
1723
+ entity,
1724
+ message: maybeError
1725
+ }];
1726
+ else if (Array.isArray(maybeError)) return maybeError.map((e) => {
1727
+ if (typeof e === "string") return {
1728
+ entity,
1729
+ message: e
1730
+ };
1731
+ else return {
1732
+ entity,
1733
+ ...e
1734
+ };
1735
+ });
1736
+ else return [{
1737
+ entity,
1738
+ ...maybeError
1739
+ }];
2040
1740
  }
2041
1741
  /** Evaluates each (non-async) derived field to see if it's value has changed. */
2042
1742
  function recalcSynchronousDerivedFields(todos) {
2043
- const entities = Object.values(todos)
2044
- .flatMap((todo) => [...todo.inserts, ...todo.updates])
2045
- .filter((e) => !e.isDeletedEntity);
2046
- const derivedFieldsByMeta = new Map([...new Set(entities.map(index_1.getMetadata))].map((m) => {
2047
- return [
2048
- m,
2049
- Object.values(m.allFields)
2050
- .filter((f) => (f.kind === "primitive" || f.kind === "enum") && f.derived === "sync")
2051
- .map((f) => f.fieldName),
2052
- ];
2053
- }));
2054
- for (const entity of entities) {
2055
- const derivedFields = derivedFieldsByMeta.get((0, index_1.getMetadata)(entity)) || [];
2056
- derivedFields.forEach((fieldName) => {
2057
- // setField will intelligently mark/not mark the field as dirty.
2058
- (0, fields_1.setField)(entity, fieldName, entity[fieldName]);
2059
- });
2060
- }
1743
+ for (const todoKey in todos) {
1744
+ const todo = todos[todoKey];
1745
+ for (const entities of [todo.inserts, todo.updates]) for (const entity of entities) {
1746
+ if (entity.isDeletedEntity) continue;
1747
+ for (const fieldName of getMetadata(entity).syncDerivedFields) setField(entity, fieldName, entity[fieldName]);
1748
+ }
1749
+ }
2061
1750
  }
2062
1751
  /** Recursively crawls through `entity`, with the given populate `deep` hint, and adds anything found to `found`. */
2063
- async function crawl(found,
2064
- // We keep skipMap separated out, instead of tuple-izing `found`, so that `found`
2065
- // can be a set that is cheap to insert & check for duplicates.
2066
- skipMap, entities, deep, opts = {}) {
2067
- const { skipIf = () => false } = opts ?? {};
2068
- const skip = (0, index_1.deepNormalizeHint)(opts.skip ?? {});
2069
- // If we're passed `skip = { author: "publisher" }`, which is asking to "don't set `author.publisher`", then
2070
- // `author` will technically be a key in the "skip hint", but it's only there for us to hop down into.
2071
- // So we actually _don't_ skip any fields that have sub-hints, b/c it's the sub-hints themselves we want to skip.
2072
- const skipFields = Object.keys(skip).filter((key) => Object.keys(skip[key]).length === 0);
2073
- // It's tempting to check `!found.has(entity)` here, but that would short-circuit later crawling the
2074
- // entity at a potentially different point in the graph, i.e. a deep hint like:
2075
- //
2076
- // `{ comment: parent, books: { author: "publisher" } }`
2077
- //
2078
- // If the `comment.parent` was the same `Author` as a `books.author`, but we "crawled it first", we'd miss
2079
- // crawling through the author a 2nd time and cloning the publisher.
2080
- const entitiesToClone = entities.filter((e) => !skipIf(e));
2081
- for (const entity of entitiesToClone) {
2082
- found.add(entity);
2083
- skipMap.set(entity, skipFields);
2084
- }
2085
- await Promise.all(entitiesToClone.flatMap((entity) => Object.entries(adaptHint(deep)).map(async ([relationName, nested]) => {
2086
- const relation = entity[relationName];
2087
- // If we're using a deep `skip` hint, drill in to it
2088
- const _opts = { ...opts, skip: skip[relationName] };
2089
- if (relation instanceof index_1.OneToManyCollection) {
2090
- const relatedEntities = await relation.load();
2091
- await crawl(found, skipMap, relatedEntities, nested, _opts);
2092
- }
2093
- else if (relation instanceof relations_1.OneToOneReferenceImpl) {
2094
- const related = await relation.load();
2095
- if (related) {
2096
- await crawl(found, skipMap, [related], nested, _opts);
2097
- }
2098
- }
2099
- else if (relation instanceof relations_1.ManyToOneReferenceImpl) {
2100
- const related = await relation.load();
2101
- if (related) {
2102
- await crawl(found, skipMap, [related], nested, _opts);
2103
- }
2104
- }
2105
- else if (relation instanceof relations_1.ReactiveReferenceImpl) {
2106
- const relatedEntities = await relation.load();
2107
- await crawl(found, skipMap, relatedEntities, nested, _opts);
2108
- }
2109
- else {
2110
- (0, utils_1.fail)(`Uncloneable relation: ${relationName}`);
2111
- }
2112
- })));
1752
+ async function crawl(found, skipMap, entities, deep, opts = {}) {
1753
+ const { skipIf = () => false } = opts ?? {};
1754
+ const skip = deepNormalizeHint(opts.skip ?? {});
1755
+ const skipFields = Object.keys(skip).filter((key) => Object.keys(skip[key]).length === 0);
1756
+ const entitiesToClone = entities.filter((e) => !skipIf(e));
1757
+ for (const entity of entitiesToClone) {
1758
+ found.add(entity);
1759
+ skipMap.set(entity, skipFields);
1760
+ }
1761
+ await Promise.all(entitiesToClone.flatMap((entity) => Object.entries(adaptHint(deep)).map(async ([relationName, nested]) => {
1762
+ const relation = entity[relationName];
1763
+ const _opts = {
1764
+ ...opts,
1765
+ skip: skip[relationName]
1766
+ };
1767
+ if (relation instanceof OneToManyCollection) await crawl(found, skipMap, await relation.load(), nested, _opts);
1768
+ else if (relation instanceof OneToOneReferenceImpl) {
1769
+ const related = await relation.load();
1770
+ if (related) await crawl(found, skipMap, [related], nested, _opts);
1771
+ } else if (relation instanceof ManyToOneReferenceImpl) {
1772
+ const related = await relation.load();
1773
+ if (related) await crawl(found, skipMap, [related], nested, _opts);
1774
+ } else if (relation instanceof ReactiveReferenceImpl) await crawl(found, skipMap, await relation.load(), nested, _opts);
1775
+ else fail(`Uncloneable relation: ${relationName}`);
1776
+ })));
2113
1777
  }
2114
1778
  /** Takes our flexible string or array or hash load hint and makes it always a hash. */
2115
1779
  function adaptHint(hint) {
2116
- if (typeof hint === "string") {
2117
- return { [hint]: {} };
2118
- }
2119
- else if (Array.isArray(hint)) {
2120
- return Object.fromEntries(hint.map((relation) => [relation, {}]));
2121
- }
2122
- else if (hint) {
2123
- return hint;
2124
- }
2125
- else {
2126
- return {};
2127
- }
1780
+ if (typeof hint === "string") return { [hint]: {} };
1781
+ else if (Array.isArray(hint)) return Object.fromEntries(hint.map((relation) => [relation, {}]));
1782
+ else if (hint) return hint;
1783
+ else return {};
2128
1784
  }
2129
1785
  function isDefined(param) {
2130
- return param !== null && param !== undefined;
1786
+ return param !== null && param !== void 0;
2131
1787
  }
2132
1788
  function getCascadeDeleteRelations(entity) {
2133
- return (0, index_1.getBaseAndSelfMetas)((0, index_1.getMetadata)(entity)).flatMap((meta) => {
2134
- return meta.config.__data.cascadeDeleteFields.map((fieldName) => entity[fieldName]);
2135
- });
1789
+ return getBaseAndSelfMetas(getMetadata(entity)).flatMap((meta) => {
1790
+ return meta.config.__data.cascadeDeleteFields.map((fieldName) => entity[fieldName]);
1791
+ });
2136
1792
  }
2137
1793
  function isCustomRelation(r) {
2138
- return r instanceof index_1.CustomCollection || r instanceof index_1.CustomReference || r instanceof relations_1.ReactiveReferenceImpl;
1794
+ return r instanceof CustomCollection || r instanceof CustomReference || r instanceof ReactiveReferenceImpl;
2139
1795
  }
2140
1796
  function maybeBumpUpdatedAt(rm, todos, now) {
2141
- for (const todo of Object.values(todos)) {
2142
- const { updatedAt } = todo.metadata.timestampFields ?? {};
2143
- if (updatedAt) {
2144
- for (const e of todo.updates) {
2145
- // We avoid going through `setField` because in unit tests, it might detect that our
2146
- // bump's timestamp isn't actually different from the current value, and skip treating
2147
- // it has changed. This is technically true, but this will break the oplock SQL generation,
2148
- // so force the field to be dirty.
2149
- const orm = (0, BaseEntity_1.getInstanceData)(e);
2150
- orm.markFieldDirty(updatedAt, (0, fields_1.getField)(e, updatedAt));
2151
- const serde = todo.metadata.fields[updatedAt].serde;
2152
- orm.data[updatedAt] = serde.mapFromNow(now);
2153
- rm.queueDownstreamReactables(e, updatedAt);
2154
- }
2155
- }
2156
- }
1797
+ for (const todo of Object.values(todos)) {
1798
+ const { updatedAt } = todo.metadata.timestampFields ?? {};
1799
+ if (updatedAt) for (const e of todo.updates) {
1800
+ const orm = getInstanceData(e);
1801
+ orm.markFieldDirty(updatedAt, getField(e, updatedAt));
1802
+ const serde = todo.metadata.fields[updatedAt].serde;
1803
+ orm.data[updatedAt] = serde.mapFromNow(now);
1804
+ rm.queueDownstreamReactables(e, updatedAt);
1805
+ }
1806
+ }
2157
1807
  }
2158
- let lastNow = undefined;
2159
- // exposed so tests that do their own time management can override lastNow to get correct updatedAt values
1808
+ let lastNow = void 0;
2160
1809
  function setLastNow(now) {
2161
- lastNow = now;
1810
+ lastNow = now;
2162
1811
  }
2163
1812
  function getNow() {
2164
- let now = new Date();
2165
- // If we detect time has not progressed (or went backwards), we're probably in test that
2166
- // has frozen time, which can throw off our oplocks b/c if Joist issues multiple `UPDATE`s
2167
- // with exactly the same `updated_at`, the `updated_at` SQL trigger fallback will think "the caller
2168
- // didn't self-manage `updated_at`" and so bump it for them. Which is fine, but now
2169
- // Joist doesn't know about the bumped time, and the 2nd `UPDATE` will fail.
2170
- if (lastNow && (lastNow.getTime() === now.getTime() || now.getTime() < lastNow.getTime())) {
2171
- now = new Date(lastNow.getTime() + 1);
2172
- }
2173
- lastNow = now;
2174
- return now;
1813
+ let now = /* @__PURE__ */ new Date();
1814
+ if (lastNow && (lastNow.getTime() === now.getTime() || now.getTime() < lastNow.getTime())) now = new Date(lastNow.getTime() + 1);
1815
+ lastNow = now;
1816
+ return now;
2175
1817
  }
2176
1818
  /** Given a `row` from the db, resolves the CTI/STI subtype, if applicable. */
2177
- function findConcreteMeta(maybeBaseMeta, row) {
2178
- // Common case of no CTI or STI inheritance
2179
- if (!row.__class && maybeBaseMeta.inheritanceType !== "sti") {
2180
- return maybeBaseMeta;
2181
- }
2182
- if (row.__class) {
2183
- if (row.__class === "_" && maybeBaseMeta.ctiAbstract) {
2184
- throw new Error(`${maybeBaseMeta.type} ${(0, index_1.tagId)(maybeBaseMeta, row.id)} must be instantiated via a subtype`);
2185
- }
2186
- // Look for the CTI __class from the driver telling us which subtype to instantiate
2187
- return maybeBaseMeta.subTypesByType.get(row.__class) ?? maybeBaseMeta;
2188
- }
2189
- else if (maybeBaseMeta.inheritanceType === "sti") {
2190
- // Look for the STI discriminator value
2191
- const baseMeta = (0, index_1.getBaseMeta)(maybeBaseMeta);
2192
- const value = row[baseMeta.stiDiscriminatorColumnName];
2193
- return baseMeta.subTypesByStiValue.get(value) ?? baseMeta;
2194
- }
2195
- else {
2196
- throw new Error("Unknown inheritance type");
2197
- }
1819
+ function findConcreteMeta(maybeBaseMeta, rowData, rowIndex) {
1820
+ if (maybeBaseMeta.inheritanceType === void 0) return maybeBaseMeta;
1821
+ const __class = rowData.get(rowIndex, "__class");
1822
+ if (!__class && maybeBaseMeta.inheritanceType !== "sti") return maybeBaseMeta;
1823
+ if (__class) {
1824
+ if (__class === "_" && maybeBaseMeta.ctiAbstract) {
1825
+ const id = rowData.get(rowIndex, "id");
1826
+ throw new Error(`${maybeBaseMeta.type} ${tagId(maybeBaseMeta, id)} must be instantiated via a subtype`);
1827
+ }
1828
+ return maybeBaseMeta.subTypesByType.get(__class) ?? maybeBaseMeta;
1829
+ } else if (maybeBaseMeta.inheritanceType === "sti") {
1830
+ const baseMeta = getBaseMeta(maybeBaseMeta);
1831
+ const value = rowData.get(rowIndex, baseMeta.stiDiscriminatorColumnName);
1832
+ return baseMeta.subTypesByStiValue.get(value) ?? baseMeta;
1833
+ } else throw new Error("Unknown inheritance type");
2198
1834
  }
2199
1835
  /** Sets the `Animal.type` enum to the right subtype value. */
2200
1836
  function setStiDiscriminatorValue(baseMeta, entity) {
2201
- const typeName = entity.constructor.name;
2202
- const st = baseMeta.subTypesByType.get(typeName);
2203
- if (st) {
2204
- const field = baseMeta.fields[baseMeta.stiDiscriminatorField];
2205
- const code = field.enumDetailType.findById(st.stiDiscriminatorValue).code;
2206
- entity[baseMeta.stiDiscriminatorField] = code;
2207
- }
2208
- else {
2209
- entity[baseMeta.stiDiscriminatorField] = undefined;
2210
- }
1837
+ const typeName = entity.constructor.name;
1838
+ const st = baseMeta.subTypesByType.get(typeName);
1839
+ if (st) {
1840
+ const code = baseMeta.fields[baseMeta.stiDiscriminatorField].enumDetailType.findById(st.stiDiscriminatorValue).code;
1841
+ entity[baseMeta.stiDiscriminatorField] = code;
1842
+ } else entity[baseMeta.stiDiscriminatorField] = void 0;
2211
1843
  }
2212
1844
  function findPendingFlushEntities(maybePendingFlushEntities, hooksInvoked, pendingFlush, pendingHooks, alreadyRanHooks) {
2213
- for (const e of maybePendingFlushEntities) {
2214
- if ((0, BaseEntity_1.getInstanceData)(e).pendingOperation === "none") {
2215
- maybePendingFlushEntities.delete(e);
2216
- continue;
2217
- }
2218
- if (!hooksInvoked.has(e)) {
2219
- pendingHooks.add(e);
2220
- }
2221
- else {
2222
- alreadyRanHooks.add(e);
2223
- }
2224
- pendingFlush.add(e);
2225
- }
1845
+ for (const e of maybePendingFlushEntities) {
1846
+ if (getInstanceData(e).pendingOperation === "none") {
1847
+ maybePendingFlushEntities.delete(e);
1848
+ continue;
1849
+ }
1850
+ if (!hooksInvoked.has(e)) pendingHooks.add(e);
1851
+ else alreadyRanHooks.add(e);
1852
+ pendingFlush.add(e);
1853
+ }
2226
1854
  }
2227
1855
  /** Returns true if the caller explicitly asked `find` to use SQL pagination. */
2228
1856
  function hasPaginationSettings(options) {
2229
- return "limit" in options || "offset" in options;
1857
+ return "limit" in options || "offset" in options;
2230
1858
  }
2231
1859
  /** An error we throw to get knex to `ROLLBACK`, but then catch. */
2232
- class InMemoryRollbackError extends Error {
2233
- }
1860
+ var InMemoryRollbackError = class extends Error {};
2234
1861
  /** An error thrown when `em.mode === "read-only"` but entities are mutated/flushed. */
2235
- class ReadOnlyError extends Error {
2236
- constructor() {
2237
- super("EntityManager is read-only");
2238
- }
2239
- }
2240
- exports.ReadOnlyError = ReadOnlyError;
1862
+ var ReadOnlyError = class extends Error {
1863
+ constructor() {
1864
+ super("EntityManager is read-only");
1865
+ }
1866
+ };
2241
1867
  function maybeSetupHookOrdering(todos) {
2242
- // I'm too rushed to use a topo sort
2243
- const group1 = {};
2244
- const group2 = {};
2245
- for (const todo of Object.values(todos)) {
2246
- // If I should run before `cstr`, I go in group1
2247
- const shouldRunBeforeAnotherGroup = todo.metadata.config.__data.runHooksBefore.some((cstr) => (0, index_1.getBaseMeta)((0, index_1.getMetadata)(cstr)).type in todos);
2248
- const group = shouldRunBeforeAnotherGroup ? group1 : group2;
2249
- group[todo.metadata.type] = todo;
2250
- }
2251
- return Object.keys(group1).length ? [group1, group2] : [group2];
1868
+ const group1 = {};
1869
+ const group2 = {};
1870
+ for (const todo of Object.values(todos)) {
1871
+ const group = todo.metadata.config.__data.runHooksBefore.some((cstr) => getBaseMeta(getMetadata(cstr)).type in todos) ? group1 : group2;
1872
+ group[todo.metadata.type] = todo;
1873
+ }
1874
+ return Object.keys(group1).length ? [group1, group2] : [group2];
2252
1875
  }
2253
1876
  /**
2254
- * Given an `err` thrown in "a different context", i.e. a database error or dataloader error
2255
- * that doesn't include our stack trace, append our stack for better debugging.
2256
- *
2257
- * See https://github.com/brianc/node-postgres/pull/2983
2258
- */
1877
+ * Given an `err` thrown in "a different context", i.e. a database error or dataloader error
1878
+ * that doesn't include our stack trace, append our stack for better debugging.
1879
+ *
1880
+ * See https://github.com/brianc/node-postgres/pull/2983
1881
+ */
2259
1882
  function appendStack(err, dummy) {
2260
- if (err && typeof err === "object" && "stack" in err) {
2261
- err.stack += dummy.stack.replace(/.*\n/, "\n");
2262
- }
2263
- return err;
1883
+ if (err && typeof err === "object" && "stack" in err) err.stack += dummy.stack.replace(/.*\n/, "\n");
1884
+ return err;
2264
1885
  }
2265
1886
  /** Probe for `ctx.logger.debug` if it exists, otherwise fallback on `console.log`. */
2266
1887
  function getDefaultWriteFn(ctx) {
2267
- return ctx &&
2268
- typeof ctx === "object" &&
2269
- "logger" in ctx &&
2270
- ctx.logger &&
2271
- typeof ctx.logger === "object" &&
2272
- "debug" in ctx.logger &&
2273
- ctx.logger.debug instanceof Function
2274
- ? ctx.logger.debug.bind(ctx.logger)
2275
- : console.log;
1888
+ return ctx && typeof ctx === "object" && "logger" in ctx && ctx.logger && typeof ctx.logger === "object" && "debug" in ctx.logger && ctx.logger.debug instanceof Function ? ctx.logger.debug.bind(ctx.logger) : console.log;
2276
1889
  }
2277
1890
  const fieldMap = {};
2278
- // Generates what a row from the db would look like for a given entity
2279
1891
  function createRowFromEntityData(e, opts = {}) {
2280
- const { preferOriginalData = true } = opts;
2281
- const { row: oldRow, data, originalData } = e.__data;
2282
- const __class = e.constructor.name;
2283
- const { metadata: meta } = e.__data;
2284
- if (!fieldMap[__class]) {
2285
- fieldMap[__class] = [];
2286
- for (const field of Object.values(meta.allFields)) {
2287
- if (!field.serde)
2288
- continue;
2289
- for (const column of field.serde.columns) {
2290
- fieldMap[__class].push([field, column]);
2291
- }
2292
- }
2293
- }
2294
- const row = meta.inheritanceType === "cti" ? { __class } : {};
2295
- for (const [field, column] of fieldMap[__class]) {
2296
- const value =
2297
- // Ideally, we could only go through the serde for data that has actually changed since the last time it was
2298
- // fetched from the db and just use the row value for everything else. Unfortunately, we lose track of which
2299
- // fields are modified on flush. So we have to assume that anything present in `data` is a change and push it
2300
- // through the serde.
2301
- field.fieldName in originalData || field.fieldName in data
2302
- ? // If our field is in originalData, then the field has been changed since flush. Our `row` should
2303
- // reflect what would come from the db if we queried it right now, so use originalData when present
2304
- column.rowValue(preferOriginalData && field.fieldName in originalData ? originalData : data)
2305
- : // `data` is lazy and isn't set until it's accessed, so if the field isn't present there, then we should
2306
- // be safe to pull the raw data out of `row`
2307
- oldRow[column.columnName];
2308
- row[column.columnName] = value ?? null;
2309
- }
2310
- return row;
1892
+ const { preferOriginalData = true } = opts;
1893
+ const { rowData, rowIndex, data, originalData } = e.__data;
1894
+ const __class = e.constructor.name;
1895
+ const { metadata: meta } = e.__data;
1896
+ if (!fieldMap[__class]) {
1897
+ fieldMap[__class] = [];
1898
+ for (const field of Object.values(meta.allFields)) {
1899
+ if (!field.serde) continue;
1900
+ for (const column of field.serde.columns) fieldMap[__class].push([field, column]);
1901
+ }
1902
+ }
1903
+ const row = meta.inheritanceType === "cti" ? { __class } : {};
1904
+ for (const [field, column] of fieldMap[__class]) {
1905
+ const value = field.fieldName in originalData || field.fieldName in data ? column.rowValue(preferOriginalData && field.fieldName in originalData ? originalData : data) : rowData.get(rowIndex, column.columnName);
1906
+ row[column.columnName] = value ?? null;
1907
+ }
1908
+ return row;
2311
1909
  }
1910
+ //#endregion
1911
+ export { EntityManager, NotFoundError, ReadOnlyError, TooManyError, appendStack, createRowFromEntityData, driverAfterBegin, driverAfterCommit, driverBeforeBegin, driverBeforeCommit, getDefaultEntityLimit, getEmInternalApi, isDefined, isId, isKey, resetDefaultEntityLimit, sameEntity, sameReference, setDefaultEntityLimit, setLastNow };
1912
+
2312
1913
  //# sourceMappingURL=EntityManager.js.map