@soffinal/stream 0.2.2 → 0.2.4

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 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
- > **Enhanced event emitters with functional composition**
8
+ > **Type-safe event emitters that scale**
9
9
 
10
- A modern event emitter that's multicast, awaitable, async iterable, async generable, and pipeable. Like EventEmitter but with functional transformations, perfect TypeScript inference, and copy-paste transformers embedded in JSDoc.
10
+ Stream is like EventEmitter, but better. Send events to multiple listeners, transform data with `filter` and `map`, and never worry about memory leaks. Works with DOM elements, WebSockets, user interactions, or any async data source. Fully typed, zero dependencies, 5.5KB.
11
11
 
12
12
  ## Table of Contents
13
13
 
@@ -25,34 +25,70 @@ A modern event emitter that's multicast, awaitable, async iterable, async genera
25
25
 
26
26
  ## Features
27
27
 
28
- - 🧠 **Adaptive Constraints** - Transformers that learn and evolve based on stream history
29
- - 🔧 **Universal Primitives** - Four algebraic primitives: `filter`, `map`, `merge`, `flat`
30
- - 📚 **Documentation-as-Distribution** - Copy-paste transformers embedded in JSDoc, no separate packages needed
31
- - **Async-First** - All operations support async with order preservation
32
- - 🔄 **Multicast Streams** - One stream, unlimited consumers
33
- - **Awaitable** - `await stream` for next value
34
- - 🔁 **Async Iterable** - Native `for await` loop support
35
- - 🛠️ **Pipe Composition** - Functional transformer composition
36
- - 📊 **Reactive State** - Stateful values with automatic change propagation
37
- - 📋 **Reactive Collections** - Lists, Maps, Sets with fine-grained events
38
- - 🗑️ **Stream Termination** - Declarative stream lifecycle control
39
- - 📦 **Zero Dependencies** - Lightweight and tree-shakeable
40
- - 🌐 **Universal** - Node.js, browsers, Deno, Bun, Cloudflare Workers
41
- - 📘 **Full TypeScript** - Complete type safety without the burden
28
+ - **Adaptive Constraints** - Transformers that learn and evolve based on stream history
29
+ - **Universal Primitives** - Four primitives: `filter`, `map`, `merge`, `flat`
30
+ - **Documentation-as-Distribution** - Copy-paste transformers embedded in JSDoc, no separate packages needed
31
+ - **Async-First** - Native async/await support with configurable concurrency control
32
+ - **Concurrency Strategies** - Sequential, concurrent-unordered, concurrent-ordered processing
33
+ - **Automatic Cleanup** - WeakRef-based listener cleanup prevents memory leaks
34
+ - **Multicast Streams** - One stream, unlimited consumers
35
+ - **Awaitable** - `await stream` for next value
36
+ - **Async Iterable** - Native `for await` loop support
37
+ - **Pipe Composition** - Stream-to-stream functional composition
38
+ - **Type Guards** - Built-in TypeScript type narrowing support
39
+ - **Reactive State** - Stateful values with automatic change propagation
40
+ - **Reactive Collections** - Lists, Maps, Sets with fine-grained events
41
+ - **Stream Termination** - Declarative stream lifecycle control
42
+ - **Zero Dependencies** - Lightweight and tree-shakeable
43
+ - **Universal** - Node.js, browsers, Deno, Bun, Cloudflare Workers
44
+ - **Full TypeScript** - Complete type safety without the burden
42
45
 
43
46
  ## Quick Start
44
47
 
