@ersbeth/picoflow 0.2.0 → 0.2.2

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.
@@ -0,0 +1,49 @@
1
+ <!-- Do not edit this file. It is automatically generated by API Documenter. -->
2
+
3
+ [Home](./index.md) &gt; [@ersbeth/picoflow](./picoflow.md) &gt; [FlowDerivationAsync](./picoflow.flowderivationasync.md) &gt; [(constructor)](./picoflow.flowderivationasync._constructor_.md)
4
+
5
+ ## FlowDerivationAsync.(constructor)
6
+
7
+ Creates a new FlowDerivation.
8
+
9
+ **Signature:**
10
+
11
+ ```typescript
12
+ constructor(compute: (get: FlowGetter, watch: FlowWatcher) => Promise<T>);
13
+ ```
14
+
15
+ ## Parameters
16
+
17
+ <table><thead><tr><th>
18
+
19
+ Parameter
20
+
21
+
22
+ </th><th>
23
+
24
+ Type
25
+
26
+
27
+ </th><th>
28
+
29
+ Description
30
+
31
+
32
+ </th></tr></thead>
33
+ <tbody><tr><td>
34
+
35
+ compute
36
+
37
+
38
+ </td><td>
39
+
40
+ (get: [FlowGetter](./picoflow.flowgetter.md)<!-- -->, watch: [FlowWatcher](./picoflow.flowwatcher.md)<!-- -->) =&gt; Promise&lt;T&gt;
41
+
42
+
43
+ </td><td>
44
+
45
+ A function that computes the derived value. It is provided with two parameters: a getter and a watcher that respect dependency tracking.
46
+
47
+
48
+ </td></tr>
49
+ </tbody></table>
@@ -0,0 +1,23 @@
1
+ <!-- Do not edit this file. It is automatically generated by API Documenter. -->
2
+
3
+ [Home](./index.md) &gt; [@ersbeth/picoflow](./picoflow.md) &gt; [FlowDerivationAsync](./picoflow.flowderivationasync.md) &gt; [get](./picoflow.flowderivationasync.get.md)
4
+
5
+ ## FlowDerivationAsync.get() method
6
+
7
+ Retrieves the current resource value.
8
+
9
+ **Signature:**
10
+
11
+ ```typescript
12
+ get(): Promise<T>;
13
+ ```
14
+ **Returns:**
15
+
16
+ Promise&lt;T&gt;
17
+
18
+ The current value, or undefined if the resource has not been fetched yet.
19
+
20
+ ## Exceptions
21
+
22
+ Error if the resource is disposed.
23
+
@@ -0,0 +1,86 @@
1
+ <!-- Do not edit this file. It is automatically generated by API Documenter. -->
2
+
3
+ [Home](./index.md) &gt; [@ersbeth/picoflow](./picoflow.md) &gt; [FlowDerivationAsync](./picoflow.flowderivationasync.md)
4
+
5
+ ## FlowDerivationAsync class
6
+
7
+ Represents a reactive resource that asynchronously fetches its value.
8
+
9
+ **Signature:**
10
+
11
+ ```typescript
12
+ export declare class FlowDerivationAsync<T> extends FlowDerivation<Promise<T>>
13
+ ```
14
+ **Extends:** [FlowDerivation](./picoflow.flowderivation.md)<!-- -->&lt;Promise&lt;T&gt;&gt;
15
+
16
+ ## Remarks
17
+
18
+ A FlowResource extends FlowObservable and encapsulates an asynchronous fetch function. It is used to retrieve and update its value asynchronously. When the fetch is executed, if the new value differs from the current value, the resource is updated and its subscribers are notified.
19
+
20
+ ## Constructors
21
+
22
+ <table><thead><tr><th>
23
+
24
+ Constructor
25
+
26
+
27
+ </th><th>
28
+
29
+ Modifiers
30
+
31
+
32
+ </th><th>
33
+
34
+ Description
35
+
36
+
37
+ </th></tr></thead>
38
+ <tbody><tr><td>
39
+
40
+ [(constructor)(compute)](./picoflow.flowderivationasync._constructor_.md)
41
+
42
+
43
+ </td><td>
44
+
45
+
46
+ </td><td>
47
+
48
+ Creates a new FlowDerivation.
49
+
50
+
51
+ </td></tr>
52
+ </tbody></table>
53
+
54
+ ## Methods
55
+
56
+ <table><thead><tr><th>
57
+
58
+ Method
59
+
60
+
61
+ </th><th>
62
+
63
+ Modifiers
64
+
65
+
66
+ </th><th>
67
+
68
+ Description
69
+
70
+
71
+ </th></tr></thead>
72
+ <tbody><tr><td>
73
+
74
+ [get()](./picoflow.flowderivationasync.get.md)
75
+
76
+
77
+ </td><td>
78
+
79
+
80
+ </td><td>
81
+
82
+ Retrieves the current resource value.
83
+
84
+
85
+ </td></tr>
86
+ </tbody></table>
@@ -51,6 +51,17 @@ Represents a reactive and immutable constant value computed lazily upon first ac
51
51
  Represents a reactive derivation whose value is computed based on other reactive signals.
52
52
 
53
53
 
54
+ </td></tr>
55
+ <tr><td>
56
+
57
+ [FlowDerivationAsync](./picoflow.flowderivationasync.md)
58
+
59
+
60
+ </td><td>
61
+
62
+ Represents a reactive resource that asynchronously fetches its value.
63
+
64
+
54
65
  </td></tr>
