@ersbeth/picoflow 2.3.1 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/README.md +37 -12
  2. package/SKILL.md +130 -16
  3. package/dist/index.d.ts +767 -0
  4. package/dist/index.js +544 -0
  5. package/dist/inspect.d.ts +252 -0
  6. package/dist/inspect.js +300 -0
  7. package/dist/shared.d.ts +361 -0
  8. package/dist/shared.js +1496 -0
  9. package/dist/shared2.d.ts +93 -0
  10. package/dist/shared2.js +59 -0
  11. package/dist/shared3.d.ts +54 -0
  12. package/dist/shared3.js +17 -0
  13. package/dist/{types/converters/solid.d.ts → solid.d.ts} +10 -8
  14. package/dist/solid.js +63 -0
  15. package/package.json +38 -34
  16. package/dist/picoflow.js +0 -1283
  17. package/dist/types/api/base/flowConfig.d.ts +0 -17
  18. package/dist/types/api/base/flowDisposable.d.ts +0 -40
  19. package/dist/types/api/base/flowErrors.d.ts +0 -1
  20. package/dist/types/api/base/flowObservable.d.ts +0 -26
  21. package/dist/types/api/base/flowPrimitiveOptions.d.ts +0 -14
  22. package/dist/types/api/base/flowSubscribable.d.ts +0 -78
  23. package/dist/types/api/base/flowTracker.d.ts +0 -7
  24. package/dist/types/api/base/index.d.ts +0 -7
  25. package/dist/types/api/index.d.ts +0 -2
  26. package/dist/types/api/nodes/async/flowConstantAsync.d.ts +0 -32
  27. package/dist/types/api/nodes/async/flowDerivationAsync.d.ts +0 -37
  28. package/dist/types/api/nodes/async/flowStateAsync.d.ts +0 -42
  29. package/dist/types/api/nodes/async/flowWritableDerivationAsync.d.ts +0 -31
  30. package/dist/types/api/nodes/async/index.d.ts +0 -4
  31. package/dist/types/api/nodes/collections/flowArray.d.ts +0 -138
  32. package/dist/types/api/nodes/collections/flowMap.d.ts +0 -100
  33. package/dist/types/api/nodes/collections/index.d.ts +0 -2
  34. package/dist/types/api/nodes/flowEffect.d.ts +0 -28
  35. package/dist/types/api/nodes/flowSignal.d.ts +0 -26
  36. package/dist/types/api/nodes/flowValue.d.ts +0 -35
  37. package/dist/types/api/nodes/index.d.ts +0 -7
  38. package/dist/types/api/nodes/sync/flowConstant.d.ts +0 -30
  39. package/dist/types/api/nodes/sync/flowDerivation.d.ts +0 -37
  40. package/dist/types/api/nodes/sync/flowState.d.ts +0 -40
  41. package/dist/types/api/nodes/sync/flowWritableDerivation.d.ts +0 -29
  42. package/dist/types/api/nodes/sync/index.d.ts +0 -4
  43. package/dist/types/api/nodes/utils.d.ts +0 -22
  44. package/dist/types/base/dependenciesRegistry.d.ts +0 -1
  45. package/dist/types/base/dependentsRegistry.d.ts +0 -1
  46. package/dist/types/base/disposable.d.ts +0 -15
  47. package/dist/types/base/errors.d.ts +0 -31
  48. package/dist/types/base/executionStack.d.ts +0 -31
  49. package/dist/types/base/index.d.ts +0 -8
  50. package/dist/types/base/node.d.ts +0 -27
  51. package/dist/types/base/observable.d.ts +0 -34
  52. package/dist/types/base/observer.d.ts +0 -33
  53. package/dist/types/converters/index.d.ts +0 -1
  54. package/dist/types/index.d.ts +0 -2
  55. package/dist/types/nodes/actionNode.d.ts +0 -1
  56. package/dist/types/nodes/arrayNode.d.ts +0 -1
  57. package/dist/types/nodes/effectNode.d.ts +0 -1
  58. package/dist/types/nodes/index.d.ts +0 -8
  59. package/dist/types/nodes/mapNode.d.ts +0 -1
  60. package/dist/types/nodes/signalNode.d.ts +0 -1
  61. package/dist/types/nodes/valueAsyncNode.d.ts +0 -1
  62. package/dist/types/nodes/valueNode.d.ts +0 -1
  63. package/dist/types/nodes/valueSyncNode.d.ts +0 -1
  64. package/dist/types/schedulers/asyncResolver.d.ts +0 -1
  65. package/dist/types/schedulers/asyncScheduler.d.ts +0 -1
  66. package/dist/types/schedulers/index.d.ts +0 -4
  67. package/dist/types/schedulers/pendingError.d.ts +0 -1
  68. package/dist/types/schedulers/scheduler.d.ts +0 -1
  69. package/dist/types/schedulers/syncResolver.d.ts +0 -1
  70. package/dist/types/schedulers/syncScheduler.d.ts +0 -1
