@xx-in/tools 0.0.1 → 0.0.3

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.
Files changed (3) hide show
  1. package/README.md +35 -5
  2. package/dist/cli.js +452 -848
  3. package/package.json +4 -2
package/dist/cli.js CHANGED
@@ -7,7 +7,7 @@ import process4 from "process";
7
7
  // package.json
8
8
  var package_default = {
9
9
  name: "@xx-in/tools",
10
- version: "0.0.1",
10
+ version: "0.0.3",
11
11
  description: "A command-line tool to run in any system",
12
12
  license: "MIT",
13
13
  type: "module",
@@ -20,7 +20,9 @@ var package_default = {
20
20
  scripts: {
21
21
  build: "tsup",
22
22
  dev: "tsup --watch",
23
- prepublishOnly: "npm run build"
23
+ prepublishOnly: "npm run build",
24
+ "publish:npm": "npm publish --access public",
25
+ "publish:npm:registry": "npm --registry=https://registry.npmjs.org/ publish --access public"
24
26
  },
25
27
  engines: {
26
28
  node: ">=18"
@@ -70,7 +72,7 @@ _xx() {
70
72
  'create:\u9012\u5F52\u521B\u5EFA\u6587\u4EF6\u6216\u76EE\u5F55'
71
73
  'format:\u4F7F\u7528 Prettier \u683C\u5F0F\u5316\u4EE3\u7801'
72
74
  'help:\u663E\u793A\u6307\u5B9A\u547D\u4EE4\u7684\u5E2E\u52A9\u4FE1\u606F'
73
- 'install:\u81EA\u52A8\u5206\u53D1\u90E8\u7F72\u5B89\u88C5\u5305 (\u652F\u6301 AppImage\u3001Flatpak ID\u3001tar.gz\u3001deb\u3001rpm)'
75
+ 'install:macOS \u672C\u5730\u5DE5\u5177\u5B89\u88C5\u5668 (\u652F\u6301\u53EF\u6267\u884C\u6587\u4EF6\u4E0E tar \u5305)'
74
76
  'ip:\u672C\u5730\u6D3B\u8DC3\u7F51\u5361\u53CA\u7F51\u5173\u4FA6\u6D4B'
75
77
  'list:\u5217\u51FA\u76EE\u5F55\u4E2D\u7684\u6240\u6709\u6587\u4EF6\u548C\u76EE\u5F55\uFF08\u542B\u9690\u85CF\u9879\uFF09'
76
78
  'move:\u79FB\u52A8\u6216\u91CD\u547D\u540D\u6587\u4EF6\u53CA\u76EE\u5F55'
@@ -80,7 +82,7 @@ _xx() {
80
82
  'remove:\u5B89\u5168\u5730\u5C06\u6307\u5B9A\u7684\u6587\u4EF6\u6216\u76EE\u5F55\u79FB\u81F3\u7CFB\u7EDF\u56DE\u6536\u7AD9\uFF08\u652F\u6301\u901A\u914D\u7B26\u53CA\u591A\u9009\uFF09'
81
83
  'search:\u9012\u5F52\u641C\u7D22\u76EE\u5F55\u4E0B\u5305\u542B\u6307\u5B9A\u5173\u952E\u8BCD\u7684\u6587\u4EF6\u6216\u76EE\u5F55'
82
84
  'translate:\u7EC8\u7AEF\u7FFB\u8BD1\u5DE5\u5177'
83
- 'uninstall:\u901A\u7528\u5E94\u7528\u5378\u8F7D\u5668\uFF08\u652F\u6301\u5305\u540D\u3001Flatpak\u3001Snap\u3001\u672C\u5730\u5305\u6216\u7EFF\u8272\u8F6F\u4EF6\uFF09'
85
+ 'uninstall:macOS \u672C\u5730\u5DE5\u5177\u5378\u8F7D\u5668\uFF08\u79FB\u9664\u5B89\u88C5\u76EE\u5F55\u548C\u7EC8\u7AEF\u547D\u4EE4\u5165\u53E3\uFF09'
84
86
  'unzip:\u89E3\u538B ZIP \u538B\u7F29\u5305'
85
87
  'upgrade:\u81EA\u52A8\u66F4\u65B0 xx \u547D\u4EE4\u884C\u5DE5\u5177\u81F3\u6700\u65B0\u7248\u672C'
86
88
  'zip:\u81EA\u52A8\u8FC7\u6EE4\u5E76\u6253\u5305\u4E3A ZIP'
@@ -109,7 +111,7 @@ _xx() {
109
111
  'copy:\u590D\u5236\u6587\u4EF6\u6216\u76EE\u5F55\uFF08\u652F\u6301\u9012\u5F52\u590D\u5236\uFF09'
110
112
  'create:\u9012\u5F52\u521B\u5EFA\u6587\u4EF6\u6216\u76EE\u5F55'
111
113
  'format:\u4F7F\u7528 Prettier \u683C\u5F0F\u5316\u4EE3\u7801'
112
- 'install:\u81EA\u52A8\u5206\u53D1\u90E8\u7F72\u5B89\u88C5\u5305 (\u652F\u6301 AppImage\u3001Flatpak ID\u3001tar.gz\u3001deb\u3001rpm)'
114
+ 'install:macOS \u672C\u5730\u5DE5\u5177\u5B89\u88C5\u5668 (\u652F\u6301\u53EF\u6267\u884C\u6587\u4EF6\u4E0E tar \u5305)'
113
115
  'ip:\u672C\u5730\u6D3B\u8DC3\u7F51\u5361\u53CA\u7F51\u5173\u4FA6\u6D4B'
114
116
  'list:\u5217\u51FA\u76EE\u5F55\u4E2D\u7684\u6240\u6709\u6587\u4EF6\u548C\u76EE\u5F55\uFF08\u542B\u9690\u85CF\u9879\uFF09'
115
117
  'move:\u79FB\u52A8\u6216\u91CD\u547D\u540D\u6587\u4EF6\u53CA\u76EE\u5F55'
@@ -119,7 +121,7 @@ _xx() {
119
121
  'remove:\u5B89\u5168\u5730\u5C06\u6307\u5B9A\u7684\u6587\u4EF6\u6216\u76EE\u5F55\u79FB\u81F3\u7CFB\u7EDF\u56DE\u6536\u7AD9\uFF08\u652F\u6301\u901A\u914D\u7B26\u53CA\u591A\u9009\uFF09'
120
122
  'search:\u9012\u5F52\u641C\u7D22\u76EE\u5F55\u4E0B\u5305\u542B\u6307\u5B9A\u5173\u952E\u8BCD\u7684\u6587\u4EF6\u6216\u76EE\u5F55'
121
123
  'translate:\u7EC8\u7AEF\u7FFB\u8BD1\u5DE5\u5177'
122
- 'uninstall:\u901A\u7528\u5E94\u7528\u5378\u8F7D\u5668\uFF08\u652F\u6301\u5305\u540D\u3001Flatpak\u3001Snap\u3001\u672C\u5730\u5305\u6216\u7EFF\u8272\u8F6F\u4EF6\uFF09'
124
+ 'uninstall:macOS \u672C\u5730\u5DE5\u5177\u5378\u8F7D\u5668\uFF08\u79FB\u9664\u5B89\u88C5\u76EE\u5F55\u548C\u7EC8\u7AEF\u547D\u4EE4\u5165\u53E3\uFF09'
123
125
  'unzip:\u89E3\u538B ZIP \u538B\u7F29\u5305'
124
126
  'upgrade:\u81EA\u52A8\u66F4\u65B0 xx \u547D\u4EE4\u884C\u5DE5\u5177\u81F3\u6700\u65B0\u7248\u672C'
125
127
  'zip:\u81EA\u52A8\u8FC7\u6EE4\u5E76\u6253\u5305\u4E3A ZIP'
@@ -165,6 +167,10 @@ _xx() {
165
167
  '-d[\u6307\u5B9A\u89E3\u538B\u5230\u7684\u76EE\u6807\u76EE\u5F55\u8DEF\u5F84]:directory:_files -/' \\
166
168
  '*:Zip File:_files -g "*.zip"'
167
169
  ;;
170
+ upgrade)
171
+ _arguments \\
172
+ '-r[\u5F3A\u5236\u4F7F\u7528 npm \u5B98\u65B9\u6E90 https://registry.npmjs.org/]'
173
+ ;;
168
174
  zip)
169
175
  _arguments \\
170
176
  '*:Target Path:_files'
@@ -247,6 +253,11 @@ _xx_completion() {
247
253
  COMPREPLY=( $(compgen -W "\${sub_opts}" -- \${cur}) )
248
254
  return 0
249
255
  ;;
256
+ upgrade)
257
+ local sub_opts="-r --registry"
258
+ COMPREPLY=( $(compgen -W "\${sub_opts}" -- \${cur}) )
259
+ return 0
260
+ ;;
250
261
  help)
251
262
  local sub_opts="completion copy create format ip list move open park proxy remove search translate uninstall unzip upgrade zip"
252
263
  COMPREPLY=( $(compgen -W "\${sub_opts}" -- \${cur}) )
@@ -301,6 +312,7 @@ $xx_completer = {
301
312
  "park" = @("-d", "-o", "-g")
302
313
  "proxy" = @("on", "off")
303
314
  "unzip" = @("-d")
315
+ "upgrade" = @("-r", "--registry")
304
316
  "translate" = @("-t")
305
317
  "help" = @("completion", "copy", "create", "format", "ip", "list", "move", "open", "park", "proxy", "remove", "search", "translate", "uninstall", "unzip", "upgrade", "zip")
306
318
  }
@@ -535,12 +547,12 @@ function isCommandAvailable(cmd) {
535
547
  }
536
548
  function runCommand(cmd, args, options = {}) {
537
549
  const stdio = options.stdio ?? "pipe";
538
- return new Promise((resolve14, reject) => {
550
+ return new Promise((resolve13, reject) => {
539
551
  const child = spawn(cmd, args, { stdio });
540
552
  if (stdio === "inherit" || stdio === "ignore") {
541
553
  child.on("error", reject);
542
554
  child.on("close", (code) => {
543
- resolve14({
555
+ resolve13({
544
556
  success: code === 0,
545
557
  code,
546
558
  stdout: Buffer.alloc(0),
@@ -555,7 +567,7 @@ function runCommand(cmd, args, options = {}) {
555
567
  child.stderr?.on("data", (chunk) => stderrChunks.push(chunk));
556
568
  child.on("error", reject);
557
569
  child.on("close", (code) => {
558
- resolve14({
570
+ resolve13({
559
571
  success: code === 0,
560
572
  code,
561
573
  stdout: Buffer.concat(stdoutChunks),
@@ -752,268 +764,289 @@ function registerFormatCommand(program2) {
752
764
  }
753
765
 
754
766
  // commands/install.ts
767
+ import fs6 from "fs/promises";
768
+ import pc6 from "picocolors";
769
+ import { resolve as resolve4, join as join5, basename as basename3 } from "path";
770
+
771
+ // utils/macos-apps.ts
755
772
  import fs5 from "fs/promises";
773
+ import { basename as basename2, extname, join as join4 } from "path";
756
774
  import pc5 from "picocolors";
757
- import { resolve as resolve4, join as join4, basename as basename2 } from "path";
775
+ var APP_DIR_NAME = ".xx-tools";
776
+ var PATH_MARKER_BEGIN = "# >>> xx-tools path >>>";
777
+ var PATH_MARKER_END = "# <<< xx-tools path <<<";
758
778
  function getHomeDir() {
759
- return process.env["HOME"] || process.env["USERPROFILE"] || process.cwd();
779
+ return process.env["HOME"] || process.cwd();
780
+ }
781
+ function getToolsRootDir() {
782
+ return join4(getHomeDir(), APP_DIR_NAME);
783
+ }
784
+ function getAppsDir() {
785
+ return join4(getToolsRootDir(), "apps");
786
+ }
787
+ function getBinDir() {
788
+ return join4(getToolsRootDir(), "bin");
760
789
  }
761
- async function createShortcut(targetPath) {
790
+ function getManifestPath(appName) {
791
+ return join4(getAppsDir(), appName, ".xx-manifest.json");
792
+ }
793
+ function ensureMacOS() {
794
+ if (process.platform !== "darwin") {
795
+ console.error(pc5.red("\u274C \u5F53\u524D install/uninstall \u4EC5\u652F\u6301 macOS\u3002"));
796
+ return false;
797
+ }
798
+ return true;
799
+ }
800
+ async function ensureToolDirectories() {
801
+ await fs5.mkdir(getAppsDir(), { recursive: true });
802
+ await fs5.mkdir(getBinDir(), { recursive: true });
803
+ }
804
+ function getPreferredProfiles() {
762
805
  const home = getHomeDir();
763
- const applicationsDir = join4(home, ".local/share/applications");
764
- let name = "";
765
- let execLine = "";
766
- let desktopFileName = "";
767
- const isFlatpak = !targetPath.includes("/") && !targetPath.includes("\\") && targetPath.split(".").length >= 3;
768
- if (isFlatpak) {
769
- const segments = targetPath.split(".");
770
- name = segments[segments.length - 1];
771
- execLine = `flatpak run ${targetPath}`;
772
- desktopFileName = `flatpak-${targetPath}.desktop`;
806
+ const shell = process.env["SHELL"] || "";
807
+ const profiles = [];
808
+ if (shell.includes("zsh")) {
809
+ profiles.push(join4(home, ".zshrc"), join4(home, ".zprofile"));
810
+ } else if (shell.includes("bash")) {
811
+ profiles.push(join4(home, ".bashrc"), join4(home, ".bash_profile"));
773
812
  } else {
774
- const absolutePath = resolve4(process.cwd(), targetPath);
813
+ profiles.push(join4(home, ".zshrc"), join4(home, ".zprofile"));
814
+ }
815
+ return Array.from(new Set(profiles));
816
+ }
817
+ async function ensureBinDirOnPath() {
818
+ const pathBlock = `${PATH_MARKER_BEGIN}
819
+ export PATH="$HOME/${APP_DIR_NAME}/bin:$PATH"
820
+ ${PATH_MARKER_END}`;
821
+ for (const profilePath of getPreferredProfiles()) {
822
+ let content = "";
775
823
  try {
776
- const stat = await fs5.stat(absolutePath);
777
- if (!stat.isFile()) {
778
- console.error(pc5.red(`\u274C \u9519\u8BEF: '${targetPath}' \u4E0D\u662F\u4E00\u4E2A\u6709\u6548\u7684\u6587\u4EF6\u3002`));
779
- return;
780
- }
824
+ content = await fs5.readFile(profilePath, "utf-8");
781
825
  } catch {
782
- console.error(pc5.red(`\u274C \u9519\u8BEF: \u627E\u4E0D\u5230\u6587\u4EF6 '${targetPath}'\u3002`));
783
- return;
784
826
  }
785
- const isAppImage = targetPath.toLowerCase().endsWith(".appimage");
786
- name = basename2(absolutePath, isAppImage ? ".AppImage" : "");
787
- try {
788
- await fs5.chmod(absolutePath, 493);
789
- } catch {
827
+ if (!content.includes(PATH_MARKER_BEGIN)) {
828
+ const separator = content.endsWith("\n") || content === "" ? "" : "\n";
829
+ await fs5.writeFile(
830
+ profilePath,
831
+ `${content}${separator}${pathBlock}
832
+ `,
833
+ "utf-8"
834
+ );
835
+ console.log(pc5.green(`\u2714 \u5DF2\u5199\u5165 PATH \u914D\u7F6E: ${profilePath}`));
790
836
  }
791
- execLine = isAppImage ? `"${absolutePath}" --no-sandbox` : `"${absolutePath}"`;
792
- desktopFileName = `${name.replace(/\s+/g, "-").toLowerCase()}.desktop`;
793
- }
794
- const desktopFilePath = join4(applicationsDir, desktopFileName);
795
- const desktopContent = `[Desktop Entry]
796
- Name=${name}
797
- Exec=${execLine}
798
- Type=Application
799
- Terminal=false
800
- Categories=Utility;
801
- `;
802
- try {
803
- await fs5.mkdir(applicationsDir, { recursive: true });
804
- await fs5.writeFile(desktopFilePath, desktopContent, "utf-8");
805
- console.log(pc5.green(`\u2714 \u5FEB\u6377\u65B9\u5F0F\u5DF2\u521B\u5EFA: ${desktopFilePath}`));
806
- console.log(pc5.dim(`\u542F\u52A8\u547D\u4EE4: ${execLine}`));
807
- } catch (err) {
808
- console.error(
809
- pc5.red("\u274C \u521B\u5EFA\u5FEB\u6377\u65B9\u5F0F\u5931\u8D25:"),
810
- err instanceof Error ? err.message : err
811
- );
812
837
  }
813
838
  }
814
- async function installAppImage(absPath) {
815
- const home = getHomeDir();
816
- const greenAppDir = join4(home, "GreenApp");
817
- const fileName = basename2(absPath);
818
- const destPath = join4(greenAppDir, fileName);
819
- const isAppImage = fileName.toLowerCase().endsWith(".appimage");
820
- const appNameClean = basename2(absPath, isAppImage ? ".AppImage" : "");
821
- try {
822
- await fs5.mkdir(greenAppDir, { recursive: true });
823
- console.log(
824
- pc5.cyan(`\u{1F4E6} \u6B63\u5728\u5C06 AppImage \u90E8\u7F72\u81F3\u7EFF\u8272\u8F6F\u4EF6\u76EE\u5F55: ${destPath}...`)
825
- );
826
- await fs5.copyFile(absPath, destPath);
827
- await fs5.chmod(destPath, 493);
828
- await createShortcut(destPath);
829
- console.log(pc5.green(`\u2728 AppImage \u90E8\u7F72\u5B8C\u6210\uFF01`));
830
- console.log(
831
- pc5.green(
832
- `
833
- \u2728 \u5B89\u88C5\u6210\u529F\uFF01\u8BE5\u7EFF\u8272\u8F6F\u4EF6\u7684\u5378\u8F7D\u540D\u79F0\u4E3A: ${pc5.bold(appNameClean)}`
834
- )
835
- );
836
- console.log(pc5.cyan(`\u{1F449} \u4EE5\u540E\u60A8\u53EF\u4EE5\u901A\u8FC7\u8FD0\u884C\u4EE5\u4E0B\u547D\u4EE4\u6765\u5F7B\u5E95\u5378\u8F7D\u5B83\uFF1A`));
837
- console.log(pc5.bold(pc5.yellow(` xx delete ${appNameClean}`)));
838
- } catch (err) {
839
- console.error(
840
- pc5.red("\u274C AppImage \u90E8\u7F72\u5931\u8D25:"),
841
- err instanceof Error ? err.message : err
842
- );
839
+ function getShellReloadCommand() {
840
+ const shell = process.env["SHELL"] || "";
841
+ if (shell.includes("zsh")) {
842
+ return "source ~/.zshrc";
843
843
  }
844
+ if (shell.includes("bash")) {
845
+ return "source ~/.bashrc";
846
+ }
847
+ return "source ~/.zshrc";
844
848
  }
845
- async function installDeb(absPath) {
846
- console.log(pc5.cyan(`\u{1F4E6} \u6B63\u5728\u901A\u8FC7 dpkg \u672C\u5730\u5B89\u88C5 DEB \u8F6F\u4EF6\u5305: ${absPath}...`));
847
- const status = await spawnCommand("sudo", ["dpkg", "-i", absPath]);
848
- if (status.success) {
849
- console.log(pc5.green("\u2714 DEB \u8F6F\u4EF6\u5305\u90E8\u7F72\u6210\u529F\uFF01"));
850
- try {
851
- const { success, stdout } = await runCommand("dpkg-deb", [
852
- "-f",
853
- absPath,
854
- "Package"
855
- ]);
856
- if (success) {
857
- const packageName = decodeOutput(stdout).trim();
858
- console.log(
859
- pc5.green(
860
- `
861
- \u2728 \u5B89\u88C5\u6210\u529F\uFF01\u8BE5\u8F6F\u4EF6\u5305\u7684\u5B98\u65B9\u5378\u8F7D\u540D\u79F0\u4E3A: ${pc5.bold(packageName)}`
862
- )
863
- );
864
- console.log(pc5.cyan(`\u{1F449} \u4EE5\u540E\u60A8\u53EF\u4EE5\u901A\u8FC7\u8FD0\u884C\u4EE5\u4E0B\u547D\u4EE4\u6765\u5F7B\u5E95\u5378\u8F7D\u5B83\uFF1A`));
865
- console.log(pc5.bold(pc5.yellow(` xx delete ${packageName}`)));
866
- }
867
- } catch {
849
+ function stripArchiveSuffix(filePath) {
850
+ const lower = filePath.toLowerCase();
851
+ const name = basename2(filePath);
852
+ const suffixes = [".tar.gz", ".tgz", ".tar.xz", ".txz", ".zip", ".tar"];
853
+ for (const suffix of suffixes) {
854
+ if (lower.endsWith(suffix)) {
855
+ return name.slice(0, name.length - suffix.length);
868
856
  }
869
- } else {
870
- console.error(pc5.red(`\u274C \u5B89\u88C5\u5931\u8D25\uFF0C\u8FDB\u7A0B\u9000\u51FA\u7801: ${status.code}`));
871
857
  }
858
+ return basename2(filePath, extname(filePath));
872
859
  }
873
- async function installRpm(absPath) {
874
- console.log(pc5.cyan(`\u{1F4E6} \u6B63\u5728\u901A\u8FC7 dnf \u672C\u5730\u5B89\u88C5 RPM \u8F6F\u4EF6\u5305: ${absPath}...`));
875
- const status = await spawnCommand("sudo", ["dnf", "install", "-y", absPath]);
876
- if (status.success) {
877
- console.log(pc5.green("\u2714 RPM \u8F6F\u4EF6\u5305\u90E8\u7F72\u6210\u529F\uFF01"));
878
- try {
879
- const { success, stdout } = await runCommand("rpm", [
880
- "-qp",
881
- "--queryformat",
882
- "%{NAME}",
883
- absPath
884
- ]);
885
- if (success) {
886
- const packageName = decodeOutput(stdout).trim();
887
- console.log(
888
- pc5.green(
889
- `
890
- \u2728 \u5B89\u88C5\u6210\u529F\uFF01\u8BE5\u8F6F\u4EF6\u5305\u7684\u5B98\u65B9\u5378\u8F7D\u540D\u79F0\u4E3A: ${pc5.bold(packageName)}`
891
- )
892
- );
893
- console.log(pc5.cyan(`\u{1F449} \u4EE5\u540E\u60A8\u53EF\u4EE5\u901A\u8FC7\u8FD0\u884C\u4EE5\u4E0B\u547D\u4EE4\u6765\u5F7B\u5E95\u5378\u8F7D\u5B83\uFF1A`));
894
- console.log(pc5.bold(pc5.yellow(` xx delete ${packageName}`)));
860
+ async function removeDirectoryContents(dirPath) {
861
+ await fs5.rm(dirPath, { recursive: true, force: true });
862
+ await fs5.mkdir(dirPath, { recursive: true });
863
+ }
864
+ async function findExecutablesRecursively(rootDir) {
865
+ const matches = [];
866
+ async function walk(currentDir) {
867
+ for (const entry of await fs5.readdir(currentDir, { withFileTypes: true })) {
868
+ if (entry.name.startsWith(".")) continue;
869
+ const fullPath = join4(currentDir, entry.name);
870
+ if (entry.isDirectory()) {
871
+ if (["node_modules", "lib", "libs", "include", "share", "man"].includes(
872
+ entry.name
873
+ )) {
874
+ continue;
875
+ }
876
+ await walk(fullPath);
877
+ continue;
895
878
  }
896
- } catch {
879
+ if (!entry.isFile()) continue;
880
+ const stat = await fs5.stat(fullPath);
881
+ const isExecutable = stat.mode ? (stat.mode & 73) !== 0 : false;
882
+ if (!isExecutable) continue;
883
+ if (/\.(dylib|so|a|o|txt|md|json|yaml|yml|ts|js|c|h|sh)$/i.test(entry.name)) {
884
+ continue;
885
+ }
886
+ matches.push(fullPath);
897
887
  }
898
- } else {
899
- console.error(pc5.red(`\u274C \u5B89\u88C5\u5931\u8D25\uFF0C\u8FDB\u7A0B\u9000\u51FA\u7801: ${status.code}`));
900
888
  }
889
+ await walk(rootDir);
890
+ return matches;
901
891
  }
902
- async function installTarGz(absPath) {
903
- const home = getHomeDir();
904
- if (!home) {
905
- console.error(pc5.red("\u274C \u9519\u8BEF: \u65E0\u6CD5\u83B7\u53D6\u7528\u6237\u6839\u76EE\u5F55\u3002"));
906
- return;
892
+ async function createLinks(appName, executablePaths) {
893
+ const binDir = getBinDir();
894
+ const linkNames = [];
895
+ for (const executablePath of executablePaths) {
896
+ const linkName = basename2(executablePath);
897
+ const linkPath = join4(binDir, linkName);
898
+ await fs5.rm(linkPath, { force: true });
899
+ await fs5.symlink(executablePath, linkPath);
900
+ linkNames.push(linkName);
907
901
  }
908
- const greenAppDir = join4(home, "GreenApp");
909
- const folderName = basename2(absPath, ".tar.gz").replace(".tar", "");
910
- const destDir = join4(greenAppDir, folderName);
911
- try {
912
- await fs5.mkdir(destDir, { recursive: true });
913
- console.log(pc5.cyan(`\u{1F4E6} \u6B63\u5728\u89E3\u538B\u7EFF\u8272\u8F6F\u4EF6\u81F3: ${destDir}...`));
914
- const tarStatus = await spawnCommand("tar", [
915
- "-xzf",
916
- absPath,
917
- "-C",
918
- destDir
919
- ]);
920
- if (!tarStatus.success) {
921
- console.error(pc5.red("\u274C \u89E3\u538B\u5931\u8D25\u3002"));
922
- return;
923
- }
902
+ if (linkNames.length > 0) {
924
903
  console.log(
925
- pc5.green("\u2714 \u89E3\u538B\u5B8C\u6210\u3002\u6B63\u5728\u626B\u63CF\u4E3B\u6267\u884C\u6587\u4EF6\u4EE5\u81EA\u52A8\u914D\u7F6E\u5FEB\u6377\u65B9\u5F0F...")
904
+ pc5.green(
905
+ `\u2714 \u5DF2\u4E3A ${pc5.bold(appName)} \u521B\u5EFA\u7EC8\u7AEF\u547D\u4EE4: ${linkNames.join(", ")}`
906
+ )
926
907
  );
927
- let exePath = "";
928
- for (const entry of await fs5.readdir(destDir, { withFileTypes: true })) {
929
- if (entry.isFile()) {
930
- const fullPath = join4(destDir, entry.name);
931
- const stat = await fs5.stat(fullPath);
932
- const isExecutable = stat.mode ? (stat.mode & 73) !== 0 : false;
933
- if (isExecutable && !entry.name.endsWith(".sh") && !entry.name.endsWith(".so")) {
934
- exePath = fullPath;
935
- break;
936
- }
937
- }
938
- }
939
- if (exePath) {
940
- console.log(pc5.cyan(`\u{1F50D} \u53D1\u73B0\u53EF\u6267\u884C\u4E8C\u8FDB\u5236\u6587\u4EF6: ${exePath}`));
941
- await createShortcut(exePath);
942
- console.log(
943
- pc5.green(
944
- `
945
- \u2728 \u5B89\u88C5\u6210\u529F\uFF01\u8BE5\u7EFF\u8272\u5E94\u7528\u7684\u5378\u8F7D\u540D\u79F0\u4E3A: ${pc5.bold(folderName)}`
946
- )
947
- );
948
- console.log(pc5.cyan(`\u{1F449} \u4EE5\u540E\u60A8\u53EF\u4EE5\u901A\u8FC7\u8FD0\u884C\u4EE5\u4E0B\u547D\u4EE4\u6765\u5F7B\u5E95\u5378\u8F7D\u5B83\uFF1A`));
949
- console.log(pc5.bold(pc5.yellow(` xx delete ${folderName}`)));
950
- } else {
951
- console.log(
952
- pc5.yellow(
953
- "\u26A0\uFE0F \u672A\u80FD\u5728\u89E3\u538B\u76EE\u5F55\u4E0B\u5B9A\u4F4D\u5230\u660E\u786E\u7684\u53EF\u6267\u884C\u4E8C\u8FDB\u5236\u6587\u4EF6\uFF0C\u8BF7\u540E\u7EED\u624B\u52A8\u521B\u5EFA\u3002"
954
- )
955
- );
956
- }
957
- } catch (err) {
908
+ }
909
+ return linkNames;
910
+ }
911
+ async function writeManifest(manifest) {
912
+ await fs5.writeFile(
913
+ getManifestPath(manifest.appName),
914
+ JSON.stringify(manifest, null, 2),
915
+ "utf-8"
916
+ );
917
+ }
918
+ async function readManifest(appName) {
919
+ try {
920
+ const content = await fs5.readFile(getManifestPath(appName), "utf-8");
921
+ return JSON.parse(content);
922
+ } catch {
923
+ return null;
924
+ }
925
+ }
926
+ async function removeInstalledApp(appName) {
927
+ const manifest = await readManifest(appName);
928
+ if (!manifest) return false;
929
+ for (const linkName of manifest.links) {
930
+ await fs5.rm(join4(getBinDir(), linkName), { force: true });
931
+ console.log(pc5.green(`\u2714 \u5DF2\u79FB\u9664\u7EC8\u7AEF\u547D\u4EE4: ${linkName}`));
932
+ }
933
+ await fs5.rm(manifest.installDir, { recursive: true, force: true });
934
+ console.log(pc5.green(`\u2714 \u5DF2\u79FB\u9664\u5B89\u88C5\u76EE\u5F55: ${manifest.installDir}`));
935
+ return true;
936
+ }
937
+ async function listInstalledApps() {
938
+ try {
939
+ const entries = await fs5.readdir(getAppsDir(), { withFileTypes: true });
940
+ return entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name);
941
+ } catch {
942
+ return [];
943
+ }
944
+ }
945
+ async function extractArchiveToDir(archivePath, destDir) {
946
+ const lower = archivePath.toLowerCase();
947
+ let args;
948
+ if (lower.endsWith(".tar.gz") || lower.endsWith(".tgz")) {
949
+ args = ["-xzf", archivePath, "-C", destDir];
950
+ } else if (lower.endsWith(".tar.xz") || lower.endsWith(".txz")) {
951
+ args = ["-xJf", archivePath, "-C", destDir];
952
+ } else if (lower.endsWith(".tar")) {
953
+ args = ["-xf", archivePath, "-C", destDir];
954
+ } else {
955
+ return false;
956
+ }
957
+ const result = await spawnCommand("tar", args);
958
+ return result.success;
959
+ }
960
+
961
+ // commands/install.ts
962
+ function printReloadHint() {
963
+ const reloadCommand = getShellReloadCommand();
964
+ console.log(
965
+ pc6.yellow(`\u{1F4A1} \u5982\u679C\u5F53\u524D\u7EC8\u7AEF\u8FD8\u4E0D\u80FD\u76F4\u63A5\u8FD0\u884C\u65B0\u547D\u4EE4\uFF0C\u8BF7\u6267\u884C: ${reloadCommand}`)
966
+ );
967
+ }
968
+ async function installBinary(absPath) {
969
+ const appName = basename3(absPath);
970
+ const installDir = join5(getAppsDir(), appName);
971
+ const targetDir = join5(installDir, "bin");
972
+ const targetPath = join5(targetDir, appName);
973
+ await fs6.mkdir(targetDir, { recursive: true });
974
+ await fs6.copyFile(absPath, targetPath);
975
+ await fs6.chmod(targetPath, 493);
976
+ const links = await createLinks(appName, [targetPath]);
977
+ await writeManifest({
978
+ appName,
979
+ installDir,
980
+ links,
981
+ type: "binary"
982
+ });
983
+ console.log(pc6.green(`\u2728 \u5B89\u88C5\u6210\u529F\uFF01\u53EF\u76F4\u63A5\u5728\u7EC8\u7AEF\u4E2D\u8FD0\u884C: ${pc6.bold(appName)}`));
984
+ console.log(pc6.cyan(`\u{1F449} \u5378\u8F7D\u547D\u4EE4: ${pc6.bold(`xx uninstall ${appName}`)}`));
985
+ printReloadHint();
986
+ }
987
+ async function installArchive(absPath) {
988
+ const appName = stripArchiveSuffix(absPath);
989
+ const installDir = join5(getAppsDir(), appName);
990
+ await removeDirectoryContents(installDir);
991
+ console.log(pc6.cyan(`\u{1F4E6} \u6B63\u5728\u89E3\u538B\u8F6F\u4EF6\u5305\u81F3: ${installDir}...`));
992
+ const extracted = await extractArchiveToDir(absPath, installDir);
993
+ if (!extracted) {
958
994
  console.error(
959
- pc5.red("\u274C \u7EFF\u8272\u8F6F\u4EF6\u5B89\u88C5\u5931\u8D25:"),
960
- err instanceof Error ? err.message : err
995
+ pc6.red("\u274C \u5F53\u524D\u4EC5\u652F\u6301 .tar.gz\u3001.tgz\u3001.tar.xz\u3001.txz\u3001.tar \u683C\u5F0F\u3002")
961
996
  );
997
+ return;
962
998
  }
999
+ const executables = await findExecutablesRecursively(installDir);
1000
+ if (executables.length === 0) {
1001
+ console.error(pc6.red("\u274C \u89E3\u538B\u5B8C\u6210\uFF0C\u4F46\u672A\u627E\u5230\u53EF\u6267\u884C\u6587\u4EF6\u3002"));
1002
+ return;
1003
+ }
1004
+ const links = await createLinks(appName, executables);
1005
+ await writeManifest({
1006
+ appName,
1007
+ installDir,
1008
+ links,
1009
+ type: "archive"
1010
+ });
1011
+ console.log(
1012
+ pc6.green(`\u2728 \u5B89\u88C5\u6210\u529F\uFF01\u53EF\u76F4\u63A5\u5728\u7EC8\u7AEF\u4E2D\u8FD0\u884C: ${pc6.bold(links.join(", "))}`)
1013
+ );
1014
+ console.log(pc6.cyan(`\u{1F449} \u5378\u8F7D\u547D\u4EE4: ${pc6.bold(`xx uninstall ${appName}`)}`));
1015
+ printReloadHint();
963
1016
  }
964
1017
  function registerInstallCommand(program2) {
965
1018
  program2.command("install [path]").description(
966
- "\u901A\u7528\u5E94\u7528\u90E8\u7F72\u5B89\u88C5\uFF08\u81EA\u52A8\u5206\u53D1\u9002\u914D AppImage\u3001Flatpak ID\u3001tar.gz\u3001deb \u53CA rpm \u683C\u5F0F\u5305\uFF09"
1019
+ "macOS \u672C\u5730\u5DE5\u5177\u5B89\u88C5\u5668\uFF08\u652F\u6301\u53EF\u6267\u884C\u6587\u4EF6\u3001.tar.gz\u3001.tgz\u3001.tar.xz\u3001.txz\u3001.tar\uFF09"
967
1020
  ).action(async (target) => {
1021
+ if (!ensureMacOS()) return;
968
1022
  if (!target) {
969
- console.error(pc5.red("\u274C \u8BF7\u63D0\u4F9B\u6709\u6548\u7684\u5B89\u88C5\u5305\u6587\u4EF6\u8DEF\u5F84\u6216 Flatpak ID\u3002"));
970
- return;
971
- }
972
- const isFlatpak = !target.includes("/") && !target.includes("\\") && target.split(".").length >= 3;
973
- if (isFlatpak) {
974
- await createShortcut(target);
975
- console.log(
976
- pc5.green(
977
- `
978
- \u2728 \u5B89\u88C5\u6210\u529F\uFF01\u8BE5 Flatpak \u5FEB\u6377\u56FE\u6807\u7684\u5378\u8F7D\u540D\u79F0\u4E3A: ${pc5.bold(target)}`
979
- )
980
- );
981
- console.log(pc5.cyan(`\u{1F449} \u4EE5\u540E\u60A8\u53EF\u4EE5\u901A\u8FC7\u8FD0\u884C\u4EE5\u4E0B\u547D\u4EE4\u6765\u5220\u9664\u8BE5\u5FEB\u6377\u56FE\u6807\uFF1A`));
982
- console.log(pc5.bold(pc5.yellow(` xx delete ${target}`)));
1023
+ console.error(pc6.red("\u274C \u8BF7\u63D0\u4F9B\u6709\u6548\u7684\u672C\u5730\u6587\u4EF6\u8DEF\u5F84\u3002"));
983
1024
  return;
984
1025
  }
985
1026
  const absPath = resolve4(process.cwd(), target);
986
1027
  try {
987
- await fs5.stat(absPath);
1028
+ const stat = await fs6.stat(absPath);
1029
+ if (!stat.isFile()) {
1030
+ console.error(pc6.red(`\u274C \u9519\u8BEF: '${target}' \u4E0D\u662F\u4E00\u4E2A\u6709\u6548\u7684\u6587\u4EF6\u3002`));
1031
+ return;
1032
+ }
988
1033
  } catch {
989
- console.error(pc5.red(`\u274C \u9519\u8BEF: \u627E\u4E0D\u5230\u6307\u5B9A\u6587\u4EF6\u6216\u5305\u8DEF\u5F84 '${target}'\u3002`));
1034
+ console.error(pc6.red(`\u274C \u9519\u8BEF: \u627E\u4E0D\u5230\u6307\u5B9A\u6587\u4EF6\u6216\u5305\u8DEF\u5F84 '${target}'\u3002`));
990
1035
  return;
991
1036
  }
1037
+ await ensureToolDirectories();
1038
+ await ensureBinDirOnPath();
992
1039
  const lowerPath = target.toLowerCase();
993
- if (lowerPath.endsWith(".appimage")) {
994
- await installAppImage(absPath);
995
- } else if (lowerPath.endsWith(".deb")) {
996
- await installDeb(absPath);
997
- } else if (lowerPath.endsWith(".rpm")) {
998
- await installRpm(absPath);
999
- } else if (lowerPath.endsWith(".tar.gz") || lowerPath.endsWith(".tgz")) {
1000
- await installTarGz(absPath);
1040
+ if (lowerPath.endsWith(".tar.gz") || lowerPath.endsWith(".tgz") || lowerPath.endsWith(".tar.xz") || lowerPath.endsWith(".txz") || lowerPath.endsWith(".tar")) {
1041
+ await installArchive(absPath);
1001
1042
  } else {
1002
- console.log(
1003
- pc5.cyan(`\u{1F4E6} \u68C0\u6D4B\u5230\u901A\u7528\u672C\u5730\u53EF\u6267\u884C\u6587\u4EF6\uFF0C\u6B63\u5728\u76F4\u63A5\u4E3A\u5176\u914D\u7F6E\u684C\u9762\u56FE\u6807...`)
1004
- );
1005
- await createShortcut(absPath);
1006
- const execName = basename2(absPath);
1007
- console.log(
1008
- pc5.green(`
1009
- \u2728 \u5FEB\u6377\u65B9\u5F0F\u521B\u5EFA\u6210\u529F\uFF01\u540D\u79F0\u4E3A: ${pc5.bold(execName)}`)
1010
- );
1043
+ await installBinary(absPath);
1011
1044
  }
1012
1045
  });
1013
1046
  }
1014
1047
 
1015
1048
  // commands/ip.ts
1016
- import pc6 from "picocolors";
1049
+ import pc7 from "picocolors";
1017
1050
  import os from "os";
1018
1051
  function getInterfaceType(name) {
1019
1052
  const lowerName = name.toLowerCase();
@@ -1187,7 +1220,7 @@ async function getDefaultRouteInfo() {
1187
1220
  }
1188
1221
  function registerIpCommand(program2) {
1189
1222
  program2.command("ip").description("\u672C\u5730\u6D3B\u8DC3\u7F51\u5361\u3001\u672C\u673AIP\u53CA\u7F51\u5173\u4FA6\u6D4B\u5DE5\u5177").action(async () => {
1190
- console.log(pc6.dim("\u6B63\u5728\u5206\u6790\u7F51\u7EDC\u914D\u7F6E\uFF0C\u8BF7\u7A0D\u5019...\n"));
1223
+ console.log(pc7.dim("\u6B63\u5728\u5206\u6790\u7F51\u7EDC\u914D\u7F6E\uFF0C\u8BF7\u7A0D\u5019...\n"));
1191
1224
  try {
1192
1225
  let defaultRoute = { gateway: "", interfaceName: "" };
1193
1226
  let routeError = "";
@@ -1198,7 +1231,7 @@ function registerIpCommand(program2) {
1198
1231
  }
1199
1232
  const cards = getActiveNetworkCards();
1200
1233
  if (cards.length === 0) {
1201
- console.log(pc6.red("\u274C \u672A\u68C0\u6D4B\u5230\u4EFB\u4F55\u6D3B\u8DC3\u7684\u975E\u672C\u5730\u56DE\u73AF\u7F51\u5361\u3002"));
1234
+ console.log(pc7.red("\u274C \u672A\u68C0\u6D4B\u5230\u4EFB\u4F55\u6D3B\u8DC3\u7684\u975E\u672C\u5730\u56DE\u73AF\u7F51\u5361\u3002"));
1202
1235
  return;
1203
1236
  }
1204
1237
  cards.sort((a, b) => {
@@ -1235,76 +1268,76 @@ function registerIpCommand(program2) {
1235
1268
  ipv4.netmask
1236
1269
  );
1237
1270
  }
1238
- let cardGateway = pc6.dim("(\u975E\u9ED8\u8BA4\u8DEF\u7531\u51FA\u53E3\u7F51\u5361)");
1271
+ let cardGateway = pc7.dim("(\u975E\u9ED8\u8BA4\u8DEF\u7531\u51FA\u53E3\u7F51\u5361)");
1239
1272
  if (isDefaultRouteCard) {
1240
1273
  if (defaultRoute.gateway && defaultRoute.gateway !== "0.0.0.0") {
1241
- cardGateway = pc6.yellow(defaultRoute.gateway);
1274
+ cardGateway = pc7.yellow(defaultRoute.gateway);
1242
1275
  } else {
1243
- cardGateway = pc6.yellow("\u76F4\u63A5\u70B9\u5BF9\u70B9\u96A7\u9053\u8FDE\u63A5 (Point-to-Point)");
1276
+ cardGateway = pc7.yellow("\u76F4\u63A5\u70B9\u5BF9\u70B9\u96A7\u9053\u8FDE\u63A5 (Point-to-Point)");
1244
1277
  }
1245
1278
  } else if (routeError) {
1246
- cardGateway = pc6.dim(`\u68C0\u6D4B\u5931\u8D25 (\u539F\u56E0: ${routeError})`);
1279
+ cardGateway = pc7.dim(`\u68C0\u6D4B\u5931\u8D25 (\u539F\u56E0: ${routeError})`);
1247
1280
  }
1248
1281
  console.log(
1249
- pc6.cyan(
1282
+ pc7.cyan(
1250
1283
  `================ \u6D3B\u8DC3\u7F51\u5361\u53CA\u7F51\u5173\u4FE1\u606F [${card.type}] ================`
1251
1284
  )
1252
1285
  );
1253
1286
  console.log(
1254
- `${pc6.green("\u7F51\u5361\u540D\u79F0 (Name):")} ${pc6.bold(card.name)}`
1287
+ `${pc7.green("\u7F51\u5361\u540D\u79F0 (Name):")} ${pc7.bold(card.name)}`
1255
1288
  );
1256
1289
  console.log(
1257
- `${pc6.green("\u672C\u673A IP \u5730\u5740 (IP):")} ${pc6.bold(primaryAddr.address)}`
1290
+ `${pc7.green("\u672C\u673A IP \u5730\u5740 (IP):")} ${pc7.bold(primaryAddr.address)}`
1258
1291
  );
1259
1292
  console.log(
1260
- `${pc6.green("\u5B50\u7F51\u63A9\u7801 (Mask):")} ${primaryAddr.netmask}`
1293
+ `${pc7.green("\u5B50\u7F51\u63A9\u7801 (Mask):")} ${primaryAddr.netmask}`
1261
1294
  );
1262
- console.log(`${pc6.green("\u9ED8\u8BA4\u7F51\u5173 (Gateway):")} ${cardGateway}`);
1263
- console.log(`${pc6.green("MAC \u5730\u5740 (MAC):")} ${card.mac}`);
1295
+ console.log(`${pc7.green("\u9ED8\u8BA4\u7F51\u5173 (Gateway):")} ${cardGateway}`);
1296
+ console.log(`${pc7.green("MAC \u5730\u5740 (MAC):")} ${card.mac}`);
1264
1297
  console.log(
1265
- `${pc6.green("IP \u534F\u8BAE\u7248\u672C:")} ${primaryAddr.family === "IPv4" || primaryAddr.family === "4" ? "IPv4" : "IPv6"}`
1298
+ `${pc7.green("IP \u534F\u8BAE\u7248\u672C:")} ${primaryAddr.family === "IPv4" || primaryAddr.family === "4" ? "IPv4" : "IPv6"}`
1266
1299
  );
1267
1300
  if (ipv4 && ipv6) {
1268
1301
  console.log(
1269
- `${pc6.green("\u672C\u5730 IPv6 \u5730\u5740:")} ${pc6.dim(ipv6.address)}`
1302
+ `${pc7.green("\u672C\u5730 IPv6 \u5730\u5740:")} ${pc7.dim(ipv6.address)}`
1270
1303
  );
1271
1304
  }
1272
1305
  console.log(
1273
- pc6.cyan("====================================================")
1306
+ pc7.cyan("====================================================")
1274
1307
  );
1275
1308
  console.log("");
1276
1309
  }
1277
1310
  } catch (error) {
1278
- console.error(pc6.red("\u274C \u68C0\u6D4B\u5931\u8D25\u3002"));
1311
+ console.error(pc7.red("\u274C \u68C0\u6D4B\u5931\u8D25\u3002"));
1279
1312
  if (error instanceof Error) {
1280
- console.error(pc6.red("\u9519\u8BEF\u8BE6\u60C5:"), error.message);
1313
+ console.error(pc7.red("\u9519\u8BEF\u8BE6\u60C5:"), error.message);
1281
1314
  }
1282
1315
  }
1283
1316
  });
1284
1317
  }
1285
1318
 
1286
1319
  // commands/list.ts
1287
- import fs6 from "fs/promises";
1288
- import pc7 from "picocolors";
1320
+ import fs7 from "fs/promises";
1321
+ import pc8 from "picocolors";
1289
1322
  import { resolve as resolve5 } from "path";
1290
1323
  function registerLsCommand(program2) {
1291
1324
  program2.command("list [path]").description("\u5217\u51FA\u76EE\u5F55\u4E2D\u7684\u6240\u6709\u6587\u4EF6\u548C\u76EE\u5F55\uFF08\u542B\u9690\u85CF\u9879\uFF09").action(async (targetPath) => {
1292
1325
  const inputPath = targetPath || ".";
1293
1326
  const absolutePath = resolve5(process.cwd(), inputPath);
1294
1327
  try {
1295
- const stat = await fs6.stat(absolutePath);
1328
+ const stat = await fs7.stat(absolutePath);
1296
1329
  if (!stat.isDirectory()) {
1297
- console.error(pc7.red(`\u274C \u9519\u8BEF: '${inputPath}' \u4E0D\u662F\u4E00\u4E2A\u6709\u6548\u7684\u76EE\u5F55\u3002`));
1330
+ console.error(pc8.red(`\u274C \u9519\u8BEF: '${inputPath}' \u4E0D\u662F\u4E00\u4E2A\u6709\u6548\u7684\u76EE\u5F55\u3002`));
1298
1331
  return;
1299
1332
  }
1300
1333
  const entries = [];
1301
- for (const entry of await fs6.readdir(absolutePath, {
1334
+ for (const entry of await fs7.readdir(absolutePath, {
1302
1335
  withFileTypes: true
1303
1336
  })) {
1304
1337
  entries.push(entry);
1305
1338
  }
1306
1339
  if (entries.length === 0) {
1307
- console.log(pc7.dim("\uFF08\u7A7A\u76EE\u5F55\uFF09"));
1340
+ console.log(pc8.dim("\uFF08\u7A7A\u76EE\u5F55\uFF09"));
1308
1341
  return;
1309
1342
  }
1310
1343
  entries.sort((a, b) => {
@@ -1316,13 +1349,13 @@ function registerLsCommand(program2) {
1316
1349
  const isHidden = entry.name.startsWith(".");
1317
1350
  if (entry.isDirectory()) {
1318
1351
  if (isHidden) {
1319
- console.log(pc7.dim(`\u{1F4C1} ${pc7.blue(entry.name)}/`));
1352
+ console.log(pc8.dim(`\u{1F4C1} ${pc8.blue(entry.name)}/`));
1320
1353
  } else {
1321
- console.log(`\u{1F4C1} ${pc7.blue(pc7.bold(entry.name))}/`);
1354
+ console.log(`\u{1F4C1} ${pc8.blue(pc8.bold(entry.name))}/`);
1322
1355
  }
1323
1356
  } else {
1324
1357
  if (isHidden) {
1325
- console.log(pc7.dim(`\u{1F4C4} ${entry.name}`));
1358
+ console.log(pc8.dim(`\u{1F4C4} ${entry.name}`));
1326
1359
  } else {
1327
1360
  console.log(`\u{1F4C4} ${entry.name}`);
1328
1361
  }
@@ -1330,7 +1363,7 @@ function registerLsCommand(program2) {
1330
1363
  }
1331
1364
  } catch (err) {
1332
1365
  console.error(
1333
- pc7.red(`\u274C \u65E0\u6CD5\u8BFB\u53D6\u76EE\u5F55\u5185\u5BB9:`),
1366
+ pc8.red(`\u274C \u65E0\u6CD5\u8BFB\u53D6\u76EE\u5F55\u5185\u5BB9:`),
1334
1367
  err instanceof Error ? err.message : err
1335
1368
  );
1336
1369
  }
@@ -1338,55 +1371,55 @@ function registerLsCommand(program2) {
1338
1371
  }
1339
1372
 
1340
1373
  // commands/move.ts
1341
- import fs7 from "fs/promises";
1342
- import pc8 from "picocolors";
1343
- import { dirname as dirname4, resolve as resolve6, join as join5, basename as basename3 } from "path";
1374
+ import fs8 from "fs/promises";
1375
+ import pc9 from "picocolors";
1376
+ import { dirname as dirname3, resolve as resolve6, join as join6, basename as basename4 } from "path";
1344
1377
  async function copyRecursive2(src, dest) {
1345
- const fileInfo = await fs7.stat(src);
1378
+ const fileInfo = await fs8.stat(src);
1346
1379
  if (fileInfo.isDirectory()) {
1347
- await fs7.mkdir(dest, { recursive: true });
1348
- for (const entry of await fs7.readdir(src, { withFileTypes: true })) {
1349
- await copyRecursive2(join5(src, entry.name), join5(dest, entry.name));
1380
+ await fs8.mkdir(dest, { recursive: true });
1381
+ for (const entry of await fs8.readdir(src, { withFileTypes: true })) {
1382
+ await copyRecursive2(join6(src, entry.name), join6(dest, entry.name));
1350
1383
  }
1351
1384
  } else if (fileInfo.isFile()) {
1352
- await fs7.mkdir(dirname4(dest), { recursive: true });
1353
- await fs7.copyFile(src, dest);
1385
+ await fs8.mkdir(dirname3(dest), { recursive: true });
1386
+ await fs8.copyFile(src, dest);
1354
1387
  }
1355
1388
  }
1356
1389
  function registerMoveCommand(program2) {
1357
1390
  program2.command("move <source> <target>").description("\u79FB\u52A8\u6216\u91CD\u547D\u540D\u6587\u4EF6\u53CA\u76EE\u5F55").action(async (source, target) => {
1358
1391
  if (!source || !target) {
1359
- console.error(pc8.red("\u274C \u8BF7\u63D0\u4F9B\u6E90\u8DEF\u5F84\u548C\u76EE\u6807\u8DEF\u5F84"));
1392
+ console.error(pc9.red("\u274C \u8BF7\u63D0\u4F9B\u6E90\u8DEF\u5F84\u548C\u76EE\u6807\u8DEF\u5F84"));
1360
1393
  return;
1361
1394
  }
1362
1395
  const absSource = resolve6(process.cwd(), source);
1363
1396
  const absTarget = resolve6(process.cwd(), target);
1364
1397
  try {
1365
- await fs7.stat(absSource);
1398
+ await fs8.stat(absSource);
1366
1399
  let finalTarget = absTarget;
1367
1400
  try {
1368
- const targetStat = await fs7.stat(absTarget);
1401
+ const targetStat = await fs8.stat(absTarget);
1369
1402
  if (targetStat.isDirectory()) {
1370
- finalTarget = join5(absTarget, basename3(absSource));
1403
+ finalTarget = join6(absTarget, basename4(absSource));
1371
1404
  }
1372
1405
  } catch {
1373
1406
  }
1374
- const targetParentDir = dirname4(finalTarget);
1375
- await fs7.mkdir(targetParentDir, { recursive: true });
1376
- console.log(pc8.cyan(`\u{1F4E6} \u6B63\u5728\u79FB\u52A8: ${source} \u27A1\uFE0F ${target}...`));
1407
+ const targetParentDir = dirname3(finalTarget);
1408
+ await fs8.mkdir(targetParentDir, { recursive: true });
1409
+ console.log(pc9.cyan(`\u{1F4E6} \u6B63\u5728\u79FB\u52A8: ${source} \u27A1\uFE0F ${target}...`));
1377
1410
  try {
1378
- await fs7.rename(absSource, finalTarget);
1411
+ await fs8.rename(absSource, finalTarget);
1379
1412
  } catch {
1380
1413
  await copyRecursive2(absSource, finalTarget);
1381
- await fs7.rm(absSource, { recursive: true });
1414
+ await fs8.rm(absSource, { recursive: true });
1382
1415
  }
1383
- console.log(pc8.green(`\u2728 \u79FB\u52A8\u6210\u529F: ${source} \u27A1\uFE0F ${target}`));
1416
+ console.log(pc9.green(`\u2728 \u79FB\u52A8\u6210\u529F: ${source} \u27A1\uFE0F ${target}`));
1384
1417
  } catch (err) {
1385
1418
  if (isNotFoundError(err)) {
1386
- console.error(pc8.red(`\u274C \u9519\u8BEF: \u6E90\u8DEF\u5F84\u4E0D\u5B58\u5728: ${absSource}`));
1419
+ console.error(pc9.red(`\u274C \u9519\u8BEF: \u6E90\u8DEF\u5F84\u4E0D\u5B58\u5728: ${absSource}`));
1387
1420
  } else {
1388
1421
  console.error(
1389
- pc8.red("\u274C \u79FB\u52A8\u5931\u8D25:"),
1422
+ pc9.red("\u274C \u79FB\u52A8\u5931\u8D25:"),
1390
1423
  err instanceof Error ? err.message : err
1391
1424
  );
1392
1425
  }
@@ -1395,21 +1428,21 @@ function registerMoveCommand(program2) {
1395
1428
  }
1396
1429
 
1397
1430
  // commands/open.ts
1398
- import fs8 from "fs/promises";
1399
- import pc9 from "picocolors";
1431
+ import fs9 from "fs/promises";
1432
+ import pc10 from "picocolors";
1400
1433
  import { resolve as resolve7 } from "path";
1401
1434
  function registerOpenCommand(program2) {
1402
1435
  program2.command("open [path]").description("\u5728\u7CFB\u7EDF\u6587\u4EF6\u7BA1\u7406\u5668\u4E2D\u6253\u5F00\u6307\u5B9A\u76EE\u5F55\uFF08\u9ED8\u8BA4\u5F53\u524D\u5DE5\u4F5C\u76EE\u5F55\uFF09").action(async (targetPath) => {
1403
1436
  const inputPath = targetPath || ".";
1404
1437
  const absolutePath = resolve7(process.cwd(), inputPath);
1405
1438
  try {
1406
- const stat = await fs8.stat(absolutePath);
1439
+ const stat = await fs9.stat(absolutePath);
1407
1440
  if (!stat.isDirectory()) {
1408
- console.error(pc9.red(`\u274C \u9519\u8BEF: '${inputPath}' \u4E0D\u662F\u4E00\u4E2A\u6709\u6548\u7684\u76EE\u5F55\u3002`));
1441
+ console.error(pc10.red(`\u274C \u9519\u8BEF: '${inputPath}' \u4E0D\u662F\u4E00\u4E2A\u6709\u6548\u7684\u76EE\u5F55\u3002`));
1409
1442
  return;
1410
1443
  }
1411
1444
  } catch {
1412
- console.error(pc9.red(`\u274C \u9519\u8BEF: \u627E\u4E0D\u5230\u76EE\u5F55 '${inputPath}'\u3002`));
1445
+ console.error(pc10.red(`\u274C \u9519\u8BEF: \u627E\u4E0D\u5230\u76EE\u5F55 '${inputPath}'\u3002`));
1413
1446
  return;
1414
1447
  }
1415
1448
  const os3 = process.platform;
@@ -1425,16 +1458,16 @@ function registerOpenCommand(program2) {
1425
1458
  cmd = "xdg-open";
1426
1459
  args = [absolutePath];
1427
1460
  } else {
1428
- console.error(pc9.red("\u274C \u6682\u4E0D\u652F\u6301\u5728\u5F53\u524D\u7CFB\u7EDF\u4E0B\u8C03\u8D77\u6587\u4EF6\u7BA1\u7406\u5668\u3002"));
1461
+ console.error(pc10.red("\u274C \u6682\u4E0D\u652F\u6301\u5728\u5F53\u524D\u7CFB\u7EDF\u4E0B\u8C03\u8D77\u6587\u4EF6\u7BA1\u7406\u5668\u3002"));
1429
1462
  return;
1430
1463
  }
1431
1464
  try {
1432
- console.log(pc9.cyan(`\u{1F4C2} \u6B63\u5728\u6253\u5F00\u6587\u4EF6\u5939: ${absolutePath}...`));
1465
+ console.log(pc10.cyan(`\u{1F4C2} \u6B63\u5728\u6253\u5F00\u6587\u4EF6\u5939: ${absolutePath}...`));
1433
1466
  await spawnCommand(cmd, args);
1434
- console.log(pc9.green("\u2728 \u6210\u529F\u8C03\u8D77\u6587\u4EF6\u7BA1\u7406\u5668\uFF01"));
1467
+ console.log(pc10.green("\u2728 \u6210\u529F\u8C03\u8D77\u6587\u4EF6\u7BA1\u7406\u5668\uFF01"));
1435
1468
  } catch (err) {
1436
1469
  console.error(
1437
- pc9.red("\u274C \u65E0\u6CD5\u6253\u5F00\u7BA1\u7406\u5668:"),
1470
+ pc10.red("\u274C \u65E0\u6CD5\u6253\u5F00\u7BA1\u7406\u5668:"),
1438
1471
  err instanceof Error ? err.message : err
1439
1472
  );
1440
1473
  }
@@ -1442,19 +1475,19 @@ function registerOpenCommand(program2) {
1442
1475
  }
1443
1476
 
1444
1477
  // commands/park.ts
1445
- import fs9, { open } from "fs/promises";
1478
+ import fs10, { open } from "fs/promises";
1446
1479
  import process2 from "process";
1447
- import pc10 from "picocolors";
1448
- import { join as join6, isAbsolute, resolve as resolve8, dirname as dirname5 } from "path";
1480
+ import pc11 from "picocolors";
1481
+ import { join as join7, isAbsolute, resolve as resolve8, dirname as dirname4 } from "path";
1449
1482
  var CONFIG_FILE_NAME = ".park_config.json";
1450
1483
  function getConfigFile() {
1451
1484
  const home = process2.env["HOME"] || process2.env["USERPROFILE"] || process2.cwd();
1452
- return join6(home, CONFIG_FILE_NAME);
1485
+ return join7(home, CONFIG_FILE_NAME);
1453
1486
  }
1454
1487
  async function readConfig() {
1455
1488
  try {
1456
1489
  const path = getConfigFile();
1457
- const content = await fs9.readFile(path, "utf-8");
1490
+ const content = await fs10.readFile(path, "utf-8");
1458
1491
  return JSON.parse(content);
1459
1492
  } catch {
1460
1493
  return {};
@@ -1463,9 +1496,9 @@ async function readConfig() {
1463
1496
  async function writeConfig(config) {
1464
1497
  try {
1465
1498
  const path = getConfigFile();
1466
- await fs9.writeFile(path, JSON.stringify(config, null, 2));
1499
+ await fs10.writeFile(path, JSON.stringify(config, null, 2));
1467
1500
  } catch (err) {
1468
- console.error(pc10.red("\u274C \u5199\u5165\u5168\u5C40\u914D\u7F6E\u6587\u4EF6\u5931\u8D25:"), err);
1501
+ console.error(pc11.red("\u274C \u5199\u5165\u5168\u5C40\u914D\u7F6E\u6587\u4EF6\u5931\u8D25:"), err);
1469
1502
  }
1470
1503
  }
1471
1504
  async function downloadImage(imageName, outputFilename, targetDir) {
@@ -1477,8 +1510,8 @@ async function downloadImage(imageName, outputFilename, targetDir) {
1477
1510
  cleanName = decodeURIComponent(cleanName).substring(prefix.length);
1478
1511
  }
1479
1512
  const fullImageName = prefix + cleanName;
1480
- console.log(pc10.cyan(`\u{1F4E6} \u76EE\u6807\u955C\u50CF: ${pc10.bold(fullImageName)}`));
1481
- console.log(pc10.dim("\u6B63\u5728\u5411\u6253\u5305\u670D\u52A1\u5668\u63D0\u4EA4\u4EFB\u52A1\uFF0C\u8BF7\u7A0D\u5019...\n"));
1513
+ console.log(pc11.cyan(`\u{1F4E6} \u76EE\u6807\u955C\u50CF: ${pc11.bold(fullImageName)}`));
1514
+ console.log(pc11.dim("\u6B63\u5728\u5411\u6253\u5305\u670D\u52A1\u5668\u63D0\u4EA4\u4EFB\u52A1\uFF0C\u8BF7\u7A0D\u5019...\n"));
1482
1515
  try {
1483
1516
  const response = await fetch("https://city189.cn:1091/", {
1484
1517
  method: "POST",
@@ -1515,15 +1548,15 @@ async function downloadImage(imageName, outputFilename, targetDir) {
1515
1548
  matchedFilename = match[0];
1516
1549
  downloadUrl = `https://city189.cn:1091/download/${matchedFilename}`;
1517
1550
  } else {
1518
- console.error(pc10.red("\u274C \u672A\u80FD\u5728\u670D\u52A1\u5668\u54CD\u5E94\u4E2D\u5339\u914D\u5230\u6253\u5305\u6587\u4EF6\u540D\u3002"));
1519
- console.log(pc10.yellow("\u670D\u52A1\u5668\u539F\u59CB\u54CD\u5E94\u5982\u4E0B\uFF1A"));
1551
+ console.error(pc11.red("\u274C \u672A\u80FD\u5728\u670D\u52A1\u5668\u54CD\u5E94\u4E2D\u5339\u914D\u5230\u6253\u5305\u6587\u4EF6\u540D\u3002"));
1552
+ console.log(pc11.yellow("\u670D\u52A1\u5668\u539F\u59CB\u54CD\u5E94\u5982\u4E0B\uFF1A"));
1520
1553
  console.log(text);
1521
1554
  throw new Error("\u65E0\u6CD5\u63D0\u53D6\u6253\u5305\u540E\u7684\u6587\u4EF6\u540D");
1522
1555
  }
1523
1556
  }
1524
- console.log(pc10.green(`\u2705 \u6253\u5305\u4EFB\u52A1\u63D0\u4EA4\u6210\u529F!`));
1525
- console.log(pc10.green(`\u{1F517} \u4E0B\u8F7D\u94FE\u63A5: ${pc10.underline(downloadUrl)}`));
1526
- console.log(pc10.cyan(`
1557
+ console.log(pc11.green(`\u2705 \u6253\u5305\u4EFB\u52A1\u63D0\u4EA4\u6210\u529F!`));
1558
+ console.log(pc11.green(`\u{1F517} \u4E0B\u8F7D\u94FE\u63A5: ${pc11.underline(downloadUrl)}`));
1559
+ console.log(pc11.cyan(`
1527
1560
  \u{1F4E5} \u5F00\u59CB\u4E0B\u8F7D: ${matchedFilename}...`));
1528
1561
  const downloadRes = await fetch(downloadUrl, {
1529
1562
  headers: {
@@ -1548,10 +1581,10 @@ async function downloadImage(imageName, outputFilename, targetDir) {
1548
1581
  downloadDir = config.defaultDownloadDir ? config.defaultDownloadDir : process2.cwd();
1549
1582
  }
1550
1583
  const baseFilename = outputFilename || matchedFilename || "bundle.tar";
1551
- const finalPath = isAbsolute(baseFilename) ? baseFilename : join6(downloadDir, baseFilename);
1552
- const targetDirToCreate = dirname5(finalPath);
1584
+ const finalPath = isAbsolute(baseFilename) ? baseFilename : join7(downloadDir, baseFilename);
1585
+ const targetDirToCreate = dirname4(finalPath);
1553
1586
  try {
1554
- await fs9.mkdir(targetDirToCreate, { recursive: true });
1587
+ await fs10.mkdir(targetDirToCreate, { recursive: true });
1555
1588
  } catch {
1556
1589
  }
1557
1590
  const file = await open(finalPath, "w");
@@ -1578,11 +1611,11 @@ async function downloadImage(imageName, outputFilename, targetDir) {
1578
1611
  }
1579
1612
  }
1580
1613
  await file.close();
1581
- console.log("\n" + pc10.green(`\u2728 \u4E0B\u8F7D\u5E76\u4FDD\u5B58\u6210\u529F! \u6587\u4EF6\u8DEF\u5F84: ${finalPath}`));
1614
+ console.log("\n" + pc11.green(`\u2728 \u4E0B\u8F7D\u5E76\u4FDD\u5B58\u6210\u529F! \u6587\u4EF6\u8DEF\u5F84: ${finalPath}`));
1582
1615
  } catch (error) {
1583
- console.error(pc10.red("\n\u274C \u6267\u884C\u5931\u8D25\u3002"));
1616
+ console.error(pc11.red("\n\u274C \u6267\u884C\u5931\u8D25\u3002"));
1584
1617
  if (error instanceof Error) {
1585
- console.error(pc10.red("\u9519\u8BEF\u8BE6\u60C5:"), error.message);
1618
+ console.error(pc11.red("\u9519\u8BEF\u8BE6\u60C5:"), error.message);
1586
1619
  }
1587
1620
  }
1588
1621
  }
@@ -1595,11 +1628,11 @@ function registerParkCommand(program2) {
1595
1628
  if (options.global) {
1596
1629
  const absPath = resolve8(process2.cwd(), options.global);
1597
1630
  await writeConfig({ defaultDownloadDir: absPath });
1598
- console.log(pc10.green(`\u2728 \u5DF2\u6210\u529F\u8BBE\u7F6E\u5168\u5C40\u9ED8\u8BA4\u4E0B\u8F7D\u76EE\u5F55\u4E3A: ${absPath}`));
1631
+ console.log(pc11.green(`\u2728 \u5DF2\u6210\u529F\u8BBE\u7F6E\u5168\u5C40\u9ED8\u8BA4\u4E0B\u8F7D\u76EE\u5F55\u4E3A: ${absPath}`));
1599
1632
  return;
1600
1633
  }
1601
1634
  if (!image) {
1602
- console.error(pc10.red("\u274C \u9519\u8BEF: \u672A\u6307\u5B9A\u9700\u8981\u4E0B\u8F7D\u7684\u955C\u50CF\u540D\u79F0\u3002"));
1635
+ console.error(pc11.red("\u274C \u9519\u8BEF: \u672A\u6307\u5B9A\u9700\u8981\u4E0B\u8F7D\u7684\u955C\u50CF\u540D\u79F0\u3002"));
1603
1636
  cmd.outputHelp();
1604
1637
  return;
1605
1638
  }
@@ -1609,7 +1642,7 @@ function registerParkCommand(program2) {
1609
1642
  }
1610
1643
 
1611
1644
  // commands/proxy.ts
1612
- import pc11 from "picocolors";
1645
+ import pc12 from "picocolors";
1613
1646
  function registerProxyCommand(program2) {
1614
1647
  program2.command("proxy [action] [port]").description(
1615
1648
  "\u7BA1\u7406\u7EC8\u7AEF\u4E34\u65F6\u4EE3\u7406 (\u652F\u6301 proxy on [port] \u6216 proxy off\uFF0C\u65E0\u53C2\u6570\u65F6\u67E5\u770B\u5F53\u524D\u72B6\u6001)"
@@ -1617,29 +1650,29 @@ function registerProxyCommand(program2) {
1617
1650
  if (action === "on") {
1618
1651
  const p = port || "7890";
1619
1652
  console.log(
1620
- pc11.yellow(
1653
+ pc12.yellow(
1621
1654
  `\u26A0\uFE0F \u8B66\u544A: \u76F4\u63A5\u8FD0\u884C\u4E8C\u8FDB\u5236\u65E0\u6CD5\u76F4\u63A5\u4FEE\u6539\u5F53\u524D\u7EC8\u7AEF\u7684\u4E3B\u73AF\u5883\u53D8\u91CF\u3002`
1622
1655
  )
1623
1656
  );
1624
- console.log(pc11.cyan(`\u{1F449} \u8BF7\u8FD0\u884C\u4EE5\u4E0B\u547D\u4EE4\u6765\u624B\u52A8\u542F\u7528\u4EE3\u7406\uFF1A`));
1625
- console.log(pc11.bold(` export http_proxy="http://127.0.0.1:${p}"`));
1626
- console.log(pc11.bold(` export https_proxy="http://127.0.0.1:${p}"`));
1627
- console.log(pc11.bold(` export all_proxy="socks5://127.0.0.1:${p}"`));
1657
+ console.log(pc12.cyan(`\u{1F449} \u8BF7\u8FD0\u884C\u4EE5\u4E0B\u547D\u4EE4\u6765\u624B\u52A8\u542F\u7528\u4EE3\u7406\uFF1A`));
1658
+ console.log(pc12.bold(` export http_proxy="http://127.0.0.1:${p}"`));
1659
+ console.log(pc12.bold(` export https_proxy="http://127.0.0.1:${p}"`));
1660
+ console.log(pc12.bold(` export all_proxy="socks5://127.0.0.1:${p}"`));
1628
1661
  console.log(
1629
- pc11.dim(
1662
+ pc12.dim(
1630
1663
  `
1631
1664
  \u{1F4A1} \u63D0\u793A\uFF1A\u6267\u884C\u4E00\u6B21 'xx completion' \u5E76\u91CD\u5F00\u7EC8\u7AEF\u540E\uFF0C\u5373\u53EF\u76F4\u63A5\u8FD0\u884C 'xx proxy on' \u4E00\u952E\u5F00\u542F\uFF01`
1632
1665
  )
1633
1666
  );
1634
1667
  } else if (action === "off") {
1635
1668
  console.log(
1636
- pc11.yellow(
1669
+ pc12.yellow(
1637
1670
  `\u26A0\uFE0F \u8B66\u544A: \u76F4\u63A5\u8FD0\u884C\u4E8C\u8FDB\u5236\u65E0\u6CD5\u76F4\u63A5\u4FEE\u6539\u5F53\u524D\u7EC8\u7AEF\u7684\u4E3B\u73AF\u5883\u53D8\u91CF\u3002`
1638
1671
  )
1639
1672
  );
1640
- console.log(pc11.cyan(`\u{1F449} \u8BF7\u8FD0\u884C\u4EE5\u4E0B\u547D\u4EE4\u6765\u624B\u52A8\u5173\u95ED\u4EE3\u7406\uFF1A`));
1673
+ console.log(pc12.cyan(`\u{1F449} \u8BF7\u8FD0\u884C\u4EE5\u4E0B\u547D\u4EE4\u6765\u624B\u52A8\u5173\u95ED\u4EE3\u7406\uFF1A`));
1641
1674
  console.log(
1642
- pc11.bold(
1675
+ pc12.bold(
1643
1676
  ` unset http_proxy https_proxy all_proxy HTTP_PROXY HTTPS_PROXY ALL_PROXY`
1644
1677
  )
1645
1678
  );
@@ -1648,15 +1681,15 @@ function registerProxyCommand(program2) {
1648
1681
  const httpsProxy = process.env["https_proxy"] || process.env["HTTPS_PROXY"];
1649
1682
  const allProxy = process.env["all_proxy"] || process.env["ALL_PROXY"];
1650
1683
  if (httpProxy || httpsProxy || allProxy) {
1651
- console.log(pc11.yellow("\u{1F50D} [xx] \u68C0\u6D4B\u5230\u5F53\u524D\u7EC8\u7AEF\u5DF2\u914D\u7F6E\u4E34\u65F6\u4EE3\u7406\uFF1A"));
1652
- if (httpProxy) console.log(` http_proxy = ${pc11.bold(httpProxy)}`);
1653
- if (httpsProxy) console.log(` https_proxy = ${pc11.bold(httpsProxy)}`);
1654
- if (allProxy) console.log(` all_proxy = ${pc11.bold(allProxy)}`);
1684
+ console.log(pc12.yellow("\u{1F50D} [xx] \u68C0\u6D4B\u5230\u5F53\u524D\u7EC8\u7AEF\u5DF2\u914D\u7F6E\u4E34\u65F6\u4EE3\u7406\uFF1A"));
1685
+ if (httpProxy) console.log(` http_proxy = ${pc12.bold(httpProxy)}`);
1686
+ if (httpsProxy) console.log(` https_proxy = ${pc12.bold(httpsProxy)}`);
1687
+ if (allProxy) console.log(` all_proxy = ${pc12.bold(allProxy)}`);
1655
1688
  } else {
1656
- console.log(pc11.green("\u{1F50D} [xx] \u5F53\u524D\u7EC8\u7AEF\u672A\u914D\u7F6E\u4EFB\u4F55\u4EE3\u7406 (\u76F4\u8FDE\u6A21\u5F0F)"));
1689
+ console.log(pc12.green("\u{1F50D} [xx] \u5F53\u524D\u7EC8\u7AEF\u672A\u914D\u7F6E\u4EFB\u4F55\u4EE3\u7406 (\u76F4\u8FDE\u6A21\u5F0F)"));
1657
1690
  }
1658
1691
  console.log(
1659
- pc11.dim(
1692
+ pc12.dim(
1660
1693
  "\n\u{1F4A1} \u63D0\u793A\uFF1A\u60A8\u53EF\u4EE5\u4F7F\u7528 'xx proxy on [port]' \u5F00\u542F\u6216 'xx proxy off' \u5173\u95ED\u4E34\u65F6\u4EE3\u7406\u3002"
1661
1694
  )
1662
1695
  );
@@ -1665,15 +1698,15 @@ function registerProxyCommand(program2) {
1665
1698
  }
1666
1699
 
1667
1700
  // commands/remove.ts
1668
- import fs10 from "fs/promises";
1669
- import pc12 from "picocolors";
1701
+ import fs11 from "fs/promises";
1702
+ import pc13 from "picocolors";
1670
1703
  import { resolve as resolve9 } from "path";
1671
1704
  import fg from "fast-glob";
1672
1705
  import trash from "trash";
1673
1706
  function registerRemoveCommand(program2) {
1674
1707
  program2.command("remove <paths...>").description("\u5B89\u5168\u5730\u5C06\u6307\u5B9A\u7684\u6587\u4EF6\u6216\u76EE\u5F55\u79FB\u81F3\u7CFB\u7EDF\u56DE\u6536\u7AD9\uFF08\u652F\u6301\u901A\u914D\u7B26\u53CA\u591A\u9009\uFF09").action(async (paths) => {
1675
1708
  if (!paths || paths.length === 0) {
1676
- console.error(pc12.red("\u274C \u8BF7\u63D0\u4F9B\u8981\u653E\u5165\u56DE\u6536\u7AD9\u7684\u8DEF\u5F84\u6216\u901A\u914D\u7B26\u89C4\u5219"));
1709
+ console.error(pc13.red("\u274C \u8BF7\u63D0\u4F9B\u8981\u653E\u5165\u56DE\u6536\u7AD9\u7684\u8DEF\u5F84\u6216\u901A\u914D\u7B26\u89C4\u5219"));
1677
1710
  return;
1678
1711
  }
1679
1712
  const resolvedPathsToDelete = /* @__PURE__ */ new Set();
@@ -1693,21 +1726,21 @@ function registerRemoveCommand(program2) {
1693
1726
  }
1694
1727
  } catch (err) {
1695
1728
  console.error(
1696
- pc12.red(`\u274C \u5339\u914D\u901A\u914D\u7B26 '${pattern}' \u65F6\u53D1\u751F\u5F02\u5E38:`),
1729
+ pc13.red(`\u274C \u5339\u914D\u901A\u914D\u7B26 '${pattern}' \u65F6\u53D1\u751F\u5F02\u5E38:`),
1697
1730
  err instanceof Error ? err.message : err
1698
1731
  );
1699
1732
  }
1700
1733
  } else {
1701
1734
  const absolutePath = resolve9(process.cwd(), pattern);
1702
1735
  try {
1703
- await fs10.stat(absolutePath);
1736
+ await fs11.stat(absolutePath);
1704
1737
  resolvedPathsToDelete.add(absolutePath);
1705
1738
  } catch (err) {
1706
1739
  if (isNotFoundError(err)) {
1707
1740
  notFoundPaths.push(absolutePath);
1708
1741
  } else {
1709
1742
  console.error(
1710
- pc12.red(`\u274C \u83B7\u53D6\u8DEF\u5F84\u72B6\u6001\u5931\u8D25 [${pattern}]:`),
1743
+ pc13.red(`\u274C \u83B7\u53D6\u8DEF\u5F84\u72B6\u6001\u5931\u8D25 [${pattern}]:`),
1711
1744
  err instanceof Error ? err.message : err
1712
1745
  );
1713
1746
  }
@@ -1716,31 +1749,31 @@ function registerRemoveCommand(program2) {
1716
1749
  }
1717
1750
  if (notFoundPaths.length > 0) {
1718
1751
  for (const path of notFoundPaths) {
1719
- console.error(pc12.red(`\u274C \u8DEF\u5F84\u4E0D\u5B58\u5728: ${path}`));
1752
+ console.error(pc13.red(`\u274C \u8DEF\u5F84\u4E0D\u5B58\u5728: ${path}`));
1720
1753
  }
1721
1754
  }
1722
1755
  if (resolvedPathsToDelete.size === 0) {
1723
- console.log(pc12.yellow("\u2139\uFE0F \u672A\u80FD\u627E\u5230\u4EFB\u4F55\u4E0E\u6307\u5B9A\u6761\u4EF6\u5339\u914D\u7684\u6587\u4EF6\u6216\u76EE\u5F55\u3002"));
1756
+ console.log(pc13.yellow("\u2139\uFE0F \u672A\u80FD\u627E\u5230\u4EFB\u4F55\u4E0E\u6307\u5B9A\u6761\u4EF6\u5339\u914D\u7684\u6587\u4EF6\u6216\u76EE\u5F55\u3002"));
1724
1757
  return;
1725
1758
  }
1726
1759
  try {
1727
1760
  console.log(
1728
- pc12.cyan(
1761
+ pc13.cyan(
1729
1762
  `\u{1F4E6} \u6B63\u5728\u5C06 ${resolvedPathsToDelete.size} \u4E2A\u9879\u79FB\u81F3\u7CFB\u7EDF\u56DE\u6536\u7AD9...`
1730
1763
  )
1731
1764
  );
1732
1765
  await trash(Array.from(resolvedPathsToDelete));
1733
1766
  for (const path of resolvedPathsToDelete) {
1734
- console.log(pc12.dim(` - \u5DF2\u79FB\u5165\u5783\u573E\u7BB1: ${path}`));
1767
+ console.log(pc13.dim(` - \u5DF2\u79FB\u5165\u5783\u573E\u7BB1: ${path}`));
1735
1768
  }
1736
1769
  console.log(
1737
- pc12.green(
1770
+ pc13.green(
1738
1771
  `\u2728 \u6210\u529F\uFF01\u5171 ${resolvedPathsToDelete.size} \u4E2A\u6587\u4EF6/\u76EE\u5F55\u5DF2\u5B89\u5168\u9001\u81F3\u7CFB\u7EDF\u56DE\u6536\u7AD9\u3002`
1739
1772
  )
1740
1773
  );
1741
1774
  } catch (err) {
1742
1775
  console.error(
1743
- pc12.red("\u274C \u79FB\u81F3\u56DE\u6536\u7AD9\u5931\u8D25:"),
1776
+ pc13.red("\u274C \u79FB\u81F3\u56DE\u6536\u7AD9\u5931\u8D25:"),
1744
1777
  err instanceof Error ? err.message : err
1745
1778
  );
1746
1779
  }
@@ -1748,32 +1781,32 @@ function registerRemoveCommand(program2) {
1748
1781
  }
1749
1782
 
1750
1783
  // commands/search.ts
1751
- import fs11 from "fs/promises";
1752
- import pc13 from "picocolors";
1753
- import { resolve as resolve10, basename as basename4, relative } from "path";
1784
+ import fs12 from "fs/promises";
1785
+ import pc14 from "picocolors";
1786
+ import { resolve as resolve10, basename as basename5, relative } from "path";
1754
1787
  import fg2 from "fast-glob";
1755
1788
  function registerSearchCommand(program2) {
1756
1789
  program2.command("search <keyword> [directory]").description(
1757
1790
  "\u9012\u5F52\u641C\u7D22\u76EE\u5F55\u4E0B\u5305\u542B\u6307\u5B9A\u5173\u952E\u8BCD\u7684\u6587\u4EF6\u6216\u76EE\u5F55\uFF08\u652F\u6301 Ctrl+\u70B9\u51FB \u5FEB\u6377\u6253\u5F00\uFF09"
1758
1791
  ).action(async (keyword, directory) => {
1759
1792
  if (!keyword) {
1760
- console.error(pc13.red("\u274C \u8BF7\u63D0\u4F9B\u8981\u641C\u7D22\u7684\u6587\u4EF6\u540D\u5173\u952E\u8BCD"));
1793
+ console.error(pc14.red("\u274C \u8BF7\u63D0\u4F9B\u8981\u641C\u7D22\u7684\u6587\u4EF6\u540D\u5173\u952E\u8BCD"));
1761
1794
  return;
1762
1795
  }
1763
1796
  const startDir = directory || ".";
1764
1797
  const absoluteStartDir = resolve10(process.cwd(), startDir);
1765
1798
  try {
1766
- const stat = await fs11.stat(absoluteStartDir);
1799
+ const stat = await fs12.stat(absoluteStartDir);
1767
1800
  if (!stat.isDirectory()) {
1768
- console.error(pc13.red(`\u274C \u9519\u8BEF: '${startDir}' \u4E0D\u662F\u4E00\u4E2A\u6709\u6548\u7684\u76EE\u5F55\u3002`));
1801
+ console.error(pc14.red(`\u274C \u9519\u8BEF: '${startDir}' \u4E0D\u662F\u4E00\u4E2A\u6709\u6548\u7684\u76EE\u5F55\u3002`));
1769
1802
  return;
1770
1803
  }
1771
1804
  } catch {
1772
- console.error(pc13.red(`\u274C \u9519\u8BEF: \u627E\u4E0D\u5230\u8D77\u70B9\u76EE\u5F55 '${startDir}'\u3002`));
1805
+ console.error(pc14.red(`\u274C \u9519\u8BEF: \u627E\u4E0D\u5230\u8D77\u70B9\u76EE\u5F55 '${startDir}'\u3002`));
1773
1806
  return;
1774
1807
  }
1775
1808
  console.log(
1776
- pc13.cyan(
1809
+ pc14.cyan(
1777
1810
  `\u{1F50D} \u6B63\u5728\u76EE\u5F55 ${absoluteStartDir} \u4E2D\u9012\u5F52\u641C\u5BFB\u5305\u542B "${keyword}" \u7684\u9879\u76EE...
1778
1811
  `
1779
1812
  )
@@ -1794,30 +1827,30 @@ function registerSearchCommand(program2) {
1794
1827
  ]
1795
1828
  });
1796
1829
  for (const entryPath of entries) {
1797
- const name = basename4(entryPath);
1830
+ const name = basename5(entryPath);
1798
1831
  if (name.toLowerCase().includes(keyword.toLowerCase())) {
1799
1832
  matchCount++;
1800
1833
  const relativePath = relative(absoluteStartDir, entryPath);
1801
1834
  const isDirectory = !name.includes(".") || entryPath.endsWith("/");
1802
1835
  let isDir = isDirectory;
1803
1836
  try {
1804
- const entryStat = await fs11.stat(entryPath);
1837
+ const entryStat = await fs12.stat(entryPath);
1805
1838
  isDir = entryStat.isDirectory();
1806
1839
  } catch {
1807
1840
  }
1808
1841
  const typeIcon = isDir ? "\u{1F4C1}" : "\u{1F4C4}";
1809
1842
  const fileUri = `file://${entryPath}`;
1810
- const hyperlink = `\x1B]8;;${fileUri}\x1B\\${pc13.bold(name)}\x1B]8;;\x1B\\`;
1811
- console.log(`${typeIcon} ${hyperlink} -> ${pc13.dim(fileUri)}`);
1843
+ const hyperlink = `\x1B]8;;${fileUri}\x1B\\${pc14.bold(name)}\x1B]8;;\x1B\\`;
1844
+ console.log(`${typeIcon} ${hyperlink} -> ${pc14.dim(fileUri)}`);
1812
1845
  }
1813
1846
  }
1814
1847
  console.log(
1815
- pc13.green(`
1848
+ pc14.green(`
1816
1849
  \u2728 \u641C\u7D22\u5B8C\u6210\uFF01\u5171\u627E\u5230 ${matchCount} \u4E2A\u5339\u914D\u7684\u9879\u76EE\u3002`)
1817
1850
  );
1818
1851
  } catch (err) {
1819
1852
  console.error(
1820
- pc13.red("\u274C \u641C\u5BFB\u8FC7\u7A0B\u4E2D\u53D1\u751F\u9519\u8BEF:"),
1853
+ pc14.red("\u274C \u641C\u5BFB\u8FC7\u7A0B\u4E2D\u53D1\u751F\u9519\u8BEF:"),
1821
1854
  err instanceof Error ? err.message : err
1822
1855
  );
1823
1856
  }
@@ -1825,7 +1858,7 @@ function registerSearchCommand(program2) {
1825
1858
  }
1826
1859
 
1827
1860
  // commands/translate.ts
1828
- import pc14 from "picocolors";
1861
+ import pc15 from "picocolors";
1829
1862
  import { translate } from "google-translate-api-x";
1830
1863
  import readline from "readline";
1831
1864
  import process3 from "process";
@@ -1842,13 +1875,13 @@ async function performTranslation(text, userSpecifiedLang) {
1842
1875
  to: targetLang
1843
1876
  });
1844
1877
  console.log(
1845
- `${pc14.green("\u8BD1\u6587:")} ${pc14.bold(res.text)} ${pc14.dim(`(${res.from.language.iso} -> ${targetLang})`)}`
1878
+ `${pc15.green("\u8BD1\u6587:")} ${pc15.bold(res.text)} ${pc15.dim(`(${res.from.language.iso} -> ${targetLang})`)}`
1846
1879
  );
1847
1880
  } catch (err) {
1848
1881
  if (err instanceof Error) {
1849
- console.error(pc14.red("\u274C \u7FFB\u8BD1\u51FA\u9519:"), err.message);
1882
+ console.error(pc15.red("\u274C \u7FFB\u8BD1\u51FA\u9519:"), err.message);
1850
1883
  } else {
1851
- console.error(pc14.red("\u274C \u7FFB\u8BD1\u51FA\u9519:"), String(err));
1884
+ console.error(pc15.red("\u274C \u7FFB\u8BD1\u51FA\u9519:"), String(err));
1852
1885
  }
1853
1886
  }
1854
1887
  }
@@ -1856,11 +1889,11 @@ function startInteractiveMode(userSpecifiedLang) {
1856
1889
  const rl = readline.createInterface({
1857
1890
  input: process3.stdin,
1858
1891
  output: process3.stdout,
1859
- prompt: pc14.cyan("\u7FFB\u8BD1\u8F93\u5165 > ")
1892
+ prompt: pc15.cyan("\u7FFB\u8BD1\u8F93\u5165 > ")
1860
1893
  });
1861
1894
  const modeTip = userSpecifiedLang === "auto" ? "\u667A\u80FD\u81EA\u52A8\u8BC6\u522B" : `\u5F3A\u5236\u76EE\u6807\u8BED\u8A00: ${userSpecifiedLang}`;
1862
- console.log(pc14.yellow(`\u2728 \u5DF2\u8FDB\u5165\u4EA4\u4E92\u6A21\u5F0F (${modeTip})`));
1863
- console.log(pc14.dim('\u8F93\u5165 "exit" \u6216\u6309 Ctrl+C \u9000\u51FA\n'));
1895
+ console.log(pc15.yellow(`\u2728 \u5DF2\u8FDB\u5165\u4EA4\u4E92\u6A21\u5F0F (${modeTip})`));
1896
+ console.log(pc15.dim('\u8F93\u5165 "exit" \u6216\u6309 Ctrl+C \u9000\u51FA\n'));
1864
1897
  rl.prompt();
1865
1898
  rl.on("line", async (line) => {
1866
1899
  const input = line.trim();
@@ -1874,7 +1907,7 @@ function startInteractiveMode(userSpecifiedLang) {
1874
1907
  console.log();
1875
1908
  rl.prompt();
1876
1909
  }).on("close", () => {
1877
- console.log(pc14.blue("\n\u518D\u89C1!"));
1910
+ console.log(pc15.blue("\n\u518D\u89C1!"));
1878
1911
  process3.exit(0);
1879
1912
  });
1880
1913
  }
@@ -1893,464 +1926,33 @@ function registerTanslateCommand(program2) {
1893
1926
  }
1894
1927
 
1895
1928
  // commands/uninstall.ts
1896
- import fs12 from "fs/promises";
1897
- import pc15 from "picocolors";
1898
- import { resolve as resolve11, join as join7 } from "path";
1899
- function getHomeDir2() {
1900
- return process.env["HOME"] || process.env["USERPROFILE"] || process.cwd();
1901
- }
1902
- async function isSnapInstalled(packageName) {
1903
- if (!await isCommandAvailable("snap")) return false;
1904
- try {
1905
- const { success } = await runCommand("snap", ["list", packageName]);
1906
- return success;
1907
- } catch {
1908
- return false;
1909
- }
1910
- }
1911
- async function isSystemPackageInstalled(packageName) {
1912
- try {
1913
- const osRelease = await fs12.readFile("/etc/os-release", "utf-8");
1914
- if (osRelease.includes("fedora") || osRelease.includes("rhel") || osRelease.includes("centos")) {
1915
- const { success } = await runCommand("rpm", ["-q", packageName]);
1916
- return success;
1917
- } else {
1918
- const { success, stdout } = await runCommand("dpkg-query", [
1919
- "-W",
1920
- "-f=${Status}",
1921
- packageName
1922
- ]);
1923
- if (success) {
1924
- const status = decodeOutput(stdout).trim();
1925
- return status.includes("installed");
1926
- }
1927
- return false;
1928
- }
1929
- } catch {
1930
- return false;
1931
- }
1932
- }
1933
- async function findGreenAppPath(appName) {
1934
- const home = getHomeDir2();
1935
- const greenAppDir = join7(home, "GreenApp");
1936
- const dirPath = join7(greenAppDir, appName);
1937
- try {
1938
- const stat = await fs12.stat(dirPath);
1939
- if (stat.isDirectory()) return dirPath;
1940
- } catch {
1941
- }
1942
- const appImagePath = join7(greenAppDir, `${appName}.AppImage`);
1943
- const appImageLowerPath = join7(greenAppDir, `${appName}.appimage`);
1944
- try {
1945
- const stat = await fs12.stat(appImagePath);
1946
- if (stat.isFile()) return appImagePath;
1947
- } catch {
1948
- try {
1949
- const stat = await fs12.stat(appImageLowerPath);
1950
- if (stat.isFile()) return appImageLowerPath;
1951
- } catch {
1952
- }
1953
- }
1954
- if (appName.toLowerCase().endsWith(".appimage")) {
1955
- const directPath = join7(greenAppDir, appName);
1956
- try {
1957
- const stat = await fs12.stat(directPath);
1958
- if (stat.isFile()) return directPath;
1959
- } catch {
1960
- }
1961
- }
1962
- return null;
1963
- }
1964
- async function extractDebPackageName(absPath) {
1965
- try {
1966
- const { success, stdout } = await runCommand("dpkg-deb", [
1967
- "-f",
1968
- absPath,
1969
- "Package"
1970
- ]);
1971
- if (success) {
1972
- return decodeOutput(stdout).trim();
1973
- }
1974
- } catch {
1975
- }
1976
- return void 0;
1977
- }
1978
- async function extractRpmPackageName(absPath) {
1979
- try {
1980
- const { success, stdout } = await runCommand("rpm", [
1981
- "-qp",
1982
- "--queryformat",
1983
- "%{NAME}",
1984
- absPath
1985
- ]);
1986
- if (success) {
1987
- return decodeOutput(stdout).trim();
1988
- }
1989
- } catch {
1990
- }
1991
- return void 0;
1992
- }
1993
- async function searchGreenApps(query) {
1994
- const home = getHomeDir2();
1995
- const greenAppDir = join7(home, "GreenApp");
1996
- const candidates = [];
1997
- try {
1998
- for (const entry of await fs12.readdir(greenAppDir, {
1999
- withFileTypes: true
2000
- })) {
2001
- if (entry.name.toLowerCase().includes(query.toLowerCase())) {
2002
- candidates.push(entry.name.replace(/\.appimage/i, ""));
2003
- }
2004
- }
2005
- } catch {
2006
- }
2007
- return candidates;
2008
- }
2009
- async function searchFlatpaks(query) {
2010
- const candidates = [];
2011
- if (!await isCommandAvailable("flatpak")) return candidates;
2012
- try {
2013
- const { success, stdout } = await runCommand("flatpak", [
2014
- "list",
2015
- "--columns=application,name"
2016
- ]);
2017
- if (success) {
2018
- const output = decodeOutput(stdout).trim();
2019
- const lines = output.split("\n");
2020
- for (const line of lines) {
2021
- const parts = line.split(" ").map((p) => p.trim());
2022
- if (parts.length >= 2) {
2023
- const [id, name] = parts;
2024
- if (id.toLowerCase().includes(query.toLowerCase()) || name.toLowerCase().includes(query.toLowerCase())) {
2025
- candidates.push({ id, name });
2026
- }
2027
- }
2028
- }
2029
- }
2030
- } catch {
2031
- }
2032
- return candidates;
2033
- }
2034
- async function searchDebPackages(query) {
2035
- const pkgs = [];
2036
- try {
2037
- const { success, stdout } = await runCommand("dpkg-query", [
2038
- "-W",
2039
- "-f=${Package}\n",
2040
- `*${query}*`
2041
- ]);
2042
- if (success) {
2043
- const output = decodeOutput(stdout).trim();
2044
- const lines = output.split("\n");
2045
- for (const line of lines) {
2046
- const name = line.trim();
2047
- if (name && !name.startsWith("-f=")) {
2048
- pkgs.push(name);
2049
- }
2050
- }
2051
- }
2052
- } catch {
2053
- }
2054
- return pkgs;
2055
- }
2056
- async function searchRpmPackages(query) {
2057
- const pkgs = [];
2058
- try {
2059
- const { success, stdout } = await runCommand("rpm", [
2060
- "-qa",
2061
- "--queryformat",
2062
- "%{NAME}\n",
2063
- `*${query}*`
2064
- ]);
2065
- if (success) {
2066
- const output = decodeOutput(stdout).trim();
2067
- const lines = output.split("\n");
2068
- const uniquePkgs = /* @__PURE__ */ new Set();
2069
- for (const line of lines) {
2070
- const name = line.trim();
2071
- if (name) {
2072
- uniquePkgs.add(name);
2073
- }
2074
- }
2075
- pkgs.push(...uniquePkgs);
2076
- }
2077
- } catch {
2078
- }
2079
- return pkgs;
2080
- }
2081
- async function removeDeb(packageName) {
2082
- console.log(pc15.cyan(`\u{1F4E6} \u6B63\u5728\u901A\u8FC7 apt \u5378\u8F7D DEB \u8F6F\u4EF6\u5305: ${packageName}...`));
2083
- const status = await spawnCommand("sudo", [
2084
- "apt-get",
2085
- "remove",
2086
- "-y",
2087
- packageName
2088
- ]);
2089
- if (status.success) {
2090
- console.log(pc15.green(`\u2714 \u8F6F\u4EF6\u5305 ${packageName} \u5DF2\u6210\u529F\u4ECE\u7CFB\u7EDF\u4E2D\u79FB\u9664\u3002`));
2091
- } else {
2092
- console.error(pc15.red(`\u274C \u5378\u8F7D\u5931\u8D25\uFF0C\u8FDB\u7A0B\u9000\u51FA\u7801: ${status.code}`));
2093
- }
2094
- }
2095
- async function removeRpm(packageName) {
2096
- console.log(pc15.cyan(`\u{1F4E6} \u6B63\u5728\u901A\u8FC7 dnf \u5378\u8F7D RPM \u8F6F\u4EF6\u5305: ${packageName}...`));
2097
- const status = await spawnCommand("sudo", [
2098
- "dnf",
2099
- "remove",
2100
- "-y",
2101
- packageName
2102
- ]);
2103
- if (status.success) {
2104
- console.log(pc15.green(`\u2714 \u8F6F\u4EF6\u5305 ${packageName} \u5DF2\u6210\u529F\u4ECE\u7CFB\u7EDF\u4E2D\u79FB\u9664\u3002`));
2105
- } else {
2106
- console.error(pc15.red(`\u274C \u5378\u8F7D\u5931\u8D25\uFF0C\u8FDB\u7A0B\u9000\u51FA\u7801: ${status.code}`));
2107
- }
2108
- }
2109
- async function removeSnap(packageName) {
2110
- console.log(pc15.cyan(`\u{1F4E6} \u6B63\u5728\u901A\u8FC7 snap \u5378\u8F7D\u8F6F\u4EF6\u5305: ${packageName}...`));
2111
- const status = await spawnCommand("sudo", ["snap", "remove", packageName]);
2112
- if (status.success) {
2113
- console.log(pc15.green(`\u2714 Snap \u8F6F\u4EF6\u5305 ${packageName} \u5DF2\u6210\u529F\u4ECE\u7CFB\u7EDF\u4E2D\u79FB\u9664\u3002`));
2114
- } else {
2115
- console.error(pc15.red(`\u274C \u5378\u8F7D\u5931\u8D25\uFF0C\u9000\u51FA\u7801: ${status.code}`));
2116
- }
2117
- }
2118
- async function uninstallFlatpak(packageName) {
2119
- if (!await isCommandAvailable("flatpak")) {
2120
- console.error(pc15.red("\u274C \u5F53\u524D\u7CFB\u7EDF\u4E2D\u672A\u68C0\u6D4B\u5230\u5DF2\u5B89\u88C5\u7684 flatpak \u5DE5\u5177\u3002"));
2121
- return;
2122
- }
2123
- console.log(pc15.cyan(`\u{1F4E6} \u6B63\u5728\u901A\u8FC7 flatpak \u5378\u8F7D\u5E94\u7528: ${packageName}...`));
2124
- const status = await spawnCommand("flatpak", [
2125
- "uninstall",
2126
- "-y",
2127
- packageName
2128
- ]);
2129
- if (status.success) {
2130
- const home = getHomeDir2();
2131
- const desktopPath = join7(
2132
- home,
2133
- ".local/share/applications",
2134
- `flatpak-${packageName}.desktop`
2135
- );
2136
- try {
2137
- await fs12.rm(desktopPath);
2138
- console.log(pc15.green(`\u2714 \u5DF2\u6E05\u9664 Flatpak \u5173\u8054\u684C\u9762\u5FEB\u6377\u56FE\u6807\u3002`));
2139
- } catch {
2140
- }
2141
- console.log(pc15.green("\u2728 Flatpak \u5E94\u7528\u53CA\u56FE\u6807\u6E05\u7406\u5B8C\u6210\uFF01"));
2142
- }
2143
- }
2144
- async function performRemoveGreenApp(greenPath, appName) {
2145
- const home = getHomeDir2();
2146
- const applicationsDir = join7(home, ".local/share/applications");
2147
- try {
2148
- for (const entry of await fs12.readdir(applicationsDir, {
2149
- withFileTypes: true
2150
- })) {
2151
- if (entry.isFile() && entry.name.endsWith(".desktop")) {
2152
- const filePath = join7(applicationsDir, entry.name);
2153
- const content = await fs12.readFile(filePath, "utf-8");
2154
- if (content.includes(greenPath) || content.includes(appName)) {
2155
- await fs12.rm(filePath);
2156
- console.log(pc15.green(`\u2714 \u5DF2\u6E05\u9664\u684C\u9762\u5FEB\u6377\u56FE\u6807: ${filePath}`));
2157
- }
2158
- }
1929
+ import pc16 from "picocolors";
1930
+ function registerUninstallCommand(program2) {
1931
+ program2.command("uninstall <package>").description("macOS \u672C\u5730\u5DE5\u5177\u5378\u8F7D\u5668\uFF08\u79FB\u9664\u5B89\u88C5\u76EE\u5F55\u548C\u7EC8\u7AEF\u547D\u4EE4\u5165\u53E3\uFF09").action(async (pkg) => {
1932
+ if (!ensureMacOS()) return;
1933
+ if (!pkg) {
1934
+ console.error(pc16.red("\u274C \u8BF7\u63D0\u4F9B\u8981\u5378\u8F7D\u7684\u5E94\u7528\u540D\u3002"));
1935
+ return;
2159
1936
  }
2160
- } catch {
2161
- }
2162
- try {
2163
- await fs12.rm(greenPath, { recursive: true });
2164
- console.log(pc15.green(`\u2714 \u5DF2\u6210\u529F\u6E05\u9664\u7EFF\u8272\u8F6F\u4EF6\u4E3B\u4F53: ${greenPath}`));
2165
- } catch (err) {
2166
- console.error(
2167
- pc15.red(`\u274C \u6E05\u9664\u8F6F\u4EF6\u4E3B\u4F53\u5931\u8D25:`),
2168
- err instanceof Error ? err.message : err
2169
- );
2170
- }
2171
- }
2172
- async function performFuzzySearchAndRecommendation(query) {
2173
- const hasSnap = await isCommandAvailable("snap");
2174
- const [greenCands, flatpakCands, snapCands] = await Promise.all([
2175
- searchGreenApps(query),
2176
- searchFlatpaks(query),
2177
- hasSnap ? (async () => {
2178
- const candidates = [];
2179
- try {
2180
- const { success, stdout } = await runCommand("snap", ["list"]);
2181
- if (success) {
2182
- const lines = decodeOutput(stdout).split("\n");
2183
- for (let i = 1; i < lines.length; i++) {
2184
- const name = lines[i].trim().split(/\s+/)[0];
2185
- if (name && name.toLowerCase().includes(query.toLowerCase())) {
2186
- candidates.push(name);
2187
- }
2188
- }
2189
- }
2190
- } catch {
2191
- }
2192
- return candidates;
2193
- })() : Promise.resolve([])
2194
- ]);
2195
- let systemCands = [];
2196
- try {
2197
- const osRelease = await fs12.readFile("/etc/os-release", "utf-8");
2198
- if (osRelease.includes("fedora") || osRelease.includes("rhel") || osRelease.includes("centos")) {
2199
- systemCands = await searchRpmPackages(query);
2200
- } else {
2201
- systemCands = await searchDebPackages(query);
1937
+ const removed = await removeInstalledApp(pkg);
1938
+ if (removed) {
1939
+ console.log(pc16.green("\u2728 \u5378\u8F7D\u5B8C\u6210\uFF01\u76F8\u5173\u7EC8\u7AEF\u547D\u4EE4\u5165\u53E3\u4E5F\u5DF2\u6E05\u7406\u3002"));
1940
+ return;
2202
1941
  }
2203
- } catch {
2204
- systemCands = await searchDebPackages(query);
2205
- }
2206
- const totalCands = greenCands.length + flatpakCands.length + snapCands.length + systemCands.length;
2207
- if (totalCands > 0) {
2208
- console.log(
2209
- pc15.cyan(
2210
- `\u{1F4A1} \u5E2E\u60A8\u5728\u7CFB\u7EDF\u4E2D\u641C\u5BFB\u5230\u4EE5\u4E0B ${totalCands} \u4E2A\u5305\u542B "${query}" \u7684\u76F8\u5173\u5339\u914D\u9879\uFF1A
2211
- `
2212
- )
1942
+ const candidates = (await listInstalledApps()).filter(
1943
+ (name) => name.toLowerCase().includes(pkg.toLowerCase())
2213
1944
  );
2214
- if (greenCands.length > 0) {
2215
- console.log(pc15.bold(pc15.green("\u{1F4C1} [\u7EFF\u8272\u5E94\u7528] \u5019\u9009\uFF1A")));
2216
- for (const cand of greenCands) {
2217
- console.log(
2218
- ` - ${cand} ${pc15.dim(`(\u5378\u8F7D\u547D\u4EE4: xx uninstall ${cand})`)}`
2219
- );
2220
- }
2221
- }
2222
- if (flatpakCands.length > 0) {
2223
- console.log(pc15.bold(pc15.magenta("\n\u{1F4E6} [Flatpak] \u5019\u9009\uFF1A")));
2224
- for (const cand of flatpakCands) {
1945
+ if (candidates.length > 0) {
1946
+ console.log(pc16.yellow("\u274C \u672A\u627E\u5230\u7CBE\u786E\u5339\u914D\u7684\u5DF2\u5B89\u88C5\u5E94\u7528\u3002"));
1947
+ console.log(pc16.cyan("\u4F60\u53EF\u80FD\u60F3\u5378\u8F7D\u4EE5\u4E0B\u9879\u76EE\uFF1A"));
1948
+ for (const candidate of candidates) {
2225
1949
  console.log(
2226
- ` - ${cand.id} [${cand.name}] ${pc15.dim(`(\u5378\u8F7D\u547D\u4EE4: xx uninstall ${cand.id})`)}`
1950
+ ` - ${candidate} ${pc16.dim(`(xx uninstall ${candidate})`)}`
2227
1951
  );
2228
1952
  }
2229
- }
2230
- if (snapCands.length > 0) {
2231
- console.log(pc15.bold(pc15.yellow("\n\u26A1 [Snap] \u5019\u9009\uFF1A")));
2232
- for (const cand of snapCands) {
2233
- console.log(
2234
- ` - ${cand} ${pc15.dim(`(\u5378\u8F7D\u547D\u4EE4: xx uninstall ${cand})`)}`
2235
- );
2236
- }
2237
- }
2238
- if (systemCands.length > 0) {
2239
- console.log(pc15.bold(pc15.blue("\n\u2699 [\u7CFB\u7EDF\u6E90\u7EA7] \u5019\u9009\uFF1A")));
2240
- for (const cand of systemCands) {
2241
- console.log(
2242
- ` - ${cand} ${pc15.dim(`(\u5378\u8F7D\u547D\u4EE4: xx uninstall ${cand})`)}`
2243
- );
2244
- }
2245
- }
2246
- console.log(pc15.cyan(`
2247
- \u{1F3C1} \u641C\u5BFB\u5B8C\u6210\uFF01`));
2248
- }
2249
- }
2250
- async function parseUninstallTarget(target) {
2251
- const lower = target.toLowerCase();
2252
- const greenPath = await findGreenAppPath(target);
2253
- if (greenPath) {
2254
- return { type: "green", raw: target, greenPath };
2255
- }
2256
- const isFlatpak = !target.includes("/") && !target.includes("\\") && target.split(".").length >= 3;
2257
- if (isFlatpak) {
2258
- return { type: "flatpak", raw: target };
2259
- }
2260
- if (lower.endsWith(".deb")) {
2261
- const absPath = resolve11(process.cwd(), target);
2262
- try {
2263
- const stat = await fs12.stat(absPath);
2264
- if (stat.isFile()) {
2265
- const extractedPackageName = await extractDebPackageName(absPath);
2266
- return {
2267
- type: "deb",
2268
- raw: target,
2269
- resolvedPath: absPath,
2270
- extractedPackageName
2271
- };
2272
- }
2273
- } catch {
2274
- }
2275
- }
2276
- if (lower.endsWith(".rpm")) {
2277
- const absPath = resolve11(process.cwd(), target);
2278
- try {
2279
- const stat = await fs12.stat(absPath);
2280
- if (stat.isFile()) {
2281
- const extractedPackageName = await extractRpmPackageName(absPath);
2282
- return {
2283
- type: "rpm",
2284
- raw: target,
2285
- resolvedPath: absPath,
2286
- extractedPackageName
2287
- };
2288
- }
2289
- } catch {
2290
- }
2291
- }
2292
- if (await isSnapInstalled(target)) {
2293
- return { type: "snap", raw: target };
2294
- }
2295
- if (await isSystemPackageInstalled(target)) {
2296
- return { type: "system", raw: target };
2297
- }
2298
- return { type: "unknown", raw: target };
2299
- }
2300
- function registerUninstallCommand(program2) {
2301
- program2.command("uninstall <package>").description("\u901A\u7528\u5E94\u7528\u5378\u8F7D\u5668\uFF08\u652F\u6301\u5305\u540D\u3001Flatpak\u3001Snap\u3001\u672C\u5730\u5305\u6216\u7EFF\u8272\u8F6F\u4EF6\uFF09").action(async (pkg) => {
2302
- if (!pkg) {
2303
- console.error(
2304
- pc15.red("\u274C \u8BF7\u63D0\u4F9B\u8981\u5378\u8F7D\u7684\u8F6F\u4EF6\u5305\u540D\u79F0\u3001\u5B89\u88C5\u5305\u6216\u7EFF\u8272\u8F6F\u4EF6\u540D\u3002")
2305
- );
2306
- return;
2307
- }
2308
- try {
2309
- const parsed = await parseUninstallTarget(pkg);
2310
- switch (parsed.type) {
2311
- case "green":
2312
- await performRemoveGreenApp(parsed.greenPath, parsed.raw);
2313
- console.log(pc15.green("\u2728 \u7EFF\u8272\u5E94\u7528\u53CA\u684C\u9762\u5FEB\u6377\u65B9\u5F0F\u6E05\u7406\u5B8C\u6210\uFF01"));
2314
- break;
2315
- case "flatpak":
2316
- await uninstallFlatpak(parsed.raw);
2317
- break;
2318
- case "snap":
2319
- await removeSnap(parsed.raw);
2320
- break;
2321
- case "deb": {
2322
- const debPkgName = parsed.extractedPackageName || parsed.raw;
2323
- await removeDeb(debPkgName);
2324
- break;
2325
- }
2326
- case "rpm": {
2327
- const rpmPkgName = parsed.extractedPackageName || parsed.raw;
2328
- await removeRpm(rpmPkgName);
2329
- break;
2330
- }
2331
- case "system": {
2332
- const osRelease = await fs12.readFile("/etc/os-release", "utf-8");
2333
- if (osRelease.includes("fedora") || osRelease.includes("rhel") || osRelease.includes("centos")) {
2334
- await removeRpm(parsed.raw);
2335
- } else {
2336
- await removeDeb(parsed.raw);
2337
- }
2338
- break;
2339
- }
2340
- case "unknown":
2341
- await performFuzzySearchAndRecommendation(parsed.raw);
2342
- break;
2343
- default: {
2344
- const _exhaustiveCheck = parsed;
2345
- throw new Error(
2346
- `\u672A\u5904\u7406\u7684\u5378\u8F7D\u5206\u652F\u7C7B\u578B: ${JSON.stringify(_exhaustiveCheck)}`
2347
- );
2348
- }
2349
- }
2350
- } catch (err) {
1953
+ } else {
2351
1954
  console.error(
2352
- pc15.red("\u274C \u5378\u8F7D\u90E8\u7F72\u5931\u8D25:"),
2353
- err instanceof Error ? err.message : String(err)
1955
+ pc16.red(`\u274C \u672A\u627E\u5230\u5DF2\u5B89\u88C5\u5E94\u7528 '${pkg}'\u3002\u8BF7\u5148\u8FD0\u884C xx install \u5B89\u88C5\u3002`)
2354
1956
  );
2355
1957
  }
2356
1958
  });
@@ -2358,8 +1960,8 @@ function registerUninstallCommand(program2) {
2358
1960
 
2359
1961
  // commands/unzip.ts
2360
1962
  import fs13 from "fs/promises";
2361
- import pc16 from "picocolors";
2362
- import { join as join8, basename as basename6, extname, resolve as resolve12 } from "path";
1963
+ import pc17 from "picocolors";
1964
+ import { join as join8, basename as basename6, extname as extname2, resolve as resolve11 } from "path";
2363
1965
 
2364
1966
  // utils/archive.ts
2365
1967
  import AdmZip from "adm-zip";
@@ -2388,7 +1990,7 @@ async function uncompressTgz(src, destDir) {
2388
1990
  async function uncompressRar(src, dest) {
2389
1991
  const hasUnrar = isCommandAvailable("unrar");
2390
1992
  if (hasUnrar) {
2391
- console.log(pc16.cyan(`\u{1F4E6} \u6B63\u5728\u8C03\u7528\u7CFB\u7EDF unrar \u63D0\u53D6 RAR \u538B\u7F29\u5305...`));
1993
+ console.log(pc17.cyan(`\u{1F4E6} \u6B63\u5728\u8C03\u7528\u7CFB\u7EDF unrar \u63D0\u53D6 RAR \u538B\u7F29\u5305...`));
2392
1994
  const status = await spawnCommand("unrar", ["x", "-y", src, dest]);
2393
1995
  if (!status.success) {
2394
1996
  throw new Error(`unrar \u6267\u884C\u5931\u8D25\uFF0C\u8FDB\u7A0B\u9000\u51FA\u7801: ${status.code}`);
@@ -2397,7 +1999,7 @@ async function uncompressRar(src, dest) {
2397
1999
  }
2398
2000
  const hasRar = isCommandAvailable("rar");
2399
2001
  if (hasRar) {
2400
- console.log(pc16.cyan(`\u{1F4E6} \u6B63\u5728\u8C03\u7528\u7CFB\u7EDF rar \u63D0\u53D6 RAR \u538B\u7F29\u5305...`));
2002
+ console.log(pc17.cyan(`\u{1F4E6} \u6B63\u5728\u8C03\u7528\u7CFB\u7EDF rar \u63D0\u53D6 RAR \u538B\u7F29\u5305...`));
2401
2003
  const status = await spawnCommand("rar", ["x", "-y", src, dest]);
2402
2004
  if (!status.success) {
2403
2005
  throw new Error(`rar \u6267\u884C\u5931\u8D25\uFF0C\u8FDB\u7A0B\u9000\u51FA\u7801: ${status.code}`);
@@ -2418,20 +2020,20 @@ function registerUnzipCommand(program2) {
2418
2020
  "\u8BF7\u8F93\u5165\u8981\u89E3\u538B\u7684\u538B\u7F29\u5305\u6587\u4EF6\u8DEF\u5F84 (Enter compressed file path):"
2419
2021
  );
2420
2022
  if (!input) {
2421
- console.error(pc16.red("\u274C \u9519\u8BEF: \u672A\u6307\u5B9A\u6709\u6548\u7684\u538B\u7F29\u5305\u6587\u4EF6\u3002"));
2023
+ console.error(pc17.red("\u274C \u9519\u8BEF: \u672A\u6307\u5B9A\u6709\u6548\u7684\u538B\u7F29\u5305\u6587\u4EF6\u3002"));
2422
2024
  return;
2423
2025
  }
2424
2026
  srcFile = input.trim();
2425
2027
  }
2426
- const absSrcFile = resolve12(srcFile);
2028
+ const absSrcFile = resolve11(srcFile);
2427
2029
  try {
2428
2030
  const stat = await fs13.stat(absSrcFile);
2429
2031
  if (!stat.isFile()) {
2430
- console.error(pc16.red(`\u274C \u9519\u8BEF: '${srcFile}' \u4E0D\u662F\u4E00\u4E2A\u6709\u6548\u7684\u6587\u4EF6\u3002`));
2032
+ console.error(pc17.red(`\u274C \u9519\u8BEF: '${srcFile}' \u4E0D\u662F\u4E00\u4E2A\u6709\u6548\u7684\u6587\u4EF6\u3002`));
2431
2033
  return;
2432
2034
  }
2433
2035
  } catch {
2434
- console.error(pc16.red(`\u274C \u9519\u8BEF: \u627E\u4E0D\u5230\u6587\u4EF6 '${srcFile}'\u3002`));
2036
+ console.error(pc17.red(`\u274C \u9519\u8BEF: \u627E\u4E0D\u5230\u6587\u4EF6 '${srcFile}'\u3002`));
2435
2037
  return;
2436
2038
  }
2437
2039
  const lowerSrc = absSrcFile.toLowerCase();
@@ -2441,17 +2043,17 @@ function registerUnzipCommand(program2) {
2441
2043
  } else if (lowerSrc.endsWith(".tgz")) {
2442
2044
  folderName = basename6(absSrcFile, ".tgz");
2443
2045
  } else {
2444
- folderName = basename6(absSrcFile, extname(absSrcFile));
2046
+ folderName = basename6(absSrcFile, extname2(absSrcFile));
2445
2047
  }
2446
2048
  let destDir = options.dir;
2447
2049
  if (!destDir) {
2448
2050
  destDir = join8(process.cwd(), folderName);
2449
2051
  } else {
2450
- destDir = resolve12(process.cwd(), destDir);
2052
+ destDir = resolve11(process.cwd(), destDir);
2451
2053
  }
2452
2054
  try {
2453
- console.log(pc16.cyan(`\u{1F4E6} \u6B63\u5728\u51C6\u5907\u89E3\u538B: ${absSrcFile}...`));
2454
- console.log(pc16.cyan(`\u{1F4E5} \u76EE\u6807\u8F93\u51FA\u76EE\u5F55: ${destDir}`));
2055
+ console.log(pc17.cyan(`\u{1F4E6} \u6B63\u5728\u51C6\u5907\u89E3\u538B: ${absSrcFile}...`));
2056
+ console.log(pc17.cyan(`\u{1F4E5} \u76EE\u6807\u8F93\u51FA\u76EE\u5F55: ${destDir}`));
2455
2057
  await fs13.mkdir(destDir, { recursive: true });
2456
2058
  if (lowerSrc.endsWith(".tar.gz") || lowerSrc.endsWith(".tgz")) {
2457
2059
  await uncompressTgz(absSrcFile, destDir);
@@ -2463,16 +2065,16 @@ function registerUnzipCommand(program2) {
2463
2065
  await uncompressRar(absSrcFile, destDir);
2464
2066
  } else {
2465
2067
  console.log(
2466
- pc16.yellow(
2068
+ pc17.yellow(
2467
2069
  "\u26A0\uFE0F \u672A\u80FD\u8BC6\u522B\u7684\u538B\u7F29\u5305\u683C\u5F0F\u540E\u7F00\u3002\u5C06\u9ED8\u8BA4\u5C1D\u8BD5\u4F5C\u4E3A\u6807\u51C6 ZIP \u8FDB\u884C\u63D0\u53D6..."
2468
2070
  )
2469
2071
  );
2470
2072
  await uncompressZip(absSrcFile, destDir);
2471
2073
  }
2472
- console.log(pc16.green(`\u2728 \u63D0\u53D6\u6210\u529F\uFF01\u5DF2\u4FDD\u5B58\u5230: ${destDir}`));
2074
+ console.log(pc17.green(`\u2728 \u63D0\u53D6\u6210\u529F\uFF01\u5DF2\u4FDD\u5B58\u5230: ${destDir}`));
2473
2075
  } catch (error) {
2474
2076
  console.error(
2475
- pc16.red("\u274C \u63D0\u53D6\u5931\u8D25:"),
2077
+ pc17.red("\u274C \u63D0\u53D6\u5931\u8D25:"),
2476
2078
  error instanceof Error ? error.message : error
2477
2079
  );
2478
2080
  }
@@ -2480,39 +2082,41 @@ function registerUnzipCommand(program2) {
2480
2082
  }
2481
2083
 
2482
2084
  // commands/upgrade.ts
2483
- import pc17 from "picocolors";
2085
+ import pc18 from "picocolors";
2484
2086
  function registerUpgradeCommand(program2) {
2485
- program2.command("upgrade").description("\u68C0\u67E5\u5E76\u81EA\u52A8\u66F4\u65B0 xx \u547D\u4EE4\u884C\u5DE5\u5177\u81F3\u6700\u65B0\u7248\u672C").action(async () => {
2486
- console.log(pc17.cyan("\u{1F916} \u6B63\u5728\u4E3A\u60A8\u68C0\u67E5\u5E76\u66F4\u65B0 xx \u547D\u4EE4\u884C\u5DE5\u5177..."));
2487
- console.log(pc17.dim("\u6267\u884C\u547D\u4EE4: npm install -g @xx-in/tools@latest\n"));
2087
+ program2.command("upgrade").description("\u68C0\u67E5\u5E76\u81EA\u52A8\u66F4\u65B0 xx \u547D\u4EE4\u884C\u5DE5\u5177\u81F3\u6700\u65B0\u7248\u672C").option("-r, --registry", "\u5F3A\u5236\u4F7F\u7528 npm \u5B98\u65B9\u6E90 https://registry.npmjs.org/").action(async (options) => {
2088
+ const args = ["install", "-g"];
2089
+ if (options.registry) {
2090
+ args.push("--registry=https://registry.npmjs.org/");
2091
+ }
2092
+ args.push("@xx-in/tools@latest");
2093
+ console.log(pc18.cyan("\u{1F916} \u6B63\u5728\u4E3A\u60A8\u68C0\u67E5\u5E76\u66F4\u65B0 xx \u547D\u4EE4\u884C\u5DE5\u5177..."));
2094
+ console.log(pc18.dim(`\u6267\u884C\u547D\u4EE4: npm ${args.join(" ")}
2095
+ `));
2488
2096
  try {
2489
- const status = await spawnCommand("npm", [
2490
- "install",
2491
- "-g",
2492
- "@xx-in/tools@latest"
2493
- ]);
2097
+ const status = await spawnCommand("npm", args);
2494
2098
  if (status.success) {
2495
2099
  console.log(
2496
- pc17.cyan("\n\u{1F916} \u6B63\u5728\u4E3A\u60A8\u5F3A\u5236\u8986\u76D6\u5E76\u5237\u65B0\u7EC8\u7AEF\u81EA\u52A8\u8865\u5168\u811A\u672C...")
2100
+ pc18.cyan("\n\u{1F916} \u6B63\u5728\u4E3A\u60A8\u5F3A\u5236\u8986\u76D6\u5E76\u5237\u65B0\u7EC8\u7AEF\u81EA\u52A8\u8865\u5168\u811A\u672C...")
2497
2101
  );
2498
2102
  await autoInstallCompletion();
2499
2103
  console.log(
2500
- pc17.green("\n\u2728 xx \u81EA\u52A8\u66F4\u65B0\u5E76\u91CD\u5237\u8865\u5168\u6210\u529F\uFF01\u5DF2\u6210\u529F\u52A0\u8F7D\u6700\u65B0\u7248\u672C\u3002")
2104
+ pc18.green("\n\u2728 xx \u81EA\u52A8\u66F4\u65B0\u5E76\u91CD\u5237\u8865\u5168\u6210\u529F\uFF01\u5DF2\u6210\u529F\u52A0\u8F7D\u6700\u65B0\u7248\u672C\u3002")
2501
2105
  );
2502
2106
  } else {
2503
2107
  console.error(
2504
- pc17.red(`
2108
+ pc18.red(`
2505
2109
  \u274C \u66F4\u65B0\u5931\u8D25\uFF0C\u9000\u51FA\u4EE3\u7801 (Exit Code): ${status.code}`)
2506
2110
  );
2507
2111
  }
2508
2112
  } catch (err) {
2509
2113
  console.error(
2510
- pc17.red(
2114
+ pc18.red(
2511
2115
  "\n\u274C \u65E0\u6CD5\u6267\u884C\u66F4\u65B0\u547D\u4EE4\uFF0C\u8BF7\u786E\u8BA4\u7CFB\u7EDF\u73AF\u5883\u53D8\u91CF\u4E2D\u662F\u5426\u5DF2\u6B63\u786E\u914D\u7F6E Node.js \u4E0E npm\u3002"
2512
2116
  )
2513
2117
  );
2514
2118
  if (err instanceof Error) {
2515
- console.error(pc17.red("\u9519\u8BEF\u8BE6\u60C5:"), err.message);
2119
+ console.error(pc18.red("\u9519\u8BEF\u8BE6\u60C5:"), err.message);
2516
2120
  }
2517
2121
  }
2518
2122
  });
@@ -2521,8 +2125,8 @@ function registerUpgradeCommand(program2) {
2521
2125
  // commands/zip.ts
2522
2126
  import fs14 from "fs/promises";
2523
2127
  import os2 from "os";
2524
- import pc18 from "picocolors";
2525
- import { join as join9, basename as basename7, relative as relative2, resolve as resolve13 } from "path";
2128
+ import pc19 from "picocolors";
2129
+ import { join as join9, basename as basename7, relative as relative2, resolve as resolve12 } from "path";
2526
2130
  var IGNORE_FILE_NAME = ".cpzipignore";
2527
2131
  var DEFAULT_BLACKLIST = [
2528
2132
  "# cpzip \u5FFD\u7565\u914D\u7F6E\u6587\u4EF6",
@@ -2541,20 +2145,20 @@ async function getBlacklist(absSrcDir) {
2541
2145
  const cwdIgnorePath = join9(process.cwd(), IGNORE_FILE_NAME);
2542
2146
  try {
2543
2147
  const content = await fs14.readFile(targetIgnorePath, "utf-8");
2544
- console.log(pc18.cyan(`[zip] \u627E\u5230\u76EE\u6807\u76EE\u5F55\u4E0B\u7684\u5FFD\u7565\u6587\u4EF6: ${targetIgnorePath}`));
2148
+ console.log(pc19.cyan(`[zip] \u627E\u5230\u76EE\u6807\u76EE\u5F55\u4E0B\u7684\u5FFD\u7565\u6587\u4EF6: ${targetIgnorePath}`));
2545
2149
  return parseIgnoreContent(content);
2546
2150
  } catch {
2547
2151
  }
2548
2152
  try {
2549
2153
  const content = await fs14.readFile(cwdIgnorePath, "utf-8");
2550
- console.log(pc18.cyan(`[zip] \u627E\u5230\u5F53\u524D\u76EE\u5F55\u4E0B\u7684\u5FFD\u7565\u6587\u4EF6: ${cwdIgnorePath}`));
2154
+ console.log(pc19.cyan(`[zip] \u627E\u5230\u5F53\u524D\u76EE\u5F55\u4E0B\u7684\u5FFD\u7565\u6587\u4EF6: ${cwdIgnorePath}`));
2551
2155
  return parseIgnoreContent(content);
2552
2156
  } catch (err) {
2553
2157
  if (isNotFoundError(err)) {
2554
- console.log(pc18.dim(`[zip] \u672A\u627E\u5230\u5FFD\u7565\u6587\u4EF6\uFF0C\u5C06\u4F7F\u7528\u5185\u7F6E\u9ED8\u8BA4\u8FC7\u6EE4\u89C4\u5219\u3002`));
2158
+ console.log(pc19.dim(`[zip] \u672A\u627E\u5230\u5FFD\u7565\u6587\u4EF6\uFF0C\u5C06\u4F7F\u7528\u5185\u7F6E\u9ED8\u8BA4\u8FC7\u6EE4\u89C4\u5219\u3002`));
2555
2159
  return parseIgnoreContent(DEFAULT_BLACKLIST.join("\n"));
2556
2160
  }
2557
- console.error(pc18.red(`[zip] \u8BFB\u53D6\u5FFD\u7565\u6587\u4EF6\u5931\u8D25\uFF0C\u5C06\u4F7F\u7528\u5185\u7F6E\u9ED8\u8BA4\u89C4\u5219\u3002`), err);
2161
+ console.error(pc19.red(`[zip] \u8BFB\u53D6\u5FFD\u7565\u6587\u4EF6\u5931\u8D25\uFF0C\u5C06\u4F7F\u7528\u5185\u7F6E\u9ED8\u8BA4\u89C4\u5219\u3002`), err);
2558
2162
  return parseIgnoreContent(DEFAULT_BLACKLIST.join("\n"));
2559
2163
  }
2560
2164
  }
@@ -2603,20 +2207,20 @@ function registerZipCommand(program2) {
2603
2207
  if (!srcDir) {
2604
2208
  const input = prompt("\u8BF7\u8F93\u5165\u8981\u6253\u5305\u7684\u76EE\u5F55\u8DEF\u5F84 (Enter directory path):");
2605
2209
  if (!input) {
2606
- console.error(pc18.red("\u274C \u9519\u8BEF: \u672A\u6307\u5B9A\u6709\u6548\u7684\u8F93\u5165\u76EE\u5F55\u3002"));
2210
+ console.error(pc19.red("\u274C \u9519\u8BEF: \u672A\u6307\u5B9A\u6709\u6548\u7684\u8F93\u5165\u76EE\u5F55\u3002"));
2607
2211
  return;
2608
2212
  }
2609
2213
  srcDir = input.trim();
2610
2214
  }
2611
- const absSrcDir = resolve13(srcDir);
2215
+ const absSrcDir = resolve12(srcDir);
2612
2216
  try {
2613
2217
  const stat = await fs14.stat(absSrcDir);
2614
2218
  if (!stat.isDirectory()) {
2615
- console.error(pc18.red(`\u274C \u9519\u8BEF: '${srcDir}' \u4E0D\u662F\u4E00\u4E2A\u6709\u6548\u7684\u76EE\u5F55\u3002`));
2219
+ console.error(pc19.red(`\u274C \u9519\u8BEF: '${srcDir}' \u4E0D\u662F\u4E00\u4E2A\u6709\u6548\u7684\u76EE\u5F55\u3002`));
2616
2220
  return;
2617
2221
  }
2618
2222
  } catch {
2619
- console.error(pc18.red(`\u274C \u9519\u8BEF: \u627E\u4E0D\u5230\u76EE\u5F55 '${srcDir}'\u3002`));
2223
+ console.error(pc19.red(`\u274C \u9519\u8BEF: \u627E\u4E0D\u5230\u76EE\u5F55 '${srcDir}'\u3002`));
2620
2224
  return;
2621
2225
  }
2622
2226
  const dirName = basename7(absSrcDir);
@@ -2625,13 +2229,13 @@ function registerZipCommand(program2) {
2625
2229
  const tempDir = await fs14.mkdtemp(join9(os2.tmpdir(), "cpzip_temp_"));
2626
2230
  const tempCopyTarget = join9(tempDir, dirName);
2627
2231
  try {
2628
- console.log(pc18.cyan(`\u{1F4E6} \u6B63\u5728\u590D\u5236\u76EE\u5F55\u5E76\u8FC7\u6EE4\u5FFD\u7565\u9879...`));
2232
+ console.log(pc19.cyan(`\u{1F4E6} \u6B63\u5728\u590D\u5236\u76EE\u5F55\u5E76\u8FC7\u6EE4\u5FFD\u7565\u9879...`));
2629
2233
  await copyRecursive3(absSrcDir, tempCopyTarget, absSrcDir, blacklist);
2630
- console.log(pc18.cyan(`\u26A1 \u6B63\u5728\u6253\u5305\u4E3A ZIP \u538B\u7F29\u5305...`));
2234
+ console.log(pc19.cyan(`\u26A1 \u6B63\u5728\u6253\u5305\u4E3A ZIP \u538B\u7F29\u5305...`));
2631
2235
  await compressZip(tempCopyTarget, outputZip);
2632
- console.log(pc18.green(`\u2728 \u6253\u5305\u6210\u529F\uFF01\u538B\u7F29\u5305\u4FDD\u5B58\u4E3A: ${outputZip}`));
2236
+ console.log(pc19.green(`\u2728 \u6253\u5305\u6210\u529F\uFF01\u538B\u7F29\u5305\u4FDD\u5B58\u4E3A: ${outputZip}`));
2633
2237
  } catch (error) {
2634
- console.error(pc18.red("\u274C \u6253\u5305\u5931\u8D25:"), error);
2238
+ console.error(pc19.red("\u274C \u6253\u5305\u5931\u8D25:"), error);
2635
2239
  } finally {
2636
2240
  try {
2637
2241
  await fs14.rm(tempDir, { recursive: true });