@williamthorsen/release-kit 15.0.3 → 16.1.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 (146) hide show
  1. package/.meta/changelog.json +93 -0
  2. package/.readyup/kits/default.js +14 -14
  3. package/.readyup/kits/npm-auto-publish.js +4 -4
  4. package/.readyup/manifest.json +13 -13
  5. package/CHANGELOG.md +27 -0
  6. package/README.md +12 -3
  7. package/dist/esm/applyChangelogOverrides.js +6 -6
  8. package/dist/esm/assertReleasesOnNpm.js +11 -11
  9. package/dist/esm/assertTaggedBaseline.js +5 -5
  10. package/dist/esm/assertTarballsComplete.d.ts +9 -0
  11. package/dist/esm/assertTarballsComplete.js +52 -0
  12. package/dist/esm/bin/release-kit.js +16 -16
  13. package/dist/esm/buildChangelogEntries.d.ts +19 -19
  14. package/dist/esm/buildChangelogEntries.js +40 -36
  15. package/dist/esm/buildChangelogItem.js +24 -24
  16. package/dist/esm/buildDependencyGraph.js +23 -23
  17. package/dist/esm/buildReleasedResult.js +21 -19
  18. package/dist/esm/buildSyntheticChangelogEntry.js +2 -2
  19. package/dist/esm/bumpVersion.js +8 -8
  20. package/dist/esm/changelogArchive.d.ts +1 -1
  21. package/dist/esm/changelogArchive.js +2 -2
  22. package/dist/esm/changelogJsonFile.js +5 -5
  23. package/dist/esm/changelogJsonUtils.js +3 -3
  24. package/dist/esm/changelogOverrides.d.ts +5 -5
  25. package/dist/esm/changelogOverrides.js +23 -23
  26. package/dist/esm/classifyChangelogCommit.js +4 -4
  27. package/dist/esm/commitCommand.js +3 -3
  28. package/dist/esm/compareVersions.js +13 -13
  29. package/dist/esm/configSchema.d.ts +3 -2
  30. package/dist/esm/configSchema.js +2 -1
  31. package/dist/esm/createGithubRelease.d.ts +4 -4
  32. package/dist/esm/createGithubRelease.js +10 -10
  33. package/dist/esm/createGithubReleaseCommand.js +9 -9
  34. package/dist/esm/createTags.d.ts +2 -2
  35. package/dist/esm/createTags.js +8 -8
  36. package/dist/esm/decideDirectReleases.d.ts +5 -5
  37. package/dist/esm/decideDirectReleases.js +25 -25
  38. package/dist/esm/decideRelease.d.ts +1 -1
  39. package/dist/esm/decideRelease.js +2 -2
  40. package/dist/esm/deriveDirectoryConfig.d.ts +1 -1
  41. package/dist/esm/deriveDirectoryConfig.js +18 -18
  42. package/dist/esm/deriveWorkspaceConfig.js +4 -4
  43. package/dist/esm/detectPackageManager.d.ts +2 -0
  44. package/dist/esm/detectPackageManager.js +8 -5
  45. package/dist/esm/detectUndeclaredTagPrefixes.js +6 -6
  46. package/dist/esm/enumerateReleaseWindows.d.ts +1 -1
  47. package/dist/esm/enumerateReleaseWindows.js +7 -7
  48. package/dist/esm/findMissingManifestPaths.d.ts +14 -0
  49. package/dist/esm/findMissingManifestPaths.js +90 -0
  50. package/dist/esm/findTransitiveDependents.js +5 -5
  51. package/dist/esm/findUnroutedEntryScopes.js +11 -11
  52. package/dist/esm/format.d.ts +1 -1
  53. package/dist/esm/format.js +1 -1
  54. package/dist/esm/formatPrepareFiles.d.ts +3 -3
  55. package/dist/esm/formatPrepareFiles.js +10 -10
  56. package/dist/esm/formatPrepareWarnings.js +6 -6
  57. package/dist/esm/hasPrettierConfig.js +2 -2
  58. package/dist/esm/init/checks.js +5 -3
  59. package/dist/esm/init/detectRepoType.js +3 -3
  60. package/dist/esm/init/initCommand.d.ts +4 -4
  61. package/dist/esm/init/initCommand.js +7 -7
  62. package/dist/esm/init/parseJsonRecord.d.ts +1 -1
  63. package/dist/esm/init/parseJsonRecord.js +4 -4
  64. package/dist/esm/init/scaffold.d.ts +4 -4
  65. package/dist/esm/init/scaffold.js +15 -15
  66. package/dist/esm/init/templates.d.ts +10 -10
  67. package/dist/esm/init/templates.js +5 -5
  68. package/dist/esm/init/updateTemplatesCommand.d.ts +2 -2
  69. package/dist/esm/init/updateTemplatesCommand.js +14 -12
  70. package/dist/esm/injectReleaseNotesIntoReadme.d.ts +1 -1
  71. package/dist/esm/injectReleaseNotesIntoReadme.js +6 -6
  72. package/dist/esm/injectSection.js +8 -8
  73. package/dist/esm/loadChangelogOverrides.d.ts +1 -1
  74. package/dist/esm/loadChangelogOverrides.js +9 -9
  75. package/dist/esm/loadConfig.d.ts +3 -3
  76. package/dist/esm/loadConfig.js +10 -10
  77. package/dist/esm/loadValidatedConfig.js +4 -4
  78. package/dist/esm/mergeConfig.d.ts +1 -1
  79. package/dist/esm/mergeConfig.js +27 -27
  80. package/dist/esm/monorepoConfigAssertions.js +15 -15
  81. package/dist/esm/npmRegistry.js +4 -4
  82. package/dist/esm/packFromCleanCheckout.d.ts +11 -0
  83. package/dist/esm/packFromCleanCheckout.js +81 -0
  84. package/dist/esm/packsPath.js +3 -3
  85. package/dist/esm/parseChangeRecordBlock.js +33 -33
  86. package/dist/esm/parseCommitMessage.js +5 -5
  87. package/dist/esm/planChangelogFiles.js +8 -8
  88. package/dist/esm/planReleaseNotesPreviews.js +10 -10
  89. package/dist/esm/planVersionBump.js +24 -16
  90. package/dist/esm/prepareArgs.d.ts +9 -9
  91. package/dist/esm/prepareArgs.js +11 -11
  92. package/dist/esm/prepareCommand.js +27 -24
  93. package/dist/esm/prepareComposite.d.ts +4 -4
  94. package/dist/esm/prepareComposite.js +16 -16
  95. package/dist/esm/{releasePrepareTargets.d.ts → prepareReleaseTargets.d.ts} +9 -9
  96. package/dist/esm/{releasePrepareTargets.js → prepareReleaseTargets.js} +40 -40
  97. package/dist/esm/prepareRunContext.d.ts +1 -1
  98. package/dist/esm/prepareRunContext.js +5 -5
  99. package/dist/esm/prepareTarget.d.ts +3 -3
  100. package/dist/esm/prepareTarget.js +41 -39
  101. package/dist/esm/previewTagPrefixes.js +19 -19
  102. package/dist/esm/propagateBumps.js +8 -8
  103. package/dist/esm/publish.d.ts +3 -3
  104. package/dist/esm/publish.js +6 -11
  105. package/dist/esm/publishCommand.d.ts +3 -3
  106. package/dist/esm/publishCommand.js +28 -20
  107. package/dist/esm/pushCommand.js +8 -8
  108. package/dist/esm/pushRelease.d.ts +1 -1
  109. package/dist/esm/pushRelease.js +2 -2
  110. package/dist/esm/readChangelogSections.d.ts +1 -1
  111. package/dist/esm/readChangelogSections.js +16 -16
  112. package/dist/esm/releasePlan.js +25 -25
  113. package/dist/esm/renderChangelogMarkdown.d.ts +4 -4
  114. package/dist/esm/renderChangelogMarkdown.js +18 -15
  115. package/dist/esm/renderReleaseNotes.d.ts +1 -1
  116. package/dist/esm/renderReleaseNotes.js +16 -16
  117. package/dist/esm/reportPrepare.js +34 -34
  118. package/dist/esm/resolveCommandTags.js +9 -9
  119. package/dist/esm/resolveReleaseDeclaration.d.ts +2 -2
  120. package/dist/esm/resolveReleaseDeclaration.js +22 -22
  121. package/dist/esm/resolveReleaseTags.js +17 -15
  122. package/dist/esm/resolveReleaseTargets.js +2 -2
  123. package/dist/esm/showTagPrefixesCommand.js +4 -4
  124. package/dist/esm/sync-labels/generateCommand.d.ts +3 -3
  125. package/dist/esm/sync-labels/generateCommand.js +10 -10
  126. package/dist/esm/sync-labels/initCommand.d.ts +3 -3
  127. package/dist/esm/sync-labels/initCommand.js +15 -15
  128. package/dist/esm/sync-labels/presets.js +3 -3
  129. package/dist/esm/sync-labels/resolveLabels.js +13 -13
  130. package/dist/esm/sync-labels/templates.d.ts +2 -2
  131. package/dist/esm/sync-labels/templates.js +1 -1
  132. package/dist/esm/tagCommand.js +4 -4
  133. package/dist/esm/topologicalSort.d.ts +2 -2
  134. package/dist/esm/topologicalSort.js +7 -7
  135. package/dist/esm/types.d.ts +3 -3
  136. package/dist/esm/validateAllChangelogOverrides.js +9 -9
  137. package/dist/esm/validateConfig.d.ts +1 -1
  138. package/dist/esm/validateConfig.js +60 -50
  139. package/dist/esm/validateOverridesCommand.js +2 -2
  140. package/docs/changelogs.md +5 -5
  141. package/docs/configuration.md +16 -15
  142. package/docs/publishing.md +4 -0
  143. package/docs/releasing.md +6 -0
  144. package/docs/work-types.md +1 -1
  145. package/package.json +2 -2
  146. package/presets/labels/common.yaml +3 -0
