@thi.ng/rstream 8.5.13 → 9.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 +13 -1
- package/README.md +181 -192
- package/api.d.ts +23 -34
- package/api.js +0 -7
- package/checks.d.ts +1 -1
- package/checks.js +1 -2
- package/interval.d.ts +1 -1
- package/interval.js +1 -2
- package/iterable.d.ts +1 -1
- package/iterable.js +2 -3
- package/metastream.d.ts +4 -4
- package/metastream.js +3 -6
- package/package.json +2 -2
- package/promise.js +2 -2
- package/pubsub.d.ts +1 -1
- package/pubsub.js +1 -6
- package/stream.d.ts +1 -1
- package/stream.js +1 -4
- package/subscription.d.ts +1 -1
- package/subscription.js +4 -5
- package/tween.d.ts +1 -1
- package/tween.js +1 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
-
- **Last updated**: 2024-08-
|
|
3
|
+
- **Last updated**: 2024-08-20T11:41:56Z
|
|
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,18 @@ 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
|
+
# [9.0.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/rstream@9.0.0) (2024-08-20)
|
|
13
|
+
|
|
14
|
+
#### 🛑 Breaking changes
|
|
15
|
+
|
|
16
|
+
- replace `CloseMode` enum w/ string union type ([33b1d16](https://github.com/thi-ng/umbrella/commit/33b1d16))
|
|
17
|
+
- BREAKING CHANGE: replace `CloseMode` enum w/ string union type
|
|
18
|
+
- this simplifies all usage sites, now only using (and removing obsolete enum import):
|
|
19
|
+
- `CloseMode.FIRST` => `"first"`
|
|
20
|
+
- `CloseMode.LAST` => `"last"`
|
|
21
|
+
- `CloseMode.NEVER` => `"never"`
|
|
22
|
+
- update docs & all sites
|
|
23
|
+
|
|
12
24
|
## [8.5.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/rstream@8.5.0) (2024-05-08)
|
|
13
25
|
|
|
14
26
|
#### 🚀 Features
|
package/README.md
CHANGED
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
- [About](#about)
|
|
18
18
|
- [Conceptual differences to RxJS](#conceptual-differences-to-rxjs)
|
|
19
19
|
- [Status](#status)
|
|
20
|
+
- [New features & breaking changes in 9.0.0](#new-features--breaking-changes-in-900)
|
|
20
21
|
- [New features & breaking changes in 6.0.0](#new-features--breaking-changes-in-600)
|
|
21
22
|
- [Support packages](#support-packages)
|
|
22
23
|
- [Related packages](#related-packages)
|
|
@@ -53,52 +54,46 @@
|
|
|
53
54
|
|
|
54
55
|
Reactive streams & subscription primitives for constructing dataflow graphs / pipelines.
|
|
55
56
|
|
|
56
|
-
This library provides & uses three key building blocks for reactive
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
- **Workers**: highly configurable, web worker integration for
|
|
70
|
-
concurrent / parallel stream processing (fork-join, tunneled stream
|
|
71
|
-
processing, etc.)
|
|
57
|
+
This library provides & uses three key building blocks for reactive programming:
|
|
58
|
+
|
|
59
|
+
- **Stream sources**: event targets, iterables, timers, promises,watches,
|
|
60
|
+
workers, manual-push...
|
|
61
|
+
- **Subscriptions**: chained stream processors, each subscribable (one-tmany)
|
|
62
|
+
itself
|
|
63
|
+
- **Transducers**: stream transformers, either as individual subscription or to
|
|
64
|
+
transform incoming values for a single subscription. See packages/transducers)
|
|
65
|
+
for 100+ composable operators.
|
|
66
|
+
- **Recursive teardown**: Whenever possible, and depending on configuration,
|
|
67
|
+
unsubscriptions initiate cleanup and propagate to parent(s).
|
|
68
|
+
- **Workers**: highly configurable, web worker integration for concurrent /
|
|
69
|
+
parallel stream processing (fork-join, tunneled stream processing, etc.)
|
|
72
70
|
|
|
73
71
|
## Conceptual differences to RxJS
|
|
74
72
|
|
|
75
73
|
(No value judgments implied - there's room for both approaches!)
|
|
76
74
|
|
|
77
|
-
- Streams are not the same as Observables: I.e. stream sources are NOT
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
emitted and any future values
|
|
75
|
+
- Streams are not the same as Observables: I.e. stream sources are NOT (often
|
|
76
|
+
just cannot) re-run for each new sub added. Only the first sub is guaranteed
|
|
77
|
+
to receive **all** values. Subs added at a later time MIGHT not receive
|
|
78
|
+
earlier emitted values, but only the most recent emitted and any future values
|
|
82
79
|
- Every subscription supports any number of subscribers, which can be
|
|
83
80
|
added/removed at any time
|
|
84
|
-
- Depending on configuration options, every unsubscription recursively
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
- Every subscription can have its own transducer transforming incoming
|
|
88
|
-
|
|
89
|
-
- Transducers can create streams themselves (only for `merge()`
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
-
|
|
94
|
-
any
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
to provide specialized functions (map / filter etc.) and gain more
|
|
101
|
-
flexibility in terms of composing new operations.
|
|
81
|
+
- Depending on configuration options, every unsubscription recursively triggers
|
|
82
|
+
upstream unsubscriptions (provided a parent has no other active child
|
|
83
|
+
subscriptions)
|
|
84
|
+
- Every subscription can have its own transducer transforming incoming values
|
|
85
|
+
(possibly into multiple new ones)
|
|
86
|
+
- Transducers can create streams themselves (only for `merge()` /`sync()`)
|
|
87
|
+
- Transducers can cause early stream termination and subsequent unwinding for
|
|
88
|
+
its parent and downstream subscriptions.
|
|
89
|
+
- Values can be manually injected into the stream pipeline / graph at any point
|
|
90
|
+
- Unhandled errors in a subscription will move the subscription into an error
|
|
91
|
+
state and cause unsubscription from parent (if any). Unhandled errors in
|
|
92
|
+
stream sources will cancel the stream.
|
|
93
|
+
- _Much_ smaller API surface, since most common & custom operations can be
|
|
94
|
+
solved via available transducers. Therefore there's less of a need to provide
|
|
95
|
+
specialized functions (map / filter etc.) and gain more flexibility in terms
|
|
96
|
+
of composing new operations.
|
|
102
97
|
- IMHO less confusing naming / terminology (only streams (producers) &
|
|
103
98
|
subscriptions (consumers))
|
|
104
99
|
|
|
@@ -108,6 +103,12 @@ programming:
|
|
|
108
103
|
|
|
109
104
|
[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=%5Brstream%5D+in%3Atitle)
|
|
110
105
|
|
|
106
|
+
### New features & breaking changes in 9.0.0
|
|
107
|
+
|
|
108
|
+
The `CloseMode` enum has been replaced with a more compact & simple string union
|
|
109
|
+
type, see [docs](https://docs.thi.ng/umbrella/rstream/types/CloseMode.html) and
|
|
110
|
+
[usage](#common-configuration-options).
|
|
111
|
+
|
|
111
112
|
### New features & breaking changes in 6.0.0
|
|
112
113
|
|
|
113
114
|
Completely revised & improved [error handling](#error-handling), stronger
|
|
@@ -167,9 +168,9 @@ src.transformTopic("foo", map((e) => e.value), { error: handleError })
|
|
|
167
168
|
**Notes:**
|
|
168
169
|
|
|
169
170
|
- (1): If using multiple transducers, they must be pre-composed with
|
|
170
|
-
[`comp()`](https://docs.thi.ng/umbrella/transducers/functions/comp.html).
|
|
171
|
-
signatures of `.transform()` method support up to 4 transducers and
|
|
172
|
-
them automatically.
|
|
171
|
+
[`comp()`](https://docs.thi.ng/umbrella/transducers/functions/comp.html).
|
|
172
|
+
Other signatures of `.transform()` method support up to 4 transducers and
|
|
173
|
+
composes them automatically.
|
|
173
174
|
|
|
174
175
|
## Support packages
|
|
175
176
|
|
|
@@ -214,7 +215,7 @@ For Node.js REPL:
|
|
|
214
215
|
const rs = await import("@thi.ng/rstream");
|
|
215
216
|
```
|
|
216
217
|
|
|
217
|
-
Package sizes (brotli'd, pre-treeshake): ESM: 6.
|
|
218
|
+
Package sizes (brotli'd, pre-treeshake): ESM: 6.28 KB
|
|
218
219
|
|
|
219
220
|
## Dependencies
|
|
220
221
|
|
|
@@ -299,40 +300,40 @@ directory are using this package:
|
|
|
299
300
|
|
|
300
301
|
### Common configuration options
|
|
301
302
|
|
|
302
|
-
Since version 3.0.0 all stream and subscription factory functions take
|
|
303
|
-
|
|
304
|
-
(
|
|
303
|
+
Since version 3.0.0 all stream and subscription factory functions take an
|
|
304
|
+
optional object of [common configuration
|
|
305
|
+
options](https://docs.thi.ng/umbrella/rstream/interfaces/CommonOpts.html) with
|
|
306
|
+
**at least** these keys (each optional):
|
|
305
307
|
|
|
306
308
|
```ts
|
|
307
309
|
interface CommonOpts {
|
|
308
310
|
/**
|
|
309
|
-
* Internal ID associated with this stream. If omitted, an
|
|
310
|
-
*
|
|
311
|
+
* Internal ID associated with this stream. If omitted, an autogenerated ID
|
|
312
|
+
* will be used.
|
|
311
313
|
*/
|
|
312
314
|
id: string;
|
|
313
315
|
/**
|
|
314
|
-
* If false or `
|
|
315
|
-
*
|
|
316
|
-
*
|
|
317
|
-
*
|
|
316
|
+
* If false or `"never"`, the stream stays active even if all inputs are
|
|
317
|
+
* done. If true (default) or `"last"`, the stream closes when the last
|
|
318
|
+
* input is done. If `"first"`, the instance closes when the first input is
|
|
319
|
+
* done.
|
|
318
320
|
*
|
|
319
|
-
* @defaultValue
|
|
321
|
+
* @defaultValue "last"
|
|
320
322
|
*/
|
|
321
323
|
closeIn: CloseMode;
|
|
322
324
|
/**
|
|
323
|
-
* If false or `
|
|
324
|
-
*
|
|
325
|
-
*
|
|
326
|
-
*
|
|
327
|
-
* disconnects.
|
|
325
|
+
* If false or `"never"`, the stream stays active once there are no more
|
|
326
|
+
* subscribers. If true (default) or `"last"`, the stream closes when the
|
|
327
|
+
* last subscriber has unsubscribed. If `"first"`, the instance closes when
|
|
328
|
+
* the first subscriber disconnects.
|
|
328
329
|
*
|
|
329
|
-
* @defaultValue
|
|
330
|
+
* @defaultValue "last"
|
|
330
331
|
*/
|
|
331
332
|
closeOut: CloseMode;
|
|
332
333
|
/**
|
|
333
|
-
* If true (default), stream caches last received value and pushes
|
|
334
|
-
*
|
|
335
|
-
*
|
|
334
|
+
* If true (default), stream caches last received value and pushes it to new
|
|
335
|
+
* subscriberswhen they subscribe. If false, calling `.deref()` on this
|
|
336
|
+
* stream will always return `undefined`.
|
|
336
337
|
*
|
|
337
338
|
* @defaultValue true
|
|
338
339
|
*/
|
|
@@ -346,17 +347,16 @@ interface CommonOpts {
|
|
|
346
347
|
|
|
347
348
|
Docs: [stream()](https://docs.thi.ng/umbrella/rstream/functions/stream-1.html)
|
|
348
349
|
|
|
349
|
-
Creates a new `Stream` instance, optionally with given `StreamSource`
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
should call `stream.next()` to cause value propagation.
|
|
350
|
+
Creates a new `Stream` instance, optionally with given `StreamSource` function
|
|
351
|
+
and / or ID. If a `src` function is provided, the function will be only called
|
|
352
|
+
(with the `Stream` instance as single argument) once the first subscriber has
|
|
353
|
+
attached to the stream. If the function returns another function, it will be
|
|
354
|
+
used for cleanup purposes if the stream is cancelled, e.g. if the last
|
|
355
|
+
subscriber has unsubscribed. Streams are intended as (primarily async) data
|
|
356
|
+
sources in a dataflow graph and are the primary construct for the various
|
|
357
|
+
`from*()` functions provided by the package. However, streams can also be
|
|
358
|
+
triggered manually (from outside the stream), in which case the user should call
|
|
359
|
+
`stream.next()` to cause value propagation.
|
|
360
360
|
|
|
361
361
|
```ts
|
|
362
362
|
import { stream, trace } from "@thi.ng/rstream";
|
|
@@ -387,36 +387,33 @@ b.next(42);
|
|
|
387
387
|
|
|
388
388
|
### IDeref support
|
|
389
389
|
|
|
390
|
-
`Stream` (like all other types of `Subscription`) implements the
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
stream has not yet emitted a value or if the stream is already done, it
|
|
398
|
-
will deref to `undefined`.
|
|
390
|
+
`Stream` (like all other types of `Subscription`) implements the [@thi.ng/api
|
|
391
|
+
`IDeref`](https://docs.thi.ng/umbrella/api/interfaces/IDeref.html) interface
|
|
392
|
+
which provides read access to a stream's last received value. This is useful for
|
|
393
|
+
various purposes, e.g. in combination with @thi.ng/hdom, which supports direct
|
|
394
|
+
embedding of streams (i.e. their values) into UI components (and will be deref'd
|
|
395
|
+
automatically). If the stream has not yet emitted a value or if the stream is
|
|
396
|
+
already done, it will deref to `undefined`.
|
|
399
397
|
|
|
400
|
-
Furthermore, all subscription types can be configured (via the `cache`
|
|
401
|
-
|
|
402
|
-
|
|
398
|
+
Furthermore, all subscription types can be configured (via the `cache` option)
|
|
399
|
+
to NOT retain their last emitted value, in which case `.deref()` will always
|
|
400
|
+
return `undefined`.
|
|
403
401
|
|
|
404
402
|
#### Subscription
|
|
405
403
|
|
|
406
404
|
Docs: [subscription()](https://docs.thi.ng/umbrella/rstream/functions/subscription-1.html)
|
|
407
405
|
|
|
408
|
-
Creates a new `Subscription` instance, the fundamental datatype &
|
|
409
|
-
|
|
410
|
-
|
|
406
|
+
Creates a new `Subscription` instance, the fundamental datatype & building block
|
|
407
|
+
provided by this package (`Stream`s are `Subscription`s too). Subscriptions can
|
|
408
|
+
be:
|
|
411
409
|
|
|
412
410
|
- linked into directed graphs (if async, not necessarily DAGs)
|
|
413
411
|
- transformed using transducers (incl. early termination)
|
|
414
|
-
- can have any number of subscribers (optionally each w/ their own
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
has an error handler itself
|
|
412
|
+
- can have any number of subscribers (optionally each w/ their own transducer)
|
|
413
|
+
- recursively unsubscribe themselves from parent after their last subscriber
|
|
414
|
+
unsubscribed
|
|
415
|
+
- will go into a non-recoverable error state if NONE of the subscribers has an
|
|
416
|
+
error handler itself
|
|
420
417
|
- implement the @thi.ng/api `IDeref` interface
|
|
421
418
|
|
|
422
419
|
```ts
|
|
@@ -462,24 +459,22 @@ s.next(42);
|
|
|
462
459
|
|
|
463
460
|
Docs: [metaStream()](https://docs.thi.ng/umbrella/rstream/functions/metaStream-1.html)
|
|
464
461
|
|
|
465
|
-
`MetaStream`s are streams of streams. A `MetaStream` is a subscription
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
(acts like a `filter` transducer, i.e. the incoming value is simply
|
|
482
|
-
ignored).
|
|
462
|
+
`MetaStream`s are streams of streams. A `MetaStream` is a subscription type
|
|
463
|
+
which transforms each incoming value into a new stream, subscribes to it (via an
|
|
464
|
+
hidden / internal subscription) and then only passes values from that stream to
|
|
465
|
+
its own subscribers. If a new value is received, the meta stream first
|
|
466
|
+
unsubscribes from the possibly still active stream created from the previous
|
|
467
|
+
input, before creating and subscribing to the new stream. Hence this stream type
|
|
468
|
+
is useful for cases where streams need to be dynamically and invisibly created &
|
|
469
|
+
inserted into an existing dataflow topology without changing it, and with the
|
|
470
|
+
guarantee that never more than one of these is active at the same time. Similar
|
|
471
|
+
behavior (without the restriction in number) can be achieved using `merge()`
|
|
472
|
+
(see further below).
|
|
473
|
+
|
|
474
|
+
The user supplied `factory` function will be called for each incoming value and
|
|
475
|
+
is responsible for creating the new stream instances. If the function returns
|
|
476
|
+
`null` / `undefined`, no further action will be taken (acts like a `filter`
|
|
477
|
+
transducer, i.e. the incoming value is simply ignored).
|
|
483
478
|
|
|
484
479
|
```ts
|
|
485
480
|
import { metastream, fromIterable, trace } from "@thi.ng/rstream";
|
|
@@ -509,28 +504,27 @@ a.next(43)
|
|
|
509
504
|
// odd: 43
|
|
510
505
|
```
|
|
511
506
|
|
|
512
|
-
The factory function does NOT need to create new streams, but too can
|
|
513
|
-
|
|
514
|
-
|
|
507
|
+
The factory function does NOT need to create new streams, but too can merely
|
|
508
|
+
return other existing streams, and so making the meta stream act like a switch /
|
|
509
|
+
stream selector.
|
|
515
510
|
|
|
516
|
-
If the meta stream is the only subscriber to these input streams, you'll
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
them.
|
|
511
|
+
If the meta stream is the only subscriber to these input streams, you'll need to
|
|
512
|
+
use the `closeOut: "never"` option when creating the inputs. This keeps them
|
|
513
|
+
alive and allows for dynamic switching between them.
|
|
520
514
|
|
|
521
515
|
```ts
|
|
522
|
-
import { metastream, fromIterable, trace
|
|
516
|
+
import { metastream, fromIterable, trace } from "@thi.ng/rstream";
|
|
523
517
|
import { repeat } from "@thi.ng/transducers";
|
|
524
518
|
|
|
525
519
|
// infinite inputs
|
|
526
520
|
a = fromIterable(
|
|
527
521
|
repeat("a"),
|
|
528
|
-
{ delay: 1000, closeOut:
|
|
522
|
+
{ delay: 1000, closeOut: "never" }
|
|
529
523
|
);
|
|
530
524
|
|
|
531
525
|
b = fromIterable(
|
|
532
526
|
repeat("b"),
|
|
533
|
-
{ delay: 1000, closeOut:
|
|
527
|
+
{ delay: 1000, closeOut: "never" }
|
|
534
528
|
);
|
|
535
529
|
|
|
536
530
|
// stream selector / switch
|
|
@@ -555,12 +549,12 @@ Docs: [merge()](https://docs.thi.ng/umbrella/rstream/functions/merge.html)
|
|
|
555
549
|
|
|
556
550
|

|
|
557
551
|
|
|
558
|
-
Returns a new `StreamMerge` instance, a subscription type consuming
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
552
|
+
Returns a new `StreamMerge` instance, a subscription type consuming inputs from
|
|
553
|
+
multiple inputs and passing received values on to any subscribers. Input streams
|
|
554
|
+
can be added and removed dynamically. By default, `StreamMerge` calls `done()`
|
|
555
|
+
when the last active input is done, but this behavior can be overridden via the
|
|
556
|
+
[`closeIn`
|
|
557
|
+
option](https://docs.thi.ng/umbrella/rstream/interfaces/StreamMergeOpts.html#closeIn).
|
|
564
558
|
|
|
565
559
|
```ts
|
|
566
560
|
import { merge, fromIterable, trace } from "@thi.ng/rstream";
|
|
@@ -612,10 +606,9 @@ for further reference of the various behavior options.
|
|
|
612
606
|
|
|
613
607
|
##### Adding inputs automatically
|
|
614
608
|
|
|
615
|
-
If the `StreamMerge` receives a `Subscription`-like value from any of
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
is exhausted.
|
|
609
|
+
If the `StreamMerge` receives a `Subscription`-like value from any of its
|
|
610
|
+
inputs, it will not be processed as usual, but instead will be added as new
|
|
611
|
+
input to the merge and then automatically remove once that stream is exhausted.
|
|
619
612
|
|
|
620
613
|
```ts
|
|
621
614
|
import { merge, stream, fromIterable, trace } from "@thi.ng/rstream";
|
|
@@ -647,24 +640,24 @@ Docs: [sync()](https://docs.thi.ng/umbrella/rstream/functions/sync.html)
|
|
|
647
640
|
|
|
648
641
|

|
|
649
642
|
|
|
650
|
-
Similar to `StreamMerge` above, but with extra synchronization of
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
643
|
+
Similar to `StreamMerge` above, but with extra synchronization of inputs. Before
|
|
644
|
+
emitting any new values, `StreamSync` collects values until at least one has
|
|
645
|
+
been received from _all_ inputs. Once that's the case, the collected values are
|
|
646
|
+
sent as labeled tuple object to downstream subscribers. Each value in the
|
|
647
|
+
emitted tuple objects is stored under their input stream's ID. Only the last
|
|
648
|
+
value received from each input is passed on. After the initial tuple has been
|
|
649
|
+
emitted, you can choose from two possible behaviors:
|
|
650
|
+
|
|
651
|
+
1. Any future change in any input will produce a new result tuple. These tuples
|
|
652
|
+
will retain the most recently read values from other inputs. This behavior is
|
|
653
|
+
the default and illustrated in the above schematic.
|
|
654
|
+
2. If the `reset` option is `true`, every input will have to provide at least
|
|
655
|
+
one new value again until another result tuple is produced.
|
|
656
|
+
|
|
657
|
+
Any done inputs are automatically removed. By default, `StreamSync` calls
|
|
658
|
+
`done()` when the last active input is done, but this behavior can be overridden
|
|
659
|
+
via the [`closeIn`
|
|
660
|
+
option](https://docs.thi.ng/umbrella/rstream/interfaces/StreamMergeOpts.html#closeIn).
|
|
668
661
|
|
|
669
662
|
```ts
|
|
670
663
|
import { sync, stream, trace } from "@thi.ng/rstream";
|
|
@@ -677,13 +670,13 @@ b.next(2);
|
|
|
677
670
|
// result: { a: 1, b: 2 }
|
|
678
671
|
```
|
|
679
672
|
|
|
680
|
-
Input streams can be added and removed dynamically and the emitted tuple
|
|
681
|
-
|
|
682
|
-
|
|
673
|
+
Input streams can be added and removed dynamically and the emitted tuple size
|
|
674
|
+
adjusts to the current number of inputs (the next time a value is received from
|
|
675
|
+
any input).
|
|
683
676
|
|
|
684
|
-
If the `reset` option is enabled, the last emitted tuple is allowed to
|
|
685
|
-
|
|
686
|
-
|
|
677
|
+
If the `reset` option is enabled, the last emitted tuple is allowed to be
|
|
678
|
+
incomplete, by default. To only allow complete tuples, also set the `all` option
|
|
679
|
+
to `false`.
|
|
687
680
|
|
|
688
681
|
The synchronization is done via the
|
|
689
682
|
[`partitionSync()`](https://docs.thi.ng/umbrella/transducers/functions/partitionSync-1.html)
|
|
@@ -703,32 +696,30 @@ Docs: [pubsub()](https://docs.thi.ng/umbrella/rstream/functions/pubsub-1.html)
|
|
|
703
696
|
|
|
704
697
|

|
|
705
698
|
|
|
706
|
-
Topic based stream splitter. Applies `topic` function to each
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
Each topic can have any number of subscribers.
|
|
699
|
+
Topic based stream splitter. Applies `topic` function to each received value and
|
|
700
|
+
only forwards it to child subscriptions for returned topic. The actual topic
|
|
701
|
+
(return value from `topic` fn) can be of any type, apart from `undefined`.
|
|
702
|
+
Complex topics (e.g objects / arrays) are allowed and they're matched with
|
|
703
|
+
registered topics using @thi.ng/equiv by default (but customizable via `equiv`
|
|
704
|
+
option). Each topic can have any number of subscribers.
|
|
713
705
|
|
|
714
|
-
If a transducer is specified for the `PubSub`, it is always applied
|
|
715
|
-
|
|
716
|
-
|
|
706
|
+
If a transducer is specified for the `PubSub`, it is always applied prior to
|
|
707
|
+
passing the input to the topic function. I.e. in this case the topic function
|
|
708
|
+
will receive the transformed inputs.
|
|
717
709
|
|
|
718
710
|
PubSub supports dynamic topic subscriptions and unsubscriptions via
|
|
719
711
|
`subscribeTopic()` and `unsubscribeTopic()`. However, **the standard
|
|
720
|
-
`subscribe()` / `unsubscribe()` methods are NOT supported** (since
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
712
|
+
`subscribe()` / `unsubscribe()` methods are NOT supported** (since meaningless
|
|
713
|
+
here) and will throw an error! `unsubscribe()` can only be called WITHOUT
|
|
714
|
+
argument to unsubscribe the entire `PubSub` instance (incl. all topic
|
|
715
|
+
subscriptions) from the parent stream.
|
|
724
716
|
|
|
725
717
|
#### Splitting via predicate
|
|
726
718
|
|
|
727
719
|
Docs: [bisect()](https://docs.thi.ng/umbrella/rstream/functions/bisect.html)
|
|
728
720
|
|
|
729
|
-
Returns a new `PubSub` instance using given predicate `pred` as boolean
|
|
730
|
-
|
|
731
|
-
`b` values.
|
|
721
|
+
Returns a new `PubSub` instance using given predicate `pred` as boolean topic
|
|
722
|
+
function and `a` & `b` as subscribers for truthy (`a`) and falsy `b` values.
|
|
732
723
|
|
|
733
724
|
```ts
|
|
734
725
|
import { bisect, fromIterable, trace } from "@thi.ng/rstream";
|
|
@@ -744,9 +735,9 @@ fromIterable([1, 2, 3, 4]).subscribe(
|
|
|
744
735
|
// even done
|
|
745
736
|
```
|
|
746
737
|
|
|
747
|
-
If `a` or `b` need to be subscribed to directly, then `a` / `b` MUST be
|
|
748
|
-
|
|
749
|
-
|
|
738
|
+
If `a` or `b` need to be subscribed to directly, then `a` / `b` MUST be first
|
|
739
|
+
created as `Subscription` (if not already) and a reference kept prior to calling
|
|
740
|
+
`bisect()`.
|
|
750
741
|
|
|
751
742
|
```ts
|
|
752
743
|
import { bisect, fromIterable, subscription, trace } from "@thi.ng/rstream";
|
|
@@ -777,11 +768,10 @@ Docs: [sidechainPartition()](https://docs.thi.ng/umbrella/rstream/functions/side
|
|
|
777
768
|
|
|
778
769
|

|
|
779
770
|
|
|
780
|
-
Buffers values from `src` until side chain fires, then emits buffer
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
conditions.
|
|
771
|
+
Buffers values from `src` until side chain fires, then emits buffer (unless
|
|
772
|
+
empty) and repeats process until either input is done. By default, the value
|
|
773
|
+
read from the side chain is ignored, however the optional predicate can be used
|
|
774
|
+
to only trigger for specific values / conditions.
|
|
785
775
|
|
|
786
776
|
```ts
|
|
787
777
|
import {
|
|
@@ -825,12 +815,11 @@ Docs: [sidechainToggle()](https://docs.thi.ng/umbrella/rstream/functions/sidecha
|
|
|
825
815
|
|
|
826
816
|

|
|
827
817
|
|
|
828
|
-
Filters values from input based on values received from side chain. By
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
forwarded.
|
|
818
|
+
Filters values from input based on values received from side chain. By default,
|
|
819
|
+
the value read from the side chain is ignored, however the optional predicate
|
|
820
|
+
can be used to only trigger for specific values/conditions. Every time the
|
|
821
|
+
predicate fn returns true, the filter will be toggled on/off. Whilst switched
|
|
822
|
+
off, no input values will be forwarded.
|
|
834
823
|
|
|
835
824
|
```ts
|
|
836
825
|
import { sidechainToggle, fromInterval, trace } from "@thi.ng/rstream";
|
|
@@ -934,9 +923,9 @@ src.next(new Array(16).fill(1));
|
|
|
934
923
|
|
|
935
924
|
Docs: [tunnel()](https://docs.thi.ng/umbrella/rstream/functions/tunnel-1.html)
|
|
936
925
|
|
|
937
|
-
Delegate stream value processing to workers and pass on their responses
|
|
938
|
-
|
|
939
|
-
|
|
926
|
+
Delegate stream value processing to workers and pass on their responses to
|
|
927
|
+
downstream subscriptions. Supports multiple worker instances and worker
|
|
928
|
+
termination / restart for each new stream value received.
|
|
940
929
|
|
|
941
930
|
Docs: [postWorker()](https://docs.thi.ng/umbrella/rstream/functions/postWorker.html)
|
|
942
931
|
|
|
@@ -962,8 +951,8 @@ be found in [this issue](https://github.com/thi-ng/umbrella/issues/281)**
|
|
|
962
951
|
The `ISubscriber` interface supports optional error handlers which will be
|
|
963
952
|
called if code in the `next()` or `done()` handlers throws an error. If no error
|
|
964
953
|
handler is defined for a subscriber, the wrapping `Subscription`'s own error
|
|
965
|
-
handler will be called, which _might_ put this subscription into an error
|
|
966
|
-
|
|
954
|
+
handler will be called, which _might_ put this subscription into an error state
|
|
955
|
+
and stop it from receiving new values.
|
|
967
956
|
|
|
968
957
|
```ts
|
|
969
958
|
import { subscription, State } from "@thi.ng/rstream";
|
package/api.d.ts
CHANGED
|
@@ -9,54 +9,44 @@ export declare enum State {
|
|
|
9
9
|
ERROR = 4
|
|
10
10
|
}
|
|
11
11
|
/**
|
|
12
|
-
* Closing behaviors
|
|
12
|
+
* Closing behaviors:
|
|
13
|
+
*
|
|
14
|
+
* - Close when first input/output is done / removed
|
|
15
|
+
* - Close when last input/output is done / removed
|
|
16
|
+
* - Never close, even if no more inputs/outputs
|
|
13
17
|
*/
|
|
14
|
-
export
|
|
15
|
-
/**
|
|
16
|
-
* Never close, even if no more inputs/outputs.
|
|
17
|
-
*/
|
|
18
|
-
NEVER = 0,
|
|
19
|
-
/**
|
|
20
|
-
* Close when first input/output is done / removed.
|
|
21
|
-
*/
|
|
22
|
-
FIRST = 1,
|
|
23
|
-
/**
|
|
24
|
-
* Close when last input/output is done / removed.
|
|
25
|
-
*/
|
|
26
|
-
LAST = 2
|
|
27
|
-
}
|
|
18
|
+
export type CloseMode = "first" | "last" | "never";
|
|
28
19
|
/**
|
|
29
20
|
* Common base options for all stream / subscription types.
|
|
30
21
|
*/
|
|
31
22
|
export interface CommonOpts {
|
|
32
23
|
/**
|
|
33
|
-
* Internal ID associated with this stream. If omitted, an
|
|
34
|
-
*
|
|
24
|
+
* Internal ID associated with this stream. If omitted, an autogenerated ID
|
|
25
|
+
* will be used.
|
|
35
26
|
*/
|
|
36
27
|
id: string;
|
|
37
28
|
/**
|
|
38
|
-
* If false or `
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
29
|
+
* If false or `"never"`, the stream stays active even if all inputs are
|
|
30
|
+
* done. If true (default) or `"last"`, the stream closes when the last
|
|
31
|
+
* input is done. If `"first"`, the instance closes when the first input is
|
|
32
|
+
* done.
|
|
42
33
|
*
|
|
43
|
-
* @defaultValue
|
|
34
|
+
* @defaultValue "last"
|
|
44
35
|
*/
|
|
45
36
|
closeIn: CloseMode;
|
|
46
37
|
/**
|
|
47
|
-
* If false or `
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
* disconnects.
|
|
38
|
+
* If false or `"never"`, the stream stays active once there are no more
|
|
39
|
+
* subscribers. If true (default) or `"last"`, the stream closes when the
|
|
40
|
+
* last subscriber has unsubscribed. If `"first"`, the instance closes when
|
|
41
|
+
* the first subscriber disconnects.
|
|
52
42
|
*
|
|
53
|
-
* @defaultValue
|
|
43
|
+
* @defaultValue "last"
|
|
54
44
|
*/
|
|
55
45
|
closeOut: CloseMode;
|
|
56
46
|
/**
|
|
57
|
-
* If true (default), stream caches last received value and pushes
|
|
58
|
-
*
|
|
59
|
-
*
|
|
47
|
+
* If true (default), stream caches last received value and pushes it to new
|
|
48
|
+
* subscriberswhen they subscribe. If false, calling `.deref()` on this
|
|
49
|
+
* stream will always return `undefined`.
|
|
60
50
|
*
|
|
61
51
|
* @defaultValue true
|
|
62
52
|
*/
|
|
@@ -64,9 +54,8 @@ export interface CommonOpts {
|
|
|
64
54
|
}
|
|
65
55
|
export interface WithTransform<A, B> {
|
|
66
56
|
/**
|
|
67
|
-
* Transducer to transform incoming stream values. If given, all
|
|
68
|
-
*
|
|
69
|
-
* values.
|
|
57
|
+
* Transducer to transform incoming stream values. If given, all child
|
|
58
|
+
* subscriptions will only receive the transformed result values.
|
|
70
59
|
*/
|
|
71
60
|
xform: Transducer<A, B>;
|
|
72
61
|
}
|
package/api.js
CHANGED
|
@@ -6,13 +6,6 @@ var State = /* @__PURE__ */ ((State2) => {
|
|
|
6
6
|
State2[State2["ERROR"] = 4] = "ERROR";
|
|
7
7
|
return State2;
|
|
8
8
|
})(State || {});
|
|
9
|
-
var CloseMode = /* @__PURE__ */ ((CloseMode2) => {
|
|
10
|
-
CloseMode2[CloseMode2["NEVER"] = 0] = "NEVER";
|
|
11
|
-
CloseMode2[CloseMode2["FIRST"] = 1] = "FIRST";
|
|
12
|
-
CloseMode2[CloseMode2["LAST"] = 2] = "LAST";
|
|
13
|
-
return CloseMode2;
|
|
14
|
-
})(CloseMode || {});
|
|
15
9
|
export {
|
|
16
|
-
CloseMode,
|
|
17
10
|
State
|
|
18
11
|
};
|
package/checks.d.ts
CHANGED
package/checks.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { implementsFunction } from "@thi.ng/checks/implements-function";
|
|
2
|
-
import { CloseMode } from "./api.js";
|
|
3
2
|
const isSubscribable = (x) => implementsFunction(x, "subscribe");
|
|
4
|
-
const isFirstOrLastInput = (mode, num) => mode ===
|
|
3
|
+
const isFirstOrLastInput = (mode, num) => mode === "first" || mode === "last" && !num;
|
|
5
4
|
export {
|
|
6
5
|
isFirstOrLastInput,
|
|
7
6
|
isSubscribable
|
package/interval.d.ts
CHANGED
package/interval.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { CloseMode } from "./api.js";
|
|
2
1
|
import { __optsWithID } from "./idgen.js";
|
|
3
2
|
import { stream } from "./stream.js";
|
|
4
3
|
const fromInterval = (delay, opts) => {
|
|
@@ -14,7 +13,7 @@ const fromInterval = (delay, opts) => {
|
|
|
14
13
|
stream2.next(i++);
|
|
15
14
|
if (--count <= 0) {
|
|
16
15
|
clearInterval(id);
|
|
17
|
-
stream2.closeIn !==
|
|
16
|
+
stream2.closeIn !== "never" && stream2.done();
|
|
18
17
|
}
|
|
19
18
|
}, delay);
|
|
20
19
|
return () => clearInterval(id);
|
package/iterable.d.ts
CHANGED
package/iterable.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { CloseMode } from "./api.js";
|
|
2
1
|
import { __optsWithID } from "./idgen.js";
|
|
3
2
|
import { stream } from "./stream.js";
|
|
4
3
|
const fromIterable = (src, opts = {}) => stream((stream2) => {
|
|
@@ -7,7 +6,7 @@ const fromIterable = (src, opts = {}) => stream((stream2) => {
|
|
|
7
6
|
let val;
|
|
8
7
|
if ((val = iter.next()).done) {
|
|
9
8
|
clearInterval(id);
|
|
10
|
-
stream2.closeIn !==
|
|
9
|
+
stream2.closeIn !== "never" && stream2.done();
|
|
11
10
|
} else {
|
|
12
11
|
stream2.next(val.value);
|
|
13
12
|
}
|
|
@@ -18,7 +17,7 @@ const fromIterableSync = (src, opts) => stream((stream2) => {
|
|
|
18
17
|
for (let s of src) {
|
|
19
18
|
stream2.next(s);
|
|
20
19
|
}
|
|
21
|
-
stream2.closeIn !==
|
|
20
|
+
stream2.closeIn !== "never" && stream2.done();
|
|
22
21
|
}, __optsWithID("iterable-sync", opts));
|
|
23
22
|
export {
|
|
24
23
|
fromIterable,
|
package/metastream.d.ts
CHANGED
|
@@ -66,17 +66,17 @@ export interface MetaStreamOpts extends CommonOpts {
|
|
|
66
66
|
*
|
|
67
67
|
* @example
|
|
68
68
|
* ```ts tangle:../export/metastream-2.ts
|
|
69
|
-
* import {
|
|
69
|
+
* import { fromIterable, metaStream, trace } from "@thi.ng/rstream";
|
|
70
70
|
* import { cycle, repeat } from "@thi.ng/transducers";
|
|
71
71
|
*
|
|
72
|
-
* // infinite inputs (important: closeOut mode = never!)
|
|
72
|
+
* // infinite inputs (important: closeOut mode = "never"!)
|
|
73
73
|
* const a = fromIterable(
|
|
74
74
|
* repeat("a"),
|
|
75
|
-
* { delay: 100, closeOut:
|
|
75
|
+
* { delay: 100, closeOut: "never" }
|
|
76
76
|
* );
|
|
77
77
|
* const b = fromIterable(
|
|
78
78
|
* repeat("b"),
|
|
79
|
-
* { delay: 100, closeOut:
|
|
79
|
+
* { delay: 100, closeOut: "never" }
|
|
80
80
|
* );
|
|
81
81
|
*
|
|
82
82
|
* // stream selector / switch
|
package/metastream.js
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import { assert } from "@thi.ng/errors/assert";
|
|
2
|
-
import {
|
|
3
|
-
CloseMode,
|
|
4
|
-
State
|
|
5
|
-
} from "./api.js";
|
|
2
|
+
import { State } from "./api.js";
|
|
6
3
|
import { __optsWithID } from "./idgen.js";
|
|
7
4
|
import { Subscription } from "./subscription.js";
|
|
8
5
|
const metaStream = (factory, opts) => new MetaStream(factory, opts);
|
|
@@ -51,7 +48,7 @@ class MetaStream extends Subscription {
|
|
|
51
48
|
if (this.stream) {
|
|
52
49
|
this.detach(true);
|
|
53
50
|
}
|
|
54
|
-
this.closeIn !==
|
|
51
|
+
this.closeIn !== "never" && super.done();
|
|
55
52
|
}
|
|
56
53
|
}
|
|
57
54
|
unsubscribe(sub) {
|
|
@@ -61,7 +58,7 @@ class MetaStream extends Subscription {
|
|
|
61
58
|
return super.unsubscribe(sub);
|
|
62
59
|
}
|
|
63
60
|
detach(force) {
|
|
64
|
-
if (force || this.closeOut !==
|
|
61
|
+
if (force || this.closeOut !== "never") {
|
|
65
62
|
assert(!!this.stream, "input stream already removed");
|
|
66
63
|
this.stream.unsubscribe(this.sub);
|
|
67
64
|
delete this.stream;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thi.ng/rstream",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "9.0.0",
|
|
4
4
|
"description": "Reactive streams & subscription primitives for constructing dataflow graphs / pipelines",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./index.js",
|
|
@@ -219,5 +219,5 @@
|
|
|
219
219
|
],
|
|
220
220
|
"year": 2017
|
|
221
221
|
},
|
|
222
|
-
"gitHead": "
|
|
222
|
+
"gitHead": "bb5006182c335294b5c53abf39663d42445c4880\n"
|
|
223
223
|
}
|
package/promise.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { State } from "./api.js";
|
|
2
2
|
import { __optsWithID } from "./idgen.js";
|
|
3
3
|
import { stream } from "./stream.js";
|
|
4
4
|
const fromPromise = (src, opts) => {
|
|
@@ -18,7 +18,7 @@ const fromPromise = (src, opts) => {
|
|
|
18
18
|
err = null;
|
|
19
19
|
} else {
|
|
20
20
|
stream2.next(x);
|
|
21
|
-
stream2.closeIn !==
|
|
21
|
+
stream2.closeIn !== "never" && stream2.done();
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
},
|
package/pubsub.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Fn, Predicate2 } from "@thi.ng/api";
|
|
2
2
|
import { EquivMap } from "@thi.ng/associative/equiv-map";
|
|
3
3
|
import type { Transducer } from "@thi.ng/transducers";
|
|
4
|
-
import {
|
|
4
|
+
import type { ISubscriber, ISubscription, TransformableOpts, WithErrorHandlerOpts } from "./api.js";
|
|
5
5
|
import { Subscription } from "./subscription.js";
|
|
6
6
|
export interface PubSubOpts<A, B, T> {
|
|
7
7
|
/**
|
package/pubsub.js
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import { EquivMap } from "@thi.ng/associative/equiv-map";
|
|
2
2
|
import { unsupported } from "@thi.ng/errors/unsupported";
|
|
3
|
-
import {
|
|
4
|
-
CloseMode
|
|
5
|
-
} from "./api.js";
|
|
6
3
|
import { __optsWithID } from "./idgen.js";
|
|
7
4
|
import { LOGGER } from "./logger.js";
|
|
8
5
|
import { Subscription, subscription } from "./subscription.js";
|
|
@@ -40,9 +37,7 @@ class PubSub extends Subscription {
|
|
|
40
37
|
topicID,
|
|
41
38
|
t = subscription(
|
|
42
39
|
void 0,
|
|
43
|
-
__optsWithID("topic", {
|
|
44
|
-
closeOut: CloseMode.NEVER
|
|
45
|
-
})
|
|
40
|
+
__optsWithID("topic", { closeOut: "never" })
|
|
46
41
|
)
|
|
47
42
|
);
|
|
48
43
|
return t.subscribe(sub, opts);
|
package/stream.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Maybe } from "@thi.ng/api";
|
|
2
|
-
import {
|
|
2
|
+
import type { CommonOpts, IStream, ISubscriber, ISubscription, StreamCancel, StreamSource, TransformableOpts, WithErrorHandlerOpts } from "./api.js";
|
|
3
3
|
import { Subscription } from "./subscription.js";
|
|
4
4
|
/**
|
|
5
5
|
* Creates a new {@link Stream} instance, optionally with given `StreamSource`
|
package/stream.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
import { isFunction } from "@thi.ng/checks/is-function";
|
|
2
|
-
import {
|
|
3
|
-
CloseMode
|
|
4
|
-
} from "./api.js";
|
|
5
2
|
import { __optsWithID } from "./idgen.js";
|
|
6
3
|
import { LOGGER } from "./logger.js";
|
|
7
4
|
import { Subscription } from "./subscription.js";
|
|
@@ -45,7 +42,7 @@ class Stream extends Subscription {
|
|
|
45
42
|
}
|
|
46
43
|
unsubscribe(sub) {
|
|
47
44
|
const res = super.unsubscribe(sub);
|
|
48
|
-
if (res && (!sub || (!this.subs || !this.subs.length) && this.closeOut !==
|
|
45
|
+
if (res && (!sub || (!this.subs || !this.subs.length) && this.closeOut !== "never")) {
|
|
49
46
|
this.cancel();
|
|
50
47
|
}
|
|
51
48
|
return res;
|
package/subscription.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Fn, Maybe } from "@thi.ng/api";
|
|
2
2
|
import type { Reduced, Reducer, Transducer } from "@thi.ng/transducers";
|
|
3
|
-
import {
|
|
3
|
+
import { State, type CloseMode, type CommonOpts, type ISubscriber, type ISubscription, type SubscriptionOpts, type TransformableOpts, type WithErrorHandlerOpts, type WithTransform } from "./api.js";
|
|
4
4
|
/**
|
|
5
5
|
* Creates a new {@link Subscription} instance, the fundamental datatype and
|
|
6
6
|
* building block provided by this package.
|
package/subscription.js
CHANGED
|
@@ -9,7 +9,6 @@ import { map } from "@thi.ng/transducers/map";
|
|
|
9
9
|
import { push } from "@thi.ng/transducers/push";
|
|
10
10
|
import { isReduced, unreduced } from "@thi.ng/transducers/reduced";
|
|
11
11
|
import {
|
|
12
|
-
CloseMode,
|
|
13
12
|
State
|
|
14
13
|
} from "./api.js";
|
|
15
14
|
import { __optsWithID } from "./idgen.js";
|
|
@@ -19,8 +18,8 @@ class Subscription {
|
|
|
19
18
|
constructor(wrapped, opts) {
|
|
20
19
|
this.wrapped = wrapped;
|
|
21
20
|
opts = __optsWithID(`sub`, {
|
|
22
|
-
closeIn:
|
|
23
|
-
closeOut:
|
|
21
|
+
closeIn: "last",
|
|
22
|
+
closeOut: "last",
|
|
24
23
|
cache: true,
|
|
25
24
|
...opts
|
|
26
25
|
});
|
|
@@ -113,7 +112,7 @@ class Subscription {
|
|
|
113
112
|
const idx = this.subs.indexOf(sub);
|
|
114
113
|
if (idx >= 0) {
|
|
115
114
|
this.subs.splice(idx, 1);
|
|
116
|
-
if (this.closeOut ===
|
|
115
|
+
if (this.closeOut === "first" || !this.subs.length && this.closeOut !== "never") {
|
|
117
116
|
this.unsubscribe();
|
|
118
117
|
}
|
|
119
118
|
return true;
|
|
@@ -209,7 +208,7 @@ class Subscription {
|
|
|
209
208
|
}
|
|
210
209
|
ensureState() {
|
|
211
210
|
if (this.state >= State.DONE) {
|
|
212
|
-
illegalState(`operation not allowed in state ${this.state}`);
|
|
211
|
+
illegalState(`operation not allowed in state ${State[this.state]}`);
|
|
213
212
|
}
|
|
214
213
|
}
|
|
215
214
|
release() {
|
package/tween.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Fn2 } from "@thi.ng/api";
|
|
2
|
-
import {
|
|
2
|
+
import type { ISubscribable } from "./api.js";
|
|
3
3
|
/**
|
|
4
4
|
* Takes an existing stream/subscription `src` and attaches new
|
|
5
5
|
* subscription which interpolates between incoming values from `src`
|
package/tween.js
CHANGED
|
@@ -2,7 +2,6 @@ import { isNumber } from "@thi.ng/checks/is-number";
|
|
|
2
2
|
import { dedupe } from "@thi.ng/transducers/dedupe";
|
|
3
3
|
import { reducer } from "@thi.ng/transducers/reduce";
|
|
4
4
|
import { scan } from "@thi.ng/transducers/scan";
|
|
5
|
-
import { CloseMode } from "./api.js";
|
|
6
5
|
import { fromInterval } from "./interval.js";
|
|
7
6
|
import { fromRAF } from "./raf.js";
|
|
8
7
|
import { sync } from "./sync.js";
|
|
@@ -11,7 +10,7 @@ const tween = (src, initial, mix, stop, clock) => sync({
|
|
|
11
10
|
src,
|
|
12
11
|
_: clock == null ? fromRAF() : isNumber(clock) ? fromInterval(clock) : clock
|
|
13
12
|
},
|
|
14
|
-
closeIn:
|
|
13
|
+
closeIn: "first"
|
|
15
14
|
}).transform(
|
|
16
15
|
scan(
|
|
17
16
|
reducer(
|