@releasekit/notes 0.2.0 → 0.3.0-next.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 +1 -1
- package/dist/aggregator-BDTUZWOA.js +13 -0
- package/dist/chunk-H7G2HRHI.js +134 -0
- package/dist/chunk-O4VCGEZT.js +147 -0
- package/dist/{chunk-DGZ6TM5J.js → chunk-X4LY5WGG.js} +132 -354
- package/dist/cli.cjs +382 -326
- package/dist/cli.js +6 -27
- package/dist/index.cjs +384 -307
- package/dist/index.d.cts +11 -4
- package/dist/index.d.ts +11 -4
- package/dist/index.js +12 -6
- package/package.json +2 -2
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
import {
|
|
2
|
+
formatVersion,
|
|
3
|
+
renderMarkdown,
|
|
4
|
+
writeMarkdown
|
|
5
|
+
} from "./chunk-H7G2HRHI.js";
|
|
6
|
+
|
|
1
7
|
// src/core/config.ts
|
|
2
8
|
import {
|
|
3
9
|
loadAuth,
|
|
@@ -145,138 +151,10 @@ async function parsePackageVersionerStdin() {
|
|
|
145
151
|
return parsePackageVersioner(content);
|
|
146
152
|
}
|
|
147
153
|
|
|
148
|
-
// src/output/
|
|
154
|
+
// src/output/json.ts
|
|
149
155
|
import * as fs2 from "fs";
|
|
150
156
|
import * as path from "path";
|
|
151
157
|
import { debug, info, success } from "@releasekit/core";
|
|
152
|
-
var TYPE_ORDER = ["added", "changed", "deprecated", "removed", "fixed", "security"];
|
|
153
|
-
var TYPE_LABELS = {
|
|
154
|
-
added: "Added",
|
|
155
|
-
changed: "Changed",
|
|
156
|
-
deprecated: "Deprecated",
|
|
157
|
-
removed: "Removed",
|
|
158
|
-
fixed: "Fixed",
|
|
159
|
-
security: "Security"
|
|
160
|
-
};
|
|
161
|
-
function groupEntriesByType(entries) {
|
|
162
|
-
const grouped = /* @__PURE__ */ new Map();
|
|
163
|
-
for (const type of TYPE_ORDER) {
|
|
164
|
-
grouped.set(type, []);
|
|
165
|
-
}
|
|
166
|
-
for (const entry of entries) {
|
|
167
|
-
const existing = grouped.get(entry.type) ?? [];
|
|
168
|
-
existing.push(entry);
|
|
169
|
-
grouped.set(entry.type, existing);
|
|
170
|
-
}
|
|
171
|
-
return grouped;
|
|
172
|
-
}
|
|
173
|
-
function formatEntry(entry) {
|
|
174
|
-
let line;
|
|
175
|
-
if (entry.breaking && entry.scope) {
|
|
176
|
-
line = `- **BREAKING** **${entry.scope}**: ${entry.description}`;
|
|
177
|
-
} else if (entry.breaking) {
|
|
178
|
-
line = `- **BREAKING** ${entry.description}`;
|
|
179
|
-
} else if (entry.scope) {
|
|
180
|
-
line = `- **${entry.scope}**: ${entry.description}`;
|
|
181
|
-
} else {
|
|
182
|
-
line = `- ${entry.description}`;
|
|
183
|
-
}
|
|
184
|
-
if (entry.issueIds && entry.issueIds.length > 0) {
|
|
185
|
-
line += ` (${entry.issueIds.join(", ")})`;
|
|
186
|
-
}
|
|
187
|
-
return line;
|
|
188
|
-
}
|
|
189
|
-
function formatVersion(context) {
|
|
190
|
-
const lines = [];
|
|
191
|
-
const versionHeader = context.previousVersion ? `## [${context.version}]` : `## ${context.version}`;
|
|
192
|
-
lines.push(`${versionHeader} - ${context.date}`);
|
|
193
|
-
lines.push("");
|
|
194
|
-
if (context.compareUrl) {
|
|
195
|
-
lines.push(`[Full Changelog](${context.compareUrl})`);
|
|
196
|
-
lines.push("");
|
|
197
|
-
}
|
|
198
|
-
if (context.enhanced?.summary) {
|
|
199
|
-
lines.push(context.enhanced.summary);
|
|
200
|
-
lines.push("");
|
|
201
|
-
}
|
|
202
|
-
const grouped = groupEntriesByType(context.entries);
|
|
203
|
-
for (const [type, entries] of grouped) {
|
|
204
|
-
if (entries.length === 0) continue;
|
|
205
|
-
lines.push(`### ${TYPE_LABELS[type]}`);
|
|
206
|
-
for (const entry of entries) {
|
|
207
|
-
lines.push(formatEntry(entry));
|
|
208
|
-
}
|
|
209
|
-
lines.push("");
|
|
210
|
-
}
|
|
211
|
-
return lines.join("\n");
|
|
212
|
-
}
|
|
213
|
-
function formatHeader() {
|
|
214
|
-
return `# Changelog
|
|
215
|
-
|
|
216
|
-
All notable changes to this project will be documented in this file.
|
|
217
|
-
|
|
218
|
-
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
219
|
-
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
220
|
-
|
|
221
|
-
`;
|
|
222
|
-
}
|
|
223
|
-
function renderMarkdown(contexts) {
|
|
224
|
-
const sections = [formatHeader()];
|
|
225
|
-
for (const context of contexts) {
|
|
226
|
-
sections.push(formatVersion(context));
|
|
227
|
-
}
|
|
228
|
-
return sections.join("\n");
|
|
229
|
-
}
|
|
230
|
-
function prependVersion(existingPath, context) {
|
|
231
|
-
let existing = "";
|
|
232
|
-
if (fs2.existsSync(existingPath)) {
|
|
233
|
-
existing = fs2.readFileSync(existingPath, "utf-8");
|
|
234
|
-
const headerEnd = existing.indexOf("\n## ");
|
|
235
|
-
if (headerEnd >= 0) {
|
|
236
|
-
const header = existing.slice(0, headerEnd);
|
|
237
|
-
const body = existing.slice(headerEnd + 1);
|
|
238
|
-
const newVersion = formatVersion(context);
|
|
239
|
-
return `${header}
|
|
240
|
-
|
|
241
|
-
${newVersion}
|
|
242
|
-
${body}`;
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
return renderMarkdown([context]);
|
|
246
|
-
}
|
|
247
|
-
function writeMarkdown(outputPath, contexts, config, dryRun) {
|
|
248
|
-
const content = renderMarkdown(contexts);
|
|
249
|
-
if (dryRun) {
|
|
250
|
-
info(`Would write changelog to ${outputPath}`);
|
|
251
|
-
debug("--- Changelog Preview ---");
|
|
252
|
-
debug(content);
|
|
253
|
-
debug("--- End Preview ---");
|
|
254
|
-
return;
|
|
255
|
-
}
|
|
256
|
-
const dir = path.dirname(outputPath);
|
|
257
|
-
if (!fs2.existsSync(dir)) {
|
|
258
|
-
fs2.mkdirSync(dir, { recursive: true });
|
|
259
|
-
}
|
|
260
|
-
if (outputPath === "-") {
|
|
261
|
-
process.stdout.write(content);
|
|
262
|
-
return;
|
|
263
|
-
}
|
|
264
|
-
if (config.updateStrategy === "prepend" && fs2.existsSync(outputPath) && contexts.length === 1) {
|
|
265
|
-
const firstContext = contexts[0];
|
|
266
|
-
if (firstContext) {
|
|
267
|
-
const updated = prependVersion(outputPath, firstContext);
|
|
268
|
-
fs2.writeFileSync(outputPath, updated, "utf-8");
|
|
269
|
-
}
|
|
270
|
-
} else {
|
|
271
|
-
fs2.writeFileSync(outputPath, content, "utf-8");
|
|
272
|
-
}
|
|
273
|
-
success(`Changelog written to ${outputPath}`);
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
// src/output/json.ts
|
|
277
|
-
import * as fs3 from "fs";
|
|
278
|
-
import * as path2 from "path";
|
|
279
|
-
import { debug as debug2, info as info2, success as success2 } from "@releasekit/core";
|
|
280
158
|
function renderJson(contexts) {
|
|
281
159
|
return JSON.stringify(
|
|
282
160
|
{
|
|
@@ -296,24 +174,24 @@ function renderJson(contexts) {
|
|
|
296
174
|
function writeJson(outputPath, contexts, dryRun) {
|
|
297
175
|
const content = renderJson(contexts);
|
|
298
176
|
if (dryRun) {
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
177
|
+
info(`Would write JSON output to ${outputPath}`);
|
|
178
|
+
debug("--- JSON Output Preview ---");
|
|
179
|
+
debug(content);
|
|
180
|
+
debug("--- End Preview ---");
|
|
303
181
|
return;
|
|
304
182
|
}
|
|
305
|
-
const dir =
|
|
306
|
-
if (!
|
|
307
|
-
|
|
183
|
+
const dir = path.dirname(outputPath);
|
|
184
|
+
if (!fs2.existsSync(dir)) {
|
|
185
|
+
fs2.mkdirSync(dir, { recursive: true });
|
|
308
186
|
}
|
|
309
|
-
|
|
310
|
-
|
|
187
|
+
fs2.writeFileSync(outputPath, content, "utf-8");
|
|
188
|
+
success(`JSON output written to ${outputPath}`);
|
|
311
189
|
}
|
|
312
190
|
|
|
313
191
|
// src/core/pipeline.ts
|
|
314
|
-
import * as
|
|
315
|
-
import * as
|
|
316
|
-
import { debug as
|
|
192
|
+
import * as fs7 from "fs";
|
|
193
|
+
import * as path5 from "path";
|
|
194
|
+
import { debug as debug2, info as info3, success as success3, warn as warn3 } from "@releasekit/core";
|
|
317
195
|
|
|
318
196
|
// src/llm/defaults.ts
|
|
319
197
|
var LLM_DEFAULTS = {
|
|
@@ -949,7 +827,7 @@ function createProvider(config) {
|
|
|
949
827
|
|
|
950
828
|
// src/output/github-release.ts
|
|
951
829
|
import { Octokit } from "@octokit/rest";
|
|
952
|
-
import { info as
|
|
830
|
+
import { info as info2, success as success2 } from "@releasekit/core";
|
|
953
831
|
var GitHubClient = class {
|
|
954
832
|
octokit;
|
|
955
833
|
owner;
|
|
@@ -971,7 +849,7 @@ var GitHubClient = class {
|
|
|
971
849
|
} else {
|
|
972
850
|
body = renderMarkdown([context]);
|
|
973
851
|
}
|
|
974
|
-
|
|
852
|
+
info2(`Creating GitHub release for ${tagName}`);
|
|
975
853
|
try {
|
|
976
854
|
const response = await this.octokit.repos.createRelease({
|
|
977
855
|
owner: this.owner,
|
|
@@ -983,7 +861,7 @@ var GitHubClient = class {
|
|
|
983
861
|
prerelease: options.prerelease ?? false,
|
|
984
862
|
generate_release_notes: options.generateNotes ?? false
|
|
985
863
|
});
|
|
986
|
-
|
|
864
|
+
success2(`Release created: ${response.data.html_url}`);
|
|
987
865
|
return {
|
|
988
866
|
id: response.data.id,
|
|
989
867
|
htmlUrl: response.data.html_url,
|
|
@@ -1001,7 +879,7 @@ var GitHubClient = class {
|
|
|
1001
879
|
} else {
|
|
1002
880
|
body = renderMarkdown([context]);
|
|
1003
881
|
}
|
|
1004
|
-
|
|
882
|
+
info2(`Updating GitHub release ${releaseId}`);
|
|
1005
883
|
try {
|
|
1006
884
|
const response = await this.octokit.repos.updateRelease({
|
|
1007
885
|
owner: this.owner,
|
|
@@ -1013,7 +891,7 @@ var GitHubClient = class {
|
|
|
1013
891
|
draft: options.draft ?? false,
|
|
1014
892
|
prerelease: options.prerelease ?? false
|
|
1015
893
|
});
|
|
1016
|
-
|
|
894
|
+
success2(`Release updated: ${response.data.html_url}`);
|
|
1017
895
|
return {
|
|
1018
896
|
id: response.data.id,
|
|
1019
897
|
htmlUrl: response.data.html_url,
|
|
@@ -1063,7 +941,7 @@ async function createGitHubRelease(context, options) {
|
|
|
1063
941
|
}
|
|
1064
942
|
|
|
1065
943
|
// src/templates/ejs.ts
|
|
1066
|
-
import * as
|
|
944
|
+
import * as fs3 from "fs";
|
|
1067
945
|
import ejs from "ejs";
|
|
1068
946
|
function renderEjs(template, context) {
|
|
1069
947
|
try {
|
|
@@ -1073,16 +951,16 @@ function renderEjs(template, context) {
|
|
|
1073
951
|
}
|
|
1074
952
|
}
|
|
1075
953
|
function renderEjsFile(filePath, context) {
|
|
1076
|
-
if (!
|
|
954
|
+
if (!fs3.existsSync(filePath)) {
|
|
1077
955
|
throw new TemplateError(`Template file not found: ${filePath}`);
|
|
1078
956
|
}
|
|
1079
|
-
const template =
|
|
957
|
+
const template = fs3.readFileSync(filePath, "utf-8");
|
|
1080
958
|
return renderEjs(template, context);
|
|
1081
959
|
}
|
|
1082
960
|
|
|
1083
961
|
// src/templates/handlebars.ts
|
|
1084
|
-
import * as
|
|
1085
|
-
import * as
|
|
962
|
+
import * as fs4 from "fs";
|
|
963
|
+
import * as path2 from "path";
|
|
1086
964
|
import Handlebars from "handlebars";
|
|
1087
965
|
function registerHandlebarsHelpers() {
|
|
1088
966
|
Handlebars.registerHelper("capitalize", (str) => {
|
|
@@ -1108,28 +986,28 @@ function renderHandlebars(template, context) {
|
|
|
1108
986
|
}
|
|
1109
987
|
}
|
|
1110
988
|
function renderHandlebarsFile(filePath, context) {
|
|
1111
|
-
if (!
|
|
989
|
+
if (!fs4.existsSync(filePath)) {
|
|
1112
990
|
throw new TemplateError(`Template file not found: ${filePath}`);
|
|
1113
991
|
}
|
|
1114
|
-
const template =
|
|
992
|
+
const template = fs4.readFileSync(filePath, "utf-8");
|
|
1115
993
|
return renderHandlebars(template, context);
|
|
1116
994
|
}
|
|
1117
995
|
function renderHandlebarsComposable(templateDir, context) {
|
|
1118
996
|
registerHandlebarsHelpers();
|
|
1119
|
-
const versionPath =
|
|
1120
|
-
const entryPath =
|
|
1121
|
-
const documentPath =
|
|
1122
|
-
if (!
|
|
997
|
+
const versionPath = path2.join(templateDir, "version.hbs");
|
|
998
|
+
const entryPath = path2.join(templateDir, "entry.hbs");
|
|
999
|
+
const documentPath = path2.join(templateDir, "document.hbs");
|
|
1000
|
+
if (!fs4.existsSync(documentPath)) {
|
|
1123
1001
|
throw new TemplateError(`Document template not found: ${documentPath}`);
|
|
1124
1002
|
}
|
|
1125
|
-
if (
|
|
1126
|
-
Handlebars.registerPartial("version",
|
|
1003
|
+
if (fs4.existsSync(versionPath)) {
|
|
1004
|
+
Handlebars.registerPartial("version", fs4.readFileSync(versionPath, "utf-8"));
|
|
1127
1005
|
}
|
|
1128
|
-
if (
|
|
1129
|
-
Handlebars.registerPartial("entry",
|
|
1006
|
+
if (fs4.existsSync(entryPath)) {
|
|
1007
|
+
Handlebars.registerPartial("entry", fs4.readFileSync(entryPath, "utf-8"));
|
|
1130
1008
|
}
|
|
1131
1009
|
try {
|
|
1132
|
-
const compiled = Handlebars.compile(
|
|
1010
|
+
const compiled = Handlebars.compile(fs4.readFileSync(documentPath, "utf-8"));
|
|
1133
1011
|
return compiled(context);
|
|
1134
1012
|
} catch (error) {
|
|
1135
1013
|
throw new TemplateError(`Handlebars render error: ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -1137,8 +1015,8 @@ function renderHandlebarsComposable(templateDir, context) {
|
|
|
1137
1015
|
}
|
|
1138
1016
|
|
|
1139
1017
|
// src/templates/liquid.ts
|
|
1140
|
-
import * as
|
|
1141
|
-
import * as
|
|
1018
|
+
import * as fs5 from "fs";
|
|
1019
|
+
import * as path3 from "path";
|
|
1142
1020
|
import { Liquid } from "liquidjs";
|
|
1143
1021
|
function createLiquidEngine(root) {
|
|
1144
1022
|
return new Liquid({
|
|
@@ -1156,15 +1034,15 @@ function renderLiquid(template, context) {
|
|
|
1156
1034
|
}
|
|
1157
1035
|
}
|
|
1158
1036
|
function renderLiquidFile(filePath, context) {
|
|
1159
|
-
if (!
|
|
1037
|
+
if (!fs5.existsSync(filePath)) {
|
|
1160
1038
|
throw new TemplateError(`Template file not found: ${filePath}`);
|
|
1161
1039
|
}
|
|
1162
|
-
const template =
|
|
1040
|
+
const template = fs5.readFileSync(filePath, "utf-8");
|
|
1163
1041
|
return renderLiquid(template, context);
|
|
1164
1042
|
}
|
|
1165
1043
|
function renderLiquidComposable(templateDir, context) {
|
|
1166
|
-
const documentPath =
|
|
1167
|
-
if (!
|
|
1044
|
+
const documentPath = path3.join(templateDir, "document.liquid");
|
|
1045
|
+
if (!fs5.existsSync(documentPath)) {
|
|
1168
1046
|
throw new TemplateError(`Document template not found: ${documentPath}`);
|
|
1169
1047
|
}
|
|
1170
1048
|
const engine = createLiquidEngine(templateDir);
|
|
@@ -1176,10 +1054,10 @@ function renderLiquidComposable(templateDir, context) {
|
|
|
1176
1054
|
}
|
|
1177
1055
|
|
|
1178
1056
|
// src/templates/loader.ts
|
|
1179
|
-
import * as
|
|
1180
|
-
import * as
|
|
1057
|
+
import * as fs6 from "fs";
|
|
1058
|
+
import * as path4 from "path";
|
|
1181
1059
|
function getEngineFromFile(filePath) {
|
|
1182
|
-
const ext =
|
|
1060
|
+
const ext = path4.extname(filePath).toLowerCase();
|
|
1183
1061
|
switch (ext) {
|
|
1184
1062
|
case ".liquid":
|
|
1185
1063
|
return "liquid";
|
|
@@ -1213,10 +1091,10 @@ function getRenderFileFn(engine) {
|
|
|
1213
1091
|
}
|
|
1214
1092
|
}
|
|
1215
1093
|
function detectTemplateMode(templatePath) {
|
|
1216
|
-
if (!
|
|
1094
|
+
if (!fs6.existsSync(templatePath)) {
|
|
1217
1095
|
throw new TemplateError(`Template path not found: ${templatePath}`);
|
|
1218
1096
|
}
|
|
1219
|
-
const stat =
|
|
1097
|
+
const stat = fs6.statSync(templatePath);
|
|
1220
1098
|
if (stat.isFile()) {
|
|
1221
1099
|
return "single";
|
|
1222
1100
|
}
|
|
@@ -1234,7 +1112,7 @@ function renderSingleFile(templatePath, context, engine) {
|
|
|
1234
1112
|
};
|
|
1235
1113
|
}
|
|
1236
1114
|
function renderComposable(templateDir, context, engine) {
|
|
1237
|
-
const files =
|
|
1115
|
+
const files = fs6.readdirSync(templateDir);
|
|
1238
1116
|
const engineMap = {
|
|
1239
1117
|
liquid: { document: "document.liquid", version: "version.liquid", entry: "entry.liquid" },
|
|
1240
1118
|
handlebars: { document: "document.hbs", version: "version.hbs", entry: "entry.hbs" },
|
|
@@ -1257,15 +1135,15 @@ function renderComposable(templateDir, context, engine) {
|
|
|
1257
1135
|
return { content: renderHandlebarsComposable(templateDir, context), engine: resolvedEngine };
|
|
1258
1136
|
}
|
|
1259
1137
|
const expectedFiles = engineMap[resolvedEngine];
|
|
1260
|
-
const documentPath =
|
|
1261
|
-
if (!
|
|
1138
|
+
const documentPath = path4.join(templateDir, expectedFiles.document);
|
|
1139
|
+
if (!fs6.existsSync(documentPath)) {
|
|
1262
1140
|
throw new TemplateError(`Document template not found: ${expectedFiles.document}`);
|
|
1263
1141
|
}
|
|
1264
|
-
const versionPath =
|
|
1265
|
-
const entryPath =
|
|
1142
|
+
const versionPath = path4.join(templateDir, expectedFiles.version);
|
|
1143
|
+
const entryPath = path4.join(templateDir, expectedFiles.entry);
|
|
1266
1144
|
const render = getRenderFn(resolvedEngine);
|
|
1267
|
-
const entryTemplate =
|
|
1268
|
-
const versionTemplate =
|
|
1145
|
+
const entryTemplate = fs6.existsSync(entryPath) ? fs6.readFileSync(entryPath, "utf-8") : null;
|
|
1146
|
+
const versionTemplate = fs6.existsSync(versionPath) ? fs6.readFileSync(versionPath, "utf-8") : null;
|
|
1269
1147
|
if (entryTemplate && versionTemplate) {
|
|
1270
1148
|
const versionsWithEntries = context.versions.map((versionCtx) => {
|
|
1271
1149
|
const entries = versionCtx.entries.map((entry) => {
|
|
@@ -1276,7 +1154,7 @@ function renderComposable(templateDir, context, engine) {
|
|
|
1276
1154
|
});
|
|
1277
1155
|
const docContext = { ...context, renderedVersions: versionsWithEntries };
|
|
1278
1156
|
return {
|
|
1279
|
-
content: render(
|
|
1157
|
+
content: render(fs6.readFileSync(documentPath, "utf-8"), docContext),
|
|
1280
1158
|
engine: resolvedEngine
|
|
1281
1159
|
};
|
|
1282
1160
|
}
|
|
@@ -1383,9 +1261,9 @@ async function processWithLLM(context, config) {
|
|
|
1383
1261
|
entries: context.entries
|
|
1384
1262
|
};
|
|
1385
1263
|
try {
|
|
1386
|
-
|
|
1264
|
+
info3(`Using LLM provider: ${config.llm.provider}${config.llm.model ? ` (${config.llm.model})` : ""}`);
|
|
1387
1265
|
if (config.llm.baseURL) {
|
|
1388
|
-
|
|
1266
|
+
info3(`LLM base URL: ${config.llm.baseURL}`);
|
|
1389
1267
|
}
|
|
1390
1268
|
const rawProvider = createProvider(config.llm);
|
|
1391
1269
|
const retryOpts = config.llm.retry ?? LLM_DEFAULTS.retry;
|
|
@@ -1394,47 +1272,47 @@ async function processWithLLM(context, config) {
|
|
|
1394
1272
|
complete: (prompt, opts) => withRetry(() => rawProvider.complete(prompt, opts), retryOpts)
|
|
1395
1273
|
};
|
|
1396
1274
|
const activeTasks = Object.entries(tasks).filter(([, enabled]) => enabled).map(([name]) => name);
|
|
1397
|
-
|
|
1275
|
+
info3(`Running LLM tasks: ${activeTasks.join(", ")}`);
|
|
1398
1276
|
if (tasks.enhance && tasks.categorize) {
|
|
1399
|
-
|
|
1277
|
+
info3("Enhancing and categorizing entries with LLM...");
|
|
1400
1278
|
const result = await enhanceAndCategorize(provider, context.entries, llmContext);
|
|
1401
1279
|
enhanced.entries = result.enhancedEntries;
|
|
1402
1280
|
enhanced.categories = {};
|
|
1403
1281
|
for (const cat of result.categories) {
|
|
1404
1282
|
enhanced.categories[cat.category] = cat.entries;
|
|
1405
1283
|
}
|
|
1406
|
-
|
|
1284
|
+
info3(`Enhanced ${enhanced.entries.length} entries into ${result.categories.length} categories`);
|
|
1407
1285
|
} else {
|
|
1408
1286
|
if (tasks.enhance) {
|
|
1409
|
-
|
|
1287
|
+
info3("Enhancing entries with LLM...");
|
|
1410
1288
|
enhanced.entries = await enhanceEntries(provider, context.entries, llmContext, config.llm.concurrency);
|
|
1411
|
-
|
|
1289
|
+
info3(`Enhanced ${enhanced.entries.length} entries`);
|
|
1412
1290
|
}
|
|
1413
1291
|
if (tasks.categorize) {
|
|
1414
|
-
|
|
1292
|
+
info3("Categorizing entries with LLM...");
|
|
1415
1293
|
const categorized = await categorizeEntries(provider, enhanced.entries, llmContext);
|
|
1416
1294
|
enhanced.categories = {};
|
|
1417
1295
|
for (const cat of categorized) {
|
|
1418
1296
|
enhanced.categories[cat.category] = cat.entries;
|
|
1419
1297
|
}
|
|
1420
|
-
|
|
1298
|
+
info3(`Created ${categorized.length} categories`);
|
|
1421
1299
|
}
|
|
1422
1300
|
}
|
|
1423
1301
|
if (tasks.summarize) {
|
|
1424
|
-
|
|
1302
|
+
info3("Summarizing entries with LLM...");
|
|
1425
1303
|
enhanced.summary = await summarizeEntries(provider, enhanced.entries, llmContext);
|
|
1426
1304
|
if (enhanced.summary) {
|
|
1427
|
-
|
|
1428
|
-
|
|
1305
|
+
info3("Summary generated successfully");
|
|
1306
|
+
debug2(`Summary: ${enhanced.summary.substring(0, 100)}...`);
|
|
1429
1307
|
} else {
|
|
1430
1308
|
warn3("Summary generation returned empty result");
|
|
1431
1309
|
}
|
|
1432
1310
|
}
|
|
1433
1311
|
if (tasks.releaseNotes) {
|
|
1434
|
-
|
|
1312
|
+
info3("Generating release notes with LLM...");
|
|
1435
1313
|
enhanced.releaseNotes = await generateReleaseNotes(provider, enhanced.entries, llmContext);
|
|
1436
1314
|
if (enhanced.releaseNotes) {
|
|
1437
|
-
|
|
1315
|
+
info3("Release notes generated successfully");
|
|
1438
1316
|
} else {
|
|
1439
1317
|
warn3("Release notes generation returned empty result");
|
|
1440
1318
|
}
|
|
@@ -1453,17 +1331,17 @@ function getBuiltinTemplatePath(style) {
|
|
|
1453
1331
|
let packageRoot;
|
|
1454
1332
|
try {
|
|
1455
1333
|
const currentUrl = import.meta.url;
|
|
1456
|
-
packageRoot =
|
|
1457
|
-
packageRoot =
|
|
1334
|
+
packageRoot = path5.dirname(new URL(currentUrl).pathname);
|
|
1335
|
+
packageRoot = path5.join(packageRoot, "..", "..");
|
|
1458
1336
|
} catch {
|
|
1459
1337
|
packageRoot = __dirname;
|
|
1460
1338
|
}
|
|
1461
|
-
return
|
|
1339
|
+
return path5.join(packageRoot, "templates", style);
|
|
1462
1340
|
}
|
|
1463
1341
|
async function generateWithTemplate(contexts, config, outputPath, dryRun) {
|
|
1464
1342
|
let templatePath;
|
|
1465
1343
|
if (config.templates?.path) {
|
|
1466
|
-
templatePath =
|
|
1344
|
+
templatePath = path5.resolve(config.templates.path);
|
|
1467
1345
|
} else {
|
|
1468
1346
|
templatePath = getBuiltinTemplatePath("keep-a-changelog");
|
|
1469
1347
|
}
|
|
@@ -1473,52 +1351,63 @@ async function generateWithTemplate(contexts, config, outputPath, dryRun) {
|
|
|
1473
1351
|
);
|
|
1474
1352
|
const result = renderTemplate(templatePath, documentContext, config.templates?.engine);
|
|
1475
1353
|
if (dryRun) {
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1354
|
+
info3(`Would write templated output to ${outputPath}`);
|
|
1355
|
+
debug2("--- Changelog Preview ---");
|
|
1356
|
+
debug2(result.content);
|
|
1357
|
+
debug2("--- End Preview ---");
|
|
1480
1358
|
return;
|
|
1481
1359
|
}
|
|
1482
1360
|
if (outputPath === "-") {
|
|
1483
1361
|
process.stdout.write(result.content);
|
|
1484
1362
|
return;
|
|
1485
1363
|
}
|
|
1486
|
-
const dir =
|
|
1487
|
-
if (!
|
|
1488
|
-
|
|
1364
|
+
const dir = path5.dirname(outputPath);
|
|
1365
|
+
if (!fs7.existsSync(dir)) {
|
|
1366
|
+
fs7.mkdirSync(dir, { recursive: true });
|
|
1489
1367
|
}
|
|
1490
|
-
|
|
1491
|
-
|
|
1368
|
+
fs7.writeFileSync(outputPath, result.content, "utf-8");
|
|
1369
|
+
success3(`Changelog written to ${outputPath} (using ${result.engine} template)`);
|
|
1492
1370
|
}
|
|
1493
1371
|
async function runPipeline(input, config, dryRun) {
|
|
1494
|
-
|
|
1372
|
+
debug2(`Processing ${input.packages.length} package(s)`);
|
|
1495
1373
|
let contexts = input.packages.map(createTemplateContext);
|
|
1496
1374
|
if (config.llm && !process.env.CHANGELOG_NO_LLM) {
|
|
1497
|
-
|
|
1375
|
+
info3("Processing with LLM enhancement");
|
|
1498
1376
|
contexts = await Promise.all(contexts.map((ctx) => processWithLLM(ctx, config)));
|
|
1499
1377
|
}
|
|
1378
|
+
const files = [];
|
|
1500
1379
|
for (const output of config.output) {
|
|
1501
|
-
|
|
1380
|
+
info3(`Generating ${output.format} output`);
|
|
1502
1381
|
switch (output.format) {
|
|
1503
1382
|
case "markdown": {
|
|
1504
1383
|
const file = output.file ?? "CHANGELOG.md";
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1384
|
+
try {
|
|
1385
|
+
const effectiveTemplateConfig = output.templates ?? config.templates;
|
|
1386
|
+
if (effectiveTemplateConfig?.path || output.options?.template) {
|
|
1387
|
+
const configWithTemplate = { ...config, templates: effectiveTemplateConfig };
|
|
1388
|
+
await generateWithTemplate(contexts, configWithTemplate, file, dryRun);
|
|
1389
|
+
} else {
|
|
1390
|
+
writeMarkdown(file, contexts, config, dryRun);
|
|
1391
|
+
}
|
|
1392
|
+
if (!dryRun) files.push(file);
|
|
1393
|
+
} catch (error) {
|
|
1394
|
+
warn3(`Failed to write ${file}: ${error instanceof Error ? error.message : String(error)}`);
|
|
1511
1395
|
}
|
|
1512
1396
|
break;
|
|
1513
1397
|
}
|
|
1514
1398
|
case "json": {
|
|
1515
1399
|
const file = output.file ?? "changelog.json";
|
|
1516
|
-
|
|
1400
|
+
try {
|
|
1401
|
+
writeJson(file, contexts, dryRun);
|
|
1402
|
+
if (!dryRun) files.push(file);
|
|
1403
|
+
} catch (error) {
|
|
1404
|
+
warn3(`Failed to write ${file}: ${error instanceof Error ? error.message : String(error)}`);
|
|
1405
|
+
}
|
|
1517
1406
|
break;
|
|
1518
1407
|
}
|
|
1519
1408
|
case "github-release": {
|
|
1520
1409
|
if (dryRun) {
|
|
1521
|
-
|
|
1410
|
+
info3("[DRY RUN] Would create GitHub release");
|
|
1522
1411
|
break;
|
|
1523
1412
|
}
|
|
1524
1413
|
const firstContext = contexts[0];
|
|
@@ -1546,139 +1435,33 @@ async function runPipeline(input, config, dryRun) {
|
|
|
1546
1435
|
}
|
|
1547
1436
|
}
|
|
1548
1437
|
}
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
}
|
|
1566
|
-
return byPackage;
|
|
1567
|
-
}
|
|
1568
|
-
|
|
1569
|
-
// src/monorepo/aggregator.ts
|
|
1570
|
-
function writeFile(outputPath, content, dryRun) {
|
|
1571
|
-
if (dryRun) {
|
|
1572
|
-
info5(`Would write to ${outputPath}`);
|
|
1573
|
-
debug4(content);
|
|
1574
|
-
return;
|
|
1575
|
-
}
|
|
1576
|
-
const dir = path7.dirname(outputPath);
|
|
1577
|
-
if (!fs9.existsSync(dir)) {
|
|
1578
|
-
fs9.mkdirSync(dir, { recursive: true });
|
|
1579
|
-
}
|
|
1580
|
-
fs9.writeFileSync(outputPath, content, "utf-8");
|
|
1581
|
-
success5(`Changelog written to ${outputPath}`);
|
|
1582
|
-
}
|
|
1583
|
-
function aggregateToRoot(contexts) {
|
|
1584
|
-
const aggregated = {
|
|
1585
|
-
packageName: "monorepo",
|
|
1586
|
-
version: contexts[0]?.version ?? "0.0.0",
|
|
1587
|
-
previousVersion: contexts[0]?.previousVersion ?? null,
|
|
1588
|
-
date: (/* @__PURE__ */ new Date()).toISOString().split("T")[0] ?? "",
|
|
1589
|
-
repoUrl: contexts[0]?.repoUrl ?? null,
|
|
1590
|
-
entries: []
|
|
1591
|
-
};
|
|
1592
|
-
for (const ctx of contexts) {
|
|
1593
|
-
for (const entry of ctx.entries) {
|
|
1594
|
-
aggregated.entries.push({
|
|
1595
|
-
...entry,
|
|
1596
|
-
scope: entry.scope ? `${ctx.packageName}/${entry.scope}` : ctx.packageName
|
|
1597
|
-
});
|
|
1598
|
-
}
|
|
1599
|
-
}
|
|
1600
|
-
return aggregated;
|
|
1601
|
-
}
|
|
1602
|
-
function writeMonorepoChangelogs(contexts, options, config, dryRun) {
|
|
1603
|
-
if (options.mode === "root" || options.mode === "both") {
|
|
1604
|
-
const aggregated = aggregateToRoot(contexts);
|
|
1605
|
-
const rootPath = path7.join(options.rootPath, "CHANGELOG.md");
|
|
1606
|
-
info5(`Writing root changelog to ${rootPath}`);
|
|
1607
|
-
const rootContent = config.updateStrategy === "prepend" && fs9.existsSync(rootPath) ? prependVersion(rootPath, aggregated) : renderMarkdown([aggregated]);
|
|
1608
|
-
writeFile(rootPath, rootContent, dryRun);
|
|
1609
|
-
}
|
|
1610
|
-
if (options.mode === "packages" || options.mode === "both") {
|
|
1611
|
-
const byPackage = splitByPackage(contexts);
|
|
1612
|
-
const packageDirMap = buildPackageDirMap(options.rootPath, options.packagesPath);
|
|
1613
|
-
for (const [packageName, ctx] of byPackage) {
|
|
1614
|
-
const simpleName = packageName.split("/").pop();
|
|
1615
|
-
const packageDir = packageDirMap.get(packageName) ?? (simpleName ? packageDirMap.get(simpleName) : void 0) ?? null;
|
|
1616
|
-
if (packageDir) {
|
|
1617
|
-
const changelogPath = path7.join(packageDir, "CHANGELOG.md");
|
|
1618
|
-
info5(`Writing changelog for ${packageName} to ${changelogPath}`);
|
|
1619
|
-
const pkgContent = config.updateStrategy === "prepend" && fs9.existsSync(changelogPath) ? prependVersion(changelogPath, ctx) : renderMarkdown([ctx]);
|
|
1620
|
-
writeFile(changelogPath, pkgContent, dryRun);
|
|
1621
|
-
} else {
|
|
1622
|
-
info5(`Could not find directory for package ${packageName}, skipping`);
|
|
1623
|
-
}
|
|
1438
|
+
if (config.monorepo?.mode) {
|
|
1439
|
+
const { detectMonorepo, writeMonorepoChangelogs } = await import("./aggregator-BDTUZWOA.js");
|
|
1440
|
+
const cwd = process.cwd();
|
|
1441
|
+
const detected = detectMonorepo(cwd);
|
|
1442
|
+
if (detected.isMonorepo) {
|
|
1443
|
+
const monoFiles = writeMonorepoChangelogs(
|
|
1444
|
+
contexts,
|
|
1445
|
+
{
|
|
1446
|
+
rootPath: config.monorepo.rootPath ?? cwd,
|
|
1447
|
+
packagesPath: config.monorepo.packagesPath ?? detected.packagesPath,
|
|
1448
|
+
mode: config.monorepo.mode
|
|
1449
|
+
},
|
|
1450
|
+
config,
|
|
1451
|
+
dryRun
|
|
1452
|
+
);
|
|
1453
|
+
files.push(...monoFiles);
|
|
1624
1454
|
}
|
|
1625
1455
|
}
|
|
1626
|
-
}
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
const packagesDir = path7.join(rootPath, packagesPath);
|
|
1630
|
-
if (!fs9.existsSync(packagesDir)) {
|
|
1631
|
-
return map;
|
|
1632
|
-
}
|
|
1633
|
-
for (const entry of fs9.readdirSync(packagesDir, { withFileTypes: true })) {
|
|
1634
|
-
if (!entry.isDirectory()) continue;
|
|
1635
|
-
const dirPath = path7.join(packagesDir, entry.name);
|
|
1636
|
-
map.set(entry.name, dirPath);
|
|
1637
|
-
const packageJsonPath = path7.join(dirPath, "package.json");
|
|
1638
|
-
if (fs9.existsSync(packageJsonPath)) {
|
|
1639
|
-
try {
|
|
1640
|
-
const pkg = JSON.parse(fs9.readFileSync(packageJsonPath, "utf-8"));
|
|
1641
|
-
if (pkg.name) {
|
|
1642
|
-
map.set(pkg.name, dirPath);
|
|
1643
|
-
}
|
|
1644
|
-
} catch {
|
|
1645
|
-
}
|
|
1646
|
-
}
|
|
1456
|
+
const packageNotes = {};
|
|
1457
|
+
for (const ctx of contexts) {
|
|
1458
|
+
packageNotes[ctx.packageName] = formatVersion(ctx);
|
|
1647
1459
|
}
|
|
1648
|
-
return
|
|
1460
|
+
return { packageNotes, files };
|
|
1649
1461
|
}
|
|
1650
|
-
function
|
|
1651
|
-
const
|
|
1652
|
-
|
|
1653
|
-
if (fs9.existsSync(pnpmWorkspacesPath)) {
|
|
1654
|
-
const content = fs9.readFileSync(pnpmWorkspacesPath, "utf-8");
|
|
1655
|
-
const packagesMatch = content.match(/packages:\s*\n\s*-\s*['"]([^'"]+)['"]/);
|
|
1656
|
-
if (packagesMatch?.[1]) {
|
|
1657
|
-
const packagesGlob = packagesMatch[1];
|
|
1658
|
-
const packagesPath = packagesGlob.replace(/\/?\*$/, "").replace(/\/\*\*$/, "");
|
|
1659
|
-
return { isMonorepo: true, packagesPath: packagesPath || "packages" };
|
|
1660
|
-
}
|
|
1661
|
-
return { isMonorepo: true, packagesPath: "packages" };
|
|
1662
|
-
}
|
|
1663
|
-
if (fs9.existsSync(packageJsonPath)) {
|
|
1664
|
-
try {
|
|
1665
|
-
const content = fs9.readFileSync(packageJsonPath, "utf-8");
|
|
1666
|
-
const pkg = JSON.parse(content);
|
|
1667
|
-
if (pkg.workspaces) {
|
|
1668
|
-
const workspaces = Array.isArray(pkg.workspaces) ? pkg.workspaces : pkg.workspaces.packages;
|
|
1669
|
-
if (workspaces?.length) {
|
|
1670
|
-
const firstWorkspace = workspaces[0];
|
|
1671
|
-
if (firstWorkspace) {
|
|
1672
|
-
const packagesPath = firstWorkspace.replace(/\/?\*$/, "").replace(/\/\*\*$/, "");
|
|
1673
|
-
return { isMonorepo: true, packagesPath: packagesPath || "packages" };
|
|
1674
|
-
}
|
|
1675
|
-
}
|
|
1676
|
-
}
|
|
1677
|
-
} catch {
|
|
1678
|
-
return { isMonorepo: false, packagesPath: "" };
|
|
1679
|
-
}
|
|
1680
|
-
}
|
|
1681
|
-
return { isMonorepo: false, packagesPath: "" };
|
|
1462
|
+
async function processInput(inputJson, config, dryRun) {
|
|
1463
|
+
const input = parsePackageVersioner(inputJson);
|
|
1464
|
+
return runPipeline(input, config, dryRun);
|
|
1682
1465
|
}
|
|
1683
1466
|
|
|
1684
1467
|
export {
|
|
@@ -1697,14 +1480,9 @@ export {
|
|
|
1697
1480
|
parsePackageVersioner,
|
|
1698
1481
|
parsePackageVersionerFile,
|
|
1699
1482
|
parsePackageVersionerStdin,
|
|
1700
|
-
renderMarkdown,
|
|
1701
|
-
writeMarkdown,
|
|
1702
1483
|
renderJson,
|
|
1703
1484
|
writeJson,
|
|
1704
1485
|
createTemplateContext,
|
|
1705
1486
|
runPipeline,
|
|
1706
|
-
processInput
|
|
1707
|
-
aggregateToRoot,
|
|
1708
|
-
writeMonorepoChangelogs,
|
|
1709
|
-
detectMonorepo
|
|
1487
|
+
processInput
|
|
1710
1488
|
};
|