pubm 0.1.3 → 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 +368 -118
- package/dist/index.cjs +411 -162
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +407 -158
- 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
|
};
|
|
@@ -5621,30 +5669,48 @@ 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
|
-
|
|
5638
|
-
|
|
5639
|
-
|
|
5640
|
-
|
|
5641
|
-
|
|
5642
|
-
)
|
|
5643
|
-
)
|
|
5644
|
-
).toString(),
|
|
5645
|
-
field
|
|
5646
|
-
);
|
|
5704
|
+
raw = readFileSync3(filePath);
|
|
5705
|
+
} catch {
|
|
5706
|
+
return null;
|
|
5707
|
+
}
|
|
5708
|
+
try {
|
|
5709
|
+
return d(Buffer.from(raw).toString(), field);
|
|
5647
5710
|
} catch {
|
|
5711
|
+
console.warn(
|
|
5712
|
+
`Stored token for '${field}' appears corrupted. It will be re-requested.`
|
|
5713
|
+
);
|
|
5648
5714
|
return null;
|
|
5649
5715
|
}
|
|
5650
5716
|
}
|
|
@@ -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) {
|
|
@@ -5802,9 +5877,7 @@ var _JsrClient = class _JsrClient {
|
|
|
5802
5877
|
const response = await this.fetch("/user");
|
|
5803
5878
|
if (response.status === 401) return null;
|
|
5804
5879
|
if (!response.ok) {
|
|
5805
|
-
throw new Error(
|
|
5806
|
-
`HTTP ${response.status}: ${response.statusText}`
|
|
5807
|
-
);
|
|
5880
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
5808
5881
|
}
|
|
5809
5882
|
return await response.json();
|
|
5810
5883
|
} catch (error) {
|
|
@@ -5818,9 +5891,7 @@ var _JsrClient = class _JsrClient {
|
|
|
5818
5891
|
const response = await this.fetch(`/user/member/${scope}`);
|
|
5819
5892
|
if (response.status === 401) return null;
|
|
5820
5893
|
if (!response.ok) {
|
|
5821
|
-
throw new Error(
|
|
5822
|
-
`HTTP ${response.status}: ${response.statusText}`
|
|
5823
|
-
);
|
|
5894
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
5824
5895
|
}
|
|
5825
5896
|
return await response.json();
|
|
5826
5897
|
} catch (error) {
|
|
@@ -5837,15 +5908,11 @@ var _JsrClient = class _JsrClient {
|
|
|
5837
5908
|
const response = await this.fetch("/user/scopes");
|
|
5838
5909
|
if (response.status === 401) return [];
|
|
5839
5910
|
if (!response.ok) {
|
|
5840
|
-
throw new Error(
|
|
5841
|
-
`HTTP ${response.status}: ${response.statusText}`
|
|
5842
|
-
);
|
|
5911
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
5843
5912
|
}
|
|
5844
5913
|
const body = await response.json();
|
|
5845
5914
|
if (!Array.isArray(body)) {
|
|
5846
|
-
throw new Error(
|
|
5847
|
-
`Expected array response but got ${typeof body}`
|
|
5848
|
-
);
|
|
5915
|
+
throw new Error(`Expected array response but got ${typeof body}`);
|
|
5849
5916
|
}
|
|
5850
5917
|
return body.map(({ scope }) => scope);
|
|
5851
5918
|
} catch (error) {
|
|
@@ -5861,9 +5928,15 @@ var _JsrClient = class _JsrClient {
|
|
|
5861
5928
|
const [scope, name] = getScopeAndName(packageName);
|
|
5862
5929
|
try {
|
|
5863
5930
|
const response = await this.fetch(`/scopes/${scope}/packages/${name}`);
|
|
5864
|
-
if (
|
|
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
|
+
}
|
|
5865
5937
|
return await response.json();
|
|
5866
5938
|
} catch (error) {
|
|
5939
|
+
if (error instanceof JsrError) throw error;
|
|
5867
5940
|
throw new JsrError(
|
|
5868
5941
|
`Failed to fetch \`${this.apiEndpoint}/scopes/${scope}/packages/${name}\``,
|
|
5869
5942
|
{
|
|
@@ -5878,8 +5951,18 @@ var _JsrClient = class _JsrClient {
|
|
|
5878
5951
|
method: "POST",
|
|
5879
5952
|
body: JSON.stringify({ scope })
|
|
5880
5953
|
});
|
|
5881
|
-
|
|
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
|
+
);
|
|
5882
5964
|
} catch (error) {
|
|
5965
|
+
if (error instanceof JsrError) throw error;
|
|
5883
5966
|
throw new JsrError(`Failed to fetch \`${this.apiEndpoint}/scopes\``, {
|
|
5884
5967
|
cause: error
|
|
5885
5968
|
});
|
|
@@ -5890,8 +5973,18 @@ var _JsrClient = class _JsrClient {
|
|
|
5890
5973
|
const response = await this.fetch(`/scopes/${scope}`, {
|
|
5891
5974
|
method: "DELETE"
|
|
5892
5975
|
});
|
|
5893
|
-
|
|
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
|
+
);
|
|
5894
5986
|
} catch (error) {
|
|
5987
|
+
if (error instanceof JsrError) throw error;
|
|
5895
5988
|
throw new JsrError(
|
|
5896
5989
|
`Failed to fetch \`${this.apiEndpoint}/scopes/${scope}\``,
|
|
5897
5990
|
{
|
|
@@ -5907,8 +6000,18 @@ var _JsrClient = class _JsrClient {
|
|
|
5907
6000
|
method: "POST",
|
|
5908
6001
|
body: JSON.stringify({ package: name })
|
|
5909
6002
|
});
|
|
5910
|
-
|
|
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
|
+
);
|
|
5911
6013
|
} catch (error) {
|
|
6014
|
+
if (error instanceof JsrError) throw error;
|
|
5912
6015
|
throw new JsrError(
|
|
5913
6016
|
`Failed to fetch \`${this.apiEndpoint}/scopes/${scope}/packages\``,
|
|
5914
6017
|
{
|
|
@@ -5923,8 +6026,18 @@ var _JsrClient = class _JsrClient {
|
|
|
5923
6026
|
const response = await this.fetch(`/scopes/${scope}/packages/${name}`, {
|
|
5924
6027
|
method: "DELETE"
|
|
5925
6028
|
});
|
|
5926
|
-
|
|
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
|
+
);
|
|
5927
6039
|
} catch (error) {
|
|
6040
|
+
if (error instanceof JsrError) throw error;
|
|
5928
6041
|
throw new JsrError(
|
|
5929
6042
|
`Failed to fetch \`${this.apiEndpoint}/scopes/${scope}/packages/${name}\``,
|
|
5930
6043
|
{
|
|
@@ -5937,9 +6050,7 @@ var _JsrClient = class _JsrClient {
|
|
|
5937
6050
|
try {
|
|
5938
6051
|
const response = await this.fetch(`/packages?query=${query}`);
|
|
5939
6052
|
if (!response.ok) {
|
|
5940
|
-
throw new Error(
|
|
5941
|
-
`HTTP ${response.status}: ${response.statusText}`
|
|
5942
|
-
);
|
|
6053
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
5943
6054
|
}
|
|
5944
6055
|
return await response.json();
|
|
5945
6056
|
} catch (error) {
|
|
@@ -6017,7 +6128,7 @@ var NpmRegistry = class extends Registry {
|
|
|
6017
6128
|
await this.npm(["whoami"]);
|
|
6018
6129
|
return true;
|
|
6019
6130
|
} catch (error) {
|
|
6020
|
-
if (error instanceof NonZeroExitError2
|
|
6131
|
+
if (error instanceof NonZeroExitError2) {
|
|
6021
6132
|
return false;
|
|
6022
6133
|
}
|
|
6023
6134
|
throw new NpmError("Failed to run `npm whoami`", { cause: error });
|
|
@@ -6025,16 +6136,22 @@ var NpmRegistry = class extends Registry {
|
|
|
6025
6136
|
}
|
|
6026
6137
|
async collaborators() {
|
|
6027
6138
|
try {
|
|
6028
|
-
|
|
6029
|
-
|
|
6030
|
-
|
|
6031
|
-
|
|
6032
|
-
|
|
6033
|
-
|
|
6034
|
-
|
|
6035
|
-
|
|
6036
|
-
|
|
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
|
+
}
|
|
6037
6153
|
} catch (error) {
|
|
6154
|
+
if (error instanceof NpmError) throw error;
|
|
6038
6155
|
throw new NpmError(
|
|
6039
6156
|
`Failed to run \`npm access list collaborators ${this.packageName} --json\``,
|
|
6040
6157
|
{ cause: error }
|
|
@@ -6048,12 +6165,21 @@ var NpmRegistry = class extends Registry {
|
|
|
6048
6165
|
}
|
|
6049
6166
|
async distTags() {
|
|
6050
6167
|
try {
|
|
6051
|
-
|
|
6052
|
-
|
|
6053
|
-
|
|
6054
|
-
|
|
6055
|
-
|
|
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
|
+
}
|
|
6056
6181
|
} catch (error) {
|
|
6182
|
+
if (error instanceof NpmError) throw error;
|
|
6057
6183
|
throw new NpmError(
|
|
6058
6184
|
`Failed to run \`npm view ${this.packageName} dist-tags --json\``,
|
|
6059
6185
|
{ cause: error }
|
|
@@ -6083,12 +6209,7 @@ var NpmRegistry = class extends Registry {
|
|
|
6083
6209
|
if (error instanceof NonZeroExitError2 && error.output?.stderr.includes("EOTP")) {
|
|
6084
6210
|
return false;
|
|
6085
6211
|
}
|
|
6086
|
-
throw
|
|
6087
|
-
"Failed to run `npm publish --provenance --access public`",
|
|
6088
|
-
{
|
|
6089
|
-
cause: error
|
|
6090
|
-
}
|
|
6091
|
-
);
|
|
6212
|
+
throw this.classifyPublishError(error);
|
|
6092
6213
|
}
|
|
6093
6214
|
}
|
|
6094
6215
|
async publish(otp) {
|
|
@@ -6100,14 +6221,39 @@ var NpmRegistry = class extends Registry {
|
|
|
6100
6221
|
if (error instanceof NonZeroExitError2 && error.output?.stderr.includes("EOTP")) {
|
|
6101
6222
|
return false;
|
|
6102
6223
|
}
|
|
6103
|
-
throw
|
|
6104
|
-
cause: error
|
|
6105
|
-
});
|
|
6224
|
+
throw this.classifyPublishError(error);
|
|
6106
6225
|
}
|
|
6107
6226
|
}
|
|
6108
6227
|
async isPackageNameAvaliable() {
|
|
6109
6228
|
return isValidPackageName(this.packageName);
|
|
6110
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
|
+
}
|
|
6111
6257
|
};
|
|
6112
6258
|
async function npmRegistry() {
|
|
6113
6259
|
const packageJson = await getPackageJson();
|
|
@@ -6139,17 +6285,34 @@ var jsrAvailableCheckTasks = {
|
|
|
6139
6285
|
if (!JsrClient.token) {
|
|
6140
6286
|
task.output = "Retrieving jsr API token";
|
|
6141
6287
|
if (ctx.promptEnabled) {
|
|
6142
|
-
|
|
6288
|
+
const maxAttempts = 3;
|
|
6289
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
6143
6290
|
JsrClient.token = await task.prompt(ListrEnquirerPromptAdapter).run({
|
|
6144
6291
|
type: "password",
|
|
6145
|
-
message: `Please enter the jsr ${color.bold("API token")}`,
|
|
6292
|
+
message: `Please enter the jsr ${color.bold("API token")}${attempt > 1 ? ` (attempt ${attempt}/${maxAttempts})` : ""}`,
|
|
6146
6293
|
footer: `
|
|
6147
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'")}.`
|
|
6148
6295
|
});
|
|
6149
6296
|
try {
|
|
6150
6297
|
if (await jsr.client.user()) break;
|
|
6151
|
-
|
|
6152
|
-
|
|
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
|
+
);
|
|
6153
6316
|
}
|
|
6154
6317
|
}
|
|
6155
6318
|
} else {
|
|
@@ -6283,8 +6446,11 @@ var jsrPublishTasks = {
|
|
|
6283
6446
|
};
|
|
6284
6447
|
|
|
6285
6448
|
// src/tasks/npm.ts
|
|
6449
|
+
import { spawn } from "node:child_process";
|
|
6286
6450
|
import process13 from "node:process";
|
|
6287
6451
|
import { ListrEnquirerPromptAdapter as ListrEnquirerPromptAdapter2 } from "@listr2/prompt-adapter-enquirer";
|
|
6452
|
+
import npmCli from "@npmcli/promise-spawn";
|
|
6453
|
+
var { open } = npmCli;
|
|
6288
6454
|
var NpmAvailableError = class extends AbstractError {
|
|
6289
6455
|
constructor(message, { cause } = {}) {
|
|
6290
6456
|
super(message, { cause });
|
|
@@ -6295,12 +6461,55 @@ var NpmAvailableError = class extends AbstractError {
|
|
|
6295
6461
|
var npmAvailableCheckTasks = {
|
|
6296
6462
|
title: "Checking npm avaliable for publising",
|
|
6297
6463
|
skip: (ctx) => !!ctx.preview,
|
|
6298
|
-
task: async () => {
|
|
6464
|
+
task: async (ctx, task) => {
|
|
6299
6465
|
const npm = await npmRegistry();
|
|
6300
6466
|
if (!await npm.isLoggedIn()) {
|
|
6301
|
-
|
|
6302
|
-
|
|
6303
|
-
|
|
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
|
+
}
|
|
6304
6513
|
}
|
|
6305
6514
|
if (await npm.isPublished()) {
|
|
6306
6515
|
if (!await npm.hasPermission()) {
|
|
@@ -6328,24 +6537,31 @@ var npmPublishTasks = {
|
|
|
6328
6537
|
let result = await npm.publish();
|
|
6329
6538
|
if (!result) {
|
|
6330
6539
|
task.title = "Running npm publish (OTP code needed)";
|
|
6331
|
-
|
|
6540
|
+
const maxAttempts = 3;
|
|
6541
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
6332
6542
|
result = await npm.publish(
|
|
6333
6543
|
await task.prompt(ListrEnquirerPromptAdapter2).run({
|
|
6334
6544
|
type: "password",
|
|
6335
|
-
message:
|
|
6545
|
+
message: `npm OTP code${attempt > 1 ? ` (attempt ${attempt}/${maxAttempts})` : ""}`
|
|
6336
6546
|
})
|
|
6337
6547
|
);
|
|
6338
|
-
if (
|
|
6339
|
-
|
|
6548
|
+
if (result) break;
|
|
6549
|
+
if (attempt < maxAttempts) {
|
|
6550
|
+
task.output = "2FA failed. Please try again.";
|
|
6340
6551
|
}
|
|
6341
6552
|
}
|
|
6553
|
+
if (!result) {
|
|
6554
|
+
throw new NpmAvailableError(
|
|
6555
|
+
"OTP verification failed after 3 attempts."
|
|
6556
|
+
);
|
|
6557
|
+
}
|
|
6342
6558
|
task.title = "Running npm publish (2FA passed)";
|
|
6343
6559
|
}
|
|
6344
6560
|
} else {
|
|
6345
6561
|
const npmTokenEnv = process13.env.NODE_AUTH_TOKEN;
|
|
6346
6562
|
if (!npmTokenEnv) {
|
|
6347
6563
|
throw new NpmAvailableError(
|
|
6348
|
-
"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"
|
|
6349
6565
|
);
|
|
6350
6566
|
}
|
|
6351
6567
|
const result = await npm.publishProvenance();
|
|
@@ -6451,6 +6667,7 @@ var prerequisitesCheckTask = (options) => {
|
|
|
6451
6667
|
);
|
|
6452
6668
|
}
|
|
6453
6669
|
ctx.cleanWorkingTree = false;
|
|
6670
|
+
return;
|
|
6454
6671
|
}
|
|
6455
6672
|
ctx.cleanWorkingTree = true;
|
|
6456
6673
|
}
|
|
@@ -6551,6 +6768,16 @@ async function validateEngineVersion(engine, version2) {
|
|
|
6551
6768
|
}
|
|
6552
6769
|
|
|
6553
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
|
+
}
|
|
6554
6781
|
var RequiredConditionCheckError = class extends AbstractError {
|
|
6555
6782
|
constructor(message, { cause } = {}) {
|
|
6556
6783
|
super(message, { cause });
|
|
@@ -6626,7 +6853,7 @@ var requiredConditionsCheckTask = (options) => createListr({
|
|
|
6626
6853
|
},
|
|
6627
6854
|
{
|
|
6628
6855
|
title: "Checking if test and build scripts exist",
|
|
6629
|
-
skip: (ctx) => ctx.
|
|
6856
|
+
skip: (ctx) => !needsPackageScripts(ctx.registries),
|
|
6630
6857
|
task: async (ctx) => {
|
|
6631
6858
|
const { scripts } = await getPackageJson();
|
|
6632
6859
|
const errors = [];
|
|
@@ -6680,14 +6907,12 @@ var requiredConditionsCheckTask = (options) => createListr({
|
|
|
6680
6907
|
});
|
|
6681
6908
|
|
|
6682
6909
|
// src/tasks/runner.ts
|
|
6683
|
-
var { open } =
|
|
6910
|
+
var { open: open2 } = npmCli2;
|
|
6684
6911
|
var { prerelease } = SemVer;
|
|
6685
6912
|
async function run(options) {
|
|
6686
6913
|
const ctx = {
|
|
6687
6914
|
...options,
|
|
6688
|
-
promptEnabled: !isCI2 && process14.stdin.isTTY
|
|
6689
|
-
npmOnly: options.registries.every((registry) => registry !== "jsr"),
|
|
6690
|
-
jsrOnly: options.registries.every((registry) => registry === "jsr")
|
|
6915
|
+
promptEnabled: !isCI2 && process14.stdin.isTTY
|
|
6691
6916
|
};
|
|
6692
6917
|
try {
|
|
6693
6918
|
if (options.contents) process14.chdir(options.contents);
|
|
@@ -6723,9 +6948,16 @@ async function run(options) {
|
|
|
6723
6948
|
title: "Running tests",
|
|
6724
6949
|
task: async (ctx2) => {
|
|
6725
6950
|
const packageManager = await getPackageManager();
|
|
6726
|
-
|
|
6727
|
-
|
|
6728
|
-
|
|
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
|
+
}
|
|
6729
6961
|
}
|
|
6730
6962
|
},
|
|
6731
6963
|
{
|
|
@@ -6739,7 +6971,7 @@ async function run(options) {
|
|
|
6739
6971
|
});
|
|
6740
6972
|
} catch (error) {
|
|
6741
6973
|
throw new AbstractError(
|
|
6742
|
-
`
|
|
6974
|
+
`Build script '${ctx2.buildScript}' failed. Run \`${packageManager} run ${ctx2.buildScript}\` locally to see full output.`,
|
|
6743
6975
|
{ cause: error }
|
|
6744
6976
|
);
|
|
6745
6977
|
}
|
|
@@ -6754,15 +6986,27 @@ async function run(options) {
|
|
|
6754
6986
|
let commited = false;
|
|
6755
6987
|
addRollback(async () => {
|
|
6756
6988
|
if (tagCreated) {
|
|
6757
|
-
|
|
6758
|
-
|
|
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
|
+
}
|
|
6759
6997
|
}
|
|
6760
6998
|
if (commited) {
|
|
6761
|
-
|
|
6762
|
-
|
|
6763
|
-
|
|
6764
|
-
|
|
6765
|
-
|
|
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
|
+
}
|
|
6766
7010
|
}
|
|
6767
7011
|
}, ctx2);
|
|
6768
7012
|
await git.reset();
|
|
@@ -6835,7 +7079,7 @@ ${repositoryUrl}/compare/${lastRev}...${latestTag}`;
|
|
|
6835
7079
|
);
|
|
6836
7080
|
const linkUrl = link2("Link", releaseDraftUrl.toString());
|
|
6837
7081
|
task.title += ` ${linkUrl}`;
|
|
6838
|
-
await
|
|
7082
|
+
await open2(releaseDraftUrl.toString());
|
|
6839
7083
|
}
|
|
6840
7084
|
}
|
|
6841
7085
|
]
|
|
@@ -6863,7 +7107,9 @@ import { inc } from "semver";
|
|
|
6863
7107
|
import { stat as stat3 } from "node:fs/promises";
|
|
6864
7108
|
import path9 from "node:path";
|
|
6865
7109
|
|
|
6866
|
-
// 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";
|
|
6867
7113
|
import micromatch from "micromatch";
|
|
6868
7114
|
|
|
6869
7115
|
// src/monorepo/workspace.ts
|
|
@@ -6871,12 +7117,15 @@ import { existsSync as existsSync5, readFileSync as readFileSync4 } from "node:f
|
|
|
6871
7117
|
import { join } from "node:path";
|
|
6872
7118
|
import { parse as parse2 } from "yaml";
|
|
6873
7119
|
|
|
7120
|
+
// src/monorepo/groups.ts
|
|
7121
|
+
import micromatch2 from "micromatch";
|
|
7122
|
+
|
|
6874
7123
|
// src/validate/entry-points.ts
|
|
6875
|
-
import { existsSync as
|
|
6876
|
-
import
|
|
7124
|
+
import { existsSync as existsSync7 } from "node:fs";
|
|
7125
|
+
import path11 from "node:path";
|
|
6877
7126
|
|
|
6878
7127
|
// src/validate/extraneous-files.ts
|
|
6879
|
-
import
|
|
7128
|
+
import micromatch3 from "micromatch";
|
|
6880
7129
|
|
|
6881
7130
|
// src/index.ts
|
|
6882
7131
|
async function pubm(options) {
|
|
@@ -7121,6 +7370,7 @@ defaultCmd.action(
|
|
|
7121
7370
|
);
|
|
7122
7371
|
} catch (e2) {
|
|
7123
7372
|
consoleError(e2);
|
|
7373
|
+
process.exitCode = 1;
|
|
7124
7374
|
}
|
|
7125
7375
|
}
|
|
7126
7376
|
);
|