@soffinal/stream 0.1.3 → 0.2.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 +22 -0
- package/README.md +324 -269
- package/dist/index.d.ts +2 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +12 -8
- package/dist/reactive/index.d.ts +5 -0
- package/dist/reactive/index.d.ts.map +1 -0
- package/dist/{list.d.ts → reactive/list.d.ts} +1 -1
- package/dist/reactive/list.d.ts.map +1 -0
- package/dist/{map.d.ts → reactive/map.d.ts} +1 -1
- package/dist/reactive/map.d.ts.map +1 -0
- package/dist/{set.d.ts → reactive/set.d.ts} +1 -1
- package/dist/reactive/set.d.ts.map +1 -0
- package/dist/{state.d.ts → reactive/state.d.ts} +1 -1
- package/dist/reactive/state.d.ts.map +1 -0
- package/dist/stream.d.ts +1 -279
- package/dist/stream.d.ts.map +1 -1
- package/dist/transformers/filter.d.ts +64 -0
- package/dist/transformers/filter.d.ts.map +1 -0
- package/dist/transformers/flat.d.ts +29 -0
- package/dist/transformers/flat.d.ts.map +1 -0
- package/dist/transformers/index.d.ts +5 -0
- package/dist/transformers/index.d.ts.map +1 -0
- package/dist/transformers/map.d.ts +64 -0
- package/dist/transformers/map.d.ts.map +1 -0
- package/dist/transformers/merge.d.ts +33 -0
- package/dist/transformers/merge.d.ts.map +1 -0
- package/package.json +5 -8
- package/src/transformers/filter.md +161 -0
- package/src/transformers/flat.md +56 -0
- package/src/transformers/map.md +184 -0
- package/src/transformers/merge.md +79 -0
- package/dist/benchmark.d.ts +0 -16
- package/dist/benchmark.d.ts.map +0 -1
- package/dist/list.d.ts.map +0 -1
- package/dist/map.d.ts.map +0 -1
- package/dist/set.d.ts.map +0 -1
- package/dist/state.d.ts.map +0 -1
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# Filter Transformer
|
|
2
|
+
|
|
3
|
+
## The Adaptive Gatekeeper
|
|
4
|
+
|
|
5
|
+
Traditional filtering is binary and stateless - a value either passes or doesn't. But real-world filtering often requires **memory, learning, and evolution**. The `filter` transformer embodies **Adaptive Reactive Programming** - where the gatekeeper remembers, and can even decide when to stop.
|
|
6
|
+
|
|
7
|
+
## Design
|
|
8
|
+
|
|
9
|
+
### Why State-First Architecture?
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
filter(initialState, (state, value) => [boolean, newState]);
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
**State comes first** because it's the foundation of adaptation. This isn't just filtering - it's **Adaptive gatekeeping** that evolves with each event.
|
|
16
|
+
|
|
17
|
+
### The Dual Return Pattern
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
return [shouldPass, newState]; // Continue with evolution
|
|
21
|
+
return; // Terminate with wisdom
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
**Two outcomes, infinite possibilities:**
|
|
25
|
+
|
|
26
|
+
- `[boolean, state]` - The filter learns and continues
|
|
27
|
+
- `void` - The filter decides the stream has served its purpose
|
|
28
|
+
|
|
29
|
+
This mirrors human decision-making: we either let something through (and remember why), or we decide we've seen enough.
|
|
30
|
+
|
|
31
|
+
### Argument Order
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
(state, value) => // State first, value second
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
**State precedes value** because context shapes perception. We don't judge events in isolation - we judge them based on what we've learned. The state is the accumulated transformations; the value is just the current moment.
|
|
38
|
+
|
|
39
|
+
## The Adaptive Constraint System
|
|
40
|
+
|
|
41
|
+
### Level 1: Simple Gatekeeping
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
// Traditional filtering - no memory, no learning
|
|
45
|
+
stream.pipe(filter({}, (_, value) => [value > 0, {}]));
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Even "simple" filtering uses the adaptive architecture. The empty state `{}` represents a gatekeeper that doesn't need memory - but could develop it.
|
|
49
|
+
|
|
50
|
+
### Level 2: Memory-Based Filtering
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
// The gatekeeper remembers and counts
|
|
54
|
+
stream.pipe(
|
|
55
|
+
filter({ count: 0 }, (state, value) => {
|
|
56
|
+
const newCount = state.count + 1;
|
|
57
|
+
return [newCount % 3 === 0, { count: newCount }]; // Every 3rd passes
|
|
58
|
+
})
|
|
59
|
+
);
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Level 3: Termination
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
// The gatekeeper knows when enough is enough
|
|
66
|
+
stream.pipe(
|
|
67
|
+
filter({ seen: 0 }, (state, value) => {
|
|
68
|
+
if (state.seen >= 10) return; // Wisdom: we've seen enough
|
|
69
|
+
return [value > 0, { seen: state.seen + 1 }];
|
|
70
|
+
})
|
|
71
|
+
);
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**Stream termination** represents the ultimate adaptive behavior - knowing when to stop. This isn't just filtering; it's **stream lifecycle management**.
|
|
75
|
+
|
|
76
|
+
### Level 4: Async
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
// The gatekeeper consults external validation
|
|
80
|
+
stream.pipe(
|
|
81
|
+
filter({ cache: new Map() }, async (state, value) => {
|
|
82
|
+
if (state.cache.has(value)) {
|
|
83
|
+
return [state.cache.get(value), state]; // Remember previous decisions
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const isValid = await validateAsync(value);
|
|
87
|
+
state.cache.set(value, isValid); // Learn for next time
|
|
88
|
+
return [isValid, state];
|
|
89
|
+
})
|
|
90
|
+
);
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**Async filtering with memory** - the gatekeeper doesn't just validate, it **builds institutional knowledge**.
|
|
94
|
+
|
|
95
|
+
## Essential Copy-Paste Transformers
|
|
96
|
+
|
|
97
|
+
### simpleFilter - Gateway to Adaptation
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
// For users transitioning from traditional filtering
|
|
101
|
+
const simpleFilter = <T>(predicate: (value: T) => boolean | Promise<boolean>) =>
|
|
102
|
+
filter<T, {}>({}, async (_, value) => {
|
|
103
|
+
const shouldPass = await predicate(value);
|
|
104
|
+
return [shouldPass, {}];
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// Usage: familiar syntax, adaptive foundation
|
|
108
|
+
stream.pipe(simpleFilter((x) => x > 0));
|
|
109
|
+
stream.pipe(simpleFilter(async (user) => await isValid(user)));
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
**Design choice**: `simpleFilter` is a **bridge**, not a replacement. It introduces users to the adaptive architecture while providing familiar syntax. The empty state `{}` is an invitation to evolution.
|
|
113
|
+
|
|
114
|
+
### take - The Counting Gatekeeper
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
const take = <T>(n: number) =>
|
|
118
|
+
filter<T, { count: number }>({ count: 0 }, (state, value) => {
|
|
119
|
+
if (state.count >= n) return; // Wisdom: we have enough
|
|
120
|
+
return [true, { count: state.count + 1 }];
|
|
121
|
+
});
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**Psychology**: `take` demonstrates **self-limiting behavior** - the filter knows its purpose and fulfills it completely, then gracefully terminates.
|
|
125
|
+
|
|
126
|
+
### distinct - The Memory Gatekeeper
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
const distinct = <T>() =>
|
|
130
|
+
filter<T, { seen: Set<T> }>({ seen: new Set() }, (state, value) => {
|
|
131
|
+
if (state.seen.has(value)) return [false, state];
|
|
132
|
+
state.seen.add(value);
|
|
133
|
+
return [true, state];
|
|
134
|
+
});
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
**Philosophy**: `distinct` embodies **perfect memory** - it never forgets what it has seen, ensuring uniqueness through accumulated values.
|
|
138
|
+
|
|
139
|
+
## The Termination
|
|
140
|
+
|
|
141
|
+
Stream termination isn't failure - it's **purposeful completion**. When a filter returns `void`, it's saying: "I have served my purpose, and this stream's journey ends here."
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
// A filter that knows its mission
|
|
145
|
+
const untilCondition = <T>(condition: (value: T) => boolean) =>
|
|
146
|
+
filter<T, {}>({}, (_, value) => {
|
|
147
|
+
if (condition(value)) return; // Mission complete
|
|
148
|
+
return [true, {}];
|
|
149
|
+
});
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
This represents a fundamental shift from infinite streams to **purpose-driven streams** that know when their work is done.
|
|
153
|
+
|
|
154
|
+
## Conclusion
|
|
155
|
+
|
|
156
|
+
The `filter` transformer isn't just about removing unwanted values - it's about **intelligent gatekeeping** that:
|
|
157
|
+
|
|
158
|
+
- **Remembers** previous decisions (state)
|
|
159
|
+
- **Learns** from patterns (adaptation)
|
|
160
|
+
- **Evolves** behavior over time (constraints)
|
|
161
|
+
- **Knows** when to stop (termination)
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Flat Transformer
|
|
2
|
+
|
|
3
|
+
## Event Multiplication
|
|
4
|
+
|
|
5
|
+
The `flat` transformer converts array events into individual events - essentially `Array.prototype.flat()` for streams.
|
|
6
|
+
|
|
7
|
+
**Core Concept**: 1 array event → N individual events
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
stream.pipe(flat(depth?));
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
- **Input**: `Stream<T[]>`
|
|
16
|
+
- **Output**: `Stream<T>`
|
|
17
|
+
- **Transformation**: Each array becomes separate events
|
|
18
|
+
|
|
19
|
+
## Basic Example
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
const arrayStream = new Stream<number[]>();
|
|
23
|
+
const flattened = arrayStream.pipe(flat());
|
|
24
|
+
|
|
25
|
+
arrayStream.push([1, 2, 3]);
|
|
26
|
+
// Emits: 1, 2, 3 as separate events
|
|
27
|
+
|
|
28
|
+
flattened.listen((value) => console.log(value));
|
|
29
|
+
// Logs: 1, 2, 3
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Depth Control
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
const nested = new Stream<number[][]>();
|
|
36
|
+
const flattened = nested.pipe(flat(1)); // Flatten 2 levels
|
|
37
|
+
|
|
38
|
+
nested.push([
|
|
39
|
+
[1, 2],
|
|
40
|
+
[3, 4],
|
|
41
|
+
]);
|
|
42
|
+
// Emits: 1, 2, 3, 4 as separate events
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Common Pattern
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
// Map then flatten
|
|
49
|
+
const sentences = new Stream<string>();
|
|
50
|
+
const characters = sentences.pipe(map({}, (_, s) => [s.split(""), {}])).pipe(flat());
|
|
51
|
+
|
|
52
|
+
sentences.push("hello");
|
|
53
|
+
// Emits: 'h', 'e', 'l', 'l', 'o' as separate events
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
That's it. Simple event multiplication for arrays.
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# Map Transformer
|
|
2
|
+
|
|
3
|
+
## The Adaptive Alchemist
|
|
4
|
+
|
|
5
|
+
Traditional mapping is a simple function application - transform input A to output B. But real-world transformation often requires **context, memory, and evolution**. The `map` transformer embodies **Adaptive Reactive Programming** - where the alchemist remembers previous transformations and evolves its craft.
|
|
6
|
+
|
|
7
|
+
## Design
|
|
8
|
+
|
|
9
|
+
### Why State-First Architecture?
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
map(initialState, (state, value) => [transformed, newState]);
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
**State comes first** because transformation is contextual. We don't transform values in isolation - we transform them based on what we've learned, what we've seen, and where we're going. The state is the accumulated knowledge; the value is just the raw material.
|
|
16
|
+
|
|
17
|
+
### The Dual Return Pattern
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
return [transformedValue, newState]; // Transform and evolve
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**Every transformation teaches us something.** The dual return forces us to consider: "How does this transformation change our understanding?" Even if the state doesn't change, we must consciously decide that.
|
|
24
|
+
|
|
25
|
+
### Argument Order
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
(state, value) => // Context first, content second
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**Context shapes transformation.** A value of `5` might become `10` (double), `"5"` (stringify), or `{ count: 5, timestamp: now }` (enrich) - depending on the accumulated state. The transformer's history determines the value's destiny.
|
|
32
|
+
|
|
33
|
+
## The Adaptive Transformation System
|
|
34
|
+
|
|
35
|
+
### Level 1: Simple Alchemy
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
// Traditional transformation - no memory, no learning
|
|
39
|
+
stream.pipe(map({}, (_, value) => [value * 2, {}]));
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Even "simple" mapping uses the adaptive architecture. The empty state `{}` represents a state that doesn't need memory - but could develop it.
|
|
43
|
+
|
|
44
|
+
### Level 2: Contextual Transformation
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
// The alchemist remembers and enriches
|
|
48
|
+
stream.pipe(
|
|
49
|
+
map({ sum: 0, count: 0 }, (state, value) => {
|
|
50
|
+
const newSum = state.sum + value;
|
|
51
|
+
const newCount = state.count + 1;
|
|
52
|
+
const average = newSum / newCount;
|
|
53
|
+
|
|
54
|
+
return [
|
|
55
|
+
{ value, runningSum: newSum, runningAverage: average },
|
|
56
|
+
{ sum: newSum, count: newCount },
|
|
57
|
+
];
|
|
58
|
+
})
|
|
59
|
+
);
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Level 3: Evolutionary Transformation
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
// The alchemist adapts its formula based on patterns
|
|
66
|
+
stream.pipe(
|
|
67
|
+
map({ multiplier: 1, trend: "stable" }, (state, value) => {
|
|
68
|
+
// Adapt the transformation based on observed patterns
|
|
69
|
+
const newMultiplier = value > 100 ? state.multiplier * 1.1 : state.multiplier * 0.9;
|
|
70
|
+
const trend = newMultiplier > state.multiplier ? "growing" : "shrinking";
|
|
71
|
+
|
|
72
|
+
return [value * newMultiplier, { multiplier: newMultiplier, trend }];
|
|
73
|
+
})
|
|
74
|
+
);
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
**Adaptive transformation** - the formula itself evolves based on the data it processes.
|
|
78
|
+
|
|
79
|
+
### Level 4: Async with Order Preservation
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
// The alchemist consults external sources while maintaining order
|
|
83
|
+
stream.pipe(
|
|
84
|
+
map({ cache: new Map() }, async (state, value) => {
|
|
85
|
+
if (state.cache.has(value)) {
|
|
86
|
+
return [state.cache.get(value), state];
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const enriched = await enrichWithAPI(value);
|
|
90
|
+
state.cache.set(value, enriched); // Learn for next time
|
|
91
|
+
return [enriched, state];
|
|
92
|
+
})
|
|
93
|
+
);
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
**Async transformation with memory** - the alchemist doesn't just transform, it **builds institutional knowledge** while preserving the natural order of events.
|
|
97
|
+
|
|
98
|
+
## Essential Copy-Paste Transformers
|
|
99
|
+
|
|
100
|
+
### simpleMap - Gateway to Adaptation
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
// For users transitioning from traditional mapping
|
|
104
|
+
const simpleMap = <T, U>(fn: (value: T) => U | Promise<U>) =>
|
|
105
|
+
map<T, {}, U>({}, async (_, value) => {
|
|
106
|
+
const result = await fn(value);
|
|
107
|
+
return [result, {}];
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
// Usage: familiar syntax, adaptive foundation
|
|
111
|
+
stream.pipe(simpleMap((x) => x * 2));
|
|
112
|
+
stream.pipe(simpleMap(async (user) => await enrichUser(user)));
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
**Design choice**: `simpleMap` is a **bridge**, not a replacement. It introduces users to the adaptive architecture while providing familiar syntax. The empty state `{}` is an invitation to evolution.
|
|
116
|
+
|
|
117
|
+
### withIndex - The Counting Alchemist
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
const withIndex = <T>() =>
|
|
121
|
+
map<T, { index: number }, { value: T; index: number }>({ index: 0 }, (state, value) => [
|
|
122
|
+
{ value, index: state.index },
|
|
123
|
+
{ index: state.index + 1 },
|
|
124
|
+
]);
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
`withIndex` demonstrates **sequential awareness** - the transformer knows its place in the stream's history and shares that knowledge.
|
|
128
|
+
|
|
129
|
+
### delay - The Patient Alchemist
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
const delay = <T>(ms: number) =>
|
|
133
|
+
map<T, {}, T>({}, async (_, value) => {
|
|
134
|
+
await new Promise((resolve) => setTimeout(resolve, ms));
|
|
135
|
+
return [value, {}];
|
|
136
|
+
});
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
`delay` embodies **temporal transformation** - sometimes the most important transformation is time itself.
|
|
140
|
+
|
|
141
|
+
### pluck - The Focused Alchemist
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
const pluck = <T, K extends keyof T>(key: K) => map<T, {}, T[K]>({}, (_, value) => [value[key], {}]);
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
`pluck` demonstrates **selective transformation** - the alchemist knows exactly what it wants and ignores everything else.
|
|
148
|
+
|
|
149
|
+
## The Order Preservation
|
|
150
|
+
|
|
151
|
+
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.
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
// Order is preserved even with varying async delays
|
|
155
|
+
stream.pipe(
|
|
156
|
+
map({}, async (_, value) => {
|
|
157
|
+
const delay = Math.random() * 1000; // Random processing time
|
|
158
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
159
|
+
return [await processValue(value), {}];
|
|
160
|
+
})
|
|
161
|
+
);
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
**Philosophy**: The stream is a story, and stories must be told in order.
|
|
165
|
+
|
|
166
|
+
## The State Evolution Pattern
|
|
167
|
+
|
|
168
|
+
State evolution follows a natural progression:
|
|
169
|
+
|
|
170
|
+
1. **Empty State** `{}` - The transformer starts innocent
|
|
171
|
+
2. **Simple State** `{ count: 0 }` - It learns to count
|
|
172
|
+
3. **Rich State** `{ sum: 0, count: 0, average: 0 }` - It develops complex understanding
|
|
173
|
+
4. **Intelligent State** `{ cache: Map, patterns: [], predictions: {} }` - It becomes wise
|
|
174
|
+
|
|
175
|
+
This mirrors how expertise develops in any field - from simple rules to nuanced understanding.
|
|
176
|
+
|
|
177
|
+
## Conclusion
|
|
178
|
+
|
|
179
|
+
The `map` transformer isn't just about changing values - it's about **intelligent transformation** that:
|
|
180
|
+
|
|
181
|
+
- **Remembers** previous transformations (state)
|
|
182
|
+
- **Learns** from patterns (adaptation)
|
|
183
|
+
- **Evolves** its approach over time (constraints)
|
|
184
|
+
- **Preserves** the narrative order (respect)
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Merge Transformer
|
|
2
|
+
|
|
3
|
+
## Temporal Orchestration
|
|
4
|
+
|
|
5
|
+
The `merge` transformer combines multiple streams into one unified flow while preserving temporal order - like conducting multiple instruments into a single symphony.
|
|
6
|
+
|
|
7
|
+
**Core Concept**: Multiple streams → One unified stream with union types
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
stream.pipe(merge(...otherStreams));
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
- **Input**: `Stream<T>` + `Stream<U>[]`
|
|
16
|
+
- **Output**: `Stream<T | U>`
|
|
17
|
+
- **Order**: Maintains chronological sequence across all streams
|
|
18
|
+
|
|
19
|
+
## Basic Example
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
const numbers = new Stream<number>();
|
|
23
|
+
const strings = new Stream<string>();
|
|
24
|
+
|
|
25
|
+
const combined = numbers.pipe(merge(strings));
|
|
26
|
+
// Type: Stream<number | string>
|
|
27
|
+
|
|
28
|
+
combined.listen((value) => {
|
|
29
|
+
if (typeof value === "number") {
|
|
30
|
+
console.log("Number:", value);
|
|
31
|
+
} else {
|
|
32
|
+
console.log("String:", value);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
numbers.push(1, 2);
|
|
37
|
+
strings.push("a", "b");
|
|
38
|
+
// Output: 1, 2, "a", "b" (in temporal order)
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Multiple Streams
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
const events = new Stream<Event>();
|
|
45
|
+
const errors = new Stream<Error>();
|
|
46
|
+
const logs = new Stream<LogEntry>();
|
|
47
|
+
|
|
48
|
+
const allActivity = events.pipe(merge(errors, logs));
|
|
49
|
+
// Type: Stream<Event | Error | LogEntry>
|
|
50
|
+
|
|
51
|
+
// All streams flow into one unified timeline
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Type Safety
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
interface UserEvent {
|
|
58
|
+
type: "user";
|
|
59
|
+
data: any;
|
|
60
|
+
}
|
|
61
|
+
interface SystemEvent {
|
|
62
|
+
type: "system";
|
|
63
|
+
data: any;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const userEvents = new Stream<UserEvent>();
|
|
67
|
+
const systemEvents = new Stream<SystemEvent>();
|
|
68
|
+
|
|
69
|
+
const allEvents = userEvents.pipe(merge(systemEvents));
|
|
70
|
+
|
|
71
|
+
allEvents.listen((event) => {
|
|
72
|
+
switch (event.type) {
|
|
73
|
+
case "user" /* handle user event */:
|
|
74
|
+
break;
|
|
75
|
+
case "system" /* handle system event */:
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
```
|
package/dist/benchmark.d.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
interface BenchmarkResult {
|
|
2
|
-
name: string;
|
|
3
|
-
operations: number;
|
|
4
|
-
duration: number;
|
|
5
|
-
opsPerSecond: number;
|
|
6
|
-
memoryUsage?: number;
|
|
7
|
-
}
|
|
8
|
-
declare class Benchmark {
|
|
9
|
-
private results;
|
|
10
|
-
run(name: string, operations: number, fn: () => Promise<void> | void): Promise<BenchmarkResult>;
|
|
11
|
-
getResults(): BenchmarkResult[];
|
|
12
|
-
printSummary(): void;
|
|
13
|
-
}
|
|
14
|
-
declare function runBenchmarks(): Promise<void>;
|
|
15
|
-
export { runBenchmarks, Benchmark };
|
|
16
|
-
//# sourceMappingURL=benchmark.d.ts.map
|
package/dist/benchmark.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"benchmark.d.ts","sourceRoot":"","sources":["../src/benchmark.ts"],"names":[],"mappings":"AAEA,UAAU,eAAe;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,cAAM,SAAS;IACb,OAAO,CAAC,OAAO,CAAyB;IAElC,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,eAAe,CAAC;IAgCrG,UAAU,IAAI,eAAe,EAAE;IAI/B,YAAY;CAMb;AAED,iBAAe,aAAa,kBAwI3B;AAOD,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,CAAC"}
|
package/dist/list.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../src/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;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;;;;;;;;;;;;OAYG;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;;;;;;;;;;;;OAYG;IACK,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,KAAK,KAAK,GAAG,SAAS,CAAC,GAAG,MAAM,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;IAEjF;;;;;;;;;;;;OAYG;IACK,KAAK,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAE3C;;;;;;;;;;;;;;;;;;;;;OAqBG;gBACS,KAAK,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC;IAiGnC;;;;;;;;;;;;OAYG;IACH,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS;IAIrC;;;;;;;;;;;OAWG;IACH,IAAI,MAAM,IAAI,MAAM,CAEnB;IACD;;;;;;;;;;OAUG;IACH,MAAM,IAAI,gBAAgB,CAAC,KAAK,CAAC;IAGjC;;;;;;;;;;;;OAYG;IACH,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,gBAAgB,CAAC,KAAK,CAAC;CAG7C"}
|
package/dist/map.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"map.d.ts","sourceRoot":"","sources":["../src/map.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;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;;;;;;;;;;;;;OAaG;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;;;;;;;;;;;;OAYG;IACK,MAAM,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;IAE/D;;;;;;;;;;;;OAYG;IACK,KAAK,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAE3C;;;;;;;;;;;;;;;;;;;;OAoBG;gBACS,OAAO,CAAC,EAAE,QAAQ,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;CAuD7C"}
|
package/dist/set.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"set.d.ts","sourceRoot":"","sources":["../src/set.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC;;;;;;;;;;;;;;;;;;;;;;;GAuBG;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;;;;;;;;;;;;OAYG;IACK,GAAG,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAEtD;;;;;;;;;;;;OAYG;IACK,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAE5D;;;;;;;;;;;;OAYG;IACK,KAAK,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAE3C;;;;;;;;;;;;;;;;;OAiBG;gBACS,MAAM,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC;CAqDrC"}
|
package/dist/state.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,KAAK,CAAC,KAAK,CAAE,SAAQ,MAAM,CAAC,KAAK,CAAC;IAC7C,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC;IAExB;;;;;;;;;;;OAWG;gBACS,YAAY,EAAE,KAAK;IAI/B;;;;;;;;;;;;;;OAcG;IACM,IAAI,CAAC,GAAG,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI;IAKvC;;;;;;;;OAQG;IACH,IAAI,KAAK,IAAI,KAAK,CAEjB;IACD;;;;;;;;;;;;;OAaG;IACH,IAAI,KAAK,CAAC,KAAK,EAAE,KAAK,EAGrB;CACF"}
|