@yume-chan/adb 0.0.13 → 0.0.14
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 +15 -0
- package/CHANGELOG.md +9 -1
- package/esm/adb.d.ts +5 -4
- package/esm/adb.d.ts.map +1 -1
- package/esm/adb.js +15 -10
- package/esm/adb.js.map +1 -1
- package/esm/commands/reverse.d.ts +7 -10
- package/esm/commands/reverse.d.ts.map +1 -1
- package/esm/commands/reverse.js +9 -15
- package/esm/commands/reverse.js.map +1 -1
- package/esm/commands/subprocess/protocols/none.d.ts +1 -1
- package/esm/commands/subprocess/protocols/none.d.ts.map +1 -1
- package/esm/commands/subprocess/protocols/none.js +6 -6
- package/esm/commands/subprocess/protocols/none.js.map +1 -1
- package/esm/commands/sync/pull.d.ts.map +1 -1
- package/esm/commands/sync/pull.js +6 -3
- package/esm/commands/sync/pull.js.map +1 -1
- package/esm/socket/dispatcher.d.ts +21 -14
- package/esm/socket/dispatcher.d.ts.map +1 -1
- package/esm/socket/dispatcher.js +78 -53
- package/esm/socket/dispatcher.js.map +1 -1
- package/esm/socket/socket.d.ts +11 -2
- package/esm/socket/socket.d.ts.map +1 -1
- package/esm/socket/socket.js +21 -16
- package/esm/socket/socket.js.map +1 -1
- package/esm/stream/transform.d.ts +17 -12
- package/esm/stream/transform.d.ts.map +1 -1
- package/esm/stream/transform.js +45 -81
- package/esm/stream/transform.js.map +1 -1
- package/package.json +4 -4
- package/src/adb.ts +18 -12
- package/src/commands/reverse.ts +13 -24
- package/src/commands/subprocess/protocols/none.ts +6 -6
- package/src/commands/sync/pull.ts +6 -3
- package/src/socket/dispatcher.ts +96 -65
- package/src/socket/socket.ts +36 -30
- package/src/stream/transform.ts +53 -92
- package/tsconfig.build.tsbuildinfo +1 -1
package/esm/socket/dispatcher.js
CHANGED
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
import { AsyncOperationManager, PromiseResolver } from '@yume-chan/async';
|
|
2
|
-
import { AutoDisposable, EventEmitter } from '@yume-chan/event';
|
|
3
2
|
import { AdbCommand, calculateChecksum } from '../packet.js';
|
|
4
3
|
import { AbortController, WritableStream } from '../stream/index.js';
|
|
5
4
|
import { decodeUtf8, encodeUtf8 } from '../utils/index.js';
|
|
6
5
|
import { AdbSocketController } from './socket.js';
|
|
7
6
|
const EmptyUint8Array = new Uint8Array(0);
|
|
8
|
-
|
|
7
|
+
/**
|
|
8
|
+
* The dispatcher is the "dumb" part of the connection handling logic.
|
|
9
|
+
*
|
|
10
|
+
* Except some options to change some minor behaviors,
|
|
11
|
+
* its only job is forwarding packets between authenticated underlying streams
|
|
12
|
+
* and abstracted socket objects.
|
|
13
|
+
*
|
|
14
|
+
* The `Adb` class is responsible for doing the authentication,
|
|
15
|
+
* negotiating the options, and has shortcuts to high-level services.
|
|
16
|
+
*/
|
|
17
|
+
export class AdbPacketDispatcher {
|
|
9
18
|
// ADB socket id starts from 1
|
|
10
19
|
// (0 means open failed)
|
|
11
20
|
initializers = new AsyncOperationManager(1);
|
|
@@ -14,43 +23,44 @@ export class AdbPacketDispatcher extends AutoDisposable {
|
|
|
14
23
|
options;
|
|
15
24
|
_disconnected = new PromiseResolver();
|
|
16
25
|
get disconnected() { return this._disconnected.promise; }
|
|
17
|
-
|
|
18
|
-
get onIncomingSocket() { return this.incomingSocketEvent.event; }
|
|
26
|
+
_incomingSocketHandlers = new Set();
|
|
19
27
|
_abortController = new AbortController();
|
|
20
28
|
constructor(connection, options) {
|
|
21
|
-
super();
|
|
22
29
|
this.options = options;
|
|
23
30
|
connection.readable
|
|
24
31
|
.pipeTo(new WritableStream({
|
|
25
32
|
write: async (packet) => {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
// But won't close `readable` because of `preventCancel: true`
|
|
50
|
-
throw e;
|
|
33
|
+
switch (packet.command) {
|
|
34
|
+
case AdbCommand.OK:
|
|
35
|
+
this.handleOk(packet);
|
|
36
|
+
break;
|
|
37
|
+
case AdbCommand.Close:
|
|
38
|
+
await this.handleClose(packet);
|
|
39
|
+
break;
|
|
40
|
+
case AdbCommand.Write:
|
|
41
|
+
if (this.sockets.has(packet.arg1)) {
|
|
42
|
+
await this.sockets.get(packet.arg1).enqueue(packet.payload);
|
|
43
|
+
await this.sendPacket(AdbCommand.OK, packet.arg1, packet.arg0);
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
throw new Error(`Unknown local socket id: ${packet.arg1}`);
|
|
47
|
+
case AdbCommand.Open:
|
|
48
|
+
await this.handleOpen(packet);
|
|
49
|
+
break;
|
|
50
|
+
default:
|
|
51
|
+
// Junk data may only appear in the authentication phase,
|
|
52
|
+
// since the dispatcher only works after authentication,
|
|
53
|
+
// all packets should have a valid command.
|
|
54
|
+
// (although it's possible that Adb added new commands in the future)
|
|
55
|
+
throw new Error(`Unknown command: ${packet.command.toString(16)}`);
|
|
51
56
|
}
|
|
52
57
|
},
|
|
53
58
|
}), {
|
|
59
|
+
// There are multiple reasons for the pipe to stop,
|
|
60
|
+
// including device disconnection, protocol error, or user abort,
|
|
61
|
+
// if the underlying streams are still open,
|
|
62
|
+
// it's still possible to create another ADB connection.
|
|
63
|
+
// So don't close `readable` here.
|
|
54
64
|
preventCancel: false,
|
|
55
65
|
signal: this._abortController.signal,
|
|
56
66
|
})
|
|
@@ -84,12 +94,17 @@ export class AdbPacketDispatcher extends AutoDisposable {
|
|
|
84
94
|
* versions, CLOSE(0, remote-id, "") was also used for normal
|
|
85
95
|
* CLOSE() operations.
|
|
86
96
|
*/
|
|
87
|
-
//
|
|
97
|
+
// If the socket is still pending
|
|
88
98
|
if (packet.arg0 === 0 &&
|
|
89
99
|
this.initializers.reject(packet.arg1, new Error('Socket open failed'))) {
|
|
90
100
|
// Device failed to create the socket
|
|
101
|
+
// (unknown service string, failed to execute command, etc.)
|
|
102
|
+
// it doesn't break the connection,
|
|
103
|
+
// so only reject the socket creation promise,
|
|
104
|
+
// don't throw an error here.
|
|
91
105
|
return;
|
|
92
106
|
}
|
|
107
|
+
// Ignore `arg0` and search for the socket
|
|
93
108
|
const socket = this.sockets.get(packet.arg1);
|
|
94
109
|
if (socket) {
|
|
95
110
|
// The device want to close the socket
|
|
@@ -100,8 +115,17 @@ export class AdbPacketDispatcher extends AutoDisposable {
|
|
|
100
115
|
this.sockets.delete(packet.arg1);
|
|
101
116
|
return;
|
|
102
117
|
}
|
|
103
|
-
//
|
|
104
|
-
//
|
|
118
|
+
// TODO: adb: is double closing an socket a catastrophic error?
|
|
119
|
+
// If the client sends two `CLSE` packets for one socket,
|
|
120
|
+
// the device may also respond with two `CLSE` packets.
|
|
121
|
+
}
|
|
122
|
+
addIncomingSocketHandler(handler) {
|
|
123
|
+
this._incomingSocketHandlers.add(handler);
|
|
124
|
+
const remove = () => {
|
|
125
|
+
this._incomingSocketHandlers.delete(handler);
|
|
126
|
+
};
|
|
127
|
+
remove.dispose = remove;
|
|
128
|
+
return remove;
|
|
105
129
|
}
|
|
106
130
|
async handleOpen(packet) {
|
|
107
131
|
// AsyncOperationManager doesn't support get and skip an ID
|
|
@@ -117,20 +141,14 @@ export class AdbPacketDispatcher extends AutoDisposable {
|
|
|
117
141
|
localCreated: false,
|
|
118
142
|
serviceString,
|
|
119
143
|
});
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
this.incomingSocketEvent.fire(args);
|
|
127
|
-
if (args.handled) {
|
|
128
|
-
this.sockets.set(localId, controller);
|
|
129
|
-
await this.sendPacket(AdbCommand.OK, localId, remoteId);
|
|
130
|
-
}
|
|
131
|
-
else {
|
|
132
|
-
await this.sendPacket(AdbCommand.Close, 0, remoteId);
|
|
144
|
+
for (const handler of this._incomingSocketHandlers) {
|
|
145
|
+
if (await handler(controller.socket)) {
|
|
146
|
+
this.sockets.set(localId, controller);
|
|
147
|
+
await this.sendPacket(AdbCommand.OK, localId, remoteId);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
133
150
|
}
|
|
151
|
+
await this.sendPacket(AdbCommand.Close, 0, remoteId);
|
|
134
152
|
}
|
|
135
153
|
async createSocket(serviceString) {
|
|
136
154
|
if (this.options.appendNullToServiceString) {
|
|
@@ -178,19 +196,26 @@ export class AdbPacketDispatcher extends AutoDisposable {
|
|
|
178
196
|
}
|
|
179
197
|
await this._writer.write(init);
|
|
180
198
|
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
199
|
+
async close() {
|
|
200
|
+
// Send `CLSE` packets for all sockets
|
|
201
|
+
await Promise.all(Array.from(this.sockets.values(), socket => socket.close()));
|
|
202
|
+
// Stop receiving
|
|
203
|
+
// It's possible that we haven't received all `CLSE` confirm packets,
|
|
204
|
+
// but it doesn't matter, the next connection can cope with them.
|
|
186
205
|
try {
|
|
187
|
-
// Stop pipes
|
|
188
206
|
this._abortController.abort();
|
|
189
207
|
}
|
|
190
208
|
catch { }
|
|
209
|
+
// Adb connection doesn't have a method to confirm closing,
|
|
210
|
+
// so call `dispose` immediately
|
|
211
|
+
this.dispose();
|
|
212
|
+
}
|
|
213
|
+
dispose() {
|
|
214
|
+
for (const socket of this.sockets.values()) {
|
|
215
|
+
socket.dispose();
|
|
216
|
+
}
|
|
191
217
|
this._writer.releaseLock();
|
|
192
218
|
this._disconnected.resolve();
|
|
193
|
-
super.dispose();
|
|
194
219
|
}
|
|
195
220
|
}
|
|
196
221
|
//# sourceMappingURL=dispatcher.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dispatcher.js","sourceRoot":"","sources":["../../src/socket/dispatcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"dispatcher.js","sourceRoot":"","sources":["../../src/socket/dispatcher.ts"],"names":[],"mappings":"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"}
|
package/esm/socket/socket.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import type { Disposable } from "@yume-chan/event";
|
|
1
2
|
import { type ReadableStream, type ReadableWritablePair, type WritableStream } from '../stream/index.js';
|
|
2
|
-
import type { AdbPacketDispatcher } from './dispatcher.js';
|
|
3
|
+
import type { AdbPacketDispatcher, Closeable } from './dispatcher.js';
|
|
3
4
|
export interface AdbSocketInfo {
|
|
4
5
|
localId: number;
|
|
5
6
|
remoteId: number;
|
|
@@ -10,7 +11,7 @@ export interface AdbSocketConstructionOptions extends AdbSocketInfo {
|
|
|
10
11
|
dispatcher: AdbPacketDispatcher;
|
|
11
12
|
highWaterMark?: number | undefined;
|
|
12
13
|
}
|
|
13
|
-
export declare class AdbSocketController implements AdbSocketInfo, ReadableWritablePair<Uint8Array, Uint8Array
|
|
14
|
+
export declare class AdbSocketController implements AdbSocketInfo, ReadableWritablePair<Uint8Array, Uint8Array>, Closeable, Disposable {
|
|
14
15
|
private readonly dispatcher;
|
|
15
16
|
readonly localId: number;
|
|
16
17
|
readonly remoteId: number;
|
|
@@ -32,6 +33,14 @@ export declare class AdbSocketController implements AdbSocketInfo, ReadableWrita
|
|
|
32
33
|
close(): Promise<void>;
|
|
33
34
|
dispose(): void;
|
|
34
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* AdbSocket is a duplex stream.
|
|
38
|
+
*
|
|
39
|
+
* To close it, call either `socket.close()`,
|
|
40
|
+
* `socket.readable.cancel()`, `socket.readable.getReader().cancel()`,
|
|
41
|
+
* `socket.writable.abort()`, `socket.writable.getWriter().abort()`,
|
|
42
|
+
* `socket.writable.close()` or `socket.writable.getWriter().close()`.
|
|
43
|
+
*/
|
|
35
44
|
export declare class AdbSocket implements AdbSocketInfo, ReadableWritablePair<Uint8Array, Uint8Array> {
|
|
36
45
|
private _controller;
|
|
37
46
|
get localId(): number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"socket.d.ts","sourceRoot":"","sources":["../../src/socket/socket.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"socket.d.ts","sourceRoot":"","sources":["../../src/socket/socket.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,OAAO,EAAqG,KAAK,cAAc,EAAE,KAAK,oBAAoB,EAAE,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAC5M,OAAO,KAAK,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEtE,MAAM,WAAW,aAAa;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IAEjB,YAAY,EAAE,OAAO,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,4BAA6B,SAAQ,aAAa;IAC/D,UAAU,EAAE,mBAAmB,CAAC;IAEhC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACtC;AAED,qBAAa,mBAAoB,YAAW,aAAa,EAAE,oBAAoB,CAAC,UAAU,EAAE,UAAU,CAAC,EAAE,SAAS,EAAE,UAAU;IAC1H,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAuB;IAElD,SAAgB,OAAO,EAAG,MAAM,CAAC;IACjC,SAAgB,QAAQ,EAAG,MAAM,CAAC;IAClC,SAAgB,YAAY,EAAG,OAAO,CAAC;IACvC,SAAgB,aAAa,EAAG,MAAM,CAAC;IAEvC,OAAO,CAAC,QAAQ,CAA8C;IAE9D,OAAO,CAAC,SAAS,CAA6B;IAC9C,OAAO,CAAC,mBAAmB,CAA4C;IACvE,IAAW,QAAQ,+BAA6B;IAEhD,OAAO,CAAC,aAAa,CAAoC;IACzD,SAAgB,QAAQ,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;IAErD,OAAO,CAAC,OAAO,CAAS;IACxB,IAAW,MAAM,YAA2B;IAE5C,OAAO,CAAC,OAAO,CAAY;IAC3B,IAAW,MAAM,cAA2B;gBAEzB,OAAO,EAAE,4BAA4B;IAuD3C,OAAO,CAAC,MAAM,EAAE,UAAU;IAIhC,GAAG;IAIG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B,OAAO;CAGjB;AAED;;;;;;;GAOG;AACH,qBAAa,SAAU,YAAW,aAAa,EAAE,oBAAoB,CAAC,UAAU,EAAE,UAAU,CAAC;IACzF,OAAO,CAAC,WAAW,CAAsB;IAEzC,IAAW,OAAO,IAAI,MAAM,CAAqC;IACjE,IAAW,QAAQ,IAAI,MAAM,CAAsC;IACnE,IAAW,YAAY,IAAI,OAAO,CAA0C;IAC5E,IAAW,aAAa,IAAI,MAAM,CAA2C;IAE7E,IAAW,QAAQ,IAAI,cAAc,CAAC,UAAU,CAAC,CAAsC;IACvF,IAAW,QAAQ,IAAI,cAAc,CAAC,UAAU,CAAC,CAAsC;gBAEpE,UAAU,EAAE,mBAAmB;IAI3C,KAAK;CAGf"}
|
package/esm/socket/socket.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { PromiseResolver } from "@yume-chan/async";
|
|
2
2
|
import { AdbCommand } from '../packet.js';
|
|
3
|
-
import { ChunkStream, DuplexStreamFactory, pipeFrom } from '../stream/index.js';
|
|
3
|
+
import { ChunkStream, DuplexStreamFactory, pipeFrom, PushReadableStream } from '../stream/index.js';
|
|
4
4
|
export class AdbSocketController {
|
|
5
5
|
dispatcher;
|
|
6
6
|
localId;
|
|
@@ -24,15 +24,22 @@ export class AdbSocketController {
|
|
|
24
24
|
// https://www.plantuml.com/plantuml/png/TL0zoeGm4ErpYc3l5JxyS0yWM6mX5j4C6p4cxcJ25ejttuGX88ZftizxUKmJI275pGhXl0PP_UkfK_CAz5Z2hcWsW9Ny2fdU4C1f5aSchFVxA8vJjlTPRhqZzDQMRB7AklwJ0xXtX0ZSKH1h24ghoKAdGY23FhxC4nS2pDvxzIvxb-8THU0XlEQJ-ZB7SnXTAvc_LhOckhMdLBnbtndpb-SB7a8q2SRD_W00
|
|
25
25
|
this._factory = new DuplexStreamFactory({
|
|
26
26
|
close: async () => {
|
|
27
|
-
await this.
|
|
27
|
+
await this.dispatcher.sendPacket(AdbCommand.Close, this.localId, this.remoteId);
|
|
28
|
+
// Don't `dispose` here, we need to wait for `CLSE` response packet.
|
|
29
|
+
return false;
|
|
30
|
+
},
|
|
31
|
+
dispose: () => {
|
|
32
|
+
this._closed = true;
|
|
33
|
+
// Error out the pending writes
|
|
34
|
+
this._writePromise?.reject(new Error('Socket closed'));
|
|
28
35
|
},
|
|
29
36
|
});
|
|
30
|
-
this._readable = this._factory.
|
|
37
|
+
this._readable = this._factory.wrapReadable(new PushReadableStream(controller => {
|
|
31
38
|
this._readableController = controller;
|
|
32
39
|
}, {
|
|
33
40
|
highWaterMark: options.highWaterMark ?? 16 * 1024,
|
|
34
41
|
size(chunk) { return chunk.byteLength; }
|
|
35
|
-
});
|
|
42
|
+
}));
|
|
36
43
|
this.writable = pipeFrom(this._factory.createWritable({
|
|
37
44
|
write: async (chunk) => {
|
|
38
45
|
// Wait for an ack packet
|
|
@@ -50,22 +57,20 @@ export class AdbSocketController {
|
|
|
50
57
|
this._writePromise?.resolve();
|
|
51
58
|
}
|
|
52
59
|
async close() {
|
|
53
|
-
|
|
54
|
-
this._writePromise?.reject(new Error('Socket closed'));
|
|
55
|
-
if (!this._closed) {
|
|
56
|
-
this._closed = true;
|
|
57
|
-
// Only send close packet when `close` is called before `dispose`
|
|
58
|
-
// (the client initiated the close)
|
|
59
|
-
await this.dispatcher.sendPacket(AdbCommand.Close, this.localId, this.remoteId);
|
|
60
|
-
}
|
|
60
|
+
this._factory.close();
|
|
61
61
|
}
|
|
62
62
|
dispose() {
|
|
63
|
-
this.
|
|
64
|
-
this._factory.close();
|
|
65
|
-
// Close `writable` side
|
|
66
|
-
this.close();
|
|
63
|
+
this._factory.dispose();
|
|
67
64
|
}
|
|
68
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* AdbSocket is a duplex stream.
|
|
68
|
+
*
|
|
69
|
+
* To close it, call either `socket.close()`,
|
|
70
|
+
* `socket.readable.cancel()`, `socket.readable.getReader().cancel()`,
|
|
71
|
+
* `socket.writable.abort()`, `socket.writable.getWriter().abort()`,
|
|
72
|
+
* `socket.writable.close()` or `socket.writable.getWriter().close()`.
|
|
73
|
+
*/
|
|
69
74
|
export class AdbSocket {
|
|
70
75
|
_controller;
|
|
71
76
|
get localId() { return this._controller.localId; }
|
package/esm/socket/socket.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"socket.js","sourceRoot":"","sources":["../../src/socket/socket.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"socket.js","sourceRoot":"","sources":["../../src/socket/socket.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type Struct from "@yume-chan/struct";
|
|
2
2
|
import type { StructValueType, ValueOrPromise } from "@yume-chan/struct";
|
|
3
|
-
import { AbortSignal, ReadableStream, TransformStream, WritableStream, type QueuingStrategy, type
|
|
3
|
+
import { AbortSignal, ReadableStream, TransformStream, WritableStream, type QueuingStrategy, type ReadableStreamDefaultController, type ReadableWritablePair, type UnderlyingSink } from "./detect.js";
|
|
4
4
|
export interface DuplexStreamFactoryOptions {
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
close?: (() => ValueOrPromise<boolean | void>) | undefined;
|
|
6
|
+
dispose?: (() => void | Promise<void>) | undefined;
|
|
7
7
|
}
|
|
8
8
|
/**
|
|
9
9
|
* A factory for creating a duplex stream.
|
|
@@ -13,19 +13,16 @@ export interface DuplexStreamFactoryOptions {
|
|
|
13
13
|
*/
|
|
14
14
|
export declare class DuplexStreamFactory<R, W> {
|
|
15
15
|
private readableControllers;
|
|
16
|
-
private
|
|
16
|
+
private _writableClosed;
|
|
17
|
+
get writableClosed(): boolean;
|
|
17
18
|
private _closed;
|
|
18
19
|
get closed(): Promise<void>;
|
|
19
20
|
private options;
|
|
20
|
-
private _closeRequestedByReadable;
|
|
21
|
-
private _writableClosed;
|
|
22
21
|
constructor(options?: DuplexStreamFactoryOptions);
|
|
23
|
-
|
|
24
|
-
createWrapReadable(wrapper: ReadableStream<R> | WrapReadableStreamStart<R> | ReadableStreamWrapper<R>): WrapReadableStream<R>;
|
|
25
|
-
createReadable(source?: UnderlyingSource<R>, strategy?: QueuingStrategy<R>): ReadableStream<R>;
|
|
22
|
+
wrapReadable(readable: ReadableStream<R>): WrapReadableStream<R>;
|
|
26
23
|
createWritable(sink: UnderlyingSink<W>, strategy?: QueuingStrategy<W>): WritableStream<W>;
|
|
27
|
-
closeReadableStreams(): Promise<void>;
|
|
28
24
|
close(): Promise<void>;
|
|
25
|
+
dispose(): Promise<void>;
|
|
29
26
|
}
|
|
30
27
|
export declare class DecodeUtf8Stream extends TransformStream<Uint8Array, string> {
|
|
31
28
|
constructor();
|
|
@@ -55,11 +52,19 @@ export declare class WrapWritableStream<T> extends WritableStream<T> {
|
|
|
55
52
|
private writer;
|
|
56
53
|
constructor(wrapper: WritableStream<T> | WrapWritableStreamStart<T> | WritableStreamWrapper<T>);
|
|
57
54
|
}
|
|
58
|
-
export declare type WrapReadableStreamStart<T> = () => ValueOrPromise<ReadableStream<T>>;
|
|
55
|
+
export declare type WrapReadableStreamStart<T> = (controller: ReadableStreamDefaultController<T>) => ValueOrPromise<ReadableStream<T>>;
|
|
59
56
|
export interface ReadableStreamWrapper<T> {
|
|
60
57
|
start: WrapReadableStreamStart<T>;
|
|
61
|
-
|
|
58
|
+
cancel?(reason?: any): ValueOrPromise<void>;
|
|
59
|
+
close?(): ValueOrPromise<void>;
|
|
62
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* This class has multiple usages:
|
|
63
|
+
*
|
|
64
|
+
* 1. Get notified when the stream is cancelled or closed.
|
|
65
|
+
* 2. Synchronously create a `ReadableStream` by asynchronously return another `ReadableStream`.
|
|
66
|
+
* 3. Convert native `ReadableStream`s to polyfilled ones so they can `pipe` between.
|
|
67
|
+
*/
|
|
63
68
|
export declare class WrapReadableStream<T> extends ReadableStream<T> {
|
|
64
69
|
readable: ReadableStream<T>;
|
|
65
70
|
private reader;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../src/stream/transform.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,MAAM,mBAAmB,CAAC;AAC5C,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGzE,OAAO,EAAmB,WAAW,EAAE,cAAc,EAA+B,eAAe,EAAE,cAAc,EAA+B,KAAK,eAAe,
|
|
1
|
+
{"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../src/stream/transform.ts"],"names":[],"mappings":"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"}
|
package/esm/stream/transform.js
CHANGED
|
@@ -10,74 +10,33 @@ import { AbortController, ReadableStream, TransformStream, WritableStream } from
|
|
|
10
10
|
*/
|
|
11
11
|
export class DuplexStreamFactory {
|
|
12
12
|
readableControllers = [];
|
|
13
|
-
|
|
13
|
+
_writableClosed = false;
|
|
14
|
+
get writableClosed() { return this._writableClosed; }
|
|
14
15
|
_closed = new PromiseResolver();
|
|
15
16
|
get closed() { return this._closed.promise; }
|
|
16
17
|
options;
|
|
17
|
-
_closeRequestedByReadable = false;
|
|
18
|
-
_writableClosed = false;
|
|
19
18
|
constructor(options) {
|
|
20
19
|
this.options = options ?? {};
|
|
21
20
|
}
|
|
22
|
-
|
|
23
|
-
return new PushReadableStream(controller => {
|
|
24
|
-
this.pushReadableControllers.push(controller);
|
|
25
|
-
controller.abortSignal.addEventListener('abort', async () => {
|
|
26
|
-
this._closeRequestedByReadable = true;
|
|
27
|
-
await this.close();
|
|
28
|
-
});
|
|
29
|
-
source({
|
|
30
|
-
abortSignal: controller.abortSignal,
|
|
31
|
-
async enqueue(chunk) {
|
|
32
|
-
await controller.enqueue(chunk);
|
|
33
|
-
},
|
|
34
|
-
close: async () => {
|
|
35
|
-
// The source signals stream ended,
|
|
36
|
-
// usually means the other end closed the connection first.
|
|
37
|
-
controller.close();
|
|
38
|
-
this._closeRequestedByReadable = true;
|
|
39
|
-
await this.close();
|
|
40
|
-
},
|
|
41
|
-
error: async (e) => {
|
|
42
|
-
controller.error(e);
|
|
43
|
-
this._closeRequestedByReadable = true;
|
|
44
|
-
await this.close();
|
|
45
|
-
},
|
|
46
|
-
});
|
|
47
|
-
}, strategy);
|
|
48
|
-
}
|
|
49
|
-
;
|
|
50
|
-
createWrapReadable(wrapper) {
|
|
21
|
+
wrapReadable(readable) {
|
|
51
22
|
return new WrapReadableStream({
|
|
52
|
-
|
|
53
|
-
return getWrappedReadableStream(wrapper);
|
|
54
|
-
},
|
|
55
|
-
close: async () => {
|
|
56
|
-
if ('close' in wrapper) {
|
|
57
|
-
await wrapper.close?.();
|
|
58
|
-
}
|
|
59
|
-
this._closeRequestedByReadable = true;
|
|
60
|
-
await this.close();
|
|
61
|
-
},
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
createReadable(source, strategy) {
|
|
65
|
-
return new ReadableStream({
|
|
66
|
-
start: async (controller) => {
|
|
23
|
+
start: (controller) => {
|
|
67
24
|
this.readableControllers.push(controller);
|
|
68
|
-
|
|
69
|
-
},
|
|
70
|
-
pull: (controller) => {
|
|
71
|
-
return source?.pull?.(controller);
|
|
25
|
+
return readable;
|
|
72
26
|
},
|
|
73
|
-
cancel: async (
|
|
74
|
-
|
|
75
|
-
this._closeRequestedByReadable = true;
|
|
27
|
+
cancel: async () => {
|
|
28
|
+
// cancel means the local peer closes the connection first.
|
|
76
29
|
await this.close();
|
|
77
30
|
},
|
|
78
|
-
|
|
31
|
+
close: async () => {
|
|
32
|
+
// stream end means the remote peer closed the connection first.
|
|
33
|
+
await this.dispose();
|
|
34
|
+
},
|
|
35
|
+
});
|
|
79
36
|
}
|
|
80
37
|
createWritable(sink, strategy) {
|
|
38
|
+
// `WritableStream` has no way to tell if the remote peer has closed the connection.
|
|
39
|
+
// So it only triggers `close`.
|
|
81
40
|
return new WritableStream({
|
|
82
41
|
start: async (controller) => {
|
|
83
42
|
await sink.start?.(controller);
|
|
@@ -88,38 +47,36 @@ export class DuplexStreamFactory {
|
|
|
88
47
|
}
|
|
89
48
|
await sink.write?.(chunk, controller);
|
|
90
49
|
},
|
|
91
|
-
close: async () => {
|
|
92
|
-
await sink.close?.();
|
|
93
|
-
this.close();
|
|
94
|
-
},
|
|
95
50
|
abort: async (reason) => {
|
|
96
51
|
await sink.abort?.(reason);
|
|
97
52
|
await this.close();
|
|
98
53
|
},
|
|
54
|
+
close: async () => {
|
|
55
|
+
await sink.close?.();
|
|
56
|
+
await this.close();
|
|
57
|
+
},
|
|
99
58
|
}, strategy);
|
|
100
59
|
}
|
|
101
|
-
async
|
|
60
|
+
async close() {
|
|
61
|
+
if (this._writableClosed) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
this._writableClosed = true;
|
|
65
|
+
if (await this.options.close?.() !== false) {
|
|
66
|
+
// `close` can return `false` to disable automatic `dispose`.
|
|
67
|
+
await this.dispose();
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
async dispose() {
|
|
71
|
+
this._writableClosed = true;
|
|
102
72
|
this._closed.resolve();
|
|
103
|
-
await this.options.close?.();
|
|
104
73
|
for (const controller of this.readableControllers) {
|
|
105
74
|
try {
|
|
106
75
|
controller.close();
|
|
107
76
|
}
|
|
108
77
|
catch { }
|
|
109
78
|
}
|
|
110
|
-
|
|
111
|
-
try {
|
|
112
|
-
controller.close();
|
|
113
|
-
}
|
|
114
|
-
catch { }
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
async close() {
|
|
118
|
-
this._writableClosed = true;
|
|
119
|
-
if (this._closeRequestedByReadable ||
|
|
120
|
-
!this.options.preventCloseReadableStreams) {
|
|
121
|
-
await this.closeReadableStreams();
|
|
122
|
-
}
|
|
79
|
+
await this.options.dispose?.();
|
|
123
80
|
}
|
|
124
81
|
}
|
|
125
82
|
export class DecodeUtf8Stream extends TransformStream {
|
|
@@ -241,12 +198,12 @@ export class WrapWritableStream extends WritableStream {
|
|
|
241
198
|
});
|
|
242
199
|
}
|
|
243
200
|
}
|
|
244
|
-
function getWrappedReadableStream(wrapper) {
|
|
201
|
+
function getWrappedReadableStream(wrapper, controller) {
|
|
245
202
|
if ('start' in wrapper) {
|
|
246
|
-
return wrapper.start();
|
|
203
|
+
return wrapper.start(controller);
|
|
247
204
|
}
|
|
248
205
|
else if (typeof wrapper === 'function') {
|
|
249
|
-
return wrapper();
|
|
206
|
+
return wrapper(controller);
|
|
250
207
|
}
|
|
251
208
|
else {
|
|
252
209
|
// Can't use `wrapper instanceof ReadableStream`
|
|
@@ -254,24 +211,31 @@ function getWrappedReadableStream(wrapper) {
|
|
|
254
211
|
return wrapper;
|
|
255
212
|
}
|
|
256
213
|
}
|
|
214
|
+
/**
|
|
215
|
+
* This class has multiple usages:
|
|
216
|
+
*
|
|
217
|
+
* 1. Get notified when the stream is cancelled or closed.
|
|
218
|
+
* 2. Synchronously create a `ReadableStream` by asynchronously return another `ReadableStream`.
|
|
219
|
+
* 3. Convert native `ReadableStream`s to polyfilled ones so they can `pipe` between.
|
|
220
|
+
*/
|
|
257
221
|
export class WrapReadableStream extends ReadableStream {
|
|
258
222
|
readable;
|
|
259
223
|
reader;
|
|
260
224
|
constructor(wrapper) {
|
|
261
225
|
super({
|
|
262
|
-
start: async () => {
|
|
226
|
+
start: async (controller) => {
|
|
263
227
|
// `start` is invoked before `ReadableStream`'s constructor finish,
|
|
264
228
|
// so using `this` synchronously causes
|
|
265
229
|
// "Must call super constructor in derived class before accessing 'this' or returning from derived constructor".
|
|
266
230
|
// Queue a microtask to avoid this.
|
|
267
231
|
await Promise.resolve();
|
|
268
|
-
this.readable = await getWrappedReadableStream(wrapper);
|
|
232
|
+
this.readable = await getWrappedReadableStream(wrapper, controller);
|
|
269
233
|
this.reader = this.readable.getReader();
|
|
270
234
|
},
|
|
271
235
|
cancel: async (reason) => {
|
|
272
236
|
await this.reader.cancel(reason);
|
|
273
|
-
if ('
|
|
274
|
-
await wrapper.
|
|
237
|
+
if ('cancel' in wrapper) {
|
|
238
|
+
await wrapper.cancel?.(reason);
|
|
275
239
|
}
|
|
276
240
|
},
|
|
277
241
|
pull: async (controller) => {
|