@effectionx/stream-helpers 0.7.2 → 0.7.3

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
@@ -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();
@@ -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,CA8E/D"}
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
@@ -11,4 +11,7 @@ export * from "./reduce.ts";
11
11
  export * from "./drain.ts";
12
12
  export * from "./first.ts";
13
13
  export * from "./last.ts";
14
+ export * from "./take.ts";
15
+ export * from "./take-while.ts";
16
+ export * from "./take-until.ts";
14
17
  //# sourceMappingURL=mod.d.ts.map
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
@@ -11,3 +11,6 @@ export * from "./reduce.js";
11
11
  export * from "./drain.js";
12
12
  export * from "./first.js";
13
13
  export * from "./last.js";
14
+ export * from "./take.js";
15
+ export * from "./take-while.js";
16
+ export * from "./take-until.js";
@@ -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,KAAK,CAAC,MAAM,EACzC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,KACtB,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CA2BrB"}
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,KAAK,CAAC,MAAM,EACzC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,KACtB,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CA0BrB"}
package/dist/subject.js CHANGED
@@ -42,7 +42,6 @@ export function createSubject() {
42
42
  ? {
43
43
  *next() {
44
44
  iterator = upstream;
45
- // biome-ignore lint/style/noNonNullAssertion: current checked in ternary condition
46
45
  return current;
47
46
  },
48
47
  }
@@ -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
+ }