package-versioner 0.6.4 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -6
- package/dist/index.cjs +1061 -169
- package/dist/index.js +1052 -160
- package/docs/changelogs.md +65 -0
- package/docs/{VERSIONING_STRATEGIES.md → versioning.md} +1 -1
- package/package-versioner.schema.json +31 -0
- package/package.json +11 -7
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
|
|
|
@@ -380,7 +814,7 @@ function createTemplateString(template, variables) {
|
|
|
380
814
|
function getCommitsLength(pkgRoot) {
|
|
381
815
|
try {
|
|
382
816
|
const gitCommand = `git rev-list --count HEAD ^$(git describe --tags --abbrev=0) ${pkgRoot}`;
|
|
383
|
-
const amount =
|
|
817
|
+
const amount = execSync3(gitCommand).toString().trim();
|
|
384
818
|
return Number(amount);
|
|
385
819
|
} catch (error) {
|
|
386
820
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
@@ -477,21 +911,21 @@ async function getLatestTagForPackage(packageName, versionPrefix) {
|
|
|
477
911
|
}
|
|
478
912
|
|
|
479
913
|
// src/package/packageManagement.ts
|
|
480
|
-
var
|
|
481
|
-
var
|
|
914
|
+
var import_node_fs4 = __toESM(require("fs"), 1);
|
|
915
|
+
var import_node_path4 = __toESM(require("path"), 1);
|
|
482
916
|
|
|
483
917
|
// src/cargo/cargoHandler.ts
|
|
484
|
-
var
|
|
485
|
-
var
|
|
918
|
+
var import_node_fs3 = __toESM(require("fs"), 1);
|
|
919
|
+
var import_node_path3 = __toESM(require("path"), 1);
|
|
486
920
|
var TOML = __toESM(require("smol-toml"), 1);
|
|
487
921
|
function getCargoInfo(cargoPath) {
|
|
488
922
|
var _a;
|
|
489
|
-
if (!
|
|
923
|
+
if (!import_node_fs3.default.existsSync(cargoPath)) {
|
|
490
924
|
log(`Cargo.toml file not found at: ${cargoPath}`, "error");
|
|
491
925
|
throw new Error(`Cargo.toml file not found at: ${cargoPath}`);
|
|
492
926
|
}
|
|
493
927
|
try {
|
|
494
|
-
const fileContent =
|
|
928
|
+
const fileContent = import_node_fs3.default.readFileSync(cargoPath, "utf8");
|
|
495
929
|
const cargo = TOML.parse(fileContent);
|
|
496
930
|
if (!((_a = cargo.package) == null ? void 0 : _a.name)) {
|
|
497
931
|
log(`Package name not found in: ${cargoPath}`, "error");
|
|
@@ -501,7 +935,7 @@ function getCargoInfo(cargoPath) {
|
|
|
501
935
|
name: cargo.package.name,
|
|
502
936
|
version: cargo.package.version || "0.0.0",
|
|
503
937
|
path: cargoPath,
|
|
504
|
-
dir:
|
|
938
|
+
dir: import_node_path3.default.dirname(cargoPath),
|
|
505
939
|
content: cargo
|
|
506
940
|
};
|
|
507
941
|
} catch (error) {
|
|
@@ -514,12 +948,12 @@ function getCargoInfo(cargoPath) {
|
|
|
514
948
|
}
|
|
515
949
|
}
|
|
516
950
|
function isCargoToml(filePath) {
|
|
517
|
-
return
|
|
951
|
+
return import_node_path3.default.basename(filePath) === "Cargo.toml";
|
|
518
952
|
}
|
|
519
953
|
function updateCargoVersion(cargoPath, version) {
|
|
520
954
|
var _a;
|
|
521
955
|
try {
|
|
522
|
-
const originalContent =
|
|
956
|
+
const originalContent = import_node_fs3.default.readFileSync(cargoPath, "utf8");
|
|
523
957
|
const cargo = TOML.parse(originalContent);
|
|
524
958
|
const packageName = (_a = cargo.package) == null ? void 0 : _a.name;
|
|
525
959
|
if (!packageName) {
|
|
@@ -531,7 +965,7 @@ function updateCargoVersion(cargoPath, version) {
|
|
|
531
965
|
cargo.package.version = version;
|
|
532
966
|
}
|
|
533
967
|
const updatedContent = TOML.stringify(cargo);
|
|
534
|
-
|
|
968
|
+
import_node_fs3.default.writeFileSync(cargoPath, updatedContent);
|
|
535
969
|
addPackageUpdate(packageName, version, cargoPath);
|
|
536
970
|
log(`Updated Cargo.toml at ${cargoPath} to version ${version}`, "success");
|
|
537
971
|
} catch (error) {
|
|
@@ -550,11 +984,11 @@ function updatePackageVersion(packagePath, version) {
|
|
|
550
984
|
return;
|
|
551
985
|
}
|
|
552
986
|
try {
|
|
553
|
-
const packageContent =
|
|
987
|
+
const packageContent = import_node_fs4.default.readFileSync(packagePath, "utf8");
|
|
554
988
|
const packageJson = JSON.parse(packageContent);
|
|
555
989
|
const packageName = packageJson.name;
|
|
556
990
|
packageJson.version = version;
|
|
557
|
-
|
|
991
|
+
import_node_fs4.default.writeFileSync(packagePath, `${JSON.stringify(packageJson, null, 2)}
|
|
558
992
|
`);
|
|
559
993
|
addPackageUpdate(packageName, version, packagePath);
|
|
560
994
|
log(`Updated package.json at ${packagePath} to version ${version}`, "success");
|
|
@@ -568,24 +1002,349 @@ function updatePackageVersion(packagePath, version) {
|
|
|
568
1002
|
}
|
|
569
1003
|
|
|
570
1004
|
// src/package/packageProcessor.ts
|
|
571
|
-
var
|
|
572
|
-
var
|
|
1005
|
+
var fs8 = __toESM(require("fs"), 1);
|
|
1006
|
+
var import_node_path6 = __toESM(require("path"), 1);
|
|
573
1007
|
var import_node_process4 = require("process");
|
|
574
1008
|
|
|
1009
|
+
// src/changelog/changelogManager.ts
|
|
1010
|
+
var fs5 = __toESM(require("fs"), 1);
|
|
1011
|
+
var path4 = __toESM(require("path"), 1);
|
|
1012
|
+
function createChangelog(_packagePath, packageName) {
|
|
1013
|
+
return {
|
|
1014
|
+
projectName: packageName,
|
|
1015
|
+
unreleased: [],
|
|
1016
|
+
versions: []
|
|
1017
|
+
};
|
|
1018
|
+
}
|
|
1019
|
+
function parseChangelog(filePath) {
|
|
1020
|
+
try {
|
|
1021
|
+
if (!fs5.existsSync(filePath)) {
|
|
1022
|
+
return null;
|
|
1023
|
+
}
|
|
1024
|
+
fs5.readFileSync(filePath, "utf8");
|
|
1025
|
+
log(`Parsed changelog at ${filePath}`, "info");
|
|
1026
|
+
return {
|
|
1027
|
+
projectName: path4.basename(path4.dirname(filePath)),
|
|
1028
|
+
unreleased: [],
|
|
1029
|
+
versions: []
|
|
1030
|
+
};
|
|
1031
|
+
} catch (error) {
|
|
1032
|
+
log(
|
|
1033
|
+
`Error parsing changelog: ${error instanceof Error ? error.message : String(error)}`,
|
|
1034
|
+
"error"
|
|
1035
|
+
);
|
|
1036
|
+
return null;
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
function generateLinks(changelog, repoUrl) {
|
|
1040
|
+
var _a, _b;
|
|
1041
|
+
if (!repoUrl || changelog.versions.length === 0) {
|
|
1042
|
+
return "";
|
|
1043
|
+
}
|
|
1044
|
+
let links = "\n";
|
|
1045
|
+
if (changelog.unreleased.length > 0) {
|
|
1046
|
+
const latestVersion = ((_a = changelog.versions[0]) == null ? void 0 : _a.version) || "";
|
|
1047
|
+
links += `[unreleased]: ${repoUrl}/compare/v${latestVersion}...HEAD
|
|
1048
|
+
`;
|
|
1049
|
+
}
|
|
1050
|
+
for (let i = 0; i < changelog.versions.length; i++) {
|
|
1051
|
+
const currentVersion = changelog.versions[i].version;
|
|
1052
|
+
const previousVersion = (_b = changelog.versions[i + 1]) == null ? void 0 : _b.version;
|
|
1053
|
+
if (previousVersion) {
|
|
1054
|
+
links += `[${currentVersion}]: ${repoUrl}/compare/v${previousVersion}...v${currentVersion}
|
|
1055
|
+
`;
|
|
1056
|
+
} else if (i === changelog.versions.length - 1) {
|
|
1057
|
+
links += `[${currentVersion}]: ${repoUrl}/releases/tag/v${currentVersion}
|
|
1058
|
+
`;
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
return links;
|
|
1062
|
+
}
|
|
1063
|
+
function generateAngularChangelogContent(changelog, repoUrl) {
|
|
1064
|
+
let content = "# Changelog\n\n";
|
|
1065
|
+
if (changelog.unreleased.length > 0) {
|
|
1066
|
+
content += "## [Unreleased]\n\n";
|
|
1067
|
+
const groupedByType = groupEntriesByAngularType(changelog.unreleased);
|
|
1068
|
+
for (const [type, entries] of Object.entries(groupedByType)) {
|
|
1069
|
+
content += `### ${formatAngularType(type)}
|
|
1070
|
+
|
|
1071
|
+
`;
|
|
1072
|
+
const groupedByScope = groupEntriesByScope2(entries);
|
|
1073
|
+
for (const [scope, scopeEntries] of Object.entries(groupedByScope)) {
|
|
1074
|
+
if (scope !== "undefined" && scope !== "") {
|
|
1075
|
+
content += `* **${scope}:**
|
|
1076
|
+
`;
|
|
1077
|
+
for (const entry of scopeEntries) {
|
|
1078
|
+
content += formatAngularEntry(entry, false);
|
|
1079
|
+
}
|
|
1080
|
+
content += "\n";
|
|
1081
|
+
} else {
|
|
1082
|
+
for (const entry of scopeEntries) {
|
|
1083
|
+
content += formatAngularEntry(entry, true);
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
content += "\n";
|
|
1088
|
+
}
|
|
1089
|
+
const breakingChanges = changelog.unreleased.filter(
|
|
1090
|
+
(entry) => entry.description.includes("**BREAKING**")
|
|
1091
|
+
);
|
|
1092
|
+
if (breakingChanges.length > 0) {
|
|
1093
|
+
content += "### BREAKING CHANGES\n\n";
|
|
1094
|
+
for (const entry of breakingChanges) {
|
|
1095
|
+
const description = entry.description.replace("**BREAKING** ", "");
|
|
1096
|
+
content += `* ${entry.scope ? `**${entry.scope}:** ` : ""}${description}`;
|
|
1097
|
+
if (entry.issueIds && entry.issueIds.length > 0) {
|
|
1098
|
+
content += ` (${entry.issueIds.join(", ")})`;
|
|
1099
|
+
}
|
|
1100
|
+
content += "\n";
|
|
1101
|
+
}
|
|
1102
|
+
content += "\n";
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
for (const version of changelog.versions) {
|
|
1106
|
+
content += `## [${version.version}] - ${version.date}
|
|
1107
|
+
|
|
1108
|
+
`;
|
|
1109
|
+
const groupedByType = groupEntriesByAngularType(version.entries);
|
|
1110
|
+
for (const [type, entries] of Object.entries(groupedByType)) {
|
|
1111
|
+
content += `### ${formatAngularType(type)}
|
|
1112
|
+
|
|
1113
|
+
`;
|
|
1114
|
+
const groupedByScope = groupEntriesByScope2(entries);
|
|
1115
|
+
for (const [scope, scopeEntries] of Object.entries(groupedByScope)) {
|
|
1116
|
+
if (scope !== "undefined" && scope !== "") {
|
|
1117
|
+
content += `* **${scope}:**
|
|
1118
|
+
`;
|
|
1119
|
+
for (const entry of scopeEntries) {
|
|
1120
|
+
content += formatAngularEntry(entry, false);
|
|
1121
|
+
}
|
|
1122
|
+
content += "\n";
|
|
1123
|
+
} else {
|
|
1124
|
+
for (const entry of scopeEntries) {
|
|
1125
|
+
content += formatAngularEntry(entry, true);
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
content += "\n";
|
|
1130
|
+
}
|
|
1131
|
+
const breakingChanges = version.entries.filter(
|
|
1132
|
+
(entry) => entry.description.includes("**BREAKING**")
|
|
1133
|
+
);
|
|
1134
|
+
if (breakingChanges.length > 0) {
|
|
1135
|
+
content += "### BREAKING CHANGES\n\n";
|
|
1136
|
+
for (const entry of breakingChanges) {
|
|
1137
|
+
const description = entry.description.replace("**BREAKING** ", "");
|
|
1138
|
+
content += `* ${entry.scope ? `**${entry.scope}:** ` : ""}${description}`;
|
|
1139
|
+
if (entry.issueIds && entry.issueIds.length > 0) {
|
|
1140
|
+
content += ` (${entry.issueIds.join(", ")})`;
|
|
1141
|
+
}
|
|
1142
|
+
content += "\n";
|
|
1143
|
+
}
|
|
1144
|
+
content += "\n";
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
content += generateLinks(changelog, repoUrl);
|
|
1148
|
+
return content;
|
|
1149
|
+
}
|
|
1150
|
+
function groupEntriesByAngularType(entries) {
|
|
1151
|
+
const result = {};
|
|
1152
|
+
for (const entry of entries) {
|
|
1153
|
+
const type = entry.originalType || mapToAngularType(entry.type);
|
|
1154
|
+
if (!result[type]) {
|
|
1155
|
+
result[type] = [];
|
|
1156
|
+
}
|
|
1157
|
+
result[type].push(entry);
|
|
1158
|
+
}
|
|
1159
|
+
return result;
|
|
1160
|
+
}
|
|
1161
|
+
function mapToAngularType(type) {
|
|
1162
|
+
switch (type) {
|
|
1163
|
+
case "added":
|
|
1164
|
+
return "feat";
|
|
1165
|
+
case "fixed":
|
|
1166
|
+
return "fix";
|
|
1167
|
+
case "changed":
|
|
1168
|
+
return "perf";
|
|
1169
|
+
case "deprecated":
|
|
1170
|
+
case "removed":
|
|
1171
|
+
case "security":
|
|
1172
|
+
return type;
|
|
1173
|
+
default:
|
|
1174
|
+
return type;
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
function formatAngularType(type) {
|
|
1178
|
+
switch (type) {
|
|
1179
|
+
case "feat":
|
|
1180
|
+
return "Features";
|
|
1181
|
+
case "fix":
|
|
1182
|
+
return "Bug Fixes";
|
|
1183
|
+
case "perf":
|
|
1184
|
+
return "Performance Improvements";
|
|
1185
|
+
case "security":
|
|
1186
|
+
return "Security";
|
|
1187
|
+
case "deprecated":
|
|
1188
|
+
return "Deprecated";
|
|
1189
|
+
case "removed":
|
|
1190
|
+
return "Removed";
|
|
1191
|
+
default:
|
|
1192
|
+
return capitalizeFirstLetter(type);
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
function groupEntriesByScope2(entries) {
|
|
1196
|
+
const result = {};
|
|
1197
|
+
for (const entry of entries) {
|
|
1198
|
+
const scope = entry.scope || "";
|
|
1199
|
+
if (!result[scope]) {
|
|
1200
|
+
result[scope] = [];
|
|
1201
|
+
}
|
|
1202
|
+
result[scope].push(entry);
|
|
1203
|
+
}
|
|
1204
|
+
return result;
|
|
1205
|
+
}
|
|
1206
|
+
function formatAngularEntry(entry, includeScope) {
|
|
1207
|
+
let result = " * ";
|
|
1208
|
+
if (includeScope && entry.scope) {
|
|
1209
|
+
result += `**${entry.scope}:** `;
|
|
1210
|
+
}
|
|
1211
|
+
let description = entry.description;
|
|
1212
|
+
if (!includeScope && entry.scope && description.startsWith(`**${entry.scope}**: `)) {
|
|
1213
|
+
description = description.substring(`**${entry.scope}**: `.length);
|
|
1214
|
+
}
|
|
1215
|
+
if (description.startsWith("**BREAKING** ")) {
|
|
1216
|
+
description = description.substring("**BREAKING** ".length);
|
|
1217
|
+
}
|
|
1218
|
+
result += description;
|
|
1219
|
+
if (entry.issueIds && entry.issueIds.length > 0) {
|
|
1220
|
+
result += ` (${entry.issueIds.join(", ")})`;
|
|
1221
|
+
}
|
|
1222
|
+
result += "\n";
|
|
1223
|
+
return result;
|
|
1224
|
+
}
|
|
1225
|
+
function generateChangelogContent(changelog, repoUrl, format = "keep-a-changelog") {
|
|
1226
|
+
if (format === "angular") {
|
|
1227
|
+
return generateAngularChangelogContent(changelog, repoUrl);
|
|
1228
|
+
}
|
|
1229
|
+
let content = "# Changelog\n\n";
|
|
1230
|
+
content += `All notable changes to ${changelog.projectName} will be documented in this file.
|
|
1231
|
+
|
|
1232
|
+
`;
|
|
1233
|
+
content += "The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),\n";
|
|
1234
|
+
content += "and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n";
|
|
1235
|
+
if (changelog.unreleased.length > 0) {
|
|
1236
|
+
content += "## [Unreleased]\n\n";
|
|
1237
|
+
const grouped = changelog.unreleased.reduce(
|
|
1238
|
+
(acc, entry) => {
|
|
1239
|
+
if (!acc[entry.type]) {
|
|
1240
|
+
acc[entry.type] = [];
|
|
1241
|
+
}
|
|
1242
|
+
acc[entry.type].push(entry);
|
|
1243
|
+
return acc;
|
|
1244
|
+
},
|
|
1245
|
+
{}
|
|
1246
|
+
);
|
|
1247
|
+
for (const [type, entries] of Object.entries(grouped)) {
|
|
1248
|
+
content += `### ${capitalizeFirstLetter(type)}
|
|
1249
|
+
|
|
1250
|
+
`;
|
|
1251
|
+
for (const entry of entries) {
|
|
1252
|
+
let entryText = `- ${entry.description}`;
|
|
1253
|
+
if (entry.issueIds && entry.issueIds.length > 0) {
|
|
1254
|
+
entryText += ` (${entry.issueIds.join(", ")})`;
|
|
1255
|
+
}
|
|
1256
|
+
content += `${entryText}.
|
|
1257
|
+
`;
|
|
1258
|
+
}
|
|
1259
|
+
content += "\n";
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
for (const version of changelog.versions) {
|
|
1263
|
+
content += `## [${version.version}] - ${version.date}
|
|
1264
|
+
|
|
1265
|
+
`;
|
|
1266
|
+
const grouped = version.entries.reduce(
|
|
1267
|
+
(acc, entry) => {
|
|
1268
|
+
if (!acc[entry.type]) {
|
|
1269
|
+
acc[entry.type] = [];
|
|
1270
|
+
}
|
|
1271
|
+
acc[entry.type].push(entry);
|
|
1272
|
+
return acc;
|
|
1273
|
+
},
|
|
1274
|
+
{}
|
|
1275
|
+
);
|
|
1276
|
+
for (const [type, entries] of Object.entries(grouped)) {
|
|
1277
|
+
content += `### ${capitalizeFirstLetter(type)}
|
|
1278
|
+
|
|
1279
|
+
`;
|
|
1280
|
+
for (const entry of entries) {
|
|
1281
|
+
let entryText = `- ${entry.description}`;
|
|
1282
|
+
if (entry.issueIds && entry.issueIds.length > 0) {
|
|
1283
|
+
entryText += ` (${entry.issueIds.join(", ")})`;
|
|
1284
|
+
}
|
|
1285
|
+
content += `${entryText}.
|
|
1286
|
+
`;
|
|
1287
|
+
}
|
|
1288
|
+
content += "\n";
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1291
|
+
content += generateLinks(changelog, repoUrl);
|
|
1292
|
+
return content;
|
|
1293
|
+
}
|
|
1294
|
+
function updateChangelog(packagePath, packageName, version, entries, repoUrl, format = "keep-a-changelog") {
|
|
1295
|
+
try {
|
|
1296
|
+
const changelogPath = path4.join(packagePath, "CHANGELOG.md");
|
|
1297
|
+
let changelog;
|
|
1298
|
+
if (fs5.existsSync(changelogPath)) {
|
|
1299
|
+
const existingChangelog = parseChangelog(changelogPath);
|
|
1300
|
+
if (existingChangelog) {
|
|
1301
|
+
changelog = existingChangelog;
|
|
1302
|
+
} else {
|
|
1303
|
+
changelog = createChangelog(packagePath, packageName);
|
|
1304
|
+
}
|
|
1305
|
+
} else {
|
|
1306
|
+
changelog = createChangelog(packagePath, packageName);
|
|
1307
|
+
}
|
|
1308
|
+
if (version) {
|
|
1309
|
+
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
1310
|
+
const newVersion = {
|
|
1311
|
+
version,
|
|
1312
|
+
date: today,
|
|
1313
|
+
entries: [...changelog.unreleased, ...entries]
|
|
1314
|
+
};
|
|
1315
|
+
changelog.unreleased = [];
|
|
1316
|
+
changelog.versions.unshift(newVersion);
|
|
1317
|
+
} else {
|
|
1318
|
+
changelog.unreleased = [...changelog.unreleased, ...entries];
|
|
1319
|
+
}
|
|
1320
|
+
const content = generateChangelogContent(changelog, repoUrl, format);
|
|
1321
|
+
fs5.writeFileSync(changelogPath, content);
|
|
1322
|
+
log(`Updated changelog at ${changelogPath}`, "success");
|
|
1323
|
+
} catch (error) {
|
|
1324
|
+
log(
|
|
1325
|
+
`Error updating changelog: ${error instanceof Error ? error.message : String(error)}`,
|
|
1326
|
+
"error"
|
|
1327
|
+
);
|
|
1328
|
+
}
|
|
1329
|
+
}
|
|
1330
|
+
function capitalizeFirstLetter(input) {
|
|
1331
|
+
return input.charAt(0).toUpperCase() + input.slice(1);
|
|
1332
|
+
}
|
|
1333
|
+
|
|
575
1334
|
// src/core/versionCalculator.ts
|
|
576
1335
|
var import_node_process3 = require("process");
|
|
577
1336
|
var import_conventional_recommended_bump = require("conventional-recommended-bump");
|
|
578
1337
|
var import_semver2 = __toESM(require("semver"), 1);
|
|
579
1338
|
|
|
580
1339
|
// src/utils/manifestHelpers.ts
|
|
581
|
-
var
|
|
582
|
-
var
|
|
1340
|
+
var import_node_fs5 = __toESM(require("fs"), 1);
|
|
1341
|
+
var import_node_path5 = __toESM(require("path"), 1);
|
|
583
1342
|
function getVersionFromManifests(packageDir) {
|
|
584
|
-
const packageJsonPath =
|
|
585
|
-
const cargoTomlPath =
|
|
586
|
-
if (
|
|
1343
|
+
const packageJsonPath = import_node_path5.default.join(packageDir, "package.json");
|
|
1344
|
+
const cargoTomlPath = import_node_path5.default.join(packageDir, "Cargo.toml");
|
|
1345
|
+
if (import_node_fs5.default.existsSync(packageJsonPath)) {
|
|
587
1346
|
try {
|
|
588
|
-
const packageJson = JSON.parse(
|
|
1347
|
+
const packageJson = JSON.parse(import_node_fs5.default.readFileSync(packageJsonPath, "utf-8"));
|
|
589
1348
|
if (packageJson.version) {
|
|
590
1349
|
log(`Found version ${packageJson.version} in package.json`, "debug");
|
|
591
1350
|
return {
|
|
@@ -601,7 +1360,7 @@ function getVersionFromManifests(packageDir) {
|
|
|
601
1360
|
log(`Error reading package.json: ${errMsg}`, "warning");
|
|
602
1361
|
}
|
|
603
1362
|
}
|
|
604
|
-
if (
|
|
1363
|
+
if (import_node_fs5.default.existsSync(cargoTomlPath)) {
|
|
605
1364
|
try {
|
|
606
1365
|
const cargoInfo = getCargoInfo(cargoTomlPath);
|
|
607
1366
|
if (cargoInfo.version) {
|
|
@@ -627,15 +1386,15 @@ function getVersionFromManifests(packageDir) {
|
|
|
627
1386
|
};
|
|
628
1387
|
}
|
|
629
1388
|
function throwIfNoManifestsFound(packageDir) {
|
|
630
|
-
const packageJsonPath =
|
|
631
|
-
const cargoTomlPath =
|
|
1389
|
+
const packageJsonPath = import_node_path5.default.join(packageDir, "package.json");
|
|
1390
|
+
const cargoTomlPath = import_node_path5.default.join(packageDir, "Cargo.toml");
|
|
632
1391
|
throw new Error(
|
|
633
1392
|
`Neither package.json nor Cargo.toml found at ${packageDir}. Checked paths: ${packageJsonPath}, ${cargoTomlPath}. Cannot determine version.`
|
|
634
1393
|
);
|
|
635
1394
|
}
|
|
636
1395
|
|
|
637
1396
|
// src/utils/versionUtils.ts
|
|
638
|
-
var
|
|
1397
|
+
var import_node_fs6 = __toESM(require("fs"), 1);
|
|
639
1398
|
var import_semver = __toESM(require("semver"), 1);
|
|
640
1399
|
var TOML2 = __toESM(require("smol-toml"), 1);
|
|
641
1400
|
var STANDARD_BUMP_TYPES = ["major", "minor", "patch"];
|
|
@@ -884,7 +1643,7 @@ var PackageProcessor = class {
|
|
|
884
1643
|
* Process packages based on targeting criteria
|
|
885
1644
|
*/
|
|
886
1645
|
async processPackages(packages) {
|
|
887
|
-
var _a;
|
|
1646
|
+
var _a, _b, _c, _d, _e;
|
|
888
1647
|
const tags = [];
|
|
889
1648
|
const updatedPackagesInfo = [];
|
|
890
1649
|
if (!packages || !Array.isArray(packages)) {
|
|
@@ -969,13 +1728,81 @@ var PackageProcessor = class {
|
|
|
969
1728
|
if (!nextVersion) {
|
|
970
1729
|
continue;
|
|
971
1730
|
}
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
1731
|
+
if (this.fullConfig.updateChangelog !== false) {
|
|
1732
|
+
let changelogEntries = [];
|
|
1733
|
+
try {
|
|
1734
|
+
changelogEntries = extractChangelogEntriesFromCommits(pkgPath, latestTag);
|
|
1735
|
+
if (changelogEntries.length === 0) {
|
|
1736
|
+
changelogEntries = [
|
|
1737
|
+
{
|
|
1738
|
+
type: "changed",
|
|
1739
|
+
description: `Update version to ${nextVersion}`
|
|
1740
|
+
}
|
|
1741
|
+
];
|
|
1742
|
+
}
|
|
1743
|
+
} catch (error) {
|
|
1744
|
+
log(
|
|
1745
|
+
`Error extracting changelog entries: ${error instanceof Error ? error.message : String(error)}`,
|
|
1746
|
+
"warning"
|
|
1747
|
+
);
|
|
1748
|
+
changelogEntries = [
|
|
1749
|
+
{
|
|
1750
|
+
type: "changed",
|
|
1751
|
+
description: `Update version to ${nextVersion}`
|
|
1752
|
+
}
|
|
1753
|
+
];
|
|
1754
|
+
}
|
|
1755
|
+
let repoUrl;
|
|
1756
|
+
try {
|
|
1757
|
+
const packageJsonPath2 = import_node_path6.default.join(pkgPath, "package.json");
|
|
1758
|
+
if (fs8.existsSync(packageJsonPath2)) {
|
|
1759
|
+
const packageJson = JSON.parse(fs8.readFileSync(packageJsonPath2, "utf8"));
|
|
1760
|
+
if (packageJson.repository) {
|
|
1761
|
+
if (typeof packageJson.repository === "string") {
|
|
1762
|
+
repoUrl = packageJson.repository;
|
|
1763
|
+
} else if (packageJson.repository.url) {
|
|
1764
|
+
repoUrl = packageJson.repository.url;
|
|
1765
|
+
}
|
|
1766
|
+
if ((repoUrl == null ? void 0 : repoUrl.startsWith("git+")) && (repoUrl == null ? void 0 : repoUrl.endsWith(".git"))) {
|
|
1767
|
+
repoUrl = repoUrl.substring(4, repoUrl.length - 4);
|
|
1768
|
+
}
|
|
1769
|
+
}
|
|
1770
|
+
}
|
|
1771
|
+
} catch (error) {
|
|
1772
|
+
log(
|
|
1773
|
+
`Could not determine repository URL for changelog links: ${error instanceof Error ? error.message : String(error)}`,
|
|
1774
|
+
"warning"
|
|
1775
|
+
);
|
|
1776
|
+
}
|
|
1777
|
+
updateChangelog(
|
|
1778
|
+
pkgPath,
|
|
1779
|
+
name,
|
|
1780
|
+
nextVersion,
|
|
1781
|
+
changelogEntries,
|
|
1782
|
+
repoUrl,
|
|
1783
|
+
this.fullConfig.changelogFormat
|
|
1784
|
+
);
|
|
1785
|
+
}
|
|
1786
|
+
const packageJsonPath = import_node_path6.default.join(pkgPath, "package.json");
|
|
1787
|
+
if (fs8.existsSync(packageJsonPath)) {
|
|
975
1788
|
updatePackageVersion(packageJsonPath, nextVersion);
|
|
976
1789
|
}
|
|
977
|
-
|
|
978
|
-
|
|
1790
|
+
const cargoEnabled = ((_a = this.fullConfig.cargo) == null ? void 0 : _a.enabled) !== false;
|
|
1791
|
+
if (cargoEnabled) {
|
|
1792
|
+
const cargoPaths = (_b = this.fullConfig.cargo) == null ? void 0 : _b.paths;
|
|
1793
|
+
if (cargoPaths && cargoPaths.length > 0) {
|
|
1794
|
+
for (const cargoPath of cargoPaths) {
|
|
1795
|
+
const resolvedCargoPath = import_node_path6.default.resolve(pkgPath, cargoPath, "Cargo.toml");
|
|
1796
|
+
if (fs8.existsSync(resolvedCargoPath)) {
|
|
1797
|
+
updatePackageVersion(resolvedCargoPath, nextVersion);
|
|
1798
|
+
}
|
|
1799
|
+
}
|
|
1800
|
+
} else {
|
|
1801
|
+
const cargoTomlPath = import_node_path6.default.join(pkgPath, "Cargo.toml");
|
|
1802
|
+
if (fs8.existsSync(cargoTomlPath)) {
|
|
1803
|
+
updatePackageVersion(cargoTomlPath, nextVersion);
|
|
1804
|
+
}
|
|
1805
|
+
}
|
|
979
1806
|
}
|
|
980
1807
|
const packageTag = formatTag(
|
|
981
1808
|
nextVersion,
|
|
@@ -1007,9 +1834,32 @@ var PackageProcessor = class {
|
|
|
1007
1834
|
log("No targeted packages required a version update.", "info");
|
|
1008
1835
|
return { updatedPackages: [], tags };
|
|
1009
1836
|
}
|
|
1010
|
-
const filesToCommit =
|
|
1837
|
+
const filesToCommit = [];
|
|
1838
|
+
for (const info of updatedPackagesInfo) {
|
|
1839
|
+
const packageJsonPath = import_node_path6.default.join(info.path, "package.json");
|
|
1840
|
+
if (fs8.existsSync(packageJsonPath)) {
|
|
1841
|
+
filesToCommit.push(packageJsonPath);
|
|
1842
|
+
}
|
|
1843
|
+
const cargoEnabled = ((_c = this.fullConfig.cargo) == null ? void 0 : _c.enabled) !== false;
|
|
1844
|
+
if (cargoEnabled) {
|
|
1845
|
+
const cargoPaths = (_d = this.fullConfig.cargo) == null ? void 0 : _d.paths;
|
|
1846
|
+
if (cargoPaths && cargoPaths.length > 0) {
|
|
1847
|
+
for (const cargoPath of cargoPaths) {
|
|
1848
|
+
const resolvedCargoPath = import_node_path6.default.resolve(info.path, cargoPath, "Cargo.toml");
|
|
1849
|
+
if (fs8.existsSync(resolvedCargoPath)) {
|
|
1850
|
+
filesToCommit.push(resolvedCargoPath);
|
|
1851
|
+
}
|
|
1852
|
+
}
|
|
1853
|
+
} else {
|
|
1854
|
+
const cargoTomlPath = import_node_path6.default.join(info.path, "Cargo.toml");
|
|
1855
|
+
if (fs8.existsSync(cargoTomlPath)) {
|
|
1856
|
+
filesToCommit.push(cargoTomlPath);
|
|
1857
|
+
}
|
|
1858
|
+
}
|
|
1859
|
+
}
|
|
1860
|
+
}
|
|
1011
1861
|
const packageNames = updatedPackagesInfo.map((p) => p.name).join(", ");
|
|
1012
|
-
const representativeVersion = ((
|
|
1862
|
+
const representativeVersion = ((_e = updatedPackagesInfo[0]) == null ? void 0 : _e.version) || "multiple";
|
|
1013
1863
|
let commitMessage = this.commitMessageTemplate || "chore(release): publish packages";
|
|
1014
1864
|
const placeholderRegex = /\$\{[^}]+\}/;
|
|
1015
1865
|
if (updatedPackagesInfo.length === 1 && placeholderRegex.test(commitMessage)) {
|
|
@@ -1086,20 +1936,21 @@ function createSyncedStrategy(config) {
|
|
|
1086
1936
|
const files = [];
|
|
1087
1937
|
const updatedPackages = [];
|
|
1088
1938
|
try {
|
|
1089
|
-
const rootPkgPath =
|
|
1090
|
-
if (
|
|
1939
|
+
const rootPkgPath = path7.join(packages.root, "package.json");
|
|
1940
|
+
if (import_node_fs7.default.existsSync(rootPkgPath)) {
|
|
1091
1941
|
updatePackageVersion(rootPkgPath, nextVersion);
|
|
1092
1942
|
files.push(rootPkgPath);
|
|
1093
1943
|
updatedPackages.push("root");
|
|
1094
1944
|
}
|
|
1095
|
-
} catch (
|
|
1096
|
-
|
|
1945
|
+
} catch (error) {
|
|
1946
|
+
const errMessage = error instanceof Error ? error.message : String(error);
|
|
1947
|
+
log(`Failed to update root package.json: ${errMessage}`, "error");
|
|
1097
1948
|
}
|
|
1098
1949
|
for (const pkg of packages.packages) {
|
|
1099
1950
|
if (!shouldProcessPackage(pkg, config)) {
|
|
1100
1951
|
continue;
|
|
1101
1952
|
}
|
|
1102
|
-
const packageJsonPath =
|
|
1953
|
+
const packageJsonPath = path7.join(pkg.dir, "package.json");
|
|
1103
1954
|
updatePackageVersion(packageJsonPath, nextVersion);
|
|
1104
1955
|
files.push(packageJsonPath);
|
|
1105
1956
|
updatedPackages.push(pkg.packageJson.name);
|
|
@@ -1172,7 +2023,7 @@ function createSingleStrategy(config) {
|
|
|
1172
2023
|
log(`No version change needed for ${packageName}`, "info");
|
|
1173
2024
|
return;
|
|
1174
2025
|
}
|
|
1175
|
-
const packageJsonPath =
|
|
2026
|
+
const packageJsonPath = path7.join(pkgPath, "package.json");
|
|
1176
2027
|
updatePackageVersion(packageJsonPath, nextVersion);
|
|
1177
2028
|
log(`Updated package ${packageName} to version ${nextVersion}`, "success");
|
|
1178
2029
|
const nextTag = formatTag(
|
|
@@ -1351,11 +2202,11 @@ var VersionEngine = class {
|
|
|
1351
2202
|
var import_meta = {};
|
|
1352
2203
|
function getPackageVersion() {
|
|
1353
2204
|
try {
|
|
1354
|
-
const packageJsonPath =
|
|
1355
|
-
|
|
2205
|
+
const packageJsonPath = import_node_path7.default.resolve(
|
|
2206
|
+
import_node_path7.default.dirname(import_meta.url.replace("file:", "")),
|
|
1356
2207
|
"../package.json"
|
|
1357
2208
|
);
|
|
1358
|
-
const packageJsonContent =
|
|
2209
|
+
const packageJsonContent = fs10.readFileSync(packageJsonPath, "utf-8");
|
|
1359
2210
|
const packageJson = JSON.parse(packageJsonContent);
|
|
1360
2211
|
return packageJson.version || "0.0.0";
|
|
1361
2212
|
} catch (error) {
|
|
@@ -1364,53 +2215,94 @@ function getPackageVersion() {
|
|
|
1364
2215
|
}
|
|
1365
2216
|
}
|
|
1366
2217
|
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
2218
|
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");
|
|
2219
|
+
const buildTimestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
2220
|
+
const packageVersion = getPackageVersion();
|
|
2221
|
+
log(`package-versioner v${packageVersion} (Build: ${buildTimestamp})`, "debug");
|
|
2222
|
+
const program = new import_commander.Command();
|
|
2223
|
+
program.name("package-versioner").description(
|
|
2224
|
+
"A lightweight yet powerful CLI tool for automated semantic versioning based on Git history and conventional commits."
|
|
2225
|
+
).version(packageVersion);
|
|
2226
|
+
program.command("version", { isDefault: true }).description("Version a package or packages based on configuration").option(
|
|
2227
|
+
"-c, --config <path>",
|
|
2228
|
+
"Path to config file (defaults to version.config.json in current directory)"
|
|
2229
|
+
).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) => {
|
|
2230
|
+
if (options.json) {
|
|
2231
|
+
enableJsonOutput(options.dryRun);
|
|
1406
2232
|
}
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
2233
|
+
try {
|
|
2234
|
+
const config = await loadConfig(options.config);
|
|
2235
|
+
log(`Loaded configuration from ${options.config || "version.config.json"}`, "info");
|
|
2236
|
+
if (options.dryRun) config.dryRun = true;
|
|
2237
|
+
if (options.synced) config.synced = true;
|
|
2238
|
+
if (options.bump) config.type = options.bump;
|
|
2239
|
+
if (options.prerelease)
|
|
2240
|
+
config.prereleaseIdentifier = options.prerelease === true ? "next" : options.prerelease;
|
|
2241
|
+
const cliTargets = options.target ? options.target.split(",").map((t) => t.trim()) : [];
|
|
2242
|
+
const engine = new VersionEngine(config, !!options.json);
|
|
2243
|
+
if (config.synced) {
|
|
2244
|
+
log("Using synced versioning strategy.", "info");
|
|
2245
|
+
engine.setStrategy("synced");
|
|
2246
|
+
await engine.run();
|
|
2247
|
+
} else if (config.packages && config.packages.length === 1) {
|
|
2248
|
+
log("Using single package versioning strategy.", "info");
|
|
2249
|
+
if (cliTargets.length > 0) {
|
|
2250
|
+
log("--target flag is ignored for single package strategy.", "warning");
|
|
2251
|
+
}
|
|
2252
|
+
engine.setStrategy("single");
|
|
2253
|
+
await engine.run();
|
|
2254
|
+
} else {
|
|
2255
|
+
log("Using async versioning strategy.", "info");
|
|
2256
|
+
if (cliTargets.length > 0) {
|
|
2257
|
+
log(`Targeting specific packages: ${cliTargets.join(", ")}`, "info");
|
|
2258
|
+
}
|
|
2259
|
+
engine.setStrategy("async");
|
|
2260
|
+
await engine.run(cliTargets);
|
|
2261
|
+
}
|
|
2262
|
+
log("Versioning process completed.", "success");
|
|
2263
|
+
printJsonOutput();
|
|
2264
|
+
} catch (error) {
|
|
2265
|
+
log(error instanceof Error ? error.message : String(error), "error");
|
|
2266
|
+
process.exit(1);
|
|
2267
|
+
}
|
|
2268
|
+
});
|
|
2269
|
+
program.command("regenerate-changelog").description("Regenerate a complete changelog from git history").option("-o, --output <path>", "Output path for changelog file", "CHANGELOG.md").option(
|
|
2270
|
+
"-f, --format <format>",
|
|
2271
|
+
"Changelog format (keep-a-changelog|angular)",
|
|
2272
|
+
"keep-a-changelog"
|
|
2273
|
+
).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) => {
|
|
2274
|
+
try {
|
|
2275
|
+
log("Regenerating changelog from git history...", "info");
|
|
2276
|
+
if (options.format !== "keep-a-changelog" && options.format !== "angular") {
|
|
2277
|
+
throw new Error(
|
|
2278
|
+
'Invalid format specified. Must be either "keep-a-changelog" or "angular"'
|
|
2279
|
+
);
|
|
2280
|
+
}
|
|
2281
|
+
const regenerateOptions = {
|
|
2282
|
+
format: options.format,
|
|
2283
|
+
since: options.since,
|
|
2284
|
+
output: options.output,
|
|
2285
|
+
dryRun: options.dryRun,
|
|
2286
|
+
projectDir: options.projectDir,
|
|
2287
|
+
repoUrl: options.repoUrl
|
|
2288
|
+
};
|
|
2289
|
+
const content = await regenerateChangelog(regenerateOptions);
|
|
2290
|
+
await writeChangelog(
|
|
2291
|
+
content,
|
|
2292
|
+
import_node_path7.default.resolve(options.projectDir, options.output),
|
|
2293
|
+
options.dryRun
|
|
2294
|
+
);
|
|
2295
|
+
if (!options.dryRun) {
|
|
2296
|
+
log(`Changelog successfully regenerated at ${options.output}`, "success");
|
|
2297
|
+
}
|
|
2298
|
+
} catch (error) {
|
|
2299
|
+
log(error instanceof Error ? error.message : String(error), "error");
|
|
2300
|
+
process.exit(1);
|
|
2301
|
+
}
|
|
2302
|
+
});
|
|
2303
|
+
program.parse(process.argv);
|
|
1412
2304
|
} catch (error) {
|
|
1413
|
-
|
|
2305
|
+
console.error("Fatal error:", error);
|
|
1414
2306
|
process.exit(1);
|
|
1415
2307
|
}
|
|
1416
2308
|
}
|