devicely 2.1.3 → 2.1.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/bin/devicely.js +105 -1
- package/lib/androidDeviceDetection.js +276 -1
- package/lib/appMappings.js +337 -1
- package/lib/deviceDetection.js +394 -1
- package/lib/devices.js +54 -1
- package/lib/doctor.js +94 -1
- package/lib/executor.js +104 -1
- package/lib/logger.js +35 -1
- package/lib/scriptLoader.js +75 -0
- package/lib/server.js +3483 -1
- package/package.json +3 -12
- package/scripts/compile-shell-scripts.js +208 -0
- package/scripts/encrypt-shell-simple.js +75 -0
- package/scripts/obfuscate-shell.js +160 -0
- package/scripts/shell/android_device_control +0 -0
- package/scripts/shell/android_device_control.sh +848 -0
- package/scripts/shell/apps_presets.conf +271 -0
- package/scripts/shell/connect_android_usb +0 -0
- package/scripts/shell/connect_android_usb_multi_final +0 -0
- package/scripts/shell/connect_android_usb_multi_final.sh +289 -0
- package/scripts/shell/connect_android_wireless +0 -0
- package/scripts/shell/connect_android_wireless.sh +58 -0
- package/scripts/shell/connect_android_wireless_multi_final +0 -0
- package/scripts/shell/connect_android_wireless_multi_final.sh +476 -0
- package/scripts/shell/connect_ios_usb +0 -0
- package/scripts/shell/connect_ios_usb_multi_final +0 -0
- package/scripts/shell/connect_ios_usb_multi_final.sh +4225 -0
- package/scripts/shell/connect_ios_wireless_multi_final +0 -0
- package/scripts/shell/connect_ios_wireless_multi_final.sh +4167 -0
- package/scripts/shell/create_production_scripts +0 -0
- package/scripts/shell/create_production_scripts.sh +38 -0
- package/scripts/shell/devices.conf +24 -0
- package/scripts/shell/diagnose_wireless_ios +0 -0
- package/scripts/shell/find_element_coordinates +0 -0
- package/scripts/shell/find_wda +0 -0
- package/scripts/shell/install_uiautomator2 +0 -0
- package/scripts/shell/install_uiautomator2.sh +93 -0
- package/scripts/shell/ios_device_control +0 -0
- package/scripts/shell/ios_device_control.sh +220 -0
- package/scripts/shell/organize_project +0 -0
- package/scripts/shell/organize_project.sh +59 -0
- package/scripts/shell/pre-publish-check +0 -0
- package/scripts/shell/pre-publish-check.sh +238 -0
- package/scripts/shell/publish +0 -0
- package/scripts/shell/publish-to-npm +0 -0
- package/scripts/shell/publish-to-npm.sh +366 -0
- package/scripts/shell/publish.sh +100 -0
- package/scripts/shell/setup +0 -0
- package/scripts/shell/setup.sh +121 -0
- package/scripts/shell/setup_android +0 -0
- package/scripts/shell/start +0 -0
- package/scripts/shell/start.sh +59 -0
- package/scripts/shell/sync-to-npm-package-final +0 -0
- package/scripts/shell/sync-to-npm-package-final.sh +60 -0
- package/scripts/shell/test-local-package.sh +95 -0
- package/scripts/shell/test_android_locators +0 -0
- package/scripts/shell/test_connect +0 -0
- package/scripts/shell/test_device_detection +0 -0
- package/scripts/shell/test_fixes +0 -0
- package/scripts/shell/test_getlocators_fix +0 -0
- package/scripts/shell/test_recording_feature +0 -0
- package/scripts/shell/verify-shell-protection +0 -0
- package/scripts/shell/verify-shell-protection.sh +73 -0
- package/scripts/shell/verify_distribution +0 -0
- package/lib/package-lock.json +0 -1678
- package/lib/package.json +0 -30
- package/lib/screenshots/screenshot_ios_iPhone17_20260205_225900.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhone17_20260205_225942.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhone17_20260205_231101.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhone17_20260205_232911.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhone17_20260208_095103.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhone17_20260208_095720.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhoneXR17x_20260206_115040.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhoneXR17x_20260206_115047.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhoneXR17x_20260206_115118.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhoneXR17x_20260206_115125.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhoneXR17x_20260206_115143.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhoneXR17x_20260206_120107.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhoneXR17x_20260206_120118.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhoneXR17x_20260206_120137.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhoneXR17x_20260206_120201.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhoneXR17x_20260206_134529.png +0 -0
- package/scripts/shell/android_device_control.enc +0 -1
- package/scripts/shell/connect_android_usb_multi_final.enc +0 -1
- package/scripts/shell/connect_android_wireless.enc +0 -1
- package/scripts/shell/connect_android_wireless_multi_final.enc +0 -1
- package/scripts/shell/connect_ios_usb_multi_final.enc +0 -1
- package/scripts/shell/connect_ios_wireless_multi_final.enc +0 -1
- package/scripts/shell/ios_device_control.enc +0 -1
package/lib/executor.js
CHANGED
|
@@ -1 +1,104 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Command executor for Devicely CLI
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const { spawn } = require('child_process');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const chalk = require('chalk');
|
|
8
|
+
|
|
9
|
+
// Import deviceDetection from appropriate location
|
|
10
|
+
let discoverAllDevices;
|
|
11
|
+
try {
|
|
12
|
+
({ discoverAllDevices } = require('./deviceDetection'));
|
|
13
|
+
} catch (err) {
|
|
14
|
+
({ discoverAllDevices } = require('../../deviceDetection'));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async function executeCommand(command, options = {}) {
|
|
18
|
+
const devices = await discoverAllDevices();
|
|
19
|
+
|
|
20
|
+
if (!devices || devices.length === 0) {
|
|
21
|
+
console.log(chalk.red('\n❌ No devices found'));
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
let targetDevices = devices.filter(d => d.status === 'online');
|
|
26
|
+
|
|
27
|
+
if (options.device) {
|
|
28
|
+
targetDevices = devices.filter(d =>
|
|
29
|
+
d.name === options.device && d.status === 'online'
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
if (targetDevices.length === 0) {
|
|
33
|
+
console.log(chalk.red(`\n❌ Device "${options.device}" not found or offline`));
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (targetDevices.length === 0) {
|
|
39
|
+
console.log(chalk.yellow('\n⚠️ No online devices found'));
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
console.log(chalk.cyan(`\nExecuting on ${targetDevices.length} device(s):`));
|
|
44
|
+
targetDevices.forEach(d => console.log(` • ${d.name}`));
|
|
45
|
+
console.log('');
|
|
46
|
+
|
|
47
|
+
const scriptDir = path.join(__dirname, '../../scripts/shell');
|
|
48
|
+
|
|
49
|
+
for (const device of targetDevices) {
|
|
50
|
+
const platform = device.platform;
|
|
51
|
+
const type = device.type;
|
|
52
|
+
|
|
53
|
+
let scriptName;
|
|
54
|
+
if (platform === 'ios' && type === 'usb') {
|
|
55
|
+
scriptName = 'connect_ios_usb_multi_final.sh';
|
|
56
|
+
} else if (platform === 'ios' && type === 'wireless') {
|
|
57
|
+
scriptName = 'connect_ios_wireless_multi_final.sh';
|
|
58
|
+
} else if (platform === 'android' && type === 'usb') {
|
|
59
|
+
scriptName = 'connect_android_usb_multi_final.sh';
|
|
60
|
+
} else if (platform === 'android' && type === 'wireless') {
|
|
61
|
+
scriptName = 'connect_android_wireless_multi_final.sh';
|
|
62
|
+
} else {
|
|
63
|
+
console.log(chalk.yellow(`⚠️ Unsupported device type: ${platform}-${type}`));
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const scriptPath = path.join(scriptDir, scriptName);
|
|
68
|
+
|
|
69
|
+
console.log(chalk.blue(`[${device.name}] Running command...`));
|
|
70
|
+
|
|
71
|
+
const child = spawn(scriptPath, ['-d', device.name, ...command.split(' ')], {
|
|
72
|
+
stdio: 'pipe'
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
child.stdout.on('data', (data) => {
|
|
76
|
+
const lines = data.toString().split('\n').filter(l => l.trim());
|
|
77
|
+
lines.forEach(line => {
|
|
78
|
+
console.log(chalk.gray(` ${line}`));
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
child.stderr.on('data', (data) => {
|
|
83
|
+
const lines = data.toString().split('\n').filter(l => l.trim());
|
|
84
|
+
lines.forEach(line => {
|
|
85
|
+
console.log(chalk.red(` ${line}`));
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
await new Promise((resolve) => {
|
|
90
|
+
child.on('close', (code) => {
|
|
91
|
+
if (code === 0) {
|
|
92
|
+
console.log(chalk.green(`[${device.name}] ✅ Success\n`));
|
|
93
|
+
} else {
|
|
94
|
+
console.log(chalk.red(`[${device.name}] ❌ Failed (exit code: ${code})\n`));
|
|
95
|
+
}
|
|
96
|
+
resolve();
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
module.exports = {
|
|
103
|
+
executeCommand
|
|
104
|
+
};
|
package/lib/logger.js
CHANGED
|
@@ -1 +1,35 @@
|
|
|
1
|
-
|
|
1
|
+
// Centralized Logger for Production
|
|
2
|
+
// Use environment variable to control debug output
|
|
3
|
+
|
|
4
|
+
const DEBUG_MODE = process.env.DEBUG === 'true' || process.env.NODE_ENV === 'development';
|
|
5
|
+
|
|
6
|
+
class Logger {
|
|
7
|
+
constructor(module) {
|
|
8
|
+
this.module = module;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
debug(...args) {
|
|
12
|
+
if (DEBUG_MODE) {
|
|
13
|
+
console.log(`[DEBUG][${this.module}]`, ...args);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
info(...args) {
|
|
18
|
+
console.log(`[INFO][${this.module}]`, ...args);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
warn(...args) {
|
|
22
|
+
console.warn(`[WARN][${this.module}]`, ...args);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
error(...args) {
|
|
26
|
+
console.error(`[ERROR][${this.module}]`, ...args);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Keep critical startup/connection messages
|
|
30
|
+
startup(...args) {
|
|
31
|
+
console.log(`[STARTUP][${this.module}]`, ...args);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
module.exports = Logger;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const crypto = require('crypto');
|
|
4
|
+
const os = require('os');
|
|
5
|
+
|
|
6
|
+
function generateKey() {
|
|
7
|
+
const pkg = require('../package.json');
|
|
8
|
+
return crypto.createHash('sha256').update(pkg.name + pkg.version).digest();
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function decryptScript(encPath) {
|
|
12
|
+
const data = JSON.parse(fs.readFileSync(encPath, 'utf8'));
|
|
13
|
+
const key = generateKey();
|
|
14
|
+
const decipher = crypto.createDecipheriv('aes-256-cbc', key, Buffer.from(data.iv, 'hex'));
|
|
15
|
+
let decrypted = decipher.update(data.content, 'hex', 'utf8');
|
|
16
|
+
decrypted += decipher.final('utf8');
|
|
17
|
+
return decrypted;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function prepareScripts() {
|
|
21
|
+
const shellDir = path.join(__dirname, '../scripts/shell');
|
|
22
|
+
const tmpDir = path.join(os.tmpdir(), 'devicely_scripts_' + process.pid);
|
|
23
|
+
|
|
24
|
+
if (!fs.existsSync(tmpDir)) {
|
|
25
|
+
fs.mkdirSync(tmpDir, { recursive: true, mode: 0o700 });
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (!fs.existsSync(shellDir)) {
|
|
29
|
+
return tmpDir;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const encFiles = fs.readdirSync(shellDir).filter(f => f.endsWith('.enc'));
|
|
33
|
+
|
|
34
|
+
if (encFiles.length === 0) {
|
|
35
|
+
return tmpDir;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
console.log(`🔓 Decrypting ${encFiles.length} protected scripts...`);
|
|
39
|
+
|
|
40
|
+
encFiles.forEach(encFile => {
|
|
41
|
+
const encPath = path.join(shellDir, encFile);
|
|
42
|
+
const scriptName = encFile.replace('.enc', '.sh');
|
|
43
|
+
const tmpScript = path.join(tmpDir, scriptName);
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
const content = decryptScript(encPath);
|
|
47
|
+
fs.writeFileSync(tmpScript, content, { mode: 0o755 });
|
|
48
|
+
} catch (error) {
|
|
49
|
+
console.error(` ❌ Failed to decrypt ${encFile}: ${error.message}`);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
console.log(`✅ Scripts ready in temp directory\n`);
|
|
54
|
+
|
|
55
|
+
process.on('exit', () => {
|
|
56
|
+
try {
|
|
57
|
+
if (fs.existsSync(tmpDir)) {
|
|
58
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
59
|
+
}
|
|
60
|
+
} catch(e) {}
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
process.on('SIGINT', () => {
|
|
64
|
+
try {
|
|
65
|
+
if (fs.existsSync(tmpDir)) {
|
|
66
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
67
|
+
}
|
|
68
|
+
} catch(e) {}
|
|
69
|
+
process.exit();
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
return tmpDir;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
module.exports = { prepareScripts, decryptScript };
|