@williamthorsen/release-kit 6.0.0 → 8.0.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 (134) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +5 -3
  3. package/dist/esm/assertCleanWorkingTree.js +9 -14
  4. package/dist/esm/bin/release-kit.js +200 -199
  5. package/dist/esm/buildChangelogEntries.d.ts +2 -2
  6. package/dist/esm/buildChangelogEntries.js +142 -149
  7. package/dist/esm/buildDependencyGraph.d.ts +1 -1
  8. package/dist/esm/buildDependencyGraph.js +60 -59
  9. package/dist/esm/buildEmptyReleaseEntry.d.ts +1 -1
  10. package/dist/esm/buildEmptyReleaseEntry.js +12 -15
  11. package/dist/esm/buildReleaseSummary.d.ts +1 -1
  12. package/dist/esm/buildReleaseSummary.js +23 -26
  13. package/dist/esm/buildSyntheticChangelogEntry.d.ts +1 -1
  14. package/dist/esm/buildSyntheticChangelogEntry.js +9 -12
  15. package/dist/esm/bumpAllVersions.d.ts +1 -1
  16. package/dist/esm/bumpAllVersions.js +51 -52
  17. package/dist/esm/bumpVersion.d.ts +1 -1
  18. package/dist/esm/bumpVersion.js +25 -28
  19. package/dist/esm/changelogJsonFile.d.ts +1 -1
  20. package/dist/esm/changelogJsonFile.js +59 -62
  21. package/dist/esm/changelogJsonUtils.d.ts +1 -1
  22. package/dist/esm/changelogJsonUtils.js +35 -32
  23. package/dist/esm/changelogOverrides.d.ts +1 -1
  24. package/dist/esm/changelogOverrides.js +374 -377
  25. package/dist/esm/checkWorkTypesDrift.js +104 -102
  26. package/dist/esm/collectPolicyViolations.d.ts +2 -2
  27. package/dist/esm/collectPolicyViolations.js +11 -14
  28. package/dist/esm/commitCommand.js +48 -46
  29. package/dist/esm/compareVersions.js +20 -23
  30. package/dist/esm/createGithubRelease.js +56 -59
  31. package/dist/esm/createGithubReleaseCommand.js +21 -23
  32. package/dist/esm/createTags.js +57 -56
  33. package/dist/esm/decideRelease.d.ts +2 -2
  34. package/dist/esm/decideRelease.js +27 -41
  35. package/dist/esm/defaults.d.ts +3 -3
  36. package/dist/esm/defaults.js +36 -48
  37. package/dist/esm/deleteFileIfExists.js +10 -12
  38. package/dist/esm/deriveWorkspaceConfig.d.ts +1 -1
  39. package/dist/esm/deriveWorkspaceConfig.js +34 -36
  40. package/dist/esm/detectPackageManager.js +35 -37
  41. package/dist/esm/detectUndeclaredTagPrefixes.js +41 -40
  42. package/dist/esm/determineBumpFromCommits.d.ts +2 -2
  43. package/dist/esm/determineBumpFromCommits.js +25 -29
  44. package/dist/esm/determineBumpType.d.ts +1 -1
  45. package/dist/esm/determineBumpType.js +31 -32
  46. package/dist/esm/discoverWorkspaces.js +38 -40
  47. package/dist/esm/format.js +6 -11
  48. package/dist/esm/generateChangelogs.d.ts +1 -1
  49. package/dist/esm/generateChangelogs.js +13 -17
  50. package/dist/esm/getCommitsSinceTarget.d.ts +1 -1
  51. package/dist/esm/getCommitsSinceTarget.js +54 -55
  52. package/dist/esm/hasPrettierConfig.js +33 -35
  53. package/dist/esm/help/prepareHelp.js +4 -8
  54. package/dist/esm/index.d.ts +4 -4
  55. package/dist/esm/index.js +2 -8
  56. package/dist/esm/init/checks.js +28 -32
  57. package/dist/esm/init/detectRepoType.js +12 -15
  58. package/dist/esm/init/initCommand.js +60 -54
  59. package/dist/esm/init/parseJsonRecord.js +9 -11
  60. package/dist/esm/init/scaffold.d.ts +1 -1
  61. package/dist/esm/init/scaffold.js +32 -38
  62. package/dist/esm/init/templates.d.ts +1 -1
  63. package/dist/esm/init/templates.js +16 -22
  64. package/dist/esm/injectReleaseNotesIntoReadme.js +42 -49
  65. package/dist/esm/injectSection.js +17 -27
  66. package/dist/esm/loadConfig.d.ts +1 -1
  67. package/dist/esm/loadConfig.js +206 -225
  68. package/dist/esm/parseCommitMessage.d.ts +1 -1
  69. package/dist/esm/parseCommitMessage.js +72 -76
  70. package/dist/esm/parseRequestedTags.js +6 -9
  71. package/dist/esm/prepareCommand.d.ts +1 -1
  72. package/dist/esm/prepareCommand.js +225 -235
  73. package/dist/esm/previewTagPrefixes.d.ts +1 -1
  74. package/dist/esm/previewTagPrefixes.js +101 -96
  75. package/dist/esm/propagateBumps.d.ts +2 -2
  76. package/dist/esm/propagateBumps.js +48 -50
  77. package/dist/esm/publish.d.ts +2 -2
  78. package/dist/esm/publish.js +22 -28
  79. package/dist/esm/publishCommand.js +75 -80
  80. package/dist/esm/pushCommand.js +33 -34
  81. package/dist/esm/pushRelease.d.ts +1 -1
  82. package/dist/esm/pushRelease.js +21 -24
  83. package/dist/esm/readCurrentVersion.js +13 -17
  84. package/dist/esm/releasePrepare.d.ts +1 -1
  85. package/dist/esm/releasePrepare.js +213 -231
  86. package/dist/esm/releasePrepareMono.d.ts +2 -2
  87. package/dist/esm/releasePrepareMono.js +434 -494
  88. package/dist/esm/releasePrepareProject.d.ts +2 -2
  89. package/dist/esm/releasePrepareProject.js +143 -153
  90. package/dist/esm/renderChangelogMarkdown.d.ts +1 -1
  91. package/dist/esm/renderChangelogMarkdown.js +20 -24
  92. package/dist/esm/renderReleaseNotes.d.ts +1 -1
  93. package/dist/esm/renderReleaseNotes.js +50 -55
  94. package/dist/esm/reportPrepare.d.ts +1 -1
  95. package/dist/esm/reportPrepare.js +230 -231
  96. package/dist/esm/resolveCliffConfigPath.js +18 -23
  97. package/dist/esm/resolveCommandTags.d.ts +1 -1
  98. package/dist/esm/resolveCommandTags.js +47 -45
  99. package/dist/esm/resolveReleaseNotesConfig.d.ts +1 -1
  100. package/dist/esm/resolveReleaseNotesConfig.js +39 -43
  101. package/dist/esm/resolveReleaseTags.d.ts +1 -1
  102. package/dist/esm/resolveReleaseTags.js +39 -40
  103. package/dist/esm/runGitCliff.js +27 -30
  104. package/dist/esm/showTagPrefixesCommand.js +48 -70
  105. package/dist/esm/stripEmojiPrefix.js +2 -5
  106. package/dist/esm/stripScope.js +18 -21
  107. package/dist/esm/sync-labels/generateCommand.d.ts +1 -1
  108. package/dist/esm/sync-labels/generateCommand.js +51 -53
  109. package/dist/esm/sync-labels/initCommand.js +46 -48
  110. package/dist/esm/sync-labels/loadSyncLabelsConfig.d.ts +1 -1
  111. package/dist/esm/sync-labels/loadSyncLabelsConfig.js +46 -52
  112. package/dist/esm/sync-labels/presets.d.ts +1 -1
  113. package/dist/esm/sync-labels/presets.js +40 -43
  114. package/dist/esm/sync-labels/resolveLabels.d.ts +1 -1
  115. package/dist/esm/sync-labels/resolveLabels.js +28 -35
  116. package/dist/esm/sync-labels/syncCommand.js +30 -31
  117. package/dist/esm/sync-labels/templates.d.ts +1 -1
  118. package/dist/esm/sync-labels/templates.js +23 -26
  119. package/dist/esm/sync-labels/types.js +1 -0
  120. package/dist/esm/syncWorkTypes.js +83 -84
  121. package/dist/esm/tagCommand.js +12 -14
  122. package/dist/esm/typeGuards.js +4 -8
  123. package/dist/esm/types.js +66 -60
  124. package/dist/esm/validateConfig.d.ts +1 -1
  125. package/dist/esm/validateConfig.js +109 -115
  126. package/dist/esm/validateOnlyExcludesStrandedDependents.d.ts +2 -2
  127. package/dist/esm/validateOnlyExcludesStrandedDependents.js +97 -91
  128. package/dist/esm/validateOverridesCommand.d.ts +2 -2
  129. package/dist/esm/validateOverridesCommand.js +110 -111
  130. package/dist/esm/workTypesData.js +57 -60
  131. package/dist/esm/workTypesUtils.js +16 -21
  132. package/dist/esm/writeReleaseNotesPreviews.js +55 -57
  133. package/package.json +3 -2
  134. package/dist/esm/.cache +0 -1
