package-versioner 0.6.4 → 0.7.1

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.cjs CHANGED
@@ -34,79 +34,14 @@ __export(index_exports, {
34
34
  run: () => run
35
35
  });
36
36
  module.exports = __toCommonJS(index_exports);
37
- var fs8 = __toESM(require("fs"), 1);
38
- var import_node_path6 = __toESM(require("path"), 1);
37
+ var fs10 = __toESM(require("fs"), 1);
38
+ var import_node_path7 = __toESM(require("path"), 1);
39
39
  var import_commander = require("commander");
40
40
 
41
- // src/config.ts
42
- var fs = __toESM(require("fs"), 1);
43
- var import_node_process = require("process");
44
- function loadConfig(configPath) {
45
- const localProcess = (0, import_node_process.cwd)();
46
- const filePath = configPath || `${localProcess}/version.config.json`;
47
- return new Promise((resolve, reject) => {
48
- fs.readFile(filePath, "utf-8", (err, data) => {
49
- if (err) {
50
- reject(new Error(`Could not locate the config file at ${filePath}: ${err.message}`));
51
- return;
52
- }
53
- try {
54
- const config = JSON.parse(data);
55
- resolve(config);
56
- } catch (err2) {
57
- const errorMessage = err2 instanceof Error ? err2.message : String(err2);
58
- reject(new Error(`Failed to parse config file ${filePath}: ${errorMessage}`));
59
- }
60
- });
61
- });
62
- }
63
-
64
- // src/core/versionEngine.ts
65
- var import_node_process5 = require("process");
66
- var import_get_packages = require("@manypkg/get-packages");
67
-
68
- // src/errors/gitError.ts
69
- var GitError = class extends Error {
70
- constructor(message, code) {
71
- super(message);
72
- this.code = code;
73
- this.name = "GitError";
74
- }
75
- };
76
- function createGitError(code, details) {
77
- const messages = {
78
- ["NOT_GIT_REPO" /* NOT_GIT_REPO */]: "Not a git repository",
79
- ["GIT_PROCESS_ERROR" /* GIT_PROCESS_ERROR */]: "Failed to create new version",
80
- ["NO_FILES" /* NO_FILES */]: "No files specified for commit",
81
- ["NO_COMMIT_MESSAGE" /* NO_COMMIT_MESSAGE */]: "Commit message is required",
82
- ["GIT_ERROR" /* GIT_ERROR */]: "Git operation failed"
83
- };
84
- const baseMessage = messages[code];
85
- const fullMessage = details ? `${baseMessage}: ${details}` : baseMessage;
86
- return new GitError(fullMessage, code);
87
- }
88
-
89
- // src/errors/versionError.ts
90
- var VersionError = class extends Error {
91
- constructor(message, code) {
92
- super(message);
93
- this.code = code;
94
- this.name = "VersionError";
95
- }
96
- };
97
- function createVersionError(code, details) {
98
- const messages = {
99
- ["CONFIG_REQUIRED" /* CONFIG_REQUIRED */]: "Configuration is required",
100
- ["PACKAGES_NOT_FOUND" /* PACKAGES_NOT_FOUND */]: "Failed to get packages information",
101
- ["WORKSPACE_ERROR" /* WORKSPACE_ERROR */]: "Failed to get workspace packages",
102
- ["INVALID_CONFIG" /* INVALID_CONFIG */]: "Invalid configuration",
103
- ["PACKAGE_NOT_FOUND" /* PACKAGE_NOT_FOUND */]: "Package not found",
104
- ["VERSION_CALCULATION_ERROR" /* VERSION_CALCULATION_ERROR */]: "Failed to calculate version"
105
- };
106
- const baseMessage = messages[code];
107
- const fullMessage = details ? `${baseMessage}: ${details}` : baseMessage;
108
- return new VersionError(fullMessage, code);
109
- }
41
+ // src/changelog/changelogRegenerator.ts
42
+ var import_node_child_process2 = require("child_process");
43
+ var import_node_fs = __toESM(require("fs"), 1);
44
+ var import_node_path = __toESM(require("path"), 1);
110
45
 
111
46
  // src/utils/logging.ts
112
47
  var import_chalk = __toESM(require("chalk"), 1);
@@ -189,19 +124,518 @@ function log(message, level = "info") {
189
124
  }
190
125
  }
191
126
 
