@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.
Files changed (146) hide show
  1. package/CHANGELOG.md +36 -1
  2. package/README.md +4 -1
  3. package/esm/adb.d.ts +13 -7
  4. package/esm/adb.d.ts.map +1 -1
  5. package/esm/adb.js +3 -0
  6. package/esm/adb.js.map +1 -1
  7. package/esm/banner.d.ts +7 -6
  8. package/esm/banner.d.ts.map +1 -1
  9. package/esm/banner.js +6 -7
  10. package/esm/banner.js.map +1 -1
  11. package/esm/commands/framebuffer.d.ts +63 -34
  12. package/esm/commands/framebuffer.d.ts.map +1 -1
  13. package/esm/commands/framebuffer.js +35 -33
  14. package/esm/commands/framebuffer.js.map +1 -1
  15. package/esm/commands/reverse.d.ts +12 -12
  16. package/esm/commands/reverse.d.ts.map +1 -1
  17. package/esm/commands/reverse.js +39 -30
  18. package/esm/commands/reverse.js.map +1 -1
  19. package/esm/commands/subprocess/protocols/none.d.ts.map +1 -1
  20. package/esm/commands/subprocess/protocols/none.js +3 -5
  21. package/esm/commands/subprocess/protocols/none.js.map +1 -1
  22. package/esm/commands/subprocess/protocols/shell.d.ts +20 -12
  23. package/esm/commands/subprocess/protocols/shell.d.ts.map +1 -1
  24. package/esm/commands/subprocess/protocols/shell.js +16 -21
  25. package/esm/commands/subprocess/protocols/shell.js.map +1 -1
  26. package/esm/commands/subprocess/protocols/types.d.ts +6 -6
  27. package/esm/commands/subprocess/protocols/types.d.ts.map +1 -1
  28. package/esm/commands/sync/list.d.ts +49 -27
  29. package/esm/commands/sync/list.d.ts.map +1 -1
  30. package/esm/commands/sync/list.js +9 -9
  31. package/esm/commands/sync/list.js.map +1 -1
  32. package/esm/commands/sync/pull.d.ts +7 -6
  33. package/esm/commands/sync/pull.d.ts.map +1 -1
  34. package/esm/commands/sync/pull.js +3 -5
  35. package/esm/commands/sync/pull.js.map +1 -1
  36. package/esm/commands/sync/push.d.ts +22 -16
  37. package/esm/commands/sync/push.d.ts.map +1 -1
  38. package/esm/commands/sync/push.js +12 -16
  39. package/esm/commands/sync/push.js.map +1 -1
  40. package/esm/commands/sync/request.d.ts +19 -17
  41. package/esm/commands/sync/request.d.ts.map +1 -1
  42. package/esm/commands/sync/request.js +14 -18
  43. package/esm/commands/sync/request.js.map +1 -1
  44. package/esm/commands/sync/response.d.ts +18 -18
  45. package/esm/commands/sync/response.d.ts.map +1 -1
  46. package/esm/commands/sync/response.js +20 -19
  47. package/esm/commands/sync/response.js.map +1 -1
  48. package/esm/commands/sync/socket.d.ts +1 -1
  49. package/esm/commands/sync/socket.js +2 -2
  50. package/esm/commands/sync/socket.js.map +1 -1
  51. package/esm/commands/sync/stat.d.ts +75 -51
  52. package/esm/commands/sync/stat.d.ts.map +1 -1
  53. package/esm/commands/sync/stat.js +73 -67
  54. package/esm/commands/sync/stat.js.map +1 -1
  55. package/esm/commands/sync/sync.d.ts +14 -14
  56. package/esm/commands/sync/sync.d.ts.map +1 -1
  57. package/esm/commands/sync/sync.js +4 -7
  58. package/esm/commands/sync/sync.js.map +1 -1
  59. package/esm/commands/tcpip.d.ts +0 -1
  60. package/esm/commands/tcpip.d.ts.map +1 -1
  61. package/esm/commands/tcpip.js +8 -8
  62. package/esm/commands/tcpip.js.map +1 -1
  63. package/esm/daemon/auth.d.ts +8 -7
  64. package/esm/daemon/auth.d.ts.map +1 -1
  65. package/esm/daemon/auth.js +7 -8
  66. package/esm/daemon/auth.js.map +1 -1
  67. package/esm/daemon/crypto.d.ts +1 -1
  68. package/esm/daemon/crypto.d.ts.map +1 -1
  69. package/esm/daemon/crypto.js +1 -0
  70. package/esm/daemon/crypto.js.map +1 -1
  71. package/esm/daemon/device.d.ts +2 -2
  72. package/esm/daemon/device.d.ts.map +1 -1
  73. package/esm/daemon/dispatcher.js +6 -6
  74. package/esm/daemon/dispatcher.js.map +1 -1
  75. package/esm/daemon/packet.d.ts +46 -30
  76. package/esm/daemon/packet.d.ts.map +1 -1
  77. package/esm/daemon/packet.js +24 -21
  78. package/esm/daemon/packet.js.map +1 -1
  79. package/esm/daemon/socket.d.ts +1 -6
  80. package/esm/daemon/socket.d.ts.map +1 -1
  81. package/esm/daemon/socket.js +4 -27
  82. package/esm/daemon/socket.js.map +1 -1
  83. package/esm/daemon/transport.d.ts +14 -14
  84. package/esm/daemon/transport.d.ts.map +1 -1
  85. package/esm/daemon/transport.js +6 -8
  86. package/esm/daemon/transport.js.map +1 -1
  87. package/esm/device-observer.d.ts +10 -0
  88. package/esm/device-observer.d.ts.map +1 -0
  89. package/esm/device-observer.js +2 -0
  90. package/esm/device-observer.js.map +1 -0
  91. package/esm/features.d.ts +12 -11
  92. package/esm/features.d.ts.map +1 -1
  93. package/esm/features.js +11 -12
  94. package/esm/features.js.map +1 -1
  95. package/esm/index.d.ts +1 -0
  96. package/esm/index.d.ts.map +1 -1
  97. package/esm/index.js +1 -0
  98. package/esm/index.js.map +1 -1
  99. package/esm/server/client.d.ts +34 -22
  100. package/esm/server/client.d.ts.map +1 -1
  101. package/esm/server/client.js +151 -136
  102. package/esm/server/client.js.map +1 -1
  103. package/esm/server/transport.d.ts +2 -2
  104. package/esm/server/transport.d.ts.map +1 -1
  105. package/esm/server/transport.js +1 -3
  106. package/esm/server/transport.js.map +1 -1
  107. package/esm/utils/base64.d.ts.map +1 -1
  108. package/esm/utils/base64.js +19 -16
  109. package/esm/utils/base64.js.map +1 -1
  110. package/esm/utils/no-op.d.ts.map +1 -1
  111. package/esm/utils/no-op.js +1 -0
  112. package/esm/utils/no-op.js.map +1 -1
  113. package/package.json +14 -17
  114. package/src/adb.ts +13 -7
  115. package/src/banner.ts +8 -6
  116. package/src/commands/framebuffer.ts +44 -35
  117. package/src/commands/reverse.ts +49 -31
  118. package/src/commands/subprocess/protocols/none.ts +3 -5
  119. package/src/commands/subprocess/protocols/shell.ts +26 -24
  120. package/src/commands/subprocess/protocols/types.ts +6 -6
  121. package/src/commands/sync/list.ts +20 -13
  122. package/src/commands/sync/pull.ts +8 -7
  123. package/src/commands/sync/push.ts +20 -16
  124. package/src/commands/sync/request.ts +18 -19
  125. package/src/commands/sync/response.ts +28 -29
  126. package/src/commands/sync/socket.ts +2 -2
  127. package/src/commands/sync/stat.ts +93 -71
  128. package/src/commands/sync/sync.ts +4 -8
  129. package/src/commands/tcpip.ts +8 -8
  130. package/src/daemon/auth.ts +11 -9
  131. package/src/daemon/crypto.ts +2 -0
  132. package/src/daemon/device.ts +2 -2
  133. package/src/daemon/dispatcher.ts +6 -6
  134. package/src/daemon/packet.ts +37 -25
  135. package/src/daemon/socket.ts +4 -27
  136. package/src/daemon/transport.ts +36 -35
  137. package/src/device-observer.ts +10 -0
  138. package/src/features.ts +13 -11
  139. package/src/index.ts +1 -0
  140. package/src/server/client.ts +185 -160
  141. package/src/server/transport.ts +3 -5
  142. package/src/utils/base64.ts +26 -18
  143. package/src/utils/no-op.ts +1 -0
  144. package/tsconfig.build.json +1 -12
  145. package/tsconfig.build.tsbuildinfo +1 -1
  146. package/CHANGELOG.json +0 -298
