create-droid 1.0.4 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-droid",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "The fastest way to start an Android project. No Studio required.",
5
5
  "author": "YELrhilassi",
6
6
  "license": "MIT",
@@ -1,47 +1,156 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
- const { spawn } = require('child_process');
3
+ const { spawn, execSync } = require('child_process');
4
+ const readline = require('readline');
4
5
  const os = require('os');
5
6
 
6
- // 1. Find SDK Location from local.properties
7
+ // --- Configuration ---
7
8
  const projectRoot = path.resolve(__dirname, '..');
8
9
  const localPropertiesPath = path.join(projectRoot, 'local.properties');
9
10
  let sdkPath = process.env.ANDROID_HOME;
10
11
 
12
+ // --- 1. Resolve ADB Path ---
11
13
  if (fs.existsSync(localPropertiesPath)) {
12
14
  const content = fs.readFileSync(localPropertiesPath, 'utf8');
13
15
  const match = content.match(/^sdk\.dir=(.*)$/m);
14
16
  if (match) {
15
- sdkPath = match[1].trim().replace(/\\\\/g, '\\'); // Handle Windows escaping if present
17
+ sdkPath = match[1].trim().replace(/\\\\/g, '\\');
16
18
  }
17
19
  }
18
20
 
19
- if (!sdkPath) {
20
- console.error('❌ Could not find SDK location. Set ANDROID_HOME or create local.properties.');
21
- process.exit(1);
22
- }
23
-
24
- // 2. Resolve ADB binary
25
21
  const isWin = os.platform() === 'win32';
26
22
  const adbBinary = isWin ? 'adb.exe' : 'adb';
27
- const adbPath = path.join(sdkPath, 'platform-tools', adbBinary);
23
+ const localAdbPath = sdkPath ? path.join(sdkPath, 'platform-tools', adbBinary) : null;
24
+ const finalAdbPath = (localAdbPath && fs.existsSync(localAdbPath)) ? localAdbPath : 'adb';
28
25
 
29
- if (!fs.existsSync(adbPath)) {
30
- // Fallback to global adb if local not found
31
- console.warn(`⚠️ Local ADB not found at ${adbPath}. Trying global 'adb'...`);
26
+ // --- 2. Helper Functions ---
27
+ function runCommand(args, inherit = true) {
28
+ if (inherit) {
29
+ const child = spawn(finalAdbPath, args, { stdio: 'inherit' });
30
+ return new Promise((resolve) => {
31
+ child.on('close', (code) => resolve(code));
32
+ });
33
+ } else {
34
+ try {
35
+ return execSync(`"${finalAdbPath}" ${args.join(' ')}`, { encoding: 'utf8' }).trim();
36
+ } catch (e) {
37
+ return null;
38
+ }
39
+ }
32
40
  }
33
41
 
34
- // 3. Run ADB with arguments
35
- const args = process.argv.slice(2);
36
- const finalAdbPath = fs.existsSync(adbPath) ? adbPath : 'adb';
42
+ function clearScreen() {
43
+ process.stdout.write('\x1Bc');
44
+ }
45
+
46
+ // --- 3. Interactive Menu ---
47
+ async function showMenu() {
48
+ clearScreen();
49
+ console.log('\x1b[36m%s\x1b[0m', '🤖 Android Debug Bridge (ADB) Manager');
50
+ console.log('-----------------------------------');
51
+ console.log('1. 📱 List Connected Devices');
52
+ console.log('2. 📡 Connect to Device (Wi-Fi)');
53
+ console.log('3. 🔗 Pair Device (Android 11+)');
54
+ console.log('4. 🔄 Reverse Port 8081 (React Native/Metro)');
55
+ console.log('5. 📜 Stream Logcat');
56
+ console.log('6. 💀 Kill ADB Server');
57
+ console.log('0. 🚪 Exit');
58
+ console.log('-----------------------------------');
59
+
60
+ const rl = readline.createInterface({
61
+ input: process.stdin,
62
+ output: process.stdout
63
+ });
64
+
65
+ rl.question('Select option: ', async (answer) => {
66
+ rl.close();
67
+ switch (answer.trim()) {
68
+ case '1':
69
+ await runCommand(['devices', '-l']);
70
+ await pause();
71
+ showMenu();
72
+ break;
73
+ case '2':
74
+ await handleConnect();
75
+ break;
76
+ case '3':
77
+ await handlePair();
78
+ break;
79
+ case '4':
80
+ console.log('Reversing tcp:8081...');
81
+ await runCommand(['reverse', 'tcp:8081', 'tcp:8081']);
82
+ await pause();
83
+ showMenu();
84
+ break;
85
+ case '5':
86
+ console.log('Starting Logcat (Ctrl+C to stop)...');
87
+ await runCommand(['logcat']);
88
+ // Logcat blocks, so we won't return easily loop unless killed
89
+ break;
90
+ case '6':
91
+ await runCommand(['kill-server']);
92
+ console.log('Server killed.');
93
+ await pause();
94
+ showMenu();
95
+ break;
96
+ case '0':
97
+ process.exit(0);
98
+ break;
99
+ default:
100
+ showMenu();
101
+ }
102
+ });
103
+ }
104
+
105
+ async function handleConnect() {
106
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
107
+ rl.question('Enter Device IP:Port (e.g., 192.168.1.5:5555): ', async (ip) => {
108
+ rl.close();
109
+ if (ip) {
110
+ console.log(`Connecting to ${ip}...`);
111
+ await runCommand(['connect', ip]);
112
+ }
113
+ await pause();
114
+ showMenu();
115
+ });
116
+ }
117
+
118
+ async function handlePair() {
119
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
120
+ rl.question('Enter Device IP:Port (from "Wireless debugging"): ', (ip) => {
121
+ rl.question('Enter Pairing Code: ', async (code) => {
122
+ rl.close();
123
+ if (ip && code) {
124
+ console.log(`Pairing with ${ip}...`);
125
+ await runCommand(['pair', ip, code]);
126
+ }
127
+ await pause();
128
+ showMenu();
129
+ });
130
+ });
131
+ }
37
132
 
38
- const child = spawn(finalAdbPath, args, { stdio: 'inherit' });
133
+ function pause() {
134
+ return new Promise((resolve) => {
135
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
136
+ rl.question('\nPress Enter to continue...', () => {
137
+ rl.close();
138
+ resolve();
139
+ });
140
+ });
141
+ }
39
142
 
40
- child.on('error', (err) => {
41
- console.error(`❌ Failed to start ADB: ${err.message}`);
42
- process.exit(1);
43
- });
143
+ // --- 4. Main Execution ---
144
+ const args = process.argv.slice(2);
44
145
 
45
- child.on('close', (code) => {
46
- process.exit(code);
47
- });
146
+ if (args.length > 0) {
147
+ // Pass-through mode (e.g., npm run adb connect ...)
148
+ const child = spawn(finalAdbPath, args, { stdio: 'inherit' });
149
+ child.on('close', (code) => process.exit(code));
150
+ } else {
151
+ // Interactive mode
152
+ if (!sdkPath && !process.env.ANDROID_HOME) {
153
+ console.warn('⚠️ ANDROID_HOME not set. Trying global ADB...');
154
+ }
155
+ showMenu();
156
+ }