@yume-chan/adb 0.0.15 → 0.0.17
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/CHANGELOG.json +33 -0
- package/CHANGELOG.md +18 -1
- package/LICENSE +21 -21
- package/README.md +247 -247
- package/esm/adb.d.ts +15 -3
- package/esm/adb.d.ts.map +1 -1
- package/esm/adb.js +18 -6
- package/esm/adb.js.map +1 -1
- package/esm/auth.d.ts.map +1 -1
- package/esm/auth.js.map +1 -1
- package/esm/backend.d.ts +2 -2
- package/esm/backend.d.ts.map +1 -1
- package/esm/commands/base.d.ts.map +1 -1
- package/esm/commands/base.js.map +1 -1
- package/esm/commands/framebuffer.d.ts +17 -1
- package/esm/commands/framebuffer.d.ts.map +1 -1
- package/esm/commands/framebuffer.js +4 -15
- package/esm/commands/framebuffer.js.map +1 -1
- package/esm/commands/install.d.ts +2 -2
- package/esm/commands/install.d.ts.map +1 -1
- package/esm/commands/install.js +3 -2
- package/esm/commands/install.js.map +1 -1
- package/esm/commands/power.d.ts +1 -1
- package/esm/commands/power.js +1 -1
- package/esm/commands/reverse.d.ts +3 -3
- package/esm/commands/reverse.d.ts.map +1 -1
- package/esm/commands/reverse.js +9 -9
- package/esm/commands/reverse.js.map +1 -1
- package/esm/commands/subprocess/command.d.ts +52 -0
- package/esm/commands/subprocess/command.d.ts.map +1 -0
- package/esm/commands/subprocess/command.js +83 -0
- package/esm/commands/subprocess/command.js.map +1 -0
- package/esm/commands/subprocess/index.d.ts +1 -53
- package/esm/commands/subprocess/index.d.ts.map +1 -1
- package/esm/commands/subprocess/index.js +1 -85
- package/esm/commands/subprocess/index.js.map +1 -1
- package/esm/commands/subprocess/protocols/none.d.ts +5 -4
- package/esm/commands/subprocess/protocols/none.d.ts.map +1 -1
- package/esm/commands/subprocess/protocols/none.js +11 -8
- package/esm/commands/subprocess/protocols/none.js.map +1 -1
- package/esm/commands/subprocess/protocols/shell.d.ts +4 -4
- package/esm/commands/subprocess/protocols/shell.d.ts.map +1 -1
- package/esm/commands/subprocess/protocols/shell.js +6 -6
- package/esm/commands/subprocess/protocols/shell.js.map +1 -1
- package/esm/commands/subprocess/protocols/types.d.ts +7 -7
- package/esm/commands/subprocess/protocols/types.d.ts.map +1 -1
- package/esm/commands/sync/index.d.ts +1 -1
- package/esm/commands/sync/index.d.ts.map +1 -1
- package/esm/commands/sync/index.js +1 -1
- package/esm/commands/sync/index.js.map +1 -1
- package/esm/commands/sync/list.d.ts +2 -2
- package/esm/commands/sync/list.d.ts.map +1 -1
- package/esm/commands/sync/list.js +15 -43
- package/esm/commands/sync/list.js.map +1 -1
- package/esm/commands/sync/pull.d.ts +3 -2
- package/esm/commands/sync/pull.d.ts.map +1 -1
- package/esm/commands/sync/pull.js +15 -17
- package/esm/commands/sync/pull.js.map +1 -1
- package/esm/commands/sync/push.d.ts +2 -2
- package/esm/commands/sync/push.d.ts.map +1 -1
- package/esm/commands/sync/push.js +2 -5
- package/esm/commands/sync/push.js.map +1 -1
- package/esm/commands/sync/request.d.ts +1 -1
- package/esm/commands/sync/request.d.ts.map +1 -1
- package/esm/commands/sync/request.js +1 -1
- package/esm/commands/sync/request.js.map +1 -1
- package/esm/commands/sync/response.d.ts +4 -9
- package/esm/commands/sync/response.d.ts.map +1 -1
- package/esm/commands/sync/response.js +32 -23
- package/esm/commands/sync/response.js.map +1 -1
- package/esm/commands/sync/stat.d.ts +3 -3
- package/esm/commands/sync/stat.d.ts.map +1 -1
- package/esm/commands/sync/stat.js +13 -30
- package/esm/commands/sync/stat.js.map +1 -1
- package/esm/commands/sync/sync.d.ts +2 -2
- package/esm/commands/sync/sync.d.ts.map +1 -1
- package/esm/commands/sync/sync.js +7 -5
- package/esm/commands/sync/sync.js.map +1 -1
- package/esm/crypto.js +1 -1
- package/esm/crypto.js.map +1 -1
- package/esm/index.d.ts +0 -1
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +0 -1
- package/esm/index.js.map +1 -1
- package/esm/packet.d.ts +1 -1
- package/esm/packet.d.ts.map +1 -1
- package/esm/packet.js +1 -1
- package/esm/packet.js.map +1 -1
- package/esm/socket/dispatcher.d.ts +11 -3
- package/esm/socket/dispatcher.d.ts.map +1 -1
- package/esm/socket/dispatcher.js +19 -11
- package/esm/socket/dispatcher.js.map +1 -1
- package/esm/socket/index.d.ts +1 -1
- package/esm/socket/index.d.ts.map +1 -1
- package/esm/socket/index.js +1 -1
- package/esm/socket/index.js.map +1 -1
- package/esm/socket/socket.d.ts +9 -4
- package/esm/socket/socket.d.ts.map +1 -1
- package/esm/socket/socket.js +20 -10
- package/esm/socket/socket.js.map +1 -1
- package/esm/utils/base64.d.ts +23 -0
- package/esm/utils/base64.d.ts.map +1 -1
- package/esm/utils/base64.js +6 -0
- package/esm/utils/base64.js.map +1 -1
- package/package.json +13 -14
- package/src/adb.ts +285 -273
- package/src/auth.ts +174 -173
- package/src/backend.ts +12 -11
- package/src/commands/base.ts +12 -11
- package/src/commands/framebuffer.ts +78 -73
- package/src/commands/index.ts +8 -8
- package/src/commands/install.ts +32 -30
- package/src/commands/power.ts +54 -54
- package/src/commands/reverse.ts +141 -140
- package/src/commands/subprocess/command.ts +131 -0
- package/src/commands/subprocess/index.ts +3 -139
- package/src/commands/subprocess/protocols/none.ts +73 -68
- package/src/commands/subprocess/protocols/shell.ts +191 -190
- package/src/commands/subprocess/protocols/types.ts +60 -59
- package/src/commands/subprocess/utils.ts +20 -20
- package/src/commands/sync/index.ts +7 -7
- package/src/commands/sync/list.ts +54 -86
- package/src/commands/sync/pull.ts +45 -46
- package/src/commands/sync/push.ts +38 -41
- package/src/commands/sync/request.ts +51 -50
- package/src/commands/sync/response.ts +68 -64
- package/src/commands/sync/stat.ts +129 -150
- package/src/commands/sync/sync.ts +182 -181
- package/src/commands/tcpip.ts +21 -21
- package/src/crypto.ts +296 -296
- package/src/features.ts +9 -9
- package/src/index.ts +10 -11
- package/src/packet.ts +80 -80
- package/src/socket/dispatcher.ts +310 -304
- package/src/socket/index.ts +2 -2
- package/src/socket/socket.ts +156 -144
- package/src/utils/auto-reset-event.ts +41 -41
- package/src/utils/base64.ts +329 -306
- package/src/utils/index.ts +3 -3
- package/tsconfig.build.json +3 -3
- package/tsconfig.build.tsbuildinfo +1 -1
- package/esm/commands/subprocess/legacy.d.ts +0 -35
- package/esm/commands/subprocess/legacy.d.ts.map +0 -1
- package/esm/commands/subprocess/legacy.js +0 -53
- package/esm/commands/subprocess/legacy.js.map +0 -1
- package/esm/commands/subprocess/protocol.d.ts +0 -39
- package/esm/commands/subprocess/protocol.d.ts.map +0 -1
- package/esm/commands/subprocess/protocol.js +0 -157
- package/esm/commands/subprocess/protocol.js.map +0 -1
- package/esm/commands/subprocess/types.d.ts +0 -50
- package/esm/commands/subprocess/types.d.ts.map +0 -1
- package/esm/commands/subprocess/types.js +0 -2
- package/esm/commands/subprocess/types.js.map +0 -1
- package/esm/socket/controller.d.ts +0 -37
- package/esm/socket/controller.d.ts.map +0 -1
- package/esm/socket/controller.js +0 -66
- package/esm/socket/controller.js.map +0 -1
- package/esm/stream/buffered.d.ts +0 -35
- package/esm/stream/buffered.d.ts.map +0 -1
- package/esm/stream/buffered.js +0 -123
- package/esm/stream/buffered.js.map +0 -1
- package/esm/stream/detect.bak.d.ts +0 -240
- package/esm/stream/detect.bak.d.ts.map +0 -1
- package/esm/stream/detect.bak.js +0 -60
- package/esm/stream/detect.bak.js.map +0 -1
- package/esm/stream/detect.d.ts +0 -2
- package/esm/stream/detect.d.ts.map +0 -1
- package/esm/stream/detect.js +0 -5
- package/esm/stream/detect.js.map +0 -1
- package/esm/stream/detect.native.d.ts +0 -240
- package/esm/stream/detect.native.d.ts.map +0 -1
- package/esm/stream/detect.native.js +0 -60
- package/esm/stream/detect.native.js.map +0 -1
- package/esm/stream/detect.polyfill.d.ts +0 -18
- package/esm/stream/detect.polyfill.d.ts.map +0 -1
- package/esm/stream/detect.polyfill.js +0 -9
- package/esm/stream/detect.polyfill.js.map +0 -1
- package/esm/stream/index.d.ts +0 -4
- package/esm/stream/index.d.ts.map +0 -1
- package/esm/stream/index.js +0 -4
- package/esm/stream/index.js.map +0 -1
- package/esm/stream/transform.d.ts +0 -104
- package/esm/stream/transform.d.ts.map +0 -1
- package/esm/stream/transform.js +0 -373
- package/esm/stream/transform.js.map +0 -1
- package/esm/utils/encoding.d.ts +0 -3
- package/esm/utils/encoding.d.ts.map +0 -1
- package/esm/utils/encoding.js +0 -11
- package/esm/utils/encoding.js.map +0 -1
- package/src/stream/buffered.ts +0 -147
- package/src/stream/detect.native.ts +0 -362
- package/src/stream/detect.polyfill.ts +0 -28
- package/src/stream/detect.ts +0 -5
- package/src/stream/index.ts +0 -3
- package/src/stream/transform.ts +0 -447
- package/tsconfig.test.json +0 -10
package/src/stream/transform.ts
DELETED
|
@@ -1,447 +0,0 @@
|
|
|
1
|
-
import { PromiseResolver } from "@yume-chan/async";
|
|
2
|
-
import type Struct from "@yume-chan/struct";
|
|
3
|
-
import type { StructValueType, ValueOrPromise } from "@yume-chan/struct";
|
|
4
|
-
import { decodeUtf8 } from "../utils/index.js";
|
|
5
|
-
import { BufferedStream, BufferedStreamEndedError } from "./buffered.js";
|
|
6
|
-
import { AbortController, AbortSignal, ReadableStream, ReadableStreamDefaultReader, TransformStream, WritableStream, WritableStreamDefaultWriter, type QueuingStrategy, type ReadableStreamDefaultController, type ReadableWritablePair } from "./detect.js";
|
|
7
|
-
|
|
8
|
-
export interface DuplexStreamFactoryOptions {
|
|
9
|
-
close?: (() => ValueOrPromise<boolean | void>) | undefined;
|
|
10
|
-
|
|
11
|
-
dispose?: (() => void | Promise<void>) | undefined;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* A factory for creating a duplex stream.
|
|
16
|
-
*
|
|
17
|
-
* It can create multiple `ReadableStream`s and `WritableStream`s,
|
|
18
|
-
* when any of them is closed, all other streams will be closed as well.
|
|
19
|
-
*/
|
|
20
|
-
export class DuplexStreamFactory<R, W> {
|
|
21
|
-
private readableControllers: ReadableStreamDefaultController<R>[] = [];
|
|
22
|
-
private writers: WritableStreamDefaultWriter<W>[] = [];
|
|
23
|
-
|
|
24
|
-
private _writableClosed = false;
|
|
25
|
-
public get writableClosed() { return this._writableClosed; }
|
|
26
|
-
|
|
27
|
-
private _closed = new PromiseResolver<void>();
|
|
28
|
-
public get closed() { return this._closed.promise; }
|
|
29
|
-
|
|
30
|
-
private options: DuplexStreamFactoryOptions;
|
|
31
|
-
|
|
32
|
-
public constructor(options?: DuplexStreamFactoryOptions) {
|
|
33
|
-
this.options = options ?? {};
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
public wrapReadable(readable: ReadableStream<R>): WrapReadableStream<R> {
|
|
37
|
-
return new WrapReadableStream<R>({
|
|
38
|
-
start: (controller) => {
|
|
39
|
-
this.readableControllers.push(controller);
|
|
40
|
-
return readable;
|
|
41
|
-
},
|
|
42
|
-
cancel: async () => {
|
|
43
|
-
// cancel means the local peer closes the connection first.
|
|
44
|
-
await this.close();
|
|
45
|
-
},
|
|
46
|
-
close: async () => {
|
|
47
|
-
// stream end means the remote peer closed the connection first.
|
|
48
|
-
await this.dispose();
|
|
49
|
-
},
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
public createWritable(stream: WritableStream<W>): WritableStream<W> {
|
|
54
|
-
const writer = stream.getWriter();
|
|
55
|
-
this.writers.push(writer);
|
|
56
|
-
|
|
57
|
-
// `WritableStream` has no way to tell if the remote peer has closed the connection.
|
|
58
|
-
// So it only triggers `close`.
|
|
59
|
-
return new WritableStream<W>({
|
|
60
|
-
write: async (chunk) => {
|
|
61
|
-
await writer.ready;
|
|
62
|
-
await writer.write(chunk);
|
|
63
|
-
},
|
|
64
|
-
abort: async (reason) => {
|
|
65
|
-
await writer.abort(reason);
|
|
66
|
-
await this.close();
|
|
67
|
-
},
|
|
68
|
-
close: async () => {
|
|
69
|
-
try { await writer.close(); } catch { }
|
|
70
|
-
await this.close();
|
|
71
|
-
},
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
public async close() {
|
|
76
|
-
if (this._writableClosed) {
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
this._writableClosed = true;
|
|
80
|
-
|
|
81
|
-
if (await this.options.close?.() !== false) {
|
|
82
|
-
// `close` can return `false` to disable automatic `dispose`.
|
|
83
|
-
await this.dispose();
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
for (const writer of this.writers) {
|
|
87
|
-
try { await writer.close(); } catch { }
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
public async dispose() {
|
|
92
|
-
this._writableClosed = true;
|
|
93
|
-
this._closed.resolve();
|
|
94
|
-
|
|
95
|
-
for (const controller of this.readableControllers) {
|
|
96
|
-
try { controller.close(); } catch { }
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
await this.options.dispose?.();
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
export class DecodeUtf8Stream extends TransformStream<Uint8Array, string>{
|
|
104
|
-
public constructor() {
|
|
105
|
-
super({
|
|
106
|
-
transform(chunk, controller) {
|
|
107
|
-
controller.enqueue(decodeUtf8(chunk));
|
|
108
|
-
},
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
export class GatherStringStream extends WritableStream<string>{
|
|
114
|
-
// Optimization: rope (concat strings) is faster than `[].join('')`
|
|
115
|
-
private _result = '';
|
|
116
|
-
public get result() { return this._result; }
|
|
117
|
-
|
|
118
|
-
public constructor() {
|
|
119
|
-
super({
|
|
120
|
-
write: (chunk) => {
|
|
121
|
-
this._result += chunk;
|
|
122
|
-
},
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// TODO: StructTransformStream: Looking for better implementation
|
|
128
|
-
export class StructDeserializeStream<T extends Struct<any, any, any, any>>
|
|
129
|
-
implements ReadableWritablePair<Uint8Array, StructValueType<T>>{
|
|
130
|
-
private _readable: ReadableStream<StructValueType<T>>;
|
|
131
|
-
public get readable() { return this._readable; }
|
|
132
|
-
|
|
133
|
-
private _writable: WritableStream<Uint8Array>;
|
|
134
|
-
public get writable() { return this._writable; }
|
|
135
|
-
|
|
136
|
-
public constructor(struct: T) {
|
|
137
|
-
// Convert incoming chunks to a `BufferedStream`
|
|
138
|
-
let incomingStreamController!: PushReadableStreamController<Uint8Array>;
|
|
139
|
-
const incomingStream = new BufferedStream(
|
|
140
|
-
new PushReadableStream<Uint8Array>(
|
|
141
|
-
controller => incomingStreamController = controller,
|
|
142
|
-
)
|
|
143
|
-
);
|
|
144
|
-
|
|
145
|
-
this._readable = new ReadableStream<StructValueType<T>>({
|
|
146
|
-
async pull(controller) {
|
|
147
|
-
try {
|
|
148
|
-
const value = await struct.deserialize(incomingStream);
|
|
149
|
-
controller.enqueue(value);
|
|
150
|
-
} catch (e) {
|
|
151
|
-
if (e instanceof BufferedStreamEndedError) {
|
|
152
|
-
controller.close();
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
throw e;
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
this._writable = new WritableStream({
|
|
161
|
-
async write(chunk) {
|
|
162
|
-
await incomingStreamController.enqueue(chunk);
|
|
163
|
-
},
|
|
164
|
-
abort() {
|
|
165
|
-
incomingStreamController.close();
|
|
166
|
-
},
|
|
167
|
-
close() {
|
|
168
|
-
incomingStreamController.close();
|
|
169
|
-
},
|
|
170
|
-
});
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
export class StructSerializeStream<T extends Struct<any, any, any, any>>
|
|
175
|
-
extends TransformStream<T['TInit'], Uint8Array>{
|
|
176
|
-
constructor(struct: T) {
|
|
177
|
-
super({
|
|
178
|
-
transform(chunk, controller) {
|
|
179
|
-
controller.enqueue(struct.serialize(chunk));
|
|
180
|
-
},
|
|
181
|
-
});
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
export type WrapWritableStreamStart<T> = () => ValueOrPromise<WritableStream<T>>;
|
|
186
|
-
|
|
187
|
-
export interface WritableStreamWrapper<T> {
|
|
188
|
-
start: WrapWritableStreamStart<T>;
|
|
189
|
-
close?(): Promise<void>;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
async function getWrappedWritableStream<T>(
|
|
193
|
-
wrapper: WritableStream<T> | WrapWritableStreamStart<T> | WritableStreamWrapper<T>
|
|
194
|
-
) {
|
|
195
|
-
if ('start' in wrapper) {
|
|
196
|
-
return await wrapper.start();
|
|
197
|
-
} else if (typeof wrapper === 'function') {
|
|
198
|
-
return await wrapper();
|
|
199
|
-
} else {
|
|
200
|
-
// Can't use `wrapper instanceof WritableStream`
|
|
201
|
-
// Because we want to be compatible with any WritableStream-like objects
|
|
202
|
-
return wrapper;
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
export class WrapWritableStream<T> extends WritableStream<T> {
|
|
207
|
-
public writable!: WritableStream<T>;
|
|
208
|
-
|
|
209
|
-
private writer!: WritableStreamDefaultWriter<T>;
|
|
210
|
-
|
|
211
|
-
public constructor(wrapper: WritableStream<T> | WrapWritableStreamStart<T> | WritableStreamWrapper<T>) {
|
|
212
|
-
super({
|
|
213
|
-
start: async () => {
|
|
214
|
-
// `start` is invoked before `ReadableStream`'s constructor finish,
|
|
215
|
-
// so using `this` synchronously causes
|
|
216
|
-
// "Must call super constructor in derived class before accessing 'this' or returning from derived constructor".
|
|
217
|
-
// Queue a microtask to avoid this.
|
|
218
|
-
await Promise.resolve();
|
|
219
|
-
|
|
220
|
-
this.writable = await getWrappedWritableStream(wrapper);
|
|
221
|
-
this.writer = this.writable.getWriter();
|
|
222
|
-
},
|
|
223
|
-
write: async (chunk) => {
|
|
224
|
-
// Maintain back pressure
|
|
225
|
-
await this.writer.ready;
|
|
226
|
-
await this.writer.write(chunk);
|
|
227
|
-
},
|
|
228
|
-
abort: async (reason) => {
|
|
229
|
-
await this.writer.abort(reason);
|
|
230
|
-
if ('close' in wrapper) {
|
|
231
|
-
await wrapper.close?.();
|
|
232
|
-
}
|
|
233
|
-
},
|
|
234
|
-
close: async () => {
|
|
235
|
-
// Close the inner stream first.
|
|
236
|
-
// Usually the inner stream is a logical sub-stream over the outer stream,
|
|
237
|
-
// closing the outer stream first will make the inner stream incapable of
|
|
238
|
-
// sending data in its `close` handler.
|
|
239
|
-
await this.writer.close();
|
|
240
|
-
if ('close' in wrapper) {
|
|
241
|
-
await wrapper.close?.();
|
|
242
|
-
}
|
|
243
|
-
},
|
|
244
|
-
});
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
export type WrapReadableStreamStart<T> = (controller: ReadableStreamDefaultController<T>) => ValueOrPromise<ReadableStream<T>>;
|
|
249
|
-
|
|
250
|
-
export interface ReadableStreamWrapper<T> {
|
|
251
|
-
start: WrapReadableStreamStart<T>;
|
|
252
|
-
cancel?(reason?: any): ValueOrPromise<void>;
|
|
253
|
-
close?(): ValueOrPromise<void>;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
function getWrappedReadableStream<T>(
|
|
257
|
-
wrapper: ReadableStream<T> | WrapReadableStreamStart<T> | ReadableStreamWrapper<T>,
|
|
258
|
-
controller: ReadableStreamDefaultController<T>
|
|
259
|
-
) {
|
|
260
|
-
if ('start' in wrapper) {
|
|
261
|
-
return wrapper.start(controller);
|
|
262
|
-
} else if (typeof wrapper === 'function') {
|
|
263
|
-
return wrapper(controller);
|
|
264
|
-
} else {
|
|
265
|
-
// Can't use `wrapper instanceof ReadableStream`
|
|
266
|
-
// Because we want to be compatible with any ReadableStream-like objects
|
|
267
|
-
return wrapper;
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
/**
|
|
272
|
-
* This class has multiple usages:
|
|
273
|
-
*
|
|
274
|
-
* 1. Get notified when the stream is cancelled or closed.
|
|
275
|
-
* 2. Synchronously create a `ReadableStream` by asynchronously return another `ReadableStream`.
|
|
276
|
-
* 3. Convert native `ReadableStream`s to polyfilled ones so they can `pipe` between.
|
|
277
|
-
*/
|
|
278
|
-
export class WrapReadableStream<T> extends ReadableStream<T>{
|
|
279
|
-
public readable!: ReadableStream<T>;
|
|
280
|
-
|
|
281
|
-
private reader!: ReadableStreamDefaultReader<T>;
|
|
282
|
-
|
|
283
|
-
public constructor(wrapper: ReadableStream<T> | WrapReadableStreamStart<T> | ReadableStreamWrapper<T>) {
|
|
284
|
-
super({
|
|
285
|
-
start: async (controller) => {
|
|
286
|
-
// `start` is invoked before `ReadableStream`'s constructor finish,
|
|
287
|
-
// so using `this` synchronously causes
|
|
288
|
-
// "Must call super constructor in derived class before accessing 'this' or returning from derived constructor".
|
|
289
|
-
// Queue a microtask to avoid this.
|
|
290
|
-
await Promise.resolve();
|
|
291
|
-
|
|
292
|
-
this.readable = await getWrappedReadableStream(wrapper, controller);
|
|
293
|
-
this.reader = this.readable.getReader();
|
|
294
|
-
},
|
|
295
|
-
cancel: async (reason) => {
|
|
296
|
-
await this.reader.cancel(reason);
|
|
297
|
-
if ('cancel' in wrapper) {
|
|
298
|
-
await wrapper.cancel?.(reason);
|
|
299
|
-
}
|
|
300
|
-
},
|
|
301
|
-
pull: async (controller) => {
|
|
302
|
-
const result = await this.reader.read();
|
|
303
|
-
if (result.done) {
|
|
304
|
-
controller.close();
|
|
305
|
-
if ('close' in wrapper) {
|
|
306
|
-
await wrapper.close?.();
|
|
307
|
-
}
|
|
308
|
-
} else {
|
|
309
|
-
controller.enqueue(result.value);
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
});
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
export class ChunkStream extends TransformStream<Uint8Array, Uint8Array>{
|
|
317
|
-
public constructor(size: number) {
|
|
318
|
-
super({
|
|
319
|
-
transform(chunk, controller) {
|
|
320
|
-
for (let start = 0; start < chunk.byteLength;) {
|
|
321
|
-
const end = start + size;
|
|
322
|
-
controller.enqueue(chunk.subarray(start, end));
|
|
323
|
-
start = end;
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
});
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
function* splitLines(text: string): Generator<string, void, void> {
|
|
331
|
-
let start = 0;
|
|
332
|
-
|
|
333
|
-
while (true) {
|
|
334
|
-
const index = text.indexOf('\n', start);
|
|
335
|
-
if (index === -1) {
|
|
336
|
-
return;
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
const line = text.substring(start, index);
|
|
340
|
-
yield line;
|
|
341
|
-
|
|
342
|
-
start = index + 1;
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
export class SplitLineStream extends TransformStream<string, string> {
|
|
347
|
-
public constructor() {
|
|
348
|
-
super({
|
|
349
|
-
transform(chunk, controller) {
|
|
350
|
-
for (const line of splitLines(chunk)) {
|
|
351
|
-
controller.enqueue(line);
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
});
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
/**
|
|
359
|
-
* Create a new `WritableStream` that, when written to, will write that chunk to
|
|
360
|
-
* `pair.writable`, when pipe `pair.readable` to `writable`.
|
|
361
|
-
*
|
|
362
|
-
* It's the opposite of `ReadableStream.pipeThrough`.
|
|
363
|
-
*
|
|
364
|
-
* @param writable The `WritableStream` to write to.
|
|
365
|
-
* @param pair A `TransformStream` that converts chunks.
|
|
366
|
-
* @returns A new `WritableStream`.
|
|
367
|
-
*/
|
|
368
|
-
export function pipeFrom<W, T>(writable: WritableStream<W>, pair: ReadableWritablePair<W, T>) {
|
|
369
|
-
const writer = pair.writable.getWriter();
|
|
370
|
-
const pipe = pair.readable
|
|
371
|
-
.pipeTo(writable);
|
|
372
|
-
return new WritableStream<T>({
|
|
373
|
-
async write(chunk) {
|
|
374
|
-
await writer.ready;
|
|
375
|
-
await writer.write(chunk);
|
|
376
|
-
},
|
|
377
|
-
async close() {
|
|
378
|
-
await writer.close();
|
|
379
|
-
await pipe;
|
|
380
|
-
}
|
|
381
|
-
});
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
export class InspectStream<T> extends TransformStream<T, T> {
|
|
385
|
-
constructor(callback: (value: T) => void) {
|
|
386
|
-
super({
|
|
387
|
-
transform(chunk, controller) {
|
|
388
|
-
callback(chunk);
|
|
389
|
-
controller.enqueue(chunk);
|
|
390
|
-
}
|
|
391
|
-
});
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
export interface PushReadableStreamController<T> {
|
|
396
|
-
abortSignal: AbortSignal;
|
|
397
|
-
|
|
398
|
-
enqueue(chunk: T): Promise<void>;
|
|
399
|
-
|
|
400
|
-
close(): void;
|
|
401
|
-
|
|
402
|
-
error(e?: any): void;
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
export type PushReadableStreamSource<T> = (controller: PushReadableStreamController<T>) => void;
|
|
406
|
-
|
|
407
|
-
export class PushReadableStream<T> extends ReadableStream<T> {
|
|
408
|
-
public constructor(source: PushReadableStreamSource<T>, strategy?: QueuingStrategy<T>) {
|
|
409
|
-
let waterMarkLow: PromiseResolver<void> | undefined;
|
|
410
|
-
const canceled: AbortController = new AbortController();
|
|
411
|
-
|
|
412
|
-
super({
|
|
413
|
-
start: (controller) => {
|
|
414
|
-
source({
|
|
415
|
-
abortSignal: canceled.signal,
|
|
416
|
-
async enqueue(chunk) {
|
|
417
|
-
// Only when the stream is errored, `desiredSize` will be `null`.
|
|
418
|
-
// But since `null <= 0` is `true`
|
|
419
|
-
// (`null <= 0` is evaluated as `!(null > 0)` => `!false` => `true`),
|
|
420
|
-
// not handling it will cause a deadlock.
|
|
421
|
-
if ((controller.desiredSize ?? 1) <= 0) {
|
|
422
|
-
waterMarkLow = new PromiseResolver<void>();
|
|
423
|
-
await waterMarkLow.promise;
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
// `controller.enqueue` will throw error for us
|
|
427
|
-
// if the stream is already errored.
|
|
428
|
-
controller.enqueue(chunk);
|
|
429
|
-
},
|
|
430
|
-
close() {
|
|
431
|
-
controller.close();
|
|
432
|
-
},
|
|
433
|
-
error(e) {
|
|
434
|
-
controller.error(e);
|
|
435
|
-
},
|
|
436
|
-
});
|
|
437
|
-
},
|
|
438
|
-
pull: () => {
|
|
439
|
-
waterMarkLow?.resolve();
|
|
440
|
-
},
|
|
441
|
-
cancel: async (reason) => {
|
|
442
|
-
canceled.abort();
|
|
443
|
-
waterMarkLow?.reject(reason);
|
|
444
|
-
},
|
|
445
|
-
}, strategy);
|
|
446
|
-
}
|
|
447
|
-
}
|