@varlock/bumpy 1.0.0 → 1.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 (35) hide show
  1. package/config-schema.json +327 -0
  2. package/dist/{add-CgCjs4d-.mjs → add-BmNL5VwL.mjs} +21 -11
  3. package/dist/{apply-release-plan-CczGWJTk.mjs → apply-release-plan-0kH62jhu.mjs} +12 -7
  4. package/dist/{bump-file-CCLXMLA8.mjs → bump-file-DVqR3k67.mjs} +24 -10
  5. package/dist/{changelog-github-Cd8uJHZI.mjs → changelog-github-DkACMj0j.mjs} +1 -1
  6. package/dist/check-BjWF6SJm.mjs +65 -0
  7. package/dist/{ci-Bhx--Tj6.mjs → ci-DY58ugIi.mjs} +35 -32
  8. package/dist/{ci-setup-qz4Y3v7T.mjs → ci-setup-BQwktQEe.mjs} +3 -3
  9. package/dist/cli.mjs +20 -27
  10. package/dist/commit-message-BwsowSds.mjs +23 -0
  11. package/dist/{config-XZWUL3ma.mjs → config-B-Qg3DZH.mjs} +4 -3
  12. package/dist/{generate-gYKTpvex.mjs → generate-DX46X-rW.mjs} +73 -64
  13. package/dist/{git-CGHVXXKw.mjs → git-YDedMddc.mjs} +54 -2
  14. package/dist/index.d.mts +13 -2
  15. package/dist/index.mjs +8 -8
  16. package/dist/init-DkTPs_WQ.mjs +196 -0
  17. package/dist/{js-yaml-DpZfOoD4.mjs → package-manager-Clsmr-9r.mjs} +79 -1
  18. package/dist/picomatch-DMmqYjgq.mjs +1870 -0
  19. package/dist/{publish-Cun-zQ1b.mjs → publish-CGB4TIKD.mjs} +10 -10
  20. package/dist/{publish-pipeline-BwBuKCIk.mjs → publish-pipeline-CXuqce1N.mjs} +4 -4
  21. package/dist/{release-plan-Bi5QNSEo.mjs → release-plan-JNir7bSM.mjs} +2 -2
  22. package/dist/{shell-Dj7JRD_q.mjs → shell-CY7OD48z.mjs} +20 -2
  23. package/dist/{status-CfE63ti5.mjs → status-EGYqULJg.mjs} +6 -6
  24. package/dist/{version-19vVt9dv.mjs → version-BcfidiVX.mjs} +13 -16
  25. package/dist/{workspace-C5ULTyUN.mjs → workspace-DWXlwcH4.mjs} +2 -2
  26. package/package.json +4 -1
  27. package/skills/add-change/SKILL.md +11 -3
  28. package/dist/check-BOoxpWqk.mjs +0 -51
  29. package/dist/init-lA9E5pEc.mjs +0 -22
  30. package/dist/migrate-DmOYgmfD.mjs +0 -121
  31. package/dist/package-manager-VCe10bjc.mjs +0 -80
  32. /package/dist/{clack-CDRCHrC-.mjs → clack-C6bVkGxf.mjs} +0 -0
  33. /package/dist/{dep-graph-E-9-eQ2J.mjs → dep-graph-DiLeAhl9.mjs} +0 -0
  34. /package/dist/{names-9VubBmL0.mjs → names-C-TuOPbd.mjs} +0 -0
  35. /package/dist/{semver-DfQyVLM_.mjs → semver-BJzWIuRz.mjs} +0 -0
@@ -1,11 +1,11 @@
1
1
  import { n as log, t as colorize } from "./logger-C2dEe5Su.mjs";