127
+ // src/changelog/commitParser.ts
128
+ var import_node_child_process = require("child_process");
129
+ var CONVENTIONAL_COMMIT_REGEX = /^(\w+)(?:\(([^)]+)\))?(!)?: (.+)(?:\n\n([\s\S]*))?/;
130
+ var BREAKING_CHANGE_REGEX = /BREAKING CHANGE: ([\s\S]+?)(?:\n\n|$)/;
131
+ function extractChangelogEntriesFromCommits(projectDir, revisionRange) {
132
+ try {
133
+ const command = `git log ${revisionRange} --pretty=format:"%B---COMMIT_DELIMITER---" --no-merges`;
134
+ const output = (0, import_node_child_process.execSync)(command, {
135
+ cwd: projectDir,
136
+ encoding: "utf8"
137
+ });
138
+ const commits = output.split("---COMMIT_DELIMITER---").filter((commit) => commit.trim() !== "");
139
+ return commits.map((commit) => parseCommitMessage(commit)).filter((entry) => entry !== null);
140
+ } catch (error) {
141
+ log(`Error extracting commits: ${error}`, "error");
142
+ return [];
143
+ }
144
+ }
145
+ function parseCommitMessage(message) {
146
+ const match = message.match(CONVENTIONAL_COMMIT_REGEX);
147
+ if (match) {
148
+ const [, type, scope, breakingMark, subject, body = ""] = match;
149
+ const breakingFromMark = breakingMark === "!";
150
+ const breakingChangeMatch = body.match(BREAKING_CHANGE_REGEX);
151
+ const hasBreakingChange = breakingFromMark || breakingChangeMatch !== null;
152
+ const changelogType = mapCommitTypeToChangelogType(type);
153
+ if (!changelogType) {
154
+ return null;
155
+ }
156
+ const issueIds = extractIssueIds(body);
157
+ let description = subject;
158
+ if (hasBreakingChange) {
159
+ description = `**BREAKING** ${description}`;
160
+ }
161
+ return {
162
+ type: changelogType,
163
+ description,
164
+ scope: scope || void 0,
165
+ issueIds: issueIds.length > 0 ? issueIds : void 0,
166
+ originalType: type
167
+ // Store original type for custom formatting
168
+ };
169
+ }
170
+ if (!message.startsWith("Merge") && !message.match(/^v?\d+\.\d+\.\d+/)) {
171
+ const firstLine = message.split("\n")[0].trim();
172
+ return {
173
+ type: "changed",
174
+ description: firstLine
175
+ };
176
+ }
177
+ return null;
178
+ }
179
+ function mapCommitTypeToChangelogType(type) {
180
+ switch (type) {
181
+ case "feat":
182
+ return "added";
183
+ case "fix":
184
+ return "fixed";
185
+ case "docs":
186
+ case "style":
187
+ case "refactor":
188
+ case "perf":
189
+ case "build":
190
+ case "ci":
191
+ return "changed";
192
+ case "revert":
193
+ return "removed";
194
+ case "chore":
195
+ return "changed";
196
+ case "test":
197
+ return null;
198
+ default:
199
+ return "changed";
200
+ }
201
+ }
202
+ function extractIssueIds(body) {
203
+ const issueRegex = /(?:fix|fixes|close|closes|resolve|resolves)\s+#(\d+)/gi;
204
+ const issueIds = [];
205
+ let match = issueRegex.exec(body);
206
+ while (match !== null) {
207
+ issueIds.push(`#${match[1]}`);
208
+ match = issueRegex.exec(body);
209
+ }
210
+ return issueIds;
211
+ }
212
+
213
+ // src/changelog/formatters.ts
214
+ function formatChangelogEntries(format, version, date, entries, packageName, repoUrl) {
215
+ const formattingEntries = entries.map((entry) => {
216
+ const hasBreaking = entry.description.includes("**BREAKING**");
217
+ return {
218
+ ...entry,
219
+ breaking: hasBreaking
220
+ };
221
+ });
222
+ return format === "keep-a-changelog" ? formatKeepAChangelogEntries(version, date, formattingEntries, repoUrl) : formatAngularEntries(version, date, formattingEntries, packageName);
223
+ }
224
+ function formatKeepAChangelogEntries(version, date, entries, repoUrl) {
225
+ const added = [];
226
+ const changed = [];
227
+ const deprecated = [];
228
+ const removed = [];
229
+ const fixed = [];
230
+ const security = [];
231
+ for (const entry of entries) {
232
+ const entryText = entry.scope ? `- **${entry.scope}**: ${entry.description}` : `- ${entry.description}`;
233
+ const formattedEntry = entry.breaking ? entryText.replace(/^- /, "- **BREAKING** ") : entryText;
234
+ const entryType = entry.originalType || entry.type;
235
+ switch (entryType) {
236
+ case "feat":
237
+ added.push(formattedEntry);
238
+ break;
239
+ case "fix":
240
+ fixed.push(formattedEntry);
241
+ break;
242
+ case "docs":
243
+ case "style":
244
+ case "refactor":
245
+ case "perf":
246
+ case "build":
247
+ case "ci":
248
+ changed.push(formattedEntry);
249
+ break;
250
+ case "test":
251
+ break;
252
+ case "chore":
253
+ if (entry.description.toLowerCase().includes("deprecat")) {
254
+ deprecated.push(formattedEntry);
255
+ } else {
256
+ changed.push(formattedEntry);
257
+ }
258
+ break;
259
+ // Keep-a-changelog standard types
260
+ case "added":
261
+ added.push(formattedEntry);
262
+ break;
263
+ case "changed":
264
+ changed.push(formattedEntry);
265
+ break;
266
+ case "deprecated":
267
+ deprecated.push(formattedEntry);
268
+ break;
269
+ case "removed":
270
+ removed.push(formattedEntry);
271
+ break;
272
+ case "fixed":
273
+ fixed.push(formattedEntry);
274
+ break;
275
+ case "security":
276
+ security.push(formattedEntry);
277
+ break;
278
+ default:
279
+ changed.push(formattedEntry);
280
+ }
281
+ }
282
+ let content = `## [${version}] - ${date}
283
+
284
+ `;
285
+ if (added.length > 0) {
286
+ content += `### Added
287
+
288
+ ${added.join("\n")}
289
+
290
+ `;
291
+ }
292
+ if (changed.length > 0) {
293
+ content += `### Changed
294
+
295
+ ${changed.join("\n")}
296
+
297
+ `;
298
+ }
299
+ if (deprecated.length > 0) {
300
+ content += `### Deprecated
301
+
302
+ ${deprecated.join("\n")}
303
+
304
+ `;
305
+ }
306
+ if (removed.length > 0) {
307
+ content += `### Removed
308
+
309
+ ${removed.join("\n")}
310
+
311
+ `;
312
+ }
313
+ if (fixed.length > 0) {
314
+ content += `### Fixed
315
+
316
+ ${fixed.join("\n")}
317
+
318
+ `;
319
+ }
320
+ if (security.length > 0) {
321
+ content += `### Security
322
+
323
+ ${security.join("\n")}
324
+
325
+ `;
326
+ }
327
+ if (repoUrl) {
328
+ content += `[${version}]: ${repoUrl}/compare/v${version}...HEAD
329
+ `;
330
+ }
331
+ return content.trim();
332
+ }
333
+ function formatAngularEntries(version, date, entries, packageName) {
334
+ const features = [];
335
+ const bugfixes = [];
336
+ const performance = [];
337
+ const breaking = [];
338
+ for (const entry of entries) {
339
+ if (entry.breaking) {
340
+ breaking.push(entry);
341
+ }
342
+ const entryType = entry.originalType || entry.type;
343
+ switch (entryType) {
344
+ case "feat":
345
+ case "added":
346
+ features.push(entry);
347
+ break;
348
+ case "fix":
349
+ case "fixed":
350
+ bugfixes.push(entry);
351
+ break;
352
+ case "perf":
353
+ performance.push(entry);
354
+ break;
355
+ }
356
+ }
357
+ let content = `## [${version}]${packageName ? ` (${packageName})` : ""} (${date})
358
+
359
+ `;
360
+ if (features.length > 0) {
361
+ content += "### Features\n\n";
362
+ content += formatAngularTypeEntries(features);
363
+ content += "\n";
364
+ }
365
+ if (bugfixes.length > 0) {
366
+ content += "### Bug Fixes\n\n";
367
+ content += formatAngularTypeEntries(bugfixes);
368
+ content += "\n";
369
+ }
370
+ if (performance.length > 0) {
371
+ content += "### Performance Improvements\n\n";
372
+ content += formatAngularTypeEntries(performance);
373
+ content += "\n";
374
+ }
375
+ if (breaking.length > 0) {
376
+ content += "### BREAKING CHANGES\n\n";
377
+ content += formatAngularTypeEntries(breaking);
378
+ content += "\n";
379
+ }
380
+ return content.trim();
381
+ }
382
+ function formatAngularTypeEntries(entries) {
383
+ var _a;
384
+ const entriesByScope = /* @__PURE__ */ new Map();
385
+ for (const entry of entries) {
386
+ const scope = entry.scope || "";
387
+ if (!entriesByScope.has(scope)) {
388
+ entriesByScope.set(scope, []);
389
+ }
390
+ (_a = entriesByScope.get(scope)) == null ? void 0 : _a.push(entry);
391
+ }
392
+ const result = [];
393
+ for (const [scope, scopeEntries] of Object.entries(groupEntriesByScope(entries))) {
394
+ if (scope !== "undefined" && scope !== "") {
395
+ result.push(`* **${scope}:**`);
396
+ for (const entry of scopeEntries) {
397
+ const description = entry.description.replace("**BREAKING** ", "");
398
+ result.push(` * ${description}`);
399
+ }
400
+ } else {
401
+ for (const entry of scopeEntries) {
402
+ const description = entry.description.replace("**BREAKING** ", "");
403
+ result.push(`* ${description}`);
404
+ }
405
+ }
406
+ }
407
+ return result.join("\n");
408
+ }
409
+ function groupEntriesByScope(entries) {
410
+ const result = {};
411
+ for (const entry of entries) {
412
+ const scope = entry.scope || "";
413
+ if (!result[scope]) {
414
+ result[scope] = [];
415
+ }
416
+ result[scope].push(entry);
417
+ }
418
+ return result;
419
+ }
420
+
421
+ // src/changelog/templates.ts
422
+ function getDefaultTemplate(format) {
423
+ return format === "keep-a-changelog" ? getKeepAChangelogTemplate() : getAngularTemplate();
424
+ }
425
+ function getKeepAChangelogTemplate() {
426
+ return `# Changelog
427
+
428
+ All notable changes to this project will be documented in this file.
429
+
430
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
431
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
432
+
433
+ `;
434
+ }
435
+ function getAngularTemplate() {
436
+ return `# Changelog
437
+
438
+ `;
439
+ }
440
+
441
+ // src/changelog/changelogRegenerator.ts
442
+ function getAllVersionTags(since, versionPrefix = "v") {
443
+ try {
444
+ const command = since ? `git tag --list "${versionPrefix}*" --sort=creatordate --contains ${since}` : `git tag --list "${versionPrefix}*" --sort=creatordate`;
445
+ const tagOutput = (0, import_node_child_process2.execSync)(command, { encoding: "utf8" }).trim();
446
+ if (!tagOutput) {
447
+ return [];
448
+ }
449
+ const tags = tagOutput.split("\n").filter((tag) => !!tag);
450
+ return tags.map((tag) => {
451
+ try {
452
+ const date = (0, import_node_child_process2.execSync)(`git log -1 --format=%ad --date=short ${tag}`, {
453
+ encoding: "utf8"
454
+ }).trim();
455
+ const version = tag.replace(new RegExp(`^${versionPrefix}`), "");
456
+ return { tag, version, date };
457
+ } catch (error) {
458
+ log(`Failed to get date for tag ${tag}: ${error}`, "warning");
459
+ return { tag, version: tag.replace(new RegExp(`^${versionPrefix}`), ""), date: "Unknown" };
460
+ }
461
+ });
462
+ } catch (error) {
463
+ log(`Failed to get version tags: ${error}`, "error");
464
+ return [];
465
+ }
466
+ }
467
+ async function regenerateChangelog(options) {
468
+ const { format, since, projectDir } = options;
469
+ const packageJsonPath = import_node_path.default.join(projectDir, "package.json");
470
+ let packageName = "";
471
+ let repoUrl = options.repoUrl;
472
+ if (import_node_fs.default.existsSync(packageJsonPath)) {
473
+ try {
474
+ const packageJson = JSON.parse(import_node_fs.default.readFileSync(packageJsonPath, "utf8"));
475
+ packageName = packageJson.name || "";
476
+ if (!repoUrl && packageJson.repository) {
477
+ if (typeof packageJson.repository === "string") {
478
+ repoUrl = packageJson.repository;
479
+ } else if (packageJson.repository.url) {
480
+ repoUrl = packageJson.repository.url;
481
+ }
482
+ if ((repoUrl == null ? void 0 : repoUrl.startsWith("git+")) && (repoUrl == null ? void 0 : repoUrl.endsWith(".git"))) {
483
+ repoUrl = repoUrl.substring(4, repoUrl.length - 4);
484
+ }
485
+ }
486
+ } catch (error) {
487
+ log(`Failed to read package.json: ${error}`, "warning");
488
+ }
489
+ }
490
+ let versionPrefix = "v";
491
+ try {
492
+ const allTags = (0, import_node_child_process2.execSync)("git tag --list", { encoding: "utf8" }).trim().split("\n");
493
+ const versionTag = allTags.find((tag) => /^[vV][0-9]/.test(tag));
494
+ if (versionTag) {
495
+ versionPrefix = versionTag.charAt(0);
496
+ }
497
+ } catch {
498
+ }
499
+ const tags = getAllVersionTags(since, versionPrefix);
500
+ if (!tags.length) {
501
+ throw new Error(
502
+ 'No version tags found in git history. Make sure you have tags that start with the version prefix (usually "v").'
503
+ );
504
+ }
505
+ let changelogContent = getDefaultTemplate(format);
506
+ log(`Found ${tags.length} version tags, generating changelog...`, "info");
507
+ const versions = [];
508
+ for (let i = tags.length - 1; i >= 0; i--) {
509
+ const currentTag = tags[i];
510
+ const previousTag = i > 0 ? tags[i - 1].tag : null;
511
+ log(`Processing changes for ${currentTag.tag}...`, "info");
512
+ try {
513
+ const tagRange = previousTag ? `${previousTag}..${currentTag.tag}` : currentTag.tag;
514
+ const entries = extractChangelogEntriesFromCommits(projectDir, tagRange);
515
+ if (!entries.length) {
516
+ log(`No changelog entries found for ${currentTag.tag}, adding placeholder entry`, "info");
517
+ entries.push({
518
+ type: "changed",
519
+ description: `Release version ${currentTag.version}`
520
+ });
521
+ }
522
+ versions.unshift(
523
+ formatChangelogEntries(
524
+ format,
525
+ currentTag.version,
526
+ currentTag.date,
527
+ entries,
528
+ packageName,
529
+ repoUrl
530
+ )
531
+ );
532
+ } catch (error) {
533
+ log(`Failed to process version ${currentTag.tag}: ${error}`, "error");
534
+ }
535
+ }
536
+ changelogContent += versions.join("\n\n");
537
+ return changelogContent;
538
+ }
539
+ async function writeChangelog(content, outputPath, dryRun) {
540
+ if (dryRun) {
541
+ log("--- Changelog Preview ---", "info");
542
+ console.log(content);
543
+ log("--- End Preview ---", "info");
544
+ return;
545
+ }
546
+ try {
547
+ import_node_fs.default.writeFileSync(outputPath, content, "utf8");
548
+ log(`Changelog successfully written to ${outputPath}`, "success");
549
+ } catch (error) {
550
+ throw new Error(
551
+ `Failed to write changelog: ${error instanceof Error ? error.message : String(error)}`
552
+ );
553
+ }
554
+ }
555
+
556
+ // src/config.ts
557
+ var fs2 = __toESM(require("fs"), 1);
558
+ var import_node_process = require("process");
559
+ function loadConfig(configPath) {
560
+ const localProcess = (0, import_node_process.cwd)();
561
+ const filePath = configPath || `${localProcess}/version.config.json`;
562
+ return new Promise((resolve, reject) => {
563
+ fs2.readFile(filePath, "utf-8", (err, data) => {
564
+ if (err) {
565
+ reject(new Error(`Could not locate the config file at ${filePath}: ${err.message}`));
566
+ return;
567
+ }
568
+ try {
569
+ const config = JSON.parse(data);
570
+ resolve(config);
571
+ } catch (err2) {
572
+ const errorMessage = err2 instanceof Error ? err2.message : String(err2);
573
+ reject(new Error(`Failed to parse config file ${filePath}: ${errorMessage}`));
574
+ }
575
+ });
576
+ });
577
+ }
578
+
579
+ // src/core/versionEngine.ts
580
+ var import_node_process5 = require("process");
581
+ var import_get_packages = require("@manypkg/get-packages");
582
+
583
+ // src/errors/gitError.ts
584
+ var GitError = class extends Error {
585
+ constructor(message, code) {
586
+ super(message);
587
+ this.code = code;
588
+ this.name = "GitError";
589
+ }
590
+ };
591
+ function createGitError(code, details) {
592
+ const messages = {
593
+ ["NOT_GIT_REPO" /* NOT_GIT_REPO */]: "Not a git repository",
594
+ ["GIT_PROCESS_ERROR" /* GIT_PROCESS_ERROR */]: "Failed to create new version",
595
+ ["NO_FILES" /* NO_FILES */]: "No files specified for commit",
596
+ ["NO_COMMIT_MESSAGE" /* NO_COMMIT_MESSAGE */]: "Commit message is required",
597
+ ["GIT_ERROR" /* GIT_ERROR */]: "Git operation failed"
598
+ };
599
+ const baseMessage = messages[code];
600
+ const fullMessage = details ? `${baseMessage}: ${details}` : baseMessage;
601
+ return new GitError(fullMessage, code);
602
+ }
603
+
604
+ // src/errors/versionError.ts
605
+ var VersionError = class extends Error {
606
+ constructor(message, code) {
607
+ super(message);
608
+ this.code = code;
609
+ this.name = "VersionError";
610
+ }
611
+ };
612
+ function createVersionError(code, details) {
613
+ const messages = {
614
+ ["CONFIG_REQUIRED" /* CONFIG_REQUIRED */]: "Configuration is required",
615
+ ["PACKAGES_NOT_FOUND" /* PACKAGES_NOT_FOUND */]: "Failed to get packages information",
616
+ ["WORKSPACE_ERROR" /* WORKSPACE_ERROR */]: "Failed to get workspace packages",
617
+ ["INVALID_CONFIG" /* INVALID_CONFIG */]: "Invalid configuration",
618
+ ["PACKAGE_NOT_FOUND" /* PACKAGE_NOT_FOUND */]: "Package not found",
619
+ ["VERSION_CALCULATION_ERROR" /* VERSION_CALCULATION_ERROR */]: "Failed to calculate version"
620
+ };
621
+ const baseMessage = messages[code];
622
+ const fullMessage = details ? `${baseMessage}: ${details}` : baseMessage;
623
+ return new VersionError(fullMessage, code);
624
+ }
625
+
192
626
  // src/core/versionStrategies.ts
