@ersbeth/picoflow 1.1.1 → 2.0.0

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 (383) hide show
  1. package/.vscode/settings.json +3 -3
  2. package/CHANGELOG.md +43 -0
  3. package/README.md +2 -18
  4. package/biome.json +45 -35
  5. package/dist/picoflow.js +857 -1528
  6. package/dist/types/api/base/flowDisposable.d.ts +41 -0
  7. package/dist/types/api/base/flowDisposable.d.ts.map +1 -0
  8. package/dist/types/api/base/flowObservable.d.ts +27 -0
  9. package/dist/types/api/base/flowObservable.d.ts.map +1 -0
  10. package/dist/types/api/base/flowSubscribable.d.ts +79 -0
  11. package/dist/types/api/base/flowSubscribable.d.ts.map +1 -0
  12. package/dist/types/api/base/flowTracker.d.ts +8 -0
  13. package/dist/types/api/base/flowTracker.d.ts.map +1 -0
  14. package/dist/types/api/base/index.d.ts +5 -0
  15. package/dist/types/api/base/index.d.ts.map +1 -0
  16. package/dist/types/api/index.d.ts +3 -0
  17. package/dist/types/api/index.d.ts.map +1 -0
  18. package/dist/types/api/nodes/async/flowConstantAsync.d.ts +31 -0
  19. package/dist/types/api/nodes/async/flowConstantAsync.d.ts.map +1 -0
  20. package/dist/types/api/nodes/async/flowDerivationAsync.d.ts +37 -0
  21. package/dist/types/api/nodes/async/flowDerivationAsync.d.ts.map +1 -0
  22. package/dist/types/api/nodes/async/flowStateAsync.d.ts +41 -0
  23. package/dist/types/api/nodes/async/flowStateAsync.d.ts.map +1 -0
  24. package/dist/types/api/nodes/async/flowWritableDerivationAsync.d.ts +30 -0
  25. package/dist/types/api/nodes/async/flowWritableDerivationAsync.d.ts.map +1 -0
  26. package/dist/types/{flow → api}/nodes/async/index.d.ts +1 -2
  27. package/dist/types/api/nodes/async/index.d.ts.map +1 -0
  28. package/dist/types/api/nodes/collections/flowArray.d.ts +134 -0
  29. package/dist/types/api/nodes/collections/flowArray.d.ts.map +1 -0
  30. package/dist/types/api/nodes/collections/flowMap.d.ts +98 -0
  31. package/dist/types/api/nodes/collections/flowMap.d.ts.map +1 -0
  32. package/dist/types/api/nodes/collections/index.d.ts.map +1 -0
  33. package/dist/types/api/nodes/flowEffect.d.ts +28 -0
  34. package/dist/types/api/nodes/flowEffect.d.ts.map +1 -0
  35. package/dist/types/api/nodes/flowSignal.d.ts +25 -0
  36. package/dist/types/api/nodes/flowSignal.d.ts.map +1 -0
  37. package/dist/types/api/nodes/flowValue.d.ts +35 -0
  38. package/dist/types/api/nodes/flowValue.d.ts.map +1 -0
  39. package/dist/types/api/nodes/index.d.ts +8 -0
  40. package/dist/types/api/nodes/index.d.ts.map +1 -0
  41. package/dist/types/api/nodes/sync/flowConstant.d.ts +29 -0
  42. package/dist/types/api/nodes/sync/flowConstant.d.ts.map +1 -0
  43. package/dist/types/api/nodes/sync/flowDerivation.d.ts +36 -0
  44. package/dist/types/api/nodes/sync/flowDerivation.d.ts.map +1 -0
  45. package/dist/types/api/nodes/sync/flowState.d.ts +39 -0
  46. package/dist/types/api/nodes/sync/flowState.d.ts.map +1 -0
  47. package/dist/types/api/nodes/sync/flowWritableDerivation.d.ts +28 -0
  48. package/dist/types/api/nodes/sync/flowWritableDerivation.d.ts.map +1 -0
  49. package/dist/types/{flow → api}/nodes/sync/index.d.ts +1 -2
  50. package/dist/types/api/nodes/sync/index.d.ts.map +1 -0
  51. package/dist/types/api/nodes/utils.d.ts +22 -0
  52. package/dist/types/api/nodes/utils.d.ts.map +1 -0
  53. package/dist/types/base/disposable.d.ts +11 -0
  54. package/dist/types/base/disposable.d.ts.map +1 -0
  55. package/dist/types/base/executionStack.d.ts +14 -0
  56. package/dist/types/base/executionStack.d.ts.map +1 -0
  57. package/dist/types/base/index.d.ts +6 -0
  58. package/dist/types/base/index.d.ts.map +1 -0
  59. package/dist/types/base/node.d.ts +27 -0
  60. package/dist/types/base/node.d.ts.map +1 -0
  61. package/dist/types/base/observable.d.ts +37 -0
  62. package/dist/types/base/observable.d.ts.map +1 -0
  63. package/dist/types/base/observer.d.ts +25 -0
  64. package/dist/types/base/observer.d.ts.map +1 -0
  65. package/dist/types/converters/index.d.ts +2 -0
  66. package/dist/types/converters/index.d.ts.map +1 -0
  67. package/dist/types/converters/solid.d.ts +46 -0
  68. package/dist/types/converters/solid.d.ts.map +1 -0
  69. package/dist/types/index.d.ts +2 -63
  70. package/dist/types/index.d.ts.map +1 -1
  71. package/dist/types/nodes/arrayNode.d.ts +2 -0
  72. package/dist/types/nodes/arrayNode.d.ts.map +1 -0
  73. package/dist/types/nodes/effectNode.d.ts +2 -0
  74. package/dist/types/nodes/effectNode.d.ts.map +1 -0
  75. package/dist/types/nodes/index.d.ts +9 -0
  76. package/dist/types/nodes/index.d.ts.map +1 -0
  77. package/dist/types/nodes/mapNode.d.ts +2 -0
  78. package/dist/types/nodes/mapNode.d.ts.map +1 -0
  79. package/dist/types/nodes/signalNode.d.ts +2 -0
  80. package/dist/types/nodes/signalNode.d.ts.map +1 -0
  81. package/dist/types/nodes/valueAsyncNode.d.ts +2 -0
  82. package/dist/types/nodes/valueAsyncNode.d.ts.map +1 -0
  83. package/dist/types/nodes/valueNode.d.ts +2 -0
  84. package/dist/types/nodes/valueNode.d.ts.map +1 -0
  85. package/dist/types/nodes/valueSyncNode.d.ts +2 -0
  86. package/dist/types/nodes/valueSyncNode.d.ts.map +1 -0
  87. package/dist/types/schedulers/asyncResolver.d.ts +2 -0
  88. package/dist/types/schedulers/asyncResolver.d.ts.map +1 -0
  89. package/dist/types/schedulers/asyncScheduler.d.ts +2 -0
  90. package/dist/types/schedulers/asyncScheduler.d.ts.map +1 -0
  91. package/dist/types/schedulers/index.d.ts +5 -0
  92. package/dist/types/schedulers/index.d.ts.map +1 -0
  93. package/dist/types/schedulers/pendingError.d.ts +2 -0
  94. package/dist/types/schedulers/pendingError.d.ts.map +1 -0
  95. package/dist/types/schedulers/scheduler.d.ts +2 -0
  96. package/dist/types/schedulers/scheduler.d.ts.map +1 -0
  97. package/dist/types/schedulers/syncResolver.d.ts +2 -0
  98. package/dist/types/schedulers/syncResolver.d.ts.map +1 -0
  99. package/dist/types/schedulers/syncScheduler.d.ts +2 -0
  100. package/dist/types/schedulers/syncScheduler.d.ts.map +1 -0
  101. package/docs/.vitepress/config.mts +128 -93
  102. package/docs/api/functions/array.md +14 -37
  103. package/docs/api/functions/constant.md +13 -25
  104. package/docs/api/functions/constantAsync.md +69 -0
  105. package/docs/api/functions/derivation.md +14 -33
  106. package/docs/api/functions/derivationAsync.md +34 -0
  107. package/docs/api/functions/from.md +62 -153
  108. package/docs/api/functions/isDisposable.md +8 -30
  109. package/docs/api/functions/map.md +15 -36
  110. package/docs/api/functions/signal.md +8 -23
  111. package/docs/api/functions/state.md +43 -23
  112. package/docs/api/functions/stateAsync.md +69 -0
  113. package/docs/api/functions/subscribe.md +40 -0
  114. package/docs/api/functions/writableDerivation.md +33 -0
  115. package/docs/api/functions/writableDerivationAsync.md +34 -0
  116. package/docs/api/index.md +45 -102
  117. package/docs/api/interfaces/FlowArray.md +439 -0
  118. package/docs/api/interfaces/FlowConstant.md +220 -0
  119. package/docs/api/interfaces/FlowConstantAsync.md +221 -0
  120. package/docs/api/interfaces/FlowDerivation.md +241 -0
  121. package/docs/api/interfaces/FlowDerivationAsync.md +242 -0
  122. package/docs/api/interfaces/FlowDisposable.md +32 -38
  123. package/docs/api/interfaces/FlowEffect.md +64 -0
  124. package/docs/api/interfaces/FlowMap.md +374 -0
  125. package/docs/api/interfaces/FlowObservable.md +155 -0
  126. package/docs/api/interfaces/FlowSignal.md +156 -0
  127. package/docs/api/interfaces/FlowState.md +269 -0
  128. package/docs/api/interfaces/FlowStateAsync.md +268 -0
  129. package/docs/api/interfaces/FlowSubscribable.md +55 -0
  130. package/docs/api/interfaces/FlowTracker.md +61 -0
  131. package/docs/api/interfaces/FlowValue.md +222 -0
  132. package/docs/api/interfaces/FlowWritableDerivation.md +292 -0
  133. package/docs/api/interfaces/FlowWritableDerivationAsync.md +293 -0
  134. package/docs/api/type-aliases/DerivationFunction.md +28 -0
  135. package/docs/api/type-aliases/DerivationFunctionAsync.md +28 -0
  136. package/docs/api/type-aliases/FlowArrayAction.md +19 -8
  137. package/docs/api/type-aliases/FlowDataTracker.md +33 -0
  138. package/docs/api/type-aliases/FlowMapAction.md +48 -0
  139. package/docs/api/type-aliases/FlowOnDataListener.md +33 -0
  140. package/docs/api/type-aliases/FlowOnErrorListener.md +27 -0
  141. package/docs/api/type-aliases/FlowOnPendingListener.md +21 -0
  142. package/docs/api/type-aliases/FlowReadonly.md +22 -0
  143. package/docs/api/type-aliases/InitFunction.md +21 -0
  144. package/docs/api/type-aliases/InitFunctionAsync.md +21 -0
  145. package/docs/api/type-aliases/NotPromise.md +6 -3
  146. package/docs/api/type-aliases/UpdateFunction.md +27 -0
  147. package/docs/api/type-aliases/UpdateFunctionAsync.md +27 -0
  148. package/docs/api/typedoc-sidebar.json +1 -81
  149. package/docs/examples/examples.md +0 -2
  150. package/docs/guide/advanced/architecture.md +1234 -0
  151. package/docs/guide/advanced/migration-v2.md +204 -0
  152. package/docs/guide/advanced/solidjs.md +2 -88
  153. package/docs/guide/introduction/concepts.md +4 -3
  154. package/docs/guide/introduction/conventions.md +2 -33
  155. package/docs/guide/introduction/getting-started.md +28 -23
  156. package/docs/guide/introduction/lifecycle.md +16 -19
  157. package/docs/guide/primitives/array.md +102 -216
  158. package/docs/guide/primitives/constant.md +39 -212
  159. package/docs/guide/primitives/derivations.md +55 -122
  160. package/docs/guide/primitives/effects.md +155 -241
  161. package/docs/guide/primitives/map.md +64 -186
  162. package/docs/guide/primitives/overview.md +45 -128
  163. package/docs/guide/primitives/signal.md +51 -88
  164. package/docs/guide/primitives/state.md +34 -130
  165. package/package.json +56 -60
  166. package/src/api/base/flowDisposable.ts +44 -0
  167. package/src/api/base/flowObservable.ts +28 -0
  168. package/src/api/base/flowSubscribable.ts +87 -0
  169. package/src/api/base/flowTracker.ts +7 -0
  170. package/src/api/base/index.ts +4 -0
  171. package/src/{flow → api}/index.ts +0 -1
  172. package/src/api/nodes/async/flowConstantAsync.ts +36 -0
  173. package/src/api/nodes/async/flowDerivationAsync.ts +42 -0
  174. package/src/api/nodes/async/flowStateAsync.ts +47 -0
  175. package/src/api/nodes/async/flowWritableDerivationAsync.ts +33 -0
  176. package/src/{flow → api}/nodes/async/index.ts +1 -2
  177. package/src/api/nodes/collections/flowArray.ts +155 -0
  178. package/src/api/nodes/collections/flowMap.ts +115 -0
  179. package/src/api/nodes/flowEffect.ts +42 -0
  180. package/src/api/nodes/flowSignal.ts +28 -0
  181. package/src/api/nodes/flowValue.ts +36 -0
  182. package/src/api/nodes/index.ts +7 -0
  183. package/src/api/nodes/sync/flowConstant.ts +33 -0
  184. package/src/api/nodes/sync/flowDerivation.ts +41 -0
  185. package/src/api/nodes/sync/flowState.ts +45 -0
  186. package/src/api/nodes/sync/flowWritableDerivation.ts +31 -0
  187. package/src/{flow → api}/nodes/sync/index.ts +1 -2
  188. package/src/api/nodes/utils.ts +22 -0
  189. package/src/base/disposable.ts +18 -0
  190. package/src/base/executionStack.ts +42 -0
  191. package/src/base/index.ts +5 -0
  192. package/src/base/node.ts +98 -0
  193. package/src/base/observable.ts +87 -0
  194. package/src/base/observer.ts +51 -0
  195. package/src/converters/index.ts +1 -0
  196. package/src/converters/solid.ts +109 -0
  197. package/src/index.ts +2 -64
  198. package/src/nodes/arrayNode.ts +172 -0
  199. package/src/nodes/effectNode.ts +59 -0
  200. package/src/nodes/index.ts +8 -0
  201. package/src/nodes/mapNode.ts +127 -0
  202. package/src/nodes/signalNode.ts +21 -0
  203. package/src/nodes/valueAsyncNode.ts +88 -0
  204. package/src/nodes/valueNode.ts +144 -0
  205. package/src/nodes/valueSyncNode.ts +128 -0
  206. package/src/schedulers/asyncResolver.ts +78 -0
  207. package/src/schedulers/asyncScheduler.ts +66 -0
  208. package/src/schedulers/index.ts +4 -0
  209. package/src/schedulers/pendingError.ts +13 -0
  210. package/src/schedulers/scheduler.ts +9 -0
  211. package/src/schedulers/syncResolver.ts +69 -0
  212. package/src/schedulers/syncScheduler.ts +55 -0
  213. package/test/base/pendingError.test.ts +67 -0
  214. package/test/converters/solid.derivation.browser.test.tsx +69 -0
  215. package/test/converters/solid.node.test.ts +654 -0
  216. package/test/converters/solid.state.browser.test.tsx +1592 -0
  217. package/test/reactivity/flowSignal.test.ts +226 -0
  218. package/test/reactivity/nodes/async/asyncScheduler/asyncResolver.test.ts +593 -0
  219. package/test/reactivity/nodes/async/asyncScheduler/asyncScheduler.test.ts +317 -0
  220. package/test/reactivity/nodes/async/flowConstantAsync.test.ts +652 -0
  221. package/test/reactivity/nodes/async/flowDerivation.test.ts +898 -0
  222. package/test/reactivity/nodes/async/flowDerivationAsync.test.ts +1716 -0
  223. package/test/reactivity/nodes/async/flowStateAsync.test.ts +708 -0
  224. package/test/reactivity/nodes/async/flowWritableDerivationAsync.test.ts +614 -0
  225. package/test/reactivity/nodes/collections/flowArray.asyncStates.test.ts +1289 -0
  226. package/test/reactivity/nodes/collections/flowArray.scalars.test.ts +961 -0
  227. package/test/reactivity/nodes/collections/flowArray.states.test.ts +1035 -0
  228. package/test/reactivity/nodes/collections/flowMap.asyncStates.test.ts +960 -0
  229. package/test/reactivity/nodes/collections/flowMap.scalars.test.ts +775 -0
  230. package/test/reactivity/nodes/collections/flowMap.states.test.ts +958 -0
  231. package/test/reactivity/nodes/sync/flowConstant.test.ts +377 -0
  232. package/test/reactivity/nodes/sync/flowDerivation.test.ts +896 -0
  233. package/test/reactivity/nodes/sync/flowState.test.ts +341 -0
  234. package/test/reactivity/nodes/sync/flowWritableDerivation.test.ts +603 -0
  235. package/test/vitest.d.ts +10 -0
  236. package/tsconfig.json +31 -20
  237. package/typedoc.json +35 -35
  238. package/vite.config.ts +25 -23
  239. package/vitest.browser.config.ts +21 -0
  240. package/vitest.config.ts +12 -12
  241. package/.cursor/plans/unifier-flowresource-avec-flowderivation-c9506e24.plan.md +0 -372
  242. package/.cursor/plans/update-js-e795d61b.plan.md +0 -567
  243. package/dist/types/flow/base/flowDisposable.d.ts +0 -67
  244. package/dist/types/flow/base/flowDisposable.d.ts.map +0 -1
  245. package/dist/types/flow/base/flowEffect.d.ts +0 -127
  246. package/dist/types/flow/base/flowEffect.d.ts.map +0 -1
  247. package/dist/types/flow/base/flowGraph.d.ts +0 -97
  248. package/dist/types/flow/base/flowGraph.d.ts.map +0 -1
  249. package/dist/types/flow/base/flowSignal.d.ts +0 -134
  250. package/dist/types/flow/base/flowSignal.d.ts.map +0 -1
  251. package/dist/types/flow/base/flowTracker.d.ts +0 -15
  252. package/dist/types/flow/base/flowTracker.d.ts.map +0 -1
  253. package/dist/types/flow/base/index.d.ts +0 -7
  254. package/dist/types/flow/base/index.d.ts.map +0 -1
  255. package/dist/types/flow/base/utils.d.ts +0 -20
  256. package/dist/types/flow/base/utils.d.ts.map +0 -1
  257. package/dist/types/flow/collections/flowArray.d.ts +0 -148
  258. package/dist/types/flow/collections/flowArray.d.ts.map +0 -1
  259. package/dist/types/flow/collections/flowMap.d.ts +0 -224
  260. package/dist/types/flow/collections/flowMap.d.ts.map +0 -1
  261. package/dist/types/flow/collections/index.d.ts.map +0 -1
  262. package/dist/types/flow/index.d.ts +0 -4
  263. package/dist/types/flow/index.d.ts.map +0 -1
  264. package/dist/types/flow/nodes/async/flowConstantAsync.d.ts +0 -137
  265. package/dist/types/flow/nodes/async/flowConstantAsync.d.ts.map +0 -1
  266. package/dist/types/flow/nodes/async/flowDerivationAsync.d.ts +0 -137
  267. package/dist/types/flow/nodes/async/flowDerivationAsync.d.ts.map +0 -1
  268. package/dist/types/flow/nodes/async/flowNodeAsync.d.ts +0 -343
  269. package/dist/types/flow/nodes/async/flowNodeAsync.d.ts.map +0 -1
  270. package/dist/types/flow/nodes/async/flowReadonlyAsync.d.ts +0 -81
  271. package/dist/types/flow/nodes/async/flowReadonlyAsync.d.ts.map +0 -1
  272. package/dist/types/flow/nodes/async/flowStateAsync.d.ts +0 -111
  273. package/dist/types/flow/nodes/async/flowStateAsync.d.ts.map +0 -1
  274. package/dist/types/flow/nodes/async/index.d.ts.map +0 -1
  275. package/dist/types/flow/nodes/index.d.ts +0 -3
  276. package/dist/types/flow/nodes/index.d.ts.map +0 -1
  277. package/dist/types/flow/nodes/sync/flowConstant.d.ts +0 -108
  278. package/dist/types/flow/nodes/sync/flowConstant.d.ts.map +0 -1
  279. package/dist/types/flow/nodes/sync/flowDerivation.d.ts +0 -100
  280. package/dist/types/flow/nodes/sync/flowDerivation.d.ts.map +0 -1
  281. package/dist/types/flow/nodes/sync/flowNode.d.ts +0 -314
  282. package/dist/types/flow/nodes/sync/flowNode.d.ts.map +0 -1
  283. package/dist/types/flow/nodes/sync/flowReadonly.d.ts +0 -57
  284. package/dist/types/flow/nodes/sync/flowReadonly.d.ts.map +0 -1
  285. package/dist/types/flow/nodes/sync/flowState.d.ts +0 -96
  286. package/dist/types/flow/nodes/sync/flowState.d.ts.map +0 -1
  287. package/dist/types/flow/nodes/sync/index.d.ts.map +0 -1
  288. package/dist/types/solid/converters.d.ts +0 -53
  289. package/dist/types/solid/converters.d.ts.map +0 -1
  290. package/dist/types/solid/index.d.ts +0 -3
  291. package/dist/types/solid/index.d.ts.map +0 -1
  292. package/dist/types/solid/primitives.d.ts +0 -181
  293. package/dist/types/solid/primitives.d.ts.map +0 -1
  294. package/docs/api/classes/FlowArray.md +0 -489
  295. package/docs/api/classes/FlowConstant.md +0 -350
  296. package/docs/api/classes/FlowDerivation.md +0 -334
  297. package/docs/api/classes/FlowEffect.md +0 -100
  298. package/docs/api/classes/FlowMap.md +0 -512
  299. package/docs/api/classes/FlowObservable.md +0 -306
  300. package/docs/api/classes/FlowResource.md +0 -380
  301. package/docs/api/classes/FlowResourceAsync.md +0 -362
  302. package/docs/api/classes/FlowSignal.md +0 -160
  303. package/docs/api/classes/FlowState.md +0 -368
  304. package/docs/api/classes/FlowStream.md +0 -367
  305. package/docs/api/classes/FlowStreamAsync.md +0 -364
  306. package/docs/api/classes/SolidDerivation.md +0 -75
  307. package/docs/api/classes/SolidResource.md +0 -91
  308. package/docs/api/classes/SolidState.md +0 -71
  309. package/docs/api/classes/TrackingContext.md +0 -33
  310. package/docs/api/functions/effect.md +0 -49
  311. package/docs/api/functions/resource.md +0 -52
  312. package/docs/api/functions/resourceAsync.md +0 -50
  313. package/docs/api/functions/stream.md +0 -53
  314. package/docs/api/functions/streamAsync.md +0 -50
  315. package/docs/api/interfaces/SolidObservable.md +0 -19
  316. package/docs/api/type-aliases/FlowStreamDisposer.md +0 -15
  317. package/docs/api/type-aliases/FlowStreamSetter.md +0 -27
  318. package/docs/api/type-aliases/FlowStreamUpdater.md +0 -32
  319. package/docs/api/type-aliases/SolidGetter.md +0 -17
  320. package/docs/guide/primitives/resources.md +0 -858
  321. package/docs/guide/primitives/streams.md +0 -931
  322. package/src/flow/base/flowDisposable.ts +0 -71
  323. package/src/flow/base/flowEffect.ts +0 -171
  324. package/src/flow/base/flowGraph.ts +0 -288
  325. package/src/flow/base/flowSignal.ts +0 -207
  326. package/src/flow/base/flowTracker.ts +0 -17
  327. package/src/flow/base/index.ts +0 -6
  328. package/src/flow/base/utils.ts +0 -19
  329. package/src/flow/collections/flowArray.ts +0 -409
  330. package/src/flow/collections/flowMap.ts +0 -398
  331. package/src/flow/nodes/async/flowConstantAsync.ts +0 -142
  332. package/src/flow/nodes/async/flowDerivationAsync.ts +0 -143
  333. package/src/flow/nodes/async/flowNodeAsync.ts +0 -474
  334. package/src/flow/nodes/async/flowReadonlyAsync.ts +0 -81
  335. package/src/flow/nodes/async/flowStateAsync.ts +0 -116
  336. package/src/flow/nodes/await/advanced/index.ts +0 -5
  337. package/src/flow/nodes/await/advanced/resource.ts +0 -134
  338. package/src/flow/nodes/await/advanced/resourceAsync.ts +0 -109
  339. package/src/flow/nodes/await/advanced/stream.ts +0 -188
  340. package/src/flow/nodes/await/advanced/streamAsync.ts +0 -176
  341. package/src/flow/nodes/await/flowConstantAwait.ts +0 -154
  342. package/src/flow/nodes/await/flowDerivationAwait.ts +0 -154
  343. package/src/flow/nodes/await/flowNodeAwait.ts +0 -508
  344. package/src/flow/nodes/await/flowReadonlyAwait.ts +0 -89
  345. package/src/flow/nodes/await/flowStateAwait.ts +0 -130
  346. package/src/flow/nodes/await/index.ts +0 -5
  347. package/src/flow/nodes/index.ts +0 -3
  348. package/src/flow/nodes/sync/flowConstant.ts +0 -111
  349. package/src/flow/nodes/sync/flowDerivation.ts +0 -105
  350. package/src/flow/nodes/sync/flowNode.ts +0 -439
  351. package/src/flow/nodes/sync/flowReadonly.ts +0 -57
  352. package/src/flow/nodes/sync/flowState.ts +0 -101
  353. package/src/solid/converters.ts +0 -139
  354. package/src/solid/index.ts +0 -2
  355. package/src/solid/primitives.ts +0 -215
  356. package/test/base/flowEffect.test.ts +0 -108
  357. package/test/base/flowGraph.test.ts +0 -485
  358. package/test/base/flowSignal.test.ts +0 -372
  359. package/test/collections/flowArray.asyncStates.test.ts +0 -1553
  360. package/test/collections/flowArray.scalars.test.ts +0 -1129
  361. package/test/collections/flowArray.states.test.ts +0 -1365
  362. package/test/collections/flowMap.asyncStates.test.ts +0 -1105
  363. package/test/collections/flowMap.scalars.test.ts +0 -877
  364. package/test/collections/flowMap.states.test.ts +0 -1097
  365. package/test/nodes/async/flowConstantAsync.test.ts +0 -860
  366. package/test/nodes/async/flowDerivationAsync.test.ts +0 -1517
  367. package/test/nodes/async/flowStateAsync.test.ts +0 -1387
  368. package/test/nodes/await/advanced/resource.test.ts +0 -129
  369. package/test/nodes/await/advanced/resourceAsync.test.ts +0 -108
  370. package/test/nodes/await/advanced/stream.test.ts +0 -198
  371. package/test/nodes/await/advanced/streamAsync.test.ts +0 -196
  372. package/test/nodes/await/flowConstantAwait.test.ts +0 -643
  373. package/test/nodes/await/flowDerivationAwait.test.ts +0 -1583
  374. package/test/nodes/await/flowStateAwait.test.ts +0 -999
  375. package/test/nodes/mixed/derivation.test.ts +0 -1527
  376. package/test/nodes/sync/flowConstant.test.ts +0 -620
  377. package/test/nodes/sync/flowDerivation.test.ts +0 -1373
  378. package/test/nodes/sync/flowState.test.ts +0 -945
  379. package/test/solid/converters.test.ts +0 -721
  380. package/test/solid/primitives.test.ts +0 -1031
  381. /package/dist/types/{flow → api/nodes}/collections/index.d.ts +0 -0
  382. /package/docs/guide/advanced/{upgrading.md → migration-v1.md} +0 -0
  383. /package/src/{flow → api/nodes}/collections/index.ts +0 -0
