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