@@ -5,12 +5,30 @@ import type { ChangelogEntry, ChangelogSection, ReleaseSettings, ReleaseType } f
5
5
  /**
6
6
  * Builds structured changelog entries from the release windows of git history, naming the unreleased window `tag`.
7
7
  *
8
- * Composes `readReleaseHistory` and `toChangelogEntries` for a caller that knows the tag before it reads.
8
+ * Composes `readReleaseHistory` and `convertToChangelogEntries` for a caller that knows the tag before it reads.
9
9
  */
10
10
  export declare function buildChangelogEntries(config: ReleaseHistoryConfig, tag: string, options: GenerateChangelogOptions): {
11
11
  entries: ChangelogEntry[];
12
12
  diagnostics: ChangelogDiagnostics;
13
13
  };
14
+ /** Labels the unreleased window of `history` with `tag` and returns the entries of every window, newest first. */
15
+ export declare function convertToChangelogEntries(history: ReleaseHistory, tag: string): ChangelogEntry[];
16
+ /** One read of a scope's release windows. */
17
+ export interface ReleaseHistory {
18
+ /** The newest matching tag that HEAD reaches; undefined when none does. */
19
+ previousTag: string | undefined;
20
+ /** Entries of the released windows, newest first; a window that doesn't yield any item contributes none. */
21
+ releasedEntries: ChangelogEntry[];
22
+ unreleasedReading: UnreleasedWindowReading;
23
+ }
24
+ /** The configuration that `readReleaseHistory` reads. */
25
+ export type ReleaseHistoryConfig = Pick<ReleaseSettings, 'breakingPolicies' | 'changelogJson' | 'scopeAliases' | 'versionPatterns' | 'workTypes'>;
26
+ /**
27
+ * Returns the entries that a direct release tagged `tag` records: those of `convertToChangelogEntries`, or, when the
28
+ * unreleased window doesn't yield any item, the synthetic "Forced version bump." entry dated `today` ahead of the
29
+ * released entries.
30
+ */
31
+ export declare function convertToReleaseEntries(history: ReleaseHistory, tag: string, today: string): ChangelogEntry[];
14
32
  /**
15
33
  * Reads a scope's release windows once and returns the changelog items of every window, with what the unreleased
16
34
  * window decides: its commits, its bump, and its diagnostics.
@@ -21,16 +39,6 @@ export declare function buildChangelogEntries(config: ReleaseHistoryConfig, tag:
21
39
  * only for the unreleased window, since the released windows were reported when they were prepared.
22
40
  */
