@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.
- package/.vscode/settings.json +3 -3
- package/CHANGELOG.md +43 -0
- package/README.md +2 -18
- package/biome.json +45 -35
- package/dist/picoflow.js +857 -1528
- package/dist/types/api/base/flowDisposable.d.ts +41 -0
- package/dist/types/api/base/flowDisposable.d.ts.map +1 -0
- package/dist/types/api/base/flowObservable.d.ts +27 -0
- package/dist/types/api/base/flowObservable.d.ts.map +1 -0
- package/dist/types/api/base/flowSubscribable.d.ts +79 -0
- package/dist/types/api/base/flowSubscribable.d.ts.map +1 -0
- package/dist/types/api/base/flowTracker.d.ts +8 -0
- package/dist/types/api/base/flowTracker.d.ts.map +1 -0
- package/dist/types/api/base/index.d.ts +5 -0
- package/dist/types/api/base/index.d.ts.map +1 -0
- package/dist/types/api/index.d.ts +3 -0
- package/dist/types/api/index.d.ts.map +1 -0
- package/dist/types/api/nodes/async/flowConstantAsync.d.ts +31 -0
- package/dist/types/api/nodes/async/flowConstantAsync.d.ts.map +1 -0
- package/dist/types/api/nodes/async/flowDerivationAsync.d.ts +37 -0
- package/dist/types/api/nodes/async/flowDerivationAsync.d.ts.map +1 -0
- package/dist/types/api/nodes/async/flowStateAsync.d.ts +41 -0
- package/dist/types/api/nodes/async/flowStateAsync.d.ts.map +1 -0
- package/dist/types/api/nodes/async/flowWritableDerivationAsync.d.ts +30 -0
- package/dist/types/api/nodes/async/flowWritableDerivationAsync.d.ts.map +1 -0
- package/dist/types/{flow → api}/nodes/async/index.d.ts +1 -2
- package/dist/types/api/nodes/async/index.d.ts.map +1 -0
- package/dist/types/api/nodes/collections/flowArray.d.ts +134 -0
- package/dist/types/api/nodes/collections/flowArray.d.ts.map +1 -0
- package/dist/types/api/nodes/collections/flowMap.d.ts +98 -0
- package/dist/types/api/nodes/collections/flowMap.d.ts.map +1 -0
- package/dist/types/api/nodes/collections/index.d.ts.map +1 -0
- package/dist/types/api/nodes/flowEffect.d.ts +28 -0
- package/dist/types/api/nodes/flowEffect.d.ts.map +1 -0
- package/dist/types/api/nodes/flowSignal.d.ts +25 -0
- package/dist/types/api/nodes/flowSignal.d.ts.map +1 -0
- package/dist/types/api/nodes/flowValue.d.ts +35 -0
- package/dist/types/api/nodes/flowValue.d.ts.map +1 -0
- package/dist/types/api/nodes/index.d.ts +8 -0
- package/dist/types/api/nodes/index.d.ts.map +1 -0
- package/dist/types/api/nodes/sync/flowConstant.d.ts +29 -0
- package/dist/types/api/nodes/sync/flowConstant.d.ts.map +1 -0
- package/dist/types/api/nodes/sync/flowDerivation.d.ts +36 -0
- package/dist/types/api/nodes/sync/flowDerivation.d.ts.map +1 -0
- package/dist/types/api/nodes/sync/flowState.d.ts +39 -0
- package/dist/types/api/nodes/sync/flowState.d.ts.map +1 -0
- package/dist/types/api/nodes/sync/flowWritableDerivation.d.ts +28 -0
- package/dist/types/api/nodes/sync/flowWritableDerivation.d.ts.map +1 -0
- package/dist/types/{flow → api}/nodes/sync/index.d.ts +1 -2
- package/dist/types/api/nodes/sync/index.d.ts.map +1 -0
- package/dist/types/api/nodes/utils.d.ts +22 -0
- package/dist/types/api/nodes/utils.d.ts.map +1 -0
- package/dist/types/base/disposable.d.ts +11 -0
- package/dist/types/base/disposable.d.ts.map +1 -0
- package/dist/types/base/executionStack.d.ts +14 -0
- package/dist/types/base/executionStack.d.ts.map +1 -0
- package/dist/types/base/index.d.ts +6 -0
- package/dist/types/base/index.d.ts.map +1 -0
- package/dist/types/base/node.d.ts +27 -0
- package/dist/types/base/node.d.ts.map +1 -0
- package/dist/types/base/observable.d.ts +37 -0
- package/dist/types/base/observable.d.ts.map +1 -0
- package/dist/types/base/observer.d.ts +25 -0
- package/dist/types/base/observer.d.ts.map +1 -0
- package/dist/types/converters/index.d.ts +2 -0
- package/dist/types/converters/index.d.ts.map +1 -0
- package/dist/types/converters/solid.d.ts +46 -0
- package/dist/types/converters/solid.d.ts.map +1 -0
- package/dist/types/index.d.ts +2 -63
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/nodes/arrayNode.d.ts +2 -0
- package/dist/types/nodes/arrayNode.d.ts.map +1 -0
- package/dist/types/nodes/effectNode.d.ts +2 -0
- package/dist/types/nodes/effectNode.d.ts.map +1 -0
- package/dist/types/nodes/index.d.ts +9 -0
- package/dist/types/nodes/index.d.ts.map +1 -0
- package/dist/types/nodes/mapNode.d.ts +2 -0
- package/dist/types/nodes/mapNode.d.ts.map +1 -0
- package/dist/types/nodes/signalNode.d.ts +2 -0
- package/dist/types/nodes/signalNode.d.ts.map +1 -0
- package/dist/types/nodes/valueAsyncNode.d.ts +2 -0
- package/dist/types/nodes/valueAsyncNode.d.ts.map +1 -0
- package/dist/types/nodes/valueNode.d.ts +2 -0
- package/dist/types/nodes/valueNode.d.ts.map +1 -0
- package/dist/types/nodes/valueSyncNode.d.ts +2 -0
- package/dist/types/nodes/valueSyncNode.d.ts.map +1 -0
- package/dist/types/schedulers/asyncResolver.d.ts +2 -0
- package/dist/types/schedulers/asyncResolver.d.ts.map +1 -0
- package/dist/types/schedulers/asyncScheduler.d.ts +2 -0
- package/dist/types/schedulers/asyncScheduler.d.ts.map +1 -0
- package/dist/types/schedulers/index.d.ts +5 -0
- package/dist/types/schedulers/index.d.ts.map +1 -0
- package/dist/types/schedulers/pendingError.d.ts +2 -0
- package/dist/types/schedulers/pendingError.d.ts.map +1 -0
- package/dist/types/schedulers/scheduler.d.ts +2 -0
- package/dist/types/schedulers/scheduler.d.ts.map +1 -0
- package/dist/types/schedulers/syncResolver.d.ts +2 -0
- package/dist/types/schedulers/syncResolver.d.ts.map +1 -0
- package/dist/types/schedulers/syncScheduler.d.ts +2 -0
- package/dist/types/schedulers/syncScheduler.d.ts.map +1 -0
- package/docs/.vitepress/config.mts +128 -93
- package/docs/api/functions/array.md +14 -37
- package/docs/api/functions/constant.md +13 -25
- package/docs/api/functions/constantAsync.md +69 -0
- package/docs/api/functions/derivation.md +14 -33
- package/docs/api/functions/derivationAsync.md +34 -0
- package/docs/api/functions/from.md +62 -153
- package/docs/api/functions/isDisposable.md +8 -30
- package/docs/api/functions/map.md +15 -36
- package/docs/api/functions/signal.md +8 -23
- package/docs/api/functions/state.md +43 -23
- package/docs/api/functions/stateAsync.md +69 -0
- package/docs/api/functions/subscribe.md +40 -0
- package/docs/api/functions/writableDerivation.md +33 -0
- package/docs/api/functions/writableDerivationAsync.md +34 -0
- package/docs/api/index.md +45 -102
- package/docs/api/interfaces/FlowArray.md +439 -0
- package/docs/api/interfaces/FlowConstant.md +220 -0
- package/docs/api/interfaces/FlowConstantAsync.md +221 -0
- package/docs/api/interfaces/FlowDerivation.md +241 -0
- package/docs/api/interfaces/FlowDerivationAsync.md +242 -0
- package/docs/api/interfaces/FlowDisposable.md +32 -38
- package/docs/api/interfaces/FlowEffect.md +64 -0
- package/docs/api/interfaces/FlowMap.md +374 -0
- package/docs/api/interfaces/FlowObservable.md +155 -0
- package/docs/api/interfaces/FlowSignal.md +156 -0
- package/docs/api/interfaces/FlowState.md +269 -0
- package/docs/api/interfaces/FlowStateAsync.md +268 -0
- package/docs/api/interfaces/FlowSubscribable.md +55 -0
- package/docs/api/interfaces/FlowTracker.md +61 -0
- package/docs/api/interfaces/FlowValue.md +222 -0
- package/docs/api/interfaces/FlowWritableDerivation.md +292 -0
- package/docs/api/interfaces/FlowWritableDerivationAsync.md +293 -0
- package/docs/api/type-aliases/DerivationFunction.md +28 -0
- package/docs/api/type-aliases/DerivationFunctionAsync.md +28 -0
- package/docs/api/type-aliases/FlowArrayAction.md +19 -8
- package/docs/api/type-aliases/FlowDataTracker.md +33 -0
- package/docs/api/type-aliases/FlowMapAction.md +48 -0
- package/docs/api/type-aliases/FlowOnDataListener.md +33 -0
- package/docs/api/type-aliases/FlowOnErrorListener.md +27 -0
- package/docs/api/type-aliases/FlowOnPendingListener.md +21 -0
- package/docs/api/type-aliases/FlowReadonly.md +22 -0
- package/docs/api/type-aliases/InitFunction.md +21 -0
- package/docs/api/type-aliases/InitFunctionAsync.md +21 -0
- package/docs/api/type-aliases/NotPromise.md +6 -3
- package/docs/api/type-aliases/UpdateFunction.md +27 -0
- package/docs/api/type-aliases/UpdateFunctionAsync.md +27 -0
- package/docs/api/typedoc-sidebar.json +1 -81
- package/docs/examples/examples.md +0 -2
- package/docs/guide/advanced/architecture.md +1234 -0
- package/docs/guide/advanced/migration-v2.md +204 -0
- package/docs/guide/advanced/solidjs.md +2 -88
- package/docs/guide/introduction/concepts.md +4 -3
- package/docs/guide/introduction/conventions.md +2 -33
- package/docs/guide/introduction/getting-started.md +28 -23
- package/docs/guide/introduction/lifecycle.md +16 -19
- package/docs/guide/primitives/array.md +102 -216
- package/docs/guide/primitives/constant.md +39 -212
- package/docs/guide/primitives/derivations.md +55 -122
- package/docs/guide/primitives/effects.md +155 -241
- package/docs/guide/primitives/map.md +64 -186
- package/docs/guide/primitives/overview.md +45 -128
- package/docs/guide/primitives/signal.md +51 -88
- package/docs/guide/primitives/state.md +34 -130
- package/package.json +56 -60
- package/src/api/base/flowDisposable.ts +44 -0
- package/src/api/base/flowObservable.ts +28 -0
- package/src/api/base/flowSubscribable.ts +87 -0
- package/src/api/base/flowTracker.ts +7 -0
- package/src/api/base/index.ts +4 -0
- package/src/{flow → api}/index.ts +0 -1
- package/src/api/nodes/async/flowConstantAsync.ts +36 -0
- package/src/api/nodes/async/flowDerivationAsync.ts +42 -0
- package/src/api/nodes/async/flowStateAsync.ts +47 -0
- package/src/api/nodes/async/flowWritableDerivationAsync.ts +33 -0
- package/src/{flow → api}/nodes/async/index.ts +1 -2
- package/src/api/nodes/collections/flowArray.ts +155 -0
- package/src/api/nodes/collections/flowMap.ts +115 -0
- package/src/api/nodes/flowEffect.ts +42 -0
- package/src/api/nodes/flowSignal.ts +28 -0
- package/src/api/nodes/flowValue.ts +36 -0
- package/src/api/nodes/index.ts +7 -0
- package/src/api/nodes/sync/flowConstant.ts +33 -0
- package/src/api/nodes/sync/flowDerivation.ts +41 -0
- package/src/api/nodes/sync/flowState.ts +45 -0
- package/src/api/nodes/sync/flowWritableDerivation.ts +31 -0
- package/src/{flow → api}/nodes/sync/index.ts +1 -2
- package/src/api/nodes/utils.ts +22 -0
- package/src/base/disposable.ts +18 -0
- package/src/base/executionStack.ts +42 -0
- package/src/base/index.ts +5 -0
- package/src/base/node.ts +98 -0
- package/src/base/observable.ts +87 -0
- package/src/base/observer.ts +51 -0
- package/src/converters/index.ts +1 -0
- package/src/converters/solid.ts +109 -0
- package/src/index.ts +2 -64
- package/src/nodes/arrayNode.ts +172 -0
- package/src/nodes/effectNode.ts +59 -0
- package/src/nodes/index.ts +8 -0
- package/src/nodes/mapNode.ts +127 -0
- package/src/nodes/signalNode.ts +21 -0
- package/src/nodes/valueAsyncNode.ts +88 -0
- package/src/nodes/valueNode.ts +144 -0
- package/src/nodes/valueSyncNode.ts +128 -0
- package/src/schedulers/asyncResolver.ts +78 -0
- package/src/schedulers/asyncScheduler.ts +66 -0
- package/src/schedulers/index.ts +4 -0
- package/src/schedulers/pendingError.ts +13 -0
- package/src/schedulers/scheduler.ts +9 -0
- package/src/schedulers/syncResolver.ts +69 -0
- package/src/schedulers/syncScheduler.ts +55 -0
- package/test/base/pendingError.test.ts +67 -0
- package/test/converters/solid.derivation.browser.test.tsx +69 -0
- package/test/converters/solid.node.test.ts +654 -0
- package/test/converters/solid.state.browser.test.tsx +1592 -0
- package/test/reactivity/flowSignal.test.ts +226 -0
- package/test/reactivity/nodes/async/asyncScheduler/asyncResolver.test.ts +593 -0
- package/test/reactivity/nodes/async/asyncScheduler/asyncScheduler.test.ts +317 -0
- package/test/reactivity/nodes/async/flowConstantAsync.test.ts +652 -0
- package/test/reactivity/nodes/async/flowDerivation.test.ts +898 -0
- package/test/reactivity/nodes/async/flowDerivationAsync.test.ts +1716 -0
- package/test/reactivity/nodes/async/flowStateAsync.test.ts +708 -0
- package/test/reactivity/nodes/async/flowWritableDerivationAsync.test.ts +614 -0
- package/test/reactivity/nodes/collections/flowArray.asyncStates.test.ts +1289 -0
- package/test/reactivity/nodes/collections/flowArray.scalars.test.ts +961 -0
- package/test/reactivity/nodes/collections/flowArray.states.test.ts +1035 -0
- package/test/reactivity/nodes/collections/flowMap.asyncStates.test.ts +960 -0
- package/test/reactivity/nodes/collections/flowMap.scalars.test.ts +775 -0
- package/test/reactivity/nodes/collections/flowMap.states.test.ts +958 -0
- package/test/reactivity/nodes/sync/flowConstant.test.ts +377 -0
- package/test/reactivity/nodes/sync/flowDerivation.test.ts +896 -0
- package/test/reactivity/nodes/sync/flowState.test.ts +341 -0
- package/test/reactivity/nodes/sync/flowWritableDerivation.test.ts +603 -0
- package/test/vitest.d.ts +10 -0
- package/tsconfig.json +31 -20
- package/typedoc.json +35 -35
- package/vite.config.ts +25 -23
- package/vitest.browser.config.ts +21 -0
- package/vitest.config.ts +12 -12
- package/.cursor/plans/unifier-flowresource-avec-flowderivation-c9506e24.plan.md +0 -372
- package/.cursor/plans/update-js-e795d61b.plan.md +0 -567
- package/dist/types/flow/base/flowDisposable.d.ts +0 -67
- package/dist/types/flow/base/flowDisposable.d.ts.map +0 -1
- package/dist/types/flow/base/flowEffect.d.ts +0 -127
- package/dist/types/flow/base/flowEffect.d.ts.map +0 -1
- package/dist/types/flow/base/flowGraph.d.ts +0 -97
- package/dist/types/flow/base/flowGraph.d.ts.map +0 -1
- package/dist/types/flow/base/flowSignal.d.ts +0 -134
- package/dist/types/flow/base/flowSignal.d.ts.map +0 -1
- package/dist/types/flow/base/flowTracker.d.ts +0 -15
- package/dist/types/flow/base/flowTracker.d.ts.map +0 -1
- package/dist/types/flow/base/index.d.ts +0 -7
- package/dist/types/flow/base/index.d.ts.map +0 -1
- package/dist/types/flow/base/utils.d.ts +0 -20
- package/dist/types/flow/base/utils.d.ts.map +0 -1
- package/dist/types/flow/collections/flowArray.d.ts +0 -148
- package/dist/types/flow/collections/flowArray.d.ts.map +0 -1
- package/dist/types/flow/collections/flowMap.d.ts +0 -224
- package/dist/types/flow/collections/flowMap.d.ts.map +0 -1
- package/dist/types/flow/collections/index.d.ts.map +0 -1
- package/dist/types/flow/index.d.ts +0 -4
- package/dist/types/flow/index.d.ts.map +0 -1
- package/dist/types/flow/nodes/async/flowConstantAsync.d.ts +0 -137
- package/dist/types/flow/nodes/async/flowConstantAsync.d.ts.map +0 -1
- package/dist/types/flow/nodes/async/flowDerivationAsync.d.ts +0 -137
- package/dist/types/flow/nodes/async/flowDerivationAsync.d.ts.map +0 -1
- package/dist/types/flow/nodes/async/flowNodeAsync.d.ts +0 -343
- package/dist/types/flow/nodes/async/flowNodeAsync.d.ts.map +0 -1
- package/dist/types/flow/nodes/async/flowReadonlyAsync.d.ts +0 -81
- package/dist/types/flow/nodes/async/flowReadonlyAsync.d.ts.map +0 -1
- package/dist/types/flow/nodes/async/flowStateAsync.d.ts +0 -111
- package/dist/types/flow/nodes/async/flowStateAsync.d.ts.map +0 -1
- package/dist/types/flow/nodes/async/index.d.ts.map +0 -1
- package/dist/types/flow/nodes/index.d.ts +0 -3
- package/dist/types/flow/nodes/index.d.ts.map +0 -1
- package/dist/types/flow/nodes/sync/flowConstant.d.ts +0 -108
- package/dist/types/flow/nodes/sync/flowConstant.d.ts.map +0 -1
- package/dist/types/flow/nodes/sync/flowDerivation.d.ts +0 -100
- package/dist/types/flow/nodes/sync/flowDerivation.d.ts.map +0 -1
- package/dist/types/flow/nodes/sync/flowNode.d.ts +0 -314
- package/dist/types/flow/nodes/sync/flowNode.d.ts.map +0 -1
- package/dist/types/flow/nodes/sync/flowReadonly.d.ts +0 -57
- package/dist/types/flow/nodes/sync/flowReadonly.d.ts.map +0 -1
- package/dist/types/flow/nodes/sync/flowState.d.ts +0 -96
- package/dist/types/flow/nodes/sync/flowState.d.ts.map +0 -1
- package/dist/types/flow/nodes/sync/index.d.ts.map +0 -1
- package/dist/types/solid/converters.d.ts +0 -53
- package/dist/types/solid/converters.d.ts.map +0 -1
- package/dist/types/solid/index.d.ts +0 -3
- package/dist/types/solid/index.d.ts.map +0 -1
- package/dist/types/solid/primitives.d.ts +0 -181
- package/dist/types/solid/primitives.d.ts.map +0 -1
- package/docs/api/classes/FlowArray.md +0 -489
- package/docs/api/classes/FlowConstant.md +0 -350
- package/docs/api/classes/FlowDerivation.md +0 -334
- package/docs/api/classes/FlowEffect.md +0 -100
- package/docs/api/classes/FlowMap.md +0 -512
- package/docs/api/classes/FlowObservable.md +0 -306
- package/docs/api/classes/FlowResource.md +0 -380
- package/docs/api/classes/FlowResourceAsync.md +0 -362
- package/docs/api/classes/FlowSignal.md +0 -160
- package/docs/api/classes/FlowState.md +0 -368
- package/docs/api/classes/FlowStream.md +0 -367
- package/docs/api/classes/FlowStreamAsync.md +0 -364
- package/docs/api/classes/SolidDerivation.md +0 -75
- package/docs/api/classes/SolidResource.md +0 -91
- package/docs/api/classes/SolidState.md +0 -71
- package/docs/api/classes/TrackingContext.md +0 -33
- package/docs/api/functions/effect.md +0 -49
- package/docs/api/functions/resource.md +0 -52
- package/docs/api/functions/resourceAsync.md +0 -50
- package/docs/api/functions/stream.md +0 -53
- package/docs/api/functions/streamAsync.md +0 -50
- package/docs/api/interfaces/SolidObservable.md +0 -19
- package/docs/api/type-aliases/FlowStreamDisposer.md +0 -15
- package/docs/api/type-aliases/FlowStreamSetter.md +0 -27
- package/docs/api/type-aliases/FlowStreamUpdater.md +0 -32
- package/docs/api/type-aliases/SolidGetter.md +0 -17
- package/docs/guide/primitives/resources.md +0 -858
- package/docs/guide/primitives/streams.md +0 -931
- package/src/flow/base/flowDisposable.ts +0 -71
- package/src/flow/base/flowEffect.ts +0 -171
- package/src/flow/base/flowGraph.ts +0 -288
- package/src/flow/base/flowSignal.ts +0 -207
- package/src/flow/base/flowTracker.ts +0 -17
- package/src/flow/base/index.ts +0 -6
- package/src/flow/base/utils.ts +0 -19
- package/src/flow/collections/flowArray.ts +0 -409
- package/src/flow/collections/flowMap.ts +0 -398
- package/src/flow/nodes/async/flowConstantAsync.ts +0 -142
- package/src/flow/nodes/async/flowDerivationAsync.ts +0 -143
- package/src/flow/nodes/async/flowNodeAsync.ts +0 -474
- package/src/flow/nodes/async/flowReadonlyAsync.ts +0 -81
- package/src/flow/nodes/async/flowStateAsync.ts +0 -116
- package/src/flow/nodes/await/advanced/index.ts +0 -5
- package/src/flow/nodes/await/advanced/resource.ts +0 -134
- package/src/flow/nodes/await/advanced/resourceAsync.ts +0 -109
- package/src/flow/nodes/await/advanced/stream.ts +0 -188
- package/src/flow/nodes/await/advanced/streamAsync.ts +0 -176
- package/src/flow/nodes/await/flowConstantAwait.ts +0 -154
- package/src/flow/nodes/await/flowDerivationAwait.ts +0 -154
- package/src/flow/nodes/await/flowNodeAwait.ts +0 -508
- package/src/flow/nodes/await/flowReadonlyAwait.ts +0 -89
- package/src/flow/nodes/await/flowStateAwait.ts +0 -130
- package/src/flow/nodes/await/index.ts +0 -5
- package/src/flow/nodes/index.ts +0 -3
- package/src/flow/nodes/sync/flowConstant.ts +0 -111
- package/src/flow/nodes/sync/flowDerivation.ts +0 -105
- package/src/flow/nodes/sync/flowNode.ts +0 -439
- package/src/flow/nodes/sync/flowReadonly.ts +0 -57
- package/src/flow/nodes/sync/flowState.ts +0 -101
- package/src/solid/converters.ts +0 -139
- package/src/solid/index.ts +0 -2
- package/src/solid/primitives.ts +0 -215
- package/test/base/flowEffect.test.ts +0 -108
- package/test/base/flowGraph.test.ts +0 -485
- package/test/base/flowSignal.test.ts +0 -372
- package/test/collections/flowArray.asyncStates.test.ts +0 -1553
- package/test/collections/flowArray.scalars.test.ts +0 -1129
- package/test/collections/flowArray.states.test.ts +0 -1365
- package/test/collections/flowMap.asyncStates.test.ts +0 -1105
- package/test/collections/flowMap.scalars.test.ts +0 -877
- package/test/collections/flowMap.states.test.ts +0 -1097
- package/test/nodes/async/flowConstantAsync.test.ts +0 -860
- package/test/nodes/async/flowDerivationAsync.test.ts +0 -1517
- package/test/nodes/async/flowStateAsync.test.ts +0 -1387
- package/test/nodes/await/advanced/resource.test.ts +0 -129
- package/test/nodes/await/advanced/resourceAsync.test.ts +0 -108
- package/test/nodes/await/advanced/stream.test.ts +0 -198
- package/test/nodes/await/advanced/streamAsync.test.ts +0 -196
- package/test/nodes/await/flowConstantAwait.test.ts +0 -643
- package/test/nodes/await/flowDerivationAwait.test.ts +0 -1583
- package/test/nodes/await/flowStateAwait.test.ts +0 -999
- package/test/nodes/mixed/derivation.test.ts +0 -1527
- package/test/nodes/sync/flowConstant.test.ts +0 -620
- package/test/nodes/sync/flowDerivation.test.ts +0 -1373
- package/test/nodes/sync/flowState.test.ts +0 -945
- package/test/solid/converters.test.ts +0 -721
- package/test/solid/primitives.test.ts +0 -1031
- /package/dist/types/{flow → api/nodes}/collections/index.d.ts +0 -0
- /package/docs/guide/advanced/{upgrading.md → migration-v1.md} +0 -0
- /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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
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.
|
|
180
|
-
$items.add('
|
|
181
|
-
$items.update('
|
|
182
|
-
$items.delete('
|
|
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
|
|
137
|
+
When you create a subscription that tracks a map:
|
|
188
138
|
|
|
189
|
-
1. **Registration**: The map registers the
|
|
190
|
-
2. **Operation**: When you call `add()`, `update()`, or `
|
|
191
|
-
3. **Signal Update**: The
|
|
192
|
-
4. **Notification**: All watching
|
|
193
|
-
5. **Re-execution**: Each watching
|
|
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 $
|
|
200
|
-
participant
|
|
149
|
+
participant Signal as $lastAction
|
|
150
|
+
participant Subscription
|
|
201
151
|
|
|
202
|
-
Note over User,
|
|
203
|
-
User->>
|
|
204
|
-
activate
|
|
205
|
-
|
|
206
|
-
Note over Map: Register
|
|
207
|
-
|
|
208
|
-
Note over Signal: Register
|
|
209
|
-
|
|
210
|
-
Note over
|
|
211
|
-
deactivate
|
|
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,
|
|
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,
|
|
167
|
+
Map->>Signal: "set({ type: 'add', key, addedValue })"
|
|
218
168
|
activate Signal
|
|
219
169
|
Note over Signal: Notify watchers
|
|
220
|
-
Signal->>
|
|
170
|
+
Signal->>Subscription: Schedule execution
|
|
221
171
|
deactivate Signal
|
|
222
172
|
Map->>Map: Notify whole map watchers
|
|
223
|
-
Map->>
|
|
173
|
+
Map->>Subscription: Schedule execution
|
|
224
174
|
deactivate Map
|
|
225
175
|
|
|
226
|
-
activate
|
|
227
|
-
Note over
|
|
228
|
-
|
|
229
|
-
Signal-->>
|
|
230
|
-
|
|
231
|
-
Note over
|
|
232
|
-
deactivate
|
|
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
|
-
|
|
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
|
-
|
|
326
|
-
|
|
327
|
-
|
|
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
|
|
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
|
-
##
|
|
11
|
+
## Primitives
|
|
10
12
|
|
|
11
|
-
PicoFlow provides several reactive primitives
|
|
13
|
+
PicoFlow provides several reactive primitives, each with specific capabilities. Primitive may exist in synchrone and asynchrone flavours.
|
|
12
14
|
|
|
13
|
-
| Primitive |
|
|
14
|
-
|
|
15
|
-
| **Signal** |
|
|
16
|
-
| **State** |
|
|
17
|
-
| **Constant** |
|
|
18
|
-
| **Derivation** |
|
|
19
|
-
| **
|
|
20
|
-
| **
|
|
21
|
-
| **
|
|
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
|
-
##
|
|
25
|
+
## Side Effects
|
|
26
26
|
|
|
27
|
-
|
|
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
|
-
|
|
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((
|
|
81
|
-
console.log('Count is:',
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
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
|
-
|
|
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
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
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
|
-
|
|
61
|
+
### Key features
|
|
149
62
|
|
|
150
|
-
|
|
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
|
|
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 |
|
|
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
|