@thi.ng/rstream 7.2.46 → 8.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.
- package/CHANGELOG.md +34 -1
- package/README.md +99 -60
- package/index.d.ts +2 -0
- package/index.js +2 -0
- package/iterable.d.ts +4 -4
- package/iterable.js +4 -4
- package/object.d.ts +2 -3
- package/package.json +18 -12
- package/raf.d.ts +19 -8
- package/raf.js +11 -10
- package/sidechain-partition.d.ts +39 -16
- package/sidechain-partition.js +49 -28
- package/sidechain-toggle.d.ts +12 -14
- package/sidechain-toggle.js +15 -19
- package/sidechain-trigger.d.ts +54 -0
- package/sidechain-trigger.js +66 -0
- package/sync-raf.d.ts +45 -0
- package/sync-raf.js +72 -0
- package/view.d.ts +1 -1
- package/view.js +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
-
- **Last updated**: 2023-
|
|
3
|
+
- **Last updated**: 2023-04-08T11:09:50Z
|
|
4
4
|
- **Generator**: [thi.ng/monopub](https://thi.ng/monopub)
|
|
5
5
|
|
|
6
6
|
All notable changes to this project will be documented in this file.
|
|
@@ -9,6 +9,39 @@ See [Conventional Commits](https://conventionalcommits.org/) for commit guidelin
|
|
|
9
9
|
**Note:** Unlisted _patch_ versions only involve non-code or otherwise excluded changes
|
|
10
10
|
and/or version bumps of transitive dependencies.
|
|
11
11
|
|
|
12
|
+
# [8.0.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/rstream@8.0.0) (2023-04-08)
|
|
13
|
+
|
|
14
|
+
#### 🛑 Breaking changes
|
|
15
|
+
|
|
16
|
+
- simplify/unify sidechain API ([5e90431](https://github.com/thi-ng/umbrella/commit/5e90431))
|
|
17
|
+
- BREAKING CHANGE: simplify/unify sidechain subscription API
|
|
18
|
+
- update sidechainPartition/Toggle/Trigger() to take src sub as 1st arg
|
|
19
|
+
- old: `src.subscribe(sidechainXXX(side))`...
|
|
20
|
+
- new: `sidechainXXX(src, side)`
|
|
21
|
+
- update docs
|
|
22
|
+
- update tests
|
|
23
|
+
|
|
24
|
+
#### 🚀 Features
|
|
25
|
+
|
|
26
|
+
- add syncRAF() ([3c17520](https://github.com/thi-ng/umbrella/commit/3c17520))
|
|
27
|
+
- add SyncRAF class and syncRAF() factory
|
|
28
|
+
- deprecate sidechainPartitionRAF()
|
|
29
|
+
- add tests
|
|
30
|
+
- add sidechainTrigger() ([3d2b56d](https://github.com/thi-ng/umbrella/commit/3d2b56d))
|
|
31
|
+
- add timestamp support for fromRAF() ([a2b8629](https://github.com/thi-ng/umbrella/commit/a2b8629))
|
|
32
|
+
- add FromRAFOpts
|
|
33
|
+
- update docs
|
|
34
|
+
|
|
35
|
+
#### 🩹 Bug fixes
|
|
36
|
+
|
|
37
|
+
- fix opts handling in syncRAF() & fromView() ([baa8878](https://github.com/thi-ng/umbrella/commit/baa8878))
|
|
38
|
+
|
|
39
|
+
#### ♻️ Refactoring
|
|
40
|
+
|
|
41
|
+
- update KeyStreams type ([1dd60e9](https://github.com/thi-ng/umbrella/commit/1dd60e9))
|
|
42
|
+
- switch value types Subscription => ISubscription
|
|
43
|
+
- minor update sidechainPartition/Toggle() ([c3ffd38](https://github.com/thi-ng/umbrella/commit/c3ffd38))
|
|
44
|
+
|
|
12
45
|
### [7.2.46](https://github.com/thi-ng/umbrella/tree/@thi.ng/rstream@7.2.46) (2023-03-27)
|
|
13
46
|
|
|
14
47
|
#### ♻️ Refactoring
|
package/README.md
CHANGED
|
@@ -35,6 +35,7 @@ This project is part of the
|
|
|
35
35
|
- [Side-chaining](#side-chaining)
|
|
36
36
|
- [Input chunking / buffering, controlled by sidechain](#input-chunking--buffering-controlled-by-sidechain)
|
|
37
37
|
- [Input toggling, controlled by sidechain](#input-toggling-controlled-by-sidechain)
|
|
38
|
+
- [Input passthrough, controlled by sidechain](#input-passthrough-controlled-by-sidechain)
|
|
38
39
|
- [Worker support](#worker-support)
|
|
39
40
|
- [Parallel stream processing via workers](#parallel-stream-processing-via-workers)
|
|
40
41
|
- [Stream processing via workers](#stream-processing-via-workers)
|
|
@@ -196,7 +197,7 @@ For Node.js REPL:
|
|
|
196
197
|
const rstream = await import("@thi.ng/rstream");
|
|
197
198
|
```
|
|
198
199
|
|
|
199
|
-
Package sizes (brotli'd, pre-treeshake): ESM: 5.
|
|
200
|
+
Package sizes (brotli'd, pre-treeshake): ESM: 5.80 KB
|
|
200
201
|
|
|
201
202
|
## Dependencies
|
|
202
203
|
|
|
@@ -237,6 +238,7 @@ A selection:
|
|
|
237
238
|
| <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/parse-playground.png" width="240"/> | Parser grammar livecoding editor/playground & codegen | [Demo](https://demo.thi.ng/umbrella/parse-playground/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/parse-playground) |
|
|
238
239
|
| <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/pixel-sorting.png" width="240"/> | Interactive pixel sorting tool using thi.ng/color & thi.ng/pixel | [Demo](https://demo.thi.ng/umbrella/pixel-sorting/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/pixel-sorting) |
|
|
239
240
|
| | Demonstates various rdom usage patterns | [Demo](https://demo.thi.ng/umbrella/rdom-basics/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/rdom-basics) |
|
|
241
|
+
| <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/rdom-canvas-basics.png" width="240"/> | Minimal rdom-canvas animation | [Demo](https://demo.thi.ng/umbrella/rdom-canvas-basics/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/rdom-canvas-basics) |
|
|
240
242
|
| <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/rdom-delayed-update.jpg" width="240"/> | Dynamically loaded images w/ preloader state | [Demo](https://demo.thi.ng/umbrella/rdom-delayed-update/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/rdom-delayed-update) |
|
|
241
243
|
| <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/rdom-lissajous.png" width="240"/> | rdom & hiccup-canvas interop test | [Demo](https://demo.thi.ng/umbrella/rdom-lissajous/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/rdom-lissajous) |
|
|
242
244
|
| | Full umbrella repo doc string search w/ paginated results | [Demo](https://demo.thi.ng/umbrella/rdom-search-docs/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/rdom-search-docs) |
|
|
@@ -246,9 +248,11 @@ A selection:
|
|
|
246
248
|
| <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/rstream-grid.jpg" width="240"/> | Interactive grid generator, SVG generation & export, undo/redo support | [Demo](https://demo.thi.ng/umbrella/rstream-grid/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/rstream-grid) |
|
|
247
249
|
| | rstream based UI updates & state handling | [Demo](https://demo.thi.ng/umbrella/rstream-hdom/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/rstream-hdom) |
|
|
248
250
|
| <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/rstream-spreadsheet.png" width="240"/> | rstream based spreadsheet w/ S-expression formula DSL | [Demo](https://demo.thi.ng/umbrella/rstream-spreadsheet/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/rstream-spreadsheet) |
|
|
251
|
+
| <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/rstream-sync.png" width="240"/> | Minimal rstream sync() example using rdom | [Demo](https://demo.thi.ng/umbrella/rstream-sync/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/rstream-sync) |
|
|
249
252
|
| <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/shader-ast-workers.jpg" width="240"/> | Fork-join worker-based raymarch renderer (JS/CPU only) | [Demo](https://demo.thi.ng/umbrella/shader-ast-workers/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/shader-ast-workers) |
|
|
250
253
|
| <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/svg-resample.png" width="240"/> | SVG path parsing & dynamic resampling | [Demo](https://demo.thi.ng/umbrella/svg-resample/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/svg-resample) |
|
|
251
254
|
| <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/talk-slides.png" width="240"/> | hdom based slide deck viewer & slides from my ClojureX 2018 keynote | [Demo](http://media.thi.ng/2018/talks/clojurex/index.html) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/talk-slides) |
|
|
255
|
+
| <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/trace-bitmap.jpg" width="240"/> | Multi-layer vectorization & dithering of bitmap images | [Demo](https://demo.thi.ng/umbrella/trace-bitmap/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/trace-bitmap) |
|
|
252
256
|
| | Transducer & rstream based hdom UI updates | [Demo](https://demo.thi.ng/umbrella/transducers-hdom/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/transducers-hdom) |
|
|
253
257
|
| <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/webgl-channel-mixer.jpg" width="240"/> | rdom & WebGL-based image channel editor | [Demo](https://demo.thi.ng/umbrella/webgl-channel-mixer/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/webgl-channel-mixer) |
|
|
254
258
|
| <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/webgl-cubemap.jpg" width="240"/> | WebGL cube maps with async texture loading | [Demo](https://demo.thi.ng/umbrella/webgl-cubemap/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/webgl-cubemap) |
|
|
@@ -304,7 +308,7 @@ interface CommonOpts {
|
|
|
304
308
|
|
|
305
309
|
#### Stream
|
|
306
310
|
|
|
307
|
-
|
|
311
|
+
Docs: [stream()](https://docs.thi.ng/umbrella/rstream/functions/stream-1.html)
|
|
308
312
|
|
|
309
313
|
Creates a new `Stream` instance, optionally with given `StreamSource`
|
|
310
314
|
function and / or ID. If a `src` function is provided, the function
|
|
@@ -361,7 +365,7 @@ will always return `undefined`.
|
|
|
361
365
|
|
|
362
366
|
#### Subscription
|
|
363
367
|
|
|
364
|
-
|
|
368
|
+
Docs: [subscription()](https://docs.thi.ng/umbrella/rstream/functions/subscription-1.html)
|
|
365
369
|
|
|
366
370
|
Creates a new `Subscription` instance, the fundamental datatype &
|
|
367
371
|
building block provided by this package (`Stream`s are `Subscription`s
|
|
@@ -393,25 +397,26 @@ s.next(42);
|
|
|
393
397
|
|
|
394
398
|
#### Other stream creation helpers
|
|
395
399
|
|
|
396
|
-
- [reactive()](https://
|
|
397
|
-
- [fromAtom()](https://
|
|
400
|
+
- [reactive()](https://docs.thi.ng/umbrella/rstream/functions/reactive.html) - syntax sugar for `stream()` with initial value
|
|
401
|
+
- [fromAtom()](https://docs.thi.ng/umbrella/rstream/functions/fromAtom.html) - streams from value changes in atoms/cursors
|
|
398
402
|
- [fromChannel()](https://github.com/thi-ng/umbrella/tree/develop/packages/rstream-csp) - CSP channel to stream conversion
|
|
399
|
-
- [fromEvent()](https://
|
|
400
|
-
- [fromDOMEvent()](https://
|
|
401
|
-
- [fromInterval()](https://
|
|
402
|
-
- [fromIterable()](https://
|
|
403
|
-
- [fromNodeJS()
|
|
404
|
-
- [
|
|
405
|
-
- [
|
|
406
|
-
- [
|
|
407
|
-
- [
|
|
408
|
-
- [
|
|
409
|
-
- [
|
|
410
|
-
- [
|
|
403
|
+
- [fromEvent()](https://docs.thi.ng/umbrella/rstream/functions/fromEvent.html) - events
|
|
404
|
+
- [fromDOMEvent()](https://docs.thi.ng/umbrella/rstream/functions/fromDOMEvent.html) - DOM events
|
|
405
|
+
- [fromInterval()](https://docs.thi.ng/umbrella/rstream/functions/fromInterval.html) - interval based counters
|
|
406
|
+
- [fromIterable()](https://docs.thi.ng/umbrella/rstream/functions/fromIterable.html) - arrays, iterators / generators (async & sync)
|
|
407
|
+
- [fromNodeJS()](https://docs.thi.ng/umbrella/rstream/functions/fromNodeJS.html) - NodeJS stream adapter
|
|
408
|
+
- [linesFromNodeJS()](https://docs.thi.ng/umbrella/rstream/functions/linesFromNodeJS.html) - NodeJS stream adapter
|
|
409
|
+
- [fromObject()](https://docs.thi.ng/umbrella/rstream/functions/fromObject.html) - object property streams
|
|
410
|
+
- [fromPromise()](https://docs.thi.ng/umbrella/rstream/functions/fromPromise.html) - single value stream from promise
|
|
411
|
+
- [fromPromises()](https://docs.thi.ng/umbrella/rstream/functions/fromPromises.html) - results from multiple promise
|
|
412
|
+
- [fromRAF()](https://docs.thi.ng/umbrella/rstream/functions/fromRAF.html) - requestAnimationFrame() counter (w/ node fallback)
|
|
413
|
+
- [fromView()](https://docs.thi.ng/umbrella/rstream/functions/fromView.html) - derived view value changes (see [@thi.ng/atom](https://github.com/thi-ng/umbrella/tree/develop/packages/atom))
|
|
414
|
+
- [fromWorker()](https://docs.thi.ng/umbrella/rstream/functions/fromWorker.html) - messages received from worker
|
|
415
|
+
- [trigger()](https://docs.thi.ng/umbrella/rstream/functions/trigger.html) - one-off events
|
|
411
416
|
|
|
412
417
|
### Meta streams
|
|
413
418
|
|
|
414
|
-
|
|
419
|
+
Docs: [metaStream()](https://docs.thi.ng/umbrella/rstream/functions/metaStream-1.html)
|
|
415
420
|
|
|
416
421
|
`MetaStream`s are streams of streams. A `MetaStream` is a subscription
|
|
417
422
|
type which transforms each incoming value into a new stream, subscribes
|
|
@@ -496,7 +501,7 @@ m.next(true);
|
|
|
496
501
|
|
|
497
502
|
#### Unordered merge from multiple inputs (dynamic add/remove)
|
|
498
503
|
|
|
499
|
-
|
|
504
|
+
Docs: [merge()](https://docs.thi.ng/umbrella/rstream/functions/merge.html)
|
|
500
505
|
|
|
501
506
|

|
|
502
507
|
|
|
@@ -528,9 +533,8 @@ merge({
|
|
|
528
533
|
```
|
|
529
534
|
|
|
530
535
|
Use the [`labeled()`
|
|
531
|
-
transducer](https://
|
|
532
|
-
|
|
533
|
-
provenance:
|
|
536
|
+
transducer](https://docs.thi.ng/umbrella/transducers/functions/labeled.html) for
|
|
537
|
+
each input to create a stream of labeled values and track their provenance:
|
|
534
538
|
|
|
535
539
|
```ts
|
|
536
540
|
merge({
|
|
@@ -548,7 +552,7 @@ merge({
|
|
|
548
552
|
```
|
|
549
553
|
|
|
550
554
|
See
|
|
551
|
-
[StreamMergeOpts](https://
|
|
555
|
+
[StreamMergeOpts](https://docs.thi.ng/umbrella/rstream/interfaces/StreamMergeOpts.html)
|
|
552
556
|
for further reference of the various behavior options.
|
|
553
557
|
|
|
554
558
|
##### Adding inputs automatically
|
|
@@ -559,8 +563,10 @@ as new input to the merge and then automatically remove once that stream
|
|
|
559
563
|
is exhausted.
|
|
560
564
|
|
|
561
565
|
```ts
|
|
566
|
+
import { repeat } from "@thi.ng/transducers";
|
|
567
|
+
|
|
562
568
|
// stream source w/ transducer mapping values to new streams
|
|
563
|
-
a = stream().
|
|
569
|
+
a = stream().map((x) => fromIterable(repeat(x, 3)));
|
|
564
570
|
// simple 1Hz counter
|
|
565
571
|
b = fromInterval(1000);
|
|
566
572
|
|
|
@@ -571,17 +577,17 @@ merge({ src: [a, b] }).subscribe(trace());
|
|
|
571
577
|
|
|
572
578
|
// sent "a" will be transformed into stream via above transducer
|
|
573
579
|
// and then auto-added as new input to the StreamMerge
|
|
574
|
-
a.next("
|
|
575
|
-
//
|
|
576
|
-
//
|
|
577
|
-
//
|
|
580
|
+
a.next("abc");
|
|
581
|
+
// abc
|
|
582
|
+
// abc
|
|
583
|
+
// abc
|
|
578
584
|
// 3
|
|
579
585
|
// 4
|
|
580
586
|
```
|
|
581
587
|
|
|
582
588
|
#### Synchronized merge and labeled tuple objects
|
|
583
589
|
|
|
584
|
-
|
|
590
|
+
Docs: [sync()](https://docs.thi.ng/umbrella/rstream/functions/sync.html)
|
|
585
591
|
|
|
586
592
|

|
|
587
593
|
|
|
@@ -622,19 +628,20 @@ be incomplete, by default. To only allow complete tuples, also set the
|
|
|
622
628
|
`all` option to `false`.
|
|
623
629
|
|
|
624
630
|
The synchronization is done via the
|
|
625
|
-
[`partitionSync()`](https://
|
|
626
|
-
transducer from the
|
|
627
|
-
|
|
631
|
+
[`partitionSync()`](https://docs.thi.ng/umbrella/transducers/functions/partitionSync-1.html)
|
|
632
|
+
transducer from the
|
|
633
|
+
[@thi.ng/transducers](https://github.com/thi-ng/umbrella/tree/develop/packages/transducers)
|
|
634
|
+
package. See this function's docs for further details.
|
|
628
635
|
|
|
629
636
|
See
|
|
630
|
-
[StreamSyncOpts](https://
|
|
637
|
+
[StreamSyncOpts](https://docs.thi.ng/umbrella/rstream/interfaces/StreamSyncOpts.html)
|
|
631
638
|
for further reference of the various behavior options.
|
|
632
639
|
|
|
633
640
|
### Stream splitting
|
|
634
641
|
|
|
635
642
|
#### Topic based splitting
|
|
636
643
|
|
|
637
|
-
|
|
644
|
+
Docs: [pubsub()](https://docs.thi.ng/umbrella/rstream/functions/pubsub-1.html)
|
|
638
645
|
|
|
639
646
|

|
|
640
647
|
|
|
@@ -659,7 +666,7 @@ called WITHOUT argument to unsubscribe the entire `PubSub` instance
|
|
|
659
666
|
|
|
660
667
|
#### Splitting via predicate
|
|
661
668
|
|
|
662
|
-
|
|
669
|
+
Docs: [bisect()](https://docs.thi.ng/umbrella/rstream/functions/bisect.html)
|
|
663
670
|
|
|
664
671
|
Returns a new `PubSub` instance using given predicate `pred` as boolean
|
|
665
672
|
topic function and `a` & `b` as subscribers for truthy (`a`) and falsy
|
|
@@ -704,7 +711,7 @@ fromIterable([1, 2, 3, 4]).subscribe(bisect((x) => !!(x & 1), odd, even));
|
|
|
704
711
|
|
|
705
712
|
#### Input chunking / buffering, controlled by sidechain
|
|
706
713
|
|
|
707
|
-
|
|
714
|
+
Docs: [sidechainPartition()](https://docs.thi.ng/umbrella/rstream/functions/sidechainPartition-1.html)
|
|
708
715
|
|
|
709
716
|

|
|
710
717
|
|
|
@@ -715,21 +722,25 @@ optional predicate can be used to only trigger for specific values /
|
|
|
715
722
|
conditions.
|
|
716
723
|
|
|
717
724
|
```ts
|
|
718
|
-
//
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
725
|
+
// queue event processing to only execute during the
|
|
726
|
+
// requestAnimationFrame cycle (RAF)
|
|
727
|
+
sidechainPartition(
|
|
728
|
+
// merge various event streams
|
|
729
|
+
merge([
|
|
730
|
+
fromEvent(document, "mousemove"),
|
|
731
|
+
fromEvent(document, "mousedown"),
|
|
732
|
+
fromEvent(document, "mouseup")
|
|
733
|
+
]),
|
|
734
|
+
// sidechain control stream
|
|
735
|
+
fromRAF()
|
|
736
|
+
).subscribe(trace());
|
|
728
737
|
```
|
|
729
738
|
|
|
739
|
+
Since v8.0.0 there's [`syncRAF()`](https://docs.thi.ng/umbrella/rstream/functions/syncRAF-1.html)
|
|
740
|
+
|
|
730
741
|
#### Input toggling, controlled by sidechain
|
|
731
742
|
|
|
732
|
-
|
|
743
|
+
Docs: [sidechainToggle()](https://docs.thi.ng/umbrella/rstream/functions/sidechainToggle-1.html)
|
|
733
744
|
|
|
734
745
|

|
|
735
746
|
|
|
@@ -741,10 +752,8 @@ will be toggled on/off. Whilst switched off, no input values will be
|
|
|
741
752
|
forwarded.
|
|
742
753
|
|
|
743
754
|
```ts
|
|
744
|
-
// use slower interval stream to toggle main stream on/off
|
|
745
|
-
fromInterval(500)
|
|
746
|
-
.subscribe(sidechainToggle(fromInterval(1000)))
|
|
747
|
-
.subscribe(trace());
|
|
755
|
+
// use slower interval stream to toggle faster main stream on/off
|
|
756
|
+
sidechainToggle(fromInterval(500), fromInterval(1000)).subscribe(trace());
|
|
748
757
|
// 0
|
|
749
758
|
// 3
|
|
750
759
|
// 4
|
|
@@ -753,11 +762,41 @@ fromInterval(500)
|
|
|
753
762
|
...
|
|
754
763
|
```
|
|
755
764
|
|
|
765
|
+
#### Input passthrough, controlled by sidechain
|
|
766
|
+
|
|
767
|
+
Docs: [sidechainTrigger()](https://docs.thi.ng/umbrella/rstream/functions/sidechainTrigger-1.html)
|
|
768
|
+
|
|
769
|
+
Buffers the most recent value received and only forwards it downstream whenever
|
|
770
|
+
a new control value is received from the sidechain.
|
|
771
|
+
|
|
772
|
+
```ts
|
|
773
|
+
const src = reactive("payload");
|
|
774
|
+
|
|
775
|
+
const side = stream();
|
|
776
|
+
|
|
777
|
+
sidechainTrigger(src, side).subscribe(trace("data:"));
|
|
778
|
+
|
|
779
|
+
side.next(1);
|
|
780
|
+
// data: payload
|
|
781
|
+
|
|
782
|
+
// every time sidechain triggers
|
|
783
|
+
side.next(1);
|
|
784
|
+
// data: payload
|
|
785
|
+
|
|
786
|
+
// only newest value will be buffered
|
|
787
|
+
src.next("update #1");
|
|
788
|
+
src.next("update #2");
|
|
789
|
+
|
|
790
|
+
// ...until side chain triggers again
|
|
791
|
+
side.next(1);
|
|
792
|
+
// data: update #2
|
|
793
|
+
```
|
|
794
|
+
|
|
756
795
|
### Worker support
|
|
757
796
|
|
|
758
797
|
#### Parallel stream processing via workers
|
|
759
798
|
|
|
760
|
-
|
|
799
|
+
Docs: [forkJoin()](https://docs.thi.ng/umbrella/rstream/functions/forkJoin.html)
|
|
761
800
|
|
|
762
801
|

|
|
763
802
|
|
|
@@ -806,27 +845,27 @@ src.next(new Array(16).fill(1));
|
|
|
806
845
|
|
|
807
846
|
#### Stream processing via workers
|
|
808
847
|
|
|
809
|
-
|
|
848
|
+
Docs: [tunnel()](https://docs.thi.ng/umbrella/rstream/functions/tunnel-1.html)
|
|
810
849
|
|
|
811
850
|
Delegate stream value processing to workers and pass on their responses
|
|
812
851
|
to downstream subscriptions. Supports multiple worker instances and
|
|
813
852
|
worker termination / restart for each new stream value received.
|
|
814
853
|
|
|
815
|
-
|
|
854
|
+
Docs: [postWorker()](https://docs.thi.ng/umbrella/rstream/functions/postWorker.html)
|
|
816
855
|
|
|
817
856
|
Send values to workers (incl. optional (inline) worker instantiation)
|
|
818
857
|
|
|
819
|
-
|
|
858
|
+
Docs: [fromWorker()](https://docs.thi.ng/umbrella/rstream/functions/fromWorker.html)
|
|
820
859
|
|
|
821
860
|
Create value stream from worker messages.
|
|
822
861
|
|
|
823
862
|
### Other subscription ops
|
|
824
863
|
|
|
825
|
-
- [debounce](https://
|
|
826
|
-
- [resolve](https://
|
|
827
|
-
- [trace](https://
|
|
828
|
-
- [transduce](https://
|
|
829
|
-
- [tween](https://
|
|
864
|
+
- [debounce](https://docs.thi.ng/umbrella/rstream/functions/debounce.html): ignore high frequency interim values
|
|
865
|
+
- [resolve](https://docs.thi.ng/umbrella/rstream/functions/resolve.html): resolve on-stream promises
|
|
866
|
+
- [trace](https://docs.thi.ng/umbrella/rstream/functions/trace.html): debug helper
|
|
867
|
+
- [transduce](https://docs.thi.ng/umbrella/rstream/functions/transduce.html): transduce or just reduce an entire stream into a promise
|
|
868
|
+
- [tween](https://docs.thi.ng/umbrella/rstream/functions/tween.html): stream interpolation
|
|
830
869
|
|
|
831
870
|
### Error handling
|
|
832
871
|
|
package/index.d.ts
CHANGED
|
@@ -23,9 +23,11 @@ export * from "./raf.js";
|
|
|
23
23
|
export * from "./resolve.js";
|
|
24
24
|
export * from "./sidechain-partition.js";
|
|
25
25
|
export * from "./sidechain-toggle.js";
|
|
26
|
+
export * from "./sidechain-trigger.js";
|
|
26
27
|
export * from "./stream.js";
|
|
27
28
|
export * from "./subscription.js";
|
|
28
29
|
export * from "./sync.js";
|
|
30
|
+
export * from "./sync-raf.js";
|
|
29
31
|
export * from "./timeout.js";
|
|
30
32
|
export * from "./trace.js";
|
|
31
33
|
export * from "./transduce.js";
|
package/index.js
CHANGED
|
@@ -23,9 +23,11 @@ export * from "./raf.js";
|
|
|
23
23
|
export * from "./resolve.js";
|
|
24
24
|
export * from "./sidechain-partition.js";
|
|
25
25
|
export * from "./sidechain-toggle.js";
|
|
26
|
+
export * from "./sidechain-trigger.js";
|
|
26
27
|
export * from "./stream.js";
|
|
27
28
|
export * from "./subscription.js";
|
|
28
29
|
export * from "./sync.js";
|
|
30
|
+
export * from "./sync-raf.js";
|
|
29
31
|
export * from "./timeout.js";
|
|
30
32
|
export * from "./trace.js";
|
|
31
33
|
export * from "./transduce.js";
|
package/iterable.d.ts
CHANGED
|
@@ -26,10 +26,10 @@ export interface FromIterableOpts extends CommonOpts {
|
|
|
26
26
|
export declare const fromIterable: <T>(src: Iterable<T>, opts?: Partial<FromIterableOpts>) => import("./stream.js").Stream<T>;
|
|
27
27
|
/**
|
|
28
28
|
* Creates a new {@link Stream} of given iterable which synchronously calls
|
|
29
|
-
*
|
|
30
|
-
* case the only one) subscriber becomes available. Once the iterable is
|
|
31
|
-
* exhausted (MUST be finite!), then calls
|
|
32
|
-
* be avoided by passing `false` as last argument.
|
|
29
|
+
* {@link ISubscriber.next} for each item of the iterable when the first (and in
|
|
30
|
+
* this case the only one) subscriber becomes available. Once the iterable is
|
|
31
|
+
* exhausted (MUST be finite!), then calls {@link ISubscriber.done} by default,
|
|
32
|
+
* but can be avoided by passing `false` as last argument.
|
|
33
33
|
*
|
|
34
34
|
* @param src -
|
|
35
35
|
* @param opts -
|
package/iterable.js
CHANGED
|
@@ -32,10 +32,10 @@ export const fromIterable = (src, opts = {}) => stream((stream) => {
|
|
|
32
32
|
}, __optsWithID("iterable", opts));
|
|
33
33
|
/**
|
|
34
34
|
* Creates a new {@link Stream} of given iterable which synchronously calls
|
|
35
|
-
*
|
|
36
|
-
* case the only one) subscriber becomes available. Once the iterable is
|
|
37
|
-
* exhausted (MUST be finite!), then calls
|
|
38
|
-
* be avoided by passing `false` as last argument.
|
|
35
|
+
* {@link ISubscriber.next} for each item of the iterable when the first (and in
|
|
36
|
+
* this case the only one) subscriber becomes available. Once the iterable is
|
|
37
|
+
* exhausted (MUST be finite!), then calls {@link ISubscriber.done} by default,
|
|
38
|
+
* but can be avoided by passing `false` as last argument.
|
|
39
39
|
*
|
|
40
40
|
* @param src -
|
|
41
41
|
* @param opts -
|
package/object.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import type { Keys, Predicate2 } from "@thi.ng/api";
|
|
2
|
-
import type { CommonOpts } from "./api.js";
|
|
3
|
-
import { type Subscription } from "./subscription.js";
|
|
2
|
+
import type { CommonOpts, ISubscription } from "./api.js";
|
|
4
3
|
export type KeyStreams<T, K extends Keys<T>> = {
|
|
5
|
-
[id in K]-?:
|
|
4
|
+
[id in K]-?: ISubscription<T[id], T[id]>;
|
|
6
5
|
};
|
|
7
6
|
/**
|
|
8
7
|
* Result object type for {@link fromObject}.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thi.ng/rstream",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "8.0.0",
|
|
4
4
|
"description": "Reactive streams & subscription primitives for constructing dataflow graphs / pipelines",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./index.js",
|
|
@@ -38,22 +38,22 @@
|
|
|
38
38
|
"test": "testament test"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@thi.ng/api": "^8.7.
|
|
42
|
-
"@thi.ng/arrays": "^2.5.
|
|
43
|
-
"@thi.ng/associative": "^6.2.
|
|
44
|
-
"@thi.ng/atom": "^5.
|
|
45
|
-
"@thi.ng/checks": "^3.3.
|
|
46
|
-
"@thi.ng/errors": "^2.2.
|
|
47
|
-
"@thi.ng/logger": "^1.4.
|
|
48
|
-
"@thi.ng/transducers": "^8.4.
|
|
41
|
+
"@thi.ng/api": "^8.7.6",
|
|
42
|
+
"@thi.ng/arrays": "^2.5.10",
|
|
43
|
+
"@thi.ng/associative": "^6.2.34",
|
|
44
|
+
"@thi.ng/atom": "^5.2.0",
|
|
45
|
+
"@thi.ng/checks": "^3.3.12",
|
|
46
|
+
"@thi.ng/errors": "^2.2.15",
|
|
47
|
+
"@thi.ng/logger": "^1.4.13",
|
|
48
|
+
"@thi.ng/transducers": "^8.4.2"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@microsoft/api-extractor": "^7.34.4",
|
|
52
|
-
"@thi.ng/testament": "^0.3.
|
|
52
|
+
"@thi.ng/testament": "^0.3.15",
|
|
53
53
|
"rimraf": "^4.4.1",
|
|
54
54
|
"tools": "^0.0.1",
|
|
55
55
|
"typedoc": "^0.23.28",
|
|
56
|
-
"typescript": "^5.0.
|
|
56
|
+
"typescript": "^5.0.4"
|
|
57
57
|
},
|
|
58
58
|
"keywords": [
|
|
59
59
|
"async",
|
|
@@ -162,12 +162,18 @@
|
|
|
162
162
|
"./sidechain-toggle": {
|
|
163
163
|
"default": "./sidechain-toggle.js"
|
|
164
164
|
},
|
|
165
|
+
"./sidechain-trigger": {
|
|
166
|
+
"default": "./sidechain-trigger.js"
|
|
167
|
+
},
|
|
165
168
|
"./stream": {
|
|
166
169
|
"default": "./stream.js"
|
|
167
170
|
},
|
|
168
171
|
"./subscription": {
|
|
169
172
|
"default": "./subscription.js"
|
|
170
173
|
},
|
|
174
|
+
"./sync-raf": {
|
|
175
|
+
"default": "./sync-raf.js"
|
|
176
|
+
},
|
|
171
177
|
"./sync": {
|
|
172
178
|
"default": "./sync.js"
|
|
173
179
|
},
|
|
@@ -205,5 +211,5 @@
|
|
|
205
211
|
],
|
|
206
212
|
"year": 2017
|
|
207
213
|
},
|
|
208
|
-
"gitHead": "
|
|
214
|
+
"gitHead": "abcedd9e4e06a4b631f363610eec572f79b571c1\n"
|
|
209
215
|
}
|
package/raf.d.ts
CHANGED
|
@@ -1,15 +1,26 @@
|
|
|
1
1
|
import type { CommonOpts } from "./api.js";
|
|
2
|
+
export interface FromRAFOpts extends CommonOpts {
|
|
3
|
+
/**
|
|
4
|
+
* Browser only. If true (default: false), passes the timestamps received
|
|
5
|
+
* via `requestAnimationFrame()` as stream values. If false, a simple
|
|
6
|
+
* counter [0..∞) will be emitted.
|
|
7
|
+
*
|
|
8
|
+
* @defaultValue false
|
|
9
|
+
*/
|
|
10
|
+
timestamp: boolean;
|
|
11
|
+
}
|
|
2
12
|
/**
|
|
3
|
-
* Yields {@link Stream} of a monotonically increasing counter,
|
|
4
|
-
* triggered by a `requestAnimationFrame()` loop (only available in
|
|
5
|
-
*
|
|
13
|
+
* Yields {@link Stream} of a monotonically increasing counter (or timestamps),
|
|
14
|
+
* triggered by a `requestAnimationFrame()` loop (only available in browser
|
|
15
|
+
* environments).
|
|
6
16
|
*
|
|
7
17
|
* @remarks
|
|
8
|
-
* In NodeJS, this function falls back to {@link fromInterval}, yielding
|
|
9
|
-
*
|
|
18
|
+
* In NodeJS, this function falls back to {@link fromInterval}, yielding a
|
|
19
|
+
* similar (approx. 60Hz) stream (the {@link FromRAFOpts.timestamp} option will
|
|
20
|
+
* be ignored).
|
|
10
21
|
*
|
|
11
|
-
* All subscribers to this stream will be processed during that same
|
|
12
|
-
*
|
|
22
|
+
* All subscribers to this stream will be processed during that same RAF loop
|
|
23
|
+
* iteration.
|
|
13
24
|
*/
|
|
14
|
-
export declare const fromRAF: (opts?: Partial<
|
|
25
|
+
export declare const fromRAF: (opts?: Partial<FromRAFOpts>) => import("./stream.js").Stream<number>;
|
|
15
26
|
//# sourceMappingURL=raf.d.ts.map
|
package/raf.js
CHANGED
|
@@ -3,24 +3,25 @@ import { __optsWithID } from "./idgen.js";
|
|
|
3
3
|
import { fromInterval } from "./interval.js";
|
|
4
4
|
import { stream } from "./stream.js";
|
|
5
5
|
/**
|
|
6
|
-
* Yields {@link Stream} of a monotonically increasing counter,
|
|
7
|
-
* triggered by a `requestAnimationFrame()` loop (only available in
|
|
8
|
-
*
|
|
6
|
+
* Yields {@link Stream} of a monotonically increasing counter (or timestamps),
|
|
7
|
+
* triggered by a `requestAnimationFrame()` loop (only available in browser
|
|
8
|
+
* environments).
|
|
9
9
|
*
|
|
10
10
|
* @remarks
|
|
11
|
-
* In NodeJS, this function falls back to {@link fromInterval}, yielding
|
|
12
|
-
*
|
|
11
|
+
* In NodeJS, this function falls back to {@link fromInterval}, yielding a
|
|
12
|
+
* similar (approx. 60Hz) stream (the {@link FromRAFOpts.timestamp} option will
|
|
13
|
+
* be ignored).
|
|
13
14
|
*
|
|
14
|
-
* All subscribers to this stream will be processed during that same
|
|
15
|
-
*
|
|
15
|
+
* All subscribers to this stream will be processed during that same RAF loop
|
|
16
|
+
* iteration.
|
|
16
17
|
*/
|
|
17
|
-
export const fromRAF = (opts) => isNode()
|
|
18
|
+
export const fromRAF = (opts = {}) => isNode()
|
|
18
19
|
? fromInterval(16, opts)
|
|
19
20
|
: stream((stream) => {
|
|
20
21
|
let i = 0;
|
|
21
22
|
let isActive = true;
|
|
22
|
-
const loop = () => {
|
|
23
|
-
isActive && stream.next(i++);
|
|
23
|
+
const loop = (time) => {
|
|
24
|
+
isActive && stream.next(opts.timestamp ? time : i++);
|
|
24
25
|
isActive && (id = requestAnimationFrame(loop));
|
|
25
26
|
};
|
|
26
27
|
let id = requestAnimationFrame(loop);
|
package/sidechain-partition.d.ts
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
import type { Predicate } from "@thi.ng/api";
|
|
2
|
-
import { type CommonOpts, type ISubscribable } from "./api.js";
|
|
2
|
+
import { type CommonOpts, type ISubscribable, type ISubscription } from "./api.js";
|
|
3
3
|
import { ASidechain } from "./asidechain.js";
|
|
4
|
-
import type { Subscription } from "./subscription.js";
|
|
5
4
|
export interface SidechainPartitionOpts<T> extends CommonOpts {
|
|
6
5
|
pred: Predicate<T>;
|
|
7
6
|
}
|
|
8
7
|
/**
|
|
9
|
-
* Returns a
|
|
10
|
-
*
|
|
11
|
-
*
|
|
8
|
+
* Returns a subscription which buffers values from `src` until side chain
|
|
9
|
+
* delivers its next value, then emits buffer (unless empty) and repeats process
|
|
10
|
+
* until either input is done.
|
|
12
11
|
*
|
|
13
12
|
* @remarks
|
|
14
|
-
* By default, the values read from the side chain are ignored (i.e.
|
|
15
|
-
*
|
|
16
|
-
*
|
|
13
|
+
* By default, the values read from the side chain are ignored (i.e. only their
|
|
14
|
+
* timing is used), however the `pred`icate option can be used to only trigger
|
|
15
|
+
* for specific values / conditions.
|
|
16
|
+
*
|
|
17
|
+
* Also see: {@link sidechainToggle}, {@link sidechainTrigger}, {@link syncRAF}.
|
|
17
18
|
*
|
|
18
19
|
* @example
|
|
19
20
|
* ```t
|
|
@@ -26,23 +27,45 @@ export interface SidechainPartitionOpts<T> extends CommonOpts {
|
|
|
26
27
|
*
|
|
27
28
|
* // queue event processing to only execute during the
|
|
28
29
|
* // requestAnimationFrame cycle (RAF)
|
|
29
|
-
*
|
|
30
|
+
* sidechainPartition(events, fromRAF()).subscribe(trace())
|
|
30
31
|
* ```
|
|
31
32
|
*
|
|
33
|
+
* @param src -
|
|
32
34
|
* @param side -
|
|
33
35
|
* @param opts -
|
|
34
36
|
*/
|
|
35
|
-
export declare const sidechainPartition: <
|
|
37
|
+
export declare const sidechainPartition: <T, S>(src: ISubscribable<T>, side: ISubscribable<S>, opts?: Partial<SidechainPartitionOpts<S>> | undefined) => ISubscription<T, T[]>;
|
|
36
38
|
/**
|
|
37
|
-
*
|
|
38
|
-
* synchronize downstream processing w/ `requestAnimationFrame()`.
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
39
|
+
* **Deprecated** syntax sugar for one of most common {@link sidechainPartition}
|
|
40
|
+
* use cases, to synchronize downstream processing w/ `requestAnimationFrame()`.
|
|
41
|
+
* Please use {@link syncRAF} instead.
|
|
42
|
+
*
|
|
43
|
+
* @remarks
|
|
44
|
+
* The returned subscription debounces any high frequency intra-frame input
|
|
45
|
+
* values and (if any present), passes only most recent one downstream during
|
|
46
|
+
* next RAF event processing.
|
|
47
|
+
*
|
|
48
|
+
* This example uses thi.ng/atom as state container. Also see {@link fromAtom}
|
|
49
|
+
* and {@link syncRAF}.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```ts
|
|
53
|
+
* const atom = defAtom("alice");
|
|
54
|
+
*
|
|
55
|
+
* // any change to the atom will only be applied during next RAF update
|
|
56
|
+
* sideChainPartitionRAF(fromAtom(atom)).subscribe({
|
|
57
|
+
* next({ name }) { document.body.innerText = name; }
|
|
58
|
+
* });
|
|
59
|
+
*
|
|
60
|
+
* // trigger update
|
|
61
|
+
* atom.reset("bob");
|
|
62
|
+
* ```
|
|
42
63
|
*
|
|
43
64
|
* @param src -
|
|
65
|
+
*
|
|
66
|
+
* @deprecated
|
|
44
67
|
*/
|
|
45
|
-
export declare const sidechainPartitionRAF: <T>(src: ISubscribable<T>) =>
|
|
68
|
+
export declare const sidechainPartitionRAF: <T>(src: ISubscribable<T>) => ISubscription<T[], T>;
|
|
46
69
|
export declare class SidechainPartition<T, S> extends ASidechain<T, S, T[]> {
|
|
47
70
|
buf: T[];
|
|
48
71
|
constructor(side: ISubscribable<S>, opts?: Partial<SidechainPartitionOpts<S>>);
|
package/sidechain-partition.js
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
import { peek } from "@thi.ng/arrays/peek";
|
|
2
2
|
import { map } from "@thi.ng/transducers/map";
|
|
3
|
-
import { State } from "./api.js";
|
|
3
|
+
import { State, } from "./api.js";
|
|
4
4
|
import { ASidechain } from "./asidechain.js";
|
|
5
5
|
import { __optsWithID } from "./idgen.js";
|
|
6
6
|
import { fromRAF } from "./raf.js";
|
|
7
7
|
/**
|
|
8
|
-
* Returns a
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* Returns a subscription which buffers values from `src` until side chain
|
|
9
|
+
* delivers its next value, then emits buffer (unless empty) and repeats process
|
|
10
|
+
* until either input is done.
|
|
11
11
|
*
|
|
12
12
|
* @remarks
|
|
13
|
-
* By default, the values read from the side chain are ignored (i.e.
|
|
14
|
-
*
|
|
15
|
-
*
|
|
13
|
+
* By default, the values read from the side chain are ignored (i.e. only their
|
|
14
|
+
* timing is used), however the `pred`icate option can be used to only trigger
|
|
15
|
+
* for specific values / conditions.
|
|
16
|
+
*
|
|
17
|
+
* Also see: {@link sidechainToggle}, {@link sidechainTrigger}, {@link syncRAF}.
|
|
16
18
|
*
|
|
17
19
|
* @example
|
|
18
20
|
* ```t
|
|
@@ -25,45 +27,64 @@ import { fromRAF } from "./raf.js";
|
|
|
25
27
|
*
|
|
26
28
|
* // queue event processing to only execute during the
|
|
27
29
|
* // requestAnimationFrame cycle (RAF)
|
|
28
|
-
*
|
|
30
|
+
* sidechainPartition(events, fromRAF()).subscribe(trace())
|
|
29
31
|
* ```
|
|
30
32
|
*
|
|
33
|
+
* @param src -
|
|
31
34
|
* @param side -
|
|
32
35
|
* @param opts -
|
|
33
36
|
*/
|
|
34
|
-
export const sidechainPartition = (side, opts) => new SidechainPartition(side, opts);
|
|
37
|
+
export const sidechainPartition = (src, side, opts) => src.subscribe(new SidechainPartition(side, opts));
|
|
35
38
|
/**
|
|
36
|
-
*
|
|
37
|
-
* synchronize downstream processing w/ `requestAnimationFrame()`.
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
39
|
+
* **Deprecated** syntax sugar for one of most common {@link sidechainPartition}
|
|
40
|
+
* use cases, to synchronize downstream processing w/ `requestAnimationFrame()`.
|
|
41
|
+
* Please use {@link syncRAF} instead.
|
|
42
|
+
*
|
|
43
|
+
* @remarks
|
|
44
|
+
* The returned subscription debounces any high frequency intra-frame input
|
|
45
|
+
* values and (if any present), passes only most recent one downstream during
|
|
46
|
+
* next RAF event processing.
|
|
47
|
+
*
|
|
48
|
+
* This example uses thi.ng/atom as state container. Also see {@link fromAtom}
|
|
49
|
+
* and {@link syncRAF}.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```ts
|
|
53
|
+
* const atom = defAtom("alice");
|
|
54
|
+
*
|
|
55
|
+
* // any change to the atom will only be applied during next RAF update
|
|
56
|
+
* sideChainPartitionRAF(fromAtom(atom)).subscribe({
|
|
57
|
+
* next({ name }) { document.body.innerText = name; }
|
|
58
|
+
* });
|
|
59
|
+
*
|
|
60
|
+
* // trigger update
|
|
61
|
+
* atom.reset("bob");
|
|
62
|
+
* ```
|
|
41
63
|
*
|
|
42
64
|
* @param src -
|
|
65
|
+
*
|
|
66
|
+
* @deprecated
|
|
43
67
|
*/
|
|
44
|
-
export const sidechainPartitionRAF = (src) => src
|
|
45
|
-
.subscribe(sidechainPartition(fromRAF()))
|
|
46
|
-
.transform(map(peek));
|
|
68
|
+
export const sidechainPartitionRAF = (src) => sidechainPartition(src, fromRAF()).transform(map(peek));
|
|
47
69
|
export class SidechainPartition extends ASidechain {
|
|
48
70
|
constructor(side, opts) {
|
|
49
71
|
opts = __optsWithID("sidepart", opts);
|
|
50
72
|
super(opts);
|
|
51
|
-
this.buf = [];
|
|
52
73
|
const pred = opts.pred || (() => true);
|
|
53
|
-
|
|
74
|
+
this.buf = [];
|
|
54
75
|
this.sideSub = side.subscribe({
|
|
55
|
-
next(x) {
|
|
56
|
-
if (
|
|
57
|
-
|
|
58
|
-
|
|
76
|
+
next: (x) => {
|
|
77
|
+
if (this.buf.length && pred(x)) {
|
|
78
|
+
this.dispatch(this.buf);
|
|
79
|
+
this.buf = [];
|
|
59
80
|
}
|
|
60
81
|
},
|
|
61
|
-
done() {
|
|
62
|
-
if (
|
|
63
|
-
|
|
82
|
+
done: () => {
|
|
83
|
+
if (this.buf.length) {
|
|
84
|
+
this.dispatch(this.buf);
|
|
64
85
|
}
|
|
65
|
-
|
|
66
|
-
delete
|
|
86
|
+
this.done();
|
|
87
|
+
delete this.buf;
|
|
67
88
|
},
|
|
68
89
|
});
|
|
69
90
|
}
|
package/sidechain-toggle.d.ts
CHANGED
|
@@ -1,28 +1,25 @@
|
|
|
1
1
|
import type { Predicate } from "@thi.ng/api";
|
|
2
|
-
import { type CommonOpts, type ISubscribable } from "./api.js";
|
|
2
|
+
import { type CommonOpts, type ISubscribable, type ISubscription } from "./api.js";
|
|
3
3
|
import { ASidechain } from "./asidechain.js";
|
|
4
|
-
import type { Subscription } from "./subscription.js";
|
|
5
4
|
export interface SidechainToggleOpts<T> extends CommonOpts {
|
|
6
5
|
pred: Predicate<T>;
|
|
7
6
|
initial: boolean;
|
|
8
7
|
}
|
|
9
8
|
/**
|
|
10
|
-
* Returns
|
|
11
|
-
* values received from side chain.
|
|
9
|
+
* Returns a subscription which filters values from `src` based on control
|
|
10
|
+
* values received from `side` chain.
|
|
12
11
|
*
|
|
13
12
|
* @remarks
|
|
14
|
-
* By default, the
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
13
|
+
* By default, the values read from the side chain are ignored (i.e. only their
|
|
14
|
+
* timing is used), however the `pred`icate option can be used to only trigger
|
|
15
|
+
* for specific values/conditions. Every time the predicate fn returns true, the
|
|
16
|
+
* filter will be toggled on/off. Whilst switched off, no input values will be
|
|
17
|
+
* forwarded downstream.
|
|
19
18
|
*
|
|
20
19
|
* @example
|
|
21
20
|
* ```ts
|
|
22
|
-
* // use slower interval stream to toggle main stream on/off
|
|
23
|
-
* fromInterval(500)
|
|
24
|
-
* .subscribe(sidechainToggle(fromInterval(1000)))
|
|
25
|
-
* .subscribe(trace());
|
|
21
|
+
* // use slower interval stream to toggle faster main stream on/off
|
|
22
|
+
* sidechainToggle(fromInterval(500), fromInterval(1000)).subscribe(trace());
|
|
26
23
|
* // 0
|
|
27
24
|
* // 3
|
|
28
25
|
* // 4
|
|
@@ -31,10 +28,11 @@ export interface SidechainToggleOpts<T> extends CommonOpts {
|
|
|
31
28
|
* ...
|
|
32
29
|
* ```
|
|
33
30
|
*
|
|
31
|
+
* @param src -
|
|
34
32
|
* @param side -
|
|
35
33
|
* @param opts -
|
|
36
34
|
*/
|
|
37
|
-
export declare const sidechainToggle: <
|
|
35
|
+
export declare const sidechainToggle: <T, S>(src: ISubscribable<T>, side: ISubscribable<S>, opts?: Partial<SidechainToggleOpts<S>> | undefined) => ISubscription<T, T>;
|
|
38
36
|
export declare class SidechainToggle<T, S> extends ASidechain<T, S, T> {
|
|
39
37
|
isActive: boolean;
|
|
40
38
|
constructor(side: ISubscribable<S>, opts?: Partial<SidechainToggleOpts<S>>);
|
package/sidechain-toggle.js
CHANGED
|
@@ -1,23 +1,21 @@
|
|
|
1
|
-
import { State } from "./api.js";
|
|
1
|
+
import { State, } from "./api.js";
|
|
2
2
|
import { ASidechain } from "./asidechain.js";
|
|
3
3
|
import { __optsWithID } from "./idgen.js";
|
|
4
4
|
/**
|
|
5
|
-
* Returns
|
|
6
|
-
* values received from side chain.
|
|
5
|
+
* Returns a subscription which filters values from `src` based on control
|
|
6
|
+
* values received from `side` chain.
|
|
7
7
|
*
|
|
8
8
|
* @remarks
|
|
9
|
-
* By default, the
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
9
|
+
* By default, the values read from the side chain are ignored (i.e. only their
|
|
10
|
+
* timing is used), however the `pred`icate option can be used to only trigger
|
|
11
|
+
* for specific values/conditions. Every time the predicate fn returns true, the
|
|
12
|
+
* filter will be toggled on/off. Whilst switched off, no input values will be
|
|
13
|
+
* forwarded downstream.
|
|
14
14
|
*
|
|
15
15
|
* @example
|
|
16
16
|
* ```ts
|
|
17
|
-
* // use slower interval stream to toggle main stream on/off
|
|
18
|
-
* fromInterval(500)
|
|
19
|
-
* .subscribe(sidechainToggle(fromInterval(1000)))
|
|
20
|
-
* .subscribe(trace());
|
|
17
|
+
* // use slower interval stream to toggle faster main stream on/off
|
|
18
|
+
* sidechainToggle(fromInterval(500), fromInterval(1000)).subscribe(trace());
|
|
21
19
|
* // 0
|
|
22
20
|
* // 3
|
|
23
21
|
* // 4
|
|
@@ -26,26 +24,24 @@ import { __optsWithID } from "./idgen.js";
|
|
|
26
24
|
* ...
|
|
27
25
|
* ```
|
|
28
26
|
*
|
|
27
|
+
* @param src -
|
|
29
28
|
* @param side -
|
|
30
29
|
* @param opts -
|
|
31
30
|
*/
|
|
32
|
-
export const sidechainToggle = (side, opts) => new SidechainToggle(side, opts);
|
|
31
|
+
export const sidechainToggle = (src, side, opts) => src.subscribe(new SidechainToggle(side, opts));
|
|
33
32
|
export class SidechainToggle extends ASidechain {
|
|
34
33
|
constructor(side, opts) {
|
|
35
34
|
opts = __optsWithID("sidetoggle", opts);
|
|
36
35
|
super(opts);
|
|
37
36
|
this.isActive = !!opts.initial;
|
|
38
37
|
const pred = opts.pred || (() => true);
|
|
39
|
-
const $this = this;
|
|
40
38
|
this.sideSub = side.subscribe({
|
|
41
|
-
next(x) {
|
|
39
|
+
next: (x) => {
|
|
42
40
|
if (pred(x)) {
|
|
43
|
-
|
|
41
|
+
this.isActive = !this.isActive;
|
|
44
42
|
}
|
|
45
43
|
},
|
|
46
|
-
done()
|
|
47
|
-
$this.done();
|
|
48
|
-
},
|
|
44
|
+
done: () => this.done(),
|
|
49
45
|
});
|
|
50
46
|
}
|
|
51
47
|
next(x) {
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { Predicate } from "@thi.ng/api";
|
|
2
|
+
import { SEMAPHORE } from "@thi.ng/api/api";
|
|
3
|
+
import { type CommonOpts, type ISubscribable, type ISubscription } from "./api.js";
|
|
4
|
+
import { ASidechain } from "./asidechain.js";
|
|
5
|
+
export interface SidechainTriggerOpts<T> extends CommonOpts {
|
|
6
|
+
pred: Predicate<T>;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Returns a subscription which buffers the most recent value received from
|
|
10
|
+
* `src` and only forwards it downstream whenever a new control value is
|
|
11
|
+
* received from the `side` chain.
|
|
12
|
+
*
|
|
13
|
+
* @remarks
|
|
14
|
+
* By default, the values read from the side chain are ignored (i.e. only their
|
|
15
|
+
* timing is used), however the `pred`icate option can be used to only trigger
|
|
16
|
+
* for specific values/conditions. Every time the predicate fn returns true AND
|
|
17
|
+
* if `src` already has delivered at least one value, it will be forwarded
|
|
18
|
+
* downstream.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* const src = reactive("payload");
|
|
23
|
+
*
|
|
24
|
+
* const side = stream();
|
|
25
|
+
*
|
|
26
|
+
* sidechainTrigger(src, side).subscribe(trace("data:"));
|
|
27
|
+
*
|
|
28
|
+
* side.next(1);
|
|
29
|
+
* // data: payload
|
|
30
|
+
*
|
|
31
|
+
* side.next(1);
|
|
32
|
+
* // data: payload
|
|
33
|
+
*
|
|
34
|
+
* // only newest value will be buffered
|
|
35
|
+
* src.next("update #1");
|
|
36
|
+
* src.next("update #2");
|
|
37
|
+
*
|
|
38
|
+
* // ...until side chain triggers again
|
|
39
|
+
* side.next(1);
|
|
40
|
+
* // data: update #2
|
|
41
|
+
* ...
|
|
42
|
+
* ```
|
|
43
|
+
*
|
|
44
|
+
* @param src
|
|
45
|
+
* @param side
|
|
46
|
+
* @param opts
|
|
47
|
+
*/
|
|
48
|
+
export declare const sidechainTrigger: <T, S>(src: ISubscribable<T>, side: ISubscribable<S>, opts?: Partial<SidechainTriggerOpts<S>> | undefined) => ISubscription<T, T>;
|
|
49
|
+
export declare class SidechainTrigger<T, S> extends ASidechain<T, S, T> {
|
|
50
|
+
buf: T | typeof SEMAPHORE;
|
|
51
|
+
constructor(side: ISubscribable<S>, opts?: Partial<SidechainTriggerOpts<S>>);
|
|
52
|
+
next(x: T): void;
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=sidechain-trigger.d.ts.map
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { SEMAPHORE } from "@thi.ng/api/api";
|
|
2
|
+
import { State, } from "./api.js";
|
|
3
|
+
import { ASidechain } from "./asidechain.js";
|
|
4
|
+
import { __optsWithID } from "./idgen.js";
|
|
5
|
+
/**
|
|
6
|
+
* Returns a subscription which buffers the most recent value received from
|
|
7
|
+
* `src` and only forwards it downstream whenever a new control value is
|
|
8
|
+
* received from the `side` chain.
|
|
9
|
+
*
|
|
10
|
+
* @remarks
|
|
11
|
+
* By default, the values read from the side chain are ignored (i.e. only their
|
|
12
|
+
* timing is used), however the `pred`icate option can be used to only trigger
|
|
13
|
+
* for specific values/conditions. Every time the predicate fn returns true AND
|
|
14
|
+
* if `src` already has delivered at least one value, it will be forwarded
|
|
15
|
+
* downstream.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* const src = reactive("payload");
|
|
20
|
+
*
|
|
21
|
+
* const side = stream();
|
|
22
|
+
*
|
|
23
|
+
* sidechainTrigger(src, side).subscribe(trace("data:"));
|
|
24
|
+
*
|
|
25
|
+
* side.next(1);
|
|
26
|
+
* // data: payload
|
|
27
|
+
*
|
|
28
|
+
* side.next(1);
|
|
29
|
+
* // data: payload
|
|
30
|
+
*
|
|
31
|
+
* // only newest value will be buffered
|
|
32
|
+
* src.next("update #1");
|
|
33
|
+
* src.next("update #2");
|
|
34
|
+
*
|
|
35
|
+
* // ...until side chain triggers again
|
|
36
|
+
* side.next(1);
|
|
37
|
+
* // data: update #2
|
|
38
|
+
* ...
|
|
39
|
+
* ```
|
|
40
|
+
*
|
|
41
|
+
* @param src
|
|
42
|
+
* @param side
|
|
43
|
+
* @param opts
|
|
44
|
+
*/
|
|
45
|
+
export const sidechainTrigger = (src, side, opts) => src.subscribe(new SidechainTrigger(side, opts));
|
|
46
|
+
export class SidechainTrigger extends ASidechain {
|
|
47
|
+
constructor(side, opts) {
|
|
48
|
+
opts = __optsWithID("sidetrigger", opts);
|
|
49
|
+
super(opts);
|
|
50
|
+
this.buf = SEMAPHORE;
|
|
51
|
+
const pred = opts.pred || (() => true);
|
|
52
|
+
this.sideSub = side.subscribe({
|
|
53
|
+
next: (x) => {
|
|
54
|
+
if (this.buf !== SEMAPHORE && pred(x)) {
|
|
55
|
+
this.dispatch(this.buf);
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
done: () => this.done(),
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
next(x) {
|
|
62
|
+
if (this.state < State.DONE) {
|
|
63
|
+
this.buf = x;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
package/sync-raf.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { type CommonOpts, type ISubscribable } from "./api.js";
|
|
3
|
+
import { Subscription } from "./subscription.js";
|
|
4
|
+
/**
|
|
5
|
+
* Similar to (in in effect the same as the **now deprecated**)
|
|
6
|
+
* {@link sidechainPartitionRAF}, however more performant & lightweight.
|
|
7
|
+
* Synchronizes downstream processing w/ `requestAnimationFrame()`. The returned
|
|
8
|
+
* subscription delays & debounces any high frequency intra-frame input values
|
|
9
|
+
* and passes only most recent one downstream during next RAF event processing.
|
|
10
|
+
*
|
|
11
|
+
* This example uses thi.ng/atom as state container. Also see {@link fromAtom}.
|
|
12
|
+
*
|
|
13
|
+
* See {@link sidechainTrigger} from a similar & more general construct.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* const atom = defAtom("alice");
|
|
18
|
+
*
|
|
19
|
+
* // any changes to the atom will only be received by this subscription
|
|
20
|
+
* // during next RAF update cycle
|
|
21
|
+
* syncRAF(fromAtom(atom)).subscribe({
|
|
22
|
+
* next({ name }) { document.body.innerText = name; }
|
|
23
|
+
* });
|
|
24
|
+
*
|
|
25
|
+
* // trigger update
|
|
26
|
+
* atom.reset("bob");
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* @param src -
|
|
30
|
+
* @param opts -
|
|
31
|
+
*/
|
|
32
|
+
export declare const syncRAF: <T>(src: ISubscribable<T>, opts?: Partial<CommonOpts>) => import("./api.js").ISubscription<T, T>;
|
|
33
|
+
/**
|
|
34
|
+
* See {@link syncRAF} for details.
|
|
35
|
+
*/
|
|
36
|
+
export declare class SyncRAF<T> extends Subscription<T, T> {
|
|
37
|
+
queued?: T;
|
|
38
|
+
raf?: number | NodeJS.Timeout;
|
|
39
|
+
constructor(opts?: Partial<CommonOpts>);
|
|
40
|
+
next(x: T): void;
|
|
41
|
+
done(): void;
|
|
42
|
+
error(e: any): boolean;
|
|
43
|
+
protected _clean(): void;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=sync-raf.d.ts.map
|
package/sync-raf.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { isNode } from "@thi.ng/checks/is-node";
|
|
2
|
+
import { State } from "./api.js";
|
|
3
|
+
import { __optsWithID } from "./idgen.js";
|
|
4
|
+
import { Subscription } from "./subscription.js";
|
|
5
|
+
/**
|
|
6
|
+
* Similar to (in in effect the same as the **now deprecated**)
|
|
7
|
+
* {@link sidechainPartitionRAF}, however more performant & lightweight.
|
|
8
|
+
* Synchronizes downstream processing w/ `requestAnimationFrame()`. The returned
|
|
9
|
+
* subscription delays & debounces any high frequency intra-frame input values
|
|
10
|
+
* and passes only most recent one downstream during next RAF event processing.
|
|
11
|
+
*
|
|
12
|
+
* This example uses thi.ng/atom as state container. Also see {@link fromAtom}.
|
|
13
|
+
*
|
|
14
|
+
* See {@link sidechainTrigger} from a similar & more general construct.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* const atom = defAtom("alice");
|
|
19
|
+
*
|
|
20
|
+
* // any changes to the atom will only be received by this subscription
|
|
21
|
+
* // during next RAF update cycle
|
|
22
|
+
* syncRAF(fromAtom(atom)).subscribe({
|
|
23
|
+
* next({ name }) { document.body.innerText = name; }
|
|
24
|
+
* });
|
|
25
|
+
*
|
|
26
|
+
* // trigger update
|
|
27
|
+
* atom.reset("bob");
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* @param src -
|
|
31
|
+
* @param opts -
|
|
32
|
+
*/
|
|
33
|
+
export const syncRAF = (src, opts) => src.subscribe(new SyncRAF(__optsWithID(`syncraf-${src.id}`, opts)));
|
|
34
|
+
/**
|
|
35
|
+
* See {@link syncRAF} for details.
|
|
36
|
+
*/
|
|
37
|
+
export class SyncRAF extends Subscription {
|
|
38
|
+
constructor(opts) {
|
|
39
|
+
super(undefined, opts);
|
|
40
|
+
}
|
|
41
|
+
next(x) {
|
|
42
|
+
if (this.state >= State.DONE)
|
|
43
|
+
return;
|
|
44
|
+
this.queued = x;
|
|
45
|
+
if (!this.raf) {
|
|
46
|
+
const update = () => {
|
|
47
|
+
if (this.state < State.DONE)
|
|
48
|
+
super.next(this.queued);
|
|
49
|
+
this._clean();
|
|
50
|
+
};
|
|
51
|
+
this.raf = isNode()
|
|
52
|
+
? setTimeout(update, 16)
|
|
53
|
+
: requestAnimationFrame(update);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
done() {
|
|
57
|
+
this._clean();
|
|
58
|
+
super.done();
|
|
59
|
+
}
|
|
60
|
+
error(e) {
|
|
61
|
+
this._clean();
|
|
62
|
+
return super.error(e);
|
|
63
|
+
}
|
|
64
|
+
_clean() {
|
|
65
|
+
if (this.raf) {
|
|
66
|
+
isNode()
|
|
67
|
+
? clearTimeout(this.raf)
|
|
68
|
+
: cancelAnimationFrame(this.raf);
|
|
69
|
+
}
|
|
70
|
+
this.raf = this.queued = undefined;
|
|
71
|
+
}
|
|
72
|
+
}
|
package/view.d.ts
CHANGED
|
@@ -41,7 +41,7 @@ export declare const fromViewUnsafe: <T>(atom: ReadonlyAtom<any>, opts: FromView
|
|
|
41
41
|
/**
|
|
42
42
|
* Similar to {@link fromAtom}, but creates a type checked, eager derived view
|
|
43
43
|
* for a nested value in an Atom-like state container and yields stream of its
|
|
44
|
-
* value changes.
|
|
44
|
+
* value changes. See {@link fromViewUnsafe} for unchecked version.
|
|
45
45
|
*
|
|
46
46
|
* @remarks
|
|
47
47
|
* Stream value type is inferred from target path or (if given), the result type
|
package/view.js
CHANGED