23
41
  export declare function readReleaseHistory(config: ReleaseHistoryConfig, options: GenerateChangelogOptions): ReleaseHistory;
24
- /** One read of a scope's release windows. */
25
- export interface ReleaseHistory {
26
- /** The newest matching tag that HEAD reaches; undefined when none does. */
27
- previousTag: string | undefined;
28
- /** Entries of the released windows, newest first; a window that doesn't yield any item contributes none. */
29
- releasedEntries: ChangelogEntry[];
30
- unreleased: UnreleasedWindowReading;
31
- }
32
- /** The configuration that `readReleaseHistory` reads. */
33
- export type ReleaseHistoryConfig = Pick<ReleaseSettings, 'breakingPolicies' | 'changelogJson' | 'scopeAliases' | 'versionPatterns' | 'workTypes'>;
34
42
  /**
35
43
  * Strips a section title down to its bare name.
36
44
  *
@@ -39,14 +47,6 @@ export type ReleaseHistoryConfig = Pick<ReleaseSettings, 'breakingPolicies' | 'c
39
47
  * through this helper lets the two forms match.
40
48
  */
41
49
  export declare function stripGroupDecorations(group: string): string;
42
- /** Labels the unreleased window of `history` with `tag` and returns the entries of every window, newest first. */
43
- export declare function toChangelogEntries(history: ReleaseHistory, tag: string): ChangelogEntry[];
44
- /**
45
- * Returns the entries that a direct release tagged `tag` records: those of `toChangelogEntries`, or, when the
46
- * unreleased window doesn't yield any item, the synthetic "Forced version bump." entry dated `today` ahead of the
47
- * released entries.
48
- */
49
- export declare function toReleaseEntries(history: ReleaseHistory, tag: string, today: string): ChangelogEntry[];
50
50
  /** The unreleased window: its changelog sections and commits, and the bump and diagnostics that they determine. */
