@logixjs/core 0.0.1 → 0.0.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 (300) hide show
  1. package/LICENSE +201 -0
  2. package/dist/{Bound-BN1DQ_lM.d.ts → Bound-CEa1ihvH.d.ts} +2 -2
  3. package/dist/{Bound-BPIfH9SS.d.cts → Bound-CNLNkC7c.d.cts} +2 -2
  4. package/dist/Bound.cjs +620 -163
  5. package/dist/Bound.cjs.map +1 -1
  6. package/dist/Bound.d.cts +3 -3
  7. package/dist/Bound.d.ts +3 -3
  8. package/dist/Bound.js +14 -14
  9. package/dist/{Debug-Bq8Sqjcr.d.cts → Debug-BhMYr-1i.d.cts} +3 -3
  10. package/dist/{Debug-B5q5Bkzx.d.ts → Debug-ByM7m4Ft.d.ts} +3 -3
  11. package/dist/Debug.cjs +553 -32
  12. package/dist/Debug.cjs.map +1 -1
  13. package/dist/Debug.d.cts +10 -8
  14. package/dist/Debug.d.ts +10 -8
  15. package/dist/Debug.js +12 -10
  16. package/dist/EffectOp.cjs.map +1 -1
  17. package/dist/EffectOp.js +2 -3
  18. package/dist/EffectOp.js.map +1 -1
  19. package/dist/Env.cjs +664 -6
  20. package/dist/Env.cjs.map +1 -1
  21. package/dist/Env.js +5 -2
  22. package/dist/ExternalStore-BAz83PVq.d.cts +60 -0
  23. package/dist/ExternalStore-BYWPbYs8.d.ts +60 -0
  24. package/dist/ExternalStore.cjs +746 -0
  25. package/dist/ExternalStore.cjs.map +1 -0
  26. package/dist/ExternalStore.d.cts +4 -0
  27. package/dist/ExternalStore.d.ts +4 -0
  28. package/dist/ExternalStore.js +19 -0
  29. package/dist/ExternalStore.js.map +1 -0
  30. package/dist/{Flow-1fZT8MpX.d.cts → Flow-BlSoMmhV.d.cts} +2 -2
  31. package/dist/{Flow-BhpjE22E.d.ts → Flow-CQSGve5c.d.ts} +2 -2
  32. package/dist/Flow.cjs +2 -2
  33. package/dist/Flow.cjs.map +1 -1
  34. package/dist/Flow.d.cts +4 -4
  35. package/dist/Flow.d.ts +4 -4
  36. package/dist/Flow.js +7 -8
  37. package/dist/{Handle-D_cLW1Z3.d.ts → Handle-B7PSmsrY.d.ts} +1 -1
  38. package/dist/{Handle-D8D1zPb_.d.cts → Handle-ByovhL-c.d.cts} +1 -1
  39. package/dist/Handle.d.cts +3 -3
  40. package/dist/Handle.d.ts +3 -3
  41. package/dist/{Kernel-CnGE1Fyk.d.ts → Kernel-DGSpS4GM.d.ts} +2 -2
  42. package/dist/{Kernel-8kC-jOda.d.cts → Kernel-DZAk-Mrn.d.cts} +2 -2
  43. package/dist/Kernel.cjs +680 -22
  44. package/dist/Kernel.cjs.map +1 -1
  45. package/dist/Kernel.d.cts +10 -8
  46. package/dist/Kernel.d.ts +10 -8
  47. package/dist/Kernel.js +7 -4
  48. package/dist/{Link-Db7975nU.d.ts → Link-Cm4eR9n0.d.ts} +10 -3
  49. package/dist/{Link-fX8x1eCK.d.cts → Link-DF8i8iWR.d.cts} +10 -3
  50. package/dist/Link.cjs +1128 -86
  51. package/dist/Link.cjs.map +1 -1
  52. package/dist/Link.d.cts +3 -3
  53. package/dist/Link.d.ts +3 -3
  54. package/dist/Link.js +30 -25
  55. package/dist/{Logic-DRh4sDZj.d.cts → Logic-BcQA0AvE.d.cts} +1 -1
  56. package/dist/{Logic-BRjEMr-W.d.ts → Logic-OotSE1xw.d.ts} +1 -1
  57. package/dist/Logic.d.cts +3 -3
  58. package/dist/Logic.d.ts +3 -3
  59. package/dist/{MatchBuilder-CJk5oCkR.d.cts → MatchBuilder-BNDJ8waF.d.ts} +1 -1
  60. package/dist/{MatchBuilder-0QOc-nlU.d.ts → MatchBuilder-CvZ5WY1B.d.cts} +1 -1
  61. package/dist/MatchBuilder.d.cts +4 -4
  62. package/dist/MatchBuilder.d.ts +4 -4
  63. package/dist/Middleware-D8tUDLv_.d.cts +100 -0
  64. package/dist/Middleware-DS7CbTTN.d.ts +100 -0
  65. package/dist/Middleware.cjs +461 -13
  66. package/dist/Middleware.cjs.map +1 -1
  67. package/dist/Middleware.d.cts +2 -86
  68. package/dist/Middleware.d.ts +2 -86
  69. package/dist/Middleware.js +13 -11
  70. package/dist/{Module-DnzluX2J.d.ts → Module-CFj0I2yE.d.ts} +45 -18
  71. package/dist/{Module-B_0xRDMR.d.cts → Module-DpXPW9EQ.d.cts} +45 -18
  72. package/dist/Module.cjs +8583 -5741
  73. package/dist/Module.cjs.map +1 -1
  74. package/dist/Module.d.cts +5 -4
  75. package/dist/Module.d.ts +5 -4
  76. package/dist/Module.js +32 -27
  77. package/dist/ModuleTag-BcVF6z7B.d.ts +113 -0
  78. package/dist/ModuleTag-DuZXo_NS.d.cts +113 -0
  79. package/dist/ModuleTag.cjs +2609 -1232
  80. package/dist/ModuleTag.cjs.map +1 -1
  81. package/dist/ModuleTag.d.cts +4 -4
  82. package/dist/ModuleTag.d.ts +4 -4
  83. package/dist/ModuleTag.js +28 -25
  84. package/dist/{Observability-cY4kLn0S.d.ts → Observability-D-ZWeEVb.d.ts} +22 -15
  85. package/dist/{Observability-COqEvp2C.d.cts → Observability-V7sRMYTh.d.cts} +22 -15
  86. package/dist/Observability.cjs +1938 -640
  87. package/dist/Observability.cjs.map +1 -1
  88. package/dist/Observability.d.cts +4 -4
  89. package/dist/Observability.d.ts +4 -4
  90. package/dist/Observability.js +21 -19
  91. package/dist/{Process-mL8fHDSB.d.cts → Process-B55aJMFk.d.cts} +29 -4
  92. package/dist/{Process-CM9xbMdP.d.ts → Process-DvhFEwUS.d.ts} +29 -4
  93. package/dist/Process.cjs +1122 -85
  94. package/dist/Process.cjs.map +1 -1
  95. package/dist/Process.d.cts +4 -3
  96. package/dist/Process.d.ts +4 -3
  97. package/dist/Process.js +27 -22
  98. package/dist/{ReadQuery-BlMwhe-F.d.ts → ReadQuery-C4vZ8Prc.d.ts} +2 -2
  99. package/dist/{ReadQuery-SinbStGF.d.ts → ReadQuery-CafjlJQo.d.cts} +1 -1
  100. package/dist/{ReadQuery-SinbStGF.d.cts → ReadQuery-CafjlJQo.d.ts} +1 -1
  101. package/dist/{ReadQuery-CL5XlXts.d.cts → ReadQuery-mc0NgrFV.d.cts} +2 -2
  102. package/dist/ReadQuery.cjs +3 -3
  103. package/dist/ReadQuery.cjs.map +1 -1
  104. package/dist/ReadQuery.d.cts +2 -2
  105. package/dist/ReadQuery.d.ts +2 -2
  106. package/dist/ReadQuery.js +3 -3
  107. package/dist/{Reflection-CQnKwPXj.d.ts → Reflection-C8xZ267q.d.ts} +88 -7
  108. package/dist/{Reflection-Kabo1mlU.d.cts → Reflection-DP7Vsv3f.d.cts} +88 -7
  109. package/dist/Reflection.cjs +2934 -1553
  110. package/dist/Reflection.cjs.map +1 -1
  111. package/dist/Reflection.d.cts +14 -11
  112. package/dist/Reflection.d.ts +14 -11
  113. package/dist/Reflection.js +26 -21
  114. package/dist/Resource.cjs +670 -12
  115. package/dist/Resource.cjs.map +1 -1
  116. package/dist/Resource.js +6 -3
  117. package/dist/Root.cjs +675 -17
  118. package/dist/Root.cjs.map +1 -1
  119. package/dist/Root.js +7 -3
  120. package/dist/{Runtime-CtyzZG4i.d.ts → Runtime-BWc9YfUB.d.ts} +37 -7
  121. package/dist/{Runtime-B-aL-f29.d.cts → Runtime-PShIC4DW.d.cts} +37 -7
  122. package/dist/Runtime.cjs +1899 -809
  123. package/dist/Runtime.cjs.map +1 -1
  124. package/dist/Runtime.d.cts +14 -11
  125. package/dist/Runtime.d.ts +14 -11
  126. package/dist/Runtime.js +33 -28
  127. package/dist/ScopeRegistry.cjs +668 -10
  128. package/dist/ScopeRegistry.cjs.map +1 -1
  129. package/dist/ScopeRegistry.js +6 -3
  130. package/dist/{StateTrait-OWhbj12c.d.cts → StateTrait-CQsDlXJm.d.cts} +23 -6
  131. package/dist/{StateTrait-BGsZghTz.d.ts → StateTrait-YvJzVDKl.d.ts} +23 -6
  132. package/dist/StateTrait.cjs +1475 -370
  133. package/dist/StateTrait.cjs.map +1 -1
  134. package/dist/StateTrait.d.cts +7 -5
  135. package/dist/StateTrait.d.ts +7 -5
  136. package/dist/StateTrait.js +17 -14
  137. package/dist/{TraitLifecycle-LdIWmKlg.d.ts → TraitLifecycle-CjIBICAA.d.ts} +2 -2
  138. package/dist/{TraitLifecycle-CwV5WPFX.d.cts → TraitLifecycle-NmqGiXPC.d.cts} +2 -2
  139. package/dist/TraitLifecycle.cjs +489 -32
  140. package/dist/TraitLifecycle.cjs.map +1 -1
  141. package/dist/TraitLifecycle.d.cts +4 -4
  142. package/dist/TraitLifecycle.d.ts +4 -4
  143. package/dist/TraitLifecycle.js +7 -7
  144. package/dist/Workflow-BlFG_20_.d.cts +414 -0
  145. package/dist/Workflow-CW9S_aAP.d.ts +414 -0
  146. package/dist/Workflow.cjs +2977 -0
  147. package/dist/Workflow.cjs.map +1 -0
  148. package/dist/Workflow.d.cts +7 -0
  149. package/dist/Workflow.d.ts +7 -0
  150. package/dist/Workflow.js +55 -0
  151. package/dist/Workflow.js.map +1 -0
  152. package/dist/{chunk-G5ZBFPNU.js → chunk-2A4UKO2D.js} +2 -2
  153. package/dist/chunk-2DE6D42I.js +248 -0
  154. package/dist/chunk-2DE6D42I.js.map +1 -0
  155. package/dist/{chunk-ANLBCBDC.js → chunk-2DVLMSOE.js} +6 -6
  156. package/dist/{chunk-BE3HW4FY.js → chunk-34CF6OGE.js} +14 -16
  157. package/dist/chunk-34CF6OGE.js.map +1 -0
  158. package/dist/{chunk-ZFY7U2FR.js → chunk-3LPIXG56.js} +43 -3
  159. package/dist/chunk-3LPIXG56.js.map +1 -0
  160. package/dist/chunk-3VZYDNXZ.js +10 -0
  161. package/dist/chunk-3VZYDNXZ.js.map +1 -0
  162. package/dist/{chunk-3TMODYZV.js → chunk-3XO4HR6V.js} +2 -2
  163. package/dist/chunk-46FGVWRF.js +817 -0
  164. package/dist/chunk-46FGVWRF.js.map +1 -0
  165. package/dist/chunk-4LODUXFI.js +288 -0
  166. package/dist/chunk-4LODUXFI.js.map +1 -0
  167. package/dist/{chunk-GMPEOUP2.js → chunk-4MZ7BT3R.js} +2 -2
  168. package/dist/chunk-4MZ7BT3R.js.map +1 -0
  169. package/dist/{chunk-TKZ7MEIA.js → chunk-53GVPGSM.js} +2 -2
  170. package/dist/{chunk-KP7MUZNX.js → chunk-5W2V2NVJ.js} +2 -2
  171. package/dist/chunk-5W2V2NVJ.js.map +1 -0
  172. package/dist/chunk-6DACKW3D.js +613 -0
  173. package/dist/chunk-6DACKW3D.js.map +1 -0
  174. package/dist/chunk-AQ7L2QZ5.js +1395 -0
  175. package/dist/chunk-AQ7L2QZ5.js.map +1 -0
  176. package/dist/{chunk-NZJKFF45.js → chunk-C2UZZQ76.js} +2 -2
  177. package/dist/chunk-CCKP5Z6F.js +701 -0
  178. package/dist/chunk-CCKP5Z6F.js.map +1 -0
  179. package/dist/chunk-CUKM2XUW.js +27 -0
  180. package/dist/{chunk-QCHIQWAJ.js.map → chunk-CUKM2XUW.js.map} +1 -1
  181. package/dist/{chunk-M2RGJPXX.js → chunk-DBD6Q6JH.js} +3 -3
  182. package/dist/{chunk-ZGDVUPTM.js → chunk-EB4RGQO3.js} +2 -2
  183. package/dist/{chunk-PAYXCY6A.js → chunk-G7ESIQTI.js} +12 -14
  184. package/dist/chunk-G7ESIQTI.js.map +1 -0
  185. package/dist/chunk-GPBAZQ23.js +348 -0
  186. package/dist/chunk-GPBAZQ23.js.map +1 -0
  187. package/dist/{chunk-OFADUJWJ.js → chunk-I4LCE5OY.js} +3 -5
  188. package/dist/{chunk-OFADUJWJ.js.map → chunk-I4LCE5OY.js.map} +1 -1
  189. package/dist/{chunk-DFNM3WX2.js → chunk-IMCC6TBN.js} +158 -39
  190. package/dist/chunk-IMCC6TBN.js.map +1 -0
  191. package/dist/{chunk-76WT3HOR.js → chunk-IROZNQAF.js} +22 -21
  192. package/dist/chunk-IROZNQAF.js.map +1 -0
  193. package/dist/{chunk-TAAPQVZN.js → chunk-ISKNULNH.js} +2 -2
  194. package/dist/chunk-J3CWXIPV.js +242 -0
  195. package/dist/chunk-J3CWXIPV.js.map +1 -0
  196. package/dist/{chunk-PYOE4VSI.js → chunk-JBKYRTCS.js} +224 -161
  197. package/dist/chunk-JBKYRTCS.js.map +1 -0
  198. package/dist/{chunk-66ALHVEX.js → chunk-KKIAYH4X.js} +3 -3
  199. package/dist/{chunk-3RMKLXHX.js → chunk-KLDVG3SY.js} +2 -2
  200. package/dist/{chunk-BABLDP24.js → chunk-KSZQYSEH.js} +3 -3
  201. package/dist/chunk-KSZQYSEH.js.map +1 -0
  202. package/dist/{chunk-CW6T36TN.js → chunk-M3M7JFAH.js} +4 -4
  203. package/dist/chunk-M3M7JFAH.js.map +1 -0
  204. package/dist/{chunk-THATMZXD.js → chunk-MLB253V2.js} +2 -2
  205. package/dist/{chunk-THATMZXD.js.map → chunk-MLB253V2.js.map} +1 -1
  206. package/dist/{chunk-JGIWG6SR.js → chunk-MS77U77X.js} +664 -550
  207. package/dist/chunk-MS77U77X.js.map +1 -0
  208. package/dist/chunk-MW4FA3MW.js +23 -0
  209. package/dist/chunk-MW4FA3MW.js.map +1 -0
  210. package/dist/chunk-MYKNINNN.js +228 -0
  211. package/dist/chunk-MYKNINNN.js.map +1 -0
  212. package/dist/{chunk-4CQAV7YB.js → chunk-O6TTQXTY.js} +2 -2
  213. package/dist/{chunk-NBD3KUOZ.js → chunk-OJDJ4VDQ.js} +35 -24
  214. package/dist/chunk-OJDJ4VDQ.js.map +1 -0
  215. package/dist/{chunk-NQZ2OSGR.js → chunk-PVZEMNJY.js} +9 -9
  216. package/dist/chunk-PVZEMNJY.js.map +1 -0
  217. package/dist/chunk-RN26DV2M.js +271 -0
  218. package/dist/chunk-RN26DV2M.js.map +1 -0
  219. package/dist/{chunk-JCXGZRMU.js → chunk-RQQW3IQC.js} +3 -3
  220. package/dist/chunk-RQQW3IQC.js.map +1 -0
  221. package/dist/{chunk-24VULZ7A.js → chunk-TKOGZDD6.js} +3 -3
  222. package/dist/{chunk-EGK3KN7B.js → chunk-TQYLVXGY.js} +70 -39
  223. package/dist/chunk-TQYLVXGY.js.map +1 -0
  224. package/dist/{chunk-QMM6O4CD.js → chunk-UACD2CL2.js} +15 -3
  225. package/dist/{chunk-QMM6O4CD.js.map → chunk-UACD2CL2.js.map} +1 -1
  226. package/dist/{chunk-M3WTHJHJ.js → chunk-VH575UTV.js} +30 -34
  227. package/dist/chunk-VH575UTV.js.map +1 -0
  228. package/dist/{chunk-AUIR5O6W.js → chunk-WWBMC24F.js} +9 -15
  229. package/dist/chunk-WWBMC24F.js.map +1 -0
  230. package/dist/{chunk-JWOYLO27.js → chunk-WYJUJV4L.js} +80 -7
  231. package/dist/chunk-WYJUJV4L.js.map +1 -0
  232. package/dist/{chunk-EY4NZKDR.js → chunk-XFMMPYNU.js} +2 -2
  233. package/dist/chunk-Y4VRBIS6.js +35 -0
  234. package/dist/chunk-Y4VRBIS6.js.map +1 -0
  235. package/dist/{chunk-DMBALCE2.js → chunk-ZC7MSQ5U.js} +77 -4
  236. package/dist/chunk-ZC7MSQ5U.js.map +1 -0
  237. package/dist/{chunk-OGWBVHB3.js → chunk-ZCK6SCOE.js} +67 -8
  238. package/dist/chunk-ZCK6SCOE.js.map +1 -0
  239. package/dist/{chunk-IHVBV5C2.js → chunk-ZTFTABXV.js} +2 -1
  240. package/dist/chunk-ZTFTABXV.js.map +1 -0
  241. package/dist/index.cjs +9532 -5017
  242. package/dist/index.cjs.map +1 -1
  243. package/dist/index.d.cts +163 -27
  244. package/dist/index.d.ts +163 -27
  245. package/dist/index.js +119 -56
  246. package/dist/index.js.map +1 -1
  247. package/dist/{ir-BMP7yxJJ.d.cts → ir-C-Zm_GlZ.d.cts} +1 -1
  248. package/dist/{ir-DUOz6H-5.d.ts → ir-DGyGiwVe.d.ts} +1 -1
  249. package/dist/{module-k7m3txak.d.ts → module-DqQ1U-Me.d.ts} +129 -100
  250. package/dist/{module-B8CBqIZ_.d.cts → module-doenaCsZ.d.cts} +129 -100
  251. package/package.json +12 -1
  252. package/dist/ModuleTag-C8FHY_sY.d.ts +0 -93
  253. package/dist/ModuleTag-EGbgBMpZ.d.cts +0 -93
  254. package/dist/chunk-3QMIVH35.js +0 -43
  255. package/dist/chunk-3QMIVH35.js.map +0 -1
  256. package/dist/chunk-76WT3HOR.js.map +0 -1
  257. package/dist/chunk-AUIR5O6W.js.map +0 -1
  258. package/dist/chunk-BABLDP24.js.map +0 -1
  259. package/dist/chunk-BE3HW4FY.js.map +0 -1
  260. package/dist/chunk-CW6T36TN.js.map +0 -1
  261. package/dist/chunk-DFNM3WX2.js.map +0 -1
  262. package/dist/chunk-DMBALCE2.js.map +0 -1
  263. package/dist/chunk-EGK3KN7B.js.map +0 -1
  264. package/dist/chunk-GMPEOUP2.js.map +0 -1
  265. package/dist/chunk-IHVBV5C2.js.map +0 -1
  266. package/dist/chunk-JCXGZRMU.js.map +0 -1
  267. package/dist/chunk-JGIWG6SR.js.map +0 -1
  268. package/dist/chunk-JWOYLO27.js.map +0 -1
  269. package/dist/chunk-KIXAU3GM.js +0 -137
  270. package/dist/chunk-KIXAU3GM.js.map +0 -1
  271. package/dist/chunk-KP7MUZNX.js.map +0 -1
  272. package/dist/chunk-M3WTHJHJ.js.map +0 -1
  273. package/dist/chunk-M7IYCTJV.js +0 -79
  274. package/dist/chunk-M7IYCTJV.js.map +0 -1
  275. package/dist/chunk-NBD3KUOZ.js.map +0 -1
  276. package/dist/chunk-NQZ2OSGR.js.map +0 -1
  277. package/dist/chunk-OGWBVHB3.js.map +0 -1
  278. package/dist/chunk-PAYXCY6A.js.map +0 -1
  279. package/dist/chunk-PYOE4VSI.js.map +0 -1
  280. package/dist/chunk-QCHIQWAJ.js +0 -21
  281. package/dist/chunk-VZB726PE.js +0 -93
  282. package/dist/chunk-VZB726PE.js.map +0 -1
  283. package/dist/chunk-W3TEWHLO.js +0 -568
  284. package/dist/chunk-W3TEWHLO.js.map +0 -1
  285. package/dist/chunk-ZFLHVFUC.js +0 -192
  286. package/dist/chunk-ZFLHVFUC.js.map +0 -1
  287. package/dist/chunk-ZFY7U2FR.js.map +0 -1
  288. /package/dist/{chunk-G5ZBFPNU.js.map → chunk-2A4UKO2D.js.map} +0 -0
  289. /package/dist/{chunk-ANLBCBDC.js.map → chunk-2DVLMSOE.js.map} +0 -0
  290. /package/dist/{chunk-3TMODYZV.js.map → chunk-3XO4HR6V.js.map} +0 -0
  291. /package/dist/{chunk-TKZ7MEIA.js.map → chunk-53GVPGSM.js.map} +0 -0
  292. /package/dist/{chunk-NZJKFF45.js.map → chunk-C2UZZQ76.js.map} +0 -0
  293. /package/dist/{chunk-M2RGJPXX.js.map → chunk-DBD6Q6JH.js.map} +0 -0
  294. /package/dist/{chunk-ZGDVUPTM.js.map → chunk-EB4RGQO3.js.map} +0 -0
  295. /package/dist/{chunk-TAAPQVZN.js.map → chunk-ISKNULNH.js.map} +0 -0
  296. /package/dist/{chunk-66ALHVEX.js.map → chunk-KKIAYH4X.js.map} +0 -0
  297. /package/dist/{chunk-3RMKLXHX.js.map → chunk-KLDVG3SY.js.map} +0 -0
  298. /package/dist/{chunk-4CQAV7YB.js.map → chunk-O6TTQXTY.js.map} +0 -0
  299. /package/dist/{chunk-24VULZ7A.js.map → chunk-TKOGZDD6.js.map} +0 -0
  300. /package/dist/{chunk-EY4NZKDR.js.map → chunk-XFMMPYNU.js.map} +0 -0