48
+ ```typescript
49
+ import { Stream } from "@soffinal/stream";
50
+
51
+ const events = new Stream<string>();
52
+
53
+ events.listen(console.log);
54
+
55
+ events.push("Hello"); //log: Hello
56
+ ```
57
+
58
+ ## Examples
59
+
45
60
  ```typescript
46
61
  import { Stream, State, filter, map, merge } from "@soffinal/stream";
47
62
 
48
- // Create reactive streams
63
+ // Create streams
49
64
  const events = new Stream<string>();
50
65
  const numbers = new Stream<number>();
51
66
 
52
- // Pipe-based transformation with Adaptive Constraints
67
+ // Pull-based stream from async generator
68
+ const websocketStream = new Stream(async function* () {
69
+ const ws = new WebSocket("ws://localhost:8080");
70
+ while (ws.readyState === WebSocket.OPEN) {
71
+ yield await new Promise((resolve) => {
72
+ ws.onmessage = (event) => resolve(JSON.parse(event.data));
73
+ });
74
+ }
75
+ });
76
+
77
+ // Simple transformations
53
78
  const processed = events
54
- .pipe(simpleFilter((msg) => msg.length > 3)) // Simple filtering
55
- .pipe(simpleMap((msg) => msg.toUpperCase())); // Transform to uppercase
79
+ .pipe(filter((msg) => msg.length > 3)) // Simple filtering
80
+ .pipe(map((msg) => msg.toUpperCase())); // Transform to uppercase
81
+
82
+ // Async transformations with concurrency
83
+ const validated = events.pipe(
84
+ filter(
85
+ async (msg) => {
86
+ const isValid = await validateAsync(msg);
87
+ return isValid;
88
+ },
89
+ { strategy: "concurrent-ordered" }
90
+ ) // Parallel validation, ordered results
91
+ );
56
92
 
57
93
  // Stateful transformers that learn and adapt
58
94
  const runningAverage = numbers
@@ -75,6 +111,12 @@ const runningAverage = numbers
75
111
  })
76
112
  );
77
113
 
114
+ // Automatic cleanup with DOM elements
115
+ const element = document.createElement('div');
116
+ events.listen(value => {
117
+ element.textContent = value;
118
+ }, element); // Auto-removed when element is GC'd
119
+
78
120
  // Copy-paste transformers from JSDoc
79
121
  const limited = numbers.pipe(take(5)); // Limit to 5 items
80
122
  const indexed = events.pipe(withIndex()); // Add indices
@@ -82,6 +124,7 @@ const delayed = processed.pipe(delay(100)); // Delay each value
82
124
 
83
125
  // Multiple consumers
84
126
  processed.listen((msg) => console.log("Processed:", msg));
127
+ validated.listen((msg) => console.log("Validated:", msg));
85
128
  runningAverage.listen(({ value, average }) => console.log(`Value: ${value}, Running Average: ${average}`));
86
129
 
87
130
  // Reactive state
@@ -150,20 +193,69 @@ for await (const event of userEvents) {
150
193
  }
151
194
  ```
152
195
 
196
+ ### Automatic Listener Cleanup
197
+
198
+ Stream provides three cleanup mechanisms to prevent memory leaks:
199
+
200
+ ```typescript
201
+ const stream = new Stream<string>();
202
+
203
+ // 1. Manual cleanup
204
+ const cleanup = stream.listen(value => console.log(value));
205
+ cleanup(); // Remove listener
206
+
207
+ // 2. AbortSignal cleanup
208
+ const controller = new AbortController();
209
+ stream.listen(value => console.log(value), controller.signal);
210
+ controller.abort(); // Remove listener
211
+
212
+ // 3. WeakRef automatic cleanup (NEW!)
213
+ const element = document.createElement('div');
214
+ stream.listen(value => {
215
+ element.textContent = value;
216
+ }, element);
217
+ // Listener automatically removed when element is garbage collected
218
+ // Perfect for DOM elements, components, and temporary objects
219
+ ```
220
+
221
+ **WeakRef Benefits:**
222
+ - Zero memory leaks with DOM elements
223
+ - No manual cleanup needed
224
+ - Works with any object (components, instances, etc.)
225
+ - Leverages JavaScript's garbage collector
226
+ - Ideal for UI frameworks (React, Vue, Svelte, etc.)
227
+
228
+ ```typescript
229
+ // Real-world example: Component lifecycle
230
+ function createComponent() {
231
+ const element = document.createElement('div');
232
+ const dataStream = new Stream<Data>();
233
+
234
+ // Auto-cleanup when component unmounts
235
+ dataStream.listen(data => {
236
+ element.innerHTML = renderTemplate(data);
237
+ }, element);
238
+
239
+ return element;
240
+ }
241
+
242
+ // When element is removed from DOM and GC'd, listener is automatically cleaned up
243
+ ```
244
+
153
245
  ### Pipe: Stream-to-Stream Composition
154
246
 
155
- The `pipe` method enforces reactive composition - it only accepts functions that return Stream instances, maintaining the infinite reactive pipeline:
247
+ The `pipe` method enforces composition - it only accepts functions that return Stream instances, maintaining the infinite pipeline:
156
248
 
157
249
  ```typescript
158
250
  // All transformers return Streams - infinite chaining
159
- stream.pipe(filter({}, (_, v) => [v > 0, {}])); // → Stream<T>
160
- stream.pipe(map({}, (_, v) => [v.toString(), {}])); // → Stream<string>
251
+ stream.pipe(filter((v) => v > 0)); // → Stream<T>
252
+ stream.pipe(map((v) => v.toString())); // → Stream<string>
161
253
  stream.pipe(toState("initial")); // → State<string> (extends Stream)
162
254
 
163
255
  // Infinite chaining - every pipe returns a Stream
164
256
  const result = stream
165
- .pipe(filter({}, (_, v) => [v > 0, {}]))
166
- .pipe(map({}, (_, v) => [v * 2, {}]))
257
+ .pipe(filter((v) => v > 0))
258
+ .pipe(map((v) => v * 2))
167
259
  .pipe(take(5))
168
260
  .pipe(delay(100))
169
261
  .pipe(distinct()); // Always chainable
@@ -177,8 +269,8 @@ const result = stream
177
269
  const numbers = new Stream<number>();
178
270
 
179
271
  // TypeScript knows these are all Streams
180
- const doubled = numbers.pipe(map({}, (_, n) => [n * 2, {}])); // Stream<number>
181
- const strings = numbers.pipe(map({}, (_, n) => [n.toString(), {}])); // Stream<string>
272
+ const doubled = numbers.pipe(map((n) => n * 2)); // Stream<number>
273
+ const strings = numbers.pipe(map((n) => n.toString())); // Stream<string>
182
274
  const state = numbers.pipe(toState(0)); // State<number>
183
275
  ```