@@ -0,0 +1,361 @@
1
+ //#region src/core/api/base/flowDisposable.d.ts
2
+ /**
3
+ * Contract for resources that can be explicitly released to prevent memory leaks.
4
+ *
5
+ * All reactive primitives in PicoFlow implement this interface, allowing manual cleanup of subscriptions
6
+ * and dependencies. Once disposed, the resource cannot be reused: reads and mutations throw, while
7
+ * `dispose()` itself is idempotent.
8
+ * Call `dispose()` when you no longer need a reactive primitive to free its resources.
9
+ *
10
+ * To ask whether something has been released, read its `status` — `"disposed"` on a value, signal or
11
+ * collection, and on the effect returned by `subscribe()`. There is no separate `disposed` flag: one
12
+ * piece of state with two spellings is what A1-L8 removed. `status` is declared by those interfaces
13
+ * rather than by this one, which every disposable implements — including `FlowTracker`, which has no
14
+ * status to report.
15
+ *
16
+ * Extends the standard `Disposable` protocol, so every primitive works with `using` (A2-ARCH-2).
17
+ * Note that this covers the primitives, not everything in the library that can be released: the
18
+ * handle returned by `enableTrace()` has a `dispose()` but does not implement the protocol, so
19
+ * `isDisposable()` accepts it while `using` does not.
20
+ *
21
+ * @public
22
+ */
23
+ interface FlowDisposable extends Disposable {
24
+ /**
25
+ * Releases all resources held by this disposable object.
26
+ *
27
+ * Cleans up all subscriptions, dependencies, and internal state. After calling this method, the
28
+ * resource enters a disposed state and cannot be reused: subsequent reads and mutations throw,
29
+ * and its `status` reads `"disposed"`. Disposal itself is idempotent — calling this a second
30
+ * time is a no-op — so a teardown path needs no guard. This method should be called when you no
31
+ * longer need the reactive primitive, to prevent memory leaks.
32
+ *
33
+ * Primitives also implement the standard `Disposable` protocol, so a primitive whose lifetime
34
+ * matches a block can be declared with `using` and released automatically on exit.
35
+ */
36
+ dispose(): void;
37
+ }
38
+ /**
39
+ * Type guard to check if an object implements the FlowDisposable interface.
40
+ *
41
+ * Useful for conditionally disposing objects that may or may not be disposable,
42
+ * such as when cleaning up mixed collections of values. Returns true if the object
43
+ * has a `dispose` method, providing type-safe access to disposal functionality.
44
+ *
45
+ * @param obj - The object to check
46
+ * @returns True if the object implements FlowDisposable, false otherwise
47
+ *
48
+ * @public
49
+ */
50
+ declare function isDisposable(obj: unknown): obj is FlowDisposable;
51
+ //#endregion
52
+ //#region src/core/base/observer.d.ts
53
+ /**
54
+ * Lifecycle of an observer: idle (has run, nothing pending), queued (a dependency changed and the
55
+ * next flush will run it), or disposed (released).
56
+ *
57
+ * Deliberately distinct from {@link ObservableStatus} rather than shared with it: `resolved`,
58
+ * `pending`, `error` and `dirty` describe the state of a *computed value*, and an effect has no
59
+ * value — reusing them would name states that do not exist here (A2-ARCH-11).
60
+ *
61
+ * @public
62
+ */
63
+ type ObserverStatus = "idle" | "queued" | "disposed";
64
+ //#endregion
65
+ //#region src/core/base/observable.d.ts
66
+ /**
67
+ * Status of an observable: resolved (has value), pending (async in progress), error (failed), dirty
68
+ * (needs recomputation), or disposed (released — the getter reports this instead of throwing, so a
69
+ * debugger or a `console.log` can inspect a released primitive, A2-ARCH-2).
70
+ *
71
+ * `disposed` is never stored in `_status`; it is derived by the `status` getter from the disposal
72
+ * flag, so every read path that guards on disposal before switching on the status cannot observe it.
73
+ */
74
+ type ObservableStatus = "resolved" | "pending" | "error" | "dirty" | "disposed";
75
+ //#endregion
76
+ //#region src/core/api/nodes/flowEffect.d.ts
77
+ /**
78
+ * Options accepted when creating an effect.
79
+ *
80
+ * Deliberately not `FlowPrimitiveOptions`: `equals` and `eager` describe how a *value* is computed
81
+ * and compared, and an effect has no value — offering them here would name settings that do nothing.
82
+ *
83
+ * @public
84
+ */
85
+ interface FlowEffectOptions {
86
+ /**
87
+ * Name for this effect, used wherever it has to be identified: the disposed-effect error, and
88
+ * introspection dumps, where an unnamed effect can only be labelled `effect#12` (#50).
89
+ *
90
+ * An effect is the node this matters most for. A value primitive can often be recognised from
91
+ * its value, while every effect looks alike from the outside — so naming the ones an
92
+ * application keeps for its lifetime is what makes a dump readable.
93
+ */
94
+ name?: string;
95
+ }
96
+ /**
97
+ * Handle to a reactive effect that automatically tracks dependencies and re-executes when they change.
98
+ *
99
+ * Effects run immediately upon creation and then reactively respond to changes in any reactive values
100
+ * accessed during execution. Call `dispose()` to stop the effect and clean up its subscriptions.
101
+ *
102
+ * @public
103
+ */
104
+ interface FlowEffect extends FlowDisposable {
105
+ /**
106
+ * Reports where this effect stands: `"idle"` once it has run with nothing pending, `"queued"`
107
+ * between a dependency change and the flush that re-runs it, or `"disposed"` once released.
108
+ *
109
+ * Reading it never throws, so it is safe from a debugger or a `console.log` on a disposed
110
+ * effect. Note that writes are flushed in a later task, so an effect observed immediately
111
+ * after a dependency write reads `"queued"`, not `"idle"` (A2-ARCH-11).
112
+ */
113
+ get status(): ObserverStatus;
114
+ }
115
+ /**
116
+ * Creates a reactive effect that runs immediately and automatically re-runs when dependencies change.
117
+ *
118
+ * The effect function tracks any reactive values accessed and subscribes to their changes.
119
+ * When any tracked value changes, the effect re-executes with the new values.
120
+ * Optional callbacks handle errors and pending async states.
121
+ *
122
+ * @param data - Function that accesses reactive dependencies and returns data
123
+ * @param onData - Callback invoked with the computed data on each execution
124
+ * @param onError - Optional callback for handling errors during execution
125
+ * @param onPending - Optional callback invoked when async dependencies are pending
126
+ * @param options - Optional settings; `name` identifies the effect in errors and inspection dumps
127
+ * @returns A FlowEffect handle with a `dispose()` method to stop the effect
128
+ *
129
+ * @public
130
+ */
131
+ declare function subscribe<T>(data: FlowDataTracker<T>, onData: FlowOnDataListener<T>, onError?: FlowOnErrorListener, onPending?: FlowOnPendingListener, options?: FlowEffectOptions): FlowEffect;
132
+ //#endregion
133
+ //#region src/core/api/base/flowTracker.d.ts
134
+ /**
135
+ * The brand that makes {@link FlowTracker} nominal. Declared, never defined: it has no runtime
136
+ * existence, and no value can be produced for it outside this library (A2-TYPE-3).
137
+ *
138
+ * This symbol must SHIP in the declarations even though it is not part of the documented API. Tag it
139
+ * for internal-stripping and `stripInternal` deletes this line while leaving the `[tracker]`
140
+ * reference in {@link FlowTracker} behind, so every consumer gets a `TS2304: Cannot find name`
141
+ * error and the whole public surface fails to type-check. `@hidden` keeps it out of the
142
+ * generated documentation without touching the emit, which is all that was wanted.
143
+ *
144
+ * Note the wording above avoids spelling that tag out: `stripInternal` matches the tag anywhere in a
145
+ * doc comment, so even prose explaining its absence is enough to trigger it.
146
+ *
147
+ * @hidden
148
+ */
149
+ declare const tracker: unique symbol;
150
+ /**
151
+ * Contract for reactive computations that track dependencies and react to changes in the reactivity graph.
152
+ *
153
+ * Opaque: a tracker is obtained, never constructed. The only one that exists is the `t` passed to a
154
+ * derivation, computation or effect callback, and passing it to `get(t)` is what registers the
155
+ * dependency edge. An opaque brand makes that a type-level fact rather than a convention — an object
156
+ * that merely looks like a tracker is rejected, where this interface was previously empty and so
157
+ * accepted anything disposable (A2-TYPE-3).
158
+ *
159
+ * This is a compile-time closure only. The runtime still calls whatever `registerDependency` it is
160
+ * handed, so a duck-typed tracker keeps working as A2-RT-3 measured; it simply no longer type-checks.
161
+ *
162
+ * @public
163
+ */
164
+ interface FlowTracker extends FlowDisposable {
165
+ /**
166
+ * The brand itself. Carries no information — its presence is the whole point, and the prose above
167
+ * is what a reader needs — so it is kept out of the generated reference rather than rendering as
168
+ * an undescribed property a consumer might try to supply.
169
+ *
170
+ * @hidden
171
+ */
172
+ readonly [tracker]: true;
173
+ }
174
+ //#endregion
175
+ //#region src/core/api/base/flowSubscribable.d.ts
176
+ /**
177
+ * Function that tracks reactive dependencies and returns data.
178
+ *
179
+ * This function is called during effect execution with a tracker parameter that automatically
180
+ * records any reactive values accessed. The tracker enables automatic dependency tracking without
181
+ * explicit subscriptions. The returned data is passed to the `onData` callback.
182
+ *
183
+ * @param t - Tracker object that records dependencies when reactive values are accessed
184
+ * @returns The computed data of type T
185
+ *
186
+ * @public
187
+ */
188
+ type FlowDataTracker<T> = (t: FlowTracker) => T;
189
+ /**
190
+ * Callback invoked when new data is available.
191
+ *
192
+ * This callback runs each time the effect executes successfully, receiving the data returned
193
+ * by the tracker function. It's called immediately on effect creation and then on every reactive
194
+ * re-execution. Use this callback to perform side effects with the computed data.
195
+ *
196
+ * @param data - The computed data from the tracker function
197
+ * @returns Always returns undefined (callbacks are for side effects)
198
+ *
199
+ * @public
200
+ */
201
+ type FlowOnDataListener<T> = (data: T) => void;
202
+ /**
203
+ * Callback invoked when an error occurs during effect execution.
204
+ *
205
+ * If provided, this callback handles any errors thrown by the tracker function (except PendingError).
206
+ * Without this callback, errors propagate and may crash the application. Use this for error logging,
207
+ * recovery, or user feedback. The effect remains active and will retry on the next reactive trigger.
208
+ *
209
+ * @param error - The error that occurred, always normalized to an Error instance
210
+ * @returns Always returns undefined (callbacks are for side effects)
211
+ *
212
+ * @public
213
+ */
214
+ type FlowOnErrorListener = (error: Error) => void;
215
+ /**
216
+ * Callback invoked when an async computation is pending.
217
+ *
218
+ * This callback is triggered when the tracker function throws a PendingError, indicating that
219
+ * async dependencies are still resolving. Use this to show loading states or pending indicators.
220
+ * The effect will automatically re-execute once the async values settle.
221
+ *
222
+ * @returns Always returns undefined (callbacks are for side effects)
223
+ *
224
+ * @public
225
+ */
226
+ type FlowOnPendingListener = () => void;
227
+ /**
228
+ * Contract for observables that can be subscribed to with lifecycle callbacks.
229
+ *
230
+ * This interface enables imperative subscription to reactive values, allowing manual control over
231
+ * when effects run. The subscribe method returns a disposal function to stop the subscription.
232
+ * Useful for integrating with non-reactive code or frameworks that manage subscriptions differently.
233
+ *
234
+ * @public
235
+ */
236
+ interface FlowSubscribable<T> {
237
+ /**
238
+ * Subscribes to this observable with lifecycle callbacks.
239
+ *
240
+ * Creates an active subscription that executes immediately and then re-executes whenever
241
+ * the observable's dependencies change. The subscription remains active until the returned
242
+ * disposal function is called. The `onData` callback receives the computed value, while
243
+ * `onError` handles errors and `onPending` signals async operations in progress.
244
+ *
245
+ * @param onData - Callback invoked with the computed data on each execution
246
+ * @param onError - Optional callback for handling errors during execution
247
+ * @param onPending - Optional callback invoked when async dependencies are pending
248
+ * @param options - Optional settings; `name` identifies the resulting effect in errors and
249
+ * inspection dumps
250
+ * @returns A function to dispose the subscription and stop receiving updates
251
+ */
252
+ subscribe(onData: FlowOnDataListener<T>, onError?: FlowOnErrorListener, onPending?: FlowOnPendingListener, options?: FlowEffectOptions): FlowEffect;
253
+ }
254
+ //#endregion
255
+ //#region src/core/api/base/flowObservable.d.ts
256
+ /**
257
+ * Contract for reactive primitives that emit changes and notify their dependents in the reactivity graph.
258
+ * @public
259
+ */
260
+ interface FlowObservable<T> extends FlowDisposable, FlowSubscribable<T> {
261
+ /**
262
+ * Reports where this primitive stands: `"resolved"` when it holds a value, `"pending"` while an
263
+ * async computation is in flight, `"error"` when the last computation threw, `"dirty"` when it
264
+ * needs recomputing, or `"disposed"` once released.
265
+ *
266
+ * Reading it never throws, so it is safe from a debugger or a `console.log` on a disposed
267
+ * primitive — and it is how you ask whether something has been released (A2-ARCH-2, A1-L8).
268
+ * A value read alongside a status of `"pending"` or `"dirty"` is a stale cache, not the
269
+ * current value.
270
+ */
271
+ get status(): ObservableStatus;
272
+ /**
273
+ * Establishes a reactive dependency without reading the value.
274
+ *
275
+ * Registers this observable as a dependency of the given tracker, allowing it to be notified
276
+ * when changes occur. This enables dependency tracking without accessing the actual value.
277
+ *
278
+ * @param tracker - Tracker that records this observable as a dependency
279
+ */
280
+ watch(tracker: FlowTracker): void;
281
+ }
282
+ //#endregion
283
+ //#region src/core/api/nodes/flowValue.d.ts
284
+ /**
285
+ * A synchronous, passive snapshot of a {@link FlowValue}, discriminated on its `status`
286
+ * (A2-ARCH-10, #80).
287
+ *
288
+ * `data` exists only when the status is `"resolved"`: in any other state the cached value is stale or
289
+ * absent and reading it without its status would be misleading, so the snapshot carries the status
290
+ * alone — plus the `error` when the last computation threw. Narrow on `status` to reach `data`:
291
+ *
292
+ * ```ts
293
+ * const snapshot = $user.value;
294
+ * if (snapshot.status === "resolved") render(snapshot.data);
295
+ * ```
296
+ *
297
+ * @public
298
+ */
299
+ type FlowSnapshot<T> = {
300
+ status: "resolved";
301
+ data: T;
302
+ } | {
303
+ status: "error";
304
+ error: Error;
305
+ } | {
306
+ status: Exclude<ObservableStatus, "resolved" | "error">;
307
+ };
308
+ /**
309
+ * Base interface for reactive values that can be read synchronously or asynchronously.
310
+ *
311
+ * FlowValue extends FlowObservable with methods to access the current value. Use `get()` to read
312
+ * the value reactively (establishing a dependency), or `pick()` to read it non-reactively. All
313
+ * value-based primitives (state, derivation, constant, and their async variants) implement this
314
+ * interface, providing a consistent API for value access across the reactive system.
315
+ *
316
+ * @public
317
+ */
318
+ interface FlowValue<T> extends FlowObservable<T> {
319
+ /**
320
+ * Gets the current value and establishes a reactive dependency.
321
+ *
322
+ * When called from within a reactive computation, this method registers the value as a dependency,
323
+ * ensuring the computation re-executes when the value changes. The value is computed on first access
324
+ * (if lazy) and then cached. For async values, throws PendingError while the value is resolving.
325
+ *
326
+ * @param tracker - Tracker that records this value as a dependency
327
+ * @returns The current value
328
+ */
329
+ get(tracker: FlowTracker): T;
330
+ /**
331
+ * Asynchronously gets the current value without establishing a reactive dependency.
332
+ *
333
+ * This method reads the value non-reactively, meaning it won't trigger re-execution of the calling
334
+ * computation when the value changes. The value is computed on first access (if lazy) and then cached.
335
+ * For async values, the promise resolves once the value is available.
336
+ *
337
+ * @returns Promise that resolves with the current value
338
+ */
339
+ pick(): Promise<T>;
340
+ /**
341
+ * Synchronous, passive snapshot of this value: its current {@link FlowObservable.status}, with
342
+ * `data` only when resolved and `error` only when the last computation threw.
343
+ *
344
+ * Reading it never computes a lazy derivation, never throws — not even on a disposed primitive —
345
+ * and never registers a dependency. It is the read meant for an event handler, a debugger or a
346
+ * dev panel that wants to look without taking part in the graph; use {@link get} to depend on the
347
+ * value and {@link pick} to wait for it (A2-ARCH-10, #80).
348
+ */
349
+ get value(): FlowSnapshot<T>;
350
+ /**
351
+ * The last resolved value, or `undefined` if none was ever computed — regardless of the current
352
+ * status. Like {@link value}, it never computes, throws or tracks.
353
+ *
354
+ * This is deliberately a stale read: while the status is `"pending"` or `"dirty"` it still
355
+ * returns the previous value, which is what a stale-while-revalidate display wants. Check
356
+ * {@link FlowObservable.status} (or read {@link value}) whenever freshness matters (A2-ARCH-10, #80).
357
+ */
358
+ get latest(): T | undefined;
359
+ }
360
+ //#endregion
361
+ export { isDisposable as _, FlowOnDataListener as a, FlowSubscribable as c, FlowEffect as d, FlowEffectOptions as f, FlowDisposable as g, ObserverStatus as h, FlowDataTracker as i, FlowTracker as l, ObservableStatus as m, FlowValue as n, FlowOnErrorListener as o, subscribe as p, FlowObservable as r, FlowOnPendingListener as s, FlowSnapshot as t, tracker as u };