@@ -1,124 +1,76 @@
1
- # Effects
1
+ # Side Effects & Subscribe
2
2
 
3
- Effects are how you perform **side effects** in response to reactive changes. They're the bridge between your reactive data and the outside world - updating the DOM, making API calls, saving to localStorage, and more.
3
+ Side effects are how you perform **actions** in response to reactive changes. They're the bridge between your reactive data and the outside world - updating the DOM, making API calls, saving to localStorage, and more.
4
4
 
5
- Imagine a light switch: when you flip it, the light turns on. Effects work the same way in reactive programming - when your data changes, effects automatically run to update the world around them.
5
+ Side effects are created by subscribing to reactive primitives using `subscribe()` or `.subscribe()`. When you subscribe, you get a `FlowEffect` object that can be disposed to stop the side effect.
6
6
 
7
7
  ### Key Characteristics
8
8
 
9
+ - **Two syntaxes**: `.subscribe()` for single primitive, `subscribe()` for multiple
9
10
  - **Immediate execution**: Runs synchronously when created
10
11
  - **Automatic re-execution**: Re-runs when dependencies change
11
12
  - **Dynamic dependency tracking**: Dependencies adapt at runtime
12
- - **Side effects allowed**: Designed for DOM, API, logging, etc.
13
- - **Disposal support**: Clean up resources when no longer needed
13
+ - **Returns FlowEffect**: Disposable handle to stop the subscription
14
14
 
