@agile-team/jh4j-cloud-cli 0.5.1 → 0.6.1
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 +16 -0
- package/README.md +22 -14
- package/dist/index.js +335 -94
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.6.1
|
|
4
|
+
|
|
5
|
+
- 增加统一 JH4J 终端主题,真彩终端使用青色到靛蓝的品牌渐变,并兼容 `NO_COLOR` 与非 TTY 环境。
|
|
6
|
+
- 按语义区分交互色彩:青色表示重点、绿色表示成功、黄色表示待办、灰色表示辅助信息。
|
|
7
|
+
- 重构完成态信息层级,将项目摘要、本地服务、工程配置和运行状态分区展示。
|
|
8
|
+
- 将下一步命令独立为紧凑的主题色面板,移除大面积绿色结果边框。
|
|
9
|
+
- 模板拉取与项目生成使用统一品牌色加载动画。
|
|
10
|
+
|
|
11
|
+
## 0.6.0
|
|
12
|
+
|
|
13
|
+
- 直接展示 PC 管理端与移动端 H5 模板,并为每个选项提供独立技术栈提示。
|
|
14
|
+
- 增加“快速创建”和“自定义创建”两种方式;快速创建直接采用模板推荐值,自定义创建才询问项目名、标题、端口和联调地址。
|
|
15
|
+
- 下载与初始化过程改为轻量加载状态,不再显示冗余计时标签。
|
|
16
|
+
- 新增创建完成结果面板,集中展示模板版本、实际配置、预设能力、依赖与 Git 状态以及下一步命令。
|
|
17
|
+
- 用户取消时正常收尾,生成异常使用统一终端样式展示。
|
|
18
|
+
|
|
3
19
|
## 0.5.1
|
|
4
20
|
|
|
5
21
|
- 默认交互只选择项目类型并确认项目名;项目名直接回车使用默认值,也可以现场修改。
|
package/README.md
CHANGED
|
@@ -2,15 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
JH4J Cloud 团队项目脚手架,用于从受控模板快速创建结构一致、配置完整、可追溯的工程。
|
|
4
4
|
|
|
5
|
-
当前版本:`@agile-team/jh4j-cloud-cli@0.
|
|
5
|
+
当前版本:`@agile-team/jh4j-cloud-cli@0.6.1`。
|
|
6
6
|
|
|
7
7
|
## 核心能力
|
|
8
8
|
|
|
9
9
|
| 能力 | 说明 |
|
|
10
10
|
| --- | --- |
|
|
11
|
-
|
|
|
12
|
-
|
|
|
13
|
-
|
|
|
11
|
+
| 模板直选 | 直接展示 PC 管理端与移动端 H5,技术栈提示互不混淆 |
|
|
12
|
+
| 两种方式 | 快速创建直接使用模板推荐配置;自定义创建才展开必要参数 |
|
|
13
|
+
| 品牌终端 | 青色到靛蓝的 JH4J 品牌主题,并为成功、待办和辅助信息使用语义色彩 |
|
|
14
|
+
| 结果面板 | 分区展示模板版本、实际配置与预设能力,下一步命令使用独立紧凑面板 |
|
|
14
15
|
| 非交互创建 | 支持命令行参数和 JSON 配置文件,适用于 CI 与批量初始化 |
|
|
15
16
|
| 多源拉取 | 支持本地目录、Git、HTTP 压缩包和离线压缩包 |
|
|
16
17
|
| 源站容灾 | 内置模板按 GitHub → Gitee 顺序拉取,主源不可用时自动切换 |
|
|
@@ -24,7 +25,8 @@ JH4J Cloud 团队项目脚手架,用于从受控模板快速创建结构一致
|
|
|
24
25
|
```text
|
|
25
26
|
jh4j create
|
|
26
27
|
→ 读取 Catalog
|
|
27
|
-
→
|
|
28
|
+
→ 选择 PC 管理端或移动端 H5 模板
|
|
29
|
+
→ 选择快速创建或自定义创建
|
|
28
30
|
→ 解析可用模板源
|
|
29
31
|
→ 拉取或读取缓存
|
|
30
32
|
→ 校验 template.manifest.json
|
|
@@ -60,19 +62,23 @@ pnpm add -g @agile-team/jh4j-cloud-cli
|
|
|
60
62
|
jh4j create jh4j-ui-orders
|
|
61
63
|
```
|
|
62
64
|
|
|
63
|
-
|
|
65
|
+
默认交互提供两种创建方式:
|
|
64
66
|
|
|
65
67
|
```text
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
68
|
+
选择项目模板
|
|
69
|
+
├─ PC 管理端 Vue 3 · Vite · 微前端
|
|
70
|
+
└─ 移动端 H5 Vue 3 · Vite 7 · Vant 4
|
|
71
|
+
|
|
72
|
+
选择创建方式
|
|
73
|
+
├─ 快速创建(推荐) 使用模板推荐配置并立即生成
|
|
74
|
+
└─ 自定义创建 设置项目名、标题、端口和联调地址
|
|
71
75
|
```
|
|
72
76
|
|
|
73
|
-
|
|
77
|
+
快速创建不会继续提问:PC 使用 `jh4j-ui-app`,移动端使用 `jh4j-mobile-app`,标题、端口、联调地址、Registry、模块标识和各套环境配置全部采用模板推荐值。自定义创建中的输入框都带有可编辑默认值,直接回车接受,输入内容则覆盖默认值。
|
|
78
|
+
|
|
79
|
+
创建完成后会显示结果面板,列出技术栈、核心包、Git 与代码质量规范、多环境配置、开发地址、联调地址、依赖状态和下一步命令。默认不安装依赖,仍由开发者执行 `pnpm install`。需要后续调整时,直接修改项目中的 `project.config.json`、`.npmrc` 和 `.env*` 文件。
|
|
74
80
|
|
|
75
|
-
|
|
81
|
+
交互界面会根据终端能力自动适配:真彩终端显示 JH4J 青色到靛蓝的品牌渐变,普通终端自动降级到基础色,CI、重定向输出以及设置 `NO_COLOR` 时保持干净的纯文本结果。
|
|
76
82
|
|
|
77
83
|
当前 Catalog 中可用模板:
|
|
78
84
|
|
|
@@ -87,9 +93,11 @@ PC 项目名默认使用 `jh4j-ui-app`,移动端默认使用 `jh4j-mobile-app`
|
|
|
87
93
|
### 交互创建
|
|
88
94
|
|
|
89
95
|
```bash
|
|
90
|
-
jh4j create
|
|
96
|
+
jh4j create
|
|
91
97
|
```
|
|
92
98
|
|
|
99
|
+
快速创建会直接使用模板默认项目名。需要在创建前修改项目名及运行参数时,选择“自定义创建”;也可以把项目名作为参数传入:`jh4j create jh4j-ui-orders`。
|
|
100
|
+
|
|
93
101
|
### 使用明确参数创建
|
|
94
102
|
|
|
95
103
|
```bash
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
// src/index.ts
|
|
4
|
+
import * as prompts4 from "@clack/prompts";
|
|
5
|
+
|
|
3
6
|
// src/cli.ts
|
|
4
7
|
import { Command } from "commander";
|
|
5
8
|
|
|
6
9
|
// package.json
|
|
7
10
|
var package_default = {
|
|
8
11
|
name: "@agile-team/jh4j-cloud-cli",
|
|
9
|
-
version: "0.
|
|
12
|
+
version: "0.6.1",
|
|
10
13
|
description: "JH4J Cloud \u4F01\u4E1A\u5185\u90E8\u6807\u51C6\u5316\u9879\u76EE\u811A\u624B\u67B6",
|
|
11
14
|
repository: {
|
|
12
15
|
type: "git",
|
|
@@ -613,15 +616,77 @@ async function acquireTemplateFromSources(sources, ref, options = {}) {
|
|
|
613
616
|
}
|
|
614
617
|
|
|
615
618
|
// src/commands/create.ts
|
|
616
|
-
import * as
|
|
619
|
+
import * as prompts3 from "@clack/prompts";
|
|
617
620
|
|
|
618
621
|
// src/core/project-generator.ts
|
|
619
622
|
import { existsSync as existsSync6 } from "fs";
|
|
620
623
|
import { rename as rename3, rm as rm3 } from "fs/promises";
|
|
621
624
|
import path7 from "path";
|
|
622
|
-
import * as
|
|
625
|
+
import * as prompts2 from "@clack/prompts";
|
|
623
626
|
import { satisfies } from "semver";
|
|
624
627
|
|
|
628
|
+
// src/ui/theme.ts
|
|
629
|
+
import { stdout } from "process";
|
|
630
|
+
import { styleText } from "util";
|
|
631
|
+
import * as prompts from "@clack/prompts";
|
|
632
|
+
var BRAND_START = [34, 211, 238];
|
|
633
|
+
var BRAND_END = [99, 102, 241];
|
|
634
|
+
var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
635
|
+
function supportsTrueColor() {
|
|
636
|
+
if (process.env.FORCE_COLOR === "0") return false;
|
|
637
|
+
if (Number(process.env.FORCE_COLOR) >= 3) return true;
|
|
638
|
+
if (process.env.NO_COLOR !== void 0 || process.env.NODE_DISABLE_COLORS !== void 0) {
|
|
639
|
+
return false;
|
|
640
|
+
}
|
|
641
|
+
return Boolean(stdout.isTTY && stdout.getColorDepth?.() >= 24);
|
|
642
|
+
}
|
|
643
|
+
function interpolate(start, end, ratio) {
|
|
644
|
+
return Math.round(start + (end - start) * ratio);
|
|
645
|
+
}
|
|
646
|
+
function gradient(text3) {
|
|
647
|
+
if (!supportsTrueColor()) return styleText(["bold", "cyan"], text3);
|
|
648
|
+
const characters = [...text3];
|
|
649
|
+
const denominator = Math.max(characters.length - 1, 1);
|
|
650
|
+
return characters.map((character, index) => {
|
|
651
|
+
if (/\s/.test(character)) return character;
|
|
652
|
+
const ratio = index / denominator;
|
|
653
|
+
const red = interpolate(BRAND_START[0], BRAND_END[0], ratio);
|
|
654
|
+
const green = interpolate(BRAND_START[1], BRAND_END[1], ratio);
|
|
655
|
+
const blue = interpolate(BRAND_START[2], BRAND_END[2], ratio);
|
|
656
|
+
return `\x1B[1;38;2;${red};${green};${blue}m${character}\x1B[0m`;
|
|
657
|
+
}).join("");
|
|
658
|
+
}
|
|
659
|
+
function paint(format, text3) {
|
|
660
|
+
return styleText(format, text3, { stream: stdout });
|
|
661
|
+
}
|
|
662
|
+
var ui = {
|
|
663
|
+
brand: () => gradient("JH4J CLOUD"),
|
|
664
|
+
badge: (text3) => paint(["bold", "black", "bgCyan"], ` ${text3} `),
|
|
665
|
+
accent: (text3) => paint("cyan", text3),
|
|
666
|
+
secondary: (text3) => paint("blueBright", text3),
|
|
667
|
+
success: (text3) => paint("green", text3),
|
|
668
|
+
warning: (text3) => paint("yellow", text3),
|
|
669
|
+
danger: (text3) => paint("red", text3),
|
|
670
|
+
muted: (text3) => paint("dim", text3),
|
|
671
|
+
strong: (text3) => paint("bold", text3),
|
|
672
|
+
command: (text3) => paint(["bold", "cyan"], text3)
|
|
673
|
+
};
|
|
674
|
+
function createBrandSpinner() {
|
|
675
|
+
return prompts.spinner({
|
|
676
|
+
frames: SPINNER_FRAMES,
|
|
677
|
+
delay: 80,
|
|
678
|
+
styleFrame: (frame) => ui.accent(frame)
|
|
679
|
+
});
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
// src/core/errors.ts
|
|
683
|
+
var UserCancelledError = class extends Error {
|
|
684
|
+
constructor() {
|
|
685
|
+
super("\u7528\u6237\u53D6\u6D88\u521B\u5EFA");
|
|
686
|
+
this.name = "UserCancelledError";
|
|
687
|
+
}
|
|
688
|
+
};
|
|
689
|
+
|
|
625
690
|
// src/core/template-manifest.ts
|
|
626
691
|
import path6 from "path";
|
|
627
692
|
async function loadTemplateManifest(templateRoot) {
|
|
@@ -700,6 +765,16 @@ function ensureHttpUrl(value, label) {
|
|
|
700
765
|
throw new Error(`${label} \u5FC5\u987B\u662F http/https URL`);
|
|
701
766
|
}
|
|
702
767
|
}
|
|
768
|
+
async function askText(message, initialValue, validate) {
|
|
769
|
+
const answer = await prompts2.text({
|
|
770
|
+
message,
|
|
771
|
+
initialValue,
|
|
772
|
+
defaultValue: initialValue,
|
|
773
|
+
validate
|
|
774
|
+
});
|
|
775
|
+
if (prompts2.isCancel(answer)) throw new UserCancelledError();
|
|
776
|
+
return String(answer).trim() || initialValue;
|
|
777
|
+
}
|
|
703
778
|
async function loadCreateConfig(configFile, cwd) {
|
|
704
779
|
if (!configFile) return {};
|
|
705
780
|
const resolved = path7.resolve(cwd, configFile);
|
|
@@ -747,6 +822,29 @@ async function collectProjectInput(projectName, sourceConfig, fileConfig, option
|
|
|
747
822
|
environments[env] = { ...environments[env], ...value };
|
|
748
823
|
}
|
|
749
824
|
}
|
|
825
|
+
if (options.customize && !options.yes) {
|
|
826
|
+
title = await askText(
|
|
827
|
+
ui.strong("\u5E94\u7528\u6807\u9898"),
|
|
828
|
+
title,
|
|
829
|
+
(value) => value?.trim() ? void 0 : "\u5E94\u7528\u6807\u9898\u4E0D\u80FD\u4E3A\u7A7A"
|
|
830
|
+
);
|
|
831
|
+
port = await askText(ui.strong("\u5F00\u53D1\u7AEF\u53E3"), String(port), (value) => {
|
|
832
|
+
const parsed = Number(value);
|
|
833
|
+
return Number.isInteger(parsed) && parsed >= 1024 && parsed <= 65535 ? void 0 : "\u8BF7\u8F93\u5165 1024 \u5230 65535 \u4E4B\u95F4\u7684\u7AEF\u53E3";
|
|
834
|
+
});
|
|
835
|
+
localBackendUrl = await askText(
|
|
836
|
+
ui.strong("\u672C\u5730\u8054\u8C03\u5730\u5740"),
|
|
837
|
+
localBackendUrl,
|
|
838
|
+
(value) => {
|
|
839
|
+
try {
|
|
840
|
+
const url = new URL(value ?? "");
|
|
841
|
+
return url.protocol === "http:" || url.protocol === "https:" ? void 0 : "\u8BF7\u8F93\u5165\u5B8C\u6574\u7684 http/https \u5730\u5740";
|
|
842
|
+
} catch {
|
|
843
|
+
return "\u8BF7\u8F93\u5165\u5B8C\u6574\u7684 http/https \u5730\u5740";
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
);
|
|
847
|
+
}
|
|
750
848
|
if (!title.trim()) throw new Error("\u7CFB\u7EDF\u6807\u9898\u4E0D\u80FD\u4E3A\u7A7A");
|
|
751
849
|
for (const env of ENV_NAMES) {
|
|
752
850
|
if (!environments[env]) throw new Error(`\u7F3A\u5C11 ${env.toUpperCase()} \u73AF\u5883\u914D\u7F6E`);
|
|
@@ -796,7 +894,7 @@ async function promoteStaging(stagingRoot, targetRoot, force) {
|
|
|
796
894
|
try {
|
|
797
895
|
await removePath(backupRoot);
|
|
798
896
|
} catch {
|
|
799
|
-
|
|
897
|
+
prompts2.log.warn(`\u65E7\u76EE\u5F55\u5907\u4EFD\u672A\u80FD\u81EA\u52A8\u6E05\u7406: ${backupRoot}`);
|
|
800
898
|
}
|
|
801
899
|
}
|
|
802
900
|
async function generateProject(catalogTemplate, requestedProjectName, options, cwd = process.cwd(), configuredUserConfig = DEFAULT_USER_CONFIG) {
|
|
@@ -814,7 +912,7 @@ async function generateProject(catalogTemplate, requestedProjectName, options, c
|
|
|
814
912
|
options.source,
|
|
815
913
|
userConfig.templateSource
|
|
816
914
|
);
|
|
817
|
-
const acquisitionSpinner = options.yes ? void 0 :
|
|
915
|
+
const acquisitionSpinner = options.yes ? void 0 : createBrandSpinner();
|
|
818
916
|
acquisitionSpinner?.start("\u6B63\u5728\u83B7\u53D6\u5E76\u6821\u9A8C\u6A21\u677F");
|
|
819
917
|
let acquired;
|
|
820
918
|
try {
|
|
@@ -822,7 +920,7 @@ async function generateProject(catalogTemplate, requestedProjectName, options, c
|
|
|
822
920
|
noCache: options.cache === false,
|
|
823
921
|
cacheTtlMinutes: userConfig.cacheTtlMinutes
|
|
824
922
|
});
|
|
825
|
-
acquisitionSpinner?.stop("\u6A21\u677F\
|
|
923
|
+
acquisitionSpinner?.stop("\u6A21\u677F\u5DF2\u5C31\u7EEA");
|
|
826
924
|
} catch (error) {
|
|
827
925
|
acquisitionSpinner?.error("\u6A21\u677F\u83B7\u53D6\u5931\u8D25");
|
|
828
926
|
throw error;
|
|
@@ -832,6 +930,7 @@ async function generateProject(catalogTemplate, requestedProjectName, options, c
|
|
|
832
930
|
`.${projectName}.jh4j-tmp-${process.pid}-${Date.now()}`
|
|
833
931
|
);
|
|
834
932
|
let promoted = false;
|
|
933
|
+
let generationSpinner;
|
|
835
934
|
try {
|
|
836
935
|
const manifest = await loadTemplateManifest(acquired.root);
|
|
837
936
|
if (manifest.id !== catalogTemplate.id) {
|
|
@@ -862,7 +961,7 @@ async function generateProject(catalogTemplate, requestedProjectName, options, c
|
|
|
862
961
|
const shouldInstall = !options.skipInstall && (options.install === true || userConfig.autoInstall);
|
|
863
962
|
const shouldInitializeGit = !options.skipGit && userConfig.autoGit;
|
|
864
963
|
if (options.dryRun) {
|
|
865
|
-
|
|
964
|
+
prompts2.note(
|
|
866
965
|
[
|
|
867
966
|
`\u6A21\u677F: ${manifest.id}@${manifest.version}`,
|
|
868
967
|
`\u6765\u6E90: ${acquired.source}`,
|
|
@@ -878,13 +977,23 @@ async function generateProject(catalogTemplate, requestedProjectName, options, c
|
|
|
878
977
|
return {
|
|
879
978
|
targetRoot,
|
|
880
979
|
templateId: manifest.id,
|
|
980
|
+
templateName: manifest.name,
|
|
881
981
|
templateVersion: manifest.version,
|
|
982
|
+
category: manifest.category,
|
|
882
983
|
source: acquired.source,
|
|
883
984
|
features: input.features,
|
|
884
985
|
installed: false,
|
|
885
|
-
gitInitialized: false
|
|
986
|
+
gitInitialized: false,
|
|
987
|
+
configuration: {
|
|
988
|
+
title: input.title,
|
|
989
|
+
moduleName: input.moduleName,
|
|
990
|
+
devServerPort: input.devServerPort,
|
|
991
|
+
localBackendUrl: input.localBackendUrl
|
|
992
|
+
}
|
|
886
993
|
};
|
|
887
994
|
}
|
|
995
|
+
generationSpinner = options.yes ? void 0 : createBrandSpinner();
|
|
996
|
+
generationSpinner?.start("\u6B63\u5728\u751F\u6210\u9879\u76EE\u6587\u4EF6");
|
|
888
997
|
await copyTemplateTree(acquired.root, stagingRoot);
|
|
889
998
|
const inputFile = path7.join(stagingRoot, ".jh4j-cli-input.json");
|
|
890
999
|
await writeJson(inputFile, input);
|
|
@@ -911,6 +1020,7 @@ async function generateProject(catalogTemplate, requestedProjectName, options, c
|
|
|
911
1020
|
promoted = true;
|
|
912
1021
|
let gitInitialized = false;
|
|
913
1022
|
if (shouldInitializeGit) {
|
|
1023
|
+
generationSpinner?.message("\u6B63\u5728\u521D\u59CB\u5316 Git main \u4ED3\u5E93");
|
|
914
1024
|
await runCommand("git", ["init", "-b", "main"], {
|
|
915
1025
|
cwd: targetRoot,
|
|
916
1026
|
stdio: "pipe"
|
|
@@ -918,8 +1028,12 @@ async function generateProject(catalogTemplate, requestedProjectName, options, c
|
|
|
918
1028
|
gitInitialized = true;
|
|
919
1029
|
}
|
|
920
1030
|
if (shouldInstall) {
|
|
1031
|
+
generationSpinner?.message("\u6B63\u5728\u5B89\u88C5\u9879\u76EE\u4F9D\u8D56");
|
|
921
1032
|
try {
|
|
922
|
-
await runCommand("pnpm", ["install"], {
|
|
1033
|
+
await runCommand("pnpm", ["install"], {
|
|
1034
|
+
cwd: targetRoot,
|
|
1035
|
+
stdio: "pipe"
|
|
1036
|
+
});
|
|
923
1037
|
} catch (error) {
|
|
924
1038
|
throw new Error(
|
|
925
1039
|
`\u9879\u76EE\u5DF2\u751F\u6210\uFF0C\u4F46\u4F9D\u8D56\u5B89\u88C5\u5931\u8D25\uFF1B\u76EE\u5F55\u5DF2\u4FDD\u7559\u5728 ${targetRoot}
|
|
@@ -927,7 +1041,9 @@ ${error.message}`
|
|
|
927
1041
|
);
|
|
928
1042
|
}
|
|
929
1043
|
}
|
|
1044
|
+
let initialCommitWarning;
|
|
930
1045
|
if (shouldInitializeGit) {
|
|
1046
|
+
generationSpinner?.message("\u6B63\u5728\u521B\u5EFA\u521D\u59CB\u63D0\u4EA4");
|
|
931
1047
|
await runCommand("git", ["add", "-A"], { cwd: targetRoot, stdio: "pipe" });
|
|
932
1048
|
try {
|
|
933
1049
|
await runCommand(
|
|
@@ -940,18 +1056,33 @@ ${error.message}`
|
|
|
940
1056
|
}
|
|
941
1057
|
);
|
|
942
1058
|
} catch (error) {
|
|
943
|
-
|
|
1059
|
+
initialCommitWarning = `Git \u5DF2\u521D\u59CB\u5316\uFF0C\u4F46\u521D\u59CB\u63D0\u4EA4\u672A\u5B8C\u6210\uFF1A${error.message}`;
|
|
944
1060
|
}
|
|
945
1061
|
}
|
|
1062
|
+
generationSpinner?.stop("\u9879\u76EE\u6587\u4EF6\u521D\u59CB\u5316\u5B8C\u6210");
|
|
1063
|
+
if (initialCommitWarning) prompts2.log.warn(initialCommitWarning);
|
|
946
1064
|
return {
|
|
947
1065
|
targetRoot,
|
|
948
1066
|
templateId: manifest.id,
|
|
1067
|
+
templateName: manifest.name,
|
|
949
1068
|
templateVersion: manifest.version,
|
|
1069
|
+
category: manifest.category,
|
|
950
1070
|
source: acquired.source,
|
|
951
1071
|
features: input.features,
|
|
952
1072
|
installed: shouldInstall,
|
|
953
|
-
gitInitialized
|
|
1073
|
+
gitInitialized,
|
|
1074
|
+
configuration: {
|
|
1075
|
+
title: input.title,
|
|
1076
|
+
moduleName: input.moduleName,
|
|
1077
|
+
devServerPort: input.devServerPort,
|
|
1078
|
+
localBackendUrl: input.localBackendUrl
|
|
1079
|
+
}
|
|
954
1080
|
};
|
|
1081
|
+
} catch (error) {
|
|
1082
|
+
generationSpinner?.error(
|
|
1083
|
+
promoted ? "\u9879\u76EE\u5DF2\u751F\u6210\uFF0C\u540E\u7EED\u6B65\u9AA4\u672A\u5B8C\u6210" : "\u9879\u76EE\u751F\u6210\u5931\u8D25"
|
|
1084
|
+
);
|
|
1085
|
+
throw error;
|
|
955
1086
|
} finally {
|
|
956
1087
|
if (!promoted && existsSync6(stagingRoot)) await removePath(stagingRoot);
|
|
957
1088
|
await acquired.cleanup();
|
|
@@ -959,21 +1090,37 @@ ${error.message}`
|
|
|
959
1090
|
}
|
|
960
1091
|
|
|
961
1092
|
// src/commands/create.ts
|
|
962
|
-
var
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
1093
|
+
var TEMPLATE_PRESENTATION = {
|
|
1094
|
+
frontend: { label: "PC \u7BA1\u7406\u7AEF", hint: "Vue 3 \xB7 Vite \xB7 \u5FAE\u524D\u7AEF" },
|
|
1095
|
+
backend: { label: "\u540E\u7AEF\u670D\u52A1", hint: "Java \xB7 Spring Cloud \xB7 \u4E91\u539F\u751F" },
|
|
1096
|
+
mobile: { label: "\u79FB\u52A8\u7AEF H5", hint: "Vue 3 \xB7 Vite 7 \xB7 Vant 4" }
|
|
1097
|
+
};
|
|
967
1098
|
function isCategory(value) {
|
|
968
|
-
return
|
|
1099
|
+
return Object.hasOwn(TEMPLATE_PRESENTATION, value);
|
|
969
1100
|
}
|
|
970
1101
|
function templatesByCategory(templates, category) {
|
|
971
1102
|
return templates.filter((template) => template.category === category);
|
|
972
1103
|
}
|
|
973
|
-
function
|
|
974
|
-
return
|
|
975
|
-
|
|
976
|
-
|
|
1104
|
+
function templateOptionsFor(templates) {
|
|
1105
|
+
return templates.map((template) => ({
|
|
1106
|
+
value: template.id,
|
|
1107
|
+
label: TEMPLATE_PRESENTATION[template.category].label,
|
|
1108
|
+
hint: TEMPLATE_PRESENTATION[template.category].hint
|
|
1109
|
+
}));
|
|
1110
|
+
}
|
|
1111
|
+
function creationModeOptions() {
|
|
1112
|
+
return [
|
|
1113
|
+
{
|
|
1114
|
+
value: "quick",
|
|
1115
|
+
label: "\u5FEB\u901F\u521B\u5EFA\uFF08\u63A8\u8350\uFF09",
|
|
1116
|
+
hint: "\u91C7\u7528\u6A21\u677F\u63A8\u8350\u914D\u7F6E\uFF0C\u7ACB\u5373\u751F\u6210"
|
|
1117
|
+
},
|
|
1118
|
+
{
|
|
1119
|
+
value: "custom",
|
|
1120
|
+
label: "\u81EA\u5B9A\u4E49\u521B\u5EFA",
|
|
1121
|
+
hint: "\u8BBE\u7F6E\u9879\u76EE\u540D\u3001\u6807\u9898\u3001\u7AEF\u53E3\u548C\u8054\u8C03\u5730\u5740"
|
|
1122
|
+
}
|
|
1123
|
+
];
|
|
977
1124
|
}
|
|
978
1125
|
function defaultProjectNameFor(category) {
|
|
979
1126
|
if (category === "mobile") return "jh4j-mobile-app";
|
|
@@ -983,7 +1130,7 @@ function defaultProjectNameFor(category) {
|
|
|
983
1130
|
function projectNamePromptOptions(category) {
|
|
984
1131
|
const defaultProjectName = defaultProjectNameFor(category);
|
|
985
1132
|
return {
|
|
986
|
-
message: "\u9879\u76EE\u540D\u79F0",
|
|
1133
|
+
message: ui.strong("\u9879\u76EE\u540D\u79F0"),
|
|
987
1134
|
initialValue: defaultProjectName,
|
|
988
1135
|
defaultValue: defaultProjectName,
|
|
989
1136
|
validate(value) {
|
|
@@ -991,35 +1138,6 @@ function projectNamePromptOptions(category) {
|
|
|
991
1138
|
}
|
|
992
1139
|
};
|
|
993
1140
|
}
|
|
994
|
-
async function selectCategory(templates, requestedCategory, nonInteractive) {
|
|
995
|
-
if (requestedCategory) {
|
|
996
|
-
if (!isCategory(requestedCategory)) {
|
|
997
|
-
throw new Error(
|
|
998
|
-
`\u9879\u76EE\u7C7B\u578B\u65E0\u6548: ${requestedCategory}\u3002\u53EF\u7528\u503C: frontend\u3001backend\u3001mobile`
|
|
999
|
-
);
|
|
1000
|
-
}
|
|
1001
|
-
if (!templatesByCategory(templates, requestedCategory).length) {
|
|
1002
|
-
throw new Error(`\u9879\u76EE\u7C7B\u578B ${requestedCategory} \u6682\u65E0\u53EF\u7528\u6A21\u677F`);
|
|
1003
|
-
}
|
|
1004
|
-
return requestedCategory;
|
|
1005
|
-
}
|
|
1006
|
-
const firstAvailable = CATEGORY_OPTIONS.find(
|
|
1007
|
-
(item) => templatesByCategory(templates, item.value).length > 0
|
|
1008
|
-
);
|
|
1009
|
-
if (!firstAvailable) throw new Error("Catalog \u4E2D\u6CA1\u6709\u53EF\u7528\u6A21\u677F");
|
|
1010
|
-
if (nonInteractive) return firstAvailable.value;
|
|
1011
|
-
const availableOptions = categoryOptionsFor(templates);
|
|
1012
|
-
if (availableOptions.length === 1) return availableOptions[0].value;
|
|
1013
|
-
const selected = await prompts2.select({
|
|
1014
|
-
message: "\u9009\u62E9\u9879\u76EE\u7C7B\u578B",
|
|
1015
|
-
options: availableOptions.map((item) => ({
|
|
1016
|
-
value: item.value,
|
|
1017
|
-
label: item.label
|
|
1018
|
-
}))
|
|
1019
|
-
});
|
|
1020
|
-
if (prompts2.isCancel(selected)) throw new Error("\u7528\u6237\u53D6\u6D88\u521B\u5EFA");
|
|
1021
|
-
return selected;
|
|
1022
|
-
}
|
|
1023
1141
|
async function selectTemplate(templates, options) {
|
|
1024
1142
|
if (options.template) {
|
|
1025
1143
|
const selected2 = findTemplate(templates, options.template);
|
|
@@ -1030,75 +1148,200 @@ async function selectTemplate(templates, options) {
|
|
|
1030
1148
|
}
|
|
1031
1149
|
return selected2;
|
|
1032
1150
|
}
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
);
|
|
1038
|
-
const candidates = templatesByCategory(templates, category);
|
|
1039
|
-
if (options.yes) return findTemplate(candidates);
|
|
1040
|
-
if (candidates.length === 1) {
|
|
1041
|
-
const selected2 = candidates[0];
|
|
1042
|
-
prompts2.log.info(`\u4F7F\u7528\u6A21\u677F\uFF1A${selected2.name}`);
|
|
1043
|
-
return selected2;
|
|
1151
|
+
if (options.category && !isCategory(options.category)) {
|
|
1152
|
+
throw new Error(
|
|
1153
|
+
`\u9879\u76EE\u7C7B\u578B\u65E0\u6548: ${options.category}\u3002\u53EF\u7528\u503C: frontend\u3001backend\u3001mobile`
|
|
1154
|
+
);
|
|
1044
1155
|
}
|
|
1045
|
-
const
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1156
|
+
const candidates = options.category ? templatesByCategory(templates, options.category) : templates;
|
|
1157
|
+
if (!candidates.length) {
|
|
1158
|
+
throw new Error(
|
|
1159
|
+
options.category ? `\u9879\u76EE\u7C7B\u578B ${options.category} \u6682\u65E0\u53EF\u7528\u6A21\u677F` : "Catalog \u4E2D\u6CA1\u6709\u53EF\u7528\u6A21\u677F"
|
|
1160
|
+
);
|
|
1161
|
+
}
|
|
1162
|
+
if (options.yes) return findTemplate(candidates);
|
|
1163
|
+
if (candidates.length === 1) return candidates[0];
|
|
1164
|
+
const selected = await prompts3.select({
|
|
1165
|
+
message: ui.strong("\u9009\u62E9\u9879\u76EE\u6A21\u677F"),
|
|
1166
|
+
options: templateOptionsFor(candidates).map((option) => ({
|
|
1167
|
+
...option,
|
|
1168
|
+
label: ui.strong(option.label),
|
|
1169
|
+
hint: ui.muted(option.hint)
|
|
1170
|
+
})),
|
|
1171
|
+
initialValue: candidates[0].id
|
|
1051
1172
|
});
|
|
1052
|
-
if (
|
|
1173
|
+
if (prompts3.isCancel(selected)) throw new UserCancelledError();
|
|
1053
1174
|
return findTemplate(candidates, String(selected));
|
|
1054
1175
|
}
|
|
1055
|
-
async function
|
|
1056
|
-
|
|
1176
|
+
async function selectCreationMode(options) {
|
|
1177
|
+
if (options.yes) return "quick";
|
|
1178
|
+
const selected = await prompts3.select({
|
|
1179
|
+
message: ui.strong("\u9009\u62E9\u521B\u5EFA\u65B9\u5F0F"),
|
|
1180
|
+
options: creationModeOptions().map((option) => ({
|
|
1181
|
+
...option,
|
|
1182
|
+
label: option.value === "quick" ? ui.accent(ui.strong(option.label)) : ui.strong(option.label),
|
|
1183
|
+
hint: ui.muted(option.hint)
|
|
1184
|
+
})),
|
|
1185
|
+
initialValue: "quick"
|
|
1186
|
+
});
|
|
1187
|
+
if (prompts3.isCancel(selected)) throw new UserCancelledError();
|
|
1188
|
+
return selected;
|
|
1189
|
+
}
|
|
1190
|
+
function profileRowsFor(category, features) {
|
|
1191
|
+
const rows = category === "mobile" ? [
|
|
1192
|
+
{ label: "\u6280\u672F", value: "Vue 3 \xB7 Vite 7 \xB7 Vant 4 \xB7 TypeScript" },
|
|
1193
|
+
{ label: "\u6838\u5FC3", value: "@robot-h5/core" }
|
|
1194
|
+
] : category === "frontend" ? [
|
|
1195
|
+
{ label: "\u6280\u672F", value: "Vue 3 \xB7 Vite \xB7 Module Federation" },
|
|
1196
|
+
{ label: "\u6838\u5FC3", value: "@jhlc/common-core" }
|
|
1197
|
+
] : [{ label: "\u6280\u672F", value: "Java \xB7 Spring Cloud" }];
|
|
1198
|
+
if (features.includes("git-standards")) {
|
|
1199
|
+
rows.push({ label: "\u89C4\u8303", value: "Commitizen \xB7 Commitlint \xB7 Husky \xB7 ESLint" });
|
|
1200
|
+
}
|
|
1201
|
+
rows.push({ label: "\u73AF\u5883", value: "DEV \xB7 SIT \xB7 UAT \xB7 PRE \xB7 PRD" });
|
|
1202
|
+
return rows;
|
|
1203
|
+
}
|
|
1204
|
+
function buildCompletionView(projectName, mode, result) {
|
|
1205
|
+
const nextSteps = [
|
|
1206
|
+
`cd ${projectName}`,
|
|
1207
|
+
...!result.installed ? ["pnpm install", "pnpm dev"] : ["pnpm dev"]
|
|
1208
|
+
];
|
|
1209
|
+
return {
|
|
1210
|
+
headline: `${projectName} \u521B\u5EFA\u6210\u529F`,
|
|
1211
|
+
overview: [
|
|
1212
|
+
{
|
|
1213
|
+
label: "\u6A21\u677F",
|
|
1214
|
+
value: `${result.templateName} \xB7 v${result.templateVersion}`
|
|
1215
|
+
},
|
|
1216
|
+
{ label: "\u6807\u9898", value: result.configuration.title },
|
|
1217
|
+
{ label: "\u65B9\u5F0F", value: mode === "quick" ? "\u5FEB\u901F\u521B\u5EFA" : "\u81EA\u5B9A\u4E49\u521B\u5EFA" }
|
|
1218
|
+
],
|
|
1219
|
+
endpoints: [
|
|
1220
|
+
{
|
|
1221
|
+
label: "APP",
|
|
1222
|
+
value: `http://localhost:${result.configuration.devServerPort}`
|
|
1223
|
+
},
|
|
1224
|
+
{ label: "API", value: result.configuration.localBackendUrl }
|
|
1225
|
+
],
|
|
1226
|
+
profile: profileRowsFor(result.category, result.features),
|
|
1227
|
+
gitInitialized: result.gitInitialized,
|
|
1228
|
+
installed: result.installed,
|
|
1229
|
+
nextSteps,
|
|
1230
|
+
configFiles: "project.config.json \xB7 .env*"
|
|
1231
|
+
};
|
|
1232
|
+
}
|
|
1233
|
+
function row(label, value) {
|
|
1234
|
+
return `${ui.muted(`${label} `)}${value}`;
|
|
1235
|
+
}
|
|
1236
|
+
function renderCompletion(projectName, mode, result) {
|
|
1237
|
+
const view = buildCompletionView(projectName, mode, result);
|
|
1238
|
+
prompts3.log.message(
|
|
1239
|
+
[
|
|
1240
|
+
ui.strong(view.headline),
|
|
1241
|
+
...view.overview.map((item) => row(item.label, item.value))
|
|
1242
|
+
],
|
|
1243
|
+
{
|
|
1244
|
+
symbol: ui.success("\u25C6"),
|
|
1245
|
+
secondarySymbol: ui.muted("\u2502"),
|
|
1246
|
+
spacing: 1
|
|
1247
|
+
}
|
|
1248
|
+
);
|
|
1249
|
+
prompts3.log.message(
|
|
1250
|
+
[
|
|
1251
|
+
ui.strong("\u672C\u5730\u670D\u52A1"),
|
|
1252
|
+
...view.endpoints.map((item) => row(item.label, ui.accent(item.value)))
|
|
1253
|
+
],
|
|
1254
|
+
{
|
|
1255
|
+
symbol: ui.accent("\u25C7"),
|
|
1256
|
+
secondarySymbol: ui.muted("\u2502"),
|
|
1257
|
+
spacing: 1
|
|
1258
|
+
}
|
|
1259
|
+
);
|
|
1260
|
+
const gitStatus = view.gitInitialized ? ui.success("Git main \u5DF2\u521D\u59CB\u5316") : ui.muted("Git \u672A\u521D\u59CB\u5316");
|
|
1261
|
+
const dependencyStatus = view.installed ? ui.success("\u4F9D\u8D56\u5DF2\u5B89\u88C5") : ui.warning("\u4F9D\u8D56\u5F85\u5B89\u88C5");
|
|
1262
|
+
prompts3.log.message(
|
|
1263
|
+
[
|
|
1264
|
+
ui.strong("\u5DE5\u7A0B\u914D\u7F6E"),
|
|
1265
|
+
...view.profile.map((item) => row(item.label, item.value)),
|
|
1266
|
+
row("\u72B6\u6001", `${gitStatus} ${ui.muted("\xB7")} ${dependencyStatus}`)
|
|
1267
|
+
],
|
|
1268
|
+
{
|
|
1269
|
+
symbol: ui.secondary("\u25C7"),
|
|
1270
|
+
secondarySymbol: ui.muted("\u2502"),
|
|
1271
|
+
spacing: 1
|
|
1272
|
+
}
|
|
1273
|
+
);
|
|
1274
|
+
prompts3.outro(`${ui.success("READY")} ${ui.muted("\xB7 \u9879\u76EE\u5DF2\u51C6\u5907\u5C31\u7EEA")}`);
|
|
1275
|
+
prompts3.box(
|
|
1276
|
+
[
|
|
1277
|
+
"",
|
|
1278
|
+
...view.nextSteps.map(
|
|
1279
|
+
(command, index) => ` ${ui.muted(String(index + 1).padStart(2, "0"))} ${ui.command(command)}`
|
|
1280
|
+
),
|
|
1281
|
+
"",
|
|
1282
|
+
` ${ui.muted("\u914D\u7F6E")} ${ui.muted(view.configFiles)}`,
|
|
1283
|
+
""
|
|
1284
|
+
].join("\n"),
|
|
1285
|
+
ui.accent(ui.strong(" NEXT STEPS ")),
|
|
1286
|
+
{
|
|
1287
|
+
rounded: true,
|
|
1288
|
+
width: "auto",
|
|
1289
|
+
titleAlign: "left",
|
|
1290
|
+
titlePadding: 2,
|
|
1291
|
+
contentPadding: 1,
|
|
1292
|
+
withGuide: false,
|
|
1293
|
+
formatBorder: (value) => ui.accent(value)
|
|
1294
|
+
}
|
|
1295
|
+
);
|
|
1296
|
+
}
|
|
1297
|
+
async function executeCreateCommand(requestedName, options) {
|
|
1057
1298
|
const userConfig = await loadUserConfig();
|
|
1058
1299
|
const catalog = await loadCatalog(userConfig);
|
|
1059
1300
|
const template = await selectTemplate(catalog, options);
|
|
1301
|
+
const mode = await selectCreationMode(options);
|
|
1060
1302
|
const defaultProjectName = defaultProjectNameFor(template.category);
|
|
1061
1303
|
let rawProjectName = requestedName;
|
|
1062
|
-
if (!rawProjectName && !options.yes) {
|
|
1063
|
-
const answer = await
|
|
1304
|
+
if (mode === "custom" && !rawProjectName && !options.yes) {
|
|
1305
|
+
const answer = await prompts3.text(
|
|
1064
1306
|
projectNamePromptOptions(template.category)
|
|
1065
1307
|
);
|
|
1066
|
-
if (
|
|
1308
|
+
if (prompts3.isCancel(answer)) throw new UserCancelledError();
|
|
1067
1309
|
rawProjectName = String(answer).trim() || defaultProjectName;
|
|
1068
1310
|
}
|
|
1069
1311
|
rawProjectName ??= defaultProjectName;
|
|
1070
|
-
|
|
1071
|
-
projectName = normalizeProjectName(rawProjectName);
|
|
1312
|
+
const projectName = normalizeProjectName(rawProjectName);
|
|
1072
1313
|
if (!projectName) {
|
|
1073
1314
|
throw new Error("\u9879\u76EE\u540D\u79F0\u81F3\u5C11\u9700\u8981\u5305\u542B\u4E00\u4E2A\u5B57\u6BCD\u6216\u6570\u5B57");
|
|
1074
1315
|
}
|
|
1075
1316
|
if (projectName !== rawProjectName) {
|
|
1076
|
-
|
|
1317
|
+
prompts3.log.info(`\u9879\u76EE\u540D\u79F0\u5DF2\u89C4\u8303\u5316\uFF1A${projectName}`);
|
|
1077
1318
|
}
|
|
1078
|
-
prompts2.log.info("\u5176\u4F59\u914D\u7F6E\u4F7F\u7528\u6A21\u677F\u9ED8\u8BA4\u503C\uFF0C\u751F\u6210\u540E\u53EF\u5728\u9879\u76EE\u5185\u4FEE\u6539");
|
|
1079
1319
|
const result = await generateProject(
|
|
1080
1320
|
template,
|
|
1081
1321
|
projectName,
|
|
1082
|
-
options,
|
|
1322
|
+
{ ...options, customize: mode === "custom" },
|
|
1083
1323
|
process.cwd(),
|
|
1084
1324
|
userConfig
|
|
1085
1325
|
);
|
|
1086
1326
|
if (options.dryRun) {
|
|
1087
|
-
|
|
1327
|
+
prompts3.outro("Dry Run \u5B8C\u6210\uFF0C\u672A\u5199\u5165\u4EFB\u4F55\u9879\u76EE\u6587\u4EF6");
|
|
1088
1328
|
return;
|
|
1089
1329
|
}
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
`cd ${projectName}`,
|
|
1096
|
-
...!result.installed ? ["pnpm install"] : [],
|
|
1097
|
-
"pnpm dev",
|
|
1098
|
-
"",
|
|
1099
|
-
"\u914D\u7F6E\uFF1Aproject.config.json / .npmrc / .env*"
|
|
1100
|
-
].join("\n")
|
|
1330
|
+
renderCompletion(projectName, mode, result);
|
|
1331
|
+
}
|
|
1332
|
+
async function createCommand(requestedName, options) {
|
|
1333
|
+
prompts3.intro(
|
|
1334
|
+
`${ui.brand()} ${ui.badge("CREATE")} ${ui.muted(`v${CLI_VERSION}`)}`
|
|
1101
1335
|
);
|
|
1336
|
+
try {
|
|
1337
|
+
await executeCreateCommand(requestedName, options);
|
|
1338
|
+
} catch (error) {
|
|
1339
|
+
if (error instanceof UserCancelledError) {
|
|
1340
|
+
prompts3.cancel("\u5DF2\u53D6\u6D88\u521B\u5EFA\uFF0C\u672A\u5199\u5165\u4EFB\u4F55\u9879\u76EE\u6587\u4EF6");
|
|
1341
|
+
return;
|
|
1342
|
+
}
|
|
1343
|
+
throw error;
|
|
1344
|
+
}
|
|
1102
1345
|
}
|
|
1103
1346
|
|
|
1104
1347
|
// src/commands/doctor.ts
|
|
@@ -1349,9 +1592,7 @@ async function runCli(argv = process.argv) {
|
|
|
1349
1592
|
|
|
1350
1593
|
// src/index.ts
|
|
1351
1594
|
runCli().catch((error) => {
|
|
1352
|
-
|
|
1353
|
-
\u9519\u8BEF: ${error.message}
|
|
1354
|
-
`);
|
|
1595
|
+
prompts4.cancel(`\u64CD\u4F5C\u5931\u8D25\uFF1A${error.message}`);
|
|
1355
1596
|
process.exitCode = 1;
|
|
1356
1597
|
});
|
|
1357
1598
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../package.json","../src/constants.ts","../src/catalog.ts","../src/utils/fs.ts","../src/core/template-source.ts","../src/utils/process.ts","../src/core/template-cache.ts","../src/core/user-config.ts","../src/commands/create.ts","../src/core/project-generator.ts","../src/core/template-manifest.ts","../src/commands/doctor.ts","../src/commands/info.ts","../src/commands/list.ts","../src/commands/template.ts","../src/commands/config.ts","../src/commands/cache.ts","../src/index.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { COMMAND_NAME, CLI_VERSION } from \"./constants.js\";\nimport { findTemplate, loadCatalog } from \"./catalog.js\";\nimport {\n acquireTemplateFromSources,\n resolveTemplateSources\n} from \"./core/template-source.js\";\nimport { loadUserConfig } from \"./core/user-config.js\";\nimport { createCommand } from \"./commands/create.js\";\nimport { doctorCommand } from \"./commands/doctor.js\";\nimport { infoCommand } from \"./commands/info.js\";\nimport { listCommand } from \"./commands/list.js\";\nimport { validateTemplateCommand } from \"./commands/template.js\";\nimport {\n configGetCommand,\n configListCommand,\n configResetCommand,\n configSetCommand,\n configUnsetCommand\n} from \"./commands/config.js\";\nimport { cacheClearCommand, cacheListCommand } from \"./commands/cache.js\";\n\nexport function createProgram(): Command {\n const program = new Command();\n program\n .name(COMMAND_NAME)\n .description(\"JH4J Cloud 企业内部标准化项目脚手架\")\n .version(CLI_VERSION);\n\n program\n .command(\"create [name]\")\n .description(\"根据标准模板创建项目\")\n .option(\"-c, --category <category>\", \"项目类型:frontend、backend 或 mobile\")\n .option(\"-t, --template <id>\", \"模板 ID\")\n .option(\"--features <ids>\", \"启用的模板能力,多个 ID 使用逗号分隔\")\n .option(\"--no-standards\", \"不启用模板提供的 Git/代码标准化能力\")\n .option(\"--source <path-or-url>\", \"覆盖模板源(本地目录或 Git URL)\")\n .option(\"--ref <branch-or-tag>\", \"Git 分支或标签;默认使用模板 Catalog 配置\")\n .option(\"--module <name>\", \"平台模块标识\")\n .option(\"--title <title>\", \"系统标题\")\n .option(\"--port <port>\", \"开发端口\")\n .option(\"--npm-registry <url>\", \"npm registry(需包含企业定制包)\")\n .option(\"--jhlc-registry <url>\", \"@jhlc 私有 registry\")\n .option(\"--local-backend <url>\", \"本地后端地址\")\n .option(\"--local-public <url>\", \"本地 public 地址\")\n .option(\"--config <json-file>\", \"从 JSON 文件读取创建参数\")\n .option(\"-y, --yes\", \"接受模板默认值,非交互创建\")\n .option(\"--dry-run\", \"只预览,不写入文件\")\n .option(\"--install\", \"创建完成后安装依赖(默认不安装)\")\n .option(\"--skip-install\", \"不安装依赖(兼容旧命令)\")\n .option(\"--skip-git\", \"跳过 Git 初始化\")\n .option(\"--force\", \"覆盖已存在的同名目录\")\n .option(\"--no-cache\", \"不使用已有远程模板缓存\")\n .action(createCommand);\n\n program\n .command(\"list\")\n .description(\"列出可用模板\")\n .option(\"--json\", \"输出 JSON\")\n .action(listCommand);\n program\n .command(\"doctor\")\n .description(\"检查本机环境和模板可用性\")\n .option(\"--json\", \"输出 JSON\")\n .action(doctorCommand);\n program\n .command(\"info [path]\")\n .description(\"显示已生成项目的模板与版本信息\")\n .option(\"--json\", \"输出 JSON\")\n .action(infoCommand);\n\n const template = program.command(\"template\").description(\"模板维护命令\");\n template\n .command(\"validate [path]\")\n .description(\"校验模板 manifest 与模板契约\")\n .action(async (templatePath?: string) => {\n if (templatePath) return validateTemplateCommand(templatePath);\n const config = await loadUserConfig();\n const selected = findTemplate(await loadCatalog(config));\n const acquired = await acquireTemplateFromSources(\n resolveTemplateSources(selected, undefined, config.templateSource),\n config.templateRef ?? selected.defaultRef,\n { cacheTtlMinutes: config.cacheTtlMinutes }\n );\n try {\n return await validateTemplateCommand(acquired.root);\n } finally {\n await acquired.cleanup();\n }\n });\n\n const config = program.command(\"config\").description(\"管理用户默认配置\");\n config\n .command(\"list\")\n .option(\"--json\", \"输出 JSON\")\n .action(configListCommand);\n config.command(\"get <key>\").action(configGetCommand);\n config.command(\"set <key> <value>\").action(configSetCommand);\n config.command(\"unset <key>\").action(configUnsetCommand);\n config.command(\"reset\").action(configResetCommand);\n\n const cache = program.command(\"cache\").description(\"管理远程模板缓存\");\n cache\n .command(\"list\")\n .option(\"--json\", \"输出 JSON\")\n .action(cacheListCommand);\n cache.command(\"clear\").action(cacheClearCommand);\n\n return program;\n}\n\nexport async function runCli(argv = process.argv): Promise<void> {\n await createProgram().parseAsync(argv);\n}\n","{\n \"name\": \"@agile-team/jh4j-cloud-cli\",\n \"version\": \"0.5.1\",\n \"description\": \"JH4J Cloud 企业内部标准化项目脚手架\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/ChenyCHENYU/jh4j-cloud-cli.git\"\n },\n \"homepage\": \"https://github.com/ChenyCHENYU/jh4j-cloud-cli#readme\",\n \"bugs\": {\n \"url\": \"https://github.com/ChenyCHENYU/jh4j-cloud-cli/issues\"\n },\n \"type\": \"module\",\n \"engines\": {\n \"node\": \"^22.12.0 || ^24.0.0\",\n \"pnpm\": \">=11.8.0\"\n },\n \"packageManager\": \"pnpm@11.8.0\",\n \"bin\": {\n \"jh4j\": \"bin/jh4j.js\"\n },\n \"files\": [\n \"bin\",\n \"dist\",\n \"README.md\",\n \"CHANGELOG.md\",\n \"catalog.schema.json\"\n ],\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"tsup --watch\",\n \"typecheck\": \"tsc --noEmit\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"start\": \"node bin/jh4j.js\",\n \"check\": \"pnpm typecheck && pnpm test && pnpm build\",\n \"prepack\": \"pnpm check\"\n },\n \"dependencies\": {\n \"@clack/prompts\": \"^1.7.0\",\n \"commander\": \"^15.0.0\",\n \"semver\": \"^7.8.5\",\n \"tar\": \"^7.5.19\"\n },\n \"publishConfig\": {\n \"access\": \"public\",\n \"registry\": \"https://registry.npmjs.org/\"\n },\n \"devDependencies\": {\n \"@types/node\": \"^24.13.3\",\n \"@types/semver\": \"7.7.1\",\n \"tsup\": \"8.5.1\",\n \"typescript\": \"7.0.2\",\n \"vitest\": \"4.1.10\"\n }\n}\n","import packageJson from \"../package.json\" with { type: \"json\" };\n\nexport const CLI_NAME = \"@agile-team/jh4j-cloud-cli\";\nexport const CLI_VERSION = packageJson.version;\nexport const COMMAND_NAME = \"jh4j\";\nexport const SUPPORTED_NODE_MAJORS = new Set([22, 24]);\nexport const TEMPLATE_SOURCE_ENV = \"JH4J_UI_TEMPLATE_SOURCE\";\nexport const JH4J_HOME_ENV = \"JH4J_HOME\";\nexport const CATALOG_FILE_ENV = \"JH4J_CATALOG_FILE\";\nexport const USER_CONFIG_SCHEMA_VERSION = 1;\n","import { fileURLToPath } from \"node:url\";\nimport path from \"node:path\";\nimport { existsSync } from \"node:fs\";\nimport { CATALOG_FILE_ENV, TEMPLATE_SOURCE_ENV } from \"./constants.js\";\nimport { readJson } from \"./utils/fs.js\";\nimport type { CatalogFile, CatalogTemplate, UserConfig } from \"./types.js\";\n\nconst siblingTemplatePath = fileURLToPath(\n new URL(\"../../jh4j-ui-template/\", import.meta.url)\n);\nconst siblingMobileTemplatePath = fileURLToPath(\n new URL(\"../../../Robot_H5/\", import.meta.url)\n);\nconst remoteTemplateSources = [\n \"https://github.com/ChenyCHENYU/jh4j-ui-template.git\",\n \"https://gitee.com/ycyplus163/jh4j-ui-template.git\"\n];\nconst remoteMobileTemplateSources = [\n \"https://github.com/ChenyCHENYU/Robot_H5.git\",\n \"https://gitee.com/ycyplus163/robot_-h5.git\"\n];\n\nexport const BUILTIN_TEMPLATES: CatalogTemplate[] = [\n {\n id: \"web.jh4j-mf-remote\",\n name: \"JH4J PC 微前端业务模板\",\n description: \"Vue 3 + Vite + Module Federation 标准业务子系统\",\n category: \"frontend\",\n sourceEnvironment: TEMPLATE_SOURCE_ENV,\n defaultSource: existsSync(siblingTemplatePath)\n ? siblingTemplatePath\n : remoteTemplateSources[0],\n sources: remoteTemplateSources,\n defaultRef: \"main\",\n status: \"beta\",\n tags: [\"vue\", \"vite\", \"module-federation\", \"pc\"]\n },\n {\n id: \"mobile.robot-h5\",\n name: \"JH4J 移动端 H5 模板\",\n description: \"Vue 3 + Vite 7 + Vant 4 企业级移动端 H5 应用\",\n category: \"mobile\",\n sourceEnvironment: TEMPLATE_SOURCE_ENV,\n defaultSource: existsSync(siblingMobileTemplatePath)\n ? siblingMobileTemplatePath\n : remoteMobileTemplateSources[0],\n sources: remoteMobileTemplateSources,\n defaultRef: \"v1.6.0\",\n status: \"beta\",\n tags: [\"vue\", \"vite\", \"vant\", \"h5\", \"mobile\"]\n }\n];\n\nfunction validateCatalogTemplate(template: CatalogTemplate): void {\n if (!template.id || !template.name || !template.category) {\n throw new Error(\"Catalog 模板缺少 id、name 或 category\");\n }\n if (!new Set([\"frontend\", \"backend\", \"mobile\"]).has(template.category)) {\n throw new Error(`Catalog 模板 ${template.id} 的 category 无效`);\n }\n if (!new Set([\"stable\", \"beta\"]).has(template.status)) {\n throw new Error(`Catalog 模板 ${template.id} 的 status 无效`);\n }\n if (!template.defaultRef) {\n throw new Error(`Catalog 模板 ${template.id} 缺少 defaultRef`);\n }\n if (!template.defaultSource && !template.sourceEnvironment) {\n throw new Error(`Catalog 模板 ${template.id} 没有可解析的模板源`);\n }\n if (template.sources?.some((source) => !source.trim())) {\n throw new Error(`Catalog 模板 ${template.id} 包含空的备用源`);\n }\n}\n\nfunction resolveCatalogSource(source: string, catalogDirectory: string): string {\n const isRemote =\n /^(?:https?|ssh|file):\\/\\//.test(source) || source.startsWith(\"git@\");\n return isRemote || path.isAbsolute(source)\n ? source\n : path.resolve(catalogDirectory, source);\n}\n\nexport async function loadCatalog(config?: UserConfig): Promise<CatalogTemplate[]> {\n const configuredFile = process.env[CATALOG_FILE_ENV] || config?.catalogFile;\n if (!configuredFile) return [...BUILTIN_TEMPLATES];\n\n const catalogPath = path.resolve(configuredFile);\n if (!existsSync(catalogPath)) {\n throw new Error(`Catalog 文件不存在: ${catalogPath}`);\n }\n const external = await readJson<CatalogFile>(catalogPath);\n if (external.schemaVersion !== 1 || !Array.isArray(external.templates)) {\n throw new Error(`Catalog 文件格式无效: ${catalogPath}`);\n }\n const catalogDirectory = path.dirname(catalogPath);\n external.templates = external.templates.map((template) => {\n return {\n ...template,\n defaultSource: resolveCatalogSource(\n template.defaultSource,\n catalogDirectory\n ),\n sources: template.sources?.map((source) =>\n resolveCatalogSource(source, catalogDirectory)\n )\n };\n });\n external.templates.forEach(validateCatalogTemplate);\n\n const merged = new Map(BUILTIN_TEMPLATES.map((item) => [item.id, item]));\n external.templates.forEach((item) => merged.set(item.id, item));\n return [...merged.values()];\n}\n\nexport function findTemplate(\n catalog: CatalogTemplate[],\n id?: string\n): CatalogTemplate {\n const selected = id ?? catalog[0]?.id;\n const template = catalog.find((item) => item.id === selected);\n if (!template) {\n throw new Error(\n `模板不存在: ${selected}。可用模板: ${catalog.map((item) => item.id).join(\", \")}`\n );\n }\n return template;\n}\n","import { cp, mkdir, readFile, rm, stat, writeFile } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport path from \"node:path\";\n\nconst EXCLUDED_TEMPLATE_PATHS = new Set([\n \".git\",\n \".jhlc\",\n \"dist\",\n \"node_modules\"\n]);\n\nexport async function readJson<T>(file: string): Promise<T> {\n return JSON.parse(await readFile(file, \"utf8\")) as T;\n}\n\nexport async function writeJson(file: string, value: unknown): Promise<void> {\n await mkdir(path.dirname(file), { recursive: true });\n await writeFile(file, `${JSON.stringify(value, null, 2)}\\n`, \"utf8\");\n}\n\nexport async function isDirectory(directory: string): Promise<boolean> {\n try {\n return (await stat(directory)).isDirectory();\n } catch {\n return false;\n }\n}\n\nexport async function isDirectoryEmpty(directory: string): Promise<boolean> {\n if (!existsSync(directory)) return true;\n const { readdir } = await import(\"node:fs/promises\");\n return (await readdir(directory)).length === 0;\n}\n\nexport async function copyTemplateTree(\n sourceRoot: string,\n targetRoot: string\n): Promise<void> {\n await mkdir(targetRoot, { recursive: true });\n await cp(sourceRoot, targetRoot, {\n recursive: true,\n force: true,\n filter(source) {\n const relative = path.relative(sourceRoot, source);\n if (!relative) return true;\n const [topLevel] = relative.split(path.sep);\n return !EXCLUDED_TEMPLATE_PATHS.has(topLevel);\n }\n });\n}\n\nexport async function removePath(target: string): Promise<void> {\n await rm(target, { recursive: true, force: true, maxRetries: 3 });\n}\n","import path from \"node:path\";\nimport { existsSync } from \"node:fs\";\nimport { mkdir, readdir, rename, rm, writeFile } from \"node:fs/promises\";\nimport { x as extractTar } from \"tar\";\nimport type { CatalogTemplate } from \"../types.js\";\nimport { isDirectory } from \"../utils/fs.js\";\nimport { runCommand } from \"../utils/process.js\";\nimport {\n createTemplateCacheStaging,\n isTemplateCacheFresh,\n readTemplateCacheEntry\n} from \"./template-cache.js\";\n\nconst MAX_ARCHIVE_BYTES = 200 * 1024 * 1024;\n\nexport interface AcquiredTemplate {\n root: string;\n source: string;\n cleanup(): Promise<void>;\n}\n\nexport function resolveTemplateSource(\n template: CatalogTemplate,\n override?: string,\n configuredSource?: string\n): string {\n return resolveTemplateSources(template, override, configuredSource)[0];\n}\n\nexport function resolveTemplateSources(\n template: CatalogTemplate,\n override?: string,\n configuredSource?: string\n): string[] {\n const exclusiveSource =\n override ||\n (template.sourceEnvironment\n ? process.env[template.sourceEnvironment]\n : undefined) ||\n configuredSource;\n if (exclusiveSource) return [exclusiveSource];\n return [...new Set([template.defaultSource, ...(template.sources ?? [])])];\n}\n\nfunction isGitSource(source: string): boolean {\n return (\n source.startsWith(\"git@\") ||\n source.startsWith(\"ssh://\") ||\n source.startsWith(\"file://\") ||\n source.startsWith(\"http://\") ||\n source.startsWith(\"https://\") ||\n source.endsWith(\".git\")\n );\n}\n\nfunction isArchiveSource(source: string): boolean {\n const pathname = source.split(/[?#]/, 1)[0].toLowerCase();\n return pathname.endsWith(\".tgz\") || pathname.endsWith(\".tar.gz\") || pathname.endsWith(\".tar\");\n}\n\nasync function getFreshCache(\n source: string,\n ref: string,\n options: { noCache?: boolean; cacheTtlMinutes?: number }\n): Promise<AcquiredTemplate | null> {\n const cacheEntry = await readTemplateCacheEntry(source, ref);\n if (\n !options.noCache &&\n cacheEntry &&\n isTemplateCacheFresh(cacheEntry, options.cacheTtlMinutes ?? 60)\n ) {\n return {\n root: cacheEntry.root,\n source: `${source}#${ref} (cache)`,\n async cleanup() {}\n };\n }\n return null;\n}\n\nasync function normalizeExtractedTemplate(\n stagingRoot: string,\n templateRoot: string\n): Promise<void> {\n if (existsSync(path.join(templateRoot, \"template.manifest.json\"))) return;\n const children = await readdir(templateRoot, { withFileTypes: true });\n const candidates = children.filter(\n (entry) =>\n entry.isDirectory() &&\n existsSync(path.join(templateRoot, entry.name, \"template.manifest.json\"))\n );\n if (candidates.length !== 1) {\n throw new Error(\"压缩包根目录或唯一一级目录中未找到 template.manifest.json\");\n }\n const normalizedRoot = path.join(stagingRoot, \".normalized-template\");\n await rename(path.join(templateRoot, candidates[0].name), normalizedRoot);\n await rm(templateRoot, { recursive: true, force: true });\n await rename(normalizedRoot, templateRoot);\n}\n\nasync function acquireArchiveTemplate(\n source: string,\n ref: string,\n options: { noCache?: boolean; cacheTtlMinutes?: number }\n): Promise<AcquiredTemplate> {\n const cached = await getFreshCache(source, ref, options);\n if (cached) return cached;\n\n const cacheStaging = await createTemplateCacheStaging(source, ref);\n const archiveFile = path.join(cacheStaging.stagingRoot, \"template.tgz\");\n try {\n if (source.startsWith(\"http://\") || source.startsWith(\"https://\")) {\n const response = await fetch(source, { signal: AbortSignal.timeout(60_000) });\n if (!response.ok) {\n throw new Error(`模板压缩包下载失败: HTTP ${response.status}`);\n }\n const declaredLength = Number(response.headers.get(\"content-length\") || 0);\n if (declaredLength > MAX_ARCHIVE_BYTES) {\n throw new Error(\"模板压缩包超过 200 MB 限制\");\n }\n const archiveBuffer = Buffer.from(await response.arrayBuffer());\n if (archiveBuffer.byteLength > MAX_ARCHIVE_BYTES) {\n throw new Error(\"模板压缩包超过 200 MB 限制\");\n }\n await writeFile(archiveFile, archiveBuffer);\n } else {\n const { copyFile } = await import(\"node:fs/promises\");\n await copyFile(path.resolve(source), archiveFile);\n }\n await mkdir(cacheStaging.templateRoot, { recursive: true });\n await extractTar({ file: archiveFile, cwd: cacheStaging.templateRoot });\n await normalizeExtractedTemplate(\n cacheStaging.stagingRoot,\n cacheStaging.templateRoot\n );\n await rm(archiveFile, { force: true });\n await cacheStaging.commit();\n return {\n root: path.join(cacheStaging.entryRoot, \"template\"),\n source: `${source} (archive)`,\n async cleanup() {}\n };\n } catch (error) {\n await cacheStaging.cleanup();\n throw error;\n }\n}\n\nexport async function acquireTemplate(\n source: string,\n ref: string,\n options: { noCache?: boolean; cacheTtlMinutes?: number } = {}\n): Promise<AcquiredTemplate> {\n const localPath = path.resolve(source);\n if (existsSync(localPath)) {\n if (await isDirectory(localPath)) {\n return {\n root: localPath,\n source: localPath,\n async cleanup() {}\n };\n }\n if (isArchiveSource(localPath)) {\n return acquireArchiveTemplate(localPath, ref, options);\n }\n throw new Error(`模板源不是目录或支持的 tar 压缩包: ${localPath}`);\n }\n\n if (isArchiveSource(source)) {\n return acquireArchiveTemplate(source, ref, options);\n }\n\n if (!isGitSource(source)) {\n throw new Error(`模板源不存在: ${source}`);\n }\n\n const cached = await getFreshCache(source, ref, options);\n if (cached) return cached;\n\n const cacheStaging = await createTemplateCacheStaging(source, ref);\n try {\n await runCommand(\n \"git\",\n [\n \"-c\",\n \"http.lowSpeedLimit=1024\",\n \"-c\",\n \"http.lowSpeedTime=15\",\n \"clone\",\n \"--depth\",\n \"1\",\n \"--branch\",\n ref,\n source,\n cacheStaging.templateRoot\n ],\n { stdio: \"pipe\", env: { GIT_TERMINAL_PROMPT: \"0\" } }\n );\n await cacheStaging.commit();\n return {\n root: path.join(cacheStaging.entryRoot, \"template\"),\n source: `${source}#${ref}`,\n async cleanup() {}\n };\n } catch (error) {\n await cacheStaging.cleanup();\n throw error;\n }\n}\n\nexport async function acquireTemplateFromSources(\n sources: string[],\n ref: string,\n options: { noCache?: boolean; cacheTtlMinutes?: number } = {}\n): Promise<AcquiredTemplate> {\n if (!sources.length) throw new Error(\"没有可用的模板源\");\n const failures: string[] = [];\n for (const source of [...new Set(sources)]) {\n try {\n return await acquireTemplate(source, ref, options);\n } catch (error) {\n failures.push(`${source}: ${(error as Error).message}`);\n }\n }\n throw new Error(`所有模板源均不可用:\\n- ${failures.join(\"\\n- \")}`);\n}\n","import { spawn } from \"node:child_process\";\n\nexport interface RunCommandOptions {\n cwd?: string;\n stdio?: \"inherit\" | \"pipe\";\n env?: NodeJS.ProcessEnv;\n}\n\nexport function platformCommand(command: string): string {\n if (process.platform !== \"win32\") return command;\n return command === \"pnpm\" || command === \"npm\" || command === \"npx\"\n ? `${command}.cmd`\n : command;\n}\n\nexport async function runCommand(\n command: string,\n args: string[],\n options: RunCommandOptions = {}\n): Promise<string> {\n const stdio = options.stdio ?? \"inherit\";\n return new Promise((resolve, reject) => {\n const executable = platformCommand(command);\n const isWindowsCommand =\n process.platform === \"win32\" && executable.endsWith(\".cmd\");\n const spawnExecutable = isWindowsCommand\n ? process.env.ComSpec || \"cmd.exe\"\n : executable;\n const spawnArgs = isWindowsCommand\n ? [\"/d\", \"/s\", \"/c\", executable, ...args]\n : args;\n const child = spawn(spawnExecutable, spawnArgs, {\n cwd: options.cwd,\n stdio,\n env: { ...process.env, ...options.env },\n windowsHide: true\n });\n\n let output = \"\";\n if (stdio === \"pipe\") {\n child.stdout?.on(\"data\", (chunk) => {\n output += chunk.toString();\n });\n child.stderr?.on(\"data\", (chunk) => {\n output += chunk.toString();\n });\n }\n\n child.on(\"error\", reject);\n child.on(\"exit\", (code) => {\n if (code === 0) {\n resolve(output.trim());\n return;\n }\n reject(\n new Error(\n `${command} ${args.join(\" \")} 执行失败(exit ${code ?? \"unknown\"})${output ? `\\n${output.trim()}` : \"\"}`\n )\n );\n });\n });\n}\n\nexport async function inspectCommand(\n command: string,\n args: string[] = [\"--version\"]\n): Promise<{ ok: boolean; output: string }> {\n try {\n return { ok: true, output: await runCommand(command, args, { stdio: \"pipe\" }) };\n } catch (error) {\n return { ok: false, output: (error as Error).message };\n }\n}\n","import { createHash } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport { mkdir, readdir, rename, stat } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { getJh4jHome } from \"./user-config.js\";\nimport { readJson, removePath, writeJson } from \"../utils/fs.js\";\nimport type { TemplateCacheMetadata } from \"../types.js\";\n\nconst CACHE_SCHEMA_VERSION = 1;\n\nexport interface TemplateCacheEntry {\n key: string;\n root: string;\n metadata: TemplateCacheMetadata;\n sizeBytes: number;\n}\n\nexport function getTemplateCacheRoot(): string {\n return path.join(getJh4jHome(), \"cache\", \"templates\");\n}\n\nexport function getTemplateCacheKey(source: string, ref: string): string {\n return createHash(\"sha256\").update(`${source}\\0${ref}`).digest(\"hex\").slice(0, 20);\n}\n\nfunction getEntryPaths(key: string) {\n const entryRoot = path.join(getTemplateCacheRoot(), key);\n return {\n entryRoot,\n templateRoot: path.join(entryRoot, \"template\"),\n metadataPath: path.join(entryRoot, \"metadata.json\")\n };\n}\n\nexport async function readTemplateCacheEntry(\n source: string,\n ref: string\n): Promise<TemplateCacheEntry | null> {\n const key = getTemplateCacheKey(source, ref);\n const paths = getEntryPaths(key);\n if (!existsSync(paths.templateRoot) || !existsSync(paths.metadataPath)) return null;\n try {\n const metadata = await readJson<TemplateCacheMetadata>(paths.metadataPath);\n if (\n metadata.schemaVersion !== CACHE_SCHEMA_VERSION ||\n metadata.source !== source ||\n metadata.ref !== ref\n ) {\n return null;\n }\n return {\n key,\n root: paths.templateRoot,\n metadata,\n sizeBytes: await calculateDirectorySize(paths.entryRoot)\n };\n } catch {\n return null;\n }\n}\n\nexport function isTemplateCacheFresh(\n entry: TemplateCacheEntry,\n ttlMinutes: number\n): boolean {\n if (ttlMinutes <= 0) return false;\n const cachedAt = Date.parse(entry.metadata.cachedAt);\n return Number.isFinite(cachedAt) && Date.now() - cachedAt < ttlMinutes * 60_000;\n}\n\nexport async function createTemplateCacheStaging(\n source: string,\n ref: string\n): Promise<{\n key: string;\n entryRoot: string;\n stagingRoot: string;\n templateRoot: string;\n commit(): Promise<void>;\n cleanup(): Promise<void>;\n}> {\n const key = getTemplateCacheKey(source, ref);\n const cacheRoot = getTemplateCacheRoot();\n await mkdir(cacheRoot, { recursive: true });\n const stagingRoot = path.join(\n cacheRoot,\n `.${key}.tmp-${process.pid}-${Date.now()}`\n );\n const templateRoot = path.join(stagingRoot, \"template\");\n const entryRoot = path.join(cacheRoot, key);\n await mkdir(stagingRoot, { recursive: true });\n\n return {\n key,\n entryRoot,\n stagingRoot,\n templateRoot,\n async commit() {\n await writeJson(path.join(stagingRoot, \"metadata.json\"), {\n schemaVersion: CACHE_SCHEMA_VERSION,\n source,\n ref,\n cachedAt: new Date().toISOString()\n } satisfies TemplateCacheMetadata);\n await removePath(entryRoot);\n await rename(stagingRoot, entryRoot);\n },\n cleanup: () => removePath(stagingRoot)\n };\n}\n\nasync function calculateDirectorySize(directory: string): Promise<number> {\n let total = 0;\n const entries = await readdir(directory, { withFileTypes: true });\n for (const entry of entries) {\n const absolute = path.join(directory, entry.name);\n if (entry.isDirectory()) total += await calculateDirectorySize(absolute);\n else if (entry.isFile()) total += (await stat(absolute)).size;\n }\n return total;\n}\n\nexport async function listTemplateCache(): Promise<TemplateCacheEntry[]> {\n const cacheRoot = getTemplateCacheRoot();\n if (!existsSync(cacheRoot)) return [];\n const entries: TemplateCacheEntry[] = [];\n for (const directory of await readdir(cacheRoot, { withFileTypes: true })) {\n if (!directory.isDirectory() || directory.name.startsWith(\".\")) continue;\n const paths = getEntryPaths(directory.name);\n if (!existsSync(paths.metadataPath) || !existsSync(paths.templateRoot)) continue;\n try {\n entries.push({\n key: directory.name,\n root: paths.templateRoot,\n metadata: await readJson<TemplateCacheMetadata>(paths.metadataPath),\n sizeBytes: await calculateDirectorySize(paths.entryRoot)\n });\n } catch {\n // 损坏条目由 clear 或下一次拉取覆盖。\n }\n }\n return entries.sort((a, b) =>\n b.metadata.cachedAt.localeCompare(a.metadata.cachedAt)\n );\n}\n\nexport async function clearTemplateCache(): Promise<void> {\n await removePath(getTemplateCacheRoot());\n}\n","import os from \"node:os\";\nimport path from \"node:path\";\nimport { existsSync } from \"node:fs\";\nimport { JH4J_HOME_ENV, USER_CONFIG_SCHEMA_VERSION } from \"../constants.js\";\nimport { readJson, writeJson } from \"../utils/fs.js\";\nimport type { UserConfig } from \"../types.js\";\n\nexport const DEFAULT_USER_CONFIG: UserConfig = {\n schemaVersion: USER_CONFIG_SCHEMA_VERSION,\n autoInstall: false,\n autoGit: true,\n cacheTtlMinutes: 60\n};\n\nexport function getJh4jHome(): string {\n return path.resolve(process.env[JH4J_HOME_ENV] || path.join(os.homedir(), \".jh4j\"));\n}\n\nexport function getUserConfigPath(): string {\n return path.join(getJh4jHome(), \"config.json\");\n}\n\nexport async function loadUserConfig(): Promise<UserConfig> {\n const configPath = getUserConfigPath();\n if (!existsSync(configPath)) return { ...DEFAULT_USER_CONFIG };\n\n const stored = await readJson<Partial<UserConfig>>(configPath);\n if (\n stored.schemaVersion !== undefined &&\n stored.schemaVersion !== USER_CONFIG_SCHEMA_VERSION\n ) {\n throw new Error(\n `不支持的用户配置版本: ${stored.schemaVersion},当前要求 ${USER_CONFIG_SCHEMA_VERSION}`\n );\n }\n return { ...DEFAULT_USER_CONFIG, ...stored };\n}\n\nexport async function saveUserConfig(config: UserConfig): Promise<void> {\n await writeJson(getUserConfigPath(), {\n ...config,\n schemaVersion: USER_CONFIG_SCHEMA_VERSION\n });\n}\n\nconst CONFIG_KEYS = new Set<keyof UserConfig>([\n \"catalogFile\",\n \"templateSource\",\n \"templateRef\",\n \"npmRegistry\",\n \"jhlcRegistry\",\n \"autoInstall\",\n \"autoGit\",\n \"cacheTtlMinutes\"\n]);\n\nexport function parseUserConfigValue(\n key: string,\n rawValue: string\n): [keyof UserConfig, UserConfig[keyof UserConfig]] {\n if (!CONFIG_KEYS.has(key as keyof UserConfig)) {\n throw new Error(`不支持的配置项: ${key}`);\n }\n const typedKey = key as keyof UserConfig;\n if (typedKey === \"autoInstall\" || typedKey === \"autoGit\") {\n const normalized = rawValue.toLowerCase();\n if (!new Set([\"true\", \"false\"]).has(normalized)) {\n throw new Error(`${key} 只能是 true 或 false`);\n }\n return [typedKey, normalized === \"true\"];\n }\n if (typedKey === \"cacheTtlMinutes\") {\n const value = Number(rawValue);\n if (!Number.isInteger(value) || value < 0 || value > 10080) {\n throw new Error(\"cacheTtlMinutes 必须是 0 到 10080 之间的整数\");\n }\n return [typedKey, value];\n }\n return [typedKey, rawValue.trim()];\n}\n","import * as prompts from \"@clack/prompts\";\nimport { findTemplate, loadCatalog } from \"../catalog.js\";\nimport {\n generateProject,\n normalizeProjectName\n} from \"../core/project-generator.js\";\nimport { loadUserConfig } from \"../core/user-config.js\";\nimport type {\n CatalogTemplate,\n CreateOptions,\n TemplateCategory\n} from \"../types.js\";\n\nconst CATEGORY_OPTIONS: Array<{\n value: TemplateCategory;\n label: string;\n}> = [\n { value: \"frontend\", label: \"PC 前端 · Vue 3 / 微前端\" },\n { value: \"backend\", label: \"后端服务 · Java / 云原生\" },\n { value: \"mobile\", label: \"移动端 H5 · Vue 3 / Vant\" }\n];\n\nfunction isCategory(value: string): value is TemplateCategory {\n return CATEGORY_OPTIONS.some((item) => item.value === value);\n}\n\nexport function templatesByCategory(\n templates: CatalogTemplate[],\n category: TemplateCategory\n): CatalogTemplate[] {\n return templates.filter((template) => template.category === category);\n}\n\nexport function categoryOptionsFor(\n templates: CatalogTemplate[]\n): Array<{ value: TemplateCategory; label: string }> {\n return CATEGORY_OPTIONS.filter(\n (item) => templatesByCategory(templates, item.value).length > 0\n ).map(({ value, label }) => ({ value, label }));\n}\n\nexport function defaultProjectNameFor(category: TemplateCategory): string {\n if (category === \"mobile\") return \"jh4j-mobile-app\";\n if (category === \"backend\") return \"jh4j-service-app\";\n return \"jh4j-ui-app\";\n}\n\nexport function projectNamePromptOptions(\n category: TemplateCategory\n): Parameters<typeof prompts.text>[0] {\n const defaultProjectName = defaultProjectNameFor(category);\n return {\n message: \"项目名称\",\n initialValue: defaultProjectName,\n defaultValue: defaultProjectName,\n validate(value) {\n return !value || normalizeProjectName(value)\n ? undefined\n : \"请输入至少一个字母或数字,例如 jh4j-mobile-app\";\n }\n };\n}\n\nasync function selectCategory(\n templates: CatalogTemplate[],\n requestedCategory: string | undefined,\n nonInteractive: boolean\n): Promise<TemplateCategory> {\n if (requestedCategory) {\n if (!isCategory(requestedCategory)) {\n throw new Error(\n `项目类型无效: ${requestedCategory}。可用值: frontend、backend、mobile`\n );\n }\n if (!templatesByCategory(templates, requestedCategory).length) {\n throw new Error(`项目类型 ${requestedCategory} 暂无可用模板`);\n }\n return requestedCategory;\n }\n\n const firstAvailable = CATEGORY_OPTIONS.find(\n (item) => templatesByCategory(templates, item.value).length > 0\n );\n if (!firstAvailable) throw new Error(\"Catalog 中没有可用模板\");\n if (nonInteractive) return firstAvailable.value;\n\n const availableOptions = categoryOptionsFor(templates);\n if (availableOptions.length === 1) return availableOptions[0].value;\n\n const selected = await prompts.select({\n message: \"选择项目类型\",\n options: availableOptions.map((item) => ({\n value: item.value,\n label: item.label\n }))\n });\n if (prompts.isCancel(selected)) throw new Error(\"用户取消创建\");\n return selected as TemplateCategory;\n}\n\nasync function selectTemplate(\n templates: CatalogTemplate[],\n options: CreateOptions\n): Promise<CatalogTemplate> {\n if (options.template) {\n const selected = findTemplate(templates, options.template);\n if (options.category && selected.category !== options.category) {\n throw new Error(\n `模板 ${selected.id} 属于 ${selected.category},与 --category ${options.category} 不一致`\n );\n }\n return selected;\n }\n\n const category = await selectCategory(\n templates,\n options.category,\n Boolean(options.yes)\n );\n const candidates = templatesByCategory(templates, category);\n if (options.yes) return findTemplate(candidates);\n if (candidates.length === 1) {\n const selected = candidates[0];\n prompts.log.info(`使用模板:${selected.name}`);\n return selected;\n }\n\n const selected = await prompts.select({\n message: \"选择项目模板\",\n options: candidates.map((template) => ({\n value: template.id,\n label: `${template.name} · ${template.description}`\n }))\n });\n if (prompts.isCancel(selected)) throw new Error(\"用户取消创建\");\n return findTemplate(candidates, String(selected));\n}\n\nexport async function createCommand(\n requestedName: string | undefined,\n options: CreateOptions\n): Promise<void> {\n prompts.intro(\"JH4J Cloud 项目创建\");\n const userConfig = await loadUserConfig();\n const catalog = await loadCatalog(userConfig);\n const template = await selectTemplate(catalog, options);\n\n const defaultProjectName = defaultProjectNameFor(template.category);\n let rawProjectName = requestedName;\n if (!rawProjectName && !options.yes) {\n const answer = await prompts.text(\n projectNamePromptOptions(template.category)\n );\n if (prompts.isCancel(answer)) throw new Error(\"用户取消创建\");\n rawProjectName = String(answer).trim() || defaultProjectName;\n }\n rawProjectName ??= defaultProjectName;\n let projectName = rawProjectName;\n projectName = normalizeProjectName(rawProjectName);\n if (!projectName) {\n throw new Error(\"项目名称至少需要包含一个字母或数字\");\n }\n if (projectName !== rawProjectName) {\n prompts.log.info(`项目名称已规范化:${projectName}`);\n }\n prompts.log.info(\"其余配置使用模板默认值,生成后可在项目内修改\");\n\n const result = await generateProject(\n template,\n projectName,\n options,\n process.cwd(),\n userConfig\n );\n if (options.dryRun) {\n prompts.outro(\"Dry Run 完成,未写入任何项目文件\");\n return;\n }\n\n prompts.log.success(\n `已创建 ${projectName}(${result.templateId}@${result.templateVersion})`\n );\n prompts.outro(\n [\n `cd ${projectName}`,\n ...(!result.installed ? [\"pnpm install\"] : []),\n \"pnpm dev\",\n \"\",\n \"配置:project.config.json / .npmrc / .env*\"\n ].join(\"\\n\")\n );\n}\n","import { existsSync } from \"node:fs\";\nimport { rename, rm } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport * as prompts from \"@clack/prompts\";\nimport { satisfies } from \"semver\";\nimport { CLI_NAME, CLI_VERSION } from \"../constants.js\";\nimport {\n copyTemplateTree,\n isDirectoryEmpty,\n readJson,\n removePath,\n writeJson\n} from \"../utils/fs.js\";\nimport { runCommand } from \"../utils/process.js\";\nimport {\n acquireTemplateFromSources,\n resolveTemplateSources\n} from \"./template-source.js\";\nimport { loadTemplateManifest } from \"./template-manifest.js\";\nimport { DEFAULT_USER_CONFIG } from \"./user-config.js\";\nimport type {\n CatalogTemplate,\n CreateOptions,\n ProjectInput,\n TemplateManifest,\n UserConfig\n} from \"../types.js\";\n\nconst ENV_NAMES = [\"dev\", \"sit\", \"uat\", \"pre\", \"prd\"] as const;\ntype PartialProjectInput = Partial<Omit<ProjectInput, \"environments\">> & {\n environments?: Partial<ProjectInput[\"environments\"]>;\n};\n\nexport function normalizeProjectName(value: string): string {\n return value\n .trim()\n .toLowerCase()\n .replace(/\\s+/g, \"-\")\n .replace(/^[._-]+/, \"\")\n .replace(/[^a-z0-9._-]+/g, \"-\")\n .replace(/-{2,}/g, \"-\")\n .replace(/[-._]+$/, \"\");\n}\n\nfunction ensureProjectName(value: string): string {\n const name = normalizeProjectName(value);\n if (!/^[a-z0-9][a-z0-9._-]*$/.test(name)) {\n throw new Error(\"项目名称至少需要包含一个字母或数字\");\n }\n return name;\n}\n\nfunction inferModuleName(projectName: string): string {\n const inferred = projectName\n .replace(/^(?:jh4j|wl)-ui-/, \"\")\n .replace(/[^a-z0-9-]/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n return /^[a-z][a-z0-9-]*$/.test(inferred) ? inferred : \"app\";\n}\n\nfunction ensureModuleName(value: string): string {\n const name = value.trim();\n if (!/^[a-z][a-z0-9-]*$/.test(name)) {\n throw new Error(\"模块标识必须以小写字母开头,只能包含小写字母、数字和连字符\");\n }\n return name;\n}\n\nfunction ensurePort(value: string | number): number {\n const port = Number(value);\n if (!Number.isInteger(port) || port < 1024 || port > 65535) {\n throw new Error(\"开发端口必须是 1024 到 65535 之间的整数\");\n }\n return port;\n}\n\nfunction ensureHttpUrl(value: string, label: string): string {\n try {\n const url = new URL(value);\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") throw new Error();\n return value.replace(/\\/+$/, \"\");\n } catch {\n throw new Error(`${label} 必须是 http/https URL`);\n }\n}\n\nasync function loadCreateConfig(\n configFile: string | undefined,\n cwd: string\n): Promise<PartialProjectInput> {\n if (!configFile) return {};\n const resolved = path.resolve(cwd, configFile);\n if (!existsSync(resolved)) throw new Error(`创建配置文件不存在: ${resolved}`);\n return readJson<PartialProjectInput>(resolved);\n}\n\nfunction parseFeatureIds(value: string): string[] {\n return [...new Set(value.split(\",\").map((item) => item.trim()).filter(Boolean))];\n}\n\nasync function collectTemplateFeatures(\n manifest: TemplateManifest,\n fileConfig: PartialProjectInput,\n options: CreateOptions\n): Promise<string[]> {\n const available = manifest.features ?? [];\n if (!available.length) return [];\n\n const knownIds = new Set(available.map((feature) => feature.id));\n let selected = options.features\n ? parseFeatureIds(options.features)\n : Array.isArray(fileConfig.features)\n ? fileConfig.features\n : available\n .filter((feature) => feature.defaultEnabled || feature.required)\n .map((feature) => feature.id);\n\n const unknown = selected.filter((id) => !knownIds.has(id));\n if (unknown.length) {\n throw new Error(\n `模板不支持以下能力: ${unknown.join(\", \")}。可用能力: ${[...knownIds].join(\", \")}`\n );\n }\n\n if (options.standards === false) {\n selected = selected.filter((id) => {\n const feature = available.find((item) => item.id === id);\n return feature?.package !== \"@robot-admin/git-standards\";\n });\n }\n\n for (const feature of available) {\n if (feature.required && !selected.includes(feature.id)) {\n selected.push(feature.id);\n }\n }\n return selected;\n}\n\nasync function collectProjectInput(\n projectName: string,\n sourceConfig: ProjectInput,\n fileConfig: PartialProjectInput,\n options: CreateOptions,\n userConfig: UserConfig,\n features: string[]\n): Promise<ProjectInput> {\n let moduleName = options.module ?? fileConfig.moduleName ?? inferModuleName(projectName);\n let title = options.title ?? fileConfig.title ?? sourceConfig.title;\n let port: string | number =\n options.port ?? fileConfig.devServerPort ?? sourceConfig.devServerPort;\n let npmRegistry =\n options.npmRegistry ??\n fileConfig.npmRegistry ??\n userConfig.npmRegistry ??\n sourceConfig.npmRegistry;\n let jhlcRegistry =\n options.jhlcRegistry ??\n fileConfig.jhlcRegistry ??\n userConfig.jhlcRegistry ??\n sourceConfig.jhlcRegistry;\n let localBackendUrl =\n options.localBackend ?? fileConfig.localBackendUrl ?? sourceConfig.localBackendUrl;\n let localPublicUrl =\n options.localPublic ?? fileConfig.localPublicUrl ?? sourceConfig.localPublicUrl;\n const environments = structuredClone(sourceConfig.environments);\n for (const [env, value] of Object.entries(fileConfig.environments ?? {})) {\n if (value && environments[env]) {\n environments[env] = { ...environments[env], ...value };\n }\n }\n\n if (!title.trim()) throw new Error(\"系统标题不能为空\");\n for (const env of ENV_NAMES) {\n if (!environments[env]) throw new Error(`缺少 ${env.toUpperCase()} 环境配置`);\n environments[env] = {\n webUrl: ensureHttpUrl(environments[env].webUrl, `${env.toUpperCase()} 平台地址`),\n apiPrefix: environments[env].apiPrefix.replace(/^\\/+|\\/+$/g, \"\")\n };\n if (!environments[env].apiPrefix) {\n throw new Error(`${env.toUpperCase()} API 前缀不能为空`);\n }\n }\n\n return {\n projectName,\n moduleName: ensureModuleName(moduleName),\n title: title.trim(),\n devServerPort: ensurePort(port),\n npmRegistry: ensureHttpUrl(npmRegistry, \"npm registry\"),\n jhlcRegistry: ensureHttpUrl(jhlcRegistry, \"@jhlc 私有 registry\"),\n localBackendUrl: ensureHttpUrl(localBackendUrl, \"本地后端地址\"),\n localPublicUrl: ensureHttpUrl(localPublicUrl, \"本地 public 地址\"),\n environments,\n features\n };\n}\n\nfunction assertSafeTarget(cwd: string, target: string): void {\n if (path.dirname(target) !== cwd || target === cwd) {\n throw new Error(\"仅允许在当前目录创建一级项目目录\");\n }\n}\n\nasync function promoteStaging(\n stagingRoot: string,\n targetRoot: string,\n force: boolean\n): Promise<void> {\n const targetExists = existsSync(targetRoot);\n if (!targetExists) {\n await rename(stagingRoot, targetRoot);\n return;\n }\n\n if (!(await isDirectoryEmpty(targetRoot)) && !force) {\n throw new Error(`目标目录已存在且非空: ${targetRoot}`);\n }\n\n const backupRoot = `${targetRoot}.jh4j-backup-${Date.now()}`;\n await rename(targetRoot, backupRoot);\n try {\n await rename(stagingRoot, targetRoot);\n } catch (error) {\n await rename(backupRoot, targetRoot);\n throw error;\n }\n try {\n await removePath(backupRoot);\n } catch {\n prompts.log.warn(`旧目录备份未能自动清理: ${backupRoot}`);\n }\n}\n\nexport interface GenerateProjectResult {\n targetRoot: string;\n templateId: string;\n templateVersion: string;\n source: string;\n features: string[];\n installed: boolean;\n gitInitialized: boolean;\n}\n\nexport async function generateProject(\n catalogTemplate: CatalogTemplate,\n requestedProjectName: string,\n options: CreateOptions,\n cwd = process.cwd(),\n configuredUserConfig: UserConfig = DEFAULT_USER_CONFIG\n): Promise<GenerateProjectResult> {\n const userConfig = { ...DEFAULT_USER_CONFIG, ...configuredUserConfig };\n const projectName = ensureProjectName(requestedProjectName);\n const resolvedCwd = path.resolve(cwd);\n const targetRoot = path.resolve(resolvedCwd, projectName);\n assertSafeTarget(resolvedCwd, targetRoot);\n if (\n existsSync(targetRoot) &&\n !(await isDirectoryEmpty(targetRoot)) &&\n !options.force\n ) {\n throw new Error(`目标目录已存在且非空: ${targetRoot}`);\n }\n\n const ref = options.ref ?? userConfig.templateRef ?? catalogTemplate.defaultRef;\n const sourceValues = resolveTemplateSources(\n catalogTemplate,\n options.source,\n userConfig.templateSource\n );\n const acquisitionSpinner = options.yes\n ? undefined\n : prompts.spinner({ indicator: \"timer\" });\n acquisitionSpinner?.start(\"正在获取并校验模板\");\n let acquired: Awaited<ReturnType<typeof acquireTemplateFromSources>>;\n try {\n acquired = await acquireTemplateFromSources(sourceValues, ref, {\n noCache: options.cache === false,\n cacheTtlMinutes: userConfig.cacheTtlMinutes\n });\n acquisitionSpinner?.stop(\"模板准备完成\");\n } catch (error) {\n acquisitionSpinner?.error(\"模板获取失败\");\n throw error;\n }\n const stagingRoot = path.join(\n resolvedCwd,\n `.${projectName}.jh4j-tmp-${process.pid}-${Date.now()}`\n );\n let promoted = false;\n\n try {\n const manifest = await loadTemplateManifest(acquired.root);\n if (manifest.id !== catalogTemplate.id) {\n throw new Error(\n `模板 ID 不匹配:Catalog=${catalogTemplate.id},Manifest=${manifest.id}`\n );\n }\n if (!satisfies(process.versions.node, manifest.runtime.node)) {\n throw new Error(\n `当前 Node ${process.versions.node} 不满足模板要求 ${manifest.runtime.node}`\n );\n }\n\n const sourceProjectConfig = await readJson<\n Omit<ProjectInput, \"npmRegistry\" | \"jhlcRegistry\">\n >(path.join(acquired.root, \"project.config.json\"));\n const fileConfig = await loadCreateConfig(options.config, resolvedCwd);\n const features = await collectTemplateFeatures(manifest, fileConfig, options);\n const input = await collectProjectInput(\n projectName,\n {\n ...sourceProjectConfig,\n npmRegistry: manifest.defaults.npmRegistry,\n jhlcRegistry: manifest.defaults.jhlcRegistry\n },\n fileConfig,\n options,\n userConfig,\n features\n );\n\n const shouldInstall =\n !options.skipInstall && (options.install === true || userConfig.autoInstall);\n const shouldInitializeGit = !options.skipGit && userConfig.autoGit;\n\n if (options.dryRun) {\n prompts.note(\n [\n `模板: ${manifest.id}@${manifest.version}`,\n `来源: ${acquired.source}`,\n `目标: ${targetRoot}`,\n `模块: ${input.moduleName}`,\n `端口: ${input.devServerPort}`,\n `能力: ${input.features.length ? input.features.join(\", \") : \"无可选能力\"}`,\n `安装依赖: ${shouldInstall ? \"是\" : \"否\"}`,\n `初始化 Git: ${shouldInitializeGit ? \"是\" : \"否\"}`\n ].join(\"\\n\"),\n \"Dry Run\"\n );\n return {\n targetRoot,\n templateId: manifest.id,\n templateVersion: manifest.version,\n source: acquired.source,\n features: input.features,\n installed: false,\n gitInitialized: false\n };\n }\n\n await copyTemplateTree(acquired.root, stagingRoot);\n const inputFile = path.join(stagingRoot, \".jh4j-cli-input.json\");\n await writeJson(inputFile, input);\n try {\n await runCommand(\n process.execPath,\n [\n path.join(stagingRoot, \"scripts\", \"setup-project.mjs\"),\n \"--yes\",\n \"--config\",\n inputFile,\n \"--created-by\",\n `${CLI_NAME}@${CLI_VERSION}`\n ],\n { cwd: stagingRoot, stdio: \"pipe\" }\n );\n } finally {\n await rm(inputFile, { force: true });\n }\n\n if (!existsSync(path.join(stagingRoot, manifest.generatedMetadata))) {\n throw new Error(`模板初始化未生成元数据: ${manifest.generatedMetadata}`);\n }\n await promoteStaging(stagingRoot, targetRoot, Boolean(options.force));\n promoted = true;\n\n let gitInitialized = false;\n if (shouldInitializeGit) {\n await runCommand(\"git\", [\"init\", \"-b\", \"main\"], {\n cwd: targetRoot,\n stdio: \"pipe\"\n });\n gitInitialized = true;\n }\n\n if (shouldInstall) {\n try {\n await runCommand(\"pnpm\", [\"install\"], { cwd: targetRoot });\n } catch (error) {\n throw new Error(\n `项目已生成,但依赖安装失败;目录已保留在 ${targetRoot}\\n${(error as Error).message}`\n );\n }\n }\n\n if (shouldInitializeGit) {\n await runCommand(\"git\", [\"add\", \"-A\"], { cwd: targetRoot, stdio: \"pipe\" });\n try {\n await runCommand(\n \"git\",\n [\"commit\", \"-m\", `feat(init): 基于 ${manifest.id}@${manifest.version} 初始化`],\n {\n cwd: targetRoot,\n stdio: \"pipe\",\n env: { HUSKY: \"0\" }\n }\n );\n } catch (error) {\n prompts.log.warn(`Git 已初始化,但初始提交未完成:${(error as Error).message}`);\n }\n }\n\n return {\n targetRoot,\n templateId: manifest.id,\n templateVersion: manifest.version,\n source: acquired.source,\n features: input.features,\n installed: shouldInstall,\n gitInitialized\n };\n } finally {\n if (!promoted && existsSync(stagingRoot)) await removePath(stagingRoot);\n await acquired.cleanup();\n }\n}\n","import path from \"node:path\";\nimport { readJson } from \"../utils/fs.js\";\nimport type { TemplateManifest } from \"../types.js\";\n\nexport async function loadTemplateManifest(\n templateRoot: string\n): Promise<TemplateManifest> {\n const manifest = await readJson<TemplateManifest>(\n path.join(templateRoot, \"template.manifest.json\")\n );\n const errors: string[] = [];\n\n if (manifest.schemaVersion !== 1) errors.push(\"schemaVersion 必须为 1\");\n if (!manifest.id) errors.push(\"缺少模板 id\");\n if (!manifest.name) errors.push(\"缺少模板名称\");\n if (!/^\\d+\\.\\d+\\.\\d+([+-].+)?$/.test(manifest.version ?? \"\")) {\n errors.push(\"模板 version 不是有效的语义化版本\");\n }\n if (!manifest.runtime?.node || !manifest.runtime?.packageManager) {\n errors.push(\"缺少模板运行时约束\");\n }\n if (!manifest.entry?.nonInteractive) {\n errors.push(\"缺少非交互初始化入口\");\n }\n const featureIds = new Set<string>();\n for (const feature of manifest.features ?? []) {\n if (!/^[a-z][a-z0-9-]*$/.test(feature.id)) {\n errors.push(`模板能力 id 无效: ${feature.id}`);\n }\n if (featureIds.has(feature.id)) {\n errors.push(`模板能力 id 重复: ${feature.id}`);\n }\n featureIds.add(feature.id);\n if (!feature.name || !feature.description) {\n errors.push(`模板能力 ${feature.id} 缺少名称或说明`);\n }\n }\n\n if (errors.length) {\n throw new Error(`模板 manifest 无效:\\n- ${errors.join(\"\\n- \")}`);\n }\n return manifest;\n}\n","import { existsSync } from \"node:fs\";\nimport { mkdir, writeFile, rm } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { coerce, gte, satisfies } from \"semver\";\nimport { loadCatalog } from \"../catalog.js\";\nimport { loadTemplateManifest } from \"../core/template-manifest.js\";\nimport { resolveTemplateSources } from \"../core/template-source.js\";\nimport { getJh4jHome, loadUserConfig } from \"../core/user-config.js\";\nimport { inspectCommand } from \"../utils/process.js\";\nimport type { CatalogTemplate, UserConfig } from \"../types.js\";\n\nexport interface CheckResult {\n name: string;\n ok: boolean;\n detail: string;\n}\n\nasync function checkHomeWritable(): Promise<CheckResult> {\n const home = getJh4jHome();\n const probe = path.join(home, `.write-probe-${process.pid}`);\n try {\n await mkdir(home, { recursive: true });\n await writeFile(probe, \"ok\", \"utf8\");\n await rm(probe, { force: true });\n return { name: \"JH4J_HOME\", ok: true, detail: home };\n } catch (error) {\n return { name: \"JH4J_HOME\", ok: false, detail: (error as Error).message };\n }\n}\n\nexport async function collectDoctorChecks(\n suppliedConfig?: UserConfig,\n suppliedCatalog?: CatalogTemplate[]\n): Promise<CheckResult[]> {\n const config = suppliedConfig ?? (await loadUserConfig());\n const catalog = suppliedCatalog ?? (await loadCatalog(config));\n const [git, pnpm, home] = await Promise.all([\n inspectCommand(\"git\"),\n inspectCommand(\"pnpm\"),\n checkHomeWritable()\n ]);\n const pnpmVersion = coerce(pnpm.output)?.version;\n const checks: CheckResult[] = [\n {\n name: \"Node.js\",\n ok: satisfies(process.versions.node, \"^22.12.0 || ^24.0.0\"),\n detail: `${process.versions.node}(要求 Node 22.12+ 或 24.x)`\n },\n { name: \"Git\", ok: git.ok, detail: git.output },\n {\n name: \"pnpm\",\n ok: pnpm.ok && Boolean(pnpmVersion && gte(pnpmVersion, \"11.8.0\")),\n detail: pnpm.output\n },\n home\n ];\n\n for (const template of catalog) {\n const sources = resolveTemplateSources(\n template,\n undefined,\n config.templateSource\n );\n const source = sources[0];\n if (!existsSync(source)) {\n checks.push({\n name: `模板 ${template.id}`,\n ok:\n source.startsWith(\"http://\") ||\n source.startsWith(\"https://\") ||\n source.startsWith(\"git@\"),\n detail: `远程候选源(创建时依次验证): ${sources.join(\" → \")}`\n });\n continue;\n }\n try {\n const manifest = await loadTemplateManifest(source);\n checks.push({\n name: `模板 ${template.id}`,\n ok:\n manifest.id === template.id &&\n satisfies(process.versions.node, manifest.runtime.node),\n detail: `${manifest.id}@${manifest.version} (${source})`\n });\n } catch (error) {\n checks.push({\n name: `模板 ${template.id}`,\n ok: false,\n detail: (error as Error).message\n });\n }\n }\n return checks;\n}\n\nexport async function doctorCommand(options: { json?: boolean } = {}): Promise<void> {\n const checks = await collectDoctorChecks();\n const failed = checks.filter((check) => !check.ok);\n if (options.json) {\n console.log(JSON.stringify({ ok: failed.length === 0, checks }, null, 2));\n } else {\n for (const check of checks) {\n console.log(`${check.ok ? \"✓\" : \"✗\"} ${check.name}: ${check.detail}`);\n }\n console.log(`\\n结果: ${checks.length - failed.length} 通过, ${failed.length} 失败`);\n }\n if (failed.length) process.exitCode = 1;\n}\n","import path from \"node:path\";\nimport { existsSync } from \"node:fs\";\nimport { readJson } from \"../utils/fs.js\";\nimport type { ProjectMetadata } from \"../types.js\";\n\nexport async function infoCommand(\n projectPath = process.cwd(),\n options: { json?: boolean } = {}\n): Promise<void> {\n const root = path.resolve(projectPath);\n const metadataPath = path.join(root, \".jhlc\", \"project.json\");\n if (!existsSync(metadataPath)) {\n throw new Error(`当前目录不是 JH4J CLI 创建的项目: ${metadataPath}`);\n }\n const metadata = await readJson<ProjectMetadata>(metadataPath);\n if (options.json) {\n console.log(JSON.stringify({ projectRoot: root, ...metadata }, null, 2));\n return;\n }\n console.log(`项目目录: ${root}`);\n console.log(`模板: ${metadata.template.id}@${metadata.template.version}`);\n console.log(`平台版本: ${metadata.platformVersion ?? \"未声明\"}`);\n console.log(`创建时间: ${metadata.createdAt}`);\n console.log(`创建工具: ${metadata.createdBy}`);\n console.log(\"项目参数:\");\n console.log(JSON.stringify(metadata.parameters, null, 2));\n}\n","import { loadCatalog } from \"../catalog.js\";\nimport { loadUserConfig } from \"../core/user-config.js\";\n\nexport async function listCommand(options: { json?: boolean } = {}): Promise<void> {\n const templates = await loadCatalog(await loadUserConfig());\n if (options.json) {\n console.log(JSON.stringify(templates, null, 2));\n return;\n }\n console.table(\n templates.map((template) => ({\n ID: template.id,\n 名称: template.name,\n 类型: template.category,\n 状态: template.status,\n 默认分支: template.defaultRef,\n 标签: template.tags?.join(\", \") ?? \"\"\n }))\n );\n}\n","import path from \"node:path\";\nimport { loadTemplateManifest } from \"../core/template-manifest.js\";\nimport { runCommand } from \"../utils/process.js\";\n\nexport async function validateTemplateCommand(templatePath: string): Promise<void> {\n const root = path.resolve(templatePath);\n const manifest = await loadTemplateManifest(root);\n await runCommand(process.execPath, [path.join(root, \"scripts\", \"validate-template.mjs\")], {\n cwd: root\n });\n console.log(`模板可用: ${manifest.id}@${manifest.version}`);\n}\n","import {\n DEFAULT_USER_CONFIG,\n getUserConfigPath,\n loadUserConfig,\n parseUserConfigValue,\n saveUserConfig\n} from \"../core/user-config.js\";\n\nexport async function configListCommand(options: { json?: boolean } = {}): Promise<void> {\n const config = await loadUserConfig();\n if (options.json) console.log(JSON.stringify(config, null, 2));\n else console.table(Object.entries(config).map(([key, value]) => ({ key, value })));\n console.log(`配置文件: ${getUserConfigPath()}`);\n}\n\nexport async function configGetCommand(key: string): Promise<void> {\n const config = await loadUserConfig();\n if (!(key in config)) throw new Error(`配置项不存在: ${key}`);\n console.log(String((config as unknown as Record<string, unknown>)[key]));\n}\n\nexport async function configSetCommand(key: string, value: string): Promise<void> {\n const config = await loadUserConfig();\n const [typedKey, typedValue] = parseUserConfigValue(key, value);\n (config as unknown as Record<string, unknown>)[typedKey] = typedValue;\n await saveUserConfig(config);\n console.log(`已设置 ${typedKey}=${String(typedValue)}`);\n}\n\nexport async function configUnsetCommand(key: string): Promise<void> {\n const config = await loadUserConfig();\n if (!(key in DEFAULT_USER_CONFIG) && !(key in config)) {\n throw new Error(`配置项不存在: ${key}`);\n }\n const defaults = DEFAULT_USER_CONFIG as unknown as Record<string, unknown>;\n const mutable = config as unknown as Record<string, unknown>;\n if (key in defaults) mutable[key] = defaults[key];\n else delete mutable[key];\n await saveUserConfig(config);\n console.log(`已重置配置项: ${key}`);\n}\n\nexport async function configResetCommand(): Promise<void> {\n await saveUserConfig({ ...DEFAULT_USER_CONFIG });\n console.log(`用户配置已恢复默认值: ${getUserConfigPath()}`);\n}\n","import {\n clearTemplateCache,\n getTemplateCacheRoot,\n listTemplateCache\n} from \"../core/template-cache.js\";\n\nfunction formatBytes(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 ** 2) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / 1024 ** 2).toFixed(1)} MB`;\n}\n\nexport async function cacheListCommand(options: { json?: boolean } = {}): Promise<void> {\n const entries = await listTemplateCache();\n if (options.json) {\n console.log(JSON.stringify(entries, null, 2));\n return;\n }\n if (!entries.length) {\n console.log(`模板缓存为空: ${getTemplateCacheRoot()}`);\n return;\n }\n console.table(\n entries.map((entry) => ({\n Key: entry.key,\n 来源: entry.metadata.source,\n Ref: entry.metadata.ref,\n 缓存时间: entry.metadata.cachedAt,\n 大小: formatBytes(entry.sizeBytes)\n }))\n );\n}\n\nexport async function cacheClearCommand(): Promise<void> {\n await clearTemplateCache();\n console.log(`模板缓存已清理: ${getTemplateCacheRoot()}`);\n}\n","import { runCli } from \"./cli.js\";\n\nrunCli().catch((error) => {\n console.error(`\\n错误: ${(error as Error).message}\\n`);\n process.exitCode = 1;\n});\n"],"mappings":"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","names":["path","existsSync","readdir","existsSync","path","path","existsSync","mkdir","readdir","rename","rm","writeFile","existsSync","mkdir","stat","path","path","existsSync","path","existsSync","path","existsSync","mkdir","stat","existsSync","path","readdir","rename","rm","writeFile","mkdir","prompts","existsSync","rename","rm","path","path","path","path","existsSync","rename","rm","selected","existsSync","mkdir","writeFile","rm","path","satisfies","path","mkdir","writeFile","rm","satisfies","existsSync","path","existsSync","path","existsSync","path","path","config"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/cli.ts","../package.json","../src/constants.ts","../src/catalog.ts","../src/utils/fs.ts","../src/core/template-source.ts","../src/utils/process.ts","../src/core/template-cache.ts","../src/core/user-config.ts","../src/commands/create.ts","../src/core/project-generator.ts","../src/ui/theme.ts","../src/core/errors.ts","../src/core/template-manifest.ts","../src/commands/doctor.ts","../src/commands/info.ts","../src/commands/list.ts","../src/commands/template.ts","../src/commands/config.ts","../src/commands/cache.ts"],"sourcesContent":["import * as prompts from \"@clack/prompts\";\nimport { runCli } from \"./cli.js\";\n\nrunCli().catch((error) => {\n prompts.cancel(`操作失败:${(error as Error).message}`);\n process.exitCode = 1;\n});\n","import { Command } from \"commander\";\nimport { COMMAND_NAME, CLI_VERSION } from \"./constants.js\";\nimport { findTemplate, loadCatalog } from \"./catalog.js\";\nimport {\n acquireTemplateFromSources,\n resolveTemplateSources\n} from \"./core/template-source.js\";\nimport { loadUserConfig } from \"./core/user-config.js\";\nimport { createCommand } from \"./commands/create.js\";\nimport { doctorCommand } from \"./commands/doctor.js\";\nimport { infoCommand } from \"./commands/info.js\";\nimport { listCommand } from \"./commands/list.js\";\nimport { validateTemplateCommand } from \"./commands/template.js\";\nimport {\n configGetCommand,\n configListCommand,\n configResetCommand,\n configSetCommand,\n configUnsetCommand\n} from \"./commands/config.js\";\nimport { cacheClearCommand, cacheListCommand } from \"./commands/cache.js\";\n\nexport function createProgram(): Command {\n const program = new Command();\n program\n .name(COMMAND_NAME)\n .description(\"JH4J Cloud 企业内部标准化项目脚手架\")\n .version(CLI_VERSION);\n\n program\n .command(\"create [name]\")\n .description(\"根据标准模板创建项目\")\n .option(\"-c, --category <category>\", \"项目类型:frontend、backend 或 mobile\")\n .option(\"-t, --template <id>\", \"模板 ID\")\n .option(\"--features <ids>\", \"启用的模板能力,多个 ID 使用逗号分隔\")\n .option(\"--no-standards\", \"不启用模板提供的 Git/代码标准化能力\")\n .option(\"--source <path-or-url>\", \"覆盖模板源(本地目录或 Git URL)\")\n .option(\"--ref <branch-or-tag>\", \"Git 分支或标签;默认使用模板 Catalog 配置\")\n .option(\"--module <name>\", \"平台模块标识\")\n .option(\"--title <title>\", \"系统标题\")\n .option(\"--port <port>\", \"开发端口\")\n .option(\"--npm-registry <url>\", \"npm registry(需包含企业定制包)\")\n .option(\"--jhlc-registry <url>\", \"@jhlc 私有 registry\")\n .option(\"--local-backend <url>\", \"本地后端地址\")\n .option(\"--local-public <url>\", \"本地 public 地址\")\n .option(\"--config <json-file>\", \"从 JSON 文件读取创建参数\")\n .option(\"-y, --yes\", \"接受模板默认值,非交互创建\")\n .option(\"--dry-run\", \"只预览,不写入文件\")\n .option(\"--install\", \"创建完成后安装依赖(默认不安装)\")\n .option(\"--skip-install\", \"不安装依赖(兼容旧命令)\")\n .option(\"--skip-git\", \"跳过 Git 初始化\")\n .option(\"--force\", \"覆盖已存在的同名目录\")\n .option(\"--no-cache\", \"不使用已有远程模板缓存\")\n .action(createCommand);\n\n program\n .command(\"list\")\n .description(\"列出可用模板\")\n .option(\"--json\", \"输出 JSON\")\n .action(listCommand);\n program\n .command(\"doctor\")\n .description(\"检查本机环境和模板可用性\")\n .option(\"--json\", \"输出 JSON\")\n .action(doctorCommand);\n program\n .command(\"info [path]\")\n .description(\"显示已生成项目的模板与版本信息\")\n .option(\"--json\", \"输出 JSON\")\n .action(infoCommand);\n\n const template = program.command(\"template\").description(\"模板维护命令\");\n template\n .command(\"validate [path]\")\n .description(\"校验模板 manifest 与模板契约\")\n .action(async (templatePath?: string) => {\n if (templatePath) return validateTemplateCommand(templatePath);\n const config = await loadUserConfig();\n const selected = findTemplate(await loadCatalog(config));\n const acquired = await acquireTemplateFromSources(\n resolveTemplateSources(selected, undefined, config.templateSource),\n config.templateRef ?? selected.defaultRef,\n { cacheTtlMinutes: config.cacheTtlMinutes }\n );\n try {\n return await validateTemplateCommand(acquired.root);\n } finally {\n await acquired.cleanup();\n }\n });\n\n const config = program.command(\"config\").description(\"管理用户默认配置\");\n config\n .command(\"list\")\n .option(\"--json\", \"输出 JSON\")\n .action(configListCommand);\n config.command(\"get <key>\").action(configGetCommand);\n config.command(\"set <key> <value>\").action(configSetCommand);\n config.command(\"unset <key>\").action(configUnsetCommand);\n config.command(\"reset\").action(configResetCommand);\n\n const cache = program.command(\"cache\").description(\"管理远程模板缓存\");\n cache\n .command(\"list\")\n .option(\"--json\", \"输出 JSON\")\n .action(cacheListCommand);\n cache.command(\"clear\").action(cacheClearCommand);\n\n return program;\n}\n\nexport async function runCli(argv = process.argv): Promise<void> {\n await createProgram().parseAsync(argv);\n}\n","{\n \"name\": \"@agile-team/jh4j-cloud-cli\",\n \"version\": \"0.6.1\",\n \"description\": \"JH4J Cloud 企业内部标准化项目脚手架\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/ChenyCHENYU/jh4j-cloud-cli.git\"\n },\n \"homepage\": \"https://github.com/ChenyCHENYU/jh4j-cloud-cli#readme\",\n \"bugs\": {\n \"url\": \"https://github.com/ChenyCHENYU/jh4j-cloud-cli/issues\"\n },\n \"type\": \"module\",\n \"engines\": {\n \"node\": \"^22.12.0 || ^24.0.0\",\n \"pnpm\": \">=11.8.0\"\n },\n \"packageManager\": \"pnpm@11.8.0\",\n \"bin\": {\n \"jh4j\": \"bin/jh4j.js\"\n },\n \"files\": [\n \"bin\",\n \"dist\",\n \"README.md\",\n \"CHANGELOG.md\",\n \"catalog.schema.json\"\n ],\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"tsup --watch\",\n \"typecheck\": \"tsc --noEmit\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"start\": \"node bin/jh4j.js\",\n \"check\": \"pnpm typecheck && pnpm test && pnpm build\",\n \"prepack\": \"pnpm check\"\n },\n \"dependencies\": {\n \"@clack/prompts\": \"^1.7.0\",\n \"commander\": \"^15.0.0\",\n \"semver\": \"^7.8.5\",\n \"tar\": \"^7.5.19\"\n },\n \"publishConfig\": {\n \"access\": \"public\",\n \"registry\": \"https://registry.npmjs.org/\"\n },\n \"devDependencies\": {\n \"@types/node\": \"^24.13.3\",\n \"@types/semver\": \"7.7.1\",\n \"tsup\": \"8.5.1\",\n \"typescript\": \"7.0.2\",\n \"vitest\": \"4.1.10\"\n }\n}\n","import packageJson from \"../package.json\" with { type: \"json\" };\n\nexport const CLI_NAME = \"@agile-team/jh4j-cloud-cli\";\nexport const CLI_VERSION = packageJson.version;\nexport const COMMAND_NAME = \"jh4j\";\nexport const SUPPORTED_NODE_MAJORS = new Set([22, 24]);\nexport const TEMPLATE_SOURCE_ENV = \"JH4J_UI_TEMPLATE_SOURCE\";\nexport const JH4J_HOME_ENV = \"JH4J_HOME\";\nexport const CATALOG_FILE_ENV = \"JH4J_CATALOG_FILE\";\nexport const USER_CONFIG_SCHEMA_VERSION = 1;\n","import { fileURLToPath } from \"node:url\";\nimport path from \"node:path\";\nimport { existsSync } from \"node:fs\";\nimport { CATALOG_FILE_ENV, TEMPLATE_SOURCE_ENV } from \"./constants.js\";\nimport { readJson } from \"./utils/fs.js\";\nimport type { CatalogFile, CatalogTemplate, UserConfig } from \"./types.js\";\n\nconst siblingTemplatePath = fileURLToPath(\n new URL(\"../../jh4j-ui-template/\", import.meta.url)\n);\nconst siblingMobileTemplatePath = fileURLToPath(\n new URL(\"../../../Robot_H5/\", import.meta.url)\n);\nconst remoteTemplateSources = [\n \"https://github.com/ChenyCHENYU/jh4j-ui-template.git\",\n \"https://gitee.com/ycyplus163/jh4j-ui-template.git\"\n];\nconst remoteMobileTemplateSources = [\n \"https://github.com/ChenyCHENYU/Robot_H5.git\",\n \"https://gitee.com/ycyplus163/robot_-h5.git\"\n];\n\nexport const BUILTIN_TEMPLATES: CatalogTemplate[] = [\n {\n id: \"web.jh4j-mf-remote\",\n name: \"JH4J PC 微前端业务模板\",\n description: \"Vue 3 + Vite + Module Federation 标准业务子系统\",\n category: \"frontend\",\n sourceEnvironment: TEMPLATE_SOURCE_ENV,\n defaultSource: existsSync(siblingTemplatePath)\n ? siblingTemplatePath\n : remoteTemplateSources[0],\n sources: remoteTemplateSources,\n defaultRef: \"main\",\n status: \"beta\",\n tags: [\"vue\", \"vite\", \"module-federation\", \"pc\"]\n },\n {\n id: \"mobile.robot-h5\",\n name: \"JH4J 移动端 H5 模板\",\n description: \"Vue 3 + Vite 7 + Vant 4 企业级移动端 H5 应用\",\n category: \"mobile\",\n sourceEnvironment: TEMPLATE_SOURCE_ENV,\n defaultSource: existsSync(siblingMobileTemplatePath)\n ? siblingMobileTemplatePath\n : remoteMobileTemplateSources[0],\n sources: remoteMobileTemplateSources,\n defaultRef: \"v1.6.0\",\n status: \"beta\",\n tags: [\"vue\", \"vite\", \"vant\", \"h5\", \"mobile\"]\n }\n];\n\nfunction validateCatalogTemplate(template: CatalogTemplate): void {\n if (!template.id || !template.name || !template.category) {\n throw new Error(\"Catalog 模板缺少 id、name 或 category\");\n }\n if (!new Set([\"frontend\", \"backend\", \"mobile\"]).has(template.category)) {\n throw new Error(`Catalog 模板 ${template.id} 的 category 无效`);\n }\n if (!new Set([\"stable\", \"beta\"]).has(template.status)) {\n throw new Error(`Catalog 模板 ${template.id} 的 status 无效`);\n }\n if (!template.defaultRef) {\n throw new Error(`Catalog 模板 ${template.id} 缺少 defaultRef`);\n }\n if (!template.defaultSource && !template.sourceEnvironment) {\n throw new Error(`Catalog 模板 ${template.id} 没有可解析的模板源`);\n }\n if (template.sources?.some((source) => !source.trim())) {\n throw new Error(`Catalog 模板 ${template.id} 包含空的备用源`);\n }\n}\n\nfunction resolveCatalogSource(source: string, catalogDirectory: string): string {\n const isRemote =\n /^(?:https?|ssh|file):\\/\\//.test(source) || source.startsWith(\"git@\");\n return isRemote || path.isAbsolute(source)\n ? source\n : path.resolve(catalogDirectory, source);\n}\n\nexport async function loadCatalog(config?: UserConfig): Promise<CatalogTemplate[]> {\n const configuredFile = process.env[CATALOG_FILE_ENV] || config?.catalogFile;\n if (!configuredFile) return [...BUILTIN_TEMPLATES];\n\n const catalogPath = path.resolve(configuredFile);\n if (!existsSync(catalogPath)) {\n throw new Error(`Catalog 文件不存在: ${catalogPath}`);\n }\n const external = await readJson<CatalogFile>(catalogPath);\n if (external.schemaVersion !== 1 || !Array.isArray(external.templates)) {\n throw new Error(`Catalog 文件格式无效: ${catalogPath}`);\n }\n const catalogDirectory = path.dirname(catalogPath);\n external.templates = external.templates.map((template) => {\n return {\n ...template,\n defaultSource: resolveCatalogSource(\n template.defaultSource,\n catalogDirectory\n ),\n sources: template.sources?.map((source) =>\n resolveCatalogSource(source, catalogDirectory)\n )\n };\n });\n external.templates.forEach(validateCatalogTemplate);\n\n const merged = new Map(BUILTIN_TEMPLATES.map((item) => [item.id, item]));\n external.templates.forEach((item) => merged.set(item.id, item));\n return [...merged.values()];\n}\n\nexport function findTemplate(\n catalog: CatalogTemplate[],\n id?: string\n): CatalogTemplate {\n const selected = id ?? catalog[0]?.id;\n const template = catalog.find((item) => item.id === selected);\n if (!template) {\n throw new Error(\n `模板不存在: ${selected}。可用模板: ${catalog.map((item) => item.id).join(\", \")}`\n );\n }\n return template;\n}\n","import { cp, mkdir, readFile, rm, stat, writeFile } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport path from \"node:path\";\n\nconst EXCLUDED_TEMPLATE_PATHS = new Set([\n \".git\",\n \".jhlc\",\n \"dist\",\n \"node_modules\"\n]);\n\nexport async function readJson<T>(file: string): Promise<T> {\n return JSON.parse(await readFile(file, \"utf8\")) as T;\n}\n\nexport async function writeJson(file: string, value: unknown): Promise<void> {\n await mkdir(path.dirname(file), { recursive: true });\n await writeFile(file, `${JSON.stringify(value, null, 2)}\\n`, \"utf8\");\n}\n\nexport async function isDirectory(directory: string): Promise<boolean> {\n try {\n return (await stat(directory)).isDirectory();\n } catch {\n return false;\n }\n}\n\nexport async function isDirectoryEmpty(directory: string): Promise<boolean> {\n if (!existsSync(directory)) return true;\n const { readdir } = await import(\"node:fs/promises\");\n return (await readdir(directory)).length === 0;\n}\n\nexport async function copyTemplateTree(\n sourceRoot: string,\n targetRoot: string\n): Promise<void> {\n await mkdir(targetRoot, { recursive: true });\n await cp(sourceRoot, targetRoot, {\n recursive: true,\n force: true,\n filter(source) {\n const relative = path.relative(sourceRoot, source);\n if (!relative) return true;\n const [topLevel] = relative.split(path.sep);\n return !EXCLUDED_TEMPLATE_PATHS.has(topLevel);\n }\n });\n}\n\nexport async function removePath(target: string): Promise<void> {\n await rm(target, { recursive: true, force: true, maxRetries: 3 });\n}\n","import path from \"node:path\";\nimport { existsSync } from \"node:fs\";\nimport { mkdir, readdir, rename, rm, writeFile } from \"node:fs/promises\";\nimport { x as extractTar } from \"tar\";\nimport type { CatalogTemplate } from \"../types.js\";\nimport { isDirectory } from \"../utils/fs.js\";\nimport { runCommand } from \"../utils/process.js\";\nimport {\n createTemplateCacheStaging,\n isTemplateCacheFresh,\n readTemplateCacheEntry\n} from \"./template-cache.js\";\n\nconst MAX_ARCHIVE_BYTES = 200 * 1024 * 1024;\n\nexport interface AcquiredTemplate {\n root: string;\n source: string;\n cleanup(): Promise<void>;\n}\n\nexport function resolveTemplateSource(\n template: CatalogTemplate,\n override?: string,\n configuredSource?: string\n): string {\n return resolveTemplateSources(template, override, configuredSource)[0];\n}\n\nexport function resolveTemplateSources(\n template: CatalogTemplate,\n override?: string,\n configuredSource?: string\n): string[] {\n const exclusiveSource =\n override ||\n (template.sourceEnvironment\n ? process.env[template.sourceEnvironment]\n : undefined) ||\n configuredSource;\n if (exclusiveSource) return [exclusiveSource];\n return [...new Set([template.defaultSource, ...(template.sources ?? [])])];\n}\n\nfunction isGitSource(source: string): boolean {\n return (\n source.startsWith(\"git@\") ||\n source.startsWith(\"ssh://\") ||\n source.startsWith(\"file://\") ||\n source.startsWith(\"http://\") ||\n source.startsWith(\"https://\") ||\n source.endsWith(\".git\")\n );\n}\n\nfunction isArchiveSource(source: string): boolean {\n const pathname = source.split(/[?#]/, 1)[0].toLowerCase();\n return pathname.endsWith(\".tgz\") || pathname.endsWith(\".tar.gz\") || pathname.endsWith(\".tar\");\n}\n\nasync function getFreshCache(\n source: string,\n ref: string,\n options: { noCache?: boolean; cacheTtlMinutes?: number }\n): Promise<AcquiredTemplate | null> {\n const cacheEntry = await readTemplateCacheEntry(source, ref);\n if (\n !options.noCache &&\n cacheEntry &&\n isTemplateCacheFresh(cacheEntry, options.cacheTtlMinutes ?? 60)\n ) {\n return {\n root: cacheEntry.root,\n source: `${source}#${ref} (cache)`,\n async cleanup() {}\n };\n }\n return null;\n}\n\nasync function normalizeExtractedTemplate(\n stagingRoot: string,\n templateRoot: string\n): Promise<void> {\n if (existsSync(path.join(templateRoot, \"template.manifest.json\"))) return;\n const children = await readdir(templateRoot, { withFileTypes: true });\n const candidates = children.filter(\n (entry) =>\n entry.isDirectory() &&\n existsSync(path.join(templateRoot, entry.name, \"template.manifest.json\"))\n );\n if (candidates.length !== 1) {\n throw new Error(\"压缩包根目录或唯一一级目录中未找到 template.manifest.json\");\n }\n const normalizedRoot = path.join(stagingRoot, \".normalized-template\");\n await rename(path.join(templateRoot, candidates[0].name), normalizedRoot);\n await rm(templateRoot, { recursive: true, force: true });\n await rename(normalizedRoot, templateRoot);\n}\n\nasync function acquireArchiveTemplate(\n source: string,\n ref: string,\n options: { noCache?: boolean; cacheTtlMinutes?: number }\n): Promise<AcquiredTemplate> {\n const cached = await getFreshCache(source, ref, options);\n if (cached) return cached;\n\n const cacheStaging = await createTemplateCacheStaging(source, ref);\n const archiveFile = path.join(cacheStaging.stagingRoot, \"template.tgz\");\n try {\n if (source.startsWith(\"http://\") || source.startsWith(\"https://\")) {\n const response = await fetch(source, { signal: AbortSignal.timeout(60_000) });\n if (!response.ok) {\n throw new Error(`模板压缩包下载失败: HTTP ${response.status}`);\n }\n const declaredLength = Number(response.headers.get(\"content-length\") || 0);\n if (declaredLength > MAX_ARCHIVE_BYTES) {\n throw new Error(\"模板压缩包超过 200 MB 限制\");\n }\n const archiveBuffer = Buffer.from(await response.arrayBuffer());\n if (archiveBuffer.byteLength > MAX_ARCHIVE_BYTES) {\n throw new Error(\"模板压缩包超过 200 MB 限制\");\n }\n await writeFile(archiveFile, archiveBuffer);\n } else {\n const { copyFile } = await import(\"node:fs/promises\");\n await copyFile(path.resolve(source), archiveFile);\n }\n await mkdir(cacheStaging.templateRoot, { recursive: true });\n await extractTar({ file: archiveFile, cwd: cacheStaging.templateRoot });\n await normalizeExtractedTemplate(\n cacheStaging.stagingRoot,\n cacheStaging.templateRoot\n );\n await rm(archiveFile, { force: true });\n await cacheStaging.commit();\n return {\n root: path.join(cacheStaging.entryRoot, \"template\"),\n source: `${source} (archive)`,\n async cleanup() {}\n };\n } catch (error) {\n await cacheStaging.cleanup();\n throw error;\n }\n}\n\nexport async function acquireTemplate(\n source: string,\n ref: string,\n options: { noCache?: boolean; cacheTtlMinutes?: number } = {}\n): Promise<AcquiredTemplate> {\n const localPath = path.resolve(source);\n if (existsSync(localPath)) {\n if (await isDirectory(localPath)) {\n return {\n root: localPath,\n source: localPath,\n async cleanup() {}\n };\n }\n if (isArchiveSource(localPath)) {\n return acquireArchiveTemplate(localPath, ref, options);\n }\n throw new Error(`模板源不是目录或支持的 tar 压缩包: ${localPath}`);\n }\n\n if (isArchiveSource(source)) {\n return acquireArchiveTemplate(source, ref, options);\n }\n\n if (!isGitSource(source)) {\n throw new Error(`模板源不存在: ${source}`);\n }\n\n const cached = await getFreshCache(source, ref, options);\n if (cached) return cached;\n\n const cacheStaging = await createTemplateCacheStaging(source, ref);\n try {\n await runCommand(\n \"git\",\n [\n \"-c\",\n \"http.lowSpeedLimit=1024\",\n \"-c\",\n \"http.lowSpeedTime=15\",\n \"clone\",\n \"--depth\",\n \"1\",\n \"--branch\",\n ref,\n source,\n cacheStaging.templateRoot\n ],\n { stdio: \"pipe\", env: { GIT_TERMINAL_PROMPT: \"0\" } }\n );\n await cacheStaging.commit();\n return {\n root: path.join(cacheStaging.entryRoot, \"template\"),\n source: `${source}#${ref}`,\n async cleanup() {}\n };\n } catch (error) {\n await cacheStaging.cleanup();\n throw error;\n }\n}\n\nexport async function acquireTemplateFromSources(\n sources: string[],\n ref: string,\n options: { noCache?: boolean; cacheTtlMinutes?: number } = {}\n): Promise<AcquiredTemplate> {\n if (!sources.length) throw new Error(\"没有可用的模板源\");\n const failures: string[] = [];\n for (const source of [...new Set(sources)]) {\n try {\n return await acquireTemplate(source, ref, options);\n } catch (error) {\n failures.push(`${source}: ${(error as Error).message}`);\n }\n }\n throw new Error(`所有模板源均不可用:\\n- ${failures.join(\"\\n- \")}`);\n}\n","import { spawn } from \"node:child_process\";\n\nexport interface RunCommandOptions {\n cwd?: string;\n stdio?: \"inherit\" | \"pipe\";\n env?: NodeJS.ProcessEnv;\n}\n\nexport function platformCommand(command: string): string {\n if (process.platform !== \"win32\") return command;\n return command === \"pnpm\" || command === \"npm\" || command === \"npx\"\n ? `${command}.cmd`\n : command;\n}\n\nexport async function runCommand(\n command: string,\n args: string[],\n options: RunCommandOptions = {}\n): Promise<string> {\n const stdio = options.stdio ?? \"inherit\";\n return new Promise((resolve, reject) => {\n const executable = platformCommand(command);\n const isWindowsCommand =\n process.platform === \"win32\" && executable.endsWith(\".cmd\");\n const spawnExecutable = isWindowsCommand\n ? process.env.ComSpec || \"cmd.exe\"\n : executable;\n const spawnArgs = isWindowsCommand\n ? [\"/d\", \"/s\", \"/c\", executable, ...args]\n : args;\n const child = spawn(spawnExecutable, spawnArgs, {\n cwd: options.cwd,\n stdio,\n env: { ...process.env, ...options.env },\n windowsHide: true\n });\n\n let output = \"\";\n if (stdio === \"pipe\") {\n child.stdout?.on(\"data\", (chunk) => {\n output += chunk.toString();\n });\n child.stderr?.on(\"data\", (chunk) => {\n output += chunk.toString();\n });\n }\n\n child.on(\"error\", reject);\n child.on(\"exit\", (code) => {\n if (code === 0) {\n resolve(output.trim());\n return;\n }\n reject(\n new Error(\n `${command} ${args.join(\" \")} 执行失败(exit ${code ?? \"unknown\"})${output ? `\\n${output.trim()}` : \"\"}`\n )\n );\n });\n });\n}\n\nexport async function inspectCommand(\n command: string,\n args: string[] = [\"--version\"]\n): Promise<{ ok: boolean; output: string }> {\n try {\n return { ok: true, output: await runCommand(command, args, { stdio: \"pipe\" }) };\n } catch (error) {\n return { ok: false, output: (error as Error).message };\n }\n}\n","import { createHash } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport { mkdir, readdir, rename, stat } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { getJh4jHome } from \"./user-config.js\";\nimport { readJson, removePath, writeJson } from \"../utils/fs.js\";\nimport type { TemplateCacheMetadata } from \"../types.js\";\n\nconst CACHE_SCHEMA_VERSION = 1;\n\nexport interface TemplateCacheEntry {\n key: string;\n root: string;\n metadata: TemplateCacheMetadata;\n sizeBytes: number;\n}\n\nexport function getTemplateCacheRoot(): string {\n return path.join(getJh4jHome(), \"cache\", \"templates\");\n}\n\nexport function getTemplateCacheKey(source: string, ref: string): string {\n return createHash(\"sha256\").update(`${source}\\0${ref}`).digest(\"hex\").slice(0, 20);\n}\n\nfunction getEntryPaths(key: string) {\n const entryRoot = path.join(getTemplateCacheRoot(), key);\n return {\n entryRoot,\n templateRoot: path.join(entryRoot, \"template\"),\n metadataPath: path.join(entryRoot, \"metadata.json\")\n };\n}\n\nexport async function readTemplateCacheEntry(\n source: string,\n ref: string\n): Promise<TemplateCacheEntry | null> {\n const key = getTemplateCacheKey(source, ref);\n const paths = getEntryPaths(key);\n if (!existsSync(paths.templateRoot) || !existsSync(paths.metadataPath)) return null;\n try {\n const metadata = await readJson<TemplateCacheMetadata>(paths.metadataPath);\n if (\n metadata.schemaVersion !== CACHE_SCHEMA_VERSION ||\n metadata.source !== source ||\n metadata.ref !== ref\n ) {\n return null;\n }\n return {\n key,\n root: paths.templateRoot,\n metadata,\n sizeBytes: await calculateDirectorySize(paths.entryRoot)\n };\n } catch {\n return null;\n }\n}\n\nexport function isTemplateCacheFresh(\n entry: TemplateCacheEntry,\n ttlMinutes: number\n): boolean {\n if (ttlMinutes <= 0) return false;\n const cachedAt = Date.parse(entry.metadata.cachedAt);\n return Number.isFinite(cachedAt) && Date.now() - cachedAt < ttlMinutes * 60_000;\n}\n\nexport async function createTemplateCacheStaging(\n source: string,\n ref: string\n): Promise<{\n key: string;\n entryRoot: string;\n stagingRoot: string;\n templateRoot: string;\n commit(): Promise<void>;\n cleanup(): Promise<void>;\n}> {\n const key = getTemplateCacheKey(source, ref);\n const cacheRoot = getTemplateCacheRoot();\n await mkdir(cacheRoot, { recursive: true });\n const stagingRoot = path.join(\n cacheRoot,\n `.${key}.tmp-${process.pid}-${Date.now()}`\n );\n const templateRoot = path.join(stagingRoot, \"template\");\n const entryRoot = path.join(cacheRoot, key);\n await mkdir(stagingRoot, { recursive: true });\n\n return {\n key,\n entryRoot,\n stagingRoot,\n templateRoot,\n async commit() {\n await writeJson(path.join(stagingRoot, \"metadata.json\"), {\n schemaVersion: CACHE_SCHEMA_VERSION,\n source,\n ref,\n cachedAt: new Date().toISOString()\n } satisfies TemplateCacheMetadata);\n await removePath(entryRoot);\n await rename(stagingRoot, entryRoot);\n },\n cleanup: () => removePath(stagingRoot)\n };\n}\n\nasync function calculateDirectorySize(directory: string): Promise<number> {\n let total = 0;\n const entries = await readdir(directory, { withFileTypes: true });\n for (const entry of entries) {\n const absolute = path.join(directory, entry.name);\n if (entry.isDirectory()) total += await calculateDirectorySize(absolute);\n else if (entry.isFile()) total += (await stat(absolute)).size;\n }\n return total;\n}\n\nexport async function listTemplateCache(): Promise<TemplateCacheEntry[]> {\n const cacheRoot = getTemplateCacheRoot();\n if (!existsSync(cacheRoot)) return [];\n const entries: TemplateCacheEntry[] = [];\n for (const directory of await readdir(cacheRoot, { withFileTypes: true })) {\n if (!directory.isDirectory() || directory.name.startsWith(\".\")) continue;\n const paths = getEntryPaths(directory.name);\n if (!existsSync(paths.metadataPath) || !existsSync(paths.templateRoot)) continue;\n try {\n entries.push({\n key: directory.name,\n root: paths.templateRoot,\n metadata: await readJson<TemplateCacheMetadata>(paths.metadataPath),\n sizeBytes: await calculateDirectorySize(paths.entryRoot)\n });\n } catch {\n // 损坏条目由 clear 或下一次拉取覆盖。\n }\n }\n return entries.sort((a, b) =>\n b.metadata.cachedAt.localeCompare(a.metadata.cachedAt)\n );\n}\n\nexport async function clearTemplateCache(): Promise<void> {\n await removePath(getTemplateCacheRoot());\n}\n","import os from \"node:os\";\nimport path from \"node:path\";\nimport { existsSync } from \"node:fs\";\nimport { JH4J_HOME_ENV, USER_CONFIG_SCHEMA_VERSION } from \"../constants.js\";\nimport { readJson, writeJson } from \"../utils/fs.js\";\nimport type { UserConfig } from \"../types.js\";\n\nexport const DEFAULT_USER_CONFIG: UserConfig = {\n schemaVersion: USER_CONFIG_SCHEMA_VERSION,\n autoInstall: false,\n autoGit: true,\n cacheTtlMinutes: 60\n};\n\nexport function getJh4jHome(): string {\n return path.resolve(process.env[JH4J_HOME_ENV] || path.join(os.homedir(), \".jh4j\"));\n}\n\nexport function getUserConfigPath(): string {\n return path.join(getJh4jHome(), \"config.json\");\n}\n\nexport async function loadUserConfig(): Promise<UserConfig> {\n const configPath = getUserConfigPath();\n if (!existsSync(configPath)) return { ...DEFAULT_USER_CONFIG };\n\n const stored = await readJson<Partial<UserConfig>>(configPath);\n if (\n stored.schemaVersion !== undefined &&\n stored.schemaVersion !== USER_CONFIG_SCHEMA_VERSION\n ) {\n throw new Error(\n `不支持的用户配置版本: ${stored.schemaVersion},当前要求 ${USER_CONFIG_SCHEMA_VERSION}`\n );\n }\n return { ...DEFAULT_USER_CONFIG, ...stored };\n}\n\nexport async function saveUserConfig(config: UserConfig): Promise<void> {\n await writeJson(getUserConfigPath(), {\n ...config,\n schemaVersion: USER_CONFIG_SCHEMA_VERSION\n });\n}\n\nconst CONFIG_KEYS = new Set<keyof UserConfig>([\n \"catalogFile\",\n \"templateSource\",\n \"templateRef\",\n \"npmRegistry\",\n \"jhlcRegistry\",\n \"autoInstall\",\n \"autoGit\",\n \"cacheTtlMinutes\"\n]);\n\nexport function parseUserConfigValue(\n key: string,\n rawValue: string\n): [keyof UserConfig, UserConfig[keyof UserConfig]] {\n if (!CONFIG_KEYS.has(key as keyof UserConfig)) {\n throw new Error(`不支持的配置项: ${key}`);\n }\n const typedKey = key as keyof UserConfig;\n if (typedKey === \"autoInstall\" || typedKey === \"autoGit\") {\n const normalized = rawValue.toLowerCase();\n if (!new Set([\"true\", \"false\"]).has(normalized)) {\n throw new Error(`${key} 只能是 true 或 false`);\n }\n return [typedKey, normalized === \"true\"];\n }\n if (typedKey === \"cacheTtlMinutes\") {\n const value = Number(rawValue);\n if (!Number.isInteger(value) || value < 0 || value > 10080) {\n throw new Error(\"cacheTtlMinutes 必须是 0 到 10080 之间的整数\");\n }\n return [typedKey, value];\n }\n return [typedKey, rawValue.trim()];\n}\n","import * as prompts from \"@clack/prompts\";\nimport { findTemplate, loadCatalog } from \"../catalog.js\";\nimport { CLI_VERSION } from \"../constants.js\";\nimport {\n generateProject,\n normalizeProjectName,\n type GenerateProjectResult\n} from \"../core/project-generator.js\";\nimport { UserCancelledError } from \"../core/errors.js\";\nimport { loadUserConfig } from \"../core/user-config.js\";\nimport { ui } from \"../ui/theme.js\";\nimport type {\n CatalogTemplate,\n CreateOptions,\n TemplateCategory\n} from \"../types.js\";\n\nconst TEMPLATE_PRESENTATION: Record<\n TemplateCategory,\n {\n label: string;\n hint: string;\n }\n> = {\n frontend: { label: \"PC 管理端\", hint: \"Vue 3 · Vite · 微前端\" },\n backend: { label: \"后端服务\", hint: \"Java · Spring Cloud · 云原生\" },\n mobile: { label: \"移动端 H5\", hint: \"Vue 3 · Vite 7 · Vant 4\" }\n};\n\nexport type CreationMode = \"quick\" | \"custom\";\n\nfunction isCategory(value: string): value is TemplateCategory {\n return Object.hasOwn(TEMPLATE_PRESENTATION, value);\n}\n\nexport function templatesByCategory(\n templates: CatalogTemplate[],\n category: TemplateCategory\n): CatalogTemplate[] {\n return templates.filter((template) => template.category === category);\n}\n\nexport function templateOptionsFor(\n templates: CatalogTemplate[]\n): Array<{ value: string; label: string; hint: string }> {\n return templates.map((template) => ({\n value: template.id,\n label: TEMPLATE_PRESENTATION[template.category].label,\n hint: TEMPLATE_PRESENTATION[template.category].hint\n }));\n}\n\nexport function creationModeOptions(): Array<{\n value: CreationMode;\n label: string;\n hint: string;\n}> {\n return [\n {\n value: \"quick\",\n label: \"快速创建(推荐)\",\n hint: \"采用模板推荐配置,立即生成\"\n },\n {\n value: \"custom\",\n label: \"自定义创建\",\n hint: \"设置项目名、标题、端口和联调地址\"\n }\n ];\n}\n\nexport function defaultProjectNameFor(category: TemplateCategory): string {\n if (category === \"mobile\") return \"jh4j-mobile-app\";\n if (category === \"backend\") return \"jh4j-service-app\";\n return \"jh4j-ui-app\";\n}\n\nexport function projectNamePromptOptions(\n category: TemplateCategory\n): Parameters<typeof prompts.text>[0] {\n const defaultProjectName = defaultProjectNameFor(category);\n return {\n message: ui.strong(\"项目名称\"),\n initialValue: defaultProjectName,\n defaultValue: defaultProjectName,\n validate(value) {\n return !value || normalizeProjectName(value)\n ? undefined\n : \"请输入至少一个字母或数字,例如 jh4j-mobile-app\";\n }\n };\n}\n\nasync function selectTemplate(\n templates: CatalogTemplate[],\n options: CreateOptions\n): Promise<CatalogTemplate> {\n if (options.template) {\n const selected = findTemplate(templates, options.template);\n if (options.category && selected.category !== options.category) {\n throw new Error(\n `模板 ${selected.id} 属于 ${selected.category},与 --category ${options.category} 不一致`\n );\n }\n return selected;\n }\n\n if (options.category && !isCategory(options.category)) {\n throw new Error(\n `项目类型无效: ${options.category}。可用值: frontend、backend、mobile`\n );\n }\n const candidates = options.category\n ? templatesByCategory(templates, options.category)\n : templates;\n if (!candidates.length) {\n throw new Error(\n options.category\n ? `项目类型 ${options.category} 暂无可用模板`\n : \"Catalog 中没有可用模板\"\n );\n }\n if (options.yes) return findTemplate(candidates);\n if (candidates.length === 1) return candidates[0];\n\n const selected = await prompts.select({\n message: ui.strong(\"选择项目模板\"),\n options: templateOptionsFor(candidates).map((option) => ({\n ...option,\n label: ui.strong(option.label),\n hint: ui.muted(option.hint)\n })),\n initialValue: candidates[0].id\n });\n if (prompts.isCancel(selected)) throw new UserCancelledError();\n return findTemplate(candidates, String(selected));\n}\n\nasync function selectCreationMode(options: CreateOptions): Promise<CreationMode> {\n if (options.yes) return \"quick\";\n const selected = await prompts.select({\n message: ui.strong(\"选择创建方式\"),\n options: creationModeOptions().map((option) => ({\n ...option,\n label:\n option.value === \"quick\"\n ? ui.accent(ui.strong(option.label))\n : ui.strong(option.label),\n hint: ui.muted(option.hint)\n })),\n initialValue: \"quick\"\n });\n if (prompts.isCancel(selected)) throw new UserCancelledError();\n return selected as CreationMode;\n}\n\nfunction profileRowsFor(\n category: TemplateCategory,\n features: string[]\n): Array<{ label: string; value: string }> {\n const rows =\n category === \"mobile\"\n ? [\n { label: \"技术\", value: \"Vue 3 · Vite 7 · Vant 4 · TypeScript\" },\n { label: \"核心\", value: \"@robot-h5/core\" }\n ]\n : category === \"frontend\"\n ? [\n { label: \"技术\", value: \"Vue 3 · Vite · Module Federation\" },\n { label: \"核心\", value: \"@jhlc/common-core\" }\n ]\n : [{ label: \"技术\", value: \"Java · Spring Cloud\" }];\n if (features.includes(\"git-standards\")) {\n rows.push({ label: \"规范\", value: \"Commitizen · Commitlint · Husky · ESLint\" });\n }\n rows.push({ label: \"环境\", value: \"DEV · SIT · UAT · PRE · PRD\" });\n return rows;\n}\n\nexport interface CompletionView {\n headline: string;\n overview: Array<{ label: string; value: string }>;\n endpoints: Array<{ label: string; value: string }>;\n profile: Array<{ label: string; value: string }>;\n gitInitialized: boolean;\n installed: boolean;\n nextSteps: string[];\n configFiles: string;\n}\n\nexport function buildCompletionView(\n projectName: string,\n mode: CreationMode,\n result: GenerateProjectResult\n): CompletionView {\n const nextSteps = [\n `cd ${projectName}`,\n ...(!result.installed ? [\"pnpm install\", \"pnpm dev\"] : [\"pnpm dev\"])\n ];\n return {\n headline: `${projectName} 创建成功`,\n overview: [\n {\n label: \"模板\",\n value: `${result.templateName} · v${result.templateVersion}`\n },\n { label: \"标题\", value: result.configuration.title },\n { label: \"方式\", value: mode === \"quick\" ? \"快速创建\" : \"自定义创建\" }\n ],\n endpoints: [\n {\n label: \"APP\",\n value: `http://localhost:${result.configuration.devServerPort}`\n },\n { label: \"API\", value: result.configuration.localBackendUrl }\n ],\n profile: profileRowsFor(result.category, result.features),\n gitInitialized: result.gitInitialized,\n installed: result.installed,\n nextSteps,\n configFiles: \"project.config.json · .env*\"\n };\n}\n\nfunction row(label: string, value: string): string {\n return `${ui.muted(`${label} `)}${value}`;\n}\n\nfunction renderCompletion(\n projectName: string,\n mode: CreationMode,\n result: GenerateProjectResult\n): void {\n const view = buildCompletionView(projectName, mode, result);\n prompts.log.message(\n [\n ui.strong(view.headline),\n ...view.overview.map((item) => row(item.label, item.value))\n ],\n {\n symbol: ui.success(\"◆\"),\n secondarySymbol: ui.muted(\"│\"),\n spacing: 1\n }\n );\n prompts.log.message(\n [\n ui.strong(\"本地服务\"),\n ...view.endpoints.map((item) => row(item.label, ui.accent(item.value)))\n ],\n {\n symbol: ui.accent(\"◇\"),\n secondarySymbol: ui.muted(\"│\"),\n spacing: 1\n }\n );\n const gitStatus = view.gitInitialized\n ? ui.success(\"Git main 已初始化\")\n : ui.muted(\"Git 未初始化\");\n const dependencyStatus = view.installed\n ? ui.success(\"依赖已安装\")\n : ui.warning(\"依赖待安装\");\n prompts.log.message(\n [\n ui.strong(\"工程配置\"),\n ...view.profile.map((item) => row(item.label, item.value)),\n row(\"状态\", `${gitStatus} ${ui.muted(\"·\")} ${dependencyStatus}`)\n ],\n {\n symbol: ui.secondary(\"◇\"),\n secondarySymbol: ui.muted(\"│\"),\n spacing: 1\n }\n );\n prompts.outro(`${ui.success(\"READY\")} ${ui.muted(\"· 项目已准备就绪\")}`);\n prompts.box(\n [\n \"\",\n ...view.nextSteps.map(\n (command, index) =>\n ` ${ui.muted(String(index + 1).padStart(2, \"0\"))} ${ui.command(command)}`\n ),\n \"\",\n ` ${ui.muted(\"配置\")} ${ui.muted(view.configFiles)}`,\n \"\"\n ].join(\"\\n\"),\n ui.accent(ui.strong(\" NEXT STEPS \")),\n {\n rounded: true,\n width: \"auto\",\n titleAlign: \"left\",\n titlePadding: 2,\n contentPadding: 1,\n withGuide: false,\n formatBorder: (value) => ui.accent(value)\n }\n );\n}\n\nasync function executeCreateCommand(\n requestedName: string | undefined,\n options: CreateOptions\n): Promise<void> {\n const userConfig = await loadUserConfig();\n const catalog = await loadCatalog(userConfig);\n const template = await selectTemplate(catalog, options);\n const mode = await selectCreationMode(options);\n\n const defaultProjectName = defaultProjectNameFor(template.category);\n let rawProjectName = requestedName;\n if (mode === \"custom\" && !rawProjectName && !options.yes) {\n const answer = await prompts.text(\n projectNamePromptOptions(template.category)\n );\n if (prompts.isCancel(answer)) throw new UserCancelledError();\n rawProjectName = String(answer).trim() || defaultProjectName;\n }\n rawProjectName ??= defaultProjectName;\n const projectName = normalizeProjectName(rawProjectName);\n if (!projectName) {\n throw new Error(\"项目名称至少需要包含一个字母或数字\");\n }\n if (projectName !== rawProjectName) {\n prompts.log.info(`项目名称已规范化:${projectName}`);\n }\n\n const result = await generateProject(\n template,\n projectName,\n { ...options, customize: mode === \"custom\" },\n process.cwd(),\n userConfig\n );\n if (options.dryRun) {\n prompts.outro(\"Dry Run 完成,未写入任何项目文件\");\n return;\n }\n\n renderCompletion(projectName, mode, result);\n}\n\nexport async function createCommand(\n requestedName: string | undefined,\n options: CreateOptions\n): Promise<void> {\n prompts.intro(\n `${ui.brand()} ${ui.badge(\"CREATE\")} ${ui.muted(`v${CLI_VERSION}`)}`\n );\n try {\n await executeCreateCommand(requestedName, options);\n } catch (error) {\n if (error instanceof UserCancelledError) {\n prompts.cancel(\"已取消创建,未写入任何项目文件\");\n return;\n }\n throw error;\n }\n}\n","import { existsSync } from \"node:fs\";\nimport { rename, rm } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport * as prompts from \"@clack/prompts\";\nimport { satisfies } from \"semver\";\nimport { CLI_NAME, CLI_VERSION } from \"../constants.js\";\nimport { createBrandSpinner, ui } from \"../ui/theme.js\";\nimport {\n copyTemplateTree,\n isDirectoryEmpty,\n readJson,\n removePath,\n writeJson\n} from \"../utils/fs.js\";\nimport { runCommand } from \"../utils/process.js\";\nimport {\n acquireTemplateFromSources,\n resolveTemplateSources\n} from \"./template-source.js\";\nimport { UserCancelledError } from \"./errors.js\";\nimport { loadTemplateManifest } from \"./template-manifest.js\";\nimport { DEFAULT_USER_CONFIG } from \"./user-config.js\";\nimport type {\n CatalogTemplate,\n CreateOptions,\n ProjectInput,\n TemplateManifest,\n UserConfig\n} from \"../types.js\";\n\nconst ENV_NAMES = [\"dev\", \"sit\", \"uat\", \"pre\", \"prd\"] as const;\ntype PartialProjectInput = Partial<Omit<ProjectInput, \"environments\">> & {\n environments?: Partial<ProjectInput[\"environments\"]>;\n};\n\nexport function normalizeProjectName(value: string): string {\n return value\n .trim()\n .toLowerCase()\n .replace(/\\s+/g, \"-\")\n .replace(/^[._-]+/, \"\")\n .replace(/[^a-z0-9._-]+/g, \"-\")\n .replace(/-{2,}/g, \"-\")\n .replace(/[-._]+$/, \"\");\n}\n\nfunction ensureProjectName(value: string): string {\n const name = normalizeProjectName(value);\n if (!/^[a-z0-9][a-z0-9._-]*$/.test(name)) {\n throw new Error(\"项目名称至少需要包含一个字母或数字\");\n }\n return name;\n}\n\nfunction inferModuleName(projectName: string): string {\n const inferred = projectName\n .replace(/^(?:jh4j|wl)-ui-/, \"\")\n .replace(/[^a-z0-9-]/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n return /^[a-z][a-z0-9-]*$/.test(inferred) ? inferred : \"app\";\n}\n\nfunction ensureModuleName(value: string): string {\n const name = value.trim();\n if (!/^[a-z][a-z0-9-]*$/.test(name)) {\n throw new Error(\"模块标识必须以小写字母开头,只能包含小写字母、数字和连字符\");\n }\n return name;\n}\n\nfunction ensurePort(value: string | number): number {\n const port = Number(value);\n if (!Number.isInteger(port) || port < 1024 || port > 65535) {\n throw new Error(\"开发端口必须是 1024 到 65535 之间的整数\");\n }\n return port;\n}\n\nfunction ensureHttpUrl(value: string, label: string): string {\n try {\n const url = new URL(value);\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") throw new Error();\n return value.replace(/\\/+$/, \"\");\n } catch {\n throw new Error(`${label} 必须是 http/https URL`);\n }\n}\n\nasync function askText(\n message: string,\n initialValue: string,\n validate?: (value: string | undefined) => string | undefined\n): Promise<string> {\n const answer = await prompts.text({\n message,\n initialValue,\n defaultValue: initialValue,\n validate\n });\n if (prompts.isCancel(answer)) throw new UserCancelledError();\n return String(answer).trim() || initialValue;\n}\n\nasync function loadCreateConfig(\n configFile: string | undefined,\n cwd: string\n): Promise<PartialProjectInput> {\n if (!configFile) return {};\n const resolved = path.resolve(cwd, configFile);\n if (!existsSync(resolved)) throw new Error(`创建配置文件不存在: ${resolved}`);\n return readJson<PartialProjectInput>(resolved);\n}\n\nfunction parseFeatureIds(value: string): string[] {\n return [...new Set(value.split(\",\").map((item) => item.trim()).filter(Boolean))];\n}\n\nasync function collectTemplateFeatures(\n manifest: TemplateManifest,\n fileConfig: PartialProjectInput,\n options: CreateOptions\n): Promise<string[]> {\n const available = manifest.features ?? [];\n if (!available.length) return [];\n\n const knownIds = new Set(available.map((feature) => feature.id));\n let selected = options.features\n ? parseFeatureIds(options.features)\n : Array.isArray(fileConfig.features)\n ? fileConfig.features\n : available\n .filter((feature) => feature.defaultEnabled || feature.required)\n .map((feature) => feature.id);\n\n const unknown = selected.filter((id) => !knownIds.has(id));\n if (unknown.length) {\n throw new Error(\n `模板不支持以下能力: ${unknown.join(\", \")}。可用能力: ${[...knownIds].join(\", \")}`\n );\n }\n\n if (options.standards === false) {\n selected = selected.filter((id) => {\n const feature = available.find((item) => item.id === id);\n return feature?.package !== \"@robot-admin/git-standards\";\n });\n }\n\n for (const feature of available) {\n if (feature.required && !selected.includes(feature.id)) {\n selected.push(feature.id);\n }\n }\n return selected;\n}\n\nasync function collectProjectInput(\n projectName: string,\n sourceConfig: ProjectInput,\n fileConfig: PartialProjectInput,\n options: CreateOptions,\n userConfig: UserConfig,\n features: string[]\n): Promise<ProjectInput> {\n let moduleName = options.module ?? fileConfig.moduleName ?? inferModuleName(projectName);\n let title = options.title ?? fileConfig.title ?? sourceConfig.title;\n let port: string | number =\n options.port ?? fileConfig.devServerPort ?? sourceConfig.devServerPort;\n let npmRegistry =\n options.npmRegistry ??\n fileConfig.npmRegistry ??\n userConfig.npmRegistry ??\n sourceConfig.npmRegistry;\n let jhlcRegistry =\n options.jhlcRegistry ??\n fileConfig.jhlcRegistry ??\n userConfig.jhlcRegistry ??\n sourceConfig.jhlcRegistry;\n let localBackendUrl =\n options.localBackend ?? fileConfig.localBackendUrl ?? sourceConfig.localBackendUrl;\n let localPublicUrl =\n options.localPublic ?? fileConfig.localPublicUrl ?? sourceConfig.localPublicUrl;\n const environments = structuredClone(sourceConfig.environments);\n for (const [env, value] of Object.entries(fileConfig.environments ?? {})) {\n if (value && environments[env]) {\n environments[env] = { ...environments[env], ...value };\n }\n }\n\n if (options.customize && !options.yes) {\n title = await askText(ui.strong(\"应用标题\"), title, (value) =>\n value?.trim() ? undefined : \"应用标题不能为空\"\n );\n port = await askText(ui.strong(\"开发端口\"), String(port), (value) => {\n const parsed = Number(value);\n return Number.isInteger(parsed) && parsed >= 1024 && parsed <= 65535\n ? undefined\n : \"请输入 1024 到 65535 之间的端口\";\n });\n localBackendUrl = await askText(\n ui.strong(\"本地联调地址\"),\n localBackendUrl,\n (value) => {\n try {\n const url = new URL(value ?? \"\");\n return url.protocol === \"http:\" || url.protocol === \"https:\"\n ? undefined\n : \"请输入完整的 http/https 地址\";\n } catch {\n return \"请输入完整的 http/https 地址\";\n }\n }\n );\n }\n\n if (!title.trim()) throw new Error(\"系统标题不能为空\");\n for (const env of ENV_NAMES) {\n if (!environments[env]) throw new Error(`缺少 ${env.toUpperCase()} 环境配置`);\n environments[env] = {\n webUrl: ensureHttpUrl(environments[env].webUrl, `${env.toUpperCase()} 平台地址`),\n apiPrefix: environments[env].apiPrefix.replace(/^\\/+|\\/+$/g, \"\")\n };\n if (!environments[env].apiPrefix) {\n throw new Error(`${env.toUpperCase()} API 前缀不能为空`);\n }\n }\n\n return {\n projectName,\n moduleName: ensureModuleName(moduleName),\n title: title.trim(),\n devServerPort: ensurePort(port),\n npmRegistry: ensureHttpUrl(npmRegistry, \"npm registry\"),\n jhlcRegistry: ensureHttpUrl(jhlcRegistry, \"@jhlc 私有 registry\"),\n localBackendUrl: ensureHttpUrl(localBackendUrl, \"本地后端地址\"),\n localPublicUrl: ensureHttpUrl(localPublicUrl, \"本地 public 地址\"),\n environments,\n features\n };\n}\n\nfunction assertSafeTarget(cwd: string, target: string): void {\n if (path.dirname(target) !== cwd || target === cwd) {\n throw new Error(\"仅允许在当前目录创建一级项目目录\");\n }\n}\n\nasync function promoteStaging(\n stagingRoot: string,\n targetRoot: string,\n force: boolean\n): Promise<void> {\n const targetExists = existsSync(targetRoot);\n if (!targetExists) {\n await rename(stagingRoot, targetRoot);\n return;\n }\n\n if (!(await isDirectoryEmpty(targetRoot)) && !force) {\n throw new Error(`目标目录已存在且非空: ${targetRoot}`);\n }\n\n const backupRoot = `${targetRoot}.jh4j-backup-${Date.now()}`;\n await rename(targetRoot, backupRoot);\n try {\n await rename(stagingRoot, targetRoot);\n } catch (error) {\n await rename(backupRoot, targetRoot);\n throw error;\n }\n try {\n await removePath(backupRoot);\n } catch {\n prompts.log.warn(`旧目录备份未能自动清理: ${backupRoot}`);\n }\n}\n\nexport interface GenerateProjectResult {\n targetRoot: string;\n templateId: string;\n templateName: string;\n templateVersion: string;\n category: TemplateManifest[\"category\"];\n source: string;\n features: string[];\n installed: boolean;\n gitInitialized: boolean;\n configuration: Pick<\n ProjectInput,\n \"title\" | \"moduleName\" | \"devServerPort\" | \"localBackendUrl\"\n >;\n}\n\nexport async function generateProject(\n catalogTemplate: CatalogTemplate,\n requestedProjectName: string,\n options: CreateOptions,\n cwd = process.cwd(),\n configuredUserConfig: UserConfig = DEFAULT_USER_CONFIG\n): Promise<GenerateProjectResult> {\n const userConfig = { ...DEFAULT_USER_CONFIG, ...configuredUserConfig };\n const projectName = ensureProjectName(requestedProjectName);\n const resolvedCwd = path.resolve(cwd);\n const targetRoot = path.resolve(resolvedCwd, projectName);\n assertSafeTarget(resolvedCwd, targetRoot);\n if (\n existsSync(targetRoot) &&\n !(await isDirectoryEmpty(targetRoot)) &&\n !options.force\n ) {\n throw new Error(`目标目录已存在且非空: ${targetRoot}`);\n }\n\n const ref = options.ref ?? userConfig.templateRef ?? catalogTemplate.defaultRef;\n const sourceValues = resolveTemplateSources(\n catalogTemplate,\n options.source,\n userConfig.templateSource\n );\n const acquisitionSpinner = options.yes\n ? undefined\n : createBrandSpinner();\n acquisitionSpinner?.start(\"正在获取并校验模板\");\n let acquired: Awaited<ReturnType<typeof acquireTemplateFromSources>>;\n try {\n acquired = await acquireTemplateFromSources(sourceValues, ref, {\n noCache: options.cache === false,\n cacheTtlMinutes: userConfig.cacheTtlMinutes\n });\n acquisitionSpinner?.stop(\"模板已就绪\");\n } catch (error) {\n acquisitionSpinner?.error(\"模板获取失败\");\n throw error;\n }\n const stagingRoot = path.join(\n resolvedCwd,\n `.${projectName}.jh4j-tmp-${process.pid}-${Date.now()}`\n );\n let promoted = false;\n let generationSpinner: ReturnType<typeof prompts.spinner> | undefined;\n\n try {\n const manifest = await loadTemplateManifest(acquired.root);\n if (manifest.id !== catalogTemplate.id) {\n throw new Error(\n `模板 ID 不匹配:Catalog=${catalogTemplate.id},Manifest=${manifest.id}`\n );\n }\n if (!satisfies(process.versions.node, manifest.runtime.node)) {\n throw new Error(\n `当前 Node ${process.versions.node} 不满足模板要求 ${manifest.runtime.node}`\n );\n }\n\n const sourceProjectConfig = await readJson<\n Omit<ProjectInput, \"npmRegistry\" | \"jhlcRegistry\">\n >(path.join(acquired.root, \"project.config.json\"));\n const fileConfig = await loadCreateConfig(options.config, resolvedCwd);\n const features = await collectTemplateFeatures(manifest, fileConfig, options);\n const input = await collectProjectInput(\n projectName,\n {\n ...sourceProjectConfig,\n npmRegistry: manifest.defaults.npmRegistry,\n jhlcRegistry: manifest.defaults.jhlcRegistry\n },\n fileConfig,\n options,\n userConfig,\n features\n );\n\n const shouldInstall =\n !options.skipInstall && (options.install === true || userConfig.autoInstall);\n const shouldInitializeGit = !options.skipGit && userConfig.autoGit;\n\n if (options.dryRun) {\n prompts.note(\n [\n `模板: ${manifest.id}@${manifest.version}`,\n `来源: ${acquired.source}`,\n `目标: ${targetRoot}`,\n `模块: ${input.moduleName}`,\n `端口: ${input.devServerPort}`,\n `能力: ${input.features.length ? input.features.join(\", \") : \"无可选能力\"}`,\n `安装依赖: ${shouldInstall ? \"是\" : \"否\"}`,\n `初始化 Git: ${shouldInitializeGit ? \"是\" : \"否\"}`\n ].join(\"\\n\"),\n \"Dry Run\"\n );\n return {\n targetRoot,\n templateId: manifest.id,\n templateName: manifest.name,\n templateVersion: manifest.version,\n category: manifest.category,\n source: acquired.source,\n features: input.features,\n installed: false,\n gitInitialized: false,\n configuration: {\n title: input.title,\n moduleName: input.moduleName,\n devServerPort: input.devServerPort,\n localBackendUrl: input.localBackendUrl\n }\n };\n }\n\n generationSpinner = options.yes\n ? undefined\n : createBrandSpinner();\n generationSpinner?.start(\"正在生成项目文件\");\n await copyTemplateTree(acquired.root, stagingRoot);\n const inputFile = path.join(stagingRoot, \".jh4j-cli-input.json\");\n await writeJson(inputFile, input);\n try {\n await runCommand(\n process.execPath,\n [\n path.join(stagingRoot, \"scripts\", \"setup-project.mjs\"),\n \"--yes\",\n \"--config\",\n inputFile,\n \"--created-by\",\n `${CLI_NAME}@${CLI_VERSION}`\n ],\n { cwd: stagingRoot, stdio: \"pipe\" }\n );\n } finally {\n await rm(inputFile, { force: true });\n }\n\n if (!existsSync(path.join(stagingRoot, manifest.generatedMetadata))) {\n throw new Error(`模板初始化未生成元数据: ${manifest.generatedMetadata}`);\n }\n await promoteStaging(stagingRoot, targetRoot, Boolean(options.force));\n promoted = true;\n\n let gitInitialized = false;\n if (shouldInitializeGit) {\n generationSpinner?.message(\"正在初始化 Git main 仓库\");\n await runCommand(\"git\", [\"init\", \"-b\", \"main\"], {\n cwd: targetRoot,\n stdio: \"pipe\"\n });\n gitInitialized = true;\n }\n\n if (shouldInstall) {\n generationSpinner?.message(\"正在安装项目依赖\");\n try {\n await runCommand(\"pnpm\", [\"install\"], {\n cwd: targetRoot,\n stdio: \"pipe\"\n });\n } catch (error) {\n throw new Error(\n `项目已生成,但依赖安装失败;目录已保留在 ${targetRoot}\\n${(error as Error).message}`\n );\n }\n }\n\n let initialCommitWarning: string | undefined;\n if (shouldInitializeGit) {\n generationSpinner?.message(\"正在创建初始提交\");\n await runCommand(\"git\", [\"add\", \"-A\"], { cwd: targetRoot, stdio: \"pipe\" });\n try {\n await runCommand(\n \"git\",\n [\"commit\", \"-m\", `feat(init): 基于 ${manifest.id}@${manifest.version} 初始化`],\n {\n cwd: targetRoot,\n stdio: \"pipe\",\n env: { HUSKY: \"0\" }\n }\n );\n } catch (error) {\n initialCommitWarning = `Git 已初始化,但初始提交未完成:${(error as Error).message}`;\n }\n }\n\n generationSpinner?.stop(\"项目文件初始化完成\");\n if (initialCommitWarning) prompts.log.warn(initialCommitWarning);\n\n return {\n targetRoot,\n templateId: manifest.id,\n templateName: manifest.name,\n templateVersion: manifest.version,\n category: manifest.category,\n source: acquired.source,\n features: input.features,\n installed: shouldInstall,\n gitInitialized,\n configuration: {\n title: input.title,\n moduleName: input.moduleName,\n devServerPort: input.devServerPort,\n localBackendUrl: input.localBackendUrl\n }\n };\n } catch (error) {\n generationSpinner?.error(\n promoted ? \"项目已生成,后续步骤未完成\" : \"项目生成失败\"\n );\n throw error;\n } finally {\n if (!promoted && existsSync(stagingRoot)) await removePath(stagingRoot);\n await acquired.cleanup();\n }\n}\n","import { stdout } from \"node:process\";\nimport { styleText } from \"node:util\";\nimport * as prompts from \"@clack/prompts\";\n\nconst BRAND_START = [34, 211, 238] as const;\nconst BRAND_END = [99, 102, 241] as const;\nconst SPINNER_FRAMES = [\"⠋\", \"⠙\", \"⠹\", \"⠸\", \"⠼\", \"⠴\", \"⠦\", \"⠧\", \"⠇\", \"⠏\"];\n\nfunction supportsTrueColor(): boolean {\n if (process.env.FORCE_COLOR === \"0\") return false;\n if (Number(process.env.FORCE_COLOR) >= 3) return true;\n if (\n process.env.NO_COLOR !== undefined ||\n process.env.NODE_DISABLE_COLORS !== undefined\n ) {\n return false;\n }\n return Boolean(stdout.isTTY && stdout.getColorDepth?.() >= 24);\n}\n\nfunction interpolate(start: number, end: number, ratio: number): number {\n return Math.round(start + (end - start) * ratio);\n}\n\nfunction gradient(text: string): string {\n if (!supportsTrueColor()) return styleText([\"bold\", \"cyan\"], text);\n const characters = [...text];\n const denominator = Math.max(characters.length - 1, 1);\n return characters\n .map((character, index) => {\n if (/\\s/.test(character)) return character;\n const ratio = index / denominator;\n const red = interpolate(BRAND_START[0], BRAND_END[0], ratio);\n const green = interpolate(BRAND_START[1], BRAND_END[1], ratio);\n const blue = interpolate(BRAND_START[2], BRAND_END[2], ratio);\n return `\\u001B[1;38;2;${red};${green};${blue}m${character}\\u001B[0m`;\n })\n .join(\"\");\n}\n\nfunction paint(\n format: Parameters<typeof styleText>[0],\n text: string\n): string {\n return styleText(format, text, { stream: stdout });\n}\n\nexport const ui = {\n brand: () => gradient(\"JH4J CLOUD\"),\n badge: (text: string) => paint([\"bold\", \"black\", \"bgCyan\"], ` ${text} `),\n accent: (text: string) => paint(\"cyan\", text),\n secondary: (text: string) => paint(\"blueBright\", text),\n success: (text: string) => paint(\"green\", text),\n warning: (text: string) => paint(\"yellow\", text),\n danger: (text: string) => paint(\"red\", text),\n muted: (text: string) => paint(\"dim\", text),\n strong: (text: string) => paint(\"bold\", text),\n command: (text: string) => paint([\"bold\", \"cyan\"], text)\n};\n\nexport function createBrandSpinner(): ReturnType<typeof prompts.spinner> {\n return prompts.spinner({\n frames: SPINNER_FRAMES,\n delay: 80,\n styleFrame: (frame) => ui.accent(frame)\n });\n}\n","export class UserCancelledError extends Error {\n constructor() {\n super(\"用户取消创建\");\n this.name = \"UserCancelledError\";\n }\n}\n","import path from \"node:path\";\nimport { readJson } from \"../utils/fs.js\";\nimport type { TemplateManifest } from \"../types.js\";\n\nexport async function loadTemplateManifest(\n templateRoot: string\n): Promise<TemplateManifest> {\n const manifest = await readJson<TemplateManifest>(\n path.join(templateRoot, \"template.manifest.json\")\n );\n const errors: string[] = [];\n\n if (manifest.schemaVersion !== 1) errors.push(\"schemaVersion 必须为 1\");\n if (!manifest.id) errors.push(\"缺少模板 id\");\n if (!manifest.name) errors.push(\"缺少模板名称\");\n if (!/^\\d+\\.\\d+\\.\\d+([+-].+)?$/.test(manifest.version ?? \"\")) {\n errors.push(\"模板 version 不是有效的语义化版本\");\n }\n if (!manifest.runtime?.node || !manifest.runtime?.packageManager) {\n errors.push(\"缺少模板运行时约束\");\n }\n if (!manifest.entry?.nonInteractive) {\n errors.push(\"缺少非交互初始化入口\");\n }\n const featureIds = new Set<string>();\n for (const feature of manifest.features ?? []) {\n if (!/^[a-z][a-z0-9-]*$/.test(feature.id)) {\n errors.push(`模板能力 id 无效: ${feature.id}`);\n }\n if (featureIds.has(feature.id)) {\n errors.push(`模板能力 id 重复: ${feature.id}`);\n }\n featureIds.add(feature.id);\n if (!feature.name || !feature.description) {\n errors.push(`模板能力 ${feature.id} 缺少名称或说明`);\n }\n }\n\n if (errors.length) {\n throw new Error(`模板 manifest 无效:\\n- ${errors.join(\"\\n- \")}`);\n }\n return manifest;\n}\n","import { existsSync } from \"node:fs\";\nimport { mkdir, writeFile, rm } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { coerce, gte, satisfies } from \"semver\";\nimport { loadCatalog } from \"../catalog.js\";\nimport { loadTemplateManifest } from \"../core/template-manifest.js\";\nimport { resolveTemplateSources } from \"../core/template-source.js\";\nimport { getJh4jHome, loadUserConfig } from \"../core/user-config.js\";\nimport { inspectCommand } from \"../utils/process.js\";\nimport type { CatalogTemplate, UserConfig } from \"../types.js\";\n\nexport interface CheckResult {\n name: string;\n ok: boolean;\n detail: string;\n}\n\nasync function checkHomeWritable(): Promise<CheckResult> {\n const home = getJh4jHome();\n const probe = path.join(home, `.write-probe-${process.pid}`);\n try {\n await mkdir(home, { recursive: true });\n await writeFile(probe, \"ok\", \"utf8\");\n await rm(probe, { force: true });\n return { name: \"JH4J_HOME\", ok: true, detail: home };\n } catch (error) {\n return { name: \"JH4J_HOME\", ok: false, detail: (error as Error).message };\n }\n}\n\nexport async function collectDoctorChecks(\n suppliedConfig?: UserConfig,\n suppliedCatalog?: CatalogTemplate[]\n): Promise<CheckResult[]> {\n const config = suppliedConfig ?? (await loadUserConfig());\n const catalog = suppliedCatalog ?? (await loadCatalog(config));\n const [git, pnpm, home] = await Promise.all([\n inspectCommand(\"git\"),\n inspectCommand(\"pnpm\"),\n checkHomeWritable()\n ]);\n const pnpmVersion = coerce(pnpm.output)?.version;\n const checks: CheckResult[] = [\n {\n name: \"Node.js\",\n ok: satisfies(process.versions.node, \"^22.12.0 || ^24.0.0\"),\n detail: `${process.versions.node}(要求 Node 22.12+ 或 24.x)`\n },\n { name: \"Git\", ok: git.ok, detail: git.output },\n {\n name: \"pnpm\",\n ok: pnpm.ok && Boolean(pnpmVersion && gte(pnpmVersion, \"11.8.0\")),\n detail: pnpm.output\n },\n home\n ];\n\n for (const template of catalog) {\n const sources = resolveTemplateSources(\n template,\n undefined,\n config.templateSource\n );\n const source = sources[0];\n if (!existsSync(source)) {\n checks.push({\n name: `模板 ${template.id}`,\n ok:\n source.startsWith(\"http://\") ||\n source.startsWith(\"https://\") ||\n source.startsWith(\"git@\"),\n detail: `远程候选源(创建时依次验证): ${sources.join(\" → \")}`\n });\n continue;\n }\n try {\n const manifest = await loadTemplateManifest(source);\n checks.push({\n name: `模板 ${template.id}`,\n ok:\n manifest.id === template.id &&\n satisfies(process.versions.node, manifest.runtime.node),\n detail: `${manifest.id}@${manifest.version} (${source})`\n });\n } catch (error) {\n checks.push({\n name: `模板 ${template.id}`,\n ok: false,\n detail: (error as Error).message\n });\n }\n }\n return checks;\n}\n\nexport async function doctorCommand(options: { json?: boolean } = {}): Promise<void> {\n const checks = await collectDoctorChecks();\n const failed = checks.filter((check) => !check.ok);\n if (options.json) {\n console.log(JSON.stringify({ ok: failed.length === 0, checks }, null, 2));\n } else {\n for (const check of checks) {\n console.log(`${check.ok ? \"✓\" : \"✗\"} ${check.name}: ${check.detail}`);\n }\n console.log(`\\n结果: ${checks.length - failed.length} 通过, ${failed.length} 失败`);\n }\n if (failed.length) process.exitCode = 1;\n}\n","import path from \"node:path\";\nimport { existsSync } from \"node:fs\";\nimport { readJson } from \"../utils/fs.js\";\nimport type { ProjectMetadata } from \"../types.js\";\n\nexport async function infoCommand(\n projectPath = process.cwd(),\n options: { json?: boolean } = {}\n): Promise<void> {\n const root = path.resolve(projectPath);\n const metadataPath = path.join(root, \".jhlc\", \"project.json\");\n if (!existsSync(metadataPath)) {\n throw new Error(`当前目录不是 JH4J CLI 创建的项目: ${metadataPath}`);\n }\n const metadata = await readJson<ProjectMetadata>(metadataPath);\n if (options.json) {\n console.log(JSON.stringify({ projectRoot: root, ...metadata }, null, 2));\n return;\n }\n console.log(`项目目录: ${root}`);\n console.log(`模板: ${metadata.template.id}@${metadata.template.version}`);\n console.log(`平台版本: ${metadata.platformVersion ?? \"未声明\"}`);\n console.log(`创建时间: ${metadata.createdAt}`);\n console.log(`创建工具: ${metadata.createdBy}`);\n console.log(\"项目参数:\");\n console.log(JSON.stringify(metadata.parameters, null, 2));\n}\n","import { loadCatalog } from \"../catalog.js\";\nimport { loadUserConfig } from \"../core/user-config.js\";\n\nexport async function listCommand(options: { json?: boolean } = {}): Promise<void> {\n const templates = await loadCatalog(await loadUserConfig());\n if (options.json) {\n console.log(JSON.stringify(templates, null, 2));\n return;\n }\n console.table(\n templates.map((template) => ({\n ID: template.id,\n 名称: template.name,\n 类型: template.category,\n 状态: template.status,\n 默认分支: template.defaultRef,\n 标签: template.tags?.join(\", \") ?? \"\"\n }))\n );\n}\n","import path from \"node:path\";\nimport { loadTemplateManifest } from \"../core/template-manifest.js\";\nimport { runCommand } from \"../utils/process.js\";\n\nexport async function validateTemplateCommand(templatePath: string): Promise<void> {\n const root = path.resolve(templatePath);\n const manifest = await loadTemplateManifest(root);\n await runCommand(process.execPath, [path.join(root, \"scripts\", \"validate-template.mjs\")], {\n cwd: root\n });\n console.log(`模板可用: ${manifest.id}@${manifest.version}`);\n}\n","import {\n DEFAULT_USER_CONFIG,\n getUserConfigPath,\n loadUserConfig,\n parseUserConfigValue,\n saveUserConfig\n} from \"../core/user-config.js\";\n\nexport async function configListCommand(options: { json?: boolean } = {}): Promise<void> {\n const config = await loadUserConfig();\n if (options.json) console.log(JSON.stringify(config, null, 2));\n else console.table(Object.entries(config).map(([key, value]) => ({ key, value })));\n console.log(`配置文件: ${getUserConfigPath()}`);\n}\n\nexport async function configGetCommand(key: string): Promise<void> {\n const config = await loadUserConfig();\n if (!(key in config)) throw new Error(`配置项不存在: ${key}`);\n console.log(String((config as unknown as Record<string, unknown>)[key]));\n}\n\nexport async function configSetCommand(key: string, value: string): Promise<void> {\n const config = await loadUserConfig();\n const [typedKey, typedValue] = parseUserConfigValue(key, value);\n (config as unknown as Record<string, unknown>)[typedKey] = typedValue;\n await saveUserConfig(config);\n console.log(`已设置 ${typedKey}=${String(typedValue)}`);\n}\n\nexport async function configUnsetCommand(key: string): Promise<void> {\n const config = await loadUserConfig();\n if (!(key in DEFAULT_USER_CONFIG) && !(key in config)) {\n throw new Error(`配置项不存在: ${key}`);\n }\n const defaults = DEFAULT_USER_CONFIG as unknown as Record<string, unknown>;\n const mutable = config as unknown as Record<string, unknown>;\n if (key in defaults) mutable[key] = defaults[key];\n else delete mutable[key];\n await saveUserConfig(config);\n console.log(`已重置配置项: ${key}`);\n}\n\nexport async function configResetCommand(): Promise<void> {\n await saveUserConfig({ ...DEFAULT_USER_CONFIG });\n console.log(`用户配置已恢复默认值: ${getUserConfigPath()}`);\n}\n","import {\n clearTemplateCache,\n getTemplateCacheRoot,\n listTemplateCache\n} from \"../core/template-cache.js\";\n\nfunction formatBytes(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 ** 2) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / 1024 ** 2).toFixed(1)} MB`;\n}\n\nexport async function cacheListCommand(options: { json?: boolean } = {}): Promise<void> {\n const entries = await listTemplateCache();\n if (options.json) {\n console.log(JSON.stringify(entries, null, 2));\n return;\n }\n if (!entries.length) {\n console.log(`模板缓存为空: ${getTemplateCacheRoot()}`);\n return;\n }\n console.table(\n entries.map((entry) => ({\n Key: entry.key,\n 来源: entry.metadata.source,\n Ref: entry.metadata.ref,\n 缓存时间: entry.metadata.cachedAt,\n 大小: formatBytes(entry.sizeBytes)\n }))\n );\n}\n\nexport async function cacheClearCommand(): Promise<void> {\n await clearTemplateCache();\n console.log(`模板缓存已清理: ${getTemplateCacheRoot()}`);\n}\n"],"mappings":"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","names":["prompts","path","existsSync","readdir","existsSync","path","path","existsSync","mkdir","readdir","rename","rm","writeFile","existsSync","mkdir","stat","path","path","existsSync","path","existsSync","path","existsSync","mkdir","stat","existsSync","path","readdir","rename","rm","writeFile","mkdir","prompts","existsSync","rename","rm","path","prompts","text","path","path","path","existsSync","rename","rm","selected","existsSync","mkdir","writeFile","rm","path","satisfies","path","mkdir","writeFile","rm","satisfies","existsSync","path","existsSync","path","existsSync","path","path","config"]}
|