@varlock/bumpy 0.0.1 → 1.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 (44) hide show
  1. package/.claude-plugin/plugin.json +2 -2
  2. package/dist/add-CgCjs4d-.mjs +313 -0
  3. package/dist/{ai-B8ZL2x8z.mjs → ai-sMYUf3lP.mjs} +22 -5
  4. package/dist/{apply-release-plan-DtU3rVyL.mjs → apply-release-plan-CczGWJTk.mjs} +34 -25
  5. package/dist/bump-file-CCLXMLA8.mjs +143 -0
  6. package/dist/changelog-github-Cd8uJHZI.mjs +195 -0
  7. package/dist/{check-CkRubvuk.mjs → check-BOoxpWqk.mjs} +11 -17
  8. package/dist/ci-Bhx--Tj6.mjs +629 -0
  9. package/dist/ci-setup-qz4Y3v7T.mjs +211 -0
  10. package/dist/clack-CDRCHrC-.mjs +1216 -0
  11. package/dist/cli.mjs +37 -31
  12. package/dist/{config-CJ2orhTL.mjs → config-XZWUL3ma.mjs} +28 -23
  13. package/dist/fs-DYR2XuFE.mjs +81 -0
  14. package/dist/{generate-oOFD9ABC.mjs → generate-gYKTpvex.mjs} +31 -12
  15. package/dist/git-CGHVXXKw.mjs +78 -0
  16. package/dist/index.d.mts +63 -37
  17. package/dist/index.mjs +9 -9
  18. package/dist/{init-Blw2GfC_.mjs → init-lA9E5pEc.mjs} +3 -3
  19. package/dist/logger-C2dEe5Su.mjs +135 -0
  20. package/dist/{migrate-DvOrXSw0.mjs → migrate-DmOYgmfD.mjs} +23 -16
  21. package/dist/{names-C-u50ofE.mjs → names-9VubBmL0.mjs} +3 -2
  22. package/dist/package-manager-VCe10bjc.mjs +80 -0
  23. package/dist/{publish-DZ3m7qkX.mjs → publish-Cun-zQ1b.mjs} +90 -35
  24. package/dist/{publish-pipeline-1M5GmbdP.mjs → publish-pipeline-BwBuKCIk.mjs} +56 -65
  25. package/dist/release-plan-Bi5QNSEo.mjs +264 -0
  26. package/dist/{semver-DWO6NFKN.mjs → semver-DfQyVLM_.mjs} +14 -4
  27. package/dist/shell-Dj7JRD_q.mjs +92 -0
  28. package/dist/{status-DRpq_Mha.mjs → status-CfE63ti5.mjs} +27 -23
  29. package/dist/version-19vVt9dv.mjs +124 -0
  30. package/dist/workspace-C5ULTyUN.mjs +107 -0
  31. package/package.json +16 -2
  32. package/skills/add-change/SKILL.md +8 -12
  33. package/dist/add-u5V9V3L7.mjs +0 -131
  34. package/dist/changelog-github-n-3zV1p9.mjs +0 -59
  35. package/dist/changeset-ClCYsChu.mjs +0 -75
  36. package/dist/ci-8KWWhjXl.mjs +0 -224
  37. package/dist/fs-DbNNEyzq.mjs +0 -51
  38. package/dist/logger-ZqggsyGZ.mjs +0 -176
  39. package/dist/prompt-BP8toAOI.mjs +0 -46
  40. package/dist/release-plan-CFnutSHD.mjs +0 -173
  41. package/dist/shell-DPlltpzb.mjs +0 -44
  42. package/dist/version-CJwf8XIA.mjs +0 -81
  43. package/dist/workspace-mVjawG8g.mjs +0 -183
  44. /package/dist/{dep-graph-DiLeAhl9.mjs → dep-graph-E-9-eQ2J.mjs} +0 -0
