@icebreakers/monorepo 3.1.6 → 3.1.8

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.
@@ -8,7 +8,7 @@ export default defineMonorepoConfig({
8
8
  },
9
9
  clean: {
10
10
  autoConfirm: false,
11
- ignorePackages: ['@icebreakers/website'],
11
+ includePrivate: true,
12
12
  },
13
13
  sync: {
14
14
  concurrency: 4,
@@ -54,7 +54,7 @@
54
54
  "ci-info": "^4.3.1",
55
55
  "cross-env": "^10.1.0",
56
56
  "defu": "^6.1.4",
57
- "es-toolkit": "^1.42.0",
57
+ "es-toolkit": "^1.43.0",
58
58
  "eslint": "^9.39.1",
59
59
  "execa": "^9.6.1",
60
60
  "fs-extra": "^11.3.2",
package/dist/cli.cjs CHANGED
@@ -1,4 +1,4 @@
1
- const require_upgrade = require('./upgrade-bI11sYwb.cjs');
1
+ const require_upgrade = require('./upgrade-DEBWprtr.cjs');
2
2
  let node_process = require("node:process");
3
3
  node_process = require_upgrade.__toESM(node_process);
4
4
  let __inquirer_input = require("@inquirer/input");
@@ -50,6 +50,7 @@ commander.program.command("ai").description("AI 助手工具集").command("creat
50
50
  const tasksFile = opts.tasks ?? aiConfig?.tasksFile;
51
51
  const name$1 = opts.name;
52
52
  if (Boolean(tasksFile && !opts.output && !opts.name)) {
53
+ if (!tasksFile) throw new Error("tasks file path is required when using tasks mode");
53
54
  await require_upgrade.generateAgenticTemplates(await require_upgrade.loadAgenticTasks(tasksFile, cwd), {
54
55
  cwd,
55
56
  baseDir,
package/dist/cli.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { A as defaultAgenticBaseDir, C as name, M as generateAgenticTemplates, N as loadAgenticTasks, O as resolveCommandConfig, P as logger, T as cleanProjects, c as getCreateChoices, i as init, j as generateAgenticTemplate, k as createTimestampFolderName, n as syncNpmMirror, o as createNewProject, r as setVscodeBinaryMirror, s as defaultTemplate, t as upgradeMonorepo, w as version } from "./upgrade-DM5OLZGd.mjs";
1
+ import { A as createTimestampFolderName, E as cleanProjects, F as logger, M as generateAgenticTemplate, N as generateAgenticTemplates, P as loadAgenticTasks, T as version, c as getCreateChoices, i as init, j as defaultAgenticBaseDir, k as resolveCommandConfig, n as syncNpmMirror, o as createNewProject, r as setVscodeBinaryMirror, s as defaultTemplate, t as upgradeMonorepo, w as name } from "./upgrade-DjrKVY-g.mjs";
2
2
  import process from "node:process";
3
3
  import input from "@inquirer/input";
4
4
  import select from "@inquirer/select";
@@ -47,6 +47,7 @@ program.command("ai").description("AI 助手工具集").command("create").alias(
47
47
  const tasksFile = opts.tasks ?? aiConfig?.tasksFile;
48
48
  const name$1 = opts.name;
49
49
  if (Boolean(tasksFile && !opts.output && !opts.name)) {
50
+ if (!tasksFile) throw new Error("tasks file path is required when using tasks mode");
50
51
  await generateAgenticTemplates(await loadAgenticTasks(tasksFile, cwd), {
51
52
  cwd,
52
53
  baseDir,
package/dist/index.cjs CHANGED
@@ -1,4 +1,4 @@
1
- const require_upgrade = require('./upgrade-bI11sYwb.cjs');
1
+ const require_upgrade = require('./upgrade-DEBWprtr.cjs');
2
2
 
3
3
  exports.GitClient = require_upgrade.GitClient;
4
4
  exports.assetsDir = require_upgrade.assetsDir;
@@ -39,6 +39,7 @@ exports.templateMap = require_upgrade.templateMap;
39
39
  exports.templatesDir = require_upgrade.templatesDir;
40
40
  exports.toPublishGitignorePath = require_upgrade.toPublishGitignorePath;
41
41
  exports.toWorkspaceGitignorePath = require_upgrade.toWorkspaceGitignorePath;
42
+ exports.updateIssueTemplateConfig = require_upgrade.updateIssueTemplateConfig;
42
43
  exports.upgradeMonorepo = require_upgrade.upgradeMonorepo;
43
44
  Object.defineProperty(exports, 'version', {
44
45
  enumerable: true,
package/dist/index.d.cts CHANGED
@@ -252,7 +252,7 @@ interface CleanCommandConfig {
252
252
  ignorePackages?: string[];
253
253
  /**
254
254
  * 是否包含 private 包。
255
- * @default false
255
+ * @default true
256
256
  */
257
257
  includePrivate?: boolean;
258
258
  /**
@@ -325,6 +325,11 @@ interface InitCommandConfig {
325
325
  * @default false
326
326
  */
327
327
  skipChangeset?: boolean;
328
+ /**
329
+ * 是否跳过 Issue 模版 discussions 链接的更新。
330
+ * @default false
331
+ */
332
+ skipIssueTemplateConfig?: boolean;
328
333
  }
329
334
  /**
330
335
  * `monorepo mirror` 命令配置,可增加额外的环境变量镜像。
@@ -533,6 +538,12 @@ declare const logger: consola0.ConsolaInstance;
533
538
  */
534
539
  declare function isIgnorableFsError(error: unknown): error is NodeJS.ErrnoException;
535
540
  //#endregion
541
+ //#region src/utils/github.d.ts
542
+ /**
543
+ * 将 Issue 模版里的 discussions 链接同步为当前仓库的 discussions 地址。
544
+ */
545
+ declare function updateIssueTemplateConfig(source: string, repoName?: string): string;
546
+ //#endregion
536
547
  //#region src/utils/gitignore.d.ts
537
548
  /**
538
549
  * Map a workspace path (containing `.gitignore`) to its packaged variant.
@@ -568,4 +579,4 @@ declare function escapeStringRegexp(str: string): string;
568
579
  */
569
580
  declare function isMatch(str: string, arr: RegExp[]): boolean;
570
581
  //#endregion
571
- export { AgenticTemplateFormat, AgenticTemplateTask, type AiCommandConfig, type CleanCommandConfig, type CliOpts, type ConfigValues, Context, type CreateChoiceOption, type CreateCommandConfig, CreateNewProjectOptions, GenerateAgenticTemplateOptions, type GetWorkspacePackagesOptions, GitClient, type InitCommandConfig, type MirrorCommandConfig, type MonorepoConfig, type PackageJson, type SimpleGit, type SimpleGitOptions, type SyncCommandConfig, type UpgradeCommandConfig, assetsDir, cleanProjects, createContext, createNewProject, createTimestampFolderName, defaultAgenticBaseDir, defineMonorepoConfig, escapeStringRegexp, generateAgenticTemplate, generateAgenticTemplates, getCreateChoices, getFileHash, getTemplateMap, getWorkspaceData, getWorkspacePackages, init, isFileChanged, isGitignoreFile, isIgnorableFsError, isMatch, loadAgenticTasks, loadMonorepoConfig, logger, name, packageDir, resolveCommandConfig, rootDir, setVscodeBinaryMirror, syncNpmMirror, templateMap, templatesDir, toPublishGitignorePath, toWorkspaceGitignorePath, upgradeMonorepo, version };
582
+ export { AgenticTemplateFormat, AgenticTemplateTask, type AiCommandConfig, type CleanCommandConfig, type CliOpts, type ConfigValues, Context, type CreateChoiceOption, type CreateCommandConfig, CreateNewProjectOptions, GenerateAgenticTemplateOptions, type GetWorkspacePackagesOptions, GitClient, type InitCommandConfig, type MirrorCommandConfig, type MonorepoConfig, type PackageJson, type SimpleGit, type SimpleGitOptions, type SyncCommandConfig, type UpgradeCommandConfig, assetsDir, cleanProjects, createContext, createNewProject, createTimestampFolderName, defaultAgenticBaseDir, defineMonorepoConfig, escapeStringRegexp, generateAgenticTemplate, generateAgenticTemplates, getCreateChoices, getFileHash, getTemplateMap, getWorkspaceData, getWorkspacePackages, init, isFileChanged, isGitignoreFile, isIgnorableFsError, isMatch, loadAgenticTasks, loadMonorepoConfig, logger, name, packageDir, resolveCommandConfig, rootDir, setVscodeBinaryMirror, syncNpmMirror, templateMap, templatesDir, toPublishGitignorePath, toWorkspaceGitignorePath, updateIssueTemplateConfig, upgradeMonorepo, version };
package/dist/index.d.mts CHANGED
@@ -252,7 +252,7 @@ interface CleanCommandConfig {
252
252
  ignorePackages?: string[];
253
253
  /**
254
254
  * 是否包含 private 包。
255
- * @default false
255
+ * @default true
256
256
  */
257
257
  includePrivate?: boolean;
258
258
  /**
@@ -325,6 +325,11 @@ interface InitCommandConfig {
325
325
  * @default false
326
326
  */
327
327
  skipChangeset?: boolean;
328
+ /**
329
+ * 是否跳过 Issue 模版 discussions 链接的更新。
330
+ * @default false
331
+ */
332
+ skipIssueTemplateConfig?: boolean;
328
333
  }
329
334
  /**
330
335
  * `monorepo mirror` 命令配置,可增加额外的环境变量镜像。
@@ -533,6 +538,12 @@ declare const logger: consola0.ConsolaInstance;
533
538
  */
534
539
  declare function isIgnorableFsError(error: unknown): error is NodeJS.ErrnoException;
535
540
  //#endregion
541
+ //#region src/utils/github.d.ts
542
+ /**
543
+ * 将 Issue 模版里的 discussions 链接同步为当前仓库的 discussions 地址。
544
+ */
545
+ declare function updateIssueTemplateConfig(source: string, repoName?: string): string;
546
+ //#endregion
536
547
  //#region src/utils/gitignore.d.ts
537
548
  /**
538
549
  * Map a workspace path (containing `.gitignore`) to its packaged variant.
@@ -568,4 +579,4 @@ declare function escapeStringRegexp(str: string): string;
568
579
  */
569
580
  declare function isMatch(str: string, arr: RegExp[]): boolean;
570
581
  //#endregion
571
- export { type AgenticTemplateFormat, type AgenticTemplateTask, type AiCommandConfig, type CleanCommandConfig, type CliOpts, type ConfigValues, Context, type CreateChoiceOption, type CreateCommandConfig, type CreateNewProjectOptions, type GenerateAgenticTemplateOptions, type GetWorkspacePackagesOptions, GitClient, type InitCommandConfig, type MirrorCommandConfig, type MonorepoConfig, type PackageJson, type SimpleGit, type SimpleGitOptions, type SyncCommandConfig, type UpgradeCommandConfig, assetsDir, cleanProjects, createContext, createNewProject, createTimestampFolderName, defaultAgenticBaseDir, defineMonorepoConfig, escapeStringRegexp, generateAgenticTemplate, generateAgenticTemplates, getCreateChoices, getFileHash, getTemplateMap, getWorkspaceData, getWorkspacePackages, init, isFileChanged, isGitignoreFile, isIgnorableFsError, isMatch, loadAgenticTasks, loadMonorepoConfig, logger, name, packageDir, resolveCommandConfig, rootDir, setVscodeBinaryMirror, syncNpmMirror, templateMap, templatesDir, toPublishGitignorePath, toWorkspaceGitignorePath, upgradeMonorepo, version };
582
+ export { type AgenticTemplateFormat, type AgenticTemplateTask, type AiCommandConfig, type CleanCommandConfig, type CliOpts, type ConfigValues, Context, type CreateChoiceOption, type CreateCommandConfig, type CreateNewProjectOptions, type GenerateAgenticTemplateOptions, type GetWorkspacePackagesOptions, GitClient, type InitCommandConfig, type MirrorCommandConfig, type MonorepoConfig, type PackageJson, type SimpleGit, type SimpleGitOptions, type SyncCommandConfig, type UpgradeCommandConfig, assetsDir, cleanProjects, createContext, createNewProject, createTimestampFolderName, defaultAgenticBaseDir, defineMonorepoConfig, escapeStringRegexp, generateAgenticTemplate, generateAgenticTemplates, getCreateChoices, getFileHash, getTemplateMap, getWorkspaceData, getWorkspacePackages, init, isFileChanged, isGitignoreFile, isIgnorableFsError, isMatch, loadAgenticTasks, loadMonorepoConfig, logger, name, packageDir, resolveCommandConfig, rootDir, setVscodeBinaryMirror, syncNpmMirror, templateMap, templatesDir, toPublishGitignorePath, toWorkspaceGitignorePath, updateIssueTemplateConfig, upgradeMonorepo, version };
package/dist/index.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import { A as defaultAgenticBaseDir, C as name, D as loadMonorepoConfig, E as defineMonorepoConfig, F as getWorkspaceData, I as getWorkspacePackages, L as GitClient, M as generateAgenticTemplates, N as loadAgenticTasks, O as resolveCommandConfig, P as logger, S as templatesDir, T as cleanProjects, _ as toWorkspaceGitignorePath, a as createContext, b as packageDir, c as getCreateChoices, d as escapeStringRegexp, f as isMatch, g as toPublishGitignorePath, h as isGitignoreFile, i as init, j as generateAgenticTemplate, k as createTimestampFolderName, l as getTemplateMap, m as isFileChanged, n as syncNpmMirror, o as createNewProject, p as getFileHash, r as setVscodeBinaryMirror, t as upgradeMonorepo, u as templateMap, v as isIgnorableFsError, w as version, x as rootDir, y as assetsDir } from "./upgrade-DM5OLZGd.mjs";
1
+ import { A as createTimestampFolderName, C as templatesDir, D as defineMonorepoConfig, E as cleanProjects, F as logger, I as getWorkspaceData, L as getWorkspacePackages, M as generateAgenticTemplate, N as generateAgenticTemplates, O as loadMonorepoConfig, P as loadAgenticTasks, R as GitClient, S as rootDir, T as version, _ as toWorkspaceGitignorePath, a as createContext, b as assetsDir, c as getCreateChoices, d as escapeStringRegexp, f as isMatch, g as toPublishGitignorePath, h as isGitignoreFile, i as init, j as defaultAgenticBaseDir, k as resolveCommandConfig, l as getTemplateMap, m as isFileChanged, n as syncNpmMirror, o as createNewProject, p as getFileHash, r as setVscodeBinaryMirror, t as upgradeMonorepo, u as templateMap, v as updateIssueTemplateConfig, w as name, x as packageDir, y as isIgnorableFsError } from "./upgrade-DjrKVY-g.mjs";
2
2
 
3
- export { GitClient, assetsDir, cleanProjects, createContext, createNewProject, createTimestampFolderName, defaultAgenticBaseDir, defineMonorepoConfig, escapeStringRegexp, generateAgenticTemplate, generateAgenticTemplates, getCreateChoices, getFileHash, getTemplateMap, getWorkspaceData, getWorkspacePackages, init, isFileChanged, isGitignoreFile, isIgnorableFsError, isMatch, loadAgenticTasks, loadMonorepoConfig, logger, name, packageDir, resolveCommandConfig, rootDir, setVscodeBinaryMirror, syncNpmMirror, templateMap, templatesDir, toPublishGitignorePath, toWorkspaceGitignorePath, upgradeMonorepo, version };
3
+ export { GitClient, assetsDir, cleanProjects, createContext, createNewProject, createTimestampFolderName, defaultAgenticBaseDir, defineMonorepoConfig, escapeStringRegexp, generateAgenticTemplate, generateAgenticTemplates, getCreateChoices, getFileHash, getTemplateMap, getWorkspaceData, getWorkspacePackages, init, isFileChanged, isGitignoreFile, isIgnorableFsError, isMatch, loadAgenticTasks, loadMonorepoConfig, logger, name, packageDir, resolveCommandConfig, rootDir, setVscodeBinaryMirror, syncNpmMirror, templateMap, templatesDir, toPublishGitignorePath, toWorkspaceGitignorePath, updateIssueTemplateConfig, upgradeMonorepo, version };
@@ -47,6 +47,8 @@ picocolors = __toESM(picocolors);
47
47
  let node_path = require("node:path");
48
48
  node_path = __toESM(node_path);
49
49
  let node_url = require("node:url");
50
+ let yaml = require("yaml");
51
+ yaml = __toESM(yaml);
50
52
  let node_crypto = require("node:crypto");
51
53
  node_crypto = __toESM(node_crypto);
52
54
  require("@pnpm/types");
@@ -58,8 +60,6 @@ let p_queue = require("p-queue");
58
60
  p_queue = __toESM(p_queue);
59
61
  let klaw = require("klaw");
60
62
  klaw = __toESM(klaw);
61
- let yaml = require("yaml");
62
- yaml = __toESM(yaml);
63
63
  let node_buffer = require("node:buffer");
64
64
  let semver = require("semver");
65
65
 
@@ -74,9 +74,9 @@ var join = /* @__PURE__ */ __name((segs, joinChar, options) => {
74
74
  if (typeof options.join === "function") return options.join(segs);
75
75
  return segs[0] + joinChar + segs[1];
76
76
  }, "join");
77
- var split$1 = /* @__PURE__ */ __name((path$13, splitChar, options) => {
78
- if (typeof options.split === "function") return options.split(path$13);
79
- return path$13.split(splitChar);
77
+ var split$1 = /* @__PURE__ */ __name((path$14, splitChar, options) => {
78
+ if (typeof options.split === "function") return options.split(path$14);
79
+ return path$14.split(splitChar);
80
80
  }, "split");
81
81
  var isValid = /* @__PURE__ */ __name((key, target = {}, options) => {
82
82
  if (typeof options?.isValid === "function") return options.isValid(key, target);
@@ -85,17 +85,17 @@ var isValid = /* @__PURE__ */ __name((key, target = {}, options) => {
85
85
  var isValidObject = /* @__PURE__ */ __name((v) => {
86
86
  return isObject$2(v) || typeof v === "function";
87
87
  }, "isValidObject");
88
- var index_default = /* @__PURE__ */ __name((target, path$13, options = {}) => {
88
+ var index_default = /* @__PURE__ */ __name((target, path$14, options = {}) => {
89
89
  if (!isObject$2(options)) options = { default: options };
90
90
  if (!isValidObject(target)) return typeof options.default !== "undefined" ? options.default : target;
91
- if (typeof path$13 === "number") path$13 = String(path$13);
92
- const pathIsArray = Array.isArray(path$13);
93
- const pathIsString = typeof path$13 === "string";
91
+ if (typeof path$14 === "number") path$14 = String(path$14);
92
+ const pathIsArray = Array.isArray(path$14);
93
+ const pathIsString = typeof path$14 === "string";
94
94
  const splitChar = options.separator || ".";
95
95
  const joinChar = options.joinChar || (typeof splitChar === "string" ? splitChar : ".");
96
96
  if (!pathIsString && !pathIsArray) return target;
97
- if (target[path$13] !== void 0) return isValid(path$13, target, options) ? target[path$13] : options.default;
98
- const segs = pathIsArray ? path$13 : split$1(path$13, splitChar, options);
97
+ if (target[path$14] !== void 0) return isValid(path$14, target, options) ? target[path$14] : options.default;
98
+ const segs = pathIsArray ? path$14 : split$1(path$14, splitChar, options);
99
99
  const len = segs.length;
100
100
  let idx = 0;
101
101
  do {
@@ -494,9 +494,9 @@ var require_set_value = /* @__PURE__ */ __commonJSMin(((exports, module) => {
494
494
  } else obj[prop] = value;
495
495
  return obj;
496
496
  };
497
- const setValue = (target, path$13, value, options) => {
498
- if (!path$13 || !isObject(target)) return target;
499
- const keys = split(path$13, options);
497
+ const setValue = (target, path$14, value, options) => {
498
+ if (!path$14 || !isObject(target)) return target;
499
+ const keys = split(path$14, options);
500
500
  let obj = target;
501
501
  for (let i = 0; i < keys.length; i++) {
502
502
  const key = keys[i];
@@ -572,10 +572,11 @@ async function resolveCommandConfig(name$1, cwd) {
572
572
  //#region src/commands/clean.ts
573
573
  var import_set_value$5 = /* @__PURE__ */ __toESM(require_set_value(), 1);
574
574
  function mergeCleanConfig(base, overrides) {
575
- if (!overrides) return base;
575
+ const normalizedBase = base ?? {};
576
+ if (!overrides) return normalizedBase;
576
577
  const definedOverrides = Object.fromEntries(Object.entries(overrides).filter(([, value]) => value !== void 0));
577
578
  return {
578
- ...base,
579
+ ...normalizedBase,
579
580
  ...definedOverrides
580
581
  };
581
582
  }
@@ -584,7 +585,7 @@ function mergeCleanConfig(base, overrides) {
584
585
  */
585
586
  async function cleanProjects(cwd, overrides) {
586
587
  const cleanConfig = mergeCleanConfig(await resolveCommandConfig("clean", cwd), overrides);
587
- const { packages, workspaceDir } = await getWorkspaceData(cwd, cleanConfig?.includePrivate ? { ignorePrivatePackage: false } : void 0);
588
+ const { packages, workspaceDir } = await getWorkspaceData(cwd, cleanConfig?.includePrivate ?? true ? { ignorePrivatePackage: false } : void 0);
588
589
  const filteredPackages = packages.filter((pkg) => {
589
590
  const name$2 = pkg.manifest.name ?? "";
590
591
  if (!name$2) return true;
@@ -604,7 +605,8 @@ async function cleanProjects(cwd, overrides) {
604
605
  };
605
606
  })
606
607
  });
607
- const candidates = Array.from(new Set(cleanDirs.filter(Boolean)));
608
+ const readmeZh = pathe.default.resolve(workspaceDir, "README.zh-CN.md");
609
+ const candidates = Array.from(new Set([...cleanDirs.filter(Boolean), readmeZh]));
608
610
  await Promise.all(candidates.map(async (dir) => {
609
611
  if (await fs_extra.default.pathExists(dir)) await fs_extra.default.remove(dir);
610
612
  }));
@@ -617,7 +619,7 @@ async function cleanProjects(cwd, overrides) {
617
619
  //#endregion
618
620
  //#region package.json
619
621
  var name = "@icebreakers/monorepo";
620
- var version = "3.1.6";
622
+ var version = "3.1.8";
621
623
 
622
624
  //#endregion
623
625
  //#region src/constants.ts
@@ -655,6 +657,43 @@ function isIgnorableFsError(error) {
655
657
  return code === "ENOENT" || code === "EBUSY" || code === "EEXIST";
656
658
  }
657
659
 
660
+ //#endregion
661
+ //#region src/utils/github.ts
662
+ /**
663
+ * 将 Issue 模版里的 discussions 链接同步为当前仓库的 discussions 地址。
664
+ */
665
+ function updateIssueTemplateConfig(source, repoName) {
666
+ if (!repoName) return source;
667
+ let doc;
668
+ try {
669
+ doc = (0, yaml.parseDocument)(source);
670
+ } catch {
671
+ return source;
672
+ }
673
+ const contactLinks = doc.get("contact_links");
674
+ if (!(0, yaml.isSeq)(contactLinks)) return source;
675
+ const nextUrl = `https://github.com/${repoName}/discussions`;
676
+ let changed = false;
677
+ contactLinks.items.forEach((_, index) => {
678
+ const url = doc.getIn([
679
+ "contact_links",
680
+ index,
681
+ "url"
682
+ ]);
683
+ if (typeof url !== "string") return;
684
+ if (!url.includes("/discussions")) return;
685
+ if (url === nextUrl) return;
686
+ doc.setIn([
687
+ "contact_links",
688
+ index,
689
+ "url"
690
+ ], nextUrl);
691
+ changed = true;
692
+ });
693
+ if (!changed) return source;
694
+ return doc.toString();
695
+ }
696
+
658
697
  //#endregion
659
698
  //#region src/utils/gitignore.ts
660
699
  /**
@@ -912,6 +951,21 @@ async function setChangeset_default(ctx) {
912
951
  }
913
952
  }
914
953
 
954
+ //#endregion
955
+ //#region src/commands/init/setIssueTemplateConfig.ts
956
+ /**
957
+ * 同步 Issue 模版里的 discussions 链接到当前仓库。
958
+ */
959
+ async function setIssueTemplateConfig_default(ctx) {
960
+ const repoName = ctx.gitUrl?.full_name;
961
+ if (!repoName) return;
962
+ const configPath = pathe.default.resolve(ctx.cwd, ".github/ISSUE_TEMPLATE/config.yml");
963
+ if (!await fs_extra.default.pathExists(configPath)) return;
964
+ const source = await fs_extra.default.readFile(configPath, "utf8");
965
+ const next = updateIssueTemplateConfig(source, repoName);
966
+ if (next !== source) await fs_extra.default.writeFile(configPath, next, "utf8");
967
+ }
968
+
915
969
  //#endregion
916
970
  //#region src/commands/init/setPkgJson.ts
917
971
  var import_set_value$2 = /* @__PURE__ */ __toESM(require_set_value(), 1);
@@ -996,6 +1050,7 @@ async function init(cwd) {
996
1050
  if (!initConfig.skipChangeset) await setChangeset_default(ctx);
997
1051
  if (!initConfig.skipPkgJson) await setPkgJson_default(ctx);
998
1052
  if (!initConfig.skipReadme) await setReadme_default(ctx);
1053
+ if (!initConfig.skipIssueTemplateConfig) await setIssueTemplateConfig_default(ctx);
999
1054
  }
1000
1055
 
1001
1056
  //#endregion
@@ -1441,6 +1496,24 @@ async function upgradeMonorepo(opts) {
1441
1496
  });
1442
1497
  continue;
1443
1498
  }
1499
+ if (relPath === ".github/ISSUE_TEMPLATE/config.yml") {
1500
+ const data = updateIssueTemplateConfig(await fs_extra.default.readFile(file.path, "utf8"), repoName);
1501
+ const intent$1 = await evaluateWriteIntent(targetPath, {
1502
+ skipOverwrite,
1503
+ source: data
1504
+ });
1505
+ const action$1 = async () => {
1506
+ await fs_extra.default.outputFile(targetPath, data);
1507
+ logger.success(targetPath);
1508
+ };
1509
+ await scheduleOverwrite(intent$1, {
1510
+ relPath,
1511
+ targetPath,
1512
+ action: action$1,
1513
+ pending: pendingOverwrites
1514
+ });
1515
+ continue;
1516
+ }
1444
1517
  const source = await fs_extra.default.readFile(file.path);
1445
1518
  const intent = await evaluateWriteIntent(targetPath, {
1446
1519
  skipOverwrite,
@@ -1681,6 +1754,12 @@ Object.defineProperty(exports, 'toWorkspaceGitignorePath', {
1681
1754
  return toWorkspaceGitignorePath;
1682
1755
  }
1683
1756
  });
1757
+ Object.defineProperty(exports, 'updateIssueTemplateConfig', {
1758
+ enumerable: true,
1759
+ get: function () {
1760
+ return updateIssueTemplateConfig;
1761
+ }
1762
+ });
1684
1763
  Object.defineProperty(exports, 'upgradeMonorepo', {
1685
1764
  enumerable: true,
1686
1765
  get: function () {
@@ -12,6 +12,7 @@ import { loadConfig } from "c12";
12
12
  import pc from "picocolors";
13
13
  import path$1 from "node:path";
14
14
  import { fileURLToPath } from "node:url";
15
+ import YAML, { isSeq, parseDocument } from "yaml";
15
16
  import crypto from "node:crypto";
16
17
  import "@pnpm/types";
17
18
  import { parse, stringify } from "comment-json";
@@ -19,7 +20,6 @@ import os from "node:os";
19
20
  import { execaCommand } from "execa";
20
21
  import PQueue from "p-queue";
21
22
  import klaw from "klaw";
22
- import YAML from "yaml";
23
23
  import { Buffer as Buffer$1 } from "node:buffer";
24
24
  import { coerce, gte, minVersion } from "semver";
25
25
 
@@ -560,10 +560,11 @@ async function resolveCommandConfig(name$1, cwd) {
560
560
  //#region src/commands/clean.ts
561
561
  var import_set_value$5 = /* @__PURE__ */ __toESM(require_set_value(), 1);
562
562
  function mergeCleanConfig(base, overrides) {
563
- if (!overrides) return base;
563
+ const normalizedBase = base ?? {};
564
+ if (!overrides) return normalizedBase;
564
565
  const definedOverrides = Object.fromEntries(Object.entries(overrides).filter(([, value]) => value !== void 0));
565
566
  return {
566
- ...base,
567
+ ...normalizedBase,
567
568
  ...definedOverrides
568
569
  };
569
570
  }
@@ -572,7 +573,7 @@ function mergeCleanConfig(base, overrides) {
572
573
  */
573
574
  async function cleanProjects(cwd, overrides) {
574
575
  const cleanConfig = mergeCleanConfig(await resolveCommandConfig("clean", cwd), overrides);
575
- const { packages, workspaceDir } = await getWorkspaceData(cwd, cleanConfig?.includePrivate ? { ignorePrivatePackage: false } : void 0);
576
+ const { packages, workspaceDir } = await getWorkspaceData(cwd, cleanConfig?.includePrivate ?? true ? { ignorePrivatePackage: false } : void 0);
576
577
  const filteredPackages = packages.filter((pkg) => {
577
578
  const name$2 = pkg.manifest.name ?? "";
578
579
  if (!name$2) return true;
@@ -592,7 +593,8 @@ async function cleanProjects(cwd, overrides) {
592
593
  };
593
594
  })
594
595
  });
595
- const candidates = Array.from(new Set(cleanDirs.filter(Boolean)));
596
+ const readmeZh = path.resolve(workspaceDir, "README.zh-CN.md");
597
+ const candidates = Array.from(new Set([...cleanDirs.filter(Boolean), readmeZh]));
596
598
  await Promise.all(candidates.map(async (dir) => {
597
599
  if (await fs.pathExists(dir)) await fs.remove(dir);
598
600
  }));
@@ -605,7 +607,7 @@ async function cleanProjects(cwd, overrides) {
605
607
  //#endregion
606
608
  //#region package.json
607
609
  var name = "@icebreakers/monorepo";
608
- var version = "3.1.6";
610
+ var version = "3.1.8";
609
611
 
610
612
  //#endregion
611
613
  //#region src/constants.ts
@@ -643,6 +645,43 @@ function isIgnorableFsError(error) {
643
645
  return code === "ENOENT" || code === "EBUSY" || code === "EEXIST";
644
646
  }
645
647
 
648
+ //#endregion
649
+ //#region src/utils/github.ts
650
+ /**
651
+ * 将 Issue 模版里的 discussions 链接同步为当前仓库的 discussions 地址。
652
+ */
653
+ function updateIssueTemplateConfig(source, repoName) {
654
+ if (!repoName) return source;
655
+ let doc;
656
+ try {
657
+ doc = parseDocument(source);
658
+ } catch {
659
+ return source;
660
+ }
661
+ const contactLinks = doc.get("contact_links");
662
+ if (!isSeq(contactLinks)) return source;
663
+ const nextUrl = `https://github.com/${repoName}/discussions`;
664
+ let changed = false;
665
+ contactLinks.items.forEach((_, index) => {
666
+ const url = doc.getIn([
667
+ "contact_links",
668
+ index,
669
+ "url"
670
+ ]);
671
+ if (typeof url !== "string") return;
672
+ if (!url.includes("/discussions")) return;
673
+ if (url === nextUrl) return;
674
+ doc.setIn([
675
+ "contact_links",
676
+ index,
677
+ "url"
678
+ ], nextUrl);
679
+ changed = true;
680
+ });
681
+ if (!changed) return source;
682
+ return doc.toString();
683
+ }
684
+
646
685
  //#endregion
647
686
  //#region src/utils/gitignore.ts
648
687
  /**
@@ -900,6 +939,21 @@ async function setChangeset_default(ctx) {
900
939
  }
901
940
  }
902
941
 
942
+ //#endregion
943
+ //#region src/commands/init/setIssueTemplateConfig.ts
944
+ /**
945
+ * 同步 Issue 模版里的 discussions 链接到当前仓库。
946
+ */
947
+ async function setIssueTemplateConfig_default(ctx) {
948
+ const repoName = ctx.gitUrl?.full_name;
949
+ if (!repoName) return;
950
+ const configPath = path.resolve(ctx.cwd, ".github/ISSUE_TEMPLATE/config.yml");
951
+ if (!await fs.pathExists(configPath)) return;
952
+ const source = await fs.readFile(configPath, "utf8");
953
+ const next = updateIssueTemplateConfig(source, repoName);
954
+ if (next !== source) await fs.writeFile(configPath, next, "utf8");
955
+ }
956
+
903
957
  //#endregion
904
958
  //#region src/commands/init/setPkgJson.ts
905
959
  var import_set_value$2 = /* @__PURE__ */ __toESM(require_set_value(), 1);
@@ -984,6 +1038,7 @@ async function init(cwd) {
984
1038
  if (!initConfig.skipChangeset) await setChangeset_default(ctx);
985
1039
  if (!initConfig.skipPkgJson) await setPkgJson_default(ctx);
986
1040
  if (!initConfig.skipReadme) await setReadme_default(ctx);
1041
+ if (!initConfig.skipIssueTemplateConfig) await setIssueTemplateConfig_default(ctx);
987
1042
  }
988
1043
 
989
1044
  //#endregion
@@ -1429,6 +1484,24 @@ async function upgradeMonorepo(opts) {
1429
1484
  });
1430
1485
  continue;
1431
1486
  }
1487
+ if (relPath === ".github/ISSUE_TEMPLATE/config.yml") {
1488
+ const data = updateIssueTemplateConfig(await fs.readFile(file.path, "utf8"), repoName);
1489
+ const intent$1 = await evaluateWriteIntent(targetPath, {
1490
+ skipOverwrite,
1491
+ source: data
1492
+ });
1493
+ const action$1 = async () => {
1494
+ await fs.outputFile(targetPath, data);
1495
+ logger.success(targetPath);
1496
+ };
1497
+ await scheduleOverwrite(intent$1, {
1498
+ relPath,
1499
+ targetPath,
1500
+ action: action$1,
1501
+ pending: pendingOverwrites
1502
+ });
1503
+ continue;
1504
+ }
1432
1505
  const source = await fs.readFile(file.path);
1433
1506
  const intent = await evaluateWriteIntent(targetPath, {
1434
1507
  skipOverwrite,
@@ -1453,4 +1526,4 @@ async function upgradeMonorepo(opts) {
1453
1526
  }
1454
1527
 
1455
1528
  //#endregion
1456
- export { defaultAgenticBaseDir as A, name as C, loadMonorepoConfig as D, defineMonorepoConfig as E, getWorkspaceData as F, getWorkspacePackages as I, GitClient as L, generateAgenticTemplates as M, loadAgenticTasks as N, resolveCommandConfig as O, logger as P, templatesDir as S, cleanProjects as T, toWorkspaceGitignorePath as _, createContext as a, packageDir as b, getCreateChoices as c, escapeStringRegexp as d, isMatch as f, toPublishGitignorePath as g, isGitignoreFile as h, init as i, generateAgenticTemplate as j, createTimestampFolderName as k, getTemplateMap as l, isFileChanged as m, syncNpmMirror as n, createNewProject as o, getFileHash as p, setVscodeBinaryMirror as r, defaultTemplate as s, upgradeMonorepo as t, templateMap as u, isIgnorableFsError as v, version as w, rootDir as x, assetsDir as y };
1529
+ export { createTimestampFolderName as A, templatesDir as C, defineMonorepoConfig as D, cleanProjects as E, logger as F, getWorkspaceData as I, getWorkspacePackages as L, generateAgenticTemplate as M, generateAgenticTemplates as N, loadMonorepoConfig as O, loadAgenticTasks as P, GitClient as R, rootDir as S, version as T, toWorkspaceGitignorePath as _, createContext as a, assetsDir as b, getCreateChoices as c, escapeStringRegexp as d, isMatch as f, toPublishGitignorePath as g, isGitignoreFile as h, init as i, defaultAgenticBaseDir as j, resolveCommandConfig as k, getTemplateMap as l, isFileChanged as m, syncNpmMirror as n, createNewProject as o, getFileHash as p, setVscodeBinaryMirror as r, defaultTemplate as s, upgradeMonorepo as t, templateMap as u, updateIssueTemplateConfig as v, name as w, packageDir as x, isIgnorableFsError as y };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@icebreakers/monorepo",
3
3
  "type": "module",
4
- "version": "3.1.6",
4
+ "version": "3.1.8",
5
5
  "description": "The icebreaker's monorepo manager",
6
6
  "author": "ice breaker <1324318532@qq.com>",
7
7
  "license": "MIT",
@@ -34,7 +34,7 @@
34
34
  "@hono/trpc-server": "^0.4.1",
35
35
  "@tailwindcss/vite": "^4.1.18",
36
36
  "@trpc/server": "^11.7.2",
37
- "@vitejs/plugin-vue": "^6.0.2",
37
+ "@vitejs/plugin-vue": "^6.0.3",
38
38
  "@vitejs/plugin-vue-jsx": "^5.1.2",
39
39
  "@vue/tsconfig": "^0.8.1",
40
40
  "hono": "^4.10.8",
@@ -18,7 +18,7 @@ layout: doc
18
18
 
19
19
  1. **拉取模板**:[GitHub](https://github.com/sonofmagic/monorepo-template) 右上角 `Use this template`,或克隆源码。
20
20
  2. **安装依赖**:在 `pnpm-workspace.yaml` 所在目录执行 `pnpm install`(需要 Node.js ≥ 20,推荐 `npm i -g pnpm`)。
21
- 3. **可选清理**:运行 `pnpm script:clean` 移除演示包,仅保留最小打包模板;随后再次执行 `pnpm install` 更新 lockfile。
21
+ 3. **可选清理**:直接运行 `npx -y @icebreakers/monorepo@latest clean` 远程执行清理,移除演示包后再执行 `pnpm install`(避免依赖本地构建 `monorepo`);如已安装依赖,也可使用 `pnpm script:clean`。
22
22
  4. **初始化元数据**:`pnpm script:init` 会批量更新 `package.json`、`README.md` 等公共信息。
23
23
 
24
24
  ## 仓库结构速览
@@ -49,7 +49,7 @@ layout: doc
49
49
 
50
50
  ```bash
51
51
  npx monorepo new # 创建子包/应用
52
- npx monorepo clean # 批量删除已勾选的子项目
52
+ npx -y @icebreakers/monorepo@latest clean # 远程清理已勾选的子项目,避免依赖本地构建
53
53
  npx monorepo sync # 同步所有包到 npmmirror
54
54
  npx monorepo mirror # 写入 VS Code 镜像配置
55
55
  npx monorepo up # 从最新模板同步配置文件
@@ -98,8 +98,11 @@ jobs:
98
98
  - uses: pnpm/action-setup@v4
99
99
  - uses: actions/setup-node@v4
100
100
  with:
101
- node-version: 22
101
+ # 这是为了使用新版本的 npm, 只有 npm@11.5.x 以上版本才支持 OIDC
102
+ # 否则你就必须使用 npm i -g npm@latest 来升级 npm 版本
103
+ node-version: 24
102
104
  cache: pnpm
105
+ registry-url: https://registry.npmjs.org
103
106
  - run: pnpm install
104
107
  - name: Create Release Pull Request or Publish to npm
105
108
  uses: changesets/action@v1
@@ -107,11 +110,13 @@ jobs:
107
110
  publish: pnpm publish-packages
108
111
  env:
109
112
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
110
- NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
113
+ # npm/action-oidc-auth 会设置 NODE_AUTH_TOKEN 供 publish 使用
111
114
  ```
112
115
 
113
116
  `pnpm publish-packages` 为模板内脚本,可替换为自定义构建+发布流程。
114
117
 
118
+ > 说明:npm 现行 token 默认 90 天过期,推荐在 CI 中使用 OIDC(如上)动态获取 `NODE_AUTH_TOKEN`,无需手动传入 `NPM_TOKEN`。若使用自托管或其他 CI,需要确保工作流具备 `id-token: write` 权限。
119
+
115
120
  ## 与其他方案对比
116
121
 
117
122
  | 能力 / 工具 | changesets | lerna 经典模式 | 手写脚本 |
@@ -68,7 +68,7 @@ registry.npmjs.org/:_authToken=npm_hashhashhashhashhashhashhashhashhash
68
68
 
69
69
  假如这一行存在,说明你本地的 `npm Access Token` 就设置好了,然后你才有发包的权限。
70
70
 
71
- > 你也可以在 `https://www.npmjs.com/settings/<你的用户名>/tokens` 中管理你的 `token`,给不同的 `token` 设置不同的作用域,有效期和 `ip` 限制,帮助你适配正常开发,`CI/CD`,`Token` 分发的各种场景
71
+ > 你也可以在 `https://www.npmjs.com/settings/<你的用户名>/tokens` 中管理你的 `token`,给不同的 `token` 设置不同的作用域,有效期(目前最长 90 天)和 `ip` 限制,帮助你适配正常开发,`CI/CD`,`Token` 分发的各种场景;如需避免手动轮换,CI 场景推荐使用 npm 官方的 OIDC 方案获取临时 `NODE_AUTH_TOKEN`,并在工作流开启 `id-token: write` 权限。
72
72
 
73
73
  同样发私有源包也是同理:
74
74
 
@@ -46,7 +46,7 @@
46
46
  },
47
47
  "devDependencies": {
48
48
  "@tailwindcss/vite": "^4.1.18",
49
- "@vitejs/plugin-vue": "^6.0.2",
49
+ "@vitejs/plugin-vue": "^6.0.3",
50
50
  "@vue/test-utils": "^2.4.6",
51
51
  "@vue/tsconfig": "^0.8.1",
52
52
  "jsdom": "^27.3.0",