@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
@@ -16,7 +16,7 @@ import {
16
16
  Consumable,
17
17
  WritableStream,
18
18
  } from "@yume-chan/stream-extra";
19
- import { EMPTY_UINT8_ARRAY, decodeUtf8, encodeUtf8 } from "@yume-chan/struct";
19
+ import { EmptyUint8Array, decodeUtf8, encodeUtf8 } from "@yume-chan/struct";
20
20
 
21
21
  import type { AdbIncomingSocketHandler, AdbSocket, Closeable } from "../adb.js";
22
22
 
@@ -259,7 +259,7 @@ export class AdbPacketDispatcher implements Closeable {
259
259
  AdbCommand.Close,
260
260
  packet.arg1,
261
261
  packet.arg0,
262
- EMPTY_UINT8_ARRAY,
262
+ EmptyUint8Array,
263
263
  );
264
264
  }
265
265
 
@@ -271,7 +271,7 @@ export class AdbPacketDispatcher implements Closeable {
271
271
  payload = new Uint8Array(4);
272
272
  setUint32LittleEndian(payload, 0, ackBytes);
273
273
  } else {
274
- payload = EMPTY_UINT8_ARRAY;
274
+ payload = EmptyUint8Array;
275
275
  }
276
276
 
277
277
  return this.sendPacket(AdbCommand.Okay, localId, remoteId, payload);
@@ -312,7 +312,7 @@ export class AdbPacketDispatcher implements Closeable {
312
312
  AdbCommand.Close,
313
313
  0,
314
314
  remoteId,
315
- EMPTY_UINT8_ARRAY,
315
+ EmptyUint8Array,
316
316
  );
317
317
  return;
318
318
  }
@@ -334,12 +334,12 @@ export class AdbPacketDispatcher implements Closeable {
334
334
  remoteId,
335
335
  this.options.initialDelayedAckBytes,
336
336
  );
337
- } catch (e) {
337
+ } catch {
338
338
  await this.sendPacket(
339
339
  AdbCommand.Close,
340
340
  0,
341
341
  remoteId,
342
- EMPTY_UINT8_ARRAY,
342
+ EmptyUint8Array,
343
343
  );
344
344
  }
345
345
  }
@@ -1,32 +1,43 @@
1
1
  import { Consumable, TransformStream } from "@yume-chan/stream-extra";
2
- import Struct from "@yume-chan/struct";
2
+ import type { StructInit, StructValue } from "@yume-chan/struct";
3
+ import { buffer, s32, struct, u32 } from "@yume-chan/struct";
3
4
 
4
- export enum AdbCommand {
5
- Auth = 0x48545541, // 'AUTH'
6
- Close = 0x45534c43, // 'CLSE'
7
- Connect = 0x4e584e43, // 'CNXN'
8
- Okay = 0x59414b4f, // 'OKAY'
9
- Open = 0x4e45504f, // 'OPEN'
10
- Write = 0x45545257, // 'WRTE'
11
- }
5
+ export const AdbCommand = {
6
+ Auth: 0x48545541, // 'AUTH'
7
+ Close: 0x45534c43, // 'CLSE'
8
+ Connect: 0x4e584e43, // 'CNXN'
9
+ Okay: 0x59414b4f, // 'OKAY'
10
+ Open: 0x4e45504f, // 'OPEN'
11
+ Write: 0x45545257, // 'WRTE'
12
+ } as const;
13
+
14
+ export type AdbCommand = (typeof AdbCommand)[keyof typeof AdbCommand];
12
15
 
13
- export const AdbPacketHeader = new Struct({ littleEndian: true })
14
- .uint32("command")
15
- .uint32("arg0")
16
- .uint32("arg1")
17
- .uint32("payloadLength")
18
- .uint32("checksum")
19
- .int32("magic");
16
+ export const AdbPacketHeader = struct(
17
+ {
18
+ command: u32,
19
+ arg0: u32,
20
+ arg1: u32,
21
+ payloadLength: u32,
22
+ checksum: u32,
23
+ magic: s32,
24
+ },
25
+ { littleEndian: true },
26
+ );
20
27
 
21
- export type AdbPacketHeader = (typeof AdbPacketHeader)["TDeserializeResult"];
28
+ export type AdbPacketHeader = StructValue<typeof AdbPacketHeader>;
22
29
 