@@ -1,26 +1,48 @@
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-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";
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
- async function createIndividualReleases(releases, changesets, rootDir, opts = {}) {
19
+ async function createIndividualReleases(releases, bumpFiles, 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
- const body = buildReleaseBody(release, changesets);
27
+ const body = buildReleaseBody(release, bumpFiles);
17
28
  const title = `${release.name} v${release.newVersion}`;
18
29
  if (opts.dryRun) {
19
30
  log.dim(` Would create GitHub release: ${title}`);
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}`);
@@ -28,39 +50,54 @@ async function createIndividualReleases(releases, changesets, rootDir, opts = {}
28
50
  }
29
51
  }
30
52
  /** Create a single aggregated GitHub release for all published packages */
31
- async function createAggregateRelease(releases, changesets, rootDir, opts = {}) {
53
+ async function createAggregateRelease(releases, bumpFiles, rootDir, opts = {}) {
32
54
  if (!isGhAvailable()) {
33
55
  log.dim(" gh CLI not found — skipping GitHub release");
34
56
  return;
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}`;
40
- const body = buildAggregateBody(releases, changesets);
60
+ const { tag, title } = resolveAggregateTagAndTitle(date, listTags(`release-${date}*`, { cwd: rootDir }), opts.title);
61
+ const body = buildAggregateBody(releases, bumpFiles);
41
62
  if (opts.dryRun) {
42
63
  log.dim(` Would create aggregate GitHub release: ${title}`);
43
64
  log.dim(` Tag: ${tag}`);
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}`);
52
89
  }
53
90
  }
54
- function buildReleaseBody(release, changesets) {
91
+ function buildReleaseBody(release, bumpFiles) {
55
92
  const lines = [];
56
- const relevant = changesets.filter((cs) => release.changesets.includes(cs.id));
93
+ const relevant = bumpFiles.filter((bf) => release.bumpFiles.includes(bf.id));
57
94
  if (relevant.length > 0) {
58
- for (const cs of relevant) if (cs.summary) lines.push(`- ${cs.summary.split("\n")[0]}`);
95
+ for (const bf of relevant) if (bf.summary) lines.push(`- ${bf.summary.split("\n")[0]}`);
59
96
  }
60
97
  if (release.isDependencyBump && relevant.length === 0) lines.push("- Updated dependencies");
61
98
  return lines.join("\n") || "No changelog entries.";
62
99
  }
63
- function buildAggregateBody(releases, changesets) {
100
+ function buildAggregateBody(releases, bumpFiles) {
64
101
  const lines = [];
65
102
  const groups = [
66
103
  ["Major Changes", releases.filter((r) => r.type === "major")],
@@ -72,9 +109,9 @@ function buildAggregateBody(releases, changesets) {
72
109
  lines.push(`## ${heading}\n`);
73
110
  for (const release of group) {
74
111
  lines.push(`### ${release.name} v${release.newVersion}\n`);
75
- const relevant = changesets.filter((cs) => release.changesets.includes(cs.id));
112
+ const relevant = bumpFiles.filter((bf) => release.bumpFiles.includes(bf.id));
76
113
  if (relevant.length > 0) {
77
- for (const cs of relevant) if (cs.summary) lines.push(`- ${cs.summary.split("\n")[0]}`);
114
+ for (const bf of relevant) if (bf.summary) lines.push(`- ${bf.summary.split("\n")[0]}`);
78
115
  } else if (release.isDependencyBump) lines.push("- Updated dependencies");
79
116
  else if (release.isCascadeBump) lines.push("- Version bump via cascade rule");
80
117
  lines.push("");
@@ -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-XZWUL3ma.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
  }
@@ -114,8 +157,9 @@ async function publishCommand(rootDir, opts) {
114
157
  return;
115
158
  }
116
159
  const releasePlan = {
117
- changesets: [],
118
- releases: toPublish
160
+ bumpFiles: [],
161
+ releases: toPublish,
162
+ warnings: []
119
163
  };
120
164
  if (opts.dryRun) log.bold("Dry run — would publish:");
121
165
  else log.bold("Publishing:");
@@ -143,11 +187,11 @@ async function publishCommand(rootDir, opts) {
143
187
  const aggConfig = config.aggregateRelease;
144
188
  const isAggregate = aggConfig === true || typeof aggConfig === "object" && aggConfig.enabled;
145
189
  const aggTitle = typeof aggConfig === "object" ? aggConfig.title : void 0;
146
- if (isAggregate) await createAggregateRelease(publishedReleases, releasePlan.changesets, rootDir, {
190
+ if (isAggregate) await createAggregateRelease(publishedReleases, releasePlan.bumpFiles, rootDir, {
147
191
  dryRun: opts.dryRun,
148
192
  title: aggTitle
149
193
  });
150
- else await createIndividualReleases(publishedReleases, releasePlan.changesets, rootDir, { dryRun: opts.dryRun });
194
+ else await createIndividualReleases(publishedReleases, releasePlan.bumpFiles, rootDir, { dryRun: opts.dryRun });
151
195
  }
152
196
  }
153
197
  /**
@@ -168,7 +212,7 @@ async function findUnpublishedPackages(packages, _config) {
168
212
  type: "patch",
169
213
  oldVersion: pkg.version,
170
214
  newVersion: pkg.version,
171
- changesets: [],
215
+ bumpFiles: [],
172
216
  isDependencyBump: false,
173
217
  isCascadeBump: false
174
218
  });
@@ -176,8 +220,7 @@ async function findUnpublishedPackages(packages, _config) {
176
220
  return unpublished;
177
221
  }
178
222
  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);
223
+ const { runAsync, runArgsAsync, tryRunArgs } = await import("./shell-Dj7JRD_q.mjs").then((n) => n.i);
181
224
  if (pkgConfig?.checkPublished) try {
182
225
  return (await runAsync(pkgConfig.checkPublished)).trim() === version;
183
226
  } catch {
@@ -185,10 +228,22 @@ async function checkIfPublished(name, version, pkgConfig) {
185
228
  }
186
229
  if (pkgConfig?.skipNpmPublish || pkgConfig?.publishCommand) {
187
230
  const tag = `${name}@${version}`;
188
- return tryRun(`git tag -l "${tag}"`) === tag;
231
+ return tryRunArgs([
232
+ "git",
233
+ "tag",
234
+ "-l",
235
+ tag
236
+ ]) === tag;
189
237
  }
190
238
  try {
191
- return await runAsync(`npm info "${name}@${version}" version ${pkgConfig?.registry ? `--registry ${pkgConfig.registry}` : ""}`.trim()) === version;
239
+ const args = [
240
+ "npm",
241
+ "info",
242
+ `${name}@${version}`,
243
+ "version"
244
+ ];
245
+ if (pkgConfig?.registry) args.push("--registry", pkgConfig.registry);
246
+ return await runArgsAsync(args) === version;
192
247
  } catch {
193
248
  return false;
194
249
  }
@@ -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, 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";
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, packManager);
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,39 +173,53 @@ 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 [
183
+ "pnpm",
184
+ "pack",
185
+ "--json"
186
+ ];
187
+ case "bun": return [
188
+ "bun",
189
+ "pm",
190
+ "pack"
191
+ ];
192
+ case "yarn": return ["yarn", "pack"];
193
+ default: return [
194
+ "npm",
195
+ "pack",
196
+ "--json"
197
+ ];
204
198
  }
205
199
  }
206
- function buildPublishCommand(pkg, pkgConfig, config, opts, tarball) {
200
+ function buildPublishArgs(pkg, pkgConfig, config, opts, tarball) {
207
201
  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);
202
+ const args = [];
203
+ if (publishManager === "yarn") args.push("yarn", "npm", "publish");
204
+ else args.push(publishManager, "publish");
205
+ if (tarball) args.push(tarball);
212
206
  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(" ");
207
+ args.push("--access", access);
208
+ if (pkgConfig?.registry) args.push("--registry", pkgConfig.registry);
209
+ if (opts.tag) args.push("--tag", opts.tag);
210
+ if (config.publish.publishArgs.length > 0) args.push(...config.publish.publishArgs);
211
+ return args;
218
212
  }
219
213
  /**
220
214
  * Parse the tarball path from pack command output.
221
- * Each PM has different output formats:
222
- * npm/pnpm: tarball filename on the last line
223
- * bun: tarball filename mid-output, summary lines after
224
- * yarn: 'success Wrote tarball to "/path/to/foo.tgz".'
215
+ * npm/pnpm use --json for structured output; bun/yarn fall back to regex parsing.
225
216
  */
226
- function parseTarballPath(output, cwd) {
217
+ function parseTarballPath(output, cwd, pm) {
218
+ if (pm === "npm" || pm === "pnpm") try {
219
+ const parsed = JSON.parse(output);
220
+ const entry = Array.isArray(parsed) ? parsed[0] : parsed;
221
+ if (entry?.filename) return resolve(cwd, entry.filename);
222
+ } catch {}
227
223
  const tgzMatch = output.match(/(?:^|["'\s])([^\s"']*\.tgz)/m);
228
224
  if (tgzMatch) {
229
225
  const tarball = tgzMatch[1];
@@ -253,7 +249,6 @@ function createGitTag(release, rootDir, opts) {
253
249
  async function resolveProtocolsInPlace(pkg, packages, releasePlan, catalogs) {
254
250
  const pkgJsonPath = resolve(pkg.dir, "package.json");
255
251
  const pkgJson = await readJson(pkgJsonPath);
256
- let modified = false;
257
252
  const releaseMap = new Map(releasePlan.releases.map((r) => [r.name, r]));
258
253
  for (const depField of [
259
254
  "dependencies",
@@ -279,13 +274,9 @@ async function resolveProtocolsInPlace(pkg, packages, releasePlan, catalogs) {
279
274
  resolved = `${cleanRange === "*" ? "^" : cleanRange}${version}`;
280
275
  } else resolved = cleanRange;
281
276
  }
282
- if (resolved) {
283
- deps[depName] = resolved;
284
- modified = true;
285
- }
277
+ if (resolved) await updateJsonNestedField(pkgJsonPath, depField, depName, resolved);
286
278
  }
287
279
  }
288
- if (modified) await writeJson(pkgJsonPath, pkgJson);
289
280
  }
290
281
  //#endregion
291
- export { hasUncommittedChanges as n, pushWithTags as r, publishPackages as t };
282
+ export { publishPackages as t };