@ersbeth/picoflow 1.0.0 → 1.1.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/unifier-flowresource-avec-flowderivation-c9506e24.plan.md +372 -0
- package/README.md +25 -171
- package/biome.json +4 -1
- package/dist/picoflow.js +1129 -661
- package/dist/types/flow/base/flowDisposable.d.ts +67 -0
- package/dist/types/flow/base/flowDisposable.d.ts.map +1 -0
- package/dist/types/flow/base/flowEffect.d.ts +127 -0
- package/dist/types/flow/base/flowEffect.d.ts.map +1 -0
- package/dist/types/flow/base/flowGraph.d.ts +97 -0
- package/dist/types/flow/base/flowGraph.d.ts.map +1 -0
- package/dist/types/flow/base/flowSignal.d.ts +134 -0
- package/dist/types/flow/base/flowSignal.d.ts.map +1 -0
- package/dist/types/flow/base/flowTracker.d.ts +15 -0
- package/dist/types/flow/base/flowTracker.d.ts.map +1 -0
- package/dist/types/flow/base/index.d.ts +7 -0
- package/dist/types/flow/base/index.d.ts.map +1 -0
- package/dist/types/flow/base/utils.d.ts +20 -0
- package/dist/types/flow/base/utils.d.ts.map +1 -0
- package/dist/types/{advanced/array.d.ts → flow/collections/flowArray.d.ts} +50 -12
- package/dist/types/flow/collections/flowArray.d.ts.map +1 -0
- package/dist/types/flow/collections/flowMap.d.ts +224 -0
- package/dist/types/flow/collections/flowMap.d.ts.map +1 -0
- package/dist/types/flow/collections/index.d.ts +3 -0
- package/dist/types/flow/collections/index.d.ts.map +1 -0
- package/dist/types/flow/index.d.ts +4 -0
- package/dist/types/flow/index.d.ts.map +1 -0
- package/dist/types/flow/nodes/async/flowConstantAsync.d.ts +137 -0
- package/dist/types/flow/nodes/async/flowConstantAsync.d.ts.map +1 -0
- package/dist/types/flow/nodes/async/flowDerivationAsync.d.ts +137 -0
- package/dist/types/flow/nodes/async/flowDerivationAsync.d.ts.map +1 -0
- package/dist/types/flow/nodes/async/flowNodeAsync.d.ts +343 -0
- package/dist/types/flow/nodes/async/flowNodeAsync.d.ts.map +1 -0
- package/dist/types/flow/nodes/async/flowReadonlyAsync.d.ts +81 -0
- package/dist/types/flow/nodes/async/flowReadonlyAsync.d.ts.map +1 -0
- package/dist/types/flow/nodes/async/flowStateAsync.d.ts +111 -0
- package/dist/types/flow/nodes/async/flowStateAsync.d.ts.map +1 -0
- package/dist/types/flow/nodes/async/index.d.ts +6 -0
- package/dist/types/flow/nodes/async/index.d.ts.map +1 -0
- package/dist/types/flow/nodes/index.d.ts +3 -0
- package/dist/types/flow/nodes/index.d.ts.map +1 -0
- package/dist/types/flow/nodes/sync/flowConstant.d.ts +108 -0
- package/dist/types/flow/nodes/sync/flowConstant.d.ts.map +1 -0
- package/dist/types/flow/nodes/sync/flowDerivation.d.ts +100 -0
- package/dist/types/flow/nodes/sync/flowDerivation.d.ts.map +1 -0
- package/dist/types/flow/nodes/sync/flowNode.d.ts +314 -0
- package/dist/types/flow/nodes/sync/flowNode.d.ts.map +1 -0
- package/dist/types/flow/nodes/sync/flowReadonly.d.ts +57 -0
- package/dist/types/flow/nodes/sync/flowReadonly.d.ts.map +1 -0
- package/dist/types/flow/nodes/sync/flowState.d.ts +96 -0
- package/dist/types/flow/nodes/sync/flowState.d.ts.map +1 -0
- package/dist/types/flow/nodes/sync/index.d.ts +6 -0
- package/dist/types/flow/nodes/sync/index.d.ts.map +1 -0
- package/dist/types/index.d.ts +1 -4
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/solid/converters.d.ts +34 -44
- package/dist/types/solid/converters.d.ts.map +1 -1
- package/dist/types/solid/primitives.d.ts +1 -0
- package/dist/types/solid/primitives.d.ts.map +1 -1
- package/docs/.vitepress/config.mts +1 -1
- package/docs/api/typedoc-sidebar.json +81 -1
- package/package.json +60 -58
- package/src/flow/base/flowDisposable.ts +71 -0
- package/src/flow/base/flowEffect.ts +171 -0
- package/src/flow/base/flowGraph.ts +288 -0
- package/src/flow/base/flowSignal.ts +207 -0
- package/src/flow/base/flowTracker.ts +17 -0
- package/src/flow/base/index.ts +6 -0
- package/src/flow/base/utils.ts +19 -0
- package/src/flow/collections/flowArray.ts +409 -0
- package/src/flow/collections/flowMap.ts +398 -0
- package/src/flow/collections/index.ts +2 -0
- package/src/flow/index.ts +3 -0
- package/src/flow/nodes/async/flowConstantAsync.ts +142 -0
- package/src/flow/nodes/async/flowDerivationAsync.ts +143 -0
- package/src/flow/nodes/async/flowNodeAsync.ts +474 -0
- package/src/flow/nodes/async/flowReadonlyAsync.ts +81 -0
- package/src/flow/nodes/async/flowStateAsync.ts +116 -0
- package/src/flow/nodes/async/index.ts +5 -0
- package/src/flow/nodes/await/advanced/index.ts +5 -0
- package/src/{advanced → flow/nodes/await/advanced}/resource.ts +37 -3
- package/src/{advanced → flow/nodes/await/advanced}/resourceAsync.ts +35 -3
- package/src/{advanced → flow/nodes/await/advanced}/stream.ts +40 -2
- package/src/{advanced → flow/nodes/await/advanced}/streamAsync.ts +38 -3
- package/src/flow/nodes/await/flowConstantAwait.ts +154 -0
- package/src/flow/nodes/await/flowDerivationAwait.ts +154 -0
- package/src/flow/nodes/await/flowNodeAwait.ts +508 -0
- package/src/flow/nodes/await/flowReadonlyAwait.ts +89 -0
- package/src/flow/nodes/await/flowStateAwait.ts +130 -0
- package/src/flow/nodes/await/index.ts +5 -0
- package/src/flow/nodes/index.ts +3 -0
- package/src/flow/nodes/sync/flowConstant.ts +111 -0
- package/src/flow/nodes/sync/flowDerivation.ts +105 -0
- package/src/flow/nodes/sync/flowNode.ts +439 -0
- package/src/flow/nodes/sync/flowReadonly.ts +57 -0
- package/src/flow/nodes/sync/flowState.ts +101 -0
- package/src/flow/nodes/sync/index.ts +5 -0
- package/src/index.ts +1 -47
- package/src/solid/converters.ts +59 -198
- package/src/solid/primitives.ts +4 -0
- package/test/base/flowEffect.test.ts +108 -0
- package/test/base/flowGraph.test.ts +485 -0
- package/test/base/flowSignal.test.ts +372 -0
- package/test/collections/flowArray.asyncStates.test.ts +1553 -0
- package/test/collections/flowArray.scalars.test.ts +1129 -0
- package/test/collections/flowArray.states.test.ts +1365 -0
- package/test/collections/flowMap.asyncStates.test.ts +1105 -0
- package/test/collections/flowMap.scalars.test.ts +877 -0
- package/test/collections/flowMap.states.test.ts +1097 -0
- package/test/nodes/async/flowConstantAsync.test.ts +860 -0
- package/test/nodes/async/flowDerivationAsync.test.ts +1517 -0
- package/test/nodes/async/flowStateAsync.test.ts +1387 -0
- package/test/{resource.test.ts → nodes/await/advanced/resource.test.ts} +21 -19
- package/test/{resourceAsync.test.ts → nodes/await/advanced/resourceAsync.test.ts} +3 -1
- package/test/{stream.test.ts → nodes/await/advanced/stream.test.ts} +30 -28
- package/test/{streamAsync.test.ts → nodes/await/advanced/streamAsync.test.ts} +16 -14
- package/test/nodes/await/flowConstantAwait.test.ts +643 -0
- package/test/nodes/await/flowDerivationAwait.test.ts +1583 -0
- package/test/nodes/await/flowStateAwait.test.ts +999 -0
- package/test/nodes/mixed/derivation.test.ts +1527 -0
- package/test/nodes/sync/flowConstant.test.ts +620 -0
- package/test/nodes/sync/flowDerivation.test.ts +1373 -0
- package/test/nodes/sync/flowState.test.ts +945 -0
- package/test/solid/converters.test.ts +721 -0
- package/test/solid/primitives.test.ts +1031 -0
- package/tsconfig.json +2 -1
- package/vitest.config.ts +7 -1
- package/IMPLEMENTATION_GUIDE.md +0 -1578
- package/dist/types/advanced/array.d.ts.map +0 -1
- package/dist/types/advanced/index.d.ts +0 -9
- package/dist/types/advanced/index.d.ts.map +0 -1
- package/dist/types/advanced/map.d.ts +0 -166
- package/dist/types/advanced/map.d.ts.map +0 -1
- package/dist/types/advanced/resource.d.ts +0 -78
- package/dist/types/advanced/resource.d.ts.map +0 -1
- package/dist/types/advanced/resourceAsync.d.ts +0 -56
- package/dist/types/advanced/resourceAsync.d.ts.map +0 -1
- package/dist/types/advanced/stream.d.ts +0 -117
- package/dist/types/advanced/stream.d.ts.map +0 -1
- package/dist/types/advanced/streamAsync.d.ts +0 -97
- package/dist/types/advanced/streamAsync.d.ts.map +0 -1
- package/dist/types/basic/constant.d.ts +0 -60
- package/dist/types/basic/constant.d.ts.map +0 -1
- package/dist/types/basic/derivation.d.ts +0 -89
- package/dist/types/basic/derivation.d.ts.map +0 -1
- package/dist/types/basic/disposable.d.ts +0 -82
- package/dist/types/basic/disposable.d.ts.map +0 -1
- package/dist/types/basic/effect.d.ts +0 -67
- package/dist/types/basic/effect.d.ts.map +0 -1
- package/dist/types/basic/index.d.ts +0 -10
- package/dist/types/basic/index.d.ts.map +0 -1
- package/dist/types/basic/observable.d.ts +0 -83
- package/dist/types/basic/observable.d.ts.map +0 -1
- package/dist/types/basic/signal.d.ts +0 -69
- package/dist/types/basic/signal.d.ts.map +0 -1
- package/dist/types/basic/state.d.ts +0 -47
- package/dist/types/basic/state.d.ts.map +0 -1
- package/dist/types/basic/trackingContext.d.ts +0 -33
- package/dist/types/basic/trackingContext.d.ts.map +0 -1
- package/dist/types/creators.d.ts +0 -340
- package/dist/types/creators.d.ts.map +0 -1
- package/src/advanced/array.ts +0 -222
- package/src/advanced/index.ts +0 -12
- package/src/advanced/map.ts +0 -193
- package/src/basic/constant.ts +0 -97
- package/src/basic/derivation.ts +0 -147
- package/src/basic/disposable.ts +0 -86
- package/src/basic/effect.ts +0 -104
- package/src/basic/index.ts +0 -9
- package/src/basic/observable.ts +0 -109
- package/src/basic/signal.ts +0 -145
- package/src/basic/state.ts +0 -60
- package/src/basic/trackingContext.ts +0 -45
- package/src/creators.ts +0 -395
- package/test/array.test.ts +0 -600
- package/test/constant.test.ts +0 -44
- package/test/derivation.test.ts +0 -539
- package/test/effect.test.ts +0 -29
- package/test/map.test.ts +0 -240
- package/test/signal.test.ts +0 -72
- package/test/state.test.ts +0 -212
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { FlowReadonly, FlowReadonlyAsync } from '../flow';
|
|
2
|
+
import { FlowTracker } from '../flow/base/flowTracker';
|
|
3
|
+
import { SolidResource } from './primitives';
|
|
3
4
|
/**
|
|
4
5
|
* Utility type that excludes Promise types from T.
|
|
5
6
|
* Used to ensure type safety for synchronous derivations/resources.
|
|
@@ -8,57 +9,46 @@ import { SolidDerivation, SolidResource } from './primitives';
|
|
|
8
9
|
*/
|
|
9
10
|
export type NotPromise<T> = T extends Promise<unknown> ? never : T;
|
|
10
11
|
/**
|
|
11
|
-
* Converts a
|
|
12
|
+
* Converts a FlowNode, FlowNodeAsync, or getter function into a SolidResource.
|
|
12
13
|
*
|
|
13
|
-
* @param flow - The
|
|
14
|
-
* @returns A SolidResource
|
|
14
|
+
* @param flow - The FlowNode, FlowNodeAsync, or getter function to convert.
|
|
15
|
+
* @returns A SolidResource that wraps the value or computation.
|
|
15
16
|
*
|
|
16
|
-
* @
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
* Converts a FlowObservable of a non-Promise value into a SolidDerivation.
|
|
21
|
-
*
|
|
22
|
-
* @param flow - The FlowObservable to convert.
|
|
23
|
-
* @returns A SolidDerivation wrapping the observable.
|
|
24
|
-
*
|
|
25
|
-
* @public
|
|
26
|
-
*/
|
|
27
|
-
export declare function from<T>(flow: FlowObservable<NotPromise<T>>): SolidDerivation<NotPromise<T>>;
|
|
28
|
-
/**
|
|
29
|
-
* Converts a FlowObservable into a Solid derivation or resource, depending on whether the value is synchronous or asynchronous.
|
|
30
|
-
*
|
|
31
|
-
* @param flow - The FlowObservable to convert.
|
|
32
|
-
* @returns A SolidDerivation or SolidResource, depending on the input type.
|
|
17
|
+
* @remarks
|
|
18
|
+
* This function bridges PicoFlow's reactive system with SolidJS, allowing you to use
|
|
19
|
+
* PicoFlow nodes and computations within Solid components. All conversions return a
|
|
20
|
+
* `SolidResource`, which can handle both synchronous and asynchronous values seamlessly.
|
|
33
21
|
*
|
|
34
|
-
*
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
* Converts a getter function returning a non-Promise value into a SolidDerivation.
|
|
22
|
+
* The conversion works with:
|
|
23
|
+
* - **FlowNode**: Synchronous reactive nodes (e.g., from `state()` or `derivation()`)
|
|
24
|
+
* - **FlowNodeAsync**: Asynchronous reactive nodes (e.g., from `resourceAsync()`)
|
|
25
|
+
* - **Getter functions**: Computation functions that use a FlowTracker to access reactive values
|
|
39
26
|
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
27
|
+
* The created SolidResource automatically subscribes to the PicoFlow nodes and updates
|
|
28
|
+
* when their values change. The subscription is properly cleaned up when the Solid
|
|
29
|
+
* component unmounts.
|
|
42
30
|
*
|
|
43
|
-
* @
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
* Converts a getter function returning a Promise into a SolidResource.
|
|
31
|
+
* @example
|
|
32
|
+
* ```typescript
|
|
33
|
+
* import { from } from 'picoflow/solid';
|
|
34
|
+
* import { state } from 'picoflow';
|
|
48
35
|
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
36
|
+
* // Convert a PicoFlow state to a Solid resource
|
|
37
|
+
* const $count = state(0);
|
|
38
|
+
* const solidCount = from($count);
|
|
51
39
|
*
|
|
52
|
-
*
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
* Converts a getter function into a Solid derivation or resource, depending on whether the returned value is synchronous or asynchronous.
|
|
40
|
+
* // Use in a Solid component
|
|
41
|
+
* function Counter() {
|
|
42
|
+
* return <div>Count: {solidCount.get()}</div>;
|
|
43
|
+
* }
|
|
57
44
|
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
45
|
+
* // Or convert a computation function
|
|
46
|
+
* const solidDerived = from((t) => {
|
|
47
|
+
* return solidCount.get(t) * 2;
|
|
48
|
+
* });
|
|
49
|
+
* ```
|
|
60
50
|
*
|
|
61
51
|
* @public
|
|
62
52
|
*/
|
|
63
|
-
export declare function from<T>(flow: ((t:
|
|
53
|
+
export declare function from<T>(flow: FlowReadonlyAsync<T> | FlowReadonly<T> | ((t: FlowTracker) => T) | ((t: FlowTracker) => Promise<T>)): SolidResource<T>;
|
|
64
54
|
//# sourceMappingURL=converters.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"converters.d.ts","sourceRoot":"","sources":["../../../src/solid/converters.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"converters.d.ts","sourceRoot":"","sources":["../../../src/solid/converters.ts"],"names":[],"mappings":"AACA,OAAO,EAAY,KAAK,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAE9E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE5D,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAmE7C;;;;;GAKG;AACH,MAAM,MAAM,UAAU,CAAC,CAAC,IAAI,CAAC,SAAS,OAAO,CAAC,OAAO,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;AAEnE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,wBAAgB,IAAI,CAAC,CAAC,EACrB,IAAI,EACD,iBAAiB,CAAC,CAAC,CAAC,GACpB,YAAY,CAAC,CAAC,CAAC,GACf,CAAC,CAAC,CAAC,EAAE,WAAW,KAAK,CAAC,CAAC,GACvB,CAAC,CAAC,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,GACjC,aAAa,CAAC,CAAC,CAAC,CAUlB"}
|
|
@@ -171,6 +171,7 @@ export declare class SolidResource<T> implements SolidObservable<T | undefined>
|
|
|
171
171
|
* Triggers a refetch of the resource.
|
|
172
172
|
*/
|
|
173
173
|
readonly refetch: () => void;
|
|
174
|
+
readonly set: (param: SolidGetter<T>) => void;
|
|
174
175
|
/**
|
|
175
176
|
* Creates a new SolidResource from a fetcher function.
|
|
176
177
|
* @param fetcher - The async fetcher function.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"primitives.d.ts","sourceRoot":"","sources":["../../../src/solid/primitives.ts"],"names":[],"mappings":"AAAA,OAAO,EAIN,KAAK,eAAe,EACpB,MAAM,UAAU,CAAC;AAElB;;;;;GAKG;AACH,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC;AAEtD;;;;;GAKG;AACH,MAAM,WAAW,eAAe,CAAC,CAAC;IACjC;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC,CAAC;CACb;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,qBAAa,UAAU,CAAC,CAAC,CAAE,YAAW,eAAe,CAAC,CAAC,CAAC;IACvD;;OAEG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACtB;;OAEG;IACH,QAAQ,CAAC,GAAG,EAAE,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;IAE9C;;;OAGG;gBACS,YAAY,EAAE,CAAC;CAK3B;AAGD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,qBAAa,eAAe,CAAC,CAAC,CAAE,YAAW,eAAe,CAAC,CAAC,CAAC;IAC5D;;OAEG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAEtB;;;OAGG;gBACS,UAAU,EAAE,WAAW,CAAC,CAAC,CAAC;CAItC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,qBAAa,aAAa,CAAC,CAAC,CAAE,YAAW,eAAe,CAAC,CAAC,GAAG,SAAS,CAAC;IACtE;;OAEG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC;IAClC;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,MACb,YAAY,GACZ,SAAS,GACT,SAAS,GACT,OAAO,GACP,YAAY,CAAC;IAChB;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC;IACrC;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;IAE7B;;;OAGG;gBACS,OAAO,EAAE,eAAe,CAAC,IAAI,EAAE,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"primitives.d.ts","sourceRoot":"","sources":["../../../src/solid/primitives.ts"],"names":[],"mappings":"AAAA,OAAO,EAIN,KAAK,eAAe,EACpB,MAAM,UAAU,CAAC;AAElB;;;;;GAKG;AACH,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC;AAEtD;;;;;GAKG;AACH,MAAM,WAAW,eAAe,CAAC,CAAC;IACjC;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC,CAAC;CACb;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,qBAAa,UAAU,CAAC,CAAC,CAAE,YAAW,eAAe,CAAC,CAAC,CAAC;IACvD;;OAEG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACtB;;OAEG;IACH,QAAQ,CAAC,GAAG,EAAE,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;IAE9C;;;OAGG;gBACS,YAAY,EAAE,CAAC;CAK3B;AAGD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,qBAAa,eAAe,CAAC,CAAC,CAAE,YAAW,eAAe,CAAC,CAAC,CAAC;IAC5D;;OAEG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAEtB;;;OAGG;gBACS,UAAU,EAAE,WAAW,CAAC,CAAC,CAAC;CAItC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,qBAAa,aAAa,CAAC,CAAC,CAAE,YAAW,eAAe,CAAC,CAAC,GAAG,SAAS,CAAC;IACtE;;OAEG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC;IAClC;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,MACb,YAAY,GACZ,SAAS,GACT,SAAS,GACT,OAAO,GACP,YAAY,CAAC;IAChB;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC;IACrC;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;IAE7B,QAAQ,CAAC,GAAG,EAAE,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;IAE9C;;;OAGG;gBACS,OAAO,EAAE,eAAe,CAAC,IAAI,EAAE,CAAC,EAAE,OAAO,CAAC;CAStD"}
|
|
@@ -1 +1,81 @@
|
|
|
1
|
-
[
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"text": "Classes",
|
|
4
|
+
"collapsed": true,
|
|
5
|
+
"items": [
|
|
6
|
+
{ "text": "FlowArray", "link": "/api/classes/FlowArray.md" },
|
|
7
|
+
{ "text": "FlowConstant", "link": "/api/classes/FlowConstant.md" },
|
|
8
|
+
{ "text": "FlowDerivation", "link": "/api/classes/FlowDerivation.md" },
|
|
9
|
+
{ "text": "FlowEffect", "link": "/api/classes/FlowEffect.md" },
|
|
10
|
+
{ "text": "FlowMap", "link": "/api/classes/FlowMap.md" },
|
|
11
|
+
{ "text": "FlowObservable", "link": "/api/classes/FlowObservable.md" },
|
|
12
|
+
{ "text": "FlowResource", "link": "/api/classes/FlowResource.md" },
|
|
13
|
+
{
|
|
14
|
+
"text": "FlowResourceAsync",
|
|
15
|
+
"link": "/api/classes/FlowResourceAsync.md"
|
|
16
|
+
},
|
|
17
|
+
{ "text": "FlowSignal", "link": "/api/classes/FlowSignal.md" },
|
|
18
|
+
{ "text": "FlowState", "link": "/api/classes/FlowState.md" },
|
|
19
|
+
{ "text": "FlowStream", "link": "/api/classes/FlowStream.md" },
|
|
20
|
+
{ "text": "FlowStreamAsync", "link": "/api/classes/FlowStreamAsync.md" },
|
|
21
|
+
{ "text": "SolidDerivation", "link": "/api/classes/SolidDerivation.md" },
|
|
22
|
+
{ "text": "SolidResource", "link": "/api/classes/SolidResource.md" },
|
|
23
|
+
{ "text": "SolidState", "link": "/api/classes/SolidState.md" },
|
|
24
|
+
{ "text": "TrackingContext", "link": "/api/classes/TrackingContext.md" }
|
|
25
|
+
]
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"text": "Interfaces",
|
|
29
|
+
"collapsed": true,
|
|
30
|
+
"items": [
|
|
31
|
+
{ "text": "FlowDisposable", "link": "/api/interfaces/FlowDisposable.md" },
|
|
32
|
+
{
|
|
33
|
+
"text": "SolidObservable",
|
|
34
|
+
"link": "/api/interfaces/SolidObservable.md"
|
|
35
|
+
}
|
|
36
|
+
]
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"text": "Type Aliases",
|
|
40
|
+
"collapsed": true,
|
|
41
|
+
"items": [
|
|
42
|
+
{
|
|
43
|
+
"text": "FlowArrayAction",
|
|
44
|
+
"link": "/api/type-aliases/FlowArrayAction.md"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"text": "FlowStreamDisposer",
|
|
48
|
+
"link": "/api/type-aliases/FlowStreamDisposer.md"
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"text": "FlowStreamSetter",
|
|
52
|
+
"link": "/api/type-aliases/FlowStreamSetter.md"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"text": "FlowStreamUpdater",
|
|
56
|
+
"link": "/api/type-aliases/FlowStreamUpdater.md"
|
|
57
|
+
},
|
|
58
|
+
{ "text": "NotPromise", "link": "/api/type-aliases/NotPromise.md" },
|
|
59
|
+
{ "text": "SolidGetter", "link": "/api/type-aliases/SolidGetter.md" }
|
|
60
|
+
]
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"text": "Functions",
|
|
64
|
+
"collapsed": true,
|
|
65
|
+
"items": [
|
|
66
|
+
{ "text": "array", "link": "/api/functions/array.md" },
|
|
67
|
+
{ "text": "constant", "link": "/api/functions/constant.md" },
|
|
68
|
+
{ "text": "derivation", "link": "/api/functions/derivation.md" },
|
|
69
|
+
{ "text": "effect", "link": "/api/functions/effect.md" },
|
|
70
|
+
{ "text": "from", "link": "/api/functions/from.md" },
|
|
71
|
+
{ "text": "isDisposable", "link": "/api/functions/isDisposable.md" },
|
|
72
|
+
{ "text": "map", "link": "/api/functions/map.md" },
|
|
73
|
+
{ "text": "resource", "link": "/api/functions/resource.md" },
|
|
74
|
+
{ "text": "resourceAsync", "link": "/api/functions/resourceAsync.md" },
|
|
75
|
+
{ "text": "signal", "link": "/api/functions/signal.md" },
|
|
76
|
+
{ "text": "state", "link": "/api/functions/state.md" },
|
|
77
|
+
{ "text": "stream", "link": "/api/functions/stream.md" },
|
|
78
|
+
{ "text": "streamAsync", "link": "/api/functions/streamAsync.md" }
|
|
79
|
+
]
|
|
80
|
+
}
|
|
81
|
+
]
|
package/package.json
CHANGED
|
@@ -1,59 +1,61 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
2
|
+
"name": "@ersbeth/picoflow",
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "Minimal Dataflow librairy for TypeScript",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": {
|
|
7
|
+
"types": "./dist/types/index.d.ts",
|
|
8
|
+
"default": "./dist/picoflow.js"
|
|
9
|
+
},
|
|
10
|
+
"imports": {
|
|
11
|
+
"#package": "./src/index.ts"
|
|
12
|
+
},
|
|
13
|
+
"peerDependencies": {
|
|
14
|
+
"solid-js": "^1.9.7"
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@biomejs/biome": "2.3.8",
|
|
18
|
+
"@braintree/sanitize-url": "^7.1.1",
|
|
19
|
+
"@vitest/coverage-v8": "^3.0.9",
|
|
20
|
+
"cytoscape": "^3.33.1",
|
|
21
|
+
"cytoscape-cose-bilkent": "^4.1.0",
|
|
22
|
+
"dayjs": "^1.11.19",
|
|
23
|
+
"dompurify": "^3.3.0",
|
|
24
|
+
"jsdom": "^27.3.0",
|
|
25
|
+
"mermaid": "^11.12.1",
|
|
26
|
+
"typedoc": "^0.28.15",
|
|
27
|
+
"typedoc-plugin-markdown": "^4.9.0",
|
|
28
|
+
"typedoc-vitepress-theme": "^1.1.2",
|
|
29
|
+
"typescript": "^5.9.3",
|
|
30
|
+
"vite": "^6.2.3",
|
|
31
|
+
"vite-plugin-dts": "^4.5.3",
|
|
32
|
+
"vite-plugin-solid": "^2.11.10",
|
|
33
|
+
"vitepress": "^1.6.4",
|
|
34
|
+
"vitepress-plugin-mermaid": "^2.0.17",
|
|
35
|
+
"vitest": "^3.0.9"
|
|
36
|
+
},
|
|
37
|
+
"repository": {
|
|
38
|
+
"type": "git",
|
|
39
|
+
"url": "git+ssh://git@gitlab.com/ersbeth-web/picoflow.git"
|
|
40
|
+
},
|
|
41
|
+
"author": "Elisabeth Rousset",
|
|
42
|
+
"license": "MIT",
|
|
43
|
+
"bugs": {
|
|
44
|
+
"url": "https://gitlab.com/ersbeth-web/picoflow/issues"
|
|
45
|
+
},
|
|
46
|
+
"homepage": "https://gitlab.com/ersbeth-web/picoflow#readme",
|
|
47
|
+
"scripts": {
|
|
48
|
+
"check": "pnpm exec tsc --noEmit",
|
|
49
|
+
"lint": "pnpm exec biome check --fix",
|
|
50
|
+
"build": "pnpm exec vite build --config vite.config.ts",
|
|
51
|
+
"test": "pnpm exec vitest",
|
|
52
|
+
"docs:dev": "vitepress dev docs",
|
|
53
|
+
"docs:build": "pnpm docs:generate && vitepress build docs",
|
|
54
|
+
"docs:preview": "vitepress preview docs",
|
|
55
|
+
"docs:generate": "typedoc",
|
|
56
|
+
"api:extract": "pnpm exec api-extractor run --local",
|
|
57
|
+
"api:generate": "pnpm exec api-documenter markdown -i ./api/temp -o ./api/doc",
|
|
58
|
+
"api:clean": "rm ./api/temp/*",
|
|
59
|
+
"api": "pnpm api:extract && pnpm api:generate && pnpm api:clean"
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Contract for objects that own resources and must be cleaned up explicitly.
|
|
3
|
+
*
|
|
4
|
+
* @remarks
|
|
5
|
+
* Many PicoFlow primitives expose `dispose()` so you can tear down subscriptions,
|
|
6
|
+
* listeners, or reactive links when they are no longer needed (e.g., component
|
|
7
|
+
* unmount, feature teardown, test cleanup).
|
|
8
|
+
*
|
|
9
|
+
* Typical options:
|
|
10
|
+
* - `{ self: true }` — dispose only this instance (dependents decide their own lifecycle).
|
|
11
|
+
* - `{ self: false }` or omitted — also dispose dependents, if the implementation supports it.
|
|
12
|
+
*
|
|
13
|
+
* The exact cascade behavior depends on the concrete primitive; consult its docs.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* const $state = state(0);
|
|
18
|
+
* const fx = effect((t) => console.log($state.get(t)));
|
|
19
|
+
*
|
|
20
|
+
* $state.dispose(); // Common teardown path
|
|
21
|
+
* $state.dispose({ self: true }); // Dispose only this instance if you want dependents to persist
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* @public
|
|
25
|
+
*/
|
|
26
|
+
export interface FlowDisposable {
|
|
27
|
+
/**
|
|
28
|
+
* Disposes resources held by this object.
|
|
29
|
+
*
|
|
30
|
+
* @param options - Optional disposal behavior.
|
|
31
|
+
* @param options.self - When true, dispose only this object. When false or
|
|
32
|
+
* omitted, the implementation may also dispose dependents.
|
|
33
|
+
*
|
|
34
|
+
* @remarks
|
|
35
|
+
* Use `dispose()` during teardown (unmount, test cleanup, feature shutdown).
|
|
36
|
+
* Calling `dispose()` more than once may throw; behavior is defined by the
|
|
37
|
+
* concrete implementation.
|
|
38
|
+
*
|
|
39
|
+
* @throws Error if the object has already been disposed (implementation-specific).
|
|
40
|
+
*/
|
|
41
|
+
dispose(options?: { self: boolean }): void;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Runtime type guard that checks whether an object is disposable.
|
|
46
|
+
*
|
|
47
|
+
* @param obj - Value to test.
|
|
48
|
+
* @returns `true` if `obj` exposes a callable `dispose`; otherwise `false`.
|
|
49
|
+
*
|
|
50
|
+
* @remarks
|
|
51
|
+
* Use this for defensive cleanup in mixed collections or optional resources.
|
|
52
|
+
* It performs a runtime shape check; no assumptions about specific types are made.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```typescript
|
|
56
|
+
* function cleanup(items: unknown[]) {
|
|
57
|
+
* for (const item of items) {
|
|
58
|
+
* if (isDisposable(item)) item.dispose();
|
|
59
|
+
* }
|
|
60
|
+
* }
|
|
61
|
+
* ```
|
|
62
|
+
*
|
|
63
|
+
* @public
|
|
64
|
+
*/
|
|
65
|
+
export function isDisposable(obj: unknown): obj is FlowDisposable {
|
|
66
|
+
return (
|
|
67
|
+
obj !== null &&
|
|
68
|
+
obj !== undefined &&
|
|
69
|
+
typeof (obj as FlowDisposable).dispose === "function"
|
|
70
|
+
);
|
|
71
|
+
}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { FlowGraph } from "./flowGraph";
|
|
2
|
+
import type { FlowSignal } from "./flowSignal";
|
|
3
|
+
import type { FlowTracker } from "./flowTracker";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Runs side-effect code in response to reactive state changes.
|
|
7
|
+
*
|
|
8
|
+
* @remarks
|
|
9
|
+
* A `FlowEffect` is the bridge between reactive data and the outside world
|
|
10
|
+
* (UI updates, logging, network calls, timers, etc.). It executes a callback
|
|
11
|
+
* with a tracking context so you can choose which observables/signals should
|
|
12
|
+
* re-trigger the effect:
|
|
13
|
+
*
|
|
14
|
+
* - Use `observable.get(t)` or `signal.watch(t)` to create dependencies.
|
|
15
|
+
* - Use `observable.pick()` for untracked reads that should not re-run the effect.
|
|
16
|
+
*
|
|
17
|
+
* The callback runs immediately when the effect is created and re-runs whenever
|
|
18
|
+
* any tracked dependency changes. The effect itself is the tracking context
|
|
19
|
+
* (it implements `FlowTracker`), so `t` in your callback is the effect instance.
|
|
20
|
+
*
|
|
21
|
+
* Async callbacks are supported: if the callback returns a promise, the effect
|
|
22
|
+
* awaits it before finishing the current run. A later change can re-run the
|
|
23
|
+
* effect even if a previous async run is still pending, so write idempotent
|
|
24
|
+
* side effects when working with async flows.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* // Mixed tracked/untracked reads
|
|
29
|
+
* const fx = effect((t) => {
|
|
30
|
+
* const tracked = $stateA.get(t); // tracked -> re-runs when $stateA changes
|
|
31
|
+
* const snapshot = $config.pick(); // untracked -> does not re-run on changes
|
|
32
|
+
* console.log(tracked, snapshot);
|
|
33
|
+
* });
|
|
34
|
+
*
|
|
35
|
+
* // Async work
|
|
36
|
+
* const fxAsync = effect(async (t) => {
|
|
37
|
+
* const userId = $userId.get(t);
|
|
38
|
+
* const profile = await fetchProfile(userId);
|
|
39
|
+
* renderProfile(profile);
|
|
40
|
+
* });
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* @public
|
|
44
|
+
*/
|
|
45
|
+
export class FlowEffect {
|
|
46
|
+
private _disposed = false;
|
|
47
|
+
private _dependencies = new Set<FlowSignal>();
|
|
48
|
+
private _apply: (t: FlowTracker) => void | Promise<void>;
|
|
49
|
+
settled: Promise<void>;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Creates a new effect and runs it once immediately.
|
|
53
|
+
*
|
|
54
|
+
* @param apply - Side-effect function receiving the tracking context (`t`).
|
|
55
|
+
* It can be sync or async (returning `Promise<void>`).
|
|
56
|
+
*
|
|
57
|
+
* @remarks
|
|
58
|
+
* Use `t` to opt-in to reactive tracking:
|
|
59
|
+
* - `observable.get(t)` / `signal.watch(t)` to re-run when they change
|
|
60
|
+
* - `observable.pick()` for reads that should not re-run the effect
|
|
61
|
+
*
|
|
62
|
+
* The effect schedules its first run during construction. Each subsequent
|
|
63
|
+
* change to a tracked dependency queues another run.
|
|
64
|
+
*
|
|
65
|
+
* @public
|
|
66
|
+
*/
|
|
67
|
+
constructor(apply: (t: FlowTracker) => void | Promise<void>) {
|
|
68
|
+
this._apply = apply;
|
|
69
|
+
this.settled = FlowGraph.requestRead(() => this._exec());
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Stops the effect and detaches it from all tracked dependencies.
|
|
74
|
+
*
|
|
75
|
+
* @remarks
|
|
76
|
+
* Call this when the effect's work is no longer needed (e.g., component
|
|
77
|
+
* unmount, teardown of a feature). After disposal:
|
|
78
|
+
* - The effect will not re-run.
|
|
79
|
+
* - All dependency links are removed.
|
|
80
|
+
* - Calling `dispose()` again throws an error.
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```typescript
|
|
84
|
+
* const fx = effect((t) => $signal.watch(t));
|
|
85
|
+
* // ... later
|
|
86
|
+
* fx.dispose();
|
|
87
|
+
* ```
|
|
88
|
+
*
|
|
89
|
+
* @public
|
|
90
|
+
*/
|
|
91
|
+
public dispose(): void {
|
|
92
|
+
if (this._disposed) throw new Error("[PicoFlow] Effect is disposed");
|
|
93
|
+
Array.from(this._dependencies).forEach((dependency) => {
|
|
94
|
+
this._unregisterDependency(dependency);
|
|
95
|
+
});
|
|
96
|
+
this._disposed = true;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Whether the effect has been disposed.
|
|
101
|
+
*
|
|
102
|
+
* @returns `true` once disposal has run; `false` while the effect is active.
|
|
103
|
+
*
|
|
104
|
+
* @public
|
|
105
|
+
*/
|
|
106
|
+
public get disposed(): boolean {
|
|
107
|
+
return this._disposed;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** @internal */ async _requestExec(): Promise<void> {
|
|
111
|
+
this.settled = this._exec();
|
|
112
|
+
return this.settled;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** @internal */ _registerDependency(dependency: FlowSignal): void {
|
|
116
|
+
this._dependencies.add(dependency);
|
|
117
|
+
dependency._registerEffect(this);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** @internal */ _unregisterDependency(dependency: FlowSignal): void {
|
|
121
|
+
this._dependencies.delete(dependency);
|
|
122
|
+
dependency._unregisterEffect(this);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
private async _exec(): Promise<void> {
|
|
126
|
+
if (this._disposed)
|
|
127
|
+
/* v8 ignore next 1 */
|
|
128
|
+
throw new Error("[PicoFlow] Effect is disposed");
|
|
129
|
+
|
|
130
|
+
const result = this._apply(this);
|
|
131
|
+
if (result instanceof Promise) {
|
|
132
|
+
await result;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Creates a reactive effect that runs now and re-runs when its tracked
|
|
139
|
+
* dependencies change.
|
|
140
|
+
*
|
|
141
|
+
* @param fn - Side-effect function that receives the tracking context (`t`).
|
|
142
|
+
* @returns A new {@link FlowEffect}.
|
|
143
|
+
*
|
|
144
|
+
* @remarks
|
|
145
|
+
* Use an effect when you need to react to state changes with side effects
|
|
146
|
+
* (UI updates, logging, network calls, timers). For computing derived values,
|
|
147
|
+
* prefer derivations; for one-off work, use a normal function.
|
|
148
|
+
*
|
|
149
|
+
* - Track dependencies with `observable.get(t)` or `signal.watch(t)`.
|
|
150
|
+
* - Read without tracking using `observable.pick()`.
|
|
151
|
+
* - Async callbacks are supported; return a promise if you `await` inside.
|
|
152
|
+
*
|
|
153
|
+
* @example
|
|
154
|
+
* ```typescript
|
|
155
|
+
* const $count = state(0);
|
|
156
|
+
*
|
|
157
|
+
* const fx = effect((t) => {
|
|
158
|
+
* console.log("Count is:", $count.get(t));
|
|
159
|
+
* });
|
|
160
|
+
*
|
|
161
|
+
* $count.set(1); // Logs "Count is: 1"
|
|
162
|
+
* $count.set(2); // Logs "Count is: 2"
|
|
163
|
+
*
|
|
164
|
+
* fx.dispose(); // Stop reacting
|
|
165
|
+
* ```
|
|
166
|
+
*
|
|
167
|
+
* @public
|
|
168
|
+
*/
|
|
169
|
+
export function effect(fn: (t: FlowTracker) => void): FlowEffect {
|
|
170
|
+
return new FlowEffect(fn);
|
|
171
|
+
}
|