@soffinal/stream 0.2.0 → 0.2.1
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/README.md +141 -19
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +11 -11
- package/dist/reactive/list.d.ts +18 -0
- package/dist/reactive/list.d.ts.map +1 -1
- package/dist/reactive/map.d.ts +10 -0
- package/dist/reactive/map.d.ts.map +1 -1
- package/dist/reactive/set.d.ts +10 -0
- package/dist/reactive/set.d.ts.map +1 -1
- package/dist/reactive/state.d.ts +18 -18
- package/dist/reactive/state.d.ts.map +1 -1
- package/dist/stream.d.ts +93 -10
- package/dist/stream.d.ts.map +1 -1
- package/dist/transformers/filter.d.ts +3 -32
- package/dist/transformers/filter.d.ts.map +1 -1
- package/dist/transformers/flat.d.ts +2 -0
- package/dist/transformers/flat.d.ts.map +1 -1
- package/dist/transformers/map.d.ts +3 -31
- package/dist/transformers/map.d.ts.map +1 -1
- package/dist/transformers/merge.d.ts +2 -0
- package/dist/transformers/merge.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/transformers/filter.md +44 -3
- package/src/transformers/map.md +32 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/reactive/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC
|
|
1
|
+
{"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/reactive/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,qBAAa,IAAI,CAAC,KAAK,CAAE,YAAW,QAAQ,CAAC,KAAK,CAAC;IACjD,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,aAAa,CAAC,CAA0B;IAChD,OAAO,CAAC,aAAa,CAAC,CAA0B;IAChD,OAAO,CAAC,YAAY,CAAC,CAAe;IAEpC,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,CAAC;IAEnC;;;;;;;;;;;;;;OAcG;IACK,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;IAElF;;;;;;;;;;;;;;OAcG;IACK,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,KAAK,KAAK,GAAG,SAAS,CAAC,GAAG,MAAM,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;IAEjF;;;;;;;;;;;;;;OAcG;IACK,KAAK,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAE3C;;;;;;;;;;;;;;;;;;;;;;;OAuBG;gBACS,KAAK,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC;IAiGnC;;;;;;;;;;;;;;OAcG;IACH,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS;IAIrC;;;;;;;;;;;;;OAaG;IACH,IAAI,MAAM,IAAI,MAAM,CAEnB;IACD;;;;;;;;;;;;OAYG;IACH,MAAM,IAAI,gBAAgB,CAAC,KAAK,CAAC;IAGjC;;;;;;;;;;;;;;OAcG;IACH,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,gBAAgB,CAAC,KAAK,CAAC;CAG7C"}
|
package/dist/reactive/map.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ import { Stream } from "../stream.ts";
|
|
|
6
6
|
* @template KEY - The type of keys in the map
|
|
7
7
|
* @template VALUE - The type of values in the map
|
|
8
8
|
*
|
|
9
|
+
* @see {@link Stream} - Complete copy-paste transformers library
|
|
10
|
+
*
|
|
9
11
|
* @example
|
|
10
12
|
* ```typescript
|
|
11
13
|
* const cache = new Map<string, any>();
|
|
@@ -32,6 +34,8 @@ export declare class Map<KEY, VALUE> extends globalThis.Map<KEY, VALUE> {
|
|
|
32
34
|
* Sets a key-value pair in the map and emits the entry to listeners.
|
|
33
35
|
* Only emits if the value actually changes (not same key-value pair).
|
|
34
36
|
*
|
|
37
|
+
* @see {@link Stream} - Complete copy-paste transformers library
|
|
38
|
+
*
|
|
35
39
|
* @example
|
|
36
40
|
* ```typescript
|
|
37
41
|
* const config = new Map<string, string>();
|
|
@@ -47,6 +51,8 @@ export declare class Map<KEY, VALUE> extends globalThis.Map<KEY, VALUE> {
|
|
|
47
51
|
* Deletes a key from the map and emits the deleted entry to listeners.
|
|
48
52
|
* Only emits if the key was actually deleted (existed in map).
|
|
49
53
|
*
|
|
54
|
+
* @see {@link Stream} - Complete copy-paste transformers library
|
|
55
|
+
*
|
|
50
56
|
* @example
|
|
51
57
|
* ```typescript
|
|
52
58
|
* const users = new Map([['alice', { age: 30 }], ['bob', { age: 25 }]]);
|
|
@@ -61,6 +67,8 @@ export declare class Map<KEY, VALUE> extends globalThis.Map<KEY, VALUE> {
|
|
|
61
67
|
* Clears all entries from the map and emits to listeners.
|
|
62
68
|
* Only emits if the map was not already empty.
|
|
63
69
|
*
|
|
70
|
+
* @see {@link Stream} - Complete copy-paste transformers library
|
|
71
|
+
*
|
|
64
72
|
* @example
|
|
65
73
|
* ```typescript
|
|
66
74
|
* const store = new Map([['a', 1], ['b', 2]]);
|
|
@@ -76,6 +84,8 @@ export declare class Map<KEY, VALUE> extends globalThis.Map<KEY, VALUE> {
|
|
|
76
84
|
*
|
|
77
85
|
* @param entries - Optional iterable of initial key-value pairs
|
|
78
86
|
*
|
|
87
|
+
* @see {@link Stream} - Complete copy-paste transformers library
|
|
88
|
+
*
|
|
79
89
|
* @example
|
|
80
90
|
* ```typescript
|
|
81
91
|
* // Empty map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"map.d.ts","sourceRoot":"","sources":["../../src/reactive/map.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC
|
|
1
|
+
{"version":3,"file":"map.d.ts","sourceRoot":"","sources":["../../src/reactive/map.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBAAa,GAAG,CAAC,GAAG,EAAE,KAAK,CAAE,SAAQ,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC;IAC7D,SAAS,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;IAC5C,SAAS,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;IAC/C,SAAS,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;IAEtC;;;;;;;;;;;;;;;OAeG;IACK,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;IAEvE;;;;;;;;;;;;;;OAcG;IACK,MAAM,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;IAE/D;;;;;;;;;;;;;;OAcG;IACK,KAAK,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAE3C;;;;;;;;;;;;;;;;;;;;;;OAsBG;gBACS,OAAO,CAAC,EAAE,QAAQ,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;CAuD7C"}
|
package/dist/reactive/set.d.ts
CHANGED
|
@@ -5,6 +5,8 @@ import { Stream } from "../stream.ts";
|
|
|
5
5
|
*
|
|
6
6
|
* @template VALUE - The type of values stored in the set
|
|
7
7
|
*
|
|
8
|
+
* @see {@link Stream} - Complete copy-paste transformers library
|
|
9
|
+
*
|
|
8
10
|
* @example
|
|
9
11
|
* ```typescript
|
|
10
12
|
* const activeUsers = new Set<string>();
|
|
@@ -31,6 +33,8 @@ export declare class Set<VALUE> extends globalThis.Set<VALUE> {
|
|
|
31
33
|
* Adds a value to the set and emits the value to listeners.
|
|
32
34
|
* Only emits if the value is actually added (not a duplicate).
|
|
33
35
|
*
|
|
36
|
+
* @see {@link Stream} - Complete copy-paste transformers library
|
|
37
|
+
*
|
|
34
38
|
* @example
|
|
35
39
|
* ```typescript
|
|
36
40
|
* const tags = new Set<string>();
|
|
@@ -45,6 +49,8 @@ export declare class Set<VALUE> extends globalThis.Set<VALUE> {
|
|
|
45
49
|
* Deletes a value from the set and emits the value to listeners.
|
|
46
50
|
* Only emits if the value was actually deleted (existed in set).
|
|
47
51
|
*
|
|
52
|
+
* @see {@link Stream} - Complete copy-paste transformers library
|
|
53
|
+
*
|
|
48
54
|
* @example
|
|
49
55
|
* ```typescript
|
|
50
56
|
* const items = new Set(['a', 'b', 'c']);
|
|
@@ -59,6 +65,8 @@ export declare class Set<VALUE> extends globalThis.Set<VALUE> {
|
|
|
59
65
|
* Clears all values from the set and emits to listeners.
|
|
60
66
|
* Only emits if the set was not already empty.
|
|
61
67
|
*
|
|
68
|
+
* @see {@link Stream} - Complete copy-paste transformers library
|
|
69
|
+
*
|
|
62
70
|
* @example
|
|
63
71
|
* ```typescript
|
|
64
72
|
* const cache = new Set([1, 2, 3]);
|
|
@@ -74,6 +82,8 @@ export declare class Set<VALUE> extends globalThis.Set<VALUE> {
|
|
|
74
82
|
*
|
|
75
83
|
* @param values - Optional iterable of initial values
|
|
76
84
|
*
|
|
85
|
+
* @see {@link Stream} - Complete copy-paste transformers library
|
|
86
|
+
*
|
|
77
87
|
* @example
|
|
78
88
|
* ```typescript
|
|
79
89
|
* // Empty set
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"set.d.ts","sourceRoot":"","sources":["../../src/reactive/set.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC
|
|
1
|
+
{"version":3,"file":"set.d.ts","sourceRoot":"","sources":["../../src/reactive/set.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,qBAAa,GAAG,CAAC,KAAK,CAAE,SAAQ,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC;IACnD,SAAS,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IACrC,SAAS,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IACxC,SAAS,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;IAEtC;;;;;;;;;;;;;;OAcG;IACK,GAAG,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAEtD;;;;;;;;;;;;;;OAcG;IACK,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAE5D;;;;;;;;;;;;;;OAcG;IACK,KAAK,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAE3C;;;;;;;;;;;;;;;;;;;OAmBG;gBACS,MAAM,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC;CAqDrC"}
|
package/dist/reactive/state.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import { Stream } from "../stream.ts";
|
|
1
|
+
import { FunctionGenerator, Stream } from "../stream.ts";
|
|
2
2
|
/**
|
|
3
3
|
* A reactive state container that extends Stream to provide stateful value management.
|
|
4
4
|
*
|
|
5
5
|
* @template VALUE - The type of the state value
|
|
6
6
|
*
|
|
7
|
+
* @see {@link Stream} - Complete copy-paste transformers library
|
|
8
|
+
*
|
|
7
9
|
* @example
|
|
8
10
|
* ```typescript
|
|
9
11
|
* // Basic state
|
|
@@ -11,35 +13,29 @@ import { Stream } from "../stream.ts";
|
|
|
11
13
|
* counter.listen(value => console.log('Counter:', value));
|
|
12
14
|
* counter.value = 5; // Counter: 5
|
|
13
15
|
*
|
|
14
|
-
* //
|
|
15
|
-
*
|
|
16
|
-
* const
|
|
16
|
+
* // State from stream
|
|
17
|
+
* const source = new Stream<number>();
|
|
18
|
+
* const state = new State(0, source);
|
|
19
|
+
* state.listen(value => console.log('State:', value));
|
|
20
|
+
* source.push(1, 2, 3); // State: 1, State: 2, State: 3
|
|
17
21
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
22
|
+
* // State from transformed stream
|
|
23
|
+
* const filtered = source.pipe(filter({}, (_, v) => [v > 0, {}]));
|
|
24
|
+
* const derivedState = new State(-1, filtered);
|
|
20
25
|
* ```
|
|
21
26
|
*/
|
|
22
27
|
export declare class State<VALUE> extends Stream<VALUE> {
|
|
23
28
|
protected _value: VALUE;
|
|
24
|
-
/**
|
|
25
|
-
* Creates a new State with an initial value.
|
|
26
|
-
*
|
|
27
|
-
* @param initialValue - The initial state value
|
|
28
|
-
*
|
|
29
|
-
* @example
|
|
30
|
-
* ```typescript
|
|
31
|
-
* const count = new State(0);
|
|
32
|
-
* const theme = new State<'light' | 'dark'>('light');
|
|
33
|
-
* const user = new State<User | null>(null);
|
|
34
|
-
* ```
|
|
35
|
-
*/
|
|
36
29
|
constructor(initialValue: VALUE);
|
|
30
|
+
constructor(initialValue: VALUE, stream: FunctionGenerator<VALUE> | Stream<VALUE>);
|
|
37
31
|
/**
|
|
38
32
|
* Updates the state with one or more values sequentially.
|
|
39
33
|
* Each value triggers listeners and updates the current state.
|
|
40
34
|
*
|
|
41
35
|
* @param values - Values to set as state
|
|
42
36
|
*
|
|
37
|
+
* @see {@link Stream} - Complete copy-paste transformers library
|
|
38
|
+
*
|
|
43
39
|
* @example
|
|
44
40
|
* ```typescript
|
|
45
41
|
* const state = new State(0);
|
|
@@ -53,6 +49,8 @@ export declare class State<VALUE> extends Stream<VALUE> {
|
|
|
53
49
|
/**
|
|
54
50
|
* Gets the current state value.
|
|
55
51
|
*
|
|
52
|
+
* @see {@link Stream} - Complete copy-paste transformers library
|
|
53
|
+
*
|
|
56
54
|
* @example
|
|
57
55
|
* ```typescript
|
|
58
56
|
* const state = new State('hello');
|
|
@@ -65,6 +63,8 @@ export declare class State<VALUE> extends Stream<VALUE> {
|
|
|
65
63
|
*
|
|
66
64
|
* @param value - The new state value
|
|
67
65
|
*
|
|
66
|
+
* @see {@link Stream} - Complete copy-paste transformers library
|
|
67
|
+
*
|
|
68
68
|
* @example
|
|
69
69
|
* ```typescript
|
|
70
70
|
* const state = new State(0);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/reactive/state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/reactive/state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEzD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBAAa,KAAK,CAAC,KAAK,CAAE,SAAQ,MAAM,CAAC,KAAK,CAAC;IAC7C,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC;gBACZ,YAAY,EAAE,KAAK;gBACnB,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,iBAAiB,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC;IAmBjF;;;;;;;;;;;;;;;;OAgBG;IACM,IAAI,CAAC,GAAG,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI;IAKvC;;;;;;;;;;OAUG;IACH,IAAI,KAAK,IAAI,KAAK,CAEjB;IACD;;;;;;;;;;;;;;;OAeG;IACH,IAAI,KAAK,CAAC,KAAK,EAAE,KAAK,EAGrB;CACF"}
|
package/dist/stream.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export type ValueOf<STREAM> = STREAM extends Stream<infer VALUE> ? VALUE : never;
|
|
2
|
+
export type FunctionGenerator<VALUE> = () => AsyncGenerator<VALUE, void>;
|
|
2
3
|
/**
|
|
3
4
|
* A reactive streaming library that provides async-first data structures with built-in event streams.
|
|
4
5
|
*
|
|
@@ -26,10 +27,74 @@ export type ValueOf<STREAM> = STREAM extends Stream<infer VALUE> ? VALUE : never
|
|
|
26
27
|
* if (value === 10) break;
|
|
27
28
|
* }
|
|
28
29
|
* ```
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* // 📦 COPY-PASTE TRANSFORMERS LIBRARY - Essential transformers for immediate use
|
|
33
|
+
*
|
|
34
|
+
* // FILTERING TRANSFORMERS
|
|
35
|
+
* const simpleFilter = <T>(predicate: (value: T) => boolean | Promise<boolean>) =>
|
|
36
|
+
* filter<T, {}>({}, async (_, value) => {
|
|
37
|
+
* const shouldPass = await predicate(value);
|
|
38
|
+
* return [shouldPass, {}];
|
|
39
|
+
* });
|
|
40
|
+
*
|
|
41
|
+
* const take = <T>(n: number) =>
|
|
42
|
+
* filter<T, { count: number }>({ count: 0 }, (state, value) => {
|
|
43
|
+
* if (state.count >= n) return;
|
|
44
|
+
* return [true, { count: state.count + 1 }];
|
|
45
|
+
* });
|
|
46
|
+
*
|
|
47
|
+
* const distinct = <T>() =>
|
|
48
|
+
* filter<T, { seen: Set<T> }>({ seen: new Set() }, (state, value) => {
|
|
49
|
+
* if (state.seen.has(value)) return [false, state];
|
|
50
|
+
* state.seen.add(value);
|
|
51
|
+
* return [true, state];
|
|
52
|
+
* });
|
|
53
|
+
*
|
|
54
|
+
* const tap = <T>(fn: (value: T) => void | Promise<void>) =>
|
|
55
|
+
* filter<T, {}>({}, async (_, value) => {
|
|
56
|
+
* await fn(value);
|
|
57
|
+
* return [true, {}];
|
|
58
|
+
* });
|
|
59
|
+
*
|
|
60
|
+
* // MAPPING TRANSFORMERS
|
|
61
|
+
* const simpleMap = <T, U>(fn: (value: T) => U | Promise<U>) =>
|
|
62
|
+
* map<T, {}, U>({}, async (_, value) => {
|
|
63
|
+
* const result = await fn(value);
|
|
64
|
+
* return [result, {}];
|
|
65
|
+
* });
|
|
66
|
+
*
|
|
67
|
+
* const withIndex = <T>() =>
|
|
68
|
+
* map<T, { index: number }, { value: T; index: number }>(
|
|
69
|
+
* { index: 0 },
|
|
70
|
+
* (state, value) => [
|
|
71
|
+
* { value, index: state.index },
|
|
72
|
+
* { index: state.index + 1 }
|
|
73
|
+
* ]
|
|
74
|
+
* );
|
|
75
|
+
*
|
|
76
|
+
* const delay = <T>(ms: number) =>
|
|
77
|
+
* map<T, {}, T>({}, async (_, value) => {
|
|
78
|
+
* await new Promise(resolve => setTimeout(resolve, ms));
|
|
79
|
+
* return [value, {}];
|
|
80
|
+
* });
|
|
81
|
+
*
|
|
82
|
+
* const scan = <T, U>(fn: (acc: U, value: T) => U, initial: U) =>
|
|
83
|
+
* map<T, { acc: U }, U>({ acc: initial }, (state, value) => {
|
|
84
|
+
* const newAcc = fn(state.acc, value);
|
|
85
|
+
* return [newAcc, { acc: newAcc }];
|
|
86
|
+
* });
|
|
87
|
+
*
|
|
88
|
+
* // STATE CONVERTER
|
|
89
|
+
* const toState = <T>(initialValue: T) => (stream: Stream<T>) => {
|
|
90
|
+
* return new State(initialValue, stream);
|
|
91
|
+
* };
|
|
92
|
+
*
|
|
93
|
+
* // Usage: stream.pipe(simpleFilter(x => x > 0)).pipe(take(5)).pipe(toState(0));
|
|
29
94
|
*/
|
|
30
95
|
export declare class Stream<VALUE = unknown> implements AsyncIterable<VALUE> {
|
|
31
96
|
protected _listeners: Set<(value: VALUE) => void>;
|
|
32
|
-
protected _generatorFn:
|
|
97
|
+
protected _generatorFn: FunctionGenerator<VALUE> | undefined;
|
|
33
98
|
protected _generator: AsyncGenerator<VALUE, void> | undefined;
|
|
34
99
|
protected _listenerAdded: Stream<void> | undefined;
|
|
35
100
|
protected _listenerRemoved: Stream<void> | undefined;
|
|
@@ -38,6 +103,8 @@ export declare class Stream<VALUE = unknown> implements AsyncIterable<VALUE> {
|
|
|
38
103
|
*
|
|
39
104
|
* @param generatorFn - Optional async generator function to produce values you can use it for creating stream with custom transformation
|
|
40
105
|
*
|
|
106
|
+
* @see {@link Stream} - Complete copy-paste transformers library
|
|
107
|
+
*
|
|
41
108
|
* @example
|
|
42
109
|
* ```typescript
|
|
43
110
|
* // Empty stream
|
|
@@ -66,10 +133,12 @@ export declare class Stream<VALUE = unknown> implements AsyncIterable<VALUE> {
|
|
|
66
133
|
* ```
|
|
67
134
|
*/
|
|
68
135
|
constructor();
|
|
69
|
-
constructor(
|
|
136
|
+
constructor(stream: FunctionGenerator<VALUE> | Stream<VALUE>);
|
|
70
137
|
/**
|
|
71
138
|
* Returns true if the stream has active listeners.
|
|
72
139
|
*
|
|
140
|
+
* @see {@link Stream} - Complete copy-paste transformers library
|
|
141
|
+
*
|
|
73
142
|
* @example
|
|
74
143
|
* ```typescript
|
|
75
144
|
* const stream = new Stream<number>();
|
|
@@ -86,6 +155,8 @@ export declare class Stream<VALUE = unknown> implements AsyncIterable<VALUE> {
|
|
|
86
155
|
/**
|
|
87
156
|
* Stream that emits when a listener is added.
|
|
88
157
|
*
|
|
158
|
+
* @see {@link Stream} - Complete copy-paste transformers library
|
|
159
|
+
*
|
|
89
160
|
* @example
|
|
90
161
|
* ```typescript
|
|
91
162
|
* const stream = new Stream<number>();
|
|
@@ -98,6 +169,8 @@ export declare class Stream<VALUE = unknown> implements AsyncIterable<VALUE> {
|
|
|
98
169
|
/**
|
|
99
170
|
* Stream that emits when a listener is removed.
|
|
100
171
|
*
|
|
172
|
+
* @see {@link Stream} - Complete copy-paste transformers library
|
|
173
|
+
*
|
|
101
174
|
* @example
|
|
102
175
|
* ```typescript
|
|
103
176
|
* const stream = new Stream<number>();
|
|
@@ -112,6 +185,8 @@ export declare class Stream<VALUE = unknown> implements AsyncIterable<VALUE> {
|
|
|
112
185
|
/**
|
|
113
186
|
* Pushes one or more values to all listeners.
|
|
114
187
|
*
|
|
188
|
+
* @see {@link Stream} - Complete copy-paste transformers library
|
|
189
|
+
*
|
|
115
190
|
* @param value - The first value to push
|
|
116
191
|
* @param values - Additional values to push
|
|
117
192
|
*
|
|
@@ -132,6 +207,8 @@ export declare class Stream<VALUE = unknown> implements AsyncIterable<VALUE> {
|
|
|
132
207
|
* @param signal - Optional AbortSignal for cleanup
|
|
133
208
|
* @returns Cleanup function to remove the listener
|
|
134
209
|
*
|
|
210
|
+
* @see {@link Stream} - Complete copy-paste transformers library
|
|
211
|
+
*
|
|
135
212
|
* @example
|
|
136
213
|
* ```typescript
|
|
137
214
|
* const stream = new Stream<string>();
|
|
@@ -155,6 +232,8 @@ export declare class Stream<VALUE = unknown> implements AsyncIterable<VALUE> {
|
|
|
155
232
|
* @param onfulfilled - Optional transformation function
|
|
156
233
|
* @returns Promise that resolves with the first value
|
|
157
234
|
*
|
|
235
|
+
* @see {@link Stream} - Complete copy-paste transformers library
|
|
236
|
+
*
|
|
158
237
|
* @example
|
|
159
238
|
* ```typescript
|
|
160
239
|
* const stream = new Stream<number>();
|
|
@@ -172,18 +251,20 @@ export declare class Stream<VALUE = unknown> implements AsyncIterable<VALUE> {
|
|
|
172
251
|
/**
|
|
173
252
|
* Applies a transformer function to this stream, enabling functional composition.
|
|
174
253
|
*
|
|
175
|
-
* @param transformer - Function that takes a stream and returns
|
|
176
|
-
* @returns
|
|
254
|
+
* @param transformer - Function that takes a stream and returns any output type
|
|
255
|
+
* @returns The result of the transformer function
|
|
256
|
+
*
|
|
257
|
+
* @see {@link Stream} - Complete copy-paste transformers library
|
|
177
258
|
*
|
|
178
259
|
* @example
|
|
179
260
|
* ```typescript
|
|
180
261
|
* const numbers = new Stream<number>();
|
|
181
262
|
*
|
|
182
|
-
* //
|
|
263
|
+
* // Chain transformers
|
|
183
264
|
* const result = numbers
|
|
184
|
-
* .pipe(filter(n => n > 0))
|
|
185
|
-
* .pipe(map(n => n * 2))
|
|
186
|
-
* .pipe(
|
|
265
|
+
* .pipe(filter({}, (_, n) => [n > 0, {}]))
|
|
266
|
+
* .pipe(map({}, (_, n) => [n * 2, {}]))
|
|
267
|
+
* .pipe(toState(0));
|
|
187
268
|
*
|
|
188
269
|
* // Custom transformer
|
|
189
270
|
* const throttle = <T>(ms: number) => (stream: Stream<T>) =>
|
|
@@ -198,9 +279,11 @@ export declare class Stream<VALUE = unknown> implements AsyncIterable<VALUE> {
|
|
|
198
279
|
* }
|
|
199
280
|
* });
|
|
200
281
|
*
|
|
201
|
-
*
|
|
282
|
+
* // Transform to any type
|
|
283
|
+
* const stringResult = numbers.pipe(throttle(1000));
|
|
284
|
+
* const stateResult = numbers.pipe(toState(0));
|
|
202
285
|
* ```
|
|
203
286
|
*/
|
|
204
|
-
pipe<OUTPUT
|
|
287
|
+
pipe<OUTPUT extends Stream<any>>(transformer: (stream: this) => OUTPUT): OUTPUT;
|
|
205
288
|
}
|
|
206
289
|
//# sourceMappingURL=stream.d.ts.map
|
package/dist/stream.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../src/stream.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,OAAO,CAAC,MAAM,IAAI,MAAM,SAAS,MAAM,CAAC,MAAM,KAAK,CAAC,GAAG,KAAK,GAAG,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../src/stream.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,OAAO,CAAC,MAAM,IAAI,MAAM,SAAS,MAAM,CAAC,MAAM,KAAK,CAAC,GAAG,KAAK,GAAG,KAAK,CAAC;AACjF,MAAM,MAAM,iBAAiB,CAAC,KAAK,IAAI,MAAM,cAAc,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;AACzE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2FG;AACH,qBAAa,MAAM,CAAC,KAAK,GAAG,OAAO,CAAE,YAAW,aAAa,CAAC,KAAK,CAAC;IAClE,SAAS,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC,CAAqC;IACtF,SAAS,CAAC,YAAY,EAAE,iBAAiB,CAAC,KAAK,CAAC,GAAG,SAAS,CAAC;IAC7D,SAAS,CAAC,UAAU,EAAE,cAAc,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,SAAS,CAAC;IAC9D,SAAS,CAAC,cAAc,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC;IACnD,SAAS,CAAC,gBAAgB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC;IAErD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAiCG;;gBAES,MAAM,EAAE,iBAAiB,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC;IAK5D;;;;;;;;;;;;;;;;OAgBG;IACH,IAAI,YAAY,IAAI,OAAO,CAE1B;IAED;;;;;;;;;;;;OAYG;IACH,IAAI,aAAa,IAAI,MAAM,CAAC,IAAI,CAAC,CAGhC;IAED;;;;;;;;;;;;;OAaG;IACH,IAAI,eAAe,IAAI,MAAM,CAAC,IAAI,CAAC,CAGlC;IACM,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,cAAc,CAAC,KAAK,EAAE,IAAI,CAAC;IAsB5D;;;;;;;;;;;;;;;;OAgBG;IACH,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI;IAS5C;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,MAAM,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,IAAI;IAoCxF;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC;IASzF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAmCG;IACH,IAAI,CAAC,MAAM,SAAS,MAAM,CAAC,GAAG,CAAC,EAAE,WAAW,EAAE,CAAC,MAAM,EAAE,IAAI,KAAK,MAAM,GAAG,MAAM;CAGhF"}
|
|
@@ -13,6 +13,8 @@ import { Stream } from "../stream.ts";
|
|
|
13
13
|
*
|
|
14
14
|
* @returns A transformer function that can be used with `.pipe()`
|
|
15
15
|
*
|
|
16
|
+
* @see {@link Stream} - Complete copy-paste transformers library
|
|
17
|
+
*
|
|
16
18
|
* @example
|
|
17
19
|
* // Simple filtering
|
|
18
20
|
* stream.pipe(filter({}, (_, value) => [value > 0, {}]))
|
|
@@ -26,38 +28,7 @@ import { Stream } from "../stream.ts";
|
|
|
26
28
|
* })
|
|
27
29
|
* )
|
|
28
30
|
*
|
|
29
|
-
|
|
30
|
-
* // 📦 COPY-PASTE TRANSFORMER: simpleFilter() - Simple predicate filtering
|
|
31
|
-
* const simpleFilter = <T>(predicate: (value: T) => boolean | Promise<boolean>) =>
|
|
32
|
-
* filter<T, {}>({}, async (_, value) => {
|
|
33
|
-
* const shouldPass = await predicate(value);
|
|
34
|
-
* return [shouldPass, {}];
|
|
35
|
-
* });
|
|
36
|
-
*
|
|
37
|
-
* @example
|
|
38
|
-
* // 📦 COPY-PASTE TRANSFORMER: take(n) - Limit to N items
|
|
39
|
-
* const take = <T>(n: number) =>
|
|
40
|
-
* filter<T, { count: number }>({ count: 0 }, (state, value) => {
|
|
41
|
-
* if (state.count >= n) return;
|
|
42
|
-
* return [true, { count: state.count + 1 }];
|
|
43
|
-
* });
|
|
44
|
-
*
|
|
45
|
-
* @example
|
|
46
|
-
* // 📦 COPY-PASTE TRANSFORMER: skip(n) - Skip first N items
|
|
47
|
-
* const skip = <T>(n: number) =>
|
|
48
|
-
* filter<T, { count: number }>({ count: 0 }, (state, value) => {
|
|
49
|
-
* const newCount = state.count + 1;
|
|
50
|
-
* return [newCount > n, { count: newCount }];
|
|
51
|
-
* });
|
|
52
|
-
*
|
|
53
|
-
* @example
|
|
54
|
-
* // 📦 COPY-PASTE TRANSFORMER: distinct() - Remove duplicates
|
|
55
|
-
* const distinct = <T>() =>
|
|
56
|
-
* filter<T, { seen: Set<T> }>({ seen: new Set() }, (state, value) => {
|
|
57
|
-
* if (state.seen.has(value)) return [false, state];
|
|
58
|
-
* state.seen.add(value);
|
|
59
|
-
* return [true, state];
|
|
60
|
-
* });
|
|
31
|
+
|
|
61
32
|
*
|
|
62
33
|
*/
|
|
63
34
|
export declare function filter<VALUE, STATE extends Record<string, unknown> = {}>(initialState: STATE, predicate: (state: STATE, value: VALUE) => [boolean, STATE] | void | Promise<[boolean, STATE] | void>): (stream: Stream<VALUE>) => Stream<VALUE>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../../src/transformers/filter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC
|
|
1
|
+
{"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../../src/transformers/filter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,EAAE,EACtE,YAAY,EAAE,KAAK,EACnB,SAAS,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,IAAI,CAAC,GACpG,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,KAAK,MAAM,CAAC,KAAK,CAAC,CAe1C"}
|
|
@@ -9,6 +9,8 @@ import { Stream } from "../stream.ts";
|
|
|
9
9
|
*
|
|
10
10
|
* @returns A transformer that flattens array values into individual events
|
|
11
11
|
*
|
|
12
|
+
* @see {@link Stream} - Complete copy-paste transformers library
|
|
13
|
+
*
|
|
12
14
|
* @example
|
|
13
15
|
* // Basic flattening - 1 array → N events
|
|
14
16
|
* const arrayStream = new Stream<number[]>();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flat.d.ts","sourceRoot":"","sources":["../../src/transformers/flat.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAGtC
|
|
1
|
+
{"version":3,"file":"flat.d.ts","sourceRoot":"","sources":["../../src/transformers/flat.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAGtC;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,IAAI,CAAC,KAAK,EAAE,KAAK,SAAS,MAAM,GAAG,CAAC,EAClD,KAAK,GAAE,KAAkB,GACxB,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,KAAK,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAe5D"}
|
|
@@ -14,6 +14,8 @@ import { Stream } from "../stream.ts";
|
|
|
14
14
|
*
|
|
15
15
|
* @returns A transformer function that can be used with `.pipe()`
|
|
16
16
|
*
|
|
17
|
+
* @see {@link Stream} - Complete copy-paste transformers library
|
|
18
|
+
*
|
|
17
19
|
* @example
|
|
18
20
|
* // Simple transformation
|
|
19
21
|
* stream.pipe(map({}, (_, value) => [value * 2, {}]))
|
|
@@ -27,37 +29,7 @@ import { Stream } from "../stream.ts";
|
|
|
27
29
|
* })
|
|
28
30
|
* )
|
|
29
31
|
*
|
|
30
|
-
|
|
31
|
-
* // 📦 COPY-PASTE TRANSFORMER: simpleMap() - Simple transformation
|
|
32
|
-
* const simpleMap = <T, U>(fn: (value: T) => U | Promise<U>) =>
|
|
33
|
-
* map<T, {}, U>({}, async (_, value) => {
|
|
34
|
-
* const result = await fn(value);
|
|
35
|
-
* return [result, {}];
|
|
36
|
-
* });
|
|
37
|
-
*
|
|
38
|
-
* @example
|
|
39
|
-
* // 📦 COPY-PASTE TRANSFORMER: withIndex() - Add index to values
|
|
40
|
-
* const withIndex = <T>() =>
|
|
41
|
-
* map<T, { index: number }, { value: T; index: number }>(
|
|
42
|
-
* { index: 0 },
|
|
43
|
-
* (state, value) => [
|
|
44
|
-
* { value, index: state.index },
|
|
45
|
-
* { index: state.index + 1 }
|
|
46
|
-
* ]
|
|
47
|
-
* );
|
|
48
|
-
*
|
|
49
|
-
* @example
|
|
50
|
-
* // 📦 COPY-PASTE TRANSFORMER: delay(ms) - Delay each value
|
|
51
|
-
* const delay = <T>(ms: number) =>
|
|
52
|
-
* map<T, {}, T>({}, async (_, value) => {
|
|
53
|
-
* await new Promise(resolve => setTimeout(resolve, ms));
|
|
54
|
-
* return [value, {}];
|
|
55
|
-
* });
|
|
56
|
-
*
|
|
57
|
-
* @example
|
|
58
|
-
* // 📦 COPY-PASTE TRANSFORMER: pluck(key) - Extract property
|
|
59
|
-
* const pluck = <T, K extends keyof T>(key: K) =>
|
|
60
|
-
* map<T, {}, T[K]>({}, (_, value) => [value[key], {}]);
|
|
32
|
+
|
|
61
33
|
*
|
|
62
34
|
*/
|
|
63
35
|
export declare function map<VALUE, STATE extends Record<string, unknown>, MAPPED>(initialState: STATE, predicate: (state: STATE, value: VALUE) => [MAPPED, STATE] | Promise<[MAPPED, STATE]>): (stream: Stream<VALUE>) => Stream<MAPPED>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"map.d.ts","sourceRoot":"","sources":["../../src/transformers/map.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"map.d.ts","sourceRoot":"","sources":["../../src/transformers/map.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,GAAG,CAAC,KAAK,EAAE,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EACtE,YAAY,EAAE,KAAK,EACnB,SAAS,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,GACpF,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,CAU3C"}
|
|
@@ -10,6 +10,8 @@ type ValueOf<STREAM> = STREAM extends Stream<infer VALUE> ? VALUE : never;
|
|
|
10
10
|
*
|
|
11
11
|
* @returns A transformer that merges all streams into one with union types
|
|
12
12
|
*
|
|
13
|
+
* @see {@link Stream} - Complete copy-paste transformers library
|
|
14
|
+
*
|
|
13
15
|
* @example
|
|
14
16
|
* // Basic merge with type safety
|
|
15
17
|
* const numbers = new Stream<number>();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../../src/transformers/merge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,KAAK,OAAO,CAAC,MAAM,IAAI,MAAM,SAAS,MAAM,CAAC,MAAM,KAAK,CAAC,GAAG,KAAK,GAAG,KAAK,CAAC;AAE1E
|
|
1
|
+
{"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../../src/transformers/merge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,KAAK,OAAO,CAAC,MAAM,IAAI,MAAM,SAAS,MAAM,CAAC,MAAM,KAAK,CAAC,GAAG,KAAK,GAAG,KAAK,CAAC;AAE1E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,KAAK,CAAC,KAAK,EAAE,OAAO,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,EAC1E,GAAG,OAAO,EAAE,OAAO,GAClB,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,KAAK,MAAM,CAAC,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CA0BrE"}
|
package/package.json
CHANGED
|
@@ -121,8 +121,6 @@ const take = <T>(n: number) =>
|
|
|
121
121
|
});
|
|
122
122
|
```
|
|
123
123
|
|
|
124
|
-
**Psychology**: `take` demonstrates **self-limiting behavior** - the filter knows its purpose and fulfills it completely, then gracefully terminates.
|
|
125
|
-
|
|
126
124
|
### distinct - The Memory Gatekeeper
|
|
127
125
|
|
|
128
126
|
```typescript
|
|
@@ -134,7 +132,19 @@ const distinct = <T>() =>
|
|
|
134
132
|
});
|
|
135
133
|
```
|
|
136
134
|
|
|
137
|
-
|
|
135
|
+
### tap - The Observer Gatekeeper
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
const tap = <T>(fn: (value: T) => void | Promise<void>) =>
|
|
139
|
+
filter<T, {}>({}, async (_, value) => {
|
|
140
|
+
await fn(value);
|
|
141
|
+
return [true, {}]; // Always pass through
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
// Usage: Side effects without changing the stream
|
|
145
|
+
stream.pipe(tap((value) => console.log("Saw:", value)));
|
|
146
|
+
stream.pipe(tap(async (value) => await logToDatabase(value)));
|
|
147
|
+
```
|
|
138
148
|
|
|
139
149
|
## The Termination
|
|
140
150
|
|
|
@@ -151,6 +161,37 @@ const untilCondition = <T>(condition: (value: T) => boolean) =>
|
|
|
151
161
|
|
|
152
162
|
This represents a fundamental shift from infinite streams to **purpose-driven streams** that know when their work is done.
|
|
153
163
|
|
|
164
|
+
## Enhanced Pipe Integration
|
|
165
|
+
|
|
166
|
+
The new pipe architecture enables seamless integration:
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
// Filter integrates with any transformer
|
|
170
|
+
const result = stream
|
|
171
|
+
.pipe(filter({}, (_, v) => [v > 0, {}])) // Returns Stream<T>
|
|
172
|
+
.pipe(map({}, (_, v) => [v.toString(), {}])) // Returns Stream<string>
|
|
173
|
+
.pipe(toState("0")); // Returns State<string>
|
|
174
|
+
|
|
175
|
+
// Complex filtering chains
|
|
176
|
+
const processed = source
|
|
177
|
+
.pipe(
|
|
178
|
+
filter({ seen: 0 }, (state, v) => {
|
|
179
|
+
if (state.seen >= 100) return; // Terminate after 100
|
|
180
|
+
return [v > 0, { seen: state.seen + 1 }];
|
|
181
|
+
})
|
|
182
|
+
)
|
|
183
|
+
.pipe(tap((v) => console.log("Positive:", v)))
|
|
184
|
+
.pipe(
|
|
185
|
+
filter({ count: 0 }, (state, v) => {
|
|
186
|
+
return [state.count % 2 === 0, { count: state.count + 1 }]; // Every other
|
|
187
|
+
})
|
|
188
|
+
);
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
**Note**: Filters compose naturally because they all speak the same language - **adaptive constraints** that can terminate, remember, and evolve.
|
|
192
|
+
|
|
193
|
+
**Design insight**: Filtering State creates **conditional reactivity** - the derived state only reacts to values that pass the adaptive constraints.
|
|
194
|
+
|
|
154
195
|
## Conclusion
|
|
155
196
|
|
|
156
197
|
The `filter` transformer isn't just about removing unwanted values - it's about **intelligent gatekeeping** that:
|
package/src/transformers/map.md
CHANGED
|
@@ -146,6 +146,36 @@ const pluck = <T, K extends keyof T>(key: K) => map<T, {}, T[K]>({}, (_, value)
|
|
|
146
146
|
|
|
147
147
|
`pluck` demonstrates **selective transformation** - the alchemist knows exactly what it wants and ignores everything else.
|
|
148
148
|
|
|
149
|
+
### tap - The Observer Gatekeeper
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
const tap = <T>(fn: (value: T) => void | Promise<void>) =>
|
|
153
|
+
map<T, {}, T>({}, async (_, value) => {
|
|
154
|
+
await fn(value);
|
|
155
|
+
return [value, {}]; // Always pass through
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
// Usage: Side effects without changing the stream
|
|
159
|
+
stream.pipe(tap((value) => console.log("Saw:", value)));
|
|
160
|
+
stream.pipe(tap(async (value) => await logToDatabase(value)));
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### scan - The Accumulating Alchemist
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
const scan = <T, U>(fn: (acc: U, value: T) => U, initial: U) =>
|
|
167
|
+
map<T, { acc: U }, U>({ acc: initial }, (state, value) => {
|
|
168
|
+
const newAcc = fn(state.acc, value);
|
|
169
|
+
return [newAcc, { acc: newAcc }];
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
// Usage: Accumulate values over time
|
|
173
|
+
stream.pipe(scan((sum, value) => sum + value, 0)); // Running sum
|
|
174
|
+
stream.pipe(scan((max, value) => Math.max(max, value), -Infinity)); // Running max
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
`scan` demonstrates **accumulative transformation** - each value builds upon all previous values, creating a growing understanding.
|
|
178
|
+
|
|
149
179
|
## The Order Preservation
|
|
150
180
|
|
|
151
181
|
Async transformations maintain order because **sequence matters**. Even if transformation B completes before transformation A, the stream waits. This isn't just about correctness - it's about **respecting the narrative** of the data.
|
|
@@ -182,3 +212,5 @@ The `map` transformer isn't just about changing values - it's about **intelligen
|
|
|
182
212
|
- **Learns** from patterns (adaptation)
|
|
183
213
|
- **Evolves** its approach over time (constraints)
|
|
184
214
|
- **Preserves** the narrative order (respect)
|
|
215
|
+
- **Integrates** with reactive state (toState)
|
|
216
|
+
- **Accumulates** knowledge over time (scan)
|