joist-core 2.3.0-next.97 → 2.3.0-next.98

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 (580) hide show
  1. package/build/EntityManager.cjs +45 -46
  2. package/build/EntityManager.cjs.map +1 -1
  3. package/build/EntityManager.d.cts +7 -7
  4. package/build/EntityManager.d.mts +7 -7
  5. package/build/EntityManager.js +27 -28
  6. package/build/EntityManager.js.map +1 -1
  7. package/build/EntityMetadata.cjs +0 -2
  8. package/build/EntityMetadata.cjs.map +1 -1
  9. package/build/EntityMetadata.d.cts +3 -3
  10. package/build/EntityMetadata.d.mts +3 -3
  11. package/build/EntityMetadata.js +0 -2
  12. package/build/EntityMetadata.js.map +1 -1
  13. package/build/IndexManager.cjs +1 -1
  14. package/build/IndexManager.js +1 -1
  15. package/build/PluginManager.cjs +0 -1
  16. package/build/PluginManager.cjs.map +1 -1
  17. package/build/PluginManager.d.cts +1 -1
  18. package/build/PluginManager.d.mts +1 -1
  19. package/build/PluginManager.js +0 -1
  20. package/build/PluginManager.js.map +1 -1
  21. package/build/batchloaders/enumCollectionBatchLoader.cjs +1 -1
  22. package/build/batchloaders/enumCollectionBatchLoader.d.cts +1 -1
  23. package/build/batchloaders/enumCollectionBatchLoader.d.mts +1 -1
  24. package/build/batchloaders/enumCollectionBatchLoader.js +1 -1
  25. package/build/batchloaders/loadBatchLoader.cjs +3 -4
  26. package/build/batchloaders/loadBatchLoader.cjs.map +1 -1
  27. package/build/batchloaders/loadBatchLoader.d.cts +1 -1
  28. package/build/batchloaders/loadBatchLoader.d.mts +1 -1
  29. package/build/batchloaders/loadBatchLoader.js +2 -3
  30. package/build/batchloaders/loadBatchLoader.js.map +1 -1
  31. package/build/batchloaders/manyToManyBatchLoader.cjs +1 -1
  32. package/build/batchloaders/manyToManyBatchLoader.d.cts +1 -1
  33. package/build/batchloaders/manyToManyBatchLoader.d.mts +1 -1
  34. package/build/batchloaders/manyToManyBatchLoader.js +1 -1
  35. package/build/batchloaders/oneToManyBatchLoader.cjs +1 -1
  36. package/build/batchloaders/oneToManyBatchLoader.js +1 -1
  37. package/build/batchloaders/oneToOneBatchLoader.cjs +1 -1
  38. package/build/batchloaders/oneToOneBatchLoader.js +1 -1
  39. package/build/batchloaders/populateBatchLoader.cjs +11 -12
  40. package/build/batchloaders/populateBatchLoader.cjs.map +1 -1
  41. package/build/batchloaders/populateBatchLoader.d.cts +1 -1
  42. package/build/batchloaders/populateBatchLoader.d.mts +1 -1
  43. package/build/batchloaders/populateBatchLoader.js +7 -8
  44. package/build/batchloaders/populateBatchLoader.js.map +1 -1
  45. package/build/batchloaders/recursiveChildrenBatchLoader.cjs +2 -2
  46. package/build/batchloaders/recursiveChildrenBatchLoader.js +2 -2
  47. package/build/batchloaders/recursiveM2mBatchLoader.cjs +2 -2
  48. package/build/batchloaders/recursiveM2mBatchLoader.js +2 -2
  49. package/build/batchloaders/recursiveParentsBatchLoader.cjs +2 -2
  50. package/build/batchloaders/recursiveParentsBatchLoader.js +2 -2
  51. package/build/changes.cjs +2 -3
  52. package/build/changes.cjs.map +1 -1
  53. package/build/changes.js +2 -3
  54. package/build/changes.js.map +1 -1
  55. package/build/config.cjs +3 -3
  56. package/build/config.cjs.map +1 -1
  57. package/build/config.d.cts +2 -2
  58. package/build/config.d.mts +2 -2
  59. package/build/config.js +1 -1
  60. package/build/config.js.map +1 -1
  61. package/build/configure.cjs +10 -10
  62. package/build/configure.cjs.map +1 -1
  63. package/build/configure.js +5 -5
  64. package/build/configure.js.map +1 -1
  65. package/build/dataloaders/fastWhereFilterHash.cjs +8 -8
  66. package/build/dataloaders/fastWhereFilterHash.cjs.map +1 -1
  67. package/build/dataloaders/fastWhereFilterHash.d.cts.map +1 -1
  68. package/build/dataloaders/fastWhereFilterHash.d.mts.map +1 -1
  69. package/build/dataloaders/fastWhereFilterHash.js +3 -3
  70. package/build/dataloaders/fastWhereFilterHash.js.map +1 -1
  71. package/build/dataloaders/findByUniqueDataLoader.cjs.map +1 -1
  72. package/build/dataloaders/findByUniqueDataLoader.js.map +1 -1
  73. package/build/dataloaders/findCountDataLoader.cjs +2 -2
  74. package/build/dataloaders/findCountDataLoader.cjs.map +1 -1
  75. package/build/dataloaders/findCountDataLoader.js +1 -1
  76. package/build/dataloaders/findCountDataLoader.js.map +1 -1
  77. package/build/dataloaders/findDataLoader.cjs +6 -6
  78. package/build/dataloaders/findDataLoader.cjs.map +1 -1
  79. package/build/dataloaders/findDataLoader.d.cts +1 -1
  80. package/build/dataloaders/findDataLoader.d.mts +1 -1
  81. package/build/dataloaders/findDataLoader.js +3 -3
  82. package/build/dataloaders/findDataLoader.js.map +1 -1
  83. package/build/dataloaders/findIdsDataLoader.cjs +3 -3
  84. package/build/dataloaders/findIdsDataLoader.cjs.map +1 -1
  85. package/build/dataloaders/findIdsDataLoader.js +2 -2
  86. package/build/dataloaders/findIdsDataLoader.js.map +1 -1
  87. package/build/dataloaders/findOrCreateDataLoader.cjs +1 -1
  88. package/build/dataloaders/findOrCreateDataLoader.js +1 -1
  89. package/build/dataloaders/findPaginatedDataLoader.cjs +6 -6
  90. package/build/dataloaders/findPaginatedDataLoader.cjs.map +1 -1
  91. package/build/dataloaders/findPaginatedDataLoader.d.cts +1 -1
  92. package/build/dataloaders/findPaginatedDataLoader.d.mts +1 -1
  93. package/build/dataloaders/findPaginatedDataLoader.js +3 -3
  94. package/build/dataloaders/findPaginatedDataLoader.js.map +1 -1
  95. package/build/dataloaders/lensDataLoader.cjs +3 -3
  96. package/build/dataloaders/lensDataLoader.cjs.map +1 -1
  97. package/build/dataloaders/lensDataLoader.js +2 -2
  98. package/build/dataloaders/lensDataLoader.js.map +1 -1
  99. package/build/dataloaders/manyToManyFindDataLoader.cjs +1 -1
  100. package/build/dataloaders/manyToManyFindDataLoader.js +1 -1
  101. package/build/dataloaders/oneToManyFindDataLoader.cjs +1 -1
  102. package/build/dataloaders/oneToManyFindDataLoader.js +1 -1
  103. package/build/defaults.cjs +5 -5
  104. package/build/defaults.cjs.map +1 -1
  105. package/build/defaults.d.cts +1 -1
  106. package/build/defaults.d.mts +1 -1
  107. package/build/defaults.js +4 -4
  108. package/build/defaults.js.map +1 -1
  109. package/build/drivers/Driver.cjs +0 -1
  110. package/build/drivers/Driver.d.cts +1 -1
  111. package/build/drivers/Driver.d.mts +1 -1
  112. package/build/drivers/Driver.js +0 -1
  113. package/build/drivers/EntityWriter.cjs +6 -7
  114. package/build/drivers/EntityWriter.cjs.map +1 -1
  115. package/build/drivers/EntityWriter.d.cts +1 -1
  116. package/build/drivers/EntityWriter.d.mts +1 -1
  117. package/build/drivers/EntityWriter.js +2 -3
  118. package/build/drivers/EntityWriter.js.map +1 -1
  119. package/build/drivers/IdAssigner.cjs +0 -1
  120. package/build/drivers/IdAssigner.cjs.map +1 -1
  121. package/build/drivers/IdAssigner.d.cts +1 -1
  122. package/build/drivers/IdAssigner.d.mts +1 -1
  123. package/build/drivers/IdAssigner.js +0 -1
  124. package/build/drivers/IdAssigner.js.map +1 -1
  125. package/build/drivers/driverApi.cjs +19 -0
  126. package/build/drivers/driverApi.cjs.map +1 -0
  127. package/build/drivers/driverApi.d.cts +22 -0
  128. package/build/drivers/driverApi.d.cts.map +1 -0
  129. package/build/drivers/driverApi.d.mts +22 -0
  130. package/build/drivers/driverApi.d.mts.map +1 -0
  131. package/build/drivers/driverApi.js +18 -0
  132. package/build/drivers/driverApi.js.map +1 -0
  133. package/build/fields.cjs +3 -3
  134. package/build/fields.cjs.map +1 -1
  135. package/build/fields.js +2 -2
  136. package/build/fields.js.map +1 -1
  137. package/build/{FlushLock.cjs → flush/FlushLock.cjs} +1 -1
  138. package/build/flush/FlushLock.cjs.map +1 -0
  139. package/build/{FlushLock.d.cts → flush/FlushLock.d.cts} +1 -1
  140. package/build/flush/FlushLock.d.cts.map +1 -0
  141. package/build/{FlushLock.d.mts → flush/FlushLock.d.mts} +1 -1
  142. package/build/flush/FlushLock.d.mts.map +1 -0
  143. package/build/{FlushLock.js → flush/FlushLock.js} +1 -1
  144. package/build/flush/FlushLock.js.map +1 -0
  145. package/build/{JoinRows.cjs → flush/JoinRows.cjs} +5 -8
  146. package/build/flush/JoinRows.cjs.map +1 -0
  147. package/build/{JoinRows.d.cts → flush/JoinRows.d.cts} +5 -5
  148. package/build/flush/JoinRows.d.cts.map +1 -0
  149. package/build/{JoinRows.d.mts → flush/JoinRows.d.mts} +5 -5
  150. package/build/flush/JoinRows.d.mts.map +1 -0
  151. package/build/{JoinRows.js → flush/JoinRows.js} +5 -8
  152. package/build/flush/JoinRows.js.map +1 -0
  153. package/build/{PendingChanges.cjs → flush/PendingChanges.cjs} +0 -1
  154. package/build/{PendingChanges.d.cts → flush/PendingChanges.d.cts} +2 -2
  155. package/build/flush/PendingChanges.d.cts.map +1 -0
  156. package/build/{PendingChanges.d.mts → flush/PendingChanges.d.mts} +2 -2
  157. package/build/flush/PendingChanges.d.mts.map +1 -0
  158. package/build/flush/PendingChanges.js +1 -0
  159. package/build/{Todo.cjs → flush/Todo.cjs} +4 -6
  160. package/build/flush/Todo.cjs.map +1 -0
  161. package/build/{Todo.d.cts → flush/Todo.d.cts} +3 -3
  162. package/build/flush/Todo.d.cts.map +1 -0
  163. package/build/{Todo.d.mts → flush/Todo.d.mts} +3 -3
  164. package/build/flush/Todo.d.mts.map +1 -0
  165. package/build/{Todo.js → flush/Todo.js} +4 -6
  166. package/build/flush/Todo.js.map +1 -0
  167. package/build/index.cjs +99 -99
  168. package/build/index.cjs.map +1 -1
  169. package/build/index.d.cts +15 -15
  170. package/build/index.d.mts +15 -15
  171. package/build/index.js +41 -41
  172. package/build/index.js.map +1 -1
  173. package/build/json.cjs +4 -4
  174. package/build/json.cjs.map +1 -1
  175. package/build/json.js +3 -3
  176. package/build/json.js.map +1 -1
  177. package/build/keys.cjs +1 -1
  178. package/build/keys.js +1 -1
  179. package/build/{HintTree.cjs → loading/HintTree.cjs} +2 -5
  180. package/build/loading/HintTree.cjs.map +1 -0
  181. package/build/{HintTree.d.cts → loading/HintTree.d.cts} +3 -3
  182. package/build/loading/HintTree.d.cts.map +1 -0
  183. package/build/{HintTree.d.mts → loading/HintTree.d.mts} +3 -3
  184. package/build/loading/HintTree.d.mts.map +1 -0
  185. package/build/{HintTree.js → loading/HintTree.js} +2 -5
  186. package/build/loading/HintTree.js.map +1 -0
  187. package/build/{IsLoadedCache.cjs → loading/IsLoadedCache.cjs} +2 -3
  188. package/build/loading/IsLoadedCache.cjs.map +1 -0
  189. package/build/{IsLoadedCache.d.cts → loading/IsLoadedCache.d.cts} +2 -2
  190. package/build/loading/IsLoadedCache.d.cts.map +1 -0
  191. package/build/{IsLoadedCache.d.mts → loading/IsLoadedCache.d.mts} +2 -2
  192. package/build/loading/IsLoadedCache.d.mts.map +1 -0
  193. package/build/{IsLoadedCache.js → loading/IsLoadedCache.js} +2 -3
  194. package/build/loading/IsLoadedCache.js.map +1 -0
  195. package/build/{loadHints.cjs → loading/loadHints.cjs} +6 -11
  196. package/build/loading/loadHints.cjs.map +1 -0
  197. package/build/{loadHints.d.cts → loading/loadHints.d.cts} +14 -14
  198. package/build/loading/loadHints.d.cts.map +1 -0
  199. package/build/{loadHints.d.mts → loading/loadHints.d.mts} +14 -14
  200. package/build/loading/loadHints.d.mts.map +1 -0
  201. package/build/{loadHints.js → loading/loadHints.js} +3 -8
  202. package/build/loading/loadHints.js.map +1 -0
  203. package/build/{loadLens.cjs → loading/loadLens.cjs} +8 -9
  204. package/build/loading/loadLens.cjs.map +1 -0
  205. package/build/{loadLens.d.cts → loading/loadLens.d.cts} +3 -3
  206. package/build/loading/loadLens.d.cts.map +1 -0
  207. package/build/{loadLens.d.mts → loading/loadLens.d.mts} +3 -3
  208. package/build/loading/loadLens.d.mts.map +1 -0
  209. package/build/{loadLens.js → loading/loadLens.js} +8 -9
  210. package/build/loading/loadLens.js.map +1 -0
  211. package/build/{withLoaded.cjs → loading/withLoaded.cjs} +12 -13
  212. package/build/loading/withLoaded.cjs.map +1 -0
  213. package/build/{withLoaded.d.cts → loading/withLoaded.d.cts} +9 -9
  214. package/build/loading/withLoaded.d.cts.map +1 -0
  215. package/build/{withLoaded.d.mts → loading/withLoaded.d.mts} +9 -9
  216. package/build/loading/withLoaded.d.mts.map +1 -0
  217. package/build/{withLoaded.js → loading/withLoaded.js} +10 -11
  218. package/build/loading/withLoaded.js.map +1 -0
  219. package/build/logging/ReactionLogger.cjs +0 -2
  220. package/build/logging/ReactionLogger.cjs.map +1 -1
  221. package/build/logging/ReactionLogger.d.cts +2 -2
  222. package/build/logging/ReactionLogger.d.mts +2 -2
  223. package/build/logging/ReactionLogger.js +0 -2
  224. package/build/logging/ReactionLogger.js.map +1 -1
  225. package/build/newTestInstance.cjs +3 -3
  226. package/build/newTestInstance.cjs.map +1 -1
  227. package/build/newTestInstance.d.cts +1 -1
  228. package/build/newTestInstance.d.mts +1 -1
  229. package/build/newTestInstance.js +2 -2
  230. package/build/newTestInstance.js.map +1 -1
  231. package/build/normalizeHints.cjs +0 -2
  232. package/build/normalizeHints.cjs.map +1 -1
  233. package/build/normalizeHints.d.cts +2 -2
  234. package/build/normalizeHints.d.mts +2 -2
  235. package/build/normalizeHints.js +0 -2
  236. package/build/normalizeHints.js.map +1 -1
  237. package/build/nowUTC.cjs +2 -2
  238. package/build/nowUTC.cjs.map +1 -1
  239. package/build/nowUTC.d.cts +1 -1
  240. package/build/nowUTC.d.mts +1 -1
  241. package/build/nowUTC.js +1 -1
  242. package/build/nowUTC.js.map +1 -1
  243. package/build/plugins/PreloadPlugin.cjs +0 -2
  244. package/build/plugins/PreloadPlugin.d.cts +2 -2
  245. package/build/plugins/PreloadPlugin.d.mts +2 -2
  246. package/build/plugins/PreloadPlugin.js +0 -2
  247. package/build/preloading/JsonAggregatePreloader.cjs +1 -4
  248. package/build/preloading/JsonAggregatePreloader.cjs.map +1 -1
  249. package/build/preloading/JsonAggregatePreloader.d.cts +2 -2
  250. package/build/preloading/JsonAggregatePreloader.d.mts +2 -2
  251. package/build/preloading/JsonAggregatePreloader.js +1 -4
  252. package/build/preloading/JsonAggregatePreloader.js.map +1 -1
  253. package/build/preloading/partitionHint.cjs +2 -3
  254. package/build/preloading/partitionHint.cjs.map +1 -1
  255. package/build/preloading/partitionHint.d.cts +1 -1
  256. package/build/preloading/partitionHint.d.mts +1 -1
  257. package/build/preloading/partitionHint.js +2 -3
  258. package/build/preloading/partitionHint.js.map +1 -1
  259. package/build/queries/ConditionBuilder.cjs.map +1 -1
  260. package/build/queries/ConditionBuilder.d.cts +1 -1
  261. package/build/queries/ConditionBuilder.d.mts +1 -1
  262. package/build/queries/ConditionBuilder.js.map +1 -1
  263. package/build/queries/find/Aliases.cjs +1 -1
  264. package/build/queries/find/Aliases.cjs.map +1 -1
  265. package/build/queries/find/Aliases.js +1 -1
  266. package/build/queries/find/Aliases.js.map +1 -1
  267. package/build/queries/find/QueryParser.cjs +1 -1
  268. package/build/queries/find/QueryParser.js +1 -1
  269. package/build/queries/find/scopes.cjs.map +1 -1
  270. package/build/queries/find/scopes.d.cts +1 -1
  271. package/build/queries/find/scopes.d.mts +1 -1
  272. package/build/queries/find/scopes.js.map +1 -1
  273. package/build/queries/sql/Expr.cjs +2 -2
  274. package/build/queries/sql/Expr.cjs.map +1 -1
  275. package/build/queries/sql/Expr.d.cts +1 -1
  276. package/build/queries/sql/Expr.d.mts +1 -1
  277. package/build/queries/sql/Expr.js +1 -1
  278. package/build/queries/sql/Expr.js.map +1 -1
  279. package/build/queries/sql/Tables.cjs +1 -1
  280. package/build/queries/sql/Tables.cjs.map +1 -1
  281. package/build/queries/sql/Tables.js +1 -1
  282. package/build/queries/sql/Tables.js.map +1 -1
  283. package/build/queries/sql/execute.cjs +1 -1
  284. package/build/queries/sql/execute.cjs.map +1 -1
  285. package/build/queries/sql/execute.js +1 -1
  286. package/build/queries/sql/execute.js.map +1 -1
  287. package/build/queries/sql/expressions/codecs.cjs +2 -2
  288. package/build/queries/sql/expressions/codecs.cjs.map +1 -1
  289. package/build/queries/sql/expressions/codecs.js +1 -1
  290. package/build/queries/sql/expressions/codecs.js.map +1 -1
  291. package/build/queries/sql/expressions/expression.cjs.map +1 -1
  292. package/build/queries/sql/expressions/expression.js.map +1 -1
  293. package/build/queries/sql/query.cjs.map +1 -1
  294. package/build/queries/sql/query.d.cts +1 -1
  295. package/build/queries/sql/query.d.mts +1 -1
  296. package/build/queries/sql/query.js.map +1 -1
  297. package/build/{unnest.cjs → queries/unnest.cjs} +1 -2
  298. package/build/queries/unnest.cjs.map +1 -0
  299. package/build/{unnest.d.cts → queries/unnest.d.cts} +3 -3
  300. package/build/queries/unnest.d.cts.map +1 -0
  301. package/build/{unnest.d.mts → queries/unnest.d.mts} +3 -3
  302. package/build/queries/unnest.d.mts.map +1 -0
  303. package/build/{unnest.js → queries/unnest.js} +1 -2
  304. package/build/queries/unnest.js.map +1 -0
  305. package/build/queries/valueFilters.cjs.map +1 -1
  306. package/build/queries/valueFilters.d.cts +1 -1
  307. package/build/queries/valueFilters.d.mts +1 -1
  308. package/build/queries/valueFilters.js.map +1 -1
  309. package/build/{ReactionsManager.cjs → reactivity/ReactionsManager.cjs} +8 -10
  310. package/build/reactivity/ReactionsManager.cjs.map +1 -0
  311. package/build/{ReactionsManager.d.cts → reactivity/ReactionsManager.d.cts} +5 -6
  312. package/build/reactivity/ReactionsManager.d.cts.map +1 -0
  313. package/build/{ReactionsManager.d.mts → reactivity/ReactionsManager.d.mts} +5 -6
  314. package/build/reactivity/ReactionsManager.d.mts.map +1 -0
  315. package/build/{ReactionsManager.js → reactivity/ReactionsManager.js} +6 -8
  316. package/build/reactivity/ReactionsManager.js.map +1 -0
  317. package/build/{reactiveHints.cjs → reactivity/reactiveHints.cjs} +12 -16
  318. package/build/reactivity/reactiveHints.cjs.map +1 -0
  319. package/build/{reactiveHints.d.cts → reactivity/reactiveHints.d.cts} +17 -17
  320. package/build/reactivity/reactiveHints.d.cts.map +1 -0
  321. package/build/{reactiveHints.d.mts → reactivity/reactiveHints.d.mts} +17 -17
  322. package/build/reactivity/reactiveHints.d.mts.map +1 -0
  323. package/build/{reactiveHints.js → reactivity/reactiveHints.js} +12 -16
  324. package/build/reactivity/reactiveHints.js.map +1 -0
  325. package/build/relations/AsyncReactiveField.cjs +6 -6
  326. package/build/relations/AsyncReactiveField.cjs.map +1 -1
  327. package/build/relations/AsyncReactiveField.d.cts +1 -1
  328. package/build/relations/AsyncReactiveField.d.mts +1 -1
  329. package/build/relations/AsyncReactiveField.js +4 -4
  330. package/build/relations/AsyncReactiveField.js.map +1 -1
  331. package/build/relations/Collection.cjs +1 -1
  332. package/build/relations/Collection.js +1 -1
  333. package/build/relations/CustomCollection.d.cts +1 -1
  334. package/build/relations/CustomCollection.d.mts +1 -1
  335. package/build/relations/CustomReference.cjs +1 -1
  336. package/build/relations/CustomReference.d.cts +1 -1
  337. package/build/relations/CustomReference.d.mts +1 -1
  338. package/build/relations/CustomReference.js +1 -1
  339. package/build/relations/EnumCollection.d.cts +1 -1
  340. package/build/relations/EnumCollection.d.mts +1 -1
  341. package/build/relations/LazyField.cjs +4 -4
  342. package/build/relations/LazyField.js +4 -4
  343. package/build/relations/ManyToManyCollection.cjs +3 -3
  344. package/build/relations/ManyToManyCollection.js +3 -3
  345. package/build/relations/ManyToManyLargeCollection.cjs +3 -3
  346. package/build/relations/ManyToManyLargeCollection.js +3 -3
  347. package/build/relations/ManyToOneReference.cjs +4 -4
  348. package/build/relations/ManyToOneReference.js +4 -4
  349. package/build/relations/OneToManyCollection.cjs +1 -2
  350. package/build/relations/OneToManyCollection.cjs.map +1 -1
  351. package/build/relations/OneToManyCollection.d.cts +1 -1
  352. package/build/relations/OneToManyCollection.d.mts +1 -1
  353. package/build/relations/OneToManyCollection.js +1 -2
  354. package/build/relations/OneToManyCollection.js.map +1 -1
  355. package/build/relations/OneToManyLargeCollection.cjs +1 -1
  356. package/build/relations/OneToManyLargeCollection.js +1 -1
  357. package/build/relations/OneToOneReference.cjs +5 -5
  358. package/build/relations/OneToOneReference.js +5 -5
  359. package/build/relations/PolymorphicReference.cjs +3 -3
  360. package/build/relations/PolymorphicReference.js +3 -3
  361. package/build/relations/ReactiveField.cjs +5 -6
  362. package/build/relations/ReactiveField.cjs.map +1 -1
  363. package/build/relations/ReactiveField.d.cts +2 -2
  364. package/build/relations/ReactiveField.d.mts +2 -2
  365. package/build/relations/ReactiveField.js +3 -4
  366. package/build/relations/ReactiveField.js.map +1 -1
  367. package/build/relations/ReactiveGetter.cjs +0 -1
  368. package/build/relations/ReactiveGetter.cjs.map +1 -1
  369. package/build/relations/ReactiveGetter.d.cts +1 -1
  370. package/build/relations/ReactiveGetter.d.mts +1 -1
  371. package/build/relations/ReactiveGetter.js +0 -1
  372. package/build/relations/ReactiveGetter.js.map +1 -1
  373. package/build/relations/ReactiveManyToMany.cjs +5 -6
  374. package/build/relations/ReactiveManyToMany.cjs.map +1 -1
  375. package/build/relations/ReactiveManyToMany.d.cts +2 -2
  376. package/build/relations/ReactiveManyToMany.d.cts.map +1 -1
  377. package/build/relations/ReactiveManyToMany.d.mts +2 -2
  378. package/build/relations/ReactiveManyToMany.d.mts.map +1 -1
  379. package/build/relations/ReactiveManyToMany.js +3 -4
  380. package/build/relations/ReactiveManyToMany.js.map +1 -1
  381. package/build/relations/ReactiveManyToManyOtherSide.cjs +1 -3
  382. package/build/relations/ReactiveManyToManyOtherSide.cjs.map +1 -1
  383. package/build/relations/ReactiveManyToManyOtherSide.d.cts +2 -2
  384. package/build/relations/ReactiveManyToManyOtherSide.d.mts +2 -2
  385. package/build/relations/ReactiveManyToManyOtherSide.js +1 -3
  386. package/build/relations/ReactiveManyToManyOtherSide.js.map +1 -1
  387. package/build/relations/ReactiveReference.cjs +8 -9
  388. package/build/relations/ReactiveReference.cjs.map +1 -1
  389. package/build/relations/ReactiveReference.d.cts +2 -2
  390. package/build/relations/ReactiveReference.d.cts.map +1 -1
  391. package/build/relations/ReactiveReference.d.mts +2 -2
  392. package/build/relations/ReactiveReference.d.mts.map +1 -1
  393. package/build/relations/ReactiveReference.js +6 -7
  394. package/build/relations/ReactiveReference.js.map +1 -1
  395. package/build/relations/RecursiveCollection.cjs +3 -4
  396. package/build/relations/RecursiveCollection.cjs.map +1 -1
  397. package/build/relations/RecursiveCollection.d.cts +1 -1
  398. package/build/relations/RecursiveCollection.d.mts +1 -1
  399. package/build/relations/RecursiveCollection.js +3 -4
  400. package/build/relations/RecursiveCollection.js.map +1 -1
  401. package/build/relations/Reference.cjs +1 -1
  402. package/build/relations/Reference.js +1 -1
  403. package/build/relations/hasAsyncMethod.cjs +2 -2
  404. package/build/relations/hasAsyncMethod.cjs.map +1 -1
  405. package/build/relations/hasAsyncMethod.d.cts +1 -1
  406. package/build/relations/hasAsyncMethod.d.mts +1 -1
  407. package/build/relations/hasAsyncMethod.js +1 -1
  408. package/build/relations/hasAsyncMethod.js.map +1 -1
  409. package/build/relations/hasManyDerived.cjs +3 -3
  410. package/build/relations/hasManyDerived.cjs.map +1 -1
  411. package/build/relations/hasManyDerived.d.cts +1 -1
  412. package/build/relations/hasManyDerived.d.mts +1 -1
  413. package/build/relations/hasManyDerived.js +2 -2
  414. package/build/relations/hasManyDerived.js.map +1 -1
  415. package/build/relations/hasManyThrough.cjs +6 -6
  416. package/build/relations/hasManyThrough.cjs.map +1 -1
  417. package/build/relations/hasManyThrough.d.cts +1 -1
  418. package/build/relations/hasManyThrough.d.mts +1 -1
  419. package/build/relations/hasManyThrough.js +2 -2
  420. package/build/relations/hasOneDerived.cjs +3 -3
  421. package/build/relations/hasOneDerived.cjs.map +1 -1
  422. package/build/relations/hasOneDerived.d.cts +1 -1
  423. package/build/relations/hasOneDerived.d.mts +1 -1
  424. package/build/relations/hasOneDerived.js +2 -2
  425. package/build/relations/hasOneDerived.js.map +1 -1
  426. package/build/relations/hasOneThrough.cjs +7 -7
  427. package/build/relations/hasOneThrough.cjs.map +1 -1
  428. package/build/relations/hasOneThrough.d.cts +1 -1
  429. package/build/relations/hasOneThrough.d.mts +1 -1
  430. package/build/relations/hasOneThrough.js +2 -2
  431. package/build/relations/hasProperty.cjs +4 -4
  432. package/build/relations/hasProperty.cjs.map +1 -1
  433. package/build/relations/hasProperty.d.cts +2 -2
  434. package/build/relations/hasProperty.d.mts +2 -2
  435. package/build/relations/hasProperty.js +2 -2
  436. package/build/relations/hasProperty.js.map +1 -1
  437. package/build/relations/index.cjs +10 -10
  438. package/build/relations/index.js +10 -10
  439. package/build/rules.cjs +3 -4
  440. package/build/rules.cjs.map +1 -1
  441. package/build/rules.d.cts +1 -1
  442. package/build/rules.d.mts +1 -1
  443. package/build/rules.js +3 -4
  444. package/build/rules.js.map +1 -1
  445. package/build/{TypeInfo.cjs → serde/TypeInfo.cjs} +1 -1
  446. package/build/serde/TypeInfo.cjs.map +1 -0
  447. package/build/{TypeInfo.d.cts → serde/TypeInfo.d.cts} +2 -2
  448. package/build/serde/TypeInfo.d.cts.map +1 -0
  449. package/build/{TypeInfo.d.mts → serde/TypeInfo.d.mts} +2 -2
  450. package/build/serde/TypeInfo.d.mts.map +1 -0
  451. package/build/{TypeInfo.js → serde/TypeInfo.js} +1 -1
  452. package/build/serde/TypeInfo.js.map +1 -0
  453. package/build/{columns.cjs → serde/columns.cjs} +1 -1
  454. package/build/serde/columns.cjs.map +1 -0
  455. package/build/{columns.d.cts → serde/columns.d.cts} +2 -2
  456. package/build/serde/columns.d.cts.map +1 -0
  457. package/build/{columns.d.mts → serde/columns.d.mts} +2 -2
  458. package/build/serde/columns.d.mts.map +1 -0
  459. package/build/{columns.js → serde/columns.js} +1 -1
  460. package/build/serde/columns.js.map +1 -0
  461. package/build/{fieldSerde.cjs → serde/fieldSerde.cjs} +6 -6
  462. package/build/serde/fieldSerde.cjs.map +1 -0
  463. package/build/{fieldSerde.d.cts → serde/fieldSerde.d.cts} +5 -5
  464. package/build/serde/fieldSerde.d.cts.map +1 -0
  465. package/build/{fieldSerde.d.mts → serde/fieldSerde.d.mts} +5 -5
  466. package/build/serde/fieldSerde.d.mts.map +1 -0
  467. package/build/{fieldSerde.js → serde/fieldSerde.js} +6 -6
  468. package/build/serde/fieldSerde.js.map +1 -0
  469. package/build/{serde.cjs → serde/serde.cjs} +25 -26
  470. package/build/serde/serde.cjs.map +1 -0
  471. package/build/{serde.d.cts → serde/serde.d.cts} +1 -1
  472. package/build/serde/serde.d.cts.map +1 -0
  473. package/build/{serde.d.mts → serde/serde.d.mts} +1 -1
  474. package/build/serde/serde.d.mts.map +1 -0
  475. package/build/{serde.js → serde/serde.js} +4 -5
  476. package/build/serde/serde.js.map +1 -0
  477. package/build/{temporal.cjs → serde/temporal.cjs} +1 -1
  478. package/build/serde/temporal.cjs.map +1 -0
  479. package/build/{temporal.d.cts → serde/temporal.d.cts} +1 -1
  480. package/build/serde/temporal.d.cts.map +1 -0
  481. package/build/{temporal.d.mts → serde/temporal.d.mts} +1 -1
  482. package/build/serde/temporal.d.mts.map +1 -0
  483. package/build/{temporal.js → serde/temporal.js} +1 -1
  484. package/build/serde/temporal.js.map +1 -0
  485. package/build/{temporalMappers.cjs → serde/temporalMappers.cjs} +4 -5
  486. package/build/serde/temporalMappers.cjs.map +1 -0
  487. package/build/{temporalMappers.d.cts → serde/temporalMappers.d.cts} +1 -1
  488. package/build/serde/temporalMappers.d.cts.map +1 -0
  489. package/build/{temporalMappers.d.mts → serde/temporalMappers.d.mts} +1 -1
  490. package/build/serde/temporalMappers.d.mts.map +1 -0
  491. package/build/{temporalMappers.js → serde/temporalMappers.js} +2 -3
  492. package/build/serde/temporalMappers.js.map +1 -0
  493. package/build/upsert.cjs +1 -1
  494. package/build/upsert.js +1 -1
  495. package/build/utils.cjs +0 -1
  496. package/build/utils.cjs.map +1 -1
  497. package/build/utils.d.cts +1 -1
  498. package/build/utils.d.mts +1 -1
  499. package/build/utils.js +0 -1
  500. package/build/utils.js.map +1 -1
  501. package/package.json +2 -2
  502. package/build/FlushLock.cjs.map +0 -1
  503. package/build/FlushLock.d.cts.map +0 -1
  504. package/build/FlushLock.d.mts.map +0 -1
  505. package/build/FlushLock.js.map +0 -1
  506. package/build/HintTree.cjs.map +0 -1
  507. package/build/HintTree.d.cts.map +0 -1
  508. package/build/HintTree.d.mts.map +0 -1
  509. package/build/HintTree.js.map +0 -1
  510. package/build/IsLoadedCache.cjs.map +0 -1
  511. package/build/IsLoadedCache.d.cts.map +0 -1
  512. package/build/IsLoadedCache.d.mts.map +0 -1
  513. package/build/IsLoadedCache.js.map +0 -1
  514. package/build/JoinRows.cjs.map +0 -1
  515. package/build/JoinRows.d.cts.map +0 -1
  516. package/build/JoinRows.d.mts.map +0 -1
  517. package/build/JoinRows.js.map +0 -1
  518. package/build/PendingChanges.d.cts.map +0 -1
  519. package/build/PendingChanges.d.mts.map +0 -1
  520. package/build/PendingChanges.js +0 -2
  521. package/build/ReactionsManager.cjs.map +0 -1
  522. package/build/ReactionsManager.d.cts.map +0 -1
  523. package/build/ReactionsManager.d.mts.map +0 -1
  524. package/build/ReactionsManager.js.map +0 -1
  525. package/build/Todo.cjs.map +0 -1
  526. package/build/Todo.d.cts.map +0 -1
  527. package/build/Todo.d.mts.map +0 -1
  528. package/build/Todo.js.map +0 -1
  529. package/build/TypeInfo.cjs.map +0 -1
  530. package/build/TypeInfo.d.cts.map +0 -1
  531. package/build/TypeInfo.d.mts.map +0 -1
  532. package/build/TypeInfo.js.map +0 -1
  533. package/build/columns.cjs.map +0 -1
  534. package/build/columns.d.cts.map +0 -1
  535. package/build/columns.d.mts.map +0 -1
  536. package/build/columns.js.map +0 -1
  537. package/build/driverApi.cjs +0 -18
  538. package/build/driverApi.cjs.map +0 -1
  539. package/build/driverApi.d.cts +0 -22
  540. package/build/driverApi.d.cts.map +0 -1
  541. package/build/driverApi.d.mts +0 -22
  542. package/build/driverApi.d.mts.map +0 -1
  543. package/build/driverApi.js +0 -18
  544. package/build/driverApi.js.map +0 -1
  545. package/build/fieldSerde.cjs.map +0 -1
  546. package/build/fieldSerde.d.cts.map +0 -1
  547. package/build/fieldSerde.d.mts.map +0 -1
  548. package/build/fieldSerde.js.map +0 -1
  549. package/build/loadHints.cjs.map +0 -1
  550. package/build/loadHints.d.cts.map +0 -1
  551. package/build/loadHints.d.mts.map +0 -1
  552. package/build/loadHints.js.map +0 -1
  553. package/build/loadLens.cjs.map +0 -1
  554. package/build/loadLens.d.cts.map +0 -1
  555. package/build/loadLens.d.mts.map +0 -1
  556. package/build/loadLens.js.map +0 -1
  557. package/build/reactiveHints.cjs.map +0 -1
  558. package/build/reactiveHints.d.cts.map +0 -1
  559. package/build/reactiveHints.d.mts.map +0 -1
  560. package/build/reactiveHints.js.map +0 -1
  561. package/build/serde.cjs.map +0 -1
  562. package/build/serde.d.cts.map +0 -1
  563. package/build/serde.d.mts.map +0 -1
  564. package/build/serde.js.map +0 -1
  565. package/build/temporal.cjs.map +0 -1
  566. package/build/temporal.d.cts.map +0 -1
  567. package/build/temporal.d.mts.map +0 -1
  568. package/build/temporal.js.map +0 -1
  569. package/build/temporalMappers.cjs.map +0 -1
  570. package/build/temporalMappers.d.cts.map +0 -1
  571. package/build/temporalMappers.d.mts.map +0 -1
  572. package/build/temporalMappers.js.map +0 -1
  573. package/build/unnest.cjs.map +0 -1
  574. package/build/unnest.d.cts.map +0 -1
  575. package/build/unnest.d.mts.map +0 -1
  576. package/build/unnest.js.map +0 -1
  577. package/build/withLoaded.cjs.map +0 -1
  578. package/build/withLoaded.d.cts.map +0 -1
  579. package/build/withLoaded.d.mts.map +0 -1
  580. package/build/withLoaded.js.map +0 -1