2
- import { a as loadConfig } from "./config-XZWUL3ma.mjs";
3
- import { n as detectWorkspaces } from "./package-manager-VCe10bjc.mjs";
4
- import { n as discoverWorkspace } from "./workspace-C5ULTyUN.mjs";
5
- import { t as DependencyGraph } from "./dep-graph-E-9-eQ2J.mjs";
6
- import { n as runArgsAsync, o as tryRunArgs } from "./shell-Dj7JRD_q.mjs";
7
- import { a as pushWithTags, i as listTags, r as hasUncommittedChanges } from "./git-CGHVXXKw.mjs";
8
- import { t as publishPackages } from "./publish-pipeline-BwBuKCIk.mjs";
2
+ import { a as loadConfig } from "./config-B-Qg3DZH.mjs";
3
+ import { n as detectWorkspaces } from "./package-manager-Clsmr-9r.mjs";
4
+ import { n as discoverWorkspace } from "./workspace-DWXlwcH4.mjs";
5
+ import { t as DependencyGraph } from "./dep-graph-DiLeAhl9.mjs";
6
+ import { r as runArgsAsync, s as tryRunArgs } from "./shell-CY7OD48z.mjs";
7
+ import { a as hasUncommittedChanges, o as listTags, s as pushWithTags } from "./git-YDedMddc.mjs";
8
+ import { t as publishPackages } from "./publish-pipeline-CXuqce1N.mjs";
9
9
  //#region src/core/github-release.ts
10
10
  /** Get the current HEAD commit SHA */
11
11
  function getHeadSha(rootDir) {
@@ -148,7 +148,7 @@ async function publishCommand(rootDir, opts) {
148
148
  }
149
149
  let toPublish = await findUnpublishedPackages(packages, config);
150
150
  if (opts.filter) {
151
- const { matchGlob } = await import("./config-XZWUL3ma.mjs").then((n) => n.t);
151
+ const { matchGlob } = await import("./config-B-Qg3DZH.mjs").then((n) => n.t);
152
152
  const patterns = opts.filter.split(",").map((p) => p.trim());
153
153
  toPublish = toPublish.filter((r) => patterns.some((p) => matchGlob(r.name, p)));
154
154
  }
@@ -169,7 +169,7 @@ async function publishCommand(rootDir, opts) {
169
169
  dryRun: opts.dryRun,
170
170
  tag: opts.tag
171
171
  }, catalogs, detectedPm);
172
- if (result.published.length > 0) log.success(`Published ${result.published.length} package(s)`);
172
+ if (result.published.length > 0) log.success(`🐸 Published ${result.published.length} package(s)`);
173
173
  if (result.skipped.length > 0) log.dim(`Skipped ${result.skipped.length}: ${result.skipped.map((s) => s.name).join(", ")}`);
