@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/dist/picoflow.js
CHANGED
|
@@ -1,3 +1,88 @@
|
|
|
1
|
+
import { createMemo, createResource, createSignal, onMount, onCleanup } from 'solid-js';
|
|
2
|
+
|
|
3
|
+
class TrackingContext {
|
|
4
|
+
/** @internal */
|
|
5
|
+
constructor(_owner) {
|
|
6
|
+
this._owner = _owner;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Registers a dependency on the given signal.
|
|
10
|
+
* @internal
|
|
11
|
+
*/
|
|
12
|
+
/** @internal */
|
|
13
|
+
_registerDependency(signal) {
|
|
14
|
+
this._owner._registerDependency(signal);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
class FlowEffect {
|
|
19
|
+
/**
|
|
20
|
+
* Creates a new FlowEffect.
|
|
21
|
+
*
|
|
22
|
+
* @param apply - A side-effect function that receives a tracking context to
|
|
23
|
+
* access and register dependencies on reactive observables and signals.
|
|
24
|
+
*
|
|
25
|
+
* @remarks
|
|
26
|
+
* The provided function is executed immediately upon construction with a tracking context.
|
|
27
|
+
* Use the context parameter to call `.get(t)` on observables you want to track, or `.pick()`
|
|
28
|
+
* on observables you want to read without creating dependencies.
|
|
29
|
+
*
|
|
30
|
+
* @public
|
|
31
|
+
*/
|
|
32
|
+
constructor(apply) {
|
|
33
|
+
this._trackedContext = new TrackingContext(this);
|
|
34
|
+
this._apply = apply;
|
|
35
|
+
this._exec();
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Disposes the effect, unregistering all its tracked dependencies.
|
|
39
|
+
*
|
|
40
|
+
* @remarks
|
|
41
|
+
* Once disposed, the effect must no longer be used. Trying to dispose an effect
|
|
42
|
+
* that is already disposed will throw an error.
|
|
43
|
+
*
|
|
44
|
+
* @public
|
|
45
|
+
*/
|
|
46
|
+
dispose() {
|
|
47
|
+
if (this._disposed) throw new Error("[PicoFlow] Effect is disposed");
|
|
48
|
+
Array.from(this._dependencies).forEach((dependency) => {
|
|
49
|
+
this._unregisterDependency(dependency);
|
|
50
|
+
});
|
|
51
|
+
this._disposed = true;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Indicates whether this effect has been disposed.
|
|
55
|
+
*
|
|
56
|
+
* @returns A boolean value that is true if the effect is disposed, false otherwise.
|
|
57
|
+
*
|
|
58
|
+
* @public
|
|
59
|
+
*/
|
|
60
|
+
get disposed() {
|
|
61
|
+
return this._disposed;
|
|
62
|
+
}
|
|
63
|
+
/* INTERNAL ------------------------------------------------------------ */
|
|
64
|
+
_disposed = false;
|
|
65
|
+
_dependencies = /* @__PURE__ */ new Set();
|
|
66
|
+
_trackedContext;
|
|
67
|
+
_apply;
|
|
68
|
+
/** @internal */
|
|
69
|
+
_exec() {
|
|
70
|
+
if (this._disposed)
|
|
71
|
+
throw new Error("[PicoFlow] Effect is disposed");
|
|
72
|
+
this._apply(this._trackedContext);
|
|
73
|
+
}
|
|
74
|
+
/** @internal */
|
|
75
|
+
_registerDependency(dependency) {
|
|
76
|
+
this._dependencies.add(dependency);
|
|
77
|
+
dependency._registerEffect(this);
|
|
78
|
+
}
|
|
79
|
+
/** @internal */
|
|
80
|
+
_unregisterDependency(dependency) {
|
|
81
|
+
this._dependencies.delete(dependency);
|
|
82
|
+
dependency._unregisterEffect(this);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
1
86
|
class FlowSignal {
|
|
2
87
|
/**
|
|
3
88
|
* Triggers the FlowSignal.
|
|
@@ -9,6 +94,43 @@ class FlowSignal {
|
|
|
9
94
|
if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
|
|
10
95
|
this._notify();
|
|
11
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* Watches the signal, registering it as a dependency in the tracking context.
|
|
99
|
+
*
|
|
100
|
+
* @param context - The tracking context in which to register this signal as a dependency.
|
|
101
|
+
*
|
|
102
|
+
* @remarks
|
|
103
|
+
* Use `watch()` when you want to track a signal without reading its value (signals don't
|
|
104
|
+
* have values to read). This is useful for triggering effects based on signal events
|
|
105
|
+
* without needing associated data.
|
|
106
|
+
*
|
|
107
|
+
* When the signal is triggered via `trigger()`, any effects or derivations that have
|
|
108
|
+
* watched this signal will automatically re-execute.
|
|
109
|
+
*
|
|
110
|
+
* This method must be called within an effect or derivation context where a TrackingContext
|
|
111
|
+
* is available. For observables (which hold values), use `.get(t)` instead, which both
|
|
112
|
+
* reads the value and watches for changes.
|
|
113
|
+
*
|
|
114
|
+
* @throws Error if the signal has been disposed.
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* ```typescript
|
|
118
|
+
* const $signal = signal();
|
|
119
|
+
*
|
|
120
|
+
* effect((t) => {
|
|
121
|
+
* $signal.watch(t); // Track the signal
|
|
122
|
+
* console.log('Signal triggered!');
|
|
123
|
+
* });
|
|
124
|
+
*
|
|
125
|
+
* $signal.trigger(); // Logs: "Signal triggered!"
|
|
126
|
+
* ```
|
|
127
|
+
*
|
|
128
|
+
* @public
|
|
129
|
+
*/
|
|
130
|
+
watch(context) {
|
|
131
|
+
if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
|
|
132
|
+
context._registerDependency(this);
|
|
133
|
+
}
|
|
12
134
|
/**
|
|
13
135
|
* Disposes the FlowSignal.
|
|
14
136
|
* Cleans up all registered effects, listeners, and dependencies.
|
|
@@ -19,17 +141,19 @@ class FlowSignal {
|
|
|
19
141
|
dispose(options) {
|
|
20
142
|
if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
|
|
21
143
|
if (options?.self) {
|
|
22
|
-
Array.from(this._effects).forEach(
|
|
23
|
-
|
|
24
|
-
);
|
|
25
|
-
Array.from(this._listeners).forEach(
|
|
26
|
-
|
|
27
|
-
);
|
|
144
|
+
Array.from(this._effects).forEach((effect) => {
|
|
145
|
+
effect._unregisterDependency(this);
|
|
146
|
+
});
|
|
147
|
+
Array.from(this._listeners).forEach((listener) => {
|
|
148
|
+
listener._unregisterDependency(this);
|
|
149
|
+
});
|
|
28
150
|
} else {
|
|
29
|
-
Array.from(this._effects).forEach((effect) =>
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
)
|
|
151
|
+
Array.from(this._effects).forEach((effect) => {
|
|
152
|
+
effect.dispose();
|
|
153
|
+
});
|
|
154
|
+
Array.from(this._listeners).forEach((listener) => {
|
|
155
|
+
listener.dispose();
|
|
156
|
+
});
|
|
33
157
|
}
|
|
34
158
|
Array.from(this._dependencies).forEach((dependency) => {
|
|
35
159
|
this._unregisterDependency(dependency);
|
|
@@ -45,141 +169,115 @@ class FlowSignal {
|
|
|
45
169
|
return this._disposed;
|
|
46
170
|
}
|
|
47
171
|
/* INTERNAL ------------------------------------------------------------- */
|
|
48
|
-
|
|
172
|
+
/** @internal */
|
|
49
173
|
_disposed = false;
|
|
50
|
-
|
|
174
|
+
/** @internal */
|
|
51
175
|
_dependencies = /* @__PURE__ */ new Set();
|
|
52
|
-
|
|
176
|
+
/** @internal */
|
|
53
177
|
_listeners = /* @__PURE__ */ new Set();
|
|
54
|
-
|
|
178
|
+
/** @internal */
|
|
55
179
|
_effects = /* @__PURE__ */ new Set();
|
|
56
|
-
|
|
57
|
-
_watch() {
|
|
58
|
-
if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
|
|
59
|
-
}
|
|
60
|
-
/*@internal*/
|
|
180
|
+
/** @internal */
|
|
61
181
|
_notify() {
|
|
62
|
-
this._listeners.forEach((listener) =>
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
this._watch();
|
|
182
|
+
this._listeners.forEach((listener) => {
|
|
183
|
+
listener._notify();
|
|
184
|
+
});
|
|
185
|
+
this._effects.forEach((effect) => {
|
|
186
|
+
effect._exec();
|
|
187
|
+
});
|
|
69
188
|
}
|
|
70
|
-
|
|
189
|
+
/** @internal */
|
|
71
190
|
_registerDependency(dependency) {
|
|
72
191
|
this._dependencies.add(dependency);
|
|
73
192
|
dependency._registerListener(this);
|
|
74
193
|
}
|
|
75
|
-
|
|
194
|
+
/** @internal */
|
|
76
195
|
_unregisterDependency(dependency) {
|
|
77
196
|
this._dependencies.delete(dependency);
|
|
78
197
|
dependency._unregisterListener(this);
|
|
79
198
|
}
|
|
80
|
-
|
|
199
|
+
/** @internal */
|
|
81
200
|
_registerListener(signal) {
|
|
82
201
|
this._listeners.add(signal);
|
|
83
202
|
}
|
|
84
|
-
|
|
203
|
+
/** @internal */
|
|
85
204
|
_unregisterListener(signal) {
|
|
86
205
|
this._listeners.delete(signal);
|
|
87
206
|
}
|
|
88
|
-
|
|
207
|
+
/** @internal */
|
|
89
208
|
_registerEffect(effect) {
|
|
90
209
|
this._effects.add(effect);
|
|
91
210
|
}
|
|
92
|
-
|
|
211
|
+
/** @internal */
|
|
93
212
|
_unregisterEffect(effect) {
|
|
94
213
|
this._effects.delete(effect);
|
|
95
214
|
}
|
|
96
215
|
}
|
|
97
216
|
|
|
98
|
-
class
|
|
217
|
+
class FlowObservable extends FlowSignal {
|
|
99
218
|
/**
|
|
100
|
-
*
|
|
219
|
+
* Gets the current value with optional dependency tracking.
|
|
101
220
|
*
|
|
102
|
-
* @param
|
|
103
|
-
*
|
|
221
|
+
* @param context - The tracking context for reactive tracking, or null for untracked access.
|
|
222
|
+
* When a context is provided, this observable is registered as a dependency. When null,
|
|
223
|
+
* the value is read without any tracking.
|
|
224
|
+
*
|
|
225
|
+
* @returns The current value of type T.
|
|
104
226
|
*
|
|
105
227
|
* @remarks
|
|
106
|
-
*
|
|
107
|
-
*
|
|
228
|
+
* Use `get(t)` within effects and derivations to create reactive dependencies.
|
|
229
|
+
* Use `get(null)` when you need to read a value without tracking (though `pick()` is more idiomatic).
|
|
230
|
+
*
|
|
231
|
+
* @example
|
|
232
|
+
* ```typescript
|
|
233
|
+
* effect((t) => {
|
|
234
|
+
* const tracked = $state.get(t); // Dependency registered
|
|
235
|
+
* const untracked = $other.get(null); // No dependency
|
|
236
|
+
* });
|
|
237
|
+
* ```
|
|
108
238
|
*
|
|
109
239
|
* @public
|
|
110
240
|
*/
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
241
|
+
get(context) {
|
|
242
|
+
if (context) {
|
|
243
|
+
this.watch(context);
|
|
244
|
+
}
|
|
245
|
+
return this._getRaw();
|
|
115
246
|
}
|
|
116
247
|
/**
|
|
117
|
-
*
|
|
248
|
+
* Gets the current value without any dependency tracking.
|
|
249
|
+
*
|
|
250
|
+
* @returns The current value of type T.
|
|
118
251
|
*
|
|
119
252
|
* @remarks
|
|
120
|
-
*
|
|
121
|
-
*
|
|
253
|
+
* This method is equivalent to calling `get(null)` but provides a more semantic and readable API.
|
|
254
|
+
* Use `pick()` when you want to read a snapshot of the current value without creating a reactive
|
|
255
|
+
* dependency. This is useful for:
|
|
256
|
+
* - Reading initial values
|
|
257
|
+
* - Accessing configuration that shouldn't trigger updates
|
|
258
|
+
* - Mixing tracked and untracked reads in the same effect
|
|
122
259
|
*
|
|
123
|
-
* @
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
Array.from(this._dependencies).forEach((dependency) => {
|
|
128
|
-
this._unregisterDependency(dependency);
|
|
129
|
-
});
|
|
130
|
-
this._disposed = true;
|
|
131
|
-
}
|
|
132
|
-
/**
|
|
133
|
-
* Indicates whether this effect has been disposed.
|
|
260
|
+
* @example
|
|
261
|
+
* ```typescript
|
|
262
|
+
* // Read a snapshot outside reactive context
|
|
263
|
+
* const currentValue = $state.pick();
|
|
134
264
|
*
|
|
135
|
-
*
|
|
265
|
+
* // Mix tracked and untracked reads
|
|
266
|
+
* effect((t) => {
|
|
267
|
+
* const tracked = $reactive.get(t); // Triggers re-runs
|
|
268
|
+
* const snapshot = $config.pick(); // Doesn't trigger re-runs
|
|
269
|
+
* processData(tracked, snapshot);
|
|
270
|
+
* });
|
|
271
|
+
* ```
|
|
136
272
|
*
|
|
137
273
|
* @public
|
|
138
274
|
*/
|
|
139
|
-
|
|
140
|
-
return this.
|
|
141
|
-
}
|
|
142
|
-
/* INTERNAL ------------------------------------------------------------ */
|
|
143
|
-
_disposed = false;
|
|
144
|
-
_initialized = false;
|
|
145
|
-
_dependencies = /* @__PURE__ */ new Set();
|
|
146
|
-
_trackedGet = (observable) => observable._getFrom(this);
|
|
147
|
-
_trackedWatch = (signal) => signal._watchFrom(this);
|
|
148
|
-
_untrackedGet = (observable) => observable.get();
|
|
149
|
-
_untrackedWatch = (signal) => signal._watch();
|
|
150
|
-
_trackedExec;
|
|
151
|
-
_untrackedExec;
|
|
152
|
-
/*@internal*/
|
|
153
|
-
_exec() {
|
|
154
|
-
if (this._disposed)
|
|
155
|
-
throw new Error("[PicoFlow] Effect is disposed");
|
|
156
|
-
if (this._initialized) this._untrackedExec();
|
|
157
|
-
else {
|
|
158
|
-
this._trackedExec();
|
|
159
|
-
this._initialized = true;
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
/*@internal*/
|
|
163
|
-
_registerDependency(dependency) {
|
|
164
|
-
this._dependencies.add(dependency);
|
|
165
|
-
dependency._registerEffect(this);
|
|
166
|
-
}
|
|
167
|
-
/*@internal*/
|
|
168
|
-
_unregisterDependency(dependency) {
|
|
169
|
-
this._dependencies.delete(dependency);
|
|
170
|
-
dependency._unregisterEffect(this);
|
|
275
|
+
pick() {
|
|
276
|
+
return this._getRaw();
|
|
171
277
|
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
class FlowObservable extends FlowSignal {
|
|
175
278
|
/* INTERNAL -------------------------------------------*/
|
|
176
|
-
|
|
279
|
+
/** @internal */
|
|
177
280
|
_value;
|
|
178
|
-
/*@internal*/
|
|
179
|
-
_getFrom(listener) {
|
|
180
|
-
listener._registerDependency(this);
|
|
181
|
-
return this.get();
|
|
182
|
-
}
|
|
183
281
|
/**
|
|
184
282
|
* Subscribes a listener function to changes of the observable.
|
|
185
283
|
* The listener is executed immediately with the current value and on subsequent updates.
|
|
@@ -187,8 +285,8 @@ class FlowObservable extends FlowSignal {
|
|
|
187
285
|
* @returns A disposer function to cancel the subscription.
|
|
188
286
|
*/
|
|
189
287
|
subscribe(listener) {
|
|
190
|
-
const effect = new FlowEffect((
|
|
191
|
-
listener(get(
|
|
288
|
+
const effect = new FlowEffect((t) => {
|
|
289
|
+
listener(this.get(t));
|
|
192
290
|
});
|
|
193
291
|
return () => effect.dispose();
|
|
194
292
|
}
|
|
@@ -198,7 +296,10 @@ class FlowConstant extends FlowObservable {
|
|
|
198
296
|
/**
|
|
199
297
|
* Creates a new FlowConstant instance.
|
|
200
298
|
*
|
|
201
|
-
* @param value - Either a direct value of type T or a function returning a value of type T
|
|
299
|
+
* @param value - Either a direct value of type T or a function returning a value of type T.
|
|
300
|
+
* If a function is provided, it will be invoked lazily on the first value access.
|
|
301
|
+
* If a direct value is provided, it is stored immediately.
|
|
302
|
+
*
|
|
202
303
|
* @public
|
|
203
304
|
*/
|
|
204
305
|
constructor(value) {
|
|
@@ -206,26 +307,20 @@ class FlowConstant extends FlowObservable {
|
|
|
206
307
|
this._initEager(value);
|
|
207
308
|
}
|
|
208
309
|
/**
|
|
209
|
-
*
|
|
210
|
-
*
|
|
211
|
-
* Accessing this method will initialize the value if it has not been computed already.
|
|
212
|
-
* Throws an error if the instance has been disposed or if lazy initialization fails.
|
|
213
|
-
*
|
|
214
|
-
* @returns The cached constant value.
|
|
215
|
-
* @throws Error if the constant is disposed or cannot be initialized.
|
|
216
|
-
* @public
|
|
310
|
+
* Internal method to get the raw value.
|
|
311
|
+
* @internal
|
|
217
312
|
*/
|
|
218
|
-
|
|
313
|
+
_getRaw() {
|
|
219
314
|
if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
|
|
220
315
|
this._initLazy();
|
|
221
316
|
return this._value;
|
|
222
317
|
}
|
|
223
318
|
/* INTERNAL --------------------------------------------------------- */
|
|
224
|
-
|
|
319
|
+
/** @internal */
|
|
225
320
|
_initialized = false;
|
|
226
|
-
|
|
321
|
+
/** @internal */
|
|
227
322
|
_init;
|
|
228
|
-
|
|
323
|
+
/** @internal */
|
|
229
324
|
_initEager(value) {
|
|
230
325
|
if (typeof value === "function") {
|
|
231
326
|
this._init = value;
|
|
@@ -234,7 +329,7 @@ class FlowConstant extends FlowObservable {
|
|
|
234
329
|
this._initialized = true;
|
|
235
330
|
}
|
|
236
331
|
}
|
|
237
|
-
|
|
332
|
+
/** @internal */
|
|
238
333
|
_initLazy() {
|
|
239
334
|
if (!this._initialized && this._init) {
|
|
240
335
|
this._value = this._init();
|
|
@@ -245,81 +340,54 @@ class FlowConstant extends FlowObservable {
|
|
|
245
340
|
}
|
|
246
341
|
}
|
|
247
342
|
|
|
248
|
-
class FlowState extends FlowConstant {
|
|
249
|
-
/**
|
|
250
|
-
* Updates the state with a new value.
|
|
251
|
-
* @param value - A new value or a callback function that computes a new value based on the current state.
|
|
252
|
-
* @remarks
|
|
253
|
-
* If the computed new value is strictly equal to the current state value, no change is made and subscribers
|
|
254
|
-
* will not be notified. Otherwise, the state is updated and all subscribers are informed of the change.
|
|
255
|
-
* @throws Error if the state has been disposed.
|
|
256
|
-
* @public
|
|
257
|
-
*/
|
|
258
|
-
set(value) {
|
|
259
|
-
if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
|
|
260
|
-
const next = typeof value === "function" ? value(this._value) : value;
|
|
261
|
-
if (next === this._value) return;
|
|
262
|
-
this._value = next;
|
|
263
|
-
this._notify();
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
|
|
267
343
|
class FlowDerivation extends FlowObservable {
|
|
268
344
|
/**
|
|
269
345
|
* Creates a new FlowDerivation.
|
|
270
|
-
*
|
|
271
|
-
*
|
|
346
|
+
*
|
|
347
|
+
* @param compute - A function that computes the derived value using a tracking context.
|
|
348
|
+
* The function receives a TrackingContext and should use it to access dependencies via
|
|
349
|
+
* `.get(t)`. The function is not executed immediately; it runs lazily on first access.
|
|
350
|
+
*
|
|
272
351
|
* @public
|
|
273
352
|
*/
|
|
274
353
|
constructor(compute) {
|
|
275
354
|
super();
|
|
276
|
-
this.
|
|
355
|
+
this._compute = compute;
|
|
356
|
+
this._trackedContext = new TrackingContext(this);
|
|
277
357
|
}
|
|
278
358
|
/**
|
|
279
|
-
*
|
|
280
|
-
* @
|
|
281
|
-
* @remarks
|
|
282
|
-
* This method lazily initializes and updates the derivation if it is marked as dirty. It throws an error
|
|
283
|
-
* if the derivation has been disposed.
|
|
284
|
-
* @public
|
|
359
|
+
* Internal method to get the raw value.
|
|
360
|
+
* @internal
|
|
285
361
|
*/
|
|
286
|
-
|
|
362
|
+
_getRaw() {
|
|
287
363
|
if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
|
|
288
364
|
this._initLazy();
|
|
289
|
-
this.
|
|
365
|
+
this._update();
|
|
290
366
|
return this._value;
|
|
291
367
|
}
|
|
292
368
|
/* INTERNAL --------------------------------------------------------- */
|
|
293
369
|
_initialized = false;
|
|
294
370
|
_dirty = false;
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
_untrackedGet = (observable) => observable.get();
|
|
298
|
-
_untrackedWatch = (signal) => signal._watch();
|
|
299
|
-
_trackedCompute;
|
|
300
|
-
_untrackedCompute;
|
|
301
|
-
_initEager(compute) {
|
|
302
|
-
this._trackedCompute = () => compute(this._trackedGet, this._trackedWatch);
|
|
303
|
-
this._untrackedCompute = () => compute(this._untrackedGet, this._untrackedWatch);
|
|
304
|
-
}
|
|
371
|
+
_compute;
|
|
372
|
+
_trackedContext;
|
|
305
373
|
_initLazy() {
|
|
306
374
|
if (!this._initialized) {
|
|
307
|
-
this._value = this.
|
|
375
|
+
this._value = this._compute(this._trackedContext);
|
|
308
376
|
this._initialized = true;
|
|
309
377
|
}
|
|
310
378
|
}
|
|
311
379
|
/* @internal */
|
|
312
|
-
|
|
380
|
+
_update() {
|
|
313
381
|
if (this._dirty) {
|
|
314
382
|
const dependencies = [...this._dependencies];
|
|
315
383
|
this._dependencies.clear();
|
|
316
|
-
this._value = this.
|
|
384
|
+
this._value = this._compute(this._trackedContext);
|
|
317
385
|
const dependenciesToRemove = dependencies.filter(
|
|
318
386
|
(dependency) => !this._dependencies.has(dependency)
|
|
319
387
|
);
|
|
320
|
-
dependenciesToRemove.forEach(
|
|
321
|
-
|
|
322
|
-
);
|
|
388
|
+
dependenciesToRemove.forEach((dependency) => {
|
|
389
|
+
dependency._unregisterDependency(this);
|
|
390
|
+
});
|
|
323
391
|
this._dirty = false;
|
|
324
392
|
}
|
|
325
393
|
}
|
|
@@ -328,259 +396,99 @@ class FlowDerivation extends FlowObservable {
|
|
|
328
396
|
this._dirty = true;
|
|
329
397
|
super._notify();
|
|
330
398
|
}
|
|
331
|
-
/* @internal */
|
|
332
|
-
_watch() {
|
|
333
|
-
if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
|
|
334
|
-
this._initLazy();
|
|
335
|
-
this._compute();
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
function isDisposable(obj) {
|
|
340
|
-
return obj !== null && obj !== void 0 && typeof obj.dispose === "function";
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
class FlowMap extends FlowState {
|
|
344
399
|
/**
|
|
345
|
-
*
|
|
400
|
+
* Watches the derivation, registering it as a dependency in the given context.
|
|
346
401
|
*
|
|
347
|
-
* @
|
|
348
|
-
* When a key is set via {@link FlowMap.setAt}, this state is updated with
|
|
349
|
-
* the corresponding key and value.
|
|
350
|
-
*
|
|
351
|
-
* @public
|
|
352
|
-
*/
|
|
353
|
-
$lastSet = new FlowState({});
|
|
354
|
-
/**
|
|
355
|
-
* A reactive state that holds the most recent key and value that were deleted.
|
|
402
|
+
* @param context - The tracking context in which to register this derivation.
|
|
356
403
|
*
|
|
357
404
|
* @remarks
|
|
358
|
-
*
|
|
359
|
-
*
|
|
405
|
+
* This method overrides the base `watch()` to handle a special case: when a derivation
|
|
406
|
+
* is watched without having its value read (e.g., `$derivation.watch(t)` instead of
|
|
407
|
+
* `$derivation.get(t)`), the derivation still needs to compute its value to establish
|
|
408
|
+
* its own dependencies. Otherwise, the derivation would be tracked but wouldn't track
|
|
409
|
+
* its own dependencies, breaking the reactive chain.
|
|
360
410
|
*
|
|
361
|
-
*
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
* Sets a value at the specified key in the underlying map.
|
|
411
|
+
* This override ensures that:
|
|
412
|
+
* 1. The derivation is registered as a dependency in the provided context
|
|
413
|
+
* 2. The derivation computes its value (if not already computed)
|
|
414
|
+
* 3. The derivation tracks its own dependencies during computation
|
|
366
415
|
*
|
|
367
|
-
* @
|
|
368
|
-
*
|
|
369
|
-
*
|
|
416
|
+
* @example
|
|
417
|
+
* ```typescript
|
|
418
|
+
* const $derived = derivation((t) => $state.get(t) * 2);
|
|
370
419
|
*
|
|
371
|
-
*
|
|
372
|
-
*
|
|
373
|
-
*
|
|
420
|
+
* effect((t) => {
|
|
421
|
+
* $derived.watch(t); // Derivation computes even without reading value
|
|
422
|
+
* doSomething(); // Effect re-runs when $derived's dependencies change
|
|
423
|
+
* });
|
|
424
|
+
* ```
|
|
374
425
|
*
|
|
375
426
|
* @public
|
|
376
427
|
*/
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
this.
|
|
380
|
-
this
|
|
381
|
-
this._notify();
|
|
428
|
+
watch(context) {
|
|
429
|
+
super.watch(context);
|
|
430
|
+
this._initLazy();
|
|
431
|
+
this._update();
|
|
382
432
|
}
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
function isDisposable(obj) {
|
|
436
|
+
return obj !== null && obj !== void 0 && typeof obj.dispose === "function";
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
class FlowState extends FlowConstant {
|
|
383
440
|
/**
|
|
384
|
-
*
|
|
385
|
-
*
|
|
386
|
-
* @param key - The key to delete.
|
|
387
|
-
* @throws If the FlowMap instance is disposed.
|
|
388
|
-
*
|
|
441
|
+
* Updates the state with a new value.
|
|
442
|
+
* @param value - A new value or a callback function that computes a new value based on the current state.
|
|
389
443
|
* @remarks
|
|
390
|
-
*
|
|
391
|
-
* and
|
|
392
|
-
*
|
|
444
|
+
* If the computed new value is strictly equal to the current state value, no change is made and subscribers
|
|
445
|
+
* will not be notified. Otherwise, the state is updated and all subscribers are informed of the change.
|
|
446
|
+
* @throws Error if the state has been disposed.
|
|
393
447
|
* @public
|
|
394
448
|
*/
|
|
395
|
-
|
|
449
|
+
set(value) {
|
|
396
450
|
if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
|
|
397
|
-
const
|
|
398
|
-
this._value
|
|
399
|
-
this
|
|
451
|
+
const next = typeof value === "function" ? value(this._value) : value;
|
|
452
|
+
if (next === this._value) return;
|
|
453
|
+
this._value = next;
|
|
400
454
|
this._notify();
|
|
401
455
|
}
|
|
402
456
|
}
|
|
403
457
|
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
* Creates a new FlowStream.
|
|
407
|
-
* @param updater - A function that receives a setter to update the stream's value.
|
|
408
|
-
* It should return a disposer function that will be called upon disposal.
|
|
409
|
-
* @public
|
|
410
|
-
*/
|
|
411
|
-
constructor(updater) {
|
|
412
|
-
super();
|
|
413
|
-
this._disposer = updater((value) => {
|
|
414
|
-
this._set(value);
|
|
415
|
-
});
|
|
416
|
-
}
|
|
417
|
-
/**
|
|
418
|
-
* Retrieves the current value of the stream.
|
|
419
|
-
* @returns The current value, or undefined if no value has been set yet.
|
|
420
|
-
* @throws Error if the stream is disposed.
|
|
421
|
-
* @public
|
|
422
|
-
*/
|
|
423
|
-
get() {
|
|
424
|
-
if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
|
|
425
|
-
return this._value;
|
|
426
|
-
}
|
|
427
|
-
/**
|
|
428
|
-
* Disposes the stream, releasing all resources.
|
|
429
|
-
* @remarks
|
|
430
|
-
* In addition to disposing the underlying observable, this method calls the disposer
|
|
431
|
-
* returned by the updater.
|
|
432
|
-
* @public
|
|
433
|
-
*/
|
|
434
|
-
dispose() {
|
|
435
|
-
super.dispose();
|
|
436
|
-
this._disposer();
|
|
437
|
-
}
|
|
438
|
-
/* INTERNAL ------------------------------------------------------ */
|
|
439
|
-
_disposer;
|
|
440
|
-
_set(value) {
|
|
441
|
-
if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
|
|
442
|
-
if (value === this._value) return;
|
|
443
|
-
this._value = value;
|
|
444
|
-
this._notify();
|
|
445
|
-
}
|
|
458
|
+
function signal() {
|
|
459
|
+
return new FlowSignal();
|
|
446
460
|
}
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
/**
|
|
450
|
-
* Creates a new asynchronous FlowStream.
|
|
451
|
-
* @param updater - A function that receives a setter to update the stream's value.
|
|
452
|
-
* It should return a disposer function that will be called upon disposal.
|
|
453
|
-
* @remarks The updater function can invoke the setter asynchronously to update the stream.
|
|
454
|
-
* @public
|
|
455
|
-
*/
|
|
456
|
-
constructor(updater) {
|
|
457
|
-
super();
|
|
458
|
-
this._disposer = updater((value) => {
|
|
459
|
-
this._set(value);
|
|
460
|
-
});
|
|
461
|
-
this._value = new Promise((resolve) => {
|
|
462
|
-
this._resolve = resolve;
|
|
463
|
-
});
|
|
464
|
-
}
|
|
465
|
-
/**
|
|
466
|
-
* Retrieves the current value of the stream as a Promise.
|
|
467
|
-
* @returns A Promise that resolves to the current value.
|
|
468
|
-
* @throws Error if the stream is disposed.
|
|
469
|
-
* @public
|
|
470
|
-
*/
|
|
471
|
-
get() {
|
|
472
|
-
if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
|
|
473
|
-
return this._value;
|
|
474
|
-
}
|
|
475
|
-
/**
|
|
476
|
-
* Disposes the stream, releasing all resources.
|
|
477
|
-
* @remarks In addition to disposing the underlying observable, this method calls the disposer
|
|
478
|
-
* returned by the updater.
|
|
479
|
-
* @public
|
|
480
|
-
*/
|
|
481
|
-
dispose() {
|
|
482
|
-
super.dispose();
|
|
483
|
-
this._disposer();
|
|
484
|
-
}
|
|
485
|
-
/* INTERNAL ------------------------------------------------------ */
|
|
486
|
-
_initialized = false;
|
|
487
|
-
_awaitedValue;
|
|
488
|
-
_resolve;
|
|
489
|
-
_disposer;
|
|
490
|
-
_set(value) {
|
|
491
|
-
if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
|
|
492
|
-
if (!this._initialized) {
|
|
493
|
-
this._resolve(value);
|
|
494
|
-
this._initialized = true;
|
|
495
|
-
this._awaitedValue = value;
|
|
496
|
-
this._notify();
|
|
497
|
-
return;
|
|
498
|
-
}
|
|
499
|
-
if (value === this._awaitedValue) return;
|
|
500
|
-
this._value = Promise.resolve(value);
|
|
501
|
-
this._awaitedValue = value;
|
|
502
|
-
this._notify();
|
|
503
|
-
}
|
|
461
|
+
function constant(value) {
|
|
462
|
+
return new FlowConstant(value);
|
|
504
463
|
}
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
/**
|
|
508
|
-
* Creates a new FlowResource.
|
|
509
|
-
* @param fetch - An asynchronous function that retrieves the resource's value.
|
|
510
|
-
*
|
|
511
|
-
* @public
|
|
512
|
-
*/
|
|
513
|
-
constructor(fetch) {
|
|
514
|
-
super();
|
|
515
|
-
this._fetch = fetch;
|
|
516
|
-
}
|
|
517
|
-
/**
|
|
518
|
-
* Retrieves the current resource value.
|
|
519
|
-
* @returns The current value, or undefined if the resource has not been fetched yet.
|
|
520
|
-
* @throws Error if the resource is disposed.
|
|
521
|
-
* @public
|
|
522
|
-
*/
|
|
523
|
-
get() {
|
|
524
|
-
if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
|
|
525
|
-
return this._value;
|
|
526
|
-
}
|
|
527
|
-
/**
|
|
528
|
-
* Asynchronously fetches a new value for the resource.
|
|
529
|
-
* @remarks
|
|
530
|
-
* Executes the internal fetch function. If the fetched value differs from the current one,
|
|
531
|
-
* updates the resource's value and notifies subscribers.
|
|
532
|
-
* @returns A Promise that resolves when the fetch operation is complete.
|
|
533
|
-
* @throws Error if the resource is disposed.
|
|
534
|
-
* @public
|
|
535
|
-
*/
|
|
536
|
-
async fetch() {
|
|
537
|
-
if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
|
|
538
|
-
const value = await this._fetch();
|
|
539
|
-
if (value === this._value) return;
|
|
540
|
-
this._value = value;
|
|
541
|
-
this._notify();
|
|
542
|
-
}
|
|
543
|
-
/* INTERNAL ------------------------------------------------ */
|
|
544
|
-
_fetch;
|
|
464
|
+
function state(value) {
|
|
465
|
+
return new FlowState(value);
|
|
545
466
|
}
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
* Executes the internal fetch function. If the fetched value differs from the current one,
|
|
572
|
-
* updates the resource's value and notifies subscribers.
|
|
573
|
-
* @returns A Promise that resolves when the fetch operation is complete.
|
|
574
|
-
* @throws Error if the resource is disposed.
|
|
575
|
-
* @public
|
|
576
|
-
*/
|
|
577
|
-
async fetch() {
|
|
578
|
-
if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
|
|
579
|
-
this._value = this._fetch();
|
|
580
|
-
this._notify();
|
|
581
|
-
}
|
|
582
|
-
/* INTERNAL ------------------------------------------------ */
|
|
583
|
-
_fetch;
|
|
467
|
+
function resource(fn) {
|
|
468
|
+
return new FlowResource(fn);
|
|
469
|
+
}
|
|
470
|
+
function resourceAsync(fn) {
|
|
471
|
+
return new FlowResourceAsync(fn);
|
|
472
|
+
}
|
|
473
|
+
function stream(updater) {
|
|
474
|
+
return new FlowStream(updater);
|
|
475
|
+
}
|
|
476
|
+
function streamAsync(updater) {
|
|
477
|
+
return new FlowStreamAsync(updater);
|
|
478
|
+
}
|
|
479
|
+
function derivation(fn) {
|
|
480
|
+
return new FlowDerivation(fn);
|
|
481
|
+
}
|
|
482
|
+
function effect(fn) {
|
|
483
|
+
return new FlowEffect(fn);
|
|
484
|
+
}
|
|
485
|
+
function map(initial) {
|
|
486
|
+
return new FlowMap(
|
|
487
|
+
new Map(initial ? Object.entries(initial) : [])
|
|
488
|
+
);
|
|
489
|
+
}
|
|
490
|
+
function array(initial) {
|
|
491
|
+
return new FlowArray(initial);
|
|
584
492
|
}
|
|
585
493
|
|
|
586
494
|
class FlowArray extends FlowObservable {
|
|
@@ -612,11 +520,10 @@ class FlowArray extends FlowObservable {
|
|
|
612
520
|
return this._value.length;
|
|
613
521
|
}
|
|
614
522
|
/**
|
|
615
|
-
*
|
|
616
|
-
* @
|
|
617
|
-
* @public
|
|
523
|
+
* Internal method to get the raw value.
|
|
524
|
+
* @internal
|
|
618
525
|
*/
|
|
619
|
-
|
|
526
|
+
_getRaw() {
|
|
620
527
|
if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
|
|
621
528
|
return [...this._value];
|
|
622
529
|
}
|
|
@@ -745,762 +652,313 @@ class FlowArray extends FlowObservable {
|
|
|
745
652
|
this._value = [];
|
|
746
653
|
}
|
|
747
654
|
/* INTERNAL */
|
|
748
|
-
|
|
655
|
+
/** @internal */
|
|
749
656
|
_value = [];
|
|
750
657
|
}
|
|
751
658
|
|
|
752
|
-
|
|
753
|
-
return new FlowSignal();
|
|
754
|
-
}
|
|
755
|
-
function constant(value) {
|
|
756
|
-
return new FlowConstant(value);
|
|
757
|
-
}
|
|
758
|
-
function state(value) {
|
|
759
|
-
return new FlowState(value);
|
|
760
|
-
}
|
|
761
|
-
function resource(fn) {
|
|
762
|
-
return new FlowResource(fn);
|
|
763
|
-
}
|
|
764
|
-
function resourceAsync(fn) {
|
|
765
|
-
return new FlowResourceAsync(fn);
|
|
766
|
-
}
|
|
767
|
-
function stream(updater) {
|
|
768
|
-
return new FlowStream(updater);
|
|
769
|
-
}
|
|
770
|
-
function streamAsync(updater) {
|
|
771
|
-
return new FlowStreamAsync(updater);
|
|
772
|
-
}
|
|
773
|
-
function derivation(fn) {
|
|
774
|
-
return new FlowDerivation(fn);
|
|
775
|
-
}
|
|
776
|
-
function effect(fn) {
|
|
777
|
-
return new FlowEffect(fn);
|
|
778
|
-
}
|
|
779
|
-
function map(initial) {
|
|
780
|
-
return new FlowMap(
|
|
781
|
-
new Map(initial ? Object.entries(initial) : [])
|
|
782
|
-
);
|
|
783
|
-
}
|
|
784
|
-
function array(initial) {
|
|
785
|
-
return new FlowArray(initial);
|
|
786
|
-
}
|
|
787
|
-
|
|
788
|
-
let FlowSignal$1 = class FlowSignal {
|
|
659
|
+
class FlowMap extends FlowState {
|
|
789
660
|
/**
|
|
790
|
-
*
|
|
791
|
-
*
|
|
792
|
-
* @
|
|
661
|
+
* A reactive state that holds the most recent key and value that were added.
|
|
662
|
+
*
|
|
663
|
+
* @remarks
|
|
664
|
+
* When a key is added via {@link FlowMap.add}, this state is updated with
|
|
665
|
+
* the corresponding key and value.
|
|
666
|
+
*
|
|
793
667
|
* @public
|
|
794
668
|
*/
|
|
795
|
-
|
|
669
|
+
$lastAdded = new FlowState(null);
|
|
670
|
+
/**
|
|
671
|
+
* A reactive state that holds the most recent key and value that were updated.
|
|
672
|
+
*
|
|
673
|
+
* @remarks
|
|
674
|
+
* When a key is updated via {@link FlowMap.update}, this state is updated with
|
|
675
|
+
* the corresponding key and value.
|
|
676
|
+
*
|
|
677
|
+
* @public
|
|
678
|
+
*/
|
|
679
|
+
$lastUpdated = new FlowState(null);
|
|
680
|
+
/**
|
|
681
|
+
* A reactive state that holds the most recent key and value that were deleted.
|
|
682
|
+
*
|
|
683
|
+
* @remarks
|
|
684
|
+
* When a key is deleted via {@link FlowMap.delete}, this state is updated with
|
|
685
|
+
* the corresponding key and its last known value.
|
|
686
|
+
*
|
|
687
|
+
* @public
|
|
688
|
+
*/
|
|
689
|
+
$lastDeleted = new FlowState(null);
|
|
690
|
+
/**
|
|
691
|
+
* Adds a new key-value pair to the map.
|
|
692
|
+
*
|
|
693
|
+
* @param key - The key to add.
|
|
694
|
+
* @param value - The value to associate with the key.
|
|
695
|
+
* @throws If the FlowMap instance is disposed.
|
|
696
|
+
* @throws If the key already exists in the map.
|
|
697
|
+
*
|
|
698
|
+
* @remarks
|
|
699
|
+
* Adds a new entry to the internal map, emits the key-value pair via {@link FlowMap.$lastAdded},
|
|
700
|
+
* and notifies all subscribers of the change.
|
|
701
|
+
*
|
|
702
|
+
* @public
|
|
703
|
+
*/
|
|
704
|
+
add(key, value) {
|
|
796
705
|
if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
|
|
706
|
+
if (this._value.has(key)) {
|
|
707
|
+
throw new Error("[PicoFlow] Key already exists");
|
|
708
|
+
}
|
|
709
|
+
this._value.set(key, value);
|
|
710
|
+
this.$lastAdded.set({ key, value });
|
|
797
711
|
this._notify();
|
|
798
712
|
}
|
|
799
713
|
/**
|
|
800
|
-
*
|
|
801
|
-
*
|
|
802
|
-
*
|
|
803
|
-
* @
|
|
714
|
+
* Updates an existing key-value pair in the map.
|
|
715
|
+
*
|
|
716
|
+
* @param key - The key to update.
|
|
717
|
+
* @param value - The new value to associate with the key.
|
|
718
|
+
* @throws If the FlowMap instance is disposed.
|
|
719
|
+
* @throws If the key does not exist in the map.
|
|
720
|
+
*
|
|
721
|
+
* @remarks
|
|
722
|
+
* Updates an existing entry in the internal map, emits the key-value pair via {@link FlowMap.$lastUpdated},
|
|
723
|
+
* and notifies all subscribers of the change.
|
|
724
|
+
*
|
|
804
725
|
* @public
|
|
805
726
|
*/
|
|
806
|
-
|
|
727
|
+
update(key, value) {
|
|
807
728
|
if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
|
|
808
|
-
if (
|
|
809
|
-
|
|
810
|
-
(effect) => effect._unregisterDependency(this)
|
|
811
|
-
);
|
|
812
|
-
Array.from(this._listeners).forEach(
|
|
813
|
-
(listener) => listener._unregisterDependency(this)
|
|
814
|
-
);
|
|
815
|
-
} else {
|
|
816
|
-
Array.from(this._effects).forEach((effect) => effect.dispose());
|
|
817
|
-
Array.from(this._listeners).forEach(
|
|
818
|
-
(listener) => listener.dispose()
|
|
819
|
-
);
|
|
729
|
+
if (!this._value.has(key)) {
|
|
730
|
+
throw new Error("[PicoFlow] Key does not exist");
|
|
820
731
|
}
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
this._disposed = true;
|
|
732
|
+
this._value.set(key, value);
|
|
733
|
+
this.$lastUpdated.set({ key, value });
|
|
734
|
+
this._notify();
|
|
825
735
|
}
|
|
826
736
|
/**
|
|
827
|
-
*
|
|
828
|
-
* @remarks Once disposed, the signal should not be used.
|
|
829
|
-
* @public
|
|
830
|
-
*/
|
|
831
|
-
get disposed() {
|
|
832
|
-
return this._disposed;
|
|
833
|
-
}
|
|
834
|
-
/* INTERNAL ------------------------------------------------------------- */
|
|
835
|
-
/*@internal*/
|
|
836
|
-
_disposed = false;
|
|
837
|
-
/*@internal*/
|
|
838
|
-
_dependencies = /* @__PURE__ */ new Set();
|
|
839
|
-
/*@internal*/
|
|
840
|
-
_listeners = /* @__PURE__ */ new Set();
|
|
841
|
-
/*@internal*/
|
|
842
|
-
_effects = /* @__PURE__ */ new Set();
|
|
843
|
-
/*@internal*/
|
|
844
|
-
_watch() {
|
|
845
|
-
if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
|
|
846
|
-
}
|
|
847
|
-
/*@internal*/
|
|
848
|
-
_notify() {
|
|
849
|
-
this._listeners.forEach((listener) => listener._notify());
|
|
850
|
-
this._effects.forEach((effect) => effect._exec());
|
|
851
|
-
}
|
|
852
|
-
/*@internal*/
|
|
853
|
-
_watchFrom(listener) {
|
|
854
|
-
listener._registerDependency(this);
|
|
855
|
-
this._watch();
|
|
856
|
-
}
|
|
857
|
-
/*@internal*/
|
|
858
|
-
_registerDependency(dependency) {
|
|
859
|
-
this._dependencies.add(dependency);
|
|
860
|
-
dependency._registerListener(this);
|
|
861
|
-
}
|
|
862
|
-
/*@internal*/
|
|
863
|
-
_unregisterDependency(dependency) {
|
|
864
|
-
this._dependencies.delete(dependency);
|
|
865
|
-
dependency._unregisterListener(this);
|
|
866
|
-
}
|
|
867
|
-
/*@internal*/
|
|
868
|
-
_registerListener(signal) {
|
|
869
|
-
this._listeners.add(signal);
|
|
870
|
-
}
|
|
871
|
-
/*@internal*/
|
|
872
|
-
_unregisterListener(signal) {
|
|
873
|
-
this._listeners.delete(signal);
|
|
874
|
-
}
|
|
875
|
-
/*@internal*/
|
|
876
|
-
_registerEffect(effect) {
|
|
877
|
-
this._effects.add(effect);
|
|
878
|
-
}
|
|
879
|
-
/*@internal*/
|
|
880
|
-
_unregisterEffect(effect) {
|
|
881
|
-
this._effects.delete(effect);
|
|
882
|
-
}
|
|
883
|
-
};
|
|
884
|
-
|
|
885
|
-
let FlowEffect$1 = class FlowEffect {
|
|
886
|
-
/**
|
|
887
|
-
* Creates a new FlowEffect.
|
|
737
|
+
* Deletes the value at the specified key from the underlying map.
|
|
888
738
|
*
|
|
889
|
-
* @param
|
|
890
|
-
*
|
|
739
|
+
* @param key - The key to delete.
|
|
740
|
+
* @throws If the FlowMap instance is disposed.
|
|
891
741
|
*
|
|
892
742
|
* @remarks
|
|
893
|
-
*
|
|
894
|
-
*
|
|
743
|
+
* Removes the key from the internal map, emits the deleted key and its value via {@link FlowMap.$lastDeleted},
|
|
744
|
+
* and notifies all subscribers of the change.
|
|
895
745
|
*
|
|
896
746
|
* @public
|
|
897
747
|
*/
|
|
898
|
-
|
|
899
|
-
this.
|
|
900
|
-
|
|
901
|
-
|
|
748
|
+
delete(key) {
|
|
749
|
+
if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
|
|
750
|
+
const value = this._value.get(key);
|
|
751
|
+
if (!value) throw new Error("[PicoFlow] Key does not exist");
|
|
752
|
+
this._value.delete(key);
|
|
753
|
+
this.$lastDeleted.set({ key, value });
|
|
754
|
+
this._notify();
|
|
902
755
|
}
|
|
903
756
|
/**
|
|
904
|
-
* Disposes the
|
|
905
|
-
*
|
|
906
|
-
* @remarks
|
|
907
|
-
* Once disposed, the effect must no longer be used. Trying to dispose an effect
|
|
908
|
-
* that is already disposed will throw an error.
|
|
909
|
-
*
|
|
757
|
+
* Disposes the FlowMap and its values.
|
|
758
|
+
* @param options - Disposal options.
|
|
910
759
|
* @public
|
|
911
760
|
*/
|
|
912
|
-
dispose() {
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
761
|
+
dispose(options) {
|
|
762
|
+
super.dispose(options);
|
|
763
|
+
this._value.forEach((item) => {
|
|
764
|
+
if (isDisposable(item)) item.dispose(options);
|
|
916
765
|
});
|
|
917
|
-
this.
|
|
766
|
+
this._value.clear();
|
|
767
|
+
this.$lastAdded.dispose(options);
|
|
768
|
+
this.$lastUpdated.dispose(options);
|
|
769
|
+
this.$lastDeleted.dispose(options);
|
|
918
770
|
}
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
class FlowResource extends FlowObservable {
|
|
919
774
|
/**
|
|
920
|
-
*
|
|
775
|
+
* Creates a new FlowResource.
|
|
921
776
|
*
|
|
922
|
-
* @
|
|
777
|
+
* @param fetch - An asynchronous function that retrieves the resource's value.
|
|
778
|
+
* This function is not invoked on construction; you must call the `fetch()` method
|
|
779
|
+
* to execute it.
|
|
923
780
|
*
|
|
924
781
|
* @public
|
|
925
782
|
*/
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
/* INTERNAL ------------------------------------------------------------ */
|
|
930
|
-
_disposed = false;
|
|
931
|
-
_initialized = false;
|
|
932
|
-
_dependencies = /* @__PURE__ */ new Set();
|
|
933
|
-
_trackedGet = (observable) => observable._getFrom(this);
|
|
934
|
-
_trackedWatch = (signal) => signal._watchFrom(this);
|
|
935
|
-
_untrackedGet = (observable) => observable.get();
|
|
936
|
-
_untrackedWatch = (signal) => signal._watch();
|
|
937
|
-
_trackedExec;
|
|
938
|
-
_untrackedExec;
|
|
939
|
-
/*@internal*/
|
|
940
|
-
_exec() {
|
|
941
|
-
if (this._disposed)
|
|
942
|
-
throw new Error("[PicoFlow] Effect is disposed");
|
|
943
|
-
if (this._initialized) this._untrackedExec();
|
|
944
|
-
else {
|
|
945
|
-
this._trackedExec();
|
|
946
|
-
this._initialized = true;
|
|
947
|
-
}
|
|
948
|
-
}
|
|
949
|
-
/*@internal*/
|
|
950
|
-
_registerDependency(dependency) {
|
|
951
|
-
this._dependencies.add(dependency);
|
|
952
|
-
dependency._registerEffect(this);
|
|
953
|
-
}
|
|
954
|
-
/*@internal*/
|
|
955
|
-
_unregisterDependency(dependency) {
|
|
956
|
-
this._dependencies.delete(dependency);
|
|
957
|
-
dependency._unregisterEffect(this);
|
|
783
|
+
constructor(fetch) {
|
|
784
|
+
super();
|
|
785
|
+
this._fetch = fetch;
|
|
958
786
|
}
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
_getFrom(listener) {
|
|
967
|
-
listener._registerDependency(this);
|
|
968
|
-
return this.get();
|
|
787
|
+
/**
|
|
788
|
+
* Internal method to get the raw value.
|
|
789
|
+
* @internal
|
|
790
|
+
*/
|
|
791
|
+
_getRaw() {
|
|
792
|
+
if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
|
|
793
|
+
return this._value;
|
|
969
794
|
}
|
|
970
795
|
/**
|
|
971
|
-
*
|
|
972
|
-
*
|
|
973
|
-
*
|
|
974
|
-
*
|
|
796
|
+
* Asynchronously fetches a new value for the resource.
|
|
797
|
+
* @remarks
|
|
798
|
+
* Executes the internal fetch function. If the fetched value differs from the current one,
|
|
799
|
+
* updates the resource's value and notifies subscribers.
|
|
800
|
+
* @returns A Promise that resolves when the fetch operation is complete.
|
|
801
|
+
* @throws Error if the resource is disposed.
|
|
802
|
+
* @public
|
|
975
803
|
*/
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
804
|
+
async fetch() {
|
|
805
|
+
if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
|
|
806
|
+
const value = await this._fetch();
|
|
807
|
+
if (value === this._value) return;
|
|
808
|
+
this._value = value;
|
|
809
|
+
this._notify();
|
|
981
810
|
}
|
|
982
|
-
|
|
811
|
+
/* INTERNAL ------------------------------------------------ */
|
|
812
|
+
_fetch;
|
|
813
|
+
}
|
|
983
814
|
|
|
984
|
-
|
|
815
|
+
class FlowResourceAsync extends FlowObservable {
|
|
985
816
|
/**
|
|
986
|
-
* Creates a new
|
|
987
|
-
* @param
|
|
988
|
-
* a getter and a watcher that respect dependency tracking.
|
|
817
|
+
* Creates a new FlowResource.
|
|
818
|
+
* @param fetch - An asynchronous function that retrieves the resource's value.
|
|
989
819
|
* @public
|
|
990
820
|
*/
|
|
991
|
-
constructor(
|
|
821
|
+
constructor(fetch) {
|
|
992
822
|
super();
|
|
993
|
-
this.
|
|
823
|
+
this._fetch = fetch;
|
|
994
824
|
}
|
|
995
825
|
/**
|
|
996
|
-
*
|
|
997
|
-
* @
|
|
998
|
-
* @remarks
|
|
999
|
-
* This method lazily initializes and updates the derivation if it is marked as dirty. It throws an error
|
|
1000
|
-
* if the derivation has been disposed.
|
|
1001
|
-
* @public
|
|
826
|
+
* Internal method to get the raw value.
|
|
827
|
+
* @internal
|
|
1002
828
|
*/
|
|
1003
|
-
|
|
829
|
+
_getRaw() {
|
|
1004
830
|
if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
|
|
1005
|
-
this.
|
|
1006
|
-
this._compute();
|
|
831
|
+
if (!this._value) this._value = this._fetch();
|
|
1007
832
|
return this._value;
|
|
1008
833
|
}
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
this._trackedCompute = () => compute(this._trackedGet, this._trackedWatch);
|
|
1020
|
-
this._untrackedCompute = () => compute(this._untrackedGet, this._untrackedWatch);
|
|
1021
|
-
}
|
|
1022
|
-
_initLazy() {
|
|
1023
|
-
if (!this._initialized) {
|
|
1024
|
-
this._value = this._trackedCompute();
|
|
1025
|
-
this._initialized = true;
|
|
1026
|
-
}
|
|
1027
|
-
}
|
|
1028
|
-
/* @internal */
|
|
1029
|
-
_compute() {
|
|
1030
|
-
if (this._dirty) {
|
|
1031
|
-
const dependencies = [...this._dependencies];
|
|
1032
|
-
this._dependencies.clear();
|
|
1033
|
-
this._value = this._trackedCompute();
|
|
1034
|
-
const dependenciesToRemove = dependencies.filter(
|
|
1035
|
-
(dependency) => !this._dependencies.has(dependency)
|
|
1036
|
-
);
|
|
1037
|
-
dependenciesToRemove.forEach(
|
|
1038
|
-
(dependency) => dependency._unregisterDependency(this)
|
|
1039
|
-
);
|
|
1040
|
-
this._dirty = false;
|
|
1041
|
-
}
|
|
1042
|
-
}
|
|
1043
|
-
/* @internal */
|
|
1044
|
-
_notify() {
|
|
1045
|
-
this._dirty = true;
|
|
1046
|
-
super._notify();
|
|
1047
|
-
}
|
|
1048
|
-
/* @internal */
|
|
1049
|
-
_watch() {
|
|
834
|
+
/**
|
|
835
|
+
* Asynchronously fetches a new value for the resource.
|
|
836
|
+
* @remarks
|
|
837
|
+
* Executes the internal fetch function. If the fetched value differs from the current one,
|
|
838
|
+
* updates the resource's value and notifies subscribers.
|
|
839
|
+
* @returns A Promise that resolves when the fetch operation is complete.
|
|
840
|
+
* @throws Error if the resource is disposed.
|
|
841
|
+
* @public
|
|
842
|
+
*/
|
|
843
|
+
async fetch() {
|
|
1050
844
|
if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
|
|
1051
|
-
this.
|
|
1052
|
-
this.
|
|
845
|
+
this._value = this._fetch();
|
|
846
|
+
this._notify();
|
|
1053
847
|
}
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
const IS_DEV = false;
|
|
1057
|
-
const equalFn = (a, b) => a === b;
|
|
1058
|
-
const signalOptions = {
|
|
1059
|
-
equals: equalFn
|
|
1060
|
-
};
|
|
1061
|
-
let runEffects = runQueue;
|
|
1062
|
-
const STALE = 1;
|
|
1063
|
-
const PENDING = 2;
|
|
1064
|
-
const UNOWNED = {
|
|
1065
|
-
};
|
|
1066
|
-
const NO_INIT = {};
|
|
1067
|
-
var Owner = null;
|
|
1068
|
-
let Transition = null;
|
|
1069
|
-
let ExternalSourceConfig = null;
|
|
1070
|
-
let Listener = null;
|
|
1071
|
-
let Updates = null;
|
|
1072
|
-
let Effects = null;
|
|
1073
|
-
let ExecCount = 0;
|
|
1074
|
-
function createSignal(value, options) {
|
|
1075
|
-
options = options ? Object.assign({}, signalOptions, options) : signalOptions;
|
|
1076
|
-
const s = {
|
|
1077
|
-
value,
|
|
1078
|
-
observers: null,
|
|
1079
|
-
observerSlots: null,
|
|
1080
|
-
comparator: options.equals || undefined
|
|
1081
|
-
};
|
|
1082
|
-
const setter = value => {
|
|
1083
|
-
if (typeof value === "function") {
|
|
1084
|
-
value = value(s.value);
|
|
1085
|
-
}
|
|
1086
|
-
return writeSignal(s, value);
|
|
1087
|
-
};
|
|
1088
|
-
return [readSignal.bind(s), setter];
|
|
1089
|
-
}
|
|
1090
|
-
function createComputed(fn, value, options) {
|
|
1091
|
-
const c = createComputation(fn, value, true, STALE);
|
|
1092
|
-
updateComputation(c);
|
|
1093
|
-
}
|
|
1094
|
-
function createEffect(fn, value, options) {
|
|
1095
|
-
runEffects = runUserEffects;
|
|
1096
|
-
const c = createComputation(fn, value, false, STALE);
|
|
1097
|
-
c.user = true;
|
|
1098
|
-
Effects ? Effects.push(c) : updateComputation(c);
|
|
1099
|
-
}
|
|
1100
|
-
function createMemo(fn, value, options) {
|
|
1101
|
-
options = options ? Object.assign({}, signalOptions, options) : signalOptions;
|
|
1102
|
-
const c = createComputation(fn, value, true, 0);
|
|
1103
|
-
c.observers = null;
|
|
1104
|
-
c.observerSlots = null;
|
|
1105
|
-
c.comparator = options.equals || undefined;
|
|
1106
|
-
updateComputation(c);
|
|
1107
|
-
return readSignal.bind(c);
|
|
1108
|
-
}
|
|
1109
|
-
function isPromise(v) {
|
|
1110
|
-
return v && typeof v === "object" && "then" in v;
|
|
848
|
+
/* INTERNAL ------------------------------------------------ */
|
|
849
|
+
_fetch;
|
|
1111
850
|
}
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
}),
|
|
1132
|
-
[state, setState] = createSignal(resolved ? "ready" : "unresolved");
|
|
1133
|
-
function loadEnd(p, v, error, key) {
|
|
1134
|
-
if (pr === p) {
|
|
1135
|
-
pr = null;
|
|
1136
|
-
key !== undefined && (resolved = true);
|
|
1137
|
-
if ((p === initP || v === initP) && options.onHydrated) queueMicrotask(() => options.onHydrated(key, {
|
|
1138
|
-
value: v
|
|
1139
|
-
}));
|
|
1140
|
-
initP = NO_INIT;
|
|
1141
|
-
completeLoad(v, error);
|
|
1142
|
-
}
|
|
1143
|
-
return v;
|
|
1144
|
-
}
|
|
1145
|
-
function completeLoad(v, err) {
|
|
1146
|
-
runUpdates(() => {
|
|
1147
|
-
if (err === undefined) setValue(() => v);
|
|
1148
|
-
setState(err !== undefined ? "errored" : resolved ? "ready" : "unresolved");
|
|
1149
|
-
setError(err);
|
|
1150
|
-
for (const c of contexts.keys()) c.decrement();
|
|
1151
|
-
contexts.clear();
|
|
1152
|
-
}, false);
|
|
1153
|
-
}
|
|
1154
|
-
function read() {
|
|
1155
|
-
const c = SuspenseContext,
|
|
1156
|
-
v = value(),
|
|
1157
|
-
err = error();
|
|
1158
|
-
if (err !== undefined && !pr) throw err;
|
|
1159
|
-
if (Listener && !Listener.user && c) {
|
|
1160
|
-
createComputed(() => {
|
|
1161
|
-
track();
|
|
1162
|
-
if (pr) {
|
|
1163
|
-
if (c.resolved && Transition) ;else if (!contexts.has(c)) {
|
|
1164
|
-
c.increment();
|
|
1165
|
-
contexts.add(c);
|
|
1166
|
-
}
|
|
1167
|
-
}
|
|
1168
|
-
});
|
|
1169
|
-
}
|
|
1170
|
-
return v;
|
|
1171
|
-
}
|
|
1172
|
-
function load(refetching = true) {
|
|
1173
|
-
if (refetching !== false && scheduled) return;
|
|
1174
|
-
scheduled = false;
|
|
1175
|
-
const lookup = dynamic ? dynamic() : source;
|
|
1176
|
-
if (lookup == null || lookup === false) {
|
|
1177
|
-
loadEnd(pr, untrack(value));
|
|
1178
|
-
return;
|
|
1179
|
-
}
|
|
1180
|
-
let error;
|
|
1181
|
-
const p = initP !== NO_INIT ? initP : untrack(() => {
|
|
1182
|
-
try {
|
|
1183
|
-
return fetcher(lookup, {
|
|
1184
|
-
value: value(),
|
|
1185
|
-
refetching
|
|
1186
|
-
});
|
|
1187
|
-
} catch (fetcherError) {
|
|
1188
|
-
error = fetcherError;
|
|
1189
|
-
}
|
|
851
|
+
|
|
852
|
+
class FlowStream extends FlowObservable {
|
|
853
|
+
/**
|
|
854
|
+
* Creates a new FlowStream.
|
|
855
|
+
*
|
|
856
|
+
* @param updater - A function that receives a setter callback and returns a disposer.
|
|
857
|
+
* The setter should be called whenever new data is available. The disposer will be
|
|
858
|
+
* invoked when the stream is disposed to clean up resources.
|
|
859
|
+
*
|
|
860
|
+
* @remarks
|
|
861
|
+
* The updater is invoked immediately during construction. Make sure to return a proper
|
|
862
|
+
* cleanup function to avoid resource leaks.
|
|
863
|
+
*
|
|
864
|
+
* @public
|
|
865
|
+
*/
|
|
866
|
+
constructor(updater) {
|
|
867
|
+
super();
|
|
868
|
+
this._disposer = updater((value) => {
|
|
869
|
+
this._set(value);
|
|
1190
870
|
});
|
|
1191
|
-
if (error !== undefined) {
|
|
1192
|
-
loadEnd(pr, undefined, castError(error), lookup);
|
|
1193
|
-
return;
|
|
1194
|
-
} else if (!isPromise(p)) {
|
|
1195
|
-
loadEnd(pr, p, undefined, lookup);
|
|
1196
|
-
return p;
|
|
1197
|
-
}
|
|
1198
|
-
pr = p;
|
|
1199
|
-
if ("v" in p) {
|
|
1200
|
-
if (p.s === 1) loadEnd(pr, p.v, undefined, lookup);else loadEnd(pr, undefined, castError(p.v), lookup);
|
|
1201
|
-
return p;
|
|
1202
|
-
}
|
|
1203
|
-
scheduled = true;
|
|
1204
|
-
queueMicrotask(() => scheduled = false);
|
|
1205
|
-
runUpdates(() => {
|
|
1206
|
-
setState(resolved ? "refreshing" : "pending");
|
|
1207
|
-
trigger();
|
|
1208
|
-
}, false);
|
|
1209
|
-
return p.then(v => loadEnd(p, v, undefined, lookup), e => loadEnd(p, undefined, castError(e), lookup));
|
|
1210
|
-
}
|
|
1211
|
-
Object.defineProperties(read, {
|
|
1212
|
-
state: {
|
|
1213
|
-
get: () => state()
|
|
1214
|
-
},
|
|
1215
|
-
error: {
|
|
1216
|
-
get: () => error()
|
|
1217
|
-
},
|
|
1218
|
-
loading: {
|
|
1219
|
-
get() {
|
|
1220
|
-
const s = state();
|
|
1221
|
-
return s === "pending" || s === "refreshing";
|
|
1222
|
-
}
|
|
1223
|
-
},
|
|
1224
|
-
latest: {
|
|
1225
|
-
get() {
|
|
1226
|
-
if (!resolved) return read();
|
|
1227
|
-
const err = error();
|
|
1228
|
-
if (err && !pr) throw err;
|
|
1229
|
-
return value();
|
|
1230
|
-
}
|
|
1231
|
-
}
|
|
1232
|
-
});
|
|
1233
|
-
let owner = Owner;
|
|
1234
|
-
if (dynamic) createComputed(() => (owner = Owner, load(false)));else load(false);
|
|
1235
|
-
return [read, {
|
|
1236
|
-
refetch: info => runWithOwner(owner, () => load(info)),
|
|
1237
|
-
mutate: setValue
|
|
1238
|
-
}];
|
|
1239
|
-
}
|
|
1240
|
-
function untrack(fn) {
|
|
1241
|
-
if (Listener === null) return fn();
|
|
1242
|
-
const listener = Listener;
|
|
1243
|
-
Listener = null;
|
|
1244
|
-
try {
|
|
1245
|
-
if (ExternalSourceConfig) ;
|
|
1246
|
-
return fn();
|
|
1247
|
-
} finally {
|
|
1248
|
-
Listener = listener;
|
|
1249
|
-
}
|
|
1250
|
-
}
|
|
1251
|
-
function onMount(fn) {
|
|
1252
|
-
createEffect(() => untrack(fn));
|
|
1253
|
-
}
|
|
1254
|
-
function onCleanup(fn) {
|
|
1255
|
-
if (Owner === null) ;else if (Owner.cleanups === null) Owner.cleanups = [fn];else Owner.cleanups.push(fn);
|
|
1256
|
-
return fn;
|
|
1257
|
-
}
|
|
1258
|
-
function runWithOwner(o, fn) {
|
|
1259
|
-
const prev = Owner;
|
|
1260
|
-
const prevListener = Listener;
|
|
1261
|
-
Owner = o;
|
|
1262
|
-
Listener = null;
|
|
1263
|
-
try {
|
|
1264
|
-
return runUpdates(fn, true);
|
|
1265
|
-
} catch (err) {
|
|
1266
|
-
handleError(err);
|
|
1267
|
-
} finally {
|
|
1268
|
-
Owner = prev;
|
|
1269
|
-
Listener = prevListener;
|
|
1270
|
-
}
|
|
1271
|
-
}
|
|
1272
|
-
const [transPending, setTransPending] = /*@__PURE__*/createSignal(false);
|
|
1273
|
-
let SuspenseContext;
|
|
1274
|
-
function readSignal() {
|
|
1275
|
-
if (this.sources && (this.state)) {
|
|
1276
|
-
if ((this.state) === STALE) updateComputation(this);else {
|
|
1277
|
-
const updates = Updates;
|
|
1278
|
-
Updates = null;
|
|
1279
|
-
runUpdates(() => lookUpstream(this), false);
|
|
1280
|
-
Updates = updates;
|
|
1281
|
-
}
|
|
1282
|
-
}
|
|
1283
|
-
if (Listener) {
|
|
1284
|
-
const sSlot = this.observers ? this.observers.length : 0;
|
|
1285
|
-
if (!Listener.sources) {
|
|
1286
|
-
Listener.sources = [this];
|
|
1287
|
-
Listener.sourceSlots = [sSlot];
|
|
1288
|
-
} else {
|
|
1289
|
-
Listener.sources.push(this);
|
|
1290
|
-
Listener.sourceSlots.push(sSlot);
|
|
1291
|
-
}
|
|
1292
|
-
if (!this.observers) {
|
|
1293
|
-
this.observers = [Listener];
|
|
1294
|
-
this.observerSlots = [Listener.sources.length - 1];
|
|
1295
|
-
} else {
|
|
1296
|
-
this.observers.push(Listener);
|
|
1297
|
-
this.observerSlots.push(Listener.sources.length - 1);
|
|
1298
|
-
}
|
|
1299
871
|
}
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
runUpdates(() => {
|
|
1308
|
-
for (let i = 0; i < node.observers.length; i += 1) {
|
|
1309
|
-
const o = node.observers[i];
|
|
1310
|
-
const TransitionRunning = Transition && Transition.running;
|
|
1311
|
-
if (TransitionRunning && Transition.disposed.has(o)) ;
|
|
1312
|
-
if (TransitionRunning ? !o.tState : !o.state) {
|
|
1313
|
-
if (o.pure) Updates.push(o);else Effects.push(o);
|
|
1314
|
-
if (o.observers) markDownstream(o);
|
|
1315
|
-
}
|
|
1316
|
-
if (!TransitionRunning) o.state = STALE;
|
|
1317
|
-
}
|
|
1318
|
-
if (Updates.length > 10e5) {
|
|
1319
|
-
Updates = [];
|
|
1320
|
-
if (IS_DEV) ;
|
|
1321
|
-
throw new Error();
|
|
1322
|
-
}
|
|
1323
|
-
}, false);
|
|
1324
|
-
}
|
|
1325
|
-
}
|
|
1326
|
-
return value;
|
|
1327
|
-
}
|
|
1328
|
-
function updateComputation(node) {
|
|
1329
|
-
if (!node.fn) return;
|
|
1330
|
-
cleanNode(node);
|
|
1331
|
-
const time = ExecCount;
|
|
1332
|
-
runComputation(node, node.value, time);
|
|
1333
|
-
}
|
|
1334
|
-
function runComputation(node, value, time) {
|
|
1335
|
-
let nextValue;
|
|
1336
|
-
const owner = Owner,
|
|
1337
|
-
listener = Listener;
|
|
1338
|
-
Listener = Owner = node;
|
|
1339
|
-
try {
|
|
1340
|
-
nextValue = node.fn(value);
|
|
1341
|
-
} catch (err) {
|
|
1342
|
-
if (node.pure) {
|
|
1343
|
-
{
|
|
1344
|
-
node.state = STALE;
|
|
1345
|
-
node.owned && node.owned.forEach(cleanNode);
|
|
1346
|
-
node.owned = null;
|
|
1347
|
-
}
|
|
1348
|
-
}
|
|
1349
|
-
node.updatedAt = time + 1;
|
|
1350
|
-
return handleError(err);
|
|
1351
|
-
} finally {
|
|
1352
|
-
Listener = listener;
|
|
1353
|
-
Owner = owner;
|
|
1354
|
-
}
|
|
1355
|
-
if (!node.updatedAt || node.updatedAt <= time) {
|
|
1356
|
-
if (node.updatedAt != null && "observers" in node) {
|
|
1357
|
-
writeSignal(node, nextValue);
|
|
1358
|
-
} else node.value = nextValue;
|
|
1359
|
-
node.updatedAt = time;
|
|
872
|
+
/**
|
|
873
|
+
* Internal method to get the raw value.
|
|
874
|
+
* @internal
|
|
875
|
+
*/
|
|
876
|
+
_getRaw() {
|
|
877
|
+
if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
|
|
878
|
+
return this._value;
|
|
1360
879
|
}
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
value: init,
|
|
1372
|
-
owner: Owner,
|
|
1373
|
-
context: Owner ? Owner.context : null,
|
|
1374
|
-
pure
|
|
1375
|
-
};
|
|
1376
|
-
if (Owner === null) ;else if (Owner !== UNOWNED) {
|
|
1377
|
-
{
|
|
1378
|
-
if (!Owner.owned) Owner.owned = [c];else Owner.owned.push(c);
|
|
1379
|
-
}
|
|
880
|
+
/**
|
|
881
|
+
* Disposes the stream, releasing all resources.
|
|
882
|
+
* @remarks
|
|
883
|
+
* In addition to disposing the underlying observable, this method calls the disposer
|
|
884
|
+
* returned by the updater.
|
|
885
|
+
* @public
|
|
886
|
+
*/
|
|
887
|
+
dispose() {
|
|
888
|
+
super.dispose();
|
|
889
|
+
this._disposer();
|
|
1380
890
|
}
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
while ((node = node.owner) && (!node.updatedAt || node.updatedAt < ExecCount)) {
|
|
1389
|
-
if (node.state) ancestors.push(node);
|
|
1390
|
-
}
|
|
1391
|
-
for (let i = ancestors.length - 1; i >= 0; i--) {
|
|
1392
|
-
node = ancestors[i];
|
|
1393
|
-
if ((node.state) === STALE) {
|
|
1394
|
-
updateComputation(node);
|
|
1395
|
-
} else if ((node.state) === PENDING) {
|
|
1396
|
-
const updates = Updates;
|
|
1397
|
-
Updates = null;
|
|
1398
|
-
runUpdates(() => lookUpstream(node, ancestors[0]), false);
|
|
1399
|
-
Updates = updates;
|
|
1400
|
-
}
|
|
891
|
+
/* INTERNAL ------------------------------------------------------ */
|
|
892
|
+
_disposer;
|
|
893
|
+
_set(value) {
|
|
894
|
+
if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
|
|
895
|
+
if (value === this._value) return;
|
|
896
|
+
this._value = value;
|
|
897
|
+
this._notify();
|
|
1401
898
|
}
|
|
1402
899
|
}
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
900
|
+
|
|
901
|
+
class FlowStreamAsync extends FlowObservable {
|
|
902
|
+
/**
|
|
903
|
+
* Creates a new asynchronous FlowStream.
|
|
904
|
+
*
|
|
905
|
+
* @param updater - A function that receives a setter callback and returns a disposer.
|
|
906
|
+
* The setter should be called whenever new data is available (can be called asynchronously).
|
|
907
|
+
* The disposer will be invoked when the stream is disposed to clean up resources.
|
|
908
|
+
*
|
|
909
|
+
* @remarks
|
|
910
|
+
* The updater is invoked immediately during construction. An initial Promise is created
|
|
911
|
+
* that will resolve when the setter is first called. Make sure to return a proper cleanup
|
|
912
|
+
* function to avoid resource leaks.
|
|
913
|
+
*
|
|
914
|
+
* @public
|
|
915
|
+
*/
|
|
916
|
+
constructor(updater) {
|
|
917
|
+
super();
|
|
918
|
+
this._disposer = updater((value) => {
|
|
919
|
+
this._set(value);
|
|
920
|
+
});
|
|
921
|
+
this._value = new Promise((resolve) => {
|
|
922
|
+
this._resolve = resolve;
|
|
923
|
+
});
|
|
1417
924
|
}
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
const e = Effects;
|
|
1426
|
-
Effects = null;
|
|
1427
|
-
if (e.length) runUpdates(() => runEffects(e), false);
|
|
1428
|
-
}
|
|
1429
|
-
function runQueue(queue) {
|
|
1430
|
-
for (let i = 0; i < queue.length; i++) runTop(queue[i]);
|
|
1431
|
-
}
|
|
1432
|
-
function runUserEffects(queue) {
|
|
1433
|
-
let i,
|
|
1434
|
-
userLength = 0;
|
|
1435
|
-
for (i = 0; i < queue.length; i++) {
|
|
1436
|
-
const e = queue[i];
|
|
1437
|
-
if (!e.user) runTop(e);else queue[userLength++] = e;
|
|
1438
|
-
}
|
|
1439
|
-
for (i = 0; i < userLength; i++) runTop(queue[i]);
|
|
1440
|
-
}
|
|
1441
|
-
function lookUpstream(node, ignore) {
|
|
1442
|
-
node.state = 0;
|
|
1443
|
-
for (let i = 0; i < node.sources.length; i += 1) {
|
|
1444
|
-
const source = node.sources[i];
|
|
1445
|
-
if (source.sources) {
|
|
1446
|
-
const state = source.state;
|
|
1447
|
-
if (state === STALE) {
|
|
1448
|
-
if (source !== ignore && (!source.updatedAt || source.updatedAt < ExecCount)) runTop(source);
|
|
1449
|
-
} else if (state === PENDING) lookUpstream(source, ignore);
|
|
1450
|
-
}
|
|
925
|
+
/**
|
|
926
|
+
* Internal method to get the raw value.
|
|
927
|
+
* @internal
|
|
928
|
+
*/
|
|
929
|
+
_getRaw() {
|
|
930
|
+
if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
|
|
931
|
+
return this._value;
|
|
1451
932
|
}
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
933
|
+
/**
|
|
934
|
+
* Disposes the stream, releasing all resources.
|
|
935
|
+
* @remarks In addition to disposing the underlying observable, this method calls the disposer
|
|
936
|
+
* returned by the updater.
|
|
937
|
+
* @public
|
|
938
|
+
*/
|
|
939
|
+
dispose() {
|
|
940
|
+
super.dispose();
|
|
941
|
+
this._disposer();
|
|
1461
942
|
}
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
obs[index] = n;
|
|
1476
|
-
source.observerSlots[index] = s;
|
|
1477
|
-
}
|
|
1478
|
-
}
|
|
943
|
+
/* INTERNAL ------------------------------------------------------ */
|
|
944
|
+
_initialized = false;
|
|
945
|
+
_awaitedValue;
|
|
946
|
+
_resolve;
|
|
947
|
+
_disposer;
|
|
948
|
+
_set(value) {
|
|
949
|
+
if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
|
|
950
|
+
if (!this._initialized) {
|
|
951
|
+
this._resolve(value);
|
|
952
|
+
this._initialized = true;
|
|
953
|
+
this._awaitedValue = value;
|
|
954
|
+
this._notify();
|
|
955
|
+
return;
|
|
1479
956
|
}
|
|
957
|
+
if (value === this._awaitedValue) return;
|
|
958
|
+
this._value = Promise.resolve(value);
|
|
959
|
+
this._awaitedValue = value;
|
|
960
|
+
this._notify();
|
|
1480
961
|
}
|
|
1481
|
-
if (node.tOwned) {
|
|
1482
|
-
for (i = node.tOwned.length - 1; i >= 0; i--) cleanNode(node.tOwned[i]);
|
|
1483
|
-
delete node.tOwned;
|
|
1484
|
-
}
|
|
1485
|
-
if (node.owned) {
|
|
1486
|
-
for (i = node.owned.length - 1; i >= 0; i--) cleanNode(node.owned[i]);
|
|
1487
|
-
node.owned = null;
|
|
1488
|
-
}
|
|
1489
|
-
if (node.cleanups) {
|
|
1490
|
-
for (i = node.cleanups.length - 1; i >= 0; i--) node.cleanups[i]();
|
|
1491
|
-
node.cleanups = null;
|
|
1492
|
-
}
|
|
1493
|
-
node.state = 0;
|
|
1494
|
-
}
|
|
1495
|
-
function castError(err) {
|
|
1496
|
-
if (err instanceof Error) return err;
|
|
1497
|
-
return new Error(typeof err === "string" ? err : "Unknown error", {
|
|
1498
|
-
cause: err
|
|
1499
|
-
});
|
|
1500
|
-
}
|
|
1501
|
-
function handleError(err, owner = Owner) {
|
|
1502
|
-
const error = castError(err);
|
|
1503
|
-
throw error;
|
|
1504
962
|
}
|
|
1505
963
|
|
|
1506
964
|
class SolidState {
|
|
@@ -1567,11 +1025,11 @@ class SolidResource {
|
|
|
1567
1025
|
}
|
|
1568
1026
|
|
|
1569
1027
|
function fromSync(state) {
|
|
1570
|
-
const solidState = new SolidState(state.
|
|
1028
|
+
const solidState = new SolidState(state.pick());
|
|
1571
1029
|
let fx;
|
|
1572
1030
|
onMount(() => {
|
|
1573
|
-
fx = new FlowEffect
|
|
1574
|
-
const value = get(
|
|
1031
|
+
fx = new FlowEffect((t) => {
|
|
1032
|
+
const value = state.get(t);
|
|
1575
1033
|
solidState.set(() => value);
|
|
1576
1034
|
});
|
|
1577
1035
|
});
|
|
@@ -1580,13 +1038,13 @@ function fromSync(state) {
|
|
|
1580
1038
|
}
|
|
1581
1039
|
function fromAsync(derivation) {
|
|
1582
1040
|
const solidResource = new SolidResource(async () => {
|
|
1583
|
-
const value = await derivation.
|
|
1041
|
+
const value = await derivation.pick();
|
|
1584
1042
|
return value;
|
|
1585
1043
|
});
|
|
1586
1044
|
let fx;
|
|
1587
1045
|
onMount(() => {
|
|
1588
|
-
fx = new FlowEffect
|
|
1589
|
-
await get(
|
|
1046
|
+
fx = new FlowEffect(async (t) => {
|
|
1047
|
+
await derivation.get(t);
|
|
1590
1048
|
solidResource.refetch();
|
|
1591
1049
|
});
|
|
1592
1050
|
});
|
|
@@ -1594,7 +1052,7 @@ function fromAsync(derivation) {
|
|
|
1594
1052
|
return solidResource;
|
|
1595
1053
|
}
|
|
1596
1054
|
function shallowFrom(flow) {
|
|
1597
|
-
const initialValue = flow.
|
|
1055
|
+
const initialValue = flow.pick();
|
|
1598
1056
|
const isAsync = initialValue instanceof Promise;
|
|
1599
1057
|
if (isAsync) {
|
|
1600
1058
|
return fromAsync(flow);
|
|
@@ -1602,10 +1060,10 @@ function shallowFrom(flow) {
|
|
|
1602
1060
|
return fromSync(flow);
|
|
1603
1061
|
}
|
|
1604
1062
|
function deepFrom(getter) {
|
|
1605
|
-
const derivation = new FlowDerivation
|
|
1606
|
-
return getter(
|
|
1063
|
+
const derivation = new FlowDerivation((t) => {
|
|
1064
|
+
return getter(t);
|
|
1607
1065
|
});
|
|
1608
|
-
const initialValue = derivation.
|
|
1066
|
+
const initialValue = derivation.pick();
|
|
1609
1067
|
const isAsync = initialValue instanceof Promise;
|
|
1610
1068
|
if (isAsync) {
|
|
1611
1069
|
return fromAsync(derivation);
|
|
@@ -1613,10 +1071,10 @@ function deepFrom(getter) {
|
|
|
1613
1071
|
return fromSync(derivation);
|
|
1614
1072
|
}
|
|
1615
1073
|
function from(flow) {
|
|
1616
|
-
if (flow instanceof FlowObservable
|
|
1074
|
+
if (flow instanceof FlowObservable) {
|
|
1617
1075
|
return shallowFrom(flow);
|
|
1618
1076
|
}
|
|
1619
1077
|
return deepFrom(flow);
|
|
1620
1078
|
}
|
|
1621
1079
|
|
|
1622
|
-
export { FlowArray, FlowConstant, FlowDerivation, FlowEffect, FlowMap, FlowObservable, FlowResource, FlowResourceAsync, FlowSignal, FlowState, FlowStream, FlowStreamAsync, SolidDerivation, SolidResource, SolidState, array, constant, derivation, effect, from, isDisposable, map, resource, resourceAsync, signal, state, stream, streamAsync };
|
|
1080
|
+
export { FlowArray, FlowConstant, FlowDerivation, FlowEffect, FlowMap, FlowObservable, FlowResource, FlowResourceAsync, FlowSignal, FlowState, FlowStream, FlowStreamAsync, SolidDerivation, SolidResource, SolidState, TrackingContext, array, constant, derivation, effect, from, isDisposable, map, resource, resourceAsync, signal, state, stream, streamAsync };
|