@effectionx/stream-helpers 0.7.1 → 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.
Files changed (53) hide show
  1. package/README.md +149 -0
  2. package/batch.test.ts +2 -2
  3. package/batch.ts +0 -1
  4. package/dist/batch.d.ts.map +1 -1
  5. package/dist/batch.js +0 -1
  6. package/dist/drain.d.ts +24 -0
  7. package/dist/drain.d.ts.map +1 -0
  8. package/dist/drain.js +33 -0
  9. package/dist/first.d.ts +28 -0
  10. package/dist/first.d.ts.map +1 -0
  11. package/dist/first.js +67 -0
  12. package/dist/for-each.d.ts.map +1 -1
  13. package/dist/for-each.js +12 -8
  14. package/dist/last.d.ts +29 -0
  15. package/dist/last.d.ts.map +1 -0
  16. package/dist/last.js +81 -0
  17. package/dist/mod.d.ts +6 -0
  18. package/dist/mod.d.ts.map +1 -1
  19. package/dist/mod.js +6 -0
  20. package/dist/subject.d.ts.map +1 -1
  21. package/dist/subject.js +0 -1
  22. package/dist/take-until.d.ts +46 -0
  23. package/dist/take-until.d.ts.map +1 -0
  24. package/dist/take-until.js +68 -0
  25. package/dist/take-while.d.ts +41 -0
  26. package/dist/take-while.d.ts.map +1 -0
  27. package/dist/take-while.js +64 -0
  28. package/dist/take.d.ts +36 -0
  29. package/dist/take.d.ts.map +1 -0
  30. package/dist/take.js +59 -0
  31. package/dist/test-helpers/faucet.d.ts.map +1 -1
  32. package/dist/test-helpers/faucet.js +28 -24
  33. package/dist/tsconfig.tsbuildinfo +1 -1
  34. package/drain.test.ts +52 -0
  35. package/drain.ts +35 -0
  36. package/first.test.ts +53 -0
  37. package/first.ts +74 -0
  38. package/for-each.ts +12 -8
  39. package/last.test.ts +65 -0
  40. package/last.ts +96 -0
  41. package/mod.ts +6 -0
  42. package/package.json +5 -4
  43. package/subject.ts +0 -1
  44. package/take-until.test.ts +113 -0
  45. package/take-until.ts +76 -0
  46. package/take-while.test.ts +89 -0
  47. package/take-while.ts +74 -0
  48. package/take.test.ts +83 -0
  49. package/take.ts +67 -0
  50. package/test-helpers/faucet.test.ts +3 -3
  51. package/test-helpers/faucet.ts +28 -24
  52. package/tracker.test.ts +4 -4
  53. package/valve.test.ts +2 -2
package/take.ts ADDED
@@ -0,0 +1,67 @@
1
+ import type { Stream } from "effection";
2
+
3
+ /**
4
+ * Creates a stream transformer that yields the first `n` values from the
5
+ * source stream, then closes with the last taken value.
6
+ *
7
+ * If the source stream closes before yielding `n` values, the resulting
8
+ * stream closes with the source's close value.
9
+ *
10
+ * @template T - The type of items in the stream
11
+ * @template TClose - The type of the close value
12
+ * @param n - The number of values to take
13
+ * @returns A stream transformer that yields at most `n` values
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * import { take, streamOf } from "@effectionx/stream-helpers";
18
+ *
19
+ * const stream = streamOf([1, 2, 3, 4, 5]);
20
+ * // yields 1, 2, then closes with 3
21
+ * const limited = take(3)(stream);
22
+ * ```
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * import { take, map } from "@effectionx/stream-helpers";
27
+ * import { pipe } from "remeda";
28
+ *
29
+ * const limited = pipe(
30
+ * source,
31
+ * map(function* (x) { return x * 2; }),
32
+ * take(5),
33
+ * );
34
+ * ```
35
+ */
36
+ export function take<T>(
37
+ n: number,
38
+ ): <TClose>(stream: Stream<T, TClose>) => Stream<T, T | TClose> {
39
+ return <TClose>(stream: Stream<T, TClose>): Stream<T, T | TClose> => ({
40
+ *[Symbol.iterator]() {
41
+ const subscription = yield* stream;
42
+ let count = 0;
43
+
44
+ return {
45
+ *next() {
46
+ if (count >= n) {
47
+ // Should not happen if used correctly, but handle gracefully
48
+ return { done: true, value: undefined as unknown as T | TClose };
49
+ }
50
+
51
+ const result = yield* subscription.next();
52
+ if (result.done) {
53
+ return result;
54
+ }
55
+
56
+ count++;
57
+ if (count >= n) {
58
+ // This is the nth value, return it and mark as done
59
+ return { done: true, value: result.value };
60
+ }
61
+
62
+ return result;
63
+ },
64
+ };
65
+ },
66
+ });
67
+ }
@@ -19,7 +19,7 @@ describe("useFaucet", () => {
19
19
  });