23
- type AdbPacketHeaderInit = (typeof AdbPacketHeader)["TInit"];
30
+ type AdbPacketHeaderInit = StructInit<typeof AdbPacketHeader>;
24
31
 
25
- export const AdbPacket = new Struct({ littleEndian: true })
26
- .concat(AdbPacketHeader)
27
- .uint8Array("payload", { lengthField: "payloadLength" });
32
+ export const AdbPacket = struct(
33
+ /* #__PURE__ */ (() => ({
34
+ ...AdbPacketHeader.fields,
35
+ payload: buffer("payloadLength"),
36
+ }))(),
37
+ { littleEndian: true },
38
+ );
28
39
 
29
- export type AdbPacket = (typeof AdbPacket)["TDeserializeResult"];
40
+ export type AdbPacket = StructValue<typeof AdbPacket>;
30
41
 
31
42
  /**
32
43
  * `AdbPacketData` contains all the useful fields of `AdbPacket`.
@@ -39,11 +50,11 @@ export type AdbPacket = (typeof AdbPacket)["TDeserializeResult"];
39
50
  * so `AdbSocket#writable#write` only needs `AdbPacketData`.
40
51
  */
41
52
  export type AdbPacketData = Omit<
42
- (typeof AdbPacket)["TInit"],
53
+ StructInit<typeof AdbPacket>,
43
54
  "checksum" | "magic"
44
55
  >;
45
56
 
46
- export type AdbPacketInit = (typeof AdbPacket)["TInit"];
57
+ export type AdbPacketInit = StructInit<typeof AdbPacket>;
47
58
 
48
59
  export function calculateChecksum(payload: Uint8Array): number {
49
60
  return payload.reduce((result, item) => result + item, 0);
@@ -61,9 +72,10 @@ export class AdbPacketSerializeStream extends TransformStream<
61
72
  const init = chunk as AdbPacketInit & AdbPacketHeaderInit;
62
73
  init.payloadLength = init.payload.length;
63
74
 
75
+ AdbPacketHeader.serialize(init, headerBuffer);
64
76
  await Consumable.ReadableStream.enqueue(
65
77
  controller,
66
- AdbPacketHeader.serialize(init, headerBuffer),
78
+ headerBuffer,
67
79
  );
68
80
 
69
81
  if (init.payloadLength) {
@@ -7,7 +7,7 @@ import type {
7
7
  WritableStreamDefaultController,
8
8
  } from "@yume-chan/stream-extra";
9
9
  import { MaybeConsumable, PushReadableStream } from "@yume-chan/stream-extra";
10
- import { EMPTY_UINT8_ARRAY } from "@yume-chan/struct";
10
+ import { EmptyUint8Array } from "@yume-chan/struct";
11
11
 
12
12
  import type { AdbSocket } from "../adb.js";
13
13
 
@@ -138,20 +138,7 @@ export class AdbDaemonSocketController
138
138
  }
139
139
 
140
140
  async enqueue(data: Uint8Array) {
141
- // Consumers can `cancel` the `readable` if they are not interested in future data.
142
- // Throw away the data if that happens.
143
- if (this.#readableController.abortSignal.aborted) {
144
- return;
145
- }
146
-
147
- try {
148
- await this.#readableController.enqueue(data);
149
- } catch (e) {
150
- if (this.#readableController.abortSignal.aborted) {
151
- return;
152
- }
153
- throw e;
154
- }
141
+ await this.#readableController.enqueue(data);
155
142
  }
156
143
 
157
144
  public ack(bytes: number) {
@@ -177,28 +164,18 @@ export class AdbDaemonSocketController
177
164
  AdbCommand.Close,
178
165
  this.localId,
179
166
  this.remoteId,
180
- EMPTY_UINT8_ARRAY,
167
+ EmptyUint8Array,
181
168
  );
182
169
  }
183
170
 
184
171
  dispose() {
185
- try {
186
- this.#readableController.close();
187
- } catch {
188
- // ignore
189
- }
190
-
172
+ this.#readableController.close();
191
173
  this.#closedPromise.resolve();
192
174
  }
193
175
  }
194
176
 
195
177
  /**
196
178
  * A duplex stream representing a socket to ADB daemon.
197
- *
198
- * To close it, call either `socket.close()`,
199
- * `socket.readable.cancel()`, `socket.readable.getReader().cancel()`,
200
- * `socket.writable.abort()`, `socket.writable.getWriter().abort()`,
201
- * `socket.writable.close()` or `socket.writable.getWriter().close()`.
202
179
  */
