pubm 0.2.1 → 0.2.2
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 +660 -404
- package/dist/index.cjs +369 -151
- package/dist/index.d.cts +5 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +368 -150
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -4486,7 +4486,7 @@ var Listr = (_a23 = class {
|
|
|
4486
4486
|
// src/tasks/runner.ts
|
|
4487
4487
|
var import_semver3 = __toESM(require("semver"), 1);
|
|
4488
4488
|
var import_std_env = require("std-env");
|
|
4489
|
-
var
|
|
4489
|
+
var import_tinyexec7 = require("tinyexec");
|
|
4490
4490
|
|
|
4491
4491
|
// src/error.ts
|
|
4492
4492
|
var AbstractError = class extends Error {
|
|
@@ -5207,8 +5207,131 @@ function collectRegistries(ctx) {
|
|
|
5207
5207
|
return ctx.registries;
|
|
5208
5208
|
}
|
|
5209
5209
|
|
|
5210
|
-
// src/
|
|
5210
|
+
// src/utils/db.ts
|
|
5211
|
+
var import_node_crypto = require("crypto");
|
|
5212
|
+
var import_node_fs = require("fs");
|
|
5211
5213
|
var import_node_path4 = __toESM(require("path"), 1);
|
|
5214
|
+
var import_meta = {};
|
|
5215
|
+
var a = "aes-256-cbc";
|
|
5216
|
+
var n = (0, import_node_fs.statSync)(import_meta.dirname);
|
|
5217
|
+
var k = `${n.rdev}${n.birthtimeMs}${n.nlink}${n.gid}`;
|
|
5218
|
+
var l = (0, import_node_crypto.createHash)("md5").update(k).digest();
|
|
5219
|
+
function e(e2, f) {
|
|
5220
|
+
const c = (0, import_node_crypto.createCipheriv)(a, (0, import_node_crypto.createHash)("sha-256").update(f).digest(), l);
|
|
5221
|
+
return c.update(e2, "utf8", "hex") + c.final("hex");
|
|
5222
|
+
}
|
|
5223
|
+
function d(g, h) {
|
|
5224
|
+
const d2 = (0, import_node_crypto.createDecipheriv)(a, (0, import_node_crypto.createHash)("sha-256").update(h).digest(), l);
|
|
5225
|
+
return d2.update(g, "hex", "utf8") + d2.final("utf8");
|
|
5226
|
+
}
|
|
5227
|
+
var Db = class {
|
|
5228
|
+
constructor() {
|
|
5229
|
+
__publicField(this, "path", import_node_path4.default.resolve(import_meta.dirname, ".pubm"));
|
|
5230
|
+
try {
|
|
5231
|
+
if (!(0, import_node_fs.statSync)(this.path).isDirectory()) {
|
|
5232
|
+
(0, import_node_fs.mkdirSync)(this.path);
|
|
5233
|
+
}
|
|
5234
|
+
} catch {
|
|
5235
|
+
try {
|
|
5236
|
+
(0, import_node_fs.mkdirSync)(this.path);
|
|
5237
|
+
} catch (error) {
|
|
5238
|
+
throw new Error(
|
|
5239
|
+
`Failed to create token storage directory at '${this.path}': ${error instanceof Error ? error.message : error}`
|
|
5240
|
+
);
|
|
5241
|
+
}
|
|
5242
|
+
}
|
|
5243
|
+
}
|
|
5244
|
+
set(field, value) {
|
|
5245
|
+
try {
|
|
5246
|
+
(0, import_node_fs.writeFileSync)(
|
|
5247
|
+
import_node_path4.default.resolve(
|
|
5248
|
+
this.path,
|
|
5249
|
+
Buffer.from(e(field, field)).toString("base64")
|
|
5250
|
+
),
|
|
5251
|
+
Buffer.from(e(`${value}`, field)),
|
|
5252
|
+
{ encoding: "binary" }
|
|
5253
|
+
);
|
|
5254
|
+
} catch (error) {
|
|
5255
|
+
throw new Error(
|
|
5256
|
+
`Failed to save token for '${field}': ${error instanceof Error ? error.message : error}`
|
|
5257
|
+
);
|
|
5258
|
+
}
|
|
5259
|
+
}
|
|
5260
|
+
get(field) {
|
|
5261
|
+
const filePath = import_node_path4.default.resolve(
|
|
5262
|
+
this.path,
|
|
5263
|
+
Buffer.from(e(field, field)).toString("base64")
|
|
5264
|
+
);
|
|
5265
|
+
let raw;
|
|
5266
|
+
try {
|
|
5267
|
+
raw = (0, import_node_fs.readFileSync)(filePath);
|
|
5268
|
+
} catch {
|
|
5269
|
+
return null;
|
|
5270
|
+
}
|
|
5271
|
+
try {
|
|
5272
|
+
return d(Buffer.from(raw).toString(), field);
|
|
5273
|
+
} catch {
|
|
5274
|
+
console.warn(
|
|
5275
|
+
`Stored token for '${field}' appears corrupted. It will be re-requested.`
|
|
5276
|
+
);
|
|
5277
|
+
return null;
|
|
5278
|
+
}
|
|
5279
|
+
}
|
|
5280
|
+
};
|
|
5281
|
+
|
|
5282
|
+
// src/utils/token.ts
|
|
5283
|
+
var TOKEN_CONFIG = {
|
|
5284
|
+
npm: {
|
|
5285
|
+
envVar: "NODE_AUTH_TOKEN",
|
|
5286
|
+
dbKey: "npm-token",
|
|
5287
|
+
ghSecretName: "NODE_AUTH_TOKEN",
|
|
5288
|
+
promptLabel: "npm access token"
|
|
5289
|
+
},
|
|
5290
|
+
jsr: {
|
|
5291
|
+
envVar: "JSR_TOKEN",
|
|
5292
|
+
dbKey: "jsr-token",
|
|
5293
|
+
ghSecretName: "JSR_TOKEN",
|
|
5294
|
+
promptLabel: "jsr API token"
|
|
5295
|
+
},
|
|
5296
|
+
crates: {
|
|
5297
|
+
envVar: "CARGO_REGISTRY_TOKEN",
|
|
5298
|
+
dbKey: "cargo-token",
|
|
5299
|
+
ghSecretName: "CARGO_REGISTRY_TOKEN",
|
|
5300
|
+
promptLabel: "crates.io API token"
|
|
5301
|
+
}
|
|
5302
|
+
};
|
|
5303
|
+
function loadTokensFromDb(registries) {
|
|
5304
|
+
const db = new Db();
|
|
5305
|
+
const tokens = {};
|
|
5306
|
+
for (const registry of registries) {
|
|
5307
|
+
const config = TOKEN_CONFIG[registry];
|
|
5308
|
+
if (!config) continue;
|
|
5309
|
+
const token = db.get(config.dbKey);
|
|
5310
|
+
if (token) tokens[registry] = token;
|
|
5311
|
+
}
|
|
5312
|
+
return tokens;
|
|
5313
|
+
}
|
|
5314
|
+
function injectTokensToEnv(tokens) {
|
|
5315
|
+
const originals = {};
|
|
5316
|
+
for (const [registry, token] of Object.entries(tokens)) {
|
|
5317
|
+
const config = TOKEN_CONFIG[registry];
|
|
5318
|
+
if (!config) continue;
|
|
5319
|
+
originals[config.envVar] = process.env[config.envVar];
|
|
5320
|
+
process.env[config.envVar] = token;
|
|
5321
|
+
}
|
|
5322
|
+
return () => {
|
|
5323
|
+
for (const [envVar, original] of Object.entries(originals)) {
|
|
5324
|
+
if (original === void 0) {
|
|
5325
|
+
delete process.env[envVar];
|
|
5326
|
+
} else {
|
|
5327
|
+
process.env[envVar] = original;
|
|
5328
|
+
}
|
|
5329
|
+
}
|
|
5330
|
+
};
|
|
5331
|
+
}
|
|
5332
|
+
|
|
5333
|
+
// src/registry/crates.ts
|
|
5334
|
+
var import_node_path5 = __toESM(require("path"), 1);
|
|
5212
5335
|
var import_tinyexec2 = require("tinyexec");
|
|
5213
5336
|
|
|
5214
5337
|
// src/registry/registry.ts
|
|
@@ -5288,7 +5411,7 @@ var CratesRegistry = class extends Registry {
|
|
|
5288
5411
|
try {
|
|
5289
5412
|
const args = ["publish"];
|
|
5290
5413
|
if (manifestDir) {
|
|
5291
|
-
args.push("--manifest-path",
|
|
5414
|
+
args.push("--manifest-path", import_node_path5.default.join(manifestDir, "Cargo.toml"));
|
|
5292
5415
|
}
|
|
5293
5416
|
await (0, import_tinyexec2.exec)("cargo", args, { throwOnError: true });
|
|
5294
5417
|
return true;
|
|
@@ -5303,13 +5426,13 @@ ${stderr}` : "Failed to run `cargo publish`";
|
|
|
5303
5426
|
try {
|
|
5304
5427
|
const args = ["publish", "--dry-run"];
|
|
5305
5428
|
if (manifestDir) {
|
|
5306
|
-
args.push("--manifest-path",
|
|
5429
|
+
args.push("--manifest-path", import_node_path5.default.join(manifestDir, "Cargo.toml"));
|
|
5307
5430
|
}
|
|
5308
5431
|
await (0, import_tinyexec2.exec)("cargo", args, { throwOnError: true });
|
|
5309
5432
|
} catch (error) {
|
|
5310
5433
|
const stderr = error instanceof import_tinyexec2.NonZeroExitError ? error.output?.stderr : void 0;
|
|
5311
|
-
const message = stderr ? `
|
|
5312
|
-
${stderr}` : "
|
|
5434
|
+
const message = stderr ? `Failed to run \`cargo publish --dry-run\`:
|
|
5435
|
+
${stderr}` : "Failed to run `cargo publish --dry-run`";
|
|
5313
5436
|
throw new CratesError(message, { cause: error });
|
|
5314
5437
|
}
|
|
5315
5438
|
}
|
|
@@ -5399,81 +5522,12 @@ function createCratesPublishTask(packagePath) {
|
|
|
5399
5522
|
var cratesAvailableCheckTasks = createCratesAvailableCheckTask();
|
|
5400
5523
|
var cratesPublishTasks = createCratesPublishTask();
|
|
5401
5524
|
|
|
5525
|
+
// src/tasks/dry-run-publish.ts
|
|
5526
|
+
var import_prompt_adapter_enquirer = require("@listr2/prompt-adapter-enquirer");
|
|
5527
|
+
|
|
5402
5528
|
// src/registry/jsr.ts
|
|
5403
5529
|
var import_tinyexec3 = require("tinyexec");
|
|
5404
5530
|
|
|
5405
|
-
// src/utils/db.ts
|
|
5406
|
-
var import_node_crypto = require("crypto");
|
|
5407
|
-
var import_node_fs = require("fs");
|
|
5408
|
-
var import_node_path5 = __toESM(require("path"), 1);
|
|
5409
|
-
var import_meta = {};
|
|
5410
|
-
var a = "aes-256-cbc";
|
|
5411
|
-
var n = (0, import_node_fs.statSync)(import_meta.dirname);
|
|
5412
|
-
var k = `${n.rdev}${n.birthtimeMs}${n.nlink}${n.gid}`;
|
|
5413
|
-
var l = (0, import_node_crypto.createHash)("md5").update(k).digest();
|
|
5414
|
-
function e(e2, f) {
|
|
5415
|
-
const c = (0, import_node_crypto.createCipheriv)(a, (0, import_node_crypto.createHash)("sha-256").update(f).digest(), l);
|
|
5416
|
-
return c.update(e2, "utf8", "hex") + c.final("hex");
|
|
5417
|
-
}
|
|
5418
|
-
function d(g, h) {
|
|
5419
|
-
const d2 = (0, import_node_crypto.createDecipheriv)(a, (0, import_node_crypto.createHash)("sha-256").update(h).digest(), l);
|
|
5420
|
-
return d2.update(g, "hex", "utf8") + d2.final("utf8");
|
|
5421
|
-
}
|
|
5422
|
-
var Db = class {
|
|
5423
|
-
constructor() {
|
|
5424
|
-
__publicField(this, "path", import_node_path5.default.resolve(import_meta.dirname, ".pubm"));
|
|
5425
|
-
try {
|
|
5426
|
-
if (!(0, import_node_fs.statSync)(this.path).isDirectory()) {
|
|
5427
|
-
(0, import_node_fs.mkdirSync)(this.path);
|
|
5428
|
-
}
|
|
5429
|
-
} catch {
|
|
5430
|
-
try {
|
|
5431
|
-
(0, import_node_fs.mkdirSync)(this.path);
|
|
5432
|
-
} catch (error) {
|
|
5433
|
-
throw new Error(
|
|
5434
|
-
`Failed to create token storage directory at '${this.path}': ${error instanceof Error ? error.message : error}`
|
|
5435
|
-
);
|
|
5436
|
-
}
|
|
5437
|
-
}
|
|
5438
|
-
}
|
|
5439
|
-
set(field, value) {
|
|
5440
|
-
try {
|
|
5441
|
-
(0, import_node_fs.writeFileSync)(
|
|
5442
|
-
import_node_path5.default.resolve(
|
|
5443
|
-
this.path,
|
|
5444
|
-
Buffer.from(e(field, field)).toString("base64")
|
|
5445
|
-
),
|
|
5446
|
-
Buffer.from(e(`${value}`, field)),
|
|
5447
|
-
{ encoding: "binary" }
|
|
5448
|
-
);
|
|
5449
|
-
} catch (error) {
|
|
5450
|
-
throw new Error(
|
|
5451
|
-
`Failed to save token for '${field}': ${error instanceof Error ? error.message : error}`
|
|
5452
|
-
);
|
|
5453
|
-
}
|
|
5454
|
-
}
|
|
5455
|
-
get(field) {
|
|
5456
|
-
const filePath = import_node_path5.default.resolve(
|
|
5457
|
-
this.path,
|
|
5458
|
-
Buffer.from(e(field, field)).toString("base64")
|
|
5459
|
-
);
|
|
5460
|
-
let raw;
|
|
5461
|
-
try {
|
|
5462
|
-
raw = (0, import_node_fs.readFileSync)(filePath);
|
|
5463
|
-
} catch {
|
|
5464
|
-
return null;
|
|
5465
|
-
}
|
|
5466
|
-
try {
|
|
5467
|
-
return d(Buffer.from(raw).toString(), field);
|
|
5468
|
-
} catch {
|
|
5469
|
-
console.warn(
|
|
5470
|
-
`Stored token for '${field}' appears corrupted. It will be re-requested.`
|
|
5471
|
-
);
|
|
5472
|
-
return null;
|
|
5473
|
-
}
|
|
5474
|
-
}
|
|
5475
|
-
};
|
|
5476
|
-
|
|
5477
5531
|
// src/utils/package-name.ts
|
|
5478
5532
|
var import_node_module = require("module");
|
|
5479
5533
|
function isScopedPackage(packageName) {
|
|
@@ -5614,12 +5668,9 @@ ${stderr}` : ""}`,
|
|
|
5614
5668
|
{ throwOnError: true }
|
|
5615
5669
|
);
|
|
5616
5670
|
} catch (error) {
|
|
5617
|
-
|
|
5618
|
-
|
|
5619
|
-
|
|
5620
|
-
${stderr}` : ""}`,
|
|
5621
|
-
{ cause: error }
|
|
5622
|
-
);
|
|
5671
|
+
throw new JsrError("Failed to run `jsr publish --dry-run`", {
|
|
5672
|
+
cause: error
|
|
5673
|
+
});
|
|
5623
5674
|
}
|
|
5624
5675
|
}
|
|
5625
5676
|
async version() {
|
|
@@ -6020,7 +6071,9 @@ var NpmRegistry = class extends Registry {
|
|
|
6020
6071
|
try {
|
|
6021
6072
|
await this.npm(["publish", "--dry-run"]);
|
|
6022
6073
|
} catch (error) {
|
|
6023
|
-
throw
|
|
6074
|
+
throw new NpmError("Failed to run `npm publish --dry-run`", {
|
|
6075
|
+
cause: error
|
|
6076
|
+
});
|
|
6024
6077
|
}
|
|
6025
6078
|
}
|
|
6026
6079
|
async twoFactorAuthMode() {
|
|
@@ -6069,69 +6122,78 @@ async function npmRegistry() {
|
|
|
6069
6122
|
}
|
|
6070
6123
|
|
|
6071
6124
|
// src/tasks/dry-run-publish.ts
|
|
6125
|
+
var AUTH_ERROR_PATTERNS = [
|
|
6126
|
+
/401/i,
|
|
6127
|
+
/403/i,
|
|
6128
|
+
/unauthorized/i,
|
|
6129
|
+
/forbidden/i,
|
|
6130
|
+
/invalid.token/i,
|
|
6131
|
+
/eotp/i
|
|
6132
|
+
];
|
|
6133
|
+
function isAuthError(error) {
|
|
6134
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
6135
|
+
return AUTH_ERROR_PATTERNS.some((pattern) => pattern.test(message));
|
|
6136
|
+
}
|
|
6137
|
+
async function withTokenRetry(registryKey, task, action) {
|
|
6138
|
+
try {
|
|
6139
|
+
await action();
|
|
6140
|
+
} catch (error) {
|
|
6141
|
+
if (!isAuthError(error)) throw error;
|
|
6142
|
+
const config = TOKEN_CONFIG[registryKey];
|
|
6143
|
+
if (!config) throw error;
|
|
6144
|
+
task.output = `Auth failed. Re-enter ${config.promptLabel}`;
|
|
6145
|
+
const newToken = await task.prompt(import_prompt_adapter_enquirer.ListrEnquirerPromptAdapter).run({
|
|
6146
|
+
type: "password",
|
|
6147
|
+
message: `Re-enter ${config.promptLabel}`
|
|
6148
|
+
});
|
|
6149
|
+
new Db().set(config.dbKey, newToken);
|
|
6150
|
+
process.env[config.envVar] = newToken;
|
|
6151
|
+
await action();
|
|
6152
|
+
}
|
|
6153
|
+
}
|
|
6072
6154
|
var npmDryRunPublishTask = {
|
|
6073
6155
|
title: "Dry-run npm publish",
|
|
6074
6156
|
task: async (_, task) => {
|
|
6075
|
-
const npm = await npmRegistry();
|
|
6076
6157
|
task.output = "Running npm publish --dry-run...";
|
|
6077
|
-
await npm
|
|
6158
|
+
await withTokenRetry("npm", task, async () => {
|
|
6159
|
+
const npm = await npmRegistry();
|
|
6160
|
+
await npm.dryRunPublish();
|
|
6161
|
+
});
|
|
6078
6162
|
}
|
|
6079
6163
|
};
|
|
6080
6164
|
var jsrDryRunPublishTask = {
|
|
6081
6165
|
title: "Dry-run jsr publish",
|
|
6082
|
-
skip: () => !JsrClient.token,
|
|
6083
6166
|
task: async (_, task) => {
|
|
6084
|
-
const jsr = await jsrRegistry();
|
|
6085
6167
|
task.output = "Running jsr publish --dry-run...";
|
|
6086
|
-
await jsr
|
|
6168
|
+
await withTokenRetry("jsr", task, async () => {
|
|
6169
|
+
const jsr = await jsrRegistry();
|
|
6170
|
+
await jsr.dryRunPublish();
|
|
6171
|
+
});
|
|
6087
6172
|
}
|
|
6088
6173
|
};
|
|
6174
|
+
async function getCrateName2(packagePath) {
|
|
6175
|
+
const eco = new RustEcosystem(packagePath ?? process.cwd());
|
|
6176
|
+
return await eco.packageName();
|
|
6177
|
+
}
|
|
6089
6178
|
function createCratesDryRunPublishTask(packagePath) {
|
|
6090
6179
|
const label = packagePath ? ` (${packagePath})` : "";
|
|
6091
6180
|
return {
|
|
6092
|
-
title: `Dry-run
|
|
6181
|
+
title: `Dry-run crates.io publish${label}`,
|
|
6093
6182
|
task: async (_, task) => {
|
|
6094
|
-
const eco = new RustEcosystem(packagePath ?? process.cwd());
|
|
6095
|
-
const packageName = await eco.packageName();
|
|
6096
|
-
const registry = new CratesRegistry(packageName);
|
|
6097
6183
|
task.output = "Running cargo publish --dry-run...";
|
|
6098
|
-
await
|
|
6184
|
+
await withTokenRetry("crates", task, async () => {
|
|
6185
|
+
const packageName = await getCrateName2(packagePath);
|
|
6186
|
+
const registry = new CratesRegistry(packageName);
|
|
6187
|
+
await registry.dryRunPublish(packagePath);
|
|
6188
|
+
});
|
|
6099
6189
|
}
|
|
6100
6190
|
};
|
|
6101
6191
|
}
|
|
6102
6192
|
var cratesDryRunPublishTask = createCratesDryRunPublishTask();
|
|
6103
|
-
function registryDryRunTask(registryKey) {
|
|
6104
|
-
switch (registryKey) {
|
|
6105
|
-
case "npm":
|
|
6106
|
-
return npmDryRunPublishTask;
|
|
6107
|
-
case "jsr":
|
|
6108
|
-
return jsrDryRunPublishTask;
|
|
6109
|
-
case "crates":
|
|
6110
|
-
return cratesDryRunPublishTask;
|
|
6111
|
-
default:
|
|
6112
|
-
return npmDryRunPublishTask;
|
|
6113
|
-
}
|
|
6114
|
-
}
|
|
6115
|
-
var dryRunPublishTask = {
|
|
6116
|
-
title: "Validating publish (dry-run)",
|
|
6117
|
-
task: (ctx, parentTask) => {
|
|
6118
|
-
if (ctx.packages?.length) {
|
|
6119
|
-
const tasks = ctx.packages.flatMap(
|
|
6120
|
-
(pkg) => pkg.registries.map(
|
|
6121
|
-
(registryKey) => registryKey === "crates" ? createCratesDryRunPublishTask(pkg.path) : registryDryRunTask(registryKey)
|
|
6122
|
-
)
|
|
6123
|
-
);
|
|
6124
|
-
return parentTask.newListr(tasks, { concurrent: true });
|
|
6125
|
-
}
|
|
6126
|
-
return parentTask.newListr(collectRegistries(ctx).map(registryDryRunTask), {
|
|
6127
|
-
concurrent: true
|
|
6128
|
-
});
|
|
6129
|
-
}
|
|
6130
|
-
};
|
|
6131
6193
|
|
|
6132
6194
|
// src/tasks/jsr.ts
|
|
6133
6195
|
var import_node_process6 = __toESM(require("process"), 1);
|
|
6134
|
-
var
|
|
6196
|
+
var import_prompt_adapter_enquirer2 = require("@listr2/prompt-adapter-enquirer");
|
|
6135
6197
|
var import_promise_spawn = __toESM(require("@npmcli/promise-spawn"), 1);
|
|
6136
6198
|
var { open } = import_promise_spawn.default;
|
|
6137
6199
|
var JsrAvailableError = class extends AbstractError {
|
|
@@ -6160,7 +6222,7 @@ var jsrAvailableCheckTasks = {
|
|
|
6160
6222
|
if (ctx.promptEnabled) {
|
|
6161
6223
|
const maxAttempts = 3;
|
|
6162
6224
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
6163
|
-
JsrClient.token = await task.prompt(
|
|
6225
|
+
JsrClient.token = await task.prompt(import_prompt_adapter_enquirer2.ListrEnquirerPromptAdapter).run({
|
|
6164
6226
|
type: "password",
|
|
6165
6227
|
message: `Please enter the jsr ${color.bold("API token")}${attempt > 1 ? ` (attempt ${attempt}/${maxAttempts})` : ""}`,
|
|
6166
6228
|
footer: `
|
|
@@ -6210,7 +6272,7 @@ Generate a token from ${color.bold(link2("jsr.io", "https://jsr.io/account/token
|
|
|
6210
6272
|
)
|
|
6211
6273
|
)).filter((v) => v !== null);
|
|
6212
6274
|
if (searchResults.length > 0) {
|
|
6213
|
-
jsrName = await task.prompt(
|
|
6275
|
+
jsrName = await task.prompt(import_prompt_adapter_enquirer2.ListrEnquirerPromptAdapter).run({
|
|
6214
6276
|
type: "select",
|
|
6215
6277
|
message: "Is there a scoped package you want to publish in the already published list?",
|
|
6216
6278
|
choices: [
|
|
@@ -6228,7 +6290,7 @@ Generate a token from ${color.bold(link2("jsr.io", "https://jsr.io/account/token
|
|
|
6228
6290
|
}
|
|
6229
6291
|
const userName = await new Git().userName();
|
|
6230
6292
|
task.output = "Select the scope of the package to publish";
|
|
6231
|
-
jsrName = await task.prompt(
|
|
6293
|
+
jsrName = await task.prompt(import_prompt_adapter_enquirer2.ListrEnquirerPromptAdapter).run({
|
|
6232
6294
|
type: "select",
|
|
6233
6295
|
message: "jsr.json does not exist, and the package name is not scoped. Please select a scope for the 'jsr' package",
|
|
6234
6296
|
choices: [
|
|
@@ -6256,7 +6318,7 @@ Generate a token from ${color.bold(link2("jsr.io", "https://jsr.io/account/token
|
|
|
6256
6318
|
});
|
|
6257
6319
|
if (jsrName === "specify") {
|
|
6258
6320
|
while (!isScopedPackage(jsrName)) {
|
|
6259
|
-
jsrName = await task.prompt(
|
|
6321
|
+
jsrName = await task.prompt(import_prompt_adapter_enquirer2.ListrEnquirerPromptAdapter).run({
|
|
6260
6322
|
type: "input",
|
|
6261
6323
|
message: "Package name"
|
|
6262
6324
|
});
|
|
@@ -6324,7 +6386,7 @@ var jsrPublishTasks = {
|
|
|
6324
6386
|
${urls.map((url) => ` ${color.cyan(url)}`).join("\n")}`;
|
|
6325
6387
|
open(urls[0]);
|
|
6326
6388
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
6327
|
-
await task.prompt(
|
|
6389
|
+
await task.prompt(import_prompt_adapter_enquirer2.ListrEnquirerPromptAdapter).run({
|
|
6328
6390
|
type: "input",
|
|
6329
6391
|
message: `Press ${color.bold("enter")} after creating the package on jsr.io${attempt > 1 ? ` (attempt ${attempt}/${maxAttempts})` : ""}`
|
|
6330
6392
|
});
|
|
@@ -6353,7 +6415,7 @@ ${jsr.packageCreationUrls.join("\n")}`
|
|
|
6353
6415
|
// src/tasks/npm.ts
|
|
6354
6416
|
var import_node_child_process = require("child_process");
|
|
6355
6417
|
var import_node_process7 = __toESM(require("process"), 1);
|
|
6356
|
-
var
|
|
6418
|
+
var import_prompt_adapter_enquirer3 = require("@listr2/prompt-adapter-enquirer");
|
|
6357
6419
|
var import_promise_spawn2 = __toESM(require("@npmcli/promise-spawn"), 1);
|
|
6358
6420
|
var { open: open2 } = import_promise_spawn2.default;
|
|
6359
6421
|
var NpmAvailableError = class extends AbstractError {
|
|
@@ -6450,7 +6512,7 @@ var npmPublishTasks = {
|
|
|
6450
6512
|
const maxAttempts = 3;
|
|
6451
6513
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
6452
6514
|
result = await npm.publish(
|
|
6453
|
-
await task.prompt(
|
|
6515
|
+
await task.prompt(import_prompt_adapter_enquirer3.ListrEnquirerPromptAdapter).run({
|
|
6454
6516
|
type: "password",
|
|
6455
6517
|
message: `npm OTP code${attempt > 1 ? ` (attempt ${attempt}/${maxAttempts})` : ""}`
|
|
6456
6518
|
})
|
|
@@ -6484,8 +6546,64 @@ var npmPublishTasks = {
|
|
|
6484
6546
|
}
|
|
6485
6547
|
};
|
|
6486
6548
|
|
|
6549
|
+
// src/tasks/preflight.ts
|
|
6550
|
+
var import_prompt_adapter_enquirer4 = require("@listr2/prompt-adapter-enquirer");
|
|
6551
|
+
var import_tinyexec5 = require("tinyexec");
|
|
6552
|
+
var PreflightError = class extends AbstractError {
|
|
6553
|
+
constructor() {
|
|
6554
|
+
super(...arguments);
|
|
6555
|
+
__publicField(this, "name", "Preflight Error");
|
|
6556
|
+
}
|
|
6557
|
+
};
|
|
6558
|
+
async function collectTokens(registries, task) {
|
|
6559
|
+
const existing = loadTokensFromDb(registries);
|
|
6560
|
+
const tokens = { ...existing };
|
|
6561
|
+
for (const registry of registries) {
|
|
6562
|
+
const config = TOKEN_CONFIG[registry];
|
|
6563
|
+
if (!config || tokens[registry]) continue;
|
|
6564
|
+
task.output = `Enter ${config.promptLabel}`;
|
|
6565
|
+
const token = await task.prompt(import_prompt_adapter_enquirer4.ListrEnquirerPromptAdapter).run({
|
|
6566
|
+
type: "password",
|
|
6567
|
+
message: `Enter ${config.promptLabel}`
|
|
6568
|
+
});
|
|
6569
|
+
tokens[registry] = token;
|
|
6570
|
+
new Db().set(config.dbKey, token);
|
|
6571
|
+
}
|
|
6572
|
+
return tokens;
|
|
6573
|
+
}
|
|
6574
|
+
async function syncGhSecrets(tokens) {
|
|
6575
|
+
for (const [registry, token] of Object.entries(tokens)) {
|
|
6576
|
+
const config = TOKEN_CONFIG[registry];
|
|
6577
|
+
if (!config) continue;
|
|
6578
|
+
await (0, import_tinyexec5.exec)("gh", ["secret", "set", config.ghSecretName], {
|
|
6579
|
+
throwOnError: true,
|
|
6580
|
+
nodeOptions: { input: token }
|
|
6581
|
+
});
|
|
6582
|
+
}
|
|
6583
|
+
}
|
|
6584
|
+
async function promptGhSecretsSync(tokens, task) {
|
|
6585
|
+
const shouldSync = await task.prompt(import_prompt_adapter_enquirer4.ListrEnquirerPromptAdapter).run({
|
|
6586
|
+
type: "toggle",
|
|
6587
|
+
message: "Sync tokens to GitHub Secrets?",
|
|
6588
|
+
enabled: "Yes",
|
|
6589
|
+
disabled: "No"
|
|
6590
|
+
});
|
|
6591
|
+
if (shouldSync) {
|
|
6592
|
+
task.output = "Syncing tokens to GitHub Secrets...";
|
|
6593
|
+
try {
|
|
6594
|
+
await syncGhSecrets(tokens);
|
|
6595
|
+
task.output = "Tokens synced to GitHub Secrets.";
|
|
6596
|
+
} catch (error) {
|
|
6597
|
+
throw new PreflightError(
|
|
6598
|
+
"Failed to sync tokens to GitHub Secrets. Ensure `gh` CLI is installed and authenticated (`gh auth login`).",
|
|
6599
|
+
{ cause: error }
|
|
6600
|
+
);
|
|
6601
|
+
}
|
|
6602
|
+
}
|
|
6603
|
+
}
|
|
6604
|
+
|
|
6487
6605
|
// src/tasks/prerequisites-check.ts
|
|
6488
|
-
var
|
|
6606
|
+
var import_prompt_adapter_enquirer5 = require("@listr2/prompt-adapter-enquirer");
|
|
6489
6607
|
var PrerequisitesCheckError = class extends AbstractError {
|
|
6490
6608
|
constructor(message, { cause } = {}) {
|
|
6491
6609
|
super(message, { cause });
|
|
@@ -6505,7 +6623,7 @@ var prerequisitesCheckTask = (options) => {
|
|
|
6505
6623
|
title: "Verifying current branch is a release branch",
|
|
6506
6624
|
task: async (ctx, task) => {
|
|
6507
6625
|
if (await git.branch() !== ctx.branch) {
|
|
6508
|
-
const swtichBranch = await task.prompt(
|
|
6626
|
+
const swtichBranch = await task.prompt(import_prompt_adapter_enquirer5.ListrEnquirerPromptAdapter).run({
|
|
6509
6627
|
type: "toggle",
|
|
6510
6628
|
message: `${warningBadge} The current HEAD branch is not the release target branch. Do you want to switch branch to ${ctx.branch}?`,
|
|
6511
6629
|
enabled: "Yes",
|
|
@@ -6527,7 +6645,7 @@ var prerequisitesCheckTask = (options) => {
|
|
|
6527
6645
|
task: async (_2, task) => {
|
|
6528
6646
|
task.output = "Checking for updates with `git fetch`";
|
|
6529
6647
|
if ((await git.dryFetch()).trim()) {
|
|
6530
|
-
const fetch2 = await task.prompt(
|
|
6648
|
+
const fetch2 = await task.prompt(import_prompt_adapter_enquirer5.ListrEnquirerPromptAdapter).run({
|
|
6531
6649
|
type: "toggle",
|
|
6532
6650
|
message: `${warningBadge} Local history is outdated. Do you want to run \`git fetch\`?`,
|
|
6533
6651
|
enabled: "Yes",
|
|
@@ -6544,7 +6662,7 @@ var prerequisitesCheckTask = (options) => {
|
|
|
6544
6662
|
}
|
|
6545
6663
|
task.output = "Checking for updates with `git pull`";
|
|
6546
6664
|
if (await git.revisionDiffsCount()) {
|
|
6547
|
-
const pull = await task.prompt(
|
|
6665
|
+
const pull = await task.prompt(import_prompt_adapter_enquirer5.ListrEnquirerPromptAdapter).run({
|
|
6548
6666
|
type: "toggle",
|
|
6549
6667
|
message: `${warningBadge} Local history is outdated. Do you want to run \`git pull\`?`,
|
|
6550
6668
|
enabled: "Yes",
|
|
@@ -6566,7 +6684,7 @@ var prerequisitesCheckTask = (options) => {
|
|
|
6566
6684
|
task: async (ctx, task) => {
|
|
6567
6685
|
if (await git.status()) {
|
|
6568
6686
|
task.output = "Local working tree is not clean.";
|
|
6569
|
-
if (!await task.prompt(
|
|
6687
|
+
if (!await task.prompt(import_prompt_adapter_enquirer5.ListrEnquirerPromptAdapter).run({
|
|
6570
6688
|
type: "toggle",
|
|
6571
6689
|
message: `${warningBadge} Local working tree is not clean. Do you want to skip?`,
|
|
6572
6690
|
enabled: "Yes",
|
|
@@ -6591,7 +6709,7 @@ var prerequisitesCheckTask = (options) => {
|
|
|
6591
6709
|
return void 0;
|
|
6592
6710
|
}
|
|
6593
6711
|
if ((await git.commits(latestTag, "HEAD")).length <= 0) {
|
|
6594
|
-
if (!await task.prompt(
|
|
6712
|
+
if (!await task.prompt(import_prompt_adapter_enquirer5.ListrEnquirerPromptAdapter).run({
|
|
6595
6713
|
type: "toggle",
|
|
6596
6714
|
message: `${warningBadge} No commits exist from the latest tag. Do you want to skip?`,
|
|
6597
6715
|
enabled: "Yes",
|
|
@@ -6609,7 +6727,7 @@ var prerequisitesCheckTask = (options) => {
|
|
|
6609
6727
|
task: async (ctx, task) => {
|
|
6610
6728
|
const gitTag = `v${ctx.version}`;
|
|
6611
6729
|
if (await git.checkTagExist(gitTag)) {
|
|
6612
|
-
const deleteTag = await task.prompt(
|
|
6730
|
+
const deleteTag = await task.prompt(import_prompt_adapter_enquirer5.ListrEnquirerPromptAdapter).run({
|
|
6613
6731
|
type: "toggle",
|
|
6614
6732
|
message: `${warningBadge} The Git tag '${gitTag}' already exists. Do you want to delete tag?`,
|
|
6615
6733
|
enabled: "Yes",
|
|
@@ -6631,13 +6749,13 @@ var prerequisitesCheckTask = (options) => {
|
|
|
6631
6749
|
};
|
|
6632
6750
|
|
|
6633
6751
|
// src/tasks/required-conditions-check.ts
|
|
6634
|
-
var
|
|
6752
|
+
var import_prompt_adapter_enquirer6 = require("@listr2/prompt-adapter-enquirer");
|
|
6635
6753
|
|
|
6636
6754
|
// src/registry/custom-registry.ts
|
|
6637
|
-
var
|
|
6755
|
+
var import_tinyexec6 = require("tinyexec");
|
|
6638
6756
|
var CustomRegistry = class extends NpmRegistry {
|
|
6639
6757
|
async npm(args) {
|
|
6640
|
-
const { stdout } = await (0,
|
|
6758
|
+
const { stdout } = await (0, import_tinyexec6.exec)(
|
|
6641
6759
|
"npm",
|
|
6642
6760
|
args.concat("--registry", this.registry),
|
|
6643
6761
|
{ throwOnError: true }
|
|
@@ -6740,7 +6858,7 @@ var requiredConditionsCheckTask = (options) => createListr({
|
|
|
6740
6858
|
task: async (_3, task) => {
|
|
6741
6859
|
const jsr = await jsrRegistry();
|
|
6742
6860
|
if (!await jsr.isInstalled()) {
|
|
6743
|
-
const install = await task.prompt(
|
|
6861
|
+
const install = await task.prompt(import_prompt_adapter_enquirer6.ListrEnquirerPromptAdapter).run({
|
|
6744
6862
|
type: "toggle",
|
|
6745
6863
|
message: `${warningBadge} jsr is not installed. Do you want to install jsr?`,
|
|
6746
6864
|
enabled: "Yes",
|
|
@@ -6874,14 +6992,66 @@ async function collectPublishTasks(ctx) {
|
|
|
6874
6992
|
}
|
|
6875
6993
|
return collectRegistries(ctx).map(registryTask);
|
|
6876
6994
|
}
|
|
6995
|
+
function dryRunRegistryTask(registry) {
|
|
6996
|
+
switch (registry) {
|
|
6997
|
+
case "npm":
|
|
6998
|
+
return npmDryRunPublishTask;
|
|
6999
|
+
case "jsr":
|
|
7000
|
+
return jsrDryRunPublishTask;
|
|
7001
|
+
case "crates":
|
|
7002
|
+
return cratesDryRunPublishTask;
|
|
7003
|
+
default:
|
|
7004
|
+
return npmDryRunPublishTask;
|
|
7005
|
+
}
|
|
7006
|
+
}
|
|
7007
|
+
async function collectDryRunPublishTasks(ctx) {
|
|
7008
|
+
if (ctx.packages?.length) {
|
|
7009
|
+
const nonCratesTasks = ctx.packages.flatMap(
|
|
7010
|
+
(pkg) => pkg.registries.filter((reg) => reg !== "crates").map((reg) => dryRunRegistryTask(reg))
|
|
7011
|
+
);
|
|
7012
|
+
const cratesPaths = ctx.packages.filter((pkg) => pkg.registries.includes("crates")).map((pkg) => pkg.path);
|
|
7013
|
+
if (cratesPaths.length === 0) {
|
|
7014
|
+
return nonCratesTasks;
|
|
7015
|
+
}
|
|
7016
|
+
const sortedPaths = await sortCratesByDependencyOrder(cratesPaths);
|
|
7017
|
+
const sequentialCratesTask = {
|
|
7018
|
+
title: "Dry-run crates.io publish (sequential)",
|
|
7019
|
+
task: (_ctx, task) => task.newListr(
|
|
7020
|
+
sortedPaths.map((p) => createCratesDryRunPublishTask(p)),
|
|
7021
|
+
{ concurrent: false }
|
|
7022
|
+
)
|
|
7023
|
+
};
|
|
7024
|
+
return [...nonCratesTasks, sequentialCratesTask];
|
|
7025
|
+
}
|
|
7026
|
+
return collectRegistries(ctx).map(dryRunRegistryTask);
|
|
7027
|
+
}
|
|
6877
7028
|
async function run(options) {
|
|
6878
7029
|
const ctx = {
|
|
6879
7030
|
...options,
|
|
6880
7031
|
promptEnabled: !import_std_env.isCI && import_node_process8.default.stdin.isTTY
|
|
6881
7032
|
};
|
|
7033
|
+
let cleanupEnv;
|
|
6882
7034
|
try {
|
|
6883
7035
|
if (options.contents) import_node_process8.default.chdir(options.contents);
|
|
6884
|
-
if (
|
|
7036
|
+
if (options.preflight) {
|
|
7037
|
+
await createListr({
|
|
7038
|
+
title: "Collecting registry tokens",
|
|
7039
|
+
task: async (ctx2, task) => {
|
|
7040
|
+
const registries2 = collectRegistries(ctx2);
|
|
7041
|
+
const tokens = await collectTokens(registries2, task);
|
|
7042
|
+
await promptGhSecretsSync(tokens, task);
|
|
7043
|
+
cleanupEnv = injectTokensToEnv(tokens);
|
|
7044
|
+
ctx2.promptEnabled = false;
|
|
7045
|
+
}
|
|
7046
|
+
}).run(ctx);
|
|
7047
|
+
await prerequisitesCheckTask({
|
|
7048
|
+
skip: options.skipPrerequisitesCheck
|
|
7049
|
+
}).run(ctx);
|
|
7050
|
+
await requiredConditionsCheckTask({
|
|
7051
|
+
skip: options.skipConditionsCheck
|
|
7052
|
+
}).run(ctx);
|
|
7053
|
+
}
|
|
7054
|
+
if (!options.publishOnly && !options.preflight) {
|
|
6885
7055
|
await prerequisitesCheckTask({
|
|
6886
7056
|
skip: options.skipPrerequisitesCheck
|
|
6887
7057
|
}).run(ctx);
|
|
@@ -6895,14 +7065,14 @@ async function run(options) {
|
|
|
6895
7065
|
task: async (ctx2, parentTask) => parentTask.newListr(await collectPublishTasks(ctx2), {
|
|
6896
7066
|
concurrent: true
|
|
6897
7067
|
})
|
|
6898
|
-
} : [
|
|
7068
|
+
} : options.preflight ? [
|
|
6899
7069
|
{
|
|
6900
7070
|
skip: options.skipTests,
|
|
6901
7071
|
title: "Running tests",
|
|
6902
7072
|
task: async (ctx2) => {
|
|
6903
7073
|
const packageManager = await getPackageManager();
|
|
6904
7074
|
try {
|
|
6905
|
-
await (0,
|
|
7075
|
+
await (0, import_tinyexec7.exec)(packageManager, ["run", ctx2.testScript], {
|
|
6906
7076
|
throwOnError: true
|
|
6907
7077
|
});
|
|
6908
7078
|
} catch (error) {
|
|
@@ -6919,7 +7089,7 @@ async function run(options) {
|
|
|
6919
7089
|
task: async (ctx2) => {
|
|
6920
7090
|
const packageManager = await getPackageManager();
|
|
6921
7091
|
try {
|
|
6922
|
-
await (0,
|
|
7092
|
+
await (0, import_tinyexec7.exec)(packageManager, ["run", ctx2.buildScript], {
|
|
6923
7093
|
throwOnError: true
|
|
6924
7094
|
});
|
|
6925
7095
|
} catch (error) {
|
|
@@ -6931,8 +7101,45 @@ async function run(options) {
|
|
|
6931
7101
|
}
|
|
6932
7102
|
},
|
|
6933
7103
|
{
|
|
6934
|
-
|
|
6935
|
-
|
|
7104
|
+
title: "Validating publish (dry-run)",
|
|
7105
|
+
task: async (ctx2, parentTask) => parentTask.newListr(await collectDryRunPublishTasks(ctx2), {
|
|
7106
|
+
concurrent: true
|
|
7107
|
+
})
|
|
7108
|
+
}
|
|
7109
|
+
] : [
|
|
7110
|
+
{
|
|
7111
|
+
skip: options.skipTests,
|
|
7112
|
+
title: "Running tests",
|
|
7113
|
+
task: async (ctx2) => {
|
|
7114
|
+
const packageManager = await getPackageManager();
|
|
7115
|
+
try {
|
|
7116
|
+
await (0, import_tinyexec7.exec)(packageManager, ["run", ctx2.testScript], {
|
|
7117
|
+
throwOnError: true
|
|
7118
|
+
});
|
|
7119
|
+
} catch (error) {
|
|
7120
|
+
throw new AbstractError(
|
|
7121
|
+
`Test script '${ctx2.testScript}' failed. Run \`${packageManager} run ${ctx2.testScript}\` locally to see full output.`,
|
|
7122
|
+
{ cause: error }
|
|
7123
|
+
);
|
|
7124
|
+
}
|
|
7125
|
+
}
|
|
7126
|
+
},
|
|
7127
|
+
{
|
|
7128
|
+
skip: options.skipBuild,
|
|
7129
|
+
title: "Building the project",
|
|
7130
|
+
task: async (ctx2) => {
|
|
7131
|
+
const packageManager = await getPackageManager();
|
|
7132
|
+
try {
|
|
7133
|
+
await (0, import_tinyexec7.exec)(packageManager, ["run", ctx2.buildScript], {
|
|
7134
|
+
throwOnError: true
|
|
7135
|
+
});
|
|
7136
|
+
} catch (error) {
|
|
7137
|
+
throw new AbstractError(
|
|
7138
|
+
`Build script '${ctx2.buildScript}' failed. Run \`${packageManager} run ${ctx2.buildScript}\` locally to see full output.`,
|
|
7139
|
+
{ cause: error }
|
|
7140
|
+
);
|
|
7141
|
+
}
|
|
7142
|
+
}
|
|
6936
7143
|
},
|
|
6937
7144
|
{
|
|
6938
7145
|
title: "Bumping version",
|
|
@@ -7048,13 +7255,24 @@ ${repositoryUrl}/compare/${lastRev}...${latestTag}`;
|
|
|
7048
7255
|
parts.push(`${color.bold(name)} on ${color.red("crates.io")}`);
|
|
7049
7256
|
}
|
|
7050
7257
|
}
|
|
7051
|
-
|
|
7052
|
-
|
|
7258
|
+
if (options.preflight) {
|
|
7259
|
+
cleanupEnv?.();
|
|
7260
|
+
console.log(
|
|
7261
|
+
`
|
|
7262
|
+
|
|
7263
|
+
\u2705 Preflight check passed. CI publish should succeed for ${parts.join(", ")}.
|
|
7264
|
+
`
|
|
7265
|
+
);
|
|
7266
|
+
} else {
|
|
7267
|
+
console.log(
|
|
7268
|
+
`
|
|
7053
7269
|
|
|
7054
7270
|
\u{1F680} Successfully published ${parts.join(", ")} ${color.blueBright(`v${ctx.version}`)} \u{1F680}
|
|
7055
7271
|
`
|
|
7056
|
-
|
|
7272
|
+
);
|
|
7273
|
+
}
|
|
7057
7274
|
} catch (e2) {
|
|
7275
|
+
cleanupEnv?.();
|
|
7058
7276
|
consoleError(e2);
|
|
7059
7277
|
await rollback();
|
|
7060
7278
|
import_node_process8.default.exit(1);
|