@williamthorsen/release-kit 6.0.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 (134) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +3 -3
  3. package/dist/esm/.cache +1 -1
  4. package/dist/esm/assertCleanWorkingTree.js +9 -14
  5. package/dist/esm/bin/release-kit.js +200 -199
  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 -102
  27. package/dist/esm/collectPolicyViolations.d.ts +2 -2
  28. package/dist/esm/collectPolicyViolations.js +11 -14
  29. package/dist/esm/commitCommand.js +48 -46
  30. package/dist/esm/compareVersions.js +20 -23
  31. package/dist/esm/createGithubRelease.js +56 -59
  32. package/dist/esm/createGithubReleaseCommand.js +21 -23
  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.js +4 -8
  55. package/dist/esm/index.d.ts +4 -4
  56. package/dist/esm/index.js +2 -8
  57. package/dist/esm/init/checks.js +28 -32
  58. package/dist/esm/init/detectRepoType.js +12 -15
  59. package/dist/esm/init/initCommand.js +60 -54
  60. package/dist/esm/init/parseJsonRecord.js +9 -11
  61. package/dist/esm/init/scaffold.d.ts +1 -1
  62. package/dist/esm/init/scaffold.js +32 -38
  63. package/dist/esm/init/templates.d.ts +1 -1
  64. package/dist/esm/init/templates.js +16 -22
  65. package/dist/esm/injectReleaseNotesIntoReadme.js +42 -49
  66. package/dist/esm/injectSection.js +17 -27
  67. package/dist/esm/loadConfig.d.ts +1 -1
  68. package/dist/esm/loadConfig.js +206 -225
  69. package/dist/esm/parseCommitMessage.d.ts +1 -1
  70. package/dist/esm/parseCommitMessage.js +72 -76
  71. package/dist/esm/parseRequestedTags.js +6 -9
  72. package/dist/esm/prepareCommand.d.ts +1 -1
  73. package/dist/esm/prepareCommand.js +225 -235
  74. package/dist/esm/previewTagPrefixes.d.ts +1 -1
  75. package/dist/esm/previewTagPrefixes.js +101 -96
  76. package/dist/esm/propagateBumps.d.ts +2 -2
  77. package/dist/esm/propagateBumps.js +48 -50
  78. package/dist/esm/publish.d.ts +2 -2
  79. package/dist/esm/publish.js +22 -28
  80. package/dist/esm/publishCommand.js +75 -80
  81. package/dist/esm/pushCommand.js +33 -34
  82. package/dist/esm/pushRelease.d.ts +1 -1
  83. package/dist/esm/pushRelease.js +21 -24
  84. package/dist/esm/readCurrentVersion.js +13 -17
  85. package/dist/esm/releasePrepare.d.ts +1 -1
  86. package/dist/esm/releasePrepare.js +213 -231
  87. package/dist/esm/releasePrepareMono.d.ts +2 -2
  88. package/dist/esm/releasePrepareMono.js +434 -494
  89. package/dist/esm/releasePrepareProject.d.ts +2 -2
  90. package/dist/esm/releasePrepareProject.js +143 -153
  91. package/dist/esm/renderChangelogMarkdown.d.ts +1 -1
  92. package/dist/esm/renderChangelogMarkdown.js +20 -24
  93. package/dist/esm/renderReleaseNotes.d.ts +1 -1
  94. package/dist/esm/renderReleaseNotes.js +50 -55
  95. package/dist/esm/reportPrepare.d.ts +1 -1
  96. package/dist/esm/reportPrepare.js +230 -231
  97. package/dist/esm/resolveCliffConfigPath.js +18 -23
  98. package/dist/esm/resolveCommandTags.d.ts +1 -1
  99. package/dist/esm/resolveCommandTags.js +47 -45
  100. package/dist/esm/resolveReleaseNotesConfig.d.ts +1 -1
  101. package/dist/esm/resolveReleaseNotesConfig.js +39 -43
  102. package/dist/esm/resolveReleaseTags.d.ts +1 -1
  103. package/dist/esm/resolveReleaseTags.js +39 -40
  104. package/dist/esm/runGitCliff.js +27 -30
  105. package/dist/esm/showTagPrefixesCommand.js +48 -70
  106. package/dist/esm/stripEmojiPrefix.js +2 -5
  107. package/dist/esm/stripScope.js +18 -21
  108. package/dist/esm/sync-labels/generateCommand.d.ts +1 -1
  109. package/dist/esm/sync-labels/generateCommand.js +51 -53
  110. package/dist/esm/sync-labels/initCommand.js +46 -48
  111. package/dist/esm/sync-labels/loadSyncLabelsConfig.d.ts +1 -1
  112. package/dist/esm/sync-labels/loadSyncLabelsConfig.js +46 -52
  113. package/dist/esm/sync-labels/presets.d.ts +1 -1
  114. package/dist/esm/sync-labels/presets.js +40 -43
  115. package/dist/esm/sync-labels/resolveLabels.d.ts +1 -1
  116. package/dist/esm/sync-labels/resolveLabels.js +28 -35
  117. package/dist/esm/sync-labels/syncCommand.js +30 -31
  118. package/dist/esm/sync-labels/templates.d.ts +1 -1
  119. package/dist/esm/sync-labels/templates.js +23 -26
  120. package/dist/esm/sync-labels/types.js +1 -0
  121. package/dist/esm/syncWorkTypes.js +83 -84
  122. package/dist/esm/tagCommand.js +12 -14
  123. package/dist/esm/typeGuards.js +4 -8
  124. package/dist/esm/types.js +66 -60
  125. package/dist/esm/validateConfig.d.ts +1 -1
  126. package/dist/esm/validateConfig.js +109 -115
  127. package/dist/esm/validateOnlyExcludesStrandedDependents.d.ts +2 -2
  128. package/dist/esm/validateOnlyExcludesStrandedDependents.js +97 -91
  129. package/dist/esm/validateOverridesCommand.d.ts +2 -2
  130. package/dist/esm/validateOverridesCommand.js +110 -111
  131. package/dist/esm/workTypesData.js +57 -60
  132. package/dist/esm/workTypesUtils.js +16 -21
  133. package/dist/esm/writeReleaseNotesPreviews.js +55 -57
  134. package/package.json +2 -2
