@icebreakers/monorepo 3.2.11 → 3.2.13

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/dist/cli.cjs CHANGED
@@ -1,4 +1,4 @@
1
- const require_upgrade = require('./upgrade-BDVNfq80.cjs');
1
+ const require_upgrade = require('./upgrade-DjOZstRC.cjs');
2
2
  let node_process = require("node:process");
3
3
  node_process = require_upgrade.__toESM(node_process);
4
4
  let _icebreakers_monorepo_templates = require("@icebreakers/monorepo-templates");
package/dist/cli.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { C as syncSkills, F as generateAgenticTemplate, I as generateAgenticTemplates, L as loadAgenticTasks, M as resolveCommandConfig, N as createTimestampFolderName, O as name, P as defaultAgenticBaseDir, R as logger, S as skillTargets, _ as getCreateChoices, b as cleanProjects, g as defaultTemplate, h as createNewProject, i as init, k as version, n as syncNpmMirror, r as setVscodeBinaryMirror, t as upgradeMonorepo } from "./upgrade-zJC3jLQe.mjs";
1
+ import { C as syncSkills, F as generateAgenticTemplate, I as generateAgenticTemplates, L as loadAgenticTasks, M as resolveCommandConfig, N as createTimestampFolderName, O as name, P as defaultAgenticBaseDir, R as logger, S as skillTargets, _ as getCreateChoices, b as cleanProjects, g as defaultTemplate, h as createNewProject, i as init, k as version, n as syncNpmMirror, r as setVscodeBinaryMirror, t as upgradeMonorepo } from "./upgrade-DiPTZW6J.mjs";
2
2
  import process from "node:process";
3
3
  import { input, program, select } from "@icebreakers/monorepo-templates";
4
4
 
package/dist/index.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- const require_upgrade = require('./upgrade-BDVNfq80.cjs');
2
+ const require_upgrade = require('./upgrade-DjOZstRC.cjs');
3
3
  let _icebreakers_monorepo_templates = require("@icebreakers/monorepo-templates");
4
4
 
5
5
  exports.GitClient = require_upgrade.GitClient;
package/dist/index.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import { A as defineMonorepoConfig, B as getWorkspacePackages, C as syncSkills, D as templatesDir, E as rootDir, F as generateAgenticTemplate, I as generateAgenticTemplates, L as loadAgenticTasks, M as resolveCommandConfig, N as createTimestampFolderName, O as name, P as defaultAgenticBaseDir, R as logger, S as skillTargets, T as packageDir, V as GitClient, _ as getCreateChoices, a as escapeStringRegexp, b as cleanProjects, c as isFileChanged, d as toWorkspaceGitignorePath, f as updateIssueTemplateConfig, h as createNewProject, i as init, j as loadMonorepoConfig, k as version, l as isGitignoreFile, m as createContext, n as syncNpmMirror, o as isMatch, p as isIgnorableFsError, r as setVscodeBinaryMirror, s as getFileHash, t as upgradeMonorepo, u as toPublishGitignorePath, v as getTemplateMap, w as assetsDir, x as getSkillTargetPaths, y as templateMap, z as getWorkspaceData } from "./upgrade-zJC3jLQe.mjs";
1
+ import { A as defineMonorepoConfig, B as getWorkspacePackages, C as syncSkills, D as templatesDir, E as rootDir, F as generateAgenticTemplate, I as generateAgenticTemplates, L as loadAgenticTasks, M as resolveCommandConfig, N as createTimestampFolderName, O as name, P as defaultAgenticBaseDir, R as logger, S as skillTargets, T as packageDir, V as GitClient, _ as getCreateChoices, a as escapeStringRegexp, b as cleanProjects, c as isFileChanged, d as toWorkspaceGitignorePath, f as updateIssueTemplateConfig, h as createNewProject, i as init, j as loadMonorepoConfig, k as version, l as isGitignoreFile, m as createContext, n as syncNpmMirror, o as isMatch, p as isIgnorableFsError, r as setVscodeBinaryMirror, s as getFileHash, t as upgradeMonorepo, u as toPublishGitignorePath, v as getTemplateMap, w as assetsDir, x as getSkillTargetPaths, y as templateMap, z as getWorkspaceData } from "./upgrade-DiPTZW6J.mjs";
2
2
 
