package-versioner 0.6.4 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,79 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
- import * as fs7 from "node:fs";
5
- import path5 from "node:path";
4
+ import * as fs9 from "node:fs";
5
+ import path7 from "node:path";
6
6
  import { Command } from "commander";
7
7
 
8
- // src/config.ts
9
- import * as fs from "node:fs";
10
- import { cwd } from "node:process";
11
- function loadConfig(configPath) {
12
- const localProcess = cwd();
13
- const filePath = configPath || `${localProcess}/version.config.json`;
14
- return new Promise((resolve, reject) => {
15
- fs.readFile(filePath, "utf-8", (err, data) => {
16
- if (err) {
17
- reject(new Error(`Could not locate the config file at ${filePath}: ${err.message}`));
18
- return;
19
- }
20
- try {
21
- const config = JSON.parse(data);
22
- resolve(config);
23
- } catch (err2) {
24
- const errorMessage = err2 instanceof Error ? err2.message : String(err2);
25
- reject(new Error(`Failed to parse config file ${filePath}: ${errorMessage}`));
26
- }
27
- });
28
- });
29
- }
30
-
31
- // src/core/versionEngine.ts
32
- import { cwd as cwd4 } from "node:process";
33
- import { getPackagesSync } from "@manypkg/get-packages";
34
-
35
- // src/errors/gitError.ts
36
- var GitError = class extends Error {
37
- constructor(message, code) {
38
- super(message);
39
- this.code = code;
40
- this.name = "GitError";
41
- }
42
- };
43
- function createGitError(code, details) {
44
- const messages = {
45
- ["NOT_GIT_REPO" /* NOT_GIT_REPO */]: "Not a git repository",
46
- ["GIT_PROCESS_ERROR" /* GIT_PROCESS_ERROR */]: "Failed to create new version",
47
- ["NO_FILES" /* NO_FILES */]: "No files specified for commit",
48
- ["NO_COMMIT_MESSAGE" /* NO_COMMIT_MESSAGE */]: "Commit message is required",
49
- ["GIT_ERROR" /* GIT_ERROR */]: "Git operation failed"
50
- };
51
- const baseMessage = messages[code];
52
- const fullMessage = details ? `${baseMessage}: ${details}` : baseMessage;
53
- return new GitError(fullMessage, code);
54
- }
55
-
56
- // src/errors/versionError.ts
57
- var VersionError = class extends Error {
58
- constructor(message, code) {
59
- super(message);
60
- this.code = code;
61
- this.name = "VersionError";
62
- }
63
- };
64
- function createVersionError(code, details) {
65
- const messages = {
66
- ["CONFIG_REQUIRED" /* CONFIG_REQUIRED */]: "Configuration is required",
67
- ["PACKAGES_NOT_FOUND" /* PACKAGES_NOT_FOUND */]: "Failed to get packages information",
68
- ["WORKSPACE_ERROR" /* WORKSPACE_ERROR */]: "Failed to get workspace packages",
69
- ["INVALID_CONFIG" /* INVALID_CONFIG */]: "Invalid configuration",
70
- ["PACKAGE_NOT_FOUND" /* PACKAGE_NOT_FOUND */]: "Package not found",
71
- ["VERSION_CALCULATION_ERROR" /* VERSION_CALCULATION_ERROR */]: "Failed to calculate version"
72
- };
73
- const baseMessage = messages[code];
74
- const fullMessage = details ? `${baseMessage}: ${details}` : baseMessage;
75
- return new VersionError(fullMessage, code);
76
- }
8
+ // src/changelog/changelogRegenerator.ts
9
+ import { execSync as execSync2 } from "node:child_process";
10
+ import fs from "node:fs";
11
+ import path from "node:path";
77
12
 
78
13
  // src/utils/logging.ts
79
14
  import chalk from "chalk";
@@ -156,9 +91,508 @@ function log(message, level = "info") {
156
91
  }
157
92
  }
158
93
 