@@ -1,6 +1,4 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- require("./loadHints.cjs");
3
- require("./fieldSerde.cjs");
4
2
  const require_configure = require("./configure.cjs");
5
3
  require("./config.cjs");
6
4
  require("./EntityManager.cjs");
@@ -1 +1 @@
1
- {"version":3,"file":"EntityMetadata.cjs","names":["getInstanceData","getMetadataForType","isEntity"],"sources":["../src/EntityMetadata.ts"],"sourcesContent":["import { getInstanceData } from \"./BaseEntity.ts\";\nimport { type Column, type ColumnDescriptors } from \"./columns.ts\";\nimport { type ConfigApi, type Reactable, type ReactiveRule } from \"./config.ts\";\nimport { getMetadataForType } from \"./configure.ts\";\nimport { type Entity, isEntity } from \"./Entity.ts\";\nimport { type EntityManager, type MaybeAbstractEntityConstructor, type TimestampFields } from \"./EntityManager.ts\";\nimport { type EnumMetadata } from \"./EnumMetadata.ts\";\nimport { type FieldSerde, type PolymorphicKeySerde } from \"./fieldSerde.ts\";\nimport { type DeepNew } from \"./loadHints.ts\";\n\nexport function getMetadata<T extends Entity>(entity: T): EntityMetadata<T>;\nexport function getMetadata<T extends Entity>(type: MaybeAbstractEntityConstructor<T>): EntityMetadata<T>;\nexport function getMetadata<T extends Entity>(meta: EntityMetadata): EntityMetadata;\nexport function getMetadata<T extends Entity>(\n param: T | MaybeAbstractEntityConstructor<T> | EntityMetadata,\n): EntityMetadata {\n if (!param) throw new Error(`Cannot getMetadata of ${param}`);\n return (\n typeof param === \"function\" ? (param as any).metadata : \"cstr\" in param ? param : getInstanceData(param).metadata\n ) as EntityMetadata;\n}\n\n/** Returns the metadata layer that declares `fieldName`, i.e. `Task.tags` for `TaskOld.tags`. */\nexport function getMetadataForField(meta: EntityMetadata, fieldName: string): EntityMetadata {\n if (!meta.allFields[fieldName]) throw new Error(`Field '${fieldName}' not found on ${meta.type}`);\n // I.e. `TaskOld.tags` is an STI-inherited `Task.tags` and should walk up, but `SmallPublisherGroup.publishers`\n // is a CTI-specialized `PublisherGroup.publishers` and should stay on `SmallPublisherGroup`.\n while (!(fieldName in meta.fields) && meta.allFields[fieldName]?.specialized !== true && meta.baseType) {\n meta = getMetadataForType(meta.baseType);\n }\n return meta;\n}\n\n/**\n * Runtime metadata about an entity.\n *\n * The `joist-codegen` step will generate this by reading the database schema at build/codegen\n * time, along with any customizations in `joist-config.json`.\n *\n * Note: This has no generic, like `T extends Entity`, because `Entity<IdType>` i.e. with\n * an unknown string/id type, causes issues when we want to generically mix `EntityMetadata`\n * of different types, that even liberally using `EntityMetadata<any>` did not avoid.\n */\nexport interface EntityMetadata<T extends Entity = any> {\n cstr: MaybeAbstractEntityConstructor<T>;\n type: string;\n /** How the domain entity's id is represented. */\n idType: \"tagged-string\" | \"untagged-string\" | \"number\";\n /** The database column type, i.e. used to do `::type` casts in Postgres. */\n idDbType: \"bigint\" | \"int\" | \"uuid\" | \"text\";\n tableName: string;\n /** Whether codegen verified this table is a supported SQL mutation target; does not gate reads. */\n supportsEmExecute?: boolean;\n /** If we're a subtype, our immediate base type's name, e.g. for `SmallPublisher` this would be `Publisher`. */\n baseType: string | undefined;\n inheritanceType?: \"sti\" | \"cti\" | undefined;\n /** Indicates the field to use to derive which subtype to instantiate; only set on the base meta. */\n stiDiscriminatorField?: string;\n /** The discriminator enum value for this subtype; only set on sub metas. */\n stiDiscriminatorValue?: number;\n /** Whether this type is abstract (cannot be instantiated directly). */\n ctiAbstract?: boolean;\n tagName: string;\n fields: Record<string, Field>;\n /** Physical storage descriptors, without CTI base columns; STI metadata shares its base table. */\n columns: ColumnDescriptors;\n allFields: Record<string, Field & { aliasSuffix: string; specialized?: true }>;\n /** Usually polys are in `allFields`, but we pull the components out for comp-specific finds, like `parentBook`. */\n polyComponentFields?: Record<string, Field & { aliasSuffix: string }>;\n // Using `any` to avoid type errors between BaseType.metadata & SubType.metadata static fields\n config: ConfigApi<any, any>;\n /** The lazy list of non-read-only reactables for this metadata and its base types. */\n reactables?: Reactable[];\n /** The lazy lookup of non-read-only reactables by source field name. */\n reactablesByField?: ReadonlyMap<string, Reactable[]>;\n /** The lazy list of all reactables for this metadata and its base types. */\n reactablesIncludingReadOnly?: Reactable[];\n /** The lazy lookup of all reactables by source field name. */\n reactablesIncludingReadOnlyByField?: ReadonlyMap<string, Reactable[]>;\n /** The lazy list of reactive validation rules for this metadata and its subtypes. */\n reactiveRules?: ReactiveRule[];\n /** The lazy list of reactive *commit* rules (post-flush/pre-commit) for this metadata and its subtypes. */\n reactiveCommitRules?: ReactiveRule[];\n /** Lazily-cached: whether flushing an entity of this type could trigger any `addCommitRule` work. */\n hasCommitRules?: boolean;\n /** The lazily-cached set of own `lazy` primitive field names, i.e. columns excluded from the default SELECT. */\n lazyFieldNames?: ReadonlySet<string>;\n /** The lazily-cached list of sync-derived (`hasReactiveField`-less) field names, recalced during flush. */\n syncDerivedFields?: string[];\n /** Lazily-cached: whether this entity has any `lazy` columns, i.e. so the default SELECT lists columns explicitly. */\n hasLazyColumns?: boolean;\n orderBy: string | undefined;\n /** Flat field names that can be used to find existing rows before creating. I.e. [[\"email\"], [\"author\", \"title\"]]. */\n uniqueBy?: string[][];\n timestampFields: TimestampFields | undefined;\n // Ideally this would be the application-specific EntityManager (to avoid anys), but it doesn't really matter\n factory: (em: EntityManager<any, any, any>, opts?: any) => DeepNew<T>;\n /** The list of base types for this subtype, e.g. for Dog it'd be [Animal, Mammal]. */\n baseTypes: EntityMetadata[];\n /** The list of subtypes for this base type, e.g. for Animal it'd be `[Mammal, Dog]`. */\n subTypes: EntityMetadata[];\n /** Cached `[...baseTypes, this]` set up by `configureMetadata`, so hot paths avoid re-allocating it. */\n baseSelfMetas?: EntityMetadata[];\n /** Cached `[...baseTypes, this, ...subTypes]` set up by `configureMetadata`, so hot paths avoid re-allocating it. */\n baseSelfAndSubMetas?: EntityMetadata[];\n /** The lazy lookup of subtypes by type name, i.e. `Animal.metadata.subTypesByType.get(\"Dog\")`. */\n subTypesByType?: ReadonlyMap<string, EntityMetadata>;\n /** The lazy lookup of STI subtypes by discriminator value, i.e. `Task.metadata.subTypesByStiValue.get(1)`. */\n subTypesByStiValue?: ReadonlyMap<unknown, EntityMetadata>;\n /** The lazy STI discriminator column name, i.e. `Task.metadata.stiDiscriminatorColumnName`. */\n stiDiscriminatorColumnName?: string;\n /** If the schema is lacking deferred FKs, this is our insertion order. */\n nonDeferredFkOrder?: number;\n}\n\nexport type Field =\n | PrimaryKeyField\n | PrimitiveField\n | EnumField\n | OneToManyField\n | LargeOneToManyField\n | ManyToOneField\n | ManyToManyField\n | ManyToManyEnumField\n | OneToOneField\n | PolymorphicField;\n\n// Only the fields that have defined `serde` keys; should be a mapped type of Field\nexport type SerdeField = PrimaryKeyField | PrimitiveField | EnumField | ManyToOneField | PolymorphicField;\n\nexport type PrimaryKeyField = {\n kind: \"primaryKey\";\n fieldName: string;\n fieldIdName: undefined;\n required: true;\n serde: FieldSerde;\n immutable: true;\n};\n\nexport type PrimitiveField = {\n kind: \"primitive\";\n fieldName: string;\n fieldIdName: undefined;\n required: boolean;\n derived: \"orm\" | \"sync\" | \"async\" | false;\n protected: boolean;\n type: string | Function;\n serde: FieldSerde;\n immutable: boolean;\n citext?: boolean;\n default?: \"schema\" | \"config\";\n sanitize?: boolean;\n /** When true, this column is excluded from the entity's default SELECT and lazy-loaded via a `LazyField`. */\n lazy?: boolean;\n};\n\nexport type EnumField = {\n kind: \"enum\";\n fieldName: string;\n fieldIdName: undefined;\n required: boolean;\n derived: \"sync\" | \"async\" | false;\n enumDetailType: { getValues(): ReadonlyArray<unknown>; findById(id: any): unknown };\n serde: FieldSerde;\n immutable: boolean;\n default?: \"schema\" | \"config\";\n};\n\nexport type OneToManyField = {\n kind: \"o2m\";\n fieldName: string;\n fieldIdName: string;\n required: boolean;\n otherMetadata: () => EntityMetadata;\n otherFieldName: string;\n /** Useful when our other side is a poly, to find which component points back to us. */\n otherColumnName: string;\n serde: undefined;\n immutable: false;\n orderBy?: { field: string; direction: \"ASC\" | \"DESC\" };\n /** When `\"include\"`, this collection's `.get`/`.load` returns soft-deleted entities instead of hiding them. */\n softDeletes?: \"include\" | \"exclude\";\n};\n\nexport type LargeOneToManyField = {\n kind: \"lo2m\";\n fieldName: string;\n fieldIdName: string;\n required: boolean;\n otherMetadata: () => EntityMetadata;\n otherFieldName: string;\n /** Useful when our other side is a poly, to find which component points back to us. */\n otherColumnName: string;\n serde: undefined;\n immutable: false;\n};\n\nexport type ManyToOneField = {\n kind: \"m2o\";\n fieldName: string;\n fieldIdName: string;\n required: boolean;\n otherMetadata: () => EntityMetadata;\n otherFieldName: string;\n serde: FieldSerde;\n immutable: boolean;\n derived: \"async\" | false;\n default?: \"schema\" | \"config\";\n};\n\nexport type ManyToManyField = {\n kind: \"m2m\";\n fieldName: string;\n fieldIdName: string;\n required: boolean;\n derived: \"async\" | \"otherSide\" | false;\n otherMetadata: () => EntityMetadata;\n otherFieldName: string;\n serde: undefined;\n immutable: false;\n joinTableName: string;\n columnNames: [string, string];\n /** Whether the join table has a surrogate `id` PK; if false the FK pair is the composite PK. */\n hasJoinTableId: boolean;\n /** When `\"include\"`, this collection's `.get`/`.load` returns soft-deleted entities instead of hiding them. */\n softDeletes?: \"include\" | \"exclude\";\n};\n\n/**\n * A many-to-many between an entity and an enum \"table\", e.g. `Publisher.logoColors` backed by a\n * `publisher_logo_colors` join table joining `publishers` to the `color` enum table.\n *\n * To the user this looks like an array of enum codes (`Color[]`), but unlike an enum-array column it\n * is lazy (needs a load hint) because it lives in its own join table.\n */\nexport type ManyToManyEnumField = {\n kind: \"m2mEnum\";\n fieldName: string;\n fieldIdName: undefined;\n required: false;\n derived: false;\n /** The enum's metadata, used to map enum codes <-> their numeric ids. */\n enumDetailType: EnumMetadata<any, any, number>;\n serde: undefined;\n immutable: false;\n joinTableName: string;\n /** `[entityColumn, enumColumn]`, e.g. `[\"publisher_id\", \"color_id\"]`. */\n columnNames: [string, string];\n /** Whether the join table has a surrogate `id` PK; if false the FK pair is the composite PK. */\n hasJoinTableId: boolean;\n};\n\nexport type OneToOneField = {\n kind: \"o2o\";\n fieldName: string;\n fieldIdName: string;\n required: boolean;\n otherMetadata: () => EntityMetadata;\n otherFieldName: string;\n /** Useful when our other side is a poly, to find which component points back to us. */\n otherColumnName: string;\n serde: undefined;\n immutable: false;\n};\n\nexport type PolymorphicField = {\n kind: \"poly\";\n fieldName: string; // eg `parent`\n fieldIdName: string; // `parentId`\n required: boolean;\n components: PolymorphicFieldComponent[];\n serde: PolymorphicKeySerde;\n immutable: boolean;\n};\n\nexport type PolymorphicFieldComponent = {\n otherMetadata: () => EntityMetadata;\n otherFieldName: string; // eg `comment` or `comments`\n columnName: string; // eg `parent_book_id` or `parent_book_review_id`\n column: Column;\n};\n\nexport function isOneToManyField(ormField: Field): ormField is OneToManyField {\n return ormField.kind === \"o2m\";\n}\n\nexport function isManyToOneField(ormField: Field): ormField is ManyToOneField {\n return ormField.kind === \"m2o\";\n}\n\nexport function isManyToManyField(ormField: Field): ormField is ManyToManyField {\n return ormField.kind === \"m2m\";\n}\n\nexport function isManyToManyEnumField(ormField: Field): ormField is ManyToManyEnumField {\n return ormField.kind === \"m2mEnum\";\n}\n\nexport function isOneToOneField(ormField: Field): ormField is OneToOneField {\n return ormField.kind === \"o2o\";\n}\n\nexport function isPolymorphicField(ormField: Field): ormField is PolymorphicField {\n return ormField.kind === \"poly\";\n}\n\nexport function isReferenceField(ormField: Field): ormField is ManyToOneField | OneToOneField | PolymorphicField {\n return ormField.kind === \"m2o\" || ormField.kind === \"o2o\" || ormField.kind === \"poly\";\n}\n\nexport function isCollectionField(ormField: Field): ormField is OneToManyField | ManyToManyField {\n return ormField.kind === \"o2m\" || ormField.kind === \"m2m\";\n}\n\nexport function getBaseAndSelfMetas(meta: EntityMetadata): EntityMetadata[];\nexport function getBaseAndSelfMetas(entity: Entity): EntityMetadata[];\nexport function getBaseAndSelfMetas(param: Entity | EntityMetadata): EntityMetadata[] {\n return isEntity(param)\n ? getBaseSelfAndSubMetas(getMetadata(param))\n : (param.baseSelfMetas ?? [...param.baseTypes, param]);\n}\n\nexport function getBaseSelfAndSubMetas(meta: EntityMetadata): EntityMetadata[] {\n return meta.baseSelfAndSubMetas ?? [...meta.baseTypes, meta, ...meta.subTypes];\n}\n\nexport function getSubMetas(meta: EntityMetadata): EntityMetadata[] {\n // We should do recursion at some point\n return meta.subTypes;\n}\n\nexport function getBaseMeta(meta: EntityMetadata): EntityMetadata {\n if (!meta.baseType) {\n return meta;\n } else {\n return meta.baseTypes[0];\n }\n}\n"],"mappings":";;;;;;;;;AAaA,SAAgB,YACd,OACgB;CAChB,IAAI,CAAC,OAAO,MAAM,IAAI,MAAM,yBAAyB,OAAO;CAC5D,OACE,OAAO,UAAU,aAAc,MAAc,WAAW,UAAU,QAAQ,QAAQA,mBAAAA,gBAAgB,KAAK,CAAC,CAAC;AAE7G;;AAGA,SAAgB,oBAAoB,MAAsB,WAAmC;CAC3F,IAAI,CAAC,KAAK,UAAU,YAAY,MAAM,IAAI,MAAM,UAAU,UAAU,iBAAiB,KAAK,MAAM;CAGhG,OAAO,EAAE,aAAa,KAAK,WAAW,KAAK,UAAU,UAAU,EAAE,gBAAgB,QAAQ,KAAK,UAC5F,OAAOC,kBAAAA,mBAAmB,KAAK,QAAQ;CAEzC,OAAO;AACT;AA2PA,SAAgB,iBAAiB,UAA6C;CAC5E,OAAO,SAAS,SAAS;AAC3B;AAEA,SAAgB,iBAAiB,UAA6C;CAC5E,OAAO,SAAS,SAAS;AAC3B;AAEA,SAAgB,kBAAkB,UAA8C;CAC9E,OAAO,SAAS,SAAS;AAC3B;AAEA,SAAgB,sBAAsB,UAAkD;CACtF,OAAO,SAAS,SAAS;AAC3B;AAEA,SAAgB,gBAAgB,UAA4C;CAC1E,OAAO,SAAS,SAAS;AAC3B;AAEA,SAAgB,mBAAmB,UAA+C;CAChF,OAAO,SAAS,SAAS;AAC3B;AAEA,SAAgB,iBAAiB,UAAgF;CAC/G,OAAO,SAAS,SAAS,SAAS,SAAS,SAAS,SAAS,SAAS,SAAS;AACjF;AAEA,SAAgB,kBAAkB,UAA+D;CAC/F,OAAO,SAAS,SAAS,SAAS,SAAS,SAAS;AACtD;AAIA,SAAgB,oBAAoB,OAAkD;CACpF,OAAOC,eAAAA,SAAS,KAAK,IACjB,uBAAuB,YAAY,KAAK,CAAC,IACxC,MAAM,iBAAiB,CAAC,GAAG,MAAM,WAAW,KAAK;AACxD;AAEA,SAAgB,uBAAuB,MAAwC;CAC7E,OAAO,KAAK,uBAAuB;EAAC,GAAG,KAAK;EAAW;EAAM,GAAG,KAAK;CAAQ;AAC/E;AAEA,SAAgB,YAAY,MAAwC;CAElE,OAAO,KAAK;AACd;AAEA,SAAgB,YAAY,MAAsC;CAChE,IAAI,CAAC,KAAK,UACR,OAAO;MAEP,OAAO,KAAK,UAAU;AAE1B"}
1
+ {"version":3,"file":"EntityMetadata.cjs","names":["getInstanceData","getMetadataForType","isEntity"],"sources":["../src/EntityMetadata.ts"],"sourcesContent":["import { getInstanceData } from \"./BaseEntity.ts\";\nimport { type ConfigApi, type Reactable, type ReactiveRule } from \"./config.ts\";\nimport { getMetadataForType } from \"./configure.ts\";\nimport { type Entity, isEntity } from \"./Entity.ts\";\nimport { type EntityManager, type MaybeAbstractEntityConstructor, type TimestampFields } from \"./EntityManager.ts\";\nimport { type EnumMetadata } from \"./EnumMetadata.ts\";\nimport type { DeepNew } from \"./loading/loadHints.ts\";\nimport type { Column, ColumnDescriptors } from \"./serde/columns.ts\";\nimport type { FieldSerde, PolymorphicKeySerde } from \"./serde/fieldSerde.ts\";\n\nexport function getMetadata<T extends Entity>(entity: T): EntityMetadata<T>;\nexport function getMetadata<T extends Entity>(type: MaybeAbstractEntityConstructor<T>): EntityMetadata<T>;\nexport function getMetadata<T extends Entity>(meta: EntityMetadata): EntityMetadata;\nexport function getMetadata<T extends Entity>(\n param: T | MaybeAbstractEntityConstructor<T> | EntityMetadata,\n): EntityMetadata {\n if (!param) throw new Error(`Cannot getMetadata of ${param}`);\n return (\n typeof param === \"function\" ? (param as any).metadata : \"cstr\" in param ? param : getInstanceData(param).metadata\n ) as EntityMetadata;\n}\n\n/** Returns the metadata layer that declares `fieldName`, i.e. `Task.tags` for `TaskOld.tags`. */\nexport function getMetadataForField(meta: EntityMetadata, fieldName: string): EntityMetadata {\n if (!meta.allFields[fieldName]) throw new Error(`Field '${fieldName}' not found on ${meta.type}`);\n // I.e. `TaskOld.tags` is an STI-inherited `Task.tags` and should walk up, but `SmallPublisherGroup.publishers`\n // is a CTI-specialized `PublisherGroup.publishers` and should stay on `SmallPublisherGroup`.\n while (!(fieldName in meta.fields) && meta.allFields[fieldName]?.specialized !== true && meta.baseType) {\n meta = getMetadataForType(meta.baseType);\n }\n return meta;\n}\n\n/**\n * Runtime metadata about an entity.\n *\n * The `joist-codegen` step will generate this by reading the database schema at build/codegen\n * time, along with any customizations in `joist-config.json`.\n *\n * Note: This has no generic, like `T extends Entity`, because `Entity<IdType>` i.e. with\n * an unknown string/id type, causes issues when we want to generically mix `EntityMetadata`\n * of different types, that even liberally using `EntityMetadata<any>` did not avoid.\n */\nexport interface EntityMetadata<T extends Entity = any> {\n cstr: MaybeAbstractEntityConstructor<T>;\n type: string;\n /** How the domain entity's id is represented. */\n idType: \"tagged-string\" | \"untagged-string\" | \"number\";\n /** The database column type, i.e. used to do `::type` casts in Postgres. */\n idDbType: \"bigint\" | \"int\" | \"uuid\" | \"text\";\n tableName: string;\n /** Whether codegen verified this table is a supported SQL mutation target; does not gate reads. */\n supportsEmExecute?: boolean;\n /** If we're a subtype, our immediate base type's name, e.g. for `SmallPublisher` this would be `Publisher`. */\n baseType: string | undefined;\n inheritanceType?: \"sti\" | \"cti\" | undefined;\n /** Indicates the field to use to derive which subtype to instantiate; only set on the base meta. */\n stiDiscriminatorField?: string;\n /** The discriminator enum value for this subtype; only set on sub metas. */\n stiDiscriminatorValue?: number;\n /** Whether this type is abstract (cannot be instantiated directly). */\n ctiAbstract?: boolean;\n tagName: string;\n fields: Record<string, Field>;\n /** Physical storage descriptors, without CTI base columns; STI metadata shares its base table. */\n columns: ColumnDescriptors;\n allFields: Record<string, Field & { aliasSuffix: string; specialized?: true }>;\n /** Usually polys are in `allFields`, but we pull the components out for comp-specific finds, like `parentBook`. */\n polyComponentFields?: Record<string, Field & { aliasSuffix: string }>;\n // Using `any` to avoid type errors between BaseType.metadata & SubType.metadata static fields\n config: ConfigApi<any, any>;\n /** The lazy list of non-read-only reactables for this metadata and its base types. */\n reactables?: Reactable[];\n /** The lazy lookup of non-read-only reactables by source field name. */\n reactablesByField?: ReadonlyMap<string, Reactable[]>;\n /** The lazy list of all reactables for this metadata and its base types. */\n reactablesIncludingReadOnly?: Reactable[];\n /** The lazy lookup of all reactables by source field name. */\n reactablesIncludingReadOnlyByField?: ReadonlyMap<string, Reactable[]>;\n /** The lazy list of reactive validation rules for this metadata and its subtypes. */\n reactiveRules?: ReactiveRule[];\n /** The lazy list of reactive *commit* rules (post-flush/pre-commit) for this metadata and its subtypes. */\n reactiveCommitRules?: ReactiveRule[];\n /** Lazily-cached: whether flushing an entity of this type could trigger any `addCommitRule` work. */\n hasCommitRules?: boolean;\n /** The lazily-cached set of own `lazy` primitive field names, i.e. columns excluded from the default SELECT. */\n lazyFieldNames?: ReadonlySet<string>;\n /** The lazily-cached list of sync-derived (`hasReactiveField`-less) field names, recalced during flush. */\n syncDerivedFields?: string[];\n /** Lazily-cached: whether this entity has any `lazy` columns, i.e. so the default SELECT lists columns explicitly. */\n hasLazyColumns?: boolean;\n orderBy: string | undefined;\n /** Flat field names that can be used to find existing rows before creating. I.e. [[\"email\"], [\"author\", \"title\"]]. */\n uniqueBy?: string[][];\n timestampFields: TimestampFields | undefined;\n // Ideally this would be the application-specific EntityManager (to avoid anys), but it doesn't really matter\n factory: (em: EntityManager<any, any, any>, opts?: any) => DeepNew<T>;\n /** The list of base types for this subtype, e.g. for Dog it'd be [Animal, Mammal]. */\n baseTypes: EntityMetadata[];\n /** The list of subtypes for this base type, e.g. for Animal it'd be `[Mammal, Dog]`. */\n subTypes: EntityMetadata[];\n /** Cached `[...baseTypes, this]` set up by `configureMetadata`, so hot paths avoid re-allocating it. */\n baseSelfMetas?: EntityMetadata[];\n /** Cached `[...baseTypes, this, ...subTypes]` set up by `configureMetadata`, so hot paths avoid re-allocating it. */\n baseSelfAndSubMetas?: EntityMetadata[];\n /** The lazy lookup of subtypes by type name, i.e. `Animal.metadata.subTypesByType.get(\"Dog\")`. */\n subTypesByType?: ReadonlyMap<string, EntityMetadata>;\n /** The lazy lookup of STI subtypes by discriminator value, i.e. `Task.metadata.subTypesByStiValue.get(1)`. */\n subTypesByStiValue?: ReadonlyMap<unknown, EntityMetadata>;\n /** The lazy STI discriminator column name, i.e. `Task.metadata.stiDiscriminatorColumnName`. */\n stiDiscriminatorColumnName?: string;\n /** If the schema is lacking deferred FKs, this is our insertion order. */\n nonDeferredFkOrder?: number;\n}\n\nexport type Field =\n | PrimaryKeyField\n | PrimitiveField\n | EnumField\n | OneToManyField\n | LargeOneToManyField\n | ManyToOneField\n | ManyToManyField\n | ManyToManyEnumField\n | OneToOneField\n | PolymorphicField;\n\n// Only the fields that have defined `serde` keys; should be a mapped type of Field\nexport type SerdeField = PrimaryKeyField | PrimitiveField | EnumField | ManyToOneField | PolymorphicField;\n\nexport type PrimaryKeyField = {\n kind: \"primaryKey\";\n fieldName: string;\n fieldIdName: undefined;\n required: true;\n serde: FieldSerde;\n immutable: true;\n};\n\nexport type PrimitiveField = {\n kind: \"primitive\";\n fieldName: string;\n fieldIdName: undefined;\n required: boolean;\n derived: \"orm\" | \"sync\" | \"async\" | false;\n protected: boolean;\n type: string | Function;\n serde: FieldSerde;\n immutable: boolean;\n citext?: boolean;\n default?: \"schema\" | \"config\";\n sanitize?: boolean;\n /** When true, this column is excluded from the entity's default SELECT and lazy-loaded via a `LazyField`. */\n lazy?: boolean;\n};\n\nexport type EnumField = {\n kind: \"enum\";\n fieldName: string;\n fieldIdName: undefined;\n required: boolean;\n derived: \"sync\" | \"async\" | false;\n enumDetailType: { getValues(): ReadonlyArray<unknown>; findById(id: any): unknown };\n serde: FieldSerde;\n immutable: boolean;\n default?: \"schema\" | \"config\";\n};\n\nexport type OneToManyField = {\n kind: \"o2m\";\n fieldName: string;\n fieldIdName: string;\n required: boolean;\n otherMetadata: () => EntityMetadata;\n otherFieldName: string;\n /** Useful when our other side is a poly, to find which component points back to us. */\n otherColumnName: string;\n serde: undefined;\n immutable: false;\n orderBy?: { field: string; direction: \"ASC\" | \"DESC\" };\n /** When `\"include\"`, this collection's `.get`/`.load` returns soft-deleted entities instead of hiding them. */\n softDeletes?: \"include\" | \"exclude\";\n};\n\nexport type LargeOneToManyField = {\n kind: \"lo2m\";\n fieldName: string;\n fieldIdName: string;\n required: boolean;\n otherMetadata: () => EntityMetadata;\n otherFieldName: string;\n /** Useful when our other side is a poly, to find which component points back to us. */\n otherColumnName: string;\n serde: undefined;\n immutable: false;\n};\n\nexport type ManyToOneField = {\n kind: \"m2o\";\n fieldName: string;\n fieldIdName: string;\n required: boolean;\n otherMetadata: () => EntityMetadata;\n otherFieldName: string;\n serde: FieldSerde;\n immutable: boolean;\n derived: \"async\" | false;\n default?: \"schema\" | \"config\";\n};\n\nexport type ManyToManyField = {\n kind: \"m2m\";\n fieldName: string;\n fieldIdName: string;\n required: boolean;\n derived: \"async\" | \"otherSide\" | false;\n otherMetadata: () => EntityMetadata;\n otherFieldName: string;\n serde: undefined;\n immutable: false;\n joinTableName: string;\n columnNames: [string, string];\n /** Whether the join table has a surrogate `id` PK; if false the FK pair is the composite PK. */\n hasJoinTableId: boolean;\n /** When `\"include\"`, this collection's `.get`/`.load` returns soft-deleted entities instead of hiding them. */\n softDeletes?: \"include\" | \"exclude\";\n};\n\n/**\n * A many-to-many between an entity and an enum \"table\", e.g. `Publisher.logoColors` backed by a\n * `publisher_logo_colors` join table joining `publishers` to the `color` enum table.\n *\n * To the user this looks like an array of enum codes (`Color[]`), but unlike an enum-array column it\n * is lazy (needs a load hint) because it lives in its own join table.\n */\nexport type ManyToManyEnumField = {\n kind: \"m2mEnum\";\n fieldName: string;\n fieldIdName: undefined;\n required: false;\n derived: false;\n /** The enum's metadata, used to map enum codes <-> their numeric ids. */\n enumDetailType: EnumMetadata<any, any, number>;\n serde: undefined;\n immutable: false;\n joinTableName: string;\n /** `[entityColumn, enumColumn]`, e.g. `[\"publisher_id\", \"color_id\"]`. */\n columnNames: [string, string];\n /** Whether the join table has a surrogate `id` PK; if false the FK pair is the composite PK. */\n hasJoinTableId: boolean;\n};\n\nexport type OneToOneField = {\n kind: \"o2o\";\n fieldName: string;\n fieldIdName: string;\n required: boolean;\n otherMetadata: () => EntityMetadata;\n otherFieldName: string;\n /** Useful when our other side is a poly, to find which component points back to us. */\n otherColumnName: string;\n serde: undefined;\n immutable: false;\n};\n\nexport type PolymorphicField = {\n kind: \"poly\";\n fieldName: string; // eg `parent`\n fieldIdName: string; // `parentId`\n required: boolean;\n components: PolymorphicFieldComponent[];\n serde: PolymorphicKeySerde;\n immutable: boolean;\n};\n\nexport type PolymorphicFieldComponent = {\n otherMetadata: () => EntityMetadata;\n otherFieldName: string; // eg `comment` or `comments`\n columnName: string; // eg `parent_book_id` or `parent_book_review_id`\n column: Column;\n};\n\nexport function isOneToManyField(ormField: Field): ormField is OneToManyField {\n return ormField.kind === \"o2m\";\n}\n\nexport function isManyToOneField(ormField: Field): ormField is ManyToOneField {\n return ormField.kind === \"m2o\";\n}\n\nexport function isManyToManyField(ormField: Field): ormField is ManyToManyField {\n return ormField.kind === \"m2m\";\n}\n\nexport function isManyToManyEnumField(ormField: Field): ormField is ManyToManyEnumField {\n return ormField.kind === \"m2mEnum\";\n}\n\nexport function isOneToOneField(ormField: Field): ormField is OneToOneField {\n return ormField.kind === \"o2o\";\n}\n\nexport function isPolymorphicField(ormField: Field): ormField is PolymorphicField {\n return ormField.kind === \"poly\";\n}\n\nexport function isReferenceField(ormField: Field): ormField is ManyToOneField | OneToOneField | PolymorphicField {\n return ormField.kind === \"m2o\" || ormField.kind === \"o2o\" || ormField.kind === \"poly\";\n}\n\nexport function isCollectionField(ormField: Field): ormField is OneToManyField | ManyToManyField {\n return ormField.kind === \"o2m\" || ormField.kind === \"m2m\";\n}\n\nexport function getBaseAndSelfMetas(meta: EntityMetadata): EntityMetadata[];\nexport function getBaseAndSelfMetas(entity: Entity): EntityMetadata[];\nexport function getBaseAndSelfMetas(param: Entity | EntityMetadata): EntityMetadata[] {\n return isEntity(param)\n ? getBaseSelfAndSubMetas(getMetadata(param))\n : (param.baseSelfMetas ?? [...param.baseTypes, param]);\n}\n\nexport function getBaseSelfAndSubMetas(meta: EntityMetadata): EntityMetadata[] {\n return meta.baseSelfAndSubMetas ?? [...meta.baseTypes, meta, ...meta.subTypes];\n}\n\nexport function getSubMetas(meta: EntityMetadata): EntityMetadata[] {\n // We should do recursion at some point\n return meta.subTypes;\n}\n\nexport function getBaseMeta(meta: EntityMetadata): EntityMetadata {\n if (!meta.baseType) {\n return meta;\n } else {\n return meta.baseTypes[0];\n }\n}\n"],"mappings":";;;;;;;AAaA,SAAgB,YACd,OACgB;CAChB,IAAI,CAAC,OAAO,MAAM,IAAI,MAAM,yBAAyB,OAAO;CAC5D,OACE,OAAO,UAAU,aAAc,MAAc,WAAW,UAAU,QAAQ,QAAQA,mBAAAA,gBAAgB,KAAK,CAAC,CAAC;AAE7G;;AAGA,SAAgB,oBAAoB,MAAsB,WAAmC;CAC3F,IAAI,CAAC,KAAK,UAAU,YAAY,MAAM,IAAI,MAAM,UAAU,UAAU,iBAAiB,KAAK,MAAM;CAGhG,OAAO,EAAE,aAAa,KAAK,WAAW,KAAK,UAAU,UAAU,EAAE,gBAAgB,QAAQ,KAAK,UAC5F,OAAOC,kBAAAA,mBAAmB,KAAK,QAAQ;CAEzC,OAAO;AACT;AA2PA,SAAgB,iBAAiB,UAA6C;CAC5E,OAAO,SAAS,SAAS;AAC3B;AAEA,SAAgB,iBAAiB,UAA6C;CAC5E,OAAO,SAAS,SAAS;AAC3B;AAEA,SAAgB,kBAAkB,UAA8C;CAC9E,OAAO,SAAS,SAAS;AAC3B;AAEA,SAAgB,sBAAsB,UAAkD;CACtF,OAAO,SAAS,SAAS;AAC3B;AAEA,SAAgB,gBAAgB,UAA4C;CAC1E,OAAO,SAAS,SAAS;AAC3B;AAEA,SAAgB,mBAAmB,UAA+C;CAChF,OAAO,SAAS,SAAS;AAC3B;AAEA,SAAgB,iBAAiB,UAAgF;CAC/G,OAAO,SAAS,SAAS,SAAS,SAAS,SAAS,SAAS,SAAS,SAAS;AACjF;AAEA,SAAgB,kBAAkB,UAA+D;CAC/F,OAAO,SAAS,SAAS,SAAS,SAAS,SAAS;AACtD;AAIA,SAAgB,oBAAoB,OAAkD;CACpF,OAAOC,eAAAA,SAAS,KAAK,IACjB,uBAAuB,YAAY,KAAK,CAAC,IACxC,MAAM,iBAAiB,CAAC,GAAG,MAAM,WAAW,KAAK;AACxD;AAEA,SAAgB,uBAAuB,MAAwC;CAC7E,OAAO,KAAK,uBAAuB;EAAC,GAAG,KAAK;EAAW;EAAM,GAAG,KAAK;CAAQ;AAC/E;AAEA,SAAgB,YAAY,MAAwC;CAElE,OAAO,KAAK;AACd;AAEA,SAAgB,YAAY,MAAsC;CAChE,IAAI,CAAC,KAAK,UACR,OAAO;MAEP,OAAO,KAAK,UAAU;AAE1B"}
@@ -1,8 +1,8 @@
1
- import { Column, ColumnDescriptors } from "./columns.cjs";
2
1
  import { EnumMetadata } from "./EnumMetadata.cjs";
