@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.
Files changed (39) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +324 -269
  3. package/dist/index.d.ts +2 -4
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +2 -2
  6. package/dist/index.js.map +12 -8
  7. package/dist/reactive/index.d.ts +5 -0
  8. package/dist/reactive/index.d.ts.map +1 -0
  9. package/dist/{list.d.ts → reactive/list.d.ts} +1 -1
  10. package/dist/reactive/list.d.ts.map +1 -0
  11. package/dist/{map.d.ts → reactive/map.d.ts} +1 -1
  12. package/dist/reactive/map.d.ts.map +1 -0
  13. package/dist/{set.d.ts → reactive/set.d.ts} +1 -1
  14. package/dist/reactive/set.d.ts.map +1 -0
  15. package/dist/{state.d.ts → reactive/state.d.ts} +1 -1
  16. package/dist/reactive/state.d.ts.map +1 -0
  17. package/dist/stream.d.ts +1 -279
  18. package/dist/stream.d.ts.map +1 -1
  19. package/dist/transformers/filter.d.ts +64 -0
  20. package/dist/transformers/filter.d.ts.map +1 -0
  21. package/dist/transformers/flat.d.ts +29 -0
  22. package/dist/transformers/flat.d.ts.map +1 -0
  23. package/dist/transformers/index.d.ts +5 -0
  24. package/dist/transformers/index.d.ts.map +1 -0
  25. package/dist/transformers/map.d.ts +64 -0
  26. package/dist/transformers/map.d.ts.map +1 -0
  27. package/dist/transformers/merge.d.ts +33 -0
  28. package/dist/transformers/merge.d.ts.map +1 -0
  29. package/package.json +5 -8
  30. package/src/transformers/filter.md +161 -0
  31. package/src/transformers/flat.md +56 -0
  32. package/src/transformers/map.md +184 -0
  33. package/src/transformers/merge.md +79 -0
  34. package/dist/benchmark.d.ts +0 -16
  35. package/dist/benchmark.d.ts.map +0 -1
  36. package/dist/list.d.ts.map +0 -1
  37. package/dist/map.d.ts.map +0 -1
  38. package/dist/set.d.ts.map +0 -1
  39. package/dist/state.d.ts.map +0 -1
