@ersbeth/picoflow 1.1.2 → 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 +856 -1530
  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 -57
  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 -148
  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
@@ -2,32 +2,18 @@
2
2
 
3
3
  PicoFlow provides reactive maps with **fine-grained tracking**. Instead of reacting to the entire map changing, you can react to specific operations like adding, updating, or deleting individual entries.
4
4
 
5
- Imagine you have a map of 1000 users. In a naive reactive system, every time you add, remove, or update a single user, the entire map re-renders. **Inefficient!** With PicoFlow's reactive maps, you can track specific operations and only update what changed.
6
-
7
- ### Key Characteristics
8
-
9
- - **Fine-grained reactivity**: Track individual operations (add, update, delete) separately
10
- - **Multiple tracking levels**: Track the whole map or specific operations
11
- - **Native Map**: Uses JavaScript's native `Map<K, V>` internally
12
- - **Operation-specific signals**: `$lastAdded`, `$lastUpdated`, `$lastDeleted` for granular tracking
13
- - **Disposable**: Can be disposed to clean up resources
14
-
15
5
  ## When to Use Maps
16
6
 
17
7
  Use maps when you need to:
18
8
 
19
9
  - ✅ Track large collections with fine-grained updates
20
10
  - ✅ React to specific operations (additions, updates, deletions) separately
21
- - ✅ Manage key-value pairs where individual key operations matter
22
11
  - ✅ Optimize performance by avoiding full map re-processing
23
- - ✅ Animate or handle UI updates for specific changes
24
12
 
25
13
  Don't use maps when:
26
14
 
27
- - ❌ You have a small, simple object (use `state` instead)
28
- - ❌ You don't need fine-grained tracking (use `state` with a Record)
15
+ - ❌ You don't need fine-grained tracking (use `state` with a Record/Map)
29
16
  - ❌ You need array-like operations (use `array` instead)
30
- - ❌ The collection is rarely modified (regular state might be simpler)
31
17
 
32
18
  ## Creating Maps
33
19
 
@@ -69,8 +55,7 @@ $cache.update('user:1', updatedUserData)
69
55
  $cache.delete('user:1')
70
56
 
71
57
  // Read (reactive)