3
- import { DeepNew } from "./loadHints.cjs";
2
+ import { DeepNew } from "./loading/loadHints.cjs";
4
3
  import { ConfigApi, Reactable, ReactiveRule } from "./config.cjs";
5
- import { FieldSerde, PolymorphicKeySerde } from "./fieldSerde.cjs";
4
+ import { Column, ColumnDescriptors } from "./serde/columns.cjs";
5
+ import { FieldSerde, PolymorphicKeySerde } from "./serde/fieldSerde.cjs";
6
6
  import { EntityManager, MaybeAbstractEntityConstructor, TimestampFields } from "./EntityManager.cjs";
7
7
  import { Entity } from "./Entity.cjs";
8
8
  //#region src/EntityMetadata.d.ts
@@ -1,8 +1,8 @@
1
- import { Column, ColumnDescriptors } from "./columns.mjs";
2
1
  import { EnumMetadata } from "./EnumMetadata.mjs";
3
- import { DeepNew } from "./loadHints.mjs";
2
+ import { DeepNew } from "./loading/loadHints.mjs";
4
3
  import { ConfigApi, Reactable, ReactiveRule } from "./config.mjs";
5
- import { FieldSerde, PolymorphicKeySerde } from "./fieldSerde.mjs";
4
+ import { Column, ColumnDescriptors } from "./serde/columns.mjs";
5
+ import { FieldSerde, PolymorphicKeySerde } from "./serde/fieldSerde.mjs";
6
6
  import { EntityManager, MaybeAbstractEntityConstructor, TimestampFields } from "./EntityManager.mjs";
