@releasekit/notes 0.2.0 → 0.3.0-next.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.
@@ -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/markdown.ts
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
- info2(`Would write JSON output to ${outputPath}`);
300
- debug2("--- JSON Output Preview ---");
301
- debug2(content);
302
- debug2("--- End Preview ---");
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 = path2.dirname(outputPath);
306
- if (!fs3.existsSync(dir)) {
307
- fs3.mkdirSync(dir, { recursive: true });
183
+ const dir = path.dirname(outputPath);
184
+ if (!fs2.existsSync(dir)) {
185
+ fs2.mkdirSync(dir, { recursive: true });
308
186
  }
309
- fs3.writeFileSync(outputPath, content, "utf-8");
310
- success2(`JSON output written to ${outputPath}`);
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 fs8 from "fs";
315
- import * as path6 from "path";
316
- import { debug as debug3, info as info4, success as success4, warn as warn3 } from "@releasekit/core";
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 = {
@@ -411,7 +289,7 @@ var OllamaProvider = class extends BaseLLMProvider {
411
289
  "Content-Type": "application/json"
412
290
  };
413
291
  if (this.apiKey) {
414
- headers["Authorization"] = `Bearer ${this.apiKey}`;
292
+ headers.Authorization = `Bearer ${this.apiKey}`;
415
293
  }
416
294
  const baseUrl = this.baseURL.endsWith("/api") ? this.baseURL.slice(0, -4) : this.baseURL;
417
295
  const response = await fetch(`${baseUrl}/api/chat`, {
@@ -572,7 +450,6 @@ function validateScope(scope, allowedScopes, rules) {
572
450
  return scope;
573
451
  case "fallback":
574
452
  return rules?.fallbackScope;
575
- case "remove":
576
453
  default:
577
454
  return void 0;
578
455
  }
@@ -949,7 +826,7 @@ function createProvider(config) {
949
826
 
950
827
  // src/output/github-release.ts
951
828
  import { Octokit } from "@octokit/rest";
952
- import { info as info3, success as success3 } from "@releasekit/core";
829
+ import { info as info2, success as success2 } from "@releasekit/core";
953
830
  var GitHubClient = class {
954
831
  octokit;
955
832
  owner;
@@ -971,7 +848,7 @@ var GitHubClient = class {
971
848
  } else {
972
849
  body = renderMarkdown([context]);
973
850
  }
974
- info3(`Creating GitHub release for ${tagName}`);
851
+ info2(`Creating GitHub release for ${tagName}`);
975
852
  try {
976
853
  const response = await this.octokit.repos.createRelease({
977
854
  owner: this.owner,
@@ -983,7 +860,7 @@ var GitHubClient = class {
983
860
  prerelease: options.prerelease ?? false,
984
861
  generate_release_notes: options.generateNotes ?? false
985
862
  });
986
- success3(`Release created: ${response.data.html_url}`);
863
+ success2(`Release created: ${response.data.html_url}`);
987
864
  return {
988
865
  id: response.data.id,
989
866
  htmlUrl: response.data.html_url,
@@ -1001,7 +878,7 @@ var GitHubClient = class {
1001
878
  } else {
1002
879
  body = renderMarkdown([context]);
1003
880
  }
1004
- info3(`Updating GitHub release ${releaseId}`);
881
+ info2(`Updating GitHub release ${releaseId}`);
1005
882
  try {
1006
883
  const response = await this.octokit.repos.updateRelease({
1007
884
  owner: this.owner,
@@ -1013,7 +890,7 @@ var GitHubClient = class {
1013
890
  draft: options.draft ?? false,
1014
891
  prerelease: options.prerelease ?? false
1015
892
  });
1016
- success3(`Release updated: ${response.data.html_url}`);
893
+ success2(`Release updated: ${response.data.html_url}`);
1017
894
  return {
1018
895
  id: response.data.id,
1019
896
  htmlUrl: response.data.html_url,
@@ -1063,7 +940,7 @@ async function createGitHubRelease(context, options) {
1063
940
  }
1064
941
 
1065
942
  // src/templates/ejs.ts
1066
- import * as fs4 from "fs";
943
+ import * as fs3 from "fs";
1067
944
  import ejs from "ejs";
1068
945
  function renderEjs(template, context) {
1069
946
  try {
@@ -1073,16 +950,16 @@ function renderEjs(template, context) {
1073
950
  }
1074
951
  }
1075
952
  function renderEjsFile(filePath, context) {
1076
- if (!fs4.existsSync(filePath)) {
953
+ if (!fs3.existsSync(filePath)) {
1077
954
  throw new TemplateError(`Template file not found: ${filePath}`);
1078
955
  }
1079
- const template = fs4.readFileSync(filePath, "utf-8");
956
+ const template = fs3.readFileSync(filePath, "utf-8");
1080
957
  return renderEjs(template, context);
1081
958
  }
1082
959
 
1083
960
  // src/templates/handlebars.ts
1084
- import * as fs5 from "fs";
1085
- import * as path3 from "path";
961
+ import * as fs4 from "fs";
962
+ import * as path2 from "path";
1086
963
  import Handlebars from "handlebars";
1087
964
  function registerHandlebarsHelpers() {
1088
965
  Handlebars.registerHelper("capitalize", (str) => {
@@ -1108,28 +985,28 @@ function renderHandlebars(template, context) {
1108
985
  }
1109
986
  }
1110
987
  function renderHandlebarsFile(filePath, context) {
1111
- if (!fs5.existsSync(filePath)) {
988
+ if (!fs4.existsSync(filePath)) {
1112
989
  throw new TemplateError(`Template file not found: ${filePath}`);
1113
990
  }
1114
- const template = fs5.readFileSync(filePath, "utf-8");
991
+ const template = fs4.readFileSync(filePath, "utf-8");
1115
992
  return renderHandlebars(template, context);
1116
993
  }
1117
994
  function renderHandlebarsComposable(templateDir, context) {
1118
995
  registerHandlebarsHelpers();
1119
- const versionPath = path3.join(templateDir, "version.hbs");
1120
- const entryPath = path3.join(templateDir, "entry.hbs");
1121
- const documentPath = path3.join(templateDir, "document.hbs");
1122
- if (!fs5.existsSync(documentPath)) {
996
+ const versionPath = path2.join(templateDir, "version.hbs");
997
+ const entryPath = path2.join(templateDir, "entry.hbs");
998
+ const documentPath = path2.join(templateDir, "document.hbs");
999
+ if (!fs4.existsSync(documentPath)) {
1123
1000
  throw new TemplateError(`Document template not found: ${documentPath}`);
1124
1001
  }
1125
- if (fs5.existsSync(versionPath)) {
1126
- Handlebars.registerPartial("version", fs5.readFileSync(versionPath, "utf-8"));
1002
+ if (fs4.existsSync(versionPath)) {
1003
+ Handlebars.registerPartial("version", fs4.readFileSync(versionPath, "utf-8"));
1127
1004
  }
1128
- if (fs5.existsSync(entryPath)) {
1129
- Handlebars.registerPartial("entry", fs5.readFileSync(entryPath, "utf-8"));
1005
+ if (fs4.existsSync(entryPath)) {
1006
+ Handlebars.registerPartial("entry", fs4.readFileSync(entryPath, "utf-8"));
1130
1007
  }
1131
1008
  try {
1132
- const compiled = Handlebars.compile(fs5.readFileSync(documentPath, "utf-8"));
1009
+ const compiled = Handlebars.compile(fs4.readFileSync(documentPath, "utf-8"));
1133
1010
  return compiled(context);
1134
1011
  } catch (error) {
1135
1012
  throw new TemplateError(`Handlebars render error: ${error instanceof Error ? error.message : String(error)}`);
@@ -1137,8 +1014,8 @@ function renderHandlebarsComposable(templateDir, context) {
1137
1014
  }
1138
1015
 
1139
1016
  // src/templates/liquid.ts
1140
- import * as fs6 from "fs";
1141
- import * as path4 from "path";
1017
+ import * as fs5 from "fs";
1018
+ import * as path3 from "path";
1142
1019
  import { Liquid } from "liquidjs";
1143
1020
  function createLiquidEngine(root) {
1144
1021
  return new Liquid({
@@ -1156,15 +1033,15 @@ function renderLiquid(template, context) {
1156
1033
  }
1157
1034
  }
1158
1035
  function renderLiquidFile(filePath, context) {
1159
- if (!fs6.existsSync(filePath)) {
1036
+ if (!fs5.existsSync(filePath)) {
1160
1037
  throw new TemplateError(`Template file not found: ${filePath}`);
1161
1038
  }
1162
- const template = fs6.readFileSync(filePath, "utf-8");
1039
+ const template = fs5.readFileSync(filePath, "utf-8");
1163
1040
  return renderLiquid(template, context);
1164
1041
  }
1165
1042
  function renderLiquidComposable(templateDir, context) {
1166
- const documentPath = path4.join(templateDir, "document.liquid");
1167
- if (!fs6.existsSync(documentPath)) {
1043
+ const documentPath = path3.join(templateDir, "document.liquid");
1044
+ if (!fs5.existsSync(documentPath)) {
1168
1045
  throw new TemplateError(`Document template not found: ${documentPath}`);
1169
1046
  }
1170
1047
  const engine = createLiquidEngine(templateDir);
@@ -1176,10 +1053,10 @@ function renderLiquidComposable(templateDir, context) {
1176
1053
  }
1177
1054
 
1178
1055
  // src/templates/loader.ts
1179
- import * as fs7 from "fs";
1180
- import * as path5 from "path";
1056
+ import * as fs6 from "fs";
1057
+ import * as path4 from "path";
1181
1058
  function getEngineFromFile(filePath) {
1182
- const ext = path5.extname(filePath).toLowerCase();
1059
+ const ext = path4.extname(filePath).toLowerCase();
1183
1060
  switch (ext) {
1184
1061
  case ".liquid":
1185
1062
  return "liquid";
@@ -1213,10 +1090,10 @@ function getRenderFileFn(engine) {
1213
1090
  }
1214
1091
  }
1215
1092
  function detectTemplateMode(templatePath) {
1216
- if (!fs7.existsSync(templatePath)) {
1093
+ if (!fs6.existsSync(templatePath)) {
1217
1094
  throw new TemplateError(`Template path not found: ${templatePath}`);
1218
1095
  }
1219
- const stat = fs7.statSync(templatePath);
1096
+ const stat = fs6.statSync(templatePath);
1220
1097
  if (stat.isFile()) {
1221
1098
  return "single";
1222
1099
  }
@@ -1234,7 +1111,7 @@ function renderSingleFile(templatePath, context, engine) {
1234
1111
  };
1235
1112
  }
1236
1113
  function renderComposable(templateDir, context, engine) {
1237
- const files = fs7.readdirSync(templateDir);
1114
+ const files = fs6.readdirSync(templateDir);
1238
1115
  const engineMap = {
1239
1116
  liquid: { document: "document.liquid", version: "version.liquid", entry: "entry.liquid" },
1240
1117
  handlebars: { document: "document.hbs", version: "version.hbs", entry: "entry.hbs" },
@@ -1257,15 +1134,15 @@ function renderComposable(templateDir, context, engine) {
1257
1134
  return { content: renderHandlebarsComposable(templateDir, context), engine: resolvedEngine };
1258
1135
  }
1259
1136
  const expectedFiles = engineMap[resolvedEngine];
1260
- const documentPath = path5.join(templateDir, expectedFiles.document);
1261
- if (!fs7.existsSync(documentPath)) {
1137
+ const documentPath = path4.join(templateDir, expectedFiles.document);
1138
+ if (!fs6.existsSync(documentPath)) {
1262
1139
  throw new TemplateError(`Document template not found: ${expectedFiles.document}`);
1263
1140
  }
1264
- const versionPath = path5.join(templateDir, expectedFiles.version);
1265
- const entryPath = path5.join(templateDir, expectedFiles.entry);
1141
+ const versionPath = path4.join(templateDir, expectedFiles.version);
1142
+ const entryPath = path4.join(templateDir, expectedFiles.entry);
1266
1143
  const render = getRenderFn(resolvedEngine);
1267
- const entryTemplate = fs7.existsSync(entryPath) ? fs7.readFileSync(entryPath, "utf-8") : null;
1268
- const versionTemplate = fs7.existsSync(versionPath) ? fs7.readFileSync(versionPath, "utf-8") : null;
1144
+ const entryTemplate = fs6.existsSync(entryPath) ? fs6.readFileSync(entryPath, "utf-8") : null;
1145
+ const versionTemplate = fs6.existsSync(versionPath) ? fs6.readFileSync(versionPath, "utf-8") : null;
1269
1146
  if (entryTemplate && versionTemplate) {
1270
1147
  const versionsWithEntries = context.versions.map((versionCtx) => {
1271
1148
  const entries = versionCtx.entries.map((entry) => {
@@ -1276,7 +1153,7 @@ function renderComposable(templateDir, context, engine) {
1276
1153
  });
1277
1154
  const docContext = { ...context, renderedVersions: versionsWithEntries };
1278
1155
  return {
1279
- content: render(fs7.readFileSync(documentPath, "utf-8"), docContext),
1156
+ content: render(fs6.readFileSync(documentPath, "utf-8"), docContext),
1280
1157
  engine: resolvedEngine
1281
1158
  };
1282
1159
  }
@@ -1383,9 +1260,9 @@ async function processWithLLM(context, config) {
1383
1260
  entries: context.entries
1384
1261
  };
1385
1262
  try {
1386
- info4(`Using LLM provider: ${config.llm.provider}${config.llm.model ? ` (${config.llm.model})` : ""}`);
1263
+ info3(`Using LLM provider: ${config.llm.provider}${config.llm.model ? ` (${config.llm.model})` : ""}`);
1387
1264
  if (config.llm.baseURL) {
1388
- info4(`LLM base URL: ${config.llm.baseURL}`);
1265
+ info3(`LLM base URL: ${config.llm.baseURL}`);
1389
1266
  }
1390
1267
  const rawProvider = createProvider(config.llm);
1391
1268
  const retryOpts = config.llm.retry ?? LLM_DEFAULTS.retry;
@@ -1394,47 +1271,47 @@ async function processWithLLM(context, config) {
1394
1271
  complete: (prompt, opts) => withRetry(() => rawProvider.complete(prompt, opts), retryOpts)
1395
1272
  };
1396
1273
  const activeTasks = Object.entries(tasks).filter(([, enabled]) => enabled).map(([name]) => name);
1397
- info4(`Running LLM tasks: ${activeTasks.join(", ")}`);
1274
+ info3(`Running LLM tasks: ${activeTasks.join(", ")}`);
1398
1275
  if (tasks.enhance && tasks.categorize) {
1399
- info4("Enhancing and categorizing entries with LLM...");
1276
+ info3("Enhancing and categorizing entries with LLM...");
1400
1277
  const result = await enhanceAndCategorize(provider, context.entries, llmContext);
1401
1278
  enhanced.entries = result.enhancedEntries;
1402
1279
  enhanced.categories = {};
1403
1280
  for (const cat of result.categories) {
1404
1281
  enhanced.categories[cat.category] = cat.entries;
1405
1282
  }
1406
- info4(`Enhanced ${enhanced.entries.length} entries into ${result.categories.length} categories`);
1283
+ info3(`Enhanced ${enhanced.entries.length} entries into ${result.categories.length} categories`);
1407
1284
  } else {
1408
1285
  if (tasks.enhance) {
1409
- info4("Enhancing entries with LLM...");
1286
+ info3("Enhancing entries with LLM...");
1410
1287
  enhanced.entries = await enhanceEntries(provider, context.entries, llmContext, config.llm.concurrency);
1411
- info4(`Enhanced ${enhanced.entries.length} entries`);
1288
+ info3(`Enhanced ${enhanced.entries.length} entries`);
1412
1289
  }
1413
1290
  if (tasks.categorize) {
1414
- info4("Categorizing entries with LLM...");
1291
+ info3("Categorizing entries with LLM...");
1415
1292
  const categorized = await categorizeEntries(provider, enhanced.entries, llmContext);
1416
1293
  enhanced.categories = {};
1417
1294
  for (const cat of categorized) {
1418
1295
  enhanced.categories[cat.category] = cat.entries;
1419
1296
  }
1420
- info4(`Created ${categorized.length} categories`);
1297
+ info3(`Created ${categorized.length} categories`);
1421
1298
  }
1422
1299
  }
1423
1300
  if (tasks.summarize) {
1424
- info4("Summarizing entries with LLM...");
1301
+ info3("Summarizing entries with LLM...");
1425
1302
  enhanced.summary = await summarizeEntries(provider, enhanced.entries, llmContext);
1426
1303
  if (enhanced.summary) {
1427
- info4("Summary generated successfully");
1428
- debug3(`Summary: ${enhanced.summary.substring(0, 100)}...`);
1304
+ info3("Summary generated successfully");
1305
+ debug2(`Summary: ${enhanced.summary.substring(0, 100)}...`);
1429
1306
  } else {
1430
1307
  warn3("Summary generation returned empty result");
1431
1308
  }
1432
1309
  }
1433
1310
  if (tasks.releaseNotes) {
1434
- info4("Generating release notes with LLM...");
1311
+ info3("Generating release notes with LLM...");
1435
1312
  enhanced.releaseNotes = await generateReleaseNotes(provider, enhanced.entries, llmContext);
1436
1313
  if (enhanced.releaseNotes) {
1437
- info4("Release notes generated successfully");
1314
+ info3("Release notes generated successfully");
1438
1315
  } else {
1439
1316
  warn3("Release notes generation returned empty result");
1440
1317
  }
@@ -1453,17 +1330,17 @@ function getBuiltinTemplatePath(style) {
1453
1330
  let packageRoot;
1454
1331
  try {
1455
1332
  const currentUrl = import.meta.url;
1456
- packageRoot = path6.dirname(new URL(currentUrl).pathname);
1457
- packageRoot = path6.join(packageRoot, "..", "..");
1333
+ packageRoot = path5.dirname(new URL(currentUrl).pathname);
1334
+ packageRoot = path5.join(packageRoot, "..", "..");
1458
1335
  } catch {
1459
1336
  packageRoot = __dirname;
1460
1337
  }
1461
- return path6.join(packageRoot, "templates", style);
1338
+ return path5.join(packageRoot, "templates", style);
1462
1339
  }
1463
1340
  async function generateWithTemplate(contexts, config, outputPath, dryRun) {
1464
1341
  let templatePath;
1465
1342
  if (config.templates?.path) {
1466
- templatePath = path6.resolve(config.templates.path);
1343
+ templatePath = path5.resolve(config.templates.path);
1467
1344
  } else {
1468
1345
  templatePath = getBuiltinTemplatePath("keep-a-changelog");
1469
1346
  }
@@ -1473,52 +1350,63 @@ async function generateWithTemplate(contexts, config, outputPath, dryRun) {
1473
1350
  );
1474
1351
  const result = renderTemplate(templatePath, documentContext, config.templates?.engine);
1475
1352
  if (dryRun) {
1476
- info4(`Would write templated output to ${outputPath}`);
1477
- debug3("--- Changelog Preview ---");
1478
- debug3(result.content);
1479
- debug3("--- End Preview ---");
1353
+ info3(`Would write templated output to ${outputPath}`);
1354
+ debug2("--- Changelog Preview ---");
1355
+ debug2(result.content);
1356
+ debug2("--- End Preview ---");
1480
1357
  return;
1481
1358
  }
1482
1359
  if (outputPath === "-") {
1483
1360
  process.stdout.write(result.content);
1484
1361
  return;
1485
1362
  }
1486
- const dir = path6.dirname(outputPath);
1487
- if (!fs8.existsSync(dir)) {
1488
- fs8.mkdirSync(dir, { recursive: true });
1363
+ const dir = path5.dirname(outputPath);
1364
+ if (!fs7.existsSync(dir)) {
1365
+ fs7.mkdirSync(dir, { recursive: true });
1489
1366
  }
1490
- fs8.writeFileSync(outputPath, result.content, "utf-8");
1491
- success4(`Changelog written to ${outputPath} (using ${result.engine} template)`);
1367
+ fs7.writeFileSync(outputPath, result.content, "utf-8");
1368
+ success3(`Changelog written to ${outputPath} (using ${result.engine} template)`);
1492
1369
  }
1493
1370
  async function runPipeline(input, config, dryRun) {
1494
- debug3(`Processing ${input.packages.length} package(s)`);
1371
+ debug2(`Processing ${input.packages.length} package(s)`);
1495
1372
  let contexts = input.packages.map(createTemplateContext);
1496
1373
  if (config.llm && !process.env.CHANGELOG_NO_LLM) {
1497
- info4("Processing with LLM enhancement");
1374
+ info3("Processing with LLM enhancement");
1498
1375
  contexts = await Promise.all(contexts.map((ctx) => processWithLLM(ctx, config)));
1499
1376
  }
1377
+ const files = [];
1500
1378
  for (const output of config.output) {
1501
- info4(`Generating ${output.format} output`);
1379
+ info3(`Generating ${output.format} output`);
1502
1380
  switch (output.format) {
1503
1381
  case "markdown": {
1504
1382
  const file = output.file ?? "CHANGELOG.md";
1505
- const effectiveTemplateConfig = output.templates ?? config.templates;
1506
- if (effectiveTemplateConfig?.path || output.options?.template) {
1507
- const configWithTemplate = { ...config, templates: effectiveTemplateConfig };
1508
- await generateWithTemplate(contexts, configWithTemplate, file, dryRun);
1509
- } else {
1510
- writeMarkdown(file, contexts, config, dryRun);
1383
+ try {
1384
+ const effectiveTemplateConfig = output.templates ?? config.templates;
1385
+ if (effectiveTemplateConfig?.path || output.options?.template) {
1386
+ const configWithTemplate = { ...config, templates: effectiveTemplateConfig };
1387
+ await generateWithTemplate(contexts, configWithTemplate, file, dryRun);
1388
+ } else {
1389
+ writeMarkdown(file, contexts, config, dryRun);
1390
+ }
1391
+ if (!dryRun) files.push(file);
1392
+ } catch (error) {
1393
+ warn3(`Failed to write ${file}: ${error instanceof Error ? error.message : String(error)}`);
1511
1394
  }
1512
1395
  break;
1513
1396
  }
1514
1397
  case "json": {
1515
1398
  const file = output.file ?? "changelog.json";
1516
- writeJson(file, contexts, dryRun);
1399
+ try {
1400
+ writeJson(file, contexts, dryRun);
1401
+ if (!dryRun) files.push(file);
1402
+ } catch (error) {
1403
+ warn3(`Failed to write ${file}: ${error instanceof Error ? error.message : String(error)}`);
1404
+ }
1517
1405
  break;
1518
1406
  }
1519
1407
  case "github-release": {
1520
1408
  if (dryRun) {
1521
- info4("[DRY RUN] Would create GitHub release");
1409
+ info3("[DRY RUN] Would create GitHub release");
1522
1410
  break;
1523
1411
  }
1524
1412
  const firstContext = contexts[0];
@@ -1546,139 +1434,33 @@ async function runPipeline(input, config, dryRun) {
1546
1434
  }
1547
1435
  }
1548
1436
  }
1549
- }
1550
- async function processInput(inputJson, config, dryRun) {
1551
- const input = parsePackageVersioner(inputJson);
1552
- await runPipeline(input, config, dryRun);
1553
- }
1554
-
1555
- // src/monorepo/aggregator.ts
1556
- import * as fs9 from "fs";
1557
- import * as path7 from "path";
1558
- import { debug as debug4, info as info5, success as success5 } from "@releasekit/core";
1559
-
1560
- // src/monorepo/splitter.ts
1561
- function splitByPackage(contexts) {
1562
- const byPackage = /* @__PURE__ */ new Map();
1563
- for (const ctx of contexts) {
1564
- byPackage.set(ctx.packageName, ctx);
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
- }
1437
+ if (config.monorepo?.mode) {
1438
+ const { detectMonorepo, writeMonorepoChangelogs } = await import("./aggregator-BDTUZWOA.js");
1439
+ const cwd = process.cwd();
1440
+ const detected = detectMonorepo(cwd);
1441
+ if (detected.isMonorepo) {
1442
+ const monoFiles = writeMonorepoChangelogs(
1443
+ contexts,
1444
+ {
1445
+ rootPath: config.monorepo.rootPath ?? cwd,
1446
+ packagesPath: config.monorepo.packagesPath ?? detected.packagesPath,
1447
+ mode: config.monorepo.mode
1448
+ },
1449
+ config,
1450
+ dryRun
1451
+ );
1452
+ files.push(...monoFiles);
1624
1453
  }
1625
1454
  }
1626
- }
1627
- function buildPackageDirMap(rootPath, packagesPath) {
1628
- const map = /* @__PURE__ */ new Map();
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
- }
1455
+ const packageNotes = {};
1456
+ for (const ctx of contexts) {
1457
+ packageNotes[ctx.packageName] = formatVersion(ctx);
1647
1458
  }
1648
- return map;
1459
+ return { packageNotes, files };
1649
1460
  }
1650
- function detectMonorepo(cwd) {
1651
- const pnpmWorkspacesPath = path7.join(cwd, "pnpm-workspace.yaml");
1652
- const packageJsonPath = path7.join(cwd, "package.json");
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: "" };
1461
+ async function processInput(inputJson, config, dryRun) {
1462
+ const input = parsePackageVersioner(inputJson);
1463
+ return runPipeline(input, config, dryRun);
1682
1464
  }
1683
1465
 
1684
1466
  export {
@@ -1697,14 +1479,9 @@ export {
1697
1479
  parsePackageVersioner,
1698
1480
  parsePackageVersionerFile,
1699
1481
  parsePackageVersionerStdin,
1700
- renderMarkdown,
1701
- writeMarkdown,
1702
1482
  renderJson,
1703
1483
  writeJson,
1704
1484
  createTemplateContext,
1705
1485
  runPipeline,
1706
- processInput,
1707
- aggregateToRoot,
1708
- writeMonorepoChangelogs,
1709
- detectMonorepo
1486
+ processInput
1710
1487
  };