184
276
 
@@ -186,13 +278,27 @@ const state = numbers.pipe(toState(0)); // State<number>
186
278
 
187
279
  All stream operations are built from four universal primitives with **Adaptive Constraints**:
188
280
 
189
- #### 1. Filter - Adaptive Gatekeeper
281
+ #### 1. Filter
190
282
 
191
283
  ```typescript
192
284
  import { filter } from "@soffinal/stream";
193
285
 
194
286
  // Simple filtering
195
- stream.pipe(filter({}, (_, value) => [value > 0, {}]));
287
+ stream.pipe(filter((value) => value > 0));
288
+
289
+ // Type guard filtering
290
+ stream.pipe(filter((value): value is number => typeof value === "number"));
291
+
292
+ // Async filtering with concurrency strategies
293
+ stream.pipe(
294
+ filter(
295
+ async (value) => {
296
+ const isValid = await validateAsync(value);
297
+ return isValid;
298
+ },
299
+ { strategy: "concurrent-ordered" }
300
+ ) // Parallel validation, ordered results
301
+ );
196
302
 
197
303
  // Stateful filtering with termination
198
304
  stream.pipe(
@@ -201,14 +307,6 @@ stream.pipe(
201
307
  return [value > 0, { count: state.count + 1 }];
202
308
  })
203
309
  );
204
-
205
- // Async filtering
206
- stream.pipe(
207
- filter({}, async (_, value) => {
208
- const isValid = await validateAsync(value);
209
- return [isValid, {}];
210
- })
211
- );
212
310
  ```
213
311
 
214
312
  **[📖 Complete Filter Documentation →](src/transformers/filter.md)**
@@ -219,7 +317,21 @@ stream.pipe(
219
317
  import { map } from "@soffinal/stream";
220
318
 
221
319
  // Simple transformation
222
- stream.pipe(map({}, (_, value) => [value * 2, {}]));
320
+ stream.pipe(map((value) => value * 2));
321
+
322
+ // Type transformation
323
+ stream.pipe(map((value: number) => value.toString()));
324
+
325
+ // Async transformation with concurrency strategies
326
+ stream.pipe(
327
+ map(
328
+ async (value) => {
329
+ const enriched = await enrichWithAPI(value);
330
+ return enriched;
331
+ },
332
+ { strategy: "concurrent-unordered" }
333
+ ) // Parallel processing, results as completed
334
+ );
223
335
 
224
336
  // Stateful transformation with context
225
337
  stream.pipe(
@@ -228,14 +340,6 @@ stream.pipe(
228
340
  return [{ value, runningSum: newSum }, { sum: newSum }];
229
341
  })
230
342
  );
231
-
232
- // Async transformation with order preservation
233
- stream.pipe(
234
- map({}, async (_, value) => {
235
- const enriched = await enrichWithAPI(value);
236
- return [{ original: value, enriched }, {}];
237
- })
238
- );
239
343
  ```
240
344
 
241
345
  **[📖 Complete Map Documentation →](src/transformers/map.md)**
@@ -273,10 +377,12 @@ const arrayStream = new Stream<number[]>();
273
377
  const individualNumbers = arrayStream.pipe(flat());
274
378
 
275
379
  arrayStream.push([1, 2, 3]); // Emits: 1, 2, 3 as separate events
380
+ // Type: Stream<number>
276
381
 
277
382
  // Configurable depth flattening
278
383
  const deepArrays = new Stream<number[][][]>();
279
384
  const flattened = deepArrays.pipe(flat(2)); // Flatten 2 levels deep
385
+ // Type: Stream<number>
280
386
  ```
281
387
 
282
388
  **[📖 Complete Flat Documentation →](src/transformers/flat.md)**
@@ -285,9 +391,7 @@ const flattened = deepArrays.pipe(flat(2)); // Flatten 2 levels deep
285
391
 
286
392
  No separate repos, no CLI tools, no package management - just copy-paste ready transformers embedded in JSDoc!
287
393
 
288
- But more importantly: **Documentation-as-Distribution is actually Education-as-Distribution.**
289
-
290
- #### The Educational Transparency Revolution
394
+ #### The Educational Transparency
291
395
 
292
396
  Our approach makes **every implementation pattern visible and learnable**:
293
397
 
