gf-packages-cli 1.0.4 → 1.0.6
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/cli.js +7 -1
- package/lib/common/appCommon.js +27 -3
- package/lib/common/updateCheck.js +66 -0
- package/package.json +2 -2
- package/src/deletePackage.js +5 -0
- package/src/exportPackage.js +1 -2
package/bin/cli.js
CHANGED
|
@@ -5,15 +5,21 @@ const pkg = require('../package.json');
|
|
|
5
5
|
const showMenu = require('../src/index.js');
|
|
6
6
|
const exportCommand = require('../src/exportPackage.js');
|
|
7
7
|
const deleteCommand = require('../src/deletePackage.js');
|
|
8
|
+
const autoUpdate = require('../lib/common/updateCheck.js');
|
|
8
9
|
|
|
9
10
|
program
|
|
10
11
|
.version(pkg.version, '-v, --version', '查看版本')
|
|
11
12
|
.helpOption('-h, --help', '查看帮助');
|
|
12
13
|
|
|
14
|
+
// 每次执行前先检查更新(-v/-h 不触发,直接退出)
|
|
15
|
+
program.hook('preAction', async () => {
|
|
16
|
+
await autoUpdate();
|
|
17
|
+
});
|
|
18
|
+
|
|
13
19
|
// 注册 export 子命令
|
|
14
20
|
program.addCommand(exportCommand);
|
|
15
21
|
// 注册 delete 子命令
|
|
16
|
-
program.addCommand(deleteCommand);
|
|
22
|
+
program.addCommand(deleteCommand);
|
|
17
23
|
// 无子命令时,显示菜单
|
|
18
24
|
program
|
|
19
25
|
.action(() => {
|
package/lib/common/appCommon.js
CHANGED
|
@@ -4,25 +4,49 @@ const { runAdbSync } = require('../tools/adb.js');
|
|
|
4
4
|
|
|
5
5
|
// ===================== 业务逻辑 =====================
|
|
6
6
|
|
|
7
|
+
// 白名单:这些包不会出现在列表中,避免误删
|
|
8
|
+
const PACKAGE_WHITELIST = [
|
|
9
|
+
'com.google.android.verifier',
|
|
10
|
+
'com.google.android.contactkeys',
|
|
11
|
+
'com.google.android.safetycore',
|
|
12
|
+
'com.zggb.self.check',
|
|
13
|
+
'com.cloudcontrol'
|
|
14
|
+
];
|
|
15
|
+
|
|
7
16
|
async function getThirdPartyPackages(deviceId) {
|
|
8
17
|
console.log(chalk.gray('[1] 读取手机第三方应用列表...'));
|
|
9
18
|
const raw = await runAdbSync(deviceId, 'shell pm list packages -3');
|
|
10
19
|
const pkgList = raw.split(/\r?\n/)
|
|
11
20
|
.map(line => line.trim())
|
|
12
21
|
.filter(line => line.startsWith('package:'))
|
|
13
|
-
.map(line => line.replace('package:', ''))
|
|
14
|
-
|
|
22
|
+
.map(line => line.replace('package:', ''))
|
|
23
|
+
.filter(pkg => !PACKAGE_WHITELIST.includes(pkg));
|
|
24
|
+
const result = [...new Set(pkgList)];
|
|
25
|
+
if (result.length === 0) {
|
|
26
|
+
console.log(chalk.yellow('当前无第三方应用'));
|
|
27
|
+
process.exit(0);
|
|
28
|
+
}
|
|
29
|
+
return result;
|
|
15
30
|
}
|
|
16
31
|
|
|
17
32
|
|
|
18
33
|
async function selectPackages(pkgList,message) {
|
|
34
|
+
const ALL_VALUE = '__ALL__';
|
|
19
35
|
const { selectedPkgs } = await inquirer.prompt([{
|
|
20
36
|
type: 'checkbox',
|
|
21
37
|
name: 'selectedPkgs',
|
|
22
38
|
message: message,
|
|
23
|
-
choices:
|
|
39
|
+
choices: [
|
|
40
|
+
{ name: chalk.green('全选'), value: ALL_VALUE },
|
|
41
|
+
new inquirer.Separator(),
|
|
42
|
+
...pkgList.map(pkg => ({ name: pkg, value: pkg })),
|
|
43
|
+
],
|
|
24
44
|
pageSize: 15
|
|
25
45
|
}]);
|
|
46
|
+
// 选中"全选"时返回全部包
|
|
47
|
+
if (selectedPkgs.includes(ALL_VALUE)) {
|
|
48
|
+
return pkgList;
|
|
49
|
+
}
|
|
26
50
|
if (selectedPkgs.length === 0) {
|
|
27
51
|
console.log(chalk.yellow('未选择任何应用,程序退出'));
|
|
28
52
|
process.exit(0);
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
const { execSync } = require('child_process');
|
|
2
|
+
const chalk = require('chalk').default;
|
|
3
|
+
const inquirer = require('inquirer');
|
|
4
|
+
const pkg = require('../../package.json');
|
|
5
|
+
|
|
6
|
+
const PKG_NAME = pkg.name;
|
|
7
|
+
const CURRENT_VERSION = pkg.version;
|
|
8
|
+
const REGISTRY_URL = `https://registry.npmjs.org/${PKG_NAME}/latest`;
|
|
9
|
+
|
|
10
|
+
// 请求 npm registry 获取最新版本号,失败返回 null(静默跳过,不阻塞工具使用)
|
|
11
|
+
async function getLatestVersion() {
|
|
12
|
+
try {
|
|
13
|
+
const res = await fetch(REGISTRY_URL, { signal: AbortSignal.timeout(3000) });
|
|
14
|
+
if (!res.ok) return null;
|
|
15
|
+
const data = await res.json();
|
|
16
|
+
return data.version || null;
|
|
17
|
+
} catch {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// 判断 latest 是否比当前版本新
|
|
23
|
+
function isNewer(latest) {
|
|
24
|
+
if (!latest) return false;
|
|
25
|
+
const cur = CURRENT_VERSION.split('.').map(Number);
|
|
26
|
+
const lat = latest.split('.').map(Number);
|
|
27
|
+
for (let i = 0; i < Math.max(cur.length, lat.length); i++) {
|
|
28
|
+
const a = cur[i] || 0;
|
|
29
|
+
const b = lat[i] || 0;
|
|
30
|
+
if (b > a) return true;
|
|
31
|
+
if (b < a) return false;
|
|
32
|
+
}
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* 启动时自更新检查:发现新版本则提示用户,确认后自动全局更新
|
|
38
|
+
*/
|
|
39
|
+
async function autoUpdate() {
|
|
40
|
+
const latest = await getLatestVersion();
|
|
41
|
+
if (!latest) return;
|
|
42
|
+
if (!isNewer(latest)) return;
|
|
43
|
+
|
|
44
|
+
console.log(chalk.yellow(`\n发现新版本: v${CURRENT_VERSION} -> v${latest}`));
|
|
45
|
+
const { shouldUpdate } = await inquirer.prompt([{
|
|
46
|
+
type: 'confirm',
|
|
47
|
+
name: 'shouldUpdate',
|
|
48
|
+
message: '是否现在自动更新?',
|
|
49
|
+
default: true
|
|
50
|
+
}]);
|
|
51
|
+
|
|
52
|
+
if (!shouldUpdate) {
|
|
53
|
+
console.log(chalk.gray(`已跳过更新,仍使用 v${CURRENT_VERSION}`));
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
console.log(chalk.cyan(`正在自动更新 ${PKG_NAME}...`));
|
|
58
|
+
try {
|
|
59
|
+
execSync(`npm install -g ${PKG_NAME}@latest`, { stdio: 'inherit' });
|
|
60
|
+
console.log(chalk.green(`✅ 更新完成,请重启命令以使用 v${latest}`));
|
|
61
|
+
} catch (err) {
|
|
62
|
+
console.log(chalk.red(`更新失败: ${err.message}`));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
module.exports = autoUpdate;
|
package/package.json
CHANGED
package/src/deletePackage.js
CHANGED
|
@@ -23,6 +23,11 @@ async function runDelete(options = {}) {
|
|
|
23
23
|
// 实现卸载应用的逻辑
|
|
24
24
|
for (const pkg of selectedPkgs) {
|
|
25
25
|
await runAdbSync(targetDevice, `shell pm uninstall ${pkg}`);
|
|
26
|
+
await runAdbSync(targetDevice, `shell rm -rf /sdcard/Download/${pkg}.zip`);
|
|
27
|
+
await runAdbSync(targetDevice, `shell rm -rf /sdcard/Download/${pkg}.apk`);
|
|
28
|
+
await runAdbSync(targetDevice, `shell rm -rf /sdcard/Download/${pkg}.apks`);
|
|
29
|
+
await runAdbSync(targetDevice, `shell rm -rf /sdcard/Download/${pkg}.xapk`);
|
|
30
|
+
await runAdbSync(targetDevice, `shell rm -rf /sdcard/Download/${pkg}`);
|
|
26
31
|
console.log(chalk.green(`已卸载应用: ${pkg}`));
|
|
27
32
|
}
|
|
28
33
|
console.log(chalk.green('所有应用卸载完成'));
|
package/src/exportPackage.js
CHANGED
|
@@ -5,7 +5,6 @@ const { execSync, spawn } = require('child_process');
|
|
|
5
5
|
const fs = require('fs');
|
|
6
6
|
const path = require('path');
|
|
7
7
|
const os = require('os');
|
|
8
|
-
const AdmZip = require('adm-zip');
|
|
9
8
|
const archiver = require('archiver');
|
|
10
9
|
const { getDeviceList, selectDevice, runAdbSync } = require('../lib/tools/adb.js');
|
|
11
10
|
const { getThirdPartyPackages, selectPackages } = require('../lib/common/appCommon.js');
|
|
@@ -96,7 +95,7 @@ function buildApks(tmpDir, targetApksPath) {
|
|
|
96
95
|
if (apkFiles.length === 0) return resolve(false);
|
|
97
96
|
|
|
98
97
|
const output = fs.createWriteStream(targetApksPath);
|
|
99
|
-
const archive = archiver(
|
|
98
|
+
const archive = new archiver.ZipArchive();
|
|
100
99
|
|
|
101
100
|
output.on('close', () => resolve(true));
|
|
102
101
|
archive.on('error', reject);
|