pubm 0.1.3 → 0.1.5

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.
package/bin/cli.js CHANGED
@@ -2416,15 +2416,15 @@ var isCompatibleTerminal = tty && tty.isatty && tty.isatty(1) && env.TERM && !is
2416
2416
  var isCI = "CI" in env && ("GITHUB_ACTIONS" in env || "GITLAB_CI" in env || "CIRCLECI" in env);
2417
2417
  var isColorSupported = !isDisabled && (isForced || isWindows && !isDumbTerminal || isCompatibleTerminal || isCI);
2418
2418
  var replaceClose = (index, string, close, replace, head = string.substring(0, index) + replace, tail = string.substring(index + close.length), next = tail.indexOf(close)) => head + (next < 0 ? tail : replaceClose(next, tail, close, replace));
2419
- var clearBleed = (index, string, open2, close, replace) => index < 0 ? open2 + string + close : open2 + replaceClose(index, string, close, replace) + close;
2420
- var filterEmpty = (open2, close, replace = open2, at = open2.length + 1) => (string) => string || !(string === "" || string === void 0) ? clearBleed(
2419
+ var clearBleed = (index, string, open4, close, replace) => index < 0 ? open4 + string + close : open4 + replaceClose(index, string, close, replace) + close;
2420
+ var filterEmpty = (open4, close, replace = open4, at = open4.length + 1) => (string) => string || !(string === "" || string === void 0) ? clearBleed(
2421
2421
  ("" + string).indexOf(close, at),
2422
2422
  string,
2423
- open2,
2423
+ open4,
2424
2424
  close,
2425
2425
  replace
2426
2426
  ) : "";
2427
- var init = (open2, close, replace) => filterEmpty(`\x1B[${open2}m`, `\x1B[${close}m`, replace);
2427
+ var init = (open4, close, replace) => filterEmpty(`\x1B[${open4}m`, `\x1B[${close}m`, replace);
2428
2428
  var colors = {
2429
2429
  reset: init(0, 0),
2430
2430
  bold: init(1, 22, "\x1B[22m\x1B[1m"),
@@ -4899,7 +4899,7 @@ var Git = class {
4899
4899
  try {
4900
4900
  return (await this.git(["tag", "-l"])).trim().split("\n").sort(semver.compareIdentifiers);
4901
4901
  } catch (error) {
4902
- throw new GitError("Failed to run `git config --get user.name`", {
4902
+ throw new GitError("Failed to run `git tag -l`", {
4903
4903
  cause: error
4904
4904
  });
4905
4905
  }
@@ -4945,7 +4945,8 @@ var Git = class {
4945
4945
  async revisionDiffsCount() {
4946
4946
  try {
4947
4947
  return Number.parseInt(
4948
- await this.git(["rev-list", "@{u}...HEAD", "--count", "--left-only"])
4948
+ await this.git(["rev-list", "@{u}...HEAD", "--count", "--left-only"]),
4949
+ 10
4949
4950
  );
4950
4951
  } catch (error) {
4951
4952
  throw new GitError(
@@ -5145,6 +5146,80 @@ var Git = class {
5145
5146
  }
5146
5147
  };
5147
5148
 
5149
+ // src/config/defaults.ts
5150
+ var defaultValidate = {
5151
+ cleanInstall: true,
5152
+ entryPoints: true,
5153
+ extraneousFiles: true
5154
+ };
5155
+ var defaultSnapshot = {
5156
+ useCalculatedVersion: false,
5157
+ prereleaseTemplate: "{tag}-{timestamp}"
5158
+ };
5159
+ var defaultConfig = {
5160
+ versioning: "independent",
5161
+ branch: "main",
5162
+ changelog: true,
5163
+ changelogFormat: "default",
5164
+ commit: false,
5165
+ access: "public",
5166
+ fixed: [],
5167
+ linked: [],
5168
+ updateInternalDependencies: "patch",
5169
+ ignore: [],
5170
+ tag: "latest",
5171
+ contents: ".",
5172
+ saveToken: true,
5173
+ releaseDraft: true,
5174
+ releaseNotes: true,
5175
+ registries: ["npm", "jsr"],
5176
+ rollbackStrategy: "individual"
5177
+ };
5178
+ function resolveConfig(config) {
5179
+ const packages = config.packages ?? [
5180
+ { path: ".", registries: ["npm", "jsr"] }
5181
+ ];
5182
+ return {
5183
+ ...defaultConfig,
5184
+ ...config,
5185
+ packages,
5186
+ validate: { ...defaultValidate, ...config.validate },
5187
+ snapshot: { ...defaultSnapshot, ...config.snapshot }
5188
+ };
5189
+ }
5190
+
5191
+ // src/config/loader.ts
5192
+ import { stat } from "node:fs/promises";
5193
+ import path6 from "node:path";
5194
+ var CONFIG_FILES = [
5195
+ "pubm.config.ts",
5196
+ "pubm.config.mts",
5197
+ "pubm.config.cts",
5198
+ "pubm.config.js",
5199
+ "pubm.config.mjs",
5200
+ "pubm.config.cjs"
5201
+ ];
5202
+ async function findConfigFile(cwd) {
5203
+ for (const file of CONFIG_FILES) {
5204
+ const filePath = path6.join(cwd, file);
5205
+ try {
5206
+ if ((await stat(filePath)).isFile()) {
5207
+ return filePath;
5208
+ }
5209
+ } catch {
5210
+ }
5211
+ }
5212
+ return null;
5213
+ }
5214
+ async function loadConfig(cwd = process.cwd()) {
5215
+ const configPath = await findConfigFile(cwd);
5216
+ if (!configPath) return null;
5217
+ const { createJiti } = await import("jiti");
5218
+ const jiti = createJiti(cwd, { interopDefault: true });
5219
+ const mod = await jiti.import(configPath);
5220
+ return mod.default ?? mod;
5221
+ }
5222
+
5148
5223
  // src/options.ts
5149
5224
  var defaultOptions = {
5150
5225
  testScript: "test",
@@ -5154,13 +5229,16 @@ var defaultOptions = {
5154
5229
  registries: ["npm", "jsr"]
5155
5230
  };
5156
5231
  function resolveOptions(options) {
5157
- const nextOptions = { ...options, ...defaultOptions };
5232
+ const defined = Object.fromEntries(
5233
+ Object.entries(options).filter(([, v]) => v !== void 0)
5234
+ );
5235
+ const nextOptions = { ...defaultOptions, ...defined };
5158
5236
  return nextOptions;
5159
5237
  }
5160
5238
 
5161
5239
  // src/tasks/runner.ts
5162
5240
  import process14 from "node:process";
5163
- import npmCli from "@npmcli/promise-spawn";
5241
+ import npmCli3 from "@npmcli/promise-spawn";
5164
5242
  import SemVer from "semver";
5165
5243
  import { isCI as isCI2 } from "std-env";
5166
5244
  import { exec as exec7 } from "tinyexec";
@@ -5182,8 +5260,24 @@ async function rollback() {
5182
5260
  called = true;
5183
5261
  if (rollbacks.length <= 0) return void 0;
5184
5262
  console.log("Rollback...");
5185
- await Promise.all(rollbacks.map(({ fn, ctx }) => fn(ctx)));
5186
- console.log("Rollback completed");
5263
+ const results = await Promise.allSettled(
5264
+ rollbacks.map(({ fn, ctx }) => fn(ctx))
5265
+ );
5266
+ const failures = results.filter(
5267
+ (r) => r.status === "rejected"
5268
+ );
5269
+ if (failures.length > 0) {
5270
+ for (const failure of failures) {
5271
+ console.error(
5272
+ `Rollback operation failed: ${failure.reason instanceof Error ? failure.reason.message : failure.reason}`
5273
+ );
5274
+ }
5275
+ console.log(
5276
+ "Rollback completed with errors. Some operations may require manual recovery."
5277
+ );
5278
+ } else {
5279
+ console.log("Rollback completed");
5280
+ }
5187
5281
  }
5188
5282
 
5189
5283
  // src/utils/listr.ts
@@ -5195,8 +5289,8 @@ function createListr(...args) {
5195
5289
  }
5196
5290
 
5197
5291
  // src/utils/package.ts
5198
- import { readFile, stat, writeFile } from "node:fs/promises";
5199
- import path6 from "node:path";
5292
+ import { readFile, stat as stat2, writeFile } from "node:fs/promises";
5293
+ import path7 from "node:path";
5200
5294
  import process11 from "node:process";
5201
5295
  var cachedPackageJson = {};
5202
5296
  var cachedJsrJson = {};
@@ -5206,16 +5300,16 @@ function patchCachedJsrJson(contents, { cwd = process11.cwd() } = {}) {
5206
5300
  async function findOutFile(file, { cwd = process11.cwd() } = {}) {
5207
5301
  let directory = cwd;
5208
5302
  let filePath = "";
5209
- const { root } = path6.parse(cwd);
5303
+ const { root } = path7.parse(cwd);
5210
5304
  while (directory) {
5211
- filePath = path6.join(directory, file);
5305
+ filePath = path7.join(directory, file);
5212
5306
  try {
5213
- if ((await stat(filePath)).isFile()) {
5307
+ if ((await stat2(filePath)).isFile()) {
5214
5308
  break;
5215
5309
  }
5216
5310
  } catch {
5217
5311
  }
5218
- directory = path6.dirname(directory);
5312
+ directory = path7.dirname(directory);
5219
5313
  if (directory === root) return null;
5220
5314
  }
5221
5315
  return filePath;
@@ -5350,20 +5444,34 @@ async function replaceVersion(version2) {
5350
5444
  const packageJsonPath = await findOutFile("package.json");
5351
5445
  if (!packageJsonPath) return void 0;
5352
5446
  const packageJson = (await readFile(packageJsonPath)).toString();
5353
- await writeFile(
5354
- packageJsonPath,
5355
- packageJson.replace(versionRegex, `$1${version2}$2`)
5356
- );
5447
+ try {
5448
+ await writeFile(
5449
+ packageJsonPath,
5450
+ packageJson.replace(versionRegex, `$1${version2}$2`)
5451
+ );
5452
+ } catch (error) {
5453
+ throw new AbstractError(
5454
+ `Failed to write version to package.json: ${error instanceof Error ? error.message : error}`,
5455
+ { cause: error }
5456
+ );
5457
+ }
5357
5458
  return "package.json";
5358
5459
  })(),
5359
5460
  (async () => {
5360
5461
  const jsrJsonPath = await findOutFile("jsr.json");
5361
5462
  if (!jsrJsonPath) return void 0;
5362
5463
  const jsrJson = (await readFile(jsrJsonPath)).toString();
5363
- await writeFile(
5364
- jsrJsonPath,
5365
- jsrJson.replace(versionRegex, `$1${version2}$2`)
5366
- );
5464
+ try {
5465
+ await writeFile(
5466
+ jsrJsonPath,
5467
+ jsrJson.replace(versionRegex, `$1${version2}$2`)
5468
+ );
5469
+ } catch (error) {
5470
+ throw new AbstractError(
5471
+ `Failed to write version to jsr.json: ${error instanceof Error ? error.message : error}`,
5472
+ { cause: error }
5473
+ );
5474
+ }
5367
5475
  return "jsr.json";
5368
5476
  })()
5369
5477
  ]);
@@ -5382,12 +5490,13 @@ async function getPackageManager() {
5382
5490
  if (await findOutFile(lockFile2)) return packageManager;
5383
5491
  }
5384
5492
  }
5493
+ console.warn("No lock file found, defaulting to npm.");
5385
5494
  return "npm";
5386
5495
  }
5387
5496
 
5388
5497
  // src/ecosystem/rust.ts
5389
- import { readFile as readFile2, stat as stat2, writeFile as writeFile2 } from "node:fs/promises";
5390
- import path7 from "node:path";
5498
+ import { readFile as readFile2, stat as stat3, writeFile as writeFile2 } from "node:fs/promises";
5499
+ import path8 from "node:path";
5391
5500
  import { parse, stringify } from "smol-toml";
5392
5501
 
5393
5502
  // src/ecosystem/ecosystem.ts
@@ -5401,14 +5510,14 @@ var Ecosystem = class {
5401
5510
  var RustEcosystem = class extends Ecosystem {
5402
5511
  static async detect(packagePath) {
5403
5512
  try {
5404
- return (await stat2(path7.join(packagePath, "Cargo.toml"))).isFile();
5513
+ return (await stat3(path8.join(packagePath, "Cargo.toml"))).isFile();
5405
5514
  } catch {
5406
5515
  return false;
5407
5516
  }
5408
5517
  }
5409
5518
  async readCargoToml() {
5410
5519
  const raw = await readFile2(
5411
- path7.join(this.packagePath, "Cargo.toml"),
5520
+ path8.join(this.packagePath, "Cargo.toml"),
5412
5521
  "utf-8"
5413
5522
  );
5414
5523
  return parse(raw);
@@ -5424,7 +5533,7 @@ var RustEcosystem = class extends Ecosystem {
5424
5533
  return pkg.version;
5425
5534
  }
5426
5535
  async writeVersion(newVersion) {
5427
- const filePath = path7.join(this.packagePath, "Cargo.toml");
5536
+ const filePath = path8.join(this.packagePath, "Cargo.toml");
5428
5537
  const raw = await readFile2(filePath, "utf-8");
5429
5538
  const cargo = parse(raw);
5430
5539
  const pkg = cargo.package;
@@ -5500,13 +5609,21 @@ var CratesRegistry = class extends Registry {
5500
5609
  { headers: this.headers }
5501
5610
  );
5502
5611
  if (!response.ok) {
5503
- throw new Error(`Crate '${this.packageName}' not found`);
5612
+ if (response.status === 404) {
5613
+ throw new CratesError(
5614
+ `Crate '${this.packageName}' not found on crates.io`
5615
+ );
5616
+ }
5617
+ throw new CratesError(
5618
+ `crates.io API error (HTTP ${response.status}) for crate '${this.packageName}'`
5619
+ );
5504
5620
  }
5505
5621
  const data = await response.json();
5506
5622
  return data.crate.max_version;
5507
5623
  } catch (error) {
5624
+ if (error instanceof CratesError) throw error;
5508
5625
  throw new CratesError(
5509
- `Failed to fetch version for crate '${this.packageName}'`,
5626
+ `Cannot reach crates.io to fetch version for '${this.packageName}'`,
5510
5627
  { cause: error }
5511
5628
  );
5512
5629
  }
@@ -5536,6 +5653,12 @@ var CratesRegistry = class extends Registry {
5536
5653
  if (process.env.CARGO_REGISTRY_TOKEN) return true;
5537
5654
  return this.isInstalled();
5538
5655
  }
5656
+ getRequirements() {
5657
+ return {
5658
+ needsPackageScripts: false,
5659
+ requiredManifest: "Cargo.toml"
5660
+ };
5661
+ }
5539
5662
  async isPackageNameAvaliable() {
5540
5663
  try {
5541
5664
  const response = await fetch(
@@ -5543,8 +5666,11 @@ var CratesRegistry = class extends Registry {
5543
5666
  { headers: this.headers }
5544
5667
  );
5545
5668
  return !response.ok;
5546
- } catch {
5547
- return true;
5669
+ } catch (error) {
5670
+ throw new CratesError(
5671
+ `Failed to check package name availability on crates.io`,
5672
+ { cause: error }
5673
+ );
5548
5674
  }
5549
5675
  }
5550
5676
  };
@@ -5593,6 +5719,7 @@ var cratesPublishTasks = {
5593
5719
  // src/tasks/jsr.ts
5594
5720
  import process12 from "node:process";
5595
5721
  import { ListrEnquirerPromptAdapter } from "@listr2/prompt-adapter-enquirer";
5722
+ import npmCli from "@npmcli/promise-spawn";
5596
5723
 
5597
5724
  // src/registry/jsr.ts
5598
5725
  import { exec as exec4, NonZeroExitError } from "tinyexec";
@@ -5600,7 +5727,7 @@ import { exec as exec4, NonZeroExitError } from "tinyexec";
5600
5727
  // src/utils/db.ts
5601
5728
  import { createCipheriv, createDecipheriv, createHash } from "node:crypto";
5602
5729
  import { mkdirSync as mkdirSync5, readFileSync as readFileSync3, statSync, writeFileSync as writeFileSync4 } from "node:fs";
5603
- import path8 from "node:path";
5730
+ import path9 from "node:path";
5604
5731
  var a = "aes-256-cbc";
5605
5732
  var n = statSync(import.meta.dirname);
5606
5733
  var k = `${n.rdev}${n.birthtimeMs}${n.nlink}${n.gid}`;
@@ -5615,36 +5742,54 @@ function d(g, h) {
5615
5742
  }
5616
5743
  var Db = class {
5617
5744
  constructor() {
5618
- __publicField(this, "path", path8.resolve(import.meta.dirname, ".pubm"));
5745
+ __publicField(this, "path", path9.resolve(import.meta.dirname, ".pubm"));
5619
5746
  try {
5620
5747
  if (!statSync(this.path).isDirectory()) {
5621
5748
  mkdirSync5(this.path);
5622
5749
  }
5623
5750
  } catch {
5624
- mkdirSync5(this.path);
5751
+ try {
5752
+ mkdirSync5(this.path);
5753
+ } catch (error) {
5754
+ throw new Error(
5755
+ `Failed to create token storage directory at '${this.path}': ${error instanceof Error ? error.message : error}`
5756
+ );
5757
+ }
5625
5758
  }
5626
5759
  }
5627
5760
  set(field, value) {
5628
- writeFileSync4(
5629
- path8.resolve(this.path, Buffer.from(e(field, field)).toString("base64")),
5630
- Buffer.from(e(`${value}`, field)),
5631
- { encoding: "binary" }
5632
- );
5761
+ try {
5762
+ writeFileSync4(
5763
+ path9.resolve(
5764
+ this.path,
5765
+ Buffer.from(e(field, field)).toString("base64")
5766
+ ),
5767
+ Buffer.from(e(`${value}`, field)),
5768
+ { encoding: "binary" }
5769
+ );
5770
+ } catch (error) {
5771
+ throw new Error(
5772
+ `Failed to save token for '${field}': ${error instanceof Error ? error.message : error}`
5773
+ );
5774
+ }
5633
5775
  }
5634
5776
  get(field) {
5777
+ const filePath = path9.resolve(
5778
+ this.path,
5779
+ Buffer.from(e(field, field)).toString("base64")
5780
+ );
5781
+ let raw;
5635
5782
  try {
5636
- return d(
5637
- Buffer.from(
5638
- readFileSync3(
5639
- path8.resolve(
5640
- this.path,
5641
- Buffer.from(e(field, field)).toString("base64")
5642
- )
5643
- )
5644
- ).toString(),
5645
- field
5646
- );
5783
+ raw = readFileSync3(filePath);
5784
+ } catch {
5785
+ return null;
5786
+ }
5787
+ try {
5788
+ return d(Buffer.from(raw).toString(), field);
5647
5789
  } catch {
5790
+ console.warn(
5791
+ `Stored token for '${field}' appears corrupted. It will be re-requested.`
5792
+ );
5648
5793
  return null;
5649
5794
  }
5650
5795
  }
@@ -5660,9 +5805,12 @@ function getScope(packageName) {
5660
5805
  }
5661
5806
  function getScopeAndName(packageName) {
5662
5807
  const matches = packageName.match(/^@([a-zA-Z0-9]+)\/([a-zA-Z0-9]+)$/);
5663
- const scope = matches?.[1];
5664
- const name = matches?.[2];
5665
- return [`${scope}`, `${name}`];
5808
+ if (!matches) {
5809
+ throw new Error(
5810
+ `Invalid scoped package name: '${packageName}'. Expected format: @scope/name`
5811
+ );
5812
+ }
5813
+ return [matches[1], matches[2]];
5666
5814
  }
5667
5815
  var scopedPackagePattern = /^(?:@([^/]+?)[/])?([^/]+?)$/;
5668
5816
  var blacklist = ["node_modules", "favicon.ico"];
@@ -5708,6 +5856,7 @@ var JsrRegisry = class extends Registry {
5708
5856
  super(packageName, registry);
5709
5857
  __publicField(this, "registry", "https://jsr.io");
5710
5858
  __publicField(this, "client");
5859
+ __publicField(this, "packageCreationUrls");
5711
5860
  this.client = new JsrClient(getApiEndpoint(this.registry));
5712
5861
  }
5713
5862
  async jsr(args) {
@@ -5749,9 +5898,19 @@ var JsrRegisry = class extends Registry {
5749
5898
  throwOnError: true
5750
5899
  }
5751
5900
  );
5901
+ this.packageCreationUrls = void 0;
5752
5902
  return true;
5753
5903
  } catch (error) {
5754
5904
  const stderr = error instanceof NonZeroExitError ? error.output?.stderr : void 0;
5905
+ if (stderr?.includes("don't exist")) {
5906
+ const urls = [...stderr.matchAll(/https:\/\/jsr\.io\/new\S+/g)].map(
5907
+ (m) => m[0]
5908
+ );
5909
+ if (urls.length > 0) {
5910
+ this.packageCreationUrls = urls;
5911
+ return false;
5912
+ }
5913
+ }
5755
5914
  throw new JsrError(
5756
5915
  `Failed to run \`jsr publish --allow-dirty --token ***\`${stderr ? `
5757
5916
  ${stderr}` : ""}`,
@@ -5781,6 +5940,12 @@ ${stderr}` : ""}`,
5781
5940
  async isPackageNameAvaliable() {
5782
5941
  return isValidPackageName(this.packageName);
5783
5942
  }
5943
+ getRequirements() {
5944
+ return {
5945
+ needsPackageScripts: false,
5946
+ requiredManifest: "jsr.json"
5947
+ };
5948
+ }
5784
5949
  };
5785
5950
  var _JsrClient = class _JsrClient {
5786
5951
  constructor(apiEndpoint) {
@@ -5802,9 +5967,7 @@ var _JsrClient = class _JsrClient {
5802
5967
  const response = await this.fetch("/user");
5803
5968
  if (response.status === 401) return null;
5804
5969
  if (!response.ok) {
5805
- throw new Error(
5806
- `HTTP ${response.status}: ${response.statusText}`
5807
- );
5970
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
5808
5971
  }
5809
5972
  return await response.json();
5810
5973
  } catch (error) {
@@ -5818,9 +5981,7 @@ var _JsrClient = class _JsrClient {
5818
5981
  const response = await this.fetch(`/user/member/${scope}`);
5819
5982
  if (response.status === 401) return null;
5820
5983
  if (!response.ok) {
5821
- throw new Error(
5822
- `HTTP ${response.status}: ${response.statusText}`
5823
- );
5984
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
5824
5985
  }
5825
5986
  return await response.json();
5826
5987
  } catch (error) {
@@ -5837,15 +5998,11 @@ var _JsrClient = class _JsrClient {
5837
5998
  const response = await this.fetch("/user/scopes");
5838
5999
  if (response.status === 401) return [];
5839
6000
  if (!response.ok) {
5840
- throw new Error(
5841
- `HTTP ${response.status}: ${response.statusText}`
5842
- );
6001
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
5843
6002
  }
5844
6003
  const body = await response.json();
5845
6004
  if (!Array.isArray(body)) {
5846
- throw new Error(
5847
- `Expected array response but got ${typeof body}`
5848
- );
6005
+ throw new Error(`Expected array response but got ${typeof body}`);
5849
6006
  }
5850
6007
  return body.map(({ scope }) => scope);
5851
6008
  } catch (error) {
@@ -5861,9 +6018,15 @@ var _JsrClient = class _JsrClient {
5861
6018
  const [scope, name] = getScopeAndName(packageName);
5862
6019
  try {
5863
6020
  const response = await this.fetch(`/scopes/${scope}/packages/${name}`);
5864
- if (!response.ok) return null;
6021
+ if (response.status === 404) return null;
6022
+ if (!response.ok) {
6023
+ throw new JsrError(
6024
+ `JSR API error (HTTP ${response.status}) for package '${packageName}'`
6025
+ );
6026
+ }
5865
6027
  return await response.json();
5866
6028
  } catch (error) {
6029
+ if (error instanceof JsrError) throw error;
5867
6030
  throw new JsrError(
5868
6031
  `Failed to fetch \`${this.apiEndpoint}/scopes/${scope}/packages/${name}\``,
5869
6032
  {
@@ -5878,8 +6041,18 @@ var _JsrClient = class _JsrClient {
5878
6041
  method: "POST",
5879
6042
  body: JSON.stringify({ scope })
5880
6043
  });
5881
- return response.status === 200 || response.status === 201;
6044
+ if (response.status === 200 || response.status === 201) return true;
6045
+ let detail = "";
6046
+ try {
6047
+ const body = await response.json();
6048
+ detail = body.message || body.error || JSON.stringify(body);
6049
+ } catch {
6050
+ }
6051
+ throw new JsrError(
6052
+ `Failed to create scope '${scope}': HTTP ${response.status}${detail ? ` \u2014 ${detail}` : ""}`
6053
+ );
5882
6054
  } catch (error) {
6055
+ if (error instanceof JsrError) throw error;
5883
6056
  throw new JsrError(`Failed to fetch \`${this.apiEndpoint}/scopes\``, {
5884
6057
  cause: error
5885
6058
  });
@@ -5890,8 +6063,18 @@ var _JsrClient = class _JsrClient {
5890
6063
  const response = await this.fetch(`/scopes/${scope}`, {
5891
6064
  method: "DELETE"
5892
6065
  });
5893
- return response.status === 200 || response.status === 204;
6066
+ if (response.status === 200 || response.status === 204) return true;
6067
+ let detail = "";
6068
+ try {
6069
+ const body = await response.json();
6070
+ detail = body.message || body.error || JSON.stringify(body);
6071
+ } catch {
6072
+ }
6073
+ throw new JsrError(
6074
+ `Failed to delete scope '${scope}': HTTP ${response.status}${detail ? ` \u2014 ${detail}` : ""}`
6075
+ );
5894
6076
  } catch (error) {
6077
+ if (error instanceof JsrError) throw error;
5895
6078
  throw new JsrError(
5896
6079
  `Failed to fetch \`${this.apiEndpoint}/scopes/${scope}\``,
5897
6080
  {
@@ -5907,8 +6090,18 @@ var _JsrClient = class _JsrClient {
5907
6090
  method: "POST",
5908
6091
  body: JSON.stringify({ package: name })
5909
6092
  });
5910
- return response.status === 200 || response.status === 201;
6093
+ if (response.status === 200 || response.status === 201) return true;
6094
+ let detail = "";
6095
+ try {
6096
+ const body = await response.json();
6097
+ detail = body.message || body.error || JSON.stringify(body);
6098
+ } catch {
6099
+ }
6100
+ throw new JsrError(
6101
+ `Failed to create package '${packageName}': HTTP ${response.status}${detail ? ` \u2014 ${detail}` : ""}`
6102
+ );
5911
6103
  } catch (error) {
6104
+ if (error instanceof JsrError) throw error;
5912
6105
  throw new JsrError(
5913
6106
  `Failed to fetch \`${this.apiEndpoint}/scopes/${scope}/packages\``,
5914
6107
  {
@@ -5923,8 +6116,18 @@ var _JsrClient = class _JsrClient {
5923
6116
  const response = await this.fetch(`/scopes/${scope}/packages/${name}`, {
5924
6117
  method: "DELETE"
5925
6118
  });
5926
- return response.status === 200 || response.status === 204;
6119
+ if (response.status === 200 || response.status === 204) return true;
6120
+ let detail = "";
6121
+ try {
6122
+ const body = await response.json();
6123
+ detail = body.message || body.error || JSON.stringify(body);
6124
+ } catch {
6125
+ }
6126
+ throw new JsrError(
6127
+ `Failed to delete package '${packageName}': HTTP ${response.status}${detail ? ` \u2014 ${detail}` : ""}`
6128
+ );
5927
6129
  } catch (error) {
6130
+ if (error instanceof JsrError) throw error;
5928
6131
  throw new JsrError(
5929
6132
  `Failed to fetch \`${this.apiEndpoint}/scopes/${scope}/packages/${name}\``,
5930
6133
  {
@@ -5937,9 +6140,7 @@ var _JsrClient = class _JsrClient {
5937
6140
  try {
5938
6141
  const response = await this.fetch(`/packages?query=${query}`);
5939
6142
  if (!response.ok) {
5940
- throw new Error(
5941
- `HTTP ${response.status}: ${response.statusText}`
5942
- );
6143
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
5943
6144
  }
5944
6145
  return await response.json();
5945
6146
  } catch (error) {
@@ -6017,7 +6218,7 @@ var NpmRegistry = class extends Registry {
6017
6218
  await this.npm(["whoami"]);
6018
6219
  return true;
6019
6220
  } catch (error) {
6020
- if (error instanceof NonZeroExitError2 && error.output?.stderr.includes("ENEEDAUTH")) {
6221
+ if (error instanceof NonZeroExitError2) {
6021
6222
  return false;
6022
6223
  }
6023
6224
  throw new NpmError("Failed to run `npm whoami`", { cause: error });
@@ -6025,16 +6226,22 @@ var NpmRegistry = class extends Registry {
6025
6226
  }
6026
6227
  async collaborators() {
6027
6228
  try {
6028
- return JSON.parse(
6029
- await this.npm([
6030
- "access",
6031
- "list",
6032
- "collaborators",
6033
- this.packageName,
6034
- "--json"
6035
- ])
6036
- );
6229
+ const output = await this.npm([
6230
+ "access",
6231
+ "list",
6232
+ "collaborators",
6233
+ this.packageName,
6234
+ "--json"
6235
+ ]);
6236
+ try {
6237
+ return JSON.parse(output);
6238
+ } catch {
6239
+ throw new NpmError(
6240
+ `Unexpected response from npm registry for collaborators of '${this.packageName}'`
6241
+ );
6242
+ }
6037
6243
  } catch (error) {
6244
+ if (error instanceof NpmError) throw error;
6038
6245
  throw new NpmError(
6039
6246
  `Failed to run \`npm access list collaborators ${this.packageName} --json\``,
6040
6247
  { cause: error }
@@ -6048,12 +6255,21 @@ var NpmRegistry = class extends Registry {
6048
6255
  }
6049
6256
  async distTags() {
6050
6257
  try {
6051
- return Object.keys(
6052
- JSON.parse(
6053
- await this.npm(["view", this.packageName, "dist-tags", "--json"])
6054
- )
6055
- );
6258
+ const output = await this.npm([
6259
+ "view",
6260
+ this.packageName,
6261
+ "dist-tags",
6262
+ "--json"
6263
+ ]);
6264
+ try {
6265
+ return Object.keys(JSON.parse(output));
6266
+ } catch {
6267
+ throw new NpmError(
6268
+ `Unexpected response from npm registry for dist-tags of '${this.packageName}'`
6269
+ );
6270
+ }
6056
6271
  } catch (error) {
6272
+ if (error instanceof NpmError) throw error;
6057
6273
  throw new NpmError(
6058
6274
  `Failed to run \`npm view ${this.packageName} dist-tags --json\``,
6059
6275
  { cause: error }
@@ -6083,12 +6299,7 @@ var NpmRegistry = class extends Registry {
6083
6299
  if (error instanceof NonZeroExitError2 && error.output?.stderr.includes("EOTP")) {
6084
6300
  return false;
6085
6301
  }
6086
- throw new NpmError(
6087
- "Failed to run `npm publish --provenance --access public`",
6088
- {
6089
- cause: error
6090
- }
6091
- );
6302
+ throw this.classifyPublishError(error);
6092
6303
  }
6093
6304
  }
6094
6305
  async publish(otp) {
@@ -6100,14 +6311,39 @@ var NpmRegistry = class extends Registry {
6100
6311
  if (error instanceof NonZeroExitError2 && error.output?.stderr.includes("EOTP")) {
6101
6312
  return false;
6102
6313
  }
6103
- throw new NpmError(`Failed to run \`npm ${args.join(" ")}\``, {
6104
- cause: error
6105
- });
6314
+ throw this.classifyPublishError(error);
6106
6315
  }
6107
6316
  }
6108
6317
  async isPackageNameAvaliable() {
6109
6318
  return isValidPackageName(this.packageName);
6110
6319
  }
6320
+ getRequirements() {
6321
+ return {
6322
+ needsPackageScripts: true,
6323
+ requiredManifest: "package.json"
6324
+ };
6325
+ }
6326
+ classifyPublishError(error) {
6327
+ if (error instanceof NonZeroExitError2) {
6328
+ const stderr = error.output?.stderr ?? "";
6329
+ if (stderr.includes("EOTP")) {
6330
+ return new NpmError("OTP required for publishing", { cause: error });
6331
+ }
6332
+ if (stderr.includes("403") || stderr.includes("Forbidden")) {
6333
+ return new NpmError(
6334
+ "Permission denied (403 Forbidden). Check your npm access token permissions.",
6335
+ { cause: error }
6336
+ );
6337
+ }
6338
+ if (stderr.includes("429") || stderr.includes("Too Many Requests")) {
6339
+ return new NpmError(
6340
+ "Rate limited by npm registry. Please wait and try again.",
6341
+ { cause: error }
6342
+ );
6343
+ }
6344
+ }
6345
+ return new NpmError("Failed to publish to npm", { cause: error });
6346
+ }
6111
6347
  };
6112
6348
  async function npmRegistry() {
6113
6349
  const packageJson = await getPackageJson();
@@ -6115,6 +6351,7 @@ async function npmRegistry() {
6115
6351
  }
6116
6352
 
6117
6353
  // src/tasks/jsr.ts
6354
+ var { open } = npmCli;
6118
6355
  var JsrAvailableError = class extends AbstractError {
6119
6356
  constructor(message, { cause } = {}) {
6120
6357
  super(message, { cause });
@@ -6139,17 +6376,34 @@ var jsrAvailableCheckTasks = {
6139
6376
  if (!JsrClient.token) {
6140
6377
  task.output = "Retrieving jsr API token";
6141
6378
  if (ctx.promptEnabled) {
6142
- while (true) {
6379
+ const maxAttempts = 3;
6380
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
6143
6381
  JsrClient.token = await task.prompt(ListrEnquirerPromptAdapter).run({
6144
6382
  type: "password",
6145
- message: `Please enter the jsr ${color.bold("API token")}`,
6383
+ message: `Please enter the jsr ${color.bold("API token")}${attempt > 1 ? ` (attempt ${attempt}/${maxAttempts})` : ""}`,
6146
6384
  footer: `
6147
6385
  Generate a token from ${color.bold(link2("jsr.io", "https://jsr.io/account/tokens/create/"))}. ${color.red("You should select")} ${color.bold("'Interact with the JSR API'")}.`
6148
6386
  });
6149
6387
  try {
6150
6388
  if (await jsr.client.user()) break;
6151
- task.output = "The jsr API token is invalid. Please re-enter a valid token.";
6152
- } catch {
6389
+ if (attempt < maxAttempts) {
6390
+ task.output = "The jsr API token is invalid. Please re-enter a valid token.";
6391
+ }
6392
+ } catch (error) {
6393
+ if (error instanceof Error && (error.message.includes("fetch") || error.message.includes("network") || error.message.includes("ENOTFOUND"))) {
6394
+ throw new JsrAvailableError(
6395
+ "JSR API is unreachable. Check your network connection.",
6396
+ { cause: error }
6397
+ );
6398
+ }
6399
+ if (attempt < maxAttempts) {
6400
+ task.output = "The jsr API token is invalid. Please re-enter a valid token.";
6401
+ }
6402
+ }
6403
+ if (attempt === maxAttempts) {
6404
+ throw new JsrAvailableError(
6405
+ "JSR token verification failed after 3 attempts."
6406
+ );
6153
6407
  }
6154
6408
  }
6155
6409
  } else {
@@ -6278,13 +6532,48 @@ var jsrPublishTasks = {
6278
6532
  }
6279
6533
  JsrClient.token = jsrTokenEnv;
6280
6534
  }
6281
- await jsr.publish();
6535
+ let result = await jsr.publish();
6536
+ if (!result && jsr.packageCreationUrls) {
6537
+ if (ctx.promptEnabled) {
6538
+ task.title = "Running jsr publish (package creation needed)";
6539
+ const urls = jsr.packageCreationUrls;
6540
+ const maxAttempts = 3;
6541
+ task.output = `Package doesn't exist on jsr. Create it at:
6542
+ ${urls.map((url) => ` ${color.cyan(url)}`).join("\n")}`;
6543
+ open(urls[0]);
6544
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
6545
+ await task.prompt(ListrEnquirerPromptAdapter).run({
6546
+ type: "input",
6547
+ message: `Press ${color.bold("enter")} after creating the package on jsr.io${attempt > 1 ? ` (attempt ${attempt}/${maxAttempts})` : ""}`
6548
+ });
6549
+ result = await jsr.publish();
6550
+ if (result) break;
6551
+ if (attempt < maxAttempts) {
6552
+ task.output = "Package still doesn't exist. Please create it and try again.";
6553
+ }
6554
+ }
6555
+ if (!result) {
6556
+ throw new JsrAvailableError(
6557
+ "Package creation not completed after 3 attempts."
6558
+ );
6559
+ }
6560
+ task.title = "Running jsr publish (package created)";
6561
+ } else {
6562
+ throw new JsrAvailableError(
6563
+ `Package doesn't exist on jsr. Create it at:
6564
+ ${jsr.packageCreationUrls.join("\n")}`
6565
+ );
6566
+ }
6567
+ }
6282
6568
  }
6283
6569
  };
6284
6570
 
6285
6571
  // src/tasks/npm.ts
6572
+ import { spawn } from "node:child_process";
6286
6573
  import process13 from "node:process";
6287
6574
  import { ListrEnquirerPromptAdapter as ListrEnquirerPromptAdapter2 } from "@listr2/prompt-adapter-enquirer";
6575
+ import npmCli2 from "@npmcli/promise-spawn";
6576
+ var { open: open2 } = npmCli2;
6288
6577
  var NpmAvailableError = class extends AbstractError {
6289
6578
  constructor(message, { cause } = {}) {
6290
6579
  super(message, { cause });
@@ -6295,12 +6584,55 @@ var NpmAvailableError = class extends AbstractError {
6295
6584
  var npmAvailableCheckTasks = {
6296
6585
  title: "Checking npm avaliable for publising",
6297
6586
  skip: (ctx) => !!ctx.preview,
6298
- task: async () => {
6587
+ task: async (ctx, task) => {
6299
6588
  const npm = await npmRegistry();
6300
6589
  if (!await npm.isLoggedIn()) {
6301
- throw new NpmAvailableError(
6302
- "You are not logged in. Please log in first using `npm login`."
6303
- );
6590
+ if (ctx.promptEnabled) {
6591
+ try {
6592
+ task.output = "Launching npm login...";
6593
+ await new Promise((resolve, reject) => {
6594
+ const child = spawn("npm", ["login"], {
6595
+ stdio: ["pipe", "pipe", "pipe"]
6596
+ });
6597
+ let opened = false;
6598
+ const onData = (data) => {
6599
+ const text = data.toString();
6600
+ const urlMatch = text.match(
6601
+ /https:\/\/www\.npmjs\.com\/login[^\s]*/
6602
+ );
6603
+ if (urlMatch && !opened) {
6604
+ opened = true;
6605
+ task.output = `Login at: ${color.cyan(urlMatch[0])}`;
6606
+ open2(urlMatch[0]);
6607
+ child.stdin?.write("\n");
6608
+ }
6609
+ };
6610
+ child.stdout?.on("data", onData);
6611
+ child.stderr?.on("data", onData);
6612
+ child.on(
6613
+ "close",
6614
+ (code) => code === 0 ? resolve() : reject(
6615
+ new Error(`npm login exited with code ${code}`)
6616
+ )
6617
+ );
6618
+ child.on("error", reject);
6619
+ });
6620
+ } catch (error) {
6621
+ throw new NpmAvailableError(
6622
+ "npm login failed. Please run `npm login` manually and try again.",
6623
+ { cause: error }
6624
+ );
6625
+ }
6626
+ if (!await npm.isLoggedIn()) {
6627
+ throw new NpmAvailableError(
6628
+ "Still not logged in after npm login. Please verify your credentials."
6629
+ );
6630
+ }
6631
+ } else {
6632
+ throw new NpmAvailableError(
6633
+ "Not logged in to npm. Set NODE_AUTH_TOKEN in your CI environment. For GitHub Actions, add it as a repository secret."
6634
+ );
6635
+ }
6304
6636
  }
6305
6637
  if (await npm.isPublished()) {
6306
6638
  if (!await npm.hasPermission()) {
@@ -6328,24 +6660,31 @@ var npmPublishTasks = {
6328
6660
  let result = await npm.publish();
6329
6661
  if (!result) {
6330
6662
  task.title = "Running npm publish (OTP code needed)";
6331
- while (!result) {
6663
+ const maxAttempts = 3;
6664
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
6332
6665
  result = await npm.publish(
6333
6666
  await task.prompt(ListrEnquirerPromptAdapter2).run({
6334
6667
  type: "password",
6335
- message: "npm OTP code"
6668
+ message: `npm OTP code${attempt > 1 ? ` (attempt ${attempt}/${maxAttempts})` : ""}`
6336
6669
  })
6337
6670
  );
6338
- if (!result) {
6339
- task.output = "2FA failed";
6671
+ if (result) break;
6672
+ if (attempt < maxAttempts) {
6673
+ task.output = "2FA failed. Please try again.";
6340
6674
  }
6341
6675
  }
6676
+ if (!result) {
6677
+ throw new NpmAvailableError(
6678
+ "OTP verification failed after 3 attempts."
6679
+ );
6680
+ }
6342
6681
  task.title = "Running npm publish (2FA passed)";
6343
6682
  }
6344
6683
  } else {
6345
6684
  const npmTokenEnv = process13.env.NODE_AUTH_TOKEN;
6346
6685
  if (!npmTokenEnv) {
6347
6686
  throw new NpmAvailableError(
6348
- "NODE_AUTH_TOKEN not found in the environment variables. Please set the token and try again."
6687
+ "NODE_AUTH_TOKEN not found in environment variables. Set it in your CI configuration:\n GitHub Actions: Add NODE_AUTH_TOKEN as a repository secret\n Other CI: Export NODE_AUTH_TOKEN with your npm access token"
6349
6688
  );
6350
6689
  }
6351
6690
  const result = await npm.publishProvenance();
@@ -6451,6 +6790,7 @@ var prerequisitesCheckTask = (options) => {
6451
6790
  );
6452
6791
  }
6453
6792
  ctx.cleanWorkingTree = false;
6793
+ return;
6454
6794
  }
6455
6795
  ctx.cleanWorkingTree = true;
6456
6796
  }
@@ -6551,6 +6891,16 @@ async function validateEngineVersion(engine, version2) {
6551
6891
  }
6552
6892
 
6553
6893
  // src/tasks/required-conditions-check.ts
6894
+ var registryRequirementsMap = {
6895
+ npm: { needsPackageScripts: true },
6896
+ jsr: { needsPackageScripts: false },
6897
+ crates: { needsPackageScripts: false }
6898
+ };
6899
+ function needsPackageScripts(registries) {
6900
+ return registries.some(
6901
+ (r) => registryRequirementsMap[r]?.needsPackageScripts ?? true
6902
+ );
6903
+ }
6554
6904
  var RequiredConditionCheckError = class extends AbstractError {
6555
6905
  constructor(message, { cause } = {}) {
6556
6906
  super(message, { cause });
@@ -6626,7 +6976,7 @@ var requiredConditionsCheckTask = (options) => createListr({
6626
6976
  },
6627
6977
  {
6628
6978
  title: "Checking if test and build scripts exist",
6629
- skip: (ctx) => ctx.jsrOnly,
6979
+ skip: (ctx) => !needsPackageScripts(ctx.registries),
6630
6980
  task: async (ctx) => {
6631
6981
  const { scripts } = await getPackageJson();
6632
6982
  const errors = [];
@@ -6680,14 +7030,28 @@ var requiredConditionsCheckTask = (options) => createListr({
6680
7030
  });
6681
7031
 
6682
7032
  // src/tasks/runner.ts
6683
- var { open } = npmCli;
7033
+ var { open: open3 } = npmCli3;
6684
7034
  var { prerelease } = SemVer;
7035
+ function collectRegistries(ctx) {
7036
+ if (ctx.packages?.length) {
7037
+ const seen = /* @__PURE__ */ new Set();
7038
+ const result = [];
7039
+ for (const pkg of ctx.packages) {
7040
+ for (const reg of pkg.registries) {
7041
+ if (!seen.has(reg)) {
7042
+ seen.add(reg);
7043
+ result.push(reg);
7044
+ }
7045
+ }
7046
+ }
7047
+ return result;
7048
+ }
7049
+ return ctx.registries;
7050
+ }
6685
7051
  async function run(options) {
6686
7052
  const ctx = {
6687
7053
  ...options,
6688
- promptEnabled: !isCI2 && process14.stdin.isTTY,
6689
- npmOnly: options.registries.every((registry) => registry !== "jsr"),
6690
- jsrOnly: options.registries.every((registry) => registry === "jsr")
7054
+ promptEnabled: !isCI2 && process14.stdin.isTTY
6691
7055
  };
6692
7056
  try {
6693
7057
  if (options.contents) process14.chdir(options.contents);
@@ -6703,7 +7067,7 @@ async function run(options) {
6703
7067
  options.publishOnly ? {
6704
7068
  title: "Publishing",
6705
7069
  task: (ctx2, parentTask) => parentTask.newListr(
6706
- ctx2.registries.map((registry) => {
7070
+ collectRegistries(ctx2).map((registry) => {
6707
7071
  switch (registry) {
6708
7072
  case "npm":
6709
7073
  return npmPublishTasks;
@@ -6723,9 +7087,16 @@ async function run(options) {
6723
7087
  title: "Running tests",
6724
7088
  task: async (ctx2) => {
6725
7089
  const packageManager = await getPackageManager();
6726
- await exec7(packageManager, ["run", ctx2.testScript], {
6727
- throwOnError: true
6728
- });
7090
+ try {
7091
+ await exec7(packageManager, ["run", ctx2.testScript], {
7092
+ throwOnError: true
7093
+ });
7094
+ } catch (error) {
7095
+ throw new AbstractError(
7096
+ `Test script '${ctx2.testScript}' failed. Run \`${packageManager} run ${ctx2.testScript}\` locally to see full output.`,
7097
+ { cause: error }
7098
+ );
7099
+ }
6729
7100
  }
6730
7101
  },
6731
7102
  {
@@ -6739,7 +7110,7 @@ async function run(options) {
6739
7110
  });
6740
7111
  } catch (error) {
6741
7112
  throw new AbstractError(
6742
- `Failed to run \`${packageManager} run ${ctx2.buildScript}\``,
7113
+ `Build script '${ctx2.buildScript}' failed. Run \`${packageManager} run ${ctx2.buildScript}\` locally to see full output.`,
6743
7114
  { cause: error }
6744
7115
  );
6745
7116
  }
@@ -6754,15 +7125,27 @@ async function run(options) {
6754
7125
  let commited = false;
6755
7126
  addRollback(async () => {
6756
7127
  if (tagCreated) {
6757
- console.log("Deleting tag...");
6758
- await git.deleteTag(`${await git.latestTag()}`);
7128
+ try {
7129
+ console.log("Deleting tag...");
7130
+ await git.deleteTag(`${await git.latestTag()}`);
7131
+ } catch (error) {
7132
+ console.error(
7133
+ `Failed to delete tag: ${error instanceof Error ? error.message : error}`
7134
+ );
7135
+ }
6759
7136
  }
6760
7137
  if (commited) {
6761
- console.log("Reset commits...");
6762
- await git.reset();
6763
- await git.stash();
6764
- await git.reset("HEAD^", "--hard");
6765
- await git.popStash();
7138
+ try {
7139
+ console.log("Reset commits...");
7140
+ await git.reset();
7141
+ await git.stash();
7142
+ await git.reset("HEAD^", "--hard");
7143
+ await git.popStash();
7144
+ } catch (error) {
7145
+ console.error(
7146
+ `Failed to reset commits: ${error instanceof Error ? error.message : error}`
7147
+ );
7148
+ }
6766
7149
  }
6767
7150
  }, ctx2);
6768
7151
  await git.reset();
@@ -6782,7 +7165,7 @@ async function run(options) {
6782
7165
  skip: (ctx2) => options.skipPublish || !!ctx2.preview,
6783
7166
  title: "Publishing",
6784
7167
  task: (ctx2, parentTask) => parentTask.newListr(
6785
- ctx2.registries.map((registry) => {
7168
+ collectRegistries(ctx2).map((registry) => {
6786
7169
  switch (registry) {
6787
7170
  case "npm":
6788
7171
  return npmPublishTasks;
@@ -6835,7 +7218,7 @@ ${repositoryUrl}/compare/${lastRev}...${latestTag}`;
6835
7218
  );
6836
7219
  const linkUrl = link2("Link", releaseDraftUrl.toString());
6837
7220
  task.title += ` ${linkUrl}`;
6838
- await open(releaseDraftUrl.toString());
7221
+ await open3(releaseDraftUrl.toString());
6839
7222
  }
6840
7223
  }
6841
7224
  ]
@@ -6859,11 +7242,9 @@ ${repositoryUrl}/compare/${lastRev}...${latestTag}`;
6859
7242
  import process15 from "node:process";
6860
7243
  import { inc } from "semver";
6861
7244
 
6862
- // src/config/loader.ts
6863
- import { stat as stat3 } from "node:fs/promises";
6864
- import path9 from "node:path";
6865
-
6866
- // src/monorepo/groups.ts
7245
+ // src/monorepo/discover.ts
7246
+ import { existsSync as existsSync6, readdirSync as readdirSync3, statSync as statSync2 } from "node:fs";
7247
+ import path10 from "node:path";
6867
7248
  import micromatch from "micromatch";
6868
7249
 
6869
7250
  // src/monorepo/workspace.ts
@@ -6871,16 +7252,30 @@ import { existsSync as existsSync5, readFileSync as readFileSync4 } from "node:f
6871
7252
  import { join } from "node:path";
6872
7253
  import { parse as parse2 } from "yaml";
6873
7254
 
7255
+ // src/monorepo/groups.ts
7256
+ import micromatch2 from "micromatch";
7257
+
6874
7258
  // src/validate/entry-points.ts
6875
- import { existsSync as existsSync6 } from "node:fs";
6876
- import path10 from "node:path";
7259
+ import { existsSync as existsSync7 } from "node:fs";
7260
+ import path11 from "node:path";
6877
7261
 
6878
7262
  // src/validate/extraneous-files.ts
6879
- import micromatch2 from "micromatch";
7263
+ import micromatch3 from "micromatch";
6880
7264
 
6881
7265
  // src/index.ts
6882
7266
  async function pubm(options) {
6883
- const resolvedOptions = resolveOptions({ ...options });
7267
+ const config = await loadConfig();
7268
+ const configOptions = {};
7269
+ if (config) {
7270
+ const resolved = resolveConfig(config);
7271
+ if (resolved.packages) {
7272
+ configOptions.packages = resolved.packages;
7273
+ }
7274
+ if (!options.registries && resolved.registries) {
7275
+ configOptions.registries = resolved.registries;
7276
+ }
7277
+ }
7278
+ const resolvedOptions = resolveOptions({ ...configOptions, ...options });
6884
7279
  await run(resolvedOptions);
6885
7280
  }
6886
7281
 
@@ -7121,6 +7516,7 @@ defaultCmd.action(
7121
7516
  );
7122
7517
  } catch (e2) {
7123
7518
  consoleError(e2);
7519
+ process.exitCode = 1;
7124
7520
  }
7125
7521
  }
7126
7522
  );