@yume-chan/adb 0.0.18 → 0.0.20

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 (241) hide show
  1. package/CHANGELOG.json +54 -0
  2. package/CHANGELOG.md +25 -1
  3. package/README.md +220 -103
  4. package/esm/adb.d.ts +43 -60
  5. package/esm/adb.d.ts.map +1 -1
  6. package/esm/adb.js +68 -249
  7. package/esm/adb.js.map +1 -1
  8. package/esm/banner.d.ts +17 -0
  9. package/esm/banner.d.ts.map +1 -0
  10. package/esm/banner.js +67 -0
  11. package/esm/banner.js.map +1 -0
  12. package/esm/commands/base.d.ts +6 -6
  13. package/esm/commands/base.d.ts.map +1 -1
  14. package/esm/commands/base.js +8 -8
  15. package/esm/commands/framebuffer.d.ts +53 -53
  16. package/esm/commands/framebuffer.d.ts.map +1 -1
  17. package/esm/commands/framebuffer.js +46 -46
  18. package/esm/commands/framebuffer.js.map +1 -1
  19. package/esm/commands/index.d.ts +7 -8
  20. package/esm/commands/index.d.ts.map +1 -1
  21. package/esm/commands/index.js +7 -8
  22. package/esm/commands/index.js.map +1 -1
  23. package/esm/commands/power.d.ts +22 -22
  24. package/esm/commands/power.js +48 -48
  25. package/esm/commands/reverse.d.ts +40 -28
  26. package/esm/commands/reverse.d.ts.map +1 -1
  27. package/esm/commands/reverse.js +130 -100
  28. package/esm/commands/reverse.js.map +1 -1
  29. package/esm/commands/subprocess/command.d.ts +57 -51
  30. package/esm/commands/subprocess/command.d.ts.map +1 -1
  31. package/esm/commands/subprocess/command.js +86 -80
  32. package/esm/commands/subprocess/command.js.map +1 -1
  33. package/esm/commands/subprocess/index.d.ts +3 -3
  34. package/esm/commands/subprocess/index.js +3 -3
  35. package/esm/commands/subprocess/protocols/index.d.ts +3 -3
  36. package/esm/commands/subprocess/protocols/index.js +3 -3
  37. package/esm/commands/subprocess/protocols/none.d.ts +30 -35
  38. package/esm/commands/subprocess/protocols/none.d.ts.map +1 -1
  39. package/esm/commands/subprocess/protocols/none.js +65 -55
  40. package/esm/commands/subprocess/protocols/none.js.map +1 -1
  41. package/esm/commands/subprocess/protocols/shell.d.ts +33 -38
  42. package/esm/commands/subprocess/protocols/shell.d.ts.map +1 -1
  43. package/esm/commands/subprocess/protocols/shell.js +172 -162
  44. package/esm/commands/subprocess/protocols/shell.js.map +1 -1
  45. package/esm/commands/subprocess/protocols/types.d.ts +48 -49
  46. package/esm/commands/subprocess/protocols/types.d.ts.map +1 -1
  47. package/esm/commands/subprocess/protocols/types.js +1 -1
  48. package/esm/commands/subprocess/utils.d.ts +1 -1
  49. package/esm/commands/subprocess/utils.js +18 -18
  50. package/esm/commands/sync/index.d.ts +8 -7
  51. package/esm/commands/sync/index.d.ts.map +1 -1
  52. package/esm/commands/sync/index.js +8 -7
  53. package/esm/commands/sync/index.js.map +1 -1
  54. package/esm/commands/sync/list.d.ts +42 -40
  55. package/esm/commands/sync/list.d.ts.map +1 -1
  56. package/esm/commands/sync/list.js +67 -47
  57. package/esm/commands/sync/list.js.map +1 -1
  58. package/esm/commands/sync/pull.d.ts +13 -11
  59. package/esm/commands/sync/pull.d.ts.map +1 -1
  60. package/esm/commands/sync/pull.js +35 -37
  61. package/esm/commands/sync/pull.js.map +1 -1
  62. package/esm/commands/sync/push.d.ts +57 -7
  63. package/esm/commands/sync/push.d.ts.map +1 -1
  64. package/esm/commands/sync/push.js +89 -22
  65. package/esm/commands/sync/push.js.map +1 -1
  66. package/esm/commands/sync/request.d.ts +26 -23
  67. package/esm/commands/sync/request.d.ts.map +1 -1
  68. package/esm/commands/sync/request.js +40 -42
  69. package/esm/commands/sync/request.js.map +1 -1
  70. package/esm/commands/sync/response.d.ts +19 -19
  71. package/esm/commands/sync/response.d.ts.map +1 -1
  72. package/esm/commands/sync/response.js +54 -54
  73. package/esm/commands/sync/response.js.map +1 -1
  74. package/esm/commands/sync/socket.d.ts +22 -0
  75. package/esm/commands/sync/socket.d.ts.map +1 -0
  76. package/esm/commands/sync/socket.js +69 -0
  77. package/esm/commands/sync/socket.js.map +1 -0
  78. package/esm/commands/sync/stat.d.ts +72 -72
  79. package/esm/commands/sync/stat.d.ts.map +1 -1
  80. package/esm/commands/sync/stat.js +116 -104
  81. package/esm/commands/sync/stat.js.map +1 -1
  82. package/esm/commands/sync/sync.d.ts +65 -60
  83. package/esm/commands/sync/sync.d.ts.map +1 -1
  84. package/esm/commands/sync/sync.js +123 -149
  85. package/esm/commands/sync/sync.js.map +1 -1
  86. package/esm/commands/tcpip.d.ts +5 -5
  87. package/esm/commands/tcpip.d.ts.map +1 -1
  88. package/esm/commands/tcpip.js +20 -18
  89. package/esm/commands/tcpip.js.map +1 -1
  90. package/esm/{auth.d.ts → daemon/auth.d.ts} +50 -51
  91. package/esm/daemon/auth.d.ts.map +1 -0
  92. package/esm/{auth.js → daemon/auth.js} +95 -96
  93. package/esm/daemon/auth.js.map +1 -0
  94. package/esm/daemon/connection.d.ts +11 -0
  95. package/esm/daemon/connection.d.ts.map +1 -0
  96. package/esm/daemon/connection.js +2 -0
  97. package/esm/daemon/connection.js.map +1 -0
  98. package/esm/{crypto.d.ts → daemon/crypto.d.ts} +36 -36
  99. package/esm/daemon/crypto.d.ts.map +1 -0
  100. package/esm/{crypto.js → daemon/crypto.js} +244 -248
  101. package/esm/daemon/crypto.js.map +1 -0
  102. package/esm/daemon/device.d.ts +9 -0
  103. package/esm/daemon/device.d.ts.map +1 -0
  104. package/esm/daemon/device.js +2 -0
  105. package/esm/daemon/device.js.map +1 -0
  106. package/esm/daemon/dispatcher.d.ts +42 -0
  107. package/esm/daemon/dispatcher.d.ts.map +1 -0
  108. package/esm/{socket → daemon}/dispatcher.js +225 -234
  109. package/esm/daemon/dispatcher.js.map +1 -0
  110. package/esm/daemon/index.d.ts +8 -0
  111. package/esm/daemon/index.d.ts.map +1 -0
  112. package/esm/daemon/index.js +8 -0
  113. package/esm/daemon/index.js.map +1 -0
  114. package/esm/{packet.d.ts → daemon/packet.d.ts} +45 -46
  115. package/esm/daemon/packet.d.ts.map +1 -0
  116. package/esm/{packet.js → daemon/packet.js} +43 -48
  117. package/esm/daemon/packet.js.map +1 -0
  118. package/esm/daemon/socket.d.ts +58 -0
  119. package/esm/daemon/socket.d.ts.map +1 -0
  120. package/esm/{socket → daemon}/socket.js +121 -118
  121. package/esm/daemon/socket.js.map +1 -0
  122. package/esm/daemon/transport.d.ts +45 -0
  123. package/esm/daemon/transport.d.ts.map +1 -0
  124. package/esm/daemon/transport.js +184 -0
  125. package/esm/daemon/transport.js.map +1 -0
  126. package/esm/features.d.ts +10 -7
  127. package/esm/features.d.ts.map +1 -1
  128. package/esm/features.js +13 -10
  129. package/esm/features.js.map +1 -1
  130. package/esm/index.d.ts +7 -9
  131. package/esm/index.d.ts.map +1 -1
  132. package/esm/index.js +7 -9
  133. package/esm/index.js.map +1 -1
  134. package/esm/server/client.d.ts +78 -0
  135. package/esm/server/client.d.ts.map +1 -0
  136. package/esm/server/client.js +329 -0
  137. package/esm/server/client.js.map +1 -0
  138. package/esm/server/index.d.ts +3 -0
  139. package/esm/server/index.d.ts.map +1 -0
  140. package/esm/server/index.js +3 -0
  141. package/esm/server/index.js.map +1 -0
  142. package/esm/server/transport.d.ts +19 -0
  143. package/esm/server/transport.d.ts.map +1 -0
  144. package/esm/server/transport.js +44 -0
  145. package/esm/server/transport.js.map +1 -0
  146. package/esm/utils/auto-reset-event.d.ts +8 -9
  147. package/esm/utils/auto-reset-event.d.ts.map +1 -1
  148. package/esm/utils/auto-reset-event.js +33 -33
  149. package/esm/utils/auto-reset-event.js.map +1 -1
  150. package/esm/utils/base64.d.ts +27 -27
  151. package/esm/utils/base64.js +246 -246
  152. package/esm/utils/base64.js.map +1 -1
  153. package/esm/utils/conditional-variable.d.ts +8 -0
  154. package/esm/utils/conditional-variable.d.ts.map +1 -0
  155. package/esm/utils/conditional-variable.js +34 -0
  156. package/esm/utils/conditional-variable.js.map +1 -0
  157. package/esm/utils/hex.d.ts +3 -0
  158. package/esm/utils/hex.d.ts.map +1 -0
  159. package/esm/utils/hex.js +55 -0
  160. package/esm/utils/hex.js.map +1 -0
  161. package/esm/utils/index.d.ts +6 -3
  162. package/esm/utils/index.d.ts.map +1 -1
  163. package/esm/utils/index.js +6 -3
  164. package/esm/utils/index.js.map +1 -1
  165. package/esm/utils/no-op.d.ts +7 -0
  166. package/esm/utils/no-op.d.ts.map +1 -0
  167. package/esm/utils/no-op.js +12 -0
  168. package/esm/utils/no-op.js.map +1 -0
  169. package/package.json +14 -12
  170. package/src/adb.ts +47 -248
  171. package/src/banner.ts +82 -0
  172. package/src/commands/base.ts +1 -1
  173. package/src/commands/framebuffer.ts +4 -4
  174. package/src/commands/index.ts +7 -8
  175. package/src/commands/power.ts +2 -2
  176. package/src/commands/reverse.ts +90 -70
  177. package/src/commands/subprocess/command.ts +12 -4
  178. package/src/commands/subprocess/index.ts +3 -3
  179. package/src/commands/subprocess/protocols/index.ts +3 -3
  180. package/src/commands/subprocess/protocols/none.ts +36 -23
  181. package/src/commands/subprocess/protocols/shell.ts +94 -74
  182. package/src/commands/subprocess/protocols/types.ts +7 -7
  183. package/src/commands/subprocess/utils.ts +1 -1
  184. package/src/commands/sync/index.ts +8 -7
  185. package/src/commands/sync/list.ts +44 -25
  186. package/src/commands/sync/pull.ts +40 -45
  187. package/src/commands/sync/push.ts +158 -39
  188. package/src/commands/sync/request.ts +21 -16
  189. package/src/commands/sync/response.ts +10 -9
  190. package/src/commands/sync/socket.ts +99 -0
  191. package/src/commands/sync/stat.ts +47 -42
  192. package/src/commands/sync/sync.ts +73 -116
  193. package/src/commands/tcpip.ts +9 -7
  194. package/src/{auth.ts → daemon/auth.ts} +24 -23
  195. package/src/{crypto.ts → daemon/crypto.ts} +25 -33
  196. package/src/daemon/device.ts +14 -0
  197. package/src/{socket → daemon}/dispatcher.ts +95 -117
  198. package/src/daemon/index.ts +7 -0
  199. package/src/daemon/packet.ts +75 -0
  200. package/src/{socket → daemon}/socket.ts +71 -56
  201. package/src/daemon/transport.ts +269 -0
  202. package/src/features.ts +9 -6
  203. package/src/index.ts +3 -5
  204. package/src/server/client.ts +476 -0
  205. package/src/server/index.ts +2 -0
  206. package/src/server/transport.ts +77 -0
  207. package/src/utils/auto-reset-event.ts +14 -15
  208. package/src/utils/conditional-variable.ts +45 -0
  209. package/src/utils/hex.ts +58 -0
  210. package/src/utils/index.ts +6 -3
  211. package/src/utils/no-op.ts +12 -0
  212. package/tsconfig.build.json +12 -1
  213. package/tsconfig.build.tsbuildinfo +1 -1
  214. package/esm/auth.d.ts.map +0 -1
  215. package/esm/auth.js.map +0 -1
  216. package/esm/backend.d.ts +0 -9
  217. package/esm/backend.d.ts.map +0 -1
  218. package/esm/backend.js +0 -2
  219. package/esm/backend.js.map +0 -1
  220. package/esm/commands/install.d.ts +0 -4
  221. package/esm/commands/install.d.ts.map +0 -1
  222. package/esm/commands/install.js +0 -29
  223. package/esm/commands/install.js.map +0 -1
  224. package/esm/crypto.d.ts.map +0 -1
  225. package/esm/crypto.js.map +0 -1
  226. package/esm/packet.d.ts.map +0 -1
  227. package/esm/packet.js.map +0 -1
  228. package/esm/socket/dispatcher.d.ts +0 -60
  229. package/esm/socket/dispatcher.d.ts.map +0 -1
  230. package/esm/socket/dispatcher.js.map +0 -1
  231. package/esm/socket/index.d.ts +0 -3
  232. package/esm/socket/index.d.ts.map +0 -1
  233. package/esm/socket/index.js +0 -3
  234. package/esm/socket/index.js.map +0 -1
  235. package/esm/socket/socket.d.ts +0 -60
  236. package/esm/socket/socket.d.ts.map +0 -1
  237. package/esm/socket/socket.js.map +0 -1
  238. package/src/backend.ts +0 -14
  239. package/src/commands/install.ts +0 -40
  240. package/src/packet.ts +0 -90
  241. package/src/socket/index.ts +0 -2