174
174
  if (result.failed.length > 0) {
175
175
  log.error(`Failed ${result.failed.length}: ${result.failed.map((f) => `${f.name} (${f.error})`).join(", ")}`);
@@ -220,7 +220,7 @@ async function findUnpublishedPackages(packages, _config) {
220
220
  return unpublished;
221
221
  }
222
222
  async function checkIfPublished(name, version, pkgConfig) {
223
- const { runAsync, runArgsAsync, tryRunArgs } = await import("./shell-Dj7JRD_q.mjs").then((n) => n.i);
223
+ const { runAsync, runArgsAsync, tryRunArgs } = await import("./shell-CY7OD48z.mjs").then((n) => n.a);
224
224
  if (pkgConfig?.checkPublished) try {
225
225
  return (await runAsync(pkgConfig.checkPublished)).trim() === version;
226
226
  } catch {
@@ -1,9 +1,9 @@
1
1
  import { n as log, t as colorize } from "./logger-C2dEe5Su.mjs";
2
2
  import { a as readJson, l as updateJsonNestedField } from "./fs-DYR2XuFE.mjs";
3
- import { r as resolveCatalogDep } from "./package-manager-VCe10bjc.mjs";
4
- import { a as sq, n as runArgsAsync, o as tryRunArgs, r as runAsync } from "./shell-Dj7JRD_q.mjs";
5
- import { r as stripProtocol } from "./semver-DfQyVLM_.mjs";
6
- import { o as tagExists, t as createTag } from "./git-CGHVXXKw.mjs";
3
+ import { r as resolveCatalogDep } from "./package-manager-Clsmr-9r.mjs";
4
+ import { i as runAsync, o as sq, r as runArgsAsync, s as tryRunArgs } from "./shell-CY7OD48z.mjs";
5
+ import { r as stripProtocol } from "./semver-BJzWIuRz.mjs";
6
+ import { c as tagExists, t as createTag } from "./git-YDedMddc.mjs";
7
7
  import { resolve } from "node:path";
8
8
  import { unlink } from "node:fs/promises";
9
9
  import { appendFileSync, existsSync, readFileSync, writeFileSync } from "node:fs";
@@ -1,5 +1,5 @@
1
- import { h as maxBump, l as DEFAULT_BUMP_RULES, m as hasCascade, p as bumpLevel, s as matchGlob } from "./config-XZWUL3ma.mjs";
2
- import { n as satisfies, t as bumpVersion } from "./semver-DfQyVLM_.mjs";
1
+ import { h as maxBump, l as DEFAULT_BUMP_RULES, m as hasCascade, p as bumpLevel, s as matchGlob } from "./config-B-Qg3DZH.mjs";
2
+ import { n as satisfies, t as bumpVersion } from "./semver-BJzWIuRz.mjs";
3
3
  //#region src/core/release-plan.ts
4
4
  /**
5
5
  * Build a release plan from pending bump files, the dependency graph, and config.
@@ -1,7 +1,8 @@
1
1
  import { a as __exportAll } from "./logger-C2dEe5Su.mjs";
2
- import { exec, execFile, execFileSync } from "node:child_process";
2
+ import { exec, execFile, execFileSync, execSync } from "node:child_process";
3
3
  //#region src/utils/shell.ts
4
4
  var shell_exports = /* @__PURE__ */ __exportAll({
5
+ run: () => run,
5
6
  runArgs: () => runArgs,
6
7
  runArgsAsync: () => runArgsAsync,
7
8
  runAsync: () => runAsync,
@@ -19,6 +20,23 @@ function sq(value) {
19
20
  function checkIntercept(args, opts) {
20
21
  return null;
21
22
  }
23
+ function run(cmd, opts) {
24
+ const result = checkIntercept(cmd.split(/\s+/), opts);
25
+ if (result?.intercepted) {
26
+ if ("error" in result) throw new Error(result.error);
27
+ return result.result;
28
+ }
29
+ return execSync(cmd, {
30
+ cwd: opts?.cwd,
31
+ input: opts?.input,
32
+ encoding: "utf-8",
33
+ stdio: [
34
+ opts?.input ? "pipe" : "pipe",
35
+ "pipe",
36
+ "pipe"
37
+ ]
38
+ }).trim();
39
+ }
22
40
  function runAsync(cmd, opts) {
23
41
  const result = checkIntercept(cmd.split(/\s+/), opts);
24
42
  if (result?.intercepted) {
@@ -89,4 +107,4 @@ function tryRunArgs(args, opts) {
89
107
  }
90
108
  }
91
109
  //#endregion
92
- export { sq as a, shell_exports as i, runArgsAsync as n, tryRunArgs as o, runAsync as r, runArgs as t };
110
+ export { shell_exports as a, runAsync as i, runArgs as n, sq as o, runArgsAsync as r, tryRunArgs as s, run as t };
@@ -1,9 +1,9 @@
1
1
  import { n as log, t as colorize } from "./logger-C2dEe5Su.mjs";
2
- import { a as loadConfig } from "./config-XZWUL3ma.mjs";
3
- import { t as discoverPackages } from "./workspace-C5ULTyUN.mjs";
4
- import { t as DependencyGraph } from "./dep-graph-E-9-eQ2J.mjs";
5
- import { r as readBumpFiles } from "./bump-file-CCLXMLA8.mjs";
6
- import { t as assembleReleasePlan } from "./release-plan-Bi5QNSEo.mjs";
2
+ import { a as loadConfig } from "./config-B-Qg3DZH.mjs";
3
+ import { t as discoverPackages } from "./workspace-DWXlwcH4.mjs";
4
+ import { t as DependencyGraph } from "./dep-graph-DiLeAhl9.mjs";
5
+ import { r as readBumpFiles } from "./bump-file-DVqR3k67.mjs";
6
+ import { t as assembleReleasePlan } from "./release-plan-JNir7bSM.mjs";
7
7
  //#region src/commands/status.ts
8
8
  async function statusCommand(rootDir, opts) {
9
9
  const config = await loadConfig(rootDir);
@@ -26,7 +26,7 @@ async function statusCommand(rootDir, opts) {
26
26
  releases = releases.filter((r) => types.includes(r.type));
27
27
  }
28
28
  if (opts.filter) {
29
- const { matchGlob } = await import("./config-XZWUL3ma.mjs").then((n) => n.t);
29
+ const { matchGlob } = await import("./config-B-Qg3DZH.mjs").then((n) => n.t);
30
30
  const patterns = opts.filter.split(",").map((p) => p.trim());
31
31
  releases = releases.filter((r) => patterns.some((p) => matchGlob(r.name, p)));
32
32
  }
@@ -1,14 +1,15 @@
1
1
  import { n as log, t as colorize } from "./logger-C2dEe5Su.mjs";
2
- import { a as loadConfig } from "./config-XZWUL3ma.mjs";
3
- import { n as detectWorkspaces } from "./package-manager-VCe10bjc.mjs";
4
- import { t as discoverPackages } from "./workspace-C5ULTyUN.mjs";
5
- import { t as DependencyGraph } from "./dep-graph-E-9-eQ2J.mjs";
6
- import { o as tryRunArgs, t as runArgs } from "./shell-Dj7JRD_q.mjs";
7
- import { r as readBumpFiles } from "./bump-file-CCLXMLA8.mjs";
8
- import { t as assembleReleasePlan } from "./release-plan-Bi5QNSEo.mjs";
9
- import { t as applyReleasePlan } from "./apply-release-plan-CczGWJTk.mjs";
2
+ import { a as loadConfig } from "./config-B-Qg3DZH.mjs";
3
+ import { n as detectWorkspaces } from "./package-manager-Clsmr-9r.mjs";
4
+ import { t as discoverPackages } from "./workspace-DWXlwcH4.mjs";
5
+ import { t as DependencyGraph } from "./dep-graph-DiLeAhl9.mjs";
6
+ import { n as runArgs, s as tryRunArgs } from "./shell-CY7OD48z.mjs";
7
+ import { r as readBumpFiles } from "./bump-file-DVqR3k67.mjs";
8
+ import { t as assembleReleasePlan } from "./release-plan-JNir7bSM.mjs";
9
+ import { t as applyReleasePlan } from "./apply-release-plan-0kH62jhu.mjs";
10
+ import { t as resolveCommitMessage } from "./commit-message-BwsowSds.mjs";
10
11
  //#region src/commands/version.ts
11
- async function versionCommand(rootDir) {
12
+ async function versionCommand(rootDir, opts = {}) {
12
13
  const config = await loadConfig(rootDir);
13
14
  const packages = await discoverPackages(rootDir, config);
14
15
  const depGraph = new DependencyGraph(packages);
@@ -32,10 +33,10 @@ async function versionCommand(rootDir) {
32
33
  console.log(` ${r.name}: ${r.oldVersion} → ${colorize(r.newVersion, "cyan")}${tag}`);
33
34
  }
34
35
  await applyReleasePlan(plan, packages, rootDir, config);
35
- log.success(`Updated ${plan.releases.length} package(s)`);
36
+ log.success(`🐸 Updated ${plan.releases.length} package(s)`);
36
37
  log.dim(` Deleted ${bumpFiles.length} bump file(s)`);
37
38
  await updateLockfile(rootDir);
38
- if (config.commit) try {
39
+ if (opts.commit) try {
39
40
  runArgs([
40
41
  "git",
41
42
  "add",
@@ -76,11 +77,7 @@ async function versionCommand(rootDir) {
76
77
  "-"
77
78
  ], {
78
79
  cwd: rootDir,
79
- input: [
80
- "Version packages",
81
- "",
82
- ...plan.releases.map((r) => `${r.name}@${r.newVersion}`)
83
- ].join("\n")
80
+ input: await resolveCommitMessage(config.versionCommitMessage, plan, rootDir)
84
81
  });
85
82
  log.success("Created git commit");
86
83
  } catch (e) {
@@ -1,6 +1,6 @@
1
1
  import { a as readJson, n as exists } from "./fs-DYR2XuFE.mjs";
2
- import { i as isPackageManaged, o as loadPackageConfig } from "./config-XZWUL3ma.mjs";
3
- import { n as detectWorkspaces } from "./package-manager-VCe10bjc.mjs";
2
+ import { i as isPackageManaged, o as loadPackageConfig } from "./config-B-Qg3DZH.mjs";
3
+ import { n as detectWorkspaces } from "./package-manager-Clsmr-9r.mjs";
4
4
  import { relative, resolve } from "node:path";
5
5
  import { readdir, stat } from "node:fs/promises";
6
6
  //#region src/core/workspace.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@varlock/bumpy",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Modern monorepo versioning and changelog tool",
5
5
  "keywords": [
6
6
  "bump",
@@ -24,6 +24,7 @@
24
24
  },
25
25
  "files": [
26
26
  "dist",
27
+ "config-schema.json",
27
28
  ".claude-plugin",
28
29
  "skills"
29
30
  ],
@@ -43,9 +44,11 @@
43
44
  "@clack/prompts": "^1.2.0",
44
45
  "@types/bun": "latest",
45
46
  "@types/js-yaml": "^4.0.9",
47
+ "@types/picomatch": "^4.0.3",
46
48
  "@types/semver": "^7.7.0",
47
49
  "js-yaml": "^4.1.0",
48
50
  "picocolors": "^1.1.1",
51
+ "picomatch": "^4.0.4",
49
52
  "semver": "^7.7.2",
50
53
  "tsdown": "^0.21.8"
51
54
  }
@@ -47,15 +47,22 @@ Use `none` in a bump file to suppress a bump on a package that would otherwise b
47
47
 
48
48
  ### 4. Write a clear summary
49
49
 
50
- Write a concise summary (1-3 sentences) describing **what** changed and **why**. This becomes the CHANGELOG entry. Good summaries:
50
+ Write a concise summary for the CHANGELOG entry. Keep it short ideally a single sentence, at most two. Good summaries:
51
51
 
52
52
  - Start with a verb: "Added...", "Fixed...", "Refactored..."
53
53
  - Focus on user-facing impact, not implementation details
54
54
  - Are specific enough to be useful months later
55
+ - Avoid filler, jargon, or restating the bump level
56
+ - Don't list every file changed — describe the logical change
55
57
 
56
- ### 5. Create the bump file
58
+ Bad: "Updated the authentication module to fix an issue where the token refresh mechanism was not properly handling expired refresh tokens, causing silent failures in the auth flow."
59
+ Good: "Fixed token refresh failing silently on expired refresh tokens."
57
60
 
58
- Use the non-interactive CLI:
61
+ ### 5. Create or update the bump file
62
+
63
+ Check if there are already bump files on this branch (from step 1's `bumpy status`). If one exists that covers the same logical change, **update it in place** by editing the `.bumpy/<name>.md` file directly — adjust the package list, bump levels, and summary to reflect the current state of the branch. Don't create a new bump file for every incremental change on the same branch.
64
+
65
+ If no relevant bump file exists yet, create one with the non-interactive CLI:
59
66
 
60
67
  ```bash
61
68
  bumpy add \
@@ -102,3 +109,4 @@ EOF
102
109
  - If the user hasn't made any changes yet, ask what they're planning to change
103
110
  - If the change doesn't affect any publishable packages (e.g., only root config files), suggest using `bumpy add --empty` to satisfy CI checks
104
111
  - One bump file per logical change — don't combine unrelated changes
112
+ - **Keep bump files up to date** — as work continues on a branch, the bump file should reflect the final state of all changes, not just the first commit. If packages were added/removed or the bump level changed (e.g., a patch fix grew into a minor feature), update the existing bump file accordingly
@@ -1,51 +0,0 @@
1
- import { n as log, t as colorize } from "./logger-C2dEe5Su.mjs";
2
- import { a as loadConfig } from "./config-XZWUL3ma.mjs";
3
- import { n as discoverWorkspace } from "./workspace-C5ULTyUN.mjs";
4
- import { r as readBumpFiles } from "./bump-file-CCLXMLA8.mjs";
5
- import { n as getChangedFiles } from "./git-CGHVXXKw.mjs";
6
- import { relative } from "node:path";
7
- //#region src/commands/check.ts
8
- /**
9
- * Local check: detect which packages have changed on this branch
10
- * and verify they have corresponding bump files.
11
- * Designed for pre-push hooks — no GitHub API needed.
12
- */
13
- async function checkCommand(rootDir) {
14
- const config = await loadConfig(rootDir);
15
- const { packages } = await discoverWorkspace(rootDir, config);
16
- const bumpFiles = await readBumpFiles(rootDir);
17
- const coveredPackages = /* @__PURE__ */ new Set();
18
- for (const bf of bumpFiles) for (const release of bf.releases) coveredPackages.add(release.name);
19
- const baseBranch = config.baseBranch;
20
- const changedFiles = getChangedFiles(rootDir, baseBranch);
21
- if (changedFiles.length === 0) {
22
- log.info("No changed files detected.");
23
- return;
24
- }
25
- const changedPackages = findChangedPackages(changedFiles, packages, rootDir);
26
- if (changedPackages.length === 0) {
27
- log.info("No managed packages have changed.");
28
- return;
29
- }
30
- const missing = changedPackages.filter((name) => !coveredPackages.has(name));
31
- if (missing.length === 0) {
32
- log.success(`All ${changedPackages.length} changed package(s) have bump files.`);
33
- return;
34
- }
35
- log.warn(`${missing.length} changed package(s) missing bump files:\n`);
36
- for (const name of missing) console.log(` ${colorize(name, "yellow")}`);
37
- console.log();
38
- log.dim("Run `bumpy add` to create a bump file, or `bumpy add --empty` if no release is needed.");
39
- process.exit(1);
40
- }
41
- /** Map changed files to the packages they belong to */
42
- function findChangedPackages(changedFiles, packages, rootDir) {
43
- const changed = /* @__PURE__ */ new Set();
44
- for (const file of changedFiles) for (const [name, pkg] of packages) {
45
- const pkgRelDir = relative(rootDir, pkg.dir);
46
- if (file.startsWith(pkgRelDir + "/")) changed.add(name);
47
- }
48
- return [...changed];
49
- }
50
- //#endregion
51
- export { checkCommand };
@@ -1,22 +0,0 @@
1
- import { n as log } from "./logger-C2dEe5Su.mjs";
2
- import { d as writeText, n as exists, t as ensureDir, u as writeJson } from "./fs-DYR2XuFE.mjs";
3
- import { resolve } from "node:path";
4
- //#region src/commands/init.ts
5
- async function initCommand(rootDir) {
6
- const bumpyDir = resolve(rootDir, ".bumpy");
7
- if (await exists(resolve(bumpyDir, "_config.json"))) {
8
- log.warn(".bumpy/_config.json already exists");
9
- return;
10
- }
11
- await ensureDir(bumpyDir);
12
- await writeJson(resolve(bumpyDir, "_config.json"), {
13
- baseBranch: "main",
14
- changelog: "default"
15
- });
16
- await writeText(resolve(bumpyDir, "README.md"), `# 🐸 Bumpy\n\nThis directory is used by [bumpy](https://github.com/dmno-dev/bumpy) to manage versioning.\n\nBump files (\`.md\`) in this directory describe pending version bumps.\nRun \`bumpy add\` to create a new bump file.\n`);
17
- log.success("Initialized .bumpy/ directory");
18
- log.dim(" Created .bumpy/_config.json");
19
- log.dim(" Created .bumpy/README.md");
20
- }
21
- //#endregion
22
- export { initCommand };
@@ -1,121 +0,0 @@
1
- import { n as log, o as __toESM, r as require_picocolors } from "./logger-C2dEe5Su.mjs";
2
- import { a as readJson, n as exists, o as readText } from "./fs-DYR2XuFE.mjs";
3
- import { r as getBumpyDir } from "./config-XZWUL3ma.mjs";
4
- import { i as writeBumpFile } from "./bump-file-CCLXMLA8.mjs";
5
- import { a as fe, c as ot, n as O, o as gt, s as mt, t as unwrap } from "./clack-CDRCHrC-.mjs";
6
- import { initCommand } from "./init-lA9E5pEc.mjs";
7
- import { resolve } from "node:path";
8
- import { readdir } from "node:fs/promises";
9
- //#region src/commands/migrate.ts
10
- var import_picocolors = /* @__PURE__ */ __toESM(require_picocolors(), 1);
11
- async function migrateCommand(rootDir, opts) {
12
- const changesetDir = resolve(rootDir, ".changeset");
13
- if (!await exists(changesetDir)) {
14
- log.error("No .changeset/ directory found. Nothing to migrate.");
15
- process.exit(1);
16
- }
17
- const bumpyDir = getBumpyDir(rootDir);
18
- if (!await exists(resolve(bumpyDir, "_config.json"))) {
19
- log.step("Initializing .bumpy/ directory...");
20
- await initCommand(rootDir);
21
- }
22
- const changesetConfigPath = resolve(changesetDir, "config.json");
23
- if (await exists(changesetConfigPath)) {
24
- log.step("Migrating config from .changeset/config.json...");
25
- await migrateConfig(changesetConfigPath, bumpyDir);
26
- }
27
- const mdFiles = (await readdir(changesetDir)).filter((f) => f.endsWith(".md") && f !== "README.md");
28
- if (mdFiles.length > 0) {
29
- log.step(`Migrating ${mdFiles.length} pending changeset(s) to bump files...`);
30
- let migrated = 0;
31
- for (const file of mdFiles) {
32
- const result = parseChangesetFile(await readText(resolve(changesetDir, file)));
33
- if (!result) {
34
- log.warn(` Skipped ${file} (could not parse)`);
35
- continue;
36
- }
37
- const name = file.replace(/\.md$/, "");
38
- if (await exists(resolve(bumpyDir, file))) {
39
- log.dim(` Skipped ${file} (already exists in .bumpy/)`);
40
- continue;
41
- }
42
- await writeBumpFile(rootDir, name, result.releases, result.summary);
43
- migrated++;
44
- log.dim(` Migrated ${file}`);
45
- }
46
- log.success(`Migrated ${migrated} bump file(s)`);
47
- } else log.info("No pending changesets to migrate.");
48
- if (!opts.force) {
49
- mt(import_picocolors.default.bgCyan(import_picocolors.default.black(" bumpy migrate ")));
50
- if (unwrap(await ot({
51
- message: "Remove .changeset/ directory?",
52
- initialValue: false
53
- }))) {
54
- const spin = fe();
55
- spin.start("Removing .changeset/");
56
- const { rm } = await import("node:fs/promises");
57
- await rm(changesetDir, { recursive: true });
58
- spin.stop("Removed .changeset/ directory");
59
- } else O.info("Keeping .changeset/ — you can remove it manually when ready.");
60
- gt(import_picocolors.default.green("Cleanup complete"));
61
- }
62
- console.log();
63
- log.success("Migration complete!");
64
- log.dim("Review .bumpy/_config.json and adjust settings as needed.");
65
- log.dim("Key differences from changesets:");
66
- log.dim(" - Out-of-range peer dep bumps match the triggering bump level (not always major)");
67
- log.dim(" - Use 'none' in a bump file to suppress a propagated bump");
68
- log.dim(" - Per-package config goes in package.json[\"bumpy\"]");
69
- }
70
- async function migrateConfig(changesetConfigPath, bumpyDir) {
71
- const csConfig = await readJson(changesetConfigPath);
72
- const bumpyConfigPath = resolve(bumpyDir, "_config.json");
73
- let bumpyConfig = {};
74
- if (await exists(bumpyConfigPath)) bumpyConfig = await readJson(bumpyConfigPath);
75
- for (const field of [
76
- "baseBranch",
77
- "access",
78
- "commit",
79
- "fixed",
80
- "linked",
81
- "ignore",
82
- "updateInternalDependencies",
83
- "privatePackages"
84
- ]) if (csConfig[field] !== void 0) bumpyConfig[field] = csConfig[field];
85
- const { writeJson } = await import("./fs-DYR2XuFE.mjs").then((n) => n.r);
86
- await writeJson(bumpyConfigPath, bumpyConfig);
87
- log.dim(" Migrated config fields: " + Object.keys(bumpyConfig).filter((k) => k !== "baseBranch" || bumpyConfig[k] !== "main").join(", "));
88
- }
89
- /** Parse a changesets-format markdown file */
90
- function parseChangesetFile(content) {
91
- const match = content.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
92
- if (!match) return null;
93
- const frontmatter = match[1].trim();
94
- const summary = match[2].trim();
95
- if (!frontmatter) return null;
96
- const releases = [];
97
- for (const line of frontmatter.split("\n")) {
98
- const trimmed = line.trim();
99
- if (!trimmed) continue;
100
- const lineMatch = trimmed.match(/^"?([^"]+)"?\s*:\s*(.+)$/);
101
- if (!lineMatch) continue;
102
- const name = lineMatch[1].trim();
103
- const type = lineMatch[2].trim();
104
- if (type === "none") continue;
105
- if ([
106
- "major",
107
- "minor",
108
- "patch"
109
- ].includes(type)) releases.push({
110
- name,
111
- type
112
- });
113
- }
114
- if (releases.length === 0 && !summary) return null;
115
- return {
116
- releases,
117
- summary
118
- };
119
- }
120
- //#endregion
121
- export { migrateCommand };
@@ -1,80 +0,0 @@
1
- import { a as readJson, n as exists, o as readText } from "./fs-DYR2XuFE.mjs";
2
- import { t as jsYaml } from "./js-yaml-DpZfOoD4.mjs";
3
- import { resolve } from "node:path";
4
- //#region src/utils/package-manager.ts
5
- /** Detect the package manager, extract workspace globs, and load catalogs */
6
- async function detectWorkspaces(rootDir) {
7
- const pm = await detectPackageManager(rootDir);
8
- return {
9
- packageManager: pm,
10
- globs: await getWorkspaceGlobs(rootDir, pm),
11
- catalogs: await loadCatalogs(rootDir, pm)
12
- };
13
- }
14
- async function detectPackageManager(rootDir) {
15
- if (await exists(resolve(rootDir, "bun.lock")) || await exists(resolve(rootDir, "bun.lockb"))) return "bun";
16
- if (await exists(resolve(rootDir, "pnpm-lock.yaml"))) return "pnpm";
17
- if (await exists(resolve(rootDir, "yarn.lock"))) return "yarn";
18
- try {
19
- const pkg = await readJson(resolve(rootDir, "package.json"));
20
- if (typeof pkg.packageManager === "string") {
21
- const name = pkg.packageManager.split("@")[0];
22
- if (name === "pnpm" || name === "yarn" || name === "bun") return name;
23
- }
24
- } catch {}
25
- return "npm";
26
- }
27
- async function getWorkspaceGlobs(rootDir, pm) {
28
- if (pm === "pnpm") {
29
- const wsFile = resolve(rootDir, "pnpm-workspace.yaml");
30
- if (await exists(wsFile)) {
31
- const content = await readText(wsFile);
32
- const parsed = jsYaml.load(content);
33
- if (parsed?.packages) return parsed.packages;
34
- }
35
- }
36
- try {
37
- const workspaces = (await readJson(resolve(rootDir, "package.json"))).workspaces;
38
- if (Array.isArray(workspaces)) return workspaces;
39
- if (workspaces && typeof workspaces === "object" && "packages" in workspaces) {
40
- const pkgs = workspaces.packages;
41
- if (Array.isArray(pkgs)) return pkgs;
42
- }
43
- } catch {}
44
- return [];
45
- }
46
- /** Load catalog definitions from pnpm-workspace.yaml or root package.json */
47
- async function loadCatalogs(rootDir, pm) {
48
- const catalogs = /* @__PURE__ */ new Map();
49
- if (pm === "pnpm") {
50
- const wsFile = resolve(rootDir, "pnpm-workspace.yaml");
51
- if (await exists(wsFile)) {
52
- const content = await readText(wsFile);
53
- const parsed = jsYaml.load(content);
54
- if (parsed?.catalog) catalogs.set("", parsed.catalog);
55
- if (parsed?.catalogs) for (const [name, deps] of Object.entries(parsed.catalogs)) catalogs.set(name, deps);
56
- }
57
- }
58
- try {
59
- const pkg = await readJson(resolve(rootDir, "package.json"));
60
- if (pkg.catalog && typeof pkg.catalog === "object") catalogs.set("", pkg.catalog);
61
- if (pkg.catalogs && typeof pkg.catalogs === "object") for (const [name, deps] of Object.entries(pkg.catalogs)) catalogs.set(name, deps);
62
- const workspaces = pkg.workspaces;
63
- if (workspaces && typeof workspaces === "object" && !Array.isArray(workspaces)) {
64
- const ws = workspaces;
65
- if (ws.catalog && typeof ws.catalog === "object") catalogs.set("", ws.catalog);
66
- if (ws.catalogs && typeof ws.catalogs === "object") for (const [name, deps] of Object.entries(ws.catalogs)) catalogs.set(name, deps);
67
- }
68
- } catch {}
69
- return catalogs;
70
- }
71
- /** Resolve a specific dependency's catalog: reference */
72
- function resolveCatalogDep(depName, range, catalogs) {
73
- if (!range.startsWith("catalog:")) return null;
74
- const catalogName = range.slice(8).trim() || "";
75
- const catalog = catalogs.get(catalogName);
76
- if (!catalog) return null;
77
- return catalog[depName] ?? null;
78
- }
79
- //#endregion
80
- export { detectWorkspaces as n, resolveCatalogDep as r, detectPackageManager as t };
File without changes
File without changes