@@ -1,424 +1,421 @@
1
- import { existsSync, readFileSync } from "node:fs";
2
- import path from "node:path";
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import path from 'node:path';
3
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 };
4
+ const OVERRIDES_FILENAME = '.meta/changelog-overrides.json';
5
+ const VALID_AUDIENCE_VALUES = new Set(['all', 'dev', 'skip']);
6
+ const V1_SUPPORTED_AUDIENCE_VALUES = new Set(['skip']);
7
+ const KNOWN_OVERRIDE_FIELDS = new Set(['audience', 'description', 'body', 'breaking']);
8
+ export function loadChangelogOverrides(path) {
9
+ if (!existsSync(path)) {
10
+ return { overrides: new Map() };
11
+ }
12
+ let content;
13
+ try {
14
+ content = readFileSync(path, 'utf8');
15
+ }
16
+ catch (error) {
17
+ return {
18
+ errors: [`Failed to read override file ${path}: ${error instanceof Error ? error.message : String(error)}`],
19
+ };
20
+ }
21
+ let parsed;
22
+ try {
23
+ parsed = JSON.parse(content);
24
+ }
25
+ catch (error) {
26
+ return {
27
+ errors: [`Failed to parse override file ${path}: ${error instanceof Error ? error.message : String(error)}`],
28
+ };
29
+ }
30
+ const result = validateChangelogOverrides(parsed);
31
+ if (result.errors.length > 0) {
32
+ return { errors: result.errors };
33
+ }
34
+ return { overrides: result.overrides };
33
35
  }
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");
36
+ export function validateChangelogOverrides(raw) {
37
+ const overrides = new Map();
38
+ const errors = [];
39
+ if (!isRecord(raw)) {
40
+ errors.push('Override file: top-level value must be an object keyed by commit hash');
41
+ return { overrides, errors };
42
+ }
43
+ for (const [key, rawEntry] of Object.entries(raw)) {
44
+ if (key === '') {
45
+ errors.push('Override file: empty-string key is not a valid commit hash');
46
+ continue;
47
+ }
48
+ const validated = validateSingleOverride(key, rawEntry, errors);
49
+ if (validated !== undefined) {
50
+ overrides.set(key, validated);
51
+ }
52
+ }
39
53
  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
54
  }
