@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/dist/index.cjs CHANGED
@@ -5,6 +5,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __esm = (fn, res) => function __init() {
9
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
10
+ };
8
11
  var __export = (target, all) => {
9
12
  for (var name in all)
10
13
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -27,6 +30,295 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
30
  ));
28
31
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
32
 
33
+ // src/output/markdown.ts
34
+ function groupEntriesByType(entries) {
35
+ const grouped = /* @__PURE__ */ new Map();
36
+ for (const type of TYPE_ORDER) {
37
+ grouped.set(type, []);
38
+ }
39
+ for (const entry of entries) {
40
+ const existing = grouped.get(entry.type) ?? [];
41
+ existing.push(entry);
42
+ grouped.set(entry.type, existing);
43
+ }
44
+ return grouped;
45
+ }
46
+ function formatEntry(entry) {
47
+ let line;
48
+ if (entry.breaking && entry.scope) {
49
+ line = `- **BREAKING** **${entry.scope}**: ${entry.description}`;
50
+ } else if (entry.breaking) {
51
+ line = `- **BREAKING** ${entry.description}`;
52
+ } else if (entry.scope) {
53
+ line = `- **${entry.scope}**: ${entry.description}`;
54
+ } else {
55
+ line = `- ${entry.description}`;
56
+ }
57
+ if (entry.issueIds && entry.issueIds.length > 0) {
58
+ line += ` (${entry.issueIds.join(", ")})`;
59
+ }
60
+ return line;
61
+ }
62
+ function formatVersion(context) {
63
+ const lines = [];
64
+ const versionHeader = context.previousVersion ? `## [${context.version}]` : `## ${context.version}`;
65
+ lines.push(`${versionHeader} - ${context.date}`);
66
+ lines.push("");
67
+ if (context.compareUrl) {
68
+ lines.push(`[Full Changelog](${context.compareUrl})`);
69
+ lines.push("");
70
+ }
71
+ if (context.enhanced?.summary) {
72
+ lines.push(context.enhanced.summary);
73
+ lines.push("");
74
+ }
75
+ const grouped = groupEntriesByType(context.entries);
76
+ for (const [type, entries] of grouped) {
77
+ if (entries.length === 0) continue;
78
+ lines.push(`### ${TYPE_LABELS[type]}`);
79
+ for (const entry of entries) {
80
+ lines.push(formatEntry(entry));
81
+ }
82
+ lines.push("");
83
+ }
84
+ return lines.join("\n");
85
+ }
86
+ function formatHeader() {
87
+ return `# Changelog
88
+
89
+ All notable changes to this project will be documented in this file.
90
+
91
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
92
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
93
+
94
+ `;
95
+ }
96
+ function renderMarkdown(contexts) {
97
+ const sections = [formatHeader()];
98
+ for (const context of contexts) {
99
+ sections.push(formatVersion(context));
100
+ }
101
+ return sections.join("\n");
102
+ }
103
+ function prependVersion(existingPath, context) {
104
+ let existing = "";
105
+ if (fs2.existsSync(existingPath)) {
106
+ existing = fs2.readFileSync(existingPath, "utf-8");
107
+ const headerEnd = existing.indexOf("\n## ");
108
+ if (headerEnd >= 0) {
109
+ const header = existing.slice(0, headerEnd);
110
+ const body = existing.slice(headerEnd + 1);
111
+ const newVersion = formatVersion(context);
112
+ return `${header}
113
+
114
+ ${newVersion}
115
+ ${body}`;
116
+ }
117
+ }
118
+ return renderMarkdown([context]);
119
+ }
120
+ function writeMarkdown(outputPath, contexts, config, dryRun) {
121
+ const content = renderMarkdown(contexts);
122
+ if (dryRun) {
123
+ (0, import_core5.info)(`Would write changelog to ${outputPath}`);
124
+ (0, import_core5.debug)("--- Changelog Preview ---");
125
+ (0, import_core5.debug)(content);
126
+ (0, import_core5.debug)("--- End Preview ---");
127
+ return;
128
+ }
129
+ const dir = path.dirname(outputPath);
130
+ if (!fs2.existsSync(dir)) {
131
+ fs2.mkdirSync(dir, { recursive: true });
132
+ }
133
+ if (outputPath === "-") {
134
+ process.stdout.write(content);
135
+ return;
136
+ }
137
+ if (config.updateStrategy === "prepend" && fs2.existsSync(outputPath) && contexts.length === 1) {
138
+ const firstContext = contexts[0];
139
+ if (firstContext) {
140
+ const updated = prependVersion(outputPath, firstContext);
141
+ fs2.writeFileSync(outputPath, updated, "utf-8");
142
+ }
143
+ } else {
144
+ fs2.writeFileSync(outputPath, content, "utf-8");
145
+ }
146
+ (0, import_core5.success)(`Changelog written to ${outputPath}`);
147
+ }
148
+ var fs2, path, import_core5, TYPE_ORDER, TYPE_LABELS;
149
+ var init_markdown = __esm({
150
+ "src/output/markdown.ts"() {
151
+ "use strict";
152
+ fs2 = __toESM(require("fs"), 1);
153
+ path = __toESM(require("path"), 1);
154
+ import_core5 = require("@releasekit/core");
155
+ TYPE_ORDER = ["added", "changed", "deprecated", "removed", "fixed", "security"];
156
+ TYPE_LABELS = {
157
+ added: "Added",
158
+ changed: "Changed",
159
+ deprecated: "Deprecated",
160
+ removed: "Removed",
161
+ fixed: "Fixed",
162
+ security: "Security"
163
+ };
164
+ }
165
+ });
166
+
167
+ // src/monorepo/splitter.ts
168
+ function splitByPackage(contexts) {
169
+ const byPackage = /* @__PURE__ */ new Map();
170
+ for (const ctx of contexts) {
171
+ byPackage.set(ctx.packageName, ctx);
172
+ }
173
+ return byPackage;
174
+ }
175
+ var init_splitter = __esm({
176
+ "src/monorepo/splitter.ts"() {
177
+ "use strict";
178
+ }
179
+ });
180
+
181
+ // src/monorepo/aggregator.ts
182
+ var aggregator_exports = {};
183
+ __export(aggregator_exports, {
184
+ aggregateToRoot: () => aggregateToRoot,
185
+ detectMonorepo: () => detectMonorepo,
186
+ splitByPackage: () => splitByPackage,
187
+ writeMonorepoChangelogs: () => writeMonorepoChangelogs
188
+ });
189
+ function writeFile(outputPath, content, dryRun) {
190
+ if (dryRun) {
191
+ (0, import_core8.info)(`Would write to ${outputPath}`);
192
+ (0, import_core8.debug)(content);
193
+ return false;
194
+ }
195
+ const dir = path6.dirname(outputPath);
196
+ if (!fs8.existsSync(dir)) {
197
+ fs8.mkdirSync(dir, { recursive: true });
198
+ }
199
+ fs8.writeFileSync(outputPath, content, "utf-8");
200
+ (0, import_core8.success)(`Changelog written to ${outputPath}`);
201
+ return true;
202
+ }
203
+ function aggregateToRoot(contexts) {
204
+ const aggregated = {
205
+ packageName: "monorepo",
206
+ version: contexts[0]?.version ?? "0.0.0",
207
+ previousVersion: contexts[0]?.previousVersion ?? null,
208
+ date: (/* @__PURE__ */ new Date()).toISOString().split("T")[0] ?? "",
209
+ repoUrl: contexts[0]?.repoUrl ?? null,
210
+ entries: []
211
+ };
212
+ for (const ctx of contexts) {
213
+ for (const entry of ctx.entries) {
214
+ aggregated.entries.push({
215
+ ...entry,
216
+ scope: entry.scope ? `${ctx.packageName}/${entry.scope}` : ctx.packageName
217
+ });
218
+ }
219
+ }
220
+ return aggregated;
221
+ }
222
+ function writeMonorepoChangelogs(contexts, options, config, dryRun) {
223
+ const files = [];
224
+ if (options.mode === "root" || options.mode === "both") {
225
+ const aggregated = aggregateToRoot(contexts);
226
+ const rootPath = path6.join(options.rootPath, "CHANGELOG.md");
227
+ (0, import_core8.info)(`Writing root changelog to ${rootPath}`);
228
+ const rootContent = config.updateStrategy === "prepend" && fs8.existsSync(rootPath) ? prependVersion(rootPath, aggregated) : renderMarkdown([aggregated]);
229
+ if (writeFile(rootPath, rootContent, dryRun)) {
230
+ files.push(rootPath);
231
+ }
232
+ }
233
+ if (options.mode === "packages" || options.mode === "both") {
234
+ const byPackage = splitByPackage(contexts);
235
+ const packageDirMap = buildPackageDirMap(options.rootPath, options.packagesPath);
236
+ for (const [packageName, ctx] of byPackage) {
237
+ const simpleName = packageName.split("/").pop();
238
+ const packageDir = packageDirMap.get(packageName) ?? (simpleName ? packageDirMap.get(simpleName) : void 0) ?? null;
239
+ if (packageDir) {
240
+ const changelogPath = path6.join(packageDir, "CHANGELOG.md");
241
+ (0, import_core8.info)(`Writing changelog for ${packageName} to ${changelogPath}`);
242
+ const pkgContent = config.updateStrategy === "prepend" && fs8.existsSync(changelogPath) ? prependVersion(changelogPath, ctx) : renderMarkdown([ctx]);
243
+ if (writeFile(changelogPath, pkgContent, dryRun)) {
244
+ files.push(changelogPath);
245
+ }
246
+ } else {
247
+ (0, import_core8.info)(`Could not find directory for package ${packageName}, skipping`);
248
+ }
249
+ }
250
+ }
251
+ return files;
252
+ }
253
+ function buildPackageDirMap(rootPath, packagesPath) {
254
+ const map = /* @__PURE__ */ new Map();
255
+ const packagesDir = path6.join(rootPath, packagesPath);
256
+ if (!fs8.existsSync(packagesDir)) {
257
+ return map;
258
+ }
259
+ for (const entry of fs8.readdirSync(packagesDir, { withFileTypes: true })) {
260
+ if (!entry.isDirectory()) continue;
261
+ const dirPath = path6.join(packagesDir, entry.name);
262
+ map.set(entry.name, dirPath);
263
+ const packageJsonPath = path6.join(dirPath, "package.json");
264
+ if (fs8.existsSync(packageJsonPath)) {
265
+ try {
266
+ const pkg = JSON.parse(fs8.readFileSync(packageJsonPath, "utf-8"));
267
+ if (pkg.name) {
268
+ map.set(pkg.name, dirPath);
269
+ }
270
+ } catch {
271
+ }
272
+ }
273
+ }
274
+ return map;
275
+ }
276
+ function detectMonorepo(cwd) {
277
+ const pnpmWorkspacesPath = path6.join(cwd, "pnpm-workspace.yaml");
278
+ const packageJsonPath = path6.join(cwd, "package.json");
279
+ if (fs8.existsSync(pnpmWorkspacesPath)) {
280
+ const content = fs8.readFileSync(pnpmWorkspacesPath, "utf-8");
281
+ const packagesMatch = content.match(/packages:\s*\n\s*-\s*['"]([^'"]+)['"]/);
282
+ if (packagesMatch?.[1]) {
283
+ const packagesGlob = packagesMatch[1];
284
+ const packagesPath = packagesGlob.replace(/\/?\*$/, "").replace(/\/\*\*$/, "");
285
+ return { isMonorepo: true, packagesPath: packagesPath || "packages" };
286
+ }
287
+ return { isMonorepo: true, packagesPath: "packages" };
288
+ }
289
+ if (fs8.existsSync(packageJsonPath)) {
290
+ try {
291
+ const content = fs8.readFileSync(packageJsonPath, "utf-8");
292
+ const pkg = JSON.parse(content);
293
+ if (pkg.workspaces) {
294
+ const workspaces = Array.isArray(pkg.workspaces) ? pkg.workspaces : pkg.workspaces.packages;
295
+ if (workspaces?.length) {
296
+ const firstWorkspace = workspaces[0];
297
+ if (firstWorkspace) {
298
+ const packagesPath = firstWorkspace.replace(/\/?\*$/, "").replace(/\/\*\*$/, "");
299
+ return { isMonorepo: true, packagesPath: packagesPath || "packages" };
300
+ }
301
+ }
302
+ }
303
+ } catch {
304
+ return { isMonorepo: false, packagesPath: "" };
305
+ }
306
+ }
307
+ return { isMonorepo: false, packagesPath: "" };
308
+ }
309
+ var fs8, path6, import_core8;
310
+ var init_aggregator = __esm({
311
+ "src/monorepo/aggregator.ts"() {
312
+ "use strict";
313
+ fs8 = __toESM(require("fs"), 1);
314
+ path6 = __toESM(require("path"), 1);
315
+ import_core8 = require("@releasekit/core");
316
+ init_markdown();
317
+ init_splitter();
318
+ init_splitter();
319
+ }
320
+ });
321
+
30
322
  // src/index.ts
