@yume-chan/adb 2.0.1 → 2.3.1
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 +95 -77
- package/README.md +5 -2
- package/esm/adb.d.ts +2 -2
- package/esm/adb.d.ts.map +1 -1
- package/esm/adb.js +2 -0
- package/esm/adb.js.map +1 -1
- package/esm/banner.d.ts +2 -2
- package/esm/banner.d.ts.map +1 -1
- package/esm/banner.js.map +1 -1
- package/esm/commands/subprocess/none/service.d.ts +1 -1
- package/esm/commands/subprocess/none/service.d.ts.map +1 -1
- package/esm/commands/subprocess/none/service.js +3 -1
- package/esm/commands/subprocess/none/service.js.map +1 -1
- package/esm/commands/subprocess/none/spawner.d.ts +4 -4
- package/esm/commands/subprocess/none/spawner.d.ts.map +1 -1
- package/esm/commands/subprocess/none/spawner.js.map +1 -1
- package/esm/commands/subprocess/shell/service.d.ts +1 -1
- package/esm/commands/subprocess/shell/service.d.ts.map +1 -1
- package/esm/commands/subprocess/shell/spawner.d.ts +4 -4
- package/esm/commands/subprocess/shell/spawner.d.ts.map +1 -1
- package/esm/commands/subprocess/shell/spawner.js.map +1 -1
- package/esm/daemon/auth.d.ts +1 -1
- package/esm/daemon/auth.d.ts.map +1 -1
- package/esm/daemon/auth.js.map +1 -1
- package/esm/daemon/crypto.d.ts +2 -2
- package/esm/daemon/crypto.d.ts.map +1 -1
- package/esm/daemon/crypto.js.map +1 -1
- package/esm/daemon/transport.d.ts +2 -2
- package/esm/daemon/transport.d.ts.map +1 -1
- package/esm/daemon/transport.js.map +1 -1
- package/esm/server/client.d.ts +10 -4
- package/esm/server/client.d.ts.map +1 -1
- package/esm/server/client.js +18 -6
- package/esm/server/client.js.map +1 -1
- package/esm/server/observer.d.ts +6 -1
- package/esm/server/observer.d.ts.map +1 -1
- package/esm/server/observer.js +31 -8
- package/esm/server/observer.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.map +1 -1
- package/esm/utils/array-buffer.d.ts +2 -0
- package/esm/utils/array-buffer.d.ts.map +1 -0
- package/esm/utils/array-buffer.js +9 -0
- package/esm/utils/array-buffer.js.map +1 -0
- package/esm/utils/base64.d.ts +2 -2
- package/esm/utils/base64.d.ts.map +1 -1
- package/esm/utils/index.d.ts +1 -0
- package/esm/utils/index.d.ts.map +1 -1
- package/esm/utils/index.js +1 -0
- package/esm/utils/index.js.map +1 -1
- package/package.json +6 -6
- package/src/adb.ts +5 -3
- package/src/banner.ts +2 -2
- package/src/commands/subprocess/none/service.ts +5 -2
- package/src/commands/subprocess/none/spawner.ts +5 -5
- package/src/commands/subprocess/shell/service.ts +1 -1
- package/src/commands/subprocess/shell/spawner.ts +5 -5
- package/src/commands/sync/response.ts +1 -1
- package/src/daemon/auth.ts +1 -1
- package/src/daemon/crypto.ts +7 -2
- package/src/daemon/transport.ts +2 -2
- package/src/server/client.ts +30 -8
- package/src/server/observer.ts +62 -15
- package/src/server/transport.ts +1 -1
- package/src/utils/array-buffer.ts +9 -0
- package/src/utils/base64.ts +2 -2
- package/src/utils/index.ts +1 -0
- package/tsconfig.build.tsbuildinfo +1 -1
package/src/banner.ts
CHANGED
|
@@ -66,7 +66,7 @@ export class AdbBanner {
|
|
|
66
66
|
return this.#device;
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
readonly #features: AdbFeature[] = [];
|
|
69
|
+
readonly #features: readonly AdbFeature[] = [];
|
|
70
70
|
get features() {
|
|
71
71
|
return this.#features;
|
|
72
72
|
}
|
|
@@ -75,7 +75,7 @@ export class AdbBanner {
|
|
|
75
75
|
product: string | undefined,
|
|
76
76
|
model: string | undefined,
|
|
77
77
|
device: string | undefined,
|
|
78
|
-
features: AdbFeature[],
|
|
78
|
+
features: readonly AdbFeature[],
|
|
79
79
|
) {
|
|
80
80
|
this.#product = product;
|
|
81
81
|
this.#model = model;
|
|
@@ -28,7 +28,9 @@ export class AdbNoneProtocolSubprocessService extends AdbNoneProtocolSpawner {
|
|
|
28
28
|
this.#adb = adb;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
async pty(
|
|
31
|
+
async pty(
|
|
32
|
+
command?: string | readonly string[],
|
|
33
|
+
): Promise<AdbNoneProtocolPtyProcess> {
|
|
32
34
|
if (command === undefined) {
|
|
33
35
|
command = "";
|
|
34
36
|
} else if (Array.isArray(command)) {
|
|
@@ -36,7 +38,8 @@ export class AdbNoneProtocolSubprocessService extends AdbNoneProtocolSpawner {
|
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
return new AdbNoneProtocolPtyProcess(
|
|
39
|
-
|
|
41
|
+
// https://github.com/microsoft/typescript/issues/17002
|
|
42
|
+
await this.#adb.createSocket(`shell:${command as string}`),
|
|
40
43
|
);
|
|
41
44
|
}
|
|
42
45
|
}
|
|
@@ -28,13 +28,13 @@ export interface AdbNoneProtocolProcess {
|
|
|
28
28
|
|
|
29
29
|
export class AdbNoneProtocolSpawner {
|
|
30
30
|
readonly #spawn: (
|
|
31
|
-
command: string[],
|
|
31
|
+
command: readonly string[],
|
|
32
32
|
signal: AbortSignal | undefined,
|
|
33
33
|
) => Promise<AdbNoneProtocolProcess>;
|
|
34
34
|
|
|
35
35
|
constructor(
|
|
36
36
|
spawn: (
|
|
37
|
-
command: string[],
|
|
37
|
+
command: readonly string[],
|
|
38
38
|
signal: AbortSignal | undefined,
|
|
39
39
|
) => Promise<AdbNoneProtocolProcess>,
|
|
40
40
|
) {
|
|
@@ -42,7 +42,7 @@ export class AdbNoneProtocolSpawner {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
spawn(
|
|
45
|
-
command: string | string[],
|
|
45
|
+
command: string | readonly string[],
|
|
46
46
|
signal?: AbortSignal,
|
|
47
47
|
): Promise<AdbNoneProtocolProcess> {
|
|
48
48
|
signal?.throwIfAborted();
|
|
@@ -54,12 +54,12 @@ export class AdbNoneProtocolSpawner {
|
|
|
54
54
|
return this.#spawn(command, signal);
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
async spawnWait(command: string | string[]): Promise<Uint8Array> {
|
|
57
|
+
async spawnWait(command: string | readonly string[]): Promise<Uint8Array> {
|
|
58
58
|
const process = await this.spawn(command);
|
|
59
59
|
return await process.output.pipeThrough(new ConcatBufferStream());
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
async spawnWaitText(command: string | string[]): Promise<string> {
|
|
62
|
+
async spawnWaitText(command: string | readonly string[]): Promise<string> {
|
|
63
63
|
const process = await this.spawn(command);
|
|
64
64
|
return await process.output
|
|
65
65
|
.pipeThrough(new TextDecoderStream())
|
|
@@ -32,7 +32,7 @@ export class AdbShellProtocolSubprocessService extends AdbShellProtocolSpawner {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
async pty(options?: {
|
|
35
|
-
command?: string | string[] | undefined;
|
|
35
|
+
command?: string | readonly string[] | undefined;
|
|
36
36
|
terminalType?: string;
|
|
37
37
|
}): Promise<AdbShellProtocolPtyProcess> {
|
|
38
38
|
let service = "shell,v2,pty";
|
|
@@ -26,13 +26,13 @@ export interface AdbShellProtocolProcess {
|
|
|
26
26
|
|
|
27
27
|
export class AdbShellProtocolSpawner {
|
|
28
28
|
readonly #spawn: (
|
|
29
|
-
command: string[],
|
|
29
|
+
command: readonly string[],
|
|
30
30
|
signal: AbortSignal | undefined,
|
|
31
31
|
) => Promise<AdbShellProtocolProcess>;
|
|
32
32
|
|
|
33
33
|
constructor(
|
|
34
34
|
spawn: (
|
|
35
|
-
command: string[],
|
|
35
|
+
command: readonly string[],
|
|
36
36
|
signal: AbortSignal | undefined,
|
|
37
37
|
) => Promise<AdbShellProtocolProcess>,
|
|
38
38
|
) {
|
|
@@ -40,7 +40,7 @@ export class AdbShellProtocolSpawner {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
spawn(
|
|
43
|
-
command: string | string[],
|
|
43
|
+
command: string | readonly string[],
|
|
44
44
|
signal?: AbortSignal,
|
|
45
45
|
): Promise<AdbShellProtocolProcess> {
|
|
46
46
|
signal?.throwIfAborted();
|
|
@@ -53,7 +53,7 @@ export class AdbShellProtocolSpawner {
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
async spawnWait(
|
|
56
|
-
command: string | string[],
|
|
56
|
+
command: string | readonly string[],
|
|
57
57
|
): Promise<AdbShellProtocolSpawner.WaitResult<Uint8Array>> {
|
|
58
58
|
const process = await this.spawn(command);
|
|
59
59
|
const [stdout, stderr, exitCode] = await Promise.all([
|
|
@@ -65,7 +65,7 @@ export class AdbShellProtocolSpawner {
|
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
async spawnWaitText(
|
|
68
|
-
command: string | string[],
|
|
68
|
+
command: string | readonly string[],
|
|
69
69
|
): Promise<AdbShellProtocolSpawner.WaitResult<string>> {
|
|
70
70
|
const process = await this.spawn(command);
|
|
71
71
|
const [stdout, stderr, exitCode] = await Promise.all([
|
|
@@ -4,7 +4,7 @@ import { decodeUtf8, string, struct, u32 } from "@yume-chan/struct";
|
|
|
4
4
|
|
|
5
5
|
import { unreachable } from "../../utils/no-op.js";
|
|
6
6
|
|
|
7
|
-
function encodeAsciiUnchecked(value: string): Uint8Array {
|
|
7
|
+
function encodeAsciiUnchecked(value: string): Uint8Array<ArrayBuffer> {
|
|
8
8
|
const result = new Uint8Array(value.length);
|
|
9
9
|
for (let i = 0; i < value.length; i += 1) {
|
|
10
10
|
result[i] = value.charCodeAt(i);
|
package/src/daemon/auth.ts
CHANGED
|
@@ -139,7 +139,7 @@ export const AdbPublicKeyAuthenticator: AdbAuthenticator = async function* (
|
|
|
139
139
|
};
|
|
140
140
|
};
|
|
141
141
|
|
|
142
|
-
export const ADB_DEFAULT_AUTHENTICATORS: AdbAuthenticator[] = [
|
|
142
|
+
export const ADB_DEFAULT_AUTHENTICATORS: readonly AdbAuthenticator[] = [
|
|
143
143
|
AdbSignatureAuthenticator,
|
|
144
144
|
AdbPublicKeyAuthenticator,
|
|
145
145
|
];
|
package/src/daemon/crypto.ts
CHANGED
|
@@ -140,7 +140,9 @@ export function adbGetPublicKeySize() {
|
|
|
140
140
|
return 4 + 4 + ModulusLengthInBytes + ModulusLengthInBytes + 4;
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
-
export function adbGeneratePublicKey(
|
|
143
|
+
export function adbGeneratePublicKey(
|
|
144
|
+
privateKey: Uint8Array,
|
|
145
|
+
): Uint8Array<ArrayBuffer>;
|
|
144
146
|
export function adbGeneratePublicKey(
|
|
145
147
|
privateKey: Uint8Array,
|
|
146
148
|
output: Uint8Array,
|
|
@@ -287,7 +289,10 @@ export const SHA1_DIGEST_INFO = new Uint8Array([
|
|
|
287
289
|
// encrypt the given data with its private key)
|
|
288
290
|
// However SubtileCrypto.encrypt() doesn't accept 'RSASSA-PKCS1-v1_5' algorithm
|
|
289
291
|
// So we need to implement the encryption by ourself
|
|
290
|
-
export function rsaSign(
|
|
292
|
+
export function rsaSign(
|
|
293
|
+
privateKey: Uint8Array,
|
|
294
|
+
data: Uint8Array,
|
|
295
|
+
): Uint8Array<ArrayBuffer> {
|
|
291
296
|
const [n, d] = rsaParsePrivateKey(privateKey);
|
|
292
297
|
|
|
293
298
|
// PKCS#1 padding
|
package/src/daemon/transport.ts
CHANGED
|
@@ -49,7 +49,7 @@ export const ADB_DAEMON_DEFAULT_FEATURES = /* #__PURE__ */ (() =>
|
|
|
49
49
|
"sendrecv_v2_zstd",
|
|
50
50
|
"sendrecv_v2_dry_run_send",
|
|
51
51
|
AdbFeature.DelayedAck,
|
|
52
|
-
] as AdbFeature[])();
|
|
52
|
+
] as readonly AdbFeature[])();
|
|
53
53
|
export const ADB_DAEMON_DEFAULT_INITIAL_PAYLOAD_SIZE = 32 * 1024 * 1024;
|
|
54
54
|
|
|
55
55
|
export type AdbDaemonConnection = ReadableWritablePair<
|
|
@@ -61,7 +61,7 @@ export interface AdbDaemonAuthenticationOptions {
|
|
|
61
61
|
serial: string;
|
|
62
62
|
connection: AdbDaemonConnection;
|
|
63
63
|
credentialStore: AdbCredentialStore;
|
|
64
|
-
authenticators?: AdbAuthenticator[];
|
|
64
|
+
authenticators?: readonly AdbAuthenticator[];
|
|
65
65
|
features?: readonly AdbFeature[];
|
|
66
66
|
|
|
67
67
|
/**
|
package/src/server/client.ts
CHANGED
|
@@ -12,6 +12,7 @@ import type {
|
|
|
12
12
|
import { AbortController } from "@yume-chan/stream-extra";
|
|
13
13
|
|
|
14
14
|
import type { AdbIncomingSocketHandler, AdbSocket, Closeable } from "../adb.js";
|
|
15
|
+
import { Adb } from "../adb.js";
|
|
15
16
|
import { AdbBanner } from "../banner.js";
|
|
16
17
|
import type { DeviceObserver as DeviceObserverBase } from "../device-observer.js";
|
|
17
18
|
import type { AdbFeature } from "../features.js";
|
|
@@ -36,7 +37,13 @@ export class AdbServerClient {
|
|
|
36
37
|
static UnauthorizedError = _UnauthorizedError;
|
|
37
38
|
static AlreadyConnectedError = _AlreadyConnectedError;
|
|
38
39
|
|
|
39
|
-
static parseDeviceList(
|
|
40
|
+
static parseDeviceList(
|
|
41
|
+
value: string,
|
|
42
|
+
includeStates: readonly AdbServerClient.ConnectionState[] = [
|
|
43
|
+
"device",
|
|
44
|
+
"unauthorized",
|
|
45
|
+
],
|
|
46
|
+
): AdbServerClient.Device[] {
|
|
40
47
|
const devices: AdbServerClient.Device[] = [];
|
|
41
48
|
for (const line of value.split("\n")) {
|
|
42
49
|
if (!line) {
|
|
@@ -45,8 +52,8 @@ export class AdbServerClient {
|
|
|
45
52
|
|
|
46
53
|
const parts = line.split(" ").filter(Boolean);
|
|
47
54
|
const serial = parts[0]!;
|
|
48
|
-
const
|
|
49
|
-
if (
|
|
55
|
+
const state = parts[1]! as AdbServerClient.ConnectionState;
|
|
56
|
+
if (!includeStates.includes(state)) {
|
|
50
57
|
continue;
|
|
51
58
|
}
|
|
52
59
|
|
|
@@ -76,7 +83,8 @@ export class AdbServerClient {
|
|
|
76
83
|
}
|
|
77
84
|
devices.push({
|
|
78
85
|
serial,
|
|
79
|
-
|
|
86
|
+
state,
|
|
87
|
+
authenticating: state === "unauthorized",
|
|
80
88
|
product,
|
|
81
89
|
model,
|
|
82
90
|
device,
|
|
@@ -192,11 +200,16 @@ export class AdbServerClient {
|
|
|
192
200
|
*
|
|
193
201
|
* Equivalent ADB Command: `adb devices -l`
|
|
194
202
|
*/
|
|
195
|
-
async getDevices(
|
|
203
|
+
async getDevices(
|
|
204
|
+
includeStates: readonly AdbServerClient.ConnectionState[] = [
|
|
205
|
+
"device",
|
|
206
|
+
"unauthorized",
|
|
207
|
+
],
|
|
208
|
+
): Promise<AdbServerClient.Device[]> {
|
|
196
209
|
const connection = await this.createConnection("host:devices-l");
|
|
197
210
|
try {
|
|
198
211
|
const response = await connection.readString();
|
|
199
|
-
return AdbServerClient.parseDeviceList(response);
|
|
212
|
+
return AdbServerClient.parseDeviceList(response, includeStates);
|
|
200
213
|
} finally {
|
|
201
214
|
await connection.dispose();
|
|
202
215
|
}
|
|
@@ -206,7 +219,7 @@ export class AdbServerClient {
|
|
|
206
219
|
* Monitors device list changes.
|
|
207
220
|
*/
|
|
208
221
|
async trackDevices(
|
|
209
|
-
options?:
|
|
222
|
+
options?: AdbServerDeviceObserverOwner.Options,
|
|
210
223
|
): Promise<AdbServerClient.DeviceObserver> {
|
|
211
224
|
return this.#observerOwner.createObserver(options);
|
|
212
225
|
}
|
|
@@ -236,7 +249,7 @@ export class AdbServerClient {
|
|
|
236
249
|
*/
|
|
237
250
|
async getDeviceFeatures(
|
|
238
251
|
device: AdbServerClient.DeviceSelector,
|
|
239
|
-
): Promise<{ transportId: bigint; features: AdbFeature[] }> {
|
|
252
|
+
): Promise<{ transportId: bigint; features: readonly AdbFeature[] }> {
|
|
240
253
|
// On paper, `host:features` is a host service (device features are cached in host),
|
|
241
254
|
// so it shouldn't use `createDeviceConnection`,
|
|
242
255
|
// which is used to forward the service to the device.
|
|
@@ -462,6 +475,11 @@ export class AdbServerClient {
|
|
|
462
475
|
|
|
463
476
|
return transport;
|
|
464
477
|
}
|
|
478
|
+
|
|
479
|
+
async createAdb(device: AdbServerClient.DeviceSelector) {
|
|
480
|
+
const transport = await this.createTransport(device);
|
|
481
|
+
return new Adb(transport);
|
|
482
|
+
}
|
|
465
483
|
}
|
|
466
484
|
|
|
467
485
|
export async function raceSignal<T>(
|
|
@@ -536,8 +554,12 @@ export namespace AdbServerClient {
|
|
|
536
554
|
| { tcp: true }
|
|
537
555
|
| undefined;
|
|
538
556
|
|
|
557
|
+
export type ConnectionState = "unauthorized" | "offline" | "device";
|
|
558
|
+
|
|
539
559
|
export interface Device {
|
|
540
560
|
serial: string;
|
|
561
|
+
state: ConnectionState;
|
|
562
|
+
/** @deprecated Use {@link state} instead */
|
|
541
563
|
authenticating: boolean;
|
|
542
564
|
product?: string | undefined;
|
|
543
565
|
model?: string | undefined;
|
package/src/server/observer.ts
CHANGED
|
@@ -13,17 +13,28 @@ export function unorderedRemove<T>(array: T[], index: number) {
|
|
|
13
13
|
array.length -= 1;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
interface Observer {
|
|
17
|
+
includeStates: readonly AdbServerClient.ConnectionState[];
|
|
18
|
+
onDeviceAdd: EventEmitter<readonly AdbServerClient.Device[]>;
|
|
19
|
+
onDeviceRemove: EventEmitter<readonly AdbServerClient.Device[]>;
|
|
20
|
+
onListChange: EventEmitter<readonly AdbServerClient.Device[]>;
|
|
21
|
+
onError: EventEmitter<Error>;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function filterDeviceStates(
|
|
25
|
+
devices: readonly AdbServerClient.Device[],
|
|
26
|
+
states: readonly AdbServerClient.ConnectionState[],
|
|
27
|
+
) {
|
|
28
|
+
return devices.filter((device) => states.includes(device.state));
|
|
29
|
+
}
|
|
30
|
+
|
|
16
31
|
export class AdbServerDeviceObserverOwner {
|
|
17
32
|
current: readonly AdbServerClient.Device[] = [];
|
|
18
33
|
|
|
19
34
|
readonly #client: AdbServerClient;
|
|
35
|
+
|
|
20
36
|
#stream: Promise<AdbServerStream> | undefined;
|
|
21
|
-
#observers:
|
|
22
|
-
onDeviceAdd: EventEmitter<readonly AdbServerClient.Device[]>;
|
|
23
|
-
onDeviceRemove: EventEmitter<readonly AdbServerClient.Device[]>;
|
|
24
|
-
onListChange: EventEmitter<readonly AdbServerClient.Device[]>;
|
|
25
|
-
onError: EventEmitter<Error>;
|
|
26
|
-
}[] = [];
|
|
37
|
+
#observers: Observer[] = [];
|
|
27
38
|
|
|
28
39
|
constructor(client: AdbServerClient) {
|
|
29
40
|
this.#client = client;
|
|
@@ -52,17 +63,33 @@ export class AdbServerDeviceObserverOwner {
|
|
|
52
63
|
|
|
53
64
|
if (added.length) {
|
|
54
65
|
for (const observer of this.#observers) {
|
|
55
|
-
|
|
66
|
+
const filtered = filterDeviceStates(
|
|
67
|
+
added,
|
|
68
|
+
observer.includeStates,
|
|
69
|
+
);
|
|
70
|
+
if (filtered.length) {
|
|
71
|
+
observer.onDeviceAdd.fire(filtered);
|
|
72
|
+
}
|
|
56
73
|
}
|
|
57
74
|
}
|
|
58
75
|
if (removed.length) {
|
|
59
76
|
for (const observer of this.#observers) {
|
|
60
|
-
|
|
77
|
+
const filtered = filterDeviceStates(
|
|
78
|
+
removed,
|
|
79
|
+
observer.includeStates,
|
|
80
|
+
);
|
|
81
|
+
if (filtered.length) {
|
|
82
|
+
observer.onDeviceRemove.fire(removed);
|
|
83
|
+
}
|
|
61
84
|
}
|
|
62
85
|
}
|
|
63
86
|
|
|
64
87
|
for (const observer of this.#observers) {
|
|
65
|
-
|
|
88
|
+
const filtered = filterDeviceStates(
|
|
89
|
+
this.current,
|
|
90
|
+
observer.includeStates,
|
|
91
|
+
);
|
|
92
|
+
observer.onListChange.fire(filtered);
|
|
66
93
|
}
|
|
67
94
|
}
|
|
68
95
|
|
|
@@ -104,10 +131,11 @@ export class AdbServerDeviceObserverOwner {
|
|
|
104
131
|
}
|
|
105
132
|
|
|
106
133
|
async createObserver(
|
|
107
|
-
options?:
|
|
134
|
+
options?: AdbServerDeviceObserverOwner.Options,
|
|
108
135
|
): Promise<AdbServerClient.DeviceObserver> {
|
|
109
136
|
options?.signal?.throwIfAborted();
|
|
110
137
|
|
|
138
|
+
let current: readonly AdbServerClient.Device[] = [];
|
|
111
139
|
const onDeviceAdd = new EventEmitter<
|
|
112
140
|
readonly AdbServerClient.Device[]
|
|
113
141
|
>();
|
|
@@ -119,13 +147,27 @@ export class AdbServerDeviceObserverOwner {
|
|
|
119
147
|
>();
|
|
120
148
|
const onError = new StickyEventEmitter<Error>();
|
|
121
149
|
|
|
122
|
-
const
|
|
150
|
+
const includeStates = options?.includeStates ?? [
|
|
151
|
+
"device",
|
|
152
|
+
"unauthorized",
|
|
153
|
+
];
|
|
154
|
+
const observer = {
|
|
155
|
+
includeStates,
|
|
156
|
+
onDeviceAdd,
|
|
157
|
+
onDeviceRemove,
|
|
158
|
+
onListChange,
|
|
159
|
+
onError,
|
|
160
|
+
} satisfies Observer;
|
|
123
161
|
// Register `observer` before `#connect`.
|
|
124
162
|
// So `#handleObserverStop` knows if there is any observer.
|
|
125
163
|
this.#observers.push(observer);
|
|
126
164
|
|
|
165
|
+
// Read the filtered `current` value from `onListChange` event
|
|
166
|
+
onListChange.event((value) => (current = value));
|
|
167
|
+
|
|
127
168
|
let stream: AdbServerStream;
|
|
128
169
|
if (!this.#stream) {
|
|
170
|
+
// `#connect` will initialize `onListChange` and `current`
|
|
129
171
|
this.#stream = this.#connect();
|
|
130
172
|
|
|
131
173
|
try {
|
|
@@ -136,7 +178,8 @@ export class AdbServerDeviceObserverOwner {
|
|
|
136
178
|
}
|
|
137
179
|
} else {
|
|
138
180
|
stream = await this.#stream;
|
|
139
|
-
onListChange
|
|
181
|
+
// Initialize `onListChange` and `current` ourselves
|
|
182
|
+
onListChange.fire(filterDeviceStates(this.current, includeStates));
|
|
140
183
|
}
|
|
141
184
|
|
|
142
185
|
const ref = new Ref(options);
|
|
@@ -156,17 +199,21 @@ export class AdbServerDeviceObserverOwner {
|
|
|
156
199
|
options.signal.addEventListener("abort", () => void stop());
|
|
157
200
|
}
|
|
158
201
|
|
|
159
|
-
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
160
|
-
const _this = this;
|
|
161
202
|
return {
|
|
162
203
|
onDeviceAdd: onDeviceAdd.event,
|
|
163
204
|
onDeviceRemove: onDeviceRemove.event,
|
|
164
205
|
onListChange: onListChange.event,
|
|
165
206
|
onError: onError.event,
|
|
166
207
|
get current() {
|
|
167
|
-
return
|
|
208
|
+
return current;
|
|
168
209
|
},
|
|
169
210
|
stop,
|
|
170
211
|
};
|
|
171
212
|
}
|
|
172
213
|
}
|
|
214
|
+
|
|
215
|
+
export namespace AdbServerDeviceObserverOwner {
|
|
216
|
+
export interface Options extends AdbServerClient.ServerConnectionOptions {
|
|
217
|
+
includeStates?: readonly AdbServerClient.ConnectionState[];
|
|
218
|
+
}
|
|
219
|
+
}
|
package/src/server/transport.ts
CHANGED
|
@@ -30,7 +30,7 @@ export const ADB_SERVER_DEFAULT_FEATURES = /* #__PURE__ */ (() =>
|
|
|
30
30
|
"sendrecv_v2_lz4",
|
|
31
31
|
"sendrecv_v2_zstd",
|
|
32
32
|
"sendrecv_v2_dry_run_send",
|
|
33
|
-
] as AdbFeature[])();
|
|
33
|
+
] as readonly AdbFeature[])();
|
|
34
34
|
|
|
35
35
|
export class AdbServerTransport implements AdbTransport {
|
|
36
36
|
#client: AdbServerClient;
|
package/src/utils/base64.ts
CHANGED
|
@@ -47,7 +47,7 @@ export function calculateBase64EncodedLength(
|
|
|
47
47
|
* @param input The input buffer
|
|
48
48
|
* @returns The encoded output buffer
|
|
49
49
|
*/
|
|
50
|
-
export function encodeBase64(input: Uint8Array): Uint8Array
|
|
50
|
+
export function encodeBase64(input: Uint8Array): Uint8Array<ArrayBuffer>;
|
|
51
51
|
/**
|
|
52
52
|
* Encode the given input into base64 and write it to the output buffer.
|
|
53
53
|
*
|
|
@@ -295,7 +295,7 @@ function encodeBackward(
|
|
|
295
295
|
}
|
|
296
296
|
}
|
|
297
297
|
|
|
298
|
-
export function decodeBase64(input: string): Uint8Array {
|
|
298
|
+
export function decodeBase64(input: string): Uint8Array<ArrayBuffer> {
|
|
299
299
|
let padding: number;
|
|
300
300
|
if (input[input.length - 2] === "=") {
|
|
301
301
|
padding = 2;
|