53
55
  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;
56
+ if (!isRecord(rawEntry)) {
57
+ errors.push(`overrides['${key}']: must be an object`);
58
+ return undefined;
59
+ }
60
+ let entryValid = true;
61
+ for (const fieldName of Object.keys(rawEntry)) {
62
+ if (!KNOWN_OVERRIDE_FIELDS.has(fieldName)) {
63
+ errors.push(`overrides['${key}']: unknown field '${fieldName}'`);
64
+ entryValid = false;
65
+ }
66
+ }
67
+ const result = {};
68
+ if (rawEntry.audience !== undefined) {
69
+ const audienceResult = validateAudience(key, rawEntry.audience, errors);
70
+ if (audienceResult === undefined) {
71
+ entryValid = false;
72
+ }
73
+ else {
74
+ result.audience = audienceResult;
75
+ }
76
+ }
77
+ if (rawEntry.description !== undefined) {
78
+ if (typeof rawEntry.description !== 'string') {
79
+ errors.push(`overrides['${key}']: 'description' must be a string`);
80
+ entryValid = false;
81
+ }
82
+ else {
83
+ result.description = rawEntry.description;
84
+ }
85
+ }
86
+ if (rawEntry.body !== undefined) {
87
+ if (typeof rawEntry.body !== 'string') {
88
+ errors.push(`overrides['${key}']: 'body' must be a string`);
89
+ entryValid = false;
90
+ }
91
+ else {
92
+ result.body = rawEntry.body;
93
+ }
94
+ }
95
+ if (rawEntry.breaking !== undefined) {
96
+ if (typeof rawEntry.breaking !== 'boolean') {
97
+ errors.push(`overrides['${key}']: 'breaking' must be a boolean`);
98
+ entryValid = false;
99
+ }
100
+ else {
101
+ result.breaking = rawEntry.breaking;
102
+ }
103
+ }
104
+ if (Object.keys(result).length === 0 && entryValid) {
105
+ errors.push(`overrides['${key}']: at least one override field must be set`);
106
+ return undefined;
107
+ }
108
+ if (!entryValid) {
109
+ return undefined;
110
+ }
111
+ return result;
106
112
  }
