iterflow 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.

Potentially problematic release.


This version of iterflow might be problematic. Click here for more details.

package/dist/index.js ADDED
@@ -0,0 +1,3977 @@
1
+ // src/errors.ts
2
+ var iterflowError = class extends Error {
3
+ operation;
4
+ context;
5
+ constructor(message, operation, context) {
6
+ super(message);
7
+ this.name = "iterflowError";
8
+ this.operation = operation;
9
+ this.context = context;
10
+ if (Error.captureStackTrace) {
11
+ Error.captureStackTrace(this, this.constructor);
12
+ }
13
+ }
14
+ /**
15
+ * Returns a detailed error message with context
16
+ */
17
+ toDetailedString() {
18
+ let msg = `${this.name}: ${this.message}`;
19
+ if (this.operation) {
20
+ msg += `
21
+ Operation: ${this.operation}`;
22
+ }
23
+ if (this.context && Object.keys(this.context).length > 0) {
24
+ msg += "\n Context:";
25
+ for (const [key, value] of Object.entries(this.context)) {
26
+ msg += `
27
+ ${key}: ${JSON.stringify(value)}`;
28
+ }
29
+ }
30
+ if (this.stack) {
31
+ msg += `
32
+ Stack: ${this.stack.split("\n").slice(1).join("\n")}`;
33
+ }
34
+ return msg;
35
+ }
36
+ };
37
+ var ValidationError = class extends iterflowError {
38
+ constructor(message, operation, context) {
39
+ super(message, operation, context);
40
+ this.name = "ValidationError";
41
+ }
42
+ };
43
+ var OperationError = class extends iterflowError {
44
+ cause;
45
+ constructor(message, operation, cause, context) {
46
+ super(message, operation, context);
47
+ this.name = "OperationError";
48
+ this.cause = cause;
49
+ }
50
+ toDetailedString() {
51
+ let msg = super.toDetailedString();
52
+ if (this.cause) {
53
+ msg += `
54
+ Caused by: ${this.cause.message}`;
55
+ if (this.cause.stack) {
56
+ msg += `
57
+ ${this.cause.stack}`;
58
+ }
59
+ }
60
+ return msg;
61
+ }
62
+ };
63
+ var EmptySequenceError = class extends iterflowError {
64
+ constructor(operation, message) {
65
+ super(
66
+ message || `Operation '${operation}' requires a non-empty sequence`,
67
+ operation
68
+ );
69
+ this.name = "EmptySequenceError";
70
+ }
71
+ };
72
+ var IndexOutOfBoundsError = class extends iterflowError {
73
+ index;
74
+ size;
75
+ constructor(index, size, operation) {
76
+ const sizeInfo = size !== void 0 ? ` (size: ${size})` : "";
77
+ super(`Index ${index} is out of bounds${sizeInfo}`, operation, {
78
+ index,
79
+ size
80
+ });
81
+ this.name = "IndexOutOfBoundsError";
82
+ this.index = index;
83
+ this.size = size;
84
+ }
85
+ };
86
+ var TypeConversionError = class extends iterflowError {
87
+ value;
88
+ expectedType;
89
+ constructor(value, expectedType, operation) {
90
+ super(
91
+ `Cannot convert value ${JSON.stringify(value)} to type ${expectedType}`,
92
+ operation,
93
+ { value, expectedType }
94
+ );
95
+ this.name = "TypeConversionError";
96
+ this.value = value;
97
+ this.expectedType = expectedType;
98
+ }
99
+ };
100
+
101
+ // src/validation.ts
102
+ function validatePositiveInteger(value, paramName, operation) {
103
+ if (!Number.isInteger(value)) {
104
+ throw new ValidationError(
105
+ `${paramName} must be an integer, got ${value}`,
106
+ operation,
107
+ { paramName, value }
108
+ );
109
+ }
110
+ if (value < 1) {
111
+ throw new ValidationError(
112
+ `${paramName} must be at least 1, got ${value}`,
113
+ operation,
114
+ { paramName, value }
115
+ );
116
+ }
117
+ }
118
+ function validateNonNegativeInteger(value, paramName, operation) {
119
+ if (!Number.isInteger(value)) {
120
+ throw new ValidationError(
121
+ `${paramName} must be an integer, got ${value}`,
122
+ operation,
123
+ { paramName, value }
124
+ );
125
+ }
126
+ if (value < 0) {
127
+ throw new ValidationError(
128
+ `${paramName} must be non-negative, got ${value}`,
129
+ operation,
130
+ { paramName, value }
131
+ );
132
+ }
133
+ }
134
+ function validateRange(value, min, max, paramName, operation) {
135
+ if (value < min || value > max) {
136
+ throw new ValidationError(
137
+ `${paramName} must be between ${min} and ${max}, got ${value}`,
138
+ operation,
139
+ { paramName, value, min, max }
140
+ );
141
+ }
142
+ }
143
+ function validateFiniteNumber(value, paramName, operation) {
144
+ if (!Number.isFinite(value)) {
145
+ throw new ValidationError(
146
+ `${paramName} must be a finite number, got ${value}`,
147
+ operation,
148
+ { paramName, value }
149
+ );
150
+ }
151
+ }
152
+ function validateNonZero(value, paramName, operation) {
153
+ if (value === 0) {
154
+ throw new ValidationError(`${paramName} cannot be zero`, operation, {
155
+ paramName,
156
+ value
157
+ });
158
+ }
159
+ }
160
+ function validateFunction(value, paramName, operation) {
161
+ if (typeof value !== "function") {
162
+ throw new ValidationError(
163
+ `${paramName} must be a function, got ${typeof value}`,
164
+ operation,
165
+ { paramName, type: typeof value }
166
+ );
167
+ }
168
+ }
169
+ function validateIterable(value, paramName, operation) {
170
+ if (value == null || typeof value[Symbol.iterator] !== "function") {
171
+ throw new ValidationError(`${paramName} must be iterable`, operation, {
172
+ paramName,
173
+ type: typeof value
174
+ });
175
+ }
176
+ }
177
+ function validateComparator(fn, operation) {
178
+ validateFunction(fn, "comparator", operation);
179
+ }
180
+ function validateNonEmpty(arr, operation) {
181
+ if (arr.length === 0) {
182
+ throw new ValidationError("Sequence cannot be empty", operation);
183
+ }
184
+ }
185
+ function toNumber(value, operation) {
186
+ const num = Number(value);
187
+ if (Number.isNaN(num)) {
188
+ throw new TypeConversionError(value, "number", operation);
189
+ }
190
+ return num;
191
+ }
192
+ function toInteger(value, operation) {
193
+ const num = toNumber(value, operation);
194
+ const int = Math.trunc(num);
195
+ if (num !== int) {
196
+ throw new TypeConversionError(value, "integer", operation);
197
+ }
198
+ return int;
199
+ }
200
+ function validateIndex(index, size, operation) {
201
+ validateNonNegativeInteger(index, "index", operation);
202
+ if (index >= size) {
203
+ throw new ValidationError(
204
+ `Index ${index} is out of bounds for size ${size}`,
205
+ operation,
206
+ { index, size }
207
+ );
208
+ }
209
+ }
210
+
211
+ // src/iter-flow.ts
212
+ var iterflow = class _iterflow {
213
+ source;
214
+ /**
215
+ * Creates a new iterflow instance from an iterable or iterator.
216
+ *
217
+ * @param source - The source iterable or iterator to wrap
218
+ * @example
219
+ * ```typescript
220
+ * const flow1 = new iterflow([1, 2, 3]);
221
+ * const flow2 = new iterflow(someIterator);
222
+ * ```
223
+ */
224
+ constructor(source) {
225
+ this.source = Symbol.iterator in source ? source[Symbol.iterator]() : source;
226
+ }
227
+ // Iterator protocol
228
+ /**
229
+ * Returns the iterator for this iterflow instance.
230
+ * This allows iterflow to be used in for...of loops.
231
+ *
232
+ * @returns The underlying iterator
233
+ */
234
+ [Symbol.iterator]() {
235
+ return this.source;
236
+ }
237
+ /**
238
+ * Retrieves the next value from the iterator.
239
+ *
240
+ * @returns An IteratorResult containing the next value or indicating completion
241
+ */
242
+ next() {
243
+ return this.source.next();
244
+ }
245
+ // ES2025 native passthrough methods (would normally delegate to native implementations)
246
+ /**
247
+ * Transforms each element using the provided function.
248
+ *
249
+ * @template U The type of the transformed elements
250
+ * @param fn - Function to transform each element
251
+ * @returns A new iterflow with transformed elements
252
+ * @example
253
+ * ```typescript
254
+ * iter([1, 2, 3]).map(x => x * 2).toArray(); // [2, 4, 6]
255
+ * ```
256
+ */
257
+ map(fn) {
258
+ const self = this;
259
+ return new _iterflow({
260
+ *[Symbol.iterator]() {
261
+ for (const value of self) {
262
+ yield fn(value);
263
+ }
264
+ }
265
+ });
266
+ }
267
+ /**
268
+ * Filters elements based on a predicate function.
269
+ * Only elements for which the predicate returns true are included.
270
+ *
271
+ * @param predicate - Function to test each element
272
+ * @returns A new iterflow with only elements that pass the predicate
273
+ * @example
274
+ * ```typescript
275
+ * iter([1, 2, 3, 4]).filter(x => x % 2 === 0).toArray(); // [2, 4]
276
+ * ```
277
+ */
278
+ filter(predicate) {
279
+ const self = this;
280
+ return new _iterflow({
281
+ *[Symbol.iterator]() {
282
+ for (const value of self) {
283
+ if (predicate(value)) {
284
+ yield value;
285
+ }
286
+ }
287
+ }
288
+ });
289
+ }
290
+ /**
291
+ * Takes only the first `limit` elements from the iterator.
292
+ *
293
+ * @param limit - Maximum number of elements to take
294
+ * @returns A new iterflow with at most `limit` elements
295
+ * @example
296
+ * ```typescript
297
+ * iter([1, 2, 3, 4, 5]).take(3).toArray(); // [1, 2, 3]
298
+ * ```
299
+ */
300
+ take(limit) {
301
+ const self = this;
302
+ return new _iterflow({
303
+ *[Symbol.iterator]() {
304
+ let count = 0;
305
+ for (const value of self) {
306
+ if (count >= limit) break;
307
+ yield value;
308
+ count++;
309
+ }
310
+ }
311
+ });
312
+ }
313
+ /**
314
+ * Skips the first `count` elements from the iterator.
315
+ *
316
+ * @param count - Number of elements to skip
317
+ * @returns A new iterflow without the first `count` elements
318
+ * @example
319
+ * ```typescript
320
+ * iter([1, 2, 3, 4, 5]).drop(2).toArray(); // [3, 4, 5]
321
+ * ```
322
+ */
323
+ drop(count) {
324
+ const self = this;
325
+ return new _iterflow({
326
+ *[Symbol.iterator]() {
327
+ let dropped = 0;
328
+ for (const value of self) {
329
+ if (dropped < count) {
330
+ dropped++;
331
+ continue;
332
+ }
333
+ yield value;
334
+ }
335
+ }
336
+ });
337
+ }
338
+ /**
339
+ * Maps each element to an iterable and flattens the results into a single iterator.
340
+ *
341
+ * @template U The type of elements in the resulting iterator
342
+ * @param fn - Function that maps each element to an iterable
343
+ * @returns A new iterflow with all mapped iterables flattened
344
+ * @example
345
+ * ```typescript
346
+ * iter([1, 2, 3]).flatMap(x => [x, x * 2]).toArray(); // [1, 2, 2, 4, 3, 6]
347
+ * ```
348
+ */
349
+ flatMap(fn) {
350
+ const self = this;
351
+ return new _iterflow({
352
+ *[Symbol.iterator]() {
353
+ for (const value of self) {
354
+ yield* fn(value);
355
+ }
356
+ }
357
+ });
358
+ }
359
+ /**
360
+ * Concatenates multiple iterators sequentially.
361
+ * Yields all elements from this iterator, then from each provided iterator.
362
+ *
363
+ * @param iterables - Additional iterables to concatenate
364
+ * @returns A new iterflow with all elements from all iterables
365
+ * @example
366
+ * ```typescript
367
+ * iter([1, 2]).concat([3, 4], [5, 6]).toArray();
368
+ * // [1, 2, 3, 4, 5, 6]
369
+ * ```
370
+ */
371
+ concat(...iterables) {
372
+ const self = this;
373
+ return new _iterflow({
374
+ *[Symbol.iterator]() {
375
+ yield* self;
376
+ for (const iterable of iterables) {
377
+ yield* iterable;
378
+ }
379
+ }
380
+ });
381
+ }
382
+ /**
383
+ * Inserts a separator element between each item.
384
+ * The separator is not added before the first element or after the last.
385
+ *
386
+ * @param separator - The element to insert between items
387
+ * @returns A new iterflow with separators interspersed
388
+ * @example
389
+ * ```typescript
390
+ * iter([1, 2, 3]).intersperse(0).toArray();
391
+ * // [1, 0, 2, 0, 3]
392
+ * iter(['a', 'b', 'c']).intersperse('-').toArray();
393
+ * // ['a', '-', 'b', '-', 'c']
394
+ * ```
395
+ */
396
+ intersperse(separator) {
397
+ const self = this;
398
+ return new _iterflow({
399
+ *[Symbol.iterator]() {
400
+ let isFirst = true;
401
+ for (const value of self) {
402
+ if (!isFirst) {
403
+ yield separator;
404
+ }
405
+ yield value;
406
+ isFirst = false;
407
+ }
408
+ }
409
+ });
410
+ }
411
+ /**
412
+ * Like reduce, but emits all intermediate accumulator values.
413
+ * Similar to reduce but returns an iterator of partial results.
414
+ *
415
+ * @template U The type of the accumulated value
416
+ * @param fn - Function to combine the accumulator with each element
417
+ * @param initial - The initial value for the accumulator
418
+ * @returns A new iterflow of intermediate accumulator values
419
+ * @example
420
+ * ```typescript
421
+ * iter([1, 2, 3, 4]).scan((acc, x) => acc + x, 0).toArray();
422
+ * // [0, 1, 3, 6, 10]
423
+ * iter([1, 2, 3]).scan((acc, x) => acc * x, 1).toArray();
424
+ * // [1, 1, 2, 6]
425
+ * ```
426
+ */
427
+ scan(fn, initial) {
428
+ const self = this;
429
+ return new _iterflow({
430
+ *[Symbol.iterator]() {
431
+ let accumulator = initial;
432
+ yield accumulator;
433
+ for (const value of self) {
434
+ accumulator = fn(accumulator, value);
435
+ yield accumulator;
436
+ }
437
+ }
438
+ });
439
+ }
440
+ /**
441
+ * Adds index as tuple with each element [index, value].
442
+ * Creates tuples pairing each element with its zero-based index.
443
+ *
444
+ * @returns A new iterflow of tuples containing [index, value]
445
+ * @example
446
+ * ```typescript
447
+ * iter(['a', 'b', 'c']).enumerate().toArray();
448
+ * // [[0, 'a'], [1, 'b'], [2, 'c']]
449
+ * ```
450
+ */
451
+ enumerate() {
452
+ const self = this;
453
+ return new _iterflow({
454
+ *[Symbol.iterator]() {
455
+ let index = 0;
456
+ for (const value of self) {
457
+ yield [index, value];
458
+ index++;
459
+ }
460
+ }
461
+ });
462
+ }
463
+ /**
464
+ * Reverses the iterator order.
465
+ * Warning: This operation buffers all elements in memory and may cause
466
+ * performance issues with large iterables. Consider using only when necessary.
467
+ *
468
+ * @returns A new iterflow with elements in reverse order
469
+ * @example
470
+ * ```typescript
471
+ * iter([1, 2, 3, 4, 5]).reverse().toArray();
472
+ * // [5, 4, 3, 2, 1]
473
+ * ```
474
+ */
475
+ reverse() {
476
+ const self = this;
477
+ return new _iterflow({
478
+ *[Symbol.iterator]() {
479
+ const buffer = Array.from(self);
480
+ for (let i = buffer.length - 1; i >= 0; i--) {
481
+ yield buffer[i];
482
+ }
483
+ }
484
+ });
485
+ }
486
+ /**
487
+ * Sorts elements using default comparison.
488
+ * Numbers are sorted numerically, strings lexicographically.
489
+ * Warning: This operation buffers all elements in memory. Avoid chaining
490
+ * with other buffering operations (reverse, sort, sortBy) for better performance.
491
+ *
492
+ * @param this - iterflow instance constrained to numbers or strings
493
+ * @returns A new iterflow with elements sorted
494
+ * @example
495
+ * ```typescript
496
+ * iter([3, 1, 4, 1, 5]).sort().toArray();
497
+ * // [1, 1, 3, 4, 5]
498
+ * iter(['c', 'a', 'b']).sort().toArray();
499
+ * // ['a', 'b', 'c']
500
+ * ```
501
+ */
502
+ sort() {
503
+ const self = this;
504
+ return new _iterflow({
505
+ *[Symbol.iterator]() {
506
+ const buffer = Array.from(self);
507
+ buffer.sort((a, b) => {
508
+ if (typeof a === "number" && typeof b === "number") {
509
+ return a - b;
510
+ }
511
+ return String(a).localeCompare(String(b));
512
+ });
513
+ yield* buffer;
514
+ }
515
+ });
516
+ }
517
+ /**
518
+ * Sorts elements using a custom comparison function.
519
+ * Warning: This operation buffers all elements in memory. Avoid chaining
520
+ * with other buffering operations (reverse, sort, sortBy) for better performance.
521
+ *
522
+ * @param compareFn - Function that compares two elements (returns negative if a < b, 0 if equal, positive if a > b)
523
+ * @returns A new iterflow with elements sorted
524
+ * @example
525
+ * ```typescript
526
+ * iter([3, 1, 4, 1, 5]).sortBy((a, b) => a - b).toArray();
527
+ * // [1, 1, 3, 4, 5]
528
+ * iter([3, 1, 4, 1, 5]).sortBy((a, b) => b - a).toArray();
529
+ * // [5, 4, 3, 1, 1]
530
+ * iter(['alice', 'bob', 'charlie']).sortBy((a, b) => a.length - b.length).toArray();
531
+ * // ['bob', 'alice', 'charlie']
532
+ * ```
533
+ */
534
+ sortBy(compareFn) {
535
+ const self = this;
536
+ return new _iterflow({
537
+ *[Symbol.iterator]() {
538
+ const buffer = Array.from(self);
539
+ buffer.sort(compareFn);
540
+ yield* buffer;
541
+ }
542
+ });
543
+ }
544
+ // Terminal operations (consume the iterator)
545
+ /**
546
+ * Collects all elements into an array.
547
+ * This is a terminal operation that consumes the iterator.
548
+ *
549
+ * @returns An array containing all elements
550
+ * @example
551
+ * ```typescript
552
+ * iter([1, 2, 3]).map(x => x * 2).toArray(); // [2, 4, 6]
553
+ * ```
554
+ */
555
+ toArray() {
556
+ return Array.from(this);
557
+ }
558
+ /**
559
+ * Counts the total number of elements in the iterator.
560
+ * This is a terminal operation that consumes the iterator.
561
+ *
562
+ * @returns The total count of elements
563
+ * @example
564
+ * ```typescript
565
+ * iter([1, 2, 3, 4, 5]).count(); // 5
566
+ * ```
567
+ */
568
+ count() {
569
+ let count = 0;
570
+ for (const _ of this) {
571
+ count++;
572
+ }
573
+ return count;
574
+ }
575
+ // Statistical operations - type-constrained to numbers
576
+ /**
577
+ * Calculates the sum of all numeric elements.
578
+ * This method is only available when T is number.
579
+ * This is a terminal operation that consumes the iterator.
580
+ *
581
+ * @param this - iterflow instance constrained to numbers
582
+ * @returns The sum of all elements
583
+ * @example
584
+ * ```typescript
585
+ * iter([1, 2, 3, 4, 5]).sum(); // 15
586
+ * ```
587
+ */
588
+ sum() {
589
+ let total = 0;
590
+ for (const value of this) {
591
+ total += value;
592
+ }
593
+ return total;
594
+ }
595
+ /**
596
+ * Calculates the arithmetic mean (average) of all numeric elements.
597
+ * This method is only available when T is number.
598
+ * This is a terminal operation that consumes the iterator.
599
+ *
600
+ * @param this - iterflow instance constrained to numbers
601
+ * @returns The mean value, or undefined if the iterator is empty
602
+ * @example
603
+ * ```typescript
604
+ * iter([1, 2, 3, 4, 5]).mean(); // 3
605
+ * iter([]).mean(); // undefined
606
+ * ```
607
+ */
608
+ mean() {
609
+ let total = 0;
610
+ let count = 0;
611
+ for (const value of this) {
612
+ total += value;
613
+ count++;
614
+ }
615
+ return count === 0 ? void 0 : total / count;
616
+ }
617
+ /**
618
+ * Finds the minimum value among all numeric elements.
619
+ * This method is only available when T is number.
620
+ * This is a terminal operation that consumes the iterator.
621
+ *
622
+ * @param this - iterflow instance constrained to numbers
623
+ * @returns The minimum value, or undefined if the iterator is empty
624
+ * @example
625
+ * ```typescript
626
+ * iter([3, 1, 4, 1, 5]).min(); // 1
627
+ * iter([]).min(); // undefined
628
+ * ```
629
+ */
630
+ min() {
631
+ let minimum = void 0;
632
+ for (const value of this) {
633
+ if (minimum === void 0 || value < minimum) {
634
+ minimum = value;
635
+ }
636
+ }
637
+ return minimum;
638
+ }
639
+ /**
640
+ * Finds the maximum value among all numeric elements.
641
+ * This method is only available when T is number.
642
+ * This is a terminal operation that consumes the iterator.
643
+ *
644
+ * @param this - iterflow instance constrained to numbers
645
+ * @returns The maximum value, or undefined if the iterator is empty
646
+ * @example
647
+ * ```typescript
648
+ * iter([3, 1, 4, 1, 5]).max(); // 5
649
+ * iter([]).max(); // undefined
650
+ * ```
651
+ */
652
+ max() {
653
+ let maximum = void 0;
654
+ for (const value of this) {
655
+ if (maximum === void 0 || value > maximum) {
656
+ maximum = value;
657
+ }
658
+ }
659
+ return maximum;
660
+ }
661
+ /**
662
+ * Calculates the median value of all numeric elements.
663
+ * The median is the middle value when elements are sorted.
664
+ * This method is only available when T is number.
665
+ * This is a terminal operation that consumes the iterator.
666
+ *
667
+ * @param this - iterflow instance constrained to numbers
668
+ * @returns The median value, or undefined if the iterator is empty
669
+ * @example
670
+ * ```typescript
671
+ * iter([1, 2, 3, 4, 5]).median(); // 3
672
+ * iter([1, 2, 3, 4]).median(); // 2.5
673
+ * iter([]).median(); // undefined
674
+ * ```
675
+ */
676
+ median() {
677
+ const values = this.toArray();
678
+ if (values.length === 0) return void 0;
679
+ values.sort((a, b) => a - b);
680
+ const mid = Math.floor(values.length / 2);
681
+ if (values.length % 2 === 0) {
682
+ return (values[mid - 1] + values[mid]) / 2;
683
+ } else {
684
+ return values[mid];
685
+ }
686
+ }
687
+ /**
688
+ * Calculates the variance of all numeric elements.
689
+ * Variance measures how far each number in the set is from the mean.
690
+ * This method is only available when T is number.
691
+ * This is a terminal operation that consumes the iterator.
692
+ *
693
+ * @param this - iterflow instance constrained to numbers
694
+ * @returns The variance, or undefined if the iterator is empty
695
+ * @example
696
+ * ```typescript
697
+ * iter([1, 2, 3, 4, 5]).variance(); // 2
698
+ * iter([]).variance(); // undefined
699
+ * ```
700
+ */
701
+ variance() {
702
+ const values = this.toArray();
703
+ if (values.length === 0) return void 0;
704
+ const mean = values.reduce((sum, val) => sum + val, 0) / values.length;
705
+ let sumSquaredDiffs = 0;
706
+ for (let i = 0; i < values.length; i++) {
707
+ const value = values[i];
708
+ const diff = value - mean;
709
+ sumSquaredDiffs += diff * diff;
710
+ }
711
+ return sumSquaredDiffs / values.length;
712
+ }
713
+ /**
714
+ * Calculates the standard deviation of all numeric elements.
715
+ * Standard deviation is the square root of variance and measures dispersion.
716
+ * This method is only available when T is number.
717
+ * This is a terminal operation that consumes the iterator.
718
+ *
719
+ * @param this - iterflow instance constrained to numbers
720
+ * @returns The standard deviation, or undefined if the iterator is empty
721
+ * @example
722
+ * ```typescript
723
+ * iter([2, 4, 4, 4, 5, 5, 7, 9]).stdDev(); // ~2
724
+ * iter([]).stdDev(); // undefined
725
+ * ```
726
+ */
727
+ stdDev() {
728
+ const variance = this.variance();
729
+ return variance === void 0 ? void 0 : Math.sqrt(variance);
730
+ }
731
+ /**
732
+ * Calculates the specified percentile of all numeric elements.
733
+ * Uses linear interpolation between closest ranks.
734
+ * This method is only available when T is number.
735
+ * This is a terminal operation that consumes the iterator.
736
+ *
737
+ * @param this - iterflow instance constrained to numbers
738
+ * @param p - The percentile to calculate (0-100)
739
+ * @returns The percentile value, or undefined if the iterator is empty
740
+ * @throws {Error} If p is not between 0 and 100
741
+ * @example
742
+ * ```typescript
743
+ * iter([1, 2, 3, 4, 5]).percentile(50); // 3 (median)
744
+ * iter([1, 2, 3, 4, 5]).percentile(75); // 4
745
+ * iter([]).percentile(50); // undefined
746
+ * ```
747
+ */
748
+ percentile(p) {
749
+ validateRange(p, 0, 100, "percentile", "percentile");
750
+ const values = this.toArray();
751
+ if (values.length === 0) return void 0;
752
+ values.sort((a, b) => a - b);
753
+ if (p === 0) return values[0];
754
+ if (p === 100) return values[values.length - 1];
755
+ const index = p / 100 * (values.length - 1);
756
+ const lower = Math.floor(index);
757
+ const upper = Math.ceil(index);
758
+ if (lower === upper) {
759
+ return values[lower];
760
+ }
761
+ const weight = index - lower;
762
+ return values[lower] * (1 - weight) + values[upper] * weight;
763
+ }
764
+ /**
765
+ * Finds the most frequent value(s) in the dataset.
766
+ * Returns an array of all values that appear most frequently.
767
+ * This method is only available when T is number.
768
+ * This is a terminal operation that consumes the iterator.
769
+ *
770
+ * @param this - iterflow instance constrained to numbers
771
+ * @returns An array of the most frequent value(s), or undefined if the iterator is empty
772
+ * @example
773
+ * ```typescript
774
+ * iter([1, 2, 2, 3, 3, 3]).mode(); // [3]
775
+ * iter([1, 1, 2, 2, 3]).mode(); // [1, 2] (bimodal)
776
+ * iter([]).mode(); // undefined
777
+ * ```
778
+ */
779
+ mode() {
780
+ const values = this.toArray();
781
+ if (values.length === 0) return void 0;
782
+ const frequency = /* @__PURE__ */ new Map();
783
+ let maxFreq = 0;
784
+ for (const value of values) {
785
+ const count = (frequency.get(value) || 0) + 1;
786
+ frequency.set(value, count);
787
+ maxFreq = Math.max(maxFreq, count);
788
+ }
789
+ const modes = [];
790
+ for (const [value, freq] of frequency) {
791
+ if (freq === maxFreq) {
792
+ modes.push(value);
793
+ }
794
+ }
795
+ return modes.sort((a, b) => a - b);
796
+ }
797
+ /**
798
+ * Calculates the quartiles (Q1, Q2, Q3) of all numeric elements.
799
+ * Q1 is the 25th percentile, Q2 is the median (50th percentile), Q3 is the 75th percentile.
800
+ * This method is only available when T is number.
801
+ * This is a terminal operation that consumes the iterator.
802
+ *
803
+ * @param this - iterflow instance constrained to numbers
804
+ * @returns An object with Q1, Q2, and Q3 values, or undefined if the iterator is empty
805
+ * @example
806
+ * ```typescript
807
+ * iter([1, 2, 3, 4, 5, 6, 7, 8, 9]).quartiles();
808
+ * // { Q1: 3, Q2: 5, Q3: 7 }
809
+ * iter([]).quartiles(); // undefined
810
+ * ```
811
+ */
812
+ quartiles() {
813
+ const values = this.toArray();
814
+ if (values.length === 0) return void 0;
815
+ values.sort((a, b) => a - b);
816
+ const calculatePercentile = (p) => {
817
+ if (p === 0) return values[0];
818
+ if (p === 100) return values[values.length - 1];
819
+ const index = p / 100 * (values.length - 1);
820
+ const lower = Math.floor(index);
821
+ const upper = Math.ceil(index);
822
+ if (lower === upper) {
823
+ return values[lower];
824
+ }
825
+ const weight = index - lower;
826
+ return values[lower] * (1 - weight) + values[upper] * weight;
827
+ };
828
+ return {
829
+ Q1: calculatePercentile(25),
830
+ Q2: calculatePercentile(50),
831
+ Q3: calculatePercentile(75)
832
+ };
833
+ }
834
+ /**
835
+ * Calculates the span (range from minimum to maximum value) of all numeric elements.
836
+ * This method is only available when T is number.
837
+ * This is a terminal operation that consumes the iterator.
838
+ *
839
+ * @param this - iterflow instance constrained to numbers
840
+ * @returns The span (max - min), or undefined if the iterator is empty
841
+ * @example
842
+ * ```typescript
843
+ * iter([1, 2, 3, 4, 5]).span(); // 4
844
+ * iter([10]).span(); // 0
845
+ * iter([]).span(); // undefined
846
+ * ```
847
+ */
848
+ span() {
849
+ let minimum = void 0;
850
+ let maximum = void 0;
851
+ for (const value of this) {
852
+ if (minimum === void 0 || value < minimum) {
853
+ minimum = value;
854
+ }
855
+ if (maximum === void 0 || value > maximum) {
856
+ maximum = value;
857
+ }
858
+ }
859
+ return minimum === void 0 || maximum === void 0 ? void 0 : maximum - minimum;
860
+ }
861
+ /**
862
+ * Calculates the product of all numeric elements.
863
+ * This method is only available when T is number.
864
+ * This is a terminal operation that consumes the iterator.
865
+ *
866
+ * @param this - iterflow instance constrained to numbers
867
+ * @returns The product of all elements, or 1 if the iterator is empty
868
+ * @example
869
+ * ```typescript
870
+ * iter([1, 2, 3, 4, 5]).product(); // 120
871
+ * iter([2, 3, 4]).product(); // 24
872
+ * iter([]).product(); // 1
873
+ * ```
874
+ */
875
+ product() {
876
+ let result = 1;
877
+ for (const value of this) {
878
+ result *= value;
879
+ }
880
+ return result;
881
+ }
882
+ /**
883
+ * Calculates the covariance between two numeric sequences.
884
+ * Covariance measures the joint variability of two random variables.
885
+ * This method is only available when T is number.
886
+ * This is a terminal operation that consumes the iterator.
887
+ *
888
+ * @param this - iterflow instance constrained to numbers
889
+ * @param other - An iterable of numbers to compare with
890
+ * @returns The covariance, or undefined if either sequence is empty or sequences have different lengths
891
+ * @example
892
+ * ```typescript
893
+ * iter([1, 2, 3, 4, 5]).covariance([2, 4, 6, 8, 10]); // 4
894
+ * iter([]).covariance([1, 2, 3]); // undefined
895
+ * ```
896
+ */
897
+ covariance(other) {
898
+ const values1 = this.toArray();
899
+ const values2 = Array.from(other);
900
+ if (values1.length === 0 || values2.length === 0 || values1.length !== values2.length) {
901
+ return void 0;
902
+ }
903
+ const mean1 = values1.reduce((sum, val) => sum + val, 0) / values1.length;
904
+ const mean2 = values2.reduce((sum, val) => sum + val, 0) / values2.length;
905
+ let covariance = 0;
906
+ for (let i = 0; i < values1.length; i++) {
907
+ covariance += (values1[i] - mean1) * (values2[i] - mean2);
908
+ }
909
+ return covariance / values1.length;
910
+ }
911
+ /**
912
+ * Calculates the Pearson correlation coefficient between two numeric sequences.
913
+ * Correlation measures the strength and direction of the linear relationship between two variables.
914
+ * Values range from -1 (perfect negative correlation) to 1 (perfect positive correlation).
915
+ * This method is only available when T is number.
916
+ * This is a terminal operation that consumes the iterator.
917
+ *
918
+ * @param this - iterflow instance constrained to numbers
919
+ * @param other - An iterable of numbers to compare with
920
+ * @returns The correlation coefficient, or undefined if either sequence is empty or sequences have different lengths
921
+ * @example
922
+ * ```typescript
923
+ * iter([1, 2, 3, 4, 5]).correlation([2, 4, 6, 8, 10]); // 1 (perfect positive correlation)
924
+ * iter([1, 2, 3]).correlation([3, 2, 1]); // -1 (perfect negative correlation)
925
+ * iter([]).correlation([1, 2, 3]); // undefined
926
+ * ```
927
+ */
928
+ correlation(other) {
929
+ const values1 = this.toArray();
930
+ const values2 = Array.from(other);
931
+ if (values1.length === 0 || values2.length === 0 || values1.length !== values2.length) {
932
+ return void 0;
933
+ }
934
+ const mean1 = values1.reduce((sum, val) => sum + val, 0) / values1.length;
935
+ const mean2 = values2.reduce((sum, val) => sum + val, 0) / values2.length;
936
+ let covariance = 0;
937
+ let variance1 = 0;
938
+ let variance2 = 0;
939
+ for (let i = 0; i < values1.length; i++) {
940
+ const diff1 = values1[i] - mean1;
941
+ const diff2 = values2[i] - mean2;
942
+ covariance += diff1 * diff2;
943
+ variance1 += diff1 * diff1;
944
+ variance2 += diff2 * diff2;
945
+ }
946
+ const stdDev1 = Math.sqrt(variance1 / values1.length);
947
+ const stdDev2 = Math.sqrt(variance2 / values2.length);
948
+ if (stdDev1 === 0 || stdDev2 === 0) {
949
+ return void 0;
950
+ }
951
+ return covariance / (values1.length * stdDev1 * stdDev2);
952
+ }
953
+ // Windowing operations
954
+ /**
955
+ * Creates a sliding window of the specified size over the elements.
956
+ * Each window contains `size` consecutive elements.
957
+ *
958
+ * @param size - The size of each window (must be at least 1)
959
+ * @returns A new iterflow of arrays, each containing `size` consecutive elements
960
+ * @throws {Error} If size is less than 1
961
+ * @example
962
+ * ```typescript
963
+ * iter([1, 2, 3, 4, 5]).window(3).toArray();
964
+ * // [[1, 2, 3], [2, 3, 4], [3, 4, 5]]
965
+ * ```
966
+ */
967
+ window(size) {
968
+ validatePositiveInteger(size, "size", "window");
969
+ const self = this;
970
+ return new _iterflow({
971
+ *[Symbol.iterator]() {
972
+ const buffer = new Array(size);
973
+ let count = 0;
974
+ let index = 0;
975
+ for (const value of self) {
976
+ buffer[index] = value;
977
+ count++;
978
+ index = (index + 1) % size;
979
+ if (count >= size) {
980
+ const window = new Array(size);
981
+ for (let i = 0; i < size; i++) {
982
+ window[i] = buffer[(index + i) % size];
983
+ }
984
+ yield window;
985
+ }
986
+ }
987
+ }
988
+ });
989
+ }
990
+ /**
991
+ * Splits elements into chunks of the specified size.
992
+ * Unlike window, chunks don't overlap. The last chunk may be smaller.
993
+ *
994
+ * @param size - The size of each chunk (must be at least 1)
995
+ * @returns A new iterflow of arrays, each containing up to `size` elements
996
+ * @throws {Error} If size is less than 1
997
+ * @example
998
+ * ```typescript
999
+ * iter([1, 2, 3, 4, 5]).chunk(2).toArray();
1000
+ * // [[1, 2], [3, 4], [5]]
1001
+ * ```
1002
+ */
1003
+ chunk(size) {
1004
+ validatePositiveInteger(size, "size", "chunk");
1005
+ const self = this;
1006
+ return new _iterflow({
1007
+ *[Symbol.iterator]() {
1008
+ let buffer = new Array(size);
1009
+ let bufferIndex = 0;
1010
+ for (const value of self) {
1011
+ buffer[bufferIndex++] = value;
1012
+ if (bufferIndex === size) {
1013
+ yield buffer;
1014
+ buffer = new Array(size);
1015
+ bufferIndex = 0;
1016
+ }
1017
+ }
1018
+ if (bufferIndex > 0) {
1019
+ yield buffer.slice(0, bufferIndex);
1020
+ }
1021
+ }
1022
+ });
1023
+ }
1024
+ /**
1025
+ * Creates pairs of consecutive elements.
1026
+ * Equivalent to window(2) but returns tuples instead of arrays.
1027
+ *
1028
+ * @returns A new iterflow of tuples, each containing two consecutive elements
1029
+ * @example
1030
+ * ```typescript
1031
+ * iter([1, 2, 3, 4]).pairwise().toArray();
1032
+ * // [[1, 2], [2, 3], [3, 4]]
1033
+ * ```
1034
+ */
1035
+ pairwise() {
1036
+ return this.window(2).map((arr) => [arr[0], arr[1]]);
1037
+ }
1038
+ // Set operations
1039
+ /**
1040
+ * Removes duplicate elements, keeping only the first occurrence of each.
1041
+ * Uses strict equality (===) to compare elements.
1042
+ *
1043
+ * @returns A new iterflow with duplicate elements removed
1044
+ * @example
1045
+ * ```typescript
1046
+ * iter([1, 2, 2, 3, 1, 4]).distinct().toArray();
1047
+ * // [1, 2, 3, 4]
1048
+ * ```
1049
+ */
1050
+ distinct() {
1051
+ const self = this;
1052
+ return new _iterflow({
1053
+ *[Symbol.iterator]() {
1054
+ const seen = /* @__PURE__ */ new Set();
1055
+ for (const value of self) {
1056
+ if (!seen.has(value)) {
1057
+ seen.add(value);
1058
+ yield value;
1059
+ }
1060
+ }
1061
+ }
1062
+ });
1063
+ }
1064
+ /**
1065
+ * Removes duplicate elements based on a key function.
1066
+ * Keeps only the first occurrence of each unique key.
1067
+ *
1068
+ * @template K The type of the key used for comparison
1069
+ * @param keyFn - Function to extract the comparison key from each element
1070
+ * @returns A new iterflow with duplicate elements (by key) removed
1071
+ * @example
1072
+ * ```typescript
1073
+ * const users = [{id: 1, name: 'Alice'}, {id: 2, name: 'Bob'}, {id: 1, name: 'Charlie'}];
1074
+ * iter(users).distinctBy(u => u.id).toArray();
1075
+ * // [{id: 1, name: 'Alice'}, {id: 2, name: 'Bob'}]
1076
+ * ```
1077
+ */
1078
+ distinctBy(keyFn) {
1079
+ const self = this;
1080
+ return new _iterflow({
1081
+ *[Symbol.iterator]() {
1082
+ const seenKeys = /* @__PURE__ */ new Set();
1083
+ for (const value of self) {
1084
+ const key = keyFn(value);
1085
+ if (!seenKeys.has(key)) {
1086
+ seenKeys.add(key);
1087
+ yield value;
1088
+ }
1089
+ }
1090
+ }
1091
+ });
1092
+ }
1093
+ // Utility operations
1094
+ /**
1095
+ * Executes a side-effect function on each element without modifying the stream.
1096
+ * Useful for debugging or performing operations like logging.
1097
+ *
1098
+ * @param fn - Function to execute for each element
1099
+ * @returns A new iterflow with the same elements
1100
+ * @example
1101
+ * ```typescript
1102
+ * iter([1, 2, 3])
1103
+ * .tap(x => console.log('Processing:', x))
1104
+ * .map(x => x * 2)
1105
+ * .toArray(); // logs each value, returns [2, 4, 6]
1106
+ * ```
1107
+ */
1108
+ tap(fn) {
1109
+ const self = this;
1110
+ return new _iterflow({
1111
+ *[Symbol.iterator]() {
1112
+ for (const value of self) {
1113
+ fn(value);
1114
+ yield value;
1115
+ }
1116
+ }
1117
+ });
1118
+ }
1119
+ /**
1120
+ * Takes elements while the predicate returns true, then stops.
1121
+ * Stops at the first element that fails the predicate.
1122
+ *
1123
+ * @param predicate - Function to test each element
1124
+ * @returns A new iterflow with elements up to the first failing predicate
1125
+ * @example
1126
+ * ```typescript
1127
+ * iter([1, 2, 3, 4, 1, 2]).takeWhile(x => x < 4).toArray();
1128
+ * // [1, 2, 3]
1129
+ * ```
1130
+ */
1131
+ takeWhile(predicate) {
1132
+ const self = this;
1133
+ return new _iterflow({
1134
+ *[Symbol.iterator]() {
1135
+ for (const value of self) {
1136
+ if (!predicate(value)) break;
1137
+ yield value;
1138
+ }
1139
+ }
1140
+ });
1141
+ }
1142
+ /**
1143
+ * Skips elements while the predicate returns true, then yields all remaining elements.
1144
+ * Starts yielding from the first element that fails the predicate.
1145
+ *
1146
+ * @param predicate - Function to test each element
1147
+ * @returns A new iterflow starting from the first element that fails the predicate
1148
+ * @example
1149
+ * ```typescript
1150
+ * iter([1, 2, 3, 4, 1, 2]).dropWhile(x => x < 3).toArray();
1151
+ * // [3, 4, 1, 2]
1152
+ * ```
1153
+ */
1154
+ dropWhile(predicate) {
1155
+ const self = this;
1156
+ return new _iterflow({
1157
+ *[Symbol.iterator]() {
1158
+ let dropping = true;
1159
+ for (const value of self) {
1160
+ if (dropping && predicate(value)) {
1161
+ continue;
1162
+ }
1163
+ dropping = false;
1164
+ yield value;
1165
+ }
1166
+ }
1167
+ });
1168
+ }
1169
+ // Grouping operations (terminal)
1170
+ /**
1171
+ * Splits elements into two arrays based on a predicate.
1172
+ * This is a terminal operation that consumes the iterator.
1173
+ *
1174
+ * @param predicate - Function to test each element
1175
+ * @returns A tuple of two arrays: [elements passing predicate, elements failing predicate]
1176
+ * @example
1177
+ * ```typescript
1178
+ * iter([1, 2, 3, 4, 5]).partition(x => x % 2 === 0);
1179
+ * // [[2, 4], [1, 3, 5]]
1180
+ * ```
1181
+ */
1182
+ partition(predicate) {
1183
+ const truthy = [];
1184
+ const falsy = [];
1185
+ for (const value of this) {
1186
+ if (predicate(value)) {
1187
+ truthy.push(value);
1188
+ } else {
1189
+ falsy.push(value);
1190
+ }
1191
+ }
1192
+ return [truthy, falsy];
1193
+ }
1194
+ /**
1195
+ * Groups elements by a key function into a Map.
1196
+ * This is a terminal operation that consumes the iterator.
1197
+ *
1198
+ * @template K The type of the grouping key
1199
+ * @param keyFn - Function to extract the grouping key from each element
1200
+ * @returns A Map where keys are the result of keyFn and values are arrays of elements
1201
+ * @example
1202
+ * ```typescript
1203
+ * iter(['alice', 'bob', 'charlie', 'dave'])
1204
+ * .groupBy(name => name.length);
1205
+ * // Map { 3 => ['bob'], 5 => ['alice'], 7 => ['charlie'], 4 => ['dave'] }
1206
+ * ```
1207
+ */
1208
+ groupBy(keyFn) {
1209
+ const groups = /* @__PURE__ */ new Map();
1210
+ for (const value of this) {
1211
+ const key = keyFn(value);
1212
+ if (!groups.has(key)) {
1213
+ groups.set(key, []);
1214
+ }
1215
+ groups.get(key).push(value);
1216
+ }
1217
+ return groups;
1218
+ }
1219
+ // Additional terminal operations
1220
+ /**
1221
+ * Reduces the iterator to a single value using an accumulator function.
1222
+ * This is a terminal operation that consumes the iterator.
1223
+ *
1224
+ * @template U The type of the accumulated value
1225
+ * @param fn - Function to combine the accumulator with each element
1226
+ * @param initial - The initial value for the accumulator
1227
+ * @returns The final accumulated value
1228
+ * @example
1229
+ * ```typescript
1230
+ * iter([1, 2, 3, 4]).reduce((acc, x) => acc + x, 0); // 10
1231
+ * iter(['a', 'b', 'c']).reduce((acc, x) => acc + x, ''); // 'abc'
1232
+ * ```
1233
+ */
1234
+ reduce(fn, initial) {
1235
+ let accumulator = initial;
1236
+ for (const value of this) {
1237
+ accumulator = fn(accumulator, value);
1238
+ }
1239
+ return accumulator;
1240
+ }
1241
+ /**
1242
+ * Finds the first element that matches the predicate.
1243
+ * This is a terminal operation that may consume part of the iterator.
1244
+ *
1245
+ * @param predicate - Function to test each element
1246
+ * @returns The first matching element, or undefined if none found
1247
+ * @example
1248
+ * ```typescript
1249
+ * iter([1, 2, 3, 4, 5]).find(x => x > 3); // 4
1250
+ * iter([1, 2, 3]).find(x => x > 10); // undefined
1251
+ * ```
1252
+ */
1253
+ find(predicate) {
1254
+ for (const value of this) {
1255
+ if (predicate(value)) {
1256
+ return value;
1257
+ }
1258
+ }
1259
+ return void 0;
1260
+ }
1261
+ /**
1262
+ * Finds the index of the first element that matches the predicate.
1263
+ * This is a terminal operation that may consume part of the iterator.
1264
+ *
1265
+ * @param predicate - Function to test each element
1266
+ * @returns The index of the first matching element, or -1 if none found
1267
+ * @example
1268
+ * ```typescript
1269
+ * iter([1, 2, 3, 4, 5]).findIndex(x => x > 3); // 3
1270
+ * iter([1, 2, 3]).findIndex(x => x > 10); // -1
1271
+ * ```
1272
+ */
1273
+ findIndex(predicate) {
1274
+ let index = 0;
1275
+ for (const value of this) {
1276
+ if (predicate(value)) {
1277
+ return index;
1278
+ }
1279
+ index++;
1280
+ }
1281
+ return -1;
1282
+ }
1283
+ /**
1284
+ * Tests whether at least one element matches the predicate.
1285
+ * This is a terminal operation that may consume part of the iterator.
1286
+ *
1287
+ * @param predicate - Function to test each element
1288
+ * @returns true if any element matches, false otherwise
1289
+ * @example
1290
+ * ```typescript
1291
+ * iter([1, 2, 3, 4, 5]).some(x => x > 3); // true
1292
+ * iter([1, 2, 3]).some(x => x > 10); // false
1293
+ * ```
1294
+ */
1295
+ some(predicate) {
1296
+ for (const value of this) {
1297
+ if (predicate(value)) {
1298
+ return true;
1299
+ }
1300
+ }
1301
+ return false;
1302
+ }
1303
+ /**
1304
+ * Tests whether all elements match the predicate.
1305
+ * This is a terminal operation that may consume part or all of the iterator.
1306
+ *
1307
+ * @param predicate - Function to test each element
1308
+ * @returns true if all elements match, false otherwise
1309
+ * @example
1310
+ * ```typescript
1311
+ * iter([2, 4, 6]).every(x => x % 2 === 0); // true
1312
+ * iter([1, 2, 3]).every(x => x % 2 === 0); // false
1313
+ * ```
1314
+ */
1315
+ every(predicate) {
1316
+ for (const value of this) {
1317
+ if (!predicate(value)) {
1318
+ return false;
1319
+ }
1320
+ }
1321
+ return true;
1322
+ }
1323
+ /**
1324
+ * Executes a function for each element in the iterator.
1325
+ * This is a terminal operation that consumes the entire iterator.
1326
+ *
1327
+ * @param fn - Function to execute for each element
1328
+ * @example
1329
+ * ```typescript
1330
+ * iter([1, 2, 3]).forEach(x => console.log(x));
1331
+ * // Logs: 1, 2, 3
1332
+ * ```
1333
+ */
1334
+ forEach(fn) {
1335
+ for (const value of this) {
1336
+ fn(value);
1337
+ }
1338
+ }
1339
+ /**
1340
+ * Gets the first element from the iterator.
1341
+ * This is a terminal operation that consumes the first element.
1342
+ *
1343
+ * @param defaultValue - Optional default value to return if iterator is empty
1344
+ * @returns The first element, the default value, or undefined if empty and no default
1345
+ * @example
1346
+ * ```typescript
1347
+ * iter([1, 2, 3]).first(); // 1
1348
+ * iter([]).first(); // undefined
1349
+ * iter([]).first(0); // 0
1350
+ * ```
1351
+ */
1352
+ first(defaultValue) {
1353
+ const result = this.source.next();
1354
+ return result.done ? defaultValue : result.value;
1355
+ }
1356
+ /**
1357
+ * Gets the last element from the iterator.
1358
+ * This is a terminal operation that consumes the entire iterator.
1359
+ *
1360
+ * @param defaultValue - Optional default value to return if iterator is empty
1361
+ * @returns The last element, the default value, or undefined if empty and no default
1362
+ * @example
1363
+ * ```typescript
1364
+ * iter([1, 2, 3]).last(); // 3
1365
+ * iter([]).last(); // undefined
1366
+ * iter([]).last(0); // 0
1367
+ * ```
1368
+ */
1369
+ last(defaultValue) {
1370
+ let lastValue = defaultValue;
1371
+ let hasValue = false;
1372
+ for (const value of this) {
1373
+ lastValue = value;
1374
+ hasValue = true;
1375
+ }
1376
+ return hasValue ? lastValue : defaultValue;
1377
+ }
1378
+ /**
1379
+ * Gets the element at the specified index.
1380
+ * This is a terminal operation that may consume part of the iterator.
1381
+ *
1382
+ * @param index - Zero-based index of the element to retrieve
1383
+ * @returns The element at the index, or undefined if index is out of bounds
1384
+ * @example
1385
+ * ```typescript
1386
+ * iter([1, 2, 3, 4, 5]).nth(2); // 3
1387
+ * iter([1, 2, 3]).nth(10); // undefined
1388
+ * iter([1, 2, 3]).nth(-1); // undefined
1389
+ * ```
1390
+ */
1391
+ nth(index) {
1392
+ if (index < 0) {
1393
+ return void 0;
1394
+ }
1395
+ let currentIndex = 0;
1396
+ for (const value of this) {
1397
+ if (currentIndex === index) {
1398
+ return value;
1399
+ }
1400
+ currentIndex++;
1401
+ }
1402
+ return void 0;
1403
+ }
1404
+ /**
1405
+ * Checks if the iterator is empty.
1406
+ * This is a terminal operation that may consume the first element.
1407
+ *
1408
+ * @returns true if the iterator has no elements, false otherwise
1409
+ * @example
1410
+ * ```typescript
1411
+ * iter([]).isEmpty(); // true
1412
+ * iter([1, 2, 3]).isEmpty(); // false
1413
+ * ```
1414
+ */
1415
+ isEmpty() {
1416
+ const result = this.source.next();
1417
+ return result.done === true;
1418
+ }
1419
+ /**
1420
+ * Checks if the iterator includes a specific value.
1421
+ * Uses strict equality (===) for comparison.
1422
+ * This is a terminal operation that may consume part or all of the iterator.
1423
+ *
1424
+ * @param searchValue - The value to search for
1425
+ * @returns true if the value is found, false otherwise
1426
+ * @example
1427
+ * ```typescript
1428
+ * iter([1, 2, 3, 4, 5]).includes(3); // true
1429
+ * iter([1, 2, 3]).includes(10); // false
1430
+ * iter(['a', 'b', 'c']).includes('b'); // true
1431
+ * ```
1432
+ */
1433
+ includes(searchValue) {
1434
+ for (const value of this) {
1435
+ if (value === searchValue) {
1436
+ return true;
1437
+ }
1438
+ }
1439
+ return false;
1440
+ }
1441
+ // Alias methods for compatibility
1442
+ /**
1443
+ * Alias for stdDev() method for compatibility.
1444
+ * Calculates the standard deviation of all numeric elements.
1445
+ */
1446
+ stddev() {
1447
+ return this.stdDev();
1448
+ }
1449
+ /**
1450
+ * Alias for drop() method for compatibility.
1451
+ * Skips the first `count` elements from the iterator.
1452
+ */
1453
+ skip(count) {
1454
+ return this.drop(count);
1455
+ }
1456
+ /**
1457
+ * Interleaves elements from this iterator with elements from other iterables.
1458
+ * Takes one element from each iterable in round-robin fashion.
1459
+ *
1460
+ * @param others - Variable number of iterables to interleave with
1461
+ * @returns A new iterflow with elements from all iterables interleaved
1462
+ * @example
1463
+ * ```typescript
1464
+ * iter([1, 2, 3]).interleave([4, 5, 6]).toArray(); // [1, 4, 2, 5, 3, 6]
1465
+ * ```
1466
+ */
1467
+ interleave(...others) {
1468
+ const self = this;
1469
+ return new _iterflow({
1470
+ *[Symbol.iterator]() {
1471
+ const allIterables = [self, ...others];
1472
+ if (allIterables.length === 0) return;
1473
+ const iterators = allIterables.map((it) => it[Symbol.iterator]());
1474
+ const active = new Set(iterators);
1475
+ while (active.size > 0) {
1476
+ for (const iterator of iterators) {
1477
+ if (!active.has(iterator)) continue;
1478
+ const result = iterator.next();
1479
+ if (result.done) {
1480
+ active.delete(iterator);
1481
+ } else {
1482
+ yield result.value;
1483
+ }
1484
+ }
1485
+ }
1486
+ }
1487
+ });
1488
+ }
1489
+ /**
1490
+ * Merges this iterator with other sorted iterables into a single sorted iterator.
1491
+ * Assumes all input iterables are already sorted in ascending order.
1492
+ *
1493
+ * @param others - Variable number of sorted iterables to merge with
1494
+ * @returns A new iterflow with all elements merged in sorted order
1495
+ * @example
1496
+ * ```typescript
1497
+ * iter([1, 3, 5]).merge([2, 4, 6]).toArray(); // [1, 2, 3, 4, 5, 6]
1498
+ * ```
1499
+ */
1500
+ merge(...others) {
1501
+ const self = this;
1502
+ return new _iterflow({
1503
+ *[Symbol.iterator]() {
1504
+ const allIterables = [self, ...others];
1505
+ if (allIterables.length === 0) return;
1506
+ const compareFn = (a, b) => {
1507
+ if (a < b) return -1;
1508
+ if (a > b) return 1;
1509
+ return 0;
1510
+ };
1511
+ const heap = [];
1512
+ for (let i = 0; i < allIterables.length; i++) {
1513
+ const iterator = allIterables[i][Symbol.iterator]();
1514
+ const result = iterator.next();
1515
+ if (!result.done) {
1516
+ heap.push({ value: result.value, iterator, index: i });
1517
+ }
1518
+ }
1519
+ const bubbleDown = (index) => {
1520
+ const length = heap.length;
1521
+ while (true) {
1522
+ let smallest = index;
1523
+ const leftChild = 2 * index + 1;
1524
+ const rightChild = 2 * index + 2;
1525
+ if (leftChild < length && compareFn(heap[leftChild].value, heap[smallest].value) < 0) {
1526
+ smallest = leftChild;
1527
+ }
1528
+ if (rightChild < length && compareFn(heap[rightChild].value, heap[smallest].value) < 0) {
1529
+ smallest = rightChild;
1530
+ }
1531
+ if (smallest === index) break;
1532
+ const temp = heap[index];
1533
+ heap[index] = heap[smallest];
1534
+ heap[smallest] = temp;
1535
+ index = smallest;
1536
+ }
1537
+ };
1538
+ for (let i = Math.floor(heap.length / 2) - 1; i >= 0; i--) {
1539
+ bubbleDown(i);
1540
+ }
1541
+ while (heap.length > 0) {
1542
+ const min = heap[0];
1543
+ yield min.value;
1544
+ const nextResult = min.iterator.next();
1545
+ if (nextResult.done) {
1546
+ heap[0] = heap[heap.length - 1];
1547
+ heap.pop();
1548
+ if (heap.length > 0) {
1549
+ bubbleDown(0);
1550
+ }
1551
+ } else {
1552
+ heap[0].value = nextResult.value;
1553
+ bubbleDown(0);
1554
+ }
1555
+ }
1556
+ }
1557
+ });
1558
+ }
1559
+ };
1560
+
1561
+ // src/async-iter-flow.ts
1562
+ var Asynciterflow = class _Asynciterflow {
1563
+ source;
1564
+ /**
1565
+ * Creates a new async iterflow instance from an async iterable or async iterator.
1566
+ *
1567
+ * @param source - The source async iterable or async iterator to wrap
1568
+ * @example
1569
+ * ```typescript
1570
+ * const flow1 = new Asynciterflow(asyncIterable);
1571
+ * const flow2 = new Asynciterflow(asyncIterator);
1572
+ * ```
1573
+ */
1574
+ constructor(source) {
1575
+ this.source = Symbol.asyncIterator in source ? source[Symbol.asyncIterator]() : source;
1576
+ }
1577
+ // Async Iterator protocol
1578
+ /**
1579
+ * Returns the async iterator for this iterflow instance.
1580
+ * This allows iterflow to be used in for await...of loops.
1581
+ *
1582
+ * @returns The underlying async iterator
1583
+ */
1584
+ [Symbol.asyncIterator]() {
1585
+ return this.source;
1586
+ }
1587
+ /**
1588
+ * Retrieves the next value from the async iterator.
1589
+ *
1590
+ * @returns A promise of an IteratorResult containing the next value or indicating completion
1591
+ */
1592
+ next() {
1593
+ return this.source.next();
1594
+ }
1595
+ // Transformation operations
1596
+ /**
1597
+ * Transforms each element using the provided async or sync function.
1598
+ *
1599
+ * @template U The type of the transformed elements
1600
+ * @param fn - Async or sync function to transform each element
1601
+ * @returns A new async iterflow with transformed elements
1602
+ * @example
1603
+ * ```typescript
1604
+ * await asyncIter([1, 2, 3]).map(async x => x * 2).toArray(); // [2, 4, 6]
1605
+ * ```
1606
+ */
1607
+ map(fn) {
1608
+ const self = this;
1609
+ return new _Asynciterflow({
1610
+ async *[Symbol.asyncIterator]() {
1611
+ for await (const value of self) {
1612
+ yield await fn(value);
1613
+ }
1614
+ }
1615
+ });
1616
+ }
1617
+ /**
1618
+ * Filters elements based on an async or sync predicate function.
1619
+ * Only elements for which the predicate returns true are included.
1620
+ *
1621
+ * @param predicate - Async or sync function to test each element
1622
+ * @returns A new async iterflow with only elements that pass the predicate
1623
+ * @example
1624
+ * ```typescript
1625
+ * await asyncIter([1, 2, 3, 4]).filter(async x => x % 2 === 0).toArray(); // [2, 4]
1626
+ * ```
1627
+ */
1628
+ filter(predicate) {
1629
+ const self = this;
1630
+ return new _Asynciterflow({
1631
+ async *[Symbol.asyncIterator]() {
1632
+ for await (const value of self) {
1633
+ if (await predicate(value)) {
1634
+ yield value;
1635
+ }
1636
+ }
1637
+ }
1638
+ });
1639
+ }
1640
+ /**
1641
+ * Takes only the first `limit` elements from the async iterator.
1642
+ *
1643
+ * @param limit - Maximum number of elements to take
1644
+ * @returns A new async iterflow with at most `limit` elements
1645
+ * @example
1646
+ * ```typescript
1647
+ * await asyncIter([1, 2, 3, 4, 5]).take(3).toArray(); // [1, 2, 3]
1648
+ * ```
1649
+ */
1650
+ take(limit) {
1651
+ const self = this;
1652
+ return new _Asynciterflow({
1653
+ async *[Symbol.asyncIterator]() {
1654
+ let count = 0;
1655
+ for await (const value of self) {
1656
+ if (count >= limit) break;
1657
+ yield value;
1658
+ count++;
1659
+ }
1660
+ }
1661
+ });
1662
+ }
1663
+ /**
1664
+ * Skips the first `count` elements from the async iterator.
1665
+ *
1666
+ * @param count - Number of elements to skip
1667
+ * @returns A new async iterflow without the first `count` elements
1668
+ * @example
1669
+ * ```typescript
1670
+ * await asyncIter([1, 2, 3, 4, 5]).drop(2).toArray(); // [3, 4, 5]
1671
+ * ```
1672
+ */
1673
+ drop(count) {
1674
+ const self = this;
1675
+ return new _Asynciterflow({
1676
+ async *[Symbol.asyncIterator]() {
1677
+ let dropped = 0;
1678
+ for await (const value of self) {
1679
+ if (dropped < count) {
1680
+ dropped++;
1681
+ continue;
1682
+ }
1683
+ yield value;
1684
+ }
1685
+ }
1686
+ });
1687
+ }
1688
+ /**
1689
+ * Maps each element to an async iterable and flattens the results.
1690
+ *
1691
+ * @template U The type of elements in the resulting iterator
1692
+ * @param fn - Async or sync function that maps each element to an async iterable
1693
+ * @returns A new async iterflow with all mapped iterables flattened
1694
+ * @example
1695
+ * ```typescript
1696
+ * await asyncIter([1, 2, 3]).flatMap(async x => [x, x * 2]).toArray(); // [1, 2, 2, 4, 3, 6]
1697
+ * ```
1698
+ */
1699
+ flatMap(fn) {
1700
+ const self = this;
1701
+ return new _Asynciterflow({
1702
+ async *[Symbol.asyncIterator]() {
1703
+ for await (const value of self) {
1704
+ const result = await fn(value);
1705
+ if (Symbol.asyncIterator in result) {
1706
+ yield* result;
1707
+ } else {
1708
+ yield* result;
1709
+ }
1710
+ }
1711
+ }
1712
+ });
1713
+ }
1714
+ /**
1715
+ * Concatenates multiple async iterators sequentially.
1716
+ *
1717
+ * @param iterables - Additional async iterables to concatenate
1718
+ * @returns A new async iterflow with all elements from all iterables
1719
+ * @example
1720
+ * ```typescript
1721
+ * await asyncIter([1, 2]).concat([3, 4], [5, 6]).toArray();
1722
+ * // [1, 2, 3, 4, 5, 6]
1723
+ * ```
1724
+ */
1725
+ concat(...iterables) {
1726
+ const self = this;
1727
+ return new _Asynciterflow({
1728
+ async *[Symbol.asyncIterator]() {
1729
+ yield* self;
1730
+ for (const iterable of iterables) {
1731
+ if (Symbol.asyncIterator in iterable) {
1732
+ yield* iterable;
1733
+ } else {
1734
+ yield* iterable;
1735
+ }
1736
+ }
1737
+ }
1738
+ });
1739
+ }
1740
+ /**
1741
+ * Inserts a separator element between each item.
1742
+ *
1743
+ * @param separator - The element to insert between items
1744
+ * @returns A new async iterflow with separators interspersed
1745
+ * @example
1746
+ * ```typescript
1747
+ * await asyncIter([1, 2, 3]).intersperse(0).toArray();
1748
+ * // [1, 0, 2, 0, 3]
1749
+ * ```
1750
+ */
1751
+ intersperse(separator) {
1752
+ const self = this;
1753
+ return new _Asynciterflow({
1754
+ async *[Symbol.asyncIterator]() {
1755
+ let isFirst = true;
1756
+ for await (const value of self) {
1757
+ if (!isFirst) {
1758
+ yield separator;
1759
+ }
1760
+ yield value;
1761
+ isFirst = false;
1762
+ }
1763
+ }
1764
+ });
1765
+ }
1766
+ /**
1767
+ * Like reduce, but emits all intermediate accumulator values.
1768
+ *
1769
+ * @template U The type of the accumulated value
1770
+ * @param fn - Async or sync function to combine the accumulator with each element
1771
+ * @param initial - The initial value for the accumulator
1772
+ * @returns A new async iterflow of intermediate accumulator values
1773
+ * @example
1774
+ * ```typescript
1775
+ * await asyncIter([1, 2, 3, 4]).scan((acc, x) => acc + x, 0).toArray();
1776
+ * // [0, 1, 3, 6, 10]
1777
+ * ```
1778
+ */
1779
+ scan(fn, initial) {
1780
+ const self = this;
1781
+ return new _Asynciterflow({
1782
+ async *[Symbol.asyncIterator]() {
1783
+ let accumulator = initial;
1784
+ yield accumulator;
1785
+ for await (const value of self) {
1786
+ accumulator = await fn(accumulator, value);
1787
+ yield accumulator;
1788
+ }
1789
+ }
1790
+ });
1791
+ }
1792
+ /**
1793
+ * Adds index as tuple with each element [index, value].
1794
+ *
1795
+ * @returns A new async iterflow of tuples containing [index, value]
1796
+ * @example
1797
+ * ```typescript
1798
+ * await asyncIter(['a', 'b', 'c']).enumerate().toArray();
1799
+ * // [[0, 'a'], [1, 'b'], [2, 'c']]
1800
+ * ```
1801
+ */
1802
+ enumerate() {
1803
+ const self = this;
1804
+ return new _Asynciterflow({
1805
+ async *[Symbol.asyncIterator]() {
1806
+ let index = 0;
1807
+ for await (const value of self) {
1808
+ yield [index, value];
1809
+ index++;
1810
+ }
1811
+ }
1812
+ });
1813
+ }
1814
+ /**
1815
+ * Reverses the async iterator order.
1816
+ * Warning: This operation buffers all elements in memory.
1817
+ *
1818
+ * @returns A new async iterflow with elements in reverse order
1819
+ * @example
1820
+ * ```typescript
1821
+ * await asyncIter([1, 2, 3, 4, 5]).reverse().toArray();
1822
+ * // [5, 4, 3, 2, 1]
1823
+ * ```
1824
+ */
1825
+ reverse() {
1826
+ const self = this;
1827
+ return new _Asynciterflow({
1828
+ async *[Symbol.asyncIterator]() {
1829
+ const buffer = await self.toArray();
1830
+ for (let i = buffer.length - 1; i >= 0; i--) {
1831
+ yield buffer[i];
1832
+ }
1833
+ }
1834
+ });
1835
+ }
1836
+ /**
1837
+ * Sorts elements using default comparison.
1838
+ * Warning: This operation buffers all elements in memory.
1839
+ *
1840
+ * @param this - async iterflow instance constrained to numbers or strings
1841
+ * @returns A new async iterflow with elements sorted
1842
+ * @example
1843
+ * ```typescript
1844
+ * await asyncIter([3, 1, 4, 1, 5]).sort().toArray();
1845
+ * // [1, 1, 3, 4, 5]
1846
+ * ```
1847
+ */
1848
+ sort() {
1849
+ const self = this;
1850
+ return new _Asynciterflow({
1851
+ async *[Symbol.asyncIterator]() {
1852
+ const buffer = await self.toArray();
1853
+ buffer.sort((a, b) => {
1854
+ if (typeof a === "number" && typeof b === "number") {
1855
+ return a - b;
1856
+ }
1857
+ return String(a).localeCompare(String(b));
1858
+ });
1859
+ yield* buffer;
1860
+ }
1861
+ });
1862
+ }
1863
+ /**
1864
+ * Sorts elements using a custom comparison function.
1865
+ * Warning: This operation buffers all elements in memory.
1866
+ *
1867
+ * @param compareFn - Function that compares two elements
1868
+ * @returns A new async iterflow with elements sorted
1869
+ * @example
1870
+ * ```typescript
1871
+ * await asyncIter([3, 1, 4, 1, 5]).sortBy((a, b) => a - b).toArray();
1872
+ * // [1, 1, 3, 4, 5]
1873
+ * ```
1874
+ */
1875
+ sortBy(compareFn) {
1876
+ const self = this;
1877
+ return new _Asynciterflow({
1878
+ async *[Symbol.asyncIterator]() {
1879
+ const buffer = await self.toArray();
1880
+ buffer.sort(compareFn);
1881
+ yield* buffer;
1882
+ }
1883
+ });
1884
+ }
1885
+ // Terminal operations
1886
+ /**
1887
+ * Collects all elements into an array.
1888
+ * This is a terminal operation that consumes the async iterator.
1889
+ *
1890
+ * @returns A promise of an array containing all elements
1891
+ * @example
1892
+ * ```typescript
1893
+ * await asyncIter([1, 2, 3]).map(async x => x * 2).toArray(); // [2, 4, 6]
1894
+ * ```
1895
+ */
1896
+ async toArray() {
1897
+ const result = [];
1898
+ for await (const value of this) {
1899
+ result.push(value);
1900
+ }
1901
+ return result;
1902
+ }
1903
+ /**
1904
+ * Counts the total number of elements in the async iterator.
1905
+ * This is a terminal operation that consumes the async iterator.
1906
+ *
1907
+ * @returns A promise of the total count of elements
1908
+ * @example
1909
+ * ```typescript
1910
+ * await asyncIter([1, 2, 3, 4, 5]).count(); // 5
1911
+ * ```
1912
+ */
1913
+ async count() {
1914
+ let count = 0;
1915
+ for await (const _ of this) {
1916
+ count++;
1917
+ }
1918
+ return count;
1919
+ }
1920
+ /**
1921
+ * Executes a function for each element.
1922
+ * This is a terminal operation that consumes the async iterator.
1923
+ *
1924
+ * @param fn - Async or sync function to execute for each element
1925
+ * @returns A promise that resolves when all elements have been processed
1926
+ * @example
1927
+ * ```typescript
1928
+ * await asyncIter([1, 2, 3]).forEach(async x => console.log(x));
1929
+ * ```
1930
+ */
1931
+ async forEach(fn) {
1932
+ for await (const value of this) {
1933
+ await fn(value);
1934
+ }
1935
+ }
1936
+ // Statistical operations
1937
+ /**
1938
+ * Calculates the sum of all numeric elements.
1939
+ * This is a terminal operation that consumes the async iterator.
1940
+ *
1941
+ * @param this - async iterflow instance constrained to numbers
1942
+ * @returns A promise of the sum of all elements
1943
+ * @example
1944
+ * ```typescript
1945
+ * await asyncIter([1, 2, 3, 4, 5]).sum(); // 15
1946
+ * ```
1947
+ */
1948
+ async sum() {
1949
+ let total = 0;
1950
+ for await (const value of this) {
1951
+ total += value;
1952
+ }
1953
+ return total;
1954
+ }
1955
+ /**
1956
+ * Calculates the arithmetic mean (average) of all numeric elements.
1957
+ * This is a terminal operation that consumes the async iterator.
1958
+ *
1959
+ * @param this - async iterflow instance constrained to numbers
1960
+ * @returns A promise of the mean value, or undefined if empty
1961
+ * @example
1962
+ * ```typescript
1963
+ * await asyncIter([1, 2, 3, 4, 5]).mean(); // 3
1964
+ * ```
1965
+ */
1966
+ async mean() {
1967
+ let total = 0;
1968
+ let count = 0;
1969
+ for await (const value of this) {
1970
+ total += value;
1971
+ count++;
1972
+ }
1973
+ return count === 0 ? void 0 : total / count;
1974
+ }
1975
+ /**
1976
+ * Finds the minimum value among all numeric elements.
1977
+ * This is a terminal operation that consumes the async iterator.
1978
+ *
1979
+ * @param this - async iterflow instance constrained to numbers
1980
+ * @returns A promise of the minimum value, or undefined if empty
1981
+ * @example
1982
+ * ```typescript
1983
+ * await asyncIter([3, 1, 4, 1, 5]).min(); // 1
1984
+ * ```
1985
+ */
1986
+ async min() {
1987
+ let minimum = void 0;
1988
+ for await (const value of this) {
1989
+ if (minimum === void 0 || value < minimum) {
1990
+ minimum = value;
1991
+ }
1992
+ }
1993
+ return minimum;
1994
+ }
1995
+ /**
1996
+ * Finds the maximum value among all numeric elements.
1997
+ * This is a terminal operation that consumes the async iterator.
1998
+ *
1999
+ * @param this - async iterflow instance constrained to numbers
2000
+ * @returns A promise of the maximum value, or undefined if empty
2001
+ * @example
2002
+ * ```typescript
2003
+ * await asyncIter([3, 1, 4, 1, 5]).max(); // 5
2004
+ * ```
2005
+ */
2006
+ async max() {
2007
+ let maximum = void 0;
2008
+ for await (const value of this) {
2009
+ if (maximum === void 0 || value > maximum) {
2010
+ maximum = value;
2011
+ }
2012
+ }
2013
+ return maximum;
2014
+ }
2015
+ /**
2016
+ * Calculates the median value of all numeric elements.
2017
+ * This is a terminal operation that consumes the async iterator.
2018
+ *
2019
+ * @param this - async iterflow instance constrained to numbers
2020
+ * @returns A promise of the median value, or undefined if empty
2021
+ * @example
2022
+ * ```typescript
2023
+ * await asyncIter([1, 2, 3, 4, 5]).median(); // 3
2024
+ * ```
2025
+ */
2026
+ async median() {
2027
+ const values = await this.toArray();
2028
+ if (values.length === 0) return void 0;
2029
+ values.sort((a, b) => a - b);
2030
+ const mid = Math.floor(values.length / 2);
2031
+ if (values.length % 2 === 0) {
2032
+ return (values[mid - 1] + values[mid]) / 2;
2033
+ } else {
2034
+ return values[mid];
2035
+ }
2036
+ }
2037
+ /**
2038
+ * Calculates the variance of all numeric elements.
2039
+ * This is a terminal operation that consumes the async iterator.
2040
+ *
2041
+ * @param this - async iterflow instance constrained to numbers
2042
+ * @returns A promise of the variance, or undefined if empty
2043
+ * @example
2044
+ * ```typescript
2045
+ * await asyncIter([1, 2, 3, 4, 5]).variance(); // 2
2046
+ * ```
2047
+ */
2048
+ async variance() {
2049
+ const values = await this.toArray();
2050
+ if (values.length === 0) return void 0;
2051
+ const mean = values.reduce((sum, val) => sum + val, 0) / values.length;
2052
+ let sumSquaredDiffs = 0;
2053
+ for (let i = 0; i < values.length; i++) {
2054
+ const diff = values[i] - mean;
2055
+ sumSquaredDiffs += diff * diff;
2056
+ }
2057
+ return sumSquaredDiffs / values.length;
2058
+ }
2059
+ /**
2060
+ * Calculates the standard deviation of all numeric elements.
2061
+ * This is a terminal operation that consumes the async iterator.
2062
+ *
2063
+ * @param this - async iterflow instance constrained to numbers
2064
+ * @returns A promise of the standard deviation, or undefined if empty
2065
+ * @example
2066
+ * ```typescript
2067
+ * await asyncIter([2, 4, 4, 4, 5, 5, 7, 9]).stdDev(); // ~2
2068
+ * ```
2069
+ */
2070
+ async stdDev() {
2071
+ const variance = await this.variance();
2072
+ return variance === void 0 ? void 0 : Math.sqrt(variance);
2073
+ }
2074
+ /**
2075
+ * Calculates the specified percentile of all numeric elements.
2076
+ * This is a terminal operation that consumes the async iterator.
2077
+ *
2078
+ * @param this - async iterflow instance constrained to numbers
2079
+ * @param p - The percentile to calculate (0-100)
2080
+ * @returns A promise of the percentile value, or undefined if empty
2081
+ * @throws {Error} If p is not between 0 and 100
2082
+ * @example
2083
+ * ```typescript
2084
+ * await asyncIter([1, 2, 3, 4, 5]).percentile(50); // 3
2085
+ * ```
2086
+ */
2087
+ async percentile(p) {
2088
+ validateRange(p, 0, 100, "percentile", "percentile");
2089
+ const values = await this.toArray();
2090
+ if (values.length === 0) return void 0;
2091
+ values.sort((a, b) => a - b);
2092
+ if (p === 0) return values[0];
2093
+ if (p === 100) return values[values.length - 1];
2094
+ const index = p / 100 * (values.length - 1);
2095
+ const lower = Math.floor(index);
2096
+ const upper = Math.ceil(index);
2097
+ if (lower === upper) {
2098
+ return values[lower];
2099
+ }
2100
+ const weight = index - lower;
2101
+ return values[lower] * (1 - weight) + values[upper] * weight;
2102
+ }
2103
+ /**
2104
+ * Finds the most frequent value(s) in the dataset.
2105
+ * This is a terminal operation that consumes the async iterator.
2106
+ *
2107
+ * @param this - async iterflow instance constrained to numbers
2108
+ * @returns A promise of an array of the most frequent value(s), or undefined if empty
2109
+ * @example
2110
+ * ```typescript
2111
+ * await asyncIter([1, 2, 2, 3, 3, 3]).mode(); // [3]
2112
+ * ```
2113
+ */
2114
+ async mode() {
2115
+ const values = await this.toArray();
2116
+ if (values.length === 0) return void 0;
2117
+ const frequency = /* @__PURE__ */ new Map();
2118
+ let maxFreq = 0;
2119
+ for (const value of values) {
2120
+ const count = (frequency.get(value) || 0) + 1;
2121
+ frequency.set(value, count);
2122
+ maxFreq = Math.max(maxFreq, count);
2123
+ }
2124
+ const modes = [];
2125
+ for (const [value, freq] of frequency) {
2126
+ if (freq === maxFreq) {
2127
+ modes.push(value);
2128
+ }
2129
+ }
2130
+ return modes.sort((a, b) => a - b);
2131
+ }
2132
+ /**
2133
+ * Calculates the quartiles (Q1, Q2, Q3) of all numeric elements.
2134
+ * This is a terminal operation that consumes the async iterator.
2135
+ *
2136
+ * @param this - async iterflow instance constrained to numbers
2137
+ * @returns A promise of an object with Q1, Q2, and Q3 values, or undefined if empty
2138
+ * @example
2139
+ * ```typescript
2140
+ * await asyncIter([1, 2, 3, 4, 5, 6, 7, 8, 9]).quartiles();
2141
+ * // { Q1: 3, Q2: 5, Q3: 7 }
2142
+ * ```
2143
+ */
2144
+ async quartiles() {
2145
+ const values = await this.toArray();
2146
+ if (values.length === 0) return void 0;
2147
+ values.sort((a, b) => a - b);
2148
+ const calculatePercentile = (p) => {
2149
+ if (p === 0) return values[0];
2150
+ if (p === 100) return values[values.length - 1];
2151
+ const index = p / 100 * (values.length - 1);
2152
+ const lower = Math.floor(index);
2153
+ const upper = Math.ceil(index);
2154
+ if (lower === upper) {
2155
+ return values[lower];
2156
+ }
2157
+ const weight = index - lower;
2158
+ return values[lower] * (1 - weight) + values[upper] * weight;
2159
+ };
2160
+ return {
2161
+ Q1: calculatePercentile(25),
2162
+ Q2: calculatePercentile(50),
2163
+ Q3: calculatePercentile(75)
2164
+ };
2165
+ }
2166
+ /**
2167
+ * Calculates the span (range from minimum to maximum value).
2168
+ * This is a terminal operation that consumes the async iterator.
2169
+ *
2170
+ * @param this - async iterflow instance constrained to numbers
2171
+ * @returns A promise of the span (max - min), or undefined if empty
2172
+ * @example
2173
+ * ```typescript
2174
+ * await asyncIter([1, 2, 3, 4, 5]).span(); // 4
2175
+ * ```
2176
+ */
2177
+ async span() {
2178
+ let minimum = void 0;
2179
+ let maximum = void 0;
2180
+ for await (const value of this) {
2181
+ if (minimum === void 0 || value < minimum) {
2182
+ minimum = value;
2183
+ }
2184
+ if (maximum === void 0 || value > maximum) {
2185
+ maximum = value;
2186
+ }
2187
+ }
2188
+ return minimum === void 0 || maximum === void 0 ? void 0 : maximum - minimum;
2189
+ }
2190
+ /**
2191
+ * Calculates the product of all numeric elements.
2192
+ * This is a terminal operation that consumes the async iterator.
2193
+ *
2194
+ * @param this - async iterflow instance constrained to numbers
2195
+ * @returns A promise of the product of all elements
2196
+ * @example
2197
+ * ```typescript
2198
+ * await asyncIter([1, 2, 3, 4, 5]).product(); // 120
2199
+ * ```
2200
+ */
2201
+ async product() {
2202
+ let result = 1;
2203
+ for await (const value of this) {
2204
+ result *= value;
2205
+ }
2206
+ return result;
2207
+ }
2208
+ /**
2209
+ * Calculates the covariance between two numeric sequences.
2210
+ * This is a terminal operation that consumes the async iterator.
2211
+ *
2212
+ * @param this - async iterflow instance constrained to numbers
2213
+ * @param other - An async iterable of numbers to compare with
2214
+ * @returns A promise of the covariance, or undefined if sequences are empty or have different lengths
2215
+ * @example
2216
+ * ```typescript
2217
+ * await asyncIter([1, 2, 3, 4, 5]).covariance([2, 4, 6, 8, 10]); // 4
2218
+ * ```
2219
+ */
2220
+ async covariance(other) {
2221
+ const values1 = await this.toArray();
2222
+ const values2 = [];
2223
+ if (Symbol.asyncIterator in other) {
2224
+ for await (const value of other) {
2225
+ values2.push(value);
2226
+ }
2227
+ } else {
2228
+ for (const value of other) {
2229
+ values2.push(value);
2230
+ }
2231
+ }
2232
+ if (values1.length === 0 || values2.length === 0 || values1.length !== values2.length) {
2233
+ return void 0;
2234
+ }
2235
+ const mean1 = values1.reduce((sum, val) => sum + val, 0) / values1.length;
2236
+ const mean2 = values2.reduce((sum, val) => sum + val, 0) / values2.length;
2237
+ let covariance = 0;
2238
+ for (let i = 0; i < values1.length; i++) {
2239
+ covariance += (values1[i] - mean1) * (values2[i] - mean2);
2240
+ }
2241
+ return covariance / values1.length;
2242
+ }
2243
+ /**
2244
+ * Calculates the Pearson correlation coefficient between two numeric sequences.
2245
+ * This is a terminal operation that consumes the async iterator.
2246
+ *
2247
+ * @param this - async iterflow instance constrained to numbers
2248
+ * @param other - An async iterable of numbers to compare with
2249
+ * @returns A promise of the correlation coefficient, or undefined if sequences are empty or have different lengths
2250
+ * @example
2251
+ * ```typescript
2252
+ * await asyncIter([1, 2, 3, 4, 5]).correlation([2, 4, 6, 8, 10]); // 1
2253
+ * ```
2254
+ */
2255
+ async correlation(other) {
2256
+ const values1 = await this.toArray();
2257
+ const values2 = [];
2258
+ if (Symbol.asyncIterator in other) {
2259
+ for await (const value of other) {
2260
+ values2.push(value);
2261
+ }
2262
+ } else {
2263
+ for (const value of other) {
2264
+ values2.push(value);
2265
+ }
2266
+ }
2267
+ if (values1.length === 0 || values2.length === 0 || values1.length !== values2.length) {
2268
+ return void 0;
2269
+ }
2270
+ const mean1 = values1.reduce((sum, val) => sum + val, 0) / values1.length;
2271
+ const mean2 = values2.reduce((sum, val) => sum + val, 0) / values2.length;
2272
+ let covariance = 0;
2273
+ let variance1 = 0;
2274
+ let variance2 = 0;
2275
+ for (let i = 0; i < values1.length; i++) {
2276
+ const diff1 = values1[i] - mean1;
2277
+ const diff2 = values2[i] - mean2;
2278
+ covariance += diff1 * diff2;
2279
+ variance1 += diff1 * diff1;
2280
+ variance2 += diff2 * diff2;
2281
+ }
2282
+ const stdDev1 = Math.sqrt(variance1 / values1.length);
2283
+ const stdDev2 = Math.sqrt(variance2 / values2.length);
2284
+ if (stdDev1 === 0 || stdDev2 === 0) {
2285
+ return void 0;
2286
+ }
2287
+ return covariance / (values1.length * stdDev1 * stdDev2);
2288
+ }
2289
+ // Windowing operations
2290
+ /**
2291
+ * Creates a sliding window of the specified size over the elements.
2292
+ *
2293
+ * @param size - The size of each window
2294
+ * @returns A new async iterflow of arrays, each containing `size` consecutive elements
2295
+ * @throws {Error} If size is less than 1
2296
+ * @example
2297
+ * ```typescript
2298
+ * await asyncIter([1, 2, 3, 4, 5]).window(3).toArray();
2299
+ * // [[1, 2, 3], [2, 3, 4], [3, 4, 5]]
2300
+ * ```
2301
+ */
2302
+ window(size) {
2303
+ validatePositiveInteger(size, "size", "window");
2304
+ const self = this;
2305
+ return new _Asynciterflow({
2306
+ async *[Symbol.asyncIterator]() {
2307
+ const buffer = new Array(size);
2308
+ let count = 0;
2309
+ let index = 0;
2310
+ for await (const value of self) {
2311
+ buffer[index] = value;
2312
+ count++;
2313
+ index = (index + 1) % size;
2314
+ if (count >= size) {
2315
+ const window = new Array(size);
2316
+ for (let i = 0; i < size; i++) {
2317
+ window[i] = buffer[(index + i) % size];
2318
+ }
2319
+ yield window;
2320
+ }
2321
+ }
2322
+ }
2323
+ });
2324
+ }
2325
+ /**
2326
+ * Splits elements into chunks of the specified size.
2327
+ *
2328
+ * @param size - The size of each chunk
2329
+ * @returns A new async iterflow of arrays, each containing up to `size` elements
2330
+ * @throws {Error} If size is less than 1
2331
+ * @example
2332
+ * ```typescript
2333
+ * await asyncIter([1, 2, 3, 4, 5]).chunk(2).toArray();
2334
+ * // [[1, 2], [3, 4], [5]]
2335
+ * ```
2336
+ */
2337
+ chunk(size) {
2338
+ validatePositiveInteger(size, "size", "chunk");
2339
+ const self = this;
2340
+ return new _Asynciterflow({
2341
+ async *[Symbol.asyncIterator]() {
2342
+ let buffer = new Array(size);
2343
+ let bufferIndex = 0;
2344
+ for await (const value of self) {
2345
+ buffer[bufferIndex++] = value;
2346
+ if (bufferIndex === size) {
2347
+ yield buffer;
2348
+ buffer = new Array(size);
2349
+ bufferIndex = 0;
2350
+ }
2351
+ }
2352
+ if (bufferIndex > 0) {
2353
+ yield buffer.slice(0, bufferIndex);
2354
+ }
2355
+ }
2356
+ });
2357
+ }
2358
+ /**
2359
+ * Creates pairs of consecutive elements.
2360
+ *
2361
+ * @returns A new async iterflow of tuples, each containing two consecutive elements
2362
+ * @example
2363
+ * ```typescript
2364
+ * await asyncIter([1, 2, 3, 4]).pairwise().toArray();
2365
+ * // [[1, 2], [2, 3], [3, 4]]
2366
+ * ```
2367
+ */
2368
+ pairwise() {
2369
+ return this.window(2).map((arr) => [arr[0], arr[1]]);
2370
+ }
2371
+ // Set operations
2372
+ /**
2373
+ * Removes duplicate elements, keeping only the first occurrence.
2374
+ *
2375
+ * @returns A new async iterflow with duplicate elements removed
2376
+ * @example
2377
+ * ```typescript
2378
+ * await asyncIter([1, 2, 2, 3, 1, 4]).distinct().toArray();
2379
+ * // [1, 2, 3, 4]
2380
+ * ```
2381
+ */
2382
+ distinct() {
2383
+ const self = this;
2384
+ return new _Asynciterflow({
2385
+ async *[Symbol.asyncIterator]() {
2386
+ const seen = /* @__PURE__ */ new Set();
2387
+ for await (const value of self) {
2388
+ if (!seen.has(value)) {
2389
+ seen.add(value);
2390
+ yield value;
2391
+ }
2392
+ }
2393
+ }
2394
+ });
2395
+ }
2396
+ /**
2397
+ * Removes duplicate elements based on a key function.
2398
+ *
2399
+ * @template K The type of the key used for comparison
2400
+ * @param keyFn - Async or sync function to extract the comparison key
2401
+ * @returns A new async iterflow with duplicate elements (by key) removed
2402
+ * @example
2403
+ * ```typescript
2404
+ * const users = [{id: 1, name: 'Alice'}, {id: 2, name: 'Bob'}, {id: 1, name: 'Charlie'}];
2405
+ * await asyncIter(users).distinctBy(async u => u.id).toArray();
2406
+ * // [{id: 1, name: 'Alice'}, {id: 2, name: 'Bob'}]
2407
+ * ```
2408
+ */
2409
+ distinctBy(keyFn) {
2410
+ const self = this;
2411
+ return new _Asynciterflow({
2412
+ async *[Symbol.asyncIterator]() {
2413
+ const seenKeys = /* @__PURE__ */ new Set();
2414
+ for await (const value of self) {
2415
+ const key = await keyFn(value);
2416
+ if (!seenKeys.has(key)) {
2417
+ seenKeys.add(key);
2418
+ yield value;
2419
+ }
2420
+ }
2421
+ }
2422
+ });
2423
+ }
2424
+ // Utility operations
2425
+ /**
2426
+ * Executes a side-effect function on each element without modifying the stream.
2427
+ *
2428
+ * @param fn - Async or sync function to execute for each element
2429
+ * @returns A new async iterflow with the same elements
2430
+ * @example
2431
+ * ```typescript
2432
+ * await asyncIter([1, 2, 3])
2433
+ * .tap(async x => console.log('Processing:', x))
2434
+ * .map(async x => x * 2)
2435
+ * .toArray(); // logs each value, returns [2, 4, 6]
2436
+ * ```
2437
+ */
2438
+ tap(fn) {
2439
+ const self = this;
2440
+ return new _Asynciterflow({
2441
+ async *[Symbol.asyncIterator]() {
2442
+ for await (const value of self) {
2443
+ await fn(value);
2444
+ yield value;
2445
+ }
2446
+ }
2447
+ });
2448
+ }
2449
+ /**
2450
+ * Takes elements while the predicate returns true, then stops.
2451
+ *
2452
+ * @param predicate - Async or sync function to test each element
2453
+ * @returns A new async iterflow with elements up to the first failing predicate
2454
+ * @example
2455
+ * ```typescript
2456
+ * await asyncIter([1, 2, 3, 4, 1, 2]).takeWhile(async x => x < 4).toArray();
2457
+ * // [1, 2, 3]
2458
+ * ```
2459
+ */
2460
+ takeWhile(predicate) {
2461
+ const self = this;
2462
+ return new _Asynciterflow({
2463
+ async *[Symbol.asyncIterator]() {
2464
+ for await (const value of self) {
2465
+ if (!await predicate(value)) break;
2466
+ yield value;
2467
+ }
2468
+ }
2469
+ });
2470
+ }
2471
+ /**
2472
+ * Skips elements while the predicate returns true, then yields all remaining.
2473
+ *
2474
+ * @param predicate - Async or sync function to test each element
2475
+ * @returns A new async iterflow starting from the first element that fails the predicate
2476
+ * @example
2477
+ * ```typescript
2478
+ * await asyncIter([1, 2, 3, 4, 1, 2]).dropWhile(async x => x < 3).toArray();
2479
+ * // [3, 4, 1, 2]
2480
+ * ```
2481
+ */
2482
+ dropWhile(predicate) {
2483
+ const self = this;
2484
+ return new _Asynciterflow({
2485
+ async *[Symbol.asyncIterator]() {
2486
+ let dropping = true;
2487
+ for await (const value of self) {
2488
+ if (dropping && await predicate(value)) {
2489
+ continue;
2490
+ }
2491
+ dropping = false;
2492
+ yield value;
2493
+ }
2494
+ }
2495
+ });
2496
+ }
2497
+ // Grouping operations (terminal)
2498
+ /**
2499
+ * Splits elements into two arrays based on a predicate.
2500
+ * This is a terminal operation that consumes the async iterator.
2501
+ *
2502
+ * @param predicate - Async or sync function to test each element
2503
+ * @returns A promise of a tuple of two arrays
2504
+ * @example
2505
+ * ```typescript
2506
+ * await asyncIter([1, 2, 3, 4, 5]).partition(async x => x % 2 === 0);
2507
+ * // [[2, 4], [1, 3, 5]]
2508
+ * ```
2509
+ */
2510
+ async partition(predicate) {
2511
+ const truthy = [];
2512
+ const falsy = [];
2513
+ for await (const value of this) {
2514
+ if (await predicate(value)) {
2515
+ truthy.push(value);
2516
+ } else {
2517
+ falsy.push(value);
2518
+ }
2519
+ }
2520
+ return [truthy, falsy];
2521
+ }
2522
+ /**
2523
+ * Groups elements by a key function into a Map.
2524
+ * This is a terminal operation that consumes the async iterator.
2525
+ *
2526
+ * @template K The type of the grouping key
2527
+ * @param keyFn - Async or sync function to extract the grouping key
2528
+ * @returns A promise of a Map where keys are the result of keyFn and values are arrays of elements
2529
+ * @example
2530
+ * ```typescript
2531
+ * await asyncIter(['alice', 'bob', 'charlie', 'dave'])
2532
+ * .groupBy(async name => name.length);
2533
+ * // Map { 3 => ['bob'], 5 => ['alice'], 7 => ['charlie'], 4 => ['dave'] }
2534
+ * ```
2535
+ */
2536
+ async groupBy(keyFn) {
2537
+ const groups = /* @__PURE__ */ new Map();
2538
+ for await (const value of this) {
2539
+ const key = await keyFn(value);
2540
+ if (!groups.has(key)) {
2541
+ groups.set(key, []);
2542
+ }
2543
+ groups.get(key).push(value);
2544
+ }
2545
+ return groups;
2546
+ }
2547
+ // Additional terminal operations
2548
+ /**
2549
+ * Reduces the async iterator to a single value using an accumulator function.
2550
+ * This is a terminal operation that consumes the async iterator.
2551
+ *
2552
+ * @template U The type of the accumulated value
2553
+ * @param fn - Async or sync function to combine the accumulator with each element
2554
+ * @param initial - The initial value for the accumulator
2555
+ * @returns A promise of the final accumulated value
2556
+ * @example
2557
+ * ```typescript
2558
+ * await asyncIter([1, 2, 3, 4]).reduce(async (acc, x) => acc + x, 0); // 10
2559
+ * ```
2560
+ */
2561
+ async reduce(fn, initial) {
2562
+ let accumulator = initial;
2563
+ for await (const value of this) {
2564
+ accumulator = await fn(accumulator, value);
2565
+ }
2566
+ return accumulator;
2567
+ }
2568
+ /**
2569
+ * Finds the first element that matches the predicate.
2570
+ * This is a terminal operation that may consume part of the async iterator.
2571
+ *
2572
+ * @param predicate - Async or sync function to test each element
2573
+ * @returns A promise of the first matching element, or undefined if none found
2574
+ * @example
2575
+ * ```typescript
2576
+ * await asyncIter([1, 2, 3, 4, 5]).find(async x => x > 3); // 4
2577
+ * ```
2578
+ */
2579
+ async find(predicate) {
2580
+ for await (const value of this) {
2581
+ if (await predicate(value)) {
2582
+ return value;
2583
+ }
2584
+ }
2585
+ return void 0;
2586
+ }
2587
+ /**
2588
+ * Finds the index of the first element that matches the predicate.
2589
+ * This is a terminal operation that may consume part of the async iterator.
2590
+ *
2591
+ * @param predicate - Async or sync function to test each element
2592
+ * @returns A promise of the index of the first matching element, or -1 if none found
2593
+ * @example
2594
+ * ```typescript
2595
+ * await asyncIter([1, 2, 3, 4, 5]).findIndex(async x => x > 3); // 3
2596
+ * ```
2597
+ */
2598
+ async findIndex(predicate) {
2599
+ let index = 0;
2600
+ for await (const value of this) {
2601
+ if (await predicate(value)) {
2602
+ return index;
2603
+ }
2604
+ index++;
2605
+ }
2606
+ return -1;
2607
+ }
2608
+ /**
2609
+ * Tests whether at least one element matches the predicate.
2610
+ * This is a terminal operation that may consume part of the async iterator.
2611
+ *
2612
+ * @param predicate - Async or sync function to test each element
2613
+ * @returns A promise of true if any element matches, false otherwise
2614
+ * @example
2615
+ * ```typescript
2616
+ * await asyncIter([1, 2, 3, 4, 5]).some(async x => x > 3); // true
2617
+ * ```
2618
+ */
2619
+ async some(predicate) {
2620
+ for await (const value of this) {
2621
+ if (await predicate(value)) {
2622
+ return true;
2623
+ }
2624
+ }
2625
+ return false;
2626
+ }
2627
+ /**
2628
+ * Tests whether all elements match the predicate.
2629
+ * This is a terminal operation that may consume part or all of the async iterator.
2630
+ *
2631
+ * @param predicate - Async or sync function to test each element
2632
+ * @returns A promise of true if all elements match, false otherwise
2633
+ * @example
2634
+ * ```typescript
2635
+ * await asyncIter([2, 4, 6]).every(async x => x % 2 === 0); // true
2636
+ * ```
2637
+ */
2638
+ async every(predicate) {
2639
+ for await (const value of this) {
2640
+ if (!await predicate(value)) {
2641
+ return false;
2642
+ }
2643
+ }
2644
+ return true;
2645
+ }
2646
+ /**
2647
+ * Gets the first element from the async iterator.
2648
+ * This is a terminal operation that consumes the first element.
2649
+ *
2650
+ * @param defaultValue - Optional default value to return if iterator is empty
2651
+ * @returns A promise of the first element, the default value, or undefined if empty and no default
2652
+ * @example
2653
+ * ```typescript
2654
+ * await asyncIter([1, 2, 3]).first(); // 1
2655
+ * ```
2656
+ */
2657
+ async first(defaultValue) {
2658
+ const result = await this.source.next();
2659
+ return result.done ? defaultValue : result.value;
2660
+ }
2661
+ /**
2662
+ * Gets the last element from the async iterator.
2663
+ * This is a terminal operation that consumes the entire async iterator.
2664
+ *
2665
+ * @param defaultValue - Optional default value to return if iterator is empty
2666
+ * @returns A promise of the last element, the default value, or undefined if empty and no default
2667
+ * @example
2668
+ * ```typescript
2669
+ * await asyncIter([1, 2, 3]).last(); // 3
2670
+ * ```
2671
+ */
2672
+ async last(defaultValue) {
2673
+ let lastValue = defaultValue;
2674
+ let hasValue = false;
2675
+ for await (const value of this) {
2676
+ lastValue = value;
2677
+ hasValue = true;
2678
+ }
2679
+ return hasValue ? lastValue : defaultValue;
2680
+ }
2681
+ /**
2682
+ * Gets the element at the specified index.
2683
+ * This is a terminal operation that may consume part of the async iterator.
2684
+ *
2685
+ * @param index - Zero-based index of the element to retrieve
2686
+ * @returns A promise of the element at the index, or undefined if index is out of bounds
2687
+ * @example
2688
+ * ```typescript
2689
+ * await asyncIter([1, 2, 3, 4, 5]).nth(2); // 3
2690
+ * ```
2691
+ */
2692
+ async nth(index) {
2693
+ if (index < 0) {
2694
+ return void 0;
2695
+ }
2696
+ let currentIndex = 0;
2697
+ for await (const value of this) {
2698
+ if (currentIndex === index) {
2699
+ return value;
2700
+ }
2701
+ currentIndex++;
2702
+ }
2703
+ return void 0;
2704
+ }
2705
+ /**
2706
+ * Checks if the async iterator is empty.
2707
+ * This is a terminal operation that may consume the first element.
2708
+ *
2709
+ * @returns A promise of true if the iterator has no elements, false otherwise
2710
+ * @example
2711
+ * ```typescript
2712
+ * await asyncIter([]).isEmpty(); // true
2713
+ * ```
2714
+ */
2715
+ async isEmpty() {
2716
+ const result = await this.source.next();
2717
+ return result.done === true;
2718
+ }
2719
+ /**
2720
+ * Checks if the async iterator includes a specific value.
2721
+ * This is a terminal operation that may consume part or all of the async iterator.
2722
+ *
2723
+ * @param searchValue - The value to search for
2724
+ * @returns A promise of true if the value is found, false otherwise
2725
+ * @example
2726
+ * ```typescript
2727
+ * await asyncIter([1, 2, 3, 4, 5]).includes(3); // true
2728
+ * ```
2729
+ */
2730
+ async includes(searchValue) {
2731
+ for await (const value of this) {
2732
+ if (value === searchValue) {
2733
+ return true;
2734
+ }
2735
+ }
2736
+ return false;
2737
+ }
2738
+ // Concurrent/Parallel processing operations
2739
+ /**
2740
+ * Maps elements in parallel with a concurrency limit.
2741
+ * Processes multiple elements simultaneously while respecting the concurrency limit.
2742
+ *
2743
+ * @template U The type of the transformed elements
2744
+ * @param fn - Async function to transform each element
2745
+ * @param concurrency - Maximum number of concurrent operations (default: 10)
2746
+ * @returns A new async iterflow with transformed elements
2747
+ * @example
2748
+ * ```typescript
2749
+ * await asyncIter([1, 2, 3, 4, 5])
2750
+ * .mapParallel(async x => {
2751
+ * await sleep(100);
2752
+ * return x * 2;
2753
+ * }, 3)
2754
+ * .toArray(); // Processes 3 items at a time
2755
+ * ```
2756
+ */
2757
+ mapParallel(fn, concurrency = 10) {
2758
+ const self = this;
2759
+ return new _Asynciterflow({
2760
+ async *[Symbol.asyncIterator]() {
2761
+ const promises = [];
2762
+ const results = /* @__PURE__ */ new Map();
2763
+ let nextIndex = 0;
2764
+ let completedIndex = 0;
2765
+ for await (const value of self) {
2766
+ const currentIndex = nextIndex++;
2767
+ const promise = fn(value).then((result) => ({
2768
+ index: currentIndex,
2769
+ value: result
2770
+ }));
2771
+ promises.push(promise);
2772
+ if (promises.length >= concurrency) {
2773
+ const completed = await Promise.race(promises);
2774
+ results.set(completed.index, completed.value);
2775
+ promises.splice(
2776
+ promises.findIndex(
2777
+ (p) => p.then((r) => r.index === completed.index)
2778
+ ),
2779
+ 1
2780
+ );
2781
+ while (results.has(completedIndex)) {
2782
+ yield results.get(completedIndex);
2783
+ results.delete(completedIndex);
2784
+ completedIndex++;
2785
+ }
2786
+ }
2787
+ }
2788
+ while (promises.length > 0) {
2789
+ const completed = await Promise.race(promises);
2790
+ results.set(completed.index, completed.value);
2791
+ promises.splice(
2792
+ promises.findIndex(
2793
+ (p) => p.then((r) => r.index === completed.index)
2794
+ ),
2795
+ 1
2796
+ );
2797
+ while (results.has(completedIndex)) {
2798
+ yield results.get(completedIndex);
2799
+ results.delete(completedIndex);
2800
+ completedIndex++;
2801
+ }
2802
+ }
2803
+ }
2804
+ });
2805
+ }
2806
+ /**
2807
+ * Filters elements in parallel with a concurrency limit.
2808
+ *
2809
+ * @param predicate - Async function to test each element
2810
+ * @param concurrency - Maximum number of concurrent operations (default: 10)
2811
+ * @returns A new async iterflow with only elements that pass the predicate
2812
+ * @example
2813
+ * ```typescript
2814
+ * await asyncIter([1, 2, 3, 4, 5])
2815
+ * .filterParallel(async x => {
2816
+ * await sleep(100);
2817
+ * return x % 2 === 0;
2818
+ * }, 3)
2819
+ * .toArray(); // [2, 4]
2820
+ * ```
2821
+ */
2822
+ filterParallel(predicate, concurrency = 10) {
2823
+ const self = this;
2824
+ return new _Asynciterflow({
2825
+ async *[Symbol.asyncIterator]() {
2826
+ const promises = [];
2827
+ const results = /* @__PURE__ */ new Map();
2828
+ let nextIndex = 0;
2829
+ let completedIndex = 0;
2830
+ for await (const value of self) {
2831
+ const currentIndex = nextIndex++;
2832
+ const promise = predicate(value).then((keep) => ({
2833
+ index: currentIndex,
2834
+ value,
2835
+ keep
2836
+ }));
2837
+ promises.push(promise);
2838
+ if (promises.length >= concurrency) {
2839
+ const completed = await Promise.race(promises);
2840
+ results.set(completed.index, {
2841
+ value: completed.value,
2842
+ keep: completed.keep
2843
+ });
2844
+ promises.splice(
2845
+ promises.findIndex(
2846
+ (p) => p.then((r) => r.index === completed.index)
2847
+ ),
2848
+ 1
2849
+ );
2850
+ while (results.has(completedIndex)) {
2851
+ const result = results.get(completedIndex);
2852
+ if (result.keep) {
2853
+ yield result.value;
2854
+ }
2855
+ results.delete(completedIndex);
2856
+ completedIndex++;
2857
+ }
2858
+ }
2859
+ }
2860
+ while (promises.length > 0) {
2861
+ const completed = await Promise.race(promises);
2862
+ results.set(completed.index, {
2863
+ value: completed.value,
2864
+ keep: completed.keep
2865
+ });
2866
+ promises.splice(
2867
+ promises.findIndex(
2868
+ (p) => p.then((r) => r.index === completed.index)
2869
+ ),
2870
+ 1
2871
+ );
2872
+ while (results.has(completedIndex)) {
2873
+ const result = results.get(completedIndex);
2874
+ if (result.keep) {
2875
+ yield result.value;
2876
+ }
2877
+ results.delete(completedIndex);
2878
+ completedIndex++;
2879
+ }
2880
+ }
2881
+ }
2882
+ });
2883
+ }
2884
+ /**
2885
+ * FlatMaps elements in parallel with a concurrency limit.
2886
+ *
2887
+ * @template U The type of elements in the resulting iterator
2888
+ * @param fn - Async function that maps each element to an async iterable
2889
+ * @param concurrency - Maximum number of concurrent operations (default: 10)
2890
+ * @returns A new async iterflow with all mapped iterables flattened
2891
+ * @example
2892
+ * ```typescript
2893
+ * await asyncIter([1, 2, 3])
2894
+ * .flatMapParallel(async x => [x, x * 2], 2)
2895
+ * .toArray(); // [1, 2, 2, 4, 3, 6]
2896
+ * ```
2897
+ */
2898
+ flatMapParallel(fn, concurrency = 10) {
2899
+ const self = this;
2900
+ return new _Asynciterflow({
2901
+ async *[Symbol.asyncIterator]() {
2902
+ const promises = [];
2903
+ const results = /* @__PURE__ */ new Map();
2904
+ let nextIndex = 0;
2905
+ let completedIndex = 0;
2906
+ for await (const value of self) {
2907
+ const currentIndex = nextIndex++;
2908
+ const promise = fn(value).then((values) => ({
2909
+ index: currentIndex,
2910
+ values
2911
+ }));
2912
+ promises.push(promise);
2913
+ if (promises.length >= concurrency) {
2914
+ const completed = await Promise.race(promises);
2915
+ results.set(completed.index, completed.values);
2916
+ promises.splice(
2917
+ promises.findIndex(
2918
+ (p) => p.then((r) => r.index === completed.index)
2919
+ ),
2920
+ 1
2921
+ );
2922
+ while (results.has(completedIndex)) {
2923
+ const result = results.get(completedIndex);
2924
+ if (Symbol.asyncIterator in result) {
2925
+ yield* result;
2926
+ } else {
2927
+ yield* result;
2928
+ }
2929
+ results.delete(completedIndex);
2930
+ completedIndex++;
2931
+ }
2932
+ }
2933
+ }
2934
+ while (promises.length > 0) {
2935
+ const completed = await Promise.race(promises);
2936
+ results.set(completed.index, completed.values);
2937
+ promises.splice(
2938
+ promises.findIndex(
2939
+ (p) => p.then((r) => r.index === completed.index)
2940
+ ),
2941
+ 1
2942
+ );
2943
+ while (results.has(completedIndex)) {
2944
+ const result = results.get(completedIndex);
2945
+ if (Symbol.asyncIterator in result) {
2946
+ yield* result;
2947
+ } else {
2948
+ yield* result;
2949
+ }
2950
+ results.delete(completedIndex);
2951
+ completedIndex++;
2952
+ }
2953
+ }
2954
+ }
2955
+ });
2956
+ }
2957
+ // Backpressure handling
2958
+ /**
2959
+ * Buffers elements up to a specified size.
2960
+ *
2961
+ * @param size - Maximum buffer size
2962
+ * @returns A new async iterflow with buffered elements
2963
+ * @example
2964
+ * ```typescript
2965
+ * await asyncIter([1, 2, 3, 4, 5]).buffer(2).toArray();
2966
+ * // [[1, 2], [3, 4], [5]]
2967
+ * ```
2968
+ */
2969
+ buffer(size) {
2970
+ return this.chunk(size);
2971
+ }
2972
+ /**
2973
+ * Throttles the stream to emit at most one value per time interval.
2974
+ *
2975
+ * @param intervalMs - Minimum time between emissions in milliseconds
2976
+ * @returns A new async iterflow with throttled elements
2977
+ * @example
2978
+ * ```typescript
2979
+ * await asyncIter([1, 2, 3, 4, 5]).throttle(100).toArray();
2980
+ * // Emits one value every 100ms
2981
+ * ```
2982
+ */
2983
+ throttle(intervalMs) {
2984
+ const self = this;
2985
+ return new _Asynciterflow({
2986
+ async *[Symbol.asyncIterator]() {
2987
+ let lastEmitTime = 0;
2988
+ for await (const value of self) {
2989
+ const now = Date.now();
2990
+ if (now - lastEmitTime >= intervalMs) {
2991
+ lastEmitTime = now;
2992
+ yield value;
2993
+ } else {
2994
+ const delay = intervalMs - (now - lastEmitTime);
2995
+ await new Promise((resolve) => setTimeout(resolve, delay));
2996
+ lastEmitTime = Date.now();
2997
+ yield value;
2998
+ }
2999
+ }
3000
+ }
3001
+ });
3002
+ }
3003
+ /**
3004
+ * Debounces the stream, only emitting values after a period of silence.
3005
+ *
3006
+ * @param waitMs - Time to wait for silence in milliseconds
3007
+ * @returns A new async iterflow with debounced elements
3008
+ * @example
3009
+ * ```typescript
3010
+ * await asyncIter([1, 2, 3, 4, 5]).debounce(100).toArray();
3011
+ * // Only emits values after 100ms of no new values
3012
+ * ```
3013
+ */
3014
+ debounce(waitMs) {
3015
+ const self = this;
3016
+ return new _Asynciterflow({
3017
+ async *[Symbol.asyncIterator]() {
3018
+ const buffer = [];
3019
+ let lastValue;
3020
+ let hasValue = false;
3021
+ for await (const value of self) {
3022
+ hasValue = true;
3023
+ lastValue = value;
3024
+ buffer.push(value);
3025
+ await new Promise((resolve) => setTimeout(resolve, waitMs));
3026
+ if (lastValue === value && buffer[buffer.length - 1] === value) {
3027
+ yield value;
3028
+ buffer.length = 0;
3029
+ }
3030
+ }
3031
+ if (hasValue && buffer.length > 0 && lastValue !== void 0) {
3032
+ yield lastValue;
3033
+ }
3034
+ }
3035
+ });
3036
+ }
3037
+ // Error handling
3038
+ /**
3039
+ * Catches errors and continues with a fallback value or stream.
3040
+ *
3041
+ * @param handler - Function to handle errors and return a fallback value or async iterable
3042
+ * @returns A new async iterflow with error handling
3043
+ * @example
3044
+ * ```typescript
3045
+ * await asyncIter([1, 2, 3])
3046
+ * .map(async x => {
3047
+ * if (x === 2) throw new Error('Error!');
3048
+ * return x;
3049
+ * })
3050
+ * .catchError(async (error) => [-1])
3051
+ * .toArray(); // [1, -1, 3]
3052
+ * ```
3053
+ */
3054
+ catchError(handler) {
3055
+ const self = this;
3056
+ return new _Asynciterflow({
3057
+ async *[Symbol.asyncIterator]() {
3058
+ try {
3059
+ for await (const value of self) {
3060
+ yield value;
3061
+ }
3062
+ } catch (error) {
3063
+ const fallback = await handler(error);
3064
+ if (typeof fallback === "object" && fallback !== null && (Symbol.asyncIterator in fallback || Symbol.iterator in fallback)) {
3065
+ if (Symbol.asyncIterator in fallback) {
3066
+ yield* fallback;
3067
+ } else {
3068
+ yield* fallback;
3069
+ }
3070
+ } else {
3071
+ yield fallback;
3072
+ }
3073
+ }
3074
+ }
3075
+ });
3076
+ }
3077
+ /**
3078
+ * Retries failed operations a specified number of times.
3079
+ *
3080
+ * @param maxRetries - Maximum number of retry attempts
3081
+ * @param delayMs - Optional delay between retries in milliseconds
3082
+ * @returns A new async iterflow with retry logic
3083
+ * @example
3084
+ * ```typescript
3085
+ * await asyncIter([1, 2, 3])
3086
+ * .map(async x => {
3087
+ * if (Math.random() > 0.5) throw new Error('Random error');
3088
+ * return x;
3089
+ * })
3090
+ * .retry(3, 100)
3091
+ * .toArray(); // Retries up to 3 times with 100ms delay
3092
+ * ```
3093
+ */
3094
+ retry(maxRetries, delayMs = 0) {
3095
+ const self = this;
3096
+ return new _Asynciterflow({
3097
+ async *[Symbol.asyncIterator]() {
3098
+ const iterator = self[Symbol.asyncIterator]();
3099
+ let retryCount = 0;
3100
+ while (true) {
3101
+ try {
3102
+ const result = await iterator.next();
3103
+ if (result.done) break;
3104
+ yield result.value;
3105
+ retryCount = 0;
3106
+ } catch (error) {
3107
+ if (retryCount < maxRetries) {
3108
+ retryCount++;
3109
+ if (delayMs > 0) {
3110
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
3111
+ }
3112
+ } else {
3113
+ throw error;
3114
+ }
3115
+ }
3116
+ }
3117
+ }
3118
+ });
3119
+ }
3120
+ /**
3121
+ * Handles errors for each element individually.
3122
+ *
3123
+ * @param handler - Async or sync function to handle errors for each element
3124
+ * @returns A new async iterflow with error handling
3125
+ * @example
3126
+ * ```typescript
3127
+ * await asyncIter([1, 2, 3])
3128
+ * .map(async x => {
3129
+ * if (x === 2) throw new Error('Error!');
3130
+ * return x;
3131
+ * })
3132
+ * .onError(async (error, value) => console.error('Error:', error))
3133
+ * .toArray(); // [1, 3] (2 is skipped)
3134
+ * ```
3135
+ */
3136
+ onError(handler) {
3137
+ const self = this;
3138
+ return new _Asynciterflow({
3139
+ async *[Symbol.asyncIterator]() {
3140
+ for await (const value of self) {
3141
+ try {
3142
+ yield value;
3143
+ } catch (error) {
3144
+ await handler(error, value);
3145
+ }
3146
+ }
3147
+ }
3148
+ });
3149
+ }
3150
+ };
3151
+ function asyncIter(source) {
3152
+ if (Symbol.asyncIterator in source) {
3153
+ return new Asynciterflow(source);
3154
+ }
3155
+ return new Asynciterflow({
3156
+ async *[Symbol.asyncIterator]() {
3157
+ yield* source;
3158
+ }
3159
+ });
3160
+ }
3161
+ ((asyncIter2) => {
3162
+ function zip(iter1, iter2) {
3163
+ return new Asynciterflow({
3164
+ async *[Symbol.asyncIterator]() {
3165
+ const it1 = Symbol.asyncIterator in iter1 ? iter1[Symbol.asyncIterator]() : (async function* () {
3166
+ yield* iter1;
3167
+ })();
3168
+ const it2 = Symbol.asyncIterator in iter2 ? iter2[Symbol.asyncIterator]() : (async function* () {
3169
+ yield* iter2;
3170
+ })();
3171
+ while (true) {
3172
+ const result1 = await it1.next();
3173
+ const result2 = await it2.next();
3174
+ if (result1.done || result2.done) {
3175
+ break;
3176
+ }
3177
+ yield [result1.value, result2.value];
3178
+ }
3179
+ }
3180
+ });
3181
+ }
3182
+ asyncIter2.zip = zip;
3183
+ function zipWith(iter1, iter2, fn) {
3184
+ return zip(iter1, iter2).map(async ([a, b]) => await fn(a, b));
3185
+ }
3186
+ asyncIter2.zipWith = zipWith;
3187
+ function range(startOrStop, stop, step = 1) {
3188
+ const actualStart = stop === void 0 ? 0 : startOrStop;
3189
+ const actualStop = stop === void 0 ? startOrStop : stop;
3190
+ return new Asynciterflow({
3191
+ async *[Symbol.asyncIterator]() {
3192
+ if (step === 0) {
3193
+ validateNonZero(step, "step", "range");
3194
+ }
3195
+ if (step > 0) {
3196
+ for (let i = actualStart; i < actualStop; i += step) {
3197
+ yield i;
3198
+ }
3199
+ } else {
3200
+ for (let i = actualStart; i > actualStop; i += step) {
3201
+ yield i;
3202
+ }
3203
+ }
3204
+ }
3205
+ });
3206
+ }
3207
+ asyncIter2.range = range;
3208
+ function repeat(value, times) {
3209
+ return new Asynciterflow({
3210
+ async *[Symbol.asyncIterator]() {
3211
+ if (times === void 0) {
3212
+ while (true) {
3213
+ yield value;
3214
+ }
3215
+ } else {
3216
+ for (let i = 0; i < times; i++) {
3217
+ yield value;
3218
+ }
3219
+ }
3220
+ }
3221
+ });
3222
+ }
3223
+ asyncIter2.repeat = repeat;
3224
+ function interleave(...iterables) {
3225
+ return new Asynciterflow({
3226
+ async *[Symbol.asyncIterator]() {
3227
+ if (iterables.length === 0) return;
3228
+ const iterators = iterables.map(
3229
+ (it) => Symbol.asyncIterator in it ? it[Symbol.asyncIterator]() : (async function* () {
3230
+ yield* it;
3231
+ })()
3232
+ );
3233
+ const active = new Set(iterators);
3234
+ while (active.size > 0) {
3235
+ for (const iterator of iterators) {
3236
+ if (!active.has(iterator)) continue;
3237
+ const result = await iterator.next();
3238
+ if (result.done) {
3239
+ active.delete(iterator);
3240
+ } else {
3241
+ yield result.value;
3242
+ }
3243
+ }
3244
+ }
3245
+ }
3246
+ });
3247
+ }
3248
+ asyncIter2.interleave = interleave;
3249
+ function merge(...args) {
3250
+ let compareFn;
3251
+ let iterables;
3252
+ if (typeof args[0] === "function") {
3253
+ compareFn = args[0];
3254
+ iterables = args.slice(1);
3255
+ } else {
3256
+ compareFn = (a, b) => {
3257
+ if (a < b) return -1;
3258
+ if (a > b) return 1;
3259
+ return 0;
3260
+ };
3261
+ iterables = args;
3262
+ }
3263
+ return new Asynciterflow({
3264
+ async *[Symbol.asyncIterator]() {
3265
+ if (iterables.length === 0) return;
3266
+ const heap = [];
3267
+ for (let i = 0; i < iterables.length; i++) {
3268
+ const iterable = iterables[i];
3269
+ const iterator = Symbol.asyncIterator in iterable ? iterable[Symbol.asyncIterator]() : (async function* () {
3270
+ yield* iterable;
3271
+ })();
3272
+ const result = await iterator.next();
3273
+ if (!result.done) {
3274
+ heap.push({ value: result.value, iterator, index: i });
3275
+ }
3276
+ }
3277
+ const bubbleDown = (index) => {
3278
+ const length = heap.length;
3279
+ while (true) {
3280
+ let smallest = index;
3281
+ const leftChild = 2 * index + 1;
3282
+ const rightChild = 2 * index + 2;
3283
+ if (leftChild < length && compareFn(heap[leftChild].value, heap[smallest].value) < 0) {
3284
+ smallest = leftChild;
3285
+ }
3286
+ if (rightChild < length && compareFn(heap[rightChild].value, heap[smallest].value) < 0) {
3287
+ smallest = rightChild;
3288
+ }
3289
+ if (smallest === index) break;
3290
+ [heap[index], heap[smallest]] = [heap[smallest], heap[index]];
3291
+ index = smallest;
3292
+ }
3293
+ };
3294
+ for (let i = Math.floor(heap.length / 2) - 1; i >= 0; i--) {
3295
+ bubbleDown(i);
3296
+ }
3297
+ while (heap.length > 0) {
3298
+ const { value, iterator } = heap[0];
3299
+ yield value;
3300
+ const result = await iterator.next();
3301
+ if (result.done) {
3302
+ heap[0] = heap[heap.length - 1];
3303
+ heap.pop();
3304
+ if (heap.length > 0) {
3305
+ bubbleDown(0);
3306
+ }
3307
+ } else {
3308
+ heap[0].value = result.value;
3309
+ bubbleDown(0);
3310
+ }
3311
+ }
3312
+ }
3313
+ });
3314
+ }
3315
+ asyncIter2.merge = merge;
3316
+ function chain(...iterables) {
3317
+ return new Asynciterflow({
3318
+ async *[Symbol.asyncIterator]() {
3319
+ for (const iterable of iterables) {
3320
+ if (Symbol.asyncIterator in iterable) {
3321
+ yield* iterable;
3322
+ } else {
3323
+ yield* iterable;
3324
+ }
3325
+ }
3326
+ }
3327
+ });
3328
+ }
3329
+ asyncIter2.chain = chain;
3330
+ function fromGenerator(fn) {
3331
+ return new Asynciterflow(fn());
3332
+ }
3333
+ asyncIter2.fromGenerator = fromGenerator;
3334
+ function fromPromise(promise) {
3335
+ return new Asynciterflow({
3336
+ async *[Symbol.asyncIterator]() {
3337
+ yield await promise;
3338
+ }
3339
+ });
3340
+ }
3341
+ asyncIter2.fromPromise = fromPromise;
3342
+ function fromPromises(promises) {
3343
+ return new Asynciterflow({
3344
+ async *[Symbol.asyncIterator]() {
3345
+ const pending = new Set(promises);
3346
+ const results = /* @__PURE__ */ new Map();
3347
+ const indexed = promises.map((p, i) => p.then((v) => ({ i, v })));
3348
+ while (pending.size > 0) {
3349
+ const result = await Promise.race(indexed);
3350
+ results.set(result.i, result.v);
3351
+ pending.delete(promises[result.i]);
3352
+ let nextIndex = promises.length - pending.size - 1;
3353
+ while (results.has(nextIndex)) {
3354
+ yield results.get(nextIndex);
3355
+ results.delete(nextIndex);
3356
+ nextIndex++;
3357
+ }
3358
+ }
3359
+ }
3360
+ });
3361
+ }
3362
+ asyncIter2.fromPromises = fromPromises;
3363
+ })(asyncIter || (asyncIter = {}));
3364
+
3365
+ // src/debug.ts
3366
+ var DebugState = class {
3367
+ config = {
3368
+ enabled: false,
3369
+ traceOperations: false,
3370
+ traceInput: false,
3371
+ traceOutput: false,
3372
+ logToConsole: false,
3373
+ maxTraceEntries: 1e3
3374
+ };
3375
+ traces = [];
3376
+ /**
3377
+ * Enable debug mode with optional configuration
3378
+ */
3379
+ enable(config2) {
3380
+ this.config = {
3381
+ ...this.config,
3382
+ enabled: true,
3383
+ traceOperations: true,
3384
+ ...config2
3385
+ };
3386
+ if (this.config.logToConsole) {
3387
+ console.log("[iterflow Debug] Debug mode enabled", this.config);
3388
+ }
3389
+ }
3390
+ /**
3391
+ * Disable debug mode
3392
+ */
3393
+ disable() {
3394
+ this.config.enabled = false;
3395
+ this.config.traceOperations = false;
3396
+ if (this.config.logToConsole) {
3397
+ console.log("[iterflow Debug] Debug mode disabled");
3398
+ }
3399
+ }
3400
+ /**
3401
+ * Check if debug mode is enabled
3402
+ */
3403
+ isEnabled() {
3404
+ return this.config.enabled;
3405
+ }
3406
+ /**
3407
+ * Get current configuration
3408
+ */
3409
+ getConfig() {
3410
+ return { ...this.config };
3411
+ }
3412
+ /**
3413
+ * Add a trace entry
3414
+ */
3415
+ trace(entry) {
3416
+ if (!this.config.traceOperations) {
3417
+ return;
3418
+ }
3419
+ if (this.traces.length >= (this.config.maxTraceEntries || 1e3)) {
3420
+ this.traces.shift();
3421
+ }
3422
+ this.traces.push(entry);
3423
+ if (this.config.logToConsole) {
3424
+ this.logTrace(entry);
3425
+ }
3426
+ }
3427
+ /**
3428
+ * Get all trace entries
3429
+ */
3430
+ getTraces() {
3431
+ return [...this.traces];
3432
+ }
3433
+ /**
3434
+ * Clear all traces
3435
+ */
3436
+ clearTraces() {
3437
+ this.traces = [];
3438
+ if (this.config.logToConsole) {
3439
+ console.log("[iterflow Debug] Traces cleared");
3440
+ }
3441
+ }
3442
+ /**
3443
+ * Get traces for a specific operation
3444
+ */
3445
+ getTracesForOperation(operation) {
3446
+ return this.traces.filter((t) => t.operation === operation);
3447
+ }
3448
+ /**
3449
+ * Get summary statistics for traces
3450
+ */
3451
+ getTraceSummary() {
3452
+ const summary = {};
3453
+ for (const trace of this.traces) {
3454
+ if (!summary[trace.operation]) {
3455
+ summary[trace.operation] = { count: 0, totalDuration: 0, errors: 0 };
3456
+ }
3457
+ const operationSummary = summary[trace.operation];
3458
+ operationSummary.count++;
3459
+ if (trace.duration !== void 0) {
3460
+ operationSummary.totalDuration += trace.duration;
3461
+ }
3462
+ if (trace.error) {
3463
+ operationSummary.errors++;
3464
+ }
3465
+ }
3466
+ const result = {};
3467
+ for (const [op, stats] of Object.entries(summary)) {
3468
+ result[op] = {
3469
+ count: stats.count,
3470
+ avgDuration: stats.count > 0 ? stats.totalDuration / stats.count : 0,
3471
+ errors: stats.errors
3472
+ };
3473
+ }
3474
+ return result;
3475
+ }
3476
+ /**
3477
+ * Log a trace entry to console
3478
+ */
3479
+ logTrace(entry) {
3480
+ const timestamp = new Date(entry.timestamp).toISOString();
3481
+ const duration = entry.duration !== void 0 ? `${entry.duration.toFixed(2)}ms` : "N/A";
3482
+ if (entry.error) {
3483
+ console.error(
3484
+ `[iterflow Debug] ${timestamp} | ${entry.operation} | ERROR | ${duration}`,
3485
+ entry.error
3486
+ );
3487
+ } else {
3488
+ console.log(
3489
+ `[iterflow Debug] ${timestamp} | ${entry.operation} | ${duration}`
3490
+ );
3491
+ if (this.config.traceInput && entry.input !== void 0) {
3492
+ console.log(" Input:", entry.input);
3493
+ }
3494
+ if (this.config.traceOutput && entry.output !== void 0) {
3495
+ console.log(" Output:", entry.output);
3496
+ }
3497
+ if (entry.metadata) {
3498
+ console.log(" Metadata:", entry.metadata);
3499
+ }
3500
+ }
3501
+ }
3502
+ };
3503
+ var debugState = new DebugState();
3504
+ function enableDebug(config2) {
3505
+ debugState.enable(config2);
3506
+ }
3507
+ function disableDebug() {
3508
+ debugState.disable();
3509
+ }
3510
+ function isDebugEnabled() {
3511
+ return debugState.isEnabled();
3512
+ }
3513
+ function getDebugConfig() {
3514
+ return debugState.getConfig();
3515
+ }
3516
+ function addTrace(entry) {
3517
+ debugState.trace(entry);
3518
+ }
3519
+ function getTraces() {
3520
+ return debugState.getTraces();
3521
+ }
3522
+ function clearTraces() {
3523
+ debugState.clearTraces();
3524
+ }
3525
+ function getTracesForOperation(operation) {
3526
+ return debugState.getTracesForOperation(operation);
3527
+ }
3528
+ function getTraceSummary() {
3529
+ return debugState.getTraceSummary();
3530
+ }
3531
+ function traceOperation(operation, fn, metadata) {
3532
+ if (!debugState.isEnabled()) {
3533
+ return fn();
3534
+ }
3535
+ const startTime = performance.now();
3536
+ const timestamp = Date.now();
3537
+ try {
3538
+ const result = fn();
3539
+ const duration = performance.now() - startTime;
3540
+ debugState.trace({
3541
+ operation,
3542
+ timestamp,
3543
+ duration,
3544
+ output: debugState.getConfig().traceOutput ? result : void 0,
3545
+ metadata
3546
+ });
3547
+ return result;
3548
+ } catch (error) {
3549
+ const duration = performance.now() - startTime;
3550
+ debugState.trace({
3551
+ operation,
3552
+ timestamp,
3553
+ duration,
3554
+ error,
3555
+ metadata
3556
+ });
3557
+ throw error;
3558
+ }
3559
+ }
3560
+ async function traceOperationAsync(operation, fn, metadata) {
3561
+ if (!debugState.isEnabled()) {
3562
+ return fn();
3563
+ }
3564
+ const startTime = performance.now();
3565
+ const timestamp = Date.now();
3566
+ try {
3567
+ const result = await fn();
3568
+ const duration = performance.now() - startTime;
3569
+ debugState.trace({
3570
+ operation,
3571
+ timestamp,
3572
+ duration,
3573
+ output: debugState.getConfig().traceOutput ? result : void 0,
3574
+ metadata
3575
+ });
3576
+ return result;
3577
+ } catch (error) {
3578
+ const duration = performance.now() - startTime;
3579
+ debugState.trace({
3580
+ operation,
3581
+ timestamp,
3582
+ duration,
3583
+ error,
3584
+ metadata
3585
+ });
3586
+ throw error;
3587
+ }
3588
+ }
3589
+
3590
+ // src/recovery.ts
3591
+ function withErrorRecovery(fn, errorHandler) {
3592
+ return (value, index) => {
3593
+ try {
3594
+ return fn(value, index);
3595
+ } catch (error) {
3596
+ return errorHandler(error, value, index);
3597
+ }
3598
+ };
3599
+ }
3600
+ function withRetry(fn, options = {}) {
3601
+ const { maxAttempts = 3, delay = 0, backoff = false, onRetry } = options;
3602
+ return (...args) => {
3603
+ let lastError;
3604
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
3605
+ try {
3606
+ return fn(...args);
3607
+ } catch (error) {
3608
+ lastError = error;
3609
+ if (attempt < maxAttempts) {
3610
+ if (onRetry) {
3611
+ onRetry(attempt, lastError);
3612
+ }
3613
+ }
3614
+ }
3615
+ }
3616
+ throw new OperationError(
3617
+ `Operation failed after ${maxAttempts} attempts`,
3618
+ "retry",
3619
+ lastError
3620
+ );
3621
+ };
3622
+ }
3623
+ function withRetryAsync(fn, options = {}) {
3624
+ const { maxAttempts = 3, delay = 0, backoff = false, onRetry } = options;
3625
+ return async (...args) => {
3626
+ let lastError;
3627
+ let currentDelay = delay;
3628
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
3629
+ try {
3630
+ return await fn(...args);
3631
+ } catch (error) {
3632
+ lastError = error;
3633
+ if (attempt < maxAttempts) {
3634
+ if (onRetry) {
3635
+ onRetry(attempt, lastError);
3636
+ }
3637
+ if (currentDelay > 0) {
3638
+ await new Promise((resolve) => setTimeout(resolve, currentDelay));
3639
+ }
3640
+ if (backoff) {
3641
+ currentDelay *= 2;
3642
+ }
3643
+ }
3644
+ }
3645
+ }
3646
+ throw new OperationError(
3647
+ `Operation failed after ${maxAttempts} attempts`,
3648
+ "retry",
3649
+ lastError
3650
+ );
3651
+ };
3652
+ }
3653
+ function withDefault(fn, defaultValue) {
3654
+ return (value) => {
3655
+ try {
3656
+ return fn(value);
3657
+ } catch {
3658
+ return defaultValue;
3659
+ }
3660
+ };
3661
+ }
3662
+ function tryOr(fn, fallback) {
3663
+ return (value) => {
3664
+ try {
3665
+ return fn(value);
3666
+ } catch {
3667
+ return fallback;
3668
+ }
3669
+ };
3670
+ }
3671
+ function tryCatch(fn, value) {
3672
+ try {
3673
+ return [fn(value), void 0];
3674
+ } catch (error) {
3675
+ return [void 0, error];
3676
+ }
3677
+ }
3678
+ async function tryCatchAsync(fn, value) {
3679
+ try {
3680
+ return [await fn(value), void 0];
3681
+ } catch (error) {
3682
+ return [void 0, error];
3683
+ }
3684
+ }
3685
+ function toResult(fn) {
3686
+ return (value) => {
3687
+ try {
3688
+ return { success: true, value: fn(value) };
3689
+ } catch (error) {
3690
+ return { success: false, error };
3691
+ }
3692
+ };
3693
+ }
3694
+ function toResultAsync(fn) {
3695
+ return async (value) => {
3696
+ try {
3697
+ return { success: true, value: await fn(value) };
3698
+ } catch (error) {
3699
+ return { success: false, error };
3700
+ }
3701
+ };
3702
+ }
3703
+ function safePredicate(predicate, defaultValue = false) {
3704
+ return (value, index) => {
3705
+ try {
3706
+ return predicate(value, index);
3707
+ } catch {
3708
+ return defaultValue;
3709
+ }
3710
+ };
3711
+ }
3712
+ function safeComparator(comparator, defaultComparison = 0) {
3713
+ return (a, b) => {
3714
+ try {
3715
+ return comparator(a, b);
3716
+ } catch {
3717
+ return defaultComparison;
3718
+ }
3719
+ };
3720
+ }
3721
+ function errorBoundary(fn, options = {}) {
3722
+ const { onError, rethrow = true, defaultValue } = options;
3723
+ return (...args) => {
3724
+ try {
3725
+ return fn(...args);
3726
+ } catch (error) {
3727
+ if (onError) {
3728
+ onError(error, args);
3729
+ }
3730
+ if (rethrow) {
3731
+ throw error;
3732
+ }
3733
+ return defaultValue;
3734
+ }
3735
+ };
3736
+ }
3737
+
3738
+ // src/deprecation.ts
3739
+ var config = {
3740
+ enabled: typeof process !== "undefined" && process.env.NODE_ENV !== "production",
3741
+ showStackTrace: false
3742
+ };
3743
+ var warnedFeatures = /* @__PURE__ */ new Set();
3744
+ function configureDeprecation(options) {
3745
+ config = { ...config, ...options };
3746
+ }
3747
+ function getDeprecationConfig() {
3748
+ return { ...config };
3749
+ }
3750
+ function clearDeprecationWarnings() {
3751
+ warnedFeatures.clear();
3752
+ }
3753
+ function emitWarning(warning) {
3754
+ if (!config.enabled) return;
3755
+ if (warnedFeatures.has(warning.feature)) return;
3756
+ warnedFeatures.add(warning.feature);
3757
+ if (config.handler) {
3758
+ config.handler(warning);
3759
+ return;
3760
+ }
3761
+ let message = `[iterflow] DEPRECATED: ${warning.feature} has been deprecated since v${warning.since}`;
3762
+ if (warning.removeIn) {
3763
+ message += ` and will be removed in v${warning.removeIn}`;
3764
+ }
3765
+ if (warning.alternative) {
3766
+ message += `
3767
+ Please use ${warning.alternative} instead.`;
3768
+ }
3769
+ if (warning.message) {
3770
+ message += `
3771
+ ${warning.message}`;
3772
+ }
3773
+ if (typeof process !== "undefined" && process.emitWarning) {
3774
+ const options = {
3775
+ type: "DeprecationWarning",
3776
+ code: "ITERFLOW_DEPRECATION",
3777
+ detail: warning.message
3778
+ };
3779
+ process.emitWarning(message, options);
3780
+ } else {
3781
+ console.warn(message);
3782
+ }
3783
+ if (config.showStackTrace && warning.stack) {
3784
+ console.warn("Stack trace:", warning.stack);
3785
+ }
3786
+ }
3787
+ function deprecate(options) {
3788
+ const warning = {
3789
+ ...options,
3790
+ stack: config.showStackTrace ? new Error().stack : void 0
3791
+ };
3792
+ emitWarning(warning);
3793
+ }
3794
+ function deprecated(options) {
3795
+ return function(target, propertyKey, descriptor) {
3796
+ const originalMethod = descriptor.value;
3797
+ if (!originalMethod) return;
3798
+ const className = target.constructor?.name || "Object";
3799
+ const feature = `${className}.${propertyKey}`;
3800
+ descriptor.value = function(...args) {
3801
+ deprecate({ ...options, feature });
3802
+ return originalMethod.apply(this, args);
3803
+ };
3804
+ return descriptor;
3805
+ };
3806
+ }
3807
+ function deprecatedFunction(fn, options) {
3808
+ return function(...args) {
3809
+ deprecate(options);
3810
+ return fn.apply(this, args);
3811
+ };
3812
+ }
3813
+ function hasDeprecationWarning(feature) {
3814
+ return warnedFeatures.has(feature);
3815
+ }
3816
+
3817
+ // src/index.ts
3818
+ function iter(source) {
3819
+ return new iterflow(source);
3820
+ }
3821
+ ((iter2) => {
3822
+ function zip(iter1, iter22) {
3823
+ return new iterflow({
3824
+ *[Symbol.iterator]() {
3825
+ const it1 = iter1[Symbol.iterator]();
3826
+ const it2 = iter22[Symbol.iterator]();
3827
+ while (true) {
3828
+ const result1 = it1.next();
3829
+ const result2 = it2.next();
3830
+ if (result1.done || result2.done) {
3831
+ break;
3832
+ }
3833
+ yield [result1.value, result2.value];
3834
+ }
3835
+ }
3836
+ });
3837
+ }
3838
+ iter2.zip = zip;
3839
+ function zipWith(iter1, iter22, fn) {
3840
+ return zip(iter1, iter22).map(([a, b]) => fn(a, b));
3841
+ }
3842
+ iter2.zipWith = zipWith;
3843
+ function range(startOrStop, stop, step = 1) {
3844
+ const actualStart = stop === void 0 ? 0 : startOrStop;
3845
+ const actualStop = stop === void 0 ? startOrStop : stop;
3846
+ return new iterflow({
3847
+ *[Symbol.iterator]() {
3848
+ validateNonZero(step, "step", "range");
3849
+ if (step > 0) {
3850
+ for (let i = actualStart; i < actualStop; i += step) {
3851
+ yield i;
3852
+ }
3853
+ } else {
3854
+ for (let i = actualStart; i > actualStop; i += step) {
3855
+ yield i;
3856
+ }
3857
+ }
3858
+ }
3859
+ });
3860
+ }
3861
+ iter2.range = range;
3862
+ function repeat(value, times) {
3863
+ return new iterflow({
3864
+ *[Symbol.iterator]() {
3865
+ if (times === void 0) {
3866
+ while (true) {
3867
+ yield value;
3868
+ }
3869
+ } else {
3870
+ for (let i = 0; i < times; i++) {
3871
+ yield value;
3872
+ }
3873
+ }
3874
+ }
3875
+ });
3876
+ }
3877
+ iter2.repeat = repeat;
3878
+ function interleave(...iterables) {
3879
+ return new iterflow({
3880
+ *[Symbol.iterator]() {
3881
+ if (iterables.length === 0) return;
3882
+ const iterators = iterables.map((it) => it[Symbol.iterator]());
3883
+ const active = new Set(iterators);
3884
+ while (active.size > 0) {
3885
+ for (const iterator of iterators) {
3886
+ if (!active.has(iterator)) continue;
3887
+ const result = iterator.next();
3888
+ if (result.done) {
3889
+ active.delete(iterator);
3890
+ } else {
3891
+ yield result.value;
3892
+ }
3893
+ }
3894
+ }
3895
+ }
3896
+ });
3897
+ }
3898
+ iter2.interleave = interleave;
3899
+ function merge(...args) {
3900
+ let compareFn;
3901
+ let iterables;
3902
+ if (typeof args[0] === "function") {
3903
+ compareFn = args[0];
3904
+ iterables = args.slice(1);
3905
+ } else {
3906
+ compareFn = (a, b) => {
3907
+ if (a < b) return -1;
3908
+ if (a > b) return 1;
3909
+ return 0;
3910
+ };
3911
+ iterables = args;
3912
+ }
3913
+ return new iterflow({
3914
+ *[Symbol.iterator]() {
3915
+ if (iterables.length === 0) return;
3916
+ const heap = [];
3917
+ for (let i = 0; i < iterables.length; i++) {
3918
+ const iterator = iterables[i][Symbol.iterator]();
3919
+ const result = iterator.next();
3920
+ if (!result.done) {
3921
+ heap.push({ value: result.value, iterator, index: i });
3922
+ }
3923
+ }
3924
+ const bubbleDown = (index) => {
3925
+ const length = heap.length;
3926
+ while (true) {
3927
+ let smallest = index;
3928
+ const leftChild = 2 * index + 1;
3929
+ const rightChild = 2 * index + 2;
3930
+ if (leftChild < length && compareFn(heap[leftChild].value, heap[smallest].value) < 0) {
3931
+ smallest = leftChild;
3932
+ }
3933
+ if (rightChild < length && compareFn(heap[rightChild].value, heap[smallest].value) < 0) {
3934
+ smallest = rightChild;
3935
+ }
3936
+ if (smallest === index) break;
3937
+ [heap[index], heap[smallest]] = [heap[smallest], heap[index]];
3938
+ index = smallest;
3939
+ }
3940
+ };
3941
+ for (let i = Math.floor(heap.length / 2) - 1; i >= 0; i--) {
3942
+ bubbleDown(i);
3943
+ }
3944
+ while (heap.length > 0) {
3945
+ const { value, iterator } = heap[0];
3946
+ yield value;
3947
+ const result = iterator.next();
3948
+ if (result.done) {
3949
+ heap[0] = heap[heap.length - 1];
3950
+ heap.pop();
3951
+ if (heap.length > 0) {
3952
+ bubbleDown(0);
3953
+ }
3954
+ } else {
3955
+ heap[0].value = result.value;
3956
+ bubbleDown(0);
3957
+ }
3958
+ }
3959
+ }
3960
+ });
3961
+ }
3962
+ iter2.merge = merge;
3963
+ function chain(...iterables) {
3964
+ return new iterflow({
3965
+ *[Symbol.iterator]() {
3966
+ for (const iterable of iterables) {
3967
+ yield* iterable;
3968
+ }
3969
+ }
3970
+ });
3971
+ }
3972
+ iter2.chain = chain;
3973
+ })(iter || (iter = {}));
3974
+
3975
+ export { Asynciterflow, EmptySequenceError, IndexOutOfBoundsError, OperationError, TypeConversionError, ValidationError, addTrace, asyncIter, clearDeprecationWarnings, clearTraces, configureDeprecation, deprecate, deprecated, deprecatedFunction, disableDebug, enableDebug, errorBoundary, getDebugConfig, getDeprecationConfig, getTraceSummary, getTraces, getTracesForOperation, hasDeprecationWarning, isDebugEnabled, iter, iterflow, iterflowError, safeComparator, safePredicate, toInteger, toNumber, toResult, toResultAsync, traceOperation, traceOperationAsync, tryCatch, tryCatchAsync, tryOr, validateComparator, validateFiniteNumber, validateFunction, validateIndex, validateIterable, validateNonEmpty, validateNonNegativeInteger, validateNonZero, validatePositiveInteger, validateRange, withDefault, withErrorRecovery, withRetry, withRetryAsync };
3976
+ //# sourceMappingURL=index.js.map
3977
+ //# sourceMappingURL=index.js.map