@@ -1,23 +1,26 @@
1
- import { PromiseResolver } from '@yume-chan/async';
1
+ import { PromiseResolver } from "@yume-chan/async";
2
+ import type {
3
+ Consumable,
4
+ PushReadableStreamController,
5
+ ReadableStream,
6
+ WritableStreamDefaultWriter,
7
+ } from "@yume-chan/stream-extra";
2
8
  import {
9
+ ConsumableTransformStream,
10
+ ConsumableWritableStream,
3
11
  PushReadableStream,
4
12
  StructDeserializeStream,
5
- StructSerializeStream,
6
- TransformStream,
7
13
  WritableStream,
8
14
  pipeFrom,
9
- type PushReadableStreamController,
10
- type ReadableStream,
11
- type WritableStreamDefaultWriter,
12
15
  } from "@yume-chan/stream-extra";
13
- import Struct, { placeholder, type StructValueType } from '@yume-chan/struct';
16
+ import type { StructValueType } from "@yume-chan/struct";
17
+ import Struct, { placeholder } from "@yume-chan/struct";
14
18
 
15
- import { type Adb } from "../../../adb.js";
16
- import { AdbFeatures } from '../../../features.js';
17
- import { type AdbSocket } from "../../../socket/index.js";
18
- import { encodeUtf8 } from '../../../utils/index.js';
19
+ import type { Adb, AdbSocket } from "../../../adb.js";
20
+ import { AdbFeature } from "../../../features.js";
21
+ import { encodeUtf8 } from "../../../utils/index.js";
19
22
 