107
113
  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";
114
+ if (typeof value !== 'string' || !VALID_AUDIENCE_VALUES.has(value)) {
115
+ errors.push(`overrides['${key}']: 'audience' must be one of 'all' | 'dev' | 'skip'`);
116
+ return undefined;
117
+ }
118
+ if (!V1_SUPPORTED_AUDIENCE_VALUES.has(value)) {
119
+ errors.push(`overrides['${key}']: audience '${value}' is not yet supported; only 'skip' is currently accepted`);
120
+ return undefined;
121
+ }
122
+ return 'skip';
117
123
  }
118
- function formatStaleOverrideKeyWarning(key) {
119
- return `Override key '${key}' did not match any commit hash in the changelog (likely a stale reference)`;
124
+ export function formatStaleOverrideKeyWarning(key) {
125
+ return `Override key '${key}' did not match any commit hash in the changelog (likely a stale reference)`;
120
126
  }
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);
127
+ export function applyChangelogOverrides(entries, overrides) {
128
+ const warnings = [];
129
+ const errors = [];
130
+ const matchedKeys = [];
131
+ if (overrides.size === 0) {
132
+ return { entries: entries.map(cloneEntry), warnings, errors, matchedKeys };
133
+ }
134
+ const allHashes = [];
135
+ for (const entry of entries) {
136
+ for (const section of entry.sections) {
137
+ for (const item of section.items) {
138
+ if (item.hash !== undefined) {
139
+ allHashes.push(item.hash);
140
+ }
141
+ }
142
+ }
143
+ }
144
+ const keyToMatchedHashes = new Map();
145
+ for (const overrideKey of overrides.keys()) {
146
+ const matches = allHashes.filter((hash) => hash.startsWith(overrideKey));
147
+ if (matches.length === 0) {
148
+ continue;
149
+ }
150
+ if (matches.length > 1) {
151
+ errors.push(`Override key '${overrideKey}' is ambiguous: matches multiple commits (${matches.join(', ')}). ` +
152
+ 'Use a longer prefix or the full commit hash.');
153
+ continue;
154
+ }
155
+ keyToMatchedHashes.set(overrideKey, matches);
156
+ matchedKeys.push(overrideKey);
157
+ }
158
+ const hashToOverride = new Map();
159
+ for (const [overrideKey, matchedHashes] of keyToMatchedHashes) {
160
+ const override = overrides.get(overrideKey);
161
+ if (override === undefined)
162
+ continue;
163
+ for (const hash of matchedHashes) {
164
+ hashToOverride.set(hash, override);
134
165
  }
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 };
166
+ }
167
+ const transformedEntries = [];
168
+ for (const entry of entries) {
169
+ const transformedSections = [];
170
+ for (const section of entry.sections) {
171
+ const transformedItems = applyOverridesToItems(section.items, hashToOverride);
172
+ if (transformedItems.length === 0) {
173
+ continue;
174
+ }
175
+ transformedSections.push({ ...section, items: transformedItems });
176
+ }
177
+ transformedEntries.push({ ...entry, sections: transformedSections });
178
+ }
179
+ return { entries: transformedEntries, warnings, errors, matchedKeys };
174
180
  }