55
66
  <tr><td>
56
67
 
@@ -74,6 +74,12 @@ export class FlowDerivation<T> extends FlowObservable<T> {
74
74
  get(): T;
75
75
  }
76
76
 
77
+ // @public
78
+ export class FlowDerivationAsync<T> extends FlowDerivation<Promise<T>> {
79
+ constructor(compute: (get: FlowGetter, watch: FlowWatcher) => Promise<T>);
80
+ get(): Promise<T>;
81
+ }
82
+
77
83
  // @public
78
84
  export interface FlowDisposable {
79
85
  dispose(options?: {
package/dist/picoflow.js CHANGED
@@ -1,4 +1,4 @@
1
- class FlowSignal {
1
+ let FlowSignal$1 = class FlowSignal {
2
2
  /**
3
3
  * Triggers the FlowSignal.
4
4
  * Notifies all registered listeners and schedules execution of associated effects.
@@ -93,9 +93,9 @@ class FlowSignal {
93
93
  _unregisterEffect(effect) {
94
94
  this._effects.delete(effect);
95
95
  }
96
- }
96
+ };
97
97
 
98
- class FlowEffect {
98
+ let FlowEffect$1 = class FlowEffect {
99
99
  /**
100
100
  * Creates a new FlowEffect.
101
101
  *
@@ -169,9 +169,9 @@ class FlowEffect {
169
169
  this._dependencies.delete(dependency);
170
170
  dependency._unregisterEffect(this);
171
171
  }
172
- }
172
+ };
173
173
 
174
- class FlowObservable extends FlowSignal {
174
+ let FlowObservable$1 = class FlowObservable extends FlowSignal$1 {
175
175
  /* INTERNAL -------------------------------------------*/
176
176
  /*@internal*/
177
177
  _value;
@@ -187,14 +187,14 @@ class FlowObservable extends FlowSignal {
187
187
  * @returns A disposer function to cancel the subscription.
188
188
  */
189
189
  subscribe(listener) {
190
- const effect = new FlowEffect((get) => {
190
+ const effect = new FlowEffect$1((get) => {
191
191
  listener(get(this));
192
192
  });
193
193
  return () => effect.dispose();
194
194
  }
195
- }
195
+ };
196
196
 
197
- class FlowConstant extends FlowObservable {
197
+ class FlowConstant extends FlowObservable$1 {
198
198
  /**
199
199
  * Creates a new FlowConstant instance.
200
200
  *
@@ -264,6 +264,274 @@ class FlowState extends FlowConstant {
264
264
  }
265
265
  }
266
266
 
267
+ let FlowDerivation$1 = class FlowDerivation extends FlowObservable$1 {
268
+ /**
269
+ * Creates a new FlowDerivation.
270
+ * @param compute - A function that computes the derived value. It is provided with two parameters:
271
+ * a getter and a watcher that respect dependency tracking.
272
+ * @public
273
+ */
274
+ constructor(compute) {
275
+ super();
276
+ this._initEager(compute);
277
+ }
278
+ /**
279
+ * Gets the current derived value.
280
+ * @returns The current computed value.
281
+ * @remarks
282
+ * This method lazily initializes and updates the derivation if it is marked as dirty. It throws an error
283
+ * if the derivation has been disposed.
284
+ * @public
285
+ */
286
+ get() {
287
+ if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
288
+ this._initLazy();
289
+ this._compute();
290
+ return this._value;
291
+ }
292
+ /* INTERNAL --------------------------------------------------------- */
293
+ _initialized = false;
294
+ _dirty = false;
295
+ _trackedGet = (observable) => observable._getFrom(this);
296
+ _trackedWatch = (signal) => signal._watchFrom(this);
297
+ _untrackedGet = (observable) => observable.get();
298
+ _untrackedWatch = (signal) => signal._watch();
299
+ _trackedCompute;
300
+ _untrackedCompute;
301
+ _initEager(compute) {
302
+ this._trackedCompute = () => compute(this._trackedGet, this._trackedWatch);
303
+ this._untrackedCompute = () => compute(this._untrackedGet, this._untrackedWatch);
304
+ }
305
+ _initLazy() {
306
+ if (!this._initialized) {
307
+ this._value = this._trackedCompute();
308
+ this._initialized = true;
309
+ }
310
+ }
311
+ /* @internal */
312
+ _compute() {
313
+ if (this._dirty) {
314
+ const dependencies = [...this._dependencies];
315
+ this._dependencies.clear();
316
+ this._value = this._trackedCompute();
317
+ const dependenciesToRemove = dependencies.filter(
318
+ (dependency) => !this._dependencies.has(dependency)
319
+ );
320
+ dependenciesToRemove.forEach(
321
+ (dependency) => dependency._unregisterDependency(this)
322
+ );
323
+ this._dirty = false;
324
+ }
325
+ }
326
+ /* @internal */
327
+ _notify() {
328
+ this._dirty = true;
329
+ super._notify();
330
+ }
331
+ /* @internal */
332
+ _watch() {
333
+ if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
334
+ this._initLazy();
335
+ this._compute();
336
+ }
337
+ };
338
+
339
+ class FlowSignal {
340
+ /**
341
+ * Triggers the FlowSignal.
342
+ * Notifies all registered listeners and schedules execution of associated effects.
343
+ * @throws If the FlowSignal has already been disposed.
344
+ * @public
345
+ */
346
+ trigger() {
347
+ if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
348
+ this._notify();
349
+ }
350
+ /**
351
+ * Disposes the FlowSignal.
352
+ * Cleans up all registered effects, listeners, and dependencies.
353
+ * Once disposed, further usage of the signal will throw an error.
354
+ * @throws If the FlowSignal is already disposed.
355
+ * @public
356
+ */
357
+ dispose(options) {
358
+ if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
359
+ if (options?.self) {
360
+ Array.from(this._effects).forEach(
361
+ (effect) => effect._unregisterDependency(this)
362
+ );
363
+ Array.from(this._listeners).forEach(
364
+ (listener) => listener._unregisterDependency(this)
365
+ );
366
+ } else {
367
+ Array.from(this._effects).forEach((effect) => effect.dispose());
368
+ Array.from(this._listeners).forEach(
369
+ (listener) => listener.dispose()
370
+ );
371
+ }
372
+ Array.from(this._dependencies).forEach((dependency) => {
373
+ this._unregisterDependency(dependency);
374
+ });
375
+ this._disposed = true;
376
+ }
377
+ /**
378
+ * Indicates whether the FlowSignal has been disposed.
379
+ * @remarks Once disposed, the signal should not be used.
380
+ * @public
381
+ */
382
+ get disposed() {
383
+ return this._disposed;
384
+ }
385
+ /* INTERNAL ------------------------------------------------------------- */
386
+ /*@internal*/
387
+ _disposed = false;
388
+ /*@internal*/
389
+ _dependencies = /* @__PURE__ */ new Set();
390
+ /*@internal*/
391
+ _listeners = /* @__PURE__ */ new Set();
392
+ /*@internal*/
393
+ _effects = /* @__PURE__ */ new Set();
394
+ /*@internal*/
395
+ _watch() {
396
+ if (this._disposed) throw new Error("[PicoFlow] Primitive is disposed");
397
+ }
398
+ /*@internal*/
399
+ _notify() {
400
+ this._listeners.forEach((listener) => listener._notify());
401
+ this._effects.forEach((effect) => effect._exec());
402
+ }
403
+ /*@internal*/
404
+ _watchFrom(listener) {
405
+ listener._registerDependency(this);
406
+ this._watch();
407
+ }
408
+ /*@internal*/
409
+ _registerDependency(dependency) {
410
+ this._dependencies.add(dependency);
411
+ dependency._registerListener(this);
412
+ }
413
+ /*@internal*/
414
+ _unregisterDependency(dependency) {
415
+ this._dependencies.delete(dependency);
416
+ dependency._unregisterListener(this);
417
+ }
418
+ /*@internal*/
419
+ _registerListener(signal) {
420
+ this._listeners.add(signal);
421
+ }
422
+ /*@internal*/
423
+ _unregisterListener(signal) {
424
+ this._listeners.delete(signal);
425
+ }
426
+ /*@internal*/
427
+ _registerEffect(effect) {
428
+ this._effects.add(effect);
429
+ }
430
+ /*@internal*/
431
+ _unregisterEffect(effect) {
432
+ this._effects.delete(effect);
433
+ }
434
+ }
435
+
436
+ class FlowEffect {
437
+ /**
438
+ * Creates a new FlowEffect.
439
+ *
440
+ * @param apply - A side-effect function that receives a getter and a watcher to
441
+ * access and register dependencies on reactive observables and signals.
442
+ *
443
+ * @remarks
444
+ * The provided function is executed immediately in a tracked mode to collect dependencies.
445
+ * On subsequent executions, it runs in an untracked mode.
446
+ *
447
+ * @public
448
+ */
449
+ constructor(apply) {
450
+ this._trackedExec = () => apply(this._trackedGet, this._trackedWatch);
451
+ this._untrackedExec = () => apply(this._untrackedGet, this._untrackedWatch);
452
+ this._exec();
453
+ }
454
+ /**
455
+ * Disposes the effect, unregistering all its tracked dependencies.
456
+ *
457
+ * @remarks
458
+ * Once disposed, the effect must no longer be used. Trying to dispose an effect
459
+ * that is already disposed will throw an error.
460
+ *
461
+ * @public
462
+ */
463
+ dispose() {
464
+ if (this._disposed) throw new Error("[PicoFlow] Effect is disposed");
465
+ Array.from(this._dependencies).forEach((dependency) => {
466
+ this._unregisterDependency(dependency);
467
+ });
468
+ this._disposed = true;
469
+ }
470
+ /**
471
+ * Indicates whether this effect has been disposed.
472
+ *
473
+ * @returns A boolean value that is true if the effect is disposed, false otherwise.
474
+ *
475
+ * @public
476
+ */
477
+ get disposed() {
478
+ return this._disposed;
479
+ }
480
+ /* INTERNAL ------------------------------------------------------------ */
481
+ _disposed = false;
482
+ _initialized = false;
483
+ _dependencies = /* @__PURE__ */ new Set();
484
+ _trackedGet = (observable) => observable._getFrom(this);
485
+ _trackedWatch = (signal) => signal._watchFrom(this);
486
+ _untrackedGet = (observable) => observable.get();
487
+ _untrackedWatch = (signal) => signal._watch();
488
+ _trackedExec;
489
+ _untrackedExec;
490
+ /*@internal*/
491
+ _exec() {
492
+ if (this._disposed)
493
+ throw new Error("[PicoFlow] Effect is disposed");
494
+ if (this._initialized) this._untrackedExec();
495
+ else {
496
+ this._trackedExec();
497
+ this._initialized = true;
498
+ }
499
+ }
500
+ /*@internal*/
501
+ _registerDependency(dependency) {
502
+ this._dependencies.add(dependency);
503
+ dependency._registerEffect(this);
504
+ }
505
+ /*@internal*/
506
+ _unregisterDependency(dependency) {
507
+ this._dependencies.delete(dependency);
508
+ dependency._unregisterEffect(this);
509
+ }
510
+ }
511
+
512
+ class FlowObservable extends FlowSignal {
513
+ /* INTERNAL -------------------------------------------*/
514
+ /*@internal*/
515
+ _value;
516
+ /*@internal*/
517
+ _getFrom(listener) {
518
+ listener._registerDependency(this);
519
+ return this.get();
520
+ }
521
+ /**
522
+ * Subscribes a listener function to changes of the observable.
523
+ * The listener is executed immediately with the current value and on subsequent updates.
524
+ * @param listener - A callback function that receives the new value.
525
+ * @returns A disposer function to cancel the subscription.
526
+ */
527
+ subscribe(listener) {
528
+ const effect = new FlowEffect((get) => {
529
+ listener(get(this));
530
+ });
531
+ return () => effect.dispose();
532
+ }
533
+ }
534
+
267
535
  class FlowDerivation extends FlowObservable {
268
536
  /**
269
537
  * Creates a new FlowDerivation.
@@ -328,6 +596,28 @@ class FlowDerivation extends FlowObservable {
328
596
  }
329
597
  }
330
598
 
599
+ class FlowDerivationAsync extends FlowDerivation {
600
+ /**
601
+ * Creates a new FlowDerivation.
602
+ * @param compute - A function that computes the derived value. It is provided with two parameters:
603
+ * a getter and a watcher that respect dependency tracking.
604
+ * @public
605
+ */
606
+ // biome-ignore lint/complexity/noUselessConstructor: <explanation>
607
+ constructor(compute) {
608
+ super(compute);
609
+ }
610
+ /**
611
+ * Retrieves the current resource value.
612
+ * @returns The current value, or undefined if the resource has not been fetched yet.
613
+ * @throws Error if the resource is disposed.
614
+ * @public
615
+ */
616
+ get() {
617
+ return super.get();
618
+ }
619
+ }
620
+
331
621
  function isDisposable(obj) {
332
622
  return obj !== null && obj !== void 0 && typeof obj.dispose === "function";
333
623
  }
@@ -393,7 +683,7 @@ class FlowMap extends FlowState {
393
683
  }
394
684
  }
395
685
 
396
- class FlowStream extends FlowObservable {
686
+ class FlowStream extends FlowObservable$1 {
397
687
  /**
398
688
  * Creates a new FlowStream.
399
689
  * @param updater - A function that receives a setter to update the stream's value.
@@ -437,7 +727,7 @@ class FlowStream extends FlowObservable {
437
727
  }
438
728
  }
439
729
 
440
- class FlowStreamAsync extends FlowObservable {
730
+ class FlowStreamAsync extends FlowObservable$1 {
441
731
  /**
442
732
  * Creates a new asynchronous FlowStream.
443
733
  * @param updater - A function that receives a setter to update the stream's value.
@@ -495,7 +785,7 @@ class FlowStreamAsync extends FlowObservable {
495
785
  }
496
786
  }
497
787
 
498
- class FlowResource extends FlowObservable {
788
+ class FlowResource extends FlowObservable$1 {
499
789
  /**
500
790
  * Creates a new FlowResource.
501
791
  * @param fetch - An asynchronous function that retrieves the resource's value.
@@ -536,7 +826,7 @@ class FlowResource extends FlowObservable {
536
826
  _fetch;
537
827
  }
538
828
 
539
- class FlowResourceAsync extends FlowObservable {
829
+ class FlowResourceAsync extends FlowObservable$1 {
540
830
  /**
541
831
  * Creates a new FlowResource.
542
832
  * @param fetch - An asynchronous function that retrieves the resource's value.
@@ -575,7 +865,7 @@ class FlowResourceAsync extends FlowObservable {
575
865
  _fetch;
576
866
  }
577
867
 
578
- class FlowArray extends FlowObservable {
868
+ class FlowArray extends FlowObservable$1 {
579
869
  /**
580
870
  * Last action performed on the FlowArray.
581
871
  * @public
@@ -742,7 +1032,7 @@ class FlowArray extends FlowObservable {
742
1032
  }
743
1033
 
744
1034
  function signal() {
745
- return new FlowSignal();
1035
+ return new FlowSignal$1();
746
1036
  }
747
1037
  function constant(value) {
748
1038
  return new FlowConstant(value);
@@ -763,10 +1053,10 @@ function streamAsync(updater) {
763
1053
  return new FlowStreamAsync(updater);
764
1054
  }
765
1055
  function derivation(fn) {
766
- return new FlowDerivation(fn);
1056
+ return new FlowDerivation$1(fn);
767
1057
  }
768
1058
  function effect(fn) {
769
- return new FlowEffect(fn);
1059
+ return new FlowEffect$1(fn);
770
1060
  }
771
1061
  function map(initial) {
772
1062
  return new FlowMap(
@@ -777,4 +1067,4 @@ function array(initial) {
777
1067
  return new FlowArray(initial);
778
1068
  }
779
1069
 
780
- export { array, constant, derivation, effect, isDisposable, map, resource, resourceAsync, signal, state, stream, streamAsync };
1070
+ export { FlowArray, FlowConstant, FlowDerivation$1 as FlowDerivation, FlowDerivationAsync, FlowEffect$1 as FlowEffect, FlowMap, FlowObservable$1 as FlowObservable, FlowResource, FlowResourceAsync, FlowSignal$1 as FlowSignal, FlowState, FlowStream, FlowStreamAsync, array, constant, derivation, effect, isDisposable, map, resource, resourceAsync, signal, state, stream, streamAsync };
@@ -1 +1 @@
1
- {"version":3,"file":"array.d.ts","sourceRoot":"","sources":["../../../src/advanced/array.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,KAAK,SAAS,EAAE,MAAM,UAAU,CAAC;AAI1D;;;GAGG;AACH,MAAM,MAAM,eAAe,CAAC,CAAC,IACvB;IACE,IAAI,EAAE,KAAK,CAAC;IACZ,KAAK,EAAE,CAAC,EAAE,CAAC;CACd,GACC;IACE,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,CAAC,CAAC;CACX,GACC;IACE,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,CAAC,CAAC;CACX,GACC;IACE,IAAI,EAAE,KAAK,CAAC;CACf,GACC;IACE,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,CAAC,CAAC;CACX,GACC;IACE,IAAI,EAAE,OAAO,CAAC;CACjB,GACC;IACE,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,CAAC,EAAE,CAAC;CACd,GACC;IACE,IAAI,EAAE,OAAO,CAAC;CACjB,CAAC;AAEN;;;GAGG;AACH,qBAAa,SAAS,CAAC,CAAC,CAAE,SAAQ,cAAc,CAAC,CAAC,EAAE,CAAC;IACjD;;;OAGG;IACH,WAAW,EAAE,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;IAE3C;;;;OAIG;gBACS,KAAK,GAAE,CAAC,EAAO;IAS3B;;;;OAIG;IACH,IAAI,MAAM,IAAI,MAAM,CAGnB;IAED;;;;OAIG;IACH,GAAG,IAAI,CAAC,EAAE;IAKV;;;;OAIG;IACH,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,IAAI;IAUrB;;;;;OAKG;IACH,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI;IAUrC;;;;OAIG;IACH,IAAI,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI;IAOnB;;;OAGG;IACH,GAAG,IAAI,IAAI;IAUX;;;;OAIG;IACH,OAAO,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI;IAOtB;;;OAGG;IACH,KAAK,IAAI,IAAI;IAUb;;;;;;OAMG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAC,EAAE,GAAG,IAAI;IAelE;;;OAGG;IACH,KAAK,IAAI,IAAI;IAWb;;;;OAIG;IACM,OAAO,CAAC,OAAO,CAAC,EAAE;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI;CAWtD"}
1
+ {"version":3,"file":"array.d.ts","sourceRoot":"","sources":["../../../src/advanced/array.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,KAAK,SAAS,EAAE,MAAM,UAAU,CAAC;AAI1D;;;GAGG;AACH,MAAM,MAAM,eAAe,CAAC,CAAC,IACvB;IACI,IAAI,EAAE,KAAK,CAAC;IACZ,KAAK,EAAE,CAAC,EAAE,CAAC;CACd,GACD;IACI,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,CAAC,CAAC;CACX,GACD;IACI,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,CAAC,CAAC;CACX,GACD;IACI,IAAI,EAAE,KAAK,CAAC;CACf,GACD;IACI,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,CAAC,CAAC;CACX,GACD;IACI,IAAI,EAAE,OAAO,CAAC;CACjB,GACD;IACI,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,CAAC,EAAE,CAAC;CACd,GACD;IACI,IAAI,EAAE,OAAO,CAAC;CACjB,CAAC;AAER;;;GAGG;AACH,qBAAa,SAAS,CAAC,CAAC,CAAE,SAAQ,cAAc,CAAC,CAAC,EAAE,CAAC;IACjD;;;OAGG;IACH,WAAW,EAAE,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;IAE3C;;;;OAIG;gBACS,KAAK,GAAE,CAAC,EAAO;IAS3B;;;;OAIG;IACH,IAAI,MAAM,IAAI,MAAM,CAGnB;IAED;;;;OAIG;IACH,GAAG,IAAI,CAAC,EAAE;IAKV;;;;OAIG;IACH,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,IAAI;IAUrB;;;;;OAKG;IACH,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI;IAUrC;;;;OAIG;IACH,IAAI,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI;IAOnB;;;OAGG;IACH,GAAG,IAAI,IAAI;IAUX;;;;OAIG;IACH,OAAO,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI;IAOtB;;;OAGG;IACH,KAAK,IAAI,IAAI;IAUb;;;;;;OAMG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAC,EAAE,GAAG,IAAI;IAelE;;;OAGG;IACH,KAAK,IAAI,IAAI;IAWb;;;;OAIG;IACM,OAAO,CAAC,OAAO,CAAC,EAAE;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI;CAWtD"}
@@ -1 +1 @@
1
- {"version":3,"file":"derivation.d.ts","sourceRoot":"","sources":["../../../src/basic/derivation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C;;;;;;;;GAQG;AACH,qBAAa,cAAc,CAAC,CAAC,CAAE,SAAQ,cAAc,CAAC,CAAC,CAAC;IACpD;;;;;OAKG;gBACS,OAAO,EAAE,CAAC,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,KAAK,CAAC;IAK/D;;;;;;;OAOG;IACI,GAAG,IAAI,CAAC;IASf,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,MAAM,CAAS;IAEvB,OAAO,CAAC,WAAW,CAAyD;IAC5E,OAAO,CAAC,aAAa,CAAoD;IACzE,OAAO,CAAC,aAAa,CAAgD;IACrE,OAAO,CAAC,eAAe,CAA4C;IACnE,OAAO,CAAC,eAAe,CAAW;IAClC,OAAO,CAAC,iBAAiB,CAAW;IAEpC,OAAO,CAAC,UAAU;IASlB,OAAO,CAAC,SAAS;CAyBpB"}
1
+ {"version":3,"file":"derivation.d.ts","sourceRoot":"","sources":["../../../src/basic/derivation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C;;;;;;;;GAQG;AACH,qBAAa,cAAc,CAAC,CAAC,CAAE,SAAQ,cAAc,CAAC,CAAC,CAAC;IACpD;;;;;OAKG;gBACS,OAAO,EAAE,CAAC,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,KAAK,CAAC;IAK/D;;;;;;;OAOG;IACI,GAAG,IAAI,CAAC;IASf,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,MAAM,CAAS;IAEvB,OAAO,CAAC,WAAW,CAAyD;IAC5E,OAAO,CAAC,aAAa,CAAoD;IACzE,OAAO,CAAC,aAAa,CAAgD;IACrE,OAAO,CAAC,eAAe,CAA4C;IACnE,OAAO,CAAC,eAAe,CAAW;IAClC,OAAO,CAAC,iBAAiB,CAAW;IAEpC,OAAO,CAAC,UAAU;IASlB,OAAO,CAAC,SAAS;CA0CpB"}
@@ -0,0 +1,31 @@
1
+ import { FlowDerivation, FlowGetter, FlowWatcher } from '@ersbeth/picoflow';
2
+ /**
3
+ * Represents a reactive resource that asynchronously fetches its value.
4
+ *
5
+ * @remarks
6
+ * A FlowResource extends FlowObservable and encapsulates an asynchronous fetch function.
7
+ * It is used to retrieve and update its value asynchronously. When the fetch is executed,
8
+ * if the new value differs from the current value, the resource is updated and its subscribers
9
+ * are notified.
10
+ *
11
+ * @typeparam T - The type of the resource value.
12
+ *
13
+ * @public
14
+ */
15
+ export declare class FlowDerivationAsync<T> extends FlowDerivation<Promise<T>> {
16
+ /**
17
+ * Creates a new FlowDerivation.
18
+ * @param compute - A function that computes the derived value. It is provided with two parameters:
19
+ * a getter and a watcher that respect dependency tracking.
20
+ * @public
21
+ */
22
+ constructor(compute: (get: FlowGetter, watch: FlowWatcher) => Promise<T>);
23
+ /**
24
+ * Retrieves the current resource value.
25
+ * @returns The current value, or undefined if the resource has not been fetched yet.
26
+ * @throws Error if the resource is disposed.
27
+ * @public
28
+ */
29
+ get(): Promise<T>;
30
+ }
31
+ //# sourceMappingURL=derivationAsync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"derivationAsync.d.ts","sourceRoot":"","sources":["../../../src/basic/derivationAsync.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,KAAK,UAAU,EAAE,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEtF;;;;;;;;;;;;GAYG;AACH,qBAAa,mBAAmB,CAAC,CAAC,CAAE,SAAQ,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAClE;;;;;OAKG;gBAGS,OAAO,EAAE,CAAC,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC;IAIxE;;;;;OAKG;IACa,GAAG,IAAI,OAAO,CAAC,CAAC,CAAC;CAGpC"}
@@ -2,6 +2,7 @@ export { FlowSignal } from './signal';
2
2
  export { FlowState } from './state';
3
3
  export { FlowObservable } from './observable';
4
4
  export { FlowDerivation } from './derivation';
5
+ export { FlowDerivationAsync } from './derivationAsync';
5
6
  export { FlowEffect } from './effect';
6
7
  export { FlowConstant } from './constant';
7
8
  export { isDisposable } from './disposable';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/basic/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,YAAY,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,YAAY,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/basic/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,YAAY,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,YAAY,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC"}
@@ -8,6 +8,8 @@
8
8
  */
9
9
  export { signal, state, constant, resource, stream, derivation, effect, map, array, streamAsync, resourceAsync, } from './creators';
10
10
  export { isDisposable } from './basic';
11
- export type { FlowDerivation, FlowEffect, FlowGetter, FlowObservable, FlowSignal, FlowWatcher, FlowState, FlowConstant, FlowDisposable, } from './basic/';
12
- export type { FlowResource, FlowMap, FlowResourceAsync, FlowStreamAsync, FlowStream, FlowStreamDisposer, FlowStreamSetter, FlowStreamUpdater, FlowArray, FlowArrayAction, } from './advanced/';
11
+ export { FlowDerivation, FlowDerivationAsync, FlowEffect, FlowObservable, FlowSignal, FlowState, FlowConstant, } from './basic/';
12
+ export type { FlowGetter, FlowWatcher, FlowDisposable, } from './basic/';
13
+ export { FlowResource, FlowMap, FlowResourceAsync, FlowStreamAsync, FlowStream, FlowArray, } from './advanced/';
14
+ export type { FlowStreamDisposer, FlowStreamSetter, FlowStreamUpdater, FlowArrayAction, } from './advanced/';
13
15
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EACH,MAAM,EACN,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,UAAU,EACV,MAAM,EACN,GAAG,EACH,KAAK,EACL,WAAW,EACX,aAAa,GAChB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,YAAY,EACR,cAAc,EACd,UAAU,EACV,UAAU,EACV,cAAc,EACd,UAAU,EACV,WAAW,EACX,SAAS,EACT,YAAY,EACZ,cAAc,GACjB,MAAM,UAAU,CAAC;AAClB,YAAY,EACR,YAAY,EACZ,OAAO,EACP,iBAAiB,EACjB,eAAe,EACf,UAAU,EACV,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,SAAS,EACT,eAAe,GAClB,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EACH,MAAM,EACN,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,UAAU,EACV,MAAM,EACN,GAAG,EACH,KAAK,EACL,WAAW,EACX,aAAa,GAChB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EACH,cAAc,EACd,mBAAmB,EACnB,UAAU,EACV,cAAc,EACd,UAAU,EACV,SAAS,EACT,YAAY,GACf,MAAM,UAAU,CAAC;AAElB,YAAY,EACR,UAAU,EACV,WAAW,EACX,cAAc,GACjB,MAAM,UAAU,CAAC;AAClB,OAAO,EACH,YAAY,EACZ,OAAO,EACP,iBAAiB,EACjB,eAAe,EACf,UAAU,EACV,SAAS,GACZ,MAAM,aAAa,CAAC;AACrB,YAAY,EACR,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,GAClB,MAAM,aAAa,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ersbeth/picoflow",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Minimal Dataflow librairy for TypeScript",
5
5
  "type": "module",
6
6
  "exports": {
@@ -67,7 +67,24 @@ export class FlowDerivation<T> extends FlowObservable<T> {
67
67
 
68
68
  /* @internal */ _compute(): void {
69
69
  if (this._dirty) {
70
- this._value = this._untrackedCompute();
70
+ // we cant use untrackedCompute because it will not track dependencies
71
+ // that changed dynamically
72
+
73
+ // store current dependencies
74
+ const dependencies = [...this._dependencies];
75
+
76
+ // clear current dependencies, compute and retrack dependencies
77
+ this._dependencies.clear();
78
+ this._value = this._trackedCompute();
79
+
80
+ // unsubscribe from dependencies that are no longer needed
81
+ const dependenciesToRemove = dependencies.filter(
82
+ (dependency) => !this._dependencies.has(dependency),
83
+ );
84
+ dependenciesToRemove.forEach((dependency) =>
85
+ dependency._unregisterDependency(this),
86
+ );
87
+
71
88
  this._dirty = false;
72
89
  }
73
90
  }
@@ -0,0 +1,38 @@
1
+ import { FlowDerivation, type FlowGetter, type FlowWatcher } from '@ersbeth/picoflow';
2
+
3
+ /**
4
+ * Represents a reactive resource that asynchronously fetches its value.
5
+ *
6
+ * @remarks
7
+ * A FlowResource extends FlowObservable and encapsulates an asynchronous fetch function.
8
+ * It is used to retrieve and update its value asynchronously. When the fetch is executed,
9
+ * if the new value differs from the current value, the resource is updated and its subscribers
10
+ * are notified.
11
+ *
12
+ * @typeparam T - The type of the resource value.
13
+ *
14
+ * @public
15
+ */
16
+ export class FlowDerivationAsync<T> extends FlowDerivation<Promise<T>> {
17
+ /**
18
+ * Creates a new FlowDerivation.
19
+ * @param compute - A function that computes the derived value. It is provided with two parameters:
20
+ * a getter and a watcher that respect dependency tracking.
21
+ * @public
22
+ */
23
+
24
+ // biome-ignore lint/complexity/noUselessConstructor: <explanation>
25
+ constructor(compute: (get: FlowGetter, watch: FlowWatcher) => Promise<T>) {
26
+ super(compute);
27
+ }
28
+
29
+ /**
30
+ * Retrieves the current resource value.
31
+ * @returns The current value, or undefined if the resource has not been fetched yet.
32
+ * @throws Error if the resource is disposed.
33
+ * @public
34
+ */
35
+ public override get(): Promise<T> {
36
+ return super.get();
37
+ }
38
+ }
@@ -2,6 +2,7 @@ export { FlowSignal } from "./signal";
2
2
  export { FlowState } from "./state";
3
3
  export { FlowObservable } from "./observable";
4
4
  export { FlowDerivation } from "./derivation";
5
+ export { FlowDerivationAsync } from "./derivationAsync";
5
6
  export { FlowEffect } from "./effect";
6
7
  export { FlowConstant } from "./constant";
7
8
  export { isDisposable } from "./disposable";
package/src/index.ts CHANGED
@@ -20,26 +20,32 @@ export {
20
20
  resourceAsync,
21
21
  } from "./creators";
22
22
  export { isDisposable } from "./basic";
23
- export type {
23
+ export {
24
24
  FlowDerivation,
25
+ FlowDerivationAsync,
25
26
  FlowEffect,
26
- FlowGetter,
27
27
  FlowObservable,
28
28
  FlowSignal,
29
- FlowWatcher,
30
29
  FlowState,
31
30
  FlowConstant,
32
- FlowDisposable,
33
31
  } from "./basic/";
32
+
34
33
  export type {
34
+ FlowGetter,
35
+ FlowWatcher,
36
+ FlowDisposable,
37
+ } from "./basic/";
38
+ export {
35
39
  FlowResource,
36
40
  FlowMap,
37
41
  FlowResourceAsync,
38
42
  FlowStreamAsync,
39
43
  FlowStream,
44
+ FlowArray,
45
+ } from "./advanced/";
46
+ export type {
40
47
  FlowStreamDisposer,
41
48
  FlowStreamSetter,
42
49
  FlowStreamUpdater,
43
- FlowArray,
44
50
  FlowArrayAction,
45
51
  } from "./advanced/";
@@ -443,4 +443,102 @@ describe("effect", () => {
443
443
  expect(effectFn).toHaveBeenLastCalledWith(4);
444
444
  });
445
445
  });
446
+
447
+ describe("complex test", () => {
448
+ test("test", () => {
449
+ const obj1 = {
450
+ cond: state(false),
451
+ num: state(2),
452
+ dispose: (options: { self: boolean }) => {
453
+ obj1.cond.dispose(options);
454
+ obj1.num.dispose(options);
455
+ }
456
+ }
457
+ const obj2 = {
458
+ cond: state(false),
459
+ num: state(4),
460
+ dispose: (options: { self: boolean }) => {
461
+ obj2.cond.dispose(options);
462
+ obj2.num.dispose(options);
463
+ }
464
+ }
465
+ const $state = state(obj1);
466
+ const $derivationCond = derivation((get) => get(get($state).cond));
467
+ const $derivationNum = derivation((get) => get(get($state).num) * 2);
468
+ const effectCondFn = vi.fn();
469
+ const effectNumFn = vi.fn();
470
+ effect((get) => effectCondFn(get($derivationCond)));
471
+ effect((get) => effectNumFn(get($derivationNum)));
472
+
473
+ expect(effectCondFn).toHaveBeenCalledTimes(1);
474
+ expect(effectCondFn).toHaveBeenLastCalledWith(false);
475
+ expect(effectNumFn).toHaveBeenCalledTimes(1);
476
+ expect(effectNumFn).toHaveBeenLastCalledWith(4);
477
+
478
+ $state.get().num.set(3);
479
+ expect(effectCondFn).toHaveBeenCalledTimes(1);
480
+ expect(effectCondFn).toHaveBeenLastCalledWith(false);
481
+ expect(effectNumFn).toHaveBeenCalledTimes(2);
482
+ expect(effectNumFn).toHaveBeenLastCalledWith(6);
483
+
484
+ $state.get().cond.set(true);
485
+ expect(effectCondFn).toHaveBeenCalledTimes(2);
486
+ expect(effectCondFn).toHaveBeenLastCalledWith(true);
487
+ expect(effectNumFn).toHaveBeenCalledTimes(2);
488
+ expect(effectNumFn).toHaveBeenLastCalledWith(6);
489
+
490
+ $state.set(obj2)
491
+ expect(effectCondFn).toHaveBeenCalledTimes(3);
492
+ expect(effectCondFn).toHaveBeenLastCalledWith(false);
493
+ expect(effectNumFn).toHaveBeenCalledTimes(3);
494
+ expect(effectNumFn).toHaveBeenLastCalledWith(8);
495
+
496
+ $state.get().cond.set(true);
497
+ expect(effectCondFn).toHaveBeenCalledTimes(4); // fails -> called 3 times
498
+ expect(effectCondFn).toHaveBeenLastCalledWith(true);
499
+ expect(effectNumFn).toHaveBeenCalledTimes(3);
500
+ expect(effectNumFn).toHaveBeenLastCalledWith(8);
501
+
502
+ $state.get().num.set(5);
503
+ expect(effectCondFn).toHaveBeenCalledTimes(4);
504
+ expect(effectCondFn).toHaveBeenLastCalledWith(true);
505
+ expect(effectNumFn).toHaveBeenCalledTimes(4);
506
+ expect(effectNumFn).toHaveBeenLastCalledWith(10);
507
+ });
508
+
509
+ test("test", () => {
510
+ const obj = {
511
+ cond: state(false),
512
+ b: state(2)
513
+ }
514
+
515
+ const $state = state(obj);
516
+ const $derivation = derivation((get) => {
517
+ const cond = get(get($state).cond);
518
+ if (cond) {
519
+ return get(get($state).b) * 2;
520
+ }
521
+ return 0;
522
+ });
523
+
524
+
525
+ const effectFn = vi.fn();
526
+ effect((get) => effectFn(get($derivation)));
527
+
528
+ expect(effectFn).toHaveBeenCalledTimes(1);
529
+ expect(effectFn).toHaveBeenLastCalledWith(0);
530
+
531
+ $state.get().cond.set(true);
532
+ expect(effectFn).toHaveBeenCalledTimes(2);
533
+ expect(effectFn).toHaveBeenLastCalledWith(4);
534
+
535
+ $state.set({ cond: state(false), b: state(3) })
536
+ expect(effectFn).toHaveBeenCalledTimes(3);
537
+ expect(effectFn).toHaveBeenLastCalledWith(0);
538
+
539
+ $state.get().cond.set(true);
540
+ expect(effectFn).toHaveBeenCalledTimes(4);
541
+ expect(effectFn).toHaveBeenLastCalledWith(6);
542
+ });
543
+ });
446
544
  });