7
7
  import { Entity } from "./Entity.mjs";
8
8
  //#region src/EntityMetadata.d.ts
@@ -1,5 +1,3 @@
1
- import "./loadHints.js";
2
- import "./fieldSerde.js";
3
1
  import { getMetadataForType } from "./configure.js";
4
2
  import "./config.js";
5
3
  import "./EntityManager.js";
@@ -1 +1 @@
1
- {"version":3,"file":"EntityMetadata.js","names":[],"sources":["../src/EntityMetadata.ts"],"sourcesContent":["import { getInstanceData } from \"./BaseEntity.ts\";\nimport { type Column, type ColumnDescriptors } from \"./columns.ts\";\nimport { type ConfigApi, type Reactable, type ReactiveRule } from \"./config.ts\";\nimport { getMetadataForType } from \"./configure.ts\";\nimport { type Entity, isEntity } from \"./Entity.ts\";\nimport { type EntityManager, type MaybeAbstractEntityConstructor, type TimestampFields } from \"./EntityManager.ts\";\nimport { type EnumMetadata } from \"./EnumMetadata.ts\";\nimport { type FieldSerde, type PolymorphicKeySerde } from \"./fieldSerde.ts\";\nimport { type DeepNew } from \"./loadHints.ts\";\n\nexport function getMetadata<T extends Entity>(entity: T): EntityMetadata<T>;\nexport function getMetadata<T extends Entity>(type: MaybeAbstractEntityConstructor<T>): EntityMetadata<T>;\nexport function getMetadata<T extends Entity>(meta: EntityMetadata): EntityMetadata;\nexport function getMetadata<T extends Entity>(\n param: T | MaybeAbstractEntityConstructor<T> | EntityMetadata,\n): EntityMetadata {\n if (!param) throw new Error(`Cannot getMetadata of ${param}`);\n return (\n typeof param === \"function\" ? (param as any).metadata : \"cstr\" in param ? param : getInstanceData(param).metadata\n ) as EntityMetadata;\n}\n\n/** Returns the metadata layer that declares `fieldName`, i.e. `Task.tags` for `TaskOld.tags`. */\nexport function getMetadataForField(meta: EntityMetadata, fieldName: string): EntityMetadata {\n if (!meta.allFields[fieldName]) throw new Error(`Field '${fieldName}' not found on ${meta.type}`);\n // I.e. `TaskOld.tags` is an STI-inherited `Task.tags` and should walk up, but `SmallPublisherGroup.publishers`\n // is a CTI-specialized `PublisherGroup.publishers` and should stay on `SmallPublisherGroup`.\n while (!(fieldName in meta.fields) && meta.allFields[fieldName]?.specialized !== true && meta.baseType) {\n meta = getMetadataForType(meta.baseType);\n }\n return meta;\n}\n\n/**\n * Runtime metadata about an entity.\n *\n * The `joist-codegen` step will generate this by reading the database schema at build/codegen\n * time, along with any customizations in `joist-config.json`.\n *\n * Note: This has no generic, like `T extends Entity`, because `Entity<IdType>` i.e. with\n * an unknown string/id type, causes issues when we want to generically mix `EntityMetadata`\n * of different types, that even liberally using `EntityMetadata<any>` did not avoid.\n */\nexport interface EntityMetadata<T extends Entity = any> {\n cstr: MaybeAbstractEntityConstructor<T>;\n type: string;\n /** How the domain entity's id is represented. */\n idType: \"tagged-string\" | \"untagged-string\" | \"number\";\n /** The database column type, i.e. used to do `::type` casts in Postgres. */\n idDbType: \"bigint\" | \"int\" | \"uuid\" | \"text\";\n tableName: string;\n /** Whether codegen verified this table is a supported SQL mutation target; does not gate reads. */\n supportsEmExecute?: boolean;\n /** If we're a subtype, our immediate base type's name, e.g. for `SmallPublisher` this would be `Publisher`. */\n baseType: string | undefined;\n inheritanceType?: \"sti\" | \"cti\" | undefined;\n /** Indicates the field to use to derive which subtype to instantiate; only set on the base meta. */\n stiDiscriminatorField?: string;\n /** The discriminator enum value for this subtype; only set on sub metas. */\n stiDiscriminatorValue?: number;\n /** Whether this type is abstract (cannot be instantiated directly). */\n ctiAbstract?: boolean;\n tagName: string;\n fields: Record<string, Field>;\n /** Physical storage descriptors, without CTI base columns; STI metadata shares its base table. */\n columns: ColumnDescriptors;\n allFields: Record<string, Field & { aliasSuffix: string; specialized?: true }>;\n /** Usually polys are in `allFields`, but we pull the components out for comp-specific finds, like `parentBook`. */\n polyComponentFields?: Record<string, Field & { aliasSuffix: string }>;\n // Using `any` to avoid type errors between BaseType.metadata & SubType.metadata static fields\n config: ConfigApi<any, any>;\n /** The lazy list of non-read-only reactables for this metadata and its base types. */\n reactables?: Reactable[];\n /** The lazy lookup of non-read-only reactables by source field name. */\n reactablesByField?: ReadonlyMap<string, Reactable[]>;\n /** The lazy list of all reactables for this metadata and its base types. */\n reactablesIncludingReadOnly?: Reactable[];\n /** The lazy lookup of all reactables by source field name. */\n reactablesIncludingReadOnlyByField?: ReadonlyMap<string, Reactable[]>;\n /** The lazy list of reactive validation rules for this metadata and its subtypes. */\n reactiveRules?: ReactiveRule[];\n /** The lazy list of reactive *commit* rules (post-flush/pre-commit) for this metadata and its subtypes. */\n reactiveCommitRules?: ReactiveRule[];\n /** Lazily-cached: whether flushing an entity of this type could trigger any `addCommitRule` work. */\n hasCommitRules?: boolean;\n /** The lazily-cached set of own `lazy` primitive field names, i.e. columns excluded from the default SELECT. */\n lazyFieldNames?: ReadonlySet<string>;\n /** The lazily-cached list of sync-derived (`hasReactiveField`-less) field names, recalced during flush. */\n syncDerivedFields?: string[];\n /** Lazily-cached: whether this entity has any `lazy` columns, i.e. so the default SELECT lists columns explicitly. */\n hasLazyColumns?: boolean;\n orderBy: string | undefined;\n /** Flat field names that can be used to find existing rows before creating. I.e. [[\"email\"], [\"author\", \"title\"]]. */\n uniqueBy?: string[][];\n timestampFields: TimestampFields | undefined;\n // Ideally this would be the application-specific EntityManager (to avoid anys), but it doesn't really matter\n factory: (em: EntityManager<any, any, any>, opts?: any) => DeepNew<T>;\n /** The list of base types for this subtype, e.g. for Dog it'd be [Animal, Mammal]. */\n baseTypes: EntityMetadata[];\n /** The list of subtypes for this base type, e.g. for Animal it'd be `[Mammal, Dog]`. */\n subTypes: EntityMetadata[];\n /** Cached `[...baseTypes, this]` set up by `configureMetadata`, so hot paths avoid re-allocating it. */\n baseSelfMetas?: EntityMetadata[];\n /** Cached `[...baseTypes, this, ...subTypes]` set up by `configureMetadata`, so hot paths avoid re-allocating it. */\n baseSelfAndSubMetas?: EntityMetadata[];\n /** The lazy lookup of subtypes by type name, i.e. `Animal.metadata.subTypesByType.get(\"Dog\")`. */\n subTypesByType?: ReadonlyMap<string, EntityMetadata>;\n /** The lazy lookup of STI subtypes by discriminator value, i.e. `Task.metadata.subTypesByStiValue.get(1)`. */\n subTypesByStiValue?: ReadonlyMap<unknown, EntityMetadata>;\n /** The lazy STI discriminator column name, i.e. `Task.metadata.stiDiscriminatorColumnName`. */\n stiDiscriminatorColumnName?: string;\n /** If the schema is lacking deferred FKs, this is our insertion order. */\n nonDeferredFkOrder?: number;\n}\n\nexport type Field =\n | PrimaryKeyField\n | PrimitiveField\n | EnumField\n | OneToManyField\n | LargeOneToManyField\n | ManyToOneField\n | ManyToManyField\n | ManyToManyEnumField\n | OneToOneField\n | PolymorphicField;\n\n// Only the fields that have defined `serde` keys; should be a mapped type of Field\nexport type SerdeField = PrimaryKeyField | PrimitiveField | EnumField | ManyToOneField | PolymorphicField;\n\nexport type PrimaryKeyField = {\n kind: \"primaryKey\";\n fieldName: string;\n fieldIdName: undefined;\n required: true;\n serde: FieldSerde;\n immutable: true;\n};\n\nexport type PrimitiveField = {\n kind: \"primitive\";\n fieldName: string;\n fieldIdName: undefined;\n required: boolean;\n derived: \"orm\" | \"sync\" | \"async\" | false;\n protected: boolean;\n type: string | Function;\n serde: FieldSerde;\n immutable: boolean;\n citext?: boolean;\n default?: \"schema\" | \"config\";\n sanitize?: boolean;\n /** When true, this column is excluded from the entity's default SELECT and lazy-loaded via a `LazyField`. */\n lazy?: boolean;\n};\n\nexport type EnumField = {\n kind: \"enum\";\n fieldName: string;\n fieldIdName: undefined;\n required: boolean;\n derived: \"sync\" | \"async\" | false;\n enumDetailType: { getValues(): ReadonlyArray<unknown>; findById(id: any): unknown };\n serde: FieldSerde;\n immutable: boolean;\n default?: \"schema\" | \"config\";\n};\n\nexport type OneToManyField = {\n kind: \"o2m\";\n fieldName: string;\n fieldIdName: string;\n required: boolean;\n otherMetadata: () => EntityMetadata;\n otherFieldName: string;\n /** Useful when our other side is a poly, to find which component points back to us. */\n otherColumnName: string;\n serde: undefined;\n immutable: false;\n orderBy?: { field: string; direction: \"ASC\" | \"DESC\" };\n /** When `\"include\"`, this collection's `.get`/`.load` returns soft-deleted entities instead of hiding them. */\n softDeletes?: \"include\" | \"exclude\";\n};\n\nexport type LargeOneToManyField = {\n kind: \"lo2m\";\n fieldName: string;\n fieldIdName: string;\n required: boolean;\n otherMetadata: () => EntityMetadata;\n otherFieldName: string;\n /** Useful when our other side is a poly, to find which component points back to us. */\n otherColumnName: string;\n serde: undefined;\n immutable: false;\n};\n\nexport type ManyToOneField = {\n kind: \"m2o\";\n fieldName: string;\n fieldIdName: string;\n required: boolean;\n otherMetadata: () => EntityMetadata;\n otherFieldName: string;\n serde: FieldSerde;\n immutable: boolean;\n derived: \"async\" | false;\n default?: \"schema\" | \"config\";\n};\n\nexport type ManyToManyField = {\n kind: \"m2m\";\n fieldName: string;\n fieldIdName: string;\n required: boolean;\n derived: \"async\" | \"otherSide\" | false;\n otherMetadata: () => EntityMetadata;\n otherFieldName: string;\n serde: undefined;\n immutable: false;\n joinTableName: string;\n columnNames: [string, string];\n /** Whether the join table has a surrogate `id` PK; if false the FK pair is the composite PK. */\n hasJoinTableId: boolean;\n /** When `\"include\"`, this collection's `.get`/`.load` returns soft-deleted entities instead of hiding them. */\n softDeletes?: \"include\" | \"exclude\";\n};\n\n/**\n * A many-to-many between an entity and an enum \"table\", e.g. `Publisher.logoColors` backed by a\n * `publisher_logo_colors` join table joining `publishers` to the `color` enum table.\n *\n * To the user this looks like an array of enum codes (`Color[]`), but unlike an enum-array column it\n * is lazy (needs a load hint) because it lives in its own join table.\n */\nexport type ManyToManyEnumField = {\n kind: \"m2mEnum\";\n fieldName: string;\n fieldIdName: undefined;\n required: false;\n derived: false;\n /** The enum's metadata, used to map enum codes <-> their numeric ids. */\n enumDetailType: EnumMetadata<any, any, number>;\n serde: undefined;\n immutable: false;\n joinTableName: string;\n /** `[entityColumn, enumColumn]`, e.g. `[\"publisher_id\", \"color_id\"]`. */\n columnNames: [string, string];\n /** Whether the join table has a surrogate `id` PK; if false the FK pair is the composite PK. */\n hasJoinTableId: boolean;\n};\n\nexport type OneToOneField = {\n kind: \"o2o\";\n fieldName: string;\n fieldIdName: string;\n required: boolean;\n otherMetadata: () => EntityMetadata;\n otherFieldName: string;\n /** Useful when our other side is a poly, to find which component points back to us. */\n otherColumnName: string;\n serde: undefined;\n immutable: false;\n};\n\nexport type PolymorphicField = {\n kind: \"poly\";\n fieldName: string; // eg `parent`\n fieldIdName: string; // `parentId`\n required: boolean;\n components: PolymorphicFieldComponent[];\n serde: PolymorphicKeySerde;\n immutable: boolean;\n};\n\nexport type PolymorphicFieldComponent = {\n otherMetadata: () => EntityMetadata;\n otherFieldName: string; // eg `comment` or `comments`\n columnName: string; // eg `parent_book_id` or `parent_book_review_id`\n column: Column;\n};\n\nexport function isOneToManyField(ormField: Field): ormField is OneToManyField {\n return ormField.kind === \"o2m\";\n}\n\nexport function isManyToOneField(ormField: Field): ormField is ManyToOneField {\n return ormField.kind === \"m2o\";\n}\n\nexport function isManyToManyField(ormField: Field): ormField is ManyToManyField {\n return ormField.kind === \"m2m\";\n}\n\nexport function isManyToManyEnumField(ormField: Field): ormField is ManyToManyEnumField {\n return ormField.kind === \"m2mEnum\";\n}\n\nexport function isOneToOneField(ormField: Field): ormField is OneToOneField {\n return ormField.kind === \"o2o\";\n}\n\nexport function isPolymorphicField(ormField: Field): ormField is PolymorphicField {\n return ormField.kind === \"poly\";\n}\n\nexport function isReferenceField(ormField: Field): ormField is ManyToOneField | OneToOneField | PolymorphicField {\n return ormField.kind === \"m2o\" || ormField.kind === \"o2o\" || ormField.kind === \"poly\";\n}\n\nexport function isCollectionField(ormField: Field): ormField is OneToManyField | ManyToManyField {\n return ormField.kind === \"o2m\" || ormField.kind === \"m2m\";\n}\n\nexport function getBaseAndSelfMetas(meta: EntityMetadata): EntityMetadata[];\nexport function getBaseAndSelfMetas(entity: Entity): EntityMetadata[];\nexport function getBaseAndSelfMetas(param: Entity | EntityMetadata): EntityMetadata[] {\n return isEntity(param)\n ? getBaseSelfAndSubMetas(getMetadata(param))\n : (param.baseSelfMetas ?? [...param.baseTypes, param]);\n}\n\nexport function getBaseSelfAndSubMetas(meta: EntityMetadata): EntityMetadata[] {\n return meta.baseSelfAndSubMetas ?? [...meta.baseTypes, meta, ...meta.subTypes];\n}\n\nexport function getSubMetas(meta: EntityMetadata): EntityMetadata[] {\n // We should do recursion at some point\n return meta.subTypes;\n}\n\nexport function getBaseMeta(meta: EntityMetadata): EntityMetadata {\n if (!meta.baseType) {\n return meta;\n } else {\n return meta.baseTypes[0];\n }\n}\n"],"mappings":";;;;;;;;AAaA,SAAgB,YACd,OACgB;CAChB,IAAI,CAAC,OAAO,MAAM,IAAI,MAAM,yBAAyB,OAAO;CAC5D,OACE,OAAO,UAAU,aAAc,MAAc,WAAW,UAAU,QAAQ,QAAQ,gBAAgB,KAAK,CAAC,CAAC;AAE7G;;AAGA,SAAgB,oBAAoB,MAAsB,WAAmC;CAC3F,IAAI,CAAC,KAAK,UAAU,YAAY,MAAM,IAAI,MAAM,UAAU,UAAU,iBAAiB,KAAK,MAAM;CAGhG,OAAO,EAAE,aAAa,KAAK,WAAW,KAAK,UAAU,UAAU,EAAE,gBAAgB,QAAQ,KAAK,UAC5F,OAAO,mBAAmB,KAAK,QAAQ;CAEzC,OAAO;AACT;AA2PA,SAAgB,iBAAiB,UAA6C;CAC5E,OAAO,SAAS,SAAS;AAC3B;AAEA,SAAgB,iBAAiB,UAA6C;CAC5E,OAAO,SAAS,SAAS;AAC3B;AAEA,SAAgB,kBAAkB,UAA8C;CAC9E,OAAO,SAAS,SAAS;AAC3B;AAEA,SAAgB,sBAAsB,UAAkD;CACtF,OAAO,SAAS,SAAS;AAC3B;AAEA,SAAgB,gBAAgB,UAA4C;CAC1E,OAAO,SAAS,SAAS;AAC3B;AAEA,SAAgB,mBAAmB,UAA+C;CAChF,OAAO,SAAS,SAAS;AAC3B;AAEA,SAAgB,iBAAiB,UAAgF;CAC/G,OAAO,SAAS,SAAS,SAAS,SAAS,SAAS,SAAS,SAAS,SAAS;AACjF;AAEA,SAAgB,kBAAkB,UAA+D;CAC/F,OAAO,SAAS,SAAS,SAAS,SAAS,SAAS;AACtD;AAIA,SAAgB,oBAAoB,OAAkD;CACpF,OAAO,SAAS,KAAK,IACjB,uBAAuB,YAAY,KAAK,CAAC,IACxC,MAAM,iBAAiB,CAAC,GAAG,MAAM,WAAW,KAAK;AACxD;AAEA,SAAgB,uBAAuB,MAAwC;CAC7E,OAAO,KAAK,uBAAuB;EAAC,GAAG,KAAK;EAAW;EAAM,GAAG,KAAK;CAAQ;AAC/E;AAEA,SAAgB,YAAY,MAAwC;CAElE,OAAO,KAAK;AACd;AAEA,SAAgB,YAAY,MAAsC;CAChE,IAAI,CAAC,KAAK,UACR,OAAO;MAEP,OAAO,KAAK,UAAU;AAE1B"}
1
+ {"version":3,"file":"EntityMetadata.js","names":[],"sources":["../src/EntityMetadata.ts"],"sourcesContent":["import { getInstanceData } from \"./BaseEntity.ts\";\nimport { type ConfigApi, type Reactable, type ReactiveRule } from \"./config.ts\";\nimport { getMetadataForType } from \"./configure.ts\";\nimport { type Entity, isEntity } from \"./Entity.ts\";\nimport { type EntityManager, type MaybeAbstractEntityConstructor, type TimestampFields } from \"./EntityManager.ts\";\nimport { type EnumMetadata } from \"./EnumMetadata.ts\";\nimport type { DeepNew } from \"./loading/loadHints.ts\";\nimport type { Column, ColumnDescriptors } from \"./serde/columns.ts\";\nimport type { FieldSerde, PolymorphicKeySerde } from \"./serde/fieldSerde.ts\";\n\nexport function getMetadata<T extends Entity>(entity: T): EntityMetadata<T>;\nexport function getMetadata<T extends Entity>(type: MaybeAbstractEntityConstructor<T>): EntityMetadata<T>;\nexport function getMetadata<T extends Entity>(meta: EntityMetadata): EntityMetadata;\nexport function getMetadata<T extends Entity>(\n param: T | MaybeAbstractEntityConstructor<T> | EntityMetadata,\n): EntityMetadata {\n if (!param) throw new Error(`Cannot getMetadata of ${param}`);\n return (\n typeof param === \"function\" ? (param as any).metadata : \"cstr\" in param ? param : getInstanceData(param).metadata\n ) as EntityMetadata;\n}\n\n/** Returns the metadata layer that declares `fieldName`, i.e. `Task.tags` for `TaskOld.tags`. */\nexport function getMetadataForField(meta: EntityMetadata, fieldName: string): EntityMetadata {\n if (!meta.allFields[fieldName]) throw new Error(`Field '${fieldName}' not found on ${meta.type}`);\n // I.e. `TaskOld.tags` is an STI-inherited `Task.tags` and should walk up, but `SmallPublisherGroup.publishers`\n // is a CTI-specialized `PublisherGroup.publishers` and should stay on `SmallPublisherGroup`.\n while (!(fieldName in meta.fields) && meta.allFields[fieldName]?.specialized !== true && meta.baseType) {\n meta = getMetadataForType(meta.baseType);\n }\n return meta;\n}\n\n/**\n * Runtime metadata about an entity.\n *\n * The `joist-codegen` step will generate this by reading the database schema at build/codegen\n * time, along with any customizations in `joist-config.json`.\n *\n * Note: This has no generic, like `T extends Entity`, because `Entity<IdType>` i.e. with\n * an unknown string/id type, causes issues when we want to generically mix `EntityMetadata`\n * of different types, that even liberally using `EntityMetadata<any>` did not avoid.\n */\nexport interface EntityMetadata<T extends Entity = any> {\n cstr: MaybeAbstractEntityConstructor<T>;\n type: string;\n /** How the domain entity's id is represented. */\n idType: \"tagged-string\" | \"untagged-string\" | \"number\";\n /** The database column type, i.e. used to do `::type` casts in Postgres. */\n idDbType: \"bigint\" | \"int\" | \"uuid\" | \"text\";\n tableName: string;\n /** Whether codegen verified this table is a supported SQL mutation target; does not gate reads. */\n supportsEmExecute?: boolean;\n /** If we're a subtype, our immediate base type's name, e.g. for `SmallPublisher` this would be `Publisher`. */\n baseType: string | undefined;\n inheritanceType?: \"sti\" | \"cti\" | undefined;\n /** Indicates the field to use to derive which subtype to instantiate; only set on the base meta. */\n stiDiscriminatorField?: string;\n /** The discriminator enum value for this subtype; only set on sub metas. */\n stiDiscriminatorValue?: number;\n /** Whether this type is abstract (cannot be instantiated directly). */\n ctiAbstract?: boolean;\n tagName: string;\n fields: Record<string, Field>;\n /** Physical storage descriptors, without CTI base columns; STI metadata shares its base table. */\n columns: ColumnDescriptors;\n allFields: Record<string, Field & { aliasSuffix: string; specialized?: true }>;\n /** Usually polys are in `allFields`, but we pull the components out for comp-specific finds, like `parentBook`. */\n polyComponentFields?: Record<string, Field & { aliasSuffix: string }>;\n // Using `any` to avoid type errors between BaseType.metadata & SubType.metadata static fields\n config: ConfigApi<any, any>;\n /** The lazy list of non-read-only reactables for this metadata and its base types. */\n reactables?: Reactable[];\n /** The lazy lookup of non-read-only reactables by source field name. */\n reactablesByField?: ReadonlyMap<string, Reactable[]>;\n /** The lazy list of all reactables for this metadata and its base types. */\n reactablesIncludingReadOnly?: Reactable[];\n /** The lazy lookup of all reactables by source field name. */\n reactablesIncludingReadOnlyByField?: ReadonlyMap<string, Reactable[]>;\n /** The lazy list of reactive validation rules for this metadata and its subtypes. */\n reactiveRules?: ReactiveRule[];\n /** The lazy list of reactive *commit* rules (post-flush/pre-commit) for this metadata and its subtypes. */\n reactiveCommitRules?: ReactiveRule[];\n /** Lazily-cached: whether flushing an entity of this type could trigger any `addCommitRule` work. */\n hasCommitRules?: boolean;\n /** The lazily-cached set of own `lazy` primitive field names, i.e. columns excluded from the default SELECT. */\n lazyFieldNames?: ReadonlySet<string>;\n /** The lazily-cached list of sync-derived (`hasReactiveField`-less) field names, recalced during flush. */\n syncDerivedFields?: string[];\n /** Lazily-cached: whether this entity has any `lazy` columns, i.e. so the default SELECT lists columns explicitly. */\n hasLazyColumns?: boolean;\n orderBy: string | undefined;\n /** Flat field names that can be used to find existing rows before creating. I.e. [[\"email\"], [\"author\", \"title\"]]. */\n uniqueBy?: string[][];\n timestampFields: TimestampFields | undefined;\n // Ideally this would be the application-specific EntityManager (to avoid anys), but it doesn't really matter\n factory: (em: EntityManager<any, any, any>, opts?: any) => DeepNew<T>;\n /** The list of base types for this subtype, e.g. for Dog it'd be [Animal, Mammal]. */\n baseTypes: EntityMetadata[];\n /** The list of subtypes for this base type, e.g. for Animal it'd be `[Mammal, Dog]`. */\n subTypes: EntityMetadata[];\n /** Cached `[...baseTypes, this]` set up by `configureMetadata`, so hot paths avoid re-allocating it. */\n baseSelfMetas?: EntityMetadata[];\n /** Cached `[...baseTypes, this, ...subTypes]` set up by `configureMetadata`, so hot paths avoid re-allocating it. */\n baseSelfAndSubMetas?: EntityMetadata[];\n /** The lazy lookup of subtypes by type name, i.e. `Animal.metadata.subTypesByType.get(\"Dog\")`. */\n subTypesByType?: ReadonlyMap<string, EntityMetadata>;\n /** The lazy lookup of STI subtypes by discriminator value, i.e. `Task.metadata.subTypesByStiValue.get(1)`. */\n subTypesByStiValue?: ReadonlyMap<unknown, EntityMetadata>;\n /** The lazy STI discriminator column name, i.e. `Task.metadata.stiDiscriminatorColumnName`. */\n stiDiscriminatorColumnName?: string;\n /** If the schema is lacking deferred FKs, this is our insertion order. */\n nonDeferredFkOrder?: number;\n}\n\nexport type Field =\n | PrimaryKeyField\n | PrimitiveField\n | EnumField\n | OneToManyField\n | LargeOneToManyField\n | ManyToOneField\n | ManyToManyField\n | ManyToManyEnumField\n | OneToOneField\n | PolymorphicField;\n\n// Only the fields that have defined `serde` keys; should be a mapped type of Field\nexport type SerdeField = PrimaryKeyField | PrimitiveField | EnumField | ManyToOneField | PolymorphicField;\n\nexport type PrimaryKeyField = {\n kind: \"primaryKey\";\n fieldName: string;\n fieldIdName: undefined;\n required: true;\n serde: FieldSerde;\n immutable: true;\n};\n\nexport type PrimitiveField = {\n kind: \"primitive\";\n fieldName: string;\n fieldIdName: undefined;\n required: boolean;\n derived: \"orm\" | \"sync\" | \"async\" | false;\n protected: boolean;\n type: string | Function;\n serde: FieldSerde;\n immutable: boolean;\n citext?: boolean;\n default?: \"schema\" | \"config\";\n sanitize?: boolean;\n /** When true, this column is excluded from the entity's default SELECT and lazy-loaded via a `LazyField`. */\n lazy?: boolean;\n};\n\nexport type EnumField = {\n kind: \"enum\";\n fieldName: string;\n fieldIdName: undefined;\n required: boolean;\n derived: \"sync\" | \"async\" | false;\n enumDetailType: { getValues(): ReadonlyArray<unknown>; findById(id: any): unknown };\n serde: FieldSerde;\n immutable: boolean;\n default?: \"schema\" | \"config\";\n};\n\nexport type OneToManyField = {\n kind: \"o2m\";\n fieldName: string;\n fieldIdName: string;\n required: boolean;\n otherMetadata: () => EntityMetadata;\n otherFieldName: string;\n /** Useful when our other side is a poly, to find which component points back to us. */\n otherColumnName: string;\n serde: undefined;\n immutable: false;\n orderBy?: { field: string; direction: \"ASC\" | \"DESC\" };\n /** When `\"include\"`, this collection's `.get`/`.load` returns soft-deleted entities instead of hiding them. */\n softDeletes?: \"include\" | \"exclude\";\n};\n\nexport type LargeOneToManyField = {\n kind: \"lo2m\";\n fieldName: string;\n fieldIdName: string;\n required: boolean;\n otherMetadata: () => EntityMetadata;\n otherFieldName: string;\n /** Useful when our other side is a poly, to find which component points back to us. */\n otherColumnName: string;\n serde: undefined;\n immutable: false;\n};\n\nexport type ManyToOneField = {\n kind: \"m2o\";\n fieldName: string;\n fieldIdName: string;\n required: boolean;\n otherMetadata: () => EntityMetadata;\n otherFieldName: string;\n serde: FieldSerde;\n immutable: boolean;\n derived: \"async\" | false;\n default?: \"schema\" | \"config\";\n};\n\nexport type ManyToManyField = {\n kind: \"m2m\";\n fieldName: string;\n fieldIdName: string;\n required: boolean;\n derived: \"async\" | \"otherSide\" | false;\n otherMetadata: () => EntityMetadata;\n otherFieldName: string;\n serde: undefined;\n immutable: false;\n joinTableName: string;\n columnNames: [string, string];\n /** Whether the join table has a surrogate `id` PK; if false the FK pair is the composite PK. */\n hasJoinTableId: boolean;\n /** When `\"include\"`, this collection's `.get`/`.load` returns soft-deleted entities instead of hiding them. */\n softDeletes?: \"include\" | \"exclude\";\n};\n\n/**\n * A many-to-many between an entity and an enum \"table\", e.g. `Publisher.logoColors` backed by a\n * `publisher_logo_colors` join table joining `publishers` to the `color` enum table.\n *\n * To the user this looks like an array of enum codes (`Color[]`), but unlike an enum-array column it\n * is lazy (needs a load hint) because it lives in its own join table.\n */\nexport type ManyToManyEnumField = {\n kind: \"m2mEnum\";\n fieldName: string;\n fieldIdName: undefined;\n required: false;\n derived: false;\n /** The enum's metadata, used to map enum codes <-> their numeric ids. */\n enumDetailType: EnumMetadata<any, any, number>;\n serde: undefined;\n immutable: false;\n joinTableName: string;\n /** `[entityColumn, enumColumn]`, e.g. `[\"publisher_id\", \"color_id\"]`. */\n columnNames: [string, string];\n /** Whether the join table has a surrogate `id` PK; if false the FK pair is the composite PK. */\n hasJoinTableId: boolean;\n};\n\nexport type OneToOneField = {\n kind: \"o2o\";\n fieldName: string;\n fieldIdName: string;\n required: boolean;\n otherMetadata: () => EntityMetadata;\n otherFieldName: string;\n /** Useful when our other side is a poly, to find which component points back to us. */\n otherColumnName: string;\n serde: undefined;\n immutable: false;\n};\n\nexport type PolymorphicField = {\n kind: \"poly\";\n fieldName: string; // eg `parent`\n fieldIdName: string; // `parentId`\n required: boolean;\n components: PolymorphicFieldComponent[];\n serde: PolymorphicKeySerde;\n immutable: boolean;\n};\n\nexport type PolymorphicFieldComponent = {\n otherMetadata: () => EntityMetadata;\n otherFieldName: string; // eg `comment` or `comments`\n columnName: string; // eg `parent_book_id` or `parent_book_review_id`\n column: Column;\n};\n\nexport function isOneToManyField(ormField: Field): ormField is OneToManyField {\n return ormField.kind === \"o2m\";\n}\n\nexport function isManyToOneField(ormField: Field): ormField is ManyToOneField {\n return ormField.kind === \"m2o\";\n}\n\nexport function isManyToManyField(ormField: Field): ormField is ManyToManyField {\n return ormField.kind === \"m2m\";\n}\n\nexport function isManyToManyEnumField(ormField: Field): ormField is ManyToManyEnumField {\n return ormField.kind === \"m2mEnum\";\n}\n\nexport function isOneToOneField(ormField: Field): ormField is OneToOneField {\n return ormField.kind === \"o2o\";\n}\n\nexport function isPolymorphicField(ormField: Field): ormField is PolymorphicField {\n return ormField.kind === \"poly\";\n}\n\nexport function isReferenceField(ormField: Field): ormField is ManyToOneField | OneToOneField | PolymorphicField {\n return ormField.kind === \"m2o\" || ormField.kind === \"o2o\" || ormField.kind === \"poly\";\n}\n\nexport function isCollectionField(ormField: Field): ormField is OneToManyField | ManyToManyField {\n return ormField.kind === \"o2m\" || ormField.kind === \"m2m\";\n}\n\nexport function getBaseAndSelfMetas(meta: EntityMetadata): EntityMetadata[];\nexport function getBaseAndSelfMetas(entity: Entity): EntityMetadata[];\nexport function getBaseAndSelfMetas(param: Entity | EntityMetadata): EntityMetadata[] {\n return isEntity(param)\n ? getBaseSelfAndSubMetas(getMetadata(param))\n : (param.baseSelfMetas ?? [...param.baseTypes, param]);\n}\n\nexport function getBaseSelfAndSubMetas(meta: EntityMetadata): EntityMetadata[] {\n return meta.baseSelfAndSubMetas ?? [...meta.baseTypes, meta, ...meta.subTypes];\n}\n\nexport function getSubMetas(meta: EntityMetadata): EntityMetadata[] {\n // We should do recursion at some point\n return meta.subTypes;\n}\n\nexport function getBaseMeta(meta: EntityMetadata): EntityMetadata {\n if (!meta.baseType) {\n return meta;\n } else {\n return meta.baseTypes[0];\n }\n}\n"],"mappings":";;;;;;AAaA,SAAgB,YACd,OACgB;CAChB,IAAI,CAAC,OAAO,MAAM,IAAI,MAAM,yBAAyB,OAAO;CAC5D,OACE,OAAO,UAAU,aAAc,MAAc,WAAW,UAAU,QAAQ,QAAQ,gBAAgB,KAAK,CAAC,CAAC;AAE7G;;AAGA,SAAgB,oBAAoB,MAAsB,WAAmC;CAC3F,IAAI,CAAC,KAAK,UAAU,YAAY,MAAM,IAAI,MAAM,UAAU,UAAU,iBAAiB,KAAK,MAAM;CAGhG,OAAO,EAAE,aAAa,KAAK,WAAW,KAAK,UAAU,UAAU,EAAE,gBAAgB,QAAQ,KAAK,UAC5F,OAAO,mBAAmB,KAAK,QAAQ;CAEzC,OAAO;AACT;AA2PA,SAAgB,iBAAiB,UAA6C;CAC5E,OAAO,SAAS,SAAS;AAC3B;AAEA,SAAgB,iBAAiB,UAA6C;CAC5E,OAAO,SAAS,SAAS;AAC3B;AAEA,SAAgB,kBAAkB,UAA8C;CAC9E,OAAO,SAAS,SAAS;AAC3B;AAEA,SAAgB,sBAAsB,UAAkD;CACtF,OAAO,SAAS,SAAS;AAC3B;AAEA,SAAgB,gBAAgB,UAA4C;CAC1E,OAAO,SAAS,SAAS;AAC3B;AAEA,SAAgB,mBAAmB,UAA+C;CAChF,OAAO,SAAS,SAAS;AAC3B;AAEA,SAAgB,iBAAiB,UAAgF;CAC/G,OAAO,SAAS,SAAS,SAAS,SAAS,SAAS,SAAS,SAAS,SAAS;AACjF;AAEA,SAAgB,kBAAkB,UAA+D;CAC/F,OAAO,SAAS,SAAS,SAAS,SAAS,SAAS;AACtD;AAIA,SAAgB,oBAAoB,OAAkD;CACpF,OAAO,SAAS,KAAK,IACjB,uBAAuB,YAAY,KAAK,CAAC,IACxC,MAAM,iBAAiB,CAAC,GAAG,MAAM,WAAW,KAAK;AACxD;AAEA,SAAgB,uBAAuB,MAAwC;CAC7E,OAAO,KAAK,uBAAuB;EAAC,GAAG,KAAK;EAAW;EAAM,GAAG,KAAK;CAAQ;AAC/E;AAEA,SAAgB,YAAY,MAAwC;CAElE,OAAO,KAAK;AACd;AAEA,SAAgB,YAAY,MAAsC;CAChE,IAAI,CAAC,KAAK,UACR,OAAO;MAEP,OAAO,KAAK,UAAU;AAE1B"}
@@ -1,7 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_relations_Reference = require("./relations/Reference.cjs");
3
- const require_utils = require("./utils.cjs");
4
3
  require("./relations/index.cjs");