20
20
 
21
21
  yield* spawn(function* () {
22
- yield* sleep(1);
22
+ yield* sleep(0);
23
23
  // Pour an array of items
24
24
  yield* faucet.pour([1, 2, 3]);
25
25
  });
@@ -71,7 +71,7 @@ describe("useFaucet", () => {
71
71
 
72
72
  // Pour using a generator function
73
73
  yield* spawn(function* () {
74
- yield* sleep(1);
74
+ yield* sleep(0);
75
75
  yield* faucet.pour(function* (send) {
76
76
  yield* send(1);
77
77
  yield* sleep(10);
@@ -100,7 +100,7 @@ describe("useFaucet", () => {
100
100
 
101
101
  // Start pouring with a generator
102
102
  yield* spawn(function* () {
103
- yield* sleep(1);
103
+ yield* sleep(0);
104
104
  yield* faucet.pour(function* (send) {
105
105
  yield* send(1);
106
106
  yield* sleep(10);
@@ -1,5 +1,5 @@
1
- import { createChannel, type Operation, type Stream } from "effection";
2
1
  import { createBooleanSignal, is } from "@effectionx/signals";
2
+ import { type Operation, type Stream, createChannel } from "effection";
3
3
 
4
4
  /**
5
5
  * Interface of the stream returned by `useFaucet`.
@@ -80,30 +80,34 @@ export interface FaucetOptions {
80
80
  * @param options.open - Whether the faucet is open.
81
81
  * @returns stream of items coming from the faucet
82
82
  */
83
- export function* useFaucet<T>(options: FaucetOptions): Operation<Faucet<T>> {
84
- let signal = createChannel<T, never>();
85
- let open = yield* createBooleanSignal(options.open);
86
-
83
+ export function useFaucet<T>(options: FaucetOptions): Operation<Faucet<T>> {
87
84
  return {
88
- [Symbol.iterator]: signal[Symbol.iterator],
89
- *pour(items) {
90
- if (Array.isArray(items)) {
91
- for (let i of items) {
92
- yield* is(open, (open) => open);
93
- yield* signal.send(i);
94
- }
95
- } else {
96
- yield* items(function* (item) {
97
- yield* is(open, (open) => open);
98
- yield* signal.send(item);
99
- });
100
- }
101
- },
102
- close() {
103
- open.set(false);
104
- },
105
- open() {
106
- open.set(true);
85
+ *[Symbol.iterator]() {
86
+ let signal = createChannel<T, never>();
87
+ let open = yield* createBooleanSignal(options.open);
88
+
89
+ return {
90
+ [Symbol.iterator]: signal[Symbol.iterator],
91
+ *pour(items) {
92
+ if (Array.isArray(items)) {
93
+ for (let i of items) {
94
+ yield* is(open, (open) => open);
95
+ yield* signal.send(i);
96
+ }
97
+ } else {
98
+ yield* items(function* (item) {
99
+ yield* is(open, (open) => open);
100
+ yield* signal.send(item);
101
+ });
102
+ }
103
+ },
104
+ close() {
105
+ open.set(false);
106
+ },
107
+ open() {
108
+ open.set(true);
109
+ },
110
+ };
107
111
  },
108
112
  };
109
113
  }
package/tracker.test.ts CHANGED
@@ -33,13 +33,13 @@ describe("tracker", () => {
33
33
  }
34
34
  });
35
35
 
36
- yield* sleep(1);
36
+ yield* sleep(0);
37
37
 
38
38
  yield* faucet.pour(function* (send) {
39
39
  yield* send(1);
40
- yield* sleep(1);
40
+ yield* sleep(0);
41
41
  yield* send(2);
42
- yield* sleep(1);
42
+ yield* sleep(0);
43
43
  yield* send(3);
44
44
  });
45
45
 
@@ -75,7 +75,7 @@ describe("tracker", () => {
75
75
  }
76
76
  });
77
77
 
78
- yield* sleep(1);
78
+ yield* sleep(0);
79
79
 
80
80
  yield* faucet.pour(function* (send) {
81
81
  yield* send(1);
package/valve.test.ts CHANGED
@@ -33,12 +33,12 @@ describe("valve", () => {
33
33
  yield* spawn(function* () {
34
34
  for (const value of yield* each(stream(faucet))) {
35
35
  values.push(value);
36
- yield* sleep(1);
36
+ yield* sleep(0);
37
37
  yield* each.next();
38
38
  }
39
39
  });
40
40
 
41
- yield* sleep(1);
41
+ yield* sleep(0);
42
42
 
43
43
  yield* faucet.pour([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
44
44