94
+ // src/changelog/commitParser.ts
95
+ import { execSync } from "node:child_process";
96
+ var CONVENTIONAL_COMMIT_REGEX = /^(\w+)(?:\(([^)]+)\))?(!)?: (.+)(?:\n\n([\s\S]*))?/;
97
+ var BREAKING_CHANGE_REGEX = /BREAKING CHANGE: ([\s\S]+?)(?:\n\n|$)/;
98
+ function extractChangelogEntriesFromCommits(projectDir, revisionRange) {
99
+ try {
100
+ const command = `git log ${revisionRange} --pretty=format:"%B---COMMIT_DELIMITER---" --no-merges`;
101
+ const output = execSync(command, {
102
+ cwd: projectDir,
103
+ encoding: "utf8"
104
+ });
105
+ const commits = output.split("---COMMIT_DELIMITER---").filter((commit) => commit.trim() !== "");
106
+ return commits.map((commit) => parseCommitMessage(commit)).filter((entry) => entry !== null);
107
+ } catch (error) {
108
+ log(`Error extracting commits: ${error}`, "error");
109
+ return [];
110
+ }
111
+ }
112
+ function parseCommitMessage(message) {
113
+ const match = message.match(CONVENTIONAL_COMMIT_REGEX);
114
+ if (match) {
115
+ const [, type, scope, breakingMark, subject, body = ""] = match;
116
+ const breakingFromMark = breakingMark === "!";
117
+ const breakingChangeMatch = body.match(BREAKING_CHANGE_REGEX);
118
+ const hasBreakingChange = breakingFromMark || breakingChangeMatch !== null;
119
+ const changelogType = mapCommitTypeToChangelogType(type);
120
+ if (!changelogType) {
121
+ return null;
122
+ }
123
+ const issueIds = extractIssueIds(body);
124
+ let description = subject;
125
+ if (hasBreakingChange) {
126
+ description = `**BREAKING** ${description}`;
127
+ }
128
+ return {
129
+ type: changelogType,
130
+ description,
131
+ scope: scope || void 0,
132
+ issueIds: issueIds.length > 0 ? issueIds : void 0,
133
+ originalType: type
134
+ // Store original type for custom formatting
135
+ };
136
+ }
137
+ if (!message.startsWith("Merge") && !message.match(/^v?\d+\.\d+\.\d+/)) {
138
+ const firstLine = message.split("\n")[0].trim();
139
+ return {
140
+ type: "changed",
141
+ description: firstLine
142
+ };
143
+ }
144
+ return null;
145
+ }
146
+ function mapCommitTypeToChangelogType(type) {
147
+ switch (type) {
148
+ case "feat":
149
+ return "added";
150
+ case "fix":
151
+ return "fixed";
152
+ case "docs":
153
+ case "style":
154
+ case "refactor":
155
+ case "perf":
156
+ case "build":
157
+ case "ci":
158
+ return "changed";
159
+ case "revert":
160
+ return "removed";
161
+ case "chore":
162
+ return "changed";
163
+ case "test":
164
+ return null;
165
+ default:
166
+ return "changed";
167
+ }
168
+ }
169
+ function extractIssueIds(body) {
170
+ const issueRegex = /(?:fix|fixes|close|closes|resolve|resolves)\s+#(\d+)/gi;
171
+ const issueIds = [];
172
+ let match = issueRegex.exec(body);
173
+ while (match !== null) {
174
+ issueIds.push(`#${match[1]}`);
175
+ match = issueRegex.exec(body);
176
+ }
177
+ return issueIds;
178
+ }
179
+
180
+ // src/changelog/formatters.ts
181
+ function formatChangelogEntries(format, version, date, entries, packageName, repoUrl) {
182
+ const formattingEntries = entries.map((entry) => {
183
+ const hasBreaking = entry.description.includes("**BREAKING**");
184
+ return {
185
+ ...entry,
186
+ breaking: hasBreaking
187
+ };
188
+ });
189
+ return format === "keep-a-changelog" ? formatKeepAChangelogEntries(version, date, formattingEntries, repoUrl) : formatAngularEntries(version, date, formattingEntries, packageName);
190
+ }
191
+ function formatKeepAChangelogEntries(version, date, entries, repoUrl) {
192
+ const added = [];
193
+ const changed = [];
194
+ const deprecated = [];
195
+ const removed = [];
196
+ const fixed = [];
197
+ const security = [];
198
+ for (const entry of entries) {
199
+ const entryText = entry.scope ? `- **${entry.scope}**: ${entry.description}` : `- ${entry.description}`;
200
+ const formattedEntry = entry.breaking ? entryText.replace(/^- /, "- **BREAKING** ") : entryText;
201
+ const entryType = entry.originalType || entry.type;
202
+ switch (entryType) {
203
+ case "feat":
204
+ added.push(formattedEntry);
205
+ break;
206
+ case "fix":
207
+ fixed.push(formattedEntry);
208
+ break;
209
+ case "docs":
210
+ case "style":
211
+ case "refactor":
212
+ case "perf":
213
+ case "build":
214
+ case "ci":
215
+ changed.push(formattedEntry);
216
+ break;
217
+ case "test":
218
+ break;
219
+ case "chore":
220
+ if (entry.description.toLowerCase().includes("deprecat")) {
221
+ deprecated.push(formattedEntry);
222
+ } else {
223
+ changed.push(formattedEntry);
224
+ }
225
+ break;
226
+ // Keep-a-changelog standard types
227
+ case "added":
228
+ added.push(formattedEntry);
229
+ break;
230
+ case "changed":
231
+ changed.push(formattedEntry);
232
+ break;
233
+ case "deprecated":
234
+ deprecated.push(formattedEntry);
235
+ break;
236
+ case "removed":
237
+ removed.push(formattedEntry);
238
+ break;
239
+ case "fixed":
240
+ fixed.push(formattedEntry);
241
+ break;
242
+ case "security":
243
+ security.push(formattedEntry);
244
+ break;
245
+ default:
246
+ changed.push(formattedEntry);
247
+ }
248
+ }
249
+ let content = `## [${version}] - ${date}
250
+
251
+ `;
252
+ if (added.length > 0) {
253
+ content += `### Added
254
+
255
+ ${added.join("\n")}
256
+
257
+ `;
258
+ }
259
+ if (changed.length > 0) {
260
+ content += `### Changed
261
+
262
+ ${changed.join("\n")}
263
+
264
+ `;
265
+ }
266
+ if (deprecated.length > 0) {
267
+ content += `### Deprecated
268
+
269
+ ${deprecated.join("\n")}
270
+
271
+ `;
272
+ }
273
+ if (removed.length > 0) {
274
+ content += `### Removed
275
+
276
+ ${removed.join("\n")}
277
+
278
+ `;
279
+ }
280
+ if (fixed.length > 0) {
281
+ content += `### Fixed
282
+
283
+ ${fixed.join("\n")}
284
+
285
+ `;
286
+ }
287
+ if (security.length > 0) {
288
+ content += `### Security
289
+
290
+ ${security.join("\n")}
291
+
292
+ `;
293
+ }
294
+ if (repoUrl) {
295
+ content += `[${version}]: ${repoUrl}/compare/v${version}...HEAD
296
+ `;
297
+ }
298
+ return content.trim();
299
+ }
300
+ function formatAngularEntries(version, date, entries, packageName) {
301
+ const features = [];
302
+ const bugfixes = [];
303
+ const performance = [];
304
+ const breaking = [];
305
+ for (const entry of entries) {
306
+ if (entry.breaking) {
307
+ breaking.push(entry);
308
+ }
309
+ const entryType = entry.originalType || entry.type;
310
+ switch (entryType) {
311
+ case "feat":
312
+ case "added":
313
+ features.push(entry);
314
+ break;
315
+ case "fix":
316
+ case "fixed":
317
+ bugfixes.push(entry);
318
+ break;
319
+ case "perf":
320
+ performance.push(entry);
321
+ break;
322
+ }
323
+ }
324
+ let content = `## [${version}]${packageName ? ` (${packageName})` : ""} (${date})
325
+
326
+ `;
327
+ if (features.length > 0) {
328
+ content += "### Features\n\n";
329
+ content += formatAngularTypeEntries(features);
330
+ content += "\n";
331
+ }
332
+ if (bugfixes.length > 0) {
333
+ content += "### Bug Fixes\n\n";
334
+ content += formatAngularTypeEntries(bugfixes);
335
+ content += "\n";
336
+ }
337
+ if (performance.length > 0) {
338
+ content += "### Performance Improvements\n\n";
339
+ content += formatAngularTypeEntries(performance);
340
+ content += "\n";
341
+ }
342
+ if (breaking.length > 0) {
343
+ content += "### BREAKING CHANGES\n\n";
344
+ content += formatAngularTypeEntries(breaking);
345
+ content += "\n";
346
+ }
347
+ return content.trim();
348
+ }
349
+ function formatAngularTypeEntries(entries) {
350
+ var _a;
351
+ const entriesByScope = /* @__PURE__ */ new Map();
352
+ for (const entry of entries) {
353
+ const scope = entry.scope || "";
354
+ if (!entriesByScope.has(scope)) {
355
+ entriesByScope.set(scope, []);
356
+ }
357
+ (_a = entriesByScope.get(scope)) == null ? void 0 : _a.push(entry);
358
+ }
359
+ const result = [];
360
+ for (const [scope, scopeEntries] of Object.entries(groupEntriesByScope(entries))) {
361
+ if (scope !== "undefined" && scope !== "") {
362
+ result.push(`* **${scope}:**`);
363
+ for (const entry of scopeEntries) {
364
+ const description = entry.description.replace("**BREAKING** ", "");
365
+ result.push(` * ${description}`);
366
+ }
367
+ } else {
368
+ for (const entry of scopeEntries) {
369
+ const description = entry.description.replace("**BREAKING** ", "");
370
+ result.push(`* ${description}`);
371
+ }
372
+ }
373
+ }
374
+ return result.join("\n");
375
+ }
376
+ function groupEntriesByScope(entries) {
377
+ const result = {};
378
+ for (const entry of entries) {
379
+ const scope = entry.scope || "";
380
+ if (!result[scope]) {
381
+ result[scope] = [];
382
+ }
383
+ result[scope].push(entry);
384
+ }
385
+ return result;
386
+ }
387
+
388
+ // src/changelog/templates.ts
389
+ function getDefaultTemplate(format) {
390
+ return format === "keep-a-changelog" ? getKeepAChangelogTemplate() : getAngularTemplate();
391
+ }
392
+ function getKeepAChangelogTemplate() {
393
+ return `# Changelog
394
+
395
+ All notable changes to this project will be documented in this file.
396
+
397
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
398
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
399
+
400
+ `;
401
+ }
402
+ function getAngularTemplate() {
403
+ return `# Changelog
404
+
405
+ `;
406
+ }
407
+
408
+ // src/changelog/changelogRegenerator.ts
409
+ function getAllVersionTags(since, versionPrefix = "v") {
410
+ try {
411
+ const command = since ? `git tag --list "${versionPrefix}*" --sort=creatordate --contains ${since}` : `git tag --list "${versionPrefix}*" --sort=creatordate`;
412
+ const tagOutput = execSync2(command, { encoding: "utf8" }).trim();
413
+ if (!tagOutput) {
414
+ return [];
415
+ }
416
+ const tags = tagOutput.split("\n").filter((tag) => !!tag);
417
+ return tags.map((tag) => {
418
+ try {
419
+ const date = execSync2(`git log -1 --format=%ad --date=short ${tag}`, {
420
+ encoding: "utf8"
421
+ }).trim();
422
+ const version = tag.replace(new RegExp(`^${versionPrefix}`), "");
423
+ return { tag, version, date };
424
+ } catch (error) {
425
+ log(`Failed to get date for tag ${tag}: ${error}`, "warning");
426
+ return { tag, version: tag.replace(new RegExp(`^${versionPrefix}`), ""), date: "Unknown" };
427
+ }
428
+ });
429
+ } catch (error) {
430
+ log(`Failed to get version tags: ${error}`, "error");
431
+ return [];
432
+ }
433
+ }
434
+ async function regenerateChangelog(options) {
435
+ const { format, since, projectDir } = options;
436
+ const packageJsonPath = path.join(projectDir, "package.json");
437
+ let packageName = "";
438
+ let repoUrl = options.repoUrl;
439
+ if (fs.existsSync(packageJsonPath)) {
440
+ try {
441
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
442
+ packageName = packageJson.name || "";
443
+ if (!repoUrl && packageJson.repository) {
444
+ if (typeof packageJson.repository === "string") {
445
+ repoUrl = packageJson.repository;
446
+ } else if (packageJson.repository.url) {
447
+ repoUrl = packageJson.repository.url;
448
+ }
449
+ if ((repoUrl == null ? void 0 : repoUrl.startsWith("git+")) && (repoUrl == null ? void 0 : repoUrl.endsWith(".git"))) {
450
+ repoUrl = repoUrl.substring(4, repoUrl.length - 4);
451
+ }
452
+ }
453
+ } catch (error) {
454
+ log(`Failed to read package.json: ${error}`, "warning");
455
+ }
456
+ }
457
+ let versionPrefix = "v";
458
+ try {
459
+ const allTags = execSync2("git tag --list", { encoding: "utf8" }).trim().split("\n");
460
+ const versionTag = allTags.find((tag) => /^[vV][0-9]/.test(tag));
461
+ if (versionTag) {
462
+ versionPrefix = versionTag.charAt(0);
463
+ }
464
+ } catch {
465
+ }
466
+ const tags = getAllVersionTags(since, versionPrefix);
467
+ if (!tags.length) {
468
+ throw new Error(
469
+ 'No version tags found in git history. Make sure you have tags that start with the version prefix (usually "v").'
470
+ );
471
+ }
472
+ let changelogContent = getDefaultTemplate(format);
473
+ log(`Found ${tags.length} version tags, generating changelog...`, "info");
474
+ const versions = [];
475
+ for (let i = tags.length - 1; i >= 0; i--) {
476
+ const currentTag = tags[i];
477
+ const previousTag = i > 0 ? tags[i - 1].tag : null;
478
+ log(`Processing changes for ${currentTag.tag}...`, "info");
479
+ try {
480
+ const tagRange = previousTag ? `${previousTag}..${currentTag.tag}` : currentTag.tag;
481
+ const entries = extractChangelogEntriesFromCommits(projectDir, tagRange);
482
+ if (!entries.length) {
483
+ log(`No changelog entries found for ${currentTag.tag}, adding placeholder entry`, "info");
484
+ entries.push({
485
+ type: "changed",
486
+ description: `Release version ${currentTag.version}`
487
+ });
488
+ }
489
+ versions.unshift(
490
+ formatChangelogEntries(
491
+ format,
492
+ currentTag.version,
493
+ currentTag.date,
494
+ entries,
495
+ packageName,
496
+ repoUrl
497
+ )
498
+ );
499
+ } catch (error) {
500
+ log(`Failed to process version ${currentTag.tag}: ${error}`, "error");
501
+ }
502
+ }
503
+ changelogContent += versions.join("\n\n");
504
+ return changelogContent;
505
+ }
506
+ async function writeChangelog(content, outputPath, dryRun) {
507
+ if (dryRun) {
508
+ log("--- Changelog Preview ---", "info");
509
+ console.log(content);
510
+ log("--- End Preview ---", "info");
511
+ return;
512
+ }
513
+ try {
514
+ fs.writeFileSync(outputPath, content, "utf8");
515
+ log(`Changelog successfully written to ${outputPath}`, "success");
516
+ } catch (error) {
517
+ throw new Error(
518
+ `Failed to write changelog: ${error instanceof Error ? error.message : String(error)}`
519
+ );
520
+ }
521
+ }
522
+
523
+ // src/config.ts
524
+ import * as fs2 from "node:fs";
525
+ import { cwd } from "node:process";
526
+ function loadConfig(configPath) {
527
+ const localProcess = cwd();
528
+ const filePath = configPath || `${localProcess}/version.config.json`;
529
+ return new Promise((resolve, reject) => {
530
+ fs2.readFile(filePath, "utf-8", (err, data) => {
531
+ if (err) {
532
+ reject(new Error(`Could not locate the config file at ${filePath}: ${err.message}`));
533
+ return;
534
+ }
535
+ try {
536
+ const config = JSON.parse(data);
537
+ resolve(config);
538
+ } catch (err2) {
539
+ const errorMessage = err2 instanceof Error ? err2.message : String(err2);
540
+ reject(new Error(`Failed to parse config file ${filePath}: ${errorMessage}`));
541
+ }
542
+ });
543
+ });
544
+ }
545
+
546
+ // src/core/versionEngine.ts
547
+ import { cwd as cwd4 } from "node:process";
548
+ import { getPackagesSync } from "@manypkg/get-packages";
549
+
550
+ // src/errors/gitError.ts
551
+ var GitError = class extends Error {
552
+ constructor(message, code) {
553
+ super(message);
554
+ this.code = code;
555
+ this.name = "GitError";
556
+ }
557
+ };
558
+ function createGitError(code, details) {
559
+ const messages = {
560
+ ["NOT_GIT_REPO" /* NOT_GIT_REPO */]: "Not a git repository",
561
+ ["GIT_PROCESS_ERROR" /* GIT_PROCESS_ERROR */]: "Failed to create new version",
562
+ ["NO_FILES" /* NO_FILES */]: "No files specified for commit",
563
+ ["NO_COMMIT_MESSAGE" /* NO_COMMIT_MESSAGE */]: "Commit message is required",
564
+ ["GIT_ERROR" /* GIT_ERROR */]: "Git operation failed"
565
+ };
566
+ const baseMessage = messages[code];
567
+ const fullMessage = details ? `${baseMessage}: ${details}` : baseMessage;
568
+ return new GitError(fullMessage, code);
569
+ }
570
+
571
+ // src/errors/versionError.ts
572
+ var VersionError = class extends Error {
573
+ constructor(message, code) {
574
+ super(message);
575
+ this.code = code;
576
+ this.name = "VersionError";
577
+ }
578
+ };
579
+ function createVersionError(code, details) {
580
+ const messages = {
581
+ ["CONFIG_REQUIRED" /* CONFIG_REQUIRED */]: "Configuration is required",
582
+ ["PACKAGES_NOT_FOUND" /* PACKAGES_NOT_FOUND */]: "Failed to get packages information",
583
+ ["WORKSPACE_ERROR" /* WORKSPACE_ERROR */]: "Failed to get workspace packages",
584
+ ["INVALID_CONFIG" /* INVALID_CONFIG */]: "Invalid configuration",
585
+ ["PACKAGE_NOT_FOUND" /* PACKAGE_NOT_FOUND */]: "Package not found",
586
+ ["VERSION_CALCULATION_ERROR" /* VERSION_CALCULATION_ERROR */]: "Failed to calculate version"
587
+ };
588
+ const baseMessage = messages[code];
589
+ const fullMessage = details ? `${baseMessage}: ${details}` : baseMessage;
590
+ return new VersionError(fullMessage, code);
591
+ }
592
+
159
593
  // src/core/versionStrategies.ts