@@ -1,51 +1,53 @@
1
- import { reportError } from "@williamthorsen/nmr-core";
1
+ import { reportError } from '@williamthorsen/nmr-core';
2
2
  import { deriveWorkspaceConfig } from "./deriveWorkspaceConfig.js";
3
3
  import { discoverWorkspaces } from "./discoverWorkspaces.js";
4
4
  import { resolveReleaseTags } from "./resolveReleaseTags.js";
5
- async function resolveCommandTags(tags) {
6
- let discoveredPaths;
7
- try {
8
- discoveredPaths = await discoverWorkspaces();
9
- } catch (error) {
10
- reportError(`Failed to discover workspaces: ${error instanceof Error ? error.message : String(error)}`);
11
- process.exit(1);
12
- }
13
- let workspaces;
14
- let singleWorkspace;
15
- try {
16
- if (discoveredPaths === void 0) {
17
- singleWorkspace = deriveWorkspaceConfig(".");
18
- } else {
19
- workspaces = discoveredPaths.map((workspacePath) => deriveWorkspaceConfig(workspacePath));
20
- }
21
- } catch (error) {
22
- reportError(`Failed to resolve workspaces: ${error instanceof Error ? error.message : String(error)}`);
23
- process.exit(1);
24
- }
25
- let resolvedTags;
26
- if (workspaces !== void 0) {
27
- resolvedTags = resolveReleaseTags({ workspaces });
28
- } else if (singleWorkspace !== void 0) {
29
- resolvedTags = resolveReleaseTags({ singleWorkspace });
30
- } else {
31
- throw new Error("resolveCommandTags: invariant violated \u2014 neither workspaces nor singleWorkspace was derived");
32
- }
33
- if (resolvedTags.length === 0) {
34
- reportError("No release tags found on HEAD. Create tags with `release-kit tag` first.");
35
- process.exit(1);
36
- }
37
- if (tags !== void 0) {
38
- const availableTagNames = resolvedTags.map((t) => t.tag);
39
- for (const name of tags) {
40
- if (!availableTagNames.includes(name)) {
41
- reportError(`Unknown tag "${name}" in --tags. Available: ${availableTagNames.join(", ")}`);
5
+ export async function resolveCommandTags(tags) {
6
+ let discoveredPaths;
7
+ try {
8
+ discoveredPaths = await discoverWorkspaces();
9
+ }
10
+ catch (error) {
11
+ reportError(`Failed to discover workspaces: ${error instanceof Error ? error.message : String(error)}`);
12
+ process.exit(1);
13
+ }
14
+ let workspaces;
15
+ let singleWorkspace;
16
+ try {
17
+ if (discoveredPaths === undefined) {
18
+ singleWorkspace = deriveWorkspaceConfig('.');
19
+ }
20
+ else {
21
+ workspaces = discoveredPaths.map((workspacePath) => deriveWorkspaceConfig(workspacePath));
22
+ }
23
+ }
24
+ catch (error) {
25
+ reportError(`Failed to resolve workspaces: ${error instanceof Error ? error.message : String(error)}`);
26
+ process.exit(1);
27
+ }
28
+ let resolvedTags;
29
+ if (workspaces !== undefined) {
30
+ resolvedTags = resolveReleaseTags({ workspaces });
31
+ }
32
+ else if (singleWorkspace !== undefined) {
33
+ resolvedTags = resolveReleaseTags({ singleWorkspace });
34
+ }
35
+ else {
36
+ throw new Error('resolveCommandTags: invariant violated — neither workspaces nor singleWorkspace was derived');
37
+ }
38
+ if (resolvedTags.length === 0) {
39
+ reportError('No release tags found on HEAD. Create tags with `release-kit tag` first.');
42
40
  process.exit(1);
43
- }
44
41
  }
45
- resolvedTags = resolvedTags.filter((t) => tags.includes(t.tag));
46
- }
47
- return resolvedTags;
42
+ if (tags !== undefined) {
43
+ const availableTagNames = resolvedTags.map((t) => t.tag);
44
+ for (const name of tags) {
45
+ if (!availableTagNames.includes(name)) {
46
+ reportError(`Unknown tag "${name}" in --tags. Available: ${availableTagNames.join(', ')}`);
47
+ process.exit(1);
48
+ }
49
+ }
50
+ resolvedTags = resolvedTags.filter((t) => tags.includes(t.tag));
51
+ }
52
+ return resolvedTags;
48
53
  }
49
- export {
50
- resolveCommandTags
51
- };
@@ -1,4 +1,4 @@
1
- import type { ReleaseNotesConfig } from './types.ts';
1
+ import type { ReleaseNotesConfig } from './types.js';
2
2
  export interface ResolvedReleaseNotesConfig {
3
3
  releaseNotes: ReleaseNotesConfig;
4
4
  changelogJsonOutputPath: string;
@@ -1,51 +1,47 @@
1
- import { reportError } from "@williamthorsen/nmr-core";
1
+ import { reportError } from '@williamthorsen/nmr-core';
2
2
  import { DEFAULT_CHANGELOG_JSON_CONFIG, DEFAULT_RELEASE_NOTES_CONFIG } from "./defaults.js";
3
3
  import { loadConfig, resolveWorkTypes } from "./loadConfig.js";
4
4
  import { validateConfig } from "./validateConfig.js";
5
- async function resolveReleaseNotesConfig(options = {}) {
6
- const { strictLoad = false } = options;
7
- let rawConfig;
8
- try {
9
- rawConfig = await loadConfig();
10
- } catch (error) {
11
- const message = error instanceof Error ? error.message : String(error);
12
- if (strictLoad) {
13
- reportError(`Failed to load config: ${message}`);
14
- process.exit(1);
5
+ export async function resolveReleaseNotesConfig(options = {}) {
6
+ const { strictLoad = false } = options;
7
+ let rawConfig;
8
+ try {
9
+ rawConfig = await loadConfig();
10
+ }
11
+ catch (error) {
12
+ const message = error instanceof Error ? error.message : String(error);
13
+ if (strictLoad) {
14
+ reportError(`Failed to load config: ${message}`);
15
+ process.exit(1);
16
+ }
17
+ console.warn(`Warning: failed to load config; using defaults: ${message}`);
18
+ }
19
+ if (rawConfig === undefined) {
20
+ return {
21
+ releaseNotes: { ...DEFAULT_RELEASE_NOTES_CONFIG },
22
+ changelogJsonOutputPath: DEFAULT_CHANGELOG_JSON_CONFIG.outputPath,
23
+ sectionOrder: deriveSectionOrder(resolveWorkTypes()),
24
+ };
25
+ }
26
+ const { config, errors, warnings } = validateConfig(rawConfig);
27
+ if (errors.length > 0) {
28
+ process.stderr.write('Invalid config:\n');
29
+ for (const err of errors) {
30
+ process.stderr.write(` ❌ ${err}\n`);
31
+ }
32
+ process.exit(1);
33
+ }
34
+ for (const warning of warnings) {
35
+ console.warn(` ⚠️ ${warning}`);
15
36
  }
16
- console.warn(`Warning: failed to load config; using defaults: ${message}`);
17
- }
18
- if (rawConfig === void 0) {
19
37
  return {
20
- releaseNotes: { ...DEFAULT_RELEASE_NOTES_CONFIG },
21
- changelogJsonOutputPath: DEFAULT_CHANGELOG_JSON_CONFIG.outputPath,
22
- sectionOrder: deriveSectionOrder(resolveWorkTypes())
38
+ releaseNotes: {
39
+ shouldInjectIntoReadme: config.releaseNotes?.shouldInjectIntoReadme ?? DEFAULT_RELEASE_NOTES_CONFIG.shouldInjectIntoReadme,
40
+ },
41
+ changelogJsonOutputPath: config.changelogJson?.outputPath ?? DEFAULT_CHANGELOG_JSON_CONFIG.outputPath,
42
+ sectionOrder: deriveSectionOrder(resolveWorkTypes(config.workTypes)),
23
43
  };
24
- }
25
- const { config, errors, warnings } = validateConfig(rawConfig);
26
- if (errors.length > 0) {
27
- process.stderr.write("Invalid config:\n");
28
- for (const err of errors) {
29
- process.stderr.write(` \u274C ${err}
30
- `);
31
- }
32
- process.exit(1);
33
- }
34
- for (const warning of warnings) {
35
- console.warn(` \u26A0\uFE0F ${warning}`);
36
- }
37
- return {
38
- releaseNotes: {
39
- shouldInjectIntoReadme: config.releaseNotes?.shouldInjectIntoReadme ?? DEFAULT_RELEASE_NOTES_CONFIG.shouldInjectIntoReadme
40
- },
41
- changelogJsonOutputPath: config.changelogJson?.outputPath ?? DEFAULT_CHANGELOG_JSON_CONFIG.outputPath,
42
- sectionOrder: deriveSectionOrder(resolveWorkTypes(config.workTypes))
43
- };
44
44
  }
45
- function deriveSectionOrder(workTypes) {
46
- return Object.values(workTypes).map((entry) => entry.header);
45
+ export function deriveSectionOrder(workTypes) {
46
+ return Object.values(workTypes).map((entry) => entry.header);
47
47
  }
48
- export {
49
- deriveSectionOrder,
50
- resolveReleaseNotesConfig
51
- };
@@ -1,4 +1,4 @@
1
- import type { WorkspaceConfig } from './types.ts';
1
+ import type { WorkspaceConfig } from './types.js';
2
2
  export interface ResolvedTag {
3
3
  tag: string;
4
4
  dir: string;
@@ -1,51 +1,50 @@
1
- import { execFileSync } from "node:child_process";
1
+ import { execFileSync } from 'node:child_process';
2
2
  const VERSION_PATTERN = /^v\d+\.\d+\.\d+/;
3
3
  const SEMVER_SUFFIX_PATTERN = /^\d+\.\d+\.\d+/;
4
- function resolveReleaseTags(args) {
5
- const output = execFileSync("git", ["tag", "--points-at", "HEAD"], { encoding: "utf8" });
6
- const tags = output.split("\n").map((line) => line.trim()).filter((line) => line.length > 0);
7
- if (args === void 0) {
8
- return resolveSinglePackageTags(tags);
9
- }
10
- if ("workspaces" in args) {
11
- return resolveMonorepoTags(tags, args.workspaces);
12
- }
13
- return resolveSinglePackageTags(tags, args.singleWorkspace);
4
+ export function resolveReleaseTags(args) {
5
+ const output = execFileSync('git', ['tag', '--points-at', 'HEAD'], { encoding: 'utf8' });
6
+ const tags = output
7
+ .split('\n')
8
+ .map((line) => line.trim())
9
+ .filter((line) => line.length > 0);
10
+ if (args === undefined) {
11
+ return resolveSinglePackageTags(tags);
12
+ }
13
+ if ('workspaces' in args) {
14
+ return resolveMonorepoTags(tags, args.workspaces);
15
+ }
16
+ return resolveSinglePackageTags(tags, args.singleWorkspace);
14
17
  }
15
18
  function resolveSinglePackageTags(tags, singleWorkspace) {
16
- const matched = tags.filter((tag) => VERSION_PATTERN.test(tag));
17
- const isPublishable = singleWorkspace?.isPublishable ?? true;
18
- if (matched.length > 1) {
19
- console.warn(
20
- `Warning: Multiple version tags found on HEAD: ${matched.join(", ")}. Publishing the same package multiple times is almost certainly unintended. Using only the first tag.`
21
- );
22
- return matched.slice(0, 1).map((tag) => ({ tag, dir: ".", workspacePath: ".", isPublishable }));
23
- }
24
- return matched.map((tag) => ({ tag, dir: ".", workspacePath: ".", isPublishable }));
19
+ const matched = tags.filter((tag) => VERSION_PATTERN.test(tag));
20
+ const isPublishable = singleWorkspace?.isPublishable ?? true;
21
+ if (matched.length > 1) {
22
+ console.warn(`Warning: Multiple version tags found on HEAD: ${matched.join(', ')}. ` +
23
+ `Publishing the same package multiple times is almost certainly unintended. Using only the first tag.`);
24
+ return matched.slice(0, 1).map((tag) => ({ tag, dir: '.', workspacePath: '.', isPublishable }));
25
+ }
26
+ return matched.map((tag) => ({ tag, dir: '.', workspacePath: '.', isPublishable }));
25
27
  }
26
28
  function resolveMonorepoTags(tags, workspaces) {
27
- const sortedWorkspaces = [...workspaces].sort((a, b) => b.tagPrefix.length - a.tagPrefix.length);
28
- const resolved = [];
29
- for (const tag of tags) {
30
- const match = findMatchingWorkspace(tag, sortedWorkspaces);
31
- if (match !== void 0) {
32
- resolved.push({ tag, dir: match.dir, workspacePath: match.workspacePath, isPublishable: match.isPublishable });
29
+ const sortedWorkspaces = [...workspaces].sort((a, b) => b.tagPrefix.length - a.tagPrefix.length);
30
+ const resolved = [];
31
+ for (const tag of tags) {
32
+ const match = findMatchingWorkspace(tag, sortedWorkspaces);
33
+ if (match !== undefined) {
34
+ resolved.push({ tag, dir: match.dir, workspacePath: match.workspacePath, isPublishable: match.isPublishable });
35
+ }
33
36
  }
34
- }
35
- return resolved;
37
+ return resolved;
36
38
  }
37
39
  function findMatchingWorkspace(tag, sortedWorkspaces) {
38
- for (const workspace of sortedWorkspaces) {
39
- if (!tag.startsWith(workspace.tagPrefix)) {
40
- continue;
41
- }
42
- const versionSuffix = tag.slice(workspace.tagPrefix.length);
43
- if (SEMVER_SUFFIX_PATTERN.test(versionSuffix)) {
44
- return workspace;
40
+ for (const workspace of sortedWorkspaces) {
41
+ if (!tag.startsWith(workspace.tagPrefix)) {
42
+ continue;
43
+ }
44
+ const versionSuffix = tag.slice(workspace.tagPrefix.length);
45
+ if (SEMVER_SUFFIX_PATTERN.test(versionSuffix)) {
46
+ return workspace;
47
+ }
45
48
  }
46
- }
47
- return void 0;
49
+ return undefined;
48
50
  }
49
- export {
50
- resolveReleaseTags
51
- };
@@ -1,34 +1,31 @@
1
- import { execFileSync } from "node:child_process";
2
- import { copyFileSync, mkdtempSync, rmSync } from "node:fs";
3
- import { tmpdir } from "node:os";
4
- import { join } from "node:path";
5
- function runGitCliff(cliffConfigPath, cliffArgs, stdio) {
6
- let configPath = cliffConfigPath;
7
- let tempDir;
8
- try {
9
- if (cliffConfigPath.endsWith(".template")) {
10
- tempDir = mkdtempSync(join(tmpdir(), "cliff-"));
11
- configPath = join(tempDir, "cliff.toml");
12
- copyFileSync(cliffConfigPath, configPath);
1
+ import { execFileSync } from 'node:child_process';
2
+ import { copyFileSync, mkdtempSync, rmSync } from 'node:fs';
3
+ import { tmpdir } from 'node:os';
4
+ import { join } from 'node:path';
5
+ export function runGitCliff(cliffConfigPath, cliffArgs, stdio) {
6
+ let configPath = cliffConfigPath;
7
+ let tempDir;
8
+ try {
9
+ if (cliffConfigPath.endsWith('.template')) {
10
+ tempDir = mkdtempSync(join(tmpdir(), 'cliff-'));
11
+ configPath = join(tempDir, 'cliff.toml');
12
+ copyFileSync(cliffConfigPath, configPath);
13
+ }
14
+ return execFileSync('npx', ['--prefer-offline', '--yes', 'git-cliff', '--config', configPath, ...cliffArgs], {
15
+ encoding: 'utf8',
16
+ stdio,
17
+ env: { ...process.env, npm_config_progress: 'false' },
18
+ });
13
19
  }
14
- return execFileSync("npx", ["--prefer-offline", "--yes", "git-cliff", "--config", configPath, ...cliffArgs], {
15
- encoding: "utf8",
16
- stdio,
17
- env: { ...process.env, npm_config_progress: "false" }
18
- });
19
- } finally {
20
- if (tempDir !== void 0) {
21
- rmSync(tempDir, { recursive: true, force: true });
20
+ finally {
21
+ if (tempDir !== undefined) {
22
+ rmSync(tempDir, { recursive: true, force: true });
23
+ }
22
24
  }
23
- }
24
25
  }
25
- function refreshGitCliffCache() {
26
- execFileSync("npx", ["--yes", "git-cliff", "--version"], {
27
- stdio: ["ignore", "pipe", "inherit"],
28
- env: { ...process.env, npm_config_progress: "false" }
29
- });
26
+ export function refreshGitCliffCache() {
27
+ execFileSync('npx', ['--yes', 'git-cliff', '--version'], {
28
+ stdio: ['ignore', 'pipe', 'inherit'],
29
+ env: { ...process.env, npm_config_progress: 'false' },
30
+ });
30
31
  }
31
- export {
32
- refreshGitCliffCache,
33
- runGitCliff
34
- };
@@ -1,84 +1,62 @@
1
1
  import { detectRepoType } from "./init/detectRepoType.js";
2
2
  import { previewTagPrefixes } from "./previewTagPrefixes.js";
3
- async function showTagPrefixesCommand() {
4
- if (detectRepoType() === "single-package") {
5
- process.stdout.write(renderSinglePackage());
6
- return 0;
7
- }
8
- const preview = await previewTagPrefixes();
9
- process.stdout.write(renderMonorepo(preview));
10
- return computeExitCode(preview);
3
+ export async function showTagPrefixesCommand() {
4
+ if (detectRepoType() === 'single-package') {
5
+ process.stdout.write(renderSinglePackage());
6
+ return 0;
7
+ }
8
+ const preview = await previewTagPrefixes();
9
+ process.stdout.write(renderMonorepo(preview));
10
+ return computeExitCode(preview);
11
11
  }
12
12
  function renderSinglePackage() {
13
- const lines = [
14
- "Workspace Derived prefix Status",
15
- ". v (single-package mode)",
16
- ""
17
- ];
18
- return lines.join("\n");
13
+ const lines = [
14
+ 'Workspace Derived prefix Status',
15
+ '. v (single-package mode)',
16
+ '',
17
+ ];
18
+ return lines.join('\n');
19
19
  }
20
20
  function renderMonorepo(preview) {
21
- const lines = ["Workspace tag prefixes:", ""];
22
- for (const row of preview.workspaces) {
23
- lines.push(...renderWorkspaceRow(row));
24
- }
25
- if (preview.collisions.length > 0) {
26
- lines.push(
27
- "",
28
- ...preview.collisions.map(
29
- (collision) => `\u26D4 tag prefix collision: '${collision.tagPrefix}' used by ${collision.workspacePaths.join(", ")}`
30
- )
31
- );
32
- }
33
- if (preview.undeclaredCandidates.length > 0) {
34
- lines.push(
35
- "",
36
- "Undeclared tag prefixes:",
37
- "",
38
- ...preview.undeclaredCandidates.map(
39
- (candidate) => ` '${candidate.prefix}' \u2014 ${candidate.tagCount} tags (e.g., ${candidate.exampleTags.join(", ")})`
40
- ),
41
- "",
42
- "Suggested config snippet (adjust `dir` to match your workspace if the guess is wrong, and replace the `name` placeholder with the legacy npm name):",
43
- "",
44
- renderSuggestedSnippet(preview.undeclaredCandidates),
45
- "",
46
- "If the suggested `dir` does not match your workspace, adjust before pasting. Each legacy identity requires a `name` \u2014 replace the `TODO-fill-in-legacy-npm-name` placeholder with the package's prior npm name."
47
- );
48
- }
49
- lines.push("");
50
- return lines.join("\n");
21
+ const lines = ['Workspace tag prefixes:', ''];
22
+ for (const row of preview.workspaces) {
23
+ lines.push(...renderWorkspaceRow(row));
24
+ }
25
+ if (preview.collisions.length > 0) {
26
+ lines.push('', ...preview.collisions.map((collision) => `⛔ tag prefix collision: '${collision.tagPrefix}' used by ${collision.workspacePaths.join(', ')}`));
27
+ }
28
+ if (preview.undeclaredCandidates.length > 0) {
29
+ lines.push('', 'Undeclared tag prefixes:', '', ...preview.undeclaredCandidates.map((candidate) => ` '${candidate.prefix}' — ${candidate.tagCount} tags (e.g., ${candidate.exampleTags.join(', ')})`), '', 'Suggested config snippet (adjust `dir` to match your workspace if the guess is wrong, and replace the `name` placeholder with the legacy npm name):', '', renderSuggestedSnippet(preview.undeclaredCandidates), '', "If the suggested `dir` does not match your workspace, adjust before pasting. Each legacy identity requires a `name` — replace the `TODO-fill-in-legacy-npm-name` placeholder with the package's prior npm name.");
30
+ }
31
+ lines.push('');
32
+ return lines.join('\n');
51
33
  }
52
34
  function renderWorkspaceRow(row) {
53
- const lines = [];
54
- if (row.derivedPrefix === null) {
55
- lines.push(` ${row.workspacePath} \u2014 \u26D4 derivation failed: ${row.derivationError ?? "unknown error"}`);
56
- return lines;
57
- }
58
- const statusMarker = row.derivedTagCount > 0 ? `\u2705 ${row.derivedTagCount} tags` : "\u26A0\uFE0F no existing tags";
59
- lines.push(` ${row.workspacePath} \u2014 derived prefix '${row.derivedPrefix}', ${statusMarker}`);
60
- for (const entry of row.legacyEntries) {
61
- if (entry.tagCount > 0) {
62
- lines.push(` \u2705 ${entry.tagCount} legacy tags with '${entry.prefix}' prefix (recognized)`);
63
- } else {
64
- lines.push(` \u26A0\uFE0F recorded legacy prefix '${entry.prefix}' has no tags`);
35
+ const lines = [];
36
+ if (row.derivedPrefix === null) {
37
+ lines.push(` ${row.workspacePath} — ⛔ derivation failed: ${row.derivationError ?? 'unknown error'}`);
38
+ return lines;
39
+ }
40
+ const statusMarker = row.derivedTagCount > 0 ? `✅ ${row.derivedTagCount} tags` : '⚠️ no existing tags';
41
+ lines.push(` ${row.workspacePath} — derived prefix '${row.derivedPrefix}', ${statusMarker}`);
42
+ for (const entry of row.legacyEntries) {
43
+ if (entry.tagCount > 0) {
44
+ lines.push(` ✅ ${entry.tagCount} legacy tags with '${entry.prefix}' prefix (recognized)`);
45
+ }
46
+ else {
47
+ lines.push(` ⚠️ recorded legacy prefix '${entry.prefix}' has no tags`);
48
+ }
65
49
  }
66
- }
67
- return lines;
50
+ return lines;
68
51
  }
69
52
  function renderSuggestedSnippet(candidates) {
70
- const entries = candidates.map(
71
- (candidate) => ` { dir: '${candidate.suggestedDir}', legacyIdentities: [{ name: 'TODO-fill-in-legacy-npm-name', tagPrefix: '${candidate.prefix}' }] },`
72
- ).join("\n");
73
- return ` workspaces: [
74
- ${entries}
75
- ],`;
53
+ const entries = candidates
54
+ .map((candidate) => ` { dir: '${candidate.suggestedDir}', legacyIdentities: [{ name: 'TODO-fill-in-legacy-npm-name', tagPrefix: '${candidate.prefix}' }] },`)
55
+ .join('\n');
56
+ return ` workspaces: [\n${entries}\n ],`;
76
57
  }
77
58
  function computeExitCode(preview) {
78
- const hasDerivationFailure = preview.workspaces.some((row) => row.derivedPrefix === null);
79
- const hasCollision = preview.collisions.length > 0;
80
- return hasDerivationFailure || hasCollision ? 1 : 0;
59
+ const hasDerivationFailure = preview.workspaces.some((row) => row.derivedPrefix === null);
60
+ const hasCollision = preview.collisions.length > 0;
61
+ return hasDerivationFailure || hasCollision ? 1 : 0;
81
62
  }
82
- export {
83
- showTagPrefixesCommand
84
- };
@@ -1,7 +1,4 @@
1
1
  const LEADING_EMOJI = /^\p{Extended_Pictographic}️? /u;
2
- function stripEmojiPrefix(value) {
3
- return value.replace(LEADING_EMOJI, "");
2
+ export function stripEmojiPrefix(value) {
3
+ return value.replace(LEADING_EMOJI, '');
4
4
  }
5
- export {
6
- stripEmojiPrefix
7
- };
@@ -1,24 +1,21 @@
1
1
  import { COMMIT_PREPROCESSOR_PATTERNS } from "./parseCommitMessage.js";
2
- function stripScope(message) {
3
- let ticketPrefix = "";
4
- let remainder = message;
5
- for (const pattern of COMMIT_PREPROCESSOR_PATTERNS) {
6
- const match = remainder.match(pattern);
7
- if (match) {
8
- ticketPrefix += match[0];
9
- remainder = remainder.slice(match[0].length);
2
+ export function stripScope(message) {
3
+ let ticketPrefix = '';
4
+ let remainder = message;
5
+ for (const pattern of COMMIT_PREPROCESSOR_PATTERNS) {
6
+ const match = remainder.match(pattern);
7
+ if (match) {
8
+ ticketPrefix += match[0];
9
+ remainder = remainder.slice(match[0].length);
10
+ }
10
11
  }
11
- }
12
- const pipeMatch = remainder.match(/^[^|]+\|(.*)$/);
13
- if (pipeMatch) {
14
- return `${ticketPrefix}${pipeMatch[1]}`;
15
- }
16
- const parenMatch = remainder.match(/^(\w+)\([^)]+\)(.*)$/);
17
- if (parenMatch) {
18
- return `${ticketPrefix}${parenMatch[1]}${parenMatch[2]}`;
19
- }
20
- return message;
12
+ const pipeMatch = remainder.match(/^[^|]+\|(.*)$/);
13
+ if (pipeMatch) {
14
+ return `${ticketPrefix}${pipeMatch[1]}`;
15
+ }
16
+ const parenMatch = remainder.match(/^(\w+)\([^)]+\)(.*)$/);
17
+ if (parenMatch) {
18
+ return `${ticketPrefix}${parenMatch[1]}${parenMatch[2]}`;
19
+ }
20
+ return message;
21
21
  }
22
- export {
23
- stripScope
24
- };
@@ -1,4 +1,4 @@
1
- import type { LabelDefinition } from './types.ts';
1
+ import type { LabelDefinition } from './types.js';
2
2
  export declare const LABELS_OUTPUT_PATH = ".github/labels.yaml";
3
3
  export declare function formatLabelsYaml(labels: LabelDefinition[], presetHashes: Map<string, string>): string;
4
4
  export declare function generateCommand(): Promise<number>;