@blac/core 2.1.0 → 2.1.2

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 (391) hide show
  1. package/README.md +19 -29
  2. package/dist/StateContainer-BUyuxKb3.cjs +667 -0
  3. package/dist/StateContainer-BUyuxKb3.cjs.map +1 -0
  4. package/dist/StateContainer-B_7UHc3I.js +632 -0
  5. package/dist/StateContainer-B_7UHc3I.js.map +1 -0
  6. package/dist/StateContainer-Bh2ipNYj.js +632 -0
  7. package/dist/StateContainer-Bh2ipNYj.js.map +1 -0
  8. package/dist/StateContainer-ClzwKnQZ.cjs +667 -0
  9. package/dist/StateContainer-ClzwKnQZ.cjs.map +1 -0
  10. package/dist/StateContainer-CwByTd5L.js +656 -0
  11. package/dist/StateContainer-CwByTd5L.js.map +1 -0
  12. package/dist/StateContainer-D2b10eR4.cjs +691 -0
  13. package/dist/StateContainer-D2b10eR4.cjs.map +1 -0
  14. package/dist/StateContainer-DiQATvZh.js +632 -0
  15. package/dist/StateContainer-DiQATvZh.js.map +1 -0
  16. package/dist/StateContainer-j16zciex.cjs +667 -0
  17. package/dist/StateContainer-j16zciex.cjs.map +1 -0
  18. package/dist/{StateContainerRegistry-CSNm2Ws5.cjs → StateContainerRegistry-141uHhtF.cjs} +300 -397
  19. package/dist/StateContainerRegistry-141uHhtF.cjs.map +1 -0
  20. package/dist/StateContainerRegistry-B6O6cfJd.cjs +903 -0
  21. package/dist/StateContainerRegistry-B6O6cfJd.cjs.map +1 -0
  22. package/dist/{StateContainerRegistry-DVIBTxGZ.js → StateContainerRegistry-BH7aOMWV.js} +299 -406
  23. package/dist/StateContainerRegistry-BH7aOMWV.js.map +1 -0
  24. package/dist/StateContainerRegistry-BX-DlHXO.js +747 -0
  25. package/dist/StateContainerRegistry-BX-DlHXO.js.map +1 -0
  26. package/dist/StateContainerRegistry-Bf5VuVjm.js +747 -0
  27. package/dist/StateContainerRegistry-Bf5VuVjm.js.map +1 -0
  28. package/dist/{StateContainerRegistry-Dj77cok9.js → StateContainerRegistry-BsH_s0pJ.js} +303 -413
  29. package/dist/StateContainerRegistry-BsH_s0pJ.js.map +1 -0
  30. package/dist/StateContainerRegistry-BvSRfhKv.cjs +866 -0
  31. package/dist/StateContainerRegistry-BvSRfhKv.cjs.map +1 -0
  32. package/dist/StateContainerRegistry-C8jxrcqk.cjs +866 -0
  33. package/dist/StateContainerRegistry-C8jxrcqk.cjs.map +1 -0
  34. package/dist/{StateContainerRegistry-lIwo-0m3.cjs → StateContainerRegistry-CBLeHObO.cjs} +326 -418
  35. package/dist/StateContainerRegistry-CBLeHObO.cjs.map +1 -0
  36. package/dist/StateContainerRegistry-CrTtRX5V.js +772 -0
  37. package/dist/StateContainerRegistry-CrTtRX5V.js.map +1 -0
  38. package/dist/StateContainerRegistry-DjQQtlCW.cjs +870 -0
  39. package/dist/StateContainerRegistry-DjQQtlCW.cjs.map +1 -0
  40. package/dist/{StateContainerRegistry-D9BIRjwv.cjs → StateContainerRegistry-MkT0W4C2.cjs} +322 -411
  41. package/dist/StateContainerRegistry-MkT0W4C2.cjs.map +1 -0
  42. package/dist/StateContainerRegistry-gQbEutkN.js +751 -0
  43. package/dist/StateContainerRegistry-gQbEutkN.js.map +1 -0
  44. package/dist/{StateContainerRegistry-CvBOhAT2.js → StateContainerRegistry-vWgsD-RP.js} +277 -392
  45. package/dist/StateContainerRegistry-vWgsD-RP.js.map +1 -0
  46. package/dist/config.d.cts +8 -8
  47. package/dist/config.d.ts +8 -8
  48. package/dist/constants.d.cts +20 -28
  49. package/dist/constants.d.ts +20 -28
  50. package/dist/core/Cubit.d.ts +14 -10
  51. package/dist/core/StateContainer.d.ts +89 -62
  52. package/dist/core/StateContainerRegistry.d.ts +89 -166
  53. package/dist/core/meta.d.ts +37 -47
  54. package/dist/core/onActivated.d.ts +10 -0
  55. package/dist/core/symbols.d.ts +26 -1
  56. package/dist/decorators/blac.d.ts +38 -28
  57. package/dist/{acquire-B1LYXSGj.js → ensure-Bi_yXk6f.js} +16 -5
  58. package/dist/ensure-Bi_yXk6f.js.map +1 -0
  59. package/dist/{ensure-r1C_7K6_.cjs → ensure-BjhbDW8Z.cjs} +203 -160
  60. package/dist/ensure-BjhbDW8Z.cjs.map +1 -0
  61. package/dist/{ensure-BSJHkUNX.js → ensure-BnVyd6s4.js} +297 -122
  62. package/dist/ensure-BnVyd6s4.js.map +1 -0
  63. package/dist/{acquire-BZIs6tpN.cjs → ensure-Bx41d-il.cjs} +23 -6
  64. package/dist/ensure-Bx41d-il.cjs.map +1 -0
  65. package/dist/{acquire-BRIJVJaA.js → ensure-C7UQ_mKM.js} +16 -5
  66. package/dist/ensure-C7UQ_mKM.js.map +1 -0
  67. package/dist/{ensure-B59ri8oo.js → ensure-CneMkpbI.js} +298 -122
  68. package/dist/ensure-CneMkpbI.js.map +1 -0
  69. package/dist/{acquire-BdsVZBSe.js → ensure-CwtQVTam.js} +16 -5
  70. package/dist/ensure-CwtQVTam.js.map +1 -0
  71. package/dist/{ensure-B2DYCbbI.cjs → ensure-D15vGnk5.cjs} +328 -123
  72. package/dist/ensure-D15vGnk5.cjs.map +1 -0
  73. package/dist/{acquire-B1Wuqla6.cjs → ensure-D1D4WjYf.cjs} +23 -6
  74. package/dist/ensure-D1D4WjYf.cjs.map +1 -0
  75. package/dist/{ensure-BKdq5xsY.cjs → ensure-D3w6YGp9.cjs} +329 -123
  76. package/dist/ensure-D3w6YGp9.cjs.map +1 -0
  77. package/dist/{acquire-BJ3xUEmh.cjs → ensure-DBnuRJ0R.cjs} +23 -6
  78. package/dist/ensure-DBnuRJ0R.cjs.map +1 -0
  79. package/dist/{acquire-B_p1fNEh.cjs → ensure-DShrbIYY.cjs} +23 -6
  80. package/dist/ensure-DShrbIYY.cjs.map +1 -0
  81. package/dist/{acquire-BP-ZfUH2.js → ensure-NTB9nnnj.js} +16 -5
  82. package/dist/ensure-NTB9nnnj.js.map +1 -0
  83. package/dist/{ensure-D3WWWwMo.cjs → ensure-ORVw-WRE.cjs} +194 -155
  84. package/dist/ensure-ORVw-WRE.cjs.map +1 -0
  85. package/dist/{ensure-BEeY5Ab7.js → ensure-dsqWhIuO.js} +182 -147
  86. package/dist/ensure-dsqWhIuO.js.map +1 -0
  87. package/dist/{ensure-11-asM1e.js → ensure-k-6q7O25.js} +173 -150
  88. package/dist/ensure-k-6q7O25.js.map +1 -0
  89. package/dist/index.cjs +257 -86
  90. package/dist/index.cjs.map +1 -1
  91. package/dist/index.d.cts +6 -13
  92. package/dist/index.d.ts +6 -13
  93. package/dist/index.js +232 -52
  94. package/dist/index.js.map +1 -1
  95. package/dist/internal.cjs +10 -0
  96. package/dist/internal.d.cts +8 -0
  97. package/dist/internal.d.ts +8 -0
  98. package/dist/internal.js +3 -0
  99. package/dist/plugin/BlacPlugin.d.ts +25 -25
  100. package/dist/plugin/PluginManager.d.ts +46 -59
  101. package/dist/plugins.cjs +383 -3
  102. package/dist/plugins.cjs.map +1 -0
  103. package/dist/plugins.d.cts +10 -5
  104. package/dist/plugins.d.ts +10 -5
  105. package/dist/plugins.js +381 -1
  106. package/dist/plugins.js.map +1 -0
  107. package/dist/registry/acquire.d.ts +2 -2
  108. package/dist/registry/config.d.ts +12 -0
  109. package/dist/registry/index.d.ts +2 -2
  110. package/dist/registry/management.d.ts +5 -0
  111. package/dist/registry/queries.d.ts +15 -0
  112. package/dist/registry/release.d.ts +4 -20
  113. package/dist/testing.cjs +63 -38
  114. package/dist/testing.cjs.map +1 -1
  115. package/dist/testing.d.cts +14 -12
  116. package/dist/testing.d.ts +14 -12
  117. package/dist/testing.js +53 -29
  118. package/dist/testing.js.map +1 -1
  119. package/dist/types/branded.d.ts +6 -13
  120. package/dist/types/utilities.d.ts +40 -31
  121. package/dist/utils/idGenerator.d.ts +6 -13
  122. package/dist/utils/static-props.d.ts +28 -29
  123. package/dist/utils/structural-key.d.ts +0 -22
  124. package/dist/watch/index.d.ts +1 -2
  125. package/dist/watch/watch.d.ts +23 -3
  126. package/package.json +28 -54
  127. package/dist/StateContainerRegistry-4Ljd9EJx.js +0 -1018
  128. package/dist/StateContainerRegistry-4Ljd9EJx.js.map +0 -1
  129. package/dist/StateContainerRegistry-8zNFMAf7.js +0 -1067
  130. package/dist/StateContainerRegistry-8zNFMAf7.js.map +0 -1
  131. package/dist/StateContainerRegistry-B1GYx9Xo.js +0 -975
  132. package/dist/StateContainerRegistry-B1GYx9Xo.js.map +0 -1
  133. package/dist/StateContainerRegistry-B_ViBLvJ.js +0 -975
  134. package/dist/StateContainerRegistry-B_ViBLvJ.js.map +0 -1
  135. package/dist/StateContainerRegistry-Bx2ly-ba.cjs +0 -1162
  136. package/dist/StateContainerRegistry-Bx2ly-ba.cjs.map +0 -1
  137. package/dist/StateContainerRegistry-C0dCNlTF.js +0 -1005
  138. package/dist/StateContainerRegistry-C0dCNlTF.js.map +0 -1
  139. package/dist/StateContainerRegistry-C75QpeaO.cjs +0 -1260
  140. package/dist/StateContainerRegistry-C75QpeaO.cjs.map +0 -1
  141. package/dist/StateContainerRegistry-CEWpc1bj.cjs +0 -1113
  142. package/dist/StateContainerRegistry-CEWpc1bj.cjs.map +0 -1
  143. package/dist/StateContainerRegistry-CS18y4au.cjs +0 -1163
  144. package/dist/StateContainerRegistry-CS18y4au.cjs.map +0 -1
  145. package/dist/StateContainerRegistry-CSNm2Ws5.cjs.map +0 -1
  146. package/dist/StateContainerRegistry-CchRjnjX.cjs +0 -1094
  147. package/dist/StateContainerRegistry-CchRjnjX.cjs.map +0 -1
  148. package/dist/StateContainerRegistry-CvBOhAT2.js.map +0 -1
  149. package/dist/StateContainerRegistry-D8nu7Z0T.js +0 -1068
  150. package/dist/StateContainerRegistry-D8nu7Z0T.js.map +0 -1
  151. package/dist/StateContainerRegistry-D9BIRjwv.cjs.map +0 -1
  152. package/dist/StateContainerRegistry-DJQqLrli.cjs +0 -1046
  153. package/dist/StateContainerRegistry-DJQqLrli.cjs.map +0 -1
  154. package/dist/StateContainerRegistry-DL5Ai7wh.js +0 -1153
  155. package/dist/StateContainerRegistry-DL5Ai7wh.js.map +0 -1
  156. package/dist/StateContainerRegistry-DVIBTxGZ.js.map +0 -1
  157. package/dist/StateContainerRegistry-DWOzx7Gd.js +0 -1154
  158. package/dist/StateContainerRegistry-DWOzx7Gd.js.map +0 -1
  159. package/dist/StateContainerRegistry-Dj77cok9.js.map +0 -1
  160. package/dist/StateContainerRegistry-FWKzPfS-.cjs +0 -1046
  161. package/dist/StateContainerRegistry-FWKzPfS-.cjs.map +0 -1
  162. package/dist/StateContainerRegistry-G81GcCRm.cjs +0 -1261
  163. package/dist/StateContainerRegistry-G81GcCRm.cjs.map +0 -1
  164. package/dist/StateContainerRegistry-lIwo-0m3.cjs.map +0 -1
  165. package/dist/acquire-B1LYXSGj.js.map +0 -1
  166. package/dist/acquire-B1Wuqla6.cjs.map +0 -1
  167. package/dist/acquire-BJ3xUEmh.cjs.map +0 -1
  168. package/dist/acquire-BP-ZfUH2.js.map +0 -1
  169. package/dist/acquire-BRIJVJaA.js.map +0 -1
  170. package/dist/acquire-BZIs6tpN.cjs.map +0 -1
  171. package/dist/acquire-B_p1fNEh.cjs.map +0 -1
  172. package/dist/acquire-BdsVZBSe.js.map +0 -1
  173. package/dist/acquire-C3nOb3XR.cjs +0 -46
  174. package/dist/acquire-C3nOb3XR.cjs.map +0 -1
  175. package/dist/acquire-C4WAS13G.cjs +0 -46
  176. package/dist/acquire-C4WAS13G.cjs.map +0 -1
  177. package/dist/acquire-C7beGI55.cjs +0 -46
  178. package/dist/acquire-C7beGI55.cjs.map +0 -1
  179. package/dist/acquire-CE0uq0Dx.cjs +0 -46
  180. package/dist/acquire-CE0uq0Dx.cjs.map +0 -1
  181. package/dist/acquire-CU0u8BMn.js +0 -35
  182. package/dist/acquire-CU0u8BMn.js.map +0 -1
  183. package/dist/acquire-CbMz7gWs.cjs +0 -46
  184. package/dist/acquire-CbMz7gWs.cjs.map +0 -1
  185. package/dist/acquire-CkgLJ8WL.cjs +0 -46
  186. package/dist/acquire-CkgLJ8WL.cjs.map +0 -1
  187. package/dist/acquire-CwB083au.js +0 -35
  188. package/dist/acquire-CwB083au.js.map +0 -1
  189. package/dist/acquire-DHEOEVcj.cjs +0 -46
  190. package/dist/acquire-DHEOEVcj.cjs.map +0 -1
  191. package/dist/acquire-DTvfYJ0y.js +0 -35
  192. package/dist/acquire-DTvfYJ0y.js.map +0 -1
  193. package/dist/acquire-DXEQDZGr.js +0 -35
  194. package/dist/acquire-DXEQDZGr.js.map +0 -1
  195. package/dist/acquire-Dg-uXwjF.js +0 -35
  196. package/dist/acquire-Dg-uXwjF.js.map +0 -1
  197. package/dist/acquire-Don7499S.js +0 -35
  198. package/dist/acquire-Don7499S.js.map +0 -1
  199. package/dist/acquire-G8aB3GAx.js +0 -35
  200. package/dist/acquire-G8aB3GAx.js.map +0 -1
  201. package/dist/branded-BybA0_xw.cjs +0 -18
  202. package/dist/branded-BybA0_xw.cjs.map +0 -1
  203. package/dist/branded-DkbUzncc.js +0 -13
  204. package/dist/branded-DkbUzncc.js.map +0 -1
  205. package/dist/config-8pyOC5gv.js +0 -16
  206. package/dist/config-8pyOC5gv.js.map +0 -1
  207. package/dist/config-B1l8ZGlU.cjs +0 -32
  208. package/dist/config-B1l8ZGlU.cjs.map +0 -1
  209. package/dist/config-C1T6Jw7n.cjs +0 -32
  210. package/dist/config-C1T6Jw7n.cjs.map +0 -1
  211. package/dist/config-C7Ktkjh2.cjs +0 -32
  212. package/dist/config-C7Ktkjh2.cjs.map +0 -1
  213. package/dist/config-COT4Xkbc.js +0 -16
  214. package/dist/config-COT4Xkbc.js.map +0 -1
  215. package/dist/config-CzcoAvBo.js +0 -16
  216. package/dist/config-CzcoAvBo.js.map +0 -1
  217. package/dist/config-D2A8ZYRM.js +0 -16
  218. package/dist/config-D2A8ZYRM.js.map +0 -1
  219. package/dist/config-D34BkraU.cjs +0 -32
  220. package/dist/config-D34BkraU.cjs.map +0 -1
  221. package/dist/config-D6BoWWPv.js +0 -16
  222. package/dist/config-D6BoWWPv.js.map +0 -1
  223. package/dist/config-DOO82lbZ.js +0 -16
  224. package/dist/config-DOO82lbZ.js.map +0 -1
  225. package/dist/config-DVM_ESQt.js +0 -16
  226. package/dist/config-DVM_ESQt.js.map +0 -1
  227. package/dist/config-DVMnlHLv.cjs +0 -32
  228. package/dist/config-DVMnlHLv.cjs.map +0 -1
  229. package/dist/config-DWUq7zEQ.cjs +0 -32
  230. package/dist/config-DWUq7zEQ.cjs.map +0 -1
  231. package/dist/config-DXI3kzmA.js +0 -16
  232. package/dist/config-DXI3kzmA.js.map +0 -1
  233. package/dist/config-Dk1FxfXj.js +0 -16
  234. package/dist/config-Dk1FxfXj.js.map +0 -1
  235. package/dist/config-ZVy_yFZ3.js +0 -16
  236. package/dist/config-ZVy_yFZ3.js.map +0 -1
  237. package/dist/config-b2z51Y_C.cjs +0 -32
  238. package/dist/config-b2z51Y_C.cjs.map +0 -1
  239. package/dist/config-buwpT7l3.js +0 -16
  240. package/dist/config-buwpT7l3.js.map +0 -1
  241. package/dist/config-cwaTn5oy.cjs +0 -32
  242. package/dist/config-cwaTn5oy.cjs.map +0 -1
  243. package/dist/config-d9_U58ef.cjs +0 -32
  244. package/dist/config-d9_U58ef.cjs.map +0 -1
  245. package/dist/config-hWTayX76.cjs +0 -32
  246. package/dist/config-hWTayX76.cjs.map +0 -1
  247. package/dist/config-sCPKPYxZ.cjs +0 -32
  248. package/dist/config-sCPKPYxZ.cjs.map +0 -1
  249. package/dist/debug.cjs +0 -14
  250. package/dist/debug.d.cts +0 -34
  251. package/dist/debug.d.ts +0 -34
  252. package/dist/debug.js +0 -4
  253. package/dist/ensure-11-asM1e.js.map +0 -1
  254. package/dist/ensure-B1dEDsZV.cjs +0 -559
  255. package/dist/ensure-B1dEDsZV.cjs.map +0 -1
  256. package/dist/ensure-B2DYCbbI.cjs.map +0 -1
  257. package/dist/ensure-B59ri8oo.js.map +0 -1
  258. package/dist/ensure-B9oOqpOB.cjs +0 -558
  259. package/dist/ensure-B9oOqpOB.cjs.map +0 -1
  260. package/dist/ensure-BEeY5Ab7.js.map +0 -1
  261. package/dist/ensure-BKdq5xsY.cjs.map +0 -1
  262. package/dist/ensure-BSJHkUNX.js.map +0 -1
  263. package/dist/ensure-BfYnvAsI.js +0 -709
  264. package/dist/ensure-BfYnvAsI.js.map +0 -1
  265. package/dist/ensure-Bm91o37h.js +0 -536
  266. package/dist/ensure-Bm91o37h.js.map +0 -1
  267. package/dist/ensure-C1a8IFWy.js +0 -535
  268. package/dist/ensure-C1a8IFWy.js.map +0 -1
  269. package/dist/ensure-CLQEx0Nn.cjs +0 -528
  270. package/dist/ensure-CLQEx0Nn.cjs.map +0 -1
  271. package/dist/ensure-CPMiGvov.js +0 -493
  272. package/dist/ensure-CPMiGvov.js.map +0 -1
  273. package/dist/ensure-CQimeD0I.cjs +0 -559
  274. package/dist/ensure-CQimeD0I.cjs.map +0 -1
  275. package/dist/ensure-D3WWWwMo.cjs.map +0 -1
  276. package/dist/ensure-DEXSmA-N.js +0 -526
  277. package/dist/ensure-DEXSmA-N.js.map +0 -1
  278. package/dist/ensure-DTTTd2h8.js +0 -536
  279. package/dist/ensure-DTTTd2h8.js.map +0 -1
  280. package/dist/ensure-Dx86f80B.cjs +0 -567
  281. package/dist/ensure-Dx86f80B.cjs.map +0 -1
  282. package/dist/ensure-DzqGej43.js +0 -526
  283. package/dist/ensure-DzqGej43.js.map +0 -1
  284. package/dist/ensure-VuiNPccZ.cjs +0 -559
  285. package/dist/ensure-VuiNPccZ.cjs.map +0 -1
  286. package/dist/ensure-_Oh8XPm4.cjs +0 -732
  287. package/dist/ensure-_Oh8XPm4.cjs.map +0 -1
  288. package/dist/ensure-fsQMjaQL.cjs +0 -567
  289. package/dist/ensure-fsQMjaQL.cjs.map +0 -1
  290. package/dist/ensure-r1C_7K6_.cjs.map +0 -1
  291. package/dist/ensure-vxAGa2v3.js +0 -536
  292. package/dist/ensure-vxAGa2v3.js.map +0 -1
  293. package/dist/events.d.cts +0 -42
  294. package/dist/events.d.ts +0 -42
  295. package/dist/management-14vsHr4t.cjs +0 -85
  296. package/dist/management-14vsHr4t.cjs.map +0 -1
  297. package/dist/management-444tdCBG.js +0 -38
  298. package/dist/management-444tdCBG.js.map +0 -1
  299. package/dist/management-7jLjVHJd.js +0 -38
  300. package/dist/management-7jLjVHJd.js.map +0 -1
  301. package/dist/management-8x1OVMi6.js +0 -38
  302. package/dist/management-8x1OVMi6.js.map +0 -1
  303. package/dist/management-AFuqQEwz.js +0 -38
  304. package/dist/management-AFuqQEwz.js.map +0 -1
  305. package/dist/management-BZgsi29F.js +0 -38
  306. package/dist/management-BZgsi29F.js.map +0 -1
  307. package/dist/management-BodVLAfJ.cjs +0 -85
  308. package/dist/management-BodVLAfJ.cjs.map +0 -1
  309. package/dist/management-BqGBdL01.js +0 -38
  310. package/dist/management-BqGBdL01.js.map +0 -1
  311. package/dist/management-BvUAjril.js +0 -38
  312. package/dist/management-BvUAjril.js.map +0 -1
  313. package/dist/management-C-WGcwPD.js +0 -38
  314. package/dist/management-C-WGcwPD.js.map +0 -1
  315. package/dist/management-C2wv4vGS.cjs +0 -85
  316. package/dist/management-C2wv4vGS.cjs.map +0 -1
  317. package/dist/management-D2pjr38g.js +0 -38
  318. package/dist/management-D2pjr38g.js.map +0 -1
  319. package/dist/management-D5WsZoTV.js +0 -38
  320. package/dist/management-D5WsZoTV.js.map +0 -1
  321. package/dist/management-DAV9sN-k.cjs +0 -85
  322. package/dist/management-DAV9sN-k.cjs.map +0 -1
  323. package/dist/management-Df7Y2sF1.cjs +0 -85
  324. package/dist/management-Df7Y2sF1.cjs.map +0 -1
  325. package/dist/management-Dg2SxUb6.cjs +0 -85
  326. package/dist/management-Dg2SxUb6.cjs.map +0 -1
  327. package/dist/management-DwO0nBzL.cjs +0 -85
  328. package/dist/management-DwO0nBzL.cjs.map +0 -1
  329. package/dist/management-GcnNJjnm.cjs +0 -85
  330. package/dist/management-GcnNJjnm.cjs.map +0 -1
  331. package/dist/management-P_Vi_cvw.js +0 -38
  332. package/dist/management-P_Vi_cvw.js.map +0 -1
  333. package/dist/management-QWLpbXlW.cjs +0 -85
  334. package/dist/management-QWLpbXlW.cjs.map +0 -1
  335. package/dist/management-hkY13log.cjs +0 -85
  336. package/dist/management-hkY13log.cjs.map +0 -1
  337. package/dist/management-iE4x6IQY.cjs +0 -85
  338. package/dist/management-iE4x6IQY.cjs.map +0 -1
  339. package/dist/types.cjs +0 -3
  340. package/dist/types.d.cts +0 -8
  341. package/dist/types.d.ts +0 -8
  342. package/dist/types.js +0 -2
  343. package/dist/watch/observe.d.ts +0 -13
  344. package/dist/watch-B0pUfh-v.cjs +0 -119
  345. package/dist/watch-B0pUfh-v.cjs.map +0 -1
  346. package/dist/watch-B91opmva.cjs +0 -70
  347. package/dist/watch-B91opmva.cjs.map +0 -1
  348. package/dist/watch-BDiwCPmb.js +0 -108
  349. package/dist/watch-BDiwCPmb.js.map +0 -1
  350. package/dist/watch-BHfCtbn1.cjs +0 -119
  351. package/dist/watch-BHfCtbn1.cjs.map +0 -1
  352. package/dist/watch-BW7gYiDf.js +0 -108
  353. package/dist/watch-BW7gYiDf.js.map +0 -1
  354. package/dist/watch-BmC-Tyqg.js +0 -59
  355. package/dist/watch-BmC-Tyqg.js.map +0 -1
  356. package/dist/watch-Bx0y-Kcc.js +0 -108
  357. package/dist/watch-Bx0y-Kcc.js.map +0 -1
  358. package/dist/watch-CKWt788i.cjs +0 -70
  359. package/dist/watch-CKWt788i.cjs.map +0 -1
  360. package/dist/watch-CfrSSrRY.js +0 -59
  361. package/dist/watch-CfrSSrRY.js.map +0 -1
  362. package/dist/watch-Cnh3PtQA.cjs +0 -70
  363. package/dist/watch-Cnh3PtQA.cjs.map +0 -1
  364. package/dist/watch-D01MdwKy.js +0 -108
  365. package/dist/watch-D01MdwKy.js.map +0 -1
  366. package/dist/watch-D8hwbFU1.js +0 -59
  367. package/dist/watch-D8hwbFU1.js.map +0 -1
  368. package/dist/watch-DPVUwPUY.js +0 -59
  369. package/dist/watch-DPVUwPUY.js.map +0 -1
  370. package/dist/watch-DVmvZBMD.cjs +0 -70
  371. package/dist/watch-DVmvZBMD.cjs.map +0 -1
  372. package/dist/watch-DkDGmGAx.cjs +0 -119
  373. package/dist/watch-DkDGmGAx.cjs.map +0 -1
  374. package/dist/watch-DttHqefn.js +0 -108
  375. package/dist/watch-DttHqefn.js.map +0 -1
  376. package/dist/watch-DxdIZjpt.cjs +0 -119
  377. package/dist/watch-DxdIZjpt.cjs.map +0 -1
  378. package/dist/watch-DztcJuUy.cjs +0 -119
  379. package/dist/watch-DztcJuUy.cjs.map +0 -1
  380. package/dist/watch-IrR8G28N.js +0 -108
  381. package/dist/watch-IrR8G28N.js.map +0 -1
  382. package/dist/watch-aoNLQAXp.cjs +0 -119
  383. package/dist/watch-aoNLQAXp.cjs.map +0 -1
  384. package/dist/watch-entry.cjs +0 -4
  385. package/dist/watch-entry.d.cts +0 -24
  386. package/dist/watch-entry.d.ts +0 -24
  387. package/dist/watch-entry.js +0 -2
  388. package/dist/watch-hx0r92Zc.js +0 -108
  389. package/dist/watch-hx0r92Zc.js.map +0 -1
  390. package/dist/watch-lEco5Tbl.cjs +0 -119
  391. package/dist/watch-lEco5Tbl.cjs.map +0 -1