193
- var import_node_fs6 = __toESM(require("fs"), 1);
194
- var path5 = __toESM(require("path"), 1);
627
+ var import_node_fs7 = __toESM(require("fs"), 1);
628
+ var path7 = __toESM(require("path"), 1);
195
629
 
196
630
  // src/git/commands.ts
197
631
  var import_node_process2 = require("process");
198
632
 
199
633
  // src/git/commandExecutor.ts
200
- var import_node_child_process = require("child_process");
634
+ var import_node_child_process3 = require("child_process");
201
635
  var execAsync = (command, options) => {
202
636
  const defaultOptions = { maxBuffer: 1024 * 1024 * 10, ...options };
203
637
  return new Promise((resolve, reject) => {
204
- (0, import_node_child_process.exec)(
638
+ (0, import_node_child_process3.exec)(
205
639
  command,
206
640
  defaultOptions,
207
641
  (error, stdout, stderr) => {
@@ -214,29 +648,29 @@ var execAsync = (command, options) => {
214
648
  );
215
649
  });
216
650
  };
217
- var execSync = (command, args) => (0, import_node_child_process.execSync)(command, { maxBuffer: 1024 * 1024 * 10, ...args });
651
+ var execSync3 = (command, args) => (0, import_node_child_process3.execSync)(command, { maxBuffer: 1024 * 1024 * 10, ...args });
218
652
 
219
653
  // src/git/repository.ts
220
- var import_node_fs = require("fs");
221
- var import_node_path = require("path");
654
+ var import_node_fs2 = require("fs");
655
+ var import_node_path2 = require("path");
222
656
  function isGitRepository(directory) {
223
- const gitDir = (0, import_node_path.join)(directory, ".git");
224
- if (!(0, import_node_fs.existsSync)(gitDir)) {
657
+ const gitDir = (0, import_node_path2.join)(directory, ".git");
658
+ if (!(0, import_node_fs2.existsSync)(gitDir)) {
225
659
  return false;
226
660
  }
227
- const stats = (0, import_node_fs.statSync)(gitDir);
661
+ const stats = (0, import_node_fs2.statSync)(gitDir);
228
662
  if (!stats.isDirectory()) {
229
663
  return false;
230
664
  }
231
665
  try {
232
- execSync("git rev-parse --is-inside-work-tree", { cwd: directory });
666
+ execSync3("git rev-parse --is-inside-work-tree", { cwd: directory });
233
667
  return true;
234
668
  } catch (_error) {
235
669
  return false;
236
670
  }
237
671
  }
238
672
  function getCurrentBranch() {
239
- const result = execSync("git rev-parse --abbrev-ref HEAD");
673
+ const result = execSync3("git rev-parse --abbrev-ref HEAD");
240
674
  return result.toString().trim();
241
675
  }
242
676
 
@@ -298,6 +732,11 @@ async function gitProcess(options) {
298
732
  }
299
733
  } catch (err) {
300
734
  const errorMessage = err instanceof Error ? err.message : String(err);
735
+ log(`Git process error: ${errorMessage}`, "error");
736
+ if (err instanceof Error && err.stack) {
737
+ console.error("Git process stack trace:");
738
+ console.error(err.stack);
739
+ }
301
740
  throw createGitError("GIT_PROCESS_ERROR" /* GIT_PROCESS_ERROR */, errorMessage);
302
741
  }
303
742
  }
@@ -327,9 +766,16 @@ async function createGitCommitAndTag(files, nextTag, commitMessage, skipHooks, d
327
766
  const errorMessage = error instanceof Error ? error.message : String(error);
328
767
  log(`Failed to create git commit and tag: ${errorMessage}`, "error");
329
768
  if (error instanceof Error) {
769
+ console.error("Git operation error details:");
330
770
  console.error(error.stack || error.message);
771
+ if (errorMessage.includes("Command failed:")) {
772
+ const cmdOutput = errorMessage.split("Command failed:")[1];
773
+ if (cmdOutput) {
774
+ console.error("Git command output:", cmdOutput.trim());
775
+ }
776
+ }
331
777
  } else {
332
- console.error(error);
778
+ console.error("Unknown git error:", error);
333
779
  }
334
780
  throw new GitError(`Git operation failed: ${errorMessage}`, "GIT_ERROR" /* GIT_ERROR */);
335
781
  }
@@ -380,7 +826,7 @@ function createTemplateString(template, variables) {
380
826
  function getCommitsLength(pkgRoot) {
381
827
  try {
382
828
  const gitCommand = `git rev-list --count HEAD ^$(git describe --tags --abbrev=0) ${pkgRoot}`;
383
- const amount = execSync(gitCommand).toString().trim();
829
+ const amount = execSync3(gitCommand).toString().trim();
384
830
  return Number(amount);
385
831
  } catch (error) {
386
832
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -477,21 +923,21 @@ async function getLatestTagForPackage(packageName, versionPrefix) {
477
923
  }
478
924
 
479
925
  // src/package/packageManagement.ts
480
- var import_node_fs3 = __toESM(require("fs"), 1);
481
- var import_node_path3 = __toESM(require("path"), 1);
926
+ var import_node_fs4 = __toESM(require("fs"), 1);
927
+ var import_node_path4 = __toESM(require("path"), 1);
482
928
 
483
929
  // src/cargo/cargoHandler.ts
484
- var import_node_fs2 = __toESM(require("fs"), 1);
485
- var import_node_path2 = __toESM(require("path"), 1);
930
+ var import_node_fs3 = __toESM(require("fs"), 1);
931
+ var import_node_path3 = __toESM(require("path"), 1);
486
932
  var TOML = __toESM(require("smol-toml"), 1);
487
933
  function getCargoInfo(cargoPath) {
488
934
  var _a;
489
- if (!import_node_fs2.default.existsSync(cargoPath)) {
935
+ if (!import_node_fs3.default.existsSync(cargoPath)) {
490
936
  log(`Cargo.toml file not found at: ${cargoPath}`, "error");
491
937
  throw new Error(`Cargo.toml file not found at: ${cargoPath}`);
492
938
  }
493
939
  try {
494
- const fileContent = import_node_fs2.default.readFileSync(cargoPath, "utf8");
940
+ const fileContent = import_node_fs3.default.readFileSync(cargoPath, "utf8");
495
941
  const cargo = TOML.parse(fileContent);
496
942
  if (!((_a = cargo.package) == null ? void 0 : _a.name)) {
497
943
  log(`Package name not found in: ${cargoPath}`, "error");
@@ -501,7 +947,7 @@ function getCargoInfo(cargoPath) {
501
947
  name: cargo.package.name,
502
948
  version: cargo.package.version || "0.0.0",
503
949
  path: cargoPath,
504
- dir: import_node_path2.default.dirname(cargoPath),
950
+ dir: import_node_path3.default.dirname(cargoPath),
505
951
  content: cargo
506
952
  };
507
953
  } catch (error) {
@@ -514,12 +960,12 @@ function getCargoInfo(cargoPath) {
514
960
  }
515
961
  }
516
962
  function isCargoToml(filePath) {
517
- return import_node_path2.default.basename(filePath) === "Cargo.toml";
963
+ return import_node_path3.default.basename(filePath) === "Cargo.toml";
518
964
  }
519
965
  function updateCargoVersion(cargoPath, version) {
520
966
  var _a;
521
967
  try {
522
- const originalContent = import_node_fs2.default.readFileSync(cargoPath, "utf8");
968
+ const originalContent = import_node_fs3.default.readFileSync(cargoPath, "utf8");
523
969
  const cargo = TOML.parse(originalContent);
524
970
  const packageName = (_a = cargo.package) == null ? void 0 : _a.name;
525
971
  if (!packageName) {
@@ -531,7 +977,7 @@ function updateCargoVersion(cargoPath, version) {
531
977
  cargo.package.version = version;
532
978
  }
533
979
  const updatedContent = TOML.stringify(cargo);
534
- import_node_fs2.default.writeFileSync(cargoPath, updatedContent);
980
+ import_node_fs3.default.writeFileSync(cargoPath, updatedContent);
535
981
  addPackageUpdate(packageName, version, cargoPath);
536
982
  log(`Updated Cargo.toml at ${cargoPath} to version ${version}`, "success");
537
983
  } catch (error) {
@@ -550,11 +996,11 @@ function updatePackageVersion(packagePath, version) {
550
996
  return;
551
997
  }
552
998
  try {
553
- const packageContent = import_node_fs3.default.readFileSync(packagePath, "utf8");
999
+ const packageContent = import_node_fs4.default.readFileSync(packagePath, "utf8");
554
1000
  const packageJson = JSON.parse(packageContent);
555
1001
  const packageName = packageJson.name;
556
1002
  packageJson.version = version;
557
- import_node_fs3.default.writeFileSync(packagePath, `${JSON.stringify(packageJson, null, 2)}
1003
+ import_node_fs4.default.writeFileSync(packagePath, `${JSON.stringify(packageJson, null, 2)}
558
1004
  `);
559
1005
  addPackageUpdate(packageName, version, packagePath);
560
1006
  log(`Updated package.json at ${packagePath} to version ${version}`, "success");
@@ -568,24 +1014,349 @@ function updatePackageVersion(packagePath, version) {
568
1014
  }
569
1015
 
570
1016
  // src/package/packageProcessor.ts
571
- var fs6 = __toESM(require("fs"), 1);
572
- var import_node_path5 = __toESM(require("path"), 1);
1017
+ var fs8 = __toESM(require("fs"), 1);
1018
+ var import_node_path6 = __toESM(require("path"), 1);
573
1019
  var import_node_process4 = require("process");
574
1020
 
1021
+ // src/changelog/changelogManager.ts
1022
+ var fs5 = __toESM(require("fs"), 1);
1023
+ var path4 = __toESM(require("path"), 1);
1024
+ function createChangelog(_packagePath, packageName) {
1025
+ return {
1026
+ projectName: packageName,
1027
+ unreleased: [],
1028
+ versions: []
1029
+ };
1030
+ }
1031
+ function parseChangelog(filePath) {
1032
+ try {
1033
+ if (!fs5.existsSync(filePath)) {
1034
+ return null;
1035
+ }
1036
+ fs5.readFileSync(filePath, "utf8");
1037
+ log(`Parsed changelog at ${filePath}`, "info");
1038
+ return {
1039
+ projectName: path4.basename(path4.dirname(filePath)),
1040
+ unreleased: [],
1041
+ versions: []
1042
+ };
1043
+ } catch (error) {
1044
+ log(
1045
+ `Error parsing changelog: ${error instanceof Error ? error.message : String(error)}`,
1046
+ "error"
1047
+ );
1048
+ return null;
1049
+ }
1050
+ }
1051
+ function generateLinks(changelog, repoUrl) {
1052
+ var _a, _b;
1053
+ if (!repoUrl || changelog.versions.length === 0) {
1054
+ return "";
1055
+ }
1056
+ let links = "\n";
1057
+ if (changelog.unreleased.length > 0) {
1058
+ const latestVersion = ((_a = changelog.versions[0]) == null ? void 0 : _a.version) || "";
1059
+ links += `[unreleased]: ${repoUrl}/compare/v${latestVersion}...HEAD
1060
+ `;
1061
+ }
1062
+ for (let i = 0; i < changelog.versions.length; i++) {
1063
+ const currentVersion = changelog.versions[i].version;
1064
+ const previousVersion = (_b = changelog.versions[i + 1]) == null ? void 0 : _b.version;
1065
+ if (previousVersion) {
1066
+ links += `[${currentVersion}]: ${repoUrl}/compare/v${previousVersion}...v${currentVersion}
1067
+ `;
1068
+ } else if (i === changelog.versions.length - 1) {
1069
+ links += `[${currentVersion}]: ${repoUrl}/releases/tag/v${currentVersion}
1070
+ `;
1071
+ }
1072
+ }
1073
+ return links;
1074
+ }
1075
+ function generateAngularChangelogContent(changelog, repoUrl) {
1076
+ let content = "# Changelog\n\n";
1077
+ if (changelog.unreleased.length > 0) {
1078
+ content += "## [Unreleased]\n\n";
1079
+ const groupedByType = groupEntriesByAngularType(changelog.unreleased);
1080
+ for (const [type, entries] of Object.entries(groupedByType)) {
1081
+ content += `### ${formatAngularType(type)}
1082
+
1083
+ `;
1084
+ const groupedByScope = groupEntriesByScope2(entries);
1085
+ for (const [scope, scopeEntries] of Object.entries(groupedByScope)) {
1086
+ if (scope !== "undefined" && scope !== "") {
1087
+ content += `* **${scope}:**
1088
+ `;
1089
+ for (const entry of scopeEntries) {
1090
+ content += formatAngularEntry(entry, false);
1091
+ }
1092
+ content += "\n";
1093
+ } else {
1094
+ for (const entry of scopeEntries) {
1095
+ content += formatAngularEntry(entry, true);
1096
+ }
1097
+ }
1098
+ }
1099
+ content += "\n";
1100
+ }
1101
+ const breakingChanges = changelog.unreleased.filter(
1102
+ (entry) => entry.description.includes("**BREAKING**")
1103
+ );
1104
+ if (breakingChanges.length > 0) {
1105
+ content += "### BREAKING CHANGES\n\n";
1106
+ for (const entry of breakingChanges) {
1107
+ const description = entry.description.replace("**BREAKING** ", "");
1108
+ content += `* ${entry.scope ? `**${entry.scope}:** ` : ""}${description}`;
1109
+ if (entry.issueIds && entry.issueIds.length > 0) {
1110
+ content += ` (${entry.issueIds.join(", ")})`;
1111
+ }
1112
+ content += "\n";
1113
+ }
1114
+ content += "\n";
1115
+ }
1116
+ }
1117
+ for (const version of changelog.versions) {
1118
+ content += `## [${version.version}] - ${version.date}
1119
+
1120
+ `;
1121
+ const groupedByType = groupEntriesByAngularType(version.entries);
1122
+ for (const [type, entries] of Object.entries(groupedByType)) {
1123
+ content += `### ${formatAngularType(type)}
1124
+
1125
+ `;
1126
+ const groupedByScope = groupEntriesByScope2(entries);
1127
+ for (const [scope, scopeEntries] of Object.entries(groupedByScope)) {
1128
+ if (scope !== "undefined" && scope !== "") {
1129
+ content += `* **${scope}:**
1130
+ `;
1131
+ for (const entry of scopeEntries) {
1132
+ content += formatAngularEntry(entry, false);
1133
+ }
1134
+ content += "\n";
1135
+ } else {
1136
+ for (const entry of scopeEntries) {
1137
+ content += formatAngularEntry(entry, true);
1138
+ }
1139
+ }
1140
+ }
1141
+ content += "\n";
1142
+ }
1143
+ const breakingChanges = version.entries.filter(
1144
+ (entry) => entry.description.includes("**BREAKING**")
1145
+ );
1146
+ if (breakingChanges.length > 0) {
1147
+ content += "### BREAKING CHANGES\n\n";
1148
+ for (const entry of breakingChanges) {
1149
+ const description = entry.description.replace("**BREAKING** ", "");
1150
+ content += `* ${entry.scope ? `**${entry.scope}:** ` : ""}${description}`;
1151
+ if (entry.issueIds && entry.issueIds.length > 0) {
1152
+ content += ` (${entry.issueIds.join(", ")})`;
1153
+ }
1154
+ content += "\n";
1155
+ }
1156
+ content += "\n";
1157
+ }
1158
+ }
1159
+ content += generateLinks(changelog, repoUrl);
1160
+ return content;
1161
+ }
1162
+ function groupEntriesByAngularType(entries) {
1163
+ const result = {};
1164
+ for (const entry of entries) {
1165
+ const type = entry.originalType || mapToAngularType(entry.type);
1166
+ if (!result[type]) {
1167
+ result[type] = [];
1168
+ }
1169
+ result[type].push(entry);
1170
+ }
1171
+ return result;
1172
+ }
1173
+ function mapToAngularType(type) {
1174
+ switch (type) {
1175
+ case "added":
1176
+ return "feat";
1177
+ case "fixed":
1178
+ return "fix";
1179
+ case "changed":
1180
+ return "perf";
1181
+ case "deprecated":
1182
+ case "removed":
1183
+ case "security":
1184
+ return type;
1185
+ default:
1186
+ return type;
1187
+ }
1188
+ }
1189
+ function formatAngularType(type) {
1190
+ switch (type) {
1191
+ case "feat":
1192
+ return "Features";
1193
+ case "fix":
1194
+ return "Bug Fixes";
1195
+ case "perf":
1196
+ return "Performance Improvements";
1197
+ case "security":
1198
+ return "Security";
1199
+ case "deprecated":
1200
+ return "Deprecated";
1201
+ case "removed":
1202
+ return "Removed";
1203
+ default:
1204
+ return capitalizeFirstLetter(type);
1205
+ }
1206
+ }
1207
+ function groupEntriesByScope2(entries) {
1208
+ const result = {};
1209
+ for (const entry of entries) {
1210
+ const scope = entry.scope || "";
1211
+ if (!result[scope]) {
1212
+ result[scope] = [];
1213
+ }
1214
+ result[scope].push(entry);
1215
+ }
1216
+ return result;
1217
+ }
1218
+ function formatAngularEntry(entry, includeScope) {
1219
+ let result = " * ";
1220
+ if (includeScope && entry.scope) {
1221
+ result += `**${entry.scope}:** `;
1222
+ }
1223
+ let description = entry.description;
1224
+ if (!includeScope && entry.scope && description.startsWith(`**${entry.scope}**: `)) {
1225
+ description = description.substring(`**${entry.scope}**: `.length);
1226
+ }
1227
+ if (description.startsWith("**BREAKING** ")) {
1228
+ description = description.substring("**BREAKING** ".length);
1229
+ }
1230
+ result += description;
1231
+ if (entry.issueIds && entry.issueIds.length > 0) {
1232
+ result += ` (${entry.issueIds.join(", ")})`;
1233
+ }
1234
+ result += "\n";
1235
+ return result;
1236
+ }
1237
+ function generateChangelogContent(changelog, repoUrl, format = "keep-a-changelog") {
1238
+ if (format === "angular") {
1239
+ return generateAngularChangelogContent(changelog, repoUrl);
1240
+ }
1241
+ let content = "# Changelog\n\n";
1242
+ content += `All notable changes to ${changelog.projectName} will be documented in this file.
1243
+
1244
+ `;
1245
+ content += "The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),\n";
1246
+ content += "and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n";
1247
+ if (changelog.unreleased.length > 0) {
1248
+ content += "## [Unreleased]\n\n";
1249
+ const grouped = changelog.unreleased.reduce(
1250
+ (acc, entry) => {
1251
+ if (!acc[entry.type]) {
1252
+ acc[entry.type] = [];
1253
+ }
1254
+ acc[entry.type].push(entry);
1255
+ return acc;
1256
+ },
1257
+ {}
1258
+ );
1259
+ for (const [type, entries] of Object.entries(grouped)) {
1260
+ content += `### ${capitalizeFirstLetter(type)}
1261
+
1262
+ `;
1263
+ for (const entry of entries) {
1264
+ let entryText = `- ${entry.description}`;
1265
+ if (entry.issueIds && entry.issueIds.length > 0) {
1266
+ entryText += ` (${entry.issueIds.join(", ")})`;
1267
+ }
1268
+ content += `${entryText}.
1269
+ `;
1270
+ }
1271
+ content += "\n";
1272
+ }
1273
+ }
1274
+ for (const version of changelog.versions) {
1275
+ content += `## [${version.version}] - ${version.date}
1276
+
1277
+ `;
1278
+ const grouped = version.entries.reduce(
1279
+ (acc, entry) => {
1280
+ if (!acc[entry.type]) {
1281
+ acc[entry.type] = [];
1282
+ }
1283
+ acc[entry.type].push(entry);
1284
+ return acc;
1285
+ },
1286
+ {}
1287
+ );
1288
+ for (const [type, entries] of Object.entries(grouped)) {
1289
+ content += `### ${capitalizeFirstLetter(type)}
1290
+
1291
+ `;
1292
+ for (const entry of entries) {
1293
+ let entryText = `- ${entry.description}`;
1294
+ if (entry.issueIds && entry.issueIds.length > 0) {
1295
+ entryText += ` (${entry.issueIds.join(", ")})`;
1296
+ }
1297
+ content += `${entryText}.
1298
+ `;
1299
+ }
1300
+ content += "\n";
1301
+ }
1302
+ }
1303
+ content += generateLinks(changelog, repoUrl);
1304
+ return content;
1305
+ }
1306
+ function updateChangelog(packagePath, packageName, version, entries, repoUrl, format = "keep-a-changelog") {
1307
+ try {
1308
+ const changelogPath = path4.join(packagePath, "CHANGELOG.md");
1309
+ let changelog;
1310
+ if (fs5.existsSync(changelogPath)) {
1311
+ const existingChangelog = parseChangelog(changelogPath);
1312
+ if (existingChangelog) {
1313
+ changelog = existingChangelog;
1314
+ } else {
1315
+ changelog = createChangelog(packagePath, packageName);
1316
+ }
1317
+ } else {
1318
+ changelog = createChangelog(packagePath, packageName);
1319
+ }
1320
+ if (version) {
1321
+ const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
1322
+ const newVersion = {
1323
+ version,
1324
+ date: today,
1325
+ entries: [...changelog.unreleased, ...entries]
1326
+ };
1327
+ changelog.unreleased = [];
1328
+ changelog.versions.unshift(newVersion);
1329
+ } else {
1330
+ changelog.unreleased = [...changelog.unreleased, ...entries];
1331
+ }
1332
+ const content = generateChangelogContent(changelog, repoUrl, format);
1333
+ fs5.writeFileSync(changelogPath, content);
1334
+ log(`Updated changelog at ${changelogPath}`, "success");
1335
+ } catch (error) {
1336
+ log(
1337
+ `Error updating changelog: ${error instanceof Error ? error.message : String(error)}`,
1338
+ "error"
1339
+ );
1340
+ }
1341
+ }
1342
+ function capitalizeFirstLetter(input) {
1343
+ return input.charAt(0).toUpperCase() + input.slice(1);
1344
+ }
1345
+
575
1346
  // src/core/versionCalculator.ts
576
1347
  var import_node_process3 = require("process");
577
1348
  var import_conventional_recommended_bump = require("conventional-recommended-bump");
578
1349
  var import_semver2 = __toESM(require("semver"), 1);
579
1350
 
580
1351
  // src/utils/manifestHelpers.ts
581
- var import_node_fs4 = __toESM(require("fs"), 1);
582
- var import_node_path4 = __toESM(require("path"), 1);
1352
+ var import_node_fs5 = __toESM(require("fs"), 1);
1353
+ var import_node_path5 = __toESM(require("path"), 1);
583
1354
  function getVersionFromManifests(packageDir) {
584
- const packageJsonPath = import_node_path4.default.join(packageDir, "package.json");
585
- const cargoTomlPath = import_node_path4.default.join(packageDir, "Cargo.toml");
586
- if (import_node_fs4.default.existsSync(packageJsonPath)) {
1355
+ const packageJsonPath = import_node_path5.default.join(packageDir, "package.json");
1356
+ const cargoTomlPath = import_node_path5.default.join(packageDir, "Cargo.toml");
1357
+ if (import_node_fs5.default.existsSync(packageJsonPath)) {
587
1358
  try {
588
- const packageJson = JSON.parse(import_node_fs4.default.readFileSync(packageJsonPath, "utf-8"));
1359
+ const packageJson = JSON.parse(import_node_fs5.default.readFileSync(packageJsonPath, "utf-8"));
589
1360
  if (packageJson.version) {
590
1361
  log(`Found version ${packageJson.version} in package.json`, "debug");
591
1362
  return {
@@ -601,7 +1372,7 @@ function getVersionFromManifests(packageDir) {
601
1372
  log(`Error reading package.json: ${errMsg}`, "warning");
602
1373
  }
603
1374
  }
604
- if (import_node_fs4.default.existsSync(cargoTomlPath)) {
1375
+ if (import_node_fs5.default.existsSync(cargoTomlPath)) {
605
1376
  try {
606
1377
  const cargoInfo = getCargoInfo(cargoTomlPath);
607
1378
  if (cargoInfo.version) {
@@ -627,15 +1398,15 @@ function getVersionFromManifests(packageDir) {
627
1398
  };
628
1399
  }
629
1400
  function throwIfNoManifestsFound(packageDir) {
630
- const packageJsonPath = import_node_path4.default.join(packageDir, "package.json");
631
- const cargoTomlPath = import_node_path4.default.join(packageDir, "Cargo.toml");
1401
+ const packageJsonPath = import_node_path5.default.join(packageDir, "package.json");
1402
+ const cargoTomlPath = import_node_path5.default.join(packageDir, "Cargo.toml");
632
1403
  throw new Error(
633
1404
  `Neither package.json nor Cargo.toml found at ${packageDir}. Checked paths: ${packageJsonPath}, ${cargoTomlPath}. Cannot determine version.`
634
1405
  );
635
1406
  }
636
1407
 
637
1408
  // src/utils/versionUtils.ts
638
- var import_node_fs5 = __toESM(require("fs"), 1);
1409
+ var import_node_fs6 = __toESM(require("fs"), 1);
639
1410
  var import_semver = __toESM(require("semver"), 1);
640
1411
  var TOML2 = __toESM(require("smol-toml"), 1);
641
1412
  var STANDARD_BUMP_TYPES = ["major", "minor", "patch"];
@@ -884,7 +1655,7 @@ var PackageProcessor = class {
884
1655
  * Process packages based on targeting criteria
885
1656
  */
886
1657
  async processPackages(packages) {
887
- var _a;
1658
+ var _a, _b, _c, _d, _e;
888
1659
  const tags = [];
889
1660
  const updatedPackagesInfo = [];
890
1661
  if (!packages || !Array.isArray(packages)) {
@@ -969,13 +1740,81 @@ var PackageProcessor = class {
969
1740
  if (!nextVersion) {
970
1741
  continue;
971
1742
  }
972
- const packageJsonPath = import_node_path5.default.join(pkgPath, "package.json");
973
- const cargoTomlPath = import_node_path5.default.join(pkgPath, "Cargo.toml");
974
- if (fs6.existsSync(packageJsonPath)) {
1743
+ if (this.fullConfig.updateChangelog !== false) {
1744
+ let changelogEntries = [];
1745
+ try {
1746
+ changelogEntries = extractChangelogEntriesFromCommits(pkgPath, latestTag);
1747
+ if (changelogEntries.length === 0) {
1748
+ changelogEntries = [
1749
+ {
1750
+ type: "changed",
1751
+ description: `Update version to ${nextVersion}`
1752
+ }
1753
+ ];
1754
+ }
1755
+ } catch (error) {
1756
+ log(
1757
+ `Error extracting changelog entries: ${error instanceof Error ? error.message : String(error)}`,
1758
+ "warning"
1759
+ );
1760
+ changelogEntries = [
1761
+ {
1762
+ type: "changed",
1763
+ description: `Update version to ${nextVersion}`
1764
+ }
1765
+ ];
1766
+ }
1767
+ let repoUrl;
1768
+ try {
1769
+ const packageJsonPath2 = import_node_path6.default.join(pkgPath, "package.json");
1770
+ if (fs8.existsSync(packageJsonPath2)) {
1771
+ const packageJson = JSON.parse(fs8.readFileSync(packageJsonPath2, "utf8"));
1772
+ if (packageJson.repository) {
1773
+ if (typeof packageJson.repository === "string") {
1774
+ repoUrl = packageJson.repository;
1775
+ } else if (packageJson.repository.url) {
1776
+ repoUrl = packageJson.repository.url;
1777
+ }
1778
+ if ((repoUrl == null ? void 0 : repoUrl.startsWith("git+")) && (repoUrl == null ? void 0 : repoUrl.endsWith(".git"))) {
1779
+ repoUrl = repoUrl.substring(4, repoUrl.length - 4);
1780
+ }
1781
+ }
1782
+ }
1783
+ } catch (error) {
1784
+ log(
1785
+ `Could not determine repository URL for changelog links: ${error instanceof Error ? error.message : String(error)}`,
1786
+ "warning"
1787
+ );
1788
+ }
1789
+ updateChangelog(
1790
+ pkgPath,
1791
+ name,
1792
+ nextVersion,
1793
+ changelogEntries,
1794
+ repoUrl,
1795
+ this.fullConfig.changelogFormat
1796
+ );
1797
+ }
1798
+ const packageJsonPath = import_node_path6.default.join(pkgPath, "package.json");
1799
+ if (fs8.existsSync(packageJsonPath)) {
975
1800
  updatePackageVersion(packageJsonPath, nextVersion);
976
1801
  }
977
- if (fs6.existsSync(cargoTomlPath)) {
978
- updatePackageVersion(cargoTomlPath, nextVersion);
1802
+ const cargoEnabled = ((_a = this.fullConfig.cargo) == null ? void 0 : _a.enabled) !== false;
1803
+ if (cargoEnabled) {
1804
+ const cargoPaths = (_b = this.fullConfig.cargo) == null ? void 0 : _b.paths;
1805
+ if (cargoPaths && cargoPaths.length > 0) {
1806
+ for (const cargoPath of cargoPaths) {
1807
+ const resolvedCargoPath = import_node_path6.default.resolve(pkgPath, cargoPath, "Cargo.toml");
1808
+ if (fs8.existsSync(resolvedCargoPath)) {
1809
+ updatePackageVersion(resolvedCargoPath, nextVersion);
1810
+ }
1811
+ }
1812
+ } else {
1813
+ const cargoTomlPath = import_node_path6.default.join(pkgPath, "Cargo.toml");
1814
+ if (fs8.existsSync(cargoTomlPath)) {
1815
+ updatePackageVersion(cargoTomlPath, nextVersion);
1816
+ }
1817
+ }
979
1818
  }
980
1819
  const packageTag = formatTag(
981
1820
  nextVersion,
@@ -1007,9 +1846,32 @@ var PackageProcessor = class {
1007
1846
  log("No targeted packages required a version update.", "info");
1008
1847
  return { updatedPackages: [], tags };
1009
1848
  }
1010
- const filesToCommit = updatedPackagesInfo.map((info) => import_node_path5.default.join(info.path, "package.json"));
1849
+ const filesToCommit = [];
1850
+ for (const info of updatedPackagesInfo) {
1851
+ const packageJsonPath = import_node_path6.default.join(info.path, "package.json");
1852
+ if (fs8.existsSync(packageJsonPath)) {
1853
+ filesToCommit.push(packageJsonPath);
1854
+ }
1855
+ const cargoEnabled = ((_c = this.fullConfig.cargo) == null ? void 0 : _c.enabled) !== false;
1856
+ if (cargoEnabled) {
1857
+ const cargoPaths = (_d = this.fullConfig.cargo) == null ? void 0 : _d.paths;
1858
+ if (cargoPaths && cargoPaths.length > 0) {
1859
+ for (const cargoPath of cargoPaths) {
1860
+ const resolvedCargoPath = import_node_path6.default.resolve(info.path, cargoPath, "Cargo.toml");
1861
+ if (fs8.existsSync(resolvedCargoPath)) {
1862
+ filesToCommit.push(resolvedCargoPath);
1863
+ }
1864
+ }
1865
+ } else {
1866
+ const cargoTomlPath = import_node_path6.default.join(info.path, "Cargo.toml");
1867
+ if (fs8.existsSync(cargoTomlPath)) {
1868
+ filesToCommit.push(cargoTomlPath);
1869
+ }
1870
+ }
1871
+ }
1872
+ }
1011
1873
  const packageNames = updatedPackagesInfo.map((p) => p.name).join(", ");
1012
- const representativeVersion = ((_a = updatedPackagesInfo[0]) == null ? void 0 : _a.version) || "multiple";
1874
+ const representativeVersion = ((_e = updatedPackagesInfo[0]) == null ? void 0 : _e.version) || "multiple";
1013
1875
  let commitMessage = this.commitMessageTemplate || "chore(release): publish packages";
1014
1876
  const placeholderRegex = /\$\{[^}]+\}/;
1015
1877
  if (updatedPackagesInfo.length === 1 && placeholderRegex.test(commitMessage)) {
@@ -1067,16 +1929,41 @@ function createSyncedStrategy(config) {
1067
1929
  commitMessage = "chore(release): v${version}",
1068
1930
  prereleaseIdentifier,
1069
1931
  dryRun,
1070
- skipHooks
1932
+ skipHooks,
1933
+ mainPackage
1071
1934
  } = config;
1072
1935
  const formattedPrefix = formatVersionPrefix(versionPrefix || "v");
1073
1936
  const latestTag = await getLatestTag();
1937
+ let mainPkgPath = packages.root;
1938
+ let mainPkgName;
1939
+ if (mainPackage) {
1940
+ const mainPkg = packages.packages.find((p) => p.packageJson.name === mainPackage);
1941
+ if (mainPkg) {
1942
+ mainPkgPath = mainPkg.dir;
1943
+ mainPkgName = mainPkg.packageJson.name;
1944
+ log(`Using ${mainPkgName} as primary package for version determination`, "info");
1945
+ } else {
1946
+ log(
1947
+ `Main package '${mainPackage}' not found. Using root package for version determination.`,
1948
+ "warning"
1949
+ );
1950
+ }
1951
+ }
1952
+ if (!mainPkgPath) {
1953
+ mainPkgPath = process.cwd();
1954
+ log(
1955
+ `No valid package path found, using current working directory: ${mainPkgPath}`,
1956
+ "warning"
1957
+ );
1958
+ }
1074
1959
  const nextVersion = await calculateVersion(config, {
1075
1960
  latestTag,
1076
1961
  versionPrefix: formattedPrefix,
1077
1962
  branchPattern,
1078
1963
  baseBranch,
1079
1964
  prereleaseIdentifier,
1965
+ path: mainPkgPath,
1966
+ name: mainPkgName,
1080
1967
  type: config.type
1081
1968
  });
1082
1969
  if (!nextVersion) {
@@ -1086,20 +1973,25 @@ function createSyncedStrategy(config) {
1086
1973
  const files = [];
1087
1974
  const updatedPackages = [];
1088
1975
  try {
1089
- const rootPkgPath = path5.join(packages.root, "package.json");
1090
- if (import_node_fs6.default.existsSync(rootPkgPath)) {
1091
- updatePackageVersion(rootPkgPath, nextVersion);
1092
- files.push(rootPkgPath);
1093
- updatedPackages.push("root");
1976
+ if (packages.root) {
1977
+ const rootPkgPath = path7.join(packages.root, "package.json");
1978
+ if (import_node_fs7.default.existsSync(rootPkgPath)) {
1979
+ updatePackageVersion(rootPkgPath, nextVersion);
1980
+ files.push(rootPkgPath);
1981
+ updatedPackages.push("root");
1982
+ }
1983
+ } else {
1984
+ log("Root package path is undefined, skipping root package.json update", "warning");
1094
1985
  }
1095
- } catch (_error) {
1096
- log("Failed to update root package.json", "error");
1986
+ } catch (error) {
1987
+ const errMessage = error instanceof Error ? error.message : String(error);
1988
+ log(`Failed to update root package.json: ${errMessage}`, "error");
1097
1989
  }
1098
1990
  for (const pkg of packages.packages) {
1099
1991
  if (!shouldProcessPackage(pkg, config)) {
1100
1992
  continue;
1101
1993
  }
1102
- const packageJsonPath = path5.join(pkg.dir, "package.json");
1994
+ const packageJsonPath = path7.join(pkg.dir, "package.json");
1103
1995
  updatePackageVersion(packageJsonPath, nextVersion);
1104
1996
  files.push(packageJsonPath);
1105
1997
  updatedPackages.push(pkg.packageJson.name);
@@ -1129,6 +2021,7 @@ function createSingleStrategy(config) {
1129
2021
  try {
1130
2022
  const {
1131
2023
  packages: configPackages,
2024
+ mainPackage,
1132
2025
  versionPrefix,
1133
2026
  tagTemplate,
1134
2027
  packageTagTemplate,
@@ -1136,13 +2029,17 @@ function createSingleStrategy(config) {
1136
2029
  dryRun,
1137
2030
  skipHooks
1138
2031
  } = config;
1139
- if (!configPackages || configPackages.length !== 1) {
2032
+ let packageName;
2033
+ if (mainPackage) {
2034
+ packageName = mainPackage;
2035
+ } else if (configPackages && configPackages.length === 1) {
2036
+ packageName = configPackages[0];
2037
+ } else {
1140
2038
  throw createVersionError(
1141
2039
  "INVALID_CONFIG" /* INVALID_CONFIG */,
1142
- "Single mode requires exactly one package name"
2040
+ "Single mode requires either mainPackage or exactly one package in the packages array"
1143
2041
  );
1144
2042
  }
1145
- const packageName = configPackages[0];
1146
2043
  const pkg = packages.packages.find((p) => p.packageJson.name === packageName);
1147
2044
  if (!pkg) {
1148
2045
  throw createVersionError("PACKAGE_NOT_FOUND" /* PACKAGE_NOT_FOUND */, packageName);
@@ -1172,7 +2069,7 @@ function createSingleStrategy(config) {
1172
2069
  log(`No version change needed for ${packageName}`, "info");
1173
2070
  return;
1174
2071
  }
1175
- const packageJsonPath = path5.join(pkgPath, "package.json");
2072
+ const packageJsonPath = path7.join(pkgPath, "package.json");
1176
2073
  updatePackageVersion(packageJsonPath, nextVersion);
1177
2074
  log(`Updated package ${packageName} to version ${nextVersion}`, "success");
1178
2075
  const nextTag = formatTag(
@@ -1266,7 +2163,7 @@ function createStrategy(config) {
1266
2163
  if (config.synced) {
1267
2164
  return createSyncedStrategy(config);
1268
2165
  }
1269
- if (((_a = config.packages) == null ? void 0 : _a.length) === 1) {
2166
+ if (config.mainPackage || ((_a = config.packages) == null ? void 0 : _a.length) === 1) {
1270
2167
  return createSingleStrategy(config);
1271
2168
  }
1272
2169
  return createAsyncStrategy(config);
@@ -1311,6 +2208,13 @@ var VersionEngine = class {
1311
2208
  if (!pkgsResult || !pkgsResult.packages) {
1312
2209
  throw createVersionError("PACKAGES_NOT_FOUND" /* PACKAGES_NOT_FOUND */);
1313
2210
  }
2211
+ if (!pkgsResult.root) {
2212
+ log(
2213
+ "Root path is undefined in packages result, setting to current working directory",
2214
+ "warning"
2215
+ );
2216
+ pkgsResult.root = (0, import_node_process5.cwd)();
2217
+ }
1314
2218
  this.workspaceCache = pkgsResult;
1315
2219
  return pkgsResult;
1316
2220
  } catch (error) {
@@ -1331,9 +2235,22 @@ var VersionEngine = class {
1331
2235
  } catch (error) {
1332
2236
  if (error instanceof VersionError || error instanceof GitError) {
1333
2237
  log(`Version engine failed: ${error.message} (${error.code || "UNKNOWN"})`, "error");
2238
+ if (error instanceof GitError) {
2239
+ console.error("Git error details:");
2240
+ if (error.message.includes("Command failed:")) {
2241
+ const cmdOutput = error.message.split("Command failed:")[1];
2242
+ if (cmdOutput) {
2243
+ console.error("Command output:", cmdOutput.trim());
2244
+ }
2245
+ }
2246
+ }
1334
2247
  } else {
1335
2248
  const errorMessage = error instanceof Error ? error.message : String(error);
1336
2249
  log(`Version engine failed: ${errorMessage}`, "error");
2250
+ if (error instanceof Error && error.stack) {
2251
+ console.error("Error stack trace:");
2252
+ console.error(error.stack);
2253
+ }
1337
2254
  }
1338
2255
  throw error;
1339
2256
  }
@@ -1351,11 +2268,11 @@ var VersionEngine = class {
1351
2268
  var import_meta = {};
1352
2269
  function getPackageVersion() {
1353
2270
  try {
1354
- const packageJsonPath = import_node_path6.default.resolve(
1355
- import_node_path6.default.dirname(import_meta.url.replace("file:", "")),
2271
+ const packageJsonPath = import_node_path7.default.resolve(
2272
+ import_node_path7.default.dirname(import_meta.url.replace("file:", "")),
1356
2273
  "../package.json"
1357
2274
  );
1358
- const packageJsonContent = fs8.readFileSync(packageJsonPath, "utf-8");
2275
+ const packageJsonContent = fs10.readFileSync(packageJsonPath, "utf-8");
1359
2276
  const packageJson = JSON.parse(packageJsonContent);
1360
2277
  return packageJson.version || "0.0.0";
1361
2278
  } catch (error) {
@@ -1364,53 +2281,104 @@ function getPackageVersion() {
1364
2281
  }
1365
2282
  }
1366
2283
  async function run() {
1367
- const buildTimestamp = (/* @__PURE__ */ new Date()).toISOString();
1368
- const packageVersion = getPackageVersion();
1369
- log(`package-versioner v${packageVersion} (Build: ${buildTimestamp})`, "debug");
1370
- const program = new import_commander.Command();
1371
- program.name("package-versioner").description(
1372
- "A lightweight yet powerful CLI tool for automated semantic versioning based on Git history and conventional commits."
1373
- ).version(packageVersion).option(
1374
- "-c, --config <path>",
1375
- "Path to config file (defaults to version.config.json in current directory)"
1376
- ).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);
1377
- const options = program.opts();
1378
- if (options.json) {
1379
- enableJsonOutput(options.dryRun);
1380
- }
1381
2284
  try {
1382
- const config = await loadConfig(options.config);
1383
- log(`Loaded configuration from ${options.config || "version.config.json"}`, "info");
1384
- if (options.dryRun) config.dryRun = true;
1385
- if (options.synced) config.synced = true;
1386
- if (options.bump) config.type = options.bump;
1387
- if (options.prerelease)
1388
- config.prereleaseIdentifier = options.prerelease === true ? "next" : options.prerelease;
1389
- const cliTargets = options.target ? options.target.split(",").map((t) => t.trim()) : [];
1390
- const engine = new VersionEngine(config, !!options.json);
1391
- if (config.synced) {
1392
- log("Using synced versioning strategy.", "info");
1393
- engine.setStrategy("synced");
1394
- await engine.run();
1395
- } else if (config.packages && config.packages.length === 1) {
1396
- log("Using single package versioning strategy.", "info");
1397
- if (cliTargets.length > 0) {
1398
- log("--target flag is ignored for single package strategy.", "warning");
1399
- }
1400
- engine.setStrategy("single");
1401
- await engine.run();
1402
- } else {
1403
- log("Using async versioning strategy.", "info");
1404
- if (cliTargets.length > 0) {
1405
- log(`Targeting specific packages: ${cliTargets.join(", ")}`, "info");
2285
+ const buildTimestamp = (/* @__PURE__ */ new Date()).toISOString();
2286
+ const packageVersion = getPackageVersion();
2287
+ log(`package-versioner v${packageVersion} (Build: ${buildTimestamp})`, "debug");
2288
+ const program = new import_commander.Command();
2289
+ program.name("package-versioner").description(
2290
+ "A lightweight yet powerful CLI tool for automated semantic versioning based on Git history and conventional commits."
2291
+ ).version(packageVersion);
2292
+ program.command("version", { isDefault: true }).description("Version a package or packages based on configuration").option(
2293
+ "-c, --config <path>",
2294
+ "Path to config file (defaults to version.config.json in current directory)"
2295
+ ).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) => {
2296
+ if (options.json) {
2297
+ enableJsonOutput(options.dryRun);
1406
2298
  }
1407
- engine.setStrategy("async");
1408
- await engine.run(cliTargets);
1409
- }
1410
- log("Versioning process completed.", "success");
1411
- printJsonOutput();
2299
+ try {
2300
+ const config = await loadConfig(options.config);
2301
+ log(`Loaded configuration from ${options.config || "version.config.json"}`, "info");
2302
+ if (options.dryRun) config.dryRun = true;
2303
+ if (options.synced) config.synced = true;
2304
+ if (options.bump) config.type = options.bump;
2305
+ if (options.prerelease)
2306
+ config.prereleaseIdentifier = options.prerelease === true ? "next" : options.prerelease;
2307
+ const cliTargets = options.target ? options.target.split(",").map((t) => t.trim()) : [];
2308
+ const engine = new VersionEngine(config, !!options.json);
2309
+ if (config.synced) {
2310
+ log("Using synced versioning strategy.", "info");
2311
+ engine.setStrategy("synced");
2312
+ await engine.run();
2313
+ } else if (config.packages && config.packages.length === 1) {
2314
+ log("Using single package versioning strategy.", "info");
2315
+ if (cliTargets.length > 0) {
2316
+ log("--target flag is ignored for single package strategy.", "warning");
2317
+ }
2318
+ engine.setStrategy("single");
2319
+ await engine.run();
2320
+ } else {
2321
+ log("Using async versioning strategy.", "info");
2322
+ if (cliTargets.length > 0) {
2323
+ log(`Targeting specific packages: ${cliTargets.join(", ")}`, "info");
2324
+ }
2325
+ engine.setStrategy("async");
2326
+ await engine.run(cliTargets);
2327
+ }
2328
+ log("Versioning process completed.", "success");
2329
+ printJsonOutput();
2330
+ } catch (error) {
2331
+ log(error instanceof Error ? error.message : String(error), "error");
2332
+ if (error instanceof Error) {
2333
+ console.error("Error details:");
2334
+ console.error(error.stack || error.message);
2335
+ if (error.message.includes("Command failed:")) {
2336
+ const cmdOutput = error.message.split("Command failed:")[1];
2337
+ if (cmdOutput) {
2338
+ console.error("Command output:", cmdOutput.trim());
2339
+ }
2340
+ }
2341
+ }
2342
+ process.exit(1);
2343
+ }
2344
+ });
2345
+ program.command("regenerate-changelog").description("Regenerate a complete changelog from git history").option("-o, --output <path>", "Output path for changelog file", "CHANGELOG.md").option(
2346
+ "-f, --format <format>",
2347
+ "Changelog format (keep-a-changelog|angular)",
2348
+ "keep-a-changelog"
2349
+ ).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) => {
2350
+ try {
2351
+ log("Regenerating changelog from git history...", "info");
2352
+ if (options.format !== "keep-a-changelog" && options.format !== "angular") {
2353
+ throw new Error(
2354
+ 'Invalid format specified. Must be either "keep-a-changelog" or "angular"'
2355
+ );
2356
+ }
2357
+ const regenerateOptions = {
2358
+ format: options.format,
2359
+ since: options.since,
2360
+ output: options.output,
2361
+ dryRun: options.dryRun,
2362
+ projectDir: options.projectDir,
2363
+ repoUrl: options.repoUrl
2364
+ };
2365
+ const content = await regenerateChangelog(regenerateOptions);
2366
+ await writeChangelog(
2367
+ content,
2368
+ import_node_path7.default.resolve(options.projectDir, options.output),
2369
+ options.dryRun
2370
+ );
2371
+ if (!options.dryRun) {
2372
+ log(`Changelog successfully regenerated at ${options.output}`, "success");
2373
+ }
2374
+ } catch (error) {
2375
+ log(error instanceof Error ? error.message : String(error), "error");
2376
+ process.exit(1);
2377
+ }
2378
+ });
2379
+ program.parse(process.argv);
1412
2380
  } catch (error) {
1413
- log(error instanceof Error ? error.message : String(error), "error");
2381
+ console.error("Fatal error:", error);
1414
2382
  process.exit(1);
1415
2383
  }
1416
2384
  }