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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # gz-cli-front
2
2
 
3
- 一个轻量级的现代前端脚手架工具,通过远程模板创建项目。
3
+ 一个轻量级的现代前端脚手架工具,支持远程模板和内置微应用模板初始化。
4
4
 
5
5
  npm 包名为 `gz-cli-front`,安装后使用 `gz-cli` 命令。
6
6
 
7
- 版本变化见 [更新日志](CHANGELOG.md)。
7
+ 版本变化统一维护在 [gg-cli-docs 更新日志](https://github.com/gz-fronted/gg-cli-docs/blob/main/docs/changelog.md)。
8
8
 
9
9
  ## 安装
10
10
 
@@ -36,7 +36,26 @@ gz-cli --version
36
36
  gz-cli init demo-app
37
37
  ```
38
38
 
39
- 切换 CLI 后,新建项目会使用当前远程模板;已有业务项目不会自动迁移。
39
+ 切换 CLI 后,新建项目默认使用当前远程模板;已有业务项目不会自动迁移。
40
+
41
+ ### 内网初始化
42
+
43
+ 从 `1.0.2` 起,无法访问 GitHub 时,可直接使用随 CLI 发布的微应用模板:
44
+
45
+ ```bash
46
+ gz-cli init demo-app --internal
47
+ # 简写
48
+ gz-cli init demo-app -i
49
+ ```
50
+
51
+ 内网模式跳过远程模板列表和模板下载,直接生成内置 `micro-app`;不提供主应用模板,
52
+ 也不会因网络失败自动切换模式。`create` 兼容命令同样支持此参数。
53
+ `--internal` 与 `--refresh` 不能同时使用,内置模板随 CLI 版本更新。
54
+
55
+ 生成项目不需要访问 GitHub;CLI 和项目依赖安装仍需可用的 npm 源。初始化时可选择暂不
56
+ 安装依赖,之后在内网配置好的 npm 源下执行 `npm install`。
57
+
58
+ ### 包管理器
40
59
 
41
60
  可通过 `--pm` 指定本次初始化使用的包管理器:
42
61
 
@@ -122,6 +141,24 @@ gz-cli init demo-app --refresh
122
141
 
123
142
  公共仓库建议使用 `source: "git"` 和 HTTPS clone URL,避免要求使用者配置 SSH Key。CLI 会按配置的协议执行浅克隆;`source` 仍兼容 `github`、`gitlab` 和 `git`,旧的 GitHub `repo` 配置也可继续使用。
124
143
 
144
+ ### 更新内置微应用模板
145
+
146
+ 外部 `gg-cli-template-micro-app` 仓库仍是模板维护源。提交模板改动后,在 CLI 仓库执行:
147
+
148
+ ```bash
149
+ npm run sync:template
150
+ npm run test:release
151
+ ```
152
+
153
+ 同步脚本默认读取同级 `gg-cli-template-micro-app` 仓库的已提交版本,仅导出 Git 已跟踪
154
+ 内容到 `template/micro-app`,来源 commit 记录在 `template/micro-app.snapshot.json`。
155
+ 未提交改动会阻止同步;`node_modules`、构建产物和本机配置不会从工作目录复制进来。
156
+ 其他位置的模板仓库可通过 `npm run sync:template -- <仓库路径>` 指定。
157
+
158
+ 构建时将快照压缩到 `dist/template/micro-app.tar.gz`,保留 `.gitignore`、`.npmrc` 等模板
159
+ 文件。日常构建和发布只使用仓库中已有的快照,不要求本机存在外部模板仓库。
160
+ 请勿直接修改快照,也不要将旧的 `src/template` 目录作为内网模板。
161
+
125
162
  ### Git 仓库访问测试
126
163
 
127
164
  发版前可以在本机验证 Git 仓库访问失败时的错误提示,不会修改全局 Git 配置:
package/dist/index.js CHANGED
@@ -1,15 +1,15 @@
1
1
  // src/index.ts
2
- import { Command } from "commander";
2
+ import { Command, Option } from "commander";
3
3
  import { createRequire } from "module";
4
4
 
5
5
  // src/commands/create.ts
6
6
  import { confirm, input, select } from "@inquirer/prompts";
7
7
  import chalk2 from "chalk";
8
8
  import { execa as execa2 } from "execa";
9
- import fs6 from "fs-extra";
9
+ import fs7 from "fs-extra";
10
10
  import ora from "ora";
11
- import path7 from "path";
12
- import { performance as performance5 } from "perf_hooks";
11
+ import path8 from "path";
12
+ import { performance as performance6 } from "perf_hooks";
13
13
 
14
14
  // src/services/config.ts
15
15
  import fs from "fs-extra";
@@ -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 archivePath = getTemplateArchiveCachePath(sourceKey);
982
+ const archivePath2 = getTemplateArchiveCachePath(sourceKey);
983
983
  const archive = await ensureGitHubArchive(
984
984
  repository,
985
985
  version,
986
- archivePath,
986
+ archivePath2,
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: archivePath,
994
+ file: archivePath2,
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(archivePath);
1003
+ await fs5.remove(archivePath2);
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, archivePath, forceRefresh) {
1037
+ async function ensureGitHubArchive(repository, version, archivePath2, forceRefresh) {
1038
1038
  const startedAt = performance4.now();
1039
- if (!forceRefresh && await canUseArchiveCache(archivePath, Boolean(version))) {
1039
+ if (!forceRefresh && await canUseArchiveCache(archivePath2, 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, archivePath, forceRefres
1049
1049
  retries: 1,
1050
1050
  timeoutMs: TEMPLATE_DOWNLOAD_TIMEOUT_MS
1051
1051
  });
1052
- const temporaryPath = `${archivePath}.${randomUUID2()}.tmp`;
1053
- await fs5.ensureDir(path6.dirname(archivePath));
1052
+ const temporaryPath = `${archivePath2}.${randomUUID2()}.tmp`;
1053
+ await fs5.ensureDir(path6.dirname(archivePath2));
1054
1054
  try {
1055
1055
  await fs5.writeFile(temporaryPath, response.body);
1056
- await fs5.move(temporaryPath, archivePath, { overwrite: true });
1056
+ await fs5.move(temporaryPath, archivePath2, { 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(archivePath, immutableVersion) {
1079
+ async function canUseArchiveCache(archivePath2, immutableVersion) {
1080
1080
  try {
1081
- const stats = await fs5.stat(archivePath);
1081
+ const stats = await fs5.stat(archivePath2);
1082
1082
  return stats.isFile() && (immutableVersion || isCacheFresh(stats.mtimeMs, TEMPLATE_ARCHIVE_CACHE_TTL_MS));
1083
1083
  } catch {
1084
1084
  return false;
@@ -1191,16 +1191,66 @@ var StableTextSpinner = class {
1191
1191
  }
1192
1192
  };
1193
1193
 
1194
+ // src/utils/internal-template.ts
1195
+ import fs6 from "fs-extra";
1196
+ import path7 from "path";
1197
+ import { fileURLToPath as fileURLToPath2 } from "url";
1198
+ import { performance as performance5 } from "perf_hooks";
1199
+ import { x as extractTar2 } from "tar";
1200
+ var assetDirectory = fileURLToPath2(new URL("./template/", import.meta.url));
1201
+ var archivePath = path7.join(assetDirectory, "micro-app.tar.gz");
1202
+ async function loadInternalTemplate() {
1203
+ try {
1204
+ const snapshot = await fs6.readJson(path7.join(assetDirectory, "micro-app.snapshot.json"));
1205
+ if (typeof snapshot !== "object" || snapshot === null || !("commit" in snapshot) || typeof snapshot.commit !== "string" || !/^[a-f\d]{40}$/.test(snapshot.commit)) {
1206
+ throw new Error("\u5185\u7F6E\u6A21\u677F\u6765\u6E90\u7248\u672C\u65E0\u6548");
1207
+ }
1208
+ if (!(await fs6.stat(archivePath)).isFile()) {
1209
+ throw new Error("\u5185\u7F6E\u6A21\u677F\u6587\u4EF6\u65E0\u6548");
1210
+ }
1211
+ 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",
1216
+ version: snapshot.commit
1217
+ };
1218
+ } catch (error) {
1219
+ 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
1221
+ ${message}`);
1222
+ }
1223
+ }
1224
+ async function copyInternalTemplate(targetDir) {
1225
+ const startedAt = performance5.now();
1226
+ await fs6.ensureDir(targetDir);
1227
+ await extractTar2({
1228
+ cwd: targetDir,
1229
+ file: archivePath,
1230
+ preservePaths: false,
1231
+ strict: true
1232
+ });
1233
+ return {
1234
+ cacheHit: false,
1235
+ copyMs: Math.round(performance5.now() - startedAt),
1236
+ downloadMs: 0,
1237
+ extractMs: 0,
1238
+ route: "bundled"
1239
+ };
1240
+ }
1241
+
1194
1242
  // src/commands/create.ts
