@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,50 +1,38 @@
1
1
  # Constants
2
2
 
3
- A **constant** is a reactive primitive that holds an immutable value. Unlike state, constants cannot be updated after initialization - they exist to provide stable, reactive references to values that don't change.
3
+ A **constant** is a reactive primitive that holds an immutable value computed lazily on first access. Constants integrate immutable values into the reactive system, allowing them to be tracked as dependencies while ensuring they never change.
4
4
 
5
- Imagine a configuration file in your application. It's loaded once at startup and never changes, but many parts of your app need to read it. That's what constants do in PicoFlow.
6
-
7
- ### Key Characteristics
8
-
9
- - **Immutable**: No `.set()` method - value never changes
10
- - **Reactive**: Can be tracked with `.get(t)` just like state
11
- - **Lazy evaluation**: Optional - compute value on first access
12
- - **Cached forever**: Once computed, the value is permanently stored
5
+ The key benefit of constants is **lazy initialization** - the value isn't computed until it's first accessed, making them perfect for expensive one-time computations like parsing configuration files or building lookup tables.
13
6
 
14
7
  ## When to Use Constants
15
8
 
16
9
  Use constants when you need to:
17
10
 
18
- - ✅ Store configuration values that don't change
19
11
  - ✅ Cache expensive computations that only run once
20
- - ✅ Create reactive feature flags
21
- - ✅ Provide stable reactive references to initialization values
22
12
 
23
13
  Don't use constants when:
24
14
 
25
15
  - ❌ The value needs to change (use state instead)
26
- - ❌ You need a `.set()` method
27
16
  - ❌ The value isn't reactive (use plain `const` instead)
28
17
 
29
18
  ## Creating Constants
30
19
 
31
- Creating a constant is simple:
20
+ Constants always take a function that returns the value. This function is called lazily on first access:
32
21
 
33
22
  ```typescript
34
23
  import { constant } from '@ersbeth/picoflow'
35
24
 
36
- // Direct value - initialized immediately
37
- const $apiUrl = constant('https://api.example.com')
38
- const $config = constant({ apiUrl: 'https://api.example.com', timeout: 5000 })
39
- const $version = constant('1.0.0')
25
+ // Function is required - value computed on first access
26
+ const $apiUrl = constant(() => 'https://api.example.com')
27
+ const $config = constant(() => ({ apiUrl: 'https://api.example.com', timeout: 5000 }))
28
+ const $version = constant(() => '1.0.0')
40
29
  ```
41
30
 
42
- ### Lazy Initialization
31
+ ### Expensive Computations
43
32
 
44
- Pass a function to defer computation until first access:
33
+ The lazy initialization makes constants perfect for expensive one-time computations:
45
34
 
46
35
  ```typescript
47
- // Lazy initialization - computed on first access
48
36
  const $expensiveValue = constant(() => {
49
37
  console.log('Computing expensive value...')
50
38
  return performExpensiveCalculation()
@@ -52,8 +40,7 @@ const $expensiveValue = constant(() => {
52
40
 
53
41
  // Nothing logged yet - function not called
54
42
 
55
- effect((t) => {
56
- const value = $expensiveValue.get(t)
43
+ $expensiveValue.subscribe((value) => {
57
44
  // NOW it logs: "Computing expensive value..."
58
45
  console.log(value)
59
46
  })
@@ -65,92 +52,51 @@ effect((t) => {
65
52
 
66
53
  Constants provide two ways to read values:
67
54
 
68
- ### Reading with `.get(t)`
55
+ ### Get
69
56
 
70
- Inside an effect or derivation, use `.get(t)` to read the value and create a dependency:
57
+ Inside a subscription or derivation, use `.get(t)` to read the value and create a dependency:
71
58
 
72
59
  ```typescript
73
- import { constant, effect } from '@ersbeth/picoflow'
60
+ import { constant } from '@ersbeth/picoflow'
74
61
 
75
- const $config = constant({ apiUrl: 'https://api.example.com' })
62
+ const $config = constant(() => ({ apiUrl: 'https://api.example.com' }))
63
+ const $merged = derivation((t) => ({url: $config.get(t).apiUrl, data: someOtherData}))
76
64
 
