iterflow 0.10.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -3,11 +3,12 @@
3
3
  Iterator utilities for ES2022+ with statistical operations, windowing, and lazy evaluation.
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/iterflow.svg)](https://www.npmjs.com/package/iterflow)
6
+ [![CI](https://img.shields.io/github/actions/workflow/status/mathscapes/iterflow/ci.yml?branch=main)](https://github.com/mathscapes/iterflow/actions)
7
+ [![Coverage](https://img.shields.io/badge/coverage-81%25-brightgreen)](https://github.com/mathscapes/iterflow)
8
+ [![Zero Dependencies](https://img.shields.io/badge/dependencies-0-brightgreen)](https://github.com/mathscapes/iterflow/blob/main/package.json)
9
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.6%2B-blue)](https://www.typescriptlang.org/)
6
10
  [![License: Unlicense](https://img.shields.io/badge/License-Unlicense-blue.svg)](https://unlicense.org/)
7
11
 
8
- ---
9
-
10
-
11
12
  ## Installation
12
13
 
13
14
  ```bash
@@ -38,217 +39,88 @@ iter([1, 2, 3, 4, 5, 6])
38
39
  // [[4, 8], [12]]
39
40
  ```
40
41
 
41
- ## Resource Limits & Safety (v0.8.0)
42
-
43
- New in v0.8.0: Production-ready safety features to protect against infinite loops, slow operations, and runaway resource usage:
44
-
45
- ```typescript
46
- // Prevent infinite loops with hard limits
47
- iter.range(Infinity)
48
- .limit(10000) // Throws if exceeded
49
- .toArray(1000); // Collects max 1000 items
50
-
51
- // Timeout async operations
52
- await asyncIter(items)
53
- .map(slowOperation)
54
- .timeout(5000) // 5s per iteration
55
- .toArray();
56
-
57
- // User cancellation with AbortController
58
- const controller = new AbortController();
59
- const promise = asyncIter(largeJob)
60
- .withSignal(controller.signal)
61
- .toArray();
62
-
63
- // User clicks cancel
64
- controller.abort('User cancelled');
65
- ```
66
-
67
- **New APIs:**
68
- - `limit(maxIterations)` - Throw OperationError if iteration limit exceeded
69
- - `timeout(ms)` - Throw TimeoutError if async operations are too slow
70
- - `withSignal(signal)` - Integrate with AbortController for cancellation
71
- - `toArray(maxSize?)` - Optional size limit for safe collection
72
- - New error types: `TimeoutError`, `AbortError`
73
-
74
- For complete details, see the [Resource Limits Guide](docs/guides/resource-limits.md).
75
-
76
- ## API
77
-
78
- ### Wrapper API
79
-
80
- ```typescript
81
- import { iter } from 'iterflow';
82
-
83
- iter([1, 2, 3, 4, 5])
84
- .filter(x => x > 2) // Native iterator method
85
- .map(x => x * 2) // Native iterator method
86
- .sum(); // iterflow extension - 24
87
- ```
88
-
89
- ### Functional API
90
-
91
- ```typescript
92
- import { sum, filter, map } from 'iterflow/fn';
93
-
94
- const data = [1, 2, 3, 4, 5];
95
- sum(map(x => x * 2)(filter(x => x > 2)(data))); // 24
96
- ```
97
-
98
- ## Operations
42
+ ## Core Operations
99
43
 
100
44
  ### Statistical
101
45
 
102
46
  ```typescript
103
- iter([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]).sum(); // 55
104
- iter([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]).mean(); // 5.5
105
- iter([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]).median(); // 5.5
106
- iter([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]).variance(); // 8.25
107
- iter([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]).percentile(75); // 7.75
47
+ iter([1, 2, 3, 4, 5]).sum(); // 15
48
+ iter([1, 2, 3, 4, 5]).mean(); // 3
49
+ iter([1, 2, 3, 4, 5]).median(); // 3
50
+ iter([1, 2, 3, 4, 5]).variance(); // 2
108
51
  ```
109
52
 
110
53
  ### Windowing
111
54
 
112
55
  ```typescript
113
- // Sliding window
114
- iter([1, 2, 3, 4, 5]).window(3).toArray();
115
- // [[1,2,3], [2,3,4], [3,4,5]]
116
-
117
- // Non-overlapping chunks
118
- iter([1, 2, 3, 4, 5]).chunk(2).toArray();
119
- // [[1,2], [3,4], [5]]
120
-
121
- // Consecutive pairs
122
- iter([1, 2, 3, 4]).pairwise().toArray();
123
- // [[1,2], [2,3], [3,4]]
124
- ```
125
-
126
- ### Grouping
127
-
128
- ```typescript
129
- // Partition by predicate
130
- const [evens, odds] = iter([1, 2, 3, 4, 5, 6])
131
- .partition(x => x % 2 === 0);
132
-
133
- // Group by key function
134
- const items = [
135
- { category: 'fruit', name: 'apple' },
136
- { category: 'vegetable', name: 'carrot' },
137
- { category: 'fruit', name: 'banana' }
138
- ];
139
-
140
- const groups = iter(items).groupBy(item => item.category);
56
+ iter([1, 2, 3, 4, 5]).window(3).toArray(); // [[1,2,3], [2,3,4], [3,4,5]]
57
+ iter([1, 2, 3, 4, 5]).chunk(2).toArray(); // [[1,2], [3,4], [5]]
141
58
  ```
142
59
 
143
- ### Set Operations
60
+ ### Transformations
144
61
 
145
62
  ```typescript
146
- // Remove duplicates
147
- iter([1, 2, 2, 3, 3, 3, 4]).distinct().toArray();
148
- // [1, 2, 3, 4]
149
-
150
- // Remove duplicates by key
151
- iter(people).distinctBy(person => person.id).toArray();
63
+ iter([1, 2, 3, 4, 5])
64
+ .map(x => x * 2)
65
+ .filter(x => x > 5)
66
+ .take(3)
67
+ .toArray(); // [6, 8, 10]
152
68
  ```
153
69
 
154
- ### Combining
70
+ ### Resource Limits (v0.8.0+)
155
71
 
156
72
  ```typescript
157
- // Zip iterators
158
- iter.zip([1, 2, 3], ['a', 'b', 'c']).toArray();
159
- // [[1,'a'], [2,'b'], [3,'c']]
73
+ // Prevent infinite loops
74
+ iter.range(Infinity)
75
+ .limit(10000) // Throws if exceeded
76
+ .toArray(1000); // Collects max 1000
160
77
 
161
- // Interleave round-robin
162
- iter.interleave([1, 2, 3], [4, 5, 6]).toArray();
163
- // [1, 4, 2, 5, 3, 6]
78
+ // Timeout async operations
79
+ await asyncIter(items)
80
+ .timeout(5000) // 5s per iteration
81
+ .toArray();
164
82
 
165
- // Merge sorted iterators
166
- iter.merge([1, 3, 5], [2, 4, 6]).toArray();
167
- // [1, 2, 3, 4, 5, 6]
83
+ // User cancellation
84
+ const controller = new AbortController();
85
+ asyncIter(data).withSignal(controller.signal).toArray();
86
+ controller.abort(); // Cancel anytime
168
87
  ```
169
88
 
170
- ### Utilities
171
-
172
- ```typescript
173
- // Side effects
174
- iter([1, 2, 3])
175
- .tap(x => console.log(`Processing: ${x}`))
176
- .map(x => x * 2)
177
- .toArray();
89
+ ## Documentation
178
90
 
179
- // Conditional take/drop
180
- iter([1, 2, 3, 4, 3, 2, 1]).takeWhile(x => x < 4).toArray();
181
- // [1, 2, 3]
91
+ - **[API Reference](./docs/api/index.md)** - Complete TypeScript API documentation
92
+ - **[Examples](./examples/)** - Real-world usage examples
182
93
 
183
- iter([1, 2, 3, 4, 5]).dropWhile(x => x < 3).toArray();
184
- // [3, 4, 5]
185
- ```
94
+ ## When to Use iterflow
186
95
 
187
- ### Generators
96
+ ### Use iterflow when
188
97
 
189
- ```typescript
190
- // Numeric ranges
191
- iter.range(5).toArray(); // [0, 1, 2, 3, 4]
192
- iter.range(2, 8).toArray(); // [2, 3, 4, 5, 6, 7]
193
- iter.range(0, 10, 2).toArray(); // [0, 2, 4, 6, 8]
194
-
195
- // Repeat values
196
- iter.repeat('hello', 3).toArray(); // ['hello', 'hello', 'hello']
197
- iter.repeat(0).take(5).toArray(); // [0, 0, 0, 0, 0]
198
- ```
98
+ - Large datasets (1000+ items) - lazy evaluation avoids unnecessary work
99
+ - Early termination - finding first match, taking limited results
100
+ - Memory efficiency - windowing, chunking, processing huge files
101
+ - Complex pipelines - chaining 3+ operations
102
+ - Statistical operations - mean, median, variance, percentiles
199
103
 
200
- ## Examples
104
+ ### Consider alternatives when
201
105
 
202
- ### Processing Pipeline
106
+ - Small arrays (< 100 items) - native Array methods are slightly faster
107
+ - Single simple operation - map or filter alone
108
+ - Need multiple iterations - arrays are easier to loop over multiple times
203
109
 
204
- ```typescript
205
- interface Sale {
206
- product: string;
207
- amount: number;
208
- category: string;
209
- }
210
-
211
- const sales: Sale[] = [
212
- { product: 'Laptop', amount: 1200, category: 'Electronics' },
213
- { product: 'Mouse', amount: 25, category: 'Electronics' },
214
- { product: 'Book', amount: 15, category: 'Books' },
215
- ];
216
-
217
- // Average electronics sale amount
218
- const electronicsAvg = iter(sales)
219
- .filter(sale => sale.category === 'Electronics')
220
- .map(sale => sale.amount)
221
- .mean();
222
-
223
- // Total sales by category
224
- const salesByCategory = iter(sales)
225
- .groupBy(sale => sale.category)
226
- .entries()
227
- .map(([category, sales]) => ({
228
- category,
229
- total: iter(sales).map(sale => sale.amount).sum()
230
- }));
231
- ```
110
+ ## API Styles
232
111
 
233
- ### Infinite Sequences
112
+ ### Wrapper API (Recommended for most use cases)
234
113
 
235
114
  ```typescript
236
- function* fibonacci() {
237
- let a = 0, b = 1;
238
- while (true) {
239
- yield a;
240
- [a, b] = [b, a + b];
241
- }
242
- }
243
-
244
- // First 10 even fibonacci numbers
245
- const evenFibs = iter(fibonacci())
115
+ import { iter } from 'iterflow';
116
+
117
+ iter([1, 2, 3, 4, 5])
246
118
  .filter(x => x % 2 === 0)
247
- .take(10)
248
- .toArray();
119
+ .map(x => x * 2)
120
+ .sum(); // 12
249
121
  ```
250
122
 
251
- ### Moving Averages
123
+ ### Functional API (Better tree-shaking)
252
124
 
253
125
  ```typescript
254
126
  const temperatures = [20, 22, 25, 23, 21, 19, 18, 20, 22, 24];
@@ -300,11 +172,8 @@ See **[docs/BENCHMARKS.md](docs/BENCHMARKS.md)** for detailed performance data a
300
172
 
301
173
  ## Documentation
302
174
 
303
- - **[API Reference](docs/API.md)** - Complete API documentation for all methods (v0.9.0+)
304
- - **[Migration Guide](docs/MIGRATION.md)** - Upgrading from v0.x to v1.0 (v0.9.0+)
305
175
  - **[FAQ](FAQ.md)** - Frequently asked questions, common patterns, and troubleshooting
306
176
  - **[Examples](examples/)** - Real-world usage examples
307
- - **[Resource Limits Guide](docs/guides/resource-limits.md)** - Production safety features (v0.8.0+)
308
177
  - **[Memory Safety Guide](docs/guides/memory-safety.md)** - Avoiding memory leaks and efficient memory usage
309
178
  - **[Performance Guide](docs/PERFORMANCE.md)** - Optimization techniques and benchmarking
310
179
  - **[Benchmarking Guide](docs/BENCHMARKING.md)** - Running and interpreting benchmarks
@@ -312,14 +181,7 @@ See **[docs/BENCHMARKS.md](docs/BENCHMARKS.md)** for detailed performance data a
312
181
 
313
182
  ## Contributing
314
183
 
315
- We welcome contributions! Please see our [PLAYBOOK.md](PLAYBOOK.md) for:
316
-
317
- - Development workflow and branching strategy
318
- - Commit message guidelines
319
- - Testing requirements
320
- - Release process
321
-
322
- For quick start:
184
+ Quick start:
323
185
 
324
186
  1. Fork the repository
325
187
  2. Create a feature branch from `dev`
@@ -328,38 +190,6 @@ For quick start:
328
190
 
329
191
  See [PLAYBOOK.md](PLAYBOOK.md) for complete details.
330
192
 
331
- ## Semantic Versioning Commitment
332
-
333
- Starting with v1.0.0, iterflow follows strict semantic versioning:
334
-
335
- - **Major versions** (2.0.0, 3.0.0): Breaking changes to public API
336
- - **Minor versions** (1.1.0, 1.2.0): New features, backwards-compatible
337
- - **Patch versions** (1.0.1, 1.0.2): Bug fixes, no API changes
338
-
339
- ### API Stability Guarantee
340
-
341
- The following APIs are stable and will not have breaking changes in 1.x:
342
-
343
- - All public methods on `iterflow<T>` class (116 methods)
344
- - All public methods on `Asynciterflow<T>` class (116 methods)
345
- - All exports from `iterflow/fn` functional API
346
- - All error classes (`iterflowError`, `TimeoutError`, `AbortError`, `OperationError`)
347
- - All TypeScript type definitions and interfaces
348
-
349
- ### What We Promise
350
-
351
- - **No breaking changes** in minor or patch releases
352
- - **Comprehensive changelog** for all releases
353
- - **Deprecation warnings** before any breaking changes (minimum 1 major version notice)
354
- - **Migration guides** for major version upgrades
355
- - **Long-term support** for 1.x (at least 18 months from v1.0.0 release)
356
-
357
- ### Reporting Issues
358
-
359
- - **Bugs**: https://github.com/mathscapes/iterflow/issues
360
- - **Security**: See [SECURITY.md](SECURITY.md) for responsible disclosure
361
- - **Feature Requests**: https://github.com/mathscapes/iterflow/discussions
362
-
363
193
  ## License
364
194
 
365
195
  The Unlicense - See [LICENSE](LICENSE) for details.
package/dist/fn/index.cjs CHANGED
@@ -15,6 +15,26 @@ var iterflowError = class extends Error {
15
15
  }
16
16
  /**
17
17
  * Returns a detailed error message with context
18
+ *
19
+ * Formats the error as a multi-line string including operation name, context data,
20
+ * and stack trace for comprehensive debugging information.
21
+ *
22
+ * @returns A formatted string containing all error details
23
+ * @example
24
+ * ```typescript
25
+ * const error = new iterflowError(
26
+ * "Processing failed",
27
+ * "transform",
28
+ * { index: 42, value: null }
29
+ * );
30
+ * console.log(error.toDetailedString());
31
+ * // iterflowError: Processing failed
32
+ * // Operation: transform
33
+ * // Context:
34
+ * // index: 42
35
+ * // value: null
36
+ * // Stack: ...
37
+ * ```
18
38
  */
19
39
  toDetailedString() {
20
40
  let msg = `${this.name}: ${this.message}`;
@@ -87,11 +107,11 @@ function compose(...fns) {
87
107
  }
88
108
  function createOperation(name, generator) {
89
109
  if (generator.length === 1) {
90
- return (iterable) => {
110
+ return ((iterable) => {
91
111
  const result = generator(iterable);
92
112
  Object.defineProperty(result, "name", { value: name });
93
113
  return result;
94
- };
114
+ });
95
115
  }
96
116
  return (...configs) => {
97
117
  return (iterable) => {
@@ -133,7 +153,10 @@ function takeTransducer(n) {
133
153
  }
134
154
  function composeTransducers(...transducers) {
135
155
  return (reducer) => {
136
- return transducers.reduceRight((acc, xf) => xf(acc), reducer);
156
+ return transducers.reduceRight(
157
+ (acc, xf) => xf(acc),
158
+ reducer
159
+ );
137
160
  };
138
161
  }
139
162
  var REDUCED = Symbol("@@transducer/reduced");