@varlock/bumpy 0.0.1 → 0.0.2

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 (38) hide show
  1. package/dist/add-BjyVIUlr.mjs +175 -0
  2. package/dist/{ai-B8ZL2x8z.mjs → ai-CQhUyHAG.mjs} +2 -2
  3. package/dist/{apply-release-plan-DtU3rVyL.mjs → apply-release-plan-D6TSrcwX.mjs} +11 -6
  4. package/dist/changelog-github-Du62krXi.mjs +193 -0
  5. package/dist/{changeset-ClCYsChu.mjs → changeset-UCZdSRDv.mjs} +36 -3
  6. package/dist/{check-CkRubvuk.mjs → check-jIwike9F.mjs} +5 -11
  7. package/dist/ci-D6LQbR38.mjs +585 -0
  8. package/dist/ci-setup-C6FlOfW5.mjs +211 -0
  9. package/dist/clack-CDRCHrC-.mjs +1216 -0
  10. package/dist/cli.mjs +20 -16
  11. package/dist/{config-CJ2orhTL.mjs → config-BkwIEaQg.mjs} +2 -2
  12. package/dist/{fs-DbNNEyzq.mjs → fs-0AtnPUUe.mjs} +1 -1
  13. package/dist/{generate-oOFD9ABC.mjs → generate-Btrsn1qi.mjs} +28 -9
  14. package/dist/git-CGHVXXKw.mjs +78 -0
  15. package/dist/index.d.mts +10 -2
  16. package/dist/index.mjs +8 -8
  17. package/dist/{init-Blw2GfC_.mjs → init-B0q3wEQW.mjs} +2 -2
  18. package/dist/logger-C2dEe5Su.mjs +135 -0
  19. package/dist/{migrate-DvOrXSw0.mjs → migrate-CfQNwD0T.mjs} +18 -11
  20. package/dist/{names-C-u50ofE.mjs → names-Ck8cun7B.mjs} +2 -1
  21. package/dist/package-manager-DcI5TdDE.mjs +80 -0
  22. package/dist/{publish-DZ3m7qkX.mjs → publish-D_7RqEYL.mjs} +74 -20
  23. package/dist/{publish-pipeline-1M5GmbdP.mjs → publish-pipeline-ChnqW8nR.mjs} +40 -54
  24. package/dist/{release-plan-CFnutSHD.mjs → release-plan-BEzwApuK.mjs} +2 -2
  25. package/dist/{semver-DWO6NFKN.mjs → semver-BTzYh8vc.mjs} +1 -1
  26. package/dist/shell-Dj7JRD_q.mjs +92 -0
  27. package/dist/{status-DRpq_Mha.mjs → status--Q8yAxQ4.mjs} +7 -7
  28. package/dist/{version-CJwf8XIA.mjs → version-cAUkfYPx.mjs} +60 -21
  29. package/dist/workspace-CxEKakDm.mjs +107 -0
  30. package/package.json +4 -2
  31. package/dist/add-u5V9V3L7.mjs +0 -131
  32. package/dist/changelog-github-n-3zV1p9.mjs +0 -59
  33. package/dist/ci-8KWWhjXl.mjs +0 -224
  34. package/dist/logger-ZqggsyGZ.mjs +0 -176
  35. package/dist/prompt-BP8toAOI.mjs +0 -46
  36. package/dist/shell-DPlltpzb.mjs +0 -44
  37. package/dist/workspace-mVjawG8g.mjs +0 -183
  38. /package/dist/{dep-graph-DiLeAhl9.mjs → dep-graph-E-9-eQ2J.mjs} +0 -0
@@ -1,16 +1,27 @@
1
- import { n as log, t as colorize } from "./logger-ZqggsyGZ.mjs";
2
- import { a as loadConfig } from "./config-CJ2orhTL.mjs";
3
- import { n as discoverWorkspace, r as detectWorkspaces } from "./workspace-mVjawG8g.mjs";
4
- import { t as DependencyGraph } from "./dep-graph-DiLeAhl9.mjs";
5
- import { i as tryRun, n as runAsync } from "./shell-DPlltpzb.mjs";
6
- import { n as hasUncommittedChanges, r as pushWithTags, t as publishPackages } from "./publish-pipeline-1M5GmbdP.mjs";
1
+ import { n as log, t as colorize } from "./logger-C2dEe5Su.mjs";
2
+ import { a as loadConfig } from "./config-BkwIEaQg.mjs";
3
+ import { n as detectWorkspaces } from "./package-manager-DcI5TdDE.mjs";
4
+ import { n as discoverWorkspace } from "./workspace-CxEKakDm.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-ChnqW8nR.mjs";
7
9
  //#region src/core/github-release.ts