160
- import fs6 from "node:fs";
161
- import * as path4 from "node:path";
594
+ import fs8 from "node:fs";
595
+ import * as path6 from "node:path";
162
596
 
163
597
  // src/git/commands.ts
164
598
  import { cwd as cwd2 } from "node:process";
@@ -181,7 +615,7 @@ var execAsync = (command, options) => {
181
615
  );
182
616
  });
183
617
  };
184
- var execSync = (command, args) => nativeExecSync(command, { maxBuffer: 1024 * 1024 * 10, ...args });
618
+ var execSync3 = (command, args) => nativeExecSync(command, { maxBuffer: 1024 * 1024 * 10, ...args });
185
619
 
186
620
  // src/git/repository.ts
187
621
  import { existsSync, statSync } from "node:fs";
@@ -196,14 +630,14 @@ function isGitRepository(directory) {
196
630
  return false;
197
631
  }
198
632
  try {
199
- execSync("git rev-parse --is-inside-work-tree", { cwd: directory });
633
+ execSync3("git rev-parse --is-inside-work-tree", { cwd: directory });
200
634
  return true;
201
635
  } catch (_error) {
202
636
  return false;
203
637
  }
204
638
  }
205
639
  function getCurrentBranch() {
206
- const result = execSync("git rev-parse --abbrev-ref HEAD");
640
+ const result = execSync3("git rev-parse --abbrev-ref HEAD");
207
641
  return result.toString().trim();
208
642
  }