72
- effect((t) => {
73
- const data = $cache.get(t)
58
+ $cache.subscribe((data) => {
74
59
  // Track entire map - returns Map<string, Data>
75
60
  const hasUser = data.has('user:1')
76
61
  if (hasUser) {
@@ -90,21 +75,18 @@ const user = snapshot.get('user:1')
90
75
  - `delete(key)` throws an error if the key doesn't exist
91
76
 
92
77
 
93
- ### Whole Map Tracking with `.get(t)`
78
+ ### Whole Map Tracking
94
79
 
95
80
  Track when the entire map changes (any operation):
96
81
 
97
82
  ```typescript
98
- import { map, effect } from '@ersbeth/picoflow'
99
-
100
83
  const $items = map<string, number>()
101
84
 
102
85
  // Initialize with values
103
86
  $items.add('a', 1)
104
87
  $items.add('b', 2)
105
88
 
106
- effect((t) => {
107
- const items = $items.get(t) // Track all changes
89
+ $items.subscribe((items) => {
108
90
  console.log('Map size:', items.size)
109
91
  })
110
92
 
@@ -114,207 +96,104 @@ $items.delete('a') // Logs: "Map size: 2"
114
96
 
115
97
  Use `.get(t)` when you need the entire map's current state. It returns a native `Map<K, V>`.
116
98
 
117
- ### Fine-Grained: Track Additions
118
-
119
- Track only when items are added:
120
-
121
- ```typescript
122
- const $items = map<string, number>()
123
-
124
- effect((t) => {
125
- const lastAdded = $items.$lastAdded.get(t)
126
- if (lastAdded) {
127
- console.log(`Added ${lastAdded.key} = ${lastAdded.value}`)
128
- }
129
- })
130
-
131
- $items.add('a', 1) // Logs: "Added a = 1"
132
- $items.add('b', 2) // Logs: "Added b = 2"
133
- $items.update('a', 10) // No log - not an addition!
134
- $items.delete('a') // No log - not an addition!
135
- ```
136
-
137
- ### Fine-Grained: Track Updates
138
-
139
- Track only when existing items are updated:
99
+ ### Fine-Grained Tracking
140
100
 
141
- ```typescript
142
- const $items = map<string, number>()
143
-
144
- // Add some initial values
145
- $items.add('a', 1)
146
- $items.add('b', 2)
147
-
148
- effect((t) => {
149
- const lastUpdated = $items.$lastUpdated.get(t)
150
- if (lastUpdated) {
151
- console.log(`Updated ${lastUpdated.key} = ${lastUpdated.value}`)
152
- }
153
- })
154
-
155
- $items.update('a', 10) // Logs: "Updated a = 10"
156
- $items.add('c', 3) // No log - not an update!
157
- $items.delete('a') // No log - not an update!
158
- ```
159
-
160
- ### Fine-Grained: Track Deletions
161
-
162
- Track only when items are deleted:
101
+ Track specific operations with `$lastAction`:
163
102
 
164
103
  ```typescript
165
104
  const $items = map<string, number>()
166
105
 
167
- // Add some initial values
168
- $items.add('a', 1)
169
- $items.add('b', 2)
170
- $items.add('c', 3)
171
-
172
- effect((t) => {
173
- const lastDeleted = $items.$lastDeleted.get(t)
174
- if (lastDeleted) {
175
- console.log(`Deleted key: ${lastDeleted.key}, value was: ${lastDeleted.value}`)
106
+ $items.$lastAction.subscribe((action) => {
107
+ if (!action) return
108
+
109
+ switch (action.type) {
110
+ case 'add':
111
+ console.log(`Added ${action.key} = ${action.addedValue}`)
112
+ break
113
+ case 'update':
114
+ console.log(`Updated ${action.key}: ${action.clearedValue} ${action.setValue}`)
115
+ break
116
+ case 'delete':
117
+ console.log(`Deleted ${action.key}, was: ${action.removedValue}`)
118
+ break
119
+ case 'clear':
120
+ console.log(`Cleared ${action.clearedMap.size} entries`)
121
+ break
122
+ case 'set':
123
+ console.log(`Set to ${action.setMap.size} entries`)
124
+ break
176
125
  }
177
126
  })
178
127
 
179
- $items.delete('a') // Logs: "Deleted key: a, value was: 1"
180
- $items.add('d', 4) // No log - not a deletion!
181
- $items.update('b', 20) // No log - not a deletion!
182
- $items.delete('b') // Logs: "Deleted key: b, value was: 20"
128
+ $items.add('a', 1) // Logs: "Added a = 1"
129
+ $items.add('b', 2) // Logs: "Added b = 2"
130
+ $items.update('a', 10) // Logs: "Updated a: 1 10"
131
+ $items.delete('a') // Logs: "Deleted a, was: 10"
132
+ $items.clear() // Logs: "Cleared 1 entries"
183
133
  ```
184
134
 
185
135
  ## Lifecycle
186
136
 
187
- When you create an effect that tracks a map:
137
+ When you create a subscription that tracks a map:
188
138
 
189
- 1. **Registration**: The map registers the effect as a watcher
190
- 2. **Operation**: When you call `add()`, `update()`, or `delete()`, the map updates internally
191
- 3. **Signal Update**: The appropriate signal (`$lastAdded`, `$lastUpdated`, or `$lastDeleted`) is updated
192
- 4. **Notification**: All watching effects are scheduled to run
193
- 5. **Re-execution**: Each watching effect re-executes its function
139
+ 1. **Registration**: The map registers the subscription as a watcher
140
+ 2. **Operation**: When you call `add()`, `update()`, `delete()`, `set()`, or `clear()`, the map updates internally
141
+ 3. **Signal Update**: The `$lastAction` signal is updated with the operation details
142
+ 4. **Notification**: All watching subscriptions are scheduled to run
143
+ 5. **Re-execution**: Each watching subscription re-executes its function
194
144
 
195
145
  ```mermaid
196
146
  sequenceDiagram
197
147
  participant User
198
148
  participant Map as $users (Map)
199
- participant Signal as $lastAdded
200
- participant Effect
149
+ participant Signal as $lastAction
150
+ participant Subscription
201
151
 
202
- Note over User,Effect: 1. Setup Phase
203
- User->>Effect: Create effect
204
- activate Effect
205
- Effect->>Map: get(t)
206
- Note over Map: Register Effect as watcher
207
- Effect->>Signal: get(t)
208
- Note over Signal: Register Effect as watcher
209
- Effect->>Effect: Execute function
210
- Note over Effect: Initial render
211
- deactivate Effect
152
+ Note over User,Subscription: 1. Setup Phase
153
+ User->>Subscription: Create subscription
154
+ activate Subscription
155
+ Subscription->>Map: get(t)
156
+ Note over Map: Register Subscription as watcher
157
+ Subscription->>Signal: get(t)
158
+ Note over Signal: Register Subscription as watcher
159
+ Subscription->>Subscription: Execute function
160
+ Note over Subscription: Initial render
161
+ deactivate Subscription
212
162
 
213
- Note over User,Effect: 2. Operation Phase
163
+ Note over User,Subscription: 2. Operation Phase
214
164
  User->>Map: add('user1', userData)
215
165
  activate Map
216
166
  Note over Map: Update internal Map
217
- Map->>Signal: set({ key, value })
167
+ Map->>Signal: "set({ type: 'add', key, addedValue })"
218
168
  activate Signal
219
169
  Note over Signal: Notify watchers
220
- Signal->>Effect: Schedule execution
170
+ Signal->>Subscription: Schedule execution
221
171
  deactivate Signal
222
172
  Map->>Map: Notify whole map watchers
223
- Map->>Effect: Schedule execution
173
+ Map->>Subscription: Schedule execution
224
174
  deactivate Map
225
175
 
226
- activate Effect
227
- Note over Effect: Re-execute function
228
- Effect->>Signal: get(t)
229
- Signal-->>Effect: { key: 'user1', value: userData }
230
- Effect->>Effect: Handle new user
231
- Note over Effect: Update UI
232
- deactivate Effect
233
- ```
234
-
235
- ## Best Practices
236
-
237
- ### Choose the Right Granularity
238
-
239
- ```typescript
240
- // ✅ Use fine-grained for large maps
241
- const $users = map<number, User>()
242
- effect((t) => {
243
- const lastAdded = $users.$lastAdded.get(t)
244
- if (lastAdded) {
245
- // Handle specific change
246
- renderNewUser(lastAdded.value)
247
- }
248
- })
249
-
250
- // ✅ Use coarse-grained for small maps
251
- const $settings = state({ theme: 'dark', lang: 'en', size: 'large' })
252
- effect((t) => {
253
- const settings = $settings.get(t)
254
- // Re-apply all settings (cheap for 3 items)
255
- applySettings(settings)
256
- })
257
- ```
258
-
259
- ### Combine for Best Results
260
-
261
- ```typescript
262
- // Fine-grained for UI updates
263
- effect((t) => {
264
- const lastAdded = $items.$lastAdded.get(t)
265
- if (lastAdded) {
266
- updateUIIncremental(lastAdded)
267
- }
268
- })
269
-
270
- // Coarse-grained for totals
271
- const $total = derivation((t) => {
272
- const items = $items.get(t)
273
- let sum = 0
274
- for (const value of items.values()) {
275
- sum += value.price
276
- }
277
- return sum
278
- })
176
+ activate Subscription
177
+ Note over Subscription: Re-execute function
178
+ Subscription->>Signal: get(t)
179
+ Signal-->>Subscription: "{ type: 'add', key: 'user1', addedValue: userData }"
180
+ Subscription->>Subscription: Handle new user
181
+ Note over Subscription: Update UI
182
+ deactivate Subscription
279
183
  ```
280
184
 
281
185
  ## Common Pitfalls
282
186
 
283
- ### Forgetting to Handle Nulls
284
-
285
- **Problem**: The operation signals can be `null` initially.
286
-
287
- ```typescript
288
- // ❌ Can be null initially
289
- effect((t) => {
290
- const lastAdded = $items.$lastAdded.get(t)
291
- console.log(lastAdded.key) // Error if null!
292
- })
293
- ```
294
-
295
- **Solution**: Always check for null:
296
-
297
- ```typescript
298
- // ✅ Check for null
299
- effect((t) => {
300
- const lastAdded = $items.$lastAdded.get(t)
301
- if (lastAdded) {
302
- console.log(lastAdded.key)
303
- }
304
- })
305
- ```
306
-
307
187
  ### Using Wrong Tracking
308
188
 
309
189
  **Problem**: Tracking the entire map when you only need specific operations.
310
190
 
311
191
  ```typescript
312
192
  // ❌ Tracks entire map when you only need additions
313
- effect((t) => {
314
- const items = $items.get(t) // Runs on ALL changes
193
+ $items.subscribe((items) => {
315
194
  const keys = Array.from(items.keys())
316
195
  const lastKey = keys[keys.length - 1]
317
- animateNewItem(lastKey)
196
+ animateNewItem(lastKey) // Runs on ALL changes
318
197
  })
319
198
  ```
320
199
 
@@ -322,10 +201,9 @@ effect((t) => {
322
201
 
323
202
  ```typescript
324
203
  // ✅ Track only additions
325
- effect((t) => {
326
- const lastAdded = $items.$lastAdded.get(t)
327
- if (lastAdded) {
328
- animateNewItem(lastAdded.key)
204
+ $items.$lastAction.subscribe((action) => {
205
+ if (action && action.type === 'add') {
206
+ animateNewItem(action.key)
329
207
  }
330
208
  })
331
209
  ```
@@ -1,165 +1,82 @@
1
1
  # Primitives Overview
2
2
 
3
- PicoFlow provides several reactive primitives, each designed for specific use cases in reactive programming. This guide introduces all the primitives and shows how they work together.
3
+ PicoFlow distinguishes between two main concepts:
4
+ - **Primitives**: Reactive values (state, derivation, signal, collections)
5
+ - **Side Effects**: Created by subscribing to primitives
4
6
 
5
7
  ::: tip
6
8
  Looking for naming conventions? Check out the **[Conventions](/guide/introduction/conventions)** guide to learn about the `$` prefix.
7
9
  :::
8
10
 
9
- ## Listing
11
+ ## Primitives
10
12
 
11
- PicoFlow provides several reactive primitives for different use cases:
13
+ PicoFlow provides several reactive primitives, each with specific capabilities. Primitive may exist in synchrone and asynchrone flavours.
12
14
 
13
- | Primitive | Purpose | Example |
14
- |-----------|---------|---------|
15
- | **Signal** | Event notifications | Manual refresh, synchronization |
16
- | **State** | Mutable values | Form inputs, toggles, counters |
17
- | **Constant** | Immutable values | Configuration, initial values |
18
- | **Derivation** | Computed values | Totals, filtered lists, formatted strings |
19
- | **Effect** | Side effects | DOM updates, logging, API calls |
20
- | **Resource** | Async data fetching | API calls, file loading |
21
- | **Stream** | Event-driven data | WebSockets, timers, DOM events |
22
- | **Map** | Reactive dictionaries | Key-value stores, caches |
23
- | **Array** | Reactive lists | Todo lists, dynamic collections |
15
+ | Primitive | Sync | Async | Purpose |
16
+ |-----------|:----:|:-----:|---------|
17
+ | **Signal** | | - | Event notifications without values |
18
+ | **State** | | | Mutable reactive values |
19
+ | **Constant** | | | Immutable reactive values |
20
+ | **Derivation** | | | Computed values from dependencies |
21
+ | **Writable Derivation** | | | Derivations with custom setters |
22
+ | **Array** | | - | Reactive lists with fine-grained tracking |
23
+ | **Map** | ✓ | - | Reactive dictionaries with fine-grained tracking |
24
24
 
25
- ## Details
25
+ ## Side Effects
26
26
 
27
- ### Signal
27
+ You may subscribe to any primitive to perform side effects on change. When you subscribe, you get a `FlowEffect` that can be disposed.
28
28
 
29
- **Event-like notifications without values** - use when you want to trigger effects without carrying data.
30
29
 
31
- ```typescript
32
- const $refresh = signal()
33
- $refresh.trigger() // Tell everyone: "Refresh now!"
34
- ```
35
-
36
- **Use cases:** Manual refresh triggers, event notifications, synchronization points
37
-
38
- ### State
39
-
40
- **Mutable reactive values** - use for data that changes over time.
41
-
42
- ```typescript
43
- const $count = state(0)
44
- $count.set(1)
45
- $count.set(n => n + 1) // Updater function
46
- ```
47
-
48
- **Use cases:** Form inputs, counters, toggles, user data
49
-
50
- ### Constant
51
-
52
- **Immutable reactive values** - use for values that never change but need to be part of the reactive graph.
53
-
54
- ```typescript
55
- const $config = constant({ apiUrl: 'https://api.example.com', timeout: 5000 })
56
- const $version = constant('1.0.0')
57
- ```
58
-
59
- **Use cases:** Configuration values, application constants, initial data
60
-
61
- **Key feature:** Unlike regular JavaScript constants, these can be tracked in the reactive graph, making them useful for dependencies that shouldn't change.
62
-
63
- ### Derivation
64
-
65
- **Computed values** - use when you want to calculate something based on other reactive values.
66
-
67
- ```typescript
68
- const $double = derivation((t) => $count.get(t) * 2)
69
- ```
70
-
71
- **Use cases:** Totals, filtered lists, formatted values, derived UI state
72
-
73
- **Key feature:** Lazy evaluation and caching - only recomputes when dependencies change AND when the value is accessed.
74
-
75
- ### Effect
76
-
77
- **Side effects** - use when you want to do something in response to changes (DOM updates, logging, etc.).
30
+ When reacting to a single primitive, use the `.subscribe()` method:
78
31
 
79
32
  ```typescript
80
- effect((t) => {
81
- console.log('Count is:', $count.get(t))
33
+ const effect = $count.subscribe((value) => {
34
+ console.log('Count is:', value)
82
35
  })
83
- ```
84
-
85
- **Use cases:** Logging, DOM manipulation, API calls, persistence
86
-
87
- **Key feature:** Eager execution - runs immediately when created and whenever dependencies change.
88
-
89
- ### Resource
90
-
91
- **Async data fetching** - use when you need to load data asynchronously and track its loading state.
92
-
93
- ```typescript
94
- const $userId = state(1)
95
- const $user = resource(
96
- (t) => $userId.get(t),
97
- (id) => fetchUser(id)
98
- )
99
- ```
100
-
101
- **Use cases:** API calls, file loading, async data fetching
102
-
103
- **Key feature:** Provides loading, error, and ready states automatically, with built-in cancellation of stale requests.
104
-
105
- ### Stream
106
36
 
107
- **Event-driven data** - use when you want to handle continuous streams of events or data.
108
-
109
- ```typescript
110
- const $clicks = stream<MouseEvent>((emit) => {
111
- document.addEventListener('click', emit)
112
- return () => document.removeEventListener('click', emit)
113
- })
37
+ // Later: dispose the effect
38
+ effect.dispose()
114
39
  ```
115
40
 
116
- **Use cases:** WebSocket connections, timers, DOM events, real-time data
117
41
 
118
- **Key feature:** Push-based model for handling continuous event streams with automatic cleanup.
119
-
120
- ### Map
121
-
122
- **Reactive dictionaries** - use when you need fine-grained tracking of key-value pairs.
42
+ When combining multiple primitives, use the `subscribe()` function:
123
43
 
124
44
  ```typescript
125
- const $users = map<number, User>({
126
- 1: { id: 1, name: 'Alice' },
127
- 2: { id: 2, name: 'Bob' }
128
- })
129
- $users.setAt(3, { id: 3, name: 'Charlie' })
45
+ const effect = subscribe(
46
+ (t) => ({ count: $count.get(t), name: $name.get(t) }),
47
+ (data) => {
48
+ console.log('Count:', data.count, 'Name:', data.name)
49
+ }
50
+ )
130
51
  ```
131
52
 
132
- **Use cases:** Caches, entity stores, key-value collections
133
-
134
- **Key feature:** Fine-grained reactivity - track additions, deletions, or changes to the entire map separately.
135
-
136
- ### Array
53
+ ### Use cases
137
54
 
138
- **Reactive lists** - use when you need fine-grained tracking of array operations.
139
-
140
- ```typescript
141
- const $todos = array<Todo>([
142
- { id: 1, text: 'Learn PicoFlow', done: false },
143
- { id: 2, text: 'Build app', done: false }
144
- ])
145
- $todos.push({ id: 3, text: 'Deploy', done: false })
146
- ```
55
+ - Logging and debugging
56
+ - DOM manipulation
57
+ - API calls and data persistence
58
+ - Analytics and tracking
59
+ - Side effects that don't produce values
147
60
 
148
- **Use cases:** Todo lists, dynamic collections, ordered data
61
+ ### Key features
149
62
 
150
- **Key feature:** Fine-grained reactivity - track specific operations (push, pop, splice) instead of full array changes.
63
+ - **Eager execution**: Runs immediately when created
64
+ - **Automatic re-execution**: Runs whenever dependencies change
65
+ - **Returns FlowEffect**: Can be disposed to stop the effect
66
+ - **Error handling**: Optional `onError` and `onPending` callbacks
151
67
 
152
- ## Derivations vs Effects
68
+ ## Derivations vs Side Effects
153
69
 
154
- What's the difference between a derivation and an effect? Both react to changes, but they serve different purposes:
70
+ What's the difference between a derivation and a side effect? Both react to changes, but they serve different purposes:
155
71
 
156
- | Feature | Derivation | Effect |
157
- |---------|-----------|--------|
72
+ | Feature | Derivation | Side Effect (subscribe) |
73
+ |---------|-----------|---------|
158
74
  | Purpose | **Compute a value** | **Perform side effects** |
159
- | Returns | A value | Nothing (void) |
75
+ | Returns | A reactive value | FlowEffect (disposable) |
160
76
  | Should be pure? | ✅ Yes | ❌ No |
161
77
  | Side effects allowed? | ❌ No | ✅ Yes |
162
78
  | When it runs | Lazily (when accessed) | Immediately and on changes |
79
+ | How to create | `derivation()` | `subscribe()` or `.subscribe()` |
163
80
  | Use case | Calculate totals, filter lists | Update DOM, save data, log |
164
81
 
165
82
  ```mermaid