3
3
  export { GitClient, assetsDir, cleanProjects, createContext, createNewProject, createTimestampFolderName, defaultAgenticBaseDir, defineMonorepoConfig, escapeStringRegexp, generateAgenticTemplate, generateAgenticTemplates, getCreateChoices, getFileHash, getSkillTargetPaths, getTemplateMap, getWorkspaceData, getWorkspacePackages, init, isFileChanged, isGitignoreFile, isIgnorableFsError, isMatch, loadAgenticTasks, loadMonorepoConfig, logger, name, packageDir, resolveCommandConfig, rootDir, setVscodeBinaryMirror, skillTargets, syncNpmMirror, syncSkills, templateMap, templatesDir, toPublishGitignorePath, toWorkspaceGitignorePath, updateIssueTemplateConfig, upgradeMonorepo, version };
@@ -559,7 +559,7 @@ async function resolveCommandConfig(name, cwd) {
559
559
  //#endregion
560
560
  //#region package.json
561
561
  var name = "@icebreakers/monorepo";
562
- var version = "3.2.11";
562
+ var version = "3.2.13";
563
563
 
564
564
  //#endregion
565
565
  //#region src/constants.ts
@@ -664,11 +664,13 @@ async function cleanProjects(cwd, overrides) {
664
664
  });
665
665
  const readmeZh = path.resolve(workspaceDir, "README.zh-CN.md");
666
666
  const qoderDir = path.resolve(workspaceDir, ".qoder");
667
+ const docsPlansDir = path.resolve(workspaceDir, "docs/plans");
667
668
  const skillTargets = Object.values(getSkillTargetPaths());
668
669
  const candidates = Array.from(new Set([
669
670
  ...cleanDirs.filter(Boolean),
670
671
  readmeZh,
671
672
  qoderDir,
673
+ docsPlansDir,
672
674
  ...skillTargets
673
675
  ]));