15
- ## When to Use Effects
15
+ ## When to Use Subscribe
16
16
 
17
- Use effects when you need to:
17
+ Use subscribe when you need to:
18
18
 
19
19
  - ✅ Perform side effects (DOM updates, API calls, localStorage)
20
20
  - ✅ React to changes in reactive values
21
21
  - ✅ Coordinate with external systems
22
- - ✅ Set up subscriptions or event listeners
23
22
  - ✅ Log or debug reactive changes
24
23
 
25
- Don't use effects when:
24
+ Don't use subscribe when:
26
25
 
27
26
  - ❌ Computing derived values (use derivations instead)
28
- - ❌ The value needs to be used elsewhere reactively (use derivations)
29
27
  - ❌ You only need to run code once (use regular functions)
30
28
 
31
- ## Creating Effects
29
+ ## Creating Side Effects
32
30
 
33
- Creating an effect is straightforward:
31
+ There are two ways to create side effects, depending on your needs:
34
32
 
35
- ```typescript
36
- import { effect } from '@ersbeth/picoflow'
37
-
38
- effect((t) => {
39
- // Your side effect code here
40
- // Use t to track dependencies
41
- })
42
- ```
43
-
44
- The parameter `t` is the **TrackingContext** - your tool for creating dependencies.
33
+ ### Single Primitive - `.subscribe()`
45
34
 
