pubm 0.1.4 → 0.1.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.
package/dist/index.js CHANGED
@@ -1927,6 +1927,80 @@ var init_cli_truncate = __esm({
1927
1927
  }
1928
1928
  });
1929
1929
 
1930
+ // src/config/defaults.ts
1931
+ var defaultValidate = {
1932
+ cleanInstall: true,
1933
+ entryPoints: true,
1934
+ extraneousFiles: true
1935
+ };
1936
+ var defaultSnapshot = {
1937
+ useCalculatedVersion: false,
1938
+ prereleaseTemplate: "{tag}-{timestamp}"
1939
+ };
1940
+ var defaultConfig = {
1941
+ versioning: "independent",
1942
+ branch: "main",
1943
+ changelog: true,
1944
+ changelogFormat: "default",
1945
+ commit: false,
1946
+ access: "public",
1947
+ fixed: [],
1948
+ linked: [],
1949
+ updateInternalDependencies: "patch",
1950
+ ignore: [],
1951
+ tag: "latest",
1952
+ contents: ".",
1953
+ saveToken: true,
1954
+ releaseDraft: true,
1955
+ releaseNotes: true,
1956
+ registries: ["npm", "jsr"],
1957
+ rollbackStrategy: "individual"
1958
+ };
1959
+ function resolveConfig(config) {
1960
+ const packages = config.packages ?? [
1961
+ { path: ".", registries: ["npm", "jsr"] }
1962
+ ];
1963
+ return {
1964
+ ...defaultConfig,
1965
+ ...config,
1966
+ packages,
1967
+ validate: { ...defaultValidate, ...config.validate },
1968
+ snapshot: { ...defaultSnapshot, ...config.snapshot }
1969
+ };
1970
+ }
1971
+
1972
+ // src/config/loader.ts
1973
+ import { stat } from "node:fs/promises";
1974
+ import path from "node:path";
1975
+ var CONFIG_FILES = [
1976
+ "pubm.config.ts",
1977
+ "pubm.config.mts",
1978
+ "pubm.config.cts",
1979
+ "pubm.config.js",
1980
+ "pubm.config.mjs",
1981
+ "pubm.config.cjs"
1982
+ ];
1983
+ async function findConfigFile(cwd) {
1984
+ for (const file of CONFIG_FILES) {
1985
+ const filePath = path.join(cwd, file);
1986
+ try {
1987
+ if ((await stat(filePath)).isFile()) {
1988
+ return filePath;
1989
+ }
1990
+ } catch {
1991
+ }
1992
+ }
1993
+ return null;
1994
+ }
1995
+ async function loadConfig(cwd = process.cwd()) {
1996
+ const configPath = await findConfigFile(cwd);
1997
+ if (!configPath) return null;
1998
+ const { createJiti } = await import("jiti");
1999
+ const jiti = createJiti(cwd, { interopDefault: true });
2000
+ const mod = await jiti.import(configPath);
2001
+ return mod.default ?? mod;
2002
+ }
2003
+
1930
2004
  // src/options.ts
1931
2005
  var defaultOptions = {
1932
2006
  testScript: "test",
@@ -1936,13 +2010,16 @@ var defaultOptions = {
1936
2010
  registries: ["npm", "jsr"]
1937
2011
  };
1938
2012
  function resolveOptions(options) {
1939
- const nextOptions = { ...options, ...defaultOptions };
2013
+ const defined = Object.fromEntries(
2014
+ Object.entries(options).filter(([, v]) => v !== void 0)
2015
+ );
2016
+ const nextOptions = { ...defaultOptions, ...defined };
1940
2017
  return nextOptions;
1941
2018
  }
1942
2019
 
1943
2020
  // src/tasks/runner.ts
1944
2021
  import process10 from "node:process";
1945
- import npmCli2 from "@npmcli/promise-spawn";
2022
+ import npmCli3 from "@npmcli/promise-spawn";
1946
2023
 
1947
2024
  // node_modules/.pnpm/eventemitter3@5.0.1/node_modules/eventemitter3/index.mjs
1948
2025
  var import_index = __toESM(require_eventemitter3(), 1);
@@ -1963,15 +2040,15 @@ var isCompatibleTerminal = tty && tty.isatty && tty.isatty(1) && env.TERM && !is
1963
2040
  var isCI = "CI" in env && ("GITHUB_ACTIONS" in env || "GITLAB_CI" in env || "CIRCLECI" in env);
1964
2041
  var isColorSupported = !isDisabled && (isForced || isWindows && !isDumbTerminal || isCompatibleTerminal || isCI);
1965
2042
  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));