203
180
  export class AdbDaemonSocket implements AdbDaemonSocketInfo, AdbSocket {
204
181
  #controller: AdbDaemonSocketController;
@@ -1,3 +1,4 @@
1
+ import type { MaybePromiseLike } from "@yume-chan/async";
1
2
  import { PromiseResolver } from "@yume-chan/async";
2
3
  import type { ReadableWritablePair } from "@yume-chan/stream-extra";
3
4
  import {
@@ -5,7 +6,6 @@ import {
5
6
  Consumable,
6
7
  WritableStream,
7
8
  } from "@yume-chan/stream-extra";
8
- import type { ValueOrPromise } from "@yume-chan/struct";
9
9
  import { decodeUtf8, encodeUtf8 } from "@yume-chan/struct";
10
10
 
11
11
  import type {
@@ -28,27 +28,28 @@ import { AdbCommand, calculateChecksum } from "./packet.js";
28
28
  export const ADB_DAEMON_VERSION_OMIT_CHECKSUM = 0x01000001;
29
29
  // https://android.googlesource.com/platform/packages/modules/adb/+/79010dc6d5ca7490c493df800d4421730f5466ca/transport.cpp#1252
30
30
  // There are some other feature constants, but some of them are only used by ADB server, not devices (daemons).
31
- export const ADB_DAEMON_DEFAULT_FEATURES = [
32
- AdbFeature.ShellV2,
33
- AdbFeature.Cmd,
34
- AdbFeature.StatV2,
35
- AdbFeature.ListV2,
36
- AdbFeature.FixedPushMkdir,
37
- "apex",
38
- AdbFeature.Abb,
39
- // only tells the client the symlink timestamp issue in `adb push --sync` has been fixed.
40
- // No special handling required.
41
- "fixed_push_symlink_timestamp",
42
- AdbFeature.AbbExec,
43
- "remount_shell",
44
- "track_app",
45
- AdbFeature.SendReceiveV2,
46
- "sendrecv_v2_brotli",
47
- "sendrecv_v2_lz4",
48
- "sendrecv_v2_zstd",
49
- "sendrecv_v2_dry_run_send",
50
- AdbFeature.DelayedAck,
51
- ] as AdbFeature[];
31
+ export const ADB_DAEMON_DEFAULT_FEATURES = /* #__PURE__ */ (() =>
32
+ [
33
+ AdbFeature.ShellV2,
34
+ AdbFeature.Cmd,
35
+ AdbFeature.StatV2,
36
+ AdbFeature.ListV2,
37
+ AdbFeature.FixedPushMkdir,
38
+ "apex",
39
+ AdbFeature.Abb,
40
+ // only tells the client the symlink timestamp issue in `adb push --sync` has been fixed.
41
+ // No special handling required.
42
+ "fixed_push_symlink_timestamp",
43
+ AdbFeature.AbbExec,
44
+ "remount_shell",
45
+ "track_app",
46
+ AdbFeature.SendReceiveV2,
47
+ "sendrecv_v2_brotli",
48
+ "sendrecv_v2_lz4",
49
+ "sendrecv_v2_zstd",
50
+ "sendrecv_v2_dry_run_send",
51
+ AdbFeature.DelayedAck,
52
+ ] as AdbFeature[])();
52
53
  export const ADB_DAEMON_DEFAULT_INITIAL_PAYLOAD_SIZE = 32 * 1024 * 1024;
53
54
 
54
55
  export type AdbDaemonConnection = ReadableWritablePair<
@@ -114,13 +115,15 @@ interface AdbDaemonSocketConnectorConstructionOptions {
114
115
 
115
116
  /**
116
117
  * The number of bytes the device can send before receiving an ack packet.
117
- * Using delayed ack can improve the throughput,
118
- * especially when the device is connected over Wi-Fi (so the latency is higher).
118
+ *
119
+ * On Android 14 and newer, the Delayed Acknowledgement feature is added to
120
+ * improve performance, especially for high-latency connections like ADB over Wi-Fi.
119
121
  *
120
122
  * When `features` doesn't include `AdbFeature.DelayedAck`, it must be set to 0. Otherwise,
121
- * the value must be in the range of unsigned 32-bit integer. If the device enabled
122
- * delayed ack but the client didn't, the device will throw an error when the client sends
123
- * the first data packet. And vice versa.
123
+ * the value must be in the range of unsigned 32-bit integer.
124
+ *
125
+ * If the device enabled delayed ack but the client didn't, the device will throw an error
126
+ * when the client sends the first data packet. And vice versa.
124
127
  */
125
128
  initialDelayedAckBytes: number;
126
129
 
@@ -146,14 +149,12 @@ interface AdbDaemonSocketConnectorConstructionOptions {
146
149
  readTimeLimit?: number | undefined;
147
150
  }
148
151
 
152
+ /**
153
+ * An ADB Transport that connects to ADB Daemons directly.
154
+ */
149
155
  export class AdbDaemonTransport implements AdbTransport {
150
156
  /**
151
- * Authenticates the connection and creates an `AdbDaemonTransport` instance
152
- * that can be used by `Adb` class.
153
- *
154
- * If an authentication process failed,
155
- * no matter which value the `preserveConnection` option has,
156
- * the `connection` is always kept open, so it can be used in another `authenticate` call.
157
+ * Authenticate with the ADB Daemon and create a new transport.
157
158
  */
158
159
  static async authenticate({
159
160
  serial,
@@ -364,7 +365,7 @@ export class AdbDaemonTransport implements AdbTransport {
364
365
  this.#protocolVersion = version;
365
366
  }
366
367
 
367
- connect(service: string): ValueOrPromise<AdbSocket> {
368
+ connect(service: string): MaybePromiseLike<AdbSocket> {
368
369
  return this.#dispatcher.createSocket(service);
369
370
  }
370
371
 
@@ -388,7 +389,7 @@ export class AdbDaemonTransport implements AdbTransport {
388
389
  this.#dispatcher.clearReverseTunnels();
389
390
  }
390
391
 
391
- close(): ValueOrPromise<void> {
392
+ close(): MaybePromiseLike<void> {
392
393
  return this.#dispatcher.close();
393
394
  }
394
395
  }
@@ -0,0 +1,10 @@
1
+ import type { MaybePromiseLike } from "@yume-chan/async";
2
+ import type { Event } from "@yume-chan/event";
3
+
4
+ export interface DeviceObserver<T> {
5
+ onDeviceAdd: Event<T[]>;
6
+ onDeviceRemove: Event<T[]>;
7
+ onListChange: Event<T[]>;
8
+ current: T[];
9
+ stop(): MaybePromiseLike<void>;
10
+ }
package/src/features.ts CHANGED
@@ -1,13 +1,15 @@
1
1
  // The order follows
2
2
  // https://cs.android.com/android/platform/superproject/+/master:packages/modules/adb/transport.cpp;l=77;drc=6d14d35d0241f6fee145f8e54ffd77252e8d29fd
3
- export enum AdbFeature {
4
- ShellV2 = "shell_v2",
5
- Cmd = "cmd",
6
- StatV2 = "stat_v2",
7
- ListV2 = "ls_v2",
8
- FixedPushMkdir = "fixed_push_mkdir",
9
- Abb = "abb",
10
- AbbExec = "abb_exec",
11
- SendReceiveV2 = "sendrecv_v2",
12
- DelayedAck = "delayed_ack",
13
- }
3
+ export const AdbFeature = {
4
+ ShellV2: "shell_v2",
5
+ Cmd: "cmd",
6
+ StatV2: "stat_v2",
7
+ ListV2: "ls_v2",
8
+ FixedPushMkdir: "fixed_push_mkdir",
9
+ Abb: "abb",
10
+ AbbExec: "abb_exec",
11
+ SendReceiveV2: "sendrecv_v2",
12
+ DelayedAck: "delayed_ack",
13
+ } as const;
14
+
15
+ export type AdbFeature = (typeof AdbFeature)[keyof typeof AdbFeature];
package/src/index.ts CHANGED
@@ -2,6 +2,7 @@ export * from "./adb.js";
2
2
  export * from "./banner.js";
3
3
  export * from "./commands/index.js";
4
4
  export * from "./daemon/index.js";
5
+ export * from "./device-observer.js";
5
6
  export * from "./features.js";
6
7
  export * from "./server/index.js";
7
8
  export * from "./utils/index.js";