@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.
Files changed (180) hide show
  1. package/.cursor/plans/unifier-flowresource-avec-flowderivation-c9506e24.plan.md +372 -0
  2. package/README.md +25 -171
  3. package/biome.json +4 -1
  4. package/dist/picoflow.js +1129 -661
  5. package/dist/types/flow/base/flowDisposable.d.ts +67 -0
  6. package/dist/types/flow/base/flowDisposable.d.ts.map +1 -0
  7. package/dist/types/flow/base/flowEffect.d.ts +127 -0
  8. package/dist/types/flow/base/flowEffect.d.ts.map +1 -0
  9. package/dist/types/flow/base/flowGraph.d.ts +97 -0
  10. package/dist/types/flow/base/flowGraph.d.ts.map +1 -0
  11. package/dist/types/flow/base/flowSignal.d.ts +134 -0
  12. package/dist/types/flow/base/flowSignal.d.ts.map +1 -0
  13. package/dist/types/flow/base/flowTracker.d.ts +15 -0
  14. package/dist/types/flow/base/flowTracker.d.ts.map +1 -0
  15. package/dist/types/flow/base/index.d.ts +7 -0
  16. package/dist/types/flow/base/index.d.ts.map +1 -0
  17. package/dist/types/flow/base/utils.d.ts +20 -0
  18. package/dist/types/flow/base/utils.d.ts.map +1 -0
  19. package/dist/types/{advanced/array.d.ts → flow/collections/flowArray.d.ts} +50 -12
  20. package/dist/types/flow/collections/flowArray.d.ts.map +1 -0
  21. package/dist/types/flow/collections/flowMap.d.ts +224 -0
  22. package/dist/types/flow/collections/flowMap.d.ts.map +1 -0
  23. package/dist/types/flow/collections/index.d.ts +3 -0
  24. package/dist/types/flow/collections/index.d.ts.map +1 -0
  25. package/dist/types/flow/index.d.ts +4 -0
  26. package/dist/types/flow/index.d.ts.map +1 -0
  27. package/dist/types/flow/nodes/async/flowConstantAsync.d.ts +137 -0
  28. package/dist/types/flow/nodes/async/flowConstantAsync.d.ts.map +1 -0
  29. package/dist/types/flow/nodes/async/flowDerivationAsync.d.ts +137 -0
  30. package/dist/types/flow/nodes/async/flowDerivationAsync.d.ts.map +1 -0
  31. package/dist/types/flow/nodes/async/flowNodeAsync.d.ts +343 -0
  32. package/dist/types/flow/nodes/async/flowNodeAsync.d.ts.map +1 -0
  33. package/dist/types/flow/nodes/async/flowReadonlyAsync.d.ts +81 -0
  34. package/dist/types/flow/nodes/async/flowReadonlyAsync.d.ts.map +1 -0
  35. package/dist/types/flow/nodes/async/flowStateAsync.d.ts +111 -0
  36. package/dist/types/flow/nodes/async/flowStateAsync.d.ts.map +1 -0
  37. package/dist/types/flow/nodes/async/index.d.ts +6 -0
  38. package/dist/types/flow/nodes/async/index.d.ts.map +1 -0
  39. package/dist/types/flow/nodes/index.d.ts +3 -0
  40. package/dist/types/flow/nodes/index.d.ts.map +1 -0
  41. package/dist/types/flow/nodes/sync/flowConstant.d.ts +108 -0
  42. package/dist/types/flow/nodes/sync/flowConstant.d.ts.map +1 -0
  43. package/dist/types/flow/nodes/sync/flowDerivation.d.ts +100 -0
  44. package/dist/types/flow/nodes/sync/flowDerivation.d.ts.map +1 -0
  45. package/dist/types/flow/nodes/sync/flowNode.d.ts +314 -0
  46. package/dist/types/flow/nodes/sync/flowNode.d.ts.map +1 -0
  47. package/dist/types/flow/nodes/sync/flowReadonly.d.ts +57 -0
  48. package/dist/types/flow/nodes/sync/flowReadonly.d.ts.map +1 -0
  49. package/dist/types/flow/nodes/sync/flowState.d.ts +96 -0
  50. package/dist/types/flow/nodes/sync/flowState.d.ts.map +1 -0
  51. package/dist/types/flow/nodes/sync/index.d.ts +6 -0
  52. package/dist/types/flow/nodes/sync/index.d.ts.map +1 -0
  53. package/dist/types/index.d.ts +1 -4
  54. package/dist/types/index.d.ts.map +1 -1
  55. package/dist/types/solid/converters.d.ts +34 -44
  56. package/dist/types/solid/converters.d.ts.map +1 -1
  57. package/dist/types/solid/primitives.d.ts +1 -0
  58. package/dist/types/solid/primitives.d.ts.map +1 -1
  59. package/docs/.vitepress/config.mts +1 -1
  60. package/docs/api/typedoc-sidebar.json +81 -1
  61. package/package.json +60 -58
  62. package/src/flow/base/flowDisposable.ts +71 -0
  63. package/src/flow/base/flowEffect.ts +171 -0
  64. package/src/flow/base/flowGraph.ts +288 -0
  65. package/src/flow/base/flowSignal.ts +207 -0
  66. package/src/flow/base/flowTracker.ts +17 -0
  67. package/src/flow/base/index.ts +6 -0
  68. package/src/flow/base/utils.ts +19 -0
  69. package/src/flow/collections/flowArray.ts +409 -0
  70. package/src/flow/collections/flowMap.ts +398 -0
  71. package/src/flow/collections/index.ts +2 -0
  72. package/src/flow/index.ts +3 -0
  73. package/src/flow/nodes/async/flowConstantAsync.ts +142 -0
  74. package/src/flow/nodes/async/flowDerivationAsync.ts +143 -0
  75. package/src/flow/nodes/async/flowNodeAsync.ts +474 -0
  76. package/src/flow/nodes/async/flowReadonlyAsync.ts +81 -0
  77. package/src/flow/nodes/async/flowStateAsync.ts +116 -0
  78. package/src/flow/nodes/async/index.ts +5 -0
  79. package/src/flow/nodes/await/advanced/index.ts +5 -0
  80. package/src/{advanced → flow/nodes/await/advanced}/resource.ts +37 -3
  81. package/src/{advanced → flow/nodes/await/advanced}/resourceAsync.ts +35 -3
  82. package/src/{advanced → flow/nodes/await/advanced}/stream.ts +40 -2
  83. package/src/{advanced → flow/nodes/await/advanced}/streamAsync.ts +38 -3
  84. package/src/flow/nodes/await/flowConstantAwait.ts +154 -0
  85. package/src/flow/nodes/await/flowDerivationAwait.ts +154 -0
  86. package/src/flow/nodes/await/flowNodeAwait.ts +508 -0
  87. package/src/flow/nodes/await/flowReadonlyAwait.ts +89 -0
  88. package/src/flow/nodes/await/flowStateAwait.ts +130 -0
  89. package/src/flow/nodes/await/index.ts +5 -0
  90. package/src/flow/nodes/index.ts +3 -0
  91. package/src/flow/nodes/sync/flowConstant.ts +111 -0
  92. package/src/flow/nodes/sync/flowDerivation.ts +105 -0
  93. package/src/flow/nodes/sync/flowNode.ts +439 -0
  94. package/src/flow/nodes/sync/flowReadonly.ts +57 -0
  95. package/src/flow/nodes/sync/flowState.ts +101 -0
  96. package/src/flow/nodes/sync/index.ts +5 -0
  97. package/src/index.ts +1 -47
  98. package/src/solid/converters.ts +59 -198
  99. package/src/solid/primitives.ts +4 -0
  100. package/test/base/flowEffect.test.ts +108 -0
  101. package/test/base/flowGraph.test.ts +485 -0
  102. package/test/base/flowSignal.test.ts +372 -0
  103. package/test/collections/flowArray.asyncStates.test.ts +1553 -0
  104. package/test/collections/flowArray.scalars.test.ts +1129 -0
  105. package/test/collections/flowArray.states.test.ts +1365 -0
  106. package/test/collections/flowMap.asyncStates.test.ts +1105 -0
  107. package/test/collections/flowMap.scalars.test.ts +877 -0
  108. package/test/collections/flowMap.states.test.ts +1097 -0
  109. package/test/nodes/async/flowConstantAsync.test.ts +860 -0
  110. package/test/nodes/async/flowDerivationAsync.test.ts +1517 -0
  111. package/test/nodes/async/flowStateAsync.test.ts +1387 -0
  112. package/test/{resource.test.ts → nodes/await/advanced/resource.test.ts} +21 -19
  113. package/test/{resourceAsync.test.ts → nodes/await/advanced/resourceAsync.test.ts} +3 -1
  114. package/test/{stream.test.ts → nodes/await/advanced/stream.test.ts} +30 -28
  115. package/test/{streamAsync.test.ts → nodes/await/advanced/streamAsync.test.ts} +16 -14
  116. package/test/nodes/await/flowConstantAwait.test.ts +643 -0
  117. package/test/nodes/await/flowDerivationAwait.test.ts +1583 -0
  118. package/test/nodes/await/flowStateAwait.test.ts +999 -0
  119. package/test/nodes/mixed/derivation.test.ts +1527 -0
  120. package/test/nodes/sync/flowConstant.test.ts +620 -0
  121. package/test/nodes/sync/flowDerivation.test.ts +1373 -0
  122. package/test/nodes/sync/flowState.test.ts +945 -0
  123. package/test/solid/converters.test.ts +721 -0
  124. package/test/solid/primitives.test.ts +1031 -0
  125. package/tsconfig.json +2 -1
  126. package/vitest.config.ts +7 -1
  127. package/IMPLEMENTATION_GUIDE.md +0 -1578
  128. package/dist/types/advanced/array.d.ts.map +0 -1
  129. package/dist/types/advanced/index.d.ts +0 -9
  130. package/dist/types/advanced/index.d.ts.map +0 -1
  131. package/dist/types/advanced/map.d.ts +0 -166
  132. package/dist/types/advanced/map.d.ts.map +0 -1
  133. package/dist/types/advanced/resource.d.ts +0 -78
  134. package/dist/types/advanced/resource.d.ts.map +0 -1
  135. package/dist/types/advanced/resourceAsync.d.ts +0 -56
  136. package/dist/types/advanced/resourceAsync.d.ts.map +0 -1
  137. package/dist/types/advanced/stream.d.ts +0 -117
  138. package/dist/types/advanced/stream.d.ts.map +0 -1
  139. package/dist/types/advanced/streamAsync.d.ts +0 -97
  140. package/dist/types/advanced/streamAsync.d.ts.map +0 -1
  141. package/dist/types/basic/constant.d.ts +0 -60
  142. package/dist/types/basic/constant.d.ts.map +0 -1
  143. package/dist/types/basic/derivation.d.ts +0 -89
  144. package/dist/types/basic/derivation.d.ts.map +0 -1
  145. package/dist/types/basic/disposable.d.ts +0 -82
  146. package/dist/types/basic/disposable.d.ts.map +0 -1
  147. package/dist/types/basic/effect.d.ts +0 -67
  148. package/dist/types/basic/effect.d.ts.map +0 -1
  149. package/dist/types/basic/index.d.ts +0 -10
  150. package/dist/types/basic/index.d.ts.map +0 -1
  151. package/dist/types/basic/observable.d.ts +0 -83
  152. package/dist/types/basic/observable.d.ts.map +0 -1
  153. package/dist/types/basic/signal.d.ts +0 -69
  154. package/dist/types/basic/signal.d.ts.map +0 -1
  155. package/dist/types/basic/state.d.ts +0 -47
  156. package/dist/types/basic/state.d.ts.map +0 -1
  157. package/dist/types/basic/trackingContext.d.ts +0 -33
  158. package/dist/types/basic/trackingContext.d.ts.map +0 -1
  159. package/dist/types/creators.d.ts +0 -340
  160. package/dist/types/creators.d.ts.map +0 -1
  161. package/src/advanced/array.ts +0 -222
  162. package/src/advanced/index.ts +0 -12
  163. package/src/advanced/map.ts +0 -193
  164. package/src/basic/constant.ts +0 -97
  165. package/src/basic/derivation.ts +0 -147
  166. package/src/basic/disposable.ts +0 -86
  167. package/src/basic/effect.ts +0 -104
  168. package/src/basic/index.ts +0 -9
  169. package/src/basic/observable.ts +0 -109
  170. package/src/basic/signal.ts +0 -145
  171. package/src/basic/state.ts +0 -60
  172. package/src/basic/trackingContext.ts +0 -45
  173. package/src/creators.ts +0 -395
  174. package/test/array.test.ts +0 -600
  175. package/test/constant.test.ts +0 -44
  176. package/test/derivation.test.ts +0 -539
  177. package/test/effect.test.ts +0 -29
  178. package/test/map.test.ts +0 -240
  179. package/test/signal.test.ts +0 -72
  180. package/test/state.test.ts +0 -212