31
323
  var index_exports = {};
32
324
  __export(index_exports, {
@@ -41,6 +333,7 @@ __export(index_exports, {
41
333
  aggregateToRoot: () => aggregateToRoot,
42
334
  createTemplateContext: () => createTemplateContext,
43
335
  detectMonorepo: () => detectMonorepo,
336
+ formatVersion: () => formatVersion,
44
337
  getDefaultConfig: () => getDefaultConfig,
45
338
  getExitCode: () => getExitCode,
46
339
  loadAuth: () => import_config.loadAuth,
@@ -73,9 +366,9 @@ function getDefaultConfig() {
73
366
  }
74
367
 
75
368
  // src/core/pipeline.ts
76
- var fs8 = __toESM(require("fs"), 1);
77
- var path6 = __toESM(require("path"), 1);
78
- var import_core8 = require("@releasekit/core");
369
+ var fs9 = __toESM(require("fs"), 1);
370
+ var path7 = __toESM(require("path"), 1);
371
+ var import_core9 = require("@releasekit/core");
79
372
 
80
373
  // src/input/package-versioner.ts
81
374
  var fs = __toESM(require("fs"), 1);
@@ -844,136 +1137,7 @@ function createProvider(config) {
844
1137
  // src/output/github-release.ts
845
1138
  var import_rest = require("@octokit/rest");
846
1139
  var import_core6 = require("@releasekit/core");
847
-
848
- // src/output/markdown.ts
849
- var fs2 = __toESM(require("fs"), 1);
850
- var path = __toESM(require("path"), 1);
851
- var import_core5 = require("@releasekit/core");
852
- var TYPE_ORDER = ["added", "changed", "deprecated", "removed", "fixed", "security"];
853
- var TYPE_LABELS = {
854
- added: "Added",
855
- changed: "Changed",
856
- deprecated: "Deprecated",
857
- removed: "Removed",
858
- fixed: "Fixed",
859
- security: "Security"
860
- };
861
- function groupEntriesByType(entries) {
862
- const grouped = /* @__PURE__ */ new Map();
863
- for (const type of TYPE_ORDER) {
864
- grouped.set(type, []);
865
- }
866
- for (const entry of entries) {
867
- const existing = grouped.get(entry.type) ?? [];
868
- existing.push(entry);
869
- grouped.set(entry.type, existing);
870
- }
871
- return grouped;
872
- }
873
- function formatEntry(entry) {
874
- let line;
875
- if (entry.breaking && entry.scope) {
876
- line = `- **BREAKING** **${entry.scope}**: ${entry.description}`;
877
- } else if (entry.breaking) {
878
- line = `- **BREAKING** ${entry.description}`;
879
- } else if (entry.scope) {
880
- line = `- **${entry.scope}**: ${entry.description}`;
881
- } else {
882
- line = `- ${entry.description}`;
883
- }
884
- if (entry.issueIds && entry.issueIds.length > 0) {
885
- line += ` (${entry.issueIds.join(", ")})`;
886
- }
887
- return line;
888
- }
889
- function formatVersion(context) {
890
- const lines = [];
891
- const versionHeader = context.previousVersion ? `## [${context.version}]` : `## ${context.version}`;
892
- lines.push(`${versionHeader} - ${context.date}`);
893
- lines.push("");
894
- if (context.compareUrl) {
895
- lines.push(`[Full Changelog](${context.compareUrl})`);
896
- lines.push("");
897
- }
898
- if (context.enhanced?.summary) {
899
- lines.push(context.enhanced.summary);
900
- lines.push("");
901
- }
902
- const grouped = groupEntriesByType(context.entries);
903
- for (const [type, entries] of grouped) {
904
- if (entries.length === 0) continue;
905
- lines.push(`### ${TYPE_LABELS[type]}`);
906
- for (const entry of entries) {
907
- lines.push(formatEntry(entry));
908
- }
909
- lines.push("");
910
- }
911
- return lines.join("\n");
912
- }
913
- function formatHeader() {
914
- return `# Changelog
915
-
916
- All notable changes to this project will be documented in this file.
917
-
918
- The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
919
- and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
920
-
921
- `;
922
- }
923
- function renderMarkdown(contexts) {
924
- const sections = [formatHeader()];
925
- for (const context of contexts) {
926
- sections.push(formatVersion(context));
927
- }
928
- return sections.join("\n");
929
- }
930
- function prependVersion(existingPath, context) {
931
- let existing = "";
932
- if (fs2.existsSync(existingPath)) {
933
- existing = fs2.readFileSync(existingPath, "utf-8");
934
- const headerEnd = existing.indexOf("\n## ");
935
- if (headerEnd >= 0) {
936
- const header = existing.slice(0, headerEnd);
937
- const body = existing.slice(headerEnd + 1);
938
- const newVersion = formatVersion(context);
939
- return `${header}
940
-
941
- ${newVersion}
942
- ${body}`;
943
- }
944
- }
945
- return renderMarkdown([context]);
946
- }
947
- function writeMarkdown(outputPath, contexts, config, dryRun) {
948
- const content = renderMarkdown(contexts);
949
- if (dryRun) {
950
- (0, import_core5.info)(`Would write changelog to ${outputPath}`);
951
- (0, import_core5.debug)("--- Changelog Preview ---");
952
- (0, import_core5.debug)(content);
953
- (0, import_core5.debug)("--- End Preview ---");
954
- return;
955
- }
956
- const dir = path.dirname(outputPath);
957
- if (!fs2.existsSync(dir)) {
958
- fs2.mkdirSync(dir, { recursive: true });
959
- }
960
- if (outputPath === "-") {
961
- process.stdout.write(content);
962
- return;
963
- }
964
- if (config.updateStrategy === "prepend" && fs2.existsSync(outputPath) && contexts.length === 1) {
965
- const firstContext = contexts[0];
966
- if (firstContext) {
967
- const updated = prependVersion(outputPath, firstContext);
968
- fs2.writeFileSync(outputPath, updated, "utf-8");
969
- }
970
- } else {
971
- fs2.writeFileSync(outputPath, content, "utf-8");
972
- }
973
- (0, import_core5.success)(`Changelog written to ${outputPath}`);
974
- }
975
-
976
- // src/output/github-release.ts
1140
+ init_markdown();
977
1141
  var GitHubClient = class {
978
1142
  octokit;
979
1143
  owner;
@@ -1123,6 +1287,9 @@ function writeJson(outputPath, contexts, dryRun) {
1123
1287
  (0, import_core7.success)(`JSON output written to ${outputPath}`);
1124
1288
  }
1125
1289
 
1290
+ // src/core/pipeline.ts
1291
+ init_markdown();
1292
+
1126
1293
  // src/templates/ejs.ts
1127
1294
  var fs4 = __toESM(require("fs"), 1);
1128
1295
  var import_ejs = __toESM(require("ejs"), 1);
@@ -1445,9 +1612,9 @@ async function processWithLLM(context, config) {
1445
1612
  entries: context.entries
1446
1613
  };
1447
1614
  try {
1448
- (0, import_core8.info)(`Using LLM provider: ${config.llm.provider}${config.llm.model ? ` (${config.llm.model})` : ""}`);
1615
+ (0, import_core9.info)(`Using LLM provider: ${config.llm.provider}${config.llm.model ? ` (${config.llm.model})` : ""}`);
1449
1616
  if (config.llm.baseURL) {
1450
- (0, import_core8.info)(`LLM base URL: ${config.llm.baseURL}`);
1617
+ (0, import_core9.info)(`LLM base URL: ${config.llm.baseURL}`);
1451
1618
  }
1452
1619
  const rawProvider = createProvider(config.llm);
1453
1620
  const retryOpts = config.llm.retry ?? LLM_DEFAULTS.retry;
@@ -1456,49 +1623,49 @@ async function processWithLLM(context, config) {
1456
1623
  complete: (prompt, opts) => withRetry(() => rawProvider.complete(prompt, opts), retryOpts)
1457
1624
  };
1458
1625
  const activeTasks = Object.entries(tasks).filter(([, enabled]) => enabled).map(([name]) => name);
1459
- (0, import_core8.info)(`Running LLM tasks: ${activeTasks.join(", ")}`);
1626
+ (0, import_core9.info)(`Running LLM tasks: ${activeTasks.join(", ")}`);
1460
1627
  if (tasks.enhance && tasks.categorize) {
1461
- (0, import_core8.info)("Enhancing and categorizing entries with LLM...");
1628
+ (0, import_core9.info)("Enhancing and categorizing entries with LLM...");
1462
1629
  const result = await enhanceAndCategorize(provider, context.entries, llmContext);
1463
1630
  enhanced.entries = result.enhancedEntries;
1464
1631
  enhanced.categories = {};
1465
1632
  for (const cat of result.categories) {
1466
1633
  enhanced.categories[cat.category] = cat.entries;
1467
1634
  }
1468
- (0, import_core8.info)(`Enhanced ${enhanced.entries.length} entries into ${result.categories.length} categories`);
1635
+ (0, import_core9.info)(`Enhanced ${enhanced.entries.length} entries into ${result.categories.length} categories`);
1469
1636
  } else {
1470
1637
  if (tasks.enhance) {
1471
- (0, import_core8.info)("Enhancing entries with LLM...");
1638
+ (0, import_core9.info)("Enhancing entries with LLM...");
1472
1639
  enhanced.entries = await enhanceEntries(provider, context.entries, llmContext, config.llm.concurrency);
1473
- (0, import_core8.info)(`Enhanced ${enhanced.entries.length} entries`);
1640
+ (0, import_core9.info)(`Enhanced ${enhanced.entries.length} entries`);
1474
1641
  }
1475
1642
  if (tasks.categorize) {
1476
- (0, import_core8.info)("Categorizing entries with LLM...");
1643
+ (0, import_core9.info)("Categorizing entries with LLM...");
1477
1644
  const categorized = await categorizeEntries(provider, enhanced.entries, llmContext);
1478
1645
  enhanced.categories = {};
1479
1646
  for (const cat of categorized) {
1480
1647
  enhanced.categories[cat.category] = cat.entries;
1481
1648
  }
1482
- (0, import_core8.info)(`Created ${categorized.length} categories`);
1649
+ (0, import_core9.info)(`Created ${categorized.length} categories`);
1483
1650
  }
1484
1651
  }
1485
1652
  if (tasks.summarize) {
1486
- (0, import_core8.info)("Summarizing entries with LLM...");
1653
+ (0, import_core9.info)("Summarizing entries with LLM...");
1487
1654
  enhanced.summary = await summarizeEntries(provider, enhanced.entries, llmContext);
1488
1655
  if (enhanced.summary) {
1489
- (0, import_core8.info)("Summary generated successfully");
1490
- (0, import_core8.debug)(`Summary: ${enhanced.summary.substring(0, 100)}...`);
1656
+ (0, import_core9.info)("Summary generated successfully");
1657
+ (0, import_core9.debug)(`Summary: ${enhanced.summary.substring(0, 100)}...`);
1491
1658
  } else {
1492
- (0, import_core8.warn)("Summary generation returned empty result");
1659
+ (0, import_core9.warn)("Summary generation returned empty result");
1493
1660
  }
1494
1661
  }
1495
1662
  if (tasks.releaseNotes) {
1496
- (0, import_core8.info)("Generating release notes with LLM...");
1663
+ (0, import_core9.info)("Generating release notes with LLM...");
1497
1664
  enhanced.releaseNotes = await generateReleaseNotes(provider, enhanced.entries, llmContext);
1498
1665
  if (enhanced.releaseNotes) {
1499
- (0, import_core8.info)("Release notes generated successfully");
1666
+ (0, import_core9.info)("Release notes generated successfully");
1500
1667
  } else {
1501
- (0, import_core8.warn)("Release notes generation returned empty result");
1668
+ (0, import_core9.warn)("Release notes generation returned empty result");
1502
1669
  }
1503
1670
  }
1504
1671
  return {
@@ -1506,8 +1673,8 @@ async function processWithLLM(context, config) {
1506
1673
  enhanced
1507
1674
  };
1508
1675
  } catch (error) {
1509
- (0, import_core8.warn)(`LLM processing failed: ${error instanceof Error ? error.message : String(error)}`);
1510
- (0, import_core8.warn)("Falling back to raw entries");
1676
+ (0, import_core9.warn)(`LLM processing failed: ${error instanceof Error ? error.message : String(error)}`);
1677
+ (0, import_core9.warn)("Falling back to raw entries");
1511
1678
  return context;
1512
1679
  }
1513
1680
  }
@@ -1515,17 +1682,17 @@ function getBuiltinTemplatePath(style) {
1515
1682
  let packageRoot;
1516
1683
  try {
1517
1684
  const currentUrl = import_meta.url;
1518
- packageRoot = path6.dirname(new URL(currentUrl).pathname);
1519
- packageRoot = path6.join(packageRoot, "..", "..");
1685
+ packageRoot = path7.dirname(new URL(currentUrl).pathname);
1686
+ packageRoot = path7.join(packageRoot, "..", "..");
1520
1687
  } catch {
1521
1688
  packageRoot = __dirname;
1522
1689
  }
1523
- return path6.join(packageRoot, "templates", style);
1690
+ return path7.join(packageRoot, "templates", style);
1524
1691
  }
1525
1692
  async function generateWithTemplate(contexts, config, outputPath, dryRun) {
1526
1693
  let templatePath;
1527
1694
  if (config.templates?.path) {
1528
- templatePath = path6.resolve(config.templates.path);
1695
+ templatePath = path7.resolve(config.templates.path);
1529
1696
  } else {
1530
1697
  templatePath = getBuiltinTemplatePath("keep-a-changelog");
1531
1698
  }
@@ -1535,67 +1702,78 @@ async function generateWithTemplate(contexts, config, outputPath, dryRun) {
1535
1702
  );
1536
1703
  const result = renderTemplate(templatePath, documentContext, config.templates?.engine);
1537
1704
  if (dryRun) {
1538
- (0, import_core8.info)(`Would write templated output to ${outputPath}`);
1539
- (0, import_core8.debug)("--- Changelog Preview ---");
1540
- (0, import_core8.debug)(result.content);
1541
- (0, import_core8.debug)("--- End Preview ---");
1705
+ (0, import_core9.info)(`Would write templated output to ${outputPath}`);
1706
+ (0, import_core9.debug)("--- Changelog Preview ---");
1707
+ (0, import_core9.debug)(result.content);
1708
+ (0, import_core9.debug)("--- End Preview ---");
1542
1709
  return;
1543
1710
  }
1544
1711
  if (outputPath === "-") {
1545
1712
  process.stdout.write(result.content);
1546
1713
  return;
1547
1714
  }
1548
- const dir = path6.dirname(outputPath);
1549
- if (!fs8.existsSync(dir)) {
1550
- fs8.mkdirSync(dir, { recursive: true });
1715
+ const dir = path7.dirname(outputPath);
1716
+ if (!fs9.existsSync(dir)) {
1717
+ fs9.mkdirSync(dir, { recursive: true });
1551
1718
  }
1552
- fs8.writeFileSync(outputPath, result.content, "utf-8");
1553
- (0, import_core8.success)(`Changelog written to ${outputPath} (using ${result.engine} template)`);
1719
+ fs9.writeFileSync(outputPath, result.content, "utf-8");
1720
+ (0, import_core9.success)(`Changelog written to ${outputPath} (using ${result.engine} template)`);
1554
1721
  }
1555
1722
  async function runPipeline(input, config, dryRun) {
1556
- (0, import_core8.debug)(`Processing ${input.packages.length} package(s)`);
1723
+ (0, import_core9.debug)(`Processing ${input.packages.length} package(s)`);
1557
1724
  let contexts = input.packages.map(createTemplateContext);
1558
1725
  if (config.llm && !process.env.CHANGELOG_NO_LLM) {
1559
- (0, import_core8.info)("Processing with LLM enhancement");
1726
+ (0, import_core9.info)("Processing with LLM enhancement");
1560
1727
  contexts = await Promise.all(contexts.map((ctx) => processWithLLM(ctx, config)));
1561
1728
  }
1729
+ const files = [];
1562
1730
  for (const output of config.output) {
1563
- (0, import_core8.info)(`Generating ${output.format} output`);
1731
+ (0, import_core9.info)(`Generating ${output.format} output`);
1564
1732
  switch (output.format) {
1565
1733
  case "markdown": {
1566
1734
  const file = output.file ?? "CHANGELOG.md";
1567
- const effectiveTemplateConfig = output.templates ?? config.templates;
1568
- if (effectiveTemplateConfig?.path || output.options?.template) {
1569
- const configWithTemplate = { ...config, templates: effectiveTemplateConfig };
1570
- await generateWithTemplate(contexts, configWithTemplate, file, dryRun);
1571
- } else {
1572
- writeMarkdown(file, contexts, config, dryRun);
1735
+ try {
1736
+ const effectiveTemplateConfig = output.templates ?? config.templates;
1737
+ if (effectiveTemplateConfig?.path || output.options?.template) {
1738
+ const configWithTemplate = { ...config, templates: effectiveTemplateConfig };
1739
+ await generateWithTemplate(contexts, configWithTemplate, file, dryRun);
1740
+ } else {
1741
+ writeMarkdown(file, contexts, config, dryRun);
1742
+ }
1743
+ if (!dryRun) files.push(file);
1744
+ } catch (error) {
1745
+ (0, import_core9.warn)(`Failed to write ${file}: ${error instanceof Error ? error.message : String(error)}`);
1573
1746
  }
1574
1747
  break;
1575
1748
  }
1576
1749
  case "json": {
1577
1750
  const file = output.file ?? "changelog.json";
1578
- writeJson(file, contexts, dryRun);
1751
+ try {
1752
+ writeJson(file, contexts, dryRun);
1753
+ if (!dryRun) files.push(file);
1754
+ } catch (error) {
1755
+ (0, import_core9.warn)(`Failed to write ${file}: ${error instanceof Error ? error.message : String(error)}`);
1756
+ }
1579
1757
  break;
1580
1758
  }
1581
1759
  case "github-release": {
1582
1760
  if (dryRun) {
1583
- (0, import_core8.info)("[DRY RUN] Would create GitHub release");
1761
+ (0, import_core9.info)("[DRY RUN] Would create GitHub release");
1584
1762
  break;
1585
1763
  }
1586
1764
  const firstContext = contexts[0];
1587
1765
  if (!firstContext) {
1588
- (0, import_core8.warn)("No context available for GitHub release");
1766
+ (0, import_core9.warn)("No context available for GitHub release");
1589
1767
  break;
1590
1768
  }
1591
1769
  const repoUrl = firstContext.repoUrl;
1592
1770
  if (!repoUrl) {
1593
- (0, import_core8.warn)("No repo URL available, cannot create GitHub release");
1771
+ (0, import_core9.warn)("No repo URL available, cannot create GitHub release");
1594
1772
  break;
1595
1773
  }
1596
1774
  const parsed = parseRepoUrl(repoUrl);
1597
1775
  if (!parsed) {
1598
- (0, import_core8.warn)(`Could not parse repo URL: ${repoUrl}`);
1776
+ (0, import_core9.warn)(`Could not parse repo URL: ${repoUrl}`);
1599
1777
  break;
1600
1778
  }
1601
1779
  await createGitHubRelease(firstContext, {
@@ -1608,140 +1786,38 @@ async function runPipeline(input, config, dryRun) {
1608
1786
  }
1609
1787
  }
1610
1788
  }
1611
- }
1612
- async function processInput(inputJson, config, dryRun) {
1613
- const input = parsePackageVersioner(inputJson);
1614
- await runPipeline(input, config, dryRun);
1615
- }
1616
-
1617
- // src/monorepo/aggregator.ts
1618
- var fs9 = __toESM(require("fs"), 1);
1619
- var path7 = __toESM(require("path"), 1);
1620
- var import_core9 = require("@releasekit/core");
1621
-
1622
- // src/monorepo/splitter.ts
1623
- function splitByPackage(contexts) {
1624
- const byPackage = /* @__PURE__ */ new Map();
1625
- for (const ctx of contexts) {
1626
- byPackage.set(ctx.packageName, ctx);
1627
- }
1628
- return byPackage;
1629
- }
1630
-
1631
- // src/monorepo/aggregator.ts
1632
- function writeFile(outputPath, content, dryRun) {
1633
- if (dryRun) {
1634
- (0, import_core9.info)(`Would write to ${outputPath}`);
1635
- (0, import_core9.debug)(content);
1636
- return;
1637
- }
1638
- const dir = path7.dirname(outputPath);
1639
- if (!fs9.existsSync(dir)) {
1640
- fs9.mkdirSync(dir, { recursive: true });
1641
- }
1642
- fs9.writeFileSync(outputPath, content, "utf-8");
1643
- (0, import_core9.success)(`Changelog written to ${outputPath}`);
1644
- }
1645
- function aggregateToRoot(contexts) {
1646
- const aggregated = {
1647
- packageName: "monorepo",
1648
- version: contexts[0]?.version ?? "0.0.0",
1649
- previousVersion: contexts[0]?.previousVersion ?? null,
1650
- date: (/* @__PURE__ */ new Date()).toISOString().split("T")[0] ?? "",
1651
- repoUrl: contexts[0]?.repoUrl ?? null,
1652
- entries: []
1653
- };
1654
- for (const ctx of contexts) {
1655
- for (const entry of ctx.entries) {
1656
- aggregated.entries.push({
1657
- ...entry,
1658
- scope: entry.scope ? `${ctx.packageName}/${entry.scope}` : ctx.packageName
1659
- });
1789
+ if (config.monorepo?.mode) {
1790
+ const { detectMonorepo: detectMonorepo2, writeMonorepoChangelogs: writeMonorepoChangelogs2 } = await Promise.resolve().then(() => (init_aggregator(), aggregator_exports));
1791
+ const cwd = process.cwd();
1792
+ const detected = detectMonorepo2(cwd);
1793
+ if (detected.isMonorepo) {
1794
+ const monoFiles = writeMonorepoChangelogs2(
1795
+ contexts,
1796
+ {
1797
+ rootPath: config.monorepo.rootPath ?? cwd,
1798
+ packagesPath: config.monorepo.packagesPath ?? detected.packagesPath,
1799
+ mode: config.monorepo.mode
1800
+ },
1801
+ config,
1802
+ dryRun
1803
+ );
1804
+ files.push(...monoFiles);
1660
1805
  }
1661
1806
  }
1662
- return aggregated;
1663
- }
1664
- function writeMonorepoChangelogs(contexts, options, config, dryRun) {
1665
- if (options.mode === "root" || options.mode === "both") {
1666
- const aggregated = aggregateToRoot(contexts);
1667
- const rootPath = path7.join(options.rootPath, "CHANGELOG.md");
1668
- (0, import_core9.info)(`Writing root changelog to ${rootPath}`);
1669
- const rootContent = config.updateStrategy === "prepend" && fs9.existsSync(rootPath) ? prependVersion(rootPath, aggregated) : renderMarkdown([aggregated]);
1670
- writeFile(rootPath, rootContent, dryRun);
1671
- }
1672
- if (options.mode === "packages" || options.mode === "both") {
1673
- const byPackage = splitByPackage(contexts);
1674
- const packageDirMap = buildPackageDirMap(options.rootPath, options.packagesPath);
1675
- for (const [packageName, ctx] of byPackage) {
1676
- const simpleName = packageName.split("/").pop();
1677
- const packageDir = packageDirMap.get(packageName) ?? (simpleName ? packageDirMap.get(simpleName) : void 0) ?? null;
1678
- if (packageDir) {
1679
- const changelogPath = path7.join(packageDir, "CHANGELOG.md");
1680
- (0, import_core9.info)(`Writing changelog for ${packageName} to ${changelogPath}`);
1681
- const pkgContent = config.updateStrategy === "prepend" && fs9.existsSync(changelogPath) ? prependVersion(changelogPath, ctx) : renderMarkdown([ctx]);
1682
- writeFile(changelogPath, pkgContent, dryRun);
1683
- } else {
1684
- (0, import_core9.info)(`Could not find directory for package ${packageName}, skipping`);
1685
- }
1686
- }
1687
- }
1688
- }
1689
- function buildPackageDirMap(rootPath, packagesPath) {
1690
- const map = /* @__PURE__ */ new Map();
1691
- const packagesDir = path7.join(rootPath, packagesPath);
1692
- if (!fs9.existsSync(packagesDir)) {
1693
- return map;
1694
- }
1695
- for (const entry of fs9.readdirSync(packagesDir, { withFileTypes: true })) {
1696
- if (!entry.isDirectory()) continue;
1697
- const dirPath = path7.join(packagesDir, entry.name);
1698
- map.set(entry.name, dirPath);
1699
- const packageJsonPath = path7.join(dirPath, "package.json");
1700
- if (fs9.existsSync(packageJsonPath)) {
1701
- try {
1702
- const pkg = JSON.parse(fs9.readFileSync(packageJsonPath, "utf-8"));
1703
- if (pkg.name) {
1704
- map.set(pkg.name, dirPath);
1705
- }
1706
- } catch {
1707
- }
1708
- }
1807
+ const packageNotes = {};
1808
+ for (const ctx of contexts) {
1809
+ packageNotes[ctx.packageName] = formatVersion(ctx);
1709
1810
  }
1710
- return map;
1811
+ return { packageNotes, files };
1711
1812
  }
1712
- function detectMonorepo(cwd) {
1713
- const pnpmWorkspacesPath = path7.join(cwd, "pnpm-workspace.yaml");
1714
- const packageJsonPath = path7.join(cwd, "package.json");
1715
- if (fs9.existsSync(pnpmWorkspacesPath)) {
1716
- const content = fs9.readFileSync(pnpmWorkspacesPath, "utf-8");
1717
- const packagesMatch = content.match(/packages:\s*\n\s*-\s*['"]([^'"]+)['"]/);
1718
- if (packagesMatch?.[1]) {
1719
- const packagesGlob = packagesMatch[1];
1720
- const packagesPath = packagesGlob.replace(/\/?\*$/, "").replace(/\/\*\*$/, "");
1721
- return { isMonorepo: true, packagesPath: packagesPath || "packages" };
1722
- }
1723
- return { isMonorepo: true, packagesPath: "packages" };
1724
- }
1725
- if (fs9.existsSync(packageJsonPath)) {
1726
- try {
1727
- const content = fs9.readFileSync(packageJsonPath, "utf-8");
1728
- const pkg = JSON.parse(content);
1729
- if (pkg.workspaces) {
1730
- const workspaces = Array.isArray(pkg.workspaces) ? pkg.workspaces : pkg.workspaces.packages;
1731
- if (workspaces?.length) {
1732
- const firstWorkspace = workspaces[0];
1733
- if (firstWorkspace) {
1734
- const packagesPath = firstWorkspace.replace(/\/?\*$/, "").replace(/\/\*\*$/, "");
1735
- return { isMonorepo: true, packagesPath: packagesPath || "packages" };
1736
- }
1737
- }
1738
- }
1739
- } catch {
1740
- return { isMonorepo: false, packagesPath: "" };
1741
- }
1742
- }
1743
- return { isMonorepo: false, packagesPath: "" };
1813
+ async function processInput(inputJson, config, dryRun) {
1814
+ const input = parsePackageVersioner(inputJson);
1815
+ return runPipeline(input, config, dryRun);
1744
1816
  }
1817
+
1818
+ // src/index.ts
1819
+ init_aggregator();
1820
+ init_markdown();
1745
1821
  // Annotate the CommonJS export names for ESM import in node:
1746
1822
  0 && (module.exports = {
1747
1823
  ChangelogCreatorError,
@@ -1755,6 +1831,7 @@ function detectMonorepo(cwd) {
1755
1831
  aggregateToRoot,
1756
1832
  createTemplateContext,
1757
1833
  detectMonorepo,
1834
+ formatVersion,
1758
1835
  getDefaultConfig,
1759
1836
  getExitCode,
1760
1837
  loadAuth,