77
- effect((t) => {
78
- const config = $config.get(t) // Read and track
79
- console.log('API URL:', config.apiUrl)
65
+ $merged.subscribe((merged) => {
66
+ console.log('Merged data', merged)
80
67
  })
81
68
  ```
82
69
 
83
- ### Reading with `.pick()`
70
+ ### Pick
84
71
 
85
72
  Use `.pick()` when you want the current value without creating a dependency:
86
73
 
87
74
  ```typescript
88
- const $config = constant({ apiUrl: 'https://api.example.com' })
75
+ const $config = constant(() => ({ apiUrl: 'https://api.example.com' }))
89
76
 
90
- // Read without tracking (e.g., outside an effect)
91
- const currentConfig = $config.pick()
77
+ // Read without tracking (e.g., outside a subscription or derivation)
78
+ const currentConfig = await $config.pick()
92
79
  console.log(currentConfig.apiUrl)
93
80
 
94
- // Or inside an effect, when you don't want to track changes
95
- effect((t) => {
96
- $trigger.watch(t) // Only track trigger
97
- const config = $config.pick() // Don't track config
98
- console.log(config)
99
- })
100
81
  ```
101
82
 
102
- ### No `.set()` Method
103
-
104
- Constants are immutable - attempting to call `.set()` will result in a TypeScript error:
105
-
106
- ```typescript
107
- const $config = constant({ apiUrl: 'https://api.example.com' })
108
-
109
- $config.set({ apiUrl: 'new-url' }) // Type error! Constants have no .set() method
110
- ```
111
-
112
- ### Disposing with `.dispose()`
83
+ ### Dispose
113
84
 
114
85
  Constants can be disposed to free resources:
115
86
 
116
87
  ```typescript
117
- const $config = constant({ apiUrl: 'https://api.example.com' })
88
+ const $config = constant(() => ({ apiUrl: 'https://api.example.com' }))
118
89
 
119
90
  // Later, clean up
120
91
  $config.dispose()
121
92
 
122
93
  // Subsequent operations will throw
123
- $config.get(t) // Error: Primitive is disposed
94
+ $config.pick() // Error: Primitive is disposed
124
95
  ```
125
96
 
126
97
  ## Lifecycle
127
98
 
128
- Constants have two initialization patterns depending on whether you pass a value or a function.
129
-
130
- ### Eager Initialization Flow
131
-
132
- When you pass a direct value, it's stored immediately:
133
-
134
- ```mermaid
135
- sequenceDiagram
136
- participant User
137
- participant $config as $config (Constant)
138
-
139
- User->>$config: constant({ value: 'data' })
140
- activate $config
141
- Note over $config: Store value immediately<br/>Mark as initialized
142
- deactivate $config
143
-
144
- User->>$config: get(t)
145
- activate $config
146
- Note over $config: Already initialized<br/>Return stored value
147
- $config-->>User: { value: 'data' }
148
- deactivate $config
149
- ```
150
-
151
- ### Lazy Initialization Flow
152
-
153
- When you pass a function, it's executed on first access:
99
+ Constants use lazy initialization - the function you provide is executed only on first access:
154
100
 
155
101
  ```mermaid
156
102
  sequenceDiagram
@@ -189,77 +135,38 @@ sequenceDiagram
189
135
 
190
136
  **How it works:**
191
137
 
192
- 1. **Creation**: Constructor checks if value is a function
193
- - If function: store it, mark as not initialized
194
- - If value: store it directly, mark as initialized
138
+ 1. **Creation**: Store the initializer function, mark as not initialized
195
139
 
196
140
  2. **First access**: When `.get(t)` or `.pick()` is called
197
141
  - Check if initialized
198
- - If not, execute stored function
142
+ - If not, execute the function
199
143
  - Cache result and mark as initialized
200
144
 
201
- 3. **Subsequent access**: Always return cached value
145
+ 3. **Subsequent access**: Always return cached value (function never called again)
202
146
 
203
147
  ## Best Practices
204
148
 
205
- ### Use Lazy Init for Expensive Computations
206
-
207
- Defer expensive work until it's actually needed:
208
-
209
- ```typescript
210
- // ✅ Good - lazy evaluation
211
- const $parsedData = constant(() => {
212
- return JSON.parse(largeDataString) // Only runs when accessed
213
- })
214
-
215
- // ❌ Less efficient - eager evaluation
216
- const $parsedData = constant(JSON.parse(largeDataString)) // Runs immediately
217
- ```
218
-
219
- ### Use Constants for Configuration
149
+ ### Use Constants for Expensive Computations
220
150
 
221
- Perfect for application configuration:
151
+ Constants defer expensive work until it's actually needed:
222
152
 
223
153
  ```typescript
224
- const $appConfig = constant({
225
- apiUrl: process.env.API_URL || 'https://api.example.com',
226
- environment: process.env.NODE_ENV || 'development',
227
- features: {
228
- darkMode: true,
229
- betaFeatures: false
230
- }
231
- })
232
-
233
- effect((t) => {
234
- const config = $appConfig.get(t)
235
- setupApp(config)
236
- })
237
- ```
238
-
239
- ### Name Constants Clearly
154
+ // Good - lazy evaluation with constant
155
+ const $parsedData = constant(() => JSON.parse(largeDataString))
240
156
 
241
- Use the `$` prefix like other reactive primitives:
242
-
243
- ```typescript
244
- // ✅ Good - clear constant names
245
- const $apiEndpoint = constant('https://api.example.com')
246
- const $appVersion = constant('1.0.0')
247
- const $maxRetries = constant(3)
248
-
249
- // ❌ Less clear
250
- const apiEndpoint = constant('https://api.example.com')
251
- const APP_VERSION = constant('1.0.0')
157
+ // Eager - runs immediately (plain JavaScript)
158
+ const parsedData = JSON.parse(largeDataString)
252
159
  ```
253
160
 
254
161
  ### Prefer Plain const for Non-Reactive Values
255
162
 
256
- If no effects or derivations will read it, use plain JavaScript:
163
+ If no subscriptions or derivations will read it, use plain JavaScript:
257
164
 
258
165
  ```typescript
259
166
  // ❌ Unnecessary - no reactivity needed
260
- const $localConfig = constant({ timeout: 5000 })
261
- function fetch() {
262
- const config = $localConfig.pick() // Never tracked
167
+ const $localConfig = constant(() => ({ timeout: 5000 }))
168
+ function async fetch() {
169
+ const config = await $localConfig.pick() // Never tracked
263
170
  return doFetch(config)
264
171
  }
265
172
 
@@ -272,85 +179,6 @@ function fetch() {
272
179
 
273
180
  ## Common Pitfalls
274
181
 
275
- ### Using Constants When State Would Be Better
276
-
277
- **Problem**: Using a constant for a value that actually needs to change.
278
-
279
- ```typescript
280
- // ❌ Bad - theme should be changeable
281
- const $theme = constant('light')
282
-
283
- // Can't update it later!
284
- // $theme.set('dark') // Type error!
285
- ```
286
-
287
- **Solution**: Use state for mutable values:
288
-
289
- ```typescript
290
- // ✅ Good - theme is mutable
291
- const $theme = state('light')
292
-
293
- // Can update it
294
- $theme.set('dark')
295
- ```
296
-
297
- ### Creating Too Many Constants
298
-
299
- **Problem**: Making every value a constant even when plain const would work.
300
-
301
- ```typescript
302
- // ❌ Overkill - not used reactively
303
- const $pi = constant(3.14159)
304
- const $maxLength = constant(100)
305
-
306
- function calculate() {
307
- return $pi.pick() * radius // Just use plain const
308
- }
309
- ```
310
-
311
- **Solution**: Use plain const for non-reactive values:
312
-
313
- ```typescript
314
- // ✅ Better - plain JavaScript
315
- const PI = 3.14159
316
- const MAX_LENGTH = 100
317
-
318
- function calculate() {
319
- return PI * radius
320
- }
321
- ```
322
-
323
- ### Expecting Constants to Update
324
-
325
- **Problem**: Thinking constants will somehow update like state.
326
-
327
- ```typescript
328
- // ❌ Wrong - constant won't update
329
- const $userName = constant('Alice')
330
-
331
- effect((t) => {
332
- const name = $userName.get(t)
333
- console.log(name) // Always "Alice"
334
- })
335
-
336
- // This won't work - no .set() method!
337
- // $userName.set('Bob')
338
- ```
339
-
340
- **Solution**: Use state if the value needs to change:
341
-
342
- ```typescript
343
- // ✅ Correct - use state
344
- const $userName = state('Alice')
345
-
346
- effect((t) => {
347
- const name = $userName.get(t)
348
- console.log(name) // Updates when changed
349
- })
350
-
351
- $userName.set('Bob') // Now this works!
352
- ```
353
-
354
182
  ### Lazy Init with Side Effects
355
183
 
356
184
  **Problem**: Using lazy initialization with side effects.
@@ -371,8 +199,7 @@ const $config = constant(() => {
371
199
  const $config = constant(() => loadConfig())
372
200
 
373
201
  // Handle side effects separately
374
- effect((t) => {
375
- const config = $config.get(t)
202
+ $config.subscribe((config) => {
376
203
  console.log('Config loaded:', config)
377
204
  localStorage.setItem('loaded', 'true')
378
205
  })
@@ -6,9 +6,6 @@ Derivations are **reactive formulas** that compute values based on other reactiv
6
6
 
7
7
  - **Lazy evaluation**: Computes only when accessed, not when created
8
8
  - **Automatic caching**: Caches results until dependencies change
9
- - **Dirty tracking**: Marked as "dirty" on changes, recomputes on next access
10
- - **Pure computation**: Should have no side effects
11
- - **Efficient**: Avoids unnecessary recomputation through smart caching
12
9
 
13
10
  ## When to Use Derivations
14
11
 
@@ -16,17 +13,14 @@ Use derivations when you need to:
16
13
 
17
14
  - ✅ Compute values from other reactive primitives
18
15
  - ✅ Transform or filter data reactively
19
- - ✅ Create calculated fields (totals, averages, formatted values)
20
- - ✅ Chain computations together
21
16
  - ✅ Build complex reactive data flows
22
17
 
23
18
  Don't use derivations when:
24
19
 
25
- - ❌ You need to perform side effects (use effects instead)
26
- - ❌ The computation is not pure or deterministic
20
+ - ❌ You need to perform side effects (use subscribe instead)
27
21
 
28
22
  ::: tip
29
- Not sure whether to use a derivation or an effect? See the [Derivations vs Effects](./overview.md#derivations-vs-effects) section for a detailed comparison and guidance.
23
+ Not sure whether to use a derivation or a side effect? See the [Derivations vs Side Effects](./overview.md#derivations-vs-side-effects) section for a detailed comparison and guidance.
30
24
  :::
31
25
 
32
26
 
@@ -37,6 +31,8 @@ Creating a derivation is straightforward:
37
31
  ```typescript
38
32
  import { derivation } from '@ersbeth/picoflow'
39
33
 
34
+ const $count = state(1);
35
+
40
36
  const $doubled = derivation((t) => {
41
37
  // Your computation here
42
38
  return $count.get(t) * 2
@@ -49,23 +45,23 @@ TypeScript automatically infers the return type based on what your function retu
49
45
 
50
46
  Derivations have several methods for reading values and managing lifecycle.
51
47
 
52
- ### Reading with `.get(t)` (Reactive)
48
+ ### Get
53
49
 
54
- Inside an effect or another derivation, use `.get(t)` to read the value and track the dependency:
50
+ Inside a subscription or another derivation, use `.get(t)` to read the value and track the dependency:
55
51
 
56
52
  ```typescript
57
53
  const $count = state(10)
58
54
  const $doubled = derivation((t) => $count.get(t) * 2)
55
+ const $result = derivation(t)=> $doubled.get(t) + 2)
59
56
 
60
- effect((t) => {
61
- const value = $doubled.get(t) // Tracks dependency
62
- console.log('Doubled:', value)
57
+ $result.subscribe((value) => {
58
+ console.log('Result:', value)
63
59
  })
64
60
 
65
- $count.set(20) // Logs: "Doubled: 40"
61
+ $count.set(20) // Logs: "Result: 42"
66
62
  ```
67
63
 
68
- ### Reading with `.pick()` (Non-Reactive)
64
+ ### Pick
69
65
 
70
66
  Use `.pick()` to read the current value without tracking:
71
67
 
@@ -81,7 +77,26 @@ $count.set(20)
81
77
  // No reaction because we used .pick()
82
78
  ```
83
79
 
84
- ### Chaining Derivations
80
+ ### Dispose
81
+
82
+ Derivations can be disposed to free resources and prevent memory leaks:
83
+
84
+ ```typescript
85
+ const $doubled = derivation((t) => $count.get(t) * 2)
86
+
87
+ // Use the derivation
88
+ $doubled.subscribe((value) => {
89
+ console.log(value)
90
+ })
91
+
92
+ // Later, clean up
93
+ $doubled.dispose()
94
+
95
+ // Subsequent operations will throw
96
+ await $doubled.pick() // Error: Primitive is disposed
97
+ ```
98
+
99
+ ## Chaining Derivations
85
100
 
86
101
  Derivations can depend on other derivations, creating chains of reactive computations:
87
102
 
@@ -96,7 +111,7 @@ const $sum = derivation((t) => {
96
111
  // Second derivation: average (depends on $sum)
97
112
  const $average = derivation((t) => {
98
113
  const sum = $sum.get(t)
99
- const count = $items.pick().length
114
+ const count = $items.get(t).length
100
115
  return sum / count
101
116
  })
102
117
 
@@ -106,8 +121,8 @@ const $formatted = derivation((t) => {
106
121
  return `Average: ${avg.toFixed(2)}`
107
122
  })
108
123
 
109
- effect((t) => {
110
- console.log($formatted.get(t))
124
+ $formatted.subscribe((value) => {
125
+ console.log(value)
111
126
  })
112
127
 
113
128
  $items.set([15, 25, 35]) // All derivations update in sequence
@@ -119,27 +134,10 @@ graph LR
119
134
  B --> C[$average]
120
135
  A -.-> C
121
136
  C --> D[$formatted]
122
- D --> E[Effect]
137
+ D --> E[Subscription]
123
138
  ```
124
139
 
125
- ### Disposing with `.dispose()`
126
140
 
127
- Derivations can be disposed to free resources and prevent memory leaks:
128
-
129
- ```typescript
130
- const $doubled = derivation((t) => $count.get(t) * 2)
131
-
132
- // Use the derivation
133
- effect((t) => {
134
- console.log($doubled.get(t))
135
- })
136
-
137
- // Later, clean up
138
- $doubled.dispose()
139
-
140
- // Subsequent operations will throw
141
- $doubled.get(someContext) // Error: Primitive is disposed
142
- ```
143
141
 
144
142
  ## Lifecycle
145
143
 
@@ -152,16 +150,16 @@ sequenceDiagram
152
150
  participant User
153
151
  participant $count as $count (State)
154
152
  participant $doubled as $doubled (Derivation)
155
- participant Effect
153
+ participant Subscription
156
154
 
157
155
  Note over User,$doubled: 1. Creation Phase
158
156
  User->>$doubled: Create derivation
159
157
  Note over $doubled: Store function<br/>NOT executed yet
160
158
 
161
- Note over User,Effect: 2. First Access
162
- User->>Effect: Create effect
163
- activate Effect
164
- Effect->>$doubled: get(t)
159
+ Note over User,Subscription: 2. First Access
160
+ User->>Subscription: Create subscription
161
+ activate Subscription
162
+ Subscription->>$doubled: get(t)
165
163
  activate $doubled
166
164
  Note over $doubled: Not computed yet<br/>Need to compute!
167
165
 
@@ -172,12 +170,12 @@ sequenceDiagram
172
170
  deactivate $count
173
171
 
174
172
  Note over $doubled: Compute: 0 * 2 = 0<br/>Cache result
175
- $doubled-->>Effect: 0
173
+ $doubled-->>Subscription: 0
176
174
  deactivate $doubled
177
- Note over Effect: Log: "Doubled: 0"
178
- deactivate Effect
175
+ Note over Subscription: Log: "Doubled: 0"
176
+ deactivate Subscription
179
177
 
180
- Note over User,Effect: 3. Dependency Change
178
+ Note over User,Subscription: 3. Dependency Change
181
179
  User->>$count: set(5)
182
180
  activate $count
183
181
  Note over $count: Value changed
@@ -187,12 +185,12 @@ sequenceDiagram
187
185
  Note over $doubled: Mark as dirty<br/>NO recompute yet!
188
186
  deactivate $doubled
189
187
 
190
- $count->>Effect: Schedule execution
188
+ $count->>Subscription: Schedule execution
191
189
  deactivate $count
192
190
 
193
- Note over User,Effect: 4. Recompute on Access
194
- activate Effect
195
- Effect->>$doubled: get(t)
191
+ Note over User,Subscription: 4. Recompute on Access
192
+ activate Subscription
193
+ Subscription->>$doubled: get(t)
196
194
  activate $doubled
197
195
  Note over $doubled: Dirty? YES<br/>Recompute now!
198
196
 
@@ -202,12 +200,12 @@ sequenceDiagram
202
200
  deactivate $count
203
201
 
204
202
  Note over $doubled: Compute: 5 * 2 = 10<br/>Cache new result
205
- $doubled-->>Effect: 10
203
+ $doubled-->>Subscription: 10
206
204
  deactivate $doubled
207
- Note over Effect: Log: "Doubled: 10"
208
- deactivate Effect
205
+ Note over Subscription: Log: "Doubled: 10"
206
+ deactivate Subscription
209
207
 
210
- Note over User,Effect: 5. Cached Access
208
+ Note over User,Subscription: 5. Cached Access
211
209
  User->>$doubled: pick()
212
210
  activate $doubled
213
211
  Note over $doubled: Not dirty<br/>Return cache
@@ -228,43 +226,6 @@ This lazy + cached approach means:
228
226
  - **Multiple reads use the cache** (efficient)
229
227
  - **Multiple dependency changes = one recompute** (optimized)
230
228
 
231
- ## Best Practices
232
-
233
- ### Keep Derivations Pure
234
-
235
- Derivations should be pure functions with no side effects:
236
-
237
- ```typescript
238
- // ✅ Good - pure function
239
- const $total = derivation((t) => {
240
- return $items.get(t).reduce((sum, item) => sum + item.price, 0)
241
- })
242
-
243
- // ❌ Bad - side effect
244
- const $total = derivation((t) => {
245
- const total = $items.get(t).reduce((sum, item) => sum + item.price, 0)
246
- console.log('Total:', total) // Side effect!
247
- return total
248
- })
249
- ```
250
-
251
- **Why pure?** PicoFlow may skip recomputation if it thinks the result hasn't changed. Side effects would be unpredictable!
252
-
253
- ### Name Derivations Clearly
254
-
255
- Use names that describe the computed value:
256
-
257
- ```typescript
258
- // ✅ Good - clear what it computes
259
- const $totalPrice = derivation((t) => ...)
260
- const $filteredUsers = derivation((t) => ...)
261
- const $formattedDate = derivation((t) => ...)
262
-
263
- // ❌ Bad - unclear purpose
264
- const $result = derivation((t) => ...)
265
- const $temp = derivation((t) => ...)
266
- ```
267
-
268
229
  ## Common Pitfalls
269
230
 
270
231
  ### Side Effects in Derivations
@@ -281,14 +242,13 @@ const $logged = derivation((t) => {
281
242
  })
282
243
  ```
283
244
 
284
- **Solution**: Move side effects to an effect:
245
+ **Solution**: Move side effects to a subscription:
285
246
 
286
247
  ```typescript
287
- // ✅ Correct - side effect in effect
248
+ // ✅ Correct - side effect in subscription
288
249
  const $count = state(0)
289
250
 
290
- effect((t) => {
291
- const value = $count.get(t)
251
+ $count.subscribe((value) => {
292
252
  console.log('Count:', value) // Side effect here is fine
293
253
  })
294
254
 
@@ -297,33 +257,6 @@ const $doubled = derivation((t) => {
297
257
  })
298
258
  ```
299
259
 
300
- ### Using `.pick()` Instead of `.get(t)`
301
-
302
- **Problem**: Using `.pick()` inside a derivation breaks doesn't trigger the reactivity system.
303
-
304
- ```typescript
305
- // ❌ Derivation doesn't track $count
306
- const $count = state(10)
307
- const $doubled = derivation((t) => {
308
- return $count.pick() * 2 // No dependency tracking!
309
- })
310
-
311
- effect((t) => {
312
- console.log($doubled.get(t))
313
- })
314
-
315
- $count.set(20) // Effect won't run - no dependency!
316
- ```
317
-
318
- **Solution**: Always use `.get(t)` to track dependencies:
319
-
320
- ```typescript
321
- // ✅ Correct - tracks $count
322
- const $doubled = derivation((t) => {
323
- return $count.get(t) * 2
324
- })
325
- ```
326
-
327
260
  ### Mutating Returned Values
328
261
 
329
262
  **Problem**: Mutating arrays or objects returned from derivations doesn't trigger the reactivity system.