@@ -0,0 +1,67 @@
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?: {
42
+ self: boolean;
43
+ }): void;
44
+ }
45
+ /**
46
+ * Runtime type guard that checks whether an object is disposable.
47
+ *
48
+ * @param obj - Value to test.
49
+ * @returns `true` if `obj` exposes a callable `dispose`; otherwise `false`.
50
+ *
51
+ * @remarks
52
+ * Use this for defensive cleanup in mixed collections or optional resources.
53
+ * It performs a runtime shape check; no assumptions about specific types are made.
54
+ *
55
+ * @example
56
+ * ```typescript
57
+ * function cleanup(items: unknown[]) {
58
+ * for (const item of items) {
59
+ * if (isDisposable(item)) item.dispose();
60
+ * }
61
+ * }
62
+ * ```
63
+ *
64
+ * @public
65
+ */
66
+ export declare function isDisposable(obj: unknown): obj is FlowDisposable;
67
+ //# sourceMappingURL=flowDisposable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flowDisposable.d.ts","sourceRoot":"","sources":["../../../../src/flow/base/flowDisposable.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,WAAW,cAAc;IAC9B;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,OAAO,CAAC,EAAE;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;CAC3C;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,cAAc,CAMhE"}
@@ -0,0 +1,127 @@
1
+ import { FlowTracker } from './flowTracker';
2
+ /**
3
+ * Runs side-effect code in response to reactive state changes.
4
+ *
5
+ * @remarks
6
+ * A `FlowEffect` is the bridge between reactive data and the outside world
7
+ * (UI updates, logging, network calls, timers, etc.). It executes a callback
8
+ * with a tracking context so you can choose which observables/signals should
9
+ * re-trigger the effect:
10
+ *
11
+ * - Use `observable.get(t)` or `signal.watch(t)` to create dependencies.
12
+ * - Use `observable.pick()` for untracked reads that should not re-run the effect.
13
+ *
14
+ * The callback runs immediately when the effect is created and re-runs whenever
15
+ * any tracked dependency changes. The effect itself is the tracking context
16
+ * (it implements `FlowTracker`), so `t` in your callback is the effect instance.
17
+ *
18
+ * Async callbacks are supported: if the callback returns a promise, the effect
19
+ * awaits it before finishing the current run. A later change can re-run the
20
+ * effect even if a previous async run is still pending, so write idempotent
21
+ * side effects when working with async flows.
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * // Mixed tracked/untracked reads
26
+ * const fx = effect((t) => {
27
+ * const tracked = $stateA.get(t); // tracked -> re-runs when $stateA changes
28
+ * const snapshot = $config.pick(); // untracked -> does not re-run on changes
29
+ * console.log(tracked, snapshot);
30
+ * });
31
+ *
32
+ * // Async work
33
+ * const fxAsync = effect(async (t) => {
34
+ * const userId = $userId.get(t);
35
+ * const profile = await fetchProfile(userId);
36
+ * renderProfile(profile);
37
+ * });
38
+ * ```
39
+ *
40
+ * @public
41
+ */
42
+ export declare class FlowEffect {
43
+ private _disposed;
44
+ private _dependencies;
45
+ private _apply;
46
+ settled: Promise<void>;
47
+ /**
48
+ * Creates a new effect and runs it once immediately.
49
+ *
50
+ * @param apply - Side-effect function receiving the tracking context (`t`).
51
+ * It can be sync or async (returning `Promise<void>`).
52
+ *
53
+ * @remarks
54
+ * Use `t` to opt-in to reactive tracking:
55
+ * - `observable.get(t)` / `signal.watch(t)` to re-run when they change
56
+ * - `observable.pick()` for reads that should not re-run the effect
57
+ *
58
+ * The effect schedules its first run during construction. Each subsequent
59
+ * change to a tracked dependency queues another run.
60
+ *
61
+ * @public
62
+ */
63
+ constructor(apply: (t: FlowTracker) => void | Promise<void>);
64
+ /**
65
+ * Stops the effect and detaches it from all tracked dependencies.
66
+ *
67
+ * @remarks
68
+ * Call this when the effect's work is no longer needed (e.g., component
69
+ * unmount, teardown of a feature). After disposal:
70
+ * - The effect will not re-run.
71
+ * - All dependency links are removed.
72
+ * - Calling `dispose()` again throws an error.
73
+ *
74
+ * @example
75
+ * ```typescript
76
+ * const fx = effect((t) => $signal.watch(t));
77
+ * // ... later
78
+ * fx.dispose();
79
+ * ```
80
+ *
81
+ * @public
82
+ */
83
+ dispose(): void;
84
+ /**
85
+ * Whether the effect has been disposed.
86
+ *
87
+ * @returns `true` once disposal has run; `false` while the effect is active.
88
+ *
89
+ * @public
90
+ */
91
+ get disposed(): boolean;
92
+ private _exec;
93
+ }
94
+ /**
95
+ * Creates a reactive effect that runs now and re-runs when its tracked
96
+ * dependencies change.
97
+ *
98
+ * @param fn - Side-effect function that receives the tracking context (`t`).
99
+ * @returns A new {@link FlowEffect}.
100
+ *
101
+ * @remarks
102
+ * Use an effect when you need to react to state changes with side effects
103
+ * (UI updates, logging, network calls, timers). For computing derived values,
104
+ * prefer derivations; for one-off work, use a normal function.
105
+ *
106
+ * - Track dependencies with `observable.get(t)` or `signal.watch(t)`.
107
+ * - Read without tracking using `observable.pick()`.
108
+ * - Async callbacks are supported; return a promise if you `await` inside.
109
+ *
110
+ * @example
111
+ * ```typescript
112
+ * const $count = state(0);
113
+ *
114
+ * const fx = effect((t) => {
115
+ * console.log("Count is:", $count.get(t));
116
+ * });
117
+ *
118
+ * $count.set(1); // Logs "Count is: 1"
119
+ * $count.set(2); // Logs "Count is: 2"
120
+ *
121
+ * fx.dispose(); // Stop reacting
122
+ * ```
123
+ *
124
+ * @public
125
+ */
126
+ export declare function effect(fn: (t: FlowTracker) => void): FlowEffect;
127
+ //# sourceMappingURL=flowEffect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flowEffect.d.ts","sourceRoot":"","sources":["../../../../src/flow/base/flowEffect.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,qBAAa,UAAU;IACtB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,aAAa,CAAyB;IAC9C,OAAO,CAAC,MAAM,CAA2C;IACzD,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvB;;;;;;;;;;;;;;;OAeG;gBACS,KAAK,EAAE,CAAC,CAAC,EAAE,WAAW,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAK3D;;;;;;;;;;;;;;;;;;OAkBG;IACI,OAAO,IAAI,IAAI;IAQtB;;;;;;OAMG;IACH,IAAW,QAAQ,IAAI,OAAO,CAE7B;YAiBa,KAAK;CAUnB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,WAAW,KAAK,IAAI,GAAG,UAAU,CAE/D"}
@@ -0,0 +1,97 @@
1
+ import { FlowEffect } from './flowEffect';
2
+ /**
3
+ * Coordinates reactive operations (reads, writes, triggers, effects).
4
+ *
5
+ * @remarks
6
+ * FlowGraph manages the execution order of reactive operations to ensure
7
+ * consistent state updates. It queues operations and processes them in a
8
+ * controlled sequence, executing effects after state changes complete.
9
+ *
10
+ * Most users will not interact with FlowGraph directly; reactive primitives
11
+ * use it internally. The `clear()` method may be useful for testing scenarios
12
+ * where you need to reset the internal state between tests.
13
+ *
14
+ * @public
15
+ */
16
+ export declare class FlowGraph {
17
+ private static _effectsQueue;
18
+ private static _actionQueue;
19
+ private static _processingActionQueue;
20
+ /**
21
+ * Resets all internal queues and processing state.
22
+ *
23
+ * @remarks
24
+ * Use this method primarily for testing scenarios where you need to ensure
25
+ * a clean state between test runs. It clears pending effects and queued
26
+ * operations.
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * beforeEach(() => {
31
+ * FlowGraph.clear();
32
+ * });
33
+ * ```
34
+ *
35
+ * @public
36
+ */
37
+ static clear(): void;
38
+ /**
39
+ * Queues a trigger notification for processing.
40
+ *
41
+ * @param notify - Function to call when the trigger is processed.
42
+ * @returns A promise that resolves after the trigger is processed.
43
+ *
44
+ * @remarks
45
+ * This method is used internally by reactive primitives to coordinate
46
+ * signal triggers. The promise resolves after all associated effects
47
+ * have been executed.
48
+ *
49
+ * @public
50
+ */
51
+ static requestTrigger(notify: () => void): Promise<void>;
52
+ /**
53
+ * Queues a read operation for processing.
54
+ *
55
+ * @param read - Function that performs the read operation.
56
+ * @returns A promise that resolves with the read value.
57
+ *
58
+ * @remarks
59
+ * This method is used internally by reactive primitives to coordinate
60
+ * read operations. The read function is executed and its result (or promise)
61
+ * is returned.
62
+ *
63
+ * @public
64
+ */
65
+ static requestRead<T>(read: () => T | Promise<T>): Promise<T>;
66
+ /**
67
+ * Queues a write operation with update logic for processing.
68
+ *
69
+ * @param notify - Function to call if the update succeeds.
70
+ * @param update - Function that performs the update and returns whether
71
+ * it changed the value.
72
+ * @returns A promise that resolves after the write is processed.
73
+ *
74
+ * @remarks
75
+ * This method is used internally by reactive primitives to coordinate
76
+ * write operations. The update function is executed, and if it returns true
77
+ * (or a promise resolving to true), the notify function is called to
78
+ * trigger dependent effects.
79
+ *
80
+ * @public
81
+ */
82
+ static requestWrite(notify: () => void, update: () => boolean | Promise<boolean>): Promise<void>;
83
+ /**
84
+ * Queues effects for execution after the current operation completes.
85
+ *
86
+ * @param effects - Array of effects to queue for execution.
87
+ *
88
+ * @remarks
89
+ * This method is used internally by reactive primitives to schedule effect
90
+ * execution. Effects are executed after the current read/write/trigger
91
+ * operation completes, ensuring proper ordering of reactive updates.
92
+ *
93
+ * @public
94
+ */
95
+ static pushEffects(effects: FlowEffect[]): void;
96
+ }
97
+ //# sourceMappingURL=flowGraph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flowGraph.d.ts","sourceRoot":"","sources":["../../../../src/flow/base/flowGraph.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAmE/C;;;;;;;;;;;;;GAaG;AACH,qBAAa,SAAS;IACrB,OAAO,CAAC,MAAM,CAAC,aAAa,CAAoB;IAChD,OAAO,CAAC,MAAM,CAAC,YAAY,CAAuB;IAClD,OAAO,CAAC,MAAM,CAAC,sBAAsB,CAAS;IAE9C;;;;;;;;;;;;;;;;OAgBG;IACH,MAAM,CAAC,KAAK,IAAI,IAAI;IAMpB;;;;;;;;;;;;OAYG;IACH,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAWxD;;;;;;;;;;;;OAYG;IACH,MAAM,CAAC,WAAW,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAW7D;;;;;;;;;;;;;;;OAeG;IACH,MAAM,CAAC,YAAY,CAClB,MAAM,EAAE,MAAM,IAAI,EAClB,MAAM,EAAE,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,GACtC,OAAO,CAAC,IAAI,CAAC;IAYhB;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,IAAI;CAuF/C"}
@@ -0,0 +1,134 @@
1
+ import { FlowDisposable } from './flowDisposable';
2
+ import { FlowEffect } from './flowEffect';
3
+ import { FlowTracker } from './flowTracker';
4
+ /**
5
+ * Event-like reactive primitive with no payload.
6
+ *
7
+ * @remarks
8
+ * A signal is used to broadcast that “something happened” (refresh, invalidate,
9
+ * notify). It does not carry data; it only notifies dependents that they should
10
+ * react. Track it with `watch(t)` inside an effect or derivation to re-run when
11
+ * the signal is triggered.
12
+ *
13
+ * Signals can be triggered and disposed. Once disposed, further interaction
14
+ * throws an error.
15
+ *
16
+ * @public
17
+ */
18
+ export declare class FlowSignal implements FlowDisposable, FlowTracker {
19
+ /**
20
+ * Triggers the signal and notifies all dependents.
21
+ *
22
+ * @remarks
23
+ * Any effect/derivation that called `watch(t)` on this signal will re-run.
24
+ * Returns a promise that settles after notifications complete.
25
+ *
26
+ * @throws Error if the signal is disposed.
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * const $tick = signal();
31
+ *
32
+ * effect((t) => {
33
+ * $tick.watch(t);
34
+ * console.log("tick");
35
+ * });
36
+ *
37
+ * $tick.trigger(); // logs "tick"
38
+ * ```
39
+ *
40
+ * @public
41
+ */
42
+ trigger(): Promise<void>;
43
+ /**
44
+ * Registers this signal as a dependency in the current tracking context.
45
+ *
46
+ * @param context - The tracking context (`t`) provided to effects/derivations.
47
+ *
48
+ * @remarks
49
+ * Signals have no value to read; calling `watch(t)` simply means “re-run me
50
+ * when this signal is triggered.” Call this inside an effect/derivation
51
+ * callback where a tracking context is available.
52
+ *
53
+ * @throws Error if the signal has been disposed.
54
+ *
55
+ * @example
56
+ * ```typescript
57
+ * const $refresh = signal();
58
+ *
59
+ * effect((t) => {
60
+ * $refresh.watch(t);
61
+ * console.log("refresh triggered");
62
+ * });
63
+ *
64
+ * $refresh.trigger(); // logs "refresh triggered"
65
+ * ```
66
+ *
67
+ * @public
68
+ */
69
+ watch(caller: FlowTracker): void;
70
+ /**
71
+ * Disposes the signal and cleans up its dependencies/listeners.
72
+ *
73
+ * @remarks
74
+ * After disposal the signal must not be used; calling `trigger` or `watch`
75
+ * will throw. If `options?.self` is true, only this signal is disposed; when
76
+ * false or omitted, dependents may also be disposed depending on the
77
+ * implementation.
78
+ *
79
+ * @throws Error if the signal is already disposed.
80
+ *
81
+ * @example
82
+ * ```typescript
83
+ * const $refresh = signal();
84
+ * // ... use it
85
+ * $refresh.dispose();
86
+ * ```
87
+ *
88
+ * @public
89
+ */
90
+ dispose(options?: {
91
+ self: boolean;
92
+ }): void;
93
+ /**
94
+ * Whether the signal has been disposed.
95
+ *
96
+ * @returns `true` if disposed; `false` while active.
97
+ *
98
+ * @remarks Use to guard operations or avoid double disposal.
99
+ *
100
+ * @public
101
+ */
102
+ get disposed(): boolean;
103
+ protected _disposed: boolean;
104
+ protected _dependencies: Set<FlowSignal>;
105
+ protected _listeners: Set<FlowSignal>;
106
+ protected _effects: Set<FlowEffect>;
107
+ protected _notify(): void;
108
+ }
109
+ /**
110
+ * Creates a new signal for event-like notifications.
111
+ *
112
+ * @returns A new instance of {@link FlowSignal}.
113
+ *
114
+ * @remarks
115
+ * Use signals to announce “something happened” when no payload is needed. Track
116
+ * them with `watch(t)` inside effects/derivations and trigger them to re-run
117
+ * dependents.
118
+ *
119
+ * @example
120
+ * ```typescript
121
+ * const $ready = signal();
122
+ *
123
+ * effect((t) => {
124
+ * $ready.watch(t);
125
+ * console.log("ready!");
126
+ * });
127
+ *
128
+ * $ready.trigger(); // logs "ready!"
129
+ * ```
130
+ *
131
+ * @public
132
+ */
133
+ export declare function signal(): FlowSignal;
134
+ //# sourceMappingURL=flowSignal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flowSignal.d.ts","sourceRoot":"","sources":["../../../../src/flow/base/flowSignal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD;;;;;;;;;;;;;GAaG;AACH,qBAAa,UAAW,YAAW,cAAc,EAAE,WAAW;IAC7D;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACU,OAAO;IAKpB;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACI,KAAK,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI;IAKvC;;;;;;;;;;;;;;;;;;;OAmBG;IACI,OAAO,CAAC,OAAO,CAAC,EAAE;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI;IAuBjD;;;;;;;;OAQG;IACH,IAAW,QAAQ,IAAI,OAAO,CAE7B;IAID,SAAS,CAAC,SAAS,UAAS;IAE5B,SAAS,CAAC,aAAa,kBAAyB;IAEhD,SAAS,CAAC,UAAU,kBAAyB;IAE7C,SAAS,CAAC,QAAQ,kBAAyB;IAE3C,SAAS,CAAC,OAAO,IAAI,IAAI;CAiCzB;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,MAAM,IAAI,UAAU,CAEnC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Tracking context passed to reactive callbacks.
3
+ *
4
+ * @remarks
5
+ * Effects and derivations receive an instance of `FlowTracker` as the `t`
6
+ * parameter. Use it inside your callback to register dependencies (for example
7
+ * via APIs that accept `t`) so the callback can re-run when those dependencies
8
+ * change. Typical users do not implement this interface directly; it is
9
+ * implemented by the reactive primitives themselves.
10
+ *
11
+ * @public
12
+ */
13
+ export interface FlowTracker {
14
+ }
15
+ //# sourceMappingURL=flowTracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flowTracker.d.ts","sourceRoot":"","sources":["../../../../src/flow/base/flowTracker.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,WAAW;CAE3B"}
@@ -0,0 +1,7 @@
1
+ export * from './flowDisposable';
2
+ export * from './flowEffect';
3
+ export * from './flowGraph';
4
+ export * from './flowSignal';
5
+ export * from './flowTracker';
6
+ export * from './utils';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/flow/base/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,SAAS,CAAC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Excludes `Promise` types from `T`, returning `never` if `T` is a promise.
3
+ *
4
+ * @remarks
5
+ * Use `NotPromise<T>` to constrain generics to synchronous values. It is helpful
6
+ * when an API must reject promise inputs while accepting other types unchanged.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * function useSync<T>(value: NotPromise<T>) {
11
+ * // value cannot be a Promise
12
+ * return value;
13
+ * }
14
+ *
15
+ * useSync(123); // ok
16
+ * // useSync(Promise.resolve(1)); // type error
17
+ * ```
18
+ */
19
+ export type NotPromise<T> = T extends Promise<unknown> ? never : T;
20
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../src/flow/base/utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,MAAM,UAAU,CAAC,CAAC,IAAI,CAAC,SAAS,OAAO,CAAC,OAAO,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC"}
@@ -1,4 +1,4 @@
1
- import { FlowObservable, FlowState } from '../basic';
1
+ import { FlowNode, FlowState } from '../nodes';
2
2
  /**
3
3
  * Represents the actions that can be performed on a FlowArray.
4
4
  * @public
@@ -7,7 +7,7 @@ export type FlowArrayAction<T> = {
7
7
  type: "set";
8
8
  items: T[];
9
9
  } | {
10
- type: "setItem";
10
+ type: "update";
11
11
  index: number;
12
12
  item: T;
13
13
  } | {
@@ -32,12 +32,13 @@ export type FlowArrayAction<T> = {
32
32
  * Represents a reactive array.
33
33
  * @public
34
34
  */
35
- export declare class FlowArray<T> extends FlowObservable<T[]> {
35
+ export declare class FlowArray<T> extends FlowNode<T[]> {
36
36
  /**
37
37
  * Last action performed on the FlowArray.
38
38
  * @public
39
39
  */
40
40
  $lastAction: FlowState<FlowArrayAction<T>>;
41
+ protected _value: T[];
41
42
  /**
42
43
  * Creates an instance of FlowArray.
43
44
  * @param value - Initial array value.
@@ -55,36 +56,36 @@ export declare class FlowArray<T> extends FlowObservable<T[]> {
55
56
  * @param items - The new array of items.
56
57
  * @public
57
58
  */
58
- set(items: T[]): void;
59
+ set(items: T[]): Promise<void>;
59
60
  /**
60
61
  * Replaces an item at a specific index.
61
62
  * @param index - The index of the item to replace.
62
63
  * @param item - The new item.
63
64
  * @public
64
65
  */
65
- setItem(index: number, item: T): void;
66
+ update(index: number, item: T): Promise<void>;
66
67
  /**
67
68
  * Appends an item to the end of the array.
68
69
  * @param item - The item to append.
69
70
  * @public
70
71
  */
71
- push(item: T): void;
72
+ push(item: T): Promise<void>;
72
73
  /**
73
74
  * Removes the last item from the array.
74
75
  * @public
75
76
  */
76
- pop(): void;
77
+ pop(): Promise<void>;
77
78
  /**
78
79
  * Inserts an item at the beginning of the array.
79
80
  * @param item - The item to insert.
80
81
  * @public
81
82
  */
82
- unshift(item: T): void;
83
+ unshift(item: T): Promise<void>;
83
84
  /**
84
85
  * Removes the first item from the array.
85
86
  * @public
86
87
  */
87
- shift(): void;
88
+ shift(): Promise<void>;
88
89
  /**
89
90
  * Changes the content of the array.
90
91
  * @param start - The starting index.
@@ -92,12 +93,12 @@ export declare class FlowArray<T> extends FlowObservable<T[]> {
92
93
  * @param newItems - New items to add.
93
94
  * @public
94
95
  */
95
- splice(start: number, deleteCount: number, ...newItems: T[]): void;
96
+ splice(start: number, deleteCount: number, ...newItems: T[]): Promise<void>;
96
97
  /**
97
98
  * Clears all items from the array.
98
99
  * @public
99
100
  */
100
- clear(): void;
101
+ clear(): Promise<void>;
101
102
  /**
102
103
  * Disposes the FlowArray and its items.
103
104
  * @param options - Disposal options.
@@ -107,4 +108,41 @@ export declare class FlowArray<T> extends FlowObservable<T[]> {
107
108
  self: boolean;
108
109
  }): void;
109
110
  }
110
- //# sourceMappingURL=array.d.ts.map
111
+ /**
112
+ * Creates a new reactive array with mutation methods and fine-grained action tracking.
113
+ *
114
+ * @typeParam T - The type of the array elements.
115
+ * @param initial - An optional array of initial values.
116
+ * @returns A new instance of {@link FlowArray}.
117
+ *
118
+ * @remarks
119
+ * A reactive array provides array-like mutation methods (push, pop, shift, unshift, splice)
120
+ * and tracks the last operation performed via `$lastAction`. This enables both whole-array
121
+ * reactivity and fine-grained tracking of specific mutations.
122
+ *
123
+ * The array automatically disposes disposable items when they are removed (if they implement
124
+ * the FlowDisposable interface).
125
+ *
126
+ * @example
127
+ * ```typescript
128
+ * const $items = array([1, 2, 3]);
129
+ *
130
+ * // Track the whole array
131
+ * effect((t) => {
132
+ * console.log('Items:', $items.get(t));
133
+ * });
134
+ *
135
+ * // Track the last action
136
+ * effect((t) => {
137
+ * const action = $items.$lastAction.get(t);
138
+ * console.log('Action:', action.type);
139
+ * });
140
+ *
141
+ * $items.push(4); // Logs action: "push"
142
+ * $items.pop(); // Logs action: "pop"
143
+ * ```
144
+ *
145
+ * @public
146
+ */
147
+ export declare function array<T>(initial?: T[]): FlowArray<T>;
148
+ //# sourceMappingURL=flowArray.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flowArray.d.ts","sourceRoot":"","sources":["../../../../src/flow/collections/flowArray.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,KAAK,SAAS,EAAS,MAAM,UAAU,CAAC;AAE3D;;;GAGG;AACH,MAAM,MAAM,eAAe,CAAC,CAAC,IAC1B;IACA,IAAI,EAAE,KAAK,CAAC;IACZ,KAAK,EAAE,CAAC,EAAE,CAAC;CACV,GACD;IACA,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,CAAC,CAAC;CACP,GACD;IACA,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,CAAC,CAAC;CACP,GACD;IACA,IAAI,EAAE,KAAK,CAAC;CACX,GACD;IACA,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,CAAC,CAAC;CACP,GACD;IACA,IAAI,EAAE,OAAO,CAAC;CACb,GACD;IACA,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,CAAC,EAAE,CAAC;CACV,GACD;IACA,IAAI,EAAE,OAAO,CAAC;CACb,CAAC;AAEL;;;GAGG;AACH,qBAAa,SAAS,CAAC,CAAC,CAAE,SAAQ,QAAQ,CAAC,CAAC,EAAE,CAAC;IAC9C;;;OAGG;IACH,WAAW,EAAE,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3C,UAAkB,MAAM,EAAE,CAAC,EAAE,CAAC;IAE9B;;;;OAIG;gBACS,KAAK,GAAE,CAAC,EAAO;IAQ3B;;;;OAIG;IACH,IAAI,MAAM,IAAI,MAAM,CAGnB;IAWD;;;;OAIG;IACY,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IA+B7C;;;;;OAKG;IACG,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAmCnD;;;;OAIG;IACG,IAAI,CAAC,IAAI,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBlC;;;OAGG;IACG,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;IA8B1B;;;;OAIG;IACG,OAAO,CAAC,IAAI,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBrC;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA6B5B;;;;;;OAMG;IACG,MAAM,CACX,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,EACnB,GAAG,QAAQ,EAAE,CAAC,EAAE,GACd,OAAO,CAAC,IAAI,CAAC;IA+BhB;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA2B5B;;;;OAIG;IACM,OAAO,CAAC,OAAO,CAAC,EAAE;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI;CASnD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAgB,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,CAAC,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC,CAEpD"}