@agile-team/robot-cli 2.1.0 → 2.3.0

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 (4) hide show
  1. package/CHANGELOG.md +18 -1
  2. package/README.md +27 -27
  3. package/dist/index.js +290 -247
  4. package/package.json +76 -77
package/dist/index.js CHANGED
@@ -2,15 +2,14 @@
2
2
  import { readFileSync } from "fs";
3
3
  import { fileURLToPath } from "url";
4
4
  import { dirname, join } from "path";
5
- import chalk4 from "chalk";
6
- import boxen from "boxen";
5
+ import chalk5 from "chalk";
7
6
  import inquirer2 from "inquirer";
8
7
  import { Command } from "commander";
9
8
 
10
9
  // src/create.ts
11
10
  import fs3 from "fs-extra";
12
11
  import path3 from "path";
13
- import chalk2 from "chalk";
12
+ import chalk3 from "chalk";
14
13
  import inquirer from "inquirer";
15
14
  import ora from "ora";
16
15
  import { execSync as execSync2 } from "child_process";
@@ -19,12 +18,13 @@ import { execSync as execSync2 } from "child_process";
19
18
  import fs from "fs-extra";
20
19
  import path from "path";
21
20
  import os from "os";
21
+ import chalk from "chalk";
22
22
  import extract from "extract-zip";
23
23
 
24
24
  // src/config/templates.config.ts
