@effectionx/stream-helpers 0.7.2 → 0.8.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 +83 -0
- package/batch.ts +0 -1
- package/dist/batch.d.ts.map +1 -1
- package/dist/batch.js +0 -1
- package/dist/mod.d.ts +3 -0
- package/dist/mod.d.ts.map +1 -1
- package/dist/mod.js +3 -0
- package/dist/subject.d.ts +1 -1
- package/dist/subject.d.ts.map +1 -1
- package/dist/subject.js +12 -10
- package/dist/take-until.d.ts +46 -0
- package/dist/take-until.d.ts.map +1 -0
- package/dist/take-until.js +68 -0
- package/dist/take-while.d.ts +41 -0
- package/dist/take-while.d.ts.map +1 -0
- package/dist/take-while.js +64 -0
- package/dist/take.d.ts +36 -0
- package/dist/take.d.ts.map +1 -0
- package/dist/take.js +59 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/mod.ts +3 -0
- package/package.json +2 -1
- package/subject.test.ts +25 -0
- package/subject.ts +16 -12
- package/take-until.test.ts +113 -0
- package/take-until.ts +76 -0
- package/take-while.test.ts +89 -0
- package/take-while.ts +74 -0
- package/take.test.ts +83 -0
- package/take.ts +67 -0
package/README.md
CHANGED
|
@@ -231,6 +231,89 @@ function* example() {
|
|
|
231
231
|
}
|
|
232
232
|
```
|
|
233
233
|
|
|
234
|
+
### Take
|
|
235
|
+
|
|
236
|
+
The `take` helper creates a stream transformer that yields the first `n` values
|
|
237
|
+
from the source stream, then closes with the last taken value.
|
|
238
|
+
|
|
239
|
+
```typescript
|
|
240
|
+
import { take, forEach, streamOf } from "@effectionx/stream-helpers";
|
|
241
|
+
import { pipe } from "remeda";
|
|
242
|
+
|
|
243
|
+
function* example() {
|
|
244
|
+
const stream = streamOf([1, 2, 3, 4, 5]);
|
|
245
|
+
// yields 1, 2, then closes with 3
|
|
246
|
+
const closeValue = yield* forEach(function* (value) {
|
|
247
|
+
console.log(value); // 1, then 2
|
|
248
|
+
}, take(3)(stream));
|
|
249
|
+
console.log(closeValue); // 3
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// Works with pipe
|
|
253
|
+
const limited = pipe(source, take(3));
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### TakeWhile
|
|
257
|
+
|
|
258
|
+
The `takeWhile` helper creates a stream transformer that yields values while
|
|
259
|
+
the predicate returns true. When the predicate returns false, the stream closes
|
|
260
|
+
immediately (the failing value is not included).
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
import { takeWhile, forEach, streamOf } from "@effectionx/stream-helpers";
|
|
264
|
+
import { pipe } from "remeda";
|
|
265
|
+
|
|
266
|
+
function* example() {
|
|
267
|
+
const stream = streamOf([1, 2, 3, 4, 5]);
|
|
268
|
+
// yields 1, 2 (stops when value >= 3)
|
|
269
|
+
yield* forEach(function* (value) {
|
|
270
|
+
console.log(value); // 1, then 2
|
|
271
|
+
}, takeWhile((x) => x < 3)(stream));
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// Works with pipe
|
|
275
|
+
const filtered = pipe(source, takeWhile((x) => x.isValid));
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### TakeUntil
|
|
279
|
+
|
|
280
|
+
The `takeUntil` helper creates a stream transformer that yields values until
|
|
281
|
+
the predicate returns true. When the predicate matches, the stream closes with
|
|
282
|
+
the matching value. This is useful for "iterate until a condition is met"
|
|
283
|
+
patterns.
|
|
284
|
+
|
|
285
|
+
```typescript
|
|
286
|
+
import { takeUntil, forEach } from "@effectionx/stream-helpers";
|
|
287
|
+
import { pipe } from "remeda";
|
|
288
|
+
|
|
289
|
+
function* example() {
|
|
290
|
+
// Iterate validation progress until we get a terminal status
|
|
291
|
+
const result = yield* forEach(
|
|
292
|
+
function* (progress) {
|
|
293
|
+
showSpinner(progress.status);
|
|
294
|
+
},
|
|
295
|
+
takeUntil((p) => p.status === "valid" || p.status === "invalid")(
|
|
296
|
+
validationStream,
|
|
297
|
+
),
|
|
298
|
+
);
|
|
299
|
+
|
|
300
|
+
// result is the validation object with terminal status
|
|
301
|
+
if (result.status === "valid") {
|
|
302
|
+
console.log("Validation passed!");
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// Works with pipe
|
|
307
|
+
const untilDone = pipe(source, takeUntil((x) => x.done));
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
**Key difference between `takeWhile` and `takeUntil`:**
|
|
311
|
+
|
|
312
|
+
| Helper | Yields | Closes With | Use Case |
|
|
313
|
+
| ----------- | ----------------------- | -------------- | ----------------------- |
|
|
314
|
+
| `takeWhile` | While predicate is true | `undefined` | "Keep going while good" |
|
|
315
|
+
| `takeUntil` | Until predicate is true | Matching value | "Stop when you find it" |
|
|
316
|
+
|
|
234
317
|
### ForEach
|
|
235
318
|
|
|
236
319
|
The `forEach` helper invokes a function for each item passing through a stream.
|
package/batch.ts
CHANGED
|
@@ -41,7 +41,6 @@ export function batch(
|
|
|
41
41
|
value: undefined as never,
|
|
42
42
|
};
|
|
43
43
|
if (lastPull && options.maxTime) {
|
|
44
|
-
// biome-ignore lint/style/noNonNullAssertion: lastPull checked above
|
|
45
44
|
const timeout = yield* timebox(options.maxTime, () => lastPull!);
|
|
46
45
|
if (timeout.timeout) {
|
|
47
46
|
yield* lastPull.halt();
|
package/dist/batch.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"batch.d.ts","sourceRoot":"","sources":["../batch.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,MAAM,EAAoB,MAAM,WAAW,CAAC;AAE1D,KAAK,iBAAiB,CAAC,CAAC,EAAE,IAAI,SAAS,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,IAAI,CAC9D,CAAC,EACD,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CACvB,GACC;KACG,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;CACzE,CAAC,IAAI,CAAC,CAAC;AAEV,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;;;GASG;AACH,wBAAgB,KAAK,CACnB,OAAO,EAAE,iBAAiB,CAAC,YAAY,CAAC,GACvC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"batch.d.ts","sourceRoot":"","sources":["../batch.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,MAAM,EAAoB,MAAM,WAAW,CAAC;AAE1D,KAAK,iBAAiB,CAAC,CAAC,EAAE,IAAI,SAAS,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,IAAI,CAC9D,CAAC,EACD,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CACvB,GACC;KACG,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;CACzE,CAAC,IAAI,CAAC,CAAC;AAEV,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;;;GASG;AACH,wBAAgB,KAAK,CACnB,OAAO,EAAE,iBAAiB,CAAC,YAAY,CAAC,GACvC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CA6E/D"}
|
package/dist/batch.js
CHANGED
|
@@ -24,7 +24,6 @@ export function batch(options) {
|
|
|
24
24
|
value: undefined,
|
|
25
25
|
};
|
|
26
26
|
if (lastPull && options.maxTime) {
|
|
27
|
-
// biome-ignore lint/style/noNonNullAssertion: lastPull checked above
|
|
28
27
|
const timeout = yield* timebox(options.maxTime, () => lastPull);
|
|
29
28
|
if (timeout.timeout) {
|
|
30
29
|
yield* lastPull.halt();
|
package/dist/mod.d.ts
CHANGED
package/dist/mod.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../mod.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC"}
|
|
1
|
+
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../mod.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC"}
|
package/dist/mod.js
CHANGED
package/dist/subject.d.ts
CHANGED
|
@@ -34,5 +34,5 @@ import type { Stream } from "effection";
|
|
|
34
34
|
* ]);
|
|
35
35
|
* ```
|
|
36
36
|
*/
|
|
37
|
-
export declare function createSubject<T>(): <TClose>(stream: Stream<T, TClose>) => Stream<T, TClose>;
|
|
37
|
+
export declare function createSubject<T>(initial?: T): <TClose>(stream: Stream<T, TClose>) => Stream<T, TClose>;
|
|
38
38
|
//# sourceMappingURL=subject.d.ts.map
|
package/dist/subject.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subject.d.ts","sourceRoot":"","sources":["../subject.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAgB,MAAM,WAAW,CAAC;AAEtD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,aAAa,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"subject.d.ts","sourceRoot":"","sources":["../subject.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAgB,MAAM,WAAW,CAAC;AAEtD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAC7B,OAAO,CAAC,EAAE,CAAC,GACV,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CA+B1D"}
|
package/dist/subject.js
CHANGED
|
@@ -33,25 +33,27 @@
|
|
|
33
33
|
* ]);
|
|
34
34
|
* ```
|
|
35
35
|
*/
|
|
36
|
-
export function createSubject() {
|
|
37
|
-
let current = undefined
|
|
36
|
+
export function createSubject(initial) {
|
|
37
|
+
let current = typeof initial !== "undefined"
|
|
38
|
+
? { done: false, value: initial }
|
|
39
|
+
: undefined;
|
|
38
40
|
return (stream) => ({
|
|
39
41
|
*[Symbol.iterator]() {
|
|
40
42
|
let upstream = yield* stream;
|
|
43
|
+
let tracking = {
|
|
44
|
+
*next() {
|
|
45
|
+
current = yield* upstream.next();
|
|
46
|
+
return current;
|
|
47
|
+
},
|
|
48
|
+
};
|
|
41
49
|
let iterator = current
|
|
42
50
|
? {
|
|
43
51
|
*next() {
|
|
44
|
-
iterator =
|
|
45
|
-
// biome-ignore lint/style/noNonNullAssertion: current checked in ternary condition
|
|
52
|
+
iterator = tracking;
|
|
46
53
|
return current;
|
|
47
54
|
},
|
|
48
55
|
}
|
|
49
|
-
:
|
|
50
|
-
*next() {
|
|
51
|
-
current = yield* upstream.next();
|
|
52
|
-
return current;
|
|
53
|
-
},
|
|
54
|
-
};
|
|
56
|
+
: tracking;
|
|
55
57
|
return {
|
|
56
58
|
next: () => iterator.next(),
|
|
57
59
|
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { Stream } from "effection";
|
|
2
|
+
/**
|
|
3
|
+
* Creates a stream transformer that yields values from the source stream
|
|
4
|
+
* until the predicate returns true. Closes with the matching value when
|
|
5
|
+
* the predicate returns true.
|
|
6
|
+
*
|
|
7
|
+
* This is useful for "iterate until a condition is met" patterns, where
|
|
8
|
+
* the matching value is meaningful (e.g., a terminal status).
|
|
9
|
+
*
|
|
10
|
+
* If the source stream closes before the predicate returns true, the
|
|
11
|
+
* resulting stream closes with the source's close value.
|
|
12
|
+
*
|
|
13
|
+
* @template T - The type of items in the stream
|
|
14
|
+
* @template TClose - The type of the close value
|
|
15
|
+
* @param predicate - A function that returns true to stop taking values
|
|
16
|
+
* @returns A stream transformer that yields values until predicate is true,
|
|
17
|
+
* closing with the matching value
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* import { takeUntil, forEach } from "@effectionx/stream-helpers";
|
|
22
|
+
*
|
|
23
|
+
* // Iterate validation progress until we get a terminal status
|
|
24
|
+
* const result = yield* forEach(function*(progress) {
|
|
25
|
+
* showSpinner(progress.status);
|
|
26
|
+
* }, takeUntil((p) => p.status === "valid" || p.status === "invalid")(channel));
|
|
27
|
+
*
|
|
28
|
+
* // result is the validation object with terminal status
|
|
29
|
+
* if (result.status === "valid") {
|
|
30
|
+
* // proceed
|
|
31
|
+
* }
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```typescript
|
|
36
|
+
* import { takeUntil, map } from "@effectionx/stream-helpers";
|
|
37
|
+
* import { pipe } from "remeda";
|
|
38
|
+
*
|
|
39
|
+
* const limited = pipe(
|
|
40
|
+
* source,
|
|
41
|
+
* takeUntil((x) => x.done),
|
|
42
|
+
* );
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export declare function takeUntil<T>(predicate: (item: T) => boolean): <TClose>(stream: Stream<T, TClose>) => Stream<T, T | TClose>;
|
|
46
|
+
//# sourceMappingURL=take-until.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"take-until.d.ts","sourceRoot":"","sources":["../take-until.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAExC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,wBAAgB,SAAS,CAAC,CAAC,EACzB,SAAS,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,GAC9B,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,CA4B9D"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a stream transformer that yields values from the source stream
|
|
3
|
+
* until the predicate returns true. Closes with the matching value when
|
|
4
|
+
* the predicate returns true.
|
|
5
|
+
*
|
|
6
|
+
* This is useful for "iterate until a condition is met" patterns, where
|
|
7
|
+
* the matching value is meaningful (e.g., a terminal status).
|
|
8
|
+
*
|
|
9
|
+
* If the source stream closes before the predicate returns true, the
|
|
10
|
+
* resulting stream closes with the source's close value.
|
|
11
|
+
*
|
|
12
|
+
* @template T - The type of items in the stream
|
|
13
|
+
* @template TClose - The type of the close value
|
|
14
|
+
* @param predicate - A function that returns true to stop taking values
|
|
15
|
+
* @returns A stream transformer that yields values until predicate is true,
|
|
16
|
+
* closing with the matching value
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* import { takeUntil, forEach } from "@effectionx/stream-helpers";
|
|
21
|
+
*
|
|
22
|
+
* // Iterate validation progress until we get a terminal status
|
|
23
|
+
* const result = yield* forEach(function*(progress) {
|
|
24
|
+
* showSpinner(progress.status);
|
|
25
|
+
* }, takeUntil((p) => p.status === "valid" || p.status === "invalid")(channel));
|
|
26
|
+
*
|
|
27
|
+
* // result is the validation object with terminal status
|
|
28
|
+
* if (result.status === "valid") {
|
|
29
|
+
* // proceed
|
|
30
|
+
* }
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```typescript
|
|
35
|
+
* import { takeUntil, map } from "@effectionx/stream-helpers";
|
|
36
|
+
* import { pipe } from "remeda";
|
|
37
|
+
*
|
|
38
|
+
* const limited = pipe(
|
|
39
|
+
* source,
|
|
40
|
+
* takeUntil((x) => x.done),
|
|
41
|
+
* );
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export function takeUntil(predicate) {
|
|
45
|
+
return (stream) => ({
|
|
46
|
+
*[Symbol.iterator]() {
|
|
47
|
+
const subscription = yield* stream;
|
|
48
|
+
let done = false;
|
|
49
|
+
return {
|
|
50
|
+
*next() {
|
|
51
|
+
if (done) {
|
|
52
|
+
return { done: true, value: undefined };
|
|
53
|
+
}
|
|
54
|
+
const result = yield* subscription.next();
|
|
55
|
+
if (result.done) {
|
|
56
|
+
return result;
|
|
57
|
+
}
|
|
58
|
+
if (predicate(result.value)) {
|
|
59
|
+
done = true;
|
|
60
|
+
// Close with the matching value
|
|
61
|
+
return { done: true, value: result.value };
|
|
62
|
+
}
|
|
63
|
+
return result;
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { Stream } from "effection";
|
|
2
|
+
/**
|
|
3
|
+
* Creates a stream transformer that yields values from the source stream
|
|
4
|
+
* while the predicate returns true. Closes when the predicate returns false,
|
|
5
|
+
* without including the failing value.
|
|
6
|
+
*
|
|
7
|
+
* When the predicate fails, the stream closes immediately without the failing
|
|
8
|
+
* value. The close value will be `undefined` since we don't have access to
|
|
9
|
+
* the source's close value without draining the entire stream.
|
|
10
|
+
*
|
|
11
|
+
* If the source stream closes before the predicate returns false, the
|
|
12
|
+
* resulting stream closes with the source's close value.
|
|
13
|
+
*
|
|
14
|
+
* @template T - The type of items in the stream
|
|
15
|
+
* @template TClose - The type of the close value
|
|
16
|
+
* @param predicate - A function that returns true to continue taking values
|
|
17
|
+
* @returns A stream transformer that yields values while predicate is true
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* import { takeWhile, streamOf } from "@effectionx/stream-helpers";
|
|
22
|
+
*
|
|
23
|
+
* const stream = streamOf([1, 2, 3, 4, 5]);
|
|
24
|
+
* // yields 1, 2 (stops when value >= 3)
|
|
25
|
+
* const limited = takeWhile((x: number) => x < 3)(stream);
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```typescript
|
|
30
|
+
* import { takeWhile, map } from "@effectionx/stream-helpers";
|
|
31
|
+
* import { pipe } from "remeda";
|
|
32
|
+
*
|
|
33
|
+
* const limited = pipe(
|
|
34
|
+
* source,
|
|
35
|
+
* map(function* (x) { return x * 2; }),
|
|
36
|
+
* takeWhile((x) => x < 100),
|
|
37
|
+
* );
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export declare function takeWhile<T>(predicate: (item: T) => boolean): <TClose>(stream: Stream<T, TClose>) => Stream<T, TClose | undefined>;
|
|
41
|
+
//# sourceMappingURL=take-while.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"take-while.d.ts","sourceRoot":"","sources":["../take-while.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAExC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAgB,SAAS,CAAC,CAAC,EACzB,SAAS,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,GAC9B,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC,CA+BtE"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a stream transformer that yields values from the source stream
|
|
3
|
+
* while the predicate returns true. Closes when the predicate returns false,
|
|
4
|
+
* without including the failing value.
|
|
5
|
+
*
|
|
6
|
+
* When the predicate fails, the stream closes immediately without the failing
|
|
7
|
+
* value. The close value will be `undefined` since we don't have access to
|
|
8
|
+
* the source's close value without draining the entire stream.
|
|
9
|
+
*
|
|
10
|
+
* If the source stream closes before the predicate returns false, the
|
|
11
|
+
* resulting stream closes with the source's close value.
|
|
12
|
+
*
|
|
13
|
+
* @template T - The type of items in the stream
|
|
14
|
+
* @template TClose - The type of the close value
|
|
15
|
+
* @param predicate - A function that returns true to continue taking values
|
|
16
|
+
* @returns A stream transformer that yields values while predicate is true
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* import { takeWhile, streamOf } from "@effectionx/stream-helpers";
|
|
21
|
+
*
|
|
22
|
+
* const stream = streamOf([1, 2, 3, 4, 5]);
|
|
23
|
+
* // yields 1, 2 (stops when value >= 3)
|
|
24
|
+
* const limited = takeWhile((x: number) => x < 3)(stream);
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* import { takeWhile, map } from "@effectionx/stream-helpers";
|
|
30
|
+
* import { pipe } from "remeda";
|
|
31
|
+
*
|
|
32
|
+
* const limited = pipe(
|
|
33
|
+
* source,
|
|
34
|
+
* map(function* (x) { return x * 2; }),
|
|
35
|
+
* takeWhile((x) => x < 100),
|
|
36
|
+
* );
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export function takeWhile(predicate) {
|
|
40
|
+
return (stream) => ({
|
|
41
|
+
*[Symbol.iterator]() {
|
|
42
|
+
const subscription = yield* stream;
|
|
43
|
+
let done = false;
|
|
44
|
+
return {
|
|
45
|
+
*next() {
|
|
46
|
+
if (done) {
|
|
47
|
+
return { done: true, value: undefined };
|
|
48
|
+
}
|
|
49
|
+
const result = yield* subscription.next();
|
|
50
|
+
if (result.done) {
|
|
51
|
+
return result;
|
|
52
|
+
}
|
|
53
|
+
if (!predicate(result.value)) {
|
|
54
|
+
done = true;
|
|
55
|
+
// Close immediately without the failing value
|
|
56
|
+
// We return undefined as we don't drain the stream
|
|
57
|
+
return { done: true, value: undefined };
|
|
58
|
+
}
|
|
59
|
+
return result;
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
}
|
package/dist/take.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { Stream } from "effection";
|
|
2
|
+
/**
|
|
3
|
+
* Creates a stream transformer that yields the first `n` values from the
|
|
4
|
+
* source stream, then closes with the last taken value.
|
|
5
|
+
*
|
|
6
|
+
* If the source stream closes before yielding `n` values, the resulting
|
|
7
|
+
* stream closes with the source's close value.
|
|
8
|
+
*
|
|
9
|
+
* @template T - The type of items in the stream
|
|
10
|
+
* @template TClose - The type of the close value
|
|
11
|
+
* @param n - The number of values to take
|
|
12
|
+
* @returns A stream transformer that yields at most `n` values
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* import { take, streamOf } from "@effectionx/stream-helpers";
|
|
17
|
+
*
|
|
18
|
+
* const stream = streamOf([1, 2, 3, 4, 5]);
|
|
19
|
+
* // yields 1, 2, then closes with 3
|
|
20
|
+
* const limited = take(3)(stream);
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* import { take, map } from "@effectionx/stream-helpers";
|
|
26
|
+
* import { pipe } from "remeda";
|
|
27
|
+
*
|
|
28
|
+
* const limited = pipe(
|
|
29
|
+
* source,
|
|
30
|
+
* map(function* (x) { return x * 2; }),
|
|
31
|
+
* take(5),
|
|
32
|
+
* );
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export declare function take<T>(n: number): <TClose>(stream: Stream<T, TClose>) => Stream<T, T | TClose>;
|
|
36
|
+
//# sourceMappingURL=take.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"take.d.ts","sourceRoot":"","sources":["../take.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAExC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,IAAI,CAAC,CAAC,EACpB,CAAC,EAAE,MAAM,GACR,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,CA6B9D"}
|
package/dist/take.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a stream transformer that yields the first `n` values from the
|
|
3
|
+
* source stream, then closes with the last taken value.
|
|
4
|
+
*
|
|
5
|
+
* If the source stream closes before yielding `n` values, the resulting
|
|
6
|
+
* stream closes with the source's close value.
|
|
7
|
+
*
|
|
8
|
+
* @template T - The type of items in the stream
|
|
9
|
+
* @template TClose - The type of the close value
|
|
10
|
+
* @param n - The number of values to take
|
|
11
|
+
* @returns A stream transformer that yields at most `n` values
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* import { take, streamOf } from "@effectionx/stream-helpers";
|
|
16
|
+
*
|
|
17
|
+
* const stream = streamOf([1, 2, 3, 4, 5]);
|
|
18
|
+
* // yields 1, 2, then closes with 3
|
|
19
|
+
* const limited = take(3)(stream);
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* import { take, map } from "@effectionx/stream-helpers";
|
|
25
|
+
* import { pipe } from "remeda";
|
|
26
|
+
*
|
|
27
|
+
* const limited = pipe(
|
|
28
|
+
* source,
|
|
29
|
+
* map(function* (x) { return x * 2; }),
|
|
30
|
+
* take(5),
|
|
31
|
+
* );
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export function take(n) {
|
|
35
|
+
return (stream) => ({
|
|
36
|
+
*[Symbol.iterator]() {
|
|
37
|
+
const subscription = yield* stream;
|
|
38
|
+
let count = 0;
|
|
39
|
+
return {
|
|
40
|
+
*next() {
|
|
41
|
+
if (count >= n) {
|
|
42
|
+
// Should not happen if used correctly, but handle gracefully
|
|
43
|
+
return { done: true, value: undefined };
|
|
44
|
+
}
|
|
45
|
+
const result = yield* subscription.next();
|
|
46
|
+
if (result.done) {
|
|
47
|
+
return result;
|
|
48
|
+
}
|
|
49
|
+
count++;
|
|
50
|
+
if (count >= n) {
|
|
51
|
+
// This is the nth value, return it and mark as done
|
|
52
|
+
return { done: true, value: result.value };
|
|
53
|
+
}
|
|
54
|
+
return result;
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
}
|