gz-cli-front 1.0.2 → 1.0.3-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # gz-cli-front
2
2
 
3
- 一个轻量级的现代前端脚手架工具,支持远程模板和内置微应用模板初始化。
3
+ 一个轻量级的现代前端脚手架工具,支持远程模板和内置模板初始化。
4
4
 
5
5
  npm 包名为 `gz-cli-front`,安装后使用 `gz-cli` 命令。
6
6
 
@@ -40,7 +40,12 @@ gz-cli init demo-app
40
40
 
41
41
  ### 内网初始化
42
42
 
43
- 从 `1.0.2` 起,无法访问 GitHub 时,可直接使用随 CLI 发布的微应用模板:
43
+ 从 `1.0.2` 起,无法访问 GitHub 时,可使用随 CLI 发布的内置模板。
44
+ 测试版 `1.0.3-beta.0` 新增主应用模板,测试时先安装指定版本:
45
+
46
+ ```bash
47
+ npm install -g gz-cli-front@1.0.3-beta.0
48
+ ```
44
49
 
45
50
  ```bash
46
51
  gz-cli init demo-app --internal
@@ -48,8 +53,9 @@ gz-cli init demo-app --internal
48
53
  gz-cli init demo-app -i
49
54
  ```
50
55
 
51
- 内网模式跳过远程模板列表和模板下载,直接生成内置 `micro-app`;不提供主应用模板,
52
- 也不会因网络失败自动切换模式。`create` 兼容命令同样支持此参数。
56
+ 内网模式跳过远程模板列表和模板下载,可选择内置 `micro-app` 或 `main-app`,默认选中微应用。
57
+ 正式版 `1.0.2` 仍只提供微应用模板。普通模式不会因网络失败自动切换为内网模式,
58
+ `create` 兼容命令同样支持此参数。
53
59
  `--internal` 与 `--refresh` 不能同时使用,内置模板随 CLI 版本更新。
54
60
 
55
61
  生成项目不需要访问 GitHub;CLI 和项目依赖安装仍需可用的 npm 源。初始化时可选择暂不
@@ -141,21 +147,25 @@ gz-cli init demo-app --refresh
141
147
 
142
148
  公共仓库建议使用 `source: "git"` 和 HTTPS clone URL,避免要求使用者配置 SSH Key。CLI 会按配置的协议执行浅克隆;`source` 仍兼容 `github`、`gitlab` 和 `git`,旧的 GitHub `repo` 配置也可继续使用。
143
149
 
144
- ### 更新内置微应用模板
150
+ ### 更新内置模板
145
151
 
146
- 外部 `gg-cli-template-micro-app` 仓库仍是模板维护源。提交模板改动后,在 CLI 仓库执行:
152
+ 外部 `gg-cli-template-micro-app` 和 `gg-cli-template-main-app` 仓库仍是模板维护源。
153
+ 提交模板改动后,在 CLI 仓库按需同步:
147
154
 
148
155
  ```bash
149
156
  npm run sync:template
157
+ npm run sync:template:main
150
158
  npm run test:release
151
159
  ```
152
160
 
153
- 同步脚本默认读取同级 `gg-cli-template-micro-app` 仓库的已提交版本,仅导出 Git 已跟踪
154
- 内容到 `template/micro-app`,来源 commit 记录在 `template/micro-app.snapshot.json`。
161
+ `sync:template` 同步微应用,`sync:template:main` 同步主应用;两者独立执行,不会更新另一份快照。
162
+ 同步脚本读取同级模板仓库的已提交版本,仅导出 Git 已跟踪内容到 `template/<模板名>`,
163
+ 来源 commit 记录在 `template/<模板名>.snapshot.json`。
155
164
  未提交改动会阻止同步;`node_modules`、构建产物和本机配置不会从工作目录复制进来。
156
- 其他位置的模板仓库可通过 `npm run sync:template -- <仓库路径>` 指定。
165
+ 其他位置的仓库可通过 `npm run sync:template -- <仓库路径>` 或
166
+ `npm run sync:template:main -- <仓库路径>` 指定。
157
167
 
158
- 构建时将快照压缩到 `dist/template/micro-app.tar.gz`,保留 `.gitignore`、`.npmrc` 等模板
168
+ 构建时将快照压缩到 `dist/template/<模板名>.tar.gz`,保留 `.gitignore`、`.npmrc` 等模板
159
169
  文件。日常构建和发布只使用仓库中已有的快照,不要求本机存在外部模板仓库。
160
170
  请勿直接修改快照,也不要将旧的 `src/template` 目录作为内网模板。
161
171
 
