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 +537 -141
- package/dist/index.cjs +600 -275
- package/dist/index.d.cts +49 -44
- package/dist/index.d.ts +49 -44
- package/dist/index.js +589 -264
- package/package.json +1 -1
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,
|
|
2420
|
-
var filterEmpty = (
|
|
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
|
-
|
|
2423
|
+
open4,
|
|
2424
2424
|
close,
|
|
2425
2425
|
replace
|
|
2426
2426
|
) : "";
|
|
2427
|
-
var init = (
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
5186
|
-
|
|
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
|
|
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 } =
|
|
5303
|
+
const { root } = path7.parse(cwd);
|
|
5210
5304
|
while (directory) {
|
|
5211
|
-
filePath =
|
|
5305
|
+
filePath = path7.join(directory, file);
|
|
5212
5306
|
try {
|
|
5213
|
-
if ((await
|
|
5307
|
+
if ((await stat2(filePath)).isFile()) {
|
|
5214
5308
|
break;
|
|
5215
5309
|
}
|
|
5216
5310
|
} catch {
|
|
5217
5311
|
}
|
|
5218
|
-
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
|
-
|
|
5354
|
-
|
|
5355
|
-
|
|
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
|
-
|
|
5364
|
-
|
|
5365
|
-
|
|
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
|
|
5390
|
-
import
|
|
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
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
-
`
|
|
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
|
-
|
|
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
|
|
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",
|
|
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
|
-
|
|
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
|
-
|
|
5629
|
-
|
|
5630
|
-
|
|
5631
|
-
|
|
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
|
-
|
|
5637
|
-
|
|
5638
|
-
|
|
5639
|
-
|
|
5640
|
-
|
|
5641
|
-
|
|
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
|
-
|
|
5664
|
-
|
|
5665
|
-
|
|
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 (
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
6029
|
-
|
|
6030
|
-
|
|
6031
|
-
|
|
6032
|
-
|
|
6033
|
-
|
|
6034
|
-
|
|
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
|
-
|
|
6052
|
-
|
|
6053
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
6152
|
-
|
|
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
|
-
|
|
6302
|
-
|
|
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
|
-
|
|
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:
|
|
6668
|
+
message: `npm OTP code${attempt > 1 ? ` (attempt ${attempt}/${maxAttempts})` : ""}`
|
|
6336
6669
|
})
|
|
6337
6670
|
);
|
|
6338
|
-
if (
|
|
6339
|
-
|
|
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
|
|
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.
|
|
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 } =
|
|
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.
|
|
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
|
-
|
|
6727
|
-
|
|
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
|
-
`
|
|
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
|
-
|
|
6758
|
-
|
|
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
|
-
|
|
6762
|
-
|
|
6763
|
-
|
|
6764
|
-
|
|
6765
|
-
|
|
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.
|
|
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
|
|
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/
|
|
6863
|
-
import {
|
|
6864
|
-
import
|
|
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
|
|
6876
|
-
import
|
|
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
|
|
7263
|
+
import micromatch3 from "micromatch";
|
|
6880
7264
|
|
|
6881
7265
|
// src/index.ts
|
|
6882
7266
|
async function pubm(options) {
|
|
6883
|
-
const
|
|
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
|
);
|