@williamthorsen/release-kit 5.2.0 → 5.3.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.
Files changed (47) hide show
  1. package/CHANGELOG.md +69 -25
  2. package/README.md +238 -44
  3. package/cliff.toml.template +4 -39
  4. package/dist/esm/.cache +1 -1
  5. package/dist/esm/bin/release-kit.js +59 -0
  6. package/dist/esm/buildChangelogEntries.js +6 -0
  7. package/dist/esm/buildEmptyReleaseEntry.d.ts +2 -0
  8. package/dist/esm/buildEmptyReleaseEntry.js +16 -0
  9. package/dist/esm/changelogJsonFile.d.ts +2 -0
  10. package/dist/esm/changelogJsonFile.js +11 -1
  11. package/dist/esm/changelogJsonUtils.d.ts +2 -1
  12. package/dist/esm/changelogJsonUtils.js +9 -0
  13. package/dist/esm/changelogOverrides.d.ts +53 -0
  14. package/dist/esm/changelogOverrides.js +424 -0
  15. package/dist/esm/checkWorkTypesDrift.js +3 -2
  16. package/dist/esm/createGithubReleaseCommand.js +0 -9
  17. package/dist/esm/defaults.js +1 -1
  18. package/dist/esm/generateChangelogs.d.ts +0 -3
  19. package/dist/esm/generateChangelogs.js +1 -35
  20. package/dist/esm/index.d.ts +2 -0
  21. package/dist/esm/index.js +8 -0
  22. package/dist/esm/loadConfig.d.ts +1 -1
  23. package/dist/esm/releasePrepare.js +68 -11
  24. package/dist/esm/releasePrepareMono.js +103 -56
  25. package/dist/esm/releasePrepareProject.d.ts +4 -1
  26. package/dist/esm/releasePrepareProject.js +74 -18
  27. package/dist/esm/renderChangelogMarkdown.d.ts +12 -0
  28. package/dist/esm/renderChangelogMarkdown.js +32 -0
  29. package/dist/esm/renderReleaseNotes.js +6 -1
  30. package/dist/esm/resolveReleaseNotesConfig.js +3 -1
  31. package/dist/esm/runGitCliff.d.ts +1 -0
  32. package/dist/esm/runGitCliff.js +7 -0
  33. package/dist/esm/syncWorkTypes.js +3 -2
  34. package/dist/esm/types.d.ts +98 -31
  35. package/dist/esm/types.js +60 -0
  36. package/dist/esm/validateConfig.js +84 -345
  37. package/dist/esm/validateOverridesCommand.d.ts +13 -0
  38. package/dist/esm/validateOverridesCommand.js +119 -0
  39. package/dist/esm/work-types.json +23 -17
  40. package/dist/esm/work-types.schema.json +28 -1
  41. package/dist/esm/workTypesData.d.ts +8 -0
  42. package/dist/esm/workTypesData.js +20 -17
  43. package/dist/esm/workTypesUtils.d.ts +1 -0
  44. package/dist/esm/workTypesUtils.js +8 -0
  45. package/package.json +4 -3
  46. package/dist/esm/writeSyntheticChangelog.d.ts +0 -9
  47. package/dist/esm/writeSyntheticChangelog.js +0 -27
@@ -1,5 +1,13 @@
1
1
  import { existsSync, readFileSync } from "node:fs";
2
2
  import { isRecord, isUnknownArray } from "./typeGuards.js";
3
+ function isChangelogItem(value) {
4
+ if (!isRecord(value)) return false;
5
+ if (typeof value.description !== "string") return false;
6
+ if (value.body !== void 0 && typeof value.body !== "string") return false;
7
+ if (value.breaking !== void 0 && typeof value.breaking !== "boolean") return false;
8
+ if (value.hash !== void 0 && typeof value.hash !== "string") return false;
9
+ return true;
10
+ }
3
11
  function isChangelogEntry(value) {
4
12
  return isRecord(value) && typeof value.version === "string" && typeof value.date === "string" && isUnknownArray(value.sections);
5
13
  }
