@ersbeth/picoflow 0.2.4 → 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 +610 -436
- 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 -23
- 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/solid/converters.ts
CHANGED
|
@@ -1,73 +1,143 @@
|
|
|
1
|
-
import { onCleanup, onMount } from
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { onCleanup, onMount } from "solid-js";
|
|
2
|
+
import {
|
|
3
|
+
FlowDerivation,
|
|
4
|
+
FlowEffect,
|
|
5
|
+
FlowObservable,
|
|
6
|
+
type TrackingContext,
|
|
7
|
+
} from "../basic";
|
|
8
|
+
import { type SolidDerivation, SolidResource, SolidState } from "./primitives";
|
|
5
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Converts a synchronous FlowObservable into a SolidJS signal.
|
|
12
|
+
*
|
|
13
|
+
* @param state - The FlowObservable to convert.
|
|
14
|
+
* @returns A SolidDerivation that mirrors the FlowObservable's value.
|
|
15
|
+
*
|
|
16
|
+
* @remarks
|
|
17
|
+
* This internal helper bridges PicoFlow's reactive system with SolidJS by:
|
|
18
|
+
* 1. Reading the initial value without tracking (using `pick()`)
|
|
19
|
+
* 2. Creating a FlowEffect that tracks the observable and updates the Solid signal
|
|
20
|
+
* 3. Properly disposing the effect when the Solid component unmounts
|
|
21
|
+
*
|
|
22
|
+
* @internal
|
|
23
|
+
*/
|
|
6
24
|
function fromSync<T>(state: FlowObservable<T>): SolidDerivation<T> {
|
|
25
|
+
const solidState = new SolidState<T>(state.pick());
|
|
7
26
|
|
|
8
|
-
|
|
27
|
+
let fx: FlowEffect;
|
|
9
28
|
|
|
10
|
-
|
|
29
|
+
onMount(() => {
|
|
30
|
+
fx = new FlowEffect((t) => {
|
|
31
|
+
const value = state.get(t);
|
|
32
|
+
solidState.set(() => value);
|
|
33
|
+
});
|
|
34
|
+
});
|
|
11
35
|
|
|
12
|
-
|
|
13
|
-
fx = new FlowEffect((get) => {
|
|
14
|
-
const value = get(state);
|
|
15
|
-
solidState.set(() => value);
|
|
16
|
-
});
|
|
17
|
-
});
|
|
36
|
+
onCleanup(() => fx.dispose());
|
|
18
37
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
return solidState
|
|
38
|
+
return solidState;
|
|
22
39
|
}
|
|
23
40
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
41
|
+
/**
|
|
42
|
+
* Converts an asynchronous FlowObservable (Promise-based) into a SolidJS resource.
|
|
43
|
+
*
|
|
44
|
+
* @param derivation - The FlowObservable that resolves to a Promise.
|
|
45
|
+
* @returns A SolidResource that mirrors the FlowObservable's async value.
|
|
46
|
+
*
|
|
47
|
+
* @remarks
|
|
48
|
+
* This internal helper bridges PicoFlow's async reactive system with SolidJS by:
|
|
49
|
+
* 1. Creating a SolidResource with an initial fetch using `pick()` (untracked)
|
|
50
|
+
* 2. Setting up a FlowEffect that tracks the Promise observable
|
|
51
|
+
* 3. Refetching the SolidResource whenever the Promise observable changes
|
|
52
|
+
* 4. Properly disposing the effect when the Solid component unmounts
|
|
53
|
+
*
|
|
54
|
+
* @internal
|
|
55
|
+
*/
|
|
56
|
+
function fromAsync<T>(
|
|
57
|
+
derivation: FlowObservable<Promise<T>>,
|
|
58
|
+
): SolidResource<T> {
|
|
59
|
+
const solidResource = new SolidResource<T>(async () => {
|
|
60
|
+
const value = await derivation.pick();
|
|
61
|
+
return value;
|
|
62
|
+
});
|
|
30
63
|
|
|
31
|
-
|
|
64
|
+
let fx: FlowEffect;
|
|
32
65
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
66
|
+
onMount(() => {
|
|
67
|
+
fx = new FlowEffect(async (t) => {
|
|
68
|
+
await derivation.get(t);
|
|
69
|
+
solidResource.refetch();
|
|
70
|
+
});
|
|
71
|
+
});
|
|
39
72
|
|
|
40
|
-
|
|
73
|
+
onCleanup(() => fx.dispose());
|
|
41
74
|
|
|
42
|
-
|
|
75
|
+
return solidResource;
|
|
43
76
|
}
|
|
44
77
|
|
|
78
|
+
/**
|
|
79
|
+
* Converts a FlowObservable directly into a Solid primitive (signal or resource).
|
|
80
|
+
*
|
|
81
|
+
* @param flow - The FlowObservable to convert (can be sync or async).
|
|
82
|
+
* @returns A SolidDerivation for sync values or SolidResource for async values.
|
|
83
|
+
*
|
|
84
|
+
* @remarks
|
|
85
|
+
* This internal helper performs "shallow" conversion, meaning it converts the
|
|
86
|
+
* observable itself without creating an intermediate FlowDerivation. It inspects
|
|
87
|
+
* the initial value to determine if it's a Promise, then delegates to the
|
|
88
|
+
* appropriate converter (fromSync or fromAsync).
|
|
89
|
+
*
|
|
90
|
+
* @internal
|
|
91
|
+
*/
|
|
45
92
|
function shallowFrom<T>(flow: FlowObservable<Promise<T>>): SolidResource<T>;
|
|
46
93
|
function shallowFrom<T>(flow: FlowObservable<T>): SolidDerivation<T>;
|
|
47
|
-
function shallowFrom<T>(
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
94
|
+
function shallowFrom<T>(
|
|
95
|
+
flow: FlowObservable<Promise<T>> | FlowObservable<T>,
|
|
96
|
+
): SolidDerivation<T> | SolidResource<T> {
|
|
97
|
+
const initialValue = flow.pick();
|
|
98
|
+
const isAsync = initialValue instanceof Promise;
|
|
99
|
+
if (isAsync) {
|
|
100
|
+
return fromAsync(flow as FlowObservable<Promise<T>>);
|
|
101
|
+
}
|
|
102
|
+
return fromSync(flow as FlowObservable<T>);
|
|
54
103
|
}
|
|
55
104
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
105
|
+
/**
|
|
106
|
+
* Converts a getter function with TrackingContext into a Solid primitive (signal or resource).
|
|
107
|
+
*
|
|
108
|
+
* @param getter - A function that computes a value using a TrackingContext.
|
|
109
|
+
* @returns A SolidDerivation for sync values or SolidResource for async values.
|
|
110
|
+
*
|
|
111
|
+
* @remarks
|
|
112
|
+
* This internal helper performs "deep" conversion by:
|
|
113
|
+
* 1. Creating a FlowDerivation from the getter function
|
|
114
|
+
* 2. Inspecting the initial computed value to determine if it's a Promise
|
|
115
|
+
* 3. Delegating to the appropriate converter (fromSync or fromAsync)
|
|
116
|
+
*
|
|
117
|
+
* This allows users to pass computation functions directly to `from()` without
|
|
118
|
+
* manually creating a FlowDerivation first.
|
|
119
|
+
*
|
|
120
|
+
* @internal
|
|
121
|
+
*/
|
|
122
|
+
function deepFrom<T>(getter: (t: TrackingContext) => T): SolidDerivation<T>;
|
|
123
|
+
function deepFrom<T>(
|
|
124
|
+
getter: (t: TrackingContext) => Promise<T>,
|
|
125
|
+
): SolidResource<T>;
|
|
126
|
+
function deepFrom<T>(
|
|
127
|
+
getter: (t: TrackingContext) => T | Promise<T>,
|
|
128
|
+
): SolidDerivation<T> | SolidResource<T> {
|
|
129
|
+
const derivation = new FlowDerivation((t) => {
|
|
130
|
+
return getter(t);
|
|
131
|
+
});
|
|
62
132
|
|
|
63
|
-
|
|
64
|
-
|
|
133
|
+
const initialValue = derivation.pick();
|
|
134
|
+
const isAsync = initialValue instanceof Promise;
|
|
65
135
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
136
|
+
if (isAsync) {
|
|
137
|
+
return fromAsync(derivation as FlowObservable<Promise<T>>);
|
|
138
|
+
}
|
|
69
139
|
|
|
70
|
-
|
|
140
|
+
return fromSync(derivation as FlowObservable<T>);
|
|
71
141
|
}
|
|
72
142
|
|
|
73
143
|
/**
|
|
@@ -86,7 +156,9 @@ export type NotPromise<T> = T extends Promise<unknown> ? never : T;
|
|
|
86
156
|
*
|
|
87
157
|
* @public
|
|
88
158
|
*/
|
|
89
|
-
export function from<T>(
|
|
159
|
+
export function from<T>(
|
|
160
|
+
flow: FlowObservable<Promise<NotPromise<T>>>,
|
|
161
|
+
): SolidResource<NotPromise<T>>;
|
|
90
162
|
/**
|
|
91
163
|
* Converts a FlowObservable of a non-Promise value into a SolidDerivation.
|
|
92
164
|
*
|
|
@@ -95,7 +167,9 @@ export function from<T>(flow: FlowObservable<Promise<NotPromise<T>>>): SolidReso
|
|
|
95
167
|
*
|
|
96
168
|
* @public
|
|
97
169
|
*/
|
|
98
|
-
export function from<T>(
|
|
170
|
+
export function from<T>(
|
|
171
|
+
flow: FlowObservable<NotPromise<T>>,
|
|
172
|
+
): SolidDerivation<NotPromise<T>>;
|
|
99
173
|
/**
|
|
100
174
|
* Converts a FlowObservable into a Solid derivation or resource, depending on whether the value is synchronous or asynchronous.
|
|
101
175
|
*
|
|
@@ -105,7 +179,7 @@ export function from<T>(flow: FlowObservable<NotPromise<T>>): SolidDerivation<No
|
|
|
105
179
|
* @public
|
|
106
180
|
*/
|
|
107
181
|
export function from<T>(
|
|
108
|
-
|
|
182
|
+
flow: FlowObservable<Promise<NotPromise<T>>> | FlowObservable<NotPromise<T>>,
|
|
109
183
|
): SolidDerivation<NotPromise<T>> | SolidResource<NotPromise<T>>;
|
|
110
184
|
/**
|
|
111
185
|
* Converts a getter function returning a non-Promise value into a SolidDerivation.
|
|
@@ -115,7 +189,9 @@ export function from<T>(
|
|
|
115
189
|
*
|
|
116
190
|
* @public
|
|
117
191
|
*/
|
|
118
|
-
export function from<T>(
|
|
192
|
+
export function from<T>(
|
|
193
|
+
flow: (t: TrackingContext) => NotPromise<T>,
|
|
194
|
+
): SolidDerivation<NotPromise<T>>;
|
|
119
195
|
/**
|
|
120
196
|
* Converts a getter function returning a Promise into a SolidResource.
|
|
121
197
|
*
|
|
@@ -124,7 +200,9 @@ export function from<T>(flow: (get: FlowGetter) => NotPromise<T>): SolidDerivati
|
|
|
124
200
|
*
|
|
125
201
|
* @public
|
|
126
202
|
*/
|
|
127
|
-
export function from<T>(
|
|
203
|
+
export function from<T>(
|
|
204
|
+
flow: (t: TrackingContext) => Promise<NotPromise<T>>,
|
|
205
|
+
): SolidResource<NotPromise<T>>;
|
|
128
206
|
/**
|
|
129
207
|
* Converts a getter function into a Solid derivation or resource, depending on whether the returned value is synchronous or asynchronous.
|
|
130
208
|
*
|
|
@@ -134,26 +212,67 @@ export function from<T>(flow: (get: FlowGetter) => Promise<NotPromise<T>>): Soli
|
|
|
134
212
|
* @public
|
|
135
213
|
*/
|
|
136
214
|
export function from<T>(
|
|
137
|
-
|
|
215
|
+
flow:
|
|
216
|
+
| ((t: TrackingContext) => NotPromise<T>)
|
|
217
|
+
| ((t: TrackingContext) => Promise<NotPromise<T>>),
|
|
138
218
|
): SolidDerivation<T> | SolidResource<T>;
|
|
139
219
|
/**
|
|
140
220
|
* Converts a FlowObservable or getter function into a Solid derivation or resource, depending on whether the value is synchronous or asynchronous.
|
|
141
221
|
*
|
|
142
|
-
* - If passed a FlowObservable of a non-Promise value, returns a SolidDerivation.
|
|
143
|
-
* - If passed a FlowObservable of a Promise, returns a SolidResource.
|
|
144
|
-
* - If passed a getter function returning a non-Promise value, returns a SolidDerivation.
|
|
145
|
-
* - If passed a getter function returning a Promise, returns a SolidResource.
|
|
146
|
-
*
|
|
147
222
|
* @param flow - The FlowObservable or getter function to convert.
|
|
148
|
-
* @returns A SolidDerivation or SolidResource, depending on the input type.
|
|
223
|
+
* @returns A SolidDerivation or SolidResource, depending on the input type.
|
|
224
|
+
*
|
|
225
|
+
* @remarks
|
|
226
|
+
* This function bridges PicoFlow's reactive system with SolidJS, allowing you to use
|
|
227
|
+
* PicoFlow observables within Solid components. The conversion is automatic based on
|
|
228
|
+
* whether the value is a Promise or not:
|
|
229
|
+
*
|
|
230
|
+
* - **FlowObservable of non-Promise value** → SolidDerivation (reactive signal)
|
|
231
|
+
* - **FlowObservable of Promise** → SolidResource (async resource)
|
|
232
|
+
* - **Getter function returning non-Promise** → SolidDerivation (computed signal)
|
|
233
|
+
* - **Getter function returning Promise** → SolidResource (async computed resource)
|
|
234
|
+
*
|
|
235
|
+
* The created Solid primitives automatically subscribe to the PicoFlow observables and
|
|
236
|
+
* update when changes occur. The subscription is properly cleaned up when the Solid
|
|
237
|
+
* component unmounts.
|
|
238
|
+
*
|
|
239
|
+
* @example
|
|
240
|
+
* ```typescript
|
|
241
|
+
* import { from } from 'picoflow/solid';
|
|
242
|
+
* import { state } from 'picoflow';
|
|
243
|
+
*
|
|
244
|
+
* // Convert a PicoFlow state to a Solid signal
|
|
245
|
+
* const $count = state(0);
|
|
246
|
+
* const solidCount = from($count);
|
|
247
|
+
*
|
|
248
|
+
* // Use in a Solid component
|
|
249
|
+
* function Counter() {
|
|
250
|
+
* const count = solidCount.get(); // Solid's reactive get
|
|
251
|
+
* return <div>Count: {count}</div>;
|
|
252
|
+
* }
|
|
253
|
+
*
|
|
254
|
+
* // Or convert a computation function
|
|
255
|
+
* const solidDerived = from((t) => {
|
|
256
|
+
* return $count.get(t) * 2;
|
|
257
|
+
* });
|
|
258
|
+
* ```
|
|
259
|
+
*
|
|
149
260
|
* @public
|
|
150
261
|
*/
|
|
151
262
|
export function from<T>(
|
|
152
|
-
|
|
263
|
+
flow:
|
|
264
|
+
| FlowObservable<Promise<T>>
|
|
265
|
+
| FlowObservable<T>
|
|
266
|
+
| ((t: TrackingContext) => T)
|
|
267
|
+
| ((t: TrackingContext) => Promise<T>),
|
|
153
268
|
): SolidDerivation<T> | SolidResource<T> {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
269
|
+
if (flow instanceof FlowObservable) {
|
|
270
|
+
return shallowFrom(flow as FlowObservable<T | Promise<T>>) as
|
|
271
|
+
| SolidDerivation<T>
|
|
272
|
+
| SolidResource<T>;
|
|
273
|
+
}
|
|
157
274
|
|
|
158
|
-
|
|
159
|
-
|
|
275
|
+
return deepFrom(flow as (t: TrackingContext) => T | Promise<T>) as
|
|
276
|
+
| SolidDerivation<T>
|
|
277
|
+
| SolidResource<T>;
|
|
278
|
+
}
|
package/src/solid/index.ts
CHANGED
|
@@ -1,2 +1,8 @@
|
|
|
1
|
-
export { from } from
|
|
2
|
-
export {
|
|
1
|
+
export { from, type NotPromise } from "./converters";
|
|
2
|
+
export {
|
|
3
|
+
SolidDerivation,
|
|
4
|
+
type SolidGetter,
|
|
5
|
+
type SolidObservable,
|
|
6
|
+
SolidResource,
|
|
7
|
+
SolidState,
|
|
8
|
+
} from "./primitives";
|
package/src/solid/primitives.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
createMemo,
|
|
3
|
+
createResource,
|
|
4
|
+
createSignal,
|
|
5
|
+
type ResourceFetcher,
|
|
6
|
+
} from "solid-js";
|
|
2
7
|
|
|
3
8
|
/**
|
|
4
9
|
* A getter function or value for Solid state/derivation.
|
|
@@ -15,95 +20,192 @@ export type SolidGetter<T> = ((previous: T) => T) | T;
|
|
|
15
20
|
* @public
|
|
16
21
|
*/
|
|
17
22
|
export interface SolidObservable<T> {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Returns the current value.
|
|
25
|
+
*/
|
|
26
|
+
get: () => T;
|
|
22
27
|
}
|
|
23
28
|
|
|
24
29
|
/**
|
|
25
|
-
* Solid-style state container,
|
|
30
|
+
* Solid-style state container wrapping SolidJS's createSignal, providing a writable reactive signal.
|
|
31
|
+
*
|
|
32
|
+
* @remarks
|
|
33
|
+
* SolidState is a thin wrapper around SolidJS's `createSignal` that provides a class-based
|
|
34
|
+
* interface consistent with PicoFlow's API style. It's used internally by PicoFlow's Solid
|
|
35
|
+
* integration but can also be used directly in Solid components.
|
|
36
|
+
*
|
|
37
|
+
* Unlike PicoFlow's {@link FlowState} which uses explicit tracking context, SolidState
|
|
38
|
+
* relies on SolidJS's automatic dependency tracking within reactive contexts like
|
|
39
|
+
* `createEffect` or component render functions.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```typescript
|
|
43
|
+
* const count = new SolidState(0);
|
|
44
|
+
*
|
|
45
|
+
* // In a Solid component
|
|
46
|
+
* function Counter() {
|
|
47
|
+
* return <div>{count.get()}</div>; // Automatically reactive
|
|
48
|
+
* }
|
|
49
|
+
*
|
|
50
|
+
* // Update the value
|
|
51
|
+
* count.set(1);
|
|
52
|
+
* count.set(prev => prev + 1);
|
|
53
|
+
* ```
|
|
26
54
|
*
|
|
27
55
|
* @typeParam T - The value type.
|
|
28
56
|
* @public
|
|
29
57
|
*/
|
|
30
58
|
export class SolidState<T> implements SolidObservable<T> {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
59
|
+
/**
|
|
60
|
+
* Returns the current value.
|
|
61
|
+
*/
|
|
62
|
+
readonly get: () => T;
|
|
63
|
+
/**
|
|
64
|
+
* Sets the value or updates it using a getter function.
|
|
65
|
+
*/
|
|
66
|
+
readonly set: (param: SolidGetter<T>) => void;
|
|
39
67
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
68
|
+
/**
|
|
69
|
+
* Creates a new SolidState with the given initial value.
|
|
70
|
+
* @param initialValue - The initial value.
|
|
71
|
+
*/
|
|
72
|
+
constructor(initialValue: T) {
|
|
73
|
+
const [get, set] = createSignal<T>(initialValue);
|
|
74
|
+
this.get = get;
|
|
75
|
+
this.set = set;
|
|
76
|
+
}
|
|
49
77
|
}
|
|
50
78
|
|
|
51
79
|
type EffectFunction<Prev, Next extends Prev = Prev> = (v: Prev) => Next;
|
|
52
80
|
/**
|
|
53
|
-
* Solid-style derivation,
|
|
81
|
+
* Solid-style derivation wrapping SolidJS's createMemo, providing a computed reactive value.
|
|
82
|
+
*
|
|
83
|
+
* @remarks
|
|
84
|
+
* SolidDerivation is a thin wrapper around SolidJS's `createMemo` that provides a class-based
|
|
85
|
+
* interface consistent with PicoFlow's API style. It creates a memoized computation that
|
|
86
|
+
* automatically tracks its dependencies and recomputes only when they change.
|
|
87
|
+
*
|
|
88
|
+
* Unlike PicoFlow's {@link FlowDerivation} which uses explicit tracking context, SolidDerivation
|
|
89
|
+
* relies on SolidJS's automatic dependency tracking. The computation function runs within
|
|
90
|
+
* SolidJS's reactive scope and automatically subscribes to any signals accessed during execution.
|
|
91
|
+
*
|
|
92
|
+
* **Memoization:**
|
|
93
|
+
* The computed value is cached and only recomputed when tracked dependencies change,
|
|
94
|
+
* providing efficient derived state management.
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```typescript
|
|
98
|
+
* const firstName = new SolidState('John');
|
|
99
|
+
* const lastName = new SolidState('Doe');
|
|
100
|
+
*
|
|
101
|
+
* const fullName = new SolidDerivation(() => {
|
|
102
|
+
* return `${firstName.get()} ${lastName.get()}`;
|
|
103
|
+
* });
|
|
104
|
+
*
|
|
105
|
+
* // In a Solid component
|
|
106
|
+
* function Display() {
|
|
107
|
+
* return <div>{fullName.get()}</div>; // Automatically updates
|
|
108
|
+
* }
|
|
109
|
+
* ```
|
|
54
110
|
*
|
|
55
111
|
* @typeParam T - The value type.
|
|
56
112
|
* @public
|
|
57
113
|
*/
|
|
58
114
|
export class SolidDerivation<T> implements SolidObservable<T> {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
115
|
+
/**
|
|
116
|
+
* Returns the current derived value.
|
|
117
|
+
*/
|
|
118
|
+
readonly get: () => T;
|
|
63
119
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
120
|
+
/**
|
|
121
|
+
* Creates a new SolidDerivation from a getter function or value.
|
|
122
|
+
* @param calculator - The getter function or value.
|
|
123
|
+
*/
|
|
124
|
+
constructor(calculator: SolidGetter<T>) {
|
|
125
|
+
const get = createMemo<T>(calculator as EffectFunction<T | undefined, T>);
|
|
126
|
+
this.get = get;
|
|
127
|
+
}
|
|
72
128
|
}
|
|
73
129
|
|
|
74
130
|
/**
|
|
75
|
-
* Solid-style resource
|
|
131
|
+
* Solid-style resource wrapping SolidJS's createResource, providing async data loading with reactive state.
|
|
132
|
+
*
|
|
133
|
+
* @remarks
|
|
134
|
+
* SolidResource is a thin wrapper around SolidJS's `createResource` that provides a class-based
|
|
135
|
+
* interface consistent with PicoFlow's API style. It manages asynchronous data fetching with
|
|
136
|
+
* built-in loading states, error handling, and automatic reactivity.
|
|
137
|
+
*
|
|
138
|
+
* Unlike PicoFlow's {@link FlowResource} or {@link FlowResourceAsync}, SolidResource integrates
|
|
139
|
+
* directly with SolidJS's Suspense and ErrorBoundary mechanisms, providing a first-class async
|
|
140
|
+
* data loading experience in Solid applications.
|
|
141
|
+
*
|
|
142
|
+
* **Resource States:**
|
|
143
|
+
* - `unresolved`: Initial state before first fetch
|
|
144
|
+
* - `pending`: Fetch is in progress
|
|
145
|
+
* - `ready`: Data has been successfully loaded
|
|
146
|
+
* - `refreshing`: Refetching while previous data is still available
|
|
147
|
+
* - `errored`: Fetch failed with an error
|
|
148
|
+
*
|
|
149
|
+
* **Properties:**
|
|
150
|
+
* - `get()`: Returns the current value (or undefined if not ready)
|
|
151
|
+
* - `state()`: Returns the current loading state
|
|
152
|
+
* - `latest()`: Returns the most recent successfully loaded value
|
|
153
|
+
* - `refetch()`: Triggers a new fetch operation
|
|
154
|
+
*
|
|
155
|
+
* @example
|
|
156
|
+
* ```typescript
|
|
157
|
+
* const user = new SolidResource(async () => {
|
|
158
|
+
* const res = await fetch('/api/user');
|
|
159
|
+
* return res.json();
|
|
160
|
+
* });
|
|
161
|
+
*
|
|
162
|
+
* // In a Solid component
|
|
163
|
+
* function UserProfile() {
|
|
164
|
+
* return (
|
|
165
|
+
* <div>
|
|
166
|
+
* {user.state() === 'pending' && <p>Loading...</p>}
|
|
167
|
+
* {user.state() === 'ready' && <p>Name: {user.get()?.name}</p>}
|
|
168
|
+
* <button onClick={() => user.refetch()}>Refresh</button>
|
|
169
|
+
* </div>
|
|
170
|
+
* );
|
|
171
|
+
* }
|
|
172
|
+
* ```
|
|
76
173
|
*
|
|
77
174
|
* @typeParam T - The value type.
|
|
78
175
|
* @public
|
|
79
176
|
*/
|
|
80
177
|
export class SolidResource<T> implements SolidObservable<T | undefined> {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
178
|
+
/**
|
|
179
|
+
* Returns the current value (or undefined if not yet loaded).
|
|
180
|
+
*/
|
|
181
|
+
readonly get: () => T | undefined;
|
|
182
|
+
/**
|
|
183
|
+
* Returns the current resource state.
|
|
184
|
+
*/
|
|
185
|
+
readonly state: () =>
|
|
186
|
+
| "unresolved"
|
|
187
|
+
| "pending"
|
|
188
|
+
| "errored"
|
|
189
|
+
| "ready"
|
|
190
|
+
| "refreshing";
|
|
191
|
+
/**
|
|
192
|
+
* Returns the latest successfully loaded value (or undefined).
|
|
193
|
+
*/
|
|
194
|
+
readonly latest: () => T | undefined;
|
|
195
|
+
/**
|
|
196
|
+
* Triggers a refetch of the resource.
|
|
197
|
+
*/
|
|
198
|
+
readonly refetch: () => void;
|
|
97
199
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}
|
|
200
|
+
/**
|
|
201
|
+
* Creates a new SolidResource from a fetcher function.
|
|
202
|
+
* @param fetcher - The async fetcher function.
|
|
203
|
+
*/
|
|
204
|
+
constructor(fetcher: ResourceFetcher<true, T, unknown>) {
|
|
205
|
+
const [get, set] = createResource<T>(fetcher);
|
|
206
|
+
this.get = get;
|
|
207
|
+
this.state = () => get.state;
|
|
208
|
+
this.latest = () => get.latest;
|
|
209
|
+
this.refetch = () => set.refetch();
|
|
210
|
+
}
|
|
211
|
+
}
|