46
- ## Using Effects
47
-
48
- Effects have several ways to interact with reactive values and manage their lifecycle.
49
-
50
- ### Tracking with `.get(t)` (Reactive)
51
-
52
- Use `.get(t)` to create dependencies - the effect will re-run when the value changes:
35
+ When reacting to a single primitive, use the `.subscribe()` method:
53
36
 
54
37
  ```typescript
55
- const $username = state('Alice')
56
-
57
- effect((t) => {
58
- const name = $username.get(t) // Creates dependency
59
- document.getElementById('username').textContent = name
60
- })
61
-
62
- $username.set('Bob') // Effect re-runs, DOM updates
63
- ```
64
-
65
- ### Non-Reactive Reads with `.pick()`
66
-
67
- Use `.pick()` to read the current value without creating a dependency:
38
+ import { state } from '@ersbeth/picoflow'
68
39
 
69
- ```typescript
70
- const $activeUserId = state(1)
71
- const $userDatabase = state({ /* large object */ })
40
+ const $count = state(0)
72
41
 
73
- effect((t) => {
74
- const activeId = $activeUserId.get(t) // Reactive
75
- const database = $userDatabase.pick() // Snapshot
76
-
77
- const user = database[activeId]
78
- console.log('Active user:', user)
42
+ // Subscribe directly to the primitive
43
+ const effect = $count.subscribe((value) => {
44
+ console.log('Count is:', value)
79
45
  })
80
46
 
81
- // Only changes to $activeUserId trigger the effect
82
- // Changes to $userDatabase are ignored
47
+ // Later: dispose the effect
48
+ effect.dispose()
83
49
  ```
