@ersbeth/picoflow 2.0.2 → 2.0.3

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 (152) hide show
  1. package/README.md +10 -0
  2. package/SKILL.md +106 -0
  3. package/package.json +5 -1
  4. package/.gitlab-ci.yml +0 -24
  5. package/.vscode/settings.json +0 -5
  6. package/CHANGELOG.md +0 -94
  7. package/biome.json +0 -47
  8. package/docs/.vitepress/config.mts +0 -145
  9. package/docs/api/functions/array.md +0 -35
  10. package/docs/api/functions/constant.md +0 -33
  11. package/docs/api/functions/constantAsync.md +0 -69
  12. package/docs/api/functions/derivation.md +0 -34
  13. package/docs/api/functions/derivationAsync.md +0 -34
  14. package/docs/api/functions/from.md +0 -129
  15. package/docs/api/functions/isDisposable.md +0 -27
  16. package/docs/api/functions/map.md +0 -36
  17. package/docs/api/functions/signal.md +0 -21
  18. package/docs/api/functions/state.md +0 -67
  19. package/docs/api/functions/stateAsync.md +0 -69
  20. package/docs/api/functions/subscribe.md +0 -40
  21. package/docs/api/functions/writableDerivation.md +0 -33
  22. package/docs/api/functions/writableDerivationAsync.md +0 -34
  23. package/docs/api/index.md +0 -61
  24. package/docs/api/interfaces/FlowArray.md +0 -439
  25. package/docs/api/interfaces/FlowConstant.md +0 -220
  26. package/docs/api/interfaces/FlowConstantAsync.md +0 -221
  27. package/docs/api/interfaces/FlowDerivation.md +0 -241
  28. package/docs/api/interfaces/FlowDerivationAsync.md +0 -242
  29. package/docs/api/interfaces/FlowDisposable.md +0 -59
  30. package/docs/api/interfaces/FlowEffect.md +0 -64
  31. package/docs/api/interfaces/FlowMap.md +0 -374
  32. package/docs/api/interfaces/FlowObservable.md +0 -155
  33. package/docs/api/interfaces/FlowSignal.md +0 -156
  34. package/docs/api/interfaces/FlowState.md +0 -269
  35. package/docs/api/interfaces/FlowStateAsync.md +0 -268
  36. package/docs/api/interfaces/FlowSubscribable.md +0 -55
  37. package/docs/api/interfaces/FlowTracker.md +0 -61
  38. package/docs/api/interfaces/FlowValue.md +0 -222
  39. package/docs/api/interfaces/FlowWritableDerivation.md +0 -292
  40. package/docs/api/interfaces/FlowWritableDerivationAsync.md +0 -293
  41. package/docs/api/type-aliases/DerivationFunction.md +0 -28
  42. package/docs/api/type-aliases/DerivationFunctionAsync.md +0 -28
  43. package/docs/api/type-aliases/FlowArrayAction.md +0 -60
  44. package/docs/api/type-aliases/FlowDataTracker.md +0 -33
  45. package/docs/api/type-aliases/FlowMapAction.md +0 -48
  46. package/docs/api/type-aliases/FlowOnDataListener.md +0 -33
  47. package/docs/api/type-aliases/FlowOnErrorListener.md +0 -27
  48. package/docs/api/type-aliases/FlowOnPendingListener.md +0 -21
  49. package/docs/api/type-aliases/FlowReadonly.md +0 -22
  50. package/docs/api/type-aliases/InitFunction.md +0 -21
  51. package/docs/api/type-aliases/InitFunctionAsync.md +0 -21
  52. package/docs/api/type-aliases/NotPromise.md +0 -21
  53. package/docs/api/type-aliases/UpdateFunction.md +0 -27
  54. package/docs/api/type-aliases/UpdateFunctionAsync.md +0 -27
  55. package/docs/api/typedoc-sidebar.json +0 -65
  56. package/docs/examples/examples.md +0 -2311
  57. package/docs/examples/patterns.md +0 -649
  58. package/docs/guide/advanced/architecture.md +0 -1234
  59. package/docs/guide/advanced/disposal.md +0 -426
  60. package/docs/guide/advanced/migration-v1.md +0 -464
  61. package/docs/guide/advanced/migration-v2.md +0 -204
  62. package/docs/guide/advanced/solidjs.md +0 -135
  63. package/docs/guide/introduction/concepts.md +0 -57
  64. package/docs/guide/introduction/conventions.md +0 -30
  65. package/docs/guide/introduction/getting-started.md +0 -139
  66. package/docs/guide/introduction/lifecycle.md +0 -368
  67. package/docs/guide/primitives/array.md +0 -286
  68. package/docs/guide/primitives/constant.md +0 -207
  69. package/docs/guide/primitives/derivations.md +0 -281
  70. package/docs/guide/primitives/effects.md +0 -372
  71. package/docs/guide/primitives/map.md +0 -265
  72. package/docs/guide/primitives/overview.md +0 -92
  73. package/docs/guide/primitives/signal.md +0 -222
  74. package/docs/guide/primitives/state.md +0 -272
  75. package/docs/index.md +0 -47
  76. package/docs/public/logo.svg +0 -1
  77. package/src/api/base/flowDisposable.ts +0 -44
  78. package/src/api/base/flowObservable.ts +0 -28
  79. package/src/api/base/flowSubscribable.ts +0 -87
  80. package/src/api/base/flowTracker.ts +0 -7
  81. package/src/api/base/index.ts +0 -4
  82. package/src/api/index.ts +0 -2
  83. package/src/api/nodes/async/flowConstantAsync.ts +0 -36
  84. package/src/api/nodes/async/flowDerivationAsync.ts +0 -42
  85. package/src/api/nodes/async/flowStateAsync.ts +0 -47
  86. package/src/api/nodes/async/flowWritableDerivationAsync.ts +0 -33
  87. package/src/api/nodes/async/index.ts +0 -4
  88. package/src/api/nodes/collections/flowArray.ts +0 -155
  89. package/src/api/nodes/collections/flowMap.ts +0 -115
  90. package/src/api/nodes/collections/index.ts +0 -2
  91. package/src/api/nodes/flowEffect.ts +0 -42
  92. package/src/api/nodes/flowSignal.ts +0 -28
  93. package/src/api/nodes/flowValue.ts +0 -37
  94. package/src/api/nodes/index.ts +0 -7
  95. package/src/api/nodes/sync/flowConstant.ts +0 -33
  96. package/src/api/nodes/sync/flowDerivation.ts +0 -41
  97. package/src/api/nodes/sync/flowState.ts +0 -45
  98. package/src/api/nodes/sync/flowWritableDerivation.ts +0 -31
  99. package/src/api/nodes/sync/index.ts +0 -4
  100. package/src/api/nodes/utils.ts +0 -24
  101. package/src/base/disposable.ts +0 -18
  102. package/src/base/executionStack.ts +0 -42
  103. package/src/base/index.ts +0 -5
  104. package/src/base/node.ts +0 -98
  105. package/src/base/observable.ts +0 -92
  106. package/src/base/observer.ts +0 -51
  107. package/src/converters/index.ts +0 -1
  108. package/src/converters/solid.ts +0 -109
  109. package/src/index.ts +0 -2
  110. package/src/nodes/arrayNode.ts +0 -180
  111. package/src/nodes/effectNode.ts +0 -58
  112. package/src/nodes/index.ts +0 -7
  113. package/src/nodes/mapNode.ts +0 -125
  114. package/src/nodes/signalNode.ts +0 -19
  115. package/src/nodes/valueAsyncNode.ts +0 -85
  116. package/src/nodes/valueNode.ts +0 -148
  117. package/src/nodes/valueSyncNode.ts +0 -125
  118. package/src/schedulers/asyncResolver.ts +0 -78
  119. package/src/schedulers/asyncScheduler.ts +0 -66
  120. package/src/schedulers/index.ts +0 -4
  121. package/src/schedulers/pendingError.ts +0 -13
  122. package/src/schedulers/scheduler.ts +0 -9
  123. package/src/schedulers/syncResolver.ts +0 -69
  124. package/src/schedulers/syncScheduler.ts +0 -55
  125. package/test/base/pendingError.test.ts +0 -67
  126. package/test/converters/solid.derivation.browser.test.tsx +0 -69
  127. package/test/converters/solid.node.test.ts +0 -654
  128. package/test/converters/solid.state.browser.test.tsx +0 -1592
  129. package/test/reactivity/flowSignal.test.ts +0 -226
  130. package/test/reactivity/nodes/async/asyncScheduler/asyncResolver.test.ts +0 -593
  131. package/test/reactivity/nodes/async/asyncScheduler/asyncScheduler.test.ts +0 -317
  132. package/test/reactivity/nodes/async/flowConstantAsync.test.ts +0 -652
  133. package/test/reactivity/nodes/async/flowDerivation.test.ts +0 -898
  134. package/test/reactivity/nodes/async/flowDerivationAsync.test.ts +0 -1716
  135. package/test/reactivity/nodes/async/flowStateAsync.test.ts +0 -708
  136. package/test/reactivity/nodes/async/flowWritableDerivationAsync.test.ts +0 -614
  137. package/test/reactivity/nodes/collections/flowArray.asyncStates.test.ts +0 -1289
  138. package/test/reactivity/nodes/collections/flowArray.scalars.test.ts +0 -961
  139. package/test/reactivity/nodes/collections/flowArray.states.test.ts +0 -1035
  140. package/test/reactivity/nodes/collections/flowMap.asyncStates.test.ts +0 -960
  141. package/test/reactivity/nodes/collections/flowMap.scalars.test.ts +0 -775
  142. package/test/reactivity/nodes/collections/flowMap.states.test.ts +0 -958
  143. package/test/reactivity/nodes/sync/flowConstant.test.ts +0 -377
  144. package/test/reactivity/nodes/sync/flowDerivation.test.ts +0 -896
  145. package/test/reactivity/nodes/sync/flowState.test.ts +0 -341
  146. package/test/reactivity/nodes/sync/flowWritableDerivation.test.ts +0 -603
  147. package/test/vitest.d.ts +0 -10
  148. package/tsconfig.json +0 -37
  149. package/typedoc.json +0 -37
  150. package/vite.config.ts +0 -31
  151. package/vitest.browser.config.ts +0 -21
  152. package/vitest.config.ts +0 -17