51
51
  export interface UnreleasedWindowReading {
52
52
  /** The highest bump that the window's items call for; undefined when the window doesn't yield any item. */
@@ -12,7 +12,23 @@ const UNRELEASED_TAG = 'unreleased';
12
12
  const CANONICAL_SECTION_ORDER = new Map(Object.values(DEFAULT_WORK_TYPES).map((config, index) => [stripGroupDecorations(config.header), index]));
13
13
  export function buildChangelogEntries(config, tag, options) {
14
14
  const history = readReleaseHistory(config, options);
15
- return { entries: toChangelogEntries(history, tag), diagnostics: history.unreleased.diagnostics };
15
+ return { entries: convertToChangelogEntries(history, tag), diagnostics: history.unreleasedReading.diagnostics };
16
+ }
17
+ export function convertToChangelogEntries(history, tag) {
18
+ const { unreleasedReading } = history;
19
+ if (unreleasedReading.sections.length === 0) {
20
+ return [...history.releasedEntries];
21
+ }
22
+ return [
23
+ { version: extractVersion(tag), date: unreleasedReading.date, sections: unreleasedReading.sections },
24
+ ...history.releasedEntries,
25
+ ];
26
+ }
27
+ export function convertToReleaseEntries(history, tag, today) {
28
+ if (history.unreleasedReading.sections.length === 0) {
29
+ return [buildEmptyReleaseEntry(extractVersion(tag), today), ...history.releasedEntries];
30
+ }
31
+ return convertToChangelogEntries(history, tag);
16
32
  }
17
33
  export function readReleaseHistory(config, options) {
18
34
  try {
@@ -39,22 +55,6 @@ export function readReleaseHistory(config, options) {
39
55
  export function stripGroupDecorations(group) {
40
56
  return stripEmojiPrefix(group);
41
57
  }
42
- export function toChangelogEntries(history, tag) {
43
- const { unreleased } = history;
44
- if (unreleased.sections.length === 0) {
45
- return [...history.releasedEntries];
46
- }
47
- return [
48
- { version: extractVersion(tag), date: unreleased.date, sections: unreleased.sections },
49
- ...history.releasedEntries,
50
- ];
51
- }
52
- export function toReleaseEntries(history, tag, today) {
53
- if (history.unreleased.sections.length === 0) {
54
- return [buildEmptyReleaseEntry(extractVersion(tag), today), ...history.releasedEntries];
55
- }
56
- return toChangelogEntries(history, tag);
57
- }
58
58
  function appendItem(sectionMap, header, item) {
59
59
  let items = sectionMap.get(header);
60
60
  if (items === undefined) {
@@ -72,15 +72,15 @@ function buildSections(sectionMap, devOnlySections) {
72
72
  items,
73
73
  });
74
74
  }
75
- return sections.toSorted((a, b) => canonicalSectionPriority(a.title) - canonicalSectionPriority(b.title));
75
+ return sections.toSorted((a, b) => getCanonicalSectionPriority(a.title) - getCanonicalSectionPriority(b.title));
76
76
  }
77
- function canonicalSectionPriority(title) {
77
+ function formatDate(timestampSec) {
78
+ return new Date(timestampSec * 1000).toISOString().slice(0, 10);
79
+ }
80
+ function getCanonicalSectionPriority(title) {
78
81
  const index = CANONICAL_SECTION_ORDER.get(stripGroupDecorations(title));
79
82
  return index ?? Infinity;
80
83
  }
81
- function formatDate(timestamp) {
82
- return new Date(timestamp * 1_000).toISOString().slice(0, 10);
83
- }
84
84
  function readCommit(commit, context, diagnostics) {
85
85
  if (isNonChangeSubject(commit.subject)) {
86
86
  return { items: [], isUnparseable: false };
@@ -100,10 +100,10 @@ function readCommit(commit, context, diagnostics) {
100
100
  const classification = classifyChangelogCommit(commit, context.workTypes, {
101
101
  breakingPolicies: context.breakingPolicies,
102
102
  ...(diagnostics !== undefined && {
103
- onPolicyViolation: (violating, type, surface) => {
103
+ onPolicyViolation: (violatingCommit, type, surface) => {
104
104
  diagnostics.policyViolations.push({
105
- commitHash: violating.hash,
106
- commitSubject: violating.subject,
105
+ commitHash: violatingCommit.hash,
106
+ commitSubject: violatingCommit.subject,
107
107
  type,
108
108
  surface,
109
109
  });
@@ -130,47 +130,51 @@ function transformReleases(windows, context) {
130
130
  unroutedEntryScopes: [],
131
131
  };
132
132
  const signals = [];
133
- const unparseable = [];
133
+ const unparseableCommits = [];
134
134
  let parsedCommitCount = 0;
135
135
  const sectionMap = new Map();
136
136
  const unreleasedCommits = unreleasedWindow?.commits ?? [];
137
137
  for (const commit of unreleasedCommits) {
138
138
  const reading = readCommit(commit, context, diagnostics);
139
- for (const derived of reading.items) {
140
- appendItem(sectionMap, derived.header, derived.item);
141
- signals.push(derived.signal);
139
+ for (const derivedItem of reading.items) {
140
+ appendItem(sectionMap, derivedItem.header, derivedItem.item);
141
+ signals.push(derivedItem.signal);
142
142
  }
143
143
  if (reading.items.length > 0) {
144
144
  parsedCommitCount += 1;
145
145
  }
146
146
  else if (reading.isUnparseable) {
147
- unparseable.push(commit);
147
+ unparseableCommits.push(commit);
148
148
  }
149
149
  }
150
150
  const releasedEntries = [];
151
151
  for (const release of windows.slice(1)) {
152
152
  const releaseSections = new Map();
153
153
  for (const commit of release.commits) {
154
- for (const derived of readCommit(commit, context, undefined).items) {
155
- appendItem(releaseSections, derived.header, derived.item);
154
+ for (const derivedItem of readCommit(commit, context, undefined).items) {
155
+ appendItem(releaseSections, derivedItem.header, derivedItem.item);
156
156
  }
157
157
  }
158
158
  const sections = buildSections(releaseSections, context.devOnlySections);
159
159
  if (sections.length > 0) {
160
- releasedEntries.push({ version: extractVersion(release.version), date: formatDate(release.timestamp), sections });
160
+ releasedEntries.push({
161
+ version: extractVersion(release.version),
162
+ date: formatDate(release.timestampSec),
163
+ sections,
164
+ });
161
165
  }
162
166
  }
163
167
  return {
164
168
  previousTag: baselineWindow?.version,
165
169
  releasedEntries,
166
- unreleased: {
170
+ unreleasedReading: {
167
171
  bump: determineBumpType(signals, context.workTypes, context.versionPatterns),
168
172
  commits: unreleasedCommits.filter((commit) => !isReleaseSubject(commit.subject)).toReversed(),
169
- date: formatDate(unreleasedWindow?.timestamp ?? Math.floor(Date.now() / 1_000)),
173
+ date: formatDate(unreleasedWindow?.timestampSec ?? Math.floor(Date.now() / 1000)),
170
174
  diagnostics,
171
175
  parsedCommitCount,
172
176
  sections: buildSections(sectionMap, context.devOnlySections),
173
- unparseableCommits: unparseable.length > 0 ? unparseable.toReversed() : undefined,
177
+ unparseableCommits: unparseableCommits.length > 0 ? unparseableCommits.toReversed() : undefined,
174
178
  },
175
179
  };
176
180
  }
@@ -36,10 +36,10 @@ export function buildEntryItem(commit, entry, position, prNumber, context, diagn
36
36
  prefixSurface: 'entry',
37
37
  onPolicyViolation: diagnostics === undefined
38
38
  ? undefined
39
- : (violating, violatedType, surface) => {
39
+ : (violatingCommit, violatedType, surface) => {
40
40
  diagnostics.policyViolations.push({
41
- commitHash: violating.hash,
42
- commitSubject: violating.subject,
41
+ commitHash: violatingCommit.hash,
42
+ commitSubject: violatingCommit.subject,
43
43
  type: violatedType,
44
44
  surface,
45
45
  entryPosition: position,
@@ -65,7 +65,7 @@ export function buildTitleItem(commit, isParsedBreaking, workTypes) {
65
65
  if (body !== undefined) {
66
66
  item.body = body;
67
67
  }
68
- if (isParsedBreaking && subjectHasBreakingMarker(commit.message, workTypes)) {
68
+ if (isParsedBreaking && hasBreakingMarkerInSubject(commit.message, workTypes)) {
69
69
  item.breaking = true;
70
70
  }
71
71
  const migration = extractMigration(body);
@@ -80,43 +80,43 @@ export function hasRoutedEntry(entries, routing) {
80
80
  }
81
81
  function extractBody(message) {
82
82
  const lines = message.split('\n').slice(1);
83
- let start = 0;
84
- while (start < lines.length && (lines[start] ?? '').trim() === '') {
85
- start += 1;
83
+ let startIndex = 0;
84
+ while (startIndex < lines.length && (lines[startIndex] ?? '').trim() === '') {
85
+ startIndex += 1;
86
86
  }
87
- let end = lines.length;
88
- while (end > start) {
89
- const line = lines[end - 1] ?? '';
90
- const trimmed = line.trim();
91
- if (trimmed === '') {
92
- end -= 1;
87
+ let endIndex = lines.length;
88
+ while (endIndex > startIndex) {
89
+ const line = lines[endIndex - 1] ?? '';
90
+ const trimmedLine = line.trim();
91
+ if (trimmedLine === '') {
92
+ endIndex -= 1;
93
93
  continue;
94
94
  }
95
- if (TRAILER_PATTERNS.some((pattern) => pattern.test(trimmed))) {
96
- end -= 1;
95
+ if (TRAILER_PATTERNS.some((pattern) => pattern.test(trimmedLine))) {
96
+ endIndex -= 1;
97
97
  continue;
98
98
  }
99
99
  break;
100
100
  }
101
- if (end <= start) {
101
+ if (endIndex <= startIndex) {
102
102
  return undefined;
103
103
  }
104
- return lines.slice(start, end).join('\n').trim();
104
+ return lines.slice(startIndex, endIndex).join('\n').trim();
105
105
  }
106
106
  function extractDescription(message) {
107
107
  const firstLine = message.split('\n', 1)[0] ?? message;
108
- const afterColon = firstLine.split(': ').slice(1).join(': ');
109
- return afterColon.charAt(0).toUpperCase() + afterColon.slice(1);
108
+ const descriptionText = firstLine.split(': ').slice(1).join(': ');
109
+ return descriptionText.charAt(0).toUpperCase() + descriptionText.slice(1);
110
+ }
111
+ function hasBreakingMarkerInSubject(message, workTypes) {
112
+ return parseSubject(message.split('\n', 1)[0] ?? '', workTypes)?.breaking === true;
110
113
  }
111
114
  function isRoutedTo(scopes, routing) {
112
115
  if (scopes.length === 0) {
113
116
  return true;
114
117
  }
115
118
  return scopes.some((scope) => {
116
- const resolved = routing.scopeAliases[scope] ?? scope;
117
- return resolved === '*' || resolved === routing.scope;
119
+ const resolvedScope = routing.scopeAliases[scope] ?? scope;
120
+ return resolvedScope === '*' || resolvedScope === routing.scope;
118
121
  });
119
122
  }
120
- function subjectHasBreakingMarker(message, workTypes) {
121
- return parseSubject(message.split('\n', 1)[0] ?? '', workTypes)?.breaking === true;
122
- }
@@ -15,36 +15,36 @@ export function buildDependencyGraph(targets) {
15
15
  if (primaryPackageFile === undefined) {
16
16
  continue;
17
17
  }
18
- const pkg = readPackageJsonSubset(primaryPackageFile);
19
- targetPackages.set(target, pkg);
20
- if (typeof pkg.version === 'string') {
21
- dirToVersion.set(target.id, pkg.version);
18
+ const packageJson = readPackageJsonSubset(primaryPackageFile);
19
+ targetPackages.set(target, packageJson);
20
+ if (typeof packageJson.version === 'string') {
21
+ dirToVersion.set(target.id, packageJson.version);
22
22
  }
23
- if (pkg.name === undefined) {
23
+ if (packageJson.name === undefined) {
24
24
  continue;
25
25
  }
26
- packageNameToDir.set(pkg.name, target.id);
27
- dirToPackageName.set(target.id, pkg.name);
26
+ packageNameToDir.set(packageJson.name, target.id);
27
+ dirToPackageName.set(target.id, packageJson.name);
28
28
  }
29
- for (const [target, pkg] of targetPackages) {
30
- const allDeps = { ...pkg.dependencies, ...pkg.peerDependencies };
31
- for (const [depName, depVersion] of Object.entries(allDeps)) {
32
- if (typeof depVersion !== 'string' || !depVersion.startsWith('workspace:')) {
29
+ for (const [target, packageJson] of targetPackages) {
30
+ const allDependencies = { ...packageJson.dependencies, ...packageJson.peerDependencies };
31
+ for (const [dependencyName, dependencyVersion] of Object.entries(allDependencies)) {
32
+ if (typeof dependencyVersion !== 'string' || !dependencyVersion.startsWith('workspace:')) {
33
33
  continue;
34
34
  }
35
- const existing = dependentsOf.get(depName);
36
- if (existing === undefined) {
37
- dependentsOf.set(depName, [target]);
35
+ const existingDependents = dependentsOf.get(dependencyName);
36
+ if (existingDependents === undefined) {
37
+ dependentsOf.set(dependencyName, [target]);
38
38
  }
39
39
  else {
40
- existing.push(target);
40
+ existingDependents.push(target);
41
41
  }
42
- const forward = dependenciesOf.get(target.id);
43
- if (forward === undefined) {
44
- dependenciesOf.set(target.id, new Set([depName]));
42
+ const forwardDependencies = dependenciesOf.get(target.id);
43
+ if (forwardDependencies === undefined) {
44
+ dependenciesOf.set(target.id, new Set([dependencyName]));
45
45
  }
46
46
  else {
47
- forward.add(depName);
47
+ forwardDependencies.add(dependencyName);
48
48
  }
49
49
  }
50
50
  }
@@ -58,15 +58,15 @@ function readPackageJsonSubset(filePath) {
58
58
  catch (error) {
59
59
  throw chainError(`Failed to read ${filePath}`, error);
60
60
  }
61
- let parsed;
61
+ let parsedJson;
62
62
  try {
63
- parsed = JSON.parse(content);
63
+ parsedJson = JSON.parse(content);
64
64
  }
65
65
  catch (error) {
66
66
  throw chainError(`Failed to parse JSON in ${filePath}`, error);
67
67
  }
68
- if (!isPackageJsonSubset(parsed)) {
68
+ if (!isPackageJsonSubset(parsedJson)) {
69
69
  throw new Error(`Invalid package.json at ${filePath}`);
70
70
  }
71
- return parsed;
71
+ return parsedJson;
72
72
  }
@@ -17,62 +17,64 @@ export function buildReleasedResult(target, fields, release, decision, history)
17
17
  }
18
18
  }
19
19
  function buildReleasedComposite(fields, release, decision, history) {
20
- const { unreleased } = history;
20
+ const { unreleasedReading } = history;
21
21
  const result = {
22
22
  ...fields,
23
23
  status: 'released',
24
24
  kind: 'composite',
25
- parsedCommitCount: unreleased.parsedCommitCount,
25
+ parsedCommitCount: unreleasedReading.parsedCommitCount,
26
26
  releaseType: release.releaseType,
27
- commits: unreleased.commits,
28
- ...(unreleased.unparseableCommits !== undefined && { unparseableCommits: unreleased.unparseableCommits }),
27
+ commits: unreleasedReading.commits,
28
+ ...(unreleasedReading.unparseableCommits !== undefined && {
29
+ unparseableCommits: unreleasedReading.unparseableCommits,
30
+ }),
29
31
  ...(decision?.bumpOverride !== undefined && { bumpOverride: decision.bumpOverride }),
30
32
  };
31
- attachChangelogDiagnostics(result, unreleased.diagnostics);
33
+ attachChangelogDiagnostics(result, unreleasedReading.diagnostics);
32
34
  return result;
33
35
  }
34
36
  function buildReleasedDirectory(target, fields, release, decision, history) {
35
- const { unreleased } = history;
37
+ const { unreleasedReading } = history;
36
38
  const setVersion = decision?.setVersion;
37
39
  const result = {
38
40
  ...fields,
39
41
  status: 'released',
40
42
  kind: 'directory',
41
43
  name: target.id,
42
- commits: unreleased.commits,
44
+ commits: unreleasedReading.commits,
43
45
  ...(setVersion === undefined && {
44
46
  releaseType: release.releaseType,
45
- parsedCommitCount: unreleased.parsedCommitCount,
47
+ parsedCommitCount: unreleasedReading.parsedCommitCount,
46
48
  }),
47
49
  ...(decision?.bumpOverride !== undefined && { bumpOverride: decision.bumpOverride }),
48
- ...(setVersion !== undefined && { setVersion }),
50
+ ...(setVersion !== undefined && { versionOverride: setVersion }),
49
51
  };
50
- if (setVersion === undefined && unreleased.unparseableCommits !== undefined) {
51
- result.unparseableCommits = unreleased.unparseableCommits;
52
+ if (setVersion === undefined && unreleasedReading.unparseableCommits !== undefined) {
53
+ result.unparseableCommits = unreleasedReading.unparseableCommits;
52
54
  }
53
- attachChangelogDiagnostics(result, unreleased.diagnostics);
55
+ attachChangelogDiagnostics(result, unreleasedReading.diagnostics);
54
56
  return result;
55
57
  }
56
58
  function buildReleasedPackage(target, fields, release, decision, history) {
57
- const { unreleased } = history;
59
+ const { unreleasedReading } = history;
58
60
  const setVersion = decision?.setVersion;
59
61
  const hasParseCounts = decision !== undefined && setVersion === undefined;
60
62
  const result = {
61
63
  ...fields,
62
64
  status: 'released',
63
65
  kind: 'package',
64
- commits: unreleased.commits,
66
+ commits: unreleasedReading.commits,
65
67
  ...(target.isWorkspace && { name: target.id }),
66
68
  ...(setVersion === undefined && { releaseType: release.releaseType }),
67
- ...(hasParseCounts && { parsedCommitCount: unreleased.parsedCommitCount }),
69
+ ...(hasParseCounts && { parsedCommitCount: unreleasedReading.parsedCommitCount }),
68
70
  ...(decision === undefined && { propagatedOnly: true }),
69
71
  ...(release.propagatedFrom !== undefined && { propagatedFrom: release.propagatedFrom }),
70
72
  ...(decision?.bumpOverride !== undefined && { bumpOverride: decision.bumpOverride }),
71
- ...(setVersion !== undefined && { setVersion }),
73
+ ...(setVersion !== undefined && { versionOverride: setVersion }),
72
74
  };
73
- if (setVersion === undefined && unreleased.unparseableCommits !== undefined) {
74
- result.unparseableCommits = unreleased.unparseableCommits;
75
+ if (setVersion === undefined && unreleasedReading.unparseableCommits !== undefined) {
76
+ result.unparseableCommits = unreleasedReading.unparseableCommits;
75
77
  }
76
- attachChangelogDiagnostics(result, unreleased.diagnostics);
78
+ attachChangelogDiagnostics(result, unreleasedReading.diagnostics);
77
79
  return result;
78
80
  }
@@ -1,6 +1,6 @@
1
1
  export function buildSyntheticChangelogEntry(propagatedFrom, version, date, sectionTitle) {
2
- const items = propagatedFrom.map((dep) => ({
3
- description: `Bumped \`${dep.packageName}\` to ${dep.newVersion}`,
2
+ const items = propagatedFrom.map((dependency) => ({
3
+ description: `Bumped \`${dependency.packageName}\` to ${dependency.newVersion}`,
4
4
  }));
5
5
  return {
6
6
  version,
@@ -9,18 +9,18 @@ export function bumpVersion(version, releaseType) {
9
9
  if (major === undefined || minor === undefined || patch === undefined) {
10
10
  throw new Error(`Invalid semver version: '${version}'`);
11
11
  }
12
- const majorNum = Number.parseInt(major, 10);
13
- const minorNum = Number.parseInt(minor, 10);
14
- const patchNum = Number.parseInt(patch, 10);
12
+ const majorNumber = Number.parseInt(major, 10);
13
+ const minorNumber = Number.parseInt(minor, 10);
14
+ const patchNumber = Number.parseInt(patch, 10);
15
15
  switch (releaseType) {
16
16
  case 'major':
17
- if (majorNum === 0) {
18
- return `0.${minorNum + 1}.0`;
17
+ if (majorNumber === 0) {
18
+ return `0.${minorNumber + 1}.0`;
19
19
  }
20
- return `${majorNum + 1}.0.0`;
20
+ return `${majorNumber + 1}.0.0`;
21
21
  case 'minor':
22
- return `${majorNum}.${minorNum + 1}.0`;
22
+ return `${majorNumber}.${minorNumber + 1}.0`;
23
23
  case 'patch':
24
- return `${majorNum}.${minorNum}.${patchNum + 1}`;
24
+ return `${majorNumber}.${minorNumber}.${patchNumber + 1}`;
25
25
  }
26
26
  }
@@ -2,7 +2,7 @@
2
2
  export declare const CHANGELOG_ARCHIVE_DIRECTORY = "changelogs";
3
3
  /** An archive file that exists on disk. */
4
4
  export interface ChangelogArchivePath {
5
- major: number;
5
+ majorVersion: number;
6
6
  path: string;
7
7
  }
8
8
  /** Returns the path, relative to the changelog directory, of the archive file for a major version. */
@@ -13,9 +13,9 @@ export function listArchiveFiles(changelogDir) {
13
13
  for (const name of readdirSync(archiveDir)) {
14
14
  const match = ARCHIVE_FILE_PATTERN.exec(name);
15
15
  if (match?.[1] !== undefined) {
16
- archives.push({ major: Number(match[1]), path: join(archiveDir, name) });
16
+ archives.push({ majorVersion: Number(match[1]), path: join(archiveDir, name) });
17
17
  }
18
18
  }
19
- return archives.toSorted((a, b) => b.major - a.major);
19
+ return archives.toSorted((a, b) => b.majorVersion - a.majorVersion);
20
20
  }
21
21
  const ARCHIVE_FILE_PATTERN = /^CHANGELOG-v(\d+)\.md$/;
@@ -12,8 +12,8 @@ export function renderChangelogJson(entries) {
12
12
  return stringify(sortNewestFirst(entries), { maxLength: 100 }) + '\n';
13
13
  }
14
14
  export function mergeChangelogEntriesWithDisk(filePath, entries) {
15
- const existing = readExistingEntries(filePath);
16
- return mergeEntries(entries, existing);
15
+ const existingEntries = readExistingEntries(filePath);
16
+ return mergeEntries(entries, existingEntries);
17
17
  }
18
18
  function sortNewestFirst(entries) {
19
19
  return [...entries].toSorted((a, b) => compareVersionsDescending(a.version, b.version));
@@ -24,11 +24,11 @@ function readExistingEntries(filePath) {
24
24
  }
25
25
  try {
26
26
  const content = readFileSync(filePath, 'utf8');
27
- const parsed = JSON.parse(content);
28
- if (!isUnknownArray(parsed)) {
27
+ const parsedJson = JSON.parse(content);
28
+ if (!isUnknownArray(parsedJson)) {
29
29
  return [];
30
30
  }
31
- return parsed.filter(isChangelogEntry);
31
+ return parsedJson.filter(isChangelogEntry);
32
32
  }
33
33
  catch (error) {
34
34
  console.warn(`Warning: could not parse existing ${filePath}: ${describeError(error)}; treating as empty`);
@@ -16,11 +16,11 @@ export function readChangelogEntries(filePath) {
16
16
  }
17
17
  try {
18
18
  const content = readFileSync(filePath, 'utf8');
19
- const parsed = JSON.parse(content);
20
- if (!isUnknownArray(parsed)) {
19
+ const parsedJson = JSON.parse(content);
20
+ if (!isUnknownArray(parsedJson)) {
21
21
  return undefined;
22
22
  }
23
- return parsed.filter(isChangelogEntry);
23
+ return parsedJson.filter(isChangelogEntry);
24
24
  }
25
25
  catch {
26
26
  return undefined;
@@ -31,15 +31,15 @@ export declare function createOverrideContext(workspacePaths: readonly string[])
31
31
  * yields an empty map.
32
32
  */
33
33
  export declare function loadOverridesForScopes(scopes: {
34
- project?: string;
34
+ projectPath?: string;
35
35
  workspaces?: string[];
36
36
  }): LoadOverridesForScopesResult;
37
37
  /** Result of {@link loadOverridesForScopes}: per-scope maps plus accumulated load/validation errors. */
38
38
  export interface LoadOverridesForScopesResult {
39
39
  /** Project-tier (root) overrides. Empty map when the project file is absent. */
40
- project: Map<string, ChangelogOverride>;
40
+ projectOverrides: Map<string, ChangelogOverride>;
41
41
  /** Workspace-tier overrides keyed by `workspacePath` (e.g., `'packages/foo'`). Empty map when absent. */
42
- perWorkspace: Map<string, Map<string, ChangelogOverride>>;
42
+ overridesByWorkspace: Map<string, Map<string, ChangelogOverride>>;
43
43
  /** All load and validation errors across every requested scope, prefixed with the offending file path. */
44
44
  errors: string[];
45
45
  }
@@ -50,8 +50,8 @@ export interface LoadOverridesForScopesResult {
50
50
  * that matches nothing in its own workspace is stale, and it is warned about at once rather than at the end of the run.
51
51
  */
52
52
  export interface OverrideContext {
53
- project: Map<string, ChangelogOverride>;
54
- perWorkspace: Map<string, Map<string, ChangelogOverride>>;
53
+ projectOverrides: Map<string, ChangelogOverride>;
54
+ overridesByWorkspace: Map<string, Map<string, ChangelogOverride>>;
55
55
  overrideWarnings: string[];
56
56
  globalMatchedRootKeys: Set<string>;
57
57
  }