175
181
  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;
182
+ const result = [];
183
+ for (const item of items) {
184
+ if (item.hash === undefined) {
185
+ result.push(cloneItem(item));
186
+ continue;
187
+ }
188
+ const override = hashToOverride.get(item.hash);
189
+ if (override === undefined) {
190
+ result.push(cloneItem(item));
191
+ continue;
192
+ }
193
+ if (override.audience === 'skip') {
194
+ continue;
195
+ }
196
+ result.push(applyOverrideToItem(item, override));
197
+ }
198
+ return result;
193
199
  }
194
200
  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;
201
+ const result = { ...item };
202
+ if (override.description !== undefined) {
203
+ result.description = override.description;
204
+ }
205
+ if (override.body !== undefined) {
206
+ result.body = override.body;
207
+ }
208
+ if (override.breaking !== undefined) {
209
+ result.breaking = override.breaking;
210
+ }
211
+ return result;
206
212
  }
207
213
  function cloneItem(item) {
208
- return { ...item };
214
+ return { ...item };
209
215
  }
210
216
  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);
217
+ return {
218
+ ...entry,
219
+ sections: entry.sections.map((section) => ({ ...section, items: section.items.map(cloneItem) })),
220
+ };
218
221
  }
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 };
222
+ export function resolveOverridePath(scopeRoot) {
223
+ return path.posix.join(scopeRoot, OVERRIDES_FILENAME);
240
224
  }
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;
225
+ export function loadOverridesForScopes(scopes) {
226
+ const errors = [];
227
+ let project = new Map();
228
+ const perWorkspace = new Map();
229
+ if (scopes.project !== undefined) {
230
+ const result = loadChangelogOverrides(resolveOverridePath(scopes.project));
231
+ if ('errors' in result) {
232
+ errors.push(...result.errors);
233
+ }
234
+ else {
235
+ project = result.overrides;
236
+ }
237
+ }
238
+ for (const workspacePath of scopes.workspaces ?? []) {
239
+ const result = loadChangelogOverrides(resolveOverridePath(workspacePath));
240
+ if ('errors' in result) {
241
+ errors.push(...result.errors);
242
+ }
243
+ else if (result.overrides.size > 0) {
244
+ perWorkspace.set(workspacePath, result.overrides);
245
+ }
246
+ }
247
+ return { project, perWorkspace, errors };
249
248
  }
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
- };
249
+ export function composeOverrides(rootEntries, workspaceEntries) {
250
+ const composed = new Map(rootEntries);
251
+ if (workspaceEntries !== undefined) {
252
+ for (const [key, value] of workspaceEntries) {
253
+ composed.set(key, value);
254
+ }
255
+ }
256
+ return composed;
265
257
  }
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
258
+ export function createOverrideContext(workspaces) {
259
+ const result = loadOverridesForScopes({
260
+ project: '.',
261
+ workspaces: workspaces.map((workspace) => workspace.workspacePath),
285
262
  });
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 };
263
+ if (result.errors.length > 0) {
264
+ throw new Error(`Failed to load changelog overrides:\n - ${result.errors.join('\n - ')}`);
265
+ }
266
+ return {
267
+ project: result.project,
268
+ perWorkspace: result.perWorkspace,
269
+ overrideWarnings: [],
270
+ globalMatchedRootKeys: new Set(),
271
+ };
272
+ }
273
+ export function validateAllChangelogOverrides(inputs) {
274
+ const errors = [];
275
+ const warnings = [];
276
+ const projectFilePath = inputs.project?.filePath;
277
+ const projectMap = loadScopeMap(projectFilePath, errors);
278
+ const workspaceMaps = (inputs.workspaces ?? []).map((scope) => ({
279
+ filePath: scope.filePath,
280
+ hashes: scope.hashes,
281
+ map: loadScopeMap(scope.filePath, errors),
282
+ }));
283
+ const globalMatchedRootKeys = new Set();
284
+ for (const workspace of workspaceMaps) {
285
+ processWorkspaceScope({
286
+ workspace,
287
+ projectFilePath,
288
+ projectMap,
289
+ errors,
290
+ warnings,
291
+ globalMatchedRootKeys,
292
+ });
293
+ }
294
+ const projectHashes = inputs.project?.hashes;
295
+ if (projectFilePath !== undefined && projectHashes !== undefined) {
296
+ processProjectScope({ projectFilePath, projectMap, projectHashes, errors, globalMatchedRootKeys });
297
+ }
298
+ if (projectFilePath !== undefined) {
299
+ collectRootStaleWarnings(projectFilePath, projectMap, globalMatchedRootKeys, warnings);
300
+ }
301
+ return { errors, warnings };
295
302
  }