4
+ const require_utils = require("./utils.cjs");
5
5
  const require_EntityMetadata = require("./EntityMetadata.cjs");
6
6
  const require_Entity = require("./Entity.cjs");
7
7
  //#region src/IndexManager.ts
@@ -1,6 +1,6 @@
1
1
  import { isLoadedReference } from "./relations/Reference.js";
2
- import { groupBy } from "./utils.js";
3
2
  import "./relations/index.js";
3
+ import { groupBy } from "./utils.js";
4
4
  import { getMetadata } from "./EntityMetadata.js";
5
5
  import { isEntity } from "./Entity.js";
6
6
  //#region src/IndexManager.ts
@@ -1,5 +1,4 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- require("./Todo.cjs");
3
2
  require("./EntityMetadata.cjs");
4
3
  const require_EntityManager = require("./EntityManager.cjs");
5
4
  require("./Entity.cjs");
@@ -1 +1 @@
1
- {"version":3,"file":"PluginManager.cjs","names":["isDefined","#pluginsByCallback","#plugins"],"sources":["../src/PluginManager.ts"],"sourcesContent":["import { type Entity } from \"./Entity.ts\";\nimport { type EntityManager, type FindOperation, isDefined } from \"./EntityManager.ts\";\nimport { type EntityMetadata } from \"./EntityMetadata.ts\";\nimport type { ParsedFindQuery } from \"./queries/find/QueryParser.ts\";\nimport { type RowData } from \"./RowData.ts\";\nimport { type JoinRowTodo, type Todo } from \"./Todo.ts\";\n\ninterface PluginMethods {\n /**\n * Called before a field value is retrieved from an entity via getField.\n *\n * @param entity The entity instance being accessed\n * @param field The field name being retrieved\n */\n beforeGetField?(entity: Entity, field: string): void;\n /**\n * Called before a field value is set on an entity via setField.\n *\n * @param entity The entity instance being modified\n * @param field The field name being set\n * @param newValue The new value being assigned to the field\n */\n beforeSetField?(entity: Entity, field: string, newValue: any): void;\n /**\n * Called before a find operation is executed.\n *\n * @param meta Metadata for the entity type being queried\n * @param operation The type of find operation being performed\n * @param query The parsed query conditions\n * @param settings Query settings including limit and offset\n */\n beforeFind?(\n meta: EntityMetadata,\n operation: FindOperation,\n query: ParsedFindQuery,\n settings: {\n limit?: number;\n offset?: number;\n allowMultipleLeftJoins?: boolean;\n optimizeJoinsToExists?: boolean;\n pruneJoins?: boolean;\n keepAliases?: string[];\n },\n ): void;\n /**\n * Called after a find operation has been executed to observe the raw database rows.\n *\n * The result is an observation-only {@link RowData} view — i.e. `rows.rowCount` for metrics,\n * `rows.get(i, columnName)` for specific cells, or `rows.toRows()` to materialize POJO rows.\n * For lazy results, cells decode on access, so a hook that only counts rows costs nothing;\n * materializing via `toRows()` decodes every cell of every row. Mutating materialized rows is\n * unsupported and is not guaranteed to affect entity hydration.\n *\n * @param meta Metadata for the entity type that was queried\n * @param operation The type of find operation that was performed\n * @param rows A read-only view of the raw database rows returned from the query\n */\n afterFind?(meta: EntityMetadata, operation: FindOperation, rows: RowData): void;\n\n beforeValidate?(entities: readonly Entity[]): Promise<void> | void;\n\n afterValidate?(entities: readonly Entity[]): Promise<void> | void;\n\n afterWrite(entityTodos: Record<string, Todo>, joinRowTodos: Record<string, JoinRowTodo>): void;\n}\n\nconst syncPluginMethods = [\n \"beforeGetField\",\n \"beforeSetField\",\n \"beforeFind\",\n \"afterFind\",\n \"afterWrite\",\n] as const satisfies readonly (keyof PluginMethods)[];\nconst asyncPluginMethods = [\"beforeValidate\", \"afterValidate\"] as const satisfies readonly (keyof PluginMethods)[];\nconst emsSymbol = Symbol(\"ems\");\n/**\n * Base class for plugins that hook into entity lifecycle events.\n *\n * Plugins can implement any of the PluginMethods to intercept entity operations\n * and are automatically registered with the EntityManager when added via PluginManager.\n */\nexport abstract class Plugin {\n // We need to store the EntityManager references in a WeakRef array so that they can be garbage collected. If we\n // didn't do this, then multiple EMs with the same plugin instance could keep each other from being garbage collected.\n [emsSymbol]: WeakRef<EntityManager>[] = [];\n\n maybeCloneForNewEm(): this | undefined {\n return undefined;\n }\n\n get ems(): readonly EntityManager[] {\n return this[emsSymbol]\n .values()\n .map((wr) => wr.deref())\n .filter(isDefined)\n .toArray();\n }\n}\n\nexport interface Plugin extends PluginMethods {}\n\n/**\n * Manages plugin lifecycle and dispatches plugin callbacks to registered plugins.\n *\n * The PluginManager optimizes callback dispatch by only creating dispatcher methods\n * for callbacks that have at least one registered plugin, making unused plugin hooks\n * zero-cost at runtime.\n */\nexport class PluginManager implements Required<PluginMethods> {\n #plugins = new Set<Plugin>();\n readonly #pluginsByCallback: Partial<Record<keyof Plugin, Plugin[]>> = {};\n constructor(public readonly em: EntityManager) {}\n\n /** Returns whether any registered plugin implements `method`, i.e. so callers can skip building its args. */\n hasHook(method: keyof PluginMethods): boolean {\n return this.#pluginsByCallback[method] !== undefined;\n }\n\n /**\n * Registers a plugin with this EntityManager.\n *\n * Dynamically creates dispatcher methods for any plugin callbacks implemented by this plugin,\n * enabling lazy initialization of only the hooks that are actually used.\n *\n * @throws Error if the plugin is already registered with another EntityManager\n */\n addPlugin(plugin: Plugin) {\n if (this.#plugins.has(plugin)) return; // if we're already added, then we can just early exit\n this.#plugins.add(plugin);\n plugin[emsSymbol].push(new WeakRef(this.em));\n for (const method of syncPluginMethods) {\n if (method in plugin) {\n (this.#pluginsByCallback[method] ??= []).push(plugin);\n // As a performance optimization, we only create the actual implementation for each method on the plugin manager\n // once we have at least one plugin using that method. This is to make it so any unused plugin methods are\n // effectively no-ops when called from within the em.\n if (!Object.hasOwn(this, method)) {\n this[method] = function (this: PluginManager, ...args: any[]) {\n for (const plugin of this.#pluginsByCallback[method]!) {\n (plugin[method] as (...args: any[]) => unknown)(...args);\n }\n };\n }\n }\n }\n for (const method of asyncPluginMethods) {\n if (method in plugin) {\n (this.#pluginsByCallback[method] ??= []).push(plugin);\n // Validate-phase plugin hooks are intentionally awaited without making hot-path hooks async.\n if (!Object.hasOwn(this, method)) {\n this[method] = async function (this: PluginManager, ...args: any[]) {\n for (const plugin of this.#pluginsByCallback[method]!) {\n await (plugin[method] as (...args: any[]) => Promise<void> | void)(...args);\n }\n };\n }\n }\n }\n }\n\n get plugins(): readonly Plugin[] {\n return [...this.#plugins];\n }\n\n cloneTo(other: PluginManager) {\n this.#plugins\n .values()\n .map((plugin) => plugin.maybeCloneForNewEm())\n .filter(isDefined)\n .forEach((plugin) => other.addPlugin(plugin));\n }\n\n // Defined as no-op functions initially instead of using optional chaining for performance reasons, see:\n // https://adventures.nodeland.dev/archive/noop-functions-vs-optional-chaining-a-performance/\n\n beforeGetField(entity: Entity, field: string): void {}\n beforeSetField(entity: Entity, field: string, newValue: any): void {}\n beforeFind(\n meta: EntityMetadata,\n operation: FindOperation,\n query: ParsedFindQuery,\n settings: {\n limit?: number;\n offset?: number;\n allowMultipleLeftJoins?: boolean;\n optimizeJoinsToExists?: boolean;\n pruneJoins?: boolean;\n keepAliases?: string[];\n },\n ): void {}\n afterFind(meta: EntityMetadata, operation: FindOperation, rows: RowData) {}\n beforeValidate(entities: readonly Entity[]): Promise<void> | void {}\n afterValidate(entities: readonly Entity[]): Promise<void> | void {}\n afterWrite(entityTodos: Record<string, Todo>, joinRowTodos: Record<string, JoinRowTodo>): void {}\n}\n"],"mappings":";;;;;;AAkEA,MAAM,oBAAoB;CACxB;CACA;CACA;CACA;CACA;AACF;AACA,MAAM,qBAAqB,CAAC,kBAAkB,eAAe;AAC7D,MAAM,YAAY,OAAO,KAAK;;;;;;;AAO9B,IAAsB,SAAtB,MAA6B;CAG3B,CAAC,aAAuC,CAAC;CAEzC,qBAAuC,CAEvC;CAEA,IAAI,MAAgC;EAClC,OAAO,KAAK,UAAU,CACnB,OAAO,CAAC,CACR,KAAK,OAAO,GAAG,MAAM,CAAC,CAAC,CACvB,OAAOA,sBAAAA,SAAS,CAAC,CACjB,QAAQ;CACb;AACF;;;;;;;;AAWA,IAAa,gBAAb,MAA8D;CAGhC;CAF5B,2BAAW,IAAI,IAAY;CAC3B,qBAAuE,CAAC;CACxE,YAAY,IAAmC;EAAnB,KAAA,KAAA;CAAoB;;CAGhD,QAAQ,QAAsC;EAC5C,OAAO,KAAKC,mBAAmB,YAAY,KAAA;CAC7C;;;;;;;;;CAUA,UAAU,QAAgB;EACxB,IAAI,KAAKC,SAAS,IAAI,MAAM,GAAG;EAC/B,KAAKA,SAAS,IAAI,MAAM;EACxB,OAAO,UAAU,CAAC,KAAK,IAAI,QAAQ,KAAK,EAAE,CAAC;EAC3C,KAAK,MAAM,UAAU,mBACnB,IAAI,UAAU,QAAQ;GACpB,CAAC,KAAKD,mBAAmB,YAAY,CAAC,EAAA,CAAG,KAAK,MAAM;GAIpD,IAAI,CAAC,OAAO,OAAO,MAAM,MAAM,GAC7B,KAAK,UAAU,SAA+B,GAAG,MAAa;IAC5D,KAAK,MAAM,UAAU,KAAKA,mBAAmB,SAC3C,OAAQ,OAAO,CAAiC,GAAG,IAAI;GAE3D;EAEJ;EAEF,KAAK,MAAM,UAAU,oBACnB,IAAI,UAAU,QAAQ;GACpB,CAAC,KAAKA,mBAAmB,YAAY,CAAC,EAAA,CAAG,KAAK,MAAM;GAEpD,IAAI,CAAC,OAAO,OAAO,MAAM,MAAM,GAC7B,KAAK,UAAU,eAAqC,GAAG,MAAa;IAClE,KAAK,MAAM,UAAU,KAAKA,mBAAmB,SAC3C,MAAO,OAAO,OAAO,CAA8C,GAAG,IAAI;GAE9E;EAEJ;CAEJ;CAEA,IAAI,UAA6B;EAC/B,OAAO,CAAC,GAAG,KAAKC,QAAQ;CAC1B;CAEA,QAAQ,OAAsB;EAC5B,KAAKA,SACF,OAAO,CAAC,CACR,KAAK,WAAW,OAAO,mBAAmB,CAAC,CAAC,CAC5C,OAAOF,sBAAAA,SAAS,CAAC,CACjB,SAAS,WAAW,MAAM,UAAU,MAAM,CAAC;CAChD;CAKA,eAAe,QAAgB,OAAqB,CAAC;CACrD,eAAe,QAAgB,OAAe,UAAqB,CAAC;CACpE,WACE,MACA,WACA,OACA,UAQM,CAAC;CACT,UAAU,MAAsB,WAA0B,MAAe,CAAC;CAC1E,eAAe,UAAmD,CAAC;CACnE,cAAc,UAAmD,CAAC;CAClE,WAAW,aAAmC,cAAiD,CAAC;AAClG"}
1
+ {"version":3,"file":"PluginManager.cjs","names":["isDefined","#pluginsByCallback","#plugins"],"sources":["../src/PluginManager.ts"],"sourcesContent":["import { type Entity } from \"./Entity.ts\";\nimport { type EntityManager, type FindOperation, isDefined } from \"./EntityManager.ts\";\nimport { type EntityMetadata } from \"./EntityMetadata.ts\";\nimport type { JoinRowTodo, Todo } from \"./flush/Todo.ts\";\nimport type { ParsedFindQuery } from \"./queries/find/QueryParser.ts\";\nimport { type RowData } from \"./RowData.ts\";\n\ninterface PluginMethods {\n /**\n * Called before a field value is retrieved from an entity via getField.\n *\n * @param entity The entity instance being accessed\n * @param field The field name being retrieved\n */\n beforeGetField?(entity: Entity, field: string): void;\n /**\n * Called before a field value is set on an entity via setField.\n *\n * @param entity The entity instance being modified\n * @param field The field name being set\n * @param newValue The new value being assigned to the field\n */\n beforeSetField?(entity: Entity, field: string, newValue: any): void;\n /**\n * Called before a find operation is executed.\n *\n * @param meta Metadata for the entity type being queried\n * @param operation The type of find operation being performed\n * @param query The parsed query conditions\n * @param settings Query settings including limit and offset\n */\n beforeFind?(\n meta: EntityMetadata,\n operation: FindOperation,\n query: ParsedFindQuery,\n settings: {\n limit?: number;\n offset?: number;\n allowMultipleLeftJoins?: boolean;\n optimizeJoinsToExists?: boolean;\n pruneJoins?: boolean;\n keepAliases?: string[];\n },\n ): void;\n /**\n * Called after a find operation has been executed to observe the raw database rows.\n *\n * The result is an observation-only {@link RowData} view — i.e. `rows.rowCount` for metrics,\n * `rows.get(i, columnName)` for specific cells, or `rows.toRows()` to materialize POJO rows.\n * For lazy results, cells decode on access, so a hook that only counts rows costs nothing;\n * materializing via `toRows()` decodes every cell of every row. Mutating materialized rows is\n * unsupported and is not guaranteed to affect entity hydration.\n *\n * @param meta Metadata for the entity type that was queried\n * @param operation The type of find operation that was performed\n * @param rows A read-only view of the raw database rows returned from the query\n */\n afterFind?(meta: EntityMetadata, operation: FindOperation, rows: RowData): void;\n\n beforeValidate?(entities: readonly Entity[]): Promise<void> | void;\n\n afterValidate?(entities: readonly Entity[]): Promise<void> | void;\n\n afterWrite(entityTodos: Record<string, Todo>, joinRowTodos: Record<string, JoinRowTodo>): void;\n}\n\nconst syncPluginMethods = [\n \"beforeGetField\",\n \"beforeSetField\",\n \"beforeFind\",\n \"afterFind\",\n \"afterWrite\",\n] as const satisfies readonly (keyof PluginMethods)[];\nconst asyncPluginMethods = [\"beforeValidate\", \"afterValidate\"] as const satisfies readonly (keyof PluginMethods)[];\nconst emsSymbol = Symbol(\"ems\");\n/**\n * Base class for plugins that hook into entity lifecycle events.\n *\n * Plugins can implement any of the PluginMethods to intercept entity operations\n * and are automatically registered with the EntityManager when added via PluginManager.\n */\nexport abstract class Plugin {\n // We need to store the EntityManager references in a WeakRef array so that they can be garbage collected. If we\n // didn't do this, then multiple EMs with the same plugin instance could keep each other from being garbage collected.\n [emsSymbol]: WeakRef<EntityManager>[] = [];\n\n maybeCloneForNewEm(): this | undefined {\n return undefined;\n }\n\n get ems(): readonly EntityManager[] {\n return this[emsSymbol]\n .values()\n .map((wr) => wr.deref())\n .filter(isDefined)\n .toArray();\n }\n}\n\nexport interface Plugin extends PluginMethods {}\n\n/**\n * Manages plugin lifecycle and dispatches plugin callbacks to registered plugins.\n *\n * The PluginManager optimizes callback dispatch by only creating dispatcher methods\n * for callbacks that have at least one registered plugin, making unused plugin hooks\n * zero-cost at runtime.\n */\nexport class PluginManager implements Required<PluginMethods> {\n #plugins = new Set<Plugin>();\n readonly #pluginsByCallback: Partial<Record<keyof Plugin, Plugin[]>> = {};\n constructor(public readonly em: EntityManager) {}\n\n /** Returns whether any registered plugin implements `method`, i.e. so callers can skip building its args. */\n hasHook(method: keyof PluginMethods): boolean {\n return this.#pluginsByCallback[method] !== undefined;\n }\n\n /**\n * Registers a plugin with this EntityManager.\n *\n * Dynamically creates dispatcher methods for any plugin callbacks implemented by this plugin,\n * enabling lazy initialization of only the hooks that are actually used.\n *\n * @throws Error if the plugin is already registered with another EntityManager\n */\n addPlugin(plugin: Plugin) {\n if (this.#plugins.has(plugin)) return; // if we're already added, then we can just early exit\n this.#plugins.add(plugin);\n plugin[emsSymbol].push(new WeakRef(this.em));\n for (const method of syncPluginMethods) {\n if (method in plugin) {\n (this.#pluginsByCallback[method] ??= []).push(plugin);\n // As a performance optimization, we only create the actual implementation for each method on the plugin manager\n // once we have at least one plugin using that method. This is to make it so any unused plugin methods are\n // effectively no-ops when called from within the em.\n if (!Object.hasOwn(this, method)) {\n this[method] = function (this: PluginManager, ...args: any[]) {\n for (const plugin of this.#pluginsByCallback[method]!) {\n (plugin[method] as (...args: any[]) => unknown)(...args);\n }\n };\n }\n }\n }\n for (const method of asyncPluginMethods) {\n if (method in plugin) {\n (this.#pluginsByCallback[method] ??= []).push(plugin);\n // Validate-phase plugin hooks are intentionally awaited without making hot-path hooks async.\n if (!Object.hasOwn(this, method)) {\n this[method] = async function (this: PluginManager, ...args: any[]) {\n for (const plugin of this.#pluginsByCallback[method]!) {\n await (plugin[method] as (...args: any[]) => Promise<void> | void)(...args);\n }\n };\n }\n }\n }\n }\n\n get plugins(): readonly Plugin[] {\n return [...this.#plugins];\n }\n\n cloneTo(other: PluginManager) {\n this.#plugins\n .values()\n .map((plugin) => plugin.maybeCloneForNewEm())\n .filter(isDefined)\n .forEach((plugin) => other.addPlugin(plugin));\n }\n\n // Defined as no-op functions initially instead of using optional chaining for performance reasons, see:\n // https://adventures.nodeland.dev/archive/noop-functions-vs-optional-chaining-a-performance/\n\n beforeGetField(entity: Entity, field: string): void {}\n beforeSetField(entity: Entity, field: string, newValue: any): void {}\n beforeFind(\n meta: EntityMetadata,\n operation: FindOperation,\n query: ParsedFindQuery,\n settings: {\n limit?: number;\n offset?: number;\n allowMultipleLeftJoins?: boolean;\n optimizeJoinsToExists?: boolean;\n pruneJoins?: boolean;\n keepAliases?: string[];\n },\n ): void {}\n afterFind(meta: EntityMetadata, operation: FindOperation, rows: RowData) {}\n beforeValidate(entities: readonly Entity[]): Promise<void> | void {}\n afterValidate(entities: readonly Entity[]): Promise<void> | void {}\n afterWrite(entityTodos: Record<string, Todo>, joinRowTodos: Record<string, JoinRowTodo>): void {}\n}\n"],"mappings":";;;;;AAkEA,MAAM,oBAAoB;CACxB;CACA;CACA;CACA;CACA;AACF;AACA,MAAM,qBAAqB,CAAC,kBAAkB,eAAe;AAC7D,MAAM,YAAY,OAAO,KAAK;;;;;;;AAO9B,IAAsB,SAAtB,MAA6B;CAG3B,CAAC,aAAuC,CAAC;CAEzC,qBAAuC,CAEvC;CAEA,IAAI,MAAgC;EAClC,OAAO,KAAK,UAAU,CACnB,OAAO,CAAC,CACR,KAAK,OAAO,GAAG,MAAM,CAAC,CAAC,CACvB,OAAOA,sBAAAA,SAAS,CAAC,CACjB,QAAQ;CACb;AACF;;;;;;;;AAWA,IAAa,gBAAb,MAA8D;CAGhC;CAF5B,2BAAW,IAAI,IAAY;CAC3B,qBAAuE,CAAC;CACxE,YAAY,IAAmC;EAAnB,KAAA,KAAA;CAAoB;;CAGhD,QAAQ,QAAsC;EAC5C,OAAO,KAAKC,mBAAmB,YAAY,KAAA;CAC7C;;;;;;;;;CAUA,UAAU,QAAgB;EACxB,IAAI,KAAKC,SAAS,IAAI,MAAM,GAAG;EAC/B,KAAKA,SAAS,IAAI,MAAM;EACxB,OAAO,UAAU,CAAC,KAAK,IAAI,QAAQ,KAAK,EAAE,CAAC;EAC3C,KAAK,MAAM,UAAU,mBACnB,IAAI,UAAU,QAAQ;GACpB,CAAC,KAAKD,mBAAmB,YAAY,CAAC,EAAA,CAAG,KAAK,MAAM;GAIpD,IAAI,CAAC,OAAO,OAAO,MAAM,MAAM,GAC7B,KAAK,UAAU,SAA+B,GAAG,MAAa;IAC5D,KAAK,MAAM,UAAU,KAAKA,mBAAmB,SAC3C,OAAQ,OAAO,CAAiC,GAAG,IAAI;GAE3D;EAEJ;EAEF,KAAK,MAAM,UAAU,oBACnB,IAAI,UAAU,QAAQ;GACpB,CAAC,KAAKA,mBAAmB,YAAY,CAAC,EAAA,CAAG,KAAK,MAAM;GAEpD,IAAI,CAAC,OAAO,OAAO,MAAM,MAAM,GAC7B,KAAK,UAAU,eAAqC,GAAG,MAAa;IAClE,KAAK,MAAM,UAAU,KAAKA,mBAAmB,SAC3C,MAAO,OAAO,OAAO,CAA8C,GAAG,IAAI;GAE9E;EAEJ;CAEJ;CAEA,IAAI,UAA6B;EAC/B,OAAO,CAAC,GAAG,KAAKC,QAAQ;CAC1B;CAEA,QAAQ,OAAsB;EAC5B,KAAKA,SACF,OAAO,CAAC,CACR,KAAK,WAAW,OAAO,mBAAmB,CAAC,CAAC,CAC5C,OAAOF,sBAAAA,SAAS,CAAC,CACjB,SAAS,WAAW,MAAM,UAAU,MAAM,CAAC;CAChD;CAKA,eAAe,QAAgB,OAAqB,CAAC;CACrD,eAAe,QAAgB,OAAe,UAAqB,CAAC;CACpE,WACE,MACA,WACA,OACA,UAQM,CAAC;CACT,UAAU,MAAsB,WAA0B,MAAe,CAAC;CAC1E,eAAe,UAAmD,CAAC;CACnE,cAAc,UAAmD,CAAC;CAClE,WAAW,aAAmC,cAAiD,CAAC;AAClG"}
@@ -1,4 +1,4 @@
1
- import { JoinRowTodo, Todo } from "./Todo.cjs";
1
+ import { JoinRowTodo, Todo } from "./flush/Todo.cjs";
2
2
  import { ParsedFindQuery } from "./queries/find/QueryParser.cjs";
