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/bin/cli.js CHANGED
@@ -4655,6 +4655,7 @@ var Listr = (_a23 = class {
4655
4655
  }, __name(_a23, "Listr"), _a23);
4656
4656
 
4657
4657
  // src/error.ts
4658
+ import { NonZeroExitError } from "tinyexec";
4658
4659
  var AbstractError = class extends Error {
4659
4660
  constructor(message, { cause } = {}) {
4660
4661
  super(message, { cause });
@@ -4665,20 +4666,49 @@ var AbstractError = class extends Error {
4665
4666
  function replaceCode(code) {
4666
4667
  return code.replace(/`([^`].+)`/g, color.bold(color.underline("$1")));
4667
4668
  }
4669
+ function formatStderr(stderr) {
4670
+ return stderr.split("\n").map((line) => ` ${color.dim("\u2502")} ${line}`).join("\n");
4671
+ }
4672
+ function isNoisyCause(cause) {
4673
+ if (cause instanceof NonZeroExitError) return true;
4674
+ if (cause instanceof Error && /Process exited with non-zero status/i.test(cause.message))
4675
+ return true;
4676
+ return false;
4677
+ }
4668
4678
  function formatError(error) {
4669
4679
  if (!(error instanceof Error)) return `${error}`;
4670
- const message = typeof error.message === "string" ? replaceCode(error.message) : (
4680
+ const rawMessage = typeof error.message === "string" ? error.message : (
4671
4681
  /* v8 ignore next */
4672
- formatError(error)
4682
+ String(error)
4673
4683
  );
4674
- let stringifyError = `${color.bgRed(` ${error.name} `)}${color.reset("")} ${message}
4684
+ const newlineIndex = rawMessage.indexOf("\n");
4685
+ let summary;
4686
+ let detail;
4687
+ if (newlineIndex !== -1) {
4688
+ summary = rawMessage.slice(0, newlineIndex);
4689
+ detail = rawMessage.slice(newlineIndex + 1);
4690
+ } else {
4691
+ summary = rawMessage;
4692
+ }
4693
+ let result = `${color.bgRed(` ${error.name} `)}${color.reset("")} ${replaceCode(summary)}
4694
+ `;
4695
+ if (detail) {
4696
+ result += `
4697
+ ${formatStderr(detail)}
4675
4698
  `;
4676
- stringifyError += error.stack?.split("\n").slice(1).join("\n").replace(/at/g, color.dim("at")).replace(/\(([^(].+)\)/g, `(${color.blue("$1")})`);
4677
- if (error.cause) {
4678
- stringifyError += "\n\nCaused: ";
4679
- stringifyError += formatError(error.cause);
4680
4699
  }
4681
- return stringifyError;
4700
+ if (process.env.DEBUG === "pubm" && error.stack) {
4701
+ result += error.stack.split("\n").slice(1).join("\n").replace(/at/g, color.dim("at")).replace(/\(([^(].+)\)/g, `(${color.blue("$1")})`);
4702
+ }
4703
+ if (error.cause && !isNoisyCause(error.cause)) {
4704
+ const causeMsg = error.cause instanceof Error ? error.cause.message : String(error.cause);
4705
+ if (causeMsg !== summary) {
4706
+ result += `
4707
+ ${color.dim("Caused by:")} `;
4708
+ result += formatError(error.cause);
4709
+ }
4710
+ }
4711
+ return result;
4682
4712
  }
4683
4713
  function consoleError(error) {
4684
4714
  let errorText = "\n";
@@ -4698,6 +4728,12 @@ import { createHash as createHash2 } from "node:crypto";
4698
4728
  import { ListrEnquirerPromptAdapter } from "@listr2/prompt-adapter-enquirer";
4699
4729
  import { exec as exec2 } from "tinyexec";
4700
4730
 
4731
+ // src/utils/cli.ts
4732
+ var warningBadge = color.bgYellow(" Warning ");
4733
+ function link2(text, url) {
4734
+ return `\x1B]8;;${url}\x07${text}\x1B]8;;\x07`;
4735
+ }
4736
+
4701
4737
  // src/utils/db.ts
4702
4738
  import { createCipheriv, createDecipheriv, createHash } from "node:crypto";
4703
4739
  import { mkdirSync as mkdirSync5, readFileSync as readFileSync2, statSync, writeFileSync as writeFileSync4 } from "node:fs";
@@ -4775,19 +4811,25 @@ var TOKEN_CONFIG = {
4775
4811
  envVar: "NODE_AUTH_TOKEN",
4776
4812
  dbKey: "npm-token",
4777
4813
  ghSecretName: "NODE_AUTH_TOKEN",
4778
- promptLabel: "npm access token"
4814
+ promptLabel: "npm access token",
4815
+ tokenUrl: "https://www.npmjs.com/settings/~/tokens/granular-access-tokens/new",
4816
+ tokenUrlLabel: "npmjs.com"
4779
4817
  },
4780
4818
  jsr: {
4781
4819
  envVar: "JSR_TOKEN",
4782
4820
  dbKey: "jsr-token",
4783
4821
  ghSecretName: "JSR_TOKEN",
4784
- promptLabel: "jsr API token"
4822
+ promptLabel: "jsr API token",
4823
+ tokenUrl: "https://jsr.io/account/tokens/create",
4824
+ tokenUrlLabel: "jsr.io"
4785
4825
  },
4786
4826
  crates: {
4787
4827
  envVar: "CARGO_REGISTRY_TOKEN",
4788
4828
  dbKey: "cargo-token",
4789
4829
  ghSecretName: "CARGO_REGISTRY_TOKEN",
4790
- promptLabel: "crates.io API token"
4830
+ promptLabel: "crates.io API token",
4831
+ tokenUrl: "https://crates.io/settings/tokens/new",
4832
+ tokenUrlLabel: "crates.io"
4791
4833
  }
4792
4834
  };
4793
4835
  function loadTokensFromDb(registries) {
@@ -4801,6 +4843,7 @@ function loadTokensFromDb(registries) {
4801
4843
  }
4802
4844
  return tokens;
4803
4845
  }
4846
+ var NPM_AUTH_ENV_VAR = "npm_config_//registry.npmjs.org/:_authToken";
4804
4847
  function injectTokensToEnv(tokens) {
4805
4848
  const originals = {};
4806
4849
  for (const [registry, token] of Object.entries(tokens)) {
@@ -4808,6 +4851,10 @@ function injectTokensToEnv(tokens) {
4808
4851
  if (!config) continue;
4809
4852
  originals[config.envVar] = process.env[config.envVar];
4810
4853
  process.env[config.envVar] = token;
4854
+ if (registry === "npm") {
4855
+ originals[NPM_AUTH_ENV_VAR] = process.env[NPM_AUTH_ENV_VAR];
4856
+ process.env[NPM_AUTH_ENV_VAR] = token;
4857
+ }
4811
4858
  }
4812
4859
  return () => {
4813
4860
  for (const [envVar, original] of Object.entries(originals)) {
@@ -4833,10 +4880,18 @@ async function collectTokens(registries, task) {
4833
4880
  for (const registry of registries) {
4834
4881
  const config = TOKEN_CONFIG[registry];
4835
4882
  if (!config || tokens[registry]) continue;
4883
+ let { tokenUrl } = config;
4884
+ if (registry === "npm" && tokenUrl.includes("~")) {
4885
+ const result = await exec2("npm", ["whoami"]);
4886
+ const username = result.stdout.trim();
4887
+ if (username) tokenUrl = tokenUrl.replace("~", username);
4888
+ }
4836
4889
  task.output = `Enter ${config.promptLabel}`;
4837
4890
  const token = await task.prompt(ListrEnquirerPromptAdapter).run({
4838
4891
  type: "password",
4839
- message: `Enter ${config.promptLabel}`
4892
+ message: `Enter ${config.promptLabel}`,
4893
+ footer: `
4894
+ Generate a token from ${color.bold(link2(config.tokenUrlLabel, tokenUrl))}`
4840
4895
  });
4841
4896
  tokens[registry] = token;
4842
4897
  new Db().set(config.dbKey, token);
@@ -5587,12 +5642,6 @@ var RustEcosystem = class extends Ecosystem {
5587
5642
  }
5588
5643
  };
5589
5644
 
5590
- // src/utils/cli.ts
5591
- var warningBadge = color.bgYellow(" Warning ");
5592
- function link2(text, url) {
5593
- return `\x1B]8;;${url}\x07${text}\x1B]8;;\x07`;
5594
- }
5595
-
5596
5645
  // src/utils/crate-graph.ts
5597
5646
  async function sortCratesByDependencyOrder(cratePaths) {
5598
5647
  if (cratePaths.length <= 1) return cratePaths;
@@ -5645,12 +5694,19 @@ var rollbacks = [];
5645
5694
  function addRollback(rollback2, context) {
5646
5695
  rollbacks.push({ fn: rollback2, ctx: context });
5647
5696
  }
5697
+ function rollbackLog(message) {
5698
+ console.log(` ${color.yellow("\u21A9")} ${message}`);
5699
+ }
5700
+ function rollbackError(message) {
5701
+ console.error(` ${color.red("\u2717")} ${message}`);
5702
+ }
5648
5703
  var called = false;
5649
5704
  async function rollback() {
5650
5705
  if (called) return void 0;
5651
5706
  called = true;
5652
5707
  if (rollbacks.length <= 0) return void 0;
5653
- console.log("Rollback...");
5708
+ console.log(`
5709
+ ${color.yellow("\u27F2")} ${color.yellow("Rolling back...")}`);
5654
5710
  const results = await Promise.allSettled(
5655
5711
  rollbacks.map(({ fn, ctx }) => fn(ctx))
5656
5712
  );
@@ -5659,15 +5715,15 @@ async function rollback() {
5659
5715
  );
5660
5716
  if (failures.length > 0) {
5661
5717
  for (const failure of failures) {
5662
- console.error(
5663
- `Rollback operation failed: ${failure.reason instanceof Error ? failure.reason.message : failure.reason}`
5718
+ rollbackError(
5719
+ failure.reason instanceof Error ? failure.reason.message : failure.reason
5664
5720
  );
5665
5721
  }
5666
5722
  console.log(
5667
- "Rollback completed with errors. Some operations may require manual recovery."
5723
+ `${color.red("\u2717")} ${color.red("Rollback completed with errors.")} Some operations may require manual recovery.`
5668
5724
  );
5669
5725
  } else {
5670
- console.log("Rollback completed");
5726
+ console.log(`${color.green("\u2713")} Rollback completed`);
5671
5727
  }
5672
5728
  }
5673
5729
 
@@ -5952,7 +6008,7 @@ function collectRegistries(ctx) {
5952
6008
 
5953
6009
  // src/registry/crates.ts
5954
6010
  import path10 from "node:path";
5955
- import { exec as exec5, NonZeroExitError } from "tinyexec";
6011
+ import { exec as exec5, NonZeroExitError as NonZeroExitError2 } from "tinyexec";
5956
6012
 
5957
6013
  // src/registry/registry.ts
5958
6014
  var Registry = class {
@@ -5972,6 +6028,14 @@ var CratesError = class extends AbstractError {
5972
6028
  }
5973
6029
  };
5974
6030
  var USER_AGENT = "pubm (https://github.com/syi0808/pubm)";
6031
+ function cleanCargoStderr(stderr) {
6032
+ return stderr.split("\n").filter((line) => {
6033
+ const trimmed = line.trim();
6034
+ if (trimmed === "Updating crates.io index") return false;
6035
+ if (trimmed === "") return false;
6036
+ return true;
6037
+ }).join("\n");
6038
+ }
5975
6039
  var CratesRegistry = class extends Registry {
5976
6040
  constructor() {
5977
6041
  super(...arguments);
@@ -6036,9 +6100,9 @@ var CratesRegistry = class extends Registry {
6036
6100
  await exec5("cargo", args, { throwOnError: true });
6037
6101
  return true;
6038
6102
  } catch (error) {
6039
- const stderr = error instanceof NonZeroExitError ? error.output?.stderr : void 0;
6103
+ const stderr = error instanceof NonZeroExitError2 ? error.output?.stderr : void 0;
6040
6104
  const message = stderr ? `Failed to run \`cargo publish\`:
6041
- ${stderr}` : "Failed to run `cargo publish`";
6105
+ ${cleanCargoStderr(stderr)}` : "Failed to run `cargo publish`";
6042
6106
  throw new CratesError(message, { cause: error });
6043
6107
  }
6044
6108
  }
@@ -6050,9 +6114,9 @@ ${stderr}` : "Failed to run `cargo publish`";
6050
6114
  }
6051
6115
  await exec5("cargo", args, { throwOnError: true });
6052
6116
  } catch (error) {
6053
- const stderr = error instanceof NonZeroExitError ? error.output?.stderr : void 0;
6117
+ const stderr = error instanceof NonZeroExitError2 ? error.output?.stderr : void 0;
6054
6118
  const message = stderr ? `Failed to run \`cargo publish --dry-run\`:
6055
- ${stderr}` : "Failed to run `cargo publish --dry-run`";
6119
+ ${cleanCargoStderr(stderr)}` : "Failed to run `cargo publish --dry-run`";
6056
6120
  throw new CratesError(message, { cause: error });
6057
6121
  }
6058
6122
  }
@@ -6174,7 +6238,7 @@ var cratesPublishTasks = createCratesPublishTask();
6174
6238
  import { ListrEnquirerPromptAdapter as ListrEnquirerPromptAdapter2 } from "@listr2/prompt-adapter-enquirer";
6175
6239
 
6176
6240
  // src/registry/jsr.ts
6177
- import { exec as exec6, NonZeroExitError as NonZeroExitError2 } from "tinyexec";
6241
+ import { exec as exec6, NonZeroExitError as NonZeroExitError3 } from "tinyexec";
6178
6242
 
6179
6243
  // src/utils/package-name.ts
6180
6244
  import { builtinModules } from "node:module";
@@ -6185,7 +6249,7 @@ function getScope(packageName) {
6185
6249
  return packageName.match(/^@([^/]+)/)?.[1] ?? null;
6186
6250
  }
6187
6251
  function getScopeAndName(packageName) {
6188
- const matches = packageName.match(/^@([a-zA-Z0-9]+)\/([a-zA-Z0-9]+)$/);
6252
+ const matches = packageName.match(/^@([a-zA-Z0-9_-]+)\/([a-zA-Z0-9_.-]+)$/);
6189
6253
  if (!matches) {
6190
6254
  throw new Error(
6191
6255
  `Invalid scoped package name: '${packageName}'. Expected format: @scope/name`
@@ -6230,7 +6294,7 @@ var JsrError = class extends AbstractError {
6230
6294
  function getApiEndpoint(registry) {
6231
6295
  const url = new URL(registry);
6232
6296
  url.host = `api.${url.host}`;
6233
- return `${url}`;
6297
+ return url.href.replace(/\/$/, "");
6234
6298
  }
6235
6299
  var JsrRegisry = class extends Registry {
6236
6300
  constructor(packageName, registry) {
@@ -6282,7 +6346,7 @@ var JsrRegisry = class extends Registry {
6282
6346
  this.packageCreationUrls = void 0;
6283
6347
  return true;
6284
6348
  } catch (error) {
6285
- const stderr = error instanceof NonZeroExitError2 ? error.output?.stderr : void 0;
6349
+ const stderr = error instanceof NonZeroExitError3 ? error.output?.stderr : void 0;
6286
6350
  if (stderr?.includes("don't exist")) {
6287
6351
  const urls = [...stderr.matchAll(/https:\/\/jsr\.io\/new\S+/g)].map(
6288
6352
  (m) => m[0]
@@ -6315,9 +6379,14 @@ ${stderr}` : ""}`,
6315
6379
  { throwOnError: true }
6316
6380
  );
6317
6381
  } catch (error) {
6318
- throw new JsrError("Failed to run `jsr publish --dry-run`", {
6319
- cause: error
6320
- });
6382
+ const stderr = error instanceof NonZeroExitError3 ? error.output?.stderr : void 0;
6383
+ throw new JsrError(
6384
+ `Failed to run \`jsr publish --dry-run\`${stderr ? `
6385
+ ${stderr}` : ""}`,
6386
+ {
6387
+ cause: error
6388
+ }
6389
+ );
6321
6390
  }
6322
6391
  }
6323
6392
  async version() {
@@ -6349,7 +6418,7 @@ ${stderr}` : ""}`,
6349
6418
  }
6350
6419
  }
6351
6420
  async hasPermission() {
6352
- return this.client.scopePermission(`${getScope(this.packageName)}`) !== null;
6421
+ return await this.client.scopePermission(`${getScope(this.packageName)}`) !== null;
6353
6422
  }
6354
6423
  async isPackageNameAvaliable() {
6355
6424
  return isValidPackageName(this.packageName);
@@ -6577,7 +6646,7 @@ async function jsrRegistry() {
6577
6646
  // src/registry/npm.ts
6578
6647
  import { tmpdir } from "node:os";
6579
6648
  import { join } from "node:path";
6580
- import { exec as exec7, NonZeroExitError as NonZeroExitError3 } from "tinyexec";
6649
+ import { exec as exec7, NonZeroExitError as NonZeroExitError4 } from "tinyexec";
6581
6650
  var NpmError = class extends AbstractError {
6582
6651
  constructor() {
6583
6652
  super(...arguments);
@@ -6647,7 +6716,7 @@ var NpmRegistry = class extends Registry {
6647
6716
  await this.npm(["whoami"]);
6648
6717
  return true;
6649
6718
  } catch (error) {
6650
- if (error instanceof NonZeroExitError3) {
6719
+ if (error instanceof NonZeroExitError4) {
6651
6720
  return false;
6652
6721
  }
6653
6722
  throw new NpmError("Failed to run `npm whoami`", { cause: error });
@@ -6725,7 +6794,7 @@ var NpmRegistry = class extends Registry {
6725
6794
  await this.npm(["publish", "--provenance", "--access", "public"]);
6726
6795
  return true;
6727
6796
  } catch (error) {
6728
- if (error instanceof NonZeroExitError3 && error.output?.stderr.includes("EOTP")) {
6797
+ if (error instanceof NonZeroExitError4 && error.output?.stderr.includes("EOTP")) {
6729
6798
  return false;
6730
6799
  }
6731
6800
  throw this.classifyPublishError(error);
@@ -6737,7 +6806,7 @@ var NpmRegistry = class extends Registry {
6737
6806
  await this.npm(args);
6738
6807
  return true;
6739
6808
  } catch (error) {
6740
- if (error instanceof NonZeroExitError3 && error.output?.stderr.includes("EOTP")) {
6809
+ if (error instanceof NonZeroExitError4 && error.output?.stderr.includes("EOTP")) {
6741
6810
  return false;
6742
6811
  }
6743
6812
  throw this.classifyPublishError(error);
@@ -6755,7 +6824,7 @@ var NpmRegistry = class extends Registry {
6755
6824
  }
6756
6825
  });
6757
6826
  } catch (error) {
6758
- const stderr = error instanceof NonZeroExitError3 ? error.output?.stderr : void 0;
6827
+ const stderr = error instanceof NonZeroExitError4 ? error.output?.stderr : void 0;
6759
6828
  throw new NpmError(
6760
6829
  `Failed to run \`npm publish --dry-run\`${stderr ? `
6761
6830
  ${stderr}` : ""}`,
@@ -6782,7 +6851,7 @@ ${stderr}` : ""}`,
6782
6851
  };
6783
6852
  }
6784
6853
  classifyPublishError(error) {
6785
- if (error instanceof NonZeroExitError3) {
6854
+ if (error instanceof NonZeroExitError4) {
6786
6855
  const stderr = error.output?.stderr ?? "";
6787
6856
  if (stderr.includes("EOTP")) {
6788
6857
  return new NpmError("OTP required for publishing", { cause: error });
@@ -7749,6 +7818,12 @@ async function run(options) {
7749
7818
  promptEnabled: !isCI2 && process14.stdin.isTTY
7750
7819
  };
7751
7820
  let cleanupEnv;
7821
+ const onSigint = async () => {
7822
+ cleanupEnv?.();
7823
+ await rollback();
7824
+ process14.exit(130);
7825
+ };
7826
+ process14.on("SIGINT", onSigint);
7752
7827
  try {
7753
7828
  if (options.contents) process14.chdir(options.contents);
7754
7829
  if (options.preflight) {
@@ -7828,23 +7903,28 @@ async function run(options) {
7828
7903
  addRollback(async () => {
7829
7904
  if (tagCreated) {
7830
7905
  try {
7831
- console.log("Deleting tag...");
7906
+ rollbackLog("Deleting tag");
7832
7907
  await git.deleteTag(`${await git.latestTag()}`);
7833
7908
  } catch (error) {
7834
- console.error(
7909
+ rollbackError(
7835
7910
  `Failed to delete tag: ${error instanceof Error ? error.message : error}`
7836
7911
  );
7837
7912
  }
7838
7913
  }
7839
7914
  if (commited) {
7840
7915
  try {
7841
- console.log("Reset commits...");
7916
+ rollbackLog("Resetting commits");
7842
7917
  await git.reset();
7843
- await git.stash();
7918
+ const dirty = await git.status() !== "";
7919
+ if (dirty) {
7920
+ await git.stash();
7921
+ }
7844
7922
  await git.reset("HEAD^", "--hard");
7845
- await git.popStash();
7923
+ if (dirty) {
7924
+ await git.popStash();
7925
+ }
7846
7926
  } catch (error) {
7847
- console.error(
7927
+ rollbackError(
7848
7928
  `Failed to reset commits: ${error instanceof Error ? error.message : error}`
7849
7929
  );
7850
7930
  }
@@ -7939,6 +8019,7 @@ ${repositoryUrl}/compare/${lastRev}...${latestTag}`;
7939
8019
  parts.push(`${color.bold(name)} on ${color.red("crates.io")}`);
7940
8020
  }
7941
8021
  }
8022
+ process14.removeListener("SIGINT", onSigint);
7942
8023
  if (options.preflight) {
7943
8024
  cleanupEnv?.();
7944
8025
  console.log(
@@ -7956,6 +8037,7 @@ ${repositoryUrl}/compare/${lastRev}...${latestTag}`;
7956
8037
  );
7957
8038
  }
7958
8039
  } catch (e2) {
8040
+ process14.removeListener("SIGINT", onSigint);
7959
8041
  cleanupEnv?.();
7960
8042
  consoleError(e2);
7961
8043
  await rollback();