@@ -299,7 +403,6 @@ Our approach makes **every implementation pattern visible and learnable**:
299
403
  const searchInput = new Stream<string>(); // ← Hover here for full library
300
404
  const searchResults = searchInput
301
405
  .pipe(distinct()) // Copy from Stream JSDoc - learn deduplication patterns
302
- .pipe(simpleFilter((q) => q.length > 2)) // Copy from Stream JSDoc - learn filtering logic
303
406
  .pipe(take(10)) // Copy from Stream JSDoc - learn termination patterns
304
407
  .pipe(delay(300)) // Copy from Stream JSDoc - learn async transformation
305
408
  .pipe(simpleMap((query) => searchAPI(query))); // Copy from Stream JSDoc - learn mapping patterns
@@ -383,8 +486,6 @@ Documentation-as-Distribution creates **multiplicative value**:
383
486
 
384
487
  - `take(n)`, `skip(n)`, `distinct()`, `tap(fn)` - Essential filtering patterns
385
488
  - `withIndex()`, `delay(ms)`, `pluck(key)`, `scan(fn, initial)` - Common transformation patterns
386
- - `simpleFilter(predicate)` - Convenient filtering without state
387
- - `simpleMap(fn)` - Convenient mapping without state
388
489
  - `toState(initialValue)` - Convert streams to reactive state
389
490
  - More transformers added with each release!
390
491
 
@@ -425,20 +526,20 @@ counter.value = 5;
425
526
 
426
527
  // State from transformed streams
427
528
  const source = new Stream<number>();
428
- const derivedState = new State(0, source.pipe(map({}, (_, v) => [v * 2, {}])));
529
+ const derivedState = new State(0, source.pipe(map((v) => v * 2)));
429
530
 
430
531
  // Derived state using transformers
431
- const isLoggedIn = user.pipe(map({}, (_, u) => [u !== null, {}]));
532
+ const isLoggedIn = user.pipe(map((u) => u !== null));
432
533
 
433
534
  const userDisplayName = user.pipe(
434
- filter({}, (_, u) => [u !== null, {}]),
435
- map({}, (_, u) => [`${u.firstName} ${u.lastName}`, {}])
535
+ filter((u) => u !== null),
536
+ map((u) => `${u.firstName} ${u.lastName}`)
436
537
  );
437
538
 
438
539
  // Convert streams to state with toState transformer
439
540
  const processedState = source
440
- .pipe(filter({}, (_, v) => [v > 0, {}]))
441
- .pipe(map({}, (_, v) => [v.toString(), {}]))
541
+ .pipe(filter((v) => v > 0))
542
+ .pipe(map((v) => v.toString()))
442
543
  .pipe(toState("0")); // Explicit initial value
443
544
 
444
545
  // Automatic UI updates
@@ -502,9 +603,10 @@ activeUsers.add("user1");
502
603
 
503
604
  #### Core Methods
504
605
 
