@williamthorsen/release-kit 5.4.0 → 7.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 (135) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +12 -12
  3. package/dist/esm/.cache +1 -1
  4. package/dist/esm/assertCleanWorkingTree.js +9 -14
  5. package/dist/esm/bin/release-kit.js +202 -229
  6. package/dist/esm/buildChangelogEntries.d.ts +2 -2
  7. package/dist/esm/buildChangelogEntries.js +142 -149
  8. package/dist/esm/buildDependencyGraph.d.ts +1 -1
  9. package/dist/esm/buildDependencyGraph.js +60 -59
  10. package/dist/esm/buildEmptyReleaseEntry.d.ts +1 -1
  11. package/dist/esm/buildEmptyReleaseEntry.js +12 -15
  12. package/dist/esm/buildReleaseSummary.d.ts +1 -1
  13. package/dist/esm/buildReleaseSummary.js +23 -26
  14. package/dist/esm/buildSyntheticChangelogEntry.d.ts +1 -1
  15. package/dist/esm/buildSyntheticChangelogEntry.js +9 -12
  16. package/dist/esm/bumpAllVersions.d.ts +1 -1
  17. package/dist/esm/bumpAllVersions.js +51 -52
  18. package/dist/esm/bumpVersion.d.ts +1 -1
  19. package/dist/esm/bumpVersion.js +25 -28
  20. package/dist/esm/changelogJsonFile.d.ts +1 -1
  21. package/dist/esm/changelogJsonFile.js +59 -62
  22. package/dist/esm/changelogJsonUtils.d.ts +1 -1
  23. package/dist/esm/changelogJsonUtils.js +35 -32
  24. package/dist/esm/changelogOverrides.d.ts +1 -1
  25. package/dist/esm/changelogOverrides.js +374 -377
  26. package/dist/esm/checkWorkTypesDrift.js +104 -99
  27. package/dist/esm/collectPolicyViolations.d.ts +2 -2
  28. package/dist/esm/collectPolicyViolations.js +11 -14
  29. package/dist/esm/commitCommand.js +48 -53
  30. package/dist/esm/compareVersions.js +20 -23
  31. package/dist/esm/createGithubRelease.js +56 -59
  32. package/dist/esm/createGithubReleaseCommand.js +21 -29
  33. package/dist/esm/createTags.js +57 -56
  34. package/dist/esm/decideRelease.d.ts +2 -2
  35. package/dist/esm/decideRelease.js +27 -41
  36. package/dist/esm/defaults.d.ts +3 -3
  37. package/dist/esm/defaults.js +36 -48
  38. package/dist/esm/deleteFileIfExists.js +10 -12
  39. package/dist/esm/deriveWorkspaceConfig.d.ts +1 -1
  40. package/dist/esm/deriveWorkspaceConfig.js +34 -36
  41. package/dist/esm/detectPackageManager.js +35 -37
  42. package/dist/esm/detectUndeclaredTagPrefixes.js +41 -40
  43. package/dist/esm/determineBumpFromCommits.d.ts +2 -2
  44. package/dist/esm/determineBumpFromCommits.js +25 -29
  45. package/dist/esm/determineBumpType.d.ts +1 -1
  46. package/dist/esm/determineBumpType.js +31 -32
  47. package/dist/esm/discoverWorkspaces.js +38 -40
  48. package/dist/esm/format.js +6 -11
  49. package/dist/esm/generateChangelogs.d.ts +1 -1
  50. package/dist/esm/generateChangelogs.js +13 -17
  51. package/dist/esm/getCommitsSinceTarget.d.ts +1 -1
  52. package/dist/esm/getCommitsSinceTarget.js +54 -55
  53. package/dist/esm/hasPrettierConfig.js +33 -35
  54. package/dist/esm/help/prepareHelp.d.ts +2 -0
  55. package/dist/esm/help/prepareHelp.js +26 -0
  56. package/dist/esm/index.d.ts +4 -4
  57. package/dist/esm/index.js +2 -8
  58. package/dist/esm/init/checks.js +28 -32
  59. package/dist/esm/init/detectRepoType.js +12 -15
  60. package/dist/esm/init/initCommand.js +60 -54
  61. package/dist/esm/init/parseJsonRecord.js +9 -11
  62. package/dist/esm/init/scaffold.d.ts +1 -1
  63. package/dist/esm/init/scaffold.js +32 -38
  64. package/dist/esm/init/templates.d.ts +1 -1
  65. package/dist/esm/init/templates.js +16 -22
  66. package/dist/esm/injectReleaseNotesIntoReadme.js +42 -49
  67. package/dist/esm/injectSection.js +17 -27
  68. package/dist/esm/loadConfig.d.ts +1 -1
  69. package/dist/esm/loadConfig.js +206 -225
  70. package/dist/esm/parseCommitMessage.d.ts +1 -1
  71. package/dist/esm/parseCommitMessage.js +72 -76
  72. package/dist/esm/parseRequestedTags.js +6 -9
  73. package/dist/esm/prepareCommand.d.ts +32 -1
  74. package/dist/esm/prepareCommand.js +225 -271
  75. package/dist/esm/previewTagPrefixes.d.ts +1 -1
  76. package/dist/esm/previewTagPrefixes.js +101 -96
  77. package/dist/esm/propagateBumps.d.ts +2 -2
  78. package/dist/esm/propagateBumps.js +48 -50
  79. package/dist/esm/publish.d.ts +2 -2
  80. package/dist/esm/publish.js +22 -28
  81. package/dist/esm/publishCommand.js +75 -86
  82. package/dist/esm/pushCommand.js +33 -40
  83. package/dist/esm/pushRelease.d.ts +1 -1
  84. package/dist/esm/pushRelease.js +21 -24
  85. package/dist/esm/readCurrentVersion.js +13 -17
  86. package/dist/esm/releasePrepare.d.ts +1 -1
  87. package/dist/esm/releasePrepare.js +213 -231
  88. package/dist/esm/releasePrepareMono.d.ts +2 -2
  89. package/dist/esm/releasePrepareMono.js +434 -493
  90. package/dist/esm/releasePrepareProject.d.ts +2 -2
  91. package/dist/esm/releasePrepareProject.js +143 -153
  92. package/dist/esm/renderChangelogMarkdown.d.ts +1 -1
  93. package/dist/esm/renderChangelogMarkdown.js +20 -24
  94. package/dist/esm/renderReleaseNotes.d.ts +1 -1
  95. package/dist/esm/renderReleaseNotes.js +50 -55
  96. package/dist/esm/reportPrepare.d.ts +1 -1
  97. package/dist/esm/reportPrepare.js +230 -231
  98. package/dist/esm/resolveCliffConfigPath.js +18 -23
  99. package/dist/esm/resolveCommandTags.d.ts +1 -1
  100. package/dist/esm/resolveCommandTags.js +47 -44
  101. package/dist/esm/resolveReleaseNotesConfig.d.ts +1 -1
  102. package/dist/esm/resolveReleaseNotesConfig.js +39 -41
  103. package/dist/esm/resolveReleaseTags.d.ts +1 -1
  104. package/dist/esm/resolveReleaseTags.js +39 -40
  105. package/dist/esm/runGitCliff.js +27 -30
  106. package/dist/esm/showTagPrefixesCommand.js +48 -70
  107. package/dist/esm/stripEmojiPrefix.js +2 -5
  108. package/dist/esm/stripScope.js +18 -21
  109. package/dist/esm/sync-labels/generateCommand.d.ts +1 -1
  110. package/dist/esm/sync-labels/generateCommand.js +51 -52
  111. package/dist/esm/sync-labels/initCommand.js +46 -47
  112. package/dist/esm/sync-labels/loadSyncLabelsConfig.d.ts +1 -1
  113. package/dist/esm/sync-labels/loadSyncLabelsConfig.js +46 -52
  114. package/dist/esm/sync-labels/presets.d.ts +1 -1
  115. package/dist/esm/sync-labels/presets.js +40 -43
  116. package/dist/esm/sync-labels/resolveLabels.d.ts +1 -1
  117. package/dist/esm/sync-labels/resolveLabels.js +28 -35
  118. package/dist/esm/sync-labels/syncCommand.js +30 -30
  119. package/dist/esm/sync-labels/templates.d.ts +1 -1
  120. package/dist/esm/sync-labels/templates.js +23 -26
  121. package/dist/esm/sync-labels/types.js +1 -0
  122. package/dist/esm/syncWorkTypes.js +83 -81
  123. package/dist/esm/tagCommand.js +12 -21
  124. package/dist/esm/typeGuards.js +4 -8
  125. package/dist/esm/types.js +66 -60
  126. package/dist/esm/validateConfig.d.ts +1 -1
  127. package/dist/esm/validateConfig.js +109 -115
  128. package/dist/esm/validateOnlyExcludesStrandedDependents.d.ts +2 -2
  129. package/dist/esm/validateOnlyExcludesStrandedDependents.js +97 -91
  130. package/dist/esm/validateOverridesCommand.d.ts +2 -2
  131. package/dist/esm/validateOverridesCommand.js +111 -111
  132. package/dist/esm/workTypesData.js +57 -60
  133. package/dist/esm/workTypesUtils.js +16 -21
  134. package/dist/esm/writeReleaseNotesPreviews.js +55 -57
  135. package/package.json +2 -6