296
303
  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
- }
304
+ const { workspace, projectFilePath, projectMap, errors, warnings, globalMatchedRootKeys } = args;
305
+ const { filePath, hashes, map } = workspace;
306
+ const workspaceApplied = applyChangelogOverrides(makeValidationEntries(hashes), map);
307
+ for (const message of workspaceApplied.errors) {
308
+ errors.push(prefixWithFilePath(filePath, message));
309
+ }
310
+ if (projectFilePath !== undefined && projectMap.size > 0) {
311
+ const projectMinusShadowed = filterShadowedKeys(projectMap, map);
312
+ const projectApplied = applyChangelogOverrides(makeValidationEntries(hashes), projectMinusShadowed);
313
+ for (const message of projectApplied.errors) {
314
+ errors.push(prefixWithFilePath(projectFilePath, message));
315
+ }
316
+ }
317
+ for (const key of map.keys()) {
318
+ if (!hasAnyMatch(key, hashes)) {
319
+ warnings.push(formatWorkspaceStaleWarning(filePath, key));
320
+ }
321
+ }
322
+ for (const key of projectMap.keys()) {
323
+ if (map.has(key))
324
+ continue;
325
+ if (hasAnyMatch(key, hashes)) {
326
+ globalMatchedRootKeys.add(key);
327
+ }
328
+ }
321
329
  }
322
330
  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
- }
331
+ const { projectFilePath, projectMap, projectHashes, errors, globalMatchedRootKeys } = args;
332
+ const applied = applyChangelogOverrides(makeValidationEntries(projectHashes), projectMap);
333
+ for (const message of applied.errors) {
334
+ errors.push(prefixWithFilePath(projectFilePath, message));
335
+ }
336
+ for (const key of projectMap.keys()) {
337
+ if (hasAnyMatch(key, projectHashes)) {
338
+ globalMatchedRootKeys.add(key);
339
+ }
340
+ }
333
341
  }
334
342
  function collectRootStaleWarnings(projectFilePath, projectMap, globalMatchedRootKeys, warnings) {
335
- for (const key of projectMap.keys()) {
336
- if (!globalMatchedRootKeys.has(key)) {
337
- warnings.push(formatRootStaleWarning(projectFilePath, key));
343
+ for (const key of projectMap.keys()) {
344
+ if (!globalMatchedRootKeys.has(key)) {
345
+ warnings.push(formatRootStaleWarning(projectFilePath, key));
346
+ }
338
347
  }
339
- }
340
348
  }
341
349
  function hasAnyMatch(key, hashes) {
342
- return hashes.some((hash) => hash.startsWith(key));
350
+ return hashes.some((hash) => hash.startsWith(key));
343
351
  }
344
352
  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;
353
+ const result = new Map();
354
+ for (const [key, value] of projectMap) {
355
+ if (workspaceMap.has(key))
356
+ continue;
357
+ result.set(key, value);
358
+ }
359
+ return result;
351
360
  }