@@ -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
- MaybeConsumable,
13
- WrapWritableStream,
16
+ tryCancel,
17
+ tryClose,
14
18
  } from "@yume-chan/stream-extra";
15
- import type { ValueOrPromise } from "@yume-chan/struct";
16
19
  import {
17
- EMPTY_UINT8_ARRAY,
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): ValueOrPromise<Uint8Array> {
48
+ readExactly(length: number): MaybePromiseLike<Uint8Array> {
50
49
  return this.#buffered.readExactly(length);
51
50
  }
52
51
 
53
- readString() {
54
- return SyncPromise.try(() => this.readExactly(4))
55
- .then((buffer) => {
56
- const length = hexToNumber(buffer);
57
- if (length === 0) {
58
- return EMPTY_UINT8_ARRAY;
59
- } else {
60
- return this.readExactly(length);
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
- .then((buffer) => {
64
- // TODO: Investigate using stream mode `TextDecoder` for long strings.
65
- // Because concatenating strings uses rope data structure,
66
- // which only points to the original strings and doesn't copy the data,
67
- // it's more efficient than concatenating `Uint8Array`s.
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
- await this.#buffered.cancel().catch(NOOP);
127
- await this.#writer.close().catch(NOOP);
128
- try {
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(connection: AdbServerClient.ServerConnector) {
145
- this.connector = connection;
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
- * `adb devices -l`
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 this.parseDeviceList(response);
282
+ return AdbServerClient.parseDeviceList(response);
275
283
  } finally {
276
284
  await connection.dispose();
277
285
  }
278
286
  }
279
287
 
280
288
  /**
281
- * Track the device list.
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 *trackDevices(
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
- try {
292
- while (true) {
293
- const response = await raceSignal(
294
- async () => await connection.readString(),
295
- signal,
296
- );
297
- const devices = this.parseDeviceList(response);
298
- yield devices;
299
- }
300
- } catch (e) {
301
- if (e === signal?.reason) {
302
- return;
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
- } finally {
305
- await connection.dispose();
306
- }
307
- }
334
+ })();
308
335
 
309
- formatDeviceService(
310
- device: AdbServerClient.DeviceSelector,
311
- command: string,
312
- ) {
313
- if (!device) {
314
- return `host:${command}`;
315
- }
316
- if ("transportId" in device) {
317
- return `host-transport-id:${device.transportId}:${command}`;
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
- : this.formatDeviceService(device, "reconnect"),
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: new WrapWritableStream(
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 = this.formatDeviceService(
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
- ): ValueOrPromise<ServerConnection>;
591
+ ): MaybePromiseLike<ServerConnection>;
574
592
 
575
593
  addReverseTunnel(
576
594
  handler: AdbIncomingSocketHandler,
577
595
  address?: string,
578
- ): ValueOrPromise<string>;
596
+ ): MaybePromiseLike<string>;
579
597
 
580
- removeReverseTunnel(address: string): ValueOrPromise<void>;
598
+ removeReverseTunnel(address: string): MaybePromiseLike<void>;
581
599
 
582
- clearReverseTunnels(): ValueOrPromise<void>;
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
  }
@@ -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(): ValueOrPromise<void> {
99
+ close(): MaybePromiseLike<void> {
102
100
  this.#closed.resolve();
103
101
  this.#waitAbortController.abort();
104
102
  }
@@ -1,23 +1,31 @@
1
- // Array is faster than object literal or `Map`
2
- const charToIndex: number[] = [];
3
- const indexToChar: number[] = [];
4
- const paddingChar = "=".charCodeAt(0);
5
-
6
- function addRange(start: string, end: string) {
7
- const charCodeStart = start.charCodeAt(0);
8
- const charCodeEnd = end.charCodeAt(0);
9
-
10
- for (let charCode = charCodeStart; charCode <= charCodeEnd; charCode += 1) {
11
- charToIndex[charCode] = indexToChar.length;
12
- indexToChar.push(charCode);
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.
@@ -1,3 +1,4 @@
1
+ /* #__NO_SIDE_EFFECTS__ */
1
2
  export const NOOP = () => {
2
3
  // no-op
3
4
  };
@@ -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
  }