84
50
 
85
- ### Watching Signals with `.watch(t)`
51
+ ### Multiple Primitives - `subscribe()`
86
52
 
87
- Signals are special - they don't hold values, so use `.watch(t)` to track them:
53
+ When combining multiple primitives, use the global `subscribe()` function:
88
54
 
89
55
  ```typescript
90
- import { signal, effect } from '@ersbeth/picoflow'
56
+ import { state, subscribe } from '@ersbeth/picoflow'
91
57
 
92
- const $refresh = signal()
93
-
94
- effect((t) => {
95
- $refresh.watch(t) // React to signal triggers
96
- console.log('Refreshing data...')
97
- fetchData()
98
- })
99
-
100
- $refresh.trigger() // Effect runs
101
- ```
102
-
103
- ### Multiple Dependencies
104
-
105
- Effects can track multiple reactive values:
106
-
107
- ```typescript
108
58
  const $firstName = state('Alice')
109
59
  const $lastName = state('Smith')
110
60
 
111
- effect((t) => {
112
- const first = $firstName.get(t)
113
- const last = $lastName.get(t)
114
- console.log('Full name:', first, last)
115
- })
116
-
117
- // Changes to EITHER trigger the effect
118
- $firstName.set('Bob') // Effect runs
119
- $lastName.set('Jones') // Effect runs
61
+ // Combine multiple values
62
+ const effect = subscribe(
63
+ (t) => ({ first: $firstName.get(t), last: $lastName.get(t) }),
64
+ (data) => {
65
+ console.log('Full name:', data.first, data.last)
66
+ }
67
+ )
120
68
  ```