10
+ /** Get the current HEAD commit SHA */
11
+ function getHeadSha(rootDir) {
12
+ return tryRunArgs([
13
+ "git",
14
+ "rev-parse",
15
+ "HEAD"
16
+ ], { cwd: rootDir });
17
+ }
8
18
  /** Create individual GitHub releases for each published package */
9
19
  async function createIndividualReleases(releases, changesets, rootDir, opts = {}) {
10
20
  if (!isGhAvailable()) {
11
21
  log.dim(" gh CLI not found — skipping GitHub releases");
12
22
  return;
13
23
  }
24
+ const headSha = getHeadSha(rootDir);
14
25
  for (const release of releases) {
15
26
  const tag = `${release.name}@${release.newVersion}`;
16
27
  const body = buildReleaseBody(release, changesets);
@@ -20,7 +31,18 @@ async function createIndividualReleases(releases, changesets, rootDir, opts = {}
20
31
  continue;
21
32
  }
22
33
  try {
23
- await runAsync(`gh release create "${tag}" --title "${escapeShell(title)}" --notes "${escapeShell(body)}"`, { cwd: rootDir });
34
+ const args = [
35
+ "gh",
36
+ "release",
37
+ "create",
38
+ tag,
39
+ "--title",
40
+ title,
41
+ "--notes",
42
+ body
43
+ ];
44
+ if (headSha) args.push("--target", headSha);
45
+ await runArgsAsync(args, { cwd: rootDir });
24
46
  log.dim(` Created GitHub release: ${title}`);
25
47
  } catch (err) {
26
48
  log.warn(` Failed to create GitHub release for ${tag}: ${err instanceof Error ? err.message : err}`);
@@ -35,8 +57,7 @@ async function createAggregateRelease(releases, changesets, rootDir, opts = {})
35
57
  }
36
58
  if (releases.length === 0) return;
37
59
  const date = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
38
- const title = (opts.title || "Release {{date}}").replace("{{date}}", date);
39
- const tag = `release-${date}`;
60
+ const { tag, title } = resolveAggregateTagAndTitle(date, listTags(`release-${date}*`, { cwd: rootDir }), opts.title);
40
61
  const body = buildAggregateBody(releases, changesets);
41
62
  if (opts.dryRun) {
42
63
  log.dim(` Would create aggregate GitHub release: ${title}`);
@@ -44,8 +65,24 @@ async function createAggregateRelease(releases, changesets, rootDir, opts = {})
44
65
  return;
45
66
  }
46
67
  try {
47
- tryRun(`git tag "${tag}"`, { cwd: rootDir });
48
- await runAsync(`gh release create "${tag}" --title "${escapeShell(title)}" --notes "${escapeShell(body)}"`, { cwd: rootDir });
68
+ tryRunArgs([
69
+ "git",
70
+ "tag",
71
+ tag
72
+ ], { cwd: rootDir });
73
+ const headSha = getHeadSha(rootDir);
74
+ const args = [
75
+ "gh",
76
+ "release",
77
+ "create",
78
+ tag,
79
+ "--title",
80
+ title,
81
+ "--notes",
82
+ body
83
+ ];
84
+ if (headSha) args.push("--target", headSha);
85
+ await runArgsAsync(args, { cwd: rootDir });
49
86
  log.success(`Created aggregate GitHub release: ${title}`);
50
87
  } catch (err) {
51
88
  log.warn(`Failed to create aggregate GitHub release: ${err instanceof Error ? err.message : err}`);
@@ -82,11 +119,17 @@ function buildAggregateBody(releases, changesets) {
82
119
  }
83
120
  return lines.join("\n").trim() || "No changelog entries.";
84
121
  }
85
- function isGhAvailable() {
86
- return tryRun("gh --version") !== null;
122
+ /** Compute the aggregate release tag and title, appending -n suffix if a tag for the same date already exists */
123
+ function resolveAggregateTagAndTitle(date, existingTags, titleTemplate) {
124
+ const baseTag = `release-${date}`;
125
+ const suffix = existingTags.length === 0 ? "" : `-${existingTags.length + 1}`;
126
+ return {
127
+ tag: `${baseTag}${suffix}`,
128
+ title: (titleTemplate || "Release {{date}}").replace("{{date}}", `${date}${suffix}`)
129
+ };
87
130
  }
88
- function escapeShell(str) {
89
- return str.replace(/"/g, "\\\"").replace(/\n/g, "\\n");
131
+ function isGhAvailable() {
132
+ return tryRunArgs(["gh", "--version"]) !== null;
90
133
  }
91
134
  //#endregion
92
135
  //#region src/commands/publish.ts
@@ -105,7 +148,7 @@ async function publishCommand(rootDir, opts) {
105
148
  }
106
149
  let toPublish = await findUnpublishedPackages(packages, config);
107
150
  if (opts.filter) {
108
- const { matchGlob } = await import("./config-CJ2orhTL.mjs").then((n) => n.t);
151
+ const { matchGlob } = await import("./config-BkwIEaQg.mjs").then((n) => n.t);
109
152
  const patterns = opts.filter.split(",").map((p) => p.trim());
110
153
  toPublish = toPublish.filter((r) => patterns.some((p) => matchGlob(r.name, p)));
111
154
  }
@@ -176,8 +219,7 @@ async function findUnpublishedPackages(packages, _config) {
176
219
  return unpublished;
177
220
  }
178
221
  async function checkIfPublished(name, version, pkgConfig) {
179
- const { runAsync } = await import("./shell-DPlltpzb.mjs").then((n) => n.r);
180
- const { tryRun } = await import("./shell-DPlltpzb.mjs").then((n) => n.r);
222
+ const { runAsync, runArgsAsync, tryRunArgs } = await import("./shell-Dj7JRD_q.mjs").then((n) => n.i);
181
223
  if (pkgConfig?.checkPublished) try {
182
224
  return (await runAsync(pkgConfig.checkPublished)).trim() === version;
183
225
  } catch {
@@ -185,10 +227,22 @@ async function checkIfPublished(name, version, pkgConfig) {
185
227
  }
186
228
  if (pkgConfig?.skipNpmPublish || pkgConfig?.publishCommand) {
187
229
  const tag = `${name}@${version}`;
188
- return tryRun(`git tag -l "${tag}"`) === tag;
230
+ return tryRunArgs([
231
+ "git",
232
+ "tag",
233
+ "-l",
234
+ tag
235
+ ]) === tag;
189
236
  }
190
237
  try {
191
- return await runAsync(`npm info "${name}@${version}" version ${pkgConfig?.registry ? `--registry ${pkgConfig.registry}` : ""}`.trim()) === version;
238
+ const args = [
239
+ "npm",
240
+ "info",
241
+ `${name}@${version}`,
242
+ "version"
243
+ ];
244
+ if (pkgConfig?.registry) args.push("--registry", pkgConfig.registry);
245
+ return await runArgsAsync(args) === version;
192
246
  } catch {
193
247
  return false;
194
248
  }
@@ -1,30 +1,12 @@
1
- import { n as log, t as colorize } from "./logger-ZqggsyGZ.mjs";
2
- import { a as readJson, c as writeJson } from "./fs-DbNNEyzq.mjs";
3
- import { i as resolveCatalogDep } from "./workspace-mVjawG8g.mjs";
4
- import { r as stripProtocol } from "./semver-DWO6NFKN.mjs";
5
- import { i as tryRun, n as runAsync, t as run } from "./shell-DPlltpzb.mjs";
1
+ import { n as log, t as colorize } from "./logger-C2dEe5Su.mjs";
2
+ import { a as readJson, c as writeJson } from "./fs-0AtnPUUe.mjs";
3
+ import { r as resolveCatalogDep } from "./package-manager-DcI5TdDE.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-BTzYh8vc.mjs";
6
+ import { o as tagExists, t as createTag } from "./git-CGHVXXKw.mjs";
6
7
  import { resolve } from "node:path";
7
8
  import { unlink } from "node:fs/promises";
8
9
  import { appendFileSync, existsSync, readFileSync, writeFileSync } from "node:fs";
9
- //#region src/core/git.ts
10
- /** Create a git tag */
11
- function createTag(tag, opts) {
12
- run(`git tag ${tag}`, opts);
13
- }
14
- /** Push commits and tags to remote */
15
- function pushWithTags(opts) {
16
- run("git push --follow-tags", opts);
17
- }
18
- /** Check if there are uncommitted changes */
19
- function hasUncommittedChanges(opts) {
20
- const result = tryRun("git status --porcelain", opts);
21
- return result !== null && result.length > 0;
22
- }
23
- /** Check if a tag already exists */
24
- function tagExists(tag, opts) {
25
- return tryRun(`git tag -l "${tag}"`, opts) === tag;
26
- }
27
- //#endregion
28
10
  //#region src/core/publish-pipeline.ts
29
11
  /**
30
12
  * Detect which CI OIDC provider is available for npm trusted publishing.
@@ -42,7 +24,7 @@ function detectOidcProvider() {
42
24
  return null;
43
25
  }
44
26
  const OIDC_NPM_UPGRADE_HINTS = {
45
- "github-actions": "Add `actions/setup-node@v4` with `node-version: lts/*` to your workflow",
27
+ "github-actions": "Add `actions/setup-node@v6` with `node-version: lts/*` to your workflow",
46
28
  gitlab: "Use a Node.js image with npm >= 11.5.1 or run `npm install -g npm@latest`",
47
29
  circleci: "Use a Node.js image with npm >= 11.5.1 or run `sudo npm install -g npm@latest`"
48
30
  };
@@ -67,7 +49,7 @@ function setupNpmAuth(rootDir, publishManager) {
67
49
  }
68
50
  const oidcProvider = detectOidcProvider();
69
51
  if (oidcProvider) {
70
- const npmVersion = tryRun("npm --version");
52
+ const npmVersion = tryRunArgs(["npm", "--version"]);
71
53
  if (npmVersion) {
72
54
  const [major, minor, patch] = npmVersion.split(".").map(Number);
73
55
  if (!(major > 11 || major === 11 && (minor > 5 || minor === 5 && patch >= 1))) {
@@ -135,7 +117,7 @@ async function publishPackages(releasePlan, packages, depGraph, config, rootDir,
135
117
  if (pkgConfig.publishCommand) {
136
118
  const commands = Array.isArray(pkgConfig.publishCommand) ? pkgConfig.publishCommand : [pkgConfig.publishCommand];
137
119
  for (const cmd of commands) {
138
- const expanded = cmd.replace(/\{\{version\}\}/g, release.newVersion).replace(/\{\{name\}\}/g, release.name);
120
+ const expanded = cmd.replace(/\{\{version\}\}/g, sq(release.newVersion)).replace(/\{\{name\}\}/g, sq(release.name));
139
121
  log.dim(` Running: ${expanded}`);
140
122
  if (!opts.dryRun) await runAsync(expanded, { cwd: pkg.dir });
141
123
  }
@@ -171,18 +153,18 @@ async function publishPackages(releasePlan, packages, depGraph, config, rootDir,
171
153
  * then publish the tarball with npm (which supports OIDC/provenance).
172
154
  */
173
155
  async function packThenPublish(pkg, pkgConfig, config, packManager, opts) {
174
- const packCmd = getPackCommand(packManager);
175
- log.dim(` Packing with: ${packCmd}`);
156
+ const packArgs = getPackArgs(packManager);
157
+ log.dim(` Packing with: ${packArgs.join(" ")}`);
176
158
  if (opts.dryRun) {
177
- const publishCmd = buildPublishCommand(pkg, pkgConfig, config, opts, "<tarball>");
178
- log.dim(` Would publish with: ${publishCmd}`);
159
+ const publishArgs = buildPublishArgs(pkg, pkgConfig, config, opts, "<tarball>");
160
+ log.dim(` Would publish with: ${publishArgs.join(" ")}`);
179
161
  return;
180
162
  }
181
- const tarball = parseTarballPath(await runAsync(packCmd, { cwd: pkg.dir }), pkg.dir);
163
+ const tarball = parseTarballPath(await runArgsAsync(packArgs, { cwd: pkg.dir }), pkg.dir);
182
164
  try {
183
- const publishCmd = buildPublishCommand(pkg, pkgConfig, config, opts, tarball);
184
- log.dim(` Publishing: ${publishCmd}`);
185
- await runAsync(publishCmd, { cwd: pkg.dir });
165
+ const publishArgs = buildPublishArgs(pkg, pkgConfig, config, opts, tarball);
166
+ log.dim(` Publishing: ${publishArgs.join(" ")}`);
167
+ await runArgsAsync(publishArgs, { cwd: pkg.dir });
186
168
  } finally {
187
169
  try {
188
170
  await unlink(tarball);
@@ -191,30 +173,34 @@ async function packThenPublish(pkg, pkgConfig, config, packManager, opts) {
191
173
  }
192
174
  /** Publish directly from the package directory (no tarball) */
193
175
  async function npmPublishDirect(pkg, pkgConfig, config, opts) {
194
- const cmd = buildPublishCommand(pkg, pkgConfig, config, opts);
195
- log.dim(` Running: ${cmd}`);
196
- if (!opts.dryRun) await runAsync(cmd, { cwd: pkg.dir });
176
+ const args = buildPublishArgs(pkg, pkgConfig, config, opts);
177
+ log.dim(` Running: ${args.join(" ")}`);
178
+ if (!opts.dryRun) await runArgsAsync(args, { cwd: pkg.dir });
197
179
  }
198
- function getPackCommand(pm) {
180
+ function getPackArgs(pm) {
199
181
  switch (pm) {
200
- case "pnpm": return "pnpm pack";
201
- case "bun": return "bun pm pack";
202
- case "yarn": return "yarn pack";
203
- default: return "npm pack";
182
+ case "pnpm": return ["pnpm", "pack"];
183
+ case "bun": return [
184
+ "bun",
185
+ "pm",
186
+ "pack"
187
+ ];
188
+ case "yarn": return ["yarn", "pack"];
189
+ default: return ["npm", "pack"];
204
190
  }
205
191
  }
206
- function buildPublishCommand(pkg, pkgConfig, config, opts, tarball) {
192
+ function buildPublishArgs(pkg, pkgConfig, config, opts, tarball) {
207
193
  const publishManager = config.publish.publishManager;
208
- const parts = [];
209
- if (publishManager === "yarn") parts.push("yarn npm publish");
210
- else parts.push(`${publishManager} publish`);
211
- if (tarball) parts.push(tarball);
194
+ const args = [];
195
+ if (publishManager === "yarn") args.push("yarn", "npm", "publish");
196
+ else args.push(publishManager, "publish");
197
+ if (tarball) args.push(tarball);
212
198
  const access = pkgConfig?.access || config.access;
213
- parts.push(`--access ${access}`);
214
- if (pkgConfig?.registry) parts.push(`--registry ${pkgConfig.registry}`);
215
- if (opts.tag) parts.push(`--tag ${opts.tag}`);
216
- if (config.publish.publishArgs.length > 0) parts.push(...config.publish.publishArgs);
217
- return parts.join(" ");
199
+ args.push("--access", access);
200
+ if (pkgConfig?.registry) args.push("--registry", pkgConfig.registry);
201
+ if (opts.tag) args.push("--tag", opts.tag);
202
+ if (config.publish.publishArgs.length > 0) args.push(...config.publish.publishArgs);
203
+ return args;
218
204
  }
219
205
  /**
220
206
  * Parse the tarball path from pack command output.
@@ -288,4 +274,4 @@ async function resolveProtocolsInPlace(pkg, packages, releasePlan, catalogs) {
288
274
  if (modified) await writeJson(pkgJsonPath, pkgJson);
289
275
  }
290
276
  //#endregion
291
- export { hasUncommittedChanges as n, pushWithTags as r, publishPackages as t };
277
+ export { publishPackages as t };
@@ -1,5 +1,5 @@
1
- import { g as parseIsolatedBump, h as maxBump, l as DEFAULT_BUMP_RULES, m as hasCascade, p as bumpLevel, s as matchGlob } from "./config-CJ2orhTL.mjs";
2
- import { n as satisfies, r as stripProtocol, t as bumpVersion } from "./semver-DWO6NFKN.mjs";
1
+ import { g as parseIsolatedBump, h as maxBump, l as DEFAULT_BUMP_RULES, m as hasCascade, p as bumpLevel, s as matchGlob } from "./config-BkwIEaQg.mjs";
2
+ import { n as satisfies, r as stripProtocol, t as bumpVersion } from "./semver-BTzYh8vc.mjs";
3
3
  //#region src/core/release-plan.ts
4
4
  /**
5
5
  * Build a release plan from pending changesets, the dependency graph, and config.
@@ -1,4 +1,4 @@
1
- import { a as __toESM, r as __commonJSMin } from "./logger-ZqggsyGZ.mjs";
1
+ import { i as __commonJSMin, o as __toESM } from "./logger-C2dEe5Su.mjs";
2
2
  //#region ../../node_modules/.bun/semver@7.7.4/node_modules/semver/internal/constants.js
3
3
  var require_constants = /* @__PURE__ */ __commonJSMin(((exports, module) => {
4
4
  const SEMVER_SPEC_VERSION = "2.0.0";
@@ -0,0 +1,92 @@
1
+ import { a as __exportAll } from "./logger-C2dEe5Su.mjs";
2
+ import { exec, execFile, execFileSync } from "node:child_process";
3
+ //#region src/utils/shell.ts
4
+ var shell_exports = /* @__PURE__ */ __exportAll({
5
+ runArgs: () => runArgs,
6
+ runArgsAsync: () => runArgsAsync,
7
+ runAsync: () => runAsync,
8
+ sq: () => sq,
9
+ tryRunArgs: () => tryRunArgs
10
+ });
11
+ /**
12
+ * Escape a value for safe interpolation inside a single-quoted shell string.
13
+ * Works by ending the current single-quote, inserting an escaped single-quote,
14
+ * and re-opening the single-quote: "it's" → 'it'\''s'
15
+ */
16
+ function sq(value) {
17
+ return "'" + value.replace(/'/g, "'\\''") + "'";
18
+ }
19
+ function checkIntercept(args, opts) {
20
+ return null;
21
+ }
22
+ function runAsync(cmd, opts) {
23
+ const result = checkIntercept(cmd.split(/\s+/), opts);
24
+ if (result?.intercepted) {
25
+ if ("error" in result) return Promise.reject(new Error(result.error));
26
+ return Promise.resolve(result.result);
27
+ }
28
+ return new Promise((resolve, reject) => {
29
+ const child = exec(cmd, {
30
+ cwd: opts?.cwd,
31
+ encoding: "utf-8"
32
+ }, (err, stdout, stderr) => {
33
+ if (err) reject(/* @__PURE__ */ new Error(`Command failed: ${cmd}\n${stderr}`));
34
+ else resolve(stdout.trim());
35
+ });
36
+ if (opts?.input) {
37
+ child.stdin?.write(opts.input);
38
+ child.stdin?.end();
39
+ }
40
+ });
41
+ }
42
+ /** Run a command with an argument array — bypasses the shell entirely */
43
+ function runArgs(args, opts) {
44
+ const result = checkIntercept(args, opts);
45
+ if (result?.intercepted) {
46
+ if ("error" in result) throw new Error(result.error);
47
+ return result.result;
48
+ }
49
+ const [cmd, ...rest] = args;
50
+ return execFileSync(cmd, rest, {
51
+ cwd: opts?.cwd,
52
+ input: opts?.input,
53
+ encoding: "utf-8",
54
+ stdio: [
55
+ opts?.input ? "pipe" : "pipe",
56
+ "pipe",
57
+ "pipe"
58
+ ]
59
+ }).trim();
60
+ }
61
+ /** Async version of runArgs */
62
+ function runArgsAsync(args, opts) {
63
+ const result = checkIntercept(args, opts);
64
+ if (result?.intercepted) {
65
+ if ("error" in result) return Promise.reject(new Error(result.error));
66
+ return Promise.resolve(result.result);
67
+ }
68
+ const [cmd, ...rest] = args;
69
+ return new Promise((resolve, reject) => {
70
+ const child = execFile(cmd, rest, {
71
+ cwd: opts?.cwd,
72
+ encoding: "utf-8"
73
+ }, (err, stdout, stderr) => {
74
+ if (err) reject(/* @__PURE__ */ new Error(`Command failed: ${args.join(" ")}\n${stderr}`));
75
+ else resolve(stdout.trim());
76
+ });
77
+ if (opts?.input) {
78
+ child.stdin?.write(opts.input);
79
+ child.stdin?.end();
80
+ }
81
+ });
82
+ }
83
+ /** tryRun equivalent for argument arrays */
84
+ function tryRunArgs(args, opts) {
85
+ try {
86
+ return runArgs(args, opts);
87
+ } catch {
88
+ return null;
89
+ }
90
+ }
91
+ //#endregion
92
+ export { sq as a, shell_exports as i, runArgsAsync as n, tryRunArgs as o, runAsync as r, runArgs as t };
@@ -1,9 +1,9 @@
1
- import { n as log, t as colorize } from "./logger-ZqggsyGZ.mjs";
2
- import { a as loadConfig } from "./config-CJ2orhTL.mjs";
3
- import { t as discoverPackages } from "./workspace-mVjawG8g.mjs";
4
- import { t as DependencyGraph } from "./dep-graph-DiLeAhl9.mjs";
5
- import { r as readChangesets } from "./changeset-ClCYsChu.mjs";
6
- import { t as assembleReleasePlan } from "./release-plan-CFnutSHD.mjs";
1
+ import { n as log, t as colorize } from "./logger-C2dEe5Su.mjs";
2
+ import { a as loadConfig } from "./config-BkwIEaQg.mjs";
3
+ import { t as discoverPackages } from "./workspace-CxEKakDm.mjs";
4
+ import { t as DependencyGraph } from "./dep-graph-E-9-eQ2J.mjs";
5
+ import { r as readChangesets } from "./changeset-UCZdSRDv.mjs";
6
+ import { t as assembleReleasePlan } from "./release-plan-BEzwApuK.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-CJ2orhTL.mjs").then((n) => n.t);
29
+ const { matchGlob } = await import("./config-BkwIEaQg.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,11 +1,12 @@
1
- import { n as log, t as colorize } from "./logger-ZqggsyGZ.mjs";
2
- import { a as loadConfig } from "./config-CJ2orhTL.mjs";
3
- import { r as detectWorkspaces, t as discoverPackages } from "./workspace-mVjawG8g.mjs";
4
- import { t as DependencyGraph } from "./dep-graph-DiLeAhl9.mjs";
5
- import { r as readChangesets } from "./changeset-ClCYsChu.mjs";
6
- import { t as assembleReleasePlan } from "./release-plan-CFnutSHD.mjs";
7
- import { t as applyReleasePlan } from "./apply-release-plan-DtU3rVyL.mjs";
8
- import { i as tryRun, t as run } from "./shell-DPlltpzb.mjs";
1
+ import { n as log, t as colorize } from "./logger-C2dEe5Su.mjs";
2
+ import { a as loadConfig } from "./config-BkwIEaQg.mjs";
3
+ import { n as detectWorkspaces } from "./package-manager-DcI5TdDE.mjs";
4
+ import { t as discoverPackages } from "./workspace-CxEKakDm.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 readChangesets } from "./changeset-UCZdSRDv.mjs";
8
+ import { t as assembleReleasePlan } from "./release-plan-BEzwApuK.mjs";
9
+ import { t as applyReleasePlan } from "./apply-release-plan-D6TSrcwX.mjs";
9
10
  //#region src/commands/version.ts
10
11
  async function versionCommand(rootDir) {
11
12
  const config = await loadConfig(rootDir);
@@ -31,11 +32,26 @@ async function versionCommand(rootDir) {
31
32
  log.dim(` Deleted ${changesets.length} changeset file(s)`);
32
33
  await updateLockfile(rootDir);
33
34
  if (config.commit) try {
34
- run("git add -A .bumpy/", { cwd: rootDir });
35
+ runArgs([
36
+ "git",
37
+ "add",
38
+ "-A",
39
+ ".bumpy/"
40
+ ], { cwd: rootDir });
35
41
  for (const r of plan.releases) {
36
42
  const pkg = packages.get(r.name);
37
- run(`git add "${pkg.relativeDir}/package.json"`, { cwd: rootDir });
38
- run(`git add "${pkg.relativeDir}/CHANGELOG.md"`, { cwd: rootDir });
43
+ runArgs([
44
+ "git",
45
+ "add",
46
+ "--",
47
+ `${pkg.relativeDir}/package.json`
48
+ ], { cwd: rootDir });
49
+ runArgs([
50
+ "git",
51
+ "add",
52
+ "--",
53
+ `${pkg.relativeDir}/CHANGELOG.md`
54
+ ], { cwd: rootDir });
39
55
  }
40
56
  for (const lockfile of [
41
57
  "bun.lock",
@@ -43,8 +59,18 @@ async function versionCommand(rootDir) {
43
59
  "pnpm-lock.yaml",
44
60
  "yarn.lock",
45
61
  "package-lock.json"
46
- ]) tryRun(`git add "${lockfile}"`, { cwd: rootDir });
47
- run("git commit -F -", {
62
+ ]) tryRunArgs([
63
+ "git",
64
+ "add",
65
+ "--",
66
+ lockfile
67
+ ], { cwd: rootDir });
68
+ runArgs([
69
+ "git",
70
+ "commit",
71
+ "-F",
72
+ "-"
73
+ ], {
48
74
  cwd: rootDir,
49
75
  input: [
50
76
  "Version packages",
@@ -60,21 +86,34 @@ async function versionCommand(rootDir) {
60
86
  /** Run the package manager's install to update the lockfile */
61
87
  async function updateLockfile(rootDir) {
62
88
  const { packageManager } = await detectWorkspaces(rootDir);
63
- const installCmd = getInstallCommand(packageManager);
64
- log.step(`Updating lockfile (${installCmd})...`);
89
+ const installArgs = getInstallArgs(packageManager);
90
+ log.step(`Updating lockfile (${installArgs.join(" ")})...`);
65
91
  try {
66
- run(installCmd, { cwd: rootDir });
92
+ runArgs(installArgs, { cwd: rootDir });
67
93
  log.dim(" Lockfile updated");
68
94
  } catch (err) {
69
95
  log.warn(` Lockfile update failed: ${err instanceof Error ? err.message : err}`);
70
96
  }
71
97
  }
72
- function getInstallCommand(pm) {
98
+ function getInstallArgs(pm) {
73
99
  switch (pm) {
74
- case "pnpm": return "pnpm install --lockfile-only";
75
- case "bun": return "bun install";
76
- case "yarn": return "yarn install --mode update-lockfile";
77
- default: return "npm install --package-lock-only";
100
+ case "pnpm": return [
101
+ "pnpm",
102
+ "install",
103
+ "--lockfile-only"
104
+ ];
105
+ case "bun": return ["bun", "install"];
106
+ case "yarn": return [
107
+ "yarn",
108
+ "install",
109
+ "--mode",
110
+ "update-lockfile"
111
+ ];
112
+ default: return [
113
+ "npm",
114
+ "install",
115
+ "--package-lock-only"
116
+ ];
78
117
  }
79
118
  }
80
119
  //#endregion
@@ -0,0 +1,107 @@
1
+ import { a as readJson, n as exists } from "./fs-0AtnPUUe.mjs";
2
+ import { i as isPackageManaged, o as loadPackageConfig } from "./config-BkwIEaQg.mjs";
3
+ import { n as detectWorkspaces } from "./package-manager-DcI5TdDE.mjs";
4
+ import { relative, resolve } from "node:path";
5
+ import { readdir, stat } from "node:fs/promises";
6
+ //#region src/core/workspace.ts
7
+ /** Discover all workspace packages and catalogs in a monorepo */
8
+ async function discoverWorkspace(rootDir, config) {
9
+ const { globs, catalogs } = await detectWorkspaces(rootDir);
10
+ if (globs.length === 0) throw new Error("No workspace globs found. Is this a monorepo?");
11
+ const packages = /* @__PURE__ */ new Map();
12
+ for (const glob of globs) {
13
+ const dirs = await resolveGlob(rootDir, glob);
14
+ for (const dir of dirs) {
15
+ const pkg = await loadWorkspacePackage(dir, rootDir, config);
16
+ if (pkg) {
17
+ if (!isPackageManaged(pkg.name, pkg.private, config, pkg.bumpy)) continue;
18
+ packages.set(pkg.name, pkg);
19
+ }
20
+ }
21
+ }
22
+ return {
23
+ packages,
24
+ catalogs
25
+ };
26
+ }
27
+ /** Convenience wrapper that returns just packages (backwards compat) */
28
+ async function discoverPackages(rootDir, config) {
29
+ const { packages } = await discoverWorkspace(rootDir, config);
30
+ return packages;
31
+ }
32
+ /** Resolve a workspace glob pattern to directories containing package.json */
33
+ async function resolveGlob(rootDir, pattern) {
34
+ return expandGlob(rootDir, pattern.split("/"));
35
+ }
36
+ async function expandGlob(baseDir, parts) {
37
+ if (parts.length === 0) {
38
+ if (await exists(resolve(baseDir, "package.json"))) return [baseDir];
39
+ return [];
40
+ }
41
+ const [current, ...rest] = parts;
42
+ if (current === "*") {
43
+ const entries = await safeReaddir(baseDir);
44
+ const results = [];
45
+ for (const entry of entries) {
46
+ const entryPath = resolve(baseDir, entry);
47
+ if (await isDirectory(entryPath)) results.push(...await expandGlob(entryPath, rest));
48
+ }
49
+ return results;
50
+ } else if (current === "**") {
51
+ const results = [];
52
+ results.push(...await expandGlob(baseDir, rest));
53
+ const entries = await safeReaddir(baseDir);
54
+ for (const entry of entries) {
55
+ if (entry.startsWith(".") || entry === "node_modules") continue;
56
+ const entryPath = resolve(baseDir, entry);
57
+ if (await isDirectory(entryPath)) results.push(...await expandGlob(entryPath, parts));
58
+ }
59
+ return results;
60
+ } else {
61
+ const next = resolve(baseDir, current);
62
+ if (await isDirectory(next)) return expandGlob(next, rest);
63
+ return [];
64
+ }
65
+ }
66
+ async function safeReaddir(dir) {
67
+ try {
68
+ return await readdir(dir);
69
+ } catch {
70
+ return [];
71
+ }
72
+ }
73
+ async function isDirectory(path) {
74
+ try {
75
+ return (await stat(path)).isDirectory();
76
+ } catch {
77
+ return false;
78
+ }
79
+ }
80
+ async function loadWorkspacePackage(dir, rootDir, config) {
81
+ const pkgPath = resolve(dir, "package.json");
82
+ if (!await exists(pkgPath)) return null;
83
+ let pkg;
84
+ try {
85
+ pkg = await readJson(pkgPath);
86
+ } catch {
87
+ return null;
88
+ }
89
+ const name = pkg.name;
90
+ if (!name) return null;
91
+ const bumpy = await loadPackageConfig(dir, config, name);
92
+ return {
93
+ name,
94
+ version: pkg.version || "0.0.0",
95
+ dir: resolve(dir),
96
+ relativeDir: relative(rootDir, dir),
97
+ packageJson: pkg,
98
+ private: !!pkg.private,
99
+ dependencies: pkg.dependencies || {},
100
+ devDependencies: pkg.devDependencies || {},
101
+ peerDependencies: pkg.peerDependencies || {},
102
+ optionalDependencies: pkg.optionalDependencies || {},
103
+ bumpy
104
+ };
105
+ }
106
+ //#endregion
107
+ export { discoverWorkspace as n, discoverPackages as t };