@@ -1,33 +0,0 @@
1
- import { ValueSyncNode } from "../../../nodes/valueSyncNode";
2
- import type { FlowValue } from "../flowValue";
3
- import type { NotPromise } from "../utils";
4
-
5
- /** Function that initializes a value. */
6
- export type InitFunction<T> = () => NotPromise<T>;
7
-
8
- /**
9
- * Read-only reactive value that computes once on initialization and never changes.
10
- *
11
- * Constants provide lazy initialization - the value isn't computed until first accessed via `get()` or `pick()`.
12
- * Once computed, the value is cached forever. Use constants for expensive computations that only need to run once,
13
- * such as loading configuration, computing static lookups, or initializing resources.
14
- *
15
- * @public
16
- */
17
- export interface FlowConstant<T> extends FlowValue<T> {}
18
-
19
- /**
20
- * Creates a constant reactive value that initializes lazily and never recomputes.
21
- *
22
- * The initializer function runs once on first access, and the result is cached permanently.
23
- * Unlike state or derivations, constants never react to changes - they represent immutable values
24
- * in the reactive graph. Useful for expensive one-time computations or static configuration.
25
- *
26
- * @param initializer - Function that computes the constant value on first access
27
- * @returns A FlowConstant that provides read-only access to the cached value
28
- *
29
- * @public
30
- */
31
- export function constant<T>(initializer: InitFunction<T>): FlowConstant<T> {
32
- return new ValueSyncNode(initializer);
33
- }
@@ -1,41 +0,0 @@
1
- import { ValueSyncNode } from "../../../nodes/valueSyncNode";
2
- import type { FlowTracker } from "../../base/flowTracker";
3
- import type { FlowValue } from "../flowValue";
4
- import type { NotPromise } from "../utils";
5
-
6
- /** Function that derives a value from dependencies and optionally the previous value. */
7
- export type DerivationFunction<T> = (tracker: FlowTracker, previous?: NotPromise<T> | undefined) => NotPromise<T>;
8
-
9
- /**
10
- * Read-only reactive value that recomputes automatically when dependencies change.
11
- *
12
- * Derivations track reactive values accessed during computation and automatically recompute when any
13
- * tracked dependency changes. The computed value is cached until dependencies change, avoiding unnecessary
14
- * recomputations. Use derivations for values derived from other reactive state, such as filtered lists,
15
- * computed properties, or aggregated data.
16
- *
17
- * @public
18
- */
19
- export interface FlowDerivation<T> extends FlowValue<T> {
20
- /**
21
- * Forces the derivation to recompute even if dependencies haven't changed.
22
- */
23
- refresh(): void;
24
- }
25
-
26
- /**
27
- * Creates a derived reactive value that automatically recomputes when dependencies change.
28
- *
29
- * The compute function runs when any tracked dependency changes, and the result is cached until the next change.
30
- * Access reactive values within the compute function to establish dependencies automatically. The derivation
31
- * computes lazily on first access and then reactively thereafter. Use for derived data that should stay
32
- * synchronized with source state.
33
- *
34
- * @param compute - Function that accesses dependencies and computes the derived value
35
- * @returns A FlowDerivation that provides read-only access to the computed value
36
- *
37
- * @public
38
- */
39
- export function derivation<T>(compute: DerivationFunction<T>): FlowDerivation<T> {
40
- return new ValueSyncNode(compute);
41
- }
@@ -1,45 +0,0 @@
1
- import { ValueSyncNode } from "../../../nodes/valueSyncNode";
2
- import type { FlowValue } from "../flowValue";
3
- import type { NotPromise } from "../utils";
4
- import type { InitFunction } from "./flowConstant";
5
-
6
- /** Function that updates a value based on the previous value. */
7
- export type UpdateFunction<T> = (previous: NotPromise<T> | undefined) => NotPromise<T>;
8
-
9
- /**
10
- * Writable reactive value that can be updated manually and notifies dependents on changes.
11
- *
12
- * State is the simplest writable reactive primitive. Unlike derivations, it has no dependencies and never
13
- * recomputes automatically - changes only occur when you explicitly call `set()`. Use state for user input,
14
- * application state, or any data that changes imperatively. Changes propagate automatically to all dependents.
15
- *
16
- * @public
17
- */
18
- export interface FlowState<T> extends FlowValue<T> {
19
- /**
20
- * Updates the state with a new value or via an updater function.
21
- * Notifies all dependents after the update.
22
- *
23
- * @param value - New value to set, or function that receives current value and returns new value
24
- */
25
- set(value: NotPromise<T>): void;
26
- set(updater: UpdateFunction<T>): void;
27
- }
28
-
29
- /**
30
- * Creates a mutable reactive state that can be read and updated imperatively.
31
- *
32
- * State can be initialized with a direct value or a lazy initializer function. Changes propagate
33
- * automatically to all reactive computations that depend on this state. Use state for data that
34
- * changes through user actions, external events, or application logic rather than derived computations.
35
- *
36
- * @param value - Initial value for the state, or lazy initializer function
37
- * @returns A FlowState that can be read and modified
38
- *
39
- * @public
40
- */
41
- export function state<T>(value: NotPromise<T>): FlowState<T>;
42
- export function state<T>(initializer: InitFunction<T>): FlowState<T>;
43
- export function state<T>(valueOrInitializer: NotPromise<T> | InitFunction<T>): FlowState<T> {
44
- return new ValueSyncNode(valueOrInitializer);
45
- }
@@ -1,31 +0,0 @@
1
- import { ValueSyncNode } from "../../../nodes/valueSyncNode";
2
- import type { DerivationFunction, FlowDerivation } from "./flowDerivation";
3
- import type { FlowState } from "./flowState";
4
-
5
- /**
6
- * Writable reactive value that recomputes automatically when dependencies change, but can be manually overridden.
7
- *
8
- * Writable derivations combine reactive computation with manual control. They track dependencies and recompute
9
- * like regular derivations, but you can also call `set()` to override the computed value temporarily. Use this
10
- * for computed values that users can edit, such as formatted fields, calculated totals that can be adjusted,
11
- * or any value that is usually derived but sometimes needs manual correction.
12
- *
13
- * @public
14
- */
15
- export interface FlowWritableDerivation<T> extends FlowState<T>, FlowDerivation<T> {}
16
-
17
- /**
18
- * Creates a derived value that recomputes automatically but can also be manually overridden.
19
- *
20
- * The compute function tracks dependencies and recomputes when they change, just like a regular derivation.
21
- * However, you can also call `set()` to override the computed value. Use this for values that are normally
22
- * derived but need occasional manual adjustments, such as editable calculated fields or user-correctable totals.
23
- *
24
- * @param compute - Function that accesses dependencies and computes the derived value
25
- * @returns A FlowWritableDerivation that provides both reactive computation and manual control
26
- *
27
- * @public
28
- */
29
- export function writableDerivation<T>(compute: DerivationFunction<T>): FlowWritableDerivation<T> {
30
- return new ValueSyncNode(compute);
31
- }
@@ -1,4 +0,0 @@
1
- export * from "./flowConstant";
2
- export * from "./flowDerivation";
3
- export * from "./flowState";
4
- export * from "./flowWritableDerivation";
@@ -1,24 +0,0 @@
1
- import type { FlowValue } from "./flowValue";
2
-
3
- /**
4
- * Type that excludes Promise values from a type union.
5
- *
6
- * This utility type ensures that synchronous reactive primitives (like `state`, `constant`, `derivation`)
7
- * only accept non-Promise values. Use this to prevent accidental mixing of sync and async values, which
8
- * would cause runtime errors. For async values, use the async variants (like `stateAsync`, `constantAsync`).
9
- *
10
- * @public
11
- */
12
- export type NotPromise<T> = T extends Promise<unknown> ? never : T;
13
-
14
- /**
15
- * Type that restricts mutation methods to create read-only versions of reactive primitives.
16
- *
17
- * This utility type removes mutation methods (`set`, `refresh`, `trigger`) from a reactive primitive,
18
- * creating a read-only interface. Use this when you want to expose reactive values to consumers who
19
- * should observe but not modify them, such as passing state to child components or external modules
20
- * while maintaining encapsulation of write access.
21
- *
22
- * @public
23
- */
24
- export type FlowReadonly<T> = Omit<FlowValue<T>, "set" | "refresh" | "trigger">;
@@ -1,18 +0,0 @@
1
- import type { FlowDisposable } from "../api";
2
-
3
- /**
4
- * Base implementation of the disposable pattern for reactive primitives.
5
- * Throws an error if disposed multiple times.
6
- */
7
- export class Disposable implements FlowDisposable {
8
- protected _disposed = false;
9
-
10
- get disposed(): boolean {
11
- return this._disposed;
12
- }
13
-
14
- dispose(): void {
15
- if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
16
- this._disposed = true;
17
- }
18
- }
@@ -1,42 +0,0 @@
1
- import type { IObserver } from "./observer";
2
-
3
- /**
4
- * Global scheduler that batches and executes reactive computations asynchronously.
5
- */
6
- export class ExecutionStack {
7
- private static readonly _pendingQueue: IObserver[] = [];
8
- private static readonly _effectQueue: IObserver[] = [];
9
- private static _executionScheduled?: Promise<void>;
10
-
11
- static pushPending(node: IObserver): void {
12
- ExecutionStack._scheduleExecution();
13
- ExecutionStack._pendingQueue.push(node);
14
- }
15
-
16
- static pushEffect(effect: IObserver): void {
17
- ExecutionStack._scheduleExecution();
18
- ExecutionStack._effectQueue.push(effect);
19
- }
20
-
21
- private static _scheduleExecution(): void {
22
- if (ExecutionStack._executionScheduled) return;
23
- ExecutionStack._executionScheduled = new Promise((resolve) => {
24
- setTimeout(() => {
25
- ExecutionStack._executionScheduled = undefined;
26
- ExecutionStack._execute();
27
- resolve();
28
- }, 0);
29
- });
30
- }
31
-
32
- private static _execute(): void {
33
- ExecutionStack._pendingQueue.forEach((node) => {
34
- node.execute();
35
- });
36
- ExecutionStack._pendingQueue.length = 0;
37
- ExecutionStack._effectQueue.forEach((effect) => {
38
- effect.execute();
39
- });
40
- ExecutionStack._effectQueue.length = 0;
41
- }
42
- }
package/src/base/index.ts DELETED
@@ -1,5 +0,0 @@
1
- export * from "./disposable";
2
- export * from "./executionStack";
3
- export * from "./node";
4
- export * from "./observable";
5
- export * from "./observer";
package/src/base/node.ts DELETED
@@ -1,98 +0,0 @@
1
- import type { FlowEffect, FlowOnDataListener, FlowOnErrorListener, FlowOnPendingListener, FlowTracker } from "../api";
2
- import { Disposable } from "./disposable";
3
- import type { IObservable, ObservableStatus } from "./observable";
4
- import type { IObserver } from "./observer";
5
-
6
- /**
7
- * Base implementation for reactive nodes that propagate changes through the dependency graph.
8
- */
9
- export abstract class Node<T> extends Disposable implements IObservable<T>, IObserver {
10
- private _dependencies = new Set<IObservable<unknown>>();
11
- private _dependents = new Set<IObserver>();
12
- protected _status: ObservableStatus = "resolved";
13
-
14
- get status(): ObservableStatus {
15
- if (this.disposed) throw new Error("[PicoFlow] Primitive is disposed");
16
- return this._status;
17
- }
18
-
19
- set status(status: ObservableStatus) {
20
- if (this.disposed) throw new Error("[PicoFlow] Primitive is disposed");
21
- this._status = status;
22
- }
23
-
24
- registerDependency(dependency: IObservable<unknown>): void {
25
- if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
26
- this._dependencies.add(dependency);
27
- dependency.registerDependent(this);
28
- }
29
-
30
- unregisterDependency(dependency: IObservable<unknown>): void {
31
- if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
32
- this._dependencies.delete(dependency);
33
- dependency.unregisterDependent(this);
34
- }
35
-
36
- clearDependencies(): void {
37
- if (this.disposed) throw new Error("[PicoFlow] Primitive is disposed");
38
- this._dependencies.forEach((dependency) => {
39
- dependency.unregisterDependent(this);
40
- });
41
- this._dependencies.clear();
42
- }
43
-
44
- registerDependent(dependent: IObserver): void {
45
- if (this.disposed) throw new Error("[PicoFlow] Primitive is disposed");
46
- this._dependents.add(dependent);
47
- }
48
-
49
- unregisterDependent(dependent: IObserver): void {
50
- if (this.disposed) throw new Error("[PicoFlow] Primitive is disposed");
51
- this._dependents.delete(dependent);
52
- }
53
-
54
- notifyDependents(): void {
55
- if (this.disposed) return;
56
- this._dependents.forEach((dependent) => {
57
- dependent.notify();
58
- });
59
- }
60
-
61
- watch(tracker: FlowTracker): void {
62
- if (this.disposed) throw new Error("[PicoFlow] Primitive is disposed");
63
- (tracker as unknown as IObserver).registerDependency(this);
64
- }
65
-
66
- trigger(): void {
67
- if (this.disposed) throw new Error("[PicoFlow] Primitive is disposed");
68
- this.notifyDependents();
69
- }
70
-
71
- notify(): void {
72
- if (this.disposed) throw new Error("[PicoFlow] Primitive is disposed");
73
- if (this.status === "dirty") return;
74
- this.status = "dirty";
75
- this.notifyDependents();
76
- }
77
-
78
- override dispose(): void {
79
- if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
80
- Array.from(this._dependents).forEach((dependant) => {
81
- dependant.unregisterDependency(this);
82
- this.unregisterDependent(dependant);
83
- });
84
- Array.from(this._dependencies).forEach((dependency) => {
85
- this.unregisterDependency(dependency);
86
- });
87
-
88
- this._disposed = true;
89
- }
90
-
91
- abstract execute(): void;
92
-
93
- abstract subscribe(
94
- onValue: FlowOnDataListener<T>,
95
- onError?: FlowOnErrorListener,
96
- onPending?: FlowOnPendingListener,
97
- ): FlowEffect;
98
- }
@@ -1,92 +0,0 @@
1
- import type {
2
- FlowEffect,
3
- FlowObservable,
4
- FlowOnDataListener,
5
- FlowOnErrorListener,
6
- FlowOnPendingListener,
7
- FlowTracker,
8
- } from "../api";
9
- import { Disposable } from "./disposable";
10
- import type { IObserver } from "./observer";
11
-
12
- /**
13
- * Status of an observable: resolved (has value), pending (async in progress), error (failed), or dirty (needs recomputation).
14
- */
15
- export type ObservableStatus = "resolved" | "pending" | "error" | "dirty";
16
-
17
- /**
18
- * Internal interface extending FlowObservable with dependency graph management methods.
19
- */
20
- export interface IObservable<T> extends FlowObservable<T> {
21
- get status(): ObservableStatus;
22
- set status(status: ObservableStatus);
23
- registerDependent(dependent: IObserver): void;
24
- unregisterDependent(dependent: IObserver): void;
25
- notifyDependents(): void;
26
- subscribe(
27
- onValue: FlowOnDataListener<T>,
28
- onError?: FlowOnErrorListener,
29
- onPending?: FlowOnPendingListener,
30
- ): FlowEffect;
31
- }
32
-
33
- /**
34
- * Base implementation managing the dependency graph for reactive observables.
35
- */
36
- export abstract class Observable<T> extends Disposable implements IObservable<T> {
37
- private _dependents = new Set<IObserver>();
38
- protected _status: ObservableStatus = "resolved";
39
-
40
- get status(): ObservableStatus {
41
- if (this.disposed) throw new Error("[PicoFlow] Primitive is disposed");
42
- return this._status;
43
- }
44
-
45
- set status(status: ObservableStatus) {
46
- if (this.disposed) throw new Error("[PicoFlow] Primitive is disposed");
47
- this._status = status;
48
- }
49
-
50
- registerDependent(dependent: IObserver): void {
51
- if (this.disposed) throw new Error("[PicoFlow] Primitive is disposed");
52
- this._dependents.add(dependent);
53
- }
54
-
55
- unregisterDependent(dependent: IObserver): void {
56
- if (this.disposed) throw new Error("[PicoFlow] Primitive is disposed");
57
- this._dependents.delete(dependent);
58
- }
59
-
60
- notifyDependents(): void {
61
- if (this.disposed) return; //throw new Error("[PicoFlow] Primitive is disposed");
62
- this._dependents.forEach((dependent) => {
63
- dependent.notify();
64
- });
65
- }
66
-
67
- watch(tracker: FlowTracker): void {
68
- if (this.disposed) throw new Error("[PicoFlow] Primitive is disposed");
69
- (tracker as unknown as IObserver).registerDependency(this);
70
- }
71
-
72
- trigger(): void {
73
- if (this.disposed) throw new Error("[PicoFlow] Primitive is disposed");
74
- this.notifyDependents();
75
- }
76
-
77
- override dispose(): void {
78
- if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
79
- Array.from(this._dependents).forEach((dependant) => {
80
- dependant.unregisterDependency(this);
81
- this.unregisterDependent(dependant);
82
- });
83
-
84
- this._disposed = true;
85
- }
86
-
87
- abstract subscribe(
88
- onValue: FlowOnDataListener<T>,
89
- onError?: FlowOnErrorListener,
90
- onPending?: FlowOnPendingListener,
91
- ): FlowEffect;
92
- }
@@ -1,51 +0,0 @@
1
- import { Disposable } from "./disposable";
2
- import type { IObservable } from "./observable";
3
-
4
- /**
5
- * Internal interface for reactive computations that track dependencies and respond to changes.
6
- */
7
- export interface IObserver {
8
- registerDependency(dependency: IObservable<unknown>): void;
9
- unregisterDependency(dependency: IObservable<unknown>): void;
10
- clearDependencies(): void;
11
- notify(): void;
12
- execute(): void;
13
- }
14
-
15
- /**
16
- * Base implementation managing dependency tracking for reactive observers.
17
- */
18
- export abstract class Observer extends Disposable implements IObserver {
19
- private _dependencies = new Set<IObservable<unknown>>();
20
-
21
- registerDependency(dependency: IObservable<unknown>): void {
22
- if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
23
- this._dependencies.add(dependency);
24
- dependency.registerDependent(this);
25
- }
26
-
27
- unregisterDependency(dependency: IObservable<unknown>): void {
28
- if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
29
- this._dependencies.delete(dependency);
30
- dependency.unregisterDependent(this);
31
- }
32
-
33
- clearDependencies(): void {
34
- if (this.disposed) throw new Error("[PicoFlow] Primitive is disposed");
35
- this._dependencies.forEach((dependency) => {
36
- dependency.unregisterDependent(this);
37
- });
38
- this._dependencies.clear();
39
- }
40
-
41
- override dispose(): void {
42
- if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
43
- Array.from(this._dependencies).forEach((dependency) => {
44
- this.unregisterDependency(dependency);
45
- });
46
- this._disposed = true;
47
- }
48
-
49
- abstract notify(): void;
50
- abstract execute(): void;
51
- }
@@ -1 +0,0 @@
1
- export * from "./solid";
@@ -1,109 +0,0 @@
1
- import { createEffect, createResource, onCleanup, onMount, type Resource, resetErrorBoundaries } from "solid-js";
2
- import { type FlowEffect, type FlowObservable, type FlowTracker, type NotPromise, subscribe } from "../api";
3
- import { ValueAsyncNode, ValueSyncNode } from "../nodes";
4
-
5
- /**
6
- * Internal helper that converts a PicoFlow node into a SolidJS resource.
7
- * @internal
8
- */
9
- function fromNode<T>(node: ValueAsyncNode<T> | ValueSyncNode<T>): Resource<T> {
10
- const [resource, { refetch }] = createResource(() => node.pick());
11
-
12
- let fx: FlowEffect;
13
-
14
- onMount(() => {
15
- fx = subscribe(
16
- // data
17
- (t) => node.get(t),
18
- // onData
19
- () => {
20
- refetch(); // Force createResource to refetch
21
- },
22
- // onError
23
- () => {
24
- refetch(); // Force createResource to refetch
25
- },
26
- // onPending
27
- () => {
28
- refetch(); // Force createResource to refetch
29
- },
30
- );
31
- });
32
-
33
- createEffect(() => {
34
- // reset error boundaries when error state changes
35
- resource.error ?? resource();
36
- resetErrorBoundaries();
37
- });
38
-
39
- onCleanup(() => fx.dispose());
40
-
41
- return resource;
42
- }
43
-
44
- /**
45
- * Internal helper that wraps a getter function in a PicoFlow node and converts it to a SolidJS resource.
46
- * @internal
47
- */
48
- function fromGetter<T>(getter: (t: FlowTracker) => NotPromise<T>): Resource<T> {
49
- const derivation = new ValueSyncNode<T>((t) => {
50
- return getter(t);
51
- });
52
-
53
- return fromNode(derivation);
54
- }
55
-
56
- /**
57
- * Converts a PicoFlow observable or getter function into a SolidJS resource.
58
- *
59
- * @param flow - The FlowObservable or getter function to convert.
60
- * @returns A SolidJS Resource that wraps the value or computation.
61
- *
62
- * @remarks
63
- * This function bridges PicoFlow's reactive system with SolidJS, allowing you to use
64
- * PicoFlow primitives and computations within Solid components. All conversions return a
65
- * SolidJS Resource, which can handle both synchronous and asynchronous values seamlessly.
66
- *
67
- * The conversion works with:
68
- * - **FlowObservable**: Any PicoFlow reactive primitive (e.g., from `state()`, `derivation()`, `stateAsync()`, `derivationAsync()`)
69
- * - **Getter functions**: Computation functions that use a FlowTracker to access reactive values
70
- *
71
- * The created Resource automatically subscribes to the PicoFlow observables and updates
72
- * when their values change. The subscription is properly cleaned up when the Solid
73
- * component unmounts.
74
- *
75
- * @example
76
- * ```typescript
77
- * import { from } from 'picoflow/solid';
78
- * import { state, derivation } from 'picoflow';
79
- *
80
- * // Convert a PicoFlow state to a Solid resource
81
- * const $count = state(0);
82
- * const solidCount = from($count);
83
- *
84
- * // Use in a Solid component
85
- * function Counter() {
86
- * return <div>Count: {solidCount()}</div>;
87
- * }
88
- *
89
- * // Or convert a computation function
90
- * const solidDerived = from((t) => {
91
- * return $count.get(t) * 2;
92
- * });
93
- * ```
94
- *
95
- * @public
96
- */
97
- export function from<T>(flow: FlowObservable<T>): Resource<T>;
98
- export function from<T>(flow: (t: FlowTracker) => NotPromise<T>): Resource<T>;
99
- export function from<T>(flow: FlowObservable<T> | ((t: FlowTracker) => NotPromise<T>)): Resource<T> {
100
- if (flow instanceof ValueAsyncNode || flow instanceof ValueSyncNode) {
101
- return fromNode(flow);
102
- }
103
-
104
- if (typeof flow === "function") {
105
- return fromGetter(flow);
106
- }
107
-
108
- throw new Error("Invalid flow type");
109
- }
package/src/index.ts DELETED
@@ -1,2 +0,0 @@
1
- export * from "./api";
2
- export * from "./converters";