@yume-chan/adb 0.0.24 → 1.0.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/CHANGELOG.md +36 -1
- package/README.md +4 -1
- package/esm/adb.d.ts +13 -7
- package/esm/adb.d.ts.map +1 -1
- package/esm/adb.js +3 -0
- package/esm/adb.js.map +1 -1
- package/esm/banner.d.ts +7 -6
- package/esm/banner.d.ts.map +1 -1
- package/esm/banner.js +6 -7
- package/esm/banner.js.map +1 -1
- package/esm/commands/framebuffer.d.ts +63 -34
- package/esm/commands/framebuffer.d.ts.map +1 -1
- package/esm/commands/framebuffer.js +35 -33
- package/esm/commands/framebuffer.js.map +1 -1
- package/esm/commands/reverse.d.ts +12 -12
- package/esm/commands/reverse.d.ts.map +1 -1
- package/esm/commands/reverse.js +39 -30
- package/esm/commands/reverse.js.map +1 -1
- package/esm/commands/subprocess/protocols/none.d.ts.map +1 -1
- package/esm/commands/subprocess/protocols/none.js +3 -5
- package/esm/commands/subprocess/protocols/none.js.map +1 -1
- package/esm/commands/subprocess/protocols/shell.d.ts +20 -12
- package/esm/commands/subprocess/protocols/shell.d.ts.map +1 -1
- package/esm/commands/subprocess/protocols/shell.js +16 -21
- package/esm/commands/subprocess/protocols/shell.js.map +1 -1
- package/esm/commands/subprocess/protocols/types.d.ts +6 -6
- package/esm/commands/subprocess/protocols/types.d.ts.map +1 -1
- package/esm/commands/sync/list.d.ts +49 -27
- package/esm/commands/sync/list.d.ts.map +1 -1
- package/esm/commands/sync/list.js +9 -9
- package/esm/commands/sync/list.js.map +1 -1
- package/esm/commands/sync/pull.d.ts +7 -6
- package/esm/commands/sync/pull.d.ts.map +1 -1
- package/esm/commands/sync/pull.js +3 -5
- package/esm/commands/sync/pull.js.map +1 -1
- package/esm/commands/sync/push.d.ts +22 -16
- package/esm/commands/sync/push.d.ts.map +1 -1
- package/esm/commands/sync/push.js +12 -16
- package/esm/commands/sync/push.js.map +1 -1
- package/esm/commands/sync/request.d.ts +19 -17
- package/esm/commands/sync/request.d.ts.map +1 -1
- package/esm/commands/sync/request.js +14 -18
- package/esm/commands/sync/request.js.map +1 -1
- package/esm/commands/sync/response.d.ts +18 -18
- package/esm/commands/sync/response.d.ts.map +1 -1
- package/esm/commands/sync/response.js +20 -19
- package/esm/commands/sync/response.js.map +1 -1
- package/esm/commands/sync/socket.d.ts +1 -1
- package/esm/commands/sync/socket.js +2 -2
- package/esm/commands/sync/socket.js.map +1 -1
- package/esm/commands/sync/stat.d.ts +75 -51
- package/esm/commands/sync/stat.d.ts.map +1 -1
- package/esm/commands/sync/stat.js +73 -67
- package/esm/commands/sync/stat.js.map +1 -1
- package/esm/commands/sync/sync.d.ts +14 -14
- package/esm/commands/sync/sync.d.ts.map +1 -1
- package/esm/commands/sync/sync.js +4 -7
- package/esm/commands/sync/sync.js.map +1 -1
- package/esm/commands/tcpip.d.ts +0 -1
- package/esm/commands/tcpip.d.ts.map +1 -1
- package/esm/commands/tcpip.js +8 -8
- package/esm/commands/tcpip.js.map +1 -1
- package/esm/daemon/auth.d.ts +8 -7
- package/esm/daemon/auth.d.ts.map +1 -1
- package/esm/daemon/auth.js +7 -8
- package/esm/daemon/auth.js.map +1 -1
- package/esm/daemon/crypto.d.ts +1 -1
- package/esm/daemon/crypto.d.ts.map +1 -1
- package/esm/daemon/crypto.js +1 -0
- package/esm/daemon/crypto.js.map +1 -1
- package/esm/daemon/device.d.ts +2 -2
- package/esm/daemon/device.d.ts.map +1 -1
- package/esm/daemon/dispatcher.js +6 -6
- package/esm/daemon/dispatcher.js.map +1 -1
- package/esm/daemon/packet.d.ts +46 -30
- package/esm/daemon/packet.d.ts.map +1 -1
- package/esm/daemon/packet.js +24 -21
- package/esm/daemon/packet.js.map +1 -1
- package/esm/daemon/socket.d.ts +1 -6
- package/esm/daemon/socket.d.ts.map +1 -1
- package/esm/daemon/socket.js +4 -27
- package/esm/daemon/socket.js.map +1 -1
- package/esm/daemon/transport.d.ts +14 -14
- package/esm/daemon/transport.d.ts.map +1 -1
- package/esm/daemon/transport.js +6 -8
- package/esm/daemon/transport.js.map +1 -1
- package/esm/device-observer.d.ts +10 -0
- package/esm/device-observer.d.ts.map +1 -0
- package/esm/device-observer.js +2 -0
- package/esm/device-observer.js.map +1 -0
- package/esm/features.d.ts +12 -11
- package/esm/features.d.ts.map +1 -1
- package/esm/features.js +11 -12
- package/esm/features.js.map +1 -1
- package/esm/index.d.ts +1 -0
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +1 -0
- package/esm/index.js.map +1 -1
- package/esm/server/client.d.ts +34 -22
- package/esm/server/client.d.ts.map +1 -1
- package/esm/server/client.js +151 -136
- package/esm/server/client.js.map +1 -1
- package/esm/server/transport.d.ts +2 -2
- package/esm/server/transport.d.ts.map +1 -1
- package/esm/server/transport.js +1 -3
- package/esm/server/transport.js.map +1 -1
- package/esm/utils/base64.d.ts.map +1 -1
- package/esm/utils/base64.js +19 -16
- package/esm/utils/base64.js.map +1 -1
- package/esm/utils/no-op.d.ts.map +1 -1
- package/esm/utils/no-op.js +1 -0
- package/esm/utils/no-op.js.map +1 -1
- package/package.json +14 -17
- package/src/adb.ts +13 -7
- package/src/banner.ts +8 -6
- package/src/commands/framebuffer.ts +44 -35
- package/src/commands/reverse.ts +49 -31
- package/src/commands/subprocess/protocols/none.ts +3 -5
- package/src/commands/subprocess/protocols/shell.ts +26 -24
- package/src/commands/subprocess/protocols/types.ts +6 -6
- package/src/commands/sync/list.ts +20 -13
- package/src/commands/sync/pull.ts +8 -7
- package/src/commands/sync/push.ts +20 -16
- package/src/commands/sync/request.ts +18 -19
- package/src/commands/sync/response.ts +28 -29
- package/src/commands/sync/socket.ts +2 -2
- package/src/commands/sync/stat.ts +93 -71
- package/src/commands/sync/sync.ts +4 -8
- package/src/commands/tcpip.ts +8 -8
- package/src/daemon/auth.ts +11 -9
- package/src/daemon/crypto.ts +2 -0
- package/src/daemon/device.ts +2 -2
- package/src/daemon/dispatcher.ts +6 -6
- package/src/daemon/packet.ts +37 -25
- package/src/daemon/socket.ts +4 -27
- package/src/daemon/transport.ts +36 -35
- package/src/device-observer.ts +10 -0
- package/src/features.ts +13 -11
- package/src/index.ts +1 -0
- package/src/server/client.ts +185 -160
- package/src/server/transport.ts +3 -5
- package/src/utils/base64.ts +26 -18
- package/src/utils/no-op.ts +1 -0
- package/tsconfig.build.json +1 -12
- package/tsconfig.build.tsbuildinfo +1 -1
- package/CHANGELOG.json +0 -298
package/src/server/client.ts
CHANGED
|
@@ -1,34 +1,33 @@
|
|
|
1
1
|
// cspell:ignore tport
|
|
2
2
|
|
|
3
|
+
import type { MaybePromiseLike } from "@yume-chan/async";
|
|
3
4
|
import { PromiseResolver } from "@yume-chan/async";
|
|
5
|
+
import type { Event } from "@yume-chan/event";
|
|
6
|
+
import { EventEmitter } from "@yume-chan/event";
|
|
4
7
|
import { getUint64LittleEndian } from "@yume-chan/no-data-view";
|
|
5
8
|
import type {
|
|
6
9
|
AbortSignal,
|
|
10
|
+
MaybeConsumable,
|
|
7
11
|
ReadableWritablePair,
|
|
8
12
|
WritableStreamDefaultWriter,
|
|
9
13
|
} from "@yume-chan/stream-extra";
|
|
10
14
|
import {
|
|
11
15
|
BufferedReadableStream,
|
|
12
|
-
|
|
13
|
-
|
|
16
|
+
tryCancel,
|
|
17
|
+
tryClose,
|
|
14
18
|
} from "@yume-chan/stream-extra";
|
|
15
|
-
import type { ValueOrPromise } from "@yume-chan/struct";
|
|
16
19
|
import {
|
|
17
|
-
|
|
18
|
-
SyncPromise,
|
|
20
|
+
bipedal,
|
|
19
21
|
decodeUtf8,
|
|
20
22
|
encodeUtf8,
|
|
23
|
+
TextDecoder,
|
|
21
24
|
} from "@yume-chan/struct";
|
|
22
25
|
|
|
23
26
|
import type { AdbIncomingSocketHandler, AdbSocket, Closeable } from "../adb.js";
|
|
24
27
|
import { AdbBanner } from "../banner.js";
|
|
28
|
+
import type { DeviceObserver as DeviceObserverBase } from "../device-observer.js";
|
|
25
29
|
import type { AdbFeature } from "../features.js";
|
|
26
|
-
import {
|
|
27
|
-
NOOP,
|
|
28
|
-
hexToNumber,
|
|
29
|
-
sequenceEqual,
|
|
30
|
-
write4HexDigits,
|
|
31
|
-
} from "../utils/index.js";
|
|
30
|
+
import { hexToNumber, sequenceEqual, write4HexDigits } from "../utils/index.js";
|
|
32
31
|
|
|
33
32
|
import { AdbServerTransport } from "./transport.js";
|
|
34
33
|
|
|
@@ -46,44 +45,30 @@ class AdbServerStream {
|
|
|
46
45
|
this.#writer = connection.writable.getWriter();
|
|
47
46
|
}
|
|
48
47
|
|
|
49
|
-
readExactly(length: number):
|
|
48
|
+
readExactly(length: number): MaybePromiseLike<Uint8Array> {
|
|
50
49
|
return this.#buffered.readExactly(length);
|
|
51
50
|
}
|
|
52
51
|
|
|
53
|
-
readString() {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
52
|
+
readString = bipedal(function* (this: AdbServerStream, then) {
|
|
53
|
+
const data = yield* then(this.readExactly(4));
|
|
54
|
+
const length = hexToNumber(data);
|
|
55
|
+
if (length === 0) {
|
|
56
|
+
return "";
|
|
57
|
+
} else {
|
|
58
|
+
const decoder = new TextDecoder();
|
|
59
|
+
let result = "";
|
|
60
|
+
const iterator = this.#buffered.iterateExactly(length);
|
|
61
|
+
while (true) {
|
|
62
|
+
const { done, value } = iterator.next();
|
|
63
|
+
if (done) {
|
|
64
|
+
break;
|
|
61
65
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
//
|
|
69
|
-
// ```
|
|
70
|
-
// const decoder = new TextDecoder();
|
|
71
|
-
// let result = '';
|
|
72
|
-
// for await (const chunk of stream.iterateExactly(length)) {
|
|
73
|
-
// result += decoder.decode(chunk, { stream: true });
|
|
74
|
-
// }
|
|
75
|
-
// result += decoder.decode();
|
|
76
|
-
// return result;
|
|
77
|
-
// ```
|
|
78
|
-
//
|
|
79
|
-
// Although, it will be super complex to use `SyncPromise` with async iterator,
|
|
80
|
-
// `stream.iterateExactly` need to return an
|
|
81
|
-
// `Iterator<Uint8Array | Promise<Uint8Array>>` instead of a true async iterator.
|
|
82
|
-
// Maybe `SyncPromise` should support async iterators directly.
|
|
83
|
-
return decodeUtf8(buffer);
|
|
84
|
-
})
|
|
85
|
-
.valueOrPromise();
|
|
86
|
-
}
|
|
66
|
+
result += decoder.decode(yield* then(value), { stream: true });
|
|
67
|
+
}
|
|
68
|
+
result += decoder.decode();
|
|
69
|
+
return result;
|
|
70
|
+
}
|
|
71
|
+
});
|
|
87
72
|
|
|
88
73
|
async writeString(value: string): Promise<void> {
|
|
89
74
|
// TODO: investigate using `encodeUtf8("0000" + value)` then modifying the length
|
|
@@ -123,26 +108,97 @@ class AdbServerStream {
|
|
|
123
108
|
}
|
|
124
109
|
|
|
125
110
|
async dispose() {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
await this.#connection.close();
|
|
130
|
-
} catch {
|
|
131
|
-
// ignore
|
|
132
|
-
}
|
|
111
|
+
void tryCancel(this.#buffered);
|
|
112
|
+
void tryClose(this.#writer);
|
|
113
|
+
await this.#connection.close();
|
|
133
114
|
}
|
|
134
115
|
}
|
|
135
116
|
|
|
117
|
+
/**
|
|
118
|
+
* Client for the ADB Server.
|
|
119
|
+
*/
|
|
136
120
|
export class AdbServerClient {
|
|
137
121
|
static readonly VERSION = 41;
|
|
138
122
|
|
|
123
|
+
static parseDeviceList(value: string): AdbServerClient.Device[] {
|
|
124
|
+
const devices: AdbServerClient.Device[] = [];
|
|
125
|
+
for (const line of value.split("\n")) {
|
|
126
|
+
if (!line) {
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const parts = line.split(" ").filter(Boolean);
|
|
131
|
+
const serial = parts[0]!;
|
|
132
|
+
const status = parts[1]!;
|
|
133
|
+
if (status !== "device" && status !== "unauthorized") {
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
let product: string | undefined;
|
|
138
|
+
let model: string | undefined;
|
|
139
|
+
let device: string | undefined;
|
|
140
|
+
let transportId: bigint | undefined;
|
|
141
|
+
for (let i = 2; i < parts.length; i += 1) {
|
|
142
|
+
const [key, value] = parts[i]!.split(":");
|
|
143
|
+
switch (key) {
|
|
144
|
+
case "product":
|
|
145
|
+
product = value;
|
|
146
|
+
break;
|
|
147
|
+
case "model":
|
|
148
|
+
model = value;
|
|
149
|
+
break;
|
|
150
|
+
case "device":
|
|
151
|
+
device = value;
|
|
152
|
+
break;
|
|
153
|
+
case "transport_id":
|
|
154
|
+
transportId = BigInt(value!);
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
if (!transportId) {
|
|
159
|
+
throw new Error(`No transport id for device ${serial}`);
|
|
160
|
+
}
|
|
161
|
+
devices.push({
|
|
162
|
+
serial,
|
|
163
|
+
authenticating: status === "unauthorized",
|
|
164
|
+
product,
|
|
165
|
+
model,
|
|
166
|
+
device,
|
|
167
|
+
transportId,
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
return devices;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
static formatDeviceService(
|
|
174
|
+
device: AdbServerClient.DeviceSelector,
|
|
175
|
+
command: string,
|
|
176
|
+
) {
|
|
177
|
+
if (!device) {
|
|
178
|
+
return `host:${command}`;
|
|
179
|
+
}
|
|
180
|
+
if ("transportId" in device) {
|
|
181
|
+
return `host-transport-id:${device.transportId}:${command}`;
|
|
182
|
+
}
|
|
183
|
+
if ("serial" in device) {
|
|
184
|
+
return `host-serial:${device.serial}:${command}`;
|
|
185
|
+
}
|
|
186
|
+
if ("usb" in device) {
|
|
187
|
+
return `host-usb:${command}`;
|
|
188
|
+
}
|
|
189
|
+
if ("tcp" in device) {
|
|
190
|
+
return `host-local:${command}`;
|
|
191
|
+
}
|
|
192
|
+
throw new TypeError("Invalid device selector");
|
|
193
|
+
}
|
|
194
|
+
|
|
139
195
|
readonly connector: AdbServerClient.ServerConnector;
|
|
140
196
|
|
|
141
197
|
readonly wireless = new AdbServerClient.WirelessCommands(this);
|
|
142
198
|
readonly mDns = new AdbServerClient.MDnsCommands(this);
|
|
143
199
|
|
|
144
|
-
constructor(
|
|
145
|
-
this.connector =
|
|
200
|
+
constructor(connector: AdbServerClient.ServerConnector) {
|
|
201
|
+
this.connector = connector;
|
|
146
202
|
}
|
|
147
203
|
|
|
148
204
|
async createConnection(
|
|
@@ -214,118 +270,79 @@ export class AdbServerClient {
|
|
|
214
270
|
}
|
|
215
271
|
}
|
|
216
272
|
|
|
217
|
-
parseDeviceList(value: string): AdbServerClient.Device[] {
|
|
218
|
-
const devices: AdbServerClient.Device[] = [];
|
|
219
|
-
for (const line of value.split("\n")) {
|
|
220
|
-
if (!line) {
|
|
221
|
-
continue;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
const parts = line.split(" ").filter(Boolean);
|
|
225
|
-
const serial = parts[0]!;
|
|
226
|
-
const status = parts[1]!;
|
|
227
|
-
if (status !== "device" && status !== "unauthorized") {
|
|
228
|
-
continue;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
let product: string | undefined;
|
|
232
|
-
let model: string | undefined;
|
|
233
|
-
let device: string | undefined;
|
|
234
|
-
let transportId: bigint | undefined;
|
|
235
|
-
for (let i = 2; i < parts.length; i += 1) {
|
|
236
|
-
const [key, value] = parts[i]!.split(":");
|
|
237
|
-
switch (key) {
|
|
238
|
-
case "product":
|
|
239
|
-
product = value;
|
|
240
|
-
break;
|
|
241
|
-
case "model":
|
|
242
|
-
model = value;
|
|
243
|
-
break;
|
|
244
|
-
case "device":
|
|
245
|
-
device = value;
|
|
246
|
-
break;
|
|
247
|
-
case "transport_id":
|
|
248
|
-
transportId = BigInt(value!);
|
|
249
|
-
break;
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
if (!transportId) {
|
|
253
|
-
throw new Error(`No transport id for device ${serial}`);
|
|
254
|
-
}
|
|
255
|
-
devices.push({
|
|
256
|
-
serial,
|
|
257
|
-
authenticating: status === "unauthorized",
|
|
258
|
-
product,
|
|
259
|
-
model,
|
|
260
|
-
device,
|
|
261
|
-
transportId,
|
|
262
|
-
});
|
|
263
|
-
}
|
|
264
|
-
return devices;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
273
|
/**
|
|
268
|
-
*
|
|
274
|
+
* Get a list of connected devices from ADB Server.
|
|
275
|
+
*
|
|
276
|
+
* Equivalent ADB Command: `adb devices -l`
|
|
269
277
|
*/
|
|
270
278
|
async getDevices(): Promise<AdbServerClient.Device[]> {
|
|
271
279
|
const connection = await this.createConnection("host:devices-l");
|
|
272
280
|
try {
|
|
273
281
|
const response = await connection.readString();
|
|
274
|
-
return
|
|
282
|
+
return AdbServerClient.parseDeviceList(response);
|
|
275
283
|
} finally {
|
|
276
284
|
await connection.dispose();
|
|
277
285
|
}
|
|
278
286
|
}
|
|
279
287
|
|
|
280
288
|
/**
|
|
281
|
-
*
|
|
282
|
-
*
|
|
283
|
-
* @param signal An optional `AbortSignal` to stop tracking
|
|
284
|
-
*
|
|
285
|
-
* When `signal` is aborted, `trackDevices` will return normally, instead of throwing `signal.reason`.
|
|
289
|
+
* Monitors device list changes.
|
|
286
290
|
*/
|
|
287
|
-
async
|
|
288
|
-
signal?: AbortSignal,
|
|
289
|
-
): AsyncGenerator<AdbServerClient.Device[], void, void> {
|
|
291
|
+
async trackDevices(): Promise<AdbServerClient.DeviceObserver> {
|
|
290
292
|
const connection = await this.createConnection("host:track-devices-l");
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
293
|
+
|
|
294
|
+
let current: AdbServerClient.Device[] = [];
|
|
295
|
+
const onError = new EventEmitter<Error>();
|
|
296
|
+
const onDeviceAdd = new EventEmitter<AdbServerClient.Device[]>();
|
|
297
|
+
const onDeviceRemove = new EventEmitter<AdbServerClient.Device[]>();
|
|
298
|
+
const onListChange = new EventEmitter<AdbServerClient.Device[]>();
|
|
299
|
+
|
|
300
|
+
void (async () => {
|
|
301
|
+
try {
|
|
302
|
+
while (true) {
|
|
303
|
+
const response = await connection.readString();
|
|
304
|
+
const next = AdbServerClient.parseDeviceList(response);
|
|
305
|
+
|
|
306
|
+
const added: AdbServerClient.Device[] = [];
|
|
307
|
+
for (const nextDevice of next) {
|
|
308
|
+
const index = current.findIndex(
|
|
309
|
+
(device) =>
|
|
310
|
+
device.transportId === nextDevice.transportId,
|
|
311
|
+
);
|
|
312
|
+
if (index === -1) {
|
|
313
|
+
added.push(nextDevice);
|
|
314
|
+
continue;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
current[index] = current[current.length - 1]!;
|
|
318
|
+
current.length -= 1;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
if (added.length) {
|
|
322
|
+
onDeviceAdd.fire(added);
|
|
323
|
+
}
|
|
324
|
+
if (current.length) {
|
|
325
|
+
onDeviceRemove.fire(current);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
current = next;
|
|
329
|
+
onListChange.fire(current);
|
|
330
|
+
}
|
|
331
|
+
} catch (e) {
|
|
332
|
+
onError.fire(e as Error);
|
|
303
333
|
}
|
|
304
|
-
}
|
|
305
|
-
await connection.dispose();
|
|
306
|
-
}
|
|
307
|
-
}
|
|
334
|
+
})();
|
|
308
335
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
}
|
|
319
|
-
if ("serial" in device) {
|
|
320
|
-
return `host-serial:${device.serial}:${command}`;
|
|
321
|
-
}
|
|
322
|
-
if ("usb" in device) {
|
|
323
|
-
return `host-usb:${command}`;
|
|
324
|
-
}
|
|
325
|
-
if ("tcp" in device) {
|
|
326
|
-
return `host-local:${command}`;
|
|
327
|
-
}
|
|
328
|
-
throw new TypeError("Invalid device selector");
|
|
336
|
+
return {
|
|
337
|
+
onError: onError.event,
|
|
338
|
+
onDeviceAdd: onDeviceAdd.event,
|
|
339
|
+
onDeviceRemove: onDeviceRemove.event,
|
|
340
|
+
onListChange: onListChange.event,
|
|
341
|
+
get current() {
|
|
342
|
+
return current;
|
|
343
|
+
},
|
|
344
|
+
stop: () => connection.dispose(),
|
|
345
|
+
};
|
|
329
346
|
}
|
|
330
347
|
|
|
331
348
|
/**
|
|
@@ -335,7 +352,7 @@ export class AdbServerClient {
|
|
|
335
352
|
const connection = await this.createConnection(
|
|
336
353
|
device === "offline"
|
|
337
354
|
? "host:reconnect-offline"
|
|
338
|
-
:
|
|
355
|
+
: AdbServerClient.formatDeviceService(device, "reconnect"),
|
|
339
356
|
);
|
|
340
357
|
try {
|
|
341
358
|
await connection.readString();
|
|
@@ -437,9 +454,7 @@ export class AdbServerClient {
|
|
|
437
454
|
transportId,
|
|
438
455
|
service,
|
|
439
456
|
readable: socket.readable,
|
|
440
|
-
writable:
|
|
441
|
-
socket.writable,
|
|
442
|
-
).bePipedThroughFrom(new MaybeConsumable.UnwrapStream()),
|
|
457
|
+
writable: socket.writable,
|
|
443
458
|
get closed() {
|
|
444
459
|
return socket.closed;
|
|
445
460
|
},
|
|
@@ -485,7 +500,7 @@ export class AdbServerClient {
|
|
|
485
500
|
|
|
486
501
|
// `waitFor` can't use `connectDevice`, because the device
|
|
487
502
|
// might not be available yet.
|
|
488
|
-
const service =
|
|
503
|
+
const service = AdbServerClient.formatDeviceService(
|
|
489
504
|
device,
|
|
490
505
|
`wait-for-${type}-${state}`,
|
|
491
506
|
);
|
|
@@ -498,6 +513,9 @@ export class AdbServerClient {
|
|
|
498
513
|
}
|
|
499
514
|
}
|
|
500
515
|
|
|
516
|
+
/**
|
|
517
|
+
* Creates an ADB Transport for the specified device.
|
|
518
|
+
*/
|
|
501
519
|
async createTransport(
|
|
502
520
|
device: AdbServerClient.DeviceSelector,
|
|
503
521
|
): Promise<AdbServerTransport> {
|
|
@@ -562,7 +580,7 @@ export namespace AdbServerClient {
|
|
|
562
580
|
}
|
|
563
581
|
|
|
564
582
|
export interface ServerConnection
|
|
565
|
-
extends ReadableWritablePair<Uint8Array, Uint8Array
|
|
583
|
+
extends ReadableWritablePair<Uint8Array, MaybeConsumable<Uint8Array>>,
|
|
566
584
|
Closeable {
|
|
567
585
|
get closed(): Promise<void>;
|
|
568
586
|
}
|
|
@@ -570,22 +588,25 @@ export namespace AdbServerClient {
|
|
|
570
588
|
export interface ServerConnector {
|
|
571
589
|
connect(
|
|
572
590
|
options?: ServerConnectionOptions,
|
|
573
|
-
):
|
|
591
|
+
): MaybePromiseLike<ServerConnection>;
|
|
574
592
|
|
|
575
593
|
addReverseTunnel(
|
|
576
594
|
handler: AdbIncomingSocketHandler,
|
|
577
595
|
address?: string,
|
|
578
|
-
):
|
|
596
|
+
): MaybePromiseLike<string>;
|
|
579
597
|
|
|
580
|
-
removeReverseTunnel(address: string):
|
|
598
|
+
removeReverseTunnel(address: string): MaybePromiseLike<void>;
|
|
581
599
|
|
|
582
|
-
clearReverseTunnels():
|
|
600
|
+
clearReverseTunnels(): MaybePromiseLike<void>;
|
|
583
601
|
}
|
|
584
602
|
|
|
585
603
|
export interface Socket extends AdbSocket {
|
|
586
604
|
transportId: bigint;
|
|
587
605
|
}
|
|
588
606
|
|
|
607
|
+
/**
|
|
608
|
+
* A union type for selecting a device.
|
|
609
|
+
*/
|
|
589
610
|
export type DeviceSelector =
|
|
590
611
|
| { transportId: bigint }
|
|
591
612
|
| { serial: string }
|
|
@@ -732,4 +753,8 @@ export namespace AdbServerClient {
|
|
|
732
753
|
}
|
|
733
754
|
}
|
|
734
755
|
}
|
|
756
|
+
|
|
757
|
+
export interface DeviceObserver extends DeviceObserverBase<Device> {
|
|
758
|
+
onError: Event<Error>;
|
|
759
|
+
}
|
|
735
760
|
}
|
package/src/server/transport.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import type { MaybePromiseLike } from "@yume-chan/async";
|
|
1
2
|
import { PromiseResolver } from "@yume-chan/async";
|
|
2
3
|
import { AbortController } from "@yume-chan/stream-extra";
|
|
3
|
-
import type { ValueOrPromise } from "@yume-chan/struct";
|
|
4
4
|
|
|
5
5
|
import type {
|
|
6
6
|
AdbIncomingSocketHandler,
|
|
@@ -76,9 +76,7 @@ export class AdbServerTransport implements AdbTransport {
|
|
|
76
76
|
|
|
77
77
|
async connect(service: string): Promise<AdbSocket> {
|
|
78
78
|
return await this.#client.createDeviceConnection(
|
|
79
|
-
{
|
|
80
|
-
transportId: this.transportId,
|
|
81
|
-
},
|
|
79
|
+
{ transportId: this.transportId },
|
|
82
80
|
service,
|
|
83
81
|
);
|
|
84
82
|
}
|
|
@@ -98,7 +96,7 @@ export class AdbServerTransport implements AdbTransport {
|
|
|
98
96
|
await this.#client.connector.clearReverseTunnels();
|
|
99
97
|
}
|
|
100
98
|
|
|
101
|
-
close():
|
|
99
|
+
close(): MaybePromiseLike<void> {
|
|
102
100
|
this.#closed.resolve();
|
|
103
101
|
this.#waitAbortController.abort();
|
|
104
102
|
}
|
package/src/utils/base64.ts
CHANGED
|
@@ -1,23 +1,31 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
const [charToIndex, indexToChar, paddingChar] = /* #__PURE__ */ (() => {
|
|
2
|
+
// Array is faster than object literal or `Map`
|
|
3
|
+
const charToIndex: number[] = [];
|
|
4
|
+
const indexToChar: number[] = [];
|
|
5
|
+
const paddingChar = "=".charCodeAt(0);
|
|
6
|
+
|
|
7
|
+
function addRange(start: string, end: string) {
|
|
8
|
+
const charCodeStart = start.charCodeAt(0);
|
|
9
|
+
const charCodeEnd = end.charCodeAt(0);
|
|
10
|
+
|
|
11
|
+
for (
|
|
12
|
+
let charCode = charCodeStart;
|
|
13
|
+
charCode <= charCodeEnd;
|
|
14
|
+
charCode += 1
|
|
15
|
+
) {
|
|
16
|
+
charToIndex[charCode] = indexToChar.length;
|
|
17
|
+
indexToChar.push(charCode);
|
|
18
|
+
}
|
|
13
19
|
}
|
|
14
|
-
}
|
|
15
20
|
|
|
16
|
-
addRange("A", "Z");
|
|
17
|
-
addRange("a", "z");
|
|
18
|
-
addRange("0", "9");
|
|
19
|
-
addRange("+", "+");
|
|
20
|
-
addRange("/", "/");
|
|
21
|
+
addRange("A", "Z");
|
|
22
|
+
addRange("a", "z");
|
|
23
|
+
addRange("0", "9");
|
|
24
|
+
addRange("+", "+");
|
|
25
|
+
addRange("/", "/");
|
|
26
|
+
|
|
27
|
+
return [charToIndex, indexToChar, paddingChar];
|
|
28
|
+
})();
|
|
21
29
|
|
|
22
30
|
/**
|
|
23
31
|
* Calculate the required length of the output buffer for the given input length.
|
package/src/utils/no-op.ts
CHANGED
package/tsconfig.build.json
CHANGED
|
@@ -1,14 +1,3 @@
|
|
|
1
1
|
{
|
|
2
|
-
"extends": "./node_modules/@yume-chan/tsconfig/tsconfig.base.json"
|
|
3
|
-
"references": [
|
|
4
|
-
{
|
|
5
|
-
"path": "../event/tsconfig.build.json"
|
|
6
|
-
},
|
|
7
|
-
{
|
|
8
|
-
"path": "../stream-extra/tsconfig.build.json"
|
|
9
|
-
},
|
|
10
|
-
{
|
|
11
|
-
"path": "../struct/tsconfig.build.json"
|
|
12
|
-
}
|
|
13
|
-
]
|
|
2
|
+
"extends": "./node_modules/@yume-chan/tsconfig/tsconfig.base.json"
|
|
14
3
|
}
|