@mcesystems/adb-kit 1.0.32 → 1.0.33

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.
@@ -1,342 +1,342 @@
1
- #!/usr/bin/env tsx
2
- /**
3
- * Export ADB (Android Debug Bridge) resources to a specified path
4
- *
5
- * This script downloads ADB platform tools from Google and exports them
6
- * to a target directory. The resources can then be used by applications
7
- * that depend on adb-kit.
8
- *
9
- * Usage:
10
- * npx tsx export-resources.ts <target-path>
11
- *
12
- * Example:
13
- * npx tsx export-resources.ts /path/to/my-app/resources/adb-kit
14
- *
15
- * Platform support:
16
- * - macOS: Downloads darwin platform-tools from Google
17
- * - Windows: Downloads windows platform-tools from Google
18
- * - Linux: Downloads linux platform-tools from Google
19
- */
20
-
21
- import { exec } from "node:child_process";
22
- import {
23
- chmodSync,
24
- copyFileSync,
25
- createWriteStream,
26
- existsSync,
27
- mkdirSync,
28
- writeFileSync,
29
- } from "node:fs";
30
- import path from "node:path";
31
- import { promisify } from "node:util";
32
-
33
- const execAsync = promisify(exec);
34
-
35
- // ============================================================================
36
- // Configuration
37
- // ============================================================================
38
-
39
- // ADB download URLs from Google
40
- const ADB_URLS: Record<string, string> = {
41
- windows: "https://dl.google.com/android/repository/platform-tools-latest-windows.zip",
42
- darwin: "https://dl.google.com/android/repository/platform-tools-latest-darwin.zip",
43
- linux: "https://dl.google.com/android/repository/platform-tools-latest-linux.zip",
44
- };
45
-
46
- // Files to extract from platform-tools per platform
47
- const PLATFORM_FILES: Record<string, string[]> = {
48
- windows: ["adb.exe", "AdbWinApi.dll", "AdbWinUsbApi.dll"],
49
- darwin: ["adb"],
50
- linux: ["adb"],
51
- };
52
-
53
- // ============================================================================
54
- // Utility Functions
55
- // ============================================================================
56
-
57
- function printUsage(): void {
58
- console.log(`
59
- Usage: npx tsx export-resources.ts <target-path>
60
-
61
- Arguments:
62
- target-path Directory where resources will be exported
63
-
64
- Examples:
65
- npx tsx export-resources.ts ./my-app/resources/adb-kit
66
- npx tsx export-resources.ts /absolute/path/to/resources
67
-
68
- The script will create the following structure:
69
- <target-path>/
70
- bin/
71
- darwin/ (macOS ADB binary)
72
- windows/ (Windows ADB binaries and DLLs)
73
- linux/ (Linux ADB binary)
74
- licenses/
75
- APACHE-2.0.txt
76
- `);
77
- }
78
-
79
- async function downloadFile(url: string, destPath: string): Promise<void> {
80
- console.log(`Downloading ${url}...`);
81
-
82
- let response: Response;
83
- try {
84
- response = await fetch(url);
85
- } catch {
86
- // Fallback to https module if fetch is not available
87
- const https = await import("node:https");
88
- const http = await import("node:http");
89
- const urlObj = new URL(url);
90
- const client = urlObj.protocol === "https:" ? https : http;
91
-
92
- return new Promise((resolve, reject) => {
93
- const fileStream = createWriteStream(destPath);
94
- const request = client.get(url, (res) => {
95
- if (res.statusCode && res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
96
- // Handle redirect
97
- fileStream.close();
98
- return downloadFile(res.headers.location, destPath).then(resolve).catch(reject);
99
- }
100
- if (res.statusCode && res.statusCode !== 200) {
101
- fileStream.close();
102
- reject(new Error(`Failed to download ${url}: ${res.statusCode} ${res.statusMessage}`));
103
- return;
104
- }
105
- res.pipe(fileStream);
106
- fileStream.on("finish", () => {
107
- fileStream.close();
108
- resolve();
109
- });
110
- });
111
- request.on("error", (err) => {
112
- fileStream.close();
113
- reject(err);
114
- });
115
- });
116
- }
117
-
118
- if (!response.ok) {
119
- throw new Error(`Failed to download ${url}: ${response.statusText}`);
120
- }
121
-
122
- const fileStream = createWriteStream(destPath);
123
- const reader = response.body?.getReader();
124
- if (!reader) {
125
- throw new Error(`Failed to get response body for ${url}`);
126
- }
127
-
128
- try {
129
- while (true) {
130
- const { done, value } = await reader.read();
131
- if (done) break;
132
- fileStream.write(value);
133
- }
134
- fileStream.end();
135
- await new Promise<void>((resolve, reject) => {
136
- fileStream.on("finish", resolve);
137
- fileStream.on("error", reject);
138
- });
139
- console.log(`✓ Downloaded to ${destPath}`);
140
- } finally {
141
- reader.releaseLock();
142
- }
143
- }
144
-
145
- async function extractZip(zipPath: string, extractDir: string): Promise<void> {
146
- console.log(`Extracting ${zipPath}...`);
147
-
148
- if (process.platform === "win32") {
149
- // On Windows, use PowerShell Expand-Archive
150
- try {
151
- const escapedZipPath = zipPath.replace(/'/g, "''");
152
- const escapedExtractDir = extractDir.replace(/'/g, "''");
153
- await execAsync(
154
- `powershell -Command "Expand-Archive -Path '${escapedZipPath}' -DestinationPath '${escapedExtractDir}' -Force"`
155
- );
156
- } catch (error) {
157
- const err = error as { message?: string };
158
- throw new Error(
159
- `Failed to extract zip file. Please ensure PowerShell is available. Error: ${err.message || error}`
160
- );
161
- }
162
- } else {
163
- // On Unix-like systems, use unzip command
164
- try {
165
- await execAsync(`unzip -o "${zipPath}" -d "${extractDir}"`);
166
- } catch (error) {
167
- const err = error as { message?: string };
168
- throw new Error(
169
- `Failed to extract zip file. Please ensure 'unzip' is installed. Error: ${err.message || error}`
170
- );
171
- }
172
- }
173
- console.log(`✓ Extracted to ${extractDir}`);
174
- }
175
-
176
- async function copyFiles(sourceDir: string, targetDir: string, files: string[]): Promise<void> {
177
- mkdirSync(targetDir, { recursive: true });
178
-
179
- for (const file of files) {
180
- const sourcePath = path.join(sourceDir, "platform-tools", file);
181
- const targetPath = path.join(targetDir, file);
182
-
183
- if (!existsSync(sourcePath)) {
184
- console.warn(`Warning: ${file} not found in ${sourcePath}`);
185
- continue;
186
- }
187
-
188
- copyFileSync(sourcePath, targetPath);
189
- console.log(`✓ Copied ${file}`);
190
- }
191
- }
192
-
193
- function makeExecutable(filePath: string): void {
194
- if (process.platform !== "win32") {
195
- chmodSync(filePath, 0o755);
196
- }
197
- }
198
-
199
- async function cleanupDir(dirPath: string): Promise<void> {
200
- try {
201
- const { rimraf } = await import("rimraf");
202
- await rimraf(dirPath);
203
- } catch {
204
- // Ignore cleanup errors
205
- }
206
- }
207
-
208
- // ============================================================================
209
- // Export Functions
210
- // ============================================================================
211
-
212
- type PlatformType = "windows" | "darwin" | "linux";
213
-
214
- async function exportPlatformResources(platform: PlatformType, targetDir: string): Promise<void> {
215
- console.log(`\n=== Exporting ${platform} Resources ===\n`);
216
-
217
- const binDir = path.join(targetDir, "bin", platform);
218
- const files = PLATFORM_FILES[platform];
219
- const url = ADB_URLS[platform];
220
-
221
- // Create temp directory for extraction
222
- const tempDir = path.join(targetDir, ".temp", platform);
223
- mkdirSync(tempDir, { recursive: true });
224
- const zipPath = path.join(tempDir, `platform-tools-${platform}.zip`);
225
-
226
- try {
227
- // Download
228
- await downloadFile(url, zipPath);
229
-
230
- // Extract
231
- await extractZip(zipPath, tempDir);
232
-
233
- // Copy files to target
234
- await copyFiles(tempDir, binDir, files);
235
-
236
- // Make executable on Unix
237
- if (platform !== "windows") {
238
- for (const file of files) {
239
- makeExecutable(path.join(binDir, file));
240
- }
241
- }
242
-
243
- console.log(`\n✓ ${platform} resources exported to: ${binDir}`);
244
- } finally {
245
- // Clean up temp directory
246
- await cleanupDir(tempDir);
247
- }
248
- }
249
-
250
- // ============================================================================
251
- // License
252
- // ============================================================================
253
-
254
- function createLicenseFile(targetDir: string): void {
255
- const licensesDir = path.join(targetDir, "licenses");
256
- mkdirSync(licensesDir, { recursive: true });
257
-
258
- const apacheLicense = `Apache License
259
- Version 2.0, January 2004
260
- http://www.apache.org/licenses/
261
-
262
- Android Debug Bridge (ADB) is licensed under the Apache License 2.0.
263
-
264
- For full license text, see:
265
- https://www.apache.org/licenses/LICENSE-2.0
266
-
267
- These binaries are downloaded from Google's official Android SDK repository:
268
- https://developer.android.com/studio/releases/platform-tools
269
-
270
- Source code is available at:
271
- https://android.googlesource.com/platform/packages/modules/adb/
272
- `;
273
-
274
- const licensePath = path.join(licensesDir, "APACHE-2.0.txt");
275
- writeFileSync(licensePath, apacheLicense);
276
- console.log(`✓ Created license file: ${licensePath}`);
277
- }
278
-
279
- // ============================================================================
280
- // Main
281
- // ============================================================================
282
-
283
- async function main(): Promise<void> {
284
- const args = process.argv.slice(2);
285
-
286
- if (args.length === 0 || args.includes("--help") || args.includes("-h")) {
287
- printUsage();
288
- process.exit(args.length === 0 ? 1 : 0);
289
- }
290
-
291
- const targetPath = path.resolve(args[0]);
292
-
293
- // Check for optional platform argument
294
- let platforms: PlatformType[];
295
- if (args.includes("--all")) {
296
- platforms = ["windows", "darwin", "linux"];
297
- } else if (args.includes("--platform")) {
298
- const platformIdx = args.indexOf("--platform");
299
- const platformArg = args[platformIdx + 1] as PlatformType;
300
- if (!["windows", "darwin", "linux"].includes(platformArg)) {
301
- console.error(`Invalid platform: ${platformArg}`);
302
- console.error("Valid platforms: windows, darwin, linux");
303
- process.exit(1);
304
- }
305
- platforms = [platformArg];
306
- } else {
307
- // Default to current platform
308
- const currentPlatform = process.platform === "win32" ? "windows" : process.platform;
309
- if (!["windows", "darwin", "linux"].includes(currentPlatform)) {
310
- console.error(`Unsupported platform: ${currentPlatform}`);
311
- process.exit(1);
312
- }
313
- platforms = [currentPlatform as PlatformType];
314
- }
315
-
316
- console.log("=== ADB Resources Export ===");
317
- console.log(`Target: ${targetPath}`);
318
- console.log(`Platforms: ${platforms.join(", ")}`);
319
-
320
- // Create target directory
321
- mkdirSync(targetPath, { recursive: true });
322
-
323
- // Export resources for each platform
324
- for (const platform of platforms) {
325
- await exportPlatformResources(platform, targetPath);
326
- }
327
-
328
- // Create license file
329
- console.log("");
330
- createLicenseFile(targetPath);
331
-
332
- // Clean up temp directory
333
- await cleanupDir(path.join(targetPath, ".temp"));
334
-
335
- console.log("\n=== Export Complete ===");
336
- console.log(`Resources exported to: ${targetPath}`);
337
- }
338
-
339
- main().catch((error) => {
340
- console.error("Export failed:", error);
341
- process.exit(1);
342
- });
1
+ #!/usr/bin/env tsx
2
+ /**
3
+ * Export ADB (Android Debug Bridge) resources to a specified path
4
+ *
5
+ * This script downloads ADB platform tools from Google and exports them
6
+ * to a target directory. The resources can then be used by applications
7
+ * that depend on adb-kit.
8
+ *
9
+ * Usage:
10
+ * npx tsx export-resources.ts <target-path>
11
+ *
12
+ * Example:
13
+ * npx tsx export-resources.ts /path/to/my-app/resources/adb-kit
14
+ *
15
+ * Platform support:
16
+ * - macOS: Downloads darwin platform-tools from Google
17
+ * - Windows: Downloads windows platform-tools from Google
18
+ * - Linux: Downloads linux platform-tools from Google
19
+ */
20
+
21
+ import { exec } from "node:child_process";
22
+ import {
23
+ chmodSync,
24
+ copyFileSync,
25
+ createWriteStream,
26
+ existsSync,
27
+ mkdirSync,
28
+ writeFileSync,
29
+ } from "node:fs";
30
+ import path from "node:path";
31
+ import { promisify } from "node:util";
32
+
33
+ const execAsync = promisify(exec);
34
+
35
+ // ============================================================================
36
+ // Configuration
37
+ // ============================================================================
38
+
39
+ // ADB download URLs from Google
40
+ const ADB_URLS: Record<string, string> = {
41
+ windows: "https://dl.google.com/android/repository/platform-tools-latest-windows.zip",
42
+ darwin: "https://dl.google.com/android/repository/platform-tools-latest-darwin.zip",
43
+ linux: "https://dl.google.com/android/repository/platform-tools-latest-linux.zip",
44
+ };
45
+
46
+ // Files to extract from platform-tools per platform
47
+ const PLATFORM_FILES: Record<string, string[]> = {
48
+ windows: ["adb.exe", "AdbWinApi.dll", "AdbWinUsbApi.dll"],
49
+ darwin: ["adb"],
50
+ linux: ["adb"],
51
+ };
52
+
53
+ // ============================================================================
54
+ // Utility Functions
55
+ // ============================================================================
56
+
57
+ function printUsage(): void {
58
+ console.log(`
59
+ Usage: npx tsx export-resources.ts <target-path>
60
+
61
+ Arguments:
62
+ target-path Directory where resources will be exported
63
+
64
+ Examples:
65
+ npx tsx export-resources.ts ./my-app/resources/adb-kit
66
+ npx tsx export-resources.ts /absolute/path/to/resources
67
+
68
+ The script will create the following structure:
69
+ <target-path>/
70
+ bin/
71
+ darwin/ (macOS ADB binary)
72
+ windows/ (Windows ADB binaries and DLLs)
73
+ linux/ (Linux ADB binary)
74
+ licenses/
75
+ APACHE-2.0.txt
76
+ `);
77
+ }
78
+
79
+ async function downloadFile(url: string, destPath: string): Promise<void> {
80
+ console.log(`Downloading ${url}...`);
81
+
82
+ let response: Response;
83
+ try {
84
+ response = await fetch(url);
85
+ } catch {
86
+ // Fallback to https module if fetch is not available
87
+ const https = await import("node:https");
88
+ const http = await import("node:http");
89
+ const urlObj = new URL(url);
90
+ const client = urlObj.protocol === "https:" ? https : http;
91
+
92
+ return new Promise((resolve, reject) => {
93
+ const fileStream = createWriteStream(destPath);
94
+ const request = client.get(url, (res) => {
95
+ if (res.statusCode && res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
96
+ // Handle redirect
97
+ fileStream.close();
98
+ return downloadFile(res.headers.location, destPath).then(resolve).catch(reject);
99
+ }
100
+ if (res.statusCode && res.statusCode !== 200) {
101
+ fileStream.close();
102
+ reject(new Error(`Failed to download ${url}: ${res.statusCode} ${res.statusMessage}`));
103
+ return;
104
+ }
105
+ res.pipe(fileStream);
106
+ fileStream.on("finish", () => {
107
+ fileStream.close();
108
+ resolve();
109
+ });
110
+ });
111
+ request.on("error", (err) => {
112
+ fileStream.close();
113
+ reject(err);
114
+ });
115
+ });
116
+ }
117
+
118
+ if (!response.ok) {
119
+ throw new Error(`Failed to download ${url}: ${response.statusText}`);
120
+ }
121
+
122
+ const fileStream = createWriteStream(destPath);
123
+ const reader = response.body?.getReader();
124
+ if (!reader) {
125
+ throw new Error(`Failed to get response body for ${url}`);
126
+ }
127
+
128
+ try {
129
+ while (true) {
130
+ const { done, value } = await reader.read();
131
+ if (done) break;
132
+ fileStream.write(value);
133
+ }
134
+ fileStream.end();
135
+ await new Promise<void>((resolve, reject) => {
136
+ fileStream.on("finish", resolve);
137
+ fileStream.on("error", reject);
138
+ });
139
+ console.log(`✓ Downloaded to ${destPath}`);
140
+ } finally {
141
+ reader.releaseLock();
142
+ }
143
+ }
144
+
145
+ async function extractZip(zipPath: string, extractDir: string): Promise<void> {
146
+ console.log(`Extracting ${zipPath}...`);
147
+
148
+ if (process.platform === "win32") {
149
+ // On Windows, use PowerShell Expand-Archive
150
+ try {
151
+ const escapedZipPath = zipPath.replace(/'/g, "''");
152
+ const escapedExtractDir = extractDir.replace(/'/g, "''");
153
+ await execAsync(
154
+ `powershell -Command "Expand-Archive -Path '${escapedZipPath}' -DestinationPath '${escapedExtractDir}' -Force"`
155
+ );
156
+ } catch (error) {
157
+ const err = error as { message?: string };
158
+ throw new Error(
159
+ `Failed to extract zip file. Please ensure PowerShell is available. Error: ${err.message || error}`
160
+ );
161
+ }
162
+ } else {
163
+ // On Unix-like systems, use unzip command
164
+ try {
165
+ await execAsync(`unzip -o "${zipPath}" -d "${extractDir}"`);
166
+ } catch (error) {
167
+ const err = error as { message?: string };
168
+ throw new Error(
169
+ `Failed to extract zip file. Please ensure 'unzip' is installed. Error: ${err.message || error}`
170
+ );
171
+ }
172
+ }
173
+ console.log(`✓ Extracted to ${extractDir}`);
174
+ }
175
+
176
+ async function copyFiles(sourceDir: string, targetDir: string, files: string[]): Promise<void> {
177
+ mkdirSync(targetDir, { recursive: true });
178
+
179
+ for (const file of files) {
180
+ const sourcePath = path.join(sourceDir, "platform-tools", file);
181
+ const targetPath = path.join(targetDir, file);
182
+
183
+ if (!existsSync(sourcePath)) {
184
+ console.warn(`Warning: ${file} not found in ${sourcePath}`);
185
+ continue;
186
+ }
187
+
188
+ copyFileSync(sourcePath, targetPath);
189
+ console.log(`✓ Copied ${file}`);
190
+ }
191
+ }
192
+
193
+ function makeExecutable(filePath: string): void {
194
+ if (process.platform !== "win32") {
195
+ chmodSync(filePath, 0o755);
196
+ }
197
+ }
198
+
199
+ async function cleanupDir(dirPath: string): Promise<void> {
200
+ try {
201
+ const { rimraf } = await import("rimraf");
202
+ await rimraf(dirPath);
203
+ } catch {
204
+ // Ignore cleanup errors
205
+ }
206
+ }
207
+
208
+ // ============================================================================
209
+ // Export Functions
210
+ // ============================================================================
211
+
212
+ type PlatformType = "windows" | "darwin" | "linux";
213
+
214
+ async function exportPlatformResources(platform: PlatformType, targetDir: string): Promise<void> {
215
+ console.log(`\n=== Exporting ${platform} Resources ===\n`);
216
+
217
+ const binDir = path.join(targetDir, "bin", platform);
218
+ const files = PLATFORM_FILES[platform];
219
+ const url = ADB_URLS[platform];
220
+
221
+ // Create temp directory for extraction
222
+ const tempDir = path.join(targetDir, ".temp", platform);
223
+ mkdirSync(tempDir, { recursive: true });
224
+ const zipPath = path.join(tempDir, `platform-tools-${platform}.zip`);
225
+
226
+ try {
227
+ // Download
228
+ await downloadFile(url, zipPath);
229
+
230
+ // Extract
231
+ await extractZip(zipPath, tempDir);
232
+
233
+ // Copy files to target
234
+ await copyFiles(tempDir, binDir, files);
235
+
236
+ // Make executable on Unix
237
+ if (platform !== "windows") {
238
+ for (const file of files) {
239
+ makeExecutable(path.join(binDir, file));
240
+ }
241
+ }
242
+
243
+ console.log(`\n✓ ${platform} resources exported to: ${binDir}`);
244
+ } finally {
245
+ // Clean up temp directory
246
+ await cleanupDir(tempDir);
247
+ }
248
+ }
249
+
250
+ // ============================================================================
251
+ // License
252
+ // ============================================================================
253
+
254
+ function createLicenseFile(targetDir: string): void {
255
+ const licensesDir = path.join(targetDir, "licenses");
256
+ mkdirSync(licensesDir, { recursive: true });
257
+
258
+ const apacheLicense = `Apache License
259
+ Version 2.0, January 2004
260
+ http://www.apache.org/licenses/
261
+
262
+ Android Debug Bridge (ADB) is licensed under the Apache License 2.0.
263
+
264
+ For full license text, see:
265
+ https://www.apache.org/licenses/LICENSE-2.0
266
+
267
+ These binaries are downloaded from Google's official Android SDK repository:
268
+ https://developer.android.com/studio/releases/platform-tools
269
+
270
+ Source code is available at:
271
+ https://android.googlesource.com/platform/packages/modules/adb/
272
+ `;
273
+
274
+ const licensePath = path.join(licensesDir, "APACHE-2.0.txt");
275
+ writeFileSync(licensePath, apacheLicense);
276
+ console.log(`✓ Created license file: ${licensePath}`);
277
+ }
278
+
279
+ // ============================================================================
280
+ // Main
281
+ // ============================================================================
282
+
283
+ async function main(): Promise<void> {
284
+ const args = process.argv.slice(2);
285
+
286
+ if (args.length === 0 || args.includes("--help") || args.includes("-h")) {
287
+ printUsage();
288
+ process.exit(args.length === 0 ? 1 : 0);
289
+ }
290
+
291
+ const targetPath = path.resolve(args[0]);
292
+
293
+ // Check for optional platform argument
294
+ let platforms: PlatformType[];
295
+ if (args.includes("--all")) {
296
+ platforms = ["windows", "darwin", "linux"];
297
+ } else if (args.includes("--platform")) {
298
+ const platformIdx = args.indexOf("--platform");
299
+ const platformArg = args[platformIdx + 1] as PlatformType;
300
+ if (!["windows", "darwin", "linux"].includes(platformArg)) {
301
+ console.error(`Invalid platform: ${platformArg}`);
302
+ console.error("Valid platforms: windows, darwin, linux");
303
+ process.exit(1);
304
+ }
305
+ platforms = [platformArg];
306
+ } else {
307
+ // Default to current platform
308
+ const currentPlatform = process.platform === "win32" ? "windows" : process.platform;
309
+ if (!["windows", "darwin", "linux"].includes(currentPlatform)) {
310
+ console.error(`Unsupported platform: ${currentPlatform}`);
311
+ process.exit(1);
312
+ }
313
+ platforms = [currentPlatform as PlatformType];
314
+ }
315
+
316
+ console.log("=== ADB Resources Export ===");
317
+ console.log(`Target: ${targetPath}`);
318
+ console.log(`Platforms: ${platforms.join(", ")}`);
319
+
320
+ // Create target directory
321
+ mkdirSync(targetPath, { recursive: true });
322
+
323
+ // Export resources for each platform
324
+ for (const platform of platforms) {
325
+ await exportPlatformResources(platform, targetPath);
326
+ }
327
+
328
+ // Create license file
329
+ console.log("");
330
+ createLicenseFile(targetPath);
331
+
332
+ // Clean up temp directory
333
+ await cleanupDir(path.join(targetPath, ".temp"));
334
+
335
+ console.log("\n=== Export Complete ===");
336
+ console.log(`Resources exported to: ${targetPath}`);
337
+ }
338
+
339
+ main().catch((error) => {
340
+ console.error("Export failed:", error);
341
+ process.exit(1);
342
+ });