package/dist/testing.cjs CHANGED
@@ -1,8 +1,8 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_StateContainerRegistry = require("./StateContainerRegistry-G81GcCRm.cjs");
3
- const require_ensure = require("./ensure-r1C_7K6_.cjs");
4
- const require_config = require("./config-C1T6Jw7n.cjs");
5
- const require_acquire = require("./acquire-CkgLJ8WL.cjs");
2
+ const require_StateContainerRegistry = require("./StateContainerRegistry-B6O6cfJd.cjs");
3
+ const require_StateContainer = require("./StateContainer-D2b10eR4.cjs");
4
+ const require_ensure = require("./ensure-DShrbIYY.cjs");
5
+ let _dirtytalk_structural = require("@dirtytalk/structural");
6
6
  //#region src/testing.ts
7
7
  /** Synthetic owner id used by test helpers for pre-wired deps. */
8
8
  const TESTING_DEPS_OWNER = "testing-deps";
@@ -10,39 +10,42 @@ function createTestRegistry() {
10
10
  return new require_StateContainerRegistry.StateContainerRegistry();
11
11
  }
12
12
  function withTestRegistry(fn) {
13
- const previous = require_config.getRegistry();
13
+ const previous = require_StateContainer.getRegistry();
14
14
  const testRegistry = createTestRegistry();
15
- require_config.setRegistry(testRegistry);
15
+ require_StateContainer.setRegistry(testRegistry);
16
16
  try {
17
17
  const result = fn(testRegistry);
18
18
  if (result instanceof Promise) return result.then((value) => {
19
- require_config.setRegistry(previous);
19
+ require_StateContainer.setRegistry(previous);
20
20
  return value;
21
21
  }, (error) => {
22
- require_config.setRegistry(previous);
22
+ require_StateContainer.setRegistry(previous);
23
23
  throw error;
24
24
  });
25
- require_config.setRegistry(previous);
25
+ require_StateContainer.setRegistry(previous);
26
26
  return result;
27
27
  } catch (error) {
28
- require_config.setRegistry(previous);
28
+ require_StateContainer.setRegistry(previous);
29
29
  throw error;
30
30
  }
31
31
  }