121
69
 
70
+ The parameter `t` is the **FlowTracker** - your tool for creating dependencies.
71
+
72
+ ## Using Side-Effects
73
+
122
74
  ### Conditional Dependencies
123
75
 
124
76
  Dependencies can be conditional - they're re-evaluated on each execution:
@@ -127,43 +79,51 @@ Dependencies can be conditional - they're re-evaluated on each execution:
127
79
  const $showDetails = state(false)
128
80
  const $details = state({ info: 'secret' })
129
81
 
130
- effect((t) => {
131
- if ($showDetails.get(t)) {
132
- // Only depends on $details when $showDetails is true
133
- console.log('Details:', $details.get(t))
134
- } else {
135
- console.log('Details hidden')
82
+ subscribe(
83
+ (t) => {
84
+ const show = $showDetails.get(t)
85
+ if (show) {
86
+ return { show: true, details: $details.get(t) }
87
+ }
88
+ return { show: false, details: null }
89
+ },
90
+ (data) => {
91
+ if (data.show) {
92
+ console.log('Details:', data.details)
93
+ } else {
94
+ console.log('Details hidden')
95
+ }
136
96
  }
137
- })
97
+ )
138
98
 
139
- // When $showDetails is false, changes to $details don't trigger the effect
140
- $details.set({ info: 'new secret' }) // Effect doesn't run
99
+ // When $showDetails is false, changes to $details don't trigger the subscription
100
+ $details.set({ info: 'new secret' }) // Subscription doesn't run
141
101
 
142
102
  // But once $showDetails is true...
143
- $showDetails.set(true) // Effect runs and now tracks $details
144
- $details.set({ info: 'updated' }) // Now this triggers the effect!
103
+ $showDetails.set(true) // Subscription runs and now tracks $details
104
+ $details.set({ info: 'updated' }) // Now this triggers the subscription!
145
105
  ```
146
106
 
147
- ### Disposing with `.dispose()`
107
+ ### Dispose
148
108
 
149
- Effects run indefinitely unless disposed. Always clean them up when no longer needed:
109
+ Subscriptions run indefinitely unless disposed. Always clean them up when no longer needed:
150
110
 
151
111
  ```typescript
152
112
  const $count = state(0)
153
113
 
154
- // Create effect
155
- const fx = effect((t) => {
156
- console.log($count.get(t))
114
+ // Create subscription
115
+ const effect = $count.subscribe((value) => {
116
+ console.log(value)
157
117
  })
158
118
 
159
- // Later... stop the effect
160
- fx.dispose()
119
+ // Later... stop the subscription
120
+ effect.dispose()
161
121
 
162
- // After disposal, the effect won't run anymore
122
+ // After disposal, the subscription won't run anymore
163
123
  $count.set(10) // No console log
164
124
  ```
165
125
 
166
- **Always dispose effects when:**
126
+ **Always dispose subscriptions when:**
167
127
  - Component unmounts (in UI frameworks)
168
128
  - Feature is disabled
169
129
  - User navigates away
@@ -176,25 +136,25 @@ $count.set(10) // No console log
176
136
  function createUserPanel(userId: number) {
177
137
  const $user = state(getUserData(userId))
178
138
 
179
- effect((t) => {
180
- updateUI($user.get(t))
139
+ $user.subscribe((user) => {
140
+ updateUI(user)
181
141
  })
182
- // Effect never disposed! ⚠️
142
+ // Subscription never disposed! ⚠️
183
143
  }
184
144
 
185
- // Called 100 times = 100 effects still running!
145
+ // Called 100 times = 100 subscriptions still running!
186
146
 
187
147
  // ✅ Proper cleanup
188
148
  function createUserPanel(userId: number) {
189
149
  const $user = state(getUserData(userId))
190
150
 
191
- const fx = effect((t) => {
192
- updateUI($user.get(t))
151
+ const effect = $user.subscribe((user) => {
152
+ updateUI(user)
193
153
  })
194
154
 
195
155
  return {
196
156
  dispose: () => {
197
- fx.dispose()
157
+ effect.dispose()
198
158
  $user.dispose()
199
159
  }
200
160
  }
@@ -203,129 +163,140 @@ function createUserPanel(userId: number) {
203
163
 
204
164
  ## Lifecycle
205
165
 
206
- Effects execute immediately when created, track their dependencies, and re-execute when any dependency changes. Understanding this lifecycle is key to writing efficient reactive code.
166
+ Subscriptions execute immediately when created, track their dependencies, and re-execute when any dependency changes. Understanding this lifecycle is key to writing efficient reactive code.
207
167
 
208
- When you create an effect, it runs **synchronously** - not on the next tick, but right away. This allows effects to establish initial dependencies and set up initial side effects. When a dependency changes, the effect re-executes synchronously.
168
+ When you create a subscription, it runs **synchronously** - not on the next tick, but right away. This allows subscriptions to establish initial dependencies and perform initial side effects. When a dependency changes, the subscription re-executes synchronously.
209
169
 
210
170
  ```mermaid
211
171
  sequenceDiagram
212
172
  participant User
213
173
  participant $count as $count (State)
214
- participant Effect
174
+ participant Subscription
215
175
 
216
- Note over User,Effect: 1. Creation Phase
217
- User->>Effect: Create effect((t) => ...)
218
- activate Effect
219
- Note over Effect: Execute immediately
176
+ Note over User,Subscription: 1. Creation Phase
177
+ User->>Subscription: "Create $count.subscribe(...)"
178
+ activate Subscription
179
+ Note over Subscription: Execute immediately
220
180
 
221
- Effect->>$count: get(t)
181
+ Subscription->>$count: Read value
222
182
  activate $count
223
- Note over $count: Register Effect as dependent
224
- $count-->>Effect: 0
183
+ Note over $count: Register Subscription as dependent
184
+ $count-->>Subscription: 0
225
185
  deactivate $count
226
186
 
227
- Note over Effect: console.log("Count: 0")
228
- Note over Effect: Track: depends on $count
229
- deactivate Effect
187
+ Note over Subscription: "console.log(\"Count: 0\")"
188
+ Note over Subscription: Track: depends on $count
189
+ deactivate Subscription
230
190
 
231
- Note over User,Effect: 2. Change Phase
191
+ Note over User,Subscription: 2. Change Phase
232
192
  User->>$count: set(5)
233
193
  activate $count
234
194
  Note over $count: Value changed: 0 → 5
235
195
 
236
- $count->>Effect: Notify & schedule
196
+ $count->>Subscription: Notify & schedule
237
197
  deactivate $count
238
198
 
239
- activate Effect
240
- Note over Effect: Clear old dependencies<br/>Execute function
199
+ activate Subscription
200
+ Note over Subscription: Clear old dependencies<br/>Execute callback
241
201
 
242
- Effect->>$count: get(t)
202
+ Subscription->>$count: Read value
243
203
  activate $count
244
- Note over $count: Register Effect as dependent
245
- $count-->>Effect: 5
204
+ Note over $count: Register Subscription as dependent
205
+ $count-->>Subscription: 5
246
206
  deactivate $count
247
207
 
248
- Note over Effect: console.log("Count: 5")
249
- Note over Effect: Track: depends on $count
250
- deactivate Effect
208
+ Note over Subscription: "console.log(\"Count: 5\")"
209
+ Note over Subscription: Track: depends on $count
210
+ deactivate Subscription
251
211
 
252
- Note over User,Effect: 3. Disposal Phase
253
- User->>Effect: dispose()
254
- activate Effect
255
- Note over Effect: Clear dependencies<br/>Unregister from $count
256
- Note over Effect: Mark as disposed
257
- deactivate Effect
212
+ Note over User,Subscription: 3. Disposal Phase
213
+ User->>Subscription: dispose()
214
+ activate Subscription
215
+ Note over Subscription: Clear dependencies<br/>Unregister from $count
216
+ Note over Subscription: Mark as disposed
217
+ deactivate Subscription
258
218
 
259
219
  User->>$count: set(10)
260
220
  activate $count
261
221
  Note over $count: Value changed<br/>No dependents to notify
262
222
  deactivate $count
263
- Note over Effect: (Does not run - disposed)
223
+ Note over Subscription: (Does not run - disposed)
264
224
  ```
265
225
 
266
226
  ### Key Lifecycle Points
267
227
 
268
- 1. **Creation & Immediate Execution**: The effect function runs synchronously during creation
269
- 2. **Dependency Registration**: Reactive reads (`.get(t)`) register the effect as a dependent
270
- 3. **Change Notification**: When dependencies change, the effect is scheduled to re-run
271
- 4. **Re-execution**: Effect clears old dependencies, runs again, re-registers new dependencies
228
+ 1. **Creation & Immediate Execution**: The subscription callback runs synchronously during creation
229
+ 2. **Dependency Registration**: Reactive reads register the subscription as a dependent
230
+ 3. **Change Notification**: When dependencies change, the subscription is scheduled to re-run
231
+ 4. **Re-execution**: Subscription clears old dependencies, runs again, re-registers new dependencies
272
232
  5. **Disposal**: Clears all dependencies, unregisters from all reactive values, prevents future execution
273
233
 
274
234
  This immediate, synchronous execution model means:
275
- - **Effects establish dependencies on first run** (no waiting)
235
+ - **Subscriptions establish dependencies on first run** (no waiting)
276
236
  - **Changes trigger re-execution immediately** (synchronous)
277
237
  - **Dynamic dependencies adapt automatically** (conditional tracking)
278
238
 
279
239
  ## Best Practices
280
240
 
281
- ### Keep Effects Focused
241
+ ### Keep Subscriptions Focused
282
242
 
283
- Each effect should do one thing:
243
+ Each subscription should do one thing:
284
244
 
285
245
  ```typescript
286
246
  // ❌ Doing too much
287
- effect((t) => {
288
- updateDOM($count.get(t))
289
- saveToStorage($count.get(t))
290
- sendAnalytics($count.get(t))
291
- updateTitle($count.get(t))
247
+ $count.subscribe((value) => {
248
+ updateDOM(value)
249
+ saveToStorage(value)
250
+ sendAnalytics(value)
251
+ updateTitle(value)
292
252
  })
293
253
 
294
254
  // ✅ Separate concerns
295
- effect((t) => updateDOM($count.get(t)))
296
- effect((t) => saveToStorage($count.get(t)))
297
- effect((t) => sendAnalytics($count.get(t)))
298
- effect((t) => updateTitle($count.get(t)))
255
+ $count.subscribe((value) => updateDOM(value))
256
+ $count.subscribe((value) => saveToStorage(value))
257
+ $count.subscribe((value) => sendAnalytics(value))
258
+ $count.subscribe((value) => updateTitle(value))
299
259
  ```
300
260
 
301
- **Why?** Easier to debug, test, and disable individual effects.
261
+ **Why?** Easier to debug, test, and disable individual subscriptions.
302
262
 
303
- ### Avoid Creating Effects Inside Effects
263
+ ### Avoid Creating Subscriptions Inside Subscriptions
304
264
 
305
265
  ```typescript
306
- // ❌ Bad - creates new effects on every run
307
- effect((t) => {
308
- const count = $count.get(t)
309
- effect((t) => {
310
- console.log('Nested:', count) // Memory leak!
266
+ // ❌ Bad - creates new subscriptions on every run
267
+ $count.subscribe((count) => {
268
+ $other.subscribe((other) => {
269
+ console.log('Nested:', count, other) // Memory leak!
311
270
  })
312
271
  })
313
272
 
314
- // ✅ Good - create effects at the top level
315
- effect((t) => {
316
- const count = $count.get(t)
317
- console.log('Count:', count)
318
- })
273
+ // ✅ Good - create subscriptions at the top level
274
+ subscribe(
275
+ (t) => ({ count: $count.get(t), other: $other.get(t) }),
276
+ (data) => {
277
+ console.log('Values:', data.count, data.other)
278
+ }
279
+ )
319
280
  ```
320
281
 
321
282
  ### Handle Errors
322
283
 
323
- Wrap risky operations in try-catch:
284
+ Use the `onError` callback or wrap risky operations in try-catch:
324
285
 
325
286
  ```typescript
326
- effect((t) => {
327
- const data = $data.get(t)
328
-
287
+ // Using onError callback
288
+ subscribe(
289
+ (t) => $data.get(t),
290
+ (data) => {
291
+ updateDOM(data)
292
+ },
293
+ (error) => {
294
+ console.error('Failed to update DOM:', error)
295
+ }
296
+ )
297
+
298
+ // ✅ Or use try-catch
299
+ $data.subscribe((data) => {
329
300
  try {
330
301
  updateDOM(data)
331
302
  } catch (error) {
@@ -336,20 +307,18 @@ effect((t) => {
336
307
 
337
308
  ### Be Careful with Infinite Loops
338
309
 
339
- Don't update dependencies inside the same effect:
310
+ Don't update dependencies inside the same subscription:
340
311
 
341
312
  ```typescript
342
313
  const $count = state(0)
343
314
 
344
315
  // ❌ Infinite loop!
345
- effect((t) => {
346
- const count = $count.get(t)
316
+ $count.subscribe((count) => {
347
317
  $count.set(count + 1) // Triggers itself!
348
318
  })
349
319
 
350
320
  // ✅ Use a different state
351
- effect((t) => {
352
- const count = $count.get(t)
321
+ $count.subscribe((count) => {
353
322
  $doubled.set(count * 2) // Updates different state
354
323
  })
355
324
  ```
@@ -361,8 +330,7 @@ When you don't need a value, just an event:
361
330
  ```typescript
362
331
  const $refresh = signal()
363
332
 
364
- effect((t) => {
365
- $refresh.watch(t) // Track signal without reading a value
333
+ $refresh.subscribe(() => {
366
334
  fetchData()
367
335
  })
368
336
 
@@ -372,87 +340,33 @@ $refresh.trigger()
372
340
 
373
341
  ## Common Pitfalls
374
342
 
375
- ### Forgetting to Use `.get(t)`
376
-
377
- **Problem**: Using `.pick()` instead of `.get(t)` breaks reactivity.
378
-
379
- ```typescript
380
- // ❌ No dependency created - effect runs only once
381
- effect((t) => {
382
- console.log($count.pick()) // Using .pick() instead of .get(t)
383
- })
343
+ ### Not Disposing Subscriptions
384
344
 
385
- $count.set(10) // Effect won't run
386
- ```
387
-
388
- **Solution**: Always use `.get(t)` to create dependencies:
389
-
390
- ```typescript
391
- // ✅ Correct
392
- effect((t) => {
393
- console.log($count.get(t))
394
- })
395
-
396
- $count.set(10) // Effect runs
397
- ```
398
-
399
- ### Not Disposing Effects
400
-
401
- **Problem**: Effects continue running even when no longer needed.
345
+ **Problem**: Subscriptions continue running even when no longer needed.
402
346
 
403
347
  ```typescript
404
348
  // ❌ Memory leak in component lifecycle
405
349
  function MyComponent() {
406
- effect((t) => {
407
- updateView($data.get(t))
350
+ $data.subscribe((data) => {
351
+ updateView(data)
408
352
  })
409
353
  // Never disposed!
410
354
  }
411
355
 
412
- // Each component creation adds another effect that never stops
356
+ // Each component creation adds another subscription that never stops
413
357
  ```
414
358
 
415
- **Solution**: Always dispose effects when done:
359
+ **Solution**: Always dispose subscriptions when done:
416
360
 
417
361
  ```typescript
418
362
  // ✅ Proper cleanup
419
363
  function MyComponent() {
420
- const fx = effect((t) => {
421
- updateView($data.get(t))
364
+ const effect = $data.subscribe((data) => {
365
+ updateView(data)
422
366
  })
423
367
 
424
368
  return {
425
- cleanup: () => fx.dispose()
369
+ cleanup: () => effect.dispose()
426
370
  }
427
371
  }
428
- ```
429
-
430
- ### Async Operations Without Care
431
-
432
- **Problem**: Race conditions when using async operations in effects.
433
-
434
- ```typescript
435
- // ⚠️ Race condition possible
436
- effect(async (t) => {
437
- const id = $userId.get(t)
438
- const data = await fetchUser(id) // If $userId changes during fetch...
439
- displayUser(data) // ...we might display wrong user!
440
- })
441
- ```
442
-
443
- **Solution**: Check if values are still relevant after async operations:
444
-
445
- ```typescript
446
- // ✅ Better - check if still relevant
447
- effect(async (t) => {
448
- const id = $userId.get(t)
449
- const data = await fetchUser(id)
450
-
451
- // Verify ID didn't change during fetch
452
- if ($userId.pick() === id) {
453
- displayUser(data)
454
- }
455
- })
456
- ```
457
-
458
- **Why this matters**: Between starting an async operation and its completion, your reactive values might change. Always verify the context is still valid before applying results.
372
+ ```