@agile-team/robot-cli 2.1.0 → 2.2.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/dist/index.js +212 -185
- package/package.json +77 -77
package/dist/index.js
CHANGED
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
import { readFileSync } from "fs";
|
|
3
3
|
import { fileURLToPath } from "url";
|
|
4
4
|
import { dirname, join } from "path";
|
|
5
|
-
import
|
|
6
|
-
import
|
|
5
|
+
import chalk5 from "chalk";
|
|
6
|
+
import gradient from "gradient-string";
|
|
7
7
|
import inquirer2 from "inquirer";
|
|
8
8
|
import { Command } from "commander";
|
|
9
9
|
|
|
10
10
|
// src/create.ts
|
|
11
11
|
import fs3 from "fs-extra";
|
|
12
12
|
import path3 from "path";
|
|
13
|
-
import
|
|
13
|
+
import chalk3 from "chalk";
|
|
14
14
|
import inquirer from "inquirer";
|
|
15
15
|
import ora from "ora";
|
|
16
16
|
import { execSync as execSync2 } from "child_process";
|
|
@@ -19,6 +19,7 @@ import { execSync as execSync2 } from "child_process";
|
|
|
19
19
|
import fs from "fs-extra";
|
|
20
20
|
import path from "path";
|
|
21
21
|
import os from "os";
|
|
22
|
+
import chalk from "chalk";
|
|
22
23
|
import extract from "extract-zip";
|
|
23
24
|
|
|
24
25
|
// src/config/templates.config.ts
|
|
@@ -243,6 +244,11 @@ var TEMPLATE_CATEGORIES = {
|
|
|
243
244
|
|
|
244
245
|
// src/config/cli.config.ts
|
|
245
246
|
var CACHE_DIR_NAME = "cache";
|
|
247
|
+
var VERSION_LABELS = {
|
|
248
|
+
full: "\u5B8C\u6574\u7248",
|
|
249
|
+
base: "\u7CBE\u7B80\u7248",
|
|
250
|
+
micro: "\u5FAE\u670D\u52A1\u7248"
|
|
251
|
+
};
|
|
246
252
|
var RECOMMENDED_TEMPLATE_KEYS = [
|
|
247
253
|
"robot-admin",
|
|
248
254
|
"robot-monorepo",
|
|
@@ -317,7 +323,7 @@ async function getCachedTemplate(repoUrl) {
|
|
|
317
323
|
}
|
|
318
324
|
return null;
|
|
319
325
|
}
|
|
320
|
-
async function saveToCache(repoUrl, sourcePath) {
|
|
326
|
+
async function saveToCache(repoUrl, sourcePath, branch = "main") {
|
|
321
327
|
try {
|
|
322
328
|
const key = getCacheKey(repoUrl);
|
|
323
329
|
const cachePath = path.join(CACHE_DIR, key);
|
|
@@ -330,7 +336,7 @@ async function saveToCache(repoUrl, sourcePath) {
|
|
|
330
336
|
index.entries[key] = {
|
|
331
337
|
repoUrl,
|
|
332
338
|
downloadedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
333
|
-
branch
|
|
339
|
+
branch,
|
|
334
340
|
size: stat.size
|
|
335
341
|
};
|
|
336
342
|
await saveCacheIndex(index);
|
|
@@ -362,7 +368,7 @@ async function tryDownload(repoUrl, branch = "main", spinner) {
|
|
|
362
368
|
if (spinner) spinner.text = `\u{1F4E6} \u4ECE ${sourceName} \u4E0B\u8F7D\u6A21\u677F...`;
|
|
363
369
|
const response = await fetch(downloadUrl, {
|
|
364
370
|
signal: AbortSignal.timeout(isOriginal ? 15e3 : 1e4),
|
|
365
|
-
headers: { "User-Agent": "Robot-CLI
|
|
371
|
+
headers: { "User-Agent": "Robot-CLI" }
|
|
366
372
|
});
|
|
367
373
|
if (!response.ok) {
|
|
368
374
|
if (response.status === 404) throw new Error(`\u4ED3\u5E93\u4E0D\u5B58\u5728: ${repoUrl}`);
|
|
@@ -420,7 +426,7 @@ async function downloadTemplate(template, options = {}) {
|
|
|
420
426
|
throw new Error("\u6A21\u677F\u7F3A\u5C11 package.json \u6587\u4EF6");
|
|
421
427
|
}
|
|
422
428
|
if (!noCache) {
|
|
423
|
-
saveToCache(template.repoUrl, sourcePath).catch(() => {
|
|
429
|
+
saveToCache(template.repoUrl, sourcePath, branch).catch(() => {
|
|
424
430
|
});
|
|
425
431
|
}
|
|
426
432
|
if (spinner) spinner.text = `\u{1F389} \u6A21\u677F\u4E0B\u8F7D\u5B8C\u6210 (via ${sourceName})`;
|
|
@@ -433,9 +439,7 @@ async function downloadTemplate(template, options = {}) {
|
|
|
433
439
|
if (cached) {
|
|
434
440
|
if (spinner) spinner.text = "\u{1F4E6} \u7F51\u7EDC\u4E0D\u53EF\u7528\uFF0C\u4F7F\u7528\u7F13\u5B58\u6A21\u677F...";
|
|
435
441
|
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
|
-
);
|
|
442
|
+
console.log(` ${chalk.yellow("\u26A0\uFE0F \u4F7F\u7528\u7F13\u5B58\u7248\u672C\uFF08\u975E\u6700\u65B0\uFF09")}`);
|
|
439
443
|
return cached;
|
|
440
444
|
}
|
|
441
445
|
}
|
|
@@ -449,8 +453,12 @@ async function downloadTemplate(template, options = {}) {
|
|
|
449
453
|
}
|
|
450
454
|
} catch {
|
|
451
455
|
}
|
|
452
|
-
|
|
453
|
-
|
|
456
|
+
const errMsg = downloadError.message;
|
|
457
|
+
const isTimeout = errMsg.includes("aborted") || errMsg.includes("timeout") || downloadError.name === "TimeoutError";
|
|
458
|
+
let msg = `\u6A21\u677F\u4E0B\u8F7D\u5931\u8D25: ${errMsg}`;
|
|
459
|
+
if (isTimeout) {
|
|
460
|
+
msg += "\n\n\u{1F4A1} \u5EFA\u8BAE:\n1. \u5F53\u524D\u7F51\u7EDC\u8FDE\u63A5\u8F83\u6162\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\n2. \u5982\u679C\u5728\u56FD\u5185\uFF0C\u5C1D\u8BD5\u4F7F\u7528\u79D1\u5B66\u4E0A\u7F51\u6216\u914D\u7F6E\u4EE3\u7406\n3. \u4F7F\u7528 --no-cache \u5F3A\u5236\u91CD\u65B0\u4E0B\u8F7D";
|
|
461
|
+
} else if (downloadError.code === "ENOTFOUND") {
|
|
454
462
|
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";
|
|
455
463
|
}
|
|
456
464
|
throw new Error(msg);
|
|
@@ -528,7 +536,7 @@ function getCategoryForTemplate(templateKey) {
|
|
|
528
536
|
// src/utils.ts
|
|
529
537
|
import fs2 from "fs-extra";
|
|
530
538
|
import path2 from "path";
|
|
531
|
-
import
|
|
539
|
+
import chalk2 from "chalk";
|
|
532
540
|
import { execSync } from "child_process";
|
|
533
541
|
function detectPackageManager() {
|
|
534
542
|
const managers = [];
|
|
@@ -687,12 +695,12 @@ async function installDependencies(projectPath, spinner, packageManager = "npm")
|
|
|
687
695
|
} catch (error) {
|
|
688
696
|
if (spinner) spinner.text = "\u26A0\uFE0F \u4F9D\u8D56\u5B89\u88C5\u5931\u8D25\uFF0C\u8BF7\u624B\u52A8\u5B89\u88C5";
|
|
689
697
|
console.log();
|
|
690
|
-
console.log(
|
|
691
|
-
console.log(
|
|
698
|
+
console.log(chalk2.yellow("\u26A0\uFE0F \u81EA\u52A8\u5B89\u88C5\u4F9D\u8D56\u5931\u8D25"));
|
|
699
|
+
console.log(chalk2.dim(` \u9519\u8BEF: ${error.message}`));
|
|
692
700
|
console.log();
|
|
693
|
-
console.log(
|
|
694
|
-
console.log(
|
|
695
|
-
console.log(
|
|
701
|
+
console.log(chalk2.blue("\u{1F4A1} \u8BF7\u624B\u52A8\u5B89\u88C5:"));
|
|
702
|
+
console.log(chalk2.cyan(` cd ${path2.basename(projectPath)}`));
|
|
703
|
+
console.log(chalk2.cyan(` ${packageManager} install`));
|
|
696
704
|
console.log();
|
|
697
705
|
}
|
|
698
706
|
}
|
|
@@ -730,15 +738,15 @@ async function generateProjectStats(projectPath) {
|
|
|
730
738
|
}
|
|
731
739
|
}
|
|
732
740
|
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: ${
|
|
741
|
+
console.log(chalk2.blue("\u{1F4CA} \u9879\u76EE\u7EDF\u8BA1:"));
|
|
742
|
+
console.log(` \u6587\u4EF6\u6570\u91CF: ${chalk2.cyan(String(stats.files))} \u4E2A`);
|
|
743
|
+
console.log(` \u76EE\u5F55\u6570\u91CF: ${chalk2.cyan(String(stats.directories))} \u4E2A`);
|
|
744
|
+
console.log(` \u9879\u76EE\u5927\u5C0F: ${chalk2.cyan(formatBytes(stats.size))}`);
|
|
737
745
|
const top = Object.entries(stats.fileTypes).sort(([, a], [, b]) => b - a).slice(0, 5);
|
|
738
746
|
if (top.length > 0) {
|
|
739
747
|
console.log(" \u4E3B\u8981\u6587\u4EF6\u7C7B\u578B:");
|
|
740
748
|
for (const [ext, count] of top) {
|
|
741
|
-
console.log(` ${ext}: ${
|
|
749
|
+
console.log(` ${ext}: ${chalk2.cyan(String(count))} \u4E2A`);
|
|
742
750
|
}
|
|
743
751
|
}
|
|
744
752
|
}
|
|
@@ -751,9 +759,16 @@ function formatBytes(bytes) {
|
|
|
751
759
|
}
|
|
752
760
|
|
|
753
761
|
// src/create.ts
|
|
762
|
+
function getVersionLabel(version) {
|
|
763
|
+
const label = VERSION_LABELS[version] || version;
|
|
764
|
+
if (version === "full") return chalk3.green(`[${label}]`);
|
|
765
|
+
if (version === "micro") return chalk3.blue(`[${label}]`);
|
|
766
|
+
return chalk3.yellow(`[${label}]`);
|
|
767
|
+
}
|
|
768
|
+
var STRIP_VERSION_RE = /\s*(完整版|精简版|微服务版)\s*$/;
|
|
754
769
|
async function createProject(projectName, options = {}) {
|
|
755
770
|
console.log();
|
|
756
|
-
console.log(
|
|
771
|
+
console.log(chalk3.cyan(" Robot CLI - \u5F00\u59CB\u521B\u5EFA\u9879\u76EE"));
|
|
757
772
|
console.log();
|
|
758
773
|
let template;
|
|
759
774
|
if (options.from) {
|
|
@@ -765,7 +780,7 @@ async function createProject(projectName, options = {}) {
|
|
|
765
780
|
features: [],
|
|
766
781
|
version: "full"
|
|
767
782
|
};
|
|
768
|
-
console.log(
|
|
783
|
+
console.log(chalk3.blue(`\u4F7F\u7528\u81EA\u5B9A\u4E49\u6A21\u677F: ${chalk3.dim(options.from)}`));
|
|
769
784
|
console.log();
|
|
770
785
|
} else {
|
|
771
786
|
template = await selectTemplate(options.template);
|
|
@@ -776,29 +791,29 @@ async function createProject(projectName, options = {}) {
|
|
|
776
791
|
if (options.dryRun) {
|
|
777
792
|
console.log();
|
|
778
793
|
console.log(
|
|
779
|
-
|
|
794
|
+
chalk3.yellow("\u{1F50D} Dry Run \u6A21\u5F0F - \u4EE5\u4E0B\u4E3A\u9884\u89C8\u4FE1\u606F\uFF0C\u672A\u5B9E\u9645\u6267\u884C\u4EFB\u4F55\u64CD\u4F5C:")
|
|
780
795
|
);
|
|
781
796
|
console.log();
|
|
782
|
-
console.log(` \u9879\u76EE\u8DEF\u5F84: ${
|
|
783
|
-
console.log(` \u4E0B\u8F7D\u6765\u6E90: ${
|
|
797
|
+
console.log(` \u9879\u76EE\u8DEF\u5F84: ${chalk3.cyan(path3.resolve(finalProjectName))}`);
|
|
798
|
+
console.log(` \u4E0B\u8F7D\u6765\u6E90: ${chalk3.dim(template.repoUrl)}`);
|
|
784
799
|
console.log(" \u6267\u884C\u6B65\u9AA4:");
|
|
785
|
-
console.log(
|
|
786
|
-
console.log(
|
|
800
|
+
console.log(chalk3.dim(` 1. \u4ECE ${template.repoUrl} \u4E0B\u8F7D\u6700\u65B0\u6A21\u677F`));
|
|
801
|
+
console.log(chalk3.dim(` 2. \u89E3\u538B\u5E76\u590D\u5236\u5230 ./${finalProjectName}`));
|
|
787
802
|
console.log(
|
|
788
|
-
|
|
803
|
+
chalk3.dim(" 3. \u66F4\u65B0 package.json (name, description, author)")
|
|
789
804
|
);
|
|
790
805
|
let step = 4;
|
|
791
806
|
if (projectConfig.initGit) {
|
|
792
|
-
console.log(
|
|
807
|
+
console.log(chalk3.dim(` ${step}. \u521D\u59CB\u5316 Git \u4ED3\u5E93\u5E76\u63D0\u4EA4\u521D\u59CB\u4EE3\u7801`));
|
|
793
808
|
step++;
|
|
794
809
|
}
|
|
795
810
|
if (projectConfig.installDeps) {
|
|
796
811
|
console.log(
|
|
797
|
-
|
|
812
|
+
chalk3.dim(` ${step}. \u4F7F\u7528 ${projectConfig.packageManager} \u5B89\u88C5\u4F9D\u8D56`)
|
|
798
813
|
);
|
|
799
814
|
}
|
|
800
815
|
console.log();
|
|
801
|
-
console.log(
|
|
816
|
+
console.log(chalk3.dim("\u79FB\u9664 --dry-run \u53C2\u6570\u4EE5\u6267\u884C\u521B\u5EFA\u3002"));
|
|
802
817
|
console.log();
|
|
803
818
|
return;
|
|
804
819
|
}
|
|
@@ -808,8 +823,8 @@ async function handleProjectName(projectName, template) {
|
|
|
808
823
|
if (projectName) {
|
|
809
824
|
const v = validateProjectName(projectName);
|
|
810
825
|
if (!v.valid) {
|
|
811
|
-
console.log(
|
|
812
|
-
v.errors.forEach((e) => console.log(
|
|
826
|
+
console.log(chalk3.red("\u274C \u9879\u76EE\u540D\u79F0\u4E0D\u5408\u6CD5:"));
|
|
827
|
+
v.errors.forEach((e) => console.log(chalk3.red(` ${e}`)));
|
|
813
828
|
console.log();
|
|
814
829
|
const { newName } = await inquirer.prompt([
|
|
815
830
|
{
|
|
@@ -854,15 +869,15 @@ async function selectTemplate(templateOption) {
|
|
|
854
869
|
if (all[templateOption]) {
|
|
855
870
|
return { key: templateOption, ...all[templateOption] };
|
|
856
871
|
}
|
|
857
|
-
console.log(
|
|
872
|
+
console.log(chalk3.yellow(`\u26A0\uFE0F \u6A21\u677F "${templateOption}" \u4E0D\u5B58\u5728`));
|
|
858
873
|
console.log();
|
|
859
874
|
}
|
|
860
875
|
return await selectTemplateMethod();
|
|
861
876
|
}
|
|
862
877
|
async function selectTemplateMethod() {
|
|
863
878
|
console.log();
|
|
864
|
-
console.log(
|
|
865
|
-
console.log(
|
|
879
|
+
console.log(chalk3.bold(" \u9009\u62E9\u6A21\u677F\u521B\u5EFA\u65B9\u5F0F"));
|
|
880
|
+
console.log(chalk3.dim(" \u8BF7\u9009\u62E9\u6700\u9002\u5408\u4F60\u7684\u6A21\u677F\u6D4F\u89C8\u65B9\u5F0F"));
|
|
866
881
|
console.log();
|
|
867
882
|
const { selectionMode } = await inquirer.prompt([
|
|
868
883
|
{
|
|
@@ -871,22 +886,19 @@ async function selectTemplateMethod() {
|
|
|
871
886
|
message: "\u6A21\u677F\u9009\u62E9\u65B9\u5F0F:",
|
|
872
887
|
choices: [
|
|
873
888
|
{
|
|
874
|
-
name:
|
|
889
|
+
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
890
|
value: "recommended"
|
|
876
891
|
},
|
|
877
|
-
{ name: chalk2.dim("\u2500".repeat(70)), value: "sep1", disabled: true },
|
|
878
892
|
{
|
|
879
|
-
name:
|
|
893
|
+
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
894
|
value: "category"
|
|
881
895
|
},
|
|
882
|
-
{ name: chalk2.dim("\u2500".repeat(70)), value: "sep2", disabled: true },
|
|
883
896
|
{
|
|
884
|
-
name:
|
|
897
|
+
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
898
|
value: "search"
|
|
886
899
|
},
|
|
887
|
-
{ name: chalk2.dim("\u2500".repeat(70)), value: "sep3", disabled: true },
|
|
888
900
|
{
|
|
889
|
-
name:
|
|
901
|
+
name: `${chalk3.cyan(">")} ${chalk3.bold("\u5168\u90E8\u6A21\u677F")} ${chalk3.dim("\u2014 \u67E5\u770B\u6240\u6709\u53EF\u7528\u6A21\u677F")}`,
|
|
890
902
|
value: "all"
|
|
891
903
|
}
|
|
892
904
|
],
|
|
@@ -909,33 +921,33 @@ async function selectTemplateMethod() {
|
|
|
909
921
|
async function selectFromRecommended() {
|
|
910
922
|
const recommended = getRecommendedTemplates();
|
|
911
923
|
if (Object.keys(recommended).length === 0) {
|
|
912
|
-
console.log(
|
|
924
|
+
console.log(chalk3.yellow("\u26A0\uFE0F \u6682\u65E0\u63A8\u8350\u6A21\u677F"));
|
|
913
925
|
return await selectTemplateMethod();
|
|
914
926
|
}
|
|
915
927
|
console.log();
|
|
916
|
-
console.log(
|
|
917
|
-
console.log(
|
|
928
|
+
console.log(chalk3.bold(" \u63A8\u8350\u6A21\u677F"));
|
|
929
|
+
console.log(chalk3.dim(" \u57FA\u4E8E\u56E2\u961F\u4F7F\u7528\u9891\u7387\u548C\u9879\u76EE\u6210\u719F\u5EA6\u63A8\u8350"));
|
|
918
930
|
console.log();
|
|
919
931
|
const choices = [];
|
|
920
932
|
const entries = Object.entries(recommended);
|
|
921
933
|
entries.forEach(([key, template], index) => {
|
|
922
|
-
const tags = template.features.slice(0, 3).map((f) =>
|
|
923
|
-
const ver = template.version
|
|
934
|
+
const tags = template.features.slice(0, 3).map((f) => chalk3.dim(`[${f}]`)).join(" ");
|
|
935
|
+
const ver = getVersionLabel(template.version);
|
|
924
936
|
choices.push({
|
|
925
|
-
name: `${
|
|
926
|
-
${tags}${template.features.length > 3 ?
|
|
937
|
+
name: `${chalk3.bold.white(template.name.replace(STRIP_VERSION_RE, ""))} ${ver} - ${chalk3.dim(template.description)}
|
|
938
|
+
${tags}${template.features.length > 3 ? chalk3.dim(` +${template.features.length - 3}more`) : ""}`,
|
|
927
939
|
value: { key, ...template },
|
|
928
940
|
short: template.name
|
|
929
941
|
});
|
|
930
942
|
if (index < entries.length - 1) {
|
|
931
943
|
choices.push({
|
|
932
|
-
name:
|
|
944
|
+
name: chalk3.dim("\u2500".repeat(70)),
|
|
933
945
|
value: `sep_${index}`,
|
|
934
946
|
disabled: true
|
|
935
947
|
});
|
|
936
948
|
}
|
|
937
949
|
});
|
|
938
|
-
choices.push({ name:
|
|
950
|
+
choices.push({ name: chalk3.dim(" <- \u8FD4\u56DE\u9009\u62E9\u5176\u4ED6\u65B9\u5F0F"), value: "back" });
|
|
939
951
|
const { selectedTemplate } = await inquirer.prompt([
|
|
940
952
|
{
|
|
941
953
|
type: "list",
|
|
@@ -970,7 +982,7 @@ async function selectCategory() {
|
|
|
970
982
|
value: key
|
|
971
983
|
}));
|
|
972
984
|
choices.push({
|
|
973
|
-
name:
|
|
985
|
+
name: chalk3.dim("\u2190 \u8FD4\u56DE\u6A21\u677F\u9009\u62E9\u65B9\u5F0F"),
|
|
974
986
|
value: "back_to_method"
|
|
975
987
|
});
|
|
976
988
|
const { categoryKey } = await inquirer.prompt([
|
|
@@ -986,12 +998,12 @@ async function selectStack(categoryKey) {
|
|
|
986
998
|
}));
|
|
987
999
|
choices.push(
|
|
988
1000
|
{
|
|
989
|
-
name:
|
|
1001
|
+
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
1002
|
value: "separator",
|
|
991
1003
|
disabled: true
|
|
992
1004
|
},
|
|
993
|
-
{ name:
|
|
994
|
-
{ name:
|
|
1005
|
+
{ name: chalk3.dim("\u2190 \u8FD4\u56DE\u9879\u76EE\u7C7B\u578B\u9009\u62E9"), value: "back_to_category" },
|
|
1006
|
+
{ name: chalk3.dim("\u2190 \u8FD4\u56DE\u6A21\u677F\u9009\u62E9\u65B9\u5F0F"), value: "back_to_method" }
|
|
995
1007
|
);
|
|
996
1008
|
if (choices.length === 4) return choices[0].value;
|
|
997
1009
|
const { stackKey } = await inquirer.prompt([
|
|
@@ -1009,13 +1021,13 @@ async function selectPattern(catKey, stackKey) {
|
|
|
1009
1021
|
}));
|
|
1010
1022
|
choices.push(
|
|
1011
1023
|
{
|
|
1012
|
-
name:
|
|
1024
|
+
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
1025
|
value: "separator",
|
|
1014
1026
|
disabled: true
|
|
1015
1027
|
},
|
|
1016
|
-
{ name:
|
|
1017
|
-
{ name:
|
|
1018
|
-
{ name:
|
|
1028
|
+
{ name: chalk3.dim("\u2190 \u8FD4\u56DE\u6280\u672F\u6808\u9009\u62E9"), value: "back_to_stack" },
|
|
1029
|
+
{ name: chalk3.dim("\u2190 \u8FD4\u56DE\u9879\u76EE\u7C7B\u578B\u9009\u62E9"), value: "back_to_category" },
|
|
1030
|
+
{ name: chalk3.dim("\u2190 \u8FD4\u56DE\u6A21\u677F\u9009\u62E9\u65B9\u5F0F"), value: "back_to_method" }
|
|
1019
1031
|
);
|
|
1020
1032
|
if (choices.length === 5) return choices[0].value;
|
|
1021
1033
|
const { patternKey } = await inquirer.prompt([
|
|
@@ -1029,20 +1041,20 @@ async function selectSpecificTemplate(catKey, stackKey, patternKey) {
|
|
|
1029
1041
|
}
|
|
1030
1042
|
const templates = getTemplatesByCategory(catKey, stackKey, patternKey);
|
|
1031
1043
|
const choices = Object.entries(templates).map(([key, t]) => ({
|
|
1032
|
-
name: `${t.name} - ${
|
|
1044
|
+
name: `${t.name} - ${chalk3.dim(t.description)}`,
|
|
1033
1045
|
value: { key, ...t },
|
|
1034
1046
|
short: t.name
|
|
1035
1047
|
}));
|
|
1036
1048
|
choices.push(
|
|
1037
1049
|
{
|
|
1038
|
-
name:
|
|
1050
|
+
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
1051
|
value: "separator",
|
|
1040
1052
|
disabled: true
|
|
1041
1053
|
},
|
|
1042
|
-
{ name:
|
|
1043
|
-
{ name:
|
|
1044
|
-
{ name:
|
|
1045
|
-
{ name:
|
|
1054
|
+
{ name: chalk3.dim("\u2190 \u8FD4\u56DE\u67B6\u6784\u6A21\u5F0F\u9009\u62E9"), value: "back_to_pattern" },
|
|
1055
|
+
{ name: chalk3.dim("\u2190 \u8FD4\u56DE\u6280\u672F\u6808\u9009\u62E9"), value: "back_to_stack" },
|
|
1056
|
+
{ name: chalk3.dim("\u2190 \u8FD4\u56DE\u9879\u76EE\u7C7B\u578B\u9009\u62E9"), value: "back_to_category" },
|
|
1057
|
+
{ name: chalk3.dim("\u2190 \u8FD4\u56DE\u6A21\u677F\u9009\u62E9\u65B9\u5F0F"), value: "back_to_method" }
|
|
1046
1058
|
);
|
|
1047
1059
|
const { selectedTemplate } = await inquirer.prompt([
|
|
1048
1060
|
{
|
|
@@ -1067,8 +1079,8 @@ async function selectBySearch() {
|
|
|
1067
1079
|
const results = searchTemplates(keyword);
|
|
1068
1080
|
if (Object.keys(results).length === 0) {
|
|
1069
1081
|
console.log();
|
|
1070
|
-
console.log(
|
|
1071
|
-
console.log(
|
|
1082
|
+
console.log(chalk3.yellow("\u6CA1\u6709\u627E\u5230\u5339\u914D\u7684\u6A21\u677F"));
|
|
1083
|
+
console.log(chalk3.dim(`\u641C\u7D22\u5173\u952E\u8BCD: "${keyword}"`));
|
|
1072
1084
|
console.log();
|
|
1073
1085
|
const { action } = await inquirer.prompt([
|
|
1074
1086
|
{
|
|
@@ -1076,8 +1088,8 @@ async function selectBySearch() {
|
|
|
1076
1088
|
name: "action",
|
|
1077
1089
|
message: "\u8BF7\u9009\u62E9\u4E0B\u4E00\u6B65\u64CD\u4F5C:",
|
|
1078
1090
|
choices: [
|
|
1079
|
-
{ name: "\
|
|
1080
|
-
{ name: "\
|
|
1091
|
+
{ name: "\u91CD\u65B0\u641C\u7D22", value: "retry" },
|
|
1092
|
+
{ name: chalk3.dim("<- \u8FD4\u56DE\u6A21\u677F\u9009\u62E9\u65B9\u5F0F"), value: "back" }
|
|
1081
1093
|
]
|
|
1082
1094
|
}
|
|
1083
1095
|
]);
|
|
@@ -1085,9 +1097,9 @@ async function selectBySearch() {
|
|
|
1085
1097
|
return await selectTemplateMethod();
|
|
1086
1098
|
}
|
|
1087
1099
|
console.log();
|
|
1088
|
-
console.log(
|
|
1100
|
+
console.log(chalk3.bold(" \u641C\u7D22\u7ED3\u679C"));
|
|
1089
1101
|
console.log(
|
|
1090
|
-
|
|
1102
|
+
chalk3.dim(
|
|
1091
1103
|
`\u5173\u952E\u8BCD: "${keyword}" \u2022 \u627E\u5230 ${Object.keys(results).length} \u4E2A\u5339\u914D\u6A21\u677F`
|
|
1092
1104
|
)
|
|
1093
1105
|
);
|
|
@@ -1095,23 +1107,23 @@ async function selectBySearch() {
|
|
|
1095
1107
|
const choices = Object.entries(results).map(([key, t]) => {
|
|
1096
1108
|
const hl = (text) => text.replace(
|
|
1097
1109
|
new RegExp(`(${keyword})`, "gi"),
|
|
1098
|
-
|
|
1110
|
+
chalk3.bgYellow.black("$1")
|
|
1099
1111
|
);
|
|
1100
|
-
const ver = t.version
|
|
1112
|
+
const ver = getVersionLabel(t.version);
|
|
1101
1113
|
const info = t.features.slice(0, 2).join(" \u2022 ");
|
|
1102
1114
|
return {
|
|
1103
|
-
name: `${
|
|
1104
|
-
${
|
|
1105
|
-
${
|
|
1106
|
-
${
|
|
1115
|
+
name: `${chalk3.bold(hl(t.name.replace(STRIP_VERSION_RE, "")))} ${ver}
|
|
1116
|
+
${chalk3.dim(hl(t.description))}
|
|
1117
|
+
${chalk3.dim(`${info} \u2022 key: ${key}`)}
|
|
1118
|
+
${chalk3.dim("\u2500".repeat(60))}`,
|
|
1107
1119
|
value: { key, ...t },
|
|
1108
1120
|
short: t.name
|
|
1109
1121
|
};
|
|
1110
1122
|
});
|
|
1111
1123
|
choices.push(
|
|
1112
|
-
{ name:
|
|
1113
|
-
{ name: "\
|
|
1114
|
-
{ name: "\
|
|
1124
|
+
{ name: chalk3.dim("\u2501".repeat(70)), value: "separator", disabled: true },
|
|
1125
|
+
{ name: "\u91CD\u65B0\u641C\u7D22", value: "search_again" },
|
|
1126
|
+
{ name: chalk3.dim("<- \u8FD4\u56DE\u6A21\u677F\u9009\u62E9\u65B9\u5F0F"), value: "back_to_mode" }
|
|
1115
1127
|
);
|
|
1116
1128
|
const { selectedTemplate } = await inquirer.prompt([
|
|
1117
1129
|
{
|
|
@@ -1132,28 +1144,28 @@ async function selectBySearch() {
|
|
|
1132
1144
|
async function selectFromAll() {
|
|
1133
1145
|
const allTemplates = getAllTemplates();
|
|
1134
1146
|
console.log();
|
|
1135
|
-
console.log(
|
|
1136
|
-
console.log(
|
|
1147
|
+
console.log(chalk3.bold(" \u6240\u6709\u53EF\u7528\u6A21\u677F"));
|
|
1148
|
+
console.log(chalk3.dim(` \u5171 ${Object.keys(allTemplates).length} \u4E2A\u6A21\u677F\u53EF\u9009`));
|
|
1137
1149
|
console.log();
|
|
1138
1150
|
const categorizedChoices = [];
|
|
1139
1151
|
for (const [_catKey, category] of Object.entries(TEMPLATE_CATEGORIES)) {
|
|
1140
1152
|
categorizedChoices.push({
|
|
1141
|
-
name:
|
|
1153
|
+
name: chalk3.yellow.bold(category.name),
|
|
1142
1154
|
value: `${_catKey}_header`,
|
|
1143
1155
|
disabled: true
|
|
1144
1156
|
});
|
|
1145
1157
|
for (const [_sKey, stack] of Object.entries(category.stacks)) {
|
|
1146
1158
|
for (const _pattern of Object.values(stack.patterns)) {
|
|
1147
1159
|
for (const [key, t] of Object.entries(_pattern.templates)) {
|
|
1148
|
-
const ver = t.version
|
|
1160
|
+
const ver = getVersionLabel(t.version);
|
|
1149
1161
|
categorizedChoices.push({
|
|
1150
|
-
name: ` \u25CF ${
|
|
1151
|
-
${
|
|
1162
|
+
name: ` \u25CF ${chalk3.bold(t.name.replace(STRIP_VERSION_RE, ""))} ${ver} - ${chalk3.dim(t.description)}
|
|
1163
|
+
${chalk3.dim(`\u6280\u672F\u6808: ${stack.name} \u2022 \u547D\u4EE4: robot create my-app -t ${key}`)}`,
|
|
1152
1164
|
value: { key, ...t },
|
|
1153
1165
|
short: t.name
|
|
1154
1166
|
});
|
|
1155
1167
|
categorizedChoices.push({
|
|
1156
|
-
name:
|
|
1168
|
+
name: chalk3.dim(" " + "\u2500".repeat(66)),
|
|
1157
1169
|
value: `sep_${key}`,
|
|
1158
1170
|
disabled: true
|
|
1159
1171
|
});
|
|
@@ -1162,8 +1174,8 @@ async function selectFromAll() {
|
|
|
1162
1174
|
}
|
|
1163
1175
|
}
|
|
1164
1176
|
categorizedChoices.push(
|
|
1165
|
-
{ name:
|
|
1166
|
-
{ name:
|
|
1177
|
+
{ name: chalk3.dim("\u2501".repeat(70)), value: "separator", disabled: true },
|
|
1178
|
+
{ name: chalk3.dim("<- \u8FD4\u56DE\u6A21\u677F\u9009\u62E9\u65B9\u5F0F"), value: "back_to_mode" }
|
|
1167
1179
|
);
|
|
1168
1180
|
const { selectedTemplate } = await inquirer.prompt([
|
|
1169
1181
|
{
|
|
@@ -1180,7 +1192,7 @@ async function selectFromAll() {
|
|
|
1180
1192
|
}
|
|
1181
1193
|
async function configureProject(options) {
|
|
1182
1194
|
console.log();
|
|
1183
|
-
console.log(
|
|
1195
|
+
console.log(chalk3.bold(" \u9879\u76EE\u914D\u7F6E"));
|
|
1184
1196
|
console.log();
|
|
1185
1197
|
const available = detectPackageManager();
|
|
1186
1198
|
const hasBun = available.includes("bun");
|
|
@@ -1261,37 +1273,37 @@ async function configureProject(options) {
|
|
|
1261
1273
|
name: "action",
|
|
1262
1274
|
message: "\u8BF7\u9009\u62E9\u64CD\u4F5C:",
|
|
1263
1275
|
choices: [
|
|
1264
|
-
{ name: "\
|
|
1265
|
-
{ name: "\
|
|
1276
|
+
{ name: "\u91CD\u65B0\u914D\u7F6E", value: "reconfigure" },
|
|
1277
|
+
{ name: "\u53D6\u6D88\u521B\u5EFA", value: "cancel" }
|
|
1266
1278
|
]
|
|
1267
1279
|
}
|
|
1268
1280
|
]);
|
|
1269
1281
|
if (action === "reconfigure") return await configureProject(options);
|
|
1270
|
-
console.log(
|
|
1282
|
+
console.log(chalk3.yellow("\u53D6\u6D88\u521B\u5EFA\u9879\u76EE"));
|
|
1271
1283
|
process.exit(0);
|
|
1272
1284
|
}
|
|
1273
1285
|
return config;
|
|
1274
1286
|
}
|
|
1275
1287
|
async function confirmCreation(projectName, template, config) {
|
|
1276
1288
|
console.log();
|
|
1277
|
-
console.log(
|
|
1289
|
+
console.log(chalk3.bold(" \u9879\u76EE\u521B\u5EFA\u4FE1\u606F\u786E\u8BA4:"));
|
|
1278
1290
|
console.log();
|
|
1279
|
-
console.log(` \u9879\u76EE\u540D\u79F0: ${
|
|
1280
|
-
console.log(` \u9009\u62E9\u6A21\u677F: ${
|
|
1281
|
-
console.log(` \u6A21\u677F\u63CF\u8FF0: ${
|
|
1291
|
+
console.log(` \u9879\u76EE\u540D\u79F0: ${chalk3.cyan(projectName)}`);
|
|
1292
|
+
console.log(` \u9009\u62E9\u6A21\u677F: ${chalk3.cyan(template.name)}`);
|
|
1293
|
+
console.log(` \u6A21\u677F\u63CF\u8FF0: ${chalk3.dim(template.description)}`);
|
|
1282
1294
|
console.log(
|
|
1283
|
-
` \u5305\u542B\u529F\u80FD: ${
|
|
1295
|
+
` \u5305\u542B\u529F\u80FD: ${chalk3.dim(template.features.join(", ") || "\u81EA\u5B9A\u4E49\u6A21\u677F")}`
|
|
1284
1296
|
);
|
|
1285
1297
|
if (config.description)
|
|
1286
|
-
console.log(` \u9879\u76EE\u63CF\u8FF0: ${
|
|
1287
|
-
if (config.author) console.log(` \u4F5C\u3000\u3000\u8005: ${
|
|
1298
|
+
console.log(` \u9879\u76EE\u63CF\u8FF0: ${chalk3.dim(config.description)}`);
|
|
1299
|
+
if (config.author) console.log(` \u4F5C\u3000\u3000\u8005: ${chalk3.dim(config.author)}`);
|
|
1288
1300
|
console.log(
|
|
1289
|
-
` \u521D\u59CB\u5316Git: ${config.initGit ?
|
|
1301
|
+
` \u521D\u59CB\u5316Git: ${config.initGit ? chalk3.green("\u662F") : chalk3.dim("\u5426")}`
|
|
1290
1302
|
);
|
|
1291
1303
|
console.log(
|
|
1292
|
-
` \u5B89\u88C5\u4F9D\u8D56: ${config.installDeps ?
|
|
1304
|
+
` \u5B89\u88C5\u4F9D\u8D56: ${config.installDeps ? chalk3.green("\u662F") + chalk3.dim(` (${config.packageManager})`) : chalk3.dim("\u5426")}`
|
|
1293
1305
|
);
|
|
1294
|
-
console.log(` \u6E90\u7801\u4ED3\u5E93: ${
|
|
1306
|
+
console.log(` \u6E90\u7801\u4ED3\u5E93: ${chalk3.dim(template.repoUrl)}`);
|
|
1295
1307
|
console.log();
|
|
1296
1308
|
const { confirmed } = await inquirer.prompt([
|
|
1297
1309
|
{
|
|
@@ -1302,7 +1314,7 @@ async function confirmCreation(projectName, template, config) {
|
|
|
1302
1314
|
}
|
|
1303
1315
|
]);
|
|
1304
1316
|
if (!confirmed) {
|
|
1305
|
-
console.log(
|
|
1317
|
+
console.log(chalk3.yellow("\u53D6\u6D88\u521B\u5EFA"));
|
|
1306
1318
|
process.exit(0);
|
|
1307
1319
|
}
|
|
1308
1320
|
}
|
|
@@ -1321,7 +1333,7 @@ async function executeCreation(projectName, template, config, options) {
|
|
|
1321
1333
|
const projectPath = path3.resolve(projectName);
|
|
1322
1334
|
if (fs3.existsSync(projectPath)) {
|
|
1323
1335
|
spinner.stop();
|
|
1324
|
-
console.log(
|
|
1336
|
+
console.log(chalk3.yellow("\u26A0\uFE0F \u9879\u76EE\u76EE\u5F55\u5DF2\u5B58\u5728"));
|
|
1325
1337
|
const { overwrite } = await inquirer.prompt([
|
|
1326
1338
|
{
|
|
1327
1339
|
type: "confirm",
|
|
@@ -1331,7 +1343,7 @@ async function executeCreation(projectName, template, config, options) {
|
|
|
1331
1343
|
}
|
|
1332
1344
|
]);
|
|
1333
1345
|
if (!overwrite) {
|
|
1334
|
-
console.log(
|
|
1346
|
+
console.log(chalk3.yellow("\u274C \u53D6\u6D88\u521B\u5EFA"));
|
|
1335
1347
|
process.exit(0);
|
|
1336
1348
|
}
|
|
1337
1349
|
spinner.start("\u{1F5D1}\uFE0F \u6E05\u7406\u73B0\u6709\u76EE\u5F55...");
|
|
@@ -1349,8 +1361,8 @@ async function executeCreation(projectName, template, config, options) {
|
|
|
1349
1361
|
} catch (error) {
|
|
1350
1362
|
spinner.fail("\u6A21\u677F\u4E0B\u8F7D\u5931\u8D25");
|
|
1351
1363
|
console.log();
|
|
1352
|
-
console.log(
|
|
1353
|
-
console.log(
|
|
1364
|
+
console.log(chalk3.red("\u274C \u6A21\u677F\u4E0B\u8F7D\u9519\u8BEF:"));
|
|
1365
|
+
console.log(chalk3.dim(` ${error.message}`));
|
|
1354
1366
|
console.log();
|
|
1355
1367
|
throw error;
|
|
1356
1368
|
}
|
|
@@ -1370,33 +1382,33 @@ async function executeCreation(projectName, template, config, options) {
|
|
|
1370
1382
|
await fs3.remove(tempPath).catch(() => {
|
|
1371
1383
|
});
|
|
1372
1384
|
}
|
|
1373
|
-
spinner.succeed(
|
|
1385
|
+
spinner.succeed(chalk3.green("\u{1F389} \u9879\u76EE\u521B\u5EFA\u6210\u529F!"));
|
|
1374
1386
|
console.log();
|
|
1375
|
-
console.log(
|
|
1387
|
+
console.log(chalk3.green("\u9879\u76EE\u521B\u5EFA\u5B8C\u6210!"));
|
|
1376
1388
|
console.log();
|
|
1377
|
-
console.log(
|
|
1378
|
-
console.log(` \u4F4D\u7F6E: ${
|
|
1379
|
-
console.log(` \u6A21\u677F: ${
|
|
1389
|
+
console.log(chalk3.blue("\u9879\u76EE\u4FE1\u606F:"));
|
|
1390
|
+
console.log(` \u4F4D\u7F6E: ${chalk3.cyan(projectPath)}`);
|
|
1391
|
+
console.log(` \u6A21\u677F: ${chalk3.cyan(template.name)}`);
|
|
1380
1392
|
console.log(
|
|
1381
|
-
` Git\u4ED3\u5E93: ${config.initGit ?
|
|
1393
|
+
` Git\u4ED3\u5E93: ${config.initGit ? chalk3.green("\u5DF2\u521D\u59CB\u5316") : chalk3.dim("\u672A\u521D\u59CB\u5316")}`
|
|
1382
1394
|
);
|
|
1383
1395
|
console.log(
|
|
1384
|
-
` \u4F9D\u8D56\u5B89\u88C5: ${config.installDeps ?
|
|
1396
|
+
` \u4F9D\u8D56\u5B89\u88C5: ${config.installDeps ? chalk3.green("\u5DF2\u5B8C\u6210") : chalk3.dim("\u9700\u624B\u52A8\u5B89\u88C5")}`
|
|
1385
1397
|
);
|
|
1386
1398
|
console.log();
|
|
1387
|
-
console.log(
|
|
1388
|
-
console.log(
|
|
1399
|
+
console.log(chalk3.blue("\u5FEB\u901F\u5F00\u59CB:"));
|
|
1400
|
+
console.log(chalk3.cyan(` cd ${projectName}`));
|
|
1389
1401
|
const pm = config.packageManager || "bun";
|
|
1390
1402
|
if (!config.installDeps) {
|
|
1391
|
-
console.log(
|
|
1403
|
+
console.log(chalk3.cyan(` ${pm} install`));
|
|
1392
1404
|
}
|
|
1393
1405
|
const cmd = getStartCommand(template, pm);
|
|
1394
|
-
if (cmd) console.log(
|
|
1406
|
+
if (cmd) console.log(chalk3.cyan(` ${cmd}`));
|
|
1395
1407
|
if (pm === "bun")
|
|
1396
|
-
console.log(
|
|
1408
|
+
console.log(chalk3.dim(" # \u6216\u4F7F\u7528 npm: npm install && npm run dev"));
|
|
1397
1409
|
else if (pm === "npm")
|
|
1398
1410
|
console.log(
|
|
1399
|
-
|
|
1411
|
+
chalk3.dim(" # \u6216\u4F7F\u7528 bun: bun install && bun run dev (\u5982\u5DF2\u5B89\u88C5)")
|
|
1400
1412
|
);
|
|
1401
1413
|
console.log();
|
|
1402
1414
|
spinner.start("\u{1F4CA} \u7EDF\u8BA1\u9879\u76EE\u4FE1\u606F...");
|
|
@@ -1409,7 +1421,7 @@ async function executeCreation(projectName, template, config, options) {
|
|
|
1409
1421
|
} catch (error) {
|
|
1410
1422
|
if (tempPath) await fs3.remove(tempPath).catch(() => {
|
|
1411
1423
|
});
|
|
1412
|
-
spinner.fail("\u521B\u5EFA\u9879\u76EE\u5931\u8D25");
|
|
1424
|
+
if (spinner.isSpinning) spinner.fail("\u521B\u5EFA\u9879\u76EE\u5931\u8D25");
|
|
1413
1425
|
throw error;
|
|
1414
1426
|
}
|
|
1415
1427
|
}
|
|
@@ -1455,7 +1467,7 @@ function initializeGitRepository(projectPath) {
|
|
|
1455
1467
|
stdio: "ignore"
|
|
1456
1468
|
});
|
|
1457
1469
|
} catch {
|
|
1458
|
-
console.log(
|
|
1470
|
+
console.log(chalk3.yellow("\u26A0\uFE0F Git \u4E0D\u53EF\u7528\uFF0C\u8DF3\u8FC7\u4ED3\u5E93\u521D\u59CB\u5316"));
|
|
1459
1471
|
}
|
|
1460
1472
|
}
|
|
1461
1473
|
function getStartCommand(template, pm) {
|
|
@@ -1464,12 +1476,12 @@ function getStartCommand(template, pm) {
|
|
|
1464
1476
|
}
|
|
1465
1477
|
|
|
1466
1478
|
// src/doctor.ts
|
|
1467
|
-
import
|
|
1479
|
+
import chalk4 from "chalk";
|
|
1468
1480
|
import ora2 from "ora";
|
|
1469
1481
|
import { execSync as execSync3 } from "child_process";
|
|
1470
1482
|
async function runDoctor(options = {}) {
|
|
1471
1483
|
console.log();
|
|
1472
|
-
console.log(
|
|
1484
|
+
console.log(chalk4.blue.bold("Robot CLI \u73AF\u5883\u8BCA\u65AD"));
|
|
1473
1485
|
console.log();
|
|
1474
1486
|
const results = [];
|
|
1475
1487
|
const nodeVersion = process.version;
|
|
@@ -1477,7 +1489,7 @@ async function runDoctor(options = {}) {
|
|
|
1477
1489
|
results.push({
|
|
1478
1490
|
name: "Node.js",
|
|
1479
1491
|
status: nodeMajor >= 20 ? "ok" : "error",
|
|
1480
|
-
detail: nodeMajor >= 20 ? `${nodeVersion} (\u8981\u6C42 >= 20)` : `${nodeVersion} ${
|
|
1492
|
+
detail: nodeMajor >= 20 ? `${nodeVersion} (\u8981\u6C42 >= 20)` : `${nodeVersion} ${chalk4.red("(\u9700\u8981\u5347\u7EA7\u5230 Node.js 20+)")}`
|
|
1481
1493
|
});
|
|
1482
1494
|
try {
|
|
1483
1495
|
const gitVer = execSync3("git --version", { encoding: "utf8" }).trim().replace("git version ", "");
|
|
@@ -1526,23 +1538,23 @@ async function runDoctor(options = {}) {
|
|
|
1526
1538
|
detail: cacheStats.count > 0 ? `${cacheStats.count} \u4E2A\u6A21\u677F (${formatBytes(cacheStats.totalSize)})` : "\u7A7A"
|
|
1527
1539
|
});
|
|
1528
1540
|
const icons = {
|
|
1529
|
-
ok:
|
|
1530
|
-
warn:
|
|
1531
|
-
error:
|
|
1541
|
+
ok: chalk4.green("\u2705"),
|
|
1542
|
+
warn: chalk4.yellow("\u26A0\uFE0F "),
|
|
1543
|
+
error: chalk4.red("\u274C")
|
|
1532
1544
|
};
|
|
1533
1545
|
for (const r of results) {
|
|
1534
1546
|
const icon = icons[r.status];
|
|
1535
|
-
console.log(` ${icon} ${
|
|
1547
|
+
console.log(` ${icon} ${chalk4.bold(r.name.padEnd(14))} ${r.detail}`);
|
|
1536
1548
|
}
|
|
1537
1549
|
console.log();
|
|
1538
1550
|
const hasError = results.some((r) => r.status === "error");
|
|
1539
1551
|
const hasWarn = results.some((r) => r.status === "warn");
|
|
1540
1552
|
if (hasError) {
|
|
1541
|
-
console.log(
|
|
1553
|
+
console.log(chalk4.red(" \u8BCA\u65AD\u7ED3\u679C: \u73AF\u5883\u5B58\u5728\u95EE\u9898\uFF0C\u8BF7\u4FEE\u590D\u4E0A\u8FF0\u9519\u8BEF \u274C"));
|
|
1542
1554
|
} else if (hasWarn) {
|
|
1543
|
-
console.log(
|
|
1555
|
+
console.log(chalk4.yellow(" \u8BCA\u65AD\u7ED3\u679C: \u73AF\u5883\u57FA\u672C\u6B63\u5E38\uFF0C\u90E8\u5206\u7EC4\u4EF6\u7F3A\u5931 \u26A0\uFE0F"));
|
|
1544
1556
|
} else {
|
|
1545
|
-
console.log(
|
|
1557
|
+
console.log(chalk4.green(" \u8BCA\u65AD\u7ED3\u679C: \u73AF\u5883\u5065\u5EB7 \u2705"));
|
|
1546
1558
|
}
|
|
1547
1559
|
console.log();
|
|
1548
1560
|
if (options.clearCache) {
|
|
@@ -1560,38 +1572,34 @@ function getPackageVersion() {
|
|
|
1560
1572
|
const pkg = JSON.parse(
|
|
1561
1573
|
readFileSync(join(__dirname, "..", "package.json"), "utf8")
|
|
1562
1574
|
);
|
|
1563
|
-
return pkg.version || "
|
|
1575
|
+
return pkg.version || "0.0.0";
|
|
1564
1576
|
} catch {
|
|
1565
|
-
return "
|
|
1577
|
+
return "0.0.0";
|
|
1566
1578
|
}
|
|
1567
1579
|
}
|
|
1568
1580
|
var VERSION = getPackageVersion();
|
|
1581
|
+
var robotGradient = gradient(["#36d1dc", "#5b86e5"]);
|
|
1569
1582
|
function showWelcome() {
|
|
1570
|
-
const
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
borderStyle: "round",
|
|
1584
|
-
borderColor: "cyan"
|
|
1585
|
-
}
|
|
1586
|
-
);
|
|
1587
|
-
console.log(banner);
|
|
1583
|
+
const bannerLines = [
|
|
1584
|
+
" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557",
|
|
1585
|
+
" \u2551 \u2551",
|
|
1586
|
+
" \u2551 R O B O T C L I \u2551",
|
|
1587
|
+
" \u2551 \u2551",
|
|
1588
|
+
" \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"
|
|
1589
|
+
].join("\n");
|
|
1590
|
+
console.log();
|
|
1591
|
+
console.log(robotGradient.multiline(bannerLines));
|
|
1592
|
+
console.log();
|
|
1593
|
+
console.log(chalk5.gray(` v${VERSION} \xB7 \u5DE5\u7A0B\u5316\u9879\u76EE\u811A\u624B\u67B6`));
|
|
1594
|
+
console.log(chalk5.gray(" \u524D\u7AEF \xB7 \u540E\u7AEF \xB7 \u79FB\u52A8\u7AEF \xB7 \u684C\u9762\u7AEF"));
|
|
1595
|
+
console.log();
|
|
1588
1596
|
}
|
|
1589
1597
|
async function showMainMenu() {
|
|
1590
1598
|
const allTemplates = getAllTemplates();
|
|
1591
1599
|
const count = Object.keys(allTemplates).length;
|
|
1592
1600
|
console.log(
|
|
1593
|
-
|
|
1594
|
-
`
|
|
1601
|
+
chalk5.dim(
|
|
1602
|
+
` ${count} \u4E2A\u6A21\u677F\u53EF\u7528 \xB7 Node ${process.version} \xB7 v${VERSION}`
|
|
1595
1603
|
)
|
|
1596
1604
|
);
|
|
1597
1605
|
console.log();
|
|
@@ -1602,23 +1610,23 @@ async function showMainMenu() {
|
|
|
1602
1610
|
message: "\u8BF7\u9009\u62E9\u64CD\u4F5C:",
|
|
1603
1611
|
choices: [
|
|
1604
1612
|
{
|
|
1605
|
-
name:
|
|
1613
|
+
name: `${chalk5.cyan(">")} ${chalk5.bold("\u521B\u5EFA\u65B0\u9879\u76EE")} ${chalk5.dim("\u2014 \u9009\u62E9\u6A21\u677F\u521B\u5EFA\u9879\u76EE")}`,
|
|
1606
1614
|
value: "create"
|
|
1607
1615
|
},
|
|
1608
1616
|
{
|
|
1609
|
-
name:
|
|
1617
|
+
name: `${chalk5.cyan(">")} ${chalk5.bold("\u67E5\u770B\u6A21\u677F\u5217\u8868")} ${chalk5.dim("\u2014 \u6D4F\u89C8\u6240\u6709\u53EF\u7528\u6A21\u677F")}`,
|
|
1610
1618
|
value: "list"
|
|
1611
1619
|
},
|
|
1612
1620
|
{
|
|
1613
|
-
name:
|
|
1621
|
+
name: `${chalk5.cyan(">")} ${chalk5.bold("\u641C\u7D22\u6A21\u677F")} ${chalk5.dim("\u2014 \u6309\u5173\u952E\u8BCD\u641C\u7D22\u6A21\u677F")}`,
|
|
1614
1622
|
value: "search"
|
|
1615
1623
|
},
|
|
1616
1624
|
{
|
|
1617
|
-
name:
|
|
1625
|
+
name: `${chalk5.cyan(">")} ${chalk5.bold("\u73AF\u5883\u8BCA\u65AD")} ${chalk5.dim("\u2014 \u68C0\u67E5\u5F00\u53D1\u73AF\u5883")}`,
|
|
1618
1626
|
value: "doctor"
|
|
1619
1627
|
},
|
|
1620
|
-
{ name:
|
|
1621
|
-
{ name:
|
|
1628
|
+
{ name: chalk5.dim("\u2500".repeat(50)), value: "sep", disabled: true },
|
|
1629
|
+
{ name: `${chalk5.dim(" \u9000\u51FA")}`, value: "exit" }
|
|
1622
1630
|
]
|
|
1623
1631
|
}
|
|
1624
1632
|
]);
|
|
@@ -1636,26 +1644,26 @@ async function showMainMenu() {
|
|
|
1636
1644
|
await runDoctor();
|
|
1637
1645
|
break;
|
|
1638
1646
|
case "exit":
|
|
1639
|
-
console.log(
|
|
1647
|
+
console.log(chalk5.dim(" \u518D\u89C1!"));
|
|
1640
1648
|
process.exit(0);
|
|
1641
1649
|
}
|
|
1642
1650
|
}
|
|
1643
1651
|
function showTemplateList(recommended) {
|
|
1644
1652
|
const templates = recommended ? getRecommendedTemplates() : getAllTemplates();
|
|
1645
|
-
const title = recommended ? "\
|
|
1653
|
+
const title = recommended ? "\u63A8\u8350\u6A21\u677F" : "\u6240\u6709\u6A21\u677F";
|
|
1646
1654
|
const entries = Object.entries(templates);
|
|
1647
1655
|
console.log();
|
|
1648
|
-
console.log(
|
|
1649
|
-
console.log(
|
|
1656
|
+
console.log(chalk5.blue.bold(title));
|
|
1657
|
+
console.log(chalk5.dim(`\u5171 ${entries.length} \u4E2A\u6A21\u677F`));
|
|
1650
1658
|
console.log();
|
|
1651
1659
|
for (const [key, t] of entries) {
|
|
1652
|
-
const ver = t.version === "full" ?
|
|
1660
|
+
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
1661
|
const cat = getCategoryForTemplate(key);
|
|
1654
|
-
const catLabel = cat ?
|
|
1655
|
-
console.log(` ${
|
|
1656
|
-
console.log(` ${
|
|
1657
|
-
console.log(` ${
|
|
1658
|
-
console.log(` ${
|
|
1662
|
+
const catLabel = cat ? chalk5.dim(`[${cat.name}]`) : "";
|
|
1663
|
+
console.log(` ${chalk5.bold(t.name)} ${ver} ${catLabel}`);
|
|
1664
|
+
console.log(` ${chalk5.dim(t.description)}`);
|
|
1665
|
+
console.log(` ${chalk5.dim(`\u547D\u4EE4: robot create my-app -t ${key}`)}`);
|
|
1666
|
+
console.log(` ${chalk5.dim(`features: ${t.features.join(", ")}`)}`);
|
|
1659
1667
|
console.log();
|
|
1660
1668
|
}
|
|
1661
1669
|
}
|
|
@@ -1675,29 +1683,48 @@ function showSearchResults(keyword) {
|
|
|
1675
1683
|
const entries = Object.entries(results);
|
|
1676
1684
|
console.log();
|
|
1677
1685
|
if (entries.length === 0) {
|
|
1678
|
-
console.log(
|
|
1686
|
+
console.log(chalk5.yellow(`\u6CA1\u6709\u627E\u5230\u300C${keyword}\u300D\u76F8\u5173\u6A21\u677F`));
|
|
1679
1687
|
console.log();
|
|
1680
1688
|
return;
|
|
1681
1689
|
}
|
|
1682
|
-
console.log(
|
|
1683
|
-
console.log(
|
|
1690
|
+
console.log(chalk5.green.bold(`\u641C\u7D22\u7ED3\u679C: "${keyword}"`));
|
|
1691
|
+
console.log(chalk5.dim(`\u627E\u5230 ${entries.length} \u4E2A\u5339\u914D`));
|
|
1684
1692
|
console.log();
|
|
1685
1693
|
for (const [key, t] of entries) {
|
|
1686
|
-
const ver = t.version === "full" ?
|
|
1687
|
-
console.log(` ${
|
|
1688
|
-
console.log(` ${
|
|
1689
|
-
console.log(` ${
|
|
1694
|
+
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}]`);
|
|
1695
|
+
console.log(` ${chalk5.bold(t.name)} ${ver}`);
|
|
1696
|
+
console.log(` ${chalk5.dim(t.description)}`);
|
|
1697
|
+
console.log(` ${chalk5.dim(`robot create my-app -t ${key}`)}`);
|
|
1698
|
+
console.log();
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1701
|
+
async function notifyUpdate() {
|
|
1702
|
+
const newVersion = await checkForUpdates(
|
|
1703
|
+
"@agile-team/robot-cli",
|
|
1704
|
+
VERSION
|
|
1705
|
+
).catch(() => null);
|
|
1706
|
+
if (newVersion) {
|
|
1707
|
+
console.log();
|
|
1708
|
+
console.log(
|
|
1709
|
+
chalk5.yellow(
|
|
1710
|
+
` \u250C\u2500 \u53D1\u73B0\u65B0\u7248\u672C: ${chalk5.dim(VERSION)} \u2192 ${chalk5.bold.green(newVersion)}`
|
|
1711
|
+
)
|
|
1712
|
+
);
|
|
1713
|
+
console.log(
|
|
1714
|
+
chalk5.yellow(
|
|
1715
|
+
` \u2514\u2500 \u66F4\u65B0\u547D\u4EE4: ${chalk5.cyan("bun add -g @agile-team/robot-cli")}`
|
|
1716
|
+
)
|
|
1717
|
+
);
|
|
1690
1718
|
console.log();
|
|
1691
1719
|
}
|
|
1692
1720
|
}
|
|
1693
1721
|
async function main() {
|
|
1694
1722
|
const program = new Command();
|
|
1695
|
-
program.name("robot").description("
|
|
1723
|
+
program.name("robot").description("Robot CLI - \u5DE5\u7A0B\u5316\u9879\u76EE\u811A\u624B\u67B6").version(VERSION, "-v, --version");
|
|
1696
1724
|
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
1725
|
showWelcome();
|
|
1698
1726
|
await createProject(projectName, opts);
|
|
1699
|
-
|
|
1700
|
-
});
|
|
1727
|
+
await notifyUpdate();
|
|
1701
1728
|
});
|
|
1702
1729
|
program.command("list").description("\u67E5\u770B\u6A21\u677F\u5217\u8868").option("-r, --recommended", "\u53EA\u663E\u793A\u63A8\u8350\u6A21\u677F").action((opts) => {
|
|
1703
1730
|
showTemplateList(!!opts.recommended);
|
package/package.json
CHANGED
|
@@ -1,77 +1,77 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@agile-team/robot-cli",
|
|
3
|
-
"version": "2.
|
|
4
|
-
"description": "🤖 现代化项目脚手架工具,支持多技术栈快速创建项目 - 优先 bun,兼容 npm/pnpm/yarn",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"bin": {
|
|
7
|
-
"robot": "bin/robot.js"
|
|
8
|
-
},
|
|
9
|
-
"scripts": {
|
|
10
|
-
"build": "tsup",
|
|
11
|
-
"dev": "tsup --watch",
|
|
12
|
-
"test": "vitest run",
|
|
13
|
-
"test:watch": "vitest",
|
|
14
|
-
"lint": "oxlint src/ tests/",
|
|
15
|
-
"lint:fix": "oxlint --fix src/ tests/",
|
|
16
|
-
"typecheck": "tsc --noEmit",
|
|
17
|
-
"prepublishOnly": "bun run build && bun run test",
|
|
18
|
-
"release:patch": "bun version patch && bunx npm publish --access public",
|
|
19
|
-
"release:minor": "bun version minor && bunx npm publish --access public",
|
|
20
|
-
"release:major": "bun version major && bunx npm publish --access public"
|
|
21
|
-
},
|
|
22
|
-
"dependencies": {
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"inquirer": "^9.2.0",
|
|
29
|
-
"ora": "^7.0.0"
|
|
30
|
-
},
|
|
31
|
-
"devDependencies": {
|
|
32
|
-
"@types/fs-extra": "^11.0.4",
|
|
33
|
-
"@types/inquirer": "^9.0.9",
|
|
34
|
-
"@types/node": "^22.0.0",
|
|
35
|
-
"oxlint": "^0.16.0",
|
|
36
|
-
"tsup": "^8.4.0",
|
|
37
|
-
"typescript": "^5.7.0",
|
|
38
|
-
"vitest": "^3.0.0"
|
|
39
|
-
},
|
|
40
|
-
"files": [
|
|
41
|
-
"bin",
|
|
42
|
-
"dist",
|
|
43
|
-
"README.md",
|
|
44
|
-
"CHANGELOG.md"
|
|
45
|
-
],
|
|
46
|
-
"keywords": [
|
|
47
|
-
"cli",
|
|
48
|
-
"scaffold",
|
|
49
|
-
"template",
|
|
50
|
-
"vue",
|
|
51
|
-
"react",
|
|
52
|
-
"node",
|
|
53
|
-
"uni-app",
|
|
54
|
-
"electron",
|
|
55
|
-
"project-generator",
|
|
56
|
-
"boilerplate",
|
|
57
|
-
"bun-first",
|
|
58
|
-
"package-manager-smart",
|
|
59
|
-
"cheny"
|
|
60
|
-
],
|
|
61
|
-
"engines": {
|
|
62
|
-
"node": ">=20.0.0"
|
|
63
|
-
},
|
|
64
|
-
"homepage": "https://github.com/ChenyCHENYU/robot-cli#readme",
|
|
65
|
-
"repository": {
|
|
66
|
-
"type": "git",
|
|
67
|
-
"url": "git+https://github.com/ChenyCHENYU/robot-cli.git"
|
|
68
|
-
},
|
|
69
|
-
"bugs": {
|
|
70
|
-
"url": "https://github.com/ChenyCHENYU/robot-cli/issues"
|
|
71
|
-
},
|
|
72
|
-
"author": "CHENY <ycyplus@gmail.com>",
|
|
73
|
-
"license": "MIT",
|
|
74
|
-
"publishConfig": {
|
|
75
|
-
"access": "public"
|
|
76
|
-
}
|
|
77
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@agile-team/robot-cli",
|
|
3
|
+
"version": "2.2.0",
|
|
4
|
+
"description": "🤖 现代化项目脚手架工具,支持多技术栈快速创建项目 - 优先 bun,兼容 npm/pnpm/yarn",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"robot": "bin/robot.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsup",
|
|
11
|
+
"dev": "tsup --watch",
|
|
12
|
+
"test": "vitest run",
|
|
13
|
+
"test:watch": "vitest",
|
|
14
|
+
"lint": "oxlint src/ tests/",
|
|
15
|
+
"lint:fix": "oxlint --fix src/ tests/",
|
|
16
|
+
"typecheck": "tsc --noEmit",
|
|
17
|
+
"prepublishOnly": "bun run build && bun run test",
|
|
18
|
+
"release:patch": "bun version patch && bunx npm publish --access public",
|
|
19
|
+
"release:minor": "bun version minor && bunx npm publish --access public",
|
|
20
|
+
"release:major": "bun version major && bunx npm publish --access public"
|
|
21
|
+
},
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"chalk": "^5.3.0",
|
|
24
|
+
"commander": "^11.0.0",
|
|
25
|
+
"extract-zip": "^2.0.1",
|
|
26
|
+
"fs-extra": "^11.1.0",
|
|
27
|
+
"gradient-string": "^3.0.0",
|
|
28
|
+
"inquirer": "^9.2.0",
|
|
29
|
+
"ora": "^7.0.0"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/fs-extra": "^11.0.4",
|
|
33
|
+
"@types/inquirer": "^9.0.9",
|
|
34
|
+
"@types/node": "^22.0.0",
|
|
35
|
+
"oxlint": "^0.16.0",
|
|
36
|
+
"tsup": "^8.4.0",
|
|
37
|
+
"typescript": "^5.7.0",
|
|
38
|
+
"vitest": "^3.0.0"
|
|
39
|
+
},
|
|
40
|
+
"files": [
|
|
41
|
+
"bin",
|
|
42
|
+
"dist",
|
|
43
|
+
"README.md",
|
|
44
|
+
"CHANGELOG.md"
|
|
45
|
+
],
|
|
46
|
+
"keywords": [
|
|
47
|
+
"cli",
|
|
48
|
+
"scaffold",
|
|
49
|
+
"template",
|
|
50
|
+
"vue",
|
|
51
|
+
"react",
|
|
52
|
+
"node",
|
|
53
|
+
"uni-app",
|
|
54
|
+
"electron",
|
|
55
|
+
"project-generator",
|
|
56
|
+
"boilerplate",
|
|
57
|
+
"bun-first",
|
|
58
|
+
"package-manager-smart",
|
|
59
|
+
"cheny"
|
|
60
|
+
],
|
|
61
|
+
"engines": {
|
|
62
|
+
"node": ">=20.0.0"
|
|
63
|
+
},
|
|
64
|
+
"homepage": "https://github.com/ChenyCHENYU/robot-cli#readme",
|
|
65
|
+
"repository": {
|
|
66
|
+
"type": "git",
|
|
67
|
+
"url": "git+https://github.com/ChenyCHENYU/robot-cli.git"
|
|
68
|
+
},
|
|
69
|
+
"bugs": {
|
|
70
|
+
"url": "https://github.com/ChenyCHENYU/robot-cli/issues"
|
|
71
|
+
},
|
|
72
|
+
"author": "CHENY <ycyplus@gmail.com>",
|
|
73
|
+
"license": "MIT",
|
|
74
|
+
"publishConfig": {
|
|
75
|
+
"access": "public"
|
|
76
|
+
}
|
|
77
|
+
}
|