1966
- var clearBleed = (index, string, open3, close, replace) => index < 0 ? open3 + string + close : open3 + replaceClose(index, string, close, replace) + close;
1967
- var filterEmpty = (open3, close, replace = open3, at = open3.length + 1) => (string) => string || !(string === "" || string === void 0) ? clearBleed(
2043
+ var clearBleed = (index, string, open4, close, replace) => index < 0 ? open4 + string + close : open4 + replaceClose(index, string, close, replace) + close;
2044
+ var filterEmpty = (open4, close, replace = open4, at = open4.length + 1) => (string) => string || !(string === "" || string === void 0) ? clearBleed(
1968
2045
  ("" + string).indexOf(close, at),
1969
2046
  string,
1970
- open3,
2047
+ open4,
1971
2048
  close,
1972
2049
  replace
1973
2050
  ) : "";
1974
- var init = (open3, close, replace) => filterEmpty(`\x1B[${open3}m`, `\x1B[${close}m`, replace);
2051
+ var init = (open4, close, replace) => filterEmpty(`\x1B[${open4}m`, `\x1B[${close}m`, replace);
1975
2052
  var colors = {
1976
2053
  reset: init(0, 0),
1977
2054
  bold: init(1, 22, "\x1B[22m\x1B[1m"),
@@ -4497,7 +4574,8 @@ var Git = class {
4497
4574
  async revisionDiffsCount() {
4498
4575
  try {
4499
4576
  return Number.parseInt(
4500
- await this.git(["rev-list", "@{u}...HEAD", "--count", "--left-only"])
4577
+ await this.git(["rev-list", "@{u}...HEAD", "--count", "--left-only"]),
4578
+ 10
4501
4579
  );
4502
4580
  } catch (error) {
4503
4581
  throw new GitError(
@@ -4743,9 +4821,71 @@ function createListr(...args) {
4743
4821
  }
4744
4822
 
4745
4823
  // src/utils/package.ts
4746
- import { readFile, stat, writeFile } from "node:fs/promises";
4747
- import path from "node:path";
4824
+ import { readFile as readFile2, stat as stat3, writeFile as writeFile2 } from "node:fs/promises";
4825
+ import path3 from "node:path";
4748
4826
  import process7 from "node:process";
4827
+
4828
+ // src/ecosystem/rust.ts
4829
+ import { readFile, stat as stat2, writeFile } from "node:fs/promises";
4830
+ import path2 from "node:path";
4831
+ import { parse, stringify } from "smol-toml";
4832
+
4833
+ // src/ecosystem/ecosystem.ts
4834
+ var Ecosystem = class {
4835
+ constructor(packagePath) {
4836
+ this.packagePath = packagePath;
4837
+ }
4838
+ };
4839
+
4840
+ // src/ecosystem/rust.ts
4841
+ var RustEcosystem = class extends Ecosystem {
4842
+ static async detect(packagePath) {
4843
+ try {
4844
+ return (await stat2(path2.join(packagePath, "Cargo.toml"))).isFile();
4845
+ } catch {
4846
+ return false;
4847
+ }
4848
+ }
4849
+ async readCargoToml() {
4850
+ const raw = await readFile(
4851
+ path2.join(this.packagePath, "Cargo.toml"),
4852
+ "utf-8"
4853
+ );
4854
+ return parse(raw);
4855
+ }
4856
+ async packageName() {
4857
+ const cargo = await this.readCargoToml();
4858
+ const pkg = cargo.package;
4859
+ return pkg.name;
4860
+ }
4861
+ async readVersion() {
4862
+ const cargo = await this.readCargoToml();
4863
+ const pkg = cargo.package;
4864
+ return pkg.version;
4865
+ }
4866
+ async writeVersion(newVersion) {
4867
+ const filePath = path2.join(this.packagePath, "Cargo.toml");
4868
+ const raw = await readFile(filePath, "utf-8");
4869
+ const cargo = parse(raw);
4870
+ const pkg = cargo.package;
4871
+ pkg.version = newVersion;
4872
+ await writeFile(filePath, stringify(cargo));
4873
+ }
4874
+ manifestFiles() {
4875
+ return ["Cargo.toml"];
4876
+ }
4877
+ defaultTestCommand() {
4878
+ return "cargo test";
4879
+ }
4880
+ defaultBuildCommand() {
4881
+ return "cargo build --release";
4882
+ }
4883
+ supportedRegistries() {
4884
+ return ["crates"];
4885
+ }
4886
+ };
4887
+
4888
+ // src/utils/package.ts
4749
4889
  var cachedPackageJson = {};
4750
4890
  var cachedJsrJson = {};
4751
4891
  function patchCachedJsrJson(contents, { cwd = process7.cwd() } = {}) {
@@ -4754,16 +4894,16 @@ function patchCachedJsrJson(contents, { cwd = process7.cwd() } = {}) {
4754
4894
  async function findOutFile(file, { cwd = process7.cwd() } = {}) {
4755
4895
  let directory = cwd;
4756
4896
  let filePath = "";
4757
- const { root } = path.parse(cwd);
4897
+ const { root } = path3.parse(cwd);
4758
4898
  while (directory) {
4759
- filePath = path.join(directory, file);
4899
+ filePath = path3.join(directory, file);
4760
4900
  try {
4761
- if ((await stat(filePath)).isFile()) {
4901
+ if ((await stat3(filePath)).isFile()) {
4762
4902
  break;
4763
4903
  }
4764
4904
  } catch {
4765
4905
  }
4766
- directory = path.dirname(directory);
4906
+ directory = path3.dirname(directory);
4767
4907
  if (directory === root) return null;
4768
4908
  }
4769
4909
  return filePath;
@@ -4775,7 +4915,7 @@ async function getPackageJson({
4775
4915
  if (cachedPackageJson[cwd]) return cachedPackageJson[cwd];
4776
4916
  try {
4777
4917
  const packageJsonPath = await findOutFile("package.json");
4778
- const raw = packageJsonPath && (await readFile(packageJsonPath)).toString();
4918
+ const raw = packageJsonPath && (await readFile2(packageJsonPath)).toString();
4779
4919
  if (!raw) {
4780
4920
  if (!fallbackJsr) {
4781
4921
  throw new Error(
@@ -4808,7 +4948,7 @@ async function getJsrJson({
4808
4948
  if (cachedJsrJson[cwd]) return cachedJsrJson[cwd];
4809
4949
  try {
4810
4950
  const jsrJsonPath = await findOutFile("jsr.json");
4811
- const raw = jsrJsonPath && (await readFile(jsrJsonPath)).toString();
4951
+ const raw = jsrJsonPath && (await readFile2(jsrJsonPath)).toString();
4812
4952
  if (!raw) {
4813
4953
  if (!fallbackPackage) {
4814
4954
  throw new Error(
@@ -4892,14 +5032,14 @@ async function version({ cwd = process7.cwd() } = {}) {
4892
5032
  return version2;
4893
5033
  }
4894
5034
  var versionRegex = /("version"\s*:\s*")[^"]*(")/;
4895
- async function replaceVersion(version2) {
5035
+ async function replaceVersion(version2, packages) {
4896
5036
  const results = await Promise.all([
4897
5037
  (async () => {
4898
5038
  const packageJsonPath = await findOutFile("package.json");
4899
5039
  if (!packageJsonPath) return void 0;
4900
- const packageJson = (await readFile(packageJsonPath)).toString();
5040
+ const packageJson = (await readFile2(packageJsonPath)).toString();
4901
5041
  try {
4902
- await writeFile(
5042
+ await writeFile2(
4903
5043
  packageJsonPath,
4904
5044
  packageJson.replace(versionRegex, `$1${version2}$2`)
4905
5045
  );
@@ -4914,9 +5054,9 @@ async function replaceVersion(version2) {
4914
5054
  (async () => {
4915
5055
  const jsrJsonPath = await findOutFile("jsr.json");
4916
5056
  if (!jsrJsonPath) return void 0;
4917
- const jsrJson = (await readFile(jsrJsonPath)).toString();
5057
+ const jsrJson = (await readFile2(jsrJsonPath)).toString();
4918
5058
  try {
4919
- await writeFile(
5059
+ await writeFile2(
4920
5060
  jsrJsonPath,
4921
5061
  jsrJson.replace(versionRegex, `$1${version2}$2`)
4922
5062
  );
@@ -4927,7 +5067,19 @@ async function replaceVersion(version2) {
4927
5067
  );
4928
5068
  }
4929
5069
  return "jsr.json";
4930
- })()
5070
+ })(),
5071
+ ...(packages ?? []).filter((pkg) => pkg.registries.includes("crates")).map(async (pkg) => {
5072
+ const eco = new RustEcosystem(path3.resolve(pkg.path));
5073
+ try {
5074
+ await eco.writeVersion(version2);
5075
+ } catch (error) {
5076
+ throw new AbstractError(
5077
+ `Failed to write version to Cargo.toml at ${pkg.path}: ${error instanceof Error ? error.message : error}`,
5078
+ { cause: error }
5079
+ );
5080
+ }
5081
+ return path3.join(pkg.path, "Cargo.toml");
5082
+ })
4931
5083
  ]);
4932
5084
  return results.filter((v) => v);
4933
5085
  }
@@ -4948,67 +5100,26 @@ async function getPackageManager() {
4948
5100
  return "npm";
4949
5101
  }
4950
5102
 
4951
- // src/ecosystem/rust.ts
4952
- import { readFile as readFile2, stat as stat2, writeFile as writeFile2 } from "node:fs/promises";
4953
- import path2 from "node:path";
4954
- import { parse, stringify } from "smol-toml";
4955
-
4956
- // src/ecosystem/ecosystem.ts
4957
- var Ecosystem = class {
4958
- constructor(packagePath) {
4959
- this.packagePath = packagePath;
4960
- }
4961
- };
4962
-
4963
- // src/ecosystem/rust.ts
4964
- var RustEcosystem = class extends Ecosystem {
4965
- static async detect(packagePath) {
4966
- try {
4967
- return (await stat2(path2.join(packagePath, "Cargo.toml"))).isFile();
4968
- } catch {
4969
- return false;
5103
+ // src/utils/registries.ts
5104
+ function collectRegistries(ctx) {
5105
+ if (ctx.packages?.length) {
5106
+ const seen = /* @__PURE__ */ new Set();
5107
+ const result = [];
5108
+ for (const pkg of ctx.packages) {
5109
+ for (const reg of pkg.registries) {
5110
+ if (!seen.has(reg)) {
5111
+ seen.add(reg);
5112
+ result.push(reg);
5113
+ }
5114
+ }
4970
5115
  }
5116
+ return result;
4971
5117
  }
4972
- async readCargoToml() {
4973
- const raw = await readFile2(
4974
- path2.join(this.packagePath, "Cargo.toml"),
4975
- "utf-8"
4976
- );
4977
- return parse(raw);
4978
- }
4979
- async packageName() {
4980
- const cargo = await this.readCargoToml();
4981
- const pkg = cargo.package;
4982
- return pkg.name;
4983
- }
4984
- async readVersion() {
4985
- const cargo = await this.readCargoToml();
4986
- const pkg = cargo.package;
4987
- return pkg.version;
4988
- }
4989
- async writeVersion(newVersion) {
4990
- const filePath = path2.join(this.packagePath, "Cargo.toml");
4991
- const raw = await readFile2(filePath, "utf-8");
4992
- const cargo = parse(raw);
4993
- const pkg = cargo.package;
4994
- pkg.version = newVersion;
4995
- await writeFile2(filePath, stringify(cargo));
4996
- }
4997
- manifestFiles() {
4998
- return ["Cargo.toml"];
4999
- }
5000
- defaultTestCommand() {
5001
- return "cargo test";
5002
- }
5003
- defaultBuildCommand() {
5004
- return "cargo build --release";
5005
- }
5006
- supportedRegistries() {
5007
- return ["crates"];
5008
- }
5009
- };
5118
+ return ctx.registries;
5119
+ }
5010
5120
 
5011
5121
  // src/registry/crates.ts
5122
+ import path4 from "node:path";
5012
5123
  import { exec as exec3 } from "tinyexec";
5013
5124
 
5014
5125
  // src/registry/registry.ts
@@ -5082,9 +5193,13 @@ var CratesRegistry = class extends Registry {
5082
5193
  );
5083
5194
  }
5084
5195
  }
5085
- async publish() {
5196
+ async publish(manifestDir) {
5086
5197
  try {
5087
- await exec3("cargo", ["publish"], { throwOnError: true });
5198
+ const args = ["publish"];
5199
+ if (manifestDir) {
5200
+ args.push("--manifest-path", path4.join(manifestDir, "Cargo.toml"));
5201
+ }
5202
+ await exec3("cargo", args, { throwOnError: true });
5088
5203
  return true;
5089
5204
  } catch (error) {
5090
5205
  throw new CratesError("Failed to run `cargo publish`", {
@@ -5140,39 +5255,48 @@ var CratesError2 = class extends AbstractError {
5140
5255
  this.stack = "";
5141
5256
  }
5142
5257
  };
5143
- async function getCrateName() {
5144
- const eco = new RustEcosystem(process.cwd());
5258
+ async function getCrateName(packagePath) {
5259
+ const eco = new RustEcosystem(packagePath ?? process.cwd());
5145
5260
  return await eco.packageName();
5146
5261
  }
5147
- var cratesAvailableCheckTasks = {
5148
- title: "Checking crates.io availability",
5149
- task: async () => {
5150
- const packageName = await getCrateName();
5151
- const registry = new CratesRegistry(packageName);
5152
- if (!await registry.isInstalled()) {
5153
- throw new CratesError2(
5154
- "cargo is not installed. Please install Rust toolchain to proceed."
5155
- );
5262
+ function createCratesAvailableCheckTask(packagePath) {
5263
+ const label = packagePath ? ` (${packagePath})` : "";
5264
+ return {
5265
+ title: `Checking crates.io availability${label}`,
5266
+ task: async () => {
5267
+ const packageName = await getCrateName(packagePath);
5268
+ const registry = new CratesRegistry(packageName);
5269
+ if (!await registry.isInstalled()) {
5270
+ throw new CratesError2(
5271
+ "cargo is not installed. Please install Rust toolchain to proceed."
5272
+ );
5273
+ }
5274
+ if (!await registry.hasPermission()) {
5275
+ throw new CratesError2(
5276
+ "No crates.io credentials found. Run `cargo login` or set CARGO_REGISTRY_TOKEN."
5277
+ );
5278
+ }
5156
5279
  }
5157
- if (!await registry.hasPermission()) {
5158
- throw new CratesError2(
5159
- "No crates.io credentials found. Run `cargo login` or set CARGO_REGISTRY_TOKEN."
5160
- );
5280
+ };
5281
+ }
5282
+ function createCratesPublishTask(packagePath) {
5283
+ const label = packagePath ? ` (${packagePath})` : "";
5284
+ return {
5285
+ title: `Publishing to crates.io${label}`,
5286
+ task: async () => {
5287
+ const packageName = await getCrateName(packagePath);
5288
+ const registry = new CratesRegistry(packageName);
5289
+ await registry.publish(packagePath);
5161
5290
  }
5162
- }
5163
- };
5164
- var cratesPublishTasks = {
5165
- title: "Publishing to crates.io",
5166
- task: async () => {
5167
- const packageName = await getCrateName();
5168
- const registry = new CratesRegistry(packageName);
5169
- await registry.publish();
5170
- }
5171
- };
5291
+ };
5292
+ }
5293
+ var cratesAvailableCheckTasks = createCratesAvailableCheckTask();
5294
+ var cratesPublishTasks = createCratesPublishTask();
5172
5295
 
5173
5296
  // src/tasks/jsr.ts
5174
5297
  import process8 from "node:process";
5175
5298
  import { ListrEnquirerPromptAdapter } from "@listr2/prompt-adapter-enquirer";
5299
+ import npmCli from "@npmcli/promise-spawn";
5176
5300
 
5177
5301
  // src/registry/jsr.ts
5178
5302
  import { exec as exec4, NonZeroExitError } from "tinyexec";
@@ -5180,7 +5304,7 @@ import { exec as exec4, NonZeroExitError } from "tinyexec";
5180
5304
  // src/utils/db.ts
5181
5305
  import { createCipheriv, createDecipheriv, createHash } from "node:crypto";
5182
5306
  import { mkdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
5183
- import path3 from "node:path";
5307
+ import path5 from "node:path";
5184
5308
  var a = "aes-256-cbc";
5185
5309
  var n = statSync(import.meta.dirname);
5186
5310
  var k = `${n.rdev}${n.birthtimeMs}${n.nlink}${n.gid}`;
@@ -5195,7 +5319,7 @@ function d(g, h) {
5195
5319
  }
5196
5320
  var Db = class {
5197
5321
  constructor() {
5198
- __publicField(this, "path", path3.resolve(import.meta.dirname, ".pubm"));
5322
+ __publicField(this, "path", path5.resolve(import.meta.dirname, ".pubm"));
5199
5323
  try {
5200
5324
  if (!statSync(this.path).isDirectory()) {
5201
5325
  mkdirSync(this.path);
@@ -5213,7 +5337,7 @@ var Db = class {
5213
5337
  set(field, value) {
5214
5338
  try {
5215
5339
  writeFileSync(
5216
- path3.resolve(
5340
+ path5.resolve(
5217
5341
  this.path,
5218
5342
  Buffer.from(e(field, field)).toString("base64")
5219
5343
  ),
@@ -5227,7 +5351,7 @@ var Db = class {
5227
5351
  }
5228
5352
  }
5229
5353
  get(field) {
5230
- const filePath = path3.resolve(
5354
+ const filePath = path5.resolve(
5231
5355
  this.path,
5232
5356
  Buffer.from(e(field, field)).toString("base64")
5233
5357
  );
@@ -5309,6 +5433,7 @@ var JsrRegisry = class extends Registry {
5309
5433
  super(packageName, registry);
5310
5434
  __publicField(this, "registry", "https://jsr.io");
5311
5435
  __publicField(this, "client");
5436
+ __publicField(this, "packageCreationUrls");
5312
5437
  this.client = new JsrClient(getApiEndpoint(this.registry));
5313
5438
  }
5314
5439
  async jsr(args) {
@@ -5350,9 +5475,19 @@ var JsrRegisry = class extends Registry {
5350
5475
  throwOnError: true
5351
5476
  }
5352
5477
  );
5478
+ this.packageCreationUrls = void 0;
5353
5479
  return true;
5354
5480
  } catch (error) {
5355
5481
  const stderr = error instanceof NonZeroExitError ? error.output?.stderr : void 0;
5482
+ if (stderr?.includes("don't exist")) {
5483
+ const urls = [...stderr.matchAll(/https:\/\/jsr\.io\/new\S+/g)].map(
5484
+ (m) => m[0]
5485
+ );
5486
+ if (urls.length > 0) {
5487
+ this.packageCreationUrls = urls;
5488
+ return false;
5489
+ }
5490
+ }
5356
5491
  throw new JsrError(
5357
5492
  `Failed to run \`jsr publish --allow-dirty --token ***\`${stderr ? `
5358
5493
  ${stderr}` : ""}`,
@@ -5793,6 +5928,7 @@ async function npmRegistry() {
5793
5928
  }
5794
5929
 
5795
5930
  // src/tasks/jsr.ts
5931
+ var { open } = npmCli;
5796
5932
  var JsrAvailableError = class extends AbstractError {
5797
5933
  constructor(message, { cause } = {}) {
5798
5934
  super(message, { cause });
@@ -5973,7 +6109,39 @@ var jsrPublishTasks = {
5973
6109
  }
5974
6110
  JsrClient.token = jsrTokenEnv;
5975
6111
  }
5976
- await jsr.publish();
6112
+ let result = await jsr.publish();
6113
+ if (!result && jsr.packageCreationUrls) {
6114
+ if (ctx.promptEnabled) {
6115
+ task.title = "Running jsr publish (package creation needed)";
6116
+ const urls = jsr.packageCreationUrls;
6117
+ const maxAttempts = 3;
6118
+ task.output = `Package doesn't exist on jsr. Create it at:
6119
+ ${urls.map((url) => ` ${color.cyan(url)}`).join("\n")}`;
6120
+ open(urls[0]);
6121
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
6122
+ await task.prompt(ListrEnquirerPromptAdapter).run({
6123
+ type: "input",
6124
+ message: `Press ${color.bold("enter")} after creating the package on jsr.io${attempt > 1 ? ` (attempt ${attempt}/${maxAttempts})` : ""}`
6125
+ });
6126
+ result = await jsr.publish();
6127
+ if (result) break;
6128
+ if (attempt < maxAttempts) {
6129
+ task.output = "Package still doesn't exist. Please create it and try again.";
6130
+ }
6131
+ }
6132
+ if (!result) {
6133
+ throw new JsrAvailableError(
6134
+ "Package creation not completed after 3 attempts."
6135
+ );
6136
+ }
6137
+ task.title = "Running jsr publish (package created)";
6138
+ } else {
6139
+ throw new JsrAvailableError(
6140
+ `Package doesn't exist on jsr. Create it at:
6141
+ ${jsr.packageCreationUrls.join("\n")}`
6142
+ );
6143
+ }
6144
+ }
5977
6145
  }
5978
6146
  };
5979
6147
 
@@ -5981,8 +6149,8 @@ var jsrPublishTasks = {
5981
6149
  import { spawn } from "node:child_process";
5982
6150
  import process9 from "node:process";
5983
6151
  import { ListrEnquirerPromptAdapter as ListrEnquirerPromptAdapter2 } from "@listr2/prompt-adapter-enquirer";
5984
- import npmCli from "@npmcli/promise-spawn";
5985
- var { open } = npmCli;
6152
+ import npmCli2 from "@npmcli/promise-spawn";
6153
+ var { open: open2 } = npmCli2;
5986
6154
  var NpmAvailableError = class extends AbstractError {
5987
6155
  constructor(message, { cause } = {}) {
5988
6156
  super(message, { cause });
@@ -6012,7 +6180,7 @@ var npmAvailableCheckTasks = {
6012
6180
  if (urlMatch && !opened) {
6013
6181
  opened = true;
6014
6182
  task.output = `Login at: ${color.cyan(urlMatch[0])}`;
6015
- open(urlMatch[0]);
6183
+ open2(urlMatch[0]);
6016
6184
  child.stdin?.write("\n");
6017
6185
  }
6018
6186
  };
@@ -6020,9 +6188,7 @@ var npmAvailableCheckTasks = {
6020
6188
  child.stderr?.on("data", onData);
6021
6189
  child.on(
6022
6190
  "close",
6023
- (code) => code === 0 ? resolve() : reject(
6024
- new Error(`npm login exited with code ${code}`)
6025
- )
6191
+ (code) => code === 0 ? resolve() : reject(new Error(`npm login exited with code ${code}`))
6026
6192
  );
6027
6193
  child.on("error", reject);
6028
6194
  });
@@ -6325,7 +6491,7 @@ var requiredConditionsCheckTask = (options) => createListr({
6325
6491
  {
6326
6492
  title: "Ping registries",
6327
6493
  task: (ctx, parentTask2) => parentTask2.newListr(
6328
- ctx.registries.map((registryKey) => ({
6494
+ collectRegistries(ctx).map((registryKey) => ({
6329
6495
  title: `Ping to ${registryKey}`,
6330
6496
  task: async () => {
6331
6497
  const registry = await getRegistry(registryKey);
@@ -6342,7 +6508,9 @@ var requiredConditionsCheckTask = (options) => createListr({
6342
6508
  task: async (_2, parentTask2) => parentTask2.newListr(
6343
6509
  [
6344
6510
  {
6345
- enabled: (ctx) => ctx.registries.some((registry) => registry !== "jsr"),
6511
+ enabled: (ctx) => collectRegistries(ctx).some(
6512
+ (registry) => registry !== "jsr"
6513
+ ),
6346
6514
  title: "Verifying if npm are installed",
6347
6515
  task: async () => {
6348
6516
  const npm = await npmRegistry();
@@ -6354,7 +6522,9 @@ var requiredConditionsCheckTask = (options) => createListr({
6354
6522
  }
6355
6523
  },
6356
6524
  {
6357
- enabled: (ctx) => ctx.registries.some((registry) => registry === "jsr"),
6525
+ enabled: (ctx) => collectRegistries(ctx).some(
6526
+ (registry) => registry === "jsr"
6527
+ ),
6358
6528
  title: "Verifying if jsr are installed",
6359
6529
  task: async (_3, task) => {
6360
6530
  const jsr = await jsrRegistry();
@@ -6385,7 +6555,7 @@ var requiredConditionsCheckTask = (options) => createListr({
6385
6555
  },
6386
6556
  {
6387
6557
  title: "Checking if test and build scripts exist",
6388
- skip: (ctx) => !needsPackageScripts(ctx.registries),
6558
+ skip: (ctx) => !needsPackageScripts(collectRegistries(ctx)),
6389
6559
  task: async (ctx) => {
6390
6560
  const { scripts } = await getPackageJson();
6391
6561
  const errors = [];
@@ -6413,23 +6583,42 @@ var requiredConditionsCheckTask = (options) => createListr({
6413
6583
  },
6414
6584
  {
6415
6585
  title: "Checking available registries for publishing",
6416
- task: (ctx, parentTask2) => parentTask2.newListr(
6417
- ctx.registries.map((registryKey) => {
6418
- switch (registryKey) {
6419
- case "npm":
6420
- return npmAvailableCheckTasks;
6421
- case "jsr":
6422
- return jsrAvailableCheckTasks;
6423
- case "crates":
6424
- return cratesAvailableCheckTasks;
6425
- default:
6426
- return npmAvailableCheckTasks;
6427
- }
6428
- }),
6429
- {
6430
- concurrent: true
6586
+ task: (ctx, parentTask2) => {
6587
+ if (ctx.packages?.length) {
6588
+ const tasks = ctx.packages.flatMap(
6589
+ (pkg) => pkg.registries.map((registryKey) => {
6590
+ switch (registryKey) {
6591
+ case "npm":
6592
+ return npmAvailableCheckTasks;
6593
+ case "jsr":
6594
+ return jsrAvailableCheckTasks;
6595
+ case "crates":
6596
+ return createCratesAvailableCheckTask(pkg.path);
6597
+ default:
6598
+ return npmAvailableCheckTasks;
6599
+ }
6600
+ })
6601
+ );
6602
+ return parentTask2.newListr(tasks, { concurrent: true });
6431
6603
  }
6432
- )
6604
+ return parentTask2.newListr(
6605
+ collectRegistries(ctx).map((registryKey) => {
6606
+ switch (registryKey) {
6607
+ case "npm":
6608
+ return npmAvailableCheckTasks;
6609
+ case "jsr":
6610
+ return jsrAvailableCheckTasks;
6611
+ case "crates":
6612
+ return cratesAvailableCheckTasks;
6613
+ default:
6614
+ return npmAvailableCheckTasks;
6615
+ }
6616
+ }),
6617
+ {
6618
+ concurrent: true
6619
+ }
6620
+ );
6621
+ }
6433
6622
  }
6434
6623
  ],
6435
6624
  {
@@ -6439,8 +6628,30 @@ var requiredConditionsCheckTask = (options) => createListr({
6439
6628
  });
6440
6629
 
6441
6630
  // src/tasks/runner.ts
6442
- var { open: open2 } = npmCli2;
6631
+ var { open: open3 } = npmCli3;
6443
6632
  var { prerelease } = SemVer;
6633
+ function registryTask(registry) {
6634
+ switch (registry) {
6635
+ case "npm":
6636
+ return npmPublishTasks;
6637
+ case "jsr":
6638
+ return jsrPublishTasks;
6639
+ case "crates":
6640
+ return cratesPublishTasks;
6641
+ default:
6642
+ return npmPublishTasks;
6643
+ }
6644
+ }
6645
+ function collectPublishTasks(ctx) {
6646
+ if (ctx.packages?.length) {
6647
+ return ctx.packages.flatMap(
6648
+ (pkg) => pkg.registries.map(
6649
+ (reg) => reg === "crates" ? createCratesPublishTask(pkg.path) : registryTask(reg)
6650
+ )
6651
+ );
6652
+ }
6653
+ return collectRegistries(ctx).map(registryTask);
6654
+ }
6444
6655
  async function run(options) {
6445
6656
  const ctx = {
6446
6657
  ...options,
@@ -6459,21 +6670,9 @@ async function run(options) {
6459
6670
  await createListr(
6460
6671
  options.publishOnly ? {
6461
6672
  title: "Publishing",
6462
- task: (ctx2, parentTask) => parentTask.newListr(
6463
- ctx2.registries.map((registry) => {
6464
- switch (registry) {
6465
- case "npm":
6466
- return npmPublishTasks;
6467
- case "jsr":
6468
- return jsrPublishTasks;
6469
- case "crates":
6470
- return cratesPublishTasks;
6471
- default:
6472
- return npmPublishTasks;
6473
- }
6474
- }),
6475
- { concurrent: true }
6476
- )
6673
+ task: (ctx2, parentTask) => parentTask.newListr(collectPublishTasks(ctx2), {
6674
+ concurrent: true
6675
+ })
6477
6676
  } : [
6478
6677
  {
6479
6678
  skip: options.skipTests,
@@ -6542,7 +6741,10 @@ async function run(options) {
6542
6741
  }
6543
6742
  }, ctx2);
6544
6743
  await git.reset();
6545
- const replaced = await replaceVersion(ctx2.version);
6744
+ const replaced = await replaceVersion(
6745
+ ctx2.version,
6746
+ ctx2.packages
6747
+ );
6546
6748
  for (const replacedFile of replaced) {
6547
6749
  await git.stage(replacedFile);
6548
6750
  }
@@ -6557,21 +6759,9 @@ async function run(options) {
6557
6759
  {
6558
6760
  skip: (ctx2) => options.skipPublish || !!ctx2.preview,
6559
6761
  title: "Publishing",
6560
- task: (ctx2, parentTask) => parentTask.newListr(
6561
- ctx2.registries.map((registry) => {
6562
- switch (registry) {
6563
- case "npm":
6564
- return npmPublishTasks;
6565
- case "jsr":
6566
- return jsrPublishTasks;
6567
- case "crates":
6568
- return cratesPublishTasks;
6569
- default:
6570
- return npmPublishTasks;
6571
- }
6572
- }),
6573
- { concurrent: true }
6574
- )
6762
+ task: (ctx2, parentTask) => parentTask.newListr(collectPublishTasks(ctx2), {
6763
+ concurrent: true
6764
+ })
6575
6765
  },
6576
6766
  {
6577
6767
  title: "Pushing tags to GitHub",
@@ -6611,7 +6801,7 @@ ${repositoryUrl}/compare/${lastRev}...${latestTag}`;
6611
6801
  );
6612
6802
  const linkUrl = link2("Link", releaseDraftUrl.toString());
6613
6803
  task.title += ` ${linkUrl}`;
6614
- await open2(releaseDraftUrl.toString());
6804
+ await open3(releaseDraftUrl.toString());
6615
6805
  }
6616
6806
  }
6617
6807
  ]
@@ -6673,11 +6863,11 @@ function generateChangelog(version2, entries, depUpdates) {
6673
6863
 
6674
6864
  // src/changeset/migrate.ts
6675
6865
  import { copyFileSync, existsSync, mkdirSync as mkdirSync2, readdirSync } from "node:fs";
6676
- import path4 from "node:path";
6866
+ import path6 from "node:path";
6677
6867
  import process11 from "node:process";
6678
6868
  var SKIPPED_FILES = /* @__PURE__ */ new Set(["config.json", "README.md"]);
6679
6869
  function migrateFromChangesets(cwd = process11.cwd()) {
6680
- const changesetDir = path4.join(cwd, ".changeset");
6870
+ const changesetDir = path6.join(cwd, ".changeset");
6681
6871
  if (!existsSync(changesetDir)) {
6682
6872
  return {
6683
6873
  success: false,
@@ -6686,7 +6876,7 @@ function migrateFromChangesets(cwd = process11.cwd()) {
6686
6876
  configMigrated: false
6687
6877
  };
6688
6878
  }
6689
- const pubmDir = path4.join(cwd, ".pubm", "changesets");
6879
+ const pubmDir = path6.join(cwd, ".pubm", "changesets");
6690
6880
  mkdirSync2(pubmDir, { recursive: true });
6691
6881
  const files = readdirSync(changesetDir);
6692
6882
  const migratedFiles = [];
@@ -6701,15 +6891,15 @@ function migrateFromChangesets(cwd = process11.cwd()) {
6701
6891
  }
6702
6892
  if (file === "pre.json") {
6703
6893
  copyFileSync(
6704
- path4.join(changesetDir, file),
6705
- path4.resolve(cwd, ".pubm", "pre.json")
6894
+ path6.join(changesetDir, file),
6895
+ path6.resolve(cwd, ".pubm", "pre.json")
6706
6896
  );
6707
6897
  migratedFiles.push(file);
6708
6898
  continue;
6709
6899
  }
6710
6900
  if (file.endsWith(".md")) {
6711
- const src = path4.join(changesetDir, file);
6712
- const dest = path4.join(pubmDir, file);
6901
+ const src = path6.join(changesetDir, file);
6902
+ const dest = path6.join(pubmDir, file);
6713
6903
  copyFileSync(src, dest);
6714
6904
  migratedFiles.push(file);
6715
6905
  }
@@ -6756,10 +6946,10 @@ function parseChangeset(content, fileName) {
6756
6946
 
6757
6947
  // src/changeset/reader.ts
6758
6948
  import { existsSync as existsSync2, readdirSync as readdirSync2, readFileSync as readFileSync2 } from "node:fs";
6759
- import path5 from "node:path";
6949
+ import path7 from "node:path";
6760
6950
  import process12 from "node:process";
6761
6951
  function readChangesets(cwd = process12.cwd()) {
6762
- const changesetsDir = path5.join(cwd, ".pubm", "changesets");
6952
+ const changesetsDir = path7.join(cwd, ".pubm", "changesets");
6763
6953
  if (!existsSync2(changesetsDir)) {
6764
6954
  return [];
6765
6955
  }
@@ -6769,7 +6959,7 @@ function readChangesets(cwd = process12.cwd()) {
6769
6959
  if (!file.endsWith(".md") || file === "README.md") {
6770
6960
  continue;
6771
6961
  }
6772
- const filePath = path5.join(changesetsDir, file);
6962
+ const filePath = path7.join(changesetsDir, file);
6773
6963
  const content = readFileSync2(filePath, "utf-8");
6774
6964
  changesets.push(parseChangeset(content, file));
6775
6965
  }
@@ -6839,7 +7029,7 @@ function calculateVersionBumps(currentVersions, cwd = process14.cwd()) {
6839
7029
 
6840
7030
  // src/changeset/writer.ts
6841
7031
  import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync2 } from "node:fs";
6842
- import path6 from "node:path";
7032
+ import path8 from "node:path";
6843
7033
  import process15 from "node:process";
6844
7034
  import { stringify as stringifyYaml } from "yaml";
6845
7035
  var adjectives = [
@@ -6934,90 +7124,16 @@ ${summary}
6934
7124
  return content;
6935
7125
  }
6936
7126
  function writeChangeset(releases, summary, cwd = process15.cwd()) {
6937
- const changesetsDir = path6.join(cwd, ".pubm", "changesets");
7127
+ const changesetsDir = path8.join(cwd, ".pubm", "changesets");
6938
7128
  mkdirSync3(changesetsDir, { recursive: true });
6939
7129
  const id = generateChangesetId();
6940
7130
  const fileName = `${id}.md`;
6941
- const filePath = path6.join(changesetsDir, fileName);
7131
+ const filePath = path8.join(changesetsDir, fileName);
6942
7132
  const content = generateChangesetContent(releases, summary);
6943
7133
  writeFileSync2(filePath, content, "utf-8");
6944
7134
  return filePath;
6945
7135
  }
6946
7136
 
6947
- // src/config/defaults.ts
6948
- var defaultValidate = {
6949
- cleanInstall: true,
6950
- entryPoints: true,
6951
- extraneousFiles: true
6952
- };
6953
- var defaultSnapshot = {
6954
- useCalculatedVersion: false,
6955
- prereleaseTemplate: "{tag}-{timestamp}"
6956
- };
6957
- var defaultConfig = {
6958
- versioning: "independent",
6959
- branch: "main",
6960
- changelog: true,
6961
- changelogFormat: "default",
6962
- commit: false,
6963
- access: "public",
6964
- fixed: [],
6965
- linked: [],
6966
- updateInternalDependencies: "patch",
6967
- ignore: [],
6968
- tag: "latest",
6969
- contents: ".",
6970
- saveToken: true,
6971
- releaseDraft: true,
6972
- releaseNotes: true,
6973
- registries: ["npm", "jsr"],
6974
- rollbackStrategy: "individual"
6975
- };
6976
- function resolveConfig(config) {
6977
- const packages = config.packages ?? [
6978
- { path: ".", registries: ["npm", "jsr"] }
6979
- ];
6980
- return {
6981
- ...defaultConfig,
6982
- ...config,
6983
- packages,
6984
- validate: { ...defaultValidate, ...config.validate },
6985
- snapshot: { ...defaultSnapshot, ...config.snapshot }
6986
- };
6987
- }
6988
-
6989
- // src/config/loader.ts
6990
- import { stat as stat3 } from "node:fs/promises";
6991
- import path7 from "node:path";
6992
- var CONFIG_FILES = [
6993
- "pubm.config.ts",
6994
- "pubm.config.mts",
6995
- "pubm.config.cts",
6996
- "pubm.config.js",
6997
- "pubm.config.mjs",
6998
- "pubm.config.cjs"
6999
- ];
7000
- async function findConfigFile(cwd) {
7001
- for (const file of CONFIG_FILES) {
7002
- const filePath = path7.join(cwd, file);
7003
- try {
7004
- if ((await stat3(filePath)).isFile()) {
7005
- return filePath;
7006
- }
7007
- } catch {
7008
- }
7009
- }
7010
- return null;
7011
- }
7012
- async function loadConfig(cwd = process.cwd()) {
7013
- const configPath = await findConfigFile(cwd);
7014
- if (!configPath) return null;
7015
- const { createJiti } = await import("jiti");
7016
- const jiti = createJiti(cwd, { interopDefault: true });
7017
- const mod = await jiti.import(configPath);
7018
- return mod.default ?? mod;
7019
- }
7020
-
7021
7137
  // src/config/types.ts
7022
7138
  function defineConfig(config) {
7023
7139
  return config;
@@ -7071,7 +7187,7 @@ function topologicalSort(graph) {
7071
7187
 
7072
7188
  // src/monorepo/discover.ts
7073
7189
  import { existsSync as existsSync4, readdirSync as readdirSync3, statSync as statSync2 } from "node:fs";
7074
- import path8 from "node:path";
7190
+ import path9 from "node:path";
7075
7191
  import micromatch from "micromatch";
7076
7192
 
7077
7193
  // src/monorepo/workspace.ts
@@ -7154,9 +7270,9 @@ import {
7154
7270
  rmSync,
7155
7271
  writeFileSync as writeFileSync3
7156
7272
  } from "node:fs";
7157
- import path9 from "node:path";
7273
+ import path10 from "node:path";
7158
7274
  function getPreStatePath(cwd) {
7159
- return path9.resolve(cwd ?? process.cwd(), ".pubm", "pre.json");
7275
+ return path10.resolve(cwd ?? process.cwd(), ".pubm", "pre.json");
7160
7276
  }
7161
7277
  function readPreState(cwd) {
7162
7278
  const filePath = getPreStatePath(cwd);
@@ -7173,7 +7289,7 @@ function enterPreMode(tag, cwd) {
7173
7289
  "Already in pre mode. Exit pre mode first before entering a new one."
7174
7290
  );
7175
7291
  }
7176
- const dir = path9.dirname(filePath);
7292
+ const dir = path10.dirname(filePath);
7177
7293
  if (!existsSync5(dir)) {
7178
7294
  mkdirSync4(dir, { recursive: true });
7179
7295
  }
@@ -7215,10 +7331,10 @@ function generateSnapshotVersion(options) {
7215
7331
 
7216
7332
  // src/validate/entry-points.ts
7217
7333
  import { existsSync as existsSync6 } from "node:fs";
7218
- import path10 from "node:path";
7334
+ import path11 from "node:path";
7219
7335
  var SIMPLE_FIELDS = ["main", "module", "types", "typings"];
7220
7336
  function checkPath(filePath, cwd) {
7221
- return existsSync6(path10.resolve(cwd, filePath));
7337
+ return existsSync6(path11.resolve(cwd, filePath));
7222
7338
  }
7223
7339
  function validateExports(exports, cwd, prefix = "exports") {
7224
7340
  const errors = [];
@@ -7322,7 +7438,18 @@ function detectExtraneousFiles(files) {
7322
7438
 
7323
7439
  // src/index.ts
7324
7440
  async function pubm(options) {
7325
- const resolvedOptions = resolveOptions({ ...options });
7441
+ const config = await loadConfig();
7442
+ const configOptions = {};
7443
+ if (config) {
7444
+ const resolved = resolveConfig(config);
7445
+ if (resolved.packages) {
7446
+ configOptions.packages = resolved.packages;
7447
+ }
7448
+ if (!options.registries && resolved.registries) {
7449
+ configOptions.registries = resolved.registries;
7450
+ }
7451
+ }
7452
+ const resolvedOptions = resolveOptions({ ...configOptions, ...options });
7326
7453
  await run(resolvedOptions);
7327
7454
  }
7328
7455
  export {