pubm 0.2.8 → 0.2.10

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/dist/index.js CHANGED
@@ -4575,6 +4575,7 @@ var RustEcosystem = class extends Ecosystem {
4575
4575
  };
4576
4576
 
4577
4577
  // src/error.ts
4578
+ import { NonZeroExitError } from "tinyexec";
4578
4579
  var AbstractError = class extends Error {
4579
4580
  constructor(message, { cause } = {}) {
4580
4581
  super(message, { cause });
@@ -4585,20 +4586,49 @@ var AbstractError = class extends Error {
4585
4586
  function replaceCode(code) {
4586
4587
  return code.replace(/`([^`].+)`/g, color.bold(color.underline("$1")));
4587
4588
  }
4589
+ function formatStderr(stderr) {
4590
+ return stderr.split("\n").map((line) => ` ${color.dim("\u2502")} ${line}`).join("\n");
4591
+ }
4592
+ function isNoisyCause(cause) {
4593
+ if (cause instanceof NonZeroExitError) return true;
4594
+ if (cause instanceof Error && /Process exited with non-zero status/i.test(cause.message))
4595
+ return true;
4596
+ return false;
4597
+ }
4588
4598
  function formatError(error) {
4589
4599
  if (!(error instanceof Error)) return `${error}`;
4590
- const message = typeof error.message === "string" ? replaceCode(error.message) : (
4600
+ const rawMessage = typeof error.message === "string" ? error.message : (
4591
4601
  /* v8 ignore next */
4592
- formatError(error)
4602
+ String(error)
4593
4603
  );
4594
- let stringifyError = `${color.bgRed(` ${error.name} `)}${color.reset("")} ${message}
4604
+ const newlineIndex = rawMessage.indexOf("\n");
4605
+ let summary;
4606
+ let detail;
4607
+ if (newlineIndex !== -1) {
4608
+ summary = rawMessage.slice(0, newlineIndex);
4609
+ detail = rawMessage.slice(newlineIndex + 1);
4610
+ } else {
4611
+ summary = rawMessage;
4612
+ }
4613
+ let result = `${color.bgRed(` ${error.name} `)}${color.reset("")} ${replaceCode(summary)}
4595
4614
  `;
4596
- stringifyError += error.stack?.split("\n").slice(1).join("\n").replace(/at/g, color.dim("at")).replace(/\(([^(].+)\)/g, `(${color.blue("$1")})`);
4597
- if (error.cause) {
4598
- stringifyError += "\n\nCaused: ";
4599
- stringifyError += formatError(error.cause);
4615
+ if (detail) {
4616
+ result += `
4617
+ ${formatStderr(detail)}
4618
+ `;
4619
+ }
4620
+ if (process.env.DEBUG === "pubm" && error.stack) {
4621
+ result += error.stack.split("\n").slice(1).join("\n").replace(/at/g, color.dim("at")).replace(/\(([^(].+)\)/g, `(${color.blue("$1")})`);
4622
+ }
4623
+ if (error.cause && !isNoisyCause(error.cause)) {
4624
+ const causeMsg = error.cause instanceof Error ? error.cause.message : String(error.cause);
4625
+ if (causeMsg !== summary) {
4626
+ result += `
4627
+ ${color.dim("Caused by:")} `;
4628
+ result += formatError(error.cause);
4629
+ }
4600
4630
  }
4601
- return stringifyError;
4631
+ return result;
4602
4632
  }
4603
4633
  function consoleError(error) {
4604
4634
  let errorText = "\n";
@@ -4952,12 +4982,19 @@ var rollbacks = [];
4952
4982
  function addRollback(rollback2, context) {
4953
4983
  rollbacks.push({ fn: rollback2, ctx: context });
4954
4984
  }
4985
+ function rollbackLog(message) {
4986
+ console.log(` ${color.yellow("\u21A9")} ${message}`);
4987
+ }
4988
+ function rollbackError(message) {
4989
+ console.error(` ${color.red("\u2717")} ${message}`);
4990
+ }
4955
4991
  var called = false;
4956
4992
  async function rollback() {
4957
4993
  if (called) return void 0;
4958
4994
  called = true;
4959
4995
  if (rollbacks.length <= 0) return void 0;
4960
- console.log("Rollback...");
4996
+ console.log(`
4997
+ ${color.yellow("\u27F2")} ${color.yellow("Rolling back...")}`);
4961
4998
  const results = await Promise.allSettled(
4962
4999
  rollbacks.map(({ fn, ctx }) => fn(ctx))
4963
5000
  );
@@ -4966,15 +5003,15 @@ async function rollback() {
4966
5003
  );
4967
5004
  if (failures.length > 0) {
4968
5005
  for (const failure of failures) {
4969
- console.error(
4970
- `Rollback operation failed: ${failure.reason instanceof Error ? failure.reason.message : failure.reason}`
5006
+ rollbackError(
5007
+ failure.reason instanceof Error ? failure.reason.message : failure.reason
4971
5008
  );
4972
5009
  }
4973
5010
  console.log(
4974
- "Rollback completed with errors. Some operations may require manual recovery."
5011
+ `${color.red("\u2717")} ${color.red("Rollback completed with errors.")} Some operations may require manual recovery.`
4975
5012
  );
4976
5013
  } else {
4977
- console.log("Rollback completed");
5014
+ console.log(`${color.green("\u2713")} Rollback completed`);
4978
5015
  }
4979
5016
  }
4980
5017
 
@@ -5334,19 +5371,25 @@ var TOKEN_CONFIG = {
5334
5371
  envVar: "NODE_AUTH_TOKEN",
5335
5372
  dbKey: "npm-token",
5336
5373
  ghSecretName: "NODE_AUTH_TOKEN",
5337
- promptLabel: "npm access token"
5374
+ promptLabel: "npm access token",
5375
+ tokenUrl: "https://www.npmjs.com/settings/~/tokens/granular-access-tokens/new",
5376
+ tokenUrlLabel: "npmjs.com"
5338
5377
  },
5339
5378
  jsr: {
5340
5379
  envVar: "JSR_TOKEN",
5341
5380
  dbKey: "jsr-token",
5342
5381
  ghSecretName: "JSR_TOKEN",
5343
- promptLabel: "jsr API token"
5382
+ promptLabel: "jsr API token",
5383
+ tokenUrl: "https://jsr.io/account/tokens/create",
5384
+ tokenUrlLabel: "jsr.io"
5344
5385
  },
5345
5386
  crates: {
5346
5387
  envVar: "CARGO_REGISTRY_TOKEN",
5347
5388
  dbKey: "cargo-token",
5348
5389
  ghSecretName: "CARGO_REGISTRY_TOKEN",
5349
- promptLabel: "crates.io API token"
5390
+ promptLabel: "crates.io API token",
5391
+ tokenUrl: "https://crates.io/settings/tokens/new",
5392
+ tokenUrlLabel: "crates.io"
5350
5393
  }
5351
5394
  };
5352
5395
  function loadTokensFromDb(registries) {
@@ -5360,6 +5403,7 @@ function loadTokensFromDb(registries) {
5360
5403
  }
5361
5404
  return tokens;
5362
5405
  }
5406
+ var NPM_AUTH_ENV_VAR = "npm_config_//registry.npmjs.org/:_authToken";
5363
5407
  function injectTokensToEnv(tokens) {
5364
5408
  const originals = {};
5365
5409
  for (const [registry, token] of Object.entries(tokens)) {
@@ -5367,6 +5411,10 @@ function injectTokensToEnv(tokens) {
5367
5411
  if (!config) continue;
5368
5412
  originals[config.envVar] = process.env[config.envVar];
5369
5413
  process.env[config.envVar] = token;
5414
+ if (registry === "npm") {
5415
+ originals[NPM_AUTH_ENV_VAR] = process.env[NPM_AUTH_ENV_VAR];
5416
+ process.env[NPM_AUTH_ENV_VAR] = token;
5417
+ }
5370
5418
  }
5371
5419
  return () => {
5372
5420
  for (const [envVar, original] of Object.entries(originals)) {
@@ -5381,7 +5429,7 @@ function injectTokensToEnv(tokens) {
5381
5429
 
5382
5430
  // src/registry/crates.ts
5383
5431
  import path5 from "node:path";
5384
- import { exec as exec4, NonZeroExitError } from "tinyexec";
5432
+ import { exec as exec4, NonZeroExitError as NonZeroExitError2 } from "tinyexec";
5385
5433
 
5386
5434
  // src/registry/registry.ts
5387
5435
  var Registry = class {
@@ -5401,6 +5449,14 @@ var CratesError = class extends AbstractError {
5401
5449
  }
5402
5450
  };
5403
5451
  var USER_AGENT = "pubm (https://github.com/syi0808/pubm)";
5452
+ function cleanCargoStderr(stderr) {
5453
+ return stderr.split("\n").filter((line) => {
5454
+ const trimmed = line.trim();
5455
+ if (trimmed === "Updating crates.io index") return false;
5456
+ if (trimmed === "") return false;
5457
+ return true;
5458
+ }).join("\n");
5459
+ }
5404
5460
  var CratesRegistry = class extends Registry {
5405
5461
  constructor() {
5406
5462
  super(...arguments);
@@ -5465,9 +5521,9 @@ var CratesRegistry = class extends Registry {
5465
5521
  await exec4("cargo", args, { throwOnError: true });
5466
5522
  return true;
5467
5523
  } catch (error) {
5468
- const stderr = error instanceof NonZeroExitError ? error.output?.stderr : void 0;
5524
+ const stderr = error instanceof NonZeroExitError2 ? error.output?.stderr : void 0;
5469
5525
  const message = stderr ? `Failed to run \`cargo publish\`:
5470
- ${stderr}` : "Failed to run `cargo publish`";
5526
+ ${cleanCargoStderr(stderr)}` : "Failed to run `cargo publish`";
5471
5527
  throw new CratesError(message, { cause: error });
5472
5528
  }
5473
5529
  }
@@ -5479,9 +5535,9 @@ ${stderr}` : "Failed to run `cargo publish`";
5479
5535
  }
5480
5536
  await exec4("cargo", args, { throwOnError: true });
5481
5537
  } catch (error) {
5482
- const stderr = error instanceof NonZeroExitError ? error.output?.stderr : void 0;
5538
+ const stderr = error instanceof NonZeroExitError2 ? error.output?.stderr : void 0;
5483
5539
  const message = stderr ? `Failed to run \`cargo publish --dry-run\`:
5484
- ${stderr}` : "Failed to run `cargo publish --dry-run`";
5540
+ ${cleanCargoStderr(stderr)}` : "Failed to run `cargo publish --dry-run`";
5485
5541
  throw new CratesError(message, { cause: error });
5486
5542
  }
5487
5543
  }
@@ -5603,7 +5659,7 @@ var cratesPublishTasks = createCratesPublishTask();
5603
5659
  import { ListrEnquirerPromptAdapter } from "@listr2/prompt-adapter-enquirer";
5604
5660
 
5605
5661
  // src/registry/jsr.ts
5606
- import { exec as exec5, NonZeroExitError as NonZeroExitError2 } from "tinyexec";
5662
+ import { exec as exec5, NonZeroExitError as NonZeroExitError3 } from "tinyexec";
5607
5663
 
5608
5664
  // src/utils/package-name.ts
5609
5665
  import { builtinModules } from "node:module";
@@ -5614,7 +5670,7 @@ function getScope(packageName) {
5614
5670
  return packageName.match(/^@([^/]+)/)?.[1] ?? null;
5615
5671
  }
5616
5672
  function getScopeAndName(packageName) {
5617
- const matches = packageName.match(/^@([a-zA-Z0-9]+)\/([a-zA-Z0-9]+)$/);
5673
+ const matches = packageName.match(/^@([a-zA-Z0-9_-]+)\/([a-zA-Z0-9_.-]+)$/);
5618
5674
  if (!matches) {
5619
5675
  throw new Error(
5620
5676
  `Invalid scoped package name: '${packageName}'. Expected format: @scope/name`
@@ -5659,7 +5715,7 @@ var JsrError = class extends AbstractError {
5659
5715
  function getApiEndpoint(registry) {
5660
5716
  const url = new URL(registry);
5661
5717
  url.host = `api.${url.host}`;
5662
- return `${url}`;
5718
+ return url.href.replace(/\/$/, "");
5663
5719
  }
5664
5720
  var JsrRegisry = class extends Registry {
5665
5721
  constructor(packageName, registry) {
@@ -5711,7 +5767,7 @@ var JsrRegisry = class extends Registry {
5711
5767
  this.packageCreationUrls = void 0;
5712
5768
  return true;
5713
5769
  } catch (error) {
5714
- const stderr = error instanceof NonZeroExitError2 ? error.output?.stderr : void 0;
5770
+ const stderr = error instanceof NonZeroExitError3 ? error.output?.stderr : void 0;
5715
5771
  if (stderr?.includes("don't exist")) {
5716
5772
  const urls = [...stderr.matchAll(/https:\/\/jsr\.io\/new\S+/g)].map(
5717
5773
  (m) => m[0]
@@ -5744,9 +5800,14 @@ ${stderr}` : ""}`,
5744
5800
  { throwOnError: true }
5745
5801
  );
5746
5802
  } catch (error) {
5747
- throw new JsrError("Failed to run `jsr publish --dry-run`", {
5748
- cause: error
5749
- });
5803
+ const stderr = error instanceof NonZeroExitError3 ? error.output?.stderr : void 0;
5804
+ throw new JsrError(
5805
+ `Failed to run \`jsr publish --dry-run\`${stderr ? `
5806
+ ${stderr}` : ""}`,
5807
+ {
5808
+ cause: error
5809
+ }
5810
+ );
5750
5811
  }
5751
5812
  }
5752
5813
  async version() {
@@ -5778,7 +5839,7 @@ ${stderr}` : ""}`,
5778
5839
  }
5779
5840
  }
5780
5841
  async hasPermission() {
5781
- return this.client.scopePermission(`${getScope(this.packageName)}`) !== null;
5842
+ return await this.client.scopePermission(`${getScope(this.packageName)}`) !== null;
5782
5843
  }
5783
5844
  async isPackageNameAvaliable() {
5784
5845
  return isValidPackageName(this.packageName);
@@ -6006,7 +6067,7 @@ async function jsrRegistry() {
6006
6067
  // src/registry/npm.ts
6007
6068
  import { tmpdir } from "node:os";
6008
6069
  import { join } from "node:path";
6009
- import { exec as exec6, NonZeroExitError as NonZeroExitError3 } from "tinyexec";
6070
+ import { exec as exec6, NonZeroExitError as NonZeroExitError4 } from "tinyexec";
6010
6071
  var NpmError = class extends AbstractError {
6011
6072
  constructor() {
6012
6073
  super(...arguments);
@@ -6076,7 +6137,7 @@ var NpmRegistry = class extends Registry {
6076
6137
  await this.npm(["whoami"]);
6077
6138
  return true;
6078
6139
  } catch (error) {
6079
- if (error instanceof NonZeroExitError3) {
6140
+ if (error instanceof NonZeroExitError4) {
6080
6141
  return false;
6081
6142
  }
6082
6143
  throw new NpmError("Failed to run `npm whoami`", { cause: error });
@@ -6154,7 +6215,7 @@ var NpmRegistry = class extends Registry {
6154
6215
  await this.npm(["publish", "--provenance", "--access", "public"]);
6155
6216
  return true;
6156
6217
  } catch (error) {
6157
- if (error instanceof NonZeroExitError3 && error.output?.stderr.includes("EOTP")) {
6218
+ if (error instanceof NonZeroExitError4 && error.output?.stderr.includes("EOTP")) {
6158
6219
  return false;
6159
6220
  }
6160
6221
  throw this.classifyPublishError(error);
@@ -6166,7 +6227,7 @@ var NpmRegistry = class extends Registry {
6166
6227
  await this.npm(args);
6167
6228
  return true;
6168
6229
  } catch (error) {
6169
- if (error instanceof NonZeroExitError3 && error.output?.stderr.includes("EOTP")) {
6230
+ if (error instanceof NonZeroExitError4 && error.output?.stderr.includes("EOTP")) {
6170
6231
  return false;
6171
6232
  }
6172
6233
  throw this.classifyPublishError(error);
@@ -6184,7 +6245,7 @@ var NpmRegistry = class extends Registry {
6184
6245
  }
6185
6246
  });
6186
6247
  } catch (error) {
6187
- const stderr = error instanceof NonZeroExitError3 ? error.output?.stderr : void 0;
6248
+ const stderr = error instanceof NonZeroExitError4 ? error.output?.stderr : void 0;
6188
6249
  throw new NpmError(
6189
6250
  `Failed to run \`npm publish --dry-run\`${stderr ? `
6190
6251
  ${stderr}` : ""}`,
@@ -6211,7 +6272,7 @@ ${stderr}` : ""}`,
6211
6272
  };
6212
6273
  }
6213
6274
  classifyPublishError(error) {
6214
- if (error instanceof NonZeroExitError3) {
6275
+ if (error instanceof NonZeroExitError4) {
6215
6276
  const stderr = error.output?.stderr ?? "";
6216
6277
  if (stderr.includes("EOTP")) {
6217
6278
  return new NpmError("OTP required for publishing", { cause: error });
@@ -6761,10 +6822,18 @@ async function collectTokens(registries, task) {
6761
6822
  for (const registry of registries) {
6762
6823
  const config = TOKEN_CONFIG[registry];
6763
6824
  if (!config || tokens[registry]) continue;
6825
+ let { tokenUrl } = config;
6826
+ if (registry === "npm" && tokenUrl.includes("~")) {
6827
+ const result = await exec7("npm", ["whoami"]);
6828
+ const username = result.stdout.trim();
6829
+ if (username) tokenUrl = tokenUrl.replace("~", username);
6830
+ }
6764
6831
  task.output = `Enter ${config.promptLabel}`;
6765
6832
  const token = await task.prompt(ListrEnquirerPromptAdapter4).run({
6766
6833
  type: "password",
6767
- message: `Enter ${config.promptLabel}`
6834
+ message: `Enter ${config.promptLabel}`,
6835
+ footer: `
6836
+ Generate a token from ${color.bold(link2(config.tokenUrlLabel, tokenUrl))}`
6768
6837
  });
6769
6838
  tokens[registry] = token;
6770
6839
  new Db().set(config.dbKey, token);
@@ -7252,6 +7321,12 @@ async function run(options) {
7252
7321
  promptEnabled: !isCI2 && process10.stdin.isTTY
7253
7322
  };
7254
7323
  let cleanupEnv;
7324
+ const onSigint = async () => {
7325
+ cleanupEnv?.();
7326
+ await rollback();
7327
+ process10.exit(130);
7328
+ };
7329
+ process10.on("SIGINT", onSigint);
7255
7330
  try {
7256
7331
  if (options.contents) process10.chdir(options.contents);
7257
7332
  if (options.preflight) {
@@ -7331,23 +7406,28 @@ async function run(options) {
7331
7406
  addRollback(async () => {
7332
7407
  if (tagCreated) {
7333
7408
  try {
7334
- console.log("Deleting tag...");
7409
+ rollbackLog("Deleting tag");
7335
7410
  await git.deleteTag(`${await git.latestTag()}`);
7336
7411
  } catch (error) {
7337
- console.error(
7412
+ rollbackError(
7338
7413
  `Failed to delete tag: ${error instanceof Error ? error.message : error}`
7339
7414
  );
7340
7415
  }
7341
7416
  }
7342
7417
  if (commited) {
7343
7418
  try {
7344
- console.log("Reset commits...");
7419
+ rollbackLog("Resetting commits");
7345
7420
  await git.reset();
7346
- await git.stash();
7421
+ const dirty = await git.status() !== "";
7422
+ if (dirty) {
7423
+ await git.stash();
7424
+ }
7347
7425
  await git.reset("HEAD^", "--hard");
7348
- await git.popStash();
7426
+ if (dirty) {
7427
+ await git.popStash();
7428
+ }
7349
7429
  } catch (error) {
7350
- console.error(
7430
+ rollbackError(
7351
7431
  `Failed to reset commits: ${error instanceof Error ? error.message : error}`
7352
7432
  );
7353
7433
  }
@@ -7442,6 +7522,7 @@ ${repositoryUrl}/compare/${lastRev}...${latestTag}`;
7442
7522
  parts.push(`${color.bold(name)} on ${color.red("crates.io")}`);
7443
7523
  }
7444
7524
  }
7525
+ process10.removeListener("SIGINT", onSigint);
7445
7526
  if (options.preflight) {
7446
7527
  cleanupEnv?.();
7447
7528
  console.log(
@@ -7459,6 +7540,7 @@ ${repositoryUrl}/compare/${lastRev}...${latestTag}`;
7459
7540
  );
7460
7541
  }
7461
7542
  } catch (e2) {
7543
+ process10.removeListener("SIGINT", onSigint);
7462
7544
  cleanupEnv?.();
7463
7545
  consoleError(e2);
7464
7546
  await rollback();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pubm",
3
- "version": "0.2.8",
3
+ "version": "0.2.10",
4
4
  "engines": {
5
5
  "node": ">=18",
6
6
  "git": ">=2.11.0"