package/README.md CHANGED
@@ -5,9 +5,9 @@
5
5
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
6
  [![Bundle Size](https://img.shields.io/bundlephobia/minzip/@soffinal/stream)](https://bundlephobia.com/package/@soffinal/stream)
7
7
 
8
- > **High-performance reactive streaming library for TypeScript/JavaScript**
8
+ > **A reactive streaming library with Adaptive Constraints**
9
9
 
10
- A modern, async-first streaming library that treats asynchronous data flow as a first-class citizen. Built for real-time applications, event-driven architectures, and reactive programming patterns.
10
+ A groundbreaking streaming library that introduces **Adaptive Reactive Programming** - where transformers maintain state and evolve their behavior based on stream history. Built with four universal primitives that compose into infinite possibilities.
11
11
 
12
12
  ## Table of Contents
13
13
 
@@ -20,45 +20,73 @@ A modern, async-first streaming library that treats asynchronous data flow as a
20
20
  - [Performance](#performance)
21
21
  - [Browser Support](#browser-support)
22
22
  - [Migration Guide](#migration-guide)
23
+ - [Documentation](#documentation)
23
24
  - [Contributing](#contributing)
24
25
  - [License](#license)
25
26
 
26
27
  ## Features
27
28
 
28
- - 🚀 **High Performance** - Optimized for speed and efficiency
29
- - 🔄 **Multicast by Default** - One stream, many consumers
30
- - **Awaitable Streams** - `await stream` for next value
31
- - 🔁 **Async Iterable** - Use `for await` loops naturally
32
- - 🧠 **Smart Caching** - Operations run once, results shared
33
- - 🗑️ **Auto Cleanup** - Memory management handled automatically
34
- - 🔧 **Dual Programming Paradigms** - Method chaining or functional pipe composition
35
- - 🛠️ **Custom Transformers** - Create reusable transformers in both OOP and functional styles
36
- - 📊 **Reactive Collections** - Lists, Maps, Sets with fine-grained change events
37
- - 🔀 **Stateful Operations** - Built-in support for stateful filtering, mapping, and grouping
38
- - 📦 **Zero Dependencies** - Lightweight (~6KB minified, ~2KB gzipped) and tree-shakeable
29
+ - 🧠 **Adaptive Constraints** - Transformers that learn and evolve based on stream history
30
+ - 🔧 **Universal Primitives** - Four algebraic primitives: `filter`, `map`, `merge`, `flat`
31
+ - 📚 **Documentation-as-Distribution** - Copy-paste transformers embedded in JSDoc, no separate packages needed
32
+ - **Async-First** - All operations support async with order preservation
33
+ - 🔄 **Multicast Streams** - One stream, unlimited consumers
34
+ - **Awaitable** - `await stream` for next value
35
+ - 🔁 **Async Iterable** - Native `for await` loop support
36
+ - 🛠️ **Pipe Composition** - Functional transformer composition
37
+ - 📊 **Reactive State** - Stateful values with automatic change propagation
38
+ - 📋 **Reactive Collections** - Lists, Maps, Sets with fine-grained events
39
+ - 🗑️ **Stream Termination** - Declarative stream lifecycle control
40
+ - 📦 **Zero Dependencies** - Lightweight and tree-shakeable
39
41
  - 🌐 **Universal** - Node.js, browsers, Deno, Bun, Cloudflare Workers
40
- - 📘 **Full TypeScript** - Complete type safety and inference
42
+ - 📘 **Full TypeScript** - Complete type safety without the burden
41
43
 
42
44
  ## Quick Start
43
45
 
44
46
  ```typescript
45
- import { Stream, State } from "@soffinal/stream";
47
+ import { Stream, State, filter, map, merge } from "@soffinal/stream";
46
48
 
47
- // Create reactive data streams
49
+ // Create reactive streams
48
50
  const events = new Stream<string>();
49
- const counter = new State(0);
51
+ const numbers = new Stream<number>();
50
52
 
51
- // Transform and filter data
52
- const processed = events.filter((msg) => msg.length > 3).map((msg) => msg.toUpperCase());
53
+ // Pipe-based transformation with Adaptive Constraints
54
+ const processed = events
55
+ .pipe(simpleFilter((msg) => msg.length > 3)) // Simple filtering
56
+ .pipe(simpleMap((msg) => msg.toUpperCase())); // Transform to uppercase
53
57
 
54
- // Multiple consumers
55
- processed.listen((msg) => console.log("Logger:", msg));
56
- processed.listen((msg) => updateUI(msg));
58
+ // Stateful transformers that learn and adapt
59
+ const runningAverage = numbers
60
+ .pipe(
61
+ filter({ count: 0 }, (state, value) => {
62
+ // Only pass every 3rd number, terminate after 10
63
+ if (state.count >= 10) return; // Stream termination
64
+ return [(state.count + 1) % 3 === 0, { count: state.count + 1 }];
65
+ })
66
+ )
67
+ .pipe(
68
+ map({ sum: 0, count: 0 }, (state, value) => {
69
+ const newSum = state.sum + value;
70
+ const newCount = state.count + 1;
71
+ const average = newSum / newCount;
72
+ return [
73
+ { value, average },
74
+ { sum: newSum, count: newCount },
75
+ ];
76
+ })
77
+ );
57
78
 
58
- // Push data through the pipeline
59
- events.push("hello", "hi", "world"); // Only 'HELLO' and 'WORLD' processed
79
+ // Copy-paste transformers from JSDoc
80
+ const limited = numbers.pipe(take(5)); // Limit to 5 items
81
+ const indexed = events.pipe(withIndex()); // Add indices
82
+ const delayed = processed.pipe(delay(100)); // Delay each value
83
+
84
+ // Multiple consumers
85
+ processed.listen((msg) => console.log("Processed:", msg));
86
+ runningAverage.listen(({ value, average }) => console.log(`Value: ${value}, Running Average: ${average}`));
60
87
 
61
- // Reactive state management
88
+ // Reactive state
89
+ const counter = new State(0);
62
90
  counter.listen((count) => (document.title = `Count: ${count}`));
63
91
  counter.value++; // UI updates automatically
64
92
  ```
@@ -101,199 +129,319 @@ deno add jsr:@soffinal/stream
101
129
 
102
130
  ## Core Concepts
103
131
 
104
- ### Streams: Async Data Pipelines
132
+ ### Streams: Multicast Event Pipelines
105
133
 
106
- A `Stream` is an async iterable that can push values to multiple listeners while also being awaitable for the next value.
134
+ A `Stream` is a multicast, async iterable that pushes values to multiple listeners while being awaitable for the next value.
107
135
 
108
136
  ```typescript
109
137
  const userEvents = new Stream<UserEvent>();
110
138
 
111
- // Multiple consumers
139
+ // Multiple consumers automatically share the same data
112
140
  userEvents.listen((event) => analytics.track(event));
113
141
  userEvents.listen((event) => notifications.send(event));
114
142
  userEvents.listen((event) => database.save(event));
115
143
 
116
- // Or await the next event
144
+ // Await the next event
117
145
  const nextEvent = await userEvents;
146
+
147
+ // Async iteration
148
+ for await (const event of userEvents) {
149
+ if (event.type === "critical") break;
150
+ processEvent(event);
151
+ }
118
152
  ```
119
153
 
120
- ### Transformers: Fluent & Functional Styles
154
+ ### Universal Primitives: The Four Algebraic Operations
155
+
156
+ All stream operations are built from four universal primitives with **Adaptive Constraints**:
121
157
 
122
- #### Method Chaining (Fluent)
158
+ #### 1. Filter - Adaptive Gatekeeper
123
159
 
124
160
  ```typescript
125
- const stream = new Stream<number>();
126
-
127
- // Simple transformations
128
- const result = stream
129
- .filter((x) => x > 0)
130
- .map((x) => x * 2)
131
- .group((batch) => batch.length >= 5);
132
-
133
- // Stateful operations with initial state
134
- const stateful = stream
135
- .filter(0, (prev, curr) => [curr > prev, Math.max(prev, curr)]) // Only increasing values
136
- .map([], (history, value) => {
137
- const newHistory = [...history, value].slice(-3); // Keep last 3
138
- const average = newHistory.reduce((a, b) => a + b, 0) / newHistory.length;
139
- return [{ value, average, history: newHistory }, newHistory];
161
+ import { filter } from "@soffinal/stream";
162
+
163
+ // Simple filtering
164
+ stream.pipe(filter({}, (_, value) => [value > 0, {}]));
165
+
166
+ // Stateful filtering with termination
167
+ stream.pipe(
168
+ filter({ count: 0 }, (state, value) => {
169
+ if (state.count >= 10) return; // Terminate after 10 items
170
+ return [value > 0, { count: state.count + 1 }];
171
+ })
172
+ );
173
+
174
+ // Async filtering
175
+ stream.pipe(
176
+ filter({}, async (_, value) => {
177
+ const isValid = await validateAsync(value);
178
+ return [isValid, {}];
140
179
  })
141
- .group(5, (count, item) => [count >= 5, count >= 5 ? 0 : count + 1]); // Batch every 5
180
+ );
142
181
  ```
143
182
 
144
- #### Functional Composition (Pipe)
183
+ **[📖 Complete Filter Documentation →](src/transformers/filter.md)**
184
+
185
+ #### 2. Map - Adaptive Transformer
145
186
 
146
187
  ```typescript
147
- import { filter, map, group, merge } from "@soffinal/stream";
188
+ import { map } from "@soffinal/stream";
148
189
 
149
- // Simple functional composition
150
- const result = stream
151
- .pipe(filter((x) => x > 0))
152
- .pipe(map((x) => x * 2))
153
- .pipe(group((batch) => batch.length >= 5));
190
+ // Simple transformation
191
+ stream.pipe(map({}, (_, value) => [value * 2, {}]));
154
192
 
155
- // Stateful functional transformers
156
- const advanced = stream
157
- .pipe(filter(0, (prev, curr) => [curr > prev, Math.max(prev, curr)]))
158
- .pipe(
159
- map([], (acc, value) => {
160
- const newAcc = [...acc, value].slice(-10);
161
- const sum = newAcc.reduce((a, b) => a + b, 0);
162
- return [{ value, sum, count: newAcc.length }, newAcc];
163
- })
164
- )
165
- .pipe(group(0, (count, item) => [count >= 3, count >= 3 ? 0 : count + 1]));
166
-
167
- // Combining multiple streams
168
- const stream2 = new Stream<number>();
169
- const merged = stream
170
- .pipe(filter((x) => x % 2 === 0))
171
- .pipe(merge(stream2))
172
- .pipe(map((x) => x.toString()));
193
+ // Stateful transformation with context
194
+ stream.pipe(
195
+ map({ sum: 0 }, (state, value) => {
196
+ const newSum = state.sum + value;
197
+ return [{ value, runningSum: newSum }, { sum: newSum }];
198
+ })
199
+ );
200
+
201
+ // Async transformation with order preservation
202
+ stream.pipe(
203
+ map({}, async (_, value) => {
204
+ const enriched = await enrichWithAPI(value);
205
+ return [{ original: value, enriched }, {}];
206
+ })
207
+ );
173
208
  ```
174
209
 
175
- ### Custom Transformers
210
+ **[📖 Complete Map Documentation →](src/transformers/map.md)**
176
211
 
177
- Create reusable transformers for both paradigms:
212
+ #### 3. Merge - Stream Orchestration
178
213
 
179
214
  ```typescript
180
- // Custom transformer: distinctUntilChanged
181
- const distinctUntilChanged = <T>(stream: Stream<T>): Stream<T> => {
182
- return new Stream<T>(async function* () {
183
- let prev: T;
184
- let first = true;
185
-
186
- for await (const value of stream) {
187
- if (first || value !== prev) {
188
- yield value;
189
- prev = value;
190
- first = false;
191
- }
192
- }
193
- });
194
- };
195
-
196
- // Custom transformer: throttle
197
- const throttle =
198
- <T>(ms: number) =>
199
- (stream: Stream<T>): Stream<T> => {
200
- return new Stream<T>(async function* () {
201
- let lastEmit = 0;
202
-
203
- for await (const value of stream) {
204
- const now = Date.now();
205
- if (now - lastEmit >= ms) {
206
- yield value;
207
- lastEmit = now;
208
- }
209
- }
210
- });
211
- };
212
-
213
- // Usage with perfect type inference
215
+ import { merge } from "@soffinal/stream";
216
+
217
+ const stream1 = new Stream<number>();
218
+ const stream2 = new Stream<string>();
219
+
220
+ // Combine multiple streams with type safety
221
+ const combined = stream1.pipe(merge(stream2));
222
+ // Type: Stream<number | string>
223
+
224
+ combined.listen((value) => {
225
+ if (typeof value === "number") {
226
+ console.log("Number:", value);
227
+ } else {
228
+ console.log("String:", value);
229
+ }
230
+ });
231
+ ```
232
+
233
+ **[📖 Complete Merge Documentation →](src/transformers/merge.md)**
234
+
235
+ #### 4. Flat - Event Multiplication
236
+
237
+ ```typescript
238
+ import { flat } from "@soffinal/stream";
239
+
240
+ // Transform 1 array event N individual events
241
+ const arrayStream = new Stream<number[]>();
242
+ const individualNumbers = arrayStream.pipe(flat());
243
+
244
+ arrayStream.push([1, 2, 3]); // Emits: 1, 2, 3 as separate events
245
+
246
+ // Configurable depth flattening
247
+ const deepArrays = new Stream<number[][][]>();
248
+ const flattened = deepArrays.pipe(flat(2)); // Flatten 2 levels deep
249
+ ```
250
+
251
+ **[📖 Complete Flat Documentation →](src/transformers/flat.md)**
252
+
253
+ ### Documentation-as-Distribution: Revolutionary Copy-Paste Transformers
254
+
255
+ **🚀 World's First Documentation-as-Distribution System**
256
+
257
+ No separate repos, no CLI tools, no package management - just copy-paste ready transformers embedded in JSDoc!
258
+
259
+ ```typescript
260
+ // 📦 All transformers are copy-pastable from IntelliSense!
261
+ // Just hover over any primitive in your IDE to see the transformer library
262
+
263
+ // Example: Essential transformers available via autocomplete
214
264
  const searchInput = new Stream<string>();
215
265
  const searchResults = searchInput
216
- .pipe(distinctUntilChanged)
217
- .pipe(throttle(300))
218
- .pipe(map((query) => searchAPI(query)));
266
+ .pipe(distinct()) // Copy from filter() JSDoc
267
+ .pipe(simpleFilter((q) => q.length > 2)) // Copy from filter() JSDoc
268
+ .pipe(take(10)) // Copy from filter() JSDoc
269
+ .pipe(delay(300)) // Copy from map() JSDoc
270
+ .pipe(simpleMap((query) => searchAPI(query))); // Copy from map() JSDoc
271
+ ```
272
+
273
+ **Benefits:**
274
+
275
+ - ✅ **Zero friction** - Copy-paste ready transformers
276
+ - ✅ **Perfect discoverability** - IntelliSense shows all available transformers
277
+ - ✅ **Always up-to-date** - Examples match current API version
278
+ - ✅ **No ecosystem fragmentation** - Everything in one place
279
+ - ✅ **Self-documenting** - Usage examples included
280
+
281
+ **How it works:**
282
+
283
+ 1. Hover over `filter()`, `map()`, `merge()`, or `flat()` in your IDE
284
+ 2. Browse the 📦 COPY-PASTE TRANSFORMER examples
285
+ 3. Copy the transformer you need
286
+ 4. Use immediately - perfect TypeScript inference included!
287
+
288
+ **Available Transformers (via JSDoc):**
289
+
290
+ - `take(n)`, `skip(n)`, `distinct()` - Essential filtering
291
+ - `withIndex()`, `delay(ms)`, `pluck(key)` - Common transformations
292
+ - `simpleFilter(predicate)` - Convenient filtering without state
293
+ - `simpleMap(fn)` - Convenient mapping without state
294
+ - More transformers added with each release!
295
+
296
+ **📊 Bundle Size Impact:**
297
+
298
+ - **Package size**: Currently ~15KB, grows with JSDoc transformer examples over time
299
+ - **Your app bundle**: Always only 5.5KB (runtime code only, zero JSDoc overhead)
300
+ - **Tree-shaking**: Only imported functions included in final bundle
301
+ - **JSDoc transformers**: "Free" - rich transformer library without production cost
302
+
303
+ ### Manual Composition
304
+
305
+ ```typescript
306
+ // You can still build transformers manually
307
+ const customTransformer = <T>(count: number) =>
308
+ filter<T, { taken: number }>({ taken: 0 }, (state, value) => {
309
+ if (state.taken >= count) return; // Terminate after N items
310
+ return [true, { taken: state.taken + 1 }];
311
+ });
219
312
  ```
220
313
 
221
- ### Reactive State
314
+ ### Reactive State: Stateful Values
222
315
 
223
- State objects hold current values and notify dependents of changes:
316
+ `State` extends `Stream` with a current value that can be read and written:
224
317
 
225
318
  ```typescript
226
319
  const user = new State<User | null>(null);
227
320
  const theme = new State<"light" | "dark">("light");
321
+ const counter = new State(0);
228
322
 
229
- // Derived state with transformations
230
- const isLoggedIn = user.map((u) => u !== null);
231
- const userProfile = user
232
- .filter((u): u is User => u !== null)
233
- .map((u) => ({ ...u, displayName: u.firstName + " " + u.lastName }));
323
+ // Read current value
324
+ console.log(counter.value); // 0
325
+
326
+ // Write triggers all listeners
327
+ counter.value = 5;
328
+
329
+ // Derived state using transformers
330
+ const isLoggedIn = user.pipe(map({}, (_, u) => [u !== null, {}]));
331
+
332
+ const userDisplayName = user.pipe(
333
+ filter({}, (_, u) => [u !== null, {}]),
334
+ map({}, (_, u) => [`${u.firstName} ${u.lastName}`, {}])
335
+ );
234
336
 
235
337
  // Automatic UI updates
236
338
  isLoggedIn.listen((loggedIn) => {
237
339
  document.body.classList.toggle("authenticated", loggedIn);
238
340
  });
341
+
342
+ // State changes propagate through the pipeline
343
+ user.value = { firstName: "John", lastName: "Doe" };
344
+ // Triggers: isLoggedIn → true, userDisplayName → 'John Doe'
239
345
  ```
240
346
 
241
- ### Reactive Collections
347
+ ### Reactive Collections: Fine-Grained Change Events
242
348
 
243
- Collections that emit fine-grained change events:
349
+ Collections that emit specific change events for efficient UI updates:
244
350
 
245
351
  ```typescript
352
+ import { List, Map, Set } from "@soffinal/stream";
353
+
246
354
  const todos = new List<Todo>();
247
- const cache = new Map<string, any>();
355
+ const userCache = new Map<string, User>();
248
356
  const activeUsers = new Set<string>();
249
357
 
250
- // React to changes
251
- todos.insert.listen(([index, todo]) => renderTodo(todo, index));
252
- cache.set.listen(([key, value]) => console.log(`Cached: ${key}`));
253
- activeUsers.add.listen((userId) => showOnlineStatus(userId));
358
+ // React to specific operations
359
+ todos.insert.listen(([index, todo]) => {
360
+ console.log(`Todo inserted at ${index}:`, todo);
361
+ renderTodoAtIndex(index, todo);
362
+ });
363
+
364
+ todos.delete.listen(([index, todo]) => {
365
+ console.log(`Todo removed from ${index}:`, todo);
366
+ removeTodoFromDOM(index);
367
+ });
368
+
369
+ // Map changes
370
+ userCache.set.listen(([key, user]) => {
371
+ console.log(`User cached: ${key}`, user);
372
+ updateUserInUI(key, user);
373
+ });
374
+
375
+ // Set changes
376
+ activeUsers.add.listen((userId) => {
377
+ console.log(`User ${userId} came online`);
378
+ showOnlineIndicator(userId);
379
+ });
380
+
381
+ activeUsers.delete.listen((userId) => {
382
+ console.log(`User ${userId} went offline`);
383
+ hideOnlineIndicator(userId);
384
+ });
385
+
386
+ // Use like normal collections
387
+ todos.push({ id: 1, text: "Learn streams", done: false });
388
+ userCache.set("user1", { name: "Alice", email: "alice@example.com" });
389
+ activeUsers.add("user1");
254
390
  ```
255
391
 
256
392
  ## API Reference
257
393
 
258
394
  ### Stream\<T>
259
395
 
396
+ #### Core Methods
397
+
398
+ - `push(...values: T[]): void` - Emit values to all listeners
399
+ - `listen(callback: (value: T) => void, signal?: AbortSignal | Stream<any>): () => void` - Add listener, returns cleanup
400
+ - `pipe<U>(transformer: (stream: Stream<T>) => Stream<U>): Stream<U>` - Apply functional transformer
401
+
402
+ #### Async Interface
403
+
404
+ - `then<U>(callback?: (value: T) => U): Promise<U>` - Promise interface for next value
405
+ - `[Symbol.asyncIterator](): AsyncIterator<T>` - Async iteration support
406
+
260
407
  #### Properties
261
408
 
262
409
  - `hasListeners: boolean` - Whether stream has active listeners
263
410
  - `listenerAdded: Stream<void>` - Emits when listener is added
264
411
  - `listenerRemoved: Stream<void>` - Emits when listener is removed
265
412
 
266
- #### Methods
413
+ ### State\<T> extends Stream\<T>
267
414
 
268
- - `push(...values: T[]): void` - Emit values to all listeners
269
- - `listen(callback: (value: T) => void, signal?: AbortSignal): () => void` - Add listener
270
- - `filter(predicate: (value: T) => boolean): Stream<T>` - Filter values
271
- - `map<U>(mapper: (value: T) => U): Stream<U>` - Transform values
272
- - `merge(...streams: Stream<T>[]): Stream<T>` - Combine streams
273
- - `group(predicate: (batch: T[]) => boolean): Stream<T[]>` - Batch values
274
- - `flat(depth?: number): Stream<U>` - Flatten arrays
275
- - `pipe<U>(transformer: (stream: Stream<T>) => Stream<U>): Stream<U>` - Apply transformer
415
+ #### Additional Properties
276
416
 
277
- #### Async Interface
417
+ - `value: T` - Current state value (get/set)
278
418
 
279
- - `then<U>(callback?: (value: T) => U): Promise<U>` - Promise interface
280
- - `[Symbol.asyncIterator](): AsyncIterator<T>` - Async iteration
419
+ ### Universal Transformers
281
420
 
282
- ### State\<T> extends Stream\<T>
421
+ #### filter(initialState, accumulator)
283
422
 
284
- #### Properties
423
+ - **Simple**: `filter({}, (_, value) => [boolean, {}])`
424
+ - **Stateful**: `filter(state, (state, value) => [boolean, newState])`
425
+ - **Async**: `filter({}, async (_, value) => [boolean, {}])`
426
+ - **Termination**: Return `undefined` to terminate stream
285
427
 
286
- - `value: T` - Current state value (get/set)
428
+ #### map(initialState, accumulator)
429
+
430
+ - **Simple**: `map({}, (_, value) => [newValue, {}])`
431
+ - **Stateful**: `map(state, (state, value) => [newValue, newState])`
432
+ - **Async**: `map({}, async (_, value) => [newValue, {}])`
433
+
434
+ #### merge(...streams)
287
435
 
288
- ### Transformer Functions
436
+ - **Basic**: `stream.pipe(merge(stream2, stream3))`
437
+ - **Type-Safe**: Automatically creates union types
438
+ - **Temporal Order**: Maintains chronological sequence
289
439
 
290
- Functional transformers for use with `pipe()`:
440
+ #### flat(depth?)
291
441
 
292
- - `filter<T>(predicate: (value: T) => boolean): (stream: Stream<T>) => Stream<T>`
293
- - `map<T, U>(mapper: (value: T) => U): (stream: Stream<T>) => Stream<U>`
294
- - `group<T>(predicate: (batch: T[]) => boolean): (stream: Stream<T>) => Stream<T[]>`
295
- - `merge<T>(...streams: Stream<T>[]): (stream: Stream<T>) => Stream<T>`
296
- - `flat<T>(depth?: number): (stream: Stream<T>) => Stream<U>`
442
+ - **Basic**: `stream.pipe(flat())` - Flatten one level
443
+ - **Deep**: `stream.pipe(flat(2))` - Flatten N levels
444
+ - **Event Multiplication**: 1 array event N individual events
297
445
 
298
446
  ### Reactive Collections
299
447
 
@@ -315,111 +463,22 @@ Functional transformers for use with `pipe()`:
315
463
  - `delete: Stream<T>` - Delete events
316
464
  - `clear: Stream<void>` - Clear events
317
465
 
318
- ## Examples
319
-
320
- ### Real-time Data Processing
321
-
322
- ```typescript
323
- const sensorData = new Stream<SensorReading>();
324
-
325
- // Multi-stage processing pipeline
326
- const alerts = sensorData
327
- .filter((reading) => reading.temperature > 30)
328
- .map((reading) => ({ ...reading, timestamp: Date.now() }))
329
- .group((batch) => batch.length >= 5);
330
-
331
- alerts.listen((batch) => sendAlertNotification(batch));
332
- ```
333
-
334
- ### WebSocket Integration
335
-
336
- ```typescript
337
- const wsStream = new Stream<MessageEvent>(async function* () {
338
- const ws = new WebSocket("wss://api.example.com");
339
-
340
- while (ws.readyState !== WebSocket.CLOSED) {
341
- yield await new Promise((resolve) => {
342
- ws.onmessage = resolve;
343
- });
344
- }
345
- });
346
-
347
- const messages = wsStream.map((event) => JSON.parse(event.data)).filter((data) => data.type === "update");
348
-
349
- messages.listen((update) => handleUpdate(update));
350
- ```
351
-
352
- ### State Management
353
-
354
- ```typescript
355
- interface AppState {
356
- user: User | null;
357
- theme: "light" | "dark";
358
- notifications: Notification[];
359
- }
360
-
361
- const appState = new State<AppState>({
362
- user: null,
363
- theme: "light",
364
- notifications: [],
365
- });
366
-
367
- // Derived state
368
- const unreadCount = appState.map((state) => state.notifications.filter((n) => !n.read).length);
369
-
370
- // Reactive UI
371
- unreadCount.listen((count) => {
372
- document.title = count > 0 ? `(${count}) App` : "App";
373
- });
374
- ```
375
-
376
- ### Browser Counter Example
377
-
378
- ```html
379
- <!DOCTYPE html>
380
- <html>
381
- <head>
382
- <title>Reactive Counter</title>
383
- </head>
384
- <body>
385
- <div id="counter">0</div>
386
- <button id="increment">+</button>
387
- <button id="decrement">-</button>
388
-
389
- <script type="module">
390
- import { State } from "https://esm.sh/@soffinal/stream";
391
-
392
- const count = new State(0);
393
- const display = document.getElementById("counter");
394
-
395
- // Reactive UI updates
396
- count.listen((value) => (display.textContent = value));
397
-
398
- // User interactions
399
- document.getElementById("increment").onclick = () => count.value++;
400
- document.getElementById("decrement").onclick = () => count.value--;
401
- </script>
402
- </body>
403
- </html>
404
- ```
405
-
406
466
  ## Performance
407
467
 
408
- @soffinal/stream delivers exceptional performance:
468
+ ### Bundle Size
409
469
 
410
- - **High throughput** for basic operations
411
- - **Efficient processing** for complex pipelines
412
- - **Memory efficient** with automatic cleanup
413
- - **Zero overhead** for unused features
470
+ - **Runtime bundle** - 5.5KB minified, 1.6KB gzipped
471
+ - **Package size** - Starts small, grows with JSDoc transformer library
472
+ - **Your production app** - Always gets only the 5.5KB runtime code
473
+ - **Tree-shakeable** - Import only what you use
414
474
 
415
- ### Performance Characteristics
475
+ ### Benchmarks
416
476
 
417
- - **Optimized data structures** for minimal memory allocation
418
- - **Efficient event dispatch** with smart caching
419
- - **Lazy evaluation** reduces unnecessary computations
420
- - **Automatic cleanup** prevents memory leaks
477
+ - **Fast startup** - Zero dependencies, instant initialization
478
+ - **Efficient pipelines** - Optimized transformer composition
479
+ - **Memory bounded** - Built-in backpressure handling
421
480
 
422
- ## Browser Support
481
+ ## Runtime Support
423
482
 
424
483
  - **Modern browsers** supporting ES2020+
425
484
  - **Node.js** 16+
@@ -429,28 +488,6 @@ unreadCount.listen((count) => {
429
488
 
430
489
  ## Migration Guide
431
490
 
432
- ### From RxJS
433
-
434
- ```typescript
435
- // RxJS
436
- import { Subject, map, filter } from "rxjs";
437
- const subject = new Subject();
438
- subject
439
- .pipe(
440
- filter((x) => x > 0),
441
- map((x) => x * 2)
442
- )
443
- .subscribe(console.log);
444
-
445
- // @soffinal/stream
446
- import { Stream } from "@soffinal/stream";
447
- const stream = new Stream();
448
- stream
449
- .filter((x) => x > 0)
450
- .map((x) => x * 2)
451
- .listen(console.log);
452
- ```
453
-
454
491
  ### From EventEmitter
455
492
 
456
493
  ```typescript
@@ -467,6 +504,24 @@ stream.listen(console.log);
467
504
  stream.push("hello");
468
505
  ```
469
506
 
507
+ ## Documentation
508
+
509
+ ### Transformer Guides
510
+
511
+ - **[Filter Transformer →](src/transformers/filter.md)** - Adaptive constraints and stream termination
512
+ - **[Map Transformer →](src/transformers/map.md)** - Stateful transformations and async processing
513
+ - **[Merge Transformer →](src/transformers/merge.md)** - Stream orchestration and type-safe combination
514
+ - **[Flat Transformer →](src/transformers/flat.md)** - Event multiplication and array flattening
515
+
516
+ ### Philosophy
517
+
518
+ **Adaptive Reactive Programming** - A new paradigm where transformers maintain state and evolve their behavior based on stream history. This enables:
519
+
520
+ - **Learning transformers** that adapt to data patterns
521
+ - **Stateful operations** with memory between events
522
+ - **Stream termination** for lifecycle control
523
+ - **Zero-overhead types** with perfect inference
524
+
470
525
  ## Contributing
471
526
 
472
527
  We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
@@ -489,5 +544,5 @@ Contact: <smari.sofiane@gmail.com>
489
544
  ---
490
545
 
491
546
  <div align="center">
492
- <strong>Built with ❤️ for the JavaScript community</strong>
547
+ <strong>Pioneering Adaptive Reactive Programming</strong>
493
548
  </div>