@agile-team/robot-cli 2.3.0 → 3.0.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 +30 -0
- package/dist/index.js +337 -521
- package/package.json +2 -3
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,36 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/).
|
|
7
7
|
|
|
8
|
+
## [3.0.0] - 2026-03-28
|
|
9
|
+
|
|
10
|
+
### ⚠️ BREAKING CHANGES
|
|
11
|
+
|
|
12
|
+
- 交互界面从 `inquirer` 全面迁移至 `@clack/prompts`,视觉体验完全不同
|
|
13
|
+
- 移除 `inquirer` 和 `@types/inquirer` 依赖
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- **@clack/prompts 现代化 UI**:使用 `p.select`、`p.text`、`p.confirm`、`p.note`、`p.intro`/`p.outro` 等,交互体验对齐 create-vue
|
|
18
|
+
- **Banner 框框展示**:双线框 `╔══╗` 样式包裹 ROBOT CLI 标题,信息分区更清晰
|
|
19
|
+
- **下载进度条**:基于 `content-length` 的流式进度条 `[████████░░░░] 40% 1.0MB/2.6MB`
|
|
20
|
+
- **Gitee 备用源**:模板配置新增 `giteeUrl` 字段,GitHub 不可达时自动切换 Gitee 下载
|
|
21
|
+
- robot-admin / monorepo / micro-app / module-federation → `gitee.com/ycyplus163/Robot_Admin`
|
|
22
|
+
- robot-uniapp → `gitee.com/ycyplus163/Robot_uniApp`
|
|
23
|
+
- **取消操作支持**:所有交互步骤支持 Ctrl+C 优雅退出 (`p.isCancel`)
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
|
|
27
|
+
- 主菜单、模板选择、项目配置、确认创建等全部替换为 @clack/prompts 组件
|
|
28
|
+
- 项目创建完成信息使用 `p.note` 卡片式展示
|
|
29
|
+
- 分类浏览流程简化:自动跳过只有单一选项的层级
|
|
30
|
+
- 项目配置不再需要最后的"确认配置"步骤(逐项确认更自然)
|
|
31
|
+
- 构建产物从 ~63KB 减小至 ~59KB
|
|
32
|
+
|
|
33
|
+
### Removed
|
|
34
|
+
|
|
35
|
+
- `inquirer` 依赖及其 `@types/inquirer` 类型定义
|
|
36
|
+
- `getVersionLabel()` 辅助函数(改为内联 `VERSION_LABELS` 查找)
|
|
37
|
+
|
|
8
38
|
## [2.3.0] - 2026-03-28
|
|
9
39
|
|
|
10
40
|
### Fixed (Root-Cause)
|
package/dist/index.js
CHANGED
|
@@ -3,14 +3,14 @@ import { readFileSync } from "fs";
|
|
|
3
3
|
import { fileURLToPath } from "url";
|
|
4
4
|
import { dirname, join } from "path";
|
|
5
5
|
import chalk5 from "chalk";
|
|
6
|
-
import
|
|
6
|
+
import * as p2 from "@clack/prompts";
|
|
7
7
|
import { Command } from "commander";
|
|
8
8
|
|
|
9
9
|
// src/create.ts
|
|
10
10
|
import fs3 from "fs-extra";
|
|
11
11
|
import path3 from "path";
|
|
12
12
|
import chalk3 from "chalk";
|
|
13
|
-
import
|
|
13
|
+
import * as p from "@clack/prompts";
|
|
14
14
|
import ora from "ora";
|
|
15
15
|
import { execSync as execSync2 } from "child_process";
|
|
16
16
|
|
|
@@ -36,6 +36,7 @@ var TEMPLATE_CATEGORIES = {
|
|
|
36
36
|
name: "Robot Admin \u5B8C\u6574\u7248",
|
|
37
37
|
description: "\u5305\u542B50+\u5B8C\u6574\u793A\u4F8B\u3001\u6743\u9650\u7BA1\u7406\u3001\u56FE\u8868\u7EC4\u4EF6\u3001\u6700\u4F73\u5B9E\u8DF5\u7B49\u7B49",
|
|
38
38
|
repoUrl: "https://github.com/ChenyCHENYU/Robot_Admin",
|
|
39
|
+
giteeUrl: "https://gitee.com/ycyplus163/Robot_Admin",
|
|
39
40
|
features: [
|
|
40
41
|
"Naive UI",
|
|
41
42
|
"Vue Router",
|
|
@@ -63,6 +64,7 @@ var TEMPLATE_CATEGORIES = {
|
|
|
63
64
|
name: "Robot Monorepo",
|
|
64
65
|
description: "bun workspace + Monorepo \u591A\u5305\u7BA1\u7406\u67B6\u6784",
|
|
65
66
|
repoUrl: "https://github.com/ChenyCHENYU/Robot_Admin",
|
|
67
|
+
giteeUrl: "https://gitee.com/ycyplus163/Robot_Admin",
|
|
66
68
|
branch: "monorepo",
|
|
67
69
|
features: ["bun workspace", "Monorepo", "\u591A\u5305\u7BA1\u7406", "\u5171\u4EAB\u7EC4\u4EF6"],
|
|
68
70
|
version: "full"
|
|
@@ -76,6 +78,7 @@ var TEMPLATE_CATEGORIES = {
|
|
|
76
78
|
name: "Robot MicroApp \u5FAE\u524D\u7AEF",
|
|
77
79
|
description: "\u57FA\u4E8E MicroApp \u7684\u5FAE\u524D\u7AEF\u67B6\u6784\u65B9\u6848",
|
|
78
80
|
repoUrl: "https://github.com/ChenyCHENYU/Robot_Admin",
|
|
81
|
+
giteeUrl: "https://gitee.com/ycyplus163/Robot_Admin",
|
|
79
82
|
branch: "micro-app",
|
|
80
83
|
features: ["MicroApp", "\u5FAE\u524D\u7AEF", "\u4E3B\u5B50\u5E94\u7528", "\u8DEF\u7531\u5171\u4EAB"],
|
|
81
84
|
version: "full"
|
|
@@ -84,6 +87,7 @@ var TEMPLATE_CATEGORIES = {
|
|
|
84
87
|
name: "Robot Module Federation \u6A21\u5757\u8054\u90A6",
|
|
85
88
|
description: "\u57FA\u4E8E Vite Module Federation \u7684\u6A21\u5757\u8054\u90A6\u65B9\u6848",
|
|
86
89
|
repoUrl: "https://github.com/ChenyCHENYU/Robot_Admin",
|
|
90
|
+
giteeUrl: "https://gitee.com/ycyplus163/Robot_Admin",
|
|
87
91
|
branch: "module-federation",
|
|
88
92
|
features: ["Module Federation", "\u6A21\u5757\u8054\u90A6", "Vite", "\u8FDC\u7A0B\u6A21\u5757"],
|
|
89
93
|
version: "full"
|
|
@@ -131,6 +135,7 @@ var TEMPLATE_CATEGORIES = {
|
|
|
131
135
|
name: "Robot uni-app \u5B8C\u6574\u7248",
|
|
132
136
|
description: "\u591A\u7AEF\u9002\u914D + \u63D2\u4EF6\u5E02\u573A + \u5B8C\u6574\u793A\u4F8B",
|
|
133
137
|
repoUrl: "https://github.com/ChenyCHENYU/Robot_Uniapp",
|
|
138
|
+
giteeUrl: "https://gitee.com/ycyplus163/Robot_uniApp",
|
|
134
139
|
features: ["\u591A\u7AEF\u53D1\u5E03", "uView UI", "\u63D2\u4EF6\u96C6\u6210"],
|
|
135
140
|
version: "full"
|
|
136
141
|
},
|
|
@@ -341,8 +346,8 @@ async function clearCache() {
|
|
|
341
346
|
var TIMEOUT_PRIMARY = 12e4;
|
|
342
347
|
var TIMEOUT_MIRROR = 6e4;
|
|
343
348
|
var MAX_RETRIES = 3;
|
|
344
|
-
function getGitHubMirrors(repoUrl) {
|
|
345
|
-
|
|
349
|
+
function getGitHubMirrors(repoUrl, giteeUrl) {
|
|
350
|
+
const mirrors = [
|
|
346
351
|
repoUrl,
|
|
347
352
|
// 1. 原始 GitHub
|
|
348
353
|
repoUrl.replace("github.com", "hub.gitmirror.com"),
|
|
@@ -350,6 +355,8 @@ function getGitHubMirrors(repoUrl) {
|
|
|
350
355
|
`https://ghproxy.net/${repoUrl}`
|
|
351
356
|
// 3. ghproxy.net
|
|
352
357
|
];
|
|
358
|
+
if (giteeUrl) mirrors.push(giteeUrl);
|
|
359
|
+
return mirrors;
|
|
353
360
|
}
|
|
354
361
|
async function fetchWithRetry(downloadUrl, timeout, retries) {
|
|
355
362
|
let lastError;
|
|
@@ -374,10 +381,10 @@ async function fetchWithRetry(downloadUrl, timeout, retries) {
|
|
|
374
381
|
}
|
|
375
382
|
throw lastError;
|
|
376
383
|
}
|
|
377
|
-
async function tryDownload(repoUrl, branch = "main", spinner) {
|
|
384
|
+
async function tryDownload(repoUrl, branch = "main", spinner, giteeUrl) {
|
|
378
385
|
const url = new URL(repoUrl);
|
|
379
386
|
const host = url.hostname;
|
|
380
|
-
const mirrors = host === "github.com" ? getGitHubMirrors(repoUrl) : [repoUrl];
|
|
387
|
+
const mirrors = host === "github.com" ? getGitHubMirrors(repoUrl, giteeUrl) : [repoUrl];
|
|
381
388
|
for (let i = 0; i < mirrors.length; i++) {
|
|
382
389
|
const current = mirrors[i];
|
|
383
390
|
const isOriginal = i === 0;
|
|
@@ -408,8 +415,9 @@ async function tryDownload(repoUrl, branch = "main", spinner) {
|
|
|
408
415
|
throw new Error("\u6240\u6709\u4E0B\u8F7D\u6E90\u5747\u4E0D\u53EF\u7528");
|
|
409
416
|
}
|
|
410
417
|
async function downloadTemplate(template, options = {}) {
|
|
411
|
-
const { spinner, noCache } = options;
|
|
418
|
+
const { spinner, noCache, giteeUrl: optGiteeUrl } = options;
|
|
412
419
|
const branch = template.branch || "main";
|
|
420
|
+
const giteeUrl = optGiteeUrl || template.giteeUrl;
|
|
413
421
|
if (!template?.repoUrl) {
|
|
414
422
|
throw new Error(`\u6A21\u677F\u914D\u7F6E\u65E0\u6548: ${JSON.stringify(template)}`);
|
|
415
423
|
}
|
|
@@ -418,14 +426,37 @@ async function downloadTemplate(template, options = {}) {
|
|
|
418
426
|
const { response, sourceName } = await tryDownload(
|
|
419
427
|
template.repoUrl,
|
|
420
428
|
branch,
|
|
421
|
-
spinner
|
|
429
|
+
spinner,
|
|
430
|
+
giteeUrl
|
|
422
431
|
);
|
|
423
432
|
if (spinner) spinner.text = "\u4FDD\u5B58\u4E0B\u8F7D\u6587\u4EF6...";
|
|
424
433
|
const timestamp = Date.now();
|
|
425
434
|
const tempZip = path.join(os.tmpdir(), `robot-template-${timestamp}.zip`);
|
|
426
435
|
const tempExtract = path.join(os.tmpdir(), `robot-extract-${timestamp}`);
|
|
427
|
-
const
|
|
428
|
-
|
|
436
|
+
const contentLength = response.headers.get("content-length");
|
|
437
|
+
const totalSize = contentLength ? parseInt(contentLength, 10) : 0;
|
|
438
|
+
if (totalSize > 0 && response.body && spinner) {
|
|
439
|
+
const reader = response.body.getReader();
|
|
440
|
+
const chunks = [];
|
|
441
|
+
let received = 0;
|
|
442
|
+
while (true) {
|
|
443
|
+
const { done, value } = await reader.read();
|
|
444
|
+
if (done) break;
|
|
445
|
+
chunks.push(value);
|
|
446
|
+
received += value.length;
|
|
447
|
+
const pct = Math.round(received / totalSize * 100);
|
|
448
|
+
const filled = Math.round(pct / 5);
|
|
449
|
+
const bar = "\u2588".repeat(filled) + "\u2591".repeat(20 - filled);
|
|
450
|
+
const sizeMB = (received / 1024 / 1024).toFixed(1);
|
|
451
|
+
const totalMB = (totalSize / 1024 / 1024).toFixed(1);
|
|
452
|
+
spinner.text = `\u4E0B\u8F7D\u4E2D [${bar}] ${pct}% ${sizeMB}MB/${totalMB}MB (${sourceName})`;
|
|
453
|
+
}
|
|
454
|
+
const buffer = Buffer.concat(chunks);
|
|
455
|
+
await fs.writeFile(tempZip, buffer);
|
|
456
|
+
} else {
|
|
457
|
+
const buffer = Buffer.from(await response.arrayBuffer());
|
|
458
|
+
await fs.writeFile(tempZip, buffer);
|
|
459
|
+
}
|
|
429
460
|
if (spinner) spinner.text = "\u89E3\u538B\u6A21\u677F\u6587\u4EF6...";
|
|
430
461
|
await extract(tempZip, { dir: tempExtract });
|
|
431
462
|
if (spinner) spinner.text = "\u67E5\u627E\u9879\u76EE\u7ED3\u6784...";
|
|
@@ -778,17 +809,9 @@ function formatBytes(bytes) {
|
|
|
778
809
|
}
|
|
779
810
|
|
|
780
811
|
// 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
812
|
var STRIP_VERSION_RE = /\s*(完整版|精简版|微服务版)\s*$/;
|
|
788
813
|
async function createProject(projectName, options = {}) {
|
|
789
|
-
|
|
790
|
-
console.log(chalk3.cyan(" Robot CLI - \u5F00\u59CB\u521B\u5EFA\u9879\u76EE"));
|
|
791
|
-
console.log();
|
|
814
|
+
p.intro(chalk3.bgCyan.black(" Robot CLI - \u5F00\u59CB\u521B\u5EFA\u9879\u76EE "));
|
|
792
815
|
let template;
|
|
793
816
|
if (options.from) {
|
|
794
817
|
template = {
|
|
@@ -842,38 +865,33 @@ async function handleProjectName(projectName, template) {
|
|
|
842
865
|
if (projectName) {
|
|
843
866
|
const v = validateProjectName(projectName);
|
|
844
867
|
if (!v.valid) {
|
|
845
|
-
|
|
846
|
-
v.errors.forEach((e) =>
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
{
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
validate: (input) => {
|
|
854
|
-
const r = validateProjectName(input);
|
|
855
|
-
return r.valid || r.errors[0];
|
|
856
|
-
}
|
|
868
|
+
p.log.error("\u9879\u76EE\u540D\u79F0\u4E0D\u5408\u6CD5:");
|
|
869
|
+
v.errors.forEach((e) => p.log.warn(` ${e}`));
|
|
870
|
+
const newName = await p.text({
|
|
871
|
+
message: "\u8BF7\u8F93\u5165\u65B0\u7684\u9879\u76EE\u540D\u79F0:",
|
|
872
|
+
validate: (input) => {
|
|
873
|
+
if (!input) return "\u9879\u76EE\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A";
|
|
874
|
+
const r = validateProjectName(input);
|
|
875
|
+
return r.valid ? void 0 : r.errors[0];
|
|
857
876
|
}
|
|
858
|
-
|
|
877
|
+
});
|
|
878
|
+
if (p.isCancel(newName)) process.exit(0);
|
|
859
879
|
return newName;
|
|
860
880
|
}
|
|
861
881
|
return projectName;
|
|
862
882
|
}
|
|
863
883
|
const defaultName = generateDefaultProjectName(template);
|
|
864
|
-
const
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
const r = validateProjectName(input);
|
|
873
|
-
return r.valid || r.errors[0];
|
|
874
|
-
}
|
|
884
|
+
const name = await p.text({
|
|
885
|
+
message: "\u8BF7\u8F93\u5165\u9879\u76EE\u540D\u79F0:",
|
|
886
|
+
defaultValue: defaultName,
|
|
887
|
+
placeholder: defaultName,
|
|
888
|
+
validate: (input) => {
|
|
889
|
+
if (!input?.trim()) return "\u9879\u76EE\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A";
|
|
890
|
+
const r = validateProjectName(input);
|
|
891
|
+
return r.valid ? void 0 : r.errors[0];
|
|
875
892
|
}
|
|
876
|
-
|
|
893
|
+
});
|
|
894
|
+
if (p.isCancel(name)) process.exit(0);
|
|
877
895
|
return name;
|
|
878
896
|
}
|
|
879
897
|
function generateDefaultProjectName(template) {
|
|
@@ -894,36 +912,16 @@ async function selectTemplate(templateOption) {
|
|
|
894
912
|
return await selectTemplateMethod();
|
|
895
913
|
}
|
|
896
914
|
async function selectTemplateMethod() {
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
{
|
|
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")}`,
|
|
909
|
-
value: "recommended"
|
|
910
|
-
},
|
|
911
|
-
{
|
|
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")}`,
|
|
913
|
-
value: "category"
|
|
914
|
-
},
|
|
915
|
-
{
|
|
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")}`,
|
|
917
|
-
value: "search"
|
|
918
|
-
},
|
|
919
|
-
{
|
|
920
|
-
name: `${chalk3.cyan(">")} ${chalk3.bold("\u5168\u90E8\u6A21\u677F")} ${chalk3.dim("\u2014 \u67E5\u770B\u6240\u6709\u53EF\u7528\u6A21\u677F")}`,
|
|
921
|
-
value: "all"
|
|
922
|
-
}
|
|
923
|
-
],
|
|
924
|
-
pageSize: 10
|
|
925
|
-
}
|
|
926
|
-
]);
|
|
915
|
+
const selectionMode = await p.select({
|
|
916
|
+
message: "\u6A21\u677F\u9009\u62E9\u65B9\u5F0F:",
|
|
917
|
+
options: [
|
|
918
|
+
{ value: "recommended", label: "\u63A8\u8350\u6A21\u677F", hint: "\u57FA\u4E8E\u56E2\u961F\u4F7F\u7528\u9891\u7387\u63A8\u8350\u7684\u70ED\u95E8\u6A21\u677F" },
|
|
919
|
+
{ value: "category", label: "\u5206\u7C7B\u6D4F\u89C8", hint: "\u524D\u7AEF\u3001\u540E\u7AEF\u3001\u79FB\u52A8\u7AEF\u3001\u684C\u9762\u7AEF\u5206\u7C7B" },
|
|
920
|
+
{ value: "search", label: "\u5173\u952E\u8BCD\u641C\u7D22", hint: "\u6309\u6280\u672F\u6808\u3001\u529F\u80FD\u7279\u6027\u67E5\u627E" },
|
|
921
|
+
{ value: "all", label: "\u5168\u90E8\u6A21\u677F", hint: "\u67E5\u770B\u6240\u6709\u53EF\u7528\u6A21\u677F" }
|
|
922
|
+
]
|
|
923
|
+
});
|
|
924
|
+
if (p.isCancel(selectionMode)) process.exit(0);
|
|
927
925
|
switch (selectionMode) {
|
|
928
926
|
case "recommended":
|
|
929
927
|
return await selectFromRecommended();
|
|
@@ -940,400 +938,258 @@ async function selectTemplateMethod() {
|
|
|
940
938
|
async function selectFromRecommended() {
|
|
941
939
|
const recommended = getRecommendedTemplates();
|
|
942
940
|
if (Object.keys(recommended).length === 0) {
|
|
943
|
-
|
|
941
|
+
p.log.warn("\u6682\u65E0\u63A8\u8350\u6A21\u677F");
|
|
944
942
|
return await selectTemplateMethod();
|
|
945
943
|
}
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
choices.push({
|
|
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`) : ""}`,
|
|
958
|
-
value: { key, ...template },
|
|
959
|
-
short: template.name
|
|
944
|
+
p.log.info(chalk3.bold("\u63A8\u8350\u6A21\u677F") + chalk3.dim(" \u2014 \u57FA\u4E8E\u56E2\u961F\u4F7F\u7528\u9891\u7387\u548C\u9879\u76EE\u6210\u719F\u5EA6\u63A8\u8350"));
|
|
945
|
+
const options = [];
|
|
946
|
+
for (const [key, template] of Object.entries(recommended)) {
|
|
947
|
+
const ver = VERSION_LABELS[template.version] || template.version;
|
|
948
|
+
const tags = template.features.slice(0, 3).join(", ");
|
|
949
|
+
options.push({
|
|
950
|
+
value: key,
|
|
951
|
+
label: `${template.name.replace(STRIP_VERSION_RE, "")} [${ver}]`,
|
|
952
|
+
hint: `${template.description} | ${tags}`
|
|
960
953
|
});
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
});
|
|
967
|
-
}
|
|
954
|
+
}
|
|
955
|
+
options.push({ value: "back", label: "<- \u8FD4\u56DE\u9009\u62E9\u5176\u4ED6\u65B9\u5F0F" });
|
|
956
|
+
const selected = await p.select({
|
|
957
|
+
message: "\u9009\u62E9\u63A8\u8350\u6A21\u677F:",
|
|
958
|
+
options
|
|
968
959
|
});
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
name: "selectedTemplate",
|
|
974
|
-
message: "\u9009\u62E9\u63A8\u8350\u6A21\u677F:",
|
|
975
|
-
choices,
|
|
976
|
-
pageSize: 15,
|
|
977
|
-
loop: false
|
|
978
|
-
}
|
|
979
|
-
]);
|
|
980
|
-
if (selectedTemplate === "back") return await selectTemplateMethod();
|
|
981
|
-
return selectedTemplate;
|
|
960
|
+
if (p.isCancel(selected)) process.exit(0);
|
|
961
|
+
if (selected === "back") return await selectTemplateMethod();
|
|
962
|
+
const t = recommended[selected];
|
|
963
|
+
return { key: selected, ...t };
|
|
982
964
|
}
|
|
983
965
|
async function selectByCategory() {
|
|
984
966
|
while (true) {
|
|
985
|
-
const
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
const
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
if (
|
|
995
|
-
return
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
const choices = Object.entries(category.stacks).map(([key, s]) => ({
|
|
1015
|
-
name: s.name,
|
|
1016
|
-
value: key
|
|
1017
|
-
}));
|
|
1018
|
-
choices.push(
|
|
1019
|
-
{
|
|
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"),
|
|
1021
|
-
value: "separator",
|
|
1022
|
-
disabled: true
|
|
1023
|
-
},
|
|
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" }
|
|
1026
|
-
);
|
|
1027
|
-
if (choices.length === 4) return choices[0].value;
|
|
1028
|
-
const { stackKey } = await inquirer.prompt([
|
|
1029
|
-
{ type: "list", name: "stackKey", message: "\u8BF7\u9009\u62E9\u6280\u672F\u6808:", choices }
|
|
1030
|
-
]);
|
|
1031
|
-
return stackKey;
|
|
1032
|
-
}
|
|
1033
|
-
async function selectPattern(catKey, stackKey) {
|
|
1034
|
-
if (["back_to_category", "back_to_method"].includes(stackKey))
|
|
1035
|
-
return stackKey;
|
|
1036
|
-
const stack = TEMPLATE_CATEGORIES[catKey].stacks[stackKey];
|
|
1037
|
-
const choices = Object.entries(stack.patterns).map(([key, p]) => ({
|
|
1038
|
-
name: p.name,
|
|
1039
|
-
value: key
|
|
1040
|
-
}));
|
|
1041
|
-
choices.push(
|
|
1042
|
-
{
|
|
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"),
|
|
1044
|
-
value: "separator",
|
|
1045
|
-
disabled: true
|
|
1046
|
-
},
|
|
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" }
|
|
1050
|
-
);
|
|
1051
|
-
if (choices.length === 5) return choices[0].value;
|
|
1052
|
-
const { patternKey } = await inquirer.prompt([
|
|
1053
|
-
{ type: "list", name: "patternKey", message: "\u8BF7\u9009\u62E9\u67B6\u6784\u6A21\u5F0F:", choices }
|
|
1054
|
-
]);
|
|
1055
|
-
return patternKey;
|
|
1056
|
-
}
|
|
1057
|
-
async function selectSpecificTemplate(catKey, stackKey, patternKey) {
|
|
1058
|
-
if (["back_to_stack", "back_to_category", "back_to_method"].includes(patternKey)) {
|
|
1059
|
-
return patternKey;
|
|
1060
|
-
}
|
|
1061
|
-
const templates = getTemplatesByCategory(catKey, stackKey, patternKey);
|
|
1062
|
-
const choices = Object.entries(templates).map(([key, t]) => ({
|
|
1063
|
-
name: `${t.name} - ${chalk3.dim(t.description)}`,
|
|
1064
|
-
value: { key, ...t },
|
|
1065
|
-
short: t.name
|
|
1066
|
-
}));
|
|
1067
|
-
choices.push(
|
|
1068
|
-
{
|
|
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"),
|
|
1070
|
-
value: "separator",
|
|
1071
|
-
disabled: true
|
|
1072
|
-
},
|
|
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" }
|
|
1077
|
-
);
|
|
1078
|
-
const { selectedTemplate } = await inquirer.prompt([
|
|
1079
|
-
{
|
|
1080
|
-
type: "list",
|
|
1081
|
-
name: "selectedTemplate",
|
|
1082
|
-
message: "\u8BF7\u9009\u62E9\u6A21\u677F\u7248\u672C:",
|
|
1083
|
-
choices
|
|
967
|
+
const catOptions = Object.entries(TEMPLATE_CATEGORIES).map(([key, c]) => ({
|
|
968
|
+
value: key,
|
|
969
|
+
label: c.name
|
|
970
|
+
}));
|
|
971
|
+
catOptions.push({ value: "back_to_method", label: "<- \u8FD4\u56DE\u6A21\u677F\u9009\u62E9\u65B9\u5F0F" });
|
|
972
|
+
const catKey = await p.select({
|
|
973
|
+
message: "\u8BF7\u9009\u62E9\u9879\u76EE\u7C7B\u578B:",
|
|
974
|
+
options: catOptions
|
|
975
|
+
});
|
|
976
|
+
if (p.isCancel(catKey)) process.exit(0);
|
|
977
|
+
if (catKey === "back_to_method") return await selectTemplateMethod();
|
|
978
|
+
const category = TEMPLATE_CATEGORIES[catKey];
|
|
979
|
+
const stackEntries = Object.entries(category.stacks);
|
|
980
|
+
let stackKey;
|
|
981
|
+
if (stackEntries.length === 1) {
|
|
982
|
+
stackKey = stackEntries[0][0];
|
|
983
|
+
} else {
|
|
984
|
+
const stackOptions = stackEntries.map(([key, s]) => ({
|
|
985
|
+
value: key,
|
|
986
|
+
label: s.name
|
|
987
|
+
}));
|
|
988
|
+
stackOptions.push({ value: "back", label: "<- \u8FD4\u56DE" });
|
|
989
|
+
const sk = await p.select({
|
|
990
|
+
message: "\u8BF7\u9009\u62E9\u6280\u672F\u6808:",
|
|
991
|
+
options: stackOptions
|
|
992
|
+
});
|
|
993
|
+
if (p.isCancel(sk)) process.exit(0);
|
|
994
|
+
if (sk === "back") continue;
|
|
995
|
+
stackKey = sk;
|
|
1084
996
|
}
|
|
1085
|
-
|
|
1086
|
-
|
|
997
|
+
const stack = category.stacks[stackKey];
|
|
998
|
+
const patternEntries = Object.entries(stack.patterns);
|
|
999
|
+
let patternKey;
|
|
1000
|
+
if (patternEntries.length === 1) {
|
|
1001
|
+
patternKey = patternEntries[0][0];
|
|
1002
|
+
} else {
|
|
1003
|
+
const patternOptions = patternEntries.map(([key, pt]) => ({
|
|
1004
|
+
value: key,
|
|
1005
|
+
label: pt.name
|
|
1006
|
+
}));
|
|
1007
|
+
patternOptions.push({ value: "back", label: "<- \u8FD4\u56DE" });
|
|
1008
|
+
const pk = await p.select({
|
|
1009
|
+
message: "\u8BF7\u9009\u62E9\u67B6\u6784\u6A21\u5F0F:",
|
|
1010
|
+
options: patternOptions
|
|
1011
|
+
});
|
|
1012
|
+
if (p.isCancel(pk)) process.exit(0);
|
|
1013
|
+
if (pk === "back") continue;
|
|
1014
|
+
patternKey = pk;
|
|
1015
|
+
}
|
|
1016
|
+
const templates = getTemplatesByCategory(catKey, stackKey, patternKey);
|
|
1017
|
+
const tplOptions = Object.entries(templates).map(([key, t2]) => {
|
|
1018
|
+
const ver = VERSION_LABELS[t2.version] || t2.version;
|
|
1019
|
+
return {
|
|
1020
|
+
value: key,
|
|
1021
|
+
label: `${t2.name} [${ver}]`,
|
|
1022
|
+
hint: t2.description
|
|
1023
|
+
};
|
|
1024
|
+
});
|
|
1025
|
+
tplOptions.push({ value: "back", label: "<- \u8FD4\u56DE", hint: "" });
|
|
1026
|
+
const tplKey = await p.select({
|
|
1027
|
+
message: "\u8BF7\u9009\u62E9\u6A21\u677F\u7248\u672C:",
|
|
1028
|
+
options: tplOptions
|
|
1029
|
+
});
|
|
1030
|
+
if (p.isCancel(tplKey)) process.exit(0);
|
|
1031
|
+
if (tplKey === "back") continue;
|
|
1032
|
+
const t = templates[tplKey];
|
|
1033
|
+
return { key: tplKey, ...t };
|
|
1034
|
+
}
|
|
1087
1035
|
}
|
|
1088
1036
|
async function selectBySearch() {
|
|
1089
1037
|
while (true) {
|
|
1090
|
-
const
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
validate: (input) => input.trim() ? true : "\u5173\u952E\u8BCD\u4E0D\u80FD\u4E3A\u7A7A"
|
|
1096
|
-
}
|
|
1097
|
-
]);
|
|
1038
|
+
const keyword = await p.text({
|
|
1039
|
+
message: "\u8BF7\u8F93\u5165\u641C\u7D22\u5173\u952E\u8BCD (\u540D\u79F0\u3001\u63CF\u8FF0\u3001\u6280\u672F\u6808):",
|
|
1040
|
+
validate: (input) => input?.trim() ? void 0 : "\u5173\u952E\u8BCD\u4E0D\u80FD\u4E3A\u7A7A"
|
|
1041
|
+
});
|
|
1042
|
+
if (p.isCancel(keyword)) return await selectTemplateMethod();
|
|
1098
1043
|
const results = searchTemplates(keyword);
|
|
1099
1044
|
if (Object.keys(results).length === 0) {
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
{ name: "\u91CD\u65B0\u641C\u7D22", value: "retry" },
|
|
1111
|
-
{ name: chalk3.dim("<- \u8FD4\u56DE\u6A21\u677F\u9009\u62E9\u65B9\u5F0F"), value: "back" }
|
|
1112
|
-
]
|
|
1113
|
-
}
|
|
1114
|
-
]);
|
|
1115
|
-
if (action === "retry") continue;
|
|
1116
|
-
return await selectTemplateMethod();
|
|
1045
|
+
p.log.warn(`\u6CA1\u6709\u627E\u5230\u5339\u914D\u7684\u6A21\u677F (\u5173\u952E\u8BCD: "${keyword}")`);
|
|
1046
|
+
const action = await p.select({
|
|
1047
|
+
message: "\u8BF7\u9009\u62E9\u4E0B\u4E00\u6B65\u64CD\u4F5C:",
|
|
1048
|
+
options: [
|
|
1049
|
+
{ value: "retry", label: "\u91CD\u65B0\u641C\u7D22" },
|
|
1050
|
+
{ value: "back", label: "<- \u8FD4\u56DE\u6A21\u677F\u9009\u62E9\u65B9\u5F0F" }
|
|
1051
|
+
]
|
|
1052
|
+
});
|
|
1053
|
+
if (p.isCancel(action) || action === "back") return await selectTemplateMethod();
|
|
1054
|
+
continue;
|
|
1117
1055
|
}
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1056
|
+
p.log.info(`\u5173\u952E\u8BCD: "${keyword}" -- \u627E\u5230 ${Object.keys(results).length} \u4E2A\u5339\u914D\u6A21\u677F`);
|
|
1057
|
+
const options = [];
|
|
1058
|
+
for (const [key, t2] of Object.entries(results)) {
|
|
1059
|
+
const ver = VERSION_LABELS[t2.version] || t2.version;
|
|
1060
|
+
const info = t2.features.slice(0, 3).join(", ");
|
|
1061
|
+
options.push({
|
|
1062
|
+
value: key,
|
|
1063
|
+
label: `${t2.name.replace(STRIP_VERSION_RE, "")} [${ver}]`,
|
|
1064
|
+
hint: `${t2.description} | ${info}`
|
|
1065
|
+
});
|
|
1066
|
+
}
|
|
1067
|
+
options.push(
|
|
1068
|
+
{ value: "search_again", label: "\u91CD\u65B0\u641C\u7D22" },
|
|
1069
|
+
{ value: "back_to_mode", label: "<- \u8FD4\u56DE\u6A21\u677F\u9009\u62E9\u65B9\u5F0F" }
|
|
1124
1070
|
);
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
new RegExp(`(${keyword})`, "gi"),
|
|
1129
|
-
chalk3.bgYellow.black("$1")
|
|
1130
|
-
);
|
|
1131
|
-
const ver = getVersionLabel(t.version);
|
|
1132
|
-
const info = t.features.slice(0, 2).join(" \u2022 ");
|
|
1133
|
-
return {
|
|
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))}`,
|
|
1138
|
-
value: { key, ...t },
|
|
1139
|
-
short: t.name
|
|
1140
|
-
};
|
|
1071
|
+
const selected = await p.select({
|
|
1072
|
+
message: "\u9009\u62E9\u6A21\u677F:",
|
|
1073
|
+
options
|
|
1141
1074
|
});
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
const { selectedTemplate } = await inquirer.prompt([
|
|
1148
|
-
{
|
|
1149
|
-
type: "list",
|
|
1150
|
-
name: "selectedTemplate",
|
|
1151
|
-
message: "\u9009\u62E9\u6A21\u677F:",
|
|
1152
|
-
choices,
|
|
1153
|
-
pageSize: 15,
|
|
1154
|
-
loop: false
|
|
1155
|
-
}
|
|
1156
|
-
]);
|
|
1157
|
-
if (selectedTemplate === "search_again") continue;
|
|
1158
|
-
if (selectedTemplate === "back_to_mode")
|
|
1159
|
-
return await selectTemplateMethod();
|
|
1160
|
-
return selectedTemplate;
|
|
1075
|
+
if (p.isCancel(selected)) process.exit(0);
|
|
1076
|
+
if (selected === "search_again") continue;
|
|
1077
|
+
if (selected === "back_to_mode") return await selectTemplateMethod();
|
|
1078
|
+
const t = results[selected];
|
|
1079
|
+
return { key: selected, ...t };
|
|
1161
1080
|
}
|
|
1162
1081
|
}
|
|
1163
1082
|
async function selectFromAll() {
|
|
1164
1083
|
const allTemplates = getAllTemplates();
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
console.log(chalk3.dim(` \u5171 ${Object.keys(allTemplates).length} \u4E2A\u6A21\u677F\u53EF\u9009`));
|
|
1168
|
-
console.log();
|
|
1169
|
-
const categorizedChoices = [];
|
|
1084
|
+
p.log.info(chalk3.bold("\u6240\u6709\u53EF\u7528\u6A21\u677F") + chalk3.dim(` -- \u5171 ${Object.keys(allTemplates).length} \u4E2A\u6A21\u677F\u53EF\u9009`));
|
|
1085
|
+
const options = [];
|
|
1170
1086
|
for (const [_catKey, category] of Object.entries(TEMPLATE_CATEGORIES)) {
|
|
1171
|
-
categorizedChoices.push({
|
|
1172
|
-
name: chalk3.yellow.bold(category.name),
|
|
1173
|
-
value: `${_catKey}_header`,
|
|
1174
|
-
disabled: true
|
|
1175
|
-
});
|
|
1176
1087
|
for (const [_sKey, stack] of Object.entries(category.stacks)) {
|
|
1177
1088
|
for (const _pattern of Object.values(stack.patterns)) {
|
|
1178
|
-
for (const [key,
|
|
1179
|
-
const ver =
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
short: t.name
|
|
1185
|
-
});
|
|
1186
|
-
categorizedChoices.push({
|
|
1187
|
-
name: chalk3.dim(" " + "\u2500".repeat(66)),
|
|
1188
|
-
value: `sep_${key}`,
|
|
1189
|
-
disabled: true
|
|
1089
|
+
for (const [key, t2] of Object.entries(_pattern.templates)) {
|
|
1090
|
+
const ver = VERSION_LABELS[t2.version] || t2.version;
|
|
1091
|
+
options.push({
|
|
1092
|
+
value: key,
|
|
1093
|
+
label: `${t2.name.replace(STRIP_VERSION_RE, "")} [${ver}]`,
|
|
1094
|
+
hint: `${category.name} > ${stack.name} | ${t2.description}`
|
|
1190
1095
|
});
|
|
1191
1096
|
}
|
|
1192
1097
|
}
|
|
1193
1098
|
}
|
|
1194
1099
|
}
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
choices: categorizedChoices,
|
|
1205
|
-
pageSize: 25,
|
|
1206
|
-
loop: false
|
|
1207
|
-
}
|
|
1208
|
-
]);
|
|
1209
|
-
if (selectedTemplate === "back_to_mode") return await selectTemplateMethod();
|
|
1210
|
-
return selectedTemplate;
|
|
1100
|
+
options.push({ value: "back_to_mode", label: "<- \u8FD4\u56DE\u6A21\u677F\u9009\u62E9\u65B9\u5F0F" });
|
|
1101
|
+
const selected = await p.select({
|
|
1102
|
+
message: "\u9009\u62E9\u6A21\u677F:",
|
|
1103
|
+
options
|
|
1104
|
+
});
|
|
1105
|
+
if (p.isCancel(selected)) process.exit(0);
|
|
1106
|
+
if (selected === "back_to_mode") return await selectTemplateMethod();
|
|
1107
|
+
const t = allTemplates[selected];
|
|
1108
|
+
return { key: selected, ...t };
|
|
1211
1109
|
}
|
|
1212
1110
|
async function configureProject(options) {
|
|
1213
|
-
|
|
1214
|
-
console.log(chalk3.bold(" \u9879\u76EE\u914D\u7F6E"));
|
|
1215
|
-
console.log();
|
|
1111
|
+
p.log.step(chalk3.bold("\u9879\u76EE\u914D\u7F6E"));
|
|
1216
1112
|
const available = detectPackageManager();
|
|
1217
1113
|
const hasBun = available.includes("bun");
|
|
1218
1114
|
const hasPnpm = available.includes("pnpm");
|
|
1219
|
-
const
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
if (
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
value: "
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
}
|
|
1248
|
-
const config = await inquirer.prompt([
|
|
1249
|
-
{
|
|
1250
|
-
type: "confirm",
|
|
1251
|
-
name: "initGit",
|
|
1252
|
-
message: "\u662F\u5426\u521D\u59CB\u5316 Git \u4ED3\u5E93?",
|
|
1253
|
-
default: true
|
|
1254
|
-
},
|
|
1255
|
-
{
|
|
1256
|
-
type: "confirm",
|
|
1257
|
-
name: "installDeps",
|
|
1258
|
-
message: "\u662F\u5426\u7ACB\u5373\u5B89\u88C5\u4F9D\u8D56?",
|
|
1259
|
-
default: !options.skipInstall
|
|
1260
|
-
},
|
|
1261
|
-
{
|
|
1262
|
-
type: "list",
|
|
1263
|
-
name: "packageManager",
|
|
1264
|
-
message: "\u9009\u62E9\u5305\u7BA1\u7406\u5668:",
|
|
1265
|
-
choices: managerChoices,
|
|
1266
|
-
default: hasBun ? "bun" : hasPnpm ? "pnpm" : "npm",
|
|
1267
|
-
when: (a) => a.installDeps
|
|
1268
|
-
},
|
|
1269
|
-
{
|
|
1270
|
-
type: "input",
|
|
1271
|
-
name: "description",
|
|
1272
|
-
message: "\u9879\u76EE\u63CF\u8FF0 (\u53EF\u9009):",
|
|
1273
|
-
default: ""
|
|
1274
|
-
},
|
|
1275
|
-
{
|
|
1276
|
-
type: "input",
|
|
1277
|
-
name: "author",
|
|
1278
|
-
message: "\u4F5C\u8005 (\u53EF\u9009):",
|
|
1279
|
-
default: getGitUser()
|
|
1280
|
-
},
|
|
1281
|
-
{
|
|
1282
|
-
type: "confirm",
|
|
1283
|
-
name: "confirmConfig",
|
|
1284
|
-
message: "\u786E\u8BA4\u4EE5\u4E0A\u914D\u7F6E?",
|
|
1285
|
-
default: true
|
|
1115
|
+
const initGit = await p.confirm({
|
|
1116
|
+
message: "\u662F\u5426\u521D\u59CB\u5316 Git \u4ED3\u5E93?",
|
|
1117
|
+
initialValue: true
|
|
1118
|
+
});
|
|
1119
|
+
if (p.isCancel(initGit)) process.exit(0);
|
|
1120
|
+
const installDeps = await p.confirm({
|
|
1121
|
+
message: "\u662F\u5426\u7ACB\u5373\u5B89\u88C5\u4F9D\u8D56?",
|
|
1122
|
+
initialValue: !options.skipInstall
|
|
1123
|
+
});
|
|
1124
|
+
if (p.isCancel(installDeps)) process.exit(0);
|
|
1125
|
+
let packageManager = hasBun ? "bun" : hasPnpm ? "pnpm" : "npm";
|
|
1126
|
+
if (installDeps) {
|
|
1127
|
+
const managerOptions = [];
|
|
1128
|
+
if (available.includes("bun"))
|
|
1129
|
+
managerOptions.push({ value: "bun", label: "bun", hint: "\u63A8\u8350 - \u6781\u901F\u5B89\u88C5" });
|
|
1130
|
+
if (available.includes("pnpm"))
|
|
1131
|
+
managerOptions.push({ value: "pnpm", label: "pnpm", hint: "\u63A8\u8350 - \u8282\u7701\u78C1\u76D8\u7A7A\u95F4" });
|
|
1132
|
+
if (available.includes("yarn"))
|
|
1133
|
+
managerOptions.push({ value: "yarn", label: "yarn", hint: "\u517C\u5BB9\u6027\u597D" });
|
|
1134
|
+
if (available.includes("npm"))
|
|
1135
|
+
managerOptions.push({ value: "npm", label: "npm", hint: "Node.js \u5185\u7F6E" });
|
|
1136
|
+
if (managerOptions.length === 0) {
|
|
1137
|
+
managerOptions.push(
|
|
1138
|
+
{ value: "npm", label: "npm" },
|
|
1139
|
+
{ value: "bun", label: "bun" },
|
|
1140
|
+
{ value: "pnpm", label: "pnpm" },
|
|
1141
|
+
{ value: "yarn", label: "yarn" }
|
|
1142
|
+
);
|
|
1286
1143
|
}
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
choices: [
|
|
1295
|
-
{ name: "\u91CD\u65B0\u914D\u7F6E", value: "reconfigure" },
|
|
1296
|
-
{ name: "\u53D6\u6D88\u521B\u5EFA", value: "cancel" }
|
|
1297
|
-
]
|
|
1298
|
-
}
|
|
1299
|
-
]);
|
|
1300
|
-
if (action === "reconfigure") return await configureProject(options);
|
|
1301
|
-
console.log(chalk3.yellow("\u53D6\u6D88\u521B\u5EFA\u9879\u76EE"));
|
|
1302
|
-
process.exit(0);
|
|
1144
|
+
const pm = await p.select({
|
|
1145
|
+
message: "\u9009\u62E9\u5305\u7BA1\u7406\u5668:",
|
|
1146
|
+
options: managerOptions,
|
|
1147
|
+
initialValue: hasBun ? "bun" : hasPnpm ? "pnpm" : "npm"
|
|
1148
|
+
});
|
|
1149
|
+
if (p.isCancel(pm)) process.exit(0);
|
|
1150
|
+
packageManager = pm;
|
|
1303
1151
|
}
|
|
1304
|
-
|
|
1152
|
+
const description = await p.text({
|
|
1153
|
+
message: "\u9879\u76EE\u63CF\u8FF0 (\u53EF\u9009):",
|
|
1154
|
+
defaultValue: "",
|
|
1155
|
+
placeholder: "\u8F93\u5165\u9879\u76EE\u63CF\u8FF0\u6216\u76F4\u63A5\u56DE\u8F66\u8DF3\u8FC7"
|
|
1156
|
+
});
|
|
1157
|
+
if (p.isCancel(description)) process.exit(0);
|
|
1158
|
+
const author = await p.text({
|
|
1159
|
+
message: "\u4F5C\u8005 (\u53EF\u9009):",
|
|
1160
|
+
defaultValue: getGitUser(),
|
|
1161
|
+
placeholder: getGitUser() || "\u8F93\u5165\u4F5C\u8005\u540D"
|
|
1162
|
+
});
|
|
1163
|
+
if (p.isCancel(author)) process.exit(0);
|
|
1164
|
+
return {
|
|
1165
|
+
initGit,
|
|
1166
|
+
installDeps,
|
|
1167
|
+
packageManager,
|
|
1168
|
+
description,
|
|
1169
|
+
author
|
|
1170
|
+
};
|
|
1305
1171
|
}
|
|
1306
1172
|
async function confirmCreation(projectName, template, config) {
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
` \u521D\u59CB\u5316Git: ${config.initGit ? chalk3.green("\u662F") : chalk3.dim("\u5426")}`
|
|
1321
|
-
);
|
|
1322
|
-
console.log(
|
|
1323
|
-
` \u5B89\u88C5\u4F9D\u8D56: ${config.installDeps ? chalk3.green("\u662F") + chalk3.dim(` (${config.packageManager})`) : chalk3.dim("\u5426")}`
|
|
1173
|
+
p.note(
|
|
1174
|
+
[
|
|
1175
|
+
`${chalk3.dim("\u9879\u76EE\u540D\u79F0:")} ${chalk3.cyan(projectName)}`,
|
|
1176
|
+
`${chalk3.dim("\u9009\u62E9\u6A21\u677F:")} ${chalk3.cyan(template.name)}`,
|
|
1177
|
+
`${chalk3.dim("\u6A21\u677F\u63CF\u8FF0:")} ${template.description}`,
|
|
1178
|
+
`${chalk3.dim("\u5305\u542B\u529F\u80FD:")} ${template.features.join(", ") || "\u81EA\u5B9A\u4E49\u6A21\u677F"}`,
|
|
1179
|
+
config.description ? `${chalk3.dim("\u9879\u76EE\u63CF\u8FF0:")} ${config.description}` : "",
|
|
1180
|
+
config.author ? `${chalk3.dim("\u4F5C \u8005:")} ${config.author}` : "",
|
|
1181
|
+
`${chalk3.dim("\u521D\u59CB\u5316Git:")} ${config.initGit ? chalk3.green("\u662F") : "\u5426"}`,
|
|
1182
|
+
`${chalk3.dim("\u5B89\u88C5\u4F9D\u8D56:")} ${config.installDeps ? chalk3.green("\u662F") + ` (${config.packageManager})` : "\u5426"}`,
|
|
1183
|
+
`${chalk3.dim("\u6E90\u7801\u4ED3\u5E93:")} ${template.repoUrl}`
|
|
1184
|
+
].filter(Boolean).join("\n"),
|
|
1185
|
+
"\u9879\u76EE\u521B\u5EFA\u4FE1\u606F\u786E\u8BA4"
|
|
1324
1186
|
);
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
message: "\u786E\u8BA4\u521B\u5EFA\u9879\u76EE?",
|
|
1332
|
-
default: true
|
|
1333
|
-
}
|
|
1334
|
-
]);
|
|
1335
|
-
if (!confirmed) {
|
|
1336
|
-
console.log(chalk3.yellow("\u53D6\u6D88\u521B\u5EFA"));
|
|
1187
|
+
const confirmed = await p.confirm({
|
|
1188
|
+
message: "\u786E\u8BA4\u521B\u5EFA\u9879\u76EE?",
|
|
1189
|
+
initialValue: true
|
|
1190
|
+
});
|
|
1191
|
+
if (p.isCancel(confirmed) || !confirmed) {
|
|
1192
|
+
p.outro(chalk3.yellow("\u53D6\u6D88\u521B\u5EFA"));
|
|
1337
1193
|
process.exit(0);
|
|
1338
1194
|
}
|
|
1339
1195
|
}
|
|
@@ -1352,17 +1208,13 @@ async function executeCreation(projectName, template, config, options) {
|
|
|
1352
1208
|
const projectPath = path3.resolve(projectName);
|
|
1353
1209
|
if (fs3.existsSync(projectPath)) {
|
|
1354
1210
|
spinner.stop();
|
|
1355
|
-
|
|
1356
|
-
const
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
}
|
|
1363
|
-
]);
|
|
1364
|
-
if (!overwrite) {
|
|
1365
|
-
console.log(chalk3.yellow("\u53D6\u6D88\u521B\u5EFA"));
|
|
1211
|
+
p.log.warn("\u9879\u76EE\u76EE\u5F55\u5DF2\u5B58\u5728");
|
|
1212
|
+
const overwrite = await p.confirm({
|
|
1213
|
+
message: "\u76EE\u5F55\u5DF2\u5B58\u5728\uFF0C\u662F\u5426\u8986\u76D6?",
|
|
1214
|
+
initialValue: false
|
|
1215
|
+
});
|
|
1216
|
+
if (p.isCancel(overwrite) || !overwrite) {
|
|
1217
|
+
p.outro(chalk3.yellow("\u53D6\u6D88\u521B\u5EFA"));
|
|
1366
1218
|
process.exit(0);
|
|
1367
1219
|
}
|
|
1368
1220
|
spinner.start("\u6E05\u7406\u73B0\u6709\u76EE\u5F55...");
|
|
@@ -1401,41 +1253,31 @@ async function executeCreation(projectName, template, config, options) {
|
|
|
1401
1253
|
});
|
|
1402
1254
|
}
|
|
1403
1255
|
spinner.succeed(chalk3.green("\u9879\u76EE\u521B\u5EFA\u6210\u529F!"));
|
|
1404
|
-
console.log();
|
|
1405
|
-
console.log(chalk3.green("\u9879\u76EE\u521B\u5EFA\u5B8C\u6210!"));
|
|
1406
|
-
console.log();
|
|
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)}`);
|
|
1410
|
-
console.log(
|
|
1411
|
-
` Git\u4ED3\u5E93: ${config.initGit ? chalk3.green("\u5DF2\u521D\u59CB\u5316") : chalk3.dim("\u672A\u521D\u59CB\u5316")}`
|
|
1412
|
-
);
|
|
1413
|
-
console.log(
|
|
1414
|
-
` \u4F9D\u8D56\u5B89\u88C5: ${config.installDeps ? chalk3.green("\u5DF2\u5B8C\u6210") : chalk3.dim("\u9700\u624B\u52A8\u5B89\u88C5")}`
|
|
1415
|
-
);
|
|
1416
|
-
console.log();
|
|
1417
|
-
console.log(chalk3.blue("\u5FEB\u901F\u5F00\u59CB:"));
|
|
1418
|
-
console.log(chalk3.cyan(` cd ${projectName}`));
|
|
1419
1256
|
const pm = config.packageManager || "bun";
|
|
1420
|
-
if (!config.installDeps) {
|
|
1421
|
-
console.log(chalk3.cyan(` ${pm} install`));
|
|
1422
|
-
}
|
|
1423
1257
|
const cmd = getStartCommand(template, pm);
|
|
1424
|
-
|
|
1425
|
-
if (pm
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
chalk3.dim("
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1258
|
+
const steps = [`cd ${projectName}`];
|
|
1259
|
+
if (!config.installDeps) steps.push(`${pm} install`);
|
|
1260
|
+
if (cmd) steps.push(cmd);
|
|
1261
|
+
p.note(
|
|
1262
|
+
[
|
|
1263
|
+
`${chalk3.dim("\u4F4D\u7F6E:")} ${chalk3.cyan(projectPath)}`,
|
|
1264
|
+
`${chalk3.dim("\u6A21\u677F:")} ${chalk3.cyan(template.name)}`,
|
|
1265
|
+
`${chalk3.dim("Git:")} ${config.initGit ? chalk3.green("\u5DF2\u521D\u59CB\u5316") : "\u672A\u521D\u59CB\u5316"}`,
|
|
1266
|
+
`${chalk3.dim("\u4F9D\u8D56:")} ${config.installDeps ? chalk3.green("\u5DF2\u5B8C\u6210") : "\u9700\u624B\u52A8\u5B89\u88C5"}`,
|
|
1267
|
+
"",
|
|
1268
|
+
chalk3.bold("\u5FEB\u901F\u5F00\u59CB:"),
|
|
1269
|
+
...steps.map((s) => ` ${chalk3.cyan(s)}`)
|
|
1270
|
+
].join("\n"),
|
|
1271
|
+
"\u9879\u76EE\u521B\u5EFA\u5B8C\u6210"
|
|
1272
|
+
);
|
|
1273
|
+
const statsSpinner = ora("\u7EDF\u8BA1\u9879\u76EE\u4FE1\u606F...").start();
|
|
1433
1274
|
const stats = await generateProjectStats(projectPath);
|
|
1434
|
-
|
|
1275
|
+
statsSpinner.stop();
|
|
1435
1276
|
if (stats) {
|
|
1436
1277
|
printProjectStats(stats);
|
|
1437
1278
|
console.log();
|
|
1438
1279
|
}
|
|
1280
|
+
p.outro(chalk3.green("Happy coding!"));
|
|
1439
1281
|
} catch (error) {
|
|
1440
1282
|
if (tempPath) await fs3.remove(tempPath).catch(() => {
|
|
1441
1283
|
});
|
|
@@ -1597,55 +1439,32 @@ function getPackageVersion() {
|
|
|
1597
1439
|
}
|
|
1598
1440
|
var VERSION = getPackageVersion();
|
|
1599
1441
|
function showWelcome() {
|
|
1600
|
-
const supportsColor = process.stdout.isTTY && process.stdout.getColorDepth() > 1;
|
|
1601
1442
|
console.log();
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
}
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
console.log(
|
|
1608
|
-
chalk5.dim(` v${VERSION} | ${chalk5.reset.dim("\u5DE5\u7A0B\u5316\u9879\u76EE\u811A\u624B\u67B6")}`)
|
|
1609
|
-
);
|
|
1610
|
-
console.log(chalk5.dim(" \u524D\u7AEF / \u540E\u7AEF / \u79FB\u52A8\u7AEF / \u684C\u9762\u7AEF"));
|
|
1443
|
+
console.log(chalk5.cyan(" \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\u2557"));
|
|
1444
|
+
console.log(chalk5.cyan(" \u2551") + chalk5.bold.cyan(" R O B O T C L I ") + chalk5.cyan("\u2551"));
|
|
1445
|
+
console.log(chalk5.cyan(" \u2551") + chalk5.dim(` v${VERSION} | \u5DE5\u7A0B\u5316\u9879\u76EE\u811A\u624B\u67B6`.padEnd(38)) + chalk5.cyan("\u2551"));
|
|
1446
|
+
console.log(chalk5.cyan(" \u2551") + chalk5.dim(" \u524D\u7AEF / \u540E\u7AEF / \u79FB\u52A8\u7AEF / \u684C\u9762\u7AEF".padEnd(38)) + chalk5.cyan("\u2551"));
|
|
1447
|
+
console.log(chalk5.cyan(" \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\u255D"));
|
|
1611
1448
|
console.log();
|
|
1612
1449
|
}
|
|
1613
1450
|
async function showMainMenu() {
|
|
1614
1451
|
const allTemplates = getAllTemplates();
|
|
1615
1452
|
const count = Object.keys(allTemplates).length;
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
},
|
|
1632
|
-
{
|
|
1633
|
-
name: `${chalk5.cyan(">")} ${chalk5.bold("\u67E5\u770B\u6A21\u677F\u5217\u8868")} ${chalk5.dim("\u2014 \u6D4F\u89C8\u6240\u6709\u53EF\u7528\u6A21\u677F")}`,
|
|
1634
|
-
value: "list"
|
|
1635
|
-
},
|
|
1636
|
-
{
|
|
1637
|
-
name: `${chalk5.cyan(">")} ${chalk5.bold("\u641C\u7D22\u6A21\u677F")} ${chalk5.dim("\u2014 \u6309\u5173\u952E\u8BCD\u641C\u7D22\u6A21\u677F")}`,
|
|
1638
|
-
value: "search"
|
|
1639
|
-
},
|
|
1640
|
-
{
|
|
1641
|
-
name: `${chalk5.cyan(">")} ${chalk5.bold("\u73AF\u5883\u8BCA\u65AD")} ${chalk5.dim("\u2014 \u68C0\u67E5\u5F00\u53D1\u73AF\u5883")}`,
|
|
1642
|
-
value: "doctor"
|
|
1643
|
-
},
|
|
1644
|
-
{ name: chalk5.dim("\u2500".repeat(50)), value: "sep", disabled: true },
|
|
1645
|
-
{ name: `${chalk5.dim(" \u9000\u51FA")}`, value: "exit" }
|
|
1646
|
-
]
|
|
1647
|
-
}
|
|
1648
|
-
]);
|
|
1453
|
+
p2.intro(chalk5.bgCyan.black(` ${count} \u4E2A\u6A21\u677F\u53EF\u7528 \xB7 Node ${process.version} \xB7 v${VERSION} `));
|
|
1454
|
+
const action = await p2.select({
|
|
1455
|
+
message: "\u8BF7\u9009\u62E9\u64CD\u4F5C:",
|
|
1456
|
+
options: [
|
|
1457
|
+
{ value: "create", label: "\u521B\u5EFA\u65B0\u9879\u76EE", hint: "\u9009\u62E9\u6A21\u677F\u521B\u5EFA\u9879\u76EE" },
|
|
1458
|
+
{ value: "list", label: "\u67E5\u770B\u6A21\u677F\u5217\u8868", hint: "\u6D4F\u89C8\u6240\u6709\u53EF\u7528\u6A21\u677F" },
|
|
1459
|
+
{ value: "search", label: "\u641C\u7D22\u6A21\u677F", hint: "\u6309\u5173\u952E\u8BCD\u641C\u7D22\u6A21\u677F" },
|
|
1460
|
+
{ value: "doctor", label: "\u73AF\u5883\u8BCA\u65AD", hint: "\u68C0\u67E5\u5F00\u53D1\u73AF\u5883" },
|
|
1461
|
+
{ value: "exit", label: "\u9000\u51FA" }
|
|
1462
|
+
]
|
|
1463
|
+
});
|
|
1464
|
+
if (p2.isCancel(action)) {
|
|
1465
|
+
p2.outro(chalk5.dim("\u518D\u89C1!"));
|
|
1466
|
+
process.exit(0);
|
|
1467
|
+
}
|
|
1649
1468
|
switch (action) {
|
|
1650
1469
|
case "create":
|
|
1651
1470
|
await createProject(void 0, {});
|
|
@@ -1660,7 +1479,7 @@ async function showMainMenu() {
|
|
|
1660
1479
|
await runDoctor();
|
|
1661
1480
|
break;
|
|
1662
1481
|
case "exit":
|
|
1663
|
-
|
|
1482
|
+
p2.outro(chalk5.dim("\u518D\u89C1!"));
|
|
1664
1483
|
process.exit(0);
|
|
1665
1484
|
}
|
|
1666
1485
|
}
|
|
@@ -1684,14 +1503,11 @@ function showTemplateList(recommended) {
|
|
|
1684
1503
|
}
|
|
1685
1504
|
}
|
|
1686
1505
|
async function searchInteractive() {
|
|
1687
|
-
const
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
validate: (i) => i.trim() ? true : "\u8BF7\u8F93\u5165\u5173\u952E\u8BCD"
|
|
1693
|
-
}
|
|
1694
|
-
]);
|
|
1506
|
+
const keyword = await p2.text({
|
|
1507
|
+
message: "\u641C\u7D22\u5173\u952E\u8BCD:",
|
|
1508
|
+
validate: (i) => i?.trim() ? void 0 : "\u8BF7\u8F93\u5165\u5173\u952E\u8BCD"
|
|
1509
|
+
});
|
|
1510
|
+
if (p2.isCancel(keyword)) return;
|
|
1695
1511
|
showSearchResults(keyword);
|
|
1696
1512
|
}
|
|
1697
1513
|
function showSearchResults(keyword) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agile-team/robot-cli",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "现代化项目脚手架工具,支持多技术栈快速创建项目 - 优先 bun,兼容 npm/pnpm/yarn",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -20,16 +20,15 @@
|
|
|
20
20
|
"release:major": "bun version major && bunx npm publish --access public"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
+
"@clack/prompts": "^1.1.0",
|
|
23
24
|
"chalk": "^5.3.0",
|
|
24
25
|
"commander": "^11.0.0",
|
|
25
26
|
"extract-zip": "^2.0.1",
|
|
26
27
|
"fs-extra": "^11.1.0",
|
|
27
|
-
"inquirer": "^9.2.0",
|
|
28
28
|
"ora": "^7.0.0"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@types/fs-extra": "^11.0.4",
|
|
32
|
-
"@types/inquirer": "^9.0.9",
|
|
33
32
|
"@types/node": "^22.0.0",
|
|
34
33
|
"oxlint": "^0.16.0",
|
|
35
34
|
"tsup": "^8.4.0",
|