@lark-apaas/fullstack-cli 1.1.45-alpha.2 → 1.1.45-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // src/index.ts
2
- import fs27 from "fs";
3
- import path23 from "path";
2
+ import fs29 from "fs";
3
+ import path25 from "path";
4
4
  import { fileURLToPath as fileURLToPath5 } from "url";
5
5
  import { config as dotenvConfig } from "dotenv";
6
6
 
@@ -2365,21 +2365,43 @@ var genDbSchemaCommand = {
2365
2365
  };
2366
2366
 
2367
2367
  // src/commands/sync/run.handler.ts
2368
- import path5 from "path";
2369
- import fs7 from "fs";
2368
+ import path6 from "path";
2369
+ import fs8 from "fs";
2370
2370
  import { fileURLToPath as fileURLToPath3 } from "url";
2371
2371
 
2372
2372
  // src/config/sync.ts
2373
2373
  var syncConfig = {
2374
2374
  // 派生规则
2375
2375
  sync: [
2376
- // 1. 派生 scripts 目录(总是覆盖)
2376
+ // 1. 派生 scripts 目录(总是覆盖;递归同步,包含 scripts/hooks/run-precommit.js)
2377
2377
  {
2378
2378
  from: "templates/scripts",
2379
2379
  to: "scripts",
2380
2380
  type: "directory",
2381
2381
  overwrite: true
2382
2382
  },
2383
+ // 1a. 同步 .husky 目录(hook 入口,可执行 sh 脚本)
2384
+ {
2385
+ from: "templates/.husky",
2386
+ to: ".husky",
2387
+ type: "directory",
2388
+ overwrite: true
2389
+ },
2390
+ // 1b. scripts.prepare:npm install 后自动激活 git hooks(不依赖 husky 库)
2391
+ // 直接写 core.hooksPath,并保底给 pre-commit 加执行位;非 git 仓库下静默退出
2392
+ {
2393
+ type: "add-script",
2394
+ name: "prepare",
2395
+ command: "chmod +x .husky/pre-commit 2>/dev/null; git config core.hooksPath .husky 2>/dev/null || true",
2396
+ overwrite: false
2397
+ },
2398
+ // 1c. scripts.precommit = pre-commit 真正的执行体(npm run lint + read-logs ×5)
2399
+ {
2400
+ type: "add-script",
2401
+ name: "precommit",
2402
+ command: "node scripts/hooks/run-precommit.js",
2403
+ overwrite: false
2404
+ },
2383
2405
  // 2. 智能合并 nest-cli.json 配置(保留用户自定义的 assets、plugins 等)
2384
2406
  {
2385
2407
  from: "templates/nest-cli.json",
@@ -2602,18 +2624,58 @@ function cleanupPackageJson(cwd = process.cwd()) {
2602
2624
  }
2603
2625
  }
2604
2626
 
2627
+ // src/commands/sync/install-husky.ts
2628
+ import fs7 from "fs";
2629
+ import path5 from "path";
2630
+ import { spawnSync as spawnSync2 } from "child_process";
2631
+ function activateGitHooks(userProjectRoot) {
2632
+ if (!fs7.existsSync(path5.join(userProjectRoot, ".git"))) {
2633
+ return { action: "skipped-no-git" };
2634
+ }
2635
+ const hookFile = path5.join(userProjectRoot, ".husky", "pre-commit");
2636
+ if (!fs7.existsSync(hookFile)) {
2637
+ return { action: "skipped-no-hook-file" };
2638
+ }
2639
+ let changed = false;
2640
+ const currentMode = fs7.statSync(hookFile).mode & 511;
2641
+ if ((currentMode & 73) !== 73) {
2642
+ fs7.chmodSync(hookFile, 493);
2643
+ changed = true;
2644
+ }
2645
+ const probe = spawnSync2("git", ["config", "--get", "core.hooksPath"], {
2646
+ cwd: userProjectRoot,
2647
+ stdio: ["ignore", "pipe", "ignore"]
2648
+ });
2649
+ const currentHooksPath = probe.stdout ? probe.stdout.toString().trim() : "";
2650
+ if (currentHooksPath !== ".husky") {
2651
+ const res = spawnSync2("git", ["config", "core.hooksPath", ".husky"], {
2652
+ cwd: userProjectRoot,
2653
+ stdio: ["ignore", "inherit", "inherit"]
2654
+ });
2655
+ if (res.status !== 0) {
2656
+ throw new Error(`git config core.hooksPath exited with ${String(res.status)}`);
2657
+ }
2658
+ changed = true;
2659
+ }
2660
+ if (changed) {
2661
+ console.log("[fullstack-cli] \u2713 git hooks activated (core.hooksPath -> .husky)");
2662
+ return { action: "activated" };
2663
+ }
2664
+ return { action: "already-active" };
2665
+ }
2666
+
2605
2667
  // src/commands/sync/run.handler.ts
2606
2668
  async function run2(options) {
2607
2669
  const userProjectRoot = process.env.INIT_CWD || process.cwd();
2608
2670
  const __filename = fileURLToPath3(import.meta.url);
2609
- const __dirname2 = path5.dirname(__filename);
2610
- const pluginRoot = path5.resolve(__dirname2, "..");
2671
+ const __dirname2 = path6.dirname(__filename);
2672
+ const pluginRoot = path6.resolve(__dirname2, "..");
2611
2673
  if (userProjectRoot === pluginRoot) {
2612
2674
  console.log("[fullstack-cli] Skip syncing (installing plugin itself)");
2613
2675
  process.exit(0);
2614
2676
  }
2615
- const userPackageJson = path5.join(userProjectRoot, "package.json");
2616
- if (!fs7.existsSync(userPackageJson)) {
2677
+ const userPackageJson = path6.join(userProjectRoot, "package.json");
2678
+ if (!fs8.existsSync(userPackageJson)) {
2617
2679
  console.log("[fullstack-cli] Skip syncing (not a valid npm project)");
2618
2680
  process.exit(0);
2619
2681
  }
@@ -2633,6 +2695,12 @@ async function run2(options) {
2633
2695
  if (config.permissions) {
2634
2696
  setPermissions(config.permissions, userProjectRoot);
2635
2697
  }
2698
+ try {
2699
+ activateGitHooks(userProjectRoot);
2700
+ } catch (error) {
2701
+ const message = error instanceof Error ? error.message : String(error);
2702
+ console.warn(`[fullstack-cli] \u26A0 Failed to activate git hooks: ${message}`);
2703
+ }
2636
2704
  console.log("[fullstack-cli] Sync completed successfully \u2705");
2637
2705
  } catch (error) {
2638
2706
  const message = error instanceof Error ? error.message : String(error);
@@ -2665,7 +2733,7 @@ function patchUserPackageJson(userProjectRoot) {
2665
2733
  }
2666
2734
  async function syncRule(rule, pluginRoot, userProjectRoot) {
2667
2735
  if (rule.type === "delete-file" || rule.type === "delete-directory") {
2668
- const destPath2 = path5.join(userProjectRoot, rule.to);
2736
+ const destPath2 = path6.join(userProjectRoot, rule.to);
2669
2737
  if (rule.type === "delete-file") {
2670
2738
  deleteFile(destPath2);
2671
2739
  } else {
@@ -2674,32 +2742,32 @@ async function syncRule(rule, pluginRoot, userProjectRoot) {
2674
2742
  return;
2675
2743
  }
2676
2744
  if (rule.type === "remove-line") {
2677
- const destPath2 = path5.join(userProjectRoot, rule.to);
2745
+ const destPath2 = path6.join(userProjectRoot, rule.to);
2678
2746
  removeLineFromFile(destPath2, rule.pattern);
2679
2747
  return;
2680
2748
  }
2681
2749
  if (rule.type === "add-script") {
2682
- const packageJsonPath = path5.join(userProjectRoot, "package.json");
2750
+ const packageJsonPath = path6.join(userProjectRoot, "package.json");
2683
2751
  addScript(packageJsonPath, rule.name, rule.command, rule.overwrite ?? false);
2684
2752
  return;
2685
2753
  }
2686
2754
  if (rule.type === "add-line") {
2687
- const destPath2 = path5.join(userProjectRoot, rule.to);
2755
+ const destPath2 = path6.join(userProjectRoot, rule.to);
2688
2756
  addLineToFile(destPath2, rule.line);
2689
2757
  return;
2690
2758
  }
2691
2759
  if (rule.type === "merge-json") {
2692
- const srcPath2 = path5.join(pluginRoot, rule.from);
2693
- const destPath2 = path5.join(userProjectRoot, rule.to);
2760
+ const srcPath2 = path6.join(pluginRoot, rule.from);
2761
+ const destPath2 = path6.join(userProjectRoot, rule.to);
2694
2762
  mergeJsonFile(srcPath2, destPath2, rule.arrayMerge);
2695
2763
  return;
2696
2764
  }
2697
2765
  if (!("from" in rule)) {
2698
2766
  return;
2699
2767
  }
2700
- const srcPath = path5.join(pluginRoot, rule.from);
2701
- const destPath = path5.join(userProjectRoot, rule.to);
2702
- if (!fs7.existsSync(srcPath)) {
2768
+ const srcPath = path6.join(pluginRoot, rule.from);
2769
+ const destPath = path6.join(userProjectRoot, rule.to);
2770
+ if (!fs8.existsSync(srcPath)) {
2703
2771
  console.warn(`[fullstack-cli] Source not found: ${rule.from}`);
2704
2772
  return;
2705
2773
  }
@@ -2716,68 +2784,68 @@ async function syncRule(rule, pluginRoot, userProjectRoot) {
2716
2784
  }
2717
2785
  }
2718
2786
  function syncFile(src, dest, overwrite = true, onlyIfExists = false) {
2719
- if (onlyIfExists && !fs7.existsSync(dest)) {
2720
- console.log(`[fullstack-cli] \u25CB ${path5.basename(dest)} (skipped, target not exists)`);
2787
+ if (onlyIfExists && !fs8.existsSync(dest)) {
2788
+ console.log(`[fullstack-cli] \u25CB ${path6.basename(dest)} (skipped, target not exists)`);
2721
2789
  return;
2722
2790
  }
2723
- const destDir = path5.dirname(dest);
2724
- if (!fs7.existsSync(destDir)) {
2725
- fs7.mkdirSync(destDir, { recursive: true });
2791
+ const destDir = path6.dirname(dest);
2792
+ if (!fs8.existsSync(destDir)) {
2793
+ fs8.mkdirSync(destDir, { recursive: true });
2726
2794
  }
2727
- if (fs7.existsSync(dest) && !overwrite) {
2728
- console.log(`[fullstack-cli] \u25CB ${path5.basename(dest)} (skipped, already exists)`);
2795
+ if (fs8.existsSync(dest) && !overwrite) {
2796
+ console.log(`[fullstack-cli] \u25CB ${path6.basename(dest)} (skipped, already exists)`);
2729
2797
  return;
2730
2798
  }
2731
- fs7.copyFileSync(src, dest);
2732
- console.log(`[fullstack-cli] \u2713 ${path5.basename(dest)}`);
2799
+ fs8.copyFileSync(src, dest);
2800
+ console.log(`[fullstack-cli] \u2713 ${path6.basename(dest)}`);
2733
2801
  }
2734
2802
  function syncDirectory(src, dest, overwrite = true) {
2735
- if (!fs7.existsSync(dest)) {
2736
- fs7.mkdirSync(dest, { recursive: true });
2803
+ if (!fs8.existsSync(dest)) {
2804
+ fs8.mkdirSync(dest, { recursive: true });
2737
2805
  }
2738
- const files = fs7.readdirSync(src);
2806
+ const files = fs8.readdirSync(src);
2739
2807
  let count = 0;
2740
2808
  files.forEach((file) => {
2741
- const srcFile = path5.join(src, file);
2742
- const destFile = path5.join(dest, file);
2743
- const stats = fs7.statSync(srcFile);
2809
+ const srcFile = path6.join(src, file);
2810
+ const destFile = path6.join(dest, file);
2811
+ const stats = fs8.statSync(srcFile);
2744
2812
  if (stats.isDirectory()) {
2745
2813
  syncDirectory(srcFile, destFile, overwrite);
2746
2814
  } else {
2747
- if (overwrite || !fs7.existsSync(destFile)) {
2748
- fs7.copyFileSync(srcFile, destFile);
2749
- console.log(`[fullstack-cli] \u2713 ${path5.relative(dest, destFile)}`);
2815
+ if (overwrite || !fs8.existsSync(destFile)) {
2816
+ fs8.copyFileSync(srcFile, destFile);
2817
+ console.log(`[fullstack-cli] \u2713 ${path6.relative(dest, destFile)}`);
2750
2818
  count++;
2751
2819
  }
2752
2820
  }
2753
2821
  });
2754
2822
  if (count > 0) {
2755
- console.log(`[fullstack-cli] Synced ${count} files to ${path5.basename(dest)}/`);
2823
+ console.log(`[fullstack-cli] Synced ${count} files to ${path6.basename(dest)}/`);
2756
2824
  }
2757
2825
  }
2758
2826
  function appendToFile(src, dest) {
2759
- const content = fs7.readFileSync(src, "utf-8");
2827
+ const content = fs8.readFileSync(src, "utf-8");
2760
2828
  let existingContent = "";
2761
- if (fs7.existsSync(dest)) {
2762
- existingContent = fs7.readFileSync(dest, "utf-8");
2829
+ if (fs8.existsSync(dest)) {
2830
+ existingContent = fs8.readFileSync(dest, "utf-8");
2763
2831
  }
2764
2832
  if (existingContent.includes(content.trim())) {
2765
- console.log(`[fullstack-cli] \u25CB ${path5.basename(dest)} (already contains content)`);
2833
+ console.log(`[fullstack-cli] \u25CB ${path6.basename(dest)} (already contains content)`);
2766
2834
  return;
2767
2835
  }
2768
- fs7.appendFileSync(dest, content);
2769
- console.log(`[fullstack-cli] \u2713 ${path5.basename(dest)} (appended)`);
2836
+ fs8.appendFileSync(dest, content);
2837
+ console.log(`[fullstack-cli] \u2713 ${path6.basename(dest)} (appended)`);
2770
2838
  }
2771
2839
  function setPermissions(permissions, projectRoot) {
2772
2840
  for (const [pattern, mode] of Object.entries(permissions)) {
2773
2841
  if (pattern === "**/*.sh") {
2774
- const scriptsDir = path5.join(projectRoot, "scripts");
2775
- if (fs7.existsSync(scriptsDir)) {
2776
- const files = fs7.readdirSync(scriptsDir);
2842
+ const scriptsDir = path6.join(projectRoot, "scripts");
2843
+ if (fs8.existsSync(scriptsDir)) {
2844
+ const files = fs8.readdirSync(scriptsDir);
2777
2845
  files.forEach((file) => {
2778
2846
  if (file.endsWith(".sh")) {
2779
- const filePath = path5.join(scriptsDir, file);
2780
- fs7.chmodSync(filePath, mode);
2847
+ const filePath = path6.join(scriptsDir, file);
2848
+ fs8.chmodSync(filePath, mode);
2781
2849
  }
2782
2850
  });
2783
2851
  }
@@ -2785,27 +2853,27 @@ function setPermissions(permissions, projectRoot) {
2785
2853
  }
2786
2854
  }
2787
2855
  function deleteFile(filePath) {
2788
- if (fs7.existsSync(filePath)) {
2789
- fs7.unlinkSync(filePath);
2790
- console.log(`[fullstack-cli] \u2713 ${path5.basename(filePath)} (deleted)`);
2856
+ if (fs8.existsSync(filePath)) {
2857
+ fs8.unlinkSync(filePath);
2858
+ console.log(`[fullstack-cli] \u2713 ${path6.basename(filePath)} (deleted)`);
2791
2859
  } else {
2792
- console.log(`[fullstack-cli] \u25CB ${path5.basename(filePath)} (not found)`);
2860
+ console.log(`[fullstack-cli] \u25CB ${path6.basename(filePath)} (not found)`);
2793
2861
  }
2794
2862
  }
2795
2863
  function deleteDirectory(dirPath) {
2796
- if (fs7.existsSync(dirPath)) {
2797
- fs7.rmSync(dirPath, { recursive: true });
2798
- console.log(`[fullstack-cli] \u2713 ${path5.basename(dirPath)} (deleted)`);
2864
+ if (fs8.existsSync(dirPath)) {
2865
+ fs8.rmSync(dirPath, { recursive: true });
2866
+ console.log(`[fullstack-cli] \u2713 ${path6.basename(dirPath)} (deleted)`);
2799
2867
  } else {
2800
- console.log(`[fullstack-cli] \u25CB ${path5.basename(dirPath)} (not found)`);
2868
+ console.log(`[fullstack-cli] \u25CB ${path6.basename(dirPath)} (not found)`);
2801
2869
  }
2802
2870
  }
2803
2871
  function addScript(packageJsonPath, name, command, overwrite) {
2804
- if (!fs7.existsSync(packageJsonPath)) {
2872
+ if (!fs8.existsSync(packageJsonPath)) {
2805
2873
  console.log(`[fullstack-cli] \u25CB package.json (not found)`);
2806
2874
  return;
2807
2875
  }
2808
- const content = fs7.readFileSync(packageJsonPath, "utf-8");
2876
+ const content = fs8.readFileSync(packageJsonPath, "utf-8");
2809
2877
  const pkg2 = JSON.parse(content);
2810
2878
  if (!pkg2.scripts) {
2811
2879
  pkg2.scripts = {};
@@ -2817,42 +2885,42 @@ function addScript(packageJsonPath, name, command, overwrite) {
2817
2885
  }
2818
2886
  }
2819
2887
  pkg2.scripts[name] = command;
2820
- fs7.writeFileSync(packageJsonPath, JSON.stringify(pkg2, null, 2) + "\n");
2888
+ fs8.writeFileSync(packageJsonPath, JSON.stringify(pkg2, null, 2) + "\n");
2821
2889
  console.log(`[fullstack-cli] \u2713 scripts.${name}`);
2822
2890
  }
2823
2891
  function addLineToFile(filePath, line) {
2824
- const fileName = path5.basename(filePath);
2825
- if (!fs7.existsSync(filePath)) {
2892
+ const fileName = path6.basename(filePath);
2893
+ if (!fs8.existsSync(filePath)) {
2826
2894
  console.log(`[fullstack-cli] \u25CB ${fileName} (not found, skipped)`);
2827
2895
  return;
2828
2896
  }
2829
- const content = fs7.readFileSync(filePath, "utf-8");
2897
+ const content = fs8.readFileSync(filePath, "utf-8");
2830
2898
  const lines = content.split("\n").map((l) => l.trim());
2831
2899
  if (lines.includes(line)) {
2832
2900
  console.log(`[fullstack-cli] \u25CB ${fileName} (line already exists: ${line})`);
2833
2901
  return;
2834
2902
  }
2835
2903
  const appendContent = (content.endsWith("\n") ? "" : "\n") + line + "\n";
2836
- fs7.appendFileSync(filePath, appendContent);
2904
+ fs8.appendFileSync(filePath, appendContent);
2837
2905
  console.log(`[fullstack-cli] \u2713 ${fileName} (added: ${line})`);
2838
2906
  }
2839
2907
  function mergeJsonFile(src, dest, arrayMerge) {
2840
- const fileName = path5.basename(dest);
2841
- if (!fs7.existsSync(src)) {
2908
+ const fileName = path6.basename(dest);
2909
+ if (!fs8.existsSync(src)) {
2842
2910
  console.warn(`[fullstack-cli] Source not found: ${src}`);
2843
2911
  return;
2844
2912
  }
2845
- const templateContent = JSON.parse(fs7.readFileSync(src, "utf-8"));
2846
- if (!fs7.existsSync(dest)) {
2847
- const destDir = path5.dirname(dest);
2848
- if (!fs7.existsSync(destDir)) {
2849
- fs7.mkdirSync(destDir, { recursive: true });
2913
+ const templateContent = JSON.parse(fs8.readFileSync(src, "utf-8"));
2914
+ if (!fs8.existsSync(dest)) {
2915
+ const destDir = path6.dirname(dest);
2916
+ if (!fs8.existsSync(destDir)) {
2917
+ fs8.mkdirSync(destDir, { recursive: true });
2850
2918
  }
2851
- fs7.writeFileSync(dest, JSON.stringify(templateContent, null, 2) + "\n");
2919
+ fs8.writeFileSync(dest, JSON.stringify(templateContent, null, 2) + "\n");
2852
2920
  console.log(`[fullstack-cli] \u2713 ${fileName} (created)`);
2853
2921
  return;
2854
2922
  }
2855
- const userContent = JSON.parse(fs7.readFileSync(dest, "utf-8"));
2923
+ const userContent = JSON.parse(fs8.readFileSync(dest, "utf-8"));
2856
2924
  const merged = deepMergeJson(userContent, templateContent, arrayMerge ?? {});
2857
2925
  const userStr = JSON.stringify(userContent, null, 2);
2858
2926
  const mergedStr = JSON.stringify(merged, null, 2);
@@ -2860,7 +2928,7 @@ function mergeJsonFile(src, dest, arrayMerge) {
2860
2928
  console.log(`[fullstack-cli] \u25CB ${fileName} (already up to date)`);
2861
2929
  return;
2862
2930
  }
2863
- fs7.writeFileSync(dest, mergedStr + "\n");
2931
+ fs8.writeFileSync(dest, mergedStr + "\n");
2864
2932
  console.log(`[fullstack-cli] \u2713 ${fileName} (merged)`);
2865
2933
  }
2866
2934
 
@@ -2920,16 +2988,16 @@ async function reportCreateInstanceEvent(pluginKey, version) {
2920
2988
  }
2921
2989
 
2922
2990
  // src/utils/git.ts
2923
- import { execSync, spawnSync as spawnSync2 } from "child_process";
2924
- import fs8 from "fs";
2925
- import path6 from "path";
2991
+ import { execSync, spawnSync as spawnSync3 } from "child_process";
2992
+ import fs9 from "fs";
2993
+ import path7 from "path";
2926
2994
  function isGitRepository(cwd = process.cwd()) {
2927
2995
  try {
2928
- const gitDir = path6.join(cwd, ".git");
2929
- if (fs8.existsSync(gitDir)) {
2996
+ const gitDir = path7.join(cwd, ".git");
2997
+ if (fs9.existsSync(gitDir)) {
2930
2998
  return true;
2931
2999
  }
2932
- const result = spawnSync2("git", ["rev-parse", "--git-dir"], {
3000
+ const result = spawnSync3("git", ["rev-parse", "--git-dir"], {
2933
3001
  cwd,
2934
3002
  stdio: "pipe",
2935
3003
  encoding: "utf-8"
@@ -2955,11 +3023,11 @@ function getChangedFiles(cwd = process.cwd()) {
2955
3023
  function gitAddUpgradeFiles(cwd = process.cwd(), filesToStage) {
2956
3024
  const filteredFiles = [];
2957
3025
  for (const filePath of filesToStage) {
2958
- if (fs8.existsSync(path6.join(cwd, filePath))) {
3026
+ if (fs9.existsSync(path7.join(cwd, filePath))) {
2959
3027
  filteredFiles.push(filePath);
2960
3028
  continue;
2961
3029
  }
2962
- const tracked = spawnSync2("git", ["ls-files", "--error-unmatch", "--", filePath], {
3030
+ const tracked = spawnSync3("git", ["ls-files", "--error-unmatch", "--", filePath], {
2963
3031
  cwd,
2964
3032
  stdio: "pipe",
2965
3033
  encoding: "utf-8"
@@ -2971,7 +3039,7 @@ function gitAddUpgradeFiles(cwd = process.cwd(), filesToStage) {
2971
3039
  if (filteredFiles.length === 0) {
2972
3040
  return;
2973
3041
  }
2974
- const result = spawnSync2("git", ["add", "--", ...filteredFiles], {
3042
+ const result = spawnSync3("git", ["add", "--", ...filteredFiles], {
2975
3043
  cwd,
2976
3044
  stdio: "pipe",
2977
3045
  encoding: "utf-8"
@@ -2982,7 +3050,7 @@ function gitAddUpgradeFiles(cwd = process.cwd(), filesToStage) {
2982
3050
  }
2983
3051
  }
2984
3052
  function hasStagedChanges(cwd = process.cwd()) {
2985
- const result = spawnSync2("git", ["diff", "--cached", "--quiet"], {
3053
+ const result = spawnSync3("git", ["diff", "--cached", "--quiet"], {
2986
3054
  cwd,
2987
3055
  stdio: "pipe",
2988
3056
  encoding: "utf-8"
@@ -2997,7 +3065,7 @@ function hasStagedChanges(cwd = process.cwd()) {
2997
3065
  throw new Error(`Failed to check staged changes: ${errorMsg}`);
2998
3066
  }
2999
3067
  function gitCommit(message, cwd = process.cwd()) {
3000
- const result = spawnSync2("git", ["commit", "-m", message], {
3068
+ const result = spawnSync3("git", ["commit", "-m", message], {
3001
3069
  cwd,
3002
3070
  stdio: "pipe",
3003
3071
  encoding: "utf-8"
@@ -3040,15 +3108,15 @@ Auto-committed by fullstack-cli`;
3040
3108
  }
3041
3109
 
3042
3110
  // src/commands/upgrade/shared/utils.ts
3043
- import path7 from "path";
3044
- import fs9 from "fs";
3111
+ import path8 from "path";
3112
+ import fs10 from "fs";
3045
3113
  import { fileURLToPath as fileURLToPath4 } from "url";
3046
3114
  function getCliVersion() {
3047
3115
  try {
3048
3116
  const __filename = fileURLToPath4(import.meta.url);
3049
- const __dirname2 = path7.dirname(__filename);
3050
- const pkgPath = path7.resolve(__dirname2, "../../../package.json");
3051
- const pkgContent = fs9.readFileSync(pkgPath, "utf-8");
3117
+ const __dirname2 = path8.dirname(__filename);
3118
+ const pkgPath = path8.resolve(__dirname2, "../../../package.json");
3119
+ const pkgContent = fs10.readFileSync(pkgPath, "utf-8");
3052
3120
  const pkg2 = JSON.parse(pkgContent);
3053
3121
  return pkg2.version || "unknown";
3054
3122
  } catch {
@@ -3106,31 +3174,47 @@ async function run3(options = {}) {
3106
3174
  }
3107
3175
 
3108
3176
  // src/commands/upgrade/deps/run.handler.ts
3109
- import { spawnSync as spawnSync3 } from "child_process";
3110
- import fs10 from "fs";
3111
- import path8 from "path";
3177
+ import { spawnSync as spawnSync4 } from "child_process";
3178
+ import fs11 from "fs";
3179
+ import path9 from "path";
3112
3180
 
3113
3181
  // src/utils/grayscale/config.ts
3114
3182
  function getGrayscaleConfig(configJson) {
3115
3183
  if (!configJson) {
3116
3184
  return null;
3117
3185
  }
3186
+ let parsed;
3118
3187
  try {
3119
- const parsed = JSON.parse(configJson);
3120
- const config = parsed.config;
3121
- if (!config || !config.enabled) {
3188
+ parsed = JSON.parse(configJson);
3189
+ } catch {
3190
+ console.warn("[grayscale] Failed to parse grayscale config");
3191
+ return null;
3192
+ }
3193
+ if (parsed && parsed.target_versions && typeof parsed.target_versions === "object") {
3194
+ const entries = Object.entries(parsed.target_versions).filter(
3195
+ ([, v]) => typeof v === "string" && v.length > 0
3196
+ );
3197
+ if (entries.length === 0) {
3198
+ console.log("[grayscale] target_versions present but empty, skip");
3122
3199
  return null;
3123
3200
  }
3124
3201
  return {
3125
- config,
3126
- tenantId: parsed.tenant_id != null ? String(parsed.tenant_id) : void 0,
3127
- appId: parsed.app_id || void 0,
3128
- xTtEnv: parsed.x_tt_env || void 0
3202
+ kind: "resolved",
3203
+ targetVersions: new Map(entries),
3204
+ matchedChannel: typeof parsed.matched_channel === "string" ? parsed.matched_channel : void 0
3129
3205
  };
3130
- } catch {
3131
- console.warn("[grayscale] Failed to parse grayscale config");
3206
+ }
3207
+ const config = parsed?.config;
3208
+ if (!config || !config.enabled) {
3132
3209
  return null;
3133
3210
  }
3211
+ return {
3212
+ kind: "legacy",
3213
+ config,
3214
+ tenantId: parsed.tenant_id != null ? String(parsed.tenant_id) : void 0,
3215
+ appId: parsed.app_id || void 0,
3216
+ xTtEnv: parsed.x_tt_env || void 0
3217
+ };
3134
3218
  }
3135
3219
 
3136
3220
  // src/utils/grayscale/identity.ts
@@ -3218,6 +3302,19 @@ function resolveGrayscaleVersions(_cwd, configJson) {
3218
3302
  console.log("[grayscale] Config not available, skipping grayscale");
3219
3303
  return null;
3220
3304
  }
3305
+ if (result.kind === "resolved") {
3306
+ console.log(
3307
+ `[grayscale] Using server-resolved versions (matched channel: ${result.matchedChannel || "(stable)"})`
3308
+ );
3309
+ console.log(`[grayscale] Resolved ${result.targetVersions.size} package version(s):`);
3310
+ for (const [pkg2, ver] of result.targetVersions) {
3311
+ console.log(`[grayscale] ${pkg2} -> ${ver}`);
3312
+ }
3313
+ return result.targetVersions;
3314
+ }
3315
+ console.warn(
3316
+ "[grayscale] Received legacy payload (full TCC config). This path is deprecated; sandbox_console should be upgraded to server-side resolution."
3317
+ );
3221
3318
  const { config, tenantId: payloadTenantId, appId: payloadAppId, xTtEnv: payloadXTtEnv } = result;
3222
3319
  const envIdentity = readProjectIdentity();
3223
3320
  const identity = {
@@ -3298,7 +3395,7 @@ function upgradePackages(packages, version, cwd) {
3298
3395
  packages.forEach((pkg2) => {
3299
3396
  const target = `${pkg2}@${version}`;
3300
3397
  console.log(`[fullstack-cli] Installing ${target}...`);
3301
- const result = spawnSync3("npm", ["install", target], {
3398
+ const result = spawnSync4("npm", ["install", target], {
3302
3399
  cwd,
3303
3400
  stdio: "inherit"
3304
3401
  });
@@ -3310,7 +3407,7 @@ function upgradePackages(packages, version, cwd) {
3310
3407
  console.log("[fullstack-cli] Upgrading to latest compatible versions...");
3311
3408
  packages.forEach((pkg2) => {
3312
3409
  console.log(`[fullstack-cli] Updating ${pkg2}...`);
3313
- const result = spawnSync3("npm", ["update", pkg2], {
3410
+ const result = spawnSync4("npm", ["update", pkg2], {
3314
3411
  cwd,
3315
3412
  stdio: "inherit"
3316
3413
  });
@@ -3327,8 +3424,8 @@ function installGrayscaleVersions(packages, grayscaleVersions, cwd, dryRun, mode
3327
3424
  if (version) {
3328
3425
  let current = "";
3329
3426
  try {
3330
- const installedPkgPath = path8.join(cwd, "node_modules", pkg2, "package.json");
3331
- const installedPkg = JSON.parse(fs10.readFileSync(installedPkgPath, "utf-8"));
3427
+ const installedPkgPath = path9.join(cwd, "node_modules", pkg2, "package.json");
3428
+ const installedPkg = JSON.parse(fs11.readFileSync(installedPkgPath, "utf-8"));
3332
3429
  current = installedPkg.version || "";
3333
3430
  } catch (err) {
3334
3431
  const code = err?.code;
@@ -3371,7 +3468,7 @@ function installGrayscaleVersions(packages, grayscaleVersions, cwd, dryRun, mode
3371
3468
  }
3372
3469
  const targets = upgradePlan.map(({ pkg: pkg2, version }) => `${pkg2}@${version}`);
3373
3470
  console.log(`[fullstack-cli] Installing ${targets.join(" ")}...`);
3374
- const result = spawnSync3("npm", ["install", ...targets], {
3471
+ const result = spawnSync4("npm", ["install", ...targets], {
3375
3472
  cwd,
3376
3473
  stdio: "inherit"
3377
3474
  });
@@ -3444,6 +3541,111 @@ var depsCommand = {
3444
3541
  }
3445
3542
  };
3446
3543
 
3544
+ // src/commands/upgrade/global-deps/run.handler.ts
3545
+ import { spawnSync as spawnSync5 } from "child_process";
3546
+ import fs12 from "fs";
3547
+ import path10 from "path";
3548
+ var MANAGED_GLOBAL_CLIS = [
3549
+ "@lark-apaas/fullstack-cli",
3550
+ "@lark-apaas/miaoda-cli"
3551
+ ];
3552
+ function readGlobalInstalledVersion(pkg2) {
3553
+ const candidates = [];
3554
+ if (process.env.npm_config_prefix) candidates.push(process.env.npm_config_prefix);
3555
+ if (process.env.NPM_CONFIG_PREFIX) candidates.push(process.env.NPM_CONFIG_PREFIX);
3556
+ candidates.push("/usr");
3557
+ candidates.push("/usr/local");
3558
+ if (process.env.HOME) candidates.push(path10.join(process.env.HOME, ".npm-global"));
3559
+ const seen = /* @__PURE__ */ new Set();
3560
+ for (const prefix of candidates) {
3561
+ if (seen.has(prefix)) continue;
3562
+ seen.add(prefix);
3563
+ try {
3564
+ const pkgPath = path10.join(prefix, "lib", "node_modules", pkg2, "package.json");
3565
+ if (fs12.existsSync(pkgPath)) {
3566
+ const meta = JSON.parse(fs12.readFileSync(pkgPath, "utf-8"));
3567
+ if (meta && typeof meta.version === "string") return meta.version;
3568
+ }
3569
+ } catch (err) {
3570
+ console.warn(
3571
+ `[fullstack-cli] readGlobalInstalledVersion(${pkg2}) failed at prefix=${prefix}: ${err instanceof Error ? err.message : String(err)}`
3572
+ );
3573
+ }
3574
+ }
3575
+ return "";
3576
+ }
3577
+ function buildGlobalUpgradePlan(managed, resolvedVersions, readVersion) {
3578
+ const plan = [];
3579
+ for (const pkg2 of managed) {
3580
+ const target = resolvedVersions.get(pkg2);
3581
+ if (!target) {
3582
+ console.log(`[fullstack-cli] ${pkg2}: no target version in grayscale config, skip`);
3583
+ continue;
3584
+ }
3585
+ const current = readVersion(pkg2);
3586
+ if (current && current === target) {
3587
+ console.log(`[fullstack-cli] ${pkg2}@${target} (already installed, skip)`);
3588
+ continue;
3589
+ }
3590
+ plan.push({ pkg: pkg2, current, target });
3591
+ }
3592
+ return plan;
3593
+ }
3594
+ async function run5(options = {}) {
3595
+ console.log("[fullstack-cli] Starting global CLI upgrade...");
3596
+ if (!options.grayscaleConfig) {
3597
+ console.log("[fullstack-cli] No grayscale config, skip global upgrade");
3598
+ return;
3599
+ }
3600
+ const grayscaleVersions = resolveGrayscaleVersions("/", options.grayscaleConfig);
3601
+ if (!grayscaleVersions) {
3602
+ console.log("[fullstack-cli] Grayscale config not available, skip global upgrade");
3603
+ return;
3604
+ }
3605
+ const plan = buildGlobalUpgradePlan(MANAGED_GLOBAL_CLIS, grayscaleVersions, readGlobalInstalledVersion);
3606
+ if (plan.length === 0) {
3607
+ console.log("[fullstack-cli] No global CLI upgrade needed");
3608
+ return;
3609
+ }
3610
+ console.log(`[fullstack-cli] Global upgrade plan (${plan.length} package(s)):`);
3611
+ plan.forEach(({ pkg: pkg2, current, target }) => {
3612
+ console.log(` - ${pkg2} ${current || "(not installed)"} -> ${target}`);
3613
+ });
3614
+ if (options.dryRun) {
3615
+ console.log("[fullstack-cli] Dry run mode, skipping actual installation");
3616
+ return;
3617
+ }
3618
+ const targets = plan.map(({ pkg: pkg2, target }) => `${pkg2}@${target}`);
3619
+ const npmArgs = ["install", "-g", ...targets];
3620
+ if (options.registry) {
3621
+ npmArgs.push("--registry", options.registry);
3622
+ }
3623
+ console.log(`[fullstack-cli] Running: npm ${npmArgs.join(" ")}`);
3624
+ const result = spawnSync5("npm", npmArgs, { stdio: "inherit" });
3625
+ if (result.error || result.status !== 0) {
3626
+ console.warn(
3627
+ `[fullstack-cli] npm install -g failed: ${result.error?.message ?? `exit ${result.status}`}`
3628
+ );
3629
+ process.exit(1);
3630
+ }
3631
+ console.log("[fullstack-cli] \u2713 Global CLI upgrade completed");
3632
+ }
3633
+
3634
+ // src/commands/upgrade/global-deps/index.ts
3635
+ var globalDepsCommand = {
3636
+ name: "global-deps",
3637
+ description: "Upgrade global @lark-apaas CLIs (fullstack-cli, miaoda-cli) per grayscale config",
3638
+ register(parentCommand) {
3639
+ parentCommand.command(this.name).description(this.description).option("--grayscale-config <json>", "Grayscale config JSON (injected by sandbox_console)").option("--dry-run", "Show upgrade plan without executing").option(
3640
+ "--registry <url>",
3641
+ "npm registry URL (default: https://registry.npmmirror.com/)",
3642
+ "https://registry.npmmirror.com/"
3643
+ ).action(async (options) => {
3644
+ await run5(options);
3645
+ });
3646
+ }
3647
+ };
3648
+
3447
3649
  // src/commands/upgrade/index.ts
3448
3650
  var upgradeCommand = {
3449
3651
  name: "upgrade",
@@ -3453,13 +3655,14 @@ var upgradeCommand = {
3453
3655
  await run3(options);
3454
3656
  });
3455
3657
  depsCommand.register(upgradeCmd);
3658
+ globalDepsCommand.register(upgradeCmd);
3456
3659
  }
3457
3660
  };
3458
3661
 
3459
3662
  // src/commands/action-plugin/utils.ts
3460
- import fs11 from "fs";
3461
- import path9 from "path";
3462
- import { spawnSync as spawnSync4, execSync as execSync2 } from "child_process";
3663
+ import fs13 from "fs";
3664
+ import path11 from "path";
3665
+ import { spawnSync as spawnSync6, execSync as execSync2 } from "child_process";
3463
3666
  function parsePluginName(input) {
3464
3667
  const match = input.match(/^(@[^/]+\/[^@]+)(?:@(.+))?$/);
3465
3668
  if (!match) {
@@ -3476,18 +3679,18 @@ function getProjectRoot() {
3476
3679
  return process.cwd();
3477
3680
  }
3478
3681
  function getPackageJsonPath() {
3479
- return path9.join(getProjectRoot(), "package.json");
3682
+ return path11.join(getProjectRoot(), "package.json");
3480
3683
  }
3481
3684
  function getPluginPath(pluginName) {
3482
- return path9.join(getProjectRoot(), "node_modules", pluginName);
3685
+ return path11.join(getProjectRoot(), "node_modules", pluginName);
3483
3686
  }
3484
3687
  function readPackageJson2() {
3485
3688
  const pkgPath = getPackageJsonPath();
3486
- if (!fs11.existsSync(pkgPath)) {
3689
+ if (!fs13.existsSync(pkgPath)) {
3487
3690
  throw new Error("package.json not found in current directory");
3488
3691
  }
3489
3692
  try {
3490
- const content = fs11.readFileSync(pkgPath, "utf-8");
3693
+ const content = fs13.readFileSync(pkgPath, "utf-8");
3491
3694
  return JSON.parse(content);
3492
3695
  } catch {
3493
3696
  throw new Error("Failed to parse package.json");
@@ -3495,7 +3698,7 @@ function readPackageJson2() {
3495
3698
  }
3496
3699
  function writePackageJson2(pkg2) {
3497
3700
  const pkgPath = getPackageJsonPath();
3498
- fs11.writeFileSync(pkgPath, JSON.stringify(pkg2, null, 2) + "\n", "utf-8");
3701
+ fs13.writeFileSync(pkgPath, JSON.stringify(pkg2, null, 2) + "\n", "utf-8");
3499
3702
  }
3500
3703
  function readActionPlugins() {
3501
3704
  const pkg2 = readPackageJson2();
@@ -3516,7 +3719,7 @@ function getInstalledPluginVersion(pluginName) {
3516
3719
  }
3517
3720
  function npmInstall(tgzPath) {
3518
3721
  console.log(`[action-plugin] Running npm install ${tgzPath}...`);
3519
- const result = spawnSync4("npm", ["install", tgzPath, "--no-save", "--no-package-lock", "--ignore-scripts"], {
3722
+ const result = spawnSync6("npm", ["install", tgzPath, "--no-save", "--no-package-lock", "--ignore-scripts"], {
3520
3723
  cwd: getProjectRoot(),
3521
3724
  stdio: "inherit"
3522
3725
  });
@@ -3528,12 +3731,12 @@ function npmInstall(tgzPath) {
3528
3731
  }
3529
3732
  }
3530
3733
  function getPackageVersion(pluginName) {
3531
- const pkgJsonPath = path9.join(getPluginPath(pluginName), "package.json");
3532
- if (!fs11.existsSync(pkgJsonPath)) {
3734
+ const pkgJsonPath = path11.join(getPluginPath(pluginName), "package.json");
3735
+ if (!fs13.existsSync(pkgJsonPath)) {
3533
3736
  return null;
3534
3737
  }
3535
3738
  try {
3536
- const content = fs11.readFileSync(pkgJsonPath, "utf-8");
3739
+ const content = fs13.readFileSync(pkgJsonPath, "utf-8");
3537
3740
  const pkg2 = JSON.parse(content);
3538
3741
  return pkg2.version || null;
3539
3742
  } catch {
@@ -3541,49 +3744,49 @@ function getPackageVersion(pluginName) {
3541
3744
  }
3542
3745
  }
3543
3746
  function readPluginPackageJson(pluginPath) {
3544
- const pkgJsonPath = path9.join(pluginPath, "package.json");
3545
- if (!fs11.existsSync(pkgJsonPath)) {
3747
+ const pkgJsonPath = path11.join(pluginPath, "package.json");
3748
+ if (!fs13.existsSync(pkgJsonPath)) {
3546
3749
  return null;
3547
3750
  }
3548
3751
  try {
3549
- const content = fs11.readFileSync(pkgJsonPath, "utf-8");
3752
+ const content = fs13.readFileSync(pkgJsonPath, "utf-8");
3550
3753
  return JSON.parse(content);
3551
3754
  } catch {
3552
3755
  return null;
3553
3756
  }
3554
3757
  }
3555
3758
  function extractTgzToNodeModules(tgzPath, pluginName) {
3556
- const nodeModulesPath = path9.join(getProjectRoot(), "node_modules");
3557
- const targetDir = path9.join(nodeModulesPath, pluginName);
3558
- const scopeDir = path9.dirname(targetDir);
3559
- if (!fs11.existsSync(scopeDir)) {
3560
- fs11.mkdirSync(scopeDir, { recursive: true });
3759
+ const nodeModulesPath = path11.join(getProjectRoot(), "node_modules");
3760
+ const targetDir = path11.join(nodeModulesPath, pluginName);
3761
+ const scopeDir = path11.dirname(targetDir);
3762
+ if (!fs13.existsSync(scopeDir)) {
3763
+ fs13.mkdirSync(scopeDir, { recursive: true });
3561
3764
  }
3562
- if (fs11.existsSync(targetDir)) {
3563
- fs11.rmSync(targetDir, { recursive: true });
3765
+ if (fs13.existsSync(targetDir)) {
3766
+ fs13.rmSync(targetDir, { recursive: true });
3564
3767
  }
3565
- const tempDir = path9.join(nodeModulesPath, ".cache", "fullstack-cli", "extract-temp");
3566
- if (fs11.existsSync(tempDir)) {
3567
- fs11.rmSync(tempDir, { recursive: true });
3768
+ const tempDir = path11.join(nodeModulesPath, ".cache", "fullstack-cli", "extract-temp");
3769
+ if (fs13.existsSync(tempDir)) {
3770
+ fs13.rmSync(tempDir, { recursive: true });
3568
3771
  }
3569
- fs11.mkdirSync(tempDir, { recursive: true });
3772
+ fs13.mkdirSync(tempDir, { recursive: true });
3570
3773
  try {
3571
3774
  execSync2(`tar -xzf "${tgzPath}" -C "${tempDir}"`, { stdio: "pipe" });
3572
- const extractedDir = path9.join(tempDir, "package");
3573
- if (fs11.existsSync(extractedDir)) {
3574
- fs11.renameSync(extractedDir, targetDir);
3775
+ const extractedDir = path11.join(tempDir, "package");
3776
+ if (fs13.existsSync(extractedDir)) {
3777
+ fs13.renameSync(extractedDir, targetDir);
3575
3778
  } else {
3576
- const files = fs11.readdirSync(tempDir);
3779
+ const files = fs13.readdirSync(tempDir);
3577
3780
  if (files.length === 1) {
3578
- fs11.renameSync(path9.join(tempDir, files[0]), targetDir);
3781
+ fs13.renameSync(path11.join(tempDir, files[0]), targetDir);
3579
3782
  } else {
3580
3783
  throw new Error("Unexpected tgz structure");
3581
3784
  }
3582
3785
  }
3583
3786
  return targetDir;
3584
3787
  } finally {
3585
- if (fs11.existsSync(tempDir)) {
3586
- fs11.rmSync(tempDir, { recursive: true });
3788
+ if (fs13.existsSync(tempDir)) {
3789
+ fs13.rmSync(tempDir, { recursive: true });
3587
3790
  }
3588
3791
  }
3589
3792
  }
@@ -3592,10 +3795,10 @@ function checkMissingPeerDeps(peerDeps) {
3592
3795
  return [];
3593
3796
  }
3594
3797
  const missing = [];
3595
- const nodeModulesPath = path9.join(getProjectRoot(), "node_modules");
3798
+ const nodeModulesPath = path11.join(getProjectRoot(), "node_modules");
3596
3799
  for (const [depName, _version] of Object.entries(peerDeps)) {
3597
- const depPath = path9.join(nodeModulesPath, depName);
3598
- if (!fs11.existsSync(depPath)) {
3800
+ const depPath = path11.join(nodeModulesPath, depName);
3801
+ if (!fs13.existsSync(depPath)) {
3599
3802
  missing.push(depName);
3600
3803
  }
3601
3804
  }
@@ -3606,7 +3809,7 @@ function installMissingDeps(deps) {
3606
3809
  return;
3607
3810
  }
3608
3811
  console.log(`[action-plugin] Installing missing dependencies: ${deps.join(", ")}`);
3609
- const result = spawnSync4("npm", ["install", ...deps, "--no-save", "--no-package-lock"], {
3812
+ const result = spawnSync6("npm", ["install", ...deps, "--no-save", "--no-package-lock"], {
3610
3813
  cwd: getProjectRoot(),
3611
3814
  stdio: "inherit"
3612
3815
  });
@@ -3619,16 +3822,16 @@ function installMissingDeps(deps) {
3619
3822
  }
3620
3823
  function removePluginDirectory(pluginName) {
3621
3824
  const pluginPath = getPluginPath(pluginName);
3622
- if (fs11.existsSync(pluginPath)) {
3623
- fs11.rmSync(pluginPath, { recursive: true });
3825
+ if (fs13.existsSync(pluginPath)) {
3826
+ fs13.rmSync(pluginPath, { recursive: true });
3624
3827
  console.log(`[action-plugin] Removed ${pluginName}`);
3625
3828
  }
3626
3829
  }
3627
3830
 
3628
3831
  // src/commands/action-plugin/api-client.ts
3629
3832
  import { HttpClient as HttpClient2 } from "@lark-apaas/http-client";
3630
- import fs12 from "fs";
3631
- import path10 from "path";
3833
+ import fs14 from "fs";
3834
+ import path12 from "path";
3632
3835
  var PLUGIN_CACHE_DIR = "node_modules/.cache/fullstack-cli/plugins";
3633
3836
  async function getPluginVersions(keys, latestOnly = true) {
3634
3837
  const client = getHttpClient();
@@ -3692,19 +3895,19 @@ async function downloadFromPublic(downloadURL) {
3692
3895
  return Buffer.from(arrayBuffer);
3693
3896
  }
3694
3897
  function getPluginCacheDir() {
3695
- return path10.join(process.cwd(), PLUGIN_CACHE_DIR);
3898
+ return path12.join(process.cwd(), PLUGIN_CACHE_DIR);
3696
3899
  }
3697
3900
  function ensureCacheDir() {
3698
3901
  const cacheDir = getPluginCacheDir();
3699
- if (!fs12.existsSync(cacheDir)) {
3700
- fs12.mkdirSync(cacheDir, { recursive: true });
3902
+ if (!fs14.existsSync(cacheDir)) {
3903
+ fs14.mkdirSync(cacheDir, { recursive: true });
3701
3904
  }
3702
3905
  }
3703
3906
  function getTempFilePath(pluginKey, version) {
3704
3907
  ensureCacheDir();
3705
3908
  const safeKey = pluginKey.replace(/[/@]/g, "_");
3706
3909
  const filename = `${safeKey}@${version}.tgz`;
3707
- return path10.join(getPluginCacheDir(), filename);
3910
+ return path12.join(getPluginCacheDir(), filename);
3708
3911
  }
3709
3912
  var MAX_RETRIES = 2;
3710
3913
  async function withRetry(operation, description, maxRetries = MAX_RETRIES) {
@@ -3741,7 +3944,7 @@ async function downloadPlugin(pluginKey, requestedVersion) {
3741
3944
  );
3742
3945
  }
3743
3946
  const tgzPath = getTempFilePath(pluginKey, pluginInfo.version);
3744
- fs12.writeFileSync(tgzPath, tgzBuffer);
3947
+ fs14.writeFileSync(tgzPath, tgzBuffer);
3745
3948
  console.log(`[action-plugin] Downloaded to ${tgzPath} (${(tgzBuffer.length / 1024).toFixed(2)} KB)`);
3746
3949
  return {
3747
3950
  tgzPath,
@@ -3755,18 +3958,18 @@ function getCachePath(pluginKey, version) {
3755
3958
  ensureCacheDir();
3756
3959
  const safeKey = pluginKey.replace(/[/@]/g, "_");
3757
3960
  const filename = `${safeKey}@${version}.tgz`;
3758
- return path10.join(getPluginCacheDir(), filename);
3961
+ return path12.join(getPluginCacheDir(), filename);
3759
3962
  }
3760
3963
  function hasCachedPlugin(pluginKey, version) {
3761
3964
  const cachePath = getCachePath(pluginKey, version);
3762
- return fs12.existsSync(cachePath);
3965
+ return fs14.existsSync(cachePath);
3763
3966
  }
3764
3967
  function listCachedPlugins() {
3765
3968
  const cacheDir = getPluginCacheDir();
3766
- if (!fs12.existsSync(cacheDir)) {
3969
+ if (!fs14.existsSync(cacheDir)) {
3767
3970
  return [];
3768
3971
  }
3769
- const files = fs12.readdirSync(cacheDir);
3972
+ const files = fs14.readdirSync(cacheDir);
3770
3973
  const result = [];
3771
3974
  for (const file of files) {
3772
3975
  if (!file.endsWith(".tgz")) continue;
@@ -3774,8 +3977,8 @@ function listCachedPlugins() {
3774
3977
  if (!match) continue;
3775
3978
  const [, rawName, version] = match;
3776
3979
  const name = rawName.replace(/^_/, "@").replace(/_/, "/");
3777
- const filePath = path10.join(cacheDir, file);
3778
- const stat = fs12.statSync(filePath);
3980
+ const filePath = path12.join(cacheDir, file);
3981
+ const stat = fs14.statSync(filePath);
3779
3982
  result.push({
3780
3983
  name,
3781
3984
  version,
@@ -3788,14 +3991,14 @@ function listCachedPlugins() {
3788
3991
  }
3789
3992
  function cleanAllCache() {
3790
3993
  const cacheDir = getPluginCacheDir();
3791
- if (!fs12.existsSync(cacheDir)) {
3994
+ if (!fs14.existsSync(cacheDir)) {
3792
3995
  return 0;
3793
3996
  }
3794
- const files = fs12.readdirSync(cacheDir);
3997
+ const files = fs14.readdirSync(cacheDir);
3795
3998
  let count = 0;
3796
3999
  for (const file of files) {
3797
4000
  if (file.endsWith(".tgz")) {
3798
- fs12.unlinkSync(path10.join(cacheDir, file));
4001
+ fs14.unlinkSync(path12.join(cacheDir, file));
3799
4002
  count++;
3800
4003
  }
3801
4004
  }
@@ -3803,21 +4006,21 @@ function cleanAllCache() {
3803
4006
  }
3804
4007
  function cleanPluginCache(pluginKey, version) {
3805
4008
  const cacheDir = getPluginCacheDir();
3806
- if (!fs12.existsSync(cacheDir)) {
4009
+ if (!fs14.existsSync(cacheDir)) {
3807
4010
  return 0;
3808
4011
  }
3809
4012
  const safeKey = pluginKey.replace(/[/@]/g, "_");
3810
- const files = fs12.readdirSync(cacheDir);
4013
+ const files = fs14.readdirSync(cacheDir);
3811
4014
  let count = 0;
3812
4015
  for (const file of files) {
3813
4016
  if (version) {
3814
4017
  if (file === `${safeKey}@${version}.tgz`) {
3815
- fs12.unlinkSync(path10.join(cacheDir, file));
4018
+ fs14.unlinkSync(path12.join(cacheDir, file));
3816
4019
  count++;
3817
4020
  }
3818
4021
  } else {
3819
4022
  if (file.startsWith(`${safeKey}@`) && file.endsWith(".tgz")) {
3820
- fs12.unlinkSync(path10.join(cacheDir, file));
4023
+ fs14.unlinkSync(path12.join(cacheDir, file));
3821
4024
  count++;
3822
4025
  }
3823
4026
  }
@@ -4244,40 +4447,40 @@ var actionPluginCommandGroup = {
4244
4447
  };
4245
4448
 
4246
4449
  // src/commands/capability/utils.ts
4247
- import fs13 from "fs";
4450
+ import fs15 from "fs";
4248
4451
  import { createRequire as createRequire2 } from "module";
4249
- import path11 from "path";
4452
+ import path13 from "path";
4250
4453
  var CAPABILITIES_DIR = "server/capabilities";
4251
4454
  function getProjectRoot2() {
4252
4455
  return process.cwd();
4253
4456
  }
4254
4457
  function getCapabilitiesDir() {
4255
- return path11.join(getProjectRoot2(), CAPABILITIES_DIR);
4458
+ return path13.join(getProjectRoot2(), CAPABILITIES_DIR);
4256
4459
  }
4257
4460
  function getCapabilityPath(id) {
4258
- return path11.join(getCapabilitiesDir(), `${id}.json`);
4461
+ return path13.join(getCapabilitiesDir(), `${id}.json`);
4259
4462
  }
4260
4463
  function getPluginManifestPath(pluginKey) {
4261
- return path11.join(getProjectRoot2(), "node_modules", pluginKey, "manifest.json");
4464
+ return path13.join(getProjectRoot2(), "node_modules", pluginKey, "manifest.json");
4262
4465
  }
4263
4466
  function capabilitiesDirExists() {
4264
- return fs13.existsSync(getCapabilitiesDir());
4467
+ return fs15.existsSync(getCapabilitiesDir());
4265
4468
  }
4266
4469
  function listCapabilityIds() {
4267
4470
  const dir = getCapabilitiesDir();
4268
- if (!fs13.existsSync(dir)) {
4471
+ if (!fs15.existsSync(dir)) {
4269
4472
  return [];
4270
4473
  }
4271
- const files = fs13.readdirSync(dir);
4474
+ const files = fs15.readdirSync(dir);
4272
4475
  return files.filter((f) => f.endsWith(".json") && f !== "capabilities.json").map((f) => f.replace(/\.json$/, ""));
4273
4476
  }
4274
4477
  function readCapability(id) {
4275
4478
  const filePath = getCapabilityPath(id);
4276
- if (!fs13.existsSync(filePath)) {
4479
+ if (!fs15.existsSync(filePath)) {
4277
4480
  throw new Error(`Capability not found: ${id}`);
4278
4481
  }
4279
4482
  try {
4280
- const content = fs13.readFileSync(filePath, "utf-8");
4483
+ const content = fs15.readFileSync(filePath, "utf-8");
4281
4484
  return JSON.parse(content);
4282
4485
  } catch (error) {
4283
4486
  if (error instanceof SyntaxError) {
@@ -4304,11 +4507,11 @@ function readAllCapabilities() {
4304
4507
  }
4305
4508
  function readPluginManifest(pluginKey) {
4306
4509
  const manifestPath = getPluginManifestPath(pluginKey);
4307
- if (!fs13.existsSync(manifestPath)) {
4510
+ if (!fs15.existsSync(manifestPath)) {
4308
4511
  throw new Error(`Plugin not installed: ${pluginKey} (manifest.json not found)`);
4309
4512
  }
4310
4513
  try {
4311
- const content = fs13.readFileSync(manifestPath, "utf-8");
4514
+ const content = fs15.readFileSync(manifestPath, "utf-8");
4312
4515
  return JSON.parse(content);
4313
4516
  } catch (error) {
4314
4517
  if (error instanceof SyntaxError) {
@@ -4325,7 +4528,7 @@ function hasValidParamsSchema(paramsSchema) {
4325
4528
  }
4326
4529
  async function loadPlugin(pluginKey) {
4327
4530
  try {
4328
- const userRequire = createRequire2(path11.join(getProjectRoot2(), "package.json"));
4531
+ const userRequire = createRequire2(path13.join(getProjectRoot2(), "package.json"));
4329
4532
  const resolvedPath = userRequire.resolve(pluginKey);
4330
4533
  const pluginModule = await import(resolvedPath);
4331
4534
  const pluginPackage = pluginModule.default ?? pluginModule;
@@ -4488,8 +4691,8 @@ var capabilityCommandGroup = {
4488
4691
  import { execFile } from "child_process";
4489
4692
 
4490
4693
  // src/commands/component/registry-preparer.ts
4491
- import fs14 from "fs";
4492
- import path12 from "path";
4694
+ import fs16 from "fs";
4695
+ import path14 from "path";
4493
4696
  import os from "os";
4494
4697
 
4495
4698
  // src/commands/component/service.ts
@@ -4545,7 +4748,7 @@ async function sendInstallEvent(key) {
4545
4748
  }
4546
4749
 
4547
4750
  // src/commands/component/registry-preparer.ts
4548
- var REGISTRY_TEMP_DIR = path12.join(os.tmpdir(), "miaoda-registry");
4751
+ var REGISTRY_TEMP_DIR = path14.join(os.tmpdir(), "miaoda-registry");
4549
4752
  function parseComponentKey(key) {
4550
4753
  const match = key.match(/^@([^/]+)\/(.+)$/);
4551
4754
  if (!match) {
@@ -4557,11 +4760,11 @@ function parseComponentKey(key) {
4557
4760
  }
4558
4761
  function getLocalRegistryPath(key) {
4559
4762
  const { scope, name } = parseComponentKey(key);
4560
- return path12.join(REGISTRY_TEMP_DIR, scope, `${name}.json`);
4763
+ return path14.join(REGISTRY_TEMP_DIR, scope, `${name}.json`);
4561
4764
  }
4562
4765
  function ensureDir(dirPath) {
4563
- if (!fs14.existsSync(dirPath)) {
4564
- fs14.mkdirSync(dirPath, { recursive: true });
4766
+ if (!fs16.existsSync(dirPath)) {
4767
+ fs16.mkdirSync(dirPath, { recursive: true });
4565
4768
  }
4566
4769
  }
4567
4770
  async function prepareRecursive(key, visited) {
@@ -4594,8 +4797,8 @@ async function prepareRecursive(key, visited) {
4594
4797
  registryDependencies: deps.map((dep) => getLocalRegistryPath(dep))
4595
4798
  };
4596
4799
  const localPath = getLocalRegistryPath(key);
4597
- ensureDir(path12.dirname(localPath));
4598
- fs14.writeFileSync(localPath, JSON.stringify(rewrittenItem, null, 2), "utf-8");
4800
+ ensureDir(path14.dirname(localPath));
4801
+ fs16.writeFileSync(localPath, JSON.stringify(rewrittenItem, null, 2), "utf-8");
4599
4802
  debug("\u4FDD\u5B58\u5230: %s", localPath);
4600
4803
  }
4601
4804
  async function prepareComponentRegistryItems(id) {
@@ -4605,18 +4808,18 @@ async function prepareComponentRegistryItems(id) {
4605
4808
  }
4606
4809
  function cleanupTempDir() {
4607
4810
  try {
4608
- if (fs14.existsSync(REGISTRY_TEMP_DIR)) {
4609
- fs14.rmSync(REGISTRY_TEMP_DIR, { recursive: true, force: true });
4811
+ if (fs16.existsSync(REGISTRY_TEMP_DIR)) {
4812
+ fs16.rmSync(REGISTRY_TEMP_DIR, { recursive: true, force: true });
4610
4813
  }
4611
4814
  } catch {
4612
4815
  }
4613
4816
  }
4614
4817
  function getDownloadedRegistryItem(itemId) {
4615
4818
  const localPath = getLocalRegistryPath(itemId);
4616
- if (!fs14.existsSync(localPath)) {
4819
+ if (!fs16.existsSync(localPath)) {
4617
4820
  return null;
4618
4821
  }
4619
- const content = fs14.readFileSync(localPath, "utf-8");
4822
+ const content = fs16.readFileSync(localPath, "utf-8");
4620
4823
  return JSON.parse(content);
4621
4824
  }
4622
4825
 
@@ -4784,58 +4987,58 @@ var componentCommandGroup = {
4784
4987
  };
4785
4988
 
4786
4989
  // src/commands/migration/version-manager.ts
4787
- import fs15 from "fs";
4788
- import path13 from "path";
4990
+ import fs17 from "fs";
4991
+ import path15 from "path";
4789
4992
  var PACKAGE_JSON = "package.json";
4790
4993
  var VERSION_FIELD = "migrationVersion";
4791
4994
  function getPackageJsonPath2() {
4792
- return path13.join(process.cwd(), PACKAGE_JSON);
4995
+ return path15.join(process.cwd(), PACKAGE_JSON);
4793
4996
  }
4794
4997
  function getCurrentVersion() {
4795
4998
  const pkgPath = getPackageJsonPath2();
4796
- if (!fs15.existsSync(pkgPath)) {
4999
+ if (!fs17.existsSync(pkgPath)) {
4797
5000
  throw new Error("package.json not found");
4798
5001
  }
4799
- const pkg2 = JSON.parse(fs15.readFileSync(pkgPath, "utf-8"));
5002
+ const pkg2 = JSON.parse(fs17.readFileSync(pkgPath, "utf-8"));
4800
5003
  return pkg2[VERSION_FIELD] ?? 0;
4801
5004
  }
4802
5005
  function setCurrentVersion(version) {
4803
5006
  const pkgPath = getPackageJsonPath2();
4804
- const pkg2 = JSON.parse(fs15.readFileSync(pkgPath, "utf-8"));
5007
+ const pkg2 = JSON.parse(fs17.readFileSync(pkgPath, "utf-8"));
4805
5008
  pkg2[VERSION_FIELD] = version;
4806
- fs15.writeFileSync(pkgPath, JSON.stringify(pkg2, null, 2) + "\n", "utf-8");
5009
+ fs17.writeFileSync(pkgPath, JSON.stringify(pkg2, null, 2) + "\n", "utf-8");
4807
5010
  }
4808
5011
 
4809
5012
  // src/commands/migration/versions/v001_capability/json-migrator/detector.ts
4810
- import fs17 from "fs";
4811
- import path15 from "path";
5013
+ import fs19 from "fs";
5014
+ import path17 from "path";
4812
5015
 
4813
5016
  // src/commands/migration/versions/v001_capability/utils.ts
4814
- import fs16 from "fs";
4815
- import path14 from "path";
5017
+ import fs18 from "fs";
5018
+ import path16 from "path";
4816
5019
  var CAPABILITIES_DIR2 = "server/capabilities";
4817
5020
  function getProjectRoot3() {
4818
5021
  return process.cwd();
4819
5022
  }
4820
5023
  function getCapabilitiesDir2() {
4821
- return path14.join(getProjectRoot3(), CAPABILITIES_DIR2);
5024
+ return path16.join(getProjectRoot3(), CAPABILITIES_DIR2);
4822
5025
  }
4823
5026
  function getPluginManifestPath2(pluginKey) {
4824
- return path14.join(getProjectRoot3(), "node_modules", pluginKey, "manifest.json");
5027
+ return path16.join(getProjectRoot3(), "node_modules", pluginKey, "manifest.json");
4825
5028
  }
4826
5029
 
4827
5030
  // src/commands/migration/versions/v001_capability/json-migrator/detector.ts
4828
5031
  function detectJsonMigration() {
4829
5032
  const capabilitiesDir = getCapabilitiesDir2();
4830
- const oldFilePath = path15.join(capabilitiesDir, "capabilities.json");
4831
- if (!fs17.existsSync(oldFilePath)) {
5033
+ const oldFilePath = path17.join(capabilitiesDir, "capabilities.json");
5034
+ if (!fs19.existsSync(oldFilePath)) {
4832
5035
  return {
4833
5036
  needsMigration: false,
4834
5037
  reason: "capabilities.json not found"
4835
5038
  };
4836
5039
  }
4837
5040
  try {
4838
- const content = fs17.readFileSync(oldFilePath, "utf-8");
5041
+ const content = fs19.readFileSync(oldFilePath, "utf-8");
4839
5042
  const parsed = JSON.parse(content);
4840
5043
  if (!Array.isArray(parsed)) {
4841
5044
  return {
@@ -4886,8 +5089,8 @@ async function check(options) {
4886
5089
  }
4887
5090
 
4888
5091
  // src/commands/migration/versions/v001_capability/json-migrator/index.ts
4889
- import fs18 from "fs";
4890
- import path16 from "path";
5092
+ import fs20 from "fs";
5093
+ import path18 from "path";
4891
5094
 
4892
5095
  // src/commands/migration/versions/v001_capability/mapping.ts
4893
5096
  var DEFAULT_PLUGIN_VERSION = "1.0.0";
@@ -5117,18 +5320,18 @@ function transformCapabilities(oldCapabilities) {
5117
5320
  // src/commands/migration/versions/v001_capability/json-migrator/index.ts
5118
5321
  function loadExistingCapabilities() {
5119
5322
  const capabilitiesDir = getCapabilitiesDir2();
5120
- if (!fs18.existsSync(capabilitiesDir)) {
5323
+ if (!fs20.existsSync(capabilitiesDir)) {
5121
5324
  return [];
5122
5325
  }
5123
- const files = fs18.readdirSync(capabilitiesDir);
5326
+ const files = fs20.readdirSync(capabilitiesDir);
5124
5327
  const capabilities = [];
5125
5328
  for (const file of files) {
5126
5329
  if (file === "capabilities.json" || !file.endsWith(".json")) {
5127
5330
  continue;
5128
5331
  }
5129
5332
  try {
5130
- const filePath = path16.join(capabilitiesDir, file);
5131
- const content = fs18.readFileSync(filePath, "utf-8");
5333
+ const filePath = path18.join(capabilitiesDir, file);
5334
+ const content = fs20.readFileSync(filePath, "utf-8");
5132
5335
  const capability = JSON.parse(content);
5133
5336
  if (capability.id && capability.pluginKey) {
5134
5337
  capabilities.push(capability);
@@ -5186,9 +5389,9 @@ async function migrateJsonFiles(options) {
5186
5389
  }
5187
5390
  const capabilitiesDir = getCapabilitiesDir2();
5188
5391
  for (const cap of newCapabilities) {
5189
- const filePath = path16.join(capabilitiesDir, `${cap.id}.json`);
5392
+ const filePath = path18.join(capabilitiesDir, `${cap.id}.json`);
5190
5393
  const content = JSON.stringify(cap, null, 2);
5191
- fs18.writeFileSync(filePath, content, "utf-8");
5394
+ fs20.writeFileSync(filePath, content, "utf-8");
5192
5395
  console.log(` \u2713 Created: ${cap.id}.json`);
5193
5396
  }
5194
5397
  return {
@@ -5200,11 +5403,11 @@ async function migrateJsonFiles(options) {
5200
5403
  }
5201
5404
 
5202
5405
  // src/commands/migration/versions/v001_capability/plugin-installer/detector.ts
5203
- import fs19 from "fs";
5406
+ import fs21 from "fs";
5204
5407
  function isPluginInstalled2(pluginKey) {
5205
5408
  const actionPlugins = readActionPlugins();
5206
5409
  const manifestPath = getPluginManifestPath2(pluginKey);
5207
- return fs19.existsSync(manifestPath) && !!actionPlugins[pluginKey];
5410
+ return fs21.existsSync(manifestPath) && !!actionPlugins[pluginKey];
5208
5411
  }
5209
5412
  function detectPluginsToInstall(capabilities) {
5210
5413
  const pluginKeys = /* @__PURE__ */ new Set();
@@ -5280,12 +5483,12 @@ async function installPlugins(capabilities, options) {
5280
5483
  }
5281
5484
 
5282
5485
  // src/commands/migration/versions/v001_capability/code-migrator/index.ts
5283
- import path18 from "path";
5486
+ import path20 from "path";
5284
5487
  import { Project as Project3 } from "ts-morph";
5285
5488
 
5286
5489
  // src/commands/migration/versions/v001_capability/code-migrator/scanner.ts
5287
- import fs20 from "fs";
5288
- import path17 from "path";
5490
+ import fs22 from "fs";
5491
+ import path19 from "path";
5289
5492
  var EXCLUDED_DIRS = [
5290
5493
  "node_modules",
5291
5494
  "dist",
@@ -5300,9 +5503,9 @@ var EXCLUDED_PATTERNS = [
5300
5503
  /\.d\.ts$/
5301
5504
  ];
5302
5505
  function scanDirectory(dir, files = []) {
5303
- const entries = fs20.readdirSync(dir, { withFileTypes: true });
5506
+ const entries = fs22.readdirSync(dir, { withFileTypes: true });
5304
5507
  for (const entry of entries) {
5305
- const fullPath = path17.join(dir, entry.name);
5508
+ const fullPath = path19.join(dir, entry.name);
5306
5509
  if (entry.isDirectory()) {
5307
5510
  if (EXCLUDED_DIRS.includes(entry.name)) {
5308
5511
  continue;
@@ -5318,14 +5521,14 @@ function scanDirectory(dir, files = []) {
5318
5521
  return files;
5319
5522
  }
5320
5523
  function scanServerFiles() {
5321
- const serverDir = path17.join(getProjectRoot3(), "server");
5322
- if (!fs20.existsSync(serverDir)) {
5524
+ const serverDir = path19.join(getProjectRoot3(), "server");
5525
+ if (!fs22.existsSync(serverDir)) {
5323
5526
  return [];
5324
5527
  }
5325
5528
  return scanDirectory(serverDir);
5326
5529
  }
5327
5530
  function hasCapabilityImport(filePath) {
5328
- const content = fs20.readFileSync(filePath, "utf-8");
5531
+ const content = fs22.readFileSync(filePath, "utf-8");
5329
5532
  return /import\s+.*from\s+['"][^'"]*capabilities[^'"]*['"]/.test(content);
5330
5533
  }
5331
5534
  function scanFilesToMigrate() {
@@ -5702,7 +5905,7 @@ function analyzeFile(project, filePath, actionNameMap) {
5702
5905
  const callSites = analyzeCallSites(sourceFile, imports);
5703
5906
  const classInfo = analyzeClass(sourceFile);
5704
5907
  const { canMigrate, reason } = canAutoMigrate(classInfo);
5705
- const relativePath = path18.relative(getProjectRoot3(), filePath);
5908
+ const relativePath = path20.relative(getProjectRoot3(), filePath);
5706
5909
  return {
5707
5910
  filePath: relativePath,
5708
5911
  imports,
@@ -5713,7 +5916,7 @@ function analyzeFile(project, filePath, actionNameMap) {
5713
5916
  };
5714
5917
  }
5715
5918
  function migrateFile(project, analysis, dryRun) {
5716
- const absolutePath = path18.join(getProjectRoot3(), analysis.filePath);
5919
+ const absolutePath = path20.join(getProjectRoot3(), analysis.filePath);
5717
5920
  if (!analysis.canAutoMigrate) {
5718
5921
  return {
5719
5922
  filePath: analysis.filePath,
@@ -5816,17 +6019,17 @@ function getSuggestion(analysis) {
5816
6019
  }
5817
6020
 
5818
6021
  // src/commands/migration/versions/v001_capability/cleanup.ts
5819
- import fs21 from "fs";
5820
- import path19 from "path";
6022
+ import fs23 from "fs";
6023
+ import path21 from "path";
5821
6024
  function cleanupOldFiles(capabilities, dryRun) {
5822
6025
  const deletedFiles = [];
5823
6026
  const errors = [];
5824
6027
  const capabilitiesDir = getCapabilitiesDir2();
5825
- const oldJsonPath = path19.join(capabilitiesDir, "capabilities.json");
5826
- if (fs21.existsSync(oldJsonPath)) {
6028
+ const oldJsonPath = path21.join(capabilitiesDir, "capabilities.json");
6029
+ if (fs23.existsSync(oldJsonPath)) {
5827
6030
  try {
5828
6031
  if (!dryRun) {
5829
- fs21.unlinkSync(oldJsonPath);
6032
+ fs23.unlinkSync(oldJsonPath);
5830
6033
  }
5831
6034
  deletedFiles.push("capabilities.json");
5832
6035
  } catch (error) {
@@ -5834,11 +6037,11 @@ function cleanupOldFiles(capabilities, dryRun) {
5834
6037
  }
5835
6038
  }
5836
6039
  for (const cap of capabilities) {
5837
- const tsFilePath = path19.join(capabilitiesDir, `${cap.id}.ts`);
5838
- if (fs21.existsSync(tsFilePath)) {
6040
+ const tsFilePath = path21.join(capabilitiesDir, `${cap.id}.ts`);
6041
+ if (fs23.existsSync(tsFilePath)) {
5839
6042
  try {
5840
6043
  if (!dryRun) {
5841
- fs21.unlinkSync(tsFilePath);
6044
+ fs23.unlinkSync(tsFilePath);
5842
6045
  }
5843
6046
  deletedFiles.push(`${cap.id}.ts`);
5844
6047
  } catch (error) {
@@ -5854,8 +6057,8 @@ function cleanupOldFiles(capabilities, dryRun) {
5854
6057
  }
5855
6058
 
5856
6059
  // src/commands/migration/versions/v001_capability/report-generator.ts
5857
- import fs22 from "fs";
5858
- import path20 from "path";
6060
+ import fs24 from "fs";
6061
+ import path22 from "path";
5859
6062
  var REPORT_FILE = "capability-migration-report.md";
5860
6063
  function printSummary(result) {
5861
6064
  const { jsonMigration, pluginInstallation, codeMigration, cleanup } = result;
@@ -6018,15 +6221,15 @@ async function generateReport(result) {
6018
6221
  }
6019
6222
  lines.push("");
6020
6223
  const logDir = process.env.LOG_DIR || "logs";
6021
- if (!fs22.existsSync(logDir)) {
6224
+ if (!fs24.existsSync(logDir)) {
6022
6225
  return;
6023
6226
  }
6024
- const reportDir = path20.join(logDir, "migration");
6025
- if (!fs22.existsSync(reportDir)) {
6026
- fs22.mkdirSync(reportDir, { recursive: true });
6227
+ const reportDir = path22.join(logDir, "migration");
6228
+ if (!fs24.existsSync(reportDir)) {
6229
+ fs24.mkdirSync(reportDir, { recursive: true });
6027
6230
  }
6028
- const reportPath = path20.join(reportDir, REPORT_FILE);
6029
- fs22.writeFileSync(reportPath, lines.join("\n"), "utf-8");
6231
+ const reportPath = path22.join(reportDir, REPORT_FILE);
6232
+ fs24.writeFileSync(reportPath, lines.join("\n"), "utf-8");
6030
6233
  console.log(`\u{1F4C4} Report generated: ${reportPath}`);
6031
6234
  }
6032
6235
 
@@ -6203,7 +6406,7 @@ function buildResult(jsonMigration, pluginInstallation, codeMigration, cleanup)
6203
6406
  }
6204
6407
 
6205
6408
  // src/commands/migration/versions/v001_capability/run.ts
6206
- async function run5(options) {
6409
+ async function run6(options) {
6207
6410
  try {
6208
6411
  const migrationOptions = {
6209
6412
  dryRun: options.dryRun ?? false
@@ -6268,7 +6471,7 @@ var v001CapabilityMigration = {
6268
6471
  name: "capability",
6269
6472
  description: "Migrate capability configurations from old format (capabilities.json array) to new format (individual JSON files)",
6270
6473
  check,
6271
- run: run5
6474
+ run: run6
6272
6475
  };
6273
6476
 
6274
6477
  // src/commands/migration/versions/index.ts
@@ -6558,10 +6761,10 @@ var migrationCommand = {
6558
6761
  };
6559
6762
 
6560
6763
  // src/commands/read-logs/index.ts
6561
- import path21 from "path";
6764
+ import path23 from "path";
6562
6765
 
6563
6766
  // src/commands/read-logs/std-utils.ts
6564
- import fs23 from "fs";
6767
+ import fs25 from "fs";
6565
6768
  function formatStdPrefixTime(localTime) {
6566
6769
  const match = localTime.match(/^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/);
6567
6770
  if (!match) return localTime;
@@ -6591,11 +6794,11 @@ function stripPrefixFromStdLine(line) {
6591
6794
  return `[${time}] ${content}`;
6592
6795
  }
6593
6796
  function readStdLinesTailFromLastMarkerPaged(filePath, maxLines, offset, isMarker) {
6594
- const stat = fs23.statSync(filePath);
6797
+ const stat = fs25.statSync(filePath);
6595
6798
  if (stat.size === 0) {
6596
6799
  return { lines: [], markerFound: false, totalLinesCount: 0 };
6597
6800
  }
6598
- const fd = fs23.openSync(filePath, "r");
6801
+ const fd = fs25.openSync(filePath, "r");
6599
6802
  const chunkSize = 64 * 1024;
6600
6803
  let position = stat.size;
6601
6804
  let remainder = "";
@@ -6609,7 +6812,7 @@ function readStdLinesTailFromLastMarkerPaged(filePath, maxLines, offset, isMarke
6609
6812
  const length = Math.min(chunkSize, position);
6610
6813
  position -= length;
6611
6814
  const buffer = Buffer.alloc(length);
6612
- fs23.readSync(fd, buffer, 0, length, position);
6815
+ fs25.readSync(fd, buffer, 0, length, position);
6613
6816
  let chunk = buffer.toString("utf8");
6614
6817
  if (remainder) {
6615
6818
  chunk += remainder;
@@ -6651,7 +6854,7 @@ function readStdLinesTailFromLastMarkerPaged(filePath, maxLines, offset, isMarke
6651
6854
  }
6652
6855
  }
6653
6856
  } finally {
6654
- fs23.closeSync(fd);
6857
+ fs25.closeSync(fd);
6655
6858
  }
6656
6859
  return { lines: collected.reverse(), markerFound, totalLinesCount };
6657
6860
  }
@@ -6672,21 +6875,21 @@ function readServerStdSegment(filePath, maxLines, offset) {
6672
6875
  }
6673
6876
 
6674
6877
  // src/commands/read-logs/tail.ts
6675
- import fs24 from "fs";
6878
+ import fs26 from "fs";
6676
6879
  function fileExists(filePath) {
6677
6880
  try {
6678
- fs24.accessSync(filePath, fs24.constants.F_OK | fs24.constants.R_OK);
6881
+ fs26.accessSync(filePath, fs26.constants.F_OK | fs26.constants.R_OK);
6679
6882
  return true;
6680
6883
  } catch {
6681
6884
  return false;
6682
6885
  }
6683
6886
  }
6684
6887
  function readFileTailLines(filePath, maxLines) {
6685
- const stat = fs24.statSync(filePath);
6888
+ const stat = fs26.statSync(filePath);
6686
6889
  if (stat.size === 0) {
6687
6890
  return [];
6688
6891
  }
6689
- const fd = fs24.openSync(filePath, "r");
6892
+ const fd = fs26.openSync(filePath, "r");
6690
6893
  const chunkSize = 64 * 1024;
6691
6894
  const chunks = [];
6692
6895
  let position = stat.size;
@@ -6696,13 +6899,13 @@ function readFileTailLines(filePath, maxLines) {
6696
6899
  const length = Math.min(chunkSize, position);
6697
6900
  position -= length;
6698
6901
  const buffer = Buffer.alloc(length);
6699
- fs24.readSync(fd, buffer, 0, length, position);
6902
+ fs26.readSync(fd, buffer, 0, length, position);
6700
6903
  chunks.unshift(buffer.toString("utf8"));
6701
6904
  const chunkLines = buffer.toString("utf8").split("\n").length - 1;
6702
6905
  collectedLines += chunkLines;
6703
6906
  }
6704
6907
  } finally {
6705
- fs24.closeSync(fd);
6908
+ fs26.closeSync(fd);
6706
6909
  }
6707
6910
  const content = chunks.join("");
6708
6911
  const allLines = content.split("\n");
@@ -6718,11 +6921,11 @@ function readFileTailLines(filePath, maxLines) {
6718
6921
  return allLines.slice(allLines.length - maxLines);
6719
6922
  }
6720
6923
  function readFileTailNonEmptyLinesWithOffset(filePath, maxLines, offset) {
6721
- const stat = fs24.statSync(filePath);
6924
+ const stat = fs26.statSync(filePath);
6722
6925
  if (stat.size === 0) {
6723
6926
  return { lines: [], totalLinesCount: 0 };
6724
6927
  }
6725
- const fd = fs24.openSync(filePath, "r");
6928
+ const fd = fs26.openSync(filePath, "r");
6726
6929
  const chunkSize = 64 * 1024;
6727
6930
  let position = stat.size;
6728
6931
  let remainder = "";
@@ -6734,7 +6937,7 @@ function readFileTailNonEmptyLinesWithOffset(filePath, maxLines, offset) {
6734
6937
  const length = Math.min(chunkSize, position);
6735
6938
  position -= length;
6736
6939
  const buffer = Buffer.alloc(length);
6737
- fs24.readSync(fd, buffer, 0, length, position);
6940
+ fs26.readSync(fd, buffer, 0, length, position);
6738
6941
  let chunk = buffer.toString("utf8");
6739
6942
  if (remainder) {
6740
6943
  chunk += remainder;
@@ -6765,7 +6968,7 @@ function readFileTailNonEmptyLinesWithOffset(filePath, maxLines, offset) {
6765
6968
  }
6766
6969
  }
6767
6970
  } finally {
6768
- fs24.closeSync(fd);
6971
+ fs26.closeSync(fd);
6769
6972
  }
6770
6973
  return { lines: collected.reverse(), totalLinesCount };
6771
6974
  }
@@ -6907,7 +7110,7 @@ function readDevStdSegment(filePath, maxLines, offset) {
6907
7110
  }
6908
7111
 
6909
7112
  // src/commands/read-logs/json-lines.ts
6910
- import fs25 from "fs";
7113
+ import fs27 from "fs";
6911
7114
  function normalizePid(value) {
6912
7115
  if (typeof value === "number") {
6913
7116
  return String(value);
@@ -6958,11 +7161,11 @@ function buildWantedLevelSet(levels) {
6958
7161
  return set.size > 0 ? set : null;
6959
7162
  }
6960
7163
  function readJsonLinesLastPid(filePath, maxLines, offset, levels) {
6961
- const stat = fs25.statSync(filePath);
7164
+ const stat = fs27.statSync(filePath);
6962
7165
  if (stat.size === 0) {
6963
7166
  return { lines: [], totalLinesCount: 0 };
6964
7167
  }
6965
- const fd = fs25.openSync(filePath, "r");
7168
+ const fd = fs27.openSync(filePath, "r");
6966
7169
  const chunkSize = 64 * 1024;
6967
7170
  let position = stat.size;
6968
7171
  let remainder = "";
@@ -6977,7 +7180,7 @@ function readJsonLinesLastPid(filePath, maxLines, offset, levels) {
6977
7180
  const length = Math.min(chunkSize, position);
6978
7181
  position -= length;
6979
7182
  const buffer = Buffer.alloc(length);
6980
- fs25.readSync(fd, buffer, 0, length, position);
7183
+ fs27.readSync(fd, buffer, 0, length, position);
6981
7184
  let chunk = buffer.toString("utf8");
6982
7185
  if (remainder) {
6983
7186
  chunk += remainder;
@@ -7039,7 +7242,7 @@ function readJsonLinesLastPid(filePath, maxLines, offset, levels) {
7039
7242
  }
7040
7243
  }
7041
7244
  } finally {
7042
- fs25.closeSync(fd);
7245
+ fs27.closeSync(fd);
7043
7246
  }
7044
7247
  return { lines: collected.reverse(), totalLinesCount };
7045
7248
  }
@@ -7082,11 +7285,11 @@ function extractTraceId(obj) {
7082
7285
  function readJsonLinesByTraceId(filePath, traceId, maxLines, offset, levels) {
7083
7286
  const wanted = traceId.trim();
7084
7287
  if (!wanted) return { lines: [], totalLinesCount: 0 };
7085
- const stat = fs25.statSync(filePath);
7288
+ const stat = fs27.statSync(filePath);
7086
7289
  if (stat.size === 0) {
7087
7290
  return { lines: [], totalLinesCount: 0 };
7088
7291
  }
7089
- const fd = fs25.openSync(filePath, "r");
7292
+ const fd = fs27.openSync(filePath, "r");
7090
7293
  const chunkSize = 64 * 1024;
7091
7294
  let position = stat.size;
7092
7295
  let remainder = "";
@@ -7099,7 +7302,7 @@ function readJsonLinesByTraceId(filePath, traceId, maxLines, offset, levels) {
7099
7302
  const length = Math.min(chunkSize, position);
7100
7303
  position -= length;
7101
7304
  const buffer = Buffer.alloc(length);
7102
- fs25.readSync(fd, buffer, 0, length, position);
7305
+ fs27.readSync(fd, buffer, 0, length, position);
7103
7306
  let chunk = buffer.toString("utf8");
7104
7307
  if (remainder) {
7105
7308
  chunk += remainder;
@@ -7152,7 +7355,7 @@ function readJsonLinesByTraceId(filePath, traceId, maxLines, offset, levels) {
7152
7355
  }
7153
7356
  }
7154
7357
  } finally {
7155
- fs25.closeSync(fd);
7358
+ fs27.closeSync(fd);
7156
7359
  }
7157
7360
  return { lines: collected.reverse(), totalLinesCount };
7158
7361
  }
@@ -7161,11 +7364,11 @@ function readJsonLinesTailByLevel(filePath, maxLines, offset, levels) {
7161
7364
  if (!wantedLevelSet) {
7162
7365
  return { lines: [], totalLinesCount: 0 };
7163
7366
  }
7164
- const stat = fs25.statSync(filePath);
7367
+ const stat = fs27.statSync(filePath);
7165
7368
  if (stat.size === 0) {
7166
7369
  return { lines: [], totalLinesCount: 0 };
7167
7370
  }
7168
- const fd = fs25.openSync(filePath, "r");
7371
+ const fd = fs27.openSync(filePath, "r");
7169
7372
  const chunkSize = 64 * 1024;
7170
7373
  let position = stat.size;
7171
7374
  let remainder = "";
@@ -7177,7 +7380,7 @@ function readJsonLinesTailByLevel(filePath, maxLines, offset, levels) {
7177
7380
  const length = Math.min(chunkSize, position);
7178
7381
  position -= length;
7179
7382
  const buffer = Buffer.alloc(length);
7180
- fs25.readSync(fd, buffer, 0, length, position);
7383
+ fs27.readSync(fd, buffer, 0, length, position);
7181
7384
  let chunk = buffer.toString("utf8");
7182
7385
  if (remainder) {
7183
7386
  chunk += remainder;
@@ -7224,7 +7427,7 @@ function readJsonLinesTailByLevel(filePath, maxLines, offset, levels) {
7224
7427
  }
7225
7428
  }
7226
7429
  } finally {
7227
- fs25.closeSync(fd);
7430
+ fs27.closeSync(fd);
7228
7431
  }
7229
7432
  return { lines: collected.reverse(), totalLinesCount };
7230
7433
  }
@@ -7458,34 +7661,34 @@ async function readLogsJsonResult(options) {
7458
7661
  };
7459
7662
  }
7460
7663
  function resolveLogFilePath(logDir, type) {
7461
- const base = path21.isAbsolute(logDir) ? logDir : path21.join(process.cwd(), logDir);
7664
+ const base = path23.isAbsolute(logDir) ? logDir : path23.join(process.cwd(), logDir);
7462
7665
  if (type === "server") {
7463
- return path21.join(base, "server.log");
7666
+ return path23.join(base, "server.log");
7464
7667
  }
7465
7668
  if (type === "trace") {
7466
- return path21.join(base, "trace.log");
7669
+ return path23.join(base, "trace.log");
7467
7670
  }
7468
7671
  if (type === "server-std") {
7469
- return path21.join(base, "server.std.log");
7672
+ return path23.join(base, "server.std.log");
7470
7673
  }
7471
7674
  if (type === "client-std") {
7472
- return path21.join(base, "client.std.log");
7675
+ return path23.join(base, "client.std.log");
7473
7676
  }
7474
7677
  if (type === "dev") {
7475
- return path21.join(base, "dev.log");
7678
+ return path23.join(base, "dev.log");
7476
7679
  }
7477
7680
  if (type === "dev-std") {
7478
- return path21.join(base, "dev.std.log");
7681
+ return path23.join(base, "dev.std.log");
7479
7682
  }
7480
7683
  if (type === "install-dep-std") {
7481
- return path21.join(base, "install-dep.std.log");
7684
+ return path23.join(base, "install-dep.std.log");
7482
7685
  }
7483
7686
  if (type === "browser") {
7484
- return path21.join(base, "browser.log");
7687
+ return path23.join(base, "browser.log");
7485
7688
  }
7486
7689
  throw new Error(`Unsupported log type: ${type}`);
7487
7690
  }
7488
- async function run6(options) {
7691
+ async function run7(options) {
7489
7692
  const result = await readLogsJsonResult(options);
7490
7693
  process.stdout.write(JSON.stringify(result) + "\n");
7491
7694
  }
@@ -7527,7 +7730,7 @@ var readLogsCommand = {
7527
7730
  const offset = parseNonNegativeInt(rawOptions.offset, "--offset");
7528
7731
  const traceId = typeof rawOptions.traceId === "string" ? rawOptions.traceId : void 0;
7529
7732
  const levels = parseCommaSeparatedList(rawOptions.level);
7530
- await run6({ logDir, type, maxLines, offset, traceId, levels });
7733
+ await run7({ logDir, type, maxLines, offset, traceId, levels });
7531
7734
  } catch (error) {
7532
7735
  const message = error instanceof Error ? error.message : String(error);
7533
7736
  process.stderr.write(message + "\n");
@@ -7658,9 +7861,9 @@ function camelToKebab(str) {
7658
7861
  }
7659
7862
 
7660
7863
  // src/commands/build/upload-static.handler.ts
7661
- import * as fs26 from "fs";
7864
+ import * as fs28 from "fs";
7662
7865
  import * as os2 from "os";
7663
- import * as path22 from "path";
7866
+ import * as path24 from "path";
7664
7867
  import { execFileSync } from "child_process";
7665
7868
  function readCredentialsFromEnv() {
7666
7869
  const uploadPrefix = process.env.STATIC_UPLOAD_PREFIX;
@@ -7684,8 +7887,8 @@ async function uploadStatic(options) {
7684
7887
  endpoint = UPLOAD_STATIC_DEFAULTS.endpoint,
7685
7888
  region = UPLOAD_STATIC_DEFAULTS.region
7686
7889
  } = options;
7687
- const resolvedStaticDir = path22.resolve(staticDir);
7688
- if (!fs26.existsSync(resolvedStaticDir)) {
7890
+ const resolvedStaticDir = path24.resolve(staticDir);
7891
+ if (!fs28.existsSync(resolvedStaticDir)) {
7689
7892
  console.error(`${LOG_PREFIX} \u76EE\u5F55\u4E0D\u5B58\u5728: ${resolvedStaticDir}\uFF0C\u8DF3\u8FC7\u4E0A\u4F20`);
7690
7893
  return;
7691
7894
  }
@@ -7718,8 +7921,8 @@ async function uploadStatic(options) {
7718
7921
  ({ AccessKeyID: accessKeyID, SecretAccessKey: secretAccessKey, SessionToken: sessionToken } = uploadCredential);
7719
7922
  }
7720
7923
  console.error(`${LOG_PREFIX} \u4E0A\u4F20\u76EE\u6807: ${uploadPrefix}`);
7721
- const confPath = path22.join(os2.tmpdir(), `.tosutilconfig-static-${process.pid}`);
7722
- fs26.writeFileSync(confPath, "");
7924
+ const confPath = path24.join(os2.tmpdir(), `.tosutilconfig-static-${process.pid}`);
7925
+ fs28.writeFileSync(confPath, "");
7723
7926
  try {
7724
7927
  console.error(`${LOG_PREFIX} \u914D\u7F6E tosutil...`);
7725
7928
  configureTosutil(resolvedTosutil, confPath, {
@@ -7733,7 +7936,7 @@ async function uploadStatic(options) {
7733
7936
  uploadToTos(resolvedTosutil, confPath, resolvedStaticDir, uploadPrefix);
7734
7937
  } finally {
7735
7938
  try {
7736
- fs26.unlinkSync(confPath);
7939
+ fs28.unlinkSync(confPath);
7737
7940
  } catch {
7738
7941
  }
7739
7942
  }
@@ -7753,8 +7956,8 @@ async function uploadStatic(options) {
7753
7956
  }
7754
7957
  }
7755
7958
  function resolveTosutilPath(tosutilPath) {
7756
- if (path22.isAbsolute(tosutilPath)) {
7757
- return fs26.existsSync(tosutilPath) ? tosutilPath : null;
7959
+ if (path24.isAbsolute(tosutilPath)) {
7960
+ return fs28.existsSync(tosutilPath) ? tosutilPath : null;
7758
7961
  }
7759
7962
  try {
7760
7963
  const resolved = execFileSync("which", [tosutilPath], { encoding: "utf-8" }).trim();
@@ -7799,7 +8002,7 @@ async function resolveBucketId(appId) {
7799
8002
  return bucketId;
7800
8003
  }
7801
8004
  function isDirEmpty(dirPath) {
7802
- const entries = fs26.readdirSync(dirPath);
8005
+ const entries = fs28.readdirSync(dirPath);
7803
8006
  return entries.length === 0;
7804
8007
  }
7805
8008
 
@@ -7894,12 +8097,12 @@ var commands = [
7894
8097
  ];
7895
8098
 
7896
8099
  // src/index.ts
7897
- var envPath = path23.join(process.cwd(), ".env");
7898
- if (fs27.existsSync(envPath)) {
8100
+ var envPath = path25.join(process.cwd(), ".env");
8101
+ if (fs29.existsSync(envPath)) {
7899
8102
  dotenvConfig({ path: envPath });
7900
8103
  }
7901
- var __dirname = path23.dirname(fileURLToPath5(import.meta.url));
7902
- var pkg = JSON.parse(fs27.readFileSync(path23.join(__dirname, "../package.json"), "utf-8"));
8104
+ var __dirname = path25.dirname(fileURLToPath5(import.meta.url));
8105
+ var pkg = JSON.parse(fs29.readFileSync(path25.join(__dirname, "../package.json"), "utf-8"));
7903
8106
  var cli = new FullstackCLI(pkg.version);
7904
8107
  cli.useAll(commands);
7905
8108
  cli.run();