@pubm/core 0.4.4 → 0.4.6

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 (36) hide show
  1. package/dist/assets/index.d.ts +1 -1
  2. package/dist/assets/index.d.ts.map +1 -1
  3. package/dist/assets/pipeline.d.ts +4 -2
  4. package/dist/assets/pipeline.d.ts.map +1 -1
  5. package/dist/assets/types.d.ts +7 -7
  6. package/dist/assets/types.d.ts.map +1 -1
  7. package/dist/config/defaults.d.ts.map +1 -1
  8. package/dist/config/loader.d.ts +1 -1
  9. package/dist/config/loader.d.ts.map +1 -1
  10. package/dist/config/types.d.ts +1 -0
  11. package/dist/config/types.d.ts.map +1 -1
  12. package/dist/context.d.ts +1 -0
  13. package/dist/context.d.ts.map +1 -1
  14. package/dist/ecosystem/ecosystem.d.ts +14 -1
  15. package/dist/ecosystem/ecosystem.d.ts.map +1 -1
  16. package/dist/ecosystem/infer.d.ts.map +1 -1
  17. package/dist/ecosystem/js.d.ts +9 -0
  18. package/dist/ecosystem/js.d.ts.map +1 -1
  19. package/dist/ecosystem/rust.d.ts +1 -1
  20. package/dist/ecosystem/rust.d.ts.map +1 -1
  21. package/dist/index.cjs +347 -174
  22. package/dist/index.js +350 -177
  23. package/dist/manifest/write-versions.d.ts +1 -1
  24. package/dist/manifest/write-versions.d.ts.map +1 -1
  25. package/dist/monorepo/discover.d.ts.map +1 -1
  26. package/dist/monorepo/resolve-workspace.d.ts.map +1 -1
  27. package/dist/plugin/runner.d.ts +1 -1
  28. package/dist/plugin/runner.d.ts.map +1 -1
  29. package/dist/plugin/types.d.ts +6 -6
  30. package/dist/plugin/types.d.ts.map +1 -1
  31. package/dist/registry/custom-registry.d.ts.map +1 -1
  32. package/dist/tasks/dry-run-publish.d.ts.map +1 -1
  33. package/dist/tasks/runner.d.ts.map +1 -1
  34. package/dist/utils/package-manager.d.ts +3 -2
  35. package/dist/utils/package-manager.d.ts.map +1 -1
  36. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -20111,6 +20111,10 @@ async function openUrl(url) {
20111
20111
  var init_open_url = () => {};
20112
20112
 
20113
20113
  // src/plugin/runner.ts
20114
+ function isDefined(value) {
20115
+ return value !== undefined;
20116
+ }
20117
+
20114
20118
  class PluginRunner {
20115
20119
  plugins;
20116
20120
  constructor(plugins) {
@@ -20148,7 +20152,7 @@ class PluginRunner {
20148
20152
  }
20149
20153
  collectAssetHooks() {
20150
20154
  const collected = {};
20151
- const resolveChain = this.plugins.map((p) => p.hooks?.resolveAssets).filter(Boolean);
20155
+ const resolveChain = this.plugins.map((p) => p.hooks?.resolveAssets).filter(isDefined);
20152
20156
  if (resolveChain.length > 0) {
20153
20157
  collected.resolveAssets = async (assets, ctx) => {
20154
20158
  let result = assets;
@@ -20158,7 +20162,7 @@ class PluginRunner {
20158
20162
  return result;
20159
20163
  };
20160
20164
  }
20161
- const transformChain = this.plugins.map((p) => p.hooks?.transformAsset).filter(Boolean);
20165
+ const transformChain = this.plugins.map((p) => p.hooks?.transformAsset).filter(isDefined);
20162
20166
  if (transformChain.length > 0) {
20163
20167
  collected.transformAsset = async (asset, ctx) => {
20164
20168
  let items = [asset];
@@ -20173,17 +20177,18 @@ class PluginRunner {
20173
20177
  return items.length === 1 ? items[0] : items;
20174
20178
  };
20175
20179
  }
20176
- const compressChain = this.plugins.map((p) => p.hooks?.compressAsset).filter(Boolean);
20180
+ const compressChain = this.plugins.map((p) => p.hooks?.compressAsset).filter(isDefined);
20177
20181
  if (compressChain.length > 0) {
20178
20182
  collected.compressAsset = async (asset, ctx) => {
20179
- let result = asset;
20180
- for (const hook of compressChain) {
20183
+ const [firstHook, ...restHooks] = compressChain;
20184
+ let result = await firstHook(asset, ctx);
20185
+ for (const hook of restHooks) {
20181
20186
  result = await hook(result, ctx);
20182
20187
  }
20183
20188
  return result;
20184
20189
  };
20185
20190
  }
20186
- const nameChain = this.plugins.map((p) => p.hooks?.nameAsset).filter(Boolean);
20191
+ const nameChain = this.plugins.map((p) => p.hooks?.nameAsset).filter(isDefined);
20187
20192
  if (nameChain.length > 0) {
20188
20193
  collected.nameAsset = (asset, ctx) => {
20189
20194
  let result = "";
@@ -20193,7 +20198,7 @@ class PluginRunner {
20193
20198
  return result;
20194
20199
  };
20195
20200
  }
20196
- const checksumChain = this.plugins.map((p) => p.hooks?.generateChecksums).filter(Boolean);
20201
+ const checksumChain = this.plugins.map((p) => p.hooks?.generateChecksums).filter(isDefined);
20197
20202
  if (checksumChain.length > 0) {
20198
20203
  collected.generateChecksums = async (assets, ctx) => {
20199
20204
  let result = assets;
@@ -20203,7 +20208,7 @@ class PluginRunner {
20203
20208
  return result;
20204
20209
  };
20205
20210
  }
20206
- const uploadHooks = this.plugins.map((p) => p.hooks?.uploadAssets).filter(Boolean);
20211
+ const uploadHooks = this.plugins.map((p) => p.hooks?.uploadAssets).filter(isDefined);
20207
20212
  if (uploadHooks.length > 0) {
20208
20213
  collected.uploadAssets = async (assets, ctx) => {
20209
20214
  const allResults = [];
@@ -20219,7 +20224,7 @@ class PluginRunner {
20219
20224
  }
20220
20225
 
20221
20226
  // src/tasks/runner.ts
20222
- import { existsSync as existsSync5, mkdirSync as mkdirSync2, readFileSync as readFileSync8, rmSync as rmSync2 } from "node:fs";
20227
+ import { existsSync as existsSync6, mkdirSync as mkdirSync2, readFileSync as readFileSync9, rmSync as rmSync2 } from "node:fs";
20223
20228
  import { tmpdir as tmpdir2 } from "node:os";
20224
20229
  import path10, { join as join9 } from "node:path";
20225
20230
  import process17 from "node:process";
@@ -22860,7 +22865,8 @@ function createKeyResolver(packages) {
22860
22865
  }
22861
22866
 
22862
22867
  // src/ecosystem/js.ts
22863
- import { readFile as readFile3, writeFile } from "node:fs/promises";
22868
+ import { existsSync as existsSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "node:fs";
22869
+ import { readFile as readFile3, stat as stat3, writeFile } from "node:fs/promises";
22864
22870
  import path5 from "node:path";
22865
22871
 
22866
22872
  // src/registry/jsr.ts
@@ -22964,7 +22970,7 @@ function isValidPackageName(packageName) {
22964
22970
  // package.json
22965
22971
  var package_default = {
22966
22972
  name: "@pubm/core",
22967
- version: "0.4.4",
22973
+ version: "0.4.6",
22968
22974
  type: "module",
22969
22975
  description: "Core SDK for pubm - publish manager for multiple registries",
22970
22976
  types: "./dist/index.d.ts",
@@ -23038,7 +23044,7 @@ var coreEngines = package_default.engines ?? {};
23038
23044
  function resolveDefine(injected, fallback) {
23039
23045
  return typeof injected === "string" ? injected : fallback;
23040
23046
  }
23041
- var PUBM_VERSION = resolveDefine("0.4.4", package_default.version);
23047
+ var PUBM_VERSION = resolveDefine("0.4.6", package_default.version);
23042
23048
  var PUBM_ENGINES = {
23043
23049
  node: resolveDefine(">=24", coreEngines.node ?? ">=18"),
23044
23050
  git: resolveDefine(">=2.11.0", coreEngines.git ?? ">=2.11.0"),
@@ -23997,6 +24003,9 @@ async function npmPackageRegistry(packagePath) {
23997
24003
  return new NpmPackageRegistry(manifest.name, packagePath);
23998
24004
  }
23999
24005
 
24006
+ // src/ecosystem/js.ts
24007
+ init_exec();
24008
+
24000
24009
  // src/utils/package.ts
24001
24010
  import { stat as stat2 } from "node:fs/promises";
24002
24011
  import path4 from "node:path";
@@ -24020,16 +24029,28 @@ async function findOutFile(file, { cwd = process12.cwd() } = {}) {
24020
24029
  }
24021
24030
 
24022
24031
  // src/utils/package-manager.ts
24023
- var lockFile = {
24032
+ var lockFiles = {
24024
24033
  bun: ["bun.lock", "bun.lockb"],
24025
24034
  npm: ["package-lock.json", "npm-shrinkwrap.json"],
24026
24035
  pnpm: ["pnpm-lock.yaml"],
24027
24036
  yarn: ["yarn.lock"]
24028
24037
  };
24038
+ function getInstallCommand(pm, isYarnBerry) {
24039
+ switch (pm) {
24040
+ case "bun":
24041
+ return ["bun", "install", "--lockfile-only"];
24042
+ case "npm":
24043
+ return ["npm", "install", "--package-lock-only"];
24044
+ case "pnpm":
24045
+ return ["pnpm", "install", "--lockfile-only"];
24046
+ case "yarn":
24047
+ return isYarnBerry ? ["yarn", "install", "--mode", "update-lockfile"] : ["yarn", "install"];
24048
+ }
24049
+ }
24029
24050
  async function getPackageManager() {
24030
- for (const [packageManager, lockFiles] of Object.entries(lockFile)) {
24031
- for (const lockFile2 of lockFiles) {
24032
- if (await findOutFile(lockFile2))
24051
+ for (const [packageManager, files] of Object.entries(lockFiles)) {
24052
+ for (const file of files) {
24053
+ if (await findOutFile(file))
24033
24054
  return packageManager;
24034
24055
  }
24035
24056
  }
@@ -24038,6 +24059,8 @@ async function getPackageManager() {
24038
24059
  }
24039
24060
 
24040
24061
  // src/ecosystem/ecosystem.ts
24062
+ import { writeFileSync as writeFileSync3 } from "node:fs";
24063
+
24041
24064
  class Ecosystem {
24042
24065
  packagePath;
24043
24066
  constructor(packagePath) {
@@ -24078,9 +24101,17 @@ class Ecosystem {
24078
24101
  async updateSiblingDependencyVersions(_siblingVersions) {
24079
24102
  return false;
24080
24103
  }
24081
- async syncLockfile() {
24104
+ async syncLockfile(_mode = "optional") {
24082
24105
  return;
24083
24106
  }
24107
+ async resolvePublishDependencies(_workspaceVersions) {
24108
+ return new Map;
24109
+ }
24110
+ restorePublishDependencies(backups) {
24111
+ for (const [filePath, content] of backups) {
24112
+ writeFileSync3(filePath, content, "utf-8");
24113
+ }
24114
+ }
24084
24115
  }
24085
24116
 
24086
24117
  // src/ecosystem/descriptor.ts
@@ -24151,6 +24182,97 @@ class JsEcosystem extends Ecosystem {
24151
24182
  supportedRegistries() {
24152
24183
  return ["npm", "jsr"];
24153
24184
  }
24185
+ async syncLockfile(mode = "optional") {
24186
+ if (mode === "skip")
24187
+ return;
24188
+ const found = await this.findLockfile();
24189
+ if (!found)
24190
+ return;
24191
+ const { lockfilePath, packageManager } = found;
24192
+ const lockfileDir = path5.dirname(lockfilePath);
24193
+ try {
24194
+ let isYarnBerry;
24195
+ if (packageManager === "yarn") {
24196
+ const yarnrcPath = path5.join(lockfileDir, ".yarnrc.yml");
24197
+ try {
24198
+ isYarnBerry = (await stat3(yarnrcPath)).isFile();
24199
+ } catch {
24200
+ isYarnBerry = false;
24201
+ }
24202
+ }
24203
+ const [cmd, ...args] = getInstallCommand(packageManager, isYarnBerry);
24204
+ await exec3(cmd, args, { nodeOptions: { cwd: lockfileDir } });
24205
+ return lockfilePath;
24206
+ } catch (error2) {
24207
+ if (mode === "required")
24208
+ throw error2;
24209
+ console.warn(`Warning: Failed to sync lockfile at ${lockfilePath}: ${error2 instanceof Error ? error2.message : error2}`);
24210
+ return;
24211
+ }
24212
+ }
24213
+ async findLockfile() {
24214
+ let dir = this.packagePath;
24215
+ const { root } = path5.parse(dir);
24216
+ while (dir !== root) {
24217
+ for (const [pm, files] of Object.entries(lockFiles)) {
24218
+ for (const file of files) {
24219
+ const candidate = path5.join(dir, file);
24220
+ try {
24221
+ if ((await stat3(candidate)).isFile()) {
24222
+ return {
24223
+ lockfilePath: candidate,
24224
+ packageManager: pm
24225
+ };
24226
+ }
24227
+ } catch {}
24228
+ }
24229
+ }
24230
+ dir = path5.dirname(dir);
24231
+ }
24232
+ return;
24233
+ }
24234
+ async resolvePublishDependencies(workspaceVersions) {
24235
+ const backups = new Map;
24236
+ const manifestPath = path5.join(this.packagePath, "package.json");
24237
+ if (!existsSync3(manifestPath))
24238
+ return backups;
24239
+ const original = readFileSync4(manifestPath, "utf-8");
24240
+ const pkg = JSON.parse(original);
24241
+ let modified = false;
24242
+ const WORKSPACE_PREFIX = "workspace:";
24243
+ const DEPENDENCY_FIELDS = [
24244
+ "dependencies",
24245
+ "devDependencies",
24246
+ "optionalDependencies",
24247
+ "peerDependencies"
24248
+ ];
24249
+ for (const field of DEPENDENCY_FIELDS) {
24250
+ const deps = pkg[field];
24251
+ if (!deps)
24252
+ continue;
24253
+ for (const [depName, spec] of Object.entries(deps)) {
24254
+ if (!spec.startsWith(WORKSPACE_PREFIX))
24255
+ continue;
24256
+ const range = spec.slice(WORKSPACE_PREFIX.length);
24257
+ if (range === "*" || range === "^" || range === "~") {
24258
+ const version = workspaceVersions.get(depName);
24259
+ if (!version) {
24260
+ throw new Error(`Cannot resolve "${spec}" for dependency "${depName}": package not found in workspace`);
24261
+ }
24262
+ deps[depName] = range === "*" ? version : range === "^" ? `^${version}` : `~${version}`;
24263
+ } else {
24264
+ deps[depName] = range;
24265
+ }
24266
+ modified = true;
24267
+ }
24268
+ }
24269
+ if (modified) {
24270
+ backups.set(manifestPath, original);
24271
+ writeFileSync4(manifestPath, `${JSON.stringify(pkg, null, 2)}
24272
+ `, "utf-8");
24273
+ }
24274
+ return backups;
24275
+ }
24154
24276
  async createDescriptor() {
24155
24277
  const npmReader = NpmPackageRegistry.reader;
24156
24278
  const jsrReader = JsrPackageRegistry.reader;
@@ -24161,7 +24283,7 @@ class JsEcosystem extends Ecosystem {
24161
24283
  }
24162
24284
 
24163
24285
  // src/ecosystem/rust.ts
24164
- import { readFile as readFile4, stat as stat3, writeFile as writeFile2 } from "node:fs/promises";
24286
+ import { readFile as readFile4, stat as stat4, writeFile as writeFile2 } from "node:fs/promises";
24165
24287
  import path7 from "node:path";
24166
24288
 
24167
24289
  // ../../node_modules/.bun/smol-toml@1.6.0/node_modules/smol-toml/dist/error.js
@@ -25486,15 +25608,24 @@ class RustEcosystem extends Ecosystem {
25486
25608
  }
25487
25609
  return modified;
25488
25610
  }
25489
- async syncLockfile() {
25611
+ async syncLockfile(mode = "optional") {
25612
+ if (mode === "skip")
25613
+ return;
25490
25614
  const lockfilePath = await this.findLockfile();
25491
25615
  if (!lockfilePath)
25492
25616
  return;
25493
- const name = await this.packageName();
25494
- await exec3("cargo", ["update", "--package", name], {
25495
- nodeOptions: { cwd: path7.dirname(lockfilePath) }
25496
- });
25497
- return lockfilePath;
25617
+ try {
25618
+ const name = await this.packageName();
25619
+ await exec3("cargo", ["update", "--package", name], {
25620
+ nodeOptions: { cwd: path7.dirname(lockfilePath) }
25621
+ });
25622
+ return lockfilePath;
25623
+ } catch (error2) {
25624
+ if (mode === "required")
25625
+ throw error2;
25626
+ console.warn(`Warning: Failed to sync lockfile at ${lockfilePath}: ${error2 instanceof Error ? error2.message : error2}`);
25627
+ return;
25628
+ }
25498
25629
  }
25499
25630
  async findLockfile() {
25500
25631
  let dir = this.packagePath;
@@ -25502,7 +25633,7 @@ class RustEcosystem extends Ecosystem {
25502
25633
  while (dir !== root) {
25503
25634
  const candidate = path7.join(dir, "Cargo.lock");
25504
25635
  try {
25505
- if ((await stat3(candidate)).isFile())
25636
+ if ((await stat4(candidate)).isFile())
25506
25637
  return candidate;
25507
25638
  } catch {}
25508
25639
  dir = path7.dirname(dir);
@@ -25570,7 +25701,7 @@ init_error();
25570
25701
  init_git();
25571
25702
 
25572
25703
  // src/manifest/write-versions.ts
25573
- async function writeVersionsForEcosystem(ecosystems, versions) {
25704
+ async function writeVersionsForEcosystem(ecosystems, versions, lockfileSync) {
25574
25705
  const modifiedFiles = [];
25575
25706
  for (const { eco, pkg } of ecosystems) {
25576
25707
  const version = versions.get(pkg.path);
@@ -25591,25 +25722,28 @@ async function writeVersionsForEcosystem(ecosystems, versions) {
25591
25722
  }
25592
25723
  await Promise.all(ecosystems.map(({ eco }) => eco.updateSiblingDependencyVersions(nameKeyedVersions)));
25593
25724
  }
25725
+ const syncedLockfiles = new Set;
25594
25726
  for (const { eco } of ecosystems) {
25595
- const lockfilePath = await eco.syncLockfile();
25596
- if (lockfilePath)
25727
+ const lockfilePath = await eco.syncLockfile(lockfileSync);
25728
+ if (lockfilePath && !syncedLockfiles.has(lockfilePath)) {
25729
+ syncedLockfiles.add(lockfilePath);
25597
25730
  modifiedFiles.push(lockfilePath);
25731
+ }
25598
25732
  }
25599
25733
  return modifiedFiles;
25600
25734
  }
25601
25735
 
25602
25736
  // src/monorepo/resolve-workspace.ts
25603
- import { existsSync as existsSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync3 } from "node:fs";
25737
+ import { existsSync as existsSync5, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "node:fs";
25604
25738
  import { join as join7 } from "node:path";
25605
25739
 
25606
25740
  // src/monorepo/discover.ts
25607
25741
  var import_micromatch2 = __toESM(require_micromatch(), 1);
25608
- import { readdirSync as readdirSync3, statSync as statSync2 } from "node:fs";
25742
+ import { lstatSync, readdirSync as readdirSync3 } from "node:fs";
25609
25743
  import path8 from "node:path";
25610
25744
 
25611
25745
  // src/ecosystem/infer.ts
25612
- import { readFile as readFile5, stat as stat4 } from "node:fs/promises";
25746
+ import { readFile as readFile5, stat as stat5 } from "node:fs/promises";
25613
25747
  import { join as join5 } from "node:path";
25614
25748
 
25615
25749
  // src/utils/crate-graph.ts
@@ -25681,6 +25815,9 @@ function normalizeRegistryUrl(url) {
25681
25815
  init_exec();
25682
25816
  class CustomPackageRegistry extends NpmPackageRegistry {
25683
25817
  async npm(args, cwd) {
25818
+ if (!this.registry) {
25819
+ throw new Error("Custom registry URL is required for npm operations.");
25820
+ }
25684
25821
  const { stdout } = await exec3("npm", args.concat("--registry", this.registry), {
25685
25822
  throwOnError: true,
25686
25823
  nodeOptions: cwd ? { cwd } : undefined
@@ -25785,7 +25922,7 @@ registryCatalog.register({
25785
25922
  return token.trim().length >= 32;
25786
25923
  },
25787
25924
  resolveDisplayName: async (ctx) => {
25788
- return ctx.packages?.filter((pkg) => pkg.registries?.includes("crates")).map((pkg) => pkg.path) ?? ["crate"];
25925
+ return ctx.packages?.filter((pkg) => pkg.registries?.includes("crates")).map((pkg) => pkg.name) ?? ["crate"];
25789
25926
  },
25790
25927
  concurrentPublish: false,
25791
25928
  orderPackages: (paths) => sortCratesByDependencyOrder(paths),
@@ -25823,7 +25960,7 @@ function registerPrivateRegistry(config, ecosystemKey, catalog = registryCatalog
25823
25960
  var NPM_OFFICIAL = "registry.npmjs.org";
25824
25961
  async function fileExists(path8) {
25825
25962
  try {
25826
- const s2 = await stat4(path8);
25963
+ const s2 = await stat5(path8);
25827
25964
  return s2.isFile();
25828
25965
  } catch {
25829
25966
  return false;
@@ -25837,6 +25974,12 @@ async function readJsonSafe(path8) {
25837
25974
  return null;
25838
25975
  }
25839
25976
  }
25977
+ function asRecord(value) {
25978
+ return value !== null && typeof value === "object" ? value : null;
25979
+ }
25980
+ function readString(value) {
25981
+ return typeof value === "string" ? value : undefined;
25982
+ }
25840
25983
  async function readFileSafe(path8) {
25841
25984
  try {
25842
25985
  return await readFile5(path8, "utf-8");
@@ -25886,8 +26029,8 @@ async function inferJsRegistries(packagePath, rootPath) {
25886
26029
  return [];
25887
26030
  }
25888
26031
  const packageJson = await readJsonSafe(join5(packagePath, "package.json"));
25889
- const packageName = packageJson?.name;
25890
- const publishConfigRegistry = packageJson?.publishConfig?.registry;
26032
+ const packageName = readString(packageJson?.name);
26033
+ const publishConfigRegistry = readString(asRecord(packageJson?.publishConfig)?.registry);
25891
26034
  let npmRegistryUrl = null;
25892
26035
  if (publishConfigRegistry) {
25893
26036
  npmRegistryUrl = publishConfigRegistry;
@@ -25928,7 +26071,7 @@ async function inferRegistries(packagePath, ecosystemKey, rootPath) {
25928
26071
  }
25929
26072
 
25930
26073
  // src/monorepo/workspace.ts
25931
- import { existsSync as existsSync3, readFileSync as readFileSync4 } from "node:fs";
26074
+ import { existsSync as existsSync4, readFileSync as readFileSync5 } from "node:fs";
25932
26075
  import { join as join6 } from "node:path";
25933
26076
 
25934
26077
  // ../../node_modules/.bun/jsonc-parser@3.3.1/node_modules/jsonc-parser/lib/esm/impl/scanner.js
@@ -26740,15 +26883,15 @@ function detectWorkspace(cwd) {
26740
26883
  const root = cwd ?? process.cwd();
26741
26884
  const workspaces = [];
26742
26885
  const pnpmWorkspacePath = join6(root, "pnpm-workspace.yaml");
26743
- if (existsSync3(pnpmWorkspacePath)) {
26744
- const content = readFileSync4(pnpmWorkspacePath, "utf-8");
26886
+ if (existsSync4(pnpmWorkspacePath)) {
26887
+ const content = readFileSync5(pnpmWorkspacePath, "utf-8");
26745
26888
  const parsed = $parse(content);
26746
26889
  const packages = parsed?.packages ?? [];
26747
26890
  workspaces.push({ type: "pnpm", patterns: packages });
26748
26891
  }
26749
26892
  const cargoTomlPath = join6(root, "Cargo.toml");
26750
- if (existsSync3(cargoTomlPath)) {
26751
- const content = readFileSync4(cargoTomlPath, "utf-8");
26893
+ if (existsSync4(cargoTomlPath)) {
26894
+ const content = readFileSync5(cargoTomlPath, "utf-8");
26752
26895
  try {
26753
26896
  const parsed = parse(content);
26754
26897
  const workspace = parsed.workspace;
@@ -26763,8 +26906,8 @@ function detectWorkspace(cwd) {
26763
26906
  }
26764
26907
  for (const denoFile of ["deno.json", "deno.jsonc"]) {
26765
26908
  const denoPath = join6(root, denoFile);
26766
- if (existsSync3(denoPath)) {
26767
- const content = readFileSync4(denoPath, "utf-8");
26909
+ if (existsSync4(denoPath)) {
26910
+ const content = readFileSync5(denoPath, "utf-8");
26768
26911
  try {
26769
26912
  const parsed = denoFile.endsWith(".jsonc") ? parse3(content) : JSON.parse(content);
26770
26913
  if (Array.isArray(parsed?.workspace)) {
@@ -26777,12 +26920,12 @@ function detectWorkspace(cwd) {
26777
26920
  }
26778
26921
  if (!workspaces.some((w2) => w2.type === "pnpm")) {
26779
26922
  const packageJsonPath = join6(root, "package.json");
26780
- if (existsSync3(packageJsonPath)) {
26781
- const content = readFileSync4(packageJsonPath, "utf-8");
26923
+ if (existsSync4(packageJsonPath)) {
26924
+ const content = readFileSync5(packageJsonPath, "utf-8");
26782
26925
  const pkg = JSON.parse(content);
26783
26926
  if (pkg.workspaces) {
26784
26927
  const bunfigPath = join6(root, "bunfig.toml");
26785
- const isBun2 = existsSync3(bunfigPath);
26928
+ const isBun2 = existsSync4(bunfigPath);
26786
26929
  if (Array.isArray(pkg.workspaces)) {
26787
26930
  workspaces.push({
26788
26931
  type: isBun2 ? "bun" : "npm",
@@ -26814,16 +26957,32 @@ function matchesIgnore(pkgPath, ignorePatterns) {
26814
26957
  return regex3.test(normalized);
26815
26958
  });
26816
26959
  }
26817
- function resolvePatterns(cwd, patterns) {
26818
- const entries = readdirSync3(cwd, { recursive: true, encoding: "utf-8" });
26819
- const dirs = entries.filter((entry) => {
26820
- const fullPath = path8.join(cwd, entry);
26960
+ function readdirRecursiveNoSymlinks(dir, root) {
26961
+ const results = [];
26962
+ let entries;
26963
+ try {
26964
+ entries = readdirSync3(dir, { encoding: "utf-8" });
26965
+ } catch {
26966
+ return results;
26967
+ }
26968
+ for (const entry of entries) {
26969
+ if (entry === "node_modules" || entry === ".git")
26970
+ continue;
26971
+ const fullPath = path8.join(dir, entry);
26821
26972
  try {
26822
- return statSync2(fullPath).isDirectory();
26823
- } catch {
26824
- return false;
26825
- }
26826
- });
26973
+ const stat6 = lstatSync(fullPath);
26974
+ if (stat6.isSymbolicLink())
26975
+ continue;
26976
+ if (stat6.isDirectory()) {
26977
+ results.push(path8.relative(root, fullPath));
26978
+ results.push(...readdirRecursiveNoSymlinks(fullPath, root));
26979
+ }
26980
+ } catch {}
26981
+ }
26982
+ return results;
26983
+ }
26984
+ function resolvePatterns(cwd, patterns) {
26985
+ const dirs = readdirRecursiveNoSymlinks(cwd, cwd);
26827
26986
  const normalizedDirs = dirs.map((d3) => d3.replace(/\\/g, "/"));
26828
26987
  const matched = import_micromatch2.default(normalizedDirs, patterns);
26829
26988
  return matched.map((d3) => path8.resolve(cwd, d3));
@@ -26920,31 +27079,6 @@ async function discoverPackages(options) {
26920
27079
  }
26921
27080
 
26922
27081
  // src/monorepo/resolve-workspace.ts
26923
- var WORKSPACE_PREFIX = "workspace:";
26924
- var DEPENDENCY_FIELDS = [
26925
- "dependencies",
26926
- "devDependencies",
26927
- "optionalDependencies",
26928
- "peerDependencies"
26929
- ];
26930
- function resolveWorkspaceProtocol(spec, version) {
26931
- if (!spec.startsWith(WORKSPACE_PREFIX))
26932
- return spec;
26933
- const range = spec.slice(WORKSPACE_PREFIX.length);
26934
- switch (range) {
26935
- case "*":
26936
- return version;
26937
- case "^":
26938
- return `^${version}`;
26939
- case "~":
26940
- return `~${version}`;
26941
- default:
26942
- return range;
26943
- }
26944
- }
26945
- function isDynamicWorkspaceSpec(range) {
26946
- return range === "*" || range === "^" || range === "~";
26947
- }
26948
27082
  function collectWorkspaceVersions(cwd) {
26949
27083
  const versions = new Map;
26950
27084
  const workspaces = detectWorkspace(cwd);
@@ -26956,10 +27090,10 @@ function collectWorkspaceVersions(cwd) {
26956
27090
  const dirs = resolvePatterns(cwd, workspace.patterns);
26957
27091
  for (const dir of dirs) {
26958
27092
  const pkgJsonPath = join7(dir, "package.json");
26959
- if (!existsSync4(pkgJsonPath))
27093
+ if (!existsSync5(pkgJsonPath))
26960
27094
  continue;
26961
27095
  try {
26962
- const content = readFileSync5(pkgJsonPath, "utf-8");
27096
+ const content = readFileSync6(pkgJsonPath, "utf-8");
26963
27097
  const pkg = JSON.parse(content);
26964
27098
  if (typeof pkg.name === "string" && pkg.name && typeof pkg.version === "string" && pkg.version) {
26965
27099
  versions.set(pkg.name, pkg.version);
@@ -26969,44 +27103,9 @@ function collectWorkspaceVersions(cwd) {
26969
27103
  }
26970
27104
  return versions;
26971
27105
  }
26972
- function resolveWorkspaceProtocolsInManifests(packagePaths, workspaceVersions) {
26973
- const backups = new Map;
26974
- for (const pkgPath of packagePaths) {
26975
- const manifestPath = join7(pkgPath, "package.json");
26976
- const original = readFileSync5(manifestPath, "utf-8");
26977
- const pkg = JSON.parse(original);
26978
- let modified = false;
26979
- for (const field of DEPENDENCY_FIELDS) {
26980
- const deps = pkg[field];
26981
- if (!deps)
26982
- continue;
26983
- for (const [depName, spec] of Object.entries(deps)) {
26984
- if (!spec.startsWith(WORKSPACE_PREFIX))
26985
- continue;
26986
- const range = spec.slice(WORKSPACE_PREFIX.length);
26987
- if (isDynamicWorkspaceSpec(range)) {
26988
- const version = workspaceVersions.get(depName);
26989
- if (!version) {
26990
- throw new Error(`Cannot resolve "${spec}" for dependency "${depName}": package not found in workspace`);
26991
- }
26992
- deps[depName] = resolveWorkspaceProtocol(spec, version);
26993
- } else {
26994
- deps[depName] = range;
26995
- }
26996
- modified = true;
26997
- }
26998
- }
26999
- if (modified) {
27000
- backups.set(manifestPath, original);
27001
- writeFileSync3(manifestPath, `${JSON.stringify(pkg, null, 2)}
27002
- `, "utf-8");
27003
- }
27004
- }
27005
- return backups;
27006
- }
27007
27106
  function restoreManifests(backups) {
27008
27107
  for (const [filePath, content] of backups) {
27009
- writeFileSync3(filePath, content, "utf-8");
27108
+ writeFileSync5(filePath, content, "utf-8");
27010
27109
  }
27011
27110
  }
27012
27111
 
@@ -27310,7 +27409,8 @@ function createContext(config, options, cwd) {
27310
27409
  tag: options.tag ?? "latest",
27311
27410
  promptEnabled: false,
27312
27411
  cleanWorkingTree: false,
27313
- pluginRunner: new PluginRunner([])
27412
+ pluginRunner: new PluginRunner([]),
27413
+ tokenRetryPromises: {}
27314
27414
  };
27315
27415
  const ctx = Object.defineProperties(Object.create(null), {
27316
27416
  config: {
@@ -27397,9 +27497,10 @@ async function withTokenRetry(registryKey, ctx, task, action) {
27397
27497
  if (!descriptor)
27398
27498
  throw error2;
27399
27499
  const config = descriptor.tokenConfig;
27400
- const retryKey = `_tokenRetry_${registryKey}`;
27401
- if (!ctx.runtime[retryKey]) {
27402
- ctx.runtime[retryKey] = (async () => {
27500
+ const retryPromises = ctx.runtime.tokenRetryPromises ?? {};
27501
+ ctx.runtime.tokenRetryPromises = retryPromises;
27502
+ if (!retryPromises[registryKey]) {
27503
+ retryPromises[registryKey] = (async () => {
27403
27504
  task.output = `Auth failed. Re-enter ${config.promptLabel}`;
27404
27505
  const newToken = await task.prompt(ListrEnquirerPromptAdapter).run({
27405
27506
  type: "password",
@@ -27410,7 +27511,7 @@ async function withTokenRetry(registryKey, ctx, task, action) {
27410
27511
  return newToken;
27411
27512
  })();
27412
27513
  }
27413
- await ctx.runtime[retryKey];
27514
+ await retryPromises[registryKey];
27414
27515
  await action();
27415
27516
  }
27416
27517
  }
@@ -27467,7 +27568,11 @@ async function findUnpublishedSiblingDeps(packagePath, siblingPaths) {
27467
27568
  }));
27468
27569
  const siblingDeps = deps.filter((d3) => siblingNameToPath.has(d3));
27469
27570
  const results = await Promise.all(siblingDeps.map(async (name) => {
27470
- const registry = await cratesPackageRegistry(siblingNameToPath.get(name));
27571
+ const siblingPath = siblingNameToPath.get(name);
27572
+ if (!siblingPath) {
27573
+ throw new Error(`Missing sibling crate path for dependency: ${name}`);
27574
+ }
27575
+ const registry = await cratesPackageRegistry(siblingPath);
27471
27576
  const published = await registry.isPublished();
27472
27577
  return published ? null : name;
27473
27578
  }));
@@ -27518,7 +27623,7 @@ function createCratesDryRunPublishTask(packagePath, siblingPaths) {
27518
27623
  init_error();
27519
27624
  init_git();
27520
27625
  var import_semver2 = __toESM(require_semver2(), 1);
27521
- import { readFileSync as readFileSync6 } from "node:fs";
27626
+ import { readFileSync as readFileSync7 } from "node:fs";
27522
27627
  var { prerelease } = import_semver2.default;
27523
27628
 
27524
27629
  class GitHubReleaseError extends AbstractError {
@@ -27587,7 +27692,7 @@ async function createGitHubRelease(_ctx, options) {
27587
27692
  const uploadUrl = release.upload_url.replace(/\{[^}]*\}/, "");
27588
27693
  const releaseAssets = [];
27589
27694
  for (const asset of options.assets) {
27590
- const archiveContent = readFileSync6(asset.filePath);
27695
+ const archiveContent = readFileSync7(asset.filePath);
27591
27696
  const uploadResponse = await fetch(`${uploadUrl}?name=${encodeURIComponent(asset.name)}`, {
27592
27697
  method: "POST",
27593
27698
  headers: {
@@ -27836,7 +27941,7 @@ init_error();
27836
27941
  init_exec();
27837
27942
 
27838
27943
  // src/utils/gh-secrets-sync-state.ts
27839
- import { readFileSync as readFileSync7, writeFileSync as writeFileSync4 } from "node:fs";
27944
+ import { readFileSync as readFileSync8, writeFileSync as writeFileSync6 } from "node:fs";
27840
27945
  import path9 from "node:path";
27841
27946
  var SYNC_HASH_FILENAME = "gh-secrets-sync-hash";
27842
27947
  function syncHashFilePath() {
@@ -27844,14 +27949,14 @@ function syncHashFilePath() {
27844
27949
  }
27845
27950
  function readGhSecretsSyncHash() {
27846
27951
  try {
27847
- const value = readFileSync7(syncHashFilePath(), "utf8").trim();
27952
+ const value = readFileSync8(syncHashFilePath(), "utf8").trim();
27848
27953
  return value || null;
27849
27954
  } catch {
27850
27955
  return null;
27851
27956
  }
27852
27957
  }
27853
27958
  function writeGhSecretsSyncHash(hash) {
27854
- writeFileSync4(syncHashFilePath(), `${hash}
27959
+ writeFileSync6(syncHashFilePath(), `${hash}
27855
27960
  `, "utf8");
27856
27961
  }
27857
27962
 
@@ -28239,16 +28344,30 @@ function isReleaseExcluded(config, pkgPath) {
28239
28344
  function getPackageName(ctx, packagePath) {
28240
28345
  return ctx.config.packages.find((p2) => p2.path === packagePath)?.name ?? packagePath;
28241
28346
  }
28347
+ function requirePackageEcosystem(pkg) {
28348
+ if (!pkg.ecosystem) {
28349
+ throw new Error(`Package ${pkg.path} is missing an ecosystem.`);
28350
+ }
28351
+ return pkg.ecosystem;
28352
+ }
28353
+ function requireVersionPlan(ctx) {
28354
+ const { versionPlan } = ctx.runtime;
28355
+ if (!versionPlan) {
28356
+ throw new Error("Version plan is required before running release tasks.");
28357
+ }
28358
+ return versionPlan;
28359
+ }
28242
28360
  async function writeVersions(ctx, versions) {
28243
28361
  const ecosystems = ctx.config.packages.map((pkg) => {
28244
28362
  const absPath = path10.resolve(ctx.cwd ?? process17.cwd(), pkg.path);
28245
- const descriptor = ecosystemCatalog.get(pkg.ecosystem);
28363
+ const ecosystem = requirePackageEcosystem(pkg);
28364
+ const descriptor = ecosystemCatalog.get(ecosystem);
28246
28365
  if (!descriptor)
28247
- throw new Error(`Unknown ecosystem: ${pkg.ecosystem}`);
28366
+ throw new Error(`Unknown ecosystem: ${ecosystem}`);
28248
28367
  const eco = new descriptor.ecosystemClass(absPath);
28249
28368
  return { eco, pkg };
28250
28369
  });
28251
- const lockfileChanges = await writeVersionsForEcosystem(ecosystems, versions);
28370
+ const lockfileChanges = await writeVersionsForEcosystem(ecosystems, versions, ctx.config.lockfileSync);
28252
28371
  const manifestFiles = ecosystems.flatMap(({ eco }) => eco.manifestFiles().map((f2) => path10.resolve(eco.packagePath, f2)));
28253
28372
  return [...manifestFiles, ...lockfileChanges];
28254
28373
  }
@@ -28263,17 +28382,38 @@ function createPublishTaskForPath(registryKey, packagePath) {
28263
28382
  return { title: `Publish to ${registryKey}`, task: async () => {} };
28264
28383
  return factory(packagePath);
28265
28384
  }
28266
- function resolveWorkspaceProtocols(ctx) {
28385
+ async function resolveWorkspaceProtocols(ctx) {
28267
28386
  if (!ctx.cwd)
28268
28387
  return;
28269
28388
  const workspaceVersions = collectWorkspaceVersions(ctx.cwd);
28270
28389
  if (workspaceVersions.size === 0)
28271
28390
  return;
28272
- const packagePaths = ctx.config.packages.map((pkg) => path10.resolve(ctx.cwd, pkg.path));
28273
- const backups = resolveWorkspaceProtocolsInManifests(packagePaths, workspaceVersions);
28274
- if (backups.size > 0) {
28275
- ctx.runtime.workspaceBackups = backups;
28276
- addRollback(async () => restoreManifests(backups), ctx);
28391
+ const allBackups = new Map;
28392
+ for (const pkg of ctx.config.packages) {
28393
+ const absPath = path10.resolve(ctx.cwd, pkg.path);
28394
+ const ecosystem = requirePackageEcosystem(pkg);
28395
+ const descriptor = ecosystemCatalog.get(ecosystem);
28396
+ if (!descriptor)
28397
+ continue;
28398
+ const eco = new descriptor.ecosystemClass(absPath);
28399
+ const backups = await eco.resolvePublishDependencies(workspaceVersions);
28400
+ for (const [k3, v2] of backups) {
28401
+ allBackups.set(k3, v2);
28402
+ }
28403
+ }
28404
+ if (allBackups.size > 0) {
28405
+ ctx.runtime.workspaceBackups = allBackups;
28406
+ addRollback(async () => {
28407
+ for (const pkg of ctx.config.packages) {
28408
+ const absPath = path10.resolve(ctx.cwd, pkg.path);
28409
+ const ecosystem = requirePackageEcosystem(pkg);
28410
+ const descriptor = ecosystemCatalog.get(ecosystem);
28411
+ if (!descriptor)
28412
+ continue;
28413
+ const eco = new descriptor.ecosystemClass(absPath);
28414
+ eco.restorePublishDependencies(allBackups);
28415
+ }
28416
+ }, ctx);
28277
28417
  }
28278
28418
  }
28279
28419
  async function applyVersionsForDryRun(ctx) {
@@ -28393,8 +28533,8 @@ ${[...plan.packages].map(([pkgPath, ver]) => ` ${getPackageName(ctx, pkgPath)}:
28393
28533
  }
28394
28534
  return "";
28395
28535
  }
28396
- function shouldRenderLiveCommandOutput(ctx) {
28397
- return ctx.options.mode !== "ci" && !m && Boolean(process17.stdout.isTTY);
28536
+ function shouldRenderLiveCommandOutput(_ctx) {
28537
+ return !m && Boolean(process17.stdout.isTTY);
28398
28538
  }
28399
28539
  function normalizeLiveCommandOutputLine(line) {
28400
28540
  const normalized = stripVTControlCharacters2(line).trimEnd();
@@ -28475,7 +28615,7 @@ async function run(ctx) {
28475
28615
  await requiredConditionsCheckTask({
28476
28616
  skip: ctx.options.skipConditionsCheck
28477
28617
  }).run(ctx);
28478
- const pipelineListrOptions2 = mode === "ci" || m ? createCiListrOptions() : undefined;
28618
+ const pipelineListrOptions2 = m ? createCiListrOptions() : undefined;
28479
28619
  await createListr([
28480
28620
  {
28481
28621
  skip: ctx.options.skipTests,
@@ -28557,7 +28697,7 @@ async function run(ctx) {
28557
28697
  skip: () => dryRun,
28558
28698
  task: async (ctx2, task) => {
28559
28699
  const git = new Git;
28560
- const snapshotPlan = ctx2.runtime.versionPlan;
28700
+ const snapshotPlan = requireVersionPlan(ctx2);
28561
28701
  const tagName = `v${snapshotPlan.mode !== "independent" ? snapshotPlan.version : ""}`;
28562
28702
  task.output = `Creating tag ${tagName}...`;
28563
28703
  const headCommit = await git.latestCommit();
@@ -28624,7 +28764,7 @@ async function run(ctx) {
28624
28764
  skip: ctx.options.skipConditionsCheck
28625
28765
  }).run(ctx);
28626
28766
  }
28627
- const pipelineListrOptions = mode === "ci" || m ? createCiListrOptions() : undefined;
28767
+ const pipelineListrOptions = m ? createCiListrOptions() : undefined;
28628
28768
  await createListr([
28629
28769
  {
28630
28770
  skip: !hasPrepare || ctx.options.skipTests,
@@ -28690,7 +28830,7 @@ async function run(ctx) {
28690
28830
  const git = new Git;
28691
28831
  let tagCreated = false;
28692
28832
  let commited = false;
28693
- const plan = ctx2.runtime.versionPlan;
28833
+ const plan = requireVersionPlan(ctx2);
28694
28834
  task.output = formatVersionPlan(ctx2);
28695
28835
  addRollback(async () => {
28696
28836
  if (tagCreated) {
@@ -28914,7 +29054,7 @@ ${[...plan.packages].map(([pkgPath, ver]) => `- ${getPackageName(ctx2, pkgPath)}
28914
29054
  task: async (ctx2, parentTask) => {
28915
29055
  parentTask.output = "Running plugin beforePublish hooks...";
28916
29056
  await ctx2.runtime.pluginRunner.runHook("beforePublish", ctx2);
28917
- resolveWorkspaceProtocols(ctx2);
29057
+ await resolveWorkspaceProtocols(ctx2);
28918
29058
  const publishTasks = await collectPublishTasks(ctx2);
28919
29059
  parentTask.title = `Publishing (${countPublishTargets(ctx2)} targets)`;
28920
29060
  parentTask.output = formatRegistryGroupSummary("Concurrent publish tasks", ctx2, true);
@@ -28927,7 +29067,11 @@ ${[...plan.packages].map(([pkgPath, ver]) => `- ${getPackageName(ctx2, pkgPath)}
28927
29067
  skip: (ctx2) => !hasPublish || !!ctx2.options.skipPublish || dryRun || !ctx2.runtime.workspaceBackups?.size,
28928
29068
  title: "Restoring workspace protocols",
28929
29069
  task: (ctx2) => {
28930
- restoreManifests(ctx2.runtime.workspaceBackups);
29070
+ const backups = ctx2.runtime.workspaceBackups;
29071
+ if (!backups) {
29072
+ throw new Error("Workspace backups are required for restore.");
29073
+ }
29074
+ restoreManifests(backups);
28931
29075
  ctx2.runtime.workspaceBackups = undefined;
28932
29076
  }
28933
29077
  },
@@ -28944,7 +29088,7 @@ ${[...plan.packages].map(([pkgPath, ver]) => `- ${getPackageName(ctx2, pkgPath)}
28944
29088
  skip: !dryRun && !(mode === "ci" && hasPrepare),
28945
29089
  title: "Validating publish (dry-run)",
28946
29090
  task: async (ctx2, parentTask) => {
28947
- resolveWorkspaceProtocols(ctx2);
29091
+ await resolveWorkspaceProtocols(ctx2);
28948
29092
  await applyVersionsForDryRun(ctx2);
28949
29093
  const dryRunTasks = await collectDryRunPublishTasks(ctx2);
28950
29094
  parentTask.title = `Validating publish (${countRegistryTargets(collectEcosystemRegistryGroups(ctx2.config))} targets)`;
@@ -28958,7 +29102,11 @@ ${[...plan.packages].map(([pkgPath, ver]) => `- ${getPackageName(ctx2, pkgPath)}
28958
29102
  skip: (ctx2) => !dryRun && !(mode === "ci" && hasPrepare) || !ctx2.runtime.workspaceBackups?.size,
28959
29103
  title: "Restoring workspace protocols",
28960
29104
  task: (ctx2) => {
28961
- restoreManifests(ctx2.runtime.workspaceBackups);
29105
+ const backups = ctx2.runtime.workspaceBackups;
29106
+ if (!backups) {
29107
+ throw new Error("Workspace backups are required for restore.");
29108
+ }
29109
+ restoreManifests(backups);
28962
29110
  ctx2.runtime.workspaceBackups = undefined;
28963
29111
  }
28964
29112
  },
@@ -28966,7 +29114,11 @@ ${[...plan.packages].map(([pkgPath, ver]) => `- ${getPackageName(ctx2, pkgPath)}
28966
29114
  skip: (ctx2) => !dryRun || !ctx2.runtime.dryRunVersionBackup?.size,
28967
29115
  title: "Restoring original versions (dry-run)",
28968
29116
  task: async (ctx2) => {
28969
- await writeVersions(ctx2, ctx2.runtime.dryRunVersionBackup);
29117
+ const backupVersions = ctx2.runtime.dryRunVersionBackup;
29118
+ if (!backupVersions) {
29119
+ throw new Error("Dry-run version backup is required for restore.");
29120
+ }
29121
+ await writeVersions(ctx2, backupVersions);
28970
29122
  ctx2.runtime.dryRunVersionBackup = undefined;
28971
29123
  }
28972
29124
  },
@@ -28993,7 +29145,7 @@ ${[...plan.packages].map(([pkgPath, ver]) => `- ${getPackageName(ctx2, pkgPath)}
28993
29145
  skip: (ctx2) => !hasPublish || !!ctx2.options.skipReleaseDraft || dryRun,
28994
29146
  title: "Creating GitHub Release",
28995
29147
  task: async (ctx2, task) => {
28996
- const plan = ctx2.runtime.versionPlan;
29148
+ const plan = requireVersionPlan(ctx2);
28997
29149
  const tokenResult = resolveGitHubToken();
28998
29150
  let hasToken = !!tokenResult;
28999
29151
  if (tokenResult) {
@@ -29039,8 +29191,8 @@ ${[...plan.packages].map(([pkgPath, ver]) => `- ${getPackageName(ctx2, pkgPath)}
29039
29191
  const pkgConfig = ctx2.config.packages.find((p2) => p2.path === pkgPath);
29040
29192
  if (pkgConfig) {
29041
29193
  const changelogPath = join9(process17.cwd(), pkgConfig.path, "CHANGELOG.md");
29042
- if (existsSync5(changelogPath)) {
29043
- const section = parseChangelogSection(readFileSync8(changelogPath, "utf-8"), pkgVersion);
29194
+ if (existsSync6(changelogPath)) {
29195
+ const section = parseChangelogSection(readFileSync9(changelogPath, "utf-8"), pkgVersion);
29044
29196
  if (section)
29045
29197
  changelogBody = section;
29046
29198
  }
@@ -29086,8 +29238,8 @@ ${[...plan.packages].map(([pkgPath, ver]) => `- ${getPackageName(ctx2, pkgPath)}
29086
29238
  if (!pkgConfig)
29087
29239
  continue;
29088
29240
  const changelogPath = join9(process17.cwd(), pkgConfig.path, "CHANGELOG.md");
29089
- if (existsSync5(changelogPath)) {
29090
- const section = parseChangelogSection(readFileSync8(changelogPath, "utf-8"), pkgVersion);
29241
+ if (existsSync6(changelogPath)) {
29242
+ const section = parseChangelogSection(readFileSync9(changelogPath, "utf-8"), pkgVersion);
29091
29243
  if (section) {
29092
29244
  sections.push(`## ${pkgName} v${pkgVersion}
29093
29245
 
@@ -29104,8 +29256,8 @@ ${section}`);
29104
29256
  }
29105
29257
  } else {
29106
29258
  const changelogPath = join9(process17.cwd(), "CHANGELOG.md");
29107
- if (existsSync5(changelogPath)) {
29108
- const section = parseChangelogSection(readFileSync8(changelogPath, "utf-8"), version);
29259
+ if (existsSync6(changelogPath)) {
29260
+ const section = parseChangelogSection(readFileSync9(changelogPath, "utf-8"), version);
29109
29261
  if (section)
29110
29262
  changelogBody = section;
29111
29263
  }
@@ -29245,13 +29397,13 @@ function maxBump(a3, b2) {
29245
29397
  return BUMP_ORDER[a3] >= BUMP_ORDER[b2] ? a3 : b2;
29246
29398
  }
29247
29399
  // src/changeset/migrate.ts
29248
- import { copyFileSync, existsSync as existsSync6, mkdirSync as mkdirSync3, readdirSync as readdirSync4 } from "node:fs";
29400
+ import { copyFileSync, existsSync as existsSync7, mkdirSync as mkdirSync3, readdirSync as readdirSync4 } from "node:fs";
29249
29401
  import path11 from "node:path";
29250
29402
  import process18 from "node:process";
29251
29403
  var SKIPPED_FILES = new Set(["config.json", "README.md"]);
29252
29404
  function migrateFromChangesets(cwd = process18.cwd()) {
29253
29405
  const changesetDir = path11.join(cwd, ".changeset");
29254
- if (!existsSync6(changesetDir)) {
29406
+ if (!existsSync7(changesetDir)) {
29255
29407
  return {
29256
29408
  success: false,
29257
29409
  error: ".changeset/ directory not found",
@@ -29352,7 +29504,7 @@ function calculateVersionBumps(currentVersions, cwd = process20.cwd(), resolveKe
29352
29504
  return result;
29353
29505
  }
29354
29506
  // src/changeset/writer.ts
29355
- import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync5 } from "node:fs";
29507
+ import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync7 } from "node:fs";
29356
29508
  import path12 from "node:path";
29357
29509
  import process21 from "node:process";
29358
29510
  var adjectives = [
@@ -29455,7 +29607,7 @@ function writeChangeset(releases, summary, cwd = process21.cwd()) {
29455
29607
  const fileName = `${id}.md`;
29456
29608
  const filePath = path12.join(changesetsDir, fileName);
29457
29609
  const content = generateChangesetContent(releases, summary);
29458
- writeFileSync5(filePath, content, "utf-8");
29610
+ writeFileSync7(filePath, content, "utf-8");
29459
29611
  return filePath;
29460
29612
  }
29461
29613
  // src/config/defaults.ts
@@ -29481,7 +29633,8 @@ var defaultConfig = {
29481
29633
  saveToken: true,
29482
29634
  releaseDraft: true,
29483
29635
  releaseNotes: true,
29484
- rollbackStrategy: "individual"
29636
+ rollbackStrategy: "individual",
29637
+ lockfileSync: "optional"
29485
29638
  };
29486
29639
  async function resolveConfig(config, cwd) {
29487
29640
  const resolvedCwd = cwd ?? process.cwd();
@@ -29545,7 +29698,7 @@ import {
29545
29698
  mkdtemp,
29546
29699
  readFile as readFile7,
29547
29700
  rm,
29548
- stat as stat5,
29701
+ stat as stat6,
29549
29702
  writeFile as writeFile3
29550
29703
  } from "node:fs/promises";
29551
29704
  import { createRequire as createRequire2 } from "node:module";
@@ -29605,7 +29758,7 @@ async function findConfigFile(cwd) {
29605
29758
  for (const file of CONFIG_FILES) {
29606
29759
  const filePath = path13.join(cwd, file);
29607
29760
  try {
29608
- if ((await stat5(filePath)).isFile()) {
29761
+ if ((await stat6(filePath)).isFile()) {
29609
29762
  return filePath;
29610
29763
  }
29611
29764
  } catch {}
@@ -29628,7 +29781,7 @@ async function findClosestPackageManifest(filePath) {
29628
29781
  while (true) {
29629
29782
  const manifestPath = path13.join(current, "package.json");
29630
29783
  try {
29631
- if ((await stat5(manifestPath)).isFile()) {
29784
+ if ((await stat6(manifestPath)).isFile()) {
29632
29785
  return manifestPath;
29633
29786
  }
29634
29787
  } catch {}
@@ -29736,7 +29889,7 @@ async function findInstalledPackagePath(startDir, dependency) {
29736
29889
  while (true) {
29737
29890
  const packageDir = path13.join(current, "node_modules", dependency);
29738
29891
  try {
29739
- if ((await stat5(packageDir)).isDirectory()) {
29892
+ if ((await stat6(packageDir)).isDirectory()) {
29740
29893
  return packageDir;
29741
29894
  }
29742
29895
  } catch {}
@@ -30217,17 +30370,32 @@ function formatStageError(stage, error2) {
30217
30370
  const message = error2 instanceof Error ? error2.stack ?? error2.message : String(error2);
30218
30371
  return `[${stage}] ${message}`;
30219
30372
  }
30220
- async function loadConfig(cwd = process.cwd()) {
30221
- const configPath = await findConfigFile(cwd);
30222
- if (!configPath)
30373
+ async function loadConfig(cwd = process.cwd(), configPath) {
30374
+ let resolvedConfigPath;
30375
+ if (configPath) {
30376
+ resolvedConfigPath = path13.resolve(cwd, configPath);
30377
+ try {
30378
+ if (!(await stat6(resolvedConfigPath)).isFile()) {
30379
+ throw new Error(`Config path is not a file: ${resolvedConfigPath}`);
30380
+ }
30381
+ } catch (e3) {
30382
+ if (e3.code === "ENOENT") {
30383
+ throw new Error(`Config file not found: ${resolvedConfigPath}`);
30384
+ }
30385
+ throw e3;
30386
+ }
30387
+ } else {
30388
+ resolvedConfigPath = await findConfigFile(cwd);
30389
+ }
30390
+ if (!resolvedConfigPath)
30223
30391
  return null;
30224
30392
  const errors2 = [];
30225
30393
  try {
30226
- return await importConfigModule(configPath);
30394
+ return await importConfigModule(resolvedConfigPath);
30227
30395
  } catch (error2) {
30228
30396
  errors2.push(formatStageError("native import", error2));
30229
30397
  }
30230
- const output = await buildConfig(configPath);
30398
+ const output = await buildConfig(resolvedConfigPath);
30231
30399
  if (!output.success) {
30232
30400
  errors2.push(formatStageError("bundled build", output.logs.map((log) => log.message).join(`
30233
30401
  `)));
@@ -30246,11 +30414,11 @@ ${errors2.join(`
30246
30414
  }
30247
30415
  const bundledSource = await entrypoint.text();
30248
30416
  try {
30249
- return await importBundledConfig(bundledSource, configPath, output.optionalDependencies);
30417
+ return await importBundledConfig(bundledSource, resolvedConfigPath, output.optionalDependencies);
30250
30418
  } catch (error2) {
30251
30419
  errors2.push(formatStageError("bundled import", error2));
30252
30420
  }
30253
- const vmOutput = await buildConfigWithFormat(configPath, "cjs");
30421
+ const vmOutput = await buildConfigWithFormat(resolvedConfigPath, "cjs");
30254
30422
  if (!vmOutput.success) {
30255
30423
  errors2.push(formatStageError("bundled vm build", vmOutput.logs.map((log) => log.message).join(`
30256
30424
  `)));
@@ -30268,7 +30436,7 @@ ${errors2.join(`
30268
30436
  `)}`);
30269
30437
  }
30270
30438
  try {
30271
- return await executeBundledConfigInVm(await vmEntrypoint.text(), configPath);
30439
+ return await executeBundledConfigInVm(await vmEntrypoint.text(), resolvedConfigPath);
30272
30440
  } catch (error2) {
30273
30441
  errors2.push(formatStageError("bundled vm", error2));
30274
30442
  throw new Error(`Failed to load config:
@@ -30688,6 +30856,9 @@ async function handleMultiPackage(ctx, task, packageInfos) {
30688
30856
  if (result === "accepted")
30689
30857
  return;
30690
30858
  if (result === "add_packages") {
30859
+ if (!bumps) {
30860
+ throw new Error("Changeset bumps are required for add_packages.");
30861
+ }
30691
30862
  await handleAddPackages(ctx, task, sortedPackageInfos, currentVersions, graph, bumps);
30692
30863
  return;
30693
30864
  }
@@ -30711,6 +30882,7 @@ async function handleRemainingPackages(ctx, task, remainingPackages, packageInfo
30711
30882
  const versions = new Map([...bumps].map(([p2, b2]) => [p2, b2.newVersion]));
30712
30883
  const publishPaths = new Set(bumps.keys());
30713
30884
  const reverseDeps = buildReverseDeps(graph);
30885
+ let lastBumpType;
30714
30886
  for (const pkg of remainingPackages) {
30715
30887
  const currentVersion = currentVersions.get(pkg.path) ?? pkg.version;
30716
30888
  const deps = graph.get(pkg.path) ?? [];
@@ -30723,8 +30895,9 @@ async function handleRemainingPackages(ctx, task, remainingPackages, packageInfo
30723
30895
  if (pkgNotes.length > 0) {
30724
30896
  task.output = renderPackageVersionSummary(remainingPackages, currentVersions, versions, { activePackage: pkg.path, notes: new Map([[pkg.path, pkgNotes]]) });
30725
30897
  }
30726
- const result = await promptVersion(task, currentVersion, pkg.name);
30898
+ const result = await promptVersion(task, currentVersion, pkg.name, undefined, lastBumpType);
30727
30899
  versions.set(pkg.path, result.version);
30900
+ lastBumpType = result.bumpType;
30728
30901
  if (result.version !== currentVersion) {
30729
30902
  bumpedPackages.add(pkg.path);
30730
30903
  publishPaths.add(pkg.path);
@@ -31031,7 +31204,7 @@ import { homedir as homedir2 } from "os";
31031
31204
  import { join as join10 } from "path";
31032
31205
  import os2 from "os";
31033
31206
  import path32 from "path";
31034
- import { readFileSync as readFileSync9 } from "fs";
31207
+ import { readFileSync as readFileSync10 } from "fs";
31035
31208
  import { readFile as readFile22 } from "fs/promises";
31036
31209
  import { dirname, join as join22, resolve as resolve2, sep } from "path";
31037
31210
  import { fileURLToPath } from "url";
@@ -32611,7 +32784,7 @@ function findPackageJsonSync(startDir) {
32611
32784
  for (;; ) {
32612
32785
  const candidate = join22(current, "package.json");
32613
32786
  try {
32614
- const content = readFileSync9(candidate, "utf-8");
32787
+ const content = readFileSync10(candidate, "utf-8");
32615
32788
  const result = parsePackageJson(content, candidate);
32616
32789
  if (result)
32617
32790
  return result;
@@ -33014,11 +33187,11 @@ function isBun2() {
33014
33187
  init_ui();
33015
33188
 
33016
33189
  // src/validate/entry-points.ts
33017
- import { existsSync as existsSync7 } from "node:fs";
33190
+ import { existsSync as existsSync8 } from "node:fs";
33018
33191
  import path15 from "node:path";
33019
33192
  var SIMPLE_FIELDS = ["main", "module", "types", "typings"];
33020
33193
  function checkPath(filePath, cwd) {
33021
- return existsSync7(path15.resolve(cwd, filePath));
33194
+ return existsSync8(path15.resolve(cwd, filePath));
33022
33195
  }
33023
33196
  function validateExports(exports, cwd, prefix = "exports") {
33024
33197
  const errors2 = [];