pubm 0.1.2 → 0.1.4
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 +384 -109
- package/dist/index.cjs +425 -151
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +423 -149
- 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, open3, close, replace) => index < 0 ? open3 + string + close : open3 + replaceClose(index, string, close, replace) + close;
|
|
2420
|
+
var filterEmpty = (open3, close, replace = open3, at = open3.length + 1) => (string) => string || !(string === "" || string === void 0) ? clearBleed(
|
|
2421
2421
|
("" + string).indexOf(close, at),
|
|
2422
2422
|
string,
|
|
2423
|
-
|
|
2423
|
+
open3,
|
|
2424
2424
|
close,
|
|
2425
2425
|
replace
|
|
2426
2426
|
) : "";
|
|
2427
|
-
var init = (
|
|
2427
|
+
var init = (open3, close, replace) => filterEmpty(`\x1B[${open3}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
|
}
|
|
@@ -5160,7 +5160,7 @@ function resolveOptions(options) {
|
|
|
5160
5160
|
|
|
5161
5161
|
// src/tasks/runner.ts
|
|
5162
5162
|
import process14 from "node:process";
|
|
5163
|
-
import
|
|
5163
|
+
import npmCli2 from "@npmcli/promise-spawn";
|
|
5164
5164
|
import SemVer from "semver";
|
|
5165
5165
|
import { isCI as isCI2 } from "std-env";
|
|
5166
5166
|
import { exec as exec7 } from "tinyexec";
|
|
@@ -5182,8 +5182,24 @@ async function rollback() {
|
|
|
5182
5182
|
called = true;
|
|
5183
5183
|
if (rollbacks.length <= 0) return void 0;
|
|
5184
5184
|
console.log("Rollback...");
|
|
5185
|
-
await Promise.
|
|
5186
|
-
|
|
5185
|
+
const results = await Promise.allSettled(
|
|
5186
|
+
rollbacks.map(({ fn, ctx }) => fn(ctx))
|
|
5187
|
+
);
|
|
5188
|
+
const failures = results.filter(
|
|
5189
|
+
(r) => r.status === "rejected"
|
|
5190
|
+
);
|
|
5191
|
+
if (failures.length > 0) {
|
|
5192
|
+
for (const failure of failures) {
|
|
5193
|
+
console.error(
|
|
5194
|
+
`Rollback operation failed: ${failure.reason instanceof Error ? failure.reason.message : failure.reason}`
|
|
5195
|
+
);
|
|
5196
|
+
}
|
|
5197
|
+
console.log(
|
|
5198
|
+
"Rollback completed with errors. Some operations may require manual recovery."
|
|
5199
|
+
);
|
|
5200
|
+
} else {
|
|
5201
|
+
console.log("Rollback completed");
|
|
5202
|
+
}
|
|
5187
5203
|
}
|
|
5188
5204
|
|
|
5189
5205
|
// src/utils/listr.ts
|
|
@@ -5350,20 +5366,34 @@ async function replaceVersion(version2) {
|
|
|
5350
5366
|
const packageJsonPath = await findOutFile("package.json");
|
|
5351
5367
|
if (!packageJsonPath) return void 0;
|
|
5352
5368
|
const packageJson = (await readFile(packageJsonPath)).toString();
|
|
5353
|
-
|
|
5354
|
-
|
|
5355
|
-
|
|
5356
|
-
|
|
5369
|
+
try {
|
|
5370
|
+
await writeFile(
|
|
5371
|
+
packageJsonPath,
|
|
5372
|
+
packageJson.replace(versionRegex, `$1${version2}$2`)
|
|
5373
|
+
);
|
|
5374
|
+
} catch (error) {
|
|
5375
|
+
throw new AbstractError(
|
|
5376
|
+
`Failed to write version to package.json: ${error instanceof Error ? error.message : error}`,
|
|
5377
|
+
{ cause: error }
|
|
5378
|
+
);
|
|
5379
|
+
}
|
|
5357
5380
|
return "package.json";
|
|
5358
5381
|
})(),
|
|
5359
5382
|
(async () => {
|
|
5360
5383
|
const jsrJsonPath = await findOutFile("jsr.json");
|
|
5361
5384
|
if (!jsrJsonPath) return void 0;
|
|
5362
5385
|
const jsrJson = (await readFile(jsrJsonPath)).toString();
|
|
5363
|
-
|
|
5364
|
-
|
|
5365
|
-
|
|
5366
|
-
|
|
5386
|
+
try {
|
|
5387
|
+
await writeFile(
|
|
5388
|
+
jsrJsonPath,
|
|
5389
|
+
jsrJson.replace(versionRegex, `$1${version2}$2`)
|
|
5390
|
+
);
|
|
5391
|
+
} catch (error) {
|
|
5392
|
+
throw new AbstractError(
|
|
5393
|
+
`Failed to write version to jsr.json: ${error instanceof Error ? error.message : error}`,
|
|
5394
|
+
{ cause: error }
|
|
5395
|
+
);
|
|
5396
|
+
}
|
|
5367
5397
|
return "jsr.json";
|
|
5368
5398
|
})()
|
|
5369
5399
|
]);
|
|
@@ -5382,6 +5412,7 @@ async function getPackageManager() {
|
|
|
5382
5412
|
if (await findOutFile(lockFile2)) return packageManager;
|
|
5383
5413
|
}
|
|
5384
5414
|
}
|
|
5415
|
+
console.warn("No lock file found, defaulting to npm.");
|
|
5385
5416
|
return "npm";
|
|
5386
5417
|
}
|
|
5387
5418
|
|
|
@@ -5500,13 +5531,21 @@ var CratesRegistry = class extends Registry {
|
|
|
5500
5531
|
{ headers: this.headers }
|
|
5501
5532
|
);
|
|
5502
5533
|
if (!response.ok) {
|
|
5503
|
-
|
|
5534
|
+
if (response.status === 404) {
|
|
5535
|
+
throw new CratesError(
|
|
5536
|
+
`Crate '${this.packageName}' not found on crates.io`
|
|
5537
|
+
);
|
|
5538
|
+
}
|
|
5539
|
+
throw new CratesError(
|
|
5540
|
+
`crates.io API error (HTTP ${response.status}) for crate '${this.packageName}'`
|
|
5541
|
+
);
|
|
5504
5542
|
}
|
|
5505
5543
|
const data = await response.json();
|
|
5506
5544
|
return data.crate.max_version;
|
|
5507
5545
|
} catch (error) {
|
|
5546
|
+
if (error instanceof CratesError) throw error;
|
|
5508
5547
|
throw new CratesError(
|
|
5509
|
-
`
|
|
5548
|
+
`Cannot reach crates.io to fetch version for '${this.packageName}'`,
|
|
5510
5549
|
{ cause: error }
|
|
5511
5550
|
);
|
|
5512
5551
|
}
|
|
@@ -5536,6 +5575,12 @@ var CratesRegistry = class extends Registry {
|
|
|
5536
5575
|
if (process.env.CARGO_REGISTRY_TOKEN) return true;
|
|
5537
5576
|
return this.isInstalled();
|
|
5538
5577
|
}
|
|
5578
|
+
getRequirements() {
|
|
5579
|
+
return {
|
|
5580
|
+
needsPackageScripts: false,
|
|
5581
|
+
requiredManifest: "Cargo.toml"
|
|
5582
|
+
};
|
|
5583
|
+
}
|
|
5539
5584
|
async isPackageNameAvaliable() {
|
|
5540
5585
|
try {
|
|
5541
5586
|
const response = await fetch(
|
|
@@ -5543,8 +5588,11 @@ var CratesRegistry = class extends Registry {
|
|
|
5543
5588
|
{ headers: this.headers }
|
|
5544
5589
|
);
|
|
5545
5590
|
return !response.ok;
|
|
5546
|
-
} catch {
|
|
5547
|
-
|
|
5591
|
+
} catch (error) {
|
|
5592
|
+
throw new CratesError(
|
|
5593
|
+
`Failed to check package name availability on crates.io`,
|
|
5594
|
+
{ cause: error }
|
|
5595
|
+
);
|
|
5548
5596
|
}
|
|
5549
5597
|
}
|
|
5550
5598
|
};
|
|
@@ -5595,7 +5643,7 @@ import process12 from "node:process";
|
|
|
5595
5643
|
import { ListrEnquirerPromptAdapter } from "@listr2/prompt-adapter-enquirer";
|
|
5596
5644
|
|
|
5597
5645
|
// src/registry/jsr.ts
|
|
5598
|
-
import {
|
|
5646
|
+
import { exec as exec4, NonZeroExitError } from "tinyexec";
|
|
5599
5647
|
|
|
5600
5648
|
// src/utils/db.ts
|
|
5601
5649
|
import { createCipheriv, createDecipheriv, createHash } from "node:crypto";
|
|
@@ -5621,32 +5669,50 @@ var Db = class {
|
|
|
5621
5669
|
mkdirSync5(this.path);
|
|
5622
5670
|
}
|
|
5623
5671
|
} catch {
|
|
5624
|
-
|
|
5672
|
+
try {
|
|
5673
|
+
mkdirSync5(this.path);
|
|
5674
|
+
} catch (error) {
|
|
5675
|
+
throw new Error(
|
|
5676
|
+
`Failed to create token storage directory at '${this.path}': ${error instanceof Error ? error.message : error}`
|
|
5677
|
+
);
|
|
5678
|
+
}
|
|
5625
5679
|
}
|
|
5626
5680
|
}
|
|
5627
5681
|
set(field, value) {
|
|
5628
|
-
|
|
5629
|
-
|
|
5630
|
-
|
|
5631
|
-
|
|
5632
|
-
|
|
5682
|
+
try {
|
|
5683
|
+
writeFileSync4(
|
|
5684
|
+
path8.resolve(
|
|
5685
|
+
this.path,
|
|
5686
|
+
Buffer.from(e(field, field)).toString("base64")
|
|
5687
|
+
),
|
|
5688
|
+
Buffer.from(e(`${value}`, field)),
|
|
5689
|
+
{ encoding: "binary" }
|
|
5690
|
+
);
|
|
5691
|
+
} catch (error) {
|
|
5692
|
+
throw new Error(
|
|
5693
|
+
`Failed to save token for '${field}': ${error instanceof Error ? error.message : error}`
|
|
5694
|
+
);
|
|
5695
|
+
}
|
|
5633
5696
|
}
|
|
5634
5697
|
get(field) {
|
|
5698
|
+
const filePath = path8.resolve(
|
|
5699
|
+
this.path,
|
|
5700
|
+
Buffer.from(e(field, field)).toString("base64")
|
|
5701
|
+
);
|
|
5702
|
+
let raw;
|
|
5635
5703
|
try {
|
|
5636
|
-
|
|
5637
|
-
Buffer.from(
|
|
5638
|
-
readFileSync3(
|
|
5639
|
-
path8.resolve(
|
|
5640
|
-
this.path,
|
|
5641
|
-
Buffer.from(e(field, field)).toString("base64")
|
|
5642
|
-
)
|
|
5643
|
-
)
|
|
5644
|
-
).toString(),
|
|
5645
|
-
field
|
|
5646
|
-
);
|
|
5704
|
+
raw = readFileSync3(filePath);
|
|
5647
5705
|
} catch {
|
|
5648
5706
|
return null;
|
|
5649
5707
|
}
|
|
5708
|
+
try {
|
|
5709
|
+
return d(Buffer.from(raw).toString(), field);
|
|
5710
|
+
} catch {
|
|
5711
|
+
console.warn(
|
|
5712
|
+
`Stored token for '${field}' appears corrupted. It will be re-requested.`
|
|
5713
|
+
);
|
|
5714
|
+
return null;
|
|
5715
|
+
}
|
|
5650
5716
|
}
|
|
5651
5717
|
};
|
|
5652
5718
|
|
|
@@ -5660,9 +5726,12 @@ function getScope(packageName) {
|
|
|
5660
5726
|
}
|
|
5661
5727
|
function getScopeAndName(packageName) {
|
|
5662
5728
|
const matches = packageName.match(/^@([a-zA-Z0-9]+)\/([a-zA-Z0-9]+)$/);
|
|
5663
|
-
|
|
5664
|
-
|
|
5665
|
-
|
|
5729
|
+
if (!matches) {
|
|
5730
|
+
throw new Error(
|
|
5731
|
+
`Invalid scoped package name: '${packageName}'. Expected format: @scope/name`
|
|
5732
|
+
);
|
|
5733
|
+
}
|
|
5734
|
+
return [matches[1], matches[2]];
|
|
5666
5735
|
}
|
|
5667
5736
|
var scopedPackagePattern = /^(?:@([^/]+?)[/])?([^/]+?)$/;
|
|
5668
5737
|
var blacklist = ["node_modules", "favicon.ico"];
|
|
@@ -5781,6 +5850,12 @@ ${stderr}` : ""}`,
|
|
|
5781
5850
|
async isPackageNameAvaliable() {
|
|
5782
5851
|
return isValidPackageName(this.packageName);
|
|
5783
5852
|
}
|
|
5853
|
+
getRequirements() {
|
|
5854
|
+
return {
|
|
5855
|
+
needsPackageScripts: false,
|
|
5856
|
+
requiredManifest: "jsr.json"
|
|
5857
|
+
};
|
|
5858
|
+
}
|
|
5784
5859
|
};
|
|
5785
5860
|
var _JsrClient = class _JsrClient {
|
|
5786
5861
|
constructor(apiEndpoint) {
|
|
@@ -5801,6 +5876,9 @@ var _JsrClient = class _JsrClient {
|
|
|
5801
5876
|
try {
|
|
5802
5877
|
const response = await this.fetch("/user");
|
|
5803
5878
|
if (response.status === 401) return null;
|
|
5879
|
+
if (!response.ok) {
|
|
5880
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
5881
|
+
}
|
|
5804
5882
|
return await response.json();
|
|
5805
5883
|
} catch (error) {
|
|
5806
5884
|
throw new JsrError(`Failed to fetch \`${this.apiEndpoint}/user\``, {
|
|
@@ -5812,6 +5890,9 @@ var _JsrClient = class _JsrClient {
|
|
|
5812
5890
|
try {
|
|
5813
5891
|
const response = await this.fetch(`/user/member/${scope}`);
|
|
5814
5892
|
if (response.status === 401) return null;
|
|
5893
|
+
if (!response.ok) {
|
|
5894
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
5895
|
+
}
|
|
5815
5896
|
return await response.json();
|
|
5816
5897
|
} catch (error) {
|
|
5817
5898
|
throw new JsrError(
|
|
@@ -5826,9 +5907,14 @@ var _JsrClient = class _JsrClient {
|
|
|
5826
5907
|
try {
|
|
5827
5908
|
const response = await this.fetch("/user/scopes");
|
|
5828
5909
|
if (response.status === 401) return [];
|
|
5829
|
-
|
|
5830
|
-
({
|
|
5831
|
-
|
|
5910
|
+
if (!response.ok) {
|
|
5911
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
5912
|
+
}
|
|
5913
|
+
const body = await response.json();
|
|
5914
|
+
if (!Array.isArray(body)) {
|
|
5915
|
+
throw new Error(`Expected array response but got ${typeof body}`);
|
|
5916
|
+
}
|
|
5917
|
+
return body.map(({ scope }) => scope);
|
|
5832
5918
|
} catch (error) {
|
|
5833
5919
|
throw new JsrError(
|
|
5834
5920
|
`Failed to fetch \`${this.apiEndpoint}/user/scopes\``,
|
|
@@ -5842,10 +5928,17 @@ var _JsrClient = class _JsrClient {
|
|
|
5842
5928
|
const [scope, name] = getScopeAndName(packageName);
|
|
5843
5929
|
try {
|
|
5844
5930
|
const response = await this.fetch(`/scopes/${scope}/packages/${name}`);
|
|
5931
|
+
if (response.status === 404) return null;
|
|
5932
|
+
if (!response.ok) {
|
|
5933
|
+
throw new JsrError(
|
|
5934
|
+
`JSR API error (HTTP ${response.status}) for package '${packageName}'`
|
|
5935
|
+
);
|
|
5936
|
+
}
|
|
5845
5937
|
return await response.json();
|
|
5846
5938
|
} catch (error) {
|
|
5939
|
+
if (error instanceof JsrError) throw error;
|
|
5847
5940
|
throw new JsrError(
|
|
5848
|
-
`Failed to fetch \`${this.apiEndpoint}/
|
|
5941
|
+
`Failed to fetch \`${this.apiEndpoint}/scopes/${scope}/packages/${name}\``,
|
|
5849
5942
|
{
|
|
5850
5943
|
cause: error
|
|
5851
5944
|
}
|
|
@@ -5858,8 +5951,18 @@ var _JsrClient = class _JsrClient {
|
|
|
5858
5951
|
method: "POST",
|
|
5859
5952
|
body: JSON.stringify({ scope })
|
|
5860
5953
|
});
|
|
5861
|
-
|
|
5954
|
+
if (response.status === 200 || response.status === 201) return true;
|
|
5955
|
+
let detail = "";
|
|
5956
|
+
try {
|
|
5957
|
+
const body = await response.json();
|
|
5958
|
+
detail = body.message || body.error || JSON.stringify(body);
|
|
5959
|
+
} catch {
|
|
5960
|
+
}
|
|
5961
|
+
throw new JsrError(
|
|
5962
|
+
`Failed to create scope '${scope}': HTTP ${response.status}${detail ? ` \u2014 ${detail}` : ""}`
|
|
5963
|
+
);
|
|
5862
5964
|
} catch (error) {
|
|
5965
|
+
if (error instanceof JsrError) throw error;
|
|
5863
5966
|
throw new JsrError(`Failed to fetch \`${this.apiEndpoint}/scopes\``, {
|
|
5864
5967
|
cause: error
|
|
5865
5968
|
});
|
|
@@ -5870,8 +5973,18 @@ var _JsrClient = class _JsrClient {
|
|
|
5870
5973
|
const response = await this.fetch(`/scopes/${scope}`, {
|
|
5871
5974
|
method: "DELETE"
|
|
5872
5975
|
});
|
|
5873
|
-
|
|
5976
|
+
if (response.status === 200 || response.status === 204) return true;
|
|
5977
|
+
let detail = "";
|
|
5978
|
+
try {
|
|
5979
|
+
const body = await response.json();
|
|
5980
|
+
detail = body.message || body.error || JSON.stringify(body);
|
|
5981
|
+
} catch {
|
|
5982
|
+
}
|
|
5983
|
+
throw new JsrError(
|
|
5984
|
+
`Failed to delete scope '${scope}': HTTP ${response.status}${detail ? ` \u2014 ${detail}` : ""}`
|
|
5985
|
+
);
|
|
5874
5986
|
} catch (error) {
|
|
5987
|
+
if (error instanceof JsrError) throw error;
|
|
5875
5988
|
throw new JsrError(
|
|
5876
5989
|
`Failed to fetch \`${this.apiEndpoint}/scopes/${scope}\``,
|
|
5877
5990
|
{
|
|
@@ -5887,8 +6000,18 @@ var _JsrClient = class _JsrClient {
|
|
|
5887
6000
|
method: "POST",
|
|
5888
6001
|
body: JSON.stringify({ package: name })
|
|
5889
6002
|
});
|
|
5890
|
-
|
|
6003
|
+
if (response.status === 200 || response.status === 201) return true;
|
|
6004
|
+
let detail = "";
|
|
6005
|
+
try {
|
|
6006
|
+
const body = await response.json();
|
|
6007
|
+
detail = body.message || body.error || JSON.stringify(body);
|
|
6008
|
+
} catch {
|
|
6009
|
+
}
|
|
6010
|
+
throw new JsrError(
|
|
6011
|
+
`Failed to create package '${packageName}': HTTP ${response.status}${detail ? ` \u2014 ${detail}` : ""}`
|
|
6012
|
+
);
|
|
5891
6013
|
} catch (error) {
|
|
6014
|
+
if (error instanceof JsrError) throw error;
|
|
5892
6015
|
throw new JsrError(
|
|
5893
6016
|
`Failed to fetch \`${this.apiEndpoint}/scopes/${scope}/packages\``,
|
|
5894
6017
|
{
|
|
@@ -5903,8 +6026,18 @@ var _JsrClient = class _JsrClient {
|
|
|
5903
6026
|
const response = await this.fetch(`/scopes/${scope}/packages/${name}`, {
|
|
5904
6027
|
method: "DELETE"
|
|
5905
6028
|
});
|
|
5906
|
-
|
|
6029
|
+
if (response.status === 200 || response.status === 204) return true;
|
|
6030
|
+
let detail = "";
|
|
6031
|
+
try {
|
|
6032
|
+
const body = await response.json();
|
|
6033
|
+
detail = body.message || body.error || JSON.stringify(body);
|
|
6034
|
+
} catch {
|
|
6035
|
+
}
|
|
6036
|
+
throw new JsrError(
|
|
6037
|
+
`Failed to delete package '${packageName}': HTTP ${response.status}${detail ? ` \u2014 ${detail}` : ""}`
|
|
6038
|
+
);
|
|
5907
6039
|
} catch (error) {
|
|
6040
|
+
if (error instanceof JsrError) throw error;
|
|
5908
6041
|
throw new JsrError(
|
|
5909
6042
|
`Failed to fetch \`${this.apiEndpoint}/scopes/${scope}/packages/${name}\``,
|
|
5910
6043
|
{
|
|
@@ -5916,6 +6049,9 @@ var _JsrClient = class _JsrClient {
|
|
|
5916
6049
|
async searchPackage(query) {
|
|
5917
6050
|
try {
|
|
5918
6051
|
const response = await this.fetch(`/packages?query=${query}`);
|
|
6052
|
+
if (!response.ok) {
|
|
6053
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
6054
|
+
}
|
|
5919
6055
|
return await response.json();
|
|
5920
6056
|
} catch (error) {
|
|
5921
6057
|
throw new JsrError(
|
|
@@ -5935,7 +6071,7 @@ async function jsrRegistry() {
|
|
|
5935
6071
|
}
|
|
5936
6072
|
|
|
5937
6073
|
// src/registry/npm.ts
|
|
5938
|
-
import {
|
|
6074
|
+
import { exec as exec5, NonZeroExitError as NonZeroExitError2 } from "tinyexec";
|
|
5939
6075
|
var NpmError = class extends AbstractError {
|
|
5940
6076
|
constructor() {
|
|
5941
6077
|
super(...arguments);
|
|
@@ -5992,7 +6128,7 @@ var NpmRegistry = class extends Registry {
|
|
|
5992
6128
|
await this.npm(["whoami"]);
|
|
5993
6129
|
return true;
|
|
5994
6130
|
} catch (error) {
|
|
5995
|
-
if (error instanceof NonZeroExitError2
|
|
6131
|
+
if (error instanceof NonZeroExitError2) {
|
|
5996
6132
|
return false;
|
|
5997
6133
|
}
|
|
5998
6134
|
throw new NpmError("Failed to run `npm whoami`", { cause: error });
|
|
@@ -6000,16 +6136,22 @@ var NpmRegistry = class extends Registry {
|
|
|
6000
6136
|
}
|
|
6001
6137
|
async collaborators() {
|
|
6002
6138
|
try {
|
|
6003
|
-
|
|
6004
|
-
|
|
6005
|
-
|
|
6006
|
-
|
|
6007
|
-
|
|
6008
|
-
|
|
6009
|
-
|
|
6010
|
-
|
|
6011
|
-
|
|
6139
|
+
const output = await this.npm([
|
|
6140
|
+
"access",
|
|
6141
|
+
"list",
|
|
6142
|
+
"collaborators",
|
|
6143
|
+
this.packageName,
|
|
6144
|
+
"--json"
|
|
6145
|
+
]);
|
|
6146
|
+
try {
|
|
6147
|
+
return JSON.parse(output);
|
|
6148
|
+
} catch {
|
|
6149
|
+
throw new NpmError(
|
|
6150
|
+
`Unexpected response from npm registry for collaborators of '${this.packageName}'`
|
|
6151
|
+
);
|
|
6152
|
+
}
|
|
6012
6153
|
} catch (error) {
|
|
6154
|
+
if (error instanceof NpmError) throw error;
|
|
6013
6155
|
throw new NpmError(
|
|
6014
6156
|
`Failed to run \`npm access list collaborators ${this.packageName} --json\``,
|
|
6015
6157
|
{ cause: error }
|
|
@@ -6023,12 +6165,21 @@ var NpmRegistry = class extends Registry {
|
|
|
6023
6165
|
}
|
|
6024
6166
|
async distTags() {
|
|
6025
6167
|
try {
|
|
6026
|
-
|
|
6027
|
-
|
|
6028
|
-
|
|
6029
|
-
|
|
6030
|
-
|
|
6168
|
+
const output = await this.npm([
|
|
6169
|
+
"view",
|
|
6170
|
+
this.packageName,
|
|
6171
|
+
"dist-tags",
|
|
6172
|
+
"--json"
|
|
6173
|
+
]);
|
|
6174
|
+
try {
|
|
6175
|
+
return Object.keys(JSON.parse(output));
|
|
6176
|
+
} catch {
|
|
6177
|
+
throw new NpmError(
|
|
6178
|
+
`Unexpected response from npm registry for dist-tags of '${this.packageName}'`
|
|
6179
|
+
);
|
|
6180
|
+
}
|
|
6031
6181
|
} catch (error) {
|
|
6182
|
+
if (error instanceof NpmError) throw error;
|
|
6032
6183
|
throw new NpmError(
|
|
6033
6184
|
`Failed to run \`npm view ${this.packageName} dist-tags --json\``,
|
|
6034
6185
|
{ cause: error }
|
|
@@ -6058,12 +6209,7 @@ var NpmRegistry = class extends Registry {
|
|
|
6058
6209
|
if (error instanceof NonZeroExitError2 && error.output?.stderr.includes("EOTP")) {
|
|
6059
6210
|
return false;
|
|
6060
6211
|
}
|
|
6061
|
-
throw
|
|
6062
|
-
"Failed to run `npm publish --provenance --access public`",
|
|
6063
|
-
{
|
|
6064
|
-
cause: error
|
|
6065
|
-
}
|
|
6066
|
-
);
|
|
6212
|
+
throw this.classifyPublishError(error);
|
|
6067
6213
|
}
|
|
6068
6214
|
}
|
|
6069
6215
|
async publish(otp) {
|
|
@@ -6075,14 +6221,39 @@ var NpmRegistry = class extends Registry {
|
|
|
6075
6221
|
if (error instanceof NonZeroExitError2 && error.output?.stderr.includes("EOTP")) {
|
|
6076
6222
|
return false;
|
|
6077
6223
|
}
|
|
6078
|
-
throw
|
|
6079
|
-
cause: error
|
|
6080
|
-
});
|
|
6224
|
+
throw this.classifyPublishError(error);
|
|
6081
6225
|
}
|
|
6082
6226
|
}
|
|
6083
6227
|
async isPackageNameAvaliable() {
|
|
6084
6228
|
return isValidPackageName(this.packageName);
|
|
6085
6229
|
}
|
|
6230
|
+
getRequirements() {
|
|
6231
|
+
return {
|
|
6232
|
+
needsPackageScripts: true,
|
|
6233
|
+
requiredManifest: "package.json"
|
|
6234
|
+
};
|
|
6235
|
+
}
|
|
6236
|
+
classifyPublishError(error) {
|
|
6237
|
+
if (error instanceof NonZeroExitError2) {
|
|
6238
|
+
const stderr = error.output?.stderr ?? "";
|
|
6239
|
+
if (stderr.includes("EOTP")) {
|
|
6240
|
+
return new NpmError("OTP required for publishing", { cause: error });
|
|
6241
|
+
}
|
|
6242
|
+
if (stderr.includes("403") || stderr.includes("Forbidden")) {
|
|
6243
|
+
return new NpmError(
|
|
6244
|
+
"Permission denied (403 Forbidden). Check your npm access token permissions.",
|
|
6245
|
+
{ cause: error }
|
|
6246
|
+
);
|
|
6247
|
+
}
|
|
6248
|
+
if (stderr.includes("429") || stderr.includes("Too Many Requests")) {
|
|
6249
|
+
return new NpmError(
|
|
6250
|
+
"Rate limited by npm registry. Please wait and try again.",
|
|
6251
|
+
{ cause: error }
|
|
6252
|
+
);
|
|
6253
|
+
}
|
|
6254
|
+
}
|
|
6255
|
+
return new NpmError("Failed to publish to npm", { cause: error });
|
|
6256
|
+
}
|
|
6086
6257
|
};
|
|
6087
6258
|
async function npmRegistry() {
|
|
6088
6259
|
const packageJson = await getPackageJson();
|
|
@@ -6114,17 +6285,34 @@ var jsrAvailableCheckTasks = {
|
|
|
6114
6285
|
if (!JsrClient.token) {
|
|
6115
6286
|
task.output = "Retrieving jsr API token";
|
|
6116
6287
|
if (ctx.promptEnabled) {
|
|
6117
|
-
|
|
6288
|
+
const maxAttempts = 3;
|
|
6289
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
6118
6290
|
JsrClient.token = await task.prompt(ListrEnquirerPromptAdapter).run({
|
|
6119
6291
|
type: "password",
|
|
6120
|
-
message: `Please enter the jsr ${color.bold("API token")}`,
|
|
6292
|
+
message: `Please enter the jsr ${color.bold("API token")}${attempt > 1 ? ` (attempt ${attempt}/${maxAttempts})` : ""}`,
|
|
6121
6293
|
footer: `
|
|
6122
6294
|
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'")}.`
|
|
6123
6295
|
});
|
|
6124
6296
|
try {
|
|
6125
6297
|
if (await jsr.client.user()) break;
|
|
6126
|
-
|
|
6127
|
-
|
|
6298
|
+
if (attempt < maxAttempts) {
|
|
6299
|
+
task.output = "The jsr API token is invalid. Please re-enter a valid token.";
|
|
6300
|
+
}
|
|
6301
|
+
} catch (error) {
|
|
6302
|
+
if (error instanceof Error && (error.message.includes("fetch") || error.message.includes("network") || error.message.includes("ENOTFOUND"))) {
|
|
6303
|
+
throw new JsrAvailableError(
|
|
6304
|
+
"JSR API is unreachable. Check your network connection.",
|
|
6305
|
+
{ cause: error }
|
|
6306
|
+
);
|
|
6307
|
+
}
|
|
6308
|
+
if (attempt < maxAttempts) {
|
|
6309
|
+
task.output = "The jsr API token is invalid. Please re-enter a valid token.";
|
|
6310
|
+
}
|
|
6311
|
+
}
|
|
6312
|
+
if (attempt === maxAttempts) {
|
|
6313
|
+
throw new JsrAvailableError(
|
|
6314
|
+
"JSR token verification failed after 3 attempts."
|
|
6315
|
+
);
|
|
6128
6316
|
}
|
|
6129
6317
|
}
|
|
6130
6318
|
} else {
|
|
@@ -6147,7 +6335,7 @@ Generate a token from ${color.bold(link2("jsr.io", "https://jsr.io/account/token
|
|
|
6147
6335
|
scopes.map(
|
|
6148
6336
|
(scope2) => jsr.client.package(`@${scope2}/${jsr.packageName}`)
|
|
6149
6337
|
)
|
|
6150
|
-
)).filter((v) => v);
|
|
6338
|
+
)).filter((v) => v !== null);
|
|
6151
6339
|
if (searchResults.length > 0) {
|
|
6152
6340
|
jsrName = await task.prompt(ListrEnquirerPromptAdapter).run({
|
|
6153
6341
|
type: "select",
|
|
@@ -6258,8 +6446,11 @@ var jsrPublishTasks = {
|
|
|
6258
6446
|
};
|
|
6259
6447
|
|
|
6260
6448
|
// src/tasks/npm.ts
|
|
6449
|
+
import { spawn } from "node:child_process";
|
|
6261
6450
|
import process13 from "node:process";
|
|
6262
6451
|
import { ListrEnquirerPromptAdapter as ListrEnquirerPromptAdapter2 } from "@listr2/prompt-adapter-enquirer";
|
|
6452
|
+
import npmCli from "@npmcli/promise-spawn";
|
|
6453
|
+
var { open } = npmCli;
|
|
6263
6454
|
var NpmAvailableError = class extends AbstractError {
|
|
6264
6455
|
constructor(message, { cause } = {}) {
|
|
6265
6456
|
super(message, { cause });
|
|
@@ -6270,12 +6461,55 @@ var NpmAvailableError = class extends AbstractError {
|
|
|
6270
6461
|
var npmAvailableCheckTasks = {
|
|
6271
6462
|
title: "Checking npm avaliable for publising",
|
|
6272
6463
|
skip: (ctx) => !!ctx.preview,
|
|
6273
|
-
task: async () => {
|
|
6464
|
+
task: async (ctx, task) => {
|
|
6274
6465
|
const npm = await npmRegistry();
|
|
6275
6466
|
if (!await npm.isLoggedIn()) {
|
|
6276
|
-
|
|
6277
|
-
|
|
6278
|
-
|
|
6467
|
+
if (ctx.promptEnabled) {
|
|
6468
|
+
try {
|
|
6469
|
+
task.output = "Launching npm login...";
|
|
6470
|
+
await new Promise((resolve, reject) => {
|
|
6471
|
+
const child = spawn("npm", ["login"], {
|
|
6472
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
6473
|
+
});
|
|
6474
|
+
let opened = false;
|
|
6475
|
+
const onData = (data) => {
|
|
6476
|
+
const text = data.toString();
|
|
6477
|
+
const urlMatch = text.match(
|
|
6478
|
+
/https:\/\/www\.npmjs\.com\/login[^\s]*/
|
|
6479
|
+
);
|
|
6480
|
+
if (urlMatch && !opened) {
|
|
6481
|
+
opened = true;
|
|
6482
|
+
task.output = `Login at: ${color.cyan(urlMatch[0])}`;
|
|
6483
|
+
open(urlMatch[0]);
|
|
6484
|
+
child.stdin?.write("\n");
|
|
6485
|
+
}
|
|
6486
|
+
};
|
|
6487
|
+
child.stdout?.on("data", onData);
|
|
6488
|
+
child.stderr?.on("data", onData);
|
|
6489
|
+
child.on(
|
|
6490
|
+
"close",
|
|
6491
|
+
(code) => code === 0 ? resolve() : reject(
|
|
6492
|
+
new Error(`npm login exited with code ${code}`)
|
|
6493
|
+
)
|
|
6494
|
+
);
|
|
6495
|
+
child.on("error", reject);
|
|
6496
|
+
});
|
|
6497
|
+
} catch (error) {
|
|
6498
|
+
throw new NpmAvailableError(
|
|
6499
|
+
"npm login failed. Please run `npm login` manually and try again.",
|
|
6500
|
+
{ cause: error }
|
|
6501
|
+
);
|
|
6502
|
+
}
|
|
6503
|
+
if (!await npm.isLoggedIn()) {
|
|
6504
|
+
throw new NpmAvailableError(
|
|
6505
|
+
"Still not logged in after npm login. Please verify your credentials."
|
|
6506
|
+
);
|
|
6507
|
+
}
|
|
6508
|
+
} else {
|
|
6509
|
+
throw new NpmAvailableError(
|
|
6510
|
+
"Not logged in to npm. Set NODE_AUTH_TOKEN in your CI environment. For GitHub Actions, add it as a repository secret."
|
|
6511
|
+
);
|
|
6512
|
+
}
|
|
6279
6513
|
}
|
|
6280
6514
|
if (await npm.isPublished()) {
|
|
6281
6515
|
if (!await npm.hasPermission()) {
|
|
@@ -6303,24 +6537,31 @@ var npmPublishTasks = {
|
|
|
6303
6537
|
let result = await npm.publish();
|
|
6304
6538
|
if (!result) {
|
|
6305
6539
|
task.title = "Running npm publish (OTP code needed)";
|
|
6306
|
-
|
|
6540
|
+
const maxAttempts = 3;
|
|
6541
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
6307
6542
|
result = await npm.publish(
|
|
6308
6543
|
await task.prompt(ListrEnquirerPromptAdapter2).run({
|
|
6309
6544
|
type: "password",
|
|
6310
|
-
message:
|
|
6545
|
+
message: `npm OTP code${attempt > 1 ? ` (attempt ${attempt}/${maxAttempts})` : ""}`
|
|
6311
6546
|
})
|
|
6312
6547
|
);
|
|
6313
|
-
if (
|
|
6314
|
-
|
|
6548
|
+
if (result) break;
|
|
6549
|
+
if (attempt < maxAttempts) {
|
|
6550
|
+
task.output = "2FA failed. Please try again.";
|
|
6315
6551
|
}
|
|
6316
6552
|
}
|
|
6553
|
+
if (!result) {
|
|
6554
|
+
throw new NpmAvailableError(
|
|
6555
|
+
"OTP verification failed after 3 attempts."
|
|
6556
|
+
);
|
|
6557
|
+
}
|
|
6317
6558
|
task.title = "Running npm publish (2FA passed)";
|
|
6318
6559
|
}
|
|
6319
6560
|
} else {
|
|
6320
6561
|
const npmTokenEnv = process13.env.NODE_AUTH_TOKEN;
|
|
6321
6562
|
if (!npmTokenEnv) {
|
|
6322
6563
|
throw new NpmAvailableError(
|
|
6323
|
-
"NODE_AUTH_TOKEN not found in
|
|
6564
|
+
"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"
|
|
6324
6565
|
);
|
|
6325
6566
|
}
|
|
6326
6567
|
const result = await npm.publishProvenance();
|
|
@@ -6426,6 +6667,7 @@ var prerequisitesCheckTask = (options) => {
|
|
|
6426
6667
|
);
|
|
6427
6668
|
}
|
|
6428
6669
|
ctx.cleanWorkingTree = false;
|
|
6670
|
+
return;
|
|
6429
6671
|
}
|
|
6430
6672
|
ctx.cleanWorkingTree = true;
|
|
6431
6673
|
}
|
|
@@ -6526,6 +6768,16 @@ async function validateEngineVersion(engine, version2) {
|
|
|
6526
6768
|
}
|
|
6527
6769
|
|
|
6528
6770
|
// src/tasks/required-conditions-check.ts
|
|
6771
|
+
var registryRequirementsMap = {
|
|
6772
|
+
npm: { needsPackageScripts: true },
|
|
6773
|
+
jsr: { needsPackageScripts: false },
|
|
6774
|
+
crates: { needsPackageScripts: false }
|
|
6775
|
+
};
|
|
6776
|
+
function needsPackageScripts(registries) {
|
|
6777
|
+
return registries.some(
|
|
6778
|
+
(r) => registryRequirementsMap[r]?.needsPackageScripts ?? true
|
|
6779
|
+
);
|
|
6780
|
+
}
|
|
6529
6781
|
var RequiredConditionCheckError = class extends AbstractError {
|
|
6530
6782
|
constructor(message, { cause } = {}) {
|
|
6531
6783
|
super(message, { cause });
|
|
@@ -6601,7 +6853,7 @@ var requiredConditionsCheckTask = (options) => createListr({
|
|
|
6601
6853
|
},
|
|
6602
6854
|
{
|
|
6603
6855
|
title: "Checking if test and build scripts exist",
|
|
6604
|
-
skip: (ctx) => ctx.
|
|
6856
|
+
skip: (ctx) => !needsPackageScripts(ctx.registries),
|
|
6605
6857
|
task: async (ctx) => {
|
|
6606
6858
|
const { scripts } = await getPackageJson();
|
|
6607
6859
|
const errors = [];
|
|
@@ -6655,14 +6907,12 @@ var requiredConditionsCheckTask = (options) => createListr({
|
|
|
6655
6907
|
});
|
|
6656
6908
|
|
|
6657
6909
|
// src/tasks/runner.ts
|
|
6658
|
-
var { open } =
|
|
6910
|
+
var { open: open2 } = npmCli2;
|
|
6659
6911
|
var { prerelease } = SemVer;
|
|
6660
6912
|
async function run(options) {
|
|
6661
6913
|
const ctx = {
|
|
6662
6914
|
...options,
|
|
6663
|
-
promptEnabled: !isCI2 && process14.stdin.isTTY
|
|
6664
|
-
npmOnly: options.registries.every((registry) => registry !== "jsr"),
|
|
6665
|
-
jsrOnly: options.registries.every((registry) => registry === "jsr")
|
|
6915
|
+
promptEnabled: !isCI2 && process14.stdin.isTTY
|
|
6666
6916
|
};
|
|
6667
6917
|
try {
|
|
6668
6918
|
if (options.contents) process14.chdir(options.contents);
|
|
@@ -6698,9 +6948,16 @@ async function run(options) {
|
|
|
6698
6948
|
title: "Running tests",
|
|
6699
6949
|
task: async (ctx2) => {
|
|
6700
6950
|
const packageManager = await getPackageManager();
|
|
6701
|
-
|
|
6702
|
-
|
|
6703
|
-
|
|
6951
|
+
try {
|
|
6952
|
+
await exec7(packageManager, ["run", ctx2.testScript], {
|
|
6953
|
+
throwOnError: true
|
|
6954
|
+
});
|
|
6955
|
+
} catch (error) {
|
|
6956
|
+
throw new AbstractError(
|
|
6957
|
+
`Test script '${ctx2.testScript}' failed. Run \`${packageManager} run ${ctx2.testScript}\` locally to see full output.`,
|
|
6958
|
+
{ cause: error }
|
|
6959
|
+
);
|
|
6960
|
+
}
|
|
6704
6961
|
}
|
|
6705
6962
|
},
|
|
6706
6963
|
{
|
|
@@ -6714,7 +6971,7 @@ async function run(options) {
|
|
|
6714
6971
|
});
|
|
6715
6972
|
} catch (error) {
|
|
6716
6973
|
throw new AbstractError(
|
|
6717
|
-
`
|
|
6974
|
+
`Build script '${ctx2.buildScript}' failed. Run \`${packageManager} run ${ctx2.buildScript}\` locally to see full output.`,
|
|
6718
6975
|
{ cause: error }
|
|
6719
6976
|
);
|
|
6720
6977
|
}
|
|
@@ -6729,15 +6986,27 @@ async function run(options) {
|
|
|
6729
6986
|
let commited = false;
|
|
6730
6987
|
addRollback(async () => {
|
|
6731
6988
|
if (tagCreated) {
|
|
6732
|
-
|
|
6733
|
-
|
|
6989
|
+
try {
|
|
6990
|
+
console.log("Deleting tag...");
|
|
6991
|
+
await git.deleteTag(`${await git.latestTag()}`);
|
|
6992
|
+
} catch (error) {
|
|
6993
|
+
console.error(
|
|
6994
|
+
`Failed to delete tag: ${error instanceof Error ? error.message : error}`
|
|
6995
|
+
);
|
|
6996
|
+
}
|
|
6734
6997
|
}
|
|
6735
6998
|
if (commited) {
|
|
6736
|
-
|
|
6737
|
-
|
|
6738
|
-
|
|
6739
|
-
|
|
6740
|
-
|
|
6999
|
+
try {
|
|
7000
|
+
console.log("Reset commits...");
|
|
7001
|
+
await git.reset();
|
|
7002
|
+
await git.stash();
|
|
7003
|
+
await git.reset("HEAD^", "--hard");
|
|
7004
|
+
await git.popStash();
|
|
7005
|
+
} catch (error) {
|
|
7006
|
+
console.error(
|
|
7007
|
+
`Failed to reset commits: ${error instanceof Error ? error.message : error}`
|
|
7008
|
+
);
|
|
7009
|
+
}
|
|
6741
7010
|
}
|
|
6742
7011
|
}, ctx2);
|
|
6743
7012
|
await git.reset();
|
|
@@ -6810,7 +7079,7 @@ ${repositoryUrl}/compare/${lastRev}...${latestTag}`;
|
|
|
6810
7079
|
);
|
|
6811
7080
|
const linkUrl = link2("Link", releaseDraftUrl.toString());
|
|
6812
7081
|
task.title += ` ${linkUrl}`;
|
|
6813
|
-
await
|
|
7082
|
+
await open2(releaseDraftUrl.toString());
|
|
6814
7083
|
}
|
|
6815
7084
|
}
|
|
6816
7085
|
]
|
|
@@ -6838,7 +7107,9 @@ import { inc } from "semver";
|
|
|
6838
7107
|
import { stat as stat3 } from "node:fs/promises";
|
|
6839
7108
|
import path9 from "node:path";
|
|
6840
7109
|
|
|
6841
|
-
// src/monorepo/
|
|
7110
|
+
// src/monorepo/discover.ts
|
|
7111
|
+
import { existsSync as existsSync6, readdirSync as readdirSync3, statSync as statSync2 } from "node:fs";
|
|
7112
|
+
import path10 from "node:path";
|
|
6842
7113
|
import micromatch from "micromatch";
|
|
6843
7114
|
|
|
6844
7115
|
// src/monorepo/workspace.ts
|
|
@@ -6846,12 +7117,15 @@ import { existsSync as existsSync5, readFileSync as readFileSync4 } from "node:f
|
|
|
6846
7117
|
import { join } from "node:path";
|
|
6847
7118
|
import { parse as parse2 } from "yaml";
|
|
6848
7119
|
|
|
7120
|
+
// src/monorepo/groups.ts
|
|
7121
|
+
import micromatch2 from "micromatch";
|
|
7122
|
+
|
|
6849
7123
|
// src/validate/entry-points.ts
|
|
6850
|
-
import { existsSync as
|
|
6851
|
-
import
|
|
7124
|
+
import { existsSync as existsSync7 } from "node:fs";
|
|
7125
|
+
import path11 from "node:path";
|
|
6852
7126
|
|
|
6853
7127
|
// src/validate/extraneous-files.ts
|
|
6854
|
-
import
|
|
7128
|
+
import micromatch3 from "micromatch";
|
|
6855
7129
|
|
|
6856
7130
|
// src/index.ts
|
|
6857
7131
|
async function pubm(options) {
|
|
@@ -7096,6 +7370,7 @@ defaultCmd.action(
|
|
|
7096
7370
|
);
|
|
7097
7371
|
} catch (e2) {
|
|
7098
7372
|
consoleError(e2);
|
|
7373
|
+
process.exitCode = 1;
|
|
7099
7374
|
}
|
|
7100
7375
|
}
|
|
7101
7376
|
);
|