@anabranch/fs 0.1.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/LICENSE +21 -0
- package/README.md +45 -0
- package/esm/_dnt.polyfills.d.ts +7 -0
- package/esm/_dnt.polyfills.d.ts.map +1 -0
- package/esm/_dnt.polyfills.js +1 -0
- package/esm/anabranch/index.d.ts +44 -0
- package/esm/anabranch/index.d.ts.map +1 -0
- package/esm/anabranch/index.js +41 -0
- package/esm/anabranch/streams/channel.d.ts +15 -0
- package/esm/anabranch/streams/channel.d.ts.map +1 -0
- package/esm/anabranch/streams/channel.js +122 -0
- package/esm/anabranch/streams/source.d.ts +68 -0
- package/esm/anabranch/streams/source.d.ts.map +1 -0
- package/esm/anabranch/streams/source.js +72 -0
- package/esm/anabranch/streams/stream.d.ts +431 -0
- package/esm/anabranch/streams/stream.d.ts.map +1 -0
- package/esm/anabranch/streams/stream.js +625 -0
- package/esm/anabranch/streams/task.d.ts +117 -0
- package/esm/anabranch/streams/task.d.ts.map +1 -0
- package/esm/anabranch/streams/task.js +416 -0
- package/esm/anabranch/streams/util.d.ts +33 -0
- package/esm/anabranch/streams/util.d.ts.map +1 -0
- package/esm/anabranch/streams/util.js +18 -0
- package/esm/fs/dir.d.ts +17 -0
- package/esm/fs/dir.d.ts.map +1 -0
- package/esm/fs/dir.js +90 -0
- package/esm/fs/errors.d.ts +64 -0
- package/esm/fs/errors.d.ts.map +1 -0
- package/esm/fs/errors.js +125 -0
- package/esm/fs/glob_match.d.ts +15 -0
- package/esm/fs/glob_match.d.ts.map +1 -0
- package/esm/fs/glob_match.js +73 -0
- package/esm/fs/index.d.ts +38 -0
- package/esm/fs/index.d.ts.map +1 -0
- package/esm/fs/index.js +31 -0
- package/esm/fs/read.d.ts +22 -0
- package/esm/fs/read.d.ts.map +1 -0
- package/esm/fs/read.js +75 -0
- package/esm/fs/types.d.ts +67 -0
- package/esm/fs/types.d.ts.map +1 -0
- package/esm/fs/types.js +1 -0
- package/esm/fs/watch.d.ts +17 -0
- package/esm/fs/watch.d.ts.map +1 -0
- package/esm/fs/watch.js +37 -0
- package/esm/fs/write.d.ts +16 -0
- package/esm/fs/write.d.ts.map +1 -0
- package/esm/fs/write.js +42 -0
- package/esm/package.json +3 -0
- package/package.json +24 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Frodi Karlsson
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# @anabranch/fs
|
|
2
|
+
|
|
3
|
+
Streaming file-system utilities for the anabranch ecosystem. Multi-value
|
|
4
|
+
operations return a `Source` for streaming; single-value operations return a
|
|
5
|
+
`Task` for composable error handling.
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { glob, readLines } from "@anabranch/fs";
|
|
11
|
+
|
|
12
|
+
const { successes, errors } = await glob("./src", "**/*.ts")
|
|
13
|
+
.flatMap(async (entry) => {
|
|
14
|
+
const lines = await readLines(entry.path)
|
|
15
|
+
.filter((line) => line.includes("TODO"))
|
|
16
|
+
.map((line) => ({ path: entry.path, line }))
|
|
17
|
+
.collect();
|
|
18
|
+
return lines;
|
|
19
|
+
})
|
|
20
|
+
.partition();
|
|
21
|
+
|
|
22
|
+
console.log("TODOs found:", successes.length);
|
|
23
|
+
for (const error of errors) {
|
|
24
|
+
console.error("Failed:", error);
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Installation
|
|
29
|
+
|
|
30
|
+
**Deno (JSR)**
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
import { glob } from "jsr:@anabranch/fs";
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**Node / Bun (npm)**
|
|
37
|
+
|
|
38
|
+
```sh
|
|
39
|
+
npm install @anabranch/fs
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## API reference
|
|
43
|
+
|
|
44
|
+
See [generated documentation](https://frodi-karlsson.github.io/anabranch/fs) for
|
|
45
|
+
full API details.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_dnt.polyfills.d.ts","sourceRoot":"","sources":["../src/_dnt.polyfills.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,KAAK;QACb,KAAK,CAAC,EAAE,OAAO,CAAC;KACjB;CACF;AAED,OAAO,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anabranch is a TypeScript library for error-tolerant async streams.
|
|
3
|
+
*
|
|
4
|
+
* Instead of throwing on the first error, it collects errors alongside
|
|
5
|
+
* successful values so you can process a stream to completion and deal with
|
|
6
|
+
* failures at the end — or not at all.
|
|
7
|
+
*
|
|
8
|
+
* The entry point is {@link Source}. Once you have a stream, chain operations
|
|
9
|
+
* like {@link Stream.map map}, {@link Stream.filter filter},
|
|
10
|
+
* {@link Stream.flatMap flatMap}, and {@link Stream.fold fold} to transform it,
|
|
11
|
+
* then consume it with {@link Stream.collect collect} or
|
|
12
|
+
* {@link Stream.partition partition}.
|
|
13
|
+
*
|
|
14
|
+
* @example Fetch a list of URLs concurrently, collect results and failures separately
|
|
15
|
+
* ```ts
|
|
16
|
+
* import { Source } from "anabranch";
|
|
17
|
+
*
|
|
18
|
+
* const { successes, errors } = await Source.from<string, Error>(
|
|
19
|
+
* async function* () {
|
|
20
|
+
* yield "https://example.com/1";
|
|
21
|
+
* yield "https://example.com/2";
|
|
22
|
+
* yield "https://example.com/3";
|
|
23
|
+
* },
|
|
24
|
+
* )
|
|
25
|
+
* .withConcurrency(3)
|
|
26
|
+
* .map(async (url) => {
|
|
27
|
+
* const res = await fetch(url);
|
|
28
|
+
* if (!res.ok) throw new Error(`HTTP ${res.status} for ${url}`);
|
|
29
|
+
* return res.json();
|
|
30
|
+
* })
|
|
31
|
+
* .partition();
|
|
32
|
+
*
|
|
33
|
+
* console.log(`${successes.length} succeeded, ${errors.length} failed`);
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* @module
|
|
37
|
+
*/
|
|
38
|
+
export { Source } from "./streams/source.js";
|
|
39
|
+
export { Task } from "./streams/task.js";
|
|
40
|
+
export { Channel } from "./streams/channel.js";
|
|
41
|
+
export type { Stream } from "./streams/stream.js";
|
|
42
|
+
export { AggregateError } from "./streams/util.js";
|
|
43
|
+
export type { ErrorResult, Promisable, Result, SuccessResult, } from "./streams/util.js";
|
|
44
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/anabranch/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,YAAY,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,YAAY,EACV,WAAW,EACX,UAAU,EACV,MAAM,EACN,aAAa,GACd,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anabranch is a TypeScript library for error-tolerant async streams.
|
|
3
|
+
*
|
|
4
|
+
* Instead of throwing on the first error, it collects errors alongside
|
|
5
|
+
* successful values so you can process a stream to completion and deal with
|
|
6
|
+
* failures at the end — or not at all.
|
|
7
|
+
*
|
|
8
|
+
* The entry point is {@link Source}. Once you have a stream, chain operations
|
|
9
|
+
* like {@link Stream.map map}, {@link Stream.filter filter},
|
|
10
|
+
* {@link Stream.flatMap flatMap}, and {@link Stream.fold fold} to transform it,
|
|
11
|
+
* then consume it with {@link Stream.collect collect} or
|
|
12
|
+
* {@link Stream.partition partition}.
|
|
13
|
+
*
|
|
14
|
+
* @example Fetch a list of URLs concurrently, collect results and failures separately
|
|
15
|
+
* ```ts
|
|
16
|
+
* import { Source } from "anabranch";
|
|
17
|
+
*
|
|
18
|
+
* const { successes, errors } = await Source.from<string, Error>(
|
|
19
|
+
* async function* () {
|
|
20
|
+
* yield "https://example.com/1";
|
|
21
|
+
* yield "https://example.com/2";
|
|
22
|
+
* yield "https://example.com/3";
|
|
23
|
+
* },
|
|
24
|
+
* )
|
|
25
|
+
* .withConcurrency(3)
|
|
26
|
+
* .map(async (url) => {
|
|
27
|
+
* const res = await fetch(url);
|
|
28
|
+
* if (!res.ok) throw new Error(`HTTP ${res.status} for ${url}`);
|
|
29
|
+
* return res.json();
|
|
30
|
+
* })
|
|
31
|
+
* .partition();
|
|
32
|
+
*
|
|
33
|
+
* console.log(`${successes.length} succeeded, ${errors.length} failed`);
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* @module
|
|
37
|
+
*/
|
|
38
|
+
export { Source } from "./streams/source.js";
|
|
39
|
+
export { Task } from "./streams/task.js";
|
|
40
|
+
export { Channel } from "./streams/channel.js";
|
|
41
|
+
export { AggregateError } from "./streams/util.js";
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { _StreamImpl } from "./stream.js";
|
|
2
|
+
interface ChannelOptions<T> {
|
|
3
|
+
bufferSize?: number;
|
|
4
|
+
onDrop?: (value: T) => void;
|
|
5
|
+
onClose?: () => void;
|
|
6
|
+
}
|
|
7
|
+
export declare class Channel<T, E = never> extends _StreamImpl<T, E> {
|
|
8
|
+
private sourceImpl;
|
|
9
|
+
constructor(options?: ChannelOptions<T>);
|
|
10
|
+
send(value: T): void;
|
|
11
|
+
fail(error: E): void;
|
|
12
|
+
close(): void;
|
|
13
|
+
}
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=channel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../../../src/anabranch/streams/channel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG1C,UAAU,cAAc,CAAC,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAgFD,qBAAa,OAAO,CAAC,CAAC,EAAE,CAAC,GAAG,KAAK,CAAE,SAAQ,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC;IAC1D,OAAO,CAAC,UAAU,CAAsB;gBAE5B,OAAO,GAAE,cAAc,CAAC,CAAC,CAAM;IAM3C,IAAI,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI;IAIpB,IAAI,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI;IAIpB,KAAK,IAAI,IAAI;CAGd"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { _StreamImpl } from "./stream.js";
|
|
2
|
+
class ChannelSource {
|
|
3
|
+
constructor(options = {}) {
|
|
4
|
+
Object.defineProperty(this, "queue", {
|
|
5
|
+
enumerable: true,
|
|
6
|
+
configurable: true,
|
|
7
|
+
writable: true,
|
|
8
|
+
value: []
|
|
9
|
+
});
|
|
10
|
+
Object.defineProperty(this, "closed", {
|
|
11
|
+
enumerable: true,
|
|
12
|
+
configurable: true,
|
|
13
|
+
writable: true,
|
|
14
|
+
value: false
|
|
15
|
+
});
|
|
16
|
+
Object.defineProperty(this, "consumers", {
|
|
17
|
+
enumerable: true,
|
|
18
|
+
configurable: true,
|
|
19
|
+
writable: true,
|
|
20
|
+
value: []
|
|
21
|
+
});
|
|
22
|
+
Object.defineProperty(this, "bufferSize", {
|
|
23
|
+
enumerable: true,
|
|
24
|
+
configurable: true,
|
|
25
|
+
writable: true,
|
|
26
|
+
value: void 0
|
|
27
|
+
});
|
|
28
|
+
Object.defineProperty(this, "onDrop", {
|
|
29
|
+
enumerable: true,
|
|
30
|
+
configurable: true,
|
|
31
|
+
writable: true,
|
|
32
|
+
value: void 0
|
|
33
|
+
});
|
|
34
|
+
Object.defineProperty(this, "onClose", {
|
|
35
|
+
enumerable: true,
|
|
36
|
+
configurable: true,
|
|
37
|
+
writable: true,
|
|
38
|
+
value: void 0
|
|
39
|
+
});
|
|
40
|
+
this.bufferSize = Number.isFinite(options.bufferSize)
|
|
41
|
+
? Math.max(1, options.bufferSize)
|
|
42
|
+
: Infinity;
|
|
43
|
+
this.onDrop = options.onDrop;
|
|
44
|
+
this.onClose = options.onClose;
|
|
45
|
+
}
|
|
46
|
+
send(value) {
|
|
47
|
+
if (this.closed) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (this.queue.length >= this.bufferSize && this.bufferSize !== Infinity) {
|
|
51
|
+
this.onDrop?.(value);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
this.queue.push({ type: "success", value });
|
|
55
|
+
this.wake();
|
|
56
|
+
}
|
|
57
|
+
fail(error) {
|
|
58
|
+
if (this.closed) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
this.queue.push({ type: "error", error });
|
|
62
|
+
this.wake();
|
|
63
|
+
}
|
|
64
|
+
close() {
|
|
65
|
+
if (this.closed) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
this.closed = true;
|
|
69
|
+
this.wake();
|
|
70
|
+
}
|
|
71
|
+
wake() {
|
|
72
|
+
while (this.consumers.length > 0) {
|
|
73
|
+
const consumer = this.consumers.shift();
|
|
74
|
+
if (consumer)
|
|
75
|
+
consumer();
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
async *generator() {
|
|
79
|
+
try {
|
|
80
|
+
while (true) {
|
|
81
|
+
while (this.queue.length > 0) {
|
|
82
|
+
yield this.queue.shift();
|
|
83
|
+
}
|
|
84
|
+
if (this.closed && this.queue.length === 0) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (this.queue.length === 0) {
|
|
88
|
+
await new Promise((resolve) => {
|
|
89
|
+
this.consumers.push(resolve);
|
|
90
|
+
});
|
|
91
|
+
if (this.queue.length > 0)
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
finally {
|
|
97
|
+
this.onClose?.();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
export class Channel extends _StreamImpl {
|
|
102
|
+
constructor(options = {}) {
|
|
103
|
+
const sourceImpl = new ChannelSource(options);
|
|
104
|
+
super(() => sourceImpl.generator(), Infinity, Infinity);
|
|
105
|
+
Object.defineProperty(this, "sourceImpl", {
|
|
106
|
+
enumerable: true,
|
|
107
|
+
configurable: true,
|
|
108
|
+
writable: true,
|
|
109
|
+
value: void 0
|
|
110
|
+
});
|
|
111
|
+
this.sourceImpl = sourceImpl;
|
|
112
|
+
}
|
|
113
|
+
send(value) {
|
|
114
|
+
this.sourceImpl.send(value);
|
|
115
|
+
}
|
|
116
|
+
fail(error) {
|
|
117
|
+
this.sourceImpl.fail(error);
|
|
118
|
+
}
|
|
119
|
+
close() {
|
|
120
|
+
this.sourceImpl.close();
|
|
121
|
+
}
|
|
122
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { _StreamImpl } from "./stream.js";
|
|
2
|
+
/**
|
|
3
|
+
* The entry point for creating a {@link Stream}. Wraps an async generator so
|
|
4
|
+
* that yielded values become success results and any thrown error becomes a
|
|
5
|
+
* single error result.
|
|
6
|
+
*
|
|
7
|
+
* Use {@link Source.from} to create a source from an existing `AsyncIterable`
|
|
8
|
+
* or generator function. Use {@link Source.withConcurrency} and
|
|
9
|
+
* {@link Source.withBufferSize} to configure parallel execution.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* import { Source } from "anabranch";
|
|
14
|
+
*
|
|
15
|
+
* const stream = Source.from<number, Error>(async function* () {
|
|
16
|
+
* yield 1;
|
|
17
|
+
* yield 2;
|
|
18
|
+
* yield 3;
|
|
19
|
+
* });
|
|
20
|
+
*
|
|
21
|
+
* const results = await stream.collect();
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare class Source<T, E> extends _StreamImpl<T, E> {
|
|
25
|
+
private readonly rawSource;
|
|
26
|
+
/**
|
|
27
|
+
* @param source An async generator function. Each yielded value becomes a
|
|
28
|
+
* success result; any thrown error becomes an error result and terminates
|
|
29
|
+
* the source.
|
|
30
|
+
* @param concurrency Maximum number of concurrent operations. Defaults to `Infinity`.
|
|
31
|
+
* @param bufferSize Maximum number of buffered results before backpressure is applied. Defaults to `Infinity`.
|
|
32
|
+
*/
|
|
33
|
+
private constructor();
|
|
34
|
+
/**
|
|
35
|
+
* Creates a {@link Source} from an existing `AsyncIterable` or async
|
|
36
|
+
* generator function. Each value emitted becomes a success result; any
|
|
37
|
+
* thrown error becomes an error result.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```ts
|
|
41
|
+
* import { Source } from "anabranch";
|
|
42
|
+
*
|
|
43
|
+
* // From a generator function
|
|
44
|
+
* const stream = Source.from<number, Error>(async function* () {
|
|
45
|
+
* yield 1;
|
|
46
|
+
* yield 2;
|
|
47
|
+
* });
|
|
48
|
+
*
|
|
49
|
+
* // From an AsyncIterable
|
|
50
|
+
* async function* generate() {
|
|
51
|
+
* yield 1;
|
|
52
|
+
* yield 2;
|
|
53
|
+
* }
|
|
54
|
+
* const stream2 = Source.from<number, Error>(generate());
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
static from<T, E>(source: AsyncIterable<T>): Source<T, E>;
|
|
58
|
+
static from<T, E>(fn: () => AsyncGenerator<T>): Source<T, E>;
|
|
59
|
+
/**
|
|
60
|
+
* Sets the maximum number of concurrent operations for the stream.
|
|
61
|
+
*/
|
|
62
|
+
withConcurrency(n: number): Source<T, E>;
|
|
63
|
+
/**
|
|
64
|
+
* Sets the maximum number of buffered results before backpressure is applied to the stream. If the buffer is full, the stream will pause until there is space in the buffer for new results.
|
|
65
|
+
*/
|
|
66
|
+
withBufferSize(n: number): Source<T, E>;
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=source.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"source.d.ts","sourceRoot":"","sources":["../../../src/anabranch/streams/source.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG1C;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBAAa,MAAM,CAAC,CAAC,EAAE,CAAC,CAAE,SAAQ,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC;IACjD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA0B;IAEpD;;;;;;OAMG;IACH,OAAO;IAmBP;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;IACzD,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;IAc5D;;OAEG;IACH,eAAe,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;IAIxC;;OAEG;IACH,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;CAGxC"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { _StreamImpl } from "./stream.js";
|
|
2
|
+
/**
|
|
3
|
+
* The entry point for creating a {@link Stream}. Wraps an async generator so
|
|
4
|
+
* that yielded values become success results and any thrown error becomes a
|
|
5
|
+
* single error result.
|
|
6
|
+
*
|
|
7
|
+
* Use {@link Source.from} to create a source from an existing `AsyncIterable`
|
|
8
|
+
* or generator function. Use {@link Source.withConcurrency} and
|
|
9
|
+
* {@link Source.withBufferSize} to configure parallel execution.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* import { Source } from "anabranch";
|
|
14
|
+
*
|
|
15
|
+
* const stream = Source.from<number, Error>(async function* () {
|
|
16
|
+
* yield 1;
|
|
17
|
+
* yield 2;
|
|
18
|
+
* yield 3;
|
|
19
|
+
* });
|
|
20
|
+
*
|
|
21
|
+
* const results = await stream.collect();
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export class Source extends _StreamImpl {
|
|
25
|
+
/**
|
|
26
|
+
* @param source An async generator function. Each yielded value becomes a
|
|
27
|
+
* success result; any thrown error becomes an error result and terminates
|
|
28
|
+
* the source.
|
|
29
|
+
* @param concurrency Maximum number of concurrent operations. Defaults to `Infinity`.
|
|
30
|
+
* @param bufferSize Maximum number of buffered results before backpressure is applied. Defaults to `Infinity`.
|
|
31
|
+
*/
|
|
32
|
+
constructor(source, concurrency = Infinity, bufferSize = Infinity) {
|
|
33
|
+
const wrappedSource = async function* () {
|
|
34
|
+
try {
|
|
35
|
+
for await (const value of source()) {
|
|
36
|
+
yield { type: "success", value };
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
yield { type: "error", error: error };
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
super(wrappedSource, concurrency, bufferSize);
|
|
44
|
+
Object.defineProperty(this, "rawSource", {
|
|
45
|
+
enumerable: true,
|
|
46
|
+
configurable: true,
|
|
47
|
+
writable: true,
|
|
48
|
+
value: void 0
|
|
49
|
+
});
|
|
50
|
+
this.rawSource = source;
|
|
51
|
+
}
|
|
52
|
+
static from(source) {
|
|
53
|
+
if (typeof source === "function") {
|
|
54
|
+
return new Source(source);
|
|
55
|
+
}
|
|
56
|
+
return new Source(async function* () {
|
|
57
|
+
yield* source;
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Sets the maximum number of concurrent operations for the stream.
|
|
62
|
+
*/
|
|
63
|
+
withConcurrency(n) {
|
|
64
|
+
return new Source(this.rawSource, n, this.bufferSize);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Sets the maximum number of buffered results before backpressure is applied to the stream. If the buffer is full, the stream will pause until there is space in the buffer for new results.
|
|
68
|
+
*/
|
|
69
|
+
withBufferSize(n) {
|
|
70
|
+
return new Source(this.rawSource, this.concurrency, n);
|
|
71
|
+
}
|
|
72
|
+
}
|