32
32
  function blacTestSetup() {
33
33
  let savedRegistry;
34
+ let testRegistry;
34
35
  beforeEach(() => {
35
- savedRegistry = require_config.getRegistry();
36
- require_config.setRegistry(new require_StateContainerRegistry.StateContainerRegistry());
36
+ savedRegistry = require_StateContainer.getRegistry();
37
+ testRegistry = createTestRegistry();
38
+ require_StateContainer.setRegistry(testRegistry);
37
39
  });
38
40
  afterEach(() => {
39
- require_config.setRegistry(savedRegistry);
41
+ testRegistry.clearAll();
42
+ require_StateContainer.setRegistry(savedRegistry);
40
43
  });
41
44
  }
42
45
  function registerOverride(BlocClass, instance, args) {
43
- const registry = require_config.getRegistry();
44
- const key = require_acquire.resolveInstanceKey(BlocClass, args);
45
- registry.insertInstance(BlocClass, key, instance, new Map([["testing-override", 1]]));
46
+ const registry = require_StateContainer.getRegistry();
47
+ const key = require_ensure.resolveInstanceKey(BlocClass, args);
48
+ registry[require_StateContainerRegistry.INSERT_INSTANCE](BlocClass, key, instance, new Map([["testing-override", 1]]));
46
49
  }