1195
1243
  async function create(projectName, options = {}) {
1196
1244
  try {
1197
- configureNetwork({
1198
- forceDirect: options.proxy === false,
1199
- proxy: typeof options.proxy === "string" ? options.proxy : void 0
1200
- });
1245
+ if (!options.internal) {
1246
+ configureNetwork({
1247
+ forceDirect: options.proxy === false,
1248
+ proxy: typeof options.proxy === "string" ? options.proxy : void 0
1249
+ });
1250
+ }
1201
1251
  const templateTiming = createTemplateTiming();
1202
1252
  const context = await createInitContext(projectName, options, templateTiming);
1203
- const targetPath = path7.resolve(process.cwd(), context.projectName);
1253
+ const targetPath = path8.resolve(process.cwd(), context.projectName);
1204
1254
  if (!await prepareTargetDirectory(targetPath, context.projectName)) {
1205
1255
  return;
1206
1256
  }
@@ -1223,7 +1273,7 @@ async function create(projectName, options = {}) {
1223
1273
  async function createInitContext(projectName, options, templateTiming) {
1224
1274
  const finalProjectName = await getProjectName(projectName);
1225
1275
  const templates = await loadTemplates(templateTiming, options);
1226
- const template = await chooseTemplate(templates);
1276
+ const template = options.internal ? templates[0] : await chooseTemplate(templates);
1227
1277
  return {
1228
1278
  projectName: finalProjectName,
1229
1279
  template,
@@ -1240,6 +1290,14 @@ async function getProjectName(projectName) {
1240
1290
  });
1241
1291
  }
1242
1292
  async function loadTemplates(templateTiming, options) {
1293
+ if (options.internal) {
1294
+ const startedAt = performance6.now();
1295
+ const template = await loadInternalTemplate();
1296
+ templateTiming.configRoute = "bundled";
1297
+ 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];
1300
+ }
1243
1301
  const spinner = createStableSpinner();
1244
1302
  try {
1245
1303
  const config = await loadCliConfig();
@@ -1291,7 +1349,7 @@ function resolvePackageManager(requestedPackageManager) {
1291
1349
  return packageManager;
1292
1350
  }
1293
1351
  async function prepareTargetDirectory(targetPath, projectName) {
1294
- if (!await fs6.pathExists(targetPath)) {
1352
+ if (!await fs7.pathExists(targetPath)) {
1295
1353
  return true;
1296
1354
  }
1297
1355
  const overwrite = await confirm({
@@ -1302,42 +1360,43 @@ async function prepareTargetDirectory(targetPath, projectName) {
1302
1360
  console.log(chalk2.yellow("\u5DF2\u53D6\u6D88\u521B\u5EFA\u3002"));
1303
1361
  return false;
1304
1362
  }
1305
- await fs6.remove(targetPath);
1363
+ await fs7.remove(targetPath);
1306
1364
  return true;
1307
1365
  }
1308
1366
  async function downloadAndGenerate(context, targetPath, templateTiming, options) {
1309
1367
  const { template, projectName, packageManager } = context;
1310
1368
  const spinner = createStableSpinner();
1311
- const downloadStartedAt = performance5.now();
1369
+ const downloadStartedAt = performance6.now();
1312
1370
  try {
1313
- spinner.start(`\u6B63\u5728\u4E0B\u8F7D\u6A21\u677F ${template.label}...`);
1314
- const downloadTiming = await downloadTemplate(template, targetPath, {
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, {
1315
1373
  forceRefresh: options.refresh === true
1316
1374
  });
1317
1375
  assignDownloadTiming(templateTiming, downloadTiming);
1318
1376
  } catch (error) {
1319
- templateTiming.downloadMs = Math.round(performance5.now() - downloadStartedAt);
1320
- await fs6.remove(targetPath);
1377
+ templateTiming.downloadMs = Math.round(performance6.now() - downloadStartedAt);
1378
+ await fs7.remove(targetPath);
1321
1379
  if (spinner.isSpinning) {
1322
- spinner.fail("\u6A21\u677F\u4E0B\u8F7D\u5931\u8D25");
1380
+ spinner.fail(options.internal ? "\u5185\u7F6E\u6A21\u677F\u8BFB\u53D6\u5931\u8D25" : "\u6A21\u677F\u4E0B\u8F7D\u5931\u8D25");
1323
1381
  } else {
1324
- console.error(chalk2.red("\u6A21\u677F\u4E0B\u8F7D\u5931\u8D25"));
1382
+ console.error(chalk2.red(options.internal ? "\u5185\u7F6E\u6A21\u677F\u8BFB\u53D6\u5931\u8D25" : "\u6A21\u677F\u4E0B\u8F7D\u5931\u8D25"));
1325
1383
  }
1326
1384
  printTemplateTiming(templateTiming);
1327
1385
  const message = error instanceof Error && error.message ? error.message : "\u672A\u77E5\u9519\u8BEF";
1328
- throw new Error(`\u6A21\u677F\u4E0B\u8F7D\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u4ED3\u5E93\u5730\u5740\u6216\u7F51\u7EDC\u8FDE\u63A5\u3002
1386
+ throw new Error(options.internal ? `\u5185\u7F6E\u6A21\u677F\u8BFB\u53D6\u5931\u8D25\uFF0C\u8BF7\u91CD\u65B0\u5B89\u88C5 gz-cli-front\u3002
1387
+ ${message}` : `\u6A21\u677F\u4E0B\u8F7D\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u4ED3\u5E93\u5730\u5740\u6216\u7F51\u7EDC\u8FDE\u63A5\u3002
1329
1388
  ${message}`);
1330
1389
  }
1331
1390
  try {
1332
1391
  spinner.text = "\u6B63\u5728\u66FF\u6362\u6A21\u677F\u53D8\u91CF...";
1333
- const startedAt = performance5.now();
1392
+ const startedAt = performance6.now();
1334
1393
  await replaceTemplateVariables(targetPath, { projectName });
1335
1394
  await updateProjectPackageJson(targetPath, projectName, packageManager);
1336
- templateTiming.renderMs = Math.round(performance5.now() - startedAt);
1337
- spinner.succeed("\u6A21\u677F\u4E0B\u8F7D\u5E76\u751F\u6210\u5B8C\u6210");
1395
+ templateTiming.renderMs = Math.round(performance6.now() - startedAt);
1396
+ spinner.succeed(options.internal ? "\u5185\u7F6E\u6A21\u677F\u751F\u6210\u5B8C\u6210" : "\u6A21\u677F\u4E0B\u8F7D\u5E76\u751F\u6210\u5B8C\u6210");
1338
1397
  printTemplateTiming(templateTiming);
1339
1398
  } catch {
1340
- await fs6.remove(targetPath);
1399
+ await fs7.remove(targetPath);
1341
1400
  spinner.fail("\u6A21\u677F\u4E0B\u8F7D\u6216\u53D8\u91CF\u66FF\u6362\u5931\u8D25");
1342
1401
  throw new Error("\u6A21\u677F\u53D8\u91CF\u66FF\u6362\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u6A21\u677F\u6587\u4EF6\u5185\u5BB9\u3002");
1343
1402
  }
@@ -1375,6 +1434,9 @@ function printTemplateTiming(templateTiming) {
1375
1434
  console.log(`render: ${templateTiming.renderMs} ms`);
1376
1435
  }
1377
1436
  function formatRoute(route) {
1437
+ if (route === "bundled") {
1438
+ return "bundled, \u5185\u7F6E\u6A21\u677F";
1439
+ }
1378
1440
  if (route === "proxy-environment") {
1379
1441
  return "remote, \u73AF\u5883\u53D8\u91CF\u4EE3\u7406";
1380
1442
  }
@@ -1452,10 +1514,10 @@ var require2 = createRequire(import.meta.url);
1452
1514
  var packageMetadata = require2("../package.json");
1453
1515
  var packageVersion = getPackageVersion(packageMetadata);
1454
1516
  program.name("gz-cli").description("\u524D\u7AEF\u811A\u624B\u67B6\u5DE5\u5177").version(packageVersion);
1455
- program.command("init [project-name]", { isDefault: true }).description("\u521B\u5EFA\u4E00\u4E2A\u65B0\u9879\u76EE").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) => {
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) => {
1456
1518
  void create(projectName, options);
1457
1519
  });
1458
- program.command("create [project-name]").description("\u521B\u5EFA\u4E00\u4E2A\u65B0\u9879\u76EE\uFF08\u517C\u5BB9\u65E7\u547D\u4EE4\uFF09").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) => {
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) => {
1459
1521
  void create(projectName, options);
1460
1522
  });
1461
1523
  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/pre/index.ts"],"sourcesContent":["import { Command } 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 .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 .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\n\r\nexport interface InitOptions {\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';\r\n copyMs: number;\r\n fetchConfigMs: number;\r\n parseConfigMs: number;\r\n templateRoute: NetworkRoute | 'ssh' | 'cache' | 'stale-cache' | 'git';\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 configureNetwork({\r\n forceDirect: options.proxy === false,\r\n proxy: typeof options.proxy === 'string' ? options.proxy : undefined,\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 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(`正在下载模板 ${template.label}...`);\r\n const downloadTiming = 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('模板下载失败');\r\n } else {\r\n console.error(chalk.red('模板下载失败'));\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(`模板下载失败,请检查仓库地址或网络连接。\\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('模板下载并生成完成');\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 === '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';\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 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","path","chalk","getErrorMessage","fs","performance","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, 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"]}
@@ -0,0 +1,4 @@
1
+ {
2
+ "repository": "https://github.com/gz-fronted/gg-cli-template-micro-app.git",
3
+ "commit": "615cb063481c3c91737c8106ff838b57e668eedd"
4
+ }
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gz-cli-front",
3
- "version": "1.0.1-beta.0",
3
+ "version": "1.0.2",
4
4
  "description": "一个轻量级的现代前端脚手架工具",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -15,13 +15,15 @@
15
15
  "scripts": {
16
16
  "dev": "tsup --watch",
17
17
  "build": "tsup && node scripts/copy-assets.js",
18
+ "sync:template": "node scripts/sync-template.js",
18
19
  "prepublishOnly": "npm run test:release",
19
20
  "test": "echo \"Error: no test specified\" && exit 1",
20
21
  "test:cli": "node scripts/test-cli.js",
22
+ "test:internal": "node scripts/test-internal.js",
21
23
  "test:auth-error": "npm run build && node scripts/test-private-auth.js",
22
24
  "test:git-compat": "node --no-warnings --loader ts-node/esm scripts/test-git-credential-compat.ts",
23
25
  "test:private-access": "node --no-warnings --loader ts-node/esm scripts/test-private-access.ts",
24
- "test:smoke": "npm run test:cli && npm run test:git-compat && npm run test:private-access && node scripts/test-private-auth.js && npm pack --dry-run",
26
+ "test:smoke": "npm run test:cli && npm run test:internal && npm run test:git-compat && npm run test:private-access && node scripts/test-private-auth.js && npm pack --dry-run",
25
27
  "test:release": "npm run build && npm run test:smoke"
26
28
  },
27
29
  "keywords": [],