@@ -1,32 +1,28 @@
1
1
  import { determineBumpType } from "./determineBumpType.js";
2
- import {
3
- parseCommitMessage
4
- } from "./parseCommitMessage.js";
5
- function determineBumpFromCommits(commits, workTypes, versionPatterns, scopeAliases, options) {
6
- const parseOptions = {
7
- ...options?.breakingPolicies !== void 0 && { breakingPolicies: options.breakingPolicies },
8
- ...options?.onPolicyViolation !== void 0 && { onPolicyViolation: options.onPolicyViolation }
9
- };
10
- const parsedCommits = [];
11
- const unparseable = [];
12
- for (const commit of commits) {
13
- const parsed = parseCommitMessage(commit.message, commit.hash, workTypes, scopeAliases, parseOptions);
14
- if (parsed === void 0) {
15
- unparseable.push(commit);
16
- } else {
17
- parsedCommits.push(parsed);
2
+ import { parseCommitMessage, } from "./parseCommitMessage.js";
3
+ export function determineBumpFromCommits(commits, workTypes, versionPatterns, scopeAliases, options) {
4
+ const parseOptions = {
5
+ ...(options?.breakingPolicies !== undefined && { breakingPolicies: options.breakingPolicies }),
6
+ ...(options?.onPolicyViolation !== undefined && { onPolicyViolation: options.onPolicyViolation }),
7
+ };
8
+ const parsedCommits = [];
9
+ const unparseable = [];
10
+ for (const commit of commits) {
11
+ const parsed = parseCommitMessage(commit.message, commit.hash, workTypes, scopeAliases, parseOptions);
12
+ if (parsed === undefined) {
13
+ unparseable.push(commit);
14
+ }
15
+ else {
16
+ parsedCommits.push(parsed);
17
+ }
18
18
  }
19
- }
20
- let releaseType = determineBumpType(parsedCommits, workTypes, versionPatterns);
21
- if (releaseType === void 0 && commits.length > 0) {
22
- releaseType = "patch";
23
- }
24
- return {
25
- releaseType,
26
- parsedCommitCount: parsedCommits.length,
27
- unparseableCommits: unparseable.length > 0 ? unparseable : void 0
28
- };
19
+ let releaseType = determineBumpType(parsedCommits, workTypes, versionPatterns);
20
+ if (releaseType === undefined && commits.length > 0) {
21
+ releaseType = 'patch';
22
+ }
23
+ return {
24
+ releaseType,
25
+ parsedCommitCount: parsedCommits.length,
26
+ unparseableCommits: unparseable.length > 0 ? unparseable : undefined,
27
+ };
29
28
  }
30
- export {
31
- determineBumpFromCommits
32
- };
@@ -1,2 +1,2 @@
1
- import type { ParsedCommit, ReleaseType, VersionPatterns, WorkTypeConfig } from './types.ts';
1
+ import type { ParsedCommit, ReleaseType, VersionPatterns, WorkTypeConfig } from './types.js';
2
2
  export declare function determineBumpType(commits: readonly ParsedCommit[], workTypes: Record<string, WorkTypeConfig>, versionPatterns: VersionPatterns): ReleaseType | undefined;
@@ -1,36 +1,35 @@
1
1
  const RELEASE_PRIORITY = {
2
- major: 3,
3
- minor: 2,
4
- patch: 1
2
+ major: 3,
3
+ minor: 2,
4
+ patch: 1,
5
5
  };
6
- function determineBumpType(commits, workTypes, versionPatterns) {
7
- const knownTypes = new Set(Object.keys(workTypes));
8
- let highestPriority = 0;
9
- let result;
10
- for (const commit of commits) {
11
- if (commit.breaking && versionPatterns.major.includes("!")) {
12
- return "major";
6
+ export function determineBumpType(commits, workTypes, versionPatterns) {
7
+ const knownTypes = new Set(Object.keys(workTypes));
8
+ let highestPriority = 0;
9
+ let result;
10
+ for (const commit of commits) {
11
+ if (commit.breaking && versionPatterns.major.includes('!')) {
12
+ return 'major';
13
+ }
14
+ const commitType = commit.type;
15
+ if (!knownTypes.has(commitType)) {
16
+ continue;
17
+ }
18
+ let bump;
19
+ if (versionPatterns.major.includes(commitType)) {
20
+ bump = 'major';
21
+ }
22
+ else if (versionPatterns.minor.includes(commitType)) {
23
+ bump = 'minor';
24
+ }
25
+ else {
26
+ bump = 'patch';
27
+ }
28
+ const priority = RELEASE_PRIORITY[bump];
29
+ if (priority > highestPriority) {
30
+ highestPriority = priority;
31
+ result = bump;
32
+ }
13
33
  }
14
- const commitType = commit.type;
15
- if (!knownTypes.has(commitType)) {
16
- continue;
17
- }
18
- let bump;
19
- if (versionPatterns.major.includes(commitType)) {
20
- bump = "major";
21
- } else if (versionPatterns.minor.includes(commitType)) {
22
- bump = "minor";
23
- } else {
24
- bump = "patch";
25
- }
26
- const priority = RELEASE_PRIORITY[bump];
27
- if (priority > highestPriority) {
28
- highestPriority = priority;
29
- result = bump;
30
- }
31
- }
32
- return result;
34
+ return result;
33
35
  }
34
- export {
35
- determineBumpType
36
- };
@@ -1,43 +1,41 @@
1
- import { existsSync, readFileSync } from "node:fs";
2
- import { join } from "node:path";
3
- import { glob } from "glob";
4
- import { parse } from "yaml";
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { glob } from 'glob';
4
+ import { parse } from 'yaml';
5
5
  import { isRecord } from "./typeGuards.js";
6
- async function discoverWorkspaces() {
7
- const workspaceFile = "pnpm-workspace.yaml";
8
- if (!existsSync(workspaceFile)) {
9
- return void 0;
10
- }
11
- let content;
12
- try {
13
- content = readFileSync(workspaceFile, "utf8");
14
- } catch (error) {
15
- console.warn(`Warning: Failed to read ${workspaceFile}: ${error instanceof Error ? error.message : String(error)}`);
16
- return void 0;
17
- }
18
- const parsed = parse(content);
19
- if (!isRecord(parsed)) {
20
- return void 0;
21
- }
22
- const packagesField = parsed.packages;
23
- if (!Array.isArray(packagesField)) {
24
- return void 0;
25
- }
26
- const patterns = packagesField.filter((p) => typeof p === "string");
27
- if (patterns.length === 0) {
28
- return void 0;
29
- }
30
- const directories = [];
31
- for (const pattern of patterns) {
32
- const matches = await glob(pattern, { posix: true });
33
- for (const match of matches) {
34
- if (existsSync(join(match, "package.json"))) {
35
- directories.push(match);
36
- }
6
+ export async function discoverWorkspaces() {
7
+ const workspaceFile = 'pnpm-workspace.yaml';
8
+ if (!existsSync(workspaceFile)) {
9
+ return undefined;
37
10
  }
38
- }
39
- return directories.length > 0 ? [...directories].sort() : void 0;
11
+ let content;
12
+ try {
13
+ content = readFileSync(workspaceFile, 'utf8');
14
+ }
15
+ catch (error) {
16
+ console.warn(`Warning: Failed to read ${workspaceFile}: ${error instanceof Error ? error.message : String(error)}`);
17
+ return undefined;
18
+ }
19
+ const parsed = parse(content);
20
+ if (!isRecord(parsed)) {
21
+ return undefined;
22
+ }
23
+ const packagesField = parsed.packages;
24
+ if (!Array.isArray(packagesField)) {
25
+ return undefined;
26
+ }
27
+ const patterns = packagesField.filter((p) => typeof p === 'string');
28
+ if (patterns.length === 0) {
29
+ return undefined;
30
+ }
31
+ const directories = [];
32
+ for (const pattern of patterns) {
33
+ const matches = await glob(pattern, { posix: true });
34
+ for (const match of matches) {
35
+ if (existsSync(join(match, 'package.json'))) {
36
+ directories.push(match);
37
+ }
38
+ }
39
+ }
40
+ return directories.length > 0 ? [...directories].sort() : undefined;
40
41
  }
41
- export {
42
- discoverWorkspaces
43
- };
@@ -1,14 +1,9 @@
1
- function bold(text) {
2
- return `\x1B[1m${text}\x1B[0m`;
1
+ export function bold(text) {
2
+ return `\u001B[1m${text}\u001B[0m`;
3
3
  }
4
- function dim(text) {
5
- return `\x1B[2m${text}\x1B[0m`;
4
+ export function dim(text) {
5
+ return `\u001B[2m${text}\u001B[0m`;
6
6
  }
7
- function sectionHeader(name) {
8
- return `\u2501\u2501\u2501 ${name} \u2501\u2501\u2501`;
7
+ export function sectionHeader(name) {
8
+ return `━━━ ${name} ━━━`;
9
9
  }
10
- export {
11
- bold,
12
- dim,
13
- sectionHeader
14
- };
@@ -1,4 +1,4 @@
1
- import type { WorkspaceConfig } from './types.ts';
1
+ import type { WorkspaceConfig } from './types.js';
2
2
  export declare function buildTagPattern(tagPrefixes: readonly string[]): string;
3
3
  export declare function getAllTagPrefixes(workspace: WorkspaceConfig): string[];
4
4
  export interface GenerateChangelogOptions {
@@ -1,21 +1,17 @@
1
- function buildTagPattern(tagPrefixes) {
2
- if (tagPrefixes.length === 0) {
3
- throw new Error("buildTagPattern: tagPrefixes must contain at least one entry");
4
- }
5
- if (tagPrefixes.length === 1) {
6
- const single = tagPrefixes[0] ?? "";
7
- return `${single}[0-9].*`;
8
- }
9
- const escaped = tagPrefixes.map(escapeRegex);
10
- return `(${escaped.join("|")})[0-9].*`;
1
+ export function buildTagPattern(tagPrefixes) {
2
+ if (tagPrefixes.length === 0) {
3
+ throw new Error('buildTagPattern: tagPrefixes must contain at least one entry');
4
+ }
5
+ if (tagPrefixes.length === 1) {
6
+ const single = tagPrefixes[0] ?? '';
7
+ return `${single}[0-9].*`;
8
+ }
9
+ const escaped = tagPrefixes.map(escapeRegex);
10
+ return `(${escaped.join('|')})[0-9].*`;
11
11
  }
12
- function getAllTagPrefixes(workspace) {
13
- return [workspace.tagPrefix, ...workspace.legacyIdentities?.map((identity) => identity.tagPrefix) ?? []];
12
+ export function getAllTagPrefixes(workspace) {
13
+ return [workspace.tagPrefix, ...(workspace.legacyIdentities?.map((identity) => identity.tagPrefix) ?? [])];
14
14
  }
15
15
  function escapeRegex(value) {
16
- return value.replace(/[.*+?^${}()|[\]\\]/g, String.raw`\$&`);
16
+ return value.replace(/[.*+?^${}()|[\]\\]/g, String.raw `\$&`);
17
17
  }
18
- export {
19
- buildTagPattern,
20
- getAllTagPrefixes
21
- };
@@ -1,4 +1,4 @@
1
- import type { Commit } from './types.ts';
1
+ import type { Commit } from './types.js';
2
2
  export declare function getCommitsSinceTarget(tagPrefixes: readonly string[], paths?: string[]): {
3
3
  tag: string | undefined;
4
4
  commits: Commit[];
@@ -1,66 +1,65 @@
1
- import { execFileSync } from "node:child_process";
2
- const FIELD_SEPARATOR = "";
1
+ import { execFileSync } from 'node:child_process';
2
+ const FIELD_SEPARATOR = '\u001F';
3
3
  function isNoTagError(err) {
4
- return typeof err === "object" && err !== null && "status" in err && err.status === 128;
4
+ return typeof err === 'object' && err !== null && 'status' in err && err.status === 128;
5
5
  }
6
6
  function errorMessage(err) {
7
- return err instanceof Error ? err.message : String(err);
7
+ return err instanceof Error ? err.message : String(err);
8
8
  }
9
9
  function findLatestTag(tagPrefixes) {
10
- if (tagPrefixes.length === 0) {
11
- throw new Error("findLatestTag: tagPrefixes must contain at least one entry");
12
- }
13
- const matchArgs = tagPrefixes.map((prefix) => `--match=${prefix}*`);
14
- try {
15
- const tagResult = execFileSync("git", ["describe", "--tags", "--abbrev=0", ...matchArgs], {
16
- encoding: "utf8",
17
- stdio: ["pipe", "pipe", "pipe"]
18
- }).trim();
19
- return tagResult || void 0;
20
- } catch (error) {
21
- if (isNoTagError(error)) {
22
- return void 0;
10
+ if (tagPrefixes.length === 0) {
11
+ throw new Error('findLatestTag: tagPrefixes must contain at least one entry');
12
+ }
13
+ const matchArgs = tagPrefixes.map((prefix) => `--match=${prefix}*`);
14
+ try {
15
+ const tagResult = execFileSync('git', ['describe', '--tags', '--abbrev=0', ...matchArgs], {
16
+ encoding: 'utf8',
17
+ stdio: ['pipe', 'pipe', 'pipe'],
18
+ }).trim();
19
+ return tagResult || undefined;
20
+ }
21
+ catch (error) {
22
+ if (isNoTagError(error)) {
23
+ return undefined;
24
+ }
25
+ throw new Error(`Failed to run 'git describe': ${errorMessage(error)}`);
23
26
  }
24
- throw new Error(`Failed to run 'git describe': ${errorMessage(error)}`);
25
- }
26
27
  }
27
- const RELEASE_COMMIT_PREFIX = "release:";
28
+ const RELEASE_COMMIT_PREFIX = 'release:';
28
29
  function parseLogOutput(logOutput) {
29
- const commits = [];
30
- for (const line of logOutput.split("\n")) {
31
- const trimmedLine = line.trim();
32
- if (trimmedLine === "") {
33
- continue;
30
+ const commits = [];
31
+ for (const line of logOutput.split('\n')) {
32
+ const trimmedLine = line.trim();
33
+ if (trimmedLine === '') {
34
+ continue;
35
+ }
36
+ const [message, hash] = trimmedLine.split(FIELD_SEPARATOR);
37
+ if (message !== undefined && hash !== undefined && !message.startsWith(RELEASE_COMMIT_PREFIX)) {
38
+ commits.push({ message, hash });
39
+ }
34
40
  }
35
- const [message, hash] = trimmedLine.split(FIELD_SEPARATOR);
36
- if (message !== void 0 && hash !== void 0 && !message.startsWith(RELEASE_COMMIT_PREFIX)) {
37
- commits.push({ message, hash });
38
- }
39
- }
40
- return commits;
41
+ return commits;
41
42
  }
42
- function getCommitsSinceTarget(tagPrefixes, paths) {
43
- const tag = findLatestTag(tagPrefixes);
44
- const range = tag === void 0 ? "HEAD" : `${tag}..HEAD`;
45
- const format = `%s${FIELD_SEPARATOR}%H`;
46
- const args = ["log", range, `--pretty=format:${format}`];
47
- if (paths !== void 0 && paths.length > 0) {
48
- args.push("--", ...paths);
49
- }
50
- let logOutput;
51
- try {
52
- logOutput = execFileSync("git", args, {
53
- encoding: "utf8",
54
- stdio: ["pipe", "pipe", "pipe"]
55
- }).trim();
56
- } catch (error) {
57
- throw new Error(`Failed to run 'git log' for range '${range}': ${errorMessage(error)}`);
58
- }
59
- if (logOutput === "") {
60
- return { tag, commits: [] };
61
- }
62
- return { tag, commits: parseLogOutput(logOutput) };
43
+ export function getCommitsSinceTarget(tagPrefixes, paths) {
44
+ const tag = findLatestTag(tagPrefixes);
45
+ const range = tag === undefined ? 'HEAD' : `${tag}..HEAD`;
46
+ const format = `%s${FIELD_SEPARATOR}%H`;
47
+ const args = ['log', range, `--pretty=format:${format}`];
48
+ if (paths !== undefined && paths.length > 0) {
49
+ args.push('--', ...paths);
50
+ }
51
+ let logOutput;
52
+ try {
53
+ logOutput = execFileSync('git', args, {
54
+ encoding: 'utf8',
55
+ stdio: ['pipe', 'pipe', 'pipe'],
56
+ }).trim();
57
+ }
58
+ catch (error) {
59
+ throw new Error(`Failed to run 'git log' for range '${range}': ${errorMessage(error)}`);
60
+ }
61
+ if (logOutput === '') {
62
+ return { tag, commits: [] };
63
+ }
64
+ return { tag, commits: parseLogOutput(logOutput) };
63
65
  }
64
- export {
65
- getCommitsSinceTarget
66
- };
@@ -1,42 +1,40 @@
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
- function hasPrettierConfig() {
5
- const cwd = process.cwd();
6
- for (const file of PRETTIER_CONFIG_FILES) {
7
- if (existsSync(path.join(cwd, file))) {
8
- return true;
4
+ export function hasPrettierConfig() {
5
+ const cwd = process.cwd();
6
+ for (const file of PRETTIER_CONFIG_FILES) {
7
+ if (existsSync(path.join(cwd, file))) {
8
+ return true;
9
+ }
9
10
  }
10
- }
11
- return hasPrettierKeyInPackageJson(path.join(cwd, "package.json"));
11
+ return hasPrettierKeyInPackageJson(path.join(cwd, 'package.json'));
12
12
  }
13
13
  function hasPrettierKeyInPackageJson(packageJsonPath) {
14
- if (!existsSync(packageJsonPath)) {
15
- return false;
16
- }
17
- try {
18
- const parsed = JSON.parse(readFileSync(packageJsonPath, "utf8"));
19
- return isRecord(parsed) && "prettier" in parsed;
20
- } catch {
21
- return false;
22
- }
14
+ if (!existsSync(packageJsonPath)) {
15
+ return false;
16
+ }
17
+ try {
18
+ const parsed = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
19
+ return isRecord(parsed) && 'prettier' in parsed;
20
+ }
21
+ catch {
22
+ return false;
23
+ }
23
24
  }
24
25
  const PRETTIER_CONFIG_FILES = [
25
- ".prettierrc",
26
- ".prettierrc.cjs",
27
- ".prettierrc.js",
28
- ".prettierrc.json",
29
- ".prettierrc.json5",
30
- ".prettierrc.mjs",
31
- ".prettierrc.toml",
32
- ".prettierrc.ts",
33
- ".prettierrc.yaml",
34
- ".prettierrc.yml",
35
- "prettier.config.cjs",
36
- "prettier.config.js",
37
- "prettier.config.mjs",
38
- "prettier.config.ts"
26
+ '.prettierrc',
27
+ '.prettierrc.cjs',
28
+ '.prettierrc.js',
29
+ '.prettierrc.json',
30
+ '.prettierrc.json5',
31
+ '.prettierrc.mjs',
32
+ '.prettierrc.toml',
33
+ '.prettierrc.ts',
34
+ '.prettierrc.yaml',
35
+ '.prettierrc.yml',
36
+ 'prettier.config.cjs',
37
+ 'prettier.config.js',
38
+ 'prettier.config.mjs',
39
+ 'prettier.config.ts',
39
40
  ];
40
- export {
41
- hasPrettierConfig
42
- };
@@ -0,0 +1,2 @@
1
+ export declare const prepareHelpText = "\nUsage: release-kit prepare [options]\n\nRun release preparation with automatic workspace discovery.\n\nOptions:\n --dry-run Run without modifying any files\n --bump=major|minor|patch Override the bump type for all workspaces\n --set-version=X.Y.Z Set an explicit version; bypasses commit-derived bumps.\n Requires --only in monorepo mode (rejected when a 'project' block is configured).\n --force Release even when no commits or no bump-worthy commits exist\n since the last tag. In monorepo and project mode, defaults to\n patch when --bump is not given; use --bump=X for a different\n level. In single-package mode, a bare --force is rejected \u2014\n pass --bump=major|minor|patch.\n --no-git-checks, -n Skip the clean-working-tree check\n --only=name1,name2 Only process the named workspaces (comma-separated, monorepo only;\n rejected when a 'project' block is configured)\n --with-release-notes Also write per-workspace release-notes previews under {workspacePath}/docs/\n (docs/README.v{version}.md and docs/RELEASE_NOTES.v{version}.md).\n Recommended .gitignore entry: packages/*/docs/*.v*.md (or docs/*.v*.md).\n --help, -h Show this help message\n";
2
+ export declare function showPrepareHelp(): void;
@@ -0,0 +1,26 @@
1
+ export const prepareHelpText = `
2
+ Usage: release-kit prepare [options]
3
+
4
+ Run release preparation with automatic workspace discovery.
5
+
6
+ Options:
7
+ --dry-run Run without modifying any files
8
+ --bump=major|minor|patch Override the bump type for all workspaces
9
+ --set-version=X.Y.Z Set an explicit version; bypasses commit-derived bumps.
10
+ Requires --only in monorepo mode (rejected when a 'project' block is configured).
11
+ --force Release even when no commits or no bump-worthy commits exist
12
+ since the last tag. In monorepo and project mode, defaults to
13
+ patch when --bump is not given; use --bump=X for a different
14
+ level. In single-package mode, a bare --force is rejected —
15
+ pass --bump=major|minor|patch.
16
+ --no-git-checks, -n Skip the clean-working-tree check
17
+ --only=name1,name2 Only process the named workspaces (comma-separated, monorepo only;
18
+ rejected when a 'project' block is configured)
19
+ --with-release-notes Also write per-workspace release-notes previews under {workspacePath}/docs/
20
+ (docs/README.v{version}.md and docs/RELEASE_NOTES.v{version}.md).
21
+ Recommended .gitignore entry: packages/*/docs/*.v*.md (or docs/*.v*.md).
22
+ --help, -h Show this help message
23
+ `;
24
+ export function showPrepareHelp() {
25
+ console.info(prepareHelpText);
26
+ }
@@ -1,4 +1,4 @@
1
- export { type ChangelogOverrideScope, validateAllChangelogOverrides, type ValidateAllChangelogOverridesInputs, type ValidateAllChangelogOverridesResult, } from './changelogOverrides.ts';
2
- export type { SyncLabelsConfig } from './sync-labels/types.ts';
3
- export type { ReleaseKitConfig } from './types.ts';
4
- export { formatValidateOverridesResult, type ValidateOverridesCommandResult } from './validateOverridesCommand.ts';
1
+ export { type ChangelogOverrideScope, validateAllChangelogOverrides, type ValidateAllChangelogOverridesInputs, type ValidateAllChangelogOverridesResult, } from './changelogOverrides.js';
2
+ export type { SyncLabelsConfig } from './sync-labels/types.js';
3
+ export type { ReleaseKitConfig } from './types.js';
4
+ export { formatValidateOverridesResult, type ValidateOverridesCommandResult } from './validateOverridesCommand.js';
package/dist/esm/index.js CHANGED
@@ -1,8 +1,2 @@
1
- import {
2
- validateAllChangelogOverrides
3
- } from "./changelogOverrides.js";
4
- import { formatValidateOverridesResult } from "./validateOverridesCommand.js";
5
- export {
6
- formatValidateOverridesResult,
7
- validateAllChangelogOverrides
8
- };
1
+ export { validateAllChangelogOverrides, } from "./changelogOverrides.js";
2
+ export { formatValidateOverridesResult } from "./validateOverridesCommand.js";
@@ -1,36 +1,32 @@
1
- import { execSync } from "node:child_process";
2
- import { existsSync, readFileSync } from "node:fs";
1
+ import { execSync } from 'node:child_process';
2
+ import { existsSync, readFileSync } from 'node:fs';
3
3
  import { parseJsonRecord } from "./parseJsonRecord.js";
4
- function isGitRepo() {
5
- try {
6
- execSync("git rev-parse --is-inside-work-tree", { stdio: "pipe" });
7
- return { ok: true };
8
- } catch {
9
- return { ok: false, message: "Not inside a git repository. Run `git init` first." };
10
- }
4
+ export function isGitRepo() {
5
+ try {
6
+ execSync('git rev-parse --is-inside-work-tree', { stdio: 'pipe' });
7
+ return { ok: true };
8
+ }
9
+ catch {
10
+ return { ok: false, message: 'Not inside a git repository. Run `git init` first.' };
11
+ }
11
12
  }
12
- function hasPackageJson() {
13
- if (existsSync("package.json")) {
14
- return { ok: true };
15
- }
16
- return { ok: false, message: "No package.json found. Run `npm init` or `pnpm init` first." };
13
+ export function hasPackageJson() {
14
+ if (existsSync('package.json')) {
15
+ return { ok: true };
16
+ }
17
+ return { ok: false, message: 'No package.json found. Run `npm init` or `pnpm init` first.' };
17
18
  }
18
- function usesPnpm() {
19
- if (existsSync("pnpm-lock.yaml")) {
20
- return { ok: true };
21
- }
22
- const raw = readFileSync("package.json", "utf8");
23
- const pkg = parseJsonRecord(raw);
24
- if (pkg !== void 0 && typeof pkg.packageManager === "string" && pkg.packageManager.startsWith("pnpm")) {
25
- return { ok: true };
26
- }
27
- return {
28
- ok: false,
29
- message: "This project does not appear to use pnpm. A pnpm-lock.yaml or packageManager field is required."
30
- };
19
+ export function usesPnpm() {
20
+ if (existsSync('pnpm-lock.yaml')) {
21
+ return { ok: true };
22
+ }
23
+ const raw = readFileSync('package.json', 'utf8');
24
+ const pkg = parseJsonRecord(raw);
25
+ if (pkg !== undefined && typeof pkg.packageManager === 'string' && pkg.packageManager.startsWith('pnpm')) {
26
+ return { ok: true };
27
+ }
28
+ return {
29
+ ok: false,
30
+ message: 'This project does not appear to use pnpm. A pnpm-lock.yaml or packageManager field is required.',
31
+ };
31
32
  }
32
- export {
33
- hasPackageJson,
34
- isGitRepo,
35
- usesPnpm
36
- };
@@ -1,18 +1,15 @@
1
- import { existsSync, readFileSync } from "node:fs";
1
+ import { existsSync, readFileSync } from 'node:fs';
2
2
  import { parseJsonRecord } from "./parseJsonRecord.js";
3
- function detectRepoType() {
4
- if (existsSync("pnpm-workspace.yaml")) {
5
- return "monorepo";
6
- }
7
- if (existsSync("package.json")) {
8
- const raw = readFileSync("package.json", "utf8");
9
- const pkg = parseJsonRecord(raw);
10
- if (pkg !== void 0 && Array.isArray(pkg.workspaces)) {
11
- return "monorepo";
3
+ export function detectRepoType() {
4
+ if (existsSync('pnpm-workspace.yaml')) {
5
+ return 'monorepo';
12
6
  }
13
- }
14
- return "single-package";
7
+ if (existsSync('package.json')) {
8
+ const raw = readFileSync('package.json', 'utf8');
9
+ const pkg = parseJsonRecord(raw);
10
+ if (pkg !== undefined && Array.isArray(pkg.workspaces)) {
11
+ return 'monorepo';
12
+ }
13
+ }
14
+ return 'single-package';
15
15
  }
16
- export {
17
- detectRepoType
18
- };