20
- import { type AdbSubprocessProtocol } from "./types.js";
23
+ import type { AdbSubprocessProtocol } from "./types.js";
21
24
 
22
25
  export enum AdbShellProtocolId {
23
26
  Stdin,
@@ -29,39 +32,29 @@ export enum AdbShellProtocolId {
29
32
  }
30
33
 
31
34
  // This packet format is used in both direction.
32
- const AdbShellProtocolPacket =
33
- new Struct({ littleEndian: true })
34
- .uint8('id', placeholder<AdbShellProtocolId>())
35
- .uint32('length')
36
- .uint8Array('data', { lengthField: 'length' });
35
+ const AdbShellProtocolPacket = new Struct({ littleEndian: true })
36
+ .uint8("id", placeholder<AdbShellProtocolId>())
37
+ .uint32("length")
38
+ .uint8Array("data", { lengthField: "length" });
37
39
 
38
- type AdbShellProtocolPacketInit = typeof AdbShellProtocolPacket['TInit'];
40
+ type AdbShellProtocolPacketInit = (typeof AdbShellProtocolPacket)["TInit"];
39
41
 
40
42
  type AdbShellProtocolPacket = StructValueType<typeof AdbShellProtocolPacket>;
41
43
 
42
- class StdinSerializeStream extends TransformStream<Uint8Array, AdbShellProtocolPacketInit>{
44
+ class StdinSerializeStream extends ConsumableTransformStream<
45
+ Uint8Array,
46
+ AdbShellProtocolPacketInit
47
+ > {
43
48
  constructor() {
44
49
  super({
45
- transform(chunk, controller) {
46
- controller.enqueue({
50
+ async transform(chunk, controller) {
51
+ await controller.enqueue({
47
52
  id: AdbShellProtocolId.Stdin,
48
53
  data: chunk,
49
54
  });
50
55
  },
51
56
  flush() {
52
57
  // TODO: AdbShellSubprocessProtocol: support closing stdin
53
- }
54
- });
55
- }
56
- }
57
-
58
- class StdoutDeserializeStream extends TransformStream<AdbShellProtocolPacket, Uint8Array>{
59
- constructor(type: AdbShellProtocolId.Stdout | AdbShellProtocolId.Stderr) {
60
- super({
61
- transform(chunk, controller) {
62
- if (chunk.id === type) {
63
- controller.enqueue(chunk.data);
64
- }
65
58
  },
66
59
  });
67
60
  }
@@ -116,7 +109,7 @@ class MultiplexStream<T> {
116
109
  */
117
110
  export class AdbSubprocessShellProtocol implements AdbSubprocessProtocol {
118
111
  public static isSupported(adb: Adb) {
119
- return adb.features.includes(AdbFeatures.ShellV2);
112
+ return adb.supportsFeature(AdbFeature.ShellV2);
120
113
  }
121
114
 
122
115
  public static async pty(adb: Adb, command: string) {
@@ -132,81 +125,108 @@ export class AdbSubprocessShellProtocol implements AdbSubprocessProtocol {
132
125
  );
133
126
  }
134
127
 
135
- private readonly _socket: AdbSocket;
136
- private _socketWriter: WritableStreamDefaultWriter<AdbShellProtocolPacketInit>;
128
+ readonly #socket: AdbSocket;
129
+ #socketWriter: WritableStreamDefaultWriter<
130
+ Consumable<AdbShellProtocolPacketInit>
131
+ >;
137
132
 
138
- private _stdin: WritableStream<Uint8Array>;
133
+ #stdin: WritableStream<Consumable<Uint8Array>>;
139
134
  public get stdin() {
140
- return this._stdin;
135
+ return this.#stdin;
141
136
  }
142
137
 
143
- private _stdout: ReadableStream<Uint8Array>;
138
+ #stdout: ReadableStream<Uint8Array>;
144
139
  public get stdout() {
145
- return this._stdout;
140
+ return this.#stdout;
146
141
  }
147
142
 
148
- private _stderr: ReadableStream<Uint8Array>;
143
+ #stderr: ReadableStream<Uint8Array>;
149
144
  public get stderr() {
150
- return this._stderr;
145
+ return this.#stderr;
151
146
  }
152
147
 
153
- private readonly _exit = new PromiseResolver<number>();
148
+ readonly #exit = new PromiseResolver<number>();
154
149
  public get exit() {
155
- return this._exit.promise;
150
+ return this.#exit.promise;
156
151
  }
157
152
 
158
153
  public constructor(socket: AdbSocket) {
159
- this._socket = socket;
154
+ this.#socket = socket;
160
155
 
161
156
  // Check this image to help you understand the stream graph
162
157
  // cspell: disable-next-line
163
158
  // https://www.plantuml.com/plantuml/png/bL91QiCm4Bpx5SAdv90lb1JISmiw5XzaQKf5PIkiLZIqzEyLSg8ks13gYtOykpFhiOw93N6UGjVDqK7rZsxKqNw0U_NTgVAy4empOy2mm4_olC0VEVEE47GUpnGjKdgXoD76q4GIEpyFhOwP_m28hW0NNzxNUig1_JdW0bA7muFIJDco1daJ_1SAX9bgvoPJPyIkSekhNYctvIGXrCH6tIsPL5fs-s6J5yc9BpWXhKtNdF2LgVYPGM_6GlMwfhWUsIt4lbScANrwlgVVUifPSVi__t44qStnwPvZwobdSmHHlL57p2vFuHS0
164
159
 
165
- // TODO: AdbShellSubprocessProtocol: Optimize stream graph
160
+ let stdoutController!: PushReadableStreamController<Uint8Array>;
161
+ let stderrController!: PushReadableStreamController<Uint8Array>;
162
+ this.#stdout = new PushReadableStream<Uint8Array>((controller) => {
163
+ stdoutController = controller;
164
+ });
165
+ this.#stderr = new PushReadableStream<Uint8Array>((controller) => {
166
+ stderrController = controller;
167
+ });
166
168
 
167
- const [stdout, stderr] = socket.readable
169
+ socket.readable
168
170
  .pipeThrough(new StructDeserializeStream(AdbShellProtocolPacket))
169
- .pipeThrough(
170
- new TransformStream<
171
- AdbShellProtocolPacket,
172
- AdbShellProtocolPacket
173
- >({
174
- transform: (chunk, controller) => {
175
- if (chunk.id === AdbShellProtocolId.Exit) {
176
- this._exit.resolve(new Uint8Array(chunk.data)[0]!);
177
- // We can let `StdoutDeserializeStream` to process `AdbShellProtocolId.Exit`,
178
- // but since we need this `TransformStream` to capture the exit code anyway,
179
- // terminating child streams here is killing two birds with one stone.
180
- controller.terminate();
181
- return;
171
+ .pipeTo(
172
+ new WritableStream<AdbShellProtocolPacket>({
173
+ write: async (chunk) => {
174
+ switch (chunk.id) {
175
+ case AdbShellProtocolId.Exit:
176
+ this.#exit.resolve(chunk.data[0]!);
177
+ break;
178
+ case AdbShellProtocolId.Stdout:
179
+ await stdoutController.enqueue(chunk.data);
180
+ break;
181
+ case AdbShellProtocolId.Stderr:
182
+ await stderrController.enqueue(chunk.data);
183
+ break;
182
184
  }
183
- controller.enqueue(chunk);
184
185
  },
185
186
  })
186
187
  )
187
- .tee();
188
- this._stdout = stdout.pipeThrough(
189
- new StdoutDeserializeStream(AdbShellProtocolId.Stdout)
190
- );
191
- this._stderr = stderr.pipeThrough(
192
- new StdoutDeserializeStream(AdbShellProtocolId.Stderr)
193
- );
188
+ .then(
189
+ () => {
190
+ stdoutController.close();
191
+ stderrController.close();
192
+ // If `#exit` has already resolved, this will be a no-op
193
+ this.#exit.reject(
194
+ new Error("Socket ended without exit message")
195
+ );
196
+ },
197
+ (e) => {
198
+ stdoutController.error(e);
199
+ stderrController.error(e);
200
+ // If `#exit` has already resolved, this will be a no-op
201
+ this.#exit.reject(e);
202
+ }
203
+ );
194
204
 
195
- const multiplexer = new MultiplexStream<AdbShellProtocolPacketInit>();
205
+ const multiplexer = new MultiplexStream<
206
+ Consumable<AdbShellProtocolPacketInit>
207
+ >();
196
208
  void multiplexer.readable
197
- .pipeThrough(new StructSerializeStream(AdbShellProtocolPacket))
209
+ .pipeThrough(
210
+ new ConsumableTransformStream({
211
+ async transform(chunk, controller) {
212
+ await controller.enqueue(
213
+ AdbShellProtocolPacket.serialize(chunk)
214
+ );
215
+ },
216
+ })
217
+ )
198
218
  .pipeTo(socket.writable);
199
219
 
200
- this._stdin = pipeFrom(
220
+ this.#stdin = pipeFrom(
201
221
  multiplexer.createWriteable(),
202
222
  new StdinSerializeStream()
203
223
  );
204
224
 
205
- this._socketWriter = multiplexer.createWriteable().getWriter();
225
+ this.#socketWriter = multiplexer.createWriteable().getWriter();
206
226
  }
207
227
 
208
228
  public async resize(rows: number, cols: number) {
209
- await this._socketWriter.write({
229
+ await ConsumableWritableStream.write(this.#socketWriter, {
210
230
  id: AdbShellProtocolId.WindowSizeChange,
211
231
  data: encodeUtf8(
212
232
  // The "correct" format is `${rows}x${cols},${x_pixels}x${y_pixels}`
@@ -218,6 +238,6 @@ export class AdbSubprocessShellProtocol implements AdbSubprocessProtocol {
218
238
  }
219
239
 
220
240
  public kill() {
221
- return this._socket.close();
241
+ return this.#socket.close();
222
242
  }
223
243
  }
@@ -1,17 +1,17 @@
1
- import {
2
- type ReadableStream,
3
- type WritableStream,
1
+ import type {
2
+ Consumable,
3
+ ReadableStream,
4
+ WritableStream,
4
5
  } from "@yume-chan/stream-extra";
5
- import { type ValueOrPromise } from "@yume-chan/struct";
6
+ import type { ValueOrPromise } from "@yume-chan/struct";
6
7
 
7
- import { type Adb } from "../../../adb.js";
8
- import { type AdbSocket } from "../../../socket/index.js";
8
+ import type { Adb, AdbSocket } from "../../../adb.js";
9
9
 
10
10
  export interface AdbSubprocessProtocol {
11
11
  /**
12
12
  * A WritableStream that writes to the `stdin` stream.
13
13
  */
14
- readonly stdin: WritableStream<Uint8Array>;
14
+ readonly stdin: WritableStream<Consumable<Uint8Array>>;
15
15
 
16
16
  /**
17
17
  * The `stdout` stream of the process.
@@ -1,5 +1,5 @@
1
1
  export function escapeArg(s: string) {
2
- let result = '';
2
+ let result = "";
3
3
  result += `'`;
4
4
 
5
5
  let base = 0;
@@ -1,7 +1,8 @@
1
- export * from './list.js';
2
- export * from './pull.js';
3
- export * from './push.js';
4
- export * from './request.js';
5
- export * from './response.js';
6
- export * from './stat.js';
7
- export * from './sync.js';
1
+ export * from "./list.js";
2
+ export * from "./pull.js";
3
+ export * from "./push.js";
4
+ export * from "./request.js";
5
+ export * from "./response.js";
6
+ export * from "./socket.js";
7
+ export * from "./stat.js";
8
+ export * from "./sync.js";
@@ -1,49 +1,42 @@
1
- import {
2
- type BufferedReadableStream,
3
- type WritableStreamDefaultWriter,
4
- } from "@yume-chan/stream-extra";
5
1
  import Struct from "@yume-chan/struct";
6
2
 
7
3
  import { AdbSyncRequestId, adbSyncWriteRequest } from "./request.js";
8
4
  import { AdbSyncResponseId, adbSyncReadResponses } from "./response.js";
9
- import {
10
- AdbSyncLstatResponse,
11
- AdbSyncStatResponse,
12
- type AdbSyncStat,
13
- } from "./stat.js";
5
+ import type { AdbSyncSocket } from "./socket.js";
6
+ import type { AdbSyncStat } from "./stat.js";
7
+ import { AdbSyncLstatResponse, AdbSyncStatResponse } from "./stat.js";
14
8
 
15
9
  export interface AdbSyncEntry extends AdbSyncStat {
16
10
  name: string;
17
11
  }
18
12
 
19
13
  export const AdbSyncEntryResponse = new Struct({ littleEndian: true })
20
- .fields(AdbSyncLstatResponse)
14
+ .concat(AdbSyncLstatResponse)
21
15
  .uint32("nameLength")
22
16
  .string("name", { lengthField: "nameLength" })
23
17
  .extra({ id: AdbSyncResponseId.Entry as const });
24
18
 
25
19
  export type AdbSyncEntryResponse =
26
- typeof AdbSyncEntryResponse["TDeserializeResult"];
20
+ (typeof AdbSyncEntryResponse)["TDeserializeResult"];
27
21
 
28
22
  export const AdbSyncEntry2Response = new Struct({ littleEndian: true })
29
- .fields(AdbSyncStatResponse)
23
+ .concat(AdbSyncStatResponse)
30
24
  .uint32("nameLength")
31
25
  .string("name", { lengthField: "nameLength" })
32
26
  .extra({ id: AdbSyncResponseId.Entry2 as const });
33
27
 
34
28
  export type AdbSyncEntry2Response =
35
- typeof AdbSyncEntry2Response["TDeserializeResult"];
29
+ (typeof AdbSyncEntry2Response)["TDeserializeResult"];
36
30
 
37
- export async function* adbSyncOpenDir(
38
- stream: BufferedReadableStream,
39
- writer: WritableStreamDefaultWriter<Uint8Array>,
40
- path: string,
41
- v2: boolean
42
- ): AsyncGenerator<AdbSyncEntry, void, void> {
43
- if (v2) {
44
- await adbSyncWriteRequest(writer, AdbSyncRequestId.List2, path);
31
+ export async function* adbSyncOpenDirV2(
32
+ socket: AdbSyncSocket,
33
+ path: string
34
+ ): AsyncGenerator<AdbSyncEntry2Response, void, void> {
35
+ const locked = await socket.lock();
36
+ try {
37
+ await adbSyncWriteRequest(locked, AdbSyncRequestId.ListV2, path);
45
38
  for await (const item of adbSyncReadResponses(
46
- stream,
39
+ locked,
47
40
  AdbSyncResponseId.Entry2,
48
41
  AdbSyncEntry2Response
49
42
  )) {
@@ -55,13 +48,39 @@ export async function* adbSyncOpenDir(
55
48
  }
56
49
  yield item;
57
50
  }
58
- } else {
59
- await adbSyncWriteRequest(writer, AdbSyncRequestId.List, path);
51
+ } finally {
52
+ locked.release();
53
+ }
54
+ }
55
+
56
+ export async function* adbSyncOpenDirV1(
57
+ socket: AdbSyncSocket,
58
+ path: string
59
+ ): AsyncGenerator<AdbSyncEntryResponse, void, void> {
60
+ const locked = await socket.lock();
61
+ try {
62
+ await adbSyncWriteRequest(locked, AdbSyncRequestId.List, path);
60
63
  for await (const item of adbSyncReadResponses(
61
- stream,
64
+ locked,
62
65
  AdbSyncResponseId.Entry,
63
66
  AdbSyncEntryResponse
64
67
  )) {
68
+ yield item;
69
+ }
70
+ } finally {
71
+ locked.release();
72
+ }
73
+ }
74
+
75
+ export async function* adbSyncOpenDir(
76
+ socket: AdbSyncSocket,
77
+ path: string,
78
+ v2: boolean
79
+ ): AsyncGenerator<AdbSyncEntry, void, void> {
80
+ if (v2) {
81
+ yield* adbSyncOpenDirV2(socket, path);
82
+ } else {
83
+ for await (const item of adbSyncOpenDirV1(socket, path)) {
65
84
  // Convert to same format as `AdbSyncEntry2Response` for easier consumption.
66
85
  // However it will add some overhead.
67
86
  yield {
@@ -1,12 +1,10 @@
1
- import {
2
- ReadableStream,
3
- type BufferedReadableStream,
4
- type WritableStreamDefaultWriter,
5
- } from "@yume-chan/stream-extra";
1
+ import type { ReadableStream } from "@yume-chan/stream-extra";
2
+ import { PushReadableStream } from "@yume-chan/stream-extra";
6
3
  import Struct from "@yume-chan/struct";
7
4
 
8
5
  import { AdbSyncRequestId, adbSyncWriteRequest } from "./request.js";
9
6
  import { AdbSyncResponseId, adbSyncReadResponses } from "./response.js";
7
+ import type { AdbSyncSocket } from "./socket.js";
10
8
 
11
9
  export const AdbSyncDataResponse = new Struct({ littleEndian: true })
12
10
  .uint32("dataLength")
@@ -14,49 +12,46 @@ export const AdbSyncDataResponse = new Struct({ littleEndian: true })
14
12
  .extra({ id: AdbSyncResponseId.Data as const });
15
13
 
16
14
  export type AdbSyncDataResponse =
17
- typeof AdbSyncDataResponse["TDeserializeResult"];
15
+ (typeof AdbSyncDataResponse)["TDeserializeResult"];
16
+
17
+ export async function* adbSyncPullGenerator(
18
+ socket: AdbSyncSocket,
19
+ path: string
20
+ ): AsyncGenerator<Uint8Array, void, void> {
21
+ const locked = await socket.lock();
22
+ let done = false;
23
+ try {
24
+ await adbSyncWriteRequest(locked, AdbSyncRequestId.Receive, path);
25
+ for await (const packet of adbSyncReadResponses(
26
+ locked,
27
+ AdbSyncResponseId.Data,
28
+ AdbSyncDataResponse
29
+ )) {
30
+ yield packet.data;
31
+ }
32
+ done = true;
33
+ } finally {
34
+ if (!done) {
35
+ // sync pull can't be cancelled, so we have to read all data
36
+ for await (const packet of adbSyncReadResponses(
37
+ locked,
38
+ AdbSyncResponseId.Data,
39
+ AdbSyncDataResponse
40
+ )) {
41
+ void packet;
42
+ }
43
+ }
44
+ locked.release();
45
+ }
46
+ }
18
47
 
19
48
  export function adbSyncPull(
20
- stream: BufferedReadableStream,
21
- writer: WritableStreamDefaultWriter<Uint8Array>,
49
+ socket: AdbSyncSocket,
22
50
  path: string
23
51
  ): ReadableStream<Uint8Array> {
24
- let generator!: AsyncGenerator<AdbSyncDataResponse, void, void>;
25
- return new ReadableStream<Uint8Array>(
26
- {
27
- async start() {
28
- // TODO: If `ReadableStream.from(AsyncGenerator)` is added to spec, use it instead.
29
- await adbSyncWriteRequest(
30
- writer,
31
- AdbSyncRequestId.Receive,
32
- path
33
- );
34
- generator = adbSyncReadResponses(
35
- stream,
36
- AdbSyncResponseId.Data,
37
- AdbSyncDataResponse
38
- );
39
- },
40
- async pull(controller) {
41
- const { done, value } = await generator.next();
42
- if (done) {
43
- controller.close();
44
- return;
45
- }
46
- controller.enqueue(value.data);
47
- },
48
- cancel() {
49
- generator.return().catch((e) => {
50
- void e;
51
- });
52
- throw new Error(`Sync commands can't be canceled.`);
53
- },
54
- },
55
- {
56
- highWaterMark: 16 * 1024,
57
- size(chunk) {
58
- return chunk.byteLength;
59
- },
52
+ return new PushReadableStream(async (controller) => {
53
+ for await (const data of adbSyncPullGenerator(socket, path)) {
54
+ await controller.enqueue(data);
60
55
  }
61
- );
56
+ });
62
57
  }