package-versioner 0.8.2 → 0.8.4

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/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  // src/index.ts
4
4
  import * as fs10 from "fs";
5
- import path8 from "path";
5
+ import path9 from "path";
6
6
  import { Command } from "commander";
7
7
 
8
8
  // src/changelog/changelogRegenerator.ts
@@ -126,7 +126,8 @@ function extractChangelogEntriesFromCommits(projectDir, revisionRange) {
126
126
  }
127
127
  }
128
128
  function parseCommitMessage(message) {
129
- const match = message.match(CONVENTIONAL_COMMIT_REGEX);
129
+ const trimmedMessage = message.trim();
130
+ const match = trimmedMessage.match(CONVENTIONAL_COMMIT_REGEX);
130
131
  if (match) {
131
132
  const [, type, scope, breakingMark, subject, body = ""] = match;
132
133
  const breakingFromMark = breakingMark === "!";
@@ -150,8 +151,8 @@ function parseCommitMessage(message) {
150
151
  // Store original type for custom formatting
151
152
  };
152
153
  }
153
- if (!message.startsWith("Merge") && !message.match(/^v?\d+\.\d+\.\d+/)) {
154
- const firstLine = message.split("\n")[0].trim();
154
+ if (!trimmedMessage.startsWith("Merge") && !trimmedMessage.match(/^v?\d+\.\d+\.\d+/)) {
155
+ const firstLine = trimmedMessage.split("\n")[0].trim();
155
156
  return {
156
157
  type: "changed",
157
158
  description: firstLine
@@ -199,7 +200,9 @@ function formatChangelogEntries(format, version, date, entries, packageName, rep
199
200
  const hasBreaking = entry.description.includes("**BREAKING**");
200
201
  return {
201
202
  ...entry,
202
- breaking: hasBreaking
203
+ breaking: hasBreaking,
204
+ // Clean up the description to remove the **BREAKING** prefix since we'll handle it in formatting
205
+ description: hasBreaking ? entry.description.replace("**BREAKING** ", "") : entry.description
203
206
  };
204
207
  });
205
208
  return format === "keep-a-changelog" ? formatKeepAChangelogEntries(version, date, formattingEntries, repoUrl) : formatAngularEntries(version, date, formattingEntries, packageName);
@@ -212,15 +215,19 @@ function formatKeepAChangelogEntries(version, date, entries, repoUrl) {
212
215
  const fixed = [];
213
216
  const security = [];
214
217
  for (const entry of entries) {
215
- const entryText = entry.scope ? `- **${entry.scope}**: ${entry.description}` : `- ${entry.description}`;
216
- const formattedEntry = entry.breaking ? entryText.replace(/^- /, "- **BREAKING** ") : entryText;
218
+ let entryText;
219
+ if (entry.breaking) {
220
+ entryText = entry.scope ? `- **BREAKING** **${entry.scope}**: ${entry.description}` : `- **BREAKING** ${entry.description}`;
221
+ } else {
222
+ entryText = entry.scope ? `- **${entry.scope}**: ${entry.description}` : `- ${entry.description}`;
223
+ }
217
224
  const entryType = entry.originalType || entry.type;
218
225
  switch (entryType) {
219
226
  case "feat":
220
- added.push(formattedEntry);
227
+ added.push(entryText);
221
228
  break;
222
229
  case "fix":
223
- fixed.push(formattedEntry);
230
+ fixed.push(entryText);
224
231
  break;
225
232
  case "docs":
226
233
  case "style":
@@ -228,38 +235,38 @@ function formatKeepAChangelogEntries(version, date, entries, repoUrl) {
228
235
  case "perf":
229
236
  case "build":
230
237
  case "ci":
231
- changed.push(formattedEntry);
238
+ changed.push(entryText);
232
239
  break;
233
240
  case "test":
234
241
  break;
235
242
  case "chore":
236
243
  if (entry.description.toLowerCase().includes("deprecat")) {
237
- deprecated.push(formattedEntry);
244
+ deprecated.push(entryText);
238
245
  } else {
239
- changed.push(formattedEntry);
246
+ changed.push(entryText);
240
247
  }
241
248
  break;
242
249
  // Keep-a-changelog standard types
243
250
  case "added":
244
- added.push(formattedEntry);
251
+ added.push(entryText);
245
252
  break;
246
253
  case "changed":
247
- changed.push(formattedEntry);
254
+ changed.push(entryText);
248
255
  break;
249
256
  case "deprecated":
250
- deprecated.push(formattedEntry);
257
+ deprecated.push(entryText);
251
258
  break;
252
259
  case "removed":
253
- removed.push(formattedEntry);
260
+ removed.push(entryText);
254
261
  break;
255
262
  case "fixed":
256
- fixed.push(formattedEntry);
263
+ fixed.push(entryText);
257
264
  break;
258
265
  case "security":
259
- security.push(formattedEntry);
266
+ security.push(entryText);
260
267
  break;
261
268
  default:
262
- changed.push(formattedEntry);
269
+ changed.push(entryText);
263
270
  }
264
271
  }
265
272
  let content = `## [${version}] - ${date}
@@ -424,13 +431,25 @@ function getAngularTemplate() {
424
431
  // src/changelog/changelogRegenerator.ts
425
432
  function getAllVersionTags(since, versionPrefix = "v") {
426
433
  try {
427
- const command = since ? `git tag --list "${versionPrefix}*" --sort=creatordate --contains ${since}` : `git tag --list "${versionPrefix}*" --sort=creatordate`;
434
+ const command = `git tag --list "${versionPrefix}*" --sort=creatordate`;
428
435
  const tagOutput = execSync2(command, { encoding: "utf8" }).trim();
429
436
  if (!tagOutput) {
430
437
  return [];
431
438
  }
432
- const tags = tagOutput.split("\n").filter((tag) => !!tag);
433
- return tags.map((tag) => {
439
+ const allTags = tagOutput.split("\n").filter((tag) => !!tag);
440
+ let filteredTags = allTags;
441
+ if (since) {
442
+ const sinceIndex = allTags.findIndex((tag) => tag === since);
443
+ if (sinceIndex >= 0) {
444
+ filteredTags = allTags.slice(sinceIndex);
445
+ } else {
446
+ log(
447
+ `Warning: --since tag "${since}" not found in git history, including all tags`,
448
+ "warning"
449
+ );
450
+ }
451
+ }
452
+ return filteredTags.map((tag) => {
434
453
  try {
435
454
  const date = execSync2(`git log -1 --format=%ad --date=short ${tag}`, {
436
455
  encoding: "utf8"
@@ -479,7 +498,10 @@ async function regenerateChangelog(options) {
479
498
  }
480
499
  } catch {
481
500
  }
482
- const tags = getAllVersionTags(since, versionPrefix);
501
+ let tags = getAllVersionTags(since, versionPrefix);
502
+ if (!tags.length && since) {
503
+ tags = getAllVersionTags(void 0, versionPrefix);
504
+ }
483
505
  if (!tags.length) {
484
506
  throw new Error(
485
507
  'No version tags found in git history. Make sure you have tags that start with the version prefix (usually "v").'
@@ -493,7 +515,28 @@ async function regenerateChangelog(options) {
493
515
  const previousTag = i > 0 ? tags[i - 1].tag : null;
494
516
  log(`Processing changes for ${currentTag.tag}...`, "info");
495
517
  try {
496
- const tagRange = previousTag ? `${previousTag}..${currentTag.tag}` : currentTag.tag;
518
+ let tagRange;
519
+ if (previousTag) {
520
+ tagRange = `${previousTag}..${currentTag.tag}`;
521
+ } else if (since && currentTag.tag === since) {
522
+ try {
523
+ const allTagsCmd = `git tag --list "${versionPrefix}*" --sort=creatordate`;
524
+ const allTagsOutput = execSync2(allTagsCmd, { encoding: "utf8" }).trim();
525
+ const allTags = allTagsOutput.split("\n").filter((tag) => !!tag);
526
+ const sinceIndex = allTags.findIndex((tag) => tag === since);
527
+ const actualPreviousTag = sinceIndex > 0 ? allTags[sinceIndex - 1] : null;
528
+ if (actualPreviousTag) {
529
+ tagRange = `${actualPreviousTag}..${currentTag.tag}`;
530
+ } else {
531
+ tagRange = currentTag.tag;
532
+ }
533
+ } catch (error) {
534
+ log(`Failed to find previous tag for ${currentTag.tag}: ${error}`, "warning");
535
+ tagRange = currentTag.tag;
536
+ }
537
+ } else {
538
+ tagRange = currentTag.tag;
539
+ }
497
540
  const entries = extractChangelogEntriesFromCommits(projectDir, tagRange);
498
541
  if (!entries.length) {
499
542
  log(`No changelog entries found for ${currentTag.tag}, adding placeholder entry`, "info");
@@ -606,33 +649,163 @@ function createVersionError(code, details) {
606
649
  return new VersionError(fullMessage, code);
607
650
  }
608
651
 
609
- // src/utils/packageMatching.ts
610
- function matchesPackageTarget(packageName, target) {
611
- if (packageName === target) {
652
+ // src/utils/packageFiltering.ts
653
+ import path2 from "path";
654
+ import micromatch from "micromatch";
655
+ function filterPackagesByConfig(packages, configTargets, workspaceRoot) {
656
+ if (configTargets.length === 0) {
657
+ log("No config targets specified, returning all packages", "debug");
658
+ return packages;
659
+ }
660
+ const matchedPackages = /* @__PURE__ */ new Set();
661
+ for (const target of configTargets) {
662
+ const dirMatches = filterByDirectoryPattern(packages, target, workspaceRoot);
663
+ const nameMatches = filterByPackageNamePattern(packages, target);
664
+ dirMatches.forEach((pkg) => matchedPackages.add(pkg));
665
+ nameMatches.forEach((pkg) => matchedPackages.add(pkg));
666
+ }
667
+ return Array.from(matchedPackages);
668
+ }
669
+ function filterByDirectoryPattern(packages, pattern, workspaceRoot) {
670
+ if (pattern === "./" || pattern === ".") {
671
+ return packages.filter((pkg) => pkg.dir === workspaceRoot);
672
+ }
673
+ const normalizedPattern = pattern.replace(/\\/g, "/");
674
+ return packages.filter((pkg) => {
675
+ const relativePath = path2.relative(workspaceRoot, pkg.dir);
676
+ const normalizedRelativePath = relativePath.replace(/\\/g, "/");
677
+ if (normalizedPattern === normalizedRelativePath) {
678
+ return true;
679
+ }
680
+ try {
681
+ return micromatch.isMatch(normalizedRelativePath, normalizedPattern, {
682
+ dot: true,
683
+ noglobstar: false,
684
+ bash: true
685
+ });
686
+ } catch (error) {
687
+ log(
688
+ `Invalid directory pattern "${pattern}": ${error instanceof Error ? error.message : String(error)}`,
689
+ "warning"
690
+ );
691
+ return false;
692
+ }
693
+ });
694
+ }
695
+ function filterByPackageNamePattern(packages, pattern) {
696
+ return packages.filter((pkg) => {
697
+ var _a;
698
+ if (!((_a = pkg.packageJson) == null ? void 0 : _a.name) || typeof pkg.packageJson.name !== "string") {
699
+ return false;
700
+ }
701
+ return matchesPackageNamePattern(pkg.packageJson.name, pattern);
702
+ });
703
+ }
704
+ function matchesPackageNamePattern(packageName, pattern) {
705
+ if (packageName === pattern) {
612
706
  return true;
613
707
  }
614
- if (target.endsWith("/*")) {
615
- const scope = target.slice(0, -2);
616
- if (scope.startsWith("@")) {
617
- return packageName.startsWith(`${scope}/`);
618
- }
708
+ if (pattern.startsWith("@") && pattern.endsWith("/*") && !pattern.includes("**")) {
709
+ const scope = pattern.slice(0, -2);
619
710
  return packageName.startsWith(`${scope}/`);
620
711
  }
621
- if (target === "*") {
622
- return true;
712
+ try {
713
+ return micromatch.isMatch(packageName, pattern, {
714
+ dot: true,
715
+ contains: false,
716
+ noglobstar: false,
717
+ bash: true
718
+ });
719
+ } catch (error) {
720
+ log(
721
+ `Invalid package name pattern "${pattern}": ${error instanceof Error ? error.message : String(error)}`,
722
+ "warning"
723
+ );
724
+ return false;
623
725
  }
624
- return false;
625
- }
626
- function shouldMatchPackageTargets(packageName, targets) {
627
- return targets.some((target) => matchesPackageTarget(packageName, target));
628
- }
629
- function shouldProcessPackage(packageName, skip = []) {
630
- return !skip.includes(packageName);
631
726
  }
632
727
 
633
728
  // src/core/versionStrategies.ts
729
+ import { execSync as execSync5 } from "child_process";
634
730
  import fs9 from "fs";
635
- import * as path7 from "path";
731
+ import * as path8 from "path";
732
+
733
+ // src/changelog/changelogManager.ts
734
+ import * as fs3 from "fs";
735
+ import * as path3 from "path";
736
+ function updateChangelog(packagePath, packageName, version, entries, repoUrl, format = "keep-a-changelog") {
737
+ try {
738
+ const changelogPath = path3.join(packagePath, "CHANGELOG.md");
739
+ let existingContent = "";
740
+ if (fs3.existsSync(changelogPath)) {
741
+ existingContent = fs3.readFileSync(changelogPath, "utf8");
742
+ }
743
+ const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
744
+ const newVersionContent = formatChangelogEntries(
745
+ format,
746
+ version,
747
+ today,
748
+ entries,
749
+ packageName,
750
+ repoUrl
751
+ );
752
+ let finalContent;
753
+ if (existingContent) {
754
+ if (format === "keep-a-changelog") {
755
+ const headerEndIndex = existingContent.indexOf("\n## ");
756
+ if (headerEndIndex > 0) {
757
+ const beforeVersions = existingContent.substring(0, headerEndIndex);
758
+ const afterVersions = existingContent.substring(headerEndIndex);
759
+ finalContent = `${beforeVersions}
760
+ ${newVersionContent}
761
+ ${afterVersions}`;
762
+ } else {
763
+ finalContent = `${existingContent}
764
+ ${newVersionContent}
765
+ `;
766
+ }
767
+ } else {
768
+ const headerEndIndex = existingContent.indexOf("\n## ");
769
+ if (headerEndIndex > 0) {
770
+ const beforeVersions = existingContent.substring(0, headerEndIndex);
771
+ const afterVersions = existingContent.substring(headerEndIndex);
772
+ finalContent = `${beforeVersions}
773
+ ${newVersionContent}
774
+ ${afterVersions}`;
775
+ } else {
776
+ finalContent = `${existingContent}
777
+ ${newVersionContent}
778
+ `;
779
+ }
780
+ }
781
+ } else {
782
+ if (format === "keep-a-changelog") {
783
+ finalContent = `# Changelog
784
+
785
+ All notable changes to ${packageName} will be documented in this file.
786
+
787
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
788
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
789
+
790
+ ${newVersionContent}
791
+ `;
792
+ } else {
793
+ finalContent = `# Changelog
794
+
795
+ ${newVersionContent}
796
+ `;
797
+ }
798
+ }
799
+ log(`Writing changelog to: ${changelogPath}`, "info");
800
+ fs3.writeFileSync(changelogPath, finalContent);
801
+ log(`Updated changelog at ${changelogPath}`, "success");
802
+ } catch (error) {
803
+ log(
804
+ `Error updating changelog: ${error instanceof Error ? error.message : String(error)}`,
805
+ "error"
806
+ );
807
+ }
808
+ }
636
809
 
637
810
  // src/git/commands.ts
638
811
  import { cwd as cwd2 } from "process";
@@ -658,11 +831,11 @@ var execAsync = (command, options) => {
658
831
  var execSync3 = (command, args) => nativeExecSync(command, { maxBuffer: 1024 * 1024 * 10, ...args });
659
832
 
660
833
  // src/git/repository.ts
661
- import { existsSync, statSync } from "fs";
662
- import { join } from "path";
834
+ import { existsSync as existsSync2, statSync } from "fs";
835
+ import { join as join2 } from "path";
663
836
  function isGitRepository(directory) {
664
- const gitDir = join(directory, ".git");
665
- if (!existsSync(gitDir)) {
837
+ const gitDir = join2(directory, ".git");
838
+ if (!existsSync2(gitDir)) {
666
839
  return false;
667
840
  }
668
841
  const stats = statSync(gitDir);
@@ -1020,21 +1193,21 @@ async function getLatestTagForPackage(packageName, versionPrefix, options) {
1020
1193
  }
1021
1194
 
1022
1195
  // src/package/packageManagement.ts
1023
- import fs4 from "fs";
1024
- import path3 from "path";
1196
+ import fs5 from "fs";
1197
+ import path5 from "path";
1025
1198
 
1026
1199
  // src/cargo/cargoHandler.ts
1027
- import fs3 from "fs";
1028
- import path2 from "path";
1200
+ import fs4 from "fs";
1201
+ import path4 from "path";
1029
1202
  import * as TOML from "smol-toml";
1030
1203
  function getCargoInfo(cargoPath) {
1031
1204
  var _a;
1032
- if (!fs3.existsSync(cargoPath)) {
1205
+ if (!fs4.existsSync(cargoPath)) {
1033
1206
  log(`Cargo.toml file not found at: ${cargoPath}`, "error");
1034
1207
  throw new Error(`Cargo.toml file not found at: ${cargoPath}`);
1035
1208
  }
1036
1209
  try {
1037
- const fileContent = fs3.readFileSync(cargoPath, "utf8");
1210
+ const fileContent = fs4.readFileSync(cargoPath, "utf8");
1038
1211
  const cargo = TOML.parse(fileContent);
1039
1212
  if (!((_a = cargo.package) == null ? void 0 : _a.name)) {
1040
1213
  log(`Package name not found in: ${cargoPath}`, "error");
@@ -1044,7 +1217,7 @@ function getCargoInfo(cargoPath) {
1044
1217
  name: cargo.package.name,
1045
1218
  version: cargo.package.version || "0.0.0",
1046
1219
  path: cargoPath,
1047
- dir: path2.dirname(cargoPath),
1220
+ dir: path4.dirname(cargoPath),
1048
1221
  content: cargo
1049
1222
  };
1050
1223
  } catch (error) {
@@ -1057,12 +1230,12 @@ function getCargoInfo(cargoPath) {
1057
1230
  }
1058
1231
  }
1059
1232
  function isCargoToml(filePath) {
1060
- return path2.basename(filePath) === "Cargo.toml";
1233
+ return path4.basename(filePath) === "Cargo.toml";
1061
1234
  }
1062
1235
  function updateCargoVersion(cargoPath, version) {
1063
1236
  var _a;
1064
1237
  try {
1065
- const originalContent = fs3.readFileSync(cargoPath, "utf8");
1238
+ const originalContent = fs4.readFileSync(cargoPath, "utf8");
1066
1239
  const cargo = TOML.parse(originalContent);
1067
1240
  const packageName = (_a = cargo.package) == null ? void 0 : _a.name;
1068
1241
  if (!packageName) {
@@ -1074,7 +1247,7 @@ function updateCargoVersion(cargoPath, version) {
1074
1247
  cargo.package.version = version;
1075
1248
  }
1076
1249
  const updatedContent = TOML.stringify(cargo);
1077
- fs3.writeFileSync(cargoPath, updatedContent);
1250
+ fs4.writeFileSync(cargoPath, updatedContent);
1078
1251
  addPackageUpdate(packageName, version, cargoPath);
1079
1252
  log(`Updated Cargo.toml at ${cargoPath} to version ${version}`, "success");
1080
1253
  } catch (error) {
@@ -1093,11 +1266,11 @@ function updatePackageVersion(packagePath, version) {
1093
1266
  return;
1094
1267
  }
1095
1268
  try {
1096
- const packageContent = fs4.readFileSync(packagePath, "utf8");
1269
+ const packageContent = fs5.readFileSync(packagePath, "utf8");
1097
1270
  const packageJson = JSON.parse(packageContent);
1098
1271
  const packageName = packageJson.name;
1099
1272
  packageJson.version = version;
1100
- fs4.writeFileSync(packagePath, `${JSON.stringify(packageJson, null, 2)}
1273
+ fs5.writeFileSync(packagePath, `${JSON.stringify(packageJson, null, 2)}
1101
1274
  `);
1102
1275
  addPackageUpdate(packageName, version, packagePath);
1103
1276
  log(`Updated package.json at ${packagePath} to version ${version}`, "success");
@@ -1113,334 +1286,9 @@ function updatePackageVersion(packagePath, version) {
1113
1286
  // src/package/packageProcessor.ts
1114
1287
  import { execSync as execSync4 } from "child_process";
1115
1288
  import * as fs8 from "fs";
1116
- import path6 from "path";
1289
+ import path7 from "path";
1117
1290
  import { exit } from "process";
1118
1291
 
1119
- // src/changelog/changelogManager.ts
1120
- import * as fs5 from "fs";
1121
- import * as path4 from "path";
1122
- function createChangelog(_packagePath, packageName) {
1123
- return {
1124
- projectName: packageName,
1125
- unreleased: [],
1126
- versions: []
1127
- };
1128
- }
1129
- function parseChangelog(filePath) {
1130
- try {
1131
- if (!fs5.existsSync(filePath)) {
1132
- return null;
1133
- }
1134
- fs5.readFileSync(filePath, "utf8");
1135
- log(`Parsed changelog at ${filePath}`, "info");
1136
- return {
1137
- projectName: path4.basename(path4.dirname(filePath)),
1138
- unreleased: [],
1139
- versions: []
1140
- };
1141
- } catch (error) {
1142
- log(
1143
- `Error parsing changelog: ${error instanceof Error ? error.message : String(error)}`,
1144
- "error"
1145
- );
1146
- return null;
1147
- }
1148
- }
1149
- function generateLinks(changelog, repoUrl) {
1150
- var _a, _b;
1151
- if (!repoUrl || changelog.versions.length === 0) {
1152
- return "";
1153
- }
1154
- let links = "\n";
1155
- if (changelog.unreleased.length > 0) {
1156
- const latestVersion = ((_a = changelog.versions[0]) == null ? void 0 : _a.version) || "";
1157
- links += `[unreleased]: ${repoUrl}/compare/v${latestVersion}...HEAD
1158
- `;
1159
- }
1160
- for (let i = 0; i < changelog.versions.length; i++) {
1161
- const currentVersion = changelog.versions[i].version;
1162
- const previousVersion = (_b = changelog.versions[i + 1]) == null ? void 0 : _b.version;
1163
- if (previousVersion) {
1164
- links += `[${currentVersion}]: ${repoUrl}/compare/v${previousVersion}...v${currentVersion}
1165
- `;
1166
- } else if (i === changelog.versions.length - 1) {
1167
- links += `[${currentVersion}]: ${repoUrl}/releases/tag/v${currentVersion}
1168
- `;
1169
- }
1170
- }
1171
- return links;
1172
- }
1173
- function generateAngularChangelogContent(changelog, repoUrl) {
1174
- let content = "# Changelog\n\n";
1175
- if (changelog.unreleased.length > 0) {
1176
- content += "## [Unreleased]\n\n";
1177
- const groupedByType = groupEntriesByAngularType(changelog.unreleased);
1178
- for (const [type, entries] of Object.entries(groupedByType)) {
1179
- content += `### ${formatAngularType(type)}
1180
-
1181
- `;
1182
- const groupedByScope = groupEntriesByScope2(entries);
1183
- for (const [scope, scopeEntries] of Object.entries(groupedByScope)) {
1184
- if (scope !== "undefined" && scope !== "") {
1185
- content += `* **${scope}:**
1186
- `;
1187
- for (const entry of scopeEntries) {
1188
- content += formatAngularEntry(entry, false);
1189
- }
1190
- content += "\n";
1191
- } else {
1192
- for (const entry of scopeEntries) {
1193
- content += formatAngularEntry(entry, true);
1194
- }
1195
- }
1196
- }
1197
- content += "\n";
1198
- }
1199
- const breakingChanges = changelog.unreleased.filter(
1200
- (entry) => entry.description.includes("**BREAKING**")
1201
- );
1202
- if (breakingChanges.length > 0) {
1203
- content += "### BREAKING CHANGES\n\n";
1204
- for (const entry of breakingChanges) {
1205
- const description = entry.description.replace("**BREAKING** ", "");
1206
- content += `* ${entry.scope ? `**${entry.scope}:** ` : ""}${description}`;
1207
- if (entry.issueIds && entry.issueIds.length > 0) {
1208
- content += ` (${entry.issueIds.join(", ")})`;
1209
- }
1210
- content += "\n";
1211
- }
1212
- content += "\n";
1213
- }
1214
- }
1215
- for (const version of changelog.versions) {
1216
- content += `## [${version.version}] - ${version.date}
1217
-
1218
- `;
1219
- const groupedByType = groupEntriesByAngularType(version.entries);
1220
- for (const [type, entries] of Object.entries(groupedByType)) {
1221
- content += `### ${formatAngularType(type)}
1222
-
1223
- `;
1224
- const groupedByScope = groupEntriesByScope2(entries);
1225
- for (const [scope, scopeEntries] of Object.entries(groupedByScope)) {
1226
- if (scope !== "undefined" && scope !== "") {
1227
- content += `* **${scope}:**
1228
- `;
1229
- for (const entry of scopeEntries) {
1230
- content += formatAngularEntry(entry, false);
1231
- }
1232
- content += "\n";
1233
- } else {
1234
- for (const entry of scopeEntries) {
1235
- content += formatAngularEntry(entry, true);
1236
- }
1237
- }
1238
- }
1239
- content += "\n";
1240
- }
1241
- const breakingChanges = version.entries.filter(
1242
- (entry) => entry.description.includes("**BREAKING**")
1243
- );
1244
- if (breakingChanges.length > 0) {
1245
- content += "### BREAKING CHANGES\n\n";
1246
- for (const entry of breakingChanges) {
1247
- const description = entry.description.replace("**BREAKING** ", "");
1248
- content += `* ${entry.scope ? `**${entry.scope}:** ` : ""}${description}`;
1249
- if (entry.issueIds && entry.issueIds.length > 0) {
1250
- content += ` (${entry.issueIds.join(", ")})`;
1251
- }
1252
- content += "\n";
1253
- }
1254
- content += "\n";
1255
- }
1256
- }
1257
- content += generateLinks(changelog, repoUrl);
1258
- return content;
1259
- }
1260
- function groupEntriesByAngularType(entries) {
1261
- const result = {};
1262
- for (const entry of entries) {
1263
- const type = entry.originalType || mapToAngularType(entry.type);
1264
- if (!result[type]) {
1265
- result[type] = [];
1266
- }
1267
- result[type].push(entry);
1268
- }
1269
- return result;
1270
- }
1271
- function mapToAngularType(type) {
1272
- switch (type) {
1273
- case "added":
1274
- return "feat";
1275
- case "fixed":
1276
- return "fix";
1277
- case "changed":
1278
- return "perf";
1279
- case "deprecated":
1280
- case "removed":
1281
- case "security":
1282
- return type;
1283
- default:
1284
- return type;
1285
- }
1286
- }
1287
- function formatAngularType(type) {
1288
- switch (type) {
1289
- case "feat":
1290
- return "Features";
1291
- case "fix":
1292
- return "Bug Fixes";
1293
- case "perf":
1294
- return "Performance Improvements";
1295
- case "security":
1296
- return "Security";
1297
- case "deprecated":
1298
- return "Deprecated";
1299
- case "removed":
1300
- return "Removed";
1301
- default:
1302
- return capitalizeFirstLetter(type);
1303
- }
1304
- }
1305
- function groupEntriesByScope2(entries) {
1306
- const result = {};
1307
- for (const entry of entries) {
1308
- const scope = entry.scope || "";
1309
- if (!result[scope]) {
1310
- result[scope] = [];
1311
- }
1312
- result[scope].push(entry);
1313
- }
1314
- return result;
1315
- }
1316
- function formatAngularEntry(entry, includeScope) {
1317
- let result = " * ";
1318
- if (includeScope && entry.scope) {
1319
- result += `**${entry.scope}:** `;
1320
- }
1321
- let description = entry.description;
1322
- if (!includeScope && entry.scope && description.startsWith(`**${entry.scope}**: `)) {
1323
- description = description.substring(`**${entry.scope}**: `.length);
1324
- }
1325
- if (description.startsWith("**BREAKING** ")) {
1326
- description = description.substring("**BREAKING** ".length);
1327
- }
1328
- result += description;
1329
- if (entry.issueIds && entry.issueIds.length > 0) {
1330
- result += ` (${entry.issueIds.join(", ")})`;
1331
- }
1332
- result += "\n";
1333
- return result;
1334
- }
1335
- function generateChangelogContent(changelog, repoUrl, format = "keep-a-changelog") {
1336
- if (format === "angular") {
1337
- return generateAngularChangelogContent(changelog, repoUrl);
1338
- }
1339
- let content = "# Changelog\n\n";
1340
- content += `All notable changes to ${changelog.projectName} will be documented in this file.
1341
-
1342
- `;
1343
- content += "The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),\n";
1344
- content += "and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n";
1345
- if (changelog.unreleased.length > 0) {
1346
- content += "## [Unreleased]\n\n";
1347
- const grouped = changelog.unreleased.reduce(
1348
- (acc, entry) => {
1349
- if (!acc[entry.type]) {
1350
- acc[entry.type] = [];
1351
- }
1352
- acc[entry.type].push(entry);
1353
- return acc;
1354
- },
1355
- {}
1356
- );
1357
- for (const [type, entries] of Object.entries(grouped)) {
1358
- content += `### ${capitalizeFirstLetter(type)}
1359
-
1360
- `;
1361
- for (const entry of entries) {
1362
- let entryText = `- ${entry.description}`;
1363
- if (entry.issueIds && entry.issueIds.length > 0) {
1364
- entryText += ` (${entry.issueIds.join(", ")})`;
1365
- }
1366
- content += `${entryText}.
1367
- `;
1368
- }
1369
- content += "\n";
1370
- }
1371
- }
1372
- for (const version of changelog.versions) {
1373
- content += `## [${version.version}] - ${version.date}
1374
-
1375
- `;
1376
- const grouped = version.entries.reduce(
1377
- (acc, entry) => {
1378
- if (!acc[entry.type]) {
1379
- acc[entry.type] = [];
1380
- }
1381
- acc[entry.type].push(entry);
1382
- return acc;
1383
- },
1384
- {}
1385
- );
1386
- for (const [type, entries] of Object.entries(grouped)) {
1387
- content += `### ${capitalizeFirstLetter(type)}
1388
-
1389
- `;
1390
- for (const entry of entries) {
1391
- let entryText = `- ${entry.description}`;
1392
- if (entry.issueIds && entry.issueIds.length > 0) {
1393
- entryText += ` (${entry.issueIds.join(", ")})`;
1394
- }
1395
- content += `${entryText}.
1396
- `;
1397
- }
1398
- content += "\n";
1399
- }
1400
- }
1401
- content += generateLinks(changelog, repoUrl);
1402
- return content;
1403
- }
1404
- function updateChangelog(packagePath, packageName, version, entries, repoUrl, format = "keep-a-changelog") {
1405
- try {
1406
- const changelogPath = path4.join(packagePath, "CHANGELOG.md");
1407
- let changelog;
1408
- if (fs5.existsSync(changelogPath)) {
1409
- const existingChangelog = parseChangelog(changelogPath);
1410
- if (existingChangelog) {
1411
- changelog = existingChangelog;
1412
- } else {
1413
- changelog = createChangelog(packagePath, packageName);
1414
- }
1415
- } else {
1416
- changelog = createChangelog(packagePath, packageName);
1417
- }
1418
- if (version) {
1419
- const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
1420
- const newVersion = {
1421
- version,
1422
- date: today,
1423
- entries: [...changelog.unreleased, ...entries]
1424
- };
1425
- changelog.unreleased = [];
1426
- changelog.versions.unshift(newVersion);
1427
- } else {
1428
- changelog.unreleased = [...changelog.unreleased, ...entries];
1429
- }
1430
- const content = generateChangelogContent(changelog, repoUrl, format);
1431
- fs5.writeFileSync(changelogPath, content);
1432
- log(`Updated changelog at ${changelogPath}`, "success");
1433
- } catch (error) {
1434
- log(
1435
- `Error updating changelog: ${error instanceof Error ? error.message : String(error)}`,
1436
- "error"
1437
- );
1438
- }
1439
- }
1440
- function capitalizeFirstLetter(input) {
1441
- return input.charAt(0).toUpperCase() + input.slice(1);
1442
- }
1443
-
1444
1292
  // src/core/versionCalculator.ts
1445
1293
  import { cwd as cwd3 } from "process";
1446
1294
  import { Bumper } from "conventional-recommended-bump";
@@ -1448,10 +1296,10 @@ import semver3 from "semver";
1448
1296
 
1449
1297
  // src/utils/manifestHelpers.ts
1450
1298
  import fs6 from "fs";
1451
- import path5 from "path";
1299
+ import path6 from "path";
1452
1300
  function getVersionFromManifests(packageDir) {
1453
- const packageJsonPath = path5.join(packageDir, "package.json");
1454
- const cargoTomlPath = path5.join(packageDir, "Cargo.toml");
1301
+ const packageJsonPath = path6.join(packageDir, "package.json");
1302
+ const cargoTomlPath = path6.join(packageDir, "Cargo.toml");
1455
1303
  if (fs6.existsSync(packageJsonPath)) {
1456
1304
  try {
1457
1305
  const packageJson = JSON.parse(fs6.readFileSync(packageJsonPath, "utf-8"));
@@ -1496,8 +1344,8 @@ function getVersionFromManifests(packageDir) {
1496
1344
  };
1497
1345
  }
1498
1346
  function throwIfNoManifestsFound(packageDir) {
1499
- const packageJsonPath = path5.join(packageDir, "package.json");
1500
- const cargoTomlPath = path5.join(packageDir, "Cargo.toml");
1347
+ const packageJsonPath = path6.join(packageDir, "package.json");
1348
+ const cargoTomlPath = path6.join(packageDir, "Cargo.toml");
1501
1349
  throw new Error(
1502
1350
  `Neither package.json nor Cargo.toml found at ${packageDir}. Checked paths: ${packageJsonPath}, ${cargoTomlPath}. Cannot determine version.`
1503
1351
  );
@@ -1774,6 +1622,42 @@ function calculateNextVersion(version, manifestType, name, releaseType, prerelea
1774
1622
  return result || initialVersion;
1775
1623
  }
1776
1624
 
1625
+ // src/utils/packageMatching.ts
1626
+ import micromatch2 from "micromatch";
1627
+ function matchesPackageTarget(packageName, target) {
1628
+ if (packageName === target) {
1629
+ return true;
1630
+ }
1631
+ if (target.startsWith("@") && target.endsWith("/*") && !target.includes("**")) {
1632
+ const scope = target.slice(0, -2);
1633
+ return packageName.startsWith(`${scope}/`);
1634
+ }
1635
+ try {
1636
+ return micromatch2.isMatch(packageName, target, {
1637
+ dot: true,
1638
+ contains: false,
1639
+ // Changed to false to ensure full pattern matching
1640
+ noglobstar: false,
1641
+ bash: true
1642
+ });
1643
+ } catch (error) {
1644
+ log(
1645
+ `Invalid pattern "${target}": ${error instanceof Error ? error.message : String(error)}`,
1646
+ "warning"
1647
+ );
1648
+ return false;
1649
+ }
1650
+ }
1651
+ function shouldMatchPackageTargets(packageName, targets) {
1652
+ return targets.some((target) => matchesPackageTarget(packageName, target));
1653
+ }
1654
+ function shouldProcessPackage(packageName, skip = []) {
1655
+ if (skip.length === 0) {
1656
+ return true;
1657
+ }
1658
+ return !shouldMatchPackageTargets(packageName, skip);
1659
+ }
1660
+
1777
1661
  // src/package/packageProcessor.ts
1778
1662
  var PackageProcessor = class {
1779
1663
  skip;
@@ -1884,22 +1768,20 @@ var PackageProcessor = class {
1884
1768
  if (this.fullConfig.updateChangelog !== false) {
1885
1769
  let changelogEntries = [];
1886
1770
  try {
1887
- let revisionRange = latestTag;
1771
+ let revisionRange;
1888
1772
  if (latestTag) {
1889
1773
  try {
1890
1774
  execSync4(`git rev-parse --verify "${latestTag}"`, {
1891
1775
  cwd: pkgPath,
1892
1776
  stdio: "ignore"
1893
1777
  });
1778
+ revisionRange = `${latestTag}..HEAD`;
1894
1779
  } catch {
1895
- log(
1896
- `Tag ${latestTag} doesn't exist, using recent commits from HEAD for changelog`,
1897
- "debug"
1898
- );
1899
- revisionRange = "HEAD~10..HEAD";
1780
+ log(`Tag ${latestTag} doesn't exist, using all commits for changelog`, "debug");
1781
+ revisionRange = "HEAD";
1900
1782
  }
1901
1783
  } else {
1902
- revisionRange = "HEAD~10..HEAD";
1784
+ revisionRange = "HEAD";
1903
1785
  }
1904
1786
  changelogEntries = extractChangelogEntriesFromCommits(pkgPath, revisionRange);
1905
1787
  if (changelogEntries.length === 0) {
@@ -1924,7 +1806,7 @@ var PackageProcessor = class {
1924
1806
  }
1925
1807
  let repoUrl;
1926
1808
  try {
1927
- const packageJsonPath2 = path6.join(pkgPath, "package.json");
1809
+ const packageJsonPath2 = path7.join(pkgPath, "package.json");
1928
1810
  if (fs8.existsSync(packageJsonPath2)) {
1929
1811
  const packageJson = JSON.parse(fs8.readFileSync(packageJsonPath2, "utf8"));
1930
1812
  if (packageJson.repository) {
@@ -1953,7 +1835,7 @@ var PackageProcessor = class {
1953
1835
  this.fullConfig.changelogFormat
1954
1836
  );
1955
1837
  }
1956
- const packageJsonPath = path6.join(pkgPath, "package.json");
1838
+ const packageJsonPath = path7.join(pkgPath, "package.json");
1957
1839
  if (fs8.existsSync(packageJsonPath)) {
1958
1840
  updatePackageVersion(packageJsonPath, nextVersion);
1959
1841
  }
@@ -1962,13 +1844,13 @@ var PackageProcessor = class {
1962
1844
  const cargoPaths = (_b = this.fullConfig.cargo) == null ? void 0 : _b.paths;
1963
1845
  if (cargoPaths && cargoPaths.length > 0) {
1964
1846
  for (const cargoPath of cargoPaths) {
1965
- const resolvedCargoPath = path6.resolve(pkgPath, cargoPath, "Cargo.toml");
1847
+ const resolvedCargoPath = path7.resolve(pkgPath, cargoPath, "Cargo.toml");
1966
1848
  if (fs8.existsSync(resolvedCargoPath)) {
1967
1849
  updatePackageVersion(resolvedCargoPath, nextVersion);
1968
1850
  }
1969
1851
  }
1970
1852
  } else {
1971
- const cargoTomlPath = path6.join(pkgPath, "Cargo.toml");
1853
+ const cargoTomlPath = path7.join(pkgPath, "Cargo.toml");
1972
1854
  if (fs8.existsSync(cargoTomlPath)) {
1973
1855
  updatePackageVersion(cargoTomlPath, nextVersion);
1974
1856
  }
@@ -2006,7 +1888,7 @@ var PackageProcessor = class {
2006
1888
  }
2007
1889
  const filesToCommit = [];
2008
1890
  for (const info of updatedPackagesInfo) {
2009
- const packageJsonPath = path6.join(info.path, "package.json");
1891
+ const packageJsonPath = path7.join(info.path, "package.json");
2010
1892
  if (fs8.existsSync(packageJsonPath)) {
2011
1893
  filesToCommit.push(packageJsonPath);
2012
1894
  }
@@ -2015,13 +1897,13 @@ var PackageProcessor = class {
2015
1897
  const cargoPaths = (_d = this.fullConfig.cargo) == null ? void 0 : _d.paths;
2016
1898
  if (cargoPaths && cargoPaths.length > 0) {
2017
1899
  for (const cargoPath of cargoPaths) {
2018
- const resolvedCargoPath = path6.resolve(info.path, cargoPath, "Cargo.toml");
1900
+ const resolvedCargoPath = path7.resolve(info.path, cargoPath, "Cargo.toml");
2019
1901
  if (fs8.existsSync(resolvedCargoPath)) {
2020
1902
  filesToCommit.push(resolvedCargoPath);
2021
1903
  }
2022
1904
  }
2023
1905
  } else {
2024
- const cargoTomlPath = path6.join(info.path, "Cargo.toml");
1906
+ const cargoTomlPath = path7.join(info.path, "Cargo.toml");
2025
1907
  if (fs8.existsSync(cargoTomlPath)) {
2026
1908
  filesToCommit.push(cargoTomlPath);
2027
1909
  }
@@ -2084,7 +1966,7 @@ function createSyncedStrategy(config) {
2084
1966
  mainPackage
2085
1967
  } = config;
2086
1968
  const formattedPrefix = formatVersionPrefix(versionPrefix || "v");
2087
- const latestTag = await getLatestTag();
1969
+ let latestTag = await getLatestTag();
2088
1970
  let mainPkgPath = packages.root;
2089
1971
  let mainPkgName;
2090
1972
  if (mainPackage) {
@@ -2107,6 +1989,21 @@ function createSyncedStrategy(config) {
2107
1989
  "warning"
2108
1990
  );
2109
1991
  }
1992
+ if (mainPkgName) {
1993
+ const packageSpecificTag = await getLatestTagForPackage(mainPkgName, formattedPrefix, {
1994
+ tagTemplate,
1995
+ packageSpecificTags: config.packageSpecificTags
1996
+ });
1997
+ if (packageSpecificTag) {
1998
+ latestTag = packageSpecificTag;
1999
+ log(`Using package-specific tag for ${mainPkgName}: ${latestTag}`, "debug");
2000
+ } else {
2001
+ log(
2002
+ `No package-specific tag found for ${mainPkgName}, using global tag: ${latestTag}`,
2003
+ "debug"
2004
+ );
2005
+ }
2006
+ }
2110
2007
  const nextVersion = await calculateVersion(config, {
2111
2008
  latestTag,
2112
2009
  versionPrefix: formattedPrefix,
@@ -2118,7 +2015,8 @@ function createSyncedStrategy(config) {
2118
2015
  type: config.type
2119
2016
  });
2120
2017
  if (!nextVersion) {
2121
- log("No version change needed", "info");
2018
+ const msg = mainPkgName ? `No version change needed for ${mainPkgName}` : "No version change needed";
2019
+ log(msg, "info");
2122
2020
  return;
2123
2021
  }
2124
2022
  const files = [];
@@ -2126,7 +2024,7 @@ function createSyncedStrategy(config) {
2126
2024
  const processedPaths = /* @__PURE__ */ new Set();
2127
2025
  try {
2128
2026
  if (packages.root) {
2129
- const rootPkgPath = path7.join(packages.root, "package.json");
2027
+ const rootPkgPath = path8.join(packages.root, "package.json");
2130
2028
  if (fs9.existsSync(rootPkgPath)) {
2131
2029
  updatePackageVersion(rootPkgPath, nextVersion);
2132
2030
  files.push(rootPkgPath);
@@ -2144,7 +2042,7 @@ function createSyncedStrategy(config) {
2144
2042
  if (!shouldProcessPackage2(pkg, config)) {
2145
2043
  continue;
2146
2044
  }
2147
- const packageJsonPath = path7.join(pkg.dir, "package.json");
2045
+ const packageJsonPath = path8.join(pkg.dir, "package.json");
2148
2046
  if (processedPaths.has(packageJsonPath)) {
2149
2047
  continue;
2150
2048
  }
@@ -2160,7 +2058,7 @@ function createSyncedStrategy(config) {
2160
2058
  return;
2161
2059
  }
2162
2060
  let tagPackageName = null;
2163
- let commitPackageName = void 0;
2061
+ let commitPackageName;
2164
2062
  if (config.packageSpecificTags && packages.packages.length === 1) {
2165
2063
  tagPackageName = packages.packages[0].packageJson.name;
2166
2064
  commitPackageName = packages.packages[0].packageJson.name;
@@ -2194,7 +2092,6 @@ function createSingleStrategy(config) {
2194
2092
  return async (packages) => {
2195
2093
  try {
2196
2094
  const {
2197
- packages: configPackages,
2198
2095
  mainPackage,
2199
2096
  versionPrefix,
2200
2097
  tagTemplate,
@@ -2205,12 +2102,12 @@ function createSingleStrategy(config) {
2205
2102
  let packageName;
2206
2103
  if (mainPackage) {
2207
2104
  packageName = mainPackage;
2208
- } else if (configPackages && configPackages.length === 1) {
2209
- packageName = configPackages[0];
2105
+ } else if (packages.packages.length === 1) {
2106
+ packageName = packages.packages[0].packageJson.name;
2210
2107
  } else {
2211
2108
  throw createVersionError(
2212
2109
  "INVALID_CONFIG" /* INVALID_CONFIG */,
2213
- "Single mode requires either mainPackage or exactly one package in the packages array"
2110
+ "Single mode requires either mainPackage or exactly one resolved package"
2214
2111
  );
2215
2112
  }
2216
2113
  const pkg = packages.packages.find((p) => p.packageJson.name === packageName);
@@ -2228,50 +2125,114 @@ function createSingleStrategy(config) {
2228
2125
  latestTagResult = globalTagResult || "";
2229
2126
  }
2230
2127
  const latestTag = latestTagResult;
2231
- let nextVersion = void 0;
2232
- try {
2233
- nextVersion = await calculateVersion(config, {
2234
- latestTag,
2235
- versionPrefix: formattedPrefix,
2236
- path: pkgPath,
2237
- name: packageName,
2238
- type: config.type
2239
- });
2240
- } catch (error) {
2241
- const errorMessage = error instanceof Error ? error.message : String(error);
2242
- throw createVersionError("VERSION_CALCULATION_ERROR" /* VERSION_CALCULATION_ERROR */, errorMessage);
2243
- }
2244
- if (nextVersion === void 0 || nextVersion === "") {
2128
+ let nextVersion;
2129
+ nextVersion = await calculateVersion(config, {
2130
+ latestTag,
2131
+ versionPrefix: formattedPrefix,
2132
+ branchPattern: config.branchPattern,
2133
+ baseBranch: config.baseBranch,
2134
+ prereleaseIdentifier: config.prereleaseIdentifier,
2135
+ path: pkgPath,
2136
+ name: packageName,
2137
+ type: config.type
2138
+ });
2139
+ if (!nextVersion) {
2245
2140
  log(`No version change needed for ${packageName}`, "info");
2246
2141
  return;
2247
2142
  }
2248
- const packageJsonPath = path7.join(pkgPath, "package.json");
2143
+ if (config.updateChangelog !== false) {
2144
+ let changelogEntries = [];
2145
+ try {
2146
+ let revisionRange;
2147
+ if (latestTag) {
2148
+ try {
2149
+ execSync5(`git rev-parse --verify "${latestTag}"`, {
2150
+ cwd: pkgPath,
2151
+ stdio: "ignore"
2152
+ });
2153
+ revisionRange = `${latestTag}..HEAD`;
2154
+ } catch {
2155
+ log(`Tag ${latestTag} doesn't exist, using all commits for changelog`, "debug");
2156
+ revisionRange = "HEAD";
2157
+ }
2158
+ } else {
2159
+ revisionRange = "HEAD";
2160
+ }
2161
+ changelogEntries = extractChangelogEntriesFromCommits(pkgPath, revisionRange);
2162
+ if (changelogEntries.length === 0) {
2163
+ changelogEntries = [
2164
+ {
2165
+ type: "changed",
2166
+ description: `Update version to ${nextVersion}`
2167
+ }
2168
+ ];
2169
+ }
2170
+ } catch (error) {
2171
+ log(
2172
+ `Error extracting changelog entries: ${error instanceof Error ? error.message : String(error)}`,
2173
+ "warning"
2174
+ );
2175
+ changelogEntries = [
2176
+ {
2177
+ type: "changed",
2178
+ description: `Update version to ${nextVersion}`
2179
+ }
2180
+ ];
2181
+ }
2182
+ let repoUrl;
2183
+ try {
2184
+ const packageJsonPath2 = path8.join(pkgPath, "package.json");
2185
+ if (fs9.existsSync(packageJsonPath2)) {
2186
+ const packageJson = JSON.parse(fs9.readFileSync(packageJsonPath2, "utf8"));
2187
+ if (packageJson.repository) {
2188
+ if (typeof packageJson.repository === "string") {
2189
+ repoUrl = packageJson.repository;
2190
+ } else if (packageJson.repository.url) {
2191
+ repoUrl = packageJson.repository.url;
2192
+ }
2193
+ if ((repoUrl == null ? void 0 : repoUrl.startsWith("git+")) && (repoUrl == null ? void 0 : repoUrl.endsWith(".git"))) {
2194
+ repoUrl = repoUrl.substring(4, repoUrl.length - 4);
2195
+ }
2196
+ }
2197
+ }
2198
+ } catch (error) {
2199
+ log(
2200
+ `Could not determine repository URL for changelog links: ${error instanceof Error ? error.message : String(error)}`,
2201
+ "warning"
2202
+ );
2203
+ }
2204
+ updateChangelog(
2205
+ pkgPath,
2206
+ packageName,
2207
+ nextVersion,
2208
+ changelogEntries,
2209
+ repoUrl,
2210
+ config.changelogFormat
2211
+ );
2212
+ }
2213
+ const packageJsonPath = path8.join(pkgPath, "package.json");
2249
2214
  updatePackageVersion(packageJsonPath, nextVersion);
2250
2215
  log(`Updated package ${packageName} to version ${nextVersion}`, "success");
2251
- const nextTag = formatTag(
2216
+ const tagName = formatTag(
2252
2217
  nextVersion,
2253
2218
  formattedPrefix,
2254
2219
  packageName,
2255
2220
  tagTemplate,
2256
2221
  config.packageSpecificTags
2257
2222
  );
2258
- const formattedCommitMessage = formatCommitMessage(commitMessage, nextVersion, packageName);
2259
- await createGitCommitAndTag(
2260
- [packageJsonPath],
2261
- nextTag,
2262
- formattedCommitMessage,
2263
- skipHooks,
2264
- dryRun
2265
- );
2223
+ const commitMsg = formatCommitMessage(commitMessage, nextVersion, packageName);
2224
+ if (!dryRun) {
2225
+ await createGitCommitAndTag([packageJsonPath], tagName, commitMsg, skipHooks, dryRun);
2226
+ log(`Created tag: ${tagName}`, "success");
2227
+ } else {
2228
+ log(`Would create tag: ${tagName}`, "info");
2229
+ }
2266
2230
  } catch (error) {
2267
2231
  if (error instanceof VersionError || error instanceof GitError) {
2268
- log(
2269
- `Single Package Strategy failed: ${error.message} (${error.code || "UNKNOWN"})`,
2270
- "error"
2271
- );
2232
+ log(`Single Strategy failed: ${error.message} (${error.code || "UNKNOWN"})`, "error");
2272
2233
  } else {
2273
2234
  const errorMessage = error instanceof Error ? error.message : String(error);
2274
- log(`Single Package Strategy failed: ${errorMessage}`, "error");
2235
+ log(`Single Strategy failed: ${errorMessage}`, "error");
2275
2236
  }
2276
2237
  throw error;
2277
2238
  }
@@ -2327,13 +2288,9 @@ function createAsyncStrategy(config) {
2327
2288
  };
2328
2289
  }
2329
2290
  function createStrategy(config) {
2330
- var _a;
2331
2291
  if (config.synced) {
2332
2292
  return createSyncedStrategy(config);
2333
2293
  }
2334
- if (config.mainPackage || ((_a = config.packages) == null ? void 0 : _a.length) === 1) {
2335
- return createSingleStrategy(config);
2336
- }
2337
2294
  return createAsyncStrategy(config);
2338
2295
  }
2339
2296
  function createStrategyMap(config) {
@@ -2385,8 +2342,10 @@ var VersionEngine = class {
2385
2342
  }
2386
2343
  if (this.config.packages && this.config.packages.length > 0) {
2387
2344
  const originalCount = pkgsResult.packages.length;
2388
- const filteredPackages = pkgsResult.packages.filter(
2389
- (pkg) => shouldMatchPackageTargets(pkg.packageJson.name, this.config.packages)
2345
+ const filteredPackages = filterPackagesByConfig(
2346
+ pkgsResult.packages,
2347
+ this.config.packages,
2348
+ pkgsResult.root
2390
2349
  );
2391
2350
  pkgsResult.packages = filteredPackages;
2392
2351
  log(
@@ -2396,11 +2355,6 @@ var VersionEngine = class {
2396
2355
  if (filteredPackages.length === 0) {
2397
2356
  log("Warning: No packages matched the specified patterns in config.packages", "warning");
2398
2357
  }
2399
- } else {
2400
- log(
2401
- `Processing all ${pkgsResult.packages.length} workspace packages (no packages filter specified)`,
2402
- "info"
2403
- );
2404
2358
  }
2405
2359
  this.workspaceCache = pkgsResult;
2406
2360
  return pkgsResult;
@@ -2413,11 +2367,11 @@ var VersionEngine = class {
2413
2367
  }
2414
2368
  /**
2415
2369
  * Run the current strategy
2370
+ * @param packages Workspace packages to process
2416
2371
  * @param targets Optional package targets to process (only used by async strategy)
2417
2372
  */
2418
- async run(targets = []) {
2373
+ async run(packages, targets = []) {
2419
2374
  try {
2420
- const packages = await this.getWorkspacePackages();
2421
2375
  return this.currentStrategy(packages, targets);
2422
2376
  } catch (error) {
2423
2377
  if (error instanceof VersionError || error instanceof GitError) {
@@ -2454,8 +2408,8 @@ var VersionEngine = class {
2454
2408
  // src/index.ts
2455
2409
  function getPackageVersion() {
2456
2410
  try {
2457
- const packageJsonPath = path8.resolve(
2458
- path8.dirname(import.meta.url.replace("file:", "")),
2411
+ const packageJsonPath = path9.resolve(
2412
+ path9.dirname(import.meta.url.replace("file:", "")),
2459
2413
  "../package.json"
2460
2414
  );
2461
2415
  const packageJsonContent = fs10.readFileSync(packageJsonPath, "utf-8");
@@ -2492,24 +2446,31 @@ async function run() {
2492
2446
  config.prereleaseIdentifier = options.prerelease === true ? "next" : options.prerelease;
2493
2447
  const cliTargets = options.target ? options.target.split(",").map((t) => t.trim()) : [];
2494
2448
  const engine = new VersionEngine(config, !!options.json);
2449
+ const pkgsResult = await engine.getWorkspacePackages();
2450
+ const resolvedCount = pkgsResult.packages.length;
2451
+ log(`Resolved ${resolvedCount} packages from workspace`, "debug");
2452
+ log(`Config packages: ${JSON.stringify(config.packages)}`, "debug");
2453
+ log(`Config synced: ${config.synced}`, "debug");
2495
2454
  if (config.synced) {
2496
2455
  log("Using synced versioning strategy.", "info");
2497
2456
  engine.setStrategy("synced");
2498
- await engine.run();
2499
- } else if (config.packages && config.packages.length === 1) {
2457
+ await engine.run(pkgsResult);
2458
+ } else if (resolvedCount === 1) {
2500
2459
  log("Using single package versioning strategy.", "info");
2501
2460
  if (cliTargets.length > 0) {
2502
2461
  log("--target flag is ignored for single package strategy.", "warning");
2503
2462
  }
2504
2463
  engine.setStrategy("single");
2505
- await engine.run();
2464
+ await engine.run(pkgsResult);
2465
+ } else if (resolvedCount === 0) {
2466
+ throw new Error("No packages found in workspace");
2506
2467
  } else {
2507
2468
  log("Using async versioning strategy.", "info");
2508
2469
  if (cliTargets.length > 0) {
2509
2470
  log(`Targeting specific packages: ${cliTargets.join(", ")}`, "info");
2510
2471
  }
2511
2472
  engine.setStrategy("async");
2512
- await engine.run(cliTargets);
2473
+ await engine.run(pkgsResult, cliTargets);
2513
2474
  }
2514
2475
  log("Versioning process completed.", "success");
2515
2476
  printJsonOutput();
@@ -2528,38 +2489,43 @@ async function run() {
2528
2489
  process.exit(1);
2529
2490
  }
2530
2491
  });
2531
- program.command("regenerate-changelog").description("Regenerate a complete changelog from git history").option("-o, --output <path>", "Output path for changelog file", "CHANGELOG.md").option(
2492
+ program.command("changelog").description("Changelog management commands").option("--regenerate", "Regenerate a complete changelog from git history").option("-o, --output <path>", "Output path for changelog file", "CHANGELOG.md").option(
2532
2493
  "-f, --format <format>",
2533
2494
  "Changelog format (keep-a-changelog|angular)",
2534
2495
  "keep-a-changelog"
2535
2496
  ).option("-s, --since <tag>", "Start changelog from specific tag").option("-u, --repo-url <url>", "Repository URL for changelog links").option("-d, --dry-run", "Preview changelog without writing to file", false).option("-p, --project-dir <path>", "Project directory", process.cwd()).action(async (options) => {
2536
- try {
2537
- log("Regenerating changelog from git history...", "info");
2538
- if (options.format !== "keep-a-changelog" && options.format !== "angular") {
2539
- throw new Error(
2540
- 'Invalid format specified. Must be either "keep-a-changelog" or "angular"'
2497
+ var _a;
2498
+ if (options.regenerate) {
2499
+ try {
2500
+ log("Regenerating changelog from git history...", "info");
2501
+ if (options.format !== "keep-a-changelog" && options.format !== "angular") {
2502
+ throw new Error(
2503
+ 'Invalid format specified. Must be either "keep-a-changelog" or "angular"'
2504
+ );
2505
+ }
2506
+ const regenerateOptions = {
2507
+ format: options.format,
2508
+ since: options.since,
2509
+ output: options.output,
2510
+ dryRun: options.dryRun,
2511
+ projectDir: options.projectDir,
2512
+ repoUrl: options.repoUrl
2513
+ };
2514
+ const content = await regenerateChangelog(regenerateOptions);
2515
+ await writeChangelog(
2516
+ content,
2517
+ path9.resolve(options.projectDir, options.output),
2518
+ options.dryRun
2541
2519
  );
2520
+ if (!options.dryRun) {
2521
+ log(`Changelog successfully regenerated at ${options.output}`, "success");
2522
+ }
2523
+ } catch (error) {
2524
+ log(error instanceof Error ? error.message : String(error), "error");
2525
+ process.exit(1);
2542
2526
  }
2543
- const regenerateOptions = {
2544
- format: options.format,
2545
- since: options.since,
2546
- output: options.output,
2547
- dryRun: options.dryRun,
2548
- projectDir: options.projectDir,
2549
- repoUrl: options.repoUrl
2550
- };
2551
- const content = await regenerateChangelog(regenerateOptions);
2552
- await writeChangelog(
2553
- content,
2554
- path8.resolve(options.projectDir, options.output),
2555
- options.dryRun
2556
- );
2557
- if (!options.dryRun) {
2558
- log(`Changelog successfully regenerated at ${options.output}`, "success");
2559
- }
2560
- } catch (error) {
2561
- log(error instanceof Error ? error.message : String(error), "error");
2562
- process.exit(1);
2527
+ } else {
2528
+ (_a = program.commands.find((cmd) => cmd.name() === "changelog")) == null ? void 0 : _a.help();
2563
2529
  }
2564
2530
  });
2565
2531
  program.parse(process.argv);