@soffinal/stream 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +133 -25
- 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
- package/CHANGELOG.md +0 -22
|
@@ -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)
|
package/CHANGELOG.md
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
All notable changes to this project will be documented in this file.
|
|
4
|
-
|
|
5
|
-
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
-
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
-
|
|
8
|
-
## [Unreleased]
|
|
9
|
-
|
|
10
|
-
## [0.2.0] - 2024-12-19
|
|
11
|
-
|
|
12
|
-
### Changed
|
|
13
|
-
|
|
14
|
-
- **BREAKING**: Removed instance methods for transformers from Stream class - use `.pipe()` exclusively
|
|
15
|
-
- **BREAKING**: filte and map transformers signatures now require state-based accumulators instead of simple sync/async predicates
|
|
16
|
-
- Improved internal transformer implementation
|
|
17
|
-
|
|
18
|
-
## [0.1.4] - 2024-12-18
|
|
19
|
-
|
|
20
|
-
[Unreleased]: https://github.com/soffinal/stream/compare/v0.1.4...HEAD
|
|
21
|
-
[0.2.0]: https://github.com/soffinal/stream/compare/v0.1.4...v0.2.0
|
|
22
|
-
[0.1.4]: https://github.com/soffinal/stream/releases/tag/v0.1.4
|