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,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- //#region src/temporal.ts
2
+ //#region src/serde/temporal.ts
3
3
  const runtimeRequire = (0, require("node:module").createRequire)(require("url").pathToFileURL(__filename).href);
4
4
  let temporal;
5
5
  /**
@@ -0,0 +1 @@
1
+ {"version":3,"file":"temporal.cjs","names":["createRequire"],"sources":["../../src/serde/temporal.ts"],"sourcesContent":["/// <reference types=\"temporal-spec/global\" preserve=\"true\" />\n\nimport { createRequire } from \"node:module\";\n\nconst runtimeRequire = createRequire(import.meta.url);\n\n// Native Temporal and both supported polyfills expose this shape; use the shared spec types instead of duplicating it.\ntype TemporalModule = typeof import(\"temporal-spec\");\nlet temporal: TemporalModule | undefined | false;\n\n/**\n * Lazily exposes Joist's native-first / polyfill-fallback Temporal detection.\n *\n * This is useful while the joist-orm repo itself has both pre-Node 26, and post-Node 26\n * test coverage, b/c our CI test suite needs the same a) codegen output and b) test suites\n * to \"just work\" with either Node 24/25 or Node 26, which means they can't have an explicit\n * import to either `temporal-polyfill` or the `Temporal` global.\n *\n * This is exactly what Joist's internal temporal resolution was already working around, so\n * this just exposes an `import { Temporal } from joist-orm` that lets the codegen & tests\n * reuse the same abstraction.\n */\nexport const Temporal = new Proxy(\n {},\n {\n get(_target, property, receiver) {\n return Reflect.get(requireTemporal().Temporal, property, receiver);\n },\n },\n) as typeof globalThis.Temporal;\n\n/**\n * A type-only `Temporal` namespace that merges with the `const Temporal` above.\n *\n * The `const` is only a value, so using `Temporal.PlainDate` / `Temporal.ZonedDateTime` as a\n * type needs a namespace to resolve against. Node 26 has that as a global, but older Node\n * versions don't, so `temporal-spec/global` supplies the same global namespace as a fallback.\n */\nexport declare namespace Temporal {\n export type Instant = globalThis.Temporal.Instant;\n export type ZonedDateTime = globalThis.Temporal.ZonedDateTime;\n export type PlainDate = globalThis.Temporal.PlainDate;\n export type PlainTime = globalThis.Temporal.PlainTime;\n export type PlainDateTime = globalThis.Temporal.PlainDateTime;\n export type PlainYearMonth = globalThis.Temporal.PlainYearMonth;\n export type PlainMonthDay = globalThis.Temporal.PlainMonthDay;\n export type Duration = globalThis.Temporal.Duration;\n}\n\n/**\n * Conditionally/dynamically requires `temporal-polyfill`.\n *\n * We want to avoid directly importing/requiring `temporal-polyfill` because\n * it will introduce the dependency to all users of Joist.\n */\nexport function maybeRequireTemporal(): TemporalModule | undefined {\n // if we've already failed to find a temporal implementation before, early exit\n if (temporal === false) return undefined;\n // if we already required temporal, just return that\n if (temporal) return temporal;\n // use built in temporal if present\n if (\"Temporal\" in global && \"Intl\" in global) {\n temporal = {\n Temporal: global.Temporal as typeof globalThis.Temporal,\n toTemporalInstant: Date.prototype.toTemporalInstant,\n Intl: global.Intl,\n };\n return temporal;\n }\n // preferentially try to use temporal-polyfill\n try {\n temporal = runtimeRequire(\"temporal-polyfill\");\n return temporal as TemporalModule;\n } catch (e) {}\n // last resort, try to use @js-temporal/polyfill\n try {\n temporal = runtimeRequire(\"@js-temporal/polyfill\");\n return temporal as TemporalModule;\n } catch (e) {}\n // don't try to load temporal again\n temporal = false;\n return undefined;\n}\n\nexport function requireTemporal(): TemporalModule {\n const temporal = maybeRequireTemporal();\n if (!temporal) throw new Error(\"Unable to find a Temporal implementation\");\n return temporal;\n}\n"],"mappings":";;AAIA,MAAM,kBAAA,wBAAiBA,CAAAA,CAAAA,cAAAA,CAAAA,QAAAA,KAAAA,CAAAA,CAAAA,cAAAA,UAAAA,CAAAA,CAAAA,IAA6B;AAIpD,IAAI;;;;;;;;;;;;;AAcJ,MAAa,WAAW,IAAI,MAC1B,CAAC,GACD,EACE,IAAI,SAAS,UAAU,UAAU;CAC/B,OAAO,QAAQ,IAAI,gBAAgB,CAAC,CAAC,UAAU,UAAU,QAAQ;AACnE,EACF,CACF;;;;;;;AA0BA,SAAgB,uBAAmD;CAEjE,IAAI,aAAa,OAAO,OAAO,KAAA;CAE/B,IAAI,UAAU,OAAO;CAErB,IAAI,cAAc,UAAU,UAAU,QAAQ;EAC5C,WAAW;GACT,UAAU,OAAO;GACjB,mBAAmB,KAAK,UAAU;GAClC,MAAM,OAAO;EACf;EACA,OAAO;CACT;CAEA,IAAI;EACF,WAAW,eAAe,mBAAmB;EAC7C,OAAO;CACT,SAAS,GAAG,CAAC;CAEb,IAAI;EACF,WAAW,eAAe,uBAAuB;EACjD,OAAO;CACT,SAAS,GAAG,CAAC;CAEb,WAAW;AAEb;AAEA,SAAgB,kBAAkC;CAChD,MAAM,WAAW,qBAAqB;CACtC,IAAI,CAAC,UAAU,MAAM,IAAI,MAAM,0CAA0C;CACzE,OAAO;AACT"}
@@ -1,5 +1,5 @@
1
1
  /// <reference types="temporal-spec/global" preserve="true" />
2
- //#region src/temporal.d.ts
2
+ //#region src/serde/temporal.d.ts
3
3
  type TemporalModule = typeof import("temporal-spec");
4
4
  /**
5
5
  * Lazily exposes Joist's native-first / polyfill-fallback Temporal detection.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"temporal.d.cts","names":[],"sources":["../../src/serde/temporal.ts"],"mappings":";;KAOK;;;;;;;;;;;;;cAeQ,iBAOD,WAAW;;;;;;;;kBASE;OACX,UAAU,WAAW,SAAS;OAC9B,gBAAgB,WAAW,SAAS;OACpC,YAAY,WAAW,SAAS;OAChC,YAAY,WAAW,SAAS;OAChC,gBAAgB,WAAW,SAAS;OACpC,iBAAiB,WAAW,SAAS;OACrC,gBAAgB,WAAW,SAAS;OACpC,WAAW,WAAW,SAAS;;;;;;;;iBAS7B,wBAAwB;iBA6BxB,mBAAmB"}
@@ -1,5 +1,5 @@
1
1
  /// <reference types="temporal-spec/global" preserve="true" />
2
- //#region src/temporal.d.ts
2
+ //#region src/serde/temporal.d.ts
3
3
  type TemporalModule = typeof import("temporal-spec");
4
4
  /**
5
5
  * Lazily exposes Joist's native-first / polyfill-fallback Temporal detection.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"temporal.d.mts","names":[],"sources":["../../src/serde/temporal.ts"],"mappings":";;KAOK;;;;;;;;;;;;;cAeQ,iBAOD,WAAW;;;;;;;;kBASE;OACX,UAAU,WAAW,SAAS;OAC9B,gBAAgB,WAAW,SAAS;OACpC,YAAY,WAAW,SAAS;OAChC,YAAY,WAAW,SAAS;OAChC,gBAAgB,WAAW,SAAS;OACpC,iBAAiB,WAAW,SAAS;OACrC,gBAAgB,WAAW,SAAS;OACpC,WAAW,WAAW,SAAS;;;;;;;;iBAS7B,wBAAwB;iBA6BxB,mBAAmB"}
@@ -1,5 +1,5 @@
1
1
  import { createRequire } from "node:module";
2
- //#region src/temporal.ts
2
+ //#region src/serde/temporal.ts
3
3
  const runtimeRequire = createRequire(import.meta.url);
4
4
  let temporal;
5
5
  /**
@@ -0,0 +1 @@
1
+ {"version":3,"file":"temporal.js","names":[],"sources":["../../src/serde/temporal.ts"],"sourcesContent":["/// <reference types=\"temporal-spec/global\" preserve=\"true\" />\n\nimport { createRequire } from \"node:module\";\n\nconst runtimeRequire = createRequire(import.meta.url);\n\n// Native Temporal and both supported polyfills expose this shape; use the shared spec types instead of duplicating it.\ntype TemporalModule = typeof import(\"temporal-spec\");\nlet temporal: TemporalModule | undefined | false;\n\n/**\n * Lazily exposes Joist's native-first / polyfill-fallback Temporal detection.\n *\n * This is useful while the joist-orm repo itself has both pre-Node 26, and post-Node 26\n * test coverage, b/c our CI test suite needs the same a) codegen output and b) test suites\n * to \"just work\" with either Node 24/25 or Node 26, which means they can't have an explicit\n * import to either `temporal-polyfill` or the `Temporal` global.\n *\n * This is exactly what Joist's internal temporal resolution was already working around, so\n * this just exposes an `import { Temporal } from joist-orm` that lets the codegen & tests\n * reuse the same abstraction.\n */\nexport const Temporal = new Proxy(\n {},\n {\n get(_target, property, receiver) {\n return Reflect.get(requireTemporal().Temporal, property, receiver);\n },\n },\n) as typeof globalThis.Temporal;\n\n/**\n * A type-only `Temporal` namespace that merges with the `const Temporal` above.\n *\n * The `const` is only a value, so using `Temporal.PlainDate` / `Temporal.ZonedDateTime` as a\n * type needs a namespace to resolve against. Node 26 has that as a global, but older Node\n * versions don't, so `temporal-spec/global` supplies the same global namespace as a fallback.\n */\nexport declare namespace Temporal {\n export type Instant = globalThis.Temporal.Instant;\n export type ZonedDateTime = globalThis.Temporal.ZonedDateTime;\n export type PlainDate = globalThis.Temporal.PlainDate;\n export type PlainTime = globalThis.Temporal.PlainTime;\n export type PlainDateTime = globalThis.Temporal.PlainDateTime;\n export type PlainYearMonth = globalThis.Temporal.PlainYearMonth;\n export type PlainMonthDay = globalThis.Temporal.PlainMonthDay;\n export type Duration = globalThis.Temporal.Duration;\n}\n\n/**\n * Conditionally/dynamically requires `temporal-polyfill`.\n *\n * We want to avoid directly importing/requiring `temporal-polyfill` because\n * it will introduce the dependency to all users of Joist.\n */\nexport function maybeRequireTemporal(): TemporalModule | undefined {\n // if we've already failed to find a temporal implementation before, early exit\n if (temporal === false) return undefined;\n // if we already required temporal, just return that\n if (temporal) return temporal;\n // use built in temporal if present\n if (\"Temporal\" in global && \"Intl\" in global) {\n temporal = {\n Temporal: global.Temporal as typeof globalThis.Temporal,\n toTemporalInstant: Date.prototype.toTemporalInstant,\n Intl: global.Intl,\n };\n return temporal;\n }\n // preferentially try to use temporal-polyfill\n try {\n temporal = runtimeRequire(\"temporal-polyfill\");\n return temporal as TemporalModule;\n } catch (e) {}\n // last resort, try to use @js-temporal/polyfill\n try {\n temporal = runtimeRequire(\"@js-temporal/polyfill\");\n return temporal as TemporalModule;\n } catch (e) {}\n // don't try to load temporal again\n temporal = false;\n return undefined;\n}\n\nexport function requireTemporal(): TemporalModule {\n const temporal = maybeRequireTemporal();\n if (!temporal) throw new Error(\"Unable to find a Temporal implementation\");\n return temporal;\n}\n"],"mappings":";;AAIA,MAAM,iBAAiB,cAAc,YAAY,GAAG;AAIpD,IAAI;;;;;;;;;;;;;AAcJ,MAAa,WAAW,IAAI,MAC1B,CAAC,GACD,EACE,IAAI,SAAS,UAAU,UAAU;CAC/B,OAAO,QAAQ,IAAI,gBAAgB,CAAC,CAAC,UAAU,UAAU,QAAQ;AACnE,EACF,CACF;;;;;;;AA0BA,SAAgB,uBAAmD;CAEjE,IAAI,aAAa,OAAO,OAAO,KAAA;CAE/B,IAAI,UAAU,OAAO;CAErB,IAAI,cAAc,UAAU,UAAU,QAAQ;EAC5C,WAAW;GACT,UAAU,OAAO;GACjB,mBAAmB,KAAK,UAAU;GAClC,MAAM,OAAO;EACf;EACA,OAAO;CACT;CAEA,IAAI;EACF,WAAW,eAAe,mBAAmB;EAC7C,OAAO;CACT,SAAS,GAAG,CAAC;CAEb,IAAI;EACF,WAAW,eAAe,uBAAuB;EACjD,OAAO;CACT,SAAS,GAAG,CAAC;CAEb,WAAW;AAEb;AAEA,SAAgB,kBAAkC;CAChD,MAAM,WAAW,qBAAqB;CACtC,IAAI,CAAC,UAAU,MAAM,IAAI,MAAM,0CAA0C;CACzE,OAAO;AACT"}
@@ -1,9 +1,8 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_temporal = require("./temporal.cjs");
3
- const require_utils = require("./utils.cjs");
4
- require("./serde.cjs");
5
- //#region src/temporalMappers.ts
6
- const { Temporal: t } = require_temporal.maybeRequireTemporal() ?? {};
2
+ const require_serde_temporal = require("./temporal.cjs");
3
+ const require_utils = require("../utils.cjs");
4
+ //#region src/serde/temporalMappers.ts
5
+ const { Temporal: t } = require_serde_temporal.maybeRequireTemporal() ?? {};
7
6
  const temporalNotAvailable = {
8
7
  fromDb: () => require_utils.fail("Temporal not available"),
9
8
  toDb: () => require_utils.fail("Temporal not available")
@@ -0,0 +1 @@
1
+ {"version":3,"file":"temporalMappers.cjs","names":["maybeRequireTemporal","fail"],"sources":["../../src/serde/temporalMappers.ts"],"sourcesContent":["import { fail } from \"../utils.ts\";\nimport type { CustomSerde } from \"./serde.ts\";\nimport { type Temporal, maybeRequireTemporal } from \"./temporal.ts\";\n\nconst { Temporal: t } = maybeRequireTemporal() ?? {};\nconst temporalNotAvailable = {\n fromDb: () => fail(\"Temporal not available\"),\n toDb: () => fail(\"Temporal not available\"),\n};\n\n/**\n * Converts Postgres `DATE` to/from Temporal.PlainDate.\n *\n * `fromDb` accepts either pg's text form (classic/knex text queries, json_agg preloads) or an\n * already-constructed `PlainDate` (lazy binary queries decode wire bytes -> Temporal directly).\n */\nexport const plainDateMapper: CustomSerde<Temporal.PlainDate, string> = t\n ? {\n fromDb: (value: string | Temporal.PlainDate) => (value instanceof t.PlainDate ? value : t.PlainDate.from(value)),\n toDb: (p) => p.toString(),\n }\n : temporalNotAvailable;\n\n/** Converts Postgres `TIME` to/from Temporal.PlainTime; `fromDb` also passes binary-decoded instances through. */\nexport const plainTimeMapper: CustomSerde<Temporal.PlainTime, string> = t\n ? {\n fromDb: (value: string | Temporal.PlainTime) => (value instanceof t.PlainTime ? value : t.PlainTime.from(value)),\n toDb: (pt) => pt.toString(),\n }\n : temporalNotAvailable;\n\n/**\n * Converts Postgres `TIMESTAMP` / `TIMESTAMP WITHOUT TIME ZONE` to/from Temporal.PlainDateTime;\n * `fromDb` also passes binary-decoded instances through.\n */\nexport const plainDateTimeMapper: CustomSerde<Temporal.PlainDateTime, string> = t\n ? {\n // Text values look like `2018-01-01 10:00:00`\n fromDb: (value: string | Temporal.PlainDateTime) =>\n value instanceof t.PlainDateTime ? value : t.PlainDateTime.from(value),\n toDb: (p) => p.toString(),\n }\n : temporalNotAvailable;\n\n/**\n * Converts Postgres `TIMESTAMPTZ`, `TIMESTAMPTZ WITH TIME ZONE` to/from Temporal.ZonedDateTime.\n *\n * Specifically, Postgres uses ISO 8601, which Temporal supports as well, except that PG ouputs a space instead of `T`\n * between the date/time for output.\n *\n * Additionally, `Temporal.ZonedDateTime.from` expects a time zone literal name to be supplied as part of the string,\n * but this is not stored by postgres.\n *\n * As such, we parse the offset and append it to string passed to `from` as the time zone. This means that if we did a\n * round trip of generating a db value then parsing it, then it may not strictly equal the original zdt.\n *\n * Finally, PG stores dates as UTC and converts them to its local time zone for output, so we could get any offset\n * theoretically. If, somehow, we don't get an offset, then we assume UTC.\n */\nexport const zonedDateTimeMapper: CustomSerde<Temporal.ZonedDateTime, string> = t\n ? {\n // Produce a ZDT from a PG output like \"2021-01-01 12:00:00-05:00\"; binary-decoded\n // instances (lazy queries construct ZonedDateTimes directly) pass through\n fromDb: (value: string | Temporal.ZonedDateTime) => {\n if (typeof value !== \"string\") return value;\n const [offset] = value.match(/([+-]\\d{2}(?::?\\d{2})?)$/) ?? [];\n return t.ZonedDateTime.from(`${value}[${!offset || /^\\+00(:?00)?$/.test(offset) ? \"UTC\" : offset}]`);\n },\n // Match a PG `TIMESTAMPTZ` input format, i.e. \"2021-01-01T12:00:00-05:00\"\n toDb: (zdt) => zdt.toString({ timeZoneName: \"never\" }),\n }\n : temporalNotAvailable;\n"],"mappings":";;;;AAIA,MAAM,EAAE,UAAU,MAAMA,uBAAAA,qBAAqB,KAAK,CAAC;AACnD,MAAM,uBAAuB;CAC3B,cAAcC,cAAAA,KAAK,wBAAwB;CAC3C,YAAYA,cAAAA,KAAK,wBAAwB;AAC3C;;;;;;;AAQA,MAAa,kBAA2D,IACpE;CACE,SAAS,UAAwC,iBAAiB,EAAE,YAAY,QAAQ,EAAE,UAAU,KAAK,KAAK;CAC9G,OAAO,MAAM,EAAE,SAAS;AAC1B,IACA;;AAGJ,MAAa,kBAA2D,IACpE;CACE,SAAS,UAAwC,iBAAiB,EAAE,YAAY,QAAQ,EAAE,UAAU,KAAK,KAAK;CAC9G,OAAO,OAAO,GAAG,SAAS;AAC5B,IACA;;;;;AAMJ,MAAa,sBAAmE,IAC5E;CAEE,SAAS,UACP,iBAAiB,EAAE,gBAAgB,QAAQ,EAAE,cAAc,KAAK,KAAK;CACvE,OAAO,MAAM,EAAE,SAAS;AAC1B,IACA;;;;;;;;;;;;;;;;AAiBJ,MAAa,sBAAmE,IAC5E;CAGE,SAAS,UAA2C;EAClD,IAAI,OAAO,UAAU,UAAU,OAAO;EACtC,MAAM,CAAC,UAAU,MAAM,MAAM,0BAA0B,KAAK,CAAC;EAC7D,OAAO,EAAE,cAAc,KAAK,GAAG,MAAM,GAAG,CAAC,UAAU,gBAAgB,KAAK,MAAM,IAAI,QAAQ,OAAO,EAAE;CACrG;CAEA,OAAO,QAAQ,IAAI,SAAS,EAAE,cAAc,QAAQ,CAAC;AACvD,IACA"}
@@ -1,6 +1,6 @@
1
1
  import { Temporal } from "./temporal.cjs";
2
2
  import { CustomSerde } from "./serde.cjs";
3
- //#region src/temporalMappers.d.ts
3
+ //#region src/serde/temporalMappers.d.ts
4
4
  /**
5
5
  * Converts Postgres `DATE` to/from Temporal.PlainDate.
6
6
  *
@@ -0,0 +1 @@
1
+ {"version":3,"file":"temporalMappers.d.cts","names":[],"sources":["../../src/serde/temporalMappers.ts"],"mappings":";;;;;;;;;cAgBa,iBAAiB,YAAY,SAAS;;cAQtC,iBAAiB,YAAY,SAAS;;;;;cAWtC,qBAAqB,YAAY,SAAS;;;;;;;;;;;;;;;;cAwB1C,qBAAqB,YAAY,SAAS"}
@@ -1,6 +1,6 @@
1
1
  import { Temporal } from "./temporal.mjs";
2
2
  import { CustomSerde } from "./serde.mjs";
3
- //#region src/temporalMappers.d.ts
3
+ //#region src/serde/temporalMappers.d.ts
4
4
  /**
5
5
  * Converts Postgres `DATE` to/from Temporal.PlainDate.
6
6
  *
@@ -0,0 +1 @@
1
+ {"version":3,"file":"temporalMappers.d.mts","names":[],"sources":["../../src/serde/temporalMappers.ts"],"mappings":";;;;;;;;;cAgBa,iBAAiB,YAAY,SAAS;;cAQtC,iBAAiB,YAAY,SAAS;;;;;cAWtC,qBAAqB,YAAY,SAAS;;;;;;;;;;;;;;;;cAwB1C,qBAAqB,YAAY,SAAS"}
@@ -1,7 +1,6 @@
1
1
  import { maybeRequireTemporal } from "./temporal.js";
2
- import { fail } from "./utils.js";
3
- import "./serde.js";
4
- //#region src/temporalMappers.ts
2
+ import { fail } from "../utils.js";
3
+ //#region src/serde/temporalMappers.ts
5
4
  const { Temporal: t } = maybeRequireTemporal() ?? {};
6
5
  const temporalNotAvailable = {
7
6
  fromDb: () => fail("Temporal not available"),
@@ -0,0 +1 @@
1
+ {"version":3,"file":"temporalMappers.js","names":[],"sources":["../../src/serde/temporalMappers.ts"],"sourcesContent":["import { fail } from \"../utils.ts\";\nimport type { CustomSerde } from \"./serde.ts\";\nimport { type Temporal, maybeRequireTemporal } from \"./temporal.ts\";\n\nconst { Temporal: t } = maybeRequireTemporal() ?? {};\nconst temporalNotAvailable = {\n fromDb: () => fail(\"Temporal not available\"),\n toDb: () => fail(\"Temporal not available\"),\n};\n\n/**\n * Converts Postgres `DATE` to/from Temporal.PlainDate.\n *\n * `fromDb` accepts either pg's text form (classic/knex text queries, json_agg preloads) or an\n * already-constructed `PlainDate` (lazy binary queries decode wire bytes -> Temporal directly).\n */\nexport const plainDateMapper: CustomSerde<Temporal.PlainDate, string> = t\n ? {\n fromDb: (value: string | Temporal.PlainDate) => (value instanceof t.PlainDate ? value : t.PlainDate.from(value)),\n toDb: (p) => p.toString(),\n }\n : temporalNotAvailable;\n\n/** Converts Postgres `TIME` to/from Temporal.PlainTime; `fromDb` also passes binary-decoded instances through. */\nexport const plainTimeMapper: CustomSerde<Temporal.PlainTime, string> = t\n ? {\n fromDb: (value: string | Temporal.PlainTime) => (value instanceof t.PlainTime ? value : t.PlainTime.from(value)),\n toDb: (pt) => pt.toString(),\n }\n : temporalNotAvailable;\n\n/**\n * Converts Postgres `TIMESTAMP` / `TIMESTAMP WITHOUT TIME ZONE` to/from Temporal.PlainDateTime;\n * `fromDb` also passes binary-decoded instances through.\n */\nexport const plainDateTimeMapper: CustomSerde<Temporal.PlainDateTime, string> = t\n ? {\n // Text values look like `2018-01-01 10:00:00`\n fromDb: (value: string | Temporal.PlainDateTime) =>\n value instanceof t.PlainDateTime ? value : t.PlainDateTime.from(value),\n toDb: (p) => p.toString(),\n }\n : temporalNotAvailable;\n\n/**\n * Converts Postgres `TIMESTAMPTZ`, `TIMESTAMPTZ WITH TIME ZONE` to/from Temporal.ZonedDateTime.\n *\n * Specifically, Postgres uses ISO 8601, which Temporal supports as well, except that PG ouputs a space instead of `T`\n * between the date/time for output.\n *\n * Additionally, `Temporal.ZonedDateTime.from` expects a time zone literal name to be supplied as part of the string,\n * but this is not stored by postgres.\n *\n * As such, we parse the offset and append it to string passed to `from` as the time zone. This means that if we did a\n * round trip of generating a db value then parsing it, then it may not strictly equal the original zdt.\n *\n * Finally, PG stores dates as UTC and converts them to its local time zone for output, so we could get any offset\n * theoretically. If, somehow, we don't get an offset, then we assume UTC.\n */\nexport const zonedDateTimeMapper: CustomSerde<Temporal.ZonedDateTime, string> = t\n ? {\n // Produce a ZDT from a PG output like \"2021-01-01 12:00:00-05:00\"; binary-decoded\n // instances (lazy queries construct ZonedDateTimes directly) pass through\n fromDb: (value: string | Temporal.ZonedDateTime) => {\n if (typeof value !== \"string\") return value;\n const [offset] = value.match(/([+-]\\d{2}(?::?\\d{2})?)$/) ?? [];\n return t.ZonedDateTime.from(`${value}[${!offset || /^\\+00(:?00)?$/.test(offset) ? \"UTC\" : offset}]`);\n },\n // Match a PG `TIMESTAMPTZ` input format, i.e. \"2021-01-01T12:00:00-05:00\"\n toDb: (zdt) => zdt.toString({ timeZoneName: \"never\" }),\n }\n : temporalNotAvailable;\n"],"mappings":";;;AAIA,MAAM,EAAE,UAAU,MAAM,qBAAqB,KAAK,CAAC;AACnD,MAAM,uBAAuB;CAC3B,cAAc,KAAK,wBAAwB;CAC3C,YAAY,KAAK,wBAAwB;AAC3C;;;;;;;AAQA,MAAa,kBAA2D,IACpE;CACE,SAAS,UAAwC,iBAAiB,EAAE,YAAY,QAAQ,EAAE,UAAU,KAAK,KAAK;CAC9G,OAAO,MAAM,EAAE,SAAS;AAC1B,IACA;;AAGJ,MAAa,kBAA2D,IACpE;CACE,SAAS,UAAwC,iBAAiB,EAAE,YAAY,QAAQ,EAAE,UAAU,KAAK,KAAK;CAC9G,OAAO,OAAO,GAAG,SAAS;AAC5B,IACA;;;;;AAMJ,MAAa,sBAAmE,IAC5E;CAEE,SAAS,UACP,iBAAiB,EAAE,gBAAgB,QAAQ,EAAE,cAAc,KAAK,KAAK;CACvE,OAAO,MAAM,EAAE,SAAS;AAC1B,IACA;;;;;;;;;;;;;;;;AAiBJ,MAAa,sBAAmE,IAC5E;CAGE,SAAS,UAA2C;EAClD,IAAI,OAAO,UAAU,UAAU,OAAO;EACtC,MAAM,CAAC,UAAU,MAAM,MAAM,0BAA0B,KAAK,CAAC;EAC7D,OAAO,EAAE,cAAc,KAAK,GAAG,MAAM,GAAG,CAAC,UAAU,gBAAgB,KAAK,MAAM,IAAI,QAAQ,OAAO,EAAE;CACrG;CAEA,OAAO,QAAQ,IAAI,SAAS,EAAE,cAAc,QAAQ,CAAC;AACvD,IACA"}
package/build/upsert.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- require("./typeMap.cjs");
3
2
  const require_utils = require("./utils.cjs");
4
3
  const require_getProperties = require("./getProperties.cjs");
4
+ require("./typeMap.cjs");
5
5
  const require_configure = require("./configure.cjs");
6
6
  const require_EntityMetadata = require("./EntityMetadata.cjs");
7
7
  const require_defaults = require("./defaults.cjs");
package/build/upsert.js CHANGED
@@ -1,6 +1,6 @@
1
- import "./typeMap.js";
2
1
  import { toArray } from "./utils.js";
3
2
  import { getProperties } from "./getProperties.js";
3
+ import "./typeMap.js";
4
4
  import { getConstructorFromTaggedId } from "./configure.js";
5
5
  import { getMetadata } from "./EntityMetadata.js";
6
6
  import { setSyncDefaults } from "./defaults.js";
package/build/utils.cjs CHANGED
@@ -1,6 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_relations_Reference = require("./relations/Reference.cjs");
3
- require("./loadHints.cjs");
4
3
  const require_relations_ReactiveField = require("./relations/ReactiveField.cjs");
5
4
  require("./relations/index.cjs");
6
5
  const require_EntityManager = require("./EntityManager.cjs");
@@ -1 +1 @@
1
- {"version":3,"file":"utils.cjs","names":["isReactiveField","isReference","isDefined"],"sources":["../src/utils.ts"],"sourcesContent":["import { type Entity } from \"./Entity.ts\";\nimport { isDefined } from \"./EntityManager.ts\";\nimport { type New } from \"./loadHints.ts\";\nimport type { OrderBy } from \"./queries/find/EntityFilter.ts\";\nimport { isReactiveField, isReference } from \"./relations/index.ts\";\n\nexport type MaybePromise<T> = T | Promise<T>;\n\n/**\n * Given a `MaybePromise` of T, invoke `callback` against `T` either immediately or via `then`.\n *\n * This is the same as:\n *\n * ```\n * const r = await maybePromise;\n * return callback(r;;\n * ```\n *\n * But saves an `await` if `maybePromise` is not actually a promise.\n */\nexport function maybePromiseThen<T, U>(promiseOrObj: MaybePromise<T>, callback: (obj: T) => U): MaybePromise<U> {\n return promiseOrObj instanceof Promise ? promiseOrObj.then(callback) : callback(promiseOrObj);\n}\n\nexport function failIfAnyRejected<T>(results: PromiseSettledResult<T>[]): T[] {\n const rejects = results.filter((r) => r.status === \"rejected\");\n // For now just throw the 1st rejection; this should be pretty rare\n if (rejects.length > 0 && rejects[0].status === \"rejected\") {\n throw rejects[0].reason;\n }\n return results.map((r) => (r as PromiseFulfilledResult<T>).value);\n}\n\nexport function getOrSet<T extends Record<keyof unknown, unknown>>(\n record: T,\n key: keyof T,\n defaultValue: T[keyof T] | (() => T[keyof T]),\n): T[keyof T] {\n if (record[key] === undefined) {\n record[key] = defaultValue instanceof Function ? defaultValue() : defaultValue;\n }\n return record[key];\n}\n\n/** Defines a getter that replaces itself with its computed value on first access. */\nexport function defineLazyGetter<T extends object, K extends keyof T>(obj: T, key: K, build: () => T[K]): void {\n Object.defineProperty(obj, key, {\n configurable: true,\n get: function getLazyProperty() {\n const value = build();\n Object.defineProperty(obj, key, { configurable: true, value });\n return value;\n },\n });\n}\n\n/**\n * A utility to ensure a Promise-returning method actually returns a promise and doesn't\n * early exit. Using `async function` guarantees these semantics, but sometimes we avoid\n * `async` as a likely-premature optimization to avoid the overhead.\n */\nexport function tryResolve<T>(fn: () => T): Promise<T> {\n try {\n return Promise.resolve(fn());\n } catch (e) {\n return Promise.reject(e);\n }\n}\n\n/** Returns whether `obj` has at least one key, without allocating a keys array. */\nexport function hasAnyKey(obj: Record<any, any> | undefined): boolean {\n for (const _ in obj) return true;\n return false;\n}\n\nexport function fail(message?: string): never {\n throw new Error(message || \"Failed\");\n}\n\nexport function remove<T>(array: T[], t: T): void {\n const index = array.indexOf(t);\n if (index > -1) {\n array.splice(index, 1);\n }\n}\n\nexport function maybeRemove<T>(array: T[] | undefined, t: T): void {\n if (array) remove(array, t);\n}\n\nexport function maybeAdd<T>(array: T[], t: T): void {\n if (!array.includes(t)) {\n array.push(t);\n }\n}\n\nexport function clear<T>(array: T[]): void {\n array.splice(0, array.length);\n}\n\n/** Returns 0 inclusive to n exclusive. */\nexport function zeroTo(n: number): number[] {\n return [...Array(n).keys()];\n}\n\nexport function groupBy<T, Y = T, K = string>(list: readonly T[], fn: (x: T) => K, valueFn?: (x: T) => Y): Map<K, Y[]> {\n const result = new Map<K, Y[]>();\n list.forEach((o) => {\n const group = fn(o);\n if (!result.has(group)) {\n result.set(group, []);\n }\n result.get(group)!.push(valueFn === undefined ? (o as any as Y) : valueFn(o));\n });\n return result;\n}\n\nexport function indexBy<T, Y = T, K = string>(list: T[], fn: (x: T) => K, valueFn?: (x: T) => Y): Map<K, Y> {\n const result = new Map<K, Y>();\n list.forEach((o) => {\n const group = fn(o);\n result.set(group, valueFn === undefined ? (o as any as Y) : valueFn(o));\n });\n return result;\n}\n\nexport function batched<T>(list: Array<T>, n: number): T[][] {\n const result = [] as T[][];\n for (let i = 0; i < list.length; i += n) {\n result.push(list.slice(i, i + n));\n }\n return result;\n}\n\nexport function partition<T>(array: ReadonlyArray<T>, f: (el: T) => boolean): [T[], T[]] {\n const trueElements: T[] = [];\n const falseElements: T[] = [];\n array.forEach((el) => {\n if (f(el)) {\n trueElements.push(el);\n } else {\n falseElements.push(el);\n }\n });\n return [trueElements, falseElements];\n}\n\n// Utility function to wrap an object or value in an array, unless it's already an array\nexport function toArray<T>(maybeArray: T | T[] | undefined | null): T[] {\n return Array.isArray(maybeArray) ? maybeArray : maybeArray === undefined || maybeArray === null ? [] : [maybeArray];\n}\n\n// Utility type to strip off null and defined and infer only T.\nexport type NullOrDefinedOr<T> = T | null | undefined;\n\nexport function assertNever(x: never): never {\n throw new Error(\"Unexpected object: \" + x);\n}\n\nexport function abbreviation(tableName: string): string {\n return tableName\n .split(\"_\")\n .map((w) => w[0])\n .join(\"\");\n}\n\n/**\n * Utility method for casting `entity` to a `New` entity.\n *\n * Note that we don't actually do any runtime checks; a very simple one would be if the id is undefined,\n * but we want this method to be used in tests that are post-`flush` but still \"know\" the entity is\n * effectively new / fully loaded.\n *\n * Granted, we could do a runtime check that all relations are loaded.\n */\nexport function asNew<T extends Entity>(entity: T): New<T> {\n return entity as New<T>;\n}\n\nexport function compareValues(av: any, bv: any, direction: OrderBy): number {\n const d = direction === \"ASC\" ? 1 : -1;\n if (isReactiveField(av)) {\n av = !av.isSet ? -1 : av.get;\n }\n if (isReactiveField(bv)) {\n bv = !bv.isSet ? -1 : bv.get;\n }\n if (isReference(av) && isReference(bv)) {\n const aIsNew = av.isLoaded && (av as any).get?.isNewEntity;\n const bIsNew = bv.isLoaded && (bv as any).get?.isNewEntity;\n const bothSame = (aIsNew && bIsNew) || (!aIsNew && !bIsNew);\n if (!bothSame) {\n if (aIsNew) return 1 * d; // New entities are always \"greater than\" loaded entities\n if (bIsNew) return -1 * d; // Loaded entities are always \"less than\" new entities\n }\n av = av.idTaggedMaybe ?? (av.isLoaded && (av as any).get?.toString()) ?? undefined;\n bv = bv.idTaggedMaybe ?? (bv.isLoaded && (bv as any).get?.toString()) ?? undefined;\n }\n if (!isDefined(av) || !isDefined(bv)) {\n return !av && !bv ? 0 : (!av ? 1 : -1) * d;\n } else if (typeof av === \"number\" && typeof bv === \"number\") {\n return (av - bv) * d;\n } else if (typeof av === \"string\" && typeof bv === \"string\") {\n return av.localeCompare(bv) * d;\n } else if (av instanceof Date && bv instanceof Date) {\n return ((av as Date).getTime() - (bv as Date).getTime()) * d;\n } else {\n throw new Error(`Unsupported sortBy values ${av}, ${bv}`);\n }\n}\n\n/** A ~naive deep merge that requires already-normalized hints and will mutate `source`. */\n// https://gist.github.com/ahtcx/0cd94e62691f539160b32ecda18af3d6\nexport function mergeNormalizedHints(target: any, source: any): void {\n for (const key of Object.keys(source)) {\n // We assume both target & source are already normalized, i.e. we won't have\n // source=\"books\" and target={books: \"title\"}. They will both be {books: ...}.\n if (target[key]) {\n mergeNormalizedHints(source[key], target[key]);\n }\n }\n Object.assign(target, source);\n}\n\nconst newLine = /\\n/g;\nconst doubleSpace = / +/g;\n\nexport function cleanStringValue(value: unknown): string | undefined {\n // If this is not a string, coerce it -- or maybe fail?\n let s = typeof value !== \"string\" && value !== undefined && value !== null ? String(value) : value;\n // We always trim to remove leading/trailing spaces\n s = typeof s === \"string\" ? s.trim() : s;\n // And if it's empty string, we swap to undefined (null in the db)\n return s === \"\" || s === null ? undefined : s;\n}\n\n/** Strips new lines/indentation from our `UPDATE` string; doesn't do any actual SQL param escaping/etc. */\nexport function cleanSql(sql: string): string {\n return sql.trim().replace(newLine, \"\").replace(doubleSpace, \" \");\n}\n\n// Collections return an array, so do a hot-path `.flat()`\nexport function flatAndUnique<T extends unknown>(list: (T | T[] | undefined)[]): Set<T> {\n const result = new Set<T>();\n for (const c of list) {\n if (Array.isArray(c)) {\n for (const e of c) result.add(e);\n } else if (c) {\n result.add(c);\n }\n }\n return result;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"utils.cjs","names":["isReactiveField","isReference","isDefined"],"sources":["../src/utils.ts"],"sourcesContent":["import { type Entity } from \"./Entity.ts\";\nimport { isDefined } from \"./EntityManager.ts\";\nimport type { New } from \"./loading/loadHints.ts\";\nimport type { OrderBy } from \"./queries/find/EntityFilter.ts\";\nimport { isReactiveField, isReference } from \"./relations/index.ts\";\n\nexport type MaybePromise<T> = T | Promise<T>;\n\n/**\n * Given a `MaybePromise` of T, invoke `callback` against `T` either immediately or via `then`.\n *\n * This is the same as:\n *\n * ```\n * const r = await maybePromise;\n * return callback(r;;\n * ```\n *\n * But saves an `await` if `maybePromise` is not actually a promise.\n */\nexport function maybePromiseThen<T, U>(promiseOrObj: MaybePromise<T>, callback: (obj: T) => U): MaybePromise<U> {\n return promiseOrObj instanceof Promise ? promiseOrObj.then(callback) : callback(promiseOrObj);\n}\n\nexport function failIfAnyRejected<T>(results: PromiseSettledResult<T>[]): T[] {\n const rejects = results.filter((r) => r.status === \"rejected\");\n // For now just throw the 1st rejection; this should be pretty rare\n if (rejects.length > 0 && rejects[0].status === \"rejected\") {\n throw rejects[0].reason;\n }\n return results.map((r) => (r as PromiseFulfilledResult<T>).value);\n}\n\nexport function getOrSet<T extends Record<keyof unknown, unknown>>(\n record: T,\n key: keyof T,\n defaultValue: T[keyof T] | (() => T[keyof T]),\n): T[keyof T] {\n if (record[key] === undefined) {\n record[key] = defaultValue instanceof Function ? defaultValue() : defaultValue;\n }\n return record[key];\n}\n\n/** Defines a getter that replaces itself with its computed value on first access. */\nexport function defineLazyGetter<T extends object, K extends keyof T>(obj: T, key: K, build: () => T[K]): void {\n Object.defineProperty(obj, key, {\n configurable: true,\n get: function getLazyProperty() {\n const value = build();\n Object.defineProperty(obj, key, { configurable: true, value });\n return value;\n },\n });\n}\n\n/**\n * A utility to ensure a Promise-returning method actually returns a promise and doesn't\n * early exit. Using `async function` guarantees these semantics, but sometimes we avoid\n * `async` as a likely-premature optimization to avoid the overhead.\n */\nexport function tryResolve<T>(fn: () => T): Promise<T> {\n try {\n return Promise.resolve(fn());\n } catch (e) {\n return Promise.reject(e);\n }\n}\n\n/** Returns whether `obj` has at least one key, without allocating a keys array. */\nexport function hasAnyKey(obj: Record<any, any> | undefined): boolean {\n for (const _ in obj) return true;\n return false;\n}\n\nexport function fail(message?: string): never {\n throw new Error(message || \"Failed\");\n}\n\nexport function remove<T>(array: T[], t: T): void {\n const index = array.indexOf(t);\n if (index > -1) {\n array.splice(index, 1);\n }\n}\n\nexport function maybeRemove<T>(array: T[] | undefined, t: T): void {\n if (array) remove(array, t);\n}\n\nexport function maybeAdd<T>(array: T[], t: T): void {\n if (!array.includes(t)) {\n array.push(t);\n }\n}\n\nexport function clear<T>(array: T[]): void {\n array.splice(0, array.length);\n}\n\n/** Returns 0 inclusive to n exclusive. */\nexport function zeroTo(n: number): number[] {\n return [...Array(n).keys()];\n}\n\nexport function groupBy<T, Y = T, K = string>(list: readonly T[], fn: (x: T) => K, valueFn?: (x: T) => Y): Map<K, Y[]> {\n const result = new Map<K, Y[]>();\n list.forEach((o) => {\n const group = fn(o);\n if (!result.has(group)) {\n result.set(group, []);\n }\n result.get(group)!.push(valueFn === undefined ? (o as any as Y) : valueFn(o));\n });\n return result;\n}\n\nexport function indexBy<T, Y = T, K = string>(list: T[], fn: (x: T) => K, valueFn?: (x: T) => Y): Map<K, Y> {\n const result = new Map<K, Y>();\n list.forEach((o) => {\n const group = fn(o);\n result.set(group, valueFn === undefined ? (o as any as Y) : valueFn(o));\n });\n return result;\n}\n\nexport function batched<T>(list: Array<T>, n: number): T[][] {\n const result = [] as T[][];\n for (let i = 0; i < list.length; i += n) {\n result.push(list.slice(i, i + n));\n }\n return result;\n}\n\nexport function partition<T>(array: ReadonlyArray<T>, f: (el: T) => boolean): [T[], T[]] {\n const trueElements: T[] = [];\n const falseElements: T[] = [];\n array.forEach((el) => {\n if (f(el)) {\n trueElements.push(el);\n } else {\n falseElements.push(el);\n }\n });\n return [trueElements, falseElements];\n}\n\n// Utility function to wrap an object or value in an array, unless it's already an array\nexport function toArray<T>(maybeArray: T | T[] | undefined | null): T[] {\n return Array.isArray(maybeArray) ? maybeArray : maybeArray === undefined || maybeArray === null ? [] : [maybeArray];\n}\n\n// Utility type to strip off null and defined and infer only T.\nexport type NullOrDefinedOr<T> = T | null | undefined;\n\nexport function assertNever(x: never): never {\n throw new Error(\"Unexpected object: \" + x);\n}\n\nexport function abbreviation(tableName: string): string {\n return tableName\n .split(\"_\")\n .map((w) => w[0])\n .join(\"\");\n}\n\n/**\n * Utility method for casting `entity` to a `New` entity.\n *\n * Note that we don't actually do any runtime checks; a very simple one would be if the id is undefined,\n * but we want this method to be used in tests that are post-`flush` but still \"know\" the entity is\n * effectively new / fully loaded.\n *\n * Granted, we could do a runtime check that all relations are loaded.\n */\nexport function asNew<T extends Entity>(entity: T): New<T> {\n return entity as New<T>;\n}\n\nexport function compareValues(av: any, bv: any, direction: OrderBy): number {\n const d = direction === \"ASC\" ? 1 : -1;\n if (isReactiveField(av)) {\n av = !av.isSet ? -1 : av.get;\n }\n if (isReactiveField(bv)) {\n bv = !bv.isSet ? -1 : bv.get;\n }\n if (isReference(av) && isReference(bv)) {\n const aIsNew = av.isLoaded && (av as any).get?.isNewEntity;\n const bIsNew = bv.isLoaded && (bv as any).get?.isNewEntity;\n const bothSame = (aIsNew && bIsNew) || (!aIsNew && !bIsNew);\n if (!bothSame) {\n if (aIsNew) return 1 * d; // New entities are always \"greater than\" loaded entities\n if (bIsNew) return -1 * d; // Loaded entities are always \"less than\" new entities\n }\n av = av.idTaggedMaybe ?? (av.isLoaded && (av as any).get?.toString()) ?? undefined;\n bv = bv.idTaggedMaybe ?? (bv.isLoaded && (bv as any).get?.toString()) ?? undefined;\n }\n if (!isDefined(av) || !isDefined(bv)) {\n return !av && !bv ? 0 : (!av ? 1 : -1) * d;\n } else if (typeof av === \"number\" && typeof bv === \"number\") {\n return (av - bv) * d;\n } else if (typeof av === \"string\" && typeof bv === \"string\") {\n return av.localeCompare(bv) * d;\n } else if (av instanceof Date && bv instanceof Date) {\n return ((av as Date).getTime() - (bv as Date).getTime()) * d;\n } else {\n throw new Error(`Unsupported sortBy values ${av}, ${bv}`);\n }\n}\n\n/** A ~naive deep merge that requires already-normalized hints and will mutate `source`. */\n// https://gist.github.com/ahtcx/0cd94e62691f539160b32ecda18af3d6\nexport function mergeNormalizedHints(target: any, source: any): void {\n for (const key of Object.keys(source)) {\n // We assume both target & source are already normalized, i.e. we won't have\n // source=\"books\" and target={books: \"title\"}. They will both be {books: ...}.\n if (target[key]) {\n mergeNormalizedHints(source[key], target[key]);\n }\n }\n Object.assign(target, source);\n}\n\nconst newLine = /\\n/g;\nconst doubleSpace = / +/g;\n\nexport function cleanStringValue(value: unknown): string | undefined {\n // If this is not a string, coerce it -- or maybe fail?\n let s = typeof value !== \"string\" && value !== undefined && value !== null ? String(value) : value;\n // We always trim to remove leading/trailing spaces\n s = typeof s === \"string\" ? s.trim() : s;\n // And if it's empty string, we swap to undefined (null in the db)\n return s === \"\" || s === null ? undefined : s;\n}\n\n/** Strips new lines/indentation from our `UPDATE` string; doesn't do any actual SQL param escaping/etc. */\nexport function cleanSql(sql: string): string {\n return sql.trim().replace(newLine, \"\").replace(doubleSpace, \" \");\n}\n\n// Collections return an array, so do a hot-path `.flat()`\nexport function flatAndUnique<T extends unknown>(list: (T | T[] | undefined)[]): Set<T> {\n const result = new Set<T>();\n for (const c of list) {\n if (Array.isArray(c)) {\n for (const e of c) result.add(e);\n } else if (c) {\n result.add(c);\n }\n }\n return result;\n}\n"],"mappings":"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"}
package/build/utils.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { OrderBy } from "./queries/find/EntityFilter.cjs";
2
- import { New } from "./loadHints.cjs";
2
+ import { New } from "./loading/loadHints.cjs";
3
3
  import { Entity } from "./Entity.cjs";
4
4
  //#region src/utils.d.ts
5
5
  type MaybePromise<T> = T | Promise<T>;
package/build/utils.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { OrderBy } from "./queries/find/EntityFilter.mjs";
2
- import { New } from "./loadHints.mjs";
2
+ import { New } from "./loading/loadHints.mjs";
3
3
  import { Entity } from "./Entity.mjs";
4
4
  //#region src/utils.d.ts
5
5
  type MaybePromise<T> = T | Promise<T>;
package/build/utils.js CHANGED
@@ -1,5 +1,4 @@
1
1
  import { isReference } from "./relations/Reference.js";
2
- import "./loadHints.js";
3
2
  import { isReactiveField } from "./relations/ReactiveField.js";
4
3
  import "./relations/index.js";
5
4
  import { isDefined } from "./EntityManager.js";
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","names":[],"sources":["../src/utils.ts"],"sourcesContent":["import { type Entity } from \"./Entity.ts\";\nimport { isDefined } from \"./EntityManager.ts\";\nimport { type New } from \"./loadHints.ts\";\nimport type { OrderBy } from \"./queries/find/EntityFilter.ts\";\nimport { isReactiveField, isReference } from \"./relations/index.ts\";\n\nexport type MaybePromise<T> = T | Promise<T>;\n\n/**\n * Given a `MaybePromise` of T, invoke `callback` against `T` either immediately or via `then`.\n *\n * This is the same as:\n *\n * ```\n * const r = await maybePromise;\n * return callback(r;;\n * ```\n *\n * But saves an `await` if `maybePromise` is not actually a promise.\n */\nexport function maybePromiseThen<T, U>(promiseOrObj: MaybePromise<T>, callback: (obj: T) => U): MaybePromise<U> {\n return promiseOrObj instanceof Promise ? promiseOrObj.then(callback) : callback(promiseOrObj);\n}\n\nexport function failIfAnyRejected<T>(results: PromiseSettledResult<T>[]): T[] {\n const rejects = results.filter((r) => r.status === \"rejected\");\n // For now just throw the 1st rejection; this should be pretty rare\n if (rejects.length > 0 && rejects[0].status === \"rejected\") {\n throw rejects[0].reason;\n }\n return results.map((r) => (r as PromiseFulfilledResult<T>).value);\n}\n\nexport function getOrSet<T extends Record<keyof unknown, unknown>>(\n record: T,\n key: keyof T,\n defaultValue: T[keyof T] | (() => T[keyof T]),\n): T[keyof T] {\n if (record[key] === undefined) {\n record[key] = defaultValue instanceof Function ? defaultValue() : defaultValue;\n }\n return record[key];\n}\n\n/** Defines a getter that replaces itself with its computed value on first access. */\nexport function defineLazyGetter<T extends object, K extends keyof T>(obj: T, key: K, build: () => T[K]): void {\n Object.defineProperty(obj, key, {\n configurable: true,\n get: function getLazyProperty() {\n const value = build();\n Object.defineProperty(obj, key, { configurable: true, value });\n return value;\n },\n });\n}\n\n/**\n * A utility to ensure a Promise-returning method actually returns a promise and doesn't\n * early exit. Using `async function` guarantees these semantics, but sometimes we avoid\n * `async` as a likely-premature optimization to avoid the overhead.\n */\nexport function tryResolve<T>(fn: () => T): Promise<T> {\n try {\n return Promise.resolve(fn());\n } catch (e) {\n return Promise.reject(e);\n }\n}\n\n/** Returns whether `obj` has at least one key, without allocating a keys array. */\nexport function hasAnyKey(obj: Record<any, any> | undefined): boolean {\n for (const _ in obj) return true;\n return false;\n}\n\nexport function fail(message?: string): never {\n throw new Error(message || \"Failed\");\n}\n\nexport function remove<T>(array: T[], t: T): void {\n const index = array.indexOf(t);\n if (index > -1) {\n array.splice(index, 1);\n }\n}\n\nexport function maybeRemove<T>(array: T[] | undefined, t: T): void {\n if (array) remove(array, t);\n}\n\nexport function maybeAdd<T>(array: T[], t: T): void {\n if (!array.includes(t)) {\n array.push(t);\n }\n}\n\nexport function clear<T>(array: T[]): void {\n array.splice(0, array.length);\n}\n\n/** Returns 0 inclusive to n exclusive. */\nexport function zeroTo(n: number): number[] {\n return [...Array(n).keys()];\n}\n\nexport function groupBy<T, Y = T, K = string>(list: readonly T[], fn: (x: T) => K, valueFn?: (x: T) => Y): Map<K, Y[]> {\n const result = new Map<K, Y[]>();\n list.forEach((o) => {\n const group = fn(o);\n if (!result.has(group)) {\n result.set(group, []);\n }\n result.get(group)!.push(valueFn === undefined ? (o as any as Y) : valueFn(o));\n });\n return result;\n}\n\nexport function indexBy<T, Y = T, K = string>(list: T[], fn: (x: T) => K, valueFn?: (x: T) => Y): Map<K, Y> {\n const result = new Map<K, Y>();\n list.forEach((o) => {\n const group = fn(o);\n result.set(group, valueFn === undefined ? (o as any as Y) : valueFn(o));\n });\n return result;\n}\n\nexport function batched<T>(list: Array<T>, n: number): T[][] {\n const result = [] as T[][];\n for (let i = 0; i < list.length; i += n) {\n result.push(list.slice(i, i + n));\n }\n return result;\n}\n\nexport function partition<T>(array: ReadonlyArray<T>, f: (el: T) => boolean): [T[], T[]] {\n const trueElements: T[] = [];\n const falseElements: T[] = [];\n array.forEach((el) => {\n if (f(el)) {\n trueElements.push(el);\n } else {\n falseElements.push(el);\n }\n });\n return [trueElements, falseElements];\n}\n\n// Utility function to wrap an object or value in an array, unless it's already an array\nexport function toArray<T>(maybeArray: T | T[] | undefined | null): T[] {\n return Array.isArray(maybeArray) ? maybeArray : maybeArray === undefined || maybeArray === null ? [] : [maybeArray];\n}\n\n// Utility type to strip off null and defined and infer only T.\nexport type NullOrDefinedOr<T> = T | null | undefined;\n\nexport function assertNever(x: never): never {\n throw new Error(\"Unexpected object: \" + x);\n}\n\nexport function abbreviation(tableName: string): string {\n return tableName\n .split(\"_\")\n .map((w) => w[0])\n .join(\"\");\n}\n\n/**\n * Utility method for casting `entity` to a `New` entity.\n *\n * Note that we don't actually do any runtime checks; a very simple one would be if the id is undefined,\n * but we want this method to be used in tests that are post-`flush` but still \"know\" the entity is\n * effectively new / fully loaded.\n *\n * Granted, we could do a runtime check that all relations are loaded.\n */\nexport function asNew<T extends Entity>(entity: T): New<T> {\n return entity as New<T>;\n}\n\nexport function compareValues(av: any, bv: any, direction: OrderBy): number {\n const d = direction === \"ASC\" ? 1 : -1;\n if (isReactiveField(av)) {\n av = !av.isSet ? -1 : av.get;\n }\n if (isReactiveField(bv)) {\n bv = !bv.isSet ? -1 : bv.get;\n }\n if (isReference(av) && isReference(bv)) {\n const aIsNew = av.isLoaded && (av as any).get?.isNewEntity;\n const bIsNew = bv.isLoaded && (bv as any).get?.isNewEntity;\n const bothSame = (aIsNew && bIsNew) || (!aIsNew && !bIsNew);\n if (!bothSame) {\n if (aIsNew) return 1 * d; // New entities are always \"greater than\" loaded entities\n if (bIsNew) return -1 * d; // Loaded entities are always \"less than\" new entities\n }\n av = av.idTaggedMaybe ?? (av.isLoaded && (av as any).get?.toString()) ?? undefined;\n bv = bv.idTaggedMaybe ?? (bv.isLoaded && (bv as any).get?.toString()) ?? undefined;\n }\n if (!isDefined(av) || !isDefined(bv)) {\n return !av && !bv ? 0 : (!av ? 1 : -1) * d;\n } else if (typeof av === \"number\" && typeof bv === \"number\") {\n return (av - bv) * d;\n } else if (typeof av === \"string\" && typeof bv === \"string\") {\n return av.localeCompare(bv) * d;\n } else if (av instanceof Date && bv instanceof Date) {\n return ((av as Date).getTime() - (bv as Date).getTime()) * d;\n } else {\n throw new Error(`Unsupported sortBy values ${av}, ${bv}`);\n }\n}\n\n/** A ~naive deep merge that requires already-normalized hints and will mutate `source`. */\n// https://gist.github.com/ahtcx/0cd94e62691f539160b32ecda18af3d6\nexport function mergeNormalizedHints(target: any, source: any): void {\n for (const key of Object.keys(source)) {\n // We assume both target & source are already normalized, i.e. we won't have\n // source=\"books\" and target={books: \"title\"}. They will both be {books: ...}.\n if (target[key]) {\n mergeNormalizedHints(source[key], target[key]);\n }\n }\n Object.assign(target, source);\n}\n\nconst newLine = /\\n/g;\nconst doubleSpace = / +/g;\n\nexport function cleanStringValue(value: unknown): string | undefined {\n // If this is not a string, coerce it -- or maybe fail?\n let s = typeof value !== \"string\" && value !== undefined && value !== null ? String(value) : value;\n // We always trim to remove leading/trailing spaces\n s = typeof s === \"string\" ? s.trim() : s;\n // And if it's empty string, we swap to undefined (null in the db)\n return s === \"\" || s === null ? undefined : s;\n}\n\n/** Strips new lines/indentation from our `UPDATE` string; doesn't do any actual SQL param escaping/etc. */\nexport function cleanSql(sql: string): string {\n return sql.trim().replace(newLine, \"\").replace(doubleSpace, \" \");\n}\n\n// Collections return an array, so do a hot-path `.flat()`\nexport function flatAndUnique<T extends unknown>(list: (T | T[] | undefined)[]): Set<T> {\n const result = new Set<T>();\n for (const c of list) {\n if (Array.isArray(c)) {\n for (const e of c) result.add(e);\n } else if (c) {\n result.add(c);\n }\n }\n return result;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"utils.js","names":[],"sources":["../src/utils.ts"],"sourcesContent":["import { type Entity } from \"./Entity.ts\";\nimport { isDefined } from \"./EntityManager.ts\";\nimport type { New } from \"./loading/loadHints.ts\";\nimport type { OrderBy } from \"./queries/find/EntityFilter.ts\";\nimport { isReactiveField, isReference } from \"./relations/index.ts\";\n\nexport type MaybePromise<T> = T | Promise<T>;\n\n/**\n * Given a `MaybePromise` of T, invoke `callback` against `T` either immediately or via `then`.\n *\n * This is the same as:\n *\n * ```\n * const r = await maybePromise;\n * return callback(r;;\n * ```\n *\n * But saves an `await` if `maybePromise` is not actually a promise.\n */\nexport function maybePromiseThen<T, U>(promiseOrObj: MaybePromise<T>, callback: (obj: T) => U): MaybePromise<U> {\n return promiseOrObj instanceof Promise ? promiseOrObj.then(callback) : callback(promiseOrObj);\n}\n\nexport function failIfAnyRejected<T>(results: PromiseSettledResult<T>[]): T[] {\n const rejects = results.filter((r) => r.status === \"rejected\");\n // For now just throw the 1st rejection; this should be pretty rare\n if (rejects.length > 0 && rejects[0].status === \"rejected\") {\n throw rejects[0].reason;\n }\n return results.map((r) => (r as PromiseFulfilledResult<T>).value);\n}\n\nexport function getOrSet<T extends Record<keyof unknown, unknown>>(\n record: T,\n key: keyof T,\n defaultValue: T[keyof T] | (() => T[keyof T]),\n): T[keyof T] {\n if (record[key] === undefined) {\n record[key] = defaultValue instanceof Function ? defaultValue() : defaultValue;\n }\n return record[key];\n}\n\n/** Defines a getter that replaces itself with its computed value on first access. */\nexport function defineLazyGetter<T extends object, K extends keyof T>(obj: T, key: K, build: () => T[K]): void {\n Object.defineProperty(obj, key, {\n configurable: true,\n get: function getLazyProperty() {\n const value = build();\n Object.defineProperty(obj, key, { configurable: true, value });\n return value;\n },\n });\n}\n\n/**\n * A utility to ensure a Promise-returning method actually returns a promise and doesn't\n * early exit. Using `async function` guarantees these semantics, but sometimes we avoid\n * `async` as a likely-premature optimization to avoid the overhead.\n */\nexport function tryResolve<T>(fn: () => T): Promise<T> {\n try {\n return Promise.resolve(fn());\n } catch (e) {\n return Promise.reject(e);\n }\n}\n\n/** Returns whether `obj` has at least one key, without allocating a keys array. */\nexport function hasAnyKey(obj: Record<any, any> | undefined): boolean {\n for (const _ in obj) return true;\n return false;\n}\n\nexport function fail(message?: string): never {\n throw new Error(message || \"Failed\");\n}\n\nexport function remove<T>(array: T[], t: T): void {\n const index = array.indexOf(t);\n if (index > -1) {\n array.splice(index, 1);\n }\n}\n\nexport function maybeRemove<T>(array: T[] | undefined, t: T): void {\n if (array) remove(array, t);\n}\n\nexport function maybeAdd<T>(array: T[], t: T): void {\n if (!array.includes(t)) {\n array.push(t);\n }\n}\n\nexport function clear<T>(array: T[]): void {\n array.splice(0, array.length);\n}\n\n/** Returns 0 inclusive to n exclusive. */\nexport function zeroTo(n: number): number[] {\n return [...Array(n).keys()];\n}\n\nexport function groupBy<T, Y = T, K = string>(list: readonly T[], fn: (x: T) => K, valueFn?: (x: T) => Y): Map<K, Y[]> {\n const result = new Map<K, Y[]>();\n list.forEach((o) => {\n const group = fn(o);\n if (!result.has(group)) {\n result.set(group, []);\n }\n result.get(group)!.push(valueFn === undefined ? (o as any as Y) : valueFn(o));\n });\n return result;\n}\n\nexport function indexBy<T, Y = T, K = string>(list: T[], fn: (x: T) => K, valueFn?: (x: T) => Y): Map<K, Y> {\n const result = new Map<K, Y>();\n list.forEach((o) => {\n const group = fn(o);\n result.set(group, valueFn === undefined ? (o as any as Y) : valueFn(o));\n });\n return result;\n}\n\nexport function batched<T>(list: Array<T>, n: number): T[][] {\n const result = [] as T[][];\n for (let i = 0; i < list.length; i += n) {\n result.push(list.slice(i, i + n));\n }\n return result;\n}\n\nexport function partition<T>(array: ReadonlyArray<T>, f: (el: T) => boolean): [T[], T[]] {\n const trueElements: T[] = [];\n const falseElements: T[] = [];\n array.forEach((el) => {\n if (f(el)) {\n trueElements.push(el);\n } else {\n falseElements.push(el);\n }\n });\n return [trueElements, falseElements];\n}\n\n// Utility function to wrap an object or value in an array, unless it's already an array\nexport function toArray<T>(maybeArray: T | T[] | undefined | null): T[] {\n return Array.isArray(maybeArray) ? maybeArray : maybeArray === undefined || maybeArray === null ? [] : [maybeArray];\n}\n\n// Utility type to strip off null and defined and infer only T.\nexport type NullOrDefinedOr<T> = T | null | undefined;\n\nexport function assertNever(x: never): never {\n throw new Error(\"Unexpected object: \" + x);\n}\n\nexport function abbreviation(tableName: string): string {\n return tableName\n .split(\"_\")\n .map((w) => w[0])\n .join(\"\");\n}\n\n/**\n * Utility method for casting `entity` to a `New` entity.\n *\n * Note that we don't actually do any runtime checks; a very simple one would be if the id is undefined,\n * but we want this method to be used in tests that are post-`flush` but still \"know\" the entity is\n * effectively new / fully loaded.\n *\n * Granted, we could do a runtime check that all relations are loaded.\n */\nexport function asNew<T extends Entity>(entity: T): New<T> {\n return entity as New<T>;\n}\n\nexport function compareValues(av: any, bv: any, direction: OrderBy): number {\n const d = direction === \"ASC\" ? 1 : -1;\n if (isReactiveField(av)) {\n av = !av.isSet ? -1 : av.get;\n }\n if (isReactiveField(bv)) {\n bv = !bv.isSet ? -1 : bv.get;\n }\n if (isReference(av) && isReference(bv)) {\n const aIsNew = av.isLoaded && (av as any).get?.isNewEntity;\n const bIsNew = bv.isLoaded && (bv as any).get?.isNewEntity;\n const bothSame = (aIsNew && bIsNew) || (!aIsNew && !bIsNew);\n if (!bothSame) {\n if (aIsNew) return 1 * d; // New entities are always \"greater than\" loaded entities\n if (bIsNew) return -1 * d; // Loaded entities are always \"less than\" new entities\n }\n av = av.idTaggedMaybe ?? (av.isLoaded && (av as any).get?.toString()) ?? undefined;\n bv = bv.idTaggedMaybe ?? (bv.isLoaded && (bv as any).get?.toString()) ?? undefined;\n }\n if (!isDefined(av) || !isDefined(bv)) {\n return !av && !bv ? 0 : (!av ? 1 : -1) * d;\n } else if (typeof av === \"number\" && typeof bv === \"number\") {\n return (av - bv) * d;\n } else if (typeof av === \"string\" && typeof bv === \"string\") {\n return av.localeCompare(bv) * d;\n } else if (av instanceof Date && bv instanceof Date) {\n return ((av as Date).getTime() - (bv as Date).getTime()) * d;\n } else {\n throw new Error(`Unsupported sortBy values ${av}, ${bv}`);\n }\n}\n\n/** A ~naive deep merge that requires already-normalized hints and will mutate `source`. */\n// https://gist.github.com/ahtcx/0cd94e62691f539160b32ecda18af3d6\nexport function mergeNormalizedHints(target: any, source: any): void {\n for (const key of Object.keys(source)) {\n // We assume both target & source are already normalized, i.e. we won't have\n // source=\"books\" and target={books: \"title\"}. They will both be {books: ...}.\n if (target[key]) {\n mergeNormalizedHints(source[key], target[key]);\n }\n }\n Object.assign(target, source);\n}\n\nconst newLine = /\\n/g;\nconst doubleSpace = / +/g;\n\nexport function cleanStringValue(value: unknown): string | undefined {\n // If this is not a string, coerce it -- or maybe fail?\n let s = typeof value !== \"string\" && value !== undefined && value !== null ? String(value) : value;\n // We always trim to remove leading/trailing spaces\n s = typeof s === \"string\" ? s.trim() : s;\n // And if it's empty string, we swap to undefined (null in the db)\n return s === \"\" || s === null ? undefined : s;\n}\n\n/** Strips new lines/indentation from our `UPDATE` string; doesn't do any actual SQL param escaping/etc. */\nexport function cleanSql(sql: string): string {\n return sql.trim().replace(newLine, \"\").replace(doubleSpace, \" \");\n}\n\n// Collections return an array, so do a hot-path `.flat()`\nexport function flatAndUnique<T extends unknown>(list: (T | T[] | undefined)[]): Set<T> {\n const result = new Set<T>();\n for (const c of list) {\n if (Array.isArray(c)) {\n for (const e of c) result.add(e);\n } else if (c) {\n result.add(c);\n }\n }\n return result;\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "joist-core",
3
- "version": "2.3.0-next.97",
3
+ "version": "2.3.0-next.98",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "repository": {
@@ -42,7 +42,7 @@
42
42
  "build"
43
43
  ],
44
44
  "peerDependencies": {
45
- "joist-utils": "2.3.0-next.97"
45
+ "joist-utils": "2.3.0-next.98"
46
46
  },
47
47
  "dependencies": {
48
48
  "ansis": "^4.3.1",
@@ -1 +0,0 @@
1
- {"version":3,"file":"FlushLock.cjs","names":["AsyncLocalStorage","#isFlushing","#flushSecret"],"sources":["../src/FlushLock.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"async_hooks\";\n\n/** A marker to prevent setter calls during `flush` calls. */\nconst currentFlushSecret = new AsyncLocalStorage<{ flushSecret: number }>();\n\n/**\n * Prevents entities being mutated mid-flush.\n *\n * The `flush` process does a dirty check + SQL flush and generally doesn't want\n * entities to re-dirtied after it's done the initial dirty check. So we'd like\n * to prevent all setter calls while `flush` is running.\n *\n * That said, lifecycle code like hooks actually can make setter calls b/c `flush`\n * invokes them at a specific point in its process.\n *\n * We solve this by using node's `AsyncLocalStorage` to mark certain callbacks (promise\n * handlers) as blessed / invoked-from-`flush`-itself, and they are allowed to call setters,\n * but any external callers (i.e. application code) will be rejected.\n */\nexport class FlushLock {\n #flushSecret: number = 0;\n #isFlushing: boolean = false;\n\n /** This will begin any non-hook restrictions on writing to entities. */\n startLock(): void {\n if (this.#isFlushing) {\n throw new Error(\"Cannot flush while another flush is already in progress\");\n }\n this.#isFlushing = true;\n }\n\n releaseLock(): void {\n this.#isFlushing = false;\n }\n\n /** Any writes that happen from `fn`, despite flush being locked, will be allowed. */\n allowWrites(fn: () => Promise<void>): Promise<void> {\n return currentFlushSecret.run({ flushSecret: this.#flushSecret }, () =>\n fn().then(() => {\n this.#flushSecret += 1;\n }),\n );\n }\n\n /** Blows up if writes are locked, i.e. we're flushing and the caller is not within an `allowWrites` block. */\n checkWritesAllowed(): void {\n if (this.#isFlushing) {\n const { flushSecret } = currentFlushSecret.getStore() || {};\n if (flushSecret === undefined) {\n throw new Error(`Cannot mutate an entity during an em.flush outside of a entity hook or from afterCommit`);\n } else if (flushSecret !== this.#flushSecret) {\n throw new Error(`Attempting to reuse a hook context outside its flush loop`);\n }\n }\n }\n\n get isFlushing(): boolean {\n return this.#isFlushing;\n }\n}\n"],"mappings":";;;AAGA,MAAM,qBAAqB,0BAAIA,EAAAA,CAAAA,kBAA2C;;;;;;;;;;;;;;;AAgB1E,IAAa,YAAb,MAAuB;CACrB,eAAuB;CACvB,cAAuB;;CAGvB,YAAkB;EAChB,IAAI,KAAKC,aACP,MAAM,IAAI,MAAM,yDAAyD;EAE3E,KAAKA,cAAc;CACrB;CAEA,cAAoB;EAClB,KAAKA,cAAc;CACrB;;CAGA,YAAY,IAAwC;EAClD,OAAO,mBAAmB,IAAI,EAAE,aAAa,KAAKC,aAAa,SAC7D,GAAG,CAAC,CAAC,WAAW;GACd,KAAKA,gBAAgB;EACvB,CAAC,CACH;CACF;;CAGA,qBAA2B;EACzB,IAAI,KAAKD,aAAa;GACpB,MAAM,EAAE,gBAAgB,mBAAmB,SAAS,KAAK,CAAC;GAC1D,IAAI,gBAAgB,KAAA,GAClB,MAAM,IAAI,MAAM,yFAAyF;QACpG,IAAI,gBAAgB,KAAKC,cAC9B,MAAM,IAAI,MAAM,2DAA2D;EAE/E;CACF;CAEA,IAAI,aAAsB;EACxB,OAAO,KAAKD;CACd;AACF"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"FlushLock.d.cts","names":[],"sources":["../src/FlushLock.ts"],"mappings":";;;;;;;;;;;;;;;cAmBa;;;EAKX;EAOA;;EAKA,YAAY,UAAU,gBAAgB;;EAStC;MAWI"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"FlushLock.d.mts","names":[],"sources":["../src/FlushLock.ts"],"mappings":";;;;;;;;;;;;;;;cAmBa;;;EAKX;EAOA;;EAKA,YAAY,UAAU,gBAAgB;;EAStC;MAWI"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"FlushLock.js","names":["#isFlushing","#flushSecret"],"sources":["../src/FlushLock.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"async_hooks\";\n\n/** A marker to prevent setter calls during `flush` calls. */\nconst currentFlushSecret = new AsyncLocalStorage<{ flushSecret: number }>();\n\n/**\n * Prevents entities being mutated mid-flush.\n *\n * The `flush` process does a dirty check + SQL flush and generally doesn't want\n * entities to re-dirtied after it's done the initial dirty check. So we'd like\n * to prevent all setter calls while `flush` is running.\n *\n * That said, lifecycle code like hooks actually can make setter calls b/c `flush`\n * invokes them at a specific point in its process.\n *\n * We solve this by using node's `AsyncLocalStorage` to mark certain callbacks (promise\n * handlers) as blessed / invoked-from-`flush`-itself, and they are allowed to call setters,\n * but any external callers (i.e. application code) will be rejected.\n */\nexport class FlushLock {\n #flushSecret: number = 0;\n #isFlushing: boolean = false;\n\n /** This will begin any non-hook restrictions on writing to entities. */\n startLock(): void {\n if (this.#isFlushing) {\n throw new Error(\"Cannot flush while another flush is already in progress\");\n }\n this.#isFlushing = true;\n }\n\n releaseLock(): void {\n this.#isFlushing = false;\n }\n\n /** Any writes that happen from `fn`, despite flush being locked, will be allowed. */\n allowWrites(fn: () => Promise<void>): Promise<void> {\n return currentFlushSecret.run({ flushSecret: this.#flushSecret }, () =>\n fn().then(() => {\n this.#flushSecret += 1;\n }),\n );\n }\n\n /** Blows up if writes are locked, i.e. we're flushing and the caller is not within an `allowWrites` block. */\n checkWritesAllowed(): void {\n if (this.#isFlushing) {\n const { flushSecret } = currentFlushSecret.getStore() || {};\n if (flushSecret === undefined) {\n throw new Error(`Cannot mutate an entity during an em.flush outside of a entity hook or from afterCommit`);\n } else if (flushSecret !== this.#flushSecret) {\n throw new Error(`Attempting to reuse a hook context outside its flush loop`);\n }\n }\n }\n\n get isFlushing(): boolean {\n return this.#isFlushing;\n }\n}\n"],"mappings":";;;AAGA,MAAM,qBAAqB,IAAI,kBAA2C;;;;;;;;;;;;;;;AAgB1E,IAAa,YAAb,MAAuB;CACrB,eAAuB;CACvB,cAAuB;;CAGvB,YAAkB;EAChB,IAAI,KAAKA,aACP,MAAM,IAAI,MAAM,yDAAyD;EAE3E,KAAKA,cAAc;CACrB;CAEA,cAAoB;EAClB,KAAKA,cAAc;CACrB;;CAGA,YAAY,IAAwC;EAClD,OAAO,mBAAmB,IAAI,EAAE,aAAa,KAAKC,aAAa,SAC7D,GAAG,CAAC,CAAC,WAAW;GACd,KAAKA,gBAAgB;EACvB,CAAC,CACH;CACF;;CAGA,qBAA2B;EACzB,IAAI,KAAKD,aAAa;GACpB,MAAM,EAAE,gBAAgB,mBAAmB,SAAS,KAAK,CAAC;GAC1D,IAAI,gBAAgB,KAAA,GAClB,MAAM,IAAI,MAAM,yFAAyF;QACpG,IAAI,gBAAgB,KAAKC,cAC9B,MAAM,IAAI,MAAM,2DAA2D;EAE/E;CACF;CAEA,IAAI,aAAsB;EACxB,OAAO,KAAKD;CACd;AACF"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"HintTree.cjs","names":["normalizeHint"],"sources":["../src/HintTree.ts"],"sourcesContent":["import { type Entity } from \"./Entity.ts\";\nimport { type TaggedId } from \"./EntityManager.ts\";\nimport { type LoadHint } from \"./loadHints.ts\";\nimport { normalizeHint } from \"./normalizeHints.ts\";\n\n// We support preloading in `populate` with existing entities, or `load` with just ids.\n// (We could ask `populate` to convert its entities to ids, but it's convenient for it\n// to keep the HintTree populated with Entities so that newly-created entities can have\n// their collections marked as loaded.\nexport type EntityOrId = Entity | TaggedId;\n\nexport type HintNode<E extends EntityOrId> = {\n /** These entities are the root entities of our preload, i.e. we use them to trim the tree to prevent over-fetching. */\n entities: Set<E>;\n /** A runtime indication of the type of `E`. */\n entitiesKind: \"instances\" | \"ids\" | \"none\";\n /** The hints to preload at this node, i.e. if `E` is `Author`, the `books: \"reviews` or just `comments: {}`. */\n hints: { [key: string]: HintNode<E> };\n};\n\n/**\n * Given a number of potentially overlapping load hints, i.e. `{ authors: \"books\" }` and\n * `{ authors: \"reviews\" }`, combines them into a single `HintNode` tree, with bookkeeping\n * of which entities requested each specific node of the tree.\n *\n * I.e. if we're populating three publishers, two with `{ authors: \"books\" }` and one with\n * `{ authors: \"reviews\" }`, we'll end up with a tree like:\n *\n * ```\n * {\n * authors: {\n * entities: [p1, p2, p3],\n * hints: {\n * books: { entities: [p1, p2], hints: {} },\n * reviews: { entities: [p3], hints: {} },\n * }\n * }\n * }\n * ```\n *\n * Which will let us preload `authors` for all three publishers, but `books` only for the\n * first two, and `reviews` only for the third, i.e. we can prevent over-fetching.\n */\nexport function buildHintTree<E extends EntityOrId>(\n hints: readonly { entity: E; hint: LoadHint<any> | undefined }[] | LoadHint<any>,\n): HintNode<E> {\n if (Array.isArray(hints)) {\n // This might be a top-level LoadHint string[] like [\"books\"]\n const isLoadHint = hints.length > 0 && typeof hints[0] === \"string\";\n if (isLoadHint) {\n const root: HintNode<E> = { entitiesKind: \"none\", entities: new Set(), hints: {} };\n addHintNode(root, undefined, hints as LoadHint<any>);\n return root;\n } else {\n const entitiesKind = typeof hints[0].entity === \"string\" ? (\"ids\" as const) : (\"instances\" as const);\n const root: HintNode<E> = { entitiesKind, entities: new Set(), hints: {} };\n for (const { entity, hint } of hints) {\n addHintNode(root, entity, hint);\n }\n return root;\n }\n } else {\n const root: HintNode<E> = { entitiesKind: \"none\", entities: new Set(), hints: {} };\n addHintNode(root, undefined, hints as LoadHint<any>);\n return root;\n }\n}\n\nfunction addHintNode<E extends EntityOrId>(node: HintNode<E>, entity: E | undefined, hint: LoadHint<any> | undefined) {\n // It's tempting to filter out new entities here, but we need to call `.load()` on their\n // relations to ensure the `.get`s will later work, even if we don't look in the db for them.\n if (entity) node.entities.add(entity);\n if (hint) {\n for (const [key, nestedHint] of Object.entries(normalizeHint(hint))) {\n const child = (node.hints[key] ??= { entitiesKind: node.entitiesKind, entities: new Set(), hints: {} });\n addHintNode(child, entity, nestedHint);\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2CA,SAAgB,cACd,OACa;CACb,IAAI,MAAM,QAAQ,KAAK,GAAG;EAGxB,IADmB,MAAM,SAAS,KAAK,OAAO,MAAM,OAAO,UAC3C;GACd,MAAM,OAAoB;IAAE,cAAc;IAAQ,0BAAU,IAAI,IAAI;IAAG,OAAO,CAAC;GAAE;GACjF,YAAY,MAAM,KAAA,GAAW,KAAsB;GACnD,OAAO;EACT,OAAO;GAEL,MAAM,OAAoB;IAAE,cADP,OAAO,MAAM,EAAE,CAAC,WAAW,WAAY,QAAmB;IACrC,0BAAU,IAAI,IAAI;IAAG,OAAO,CAAC;GAAE;GACzE,KAAK,MAAM,EAAE,QAAQ,UAAU,OAC7B,YAAY,MAAM,QAAQ,IAAI;GAEhC,OAAO;EACT;CACF,OAAO;EACL,MAAM,OAAoB;GAAE,cAAc;GAAQ,0BAAU,IAAI,IAAI;GAAG,OAAO,CAAC;EAAE;EACjF,YAAY,MAAM,KAAA,GAAW,KAAsB;EACnD,OAAO;CACT;AACF;AAEA,SAAS,YAAkC,MAAmB,QAAuB,MAAiC;CAGpH,IAAI,QAAQ,KAAK,SAAS,IAAI,MAAM;CACpC,IAAI,MACF,KAAK,MAAM,CAAC,KAAK,eAAe,OAAO,QAAQA,uBAAAA,cAAc,IAAI,CAAC,GAEhE,YAAY,KADQ,MAAM,SAAS;EAAE,cAAc,KAAK;EAAc,0BAAU,IAAI,IAAI;EAAG,OAAO,CAAC;CAAE,GAClF,QAAQ,UAAU;AAG3C"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"HintTree.d.cts","names":[],"sources":["../src/HintTree.ts"],"mappings":";;;;KASY,aAAa,SAAS;KAEtB,SAAS,UAAU;;EAE7B,UAAU,IAAI;;EAEd;;EAEA;KAAU,cAAc,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;iBA0BnB,cAAc,UAAU,YACtC;EAAkB,QAAQ;EAAG,MAAM;MAAgC,gBAClE,SAAS"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"HintTree.d.mts","names":[],"sources":["../src/HintTree.ts"],"mappings":";;;;KASY,aAAa,SAAS;KAEtB,SAAS,UAAU;;EAE7B,UAAU,IAAI;;EAEd;;EAEA;KAAU,cAAc,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;iBA0BnB,cAAc,UAAU,YACtC;EAAkB,QAAQ;EAAG,MAAM;MAAgC,gBAClE,SAAS"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"HintTree.js","names":[],"sources":["../src/HintTree.ts"],"sourcesContent":["import { type Entity } from \"./Entity.ts\";\nimport { type TaggedId } from \"./EntityManager.ts\";\nimport { type LoadHint } from \"./loadHints.ts\";\nimport { normalizeHint } from \"./normalizeHints.ts\";\n\n// We support preloading in `populate` with existing entities, or `load` with just ids.\n// (We could ask `populate` to convert its entities to ids, but it's convenient for it\n// to keep the HintTree populated with Entities so that newly-created entities can have\n// their collections marked as loaded.\nexport type EntityOrId = Entity | TaggedId;\n\nexport type HintNode<E extends EntityOrId> = {\n /** These entities are the root entities of our preload, i.e. we use them to trim the tree to prevent over-fetching. */\n entities: Set<E>;\n /** A runtime indication of the type of `E`. */\n entitiesKind: \"instances\" | \"ids\" | \"none\";\n /** The hints to preload at this node, i.e. if `E` is `Author`, the `books: \"reviews` or just `comments: {}`. */\n hints: { [key: string]: HintNode<E> };\n};\n\n/**\n * Given a number of potentially overlapping load hints, i.e. `{ authors: \"books\" }` and\n * `{ authors: \"reviews\" }`, combines them into a single `HintNode` tree, with bookkeeping\n * of which entities requested each specific node of the tree.\n *\n * I.e. if we're populating three publishers, two with `{ authors: \"books\" }` and one with\n * `{ authors: \"reviews\" }`, we'll end up with a tree like:\n *\n * ```\n * {\n * authors: {\n * entities: [p1, p2, p3],\n * hints: {\n * books: { entities: [p1, p2], hints: {} },\n * reviews: { entities: [p3], hints: {} },\n * }\n * }\n * }\n * ```\n *\n * Which will let us preload `authors` for all three publishers, but `books` only for the\n * first two, and `reviews` only for the third, i.e. we can prevent over-fetching.\n */\nexport function buildHintTree<E extends EntityOrId>(\n hints: readonly { entity: E; hint: LoadHint<any> | undefined }[] | LoadHint<any>,\n): HintNode<E> {\n if (Array.isArray(hints)) {\n // This might be a top-level LoadHint string[] like [\"books\"]\n const isLoadHint = hints.length > 0 && typeof hints[0] === \"string\";\n if (isLoadHint) {\n const root: HintNode<E> = { entitiesKind: \"none\", entities: new Set(), hints: {} };\n addHintNode(root, undefined, hints as LoadHint<any>);\n return root;\n } else {\n const entitiesKind = typeof hints[0].entity === \"string\" ? (\"ids\" as const) : (\"instances\" as const);\n const root: HintNode<E> = { entitiesKind, entities: new Set(), hints: {} };\n for (const { entity, hint } of hints) {\n addHintNode(root, entity, hint);\n }\n return root;\n }\n } else {\n const root: HintNode<E> = { entitiesKind: \"none\", entities: new Set(), hints: {} };\n addHintNode(root, undefined, hints as LoadHint<any>);\n return root;\n }\n}\n\nfunction addHintNode<E extends EntityOrId>(node: HintNode<E>, entity: E | undefined, hint: LoadHint<any> | undefined) {\n // It's tempting to filter out new entities here, but we need to call `.load()` on their\n // relations to ensure the `.get`s will later work, even if we don't look in the db for them.\n if (entity) node.entities.add(entity);\n if (hint) {\n for (const [key, nestedHint] of Object.entries(normalizeHint(hint))) {\n const child = (node.hints[key] ??= { entitiesKind: node.entitiesKind, entities: new Set(), hints: {} });\n addHintNode(child, entity, nestedHint);\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2CA,SAAgB,cACd,OACa;CACb,IAAI,MAAM,QAAQ,KAAK,GAAG;EAGxB,IADmB,MAAM,SAAS,KAAK,OAAO,MAAM,OAAO,UAC3C;GACd,MAAM,OAAoB;IAAE,cAAc;IAAQ,0BAAU,IAAI,IAAI;IAAG,OAAO,CAAC;GAAE;GACjF,YAAY,MAAM,KAAA,GAAW,KAAsB;GACnD,OAAO;EACT,OAAO;GAEL,MAAM,OAAoB;IAAE,cADP,OAAO,MAAM,EAAE,CAAC,WAAW,WAAY,QAAmB;IACrC,0BAAU,IAAI,IAAI;IAAG,OAAO,CAAC;GAAE;GACzE,KAAK,MAAM,EAAE,QAAQ,UAAU,OAC7B,YAAY,MAAM,QAAQ,IAAI;GAEhC,OAAO;EACT;CACF,OAAO;EACL,MAAM,OAAoB;GAAE,cAAc;GAAQ,0BAAU,IAAI,IAAI;GAAG,OAAO,CAAC;EAAE;EACjF,YAAY,MAAM,KAAA,GAAW,KAAsB;EACnD,OAAO;CACT;AACF;AAEA,SAAS,YAAkC,MAAmB,QAAuB,MAAiC;CAGpH,IAAI,QAAQ,KAAK,SAAS,IAAI,MAAM;CACpC,IAAI,MACF,KAAK,MAAM,CAAC,KAAK,eAAe,OAAO,QAAQ,cAAc,IAAI,CAAC,GAEhE,YAAY,KADQ,MAAM,SAAS;EAAE,cAAc,KAAK;EAAc,0BAAU,IAAI,IAAI;EAAG,OAAO,CAAC;CAAE,GAClF,QAAQ,UAAU;AAG3C"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"IsLoadedCache.cjs","names":["getMetadata","#smartCache","#smartDirtySets","#naiveCache","#naiveDirtySets","#resetDownstreamReactables"],"sources":["../src/IsLoadedCache.ts"],"sourcesContent":["import { type Entity } from \"./Entity.ts\";\nimport { type EntityMetadata, getMetadata } from \"./EntityMetadata.ts\";\n\n/**\n * Interface for our relations that have dynamic & expensive `isLoaded` checks.\n *\n * ...and also `OneToManyCollection.get` calls.\n *\n * The primary m2o/o2m/m2m relations all have trivial `isLoaded` checks--are they\n * loaded or not.\n *\n * But for \"composite relations\", i.e. a ReactiveField or ReactiveRelation whose\n * \"load-ness\" is calculated by evaluating its load hint across a subgraph of entities\n * & relations, load-ness can be more dynamic true-then-false, as its subgraph changes.\n *\n * To avoid performance issues (see https://github.com/joist-orm/joist-orm/issues/1166),\n * we cache this dynamic/expensive `isLoaded` checks, and then do targeted, reactivity-driven\n * cache invalidation whenever relations are mutated (via a hook in `setField`).\n */\nexport interface IsLoadedCachable {\n entity: Entity;\n fieldName: string;\n isLoaded: boolean;\n resetIsLoaded(): void;\n}\n\nexport class IsLoadedCache {\n // Cache of `{ tag -> { fieldName -> Set<IsLoadedCachable> } }` to hold derived relations\n // we can selectively invalidate by walking from the mutated field to any downstream\n // cacheables.\n #smartCache: Record<string, Record<string, Set<IsLoadedCachable>>> = {};\n // A dumb cache for things that are hard selectively invalidate (o2m.get, recursive collections,\n // and custom references/collections), so any mutation resets these.\n #naiveCache = new Set<IsLoadedCachable>();\n // Counter to skip reactive hint walking when no smart cache sets are populated.\n #smartDirtySets = 0;\n // Counter to fast-path resetIsLoaded when the naive cache is empty.\n #naiveDirtySets = 0;\n\n /** Adds a ReactiveField/Relation/Collection to be invalidated when its dependencies change. */\n add(target: IsLoadedCachable): void {\n const meta = getMetadata(target.entity);\n const set = ((this.#smartCache[meta.tagName] ??= {})[target.fieldName] ??= new Set());\n if (set.size === 0) {\n this.#smartDirtySets++;\n }\n set.add(target);\n }\n\n addNaive(target: IsLoadedCachable): void {\n if (this.#naiveCache.size === 0) this.#naiveDirtySets++;\n this.#naiveCache.add(target);\n }\n\n /** Resets any in-memory #isLoaded/#isCached caches that depend on `entity.fieldName`. */\n resetIsLoaded(entity: Entity, fieldName: string): void {\n if (this.#smartDirtySets === 0 && this.#naiveDirtySets === 0) return;\n // Reset caches that we can deterministically find by walking the reactivity hints\n if (this.#smartDirtySets > 0) {\n this.#resetDownstreamReactables(getMetadata(entity), fieldName);\n }\n // We could use this to invalidate m2o.get, but it doesn't work for collections\n // with an orderBy, when the orderBy changes, so for now we use the blunt naiveCache.\n // const field = meta.allFields[fieldName];\n // if (field.kind === \"m2o\") {\n // const otherMeta = field.otherMetadata();\n // const set = this.smartCache[otherMeta.tagName]?.[field.otherFieldName];\n // if (set) {\n // for (const target of set) target.resetIsLoaded();\n // set.clear();\n // }\n // }\n if (this.#naiveCache.size > 0) {\n for (const target of this.#naiveCache.values()) target.resetIsLoaded();\n this.#naiveCache.clear();\n this.#naiveDirtySets--;\n }\n }\n\n /**\n * Given a `meta+field`, statically find all downstream Reactables, and if any of those\n * Reactables are a) in-memory already, and b) registered themselves as cached,\n * tell them to reset.\n */\n #resetDownstreamReactables(meta: EntityMetadata, fieldName: string): void {\n // These are reactables in other entities that are watching/reacting to this entity/fieldName\n const reactables = meta.reactablesIncludingReadOnlyByField!.get(fieldName);\n if (reactables === undefined) return;\n for (const r of reactables) {\n if (this.#smartDirtySets === 0) return;\n // I.e. we've written to Author.firstName, and this reactable in Book/otherMeta depends on it\n const otherMeta = getMetadata(r.cstr);\n // Find any cache entries for this cstr + name\n const set = this.#smartCache[otherMeta.tagName]?.[r.name];\n if (set?.size > 0) {\n for (const target of set) {\n target.resetIsLoaded();\n // Is this target itself a RF/RR? If so, transitively reset its cache as well.\n const otherMeta = getMetadata(target.entity);\n const otherField = otherMeta.allFields[target.fieldName];\n if (\"derived\" in otherField && otherField.derived) {\n this.#resetDownstreamReactables(otherMeta, otherField.fieldName);\n }\n }\n set.clear();\n this.#smartDirtySets--;\n }\n }\n }\n}\n"],"mappings":";;;;AA0BA,IAAa,gBAAb,MAA2B;CAIzB,cAAqE,CAAC;CAGtE,8BAAc,IAAI,IAAsB;CAExC,kBAAkB;CAElB,kBAAkB;;CAGlB,IAAI,QAAgC;EAClC,MAAM,OAAOA,uBAAAA,YAAY,OAAO,MAAM;EACtC,MAAM,MAAO,CAAC,KAAKC,YAAY,KAAK,aAAa,CAAC,EAAA,CAAG,OAAO,+BAAe,IAAI,IAAI;EACnF,IAAI,IAAI,SAAS,GACf,KAAKC;EAEP,IAAI,IAAI,MAAM;CAChB;CAEA,SAAS,QAAgC;EACvC,IAAI,KAAKC,YAAY,SAAS,GAAG,KAAKC;EACtC,KAAKD,YAAY,IAAI,MAAM;CAC7B;;CAGA,cAAc,QAAgB,WAAyB;EACrD,IAAI,KAAKD,oBAAoB,KAAK,KAAKE,oBAAoB,GAAG;EAE9D,IAAI,KAAKF,kBAAkB,GACzB,KAAKG,2BAA2BL,uBAAAA,YAAY,MAAM,GAAG,SAAS;EAahE,IAAI,KAAKG,YAAY,OAAO,GAAG;GAC7B,KAAK,MAAM,UAAU,KAAKA,YAAY,OAAO,GAAG,OAAO,cAAc;GACrE,KAAKA,YAAY,MAAM;GACvB,KAAKC;EACP;CACF;;;;;;CAOA,2BAA2B,MAAsB,WAAyB;EAExE,MAAM,aAAa,KAAK,mCAAoC,IAAI,SAAS;EACzE,IAAI,eAAe,KAAA,GAAW;EAC9B,KAAK,MAAM,KAAK,YAAY;GAC1B,IAAI,KAAKF,oBAAoB,GAAG;GAEhC,MAAM,YAAYF,uBAAAA,YAAY,EAAE,IAAI;GAEpC,MAAM,MAAM,KAAKC,YAAY,UAAU,QAAQ,GAAG,EAAE;GACpD,IAAI,KAAK,OAAO,GAAG;IACjB,KAAK,MAAM,UAAU,KAAK;KACxB,OAAO,cAAc;KAErB,MAAM,YAAYD,uBAAAA,YAAY,OAAO,MAAM;KAC3C,MAAM,aAAa,UAAU,UAAU,OAAO;KAC9C,IAAI,aAAa,cAAc,WAAW,SACxC,KAAKK,2BAA2B,WAAW,WAAW,SAAS;IAEnE;IACA,IAAI,MAAM;IACV,KAAKH;GACP;EACF;CACF;AACF"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"IsLoadedCache.d.cts","names":[],"sources":["../src/IsLoadedCache.ts"],"mappings":";;;;;;;;;;;;;;;;;;UAmBiB;EACf,QAAQ;EACR;EACA;EACA;;cAGW;;;EAcX,IAAI,QAAQ;EASZ,SAAS,QAAQ;;EAMjB,cAAc,QAAQ,QAAQ"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"IsLoadedCache.d.mts","names":[],"sources":["../src/IsLoadedCache.ts"],"mappings":";;;;;;;;;;;;;;;;;;UAmBiB;EACf,QAAQ;EACR;EACA;EACA;;cAGW;;;EAcX,IAAI,QAAQ;EASZ,SAAS,QAAQ;;EAMjB,cAAc,QAAQ,QAAQ"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"IsLoadedCache.js","names":["#smartCache","#smartDirtySets","#naiveCache","#naiveDirtySets","#resetDownstreamReactables"],"sources":["../src/IsLoadedCache.ts"],"sourcesContent":["import { type Entity } from \"./Entity.ts\";\nimport { type EntityMetadata, getMetadata } from \"./EntityMetadata.ts\";\n\n/**\n * Interface for our relations that have dynamic & expensive `isLoaded` checks.\n *\n * ...and also `OneToManyCollection.get` calls.\n *\n * The primary m2o/o2m/m2m relations all have trivial `isLoaded` checks--are they\n * loaded or not.\n *\n * But for \"composite relations\", i.e. a ReactiveField or ReactiveRelation whose\n * \"load-ness\" is calculated by evaluating its load hint across a subgraph of entities\n * & relations, load-ness can be more dynamic true-then-false, as its subgraph changes.\n *\n * To avoid performance issues (see https://github.com/joist-orm/joist-orm/issues/1166),\n * we cache this dynamic/expensive `isLoaded` checks, and then do targeted, reactivity-driven\n * cache invalidation whenever relations are mutated (via a hook in `setField`).\n */\nexport interface IsLoadedCachable {\n entity: Entity;\n fieldName: string;\n isLoaded: boolean;\n resetIsLoaded(): void;\n}\n\nexport class IsLoadedCache {\n // Cache of `{ tag -> { fieldName -> Set<IsLoadedCachable> } }` to hold derived relations\n // we can selectively invalidate by walking from the mutated field to any downstream\n // cacheables.\n #smartCache: Record<string, Record<string, Set<IsLoadedCachable>>> = {};\n // A dumb cache for things that are hard selectively invalidate (o2m.get, recursive collections,\n // and custom references/collections), so any mutation resets these.\n #naiveCache = new Set<IsLoadedCachable>();\n // Counter to skip reactive hint walking when no smart cache sets are populated.\n #smartDirtySets = 0;\n // Counter to fast-path resetIsLoaded when the naive cache is empty.\n #naiveDirtySets = 0;\n\n /** Adds a ReactiveField/Relation/Collection to be invalidated when its dependencies change. */\n add(target: IsLoadedCachable): void {\n const meta = getMetadata(target.entity);\n const set = ((this.#smartCache[meta.tagName] ??= {})[target.fieldName] ??= new Set());\n if (set.size === 0) {\n this.#smartDirtySets++;\n }\n set.add(target);\n }\n\n addNaive(target: IsLoadedCachable): void {\n if (this.#naiveCache.size === 0) this.#naiveDirtySets++;\n this.#naiveCache.add(target);\n }\n\n /** Resets any in-memory #isLoaded/#isCached caches that depend on `entity.fieldName`. */\n resetIsLoaded(entity: Entity, fieldName: string): void {\n if (this.#smartDirtySets === 0 && this.#naiveDirtySets === 0) return;\n // Reset caches that we can deterministically find by walking the reactivity hints\n if (this.#smartDirtySets > 0) {\n this.#resetDownstreamReactables(getMetadata(entity), fieldName);\n }\n // We could use this to invalidate m2o.get, but it doesn't work for collections\n // with an orderBy, when the orderBy changes, so for now we use the blunt naiveCache.\n // const field = meta.allFields[fieldName];\n // if (field.kind === \"m2o\") {\n // const otherMeta = field.otherMetadata();\n // const set = this.smartCache[otherMeta.tagName]?.[field.otherFieldName];\n // if (set) {\n // for (const target of set) target.resetIsLoaded();\n // set.clear();\n // }\n // }\n if (this.#naiveCache.size > 0) {\n for (const target of this.#naiveCache.values()) target.resetIsLoaded();\n this.#naiveCache.clear();\n this.#naiveDirtySets--;\n }\n }\n\n /**\n * Given a `meta+field`, statically find all downstream Reactables, and if any of those\n * Reactables are a) in-memory already, and b) registered themselves as cached,\n * tell them to reset.\n */\n #resetDownstreamReactables(meta: EntityMetadata, fieldName: string): void {\n // These are reactables in other entities that are watching/reacting to this entity/fieldName\n const reactables = meta.reactablesIncludingReadOnlyByField!.get(fieldName);\n if (reactables === undefined) return;\n for (const r of reactables) {\n if (this.#smartDirtySets === 0) return;\n // I.e. we've written to Author.firstName, and this reactable in Book/otherMeta depends on it\n const otherMeta = getMetadata(r.cstr);\n // Find any cache entries for this cstr + name\n const set = this.#smartCache[otherMeta.tagName]?.[r.name];\n if (set?.size > 0) {\n for (const target of set) {\n target.resetIsLoaded();\n // Is this target itself a RF/RR? If so, transitively reset its cache as well.\n const otherMeta = getMetadata(target.entity);\n const otherField = otherMeta.allFields[target.fieldName];\n if (\"derived\" in otherField && otherField.derived) {\n this.#resetDownstreamReactables(otherMeta, otherField.fieldName);\n }\n }\n set.clear();\n this.#smartDirtySets--;\n }\n }\n }\n}\n"],"mappings":";;;AA0BA,IAAa,gBAAb,MAA2B;CAIzB,cAAqE,CAAC;CAGtE,8BAAc,IAAI,IAAsB;CAExC,kBAAkB;CAElB,kBAAkB;;CAGlB,IAAI,QAAgC;EAClC,MAAM,OAAO,YAAY,OAAO,MAAM;EACtC,MAAM,MAAO,CAAC,KAAKA,YAAY,KAAK,aAAa,CAAC,EAAA,CAAG,OAAO,+BAAe,IAAI,IAAI;EACnF,IAAI,IAAI,SAAS,GACf,KAAKC;EAEP,IAAI,IAAI,MAAM;CAChB;CAEA,SAAS,QAAgC;EACvC,IAAI,KAAKC,YAAY,SAAS,GAAG,KAAKC;EACtC,KAAKD,YAAY,IAAI,MAAM;CAC7B;;CAGA,cAAc,QAAgB,WAAyB;EACrD,IAAI,KAAKD,oBAAoB,KAAK,KAAKE,oBAAoB,GAAG;EAE9D,IAAI,KAAKF,kBAAkB,GACzB,KAAKG,2BAA2B,YAAY,MAAM,GAAG,SAAS;EAahE,IAAI,KAAKF,YAAY,OAAO,GAAG;GAC7B,KAAK,MAAM,UAAU,KAAKA,YAAY,OAAO,GAAG,OAAO,cAAc;GACrE,KAAKA,YAAY,MAAM;GACvB,KAAKC;EACP;CACF;;;;;;CAOA,2BAA2B,MAAsB,WAAyB;EAExE,MAAM,aAAa,KAAK,mCAAoC,IAAI,SAAS;EACzE,IAAI,eAAe,KAAA,GAAW;EAC9B,KAAK,MAAM,KAAK,YAAY;GAC1B,IAAI,KAAKF,oBAAoB,GAAG;GAEhC,MAAM,YAAY,YAAY,EAAE,IAAI;GAEpC,MAAM,MAAM,KAAKD,YAAY,UAAU,QAAQ,GAAG,EAAE;GACpD,IAAI,KAAK,OAAO,GAAG;IACjB,KAAK,MAAM,UAAU,KAAK;KACxB,OAAO,cAAc;KAErB,MAAM,YAAY,YAAY,OAAO,MAAM;KAC3C,MAAM,aAAa,UAAU,UAAU,OAAO;KAC9C,IAAI,aAAa,cAAc,WAAW,SACxC,KAAKI,2BAA2B,WAAW,WAAW,SAAS;IAEnE;IACA,IAAI,MAAM;IACV,KAAKH;GACP;EACF;CACF;AACF"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"JoinRows.cjs","names":["#reactToChange","keyToTaggedId","#dbValue","keyToNumber","getEmInternalApi","getBaseAndSelfMetas","#doAdd","#doRemove"],"sources":["../src/JoinRows.ts"],"sourcesContent":["import { type Entity } from \"./Entity.ts\";\nimport { getEmInternalApi } from \"./EntityManager.ts\";\nimport { type EntityMetadata, getBaseAndSelfMetas } from \"./EntityMetadata.ts\";\nimport { type EnumMetadata } from \"./EnumMetadata.ts\";\nimport { keyToNumber, keyToTaggedId } from \"./keys.ts\";\nimport { type ReactionsManager } from \"./ReactionsManager.ts\";\nimport { type JoinRowTodo } from \"./Todo.ts\";\nimport { remove } from \"./utils.ts\";\n\n/**\n * A simplified interface for ManyToManyCollection-like relations.\n *\n * Specifically lets ReactiveManyToMany & ReactiveManyToManyOtherSide use JoinRows\n * as if they were full-fledged m2m relations.\n *\n * The \"other\" side of the join table is usually a second entity, but for `EnumCollection`s\n * (i.e. `Publisher.logoColors`) it is an enum table; in that case `otherEnum` is set and the\n * other column's value is the enum's numeric id rather than an `Entity` (there is also no\n * `otherMeta`/`otherFieldName`, since enums have no reverse collection to keep in sync).\n */\nexport type ManyToManyLike = {\n entity: Entity;\n joinTableName: string;\n columnName: string;\n otherColumnName: string;\n fieldName: string;\n meta: EntityMetadata;\n /** Undefined when the other side is an enum. */\n otherFieldName?: string;\n /** Undefined when the other side is an enum. */\n otherMeta?: EntityMetadata;\n /** Set when the other side is an enum table, for mapping enum codes <-> their numeric ids. */\n otherEnum?: EnumMetadata<any, any, number>;\n /** Whether the join table has a surrogate `id` PK; if false the FK pair is the composite PK. */\n hasJoinTableId: boolean;\n};\n\n/** The value of a join row's column: an `Entity`, or an enum's numeric id for `EnumCollection`s. */\nexport type JoinColumnValue = Entity | number;\n\n/** Whether a join column points at a not-yet-inserted entity (enum ids are never \"new\"). */\nfunction isNewColumn(value: JoinColumnValue): boolean {\n return typeof value !== \"number\" && value.isNewEntity;\n}\n\n/** A small holder around m2m join rows, which we treat as psuedo-entities. */\nexport class JoinRows {\n // The in-memory rows for our m2m table.\n private readonly rows: JoinRow[] = [];\n private readonly index: ManyToManyIndex;\n\n constructor(\n // This could be either side of the m2m relation, depending on which is accessed first.\n // Regardless of which m2m side, we still have a single `JoinRows` instance in memory per m2m table.\n readonly m2m: ManyToManyLike,\n private rm: ReactionsManager,\n ) {\n this.index = new ManyToManyIndex(m2m);\n }\n\n /** Adds a new join row to this table. */\n addNew(m2m: ManyToManyLike, e1: Entity, e2: JoinColumnValue): void {\n if (!e1) throw new Error(`Cannot add a m2m row with an entity that is ${e1}`);\n if (!e2) throw new Error(`Cannot add a m2m row with an entity that is ${e2}`);\n const existing = this.index.get(m2m, e1, e2);\n if (existing) {\n existing.deleted = false;\n existing.op = JoinRowOperation.Pending;\n } else {\n const row = {\n op: JoinRowOperation.Pending,\n id: undefined,\n persisted: false,\n columns: { [m2m.columnName]: e1, [m2m.otherColumnName]: e2 },\n } satisfies JoinRow;\n this.rows.push(row);\n this.index.add(m2m, e1, e2, row);\n }\n this.#reactToChange(m2m, e1, e2);\n }\n\n /** Adds a new remove to this table. */\n addRemove(m2m: ManyToManyLike, e1: Entity, e2: JoinColumnValue): void {\n const existing = this.index.get(m2m, e1, e2);\n if (existing) {\n if (!existing.persisted) {\n // It was only added in-memory and never persisted, so just drop it\n remove(this.rows, existing);\n this.index.remove(existing);\n } else {\n existing.deleted = true;\n }\n existing.op = JoinRowOperation.Pending;\n } else {\n // We're removing against an unloaded collection, so assume the row exists in the database\n // (persisted: true) and queue a delete; the delete keys off the (col1, col2) composite.\n const row = {\n op: JoinRowOperation.Pending,\n id: undefined,\n persisted: true,\n columns: { [m2m.columnName]: e1, [m2m.otherColumnName]: e2 },\n deleted: true,\n } satisfies JoinRow;\n this.rows.push(row);\n this.index.add(m2m, e1, e2, row);\n }\n this.#reactToChange(m2m, e1, e2);\n }\n\n /** Return any \"old values\" for a m2m collection that might need reactivity checks. */\n removedFor(m2m: ManyToManyLike, e1: Entity): JoinColumnValue[] {\n const { otherColumnName } = m2m;\n // I.e. if we did `t1.books.remove(b1)` find all join rows that have\n // `tag_id=t1`, are marked for deletion, and then `.map` them to the removed book.\n const removedRows = this.index.getOthers(m2m.columnName, e1).filter((r) => r.deleted);\n return removedRows.map((r) => r.columns[otherColumnName]);\n }\n\n addedFor(m2m: ManyToManyLike, e1: Entity): JoinColumnValue[] {\n const { otherColumnName } = m2m;\n const addedRows = this.index\n .getOthers(m2m.columnName, e1)\n .filter(\n (r) =>\n ((!r.persisted && r.op === JoinRowOperation.Pending) || r.op === JoinRowOperation.Flushed) &&\n r.deleted !== true,\n );\n return addedRows.map((r) => r.columns[otherColumnName]);\n }\n\n /** Adds an existing join row to this table. */\n addPreloadedRow(m2m: ManyToManyLike, id: number | undefined, e1: Entity, e2: JoinColumnValue): void {\n const existing = this.index.get(m2m, e1, e2);\n if (existing) {\n // Treat any existing WIP change as source-of-truth, so leave it alone\n } else {\n const row = {\n op: JoinRowOperation.Pending,\n id,\n persisted: true,\n columns: { [m2m.columnName]: e1, [m2m.otherColumnName]: e2 },\n } satisfies JoinRow;\n this.rows.push(row);\n this.index.add(m2m, e1, e2, row);\n }\n }\n\n /** Look up/create our internal JoinRow psuedo-entities for the db rows. */\n async loadRows(tuples: [string, string][], dbRows: any[]): Promise<void> {\n const { em } = this.m2m.entity;\n const { columnName: column1, otherColumnName: column2, meta: meta1, otherMeta: meta2, otherEnum } = this.m2m;\n\n const oneIds: string[] = [];\n // Tagged ids for an entity other-side, or raw enum ids for an enum other-side.\n const twoVals: JoinColumnValue[] = [];\n for (const dbRow of dbRows) {\n oneIds.push(keyToTaggedId(meta1, dbRow[column1])!);\n twoVals.push(\n otherEnum ? (dbRow[column2] as number) : (em.getEntity(keyToTaggedId(meta2!, dbRow[column2])!) as any),\n );\n }\n\n // Make sure we have entities in memory for all the joined-to tables. The enum side has no\n // entities to load; the entity sides do (and `twoVals` is re-resolved to entities below).\n await Promise.all([\n em.loadAll(meta1.cstr, oneIds),\n otherEnum\n ? Promise.resolve([])\n : em.loadAll(\n meta2!.cstr,\n dbRows.map((dbRow) => keyToTaggedId(meta2!, dbRow[column2])!),\n ),\n ]);\n\n // If we're doing a em.refresh/reload, we need to watch for rows that are no longer here. For an\n // enum other-side, only persisted rows are delete-candidates (pending in-memory adds are kept,\n // since `EnumCollection` relies on `JoinRows` to hold them rather than re-asserting on load).\n const existingRows = new Set<JoinRow>();\n for (const [columnName, id] of tuples) {\n const others = this.index.getOthers(columnName, em.getEntity(id)!);\n for (const row of others) if (!otherEnum || row.persisted) existingRows.add(row);\n }\n\n let i = 0;\n for (const dbRow of dbRows) {\n const e1 = em.getEntity(oneIds[i])!;\n const e2 = otherEnum ? (dbRow[column2] as number) : em.getEntity(keyToTaggedId(meta2!, dbRow[column2])!)!;\n i++;\n let row = this.index.get(this.m2m, e1, e2);\n if (!row) {\n row = {\n op: JoinRowOperation.Completed,\n id: dbRow.id,\n persisted: true,\n columns: { [column1]: e1, [column2]: e2 },\n created_at: dbRow.created_at,\n };\n this.rows.push(row);\n this.index.add(this.m2m, e1, e2, row);\n } else {\n // If a placeholder row was created while a ManyToManyCollection was unloaded, and we find it during\n // a subsequent load/query, update its id to be what is in the database and mark it persisted.\n row.id = dbRow.id;\n row.persisted = true;\n // Mark this row as still valid\n existingRows.delete(row);\n }\n }\n\n // Mark all no-longer-there rows as deleted\n for (const row of existingRows) row.deleted = true;\n }\n\n getOthers(columnName: string, entity: Entity): JoinColumnValue[] {\n const others = this.index.getOthers(columnName, entity);\n if (others.length === 0) return [];\n const [c1, c2] = Object.keys(others[0].columns);\n const c = others[0].columns[c1] === entity ? c2 : c1;\n return others.filter((o) => !o.deleted).map((row) => row.columns[c]);\n }\n\n /** Drops all in-memory rows where `entity` is on `columnName`, e.g. when it is being deleted. */\n removeAllFor(columnName: string, entity: Entity): void {\n for (const row of this.index.getOthers(columnName, entity)) {\n remove(this.rows, row);\n this.index.remove(row);\n }\n }\n\n /** Drops a single `(e1, e2)` row without queuing a flush, e.g. when mirroring another em's removal. */\n removePreloadedRow(m2m: ManyToManyLike, e1: Entity, e2: JoinColumnValue): void {\n const row = this.index.get(m2m, e1, e2);\n if (row) {\n remove(this.rows, row);\n this.index.remove(row);\n }\n }\n\n /** Scans our `rows` for newly-added/newly-deleted rows that need `INSERT`s/`UPDATE`s. */\n toTodo(): JoinRowTodo | undefined {\n const newRows = this.rows.filter((r) => !r.persisted && r.deleted !== true && r.op === \"pending\");\n const deletedRows = this.rows.filter((r) => r.persisted && r.deleted === true && r.op === \"pending\");\n if (newRows.length === 0 && deletedRows.length === 0) {\n return undefined;\n }\n return {\n m2m: this.m2m,\n newRows,\n deletedRows,\n resetAfterFlushed: () => {\n for (const row of this.rows) {\n if (row.op === JoinRowOperation.Pending || row.op === JoinRowOperation.Flushed)\n row.op = JoinRowOperation.Completed;\n }\n },\n // The driver flushes pure (int, int) FK pairs; resolve them here so it never has to know\n // whether a column points at an entity (use its id) or an enum (its value is already the id).\n dbValue: (row, columnName) => this.#dbValue(row, columnName),\n isNew: (row, columnName) => isNewColumn(row.columns[columnName]),\n };\n }\n\n get hasChanges() {\n return this.rows.some(({ op }) => op === JoinRowOperation.Pending || op === JoinRowOperation.Flushed);\n }\n\n /** The db int value for `row`'s `columnName`: an entity's id, or (for enums) the enum's id itself. */\n #dbValue(row: JoinRow, columnName: string): number {\n const value = row.columns[columnName];\n if (typeof value === \"number\") return value;\n const meta = columnName === this.m2m.columnName ? this.m2m.meta : this.m2m.otherMeta!;\n return keyToNumber(meta, value.idTagged)!;\n }\n\n /**\n * Invalidates caches & queues reactivity for a join-row change.\n *\n * The owning entity (`e1`) always reacts; the \"other\" side only reacts when it is an entity,\n * since enum other-sides have no `em`/reverse-field to keep in sync.\n */\n #reactToChange(m2m: ManyToManyLike, e1: Entity, e2: JoinColumnValue): void {\n const { em } = this.m2m.entity;\n const api = getEmInternalApi(e1.em);\n api.isLoadedCache.resetIsLoaded(e1, m2m.fieldName);\n this.rm.queueDownstreamReactables(e1, m2m.fieldName);\n if (getBaseAndSelfMetas(e1).some((meta) => meta.config.__data.touchOnChange.has(m2m.fieldName))) {\n em.touch(e1);\n }\n if (!m2m.otherEnum) {\n const other = e2 as Entity;\n const otherFieldName = m2m.otherFieldName!;\n api.isLoadedCache.resetIsLoaded(other, otherFieldName);\n this.rm.queueDownstreamReactables(other, otherFieldName);\n if (getBaseAndSelfMetas(other).some((meta) => meta.config.__data.touchOnChange.has(otherFieldName))) {\n em.touch(other);\n }\n }\n }\n}\n\n/**\n * A \"psuedo-entity\" for a join row.\n *\n * We treat this as a special entity, i.e. it has two \"relations\" to each entity for the current\n * row, an optional surrogate `id` primary key, and an optional `created_at` column.\n *\n * These rows are immutable, i.e. once created we don't change either FK, and instead make\n * collection changes only by inserting new rows and deleting old rows.\n *\n * This makes the column1+column2 combination a composite key. For id-less join tables, that\n * composite is the actual primary key and `id` is always undefined.\n */\nexport interface JoinRow {\n /**\n * Whether our relation has been processed or not.\n *\n * - `pending` means we've not flushed it to the Database\n * - `flushed` means we've flushed but `em.flush` hasn't fully completed yet, likely due to AsyncReactiveField calcs\n * - `completed` means we've been flushed and `em.flush` has completed\n */\n op: JoinRowOperation;\n /** The surrogate key for id-ful join tables; always undefined for id-less tables. */\n id: number | undefined;\n /**\n * Whether this row exists (or is assumed to exist) in the database.\n *\n * This is orthogonal to `op` (the flush lifecycle) and is what distinguishes a pending insert\n * from a pending delete: a `pending` row that is `!persisted` is a pending INSERT (added in\n * memory, not yet in the db), while a `pending` row that is `persisted` is a pending DELETE\n * (in the db, marked `deleted`). `op` alone cannot tell these apart, because both inserts and\n * deletes walk the same `pending -> flushed -> completed` progression.\n *\n * We track this as its own flag rather than inferring it from `id` being set/unset, because\n * id-less join tables (whose PK is just the composite of the two FKs) never have an `id` — so\n * `id === undefined` would be ambiguous. `persisted` is the id-agnostic generalization of the\n * `id`-is-set check that id-ful tables historically relied on.\n *\n * It must survive add/remove/re-add sequences: e.g. loading a row (persisted), removing it\n * (pending delete), then re-adding it (`deleted` flipped back to false, `op` back to `pending`)\n * leaves a `pending && !deleted` row that looks identical to a fresh insert — but it is still in\n * the db, so a subsequent remove must issue a DELETE, which only `persisted` can tell us.\n */\n persisted: boolean;\n /** Maps each FK column to its value: an `Entity`, or (for `EnumCollection`s) an enum's numeric id. */\n columns: Record<string, JoinColumnValue>;\n created_at?: Date;\n deleted?: boolean;\n}\n\n/** An enum to track our insert/delete state progression. */\nexport enum JoinRowOperation {\n Pending = \"pending\",\n Flushed = \"flushed\",\n Completed = \"completed\",\n}\n\n/** Keep an in-memory index to avoid sequentially scanning `rows`. */\nclass ManyToManyIndex {\n private indexes: Record<string, Map<JoinColumnValue, Map<JoinColumnValue, JoinRow>>> = {};\n\n constructor(private readonly m2m: ManyToManyLike) {\n this.indexes[m2m.columnName] = new Map();\n this.indexes[m2m.otherColumnName] = new Map();\n }\n\n add(m2m: ManyToManyLike, e1: JoinColumnValue, e2: JoinColumnValue, value: JoinRow): void {\n // Store both e1+e2 => value and e2+e1 => value so we can do lookups from either side\n this.#doAdd(this.indexes[m2m.columnName], e1, e2, value);\n this.#doAdd(this.indexes[m2m.otherColumnName], e2, e1, value);\n }\n\n remove(value: JoinRow): void {\n const [[column1, e1], [column2, e2]] = Object.entries(value.columns);\n this.#doRemove(this.indexes[column1], e1, e2);\n this.#doRemove(this.indexes[column2], e2, e1);\n }\n\n get(m2m: ManyToManyLike, e1: JoinColumnValue, e2: JoinColumnValue): JoinRow | undefined {\n return this.indexes[m2m.columnName].get(e1)?.get(e2);\n }\n\n /** Cheat and use the index to return \"the other entities\" for `entity`. */\n getOthers(columnName: string, entity: JoinColumnValue): JoinRow[] {\n // It's empty m2m collection won't have any other entities, and so no index entries\n const map = this.indexes[columnName].get(entity);\n if (!map) return [];\n // Sort for a stable order regardless of how many batches contributed rows — the underlying\n // Map preserves insertion order, which depends on DataLoader timing and is non-deterministic\n // across processes. New rows (no key yet) sort last.\n const rows = Array.from(map.values());\n if (this.m2m.hasJoinTableId) {\n // Sort by join-row id.\n return rows.sort((a, b) => (a.id ?? Infinity) - (b.id ?? Infinity));\n }\n // Id-less tables have no surrogate id, so sort by the other side's id.\n const otherColumn = columnName === this.m2m.columnName ? this.m2m.otherColumnName : this.m2m.columnName;\n if (this.m2m.otherEnum && otherColumn === this.m2m.otherColumnName) {\n // The other side is an enum, so its column value is already its numeric id.\n return rows.sort((a, b) => (a.columns[otherColumn] as number) - (b.columns[otherColumn] as number));\n }\n const otherMeta = columnName === this.m2m.columnName ? this.m2m.otherMeta! : this.m2m.meta;\n const key = (r: JoinRow) => {\n const other = r.columns[otherColumn] as Entity;\n return other.isNewEntity ? Infinity : keyToNumber(otherMeta, other.id)!;\n };\n return rows.sort((a, b) => key(a) - key(b));\n }\n\n #doAdd(\n index: Map<JoinColumnValue, Map<JoinColumnValue, JoinRow>>,\n e1: JoinColumnValue,\n e2: JoinColumnValue,\n value: JoinRow,\n ): void {\n const map = index.get(e1) ?? new Map();\n if (map.size === 0) index.set(e1, map);\n map.set(e2, value);\n }\n\n #doRemove(\n index: Map<JoinColumnValue, Map<JoinColumnValue, JoinRow>>,\n e1: JoinColumnValue,\n e2: JoinColumnValue,\n ): void {\n index.get(e1)?.delete(e2);\n }\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"JoinRows.d.cts","names":[],"sources":["../src/JoinRows.ts"],"mappings":";;;;;;;;;;;;;;;;;KAoBY;EACV,QAAQ;EACR;EACA;EACA;EACA;EACA,MAAM;;EAEN;;EAEA,YAAY;;EAEZ,YAAY;;EAEZ;;;KAIU,kBAAkB;;cAQjB;;WAQA,KAAK;UACN;mBAPO;mBACA;EAEjB,YAGW,KAAK,gBACN,IAAI;;EAMd,OAAO,KAAK,gBAAgB,IAAI,QAAQ,IAAI;;EAqB5C,UAAU,KAAK,gBAAgB,IAAI,QAAQ,IAAI;;EA4B/C,WAAW,KAAK,gBAAgB,IAAI,SAAS;EAQ7C,SAAS,KAAK,gBAAgB,IAAI,SAAS;;EAa3C,gBAAgB,KAAK,gBAAgB,wBAAwB,IAAI,QAAQ,IAAI;;EAiBvE,SAAS,4BAA4B,gBAAgB;EAiE3D,UAAU,oBAAoB,QAAQ,SAAS;;EAS/C,aAAa,oBAAoB,QAAQ;;EAQzC,mBAAmB,KAAK,gBAAgB,IAAI,QAAQ,IAAI;;EASxD,UAAU;MAuBN;;;;;;;;;;;;;;UAkDW;;;;;;;;EAQf,IAAI;;EAEJ;;;;;;;;;;;;;;;;;;;;EAoBA;;EAEA,SAAS,eAAe;EACxB,aAAa;EACb;;;aAIU;EACV;EACA;EACA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"JoinRows.d.mts","names":[],"sources":["../src/JoinRows.ts"],"mappings":";;;;;;;;;;;;;;;;;KAoBY;EACV,QAAQ;EACR;EACA;EACA;EACA;EACA,MAAM;;EAEN;;EAEA,YAAY;;EAEZ,YAAY;;EAEZ;;;KAIU,kBAAkB;;cAQjB;;WAQA,KAAK;UACN;mBAPO;mBACA;EAEjB,YAGW,KAAK,gBACN,IAAI;;EAMd,OAAO,KAAK,gBAAgB,IAAI,QAAQ,IAAI;;EAqB5C,UAAU,KAAK,gBAAgB,IAAI,QAAQ,IAAI;;EA4B/C,WAAW,KAAK,gBAAgB,IAAI,SAAS;EAQ7C,SAAS,KAAK,gBAAgB,IAAI,SAAS;;EAa3C,gBAAgB,KAAK,gBAAgB,wBAAwB,IAAI,QAAQ,IAAI;;EAiBvE,SAAS,4BAA4B,gBAAgB;EAiE3D,UAAU,oBAAoB,QAAQ,SAAS;;EAS/C,aAAa,oBAAoB,QAAQ;;EAQzC,mBAAmB,KAAK,gBAAgB,IAAI,QAAQ,IAAI;;EASxD,UAAU;MAuBN;;;;;;;;;;;;;;UAkDW;;;;;;;;EAQf,IAAI;;EAEJ;;;;;;;;;;;;;;;;;;;;EAoBA;;EAEA,SAAS,eAAe;EACxB,aAAa;EACb;;;aAIU;EACV;EACA;EACA"}