3
3
  import { RowData } from "./RowData.cjs";
4
4
  import { EntityMetadata } from "./EntityMetadata.cjs";
@@ -1,4 +1,4 @@
1
- import { JoinRowTodo, Todo } from "./Todo.mjs";
1
+ import { JoinRowTodo, Todo } from "./flush/Todo.mjs";
2
2
  import { ParsedFindQuery } from "./queries/find/QueryParser.mjs";
3
3
  import { RowData } from "./RowData.mjs";
4
4
  import { EntityMetadata } from "./EntityMetadata.mjs";
@@ -1,4 +1,3 @@
1
- import "./Todo.js";
2
1
  import "./EntityMetadata.js";
3
2
  import { isDefined } from "./EntityManager.js";
4
3
  import "./Entity.js";
@@ -1 +1 @@
1
- {"version":3,"file":"PluginManager.js","names":["#pluginsByCallback","#plugins"],"sources":["../src/PluginManager.ts"],"sourcesContent":["import { type Entity } from \"./Entity.ts\";\nimport { type EntityManager, type FindOperation, isDefined } from \"./EntityManager.ts\";\nimport { type EntityMetadata } from \"./EntityMetadata.ts\";\nimport type { ParsedFindQuery } from \"./queries/find/QueryParser.ts\";\nimport { type RowData } from \"./RowData.ts\";\nimport { type JoinRowTodo, type Todo } from \"./Todo.ts\";\n\ninterface PluginMethods {\n /**\n * Called before a field value is retrieved from an entity via getField.\n *\n * @param entity The entity instance being accessed\n * @param field The field name being retrieved\n */\n beforeGetField?(entity: Entity, field: string): void;\n /**\n * Called before a field value is set on an entity via setField.\n *\n * @param entity The entity instance being modified\n * @param field The field name being set\n * @param newValue The new value being assigned to the field\n */\n beforeSetField?(entity: Entity, field: string, newValue: any): void;\n /**\n * Called before a find operation is executed.\n *\n * @param meta Metadata for the entity type being queried\n * @param operation The type of find operation being performed\n * @param query The parsed query conditions\n * @param settings Query settings including limit and offset\n */\n beforeFind?(\n meta: EntityMetadata,\n operation: FindOperation,\n query: ParsedFindQuery,\n settings: {\n limit?: number;\n offset?: number;\n allowMultipleLeftJoins?: boolean;\n optimizeJoinsToExists?: boolean;\n pruneJoins?: boolean;\n keepAliases?: string[];\n },\n ): void;\n /**\n * Called after a find operation has been executed to observe the raw database rows.\n *\n * The result is an observation-only {@link RowData} view — i.e. `rows.rowCount` for metrics,\n * `rows.get(i, columnName)` for specific cells, or `rows.toRows()` to materialize POJO rows.\n * For lazy results, cells decode on access, so a hook that only counts rows costs nothing;\n * materializing via `toRows()` decodes every cell of every row. Mutating materialized rows is\n * unsupported and is not guaranteed to affect entity hydration.\n *\n * @param meta Metadata for the entity type that was queried\n * @param operation The type of find operation that was performed\n * @param rows A read-only view of the raw database rows returned from the query\n */\n afterFind?(meta: EntityMetadata, operation: FindOperation, rows: RowData): void;\n\n beforeValidate?(entities: readonly Entity[]): Promise<void> | void;\n\n afterValidate?(entities: readonly Entity[]): Promise<void> | void;\n\n afterWrite(entityTodos: Record<string, Todo>, joinRowTodos: Record<string, JoinRowTodo>): void;\n}\n\nconst syncPluginMethods = [\n \"beforeGetField\",\n \"beforeSetField\",\n \"beforeFind\",\n \"afterFind\",\n \"afterWrite\",\n] as const satisfies readonly (keyof PluginMethods)[];\nconst asyncPluginMethods = [\"beforeValidate\", \"afterValidate\"] as const satisfies readonly (keyof PluginMethods)[];\nconst emsSymbol = Symbol(\"ems\");\n/**\n * Base class for plugins that hook into entity lifecycle events.\n *\n * Plugins can implement any of the PluginMethods to intercept entity operations\n * and are automatically registered with the EntityManager when added via PluginManager.\n */\nexport abstract class Plugin {\n // We need to store the EntityManager references in a WeakRef array so that they can be garbage collected. If we\n // didn't do this, then multiple EMs with the same plugin instance could keep each other from being garbage collected.\n [emsSymbol]: WeakRef<EntityManager>[] = [];\n\n maybeCloneForNewEm(): this | undefined {\n return undefined;\n }\n\n get ems(): readonly EntityManager[] {\n return this[emsSymbol]\n .values()\n .map((wr) => wr.deref())\n .filter(isDefined)\n .toArray();\n }\n}\n\nexport interface Plugin extends PluginMethods {}\n\n/**\n * Manages plugin lifecycle and dispatches plugin callbacks to registered plugins.\n *\n * The PluginManager optimizes callback dispatch by only creating dispatcher methods\n * for callbacks that have at least one registered plugin, making unused plugin hooks\n * zero-cost at runtime.\n */\nexport class PluginManager implements Required<PluginMethods> {\n #plugins = new Set<Plugin>();\n readonly #pluginsByCallback: Partial<Record<keyof Plugin, Plugin[]>> = {};\n constructor(public readonly em: EntityManager) {}\n\n /** Returns whether any registered plugin implements `method`, i.e. so callers can skip building its args. */\n hasHook(method: keyof PluginMethods): boolean {\n return this.#pluginsByCallback[method] !== undefined;\n }\n\n /**\n * Registers a plugin with this EntityManager.\n *\n * Dynamically creates dispatcher methods for any plugin callbacks implemented by this plugin,\n * enabling lazy initialization of only the hooks that are actually used.\n *\n * @throws Error if the plugin is already registered with another EntityManager\n */\n addPlugin(plugin: Plugin) {\n if (this.#plugins.has(plugin)) return; // if we're already added, then we can just early exit\n this.#plugins.add(plugin);\n plugin[emsSymbol].push(new WeakRef(this.em));\n for (const method of syncPluginMethods) {\n if (method in plugin) {\n (this.#pluginsByCallback[method] ??= []).push(plugin);\n // As a performance optimization, we only create the actual implementation for each method on the plugin manager\n // once we have at least one plugin using that method. This is to make it so any unused plugin methods are\n // effectively no-ops when called from within the em.\n if (!Object.hasOwn(this, method)) {\n this[method] = function (this: PluginManager, ...args: any[]) {\n for (const plugin of this.#pluginsByCallback[method]!) {\n (plugin[method] as (...args: any[]) => unknown)(...args);\n }\n };\n }\n }\n }\n for (const method of asyncPluginMethods) {\n if (method in plugin) {\n (this.#pluginsByCallback[method] ??= []).push(plugin);\n // Validate-phase plugin hooks are intentionally awaited without making hot-path hooks async.\n if (!Object.hasOwn(this, method)) {\n this[method] = async function (this: PluginManager, ...args: any[]) {\n for (const plugin of this.#pluginsByCallback[method]!) {\n await (plugin[method] as (...args: any[]) => Promise<void> | void)(...args);\n }\n };\n }\n }\n }\n }\n\n get plugins(): readonly Plugin[] {\n return [...this.#plugins];\n }\n\n cloneTo(other: PluginManager) {\n this.#plugins\n .values()\n .map((plugin) => plugin.maybeCloneForNewEm())\n .filter(isDefined)\n .forEach((plugin) => other.addPlugin(plugin));\n }\n\n // Defined as no-op functions initially instead of using optional chaining for performance reasons, see:\n // https://adventures.nodeland.dev/archive/noop-functions-vs-optional-chaining-a-performance/\n\n beforeGetField(entity: Entity, field: string): void {}\n beforeSetField(entity: Entity, field: string, newValue: any): void {}\n beforeFind(\n meta: EntityMetadata,\n operation: FindOperation,\n query: ParsedFindQuery,\n settings: {\n limit?: number;\n offset?: number;\n allowMultipleLeftJoins?: boolean;\n optimizeJoinsToExists?: boolean;\n pruneJoins?: boolean;\n keepAliases?: string[];\n },\n ): void {}\n afterFind(meta: EntityMetadata, operation: FindOperation, rows: RowData) {}\n beforeValidate(entities: readonly Entity[]): Promise<void> | void {}\n afterValidate(entities: readonly Entity[]): Promise<void> | void {}\n afterWrite(entityTodos: Record<string, Todo>, joinRowTodos: Record<string, JoinRowTodo>): void {}\n}\n"],"mappings":";;;;;AAkEA,MAAM,oBAAoB;CACxB;CACA;CACA;CACA;CACA;AACF;AACA,MAAM,qBAAqB,CAAC,kBAAkB,eAAe;AAC7D,MAAM,YAAY,OAAO,KAAK;;;;;;;AAO9B,IAAsB,SAAtB,MAA6B;CAG3B,CAAC,aAAuC,CAAC;CAEzC,qBAAuC,CAEvC;CAEA,IAAI,MAAgC;EAClC,OAAO,KAAK,UAAU,CACnB,OAAO,CAAC,CACR,KAAK,OAAO,GAAG,MAAM,CAAC,CAAC,CACvB,OAAO,SAAS,CAAC,CACjB,QAAQ;CACb;AACF;;;;;;;;AAWA,IAAa,gBAAb,MAA8D;CAGhC;CAF5B,2BAAW,IAAI,IAAY;CAC3B,qBAAuE,CAAC;CACxE,YAAY,IAAmC;EAAnB,KAAA,KAAA;CAAoB;;CAGhD,QAAQ,QAAsC;EAC5C,OAAO,KAAKA,mBAAmB,YAAY,KAAA;CAC7C;;;;;;;;;CAUA,UAAU,QAAgB;EACxB,IAAI,KAAKC,SAAS,IAAI,MAAM,GAAG;EAC/B,KAAKA,SAAS,IAAI,MAAM;EACxB,OAAO,UAAU,CAAC,KAAK,IAAI,QAAQ,KAAK,EAAE,CAAC;EAC3C,KAAK,MAAM,UAAU,mBACnB,IAAI,UAAU,QAAQ;GACpB,CAAC,KAAKD,mBAAmB,YAAY,CAAC,EAAA,CAAG,KAAK,MAAM;GAIpD,IAAI,CAAC,OAAO,OAAO,MAAM,MAAM,GAC7B,KAAK,UAAU,SAA+B,GAAG,MAAa;IAC5D,KAAK,MAAM,UAAU,KAAKA,mBAAmB,SAC3C,OAAQ,OAAO,CAAiC,GAAG,IAAI;GAE3D;EAEJ;EAEF,KAAK,MAAM,UAAU,oBACnB,IAAI,UAAU,QAAQ;GACpB,CAAC,KAAKA,mBAAmB,YAAY,CAAC,EAAA,CAAG,KAAK,MAAM;GAEpD,IAAI,CAAC,OAAO,OAAO,MAAM,MAAM,GAC7B,KAAK,UAAU,eAAqC,GAAG,MAAa;IAClE,KAAK,MAAM,UAAU,KAAKA,mBAAmB,SAC3C,MAAO,OAAO,OAAO,CAA8C,GAAG,IAAI;GAE9E;EAEJ;CAEJ;CAEA,IAAI,UAA6B;EAC/B,OAAO,CAAC,GAAG,KAAKC,QAAQ;CAC1B;CAEA,QAAQ,OAAsB;EAC5B,KAAKA,SACF,OAAO,CAAC,CACR,KAAK,WAAW,OAAO,mBAAmB,CAAC,CAAC,CAC5C,OAAO,SAAS,CAAC,CACjB,SAAS,WAAW,MAAM,UAAU,MAAM,CAAC;CAChD;CAKA,eAAe,QAAgB,OAAqB,CAAC;CACrD,eAAe,QAAgB,OAAe,UAAqB,CAAC;CACpE,WACE,MACA,WACA,OACA,UAQM,CAAC;CACT,UAAU,MAAsB,WAA0B,MAAe,CAAC;CAC1E,eAAe,UAAmD,CAAC;CACnE,cAAc,UAAmD,CAAC;CAClE,WAAW,aAAmC,cAAiD,CAAC;AAClG"}
1
+ {"version":3,"file":"PluginManager.js","names":["#pluginsByCallback","#plugins"],"sources":["../src/PluginManager.ts"],"sourcesContent":["import { type Entity } from \"./Entity.ts\";\nimport { type EntityManager, type FindOperation, isDefined } from \"./EntityManager.ts\";\nimport { type EntityMetadata } from \"./EntityMetadata.ts\";\nimport type { JoinRowTodo, Todo } from \"./flush/Todo.ts\";\nimport type { ParsedFindQuery } from \"./queries/find/QueryParser.ts\";\nimport { type RowData } from \"./RowData.ts\";\n\ninterface PluginMethods {\n /**\n * Called before a field value is retrieved from an entity via getField.\n *\n * @param entity The entity instance being accessed\n * @param field The field name being retrieved\n */\n beforeGetField?(entity: Entity, field: string): void;\n /**\n * Called before a field value is set on an entity via setField.\n *\n * @param entity The entity instance being modified\n * @param field The field name being set\n * @param newValue The new value being assigned to the field\n */\n beforeSetField?(entity: Entity, field: string, newValue: any): void;\n /**\n * Called before a find operation is executed.\n *\n * @param meta Metadata for the entity type being queried\n * @param operation The type of find operation being performed\n * @param query The parsed query conditions\n * @param settings Query settings including limit and offset\n */\n beforeFind?(\n meta: EntityMetadata,\n operation: FindOperation,\n query: ParsedFindQuery,\n settings: {\n limit?: number;\n offset?: number;\n allowMultipleLeftJoins?: boolean;\n optimizeJoinsToExists?: boolean;\n pruneJoins?: boolean;\n keepAliases?: string[];\n },\n ): void;\n /**\n * Called after a find operation has been executed to observe the raw database rows.\n *\n * The result is an observation-only {@link RowData} view — i.e. `rows.rowCount` for metrics,\n * `rows.get(i, columnName)` for specific cells, or `rows.toRows()` to materialize POJO rows.\n * For lazy results, cells decode on access, so a hook that only counts rows costs nothing;\n * materializing via `toRows()` decodes every cell of every row. Mutating materialized rows is\n * unsupported and is not guaranteed to affect entity hydration.\n *\n * @param meta Metadata for the entity type that was queried\n * @param operation The type of find operation that was performed\n * @param rows A read-only view of the raw database rows returned from the query\n */\n afterFind?(meta: EntityMetadata, operation: FindOperation, rows: RowData): void;\n\n beforeValidate?(entities: readonly Entity[]): Promise<void> | void;\n\n afterValidate?(entities: readonly Entity[]): Promise<void> | void;\n\n afterWrite(entityTodos: Record<string, Todo>, joinRowTodos: Record<string, JoinRowTodo>): void;\n}\n\nconst syncPluginMethods = [\n \"beforeGetField\",\n \"beforeSetField\",\n \"beforeFind\",\n \"afterFind\",\n \"afterWrite\",\n] as const satisfies readonly (keyof PluginMethods)[];\nconst asyncPluginMethods = [\"beforeValidate\", \"afterValidate\"] as const satisfies readonly (keyof PluginMethods)[];\nconst emsSymbol = Symbol(\"ems\");\n/**\n * Base class for plugins that hook into entity lifecycle events.\n *\n * Plugins can implement any of the PluginMethods to intercept entity operations\n * and are automatically registered with the EntityManager when added via PluginManager.\n */\nexport abstract class Plugin {\n // We need to store the EntityManager references in a WeakRef array so that they can be garbage collected. If we\n // didn't do this, then multiple EMs with the same plugin instance could keep each other from being garbage collected.\n [emsSymbol]: WeakRef<EntityManager>[] = [];\n\n maybeCloneForNewEm(): this | undefined {\n return undefined;\n }\n\n get ems(): readonly EntityManager[] {\n return this[emsSymbol]\n .values()\n .map((wr) => wr.deref())\n .filter(isDefined)\n .toArray();\n }\n}\n\nexport interface Plugin extends PluginMethods {}\n\n/**\n * Manages plugin lifecycle and dispatches plugin callbacks to registered plugins.\n *\n * The PluginManager optimizes callback dispatch by only creating dispatcher methods\n * for callbacks that have at least one registered plugin, making unused plugin hooks\n * zero-cost at runtime.\n */\nexport class PluginManager implements Required<PluginMethods> {\n #plugins = new Set<Plugin>();\n readonly #pluginsByCallback: Partial<Record<keyof Plugin, Plugin[]>> = {};\n constructor(public readonly em: EntityManager) {}\n\n /** Returns whether any registered plugin implements `method`, i.e. so callers can skip building its args. */\n hasHook(method: keyof PluginMethods): boolean {\n return this.#pluginsByCallback[method] !== undefined;\n }\n\n /**\n * Registers a plugin with this EntityManager.\n *\n * Dynamically creates dispatcher methods for any plugin callbacks implemented by this plugin,\n * enabling lazy initialization of only the hooks that are actually used.\n *\n * @throws Error if the plugin is already registered with another EntityManager\n */\n addPlugin(plugin: Plugin) {\n if (this.#plugins.has(plugin)) return; // if we're already added, then we can just early exit\n this.#plugins.add(plugin);\n plugin[emsSymbol].push(new WeakRef(this.em));\n for (const method of syncPluginMethods) {\n if (method in plugin) {\n (this.#pluginsByCallback[method] ??= []).push(plugin);\n // As a performance optimization, we only create the actual implementation for each method on the plugin manager\n // once we have at least one plugin using that method. This is to make it so any unused plugin methods are\n // effectively no-ops when called from within the em.\n if (!Object.hasOwn(this, method)) {\n this[method] = function (this: PluginManager, ...args: any[]) {\n for (const plugin of this.#pluginsByCallback[method]!) {\n (plugin[method] as (...args: any[]) => unknown)(...args);\n }\n };\n }\n }\n }\n for (const method of asyncPluginMethods) {\n if (method in plugin) {\n (this.#pluginsByCallback[method] ??= []).push(plugin);\n // Validate-phase plugin hooks are intentionally awaited without making hot-path hooks async.\n if (!Object.hasOwn(this, method)) {\n this[method] = async function (this: PluginManager, ...args: any[]) {\n for (const plugin of this.#pluginsByCallback[method]!) {\n await (plugin[method] as (...args: any[]) => Promise<void> | void)(...args);\n }\n };\n }\n }\n }\n }\n\n get plugins(): readonly Plugin[] {\n return [...this.#plugins];\n }\n\n cloneTo(other: PluginManager) {\n this.#plugins\n .values()\n .map((plugin) => plugin.maybeCloneForNewEm())\n .filter(isDefined)\n .forEach((plugin) => other.addPlugin(plugin));\n }\n\n // Defined as no-op functions initially instead of using optional chaining for performance reasons, see:\n // https://adventures.nodeland.dev/archive/noop-functions-vs-optional-chaining-a-performance/\n\n beforeGetField(entity: Entity, field: string): void {}\n beforeSetField(entity: Entity, field: string, newValue: any): void {}\n beforeFind(\n meta: EntityMetadata,\n operation: FindOperation,\n query: ParsedFindQuery,\n settings: {\n limit?: number;\n offset?: number;\n allowMultipleLeftJoins?: boolean;\n optimizeJoinsToExists?: boolean;\n pruneJoins?: boolean;\n keepAliases?: string[];\n },\n ): void {}\n afterFind(meta: EntityMetadata, operation: FindOperation, rows: RowData) {}\n beforeValidate(entities: readonly Entity[]): Promise<void> | void {}\n afterValidate(entities: readonly Entity[]): Promise<void> | void {}\n afterWrite(entityTodos: Record<string, Todo>, joinRowTodos: Record<string, JoinRowTodo>): void {}\n}\n"],"mappings":";;;;AAkEA,MAAM,oBAAoB;CACxB;CACA;CACA;CACA;CACA;AACF;AACA,MAAM,qBAAqB,CAAC,kBAAkB,eAAe;AAC7D,MAAM,YAAY,OAAO,KAAK;;;;;;;AAO9B,IAAsB,SAAtB,MAA6B;CAG3B,CAAC,aAAuC,CAAC;CAEzC,qBAAuC,CAEvC;CAEA,IAAI,MAAgC;EAClC,OAAO,KAAK,UAAU,CACnB,OAAO,CAAC,CACR,KAAK,OAAO,GAAG,MAAM,CAAC,CAAC,CACvB,OAAO,SAAS,CAAC,CACjB,QAAQ;CACb;AACF;;;;;;;;AAWA,IAAa,gBAAb,MAA8D;CAGhC;CAF5B,2BAAW,IAAI,IAAY;CAC3B,qBAAuE,CAAC;CACxE,YAAY,IAAmC;EAAnB,KAAA,KAAA;CAAoB;;CAGhD,QAAQ,QAAsC;EAC5C,OAAO,KAAKA,mBAAmB,YAAY,KAAA;CAC7C;;;;;;;;;CAUA,UAAU,QAAgB;EACxB,IAAI,KAAKC,SAAS,IAAI,MAAM,GAAG;EAC/B,KAAKA,SAAS,IAAI,MAAM;EACxB,OAAO,UAAU,CAAC,KAAK,IAAI,QAAQ,KAAK,EAAE,CAAC;EAC3C,KAAK,MAAM,UAAU,mBACnB,IAAI,UAAU,QAAQ;GACpB,CAAC,KAAKD,mBAAmB,YAAY,CAAC,EAAA,CAAG,KAAK,MAAM;GAIpD,IAAI,CAAC,OAAO,OAAO,MAAM,MAAM,GAC7B,KAAK,UAAU,SAA+B,GAAG,MAAa;IAC5D,KAAK,MAAM,UAAU,KAAKA,mBAAmB,SAC3C,OAAQ,OAAO,CAAiC,GAAG,IAAI;GAE3D;EAEJ;EAEF,KAAK,MAAM,UAAU,oBACnB,IAAI,UAAU,QAAQ;GACpB,CAAC,KAAKA,mBAAmB,YAAY,CAAC,EAAA,CAAG,KAAK,MAAM;GAEpD,IAAI,CAAC,OAAO,OAAO,MAAM,MAAM,GAC7B,KAAK,UAAU,eAAqC,GAAG,MAAa;IAClE,KAAK,MAAM,UAAU,KAAKA,mBAAmB,SAC3C,MAAO,OAAO,OAAO,CAA8C,GAAG,IAAI;GAE9E;EAEJ;CAEJ;CAEA,IAAI,UAA6B;EAC/B,OAAO,CAAC,GAAG,KAAKC,QAAQ;CAC1B;CAEA,QAAQ,OAAsB;EAC5B,KAAKA,SACF,OAAO,CAAC,CACR,KAAK,WAAW,OAAO,mBAAmB,CAAC,CAAC,CAC5C,OAAO,SAAS,CAAC,CACjB,SAAS,WAAW,MAAM,UAAU,MAAM,CAAC;CAChD;CAKA,eAAe,QAAgB,OAAqB,CAAC;CACrD,eAAe,QAAgB,OAAe,UAAqB,CAAC;CACpE,WACE,MACA,WACA,OACA,UAQM,CAAC;CACT,UAAU,MAAsB,WAA0B,MAAe,CAAC;CAC1E,eAAe,UAAmD,CAAC;CACnE,cAAc,UAAmD,CAAC;CAClE,WAAW,aAAmC,cAAiD,CAAC;AAClG"}
@@ -1,7 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  require("./BatchLoader.cjs");
3
- const require_utils = require("../utils.cjs");
4
3
  const require_keys = require("../keys.cjs");
