refactor(app): rename the desktop app and refine the interface

This commit is contained in:
lzt404 committed 2026-07-19 02:47:57 +08:00
1 parent 91032f3a06
commit ad02c2a8a6
15 files changed
+206 -87

No files matched your search

+15 -33
View File
@@ -1,8 +1,7 @@
import { createHash } from 'node:crypto';
import { existsSync } from 'node:fs';
import { chmod, copyFile, mkdir, readFile, rm, writeFile } from 'node:fs/promises';
import { chmod, copyFile, mkdir, readFile, readdir, rm, writeFile } from 'node:fs/promises';
import { basename, join, resolve } from 'node:path';
import { spawnSync } from 'node:child_process';
const args = new Map();
for (let index = 2; index < process.argv.length; index += 2) {
@@ -15,7 +14,6 @@ const binary = resolve(args.get('--binary') ?? join(root, 'src-tauri', 'target',
const targetOS = args.get('--os') ?? ({ linux: 'linux', darwin: 'darwin', win32: 'windows' })[process.platform];
const targetArch = args.get('--arch') ?? ({ x64: 'amd64', arm64: 'aarch64' })[process.arch];
const shouldDownload = args.get('--download') === 'true';
const cleanCore = args.get('--clean-core') === 'true';
if (!targetOS || !targetArch) throw new Error(`Unsupported target: ${process.platform}/${process.arch}`);
if (!existsSync(binary)) throw new Error(`GUI binary not found: ${binary}`);
@@ -32,13 +30,7 @@ const checksumsPath = join(sourceDir, 'checksums.txt');
await mkdir(sourceDir, { recursive: true });
if (!existsSync(sourceArchive)) {
if (!shouldDownload) {
console.warn(`Built-in core archive not found; portable output keeps the existing core: ${sourceArchive}`);
await mkdir(output, { recursive: true });
const outputBinary = join(output, targetOS === 'windows' ? 'cpa-gui.exe' : 'cpa-gui');
await copyFile(binary, outputBinary);
if (targetOS !== 'windows') await chmod(outputBinary, 0o755);
await copyFile(join(root, 'core-version.txt'), join(output, 'core-version.txt'));
process.exit(0);
throw new Error(`Built-in core archive not found: ${sourceArchive}`);
}
const tag = `v${version}`;
const releaseBase = `https://github.com/router-for-me/CLIProxyAPI/releases/download/${tag}`;
@@ -61,35 +53,25 @@ if (existsSync(checksumsPath)) {
}
await mkdir(output, { recursive: true });
const outputBinary = join(output, targetOS === 'windows' ? 'cpa-gui.exe' : 'cpa-gui');
const outputBinary = join(output, targetOS === 'windows' ? 'Easy_CLIProxyAPI.exe' : 'Easy_CLIProxyAPI');
const legacyOutputBinary = join(output, targetOS === 'windows' ? 'cpa-gui.exe' : 'cpa-gui');
await rm(legacyOutputBinary, { force: true });
await copyFile(binary, outputBinary);
if (targetOS !== 'windows') await chmod(outputBinary, 0o755);
await copyFile(join(root, 'core-version.txt'), join(output, 'core-version.txt'));
const coreOutput = join(output, 'cpa-core');
if (cleanCore) await rm(coreOutput, { recursive: true, force: true });
await rm(coreOutput, { recursive: true, force: true });
await mkdir(coreOutput, { recursive: true });
let extraction;
if (extension === 'zip') {
if (process.platform === 'win32') {
const quotePowerShell = (value) => value.replaceAll("'", "''");
const command = `Expand-Archive -LiteralPath '${quotePowerShell(sourceArchive)}' -DestinationPath '${quotePowerShell(coreOutput)}' -Force`;
extraction = spawnSync('powershell.exe', ['-NoLogo', '-NoProfile', '-NonInteractive', '-Command', command], { stdio: 'inherit' });
} else {
extraction = spawnSync('unzip', ['-q', sourceArchive, '-d', coreOutput], { stdio: 'inherit' });
}
} else {
extraction = spawnSync('tar', ['-xf', sourceArchive, '-C', coreOutput], { stdio: 'inherit' });
}
if (extraction.error) throw new Error(`Failed to start archive extractor for ${assetName}: ${extraction.error.message}`);
if (extraction.status !== 0) throw new Error(`Failed to extract ${assetName} (exit code ${extraction.status})`);
await copyFile(sourceArchive, join(coreOutput, assetName));
if (existsSync(checksumsPath)) await copyFile(checksumsPath, join(coreOutput, 'checksums.txt'));
await writeFile(join(coreOutput, 'cpa-gui-meta.json'), `${JSON.stringify({
version: `v${version}`,
assetName,
installedAtUnix: Math.floor(Date.now() / 1000),
}, null, 2)}\n`);
const coreEntries = await readdir(coreOutput, { withFileTypes: true });
if (
coreEntries.length !== 1
|| !coreEntries[0].isFile()
|| coreEntries[0].name !== assetName
) {
throw new Error(`Core output must contain only ${assetName}`);
}
console.log(`Prepared portable directory: ${output}`);
console.log(`Bundled core: ${basename(sourceArchive)}`);
console.log(`Bundled core: ${basename(sourceArchive)} (archive only)`);