package/dist/index.js CHANGED
@@ -979,11 +979,11 @@ async function downloadFromGitHub(template, targetDir, options) {
979
979
  const repository = normalizeGitHubRepository(getTemplateUrl(template));
980
980
  const version = template.version && template.version !== "latest" ? template.version : void 0;
981
981
  const sourceKey = `${repository}${version ? `#${version}` : "#latest"}`;
982
- const archivePath2 = getTemplateArchiveCachePath(sourceKey);
982
+ const archivePath = getTemplateArchiveCachePath(sourceKey);
983
983
  const archive = await ensureGitHubArchive(
984
984
  repository,
985
985
  version,
986
- archivePath2,
986
+ archivePath,
987
987
  options.forceRefresh === true
988
988
  );
989
989
  const extractStartedAt = performance4.now();
@@ -991,7 +991,7 @@ async function downloadFromGitHub(template, targetDir, options) {
991
991
  try {
992
992
  await extractTar({
993
993
  cwd: targetDir,
994
- file: archivePath2,
994
+ file: archivePath,
995
995
  preservePaths: false,
996
996
  strict: true,
997
997
  strip: 1
@@ -1000,7 +1000,7 @@ async function downloadFromGitHub(template, targetDir, options) {
1000
1000
  if (!archive.cacheHit) {
1001
1001
  throw error;
1002
1002
  }
1003
- await fs5.remove(archivePath2);
1003
+ await fs5.remove(archivePath);
1004
1004
  await fs5.emptyDir(targetDir);
1005
1005
  return downloadFromGitHub(template, targetDir, { forceRefresh: true });
1006
1006
  }
@@ -1034,9 +1034,9 @@ async function downloadFromGit(template, targetDir, options) {
1034
1034
  route: repository.route
1035
1035
  };
1036
1036
  }
1037
- async function ensureGitHubArchive(repository, version, archivePath2, forceRefresh) {
1037
+ async function ensureGitHubArchive(repository, version, archivePath, forceRefresh) {
1038
1038
  const startedAt = performance4.now();
1039
- if (!forceRefresh && await canUseArchiveCache(archivePath2, Boolean(version))) {
1039
+ if (!forceRefresh && await canUseArchiveCache(archivePath, Boolean(version))) {
1040
1040
  return {
1041
1041
  cacheHit: true,
1042
1042
  downloadMs: Math.round(performance4.now() - startedAt),
@@ -1049,11 +1049,11 @@ async function ensureGitHubArchive(repository, version, archivePath2, forceRefre
1049
1049
  retries: 1,
1050
1050
  timeoutMs: TEMPLATE_DOWNLOAD_TIMEOUT_MS
1051
1051
  });
1052
- const temporaryPath = `${archivePath2}.${randomUUID2()}.tmp`;
1053
- await fs5.ensureDir(path6.dirname(archivePath2));
1052
+ const temporaryPath = `${archivePath}.${randomUUID2()}.tmp`;
1053
+ await fs5.ensureDir(path6.dirname(archivePath));
1054
1054
  try {
1055
1055
  await fs5.writeFile(temporaryPath, response.body);
1056
- await fs5.move(temporaryPath, archivePath2, { overwrite: true });
1056
+ await fs5.move(temporaryPath, archivePath, { overwrite: true });
1057
1057
  } finally {
1058
1058
  await fs5.remove(temporaryPath);
1059
1059
  }
@@ -1076,9 +1076,9 @@ function createGitHubArchiveRequest(repository, version) {
1076
1076
  url: `https://codeload.github.com/${repository}/tar.gz/${encodeURIComponent(version ?? "HEAD")}`
1077
1077
  };
1078
1078
  }
1079
- async function canUseArchiveCache(archivePath2, immutableVersion) {
1079
+ async function canUseArchiveCache(archivePath, immutableVersion) {
1080
1080
  try {
1081
- const stats = await fs5.stat(archivePath2);
1081
+ const stats = await fs5.stat(archivePath);
1082
1082
  return stats.isFile() && (immutableVersion || isCacheFresh(stats.mtimeMs, TEMPLATE_ARCHIVE_CACHE_TTL_MS));
1083
1083
  } catch {
1084
1084
  return false;
@@ -1198,35 +1198,45 @@ import { fileURLToPath as fileURLToPath2 } from "url";
1198
1198
  import { performance as performance5 } from "perf_hooks";
1199
1199
  import { x as extractTar2 } from "tar";
1200
1200
  var assetDirectory = fileURLToPath2(new URL("./template/", import.meta.url));
1201
- var archivePath = path7.join(assetDirectory, "micro-app.tar.gz");
1202
- async function loadInternalTemplate() {
1201
+ var definitions = [
1202
+ { name: "micro-app", label: "\u5FAE\u5E94\u7528\u6A21\u677F\uFF08\u5185\u7F6E\uFF09", type: "micro", title: "\u5FAE\u5E94\u7528" },
1203
+ { name: "main-app", label: "\u4E3B\u5E94\u7528\u6A21\u677F\uFF08\u5185\u7F6E\uFF09", type: "main", title: "\u4E3B\u5E94\u7528" }
1204
+ ];
1205
+ async function loadInternalTemplates() {
1206
+ return Promise.all(definitions.map(loadInternalTemplate));
1207
+ }
1208
+ async function loadInternalTemplate(definition) {
1203
1209
  try {
1204
- const snapshot = await fs6.readJson(path7.join(assetDirectory, "micro-app.snapshot.json"));
1210
+ const snapshot = await fs6.readJson(path7.join(assetDirectory, `${definition.name}.snapshot.json`));
1205
1211
  if (typeof snapshot !== "object" || snapshot === null || !("commit" in snapshot) || typeof snapshot.commit !== "string" || !/^[a-f\d]{40}$/.test(snapshot.commit)) {
1206
1212
  throw new Error("\u5185\u7F6E\u6A21\u677F\u6765\u6E90\u7248\u672C\u65E0\u6548");
1207
1213
  }
1208
- if (!(await fs6.stat(archivePath)).isFile()) {
1214
+ if (!(await fs6.stat(path7.join(assetDirectory, `${definition.name}.tar.gz`))).isFile()) {
1209
1215
  throw new Error("\u5185\u7F6E\u6A21\u677F\u6587\u4EF6\u65E0\u6548");
1210
1216
  }
1211
1217
  return {
1212
- name: "micro-app",
1213
- label: "\u5FAE\u5E94\u7528\u6A21\u677F\uFF08\u5185\u7F6E\uFF09",
1214
- description: "\u968F CLI \u53D1\u5E03\u7684 gg-cli-template-micro-app \u6A21\u677F\u5FEB\u7167",
1215
- type: "micro",
1218
+ name: definition.name,
1219
+ label: definition.label,
1220
+ description: `\u968F CLI \u53D1\u5E03\u7684 gg-cli-template-${definition.name} \u6A21\u677F\u5FEB\u7167`,
1221
+ type: definition.type,
1216
1222
  version: snapshot.commit
1217
1223
  };
1218
1224
  } catch (error) {
1219
1225
  const message = error instanceof Error ? error.message : "\u672A\u77E5\u9519\u8BEF";
1220
- throw new Error(`\u5185\u7F6E\u5FAE\u5E94\u7528\u6A21\u677F\u4E0D\u53EF\u7528\uFF0C\u8BF7\u91CD\u65B0\u5B89\u88C5 gz-cli-front\u3002
1226
+ throw new Error(`\u5185\u7F6E${definition.title}\u6A21\u677F\u4E0D\u53EF\u7528\uFF0C\u8BF7\u91CD\u65B0\u5B89\u88C5 gz-cli-front\u3002
1221
1227
  ${message}`);
1222
1228
  }
1223
1229
  }
1224
- async function copyInternalTemplate(targetDir) {
1230
+ async function copyInternalTemplate(template, targetDir) {
1231
+ const definition = definitions.find(({ name }) => name === template.name);
1232
+ if (!definition) {
1233
+ throw new Error(`\u4E0D\u652F\u6301\u7684\u5185\u7F6E\u6A21\u677F\uFF1A${template.name}`);
1234
+ }
1225
1235
  const startedAt = performance5.now();
1226
1236
  await fs6.ensureDir(targetDir);
1227
1237
  await extractTar2({
1228
1238
  cwd: targetDir,
1229
- file: archivePath,
1239
+ file: path7.join(assetDirectory, `${definition.name}.tar.gz`),
1230
1240
  preservePaths: false,
1231
1241
  strict: true
1232
1242
  });
@@ -1273,7 +1283,7 @@ async function create(projectName, options = {}) {
1273
1283
  async function createInitContext(projectName, options, templateTiming) {
1274
1284
  const finalProjectName = await getProjectName(projectName);
1275
1285
  const templates = await loadTemplates(templateTiming, options);
1276
- const template = options.internal ? templates[0] : await chooseTemplate(templates);
1286
+ const template = await chooseTemplate(templates);
1277
1287
  return {
1278
1288
  projectName: finalProjectName,
1279
1289
  template,
@@ -1292,11 +1302,11 @@ async function getProjectName(projectName) {
1292
1302
  async function loadTemplates(templateTiming, options) {
1293
1303
  if (options.internal) {
1294
1304
  const startedAt = performance6.now();
1295
- const template = await loadInternalTemplate();
1305
+ const templates = await loadInternalTemplates();
1296
1306
  templateTiming.configRoute = "bundled";
1297
1307
  templateTiming.fetchConfigMs = Math.round(performance6.now() - startedAt);
1298
- console.log(chalk2.cyan(`\u5185\u7F51\u6A21\u5F0F\uFF1A\u4F7F\u7528\u5185\u7F6E\u5FAE\u5E94\u7528\u6A21\u677F\uFF08${template.version?.slice(0, 8)}\uFF09\uFF0C\u4E0D\u8BBF\u95EE\u8FDC\u7A0B\u6A21\u677F\u4ED3\u5E93\u3002`));
1299
- return [template];
1308
+ console.log(chalk2.cyan("\u5185\u7F51\u6A21\u5F0F\uFF1A\u4F7F\u7528\u5185\u7F6E\u6A21\u677F\uFF0C\u4E0D\u8BBF\u95EE\u8FDC\u7A0B\u6A21\u677F\u4ED3\u5E93\u3002"));
1309
+ return templates;
1300
1310
  }
1301
1311
  const spinner = createStableSpinner();
1302
1312
  try {
@@ -1368,8 +1378,8 @@ async function downloadAndGenerate(context, targetPath, templateTiming, options)
1368
1378
  const spinner = createStableSpinner();
1369
1379
  const downloadStartedAt = performance6.now();
1370
1380
  try {
1371
- spinner.start(options.internal ? "\u6B63\u5728\u590D\u5236\u5185\u7F6E\u5FAE\u5E94\u7528\u6A21\u677F..." : `\u6B63\u5728\u4E0B\u8F7D\u6A21\u677F ${template.label}...`);
1372
- const downloadTiming = options.internal ? await copyInternalTemplate(targetPath) : await downloadTemplate(template, targetPath, {
1381
+ spinner.start(options.internal ? `\u6B63\u5728\u590D\u5236${template.label}...` : `\u6B63\u5728\u4E0B\u8F7D\u6A21\u677F ${template.label}...`);
1382
+ const downloadTiming = options.internal ? await copyInternalTemplate(template, targetPath) : await downloadTemplate(template, targetPath, {
1373
1383
  forceRefresh: options.refresh === true
1374
1384
  });
1375
1385
  assignDownloadTiming(templateTiming, downloadTiming);
@@ -1514,10 +1524,10 @@ var require2 = createRequire(import.meta.url);
1514
1524
  var packageMetadata = require2("../package.json");
1515
1525
  var packageVersion = getPackageVersion(packageMetadata);
1516
1526
  program.name("gz-cli").description("\u524D\u7AEF\u811A\u624B\u67B6\u5DE5\u5177").version(packageVersion);
1517
- program.command("init [project-name]", { isDefault: true }).description("\u521B\u5EFA\u4E00\u4E2A\u65B0\u9879\u76EE").addOption(new Option("-i, --internal", "\u4F7F\u7528\u5185\u7F6E\u5FAE\u5E94\u7528\u6A21\u677F\uFF0C\u4E0D\u8BBF\u95EE\u8FDC\u7A0B\u6A21\u677F\u4ED3\u5E93").conflicts("refresh")).option("--pm <package-manager>", "\u6307\u5B9A\u5305\u7BA1\u7406\u5668\uFF1Anpm\u3001pnpm \u6216 yarn").option("--proxy <url>", "\u6307\u5B9A\u672C\u6B21\u521D\u59CB\u5316\u4F7F\u7528\u7684 HTTP(S) \u4EE3\u7406").option("--no-proxy", "\u5F3A\u5236\u76F4\u8FDE\uFF0C\u4E0D\u8BFB\u53D6\u73AF\u5883\u53D8\u91CF\u6216\u7CFB\u7EDF\u4EE3\u7406").option("--refresh", "\u5FFD\u7565\u6A21\u677F\u914D\u7F6E\u548C\u6A21\u677F\u7F13\u5B58\uFF0C\u5F3A\u5236\u4ECE\u8FDC\u7A0B\u4ED3\u5E93\u5237\u65B0").action((projectName, options) => {
1527
+ program.command("init [project-name]", { isDefault: true }).description("\u521B\u5EFA\u4E00\u4E2A\u65B0\u9879\u76EE").addOption(new Option("-i, --internal", "\u9009\u62E9\u5185\u7F6E\u4E3B\u5E94\u7528\u6216\u5FAE\u5E94\u7528\u6A21\u677F\uFF0C\u4E0D\u8BBF\u95EE\u8FDC\u7A0B\u6A21\u677F\u4ED3\u5E93").conflicts("refresh")).option("--pm <package-manager>", "\u6307\u5B9A\u5305\u7BA1\u7406\u5668\uFF1Anpm\u3001pnpm \u6216 yarn").option("--proxy <url>", "\u6307\u5B9A\u672C\u6B21\u521D\u59CB\u5316\u4F7F\u7528\u7684 HTTP(S) \u4EE3\u7406").option("--no-proxy", "\u5F3A\u5236\u76F4\u8FDE\uFF0C\u4E0D\u8BFB\u53D6\u73AF\u5883\u53D8\u91CF\u6216\u7CFB\u7EDF\u4EE3\u7406").option("--refresh", "\u5FFD\u7565\u6A21\u677F\u914D\u7F6E\u548C\u6A21\u677F\u7F13\u5B58\uFF0C\u5F3A\u5236\u4ECE\u8FDC\u7A0B\u4ED3\u5E93\u5237\u65B0").action((projectName, options) => {
1518
1528
  void create(projectName, options);
1519
1529
  });
1520
- program.command("create [project-name]").description("\u521B\u5EFA\u4E00\u4E2A\u65B0\u9879\u76EE\uFF08\u517C\u5BB9\u65E7\u547D\u4EE4\uFF09").addOption(new Option("-i, --internal", "\u4F7F\u7528\u5185\u7F6E\u5FAE\u5E94\u7528\u6A21\u677F\uFF0C\u4E0D\u8BBF\u95EE\u8FDC\u7A0B\u6A21\u677F\u4ED3\u5E93").conflicts("refresh")).option("--pm <package-manager>", "\u6307\u5B9A\u5305\u7BA1\u7406\u5668\uFF1Anpm\u3001pnpm \u6216 yarn").option("--proxy <url>", "\u6307\u5B9A\u672C\u6B21\u521D\u59CB\u5316\u4F7F\u7528\u7684 HTTP(S) \u4EE3\u7406").option("--no-proxy", "\u5F3A\u5236\u76F4\u8FDE\uFF0C\u4E0D\u8BFB\u53D6\u73AF\u5883\u53D8\u91CF\u6216\u7CFB\u7EDF\u4EE3\u7406").option("--refresh", "\u5FFD\u7565\u6A21\u677F\u914D\u7F6E\u548C\u6A21\u677F\u7F13\u5B58\uFF0C\u5F3A\u5236\u4ECE\u8FDC\u7A0B\u4ED3\u5E93\u5237\u65B0").action((projectName, options) => {
1530
+ program.command("create [project-name]").description("\u521B\u5EFA\u4E00\u4E2A\u65B0\u9879\u76EE\uFF08\u517C\u5BB9\u65E7\u547D\u4EE4\uFF09").addOption(new Option("-i, --internal", "\u9009\u62E9\u5185\u7F6E\u4E3B\u5E94\u7528\u6216\u5FAE\u5E94\u7528\u6A21\u677F\uFF0C\u4E0D\u8BBF\u95EE\u8FDC\u7A0B\u6A21\u677F\u4ED3\u5E93").conflicts("refresh")).option("--pm <package-manager>", "\u6307\u5B9A\u5305\u7BA1\u7406\u5668\uFF1Anpm\u3001pnpm \u6216 yarn").option("--proxy <url>", "\u6307\u5B9A\u672C\u6B21\u521D\u59CB\u5316\u4F7F\u7528\u7684 HTTP(S) \u4EE3\u7406").option("--no-proxy", "\u5F3A\u5236\u76F4\u8FDE\uFF0C\u4E0D\u8BFB\u53D6\u73AF\u5883\u53D8\u91CF\u6216\u7CFB\u7EDF\u4EE3\u7406").option("--refresh", "\u5FFD\u7565\u6A21\u677F\u914D\u7F6E\u548C\u6A21\u677F\u7F13\u5B58\uFF0C\u5F3A\u5236\u4ECE\u8FDC\u7A0B\u4ED3\u5E93\u5237\u65B0").action((projectName, options) => {
1521
1531
  void create(projectName, options);
1522
1532
  });
1523
1533
  program.parse(process.argv);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/commands/create.ts","../src/services/config.ts","../src/utils/pkg-manager.ts","../src/utils/template.ts","../src/utils/cache.ts","../src/utils/http.ts","../src/utils/system-proxy.ts","../src/utils/git-repository.ts","../src/utils/template-downloader.ts","../src/utils/stable-spinner.ts","../src/utils/internal-template.ts","../src/pre/index.ts"],"sourcesContent":["import { Command, Option } from 'commander';\r\nimport { createRequire } from 'node:module';\r\nimport { create } from './commands/create.js';\r\nimport { checkNodeVersion } from './pre/index.js';\r\n\r\n// 1. 前置检查:Node.js 版本\r\ncheckNodeVersion();\r\n\r\nconst program = new Command();\r\nconst require = createRequire(import.meta.url);\r\nconst packageMetadata: unknown = require('../package.json');\r\nconst packageVersion = getPackageVersion(packageMetadata);\r\n\r\nprogram\r\n .name('gz-cli')\r\n .description('前端脚手架工具')\r\n .version(packageVersion);\r\n\r\n// 将 init 设为默认命令,参数改为可选 [project-name]\r\nprogram\r\n .command('init [project-name]', { isDefault: true })\r\n .description('创建一个新项目')\r\n .addOption(new Option('-i, --internal', '使用内置微应用模板,不访问远程模板仓库').conflicts('refresh'))\r\n .option('--pm <package-manager>', '指定包管理器:npm、pnpm 或 yarn')\r\n .option('--proxy <url>', '指定本次初始化使用的 HTTP(S) 代理')\r\n .option('--no-proxy', '强制直连,不读取环境变量或系统代理')\r\n .option('--refresh', '忽略模板配置和模板缓存,强制从远程仓库刷新')\r\n .action((projectName, options) => {\r\n void create(projectName, options);\r\n });\r\n\r\nprogram\r\n .command('create [project-name]')\r\n .description('创建一个新项目(兼容旧命令)')\r\n .addOption(new Option('-i, --internal', '使用内置微应用模板,不访问远程模板仓库').conflicts('refresh'))\r\n .option('--pm <package-manager>', '指定包管理器:npm、pnpm 或 yarn')\r\n .option('--proxy <url>', '指定本次初始化使用的 HTTP(S) 代理')\r\n .option('--no-proxy', '强制直连,不读取环境变量或系统代理')\r\n .option('--refresh', '忽略模板配置和模板缓存,强制从远程仓库刷新')\r\n .action((projectName, options) => {\r\n void create(projectName, options);\r\n });\r\n\r\nprogram.parse(process.argv);\r\n\r\nfunction getPackageVersion(value: unknown): string {\r\n if (typeof value !== 'object' || value === null) {\r\n throw new Error('无法读取 gz-cli-front 版本号。');\r\n }\r\n\r\n const version = (value as Record<string, unknown>).version;\r\n if (typeof version !== 'string' || !version.trim()) {\r\n throw new Error('gz-cli-front package.json 中缺少有效版本号。');\r\n }\r\n return version;\r\n}\r\n","import { confirm, input, select } from '@inquirer/prompts';\r\nimport chalk from 'chalk';\r\nimport { execa } from 'execa';\r\nimport fs from 'fs-extra';\r\nimport ora from 'ora';\r\nimport path from 'path';\r\nimport { performance } from 'node:perf_hooks';\r\nimport { loadCliConfig } from '../services/config.js';\r\nimport {\r\n detectPackageManager,\r\n isPackageManager,\r\n updateProjectPackageJson,\r\n type PackageManager,\r\n} from '../utils/pkg-manager.js';\r\nimport {\r\n fetchTemplates,\r\n replaceTemplateVariables,\r\n type FetchTemplatesResult,\r\n type TemplateMeta,\r\n} from '../utils/template.js';\r\nimport { downloadTemplate, type TemplateDownloadTiming } from '../utils/template-downloader.js';\r\nimport { configureNetwork, type NetworkRoute } from '../utils/http.js';\r\nimport { createStableSpinner } from '../utils/stable-spinner.js';\r\nimport { copyInternalTemplate, loadInternalTemplate } from '../utils/internal-template.js';\r\n\r\nexport interface InitOptions {\r\n internal?: boolean;\r\n pm?: string;\r\n proxy?: string | false;\r\n refresh?: boolean;\r\n}\r\n\r\ninterface InitContext {\r\n projectName: string;\r\n template: TemplateMeta;\r\n packageManager: PackageManager;\r\n}\r\n\r\ninterface TemplateTiming {\r\n configRoute: NetworkRoute | 'ssh' | 'cache' | 'stale-cache' | 'bundled';\r\n copyMs: number;\r\n fetchConfigMs: number;\r\n parseConfigMs: number;\r\n templateRoute: TemplateDownloadTiming['route'];\r\n downloadMs: number;\r\n extractMs: number;\r\n renderMs: number;\r\n}\r\n\r\nexport async function create(projectName?: string, options: InitOptions = {}): Promise<void> {\r\n try {\r\n if (!options.internal) {\r\n configureNetwork({\r\n forceDirect: options.proxy === false,\r\n proxy: typeof options.proxy === 'string' ? options.proxy : undefined,\r\n });\r\n }\r\n const templateTiming = createTemplateTiming();\r\n const context = await createInitContext(projectName, options, templateTiming);\r\n const targetPath = path.resolve(process.cwd(), context.projectName);\r\n\r\n if (!(await prepareTargetDirectory(targetPath, context.projectName))) {\r\n return;\r\n }\r\n\r\n const install = await confirm({\r\n message: '是否自动安装依赖?',\r\n default: true,\r\n });\r\n\r\n await downloadAndGenerate(context, targetPath, templateTiming, options);\r\n await installDependencies(install, targetPath, context.packageManager);\r\n await initializeGit(targetPath);\r\n printNextSteps(context, install);\r\n } catch (error: unknown) {\r\n if (isUserCancellation(error)) {\r\n console.log(chalk.yellow('\\n已取消操作。'));\r\n return;\r\n }\r\n\r\n console.error(chalk.red(`创建项目失败:${getErrorMessage(error)}`));\r\n }\r\n}\r\n\r\nasync function createInitContext(\r\n projectName: string | undefined,\r\n options: InitOptions,\r\n templateTiming: TemplateTiming,\r\n): Promise<InitContext> {\r\n const finalProjectName = await getProjectName(projectName);\r\n const templates = await loadTemplates(templateTiming, options);\r\n const template = options.internal ? templates[0] : await chooseTemplate(templates);\r\n\r\n return {\r\n projectName: finalProjectName,\r\n template,\r\n packageManager: resolvePackageManager(options.pm),\r\n };\r\n}\r\n\r\nasync function getProjectName(projectName?: string): Promise<string> {\r\n if (projectName?.trim()) {\r\n return projectName.trim();\r\n }\r\n\r\n return input({\r\n message: '请输入项目名称:',\r\n validate: (value) => value.trim() ? true : '项目名称不能为空',\r\n });\r\n}\r\n\r\nasync function loadTemplates(\r\n templateTiming: TemplateTiming,\r\n options: InitOptions,\r\n): Promise<TemplateMeta[]> {\r\n if (options.internal) {\r\n const startedAt = performance.now();\r\n const template = await loadInternalTemplate();\r\n templateTiming.configRoute = 'bundled';\r\n templateTiming.fetchConfigMs = Math.round(performance.now() - startedAt);\r\n console.log(chalk.cyan(`内网模式:使用内置微应用模板(${template.version?.slice(0, 8)}),不访问远程模板仓库。`));\r\n return [template];\r\n }\r\n\r\n const spinner = createStableSpinner();\r\n try {\r\n const config = await loadCliConfig();\r\n spinner.start('正在获取远程模板配置...');\r\n const result = await fetchTemplates(config.templateRegistry, {\r\n forceRefresh: options.refresh === true,\r\n });\r\n assignFetchTiming(templateTiming, result);\r\n spinner.succeed('远程模板配置获取成功');\r\n if (result.staleCache) {\r\n console.log(chalk.yellow('远程模板配置暂时不可用,已使用本地缓存。'));\r\n }\r\n return result.templates;\r\n } catch (error: unknown) {\r\n if (spinner.isSpinning) {\r\n spinner.fail('获取远程模板配置失败');\r\n } else {\r\n console.error(chalk.red('获取远程模板配置失败'));\r\n }\r\n const message = error instanceof Error && error.message\r\n ? error.message\r\n : '未知错误';\r\n throw new Error(`获取远程模板配置失败,请检查网络或模板配置地址。\\n${message}`);\r\n }\r\n}\r\n\r\nasync function chooseTemplate(templates: TemplateMeta[]): Promise<TemplateMeta> {\r\n return select({\r\n message: '请选择项目模板:',\r\n choices: templates.map((template) => ({\r\n name: `${template.label} (${template.name}) - ${template.description}`,\r\n value: template,\r\n })),\r\n default: templates.find((template) => template.type === 'micro') ?? templates[0],\r\n });\r\n}\r\n\r\nfunction resolvePackageManager(requestedPackageManager?: string): PackageManager {\r\n if (requestedPackageManager !== undefined) {\r\n if (!isPackageManager(requestedPackageManager)) {\r\n throw new Error(\r\n `不支持的 packageManager: ${requestedPackageManager}\\n支持: npm、pnpm、yarn`,\r\n );\r\n }\r\n return requestedPackageManager;\r\n }\r\n\r\n const packageManager = detectPackageManager();\r\n if (packageManager === 'npm') {\r\n console.log(chalk.yellow('未检测到 pnpm 或 yarn,自动使用 npm。'));\r\n }\r\n return packageManager;\r\n}\r\n\r\nasync function prepareTargetDirectory(targetPath: string, projectName: string): Promise<boolean> {\r\n if (!(await fs.pathExists(targetPath))) {\r\n return true;\r\n }\r\n\r\n const overwrite = await confirm({\r\n message: `目录 ${projectName} 已存在,是否覆盖?`,\r\n default: false,\r\n });\r\n\r\n if (!overwrite) {\r\n console.log(chalk.yellow('已取消创建。'));\r\n return false;\r\n }\r\n\r\n await fs.remove(targetPath);\r\n return true;\r\n}\r\n\r\nasync function downloadAndGenerate(\r\n context: InitContext,\r\n targetPath: string,\r\n templateTiming: TemplateTiming,\r\n options: InitOptions,\r\n): Promise<void> {\r\n const { template, projectName, packageManager } = context;\r\n const spinner = createStableSpinner();\r\n const downloadStartedAt = performance.now();\r\n try {\r\n spinner.start(options.internal ? '正在复制内置微应用模板...' : `正在下载模板 ${template.label}...`);\r\n const downloadTiming = options.internal\r\n ? await copyInternalTemplate(targetPath)\r\n : await downloadTemplate(template, targetPath, {\r\n forceRefresh: options.refresh === true,\r\n });\r\n assignDownloadTiming(templateTiming, downloadTiming);\r\n } catch (error: unknown) {\r\n templateTiming.downloadMs = Math.round(performance.now() - downloadStartedAt);\r\n await fs.remove(targetPath);\r\n if (spinner.isSpinning) {\r\n spinner.fail(options.internal ? '内置模板读取失败' : '模板下载失败');\r\n } else {\r\n console.error(chalk.red(options.internal ? '内置模板读取失败' : '模板下载失败'));\r\n }\r\n printTemplateTiming(templateTiming);\r\n const message = error instanceof Error && error.message\r\n ? error.message\r\n : '未知错误';\r\n throw new Error(options.internal\r\n ? `内置模板读取失败,请重新安装 gz-cli-front。\\n${message}`\r\n : `模板下载失败,请检查仓库地址或网络连接。\\n${message}`);\r\n }\r\n\r\n try {\r\n spinner.text = '正在替换模板变量...';\r\n const startedAt = performance.now();\r\n await replaceTemplateVariables(targetPath, { projectName });\r\n await updateProjectPackageJson(targetPath, projectName, packageManager);\r\n templateTiming.renderMs = Math.round(performance.now() - startedAt);\r\n spinner.succeed(options.internal ? '内置模板生成完成' : '模板下载并生成完成');\r\n printTemplateTiming(templateTiming);\r\n } catch {\r\n await fs.remove(targetPath);\r\n spinner.fail('模板下载或变量替换失败');\r\n throw new Error('模板变量替换失败,请检查模板文件内容。');\r\n }\r\n}\r\n\r\nfunction createTemplateTiming(): TemplateTiming {\r\n return {\r\n configRoute: 'direct',\r\n copyMs: 0,\r\n fetchConfigMs: 0,\r\n parseConfigMs: 0,\r\n templateRoute: 'direct',\r\n downloadMs: 0,\r\n extractMs: 0,\r\n renderMs: 0,\r\n };\r\n}\r\n\r\nfunction assignFetchTiming(\r\n templateTiming: TemplateTiming,\r\n result: FetchTemplatesResult,\r\n): void {\r\n templateTiming.fetchConfigMs = result.fetchMs;\r\n templateTiming.parseConfigMs = result.parseMs;\r\n templateTiming.configRoute = result.route;\r\n}\r\n\r\nfunction assignDownloadTiming(\r\n templateTiming: TemplateTiming,\r\n downloadTiming: TemplateDownloadTiming,\r\n): void {\r\n templateTiming.copyMs = downloadTiming.copyMs;\r\n templateTiming.downloadMs = downloadTiming.downloadMs;\r\n templateTiming.extractMs = downloadTiming.extractMs;\r\n templateTiming.templateRoute = downloadTiming.route;\r\n}\r\n\r\nfunction printTemplateTiming(templateTiming: TemplateTiming): void {\r\n console.log('\\n[template]');\r\n console.log(`fetch config: ${templateTiming.fetchConfigMs} ms (${formatRoute(templateTiming.configRoute)})`);\r\n console.log(`parse config: ${templateTiming.parseConfigMs} ms`);\r\n console.log(`download: ${templateTiming.downloadMs} ms (${formatRoute(templateTiming.templateRoute)})`);\r\n console.log(`extract: ${templateTiming.extractMs} ms`);\r\n console.log(`copy: ${templateTiming.copyMs} ms`);\r\n console.log(`render: ${templateTiming.renderMs} ms`);\r\n}\r\n\r\nfunction formatRoute(route: TemplateTiming['configRoute'] | TemplateTiming['templateRoute']): string {\r\n if (route === 'bundled') {\r\n return 'bundled, 内置模板';\r\n }\r\n if (route === 'proxy-environment') {\r\n return 'remote, 环境变量代理';\r\n }\r\n if (route === 'proxy-system') {\r\n return 'remote, 系统代理';\r\n }\r\n if (route === 'direct') {\r\n return 'remote, 直连';\r\n }\r\n if (route === 'ssh') {\r\n return 'remote, Git/SSH';\r\n }\r\n return route.replace('-', ' ');\r\n}\r\n\r\nasync function installDependencies(\r\n install: boolean,\r\n targetPath: string,\r\n packageManager: PackageManager,\r\n): Promise<void> {\r\n if (!install) {\r\n return;\r\n }\r\n\r\n const installCommand = packageManager === 'yarn' ? [] : ['install'];\r\n const spinner = ora(`正在安装依赖 (${packageManager} ${installCommand.join(' ')})...`).start();\r\n try {\r\n await execa(packageManager, installCommand, { cwd: targetPath });\r\n spinner.succeed('依赖安装成功');\r\n } catch {\r\n spinner.warn('依赖安装失败,请进入项目目录后手动安装');\r\n }\r\n}\r\n\r\nasync function initializeGit(targetPath: string): Promise<void> {\r\n const spinner = ora('正在初始化 Git 仓库...').start();\r\n try {\r\n await execa('git', ['init'], { cwd: targetPath });\r\n spinner.succeed('Git 仓库初始化成功');\r\n } catch {\r\n spinner.warn('Git 仓库初始化失败,请确认 Git 已安装');\r\n }\r\n}\r\n\r\nfunction printNextSteps(context: InitContext, installed: boolean): void {\r\n const { projectName, packageManager } = context;\r\n const installCommand = packageManager === 'yarn' ? 'yarn' : `${packageManager} install`;\r\n const devCommand = packageManager === 'npm' ? 'npm run dev' : `${packageManager} dev`;\r\n\r\n console.log(chalk.green(`\\n项目 ${projectName} 创建成功!`));\r\n console.log('\\n接下来你可以:\\n');\r\n console.log(chalk.cyan(` cd ${projectName}`));\r\n if (!installed) {\r\n console.log(chalk.cyan(` ${installCommand}`));\r\n }\r\n console.log(chalk.cyan(` ${devCommand}`));\r\n}\r\n\r\nfunction isUserCancellation(error: unknown): boolean {\r\n return error instanceof Error && /User force closed|User cancelled/i.test(error.message);\r\n}\r\n\r\nfunction getErrorMessage(error: unknown): string {\r\n return error instanceof Error && error.message ? ` ${error.message}` : '';\r\n}\r\n","import fs from 'fs-extra';\r\nimport path from 'path';\r\nimport { fileURLToPath } from 'url';\r\nimport type { CliConfig } from '../types/config.js';\r\n\r\nconst CONFIG_FILE_NAME = 'gz-cli-front.config.json';\r\n\r\nexport async function loadCliConfig(): Promise<CliConfig> {\r\n const configPath = await findConfigPath();\r\n const config: unknown = await fs.readJson(configPath);\r\n\r\n if (!isCliConfig(config)) {\r\n throw new Error(`CLI 配置文件无效:${configPath}`);\r\n }\r\n\r\n return config;\r\n}\r\n\r\nasync function findConfigPath(): Promise<string> {\r\n const moduleDirectory = path.dirname(fileURLToPath(import.meta.url));\r\n const configPaths = [\r\n path.resolve(moduleDirectory, 'config', CONFIG_FILE_NAME),\r\n path.resolve(moduleDirectory, '..', 'config', CONFIG_FILE_NAME),\r\n path.resolve(moduleDirectory, '..', '..', 'config', CONFIG_FILE_NAME),\r\n ];\r\n\r\n for (const configPath of configPaths) {\r\n if (await fs.pathExists(configPath)) {\r\n return configPath;\r\n }\r\n }\r\n\r\n throw new Error('未找到 gz-cli-front 配置文件。');\r\n}\r\n\r\nfunction isCliConfig(value: unknown): value is CliConfig {\r\n if (typeof value !== 'object' || value === null) {\r\n return false;\r\n }\r\n\r\n const templateRegistry = (value as Record<string, unknown>).templateRegistry;\r\n if (typeof templateRegistry !== 'object' || templateRegistry === null) {\r\n return false;\r\n }\r\n\r\n return isTemplateRegistryConfig(templateRegistry as Record<string, unknown>);\r\n}\r\n\r\nfunction isTemplateRegistryConfig(value: Record<string, unknown>): boolean {\r\n if (!isNonEmptyString(value.url)) {\r\n return false;\r\n }\r\n\r\n if (value.source === undefined || value.source === 'http') {\r\n return true;\r\n }\r\n\r\n return value.source === 'git'\r\n && isNonEmptyString(value.file)\r\n && (value.version === undefined || isNonEmptyString(value.version));\r\n}\r\n\r\nfunction isNonEmptyString(value: unknown): value is string {\r\n return typeof value === 'string' && value.trim().length > 0;\r\n}\r\n","import fs from 'fs-extra';\r\nimport path from 'path';\r\nimport { spawnSync } from 'node:child_process';\r\n\r\nexport type PackageManager = 'npm' | 'pnpm' | 'yarn';\r\n\r\nconst PACKAGE_MANAGERS: readonly PackageManager[] = ['pnpm', 'yarn', 'npm'];\r\n\r\nexport function detectPackageManager(): PackageManager {\r\n return PACKAGE_MANAGERS.find(isPackageManagerAvailable) ?? 'npm';\r\n}\r\n\r\nexport function isPackageManager(value: string): value is PackageManager {\r\n return PACKAGE_MANAGERS.includes(value as PackageManager);\r\n}\r\n\r\nexport async function updateProjectPackageJson(\r\n targetDir: string,\r\n projectName: string,\r\n packageManager: PackageManager,\r\n): Promise<void> {\r\n const packageJsonPath = path.join(targetDir, 'package.json');\r\n if (!(await fs.pathExists(packageJsonPath))) {\r\n return;\r\n }\r\n\r\n const packageJson: Record<string, unknown> = await fs.readJson(packageJsonPath);\r\n packageJson.name = projectName;\r\n\r\n if (Object.prototype.hasOwnProperty.call(packageJson, 'packageManager')) {\r\n packageJson.packageManager = packageManager;\r\n }\r\n\r\n await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });\r\n}\r\n\r\nfunction isPackageManagerAvailable(packageManager: PackageManager): boolean {\r\n const result = spawnSync(packageManager, ['--version'], {\r\n shell: process.platform === 'win32',\r\n stdio: 'ignore',\r\n });\r\n\r\n return result.status === 0;\r\n}\r\n","import fs from 'fs-extra';\r\nimport path from 'path';\r\nimport { performance } from 'node:perf_hooks';\r\nimport type { TemplateRegistryConfig } from '../types/config.js';\r\nimport type { TemplateMeta, TemplateSource, TemplateType } from '../types/template.js';\r\nimport {\r\n getTemplateRegistryCachePath,\r\n isCacheFresh,\r\n TEMPLATE_REGISTRY_CACHE_TTL_MS,\r\n} from './cache.js';\r\nimport { requestBuffer, type NetworkRoute } from './http.js';\r\nimport { ensureGitRepository } from './git-repository.js';\r\n\r\nconst TEXT_FILE_EXTENSIONS = new Set([\r\n '.json', '.ts', '.tsx', '.js', '.jsx', '.md', '.html', '.css', '.less', '.scss', '.env',\r\n]);\r\nconst IGNORED_DIRECTORIES = new Set(['node_modules', 'dist', '.git']);\r\nconst TEMPLATE_DEBUG_ENV = 'GZ_CLI_FRONT_DEBUG';\r\nconst TEMPLATE_REGISTRY_TIMEOUT_MS = 5_000;\r\n\r\ninterface TemplateRegistryCache {\r\n body: string;\r\n fetchedAt: number;\r\n url: string;\r\n}\r\n\r\nexport interface FetchTemplatesOptions {\r\n forceRefresh?: boolean;\r\n}\r\n\r\nexport interface FetchTemplatesResult {\r\n cacheHit: boolean;\r\n fetchMs: number;\r\n parseMs: number;\r\n route: NetworkRoute | 'ssh' | 'cache' | 'stale-cache';\r\n staleCache: boolean;\r\n templates: TemplateMeta[];\r\n}\r\n\r\nexport type { TemplateMeta, TemplateSource, TemplateType } from '../types/template.js';\r\n\r\nexport async function fetchTemplates(\r\n templateRegistry: TemplateRegistryConfig | string,\r\n options: FetchTemplatesOptions = {},\r\n): Promise<FetchTemplatesResult> {\r\n const registry = typeof templateRegistry === 'string'\r\n ? { url: templateRegistry } satisfies TemplateRegistryConfig\r\n : templateRegistry;\r\n\r\n if (registry.source === 'git') {\r\n return fetchTemplatesFromGit(registry, options);\r\n }\r\n\r\n return fetchTemplatesFromHttp(registry.url, options);\r\n}\r\n\r\nasync function fetchTemplatesFromHttp(\r\n templateRegistryUrl: string,\r\n options: FetchTemplatesOptions,\r\n): Promise<FetchTemplatesResult> {\r\n const cachePath = getTemplateRegistryCachePath(templateRegistryUrl);\r\n const cacheStartedAt = performance.now();\r\n let cached = await readRegistryCache(cachePath, templateRegistryUrl);\r\n const cacheReadMs = Math.round(performance.now() - cacheStartedAt);\r\n debugTemplateRequest(templateRegistryUrl, cachePath, options.forceRefresh === true);\r\n\r\n if (!options.forceRefresh && cached\r\n && isCacheFresh(cached.fetchedAt, TEMPLATE_REGISTRY_CACHE_TTL_MS)) {\r\n try {\r\n return parseTemplates(cached.body, true, false, cacheReadMs, 'cache');\r\n } catch {\r\n await fs.remove(cachePath);\r\n cached = undefined;\r\n }\r\n }\r\n\r\n const fetchStartedAt = performance.now();\r\n try {\r\n const response = await requestBuffer(templateRegistryUrl, {\r\n retries: 1,\r\n timeoutMs: TEMPLATE_REGISTRY_TIMEOUT_MS,\r\n });\r\n const body = response.body.toString('utf8');\r\n const result = parseTemplates(body, false, false, response.elapsedMs, response.route);\r\n try {\r\n await writeRegistryCache(cachePath, {\r\n body,\r\n fetchedAt: Date.now(),\r\n url: templateRegistryUrl,\r\n });\r\n } catch (error: unknown) {\r\n if (process.env[TEMPLATE_DEBUG_ENV] === '1') {\r\n console.log(`template config cache write failed: ${getErrorMessage(error)}`);\r\n }\r\n }\r\n return result;\r\n } catch (error: unknown) {\r\n if (!options.forceRefresh && cached) {\r\n return parseTemplates(\r\n cached.body,\r\n true,\r\n true,\r\n Math.round(performance.now() - fetchStartedAt),\r\n 'stale-cache',\r\n );\r\n }\r\n throw createTemplateRequestError(templateRegistryUrl, error);\r\n }\r\n}\r\n\r\nasync function fetchTemplatesFromGit(\r\n registry: Extract<TemplateRegistryConfig, { source: 'git' }>,\r\n options: FetchTemplatesOptions,\r\n): Promise<FetchTemplatesResult> {\r\n const cacheKey = `git:${registry.url}#${registry.version ?? 'latest'}:${registry.file}`;\r\n const fallbackCachePath = getTemplateRegistryCachePath(cacheKey);\r\n const fallbackCache = await readRegistryCache(fallbackCachePath, cacheKey);\r\n const startedAt = performance.now();\r\n\r\n try {\r\n const result = await ensureGitRepository(registry.url, {\r\n forceRefresh: options.forceRefresh,\r\n namespace: 'registry',\r\n ttlMs: TEMPLATE_REGISTRY_CACHE_TTL_MS,\r\n version: registry.version,\r\n });\r\n const registryFile = resolveRegistryFile(result.path, registry.file);\r\n const body = await fs.readFile(registryFile, 'utf8');\r\n const parsed = parseTemplates(\r\n body,\r\n result.cacheHit,\r\n result.staleCache,\r\n result.elapsedMs,\r\n result.route,\r\n );\r\n if (!result.cacheHit || !fallbackCache) {\r\n await writeRegistryCache(fallbackCachePath, {\r\n body,\r\n fetchedAt: Date.now(),\r\n url: cacheKey,\r\n }).catch(() => undefined);\r\n }\r\n return parsed;\r\n } catch (error: unknown) {\r\n if (!options.forceRefresh && fallbackCache) {\r\n return parseTemplates(\r\n fallbackCache.body,\r\n true,\r\n true,\r\n Math.round(performance.now() - startedAt),\r\n 'stale-cache',\r\n );\r\n }\r\n throw new Error(`模板注册仓库读取失败\\nerror: ${getErrorMessage(error)}`);\r\n }\r\n}\r\n\r\nfunction resolveRegistryFile(repositoryPath: string, registryFile: string): string {\r\n const resolvedRepository = path.resolve(repositoryPath);\r\n const resolvedFile = path.resolve(repositoryPath, registryFile);\r\n if (resolvedFile !== resolvedRepository\r\n && !resolvedFile.startsWith(`${resolvedRepository}${path.sep}`)) {\r\n throw new Error(`模板注册文件必须位于注册仓库内:${registryFile}`);\r\n }\r\n return resolvedFile;\r\n}\r\n\r\nfunction parseTemplates(\r\n body: string,\r\n cacheHit: boolean,\r\n staleCache: boolean,\r\n fetchMs: number,\r\n route: FetchTemplatesResult['route'],\r\n): FetchTemplatesResult {\r\n const parseStartedAt = performance.now();\r\n let data: unknown;\r\n\r\n try {\r\n data = JSON.parse(body);\r\n } catch (error: unknown) {\r\n throw new Error(`模板配置 JSON 解析失败:${getErrorMessage(error)}`);\r\n }\r\n if (!Array.isArray(data) || data.length === 0) {\r\n throw new Error('模板注册表为空');\r\n }\r\n\r\n const templates = data.filter(isTemplateMeta);\r\n if (templates.length === 0) {\r\n throw new Error('模板注册表中没有有效模板');\r\n }\r\n\r\n return {\r\n cacheHit,\r\n fetchMs,\r\n parseMs: Math.round(performance.now() - parseStartedAt),\r\n route,\r\n staleCache,\r\n templates,\r\n };\r\n}\r\n\r\nfunction debugTemplateRequest(\r\n templateRegistryUrl: string,\r\n cachePath: string,\r\n forceRefresh: boolean,\r\n): void {\r\n if (process.env[TEMPLATE_DEBUG_ENV] !== '1') {\r\n return;\r\n }\r\n\r\n console.log('template config url:', templateRegistryUrl);\r\n console.log('template config client: undici fetch');\r\n console.log(`template config timeout: ${TEMPLATE_REGISTRY_TIMEOUT_MS} ms`);\r\n console.log('template config cache:', cachePath);\r\n console.log('template config force refresh:', forceRefresh);\r\n}\r\n\r\nfunction createTemplateRequestError(templateRegistryUrl: string, error: unknown): Error {\r\n return new Error(\r\n `模板配置请求失败\\nurl: ${templateRegistryUrl}\\nerror: ${getErrorMessage(error)}`,\r\n );\r\n}\r\n\r\nfunction getErrorMessage(error: unknown): string {\r\n if (!(error instanceof Error)) {\r\n return '未知错误';\r\n }\r\n\r\n const cause = 'cause' in error ? error.cause : undefined;\r\n const causeMessage = cause instanceof Error ? cause.message : String(cause ?? '');\r\n return causeMessage ? `${error.message} (${causeMessage})` : error.message;\r\n}\r\n\r\nasync function readRegistryCache(\r\n cachePath: string,\r\n templateRegistryUrl: string,\r\n): Promise<TemplateRegistryCache | undefined> {\r\n try {\r\n const cache: unknown = await fs.readJson(cachePath);\r\n if (!isRecord(cache)\r\n || cache.url !== templateRegistryUrl\r\n || typeof cache.body !== 'string'\r\n || typeof cache.fetchedAt !== 'number') {\r\n return undefined;\r\n }\r\n return {\r\n body: cache.body,\r\n fetchedAt: cache.fetchedAt,\r\n url: cache.url,\r\n };\r\n } catch {\r\n return undefined;\r\n }\r\n}\r\n\r\nasync function writeRegistryCache(\r\n cachePath: string,\r\n cache: TemplateRegistryCache,\r\n): Promise<void> {\r\n await fs.ensureDir(path.dirname(cachePath));\r\n await fs.writeJson(cachePath, cache);\r\n}\r\n\r\nexport async function replaceTemplateVariables(\r\n targetDir: string,\r\n variables: Readonly<Record<string, string>>,\r\n): Promise<void> {\r\n await visitDirectory(targetDir, async (filePath) => {\r\n if (!shouldProcessFile(filePath)) {\r\n return;\r\n }\r\n\r\n const content = await fs.readFile(filePath, 'utf8');\r\n const replaced = Object.entries(variables).reduce(\r\n (result, [key, value]) => result.split(`{{ ${key} }}`).join(value),\r\n content,\r\n );\r\n\r\n if (replaced !== content) {\r\n await fs.writeFile(filePath, replaced, 'utf8');\r\n }\r\n });\r\n}\r\n\r\nasync function visitDirectory(\r\n directory: string,\r\n onFile: (filePath: string) => Promise<void>,\r\n): Promise<void> {\r\n const entries = await fs.readdir(directory, { withFileTypes: true });\r\n for (const entry of entries) {\r\n const entryPath = path.join(directory, entry.name);\r\n if (entry.isDirectory()) {\r\n if (!IGNORED_DIRECTORIES.has(entry.name)) {\r\n await visitDirectory(entryPath, onFile);\r\n }\r\n } else if (entry.isFile()) {\r\n await onFile(entryPath);\r\n }\r\n }\r\n}\r\n\r\nfunction shouldProcessFile(filePath: string): boolean {\r\n const filename = path.basename(filePath);\r\n return TEXT_FILE_EXTENSIONS.has(path.extname(filename)) || filename.startsWith('.env');\r\n}\r\n\r\nfunction isTemplateMeta(value: unknown): value is TemplateMeta {\r\n if (!isRecord(value)) {\r\n return false;\r\n }\r\n\r\n return isString(value.name)\r\n && isString(value.label)\r\n && isString(value.description)\r\n && isTemplateType(value.type)\r\n && isTemplateLocation(value)\r\n && (value.version === undefined || isString(value.version));\r\n}\r\n\r\nfunction isRecord(value: unknown): value is Record<string, unknown> {\r\n return typeof value === 'object' && value !== null;\r\n}\r\n\r\nfunction isString(value: unknown): value is string {\r\n return typeof value === 'string' && value.trim().length > 0;\r\n}\r\n\r\nfunction isTemplateType(value: unknown): value is TemplateType {\r\n return value === 'main' || value === 'micro';\r\n}\r\n\r\nfunction isTemplateLocation(value: Record<string, unknown>): boolean {\r\n if (value.source !== undefined && !isTemplateSource(value.source)) {\r\n return false;\r\n }\r\n\r\n if (isString(value.url)) {\r\n return true;\r\n }\r\n\r\n return value.source === undefined && isString(value.repo);\r\n}\r\n\r\nfunction isTemplateSource(value: unknown): value is TemplateSource {\r\n return value === 'github' || value === 'gitlab' || value === 'git';\r\n}\r\n","import { createHash } from 'node:crypto';\r\nimport os from 'node:os';\r\nimport path from 'node:path';\r\n\r\nexport const TEMPLATE_REGISTRY_CACHE_TTL_MS = 5 * 60 * 1000;\r\nexport const TEMPLATE_ARCHIVE_CACHE_TTL_MS = 10 * 60 * 1000;\r\n\r\nexport function getTemplateRegistryCachePath(url: string): string {\r\n return path.join(getCacheDirectory(), 'registry', `${createCacheKey(url)}.json`);\r\n}\r\n\r\nexport function getTemplateArchiveCachePath(source: string): string {\r\n return path.join(getCacheDirectory(), 'templates', `${createCacheKey(source)}.tar.gz`);\r\n}\r\n\r\nexport function getGitRepositoryCachePath(\r\n namespace: 'registry' | 'templates',\r\n source: string,\r\n): string {\r\n return path.join(getCacheDirectory(), namespace, `git-${createCacheKey(source)}`);\r\n}\r\n\r\nexport function isCacheFresh(updatedAt: number, ttlMs: number): boolean {\r\n return Date.now() - updatedAt < ttlMs;\r\n}\r\n\r\nfunction getCacheDirectory(): string {\r\n const configuredDirectory = process.env.GZ_CLI_FRONT_CACHE_DIR?.trim();\r\n return configuredDirectory || path.join(os.homedir(), '.gz-cli-front', 'cache');\r\n}\r\n\r\nfunction createCacheKey(value: string): string {\r\n return createHash('sha256').update(value).digest('hex').slice(0, 24);\r\n}\r\n","import { setTimeout as delay } from 'node:timers/promises';\r\nimport {\r\n EnvHttpProxyAgent,\r\n ProxyAgent,\r\n fetch as undiciFetch,\r\n type Dispatcher,\r\n} from 'undici';\r\nimport { getSystemProxy } from './system-proxy.js';\r\n\r\nexport interface NetworkOptions {\r\n forceDirect?: boolean;\r\n proxy?: string;\r\n}\r\n\r\nexport interface HttpRequestOptions {\r\n headers?: Readonly<Record<string, string>>;\r\n retries: number;\r\n timeoutMs: number;\r\n}\r\n\r\nexport interface HttpResponseData {\r\n body: Buffer;\r\n elapsedMs: number;\r\n route: NetworkRoute;\r\n status: number;\r\n}\r\n\r\nexport type NetworkRoute = 'direct' | 'proxy-environment' | 'proxy-system';\r\n\r\nlet networkOptions: NetworkOptions = {};\r\n\r\nexport function configureNetwork(options: NetworkOptions): void {\r\n if (options.proxy) {\r\n validateProxyUrl(options.proxy);\r\n }\r\n networkOptions = { ...options };\r\n}\r\n\r\nexport async function requestBuffer(\r\n url: string,\r\n options: HttpRequestOptions,\r\n): Promise<HttpResponseData> {\r\n const startedAt = performance.now();\r\n let lastError: unknown;\r\n const proxyConfig = await resolveProxyConfig(url);\r\n\r\n for (let attempt = 0; attempt <= options.retries; attempt += 1) {\r\n const controller = new AbortController();\r\n const timeout = setTimeout(() => controller.abort(), options.timeoutMs);\r\n const dispatcher = proxyConfig.createDispatcher?.();\r\n\r\n debugNetworkRoute(url, proxyConfig.route, attempt + 1, options.retries + 1);\r\n\r\n try {\r\n const response = await undiciFetch(url, {\r\n ...(dispatcher ? { dispatcher } : {}),\r\n headers: options.headers,\r\n redirect: 'follow',\r\n signal: controller.signal,\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error(`HTTP ${response.status} ${response.statusText}`);\r\n }\r\n\r\n return {\r\n body: Buffer.from(await response.arrayBuffer()),\r\n elapsedMs: Math.round(performance.now() - startedAt),\r\n route: proxyConfig.route,\r\n status: response.status,\r\n };\r\n } catch (error: unknown) {\r\n lastError = error;\r\n if (attempt < options.retries) {\r\n await delay(250 * (attempt + 1));\r\n }\r\n } finally {\r\n clearTimeout(timeout);\r\n await dispatcher?.destroy();\r\n }\r\n }\r\n\r\n throw createRequestError(url, options, proxyConfig.route, lastError);\r\n}\r\n\r\ninterface ResolvedProxyConfig {\r\n createDispatcher?: () => Dispatcher;\r\n proxyUrl?: string;\r\n route: NetworkRoute;\r\n}\r\n\r\nasync function resolveProxyConfig(url: string): Promise<ResolvedProxyConfig> {\r\n const target = new URL(url);\r\n\r\n if (networkOptions.forceDirect) {\r\n return { route: 'direct' };\r\n }\r\n\r\n if (networkOptions.proxy) {\r\n const proxyUrl = networkOptions.proxy;\r\n return {\r\n createDispatcher: () => new ProxyAgent({ uri: proxyUrl }),\r\n proxyUrl,\r\n route: 'proxy-environment',\r\n };\r\n }\r\n\r\n const httpProxy = readEnvironmentVariable('http_proxy', 'HTTP_PROXY');\r\n const httpsProxy = readEnvironmentVariable('https_proxy', 'HTTPS_PROXY');\r\n const noProxy = readEnvironmentVariable('no_proxy', 'NO_PROXY');\r\n const environmentProxy = target.protocol === 'https:'\r\n ? httpsProxy ?? httpProxy\r\n : httpProxy;\r\n\r\n if (noProxy && shouldBypassProxy(target, noProxy)) {\r\n return { route: 'direct' };\r\n }\r\n\r\n if (environmentProxy) {\r\n return {\r\n createDispatcher: () => new EnvHttpProxyAgent({\r\n httpProxy,\r\n httpsProxy,\r\n noProxy,\r\n }),\r\n proxyUrl: environmentProxy,\r\n route: 'proxy-environment',\r\n };\r\n }\r\n\r\n const systemProxy = await getSystemProxy(target);\r\n if (systemProxy.noProxy && shouldBypassProxy(target, systemProxy.noProxy)) {\r\n return { route: 'direct' };\r\n }\r\n if (systemProxy.proxyUrl) {\r\n return {\r\n createDispatcher: () => new ProxyAgent({ uri: systemProxy.proxyUrl! }),\r\n proxyUrl: systemProxy.proxyUrl,\r\n route: 'proxy-system',\r\n };\r\n }\r\n\r\n return { route: 'direct' };\r\n}\r\n\r\nexport interface GitNetworkConfig {\r\n args: string[];\r\n route: NetworkRoute | 'ssh';\r\n}\r\n\r\nexport async function resolveGitNetworkConfig(repositoryUrl: string): Promise<GitNetworkConfig> {\r\n if (!/^https?:\\/\\//i.test(repositoryUrl)) {\r\n return { args: [], route: 'ssh' };\r\n }\r\n\r\n const proxyConfig = await resolveProxyConfig(repositoryUrl);\r\n if (proxyConfig.proxyUrl) {\r\n return {\r\n args: ['-c', `http.proxy=${proxyConfig.proxyUrl}`],\r\n route: proxyConfig.route,\r\n };\r\n }\r\n\r\n return {\r\n args: networkOptions.forceDirect ? ['-c', 'http.proxy='] : [],\r\n route: 'direct',\r\n };\r\n}\r\n\r\nfunction readEnvironmentVariable(primaryName: string, fallbackName: string): string | undefined {\r\n const value = process.env[primaryName] ?? process.env[fallbackName];\r\n return value?.trim() || undefined;\r\n}\r\n\r\nfunction shouldBypassProxy(target: URL, noProxy: string): boolean {\r\n const hostname = target.hostname.toLowerCase();\r\n const port = Number.parseInt(target.port, 10)\r\n || (target.protocol === 'https:' ? 443 : 80);\r\n\r\n return noProxy.split(/[,\\s]/).some((rawEntry) => {\r\n const entry = rawEntry.trim().toLowerCase();\r\n if (!entry) {\r\n return false;\r\n }\r\n if (entry === '*') {\r\n return true;\r\n }\r\n\r\n const parsed = entry.match(/^(.+):(\\d+)$/);\r\n const entryHostname = parsed ? parsed[1] : entry;\r\n const entryPort = parsed ? Number.parseInt(parsed[2], 10) : 0;\r\n if (entryPort && entryPort !== port) {\r\n return false;\r\n }\r\n\r\n if (!/^[.*]/.test(entryHostname)) {\r\n return hostname === entryHostname;\r\n }\r\n return hostname.endsWith(entryHostname.replace(/^\\*/, ''));\r\n });\r\n}\r\n\r\nexport function formatNetworkRoute(route: NetworkRoute): string {\r\n if (route === 'proxy-environment') {\r\n return '环境变量代理';\r\n }\r\n if (route === 'proxy-system') {\r\n return '系统代理';\r\n }\r\n return '直连';\r\n}\r\n\r\nfunction createRequestError(\r\n url: string,\r\n options: HttpRequestOptions,\r\n route: NetworkRoute,\r\n error: unknown,\r\n): Error {\r\n const cause = getErrorMessage(error);\r\n return new Error(\r\n `请求失败\\nurl: ${url}\\nerror: ${cause}\\nnetwork: ${formatNetworkRoute(route)}\\ntimeout: ${options.timeoutMs} ms\\nattempts: ${options.retries + 1}`,\r\n );\r\n}\r\n\r\nfunction validateProxyUrl(proxyUrl: string): void {\r\n try {\r\n const parsed = new URL(proxyUrl);\r\n if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\r\n throw new Error();\r\n }\r\n } catch {\r\n throw new Error('无效的代理地址,请使用 http://host:port 或 https://host:port 格式。');\r\n }\r\n}\r\n\r\nfunction debugNetworkRoute(\r\n url: string,\r\n route: NetworkRoute,\r\n attempt: number,\r\n attempts: number,\r\n): void {\r\n if (process.env.GZ_CLI_FRONT_DEBUG !== '1') {\r\n return;\r\n }\r\n\r\n console.log(`[network] host: ${new URL(url).host}`);\r\n console.log(`[network] route: ${formatNetworkRoute(route)}`);\r\n console.log(`[network] attempt: ${attempt}/${attempts}`);\r\n}\r\n\r\nfunction getErrorMessage(error: unknown): string {\r\n if (!(error instanceof Error)) {\r\n return '未知错误';\r\n }\r\n const cause = 'cause' in error ? error.cause : undefined;\r\n const causeMessage = cause instanceof Error ? cause.message : String(cause ?? '');\r\n return causeMessage ? `${error.message} (${causeMessage})` : error.message;\r\n}\r\n","import { execFile } from 'node:child_process';\r\nimport { promisify } from 'node:util';\r\n\r\nconst execFileAsync = promisify(execFile);\r\nconst WINDOWS_INTERNET_SETTINGS = String.raw`HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings`;\r\nconst SYSTEM_PROXY_TIMEOUT_MS = 1_500;\r\n\r\nexport interface SystemProxyConfig {\r\n noProxy?: string;\r\n proxyUrl?: string;\r\n}\r\n\r\nconst systemProxyCache = new Map<string, Promise<SystemProxyConfig>>();\r\n\r\nexport function getSystemProxy(target: URL): Promise<SystemProxyConfig> {\r\n const cacheKey = `${process.platform}:${target.protocol}`;\r\n const cached = systemProxyCache.get(cacheKey);\r\n if (cached) {\r\n return cached;\r\n }\r\n\r\n const request = detectSystemProxy(target).catch(() => ({}));\r\n systemProxyCache.set(cacheKey, request);\r\n return request;\r\n}\r\n\r\nasync function detectSystemProxy(target: URL): Promise<SystemProxyConfig> {\r\n if (process.platform === 'win32') {\r\n return detectWindowsProxy(target);\r\n }\r\n if (process.platform === 'darwin') {\r\n return detectMacOsProxy(target);\r\n }\r\n if (process.platform === 'linux') {\r\n return detectLinuxProxy(target);\r\n }\r\n return {};\r\n}\r\n\r\nasync function detectWindowsProxy(target: URL): Promise<SystemProxyConfig> {\r\n const [enabledOutput, serverOutput, overrideOutput] = await Promise.all([\r\n queryWindowsRegistry('ProxyEnable'),\r\n queryWindowsRegistry('ProxyServer'),\r\n queryWindowsRegistry('ProxyOverride'),\r\n ]);\r\n const enabled = readRegistryValue(enabledOutput, 'ProxyEnable');\r\n if (enabled !== '0x1' && enabled !== '1') {\r\n return {};\r\n }\r\n\r\n const proxyServer = readRegistryValue(serverOutput, 'ProxyServer');\r\n if (!proxyServer) {\r\n return {};\r\n }\r\n\r\n const proxyAddress = selectWindowsProxy(proxyServer, target.protocol);\r\n if (!proxyAddress) {\r\n return {};\r\n }\r\n\r\n const proxyOverride = readRegistryValue(overrideOutput, 'ProxyOverride');\r\n return {\r\n noProxy: proxyOverride?.split(';').filter((entry) => entry !== '<local>').join(','),\r\n proxyUrl: normalizeProxyUrl(proxyAddress),\r\n };\r\n}\r\n\r\nasync function queryWindowsRegistry(valueName: string): Promise<string> {\r\n try {\r\n const result = await execFileAsync(\r\n 'reg.exe',\r\n ['query', WINDOWS_INTERNET_SETTINGS, '/v', valueName],\r\n { timeout: SYSTEM_PROXY_TIMEOUT_MS, windowsHide: true },\r\n );\r\n return result.stdout;\r\n } catch {\r\n return '';\r\n }\r\n}\r\n\r\nfunction readRegistryValue(output: string, valueName: string): string | undefined {\r\n const line = output.split(/\\r?\\n/).find((entry) => entry.includes(valueName));\r\n return line?.match(/REG_\\w+\\s+(.+)$/)?.[1]?.trim();\r\n}\r\n\r\nfunction selectWindowsProxy(proxyServer: string, protocol: string): string | undefined {\r\n if (!proxyServer.includes('=')) {\r\n return proxyServer;\r\n }\r\n\r\n const proxies = new Map(\r\n proxyServer.split(';').flatMap((entry) => {\r\n const [key, value] = entry.split('=', 2).map((part) => part.trim());\r\n return key && value ? [[key.toLowerCase(), value] as const] : [];\r\n }),\r\n );\r\n const protocolName = protocol.replace(':', '');\r\n return proxies.get(protocolName) ?? proxies.get('http');\r\n}\r\n\r\nasync function detectMacOsProxy(target: URL): Promise<SystemProxyConfig> {\r\n try {\r\n const result = await execFileAsync('scutil', ['--proxy'], {\r\n timeout: SYSTEM_PROXY_TIMEOUT_MS,\r\n });\r\n const prefix = target.protocol === 'https:' ? 'HTTPS' : 'HTTP';\r\n if (readScutilValue(result.stdout, `${prefix}Enable`) !== '1') {\r\n return {};\r\n }\r\n const host = readScutilValue(result.stdout, `${prefix}Proxy`);\r\n const port = readScutilValue(result.stdout, `${prefix}Port`);\r\n return host && port ? { proxyUrl: `http://${host}:${port}` } : {};\r\n } catch {\r\n return {};\r\n }\r\n}\r\n\r\nfunction readScutilValue(output: string, key: string): string | undefined {\r\n return output.match(new RegExp(`^\\\\s*${key}\\\\s*:\\\\s*(.+)$`, 'm'))?.[1]?.trim();\r\n}\r\n\r\nasync function detectLinuxProxy(target: URL): Promise<SystemProxyConfig> {\r\n try {\r\n const mode = stripQuotes(await queryGSettings('org.gnome.system.proxy', 'mode'));\r\n if (mode !== 'manual') {\r\n return {};\r\n }\r\n\r\n const protocol = target.protocol === 'https:' ? 'https' : 'http';\r\n const [hostValue, portValue, ignoredHostsValue] = await Promise.all([\r\n queryGSettings(`org.gnome.system.proxy.${protocol}`, 'host'),\r\n queryGSettings(`org.gnome.system.proxy.${protocol}`, 'port'),\r\n queryGSettings('org.gnome.system.proxy', 'ignore-hosts'),\r\n ]);\r\n const host = stripQuotes(hostValue);\r\n const port = Number.parseInt(portValue.trim(), 10);\r\n if (!host || !Number.isInteger(port) || port <= 0) {\r\n return {};\r\n }\r\n\r\n return {\r\n noProxy: Array.from(\r\n ignoredHostsValue.matchAll(/'([^']+)'/g),\r\n (match) => match[1],\r\n ).join(','),\r\n proxyUrl: `http://${host}:${port}`,\r\n };\r\n } catch {\r\n return {};\r\n }\r\n}\r\n\r\nasync function queryGSettings(schema: string, key: string): Promise<string> {\r\n const result = await execFileAsync('gsettings', ['get', schema, key], {\r\n timeout: SYSTEM_PROXY_TIMEOUT_MS,\r\n });\r\n return result.stdout;\r\n}\r\n\r\nfunction stripQuotes(value: string): string {\r\n return value.trim().replace(/^['\"]|['\"]$/g, '');\r\n}\r\n\r\nfunction normalizeProxyUrl(proxyAddress: string): string {\r\n return /^[a-z][a-z\\d+.-]*:\\/\\//i.test(proxyAddress)\r\n ? proxyAddress\r\n : `http://${proxyAddress}`;\r\n}\r\n","import { execa } from 'execa';\r\nimport fs from 'fs-extra';\r\nimport { randomUUID } from 'node:crypto';\r\nimport path from 'node:path';\r\nimport { performance } from 'node:perf_hooks';\r\nimport { setTimeout as delay } from 'node:timers/promises';\r\nimport { getGitRepositoryCachePath, isCacheFresh } from './cache.js';\r\nimport {\r\n formatNetworkRoute,\r\n resolveGitNetworkConfig,\r\n type NetworkRoute,\r\n} from './http.js';\r\n\r\nconst GIT_OPERATION_ATTEMPTS = 2;\r\nconst GIT_AUTH_TIMEOUT_MS = 60_000;\r\nconst GIT_SSH_CLONE_TIMEOUT_MS = 20_000;\r\ntype GitOperationStage = 'clone';\r\n\r\nexport interface GitRepositoryOptions {\r\n forceRefresh?: boolean;\r\n namespace: 'registry' | 'templates';\r\n ttlMs: number;\r\n version?: string;\r\n}\r\n\r\nexport interface GitRepositoryResult {\r\n cacheHit: boolean;\r\n elapsedMs: number;\r\n path: string;\r\n route: NetworkRoute | 'ssh' | 'cache' | 'stale-cache';\r\n staleCache: boolean;\r\n}\r\n\r\nexport async function ensureGitRepository(\r\n repositoryUrl: string,\r\n options: GitRepositoryOptions,\r\n): Promise<GitRepositoryResult> {\r\n const version = normalizeVersion(options.version);\r\n const repositoryPath = getRepositoryCachePath(repositoryUrl, options.namespace, version);\r\n const startedAt = performance.now();\r\n const cacheExists = await isValidGitCache(repositoryPath);\r\n\r\n if (await canUseGitCache(repositoryPath, cacheExists, version, options)) {\r\n return createCacheResult(repositoryPath, startedAt, false);\r\n }\r\n\r\n const temporaryPath = `${repositoryPath}.${randomUUID()}.tmp`;\r\n const candidates = getRepositoryCandidates(repositoryUrl);\r\n let lastError: unknown;\r\n await fs.ensureDir(path.dirname(repositoryPath));\r\n\r\n for (const [index, candidate] of candidates.entries()) {\r\n try {\r\n const network = await resolveGitNetworkConfig(candidate);\r\n const isSshCandidate = network.route === 'ssh';\r\n const timeoutMs = isSshCandidate ? GIT_SSH_CLONE_TIMEOUT_MS : GIT_AUTH_TIMEOUT_MS;\r\n debugGitRepository(candidate, network.route, timeoutMs);\r\n await cloneRepository(\r\n candidate,\r\n temporaryPath,\r\n version,\r\n network.args,\r\n timeoutMs,\r\n isSshCandidate ? 1 : GIT_OPERATION_ATTEMPTS,\r\n );\r\n await replaceCacheDirectory(temporaryPath, repositoryPath);\r\n return {\r\n cacheHit: false,\r\n elapsedMs: Math.round(performance.now() - startedAt),\r\n path: repositoryPath,\r\n route: network.route,\r\n staleCache: false,\r\n };\r\n } catch (error: unknown) {\r\n lastError = error;\r\n await fs.remove(temporaryPath);\r\n if (index < candidates.length - 1) {\r\n if (process.env.GZ_CLI_FRONT_DEBUG === '1') {\r\n console.log('[git] SSH 不可用,正在尝试 HTTPS...');\r\n }\r\n continue;\r\n }\r\n }\r\n }\r\n\r\n if (cacheExists && !options.forceRefresh) {\r\n return createCacheResult(repositoryPath, startedAt, true);\r\n }\r\n throw createGitError(repositoryUrl, lastError, 'clone');\r\n}\r\n\r\nfunction getRepositoryCachePath(\r\n repositoryUrl: string,\r\n namespace: GitRepositoryOptions['namespace'],\r\n version: string | undefined,\r\n): string {\r\n return getGitRepositoryCachePath(\r\n namespace,\r\n `${getRepositoryIdentity(repositoryUrl)}#${version ?? 'latest'}`,\r\n );\r\n}\r\n\r\nfunction getRepositoryCandidates(repositoryUrl: string): string[] {\r\n return [repositoryUrl];\r\n}\r\n\r\nfunction getRepositoryIdentity(repositoryUrl: string): string {\r\n try {\r\n const parsed = new URL(repositoryUrl);\r\n const repositoryPath = parsed.pathname.replace(/^\\/|\\/$/g, '').replace(/\\.git$/i, '');\r\n return `${parsed.hostname.toLowerCase()}/${repositoryPath}`;\r\n } catch {\r\n const sshMatch = repositoryUrl.match(/^[^@]+@([^:]+):(.+)$/);\r\n if (!sshMatch) {\r\n return repositoryUrl;\r\n }\r\n return `${sshMatch[1].toLowerCase()}/${sshMatch[2].replace(/\\.git$/i, '')}`;\r\n }\r\n}\r\n\r\nasync function canUseGitCache(\r\n repositoryPath: string,\r\n cacheExists: boolean,\r\n version: string | undefined,\r\n options: GitRepositoryOptions,\r\n): Promise<boolean> {\r\n if (options.forceRefresh || !cacheExists) {\r\n return false;\r\n }\r\n const stats = await fs.stat(repositoryPath);\r\n return Boolean(version) || isCacheFresh(stats.mtimeMs, options.ttlMs);\r\n}\r\n\r\nfunction debugGitRepository(\r\n repositoryUrl: string,\r\n route: NetworkRoute | 'ssh',\r\n timeoutMs: number,\r\n): void {\r\n if (process.env.GZ_CLI_FRONT_DEBUG !== '1') {\r\n return;\r\n }\r\n\r\n const routeLabel = route === 'ssh' ? 'Git/SSH' : formatNetworkRoute(route);\r\n console.log(`[git] host: ${getRepositoryHost(repositoryUrl)}`);\r\n console.log(`[git] route: ${routeLabel}`);\r\n console.log(`[git] timeout: ${timeoutMs} ms`);\r\n}\r\n\r\nfunction getRepositoryHost(repositoryUrl: string): string {\r\n try {\r\n return new URL(repositoryUrl).host;\r\n } catch {\r\n return repositoryUrl.match(/^[^@]+@([^:]+):/)?.[1] ?? 'unknown';\r\n }\r\n}\r\n\r\nasync function cloneRepository(\r\n repositoryUrl: string,\r\n targetPath: string,\r\n version: string | undefined,\r\n networkArgs: string[],\r\n timeoutMs: number,\r\n attempts: number,\r\n): Promise<void> {\r\n const args = [\r\n ...networkArgs,\r\n 'clone',\r\n '--quiet',\r\n '--depth',\r\n '1',\r\n '--single-branch',\r\n ];\r\n if (version) {\r\n args.push('--branch', version);\r\n }\r\n args.push(repositoryUrl, targetPath);\r\n\r\n for (let attempt = 1; attempt <= attempts; attempt += 1) {\r\n try {\r\n await execa('git', args, {\r\n forceKillAfterDelay: 1_000,\r\n stdin: 'inherit',\r\n stdout: 'pipe',\r\n stderr: ['pipe', 'inherit'],\r\n timeout: timeoutMs,\r\n windowsHide: true,\r\n });\r\n return;\r\n } catch (error: unknown) {\r\n if (attempt === attempts || !isTransientGitError(error)) {\r\n throw error;\r\n }\r\n if (process.env.GZ_CLI_FRONT_DEBUG === '1') {\r\n console.log(`[git] transient failure, retry: ${attempt + 1}/${attempts}`);\r\n }\r\n await fs.remove(targetPath);\r\n await delay(300);\r\n }\r\n }\r\n}\r\n\r\nfunction isTransientGitError(error: unknown): boolean {\r\n if (typeof error === 'object' && error !== null\r\n && (error as Record<string, unknown>).timedOut === true) {\r\n return true;\r\n }\r\n\r\n const message = error instanceof Error ? error.message : String(error);\r\n return [\r\n /SSL\\/TLS connection failed/i,\r\n /failed to receive handshake/i,\r\n /connection (?:was )?reset/i,\r\n /remote end hung up unexpectedly/i,\r\n /early EOF/i,\r\n /failed to connect/i,\r\n /could not resolve host/i,\r\n /timed out|timeout/i,\r\n ].some((pattern) => pattern.test(message));\r\n}\r\n\r\nasync function replaceCacheDirectory(sourcePath: string, targetPath: string): Promise<void> {\r\n const backupPath = `${targetPath}.${randomUUID()}.bak`;\r\n const targetExists = await fs.pathExists(targetPath);\r\n if (targetExists) {\r\n await fs.move(targetPath, backupPath);\r\n }\r\n\r\n try {\r\n await fs.move(sourcePath, targetPath);\r\n await fs.remove(backupPath);\r\n } catch (error: unknown) {\r\n await fs.remove(targetPath);\r\n if (await fs.pathExists(backupPath)) {\r\n await fs.move(backupPath, targetPath);\r\n }\r\n throw error;\r\n }\r\n}\r\n\r\nasync function isValidGitCache(repositoryPath: string): Promise<boolean> {\r\n return fs.pathExists(path.join(repositoryPath, '.git'));\r\n}\r\n\r\nfunction createCacheResult(\r\n repositoryPath: string,\r\n startedAt: number,\r\n staleCache: boolean,\r\n): GitRepositoryResult {\r\n return {\r\n cacheHit: true,\r\n elapsedMs: Math.round(performance.now() - startedAt),\r\n path: repositoryPath,\r\n route: staleCache ? 'stale-cache' : 'cache',\r\n staleCache,\r\n };\r\n}\r\n\r\nfunction normalizeVersion(version: string | undefined): string | undefined {\r\n return version && version !== 'latest' ? version : undefined;\r\n}\r\n\r\nfunction createGitError(\r\n repositoryUrl: string,\r\n error: unknown,\r\n stage: GitOperationStage,\r\n): Error {\r\n const message = getGitErrorMessage(error);\r\n const safeRepository = sanitizeRepositoryUrl(repositoryUrl);\r\n debugGitFailure(stage, message);\r\n if (isGitTimeoutError(error, message)) {\r\n return new Error(\r\n `Git 仓库连接超时(阶段:${stage},${GIT_AUTH_TIMEOUT_MS} ms):${safeRepository}\\n请检查当前网络或代理设置后重试。`,\r\n );\r\n }\r\n\r\n if (isGitPermissionError(message)) {\r\n return new Error(\r\n `无法访问 Git 仓库(阶段:${stage}):${safeRepository}\\n请检查仓库地址、网络连接及当前 Git 凭据后重试。`,\r\n );\r\n }\r\n\r\n return new Error(\r\n `Git 仓库访问失败(阶段:${stage}):${safeRepository}\\n请确认已安装 Git,且当前 Git/SSH 账号拥有仓库 Read 权限。\\n${message}`,\r\n );\r\n}\r\n\r\nfunction getGitErrorMessage(error: unknown): string {\r\n return redactCredentials(error instanceof Error ? error.message : '未知错误');\r\n}\r\n\r\nfunction debugGitFailure(stage: GitOperationStage, message: string): void {\r\n if (process.env.GZ_CLI_FRONT_DEBUG !== '1') {\r\n return;\r\n }\r\n\r\n console.error(`[git] failed stage: ${stage}`);\r\n console.error(`[git] error: ${message}`);\r\n}\r\n\r\nfunction isGitTimeoutError(error: unknown, message: string): boolean {\r\n if (typeof error === 'object' && error !== null\r\n && (error as Record<string, unknown>).timedOut === true) {\r\n return true;\r\n }\r\n return /timed out|timeout/i.test(message);\r\n}\r\n\r\nfunction isGitPermissionError(message: string): boolean {\r\n return [\r\n /authentication failed/i,\r\n /permission denied/i,\r\n /repository not found/i,\r\n /could not read username/i,\r\n /unable to get (?:password|username) from user/i,\r\n /terminal prompts disabled/i,\r\n /user interaction is disabled/i,\r\n /interactive prompts are disabled/i,\r\n /credential.*(?:failed|unavailable)/i,\r\n /access denied/i,\r\n /http (?:error )?40[13]/i,\r\n /status code: 40[13]/i,\r\n ].some((pattern) => pattern.test(message));\r\n}\r\n\r\nfunction redactCredentials(message: string): string {\r\n return message\r\n .replace(/http\\.proxy=\\S+/gi, 'http.proxy=***')\r\n .replace(/(https?:\\/\\/)[^@\\s/]+@/gi, '$1***@');\r\n}\r\n\r\nfunction sanitizeRepositoryUrl(repositoryUrl: string): string {\r\n try {\r\n const parsed = new URL(repositoryUrl);\r\n parsed.username = '';\r\n parsed.password = '';\r\n return parsed.toString();\r\n } catch {\r\n return repositoryUrl;\r\n }\r\n}\r\n","import fs from 'fs-extra';\r\nimport { randomUUID } from 'node:crypto';\r\nimport path from 'path';\r\nimport { performance } from 'node:perf_hooks';\r\nimport { x as extractTar } from 'tar';\r\nimport type { TemplateMeta, TemplateSource } from '../types/template.js';\r\nimport {\r\n getTemplateArchiveCachePath,\r\n isCacheFresh,\r\n TEMPLATE_ARCHIVE_CACHE_TTL_MS,\r\n} from './cache.js';\r\nimport { requestBuffer, type NetworkRoute } from './http.js';\r\nimport { ensureGitRepository } from './git-repository.js';\r\n\r\nconst TEMPLATE_DOWNLOAD_TIMEOUT_MS = 12_000;\r\n\r\nexport interface TemplateDownloadTiming {\r\n cacheHit: boolean;\r\n copyMs: number;\r\n downloadMs: number;\r\n extractMs: number;\r\n route: NetworkRoute | 'ssh' | 'cache' | 'stale-cache' | 'git' | 'bundled';\r\n}\r\n\r\nexport interface DownloadTemplateOptions {\r\n forceRefresh?: boolean;\r\n}\r\n\r\ntype TemplateDownloader = (\r\n template: TemplateMeta,\r\n targetDir: string,\r\n options: DownloadTemplateOptions,\r\n) => Promise<TemplateDownloadTiming>;\r\n\r\nconst DOWNLOADERS: Readonly<Record<TemplateSource, TemplateDownloader>> = {\r\n github: downloadFromGitHub,\r\n gitlab: downloadFromGit,\r\n git: downloadFromGit,\r\n};\r\n\r\nexport async function downloadTemplate(\r\n template: TemplateMeta,\r\n targetDir: string,\r\n options: DownloadTemplateOptions = {},\r\n): Promise<TemplateDownloadTiming> {\r\n const source = template.source ?? 'github';\r\n return DOWNLOADERS[source](template, targetDir, options);\r\n}\r\n\r\nasync function downloadFromGitHub(\r\n template: TemplateMeta,\r\n targetDir: string,\r\n options: DownloadTemplateOptions,\r\n): Promise<TemplateDownloadTiming> {\r\n const repository = normalizeGitHubRepository(getTemplateUrl(template));\r\n const version = template.version && template.version !== 'latest'\r\n ? template.version\r\n : undefined;\r\n const sourceKey = `${repository}${version ? `#${version}` : '#latest'}`;\r\n const archivePath = getTemplateArchiveCachePath(sourceKey);\r\n const archive = await ensureGitHubArchive(\r\n repository,\r\n version,\r\n archivePath,\r\n options.forceRefresh === true,\r\n );\r\n\r\n const extractStartedAt = performance.now();\r\n await fs.ensureDir(targetDir);\r\n try {\r\n await extractTar({\r\n cwd: targetDir,\r\n file: archivePath,\r\n preservePaths: false,\r\n strict: true,\r\n strip: 1,\r\n });\r\n } catch (error: unknown) {\r\n if (!archive.cacheHit) {\r\n throw error;\r\n }\r\n\r\n await fs.remove(archivePath);\r\n await fs.emptyDir(targetDir);\r\n return downloadFromGitHub(template, targetDir, { forceRefresh: true });\r\n }\r\n\r\n return {\r\n cacheHit: archive.cacheHit,\r\n copyMs: 0,\r\n downloadMs: archive.downloadMs,\r\n extractMs: Math.round(performance.now() - extractStartedAt),\r\n route: archive.route,\r\n };\r\n}\r\n\r\nasync function downloadFromGit(\r\n template: TemplateMeta,\r\n targetDir: string,\r\n options: DownloadTemplateOptions,\r\n): Promise<TemplateDownloadTiming> {\r\n if (!template.url) {\r\n throw new Error(`${template.source} 模板必须提供 Git clone URL。`);\r\n }\r\n\r\n const repository = await ensureGitRepository(template.url, {\r\n forceRefresh: options.forceRefresh,\r\n namespace: 'templates',\r\n ttlMs: TEMPLATE_ARCHIVE_CACHE_TTL_MS,\r\n version: template.version,\r\n });\r\n const copyStartedAt = performance.now();\r\n await fs.copy(repository.path, targetDir, {\r\n filter: (sourcePath) => path.basename(sourcePath) !== '.git',\r\n });\r\n\r\n return {\r\n cacheHit: repository.cacheHit,\r\n copyMs: Math.round(performance.now() - copyStartedAt),\r\n downloadMs: repository.elapsedMs,\r\n extractMs: 0,\r\n route: repository.route,\r\n };\r\n}\r\n\r\ninterface GitHubArchiveResult {\r\n cacheHit: boolean;\r\n downloadMs: number;\r\n route: NetworkRoute | 'cache';\r\n}\r\n\r\nasync function ensureGitHubArchive(\r\n repository: string,\r\n version: string | undefined,\r\n archivePath: string,\r\n forceRefresh: boolean,\r\n): Promise<GitHubArchiveResult> {\r\n const startedAt = performance.now();\r\n if (!forceRefresh && await canUseArchiveCache(archivePath, Boolean(version))) {\r\n return {\r\n cacheHit: true,\r\n downloadMs: Math.round(performance.now() - startedAt),\r\n route: 'cache',\r\n };\r\n }\r\n\r\n const archiveRequest = createGitHubArchiveRequest(repository, version);\r\n const response = await requestBuffer(archiveRequest.url, {\r\n headers: archiveRequest.headers,\r\n retries: 1,\r\n timeoutMs: TEMPLATE_DOWNLOAD_TIMEOUT_MS,\r\n });\r\n const temporaryPath = `${archivePath}.${randomUUID()}.tmp`;\r\n\r\n await fs.ensureDir(path.dirname(archivePath));\r\n try {\r\n await fs.writeFile(temporaryPath, response.body);\r\n await fs.move(temporaryPath, archivePath, { overwrite: true });\r\n } finally {\r\n await fs.remove(temporaryPath);\r\n }\r\n\r\n return {\r\n cacheHit: false,\r\n downloadMs: Math.round(performance.now() - startedAt),\r\n route: response.route,\r\n };\r\n}\r\n\r\ninterface GitHubArchiveRequest {\r\n headers: Readonly<Record<string, string>>;\r\n url: string;\r\n}\r\n\r\nfunction createGitHubArchiveRequest(\r\n repository: string,\r\n version: string | undefined,\r\n): GitHubArchiveRequest {\r\n const token = process.env.GITHUB_TOKEN?.trim();\r\n if (token) {\r\n return {\r\n headers: createGitHubApiHeaders(token),\r\n url: `https://api.github.com/repos/${repository}/tarball${version ? `/${encodeURIComponent(version)}` : ''}`,\r\n };\r\n }\r\n\r\n return {\r\n headers: { 'user-agent': 'gz-cli-front' },\r\n url: `https://codeload.github.com/${repository}/tar.gz/${encodeURIComponent(version ?? 'HEAD')}`,\r\n };\r\n}\r\n\r\nasync function canUseArchiveCache(archivePath: string, immutableVersion: boolean): Promise<boolean> {\r\n try {\r\n const stats = await fs.stat(archivePath);\r\n return stats.isFile()\r\n && (immutableVersion || isCacheFresh(stats.mtimeMs, TEMPLATE_ARCHIVE_CACHE_TTL_MS));\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\nfunction normalizeGitHubRepository(repository: string): string {\r\n const normalized = repository\r\n .replace(/^https:\\/\\/github\\.com\\//i, '')\r\n .replace(/\\.git$/i, '')\r\n .replace(/^\\/+|\\/+$/g, '');\r\n\r\n if (!/^[^/\\s]+\\/[^/\\s]+$/.test(normalized)) {\r\n throw new Error(`无效的 GitHub 模板地址:${repository}`);\r\n }\r\n\r\n return normalized;\r\n}\r\n\r\nfunction createGitHubApiHeaders(token: string): Readonly<Record<string, string>> {\r\n return {\r\n accept: 'application/vnd.github+json',\r\n authorization: `Bearer ${token}`,\r\n 'user-agent': 'gz-cli-front',\r\n 'x-github-api-version': '2022-11-28',\r\n };\r\n}\r\n\r\nfunction getTemplateUrl(template: TemplateMeta): string {\r\n if (template.url) {\r\n return template.url;\r\n }\r\n if (template.repo) {\r\n return template.repo;\r\n }\r\n throw new Error('模板配置缺少 url。');\r\n}\r\n","import chalk from 'chalk';\r\nimport { clearLine, cursorTo } from 'node:readline';\r\n\r\nconst SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];\r\nconst SPINNER_INTERVAL_MS = 80;\r\nconst RESTORE_CURSOR = '\\u001B[u';\r\nconst SAVE_CURSOR = '\\u001B[s';\r\n\r\nexport interface StableSpinner {\r\n readonly isSpinning: boolean;\r\n text: string;\r\n fail(text?: string): void;\r\n start(text?: string): void;\r\n succeed(text?: string): void;\r\n}\r\n\r\nexport function createStableSpinner(): StableSpinner {\r\n return new StableTextSpinner(process.stderr);\r\n}\r\n\r\nclass StableTextSpinner implements StableSpinner {\r\n private frameIndex = 0;\r\n private interval: NodeJS.Timeout | undefined;\r\n private readonly stream: NodeJS.WriteStream;\r\n private value = '';\r\n\r\n constructor(stream: NodeJS.WriteStream) {\r\n this.stream = stream;\r\n }\r\n\r\n get isSpinning(): boolean {\r\n return this.interval !== undefined;\r\n }\r\n\r\n get text(): string {\r\n return this.value;\r\n }\r\n\r\n set text(value: string) {\r\n this.value = value;\r\n if (this.isSpinning) {\r\n this.renderLine();\r\n }\r\n }\r\n\r\n start(text?: string): void {\r\n if (text !== undefined) {\r\n this.value = text;\r\n }\r\n if (!this.stream.isTTY || this.isSpinning) {\r\n if (!this.stream.isTTY && this.value) {\r\n this.stream.write(`- ${this.value}\\n`);\r\n }\r\n return;\r\n }\r\n\r\n this.stream.write(\r\n `${chalk.cyan(SPINNER_FRAMES[this.frameIndex])} ${this.value}${SAVE_CURSOR}`,\r\n );\r\n this.interval = setInterval(() => this.renderFrame(), SPINNER_INTERVAL_MS);\r\n }\r\n\r\n succeed(text?: string): void {\r\n this.persist(chalk.green('✔'), text);\r\n }\r\n\r\n fail(text?: string): void {\r\n this.persist(chalk.red('✖'), text);\r\n }\r\n\r\n private renderLine(): void {\r\n this.restoreAndClearLine();\r\n this.stream.write(`${chalk.cyan(SPINNER_FRAMES[this.frameIndex])} ${this.value}${SAVE_CURSOR}`);\r\n }\r\n\r\n private renderFrame(): void {\r\n this.frameIndex = (this.frameIndex + 1) % SPINNER_FRAMES.length;\r\n this.stream.write(\r\n `${RESTORE_CURSOR}\\r${chalk.cyan(SPINNER_FRAMES[this.frameIndex])}${RESTORE_CURSOR}`,\r\n );\r\n }\r\n\r\n private persist(symbol: string, text?: string): void {\r\n const finalText = text ?? this.value;\r\n this.stop();\r\n this.stream.write(`${symbol}${finalText ? ` ${finalText}` : ''}\\n`);\r\n }\r\n\r\n private stop(): boolean {\r\n if (!this.interval) {\r\n return false;\r\n }\r\n\r\n clearInterval(this.interval);\r\n this.interval = undefined;\r\n this.restoreAndClearLine();\r\n return true;\r\n }\r\n\r\n private restoreAndClearLine(): void {\r\n this.stream.write(RESTORE_CURSOR);\r\n cursorTo(this.stream, 0);\r\n clearLine(this.stream, 0);\r\n }\r\n}\r\n","import fs from 'fs-extra';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { performance } from 'node:perf_hooks';\nimport { x as extractTar } from 'tar';\nimport type { TemplateMeta } from '../types/template.js';\nimport type { TemplateDownloadTiming } from './template-downloader.js';\n\n// tsup bundles this module into dist/index.js; assets are relative to that entry.\nconst assetDirectory = fileURLToPath(new URL('./template/', import.meta.url));\nconst archivePath = path.join(assetDirectory, 'micro-app.tar.gz');\n\nexport async function loadInternalTemplate(): Promise<TemplateMeta> {\n try {\n const snapshot: unknown = await fs.readJson(path.join(assetDirectory, 'micro-app.snapshot.json'));\n if (typeof snapshot !== 'object' || snapshot === null\n || !('commit' in snapshot) || typeof snapshot.commit !== 'string'\n || !/^[a-f\\d]{40}$/.test(snapshot.commit)) {\n throw new Error('内置模板来源版本无效');\n }\n if (!(await fs.stat(archivePath)).isFile()) {\n throw new Error('内置模板文件无效');\n }\n return {\n name: 'micro-app',\n label: '微应用模板(内置)',\n description: '随 CLI 发布的 gg-cli-template-micro-app 模板快照',\n type: 'micro',\n version: snapshot.commit,\n };\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : '未知错误';\n throw new Error(`内置微应用模板不可用,请重新安装 gz-cli-front。\\n${message}`);\n }\n}\n\nexport async function copyInternalTemplate(targetDir: string): Promise<TemplateDownloadTiming> {\n const startedAt = performance.now();\n await fs.ensureDir(targetDir);\n await extractTar({\n cwd: targetDir,\n file: archivePath,\n preservePaths: false,\n strict: true,\n });\n return {\n cacheHit: false,\n copyMs: Math.round(performance.now() - startedAt),\n downloadMs: 0,\n extractMs: 0,\n route: 'bundled',\n };\n}\n","import chalk from 'chalk';\r\n\r\n/**\r\n * 检查当前 Node.js 版本是否符合要求\r\n * 要求 Node.js 版本 >= 22.19.0\r\n */\r\nexport function checkNodeVersion() {\r\n const currentVersion = process.version;\r\n // 去掉版本号前的 'v',例如 'v22.5.1' -> '22.5.1'\r\n const version = currentVersion.replace(/^v/, '');\r\n const [major] = version.split('.').map(Number);\r\n\r\n if (major < 22) {\r\n console.error(chalk.red(`\\n❌ 错误:当前 Node.js 版本 (${currentVersion}) 过低!`));\r\n console.error(chalk.yellow('⚠️ 请升级 Node.js 版本,不低于 v22.19.0'));\r\n process.exit(1);\r\n }\r\n}\r\n"],"mappings":"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","names":["chalk","execa","fs","path","performance","fs","path","fs","path","performance","path","fs","path","performance","delay","performance","fs","path","delay","performance","fs","getErrorMessage","path","fs","randomUUID","path","performance","archivePath","performance","fs","path","randomUUID","fs","path","fileURLToPath","performance","extractTar","path","chalk","getErrorMessage","performance","fs","execa","chalk","require"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/commands/create.ts","../src/services/config.ts","../src/utils/pkg-manager.ts","../src/utils/template.ts","../src/utils/cache.ts","../src/utils/http.ts","../src/utils/system-proxy.ts","../src/utils/git-repository.ts","../src/utils/template-downloader.ts","../src/utils/stable-spinner.ts","../src/utils/internal-template.ts","../src/pre/index.ts"],"sourcesContent":["import { Command, Option } from 'commander';\r\nimport { createRequire } from 'node:module';\r\nimport { create } from './commands/create.js';\r\nimport { checkNodeVersion } from './pre/index.js';\r\n\r\n// 1. 前置检查:Node.js 版本\r\ncheckNodeVersion();\r\n\r\nconst program = new Command();\r\nconst require = createRequire(import.meta.url);\r\nconst packageMetadata: unknown = require('../package.json');\r\nconst packageVersion = getPackageVersion(packageMetadata);\r\n\r\nprogram\r\n .name('gz-cli')\r\n .description('前端脚手架工具')\r\n .version(packageVersion);\r\n\r\n// 将 init 设为默认命令,参数改为可选 [project-name]\r\nprogram\r\n .command('init [project-name]', { isDefault: true })\r\n .description('创建一个新项目')\r\n .addOption(new Option('-i, --internal', '选择内置主应用或微应用模板,不访问远程模板仓库').conflicts('refresh'))\r\n .option('--pm <package-manager>', '指定包管理器:npm、pnpm 或 yarn')\r\n .option('--proxy <url>', '指定本次初始化使用的 HTTP(S) 代理')\r\n .option('--no-proxy', '强制直连,不读取环境变量或系统代理')\r\n .option('--refresh', '忽略模板配置和模板缓存,强制从远程仓库刷新')\r\n .action((projectName, options) => {\r\n void create(projectName, options);\r\n });\r\n\r\nprogram\r\n .command('create [project-name]')\r\n .description('创建一个新项目(兼容旧命令)')\r\n .addOption(new Option('-i, --internal', '选择内置主应用或微应用模板,不访问远程模板仓库').conflicts('refresh'))\r\n .option('--pm <package-manager>', '指定包管理器:npm、pnpm 或 yarn')\r\n .option('--proxy <url>', '指定本次初始化使用的 HTTP(S) 代理')\r\n .option('--no-proxy', '强制直连,不读取环境变量或系统代理')\r\n .option('--refresh', '忽略模板配置和模板缓存,强制从远程仓库刷新')\r\n .action((projectName, options) => {\r\n void create(projectName, options);\r\n });\r\n\r\nprogram.parse(process.argv);\r\n\r\nfunction getPackageVersion(value: unknown): string {\r\n if (typeof value !== 'object' || value === null) {\r\n throw new Error('无法读取 gz-cli-front 版本号。');\r\n }\r\n\r\n const version = (value as Record<string, unknown>).version;\r\n if (typeof version !== 'string' || !version.trim()) {\r\n throw new Error('gz-cli-front package.json 中缺少有效版本号。');\r\n }\r\n return version;\r\n}\r\n","import { confirm, input, select } from '@inquirer/prompts';\r\nimport chalk from 'chalk';\r\nimport { execa } from 'execa';\r\nimport fs from 'fs-extra';\r\nimport ora from 'ora';\r\nimport path from 'path';\r\nimport { performance } from 'node:perf_hooks';\r\nimport { loadCliConfig } from '../services/config.js';\r\nimport {\r\n detectPackageManager,\r\n isPackageManager,\r\n updateProjectPackageJson,\r\n type PackageManager,\r\n} from '../utils/pkg-manager.js';\r\nimport {\r\n fetchTemplates,\r\n replaceTemplateVariables,\r\n type FetchTemplatesResult,\r\n type TemplateMeta,\r\n} from '../utils/template.js';\r\nimport { downloadTemplate, type TemplateDownloadTiming } from '../utils/template-downloader.js';\r\nimport { configureNetwork, type NetworkRoute } from '../utils/http.js';\r\nimport { createStableSpinner } from '../utils/stable-spinner.js';\r\nimport { copyInternalTemplate, loadInternalTemplates } from '../utils/internal-template.js';\r\n\r\nexport interface InitOptions {\r\n internal?: boolean;\r\n pm?: string;\r\n proxy?: string | false;\r\n refresh?: boolean;\r\n}\r\n\r\ninterface InitContext {\r\n projectName: string;\r\n template: TemplateMeta;\r\n packageManager: PackageManager;\r\n}\r\n\r\ninterface TemplateTiming {\r\n configRoute: NetworkRoute | 'ssh' | 'cache' | 'stale-cache' | 'bundled';\r\n copyMs: number;\r\n fetchConfigMs: number;\r\n parseConfigMs: number;\r\n templateRoute: TemplateDownloadTiming['route'];\r\n downloadMs: number;\r\n extractMs: number;\r\n renderMs: number;\r\n}\r\n\r\nexport async function create(projectName?: string, options: InitOptions = {}): Promise<void> {\r\n try {\r\n if (!options.internal) {\r\n configureNetwork({\r\n forceDirect: options.proxy === false,\r\n proxy: typeof options.proxy === 'string' ? options.proxy : undefined,\r\n });\r\n }\r\n const templateTiming = createTemplateTiming();\r\n const context = await createInitContext(projectName, options, templateTiming);\r\n const targetPath = path.resolve(process.cwd(), context.projectName);\r\n\r\n if (!(await prepareTargetDirectory(targetPath, context.projectName))) {\r\n return;\r\n }\r\n\r\n const install = await confirm({\r\n message: '是否自动安装依赖?',\r\n default: true,\r\n });\r\n\r\n await downloadAndGenerate(context, targetPath, templateTiming, options);\r\n await installDependencies(install, targetPath, context.packageManager);\r\n await initializeGit(targetPath);\r\n printNextSteps(context, install);\r\n } catch (error: unknown) {\r\n if (isUserCancellation(error)) {\r\n console.log(chalk.yellow('\\n已取消操作。'));\r\n return;\r\n }\r\n\r\n console.error(chalk.red(`创建项目失败:${getErrorMessage(error)}`));\r\n }\r\n}\r\n\r\nasync function createInitContext(\r\n projectName: string | undefined,\r\n options: InitOptions,\r\n templateTiming: TemplateTiming,\r\n): Promise<InitContext> {\r\n const finalProjectName = await getProjectName(projectName);\r\n const templates = await loadTemplates(templateTiming, options);\r\n const template = await chooseTemplate(templates);\r\n\r\n return {\r\n projectName: finalProjectName,\r\n template,\r\n packageManager: resolvePackageManager(options.pm),\r\n };\r\n}\r\n\r\nasync function getProjectName(projectName?: string): Promise<string> {\r\n if (projectName?.trim()) {\r\n return projectName.trim();\r\n }\r\n\r\n return input({\r\n message: '请输入项目名称:',\r\n validate: (value) => value.trim() ? true : '项目名称不能为空',\r\n });\r\n}\r\n\r\nasync function loadTemplates(\r\n templateTiming: TemplateTiming,\r\n options: InitOptions,\r\n): Promise<TemplateMeta[]> {\r\n if (options.internal) {\r\n const startedAt = performance.now();\r\n const templates = await loadInternalTemplates();\r\n templateTiming.configRoute = 'bundled';\r\n templateTiming.fetchConfigMs = Math.round(performance.now() - startedAt);\r\n console.log(chalk.cyan('内网模式:使用内置模板,不访问远程模板仓库。'));\r\n return templates;\r\n }\r\n\r\n const spinner = createStableSpinner();\r\n try {\r\n const config = await loadCliConfig();\r\n spinner.start('正在获取远程模板配置...');\r\n const result = await fetchTemplates(config.templateRegistry, {\r\n forceRefresh: options.refresh === true,\r\n });\r\n assignFetchTiming(templateTiming, result);\r\n spinner.succeed('远程模板配置获取成功');\r\n if (result.staleCache) {\r\n console.log(chalk.yellow('远程模板配置暂时不可用,已使用本地缓存。'));\r\n }\r\n return result.templates;\r\n } catch (error: unknown) {\r\n if (spinner.isSpinning) {\r\n spinner.fail('获取远程模板配置失败');\r\n } else {\r\n console.error(chalk.red('获取远程模板配置失败'));\r\n }\r\n const message = error instanceof Error && error.message\r\n ? error.message\r\n : '未知错误';\r\n throw new Error(`获取远程模板配置失败,请检查网络或模板配置地址。\\n${message}`);\r\n }\r\n}\r\n\r\nasync function chooseTemplate(templates: TemplateMeta[]): Promise<TemplateMeta> {\r\n return select({\r\n message: '请选择项目模板:',\r\n choices: templates.map((template) => ({\r\n name: `${template.label} (${template.name}) - ${template.description}`,\r\n value: template,\r\n })),\r\n default: templates.find((template) => template.type === 'micro') ?? templates[0],\r\n });\r\n}\r\n\r\nfunction resolvePackageManager(requestedPackageManager?: string): PackageManager {\r\n if (requestedPackageManager !== undefined) {\r\n if (!isPackageManager(requestedPackageManager)) {\r\n throw new Error(\r\n `不支持的 packageManager: ${requestedPackageManager}\\n支持: npm、pnpm、yarn`,\r\n );\r\n }\r\n return requestedPackageManager;\r\n }\r\n\r\n const packageManager = detectPackageManager();\r\n if (packageManager === 'npm') {\r\n console.log(chalk.yellow('未检测到 pnpm 或 yarn,自动使用 npm。'));\r\n }\r\n return packageManager;\r\n}\r\n\r\nasync function prepareTargetDirectory(targetPath: string, projectName: string): Promise<boolean> {\r\n if (!(await fs.pathExists(targetPath))) {\r\n return true;\r\n }\r\n\r\n const overwrite = await confirm({\r\n message: `目录 ${projectName} 已存在,是否覆盖?`,\r\n default: false,\r\n });\r\n\r\n if (!overwrite) {\r\n console.log(chalk.yellow('已取消创建。'));\r\n return false;\r\n }\r\n\r\n await fs.remove(targetPath);\r\n return true;\r\n}\r\n\r\nasync function downloadAndGenerate(\r\n context: InitContext,\r\n targetPath: string,\r\n templateTiming: TemplateTiming,\r\n options: InitOptions,\r\n): Promise<void> {\r\n const { template, projectName, packageManager } = context;\r\n const spinner = createStableSpinner();\r\n const downloadStartedAt = performance.now();\r\n try {\r\n spinner.start(options.internal ? `正在复制${template.label}...` : `正在下载模板 ${template.label}...`);\r\n const downloadTiming = options.internal\r\n ? await copyInternalTemplate(template, targetPath)\r\n : await downloadTemplate(template, targetPath, {\r\n forceRefresh: options.refresh === true,\r\n });\r\n assignDownloadTiming(templateTiming, downloadTiming);\r\n } catch (error: unknown) {\r\n templateTiming.downloadMs = Math.round(performance.now() - downloadStartedAt);\r\n await fs.remove(targetPath);\r\n if (spinner.isSpinning) {\r\n spinner.fail(options.internal ? '内置模板读取失败' : '模板下载失败');\r\n } else {\r\n console.error(chalk.red(options.internal ? '内置模板读取失败' : '模板下载失败'));\r\n }\r\n printTemplateTiming(templateTiming);\r\n const message = error instanceof Error && error.message\r\n ? error.message\r\n : '未知错误';\r\n throw new Error(options.internal\r\n ? `内置模板读取失败,请重新安装 gz-cli-front。\\n${message}`\r\n : `模板下载失败,请检查仓库地址或网络连接。\\n${message}`);\r\n }\r\n\r\n try {\r\n spinner.text = '正在替换模板变量...';\r\n const startedAt = performance.now();\r\n await replaceTemplateVariables(targetPath, { projectName });\r\n await updateProjectPackageJson(targetPath, projectName, packageManager);\r\n templateTiming.renderMs = Math.round(performance.now() - startedAt);\r\n spinner.succeed(options.internal ? '内置模板生成完成' : '模板下载并生成完成');\r\n printTemplateTiming(templateTiming);\r\n } catch {\r\n await fs.remove(targetPath);\r\n spinner.fail('模板下载或变量替换失败');\r\n throw new Error('模板变量替换失败,请检查模板文件内容。');\r\n }\r\n}\r\n\r\nfunction createTemplateTiming(): TemplateTiming {\r\n return {\r\n configRoute: 'direct',\r\n copyMs: 0,\r\n fetchConfigMs: 0,\r\n parseConfigMs: 0,\r\n templateRoute: 'direct',\r\n downloadMs: 0,\r\n extractMs: 0,\r\n renderMs: 0,\r\n };\r\n}\r\n\r\nfunction assignFetchTiming(\r\n templateTiming: TemplateTiming,\r\n result: FetchTemplatesResult,\r\n): void {\r\n templateTiming.fetchConfigMs = result.fetchMs;\r\n templateTiming.parseConfigMs = result.parseMs;\r\n templateTiming.configRoute = result.route;\r\n}\r\n\r\nfunction assignDownloadTiming(\r\n templateTiming: TemplateTiming,\r\n downloadTiming: TemplateDownloadTiming,\r\n): void {\r\n templateTiming.copyMs = downloadTiming.copyMs;\r\n templateTiming.downloadMs = downloadTiming.downloadMs;\r\n templateTiming.extractMs = downloadTiming.extractMs;\r\n templateTiming.templateRoute = downloadTiming.route;\r\n}\r\n\r\nfunction printTemplateTiming(templateTiming: TemplateTiming): void {\r\n console.log('\\n[template]');\r\n console.log(`fetch config: ${templateTiming.fetchConfigMs} ms (${formatRoute(templateTiming.configRoute)})`);\r\n console.log(`parse config: ${templateTiming.parseConfigMs} ms`);\r\n console.log(`download: ${templateTiming.downloadMs} ms (${formatRoute(templateTiming.templateRoute)})`);\r\n console.log(`extract: ${templateTiming.extractMs} ms`);\r\n console.log(`copy: ${templateTiming.copyMs} ms`);\r\n console.log(`render: ${templateTiming.renderMs} ms`);\r\n}\r\n\r\nfunction formatRoute(route: TemplateTiming['configRoute'] | TemplateTiming['templateRoute']): string {\r\n if (route === 'bundled') {\r\n return 'bundled, 内置模板';\r\n }\r\n if (route === 'proxy-environment') {\r\n return 'remote, 环境变量代理';\r\n }\r\n if (route === 'proxy-system') {\r\n return 'remote, 系统代理';\r\n }\r\n if (route === 'direct') {\r\n return 'remote, 直连';\r\n }\r\n if (route === 'ssh') {\r\n return 'remote, Git/SSH';\r\n }\r\n return route.replace('-', ' ');\r\n}\r\n\r\nasync function installDependencies(\r\n install: boolean,\r\n targetPath: string,\r\n packageManager: PackageManager,\r\n): Promise<void> {\r\n if (!install) {\r\n return;\r\n }\r\n\r\n const installCommand = packageManager === 'yarn' ? [] : ['install'];\r\n const spinner = ora(`正在安装依赖 (${packageManager} ${installCommand.join(' ')})...`).start();\r\n try {\r\n await execa(packageManager, installCommand, { cwd: targetPath });\r\n spinner.succeed('依赖安装成功');\r\n } catch {\r\n spinner.warn('依赖安装失败,请进入项目目录后手动安装');\r\n }\r\n}\r\n\r\nasync function initializeGit(targetPath: string): Promise<void> {\r\n const spinner = ora('正在初始化 Git 仓库...').start();\r\n try {\r\n await execa('git', ['init'], { cwd: targetPath });\r\n spinner.succeed('Git 仓库初始化成功');\r\n } catch {\r\n spinner.warn('Git 仓库初始化失败,请确认 Git 已安装');\r\n }\r\n}\r\n\r\nfunction printNextSteps(context: InitContext, installed: boolean): void {\r\n const { projectName, packageManager } = context;\r\n const installCommand = packageManager === 'yarn' ? 'yarn' : `${packageManager} install`;\r\n const devCommand = packageManager === 'npm' ? 'npm run dev' : `${packageManager} dev`;\r\n\r\n console.log(chalk.green(`\\n项目 ${projectName} 创建成功!`));\r\n console.log('\\n接下来你可以:\\n');\r\n console.log(chalk.cyan(` cd ${projectName}`));\r\n if (!installed) {\r\n console.log(chalk.cyan(` ${installCommand}`));\r\n }\r\n console.log(chalk.cyan(` ${devCommand}`));\r\n}\r\n\r\nfunction isUserCancellation(error: unknown): boolean {\r\n return error instanceof Error && /User force closed|User cancelled/i.test(error.message);\r\n}\r\n\r\nfunction getErrorMessage(error: unknown): string {\r\n return error instanceof Error && error.message ? ` ${error.message}` : '';\r\n}\r\n","import fs from 'fs-extra';\r\nimport path from 'path';\r\nimport { fileURLToPath } from 'url';\r\nimport type { CliConfig } from '../types/config.js';\r\n\r\nconst CONFIG_FILE_NAME = 'gz-cli-front.config.json';\r\n\r\nexport async function loadCliConfig(): Promise<CliConfig> {\r\n const configPath = await findConfigPath();\r\n const config: unknown = await fs.readJson(configPath);\r\n\r\n if (!isCliConfig(config)) {\r\n throw new Error(`CLI 配置文件无效:${configPath}`);\r\n }\r\n\r\n return config;\r\n}\r\n\r\nasync function findConfigPath(): Promise<string> {\r\n const moduleDirectory = path.dirname(fileURLToPath(import.meta.url));\r\n const configPaths = [\r\n path.resolve(moduleDirectory, 'config', CONFIG_FILE_NAME),\r\n path.resolve(moduleDirectory, '..', 'config', CONFIG_FILE_NAME),\r\n path.resolve(moduleDirectory, '..', '..', 'config', CONFIG_FILE_NAME),\r\n ];\r\n\r\n for (const configPath of configPaths) {\r\n if (await fs.pathExists(configPath)) {\r\n return configPath;\r\n }\r\n }\r\n\r\n throw new Error('未找到 gz-cli-front 配置文件。');\r\n}\r\n\r\nfunction isCliConfig(value: unknown): value is CliConfig {\r\n if (typeof value !== 'object' || value === null) {\r\n return false;\r\n }\r\n\r\n const templateRegistry = (value as Record<string, unknown>).templateRegistry;\r\n if (typeof templateRegistry !== 'object' || templateRegistry === null) {\r\n return false;\r\n }\r\n\r\n return isTemplateRegistryConfig(templateRegistry as Record<string, unknown>);\r\n}\r\n\r\nfunction isTemplateRegistryConfig(value: Record<string, unknown>): boolean {\r\n if (!isNonEmptyString(value.url)) {\r\n return false;\r\n }\r\n\r\n if (value.source === undefined || value.source === 'http') {\r\n return true;\r\n }\r\n\r\n return value.source === 'git'\r\n && isNonEmptyString(value.file)\r\n && (value.version === undefined || isNonEmptyString(value.version));\r\n}\r\n\r\nfunction isNonEmptyString(value: unknown): value is string {\r\n return typeof value === 'string' && value.trim().length > 0;\r\n}\r\n","import fs from 'fs-extra';\r\nimport path from 'path';\r\nimport { spawnSync } from 'node:child_process';\r\n\r\nexport type PackageManager = 'npm' | 'pnpm' | 'yarn';\r\n\r\nconst PACKAGE_MANAGERS: readonly PackageManager[] = ['pnpm', 'yarn', 'npm'];\r\n\r\nexport function detectPackageManager(): PackageManager {\r\n return PACKAGE_MANAGERS.find(isPackageManagerAvailable) ?? 'npm';\r\n}\r\n\r\nexport function isPackageManager(value: string): value is PackageManager {\r\n return PACKAGE_MANAGERS.includes(value as PackageManager);\r\n}\r\n\r\nexport async function updateProjectPackageJson(\r\n targetDir: string,\r\n projectName: string,\r\n packageManager: PackageManager,\r\n): Promise<void> {\r\n const packageJsonPath = path.join(targetDir, 'package.json');\r\n if (!(await fs.pathExists(packageJsonPath))) {\r\n return;\r\n }\r\n\r\n const packageJson: Record<string, unknown> = await fs.readJson(packageJsonPath);\r\n packageJson.name = projectName;\r\n\r\n if (Object.prototype.hasOwnProperty.call(packageJson, 'packageManager')) {\r\n packageJson.packageManager = packageManager;\r\n }\r\n\r\n await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });\r\n}\r\n\r\nfunction isPackageManagerAvailable(packageManager: PackageManager): boolean {\r\n const result = spawnSync(packageManager, ['--version'], {\r\n shell: process.platform === 'win32',\r\n stdio: 'ignore',\r\n });\r\n\r\n return result.status === 0;\r\n}\r\n","import fs from 'fs-extra';\r\nimport path from 'path';\r\nimport { performance } from 'node:perf_hooks';\r\nimport type { TemplateRegistryConfig } from '../types/config.js';\r\nimport type { TemplateMeta, TemplateSource, TemplateType } from '../types/template.js';\r\nimport {\r\n getTemplateRegistryCachePath,\r\n isCacheFresh,\r\n TEMPLATE_REGISTRY_CACHE_TTL_MS,\r\n} from './cache.js';\r\nimport { requestBuffer, type NetworkRoute } from './http.js';\r\nimport { ensureGitRepository } from './git-repository.js';\r\n\r\nconst TEXT_FILE_EXTENSIONS = new Set([\r\n '.json', '.ts', '.tsx', '.js', '.jsx', '.md', '.html', '.css', '.less', '.scss', '.env',\r\n]);\r\nconst IGNORED_DIRECTORIES = new Set(['node_modules', 'dist', '.git']);\r\nconst TEMPLATE_DEBUG_ENV = 'GZ_CLI_FRONT_DEBUG';\r\nconst TEMPLATE_REGISTRY_TIMEOUT_MS = 5_000;\r\n\r\ninterface TemplateRegistryCache {\r\n body: string;\r\n fetchedAt: number;\r\n url: string;\r\n}\r\n\r\nexport interface FetchTemplatesOptions {\r\n forceRefresh?: boolean;\r\n}\r\n\r\nexport interface FetchTemplatesResult {\r\n cacheHit: boolean;\r\n fetchMs: number;\r\n parseMs: number;\r\n route: NetworkRoute | 'ssh' | 'cache' | 'stale-cache';\r\n staleCache: boolean;\r\n templates: TemplateMeta[];\r\n}\r\n\r\nexport type { TemplateMeta, TemplateSource, TemplateType } from '../types/template.js';\r\n\r\nexport async function fetchTemplates(\r\n templateRegistry: TemplateRegistryConfig | string,\r\n options: FetchTemplatesOptions = {},\r\n): Promise<FetchTemplatesResult> {\r\n const registry = typeof templateRegistry === 'string'\r\n ? { url: templateRegistry } satisfies TemplateRegistryConfig\r\n : templateRegistry;\r\n\r\n if (registry.source === 'git') {\r\n return fetchTemplatesFromGit(registry, options);\r\n }\r\n\r\n return fetchTemplatesFromHttp(registry.url, options);\r\n}\r\n\r\nasync function fetchTemplatesFromHttp(\r\n templateRegistryUrl: string,\r\n options: FetchTemplatesOptions,\r\n): Promise<FetchTemplatesResult> {\r\n const cachePath = getTemplateRegistryCachePath(templateRegistryUrl);\r\n const cacheStartedAt = performance.now();\r\n let cached = await readRegistryCache(cachePath, templateRegistryUrl);\r\n const cacheReadMs = Math.round(performance.now() - cacheStartedAt);\r\n debugTemplateRequest(templateRegistryUrl, cachePath, options.forceRefresh === true);\r\n\r\n if (!options.forceRefresh && cached\r\n && isCacheFresh(cached.fetchedAt, TEMPLATE_REGISTRY_CACHE_TTL_MS)) {\r\n try {\r\n return parseTemplates(cached.body, true, false, cacheReadMs, 'cache');\r\n } catch {\r\n await fs.remove(cachePath);\r\n cached = undefined;\r\n }\r\n }\r\n\r\n const fetchStartedAt = performance.now();\r\n try {\r\n const response = await requestBuffer(templateRegistryUrl, {\r\n retries: 1,\r\n timeoutMs: TEMPLATE_REGISTRY_TIMEOUT_MS,\r\n });\r\n const body = response.body.toString('utf8');\r\n const result = parseTemplates(body, false, false, response.elapsedMs, response.route);\r\n try {\r\n await writeRegistryCache(cachePath, {\r\n body,\r\n fetchedAt: Date.now(),\r\n url: templateRegistryUrl,\r\n });\r\n } catch (error: unknown) {\r\n if (process.env[TEMPLATE_DEBUG_ENV] === '1') {\r\n console.log(`template config cache write failed: ${getErrorMessage(error)}`);\r\n }\r\n }\r\n return result;\r\n } catch (error: unknown) {\r\n if (!options.forceRefresh && cached) {\r\n return parseTemplates(\r\n cached.body,\r\n true,\r\n true,\r\n Math.round(performance.now() - fetchStartedAt),\r\n 'stale-cache',\r\n );\r\n }\r\n throw createTemplateRequestError(templateRegistryUrl, error);\r\n }\r\n}\r\n\r\nasync function fetchTemplatesFromGit(\r\n registry: Extract<TemplateRegistryConfig, { source: 'git' }>,\r\n options: FetchTemplatesOptions,\r\n): Promise<FetchTemplatesResult> {\r\n const cacheKey = `git:${registry.url}#${registry.version ?? 'latest'}:${registry.file}`;\r\n const fallbackCachePath = getTemplateRegistryCachePath(cacheKey);\r\n const fallbackCache = await readRegistryCache(fallbackCachePath, cacheKey);\r\n const startedAt = performance.now();\r\n\r\n try {\r\n const result = await ensureGitRepository(registry.url, {\r\n forceRefresh: options.forceRefresh,\r\n namespace: 'registry',\r\n ttlMs: TEMPLATE_REGISTRY_CACHE_TTL_MS,\r\n version: registry.version,\r\n });\r\n const registryFile = resolveRegistryFile(result.path, registry.file);\r\n const body = await fs.readFile(registryFile, 'utf8');\r\n const parsed = parseTemplates(\r\n body,\r\n result.cacheHit,\r\n result.staleCache,\r\n result.elapsedMs,\r\n result.route,\r\n );\r\n if (!result.cacheHit || !fallbackCache) {\r\n await writeRegistryCache(fallbackCachePath, {\r\n body,\r\n fetchedAt: Date.now(),\r\n url: cacheKey,\r\n }).catch(() => undefined);\r\n }\r\n return parsed;\r\n } catch (error: unknown) {\r\n if (!options.forceRefresh && fallbackCache) {\r\n return parseTemplates(\r\n fallbackCache.body,\r\n true,\r\n true,\r\n Math.round(performance.now() - startedAt),\r\n 'stale-cache',\r\n );\r\n }\r\n throw new Error(`模板注册仓库读取失败\\nerror: ${getErrorMessage(error)}`);\r\n }\r\n}\r\n\r\nfunction resolveRegistryFile(repositoryPath: string, registryFile: string): string {\r\n const resolvedRepository = path.resolve(repositoryPath);\r\n const resolvedFile = path.resolve(repositoryPath, registryFile);\r\n if (resolvedFile !== resolvedRepository\r\n && !resolvedFile.startsWith(`${resolvedRepository}${path.sep}`)) {\r\n throw new Error(`模板注册文件必须位于注册仓库内:${registryFile}`);\r\n }\r\n return resolvedFile;\r\n}\r\n\r\nfunction parseTemplates(\r\n body: string,\r\n cacheHit: boolean,\r\n staleCache: boolean,\r\n fetchMs: number,\r\n route: FetchTemplatesResult['route'],\r\n): FetchTemplatesResult {\r\n const parseStartedAt = performance.now();\r\n let data: unknown;\r\n\r\n try {\r\n data = JSON.parse(body);\r\n } catch (error: unknown) {\r\n throw new Error(`模板配置 JSON 解析失败:${getErrorMessage(error)}`);\r\n }\r\n if (!Array.isArray(data) || data.length === 0) {\r\n throw new Error('模板注册表为空');\r\n }\r\n\r\n const templates = data.filter(isTemplateMeta);\r\n if (templates.length === 0) {\r\n throw new Error('模板注册表中没有有效模板');\r\n }\r\n\r\n return {\r\n cacheHit,\r\n fetchMs,\r\n parseMs: Math.round(performance.now() - parseStartedAt),\r\n route,\r\n staleCache,\r\n templates,\r\n };\r\n}\r\n\r\nfunction debugTemplateRequest(\r\n templateRegistryUrl: string,\r\n cachePath: string,\r\n forceRefresh: boolean,\r\n): void {\r\n if (process.env[TEMPLATE_DEBUG_ENV] !== '1') {\r\n return;\r\n }\r\n\r\n console.log('template config url:', templateRegistryUrl);\r\n console.log('template config client: undici fetch');\r\n console.log(`template config timeout: ${TEMPLATE_REGISTRY_TIMEOUT_MS} ms`);\r\n console.log('template config cache:', cachePath);\r\n console.log('template config force refresh:', forceRefresh);\r\n}\r\n\r\nfunction createTemplateRequestError(templateRegistryUrl: string, error: unknown): Error {\r\n return new Error(\r\n `模板配置请求失败\\nurl: ${templateRegistryUrl}\\nerror: ${getErrorMessage(error)}`,\r\n );\r\n}\r\n\r\nfunction getErrorMessage(error: unknown): string {\r\n if (!(error instanceof Error)) {\r\n return '未知错误';\r\n }\r\n\r\n const cause = 'cause' in error ? error.cause : undefined;\r\n const causeMessage = cause instanceof Error ? cause.message : String(cause ?? '');\r\n return causeMessage ? `${error.message} (${causeMessage})` : error.message;\r\n}\r\n\r\nasync function readRegistryCache(\r\n cachePath: string,\r\n templateRegistryUrl: string,\r\n): Promise<TemplateRegistryCache | undefined> {\r\n try {\r\n const cache: unknown = await fs.readJson(cachePath);\r\n if (!isRecord(cache)\r\n || cache.url !== templateRegistryUrl\r\n || typeof cache.body !== 'string'\r\n || typeof cache.fetchedAt !== 'number') {\r\n return undefined;\r\n }\r\n return {\r\n body: cache.body,\r\n fetchedAt: cache.fetchedAt,\r\n url: cache.url,\r\n };\r\n } catch {\r\n return undefined;\r\n }\r\n}\r\n\r\nasync function writeRegistryCache(\r\n cachePath: string,\r\n cache: TemplateRegistryCache,\r\n): Promise<void> {\r\n await fs.ensureDir(path.dirname(cachePath));\r\n await fs.writeJson(cachePath, cache);\r\n}\r\n\r\nexport async function replaceTemplateVariables(\r\n targetDir: string,\r\n variables: Readonly<Record<string, string>>,\r\n): Promise<void> {\r\n await visitDirectory(targetDir, async (filePath) => {\r\n if (!shouldProcessFile(filePath)) {\r\n return;\r\n }\r\n\r\n const content = await fs.readFile(filePath, 'utf8');\r\n const replaced = Object.entries(variables).reduce(\r\n (result, [key, value]) => result.split(`{{ ${key} }}`).join(value),\r\n content,\r\n );\r\n\r\n if (replaced !== content) {\r\n await fs.writeFile(filePath, replaced, 'utf8');\r\n }\r\n });\r\n}\r\n\r\nasync function visitDirectory(\r\n directory: string,\r\n onFile: (filePath: string) => Promise<void>,\r\n): Promise<void> {\r\n const entries = await fs.readdir(directory, { withFileTypes: true });\r\n for (const entry of entries) {\r\n const entryPath = path.join(directory, entry.name);\r\n if (entry.isDirectory()) {\r\n if (!IGNORED_DIRECTORIES.has(entry.name)) {\r\n await visitDirectory(entryPath, onFile);\r\n }\r\n } else if (entry.isFile()) {\r\n await onFile(entryPath);\r\n }\r\n }\r\n}\r\n\r\nfunction shouldProcessFile(filePath: string): boolean {\r\n const filename = path.basename(filePath);\r\n return TEXT_FILE_EXTENSIONS.has(path.extname(filename)) || filename.startsWith('.env');\r\n}\r\n\r\nfunction isTemplateMeta(value: unknown): value is TemplateMeta {\r\n if (!isRecord(value)) {\r\n return false;\r\n }\r\n\r\n return isString(value.name)\r\n && isString(value.label)\r\n && isString(value.description)\r\n && isTemplateType(value.type)\r\n && isTemplateLocation(value)\r\n && (value.version === undefined || isString(value.version));\r\n}\r\n\r\nfunction isRecord(value: unknown): value is Record<string, unknown> {\r\n return typeof value === 'object' && value !== null;\r\n}\r\n\r\nfunction isString(value: unknown): value is string {\r\n return typeof value === 'string' && value.trim().length > 0;\r\n}\r\n\r\nfunction isTemplateType(value: unknown): value is TemplateType {\r\n return value === 'main' || value === 'micro';\r\n}\r\n\r\nfunction isTemplateLocation(value: Record<string, unknown>): boolean {\r\n if (value.source !== undefined && !isTemplateSource(value.source)) {\r\n return false;\r\n }\r\n\r\n if (isString(value.url)) {\r\n return true;\r\n }\r\n\r\n return value.source === undefined && isString(value.repo);\r\n}\r\n\r\nfunction isTemplateSource(value: unknown): value is TemplateSource {\r\n return value === 'github' || value === 'gitlab' || value === 'git';\r\n}\r\n","import { createHash } from 'node:crypto';\r\nimport os from 'node:os';\r\nimport path from 'node:path';\r\n\r\nexport const TEMPLATE_REGISTRY_CACHE_TTL_MS = 5 * 60 * 1000;\r\nexport const TEMPLATE_ARCHIVE_CACHE_TTL_MS = 10 * 60 * 1000;\r\n\r\nexport function getTemplateRegistryCachePath(url: string): string {\r\n return path.join(getCacheDirectory(), 'registry', `${createCacheKey(url)}.json`);\r\n}\r\n\r\nexport function getTemplateArchiveCachePath(source: string): string {\r\n return path.join(getCacheDirectory(), 'templates', `${createCacheKey(source)}.tar.gz`);\r\n}\r\n\r\nexport function getGitRepositoryCachePath(\r\n namespace: 'registry' | 'templates',\r\n source: string,\r\n): string {\r\n return path.join(getCacheDirectory(), namespace, `git-${createCacheKey(source)}`);\r\n}\r\n\r\nexport function isCacheFresh(updatedAt: number, ttlMs: number): boolean {\r\n return Date.now() - updatedAt < ttlMs;\r\n}\r\n\r\nfunction getCacheDirectory(): string {\r\n const configuredDirectory = process.env.GZ_CLI_FRONT_CACHE_DIR?.trim();\r\n return configuredDirectory || path.join(os.homedir(), '.gz-cli-front', 'cache');\r\n}\r\n\r\nfunction createCacheKey(value: string): string {\r\n return createHash('sha256').update(value).digest('hex').slice(0, 24);\r\n}\r\n","import { setTimeout as delay } from 'node:timers/promises';\r\nimport {\r\n EnvHttpProxyAgent,\r\n ProxyAgent,\r\n fetch as undiciFetch,\r\n type Dispatcher,\r\n} from 'undici';\r\nimport { getSystemProxy } from './system-proxy.js';\r\n\r\nexport interface NetworkOptions {\r\n forceDirect?: boolean;\r\n proxy?: string;\r\n}\r\n\r\nexport interface HttpRequestOptions {\r\n headers?: Readonly<Record<string, string>>;\r\n retries: number;\r\n timeoutMs: number;\r\n}\r\n\r\nexport interface HttpResponseData {\r\n body: Buffer;\r\n elapsedMs: number;\r\n route: NetworkRoute;\r\n status: number;\r\n}\r\n\r\nexport type NetworkRoute = 'direct' | 'proxy-environment' | 'proxy-system';\r\n\r\nlet networkOptions: NetworkOptions = {};\r\n\r\nexport function configureNetwork(options: NetworkOptions): void {\r\n if (options.proxy) {\r\n validateProxyUrl(options.proxy);\r\n }\r\n networkOptions = { ...options };\r\n}\r\n\r\nexport async function requestBuffer(\r\n url: string,\r\n options: HttpRequestOptions,\r\n): Promise<HttpResponseData> {\r\n const startedAt = performance.now();\r\n let lastError: unknown;\r\n const proxyConfig = await resolveProxyConfig(url);\r\n\r\n for (let attempt = 0; attempt <= options.retries; attempt += 1) {\r\n const controller = new AbortController();\r\n const timeout = setTimeout(() => controller.abort(), options.timeoutMs);\r\n const dispatcher = proxyConfig.createDispatcher?.();\r\n\r\n debugNetworkRoute(url, proxyConfig.route, attempt + 1, options.retries + 1);\r\n\r\n try {\r\n const response = await undiciFetch(url, {\r\n ...(dispatcher ? { dispatcher } : {}),\r\n headers: options.headers,\r\n redirect: 'follow',\r\n signal: controller.signal,\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error(`HTTP ${response.status} ${response.statusText}`);\r\n }\r\n\r\n return {\r\n body: Buffer.from(await response.arrayBuffer()),\r\n elapsedMs: Math.round(performance.now() - startedAt),\r\n route: proxyConfig.route,\r\n status: response.status,\r\n };\r\n } catch (error: unknown) {\r\n lastError = error;\r\n if (attempt < options.retries) {\r\n await delay(250 * (attempt + 1));\r\n }\r\n } finally {\r\n clearTimeout(timeout);\r\n await dispatcher?.destroy();\r\n }\r\n }\r\n\r\n throw createRequestError(url, options, proxyConfig.route, lastError);\r\n}\r\n\r\ninterface ResolvedProxyConfig {\r\n createDispatcher?: () => Dispatcher;\r\n proxyUrl?: string;\r\n route: NetworkRoute;\r\n}\r\n\r\nasync function resolveProxyConfig(url: string): Promise<ResolvedProxyConfig> {\r\n const target = new URL(url);\r\n\r\n if (networkOptions.forceDirect) {\r\n return { route: 'direct' };\r\n }\r\n\r\n if (networkOptions.proxy) {\r\n const proxyUrl = networkOptions.proxy;\r\n return {\r\n createDispatcher: () => new ProxyAgent({ uri: proxyUrl }),\r\n proxyUrl,\r\n route: 'proxy-environment',\r\n };\r\n }\r\n\r\n const httpProxy = readEnvironmentVariable('http_proxy', 'HTTP_PROXY');\r\n const httpsProxy = readEnvironmentVariable('https_proxy', 'HTTPS_PROXY');\r\n const noProxy = readEnvironmentVariable('no_proxy', 'NO_PROXY');\r\n const environmentProxy = target.protocol === 'https:'\r\n ? httpsProxy ?? httpProxy\r\n : httpProxy;\r\n\r\n if (noProxy && shouldBypassProxy(target, noProxy)) {\r\n return { route: 'direct' };\r\n }\r\n\r\n if (environmentProxy) {\r\n return {\r\n createDispatcher: () => new EnvHttpProxyAgent({\r\n httpProxy,\r\n httpsProxy,\r\n noProxy,\r\n }),\r\n proxyUrl: environmentProxy,\r\n route: 'proxy-environment',\r\n };\r\n }\r\n\r\n const systemProxy = await getSystemProxy(target);\r\n if (systemProxy.noProxy && shouldBypassProxy(target, systemProxy.noProxy)) {\r\n return { route: 'direct' };\r\n }\r\n if (systemProxy.proxyUrl) {\r\n return {\r\n createDispatcher: () => new ProxyAgent({ uri: systemProxy.proxyUrl! }),\r\n proxyUrl: systemProxy.proxyUrl,\r\n route: 'proxy-system',\r\n };\r\n }\r\n\r\n return { route: 'direct' };\r\n}\r\n\r\nexport interface GitNetworkConfig {\r\n args: string[];\r\n route: NetworkRoute | 'ssh';\r\n}\r\n\r\nexport async function resolveGitNetworkConfig(repositoryUrl: string): Promise<GitNetworkConfig> {\r\n if (!/^https?:\\/\\//i.test(repositoryUrl)) {\r\n return { args: [], route: 'ssh' };\r\n }\r\n\r\n const proxyConfig = await resolveProxyConfig(repositoryUrl);\r\n if (proxyConfig.proxyUrl) {\r\n return {\r\n args: ['-c', `http.proxy=${proxyConfig.proxyUrl}`],\r\n route: proxyConfig.route,\r\n };\r\n }\r\n\r\n return {\r\n args: networkOptions.forceDirect ? ['-c', 'http.proxy='] : [],\r\n route: 'direct',\r\n };\r\n}\r\n\r\nfunction readEnvironmentVariable(primaryName: string, fallbackName: string): string | undefined {\r\n const value = process.env[primaryName] ?? process.env[fallbackName];\r\n return value?.trim() || undefined;\r\n}\r\n\r\nfunction shouldBypassProxy(target: URL, noProxy: string): boolean {\r\n const hostname = target.hostname.toLowerCase();\r\n const port = Number.parseInt(target.port, 10)\r\n || (target.protocol === 'https:' ? 443 : 80);\r\n\r\n return noProxy.split(/[,\\s]/).some((rawEntry) => {\r\n const entry = rawEntry.trim().toLowerCase();\r\n if (!entry) {\r\n return false;\r\n }\r\n if (entry === '*') {\r\n return true;\r\n }\r\n\r\n const parsed = entry.match(/^(.+):(\\d+)$/);\r\n const entryHostname = parsed ? parsed[1] : entry;\r\n const entryPort = parsed ? Number.parseInt(parsed[2], 10) : 0;\r\n if (entryPort && entryPort !== port) {\r\n return false;\r\n }\r\n\r\n if (!/^[.*]/.test(entryHostname)) {\r\n return hostname === entryHostname;\r\n }\r\n return hostname.endsWith(entryHostname.replace(/^\\*/, ''));\r\n });\r\n}\r\n\r\nexport function formatNetworkRoute(route: NetworkRoute): string {\r\n if (route === 'proxy-environment') {\r\n return '环境变量代理';\r\n }\r\n if (route === 'proxy-system') {\r\n return '系统代理';\r\n }\r\n return '直连';\r\n}\r\n\r\nfunction createRequestError(\r\n url: string,\r\n options: HttpRequestOptions,\r\n route: NetworkRoute,\r\n error: unknown,\r\n): Error {\r\n const cause = getErrorMessage(error);\r\n return new Error(\r\n `请求失败\\nurl: ${url}\\nerror: ${cause}\\nnetwork: ${formatNetworkRoute(route)}\\ntimeout: ${options.timeoutMs} ms\\nattempts: ${options.retries + 1}`,\r\n );\r\n}\r\n\r\nfunction validateProxyUrl(proxyUrl: string): void {\r\n try {\r\n const parsed = new URL(proxyUrl);\r\n if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\r\n throw new Error();\r\n }\r\n } catch {\r\n throw new Error('无效的代理地址,请使用 http://host:port 或 https://host:port 格式。');\r\n }\r\n}\r\n\r\nfunction debugNetworkRoute(\r\n url: string,\r\n route: NetworkRoute,\r\n attempt: number,\r\n attempts: number,\r\n): void {\r\n if (process.env.GZ_CLI_FRONT_DEBUG !== '1') {\r\n return;\r\n }\r\n\r\n console.log(`[network] host: ${new URL(url).host}`);\r\n console.log(`[network] route: ${formatNetworkRoute(route)}`);\r\n console.log(`[network] attempt: ${attempt}/${attempts}`);\r\n}\r\n\r\nfunction getErrorMessage(error: unknown): string {\r\n if (!(error instanceof Error)) {\r\n return '未知错误';\r\n }\r\n const cause = 'cause' in error ? error.cause : undefined;\r\n const causeMessage = cause instanceof Error ? cause.message : String(cause ?? '');\r\n return causeMessage ? `${error.message} (${causeMessage})` : error.message;\r\n}\r\n","import { execFile } from 'node:child_process';\r\nimport { promisify } from 'node:util';\r\n\r\nconst execFileAsync = promisify(execFile);\r\nconst WINDOWS_INTERNET_SETTINGS = String.raw`HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings`;\r\nconst SYSTEM_PROXY_TIMEOUT_MS = 1_500;\r\n\r\nexport interface SystemProxyConfig {\r\n noProxy?: string;\r\n proxyUrl?: string;\r\n}\r\n\r\nconst systemProxyCache = new Map<string, Promise<SystemProxyConfig>>();\r\n\r\nexport function getSystemProxy(target: URL): Promise<SystemProxyConfig> {\r\n const cacheKey = `${process.platform}:${target.protocol}`;\r\n const cached = systemProxyCache.get(cacheKey);\r\n if (cached) {\r\n return cached;\r\n }\r\n\r\n const request = detectSystemProxy(target).catch(() => ({}));\r\n systemProxyCache.set(cacheKey, request);\r\n return request;\r\n}\r\n\r\nasync function detectSystemProxy(target: URL): Promise<SystemProxyConfig> {\r\n if (process.platform === 'win32') {\r\n return detectWindowsProxy(target);\r\n }\r\n if (process.platform === 'darwin') {\r\n return detectMacOsProxy(target);\r\n }\r\n if (process.platform === 'linux') {\r\n return detectLinuxProxy(target);\r\n }\r\n return {};\r\n}\r\n\r\nasync function detectWindowsProxy(target: URL): Promise<SystemProxyConfig> {\r\n const [enabledOutput, serverOutput, overrideOutput] = await Promise.all([\r\n queryWindowsRegistry('ProxyEnable'),\r\n queryWindowsRegistry('ProxyServer'),\r\n queryWindowsRegistry('ProxyOverride'),\r\n ]);\r\n const enabled = readRegistryValue(enabledOutput, 'ProxyEnable');\r\n if (enabled !== '0x1' && enabled !== '1') {\r\n return {};\r\n }\r\n\r\n const proxyServer = readRegistryValue(serverOutput, 'ProxyServer');\r\n if (!proxyServer) {\r\n return {};\r\n }\r\n\r\n const proxyAddress = selectWindowsProxy(proxyServer, target.protocol);\r\n if (!proxyAddress) {\r\n return {};\r\n }\r\n\r\n const proxyOverride = readRegistryValue(overrideOutput, 'ProxyOverride');\r\n return {\r\n noProxy: proxyOverride?.split(';').filter((entry) => entry !== '<local>').join(','),\r\n proxyUrl: normalizeProxyUrl(proxyAddress),\r\n };\r\n}\r\n\r\nasync function queryWindowsRegistry(valueName: string): Promise<string> {\r\n try {\r\n const result = await execFileAsync(\r\n 'reg.exe',\r\n ['query', WINDOWS_INTERNET_SETTINGS, '/v', valueName],\r\n { timeout: SYSTEM_PROXY_TIMEOUT_MS, windowsHide: true },\r\n );\r\n return result.stdout;\r\n } catch {\r\n return '';\r\n }\r\n}\r\n\r\nfunction readRegistryValue(output: string, valueName: string): string | undefined {\r\n const line = output.split(/\\r?\\n/).find((entry) => entry.includes(valueName));\r\n return line?.match(/REG_\\w+\\s+(.+)$/)?.[1]?.trim();\r\n}\r\n\r\nfunction selectWindowsProxy(proxyServer: string, protocol: string): string | undefined {\r\n if (!proxyServer.includes('=')) {\r\n return proxyServer;\r\n }\r\n\r\n const proxies = new Map(\r\n proxyServer.split(';').flatMap((entry) => {\r\n const [key, value] = entry.split('=', 2).map((part) => part.trim());\r\n return key && value ? [[key.toLowerCase(), value] as const] : [];\r\n }),\r\n );\r\n const protocolName = protocol.replace(':', '');\r\n return proxies.get(protocolName) ?? proxies.get('http');\r\n}\r\n\r\nasync function detectMacOsProxy(target: URL): Promise<SystemProxyConfig> {\r\n try {\r\n const result = await execFileAsync('scutil', ['--proxy'], {\r\n timeout: SYSTEM_PROXY_TIMEOUT_MS,\r\n });\r\n const prefix = target.protocol === 'https:' ? 'HTTPS' : 'HTTP';\r\n if (readScutilValue(result.stdout, `${prefix}Enable`) !== '1') {\r\n return {};\r\n }\r\n const host = readScutilValue(result.stdout, `${prefix}Proxy`);\r\n const port = readScutilValue(result.stdout, `${prefix}Port`);\r\n return host && port ? { proxyUrl: `http://${host}:${port}` } : {};\r\n } catch {\r\n return {};\r\n }\r\n}\r\n\r\nfunction readScutilValue(output: string, key: string): string | undefined {\r\n return output.match(new RegExp(`^\\\\s*${key}\\\\s*:\\\\s*(.+)$`, 'm'))?.[1]?.trim();\r\n}\r\n\r\nasync function detectLinuxProxy(target: URL): Promise<SystemProxyConfig> {\r\n try {\r\n const mode = stripQuotes(await queryGSettings('org.gnome.system.proxy', 'mode'));\r\n if (mode !== 'manual') {\r\n return {};\r\n }\r\n\r\n const protocol = target.protocol === 'https:' ? 'https' : 'http';\r\n const [hostValue, portValue, ignoredHostsValue] = await Promise.all([\r\n queryGSettings(`org.gnome.system.proxy.${protocol}`, 'host'),\r\n queryGSettings(`org.gnome.system.proxy.${protocol}`, 'port'),\r\n queryGSettings('org.gnome.system.proxy', 'ignore-hosts'),\r\n ]);\r\n const host = stripQuotes(hostValue);\r\n const port = Number.parseInt(portValue.trim(), 10);\r\n if (!host || !Number.isInteger(port) || port <= 0) {\r\n return {};\r\n }\r\n\r\n return {\r\n noProxy: Array.from(\r\n ignoredHostsValue.matchAll(/'([^']+)'/g),\r\n (match) => match[1],\r\n ).join(','),\r\n proxyUrl: `http://${host}:${port}`,\r\n };\r\n } catch {\r\n return {};\r\n }\r\n}\r\n\r\nasync function queryGSettings(schema: string, key: string): Promise<string> {\r\n const result = await execFileAsync('gsettings', ['get', schema, key], {\r\n timeout: SYSTEM_PROXY_TIMEOUT_MS,\r\n });\r\n return result.stdout;\r\n}\r\n\r\nfunction stripQuotes(value: string): string {\r\n return value.trim().replace(/^['\"]|['\"]$/g, '');\r\n}\r\n\r\nfunction normalizeProxyUrl(proxyAddress: string): string {\r\n return /^[a-z][a-z\\d+.-]*:\\/\\//i.test(proxyAddress)\r\n ? proxyAddress\r\n : `http://${proxyAddress}`;\r\n}\r\n","import { execa } from 'execa';\r\nimport fs from 'fs-extra';\r\nimport { randomUUID } from 'node:crypto';\r\nimport path from 'node:path';\r\nimport { performance } from 'node:perf_hooks';\r\nimport { setTimeout as delay } from 'node:timers/promises';\r\nimport { getGitRepositoryCachePath, isCacheFresh } from './cache.js';\r\nimport {\r\n formatNetworkRoute,\r\n resolveGitNetworkConfig,\r\n type NetworkRoute,\r\n} from './http.js';\r\n\r\nconst GIT_OPERATION_ATTEMPTS = 2;\r\nconst GIT_AUTH_TIMEOUT_MS = 60_000;\r\nconst GIT_SSH_CLONE_TIMEOUT_MS = 20_000;\r\ntype GitOperationStage = 'clone';\r\n\r\nexport interface GitRepositoryOptions {\r\n forceRefresh?: boolean;\r\n namespace: 'registry' | 'templates';\r\n ttlMs: number;\r\n version?: string;\r\n}\r\n\r\nexport interface GitRepositoryResult {\r\n cacheHit: boolean;\r\n elapsedMs: number;\r\n path: string;\r\n route: NetworkRoute | 'ssh' | 'cache' | 'stale-cache';\r\n staleCache: boolean;\r\n}\r\n\r\nexport async function ensureGitRepository(\r\n repositoryUrl: string,\r\n options: GitRepositoryOptions,\r\n): Promise<GitRepositoryResult> {\r\n const version = normalizeVersion(options.version);\r\n const repositoryPath = getRepositoryCachePath(repositoryUrl, options.namespace, version);\r\n const startedAt = performance.now();\r\n const cacheExists = await isValidGitCache(repositoryPath);\r\n\r\n if (await canUseGitCache(repositoryPath, cacheExists, version, options)) {\r\n return createCacheResult(repositoryPath, startedAt, false);\r\n }\r\n\r\n const temporaryPath = `${repositoryPath}.${randomUUID()}.tmp`;\r\n const candidates = getRepositoryCandidates(repositoryUrl);\r\n let lastError: unknown;\r\n await fs.ensureDir(path.dirname(repositoryPath));\r\n\r\n for (const [index, candidate] of candidates.entries()) {\r\n try {\r\n const network = await resolveGitNetworkConfig(candidate);\r\n const isSshCandidate = network.route === 'ssh';\r\n const timeoutMs = isSshCandidate ? GIT_SSH_CLONE_TIMEOUT_MS : GIT_AUTH_TIMEOUT_MS;\r\n debugGitRepository(candidate, network.route, timeoutMs);\r\n await cloneRepository(\r\n candidate,\r\n temporaryPath,\r\n version,\r\n network.args,\r\n timeoutMs,\r\n isSshCandidate ? 1 : GIT_OPERATION_ATTEMPTS,\r\n );\r\n await replaceCacheDirectory(temporaryPath, repositoryPath);\r\n return {\r\n cacheHit: false,\r\n elapsedMs: Math.round(performance.now() - startedAt),\r\n path: repositoryPath,\r\n route: network.route,\r\n staleCache: false,\r\n };\r\n } catch (error: unknown) {\r\n lastError = error;\r\n await fs.remove(temporaryPath);\r\n if (index < candidates.length - 1) {\r\n if (process.env.GZ_CLI_FRONT_DEBUG === '1') {\r\n console.log('[git] SSH 不可用,正在尝试 HTTPS...');\r\n }\r\n continue;\r\n }\r\n }\r\n }\r\n\r\n if (cacheExists && !options.forceRefresh) {\r\n return createCacheResult(repositoryPath, startedAt, true);\r\n }\r\n throw createGitError(repositoryUrl, lastError, 'clone');\r\n}\r\n\r\nfunction getRepositoryCachePath(\r\n repositoryUrl: string,\r\n namespace: GitRepositoryOptions['namespace'],\r\n version: string | undefined,\r\n): string {\r\n return getGitRepositoryCachePath(\r\n namespace,\r\n `${getRepositoryIdentity(repositoryUrl)}#${version ?? 'latest'}`,\r\n );\r\n}\r\n\r\nfunction getRepositoryCandidates(repositoryUrl: string): string[] {\r\n return [repositoryUrl];\r\n}\r\n\r\nfunction getRepositoryIdentity(repositoryUrl: string): string {\r\n try {\r\n const parsed = new URL(repositoryUrl);\r\n const repositoryPath = parsed.pathname.replace(/^\\/|\\/$/g, '').replace(/\\.git$/i, '');\r\n return `${parsed.hostname.toLowerCase()}/${repositoryPath}`;\r\n } catch {\r\n const sshMatch = repositoryUrl.match(/^[^@]+@([^:]+):(.+)$/);\r\n if (!sshMatch) {\r\n return repositoryUrl;\r\n }\r\n return `${sshMatch[1].toLowerCase()}/${sshMatch[2].replace(/\\.git$/i, '')}`;\r\n }\r\n}\r\n\r\nasync function canUseGitCache(\r\n repositoryPath: string,\r\n cacheExists: boolean,\r\n version: string | undefined,\r\n options: GitRepositoryOptions,\r\n): Promise<boolean> {\r\n if (options.forceRefresh || !cacheExists) {\r\n return false;\r\n }\r\n const stats = await fs.stat(repositoryPath);\r\n return Boolean(version) || isCacheFresh(stats.mtimeMs, options.ttlMs);\r\n}\r\n\r\nfunction debugGitRepository(\r\n repositoryUrl: string,\r\n route: NetworkRoute | 'ssh',\r\n timeoutMs: number,\r\n): void {\r\n if (process.env.GZ_CLI_FRONT_DEBUG !== '1') {\r\n return;\r\n }\r\n\r\n const routeLabel = route === 'ssh' ? 'Git/SSH' : formatNetworkRoute(route);\r\n console.log(`[git] host: ${getRepositoryHost(repositoryUrl)}`);\r\n console.log(`[git] route: ${routeLabel}`);\r\n console.log(`[git] timeout: ${timeoutMs} ms`);\r\n}\r\n\r\nfunction getRepositoryHost(repositoryUrl: string): string {\r\n try {\r\n return new URL(repositoryUrl).host;\r\n } catch {\r\n return repositoryUrl.match(/^[^@]+@([^:]+):/)?.[1] ?? 'unknown';\r\n }\r\n}\r\n\r\nasync function cloneRepository(\r\n repositoryUrl: string,\r\n targetPath: string,\r\n version: string | undefined,\r\n networkArgs: string[],\r\n timeoutMs: number,\r\n attempts: number,\r\n): Promise<void> {\r\n const args = [\r\n ...networkArgs,\r\n 'clone',\r\n '--quiet',\r\n '--depth',\r\n '1',\r\n '--single-branch',\r\n ];\r\n if (version) {\r\n args.push('--branch', version);\r\n }\r\n args.push(repositoryUrl, targetPath);\r\n\r\n for (let attempt = 1; attempt <= attempts; attempt += 1) {\r\n try {\r\n await execa('git', args, {\r\n forceKillAfterDelay: 1_000,\r\n stdin: 'inherit',\r\n stdout: 'pipe',\r\n stderr: ['pipe', 'inherit'],\r\n timeout: timeoutMs,\r\n windowsHide: true,\r\n });\r\n return;\r\n } catch (error: unknown) {\r\n if (attempt === attempts || !isTransientGitError(error)) {\r\n throw error;\r\n }\r\n if (process.env.GZ_CLI_FRONT_DEBUG === '1') {\r\n console.log(`[git] transient failure, retry: ${attempt + 1}/${attempts}`);\r\n }\r\n await fs.remove(targetPath);\r\n await delay(300);\r\n }\r\n }\r\n}\r\n\r\nfunction isTransientGitError(error: unknown): boolean {\r\n if (typeof error === 'object' && error !== null\r\n && (error as Record<string, unknown>).timedOut === true) {\r\n return true;\r\n }\r\n\r\n const message = error instanceof Error ? error.message : String(error);\r\n return [\r\n /SSL\\/TLS connection failed/i,\r\n /failed to receive handshake/i,\r\n /connection (?:was )?reset/i,\r\n /remote end hung up unexpectedly/i,\r\n /early EOF/i,\r\n /failed to connect/i,\r\n /could not resolve host/i,\r\n /timed out|timeout/i,\r\n ].some((pattern) => pattern.test(message));\r\n}\r\n\r\nasync function replaceCacheDirectory(sourcePath: string, targetPath: string): Promise<void> {\r\n const backupPath = `${targetPath}.${randomUUID()}.bak`;\r\n const targetExists = await fs.pathExists(targetPath);\r\n if (targetExists) {\r\n await fs.move(targetPath, backupPath);\r\n }\r\n\r\n try {\r\n await fs.move(sourcePath, targetPath);\r\n await fs.remove(backupPath);\r\n } catch (error: unknown) {\r\n await fs.remove(targetPath);\r\n if (await fs.pathExists(backupPath)) {\r\n await fs.move(backupPath, targetPath);\r\n }\r\n throw error;\r\n }\r\n}\r\n\r\nasync function isValidGitCache(repositoryPath: string): Promise<boolean> {\r\n return fs.pathExists(path.join(repositoryPath, '.git'));\r\n}\r\n\r\nfunction createCacheResult(\r\n repositoryPath: string,\r\n startedAt: number,\r\n staleCache: boolean,\r\n): GitRepositoryResult {\r\n return {\r\n cacheHit: true,\r\n elapsedMs: Math.round(performance.now() - startedAt),\r\n path: repositoryPath,\r\n route: staleCache ? 'stale-cache' : 'cache',\r\n staleCache,\r\n };\r\n}\r\n\r\nfunction normalizeVersion(version: string | undefined): string | undefined {\r\n return version && version !== 'latest' ? version : undefined;\r\n}\r\n\r\nfunction createGitError(\r\n repositoryUrl: string,\r\n error: unknown,\r\n stage: GitOperationStage,\r\n): Error {\r\n const message = getGitErrorMessage(error);\r\n const safeRepository = sanitizeRepositoryUrl(repositoryUrl);\r\n debugGitFailure(stage, message);\r\n if (isGitTimeoutError(error, message)) {\r\n return new Error(\r\n `Git 仓库连接超时(阶段:${stage},${GIT_AUTH_TIMEOUT_MS} ms):${safeRepository}\\n请检查当前网络或代理设置后重试。`,\r\n );\r\n }\r\n\r\n if (isGitPermissionError(message)) {\r\n return new Error(\r\n `无法访问 Git 仓库(阶段:${stage}):${safeRepository}\\n请检查仓库地址、网络连接及当前 Git 凭据后重试。`,\r\n );\r\n }\r\n\r\n return new Error(\r\n `Git 仓库访问失败(阶段:${stage}):${safeRepository}\\n请确认已安装 Git,且当前 Git/SSH 账号拥有仓库 Read 权限。\\n${message}`,\r\n );\r\n}\r\n\r\nfunction getGitErrorMessage(error: unknown): string {\r\n return redactCredentials(error instanceof Error ? error.message : '未知错误');\r\n}\r\n\r\nfunction debugGitFailure(stage: GitOperationStage, message: string): void {\r\n if (process.env.GZ_CLI_FRONT_DEBUG !== '1') {\r\n return;\r\n }\r\n\r\n console.error(`[git] failed stage: ${stage}`);\r\n console.error(`[git] error: ${message}`);\r\n}\r\n\r\nfunction isGitTimeoutError(error: unknown, message: string): boolean {\r\n if (typeof error === 'object' && error !== null\r\n && (error as Record<string, unknown>).timedOut === true) {\r\n return true;\r\n }\r\n return /timed out|timeout/i.test(message);\r\n}\r\n\r\nfunction isGitPermissionError(message: string): boolean {\r\n return [\r\n /authentication failed/i,\r\n /permission denied/i,\r\n /repository not found/i,\r\n /could not read username/i,\r\n /unable to get (?:password|username) from user/i,\r\n /terminal prompts disabled/i,\r\n /user interaction is disabled/i,\r\n /interactive prompts are disabled/i,\r\n /credential.*(?:failed|unavailable)/i,\r\n /access denied/i,\r\n /http (?:error )?40[13]/i,\r\n /status code: 40[13]/i,\r\n ].some((pattern) => pattern.test(message));\r\n}\r\n\r\nfunction redactCredentials(message: string): string {\r\n return message\r\n .replace(/http\\.proxy=\\S+/gi, 'http.proxy=***')\r\n .replace(/(https?:\\/\\/)[^@\\s/]+@/gi, '$1***@');\r\n}\r\n\r\nfunction sanitizeRepositoryUrl(repositoryUrl: string): string {\r\n try {\r\n const parsed = new URL(repositoryUrl);\r\n parsed.username = '';\r\n parsed.password = '';\r\n return parsed.toString();\r\n } catch {\r\n return repositoryUrl;\r\n }\r\n}\r\n","import fs from 'fs-extra';\r\nimport { randomUUID } from 'node:crypto';\r\nimport path from 'path';\r\nimport { performance } from 'node:perf_hooks';\r\nimport { x as extractTar } from 'tar';\r\nimport type { TemplateMeta, TemplateSource } from '../types/template.js';\r\nimport {\r\n getTemplateArchiveCachePath,\r\n isCacheFresh,\r\n TEMPLATE_ARCHIVE_CACHE_TTL_MS,\r\n} from './cache.js';\r\nimport { requestBuffer, type NetworkRoute } from './http.js';\r\nimport { ensureGitRepository } from './git-repository.js';\r\n\r\nconst TEMPLATE_DOWNLOAD_TIMEOUT_MS = 12_000;\r\n\r\nexport interface TemplateDownloadTiming {\r\n cacheHit: boolean;\r\n copyMs: number;\r\n downloadMs: number;\r\n extractMs: number;\r\n route: NetworkRoute | 'ssh' | 'cache' | 'stale-cache' | 'git' | 'bundled';\r\n}\r\n\r\nexport interface DownloadTemplateOptions {\r\n forceRefresh?: boolean;\r\n}\r\n\r\ntype TemplateDownloader = (\r\n template: TemplateMeta,\r\n targetDir: string,\r\n options: DownloadTemplateOptions,\r\n) => Promise<TemplateDownloadTiming>;\r\n\r\nconst DOWNLOADERS: Readonly<Record<TemplateSource, TemplateDownloader>> = {\r\n github: downloadFromGitHub,\r\n gitlab: downloadFromGit,\r\n git: downloadFromGit,\r\n};\r\n\r\nexport async function downloadTemplate(\r\n template: TemplateMeta,\r\n targetDir: string,\r\n options: DownloadTemplateOptions = {},\r\n): Promise<TemplateDownloadTiming> {\r\n const source = template.source ?? 'github';\r\n return DOWNLOADERS[source](template, targetDir, options);\r\n}\r\n\r\nasync function downloadFromGitHub(\r\n template: TemplateMeta,\r\n targetDir: string,\r\n options: DownloadTemplateOptions,\r\n): Promise<TemplateDownloadTiming> {\r\n const repository = normalizeGitHubRepository(getTemplateUrl(template));\r\n const version = template.version && template.version !== 'latest'\r\n ? template.version\r\n : undefined;\r\n const sourceKey = `${repository}${version ? `#${version}` : '#latest'}`;\r\n const archivePath = getTemplateArchiveCachePath(sourceKey);\r\n const archive = await ensureGitHubArchive(\r\n repository,\r\n version,\r\n archivePath,\r\n options.forceRefresh === true,\r\n );\r\n\r\n const extractStartedAt = performance.now();\r\n await fs.ensureDir(targetDir);\r\n try {\r\n await extractTar({\r\n cwd: targetDir,\r\n file: archivePath,\r\n preservePaths: false,\r\n strict: true,\r\n strip: 1,\r\n });\r\n } catch (error: unknown) {\r\n if (!archive.cacheHit) {\r\n throw error;\r\n }\r\n\r\n await fs.remove(archivePath);\r\n await fs.emptyDir(targetDir);\r\n return downloadFromGitHub(template, targetDir, { forceRefresh: true });\r\n }\r\n\r\n return {\r\n cacheHit: archive.cacheHit,\r\n copyMs: 0,\r\n downloadMs: archive.downloadMs,\r\n extractMs: Math.round(performance.now() - extractStartedAt),\r\n route: archive.route,\r\n };\r\n}\r\n\r\nasync function downloadFromGit(\r\n template: TemplateMeta,\r\n targetDir: string,\r\n options: DownloadTemplateOptions,\r\n): Promise<TemplateDownloadTiming> {\r\n if (!template.url) {\r\n throw new Error(`${template.source} 模板必须提供 Git clone URL。`);\r\n }\r\n\r\n const repository = await ensureGitRepository(template.url, {\r\n forceRefresh: options.forceRefresh,\r\n namespace: 'templates',\r\n ttlMs: TEMPLATE_ARCHIVE_CACHE_TTL_MS,\r\n version: template.version,\r\n });\r\n const copyStartedAt = performance.now();\r\n await fs.copy(repository.path, targetDir, {\r\n filter: (sourcePath) => path.basename(sourcePath) !== '.git',\r\n });\r\n\r\n return {\r\n cacheHit: repository.cacheHit,\r\n copyMs: Math.round(performance.now() - copyStartedAt),\r\n downloadMs: repository.elapsedMs,\r\n extractMs: 0,\r\n route: repository.route,\r\n };\r\n}\r\n\r\ninterface GitHubArchiveResult {\r\n cacheHit: boolean;\r\n downloadMs: number;\r\n route: NetworkRoute | 'cache';\r\n}\r\n\r\nasync function ensureGitHubArchive(\r\n repository: string,\r\n version: string | undefined,\r\n archivePath: string,\r\n forceRefresh: boolean,\r\n): Promise<GitHubArchiveResult> {\r\n const startedAt = performance.now();\r\n if (!forceRefresh && await canUseArchiveCache(archivePath, Boolean(version))) {\r\n return {\r\n cacheHit: true,\r\n downloadMs: Math.round(performance.now() - startedAt),\r\n route: 'cache',\r\n };\r\n }\r\n\r\n const archiveRequest = createGitHubArchiveRequest(repository, version);\r\n const response = await requestBuffer(archiveRequest.url, {\r\n headers: archiveRequest.headers,\r\n retries: 1,\r\n timeoutMs: TEMPLATE_DOWNLOAD_TIMEOUT_MS,\r\n });\r\n const temporaryPath = `${archivePath}.${randomUUID()}.tmp`;\r\n\r\n await fs.ensureDir(path.dirname(archivePath));\r\n try {\r\n await fs.writeFile(temporaryPath, response.body);\r\n await fs.move(temporaryPath, archivePath, { overwrite: true });\r\n } finally {\r\n await fs.remove(temporaryPath);\r\n }\r\n\r\n return {\r\n cacheHit: false,\r\n downloadMs: Math.round(performance.now() - startedAt),\r\n route: response.route,\r\n };\r\n}\r\n\r\ninterface GitHubArchiveRequest {\r\n headers: Readonly<Record<string, string>>;\r\n url: string;\r\n}\r\n\r\nfunction createGitHubArchiveRequest(\r\n repository: string,\r\n version: string | undefined,\r\n): GitHubArchiveRequest {\r\n const token = process.env.GITHUB_TOKEN?.trim();\r\n if (token) {\r\n return {\r\n headers: createGitHubApiHeaders(token),\r\n url: `https://api.github.com/repos/${repository}/tarball${version ? `/${encodeURIComponent(version)}` : ''}`,\r\n };\r\n }\r\n\r\n return {\r\n headers: { 'user-agent': 'gz-cli-front' },\r\n url: `https://codeload.github.com/${repository}/tar.gz/${encodeURIComponent(version ?? 'HEAD')}`,\r\n };\r\n}\r\n\r\nasync function canUseArchiveCache(archivePath: string, immutableVersion: boolean): Promise<boolean> {\r\n try {\r\n const stats = await fs.stat(archivePath);\r\n return stats.isFile()\r\n && (immutableVersion || isCacheFresh(stats.mtimeMs, TEMPLATE_ARCHIVE_CACHE_TTL_MS));\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\nfunction normalizeGitHubRepository(repository: string): string {\r\n const normalized = repository\r\n .replace(/^https:\\/\\/github\\.com\\//i, '')\r\n .replace(/\\.git$/i, '')\r\n .replace(/^\\/+|\\/+$/g, '');\r\n\r\n if (!/^[^/\\s]+\\/[^/\\s]+$/.test(normalized)) {\r\n throw new Error(`无效的 GitHub 模板地址:${repository}`);\r\n }\r\n\r\n return normalized;\r\n}\r\n\r\nfunction createGitHubApiHeaders(token: string): Readonly<Record<string, string>> {\r\n return {\r\n accept: 'application/vnd.github+json',\r\n authorization: `Bearer ${token}`,\r\n 'user-agent': 'gz-cli-front',\r\n 'x-github-api-version': '2022-11-28',\r\n };\r\n}\r\n\r\nfunction getTemplateUrl(template: TemplateMeta): string {\r\n if (template.url) {\r\n return template.url;\r\n }\r\n if (template.repo) {\r\n return template.repo;\r\n }\r\n throw new Error('模板配置缺少 url。');\r\n}\r\n","import chalk from 'chalk';\r\nimport { clearLine, cursorTo } from 'node:readline';\r\n\r\nconst SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];\r\nconst SPINNER_INTERVAL_MS = 80;\r\nconst RESTORE_CURSOR = '\\u001B[u';\r\nconst SAVE_CURSOR = '\\u001B[s';\r\n\r\nexport interface StableSpinner {\r\n readonly isSpinning: boolean;\r\n text: string;\r\n fail(text?: string): void;\r\n start(text?: string): void;\r\n succeed(text?: string): void;\r\n}\r\n\r\nexport function createStableSpinner(): StableSpinner {\r\n return new StableTextSpinner(process.stderr);\r\n}\r\n\r\nclass StableTextSpinner implements StableSpinner {\r\n private frameIndex = 0;\r\n private interval: NodeJS.Timeout | undefined;\r\n private readonly stream: NodeJS.WriteStream;\r\n private value = '';\r\n\r\n constructor(stream: NodeJS.WriteStream) {\r\n this.stream = stream;\r\n }\r\n\r\n get isSpinning(): boolean {\r\n return this.interval !== undefined;\r\n }\r\n\r\n get text(): string {\r\n return this.value;\r\n }\r\n\r\n set text(value: string) {\r\n this.value = value;\r\n if (this.isSpinning) {\r\n this.renderLine();\r\n }\r\n }\r\n\r\n start(text?: string): void {\r\n if (text !== undefined) {\r\n this.value = text;\r\n }\r\n if (!this.stream.isTTY || this.isSpinning) {\r\n if (!this.stream.isTTY && this.value) {\r\n this.stream.write(`- ${this.value}\\n`);\r\n }\r\n return;\r\n }\r\n\r\n this.stream.write(\r\n `${chalk.cyan(SPINNER_FRAMES[this.frameIndex])} ${this.value}${SAVE_CURSOR}`,\r\n );\r\n this.interval = setInterval(() => this.renderFrame(), SPINNER_INTERVAL_MS);\r\n }\r\n\r\n succeed(text?: string): void {\r\n this.persist(chalk.green('✔'), text);\r\n }\r\n\r\n fail(text?: string): void {\r\n this.persist(chalk.red('✖'), text);\r\n }\r\n\r\n private renderLine(): void {\r\n this.restoreAndClearLine();\r\n this.stream.write(`${chalk.cyan(SPINNER_FRAMES[this.frameIndex])} ${this.value}${SAVE_CURSOR}`);\r\n }\r\n\r\n private renderFrame(): void {\r\n this.frameIndex = (this.frameIndex + 1) % SPINNER_FRAMES.length;\r\n this.stream.write(\r\n `${RESTORE_CURSOR}\\r${chalk.cyan(SPINNER_FRAMES[this.frameIndex])}${RESTORE_CURSOR}`,\r\n );\r\n }\r\n\r\n private persist(symbol: string, text?: string): void {\r\n const finalText = text ?? this.value;\r\n this.stop();\r\n this.stream.write(`${symbol}${finalText ? ` ${finalText}` : ''}\\n`);\r\n }\r\n\r\n private stop(): boolean {\r\n if (!this.interval) {\r\n return false;\r\n }\r\n\r\n clearInterval(this.interval);\r\n this.interval = undefined;\r\n this.restoreAndClearLine();\r\n return true;\r\n }\r\n\r\n private restoreAndClearLine(): void {\r\n this.stream.write(RESTORE_CURSOR);\r\n cursorTo(this.stream, 0);\r\n clearLine(this.stream, 0);\r\n }\r\n}\r\n","import fs from 'fs-extra';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { performance } from 'node:perf_hooks';\nimport { x as extractTar } from 'tar';\nimport type { TemplateMeta } from '../types/template.js';\nimport type { TemplateDownloadTiming } from './template-downloader.js';\n\n// tsup bundles this module into dist/index.js; assets are relative to that entry.\nconst assetDirectory = fileURLToPath(new URL('./template/', import.meta.url));\nconst definitions = [\n { name: 'micro-app', label: '微应用模板(内置)', type: 'micro', title: '微应用' },\n { name: 'main-app', label: '主应用模板(内置)', type: 'main', title: '主应用' },\n] as const;\n\nexport async function loadInternalTemplates(): Promise<TemplateMeta[]> {\n return Promise.all(definitions.map(loadInternalTemplate));\n}\n\nasync function loadInternalTemplate(definition: typeof definitions[number]): Promise<TemplateMeta> {\n try {\n const snapshot: unknown = await fs.readJson(path.join(assetDirectory, `${definition.name}.snapshot.json`));\n if (typeof snapshot !== 'object' || snapshot === null\n || !('commit' in snapshot) || typeof snapshot.commit !== 'string'\n || !/^[a-f\\d]{40}$/.test(snapshot.commit)) {\n throw new Error('内置模板来源版本无效');\n }\n if (!(await fs.stat(path.join(assetDirectory, `${definition.name}.tar.gz`))).isFile()) {\n throw new Error('内置模板文件无效');\n }\n return {\n name: definition.name,\n label: definition.label,\n description: `随 CLI 发布的 gg-cli-template-${definition.name} 模板快照`,\n type: definition.type,\n version: snapshot.commit,\n };\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : '未知错误';\n throw new Error(`内置${definition.title}模板不可用,请重新安装 gz-cli-front。\\n${message}`);\n }\n}\n\nexport async function copyInternalTemplate(\n template: TemplateMeta,\n targetDir: string,\n): Promise<TemplateDownloadTiming> {\n const definition = definitions.find(({ name }) => name === template.name);\n if (!definition) {\n throw new Error(`不支持的内置模板:${template.name}`);\n }\n const startedAt = performance.now();\n await fs.ensureDir(targetDir);\n await extractTar({\n cwd: targetDir,\n file: path.join(assetDirectory, `${definition.name}.tar.gz`),\n preservePaths: false,\n strict: true,\n });\n return {\n cacheHit: false,\n copyMs: Math.round(performance.now() - startedAt),\n downloadMs: 0,\n extractMs: 0,\n route: 'bundled',\n };\n}\n","import chalk from 'chalk';\r\n\r\n/**\r\n * 检查当前 Node.js 版本是否符合要求\r\n * 要求 Node.js 版本 >= 22.19.0\r\n */\r\nexport function checkNodeVersion() {\r\n const currentVersion = process.version;\r\n // 去掉版本号前的 'v',例如 'v22.5.1' -> '22.5.1'\r\n const version = currentVersion.replace(/^v/, '');\r\n const [major] = version.split('.').map(Number);\r\n\r\n if (major < 22) {\r\n console.error(chalk.red(`\\n❌ 错误:当前 Node.js 版本 (${currentVersion}) 过低!`));\r\n console.error(chalk.yellow('⚠️ 请升级 Node.js 版本,不低于 v22.19.0'));\r\n process.exit(1);\r\n }\r\n}\r\n"],"mappings":"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","names":["chalk","execa","fs","path","performance","fs","path","fs","path","performance","path","fs","path","performance","delay","performance","fs","path","delay","performance","fs","getErrorMessage","path","fs","randomUUID","path","performance","performance","fs","path","randomUUID","fs","path","fileURLToPath","performance","extractTar","path","chalk","getErrorMessage","performance","fs","execa","chalk","require"]}
@@ -0,0 +1,4 @@
1
+ {
2
+ "repository": "https://github.com/gz-fronted/gg-cli-template-main-app.git",
3
+ "commit": "e39203a456092fa483e46cab4bca6c2f9159d759"
4
+ }
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gz-cli-front",
3
- "version": "1.0.2",
3
+ "version": "1.0.3-beta.0",
4
4
  "description": "一个轻量级的现代前端脚手架工具",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -16,6 +16,7 @@
16
16
  "dev": "tsup --watch",
17
17
  "build": "tsup && node scripts/copy-assets.js",
18
18
  "sync:template": "node scripts/sync-template.js",
19
+ "sync:template:main": "node scripts/sync-template.js --main",
19
20
  "prepublishOnly": "npm run test:release",
20
21
  "test": "echo \"Error: no test specified\" && exit 1",
21
22
  "test:cli": "node scripts/test-cli.js",