4
+ const require_utils = require("../utils.cjs");
5
5
  require("../index.cjs");
6
6
  const require_EntityManager = require("../EntityManager.cjs");
7
7
  //#region src/batchloaders/enumCollectionBatchLoader.ts
@@ -1,5 +1,5 @@
1
1
  import { BatchLoader } from "./BatchLoader.cjs";
2
- import { ManyToManyLike } from "../JoinRows.cjs";
2
+ import { ManyToManyLike } from "../flush/JoinRows.cjs";
3
3
  import "../index.cjs";
4
4
  import { EntityManager } from "../EntityManager.cjs";
5
5
  //#region src/batchloaders/enumCollectionBatchLoader.d.ts
@@ -1,5 +1,5 @@
1
1
  import { BatchLoader } from "./BatchLoader.mjs";
2
- import { ManyToManyLike } from "../JoinRows.mjs";
2
+ import { ManyToManyLike } from "../flush/JoinRows.mjs";
3
3
  import "../index.mjs";
4
4
  import { EntityManager } from "../EntityManager.mjs";
5
5
  //#region src/batchloaders/enumCollectionBatchLoader.d.ts
@@ -1,6 +1,6 @@
1
1
  import "./BatchLoader.js";
2
- import { abbreviation } from "../utils.js";
3
2
  import { keyToNumber } from "../keys.js";
3
+ import { abbreviation } from "../utils.js";
4
4
  import "../index.js";
5
5
  import { getEmInternalApi } from "../EntityManager.js";
6
6
  //#region src/batchloaders/enumCollectionBatchLoader.ts
@@ -1,12 +1,11 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  require("./BatchLoader.cjs");
3
+ const require_keys = require("../keys.cjs");
3
4
  const require_queries_entityQueryUtils = require("../queries/entityQueryUtils.cjs");
4
5
  const require_queries_find_QueryParser = require("../queries/find/QueryParser.cjs");
5
- require("../loadHints.cjs");
6
6
  const require_utils = require("../utils.cjs");
7
- const require_keys = require("../keys.cjs");
8
7
  require("../EntityMetadata.cjs");
9
- const require_HintTree = require("../HintTree.cjs");
8
+ const require_loading_HintTree = require("../loading/HintTree.cjs");
10
9
  const require_EntityManager = require("../EntityManager.cjs");
11
10
  const require_BaseEntity = require("../BaseEntity.cjs");
12
11
  //#region src/batchloaders/loadBatchLoader.ts
@@ -51,7 +50,7 @@ function loadBatchLoader(em, meta, overwriteExisting = false) {
51
50
  };
52
51
  require_queries_find_QueryParser.addTablePerClassJoinsAndClassTag(query, meta, alias, true);
53
52
  const { preloader } = require_EntityManager.getEmInternalApi(em);