674
676
  await Promise.all(candidates.map(async (dir) => {
@@ -1162,9 +1164,12 @@ async function syncNpmMirror(cwd, options) {
1162
1164
 
1163
1165
  //#endregion
1164
1166
  //#region src/commands/upgrade/agents.ts
1165
- function normalizeEol(input) {
1167
+ function normalizeEol$1(input) {
1166
1168
  return input.replace(/\r\n/g, "\n");
1167
1169
  }
1170
+ function normalizeComparableContent(input) {
1171
+ return normalizeEol$1(input).trimEnd();
1172
+ }
1168
1173
  function normalizeHeadingKey(line) {
1169
1174
  return line.replace(/^##\s+/, "").trim().toLowerCase();
1170
1175
  }
@@ -1183,7 +1188,7 @@ function trimEdgeEmptyLines(lines) {
1183
1188
  return next;
1184
1189
  }
1185
1190
  function parseMarkdownByH2(content) {
1186
- const lines = normalizeEol(content).split("\n");
1191
+ const lines = normalizeEol$1(content).split("\n");
1187
1192
  const preamble = [];
1188
1193
  const sections = [];
1189
1194
  let current;
@@ -1209,8 +1214,8 @@ function parseMarkdownByH2(content) {
1209
1214
  };
1210
1215
  }
1211
1216
  function mergePlainText(source, target) {
1212
- const sourceLines = trimEdgeEmptyLines(normalizeEol(source).split("\n"));
1213
- const result = trimEdgeEmptyLines(normalizeEol(target).split("\n"));
1217
+ const sourceLines = trimEdgeEmptyLines(normalizeEol$1(source).split("\n"));
1218
+ const result = trimEdgeEmptyLines(normalizeEol$1(target).split("\n"));
1214
1219
  const seen = new Set(result);
1215
1220
  for (const line of sourceLines) {
1216
1221
  if (!line.trim()) continue;
@@ -1220,6 +1225,9 @@ function mergePlainText(source, target) {
1220
1225
  }
1221
1226
  return `${result.join("\n")}\n`;
1222
1227
  }
1228
+ function getSectionSignature(section) {
1229
+ return `${section.key}\n${trimEdgeEmptyLines(section.lines).join("\n")}`;
1230
+ }
1223
1231
  /**
1224
1232
  * Merge AGENTS instructions by keeping existing sections and filling missing sections
1225
1233
  * from source defaults. This avoids destructive overwrite while still syncing updates.
@@ -1232,13 +1240,25 @@ function mergeAgentsMarkdown(source, target) {
1232
1240
  const targetSectionMap = new Map(targetParsed.sections.map((section) => [section.key, section]));
1233
1241
  const mergedSections = [];
1234
1242
  for (const section of sourceParsed.sections) mergedSections.push(targetSectionMap.get(section.key) ?? section);
1235
- for (const section of targetParsed.sections) if (!sourceSectionKeys.has(section.key)) mergedSections.push(section);
1243
+ const seenTargetOnlySectionSignatures = /* @__PURE__ */ new Set();
1244
+ for (const section of targetParsed.sections) if (!sourceSectionKeys.has(section.key)) {
1245
+ const signature = getSectionSignature(section);
1246
+ if (seenTargetOnlySectionSignatures.has(signature)) continue;
1247
+ seenTargetOnlySectionSignatures.add(signature);
1248
+ mergedSections.push(section);
1249
+ }
1236
1250
  const preamble = trimEdgeEmptyLines(targetParsed.preamble.length ? targetParsed.preamble : sourceParsed.preamble);
1237
1251
  const blocks = [];
1238
1252
  if (preamble.length) blocks.push(preamble.join("\n"));
1239
1253
  for (const section of mergedSections) blocks.push(trimEdgeEmptyLines(section.lines).join("\n"));
1240
1254
  return `${blocks.filter(Boolean).join("\n\n")}\n`;
1241
1255
  }
1256
+ /**
1257
+ * Compare AGENTS markdown with normalized EOL and trailing newline differences ignored.
1258
+ */
1259
+ function isAgentsMarkdownEquivalent(left, right) {
1260
+ return normalizeComparableContent(left) === normalizeComparableContent(right);
1261
+ }
1242
1262
 
1243
1263
  //#endregion
1244
1264
  //#region src/commands/upgrade/overwrite.ts
@@ -1441,6 +1461,35 @@ function mergeWorkspaceManifest(source, target) {
1441
1461
 
1442
1462
  //#endregion
1443
1463
  //#region src/commands/upgrade/index.ts
1464
+ function normalizeEol(input) {
1465
+ return input.replace(/\r\n/g, "\n");
1466
+ }
1467
+ function normalizeGitignoreLine(line) {
1468
+ const trimmed = line.trim();
1469
+ if (!trimmed) return "";
1470
+ if (trimmed.startsWith("#")) return `#${trimmed.slice(1).trim()}`;
1471
+ return trimmed;
1472
+ }
1473
+ function isTextEquivalent(left, right) {
1474
+ return normalizeEol(left).trimEnd() === normalizeEol(right).trimEnd();
1475
+ }
1476
+ function mergeGitignore(source, target) {
1477
+ const sourceLines = normalizeEol(source).split("\n");
1478
+ const result = normalizeEol(target).split("\n");
1479
+ const seen = new Set(result.map((line) => normalizeGitignoreLine(line)).filter(Boolean));
1480
+ for (const line of sourceLines) {
1481
+ const normalized = normalizeGitignoreLine(line);
1482
+ if (!normalized || seen.has(normalized)) continue;
1483
+ seen.add(normalized);
1484
+ result.push(line);
1485
+ }
1486
+ while (result.length) {
1487
+ const last = result.at(-1);
1488
+ if (last === void 0 || last.trim().length > 0) break;
1489
+ result.pop();
1490
+ }
1491
+ return `${result.join("\n")}\n`;
1492
+ }
1444
1493
  /**
1445
1494
  * 将 assets 目录的模版文件同步到工程中,实现一键升级脚手架能力。
1446
1495
  */
@@ -1531,11 +1580,31 @@ async function upgradeMonorepo(opts) {
1531
1580
  });
1532
1581
  continue;
1533
1582
  }
1583
+ if (relPath === ".gitignore") {
1584
+ const source = await fs.readFile(file.path, "utf8");
1585
+ const exists = await fs.pathExists(targetPath);
1586
+ const target = exists ? await fs.readFile(targetPath, "utf8") : "";
1587
+ const data = exists ? mergeGitignore(source, target) : source;
1588
+ if (exists && isTextEquivalent(target, data)) continue;
1589
+ const intent = await evaluateWriteIntent(targetPath, buildWriteIntentOptions(data));
1590
+ const action = async () => {
1591
+ await fs.outputFile(targetPath, data, "utf8");
1592
+ logger.success(targetPath);
1593
+ };
1594
+ await scheduleOverwrite(intent, {
1595
+ relPath,
1596
+ targetPath,
1597
+ action,
1598
+ pending: pendingOverwrites
1599
+ });
1600
+ continue;
1601
+ }
1534
1602
  if (relPath === "AGENTS.md") {
1535
1603
  const source = await fs.readFile(file.path, "utf8");
1536
1604
  const exists = await fs.pathExists(targetPath);
1537
1605
  const target = exists ? await fs.readFile(targetPath, "utf8") : "";
1538
1606
  const data = exists ? mergeAgentsMarkdown(source, target) : source;
1607
+ if (exists && isAgentsMarkdownEquivalent(target, data)) continue;
1539
1608
  const intent = await evaluateWriteIntent(targetPath, buildWriteIntentOptions(data));
1540
1609
  const action = async () => {
1541
1610
  await fs.outputFile(targetPath, data, "utf8");
@@ -570,7 +570,7 @@ async function resolveCommandConfig(name, cwd) {
570
570
  //#endregion
571
571
  //#region package.json
572
572
  var name = "@icebreakers/monorepo";
573
- var version = "3.2.11";
573
+ var version = "3.2.13";
574
574
 
575
575
  //#endregion
576
576
  //#region src/constants.ts
@@ -675,11 +675,13 @@ async function cleanProjects(cwd, overrides) {
675
675
  });
676
676
  const readmeZh = pathe.default.resolve(workspaceDir, "README.zh-CN.md");
677
677
  const qoderDir = pathe.default.resolve(workspaceDir, ".qoder");
678
+ const docsPlansDir = pathe.default.resolve(workspaceDir, "docs/plans");
678
679
  const skillTargets = Object.values(getSkillTargetPaths());
679
680
  const candidates = Array.from(new Set([
680
681
  ...cleanDirs.filter(Boolean),
681
682
  readmeZh,
682
683
  qoderDir,
684
+ docsPlansDir,
683
685
  ...skillTargets
684
686
  ]));
685
687
  await Promise.all(candidates.map(async (dir) => {
@@ -1173,9 +1175,12 @@ async function syncNpmMirror(cwd, options) {
1173
1175
 
1174
1176
  //#endregion
1175
1177
  //#region src/commands/upgrade/agents.ts
1176
- function normalizeEol(input) {
1178
+ function normalizeEol$1(input) {
1177
1179
  return input.replace(/\r\n/g, "\n");
1178
1180
  }
1181
+ function normalizeComparableContent(input) {
1182
+ return normalizeEol$1(input).trimEnd();
1183
+ }
1179
1184
  function normalizeHeadingKey(line) {
1180
1185
  return line.replace(/^##\s+/, "").trim().toLowerCase();
1181
1186
  }
@@ -1194,7 +1199,7 @@ function trimEdgeEmptyLines(lines) {
1194
1199
  return next;
1195
1200
  }
1196
1201
  function parseMarkdownByH2(content) {
1197
- const lines = normalizeEol(content).split("\n");
1202
+ const lines = normalizeEol$1(content).split("\n");
1198
1203
  const preamble = [];
1199
1204
  const sections = [];
1200
1205
  let current;
@@ -1220,8 +1225,8 @@ function parseMarkdownByH2(content) {
1220
1225
  };
1221
1226
  }
1222
1227
  function mergePlainText(source, target) {
1223
- const sourceLines = trimEdgeEmptyLines(normalizeEol(source).split("\n"));
1224
- const result = trimEdgeEmptyLines(normalizeEol(target).split("\n"));
1228
+ const sourceLines = trimEdgeEmptyLines(normalizeEol$1(source).split("\n"));
1229
+ const result = trimEdgeEmptyLines(normalizeEol$1(target).split("\n"));
1225
1230
  const seen = new Set(result);
1226
1231
  for (const line of sourceLines) {
1227
1232
  if (!line.trim()) continue;
@@ -1231,6 +1236,9 @@ function mergePlainText(source, target) {
1231
1236
  }
1232
1237
  return `${result.join("\n")}\n`;
1233
1238
  }
1239
+ function getSectionSignature(section) {
1240
+ return `${section.key}\n${trimEdgeEmptyLines(section.lines).join("\n")}`;
1241
+ }
1234
1242
  /**
1235
1243
  * Merge AGENTS instructions by keeping existing sections and filling missing sections
1236
1244
  * from source defaults. This avoids destructive overwrite while still syncing updates.
@@ -1243,13 +1251,25 @@ function mergeAgentsMarkdown(source, target) {
1243
1251
  const targetSectionMap = new Map(targetParsed.sections.map((section) => [section.key, section]));
1244
1252
  const mergedSections = [];
1245
1253
  for (const section of sourceParsed.sections) mergedSections.push(targetSectionMap.get(section.key) ?? section);
1246
- for (const section of targetParsed.sections) if (!sourceSectionKeys.has(section.key)) mergedSections.push(section);
1254
+ const seenTargetOnlySectionSignatures = /* @__PURE__ */ new Set();
1255
+ for (const section of targetParsed.sections) if (!sourceSectionKeys.has(section.key)) {
1256
+ const signature = getSectionSignature(section);
1257
+ if (seenTargetOnlySectionSignatures.has(signature)) continue;
1258
+ seenTargetOnlySectionSignatures.add(signature);
1259
+ mergedSections.push(section);
1260
+ }
1247
1261
  const preamble = trimEdgeEmptyLines(targetParsed.preamble.length ? targetParsed.preamble : sourceParsed.preamble);
1248
1262
  const blocks = [];
1249
1263
  if (preamble.length) blocks.push(preamble.join("\n"));
1250
1264
  for (const section of mergedSections) blocks.push(trimEdgeEmptyLines(section.lines).join("\n"));
1251
1265
  return `${blocks.filter(Boolean).join("\n\n")}\n`;
1252
1266
  }
1267
+ /**
1268
+ * Compare AGENTS markdown with normalized EOL and trailing newline differences ignored.
1269
+ */
1270
+ function isAgentsMarkdownEquivalent(left, right) {
1271
+ return normalizeComparableContent(left) === normalizeComparableContent(right);
1272
+ }
1253
1273
 
1254
1274
  //#endregion
1255
1275
  //#region src/commands/upgrade/overwrite.ts
@@ -1452,6 +1472,35 @@ function mergeWorkspaceManifest(source, target) {
1452
1472
 
1453
1473
  //#endregion
1454
1474
  //#region src/commands/upgrade/index.ts
1475
+ function normalizeEol(input) {
1476
+ return input.replace(/\r\n/g, "\n");
1477
+ }
1478
+ function normalizeGitignoreLine(line) {
1479
+ const trimmed = line.trim();
1480
+ if (!trimmed) return "";
1481
+ if (trimmed.startsWith("#")) return `#${trimmed.slice(1).trim()}`;
1482
+ return trimmed;
1483
+ }
1484
+ function isTextEquivalent(left, right) {
1485
+ return normalizeEol(left).trimEnd() === normalizeEol(right).trimEnd();
1486
+ }
1487
+ function mergeGitignore(source, target) {
1488
+ const sourceLines = normalizeEol(source).split("\n");
1489
+ const result = normalizeEol(target).split("\n");
1490
+ const seen = new Set(result.map((line) => normalizeGitignoreLine(line)).filter(Boolean));
1491
+ for (const line of sourceLines) {
1492
+ const normalized = normalizeGitignoreLine(line);
1493
+ if (!normalized || seen.has(normalized)) continue;
1494
+ seen.add(normalized);
1495
+ result.push(line);
1496
+ }
1497
+ while (result.length) {
1498
+ const last = result.at(-1);
1499
+ if (last === void 0 || last.trim().length > 0) break;
1500
+ result.pop();
1501
+ }
1502
+ return `${result.join("\n")}\n`;
1503
+ }
1455
1504
  /**
1456
1505
  * 将 assets 目录的模版文件同步到工程中,实现一键升级脚手架能力。
1457
1506
  */
@@ -1542,11 +1591,31 @@ async function upgradeMonorepo(opts) {
1542
1591
  });
1543
1592
  continue;
1544
1593
  }
1594
+ if (relPath === ".gitignore") {
1595
+ const source = await fs_extra.default.readFile(file.path, "utf8");
1596
+ const exists = await fs_extra.default.pathExists(targetPath);
1597
+ const target = exists ? await fs_extra.default.readFile(targetPath, "utf8") : "";
1598
+ const data = exists ? mergeGitignore(source, target) : source;
1599
+ if (exists && isTextEquivalent(target, data)) continue;
1600
+ const intent = await evaluateWriteIntent(targetPath, buildWriteIntentOptions(data));
1601
+ const action = async () => {
1602
+ await fs_extra.default.outputFile(targetPath, data, "utf8");
1603
+ logger.success(targetPath);
1604
+ };
1605
+ await scheduleOverwrite(intent, {
1606
+ relPath,
1607
+ targetPath,
1608
+ action,
1609
+ pending: pendingOverwrites
1610
+ });
1611
+ continue;
1612
+ }
1545
1613
  if (relPath === "AGENTS.md") {
1546
1614
  const source = await fs_extra.default.readFile(file.path, "utf8");
1547
1615
  const exists = await fs_extra.default.pathExists(targetPath);
1548
1616
  const target = exists ? await fs_extra.default.readFile(targetPath, "utf8") : "";
1549
1617
  const data = exists ? mergeAgentsMarkdown(source, target) : source;
1618
+ if (exists && isAgentsMarkdownEquivalent(target, data)) continue;
1550
1619
  const intent = await evaluateWriteIntent(targetPath, buildWriteIntentOptions(data));
1551
1620
  const action = async () => {
1552
1621
  await fs_extra.default.outputFile(targetPath, data, "utf8");
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@icebreakers/monorepo",
3
3
  "type": "module",
4
- "version": "3.2.11",
4
+ "version": "3.2.13",
5
5
  "description": "The icebreaker's monorepo manager",
6
6
  "author": "ice breaker <hi@sonofmagic.top>",
7
7
  "license": "MIT",
@@ -64,7 +64,7 @@
64
64
  "@pnpm/workspace.find-packages": "^1000.0.62",
65
65
  "@pnpm/workspace.read-manifest": "^1000.2.10",
66
66
  "c12": "^3.3.3",
67
- "comment-json": "^4.5.1",
67
+ "comment-json": "^4.6.1",
68
68
  "consola": "^3.4.2",
69
69
  "fs-extra": "^11.3.3",
70
70
  "git-url-parse": "^16.1.0",
@@ -73,7 +73,7 @@
73
73
  "pathe": "^2.0.3",
74
74
  "picocolors": "^1.1.1",
75
75
  "semver": "^7.7.4",
76
- "simple-git": "^3.32.2",
76
+ "simple-git": "^3.32.3",
77
77
  "yaml": "^2.8.2",
78
78
  "@icebreakers/monorepo-templates": "0.1.11"
79
79
  },