@@ -34,6 +34,7 @@ __export(StateTrait_exports, {
34
34
  build: () => build2,
35
35
  computed: () => computed,
36
36
  exportStaticIr: () => exportStaticIr2,
37
+ externalStore: () => externalStore,
37
38
  from: () => from,
38
39
  install: () => install2,
39
40
  link: () => link,
@@ -106,21 +107,31 @@ var uniqSortedStrings = (input) => {
106
107
  if (!v) continue;
107
108
  set.add(v);
108
109
  }
109
- return Array.from(set).sort((a, b) => a.localeCompare(b));
110
+ return Array.from(set).sort();
110
111
  };
111
112
  var isPlainRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
112
- var sanitizeJsonValue = (input, depth) => {
113
+ var sanitizeJsonValue = (input, depth, stats) => {
113
114
  if (input === null) return null;
114
115
  if (typeof input === "string") return input;
115
116
  if (typeof input === "boolean") return input;
116
117
  if (typeof input === "number") {
117
- return Number.isFinite(input) ? input : void 0;
118
+ if (!Number.isFinite(input)) {
119
+ stats.dropped += 1;
120
+ stats.nonSerializable += 1;
121
+ stats.nonFiniteNumber += 1;
122
+ return void 0;
123
+ }
124
+ return input;
125
+ }
126
+ if (depth >= 6) {
127
+ stats.dropped += 1;
128
+ stats.depthExceeded += 1;
129
+ return void 0;
118
130
  }
119
- if (depth >= 6) return void 0;
120
131
  if (Array.isArray(input)) {
121
132
  const out = [];
122
133
  for (const item of input) {
123
- const v = sanitizeJsonValue(item, depth + 1);
134
+ const v = sanitizeJsonValue(item, depth + 1, stats);
124
135
  if (v !== void 0) out.push(v);
125
136
  }
126
137
  return out;
@@ -129,18 +140,50 @@ var sanitizeJsonValue = (input, depth) => {
129
140
  const keys = Object.keys(input).sort();
130
141
  const out = {};
131
142
  for (const key of keys) {
132
- const v = sanitizeJsonValue(input[key], depth + 1);
143
+ const v = sanitizeJsonValue(input[key], depth + 1, stats);
133
144
  if (v !== void 0) out[key] = v;
134
145
  }
135
146
  return out;
136
147
  }
148
+ stats.dropped += 1;
149
+ stats.nonSerializable += 1;
137
150
  return void 0;
138
151
  };
139
- var sanitize = (input) => {
140
- if (input === null || input === void 0) return void 0;
141
- if (typeof input !== "object" || Array.isArray(input)) return void 0;
152
+ var pushSample = (target, value, limit) => {
153
+ if (target.length >= limit) return;
154
+ target.push(value);
155
+ };
156
+ var sanitizeWithReport = (input) => {
157
+ if (input === null || input === void 0) return {};
158
+ if (typeof input !== "object" || Array.isArray(input)) {
159
+ return { report: { invalidInput: true } };
160
+ }
142
161
  const record2 = input;
143
162
  const out = {};
163
+ const reportUnknownKeys = [];
164
+ let unknownKeyCount = 0;
165
+ const reportDroppedKeys = [];
166
+ let droppedTagItems = 0;
167
+ const reportIgnoredAnnotationKeys = [];
168
+ let ignoredAnnotationKeyCount = 0;
169
+ const reportDroppedAnnotationKeys = [];
170
+ let droppedAnnotationKeyCount = 0;
171
+ const stats = { dropped: 0, nonSerializable: 0, depthExceeded: 0, nonFiniteNumber: 0 };
172
+ const allowed = /* @__PURE__ */ new Set([
173
+ "label",
174
+ "description",
175
+ "group",
176
+ "docsUrl",
177
+ "cacheGroup",
178
+ "canonical",
179
+ "tags",
180
+ "annotations"
181
+ ]);
182
+ for (const key of Object.keys(record2)) {
183
+ if (allowed.has(key) || key.startsWith("x-")) continue;
184
+ unknownKeyCount += 1;
185
+ pushSample(reportUnknownKeys, key, 8);
186
+ }
144
187
  const pickString = (key) => {
145
188
  const value = record2[key];
146
189
  if (typeof value !== "string") return;
@@ -154,7 +197,9 @@ var sanitize = (input) => {
154
197
  pickString("docsUrl");
155
198
  pickString("cacheGroup");
156
199
  const canonical = record2.canonical;
157
- if (typeof canonical === "boolean") {
200
+ if (canonical !== void 0 && canonical !== null && typeof canonical !== "boolean") {
201
+ pushSample(reportDroppedKeys, "canonical", 8);
202
+ } else if (typeof canonical === "boolean") {
158
203
  out.canonical = canonical;
159
204
  }
160
205
  const tagsRaw = record2.tags;
@@ -162,26 +207,80 @@ var sanitize = (input) => {
162
207
  const tags = uniqSortedStrings([tagsRaw]);
163
208
  if (tags.length > 0) out.tags = tags;
164
209
  } else if (Array.isArray(tagsRaw)) {
165
- const tags = uniqSortedStrings(tagsRaw.filter((x) => typeof x === "string"));
210
+ const raw = tagsRaw.filter((x) => typeof x === "string");
211
+ droppedTagItems += tagsRaw.length - raw.length;
212
+ const tags = uniqSortedStrings(raw);
166
213
  if (tags.length > 0) out.tags = tags;
214
+ droppedTagItems += raw.length - tags.length;
215
+ } else if (tagsRaw !== void 0 && tagsRaw !== null) {
216
+ pushSample(reportDroppedKeys, "tags", 8);
167
217
  }
168
218
  const annotations = {};
169
- const annotationKeys = Object.keys(record2).filter((k) => k.startsWith("x-")).sort((a, b) => a.localeCompare(b));
219
+ const annotationKeys = Object.keys(record2).filter((k) => k.startsWith("x-")).sort();
170
220
  for (const key of annotationKeys) {
171
- const v = sanitizeJsonValue(record2[key], 0);
172
- if (v !== void 0) annotations[key] = v;
221
+ const v = sanitizeJsonValue(record2[key], 0, stats);
222
+ if (v !== void 0) {
223
+ annotations[key] = v;
224
+ } else {
225
+ droppedAnnotationKeyCount += 1;
226
+ pushSample(reportDroppedAnnotationKeys, key, 8);
227
+ }
173
228
  }
174
229
  const annotationsRaw = record2.annotations;
175
- if (isPlainRecord(annotationsRaw)) {
176
- const keys = Object.keys(annotationsRaw).filter((k) => k.startsWith("x-")).sort((a, b) => a.localeCompare(b));
230
+ if (annotationsRaw !== void 0 && annotationsRaw !== null && !isPlainRecord(annotationsRaw)) {
231
+ pushSample(reportDroppedKeys, "annotations", 8);
232
+ } else if (isPlainRecord(annotationsRaw)) {
233
+ const keys = Object.keys(annotationsRaw).sort();
177
234
  for (const key of keys) {
178
- const v = sanitizeJsonValue(annotationsRaw[key], 0);
179
- if (v !== void 0) annotations[key] = v;
235
+ if (!key.startsWith("x-")) {
236
+ ignoredAnnotationKeyCount += 1;
237
+ pushSample(reportIgnoredAnnotationKeys, key, 8);
238
+ continue;
239
+ }
240
+ const v = sanitizeJsonValue(annotationsRaw[key], 0, stats);
241
+ if (v !== void 0) {
242
+ annotations[key] = v;
243
+ } else {
244
+ droppedAnnotationKeyCount += 1;
245
+ pushSample(reportDroppedAnnotationKeys, key, 8);
246
+ }
180
247
  }
181
248
  }
182
249
  if (Object.keys(annotations).length > 0) out.annotations = annotations;
183
- return Object.keys(out).length > 0 ? out : void 0;
250
+ for (const key of ["label", "description", "group", "docsUrl", "cacheGroup"]) {
251
+ const value = record2[key];
252
+ if (value !== void 0 && value !== null && typeof value !== "string") {
253
+ pushSample(reportDroppedKeys, key, 8);
254
+ }
255
+ }
256
+ const meta = Object.keys(out).length > 0 ? out : void 0;
257
+ const report = (() => {
258
+ const hasUnknownKeys = unknownKeyCount > 0;
259
+ const hasDroppedKeys = reportDroppedKeys.length > 0;
260
+ const hasDroppedTagItems = droppedTagItems > 0;
261
+ const hasIgnoredAnnotationKeys = ignoredAnnotationKeyCount > 0;
262
+ const hasDroppedAnnotations = droppedAnnotationKeyCount > 0 || stats.dropped > 0;
263
+ if (!hasUnknownKeys && !hasDroppedKeys && !hasDroppedTagItems && !hasIgnoredAnnotationKeys && !hasDroppedAnnotations) {
264
+ return void 0;
265
+ }
266
+ return {
267
+ ...hasUnknownKeys ? { unknownKeys: reportUnknownKeys, unknownKeyCount } : {},
268
+ ...hasDroppedKeys ? { droppedKeys: uniqSortedStrings(reportDroppedKeys) } : {},
269
+ ...hasDroppedTagItems ? { droppedTagItems } : {},
270
+ ...hasIgnoredAnnotationKeys ? { ignoredAnnotationKeys: uniqSortedStrings(reportIgnoredAnnotationKeys), ignoredAnnotationKeyCount } : {},
271
+ ...hasDroppedAnnotations ? {
272
+ droppedAnnotationKeys: uniqSortedStrings(reportDroppedAnnotationKeys),
273
+ droppedAnnotationKeyCount,
274
+ droppedAnnotationValues: stats.dropped,
275
+ droppedAnnotationNonSerializable: stats.nonSerializable,
276
+ droppedAnnotationDepthExceeded: stats.depthExceeded,
277
+ droppedAnnotationNonFiniteNumber: stats.nonFiniteNumber
278
+ } : {}
279
+ };
280
+ })();
281
+ return report ? { meta, report } : { meta };
184
282
  };
283
+ var sanitize = (input) => sanitizeWithReport(input).meta;
185
284
  var stableStringify = (meta) => {
186
285
  const out = {};
187
286
  const keys = Object.keys(meta).sort();
@@ -271,6 +370,14 @@ var normalizeSpec = (spec) => {
271
370
  meta: { ...meta, deps, _fieldPath: fieldPath }
272
371
  };
273
372
  }
373
+ if (entry.kind === "externalStore") {
374
+ const meta = entry.meta;
375
+ return {
376
+ ...entry,
377
+ fieldPath,
378
+ meta: { ...meta, _fieldPath: fieldPath }
379
+ };
380
+ }
274
381
  if (entry.kind === "link") {
275
382
  const meta = entry.meta;
276
383
  const from2 = prefixDeps([meta.from], depPrefix)[0] ?? meta.from;
@@ -308,6 +415,7 @@ var normalizeSpec = (spec) => {
308
415
  expandMaybeRecord(node2.computed);
309
416
  expandMaybeRecord(node2.source);
310
417
  expandMaybeRecord(node2.link);
418
+ expandMaybeRecord(node2.externalStore);
311
419
  if (node2.check) {
312
420
  const rules = {};
313
421
  const checkDepsPrefix = options?.checkDepsPrefix ?? (joinPrefix.endsWith("[]") ? joinPrefix : "");
@@ -522,7 +630,7 @@ var stableStringify2 = (value) => {
522
630
  }
523
631
  if (t === "object") {
524
632
  const record2 = value;
525
- const keys = Object.keys(record2).sort((a, b) => a.localeCompare(b));
633
+ const keys = Object.keys(record2).sort();
526
634
  return `{${keys.map((k) => `${JSON.stringify(k)}:${stableStringify2(record2[k])}`).join(",")}}`;
527
635
  }
528
636
  return "null";
@@ -538,6 +646,32 @@ var fnv1a32 = (input) => {
538
646
 
539
647
  // src/internal/state-trait/build.ts
540
648
  var nowPerf = () => typeof globalThis.performance !== "undefined" && typeof globalThis.performance.now === "function" ? globalThis.performance.now() : Date.now();
649
+ var collectMultipleWritersError = (entries) => {
650
+ const kindsByFieldPath = /* @__PURE__ */ new Map();
651
+ for (const entry of entries) {
652
+ if (entry.kind !== "computed" && entry.kind !== "link" && entry.kind !== "source" && entry.kind !== "externalStore") {
653
+ continue;
654
+ }
655
+ const set = kindsByFieldPath.get(entry.fieldPath) ?? /* @__PURE__ */ new Set();
656
+ set.add(entry.kind);
657
+ kindsByFieldPath.set(entry.fieldPath, set);
658
+ }
659
+ const conflicts = [];
660
+ for (const [fieldPath, kinds] of kindsByFieldPath.entries()) {
661
+ if (kinds.size <= 1) continue;
662
+ conflicts.push({ fieldPath, kinds: Array.from(kinds).sort() });
663
+ }
664
+ if (conflicts.length === 0) return void 0;
665
+ conflicts.sort((a, b) => a.fieldPath < b.fieldPath ? -1 : a.fieldPath > b.fieldPath ? 1 : 0);
666
+ const fields = conflicts.map((c) => c.fieldPath);
667
+ const primary = conflicts[0];
668
+ const kindSummary = primary.kinds.join(" + ");
669
+ return {
670
+ code: "MULTIPLE_WRITERS",
671
+ message: `[StateTrait.build] Multiple writers for field "${primary.fieldPath}" (${kindSummary}). Only one of computed/link/source/externalStore can write a fieldPath.`,
672
+ fields
673
+ };
674
+ };
541
675
  var getConvergeWriterDeps = (entry) => {
542
676
  if (entry.kind === "computed") {
543
677
  return entry.meta?.deps ?? [];
@@ -666,6 +800,7 @@ var collectSchemaFieldPaths = (schema) => {
666
800
  var buildConvergeIr = (stateSchema, entries) => {
667
801
  const startedAt = nowPerf();
668
802
  const generation = 0;
803
+ const multipleWritersError = collectMultipleWritersError(entries);
669
804
  const writers = entries.filter((e) => e.kind === "computed" || e.kind === "link");
670
805
  const writersKey = writers.map((entry) => `${entry.kind}:${entry.fieldPath}`).sort().join("|");
671
806
  const depsKey = writers.map((entry) => {
@@ -677,7 +812,7 @@ var buildConvergeIr = (stateSchema, entries) => {
677
812
  for (const entry of writers) {
678
813
  writerByPath.set(entry.fieldPath, entry);
679
814
  }
680
- const topo = writers.length > 0 ? computeConvergeTopoOrder(writers) : { order: [] };
815
+ const topo = multipleWritersError ? { order: [] } : writers.length > 0 ? computeConvergeTopoOrder(writers) : { order: [] };
681
816
  const stepsById = topo.configError ? [] : topo.order.map((path) => writerByPath.get(path));
682
817
  const fieldPathTable = /* @__PURE__ */ new Map();
683
818
  const addPath = (path) => {
@@ -730,7 +865,7 @@ var buildConvergeIr = (stateSchema, entries) => {
730
865
  fieldPathsKey,
731
866
  fieldPaths,
732
867
  fieldPathIdRegistry,
733
- ...topo.configError ? { configError: topo.configError } : null,
868
+ ...multipleWritersError ? { configError: multipleWritersError } : topo.configError ? { configError: topo.configError } : null,
734
869
  stepsById,
735
870
  stepOutFieldPathIdByStepId,
736
871
  stepDepsFieldPathIdsByStepId,
@@ -886,6 +1021,12 @@ var buildGraph = (entries, nodeMetaByFieldPath) => {
886
1021
  });
887
1022
  }
888
1023
  }
1024
+ } else if (entry.kind === "externalStore") {
1025
+ planSteps.push({
1026
+ id: `external-store:${fieldPath}`,
1027
+ kind: "external-store-sync",
1028
+ targetFieldPath: fieldPath
1029
+ });
889
1030
  } else if (entry.kind === "check") {
890
1031
  planSteps.push({
891
1032
  id: `check:${fieldPath}`,
@@ -1026,7 +1167,7 @@ var collectSchemaPaths = (entries) => {
1026
1167
  }
1027
1168
  }
1028
1169
  }
1029
- return Array.from(byKey.entries()).sort((a, b) => a[0].localeCompare(b[0])).map(([, v]) => v);
1170
+ return Array.from(byKey.entries()).sort((a, b) => a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0).map(([, v]) => v);
1030
1171
  };
1031
1172
  var build = (stateSchema, spec) => {
1032
1173
  const entries = normalizeSpec(spec);
@@ -1079,55 +1220,290 @@ var build = (stateSchema, spec) => {
1079
1220
  };
1080
1221
 
1081
1222
  // src/internal/state-trait/install.ts
1082
- var import_effect11 = require("effect");
1223
+ var import_effect17 = require("effect");
1083
1224
 
1084
1225
  // src/internal/runtime/core/env.ts
1085
- var import_effect = require("effect");
1086
- var getNodeEnv = () => {
1226
+ var import_effect8 = require("effect");
1227
+
1228
+ // src/internal/runtime/core/HostScheduler.ts
1229
+ var noopCancel = () => {
1230
+ };
1231
+ var safeNowMs = () => {
1232
+ const perf = globalThis.performance;
1233
+ if (perf && typeof perf.now === "function") {
1234
+ try {
1235
+ const v = perf.now();
1236
+ if (typeof v === "number" && Number.isFinite(v)) return v;
1237
+ } catch {
1238
+ }
1239
+ }
1240
+ return Date.now();
1241
+ };
1242
+ var safeQueueMicrotask = (cb) => {
1243
+ const qm = globalThis.queueMicrotask;
1244
+ if (typeof qm === "function") {
1245
+ try {
1246
+ qm(cb);
1247
+ return;
1248
+ } catch {
1249
+ }
1250
+ }
1087
1251
  try {
1088
- const env = globalThis?.process?.env;
1089
- return typeof env?.NODE_ENV === "string" ? env.NODE_ENV : void 0;
1252
+ Promise.resolve().then(cb);
1090
1253
  } catch {
1091
- return void 0;
1254
+ setTimeout(cb, 0);
1092
1255
  }
1093
1256
  };
1094
- var isDevEnv = () => getNodeEnv() !== "production";
1095
- var StateTransactionConfigTagImpl = class extends import_effect.Context.Tag("@logixjs/core/StateTransactionRuntimeConfig")() {
1096
- };
1097
- var ReadQueryStrictGateConfigTagImpl = class extends import_effect.Context.Tag("@logixjs/core/ReadQueryStrictGateRuntimeConfig")() {
1257
+ var safeSetTimeout = (ms, cb) => {
1258
+ const id = setTimeout(cb, ms);
1259
+ return () => {
1260
+ try {
1261
+ clearTimeout(id);
1262
+ } catch {
1263
+ }
1264
+ };
1098
1265
  };
1099
- var ReplayModeConfigTagImpl = class extends import_effect.Context.Tag("@logixjs/core/ReplayModeConfig")() {
1266
+ var makeMessageChannelMacrotask = () => {
1267
+ const MC = globalThis.MessageChannel;
1268
+ if (typeof MC !== "function") return void 0;
1269
+ let channel;
1270
+ try {
1271
+ channel = new MC();
1272
+ } catch {
1273
+ return void 0;
1274
+ }
1275
+ const queue = [];
1276
+ let scheduled = false;
1277
+ const flush = () => {
1278
+ scheduled = false;
1279
+ const tasks = queue.splice(0, queue.length);
1280
+ for (const t of tasks) {
1281
+ if (t.canceled) continue;
1282
+ try {
1283
+ t.cb();
1284
+ } catch {
1285
+ }
1286
+ }
1287
+ };
1288
+ try {
1289
+ channel.port1.onmessage = flush;
1290
+ } catch {
1291
+ return void 0;
1292
+ }
1293
+ const schedule = (cb) => {
1294
+ const task = { canceled: false, cb };
1295
+ queue.push(task);
1296
+ if (!scheduled) {
1297
+ scheduled = true;
1298
+ try {
1299
+ channel.port2.postMessage(void 0);
1300
+ } catch {
1301
+ scheduled = false;
1302
+ return safeSetTimeout(0, cb);
1303
+ }
1304
+ }
1305
+ return () => {
1306
+ task.canceled = true;
1307
+ };
1308
+ };
1309
+ return schedule;
1310
+ };
1311
+ var makeSetImmediateMacrotask = () => {
1312
+ const si = globalThis.setImmediate;
1313
+ const ci = globalThis.clearImmediate;
1314
+ if (typeof si !== "function") return void 0;
1315
+ return (cb) => {
1316
+ let id;
1317
+ try {
1318
+ id = si(cb);
1319
+ } catch {
1320
+ return safeSetTimeout(0, cb);
1321
+ }
1322
+ return () => {
1323
+ if (typeof ci !== "function") return;
1324
+ try {
1325
+ ci(id);
1326
+ } catch {
1327
+ }
1328
+ };
1329
+ };
1100
1330
  };
1101
- var ReplayModeConfigTag = ReplayModeConfigTagImpl;
1102
- var StateTransactionOverridesTagImpl = class extends import_effect.Context.Tag("@logixjs/core/StateTransactionOverrides")() {
1331
+ var makeRaf = () => {
1332
+ const raf = globalThis.requestAnimationFrame;
1333
+ const cancel = globalThis.cancelAnimationFrame;
1334
+ if (typeof raf !== "function") return void 0;
1335
+ return (cb) => {
1336
+ let id;
1337
+ try {
1338
+ id = raf(cb);
1339
+ } catch {
1340
+ return noopCancel;
1341
+ }
1342
+ return () => {
1343
+ if (typeof cancel !== "function") return;
1344
+ try {
1345
+ cancel(id);
1346
+ } catch {
1347
+ }
1348
+ };
1349
+ };
1103
1350
  };
1104
- var ConcurrencyPolicyTagImpl = class extends import_effect.Context.Tag("@logixjs/core/ConcurrencyPolicy")() {
1351
+ var makeDefaultHostScheduler = () => {
1352
+ const macrotask = makeSetImmediateMacrotask() ?? makeMessageChannelMacrotask() ?? ((cb) => safeSetTimeout(0, cb));
1353
+ const raf = makeRaf();
1354
+ return {
1355
+ nowMs: safeNowMs,
1356
+ scheduleMicrotask: safeQueueMicrotask,
1357
+ scheduleMacrotask: macrotask,
1358
+ scheduleAnimationFrame: (cb) => raf?.(cb) ?? macrotask(cb),
1359
+ scheduleTimeout: safeSetTimeout
1360
+ };
1105
1361
  };
1106
- var ConcurrencyPolicyOverridesTagImpl = class extends import_effect.Context.Tag("@logixjs/core/ConcurrencyPolicyOverrides")() {
1362
+ var globalHostScheduler;
1363
+ var getGlobalHostScheduler = () => {
1364
+ globalHostScheduler ?? (globalHostScheduler = makeDefaultHostScheduler());
1365
+ return globalHostScheduler;
1107
1366
  };
1108
1367
 
1109
- // src/internal/runtime/core/runtimeInternalsAccessor.ts
1110
- var BOUND_INTERNALS = /* @__PURE__ */ Symbol.for("@logixjs/core/boundInternals");
1111
- var getBoundInternals = (bound) => {
1112
- const internals = bound[BOUND_INTERNALS];
1113
- if (!internals) {
1114
- const msg = isDevEnv() ? [
1115
- "[MissingBoundInternals] Bound internals not installed on Bound API instance.",
1116
- "fix:",
1117
- "- Ensure BoundApiRuntime attaches internals (020 foundation).",
1118
- "- If you created a mock bound for tests, attach internals or avoid calling internal-only APIs."
1119
- ].join("\n") : "Bound internals not installed";
1120
- throw new Error(msg);
1368
+ // src/internal/runtime/core/RuntimeStore.ts
1369
+ var parseTopicKey = (topicKey) => {
1370
+ const idx = topicKey.indexOf("::");
1371
+ if (idx <= 0) return void 0;
1372
+ const moduleId = topicKey.slice(0, idx);
1373
+ const rest = topicKey.slice(idx + 2);
1374
+ if (rest.length === 0) return void 0;
1375
+ const idx2 = rest.indexOf("::");
1376
+ if (idx2 < 0) {
1377
+ return { kind: "module", moduleInstanceKey: `${moduleId}::${rest}` };
1378
+ }
1379
+ const instanceId = rest.slice(0, idx2);
1380
+ const suffix = rest.slice(idx2 + 2);
1381
+ if (suffix.startsWith("rq:")) {
1382
+ const selectorId = suffix.slice("rq:".length);
1383
+ if (selectorId.length === 0) return void 0;
1384
+ return {
1385
+ kind: "readQuery",
1386
+ moduleInstanceKey: `${moduleId}::${instanceId}`,
1387
+ selectorId
1388
+ };
1121
1389
  }
1122
- return internals;
1390
+ return { kind: "module", moduleInstanceKey: `${moduleId}::${instanceId}` };
1391
+ };
1392
+ var makeRuntimeStore = () => {
1393
+ let tickSeq = 0;
1394
+ const moduleStates = /* @__PURE__ */ new Map();
1395
+ const topicVersions = /* @__PURE__ */ new Map();
1396
+ const topicPriorities = /* @__PURE__ */ new Map();
1397
+ const listenersByTopic = /* @__PURE__ */ new Map();
1398
+ const subscriberCountByModule = /* @__PURE__ */ new Map();
1399
+ const getTopicVersion = (topicKey) => topicVersions.get(topicKey) ?? 0;
1400
+ const getTopicPriority = (topicKey) => topicPriorities.get(topicKey) ?? "normal";
1401
+ const commitTopicBump = (topicKey, priority) => {
1402
+ const prev = topicVersions.get(topicKey) ?? 0;
1403
+ topicVersions.set(topicKey, prev + 1);
1404
+ topicPriorities.set(topicKey, priority);
1405
+ };
1406
+ const subscribeTopic = (topicKey, listener) => {
1407
+ const info = parseTopicKey(topicKey);
1408
+ const existing = listenersByTopic.get(topicKey);
1409
+ const set = existing ?? /* @__PURE__ */ new Set();
1410
+ const alreadyHas = set.has(listener);
1411
+ if (!alreadyHas) {
1412
+ set.add(listener);
1413
+ }
1414
+ if (!existing) {
1415
+ listenersByTopic.set(topicKey, set);
1416
+ }
1417
+ if (!alreadyHas && info) {
1418
+ const prev = subscriberCountByModule.get(info.moduleInstanceKey) ?? 0;
1419
+ subscriberCountByModule.set(info.moduleInstanceKey, prev + 1);
1420
+ }
1421
+ return () => {
1422
+ const current = listenersByTopic.get(topicKey);
1423
+ if (!current) return;
1424
+ const deleted = current.delete(listener);
1425
+ if (deleted && info) {
1426
+ const prev = subscriberCountByModule.get(info.moduleInstanceKey) ?? 0;
1427
+ const next = prev - 1;
1428
+ if (next <= 0) {
1429
+ subscriberCountByModule.delete(info.moduleInstanceKey);
1430
+ } else {
1431
+ subscriberCountByModule.set(info.moduleInstanceKey, next);
1432
+ }
1433
+ }
1434
+ if (current.size === 0) {
1435
+ listenersByTopic.delete(topicKey);
1436
+ }
1437
+ };
1438
+ };
1439
+ const getTopicSubscriberCount = (topicKey) => listenersByTopic.get(topicKey)?.size ?? 0;
1440
+ const getModuleSubscriberCount = (moduleInstanceKey) => subscriberCountByModule.get(moduleInstanceKey) ?? 0;
1441
+ const registerModuleInstance = (args) => {
1442
+ moduleStates.set(args.moduleInstanceKey, args.initialState);
1443
+ if (!topicVersions.has(args.moduleInstanceKey)) {
1444
+ topicVersions.set(args.moduleInstanceKey, 0);
1445
+ topicPriorities.set(args.moduleInstanceKey, "normal");
1446
+ }
1447
+ };
1448
+ const unregisterModuleInstance = (moduleInstanceKey) => {
1449
+ moduleStates.delete(moduleInstanceKey);
1450
+ };
1451
+ const commitTick = (args) => {
1452
+ tickSeq = args.tickSeq;
1453
+ for (const [key, commit] of args.accepted.modules) {
1454
+ moduleStates.set(key, commit.state);
1455
+ }
1456
+ const changedTopics = /* @__PURE__ */ new Map();
1457
+ for (const [topicKey, priority] of args.accepted.dirtyTopics) {
1458
+ commitTopicBump(topicKey, priority);
1459
+ const listeners = Array.from(listenersByTopic.get(topicKey) ?? []);
1460
+ if (listeners.length > 0) {
1461
+ changedTopics.set(topicKey, { priority, listeners });
1462
+ }
1463
+ }
1464
+ return { changedTopics };
1465
+ };
1466
+ const getModuleState = (moduleInstanceKey) => moduleStates.get(moduleInstanceKey);
1467
+ const dispose = () => {
1468
+ moduleStates.clear();
1469
+ topicVersions.clear();
1470
+ topicPriorities.clear();
1471
+ listenersByTopic.clear();
1472
+ subscriberCountByModule.clear();
1473
+ };
1474
+ return {
1475
+ getTickSeq: () => tickSeq,
1476
+ getModuleState,
1477
+ getTopicVersion,
1478
+ getTopicPriority,
1479
+ subscribeTopic,
1480
+ getTopicSubscriberCount,
1481
+ getModuleSubscriberCount,
1482
+ registerModuleInstance,
1483
+ unregisterModuleInstance,
1484
+ commitTick,
1485
+ dispose
1486
+ };
1123
1487
  };
1124
1488
 
1125
- // src/internal/state-trait/source.ts
1126
- var import_effect10 = require("effect");
1127
- var import_mutative = require("mutative");
1489
+ // src/internal/runtime/core/TickScheduler.ts
1490
+ var import_effect6 = require("effect");
1128
1491
 
1129
- // src/internal/effect-op.ts
1130
- var import_effect4 = require("effect");
1492
+ // src/internal/runtime/core/DebugSink.record.ts
1493
+ var import_effect3 = require("effect");
1494
+
1495
+ // src/internal/observability/jsonValue.ts
1496
+ var defaultOptions = {
1497
+ maxDepth: 6,
1498
+ maxObjectKeys: 32,
1499
+ maxArrayLength: 32,
1500
+ maxStringLength: 256,
1501
+ maxJsonBytes: 4 * 1024,
1502
+ oversizedPreviewBytes: 256
1503
+ };
1504
+
1505
+ // src/internal/runtime/core/errorSummary.ts
1506
+ var import_effect = require("effect");
1131
1507
 
1132
1508
  // src/internal/runtime/core/EffectOpCore.ts
1133
1509
  var import_effect2 = require("effect");
@@ -1157,140 +1533,13 @@ var runWithMiddleware = (op, stack) => {
1157
1533
  });
1158
1534
  };
1159
1535
 
1160
- // src/internal/observability/runSession.ts
1161
- var import_effect3 = require("effect");
1162
-
1163
- // src/internal/observability/jsonValue.ts
1164
- var defaultOptions = {
1165
- maxDepth: 6,
1166
- maxObjectKeys: 32,
1167
- maxArrayLength: 32,
1168
- maxStringLength: 256,
1169
- maxJsonBytes: 4 * 1024,
1170
- oversizedPreviewBytes: 256
1171
- };
1172
-
1173
- // src/internal/observability/runSession.ts
1174
- var RunSessionTagImpl = class extends import_effect3.Context.Tag("@logixjs/core/RunSession")() {
1175
- };
1176
- var RunSessionTag = RunSessionTagImpl;
1177
-
1178
- // src/internal/effect-op.ts
1179
- var nextGlobalOpSeq = 0;
1180
- var nextOpSeq = () => {
1181
- nextGlobalOpSeq += 1;
1182
- return nextGlobalOpSeq;
1183
- };
1184
- var makeId = (instanceId, opSeq) => instanceId ? `${instanceId}::o${opSeq}` : `o${opSeq}`;
1185
- var make = (params) => ({
1186
- ...params.id ? { id: params.id, meta: params.meta } : (() => {
1187
- const meta = params.meta ?? {};
1188
- const instanceId = meta.instanceId;
1189
- const opSeq = typeof meta.opSeq === "number" && Number.isFinite(meta.opSeq) ? Math.floor(meta.opSeq) : nextOpSeq();
1190
- return {
1191
- id: makeId(instanceId, opSeq),
1192
- meta: meta.opSeq === opSeq ? meta : { ...meta, opSeq }
1193
- };
1194
- })(),
1195
- kind: params.kind,
1196
- name: params.name,
1197
- payload: params.payload,
1198
- effect: params.effect
1199
- });
1200
- var run = (op, stack) => runWithMiddleware(op, stack);
1201
-
1202
- // src/internal/resource.ts
1203
- var import_effect5 = require("effect");
1204
- var stableStringify3 = (value) => {
1205
- const seen = /* @__PURE__ */ new WeakSet();
1206
- const encode = (input) => {
1207
- if (input === null) return null;
1208
- if (typeof input === "string" || typeof input === "number" || typeof input === "boolean") {
1209
- return input;
1210
- }
1211
- if (typeof input === "bigint") return input.toString();
1212
- if (typeof input === "undefined") return "__undefined__";
1213
- if (typeof input === "symbol") return `__symbol__:${String(input)}`;
1214
- if (typeof input === "function") return "__function__";
1215
- if (Array.isArray(input)) {
1216
- return input.map((v) => encode(v));
1217
- }
1218
- if (input instanceof Date) {
1219
- return `__date__:${input.toISOString()}`;
1220
- }
1221
- if (input instanceof Error) {
1222
- return {
1223
- _tag: "Error",
1224
- name: input.name,
1225
- message: input.message
1226
- };
1227
- }
1228
- if (input && typeof input === "object") {
1229
- const obj = input;
1230
- if (seen.has(obj)) return "__cycle__";
1231
- seen.add(obj);
1232
- const record2 = input;
1233
- const keys = Object.keys(record2).sort();
1234
- const out = {};
1235
- for (const k of keys) {
1236
- out[k] = encode(record2[k]);
1237
- }
1238
- return out;
1239
- }
1240
- return String(input);
1241
- };
1242
- try {
1243
- return JSON.stringify(encode(value));
1244
- } catch {
1245
- return String(value);
1246
- }
1247
- };
1248
- var keyHash = (key) => stableStringify3(key);
1249
- var Snapshot = {
1250
- idle: () => ({
1251
- status: "idle",
1252
- keyHash: void 0,
1253
- data: void 0,
1254
- error: void 0
1255
- }),
1256
- loading: (params) => ({
1257
- status: "loading",
1258
- keyHash: params.keyHash,
1259
- data: void 0,
1260
- error: void 0
1261
- }),
1262
- success: (params) => ({
1263
- status: "success",
1264
- keyHash: params.keyHash,
1265
- data: params.data,
1266
- error: void 0
1267
- }),
1268
- error: (params) => ({
1269
- status: "error",
1270
- keyHash: params.keyHash,
1271
- data: void 0,
1272
- error: params.error
1273
- })
1274
- };
1275
- var ResourceRegistryTag = class extends import_effect5.Context.Tag("@logixjs/core/ResourceRegistry")() {
1276
- };
1277
- var internal = {
1278
- ResourceRegistryTag
1279
- };
1280
-
1281
- // src/internal/runtime/core/DebugSink.ts
1282
- var import_effect7 = require("effect");
1283
-
1284
- // src/internal/runtime/core/errorSummary.ts
1285
- var import_effect6 = require("effect");
1286
-
1287
- // src/internal/runtime/core/DebugSink.ts
1288
- var currentDebugSinks = import_effect7.FiberRef.unsafeMake([]);
1289
- var currentRuntimeLabel = import_effect7.FiberRef.unsafeMake(void 0);
1290
- var currentTxnId = import_effect7.FiberRef.unsafeMake(void 0);
1291
- var currentOpSeq = import_effect7.FiberRef.unsafeMake(void 0);
1292
- var currentDiagnosticsLevel = import_effect7.FiberRef.unsafeMake("off");
1293
- var currentTraitConvergeDiagnosticsSampling = import_effect7.FiberRef.unsafeMake({
1536
+ // src/internal/runtime/core/DebugSink.record.ts
1537
+ var currentDebugSinks = import_effect3.FiberRef.unsafeMake([]);
1538
+ var currentRuntimeLabel = import_effect3.FiberRef.unsafeMake(void 0);
1539
+ var currentTxnId = import_effect3.FiberRef.unsafeMake(void 0);
1540
+ var currentOpSeq = import_effect3.FiberRef.unsafeMake(void 0);
1541
+ var currentDiagnosticsLevel = import_effect3.FiberRef.unsafeMake("off");
1542
+ var currentTraitConvergeDiagnosticsSampling = import_effect3.FiberRef.unsafeMake({
1294
1543
  sampleEveryN: 32,
1295
1544
  topK: 3
1296
1545
  });
@@ -1300,7 +1549,7 @@ var lifecycleErrorLog = (event) => {
1300
1549
  const moduleId = event.moduleId ?? "unknown";
1301
1550
  const causePretty = (() => {
1302
1551
  try {
1303
- return import_effect7.Cause.pretty(event.cause, {
1552
+ return import_effect3.Cause.pretty(event.cause, {
1304
1553
  renderErrorCause: true
1305
1554
  });
1306
1555
  } catch {
@@ -1313,8 +1562,8 @@ var lifecycleErrorLog = (event) => {
1313
1562
  })();
1314
1563
  const message = `[Logix][module=${moduleId}] lifecycle:error
1315
1564
  ${causePretty}`;
1316
- return import_effect7.Effect.logError(message).pipe(
1317
- import_effect7.Effect.annotateLogs({
1565
+ return import_effect3.Effect.logError(message).pipe(
1566
+ import_effect3.Effect.annotateLogs({
1318
1567
  "logix.moduleId": moduleId,
1319
1568
  "logix.event": "lifecycle:error",
1320
1569
  "logix.cause": causePretty
@@ -1328,7 +1577,7 @@ var diagnosticLog = (event) => {
1328
1577
  hint: ${event.hint}` : ""}`;
1329
1578
  const msg = `${header}
1330
1579
  ${detail}`;
1331
- const base = event.severity === "warning" ? import_effect7.Effect.logWarning(msg) : event.severity === "info" ? import_effect7.Effect.logInfo(msg) : import_effect7.Effect.logError(msg);
1580
+ const base = event.severity === "warning" ? import_effect3.Effect.logWarning(msg) : event.severity === "info" ? import_effect3.Effect.logInfo(msg) : import_effect3.Effect.logError(msg);
1332
1581
  const annotations = {
1333
1582
  "logix.moduleId": moduleId,
1334
1583
  "logix.event": `diagnostic(${event.severity})`,
@@ -1341,24 +1590,24 @@ ${detail}`;
1341
1590
  if (event.actionTag) {
1342
1591
  annotations["logix.diagnostic.actionTag"] = event.actionTag;
1343
1592
  }
1344
- return base.pipe(import_effect7.Effect.annotateLogs(annotations));
1593
+ return base.pipe(import_effect3.Effect.annotateLogs(annotations));
1345
1594
  };
1346
- var noopLayer = import_effect7.Layer.locallyScoped(currentDebugSinks, []);
1595
+ var noopLayer = import_effect3.Layer.locallyScoped(currentDebugSinks, []);
1347
1596
  var errorOnlySink = {
1348
- record: (event) => event.type === "lifecycle:error" ? lifecycleErrorLog(event) : event.type === "diagnostic" && event.severity !== "info" ? diagnosticLog(event) : import_effect7.Effect.void
1597
+ record: (event) => event.type === "lifecycle:error" ? lifecycleErrorLog(event) : event.type === "diagnostic" && event.severity !== "info" ? diagnosticLog(event) : import_effect3.Effect.void
1349
1598
  };
1350
- var errorOnlyLayer = import_effect7.Layer.locallyScoped(currentDebugSinks, [errorOnlySink]);
1599
+ var errorOnlyLayer = import_effect3.Layer.locallyScoped(currentDebugSinks, [errorOnlySink]);
1351
1600
  var isErrorOnlyOnlySinks = (sinks) => sinks.length === 1 && sinks[0] === errorOnlySink;
1352
1601
  var consoleSink = {
1353
- record: (event) => event.type === "lifecycle:error" ? lifecycleErrorLog(event) : event.type === "diagnostic" ? diagnosticLog(event) : import_effect7.Effect.logDebug({ debugEvent: event })
1602
+ record: (event) => event.type === "lifecycle:error" ? lifecycleErrorLog(event) : event.type === "diagnostic" ? diagnosticLog(event) : import_effect3.Effect.logDebug({ debugEvent: event })
1354
1603
  };
1355
- var consoleLayer = import_effect7.Layer.locallyScoped(currentDebugSinks, [consoleSink]);
1604
+ var consoleLayer = import_effect3.Layer.locallyScoped(currentDebugSinks, [consoleSink]);
1356
1605
  var isBrowser = typeof window !== "undefined" && typeof document !== "undefined";
1357
1606
  var renderBrowserConsoleEvent = (event) => {
1358
1607
  if (typeof event.type === "string" && event.type.startsWith("trace:")) {
1359
1608
  const moduleId = event.moduleId ?? "unknown";
1360
1609
  const type = event.type;
1361
- return import_effect7.Effect.sync(() => {
1610
+ return import_effect3.Effect.sync(() => {
1362
1611
  console.groupCollapsed(
1363
1612
  "%c[Logix]%c trace %c" + moduleId + "%c " + String(type),
1364
1613
  "color:#6b7280;font-weight:bold",
@@ -1378,7 +1627,7 @@ var renderBrowserConsoleEvent = (event) => {
1378
1627
  const moduleId = event.moduleId ?? "unknown";
1379
1628
  const causePretty = (() => {
1380
1629
  try {
1381
- return import_effect7.Cause.pretty(event.cause, { renderErrorCause: true });
1630
+ return import_effect3.Cause.pretty(event.cause, { renderErrorCause: true });
1382
1631
  } catch {
1383
1632
  try {
1384
1633
  return JSON.stringify(event.cause, null, 2);
@@ -1389,10 +1638,10 @@ var renderBrowserConsoleEvent = (event) => {
1389
1638
  })();
1390
1639
  const key = `${moduleId}|${causePretty}`;
1391
1640
  if (browserLifecycleSeen.has(key)) {
1392
- return import_effect7.Effect.void;
1641
+ return import_effect3.Effect.void;
1393
1642
  }
1394
1643
  browserLifecycleSeen.add(key);
1395
- return import_effect7.Effect.sync(() => {
1644
+ return import_effect3.Effect.sync(() => {
1396
1645
  console.groupCollapsed(
1397
1646
  "%c[Logix]%c lifecycle:error %c" + moduleId,
1398
1647
  "color:#ef4444;font-weight:bold",
@@ -1414,10 +1663,10 @@ hint: ${event.hint}` : ""}`;
1414
1663
  const label = event.severity === "warning" ? "diagnostic(warning)" : event.severity === "info" ? "diagnostic(info)" : "diagnostic(error)";
1415
1664
  const key = `${moduleId}|${event.code}|${event.message}`;
1416
1665
  if (browserDiagnosticSeen.has(key)) {
1417
- return import_effect7.Effect.void;
1666
+ return import_effect3.Effect.void;
1418
1667
  }
1419
1668
  browserDiagnosticSeen.add(key);
1420
- return import_effect7.Effect.sync(() => {
1669
+ return import_effect3.Effect.sync(() => {
1421
1670
  console.groupCollapsed(
1422
1671
  "%c[Logix]%c " + label + "%c module=" + moduleId,
1423
1672
  "color:#6b7280;font-weight:bold",
@@ -1434,32 +1683,32 @@ hint: ${event.hint}` : ""}`;
1434
1683
  console.groupEnd();
1435
1684
  });
1436
1685
  }
1437
- return import_effect7.Effect.void;
1686
+ return import_effect3.Effect.void;
1438
1687
  };
1439
1688
  var browserConsoleSink = {
1440
1689
  record: (event) => {
1441
1690
  if (!isBrowser) {
1442
- return event.type === "lifecycle:error" ? lifecycleErrorLog(event) : event.type === "diagnostic" ? diagnosticLog(event) : import_effect7.Effect.logDebug({ debugEvent: event });
1691
+ return event.type === "lifecycle:error" ? lifecycleErrorLog(event) : event.type === "diagnostic" ? diagnosticLog(event) : import_effect3.Effect.logDebug({ debugEvent: event });
1443
1692
  }
1444
1693
  return renderBrowserConsoleEvent(event);
1445
1694
  }
1446
1695
  };
1447
- var browserConsoleLayer = import_effect7.Layer.locallyScoped(currentDebugSinks, [browserConsoleSink]);
1696
+ var browserConsoleLayer = import_effect3.Layer.locallyScoped(currentDebugSinks, [browserConsoleSink]);
1448
1697
  var browserDiagnosticConsoleSink = {
1449
1698
  record: (event) => {
1450
1699
  if (!isBrowser) {
1451
- return event.type === "lifecycle:error" ? lifecycleErrorLog(event) : event.type === "diagnostic" && event.severity !== "info" ? diagnosticLog(event) : import_effect7.Effect.void;
1700
+ return event.type === "lifecycle:error" ? lifecycleErrorLog(event) : event.type === "diagnostic" && event.severity !== "info" ? diagnosticLog(event) : import_effect3.Effect.void;
1452
1701
  }
1453
- return event.type === "lifecycle:error" || event.type === "diagnostic" && event.severity !== "info" ? renderBrowserConsoleEvent(event) : import_effect7.Effect.void;
1702
+ return event.type === "lifecycle:error" || event.type === "diagnostic" && event.severity !== "info" ? renderBrowserConsoleEvent(event) : import_effect3.Effect.void;
1454
1703
  }
1455
1704
  };
1456
- var browserDiagnosticConsoleLayer = import_effect7.Layer.locallyScoped(currentDebugSinks, [browserDiagnosticConsoleSink]);
1457
- var browserPrettyLoggerLayer = import_effect7.Logger.replace(
1458
- import_effect7.Logger.defaultLogger,
1459
- import_effect7.Logger.prettyLogger({ mode: "browser", colors: true })
1705
+ var browserDiagnosticConsoleLayer = import_effect3.Layer.locallyScoped(currentDebugSinks, [browserDiagnosticConsoleSink]);
1706
+ var browserPrettyLoggerLayer = import_effect3.Logger.replace(
1707
+ import_effect3.Logger.defaultLogger,
1708
+ import_effect3.Logger.prettyLogger({ mode: "browser", colors: true })
1460
1709
  );
1461
- var record = (event) => import_effect7.Effect.gen(function* () {
1462
- const sinks = yield* import_effect7.FiberRef.get(currentDebugSinks);
1710
+ var record = (event) => import_effect3.Effect.gen(function* () {
1711
+ const sinks = yield* import_effect3.FiberRef.get(currentDebugSinks);
1463
1712
  if (isErrorOnlyOnlySinks(sinks)) {
1464
1713
  if (event.type === "lifecycle:error") {
1465
1714
  yield* lifecycleErrorLog(event);
@@ -1469,11 +1718,11 @@ var record = (event) => import_effect7.Effect.gen(function* () {
1469
1718
  if (event.severity !== "info") {
1470
1719
  yield* diagnosticLog(event);
1471
1720
  } else {
1472
- yield* import_effect7.Effect.void;
1721
+ yield* import_effect3.Effect.void;
1473
1722
  }
1474
1723
  return;
1475
1724
  }
1476
- yield* import_effect7.Effect.void;
1725
+ yield* import_effect3.Effect.void;
1477
1726
  return;
1478
1727
  }
1479
1728
  if (sinks.length === 0) {
@@ -1482,73 +1731,420 @@ var record = (event) => import_effect7.Effect.gen(function* () {
1482
1731
  yield* renderBrowserConsoleEvent(event);
1483
1732
  return;
1484
1733
  }
1485
- yield* import_effect7.Effect.void;
1734
+ yield* import_effect3.Effect.void;
1486
1735
  return;
1487
1736
  }
1488
1737
  if (event.type === "lifecycle:error") {
1489
1738
  yield* lifecycleErrorLog(event);
1490
1739
  return;
1491
1740
  }
1492
- if (event.type === "diagnostic") {
1493
- yield* diagnosticLog(event);
1494
- return;
1741
+ if (event.type === "diagnostic") {
1742
+ yield* diagnosticLog(event);
1743
+ return;
1744
+ }
1745
+ yield* import_effect3.Effect.void;
1746
+ return;
1747
+ }
1748
+ const enriched = event;
1749
+ const diagnosticsLevel = yield* import_effect3.FiberRef.get(currentDiagnosticsLevel);
1750
+ let now;
1751
+ const getNow = () => {
1752
+ if (now === void 0) now = Date.now();
1753
+ return now;
1754
+ };
1755
+ if (enriched.timestamp === void 0 && (diagnosticsLevel !== "off" || enriched.type === "lifecycle:error" || enriched.type === "diagnostic")) {
1756
+ ;
1757
+ enriched.timestamp = getNow();
1758
+ }
1759
+ if (diagnosticsLevel !== "off" && enriched.runtimeLabel === void 0) {
1760
+ const runtimeLabel = yield* import_effect3.FiberRef.get(currentRuntimeLabel);
1761
+ if (runtimeLabel) {
1762
+ ;
1763
+ enriched.runtimeLabel = runtimeLabel;
1764
+ }
1765
+ }
1766
+ if (enriched.type === "diagnostic" && enriched.txnId === void 0) {
1767
+ const txnId = yield* import_effect3.FiberRef.get(currentTxnId);
1768
+ if (txnId) {
1769
+ ;
1770
+ enriched.txnId = txnId;
1771
+ }
1772
+ }
1773
+ if (diagnosticsLevel !== "off" && enriched.type === "trace:effectop" && enriched.linkId === void 0) {
1774
+ const linkId = yield* import_effect3.FiberRef.get(currentLinkId);
1775
+ if (linkId) {
1776
+ ;
1777
+ enriched.linkId = linkId;
1778
+ }
1779
+ }
1780
+ if (sinks.length === 1) {
1781
+ yield* sinks[0].record(enriched);
1782
+ return;
1783
+ }
1784
+ yield* import_effect3.Effect.forEach(sinks, (sink) => sink.record(enriched), { discard: true });
1785
+ });
1786
+
1787
+ // src/internal/runtime/core/DevtoolsHub.ts
1788
+ var import_effect4 = require("effect");
1789
+ var lastRunTs = 0;
1790
+ var lastRunTsSeq = 0;
1791
+ var nextRunId = () => {
1792
+ const ts = Date.now();
1793
+ if (ts === lastRunTs) {
1794
+ lastRunTsSeq += 1;
1795
+ } else {
1796
+ lastRunTs = ts;
1797
+ lastRunTsSeq = 0;
1798
+ }
1799
+ return lastRunTsSeq === 0 ? `run-${ts}` : `run-${ts}.${lastRunTsSeq}`;
1800
+ };
1801
+ var currentRunId = nextRunId();
1802
+
1803
+ // src/internal/runtime/core/TaskRunner.ts
1804
+ var import_effect5 = require("effect");
1805
+ var inSyncTransactionFiber = import_effect5.FiberRef.unsafeMake(false);
1806
+ var forceSourceRefresh = import_effect5.FiberRef.unsafeMake(false);
1807
+
1808
+ // src/internal/runtime/core/DeclarativeLinkRuntime.ts
1809
+ var import_effect7 = require("effect");
1810
+ var makeDeclarativeLinkRuntime = () => {
1811
+ const moduleAsSourceById = /* @__PURE__ */ new Map();
1812
+ const moduleAsSourceIdsBySource = /* @__PURE__ */ new Map();
1813
+ const declarativeById = /* @__PURE__ */ new Map();
1814
+ const declarativeReadNodesBySource = /* @__PURE__ */ new Map();
1815
+ const registerModuleAsSourceLink = (link2) => {
1816
+ const stored = {
1817
+ ...link2,
1818
+ hasValue: false,
1819
+ lastValue: void 0
1820
+ };
1821
+ moduleAsSourceById.set(link2.id, stored);
1822
+ const set = moduleAsSourceIdsBySource.get(link2.sourceModuleInstanceKey) ?? /* @__PURE__ */ new Set();
1823
+ set.add(link2.id);
1824
+ moduleAsSourceIdsBySource.set(link2.sourceModuleInstanceKey, set);
1825
+ return () => {
1826
+ moduleAsSourceById.delete(link2.id);
1827
+ const current = moduleAsSourceIdsBySource.get(link2.sourceModuleInstanceKey);
1828
+ if (!current) return;
1829
+ current.delete(link2.id);
1830
+ if (current.size === 0) {
1831
+ moduleAsSourceIdsBySource.delete(link2.sourceModuleInstanceKey);
1832
+ }
1833
+ };
1834
+ };
1835
+ const registerDeclarativeLink = (link2) => {
1836
+ const readNodeById = /* @__PURE__ */ new Map();
1837
+ for (const n of link2.readNodes) {
1838
+ readNodeById.set(n.nodeId, n);
1839
+ }
1840
+ const dispatchNodeById = /* @__PURE__ */ new Map();
1841
+ for (const n of link2.dispatchNodes) {
1842
+ dispatchNodeById.set(n.nodeId, n);
1843
+ }
1844
+ const incomingByDispatch = /* @__PURE__ */ new Map();
1845
+ for (const e of link2.ir.edges) {
1846
+ const to = e.to;
1847
+ const isDispatch = dispatchNodeById.has(to);
1848
+ if (!isDispatch) continue;
1849
+ incomingByDispatch.set(to, (incomingByDispatch.get(to) ?? 0) + 1);
1850
+ const count = incomingByDispatch.get(to) ?? 0;
1851
+ if (count > 1) {
1852
+ throw new Error(
1853
+ `[DeclarativeLinkRuntime] Invalid DeclarativeLinkIR: dispatch node has multiple incoming edges (linkId=${link2.linkId}, nodeId=${to}).`
1854
+ );
1855
+ }
1856
+ }
1857
+ const dispatchTargetsByReadNode = /* @__PURE__ */ new Map();
1858
+ for (const e of link2.ir.edges) {
1859
+ const from2 = e.from;
1860
+ const to = e.to;
1861
+ if (!readNodeById.has(from2)) continue;
1862
+ if (!dispatchNodeById.has(to)) continue;
1863
+ const list2 = dispatchTargetsByReadNode.get(from2) ?? [];
1864
+ list2.push(to);
1865
+ dispatchTargetsByReadNode.set(from2, list2);
1866
+ }
1867
+ const stored = {
1868
+ ...link2,
1869
+ readNodeById,
1870
+ dispatchNodeById,
1871
+ dispatchTargetsByReadNode,
1872
+ readNodeState: /* @__PURE__ */ new Map()
1873
+ };
1874
+ declarativeById.set(link2.linkId, stored);
1875
+ for (const n of link2.readNodes) {
1876
+ const list2 = declarativeReadNodesBySource.get(n.moduleInstanceKey) ?? [];
1877
+ list2.push({ linkId: link2.linkId, nodeId: n.nodeId });
1878
+ declarativeReadNodesBySource.set(n.moduleInstanceKey, list2);
1879
+ }
1880
+ return () => {
1881
+ declarativeById.delete(link2.linkId);
1882
+ for (const n of link2.readNodes) {
1883
+ const list2 = declarativeReadNodesBySource.get(n.moduleInstanceKey);
1884
+ if (!list2) continue;
1885
+ const next = list2.filter((x) => !(x.linkId === link2.linkId && x.nodeId === n.nodeId));
1886
+ if (next.length === 0) {
1887
+ declarativeReadNodesBySource.delete(n.moduleInstanceKey);
1888
+ } else {
1889
+ declarativeReadNodesBySource.set(n.moduleInstanceKey, next);
1890
+ }
1891
+ }
1892
+ };
1893
+ };
1894
+ const applyForSources = (args) => import_effect7.Effect.gen(function* () {
1895
+ let scheduled = false;
1896
+ for (const sourceKey of args.changedModuleInstanceKeys) {
1897
+ const ids = moduleAsSourceIdsBySource.get(sourceKey);
1898
+ if (!ids || ids.size === 0) continue;
1899
+ const commit = args.acceptedModules.get(sourceKey);
1900
+ if (!commit) continue;
1901
+ for (const id of ids) {
1902
+ const link2 = moduleAsSourceById.get(id);
1903
+ if (!link2) continue;
1904
+ let selected;
1905
+ try {
1906
+ selected = link2.readQuery.select(commit.state);
1907
+ } catch {
1908
+ continue;
1909
+ }
1910
+ const nextValue = link2.computeValue(selected);
1911
+ if (link2.hasValue && link2.equalsValue(link2.lastValue, nextValue)) {
1912
+ continue;
1913
+ }
1914
+ link2.hasValue = true;
1915
+ link2.lastValue = nextValue;
1916
+ scheduled = true;
1917
+ yield* link2.applyValue(nextValue);
1918
+ }
1919
+ }
1920
+ for (const sourceKey of args.changedModuleInstanceKeys) {
1921
+ const refs = declarativeReadNodesBySource.get(sourceKey);
1922
+ if (!refs || refs.length === 0) continue;
1923
+ const commit = args.acceptedModules.get(sourceKey);
1924
+ if (!commit) continue;
1925
+ for (const ref of refs) {
1926
+ const link2 = declarativeById.get(ref.linkId);
1927
+ if (!link2) continue;
1928
+ const readNode = link2.readNodeById.get(ref.nodeId);
1929
+ if (!readNode) continue;
1930
+ let value;
1931
+ try {
1932
+ value = readNode.readQuery.select(commit.state);
1933
+ } catch {
1934
+ continue;
1935
+ }
1936
+ const state = link2.readNodeState.get(ref.nodeId) ?? { hasValue: false, lastValue: void 0 };
1937
+ const changed = !state.hasValue || !Object.is(state.lastValue, value);
1938
+ if (!changed) continue;
1939
+ state.hasValue = true;
1940
+ state.lastValue = value;
1941
+ link2.readNodeState.set(ref.nodeId, state);
1942
+ const targets = link2.dispatchTargetsByReadNode.get(ref.nodeId) ?? [];
1943
+ for (const dispatchNodeId of targets) {
1944
+ const node2 = link2.dispatchNodeById.get(dispatchNodeId);
1945
+ if (!node2) continue;
1946
+ scheduled = true;
1947
+ yield* node2.dispatch(value);
1948
+ }
1949
+ }
1950
+ }
1951
+ return { scheduled };
1952
+ });
1953
+ return {
1954
+ registerModuleAsSourceLink,
1955
+ registerDeclarativeLink,
1956
+ applyForSources
1957
+ };
1958
+ };
1959
+
1960
+ // src/internal/runtime/core/env.ts
1961
+ var getNodeEnv = () => {
1962
+ try {
1963
+ const env = globalThis?.process?.env;
1964
+ return typeof env?.NODE_ENV === "string" ? env.NODE_ENV : void 0;
1965
+ } catch {
1966
+ return void 0;
1967
+ }
1968
+ };
1969
+ var isDevEnv = () => getNodeEnv() !== "production";
1970
+ var StateTransactionConfigTagImpl = class extends import_effect8.Context.Tag("@logixjs/core/StateTransactionRuntimeConfig")() {
1971
+ };
1972
+ var ReadQueryStrictGateConfigTagImpl = class extends import_effect8.Context.Tag("@logixjs/core/ReadQueryStrictGateRuntimeConfig")() {
1973
+ };
1974
+ var ReplayModeConfigTagImpl = class extends import_effect8.Context.Tag("@logixjs/core/ReplayModeConfig")() {
1975
+ };
1976
+ var ReplayModeConfigTag = ReplayModeConfigTagImpl;
1977
+ var StateTransactionOverridesTagImpl = class extends import_effect8.Context.Tag("@logixjs/core/StateTransactionOverrides")() {
1978
+ };
1979
+ var ConcurrencyPolicyTagImpl = class extends import_effect8.Context.Tag("@logixjs/core/ConcurrencyPolicy")() {
1980
+ };
1981
+ var ConcurrencyPolicyOverridesTagImpl = class extends import_effect8.Context.Tag("@logixjs/core/ConcurrencyPolicyOverrides")() {
1982
+ };
1983
+ var RuntimeStoreTag = class extends import_effect8.Context.Tag("@logixjs/core/RuntimeStore")() {
1984
+ };
1985
+ var runtimeStoreLayer = import_effect8.Layer.scoped(
1986
+ RuntimeStoreTag,
1987
+ import_effect8.Effect.acquireRelease(
1988
+ import_effect8.Effect.sync(() => makeRuntimeStore()),
1989
+ (store) => import_effect8.Effect.sync(() => store.dispose())
1990
+ )
1991
+ );
1992
+ var HostSchedulerTag = class extends import_effect8.Context.Tag("@logixjs/core/HostScheduler")() {
1993
+ };
1994
+ var hostSchedulerLayer = import_effect8.Layer.succeed(
1995
+ HostSchedulerTag,
1996
+ getGlobalHostScheduler()
1997
+ );
1998
+ var DeclarativeLinkRuntimeTag = class extends import_effect8.Context.Tag("@logixjs/core/DeclarativeLinkRuntime")() {
1999
+ };
2000
+ var declarativeLinkRuntimeLayer = import_effect8.Layer.succeed(
2001
+ DeclarativeLinkRuntimeTag,
2002
+ makeDeclarativeLinkRuntime()
2003
+ );
2004
+ var TickSchedulerTag = class extends import_effect8.Context.Tag("@logixjs/core/TickScheduler")() {
2005
+ };
2006
+
2007
+ // src/internal/runtime/core/runtimeInternalsAccessor.ts
2008
+ var BOUND_INTERNALS = /* @__PURE__ */ Symbol.for("@logixjs/core/boundInternals");
2009
+ var getBoundInternals = (bound) => {
2010
+ const internals = bound[BOUND_INTERNALS];
2011
+ if (!internals) {
2012
+ const msg = isDevEnv() ? [
2013
+ "[MissingBoundInternals] Bound internals not installed on Bound API instance.",
2014
+ "fix:",
2015
+ "- Ensure BoundApiRuntime attaches internals (020 foundation).",
2016
+ "- If you created a mock bound for tests, attach internals or avoid calling internal-only APIs."
2017
+ ].join("\n") : "Bound internals not installed";
2018
+ throw new Error(msg);
2019
+ }
2020
+ return internals;
2021
+ };
2022
+
2023
+ // src/internal/state-trait/source.impl.ts
2024
+ var import_effect13 = require("effect");
2025
+ var import_mutative = require("mutative");
2026
+
2027
+ // src/internal/effect-op.ts
2028
+ var import_effect10 = require("effect");
2029
+
2030
+ // src/internal/observability/runSession.ts
2031
+ var import_effect9 = require("effect");
2032
+ var RunSessionTagImpl = class extends import_effect9.Context.Tag("@logixjs/core/RunSession")() {
2033
+ };
2034
+ var RunSessionTag = RunSessionTagImpl;
2035
+
2036
+ // src/internal/effect-op.ts
2037
+ var nextGlobalOpSeq = 0;
2038
+ var nextOpSeq = () => {
2039
+ nextGlobalOpSeq += 1;
2040
+ return nextGlobalOpSeq;
2041
+ };
2042
+ var makeId = (instanceId, opSeq) => instanceId ? `${instanceId}::o${opSeq}` : `o${opSeq}`;
2043
+ var make = (params) => ({
2044
+ ...params.id ? { id: params.id, meta: params.meta } : (() => {
2045
+ const meta = params.meta ?? {};
2046
+ const instanceId = meta.instanceId;
2047
+ const opSeq = typeof meta.opSeq === "number" && Number.isFinite(meta.opSeq) ? Math.floor(meta.opSeq) : nextOpSeq();
2048
+ return {
2049
+ id: makeId(instanceId, opSeq),
2050
+ meta: meta.opSeq === opSeq ? meta : { ...meta, opSeq }
2051
+ };
2052
+ })(),
2053
+ kind: params.kind,
2054
+ name: params.name,
2055
+ payload: params.payload,
2056
+ effect: params.effect
2057
+ });
2058
+ var run = (op, stack) => runWithMiddleware(op, stack);
2059
+
2060
+ // src/internal/resource.ts
2061
+ var import_effect11 = require("effect");
2062
+ var stableStringify3 = (value) => {
2063
+ const seen = /* @__PURE__ */ new WeakSet();
2064
+ const encode = (input) => {
2065
+ if (input === null) return null;
2066
+ if (typeof input === "string" || typeof input === "number" || typeof input === "boolean") {
2067
+ return input;
2068
+ }
2069
+ if (typeof input === "bigint") return input.toString();
2070
+ if (typeof input === "undefined") return "__undefined__";
2071
+ if (typeof input === "symbol") return `__symbol__:${String(input)}`;
2072
+ if (typeof input === "function") return "__function__";
2073
+ if (Array.isArray(input)) {
2074
+ return input.map((v) => encode(v));
1495
2075
  }
1496
- yield* import_effect7.Effect.void;
1497
- return;
1498
- }
1499
- const enriched = event;
1500
- const diagnosticsLevel = yield* import_effect7.FiberRef.get(currentDiagnosticsLevel);
1501
- let now;
1502
- const getNow = () => {
1503
- if (now === void 0) now = Date.now();
1504
- return now;
1505
- };
1506
- if (enriched.timestamp === void 0 && (diagnosticsLevel !== "off" || enriched.type === "lifecycle:error" || enriched.type === "diagnostic")) {
1507
- ;
1508
- enriched.timestamp = getNow();
1509
- }
1510
- if (diagnosticsLevel !== "off" && enriched.runtimeLabel === void 0) {
1511
- const runtimeLabel = yield* import_effect7.FiberRef.get(currentRuntimeLabel);
1512
- if (runtimeLabel) {
1513
- ;
1514
- enriched.runtimeLabel = runtimeLabel;
2076
+ if (input instanceof Date) {
2077
+ return `__date__:${input.toISOString()}`;
1515
2078
  }
1516
- }
1517
- if (enriched.type === "diagnostic" && enriched.txnId === void 0) {
1518
- const txnId = yield* import_effect7.FiberRef.get(currentTxnId);
1519
- if (txnId) {
1520
- ;
1521
- enriched.txnId = txnId;
2079
+ if (input instanceof Error) {
2080
+ return {
2081
+ _tag: "Error",
2082
+ name: input.name,
2083
+ message: input.message
2084
+ };
1522
2085
  }
1523
- }
1524
- if (diagnosticsLevel !== "off" && enriched.type === "trace:effectop" && enriched.linkId === void 0) {
1525
- const linkId = yield* import_effect7.FiberRef.get(currentLinkId);
1526
- if (linkId) {
1527
- ;
1528
- enriched.linkId = linkId;
2086
+ if (input && typeof input === "object") {
2087
+ const obj = input;
2088
+ if (seen.has(obj)) return "__cycle__";
2089
+ seen.add(obj);
2090
+ const record2 = input;
2091
+ const keys = Object.keys(record2).sort();
2092
+ const out = {};
2093
+ for (const k of keys) {
2094
+ out[k] = encode(record2[k]);
2095
+ }
2096
+ return out;
1529
2097
  }
2098
+ return String(input);
2099
+ };
2100
+ try {
2101
+ return JSON.stringify(encode(value));
2102
+ } catch {
2103
+ return String(value);
1530
2104
  }
1531
- if (sinks.length === 1) {
1532
- yield* sinks[0].record(enriched);
1533
- return;
1534
- }
1535
- yield* import_effect7.Effect.forEach(sinks, (sink) => sink.record(enriched), { discard: true });
1536
- });
1537
-
1538
- // src/internal/runtime/core/TaskRunner.ts
1539
- var import_effect8 = require("effect");
1540
- var inSyncTransactionFiber = import_effect8.FiberRef.unsafeMake(false);
1541
- var forceSourceRefresh = import_effect8.FiberRef.unsafeMake(false);
2105
+ };
2106
+ var keyHash = (key) => stableStringify3(key);
2107
+ var Snapshot = {
2108
+ idle: () => ({
2109
+ status: "idle",
2110
+ keyHash: void 0,
2111
+ data: void 0,
2112
+ error: void 0
2113
+ }),
2114
+ loading: (params) => ({
2115
+ status: "loading",
2116
+ keyHash: params.keyHash,
2117
+ data: void 0,
2118
+ error: void 0
2119
+ }),
2120
+ success: (params) => ({
2121
+ status: "success",
2122
+ keyHash: params.keyHash,
2123
+ data: params.data,
2124
+ error: void 0
2125
+ }),
2126
+ error: (params) => ({
2127
+ status: "error",
2128
+ keyHash: params.keyHash,
2129
+ data: void 0,
2130
+ error: params.error
2131
+ })
2132
+ };
2133
+ var ResourceRegistryTag = class extends import_effect11.Context.Tag("@logixjs/core/ResourceRegistry")() {
2134
+ };
2135
+ var internal = {
2136
+ ResourceRegistryTag
2137
+ };
1542
2138
 
1543
2139
  // src/internal/runtime/core/ReplayLog.ts
1544
- var import_effect9 = require("effect");
1545
- var ReplayLog = class extends import_effect9.Context.Tag("@logixjs/core/ReplayLog")() {
2140
+ var import_effect12 = require("effect");
2141
+ var ReplayLog = class extends import_effect12.Context.Tag("@logixjs/core/ReplayLog")() {
1546
2142
  };
1547
- var snapshot = import_effect9.Effect.gen(function* () {
2143
+ var snapshot = import_effect12.Effect.gen(function* () {
1548
2144
  const log = yield* ReplayLog;
1549
2145
  return yield* log.snapshot;
1550
2146
  });
1551
- var resetCursor = import_effect9.Effect.gen(function* () {
2147
+ var resetCursor = import_effect12.Effect.gen(function* () {
1552
2148
  const log = yield* ReplayLog;
1553
2149
  yield* log.resetCursor;
1554
2150
  });
@@ -1698,16 +2294,16 @@ var trace = (fn, state) => {
1698
2294
  };
1699
2295
  };
1700
2296
 
1701
- // src/internal/state-trait/source.ts
1702
- var onceInRunSession = (key) => import_effect10.Effect.serviceOption(RunSessionTag).pipe(
1703
- import_effect10.Effect.map((maybe) => import_effect10.Option.isSome(maybe) ? maybe.value.local.once(key) : true)
2297
+ // src/internal/state-trait/source.impl.ts
2298
+ var onceInRunSession = (key) => import_effect13.Effect.serviceOption(RunSessionTag).pipe(
2299
+ import_effect13.Effect.map((maybe) => import_effect13.Option.isSome(maybe) ? maybe.value.local.once(key) : true)
1704
2300
  );
1705
2301
  var formatList = (items, limit = 10) => {
1706
2302
  if (items.length === 0) return "";
1707
2303
  if (items.length <= limit) return items.join(", ");
1708
2304
  return `${items.slice(0, limit).join(", ")}, \u2026(+${items.length - limit})`;
1709
2305
  };
1710
- var emitDepsMismatch = (params) => import_effect10.Effect.gen(function* () {
2306
+ var emitDepsMismatch = (params) => import_effect13.Effect.gen(function* () {
1711
2307
  const key = `${params.instanceId ?? "unknown"}::${params.kind}::${params.fieldPath}`;
1712
2308
  const shouldEmit = yield* onceInRunSession(`deps_mismatch:${key}`);
1713
2309
  if (!shouldEmit) return;
@@ -1722,8 +2318,8 @@ var emitDepsMismatch = (params) => import_effect10.Effect.gen(function* () {
1722
2318
  kind: `deps_mismatch:${params.kind}`
1723
2319
  });
1724
2320
  });
1725
- var getMiddlewareStack = () => import_effect10.Effect.serviceOption(EffectOpMiddlewareTag).pipe(
1726
- import_effect10.Effect.map((maybe) => import_effect10.Option.isSome(maybe) ? maybe.value.stack : [])
2321
+ var getMiddlewareStack = () => import_effect13.Effect.serviceOption(EffectOpMiddlewareTag).pipe(
2322
+ import_effect13.Effect.map((maybe) => import_effect13.Option.isSome(maybe) ? maybe.value.stack : [])
1727
2323
  );
1728
2324
  var recordTraitPatch = (bound, path, reason, from2, to, traitNodeId) => {
1729
2325
  const normalized = normalizeFieldPath(path) ?? [];
@@ -1748,7 +2344,7 @@ var getBoundScope = (bound) => {
1748
2344
  return { moduleId: void 0, instanceId: void 0 };
1749
2345
  }
1750
2346
  };
1751
- var setSnapshotInTxn = (bound, fieldPath, next, reason, stepId, traitNodeId) => import_effect10.Effect.gen(function* () {
2347
+ var setSnapshotInTxn = (bound, fieldPath, next, reason, stepId, traitNodeId) => import_effect13.Effect.gen(function* () {
1752
2348
  let wrote = false;
1753
2349
  yield* bound.state.mutate((draft) => {
1754
2350
  const prev = getAtPath(draft, fieldPath);
@@ -1759,7 +2355,7 @@ var setSnapshotInTxn = (bound, fieldPath, next, reason, stepId, traitNodeId) =>
1759
2355
  });
1760
2356
  return wrote;
1761
2357
  });
1762
- var writebackIfCurrentKeyHash = (bound, fieldPath, keyHash2, next, reason, stepId, traitNodeId, replayEvent) => import_effect10.Effect.gen(function* () {
2358
+ var writebackIfCurrentKeyHash = (bound, fieldPath, keyHash2, next, reason, stepId, traitNodeId, replayEvent) => import_effect13.Effect.gen(function* () {
1763
2359
  let wrote = false;
1764
2360
  yield* bound.state.mutate((draft) => {
1765
2361
  const current = getAtPath(draft, fieldPath);
@@ -1777,7 +2373,7 @@ var writebackIfCurrentKeyHash = (bound, fieldPath, keyHash2, next, reason, stepI
1777
2373
  return wrote;
1778
2374
  });
1779
2375
  var installSourceRefresh = (bound, step, entry) => {
1780
- if (!step.targetFieldPath) return import_effect10.Effect.void;
2376
+ if (!step.targetFieldPath) return import_effect13.Effect.void;
1781
2377
  const fieldPath = step.targetFieldPath;
1782
2378
  const resourceId = step.resourceId ?? entry.meta.resource;
1783
2379
  const listItem = parseListItemFieldPath(fieldPath);
@@ -1785,12 +2381,12 @@ var installSourceRefresh = (bound, step, entry) => {
1785
2381
  try {
1786
2382
  internals = getBoundInternals(bound);
1787
2383
  } catch {
1788
- return import_effect10.Effect.void;
2384
+ return import_effect13.Effect.void;
1789
2385
  }
1790
2386
  const register = internals.traits.registerSourceRefresh;
1791
2387
  const recordSnapshot = (replayMode, replayLog, input) => {
1792
- if (!replayLog) return import_effect10.Effect.void;
1793
- if (replayMode !== "live") return import_effect10.Effect.void;
2388
+ if (!replayLog) return import_effect13.Effect.void;
2389
+ if (replayMode !== "live") return import_effect13.Effect.void;
1794
2390
  const event = input && typeof input === "object" && input._tag === "ResourceSnapshot" ? input : {
1795
2391
  _tag: "ResourceSnapshot",
1796
2392
  resourceId,
@@ -1808,12 +2404,12 @@ var installSourceRefresh = (bound, step, entry) => {
1808
2404
  if (listItem) {
1809
2405
  const store = internals.traits.rowIdStore;
1810
2406
  if (!store) {
1811
- return import_effect10.Effect.void;
2407
+ return import_effect13.Effect.void;
1812
2408
  }
1813
2409
  const listPath = listItem.listPath;
1814
2410
  const itemPath = listItem.itemPath;
1815
2411
  if (!itemPath) {
1816
- return import_effect10.Effect.void;
2412
+ return import_effect13.Effect.void;
1817
2413
  }
1818
2414
  const concurrency2 = entry.meta.concurrency;
1819
2415
  const mode2 = concurrency2 ?? "switch";
@@ -1824,7 +2420,7 @@ var installSourceRefresh = (bound, step, entry) => {
1824
2420
  trailing2.delete(rowId);
1825
2421
  inFlight2.delete(rowId);
1826
2422
  });
1827
- const setSnapshotForRowInTxn = (rowId, next, reason, stepId) => import_effect10.Effect.gen(function* () {
2423
+ const setSnapshotForRowInTxn = (rowId, next, reason, stepId) => import_effect13.Effect.gen(function* () {
1828
2424
  let wrotePath;
1829
2425
  yield* bound.state.mutate((draft) => {
1830
2426
  const index = store.getIndex(listPath, rowId);
@@ -1838,7 +2434,7 @@ var installSourceRefresh = (bound, step, entry) => {
1838
2434
  });
1839
2435
  return wrotePath;
1840
2436
  });
1841
- const writebackIfCurrentKeyHashForRow = (rowId, keyHash2, next, reason, stepId, phase) => import_effect10.Effect.gen(function* () {
2437
+ const writebackIfCurrentKeyHashForRow = (rowId, keyHash2, next, reason, stepId, phase) => import_effect13.Effect.gen(function* () {
1842
2438
  let wrotePath;
1843
2439
  yield* bound.state.mutate((draft) => {
1844
2440
  const index = store.getIndex(listPath, rowId);
@@ -1870,7 +2466,7 @@ var installSourceRefresh = (bound, step, entry) => {
1870
2466
  });
1871
2467
  return wrotePath;
1872
2468
  });
1873
- const startFetch2 = (rowId, key, keyHash2, replayMode, replayLog) => import_effect10.Effect.gen(function* () {
2469
+ const startFetch2 = (rowId, key, keyHash2, replayMode, replayLog) => import_effect13.Effect.gen(function* () {
1874
2470
  const { moduleId, instanceId } = getBoundScope(bound);
1875
2471
  const indexForLog = store.getIndex(listPath, rowId);
1876
2472
  const logFieldPath = indexForLog === void 0 ? void 0 : toListItemValuePath(listPath, indexForLog, itemPath);
@@ -1908,17 +2504,17 @@ var installSourceRefresh = (bound, step, entry) => {
1908
2504
  recordReplayEvent(bound, event);
1909
2505
  yield* recordSnapshot(replayMode, replayLog, event);
1910
2506
  }
1911
- const io = import_effect10.Effect.gen(function* () {
2507
+ const io = import_effect13.Effect.gen(function* () {
1912
2508
  if (replayMode === "replay" && replayLog) {
1913
- yield* import_effect10.Effect.yieldNow();
2509
+ yield* import_effect13.Effect.yieldNow();
1914
2510
  const consumePath = wroteLoadingPath ?? logFieldPath;
1915
- if (!consumePath) return yield* import_effect10.Effect.void;
2511
+ if (!consumePath) return yield* import_effect13.Effect.void;
1916
2512
  const replayed = yield* replayLog.consumeNextResourceSnapshot({
1917
2513
  resourceId,
1918
2514
  fieldPath: consumePath,
1919
2515
  keyHash: keyHash2
1920
2516
  });
1921
- if (!replayed) return yield* import_effect10.Effect.void;
2517
+ if (!replayed) return yield* import_effect13.Effect.void;
1922
2518
  if (replayed.phase === "success") {
1923
2519
  yield* writebackIfCurrentKeyHashForRow(
1924
2520
  rowId,
@@ -1938,14 +2534,14 @@ var installSourceRefresh = (bound, step, entry) => {
1938
2534
  "error"
1939
2535
  );
1940
2536
  }
1941
- return yield* import_effect10.Effect.void;
2537
+ return yield* import_effect13.Effect.void;
1942
2538
  }
1943
2539
  const stack = yield* getMiddlewareStack();
1944
- const registryOpt = yield* import_effect10.Effect.serviceOption(internal.ResourceRegistryTag);
1945
- const registry = import_effect10.Option.isSome(registryOpt) ? registryOpt.value : void 0;
2540
+ const registryOpt = yield* import_effect13.Effect.serviceOption(internal.ResourceRegistryTag);
2541
+ const registry = import_effect13.Option.isSome(registryOpt) ? registryOpt.value : void 0;
1946
2542
  const spec = registry?.specs.get(resourceId);
1947
2543
  if (!spec) {
1948
- return yield* import_effect10.Effect.void;
2544
+ return yield* import_effect13.Effect.void;
1949
2545
  }
1950
2546
  const loadEffect = spec.load(key);
1951
2547
  const meta = {
@@ -1960,8 +2556,8 @@ var installSourceRefresh = (bound, step, entry) => {
1960
2556
  stepId: step.id
1961
2557
  };
1962
2558
  if (!(typeof meta.opSeq === "number" && Number.isFinite(meta.opSeq))) {
1963
- const sessionOpt = yield* import_effect10.Effect.serviceOption(RunSessionTag);
1964
- if (import_effect10.Option.isSome(sessionOpt)) {
2559
+ const sessionOpt = yield* import_effect13.Effect.serviceOption(RunSessionTag);
2560
+ if (import_effect13.Option.isSome(sessionOpt)) {
1965
2561
  const seqKey = instanceId ?? "global";
1966
2562
  meta.opSeq = sessionOpt.value.local.nextSeq("opSeq", seqKey);
1967
2563
  }
@@ -1972,7 +2568,7 @@ var installSourceRefresh = (bound, step, entry) => {
1972
2568
  effect: loadEffect,
1973
2569
  meta
1974
2570
  });
1975
- const exit = yield* import_effect10.Effect.exit(run(op, stack));
2571
+ const exit = yield* import_effect13.Effect.exit(run(op, stack));
1976
2572
  if (exit._tag === "Success") {
1977
2573
  const successSnapshot = Snapshot.success({ keyHash: keyHash2, data: exit.value });
1978
2574
  const wroteSuccessPath = yield* writebackIfCurrentKeyHashForRow(
@@ -2022,47 +2618,47 @@ var installSourceRefresh = (bound, step, entry) => {
2022
2618
  });
2023
2619
  }
2024
2620
  }
2025
- }).pipe(import_effect10.Effect.catchAllCause(() => import_effect10.Effect.void));
2026
- const fiber = yield* import_effect10.Effect.forkScoped(import_effect10.Effect.locally(inSyncTransactionFiber, false)(io));
2621
+ }).pipe(import_effect13.Effect.catchAllCause(() => import_effect13.Effect.void));
2622
+ const fiber = yield* import_effect13.Effect.forkScoped(import_effect13.Effect.locally(inSyncTransactionFiber, false)(io));
2027
2623
  const myGen = gen2 += 1;
2028
2624
  inFlight2.set(rowId, { gen: myGen, fiber, keyHash: keyHash2 });
2029
- yield* import_effect10.Effect.forkScoped(
2030
- import_effect10.Effect.locally(
2625
+ yield* import_effect13.Effect.forkScoped(
2626
+ import_effect13.Effect.locally(
2031
2627
  inSyncTransactionFiber,
2032
2628
  false
2033
2629
  )(
2034
- import_effect10.Fiber.await(fiber).pipe(
2035
- import_effect10.Effect.zipRight(
2036
- import_effect10.Effect.sync(() => {
2630
+ import_effect13.Fiber.await(fiber).pipe(
2631
+ import_effect13.Effect.zipRight(
2632
+ import_effect13.Effect.sync(() => {
2037
2633
  const current = inFlight2.get(rowId);
2038
2634
  if (current && current.gen === myGen) {
2039
2635
  inFlight2.delete(rowId);
2040
2636
  }
2041
2637
  })
2042
2638
  ),
2043
- import_effect10.Effect.zipRight(
2044
- mode2 === "exhaust-trailing" ? import_effect10.Effect.gen(function* () {
2639
+ import_effect13.Effect.zipRight(
2640
+ mode2 === "exhaust-trailing" ? import_effect13.Effect.gen(function* () {
2045
2641
  const next = trailing2.get(rowId);
2046
2642
  trailing2.delete(rowId);
2047
2643
  if (next) {
2048
2644
  yield* startFetch2(rowId, next.key, next.keyHash, replayMode, replayLog);
2049
2645
  }
2050
- }) : import_effect10.Effect.void
2646
+ }) : import_effect13.Effect.void
2051
2647
  ),
2052
- import_effect10.Effect.catchAllCause(() => import_effect10.Effect.void)
2648
+ import_effect13.Effect.catchAllCause(() => import_effect13.Effect.void)
2053
2649
  )
2054
2650
  )
2055
2651
  );
2056
2652
  });
2057
2653
  register(
2058
2654
  fieldPath,
2059
- (state) => import_effect10.Effect.gen(function* () {
2655
+ (state) => import_effect13.Effect.gen(function* () {
2060
2656
  const { moduleId, instanceId } = getBoundScope(bound);
2061
- const replayModeOpt = yield* import_effect10.Effect.serviceOption(ReplayModeConfigTag);
2062
- const replayMode = import_effect10.Option.isSome(replayModeOpt) ? replayModeOpt.value.mode : "live";
2063
- const replayLogOpt = yield* import_effect10.Effect.serviceOption(ReplayLog);
2064
- const replayLog = import_effect10.Option.isSome(replayLogOpt) ? replayLogOpt.value : void 0;
2065
- const force = yield* import_effect10.FiberRef.get(forceSourceRefresh);
2657
+ const replayModeOpt = yield* import_effect13.Effect.serviceOption(ReplayModeConfigTag);
2658
+ const replayMode = import_effect13.Option.isSome(replayModeOpt) ? replayModeOpt.value.mode : "live";
2659
+ const replayLogOpt = yield* import_effect13.Effect.serviceOption(ReplayLog);
2660
+ const replayLog = import_effect13.Option.isSome(replayLogOpt) ? replayLogOpt.value : void 0;
2661
+ const force = yield* import_effect13.FiberRef.get(forceSourceRefresh);
2066
2662
  const listValue = getAtPath(state, listPath);
2067
2663
  const items = Array.isArray(listValue) ? listValue : [];
2068
2664
  const ids = store.ensureList(listPath, items);
@@ -2173,14 +2769,14 @@ var installSourceRefresh = (bound, step, entry) => {
2173
2769
  }
2174
2770
  })
2175
2771
  );
2176
- return import_effect10.Effect.void;
2772
+ return import_effect13.Effect.void;
2177
2773
  }
2178
2774
  let inFlight;
2179
2775
  let gen = 0;
2180
2776
  let trailing;
2181
2777
  const concurrency = entry.meta.concurrency;
2182
2778
  const mode = concurrency ?? "switch";
2183
- const startFetch = (key, keyHash2, replayMode, replayLog) => import_effect10.Effect.gen(function* () {
2779
+ const startFetch = (key, keyHash2, replayMode, replayLog) => import_effect13.Effect.gen(function* () {
2184
2780
  const { moduleId, instanceId } = getBoundScope(bound);
2185
2781
  let loadingSnapshot = Snapshot.loading({ keyHash: keyHash2 });
2186
2782
  if (replayMode === "replay" && replayLog) {
@@ -2218,15 +2814,15 @@ var installSourceRefresh = (bound, step, entry) => {
2218
2814
  recordReplayEvent(bound, event);
2219
2815
  yield* recordSnapshot(replayMode, replayLog, event);
2220
2816
  }
2221
- const io = import_effect10.Effect.gen(function* () {
2817
+ const io = import_effect13.Effect.gen(function* () {
2222
2818
  if (replayMode === "replay" && replayLog) {
2223
- yield* import_effect10.Effect.yieldNow();
2819
+ yield* import_effect13.Effect.yieldNow();
2224
2820
  const replayed = yield* replayLog.consumeNextResourceSnapshot({
2225
2821
  resourceId,
2226
2822
  fieldPath,
2227
2823
  keyHash: keyHash2
2228
2824
  });
2229
- if (!replayed) return yield* import_effect10.Effect.void;
2825
+ if (!replayed) return yield* import_effect13.Effect.void;
2230
2826
  if (replayed.phase === "success") {
2231
2827
  const event = {
2232
2828
  _tag: "ResourceSnapshot",
@@ -2274,14 +2870,14 @@ var installSourceRefresh = (bound, step, entry) => {
2274
2870
  event
2275
2871
  );
2276
2872
  }
2277
- return yield* import_effect10.Effect.void;
2873
+ return yield* import_effect13.Effect.void;
2278
2874
  }
2279
2875
  const stack = yield* getMiddlewareStack();
2280
- const registryOpt = yield* import_effect10.Effect.serviceOption(internal.ResourceRegistryTag);
2281
- const registry = import_effect10.Option.isSome(registryOpt) ? registryOpt.value : void 0;
2876
+ const registryOpt = yield* import_effect13.Effect.serviceOption(internal.ResourceRegistryTag);
2877
+ const registry = import_effect13.Option.isSome(registryOpt) ? registryOpt.value : void 0;
2282
2878
  const spec = registry?.specs.get(resourceId);
2283
2879
  if (!spec) {
2284
- return yield* import_effect10.Effect.void;
2880
+ return yield* import_effect13.Effect.void;
2285
2881
  }
2286
2882
  const loadEffect = spec.load(key);
2287
2883
  const meta = {
@@ -2295,8 +2891,8 @@ var installSourceRefresh = (bound, step, entry) => {
2295
2891
  stepId: step.id
2296
2892
  };
2297
2893
  if (!(typeof meta.opSeq === "number" && Number.isFinite(meta.opSeq))) {
2298
- const sessionOpt = yield* import_effect10.Effect.serviceOption(RunSessionTag);
2299
- if (import_effect10.Option.isSome(sessionOpt)) {
2894
+ const sessionOpt = yield* import_effect13.Effect.serviceOption(RunSessionTag);
2895
+ if (import_effect13.Option.isSome(sessionOpt)) {
2300
2896
  const seqKey = instanceId ?? "global";
2301
2897
  meta.opSeq = sessionOpt.value.local.nextSeq("opSeq", seqKey);
2302
2898
  }
@@ -2307,7 +2903,7 @@ var installSourceRefresh = (bound, step, entry) => {
2307
2903
  effect: loadEffect,
2308
2904
  meta
2309
2905
  });
2310
- const exit = yield* import_effect10.Effect.exit(run(op, stack));
2906
+ const exit = yield* import_effect13.Effect.exit(run(op, stack));
2311
2907
  if (exit._tag === "Success") {
2312
2908
  const successSnapshot = Snapshot.success({ keyHash: keyHash2, data: exit.value });
2313
2909
  const event = {
@@ -2363,46 +2959,46 @@ var installSourceRefresh = (bound, step, entry) => {
2363
2959
  yield* recordSnapshot(replayMode, replayLog, event);
2364
2960
  }
2365
2961
  }
2366
- }).pipe(import_effect10.Effect.catchAllCause(() => import_effect10.Effect.void));
2367
- const fiber = yield* import_effect10.Effect.forkScoped(import_effect10.Effect.locally(inSyncTransactionFiber, false)(io));
2962
+ }).pipe(import_effect13.Effect.catchAllCause(() => import_effect13.Effect.void));
2963
+ const fiber = yield* import_effect13.Effect.forkScoped(import_effect13.Effect.locally(inSyncTransactionFiber, false)(io));
2368
2964
  const myGen = gen += 1;
2369
2965
  inFlight = { gen: myGen, fiber, keyHash: keyHash2 };
2370
- yield* import_effect10.Effect.forkScoped(
2371
- import_effect10.Effect.locally(
2966
+ yield* import_effect13.Effect.forkScoped(
2967
+ import_effect13.Effect.locally(
2372
2968
  inSyncTransactionFiber,
2373
2969
  false
2374
2970
  )(
2375
- import_effect10.Fiber.await(fiber).pipe(
2376
- import_effect10.Effect.zipRight(
2377
- import_effect10.Effect.sync(() => {
2971
+ import_effect13.Fiber.await(fiber).pipe(
2972
+ import_effect13.Effect.zipRight(
2973
+ import_effect13.Effect.sync(() => {
2378
2974
  if (inFlight && inFlight.gen === myGen) {
2379
2975
  inFlight = void 0;
2380
2976
  }
2381
2977
  })
2382
2978
  ),
2383
- import_effect10.Effect.zipRight(
2384
- mode === "exhaust-trailing" ? import_effect10.Effect.gen(function* () {
2979
+ import_effect13.Effect.zipRight(
2980
+ mode === "exhaust-trailing" ? import_effect13.Effect.gen(function* () {
2385
2981
  const next = trailing;
2386
2982
  trailing = void 0;
2387
2983
  if (next) {
2388
2984
  yield* startFetch(next.key, next.keyHash, replayMode, replayLog);
2389
2985
  }
2390
- }) : import_effect10.Effect.void
2986
+ }) : import_effect13.Effect.void
2391
2987
  ),
2392
- import_effect10.Effect.catchAllCause(() => import_effect10.Effect.void)
2988
+ import_effect13.Effect.catchAllCause(() => import_effect13.Effect.void)
2393
2989
  )
2394
2990
  )
2395
2991
  );
2396
2992
  });
2397
2993
  register(
2398
2994
  fieldPath,
2399
- (state) => import_effect10.Effect.gen(function* () {
2995
+ (state) => import_effect13.Effect.gen(function* () {
2400
2996
  const { moduleId, instanceId } = getBoundScope(bound);
2401
- const replayModeOpt = yield* import_effect10.Effect.serviceOption(ReplayModeConfigTag);
2402
- const replayMode = import_effect10.Option.isSome(replayModeOpt) ? replayModeOpt.value.mode : "live";
2403
- const replayLogOpt = yield* import_effect10.Effect.serviceOption(ReplayLog);
2404
- const replayLog = import_effect10.Option.isSome(replayLogOpt) ? replayLogOpt.value : void 0;
2405
- const force = yield* import_effect10.FiberRef.get(forceSourceRefresh);
2997
+ const replayModeOpt = yield* import_effect13.Effect.serviceOption(ReplayModeConfigTag);
2998
+ const replayMode = import_effect13.Option.isSome(replayModeOpt) ? replayModeOpt.value.mode : "live";
2999
+ const replayLogOpt = yield* import_effect13.Effect.serviceOption(ReplayLog);
3000
+ const replayLog = import_effect13.Option.isSome(replayLogOpt) ? replayLogOpt.value : void 0;
3001
+ const force = yield* import_effect13.FiberRef.get(forceSourceRefresh);
2406
3002
  let key;
2407
3003
  try {
2408
3004
  key = entry.meta.key(state);
@@ -2428,7 +3024,7 @@ var installSourceRefresh = (bound, step, entry) => {
2428
3024
  }
2429
3025
  if (key === void 0) {
2430
3026
  if (inFlight) {
2431
- yield* import_effect10.Fiber.interruptFork(inFlight.fiber);
3027
+ yield* import_effect13.Fiber.interruptFork(inFlight.fiber);
2432
3028
  inFlight = void 0;
2433
3029
  }
2434
3030
  trailing = void 0;
@@ -2501,15 +3097,475 @@ var installSourceRefresh = (bound, step, entry) => {
2501
3097
  return;
2502
3098
  }
2503
3099
  if (mode === "switch" && inFlight) {
2504
- yield* import_effect10.Fiber.interruptFork(inFlight.fiber);
3100
+ yield* import_effect13.Fiber.interruptFork(inFlight.fiber);
2505
3101
  inFlight = void 0;
2506
3102
  trailing = void 0;
2507
3103
  }
2508
3104
  yield* startFetch(key, h, replayMode, replayLog);
2509
3105
  })
2510
3106
  );
2511
- return import_effect10.Effect.void;
3107
+ return import_effect13.Effect.void;
3108
+ };
3109
+
3110
+ // src/internal/state-trait/external-store.ts
3111
+ var import_effect14 = require("effect");
3112
+ var import_mutative2 = require("mutative");
3113
+
3114
+ // src/internal/external-store-descriptor.ts
3115
+ var EXTERNAL_STORE_DESCRIPTOR = /* @__PURE__ */ Symbol.for("@logixjs/core/externalStoreDescriptor");
3116
+ var getExternalStoreDescriptor = (store) => {
3117
+ if (!store || typeof store !== "object" && typeof store !== "function") return void 0;
3118
+ return store[EXTERNAL_STORE_DESCRIPTOR];
3119
+ };
3120
+
3121
+ // src/internal/state-trait/external-store.ts
3122
+ var isFn = (value) => typeof value === "function";
3123
+ var resolveStore = (entry) => import_effect14.Effect.gen(function* () {
3124
+ const store = entry.meta?.store;
3125
+ const descriptor = getExternalStoreDescriptor(store);
3126
+ if (descriptor?.kind === "service") {
3127
+ const service = yield* descriptor.tag;
3128
+ return descriptor.map(service);
3129
+ }
3130
+ return store;
3131
+ });
3132
+ var installExternalStoreSync = (bound, step, entry) => import_effect14.Effect.gen(function* () {
3133
+ const fieldPath = step.targetFieldPath;
3134
+ if (!fieldPath) return;
3135
+ const env = yield* import_effect14.Effect.context();
3136
+ const hostSchedulerOpt = yield* import_effect14.Effect.serviceOption(HostSchedulerTag);
3137
+ const hostScheduler = import_effect14.Option.isSome(hostSchedulerOpt) ? hostSchedulerOpt.value : getGlobalHostScheduler();
3138
+ const microtask = import_effect14.Effect.async((resume2) => {
3139
+ hostScheduler.scheduleMicrotask(() => resume2(import_effect14.Effect.void));
3140
+ });
3141
+ let internals;
3142
+ try {
3143
+ internals = getBoundInternals(bound);
3144
+ } catch {
3145
+ return;
3146
+ }
3147
+ const select = entry.meta?.select;
3148
+ const equals2 = entry.meta?.equals;
3149
+ const computeValue = (snapshot2) => isFn(select) ? select(snapshot2) : snapshot2;
3150
+ const isEqual = (a, b) => isFn(equals2) ? equals2(a, b) : Object.is(a, b);
3151
+ const traitLane = entry.meta?.priority;
3152
+ const rawStore = entry.meta?.store;
3153
+ const rawDescriptor = getExternalStoreDescriptor(rawStore);
3154
+ if (rawDescriptor?.kind === "module") {
3155
+ const linkRuntimeOpt = yield* import_effect14.Effect.serviceOption(DeclarativeLinkRuntimeTag);
3156
+ if (import_effect14.Option.isNone(linkRuntimeOpt)) {
3157
+ return yield* import_effect14.Effect.dieMessage("[StateTrait.externalStore] Missing DeclarativeLinkRuntime service (073).");
3158
+ }
3159
+ const module2 = rawDescriptor.module;
3160
+ const sourceRuntime = (() => {
3161
+ if (module2 && typeof module2 === "object") {
3162
+ const moduleId = module2.moduleId;
3163
+ const instanceId = module2.instanceId;
3164
+ const getState = module2.getState;
3165
+ if (typeof moduleId === "string" && moduleId.length > 0 && typeof instanceId === "string" && instanceId.length > 0 && getState) {
3166
+ return module2;
3167
+ }
3168
+ const tag = module2.tag;
3169
+ if (tag && import_effect14.Context.isTag(tag)) {
3170
+ return internals.imports.get(tag);
3171
+ }
3172
+ if (import_effect14.Context.isTag(module2)) {
3173
+ return internals.imports.get(module2);
3174
+ }
3175
+ }
3176
+ return void 0;
3177
+ })();
3178
+ if (!sourceRuntime) {
3179
+ return yield* import_effect14.Effect.dieMessage(
3180
+ `[StateTrait.externalStore] Module-as-Source store is unresolved for "${fieldPath}". Fix: include the source ModuleTag in module imports (moduleId=${rawDescriptor.moduleId}).`
3181
+ );
3182
+ }
3183
+ if (rawDescriptor.instanceId && rawDescriptor.instanceId !== sourceRuntime.instanceId) {
3184
+ return yield* import_effect14.Effect.dieMessage(
3185
+ `[StateTrait.externalStore] Module-as-Source instanceId mismatch for "${fieldPath}". descriptor.instanceId=${rawDescriptor.instanceId}, resolved.instanceId=${sourceRuntime.instanceId}`
3186
+ );
3187
+ }
3188
+ if (sourceRuntime.moduleId !== rawDescriptor.moduleId) {
3189
+ return yield* import_effect14.Effect.dieMessage(
3190
+ `[StateTrait.externalStore] Module-as-Source moduleId mismatch for "${fieldPath}". descriptor.moduleId=${rawDescriptor.moduleId}, resolved.moduleId=${sourceRuntime.moduleId}`
3191
+ );
3192
+ }
3193
+ const staticIr = rawDescriptor.readQuery.staticIr;
3194
+ const isRecognizableStatic = staticIr.lane === "static" && staticIr.readsDigest != null && staticIr.fallbackReason == null;
3195
+ if (!isRecognizableStatic) {
3196
+ yield* record({
3197
+ type: "diagnostic",
3198
+ moduleId: internals.moduleId,
3199
+ instanceId: internals.instanceId,
3200
+ code: "external_store::module_source_degraded",
3201
+ severity: "warning",
3202
+ message: "[StateTrait.externalStore] Module-as-Source selector is not fully IR-recognizable; falling back to module-topic edge (may reduce perf).",
3203
+ hint: "Fix: provide a static ReadQuery (ReadQuery.make) or annotate selector.fieldPaths to get a stable readsDigest; avoid dynamic lane.",
3204
+ kind: "module_as_source_degraded",
3205
+ trigger: {
3206
+ kind: "trait",
3207
+ name: "externalStore.moduleSource",
3208
+ details: {
3209
+ sourceModuleId: rawDescriptor.moduleId,
3210
+ selectorId: staticIr.selectorId,
3211
+ lane: staticIr.lane,
3212
+ fallbackReason: staticIr.fallbackReason,
3213
+ readsDigest: staticIr.readsDigest
3214
+ }
3215
+ }
3216
+ });
3217
+ }
3218
+ const moduleInstanceKey = `${sourceRuntime.moduleId}::${sourceRuntime.instanceId}`;
3219
+ const writeValue2 = (nextValue) => import_effect14.Effect.gen(function* () {
3220
+ const inTxn = yield* import_effect14.FiberRef.get(inSyncTransactionFiber);
3221
+ const body = import_effect14.Effect.gen(function* () {
3222
+ const prevState = yield* bound.state.read;
3223
+ const prevValue = getAtPath(prevState, fieldPath);
3224
+ if (isEqual(prevValue, nextValue)) {
3225
+ return;
3226
+ }
3227
+ const nextDraft = (0, import_mutative2.create)(prevState, (draft) => {
3228
+ setAtPathMutating(draft, fieldPath, nextValue);
3229
+ });
3230
+ const normalized = normalizeFieldPath(fieldPath) ?? [];
3231
+ internals.txn.recordStatePatch(normalized, "trait-external-store", prevValue, nextValue, step.id);
3232
+ internals.txn.updateDraft(nextDraft);
3233
+ });
3234
+ if (inTxn) {
3235
+ return yield* body;
3236
+ }
3237
+ const stateCommitPriority = traitLane === "nonUrgent" ? "low" : "normal";
3238
+ return yield* internals.txn.runWithStateTransaction(
3239
+ {
3240
+ kind: "trait-external-store",
3241
+ name: fieldPath,
3242
+ details: {
3243
+ stateCommit: {
3244
+ priority: stateCommitPriority
3245
+ }
3246
+ }
3247
+ },
3248
+ () => body.pipe(import_effect14.Effect.asVoid)
3249
+ );
3250
+ }).pipe(import_effect14.Effect.provide(env));
3251
+ const unregister = linkRuntimeOpt.value.registerModuleAsSourceLink({
3252
+ id: `${internals.instanceId}::externalStore:${step.id}`,
3253
+ sourceModuleInstanceKey: moduleInstanceKey,
3254
+ readQuery: rawDescriptor.readQuery,
3255
+ computeValue,
3256
+ equalsValue: isEqual,
3257
+ applyValue: writeValue2
3258
+ });
3259
+ yield* import_effect14.Effect.addFinalizer(
3260
+ () => import_effect14.Effect.sync(() => {
3261
+ unregister();
3262
+ })
3263
+ );
3264
+ const initialState = yield* sourceRuntime.getState;
3265
+ const initialSelected = rawDescriptor.readQuery.select(initialState);
3266
+ yield* writeValue2(computeValue(initialSelected));
3267
+ return;
3268
+ }
3269
+ const store = rawDescriptor?.kind === "service" ? yield* resolveStore(entry) : rawStore;
3270
+ if (!store || typeof store !== "object") {
3271
+ return yield* import_effect14.Effect.dieMessage(
3272
+ `[StateTrait.externalStore] Invalid store for "${fieldPath}". Expected { getSnapshot, subscribe }.`
3273
+ );
3274
+ }
3275
+ if (!isFn(store.getSnapshot) || !isFn(store.subscribe)) {
3276
+ return yield* import_effect14.Effect.dieMessage(
3277
+ `[StateTrait.externalStore] Invalid store for "${fieldPath}". Expected { getSnapshot, subscribe }.`
3278
+ );
3279
+ }
3280
+ let fused = false;
3281
+ let fuseCause;
3282
+ let fuseRecorded = false;
3283
+ let pending = false;
3284
+ let resume;
3285
+ const recordFuseDiagnostic = import_effect14.Effect.gen(function* () {
3286
+ if (fuseRecorded) return;
3287
+ fuseRecorded = true;
3288
+ const errorMessage = (() => {
3289
+ if (fuseCause instanceof Error) return fuseCause.message;
3290
+ if (typeof fuseCause === "string") return fuseCause;
3291
+ return "unknown";
3292
+ })();
3293
+ yield* record({
3294
+ type: "diagnostic",
3295
+ moduleId: internals.moduleId,
3296
+ instanceId: internals.instanceId,
3297
+ code: "external_store::snapshot_threw",
3298
+ severity: "warning",
3299
+ message: `[StateTrait.externalStore] store.getSnapshot() threw; trait is fused and will stop syncing for "${fieldPath}".`,
3300
+ hint: "Fix: ensure getSnapshot is synchronous and non-throwing; async resources should use StateTrait.source or ExternalStore.fromStream({ current/initial }).",
3301
+ kind: "external_store_fused:get_snapshot",
3302
+ trigger: {
3303
+ kind: "trait",
3304
+ name: "externalStore.getSnapshot",
3305
+ details: {
3306
+ fieldPath,
3307
+ traitId: step.id,
3308
+ storeKind: rawDescriptor?.kind ?? "raw",
3309
+ error: errorMessage
3310
+ }
3311
+ }
3312
+ });
3313
+ });
3314
+ const signal = () => {
3315
+ if (fused) return;
3316
+ if (resume) {
3317
+ const r = resume;
3318
+ pending = false;
3319
+ r();
3320
+ return;
3321
+ }
3322
+ pending = true;
3323
+ };
3324
+ const awaitSignal = () => {
3325
+ if (pending) {
3326
+ pending = false;
3327
+ return import_effect14.Effect.void;
3328
+ }
3329
+ return import_effect14.Effect.async((resumeEffect, signal2) => {
3330
+ let done = false;
3331
+ const r = () => {
3332
+ if (done) return;
3333
+ done = true;
3334
+ resume = void 0;
3335
+ resumeEffect(import_effect14.Effect.void);
3336
+ };
3337
+ resume = r;
3338
+ try {
3339
+ signal2.addEventListener(
3340
+ "abort",
3341
+ () => {
3342
+ if (resume === r) {
3343
+ resume = void 0;
3344
+ }
3345
+ },
3346
+ { once: true }
3347
+ );
3348
+ } catch {
3349
+ }
3350
+ });
3351
+ };
3352
+ const getSnapshotOrFuse = () => {
3353
+ try {
3354
+ return store.getSnapshot();
3355
+ } catch (err) {
3356
+ fused = true;
3357
+ fuseCause = err;
3358
+ return void 0;
3359
+ }
3360
+ };
3361
+ const readSnapshotOrFuse = import_effect14.Effect.locally(inSyncTransactionFiber, false)(import_effect14.Effect.sync(getSnapshotOrFuse));
3362
+ const before = yield* readSnapshotOrFuse;
3363
+ if (fused) {
3364
+ yield* recordFuseDiagnostic;
3365
+ return;
3366
+ }
3367
+ const unsubscribe = store.subscribe(signal);
3368
+ yield* import_effect14.Effect.addFinalizer(
3369
+ () => import_effect14.Effect.sync(() => {
3370
+ try {
3371
+ unsubscribe?.();
3372
+ } catch {
3373
+ }
3374
+ })
3375
+ );
3376
+ const after = yield* readSnapshotOrFuse;
3377
+ if (fused) {
3378
+ yield* recordFuseDiagnostic;
3379
+ return;
3380
+ }
3381
+ const writeValue = (nextValue) => import_effect14.Effect.gen(function* () {
3382
+ const inTxn = yield* import_effect14.FiberRef.get(inSyncTransactionFiber);
3383
+ const body = import_effect14.Effect.gen(function* () {
3384
+ const prevState = yield* bound.state.read;
3385
+ const prevValue = getAtPath(prevState, fieldPath);
3386
+ if (isEqual(prevValue, nextValue)) {
3387
+ return;
3388
+ }
3389
+ const nextDraft = (0, import_mutative2.create)(prevState, (draft) => {
3390
+ setAtPathMutating(draft, fieldPath, nextValue);
3391
+ });
3392
+ const normalized = normalizeFieldPath(fieldPath) ?? [];
3393
+ internals.txn.recordStatePatch(normalized, "trait-external-store", prevValue, nextValue, step.id);
3394
+ internals.txn.updateDraft(nextDraft);
3395
+ });
3396
+ if (inTxn) {
3397
+ return yield* body;
3398
+ }
3399
+ const stateCommitPriority = traitLane === "nonUrgent" ? "low" : "normal";
3400
+ return yield* internals.txn.runWithStateTransaction(
3401
+ {
3402
+ kind: "trait-external-store",
3403
+ name: fieldPath,
3404
+ details: {
3405
+ stateCommit: {
3406
+ priority: stateCommitPriority
3407
+ }
3408
+ }
3409
+ },
3410
+ () => body.pipe(import_effect14.Effect.asVoid)
3411
+ );
3412
+ });
3413
+ yield* writeValue(computeValue(after));
3414
+ if (!isEqual(before, after)) {
3415
+ signal();
3416
+ }
3417
+ yield* import_effect14.Effect.forkScoped(
3418
+ import_effect14.Effect.locally(inSyncTransactionFiber, false)(
3419
+ import_effect14.Effect.gen(function* () {
3420
+ while (true) {
3421
+ yield* awaitSignal();
3422
+ if (fused) return;
3423
+ yield* microtask;
3424
+ if (fused) return;
3425
+ const snapshot2 = yield* readSnapshotOrFuse;
3426
+ if (fused) {
3427
+ yield* recordFuseDiagnostic;
3428
+ return;
3429
+ }
3430
+ yield* writeValue(computeValue(snapshot2));
3431
+ }
3432
+ })
3433
+ )
3434
+ );
3435
+ });
3436
+
3437
+ // src/internal/state-trait/meta-diagnostics.ts
3438
+ var import_effect16 = require("effect");
3439
+
3440
+ // src/internal/state-trait/converge-diagnostics.ts
3441
+ var import_effect15 = require("effect");
3442
+ var SchemaAST2 = __toESM(require("effect/SchemaAST"), 1);
3443
+ var onceKeysFallback = /* @__PURE__ */ new Set();
3444
+ var onceInRunSession2 = (key) => import_effect15.Effect.serviceOption(RunSessionTag).pipe(
3445
+ import_effect15.Effect.map((maybe) => {
3446
+ if (import_effect15.Option.isSome(maybe)) {
3447
+ return maybe.value.local.once(key);
3448
+ }
3449
+ if (onceKeysFallback.has(key)) return false;
3450
+ onceKeysFallback.add(key);
3451
+ return true;
3452
+ })
3453
+ );
3454
+
3455
+ // src/internal/state-trait/meta-diagnostics.ts
3456
+ var formatList2 = (items, limit = 6) => {
3457
+ if (!items || items.length === 0) return void 0;
3458
+ if (items.length <= limit) return items.join(", ");
3459
+ return `${items.slice(0, limit).join(", ")}, \u2026(+${items.length - limit})`;
3460
+ };
3461
+ var formatPart = (label, value) => {
3462
+ if (value === void 0) return void 0;
3463
+ return `${label}=${value}`;
3464
+ };
3465
+ var formatIssue = (issue) => {
3466
+ const r = issue.report;
3467
+ const parts = [];
3468
+ if (r.invalidInput) parts.push("invalidInput=true");
3469
+ const unknownKeys = formatList2(r.unknownKeys, 6);
3470
+ if (unknownKeys) {
3471
+ parts.push(
3472
+ `unknownKeys=[${unknownKeys}]${typeof r.unknownKeyCount === "number" && r.unknownKeyCount > r.unknownKeys.length ? ` total=${r.unknownKeyCount}` : ""}`
3473
+ );
3474
+ }
3475
+ const droppedKeys = formatList2(r.droppedKeys, 6);
3476
+ if (droppedKeys) parts.push(`droppedKeys=[${droppedKeys}]`);
3477
+ if (typeof r.droppedTagItems === "number" && r.droppedTagItems > 0) {
3478
+ parts.push(`droppedTagItems=${r.droppedTagItems}`);
3479
+ }
3480
+ const ignoredAnnotationKeys = formatList2(r.ignoredAnnotationKeys, 6);
3481
+ if (ignoredAnnotationKeys) {
3482
+ parts.push(
3483
+ `ignoredAnnotationKeys=[${ignoredAnnotationKeys}]${typeof r.ignoredAnnotationKeyCount === "number" && r.ignoredAnnotationKeyCount > r.ignoredAnnotationKeys.length ? ` total=${r.ignoredAnnotationKeyCount}` : ""}`
3484
+ );
3485
+ }
3486
+ const droppedAnnotationKeys = formatList2(r.droppedAnnotationKeys, 6);
3487
+ if (droppedAnnotationKeys) {
3488
+ parts.push(
3489
+ `droppedAnnotationKeys=[${droppedAnnotationKeys}]${typeof r.droppedAnnotationKeyCount === "number" && r.droppedAnnotationKeyCount > r.droppedAnnotationKeys.length ? ` total=${r.droppedAnnotationKeyCount}` : ""}`
3490
+ );
3491
+ }
3492
+ const droppedValues = formatPart("droppedAnnotationValues", r.droppedAnnotationValues);
3493
+ if (droppedValues) parts.push(droppedValues);
3494
+ const nonSerializable = formatPart("nonSerializable", r.droppedAnnotationNonSerializable);
3495
+ const depthExceeded = formatPart("depthExceeded", r.droppedAnnotationDepthExceeded);
3496
+ const nonFiniteNumber = formatPart("nonFiniteNumber", r.droppedAnnotationNonFiniteNumber);
3497
+ const reasons = [nonSerializable, depthExceeded, nonFiniteNumber].filter((x) => x !== void 0);
3498
+ if (reasons.length > 0) parts.push(`reasons={${reasons.join(", ")}}`);
3499
+ return `[${issue.origin}] ${parts.join(" ")}`;
3500
+ };
3501
+ var collectNodeMetaIssues = (program) => {
3502
+ const spec = program.spec;
3503
+ if (!spec || typeof spec !== "object") return [];
3504
+ const isNode = (value) => typeof value === "object" && value !== null && value._tag === "StateTraitNode";
3505
+ const isList = (value) => typeof value === "object" && value !== null && value._tag === "StateTraitList";
3506
+ const issues = [];
3507
+ const add = (origin, meta) => {
3508
+ const { report } = sanitizeWithReport(meta);
3509
+ if (report) issues.push({ origin, report });
3510
+ };
3511
+ for (const key of Object.keys(spec)) {
3512
+ const raw = spec[key];
3513
+ if (!raw) continue;
3514
+ if (isList(raw)) {
3515
+ if (raw.item && isNode(raw.item) && raw.item.meta !== void 0) {
3516
+ add(`node:${key}[]`, raw.item.meta);
3517
+ }
3518
+ if (raw.list && isNode(raw.list) && raw.list.meta !== void 0) {
3519
+ add(`node:${key}`, raw.list.meta);
3520
+ }
3521
+ continue;
3522
+ }
3523
+ if (isNode(raw)) {
3524
+ if (raw.meta === void 0) continue;
3525
+ add(`node:${key === "$root" ? "$root" : key}`, raw.meta);
3526
+ continue;
3527
+ }
3528
+ }
3529
+ return issues;
2512
3530
  };
3531
+ var collectEntryMetaIssues = (program) => {
3532
+ const issues = [];
3533
+ for (const entry of program.entries) {
3534
+ if (entry.kind !== "source" && entry.kind !== "externalStore") continue;
3535
+ const rawMeta = entry.meta?.meta;
3536
+ if (rawMeta === void 0) continue;
3537
+ const origin = entry.kind === "source" ? `source:${entry.fieldPath}` : `externalStore:${entry.fieldPath}`;
3538
+ const { report } = sanitizeWithReport(rawMeta);
3539
+ if (report) issues.push({ origin, report });
3540
+ }
3541
+ return issues;
3542
+ };
3543
+ var emitMetaSanitizeDiagnostics = (program, ctx) => import_effect16.Effect.gen(function* () {
3544
+ if (!isDevEnv()) return;
3545
+ const level = yield* import_effect16.FiberRef.get(currentDiagnosticsLevel);
3546
+ if (level === "off") return;
3547
+ const moduleId = ctx.moduleId ?? "unknown";
3548
+ const shouldEmit = yield* onceInRunSession2(`meta_sanitize:${moduleId}`);
3549
+ if (!shouldEmit) return;
3550
+ const issues = [...collectNodeMetaIssues(program), ...collectEntryMetaIssues(program)];
3551
+ if (issues.length === 0) return;
3552
+ const limit = level === "light" || level === "sampled" ? 8 : 24;
3553
+ const lines = issues.slice(0, limit).map(formatIssue);
3554
+ if (issues.length > limit) {
3555
+ lines.push(`\u2026(+${issues.length - limit})`);
3556
+ }
3557
+ yield* record({
3558
+ type: "diagnostic",
3559
+ moduleId: ctx.moduleId,
3560
+ instanceId: ctx.instanceId,
3561
+ code: "state_trait::meta_sanitized",
3562
+ severity: "warning",
3563
+ message: `[meta] TraitMeta contains non-exportable fields/values and will be sanitized (total ${issues.length}):
3564
+ ${lines.join("\n")}`,
3565
+ hint: "TraitMeta is export-only (Devtools/Static IR) and MUST be JsonValue. Use `annotations` with `x-*` keys for extension hints; avoid closures/functions/Effect/Fiber/Tag/DOM/BigInt/circular refs. See specs/016 and docs/ssot/platform/contracts/03-control-surface-manifest.md.",
3566
+ kind: "meta_sanitized"
3567
+ });
3568
+ });
2513
3569
 
2514
3570
  // src/internal/state-trait/install.ts
2515
3571
  var buildEntryIndex = (entries) => {
@@ -2522,32 +3578,41 @@ var buildEntryIndex = (entries) => {
2522
3578
  return index;
2523
3579
  };
2524
3580
  var install = (bound, program) => {
2525
- try {
2526
- const internals = getBoundInternals(bound);
2527
- internals.traits.registerStateTraitProgram(program, {
2528
- bumpReason: "logic_installed"
2529
- });
2530
- } catch {
2531
- }
2532
- const entryIndex = buildEntryIndex(program.entries);
2533
- const installStep = (step) => {
2534
- if (!step.targetFieldPath) {
2535
- return import_effect11.Effect.void;
2536
- }
2537
- if (step.kind !== "source-refresh") {
2538
- return import_effect11.Effect.void;
2539
- }
2540
- const candidates = entryIndex.get(step.targetFieldPath);
2541
- if (!candidates || candidates.length === 0) {
2542
- return import_effect11.Effect.void;
3581
+ return import_effect17.Effect.gen(function* () {
3582
+ let internals;
3583
+ try {
3584
+ internals = getBoundInternals(bound);
3585
+ internals.traits.registerStateTraitProgram(program, {
3586
+ bumpReason: "logic_installed"
3587
+ });
3588
+ } catch {
2543
3589
  }
2544
- const entry = candidates.find((e) => e.kind === "source");
2545
- if (!entry) {
2546
- return import_effect11.Effect.void;
3590
+ if (internals) {
3591
+ yield* emitMetaSanitizeDiagnostics(program, {
3592
+ moduleId: internals.moduleId,
3593
+ instanceId: internals.instanceId
3594
+ });
2547
3595
  }
2548
- return installSourceRefresh(bound, step, entry);
2549
- };
2550
- return import_effect11.Effect.forEach(program.plan.steps, (step) => installStep(step)).pipe(import_effect11.Effect.asVoid);
3596
+ const entryIndex = buildEntryIndex(program.entries);
3597
+ const installStep = (step) => {
3598
+ if (!step.targetFieldPath) {
3599
+ return import_effect17.Effect.void;
3600
+ }
3601
+ if (step.kind !== "source-refresh" && step.kind !== "external-store-sync") {
3602
+ return import_effect17.Effect.void;
3603
+ }
3604
+ const candidates = entryIndex.get(step.targetFieldPath);
3605
+ if (!candidates || candidates.length === 0) {
3606
+ return import_effect17.Effect.void;
3607
+ }
3608
+ const entry = step.kind === "source-refresh" ? candidates.find((e) => e.kind === "source") : candidates.find((e) => e.kind === "externalStore");
3609
+ if (!entry) {
3610
+ return import_effect17.Effect.void;
3611
+ }
3612
+ return step.kind === "source-refresh" ? installSourceRefresh(bound, step, entry) : installExternalStoreSync(bound, step, entry);
3613
+ };
3614
+ yield* import_effect17.Effect.forEach(program.plan.steps, (step) => installStep(step)).pipe(import_effect17.Effect.asVoid);
3615
+ }).pipe(import_effect17.Effect.asVoid);
2551
3616
  };
2552
3617
 
2553
3618
  // src/internal/state-trait/ir.ts
@@ -2569,6 +3634,8 @@ var toNodeKind = (step) => {
2569
3634
  return "link";
2570
3635
  case "source-refresh":
2571
3636
  return "source";
3637
+ case "external-store-sync":
3638
+ return "externalStore";
2572
3639
  case "check-validate":
2573
3640
  return "check";
2574
3641
  }
@@ -2593,6 +3660,9 @@ var getReadsForEntry = (entry) => {
2593
3660
  const from2 = entry.meta.from;
2594
3661
  return from2 ? [from2] : [];
2595
3662
  }
3663
+ if (entry.kind === "externalStore") {
3664
+ return [];
3665
+ }
2596
3666
  if (entry.kind === "check") {
2597
3667
  const rules = entry.meta?.rules ?? {};
2598
3668
  const out = [];
@@ -2640,11 +3710,40 @@ var exportStaticIr = (params) => {
2640
3710
  const write = normalizeFieldPath2(target);
2641
3711
  const writes = write ? [write] : [];
2642
3712
  const meta = target ? metaByField.get(target) : void 0;
3713
+ const externalStorePolicy = () => {
3714
+ if (kind !== "externalStore") return void 0;
3715
+ if (!entry || entry.kind !== "externalStore") return void 0;
3716
+ const descriptor = getExternalStoreDescriptor(entry.meta.store);
3717
+ const storeId = descriptor?.storeId;
3718
+ const priorityRaw = entry.meta?.priority;
3719
+ const lane = priorityRaw === "nonUrgent" ? "nonUrgent" : "urgent";
3720
+ const meta2 = sanitize(entry.meta.meta);
3721
+ const source2 = descriptor?.kind === "module" ? {
3722
+ kind: "module",
3723
+ storeId,
3724
+ moduleId: descriptor.moduleId,
3725
+ ...descriptor.instanceId ? { instanceKey: descriptor.instanceId } : {},
3726
+ selectorId: descriptor.readQuery.staticIr.selectorId,
3727
+ readsDigest: descriptor.readQuery.staticIr.readsDigest,
3728
+ fallbackReason: descriptor.readQuery.staticIr.fallbackReason
3729
+ } : descriptor ? { kind: "external", storeId } : { kind: "external", storeId: "unknown" };
3730
+ const coalesceWindowMs = entry.meta?.coalesceWindowMs;
3731
+ return {
3732
+ traitId: step.id,
3733
+ storeId: storeId ?? "unknown",
3734
+ source: source2,
3735
+ ownership: "external-owned",
3736
+ lane,
3737
+ ...typeof coalesceWindowMs === "number" && Number.isFinite(coalesceWindowMs) && coalesceWindowMs > 0 ? { coalesceWindowMs } : {},
3738
+ ...meta2 ? { meta: meta2 } : {}
3739
+ };
3740
+ };
2643
3741
  const base2 = {
2644
3742
  nodeId: step.id,
2645
3743
  kind,
2646
3744
  reads,
2647
3745
  writes: kind === "check" ? [] : writes,
3746
+ ...kind === "externalStore" ? { policy: externalStorePolicy() } : {},
2648
3747
  meta
2649
3748
  };
2650
3749
  if (kind !== "check" && target && !write) {
@@ -2709,6 +3808,11 @@ var source = (input) => {
2709
3808
  meta: { ...input, key }
2710
3809
  };
2711
3810
  };
3811
+ var externalStore = (input) => ({
3812
+ fieldPath: void 0,
3813
+ kind: "externalStore",
3814
+ meta: input
3815
+ });
2712
3816
  var link = (meta) => ({
2713
3817
  fieldPath: void 0,
2714
3818
  kind: "link",
@@ -2727,6 +3831,7 @@ var exportStaticIr2 = (program, moduleId, options) => exportStaticIr({
2727
3831
  build,
2728
3832
  computed,
2729
3833
  exportStaticIr,
3834
+ externalStore,
2730
3835
  from,
2731
3836
  install,
2732
3837
  link,