25
25
  var TEMPLATE_CATEGORIES = {
26
26
  frontend: {
27
- name: "\u{1F3A8} \u524D\u7AEF\u9879\u76EE",
27
+ name: "\u524D\u7AEF\u9879\u76EE",
28
28
  stacks: {
29
29
  vue: {
30
30
  name: "Vue.js",
@@ -64,12 +64,7 @@ var TEMPLATE_CATEGORIES = {
64
64
  description: "bun workspace + Monorepo \u591A\u5305\u7BA1\u7406\u67B6\u6784",
65
65
  repoUrl: "https://github.com/ChenyCHENYU/Robot_Admin",
66
66
  branch: "monorepo",
67
- features: [
68
- "bun workspace",
69
- "Monorepo",
70
- "\u591A\u5305\u7BA1\u7406",
71
- "\u5171\u4EAB\u7EC4\u4EF6"
72
- ],
67
+ features: ["bun workspace", "Monorepo", "\u591A\u5305\u7BA1\u7406", "\u5171\u4EAB\u7EC4\u4EF6"],
73
68
  version: "full"
74
69
  }
75
70
  }
@@ -82,12 +77,7 @@ var TEMPLATE_CATEGORIES = {
82
77
  description: "\u57FA\u4E8E MicroApp \u7684\u5FAE\u524D\u7AEF\u67B6\u6784\u65B9\u6848",
83
78
  repoUrl: "https://github.com/ChenyCHENYU/Robot_Admin",
84
79
  branch: "micro-app",
85
- features: [
86
- "MicroApp",
87
- "\u5FAE\u524D\u7AEF",
88
- "\u4E3B\u5B50\u5E94\u7528",
89
- "\u8DEF\u7531\u5171\u4EAB"
90
- ],
80
+ features: ["MicroApp", "\u5FAE\u524D\u7AEF", "\u4E3B\u5B50\u5E94\u7528", "\u8DEF\u7531\u5171\u4EAB"],
91
81
  version: "full"
92
82
  },
93
83
  "robot-module-federation": {
@@ -95,12 +85,7 @@ var TEMPLATE_CATEGORIES = {
95
85
  description: "\u57FA\u4E8E Vite Module Federation \u7684\u6A21\u5757\u8054\u90A6\u65B9\u6848",
96
86
  repoUrl: "https://github.com/ChenyCHENYU/Robot_Admin",
97
87
  branch: "module-federation",
98
- features: [
99
- "Module Federation",
100
- "\u6A21\u5757\u8054\u90A6",
101
- "Vite",
102
- "\u8FDC\u7A0B\u6A21\u5757"
103
- ],
88
+ features: ["Module Federation", "\u6A21\u5757\u8054\u90A6", "Vite", "\u8FDC\u7A0B\u6A21\u5757"],
104
89
  version: "full"
105
90
  }
106
91
  }
@@ -134,7 +119,7 @@ var TEMPLATE_CATEGORIES = {
134
119
  }
135
120
  },
136
121
  mobile: {
137
- name: "\u{1F4F1} \u79FB\u52A8\u7AEF\u9879\u76EE",
122
+ name: "\u79FB\u52A8\u7AEF\u9879\u76EE",
138
123
  stacks: {
139
124
  uniapp: {
140
125
  name: "uni-app",
@@ -163,7 +148,7 @@ var TEMPLATE_CATEGORIES = {
163
148
  }
164
149
  },
165
150
  backend: {
166
- name: "\u{1F680} \u540E\u7AEF\u9879\u76EE",
151
+ name: "\u540E\u7AEF\u9879\u76EE",
167
152
  stacks: {
168
153
  nestjs: {
169
154
  name: "NestJS",
@@ -211,7 +196,7 @@ var TEMPLATE_CATEGORIES = {
211
196
  }
212
197
  },
213
198
  desktop: {
214
- name: "\u{1F4BB} \u684C\u9762\u7AEF\u9879\u76EE",
199
+ name: "\u684C\u9762\u7AEF\u9879\u76EE",
215
200
  stacks: {
216
201
  electron: {
217
202
  name: "Electron",
@@ -243,6 +228,11 @@ var TEMPLATE_CATEGORIES = {
243
228
 
244
229
  // src/config/cli.config.ts
245
230
  var CACHE_DIR_NAME = "cache";
231
+ var VERSION_LABELS = {
232
+ full: "\u5B8C\u6574\u7248",
233
+ base: "\u7CBE\u7B80\u7248",
234
+ micro: "\u5FAE\u670D\u52A1\u7248"
235
+ };
246
236
  var RECOMMENDED_TEMPLATE_KEYS = [
247
237
  "robot-admin",
248
238
  "robot-monorepo",
@@ -317,7 +307,7 @@ async function getCachedTemplate(repoUrl) {
317
307
  }
318
308
  return null;
319
309
  }
320
- async function saveToCache(repoUrl, sourcePath) {
310
+ async function saveToCache(repoUrl, sourcePath, branch = "main") {
321
311
  try {
322
312
  const key = getCacheKey(repoUrl);
323
313
  const cachePath = path.join(CACHE_DIR, key);
@@ -330,7 +320,7 @@ async function saveToCache(repoUrl, sourcePath) {
330
320
  index.entries[key] = {
331
321
  repoUrl,
332
322
  downloadedAt: (/* @__PURE__ */ new Date()).toISOString(),
333
- branch: "main",
323
+ branch,
334
324
  size: stat.size
335
325
  };
336
326
  await saveCacheIndex(index);
@@ -348,35 +338,70 @@ async function getCacheStats() {
348
338
  async function clearCache() {
349
339
  await fs.remove(CACHE_DIR);
350
340
  }
341
+ var TIMEOUT_PRIMARY = 12e4;
342
+ var TIMEOUT_MIRROR = 6e4;
343
+ var MAX_RETRIES = 3;
344
+ function getGitHubMirrors(repoUrl) {
345
+ return [
346
+ repoUrl,
347
+ // 1. 原始 GitHub
348
+ repoUrl.replace("github.com", "hub.gitmirror.com"),
349
+ // 2. gitmirror
350
+ `https://ghproxy.net/${repoUrl}`
351
+ // 3. ghproxy.net
352
+ ];
353
+ }
354
+ async function fetchWithRetry(downloadUrl, timeout, retries) {
355
+ let lastError;
356
+ for (let attempt = 1; attempt <= retries; attempt++) {
357
+ try {
358
+ const response = await fetch(downloadUrl, {
359
+ signal: AbortSignal.timeout(timeout),
360
+ headers: { "User-Agent": "Robot-CLI" }
361
+ });
362
+ if (!response.ok) {
363
+ if (response.status === 404) throw new Error(`\u4ED3\u5E93\u4E0D\u5B58\u5728 (404)`);
364
+ throw new Error(`HTTP ${response.status}`);
365
+ }
366
+ return response;
367
+ } catch (error) {
368
+ lastError = error;
369
+ if (lastError.message.includes("404")) throw lastError;
370
+ if (attempt < retries) {
371
+ await new Promise((r) => setTimeout(r, 2e3 * attempt));
372
+ }
373
+ }
374
+ }
375
+ throw lastError;
376
+ }
351
377
  async function tryDownload(repoUrl, branch = "main", spinner) {
352
378
  const url = new URL(repoUrl);
353
379
  const host = url.hostname;
354
- const mirrors = host === "github.com" ? [repoUrl, `https://ghproxy.com/${repoUrl}`] : [repoUrl];
380
+ const mirrors = host === "github.com" ? getGitHubMirrors(repoUrl) : [repoUrl];
355
381
  for (let i = 0; i < mirrors.length; i++) {
356
382
  const current = mirrors[i];
357
- const isOriginal = current === repoUrl;
358
- const sourceName = isOriginal ? `${host} \u5B98\u65B9` : `${host} \u955C\u50CF`;
383
+ const isOriginal = i === 0;
384
+ let sourceName;
359
385
  try {
360
- if (spinner) spinner.text = `\u{1F50D} \u8FDE\u63A5\u5230 ${sourceName}...`;
386
+ sourceName = isOriginal ? host : new URL(current.replace(/^(https?:\/\/[^/]+)\/.*/, "$1")).hostname;
387
+ } catch {
388
+ sourceName = `\u955C\u50CF ${i}`;
389
+ }
390
+ try {
391
+ if (spinner) spinner.text = `\u8FDE\u63A5 ${sourceName} ...`;
361
392
  const downloadUrl = current.endsWith(".zip") ? current : buildDownloadUrl(current, branch);
362
- if (spinner) spinner.text = `\u{1F4E6} \u4ECE ${sourceName} \u4E0B\u8F7D\u6A21\u677F...`;
363
- const response = await fetch(downloadUrl, {
364
- signal: AbortSignal.timeout(isOriginal ? 15e3 : 1e4),
365
- headers: { "User-Agent": "Robot-CLI/2.0.0" }
366
- });
367
- if (!response.ok) {
368
- if (response.status === 404) throw new Error(`\u4ED3\u5E93\u4E0D\u5B58\u5728: ${repoUrl}`);
369
- throw new Error(`HTTP ${response.status}`);
370
- }
393
+ const timeout = isOriginal ? TIMEOUT_PRIMARY : TIMEOUT_MIRROR;
394
+ if (spinner) spinner.text = `\u4ECE ${sourceName} \u4E0B\u8F7D\u6A21\u677F (\u6700\u591A\u91CD\u8BD5${MAX_RETRIES}\u6B21)...`;
395
+ const response = await fetchWithRetry(downloadUrl, timeout, MAX_RETRIES);
371
396
  if (spinner) {
372
397
  const len = response.headers.get("content-length");
373
398
  const sizeInfo = len ? `${(parseInt(len) / 1024 / 1024).toFixed(1)}MB ` : "";
374
- spinner.text = `\u{1F4E6} \u4E0B\u8F7D\u4E2D... (${sizeInfo}from ${sourceName})`;
399
+ spinner.text = `\u4E0B\u8F7D\u4E2D ${sizeInfo}(${sourceName})`;
375
400
  }
376
401
  return { response, sourceName };
377
402
  } catch (error) {
378
403
  if (i === mirrors.length - 1) throw error;
379
- if (spinner) spinner.text = `\u26A0\uFE0F ${sourceName} \u8BBF\u95EE\u5931\u8D25\uFF0C\u5C1D\u8BD5\u5176\u4ED6\u6E90...`;
404
+ if (spinner) spinner.text = `${sourceName} \u4E0D\u53EF\u7528\uFF0C\u5207\u6362\u4E0B\u4E00\u4E2A\u6E90...`;
380
405
  await new Promise((r) => setTimeout(r, 1e3));
381
406
  }
382
407
  }
@@ -389,21 +414,21 @@ async function downloadTemplate(template, options = {}) {
389
414
  throw new Error(`\u6A21\u677F\u914D\u7F6E\u65E0\u6548: ${JSON.stringify(template)}`);
390
415
  }
391
416
  try {
392
- if (spinner) spinner.text = "\u{1F310} \u5F00\u59CB\u4E0B\u8F7D\u6700\u65B0\u6A21\u677F...";
417
+ if (spinner) spinner.text = "\u5F00\u59CB\u4E0B\u8F7D\u6700\u65B0\u6A21\u677F...";
393
418
  const { response, sourceName } = await tryDownload(
394
419
  template.repoUrl,
395
420
  branch,
396
421
  spinner
397
422
  );
398
- if (spinner) spinner.text = "\u{1F4BE} \u4FDD\u5B58\u4E0B\u8F7D\u6587\u4EF6...";
423
+ if (spinner) spinner.text = "\u4FDD\u5B58\u4E0B\u8F7D\u6587\u4EF6...";
399
424
  const timestamp = Date.now();
400
425
  const tempZip = path.join(os.tmpdir(), `robot-template-${timestamp}.zip`);
401
426
  const tempExtract = path.join(os.tmpdir(), `robot-extract-${timestamp}`);
402
427
  const buffer = Buffer.from(await response.arrayBuffer());
403
428
  await fs.writeFile(tempZip, buffer);
404
- if (spinner) spinner.text = "\u{1F4C2} \u89E3\u538B\u6A21\u677F\u6587\u4EF6...";
429
+ if (spinner) spinner.text = "\u89E3\u538B\u6A21\u677F\u6587\u4EF6...";
405
430
  await extract(tempZip, { dir: tempExtract });
406
- if (spinner) spinner.text = "\u{1F50D} \u67E5\u627E\u9879\u76EE\u7ED3\u6784...";
431
+ if (spinner) spinner.text = "\u67E5\u627E\u9879\u76EE\u7ED3\u6784...";
407
432
  const extractedItems = await fs.readdir(tempExtract);
408
433
  const repoName = template.repoUrl.split("/").pop() || "";
409
434
  const projectDir = extractedItems.find(
@@ -415,15 +440,15 @@ async function downloadTemplate(template, options = {}) {
415
440
  );
416
441
  }
417
442
  const sourcePath = path.join(tempExtract, projectDir);
418
- if (spinner) spinner.text = "\u2705 \u9A8C\u8BC1\u6A21\u677F\u5B8C\u6574\u6027...";
443
+ if (spinner) spinner.text = "\u9A8C\u8BC1\u6A21\u677F\u5B8C\u6574\u6027...";
419
444
  if (!fs.existsSync(path.join(sourcePath, "package.json"))) {
420
445
  throw new Error("\u6A21\u677F\u7F3A\u5C11 package.json \u6587\u4EF6");
421
446
  }
422
447
  if (!noCache) {
423
- saveToCache(template.repoUrl, sourcePath).catch(() => {
448
+ saveToCache(template.repoUrl, sourcePath, branch).catch(() => {
424
449
  });
425
450
  }
426
- if (spinner) spinner.text = `\u{1F389} \u6A21\u677F\u4E0B\u8F7D\u5B8C\u6210 (via ${sourceName})`;
451
+ if (spinner) spinner.text = `\u6A21\u677F\u4E0B\u8F7D\u5B8C\u6210 (via ${sourceName})`;
427
452
  await fs.remove(tempZip).catch(() => {
428
453
  });
429
454
  return sourcePath;
@@ -431,11 +456,9 @@ async function downloadTemplate(template, options = {}) {
431
456
  if (!noCache) {
432
457
  const cached = await getCachedTemplate(template.repoUrl);
433
458
  if (cached) {
434
- if (spinner) spinner.text = "\u{1F4E6} \u7F51\u7EDC\u4E0D\u53EF\u7528\uFF0C\u4F7F\u7528\u7F13\u5B58\u6A21\u677F...";
459
+ if (spinner) spinner.text = "\u7F51\u7EDC\u4E0D\u53EF\u7528\uFF0C\u4F7F\u7528\u7F13\u5B58\u6A21\u677F...";
435
460
  console.log();
436
- console.log(
437
- ` ${import("chalk").then((c) => c.default.yellow("\u26A0\uFE0F \u4F7F\u7528\u7F13\u5B58\u7248\u672C\uFF08\u975E\u6700\u65B0\uFF09"))}`
438
- );
461
+ console.log(` ${chalk.yellow(" \u6CE8\u610F: \u4F7F\u7528\u7F13\u5B58\u7248\u672C\uFF08\u975E\u6700\u65B0\uFF09")}`);
439
462
  return cached;
440
463
  }
441
464
  }
@@ -449,9 +472,13 @@ async function downloadTemplate(template, options = {}) {
449
472
  }
450
473
  } catch {
451
474
  }
452
- let msg = `\u6A21\u677F\u4E0B\u8F7D\u5931\u8D25: ${downloadError.message}`;
453
- if (downloadError.code === "ENOTFOUND") {
454
- msg += "\n\n\u{1F4A1} \u5EFA\u8BAE:\n1. \u68C0\u67E5\u7F51\u7EDC\u8FDE\u63A5\n2. \u5982\u679C\u5728\u56FD\u5185\uFF0C\u5C1D\u8BD5\u4F7F\u7528\u79D1\u5B66\u4E0A\u7F51\n3. \u7A0D\u540E\u91CD\u8BD5";
475
+ const errMsg = downloadError.message;
476
+ const isTimeout = errMsg.includes("aborted") || errMsg.includes("timeout") || downloadError.name === "TimeoutError";
477
+ let msg = `\u6A21\u677F\u4E0B\u8F7D\u5931\u8D25: ${errMsg}`;
478
+ if (isTimeout) {
479
+ msg += "\n\n \u5EFA\u8BAE:\n 1. \u5F53\u524D\u7F51\u7EDC\u8FDE\u63A5\u8F83\u6162\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\n 2. \u5982\u679C\u5728\u56FD\u5185\uFF0C\u5C1D\u8BD5\u4F7F\u7528\u4EE3\u7406\u6216\u79D1\u5B66\u4E0A\u7F51\n 3. \u4F7F\u7528 robot doctor \u68C0\u67E5\u7F51\u7EDC\u8FDE\u63A5";
480
+ } else if (downloadError.code === "ENOTFOUND") {
481
+ msg += "\n\n \u5EFA\u8BAE:\n 1. \u68C0\u67E5\u7F51\u7EDC\u8FDE\u63A5\u662F\u5426\u6B63\u5E38\n 2. \u5982\u679C\u5728\u56FD\u5185\uFF0C\u5C1D\u8BD5\u4F7F\u7528\u4EE3\u7406\n 3. \u7A0D\u540E\u91CD\u8BD5";
455
482
  }
456
483
  throw new Error(msg);
457
484
  }
@@ -528,7 +555,7 @@ function getCategoryForTemplate(templateKey) {
528
555
  // src/utils.ts
529
556
  import fs2 from "fs-extra";
530
557
  import path2 from "path";
531
- import chalk from "chalk";
558
+ import chalk2 from "chalk";
532
559
  import { execSync } from "child_process";
533
560
  function detectPackageManager() {
534
561
  const managers = [];
@@ -630,9 +657,9 @@ async function copyTemplate(sourcePath, targetPath, spinner) {
630
657
  throw new Error(`\u6E90\u8DEF\u5F84\u4E0D\u5B58\u5728: ${sourcePath}`);
631
658
  }
632
659
  await fs2.ensureDir(targetPath);
633
- if (spinner) spinner.text = "\u{1F4CA} \u7EDF\u8BA1\u6587\u4EF6\u6570\u91CF...";
660
+ if (spinner) spinner.text = "\u7EDF\u8BA1\u6587\u4EF6\u6570\u91CF...";
634
661
  const totalFiles = await countFiles(sourcePath);
635
- if (spinner) spinner.text = `\u{1F4CB} \u5F00\u59CB\u590D\u5236 ${totalFiles} \u4E2A\u6587\u4EF6...`;
662
+ if (spinner) spinner.text = `\u5F00\u59CB\u590D\u5236 ${totalFiles} \u4E2A\u6587\u4EF6...`;
636
663
  let copied = 0;
637
664
  const skipDirs = /* @__PURE__ */ new Set([
638
665
  "node_modules",
@@ -656,19 +683,19 @@ async function copyTemplate(sourcePath, targetPath, spinner) {
656
683
  copied++;
657
684
  if (spinner && (copied % 10 === 0 || copied === totalFiles)) {
658
685
  const pct = Math.round(copied / totalFiles * 100);
659
- spinner.text = `\u{1F4CB} \u590D\u5236\u4E2D... ${copied}/${totalFiles} (${pct}%)`;
686
+ spinner.text = `\u590D\u5236\u4E2D ${copied}/${totalFiles} (${pct}%)`;
660
687
  }
661
688
  }
662
689
  }
663
690
  }
664
691
  await copyDir(sourcePath, targetPath);
665
- if (spinner) spinner.text = `\u2705 \u6587\u4EF6\u590D\u5236\u5B8C\u6210 (${copied} \u4E2A\u6587\u4EF6)`;
692
+ if (spinner) spinner.text = `\u6587\u4EF6\u590D\u5236\u5B8C\u6210 (${copied} \u4E2A\u6587\u4EF6)`;
666
693
  }
667
694
  async function installDependencies(projectPath, spinner, packageManager = "npm") {
668
695
  try {
669
696
  const pkgJson = path2.join(projectPath, "package.json");
670
697
  if (!fs2.existsSync(pkgJson)) {
671
- if (spinner) spinner.text = "\u26A0\uFE0F \u8DF3\u8FC7\u4F9D\u8D56\u5B89\u88C5 (\u65E0 package.json)";
698
+ if (spinner) spinner.text = "\u8DF3\u8FC7\u4F9D\u8D56\u5B89\u88C5 (\u65E0 package.json)";
672
699
  return;
673
700
  }
674
701
  const cmds = {
@@ -677,22 +704,22 @@ async function installDependencies(projectPath, spinner, packageManager = "npm")
677
704
  yarn: "yarn install",
678
705
  npm: "npm install"
679
706
  };
680
- if (spinner) spinner.text = `\u{1F4E6} \u4F7F\u7528 ${packageManager} \u5B89\u88C5\u4F9D\u8D56...`;
707
+ if (spinner) spinner.text = `\u4F7F\u7528 ${packageManager} \u5B89\u88C5\u4F9D\u8D56...`;
681
708
  execSync(cmds[packageManager], {
682
709
  cwd: projectPath,
683
710
  stdio: "ignore",
684
711
  timeout: 3e5
685
712
  });
686
- if (spinner) spinner.text = `\u2705 \u4F9D\u8D56\u5B89\u88C5\u5B8C\u6210 (${packageManager})`;
713
+ if (spinner) spinner.text = `\u4F9D\u8D56\u5B89\u88C5\u5B8C\u6210 (${packageManager})`;
687
714
  } catch (error) {
688
- if (spinner) spinner.text = "\u26A0\uFE0F \u4F9D\u8D56\u5B89\u88C5\u5931\u8D25\uFF0C\u8BF7\u624B\u52A8\u5B89\u88C5";
715
+ if (spinner) spinner.text = "\u4F9D\u8D56\u5B89\u88C5\u5931\u8D25\uFF0C\u8BF7\u624B\u52A8\u5B89\u88C5";
689
716
  console.log();
690
- console.log(chalk.yellow("\u26A0\uFE0F \u81EA\u52A8\u5B89\u88C5\u4F9D\u8D56\u5931\u8D25"));
691
- console.log(chalk.dim(` \u9519\u8BEF: ${error.message}`));
717
+ console.log(chalk2.yellow("\u81EA\u52A8\u5B89\u88C5\u4F9D\u8D56\u5931\u8D25"));
718
+ console.log(chalk2.dim(` \u9519\u8BEF: ${error.message}`));
692
719
  console.log();
693
- console.log(chalk.blue("\u{1F4A1} \u8BF7\u624B\u52A8\u5B89\u88C5:"));
694
- console.log(chalk.cyan(` cd ${path2.basename(projectPath)}`));
695
- console.log(chalk.cyan(` ${packageManager} install`));
720
+ console.log(chalk2.blue("\u8BF7\u624B\u52A8\u5B89\u88C5:"));
721
+ console.log(chalk2.cyan(` cd ${path2.basename(projectPath)}`));
722
+ console.log(chalk2.cyan(` ${packageManager} install`));
696
723
  console.log();
697
724
  }
698
725
  }
@@ -730,15 +757,15 @@ async function generateProjectStats(projectPath) {
730
757
  }
731
758
  }
732
759
  function printProjectStats(stats) {
733
- console.log(chalk.blue("\u{1F4CA} \u9879\u76EE\u7EDF\u8BA1:"));
734
- console.log(` \u6587\u4EF6\u6570\u91CF: ${chalk.cyan(String(stats.files))} \u4E2A`);
735
- console.log(` \u76EE\u5F55\u6570\u91CF: ${chalk.cyan(String(stats.directories))} \u4E2A`);
736
- console.log(` \u9879\u76EE\u5927\u5C0F: ${chalk.cyan(formatBytes(stats.size))}`);
760
+ console.log(chalk2.blue("\u9879\u76EE\u7EDF\u8BA1:"));
761
+ console.log(` \u6587\u4EF6\u6570\u91CF: ${chalk2.cyan(String(stats.files))} \u4E2A`);
762
+ console.log(` \u76EE\u5F55\u6570\u91CF: ${chalk2.cyan(String(stats.directories))} \u4E2A`);
763
+ console.log(` \u9879\u76EE\u5927\u5C0F: ${chalk2.cyan(formatBytes(stats.size))}`);
737
764
  const top = Object.entries(stats.fileTypes).sort(([, a], [, b]) => b - a).slice(0, 5);
738
765
  if (top.length > 0) {
739
766
  console.log(" \u4E3B\u8981\u6587\u4EF6\u7C7B\u578B:");
740
767
  for (const [ext, count] of top) {
741
- console.log(` ${ext}: ${chalk.cyan(String(count))} \u4E2A`);
768
+ console.log(` ${ext}: ${chalk2.cyan(String(count))} \u4E2A`);
742
769
  }
743
770
  }
744
771
  }
@@ -751,9 +778,16 @@ function formatBytes(bytes) {
751
778
  }
752
779
 
753
780
  // src/create.ts
781
+ function getVersionLabel(version) {
782
+ const label = VERSION_LABELS[version] || version;
783
+ if (version === "full") return chalk3.green(`[${label}]`);
784
+ if (version === "micro") return chalk3.blue(`[${label}]`);
785
+ return chalk3.yellow(`[${label}]`);
786
+ }
787
+ var STRIP_VERSION_RE = /\s*(完整版|精简版|微服务版)\s*$/;
754
788
  async function createProject(projectName, options = {}) {
755
789
  console.log();
756
- console.log(chalk2.cyan("\u{1F680} Robot CLI - \u5F00\u59CB\u521B\u5EFA\u9879\u76EE"));
790
+ console.log(chalk3.cyan(" Robot CLI - \u5F00\u59CB\u521B\u5EFA\u9879\u76EE"));
757
791
  console.log();
758
792
  let template;
759
793
  if (options.from) {
@@ -765,7 +799,7 @@ async function createProject(projectName, options = {}) {
765
799
  features: [],
766
800
  version: "full"
767
801
  };
768
- console.log(chalk2.blue(`\u{1F4E6} \u4F7F\u7528\u81EA\u5B9A\u4E49\u6A21\u677F: ${chalk2.dim(options.from)}`));
802
+ console.log(chalk3.blue(`\u4F7F\u7528\u81EA\u5B9A\u4E49\u6A21\u677F: ${chalk3.dim(options.from)}`));
769
803
  console.log();
770
804
  } else {
771
805
  template = await selectTemplate(options.template);
@@ -776,29 +810,29 @@ async function createProject(projectName, options = {}) {
776
810
  if (options.dryRun) {
777
811
  console.log();
778
812
  console.log(
779
- chalk2.yellow("\u{1F50D} Dry Run \u6A21\u5F0F - \u4EE5\u4E0B\u4E3A\u9884\u89C8\u4FE1\u606F\uFF0C\u672A\u5B9E\u9645\u6267\u884C\u4EFB\u4F55\u64CD\u4F5C:")
813
+ chalk3.yellow("Dry Run \u6A21\u5F0F - \u4EE5\u4E0B\u4E3A\u9884\u89C8\u4FE1\u606F\uFF0C\u672A\u5B9E\u9645\u6267\u884C\u4EFB\u4F55\u64CD\u4F5C:")
780
814
  );
781
815
  console.log();
782
- console.log(` \u9879\u76EE\u8DEF\u5F84: ${chalk2.cyan(path3.resolve(finalProjectName))}`);
783
- console.log(` \u4E0B\u8F7D\u6765\u6E90: ${chalk2.dim(template.repoUrl)}`);
816
+ console.log(` \u9879\u76EE\u8DEF\u5F84: ${chalk3.cyan(path3.resolve(finalProjectName))}`);
817
+ console.log(` \u4E0B\u8F7D\u6765\u6E90: ${chalk3.dim(template.repoUrl)}`);
784
818
  console.log(" \u6267\u884C\u6B65\u9AA4:");
785
- console.log(chalk2.dim(` 1. \u4ECE ${template.repoUrl} \u4E0B\u8F7D\u6700\u65B0\u6A21\u677F`));
786
- console.log(chalk2.dim(` 2. \u89E3\u538B\u5E76\u590D\u5236\u5230 ./${finalProjectName}`));
819
+ console.log(chalk3.dim(` 1. \u4ECE ${template.repoUrl} \u4E0B\u8F7D\u6700\u65B0\u6A21\u677F`));
820
+ console.log(chalk3.dim(` 2. \u89E3\u538B\u5E76\u590D\u5236\u5230 ./${finalProjectName}`));
787
821
  console.log(
788
- chalk2.dim(" 3. \u66F4\u65B0 package.json (name, description, author)")
822
+ chalk3.dim(" 3. \u66F4\u65B0 package.json (name, description, author)")
789
823
  );
790
824
  let step = 4;
791
825
  if (projectConfig.initGit) {
792
- console.log(chalk2.dim(` ${step}. \u521D\u59CB\u5316 Git \u4ED3\u5E93\u5E76\u63D0\u4EA4\u521D\u59CB\u4EE3\u7801`));
826
+ console.log(chalk3.dim(` ${step}. \u521D\u59CB\u5316 Git \u4ED3\u5E93\u5E76\u63D0\u4EA4\u521D\u59CB\u4EE3\u7801`));
793
827
  step++;
794
828
  }
795
829
  if (projectConfig.installDeps) {
796
830
  console.log(
797
- chalk2.dim(` ${step}. \u4F7F\u7528 ${projectConfig.packageManager} \u5B89\u88C5\u4F9D\u8D56`)
831
+ chalk3.dim(` ${step}. \u4F7F\u7528 ${projectConfig.packageManager} \u5B89\u88C5\u4F9D\u8D56`)
798
832
  );
799
833
  }
800
834
  console.log();
801
- console.log(chalk2.dim("\u79FB\u9664 --dry-run \u53C2\u6570\u4EE5\u6267\u884C\u521B\u5EFA\u3002"));
835
+ console.log(chalk3.dim("\u79FB\u9664 --dry-run \u53C2\u6570\u4EE5\u6267\u884C\u521B\u5EFA\u3002"));
802
836
  console.log();
803
837
  return;
804
838
  }
@@ -808,8 +842,8 @@ async function handleProjectName(projectName, template) {
808
842
  if (projectName) {
809
843
  const v = validateProjectName(projectName);
810
844
  if (!v.valid) {
811
- console.log(chalk2.red("\u274C \u9879\u76EE\u540D\u79F0\u4E0D\u5408\u6CD5:"));
812
- v.errors.forEach((e) => console.log(chalk2.red(` ${e}`)));
845
+ console.log(chalk3.red("\u9879\u76EE\u540D\u79F0\u4E0D\u5408\u6CD5:"));
846
+ v.errors.forEach((e) => console.log(chalk3.red(` ${e}`)));
813
847
  console.log();
814
848
  const { newName } = await inquirer.prompt([
815
849
  {
@@ -854,15 +888,15 @@ async function selectTemplate(templateOption) {
854
888
  if (all[templateOption]) {
855
889
  return { key: templateOption, ...all[templateOption] };
856
890
  }
857
- console.log(chalk2.yellow(`\u26A0\uFE0F \u6A21\u677F "${templateOption}" \u4E0D\u5B58\u5728`));
891
+ console.log(chalk3.yellow(`\u6A21\u677F "${templateOption}" \u4E0D\u5B58\u5728`));
858
892
  console.log();
859
893
  }
860
894
  return await selectTemplateMethod();
861
895
  }
862
896
  async function selectTemplateMethod() {
863
897
  console.log();
864
- console.log(chalk2.blue.bold("\u{1F3AF} \u9009\u62E9\u6A21\u677F\u521B\u5EFA\u65B9\u5F0F"));
865
- console.log(chalk2.dim("\u8BF7\u9009\u62E9\u6700\u9002\u5408\u4F60\u7684\u6A21\u677F\u6D4F\u89C8\u65B9\u5F0F"));
898
+ console.log(chalk3.bold(" \u9009\u62E9\u6A21\u677F\u521B\u5EFA\u65B9\u5F0F"));
899
+ console.log(chalk3.dim(" \u8BF7\u9009\u62E9\u6700\u9002\u5408\u4F60\u7684\u6A21\u677F\u6D4F\u89C8\u65B9\u5F0F"));
866
900
  console.log();
867
901
  const { selectionMode } = await inquirer.prompt([
868
902
  {
@@ -871,22 +905,19 @@ async function selectTemplateMethod() {
871
905
  message: "\u6A21\u677F\u9009\u62E9\u65B9\u5F0F:",
872
906
  choices: [
873
907
  {
874
- name: `\u25CF ${chalk2.bold("\u63A8\u8350\u6A21\u677F")} ${chalk2.dim("(\u5E38\u7528\u6A21\u677F\u5FEB\u901F\u9009\u62E9) - \u57FA\u4E8E\u56E2\u961F\u4F7F\u7528\u9891\u7387\u63A8\u8350\u7684\u70ED\u95E8\u6A21\u677F")}`,
908
+ name: `${chalk3.cyan(">")} ${chalk3.bold("\u63A8\u8350\u6A21\u677F")} ${chalk3.dim("\u2014 \u57FA\u4E8E\u56E2\u961F\u4F7F\u7528\u9891\u7387\u63A8\u8350\u7684\u70ED\u95E8\u6A21\u677F")}`,
875
909
  value: "recommended"
876
910
  },
877
- { name: chalk2.dim("\u2500".repeat(70)), value: "sep1", disabled: true },
878
911
  {
879
- name: `\u25CF ${chalk2.bold("\u5206\u7C7B\u6A21\u677F")} ${chalk2.dim("(\u6309\u9879\u76EE\u7C7B\u578B\u5206\u7C7B\u9009\u62E9) - \u524D\u7AEF\u3001\u540E\u7AEF\u3001\u79FB\u52A8\u7AEF\u3001\u684C\u9762\u7AEF\u5206\u7C7B\u6D4F\u89C8")}`,
912
+ name: `${chalk3.cyan(">")} ${chalk3.bold("\u5206\u7C7B\u6D4F\u89C8")} ${chalk3.dim("\u2014 \u524D\u7AEF\u3001\u540E\u7AEF\u3001\u79FB\u52A8\u7AEF\u3001\u684C\u9762\u7AEF\u5206\u7C7B")}`,
880
913
  value: "category"
881
914
  },
882
- { name: chalk2.dim("\u2500".repeat(70)), value: "sep2", disabled: true },
883
915
  {
884
- name: `\u25CF ${chalk2.bold("\u641C\u7D22\u6A21\u677F")} ${chalk2.dim("(\u5173\u952E\u8BCD\u641C\u7D22) - \u901A\u8FC7\u6280\u672F\u6808\u3001\u529F\u80FD\u7279\u6027\u7B49\u5173\u952E\u8BCD\u5FEB\u901F\u67E5\u627E")}`,
916
+ name: `${chalk3.cyan(">")} ${chalk3.bold("\u5173\u952E\u8BCD\u641C\u7D22")} ${chalk3.dim("\u2014 \u6309\u6280\u672F\u6808\u3001\u529F\u80FD\u7279\u6027\u67E5\u627E")}`,
885
917
  value: "search"
886
918
  },
887
- { name: chalk2.dim("\u2500".repeat(70)), value: "sep3", disabled: true },
888
919
  {
889
- name: `\u25CF ${chalk2.bold("\u5168\u90E8\u6A21\u677F")} ${chalk2.dim("(\u67E5\u770B\u6240\u6709\u53EF\u7528\u6A21\u677F) - \u6309\u5206\u7C7B\u5C55\u793A\u6240\u6709\u53EF\u7528\u7684\u9879\u76EE\u6A21\u677F")}`,
920
+ name: `${chalk3.cyan(">")} ${chalk3.bold("\u5168\u90E8\u6A21\u677F")} ${chalk3.dim("\u2014 \u67E5\u770B\u6240\u6709\u53EF\u7528\u6A21\u677F")}`,
890
921
  value: "all"
891
922
  }
892
923
  ],
@@ -909,33 +940,33 @@ async function selectTemplateMethod() {
909
940
  async function selectFromRecommended() {
910
941
  const recommended = getRecommendedTemplates();
911
942
  if (Object.keys(recommended).length === 0) {
912
- console.log(chalk2.yellow("\u26A0\uFE0F \u6682\u65E0\u63A8\u8350\u6A21\u677F"));
943
+ console.log(chalk3.yellow("\u6682\u65E0\u63A8\u8350\u6A21\u677F"));
913
944
  return await selectTemplateMethod();
914
945
  }
915
946
  console.log();
916
- console.log(chalk2.blue.bold("\u{1F3AF} \u63A8\u8350\u6A21\u677F"));
917
- console.log(chalk2.dim("\u57FA\u4E8E\u56E2\u961F\u4F7F\u7528\u9891\u7387\u548C\u9879\u76EE\u6210\u719F\u5EA6\u63A8\u8350"));
947
+ console.log(chalk3.bold(" \u63A8\u8350\u6A21\u677F"));
948
+ console.log(chalk3.dim(" \u57FA\u4E8E\u56E2\u961F\u4F7F\u7528\u9891\u7387\u548C\u9879\u76EE\u6210\u719F\u5EA6\u63A8\u8350"));
918
949
  console.log();
919
950
  const choices = [];
920
951
  const entries = Object.entries(recommended);
921
952
  entries.forEach(([key, template], index) => {
922
- const tags = template.features.slice(0, 3).map((f) => chalk2.dim(`[${f}]`)).join(" ");
923
- const ver = template.version === "full" ? chalk2.green("[\u5B8C\u6574\u7248]") : chalk2.yellow("[\u7CBE\u7B80\u7248]");
953
+ const tags = template.features.slice(0, 3).map((f) => chalk3.dim(`[${f}]`)).join(" ");
954
+ const ver = getVersionLabel(template.version);
924
955
  choices.push({
925
- name: `${chalk2.bold.white(template.name.replace(/\s*(完整版|精简版)\s*$/, ""))} ${ver} - ${chalk2.dim(template.description)}
926
- ${tags}${template.features.length > 3 ? chalk2.dim(` +${template.features.length - 3}more`) : ""}`,
956
+ name: `${chalk3.bold.white(template.name.replace(STRIP_VERSION_RE, ""))} ${ver} - ${chalk3.dim(template.description)}
957
+ ${tags}${template.features.length > 3 ? chalk3.dim(` +${template.features.length - 3}more`) : ""}`,
927
958
  value: { key, ...template },
928
959
  short: template.name
929
960
  });
930
961
  if (index < entries.length - 1) {
931
962
  choices.push({
932
- name: chalk2.dim("\u2500".repeat(70)),
963
+ name: chalk3.dim("\u2500".repeat(70)),
933
964
  value: `sep_${index}`,
934
965
  disabled: true
935
966
  });
936
967
  }
937
968
  });
938
- choices.push({ name: chalk2.dim("\u2B05\uFE0F \u8FD4\u56DE\u9009\u62E9\u5176\u4ED6\u65B9\u5F0F"), value: "back" });
969
+ choices.push({ name: chalk3.dim(" <- \u8FD4\u56DE\u9009\u62E9\u5176\u4ED6\u65B9\u5F0F"), value: "back" });
939
970
  const { selectedTemplate } = await inquirer.prompt([
940
971
  {
941
972
  type: "list",
@@ -970,7 +1001,7 @@ async function selectCategory() {
970
1001
  value: key
971
1002
  }));
972
1003
  choices.push({
973
- name: chalk2.dim("\u2190 \u8FD4\u56DE\u6A21\u677F\u9009\u62E9\u65B9\u5F0F"),
1004
+ name: chalk3.dim("\u2190 \u8FD4\u56DE\u6A21\u677F\u9009\u62E9\u65B9\u5F0F"),
974
1005
  value: "back_to_method"
975
1006
  });
976
1007
  const { categoryKey } = await inquirer.prompt([
@@ -986,12 +1017,12 @@ async function selectStack(categoryKey) {
986
1017
  }));
987
1018
  choices.push(
988
1019
  {
989
- name: chalk2.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),
1020
+ name: chalk3.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),
990
1021
  value: "separator",
991
1022
  disabled: true
992
1023
  },
993
- { name: chalk2.dim("\u2190 \u8FD4\u56DE\u9879\u76EE\u7C7B\u578B\u9009\u62E9"), value: "back_to_category" },
994
- { name: chalk2.dim("\u2190 \u8FD4\u56DE\u6A21\u677F\u9009\u62E9\u65B9\u5F0F"), value: "back_to_method" }
1024
+ { name: chalk3.dim("\u2190 \u8FD4\u56DE\u9879\u76EE\u7C7B\u578B\u9009\u62E9"), value: "back_to_category" },
1025
+ { name: chalk3.dim("\u2190 \u8FD4\u56DE\u6A21\u677F\u9009\u62E9\u65B9\u5F0F"), value: "back_to_method" }
995
1026
  );
996
1027
  if (choices.length === 4) return choices[0].value;
997
1028
  const { stackKey } = await inquirer.prompt([
@@ -1009,13 +1040,13 @@ async function selectPattern(catKey, stackKey) {
1009
1040
  }));
1010
1041
  choices.push(
1011
1042
  {
1012
- name: chalk2.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),
1043
+ name: chalk3.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),
1013
1044
  value: "separator",
1014
1045
  disabled: true
1015
1046
  },
1016
- { name: chalk2.dim("\u2190 \u8FD4\u56DE\u6280\u672F\u6808\u9009\u62E9"), value: "back_to_stack" },
1017
- { name: chalk2.dim("\u2190 \u8FD4\u56DE\u9879\u76EE\u7C7B\u578B\u9009\u62E9"), value: "back_to_category" },
1018
- { name: chalk2.dim("\u2190 \u8FD4\u56DE\u6A21\u677F\u9009\u62E9\u65B9\u5F0F"), value: "back_to_method" }
1047
+ { name: chalk3.dim("\u2190 \u8FD4\u56DE\u6280\u672F\u6808\u9009\u62E9"), value: "back_to_stack" },
1048
+ { name: chalk3.dim("\u2190 \u8FD4\u56DE\u9879\u76EE\u7C7B\u578B\u9009\u62E9"), value: "back_to_category" },
1049
+ { name: chalk3.dim("\u2190 \u8FD4\u56DE\u6A21\u677F\u9009\u62E9\u65B9\u5F0F"), value: "back_to_method" }
1019
1050
  );
1020
1051
  if (choices.length === 5) return choices[0].value;
1021
1052
  const { patternKey } = await inquirer.prompt([
@@ -1029,20 +1060,20 @@ async function selectSpecificTemplate(catKey, stackKey, patternKey) {
1029
1060
  }
1030
1061
  const templates = getTemplatesByCategory(catKey, stackKey, patternKey);
1031
1062
  const choices = Object.entries(templates).map(([key, t]) => ({
1032
- name: `${t.name} - ${chalk2.dim(t.description)}`,
1063
+ name: `${t.name} - ${chalk3.dim(t.description)}`,
1033
1064
  value: { key, ...t },
1034
1065
  short: t.name
1035
1066
  }));
1036
1067
  choices.push(
1037
1068
  {
1038
- name: chalk2.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),
1069
+ name: chalk3.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),
1039
1070
  value: "separator",
1040
1071
  disabled: true
1041
1072
  },
1042
- { name: chalk2.dim("\u2190 \u8FD4\u56DE\u67B6\u6784\u6A21\u5F0F\u9009\u62E9"), value: "back_to_pattern" },
1043
- { name: chalk2.dim("\u2190 \u8FD4\u56DE\u6280\u672F\u6808\u9009\u62E9"), value: "back_to_stack" },
1044
- { name: chalk2.dim("\u2190 \u8FD4\u56DE\u9879\u76EE\u7C7B\u578B\u9009\u62E9"), value: "back_to_category" },
1045
- { name: chalk2.dim("\u2190 \u8FD4\u56DE\u6A21\u677F\u9009\u62E9\u65B9\u5F0F"), value: "back_to_method" }
1073
+ { name: chalk3.dim("\u2190 \u8FD4\u56DE\u67B6\u6784\u6A21\u5F0F\u9009\u62E9"), value: "back_to_pattern" },
1074
+ { name: chalk3.dim("\u2190 \u8FD4\u56DE\u6280\u672F\u6808\u9009\u62E9"), value: "back_to_stack" },
1075
+ { name: chalk3.dim("\u2190 \u8FD4\u56DE\u9879\u76EE\u7C7B\u578B\u9009\u62E9"), value: "back_to_category" },
1076
+ { name: chalk3.dim("\u2190 \u8FD4\u56DE\u6A21\u677F\u9009\u62E9\u65B9\u5F0F"), value: "back_to_method" }
1046
1077
  );
1047
1078
  const { selectedTemplate } = await inquirer.prompt([
1048
1079
  {
@@ -1067,8 +1098,8 @@ async function selectBySearch() {
1067
1098
  const results = searchTemplates(keyword);
1068
1099
  if (Object.keys(results).length === 0) {
1069
1100
  console.log();
1070
- console.log(chalk2.yellow("\u{1F50D} \u6CA1\u6709\u627E\u5230\u5339\u914D\u7684\u6A21\u677F"));
1071
- console.log(chalk2.dim(`\u641C\u7D22\u5173\u952E\u8BCD: "${keyword}"`));
1101
+ console.log(chalk3.yellow("\u6CA1\u6709\u627E\u5230\u5339\u914D\u7684\u6A21\u677F"));
1102
+ console.log(chalk3.dim(`\u641C\u7D22\u5173\u952E\u8BCD: "${keyword}"`));
1072
1103
  console.log();
1073
1104
  const { action } = await inquirer.prompt([
1074
1105
  {
@@ -1076,8 +1107,8 @@ async function selectBySearch() {
1076
1107
  name: "action",
1077
1108
  message: "\u8BF7\u9009\u62E9\u4E0B\u4E00\u6B65\u64CD\u4F5C:",
1078
1109
  choices: [
1079
- { name: "\u{1F50D} \u91CD\u65B0\u641C\u7D22", value: "retry" },
1080
- { name: "\u2B05\uFE0F \u8FD4\u56DE\u6A21\u677F\u9009\u62E9\u65B9\u5F0F", value: "back" }
1110
+ { name: "\u91CD\u65B0\u641C\u7D22", value: "retry" },
1111
+ { name: chalk3.dim("<- \u8FD4\u56DE\u6A21\u677F\u9009\u62E9\u65B9\u5F0F"), value: "back" }
1081
1112
  ]
1082
1113
  }
1083
1114
  ]);
@@ -1085,9 +1116,9 @@ async function selectBySearch() {
1085
1116
  return await selectTemplateMethod();
1086
1117
  }
1087
1118
  console.log();
1088
- console.log(chalk2.green.bold("\u{1F50D} \u641C\u7D22\u7ED3\u679C"));
1119
+ console.log(chalk3.bold(" \u641C\u7D22\u7ED3\u679C"));
1089
1120
  console.log(
1090
- chalk2.dim(
1121
+ chalk3.dim(
1091
1122
  `\u5173\u952E\u8BCD: "${keyword}" \u2022 \u627E\u5230 ${Object.keys(results).length} \u4E2A\u5339\u914D\u6A21\u677F`
1092
1123
  )
1093
1124
  );
@@ -1095,23 +1126,23 @@ async function selectBySearch() {
1095
1126
  const choices = Object.entries(results).map(([key, t]) => {
1096
1127
  const hl = (text) => text.replace(
1097
1128
  new RegExp(`(${keyword})`, "gi"),
1098
- chalk2.bgYellow.black("$1")
1129
+ chalk3.bgYellow.black("$1")
1099
1130
  );
1100
- const ver = t.version === "full" ? chalk2.green("[\u5B8C\u6574\u7248]") : chalk2.yellow("[\u7CBE\u7B80\u7248]");
1131
+ const ver = getVersionLabel(t.version);
1101
1132
  const info = t.features.slice(0, 2).join(" \u2022 ");
1102
1133
  return {
1103
- name: `${chalk2.bold(hl(t.name.replace(/\s*(完整版|精简版)\s*$/, "")))} ${ver}
1104
- ${chalk2.dim(hl(t.description))}
1105
- ${chalk2.dim(`${info} \u2022 key: ${key}`)}
1106
- ${chalk2.dim("\u2500".repeat(60))}`,
1134
+ name: `${chalk3.bold(hl(t.name.replace(STRIP_VERSION_RE, "")))} ${ver}
1135
+ ${chalk3.dim(hl(t.description))}
1136
+ ${chalk3.dim(`${info} \u2022 key: ${key}`)}
1137
+ ${chalk3.dim("\u2500".repeat(60))}`,
1107
1138
  value: { key, ...t },
1108
1139
  short: t.name
1109
1140
  };
1110
1141
  });
1111
1142
  choices.push(
1112
- { name: chalk2.dim("\u2501".repeat(70)), value: "separator", disabled: true },
1113
- { name: "\u{1F50D} \u91CD\u65B0\u641C\u7D22", value: "search_again" },
1114
- { name: "\u2B05\uFE0F \u8FD4\u56DE\u6A21\u677F\u9009\u62E9\u65B9\u5F0F", value: "back_to_mode" }
1143
+ { name: chalk3.dim("\u2501".repeat(70)), value: "separator", disabled: true },
1144
+ { name: "\u91CD\u65B0\u641C\u7D22", value: "search_again" },
1145
+ { name: chalk3.dim("<- \u8FD4\u56DE\u6A21\u677F\u9009\u62E9\u65B9\u5F0F"), value: "back_to_mode" }
1115
1146
  );
1116
1147
  const { selectedTemplate } = await inquirer.prompt([
1117
1148
  {
@@ -1132,28 +1163,28 @@ async function selectBySearch() {
1132
1163
  async function selectFromAll() {
1133
1164
  const allTemplates = getAllTemplates();
1134
1165
  console.log();
1135
- console.log(chalk2.blue.bold("\u{1F4CB} \u6240\u6709\u53EF\u7528\u6A21\u677F"));
1136
- console.log(chalk2.dim(`\u5171 ${Object.keys(allTemplates).length} \u4E2A\u6A21\u677F\u53EF\u9009`));
1166
+ console.log(chalk3.bold(" \u6240\u6709\u53EF\u7528\u6A21\u677F"));
1167
+ console.log(chalk3.dim(` \u5171 ${Object.keys(allTemplates).length} \u4E2A\u6A21\u677F\u53EF\u9009`));
1137
1168
  console.log();
1138
1169
  const categorizedChoices = [];
1139
1170
  for (const [_catKey, category] of Object.entries(TEMPLATE_CATEGORIES)) {
1140
1171
  categorizedChoices.push({
1141
- name: chalk2.yellow.bold(category.name),
1172
+ name: chalk3.yellow.bold(category.name),
1142
1173
  value: `${_catKey}_header`,
1143
1174
  disabled: true
1144
1175
  });
1145
1176
  for (const [_sKey, stack] of Object.entries(category.stacks)) {
1146
1177
  for (const _pattern of Object.values(stack.patterns)) {
1147
1178
  for (const [key, t] of Object.entries(_pattern.templates)) {
1148
- const ver = t.version === "full" ? chalk2.green("[\u5B8C\u6574\u7248]") : chalk2.yellow("[\u7CBE\u7B80\u7248]");
1179
+ const ver = getVersionLabel(t.version);
1149
1180
  categorizedChoices.push({
1150
- name: ` \u25CF ${chalk2.bold(t.name.replace(/\s*(完整版|精简版)\s*$/, ""))} ${ver} - ${chalk2.dim(t.description)}
1151
- ${chalk2.dim(`\u6280\u672F\u6808: ${stack.name} \u2022 \u547D\u4EE4: robot create my-app -t ${key}`)}`,
1181
+ name: ` \u25CF ${chalk3.bold(t.name.replace(STRIP_VERSION_RE, ""))} ${ver} - ${chalk3.dim(t.description)}
1182
+ ${chalk3.dim(`\u6280\u672F\u6808: ${stack.name} \u2022 \u547D\u4EE4: robot create my-app -t ${key}`)}`,
1152
1183
  value: { key, ...t },
1153
1184
  short: t.name
1154
1185
  });
1155
1186
  categorizedChoices.push({
1156
- name: chalk2.dim(" " + "\u2500".repeat(66)),
1187
+ name: chalk3.dim(" " + "\u2500".repeat(66)),
1157
1188
  value: `sep_${key}`,
1158
1189
  disabled: true
1159
1190
  });
@@ -1162,8 +1193,8 @@ async function selectFromAll() {
1162
1193
  }
1163
1194
  }
1164
1195
  categorizedChoices.push(
1165
- { name: chalk2.dim("\u2501".repeat(70)), value: "separator", disabled: true },
1166
- { name: chalk2.dim("\u2B05\uFE0F \u8FD4\u56DE\u6A21\u677F\u9009\u62E9\u65B9\u5F0F"), value: "back_to_mode" }
1196
+ { name: chalk3.dim("\u2501".repeat(70)), value: "separator", disabled: true },
1197
+ { name: chalk3.dim("<- \u8FD4\u56DE\u6A21\u677F\u9009\u62E9\u65B9\u5F0F"), value: "back_to_mode" }
1167
1198
  );
1168
1199
  const { selectedTemplate } = await inquirer.prompt([
1169
1200
  {
@@ -1180,7 +1211,7 @@ async function selectFromAll() {
1180
1211
  }
1181
1212
  async function configureProject(options) {
1182
1213
  console.log();
1183
- console.log(chalk2.blue("\u2699\uFE0F \u9879\u76EE\u914D\u7F6E"));
1214
+ console.log(chalk3.bold(" \u9879\u76EE\u914D\u7F6E"));
1184
1215
  console.log();
1185
1216
  const available = detectPackageManager();
1186
1217
  const hasBun = available.includes("bun");
@@ -1261,37 +1292,37 @@ async function configureProject(options) {
1261
1292
  name: "action",
1262
1293
  message: "\u8BF7\u9009\u62E9\u64CD\u4F5C:",
1263
1294
  choices: [
1264
- { name: "\u{1F504} \u91CD\u65B0\u914D\u7F6E", value: "reconfigure" },
1265
- { name: "\u274C \u53D6\u6D88\u521B\u5EFA", value: "cancel" }
1295
+ { name: "\u91CD\u65B0\u914D\u7F6E", value: "reconfigure" },
1296
+ { name: "\u53D6\u6D88\u521B\u5EFA", value: "cancel" }
1266
1297
  ]
1267
1298
  }
1268
1299
  ]);
1269
1300
  if (action === "reconfigure") return await configureProject(options);
1270
- console.log(chalk2.yellow("\u274C \u53D6\u6D88\u521B\u5EFA\u9879\u76EE"));
1301
+ console.log(chalk3.yellow("\u53D6\u6D88\u521B\u5EFA\u9879\u76EE"));
1271
1302
  process.exit(0);
1272
1303
  }
1273
1304
  return config;
1274
1305
  }
1275
1306
  async function confirmCreation(projectName, template, config) {
1276
1307
  console.log();
1277
- console.log(chalk2.blue("\u{1F4CB} \u9879\u76EE\u521B\u5EFA\u4FE1\u606F\u786E\u8BA4:"));
1308
+ console.log(chalk3.bold(" \u9879\u76EE\u521B\u5EFA\u4FE1\u606F\u786E\u8BA4:"));
1278
1309
  console.log();
1279
- console.log(` \u9879\u76EE\u540D\u79F0: ${chalk2.cyan(projectName)}`);
1280
- console.log(` \u9009\u62E9\u6A21\u677F: ${chalk2.cyan(template.name)}`);
1281
- console.log(` \u6A21\u677F\u63CF\u8FF0: ${chalk2.dim(template.description)}`);
1310
+ console.log(` \u9879\u76EE\u540D\u79F0: ${chalk3.cyan(projectName)}`);
1311
+ console.log(` \u9009\u62E9\u6A21\u677F: ${chalk3.cyan(template.name)}`);
1312
+ console.log(` \u6A21\u677F\u63CF\u8FF0: ${chalk3.dim(template.description)}`);
1282
1313
  console.log(
1283
- ` \u5305\u542B\u529F\u80FD: ${chalk2.dim(template.features.join(", ") || "\u81EA\u5B9A\u4E49\u6A21\u677F")}`
1314
+ ` \u5305\u542B\u529F\u80FD: ${chalk3.dim(template.features.join(", ") || "\u81EA\u5B9A\u4E49\u6A21\u677F")}`
1284
1315
  );
1285
1316
  if (config.description)
1286
- console.log(` \u9879\u76EE\u63CF\u8FF0: ${chalk2.dim(config.description)}`);
1287
- if (config.author) console.log(` \u4F5C\u3000\u3000\u8005: ${chalk2.dim(config.author)}`);
1317
+ console.log(` \u9879\u76EE\u63CF\u8FF0: ${chalk3.dim(config.description)}`);
1318
+ if (config.author) console.log(` \u4F5C\u3000\u3000\u8005: ${chalk3.dim(config.author)}`);
1288
1319
  console.log(
1289
- ` \u521D\u59CB\u5316Git: ${config.initGit ? chalk2.green("\u662F") : chalk2.dim("\u5426")}`
1320
+ ` \u521D\u59CB\u5316Git: ${config.initGit ? chalk3.green("\u662F") : chalk3.dim("\u5426")}`
1290
1321
  );
1291
1322
  console.log(
1292
- ` \u5B89\u88C5\u4F9D\u8D56: ${config.installDeps ? chalk2.green("\u662F") + chalk2.dim(` (${config.packageManager})`) : chalk2.dim("\u5426")}`
1323
+ ` \u5B89\u88C5\u4F9D\u8D56: ${config.installDeps ? chalk3.green("\u662F") + chalk3.dim(` (${config.packageManager})`) : chalk3.dim("\u5426")}`
1293
1324
  );
1294
- console.log(` \u6E90\u7801\u4ED3\u5E93: ${chalk2.dim(template.repoUrl)}`);
1325
+ console.log(` \u6E90\u7801\u4ED3\u5E93: ${chalk3.dim(template.repoUrl)}`);
1295
1326
  console.log();
1296
1327
  const { confirmed } = await inquirer.prompt([
1297
1328
  {
@@ -1302,7 +1333,7 @@ async function confirmCreation(projectName, template, config) {
1302
1333
  }
1303
1334
  ]);
1304
1335
  if (!confirmed) {
1305
- console.log(chalk2.yellow("\u274C \u53D6\u6D88\u521B\u5EFA"));
1336
+ console.log(chalk3.yellow("\u53D6\u6D88\u521B\u5EFA"));
1306
1337
  process.exit(0);
1307
1338
  }
1308
1339
  }
@@ -1311,17 +1342,17 @@ async function executeCreation(projectName, template, config, options) {
1311
1342
  if (!template?.name)
1312
1343
  throw new Error(`\u6A21\u677F\u6570\u636E\u65E0\u6548: ${JSON.stringify(template)}`);
1313
1344
  const spinner = ora({
1314
- text: "\u{1F680} \u51C6\u5907\u521B\u5EFA\u9879\u76EE...",
1345
+ text: "\u51C6\u5907\u521B\u5EFA\u9879\u76EE...",
1315
1346
  spinner: "dots",
1316
1347
  color: "cyan"
1317
1348
  }).start();
1318
1349
  let tempPath;
1319
1350
  try {
1320
- spinner.text = "\u{1F4C1} \u68C0\u67E5\u9879\u76EE\u76EE\u5F55...";
1351
+ spinner.text = "\u68C0\u67E5\u9879\u76EE\u76EE\u5F55...";
1321
1352
  const projectPath = path3.resolve(projectName);
1322
1353
  if (fs3.existsSync(projectPath)) {
1323
1354
  spinner.stop();
1324
- console.log(chalk2.yellow("\u26A0\uFE0F \u9879\u76EE\u76EE\u5F55\u5DF2\u5B58\u5728"));
1355
+ console.log(chalk3.yellow("\u9879\u76EE\u76EE\u5F55\u5DF2\u5B58\u5728"));
1325
1356
  const { overwrite } = await inquirer.prompt([
1326
1357
  {
1327
1358
  type: "confirm",
@@ -1331,14 +1362,14 @@ async function executeCreation(projectName, template, config, options) {
1331
1362
  }
1332
1363
  ]);
1333
1364
  if (!overwrite) {
1334
- console.log(chalk2.yellow("\u274C \u53D6\u6D88\u521B\u5EFA"));
1365
+ console.log(chalk3.yellow("\u53D6\u6D88\u521B\u5EFA"));
1335
1366
  process.exit(0);
1336
1367
  }
1337
- spinner.start("\u{1F5D1}\uFE0F \u6E05\u7406\u73B0\u6709\u76EE\u5F55...");
1368
+ spinner.start("\u6E05\u7406\u73B0\u6709\u76EE\u5F55...");
1338
1369
  await fs3.remove(projectPath);
1339
- spinner.text = "\u{1F4C1} \u51C6\u5907\u521B\u5EFA\u65B0\u76EE\u5F55...";
1370
+ spinner.text = "\u51C6\u5907\u521B\u5EFA\u65B0\u76EE\u5F55...";
1340
1371
  }
1341
- spinner.text = "\u{1F310} \u4E0B\u8F7D\u6700\u65B0\u6A21\u677F...";
1372
+ spinner.text = "\u4E0B\u8F7D\u6700\u65B0\u6A21\u677F...";
1342
1373
  try {
1343
1374
  tempPath = await downloadTemplate(template, {
1344
1375
  spinner,
@@ -1349,57 +1380,56 @@ async function executeCreation(projectName, template, config, options) {
1349
1380
  } catch (error) {
1350
1381
  spinner.fail("\u6A21\u677F\u4E0B\u8F7D\u5931\u8D25");
1351
1382
  console.log();
1352
- console.log(chalk2.red("\u274C \u6A21\u677F\u4E0B\u8F7D\u9519\u8BEF:"));
1353
- console.log(chalk2.dim(` ${error.message}`));
1383
+ console.log(chalk3.dim(` ${error.message}`));
1354
1384
  console.log();
1355
- throw error;
1385
+ return;
1356
1386
  }
1357
1387
  await copyTemplate(tempPath, projectPath, spinner);
1358
- spinner.text = "\u2699\uFE0F \u5904\u7406\u9879\u76EE\u914D\u7F6E...";
1388
+ spinner.text = "\u5904\u7406\u9879\u76EE\u914D\u7F6E...";
1359
1389
  await processProjectConfig(projectPath, projectName, template, config);
1360
1390
  if (config.initGit) {
1361
- spinner.text = "\u{1F4DD} \u521D\u59CB\u5316 Git \u4ED3\u5E93...";
1391
+ spinner.text = "\u521D\u59CB\u5316 Git \u4ED3\u5E93...";
1362
1392
  initializeGitRepository(projectPath);
1363
1393
  }
1364
1394
  if (config.installDeps) {
1365
- spinner.text = `\u{1F4E6} \u4F7F\u7528 ${config.packageManager} \u5B89\u88C5\u4F9D\u8D56...`;
1395
+ spinner.text = `\u4F7F\u7528 ${config.packageManager} \u5B89\u88C5\u4F9D\u8D56...`;
1366
1396
  await installDependencies(projectPath, spinner, config.packageManager);
1367
1397
  }
1368
1398
  if (tempPath) {
1369
- spinner.text = "\u{1F9F9} \u6E05\u7406\u4E34\u65F6\u6587\u4EF6...";
1399
+ spinner.text = "\u6E05\u7406\u4E34\u65F6\u6587\u4EF6...";
1370
1400
  await fs3.remove(tempPath).catch(() => {
1371
1401
  });
1372
1402
  }
1373
- spinner.succeed(chalk2.green("\u{1F389} \u9879\u76EE\u521B\u5EFA\u6210\u529F!"));
1403
+ spinner.succeed(chalk3.green("\u9879\u76EE\u521B\u5EFA\u6210\u529F!"));
1374
1404
  console.log();
1375
- console.log(chalk2.green("\u{1F389} \u9879\u76EE\u521B\u5EFA\u5B8C\u6210!"));
1405
+ console.log(chalk3.green("\u9879\u76EE\u521B\u5EFA\u5B8C\u6210!"));
1376
1406
  console.log();
1377
- console.log(chalk2.blue("\u{1F4C1} \u9879\u76EE\u4FE1\u606F:"));
1378
- console.log(` \u4F4D\u7F6E: ${chalk2.cyan(projectPath)}`);
1379
- console.log(` \u6A21\u677F: ${chalk2.cyan(template.name)}`);
1407
+ console.log(chalk3.blue("\u9879\u76EE\u4FE1\u606F:"));
1408
+ console.log(` \u4F4D\u7F6E: ${chalk3.cyan(projectPath)}`);
1409
+ console.log(` \u6A21\u677F: ${chalk3.cyan(template.name)}`);
1380
1410
  console.log(
1381
- ` Git\u4ED3\u5E93: ${config.initGit ? chalk2.green("\u5DF2\u521D\u59CB\u5316") : chalk2.dim("\u672A\u521D\u59CB\u5316")}`
1411
+ ` Git\u4ED3\u5E93: ${config.initGit ? chalk3.green("\u5DF2\u521D\u59CB\u5316") : chalk3.dim("\u672A\u521D\u59CB\u5316")}`
1382
1412
  );
1383
1413
  console.log(
1384
- ` \u4F9D\u8D56\u5B89\u88C5: ${config.installDeps ? chalk2.green("\u5DF2\u5B8C\u6210") : chalk2.dim("\u9700\u624B\u52A8\u5B89\u88C5")}`
1414
+ ` \u4F9D\u8D56\u5B89\u88C5: ${config.installDeps ? chalk3.green("\u5DF2\u5B8C\u6210") : chalk3.dim("\u9700\u624B\u52A8\u5B89\u88C5")}`
1385
1415
  );
1386
1416
  console.log();
1387
- console.log(chalk2.blue("\u{1F680} \u5FEB\u901F\u5F00\u59CB:"));
1388
- console.log(chalk2.cyan(` cd ${projectName}`));
1417
+ console.log(chalk3.blue("\u5FEB\u901F\u5F00\u59CB:"));
1418
+ console.log(chalk3.cyan(` cd ${projectName}`));
1389
1419
  const pm = config.packageManager || "bun";
1390
1420
  if (!config.installDeps) {
1391
- console.log(chalk2.cyan(` ${pm} install`));
1421
+ console.log(chalk3.cyan(` ${pm} install`));
1392
1422
  }
1393
1423
  const cmd = getStartCommand(template, pm);
1394
- if (cmd) console.log(chalk2.cyan(` ${cmd}`));
1424
+ if (cmd) console.log(chalk3.cyan(` ${cmd}`));
1395
1425
  if (pm === "bun")
1396
- console.log(chalk2.dim(" # \u6216\u4F7F\u7528 npm: npm install && npm run dev"));
1426
+ console.log(chalk3.dim(" # \u6216\u4F7F\u7528 npm: npm install && npm run dev"));
1397
1427
  else if (pm === "npm")
1398
1428
  console.log(
1399
- chalk2.dim(" # \u6216\u4F7F\u7528 bun: bun install && bun run dev (\u5982\u5DF2\u5B89\u88C5)")
1429
+ chalk3.dim(" # \u6216\u4F7F\u7528 bun: bun install && bun run dev (\u5982\u5DF2\u5B89\u88C5)")
1400
1430
  );
1401
1431
  console.log();
1402
- spinner.start("\u{1F4CA} \u7EDF\u8BA1\u9879\u76EE\u4FE1\u606F...");
1432
+ spinner.start("\u7EDF\u8BA1\u9879\u76EE\u4FE1\u606F...");
1403
1433
  const stats = await generateProjectStats(projectPath);
1404
1434
  spinner.stop();
1405
1435
  if (stats) {
@@ -1409,7 +1439,7 @@ async function executeCreation(projectName, template, config, options) {
1409
1439
  } catch (error) {
1410
1440
  if (tempPath) await fs3.remove(tempPath).catch(() => {
1411
1441
  });
1412
- spinner.fail("\u521B\u5EFA\u9879\u76EE\u5931\u8D25");
1442
+ if (spinner.isSpinning) spinner.fail("\u521B\u5EFA\u9879\u76EE\u5931\u8D25");
1413
1443
  throw error;
1414
1444
  }
1415
1445
  }
@@ -1455,7 +1485,7 @@ function initializeGitRepository(projectPath) {
1455
1485
  stdio: "ignore"
1456
1486
  });
1457
1487
  } catch {
1458
- console.log(chalk2.yellow("\u26A0\uFE0F Git \u4E0D\u53EF\u7528\uFF0C\u8DF3\u8FC7\u4ED3\u5E93\u521D\u59CB\u5316"));
1488
+ console.log(chalk3.yellow("Git \u4E0D\u53EF\u7528\uFF0C\u8DF3\u8FC7\u4ED3\u5E93\u521D\u59CB\u5316"));
1459
1489
  }
1460
1490
  }
1461
1491
  function getStartCommand(template, pm) {
@@ -1464,12 +1494,12 @@ function getStartCommand(template, pm) {
1464
1494
  }
1465
1495
 
1466
1496
  // src/doctor.ts
1467
- import chalk3 from "chalk";
1497
+ import chalk4 from "chalk";
1468
1498
  import ora2 from "ora";
1469
1499
  import { execSync as execSync3 } from "child_process";
1470
1500
  async function runDoctor(options = {}) {
1471
1501
  console.log();
1472
- console.log(chalk3.blue.bold("\u{1F3E5} Robot CLI \u73AF\u5883\u8BCA\u65AD"));
1502
+ console.log(chalk4.blue.bold("Robot CLI \u73AF\u5883\u8BCA\u65AD"));
1473
1503
  console.log();
1474
1504
  const results = [];
1475
1505
  const nodeVersion = process.version;
@@ -1477,7 +1507,7 @@ async function runDoctor(options = {}) {
1477
1507
  results.push({
1478
1508
  name: "Node.js",
1479
1509
  status: nodeMajor >= 20 ? "ok" : "error",
1480
- detail: nodeMajor >= 20 ? `${nodeVersion} (\u8981\u6C42 >= 20)` : `${nodeVersion} ${chalk3.red("(\u9700\u8981\u5347\u7EA7\u5230 Node.js 20+)")}`
1510
+ detail: nodeMajor >= 20 ? `${nodeVersion} (\u8981\u6C42 >= 20)` : `${nodeVersion} ${chalk4.red("(\u9700\u8981\u5347\u7EA7\u5230 Node.js 20+)")}`
1481
1511
  });
1482
1512
  try {
1483
1513
  const gitVer = execSync3("git --version", { encoding: "utf8" }).trim().replace("git version ", "");
@@ -1526,23 +1556,23 @@ async function runDoctor(options = {}) {
1526
1556
  detail: cacheStats.count > 0 ? `${cacheStats.count} \u4E2A\u6A21\u677F (${formatBytes(cacheStats.totalSize)})` : "\u7A7A"
1527
1557
  });
1528
1558
  const icons = {
1529
- ok: chalk3.green("\u2705"),
1530
- warn: chalk3.yellow("\u26A0\uFE0F "),
1531
- error: chalk3.red("\u274C")
1559
+ ok: chalk4.green("[OK]"),
1560
+ warn: chalk4.yellow("[!!]"),
1561
+ error: chalk4.red("[NO]")
1532
1562
  };
1533
1563
  for (const r of results) {
1534
1564
  const icon = icons[r.status];
1535
- console.log(` ${icon} ${chalk3.bold(r.name.padEnd(14))} ${r.detail}`);
1565
+ console.log(` ${icon} ${chalk4.bold(r.name.padEnd(14))} ${r.detail}`);
1536
1566
  }
1537
1567
  console.log();
1538
1568
  const hasError = results.some((r) => r.status === "error");
1539
1569
  const hasWarn = results.some((r) => r.status === "warn");
1540
1570
  if (hasError) {
1541
- console.log(chalk3.red(" \u8BCA\u65AD\u7ED3\u679C: \u73AF\u5883\u5B58\u5728\u95EE\u9898\uFF0C\u8BF7\u4FEE\u590D\u4E0A\u8FF0\u9519\u8BEF \u274C"));
1571
+ console.log(chalk4.red(" \u8BCA\u65AD\u7ED3\u679C: \u73AF\u5883\u5B58\u5728\u95EE\u9898\uFF0C\u8BF7\u4FEE\u590D\u4E0A\u8FF0\u9519\u8BEF"));
1542
1572
  } else if (hasWarn) {
1543
- console.log(chalk3.yellow(" \u8BCA\u65AD\u7ED3\u679C: \u73AF\u5883\u57FA\u672C\u6B63\u5E38\uFF0C\u90E8\u5206\u7EC4\u4EF6\u7F3A\u5931 \u26A0\uFE0F"));
1573
+ console.log(chalk4.yellow(" \u8BCA\u65AD\u7ED3\u679C: \u73AF\u5883\u57FA\u672C\u6B63\u5E38\uFF0C\u90E8\u5206\u7EC4\u4EF6\u7F3A\u5931"));
1544
1574
  } else {
1545
- console.log(chalk3.green(" \u8BCA\u65AD\u7ED3\u679C: \u73AF\u5883\u5065\u5EB7 \u2705"));
1575
+ console.log(chalk4.green(" \u8BCA\u65AD\u7ED3\u679C: \u73AF\u5883\u5065\u5EB7"));
1546
1576
  }
1547
1577
  console.log();
1548
1578
  if (options.clearCache) {
@@ -1560,38 +1590,32 @@ function getPackageVersion() {
1560
1590
  const pkg = JSON.parse(
1561
1591
  readFileSync(join(__dirname, "..", "package.json"), "utf8")
1562
1592
  );
1563
- return pkg.version || "2.0.0";
1593
+ return pkg.version || "0.0.0";
1564
1594
  } catch {
1565
- return "2.0.0";
1595
+ return "0.0.0";
1566
1596
  }
1567
1597
  }
1568
1598
  var VERSION = getPackageVersion();
1569
1599
  function showWelcome() {
1570
- const banner = boxen(
1571
- [
1572
- "",
1573
- chalk4.bold.cyan(" \u{1F916} R O B O T - C L I "),
1574
- "",
1575
- chalk4.dim(` v${VERSION} \u2014 \u5DE5\u7A0B\u5316\u9879\u76EE\u811A\u624B\u67B6`),
1576
- "",
1577
- chalk4.dim(" \u5FEB\u901F\u521B\u5EFA\u6807\u51C6\u5316\u524D\u7AEF/\u540E\u7AEF/\u79FB\u52A8\u7AEF/\u684C\u9762\u7AEF\u9879\u76EE"),
1578
- ""
1579
- ].join("\n"),
1580
- {
1581
- padding: 1,
1582
- margin: { top: 1, bottom: 1, left: 2, right: 2 },
1583
- borderStyle: "round",
1584
- borderColor: "cyan"
1585
- }
1600
+ const supportsColor = process.stdout.isTTY && process.stdout.getColorDepth() > 1;
1601
+ console.log();
1602
+ if (supportsColor) {
1603
+ console.log(chalk5.bold.cyan(" R O B O T C L I"));
1604
+ } else {
1605
+ console.log(" R O B O T C L I");
1606
+ }
1607
+ console.log(
1608
+ chalk5.dim(` v${VERSION} | ${chalk5.reset.dim("\u5DE5\u7A0B\u5316\u9879\u76EE\u811A\u624B\u67B6")}`)
1586
1609
  );
1587
- console.log(banner);
1610
+ console.log(chalk5.dim(" \u524D\u7AEF / \u540E\u7AEF / \u79FB\u52A8\u7AEF / \u684C\u9762\u7AEF"));
1611
+ console.log();
1588
1612
  }
1589
1613
  async function showMainMenu() {
1590
1614
  const allTemplates = getAllTemplates();
1591
1615
  const count = Object.keys(allTemplates).length;
1592
1616
  console.log(
1593
- chalk4.dim(
1594
- ` \u{1F4E6} ${count} \u4E2A\u6A21\u677F\u53EF\u7528 \u2022 Node ${process.version} \u2022 v${VERSION}`
1617
+ chalk5.dim(
1618
+ ` ${count} \u4E2A\u6A21\u677F\u53EF\u7528 \xB7 Node ${process.version} \xB7 v${VERSION}`
1595
1619
  )
1596
1620
  );
1597
1621
  console.log();
@@ -1602,23 +1626,23 @@ async function showMainMenu() {
1602
1626
  message: "\u8BF7\u9009\u62E9\u64CD\u4F5C:",
1603
1627
  choices: [
1604
1628
  {
1605
- name: `\u{1F680} ${chalk4.bold("\u521B\u5EFA\u65B0\u9879\u76EE")} ${chalk4.dim("\u2014 \u9009\u62E9\u6A21\u677F\u521B\u5EFA\u9879\u76EE")}`,
1629
+ name: `${chalk5.cyan(">")} ${chalk5.bold("\u521B\u5EFA\u65B0\u9879\u76EE")} ${chalk5.dim("\u2014 \u9009\u62E9\u6A21\u677F\u521B\u5EFA\u9879\u76EE")}`,
1606
1630
  value: "create"
1607
1631
  },
1608
1632
  {
1609
- name: `\u{1F4CB} ${chalk4.bold("\u67E5\u770B\u6A21\u677F\u5217\u8868")} ${chalk4.dim("\u2014 \u6D4F\u89C8\u6240\u6709\u53EF\u7528\u6A21\u677F")}`,
1633
+ name: `${chalk5.cyan(">")} ${chalk5.bold("\u67E5\u770B\u6A21\u677F\u5217\u8868")} ${chalk5.dim("\u2014 \u6D4F\u89C8\u6240\u6709\u53EF\u7528\u6A21\u677F")}`,
1610
1634
  value: "list"
1611
1635
  },
1612
1636
  {
1613
- name: `\u{1F50D} ${chalk4.bold("\u641C\u7D22\u6A21\u677F")} ${chalk4.dim("\u2014 \u6309\u5173\u952E\u8BCD\u641C\u7D22\u6A21\u677F")}`,
1637
+ name: `${chalk5.cyan(">")} ${chalk5.bold("\u641C\u7D22\u6A21\u677F")} ${chalk5.dim("\u2014 \u6309\u5173\u952E\u8BCD\u641C\u7D22\u6A21\u677F")}`,
1614
1638
  value: "search"
1615
1639
  },
1616
1640
  {
1617
- name: `\u{1F3E5} ${chalk4.bold("\u73AF\u5883\u8BCA\u65AD")} ${chalk4.dim("\u2014 \u68C0\u67E5\u5F00\u53D1\u73AF\u5883")}`,
1641
+ name: `${chalk5.cyan(">")} ${chalk5.bold("\u73AF\u5883\u8BCA\u65AD")} ${chalk5.dim("\u2014 \u68C0\u67E5\u5F00\u53D1\u73AF\u5883")}`,
1618
1642
  value: "doctor"
1619
1643
  },
1620
- { name: chalk4.dim("\u2500".repeat(50)), value: "sep", disabled: true },
1621
- { name: `\u274C ${chalk4.dim("\u9000\u51FA")}`, value: "exit" }
1644
+ { name: chalk5.dim("\u2500".repeat(50)), value: "sep", disabled: true },
1645
+ { name: `${chalk5.dim(" \u9000\u51FA")}`, value: "exit" }
1622
1646
  ]
1623
1647
  }
1624
1648
  ]);
@@ -1636,26 +1660,26 @@ async function showMainMenu() {
1636
1660
  await runDoctor();
1637
1661
  break;
1638
1662
  case "exit":
1639
- console.log(chalk4.dim("\u{1F44B} \u518D\u89C1!"));
1663
+ console.log(chalk5.dim(" \u518D\u89C1!"));
1640
1664
  process.exit(0);
1641
1665
  }
1642
1666
  }
1643
1667
  function showTemplateList(recommended) {
1644
1668
  const templates = recommended ? getRecommendedTemplates() : getAllTemplates();
1645
- const title = recommended ? "\u{1F3AF} \u63A8\u8350\u6A21\u677F" : "\u{1F4CB} \u6240\u6709\u6A21\u677F";
1669
+ const title = recommended ? "\u63A8\u8350\u6A21\u677F" : "\u6240\u6709\u6A21\u677F";
1646
1670
  const entries = Object.entries(templates);
1647
1671
  console.log();
1648
- console.log(chalk4.blue.bold(title));
1649
- console.log(chalk4.dim(`\u5171 ${entries.length} \u4E2A\u6A21\u677F`));
1672
+ console.log(chalk5.blue.bold(title));
1673
+ console.log(chalk5.dim(`\u5171 ${entries.length} \u4E2A\u6A21\u677F`));
1650
1674
  console.log();
1651
1675
  for (const [key, t] of entries) {
1652
- const ver = t.version === "full" ? chalk4.green("[\u5B8C\u6574\u7248]") : chalk4.yellow("[\u7CBE\u7B80\u7248]");
1676
+ const ver = VERSION_LABELS[t.version] ? (t.version === "full" ? chalk5.green : t.version === "micro" ? chalk5.blue : chalk5.yellow)(`[${VERSION_LABELS[t.version]}]`) : chalk5.dim(`[${t.version}]`);
1653
1677
  const cat = getCategoryForTemplate(key);
1654
- const catLabel = cat ? chalk4.dim(`[${cat}]`) : "";
1655
- console.log(` ${chalk4.bold(t.name)} ${ver} ${catLabel}`);
1656
- console.log(` ${chalk4.dim(t.description)}`);
1657
- console.log(` ${chalk4.dim(`\u547D\u4EE4: robot create my-app -t ${key}`)}`);
1658
- console.log(` ${chalk4.dim(`features: ${t.features.join(", ")}`)}`);
1678
+ const catLabel = cat ? chalk5.dim(`[${cat.name}]`) : "";
1679
+ console.log(` ${chalk5.bold(t.name)} ${ver} ${catLabel}`);
1680
+ console.log(` ${chalk5.dim(t.description)}`);
1681
+ console.log(` ${chalk5.dim(`\u547D\u4EE4: robot create my-app -t ${key}`)}`);
1682
+ console.log(` ${chalk5.dim(`features: ${t.features.join(", ")}`)}`);
1659
1683
  console.log();
1660
1684
  }
1661
1685
  }
@@ -1675,29 +1699,48 @@ function showSearchResults(keyword) {
1675
1699
  const entries = Object.entries(results);
1676
1700
  console.log();
1677
1701
  if (entries.length === 0) {
1678
- console.log(chalk4.yellow(`\u{1F50D} \u6CA1\u6709\u627E\u5230\u300C${keyword}\u300D\u76F8\u5173\u6A21\u677F`));
1702
+ console.log(chalk5.yellow(`\u6CA1\u6709\u627E\u5230\u300C${keyword}\u300D\u76F8\u5173\u6A21\u677F`));
1679
1703
  console.log();
1680
1704
  return;
1681
1705
  }
1682
- console.log(chalk4.green.bold(`\u{1F50D} \u641C\u7D22\u7ED3\u679C: "${keyword}"`));
1683
- console.log(chalk4.dim(`\u627E\u5230 ${entries.length} \u4E2A\u5339\u914D`));
1706
+ console.log(chalk5.green.bold(`\u641C\u7D22\u7ED3\u679C: "${keyword}"`));
1707
+ console.log(chalk5.dim(`\u627E\u5230 ${entries.length} \u4E2A\u5339\u914D`));
1684
1708
  console.log();
1685
1709
  for (const [key, t] of entries) {
1686
- const ver = t.version === "full" ? chalk4.green("[\u5B8C\u6574\u7248]") : chalk4.yellow("[\u7CBE\u7B80\u7248]");
1687
- console.log(` ${chalk4.bold(t.name)} ${ver}`);
1688
- console.log(` ${chalk4.dim(t.description)}`);
1689
- console.log(` ${chalk4.dim(`robot create my-app -t ${key}`)}`);
1710
+ const ver = VERSION_LABELS[t.version] ? (t.version === "full" ? chalk5.green : t.version === "micro" ? chalk5.blue : chalk5.yellow)(`[${VERSION_LABELS[t.version]}]`) : chalk5.dim(`[${t.version}]`);
1711
+ console.log(` ${chalk5.bold(t.name)} ${ver}`);
1712
+ console.log(` ${chalk5.dim(t.description)}`);
1713
+ console.log(` ${chalk5.dim(`robot create my-app -t ${key}`)}`);
1714
+ console.log();
1715
+ }
1716
+ }
1717
+ async function notifyUpdate() {
1718
+ const newVersion = await checkForUpdates(
1719
+ "@agile-team/robot-cli",
1720
+ VERSION
1721
+ ).catch(() => null);
1722
+ if (newVersion) {
1723
+ console.log();
1724
+ console.log(
1725
+ chalk5.yellow(
1726
+ ` \u250C\u2500 \u53D1\u73B0\u65B0\u7248\u672C: ${chalk5.dim(VERSION)} \u2192 ${chalk5.bold.green(newVersion)}`
1727
+ )
1728
+ );
1729
+ console.log(
1730
+ chalk5.yellow(
1731
+ ` \u2514\u2500 \u66F4\u65B0\u547D\u4EE4: ${chalk5.cyan("bun add -g @agile-team/robot-cli")}`
1732
+ )
1733
+ );
1690
1734
  console.log();
1691
1735
  }
1692
1736
  }
1693
1737
  async function main() {
1694
1738
  const program = new Command();
1695
- program.name("robot").description("\u{1F916} Robot CLI - \u5DE5\u7A0B\u5316\u9879\u76EE\u811A\u624B\u67B6").version(VERSION, "-v, --version");
1739
+ program.name("robot").description("Robot CLI - \u5DE5\u7A0B\u5316\u9879\u76EE\u811A\u624B\u67B6").version(VERSION, "-v, --version");
1696
1740
  program.command("create [project-name]").description("\u521B\u5EFA\u65B0\u9879\u76EE").option("-t, --template <name>", "\u6307\u5B9A\u6A21\u677F\u540D\u79F0").option("--skip-install", "\u8DF3\u8FC7\u4F9D\u8D56\u5B89\u88C5").option("--dry-run", "\u9884\u89C8\u6A21\u5F0F\uFF0C\u4E0D\u5B9E\u9645\u521B\u5EFA").option("--from <url>", "\u4ECE\u81EA\u5B9A\u4E49 Git \u4ED3\u5E93\u521B\u5EFA").option("--no-cache", "\u4E0D\u4F7F\u7528\u7F13\u5B58").action(async (projectName, opts) => {
1697
1741
  showWelcome();
1698
1742
  await createProject(projectName, opts);
1699
- checkForUpdates("@agile-team/robot-cli", VERSION).catch(() => {
1700
- });
1743
+ await notifyUpdate();
1701
1744
  });
1702
1745
  program.command("list").description("\u67E5\u770B\u6A21\u677F\u5217\u8868").option("-r, --recommended", "\u53EA\u663E\u793A\u63A8\u8350\u6A21\u677F").action((opts) => {
1703
1746
  showTemplateList(!!opts.recommended);