@ersbeth/picoflow 0.2.1 → 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.
- package/api/doc/picoflow.flowderivationasync._constructor_.md +49 -0
- package/api/doc/picoflow.flowderivationasync.get.md +23 -0
- package/api/doc/picoflow.flowderivationasync.md +86 -0
- package/api/doc/picoflow.md +11 -0
- package/api/picoflow.public.api.md +6 -0
- package/dist/picoflow.js +307 -17
- package/dist/types/basic/derivation.d.ts.map +1 -1
- package/dist/types/basic/derivationAsync.d.ts +31 -0
- package/dist/types/basic/derivationAsync.d.ts.map +1 -0
- package/dist/types/basic/index.d.ts +1 -0
- package/dist/types/basic/index.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/basic/derivation.ts +18 -1
- package/src/basic/derivationAsync.ts +38 -0
- package/src/basic/index.ts +1 -0
- package/src/index.ts +1 -0
- package/test/derivation.test.ts +98 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
|
2
|
+
|
|
3
|
+
[Home](./index.md) > [@ersbeth/picoflow](./picoflow.md) > [FlowDerivationAsync](./picoflow.flowderivationasync.md) > [(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)<!-- -->) => Promise<T>
|
|
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) > [@ersbeth/picoflow](./picoflow.md) > [FlowDerivationAsync](./picoflow.flowderivationasync.md) > [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<T>
|
|
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) > [@ersbeth/picoflow](./picoflow.md) > [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)<!-- --><Promise<T>>
|
|
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>
|
package/api/doc/picoflow.md
CHANGED
|
@@ -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 { FlowArray, FlowConstant, FlowDerivation, FlowEffect, FlowMap, FlowObservable, FlowResource, FlowResourceAsync, FlowSignal, FlowState, FlowStream, FlowStreamAsync, 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":"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;
|
|
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"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
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 { FlowDerivation, FlowEffect, FlowObservable, FlowSignal, FlowState, FlowConstant, } from './basic/';
|
|
11
|
+
export { FlowDerivation, FlowDerivationAsync, FlowEffect, FlowObservable, FlowSignal, FlowState, FlowConstant, } from './basic/';
|
|
12
12
|
export type { FlowGetter, FlowWatcher, FlowDisposable, } from './basic/';
|
|
13
13
|
export { FlowResource, FlowMap, FlowResourceAsync, FlowStreamAsync, FlowStream, FlowArray, } from './advanced/';
|
|
14
14
|
export type { FlowStreamDisposer, FlowStreamSetter, FlowStreamUpdater, FlowArrayAction, } from './advanced/';
|
|
@@ -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,OAAO,EACH,cAAc,EACd,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"}
|
|
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
package/src/basic/derivation.ts
CHANGED
|
@@ -67,7 +67,24 @@ export class FlowDerivation<T> extends FlowObservable<T> {
|
|
|
67
67
|
|
|
68
68
|
/* @internal */ _compute(): void {
|
|
69
69
|
if (this._dirty) {
|
|
70
|
-
|
|
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
|
+
}
|
package/src/basic/index.ts
CHANGED
|
@@ -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
package/test/derivation.test.ts
CHANGED
|
@@ -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
|
});
|