@@ -25,5 +33,6 @@ function readChangelogEntries(filePath) {
25
33
  export {
26
34
  extractVersion,
27
35
  isChangelogEntry,
36
+ isChangelogItem,
28
37
  readChangelogEntries
29
38
  };
@@ -0,0 +1,53 @@
1
+ import type { ChangelogEntry, ChangelogOverride, WorkspaceConfig } from './types.ts';
2
+ export type LoadChangelogOverridesResult = {
3
+ overrides: Map<string, ChangelogOverride>;
4
+ } | {
5
+ errors: string[];
6
+ };
7
+ export declare function loadChangelogOverrides(path: string): LoadChangelogOverridesResult;
8
+ export declare function validateChangelogOverrides(raw: unknown): {
9
+ overrides: Map<string, ChangelogOverride>;
10
+ errors: string[];
11
+ };
12
+ export declare function formatStaleOverrideKeyWarning(key: string): string;
13
+ export declare function applyChangelogOverrides(entries: ChangelogEntry[], overrides: Map<string, ChangelogOverride>): {
14
+ entries: ChangelogEntry[];
15
+ warnings: string[];
16
+ errors: string[];
17
+ matchedKeys: string[];
18
+ };
19
+ export declare function resolveOverridePath(scopeRoot: string): string;
20
+ export interface LoadOverridesForScopesResult {
21
+ project: Map<string, ChangelogOverride>;
22
+ perWorkspace: Map<string, Map<string, ChangelogOverride>>;
23
+ errors: string[];
24
+ }
25
+ export declare function loadOverridesForScopes(scopes: {
26
+ project?: string;
27
+ workspaces?: string[];
28
+ }): LoadOverridesForScopesResult;
29
+ export declare function composeOverrides(rootEntries: Map<string, ChangelogOverride>, workspaceEntries: Map<string, ChangelogOverride> | undefined): Map<string, ChangelogOverride>;
30
+ export interface OverrideContext {
31
+ project: Map<string, ChangelogOverride>;
32
+ perWorkspace: Map<string, Map<string, ChangelogOverride>>;
33
+ overrideWarnings: string[];
34
+ globalMatchedRootKeys: Set<string>;
35
+ }
36
+ export declare function createOverrideContext(workspaces: WorkspaceConfig[]): OverrideContext;
37
+ export interface ChangelogOverrideScope {
38
+ filePath: string;
39
+ hashes: readonly string[];
40
+ }
41
+ export interface ValidateAllChangelogOverridesInputs {
42
+ project?: {
43
+ filePath: string;
44
+ hashes?: readonly string[];
45
+ };
46
+ workspaces?: readonly ChangelogOverrideScope[];
47
+ }
48
+ export interface ValidateAllChangelogOverridesResult {
49
+ errors: string[];
50
+ warnings: string[];
51
+ }
52
+ export declare function validateAllChangelogOverrides(inputs: ValidateAllChangelogOverridesInputs): ValidateAllChangelogOverridesResult;
53
+ export declare function applyWorkspaceOverrides(newEntries: ChangelogEntry[], workspacePath: string, overrideContext: OverrideContext): ReturnType<typeof applyChangelogOverrides>;
@@ -0,0 +1,424 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import path from "node:path";
3
+ import { isRecord } from "./typeGuards.js";
4
+ const OVERRIDES_FILENAME = ".meta/changelog-overrides.json";
5
+ const VALID_AUDIENCE_VALUES = /* @__PURE__ */ new Set(["all", "dev", "skip"]);
6
+ const V1_SUPPORTED_AUDIENCE_VALUES = /* @__PURE__ */ new Set(["skip"]);
7
+ const KNOWN_OVERRIDE_FIELDS = /* @__PURE__ */ new Set(["audience", "description", "body", "breaking"]);
8
+ function loadChangelogOverrides(path2) {
9
+ if (!existsSync(path2)) {
10
+ return { overrides: /* @__PURE__ */ new Map() };
11
+ }
12
+ let content;
13
+ try {
14
+ content = readFileSync(path2, "utf8");
15
+ } catch (error) {
16
+ return {
17
+ errors: [`Failed to read override file ${path2}: ${error instanceof Error ? error.message : String(error)}`]
18
+ };
19
+ }
20
+ let parsed;
21
+ try {
22
+ parsed = JSON.parse(content);
23
+ } catch (error) {
24
+ return {
25
+ errors: [`Failed to parse override file ${path2}: ${error instanceof Error ? error.message : String(error)}`]
26
+ };
27
+ }
28
+ const result = validateChangelogOverrides(parsed);
29
+ if (result.errors.length > 0) {
30
+ return { errors: result.errors };
31
+ }
32
+ return { overrides: result.overrides };
33
+ }
34
+ function validateChangelogOverrides(raw) {
35
+ const overrides = /* @__PURE__ */ new Map();
36
+ const errors = [];
37
+ if (!isRecord(raw)) {
38
+ errors.push("Override file: top-level value must be an object keyed by commit hash");
39
+ return { overrides, errors };
40
+ }
41
+ for (const [key, rawEntry] of Object.entries(raw)) {
42
+ if (key === "") {
43
+ errors.push("Override file: empty-string key is not a valid commit hash");
44
+ continue;
45
+ }
46
+ const validated = validateSingleOverride(key, rawEntry, errors);
47
+ if (validated !== void 0) {
48
+ overrides.set(key, validated);
49
+ }
50
+ }
51
+ return { overrides, errors };
52
+ }
53
+ function validateSingleOverride(key, rawEntry, errors) {
54
+ if (!isRecord(rawEntry)) {
55
+ errors.push(`overrides['${key}']: must be an object`);
56
+ return void 0;
57
+ }
58
+ let entryValid = true;
59
+ for (const fieldName of Object.keys(rawEntry)) {
60
+ if (!KNOWN_OVERRIDE_FIELDS.has(fieldName)) {
61
+ errors.push(`overrides['${key}']: unknown field '${fieldName}'`);
62
+ entryValid = false;
63
+ }
64
+ }
65
+ const result = {};
66
+ if (rawEntry.audience !== void 0) {
67
+ const audienceResult = validateAudience(key, rawEntry.audience, errors);
68
+ if (audienceResult === void 0) {
69
+ entryValid = false;
70
+ } else {
71
+ result.audience = audienceResult;
72
+ }
73
+ }
74
+ if (rawEntry.description !== void 0) {
75
+ if (typeof rawEntry.description !== "string") {
76
+ errors.push(`overrides['${key}']: 'description' must be a string`);
77
+ entryValid = false;
78
+ } else {
79
+ result.description = rawEntry.description;
80
+ }
81
+ }
82
+ if (rawEntry.body !== void 0) {
83
+ if (typeof rawEntry.body !== "string") {
84
+ errors.push(`overrides['${key}']: 'body' must be a string`);
85
+ entryValid = false;
86
+ } else {
87
+ result.body = rawEntry.body;
88
+ }
89
+ }
90
+ if (rawEntry.breaking !== void 0) {
91
+ if (typeof rawEntry.breaking !== "boolean") {
92
+ errors.push(`overrides['${key}']: 'breaking' must be a boolean`);
93
+ entryValid = false;
94
+ } else {
95
+ result.breaking = rawEntry.breaking;
96
+ }
97
+ }
98
+ if (Object.keys(result).length === 0 && entryValid) {
99
+ errors.push(`overrides['${key}']: at least one override field must be set`);
100
+ return void 0;
101
+ }
102
+ if (!entryValid) {
103
+ return void 0;
104
+ }
105
+ return result;
106
+ }
107
+ function validateAudience(key, value, errors) {
108
+ if (typeof value !== "string" || !VALID_AUDIENCE_VALUES.has(value)) {
109
+ errors.push(`overrides['${key}']: 'audience' must be one of 'all' | 'dev' | 'skip'`);
110
+ return void 0;
111
+ }
112
+ if (!V1_SUPPORTED_AUDIENCE_VALUES.has(value)) {
113
+ errors.push(`overrides['${key}']: audience '${value}' is not yet supported; only 'skip' is currently accepted`);
114
+ return void 0;
115
+ }
116
+ return "skip";
117
+ }
118
+ function formatStaleOverrideKeyWarning(key) {
119
+ return `Override key '${key}' did not match any commit hash in the changelog (likely a stale reference)`;
120
+ }
121
+ function applyChangelogOverrides(entries, overrides) {
122
+ const warnings = [];
123
+ const errors = [];
124
+ const matchedKeys = [];
125
+ if (overrides.size === 0) {
126
+ return { entries: entries.map(cloneEntry), warnings, errors, matchedKeys };
127
+ }
128
+ const allHashes = [];
129
+ for (const entry of entries) {
130
+ for (const section of entry.sections) {
131
+ for (const item of section.items) {
132
+ if (item.hash !== void 0) {
133
+ allHashes.push(item.hash);
134
+ }
135
+ }
136
+ }
137
+ }
138
+ const keyToMatchedHashes = /* @__PURE__ */ new Map();
139
+ for (const overrideKey of overrides.keys()) {
140
+ const matches = allHashes.filter((hash) => hash.startsWith(overrideKey));
141
+ if (matches.length === 0) {
142
+ continue;
143
+ }
144
+ if (matches.length > 1) {
145
+ errors.push(
146
+ `Override key '${overrideKey}' is ambiguous: matches multiple commits (${matches.join(", ")}). Use a longer prefix or the full commit hash.`
147
+ );
148
+ continue;
149
+ }
150
+ keyToMatchedHashes.set(overrideKey, matches);
151
+ matchedKeys.push(overrideKey);
152
+ }
153
+ const hashToOverride = /* @__PURE__ */ new Map();
154
+ for (const [overrideKey, matchedHashes] of keyToMatchedHashes) {
155
+ const override = overrides.get(overrideKey);
156
+ if (override === void 0) continue;
157
+ for (const hash of matchedHashes) {
158
+ hashToOverride.set(hash, override);
159
+ }
160
+ }
161
+ const transformedEntries = [];
162
+ for (const entry of entries) {
163
+ const transformedSections = [];
164
+ for (const section of entry.sections) {
165
+ const transformedItems = applyOverridesToItems(section.items, hashToOverride);
166
+ if (transformedItems.length === 0) {
167
+ continue;
168
+ }
169
+ transformedSections.push({ ...section, items: transformedItems });
170
+ }
171
+ transformedEntries.push({ ...entry, sections: transformedSections });
172
+ }
173
+ return { entries: transformedEntries, warnings, errors, matchedKeys };
174
+ }
175
+ function applyOverridesToItems(items, hashToOverride) {
176
+ const result = [];
177
+ for (const item of items) {
178
+ if (item.hash === void 0) {
179
+ result.push(cloneItem(item));
180
+ continue;
181
+ }
182
+ const override = hashToOverride.get(item.hash);
183
+ if (override === void 0) {
184
+ result.push(cloneItem(item));
185
+ continue;
186
+ }
187
+ if (override.audience === "skip") {
188
+ continue;
189
+ }
190
+ result.push(applyOverrideToItem(item, override));
191
+ }
192
+ return result;
193
+ }
194
+ function applyOverrideToItem(item, override) {
195
+ const result = { ...item };
196
+ if (override.description !== void 0) {
197
+ result.description = override.description;
198
+ }
199
+ if (override.body !== void 0) {
200
+ result.body = override.body;
201
+ }
202
+ if (override.breaking !== void 0) {
203
+ result.breaking = override.breaking;
204
+ }
205
+ return result;
206
+ }
207
+ function cloneItem(item) {
208
+ return { ...item };
209
+ }
210
+ function cloneEntry(entry) {
211
+ return {
212
+ ...entry,
213
+ sections: entry.sections.map((section) => ({ ...section, items: section.items.map(cloneItem) }))
214
+ };
215
+ }
216
+ function resolveOverridePath(scopeRoot) {
217
+ return path.posix.join(scopeRoot, OVERRIDES_FILENAME);
218
+ }
219
+ function loadOverridesForScopes(scopes) {
220
+ const errors = [];
221
+ let project = /* @__PURE__ */ new Map();
222
+ const perWorkspace = /* @__PURE__ */ new Map();
223
+ if (scopes.project !== void 0) {
224
+ const result = loadChangelogOverrides(resolveOverridePath(scopes.project));
225
+ if ("errors" in result) {
226
+ errors.push(...result.errors);
227
+ } else {
228
+ project = result.overrides;
229
+ }
230
+ }
231
+ for (const workspacePath of scopes.workspaces ?? []) {
232
+ const result = loadChangelogOverrides(resolveOverridePath(workspacePath));
233
+ if ("errors" in result) {
234
+ errors.push(...result.errors);
235
+ } else if (result.overrides.size > 0) {
236
+ perWorkspace.set(workspacePath, result.overrides);
237
+ }
238
+ }
239
+ return { project, perWorkspace, errors };
240
+ }
241
+ function composeOverrides(rootEntries, workspaceEntries) {
242
+ const composed = new Map(rootEntries);
243
+ if (workspaceEntries !== void 0) {
244
+ for (const [key, value] of workspaceEntries) {
245
+ composed.set(key, value);
246
+ }
247
+ }
248
+ return composed;
249
+ }
250
+ function createOverrideContext(workspaces) {
251
+ const result = loadOverridesForScopes({
252
+ project: ".",
253
+ workspaces: workspaces.map((workspace) => workspace.workspacePath)
254
+ });
255
+ if (result.errors.length > 0) {
256
+ throw new Error(`Failed to load changelog overrides:
257
+ - ${result.errors.join("\n - ")}`);
258
+ }
259
+ return {
260
+ project: result.project,
261
+ perWorkspace: result.perWorkspace,
262
+ overrideWarnings: [],
263
+ globalMatchedRootKeys: /* @__PURE__ */ new Set()
264
+ };
265
+ }
266
+ function validateAllChangelogOverrides(inputs) {
267
+ const errors = [];
268
+ const warnings = [];
269
+ const projectFilePath = inputs.project?.filePath;
270
+ const projectMap = loadScopeMap(projectFilePath, errors);
271
+ const workspaceMaps = (inputs.workspaces ?? []).map((scope) => ({
272
+ filePath: scope.filePath,
273
+ hashes: scope.hashes,
274
+ map: loadScopeMap(scope.filePath, errors)
275
+ }));
276
+ const globalMatchedRootKeys = /* @__PURE__ */ new Set();
277
+ for (const workspace of workspaceMaps) {
278
+ processWorkspaceScope({
279
+ workspace,
280
+ projectFilePath,
281
+ projectMap,
282
+ errors,
283
+ warnings,
284
+ globalMatchedRootKeys
285
+ });
286
+ }
287
+ const projectHashes = inputs.project?.hashes;
288
+ if (projectFilePath !== void 0 && projectHashes !== void 0) {
289
+ processProjectScope({ projectFilePath, projectMap, projectHashes, errors, globalMatchedRootKeys });
290
+ }
291
+ if (projectFilePath !== void 0) {
292
+ collectRootStaleWarnings(projectFilePath, projectMap, globalMatchedRootKeys, warnings);
293
+ }
294
+ return { errors, warnings };
295
+ }
296
+ function processWorkspaceScope(args) {
297
+ const { workspace, projectFilePath, projectMap, errors, warnings, globalMatchedRootKeys } = args;
298
+ const { filePath, hashes, map } = workspace;
299
+ const workspaceApplied = applyChangelogOverrides(makeValidationEntries(hashes), map);
300
+ for (const message of workspaceApplied.errors) {
301
+ errors.push(prefixWithFilePath(filePath, message));
302
+ }
303
+ if (projectFilePath !== void 0 && projectMap.size > 0) {
304
+ const projectMinusShadowed = filterShadowedKeys(projectMap, map);
305
+ const projectApplied = applyChangelogOverrides(makeValidationEntries(hashes), projectMinusShadowed);
306
+ for (const message of projectApplied.errors) {
307
+ errors.push(prefixWithFilePath(projectFilePath, message));
308
+ }
309
+ }
310
+ for (const key of map.keys()) {
311
+ if (!hasAnyMatch(key, hashes)) {
312
+ warnings.push(formatWorkspaceStaleWarning(filePath, key));
313
+ }
314
+ }
315
+ for (const key of projectMap.keys()) {
316
+ if (map.has(key)) continue;
317
+ if (hasAnyMatch(key, hashes)) {
318
+ globalMatchedRootKeys.add(key);
319
+ }
320
+ }
321
+ }
322
+ function processProjectScope(args) {
323
+ const { projectFilePath, projectMap, projectHashes, errors, globalMatchedRootKeys } = args;
324
+ const applied = applyChangelogOverrides(makeValidationEntries(projectHashes), projectMap);
325
+ for (const message of applied.errors) {
326
+ errors.push(prefixWithFilePath(projectFilePath, message));
327
+ }
328
+ for (const key of projectMap.keys()) {
329
+ if (hasAnyMatch(key, projectHashes)) {
330
+ globalMatchedRootKeys.add(key);
331
+ }
332
+ }
333
+ }
334
+ function collectRootStaleWarnings(projectFilePath, projectMap, globalMatchedRootKeys, warnings) {
335
+ for (const key of projectMap.keys()) {
336
+ if (!globalMatchedRootKeys.has(key)) {
337
+ warnings.push(formatRootStaleWarning(projectFilePath, key));
338
+ }
339
+ }
340
+ }
341
+ function hasAnyMatch(key, hashes) {
342
+ return hashes.some((hash) => hash.startsWith(key));
343
+ }
344
+ function filterShadowedKeys(projectMap, workspaceMap) {
345
+ const result = /* @__PURE__ */ new Map();
346
+ for (const [key, value] of projectMap) {
347
+ if (workspaceMap.has(key)) continue;
348
+ result.set(key, value);
349
+ }
350
+ return result;
351
+ }
352
+ function loadScopeMap(filePath, errors) {
353
+ if (filePath === void 0) {
354
+ return /* @__PURE__ */ new Map();
355
+ }
356
+ const result = loadChangelogOverrides(filePath);
357
+ if ("errors" in result) {
358
+ for (const message of result.errors) {
359
+ errors.push(prefixWithFilePath(filePath, message));
360
+ }
361
+ return /* @__PURE__ */ new Map();
362
+ }
363
+ return result.overrides;
364
+ }
365
+ function makeValidationEntries(hashes) {
366
+ return [
367
+ {
368
+ version: "0.0.0",
369
+ date: "0000-00-00",
370
+ sections: [
371
+ {
372
+ title: "Validation",
373
+ audience: "all",
374
+ items: hashes.map((hash) => ({ description: "", hash }))
375
+ }
376
+ ]
377
+ }
378
+ ];
379
+ }
380
+ function prefixWithFilePath(filePath, message) {
381
+ return `${filePath}: ${message}`;
382
+ }
383
+ function formatWorkspaceStaleWarning(filePath, key) {
384
+ return `${filePath}: Override key '${key}' did not match any commit in this workspace's history (likely a stale reference)`;
385
+ }
386
+ function formatRootStaleWarning(filePath, key) {
387
+ return `${filePath}: Override key '${key}' did not match any commit in any scope (likely a stale reference)`;
388
+ }
389
+ function applyWorkspaceOverrides(newEntries, workspacePath, overrideContext) {
390
+ const { project, perWorkspace, overrideWarnings, globalMatchedRootKeys } = overrideContext;
391
+ const workspaceOverrides = perWorkspace.get(workspacePath);
392
+ const composed = composeOverrides(project, workspaceOverrides);
393
+ const applied = applyChangelogOverrides(newEntries, composed);
394
+ if (applied.errors.length > 0) {
395
+ throw new Error(`Changelog override application failed:
396
+ - ${applied.errors.join("\n - ")}`);
397
+ }
398
+ overrideWarnings.push(...applied.warnings);
399
+ const matchedSet = new Set(applied.matchedKeys);
400
+ if (workspaceOverrides !== void 0) {
401
+ for (const key of workspaceOverrides.keys()) {
402
+ if (!matchedSet.has(key)) {
403
+ overrideWarnings.push(formatStaleOverrideKeyWarning(key));
404
+ }
405
+ }
406
+ }
407
+ for (const key of applied.matchedKeys) {
408
+ if (workspaceOverrides?.has(key)) continue;
409
+ globalMatchedRootKeys.add(key);
410
+ }
411
+ return applied;
412
+ }
413
+ export {
414
+ applyChangelogOverrides,
415
+ applyWorkspaceOverrides,
416
+ composeOverrides,
417
+ createOverrideContext,
418
+ formatStaleOverrideKeyWarning,
419
+ loadChangelogOverrides,
420
+ loadOverridesForScopes,
421
+ resolveOverridePath,
422
+ validateAllChangelogOverrides,
423
+ validateChangelogOverrides
424
+ };
@@ -1,7 +1,7 @@
1
1
  import { readFileSync } from "node:fs";
2
2
  import { dirname, resolve } from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
- import { errorMessage, hasExpectedTopLevelShape } from "./workTypesUtils.js";
4
+ import { buildFetchInit, errorMessage, hasExpectedTopLevelShape } from "./workTypesUtils.js";
5
5
  const UPSTREAM_WORK_TYPES_URL = "https://raw.githubusercontent.com/williamthorsen/codeassembly/main/packages/agents/content/skills/_data/work-types.json";
6
6
  function resolveDefaultLocalPath() {
7
7
  const moduleDir = dirname(fileURLToPath(import.meta.url));
@@ -21,9 +21,10 @@ async function checkWorkTypesDrift(dependencies = {}) {
21
21
  message: `Local work-types.json is not valid JSON: ${errorMessage(error)}`
22
22
  };
23
23
  }
24
+ const fetchInit = buildFetchInit();
24
25
  let response;
25
26
  try {
26
- response = await fetcher(url);
27
+ response = fetchInit === void 0 ? await fetcher(url) : await fetcher(url, fetchInit);
27
28
  } catch (error) {
28
29
  return {
29
30
  exitCode: 2,
@@ -26,15 +26,6 @@ async function createGithubReleaseCommand(argv) {
26
26
  console.error(`Error creating GitHub Releases: ${error instanceof Error ? error.message : String(error)}`);
27
27
  process.exit(1);
28
28
  }
29
- if (requestedTags !== void 0) {
30
- const noEntryTags = outcome.skipped.filter((s) => s.reason === "no-entry").map((s) => s.tag);
31
- if (noEntryTags.length > 0) {
32
- console.error(
33
- `Error: requested tags have no changelog entry: ${noEntryTags.join(", ")}. Verify the tag names match a published changelog version.`
34
- );
35
- process.exit(1);
36
- }
37
- }
38
29
  if (outcome.skipped.length > 0) {
39
30
  const formatted = outcome.skipped.map((s) => `${s.tag} (${s.reason})`).join(", ");
40
31
  console.info(`Skipped ${outcome.skipped.length} tag(s) with no releasable content: ${formatted}.`);
@@ -3,7 +3,7 @@ import { WORK_TYPES_DATA as WORK_TYPES_DATA2 } from "./workTypesData.js";
3
3
  function composeHeader(entry) {
4
4
  return `${entry.emoji} ${entry.label}`;
5
5
  }
6
- const DEV_ONLY_TIERS = /* @__PURE__ */ new Set(["Internal", "Process"]);
6
+ const DEV_ONLY_TIERS = /* @__PURE__ */ new Set(["internal", "process"]);
7
7
  function deriveDefaultWorkTypes() {
8
8
  const result = {};
9
9
  for (const entry of WORK_TYPES_DATA.types) {
@@ -1,8 +1,5 @@
1
- import type { ReleaseConfig } from './types.ts';
2
1
  export declare function buildTagPattern(tagPrefixes: readonly string[]): string;
3
2
  export interface GenerateChangelogOptions {
4
3
  tagPattern?: string;
5
4
  includePaths?: string[];
6
5
  }
7
- export declare function generateChangelog(config: Pick<ReleaseConfig, 'cliffConfigPath'>, changelogPath: string, tag: string, dryRun: boolean, options?: GenerateChangelogOptions): string[];
8
- export declare function generateChangelogs(config: ReleaseConfig, tag: string, dryRun: boolean): string[];
@@ -1,5 +1,3 @@
1
- import { resolveCliffConfigPath } from "./resolveCliffConfigPath.js";
2
- import { runGitCliff } from "./runGitCliff.js";
3
1
  function buildTagPattern(tagPrefixes) {
4
2
  if (tagPrefixes.length === 0) {
5
3
  throw new Error("buildTagPattern: tagPrefixes must contain at least one entry");
@@ -14,38 +12,6 @@ function buildTagPattern(tagPrefixes) {
14
12
  function escapeRegex(value) {
15
13
  return value.replace(/[.*+?^${}()|[\]\\]/g, String.raw`\$&`);
16
14
  }
17
- function generateChangelog(config, changelogPath, tag, dryRun, options) {
18
- const outputFile = `${changelogPath}/CHANGELOG.md`;
19
- if (dryRun) {
20
- return [outputFile];
21
- }
22
- const resolvedConfigPath = resolveCliffConfigPath(config.cliffConfigPath, import.meta.url);
23
- const cliffArgs = ["--output", outputFile, "--tag", tag];
24
- if (options?.tagPattern !== void 0) {
25
- cliffArgs.push("--tag-pattern", options.tagPattern);
26
- }
27
- for (const includePath of options?.includePaths ?? []) {
28
- cliffArgs.push("--include-path", includePath);
29
- }
30
- try {
31
- runGitCliff(resolvedConfigPath, cliffArgs, "inherit");
32
- } catch (error) {
33
- throw new Error(
34
- `Failed to generate changelog for ${outputFile}: ${error instanceof Error ? error.message : String(error)}`
35
- );
36
- }
37
- return [outputFile];
38
- }
39
- function generateChangelogs(config, tag, dryRun) {
40
- const tagPattern = buildTagPattern([config.tagPrefix]);
41
- const results = [];
42
- for (const changelogPath of config.changelogPaths) {
43
- results.push(...generateChangelog(config, changelogPath, tag, dryRun, { tagPattern }));
44
- }
45
- return results;
46
- }
47
15
  export {
48
- buildTagPattern,
49
- generateChangelog,
50
- generateChangelogs
16
+ buildTagPattern
51
17
  };
@@ -1,2 +1,4 @@
1
+ export { type ChangelogOverrideScope, validateAllChangelogOverrides, type ValidateAllChangelogOverridesInputs, type ValidateAllChangelogOverridesResult, } from './changelogOverrides.ts';
1
2
  export type { SyncLabelsConfig } from './sync-labels/types.ts';
2
3
  export type { ReleaseKitConfig } from './types.ts';
4
+ export { formatValidateOverridesResult, type ValidateOverridesCommandResult } from './validateOverridesCommand.ts';
package/dist/esm/index.js CHANGED
@@ -0,0 +1,8 @@
1
+ import {
2
+ validateAllChangelogOverrides
3
+ } from "./changelogOverrides.js";
4
+ import { formatValidateOverridesResult } from "./validateOverridesCommand.js";
5
+ export {
6
+ formatValidateOverridesResult,
7
+ validateAllChangelogOverrides
8
+ };
@@ -12,4 +12,4 @@ export interface RootPackageInfo {
12
12
  }
13
13
  export declare function mergeMonorepoConfig(discoveredPaths: string[], userConfig: ReleaseKitConfig | undefined, rootPackage?: RootPackageInfo): MonorepoReleaseConfig;
14
14
  export declare function mergeSinglePackageConfig(userConfig: ReleaseKitConfig | undefined): ReleaseConfig;
15
- export declare function resolveWorkTypes(userWorkTypes?: Record<string, WorkTypeConfig>): Record<string, WorkTypeConfig>;
15
+ export declare function resolveWorkTypes(userWorkTypes?: ReleaseKitConfig['workTypes']): Record<string, WorkTypeConfig>;