@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.
- package/CHANGELOG.md +18 -1
- package/README.md +27 -27
- package/dist/index.js +290 -247
- 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
|
|
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
|
|
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: "\
|
|
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: "\
|
|
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: "\
|
|
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: "\
|
|
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
|
|
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" ?
|
|
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 =
|
|
358
|
-
|
|
383
|
+
const isOriginal = i === 0;
|
|
384
|
+
let sourceName;
|
|
359
385
|
try {
|
|
360
|
-
|
|
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
|
-
|
|
363
|
-
|
|
364
|
-
|
|
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 = `\
|
|
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 =
|
|
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 = "\
|
|
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 = "\
|
|
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 = "\
|
|
429
|
+
if (spinner) spinner.text = "\u89E3\u538B\u6A21\u677F\u6587\u4EF6...";
|
|
405
430
|
await extract(tempZip, { dir: tempExtract });
|
|
406
|
-
if (spinner) spinner.text = "\
|
|
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 = "\
|
|
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 = `\
|
|
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 = "\
|
|
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
|
-
|
|
453
|
-
|
|
454
|
-
|
|
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
|
|
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 = "\
|
|
660
|
+
if (spinner) spinner.text = "\u7EDF\u8BA1\u6587\u4EF6\u6570\u91CF...";
|
|
634
661
|
const totalFiles = await countFiles(sourcePath);
|
|
635
|
-
if (spinner) spinner.text = `\
|
|
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 = `\
|
|
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 = `\
|
|
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 = "\
|
|
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 = `\
|
|
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 = `\
|
|
713
|
+
if (spinner) spinner.text = `\u4F9D\u8D56\u5B89\u88C5\u5B8C\u6210 (${packageManager})`;
|
|
687
714
|
} catch (error) {
|
|
688
|
-
if (spinner) spinner.text = "\
|
|
715
|
+
if (spinner) spinner.text = "\u4F9D\u8D56\u5B89\u88C5\u5931\u8D25\uFF0C\u8BF7\u624B\u52A8\u5B89\u88C5";
|
|
689
716
|
console.log();
|
|
690
|
-
console.log(
|
|
691
|
-
console.log(
|
|
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(
|
|
694
|
-
console.log(
|
|
695
|
-
console.log(
|
|
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(
|
|
734
|
-
console.log(` \u6587\u4EF6\u6570\u91CF: ${
|
|
735
|
-
console.log(` \u76EE\u5F55\u6570\u91CF: ${
|
|
736
|
-
console.log(` \u9879\u76EE\u5927\u5C0F: ${
|
|
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}: ${
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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: ${
|
|
783
|
-
console.log(` \u4E0B\u8F7D\u6765\u6E90: ${
|
|
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(
|
|
786
|
-
console.log(
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
831
|
+
chalk3.dim(` ${step}. \u4F7F\u7528 ${projectConfig.packageManager} \u5B89\u88C5\u4F9D\u8D56`)
|
|
798
832
|
);
|
|
799
833
|
}
|
|
800
834
|
console.log();
|
|
801
|
-
console.log(
|
|
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(
|
|
812
|
-
v.errors.forEach((e) => console.log(
|
|
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(
|
|
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(
|
|
865
|
-
console.log(
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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(
|
|
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(
|
|
917
|
-
console.log(
|
|
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) =>
|
|
923
|
-
const ver = template.version
|
|
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: `${
|
|
926
|
-
${tags}${template.features.length > 3 ?
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
994
|
-
{ name:
|
|
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:
|
|
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:
|
|
1017
|
-
{ name:
|
|
1018
|
-
{ name:
|
|
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} - ${
|
|
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:
|
|
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:
|
|
1043
|
-
{ name:
|
|
1044
|
-
{ name:
|
|
1045
|
-
{ name:
|
|
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(
|
|
1071
|
-
console.log(
|
|
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: "\
|
|
1080
|
-
{ name: "\
|
|
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(
|
|
1119
|
+
console.log(chalk3.bold(" \u641C\u7D22\u7ED3\u679C"));
|
|
1089
1120
|
console.log(
|
|
1090
|
-
|
|
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
|
-
|
|
1129
|
+
chalk3.bgYellow.black("$1")
|
|
1099
1130
|
);
|
|
1100
|
-
const ver = t.version
|
|
1131
|
+
const ver = getVersionLabel(t.version);
|
|
1101
1132
|
const info = t.features.slice(0, 2).join(" \u2022 ");
|
|
1102
1133
|
return {
|
|
1103
|
-
name: `${
|
|
1104
|
-
${
|
|
1105
|
-
${
|
|
1106
|
-
${
|
|
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:
|
|
1113
|
-
{ name: "\
|
|
1114
|
-
{ name: "\
|
|
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(
|
|
1136
|
-
console.log(
|
|
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:
|
|
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
|
|
1179
|
+
const ver = getVersionLabel(t.version);
|
|
1149
1180
|
categorizedChoices.push({
|
|
1150
|
-
name: ` \u25CF ${
|
|
1151
|
-
${
|
|
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:
|
|
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:
|
|
1166
|
-
{ name:
|
|
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(
|
|
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: "\
|
|
1265
|
-
{ name: "\
|
|
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(
|
|
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(
|
|
1308
|
+
console.log(chalk3.bold(" \u9879\u76EE\u521B\u5EFA\u4FE1\u606F\u786E\u8BA4:"));
|
|
1278
1309
|
console.log();
|
|
1279
|
-
console.log(` \u9879\u76EE\u540D\u79F0: ${
|
|
1280
|
-
console.log(` \u9009\u62E9\u6A21\u677F: ${
|
|
1281
|
-
console.log(` \u6A21\u677F\u63CF\u8FF0: ${
|
|
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: ${
|
|
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: ${
|
|
1287
|
-
if (config.author) console.log(` \u4F5C\u3000\u3000\u8005: ${
|
|
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 ?
|
|
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 ?
|
|
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: ${
|
|
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(
|
|
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: "\
|
|
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 = "\
|
|
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(
|
|
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(
|
|
1365
|
+
console.log(chalk3.yellow("\u53D6\u6D88\u521B\u5EFA"));
|
|
1335
1366
|
process.exit(0);
|
|
1336
1367
|
}
|
|
1337
|
-
spinner.start("\
|
|
1368
|
+
spinner.start("\u6E05\u7406\u73B0\u6709\u76EE\u5F55...");
|
|
1338
1369
|
await fs3.remove(projectPath);
|
|
1339
|
-
spinner.text = "\
|
|
1370
|
+
spinner.text = "\u51C6\u5907\u521B\u5EFA\u65B0\u76EE\u5F55...";
|
|
1340
1371
|
}
|
|
1341
|
-
spinner.text = "\
|
|
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(
|
|
1353
|
-
console.log(chalk2.dim(` ${error.message}`));
|
|
1383
|
+
console.log(chalk3.dim(` ${error.message}`));
|
|
1354
1384
|
console.log();
|
|
1355
|
-
|
|
1385
|
+
return;
|
|
1356
1386
|
}
|
|
1357
1387
|
await copyTemplate(tempPath, projectPath, spinner);
|
|
1358
|
-
spinner.text = "\
|
|
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 = "\
|
|
1391
|
+
spinner.text = "\u521D\u59CB\u5316 Git \u4ED3\u5E93...";
|
|
1362
1392
|
initializeGitRepository(projectPath);
|
|
1363
1393
|
}
|
|
1364
1394
|
if (config.installDeps) {
|
|
1365
|
-
spinner.text = `\
|
|
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 = "\
|
|
1399
|
+
spinner.text = "\u6E05\u7406\u4E34\u65F6\u6587\u4EF6...";
|
|
1370
1400
|
await fs3.remove(tempPath).catch(() => {
|
|
1371
1401
|
});
|
|
1372
1402
|
}
|
|
1373
|
-
spinner.succeed(
|
|
1403
|
+
spinner.succeed(chalk3.green("\u9879\u76EE\u521B\u5EFA\u6210\u529F!"));
|
|
1374
1404
|
console.log();
|
|
1375
|
-
console.log(
|
|
1405
|
+
console.log(chalk3.green("\u9879\u76EE\u521B\u5EFA\u5B8C\u6210!"));
|
|
1376
1406
|
console.log();
|
|
1377
|
-
console.log(
|
|
1378
|
-
console.log(` \u4F4D\u7F6E: ${
|
|
1379
|
-
console.log(` \u6A21\u677F: ${
|
|
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 ?
|
|
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 ?
|
|
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(
|
|
1388
|
-
console.log(
|
|
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(
|
|
1421
|
+
console.log(chalk3.cyan(` ${pm} install`));
|
|
1392
1422
|
}
|
|
1393
1423
|
const cmd = getStartCommand(template, pm);
|
|
1394
|
-
if (cmd) console.log(
|
|
1424
|
+
if (cmd) console.log(chalk3.cyan(` ${cmd}`));
|
|
1395
1425
|
if (pm === "bun")
|
|
1396
|
-
console.log(
|
|
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
|
-
|
|
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("\
|
|
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(
|
|
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
|
|
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(
|
|
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} ${
|
|
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:
|
|
1530
|
-
warn:
|
|
1531
|
-
error:
|
|
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} ${
|
|
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(
|
|
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(
|
|
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(
|
|
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 || "
|
|
1593
|
+
return pkg.version || "0.0.0";
|
|
1564
1594
|
} catch {
|
|
1565
|
-
return "
|
|
1595
|
+
return "0.0.0";
|
|
1566
1596
|
}
|
|
1567
1597
|
}
|
|
1568
1598
|
var VERSION = getPackageVersion();
|
|
1569
1599
|
function showWelcome() {
|
|
1570
|
-
const
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
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(
|
|
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
|
-
|
|
1594
|
-
`
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
1621
|
-
{ name:
|
|
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(
|
|
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 ? "\
|
|
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(
|
|
1649
|
-
console.log(
|
|
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" ?
|
|
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 ?
|
|
1655
|
-
console.log(` ${
|
|
1656
|
-
console.log(` ${
|
|
1657
|
-
console.log(` ${
|
|
1658
|
-
console.log(` ${
|
|
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(
|
|
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(
|
|
1683
|
-
console.log(
|
|
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" ?
|
|
1687
|
-
console.log(` ${
|
|
1688
|
-
console.log(` ${
|
|
1689
|
-
console.log(` ${
|
|
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("
|
|
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
|
-
|
|
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);
|