505
- - `push(...values: T[]): void` - Emit values to all listeners
506
- - `listen(callback: (value: T) => void, signal?: AbortSignal | Stream<any>): () => void` - Add listener, returns cleanup
507
- - `pipe<OUTPUT>(transformer: (stream: this) => OUTPUT): OUTPUT` - Apply any transformer (flexible return type)
606
+ - `push(...values: T[]): void` - Emit values to all listeners (auto-removes GC'd listeners)
607
+ - `listen(callback: (value: T) => void, context?: AbortSignal | Stream<any> | object): () => void` - Add listener with optional cleanup
608
+ - `pipe<OUTPUT extends Stream<any>>(transformer: (stream: this) => OUTPUT): OUTPUT` - Apply any transformer
609
+ - `withContext(context: object): AsyncIterator<T>` - Async iterator bound to context lifetime
508
610
 
509
611
  #### Async Interface
510
612
 
@@ -530,18 +632,21 @@ activeUsers.add("user1");
530
632
 
531
633
  ### Universal Transformers
532
634
 
533
- #### filter(initialState, accumulator)
635
+ #### filter(predicate, options?)
534
636
 
535
- - **Simple**: `filter({}, (_, value) => [boolean, {}])`
536
- - **Stateful**: `filter(state, (state, value) => [boolean, newState])`
537
- - **Async**: `filter({}, async (_, value) => [boolean, {}])`
637
+ - **Simple**: `filter((value) => boolean)`
638
+ - **Type Guard**: `filter((value): value is Type => boolean)` (sync only)
639
+ - **Async**: `filter(async (value) => boolean, { strategy? })` with concurrency options
640
+ - **Stateful**: `filter(state, (state, value) => [boolean, newState])` (always sequential)
538
641
  - **Termination**: Return `undefined` to terminate stream
642
+ - **Strategies**: `"sequential"` | `"concurrent-unordered"` | `"concurrent-ordered"`
539
643
 
540
- #### map(initialState, accumulator)
644
+ #### map(mapper, options?)
541
645
 
542
- - **Simple**: `map({}, (_, value) => [newValue, {}])`
543
- - **Stateful**: `map(state, (state, value) => [newValue, newState])`
544
- - **Async**: `map({}, async (_, value) => [newValue, {}])`
646
+ - **Simple**: `map((value) => newValue)`
647
+ - **Async**: `map(async (value) => newValue, { strategy? })` with concurrency options
648
+ - **Stateful**: `map(state, (state, value) => [newValue, newState])` (always sequential)
649
+ - **Strategies**: `"sequential"` | `"concurrent-unordered"` | `"concurrent-ordered"`
545
650
 
546
651
  #### merge(...streams)
547
652
 
@@ -589,10 +694,11 @@ activeUsers.add("user1");
589
694
  - **Fast startup** - Zero dependencies, instant initialization
590
695
  - **Efficient pipelines** - Optimized transformer composition
591
696
  - **Memory bounded** - Built-in backpressure handling
697
+ - **Automatic cleanup** - WeakRef prevents memory leaks
592
698
 
593
699
  ## Runtime Support
594
700
 
595
- - **Modern browsers** supporting ES2020+
701
+ - **Modern browsers** supporting ES2020+ (WeakRef support)
596
702
  - **Node.js** 16+
597
703
  - **Deno** 1.0+
598
704
  - **Bun** 1.0+
@@ -620,20 +726,11 @@ stream.push("hello");
620
726
 
621
727
  ### Transformer Guides
622
728
 
623
- - **[Filter Transformer →](src/transformers/filter.md)** - Adaptive constraints and stream termination
624
- - **[Map Transformer →](src/transformers/map.md)** - Stateful transformations and async processing
729
+ - **[Filter Transformer →](src/transformers/filter.md)** - Concurrency strategies, type guards, stateful filtering, and stream termination
730
+ - **[Map Transformer →](src/transformers/map.md)** - Concurrency strategies, type transformations, stateful mapping, and performance optimization
625
731
  - **[Merge Transformer →](src/transformers/merge.md)** - Stream orchestration and type-safe combination
626
732
  - **[Flat Transformer →](src/transformers/flat.md)** - Event multiplication and array flattening
627
733
 
628
- ### Philosophy
629
-
630
- **Adaptive Reactive Programming** - A new paradigm where transformers maintain state and evolve their behavior based on stream history. This enables:
631
-
632
- - **Learning transformers** that adapt to data patterns
633
- - **Stateful operations** with memory between events
634
- - **Stream termination** for lifecycle control
635
- - **Zero-overhead types** with perfect inference
636
-
637
734
  ## Contributing
638
735
 
639
736
  We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- class Z{_listeners=new Set;_generatorFn;_generator;_listenerAdded;_listenerRemoved;constructor(Y){this._generatorFn=Y instanceof Z?()=>Y[Symbol.asyncIterator]():Y}get hasListeners(){return this._listeners.size>0}get listenerAdded(){if(!this._listenerAdded)this._listenerAdded=new Z;return this._listenerAdded}get listenerRemoved(){if(!this._listenerRemoved)this._listenerRemoved=new Z;return this._listenerRemoved}async*[Symbol.asyncIterator](){let Y=[],G,J=this.listen((K)=>{Y.push(K),G?.()});try{while(!0)if(Y.length)yield Y.shift();else await new Promise((K)=>G=K)}finally{J(),Y.length=0,G=void 0;return}}push(Y,...G){G.unshift(Y);for(let J of G)for(let K of this._listeners)K(J)}listen(Y,G){let J=this,K;if(G instanceof AbortSignal){if(G?.aborted)return()=>{};G?.addEventListener("abort",Q),K=()=>G?.removeEventListener("abort",Q)}else K=G?.listen(Q);if(J._listeners.add(Y),J._listenerAdded?.push(),J._generatorFn&&J._listeners.size===1)J._generator=J._generatorFn(),(async()=>{for await(let X of J._generator)J.push(X)})();return Q;function Q(){if(J._listeners.delete(Y),J._listenerRemoved?.push(),J._listeners.size===0)J._generator?.return(),J._generator=void 0;K?.()}}then(Y){return new Promise((G)=>{let J=this.listen((K)=>{G(K),J()})}).then(Y)}pipe(Y){return Y(this)}}function F(Y,G){return(J)=>new Z(async function*(){let K=Y;for await(let Q of J){let X=await G(K,Q);if(!X)return;let[$,z]=X;if(K=z,$)yield Q}})}function _(Y,G){return(J)=>new Z(async function*(){let K=Y;for await(let Q of J){let[X,$]=await G(K,Q);K=$,yield X}})}function V(...Y){return(G)=>new Z(async function*(){let J=[G,...Y],K=[],Q,X=J.map(($)=>$.listen((z)=>{K.push(z),Q?.()}));try{while(!0)if(K.length)yield K.shift();else await new Promise(($)=>Q=$)}finally{X.forEach(($)=>$())}})}function E(Y=0){return(G)=>{return new Z(async function*(){for await(let J of G)if(Array.isArray(J)){let K=J.flat(Y);for(let Q=0;Q<K.length;Q++)yield K[Q]}else yield J})}}class H{_items=[];_insertStream;_deleteStream;_clearStream;constructor(Y){if(Y)this._items=[...Y];let G=this;function J(Q,X){if(X===0)return 0;return Q<0?(Q%X+X)%X:Q%X}this.insert=new Proxy((Q,X)=>{let $=Q<0?Math.max(0,G._items.length+Q+1):Math.min(Q,G._items.length);return G._items.splice($,0,X),G._insertStream?.push([$,X]),K},{get(Q,X){if(X in Q)return Q[X];if(!G._insertStream)G._insertStream=new Z;return G._insertStream[X]}}),this.delete=new Proxy((Q)=>{if(Q<0||Q>=G._items.length)return;let X=G._items.splice(Q,1)[0];return G._deleteStream?.push([Q,X]),X},{get(Q,X){if(X in Q)return Q[X];if(!G._deleteStream)G._deleteStream=new Z;return G._deleteStream[X]}}),this.clear=new Proxy(()=>{if(G._items.length>0)G._items.length=0,G._clearStream?.push()},{get(Q,X){if(X in Q)return Q[X];if(!G._clearStream)G._clearStream=new Z;return G._clearStream[X]}});let K=new Proxy(this,{get(Q,X){if(typeof X==="string"&&/^-?\d+$/.test(X)){let $=parseInt(X);if(Q._items.length===0)return;let z=J($,Q._items.length);return Q._items[z]}return Q[X]},set(Q,X,$){if(typeof X==="string"&&/^-?\d+$/.test(X)){let z=parseInt(X);if(Q._items.length===0)return Q._items.push($),Q._insertStream?.push([0,$]),!0;let B=J(z,Q._items.length);if(Q._items[B]!==$)Q._items[B]=$,Q._insertStream?.push([B,$]);return!0}return Q[X]=$,!0}});return K}get(Y){return this._items[Y]}get length(){return this._items.length}values(){return this._items[Symbol.iterator]()}[Symbol.iterator](){return this._items[Symbol.iterator]()}}class O extends globalThis.Map{_setStream;_deleteStream;_clearStream;constructor(Y){super(Y);let G=this;this.set=new Proxy((J,K)=>{if(globalThis.Map.prototype.has.call(G,J)&&globalThis.Map.prototype.get.call(G,J)===K)return G;return globalThis.Map.prototype.set.call(G,J,K),G._setStream?.push([J,K]),G},{get(J,K){if(K in J)return J[K];if(!G._setStream)G._setStream=new Z;return G._setStream[K]}}),this.delete=new Proxy((J)=>{if(!globalThis.Map.prototype.has.call(G,J))return!1;let K=globalThis.Map.prototype.get.call(G,J);return globalThis.Map.prototype.delete.call(G,J),G._deleteStream?.push([J,K]),!0},{get(J,K){if(K in J)return J[K];if(!G._deleteStream)G._deleteStream=new Z;return G._deleteStream[K]}}),this.clear=new Proxy(()=>{if(G.size>0)globalThis.Map.prototype.clear.call(G),G._clearStream?.push()},{get(J,K){if(K in J)return J[K];if(!G._clearStream)G._clearStream=new Z;return G._clearStream[K]}})}}class W extends globalThis.Set{_addStream;_deleteStream;_clearStream;constructor(Y){super(Y);let G=this;this.add=new Proxy((J)=>{if(globalThis.Set.prototype.has.call(G,J))return G;return globalThis.Set.prototype.add.call(G,J),G._addStream?.push(J),G},{get(J,K){if(K in J)return J[K];if(!G._addStream)G._addStream=new Z;return G._addStream[K]}}),this.delete=new Proxy((J)=>{if(!globalThis.Set.prototype.has.call(G,J))return!1;return globalThis.Set.prototype.delete.call(G,J),G._deleteStream?.push(J),!0},{get(J,K){if(K in J)return J[K];if(!G._deleteStream)G._deleteStream=new Z;return G._deleteStream[K]}}),this.clear=new Proxy(()=>{if(G.size>0)globalThis.Set.prototype.clear.call(G),G._clearStream?.push()},{get(J,K){if(K in J)return J[K];if(!G._clearStream)G._clearStream=new Z;return G._clearStream[K]}})}}class j extends Z{_value;constructor(Y,G){G?super(G):super(),this._value=Y}push(...Y){for(let G of Y)this.value=G}get value(){return this._value}set value(Y){this._value=Y,super.push(Y)}}export{V as merge,_ as map,E as flat,F as filter,Z as Stream,j as State,W as Set,O as Map,H as List};
1
+ class z{_listeners=new Map;_generatorFn;_generator;_listenerAdded;_listenerRemoved;constructor(Z){this._generatorFn=Z instanceof z?()=>Z[Symbol.asyncIterator]():Z}get hasListeners(){return this._listeners.size>0}get listenerAdded(){if(!this._listenerAdded)this._listenerAdded=new z;return this._listenerAdded}get listenerRemoved(){if(!this._listenerRemoved)this._listenerRemoved=new z;return this._listenerRemoved}async*[Symbol.asyncIterator](){let Z=[],G,J=this.listen((Q)=>{Z.push(Q),G?.()});try{while(!0)if(Z.length)yield Z.shift();else await new Promise((Q)=>G=Q)}finally{J(),Z.length=0,G=void 0;return}}push(Z,...G){G.unshift(Z);let J=[];for(let Q of G)for(let[K,X]of this._listeners){if(X&&!X.deref()){J.push(K);continue}K(Q)}for(let Q of J)this._listeners.delete(Q)}async*withContext(Z){let G=new WeakRef(Z);try{for await(let J of this){if(!G.deref())break;yield J}}finally{return}}listen(Z,G){let J=this,Q,K;if(G instanceof AbortSignal){if(G?.aborted)return()=>{};G?.addEventListener("abort",X),Q=()=>G?.removeEventListener("abort",X)}else if(G instanceof z)Q=G?.listen(X);else if(G)K=new WeakRef(G);if(J._listeners.set(Z,K),J._listenerAdded?.push(),J._generatorFn&&J._listeners.size===1)J._generator=J._generatorFn(),(async()=>{for await(let Y of J._generator)J.push(Y)})();return X;function X(){if(J._listeners.delete(Z),J._listenerRemoved?.push(),J._listeners.size===0)J._generator?.return(),J._generator=void 0;Q?.(),Q=void 0,K=void 0}}then(Z){return new Promise((G)=>{let J=this.listen((Q)=>{G(Q),J()})}).then(Z)}pipe(Z){return Z(this)}}var V=(Z,G)=>{return(J)=>{if(!G||typeof G==="object"){let{strategy:K="sequential"}=G??{},X=Z;if(K==="sequential")return new z(async function*(){for await(let Y of J){let $=await X(Y);if($)yield Y;if($===void 0)return}});if(K==="concurrent-unordered")return new z(async function*(){let Y=Symbol.for("__abort"),$=[],_,H=J.listen(async(W)=>{let j=await X(W);if(j!==!1)j===void 0?$.push(Y):$.push(W),_?.(),_=void 0});try{while(!0)if($.length){let W=$.shift();if(W===Y)break;yield W}else await new Promise((W)=>_=W)}finally{$.length=0,H(),_=void 0}});if(K==="concurrent-ordered")return new z(async function*(){let Y=[],$,_=J.listen((H)=>{let W=X(H);Y.push({resultPromise:W,value:H}),(async()=>{await W,$?.(),$=void 0})()});try{while(!0)if(Y.length){let{resultPromise:H,value:W}=Y.shift(),j=await H;if(j)yield W;if(j===void 0)break}else await new Promise((H)=>$=H)}finally{Y.length=0,_(),$=void 0}})}let Q=G;return new z(async function*(){let K=Z;for await(let X of J){let Y=await Q(K,X);if(!Y)return;let[$,_]=Y;if(K=_,$)yield X}})}};var I=(Z,G)=>{return(J)=>{if(!G||typeof G==="object"){let{strategy:K="sequential"}=G??{},X=Z;if(K==="sequential")return new z(async function*(){for await(let Y of J)yield await X(Y)});if(K==="concurrent-unordered")return new z(async function*(){let Y=[],$,_=J.listen(async(H)=>{Y.push(await X(H)),$?.(),$=void 0});try{while(!0)if(Y.length)yield Y.shift();else await new Promise((H)=>$=H)}finally{Y.length=0,_(),$=void 0}});if(K==="concurrent-ordered")return new z(async function*(){let Y=[],$,_=J.listen((H)=>{let W=X(H);Y.push(W),(async()=>{await W,$?.(),$=void 0})()});try{while(!0)if(Y.length)yield await Y.shift();else await new Promise((H)=>$=H)}finally{Y.length=0,_(),$=void 0}})}let Q=G;return new z(async function*(){let K=Z;for await(let X of J){let[Y,$]=await Q(K,X);K=$,yield Y}})}};function q(...Z){return(G)=>new z(async function*(){let J=[G,...Z],Q=[],K,X=J.map((Y)=>Y.listen(($)=>{Q.push($),K?.()}));try{while(!0)if(Q.length)yield Q.shift();else await new Promise((Y)=>K=Y)}finally{X.forEach((Y)=>Y())}})}function A(Z=0){return(G)=>{return new z(async function*(){for await(let J of G)if(Array.isArray(J)){let Q=J.flat(Z);for(let K=0;K<Q.length;K++)yield Q[K]}else yield J})}}class B{_items=[];_insertStream;_deleteStream;_clearStream;constructor(Z){if(Z)this._items=[...Z];let G=this;function J(K,X){if(X===0)return 0;return K<0?(K%X+X)%X:K%X}this.insert=new Proxy((K,X)=>{let Y=K<0?Math.max(0,G._items.length+K+1):Math.min(K,G._items.length);return G._items.splice(Y,0,X),G._insertStream?.push([Y,X]),Q},{get(K,X){if(X in K)return K[X];if(!G._insertStream)G._insertStream=new z;return G._insertStream[X]}}),this.delete=new Proxy((K)=>{if(K<0||K>=G._items.length)return;let X=G._items.splice(K,1)[0];return G._deleteStream?.push([K,X]),X},{get(K,X){if(X in K)return K[X];if(!G._deleteStream)G._deleteStream=new z;return G._deleteStream[X]}}),this.clear=new Proxy(()=>{if(G._items.length>0)G._items.length=0,G._clearStream?.push()},{get(K,X){if(X in K)return K[X];if(!G._clearStream)G._clearStream=new z;return G._clearStream[X]}});let Q=new Proxy(this,{get(K,X){if(typeof X==="string"&&/^-?\d+$/.test(X)){let Y=parseInt(X);if(K._items.length===0)return;let $=J(Y,K._items.length);return K._items[$]}return K[X]},set(K,X,Y){if(typeof X==="string"&&/^-?\d+$/.test(X)){let $=parseInt(X);if(K._items.length===0)return K._items.push(Y),K._insertStream?.push([0,Y]),!0;let _=J($,K._items.length);if(K._items[_]!==Y)K._items[_]=Y,K._insertStream?.push([_,Y]);return!0}return K[X]=Y,!0}});return Q}get(Z){return this._items[Z]}get length(){return this._items.length}values(){return this._items[Symbol.iterator]()}[Symbol.iterator](){return this._items[Symbol.iterator]()}}class D extends globalThis.Map{_setStream;_deleteStream;_clearStream;constructor(Z){super(Z);let G=this;this.set=new Proxy((J,Q)=>{if(globalThis.Map.prototype.has.call(G,J)&&globalThis.Map.prototype.get.call(G,J)===Q)return G;return globalThis.Map.prototype.set.call(G,J,Q),G._setStream?.push([J,Q]),G},{get(J,Q){if(Q in J)return J[Q];if(!G._setStream)G._setStream=new z;return G._setStream[Q]}}),this.delete=new Proxy((J)=>{if(!globalThis.Map.prototype.has.call(G,J))return!1;let Q=globalThis.Map.prototype.get.call(G,J);return globalThis.Map.prototype.delete.call(G,J),G._deleteStream?.push([J,Q]),!0},{get(J,Q){if(Q in J)return J[Q];if(!G._deleteStream)G._deleteStream=new z;return G._deleteStream[Q]}}),this.clear=new Proxy(()=>{if(G.size>0)globalThis.Map.prototype.clear.call(G),G._clearStream?.push()},{get(J,Q){if(Q in J)return J[Q];if(!G._clearStream)G._clearStream=new z;return G._clearStream[Q]}})}}class F extends globalThis.Set{_addStream;_deleteStream;_clearStream;constructor(Z){super(Z);let G=this;this.add=new Proxy((J)=>{if(globalThis.Set.prototype.has.call(G,J))return G;return globalThis.Set.prototype.add.call(G,J),G._addStream?.push(J),G},{get(J,Q){if(Q in J)return J[Q];if(!G._addStream)G._addStream=new z;return G._addStream[Q]}}),this.delete=new Proxy((J)=>{if(!globalThis.Set.prototype.has.call(G,J))return!1;return globalThis.Set.prototype.delete.call(G,J),G._deleteStream?.push(J),!0},{get(J,Q){if(Q in J)return J[Q];if(!G._deleteStream)G._deleteStream=new z;return G._deleteStream[Q]}}),this.clear=new Proxy(()=>{if(G.size>0)globalThis.Set.prototype.clear.call(G),G._clearStream?.push()},{get(J,Q){if(Q in J)return J[Q];if(!G._clearStream)G._clearStream=new z;return G._clearStream[Q]}})}}class N extends z{_value;constructor(Z,G){super(G);this._value=Z}push(...Z){for(let G of Z)this.value=G}get value(){return this._value}set value(Z){this._value=Z,super.push(Z)}}export{q as merge,I as map,A as flat,V as filter,z as Stream,N as State,F as Set,D as Map,B as List};
2
2
 
3
- //# debugId=C7D29CD74B2C788064756E2164756E21
3
+ //# debugId=652D0058F0A0040264756E2164756E21
4
4
  //# sourceMappingURL=index.js.map