@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.
- package/README.md +149 -0
- package/batch.test.ts +2 -2
- package/batch.ts +0 -1
- package/dist/batch.d.ts.map +1 -1
- package/dist/batch.js +0 -1
- package/dist/drain.d.ts +24 -0
- package/dist/drain.d.ts.map +1 -0
- package/dist/drain.js +33 -0
- package/dist/first.d.ts +28 -0
- package/dist/first.d.ts.map +1 -0
- package/dist/first.js +67 -0
- package/dist/for-each.d.ts.map +1 -1
- package/dist/for-each.js +12 -8
- package/dist/last.d.ts +29 -0
- package/dist/last.d.ts.map +1 -0
- package/dist/last.js +81 -0
- package/dist/mod.d.ts +6 -0
- package/dist/mod.d.ts.map +1 -1
- package/dist/mod.js +6 -0
- package/dist/subject.d.ts.map +1 -1
- package/dist/subject.js +0 -1
- 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/test-helpers/faucet.d.ts.map +1 -1
- package/dist/test-helpers/faucet.js +28 -24
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/drain.test.ts +52 -0
- package/drain.ts +35 -0
- package/first.test.ts +53 -0
- package/first.ts +74 -0
- package/for-each.ts +12 -8
- package/last.test.ts +65 -0
- package/last.ts +96 -0
- package/mod.ts +6 -0
- package/package.json +5 -4
- package/subject.ts +0 -1
- 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/test-helpers/faucet.test.ts +3 -3
- package/test-helpers/faucet.ts +28 -24
- package/tracker.test.ts +4 -4
- package/valve.test.ts +2 -2
package/README.md
CHANGED
|
@@ -165,6 +165,155 @@ function* example() {
|
|
|
165
165
|
}
|
|
166
166
|
```
|
|
167
167
|
|
|
168
|
+
### Drain
|
|
169
|
+
|
|
170
|
+
The `drain` helper exhausts a stream, discarding all yielded values, and returns
|
|
171
|
+
the close value. This is useful when you only care about the final result of a
|
|
172
|
+
stream, not the intermediate values.
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
import { drain } from "@effectionx/stream-helpers";
|
|
176
|
+
|
|
177
|
+
function* example() {
|
|
178
|
+
// Get the response from a request channel (ignoring any progress)
|
|
179
|
+
const channel = yield* transport.send(request);
|
|
180
|
+
const response = yield* drain(channel);
|
|
181
|
+
console.log(response); // The close value
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### First
|
|
186
|
+
|
|
187
|
+
The `first` helper returns the first value yielded by a stream, or `undefined`
|
|
188
|
+
if the stream closes without yielding any values. Use `first.expect()` to throw
|
|
189
|
+
an error instead of returning `undefined`.
|
|
190
|
+
|
|
191
|
+
```typescript
|
|
192
|
+
import { first } from "@effectionx/stream-helpers";
|
|
193
|
+
import { streamOf } from "@effectionx/stream-helpers";
|
|
194
|
+
|
|
195
|
+
function* example() {
|
|
196
|
+
const stream = streamOf([1, 2, 3]);
|
|
197
|
+
const value = yield* first(stream);
|
|
198
|
+
console.log(value); // 1
|
|
199
|
+
|
|
200
|
+
const empty = streamOf([]);
|
|
201
|
+
const none = yield* first(empty);
|
|
202
|
+
console.log(none); // undefined
|
|
203
|
+
|
|
204
|
+
// Use first.expect() to throw if stream is empty
|
|
205
|
+
const required = yield* first.expect(stream); // throws if empty
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Last
|
|
210
|
+
|
|
211
|
+
The `last` helper returns the last value yielded by a stream, or `undefined`
|
|
212
|
+
if the stream closes without yielding any values. It exhausts the entire stream
|
|
213
|
+
to find the last value. Use `last.expect()` to throw an error instead of
|
|
214
|
+
returning `undefined`.
|
|
215
|
+
|
|
216
|
+
```typescript
|
|
217
|
+
import { last } from "@effectionx/stream-helpers";
|
|
218
|
+
import { streamOf } from "@effectionx/stream-helpers";
|
|
219
|
+
|
|
220
|
+
function* example() {
|
|
221
|
+
const stream = streamOf([1, 2, 3]);
|
|
222
|
+
const value = yield* last(stream);
|
|
223
|
+
console.log(value); // 3
|
|
224
|
+
|
|
225
|
+
const empty = streamOf([]);
|
|
226
|
+
const none = yield* last(empty);
|
|
227
|
+
console.log(none); // undefined
|
|
228
|
+
|
|
229
|
+
// Use last.expect() to throw if stream is empty
|
|
230
|
+
const required = yield* last.expect(stream); // throws if empty
|
|
231
|
+
}
|
|
232
|
+
```
|
|
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
|
+
|
|
168
317
|
### ForEach
|
|
169
318
|
|
|
170
319
|
The `forEach` helper invokes a function for each item passing through a stream.
|
package/batch.test.ts
CHANGED
|
@@ -57,7 +57,7 @@ describe("batch", () => {
|
|
|
57
57
|
}, stream),
|
|
58
58
|
);
|
|
59
59
|
|
|
60
|
-
yield* sleep(
|
|
60
|
+
yield* sleep(0);
|
|
61
61
|
|
|
62
62
|
yield* faucet.pour(function* (send) {
|
|
63
63
|
for (let i = 1; i <= 10; i++) {
|
|
@@ -89,7 +89,7 @@ describe("batch", () => {
|
|
|
89
89
|
}, stream),
|
|
90
90
|
);
|
|
91
91
|
|
|
92
|
-
yield* sleep(
|
|
92
|
+
yield* sleep(0);
|
|
93
93
|
|
|
94
94
|
yield* faucet.pour([1, 2, 3, 4, 5, 6]);
|
|
95
95
|
|
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/drain.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Operation, Stream } from "effection";
|
|
2
|
+
/**
|
|
3
|
+
* Exhausts a stream, discarding all yielded values, and returns the close value.
|
|
4
|
+
*
|
|
5
|
+
* Use this when you only care about the final result of a stream, not the
|
|
6
|
+
* intermediate values. This is common for request/response patterns where
|
|
7
|
+
* the response is the close value and there may be no progress events.
|
|
8
|
+
*
|
|
9
|
+
* @template T - The type of items in the stream (discarded)
|
|
10
|
+
* @template TClose - The type of the close value returned when the stream ends
|
|
11
|
+
* @param stream - The stream to drain
|
|
12
|
+
* @returns The close value of the stream
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* import { drain } from "./drain.ts";
|
|
17
|
+
*
|
|
18
|
+
* // Get the response from a request channel (ignoring any progress)
|
|
19
|
+
* const channel = yield* transport.send(request);
|
|
20
|
+
* const response = yield* drain(channel);
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export declare function drain<T, TClose>(stream: Stream<T, TClose>): Operation<TClose>;
|
|
24
|
+
//# sourceMappingURL=drain.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drain.d.ts","sourceRoot":"","sources":["../drain.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAEnD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,CAW7E"}
|
package/dist/drain.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exhausts a stream, discarding all yielded values, and returns the close value.
|
|
3
|
+
*
|
|
4
|
+
* Use this when you only care about the final result of a stream, not the
|
|
5
|
+
* intermediate values. This is common for request/response patterns where
|
|
6
|
+
* the response is the close value and there may be no progress events.
|
|
7
|
+
*
|
|
8
|
+
* @template T - The type of items in the stream (discarded)
|
|
9
|
+
* @template TClose - The type of the close value returned when the stream ends
|
|
10
|
+
* @param stream - The stream to drain
|
|
11
|
+
* @returns The close value of the stream
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* import { drain } from "./drain.ts";
|
|
16
|
+
*
|
|
17
|
+
* // Get the response from a request channel (ignoring any progress)
|
|
18
|
+
* const channel = yield* transport.send(request);
|
|
19
|
+
* const response = yield* drain(channel);
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export function drain(stream) {
|
|
23
|
+
return {
|
|
24
|
+
*[Symbol.iterator]() {
|
|
25
|
+
const subscription = yield* stream;
|
|
26
|
+
let result = yield* subscription.next();
|
|
27
|
+
while (!result.done) {
|
|
28
|
+
result = yield* subscription.next();
|
|
29
|
+
}
|
|
30
|
+
return result.value;
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
}
|
package/dist/first.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Operation, Stream } from "effection";
|
|
2
|
+
/**
|
|
3
|
+
* Returns the first value yielded by a stream, or `undefined` if the stream
|
|
4
|
+
* closes without yielding any values.
|
|
5
|
+
*
|
|
6
|
+
* Use `first.expect()` if you want to throw an error when the stream is empty.
|
|
7
|
+
*
|
|
8
|
+
* @template T - The type of items in the stream
|
|
9
|
+
* @template TClose - The type of the close value (unused)
|
|
10
|
+
* @param stream - The stream to get the first value from
|
|
11
|
+
* @returns The first value yielded by the stream, or `undefined` if empty
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* import { first } from "./first.ts";
|
|
16
|
+
*
|
|
17
|
+
* const stream = streamOf([1, 2, 3]);
|
|
18
|
+
* const value = yield* first(stream); // returns 1
|
|
19
|
+
*
|
|
20
|
+
* const empty = streamOf([]);
|
|
21
|
+
* const value = yield* first(empty); // returns undefined
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare function first<T, TClose>(stream: Stream<T, TClose>): Operation<T | undefined>;
|
|
25
|
+
export declare namespace first {
|
|
26
|
+
var expect: <T, TClose>(stream: Stream<T, TClose>) => Operation<T>;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=first.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"first.d.ts","sourceRoot":"","sources":["../first.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAEnD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,KAAK,CAAC,CAAC,EAAE,MAAM,EAC7B,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,GACxB,SAAS,CAAC,CAAC,GAAG,SAAS,CAAC,CAW1B;yBAbe,KAAK;iBAoCe,CAAC,EAAE,MAAM,UACnC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,KACxB,SAAS,CAAC,CAAC,CAAC"}
|
package/dist/first.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns the first value yielded by a stream, or `undefined` if the stream
|
|
3
|
+
* closes without yielding any values.
|
|
4
|
+
*
|
|
5
|
+
* Use `first.expect()` if you want to throw an error when the stream is empty.
|
|
6
|
+
*
|
|
7
|
+
* @template T - The type of items in the stream
|
|
8
|
+
* @template TClose - The type of the close value (unused)
|
|
9
|
+
* @param stream - The stream to get the first value from
|
|
10
|
+
* @returns The first value yielded by the stream, or `undefined` if empty
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* import { first } from "./first.ts";
|
|
15
|
+
*
|
|
16
|
+
* const stream = streamOf([1, 2, 3]);
|
|
17
|
+
* const value = yield* first(stream); // returns 1
|
|
18
|
+
*
|
|
19
|
+
* const empty = streamOf([]);
|
|
20
|
+
* const value = yield* first(empty); // returns undefined
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export function first(stream) {
|
|
24
|
+
return {
|
|
25
|
+
*[Symbol.iterator]() {
|
|
26
|
+
const subscription = yield* stream;
|
|
27
|
+
const result = yield* subscription.next();
|
|
28
|
+
if (result.done) {
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
return result.value;
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Returns the first value yielded by a stream.
|
|
37
|
+
* Throws an error if the stream closes without yielding any values.
|
|
38
|
+
*
|
|
39
|
+
* @template T - The type of items in the stream
|
|
40
|
+
* @template TClose - The type of the close value (unused)
|
|
41
|
+
* @param stream - The stream to get the first value from
|
|
42
|
+
* @returns The first value yielded by the stream
|
|
43
|
+
* @throws Error if the stream closes without yielding any values
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```typescript
|
|
47
|
+
* import { first } from "./first.ts";
|
|
48
|
+
*
|
|
49
|
+
* const stream = streamOf([1, 2, 3]);
|
|
50
|
+
* const value = yield* first.expect(stream); // returns 1
|
|
51
|
+
*
|
|
52
|
+
* const empty = streamOf([]);
|
|
53
|
+
* const value = yield* first.expect(empty); // throws Error
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
first.expect = function expectFirst(stream) {
|
|
57
|
+
return {
|
|
58
|
+
*[Symbol.iterator]() {
|
|
59
|
+
const subscription = yield* stream;
|
|
60
|
+
const result = yield* subscription.next();
|
|
61
|
+
if (result.done) {
|
|
62
|
+
throw new Error("Stream closed without yielding any values");
|
|
63
|
+
}
|
|
64
|
+
return result.value;
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
};
|
package/dist/for-each.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"for-each.d.ts","sourceRoot":"","sources":["../for-each.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAEnD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,
|
|
1
|
+
{"version":3,"file":"for-each.d.ts","sourceRoot":"","sources":["../for-each.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAEnD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,EAC/B,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,SAAS,CAAC,IAAI,CAAC,EAChC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,GACxB,SAAS,CAAC,MAAM,CAAC,CAYnB"}
|
package/dist/for-each.js
CHANGED
|
@@ -22,12 +22,16 @@
|
|
|
22
22
|
* yield* stream.send(2);
|
|
23
23
|
* ```
|
|
24
24
|
*/
|
|
25
|
-
export function
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
25
|
+
export function forEach(fn, stream) {
|
|
26
|
+
return {
|
|
27
|
+
*[Symbol.iterator]() {
|
|
28
|
+
let subscription = yield* stream;
|
|
29
|
+
let next = yield* subscription.next();
|
|
30
|
+
while (!next.done) {
|
|
31
|
+
yield* fn(next.value);
|
|
32
|
+
next = yield* subscription.next();
|
|
33
|
+
}
|
|
34
|
+
return next.value;
|
|
35
|
+
},
|
|
36
|
+
};
|
|
33
37
|
}
|
package/dist/last.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Operation, Stream } from "effection";
|
|
2
|
+
/**
|
|
3
|
+
* Returns the last value yielded by a stream, or `undefined` if the stream
|
|
4
|
+
* closes without yielding any values.
|
|
5
|
+
*
|
|
6
|
+
* Exhausts the entire stream to find the last value.
|
|
7
|
+
* Use `last.expect()` if you want to throw an error when the stream is empty.
|
|
8
|
+
*
|
|
9
|
+
* @template T - The type of items in the stream
|
|
10
|
+
* @template TClose - The type of the close value (unused)
|
|
11
|
+
* @param stream - The stream to get the last value from
|
|
12
|
+
* @returns The last value yielded by the stream, or `undefined` if empty
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* import { last } from "./last.ts";
|
|
17
|
+
*
|
|
18
|
+
* const stream = streamOf([1, 2, 3]);
|
|
19
|
+
* const value = yield* last(stream); // returns 3
|
|
20
|
+
*
|
|
21
|
+
* const empty = streamOf([]);
|
|
22
|
+
* const value = yield* last(empty); // returns undefined
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export declare function last<T, TClose>(stream: Stream<T, TClose>): Operation<T | undefined>;
|
|
26
|
+
export declare namespace last {
|
|
27
|
+
var expect: <T, TClose>(stream: Stream<T, TClose>) => Operation<T>;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=last.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"last.d.ts","sourceRoot":"","sources":["../last.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAEnD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,IAAI,CAAC,CAAC,EAAE,MAAM,EAC5B,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,GACxB,SAAS,CAAC,CAAC,GAAG,SAAS,CAAC,CAqB1B;yBAvBe,IAAI;iBA+Cc,CAAC,EAAE,MAAM,UACjC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,KACxB,SAAS,CAAC,CAAC,CAAC"}
|
package/dist/last.js
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns the last value yielded by a stream, or `undefined` if the stream
|
|
3
|
+
* closes without yielding any values.
|
|
4
|
+
*
|
|
5
|
+
* Exhausts the entire stream to find the last value.
|
|
6
|
+
* Use `last.expect()` if you want to throw an error when the stream is empty.
|
|
7
|
+
*
|
|
8
|
+
* @template T - The type of items in the stream
|
|
9
|
+
* @template TClose - The type of the close value (unused)
|
|
10
|
+
* @param stream - The stream to get the last value from
|
|
11
|
+
* @returns The last value yielded by the stream, or `undefined` if empty
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* import { last } from "./last.ts";
|
|
16
|
+
*
|
|
17
|
+
* const stream = streamOf([1, 2, 3]);
|
|
18
|
+
* const value = yield* last(stream); // returns 3
|
|
19
|
+
*
|
|
20
|
+
* const empty = streamOf([]);
|
|
21
|
+
* const value = yield* last(empty); // returns undefined
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export function last(stream) {
|
|
25
|
+
return {
|
|
26
|
+
*[Symbol.iterator]() {
|
|
27
|
+
const subscription = yield* stream;
|
|
28
|
+
const first = yield* subscription.next();
|
|
29
|
+
if (first.done) {
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
let lastValue = first.value;
|
|
33
|
+
let result = yield* subscription.next();
|
|
34
|
+
while (!result.done) {
|
|
35
|
+
lastValue = result.value;
|
|
36
|
+
result = yield* subscription.next();
|
|
37
|
+
}
|
|
38
|
+
return lastValue;
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Returns the last value yielded by a stream.
|
|
44
|
+
* Exhausts the entire stream to find the last value.
|
|
45
|
+
* Throws an error if the stream closes without yielding any values.
|
|
46
|
+
*
|
|
47
|
+
* @template T - The type of items in the stream
|
|
48
|
+
* @template TClose - The type of the close value (unused)
|
|
49
|
+
* @param stream - The stream to get the last value from
|
|
50
|
+
* @returns The last value yielded by the stream
|
|
51
|
+
* @throws Error if the stream closes without yielding any values
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```typescript
|
|
55
|
+
* import { last } from "./last.ts";
|
|
56
|
+
*
|
|
57
|
+
* const stream = streamOf([1, 2, 3]);
|
|
58
|
+
* const value = yield* last.expect(stream); // returns 3
|
|
59
|
+
*
|
|
60
|
+
* const empty = streamOf([]);
|
|
61
|
+
* const value = yield* last.expect(empty); // throws Error
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
last.expect = function expectLast(stream) {
|
|
65
|
+
return {
|
|
66
|
+
*[Symbol.iterator]() {
|
|
67
|
+
const subscription = yield* stream;
|
|
68
|
+
const first = yield* subscription.next();
|
|
69
|
+
if (first.done) {
|
|
70
|
+
throw new Error("Stream closed without yielding any values");
|
|
71
|
+
}
|
|
72
|
+
let lastValue = first.value;
|
|
73
|
+
let result = yield* subscription.next();
|
|
74
|
+
while (!result.done) {
|
|
75
|
+
lastValue = result.value;
|
|
76
|
+
result = yield* subscription.next();
|
|
77
|
+
}
|
|
78
|
+
return lastValue;
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
};
|
package/dist/mod.d.ts
CHANGED
|
@@ -8,4 +8,10 @@ export * from "./subject.ts";
|
|
|
8
8
|
export * from "./lines.ts";
|
|
9
9
|
export * from "./stream-of.ts";
|
|
10
10
|
export * from "./reduce.ts";
|
|
11
|
+
export * from "./drain.ts";
|
|
12
|
+
export * from "./first.ts";
|
|
13
|
+
export * from "./last.ts";
|
|
14
|
+
export * from "./take.ts";
|
|
15
|
+
export * from "./take-while.ts";
|
|
16
|
+
export * from "./take-until.ts";
|
|
11
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"}
|
|
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
|
@@ -8,3 +8,9 @@ export * from "./subject.js";
|
|
|
8
8
|
export * from "./lines.js";
|
|
9
9
|
export * from "./stream-of.js";
|
|
10
10
|
export * from "./reduce.js";
|
|
11
|
+
export * from "./drain.js";
|
|
12
|
+
export * from "./first.js";
|
|
13
|
+
export * from "./last.js";
|
|
14
|
+
export * from "./take.js";
|
|
15
|
+
export * from "./take-while.js";
|
|
16
|
+
export * from "./take-until.js";
|
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,KAAK,CAAC,MAAM,EACzC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,KACtB,MAAM,CAAC,CAAC,EAAE,MAAM,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,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
|
@@ -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
|
+
}
|