documonster 0.20.2 → 0.21.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 +1 -1
- package/README_zh.md +1 -1
- package/THIRD_PARTY_NOTICES.md +34 -2
- package/dist/esm/modules/archive/core/byte-queue.js +2 -1
- package/dist/esm/modules/archive/unzip/stream.browser.js +6 -0
- package/dist/esm/modules/csv/parse/async.js +2 -1
- package/dist/esm/modules/excel/bridge/csv-bridge.js +1 -1
- package/dist/esm/modules/excel/core/xlsx-io.browser.js +5 -9
- package/dist/esm/modules/excel/core/xlsx-io.js +1 -3
- package/dist/esm/modules/excel/core/xlsx-stream.js +3 -1
- package/dist/esm/modules/excel/stream/workbook-reader.browser.js +10 -10
- package/dist/esm/modules/excel/stream/workbook-reader.js +30 -6
- package/dist/esm/modules/stream/browser/collector.js +3 -5
- package/dist/esm/modules/stream/browser/compose.js +13 -228
- package/dist/esm/modules/stream/browser/duplex-pair.js +71 -0
- package/dist/esm/modules/stream/browser/factories.js +35 -217
- package/dist/esm/modules/stream/browser/pipeline.js +43 -478
- package/dist/esm/modules/stream/browser/utils.js +21 -247
- package/dist/esm/modules/stream/browser/web.js +25 -0
- package/dist/esm/modules/stream/buffered-stream.js +8 -6
- package/dist/esm/modules/stream/core/factories.js +166 -0
- package/dist/esm/modules/stream/core/pipeline-api.js +32 -0
- package/dist/esm/modules/stream/core/sink-adapter.js +94 -24
- package/dist/esm/modules/stream/core/stream-helpers.js +160 -0
- package/dist/esm/modules/stream/core/utils.js +0 -23
- package/dist/esm/modules/stream/core/web-conversions.js +31 -0
- package/dist/esm/modules/stream/core/web-pipeline.js +90 -0
- package/dist/esm/modules/stream/index.base.js +2 -2
- package/dist/esm/modules/stream/index.browser.js +13 -19
- package/dist/esm/modules/stream/index.js +6 -10
- package/dist/esm/modules/stream/kernel/classes.js +618 -0
- package/dist/esm/modules/stream/kernel/compose-impl.js +225 -0
- package/dist/esm/modules/stream/kernel/destroy.js +255 -0
- package/dist/esm/modules/stream/kernel/duplexify.js +355 -0
- package/dist/esm/modules/stream/kernel/end-of-stream.js +212 -0
- package/dist/esm/modules/stream/kernel/errors.js +215 -0
- package/dist/esm/modules/stream/kernel/from.js +202 -0
- package/dist/esm/modules/stream/kernel/legacy.js +35 -0
- package/dist/esm/modules/stream/kernel/operators.js +285 -0
- package/dist/esm/modules/stream/kernel/pipeline-impl.js +561 -0
- package/dist/esm/modules/stream/kernel/readable-impl.js +963 -0
- package/dist/esm/modules/stream/kernel/state.js +253 -0
- package/dist/esm/modules/stream/kernel/stream-utils.js +212 -0
- package/dist/esm/modules/stream/kernel/web-adapters.js +584 -0
- package/dist/esm/modules/stream/kernel/writable.js +651 -0
- package/dist/esm/modules/stream/node/collector.js +7 -1
- package/dist/esm/modules/stream/node/compose.js +21 -206
- package/dist/esm/modules/stream/node/factories.js +34 -238
- package/dist/esm/modules/stream/node/pipeline.js +40 -94
- package/dist/esm/modules/stream/node/utils.js +15 -239
- package/dist/esm/modules/stream/node/web.js +27 -0
- package/dist/esm/modules/stream/pull-stream.js +15 -9
- package/dist/esm/modules/word/writer/streaming-writer.js +3 -0
- package/dist/iife/THIRD_PARTY_NOTICES.md +34 -2
- package/dist/iife/documonster.archive.iife.min.js +4 -4
- package/dist/iife/documonster.csv.iife.min.js +19 -19
- package/dist/iife/documonster.draw.iife.min.js +1 -1
- package/dist/iife/documonster.excel.iife.min.js +50 -50
- package/dist/iife/documonster.formula.iife.min.js +1 -1
- package/dist/iife/documonster.markdown.iife.min.js +1 -1
- package/dist/iife/documonster.mermaid.iife.min.js +1 -1
- package/dist/iife/documonster.pdf.iife.min.js +1 -1
- package/dist/iife/documonster.stream.iife.min.js +2 -2
- package/dist/iife/documonster.word.iife.min.js +60 -60
- package/dist/iife/documonster.xml.iife.min.js +1 -1
- package/dist/types/modules/excel/core/xlsx-io.browser.d.ts +5 -9
- package/dist/types/modules/excel/core/xlsx-io.d.ts +1 -3
- package/dist/types/modules/excel/core/xlsx-stream.d.ts +3 -2
- package/dist/types/modules/excel/stream/workbook-reader.browser.d.ts +2 -1
- package/dist/types/modules/excel/stream/workbook-reader.d.ts +2 -1
- package/dist/types/modules/stream/browser/collector.d.ts +1 -1
- package/dist/types/modules/stream/browser/compose.d.ts +14 -15
- package/dist/types/modules/stream/browser/duplex-pair.d.ts +10 -0
- package/dist/types/modules/stream/browser/factories.d.ts +22 -79
- package/dist/types/modules/stream/browser/pipeline.d.ts +8 -40
- package/dist/types/modules/stream/browser/utils.d.ts +6 -47
- package/dist/types/modules/stream/browser/web.d.ts +18 -0
- package/dist/types/modules/stream/core/add-abort-signal.d.ts +2 -1
- package/dist/types/modules/stream/core/consumers.d.ts +1 -1
- package/dist/types/modules/stream/core/event-utils.d.ts +2 -1
- package/dist/types/modules/stream/core/factories.d.ts +129 -0
- package/dist/types/modules/stream/core/pipeline-api.d.ts +10 -0
- package/dist/types/modules/stream/core/sink-adapter.d.ts +18 -1
- package/dist/types/modules/stream/core/stream-helpers.d.ts +76 -0
- package/dist/types/modules/stream/core/utils.d.ts +0 -9
- package/dist/types/modules/stream/core/web-conversions.d.ts +68 -0
- package/dist/types/modules/stream/core/web-pipeline.d.ts +27 -0
- package/dist/types/modules/stream/index.base.d.ts +6 -4
- package/dist/types/modules/stream/index.browser.d.ts +13 -14
- package/dist/types/modules/stream/index.d.ts +7 -10
- package/dist/types/modules/stream/kernel/classes.d.ts +220 -0
- package/dist/types/modules/stream/kernel/compose-impl.d.ts +10 -0
- package/dist/types/modules/stream/kernel/destroy.d.ts +21 -0
- package/dist/types/modules/stream/kernel/duplexify.d.ts +31 -0
- package/dist/types/modules/stream/kernel/end-of-stream.d.ts +28 -0
- package/dist/types/modules/stream/kernel/errors.d.ts +42 -0
- package/dist/types/modules/stream/kernel/from.d.ts +17 -0
- package/dist/types/modules/stream/kernel/legacy.d.ts +20 -0
- package/dist/types/modules/stream/kernel/operators.d.ts +44 -0
- package/dist/types/modules/stream/kernel/pipeline-impl.d.ts +32 -0
- package/dist/types/modules/stream/kernel/readable-impl.d.ts +34 -0
- package/dist/types/modules/stream/kernel/state.d.ts +223 -0
- package/dist/types/modules/stream/kernel/stream-utils.d.ts +34 -0
- package/dist/types/modules/stream/kernel/web-adapters.d.ts +65 -0
- package/dist/types/modules/stream/kernel/writable.d.ts +107 -0
- package/dist/types/modules/stream/node/collector.d.ts +7 -2
- package/dist/types/modules/stream/node/compose.d.ts +31 -5
- package/dist/types/modules/stream/node/factories.d.ts +22 -85
- package/dist/types/modules/stream/node/pipeline.d.ts +4 -15
- package/dist/types/modules/stream/node/utils.d.ts +9 -49
- package/dist/types/modules/stream/node/web.d.ts +18 -0
- package/dist/types/modules/stream/pull-stream.d.ts +2 -2
- package/dist/types/modules/stream/types.d.ts +24 -6
- package/package.json +5 -3
- package/dist/esm/modules/stream/browser/_lazy.js +0 -30
- package/dist/esm/modules/stream/browser/chunk-buffer.js +0 -223
- package/dist/esm/modules/stream/browser/duplex.js +0 -979
- package/dist/esm/modules/stream/browser/helpers.js +0 -44
- package/dist/esm/modules/stream/browser/microtask-context.js +0 -60
- package/dist/esm/modules/stream/browser/passthrough.js +0 -16
- package/dist/esm/modules/stream/browser/pipe-manager.js +0 -161
- package/dist/esm/modules/stream/browser/readable.js +0 -2208
- package/dist/esm/modules/stream/browser/transform.js +0 -1241
- package/dist/esm/modules/stream/browser/writable.js +0 -1316
- package/dist/esm/modules/stream/core/end-args.js +0 -24
- package/dist/esm/modules/stream/node/writable.js +0 -125
- package/dist/esm/modules/stream/utils.base.js +0 -126
- package/dist/esm/modules/stream/utils.browser.js +0 -80
- package/dist/esm/modules/stream/utils.js +0 -81
- package/dist/types/modules/stream/browser/_lazy.d.ts +0 -20
- package/dist/types/modules/stream/browser/chunk-buffer.d.ts +0 -61
- package/dist/types/modules/stream/browser/duplex.d.ts +0 -299
- package/dist/types/modules/stream/browser/helpers.d.ts +0 -13
- package/dist/types/modules/stream/browser/microtask-context.d.ts +0 -44
- package/dist/types/modules/stream/browser/passthrough.d.ts +0 -11
- package/dist/types/modules/stream/browser/pipe-manager.d.ts +0 -38
- package/dist/types/modules/stream/browser/readable.d.ts +0 -379
- package/dist/types/modules/stream/browser/transform.d.ts +0 -314
- package/dist/types/modules/stream/browser/writable.d.ts +0 -238
- package/dist/types/modules/stream/core/end-args.d.ts +0 -20
- package/dist/types/modules/stream/node/writable.d.ts +0 -53
- package/dist/types/modules/stream/utils.base.d.ts +0 -63
- package/dist/types/modules/stream/utils.browser.d.ts +0 -23
- package/dist/types/modules/stream/utils.d.ts +0 -24
|
@@ -1,257 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Browser Stream -
|
|
2
|
+
* Browser Stream - utilities
|
|
3
3
|
*/
|
|
4
|
-
import {
|
|
5
|
-
import { removeEmitterListener, addEmitterListener } from "./helpers.js";
|
|
6
|
-
import { pipeline, finished } from "./pipeline.js";
|
|
7
|
-
import { Readable } from "./readable.js";
|
|
8
|
-
import { Transform } from "./transform.js";
|
|
9
|
-
import { Writable } from "./writable.js";
|
|
4
|
+
import { finished, pipeline } from "./pipeline.js";
|
|
10
5
|
import { createAddAbortSignal } from "../core/add-abort-signal.js";
|
|
11
|
-
import { toStreamBytes } from "../core/binary-chunk.js";
|
|
12
6
|
import { createConsumers } from "../core/consumers.js";
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
// =============================================================================
|
|
20
|
-
/** Convert a stream to a promise that resolves when finished */
|
|
7
|
+
import { streamToString, streamToUint8Array } from "../core/stream-helpers.js";
|
|
8
|
+
import { createIsDuplex, createIsStream, createIsTransform } from "../core/type-guards.js";
|
|
9
|
+
import { Duplex, Readable, Transform } from "../kernel/classes.js";
|
|
10
|
+
import { Writable } from "../kernel/writable.js";
|
|
11
|
+
export { drainStream, isDisturbed, isReadable, isWritable, streamToBuffer, streamToString, streamToUint8Array } from "../core/stream-helpers.js";
|
|
12
|
+
/** Resolve when a stream has finished. */
|
|
21
13
|
export const streamToPromise = finished;
|
|
22
|
-
/** Copy from a readable stream to a writable stream */
|
|
14
|
+
/** Copy from a readable stream to a writable stream. */
|
|
23
15
|
export const copyStream = pipeline;
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
*/
|
|
28
|
-
export
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Alias for streamToUint8Array (Node.js compatibility)
|
|
34
|
-
*/
|
|
35
|
-
export async function streamToBuffer(stream) {
|
|
36
|
-
return streamToUint8Array(stream);
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Collect all data from a readable stream into a string
|
|
40
|
-
*/
|
|
41
|
-
export async function streamToString(stream, encoding) {
|
|
42
|
-
const iterable = toReadableAsyncIterable(stream, "streamToString");
|
|
43
|
-
const decoder = createTextDecoder(encoding);
|
|
44
|
-
let text = "";
|
|
45
|
-
for await (const chunk of iterable) {
|
|
46
|
-
const bytes = toStreamBytes(chunk);
|
|
47
|
-
if (!bytes) {
|
|
48
|
-
throw new UnsupportedStreamTypeError("streamToString", typeof chunk);
|
|
49
|
-
}
|
|
50
|
-
text += decoder.decode(bytes, { stream: true });
|
|
51
|
-
}
|
|
52
|
-
text += decoder.decode();
|
|
53
|
-
return text;
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Drain a stream (consume all data without processing)
|
|
57
|
-
*/
|
|
58
|
-
export async function drainStream(stream) {
|
|
59
|
-
const iterable = toReadableAsyncIterable(stream, "drainStream");
|
|
60
|
-
for await (const _chunk of iterable) {
|
|
61
|
-
// Consume data
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
// =============================================================================
|
|
65
|
-
// Type Guards
|
|
66
|
-
// =============================================================================
|
|
67
|
-
/** Check if an object is a transform stream */
|
|
68
|
-
export const isTransform = createIsTransform(Transform);
|
|
69
|
-
/** Check if an object is a duplex stream */
|
|
70
|
-
export const isDuplex = createIsDuplex(Duplex, Transform);
|
|
71
|
-
/** Check if an object is any kind of stream */
|
|
72
|
-
export const isStream = createIsStream(Readable, Writable);
|
|
73
|
-
// =============================================================================
|
|
74
|
-
// Additional Utility Functions (Node.js Compatibility)
|
|
75
|
-
// =============================================================================
|
|
76
|
-
/** Add abort signal handling to any stream */
|
|
77
|
-
export const addAbortSignal = createAddAbortSignal({
|
|
16
|
+
export const isTransform =
|
|
17
|
+
/* @__PURE__ */ createIsTransform(Transform);
|
|
18
|
+
export const isDuplex =
|
|
19
|
+
/* @__PURE__ */ createIsDuplex(Duplex);
|
|
20
|
+
export const isStream =
|
|
21
|
+
/* @__PURE__ */ createIsStream(Readable, Writable);
|
|
22
|
+
export const addAbortSignal = /* @__PURE__ */ createAddAbortSignal({
|
|
78
23
|
add(emitter, event, listener) {
|
|
79
|
-
|
|
24
|
+
emitter.once?.(event, listener);
|
|
80
25
|
},
|
|
81
|
-
remove
|
|
82
|
-
|
|
83
|
-
// =============================================================================
|
|
84
|
-
// Stream State Inspection Functions
|
|
85
|
-
// =============================================================================
|
|
86
|
-
/**
|
|
87
|
-
* Check if a readable stream has been disturbed (read from or cancelled).
|
|
88
|
-
* Matches Node.js native: readableDidRead || readableAborted.
|
|
89
|
-
* For Web ReadableStreams, returns `locked` (matches Node.js behaviour).
|
|
90
|
-
*/
|
|
91
|
-
export function isDisturbed(stream) {
|
|
92
|
-
if (stream instanceof Readable) {
|
|
93
|
-
return Readable.isDisturbed(stream);
|
|
26
|
+
remove(emitter, event, listener) {
|
|
27
|
+
(emitter.off ?? emitter.removeListener)?.call(emitter, event, listener);
|
|
94
28
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}
|
|
98
|
-
// Web ReadableStream: `locked` is the closest indicator of disturbance
|
|
99
|
-
// (a reader has been acquired). Matches the Node.js isDisturbed check.
|
|
100
|
-
if (stream?.locked !== undefined) {
|
|
101
|
-
return !!stream.locked;
|
|
102
|
-
}
|
|
103
|
-
const s = stream;
|
|
104
|
-
return !!(s?.readableDidRead || s?._didRead || s?.readableAborted);
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* Check if an object is a readable stream that is still in a readable state.
|
|
108
|
-
* Returns false for destroyed or ended/finished streams (matches Node.js behavior).
|
|
109
|
-
*/
|
|
110
|
-
export function isReadable(stream) {
|
|
111
|
-
if (stream == null) {
|
|
112
|
-
return false;
|
|
113
|
-
}
|
|
114
|
-
const s = stream;
|
|
115
|
-
// Check if destroyed
|
|
116
|
-
if (s.destroyed) {
|
|
117
|
-
return false;
|
|
118
|
-
}
|
|
119
|
-
// Must be a readable stream type
|
|
120
|
-
if (!(stream instanceof Readable || stream instanceof Transform || stream instanceof Duplex)) {
|
|
121
|
-
if (!(typeof s.read === "function" && typeof s.pipe === "function")) {
|
|
122
|
-
return false;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
// Check if reading has finished (readableEnded or equivalent)
|
|
126
|
-
if (s.readableEnded === true) {
|
|
127
|
-
return false;
|
|
128
|
-
}
|
|
129
|
-
return true;
|
|
130
|
-
}
|
|
131
|
-
/**
|
|
132
|
-
* Check if an object is a writable stream that is still in a writable state.
|
|
133
|
-
* Returns false for destroyed or ended/finished streams (matches Node.js behavior).
|
|
134
|
-
*/
|
|
135
|
-
export function isWritable(stream) {
|
|
136
|
-
if (stream == null) {
|
|
137
|
-
return false;
|
|
138
|
-
}
|
|
139
|
-
const s = stream;
|
|
140
|
-
// Check if destroyed
|
|
141
|
-
if (s.destroyed) {
|
|
142
|
-
return false;
|
|
143
|
-
}
|
|
144
|
-
// Must be a writable stream type
|
|
145
|
-
if (!(stream instanceof Writable || stream instanceof Transform || stream instanceof Duplex)) {
|
|
146
|
-
if (!(typeof s.write === "function" && typeof s.end === "function")) {
|
|
147
|
-
return false;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
// Check if writing has ended (writableEnded or equivalent)
|
|
151
|
-
if (s.writableEnded === true) {
|
|
152
|
-
return false;
|
|
153
|
-
}
|
|
154
|
-
return true;
|
|
155
|
-
}
|
|
156
|
-
// =============================================================================
|
|
157
|
-
// Duplex Pair
|
|
158
|
-
// =============================================================================
|
|
159
|
-
/**
|
|
160
|
-
* Create a pair of connected Duplex streams
|
|
161
|
-
* Data written to one stream can be read from the other
|
|
162
|
-
*/
|
|
163
|
-
export function duplexPair(options) {
|
|
164
|
-
const objectMode = options?.readableObjectMode ?? options?.writableObjectMode ?? options?.objectMode ?? false;
|
|
165
|
-
const highWaterMark = options?.readableHighWaterMark ??
|
|
166
|
-
options?.writableHighWaterMark ??
|
|
167
|
-
options?.highWaterMark ??
|
|
168
|
-
getDefaultHighWaterMark(objectMode);
|
|
169
|
-
const duplexOpts = {
|
|
170
|
-
readableHighWaterMark: options?.readableHighWaterMark ?? highWaterMark,
|
|
171
|
-
writableHighWaterMark: options?.writableHighWaterMark ?? highWaterMark,
|
|
172
|
-
readableObjectMode: options?.readableObjectMode ?? objectMode,
|
|
173
|
-
writableObjectMode: options?.writableObjectMode ?? objectMode,
|
|
174
|
-
allowHalfOpen: options?.allowHalfOpen
|
|
175
|
-
};
|
|
176
|
-
// Holder object allows both streams to reference each other via closure
|
|
177
|
-
// while satisfying the `const` constraint (each variable is assigned once).
|
|
178
|
-
const pair = {};
|
|
179
|
-
const stream1 = new Duplex({
|
|
180
|
-
...duplexOpts,
|
|
181
|
-
read() {
|
|
182
|
-
// Data will be pushed from stream2's write()
|
|
183
|
-
},
|
|
184
|
-
write(chunk, _encoding, callback) {
|
|
185
|
-
// Push to peer; if peer signals backpressure, defer callback until drain.
|
|
186
|
-
if (!pair.s2.push(chunk)) {
|
|
187
|
-
pair.s2.once("drain", () => callback());
|
|
188
|
-
}
|
|
189
|
-
else {
|
|
190
|
-
callback();
|
|
191
|
-
}
|
|
192
|
-
},
|
|
193
|
-
final(callback) {
|
|
194
|
-
pair.s2.push(null);
|
|
195
|
-
callback();
|
|
196
|
-
}
|
|
197
|
-
});
|
|
198
|
-
const stream2 = new Duplex({
|
|
199
|
-
...duplexOpts,
|
|
200
|
-
read() {
|
|
201
|
-
// Data will be pushed from stream1's write()
|
|
202
|
-
},
|
|
203
|
-
write(chunk, _encoding, callback) {
|
|
204
|
-
// Push to peer; if peer signals backpressure, defer callback until drain.
|
|
205
|
-
if (!stream1.push(chunk)) {
|
|
206
|
-
stream1.once("drain", () => callback());
|
|
207
|
-
}
|
|
208
|
-
else {
|
|
209
|
-
callback();
|
|
210
|
-
}
|
|
211
|
-
},
|
|
212
|
-
final(callback) {
|
|
213
|
-
stream1.push(null);
|
|
214
|
-
callback();
|
|
215
|
-
}
|
|
216
|
-
});
|
|
217
|
-
pair.s1 = stream1;
|
|
218
|
-
pair.s2 = stream2;
|
|
219
|
-
return [stream1, stream2];
|
|
220
|
-
}
|
|
221
|
-
// =============================================================================
|
|
222
|
-
// Private Helpers
|
|
223
|
-
// =============================================================================
|
|
224
|
-
// Helper function to collect stream chunks with total length tracking
|
|
225
|
-
async function collectStreamChunks(stream) {
|
|
226
|
-
const chunks = [];
|
|
227
|
-
let totalLength = 0;
|
|
228
|
-
const iterable = toReadableAsyncIterable(stream, "collectStreamChunks");
|
|
229
|
-
for await (const chunk of iterable) {
|
|
230
|
-
const bytes = toStreamBytes(chunk);
|
|
231
|
-
if (!bytes) {
|
|
232
|
-
throw new UnsupportedStreamTypeError("streamToBuffer", typeof chunk);
|
|
233
|
-
}
|
|
234
|
-
chunks.push(bytes);
|
|
235
|
-
totalLength += bytes.length;
|
|
236
|
-
}
|
|
237
|
-
return [chunks, totalLength];
|
|
238
|
-
}
|
|
239
|
-
function toReadableAsyncIterable(stream, name) {
|
|
240
|
-
if (isReadableStream(stream)) {
|
|
241
|
-
// Boundary: `isReadableStream` erases the Web stream's element type; the
|
|
242
|
-
// caller-supplied T is reasserted for the wrapped Readable.
|
|
243
|
-
return Readable.fromWeb(stream);
|
|
244
|
-
}
|
|
245
|
-
if (isAsyncIterable(stream)) {
|
|
246
|
-
return stream;
|
|
247
|
-
}
|
|
248
|
-
throw new UnsupportedStreamTypeError(name, typeof stream);
|
|
249
|
-
}
|
|
250
|
-
// =============================================================================
|
|
251
|
-
// Stream Consumers (like stream.consumers in Node.js)
|
|
252
|
-
// =============================================================================
|
|
253
|
-
export const consumers = createConsumers({ streamToUint8Array, streamToString });
|
|
254
|
-
// =============================================================================
|
|
255
|
-
// Promises API (like stream/promises in Node.js)
|
|
256
|
-
// =============================================================================
|
|
29
|
+
});
|
|
30
|
+
export const consumers = /* @__PURE__ */ createConsumers({ streamToUint8Array, streamToString });
|
|
257
31
|
export const promises = { pipeline, finished };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser Stream - Web Streams conversions and `toWritable`
|
|
3
|
+
*
|
|
4
|
+
* Its own module so that converting a Writable does not keep the Readable
|
|
5
|
+
* side of the kernel in a bundle.
|
|
6
|
+
*/
|
|
7
|
+
import { makeReadableFromWeb, makeWritableFromWeb } from "../core/web-conversions.js";
|
|
8
|
+
import { Readable } from "../kernel/classes.js";
|
|
9
|
+
import { isWritableStream } from "../kernel/stream-utils.js";
|
|
10
|
+
import { Writable } from "../kernel/writable.js";
|
|
11
|
+
/** A Web `ReadableStream` as a Readable, with the module's guarantees; see `web-conversions`. */
|
|
12
|
+
export const readableFromWeb = /* @__PURE__ */ makeReadableFromWeb(Readable);
|
|
13
|
+
/** A Web `WritableStream` as a Writable, with the module's guarantees; see `web-conversions`. */
|
|
14
|
+
export const writableFromWeb = /* @__PURE__ */ makeWritableFromWeb(Writable);
|
|
15
|
+
export { readableToWeb, writableToWeb } from "../core/web-conversions.js";
|
|
16
|
+
/**
|
|
17
|
+
* Normalize a user-provided writable into one this module can drive: a Web
|
|
18
|
+
* `WritableStream` is adapted, anything Node-like is used as is.
|
|
19
|
+
*/
|
|
20
|
+
export function toWritable(stream) {
|
|
21
|
+
if (isWritableStream(stream)) {
|
|
22
|
+
return writableFromWeb(stream);
|
|
23
|
+
}
|
|
24
|
+
return stream;
|
|
25
|
+
}
|
|
@@ -202,7 +202,8 @@ export class BufferedStream extends EventEmitter {
|
|
|
202
202
|
while (this._bufferReadIndex < this._buffers.length) {
|
|
203
203
|
const buf = this._buffers[this._bufferReadIndex];
|
|
204
204
|
if (buf.isEOD) {
|
|
205
|
-
|
|
205
|
+
// Drop the reference so a consumed batch can be collected before compaction.
|
|
206
|
+
this._buffers[this._bufferReadIndex++] = undefined;
|
|
206
207
|
continue;
|
|
207
208
|
}
|
|
208
209
|
// Track length reduction
|
|
@@ -210,7 +211,7 @@ export class BufferedStream extends EventEmitter {
|
|
|
210
211
|
const data = buf.read(size);
|
|
211
212
|
this._totalLength -= beforeLen - buf.length;
|
|
212
213
|
if (buf.isEOD) {
|
|
213
|
-
this._bufferReadIndex
|
|
214
|
+
this._buffers[this._bufferReadIndex++] = undefined;
|
|
214
215
|
}
|
|
215
216
|
// Reset/compact buffer queue occasionally
|
|
216
217
|
if (this._bufferReadIndex === this._buffers.length) {
|
|
@@ -258,10 +259,7 @@ export class BufferedStream extends EventEmitter {
|
|
|
258
259
|
// Allocate exactly once, then copy remaining chunks/buffers.
|
|
259
260
|
const out = new Uint8Array(this._totalLength);
|
|
260
261
|
let offset = 0;
|
|
261
|
-
|
|
262
|
-
const chunk = this._chunks[i];
|
|
263
|
-
offset += chunk.copy(out, offset, 0, chunk.length);
|
|
264
|
-
}
|
|
262
|
+
// Older data first: what was already moved into buffers, then pending chunks.
|
|
265
263
|
for (let i = this._bufferReadIndex; i < this._buffers.length; i++) {
|
|
266
264
|
const buf = this._buffers[i];
|
|
267
265
|
if (buf.isEOD) {
|
|
@@ -271,6 +269,10 @@ export class BufferedStream extends EventEmitter {
|
|
|
271
269
|
out.set(view, offset);
|
|
272
270
|
offset += view.length;
|
|
273
271
|
}
|
|
272
|
+
for (let i = this._chunkReadIndex; i < this._chunks.length; i++) {
|
|
273
|
+
const chunk = this._chunks[i];
|
|
274
|
+
offset += chunk.copy(out, offset, 0, chunk.length);
|
|
275
|
+
}
|
|
274
276
|
// Reset internal state — data has been consumed.
|
|
275
277
|
this._chunks = [];
|
|
276
278
|
this._chunkReadIndex = 0;
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stream factory functions shared by the Node and browser entry points.
|
|
3
|
+
*
|
|
4
|
+
* The bodies are identical on both platforms; only the stream classes differ,
|
|
5
|
+
* so each entry point builds them with its own.
|
|
6
|
+
*/
|
|
7
|
+
import { BufferedStream } from "../buffered-stream.js";
|
|
8
|
+
import { PullStream } from "../pull-stream.js";
|
|
9
|
+
import { stringToUint8Array } from "../../../utils/binary.js";
|
|
10
|
+
/**
|
|
11
|
+
* Deliver a value that may be a promise to a Node-style callback; `undefined`
|
|
12
|
+
* means "nothing to push".
|
|
13
|
+
*
|
|
14
|
+
* A promise is recognised as `await` recognises one — anything with a `then`
|
|
15
|
+
* method — not with `instanceof Promise`, which is false for a promise from
|
|
16
|
+
* another realm (an iframe, a `vm` context) and for any other thenable, and
|
|
17
|
+
* pushed the promise itself as the chunk. `Promise.resolve` then adopts it as
|
|
18
|
+
* `await` would, so a thenable that calls back twice or throws still settles
|
|
19
|
+
* once. A plain value keeps the synchronous path.
|
|
20
|
+
*/
|
|
21
|
+
function settle(run, callback) {
|
|
22
|
+
let result;
|
|
23
|
+
try {
|
|
24
|
+
result = run();
|
|
25
|
+
}
|
|
26
|
+
catch (err) {
|
|
27
|
+
callback(err);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
if (typeof result?.then === "function") {
|
|
31
|
+
Promise.resolve(result).then(data => (data !== undefined ? callback(null, data) : callback()), err => callback(err));
|
|
32
|
+
}
|
|
33
|
+
else if (result !== undefined) {
|
|
34
|
+
callback(null, result);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
callback();
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function emptyRead() {
|
|
41
|
+
this.push(null);
|
|
42
|
+
}
|
|
43
|
+
function nullWrite(_chunk, _encoding, callback) {
|
|
44
|
+
callback();
|
|
45
|
+
}
|
|
46
|
+
/** `createPullStream`; platform-independent. */
|
|
47
|
+
export function createPullStream(options) {
|
|
48
|
+
return new PullStream(options);
|
|
49
|
+
}
|
|
50
|
+
/** `createBufferedStream`; platform-independent. */
|
|
51
|
+
export function createBufferedStream(options) {
|
|
52
|
+
return new BufferedStream(options);
|
|
53
|
+
}
|
|
54
|
+
// One maker per factory, each called once per platform with the one class it
|
|
55
|
+
// needs. A shared object of every class would make each factory keep all of
|
|
56
|
+
// them — the whole Readable/compose kernel behind a lone `createWritable`.
|
|
57
|
+
export function makeCreateReadable(Readable) {
|
|
58
|
+
return options => new Readable(options);
|
|
59
|
+
}
|
|
60
|
+
export function makeCreateReadableFromAsyncIterable(Readable) {
|
|
61
|
+
return (iterable, options) => Readable.from(iterable, { ...options, objectMode: options?.objectMode ?? true });
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* `undefined` entries are skipped: a stream's end-of-data signal is a nullish
|
|
65
|
+
* push, so there is no in-band way to carry an undefined chunk, while `0`, `""`
|
|
66
|
+
* and `false` are ordinary values that must survive.
|
|
67
|
+
*/
|
|
68
|
+
export function makeCreateReadableFromArray(Readable) {
|
|
69
|
+
return (data, options) => {
|
|
70
|
+
let index = 0;
|
|
71
|
+
return new Readable({
|
|
72
|
+
...options,
|
|
73
|
+
objectMode: options?.objectMode ?? true,
|
|
74
|
+
read() {
|
|
75
|
+
while (index < data.length) {
|
|
76
|
+
const chunk = data[index++];
|
|
77
|
+
if (chunk === undefined) {
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
if (!this.push(chunk)) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
this.push(null);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
export function makeCreateReadableFromGenerator(Readable) {
|
|
90
|
+
return (generator, options) => Readable.from(generator(), { ...options, objectMode: options?.objectMode ?? true });
|
|
91
|
+
}
|
|
92
|
+
export function makeCreateReadableFromPromise(Readable) {
|
|
93
|
+
return (promise, options) => {
|
|
94
|
+
const readable = new Readable({
|
|
95
|
+
...options,
|
|
96
|
+
objectMode: options?.objectMode ?? true,
|
|
97
|
+
read() { }
|
|
98
|
+
});
|
|
99
|
+
// Adopted as `await` would: a promise from another realm or any thenable
|
|
100
|
+
// works, one that calls back twice settles once, and a `then` that throws
|
|
101
|
+
// fails the stream rather than the call.
|
|
102
|
+
Promise.resolve()
|
|
103
|
+
.then(() => promise)
|
|
104
|
+
.then(value => {
|
|
105
|
+
readable.push(value);
|
|
106
|
+
readable.push(null);
|
|
107
|
+
}, err => readable.destroy(err));
|
|
108
|
+
return readable;
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
export function makeCreateEmptyReadable(Readable) {
|
|
112
|
+
return options => new Readable({ ...options, read: emptyRead });
|
|
113
|
+
}
|
|
114
|
+
export function makeCreateWritable(Writable) {
|
|
115
|
+
return options => new Writable(options);
|
|
116
|
+
}
|
|
117
|
+
export function makeCreateNullWritable(Writable) {
|
|
118
|
+
return options => new Writable({ ...options, write: nullWrite });
|
|
119
|
+
}
|
|
120
|
+
/** The shorthand `transformFn` returns its result; `undefined` pushes nothing. */
|
|
121
|
+
export function makeCreateTransform(Transform) {
|
|
122
|
+
return (transformFn, options) => {
|
|
123
|
+
const flush = options?.flush;
|
|
124
|
+
return new Transform({
|
|
125
|
+
...options,
|
|
126
|
+
transform(chunk, encoding, callback) {
|
|
127
|
+
settle(() => transformFn(chunk, encoding), callback);
|
|
128
|
+
},
|
|
129
|
+
flush: flush
|
|
130
|
+
? (callback) => settle(flush, callback)
|
|
131
|
+
: undefined
|
|
132
|
+
});
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
export function makeCreatePassThrough(PassThrough) {
|
|
136
|
+
return options => new PassThrough(options);
|
|
137
|
+
}
|
|
138
|
+
export function makeCreateDuplex(Duplex) {
|
|
139
|
+
return options => new Duplex(options);
|
|
140
|
+
}
|
|
141
|
+
export function makeFromBytes(Readable) {
|
|
142
|
+
return data => new Readable({
|
|
143
|
+
read() {
|
|
144
|
+
this.push(data);
|
|
145
|
+
this.push(null);
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
export function makeFromString(Readable) {
|
|
150
|
+
const fromBytes = makeFromBytes(Readable);
|
|
151
|
+
return str => fromBytes(stringToUint8Array(str));
|
|
152
|
+
}
|
|
153
|
+
export function makeFromJSON(Readable) {
|
|
154
|
+
const fromString = makeFromString(Readable);
|
|
155
|
+
return data => fromString(JSON.stringify(data));
|
|
156
|
+
}
|
|
157
|
+
export function makeTransform(Transform) {
|
|
158
|
+
const createTransform = makeCreateTransform(Transform);
|
|
159
|
+
return fn => createTransform(fn);
|
|
160
|
+
}
|
|
161
|
+
export function makeFilter(Transform) {
|
|
162
|
+
const createTransform = makeCreateTransform(Transform);
|
|
163
|
+
return (predicate) => createTransform(async (chunk) => ((await predicate(chunk)) ? chunk : undefined), {
|
|
164
|
+
objectMode: true
|
|
165
|
+
});
|
|
166
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The module's `pipeline()` calling convention, shared by both entry points:
|
|
3
|
+
* stages, then optional `{ signal, end }` options, then an optional callback;
|
|
4
|
+
* a promise is returned either way. Each entry supplies how to run the stages.
|
|
5
|
+
*/
|
|
6
|
+
import { isPipelineOptions } from "./options.js";
|
|
7
|
+
export function createPipeline(run) {
|
|
8
|
+
return function pipeline(...args) {
|
|
9
|
+
let stages = args;
|
|
10
|
+
let options;
|
|
11
|
+
let callback;
|
|
12
|
+
if (typeof stages[stages.length - 1] === "function") {
|
|
13
|
+
// A trailing function is always the completion callback.
|
|
14
|
+
callback = stages[stages.length - 1];
|
|
15
|
+
stages = stages.slice(0, -1);
|
|
16
|
+
}
|
|
17
|
+
if (isPipelineOptions(stages[stages.length - 1])) {
|
|
18
|
+
options = stages[stages.length - 1];
|
|
19
|
+
stages = stages.slice(0, -1);
|
|
20
|
+
}
|
|
21
|
+
const promise = stages.length < 2
|
|
22
|
+
? Promise.reject(new Error("Pipeline requires at least 2 streams"))
|
|
23
|
+
: new Promise((resolve, reject) => {
|
|
24
|
+
run(stages, options).then(resolve, reject);
|
|
25
|
+
});
|
|
26
|
+
if (callback) {
|
|
27
|
+
const cb = callback;
|
|
28
|
+
promise.then(() => cb(), err => cb(err));
|
|
29
|
+
}
|
|
30
|
+
return promise;
|
|
31
|
+
};
|
|
32
|
+
}
|