352
361
  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;
362
+ if (filePath === undefined) {
363
+ return new Map();
364
+ }
365
+ const result = loadChangelogOverrides(filePath);
366
+ if ('errors' in result) {
367
+ for (const message of result.errors) {
368
+ errors.push(prefixWithFilePath(filePath, message));
369
+ }
370
+ return new Map();
371
+ }
372
+ return result.overrides;
364
373
  }
365
374
  function makeValidationEntries(hashes) {
366
- return [
367
- {
368
- version: "0.0.0",
369
- date: "0000-00-00",
370
- sections: [
375
+ return [
371
376
  {
372
- title: "Validation",
373
- audience: "all",
374
- items: hashes.map((hash) => ({ description: "", hash }))
375
- }
376
- ]
377
- }
378
- ];
377
+ version: '0.0.0',
378
+ date: '0000-00-00',
379
+ sections: [
380
+ {
381
+ title: 'Validation',
382
+ audience: 'all',
383
+ items: hashes.map((hash) => ({ description: '', hash })),
384
+ },
385
+ ],
386
+ },
387
+ ];
379
388
  }
380
389
  function prefixWithFilePath(filePath, message) {
381
- return `${filePath}: ${message}`;
390
+ return `${filePath}: ${message}`;
382
391
  }
383
392
  function formatWorkspaceStaleWarning(filePath, key) {
384
- return `${filePath}: Override key '${key}' did not match any commit in this workspace's history (likely a stale reference)`;
393
+ return `${filePath}: Override key '${key}' did not match any commit in this workspace's history (likely a stale reference)`;
385
394
  }
386
395
  function formatRootStaleWarning(filePath, key) {
387
- return `${filePath}: Override key '${key}' did not match any commit in any scope (likely a stale reference)`;
396
+ return `${filePath}: Override key '${key}' did not match any commit in any scope (likely a stale reference)`;
388
397
  }
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;
398
+ export function applyWorkspaceOverrides(newEntries, workspacePath, overrideContext) {
399
+ const { project, perWorkspace, overrideWarnings, globalMatchedRootKeys } = overrideContext;
400
+ const workspaceOverrides = perWorkspace.get(workspacePath);
401
+ const composed = composeOverrides(project, workspaceOverrides);
402
+ const applied = applyChangelogOverrides(newEntries, composed);
403
+ if (applied.errors.length > 0) {
404
+ throw new Error(`Changelog override application failed:\n - ${applied.errors.join('\n - ')}`);
405
+ }
406
+ overrideWarnings.push(...applied.warnings);
407
+ const matchedSet = new Set(applied.matchedKeys);
408
+ if (workspaceOverrides !== undefined) {
409
+ for (const key of workspaceOverrides.keys()) {
410
+ if (!matchedSet.has(key)) {
411
+ overrideWarnings.push(formatStaleOverrideKeyWarning(key));
412
+ }
413
+ }
414
+ }
415
+ for (const key of applied.matchedKeys) {
416
+ if (workspaceOverrides?.has(key))
417
+ continue;
418
+ globalMatchedRootKeys.add(key);
419
+ }
420
+ return applied;
412
421
  }
413
- export {
414
- applyChangelogOverrides,
415
- applyWorkspaceOverrides,
416
- composeOverrides,
417
- createOverrideContext,
418
- formatStaleOverrideKeyWarning,
419
- loadChangelogOverrides,
420
- loadOverridesForScopes,
421
- resolveOverridePath,
422
- validateAllChangelogOverrides,
423
- validateChangelogOverrides
424
- };