54
- const preloadHydrator = preloader && preloader.addPreloading(meta, require_HintTree.buildHintTree(loads.map((l) => ({
53
+ const preloadHydrator = preloader && preloader.addPreloading(meta, require_loading_HintTree.buildHintTree(loads.map((l) => ({
55
54
  entity: l.taggedId,
56
55
  hint: l.hint
57
56
  }))), query);
@@ -1 +1 @@
1
- {"version":3,"file":"loadBatchLoader.cjs","names":["keyToNumber","abbreviation","lazyExcludedSelects","getEmInternalApi","buildHintTree","tagId"],"sources":["../../src/batchloaders/loadBatchLoader.ts"],"sourcesContent":["import { getInstanceData } from \"../BaseEntity.ts\";\nimport { type EntityManager, getEmInternalApi } from \"../EntityManager.ts\";\nimport { type EntityMetadata } from \"../EntityMetadata.ts\";\nimport { buildHintTree } from \"../HintTree.ts\";\nimport { keyToNumber, tagId } from \"../keys.ts\";\nimport { type LoadHint } from \"../loadHints.ts\";\nimport { lazyExcludedSelects } from \"../queries/entityQueryUtils.ts\";\nimport { type ParsedFindQuery, addTablePerClassJoinsAndClassTag } from \"../queries/find/QueryParser.ts\";\nimport { abbreviation } from \"../utils.ts\";\nimport { type BatchLoader } from \"./BatchLoader.ts\";\n\nexport const loadOperation = \"load\";\n\n/**\n * Batches em.load-style fetches, writing to identity map (via hydrate) instead of returning values.\n * After the batch resolves, callers retrieve their entity from `em.findExistingInstance`.\n *\n * Accepts tuples of `{ taggedId, hint }` so the preloader can inject join-based\n * preloading into the same SELECT that fetches the entities.\n */\nexport function loadBatchLoader(\n em: EntityManager,\n meta: EntityMetadata,\n overwriteExisting: boolean = false,\n): BatchLoader<{ taggedId: string; hint: LoadHint<any> | undefined }> {\n return em.getBatchLoader(loadOperation, `${meta.type}-${overwriteExisting}`, async (loads) => {\n const keys = loads.map((l) => keyToNumber(meta, l.taggedId));\n const alias = abbreviation(meta.tableName);\n const query = {\n selects: meta.hasLazyColumns ? lazyExcludedSelects(meta, alias) : [`\"${alias}\".*`],\n tables: [{ alias, join: \"primary\", table: meta.tableName }],\n condition: {\n kind: \"exp\",\n op: \"and\",\n conditions: [{ kind: \"column\", alias, column: \"id\", dbType: meta.idDbType, cond: { kind: \"in\", value: keys } }],\n },\n orderBys: [{ alias, column: \"id\", order: \"ASC\" }],\n } satisfies ParsedFindQuery;\n addTablePerClassJoinsAndClassTag(query, meta, alias, true);\n // Inject preloading joins into the query if enabled\n const { preloader } = getEmInternalApi(em);\n const preloadHydrator =\n preloader &&\n preloader.addPreloading(meta, buildHintTree(loads.map((l) => ({ entity: l.taggedId, hint: l.hint }))), query);\n const rowData = await em[\"executeFindRowData\"](meta, loadOperation, query, {});\n em[\"hydrateAndFinalize\"](meta.cstr, rowData, {\n overwriteExisting,\n sidecars: (entities) => {\n preloadHydrator && preloadHydrator(rowData, entities);\n // If we're missing any requested rows, mark any requested-but-not-found entities as deleted\n if (rowData.rowCount !== loads.length) {\n const foundIds = new Set<string>();\n for (let i = 0; i < rowData.rowCount; i++) foundIds.add(tagId(meta, rowData.get(i, \"id\")));\n for (const load of loads) {\n if (!foundIds.has(load.taggedId)) {\n const existingEntity = em.findExistingInstance(load.taggedId);\n if (existingEntity) {\n getInstanceData(existingEntity).markDeletedBecauseNotFound();\n }\n }\n }\n }\n },\n });\n });\n}\n"],"mappings":";;;;;;;;;;;;AAWA,MAAa,gBAAgB;;;;;;;;AAS7B,SAAgB,gBACd,IACA,MACA,oBAA6B,OACuC;CACpE,OAAO,GAAG,eAAe,eAAe,GAAG,KAAK,KAAK,GAAG,qBAAqB,OAAO,UAAU;EAC5F,MAAM,OAAO,MAAM,KAAK,MAAMA,aAAAA,YAAY,MAAM,EAAE,QAAQ,CAAC;EAC3D,MAAM,QAAQC,cAAAA,aAAa,KAAK,SAAS;EACzC,MAAM,QAAQ;GACZ,SAAS,KAAK,iBAAiBC,iCAAAA,oBAAoB,MAAM,KAAK,IAAI,CAAC,IAAI,MAAM,IAAI;GACjF,QAAQ,CAAC;IAAE;IAAO,MAAM;IAAW,OAAO,KAAK;GAAU,CAAC;GAC1D,WAAW;IACT,MAAM;IACN,IAAI;IACJ,YAAY,CAAC;KAAE,MAAM;KAAU;KAAO,QAAQ;KAAM,QAAQ,KAAK;KAAU,MAAM;MAAE,MAAM;MAAM,OAAO;KAAK;IAAE,CAAC;GAChH;GACA,UAAU,CAAC;IAAE;IAAO,QAAQ;IAAM,OAAO;GAAM,CAAC;EAClD;EACA,iCAAA,iCAAiC,OAAO,MAAM,OAAO,IAAI;EAEzD,MAAM,EAAE,cAAcC,sBAAAA,iBAAiB,EAAE;EACzC,MAAM,kBACJ,aACA,UAAU,cAAc,MAAMC,iBAAAA,cAAc,MAAM,KAAK,OAAO;GAAE,QAAQ,EAAE;GAAU,MAAM,EAAE;EAAK,EAAE,CAAC,GAAG,KAAK;EAC9G,MAAM,UAAU,MAAM,GAAG,qBAAqB,CAAC,MAAM,eAAe,OAAO,CAAC,CAAC;EAC7E,GAAG,qBAAqB,CAAC,KAAK,MAAM,SAAS;GAC3C;GACA,WAAW,aAAa;IACtB,mBAAmB,gBAAgB,SAAS,QAAQ;IAEpD,IAAI,QAAQ,aAAa,MAAM,QAAQ;KACrC,MAAM,2BAAW,IAAI,IAAY;KACjC,KAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,UAAU,KAAK,SAAS,IAAIC,aAAAA,MAAM,MAAM,QAAQ,IAAI,GAAG,IAAI,CAAC,CAAC;KACzF,KAAK,MAAM,QAAQ,OACjB,IAAI,CAAC,SAAS,IAAI,KAAK,QAAQ,GAAG;MAChC,MAAM,iBAAiB,GAAG,qBAAqB,KAAK,QAAQ;MAC5D,IAAI,gBACF,mBAAA,gBAAgB,cAAc,CAAC,CAAC,2BAA2B;KAE/D;IAEJ;GACF;EACF,CAAC;CACH,CAAC;AACH"}
1
+ {"version":3,"file":"loadBatchLoader.cjs","names":["keyToNumber","abbreviation","lazyExcludedSelects","getEmInternalApi","buildHintTree","tagId"],"sources":["../../src/batchloaders/loadBatchLoader.ts"],"sourcesContent":["import { getInstanceData } from \"../BaseEntity.ts\";\nimport { type EntityManager, getEmInternalApi } from \"../EntityManager.ts\";\nimport { type EntityMetadata } from \"../EntityMetadata.ts\";\nimport { keyToNumber, tagId } from \"../keys.ts\";\nimport { buildHintTree } from \"../loading/HintTree.ts\";\nimport type { LoadHint } from \"../loading/loadHints.ts\";\nimport { lazyExcludedSelects } from \"../queries/entityQueryUtils.ts\";\nimport { type ParsedFindQuery, addTablePerClassJoinsAndClassTag } from \"../queries/find/QueryParser.ts\";\nimport { abbreviation } from \"../utils.ts\";\nimport { type BatchLoader } from \"./BatchLoader.ts\";\n\nexport const loadOperation = \"load\";\n\n/**\n * Batches em.load-style fetches, writing to identity map (via hydrate) instead of returning values.\n * After the batch resolves, callers retrieve their entity from `em.findExistingInstance`.\n *\n * Accepts tuples of `{ taggedId, hint }` so the preloader can inject join-based\n * preloading into the same SELECT that fetches the entities.\n */\nexport function loadBatchLoader(\n em: EntityManager,\n meta: EntityMetadata,\n overwriteExisting: boolean = false,\n): BatchLoader<{ taggedId: string; hint: LoadHint<any> | undefined }> {\n return em.getBatchLoader(loadOperation, `${meta.type}-${overwriteExisting}`, async (loads) => {\n const keys = loads.map((l) => keyToNumber(meta, l.taggedId));\n const alias = abbreviation(meta.tableName);\n const query = {\n selects: meta.hasLazyColumns ? lazyExcludedSelects(meta, alias) : [`\"${alias}\".*`],\n tables: [{ alias, join: \"primary\", table: meta.tableName }],\n condition: {\n kind: \"exp\",\n op: \"and\",\n conditions: [{ kind: \"column\", alias, column: \"id\", dbType: meta.idDbType, cond: { kind: \"in\", value: keys } }],\n },\n orderBys: [{ alias, column: \"id\", order: \"ASC\" }],\n } satisfies ParsedFindQuery;\n addTablePerClassJoinsAndClassTag(query, meta, alias, true);\n // Inject preloading joins into the query if enabled\n const { preloader } = getEmInternalApi(em);\n const preloadHydrator =\n preloader &&\n preloader.addPreloading(meta, buildHintTree(loads.map((l) => ({ entity: l.taggedId, hint: l.hint }))), query);\n const rowData = await em[\"executeFindRowData\"](meta, loadOperation, query, {});\n em[\"hydrateAndFinalize\"](meta.cstr, rowData, {\n overwriteExisting,\n sidecars: (entities) => {\n preloadHydrator && preloadHydrator(rowData, entities);\n // If we're missing any requested rows, mark any requested-but-not-found entities as deleted\n if (rowData.rowCount !== loads.length) {\n const foundIds = new Set<string>();\n for (let i = 0; i < rowData.rowCount; i++) foundIds.add(tagId(meta, rowData.get(i, \"id\")));\n for (const load of loads) {\n if (!foundIds.has(load.taggedId)) {\n const existingEntity = em.findExistingInstance(load.taggedId);\n if (existingEntity) {\n getInstanceData(existingEntity).markDeletedBecauseNotFound();\n }\n }\n }\n }\n },\n });\n });\n}\n"],"mappings":";;;;;;;;;;;AAWA,MAAa,gBAAgB;;;;;;;;AAS7B,SAAgB,gBACd,IACA,MACA,oBAA6B,OACuC;CACpE,OAAO,GAAG,eAAe,eAAe,GAAG,KAAK,KAAK,GAAG,qBAAqB,OAAO,UAAU;EAC5F,MAAM,OAAO,MAAM,KAAK,MAAMA,aAAAA,YAAY,MAAM,EAAE,QAAQ,CAAC;EAC3D,MAAM,QAAQC,cAAAA,aAAa,KAAK,SAAS;EACzC,MAAM,QAAQ;GACZ,SAAS,KAAK,iBAAiBC,iCAAAA,oBAAoB,MAAM,KAAK,IAAI,CAAC,IAAI,MAAM,IAAI;GACjF,QAAQ,CAAC;IAAE;IAAO,MAAM;IAAW,OAAO,KAAK;GAAU,CAAC;GAC1D,WAAW;IACT,MAAM;IACN,IAAI;IACJ,YAAY,CAAC;KAAE,MAAM;KAAU;KAAO,QAAQ;KAAM,QAAQ,KAAK;KAAU,MAAM;MAAE,MAAM;MAAM,OAAO;KAAK;IAAE,CAAC;GAChH;GACA,UAAU,CAAC;IAAE;IAAO,QAAQ;IAAM,OAAO;GAAM,CAAC;EAClD;EACA,iCAAA,iCAAiC,OAAO,MAAM,OAAO,IAAI;EAEzD,MAAM,EAAE,cAAcC,sBAAAA,iBAAiB,EAAE;EACzC,MAAM,kBACJ,aACA,UAAU,cAAc,MAAMC,yBAAAA,cAAc,MAAM,KAAK,OAAO;GAAE,QAAQ,EAAE;GAAU,MAAM,EAAE;EAAK,EAAE,CAAC,GAAG,KAAK;EAC9G,MAAM,UAAU,MAAM,GAAG,qBAAqB,CAAC,MAAM,eAAe,OAAO,CAAC,CAAC;EAC7E,GAAG,qBAAqB,CAAC,KAAK,MAAM,SAAS;GAC3C;GACA,WAAW,aAAa;IACtB,mBAAmB,gBAAgB,SAAS,QAAQ;IAEpD,IAAI,QAAQ,aAAa,MAAM,QAAQ;KACrC,MAAM,2BAAW,IAAI,IAAY;KACjC,KAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,UAAU,KAAK,SAAS,IAAIC,aAAAA,MAAM,MAAM,QAAQ,IAAI,GAAG,IAAI,CAAC,CAAC;KACzF,KAAK,MAAM,QAAQ,OACjB,IAAI,CAAC,SAAS,IAAI,KAAK,QAAQ,GAAG;MAChC,MAAM,iBAAiB,GAAG,qBAAqB,KAAK,QAAQ;MAC5D,IAAI,gBACF,mBAAA,gBAAgB,cAAc,CAAC,CAAC,2BAA2B;KAE/D;IAEJ;GACF;EACF,CAAC;CACH,CAAC;AACH"}
@@ -1,5 +1,5 @@
1
1
  import { BatchLoader } from "./BatchLoader.cjs";
2
- import { LoadHint } from "../loadHints.cjs";
2
+ import { LoadHint } from "../loading/loadHints.cjs";
3
3
  import { EntityMetadata } from "../EntityMetadata.cjs";
4
4
  import { EntityManager } from "../EntityManager.cjs";
5
5
  //#region src/batchloaders/loadBatchLoader.d.ts
@@ -1,5 +1,5 @@
1
1
  import { BatchLoader } from "./BatchLoader.mjs";
2
- import { LoadHint } from "../loadHints.mjs";
2
+ import { LoadHint } from "../loading/loadHints.mjs";
3
3
  import { EntityMetadata } from "../EntityMetadata.mjs";
4
4
  import { EntityManager } from "../EntityManager.mjs";
5
5
  //#region src/batchloaders/loadBatchLoader.d.ts
@@ -1,11 +1,10 @@
1
1
  import "./BatchLoader.js";
2
+ import { keyToNumber, tagId } from "../keys.js";
2
3
  import { lazyExcludedSelects } from "../queries/entityQueryUtils.js";
3
4
  import { addTablePerClassJoinsAndClassTag } from "../queries/find/QueryParser.js";
4
- import "../loadHints.js";
5
5
  import { abbreviation } from "../utils.js";
6
- import { keyToNumber, tagId } from "../keys.js";
7
6
  import "../EntityMetadata.js";
8
- import { buildHintTree } from "../HintTree.js";
7
+ import { buildHintTree } from "../loading/HintTree.js";
9
8
  import { getEmInternalApi } from "../EntityManager.js";
10
9
  import { getInstanceData } from "../BaseEntity.js";
11
10
  //#region src/batchloaders/loadBatchLoader.ts
@@ -1 +1 @@
1
- {"version":3,"file":"loadBatchLoader.js","names":[],"sources":["../../src/batchloaders/loadBatchLoader.ts"],"sourcesContent":["import { getInstanceData } from \"../BaseEntity.ts\";\nimport { type EntityManager, getEmInternalApi } from \"../EntityManager.ts\";\nimport { type EntityMetadata } from \"../EntityMetadata.ts\";\nimport { buildHintTree } from \"../HintTree.ts\";\nimport { keyToNumber, tagId } from \"../keys.ts\";\nimport { type LoadHint } from \"../loadHints.ts\";\nimport { lazyExcludedSelects } from \"../queries/entityQueryUtils.ts\";\nimport { type ParsedFindQuery, addTablePerClassJoinsAndClassTag } from \"../queries/find/QueryParser.ts\";\nimport { abbreviation } from \"../utils.ts\";\nimport { type BatchLoader } from \"./BatchLoader.ts\";\n\nexport const loadOperation = \"load\";\n\n/**\n * Batches em.load-style fetches, writing to identity map (via hydrate) instead of returning values.\n * After the batch resolves, callers retrieve their entity from `em.findExistingInstance`.\n *\n * Accepts tuples of `{ taggedId, hint }` so the preloader can inject join-based\n * preloading into the same SELECT that fetches the entities.\n */\nexport function loadBatchLoader(\n em: EntityManager,\n meta: EntityMetadata,\n overwriteExisting: boolean = false,\n): BatchLoader<{ taggedId: string; hint: LoadHint<any> | undefined }> {\n return em.getBatchLoader(loadOperation, `${meta.type}-${overwriteExisting}`, async (loads) => {\n const keys = loads.map((l) => keyToNumber(meta, l.taggedId));\n const alias = abbreviation(meta.tableName);\n const query = {\n selects: meta.hasLazyColumns ? lazyExcludedSelects(meta, alias) : [`\"${alias}\".*`],\n tables: [{ alias, join: \"primary\", table: meta.tableName }],\n condition: {\n kind: \"exp\",\n op: \"and\",\n conditions: [{ kind: \"column\", alias, column: \"id\", dbType: meta.idDbType, cond: { kind: \"in\", value: keys } }],\n },\n orderBys: [{ alias, column: \"id\", order: \"ASC\" }],\n } satisfies ParsedFindQuery;\n addTablePerClassJoinsAndClassTag(query, meta, alias, true);\n // Inject preloading joins into the query if enabled\n const { preloader } = getEmInternalApi(em);\n const preloadHydrator =\n preloader &&\n preloader.addPreloading(meta, buildHintTree(loads.map((l) => ({ entity: l.taggedId, hint: l.hint }))), query);\n const rowData = await em[\"executeFindRowData\"](meta, loadOperation, query, {});\n em[\"hydrateAndFinalize\"](meta.cstr, rowData, {\n overwriteExisting,\n sidecars: (entities) => {\n preloadHydrator && preloadHydrator(rowData, entities);\n // If we're missing any requested rows, mark any requested-but-not-found entities as deleted\n if (rowData.rowCount !== loads.length) {\n const foundIds = new Set<string>();\n for (let i = 0; i < rowData.rowCount; i++) foundIds.add(tagId(meta, rowData.get(i, \"id\")));\n for (const load of loads) {\n if (!foundIds.has(load.taggedId)) {\n const existingEntity = em.findExistingInstance(load.taggedId);\n if (existingEntity) {\n getInstanceData(existingEntity).markDeletedBecauseNotFound();\n }\n }\n }\n }\n },\n });\n });\n}\n"],"mappings":";;;;;;;;;;;AAWA,MAAa,gBAAgB;;;;;;;;AAS7B,SAAgB,gBACd,IACA,MACA,oBAA6B,OACuC;CACpE,OAAO,GAAG,eAAe,eAAe,GAAG,KAAK,KAAK,GAAG,qBAAqB,OAAO,UAAU;EAC5F,MAAM,OAAO,MAAM,KAAK,MAAM,YAAY,MAAM,EAAE,QAAQ,CAAC;EAC3D,MAAM,QAAQ,aAAa,KAAK,SAAS;EACzC,MAAM,QAAQ;GACZ,SAAS,KAAK,iBAAiB,oBAAoB,MAAM,KAAK,IAAI,CAAC,IAAI,MAAM,IAAI;GACjF,QAAQ,CAAC;IAAE;IAAO,MAAM;IAAW,OAAO,KAAK;GAAU,CAAC;GAC1D,WAAW;IACT,MAAM;IACN,IAAI;IACJ,YAAY,CAAC;KAAE,MAAM;KAAU;KAAO,QAAQ;KAAM,QAAQ,KAAK;KAAU,MAAM;MAAE,MAAM;MAAM,OAAO;KAAK;IAAE,CAAC;GAChH;GACA,UAAU,CAAC;IAAE;IAAO,QAAQ;IAAM,OAAO;GAAM,CAAC;EAClD;EACA,iCAAiC,OAAO,MAAM,OAAO,IAAI;EAEzD,MAAM,EAAE,cAAc,iBAAiB,EAAE;EACzC,MAAM,kBACJ,aACA,UAAU,cAAc,MAAM,cAAc,MAAM,KAAK,OAAO;GAAE,QAAQ,EAAE;GAAU,MAAM,EAAE;EAAK,EAAE,CAAC,GAAG,KAAK;EAC9G,MAAM,UAAU,MAAM,GAAG,qBAAqB,CAAC,MAAM,eAAe,OAAO,CAAC,CAAC;EAC7E,GAAG,qBAAqB,CAAC,KAAK,MAAM,SAAS;GAC3C;GACA,WAAW,aAAa;IACtB,mBAAmB,gBAAgB,SAAS,QAAQ;IAEpD,IAAI,QAAQ,aAAa,MAAM,QAAQ;KACrC,MAAM,2BAAW,IAAI,IAAY;KACjC,KAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,UAAU,KAAK,SAAS,IAAI,MAAM,MAAM,QAAQ,IAAI,GAAG,IAAI,CAAC,CAAC;KACzF,KAAK,MAAM,QAAQ,OACjB,IAAI,CAAC,SAAS,IAAI,KAAK,QAAQ,GAAG;MAChC,MAAM,iBAAiB,GAAG,qBAAqB,KAAK,QAAQ;MAC5D,IAAI,gBACF,gBAAgB,cAAc,CAAC,CAAC,2BAA2B;KAE/D;IAEJ;GACF;EACF,CAAC;CACH,CAAC;AACH"}
1
+ {"version":3,"file":"loadBatchLoader.js","names":[],"sources":["../../src/batchloaders/loadBatchLoader.ts"],"sourcesContent":["import { getInstanceData } from \"../BaseEntity.ts\";\nimport { type EntityManager, getEmInternalApi } from \"../EntityManager.ts\";\nimport { type EntityMetadata } from \"../EntityMetadata.ts\";\nimport { keyToNumber, tagId } from \"../keys.ts\";\nimport { buildHintTree } from \"../loading/HintTree.ts\";\nimport type { LoadHint } from \"../loading/loadHints.ts\";\nimport { lazyExcludedSelects } from \"../queries/entityQueryUtils.ts\";\nimport { type ParsedFindQuery, addTablePerClassJoinsAndClassTag } from \"../queries/find/QueryParser.ts\";\nimport { abbreviation } from \"../utils.ts\";\nimport { type BatchLoader } from \"./BatchLoader.ts\";\n\nexport const loadOperation = \"load\";\n\n/**\n * Batches em.load-style fetches, writing to identity map (via hydrate) instead of returning values.\n * After the batch resolves, callers retrieve their entity from `em.findExistingInstance`.\n *\n * Accepts tuples of `{ taggedId, hint }` so the preloader can inject join-based\n * preloading into the same SELECT that fetches the entities.\n */\nexport function loadBatchLoader(\n em: EntityManager,\n meta: EntityMetadata,\n overwriteExisting: boolean = false,\n): BatchLoader<{ taggedId: string; hint: LoadHint<any> | undefined }> {\n return em.getBatchLoader(loadOperation, `${meta.type}-${overwriteExisting}`, async (loads) => {\n const keys = loads.map((l) => keyToNumber(meta, l.taggedId));\n const alias = abbreviation(meta.tableName);\n const query = {\n selects: meta.hasLazyColumns ? lazyExcludedSelects(meta, alias) : [`\"${alias}\".*`],\n tables: [{ alias, join: \"primary\", table: meta.tableName }],\n condition: {\n kind: \"exp\",\n op: \"and\",\n conditions: [{ kind: \"column\", alias, column: \"id\", dbType: meta.idDbType, cond: { kind: \"in\", value: keys } }],\n },\n orderBys: [{ alias, column: \"id\", order: \"ASC\" }],\n } satisfies ParsedFindQuery;\n addTablePerClassJoinsAndClassTag(query, meta, alias, true);\n // Inject preloading joins into the query if enabled\n const { preloader } = getEmInternalApi(em);\n const preloadHydrator =\n preloader &&\n preloader.addPreloading(meta, buildHintTree(loads.map((l) => ({ entity: l.taggedId, hint: l.hint }))), query);\n const rowData = await em[\"executeFindRowData\"](meta, loadOperation, query, {});\n em[\"hydrateAndFinalize\"](meta.cstr, rowData, {\n overwriteExisting,\n sidecars: (entities) => {\n preloadHydrator && preloadHydrator(rowData, entities);\n // If we're missing any requested rows, mark any requested-but-not-found entities as deleted\n if (rowData.rowCount !== loads.length) {\n const foundIds = new Set<string>();\n for (let i = 0; i < rowData.rowCount; i++) foundIds.add(tagId(meta, rowData.get(i, \"id\")));\n for (const load of loads) {\n if (!foundIds.has(load.taggedId)) {\n const existingEntity = em.findExistingInstance(load.taggedId);\n if (existingEntity) {\n getInstanceData(existingEntity).markDeletedBecauseNotFound();\n }\n }\n }\n }\n },\n });\n });\n}\n"],"mappings":";;;;;;;;;;AAWA,MAAa,gBAAgB;;;;;;;;AAS7B,SAAgB,gBACd,IACA,MACA,oBAA6B,OACuC;CACpE,OAAO,GAAG,eAAe,eAAe,GAAG,KAAK,KAAK,GAAG,qBAAqB,OAAO,UAAU;EAC5F,MAAM,OAAO,MAAM,KAAK,MAAM,YAAY,MAAM,EAAE,QAAQ,CAAC;EAC3D,MAAM,QAAQ,aAAa,KAAK,SAAS;EACzC,MAAM,QAAQ;GACZ,SAAS,KAAK,iBAAiB,oBAAoB,MAAM,KAAK,IAAI,CAAC,IAAI,MAAM,IAAI;GACjF,QAAQ,CAAC;IAAE;IAAO,MAAM;IAAW,OAAO,KAAK;GAAU,CAAC;GAC1D,WAAW;IACT,MAAM;IACN,IAAI;IACJ,YAAY,CAAC;KAAE,MAAM;KAAU;KAAO,QAAQ;KAAM,QAAQ,KAAK;KAAU,MAAM;MAAE,MAAM;MAAM,OAAO;KAAK;IAAE,CAAC;GAChH;GACA,UAAU,CAAC;IAAE;IAAO,QAAQ;IAAM,OAAO;GAAM,CAAC;EAClD;EACA,iCAAiC,OAAO,MAAM,OAAO,IAAI;EAEzD,MAAM,EAAE,cAAc,iBAAiB,EAAE;EACzC,MAAM,kBACJ,aACA,UAAU,cAAc,MAAM,cAAc,MAAM,KAAK,OAAO;GAAE,QAAQ,EAAE;GAAU,MAAM,EAAE;EAAK,EAAE,CAAC,GAAG,KAAK;EAC9G,MAAM,UAAU,MAAM,GAAG,qBAAqB,CAAC,MAAM,eAAe,OAAO,CAAC,CAAC;EAC7E,GAAG,qBAAqB,CAAC,KAAK,MAAM,SAAS;GAC3C;GACA,WAAW,aAAa;IACtB,mBAAmB,gBAAgB,SAAS,QAAQ;IAEpD,IAAI,QAAQ,aAAa,MAAM,QAAQ;KACrC,MAAM,2BAAW,IAAI,IAAY;KACjC,KAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,UAAU,KAAK,SAAS,IAAI,MAAM,MAAM,QAAQ,IAAI,GAAG,IAAI,CAAC,CAAC;KACzF,KAAK,MAAM,QAAQ,OACjB,IAAI,CAAC,SAAS,IAAI,KAAK,QAAQ,GAAG;MAChC,MAAM,iBAAiB,GAAG,qBAAqB,KAAK,QAAQ;MAC5D,IAAI,gBACF,gBAAgB,cAAc,CAAC,CAAC,2BAA2B;KAE/D;IAEJ;GACF;EACF,CAAC;CACH,CAAC;AACH"}
@@ -1,7 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  require("./BatchLoader.cjs");
3
- const require_utils = require("../utils.cjs");
4
3
  const require_keys = require("../keys.cjs");
4
+ const require_utils = require("../utils.cjs");
5
5
  require("../index.cjs");
6
6
  const require_EntityManager = require("../EntityManager.cjs");
7
7
  require("../Entity.cjs");
@@ -1,5 +1,5 @@
1
1
  import { BatchLoader } from "./BatchLoader.cjs";
2
- import { ManyToManyLike } from "../JoinRows.cjs";
2
+ import { ManyToManyLike } from "../flush/JoinRows.cjs";
3
3
  import "../index.cjs";
4
4
  import { EntityManager } from "../EntityManager.cjs";
5
5
  //#region src/batchloaders/manyToManyBatchLoader.d.ts
@@ -1,5 +1,5 @@
1
1
  import { BatchLoader } from "./BatchLoader.mjs";
2
- import { ManyToManyLike } from "../JoinRows.mjs";
2
+ import { ManyToManyLike } from "../flush/JoinRows.mjs";
3
3
  import "../index.mjs";
4
4
  import { EntityManager } from "../EntityManager.mjs";
5
5
  //#region src/batchloaders/manyToManyBatchLoader.d.ts
@@ -1,6 +1,6 @@
1
1
  import "./BatchLoader.js";
2
- import { abbreviation, getOrSet } from "../utils.js";
3
2
  import { keyToNumber } from "../keys.js";
3
+ import { abbreviation, getOrSet } from "../utils.js";
4
4
  import "../index.js";
5
5
  import { getEmInternalApi } from "../EntityManager.js";
6
6
  import "../Entity.js";
@@ -1,9 +1,9 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  require("./BatchLoader.cjs");
3
3
  const require_fields = require("../fields.cjs");
4
+ const require_keys = require("../keys.cjs");
4
5
  const require_queries_find_QueryParser = require("../queries/find/QueryParser.cjs");
5
6
  const require_utils = require("../utils.cjs");
6
- const require_keys = require("../keys.cjs");
7
7
  require("../index.cjs");
8
8
  const require_EntityManager = require("../EntityManager.cjs");
9
9
  require("../Entity.cjs");
@@ -1,8 +1,8 @@
1
1
  import "./BatchLoader.js";
2
2
  import { getField } from "../fields.js";
3
+ import { assertIdsAreTagged, deTagIds, maybeResolveReferenceToId } from "../keys.js";
3
4
  import { addTablePerClassJoinsAndClassTag } from "../queries/find/QueryParser.js";
4
5
  import { abbreviation, groupBy } from "../utils.js";
5
- import { assertIdsAreTagged, deTagIds, maybeResolveReferenceToId } from "../keys.js";
6
6
  import "../index.js";
7
7
  import { getEmInternalApi } from "../EntityManager.js";
8
8
  import "../Entity.js";
@@ -1,10 +1,10 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  require("./BatchLoader.cjs");
3
3
  const require_fields = require("../fields.cjs");
4
+ const require_keys = require("../keys.cjs");
4
5
  const require_queries_find_QueryParser = require("../queries/find/QueryParser.cjs");
5
6
  require("../relations/OneToOneReference.cjs");
6
7
  const require_utils = require("../utils.cjs");
7
- const require_keys = require("../keys.cjs");
8
8
  const require_EntityMetadata = require("../EntityMetadata.cjs");
9
9
  require("../index.cjs");
10
10
  const require_EntityManager = require("../EntityManager.cjs");
@@ -1,9 +1,9 @@
1
1
  import "./BatchLoader.js";
2
2
  import { getField } from "../fields.js";
3
+ import { assertIdsAreTagged, deTagIds, maybeResolveReferenceToId } from "../keys.js";
3
4
  import { addTablePerClassJoinsAndClassTag } from "../queries/find/QueryParser.js";
4
5
  import "../relations/OneToOneReference.js";
5
6
  import { abbreviation, groupBy } from "../utils.js";
6
- import { assertIdsAreTagged, deTagIds, maybeResolveReferenceToId } from "../keys.js";
7
7
  import { getMetadata } from "../EntityMetadata.js";
8
8
  import "../index.js";
9
9
  import { getEmInternalApi } from "../EntityManager.js";