47
50
  function overrideEnsure(BlocClass, instance, fn, args) {
48
51
  return withTestRegistry(() => {
@@ -52,14 +55,8 @@ function overrideEnsure(BlocClass, instance, fn, args) {
52
55
  }
53
56
  function createCubitStub(BlocClass, options) {
54
57
  const instance = new BlocClass();
55
- if (options?.args != null) instance[require_StateContainerRegistry.INIT_CONFIG]({ args: options.args });
56
- if (options?.state != null) {
57
- if (instance instanceof require_ensure.Cubit) {
58
- const currentState = instance.state;
59
- if (typeof currentState === "object" && currentState !== null && typeof options.state === "object" && options.state !== null) instance.patch(options.state);
60
- else instance.emit(options.state);
61
- }
62
- }
58
+ instance[require_StateContainerRegistry.INIT_CONFIG]({ args: options?.args });
59
+ if (options?.state != null) applyState(instance, options.state);
63
60
  if (options?.methods) {
64
61
  for (const [key, impl] of Object.entries(options.methods)) if (typeof impl === "function") instance[key] = impl;
65
62
  }
@@ -68,30 +65,57 @@ function createCubitStub(BlocClass, options) {
68
65
  }
69
66
  function withBlocState(BlocClass, state, args) {
70
67
  const instance = require_ensure.ensure(BlocClass, { args });
71
- if (instance instanceof require_ensure.Cubit) {
72
- const currentState = instance.state;
73
- if (typeof currentState === "object" && currentState !== null && typeof state === "object" && state !== null) instance.patch(state);
74
- else instance.emit(state);
75
- }
68
+ applyState(instance, state);
76
69
  return instance;
77
70
  }
71
+ function applyState(instance, state) {
72
+ const target = instance;
73
+ if (typeof target.state === "object" && target.state !== null && typeof state === "object" && state !== null) target.patch(state);
74
+ else target.emit(state);
75
+ }
78
76
  function withBlocMethod(BlocClass, methodName, impl, args) {
79
77
  const instance = require_ensure.ensure(BlocClass, { args });
80
78
  instance[methodName] = impl;
81
79
  return instance;
82
80
  }
83
81
  /**
84
- * Drain pending microtasks so any channel-flushed effects (channel
85
- * subscribers, `onSystemEvent('stateChanged')` handlers, plugin hooks) run
86
- * before the next assertion.
87
- *
88
- * The default `MicrotaskScheduler` coalesces emits within a tick; tests
89
- * that emit and then assert on subscriber side-effects need `await flush()`
90
- * between the two.
82
+ * Drain pending microtasks so channel-flushed effects (subscribers,
83
+ * `onSystemEvent('stateChanged')` handlers, plugin hooks) run before the
84
+ * next assertion. A subscriber can emit again, so this keeps draining until
85
+ * a round passes with no new state change.
91
86
  */
92
87
  async function flush() {
93
- await Promise.resolve();
94
- await Promise.resolve();
88
+ for (let i = 0; i < MAX_FLUSH_ROUNDS; i++) {
89
+ const before = require_StateContainer.getStateChangeCount();
90
+ await Promise.resolve();
91
+ await Promise.resolve();
92
+ if (require_StateContainer.getStateChangeCount() === before) return;
93
+ }
94
+ throw new Error(`[blac] flush(): state was still changing after ${MAX_FLUSH_ROUNDS} rounds`);
95
+ }
96
+ const MAX_FLUSH_ROUNDS = 100;
97
+ /**
98
+ * Resolves with the first state of `bloc` that satisfies `predicate`: the
99
+ * current state if it already does, otherwise the first matching change.
100
+ * Rejects after `timeout` ms (default 1000).
101
+ */
102
+ function waitForState(bloc, predicate, { timeout = 1e3 } = {}) {
103
+ if (predicate(bloc.state)) return Promise.resolve(bloc.state);
104
+ return new Promise((resolve, reject) => {
105
+ const settle = () => {
106
+ clearTimeout(timer);
107
+ unsubscribe();
108
+ };
109
+ const unsubscribe = bloc.channel.subscribe(() => _dirtytalk_structural.ALL_PATHS, () => {
110
+ if (!predicate(bloc.state)) return;
111
+ settle();
112
+ resolve(bloc.state);
113
+ });
114
+ const timer = setTimeout(() => {
115
+ settle();
116
+ reject(/* @__PURE__ */ new Error(`[blac] waitForState(): timed out after ${timeout}ms`));
117
+ }, timeout);
118
+ });
95
119
  }
96
120
  //#endregion
97
121
  exports.blacTestSetup = blacTestSetup;
@@ -100,6 +124,7 @@ exports.createTestRegistry = createTestRegistry;
100
124
  exports.flush = flush;
101
125
  exports.overrideEnsure = overrideEnsure;
102
126
  exports.registerOverride = registerOverride;
127
+ exports.waitForState = waitForState;
103
128
  exports.withBlocMethod = withBlocMethod;
104
129
  exports.withBlocState = withBlocState;
105
130
  exports.withTestRegistry = withTestRegistry;
@@ -1 +1 @@
1
- {"version":3,"file":"testing.cjs","names":["StateContainerRegistry","getRegistry","resolveInstanceKey","INIT_CONFIG","Cubit","APPLY_DEPS","ensure"],"sources":["../src/testing.ts"],"sourcesContent":["import { Cubit } from './core/Cubit';\nimport { StateContainerRegistry } from './core/StateContainerRegistry';\nimport { APPLY_DEPS, INIT_CONFIG } from './core/symbols';\nimport { ensure, getRegistry, setRegistry } from './registry';\nimport { resolveInstanceKey } from './registry/acquire';\nimport type {\n ExtractArgs,\n ExtractDeps,\n ExtractState,\n StateContainerConstructor,\n} from './types/utilities';\n\n/** Synthetic owner id used by test helpers for pre-wired deps. */\nconst TESTING_DEPS_OWNER = 'testing-deps';\n\ndeclare const beforeEach: (fn: () => void) => void;\ndeclare const afterEach: (fn: () => void) => void;\n\n// --- createTestRegistry + withTestRegistry ---\n\nexport function createTestRegistry(): StateContainerRegistry {\n return new StateContainerRegistry();\n}\n\nexport function withTestRegistry<T>(\n fn: (registry: StateContainerRegistry) => T,\n): T {\n const previous = getRegistry();\n const testRegistry = createTestRegistry();\n setRegistry(testRegistry);\n try {\n const result = fn(testRegistry);\n if (result instanceof Promise) {\n return result.then(\n (value) => {\n setRegistry(previous);\n return value;\n },\n (error) => {\n setRegistry(previous);\n throw error;\n },\n ) as T;\n }\n setRegistry(previous);\n return result;\n } catch (error) {\n setRegistry(previous);\n throw error;\n }\n}\n\n// --- blacTestSetup ---\n\nexport function blacTestSetup(): void {\n let savedRegistry: StateContainerRegistry;\n beforeEach(() => {\n savedRegistry = getRegistry();\n setRegistry(new StateContainerRegistry());\n });\n afterEach(() => {\n setRegistry(savedRegistry);\n });\n}\n\n// --- registerOverride + overrideEnsure ---\n\nexport function registerOverride<T extends StateContainerConstructor>(\n BlocClass: T,\n instance: InstanceType<T>,\n args?: ExtractArgs<T>,\n): void {\n const registry = getRegistry();\n const key = resolveInstanceKey(BlocClass, args);\n registry.insertInstance(\n BlocClass,\n key,\n instance,\n new Map([['testing-override', 1]]),\n );\n}\n\nexport function overrideEnsure<T extends StateContainerConstructor, R>(\n BlocClass: T,\n instance: InstanceType<T>,\n fn: () => R,\n args?: ExtractArgs<T>,\n): R {\n return withTestRegistry(() => {\n registerOverride(BlocClass, instance, args);\n return fn();\n });\n}\n\n// --- createCubitStub ---\n\ntype MethodKeys<T> = {\n [K in keyof T]: T[K] extends (...args: any[]) => any ? K : never;\n}[keyof T];\n\nexport interface CubitStubOptions<T extends StateContainerConstructor> {\n state?: ExtractState<T> extends Record<string, any>\n ? Partial<ExtractState<T>>\n : ExtractState<T>;\n methods?: Partial<\n Record<MethodKeys<InstanceType<T>>, (...args: any[]) => any>\n >;\n /**\n * Args to pass to init(). If the bloc's Args type is not void, supplying\n * args here causes initConfig({ args }) to be called so init() runs.\n */\n args?: ExtractArgs<T> extends void ? never : ExtractArgs<T>;\n /**\n * Deps slice to pre-wire via the core [APPLY_DEPS] path (synthetic owner\n * \"testing-deps\"), so onDepsChanged fires during tests.\n */\n deps?: Partial<ExtractDeps<T>>;\n}\n\nexport function createCubitStub<T extends StateContainerConstructor>(\n BlocClass: T,\n options?: CubitStubOptions<T>,\n): InstanceType<T> {\n const instance = new BlocClass() as InstanceType<T>;\n\n // Run init() if args are supplied — goes through the same initConfig path\n // that the registry uses, so lifecycle hooks fire correctly.\n if (options?.args != null) {\n instance[INIT_CONFIG]({ args: options.args });\n }\n\n if (options?.state != null) {\n if (instance instanceof Cubit) {\n const currentState = instance.state;\n if (\n typeof currentState === 'object' &&\n currentState !== null &&\n typeof options.state === 'object' &&\n options.state !== null\n ) {\n instance.patch(options.state as any);\n } else {\n instance.emit(options.state as any);\n }\n }\n }\n if (options?.methods) {\n for (const [key, impl] of Object.entries(options.methods)) {\n if (typeof impl === 'function') {\n (instance as any)[key] = impl;\n }\n }\n }\n\n // Pre-wire deps via the core merge path so onDepsChanged fires in tests.\n if (options?.deps != null) {\n (instance as any)[APPLY_DEPS](TESTING_DEPS_OWNER, options.deps);\n }\n\n return instance;\n}\n\n// --- withBlocState ---\n\nexport function withBlocState<T extends StateContainerConstructor>(\n BlocClass: T,\n state: ExtractState<T> extends Record<string, any>\n ? Partial<ExtractState<T>>\n : ExtractState<T>,\n args?: ExtractArgs<T>,\n): InstanceType<T> {\n const instance = ensure(BlocClass, { args });\n if (instance instanceof Cubit) {\n const currentState = instance.state;\n if (\n typeof currentState === 'object' &&\n currentState !== null &&\n typeof state === 'object' &&\n state !== null\n ) {\n instance.patch(state as any);\n } else {\n instance.emit(state as any);\n }\n }\n return instance;\n}\n\n// --- withBlocMethod ---\n\nexport function withBlocMethod<T extends StateContainerConstructor>(\n BlocClass: T,\n methodName: keyof InstanceType<T>,\n impl: (...args: any[]) => any,\n args?: ExtractArgs<T>,\n): InstanceType<T> {\n const instance = ensure(BlocClass, { args });\n (instance as any)[methodName] = impl;\n return instance;\n}\n\n// --- flush ---\n\n/**\n * Drain pending microtasks so any channel-flushed effects (channel\n * subscribers, `onSystemEvent('stateChanged')` handlers, plugin hooks) run\n * before the next assertion.\n *\n * The default `MicrotaskScheduler` coalesces emits within a tick; tests\n * that emit and then assert on subscriber side-effects need `await flush()`\n * between the two.\n */\nexport async function flush(): Promise<void> {\n // queueMicrotask wins the race against the channel's own queued flush —\n // we resolve after the channel has drained its current pending flush.\n await Promise.resolve();\n await Promise.resolve();\n}\n"],"mappings":";;;;;;;AAaA,MAAM,qBAAqB;AAO3B,SAAgB,qBAA6C;CAC3D,OAAO,IAAIA,+BAAAA,uBAAuB;AACpC;AAEA,SAAgB,iBACd,IACG;CACH,MAAM,WAAWC,eAAAA,YAAY;CAC7B,MAAM,eAAe,mBAAmB;CACxC,eAAA,YAAY,YAAY;CACxB,IAAI;EACF,MAAM,SAAS,GAAG,YAAY;EAC9B,IAAI,kBAAkB,SACpB,OAAO,OAAO,MACX,UAAU;GACT,eAAA,YAAY,QAAQ;GACpB,OAAO;EACT,IACC,UAAU;GACT,eAAA,YAAY,QAAQ;GACpB,MAAM;EACR,CACF;EAEF,eAAA,YAAY,QAAQ;EACpB,OAAO;CACT,SAAS,OAAO;EACd,eAAA,YAAY,QAAQ;EACpB,MAAM;CACR;AACF;AAIA,SAAgB,gBAAsB;CACpC,IAAI;CACJ,iBAAiB;EACf,gBAAgBA,eAAAA,YAAY;EAC5B,eAAA,YAAY,IAAID,+BAAAA,uBAAuB,CAAC;CAC1C,CAAC;CACD,gBAAgB;EACd,eAAA,YAAY,aAAa;CAC3B,CAAC;AACH;AAIA,SAAgB,iBACd,WACA,UACA,MACM;CACN,MAAM,WAAWC,eAAAA,YAAY;CAC7B,MAAM,MAAMC,gBAAAA,mBAAmB,WAAW,IAAI;CAC9C,SAAS,eACP,WACA,KACA,UACA,IAAI,IAAI,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,CACnC;AACF;AAEA,SAAgB,eACd,WACA,UACA,IACA,MACG;CACH,OAAO,uBAAuB;EAC5B,iBAAiB,WAAW,UAAU,IAAI;EAC1C,OAAO,GAAG;CACZ,CAAC;AACH;AA2BA,SAAgB,gBACd,WACA,SACiB;CACjB,MAAM,WAAW,IAAI,UAAU;CAI/B,IAAI,SAAS,QAAQ,MACnB,SAASC,+BAAAA,aAAa,EAAE,MAAM,QAAQ,KAAK,CAAC;CAG9C,IAAI,SAAS,SAAS;MAChB,oBAAoBC,eAAAA,OAAO;GAC7B,MAAM,eAAe,SAAS;GAC9B,IACE,OAAO,iBAAiB,YACxB,iBAAiB,QACjB,OAAO,QAAQ,UAAU,YACzB,QAAQ,UAAU,MAElB,SAAS,MAAM,QAAQ,KAAY;QAEnC,SAAS,KAAK,QAAQ,KAAY;EAEtC;;CAEF,IAAI,SAAS;OACN,MAAM,CAAC,KAAK,SAAS,OAAO,QAAQ,QAAQ,OAAO,GACtD,IAAI,OAAO,SAAS,YAClB,SAAkB,OAAO;CAAA;CAM/B,IAAI,SAAS,QAAQ,MACnB,SAAkBC,+BAAAA,YAAY,oBAAoB,QAAQ,IAAI;CAGhE,OAAO;AACT;AAIA,SAAgB,cACd,WACA,OAGA,MACiB;CACjB,MAAM,WAAWC,eAAAA,OAAO,WAAW,EAAE,KAAK,CAAC;CAC3C,IAAI,oBAAoBF,eAAAA,OAAO;EAC7B,MAAM,eAAe,SAAS;EAC9B,IACE,OAAO,iBAAiB,YACxB,iBAAiB,QACjB,OAAO,UAAU,YACjB,UAAU,MAEV,SAAS,MAAM,KAAY;OAE3B,SAAS,KAAK,KAAY;CAE9B;CACA,OAAO;AACT;AAIA,SAAgB,eACd,WACA,YACA,MACA,MACiB;CACjB,MAAM,WAAWE,eAAAA,OAAO,WAAW,EAAE,KAAK,CAAC;CAC3C,SAAkB,cAAc;CAChC,OAAO;AACT;;;;;;;;;;AAaA,eAAsB,QAAuB;CAG3C,MAAM,QAAQ,QAAQ;CACtB,MAAM,QAAQ,QAAQ;AACxB"}
1
+ {"version":3,"file":"testing.cjs","names":["StateContainerRegistry","getRegistry","resolveInstanceKey","INSERT_INSTANCE","INIT_CONFIG","APPLY_DEPS","ensure","getStateChangeCount","ALL_PATHS"],"sources":["../src/testing.ts"],"sourcesContent":["import { ALL_PATHS } from '@dirtytalk/structural';\nimport type { Cubit } from './core/Cubit';\nimport { getStateChangeCount } from './core/StateContainer';\nimport { StateContainerRegistry } from './core/StateContainerRegistry';\nimport { APPLY_DEPS, INIT_CONFIG, INSERT_INSTANCE } from './core/symbols';\nimport { ensure, getRegistry, setRegistry } from './registry';\nimport { resolveInstanceKey } from './registry/acquire';\nimport type {\n ExtractArgs,\n ExtractDeps,\n ExtractState,\n StateContainerConstructor,\n StateContainerInstance,\n} from './types/utilities';\n\n/** Synthetic owner id used by test helpers for pre-wired deps. */\nconst TESTING_DEPS_OWNER = 'testing-deps';\n\ndeclare const beforeEach: (fn: () => void) => void;\ndeclare const afterEach: (fn: () => void) => void;\n\nexport function createTestRegistry(): StateContainerRegistry {\n return new StateContainerRegistry();\n}\n\nexport function withTestRegistry<T>(\n fn: (registry: StateContainerRegistry) => T,\n): T {\n const previous = getRegistry();\n const testRegistry = createTestRegistry();\n setRegistry(testRegistry);\n try {\n const result = fn(testRegistry);\n if (result instanceof Promise) {\n return result.then(\n (value) => {\n setRegistry(previous);\n return value;\n },\n (error) => {\n setRegistry(previous);\n throw error;\n },\n ) as T;\n }\n setRegistry(previous);\n return result;\n } catch (error) {\n setRegistry(previous);\n throw error;\n }\n}\n\nexport function blacTestSetup(): void {\n let savedRegistry: StateContainerRegistry;\n let testRegistry: StateContainerRegistry;\n beforeEach(() => {\n savedRegistry = getRegistry();\n testRegistry = createTestRegistry();\n setRegistry(testRegistry);\n });\n afterEach(() => {\n testRegistry.clearAll();\n setRegistry(savedRegistry);\n });\n}\n\nexport function registerOverride<T extends StateContainerConstructor>(\n BlocClass: T,\n instance: InstanceType<T>,\n args?: ExtractArgs<T>,\n): void {\n const registry = getRegistry();\n const key = resolveInstanceKey(BlocClass, args);\n registry[INSERT_INSTANCE](\n BlocClass,\n key,\n instance,\n new Map([['testing-override', 1]]),\n );\n}\n\nexport function overrideEnsure<T extends StateContainerConstructor, R>(\n BlocClass: T,\n instance: InstanceType<T>,\n fn: () => R,\n args?: ExtractArgs<T>,\n): R {\n return withTestRegistry(() => {\n registerOverride(BlocClass, instance, args);\n return fn();\n });\n}\n\ntype MethodKeys<T> = {\n [K in keyof T]: T[K] extends (...args: any[]) => any ? K : never;\n}[keyof T];\n\nexport interface CubitStubOptions<T extends StateContainerConstructor> {\n state?: ExtractState<T> extends Record<string, any>\n ? Partial<ExtractState<T>>\n : ExtractState<T>;\n methods?: Partial<\n Record<MethodKeys<InstanceType<T>>, (...args: any[]) => any>\n >;\n /** Args passed to init(). */\n args?: ExtractArgs<T> extends void ? never : ExtractArgs<T>;\n /**\n * Deps slice to pre-wire via the core [APPLY_DEPS] path (synthetic owner\n * \"testing-deps\"), so onDepsChanged fires during tests.\n */\n deps?: Partial<ExtractDeps<T>>;\n}\n\nexport function createCubitStub<T extends StateContainerConstructor>(\n BlocClass: T,\n options?: CubitStubOptions<T>,\n): InstanceType<T> {\n const instance = new BlocClass() as InstanceType<T>;\n instance[INIT_CONFIG]({ args: options?.args });\n\n if (options?.state != null) {\n applyState(instance, options.state);\n }\n if (options?.methods) {\n for (const [key, impl] of Object.entries(options.methods)) {\n if (typeof impl === 'function') {\n (instance as any)[key] = impl;\n }\n }\n }\n\n // Pre-wire deps via the core merge path so onDepsChanged fires in tests.\n if (options?.deps != null) {\n (instance as any)[APPLY_DEPS](TESTING_DEPS_OWNER, options.deps);\n }\n\n return instance;\n}\n\nexport function withBlocState<T extends StateContainerConstructor>(\n BlocClass: T,\n state: ExtractState<T> extends Record<string, any>\n ? Partial<ExtractState<T>>\n : ExtractState<T>,\n args?: ExtractArgs<T>,\n): InstanceType<T> {\n const instance = ensure(BlocClass, { args });\n applyState(instance, state);\n return instance;\n}\n\n// emit/patch are protected on StateContainer; Cubit only makes them public.\nfunction applyState(instance: object, state: unknown): void {\n const target = instance as Cubit<any>;\n if (\n typeof target.state === 'object' &&\n target.state !== null &&\n typeof state === 'object' &&\n state !== null\n ) {\n target.patch(state);\n } else {\n target.emit(state as any);\n }\n}\n\nexport function withBlocMethod<T extends StateContainerConstructor>(\n BlocClass: T,\n methodName: keyof InstanceType<T>,\n impl: (...args: any[]) => any,\n args?: ExtractArgs<T>,\n): InstanceType<T> {\n const instance = ensure(BlocClass, { args });\n (instance as any)[methodName] = impl;\n return instance;\n}\n\n/**\n * Drain pending microtasks so channel-flushed effects (subscribers,\n * `onSystemEvent('stateChanged')` handlers, plugin hooks) run before the\n * next assertion. A subscriber can emit again, so this keeps draining until\n * a round passes with no new state change.\n */\nexport async function flush(): Promise<void> {\n for (let i = 0; i < MAX_FLUSH_ROUNDS; i++) {\n const before = getStateChangeCount();\n // The second tick lets microtasks queued by the drain itself (registry\n // `stateChanged` delivery) run too.\n await Promise.resolve();\n await Promise.resolve();\n if (getStateChangeCount() === before) return;\n }\n throw new Error(\n `[blac] flush(): state was still changing after ${MAX_FLUSH_ROUNDS} rounds`,\n );\n}\n\nconst MAX_FLUSH_ROUNDS = 100;\n\n/**\n * Resolves with the first state of `bloc` that satisfies `predicate`: the\n * current state if it already does, otherwise the first matching change.\n * Rejects after `timeout` ms (default 1000).\n */\nexport function waitForState<B extends StateContainerInstance>(\n bloc: B,\n predicate: (state: B['state']) => boolean,\n { timeout = 1000 }: { timeout?: number } = {},\n): Promise<B['state']> {\n if (predicate(bloc.state)) return Promise.resolve(bloc.state);\n\n return new Promise((resolve, reject) => {\n const settle = () => {\n clearTimeout(timer);\n unsubscribe();\n };\n const unsubscribe = bloc.channel.subscribe(\n () => ALL_PATHS,\n () => {\n if (!predicate(bloc.state)) return;\n settle();\n resolve(bloc.state);\n },\n );\n const timer = setTimeout(() => {\n settle();\n reject(new Error(`[blac] waitForState(): timed out after ${timeout}ms`));\n }, timeout);\n });\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { StateContainerRegistry } from './core/StateContainerRegistry';
2
- import type { ExtractArgs, ExtractDeps, ExtractState, StateContainerConstructor } from './types/utilities';
2
+ import type { ExtractArgs, ExtractDeps, ExtractState, StateContainerConstructor, StateContainerInstance } from './types/utilities';
3
3
  export declare function createTestRegistry(): StateContainerRegistry;
4
4
  export declare function withTestRegistry<T>(fn: (registry: StateContainerRegistry) => T): T;
5
5
  export declare function blacTestSetup(): void;
@@ -11,10 +11,7 @@ type MethodKeys<T> = {
11
11
  export interface CubitStubOptions<T extends StateContainerConstructor> {
12
12
  state?: ExtractState<T> extends Record<string, any> ? Partial<ExtractState<T>> : ExtractState<T>;
13
13
  methods?: Partial<Record<MethodKeys<InstanceType<T>>, (...args: any[]) => any>>;
14
- /**
15
- * Args to pass to init(). If the bloc's Args type is not void, supplying
16
- * args here causes initConfig({ args }) to be called so init() runs.
17
- */
14
+ /** Args passed to init(). */
18
15
  args?: ExtractArgs<T> extends void ? never : ExtractArgs<T>;
19
16
  /**
20
17
  * Deps slice to pre-wire via the core [APPLY_DEPS] path (synthetic owner
@@ -26,13 +23,18 @@ export declare function createCubitStub<T extends StateContainerConstructor>(Blo
26
23
  export declare function withBlocState<T extends StateContainerConstructor>(BlocClass: T, state: ExtractState<T> extends Record<string, any> ? Partial<ExtractState<T>> : ExtractState<T>, args?: ExtractArgs<T>): InstanceType<T>;
27
24
  export declare function withBlocMethod<T extends StateContainerConstructor>(BlocClass: T, methodName: keyof InstanceType<T>, impl: (...args: any[]) => any, args?: ExtractArgs<T>): InstanceType<T>;
28
25
  /**
29
- * Drain pending microtasks so any channel-flushed effects (channel
30
- * subscribers, `onSystemEvent('stateChanged')` handlers, plugin hooks) run
31
- * before the next assertion.
32
- *
33
- * The default `MicrotaskScheduler` coalesces emits within a tick; tests
34
- * that emit and then assert on subscriber side-effects need `await flush()`
35
- * between the two.
26
+ * Drain pending microtasks so channel-flushed effects (subscribers,
27
+ * `onSystemEvent('stateChanged')` handlers, plugin hooks) run before the
28
+ * next assertion. A subscriber can emit again, so this keeps draining until
29
+ * a round passes with no new state change.
36
30
  */
37
31
  export declare function flush(): Promise<void>;
32
+ /**
33
+ * Resolves with the first state of `bloc` that satisfies `predicate`: the
34
+ * current state if it already does, otherwise the first matching change.
35
+ * Rejects after `timeout` ms (default 1000).
36
+ */
37
+ export declare function waitForState<B extends StateContainerInstance>(bloc: B, predicate: (state: B['state']) => boolean, { timeout }?: {
38
+ timeout?: number;
39
+ }): Promise<B['state']>;
38
40
  export {};
package/dist/testing.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { StateContainerRegistry } from './core/StateContainerRegistry';
2
- import type { ExtractArgs, ExtractDeps, ExtractState, StateContainerConstructor } from './types/utilities';
2
+ import type { ExtractArgs, ExtractDeps, ExtractState, StateContainerConstructor, StateContainerInstance } from './types/utilities';
3
3
  export declare function createTestRegistry(): StateContainerRegistry;
4
4
  export declare function withTestRegistry<T>(fn: (registry: StateContainerRegistry) => T): T;
5
5
  export declare function blacTestSetup(): void;
@@ -11,10 +11,7 @@ type MethodKeys<T> = {
11
11
  export interface CubitStubOptions<T extends StateContainerConstructor> {
12
12
  state?: ExtractState<T> extends Record<string, any> ? Partial<ExtractState<T>> : ExtractState<T>;
13
13
  methods?: Partial<Record<MethodKeys<InstanceType<T>>, (...args: any[]) => any>>;
14
- /**
15
- * Args to pass to init(). If the bloc's Args type is not void, supplying
16
- * args here causes initConfig({ args }) to be called so init() runs.
17
- */
14
+ /** Args passed to init(). */
18
15
  args?: ExtractArgs<T> extends void ? never : ExtractArgs<T>;
19
16
  /**
20
17
  * Deps slice to pre-wire via the core [APPLY_DEPS] path (synthetic owner
@@ -26,13 +23,18 @@ export declare function createCubitStub<T extends StateContainerConstructor>(Blo
26
23
  export declare function withBlocState<T extends StateContainerConstructor>(BlocClass: T, state: ExtractState<T> extends Record<string, any> ? Partial<ExtractState<T>> : ExtractState<T>, args?: ExtractArgs<T>): InstanceType<T>;
27
24
  export declare function withBlocMethod<T extends StateContainerConstructor>(BlocClass: T, methodName: keyof InstanceType<T>, impl: (...args: any[]) => any, args?: ExtractArgs<T>): InstanceType<T>;
28
25
  /**
29
- * Drain pending microtasks so any channel-flushed effects (channel
30
- * subscribers, `onSystemEvent('stateChanged')` handlers, plugin hooks) run
31
- * before the next assertion.
32
- *
33
- * The default `MicrotaskScheduler` coalesces emits within a tick; tests
34
- * that emit and then assert on subscriber side-effects need `await flush()`
35
- * between the two.
26
+ * Drain pending microtasks so channel-flushed effects (subscribers,
27
+ * `onSystemEvent('stateChanged')` handlers, plugin hooks) run before the
28
+ * next assertion. A subscriber can emit again, so this keeps draining until
29
+ * a round passes with no new state change.
36
30
  */
37
31
  export declare function flush(): Promise<void>;
32
+ /**
33
+ * Resolves with the first state of `bloc` that satisfies `predicate`: the
34
+ * current state if it already does, otherwise the first matching change.
35
+ * Rejects after `timeout` ms (default 1000).
36
+ */
37
+ export declare function waitForState<B extends StateContainerInstance>(bloc: B, predicate: (state: B['state']) => boolean, { timeout }?: {
38
+ timeout?: number;
39
+ }): Promise<B['state']>;
38
40
  export {};
package/dist/testing.js CHANGED
@@ -1,7 +1,7 @@
1
- import { a as INIT_CONFIG, i as APPLY_DEPS, t as StateContainerRegistry } from "./StateContainerRegistry-DWOzx7Gd.js";
2
- import { n as Cubit, t as ensure } from "./ensure-11-asM1e.js";
3
- import { r as setRegistry, t as getRegistry } from "./config-D2A8ZYRM.js";
4
- import { n as resolveInstanceKey } from "./acquire-CU0u8BMn.js";
1
+ import { a as INSERT_INSTANCE, i as INIT_CONFIG, r as APPLY_DEPS, t as StateContainerRegistry } from "./StateContainerRegistry-CrTtRX5V.js";
2
+ import { i as getRegistry, o as setRegistry, r as getStateChangeCount } from "./StateContainer-CwByTd5L.js";
3
+ import { r as resolveInstanceKey, t as ensure } from "./ensure-CwtQVTam.js";
4
+ import { ALL_PATHS } from "@dirtytalk/structural";
5
5
  //#region src/testing.ts
6
6
  /** Synthetic owner id used by test helpers for pre-wired deps. */
7
7
  const TESTING_DEPS_OWNER = "testing-deps";
@@ -30,18 +30,21 @@ function withTestRegistry(fn) {
30
30
  }
31
31
  function blacTestSetup() {
32
32
  let savedRegistry;
33
+ let testRegistry;
33
34
  beforeEach(() => {
34
35
  savedRegistry = getRegistry();
35
- setRegistry(new StateContainerRegistry());
36
+ testRegistry = createTestRegistry();
37
+ setRegistry(testRegistry);
36
38
  });
37
39
  afterEach(() => {
40
+ testRegistry.clearAll();
38
41
  setRegistry(savedRegistry);
39
42
  });
40
43
  }
41
44
  function registerOverride(BlocClass, instance, args) {
42
45
  const registry = getRegistry();
43
46
  const key = resolveInstanceKey(BlocClass, args);
44
- registry.insertInstance(BlocClass, key, instance, new Map([["testing-override", 1]]));
47
+ registry[INSERT_INSTANCE](BlocClass, key, instance, new Map([["testing-override", 1]]));
45
48
  }
46
49
  function overrideEnsure(BlocClass, instance, fn, args) {
47
50
  return withTestRegistry(() => {
@@ -51,14 +54,8 @@ function overrideEnsure(BlocClass, instance, fn, args) {
51
54
  }
52
55
  function createCubitStub(BlocClass, options) {
53
56
  const instance = new BlocClass();
54
- if (options?.args != null) instance[INIT_CONFIG]({ args: options.args });
55
- if (options?.state != null) {
56
- if (instance instanceof Cubit) {
57
- const currentState = instance.state;
58
- if (typeof currentState === "object" && currentState !== null && typeof options.state === "object" && options.state !== null) instance.patch(options.state);
59
- else instance.emit(options.state);
60
- }
61
- }
57
+ instance[INIT_CONFIG]({ args: options?.args });
58
+ if (options?.state != null) applyState(instance, options.state);
62
59
  if (options?.methods) {
63
60
  for (const [key, impl] of Object.entries(options.methods)) if (typeof impl === "function") instance[key] = impl;
64
61
  }
@@ -67,32 +64,59 @@ function createCubitStub(BlocClass, options) {
67
64
  }
68
65
  function withBlocState(BlocClass, state, args) {
69
66
  const instance = ensure(BlocClass, { args });
70
- if (instance instanceof Cubit) {
71
- const currentState = instance.state;
72
- if (typeof currentState === "object" && currentState !== null && typeof state === "object" && state !== null) instance.patch(state);
73
- else instance.emit(state);
74
- }
67
+ applyState(instance, state);
75
68
  return instance;
76
69
  }
70
+ function applyState(instance, state) {
71
+ const target = instance;
72
+ if (typeof target.state === "object" && target.state !== null && typeof state === "object" && state !== null) target.patch(state);
73
+ else target.emit(state);
74
+ }
77
75
  function withBlocMethod(BlocClass, methodName, impl, args) {
78
76
  const instance = ensure(BlocClass, { args });
79
77
  instance[methodName] = impl;
80
78
  return instance;
81
79
  }
82
80
  /**
83
- * Drain pending microtasks so any channel-flushed effects (channel
84
- * subscribers, `onSystemEvent('stateChanged')` handlers, plugin hooks) run
85
- * before the next assertion.
86
- *
87
- * The default `MicrotaskScheduler` coalesces emits within a tick; tests
88
- * that emit and then assert on subscriber side-effects need `await flush()`
89
- * between the two.
81
+ * Drain pending microtasks so channel-flushed effects (subscribers,
82
+ * `onSystemEvent('stateChanged')` handlers, plugin hooks) run before the
83
+ * next assertion. A subscriber can emit again, so this keeps draining until
84
+ * a round passes with no new state change.
90
85
  */
91
86
  async function flush() {
92
- await Promise.resolve();
93
- await Promise.resolve();
87
+ for (let i = 0; i < MAX_FLUSH_ROUNDS; i++) {
88
+ const before = getStateChangeCount();
89
+ await Promise.resolve();
90
+ await Promise.resolve();
91
+ if (getStateChangeCount() === before) return;
92
+ }
93
+ throw new Error(`[blac] flush(): state was still changing after ${MAX_FLUSH_ROUNDS} rounds`);
94
+ }
95
+ const MAX_FLUSH_ROUNDS = 100;
96
+ /**
97
+ * Resolves with the first state of `bloc` that satisfies `predicate`: the
98
+ * current state if it already does, otherwise the first matching change.
99
+ * Rejects after `timeout` ms (default 1000).
100
+ */
101
+ function waitForState(bloc, predicate, { timeout = 1e3 } = {}) {
102
+ if (predicate(bloc.state)) return Promise.resolve(bloc.state);
103
+ return new Promise((resolve, reject) => {
104
+ const settle = () => {
105
+ clearTimeout(timer);
106
+ unsubscribe();
107
+ };
108
+ const unsubscribe = bloc.channel.subscribe(() => ALL_PATHS, () => {
109
+ if (!predicate(bloc.state)) return;
110
+ settle();
111
+ resolve(bloc.state);
112
+ });
113
+ const timer = setTimeout(() => {
114
+ settle();
115
+ reject(/* @__PURE__ */ new Error(`[blac] waitForState(): timed out after ${timeout}ms`));
116
+ }, timeout);
117
+ });
94
118
  }
95
119
  //#endregion
96
- export { blacTestSetup, createCubitStub, createTestRegistry, flush, overrideEnsure, registerOverride, withBlocMethod, withBlocState, withTestRegistry };
120
+ export { blacTestSetup, createCubitStub, createTestRegistry, flush, overrideEnsure, registerOverride, waitForState, withBlocMethod, withBlocState, withTestRegistry };
97
121
 
98
122
  //# sourceMappingURL=testing.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"testing.js","names":[],"sources":["../src/testing.ts"],"sourcesContent":["import { Cubit } from './core/Cubit';\nimport { StateContainerRegistry } from './core/StateContainerRegistry';\nimport { APPLY_DEPS, INIT_CONFIG } from './core/symbols';\nimport { ensure, getRegistry, setRegistry } from './registry';\nimport { resolveInstanceKey } from './registry/acquire';\nimport type {\n ExtractArgs,\n ExtractDeps,\n ExtractState,\n StateContainerConstructor,\n} from './types/utilities';\n\n/** Synthetic owner id used by test helpers for pre-wired deps. */\nconst TESTING_DEPS_OWNER = 'testing-deps';\n\ndeclare const beforeEach: (fn: () => void) => void;\ndeclare const afterEach: (fn: () => void) => void;\n\n// --- createTestRegistry + withTestRegistry ---\n\nexport function createTestRegistry(): StateContainerRegistry {\n return new StateContainerRegistry();\n}\n\nexport function withTestRegistry<T>(\n fn: (registry: StateContainerRegistry) => T,\n): T {\n const previous = getRegistry();\n const testRegistry = createTestRegistry();\n setRegistry(testRegistry);\n try {\n const result = fn(testRegistry);\n if (result instanceof Promise) {\n return result.then(\n (value) => {\n setRegistry(previous);\n return value;\n },\n (error) => {\n setRegistry(previous);\n throw error;\n },\n ) as T;\n }\n setRegistry(previous);\n return result;\n } catch (error) {\n setRegistry(previous);\n throw error;\n }\n}\n\n// --- blacTestSetup ---\n\nexport function blacTestSetup(): void {\n let savedRegistry: StateContainerRegistry;\n beforeEach(() => {\n savedRegistry = getRegistry();\n setRegistry(new StateContainerRegistry());\n });\n afterEach(() => {\n setRegistry(savedRegistry);\n });\n}\n\n// --- registerOverride + overrideEnsure ---\n\nexport function registerOverride<T extends StateContainerConstructor>(\n BlocClass: T,\n instance: InstanceType<T>,\n args?: ExtractArgs<T>,\n): void {\n const registry = getRegistry();\n const key = resolveInstanceKey(BlocClass, args);\n registry.insertInstance(\n BlocClass,\n key,\n instance,\n new Map([['testing-override', 1]]),\n );\n}\n\nexport function overrideEnsure<T extends StateContainerConstructor, R>(\n BlocClass: T,\n instance: InstanceType<T>,\n fn: () => R,\n args?: ExtractArgs<T>,\n): R {\n return withTestRegistry(() => {\n registerOverride(BlocClass, instance, args);\n return fn();\n });\n}\n\n// --- createCubitStub ---\n\ntype MethodKeys<T> = {\n [K in keyof T]: T[K] extends (...args: any[]) => any ? K : never;\n}[keyof T];\n\nexport interface CubitStubOptions<T extends StateContainerConstructor> {\n state?: ExtractState<T> extends Record<string, any>\n ? Partial<ExtractState<T>>\n : ExtractState<T>;\n methods?: Partial<\n Record<MethodKeys<InstanceType<T>>, (...args: any[]) => any>\n >;\n /**\n * Args to pass to init(). If the bloc's Args type is not void, supplying\n * args here causes initConfig({ args }) to be called so init() runs.\n */\n args?: ExtractArgs<T> extends void ? never : ExtractArgs<T>;\n /**\n * Deps slice to pre-wire via the core [APPLY_DEPS] path (synthetic owner\n * \"testing-deps\"), so onDepsChanged fires during tests.\n */\n deps?: Partial<ExtractDeps<T>>;\n}\n\nexport function createCubitStub<T extends StateContainerConstructor>(\n BlocClass: T,\n options?: CubitStubOptions<T>,\n): InstanceType<T> {\n const instance = new BlocClass() as InstanceType<T>;\n\n // Run init() if args are supplied — goes through the same initConfig path\n // that the registry uses, so lifecycle hooks fire correctly.\n if (options?.args != null) {\n instance[INIT_CONFIG]({ args: options.args });\n }\n\n if (options?.state != null) {\n if (instance instanceof Cubit) {\n const currentState = instance.state;\n if (\n typeof currentState === 'object' &&\n currentState !== null &&\n typeof options.state === 'object' &&\n options.state !== null\n ) {\n instance.patch(options.state as any);\n } else {\n instance.emit(options.state as any);\n }\n }\n }\n if (options?.methods) {\n for (const [key, impl] of Object.entries(options.methods)) {\n if (typeof impl === 'function') {\n (instance as any)[key] = impl;\n }\n }\n }\n\n // Pre-wire deps via the core merge path so onDepsChanged fires in tests.\n if (options?.deps != null) {\n (instance as any)[APPLY_DEPS](TESTING_DEPS_OWNER, options.deps);\n }\n\n return instance;\n}\n\n// --- withBlocState ---\n\nexport function withBlocState<T extends StateContainerConstructor>(\n BlocClass: T,\n state: ExtractState<T> extends Record<string, any>\n ? Partial<ExtractState<T>>\n : ExtractState<T>,\n args?: ExtractArgs<T>,\n): InstanceType<T> {\n const instance = ensure(BlocClass, { args });\n if (instance instanceof Cubit) {\n const currentState = instance.state;\n if (\n typeof currentState === 'object' &&\n currentState !== null &&\n typeof state === 'object' &&\n state !== null\n ) {\n instance.patch(state as any);\n } else {\n instance.emit(state as any);\n }\n }\n return instance;\n}\n\n// --- withBlocMethod ---\n\nexport function withBlocMethod<T extends StateContainerConstructor>(\n BlocClass: T,\n methodName: keyof InstanceType<T>,\n impl: (...args: any[]) => any,\n args?: ExtractArgs<T>,\n): InstanceType<T> {\n const instance = ensure(BlocClass, { args });\n (instance as any)[methodName] = impl;\n return instance;\n}\n\n// --- flush ---\n\n/**\n * Drain pending microtasks so any channel-flushed effects (channel\n * subscribers, `onSystemEvent('stateChanged')` handlers, plugin hooks) run\n * before the next assertion.\n *\n * The default `MicrotaskScheduler` coalesces emits within a tick; tests\n * that emit and then assert on subscriber side-effects need `await flush()`\n * between the two.\n */\nexport async function flush(): Promise<void> {\n // queueMicrotask wins the race against the channel's own queued flush —\n // we resolve after the channel has drained its current pending flush.\n await Promise.resolve();\n await Promise.resolve();\n}\n"],"mappings":";;;;;;AAaA,MAAM,qBAAqB;AAO3B,SAAgB,qBAA6C;CAC3D,OAAO,IAAI,uBAAuB;AACpC;AAEA,SAAgB,iBACd,IACG;CACH,MAAM,WAAW,YAAY;CAC7B,MAAM,eAAe,mBAAmB;CACxC,YAAY,YAAY;CACxB,IAAI;EACF,MAAM,SAAS,GAAG,YAAY;EAC9B,IAAI,kBAAkB,SACpB,OAAO,OAAO,MACX,UAAU;GACT,YAAY,QAAQ;GACpB,OAAO;EACT,IACC,UAAU;GACT,YAAY,QAAQ;GACpB,MAAM;EACR,CACF;EAEF,YAAY,QAAQ;EACpB,OAAO;CACT,SAAS,OAAO;EACd,YAAY,QAAQ;EACpB,MAAM;CACR;AACF;AAIA,SAAgB,gBAAsB;CACpC,IAAI;CACJ,iBAAiB;EACf,gBAAgB,YAAY;EAC5B,YAAY,IAAI,uBAAuB,CAAC;CAC1C,CAAC;CACD,gBAAgB;EACd,YAAY,aAAa;CAC3B,CAAC;AACH;AAIA,SAAgB,iBACd,WACA,UACA,MACM;CACN,MAAM,WAAW,YAAY;CAC7B,MAAM,MAAM,mBAAmB,WAAW,IAAI;CAC9C,SAAS,eACP,WACA,KACA,UACA,IAAI,IAAI,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,CACnC;AACF;AAEA,SAAgB,eACd,WACA,UACA,IACA,MACG;CACH,OAAO,uBAAuB;EAC5B,iBAAiB,WAAW,UAAU,IAAI;EAC1C,OAAO,GAAG;CACZ,CAAC;AACH;AA2BA,SAAgB,gBACd,WACA,SACiB;CACjB,MAAM,WAAW,IAAI,UAAU;CAI/B,IAAI,SAAS,QAAQ,MACnB,SAAS,aAAa,EAAE,MAAM,QAAQ,KAAK,CAAC;CAG9C,IAAI,SAAS,SAAS;MAChB,oBAAoB,OAAO;GAC7B,MAAM,eAAe,SAAS;GAC9B,IACE,OAAO,iBAAiB,YACxB,iBAAiB,QACjB,OAAO,QAAQ,UAAU,YACzB,QAAQ,UAAU,MAElB,SAAS,MAAM,QAAQ,KAAY;QAEnC,SAAS,KAAK,QAAQ,KAAY;EAEtC;;CAEF,IAAI,SAAS;OACN,MAAM,CAAC,KAAK,SAAS,OAAO,QAAQ,QAAQ,OAAO,GACtD,IAAI,OAAO,SAAS,YAClB,SAAkB,OAAO;CAAA;CAM/B,IAAI,SAAS,QAAQ,MACnB,SAAkB,YAAY,oBAAoB,QAAQ,IAAI;CAGhE,OAAO;AACT;AAIA,SAAgB,cACd,WACA,OAGA,MACiB;CACjB,MAAM,WAAW,OAAO,WAAW,EAAE,KAAK,CAAC;CAC3C,IAAI,oBAAoB,OAAO;EAC7B,MAAM,eAAe,SAAS;EAC9B,IACE,OAAO,iBAAiB,YACxB,iBAAiB,QACjB,OAAO,UAAU,YACjB,UAAU,MAEV,SAAS,MAAM,KAAY;OAE3B,SAAS,KAAK,KAAY;CAE9B;CACA,OAAO;AACT;AAIA,SAAgB,eACd,WACA,YACA,MACA,MACiB;CACjB,MAAM,WAAW,OAAO,WAAW,EAAE,KAAK,CAAC;CAC3C,SAAkB,cAAc;CAChC,OAAO;AACT;;;;;;;;;;AAaA,eAAsB,QAAuB;CAG3C,MAAM,QAAQ,QAAQ;CACtB,MAAM,QAAQ,QAAQ;AACxB"}
1
+ {"version":3,"file":"testing.js","names":[],"sources":["../src/testing.ts"],"sourcesContent":["import { ALL_PATHS } from '@dirtytalk/structural';\nimport type { Cubit } from './core/Cubit';\nimport { getStateChangeCount } from './core/StateContainer';\nimport { StateContainerRegistry } from './core/StateContainerRegistry';\nimport { APPLY_DEPS, INIT_CONFIG, INSERT_INSTANCE } from './core/symbols';\nimport { ensure, getRegistry, setRegistry } from './registry';\nimport { resolveInstanceKey } from './registry/acquire';\nimport type {\n ExtractArgs,\n ExtractDeps,\n ExtractState,\n StateContainerConstructor,\n StateContainerInstance,\n} from './types/utilities';\n\n/** Synthetic owner id used by test helpers for pre-wired deps. */\nconst TESTING_DEPS_OWNER = 'testing-deps';\n\ndeclare const beforeEach: (fn: () => void) => void;\ndeclare const afterEach: (fn: () => void) => void;\n\nexport function createTestRegistry(): StateContainerRegistry {\n return new StateContainerRegistry();\n}\n\nexport function withTestRegistry<T>(\n fn: (registry: StateContainerRegistry) => T,\n): T {\n const previous = getRegistry();\n const testRegistry = createTestRegistry();\n setRegistry(testRegistry);\n try {\n const result = fn(testRegistry);\n if (result instanceof Promise) {\n return result.then(\n (value) => {\n setRegistry(previous);\n return value;\n },\n (error) => {\n setRegistry(previous);\n throw error;\n },\n ) as T;\n }\n setRegistry(previous);\n return result;\n } catch (error) {\n setRegistry(previous);\n throw error;\n }\n}\n\nexport function blacTestSetup(): void {\n let savedRegistry: StateContainerRegistry;\n let testRegistry: StateContainerRegistry;\n beforeEach(() => {\n savedRegistry = getRegistry();\n testRegistry = createTestRegistry();\n setRegistry(testRegistry);\n });\n afterEach(() => {\n testRegistry.clearAll();\n setRegistry(savedRegistry);\n });\n}\n\nexport function registerOverride<T extends StateContainerConstructor>(\n BlocClass: T,\n instance: InstanceType<T>,\n args?: ExtractArgs<T>,\n): void {\n const registry = getRegistry();\n const key = resolveInstanceKey(BlocClass, args);\n registry[INSERT_INSTANCE](\n BlocClass,\n key,\n instance,\n new Map([['testing-override', 1]]),\n );\n}\n\nexport function overrideEnsure<T extends StateContainerConstructor, R>(\n BlocClass: T,\n instance: InstanceType<T>,\n fn: () => R,\n args?: ExtractArgs<T>,\n): R {\n return withTestRegistry(() => {\n registerOverride(BlocClass, instance, args);\n return fn();\n });\n}\n\ntype MethodKeys<T> = {\n [K in keyof T]: T[K] extends (...args: any[]) => any ? K : never;\n}[keyof T];\n\nexport interface CubitStubOptions<T extends StateContainerConstructor> {\n state?: ExtractState<T> extends Record<string, any>\n ? Partial<ExtractState<T>>\n : ExtractState<T>;\n methods?: Partial<\n Record<MethodKeys<InstanceType<T>>, (...args: any[]) => any>\n >;\n /** Args passed to init(). */\n args?: ExtractArgs<T> extends void ? never : ExtractArgs<T>;\n /**\n * Deps slice to pre-wire via the core [APPLY_DEPS] path (synthetic owner\n * \"testing-deps\"), so onDepsChanged fires during tests.\n */\n deps?: Partial<ExtractDeps<T>>;\n}\n\nexport function createCubitStub<T extends StateContainerConstructor>(\n BlocClass: T,\n options?: CubitStubOptions<T>,\n): InstanceType<T> {\n const instance = new BlocClass() as InstanceType<T>;\n instance[INIT_CONFIG]({ args: options?.args });\n\n if (options?.state != null) {\n applyState(instance, options.state);\n }\n if (options?.methods) {\n for (const [key, impl] of Object.entries(options.methods)) {\n if (typeof impl === 'function') {\n (instance as any)[key] = impl;\n }\n }\n }\n\n // Pre-wire deps via the core merge path so onDepsChanged fires in tests.\n if (options?.deps != null) {\n (instance as any)[APPLY_DEPS](TESTING_DEPS_OWNER, options.deps);\n }\n\n return instance;\n}\n\nexport function withBlocState<T extends StateContainerConstructor>(\n BlocClass: T,\n state: ExtractState<T> extends Record<string, any>\n ? Partial<ExtractState<T>>\n : ExtractState<T>,\n args?: ExtractArgs<T>,\n): InstanceType<T> {\n const instance = ensure(BlocClass, { args });\n applyState(instance, state);\n return instance;\n}\n\n// emit/patch are protected on StateContainer; Cubit only makes them public.\nfunction applyState(instance: object, state: unknown): void {\n const target = instance as Cubit<any>;\n if (\n typeof target.state === 'object' &&\n target.state !== null &&\n typeof state === 'object' &&\n state !== null\n ) {\n target.patch(state);\n } else {\n target.emit(state as any);\n }\n}\n\nexport function withBlocMethod<T extends StateContainerConstructor>(\n BlocClass: T,\n methodName: keyof InstanceType<T>,\n impl: (...args: any[]) => any,\n args?: ExtractArgs<T>,\n): InstanceType<T> {\n const instance = ensure(BlocClass, { args });\n (instance as any)[methodName] = impl;\n return instance;\n}\n\n/**\n * Drain pending microtasks so channel-flushed effects (subscribers,\n * `onSystemEvent('stateChanged')` handlers, plugin hooks) run before the\n * next assertion. A subscriber can emit again, so this keeps draining until\n * a round passes with no new state change.\n */\nexport async function flush(): Promise<void> {\n for (let i = 0; i < MAX_FLUSH_ROUNDS; i++) {\n const before = getStateChangeCount();\n // The second tick lets microtasks queued by the drain itself (registry\n // `stateChanged` delivery) run too.\n await Promise.resolve();\n await Promise.resolve();\n if (getStateChangeCount() === before) return;\n }\n throw new Error(\n `[blac] flush(): state was still changing after ${MAX_FLUSH_ROUNDS} rounds`,\n );\n}\n\nconst MAX_FLUSH_ROUNDS = 100;\n\n/**\n * Resolves with the first state of `bloc` that satisfies `predicate`: the\n * current state if it already does, otherwise the first matching change.\n * Rejects after `timeout` ms (default 1000).\n */\nexport function waitForState<B extends StateContainerInstance>(\n bloc: B,\n predicate: (state: B['state']) => boolean,\n { timeout = 1000 }: { timeout?: number } = {},\n): Promise<B['state']> {\n if (predicate(bloc.state)) return Promise.resolve(bloc.state);\n\n return new Promise((resolve, reject) => {\n const settle = () => {\n clearTimeout(timer);\n unsubscribe();\n };\n const unsubscribe = bloc.channel.subscribe(\n () => ALL_PATHS,\n () => {\n if (!predicate(bloc.state)) return;\n settle();\n resolve(bloc.state);\n },\n );\n const timer = setTimeout(() => {\n settle();\n reject(new Error(`[blac] waitForState(): timed out after ${timeout}ms`));\n }, timeout);\n });\n}\n"],"mappings":";;;;;;AAgBA,MAAM,qBAAqB;AAK3B,SAAgB,qBAA6C;CAC3D,OAAO,IAAI,uBAAuB;AACpC;AAEA,SAAgB,iBACd,IACG;CACH,MAAM,WAAW,YAAY;CAC7B,MAAM,eAAe,mBAAmB;CACxC,YAAY,YAAY;CACxB,IAAI;EACF,MAAM,SAAS,GAAG,YAAY;EAC9B,IAAI,kBAAkB,SACpB,OAAO,OAAO,MACX,UAAU;GACT,YAAY,QAAQ;GACpB,OAAO;EACT,IACC,UAAU;GACT,YAAY,QAAQ;GACpB,MAAM;EACR,CACF;EAEF,YAAY,QAAQ;EACpB,OAAO;CACT,SAAS,OAAO;EACd,YAAY,QAAQ;EACpB,MAAM;CACR;AACF;AAEA,SAAgB,gBAAsB;CACpC,IAAI;CACJ,IAAI;CACJ,iBAAiB;EACf,gBAAgB,YAAY;EAC5B,eAAe,mBAAmB;EAClC,YAAY,YAAY;CAC1B,CAAC;CACD,gBAAgB;EACd,aAAa,SAAS;EACtB,YAAY,aAAa;CAC3B,CAAC;AACH;AAEA,SAAgB,iBACd,WACA,UACA,MACM;CACN,MAAM,WAAW,YAAY;CAC7B,MAAM,MAAM,mBAAmB,WAAW,IAAI;CAC9C,SAAS,iBACP,WACA,KACA,UACA,IAAI,IAAI,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,CACnC;AACF;AAEA,SAAgB,eACd,WACA,UACA,IACA,MACG;CACH,OAAO,uBAAuB;EAC5B,iBAAiB,WAAW,UAAU,IAAI;EAC1C,OAAO,GAAG;CACZ,CAAC;AACH;AAsBA,SAAgB,gBACd,WACA,SACiB;CACjB,MAAM,WAAW,IAAI,UAAU;CAC/B,SAAS,aAAa,EAAE,MAAM,SAAS,KAAK,CAAC;CAE7C,IAAI,SAAS,SAAS,MACpB,WAAW,UAAU,QAAQ,KAAK;CAEpC,IAAI,SAAS;OACN,MAAM,CAAC,KAAK,SAAS,OAAO,QAAQ,QAAQ,OAAO,GACtD,IAAI,OAAO,SAAS,YAClB,SAAkB,OAAO;CAAA;CAM/B,IAAI,SAAS,QAAQ,MACnB,SAAkB,YAAY,oBAAoB,QAAQ,IAAI;CAGhE,OAAO;AACT;AAEA,SAAgB,cACd,WACA,OAGA,MACiB;CACjB,MAAM,WAAW,OAAO,WAAW,EAAE,KAAK,CAAC;CAC3C,WAAW,UAAU,KAAK;CAC1B,OAAO;AACT;AAGA,SAAS,WAAW,UAAkB,OAAsB;CAC1D,MAAM,SAAS;CACf,IACE,OAAO,OAAO,UAAU,YACxB,OAAO,UAAU,QACjB,OAAO,UAAU,YACjB,UAAU,MAEV,OAAO,MAAM,KAAK;MAElB,OAAO,KAAK,KAAY;AAE5B;AAEA,SAAgB,eACd,WACA,YACA,MACA,MACiB;CACjB,MAAM,WAAW,OAAO,WAAW,EAAE,KAAK,CAAC;CAC3C,SAAkB,cAAc;CAChC,OAAO;AACT;;;;;;;AAQA,eAAsB,QAAuB;CAC3C,KAAK,IAAI,IAAI,GAAG,IAAI,kBAAkB,KAAK;EACzC,MAAM,SAAS,oBAAoB;EAGnC,MAAM,QAAQ,QAAQ;EACtB,MAAM,QAAQ,QAAQ;EACtB,IAAI,oBAAoB,MAAM,QAAQ;CACxC;CACA,MAAM,IAAI,MACR,kDAAkD,iBAAiB,QACrE;AACF;AAEA,MAAM,mBAAmB;;;;;;AAOzB,SAAgB,aACd,MACA,WACA,EAAE,UAAU,QAA+B,CAAC,GACvB;CACrB,IAAI,UAAU,KAAK,KAAK,GAAG,OAAO,QAAQ,QAAQ,KAAK,KAAK;CAE5D,OAAO,IAAI,SAAS,SAAS,WAAW;EACtC,MAAM,eAAe;GACnB,aAAa,KAAK;GAClB,YAAY;EACd;EACA,MAAM,cAAc,KAAK,QAAQ,gBACzB,iBACA;GACJ,IAAI,CAAC,UAAU,KAAK,KAAK,GAAG;GAC5B,OAAO;GACP,QAAQ,KAAK,KAAK;EACpB,CACF;EACA,MAAM,QAAQ,iBAAiB;GAC7B,OAAO;GACP,uBAAO,IAAI,MAAM,0CAA0C,QAAQ,GAAG,CAAC;EACzE,GAAG,OAAO;CACZ,CAAC;AACH"}
@@ -1,26 +1,19 @@
1
1
  declare const brand: unique symbol;
2
2
  /**
3
- * Utility type for creating branded/nominal types.
4
- * Prevents accidental type confusion between similar primitive types.
5
- * @template T - The base type
6
- * @template B - The brand identifier
3
+ * Nominal type helper, preventing accidental confusion between similar
4
+ * primitive types.
5
+ * @typeParam T - The base type
6
+ * @typeParam B - The brand identifier
7
7
  */
8
8
  export type Brand<T, B> = T & {
9
9
  [brand]: B;
10
10
  };
11
11
  /**
12
12
  * Branded string type for type-safe IDs.
13
- * @template B - The brand identifier
13
+ * @typeParam B - The brand identifier
14
14
  */
15
15
  export type BrandedId<B> = Brand<string, B>;
16
- /**
17
- * Branded string type for state container instance IDs
18
- */
16
+ /** Branded string type for state container instance IDs. */
19
17
  export type InstanceId = Brand<string, 'InstanceId'>;
20
- /**
21
- * Create a branded InstanceId from a string
22
- * @param id - The string ID to brand
23
- * @returns Branded InstanceId
24
- */
25
18
  export declare function instanceId(id: string): InstanceId;
26
19
  export {};
@@ -1,51 +1,60 @@
1
1
  import type { StateContainer } from '../core/StateContainer';
2
2
  /**
3
- * Extract the state type from a StateContainer
4
- * @template T - The StateContainer type
3
+ * Recursively mark all properties readonly. The mirror of
4
+ * `DeepPartial` in `@dirtytalk/structural`, and carves out the same
5
+ * built-ins for the same reason.
6
+ *
7
+ * - Arrays become `ReadonlyArray`, recursing into the element type.
8
+ * - `Map`/`Set` become their `Readonly` counterparts so their contents are
9
+ * frozen too, rather than only the binding.
10
+ * - `Date | RegExp` are kept as-is; mapping over them would freeze their
11
+ * prototype methods instead of their (inaccessible) internal state.
12
+ * - Primitives and functions pass through unchanged.
13
+ *
14
+ * @typeParam T - The type to deeply freeze
15
+ * @public
5
16
  */
6
- export type ExtractState<T> = T extends StateContainerConstructor<infer S> ? Readonly<S> : never;
17
+ export type DeepReadonly<T> = T extends (...args: any[]) => any ? T : T extends ReadonlyArray<infer U> ? ReadonlyArray<DeepReadonly<U>> : T extends ReadonlyMap<infer K, infer V> ? ReadonlyMap<DeepReadonly<K>, DeepReadonly<V>> : T extends ReadonlySet<infer U> ? ReadonlySet<DeepReadonly<U>> : T extends Date | RegExp ? T : T extends object ? {
18
+ readonly [K in keyof T]: DeepReadonly<T[K]>;
19
+ } : T;
20
+ /**
21
+ * Extract the state type from a StateContainer, deeply readonly.
22
+ *
23
+ * State is owned by the container: consumers read it and mutate only through
24
+ * `emit`/`patch`, so nested writes are a compile error rather than a silent
25
+ * desync from the change-tracking channel.
26
+ *
27
+ * @typeParam T - The StateContainer type
28
+ */
29
+ export type ExtractState<T> = T extends StateContainerConstructor<infer S> ? DeepReadonly<S> : never;
7
30
  export type ExtractStateMutable<T> = T extends StateContainerConstructor<infer S> ? S : never;
8
31
  /**
9
32
  * Constructor type for StateContainer classes
10
- * @template S - State type managed by the container
33
+ * @typeParam S - State type managed by the container
11
34
  */
12
- export type StateContainerConstructor<S extends object = any> = new (...args: any[]) => StateContainer<S, any, any>;
35
+ export type StateContainerConstructor<S extends object = any> = new () => StateContainer<S, any, any>;
13
36
  /**
14
37
  * Extract the args type (serializable construction/identity data) from a
15
38
  * StateContainer subclass.
16
- * @template T - The StateContainer constructor type
39
+ * @typeParam T - The StateContainer constructor type
17
40
  */
18
41
  export type ExtractArgs<T> = T extends new () => StateContainer<any, infer A, any> ? A : void;
19
42
  /**
20
43
  * Extract the deps type (injected non-serializable handles) from a
21
44
  * StateContainer subclass.
22
- * @template T - The StateContainer constructor type
45
+ * @typeParam T - The StateContainer constructor type
23
46
  */
24
47
  export type ExtractDeps<T> = T extends new () => StateContainer<any, any, infer D> ? D : Record<string, never>;
25
- export type InstanceReadonlyState<T extends StateContainerConstructor = any> = Omit<InstanceType<T>, 'state'> & {
26
- state: ExtractState<T>;
27
- };
28
- export type InstanceState<T extends StateContainerConstructor = any> = Omit<InstanceType<T>, 'state'> & {
29
- state: ExtractStateMutable<T>;
30
- };
31
- export type StateContainerInstance<S extends object = any> = Omit<StateContainer<S, any, any>, 'state'> & {
32
- state: Readonly<S>;
33
- };
34
- /**
35
- * Extract constructor argument types from a class
36
- * @template T - The class type
37
- */
38
- export type ExtractConstructorArgs<T> = T extends new (...args: infer P) => any ? P : never[];
39
- /**
40
- * Extract instance type from an abstract class constructor
41
- * @template T - The abstract class constructor type
42
- */
43
- export type BlocInstanceType<T extends abstract new (...args: any) => any> = T extends abstract new (...args: any) => infer R ? R : any;
44
48
  /**
45
- * Constructor type for StateContainer classes.
46
- * Used for type-safe hook parameters.
47
- * @template TBloc - The StateContainer instance type
49
+ * Narrow a container instance's `state` without erasing the class. A plain
50
+ * intersection keeps private members, `this` types and symbol keys, so the
51
+ * result stays assignable to `StateContainer`; `state` is getter-only at the
52
+ * source, so no `readonly` modifier is needed here.
53
+ * @public
48
54
  */
49
- export type BlocConstructor<S extends object = any, T extends new (...args: any[]) => StateContainer<S, any, any> = new (...args: any[]) => StateContainer<S, any, any>> = (new (...args: any[]) => InstanceType<T>) & {
50
- keepAlive?: boolean;
55
+ export type WithState<I, S> = I & {
56
+ state: S;
51
57
  };
58
+ export type InstanceReadonlyState<T extends StateContainerConstructor = StateContainerConstructor> = WithState<InstanceType<T>, ExtractState<T>>;
59
+ export type InstanceState<T extends StateContainerConstructor = StateContainerConstructor> = WithState<InstanceType<T>, ExtractStateMutable<T>>;
60
+ export type StateContainerInstance<S extends object = any> = WithState<StateContainer<S, any, any>, Readonly<S>>;