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/README.md +40 -21
- package/dist/index.cjs +1146 -178
- package/dist/index.js +1145 -175
- package/docs/changelogs.md +65 -0
- package/docs/{VERSIONING_STRATEGIES.md → versioning.md} +1 -1
- package/package-versioner.schema.json +36 -0
- package/package.json +14 -10
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
|
|
38
|
-
var
|
|
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/
|
|
42
|
-
var
|
|
43
|
-
var
|
|
44
|
-
|
|
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
|
|
194
|
-
var
|
|
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
|
|
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,
|
|
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
|
|
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
|
|
221
|
-
var
|
|
654
|
+
var import_node_fs2 = require("fs");
|
|
655
|
+
var import_node_path2 = require("path");
|
|
222
656
|
function isGitRepository(directory) {
|
|
223
|
-
const gitDir = (0,
|
|
224
|
-
if (!(0,
|
|
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,
|
|
661
|
+
const stats = (0, import_node_fs2.statSync)(gitDir);
|
|
228
662
|
if (!stats.isDirectory()) {
|
|
229
663
|
return false;
|
|
230
664
|
}
|
|
231
665
|
try {
|
|
232
|
-
|
|
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 =
|
|
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 =
|
|
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
|
|
481
|
-
var
|
|
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
|
|
485
|
-
var
|
|
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 (!
|
|
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 =
|
|
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:
|
|
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
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
|
572
|
-
var
|
|
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
|
|
582
|
-
var
|
|
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 =
|
|
585
|
-
const cargoTomlPath =
|
|
586
|
-
if (
|
|
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(
|
|
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 (
|
|
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 =
|
|
631
|
-
const cargoTomlPath =
|
|
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
|
|
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
|
-
|
|
973
|
-
|
|
974
|
-
|
|
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
|
-
|
|
978
|
-
|
|
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 =
|
|
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 = ((
|
|
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
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
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 (
|
|
1096
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
|
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 =
|
|
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 =
|
|
1355
|
-
|
|
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 =
|
|
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
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
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
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
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
|
-
|
|
2381
|
+
console.error("Fatal error:", error);
|
|
1414
2382
|
process.exit(1);
|
|
1415
2383
|
}
|
|
1416
2384
|
}
|