@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,137 +1,136 @@
1
- import { formatErrorLine } from "@williamthorsen/nmr-core";
1
+ import { formatErrorLine } from '@williamthorsen/nmr-core';
2
2
  import { buildChangelogEntries } from "./buildChangelogEntries.js";
3
- import {
4
- resolveOverridePath,
5
- validateAllChangelogOverrides
6
- } from "./changelogOverrides.js";
3
+ import { resolveOverridePath, validateAllChangelogOverrides, } from "./changelogOverrides.js";
7
4
  import { discoverWorkspaces } from "./discoverWorkspaces.js";
8
5
  import { buildTagPattern, getAllTagPrefixes } from "./generateChangelogs.js";
9
6
  import { loadConfig, mergeMonorepoConfig, mergeSinglePackageConfig, readRootPackageVersion } from "./loadConfig.js";
10
7
  import { validateConfig } from "./validateConfig.js";
11
- const SYNTHETIC_VALIDATE_TAG = "validate-only";
12
- async function validateOverridesCommand(dependencies = {}) {
13
- const discover = dependencies.discoverWorkspaces ?? discoverWorkspaces;
14
- const load = dependencies.loadConfig ?? loadConfig;
15
- const buildEntries = dependencies.buildEntries ?? defaultBuildEntries;
16
- const validate = dependencies.validate ?? validateAllChangelogOverrides;
17
- let rawConfig;
18
- try {
19
- rawConfig = await load();
20
- } catch (error) {
21
- return { exitCode: 2, message: formatErrorLine(`Failed to load config: ${errorMessage(error)}`) };
22
- }
23
- let userConfig;
24
- try {
25
- userConfig = validateLoadedConfig(rawConfig);
26
- } catch (error) {
27
- return { exitCode: 2, message: errorMessage(error) };
28
- }
29
- let discoveredPaths;
30
- try {
31
- discoveredPaths = await discover();
32
- } catch (error) {
33
- return { exitCode: 2, message: formatErrorLine(`Failed to discover workspaces: ${errorMessage(error)}`) };
34
- }
35
- let inputs;
36
- try {
37
- inputs = discoveredPaths === void 0 ? buildSinglePackageInputs(userConfig, buildEntries) : buildMonorepoInputs(discoveredPaths, userConfig, buildEntries);
38
- } catch (error) {
39
- return { exitCode: 2, message: formatErrorLine(`Failed to resolve overrides scope: ${errorMessage(error)}`) };
40
- }
41
- const result = validate(inputs);
42
- return formatValidateOverridesResult(result);
8
+ const SYNTHETIC_VALIDATE_TAG = 'validate-only';
9
+ export async function validateOverridesCommand(dependencies = {}) {
10
+ const discover = dependencies.discoverWorkspaces ?? discoverWorkspaces;
11
+ const load = dependencies.loadConfig ?? loadConfig;
12
+ const buildEntries = dependencies.buildEntries ?? defaultBuildEntries;
13
+ const validate = dependencies.validate ?? validateAllChangelogOverrides;
14
+ let rawConfig;
15
+ try {
16
+ rawConfig = await load();
17
+ }
18
+ catch (error) {
19
+ return { exitCode: 2, message: formatErrorLine(`Failed to load config: ${errorMessage(error)}`) };
20
+ }
21
+ let userConfig;
22
+ try {
23
+ userConfig = validateLoadedConfig(rawConfig);
24
+ }
25
+ catch (error) {
26
+ return { exitCode: 2, message: errorMessage(error) };
27
+ }
28
+ let discoveredPaths;
29
+ try {
30
+ discoveredPaths = await discover();
31
+ }
32
+ catch (error) {
33
+ return { exitCode: 2, message: formatErrorLine(`Failed to discover workspaces: ${errorMessage(error)}`) };
34
+ }
35
+ let inputs;
36
+ try {
37
+ inputs =
38
+ discoveredPaths === undefined
39
+ ? buildSinglePackageInputs(userConfig, buildEntries)
40
+ : buildMonorepoInputs(discoveredPaths, userConfig, buildEntries);
41
+ }
42
+ catch (error) {
43
+ return { exitCode: 2, message: formatErrorLine(`Failed to resolve overrides scope: ${errorMessage(error)}`) };
44
+ }
45
+ const result = validate(inputs);
46
+ return formatValidateOverridesResult(result);
43
47
  }
44
- function formatValidateOverridesResult(result) {
45
- const { errors, warnings } = result;
46
- if (errors.length === 0 && warnings.length === 0) {
47
- return { exitCode: 0, message: "All override files are valid (no errors, no stale keys)." };
48
- }
49
- const exitCode = errors.length > 0 ? 2 : 1;
50
- const summary = formatSummaryLine(errors.length, warnings.length);
51
- const errorLines = errors.map((message2) => ` \u274C ${message2}`);
52
- const warningLines = warnings.map((message2) => ` \u26A0\uFE0F ${message2}`);
53
- const message = [summary, "", ...errorLines, ...warningLines].join("\n");
54
- return { exitCode, message };
48
+ export function formatValidateOverridesResult(result) {
49
+ const { errors, warnings } = result;
50
+ if (errors.length === 0 && warnings.length === 0) {
51
+ return { exitCode: 0, message: 'All override files are valid (no errors, no stale keys).' };
52
+ }
53
+ const exitCode = errors.length > 0 ? 2 : 1;
54
+ const summary = formatSummaryLine(errors.length, warnings.length);
55
+ const errorLines = errors.map((message) => ` ❌ ${message}`);
56
+ const warningLines = warnings.map((message) => ` ⚠️ ${message}`);
57
+ const message = [summary, '', ...errorLines, ...warningLines].join('\n');
58
+ return { exitCode, message };
55
59
  }
56
60
  function formatSummaryLine(errorCount, warningCount) {
57
- const parts = [];
58
- if (errorCount > 0) {
59
- parts.push(pluralize(errorCount, "error"));
60
- }
61
- if (warningCount > 0) {
62
- parts.push(pluralize(warningCount, "warning"));
63
- }
64
- return `Found ${parts.join(" and ")}:`;
61
+ const parts = [];
62
+ if (errorCount > 0) {
63
+ parts.push(pluralize(errorCount, 'error'));
64
+ }
65
+ if (warningCount > 0) {
66
+ parts.push(pluralize(warningCount, 'warning'));
67
+ }
68
+ return `Found ${parts.join(' and ')}:`;
65
69
  }
66
70
  function pluralize(count, noun) {
67
- return count === 1 ? `${count} ${noun}` : `${count} ${noun}s`;
71
+ return count === 1 ? `${count} ${noun}` : `${count} ${noun}s`;
68
72
  }
69
73
  function errorMessage(error) {
70
- return error instanceof Error ? error.message : String(error);
74
+ return error instanceof Error ? error.message : String(error);
71
75
  }
72
76
  function defaultBuildEntries(config, tagPattern, includePaths) {
73
- const options = {};
74
- if (tagPattern !== void 0) {
75
- options.tagPattern = tagPattern;
76
- }
77
- if (includePaths !== void 0) {
78
- options.includePaths = includePaths;
79
- }
80
- return buildChangelogEntries(config, SYNTHETIC_VALIDATE_TAG, options);
77
+ const options = {};
78
+ if (tagPattern !== undefined) {
79
+ options.tagPattern = tagPattern;
80
+ }
81
+ if (includePaths !== undefined) {
82
+ options.includePaths = includePaths;
83
+ }
84
+ return buildChangelogEntries(config, SYNTHETIC_VALIDATE_TAG, options);
81
85
  }
82
86
  function flattenEntriesToHashes(entries) {
83
- const hashes = [];
84
- for (const entry of entries) {
85
- for (const section of entry.sections) {
86
- for (const item of section.items) {
87
- if (item.hash !== void 0) {
88
- hashes.push(item.hash);
87
+ const hashes = [];
88
+ for (const entry of entries) {
89
+ for (const section of entry.sections) {
90
+ for (const item of section.items) {
91
+ if (item.hash !== undefined) {
92
+ hashes.push(item.hash);
93
+ }
94
+ }
89
95
  }
90
- }
91
96
  }
92
- }
93
- return hashes;
97
+ return hashes;
94
98
  }
95
99
  function validateLoadedConfig(rawConfig) {
96
- if (rawConfig === void 0) {
97
- return void 0;
98
- }
99
- const { config, errors } = validateConfig(rawConfig);
100
- if (errors.length > 0) {
101
- throw new Error(`Invalid config:
102
- - ${errors.join("\n - ")}`);
103
- }
104
- return config;
100
+ if (rawConfig === undefined) {
101
+ return undefined;
102
+ }
103
+ const { config, errors } = validateConfig(rawConfig);
104
+ if (errors.length > 0) {
105
+ throw new Error(`Invalid config:\n - ${errors.join('\n - ')}`);
106
+ }
107
+ return config;
105
108
  }
106
109
  function buildSinglePackageInputs(userConfig, buildEntries) {
107
- const config = mergeSinglePackageConfig(userConfig);
108
- const hashes = flattenEntriesToHashes(buildEntries(config));
109
- return {
110
- project: { filePath: resolveOverridePath("."), hashes }
111
- };
110
+ const config = mergeSinglePackageConfig(userConfig);
111
+ const hashes = flattenEntriesToHashes(buildEntries(config));
112
+ return {
113
+ project: { filePath: resolveOverridePath('.'), hashes },
114
+ };
112
115
  }
113
116
  function buildMonorepoInputs(discoveredPaths, userConfig, buildEntries) {
114
- const rootPackage = readRootPackageVersion();
115
- const config = mergeMonorepoConfig(discoveredPaths, userConfig, rootPackage);
116
- const workspaces = config.workspaces.map((workspace) => {
117
- const tagPattern = buildTagPattern(getAllTagPrefixes(workspace));
118
- return {
119
- filePath: resolveOverridePath(workspace.workspacePath),
120
- hashes: flattenEntriesToHashes(buildEntries(config, tagPattern, workspace.paths))
117
+ const rootPackage = readRootPackageVersion();
118
+ const config = mergeMonorepoConfig(discoveredPaths, userConfig, rootPackage);
119
+ const workspaces = config.workspaces.map((workspace) => {
120
+ const tagPattern = buildTagPattern(getAllTagPrefixes(workspace));
121
+ return {
122
+ filePath: resolveOverridePath(workspace.workspacePath),
123
+ hashes: flattenEntriesToHashes(buildEntries(config, tagPattern, workspace.paths)),
124
+ };
125
+ });
126
+ const project = config.project;
127
+ const projectScope = {
128
+ filePath: resolveOverridePath('.'),
121
129
  };
122
- });
123
- const project = config.project;
124
- const projectScope = {
125
- filePath: resolveOverridePath(".")
126
- };
127
- if (project !== void 0) {
128
- const contributingPaths = config.workspaces.flatMap((workspace) => workspace.paths);
129
- const projectTagPattern = buildTagPattern([project.tagPrefix]);
130
- projectScope.hashes = flattenEntriesToHashes(buildEntries(config, projectTagPattern, contributingPaths));
131
- }
132
- return { project: projectScope, workspaces };
130
+ if (project !== undefined) {
131
+ const contributingPaths = config.workspaces.flatMap((workspace) => workspace.paths);
132
+ const projectTagPattern = buildTagPattern([project.tagPrefix]);
133
+ projectScope.hashes = flattenEntriesToHashes(buildEntries(config, projectTagPattern, contributingPaths));
134
+ }
135
+ return { project: projectScope, workspaces };
133
136
  }
134
- export {
135
- formatValidateOverridesResult,
136
- validateOverridesCommand
137
- };
@@ -1,62 +1,59 @@
1
- const WORK_TYPES_DATA = {
2
- tiers: ["public", "internal", "process"],
3
- types: [
4
- { tier: "public", key: "feat", aliases: ["feature"], emoji: "\u{1F389}", label: "Features", breakingPolicy: "optional" },
5
- { tier: "public", key: "drop", aliases: [], emoji: "\u{1FAA6}", label: "Removed", breakingPolicy: "required" },
6
- { tier: "public", key: "deprecate", aliases: [], emoji: "\u{1F5D1}\uFE0F", label: "Deprecated", breakingPolicy: "forbidden" },
7
- { tier: "public", key: "fix", aliases: ["bugfix"], emoji: "\u{1F41B}", label: "Bug fixes", breakingPolicy: "forbidden" },
8
- { tier: "public", key: "sec", aliases: ["security"], emoji: "\u{1F512}", label: "Security", breakingPolicy: "optional" },
9
- {
10
- tier: "public",
11
- key: "perf",
12
- aliases: ["performance"],
13
- emoji: "\u26A1",
14
- label: "Performance",
15
- breakingPolicy: "forbidden"
1
+ export const WORK_TYPES_DATA = {
2
+ tiers: ['public', 'internal', 'process'],
3
+ types: [
4
+ { tier: 'public', key: 'feat', aliases: ['feature'], emoji: '🎉', label: 'Features', breakingPolicy: 'optional' },
5
+ { tier: 'public', key: 'drop', aliases: [], emoji: '🪦', label: 'Removed', breakingPolicy: 'required' },
6
+ { tier: 'public', key: 'deprecate', aliases: [], emoji: '🗑️', label: 'Deprecated', breakingPolicy: 'forbidden' },
7
+ { tier: 'public', key: 'fix', aliases: ['bugfix'], emoji: '🐛', label: 'Bug fixes', breakingPolicy: 'forbidden' },
8
+ { tier: 'public', key: 'sec', aliases: ['security'], emoji: '🔒', label: 'Security', breakingPolicy: 'optional' },
9
+ {
10
+ tier: 'public',
11
+ key: 'perf',
12
+ aliases: ['performance'],
13
+ emoji: '⚡',
14
+ label: 'Performance',
15
+ breakingPolicy: 'forbidden',
16
+ },
17
+ {
18
+ tier: 'internal',
19
+ key: 'internal',
20
+ aliases: ['utility'],
21
+ emoji: '🏗️',
22
+ label: 'Internal features',
23
+ breakingPolicy: 'forbidden',
24
+ },
25
+ {
26
+ tier: 'internal',
27
+ key: 'refactor',
28
+ aliases: [],
29
+ emoji: '♻️',
30
+ label: 'Refactoring',
31
+ breakingPolicy: 'forbidden',
32
+ },
33
+ { tier: 'internal', key: 'tests', aliases: ['test'], emoji: '🧪', label: 'Tests', breakingPolicy: 'forbidden' },
34
+ { tier: 'process', key: 'tooling', aliases: [], emoji: '⚙️', label: 'Tooling', breakingPolicy: 'forbidden' },
35
+ { tier: 'process', key: 'ci', aliases: [], emoji: '👷', label: 'CI', breakingPolicy: 'forbidden' },
36
+ { tier: 'process', key: 'deps', aliases: ['dep'], emoji: '📦', label: 'Dependencies', breakingPolicy: 'forbidden' },
37
+ { tier: 'process', key: 'ai', aliases: [], emoji: '🤖', label: 'Agentic support', breakingPolicy: 'forbidden' },
38
+ {
39
+ tier: 'process',
40
+ key: 'docs',
41
+ aliases: ['doc'],
42
+ emoji: '📚',
43
+ label: 'Documentation',
44
+ breakingPolicy: 'forbidden',
45
+ },
46
+ {
47
+ tier: 'process',
48
+ key: 'fmt',
49
+ aliases: [],
50
+ emoji: '🎨',
51
+ label: 'Formatting',
52
+ breakingPolicy: 'forbidden',
53
+ excludedFromChangelog: true,
54
+ },
55
+ ],
56
+ markers: {
57
+ breaking: { emoji: '🚨', label: 'Breaking' },
16
58
  },
17
- {
18
- tier: "internal",
19
- key: "internal",
20
- aliases: ["utility"],
21
- emoji: "\u{1F3D7}\uFE0F",
22
- label: "Internal features",
23
- breakingPolicy: "forbidden"
24
- },
25
- {
26
- tier: "internal",
27
- key: "refactor",
28
- aliases: [],
29
- emoji: "\u267B\uFE0F",
30
- label: "Refactoring",
31
- breakingPolicy: "forbidden"
32
- },
33
- { tier: "internal", key: "tests", aliases: ["test"], emoji: "\u{1F9EA}", label: "Tests", breakingPolicy: "forbidden" },
34
- { tier: "process", key: "tooling", aliases: [], emoji: "\u2699\uFE0F", label: "Tooling", breakingPolicy: "forbidden" },
35
- { tier: "process", key: "ci", aliases: [], emoji: "\u{1F477}", label: "CI", breakingPolicy: "forbidden" },
36
- { tier: "process", key: "deps", aliases: ["dep"], emoji: "\u{1F4E6}", label: "Dependencies", breakingPolicy: "forbidden" },
37
- { tier: "process", key: "ai", aliases: [], emoji: "\u{1F916}", label: "Agentic support", breakingPolicy: "forbidden" },
38
- {
39
- tier: "process",
40
- key: "docs",
41
- aliases: ["doc"],
42
- emoji: "\u{1F4DA}",
43
- label: "Documentation",
44
- breakingPolicy: "forbidden"
45
- },
46
- {
47
- tier: "process",
48
- key: "fmt",
49
- aliases: [],
50
- emoji: "\u{1F3A8}",
51
- label: "Formatting",
52
- breakingPolicy: "forbidden",
53
- excludedFromChangelog: true
54
- }
55
- ],
56
- markers: {
57
- breaking: { emoji: "\u{1F6A8}", label: "Breaking" }
58
- }
59
- };
60
- export {
61
- WORK_TYPES_DATA
62
59
  };
@@ -1,24 +1,19 @@
1
- function hasExpectedTopLevelShape(value) {
2
- if (typeof value !== "object" || value === null) {
3
- return false;
4
- }
5
- if (!("tiers" in value) || !("types" in value)) {
6
- return false;
7
- }
8
- return Array.isArray(value.tiers) && Array.isArray(value.types);
1
+ export function hasExpectedTopLevelShape(value) {
2
+ if (typeof value !== 'object' || value === null) {
3
+ return false;
4
+ }
5
+ if (!('tiers' in value) || !('types' in value)) {
6
+ return false;
7
+ }
8
+ return Array.isArray(value.tiers) && Array.isArray(value.types);
9
9
  }
10
- function errorMessage(error) {
11
- return error instanceof Error ? error.message : String(error);
10
+ export function errorMessage(error) {
11
+ return error instanceof Error ? error.message : String(error);
12
12
  }
13
- function buildFetchInit() {
14
- const token = process.env.GITHUB_TOKEN;
15
- if (token === void 0 || token === "") {
16
- return void 0;
17
- }
18
- return { headers: { Authorization: `Bearer ${token}` } };
13
+ export function buildFetchInit() {
14
+ const token = process.env.GITHUB_TOKEN;
15
+ if (token === undefined || token === '') {
16
+ return undefined;
17
+ }
18
+ return { headers: { Authorization: `Bearer ${token}` } };
19
19
  }
20
- export {
21
- buildFetchInit,
22
- errorMessage,
23
- hasExpectedTopLevelShape
24
- };
@@ -1,65 +1,63 @@
1
- import { existsSync, readFileSync } from "node:fs";
2
- import path from "node:path";
3
- import { reportError, writeFileWithCheck } from "@williamthorsen/nmr-core";
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import path from 'node:path';
3
+ import { reportError, writeFileWithCheck } from '@williamthorsen/nmr-core';
4
4
  import { extractVersion } from "./changelogJsonUtils.js";
5
5
  import { dim } from "./format.js";
6
6
  import { renderInjectedReadme } from "./injectReleaseNotesIntoReadme.js";
7
- function writeReleaseNotesPreviews(options) {
8
- const { workspacePath, tag, changelogJsonPath, sectionOrder, dryRun } = options;
9
- const version = extractVersion(tag);
10
- const readmePath = path.join(workspacePath, "README.md");
11
- let readmeExists = existsSync(readmePath);
12
- let readmeUnreadable = false;
13
- let readmeContent = "";
14
- if (readmeExists) {
15
- try {
16
- readmeContent = readFileSync(readmePath, "utf8");
17
- } catch (error) {
18
- const message = error instanceof Error ? error.message : String(error);
19
- console.warn(`Warning: failed to read ${readmePath}: ${message}; skipping injected-README preview`);
20
- readmeExists = false;
21
- readmeUnreadable = true;
7
+ export function writeReleaseNotesPreviews(options) {
8
+ const { workspacePath, tag, changelogJsonPath, sectionOrder, dryRun } = options;
9
+ const version = extractVersion(tag);
10
+ const readmePath = path.join(workspacePath, 'README.md');
11
+ let readmeExists = existsSync(readmePath);
12
+ let readmeUnreadable = false;
13
+ let readmeContent = '';
14
+ if (readmeExists) {
15
+ try {
16
+ readmeContent = readFileSync(readmePath, 'utf8');
17
+ }
18
+ catch (error) {
19
+ const message = error instanceof Error ? error.message : String(error);
20
+ console.warn(`Warning: failed to read ${readmePath}: ${message}; skipping injected-README preview`);
21
+ readmeExists = false;
22
+ readmeUnreadable = true;
23
+ }
22
24
  }
23
- }
24
- const rendered = renderInjectedReadme(readmeContent, changelogJsonPath, tag, sectionOrder);
25
- if (rendered === void 0) {
26
- return { renderSkipped: true };
27
- }
28
- const docsDir = path.join(workspacePath, "docs");
29
- const readmePreviewPath = path.join(docsDir, `README.v${version}.md`);
30
- const releaseNotesPreviewPath = path.join(docsDir, `RELEASE_NOTES.v${version}.md`);
31
- let injectedReadme;
32
- if (readmeExists) {
33
- injectedReadme = writePreviewFile(readmePreviewPath, rendered.injectedReadme, dryRun);
34
- } else {
35
- if (!readmeUnreadable) {
36
- console.warn(
37
- `Warning: ${readmePath} not found; skipping injected-README preview but still writing standalone release notes`
38
- );
25
+ const rendered = renderInjectedReadme(readmeContent, changelogJsonPath, tag, sectionOrder);
26
+ if (rendered === undefined) {
27
+ return { renderSkipped: true };
39
28
  }
40
- injectedReadme = { filePath: readmePreviewPath, outcome: "skipped-no-readme" };
41
- }
42
- const releaseNotesContent = rendered.releaseNotesMarkdown.endsWith("\n") ? rendered.releaseNotesMarkdown : `${rendered.releaseNotesMarkdown}
43
- `;
44
- const releaseNotes = writePreviewFile(releaseNotesPreviewPath, releaseNotesContent, dryRun);
45
- return { injectedReadme, releaseNotes, renderSkipped: false };
29
+ const docsDir = path.join(workspacePath, 'docs');
30
+ const readmePreviewPath = path.join(docsDir, `README.v${version}.md`);
31
+ const releaseNotesPreviewPath = path.join(docsDir, `RELEASE_NOTES.v${version}.md`);
32
+ let injectedReadme;
33
+ if (readmeExists) {
34
+ injectedReadme = writePreviewFile(readmePreviewPath, rendered.injectedReadme, dryRun);
35
+ }
36
+ else {
37
+ if (!readmeUnreadable) {
38
+ console.warn(`Warning: ${readmePath} not found; skipping injected-README preview but still writing standalone release notes`);
39
+ }
40
+ injectedReadme = { filePath: readmePreviewPath, outcome: 'skipped-no-readme' };
41
+ }
42
+ const releaseNotesContent = rendered.releaseNotesMarkdown.endsWith('\n')
43
+ ? rendered.releaseNotesMarkdown
44
+ : `${rendered.releaseNotesMarkdown}\n`;
45
+ const releaseNotes = writePreviewFile(releaseNotesPreviewPath, releaseNotesContent, dryRun);
46
+ return { injectedReadme, releaseNotes, renderSkipped: false };
46
47
  }
47
48
  function writePreviewFile(filePath, content, dryRun) {
48
- if (dryRun) {
49
- console.info(dim(` [dry-run] Would write ${filePath}`));
50
- return { filePath, outcome: "dry-run" };
51
- }
52
- const result = writeFileWithCheck(filePath, content, { dryRun: false, overwrite: true });
53
- if (result.outcome === "failed") {
54
- reportError(`Failed to write ${filePath}: ${result.error ?? "unknown error"}`);
55
- return { filePath, outcome: "failed", ...result.error === void 0 ? {} : { error: result.error } };
56
- }
57
- if (result.outcome === "created" || result.outcome === "overwritten") {
58
- console.info(dim(` Wrote ${filePath}`));
59
- return { filePath, outcome: result.outcome };
60
- }
61
- return { filePath, outcome: "failed", error: `unexpected outcome: ${result.outcome}` };
49
+ if (dryRun) {
50
+ console.info(dim(` [dry-run] Would write ${filePath}`));
51
+ return { filePath, outcome: 'dry-run' };
52
+ }
53
+ const result = writeFileWithCheck(filePath, content, { dryRun: false, overwrite: true });
54
+ if (result.outcome === 'failed') {
55
+ reportError(`Failed to write ${filePath}: ${result.error ?? 'unknown error'}`);
56
+ return { filePath, outcome: 'failed', ...(result.error === undefined ? {} : { error: result.error }) };
57
+ }
58
+ if (result.outcome === 'created' || result.outcome === 'overwritten') {
59
+ console.info(dim(` Wrote ${filePath}`));
60
+ return { filePath, outcome: result.outcome };
61
+ }
62
+ return { filePath, outcome: 'failed', error: `unexpected outcome: ${result.outcome}` };
62
63
  }
63
- export {
64
- writeReleaseNotesPreviews
65
- };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@williamthorsen/release-kit",
3
- "version": "6.0.0",
3
+ "version": "8.0.0",
4
4
  "description": "Version-bumping and changelog-generation toolkit for release workflows",
5
5
  "keywords": [],
6
6
  "homepage": "https://github.com/williamthorsen/node-monorepo-tools/tree/main/packages/release-kit#readme",
@@ -17,6 +17,7 @@
17
17
  "type": "module",
18
18
  "exports": {
19
19
  ".": {
20
+ "types": "./dist/esm/index.d.ts",
20
21
  "import": "./dist/esm/index.js"
21
22
  }
22
23
  },
@@ -38,7 +39,7 @@
38
39
  "semver": "7.8.5",
39
40
  "yaml": "2.9.0",
40
41
  "zod": "4.4.3",
41
- "@williamthorsen/nmr-core": "0.5.0"
42
+ "@williamthorsen/nmr-core": "0.7.0"
42
43
  },
43
44
  "devDependencies": {
44
45
  "@types/semver": "7.7.1",
package/dist/esm/.cache DELETED
@@ -1 +0,0 @@
1
- 5ed41ffb0267b5678fc3b3273d6104a1c1c120fea20f92d48e173aee3ae9e2f5