209
643
 
@@ -347,7 +781,7 @@ function createTemplateString(template, variables) {
347
781
  function getCommitsLength(pkgRoot) {
348
782
  try {
349
783
  const gitCommand = `git rev-list --count HEAD ^$(git describe --tags --abbrev=0) ${pkgRoot}`;
350
- const amount = execSync(gitCommand).toString().trim();
784
+ const amount = execSync3(gitCommand).toString().trim();
351
785
  return Number(amount);
352
786
  } catch (error) {
353
787
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -444,20 +878,20 @@ async function getLatestTagForPackage(packageName, versionPrefix) {
444
878
  }
445
879
 
446
880
  // src/package/packageManagement.ts
447
- import fs3 from "node:fs";
881
+ import fs4 from "node:fs";
448
882
 
449
883
  // src/cargo/cargoHandler.ts
450
- import fs2 from "node:fs";
451
- import path from "node:path";
884
+ import fs3 from "node:fs";
885
+ import path2 from "node:path";
452
886
  import * as TOML from "smol-toml";
453
887
  function getCargoInfo(cargoPath) {
454
888
  var _a;
455
- if (!fs2.existsSync(cargoPath)) {
889
+ if (!fs3.existsSync(cargoPath)) {
456
890
  log(`Cargo.toml file not found at: ${cargoPath}`, "error");
457
891
  throw new Error(`Cargo.toml file not found at: ${cargoPath}`);
458
892
  }
459
893
  try {
460
- const fileContent = fs2.readFileSync(cargoPath, "utf8");
894
+ const fileContent = fs3.readFileSync(cargoPath, "utf8");
461
895
  const cargo = TOML.parse(fileContent);
462
896
  if (!((_a = cargo.package) == null ? void 0 : _a.name)) {
463
897
  log(`Package name not found in: ${cargoPath}`, "error");
@@ -467,7 +901,7 @@ function getCargoInfo(cargoPath) {
467
901
  name: cargo.package.name,
468
902
  version: cargo.package.version || "0.0.0",
469
903
  path: cargoPath,
470
- dir: path.dirname(cargoPath),
904
+ dir: path2.dirname(cargoPath),
471
905
  content: cargo
472
906
  };
473
907
  } catch (error) {
@@ -480,12 +914,12 @@ function getCargoInfo(cargoPath) {
480
914
  }
481
915
  }
482
916
  function isCargoToml(filePath) {
483
- return path.basename(filePath) === "Cargo.toml";
917
+ return path2.basename(filePath) === "Cargo.toml";
484
918
  }
485
919
  function updateCargoVersion(cargoPath, version) {
486
920
  var _a;
487
921
  try {
488
- const originalContent = fs2.readFileSync(cargoPath, "utf8");
922
+ const originalContent = fs3.readFileSync(cargoPath, "utf8");
489
923
  const cargo = TOML.parse(originalContent);
490
924
  const packageName = (_a = cargo.package) == null ? void 0 : _a.name;
491
925
  if (!packageName) {
@@ -497,7 +931,7 @@ function updateCargoVersion(cargoPath, version) {
497
931
  cargo.package.version = version;
498
932
  }
499
933
  const updatedContent = TOML.stringify(cargo);
500
- fs2.writeFileSync(cargoPath, updatedContent);
934
+ fs3.writeFileSync(cargoPath, updatedContent);
501
935
  addPackageUpdate(packageName, version, cargoPath);
502
936
  log(`Updated Cargo.toml at ${cargoPath} to version ${version}`, "success");
503
937
  } catch (error) {
@@ -516,11 +950,11 @@ function updatePackageVersion(packagePath, version) {
516
950
  return;
517
951
  }
518
952
  try {
519
- const packageContent = fs3.readFileSync(packagePath, "utf8");
953
+ const packageContent = fs4.readFileSync(packagePath, "utf8");
520
954
  const packageJson = JSON.parse(packageContent);
521
955
  const packageName = packageJson.name;
522
956
  packageJson.version = version;
523
- fs3.writeFileSync(packagePath, `${JSON.stringify(packageJson, null, 2)}
957
+ fs4.writeFileSync(packagePath, `${JSON.stringify(packageJson, null, 2)}
524
958
  `);
525
959
  addPackageUpdate(packageName, version, packagePath);
526
960
  log(`Updated package.json at ${packagePath} to version ${version}`, "success");
@@ -534,24 +968,349 @@ function updatePackageVersion(packagePath, version) {
534
968
  }
535
969
 
536
970
  // src/package/packageProcessor.ts
537
- import * as fs5 from "node:fs";
538
- import path3 from "node:path";
971
+ import * as fs7 from "node:fs";
972
+ import path5 from "node:path";
539
973
  import { exit } from "node:process";
540
974
 
975
+ // src/changelog/changelogManager.ts
976
+ import * as fs5 from "node:fs";
977
+ import * as path3 from "node:path";
978
+ function createChangelog(_packagePath, packageName) {
979
+ return {
980
+ projectName: packageName,
981
+ unreleased: [],
982
+ versions: []
983
+ };
984
+ }
985
+ function parseChangelog(filePath) {
986
+ try {
987
+ if (!fs5.existsSync(filePath)) {
988
+ return null;
989
+ }
990
+ fs5.readFileSync(filePath, "utf8");
991
+ log(`Parsed changelog at ${filePath}`, "info");
992
+ return {
993
+ projectName: path3.basename(path3.dirname(filePath)),
994
+ unreleased: [],
995
+ versions: []
996
+ };
997
+ } catch (error) {
998
+ log(
999
+ `Error parsing changelog: ${error instanceof Error ? error.message : String(error)}`,
1000
+ "error"
1001
+ );
1002
+ return null;
1003
+ }
1004
+ }
1005
+ function generateLinks(changelog, repoUrl) {
1006
+ var _a, _b;
1007
+ if (!repoUrl || changelog.versions.length === 0) {
1008
+ return "";
1009
+ }
1010
+ let links = "\n";
1011
+ if (changelog.unreleased.length > 0) {
1012
+ const latestVersion = ((_a = changelog.versions[0]) == null ? void 0 : _a.version) || "";
1013
+ links += `[unreleased]: ${repoUrl}/compare/v${latestVersion}...HEAD
1014
+ `;
1015
+ }
1016
+ for (let i = 0; i < changelog.versions.length; i++) {
1017
+ const currentVersion = changelog.versions[i].version;
1018
+ const previousVersion = (_b = changelog.versions[i + 1]) == null ? void 0 : _b.version;
1019
+ if (previousVersion) {
1020
+ links += `[${currentVersion}]: ${repoUrl}/compare/v${previousVersion}...v${currentVersion}
1021
+ `;
1022
+ } else if (i === changelog.versions.length - 1) {
1023
+ links += `[${currentVersion}]: ${repoUrl}/releases/tag/v${currentVersion}
1024
+ `;
1025
+ }
1026
+ }
1027
+ return links;
1028
+ }
1029
+ function generateAngularChangelogContent(changelog, repoUrl) {
1030
+ let content = "# Changelog\n\n";
1031
+ if (changelog.unreleased.length > 0) {
1032
+ content += "## [Unreleased]\n\n";
1033
+ const groupedByType = groupEntriesByAngularType(changelog.unreleased);
1034
+ for (const [type, entries] of Object.entries(groupedByType)) {
1035
+ content += `### ${formatAngularType(type)}
1036
+
1037
+ `;
1038
+ const groupedByScope = groupEntriesByScope2(entries);
1039
+ for (const [scope, scopeEntries] of Object.entries(groupedByScope)) {
1040
+ if (scope !== "undefined" && scope !== "") {
1041
+ content += `* **${scope}:**
1042
+ `;
1043
+ for (const entry of scopeEntries) {
1044
+ content += formatAngularEntry(entry, false);
1045
+ }
1046
+ content += "\n";
1047
+ } else {
1048
+ for (const entry of scopeEntries) {
1049
+ content += formatAngularEntry(entry, true);
1050
+ }
1051
+ }
1052
+ }
1053
+ content += "\n";
1054
+ }
1055
+ const breakingChanges = changelog.unreleased.filter(
1056
+ (entry) => entry.description.includes("**BREAKING**")
1057
+ );
1058
+ if (breakingChanges.length > 0) {
1059
+ content += "### BREAKING CHANGES\n\n";
1060
+ for (const entry of breakingChanges) {
1061
+ const description = entry.description.replace("**BREAKING** ", "");
1062
+ content += `* ${entry.scope ? `**${entry.scope}:** ` : ""}${description}`;
1063
+ if (entry.issueIds && entry.issueIds.length > 0) {
1064
+ content += ` (${entry.issueIds.join(", ")})`;
1065
+ }
1066
+ content += "\n";
1067
+ }
1068
+ content += "\n";
1069
+ }
1070
+ }
1071
+ for (const version of changelog.versions) {
1072
+ content += `## [${version.version}] - ${version.date}
1073
+
1074
+ `;
1075
+ const groupedByType = groupEntriesByAngularType(version.entries);
1076
+ for (const [type, entries] of Object.entries(groupedByType)) {
1077
+ content += `### ${formatAngularType(type)}
1078
+
1079
+ `;
1080
+ const groupedByScope = groupEntriesByScope2(entries);
1081
+ for (const [scope, scopeEntries] of Object.entries(groupedByScope)) {
1082
+ if (scope !== "undefined" && scope !== "") {
1083
+ content += `* **${scope}:**
1084
+ `;
1085
+ for (const entry of scopeEntries) {
1086
+ content += formatAngularEntry(entry, false);
1087
+ }
1088
+ content += "\n";
1089
+ } else {
1090
+ for (const entry of scopeEntries) {
1091
+ content += formatAngularEntry(entry, true);
1092
+ }
1093
+ }
1094
+ }
1095
+ content += "\n";
1096
+ }
1097
+ const breakingChanges = version.entries.filter(
1098
+ (entry) => entry.description.includes("**BREAKING**")
1099
+ );
1100
+ if (breakingChanges.length > 0) {
1101
+ content += "### BREAKING CHANGES\n\n";
1102
+ for (const entry of breakingChanges) {
1103
+ const description = entry.description.replace("**BREAKING** ", "");
1104
+ content += `* ${entry.scope ? `**${entry.scope}:** ` : ""}${description}`;
1105
+ if (entry.issueIds && entry.issueIds.length > 0) {
1106
+ content += ` (${entry.issueIds.join(", ")})`;
1107
+ }
1108
+ content += "\n";
1109
+ }
1110
+ content += "\n";
1111
+ }
1112
+ }
1113
+ content += generateLinks(changelog, repoUrl);
1114
+ return content;
1115
+ }
1116
+ function groupEntriesByAngularType(entries) {
1117
+ const result = {};
1118
+ for (const entry of entries) {
1119
+ const type = entry.originalType || mapToAngularType(entry.type);
1120
+ if (!result[type]) {
1121
+ result[type] = [];
1122
+ }
1123
+ result[type].push(entry);
1124
+ }
1125
+ return result;
1126
+ }
1127
+ function mapToAngularType(type) {
1128
+ switch (type) {
1129
+ case "added":
1130
+ return "feat";
1131
+ case "fixed":
1132
+ return "fix";
1133
+ case "changed":
1134
+ return "perf";
1135
+ case "deprecated":
1136
+ case "removed":
1137
+ case "security":
1138
+ return type;
1139
+ default:
1140
+ return type;
1141
+ }
1142
+ }
1143
+ function formatAngularType(type) {
1144
+ switch (type) {
1145
+ case "feat":
1146
+ return "Features";
1147
+ case "fix":
1148
+ return "Bug Fixes";
1149
+ case "perf":
1150
+ return "Performance Improvements";
1151
+ case "security":
1152
+ return "Security";
1153
+ case "deprecated":
1154
+ return "Deprecated";
1155
+ case "removed":
1156
+ return "Removed";
1157
+ default:
1158
+ return capitalizeFirstLetter(type);
1159
+ }
1160
+ }
1161
+ function groupEntriesByScope2(entries) {
1162
+ const result = {};
1163
+ for (const entry of entries) {
1164
+ const scope = entry.scope || "";
1165
+ if (!result[scope]) {
1166
+ result[scope] = [];
1167
+ }
1168
+ result[scope].push(entry);
1169
+ }
1170
+ return result;
1171
+ }
1172
+ function formatAngularEntry(entry, includeScope) {
1173
+ let result = " * ";
1174
+ if (includeScope && entry.scope) {
1175
+ result += `**${entry.scope}:** `;
1176
+ }
1177
+ let description = entry.description;
1178
+ if (!includeScope && entry.scope && description.startsWith(`**${entry.scope}**: `)) {
1179
+ description = description.substring(`**${entry.scope}**: `.length);
1180
+ }
1181
+ if (description.startsWith("**BREAKING** ")) {
1182
+ description = description.substring("**BREAKING** ".length);
1183
+ }
1184
+ result += description;
1185
+ if (entry.issueIds && entry.issueIds.length > 0) {
1186
+ result += ` (${entry.issueIds.join(", ")})`;
1187
+ }
1188
+ result += "\n";
1189
+ return result;
1190
+ }
1191
+ function generateChangelogContent(changelog, repoUrl, format = "keep-a-changelog") {
1192
+ if (format === "angular") {
1193
+ return generateAngularChangelogContent(changelog, repoUrl);
1194
+ }
1195
+ let content = "# Changelog\n\n";
1196
+ content += `All notable changes to ${changelog.projectName} will be documented in this file.
1197
+
1198
+ `;
1199
+ content += "The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),\n";
1200
+ content += "and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n";
1201
+ if (changelog.unreleased.length > 0) {
1202
+ content += "## [Unreleased]\n\n";
1203
+ const grouped = changelog.unreleased.reduce(
1204
+ (acc, entry) => {
1205
+ if (!acc[entry.type]) {
1206
+ acc[entry.type] = [];
1207
+ }
1208
+ acc[entry.type].push(entry);
1209
+ return acc;
1210
+ },
1211
+ {}
1212
+ );
1213
+ for (const [type, entries] of Object.entries(grouped)) {
1214
+ content += `### ${capitalizeFirstLetter(type)}
1215
+
1216
+ `;
1217
+ for (const entry of entries) {
1218
+ let entryText = `- ${entry.description}`;
1219
+ if (entry.issueIds && entry.issueIds.length > 0) {
1220
+ entryText += ` (${entry.issueIds.join(", ")})`;
1221
+ }
1222
+ content += `${entryText}.
1223
+ `;
1224
+ }
1225
+ content += "\n";
1226
+ }
1227
+ }
1228
+ for (const version of changelog.versions) {
1229
+ content += `## [${version.version}] - ${version.date}
1230
+
1231
+ `;
1232
+ const grouped = version.entries.reduce(
1233
+ (acc, entry) => {
1234
+ if (!acc[entry.type]) {
1235
+ acc[entry.type] = [];
1236
+ }
1237
+ acc[entry.type].push(entry);
1238
+ return acc;
1239
+ },
1240
+ {}
1241
+ );
1242
+ for (const [type, entries] of Object.entries(grouped)) {
1243
+ content += `### ${capitalizeFirstLetter(type)}
1244
+
1245
+ `;
1246
+ for (const entry of entries) {
1247
+ let entryText = `- ${entry.description}`;
1248
+ if (entry.issueIds && entry.issueIds.length > 0) {
1249
+ entryText += ` (${entry.issueIds.join(", ")})`;
1250
+ }
1251
+ content += `${entryText}.
1252
+ `;
1253
+ }
1254
+ content += "\n";
1255
+ }
1256
+ }
1257
+ content += generateLinks(changelog, repoUrl);
1258
+ return content;
1259
+ }
1260
+ function updateChangelog(packagePath, packageName, version, entries, repoUrl, format = "keep-a-changelog") {
1261
+ try {
1262
+ const changelogPath = path3.join(packagePath, "CHANGELOG.md");
1263
+ let changelog;
1264
+ if (fs5.existsSync(changelogPath)) {
1265
+ const existingChangelog = parseChangelog(changelogPath);
1266
+ if (existingChangelog) {
1267
+ changelog = existingChangelog;
1268
+ } else {
1269
+ changelog = createChangelog(packagePath, packageName);
1270
+ }
1271
+ } else {
1272
+ changelog = createChangelog(packagePath, packageName);
1273
+ }
1274
+ if (version) {
1275
+ const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
1276
+ const newVersion = {
1277
+ version,
1278
+ date: today,
1279
+ entries: [...changelog.unreleased, ...entries]
1280
+ };
1281
+ changelog.unreleased = [];
1282
+ changelog.versions.unshift(newVersion);
1283
+ } else {
1284
+ changelog.unreleased = [...changelog.unreleased, ...entries];
1285
+ }
1286
+ const content = generateChangelogContent(changelog, repoUrl, format);
1287
+ fs5.writeFileSync(changelogPath, content);
1288
+ log(`Updated changelog at ${changelogPath}`, "success");
1289
+ } catch (error) {
1290
+ log(
1291
+ `Error updating changelog: ${error instanceof Error ? error.message : String(error)}`,
1292
+ "error"
1293
+ );
1294
+ }
1295
+ }
1296
+ function capitalizeFirstLetter(input) {
1297
+ return input.charAt(0).toUpperCase() + input.slice(1);
1298
+ }
1299
+
541
1300
  // src/core/versionCalculator.ts
542
1301
  import { cwd as cwd3 } from "node:process";
543
1302
  import { Bumper } from "conventional-recommended-bump";
544
1303
  import semver2 from "semver";
545
1304
 
546
1305
  // src/utils/manifestHelpers.ts
547
- import fs4 from "node:fs";
548
- import path2 from "node:path";
1306
+ import fs6 from "node:fs";
1307
+ import path4 from "node:path";
549
1308
  function getVersionFromManifests(packageDir) {
550
- const packageJsonPath = path2.join(packageDir, "package.json");
551
- const cargoTomlPath = path2.join(packageDir, "Cargo.toml");
552
- if (fs4.existsSync(packageJsonPath)) {
1309
+ const packageJsonPath = path4.join(packageDir, "package.json");
1310
+ const cargoTomlPath = path4.join(packageDir, "Cargo.toml");
1311
+ if (fs6.existsSync(packageJsonPath)) {
553
1312
  try {
554
- const packageJson = JSON.parse(fs4.readFileSync(packageJsonPath, "utf-8"));
1313
+ const packageJson = JSON.parse(fs6.readFileSync(packageJsonPath, "utf-8"));
555
1314
  if (packageJson.version) {
556
1315
  log(`Found version ${packageJson.version} in package.json`, "debug");
557
1316
  return {
@@ -567,7 +1326,7 @@ function getVersionFromManifests(packageDir) {
567
1326
  log(`Error reading package.json: ${errMsg}`, "warning");
568
1327
  }
569
1328
  }
570
- if (fs4.existsSync(cargoTomlPath)) {
1329
+ if (fs6.existsSync(cargoTomlPath)) {
571
1330
  try {
572
1331
  const cargoInfo = getCargoInfo(cargoTomlPath);
573
1332
  if (cargoInfo.version) {
@@ -593,8 +1352,8 @@ function getVersionFromManifests(packageDir) {
593
1352
  };
594
1353
  }
595
1354
  function throwIfNoManifestsFound(packageDir) {
596
- const packageJsonPath = path2.join(packageDir, "package.json");
597
- const cargoTomlPath = path2.join(packageDir, "Cargo.toml");
1355
+ const packageJsonPath = path4.join(packageDir, "package.json");
1356
+ const cargoTomlPath = path4.join(packageDir, "Cargo.toml");
598
1357
  throw new Error(
599
1358
  `Neither package.json nor Cargo.toml found at ${packageDir}. Checked paths: ${packageJsonPath}, ${cargoTomlPath}. Cannot determine version.`
600
1359
  );
@@ -849,7 +1608,7 @@ var PackageProcessor = class {
849
1608
  * Process packages based on targeting criteria
850
1609
  */
851
1610
  async processPackages(packages) {
852
- var _a;
1611
+ var _a, _b, _c, _d, _e;
853
1612
  const tags = [];
854
1613
  const updatedPackagesInfo = [];
855
1614
  if (!packages || !Array.isArray(packages)) {
@@ -934,13 +1693,81 @@ var PackageProcessor = class {
934
1693
  if (!nextVersion) {
935
1694
  continue;
936
1695
  }
937
- const packageJsonPath = path3.join(pkgPath, "package.json");
938
- const cargoTomlPath = path3.join(pkgPath, "Cargo.toml");
939
- if (fs5.existsSync(packageJsonPath)) {
1696
+ if (this.fullConfig.updateChangelog !== false) {
1697
+ let changelogEntries = [];
1698
+ try {
1699
+ changelogEntries = extractChangelogEntriesFromCommits(pkgPath, latestTag);
1700
+ if (changelogEntries.length === 0) {
1701
+ changelogEntries = [
1702
+ {
1703
+ type: "changed",
1704
+ description: `Update version to ${nextVersion}`
1705
+ }
1706
+ ];
1707
+ }
1708
+ } catch (error) {
1709
+ log(
1710
+ `Error extracting changelog entries: ${error instanceof Error ? error.message : String(error)}`,
1711
+ "warning"
1712
+ );
1713
+ changelogEntries = [
1714
+ {
1715
+ type: "changed",
1716
+ description: `Update version to ${nextVersion}`
1717
+ }
1718
+ ];
1719
+ }
1720
+ let repoUrl;
1721
+ try {
1722
+ const packageJsonPath2 = path5.join(pkgPath, "package.json");
1723
+ if (fs7.existsSync(packageJsonPath2)) {
1724
+ const packageJson = JSON.parse(fs7.readFileSync(packageJsonPath2, "utf8"));
1725
+ if (packageJson.repository) {
1726
+ if (typeof packageJson.repository === "string") {
1727
+ repoUrl = packageJson.repository;
1728
+ } else if (packageJson.repository.url) {
1729
+ repoUrl = packageJson.repository.url;
1730
+ }
1731
+ if ((repoUrl == null ? void 0 : repoUrl.startsWith("git+")) && (repoUrl == null ? void 0 : repoUrl.endsWith(".git"))) {
1732
+ repoUrl = repoUrl.substring(4, repoUrl.length - 4);
1733
+ }
1734
+ }
1735
+ }
1736
+ } catch (error) {
1737
+ log(
1738
+ `Could not determine repository URL for changelog links: ${error instanceof Error ? error.message : String(error)}`,
1739
+ "warning"
1740
+ );
1741
+ }
1742
+ updateChangelog(
1743
+ pkgPath,
1744
+ name,
1745
+ nextVersion,
1746
+ changelogEntries,
1747
+ repoUrl,
1748
+ this.fullConfig.changelogFormat
1749
+ );
1750
+ }
1751
+ const packageJsonPath = path5.join(pkgPath, "package.json");
1752
+ if (fs7.existsSync(packageJsonPath)) {
940
1753
  updatePackageVersion(packageJsonPath, nextVersion);
941
1754
  }
942
- if (fs5.existsSync(cargoTomlPath)) {
943
- updatePackageVersion(cargoTomlPath, nextVersion);
1755
+ const cargoEnabled = ((_a = this.fullConfig.cargo) == null ? void 0 : _a.enabled) !== false;
1756
+ if (cargoEnabled) {
1757
+ const cargoPaths = (_b = this.fullConfig.cargo) == null ? void 0 : _b.paths;
1758
+ if (cargoPaths && cargoPaths.length > 0) {
1759
+ for (const cargoPath of cargoPaths) {
1760
+ const resolvedCargoPath = path5.resolve(pkgPath, cargoPath, "Cargo.toml");
1761
+ if (fs7.existsSync(resolvedCargoPath)) {
1762
+ updatePackageVersion(resolvedCargoPath, nextVersion);
1763
+ }
1764
+ }
1765
+ } else {
1766
+ const cargoTomlPath = path5.join(pkgPath, "Cargo.toml");
1767
+ if (fs7.existsSync(cargoTomlPath)) {
1768
+ updatePackageVersion(cargoTomlPath, nextVersion);
1769
+ }
1770
+ }
944
1771
  }
945
1772
  const packageTag = formatTag(
946
1773
  nextVersion,
@@ -972,9 +1799,32 @@ var PackageProcessor = class {
972
1799
  log("No targeted packages required a version update.", "info");
973
1800
  return { updatedPackages: [], tags };
974
1801
  }
975
- const filesToCommit = updatedPackagesInfo.map((info) => path3.join(info.path, "package.json"));
1802
+ const filesToCommit = [];
1803
+ for (const info of updatedPackagesInfo) {
1804
+ const packageJsonPath = path5.join(info.path, "package.json");
1805
+ if (fs7.existsSync(packageJsonPath)) {
1806
+ filesToCommit.push(packageJsonPath);
1807
+ }
1808
+ const cargoEnabled = ((_c = this.fullConfig.cargo) == null ? void 0 : _c.enabled) !== false;
1809
+ if (cargoEnabled) {
1810
+ const cargoPaths = (_d = this.fullConfig.cargo) == null ? void 0 : _d.paths;
1811
+ if (cargoPaths && cargoPaths.length > 0) {
1812
+ for (const cargoPath of cargoPaths) {
1813
+ const resolvedCargoPath = path5.resolve(info.path, cargoPath, "Cargo.toml");
1814
+ if (fs7.existsSync(resolvedCargoPath)) {
1815
+ filesToCommit.push(resolvedCargoPath);
1816
+ }
1817
+ }
1818
+ } else {
1819
+ const cargoTomlPath = path5.join(info.path, "Cargo.toml");
1820
+ if (fs7.existsSync(cargoTomlPath)) {
1821
+ filesToCommit.push(cargoTomlPath);
1822
+ }
1823
+ }
1824
+ }
1825
+ }
976
1826
  const packageNames = updatedPackagesInfo.map((p) => p.name).join(", ");
977
- const representativeVersion = ((_a = updatedPackagesInfo[0]) == null ? void 0 : _a.version) || "multiple";
1827
+ const representativeVersion = ((_e = updatedPackagesInfo[0]) == null ? void 0 : _e.version) || "multiple";
978
1828
  let commitMessage = this.commitMessageTemplate || "chore(release): publish packages";
979
1829
  const placeholderRegex = /\$\{[^}]+\}/;
980
1830
  if (updatedPackagesInfo.length === 1 && placeholderRegex.test(commitMessage)) {
@@ -1051,20 +1901,21 @@ function createSyncedStrategy(config) {
1051
1901
  const files = [];
1052
1902
  const updatedPackages = [];
1053
1903
  try {
1054
- const rootPkgPath = path4.join(packages.root, "package.json");
1055
- if (fs6.existsSync(rootPkgPath)) {
1904
+ const rootPkgPath = path6.join(packages.root, "package.json");
1905
+ if (fs8.existsSync(rootPkgPath)) {
1056
1906
  updatePackageVersion(rootPkgPath, nextVersion);
1057
1907
  files.push(rootPkgPath);
1058
1908
  updatedPackages.push("root");
1059
1909
  }
1060
- } catch (_error) {
1061
- log("Failed to update root package.json", "error");
1910
+ } catch (error) {
1911
+ const errMessage = error instanceof Error ? error.message : String(error);
1912
+ log(`Failed to update root package.json: ${errMessage}`, "error");
1062
1913
  }
1063
1914
  for (const pkg of packages.packages) {
1064
1915
  if (!shouldProcessPackage(pkg, config)) {
1065
1916
  continue;
1066
1917
  }
1067
- const packageJsonPath = path4.join(pkg.dir, "package.json");
1918
+ const packageJsonPath = path6.join(pkg.dir, "package.json");
1068
1919
  updatePackageVersion(packageJsonPath, nextVersion);
1069
1920
  files.push(packageJsonPath);
1070
1921
  updatedPackages.push(pkg.packageJson.name);
@@ -1137,7 +1988,7 @@ function createSingleStrategy(config) {
1137
1988
  log(`No version change needed for ${packageName}`, "info");
1138
1989
  return;
1139
1990
  }
1140
- const packageJsonPath = path4.join(pkgPath, "package.json");
1991
+ const packageJsonPath = path6.join(pkgPath, "package.json");
1141
1992
  updatePackageVersion(packageJsonPath, nextVersion);
1142
1993
  log(`Updated package ${packageName} to version ${nextVersion}`, "success");
1143
1994
  const nextTag = formatTag(
@@ -1315,11 +2166,11 @@ var VersionEngine = class {
1315
2166
  // src/index.ts
1316
2167
  function getPackageVersion() {
1317
2168
  try {
1318
- const packageJsonPath = path5.resolve(
1319
- path5.dirname(import.meta.url.replace("file:", "")),
2169
+ const packageJsonPath = path7.resolve(
2170
+ path7.dirname(import.meta.url.replace("file:", "")),
1320
2171
  "../package.json"
1321
2172
  );
1322
- const packageJsonContent = fs7.readFileSync(packageJsonPath, "utf-8");
2173
+ const packageJsonContent = fs9.readFileSync(packageJsonPath, "utf-8");
1323
2174
  const packageJson = JSON.parse(packageJsonContent);
1324
2175
  return packageJson.version || "0.0.0";
1325
2176
  } catch (error) {
@@ -1328,53 +2179,94 @@ function getPackageVersion() {
1328
2179
  }
1329
2180
  }
1330
2181
  async function run() {
1331
- const buildTimestamp = (/* @__PURE__ */ new Date()).toISOString();
1332
- const packageVersion = getPackageVersion();
1333
- log(`package-versioner v${packageVersion} (Build: ${buildTimestamp})`, "debug");
1334
- const program = new Command();
1335
- program.name("package-versioner").description(
1336
- "A lightweight yet powerful CLI tool for automated semantic versioning based on Git history and conventional commits."
1337
- ).version(packageVersion).option(
1338
- "-c, --config <path>",
1339
- "Path to config file (defaults to version.config.json in current directory)"
1340
- ).option("-d, --dry-run", "Dry run (no changes made)", false).option("-b, --bump <type>", "Specify bump type (patch|minor|major)").option("-p, --prerelease [identifier]", "Create prerelease version").option("-s, --synced", "Use synchronized versioning across all packages").option("-j, --json", "Output results as JSON", false).option("-t, --target <packages>", "Comma-delimited list of package names to target").parse(process.argv);
1341
- const options = program.opts();
1342
- if (options.json) {
1343
- enableJsonOutput(options.dryRun);
1344
- }
1345
2182
  try {
1346
- const config = await loadConfig(options.config);
1347
- log(`Loaded configuration from ${options.config || "version.config.json"}`, "info");
1348
- if (options.dryRun) config.dryRun = true;
1349
- if (options.synced) config.synced = true;
1350
- if (options.bump) config.type = options.bump;
1351
- if (options.prerelease)
1352
- config.prereleaseIdentifier = options.prerelease === true ? "next" : options.prerelease;
1353
- const cliTargets = options.target ? options.target.split(",").map((t) => t.trim()) : [];
1354
- const engine = new VersionEngine(config, !!options.json);
1355
- if (config.synced) {
1356
- log("Using synced versioning strategy.", "info");
1357
- engine.setStrategy("synced");
1358
- await engine.run();
1359
- } else if (config.packages && config.packages.length === 1) {
1360
- log("Using single package versioning strategy.", "info");
1361
- if (cliTargets.length > 0) {
1362
- log("--target flag is ignored for single package strategy.", "warning");
1363
- }
1364
- engine.setStrategy("single");
1365
- await engine.run();
1366
- } else {
1367
- log("Using async versioning strategy.", "info");
1368
- if (cliTargets.length > 0) {
1369
- log(`Targeting specific packages: ${cliTargets.join(", ")}`, "info");
2183
+ const buildTimestamp = (/* @__PURE__ */ new Date()).toISOString();
2184
+ const packageVersion = getPackageVersion();
2185
+ log(`package-versioner v${packageVersion} (Build: ${buildTimestamp})`, "debug");
2186
+ const program = new Command();
2187
+ program.name("package-versioner").description(
2188
+ "A lightweight yet powerful CLI tool for automated semantic versioning based on Git history and conventional commits."
2189
+ ).version(packageVersion);
2190
+ program.command("version", { isDefault: true }).description("Version a package or packages based on configuration").option(
2191
+ "-c, --config <path>",
2192
+ "Path to config file (defaults to version.config.json in current directory)"
2193
+ ).option("-d, --dry-run", "Dry run (no changes made)", false).option("-b, --bump <type>", "Specify bump type (patch|minor|major)").option("-p, --prerelease [identifier]", "Create prerelease version").option("-s, --synced", "Use synchronized versioning across all packages").option("-j, --json", "Output results as JSON", false).option("-t, --target <packages>", "Comma-delimited list of package names to target").action(async (options) => {
2194
+ if (options.json) {
2195
+ enableJsonOutput(options.dryRun);
1370
2196
  }
1371
- engine.setStrategy("async");
1372
- await engine.run(cliTargets);
1373
- }
1374
- log("Versioning process completed.", "success");
1375
- printJsonOutput();
2197
+ try {
2198
+ const config = await loadConfig(options.config);
2199
+ log(`Loaded configuration from ${options.config || "version.config.json"}`, "info");
2200
+ if (options.dryRun) config.dryRun = true;
2201
+ if (options.synced) config.synced = true;
2202
+ if (options.bump) config.type = options.bump;
2203
+ if (options.prerelease)
2204
+ config.prereleaseIdentifier = options.prerelease === true ? "next" : options.prerelease;
2205
+ const cliTargets = options.target ? options.target.split(",").map((t) => t.trim()) : [];
2206
+ const engine = new VersionEngine(config, !!options.json);
2207
+ if (config.synced) {
2208
+ log("Using synced versioning strategy.", "info");
2209
+ engine.setStrategy("synced");
2210
+ await engine.run();
2211
+ } else if (config.packages && config.packages.length === 1) {
2212
+ log("Using single package versioning strategy.", "info");
2213
+ if (cliTargets.length > 0) {
2214
+ log("--target flag is ignored for single package strategy.", "warning");
2215
+ }
2216
+ engine.setStrategy("single");
2217
+ await engine.run();
2218
+ } else {
2219
+ log("Using async versioning strategy.", "info");
2220
+ if (cliTargets.length > 0) {
2221
+ log(`Targeting specific packages: ${cliTargets.join(", ")}`, "info");
2222
+ }
2223
+ engine.setStrategy("async");
2224
+ await engine.run(cliTargets);
2225
+ }
2226
+ log("Versioning process completed.", "success");
2227
+ printJsonOutput();
2228
+ } catch (error) {
2229
+ log(error instanceof Error ? error.message : String(error), "error");
2230
+ process.exit(1);
2231
+ }
2232
+ });
2233
+ program.command("regenerate-changelog").description("Regenerate a complete changelog from git history").option("-o, --output <path>", "Output path for changelog file", "CHANGELOG.md").option(
2234
+ "-f, --format <format>",
2235
+ "Changelog format (keep-a-changelog|angular)",
2236
+ "keep-a-changelog"
2237
+ ).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) => {
2238
+ try {
2239
+ log("Regenerating changelog from git history...", "info");
2240
+ if (options.format !== "keep-a-changelog" && options.format !== "angular") {
2241
+ throw new Error(
2242
+ 'Invalid format specified. Must be either "keep-a-changelog" or "angular"'
2243
+ );
2244
+ }
2245
+ const regenerateOptions = {
2246
+ format: options.format,
2247
+ since: options.since,
2248
+ output: options.output,
2249
+ dryRun: options.dryRun,
2250
+ projectDir: options.projectDir,
2251
+ repoUrl: options.repoUrl
2252
+ };
2253
+ const content = await regenerateChangelog(regenerateOptions);
2254
+ await writeChangelog(
2255
+ content,
2256
+ path7.resolve(options.projectDir, options.output),
2257
+ options.dryRun
2258
+ );
2259
+ if (!options.dryRun) {
2260
+ log(`Changelog successfully regenerated at ${options.output}`, "success");
2261
+ }
2262
+ } catch (error) {
2263
+ log(error instanceof Error ? error.message : String(error), "error");
2264
+ process.exit(1);
2265
+ }
2266
+ });
2267
+ program.parse(process.argv);
1376
2268
  } catch (error) {
1377
- log(error instanceof Error ? error.message : String(error), "error");
2269
+ console.error("Fatal error:", error);
1378
2270
  process.exit(1);
1379
2271
  }
1380
2272
  }