@agile-team/robot-cli 1.1.0 → 1.1.2
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/lib/create.js +235 -47
- package/package.json +1 -1
package/lib/create.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// lib/create.js -
|
|
1
|
+
// lib/create.js - 完整优化版,移除缓存功能 + 美化展示
|
|
2
2
|
import fs from "fs-extra";
|
|
3
3
|
import path from "path";
|
|
4
4
|
import chalk from "chalk";
|
|
@@ -129,20 +129,57 @@ async function selectTemplate(templateOption) {
|
|
|
129
129
|
}
|
|
130
130
|
|
|
131
131
|
/**
|
|
132
|
-
* 选择模板方式
|
|
132
|
+
* 选择模板方式 - 优化主菜单
|
|
133
133
|
*/
|
|
134
134
|
async function selectTemplateMethod() {
|
|
135
|
+
console.log();
|
|
136
|
+
console.log(chalk.blue.bold("🎯 选择模板创建方式"));
|
|
137
|
+
console.log(chalk.dim("请选择最适合你的模板浏览方式"));
|
|
138
|
+
console.log();
|
|
139
|
+
|
|
135
140
|
const { selectionMode } = await inquirer.prompt([
|
|
136
141
|
{
|
|
137
142
|
type: "list",
|
|
138
143
|
name: "selectionMode",
|
|
139
|
-
message: "
|
|
144
|
+
message: "模板选择方式:",
|
|
140
145
|
choices: [
|
|
141
|
-
{
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
146
|
+
{
|
|
147
|
+
name: `🎯 ${chalk.bold('推荐模板')} ${chalk.dim('(常用模板快速选择)')}
|
|
148
|
+
${chalk.dim('- 基于团队使用频率推荐的热门模板')}`,
|
|
149
|
+
value: "recommended"
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
name: "",
|
|
153
|
+
value: "spacer1",
|
|
154
|
+
disabled: true
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
name: `📁 ${chalk.bold('分类模板')} ${chalk.dim('(按项目类型分类选择)')}
|
|
158
|
+
${chalk.dim('- 前端、后端、移动端、桌面端分类浏览')}`,
|
|
159
|
+
value: "category"
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
name: "",
|
|
163
|
+
value: "spacer2",
|
|
164
|
+
disabled: true
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
name: `🔍 ${chalk.bold('搜索模板')} ${chalk.dim('(关键词搜索)')}
|
|
168
|
+
${chalk.dim('- 通过技术栈、功能特性等关键词快速查找')}`,
|
|
169
|
+
value: "search"
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
name: "",
|
|
173
|
+
value: "spacer3",
|
|
174
|
+
disabled: true
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
name: `📋 ${chalk.bold('全部模板')} ${chalk.dim('(查看所有可用模板)')}
|
|
178
|
+
${chalk.dim('- 按分类展示所有可用的项目模板')}`,
|
|
179
|
+
value: "all"
|
|
180
|
+
},
|
|
145
181
|
],
|
|
182
|
+
pageSize: 12
|
|
146
183
|
},
|
|
147
184
|
]);
|
|
148
185
|
|
|
@@ -161,7 +198,7 @@ async function selectTemplateMethod() {
|
|
|
161
198
|
}
|
|
162
199
|
|
|
163
200
|
/**
|
|
164
|
-
* 从推荐模板中选择
|
|
201
|
+
* 从推荐模板中选择 - 优化后的展示
|
|
165
202
|
*/
|
|
166
203
|
async function selectFromRecommended() {
|
|
167
204
|
const recommended = getRecommendedTemplates();
|
|
@@ -172,17 +209,34 @@ async function selectFromRecommended() {
|
|
|
172
209
|
}
|
|
173
210
|
|
|
174
211
|
console.log();
|
|
175
|
-
console.log(chalk.blue("🎯 推荐模板
|
|
212
|
+
console.log(chalk.blue.bold("🎯 推荐模板"));
|
|
213
|
+
console.log(chalk.dim("基于团队使用频率和项目成熟度推荐"));
|
|
176
214
|
console.log();
|
|
177
215
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
216
|
+
// 创建更美观的选择项
|
|
217
|
+
const choices = Object.entries(recommended).map(([key, template]) => {
|
|
218
|
+
// 构建特性标签
|
|
219
|
+
const featureTags = template.features.slice(0, 3).map(f =>
|
|
220
|
+
chalk.cyan(`[${f}]`)
|
|
221
|
+
).join(' ');
|
|
222
|
+
|
|
223
|
+
// 版本标签 - 只保留方括号内的版本
|
|
224
|
+
const versionTag = template.version === 'full' ?
|
|
225
|
+
chalk.green('[完整版]') :
|
|
226
|
+
chalk.yellow('[精简版]');
|
|
227
|
+
|
|
228
|
+
return {
|
|
229
|
+
name: `${chalk.bold.white(template.name)} ${versionTag}
|
|
230
|
+
${chalk.dim(template.description)}
|
|
231
|
+
${featureTags}${template.features.length > 3 ? chalk.dim(` +${template.features.length - 3}more`) : ''}
|
|
232
|
+
${chalk.dim('━'.repeat(60))}`,
|
|
233
|
+
value: { key, ...template },
|
|
234
|
+
short: template.name,
|
|
235
|
+
};
|
|
236
|
+
});
|
|
183
237
|
|
|
184
238
|
choices.push({
|
|
185
|
-
name: chalk.dim("
|
|
239
|
+
name: chalk.dim("⬅️ 返回选择其他方式"),
|
|
186
240
|
value: "back",
|
|
187
241
|
});
|
|
188
242
|
|
|
@@ -192,7 +246,8 @@ async function selectFromRecommended() {
|
|
|
192
246
|
name: "selectedTemplate",
|
|
193
247
|
message: "选择推荐模板:",
|
|
194
248
|
choices,
|
|
195
|
-
pageSize:
|
|
249
|
+
pageSize: 8,
|
|
250
|
+
loop: false
|
|
196
251
|
},
|
|
197
252
|
]);
|
|
198
253
|
|
|
@@ -412,7 +467,7 @@ async function selectSpecificTemplate(categoryKey, stackKey, patternKey) {
|
|
|
412
467
|
}
|
|
413
468
|
|
|
414
469
|
/**
|
|
415
|
-
* 搜索选择模板
|
|
470
|
+
* 搜索选择模板 - 优化结果展示
|
|
416
471
|
*/
|
|
417
472
|
async function selectBySearch() {
|
|
418
473
|
while (true) {
|
|
@@ -428,7 +483,9 @@ async function selectBySearch() {
|
|
|
428
483
|
const results = searchTemplates(keyword);
|
|
429
484
|
|
|
430
485
|
if (Object.keys(results).length === 0) {
|
|
486
|
+
console.log();
|
|
431
487
|
console.log(chalk.yellow("🔍 没有找到匹配的模板"));
|
|
488
|
+
console.log(chalk.dim(`搜索关键词: "${keyword}"`));
|
|
432
489
|
console.log();
|
|
433
490
|
|
|
434
491
|
const { action } = await inquirer.prompt([
|
|
@@ -438,39 +495,57 @@ async function selectBySearch() {
|
|
|
438
495
|
message: "请选择下一步操作:",
|
|
439
496
|
choices: [
|
|
440
497
|
{ name: "🔍 重新搜索", value: "retry" },
|
|
441
|
-
{ name: "
|
|
498
|
+
{ name: "⬅️ 返回模板选择方式", value: "back" },
|
|
442
499
|
],
|
|
443
500
|
},
|
|
444
501
|
]);
|
|
445
502
|
|
|
446
503
|
if (action === "retry") {
|
|
447
|
-
continue;
|
|
504
|
+
continue;
|
|
448
505
|
} else {
|
|
449
|
-
return await selectTemplateMethod();
|
|
506
|
+
return await selectTemplateMethod();
|
|
450
507
|
}
|
|
451
508
|
}
|
|
452
509
|
|
|
453
510
|
console.log();
|
|
454
|
-
console.log(
|
|
455
|
-
|
|
456
|
-
);
|
|
511
|
+
console.log(chalk.green.bold(`🔍 搜索结果`));
|
|
512
|
+
console.log(chalk.dim(`关键词: "${keyword}" • 找到 ${Object.keys(results).length} 个匹配模板`));
|
|
457
513
|
console.log();
|
|
458
514
|
|
|
459
|
-
const choices = Object.entries(results).map(([key, template]) =>
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
515
|
+
const choices = Object.entries(results).map(([key, template]) => {
|
|
516
|
+
// 高亮匹配的关键词
|
|
517
|
+
const highlightText = (text) => {
|
|
518
|
+
const regex = new RegExp(`(${keyword})`, 'gi');
|
|
519
|
+
return text.replace(regex, chalk.bgYellow.black('$1'));
|
|
520
|
+
};
|
|
521
|
+
|
|
522
|
+
const techInfo = template.features.slice(0, 2).join(' • ');
|
|
523
|
+
const versionTag = template.version === 'full' ?
|
|
524
|
+
chalk.green('[完整版]') : chalk.yellow('[精简版]');
|
|
525
|
+
|
|
526
|
+
return {
|
|
527
|
+
name: `${chalk.bold(highlightText(template.name))} ${versionTag}
|
|
528
|
+
${chalk.dim(highlightText(template.description))}
|
|
529
|
+
${chalk.blue(techInfo)} ${chalk.gray(`• 模板key: ${key}`)}
|
|
530
|
+
${chalk.dim('─'.repeat(60))}`,
|
|
531
|
+
value: { key, ...template },
|
|
532
|
+
short: template.name,
|
|
533
|
+
};
|
|
534
|
+
});
|
|
464
535
|
|
|
465
|
-
// 添加操作选项
|
|
466
536
|
choices.push(
|
|
467
537
|
{
|
|
468
|
-
name:
|
|
538
|
+
name: "",
|
|
539
|
+
value: "spacer",
|
|
540
|
+
disabled: true
|
|
541
|
+
},
|
|
542
|
+
{
|
|
543
|
+
name: chalk.dim("━".repeat(70)),
|
|
469
544
|
value: "separator",
|
|
470
545
|
disabled: true,
|
|
471
546
|
},
|
|
472
547
|
{ name: "🔍 重新搜索", value: "search_again" },
|
|
473
|
-
{ name: "
|
|
548
|
+
{ name: "⬅️ 返回模板选择方式", value: "back_to_mode" }
|
|
474
549
|
);
|
|
475
550
|
|
|
476
551
|
const { selectedTemplate } = await inquirer.prompt([
|
|
@@ -480,13 +555,14 @@ async function selectBySearch() {
|
|
|
480
555
|
message: "选择模板:",
|
|
481
556
|
choices,
|
|
482
557
|
pageSize: 15,
|
|
558
|
+
loop: false
|
|
483
559
|
},
|
|
484
560
|
]);
|
|
485
561
|
|
|
486
562
|
if (selectedTemplate === "search_again") {
|
|
487
|
-
continue;
|
|
563
|
+
continue;
|
|
488
564
|
} else if (selectedTemplate === "back_to_mode") {
|
|
489
|
-
return await selectTemplateMethod();
|
|
565
|
+
return await selectTemplateMethod();
|
|
490
566
|
} else {
|
|
491
567
|
return selectedTemplate;
|
|
492
568
|
}
|
|
@@ -494,31 +570,142 @@ async function selectBySearch() {
|
|
|
494
570
|
}
|
|
495
571
|
|
|
496
572
|
/**
|
|
497
|
-
* 从全部模板中选择
|
|
573
|
+
* 从全部模板中选择 - 优化后的展示
|
|
498
574
|
*/
|
|
499
575
|
async function selectFromAll() {
|
|
500
576
|
const allTemplates = getAllTemplates();
|
|
501
577
|
|
|
502
578
|
console.log();
|
|
503
|
-
console.log(
|
|
504
|
-
|
|
505
|
-
);
|
|
579
|
+
console.log(chalk.blue.bold(`📋 所有可用模板`));
|
|
580
|
+
console.log(chalk.dim(`共 ${Object.keys(allTemplates).length} 个模板可选`));
|
|
506
581
|
console.log();
|
|
507
582
|
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
583
|
+
// 按分类组织模板
|
|
584
|
+
const categorizedChoices = [];
|
|
585
|
+
|
|
586
|
+
// 前端模板
|
|
587
|
+
categorizedChoices.push({
|
|
588
|
+
name: chalk.yellow.bold("🎨 前端项目"),
|
|
589
|
+
value: "frontend_header",
|
|
590
|
+
disabled: true
|
|
591
|
+
});
|
|
592
|
+
|
|
593
|
+
Object.entries(allTemplates)
|
|
594
|
+
.filter(([key]) => key.includes('admin') || key.includes('react') || key.includes('micro'))
|
|
595
|
+
.forEach(([key, template]) => {
|
|
596
|
+
const techStack = key.includes('admin') ? 'Vue3' :
|
|
597
|
+
key.includes('react') ? 'React' : 'Vue3';
|
|
598
|
+
const versionTag = template.version === 'full' ?
|
|
599
|
+
chalk.green('[完整版]') : chalk.yellow('[精简版]');
|
|
600
|
+
|
|
601
|
+
categorizedChoices.push({
|
|
602
|
+
name: ` ● ${chalk.bold(template.name)} ${versionTag}
|
|
603
|
+
${chalk.dim(template.description)}
|
|
604
|
+
${chalk.blue(`技术栈: ${techStack}`)} ${chalk.gray(`• 命令: robot create my-app -t ${key}`)}`,
|
|
605
|
+
value: { key, ...template },
|
|
606
|
+
short: template.name
|
|
607
|
+
});
|
|
608
|
+
});
|
|
609
|
+
|
|
610
|
+
// 移动端模板
|
|
611
|
+
categorizedChoices.push({
|
|
612
|
+
name: "",
|
|
613
|
+
value: "spacer1",
|
|
614
|
+
disabled: true
|
|
615
|
+
});
|
|
616
|
+
categorizedChoices.push({
|
|
617
|
+
name: chalk.yellow.bold("📱 移动端项目"),
|
|
618
|
+
value: "mobile_header",
|
|
619
|
+
disabled: true
|
|
620
|
+
});
|
|
621
|
+
|
|
622
|
+
Object.entries(allTemplates)
|
|
623
|
+
.filter(([key]) => key.includes('uniapp') || key.includes('tarao'))
|
|
624
|
+
.forEach(([key, template]) => {
|
|
625
|
+
const versionTag = template.version === 'full' ?
|
|
626
|
+
chalk.green('[完整版]') : chalk.yellow('[精简版]');
|
|
627
|
+
|
|
628
|
+
categorizedChoices.push({
|
|
629
|
+
name: ` ● ${chalk.bold(template.name)} ${versionTag}
|
|
630
|
+
${chalk.dim(template.description)}
|
|
631
|
+
${chalk.blue('跨平台: 小程序/H5/App')} ${chalk.gray(`• 命令: robot create my-app -t ${key}`)}`,
|
|
632
|
+
value: { key, ...template },
|
|
633
|
+
short: template.name
|
|
634
|
+
});
|
|
635
|
+
});
|
|
636
|
+
|
|
637
|
+
// 后端模板
|
|
638
|
+
categorizedChoices.push({
|
|
639
|
+
name: "",
|
|
640
|
+
value: "spacer2",
|
|
641
|
+
disabled: true
|
|
642
|
+
});
|
|
643
|
+
categorizedChoices.push({
|
|
644
|
+
name: chalk.yellow.bold("🚀 后端项目"),
|
|
645
|
+
value: "backend_header",
|
|
646
|
+
disabled: true
|
|
647
|
+
});
|
|
648
|
+
|
|
649
|
+
Object.entries(allTemplates)
|
|
650
|
+
.filter(([key]) => key.includes('nest') || key.includes('koa'))
|
|
651
|
+
.forEach(([key, template]) => {
|
|
652
|
+
const framework = key.includes('nest') ? 'NestJS' : 'Koa3';
|
|
653
|
+
const versionTag = template.version === 'full' ?
|
|
654
|
+
chalk.green('[完整版]') : chalk.yellow('[精简版]');
|
|
655
|
+
|
|
656
|
+
categorizedChoices.push({
|
|
657
|
+
name: ` ● ${chalk.bold(template.name)} ${versionTag}
|
|
658
|
+
${chalk.dim(template.description)}
|
|
659
|
+
${chalk.blue(`框架: ${framework}`)} ${chalk.gray(`• 命令: robot create my-app -t ${key}`)}`,
|
|
660
|
+
value: { key, ...template },
|
|
661
|
+
short: template.name
|
|
662
|
+
});
|
|
663
|
+
});
|
|
664
|
+
|
|
665
|
+
// 桌面端模板
|
|
666
|
+
categorizedChoices.push({
|
|
667
|
+
name: "",
|
|
668
|
+
value: "spacer3",
|
|
669
|
+
disabled: true
|
|
670
|
+
});
|
|
671
|
+
categorizedChoices.push({
|
|
672
|
+
name: chalk.yellow.bold("💻 桌面端项目"),
|
|
673
|
+
value: "desktop_header",
|
|
674
|
+
disabled: true
|
|
675
|
+
});
|
|
676
|
+
|
|
677
|
+
Object.entries(allTemplates)
|
|
678
|
+
.filter(([key]) => key.includes('electron') || key.includes('tauri'))
|
|
679
|
+
.forEach(([key, template]) => {
|
|
680
|
+
const framework = key.includes('electron') ? 'Electron' : 'Tauri';
|
|
681
|
+
const versionTag = template.version === 'full' ?
|
|
682
|
+
chalk.green('[完整版]') : chalk.yellow('[精简版]');
|
|
683
|
+
|
|
684
|
+
categorizedChoices.push({
|
|
685
|
+
name: ` ● ${chalk.bold(template.name)} ${versionTag}
|
|
686
|
+
${chalk.dim(template.description)}
|
|
687
|
+
${chalk.blue(`框架: ${framework}`)} ${chalk.gray(`• 命令: robot create my-app -t ${key}`)}`,
|
|
688
|
+
value: { key, ...template },
|
|
689
|
+
short: template.name
|
|
690
|
+
});
|
|
691
|
+
});
|
|
513
692
|
|
|
514
693
|
// 添加返回选项
|
|
515
|
-
|
|
694
|
+
categorizedChoices.push(
|
|
516
695
|
{
|
|
517
|
-
name:
|
|
696
|
+
name: "",
|
|
697
|
+
value: "spacer_end",
|
|
698
|
+
disabled: true
|
|
699
|
+
},
|
|
700
|
+
{
|
|
701
|
+
name: chalk.dim("━".repeat(70)),
|
|
518
702
|
value: "separator",
|
|
519
703
|
disabled: true,
|
|
520
704
|
},
|
|
521
|
-
{
|
|
705
|
+
{
|
|
706
|
+
name: chalk.dim("⬅️ 返回模板选择方式"),
|
|
707
|
+
value: "back_to_mode"
|
|
708
|
+
}
|
|
522
709
|
);
|
|
523
710
|
|
|
524
711
|
const { selectedTemplate } = await inquirer.prompt([
|
|
@@ -526,8 +713,9 @@ async function selectFromAll() {
|
|
|
526
713
|
type: "list",
|
|
527
714
|
name: "selectedTemplate",
|
|
528
715
|
message: "选择模板:",
|
|
529
|
-
choices,
|
|
530
|
-
pageSize:
|
|
716
|
+
choices: categorizedChoices,
|
|
717
|
+
pageSize: 20,
|
|
718
|
+
loop: false
|
|
531
719
|
},
|
|
532
720
|
]);
|
|
533
721
|
|