@ersbeth/picoflow 0.2.3 → 1.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/.cursor/plans/update-js-e795d61b.plan.md +567 -0
- package/.gitlab-ci.yml +24 -0
- package/.vscode/settings.json +3 -3
- package/CHANGELOG.md +51 -0
- package/IMPLEMENTATION_GUIDE.md +1578 -0
- package/README.md +62 -25
- package/biome.json +32 -32
- package/dist/picoflow.js +557 -1099
- package/dist/types/advanced/array.d.ts +0 -6
- package/dist/types/advanced/array.d.ts.map +1 -1
- package/dist/types/advanced/index.d.ts +5 -5
- package/dist/types/advanced/index.d.ts.map +1 -1
- package/dist/types/advanced/map.d.ts +114 -23
- package/dist/types/advanced/map.d.ts.map +1 -1
- package/dist/types/advanced/resource.d.ts +51 -12
- package/dist/types/advanced/resource.d.ts.map +1 -1
- package/dist/types/advanced/resourceAsync.d.ts +28 -13
- package/dist/types/advanced/resourceAsync.d.ts.map +1 -1
- package/dist/types/advanced/stream.d.ts +74 -16
- package/dist/types/advanced/stream.d.ts.map +1 -1
- package/dist/types/advanced/streamAsync.d.ts +69 -15
- package/dist/types/advanced/streamAsync.d.ts.map +1 -1
- package/dist/types/basic/constant.d.ts +44 -16
- package/dist/types/basic/constant.d.ts.map +1 -1
- package/dist/types/basic/derivation.d.ts +73 -24
- package/dist/types/basic/derivation.d.ts.map +1 -1
- package/dist/types/basic/disposable.d.ts +65 -6
- package/dist/types/basic/disposable.d.ts.map +1 -1
- package/dist/types/basic/effect.d.ts +27 -16
- package/dist/types/basic/effect.d.ts.map +1 -1
- package/dist/types/basic/index.d.ts +7 -8
- package/dist/types/basic/index.d.ts.map +1 -1
- package/dist/types/basic/observable.d.ts +62 -13
- package/dist/types/basic/observable.d.ts.map +1 -1
- package/dist/types/basic/signal.d.ts +35 -6
- package/dist/types/basic/signal.d.ts.map +1 -1
- package/dist/types/basic/state.d.ts +25 -4
- package/dist/types/basic/state.d.ts.map +1 -1
- package/dist/types/basic/trackingContext.d.ts +33 -0
- package/dist/types/basic/trackingContext.d.ts.map +1 -0
- package/dist/types/creators.d.ts +271 -26
- package/dist/types/creators.d.ts.map +1 -1
- package/dist/types/index.d.ts +60 -7
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/solid/converters.d.ts +5 -5
- package/dist/types/solid/converters.d.ts.map +1 -1
- package/dist/types/solid/index.d.ts +2 -2
- package/dist/types/solid/index.d.ts.map +1 -1
- package/dist/types/solid/primitives.d.ts +96 -4
- package/dist/types/solid/primitives.d.ts.map +1 -1
- package/docs/.vitepress/config.mts +110 -0
- package/docs/api/classes/FlowArray.md +489 -0
- package/docs/api/classes/FlowConstant.md +350 -0
- package/docs/api/classes/FlowDerivation.md +334 -0
- package/docs/api/classes/FlowEffect.md +100 -0
- package/docs/api/classes/FlowMap.md +512 -0
- package/docs/api/classes/FlowObservable.md +306 -0
- package/docs/api/classes/FlowResource.md +380 -0
- package/docs/api/classes/FlowResourceAsync.md +362 -0
- package/docs/api/classes/FlowSignal.md +160 -0
- package/docs/api/classes/FlowState.md +368 -0
- package/docs/api/classes/FlowStream.md +367 -0
- package/docs/api/classes/FlowStreamAsync.md +364 -0
- package/docs/api/classes/SolidDerivation.md +75 -0
- package/docs/api/classes/SolidResource.md +91 -0
- package/docs/api/classes/SolidState.md +71 -0
- package/docs/api/classes/TrackingContext.md +33 -0
- package/docs/api/functions/array.md +58 -0
- package/docs/api/functions/constant.md +45 -0
- package/docs/api/functions/derivation.md +53 -0
- package/docs/api/functions/effect.md +49 -0
- package/docs/api/functions/from.md +220 -0
- package/docs/api/functions/isDisposable.md +49 -0
- package/docs/api/functions/map.md +57 -0
- package/docs/api/functions/resource.md +52 -0
- package/docs/api/functions/resourceAsync.md +50 -0
- package/docs/api/functions/signal.md +36 -0
- package/docs/api/functions/state.md +47 -0
- package/docs/api/functions/stream.md +53 -0
- package/docs/api/functions/streamAsync.md +50 -0
- package/docs/api/index.md +118 -0
- package/docs/api/interfaces/FlowDisposable.md +65 -0
- package/docs/api/interfaces/SolidObservable.md +19 -0
- package/docs/api/type-aliases/FlowArrayAction.md +49 -0
- package/docs/api/type-aliases/FlowStreamDisposer.md +15 -0
- package/docs/api/type-aliases/FlowStreamSetter.md +27 -0
- package/docs/api/type-aliases/FlowStreamUpdater.md +32 -0
- package/docs/api/type-aliases/NotPromise.md +18 -0
- package/docs/api/type-aliases/SolidGetter.md +17 -0
- package/docs/api/typedoc-sidebar.json +1 -0
- package/docs/examples/examples.md +2313 -0
- package/docs/examples/patterns.md +649 -0
- package/docs/guide/advanced/disposal.md +426 -0
- package/docs/guide/advanced/solidjs.md +221 -0
- package/docs/guide/advanced/upgrading.md +464 -0
- package/docs/guide/introduction/concepts.md +56 -0
- package/docs/guide/introduction/conventions.md +61 -0
- package/docs/guide/introduction/getting-started.md +134 -0
- package/docs/guide/introduction/lifecycle.md +371 -0
- package/docs/guide/primitives/array.md +400 -0
- package/docs/guide/primitives/constant.md +380 -0
- package/docs/guide/primitives/derivations.md +348 -0
- package/docs/guide/primitives/effects.md +458 -0
- package/docs/guide/primitives/map.md +387 -0
- package/docs/guide/primitives/overview.md +175 -0
- package/docs/guide/primitives/resources.md +858 -0
- package/docs/guide/primitives/signal.md +259 -0
- package/docs/guide/primitives/state.md +368 -0
- package/docs/guide/primitives/streams.md +931 -0
- package/docs/index.md +47 -0
- package/docs/public/logo.svg +1 -0
- package/package.json +57 -41
- package/src/advanced/array.ts +208 -210
- package/src/advanced/index.ts +7 -7
- package/src/advanced/map.ts +178 -68
- package/src/advanced/resource.ts +87 -43
- package/src/advanced/resourceAsync.ts +62 -42
- package/src/advanced/stream.ts +113 -50
- package/src/advanced/streamAsync.ts +120 -61
- package/src/basic/constant.ts +82 -49
- package/src/basic/derivation.ts +128 -84
- package/src/basic/disposable.ts +74 -15
- package/src/basic/effect.ts +85 -77
- package/src/basic/index.ts +7 -8
- package/src/basic/observable.ts +94 -36
- package/src/basic/signal.ts +133 -105
- package/src/basic/state.ts +46 -25
- package/src/basic/trackingContext.ts +45 -0
- package/src/creators.ts +297 -54
- package/src/index.ts +96 -43
- package/src/solid/converters.ts +186 -67
- package/src/solid/index.ts +8 -2
- package/src/solid/primitives.ts +167 -65
- package/test/array.test.ts +592 -612
- package/test/constant.test.ts +31 -33
- package/test/derivation.test.ts +531 -536
- package/test/effect.test.ts +21 -21
- package/test/map.test.ts +233 -137
- package/test/resource.test.ts +119 -121
- package/test/resourceAsync.test.ts +98 -100
- package/test/signal.test.ts +51 -55
- package/test/state.test.ts +186 -168
- package/test/stream.test.ts +189 -189
- package/test/streamAsync.test.ts +186 -186
- package/tsconfig.json +19 -18
- package/typedoc.json +37 -0
- package/vite.config.ts +23 -20
- package/vitest.config.ts +7 -7
- package/api/doc/index.md +0 -31
- package/api/doc/picoflow.array.md +0 -55
- package/api/doc/picoflow.constant.md +0 -55
- package/api/doc/picoflow.derivation.md +0 -55
- package/api/doc/picoflow.effect.md +0 -55
- package/api/doc/picoflow.flowarray._constructor_.md +0 -49
- package/api/doc/picoflow.flowarray._lastaction.md +0 -13
- package/api/doc/picoflow.flowarray.clear.md +0 -17
- package/api/doc/picoflow.flowarray.dispose.md +0 -55
- package/api/doc/picoflow.flowarray.get.md +0 -19
- package/api/doc/picoflow.flowarray.length.md +0 -13
- package/api/doc/picoflow.flowarray.md +0 -273
- package/api/doc/picoflow.flowarray.pop.md +0 -17
- package/api/doc/picoflow.flowarray.push.md +0 -53
- package/api/doc/picoflow.flowarray.set.md +0 -53
- package/api/doc/picoflow.flowarray.setitem.md +0 -69
- package/api/doc/picoflow.flowarray.shift.md +0 -17
- package/api/doc/picoflow.flowarray.splice.md +0 -85
- package/api/doc/picoflow.flowarray.unshift.md +0 -53
- package/api/doc/picoflow.flowarrayaction.md +0 -37
- package/api/doc/picoflow.flowconstant._constructor_.md +0 -49
- package/api/doc/picoflow.flowconstant.get.md +0 -25
- package/api/doc/picoflow.flowconstant.md +0 -88
- package/api/doc/picoflow.flowderivation._constructor_.md +0 -49
- package/api/doc/picoflow.flowderivation.get.md +0 -23
- package/api/doc/picoflow.flowderivation.md +0 -86
- package/api/doc/picoflow.flowdisposable.dispose.md +0 -55
- package/api/doc/picoflow.flowdisposable.md +0 -43
- package/api/doc/picoflow.floweffect._constructor_.md +0 -54
- package/api/doc/picoflow.floweffect.dispose.md +0 -21
- package/api/doc/picoflow.floweffect.disposed.md +0 -13
- package/api/doc/picoflow.floweffect.md +0 -131
- package/api/doc/picoflow.flowgetter.md +0 -15
- package/api/doc/picoflow.flowmap._lastdeleted.md +0 -21
- package/api/doc/picoflow.flowmap._lastset.md +0 -21
- package/api/doc/picoflow.flowmap.delete.md +0 -61
- package/api/doc/picoflow.flowmap.md +0 -133
- package/api/doc/picoflow.flowmap.setat.md +0 -77
- package/api/doc/picoflow.flowobservable.get.md +0 -19
- package/api/doc/picoflow.flowobservable.md +0 -68
- package/api/doc/picoflow.flowobservable.subscribe.md +0 -55
- package/api/doc/picoflow.flowresource._constructor_.md +0 -49
- package/api/doc/picoflow.flowresource.fetch.md +0 -27
- package/api/doc/picoflow.flowresource.get.md +0 -23
- package/api/doc/picoflow.flowresource.md +0 -100
- package/api/doc/picoflow.flowresourceasync._constructor_.md +0 -49
- package/api/doc/picoflow.flowresourceasync.fetch.md +0 -27
- package/api/doc/picoflow.flowresourceasync.get.md +0 -23
- package/api/doc/picoflow.flowresourceasync.md +0 -100
- package/api/doc/picoflow.flowsignal.dispose.md +0 -59
- package/api/doc/picoflow.flowsignal.disposed.md +0 -18
- package/api/doc/picoflow.flowsignal.md +0 -112
- package/api/doc/picoflow.flowsignal.trigger.md +0 -21
- package/api/doc/picoflow.flowstate.md +0 -52
- package/api/doc/picoflow.flowstate.set.md +0 -61
- package/api/doc/picoflow.flowstream._constructor_.md +0 -49
- package/api/doc/picoflow.flowstream.dispose.md +0 -21
- package/api/doc/picoflow.flowstream.get.md +0 -23
- package/api/doc/picoflow.flowstream.md +0 -100
- package/api/doc/picoflow.flowstreamasync._constructor_.md +0 -54
- package/api/doc/picoflow.flowstreamasync.dispose.md +0 -21
- package/api/doc/picoflow.flowstreamasync.get.md +0 -23
- package/api/doc/picoflow.flowstreamasync.md +0 -100
- package/api/doc/picoflow.flowstreamdisposer.md +0 -13
- package/api/doc/picoflow.flowstreamsetter.md +0 -13
- package/api/doc/picoflow.flowstreamupdater.md +0 -19
- package/api/doc/picoflow.flowwatcher.md +0 -15
- package/api/doc/picoflow.from.md +0 -55
- package/api/doc/picoflow.from_1.md +0 -55
- package/api/doc/picoflow.from_2.md +0 -55
- package/api/doc/picoflow.from_3.md +0 -55
- package/api/doc/picoflow.from_4.md +0 -55
- package/api/doc/picoflow.from_5.md +0 -55
- package/api/doc/picoflow.isdisposable.md +0 -55
- package/api/doc/picoflow.map.md +0 -59
- package/api/doc/picoflow.md +0 -544
- package/api/doc/picoflow.resource.md +0 -55
- package/api/doc/picoflow.resourceasync.md +0 -55
- package/api/doc/picoflow.signal.md +0 -19
- package/api/doc/picoflow.solidderivation._constructor_.md +0 -49
- package/api/doc/picoflow.solidderivation.get.md +0 -13
- package/api/doc/picoflow.solidderivation.md +0 -94
- package/api/doc/picoflow.solidgetter.md +0 -13
- package/api/doc/picoflow.solidobservable.get.md +0 -13
- package/api/doc/picoflow.solidobservable.md +0 -57
- package/api/doc/picoflow.solidresource._constructor_.md +0 -49
- package/api/doc/picoflow.solidresource.get.md +0 -13
- package/api/doc/picoflow.solidresource.latest.md +0 -13
- package/api/doc/picoflow.solidresource.md +0 -157
- package/api/doc/picoflow.solidresource.refetch.md +0 -13
- package/api/doc/picoflow.solidresource.state.md +0 -13
- package/api/doc/picoflow.solidstate._constructor_.md +0 -49
- package/api/doc/picoflow.solidstate.get.md +0 -13
- package/api/doc/picoflow.solidstate.md +0 -115
- package/api/doc/picoflow.solidstate.set.md +0 -13
- package/api/doc/picoflow.state.md +0 -55
- package/api/doc/picoflow.stream.md +0 -55
- package/api/doc/picoflow.streamasync.md +0 -55
- package/api/picoflow.public.api.md +0 -244
- package/api-extractor.json +0 -61
package/src/advanced/map.ts
CHANGED
|
@@ -1,83 +1,193 @@
|
|
|
1
|
-
import { FlowState } from "../basic/";
|
|
1
|
+
import { FlowState, isDisposable } from "../basic/";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Represents a reactive map
|
|
4
|
+
* Represents a reactive map that extends {@link FlowState} for tracking key-value pairs.
|
|
5
5
|
*
|
|
6
6
|
* @remarks
|
|
7
|
-
* FlowMap wraps a native Map and provides reactive
|
|
8
|
-
*
|
|
9
|
-
* it exposes two reactive signals:
|
|
7
|
+
* FlowMap wraps a native JavaScript Map and provides reactive tracking at multiple granularity levels.
|
|
8
|
+
* Unlike plain reactive state, FlowMap offers fine-grained reactivity that lets you track:
|
|
10
9
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
10
|
+
* 1. **Whole map changes**: Via `get(t)` or `pick()` on the FlowMap itself
|
|
11
|
+
* 2. **Last add operation**: Via the `$lastAdded` signal, track which key-value pair was most recently added
|
|
12
|
+
* 3. **Last update operation**: Via the `$lastUpdated` signal, track which key-value pair was most recently updated
|
|
13
|
+
* 4. **Last delete operation**: Via the `$lastDeleted` signal, track which key-value pair was most recently removed
|
|
13
14
|
*
|
|
14
|
-
*
|
|
15
|
+
* **Reactive Signals:**
|
|
16
|
+
* - **$lastAdded**: A FlowState containing `{ key?: K, value?: V }` updated on each `add()` call
|
|
17
|
+
* - **$lastUpdated**: A FlowState containing `{ key?: K, value?: V }` updated on each `update()` call
|
|
18
|
+
* - **$lastDeleted**: A FlowState containing `{ key?: K, value?: V }` updated on each `delete()` call
|
|
15
19
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
20
|
+
* These signals enable fine-grained reactivity patterns where effects can respond to specific
|
|
21
|
+
* map operations without re-processing the entire map.
|
|
22
|
+
*
|
|
23
|
+
* **Use Cases:**
|
|
24
|
+
* - Entity stores where you want to track additions/removals separately
|
|
25
|
+
* - Cache implementations with granular invalidation
|
|
26
|
+
* - Collections where operations on individual keys matter
|
|
27
|
+
* - UI state where you want to animate specific additions or removals
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```typescript
|
|
31
|
+
* const $users = map<string, User>();
|
|
32
|
+
*
|
|
33
|
+
* // Track the whole map
|
|
34
|
+
* effect((t) => {
|
|
35
|
+
* const users = $users.get(t);
|
|
36
|
+
* console.log(`Total users: ${users.size}`);
|
|
37
|
+
* });
|
|
38
|
+
*
|
|
39
|
+
* // Track only additions
|
|
40
|
+
* effect((t) => {
|
|
41
|
+
* const { key, value } = $users.$lastAdded.get(t);
|
|
42
|
+
* if (key && value) {
|
|
43
|
+
* console.log(`User ${key} was added:`, value);
|
|
44
|
+
* }
|
|
45
|
+
* });
|
|
46
|
+
*
|
|
47
|
+
* // Track only updates
|
|
48
|
+
* effect((t) => {
|
|
49
|
+
* const { key, value } = $users.$lastUpdated.get(t);
|
|
50
|
+
* if (key && value) {
|
|
51
|
+
* console.log(`User ${key} was updated:`, value);
|
|
52
|
+
* }
|
|
53
|
+
* });
|
|
54
|
+
*
|
|
55
|
+
* // Track only deletions
|
|
56
|
+
* effect((t) => {
|
|
57
|
+
* const { key, value } = $users.$lastDeleted.get(t);
|
|
58
|
+
* if (key && value) {
|
|
59
|
+
* console.log(`User ${key} was deleted:`, value);
|
|
60
|
+
* }
|
|
61
|
+
* });
|
|
62
|
+
*
|
|
63
|
+
* // Modify the map
|
|
64
|
+
* $users.add('user1', { name: 'John', age: 30 });
|
|
65
|
+
* $users.add('user2', { name: 'Jane', age: 25 });
|
|
66
|
+
* $users.update('user1', { name: 'John', age: 31 });
|
|
67
|
+
* $users.delete('user1');
|
|
68
|
+
* ```
|
|
69
|
+
*
|
|
70
|
+
* @typeParam K - The type of the map keys.
|
|
71
|
+
* @typeParam V - The type of the map values.
|
|
18
72
|
*
|
|
19
73
|
* @public
|
|
20
74
|
*/
|
|
21
75
|
export class FlowMap<K, V> extends FlowState<Map<K, V>> {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
76
|
+
/**
|
|
77
|
+
* A reactive state that holds the most recent key and value that were added.
|
|
78
|
+
*
|
|
79
|
+
* @remarks
|
|
80
|
+
* When a key is added via {@link FlowMap.add}, this state is updated with
|
|
81
|
+
* the corresponding key and value.
|
|
82
|
+
*
|
|
83
|
+
* @public
|
|
84
|
+
*/
|
|
85
|
+
public $lastAdded = new FlowState<{ key: K; value: V } | null>(null);
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* A reactive state that holds the most recent key and value that were updated.
|
|
89
|
+
*
|
|
90
|
+
* @remarks
|
|
91
|
+
* When a key is updated via {@link FlowMap.update}, this state is updated with
|
|
92
|
+
* the corresponding key and value.
|
|
93
|
+
*
|
|
94
|
+
* @public
|
|
95
|
+
*/
|
|
96
|
+
public $lastUpdated = new FlowState<{ key: K; value: V } | null>(null);
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* A reactive state that holds the most recent key and value that were deleted.
|
|
100
|
+
*
|
|
101
|
+
* @remarks
|
|
102
|
+
* When a key is deleted via {@link FlowMap.delete}, this state is updated with
|
|
103
|
+
* the corresponding key and its last known value.
|
|
104
|
+
*
|
|
105
|
+
* @public
|
|
106
|
+
*/
|
|
107
|
+
public $lastDeleted = new FlowState<{ key: K; value: V } | null>(null);
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Adds a new key-value pair to the map.
|
|
111
|
+
*
|
|
112
|
+
* @param key - The key to add.
|
|
113
|
+
* @param value - The value to associate with the key.
|
|
114
|
+
* @throws If the FlowMap instance is disposed.
|
|
115
|
+
* @throws If the key already exists in the map.
|
|
116
|
+
*
|
|
117
|
+
* @remarks
|
|
118
|
+
* Adds a new entry to the internal map, emits the key-value pair via {@link FlowMap.$lastAdded},
|
|
119
|
+
* and notifies all subscribers of the change.
|
|
120
|
+
*
|
|
121
|
+
* @public
|
|
122
|
+
*/
|
|
123
|
+
public add(key: K, value: V): void {
|
|
124
|
+
if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
|
|
125
|
+
if (this._value.has(key)) {
|
|
126
|
+
throw new Error("[PicoFlow] Key already exists");
|
|
127
|
+
}
|
|
128
|
+
this._value.set(key, value);
|
|
129
|
+
this.$lastAdded.set({ key, value });
|
|
130
|
+
this._notify();
|
|
131
|
+
}
|
|
32
132
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
133
|
+
/**
|
|
134
|
+
* Updates an existing key-value pair in the map.
|
|
135
|
+
*
|
|
136
|
+
* @param key - The key to update.
|
|
137
|
+
* @param value - The new value to associate with the key.
|
|
138
|
+
* @throws If the FlowMap instance is disposed.
|
|
139
|
+
* @throws If the key does not exist in the map.
|
|
140
|
+
*
|
|
141
|
+
* @remarks
|
|
142
|
+
* Updates an existing entry in the internal map, emits the key-value pair via {@link FlowMap.$lastUpdated},
|
|
143
|
+
* and notifies all subscribers of the change.
|
|
144
|
+
*
|
|
145
|
+
* @public
|
|
146
|
+
*/
|
|
147
|
+
public update(key: K, value: V): void {
|
|
148
|
+
if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
|
|
149
|
+
if (!this._value.has(key)) {
|
|
150
|
+
throw new Error("[PicoFlow] Key does not exist");
|
|
151
|
+
}
|
|
152
|
+
this._value.set(key, value);
|
|
153
|
+
this.$lastUpdated.set({ key, value });
|
|
154
|
+
this._notify();
|
|
155
|
+
}
|
|
43
156
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
157
|
+
/**
|
|
158
|
+
* Deletes the value at the specified key from the underlying map.
|
|
159
|
+
*
|
|
160
|
+
* @param key - The key to delete.
|
|
161
|
+
* @throws If the FlowMap instance is disposed.
|
|
162
|
+
*
|
|
163
|
+
* @remarks
|
|
164
|
+
* Removes the key from the internal map, emits the deleted key and its value via {@link FlowMap.$lastDeleted},
|
|
165
|
+
* and notifies all subscribers of the change.
|
|
166
|
+
*
|
|
167
|
+
* @public
|
|
168
|
+
*/
|
|
169
|
+
public delete(key: K): void {
|
|
170
|
+
if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
|
|
171
|
+
const value = this._value.get(key);
|
|
172
|
+
if (!value) throw new Error("[PicoFlow] Key does not exist");
|
|
173
|
+
this._value.delete(key);
|
|
174
|
+
this.$lastDeleted.set({ key, value });
|
|
175
|
+
this._notify();
|
|
176
|
+
}
|
|
63
177
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
this._value.delete(key);
|
|
80
|
-
this.$lastDeleted.set({ key, value });
|
|
81
|
-
this._notify();
|
|
82
|
-
}
|
|
178
|
+
/**
|
|
179
|
+
* Disposes the FlowMap and its values.
|
|
180
|
+
* @param options - Disposal options.
|
|
181
|
+
* @public
|
|
182
|
+
*/
|
|
183
|
+
override dispose(options?: { self: boolean }): void {
|
|
184
|
+
super.dispose(options);
|
|
185
|
+
this._value.forEach((item) => {
|
|
186
|
+
if (isDisposable(item)) item.dispose(options);
|
|
187
|
+
});
|
|
188
|
+
this._value.clear();
|
|
189
|
+
this.$lastAdded.dispose(options);
|
|
190
|
+
this.$lastUpdated.dispose(options);
|
|
191
|
+
this.$lastDeleted.dispose(options);
|
|
192
|
+
}
|
|
83
193
|
}
|
package/src/advanced/resource.ts
CHANGED
|
@@ -1,56 +1,100 @@
|
|
|
1
1
|
import { FlowObservable } from "../basic";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Represents a reactive resource that asynchronously fetches its value
|
|
4
|
+
* Represents a reactive resource that asynchronously fetches its value and returns `T | undefined`.
|
|
5
5
|
*
|
|
6
|
-
* @remarks
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
6
|
+
* @remarks
|
|
7
|
+
* FlowResource extends FlowObservable to manage asynchronous data fetching with reactive updates.
|
|
8
|
+
* Unlike {@link FlowResourceAsync} which always returns a Promise, FlowResource returns the resolved
|
|
9
|
+
* value directly (or `undefined` if not yet fetched), making it more convenient for synchronous access
|
|
10
|
+
* patterns in effects and derivations.
|
|
11
|
+
*
|
|
12
|
+
* **Key Characteristics:**
|
|
13
|
+
* - The value is `undefined` initially, before the first fetch
|
|
14
|
+
* - Call `fetch()` to trigger the asynchronous fetch operation
|
|
15
|
+
* - When fetched, the value is compared to the current value; only different values trigger updates
|
|
16
|
+
* - Reading via `get(t)` or `pick()` returns the current value (possibly `undefined`) without triggering a fetch
|
|
17
|
+
*
|
|
18
|
+
* **Fetch Behavior:**
|
|
19
|
+
* The fetch function is NOT called automatically on construction. You must explicitly call the
|
|
20
|
+
* `fetch()` method to retrieve the resource. This gives you control over when network requests
|
|
21
|
+
* or expensive async operations occur.
|
|
22
|
+
*
|
|
23
|
+
* **Use Cases:**
|
|
24
|
+
* - API data fetching where you want synchronous access to the cached value
|
|
25
|
+
* - Lazy-loaded data that shouldn't fetch on construction
|
|
26
|
+
* - Resources that need manual refresh control
|
|
27
|
+
* - Data that may or may not be available (hence `T | undefined`)
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```typescript
|
|
31
|
+
* const $user = resource(() => fetchUserFromAPI());
|
|
32
|
+
*
|
|
33
|
+
* // Initially undefined
|
|
34
|
+
* console.log($user.pick()); // undefined
|
|
35
|
+
*
|
|
36
|
+
* // Trigger the fetch
|
|
37
|
+
* await $user.fetch();
|
|
38
|
+
* console.log($user.pick()); // { id: 1, name: 'John' }
|
|
39
|
+
*
|
|
40
|
+
* // Use in an effect
|
|
41
|
+
* effect((t) => {
|
|
42
|
+
* const user = $user.get(t);
|
|
43
|
+
* if (user) {
|
|
44
|
+
* console.log(`Hello, ${user.name}`);
|
|
45
|
+
* }
|
|
46
|
+
* });
|
|
47
|
+
*
|
|
48
|
+
* // Refetch to update
|
|
49
|
+
* await $user.fetch();
|
|
50
|
+
* ```
|
|
51
|
+
*
|
|
52
|
+
* @typeParam T - The type of the resource value (not including the undefined case).
|
|
10
53
|
*
|
|
11
54
|
* @public
|
|
12
55
|
*/
|
|
13
56
|
export class FlowResource<T> extends FlowObservable<T | undefined> {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
57
|
+
/**
|
|
58
|
+
* Creates a new FlowResource.
|
|
59
|
+
*
|
|
60
|
+
* @param fetch - An asynchronous function that retrieves the resource's value.
|
|
61
|
+
* This function is not invoked on construction; you must call the `fetch()` method
|
|
62
|
+
* to execute it.
|
|
63
|
+
*
|
|
64
|
+
* @public
|
|
65
|
+
*/
|
|
66
|
+
constructor(fetch: () => Promise<T>) {
|
|
67
|
+
super();
|
|
68
|
+
this._fetch = fetch;
|
|
69
|
+
}
|
|
24
70
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
return this._value;
|
|
34
|
-
}
|
|
71
|
+
/**
|
|
72
|
+
* Internal method to get the raw value.
|
|
73
|
+
* @internal
|
|
74
|
+
*/
|
|
75
|
+
protected _getRaw(): T | undefined {
|
|
76
|
+
if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
|
|
77
|
+
return this._value;
|
|
78
|
+
}
|
|
35
79
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
80
|
+
/**
|
|
81
|
+
* Asynchronously fetches a new value for the resource.
|
|
82
|
+
* @remarks
|
|
83
|
+
* Executes the internal fetch function. If the fetched value differs from the current one,
|
|
84
|
+
* updates the resource's value and notifies subscribers.
|
|
85
|
+
* @returns A Promise that resolves when the fetch operation is complete.
|
|
86
|
+
* @throws Error if the resource is disposed.
|
|
87
|
+
* @public
|
|
88
|
+
*/
|
|
89
|
+
public async fetch(): Promise<void> {
|
|
90
|
+
if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
|
|
91
|
+
const value = await this._fetch();
|
|
92
|
+
if (value === this._value) return;
|
|
93
|
+
this._value = value;
|
|
94
|
+
this._notify();
|
|
95
|
+
}
|
|
52
96
|
|
|
53
|
-
|
|
97
|
+
/* INTERNAL ------------------------------------------------ */
|
|
54
98
|
|
|
55
|
-
|
|
99
|
+
private _fetch: () => Promise<T>;
|
|
56
100
|
}
|
|
@@ -1,57 +1,77 @@
|
|
|
1
1
|
import { FlowObservable } from "../basic/";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Represents a reactive resource that asynchronously fetches its value.
|
|
4
|
+
* Represents a reactive resource that asynchronously fetches its value and always returns a Promise.
|
|
5
5
|
*
|
|
6
6
|
* @remarks
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* are notified.
|
|
7
|
+
* FlowResourceAsync extends FlowObservable and encapsulates an asynchronous fetch function.
|
|
8
|
+
* Unlike {@link FlowResource} which returns `T | undefined`, FlowResourceAsync always returns
|
|
9
|
+
* a `Promise<T>`, making it suitable for async/await patterns.
|
|
11
10
|
*
|
|
12
|
-
*
|
|
11
|
+
* **Key Characteristics:**
|
|
12
|
+
* - The first call to `get()` or `pick()` creates and caches a Promise
|
|
13
|
+
* - Subsequent calls return the same Promise until `fetch()` is called
|
|
14
|
+
* - Calling `fetch()` creates a new Promise and notifies subscribers
|
|
15
|
+
* - The Promise resolves to the fetched value of type T
|
|
16
|
+
*
|
|
17
|
+
* **Lazy Promise Creation:**
|
|
18
|
+
* The fetch function doesn't execute until the resource's value is first accessed.
|
|
19
|
+
* This allows you to define resources without immediately triggering network requests.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* const $user = resourceAsync(() => fetchUserFromAPI());
|
|
24
|
+
*
|
|
25
|
+
* effect(async (t) => {
|
|
26
|
+
* const user = await $user.get(t); // Tracked, effect re-runs on fetch()
|
|
27
|
+
* console.log(user.name);
|
|
28
|
+
* });
|
|
29
|
+
*
|
|
30
|
+
* // Trigger a refetch
|
|
31
|
+
* await $user.fetch();
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* @typeParam T - The type of the resource value (not the Promise itself).
|
|
13
35
|
*
|
|
14
36
|
* @public
|
|
15
37
|
*/
|
|
16
38
|
export class FlowResourceAsync<T> extends FlowObservable<Promise<T>> {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
39
|
+
/**
|
|
40
|
+
* Creates a new FlowResource.
|
|
41
|
+
* @param fetch - An asynchronous function that retrieves the resource's value.
|
|
42
|
+
* @public
|
|
43
|
+
*/
|
|
44
|
+
constructor(fetch: () => Promise<T>) {
|
|
45
|
+
super();
|
|
46
|
+
this._fetch = fetch;
|
|
47
|
+
}
|
|
26
48
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
return this._value;
|
|
37
|
-
}
|
|
49
|
+
/**
|
|
50
|
+
* Internal method to get the raw value.
|
|
51
|
+
* @internal
|
|
52
|
+
*/
|
|
53
|
+
protected _getRaw(): Promise<T> {
|
|
54
|
+
if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
|
|
55
|
+
if (!this._value) this._value = this._fetch();
|
|
56
|
+
return this._value;
|
|
57
|
+
}
|
|
38
58
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
59
|
+
/**
|
|
60
|
+
* Asynchronously fetches a new value for the resource.
|
|
61
|
+
* @remarks
|
|
62
|
+
* Executes the internal fetch function. If the fetched value differs from the current one,
|
|
63
|
+
* updates the resource's value and notifies subscribers.
|
|
64
|
+
* @returns A Promise that resolves when the fetch operation is complete.
|
|
65
|
+
* @throws Error if the resource is disposed.
|
|
66
|
+
* @public
|
|
67
|
+
*/
|
|
68
|
+
public async fetch(): Promise<void> {
|
|
69
|
+
if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
|
|
70
|
+
this._value = this._fetch();
|
|
71
|
+
this._notify();
|
|
72
|
+
}
|
|
53
73
|
|
|
54
|
-
|
|
74
|
+
/* INTERNAL ------------------------------------------------ */
|
|
55
75
|
|
|
56
|
-
|
|
76
|
+
private _fetch: () => Promise<T>;
|
|
57
77
|
}
|