pubm 0.2.0 → 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 +736 -356
- package/dist/index.cjs +446 -104
- package/dist/index.d.cts +5 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +445 -103
- package/package.json +1 -1
package/bin/cli.js
CHANGED
|
@@ -453,7 +453,7 @@ __export(base_exports, {
|
|
|
453
453
|
scrollDown: () => scrollDown,
|
|
454
454
|
scrollUp: () => scrollUp
|
|
455
455
|
});
|
|
456
|
-
import
|
|
456
|
+
import process4 from "node:process";
|
|
457
457
|
var ESC, OSC, BEL, SEP, isTerminalApp, isWindows3, cwdFunction, cursorTo, cursorMove, cursorUp, cursorDown, cursorForward, cursorBackward, cursorLeft, cursorSavePosition, cursorRestorePosition, cursorGetPosition, cursorNextLine, cursorPrevLine, cursorHide, cursorShow, eraseLines, eraseEndLine, eraseStartLine, eraseLine, eraseDown, eraseUp, eraseScreen, scrollUp, scrollDown, clearScreen, clearTerminal, enterAlternativeScreen, exitAlternativeScreen, beep, link, image, iTerm;
|
|
458
458
|
var init_base = __esm({
|
|
459
459
|
"node_modules/.pnpm/ansi-escapes@7.0.0/node_modules/ansi-escapes/base.js"() {
|
|
@@ -463,11 +463,11 @@ var init_base = __esm({
|
|
|
463
463
|
OSC = "\x1B]";
|
|
464
464
|
BEL = "\x07";
|
|
465
465
|
SEP = ";";
|
|
466
|
-
isTerminalApp = !isBrowser &&
|
|
467
|
-
isWindows3 = !isBrowser &&
|
|
466
|
+
isTerminalApp = !isBrowser && process4.env.TERM_PROGRAM === "Apple_Terminal";
|
|
467
|
+
isWindows3 = !isBrowser && process4.platform === "win32";
|
|
468
468
|
cwdFunction = isBrowser ? () => {
|
|
469
469
|
throw new Error("`process.cwd()` only works in Node.js, not the browser.");
|
|
470
|
-
} :
|
|
470
|
+
} : process4.cwd;
|
|
471
471
|
cursorTo = (x, y) => {
|
|
472
472
|
if (typeof x !== "number") {
|
|
473
473
|
throw new TypeError("The `x` argument is required");
|
|
@@ -708,7 +708,7 @@ var init_signals = __esm({
|
|
|
708
708
|
});
|
|
709
709
|
|
|
710
710
|
// node_modules/.pnpm/signal-exit@4.1.0/node_modules/signal-exit/dist/mjs/index.js
|
|
711
|
-
var processOk, kExitEmitter, global, ObjectDefineProperty, Emitter, SignalExitBase, signalExitWrap, SignalExitFallback, _hupSig, _emitter, _process, _originalProcessEmit, _originalProcessReallyExit, _sigListeners, _loaded, _SignalExit_instances, processReallyExit_fn, processEmit_fn, SignalExit,
|
|
711
|
+
var processOk, kExitEmitter, global, ObjectDefineProperty, Emitter, SignalExitBase, signalExitWrap, SignalExitFallback, _hupSig, _emitter, _process, _originalProcessEmit, _originalProcessReallyExit, _sigListeners, _loaded, _SignalExit_instances, processReallyExit_fn, processEmit_fn, SignalExit, process5, onExit, load, unload;
|
|
712
712
|
var init_mjs = __esm({
|
|
713
713
|
"node_modules/.pnpm/signal-exit@4.1.0/node_modules/signal-exit/dist/mjs/index.js"() {
|
|
714
714
|
"use strict";
|
|
@@ -801,7 +801,7 @@ var init_mjs = __esm({
|
|
|
801
801
|
// "SIGHUP" throws an `ENOSYS` error on Windows,
|
|
802
802
|
// so use a supported signal instead
|
|
803
803
|
/* c8 ignore start */
|
|
804
|
-
__privateAdd(this, _hupSig,
|
|
804
|
+
__privateAdd(this, _hupSig, process5.platform === "win32" ? "SIGINT" : "SIGHUP");
|
|
805
805
|
/* c8 ignore stop */
|
|
806
806
|
__privateAdd(this, _emitter, new Emitter());
|
|
807
807
|
__privateAdd(this, _process);
|
|
@@ -918,7 +918,7 @@ var init_mjs = __esm({
|
|
|
918
918
|
return og.call(__privateGet(this, _process), ev, ...args);
|
|
919
919
|
}
|
|
920
920
|
};
|
|
921
|
-
|
|
921
|
+
process5 = globalThis.process;
|
|
922
922
|
({
|
|
923
923
|
onExit: (
|
|
924
924
|
/**
|
|
@@ -952,19 +952,19 @@ var init_mjs = __esm({
|
|
|
952
952
|
*/
|
|
953
953
|
unload
|
|
954
954
|
)
|
|
955
|
-
} = signalExitWrap(processOk(
|
|
955
|
+
} = signalExitWrap(processOk(process5) ? new SignalExit(process5) : new SignalExitFallback()));
|
|
956
956
|
}
|
|
957
957
|
});
|
|
958
958
|
|
|
959
959
|
// node_modules/.pnpm/restore-cursor@5.1.0/node_modules/restore-cursor/index.js
|
|
960
|
-
import
|
|
960
|
+
import process6 from "node:process";
|
|
961
961
|
var terminal, restoreCursor, restore_cursor_default;
|
|
962
962
|
var init_restore_cursor = __esm({
|
|
963
963
|
"node_modules/.pnpm/restore-cursor@5.1.0/node_modules/restore-cursor/index.js"() {
|
|
964
964
|
"use strict";
|
|
965
965
|
init_onetime();
|
|
966
966
|
init_mjs();
|
|
967
|
-
terminal =
|
|
967
|
+
terminal = process6.stderr.isTTY ? process6.stderr : process6.stdout.isTTY ? process6.stdout : void 0;
|
|
968
968
|
restoreCursor = terminal ? onetime_default(() => {
|
|
969
969
|
onExit(() => {
|
|
970
970
|
terminal.write("\x1B[?25h");
|
|
@@ -976,7 +976,7 @@ var init_restore_cursor = __esm({
|
|
|
976
976
|
});
|
|
977
977
|
|
|
978
978
|
// node_modules/.pnpm/cli-cursor@5.0.0/node_modules/cli-cursor/index.js
|
|
979
|
-
import
|
|
979
|
+
import process7 from "node:process";
|
|
980
980
|
var isHidden, cliCursor, cli_cursor_default;
|
|
981
981
|
var init_cli_cursor = __esm({
|
|
982
982
|
"node_modules/.pnpm/cli-cursor@5.0.0/node_modules/cli-cursor/index.js"() {
|
|
@@ -984,14 +984,14 @@ var init_cli_cursor = __esm({
|
|
|
984
984
|
init_restore_cursor();
|
|
985
985
|
isHidden = false;
|
|
986
986
|
cliCursor = {};
|
|
987
|
-
cliCursor.show = (writableStream =
|
|
987
|
+
cliCursor.show = (writableStream = process7.stderr) => {
|
|
988
988
|
if (!writableStream.isTTY) {
|
|
989
989
|
return;
|
|
990
990
|
}
|
|
991
991
|
isHidden = false;
|
|
992
992
|
writableStream.write("\x1B[?25h");
|
|
993
993
|
};
|
|
994
|
-
cliCursor.hide = (writableStream =
|
|
994
|
+
cliCursor.hide = (writableStream = process7.stderr) => {
|
|
995
995
|
if (!writableStream.isTTY) {
|
|
996
996
|
return;
|
|
997
997
|
}
|
|
@@ -1667,7 +1667,7 @@ __export(log_update_exports, {
|
|
|
1667
1667
|
default: () => log_update_default,
|
|
1668
1668
|
logUpdateStderr: () => logUpdateStderr
|
|
1669
1669
|
});
|
|
1670
|
-
import
|
|
1670
|
+
import process8 from "node:process";
|
|
1671
1671
|
function createLogUpdate(stream, { showCursor = false } = {}) {
|
|
1672
1672
|
let previousLineCount = 0;
|
|
1673
1673
|
let previousWidth = getWidth(stream);
|
|
@@ -1721,9 +1721,9 @@ var init_log_update = __esm({
|
|
|
1721
1721
|
const toRemove = Math.max(0, lines.length - terminalHeight);
|
|
1722
1722
|
return toRemove ? sliceAnsi(text, stripAnsi(lines.slice(0, toRemove).join("\n")).length + 1) : text;
|
|
1723
1723
|
};
|
|
1724
|
-
logUpdate = createLogUpdate(
|
|
1724
|
+
logUpdate = createLogUpdate(process8.stdout);
|
|
1725
1725
|
log_update_default = logUpdate;
|
|
1726
|
-
logUpdateStderr = createLogUpdate(
|
|
1726
|
+
logUpdateStderr = createLogUpdate(process8.stderr);
|
|
1727
1727
|
}
|
|
1728
1728
|
});
|
|
1729
1729
|
|
|
@@ -2225,178 +2225,6 @@ function registerPreCommand(cli2) {
|
|
|
2225
2225
|
});
|
|
2226
2226
|
}
|
|
2227
2227
|
|
|
2228
|
-
// src/commands/snapshot.ts
|
|
2229
|
-
function registerSnapshotCommand(cli2) {
|
|
2230
|
-
cli2.command("snapshot [tag]", "Create a snapshot release").action(async (tag) => {
|
|
2231
|
-
console.log(`pubm snapshot ${tag ?? ""} \u2014 coming in next phase`);
|
|
2232
|
-
});
|
|
2233
|
-
}
|
|
2234
|
-
|
|
2235
|
-
// src/changeset/status.ts
|
|
2236
|
-
import process5 from "node:process";
|
|
2237
|
-
|
|
2238
|
-
// src/changeset/bump-utils.ts
|
|
2239
|
-
var BUMP_ORDER = {
|
|
2240
|
-
patch: 0,
|
|
2241
|
-
minor: 1,
|
|
2242
|
-
major: 2
|
|
2243
|
-
};
|
|
2244
|
-
function maxBump(a2, b) {
|
|
2245
|
-
return BUMP_ORDER[a2] >= BUMP_ORDER[b] ? a2 : b;
|
|
2246
|
-
}
|
|
2247
|
-
|
|
2248
|
-
// src/changeset/reader.ts
|
|
2249
|
-
import { existsSync as existsSync4, readdirSync as readdirSync2, readFileSync as readFileSync2 } from "node:fs";
|
|
2250
|
-
import path5 from "node:path";
|
|
2251
|
-
import process4 from "node:process";
|
|
2252
|
-
|
|
2253
|
-
// src/changeset/parser.ts
|
|
2254
|
-
import { parse as parseYaml } from "yaml";
|
|
2255
|
-
var VALID_BUMP_TYPES = /* @__PURE__ */ new Set(["patch", "minor", "major"]);
|
|
2256
|
-
function parseChangeset(content, fileName) {
|
|
2257
|
-
const frontmatterRegex = /^---\n([\s\S]*?)---/;
|
|
2258
|
-
const match = content.match(frontmatterRegex);
|
|
2259
|
-
if (!match) {
|
|
2260
|
-
throw new Error(
|
|
2261
|
-
`Invalid changeset format in "${fileName}": missing frontmatter`
|
|
2262
|
-
);
|
|
2263
|
-
}
|
|
2264
|
-
const yamlContent = match[1];
|
|
2265
|
-
const body = content.slice(match[0].length).trim();
|
|
2266
|
-
const parsed = parseYaml(yamlContent);
|
|
2267
|
-
const releases = [];
|
|
2268
|
-
if (parsed) {
|
|
2269
|
-
for (const [name, type] of Object.entries(parsed)) {
|
|
2270
|
-
if (!VALID_BUMP_TYPES.has(type)) {
|
|
2271
|
-
throw new Error(
|
|
2272
|
-
`Invalid bump type "${type}" for package "${name}" in "${fileName}". Expected: patch, minor, or major.`
|
|
2273
|
-
);
|
|
2274
|
-
}
|
|
2275
|
-
releases.push({ name, type });
|
|
2276
|
-
}
|
|
2277
|
-
}
|
|
2278
|
-
const id = fileName.replace(/\.md$/, "");
|
|
2279
|
-
return {
|
|
2280
|
-
id,
|
|
2281
|
-
summary: body,
|
|
2282
|
-
releases
|
|
2283
|
-
};
|
|
2284
|
-
}
|
|
2285
|
-
|
|
2286
|
-
// src/changeset/reader.ts
|
|
2287
|
-
function readChangesets(cwd = process4.cwd()) {
|
|
2288
|
-
const changesetsDir = path5.join(cwd, ".pubm", "changesets");
|
|
2289
|
-
if (!existsSync4(changesetsDir)) {
|
|
2290
|
-
return [];
|
|
2291
|
-
}
|
|
2292
|
-
const files = readdirSync2(changesetsDir);
|
|
2293
|
-
const changesets = [];
|
|
2294
|
-
for (const file of files) {
|
|
2295
|
-
if (!file.endsWith(".md") || file === "README.md") {
|
|
2296
|
-
continue;
|
|
2297
|
-
}
|
|
2298
|
-
const filePath = path5.join(changesetsDir, file);
|
|
2299
|
-
const content = readFileSync2(filePath, "utf-8");
|
|
2300
|
-
changesets.push(parseChangeset(content, file));
|
|
2301
|
-
}
|
|
2302
|
-
return changesets;
|
|
2303
|
-
}
|
|
2304
|
-
|
|
2305
|
-
// src/changeset/status.ts
|
|
2306
|
-
function getStatus(cwd = process5.cwd()) {
|
|
2307
|
-
const changesets = readChangesets(cwd);
|
|
2308
|
-
const packages = /* @__PURE__ */ new Map();
|
|
2309
|
-
for (const changeset of changesets) {
|
|
2310
|
-
for (const release of changeset.releases) {
|
|
2311
|
-
const existing = packages.get(release.name);
|
|
2312
|
-
if (existing) {
|
|
2313
|
-
existing.bumpType = maxBump(existing.bumpType, release.type);
|
|
2314
|
-
existing.changesetCount += 1;
|
|
2315
|
-
existing.summaries.push(changeset.summary);
|
|
2316
|
-
} else {
|
|
2317
|
-
packages.set(release.name, {
|
|
2318
|
-
bumpType: release.type,
|
|
2319
|
-
changesetCount: 1,
|
|
2320
|
-
summaries: [changeset.summary]
|
|
2321
|
-
});
|
|
2322
|
-
}
|
|
2323
|
-
}
|
|
2324
|
-
}
|
|
2325
|
-
return {
|
|
2326
|
-
packages,
|
|
2327
|
-
changesets,
|
|
2328
|
-
hasChangesets: changesets.length > 0
|
|
2329
|
-
};
|
|
2330
|
-
}
|
|
2331
|
-
|
|
2332
|
-
// src/commands/status.ts
|
|
2333
|
-
function registerStatusCommand(cli2) {
|
|
2334
|
-
cli2.command("status", "Show pending changeset status").option("--verbose", "Show full changeset contents").option("--since <ref>", "Only check changesets since git ref").action(async (options) => {
|
|
2335
|
-
const status = getStatus();
|
|
2336
|
-
if (!status.hasChangesets) {
|
|
2337
|
-
if (options.since) {
|
|
2338
|
-
console.log("No changesets found.");
|
|
2339
|
-
process.exit(1);
|
|
2340
|
-
}
|
|
2341
|
-
console.log("No pending changesets.");
|
|
2342
|
-
return;
|
|
2343
|
-
}
|
|
2344
|
-
console.log("Pending changesets:");
|
|
2345
|
-
for (const [name, info] of status.packages) {
|
|
2346
|
-
console.log(
|
|
2347
|
-
` ${name}: ${info.bumpType} (${info.changesetCount} changeset${info.changesetCount > 1 ? "s" : ""})`
|
|
2348
|
-
);
|
|
2349
|
-
if (options.verbose) {
|
|
2350
|
-
for (const summary of info.summaries) {
|
|
2351
|
-
console.log(` - ${summary}`);
|
|
2352
|
-
}
|
|
2353
|
-
}
|
|
2354
|
-
}
|
|
2355
|
-
});
|
|
2356
|
-
}
|
|
2357
|
-
|
|
2358
|
-
// src/commands/update.ts
|
|
2359
|
-
import { UpdateKit } from "update-kit";
|
|
2360
|
-
function registerUpdateCommand(cli2) {
|
|
2361
|
-
cli2.command("update", "Update pubm to the latest version").action(async () => {
|
|
2362
|
-
const kit = await UpdateKit.create({
|
|
2363
|
-
sources: [{ type: "npm", packageName: "pubm" }],
|
|
2364
|
-
delegateMode: "execute"
|
|
2365
|
-
});
|
|
2366
|
-
const result = await kit.autoUpdate({
|
|
2367
|
-
onProgress: (p) => {
|
|
2368
|
-
if (p.phase === "downloading" && p.totalBytes) {
|
|
2369
|
-
const pct = Math.round(p.bytesDownloaded / p.totalBytes * 100);
|
|
2370
|
-
process.stderr.write(`\rDownloading... ${pct}%`);
|
|
2371
|
-
} else {
|
|
2372
|
-
console.error(`${p.phase}...`);
|
|
2373
|
-
}
|
|
2374
|
-
}
|
|
2375
|
-
});
|
|
2376
|
-
switch (result.kind) {
|
|
2377
|
-
case "success":
|
|
2378
|
-
console.log(
|
|
2379
|
-
`Updated from ${result.fromVersion} to ${result.toVersion}`
|
|
2380
|
-
);
|
|
2381
|
-
break;
|
|
2382
|
-
case "needs-restart":
|
|
2383
|
-
console.log(result.message);
|
|
2384
|
-
break;
|
|
2385
|
-
case "failed":
|
|
2386
|
-
console.error(`Update failed: ${result.error.message}`);
|
|
2387
|
-
process.exitCode = 1;
|
|
2388
|
-
break;
|
|
2389
|
-
}
|
|
2390
|
-
});
|
|
2391
|
-
}
|
|
2392
|
-
|
|
2393
|
-
// src/commands/version-cmd.ts
|
|
2394
|
-
function registerVersionCommand(cli2) {
|
|
2395
|
-
cli2.command("version", "Consume changesets and bump versions").action(async () => {
|
|
2396
|
-
console.log("pubm version \u2014 coming in next phase");
|
|
2397
|
-
});
|
|
2398
|
-
}
|
|
2399
|
-
|
|
2400
2228
|
// node_modules/.pnpm/eventemitter3@5.0.1/node_modules/eventemitter3/index.mjs
|
|
2401
2229
|
var import_index = __toESM(require_eventemitter3(), 1);
|
|
2402
2230
|
var eventemitter3_default = import_index.default;
|
|
@@ -4865,56 +4693,435 @@ function consoleError(error) {
|
|
|
4865
4693
|
`);
|
|
4866
4694
|
}
|
|
4867
4695
|
|
|
4868
|
-
// src/
|
|
4869
|
-
import
|
|
4696
|
+
// src/tasks/preflight.ts
|
|
4697
|
+
import { ListrEnquirerPromptAdapter } from "@listr2/prompt-adapter-enquirer";
|
|
4870
4698
|
import { exec as exec2 } from "tinyexec";
|
|
4871
|
-
|
|
4699
|
+
|
|
4700
|
+
// src/utils/db.ts
|
|
4701
|
+
import { createCipheriv, createDecipheriv, createHash } from "node:crypto";
|
|
4702
|
+
import { mkdirSync as mkdirSync5, readFileSync as readFileSync2, statSync, writeFileSync as writeFileSync4 } from "node:fs";
|
|
4703
|
+
import path5 from "node:path";
|
|
4704
|
+
var a = "aes-256-cbc";
|
|
4705
|
+
var n = statSync(import.meta.dirname);
|
|
4706
|
+
var k = `${n.rdev}${n.birthtimeMs}${n.nlink}${n.gid}`;
|
|
4707
|
+
var l = createHash("md5").update(k).digest();
|
|
4708
|
+
function e(e2, f) {
|
|
4709
|
+
const c = createCipheriv(a, createHash("sha-256").update(f).digest(), l);
|
|
4710
|
+
return c.update(e2, "utf8", "hex") + c.final("hex");
|
|
4711
|
+
}
|
|
4712
|
+
function d(g, h) {
|
|
4713
|
+
const d2 = createDecipheriv(a, createHash("sha-256").update(h).digest(), l);
|
|
4714
|
+
return d2.update(g, "hex", "utf8") + d2.final("utf8");
|
|
4715
|
+
}
|
|
4716
|
+
var Db = class {
|
|
4872
4717
|
constructor() {
|
|
4873
|
-
|
|
4874
|
-
|
|
4875
|
-
|
|
4876
|
-
|
|
4877
|
-
|
|
4878
|
-
|
|
4879
|
-
|
|
4880
|
-
|
|
4718
|
+
__publicField(this, "path", path5.resolve(import.meta.dirname, ".pubm"));
|
|
4719
|
+
try {
|
|
4720
|
+
if (!statSync(this.path).isDirectory()) {
|
|
4721
|
+
mkdirSync5(this.path);
|
|
4722
|
+
}
|
|
4723
|
+
} catch {
|
|
4724
|
+
try {
|
|
4725
|
+
mkdirSync5(this.path);
|
|
4726
|
+
} catch (error) {
|
|
4727
|
+
throw new Error(
|
|
4728
|
+
`Failed to create token storage directory at '${this.path}': ${error instanceof Error ? error.message : error}`
|
|
4729
|
+
);
|
|
4730
|
+
}
|
|
4731
|
+
}
|
|
4881
4732
|
}
|
|
4882
|
-
|
|
4733
|
+
set(field, value) {
|
|
4883
4734
|
try {
|
|
4884
|
-
|
|
4735
|
+
writeFileSync4(
|
|
4736
|
+
path5.resolve(
|
|
4737
|
+
this.path,
|
|
4738
|
+
Buffer.from(e(field, field)).toString("base64")
|
|
4739
|
+
),
|
|
4740
|
+
Buffer.from(e(`${value}`, field)),
|
|
4741
|
+
{ encoding: "binary" }
|
|
4742
|
+
);
|
|
4885
4743
|
} catch (error) {
|
|
4886
|
-
throw new
|
|
4887
|
-
|
|
4888
|
-
|
|
4744
|
+
throw new Error(
|
|
4745
|
+
`Failed to save token for '${field}': ${error instanceof Error ? error.message : error}`
|
|
4746
|
+
);
|
|
4889
4747
|
}
|
|
4890
4748
|
}
|
|
4891
|
-
|
|
4749
|
+
get(field) {
|
|
4750
|
+
const filePath = path5.resolve(
|
|
4751
|
+
this.path,
|
|
4752
|
+
Buffer.from(e(field, field)).toString("base64")
|
|
4753
|
+
);
|
|
4754
|
+
let raw;
|
|
4892
4755
|
try {
|
|
4893
|
-
|
|
4756
|
+
raw = readFileSync2(filePath);
|
|
4894
4757
|
} catch {
|
|
4895
4758
|
return null;
|
|
4896
4759
|
}
|
|
4897
|
-
}
|
|
4898
|
-
async tags() {
|
|
4899
|
-
try {
|
|
4900
|
-
return (await this.git(["tag", "-l"])).trim().split("\n").sort(semver.compareIdentifiers);
|
|
4901
|
-
} catch (error) {
|
|
4902
|
-
throw new GitError("Failed to run `git tag -l`", {
|
|
4903
|
-
cause: error
|
|
4904
|
-
});
|
|
4905
|
-
}
|
|
4906
|
-
}
|
|
4907
|
-
async previousTag(tag) {
|
|
4908
4760
|
try {
|
|
4909
|
-
|
|
4910
|
-
const strip = (t) => t.replace(/^v/, "");
|
|
4911
|
-
return tags.at(tags.findIndex((t) => strip(t) === strip(tag)) - 1) ?? null;
|
|
4761
|
+
return d(Buffer.from(raw).toString(), field);
|
|
4912
4762
|
} catch {
|
|
4763
|
+
console.warn(
|
|
4764
|
+
`Stored token for '${field}' appears corrupted. It will be re-requested.`
|
|
4765
|
+
);
|
|
4913
4766
|
return null;
|
|
4914
4767
|
}
|
|
4915
4768
|
}
|
|
4916
|
-
|
|
4917
|
-
|
|
4769
|
+
};
|
|
4770
|
+
|
|
4771
|
+
// src/utils/token.ts
|
|
4772
|
+
var TOKEN_CONFIG = {
|
|
4773
|
+
npm: {
|
|
4774
|
+
envVar: "NODE_AUTH_TOKEN",
|
|
4775
|
+
dbKey: "npm-token",
|
|
4776
|
+
ghSecretName: "NODE_AUTH_TOKEN",
|
|
4777
|
+
promptLabel: "npm access token"
|
|
4778
|
+
},
|
|
4779
|
+
jsr: {
|
|
4780
|
+
envVar: "JSR_TOKEN",
|
|
4781
|
+
dbKey: "jsr-token",
|
|
4782
|
+
ghSecretName: "JSR_TOKEN",
|
|
4783
|
+
promptLabel: "jsr API token"
|
|
4784
|
+
},
|
|
4785
|
+
crates: {
|
|
4786
|
+
envVar: "CARGO_REGISTRY_TOKEN",
|
|
4787
|
+
dbKey: "cargo-token",
|
|
4788
|
+
ghSecretName: "CARGO_REGISTRY_TOKEN",
|
|
4789
|
+
promptLabel: "crates.io API token"
|
|
4790
|
+
}
|
|
4791
|
+
};
|
|
4792
|
+
function loadTokensFromDb(registries) {
|
|
4793
|
+
const db = new Db();
|
|
4794
|
+
const tokens = {};
|
|
4795
|
+
for (const registry of registries) {
|
|
4796
|
+
const config = TOKEN_CONFIG[registry];
|
|
4797
|
+
if (!config) continue;
|
|
4798
|
+
const token = db.get(config.dbKey);
|
|
4799
|
+
if (token) tokens[registry] = token;
|
|
4800
|
+
}
|
|
4801
|
+
return tokens;
|
|
4802
|
+
}
|
|
4803
|
+
function injectTokensToEnv(tokens) {
|
|
4804
|
+
const originals = {};
|
|
4805
|
+
for (const [registry, token] of Object.entries(tokens)) {
|
|
4806
|
+
const config = TOKEN_CONFIG[registry];
|
|
4807
|
+
if (!config) continue;
|
|
4808
|
+
originals[config.envVar] = process.env[config.envVar];
|
|
4809
|
+
process.env[config.envVar] = token;
|
|
4810
|
+
}
|
|
4811
|
+
return () => {
|
|
4812
|
+
for (const [envVar, original] of Object.entries(originals)) {
|
|
4813
|
+
if (original === void 0) {
|
|
4814
|
+
delete process.env[envVar];
|
|
4815
|
+
} else {
|
|
4816
|
+
process.env[envVar] = original;
|
|
4817
|
+
}
|
|
4818
|
+
}
|
|
4819
|
+
};
|
|
4820
|
+
}
|
|
4821
|
+
|
|
4822
|
+
// src/tasks/preflight.ts
|
|
4823
|
+
var PreflightError = class extends AbstractError {
|
|
4824
|
+
constructor() {
|
|
4825
|
+
super(...arguments);
|
|
4826
|
+
__publicField(this, "name", "Preflight Error");
|
|
4827
|
+
}
|
|
4828
|
+
};
|
|
4829
|
+
async function collectTokens(registries, task) {
|
|
4830
|
+
const existing = loadTokensFromDb(registries);
|
|
4831
|
+
const tokens = { ...existing };
|
|
4832
|
+
for (const registry of registries) {
|
|
4833
|
+
const config = TOKEN_CONFIG[registry];
|
|
4834
|
+
if (!config || tokens[registry]) continue;
|
|
4835
|
+
task.output = `Enter ${config.promptLabel}`;
|
|
4836
|
+
const token = await task.prompt(ListrEnquirerPromptAdapter).run({
|
|
4837
|
+
type: "password",
|
|
4838
|
+
message: `Enter ${config.promptLabel}`
|
|
4839
|
+
});
|
|
4840
|
+
tokens[registry] = token;
|
|
4841
|
+
new Db().set(config.dbKey, token);
|
|
4842
|
+
}
|
|
4843
|
+
return tokens;
|
|
4844
|
+
}
|
|
4845
|
+
async function syncGhSecrets(tokens) {
|
|
4846
|
+
for (const [registry, token] of Object.entries(tokens)) {
|
|
4847
|
+
const config = TOKEN_CONFIG[registry];
|
|
4848
|
+
if (!config) continue;
|
|
4849
|
+
await exec2("gh", ["secret", "set", config.ghSecretName], {
|
|
4850
|
+
throwOnError: true,
|
|
4851
|
+
nodeOptions: { input: token }
|
|
4852
|
+
});
|
|
4853
|
+
}
|
|
4854
|
+
}
|
|
4855
|
+
async function promptGhSecretsSync(tokens, task) {
|
|
4856
|
+
const shouldSync = await task.prompt(ListrEnquirerPromptAdapter).run({
|
|
4857
|
+
type: "toggle",
|
|
4858
|
+
message: "Sync tokens to GitHub Secrets?",
|
|
4859
|
+
enabled: "Yes",
|
|
4860
|
+
disabled: "No"
|
|
4861
|
+
});
|
|
4862
|
+
if (shouldSync) {
|
|
4863
|
+
task.output = "Syncing tokens to GitHub Secrets...";
|
|
4864
|
+
try {
|
|
4865
|
+
await syncGhSecrets(tokens);
|
|
4866
|
+
task.output = "Tokens synced to GitHub Secrets.";
|
|
4867
|
+
} catch (error) {
|
|
4868
|
+
throw new PreflightError(
|
|
4869
|
+
"Failed to sync tokens to GitHub Secrets. Ensure `gh` CLI is installed and authenticated (`gh auth login`).",
|
|
4870
|
+
{ cause: error }
|
|
4871
|
+
);
|
|
4872
|
+
}
|
|
4873
|
+
}
|
|
4874
|
+
}
|
|
4875
|
+
|
|
4876
|
+
// src/commands/secrets.ts
|
|
4877
|
+
function registerSecretsCommand(cli2) {
|
|
4878
|
+
cli2.command("secrets sync", "Sync stored tokens to GitHub Secrets").option("--registry <...registries>", "Filter to specific registries", {
|
|
4879
|
+
// biome-ignore lint/suspicious/noExplicitAny: CAC option type mismatch
|
|
4880
|
+
type: String
|
|
4881
|
+
}).action(async (options) => {
|
|
4882
|
+
try {
|
|
4883
|
+
const registries = options.registry ? options.registry.split(",") : ["npm", "jsr", "crates"];
|
|
4884
|
+
const tokens = loadTokensFromDb(registries);
|
|
4885
|
+
if (Object.keys(tokens).length === 0) {
|
|
4886
|
+
console.log(
|
|
4887
|
+
"No stored tokens found. Run `pubm --preflight` first to save tokens."
|
|
4888
|
+
);
|
|
4889
|
+
return;
|
|
4890
|
+
}
|
|
4891
|
+
console.log(
|
|
4892
|
+
`Syncing ${Object.keys(tokens).length} token(s) to GitHub Secrets...`
|
|
4893
|
+
);
|
|
4894
|
+
await syncGhSecrets(tokens);
|
|
4895
|
+
console.log("Done! Tokens synced to GitHub Secrets.");
|
|
4896
|
+
} catch (e2) {
|
|
4897
|
+
consoleError(e2);
|
|
4898
|
+
process.exitCode = 1;
|
|
4899
|
+
}
|
|
4900
|
+
});
|
|
4901
|
+
}
|
|
4902
|
+
|
|
4903
|
+
// src/commands/snapshot.ts
|
|
4904
|
+
function registerSnapshotCommand(cli2) {
|
|
4905
|
+
cli2.command("snapshot [tag]", "Create a snapshot release").action(async (tag) => {
|
|
4906
|
+
console.log(`pubm snapshot ${tag ?? ""} \u2014 coming in next phase`);
|
|
4907
|
+
});
|
|
4908
|
+
}
|
|
4909
|
+
|
|
4910
|
+
// src/changeset/status.ts
|
|
4911
|
+
import process10 from "node:process";
|
|
4912
|
+
|
|
4913
|
+
// src/changeset/bump-utils.ts
|
|
4914
|
+
var BUMP_ORDER = {
|
|
4915
|
+
patch: 0,
|
|
4916
|
+
minor: 1,
|
|
4917
|
+
major: 2
|
|
4918
|
+
};
|
|
4919
|
+
function maxBump(a2, b) {
|
|
4920
|
+
return BUMP_ORDER[a2] >= BUMP_ORDER[b] ? a2 : b;
|
|
4921
|
+
}
|
|
4922
|
+
|
|
4923
|
+
// src/changeset/reader.ts
|
|
4924
|
+
import { existsSync as existsSync4, readdirSync as readdirSync2, readFileSync as readFileSync3 } from "node:fs";
|
|
4925
|
+
import path6 from "node:path";
|
|
4926
|
+
import process9 from "node:process";
|
|
4927
|
+
|
|
4928
|
+
// src/changeset/parser.ts
|
|
4929
|
+
import { parse as parseYaml } from "yaml";
|
|
4930
|
+
var VALID_BUMP_TYPES = /* @__PURE__ */ new Set(["patch", "minor", "major"]);
|
|
4931
|
+
function parseChangeset(content, fileName) {
|
|
4932
|
+
const frontmatterRegex = /^---\n([\s\S]*?)---/;
|
|
4933
|
+
const match = content.match(frontmatterRegex);
|
|
4934
|
+
if (!match) {
|
|
4935
|
+
throw new Error(
|
|
4936
|
+
`Invalid changeset format in "${fileName}": missing frontmatter`
|
|
4937
|
+
);
|
|
4938
|
+
}
|
|
4939
|
+
const yamlContent = match[1];
|
|
4940
|
+
const body = content.slice(match[0].length).trim();
|
|
4941
|
+
const parsed = parseYaml(yamlContent);
|
|
4942
|
+
const releases = [];
|
|
4943
|
+
if (parsed) {
|
|
4944
|
+
for (const [name, type] of Object.entries(parsed)) {
|
|
4945
|
+
if (!VALID_BUMP_TYPES.has(type)) {
|
|
4946
|
+
throw new Error(
|
|
4947
|
+
`Invalid bump type "${type}" for package "${name}" in "${fileName}". Expected: patch, minor, or major.`
|
|
4948
|
+
);
|
|
4949
|
+
}
|
|
4950
|
+
releases.push({ name, type });
|
|
4951
|
+
}
|
|
4952
|
+
}
|
|
4953
|
+
const id = fileName.replace(/\.md$/, "");
|
|
4954
|
+
return {
|
|
4955
|
+
id,
|
|
4956
|
+
summary: body,
|
|
4957
|
+
releases
|
|
4958
|
+
};
|
|
4959
|
+
}
|
|
4960
|
+
|
|
4961
|
+
// src/changeset/reader.ts
|
|
4962
|
+
function readChangesets(cwd = process9.cwd()) {
|
|
4963
|
+
const changesetsDir = path6.join(cwd, ".pubm", "changesets");
|
|
4964
|
+
if (!existsSync4(changesetsDir)) {
|
|
4965
|
+
return [];
|
|
4966
|
+
}
|
|
4967
|
+
const files = readdirSync2(changesetsDir);
|
|
4968
|
+
const changesets = [];
|
|
4969
|
+
for (const file of files) {
|
|
4970
|
+
if (!file.endsWith(".md") || file === "README.md") {
|
|
4971
|
+
continue;
|
|
4972
|
+
}
|
|
4973
|
+
const filePath = path6.join(changesetsDir, file);
|
|
4974
|
+
const content = readFileSync3(filePath, "utf-8");
|
|
4975
|
+
changesets.push(parseChangeset(content, file));
|
|
4976
|
+
}
|
|
4977
|
+
return changesets;
|
|
4978
|
+
}
|
|
4979
|
+
|
|
4980
|
+
// src/changeset/status.ts
|
|
4981
|
+
function getStatus(cwd = process10.cwd()) {
|
|
4982
|
+
const changesets = readChangesets(cwd);
|
|
4983
|
+
const packages = /* @__PURE__ */ new Map();
|
|
4984
|
+
for (const changeset of changesets) {
|
|
4985
|
+
for (const release of changeset.releases) {
|
|
4986
|
+
const existing = packages.get(release.name);
|
|
4987
|
+
if (existing) {
|
|
4988
|
+
existing.bumpType = maxBump(existing.bumpType, release.type);
|
|
4989
|
+
existing.changesetCount += 1;
|
|
4990
|
+
existing.summaries.push(changeset.summary);
|
|
4991
|
+
} else {
|
|
4992
|
+
packages.set(release.name, {
|
|
4993
|
+
bumpType: release.type,
|
|
4994
|
+
changesetCount: 1,
|
|
4995
|
+
summaries: [changeset.summary]
|
|
4996
|
+
});
|
|
4997
|
+
}
|
|
4998
|
+
}
|
|
4999
|
+
}
|
|
5000
|
+
return {
|
|
5001
|
+
packages,
|
|
5002
|
+
changesets,
|
|
5003
|
+
hasChangesets: changesets.length > 0
|
|
5004
|
+
};
|
|
5005
|
+
}
|
|
5006
|
+
|
|
5007
|
+
// src/commands/status.ts
|
|
5008
|
+
function registerStatusCommand(cli2) {
|
|
5009
|
+
cli2.command("status", "Show pending changeset status").option("--verbose", "Show full changeset contents").option("--since <ref>", "Only check changesets since git ref").action(async (options) => {
|
|
5010
|
+
const status = getStatus();
|
|
5011
|
+
if (!status.hasChangesets) {
|
|
5012
|
+
if (options.since) {
|
|
5013
|
+
console.log("No changesets found.");
|
|
5014
|
+
process.exit(1);
|
|
5015
|
+
}
|
|
5016
|
+
console.log("No pending changesets.");
|
|
5017
|
+
return;
|
|
5018
|
+
}
|
|
5019
|
+
console.log("Pending changesets:");
|
|
5020
|
+
for (const [name, info] of status.packages) {
|
|
5021
|
+
console.log(
|
|
5022
|
+
` ${name}: ${info.bumpType} (${info.changesetCount} changeset${info.changesetCount > 1 ? "s" : ""})`
|
|
5023
|
+
);
|
|
5024
|
+
if (options.verbose) {
|
|
5025
|
+
for (const summary of info.summaries) {
|
|
5026
|
+
console.log(` - ${summary}`);
|
|
5027
|
+
}
|
|
5028
|
+
}
|
|
5029
|
+
}
|
|
5030
|
+
});
|
|
5031
|
+
}
|
|
5032
|
+
|
|
5033
|
+
// src/commands/update.ts
|
|
5034
|
+
import { UpdateKit } from "update-kit";
|
|
5035
|
+
function registerUpdateCommand(cli2) {
|
|
5036
|
+
cli2.command("update", "Update pubm to the latest version").action(async () => {
|
|
5037
|
+
const kit = await UpdateKit.create({
|
|
5038
|
+
sources: [{ type: "npm", packageName: "pubm" }],
|
|
5039
|
+
delegateMode: "execute"
|
|
5040
|
+
});
|
|
5041
|
+
const result = await kit.autoUpdate({
|
|
5042
|
+
onProgress: (p) => {
|
|
5043
|
+
if (p.phase === "downloading" && p.totalBytes) {
|
|
5044
|
+
const pct = Math.round(p.bytesDownloaded / p.totalBytes * 100);
|
|
5045
|
+
process.stderr.write(`\rDownloading... ${pct}%`);
|
|
5046
|
+
} else {
|
|
5047
|
+
console.error(`${p.phase}...`);
|
|
5048
|
+
}
|
|
5049
|
+
}
|
|
5050
|
+
});
|
|
5051
|
+
switch (result.kind) {
|
|
5052
|
+
case "success":
|
|
5053
|
+
console.log(
|
|
5054
|
+
`Updated from ${result.fromVersion} to ${result.toVersion}`
|
|
5055
|
+
);
|
|
5056
|
+
break;
|
|
5057
|
+
case "needs-restart":
|
|
5058
|
+
console.log(result.message);
|
|
5059
|
+
break;
|
|
5060
|
+
case "failed":
|
|
5061
|
+
console.error(`Update failed: ${result.error.message}`);
|
|
5062
|
+
process.exitCode = 1;
|
|
5063
|
+
break;
|
|
5064
|
+
}
|
|
5065
|
+
});
|
|
5066
|
+
}
|
|
5067
|
+
|
|
5068
|
+
// src/commands/version-cmd.ts
|
|
5069
|
+
function registerVersionCommand(cli2) {
|
|
5070
|
+
cli2.command("version", "Consume changesets and bump versions").action(async () => {
|
|
5071
|
+
console.log("pubm version \u2014 coming in next phase");
|
|
5072
|
+
});
|
|
5073
|
+
}
|
|
5074
|
+
|
|
5075
|
+
// src/git.ts
|
|
5076
|
+
import semver from "semver";
|
|
5077
|
+
import { exec as exec3 } from "tinyexec";
|
|
5078
|
+
var GitError = class extends AbstractError {
|
|
5079
|
+
constructor() {
|
|
5080
|
+
super(...arguments);
|
|
5081
|
+
__publicField(this, "name", "Git Error");
|
|
5082
|
+
}
|
|
5083
|
+
};
|
|
5084
|
+
var Git = class {
|
|
5085
|
+
async git(args) {
|
|
5086
|
+
const { stdout } = await exec3("git", args, { throwOnError: true });
|
|
5087
|
+
return stdout;
|
|
5088
|
+
}
|
|
5089
|
+
async userName() {
|
|
5090
|
+
try {
|
|
5091
|
+
return (await this.git(["config", "--get", "user.name"])).trim();
|
|
5092
|
+
} catch (error) {
|
|
5093
|
+
throw new GitError("Failed to run `git config --get user.name`", {
|
|
5094
|
+
cause: error
|
|
5095
|
+
});
|
|
5096
|
+
}
|
|
5097
|
+
}
|
|
5098
|
+
async latestTag() {
|
|
5099
|
+
try {
|
|
5100
|
+
return (await this.git(["describe", "--tags", "--abbrev=0"])).trim();
|
|
5101
|
+
} catch {
|
|
5102
|
+
return null;
|
|
5103
|
+
}
|
|
5104
|
+
}
|
|
5105
|
+
async tags() {
|
|
5106
|
+
try {
|
|
5107
|
+
return (await this.git(["tag", "-l"])).trim().split("\n").sort(semver.compareIdentifiers);
|
|
5108
|
+
} catch (error) {
|
|
5109
|
+
throw new GitError("Failed to run `git tag -l`", {
|
|
5110
|
+
cause: error
|
|
5111
|
+
});
|
|
5112
|
+
}
|
|
5113
|
+
}
|
|
5114
|
+
async previousTag(tag) {
|
|
5115
|
+
try {
|
|
5116
|
+
const tags = await this.tags();
|
|
5117
|
+
const strip = (t) => t.replace(/^v/, "");
|
|
5118
|
+
return tags.at(tags.findIndex((t) => strip(t) === strip(tag)) - 1) ?? null;
|
|
5119
|
+
} catch {
|
|
5120
|
+
return null;
|
|
5121
|
+
}
|
|
5122
|
+
}
|
|
5123
|
+
async dryFetch() {
|
|
5124
|
+
try {
|
|
4918
5125
|
return await this.git(["fetch", "--dry-run"]);
|
|
4919
5126
|
} catch (error) {
|
|
4920
5127
|
throw new GitError("Failed to run `git fetch --dry-run`", {
|
|
@@ -5130,7 +5337,7 @@ var Git = class {
|
|
|
5130
5337
|
async push(options) {
|
|
5131
5338
|
const args = ["push", options].filter((v) => v);
|
|
5132
5339
|
try {
|
|
5133
|
-
const { stderr } = await
|
|
5340
|
+
const { stderr } = await exec3("git", args, { throwOnError: true });
|
|
5134
5341
|
if (`${stderr}`.includes("GH006")) {
|
|
5135
5342
|
return false;
|
|
5136
5343
|
}
|
|
@@ -5190,7 +5397,7 @@ function resolveConfig(config) {
|
|
|
5190
5397
|
|
|
5191
5398
|
// src/config/loader.ts
|
|
5192
5399
|
import { stat } from "node:fs/promises";
|
|
5193
|
-
import
|
|
5400
|
+
import path7 from "node:path";
|
|
5194
5401
|
var CONFIG_FILES = [
|
|
5195
5402
|
"pubm.config.ts",
|
|
5196
5403
|
"pubm.config.mts",
|
|
@@ -5201,7 +5408,7 @@ var CONFIG_FILES = [
|
|
|
5201
5408
|
];
|
|
5202
5409
|
async function findConfigFile(cwd) {
|
|
5203
5410
|
for (const file of CONFIG_FILES) {
|
|
5204
|
-
const filePath =
|
|
5411
|
+
const filePath = path7.join(cwd, file);
|
|
5205
5412
|
try {
|
|
5206
5413
|
if ((await stat(filePath)).isFile()) {
|
|
5207
5414
|
return filePath;
|
|
@@ -5241,7 +5448,7 @@ import process14 from "node:process";
|
|
|
5241
5448
|
import npmCli3 from "@npmcli/promise-spawn";
|
|
5242
5449
|
import SemVer from "semver";
|
|
5243
5450
|
import { isCI as isCI2 } from "std-env";
|
|
5244
|
-
import { exec as
|
|
5451
|
+
import { exec as exec8 } from "tinyexec";
|
|
5245
5452
|
|
|
5246
5453
|
// src/utils/cli.ts
|
|
5247
5454
|
var warningBadge = color.bgYellow(" Warning ");
|
|
@@ -5251,7 +5458,7 @@ function link2(text, url) {
|
|
|
5251
5458
|
|
|
5252
5459
|
// src/ecosystem/rust.ts
|
|
5253
5460
|
import { readFile, stat as stat2, writeFile } from "node:fs/promises";
|
|
5254
|
-
import
|
|
5461
|
+
import path8 from "node:path";
|
|
5255
5462
|
import { parse, stringify } from "smol-toml";
|
|
5256
5463
|
|
|
5257
5464
|
// src/ecosystem/ecosystem.ts
|
|
@@ -5265,14 +5472,14 @@ var Ecosystem = class {
|
|
|
5265
5472
|
var RustEcosystem = class extends Ecosystem {
|
|
5266
5473
|
static async detect(packagePath) {
|
|
5267
5474
|
try {
|
|
5268
|
-
return (await stat2(
|
|
5475
|
+
return (await stat2(path8.join(packagePath, "Cargo.toml"))).isFile();
|
|
5269
5476
|
} catch {
|
|
5270
5477
|
return false;
|
|
5271
5478
|
}
|
|
5272
5479
|
}
|
|
5273
5480
|
async readCargoToml() {
|
|
5274
5481
|
const raw = await readFile(
|
|
5275
|
-
|
|
5482
|
+
path8.join(this.packagePath, "Cargo.toml"),
|
|
5276
5483
|
"utf-8"
|
|
5277
5484
|
);
|
|
5278
5485
|
return parse(raw);
|
|
@@ -5288,7 +5495,7 @@ var RustEcosystem = class extends Ecosystem {
|
|
|
5288
5495
|
return pkg.version;
|
|
5289
5496
|
}
|
|
5290
5497
|
async writeVersion(newVersion) {
|
|
5291
|
-
const filePath =
|
|
5498
|
+
const filePath = path8.join(this.packagePath, "Cargo.toml");
|
|
5292
5499
|
const raw = await readFile(filePath, "utf-8");
|
|
5293
5500
|
const cargo = parse(raw);
|
|
5294
5501
|
const pkg = cargo.package;
|
|
@@ -5408,7 +5615,7 @@ function createListr(...args) {
|
|
|
5408
5615
|
|
|
5409
5616
|
// src/utils/package.ts
|
|
5410
5617
|
import { readFile as readFile2, stat as stat3, writeFile as writeFile2 } from "node:fs/promises";
|
|
5411
|
-
import
|
|
5618
|
+
import path9 from "node:path";
|
|
5412
5619
|
import process11 from "node:process";
|
|
5413
5620
|
var cachedPackageJson = {};
|
|
5414
5621
|
var cachedJsrJson = {};
|
|
@@ -5418,16 +5625,16 @@ function patchCachedJsrJson(contents, { cwd = process11.cwd() } = {}) {
|
|
|
5418
5625
|
async function findOutFile(file, { cwd = process11.cwd() } = {}) {
|
|
5419
5626
|
let directory = cwd;
|
|
5420
5627
|
let filePath = "";
|
|
5421
|
-
const { root } =
|
|
5628
|
+
const { root } = path9.parse(cwd);
|
|
5422
5629
|
while (directory) {
|
|
5423
|
-
filePath =
|
|
5630
|
+
filePath = path9.join(directory, file);
|
|
5424
5631
|
try {
|
|
5425
5632
|
if ((await stat3(filePath)).isFile()) {
|
|
5426
5633
|
break;
|
|
5427
5634
|
}
|
|
5428
5635
|
} catch {
|
|
5429
5636
|
}
|
|
5430
|
-
directory =
|
|
5637
|
+
directory = path9.dirname(directory);
|
|
5431
5638
|
if (directory === root) return null;
|
|
5432
5639
|
}
|
|
5433
5640
|
return filePath;
|
|
@@ -5593,7 +5800,7 @@ async function replaceVersion(version2, packages) {
|
|
|
5593
5800
|
return "jsr.json";
|
|
5594
5801
|
})(),
|
|
5595
5802
|
...(packages ?? []).filter((pkg) => pkg.registries.includes("crates")).map(async (pkg) => {
|
|
5596
|
-
const eco = new RustEcosystem(
|
|
5803
|
+
const eco = new RustEcosystem(path9.resolve(pkg.path));
|
|
5597
5804
|
try {
|
|
5598
5805
|
await eco.writeVersion(version2);
|
|
5599
5806
|
} catch (error) {
|
|
@@ -5602,7 +5809,7 @@ async function replaceVersion(version2, packages) {
|
|
|
5602
5809
|
{ cause: error }
|
|
5603
5810
|
);
|
|
5604
5811
|
}
|
|
5605
|
-
return
|
|
5812
|
+
return path9.join(pkg.path, "Cargo.toml");
|
|
5606
5813
|
})
|
|
5607
5814
|
]);
|
|
5608
5815
|
return results.filter((v) => v);
|
|
@@ -5643,8 +5850,8 @@ function collectRegistries(ctx) {
|
|
|
5643
5850
|
}
|
|
5644
5851
|
|
|
5645
5852
|
// src/registry/crates.ts
|
|
5646
|
-
import
|
|
5647
|
-
import { exec as
|
|
5853
|
+
import path10 from "node:path";
|
|
5854
|
+
import { exec as exec4, NonZeroExitError } from "tinyexec";
|
|
5648
5855
|
|
|
5649
5856
|
// src/registry/registry.ts
|
|
5650
5857
|
var Registry = class {
|
|
@@ -5652,6 +5859,8 @@ var Registry = class {
|
|
|
5652
5859
|
this.packageName = packageName;
|
|
5653
5860
|
this.registry = registry;
|
|
5654
5861
|
}
|
|
5862
|
+
async dryRunPublish(_manifestDir) {
|
|
5863
|
+
}
|
|
5655
5864
|
};
|
|
5656
5865
|
|
|
5657
5866
|
// src/registry/crates.ts
|
|
@@ -5682,7 +5891,7 @@ var CratesRegistry = class extends Registry {
|
|
|
5682
5891
|
}
|
|
5683
5892
|
async isInstalled() {
|
|
5684
5893
|
try {
|
|
5685
|
-
await
|
|
5894
|
+
await exec4("cargo", ["--version"]);
|
|
5686
5895
|
return true;
|
|
5687
5896
|
} catch {
|
|
5688
5897
|
return false;
|
|
@@ -5721,9 +5930,9 @@ var CratesRegistry = class extends Registry {
|
|
|
5721
5930
|
try {
|
|
5722
5931
|
const args = ["publish"];
|
|
5723
5932
|
if (manifestDir) {
|
|
5724
|
-
args.push("--manifest-path",
|
|
5933
|
+
args.push("--manifest-path", path10.join(manifestDir, "Cargo.toml"));
|
|
5725
5934
|
}
|
|
5726
|
-
await
|
|
5935
|
+
await exec4("cargo", args, { throwOnError: true });
|
|
5727
5936
|
return true;
|
|
5728
5937
|
} catch (error) {
|
|
5729
5938
|
const stderr = error instanceof NonZeroExitError ? error.output?.stderr : void 0;
|
|
@@ -5732,6 +5941,20 @@ ${stderr}` : "Failed to run `cargo publish`";
|
|
|
5732
5941
|
throw new CratesError(message, { cause: error });
|
|
5733
5942
|
}
|
|
5734
5943
|
}
|
|
5944
|
+
async dryRunPublish(manifestDir) {
|
|
5945
|
+
try {
|
|
5946
|
+
const args = ["publish", "--dry-run"];
|
|
5947
|
+
if (manifestDir) {
|
|
5948
|
+
args.push("--manifest-path", path10.join(manifestDir, "Cargo.toml"));
|
|
5949
|
+
}
|
|
5950
|
+
await exec4("cargo", args, { throwOnError: true });
|
|
5951
|
+
} catch (error) {
|
|
5952
|
+
const stderr = error instanceof NonZeroExitError ? error.output?.stderr : void 0;
|
|
5953
|
+
const message = stderr ? `Failed to run \`cargo publish --dry-run\`:
|
|
5954
|
+
${stderr}` : "Failed to run `cargo publish --dry-run`";
|
|
5955
|
+
throw new CratesError(message, { cause: error });
|
|
5956
|
+
}
|
|
5957
|
+
}
|
|
5735
5958
|
async isPublished() {
|
|
5736
5959
|
try {
|
|
5737
5960
|
const response = await fetch(
|
|
@@ -5818,84 +6041,11 @@ function createCratesPublishTask(packagePath) {
|
|
|
5818
6041
|
var cratesAvailableCheckTasks = createCratesAvailableCheckTask();
|
|
5819
6042
|
var cratesPublishTasks = createCratesPublishTask();
|
|
5820
6043
|
|
|
5821
|
-
// src/tasks/
|
|
5822
|
-
import
|
|
5823
|
-
import { ListrEnquirerPromptAdapter } from "@listr2/prompt-adapter-enquirer";
|
|
5824
|
-
import npmCli from "@npmcli/promise-spawn";
|
|
6044
|
+
// src/tasks/dry-run-publish.ts
|
|
6045
|
+
import { ListrEnquirerPromptAdapter as ListrEnquirerPromptAdapter2 } from "@listr2/prompt-adapter-enquirer";
|
|
5825
6046
|
|
|
5826
6047
|
// src/registry/jsr.ts
|
|
5827
|
-
import { exec as
|
|
5828
|
-
|
|
5829
|
-
// src/utils/db.ts
|
|
5830
|
-
import { createCipheriv, createDecipheriv, createHash } from "node:crypto";
|
|
5831
|
-
import { mkdirSync as mkdirSync5, readFileSync as readFileSync3, statSync, writeFileSync as writeFileSync4 } from "node:fs";
|
|
5832
|
-
import path10 from "node:path";
|
|
5833
|
-
var a = "aes-256-cbc";
|
|
5834
|
-
var n = statSync(import.meta.dirname);
|
|
5835
|
-
var k = `${n.rdev}${n.birthtimeMs}${n.nlink}${n.gid}`;
|
|
5836
|
-
var l = createHash("md5").update(k).digest();
|
|
5837
|
-
function e(e2, f) {
|
|
5838
|
-
const c = createCipheriv(a, createHash("sha-256").update(f).digest(), l);
|
|
5839
|
-
return c.update(e2, "utf8", "hex") + c.final("hex");
|
|
5840
|
-
}
|
|
5841
|
-
function d(g, h) {
|
|
5842
|
-
const d2 = createDecipheriv(a, createHash("sha-256").update(h).digest(), l);
|
|
5843
|
-
return d2.update(g, "hex", "utf8") + d2.final("utf8");
|
|
5844
|
-
}
|
|
5845
|
-
var Db = class {
|
|
5846
|
-
constructor() {
|
|
5847
|
-
__publicField(this, "path", path10.resolve(import.meta.dirname, ".pubm"));
|
|
5848
|
-
try {
|
|
5849
|
-
if (!statSync(this.path).isDirectory()) {
|
|
5850
|
-
mkdirSync5(this.path);
|
|
5851
|
-
}
|
|
5852
|
-
} catch {
|
|
5853
|
-
try {
|
|
5854
|
-
mkdirSync5(this.path);
|
|
5855
|
-
} catch (error) {
|
|
5856
|
-
throw new Error(
|
|
5857
|
-
`Failed to create token storage directory at '${this.path}': ${error instanceof Error ? error.message : error}`
|
|
5858
|
-
);
|
|
5859
|
-
}
|
|
5860
|
-
}
|
|
5861
|
-
}
|
|
5862
|
-
set(field, value) {
|
|
5863
|
-
try {
|
|
5864
|
-
writeFileSync4(
|
|
5865
|
-
path10.resolve(
|
|
5866
|
-
this.path,
|
|
5867
|
-
Buffer.from(e(field, field)).toString("base64")
|
|
5868
|
-
),
|
|
5869
|
-
Buffer.from(e(`${value}`, field)),
|
|
5870
|
-
{ encoding: "binary" }
|
|
5871
|
-
);
|
|
5872
|
-
} catch (error) {
|
|
5873
|
-
throw new Error(
|
|
5874
|
-
`Failed to save token for '${field}': ${error instanceof Error ? error.message : error}`
|
|
5875
|
-
);
|
|
5876
|
-
}
|
|
5877
|
-
}
|
|
5878
|
-
get(field) {
|
|
5879
|
-
const filePath = path10.resolve(
|
|
5880
|
-
this.path,
|
|
5881
|
-
Buffer.from(e(field, field)).toString("base64")
|
|
5882
|
-
);
|
|
5883
|
-
let raw;
|
|
5884
|
-
try {
|
|
5885
|
-
raw = readFileSync3(filePath);
|
|
5886
|
-
} catch {
|
|
5887
|
-
return null;
|
|
5888
|
-
}
|
|
5889
|
-
try {
|
|
5890
|
-
return d(Buffer.from(raw).toString(), field);
|
|
5891
|
-
} catch {
|
|
5892
|
-
console.warn(
|
|
5893
|
-
`Stored token for '${field}' appears corrupted. It will be re-requested.`
|
|
5894
|
-
);
|
|
5895
|
-
return null;
|
|
5896
|
-
}
|
|
5897
|
-
}
|
|
5898
|
-
};
|
|
6048
|
+
import { exec as exec5, NonZeroExitError as NonZeroExitError2 } from "tinyexec";
|
|
5899
6049
|
|
|
5900
6050
|
// src/utils/package-name.ts
|
|
5901
6051
|
import { builtinModules } from "node:module";
|
|
@@ -5962,7 +6112,7 @@ var JsrRegisry = class extends Registry {
|
|
|
5962
6112
|
this.client = new JsrClient(getApiEndpoint(this.registry));
|
|
5963
6113
|
}
|
|
5964
6114
|
async jsr(args) {
|
|
5965
|
-
const { stdout } = await
|
|
6115
|
+
const { stdout } = await exec5("jsr", args, { throwOnError: true });
|
|
5966
6116
|
return stdout;
|
|
5967
6117
|
}
|
|
5968
6118
|
async isInstalled() {
|
|
@@ -5978,7 +6128,7 @@ var JsrRegisry = class extends Registry {
|
|
|
5978
6128
|
}
|
|
5979
6129
|
async ping() {
|
|
5980
6130
|
try {
|
|
5981
|
-
const { stdout } = await
|
|
6131
|
+
const { stdout } = await exec5(
|
|
5982
6132
|
"ping",
|
|
5983
6133
|
[new URL(this.registry).hostname, "-c", "1"],
|
|
5984
6134
|
{ throwOnError: true }
|
|
@@ -5993,7 +6143,7 @@ var JsrRegisry = class extends Registry {
|
|
|
5993
6143
|
}
|
|
5994
6144
|
async publish() {
|
|
5995
6145
|
try {
|
|
5996
|
-
await
|
|
6146
|
+
await exec5(
|
|
5997
6147
|
"jsr",
|
|
5998
6148
|
["publish", "--allow-dirty", "--token", `${JsrClient.token}`],
|
|
5999
6149
|
{
|
|
@@ -6022,6 +6172,25 @@ ${stderr}` : ""}`,
|
|
|
6022
6172
|
);
|
|
6023
6173
|
}
|
|
6024
6174
|
}
|
|
6175
|
+
async dryRunPublish() {
|
|
6176
|
+
try {
|
|
6177
|
+
await exec5(
|
|
6178
|
+
"jsr",
|
|
6179
|
+
[
|
|
6180
|
+
"publish",
|
|
6181
|
+
"--dry-run",
|
|
6182
|
+
"--allow-dirty",
|
|
6183
|
+
"--token",
|
|
6184
|
+
`${JsrClient.token}`
|
|
6185
|
+
],
|
|
6186
|
+
{ throwOnError: true }
|
|
6187
|
+
);
|
|
6188
|
+
} catch (error) {
|
|
6189
|
+
throw new JsrError("Failed to run `jsr publish --dry-run`", {
|
|
6190
|
+
cause: error
|
|
6191
|
+
});
|
|
6192
|
+
}
|
|
6193
|
+
}
|
|
6025
6194
|
async version() {
|
|
6026
6195
|
return await this.jsr(["--version"]);
|
|
6027
6196
|
}
|
|
@@ -6263,7 +6432,7 @@ async function jsrRegistry() {
|
|
|
6263
6432
|
}
|
|
6264
6433
|
|
|
6265
6434
|
// src/registry/npm.ts
|
|
6266
|
-
import { exec as
|
|
6435
|
+
import { exec as exec6, NonZeroExitError as NonZeroExitError3 } from "tinyexec";
|
|
6267
6436
|
var NpmError = class extends AbstractError {
|
|
6268
6437
|
constructor() {
|
|
6269
6438
|
super(...arguments);
|
|
@@ -6276,7 +6445,7 @@ var NpmRegistry = class extends Registry {
|
|
|
6276
6445
|
__publicField(this, "registry", "https://registry.npmjs.org");
|
|
6277
6446
|
}
|
|
6278
6447
|
async npm(args) {
|
|
6279
|
-
const { stdout } = await
|
|
6448
|
+
const { stdout } = await exec6("npm", args, { throwOnError: true });
|
|
6280
6449
|
return stdout;
|
|
6281
6450
|
}
|
|
6282
6451
|
async isInstalled() {
|
|
@@ -6387,7 +6556,7 @@ var NpmRegistry = class extends Registry {
|
|
|
6387
6556
|
}
|
|
6388
6557
|
async ping() {
|
|
6389
6558
|
try {
|
|
6390
|
-
await
|
|
6559
|
+
await exec6("npm", ["ping"], { throwOnError: true });
|
|
6391
6560
|
return true;
|
|
6392
6561
|
} catch (error) {
|
|
6393
6562
|
throw new NpmError("Failed to run `npm ping`", { cause: error });
|
|
@@ -6416,6 +6585,24 @@ var NpmRegistry = class extends Registry {
|
|
|
6416
6585
|
throw this.classifyPublishError(error);
|
|
6417
6586
|
}
|
|
6418
6587
|
}
|
|
6588
|
+
async dryRunPublish() {
|
|
6589
|
+
try {
|
|
6590
|
+
await this.npm(["publish", "--dry-run"]);
|
|
6591
|
+
} catch (error) {
|
|
6592
|
+
throw new NpmError("Failed to run `npm publish --dry-run`", {
|
|
6593
|
+
cause: error
|
|
6594
|
+
});
|
|
6595
|
+
}
|
|
6596
|
+
}
|
|
6597
|
+
async twoFactorAuthMode() {
|
|
6598
|
+
try {
|
|
6599
|
+
const output = await this.npm(["profile", "get", "--json"]);
|
|
6600
|
+
const profile = JSON.parse(output);
|
|
6601
|
+
return profile?.tfa?.mode ?? null;
|
|
6602
|
+
} catch {
|
|
6603
|
+
return null;
|
|
6604
|
+
}
|
|
6605
|
+
}
|
|
6419
6606
|
async isPackageNameAvaliable() {
|
|
6420
6607
|
return isValidPackageName(this.packageName);
|
|
6421
6608
|
}
|
|
@@ -6452,7 +6639,80 @@ async function npmRegistry() {
|
|
|
6452
6639
|
return new NpmRegistry(packageJson.name);
|
|
6453
6640
|
}
|
|
6454
6641
|
|
|
6642
|
+
// src/tasks/dry-run-publish.ts
|
|
6643
|
+
var AUTH_ERROR_PATTERNS = [
|
|
6644
|
+
/401/i,
|
|
6645
|
+
/403/i,
|
|
6646
|
+
/unauthorized/i,
|
|
6647
|
+
/forbidden/i,
|
|
6648
|
+
/invalid.token/i,
|
|
6649
|
+
/eotp/i
|
|
6650
|
+
];
|
|
6651
|
+
function isAuthError(error) {
|
|
6652
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
6653
|
+
return AUTH_ERROR_PATTERNS.some((pattern) => pattern.test(message));
|
|
6654
|
+
}
|
|
6655
|
+
async function withTokenRetry(registryKey, task, action) {
|
|
6656
|
+
try {
|
|
6657
|
+
await action();
|
|
6658
|
+
} catch (error) {
|
|
6659
|
+
if (!isAuthError(error)) throw error;
|
|
6660
|
+
const config = TOKEN_CONFIG[registryKey];
|
|
6661
|
+
if (!config) throw error;
|
|
6662
|
+
task.output = `Auth failed. Re-enter ${config.promptLabel}`;
|
|
6663
|
+
const newToken = await task.prompt(ListrEnquirerPromptAdapter2).run({
|
|
6664
|
+
type: "password",
|
|
6665
|
+
message: `Re-enter ${config.promptLabel}`
|
|
6666
|
+
});
|
|
6667
|
+
new Db().set(config.dbKey, newToken);
|
|
6668
|
+
process.env[config.envVar] = newToken;
|
|
6669
|
+
await action();
|
|
6670
|
+
}
|
|
6671
|
+
}
|
|
6672
|
+
var npmDryRunPublishTask = {
|
|
6673
|
+
title: "Dry-run npm publish",
|
|
6674
|
+
task: async (_, task) => {
|
|
6675
|
+
task.output = "Running npm publish --dry-run...";
|
|
6676
|
+
await withTokenRetry("npm", task, async () => {
|
|
6677
|
+
const npm = await npmRegistry();
|
|
6678
|
+
await npm.dryRunPublish();
|
|
6679
|
+
});
|
|
6680
|
+
}
|
|
6681
|
+
};
|
|
6682
|
+
var jsrDryRunPublishTask = {
|
|
6683
|
+
title: "Dry-run jsr publish",
|
|
6684
|
+
task: async (_, task) => {
|
|
6685
|
+
task.output = "Running jsr publish --dry-run...";
|
|
6686
|
+
await withTokenRetry("jsr", task, async () => {
|
|
6687
|
+
const jsr = await jsrRegistry();
|
|
6688
|
+
await jsr.dryRunPublish();
|
|
6689
|
+
});
|
|
6690
|
+
}
|
|
6691
|
+
};
|
|
6692
|
+
async function getCrateName2(packagePath) {
|
|
6693
|
+
const eco = new RustEcosystem(packagePath ?? process.cwd());
|
|
6694
|
+
return await eco.packageName();
|
|
6695
|
+
}
|
|
6696
|
+
function createCratesDryRunPublishTask(packagePath) {
|
|
6697
|
+
const label = packagePath ? ` (${packagePath})` : "";
|
|
6698
|
+
return {
|
|
6699
|
+
title: `Dry-run crates.io publish${label}`,
|
|
6700
|
+
task: async (_, task) => {
|
|
6701
|
+
task.output = "Running cargo publish --dry-run...";
|
|
6702
|
+
await withTokenRetry("crates", task, async () => {
|
|
6703
|
+
const packageName = await getCrateName2(packagePath);
|
|
6704
|
+
const registry = new CratesRegistry(packageName);
|
|
6705
|
+
await registry.dryRunPublish(packagePath);
|
|
6706
|
+
});
|
|
6707
|
+
}
|
|
6708
|
+
};
|
|
6709
|
+
}
|
|
6710
|
+
var cratesDryRunPublishTask = createCratesDryRunPublishTask();
|
|
6711
|
+
|
|
6455
6712
|
// src/tasks/jsr.ts
|
|
6713
|
+
import process12 from "node:process";
|
|
6714
|
+
import { ListrEnquirerPromptAdapter as ListrEnquirerPromptAdapter3 } from "@listr2/prompt-adapter-enquirer";
|
|
6715
|
+
import npmCli from "@npmcli/promise-spawn";
|
|
6456
6716
|
var { open } = npmCli;
|
|
6457
6717
|
var JsrAvailableError = class extends AbstractError {
|
|
6458
6718
|
constructor(message, { cause } = {}) {
|
|
@@ -6480,7 +6740,7 @@ var jsrAvailableCheckTasks = {
|
|
|
6480
6740
|
if (ctx.promptEnabled) {
|
|
6481
6741
|
const maxAttempts = 3;
|
|
6482
6742
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
6483
|
-
JsrClient.token = await task.prompt(
|
|
6743
|
+
JsrClient.token = await task.prompt(ListrEnquirerPromptAdapter3).run({
|
|
6484
6744
|
type: "password",
|
|
6485
6745
|
message: `Please enter the jsr ${color.bold("API token")}${attempt > 1 ? ` (attempt ${attempt}/${maxAttempts})` : ""}`,
|
|
6486
6746
|
footer: `
|
|
@@ -6530,7 +6790,7 @@ Generate a token from ${color.bold(link2("jsr.io", "https://jsr.io/account/token
|
|
|
6530
6790
|
)
|
|
6531
6791
|
)).filter((v) => v !== null);
|
|
6532
6792
|
if (searchResults.length > 0) {
|
|
6533
|
-
jsrName = await task.prompt(
|
|
6793
|
+
jsrName = await task.prompt(ListrEnquirerPromptAdapter3).run({
|
|
6534
6794
|
type: "select",
|
|
6535
6795
|
message: "Is there a scoped package you want to publish in the already published list?",
|
|
6536
6796
|
choices: [
|
|
@@ -6548,7 +6808,7 @@ Generate a token from ${color.bold(link2("jsr.io", "https://jsr.io/account/token
|
|
|
6548
6808
|
}
|
|
6549
6809
|
const userName = await new Git().userName();
|
|
6550
6810
|
task.output = "Select the scope of the package to publish";
|
|
6551
|
-
jsrName = await task.prompt(
|
|
6811
|
+
jsrName = await task.prompt(ListrEnquirerPromptAdapter3).run({
|
|
6552
6812
|
type: "select",
|
|
6553
6813
|
message: "jsr.json does not exist, and the package name is not scoped. Please select a scope for the 'jsr' package",
|
|
6554
6814
|
choices: [
|
|
@@ -6576,7 +6836,7 @@ Generate a token from ${color.bold(link2("jsr.io", "https://jsr.io/account/token
|
|
|
6576
6836
|
});
|
|
6577
6837
|
if (jsrName === "specify") {
|
|
6578
6838
|
while (!isScopedPackage(jsrName)) {
|
|
6579
|
-
jsrName = await task.prompt(
|
|
6839
|
+
jsrName = await task.prompt(ListrEnquirerPromptAdapter3).run({
|
|
6580
6840
|
type: "input",
|
|
6581
6841
|
message: "Package name"
|
|
6582
6842
|
});
|
|
@@ -6644,7 +6904,7 @@ var jsrPublishTasks = {
|
|
|
6644
6904
|
${urls.map((url) => ` ${color.cyan(url)}`).join("\n")}`;
|
|
6645
6905
|
open(urls[0]);
|
|
6646
6906
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
6647
|
-
await task.prompt(
|
|
6907
|
+
await task.prompt(ListrEnquirerPromptAdapter3).run({
|
|
6648
6908
|
type: "input",
|
|
6649
6909
|
message: `Press ${color.bold("enter")} after creating the package on jsr.io${attempt > 1 ? ` (attempt ${attempt}/${maxAttempts})` : ""}`
|
|
6650
6910
|
});
|
|
@@ -6673,7 +6933,7 @@ ${jsr.packageCreationUrls.join("\n")}`
|
|
|
6673
6933
|
// src/tasks/npm.ts
|
|
6674
6934
|
import { spawn } from "node:child_process";
|
|
6675
6935
|
import process13 from "node:process";
|
|
6676
|
-
import { ListrEnquirerPromptAdapter as
|
|
6936
|
+
import { ListrEnquirerPromptAdapter as ListrEnquirerPromptAdapter4 } from "@listr2/prompt-adapter-enquirer";
|
|
6677
6937
|
import npmCli2 from "@npmcli/promise-spawn";
|
|
6678
6938
|
var { open: open2 } = npmCli2;
|
|
6679
6939
|
var NpmAvailableError = class extends AbstractError {
|
|
@@ -6685,7 +6945,6 @@ var NpmAvailableError = class extends AbstractError {
|
|
|
6685
6945
|
};
|
|
6686
6946
|
var npmAvailableCheckTasks = {
|
|
6687
6947
|
title: "Checking npm avaliable for publising",
|
|
6688
|
-
skip: (ctx) => !!ctx.preview,
|
|
6689
6948
|
task: async (ctx, task) => {
|
|
6690
6949
|
const npm = await npmRegistry();
|
|
6691
6950
|
if (!await npm.isLoggedIn()) {
|
|
@@ -6748,6 +7007,14 @@ var npmAvailableCheckTasks = {
|
|
|
6748
7007
|
More information: ${link2("npm naming rules", "https://github.com/npm/validate-npm-package-name?tab=readme-ov-file#naming-rules")}`
|
|
6749
7008
|
);
|
|
6750
7009
|
}
|
|
7010
|
+
if (!ctx.promptEnabled) {
|
|
7011
|
+
const tfaMode = await npm.twoFactorAuthMode();
|
|
7012
|
+
if (tfaMode === "auth-and-writes") {
|
|
7013
|
+
throw new NpmAvailableError(
|
|
7014
|
+
`npm account has 2FA enabled for writes (auth-and-writes). CI publish will fail with EOTP. Use an automation token or configure granular access token at https://www.npmjs.com/package/${npm.packageName}/access`
|
|
7015
|
+
);
|
|
7016
|
+
}
|
|
7017
|
+
}
|
|
6751
7018
|
}
|
|
6752
7019
|
};
|
|
6753
7020
|
var npmPublishTasks = {
|
|
@@ -6763,7 +7030,7 @@ var npmPublishTasks = {
|
|
|
6763
7030
|
const maxAttempts = 3;
|
|
6764
7031
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
6765
7032
|
result = await npm.publish(
|
|
6766
|
-
await task.prompt(
|
|
7033
|
+
await task.prompt(ListrEnquirerPromptAdapter4).run({
|
|
6767
7034
|
type: "password",
|
|
6768
7035
|
message: `npm OTP code${attempt > 1 ? ` (attempt ${attempt}/${maxAttempts})` : ""}`
|
|
6769
7036
|
})
|
|
@@ -6798,7 +7065,7 @@ var npmPublishTasks = {
|
|
|
6798
7065
|
};
|
|
6799
7066
|
|
|
6800
7067
|
// src/tasks/prerequisites-check.ts
|
|
6801
|
-
import { ListrEnquirerPromptAdapter as
|
|
7068
|
+
import { ListrEnquirerPromptAdapter as ListrEnquirerPromptAdapter5 } from "@listr2/prompt-adapter-enquirer";
|
|
6802
7069
|
var PrerequisitesCheckError = class extends AbstractError {
|
|
6803
7070
|
constructor(message, { cause } = {}) {
|
|
6804
7071
|
super(message, { cause });
|
|
@@ -6818,7 +7085,7 @@ var prerequisitesCheckTask = (options) => {
|
|
|
6818
7085
|
title: "Verifying current branch is a release branch",
|
|
6819
7086
|
task: async (ctx, task) => {
|
|
6820
7087
|
if (await git.branch() !== ctx.branch) {
|
|
6821
|
-
const swtichBranch = await task.prompt(
|
|
7088
|
+
const swtichBranch = await task.prompt(ListrEnquirerPromptAdapter5).run({
|
|
6822
7089
|
type: "toggle",
|
|
6823
7090
|
message: `${warningBadge} The current HEAD branch is not the release target branch. Do you want to switch branch to ${ctx.branch}?`,
|
|
6824
7091
|
enabled: "Yes",
|
|
@@ -6840,7 +7107,7 @@ var prerequisitesCheckTask = (options) => {
|
|
|
6840
7107
|
task: async (_2, task) => {
|
|
6841
7108
|
task.output = "Checking for updates with `git fetch`";
|
|
6842
7109
|
if ((await git.dryFetch()).trim()) {
|
|
6843
|
-
const fetch2 = await task.prompt(
|
|
7110
|
+
const fetch2 = await task.prompt(ListrEnquirerPromptAdapter5).run({
|
|
6844
7111
|
type: "toggle",
|
|
6845
7112
|
message: `${warningBadge} Local history is outdated. Do you want to run \`git fetch\`?`,
|
|
6846
7113
|
enabled: "Yes",
|
|
@@ -6857,7 +7124,7 @@ var prerequisitesCheckTask = (options) => {
|
|
|
6857
7124
|
}
|
|
6858
7125
|
task.output = "Checking for updates with `git pull`";
|
|
6859
7126
|
if (await git.revisionDiffsCount()) {
|
|
6860
|
-
const pull = await task.prompt(
|
|
7127
|
+
const pull = await task.prompt(ListrEnquirerPromptAdapter5).run({
|
|
6861
7128
|
type: "toggle",
|
|
6862
7129
|
message: `${warningBadge} Local history is outdated. Do you want to run \`git pull\`?`,
|
|
6863
7130
|
enabled: "Yes",
|
|
@@ -6879,7 +7146,7 @@ var prerequisitesCheckTask = (options) => {
|
|
|
6879
7146
|
task: async (ctx, task) => {
|
|
6880
7147
|
if (await git.status()) {
|
|
6881
7148
|
task.output = "Local working tree is not clean.";
|
|
6882
|
-
if (!await task.prompt(
|
|
7149
|
+
if (!await task.prompt(ListrEnquirerPromptAdapter5).run({
|
|
6883
7150
|
type: "toggle",
|
|
6884
7151
|
message: `${warningBadge} Local working tree is not clean. Do you want to skip?`,
|
|
6885
7152
|
enabled: "Yes",
|
|
@@ -6904,7 +7171,7 @@ var prerequisitesCheckTask = (options) => {
|
|
|
6904
7171
|
return void 0;
|
|
6905
7172
|
}
|
|
6906
7173
|
if ((await git.commits(latestTag, "HEAD")).length <= 0) {
|
|
6907
|
-
if (!await task.prompt(
|
|
7174
|
+
if (!await task.prompt(ListrEnquirerPromptAdapter5).run({
|
|
6908
7175
|
type: "toggle",
|
|
6909
7176
|
message: `${warningBadge} No commits exist from the latest tag. Do you want to skip?`,
|
|
6910
7177
|
enabled: "Yes",
|
|
@@ -6922,7 +7189,7 @@ var prerequisitesCheckTask = (options) => {
|
|
|
6922
7189
|
task: async (ctx, task) => {
|
|
6923
7190
|
const gitTag = `v${ctx.version}`;
|
|
6924
7191
|
if (await git.checkTagExist(gitTag)) {
|
|
6925
|
-
const deleteTag = await task.prompt(
|
|
7192
|
+
const deleteTag = await task.prompt(ListrEnquirerPromptAdapter5).run({
|
|
6926
7193
|
type: "toggle",
|
|
6927
7194
|
message: `${warningBadge} The Git tag '${gitTag}' already exists. Do you want to delete tag?`,
|
|
6928
7195
|
enabled: "Yes",
|
|
@@ -6944,13 +7211,13 @@ var prerequisitesCheckTask = (options) => {
|
|
|
6944
7211
|
};
|
|
6945
7212
|
|
|
6946
7213
|
// src/tasks/required-conditions-check.ts
|
|
6947
|
-
import { ListrEnquirerPromptAdapter as
|
|
7214
|
+
import { ListrEnquirerPromptAdapter as ListrEnquirerPromptAdapter6 } from "@listr2/prompt-adapter-enquirer";
|
|
6948
7215
|
|
|
6949
7216
|
// src/registry/custom-registry.ts
|
|
6950
|
-
import { exec as
|
|
7217
|
+
import { exec as exec7 } from "tinyexec";
|
|
6951
7218
|
var CustomRegistry = class extends NpmRegistry {
|
|
6952
7219
|
async npm(args) {
|
|
6953
|
-
const { stdout } = await
|
|
7220
|
+
const { stdout } = await exec7(
|
|
6954
7221
|
"npm",
|
|
6955
7222
|
args.concat("--registry", this.registry),
|
|
6956
7223
|
{ throwOnError: true }
|
|
@@ -7052,7 +7319,7 @@ var requiredConditionsCheckTask = (options) => createListr({
|
|
|
7052
7319
|
task: async (_3, task) => {
|
|
7053
7320
|
const jsr = await jsrRegistry();
|
|
7054
7321
|
if (!await jsr.isInstalled()) {
|
|
7055
|
-
const install = await task.prompt(
|
|
7322
|
+
const install = await task.prompt(ListrEnquirerPromptAdapter6).run({
|
|
7056
7323
|
type: "toggle",
|
|
7057
7324
|
message: `${warningBadge} jsr is not installed. Do you want to install jsr?`,
|
|
7058
7325
|
enabled: "Yes",
|
|
@@ -7186,14 +7453,66 @@ async function collectPublishTasks(ctx) {
|
|
|
7186
7453
|
}
|
|
7187
7454
|
return collectRegistries(ctx).map(registryTask);
|
|
7188
7455
|
}
|
|
7456
|
+
function dryRunRegistryTask(registry) {
|
|
7457
|
+
switch (registry) {
|
|
7458
|
+
case "npm":
|
|
7459
|
+
return npmDryRunPublishTask;
|
|
7460
|
+
case "jsr":
|
|
7461
|
+
return jsrDryRunPublishTask;
|
|
7462
|
+
case "crates":
|
|
7463
|
+
return cratesDryRunPublishTask;
|
|
7464
|
+
default:
|
|
7465
|
+
return npmDryRunPublishTask;
|
|
7466
|
+
}
|
|
7467
|
+
}
|
|
7468
|
+
async function collectDryRunPublishTasks(ctx) {
|
|
7469
|
+
if (ctx.packages?.length) {
|
|
7470
|
+
const nonCratesTasks = ctx.packages.flatMap(
|
|
7471
|
+
(pkg) => pkg.registries.filter((reg) => reg !== "crates").map((reg) => dryRunRegistryTask(reg))
|
|
7472
|
+
);
|
|
7473
|
+
const cratesPaths = ctx.packages.filter((pkg) => pkg.registries.includes("crates")).map((pkg) => pkg.path);
|
|
7474
|
+
if (cratesPaths.length === 0) {
|
|
7475
|
+
return nonCratesTasks;
|
|
7476
|
+
}
|
|
7477
|
+
const sortedPaths = await sortCratesByDependencyOrder(cratesPaths);
|
|
7478
|
+
const sequentialCratesTask = {
|
|
7479
|
+
title: "Dry-run crates.io publish (sequential)",
|
|
7480
|
+
task: (_ctx, task) => task.newListr(
|
|
7481
|
+
sortedPaths.map((p) => createCratesDryRunPublishTask(p)),
|
|
7482
|
+
{ concurrent: false }
|
|
7483
|
+
)
|
|
7484
|
+
};
|
|
7485
|
+
return [...nonCratesTasks, sequentialCratesTask];
|
|
7486
|
+
}
|
|
7487
|
+
return collectRegistries(ctx).map(dryRunRegistryTask);
|
|
7488
|
+
}
|
|
7189
7489
|
async function run(options) {
|
|
7190
7490
|
const ctx = {
|
|
7191
7491
|
...options,
|
|
7192
7492
|
promptEnabled: !isCI2 && process14.stdin.isTTY
|
|
7193
7493
|
};
|
|
7494
|
+
let cleanupEnv;
|
|
7194
7495
|
try {
|
|
7195
7496
|
if (options.contents) process14.chdir(options.contents);
|
|
7196
|
-
if (
|
|
7497
|
+
if (options.preflight) {
|
|
7498
|
+
await createListr({
|
|
7499
|
+
title: "Collecting registry tokens",
|
|
7500
|
+
task: async (ctx2, task) => {
|
|
7501
|
+
const registries2 = collectRegistries(ctx2);
|
|
7502
|
+
const tokens = await collectTokens(registries2, task);
|
|
7503
|
+
await promptGhSecretsSync(tokens, task);
|
|
7504
|
+
cleanupEnv = injectTokensToEnv(tokens);
|
|
7505
|
+
ctx2.promptEnabled = false;
|
|
7506
|
+
}
|
|
7507
|
+
}).run(ctx);
|
|
7508
|
+
await prerequisitesCheckTask({
|
|
7509
|
+
skip: options.skipPrerequisitesCheck
|
|
7510
|
+
}).run(ctx);
|
|
7511
|
+
await requiredConditionsCheckTask({
|
|
7512
|
+
skip: options.skipConditionsCheck
|
|
7513
|
+
}).run(ctx);
|
|
7514
|
+
}
|
|
7515
|
+
if (!options.publishOnly && !options.preflight) {
|
|
7197
7516
|
await prerequisitesCheckTask({
|
|
7198
7517
|
skip: options.skipPrerequisitesCheck
|
|
7199
7518
|
}).run(ctx);
|
|
@@ -7207,14 +7526,14 @@ async function run(options) {
|
|
|
7207
7526
|
task: async (ctx2, parentTask) => parentTask.newListr(await collectPublishTasks(ctx2), {
|
|
7208
7527
|
concurrent: true
|
|
7209
7528
|
})
|
|
7210
|
-
} : [
|
|
7529
|
+
} : options.preflight ? [
|
|
7211
7530
|
{
|
|
7212
7531
|
skip: options.skipTests,
|
|
7213
7532
|
title: "Running tests",
|
|
7214
7533
|
task: async (ctx2) => {
|
|
7215
7534
|
const packageManager = await getPackageManager();
|
|
7216
7535
|
try {
|
|
7217
|
-
await
|
|
7536
|
+
await exec8(packageManager, ["run", ctx2.testScript], {
|
|
7218
7537
|
throwOnError: true
|
|
7219
7538
|
});
|
|
7220
7539
|
} catch (error) {
|
|
@@ -7231,7 +7550,48 @@ async function run(options) {
|
|
|
7231
7550
|
task: async (ctx2) => {
|
|
7232
7551
|
const packageManager = await getPackageManager();
|
|
7233
7552
|
try {
|
|
7234
|
-
await
|
|
7553
|
+
await exec8(packageManager, ["run", ctx2.buildScript], {
|
|
7554
|
+
throwOnError: true
|
|
7555
|
+
});
|
|
7556
|
+
} catch (error) {
|
|
7557
|
+
throw new AbstractError(
|
|
7558
|
+
`Build script '${ctx2.buildScript}' failed. Run \`${packageManager} run ${ctx2.buildScript}\` locally to see full output.`,
|
|
7559
|
+
{ cause: error }
|
|
7560
|
+
);
|
|
7561
|
+
}
|
|
7562
|
+
}
|
|
7563
|
+
},
|
|
7564
|
+
{
|
|
7565
|
+
title: "Validating publish (dry-run)",
|
|
7566
|
+
task: async (ctx2, parentTask) => parentTask.newListr(await collectDryRunPublishTasks(ctx2), {
|
|
7567
|
+
concurrent: true
|
|
7568
|
+
})
|
|
7569
|
+
}
|
|
7570
|
+
] : [
|
|
7571
|
+
{
|
|
7572
|
+
skip: options.skipTests,
|
|
7573
|
+
title: "Running tests",
|
|
7574
|
+
task: async (ctx2) => {
|
|
7575
|
+
const packageManager = await getPackageManager();
|
|
7576
|
+
try {
|
|
7577
|
+
await exec8(packageManager, ["run", ctx2.testScript], {
|
|
7578
|
+
throwOnError: true
|
|
7579
|
+
});
|
|
7580
|
+
} catch (error) {
|
|
7581
|
+
throw new AbstractError(
|
|
7582
|
+
`Test script '${ctx2.testScript}' failed. Run \`${packageManager} run ${ctx2.testScript}\` locally to see full output.`,
|
|
7583
|
+
{ cause: error }
|
|
7584
|
+
);
|
|
7585
|
+
}
|
|
7586
|
+
}
|
|
7587
|
+
},
|
|
7588
|
+
{
|
|
7589
|
+
skip: options.skipBuild,
|
|
7590
|
+
title: "Building the project",
|
|
7591
|
+
task: async (ctx2) => {
|
|
7592
|
+
const packageManager = await getPackageManager();
|
|
7593
|
+
try {
|
|
7594
|
+
await exec8(packageManager, ["run", ctx2.buildScript], {
|
|
7235
7595
|
throwOnError: true
|
|
7236
7596
|
});
|
|
7237
7597
|
} catch (error) {
|
|
@@ -7356,13 +7716,24 @@ ${repositoryUrl}/compare/${lastRev}...${latestTag}`;
|
|
|
7356
7716
|
parts.push(`${color.bold(name)} on ${color.red("crates.io")}`);
|
|
7357
7717
|
}
|
|
7358
7718
|
}
|
|
7359
|
-
|
|
7360
|
-
|
|
7719
|
+
if (options.preflight) {
|
|
7720
|
+
cleanupEnv?.();
|
|
7721
|
+
console.log(
|
|
7722
|
+
`
|
|
7723
|
+
|
|
7724
|
+
\u2705 Preflight check passed. CI publish should succeed for ${parts.join(", ")}.
|
|
7725
|
+
`
|
|
7726
|
+
);
|
|
7727
|
+
} else {
|
|
7728
|
+
console.log(
|
|
7729
|
+
`
|
|
7361
7730
|
|
|
7362
7731
|
\u{1F680} Successfully published ${parts.join(", ")} ${color.blueBright(`v${ctx.version}`)} \u{1F680}
|
|
7363
7732
|
`
|
|
7364
|
-
|
|
7733
|
+
);
|
|
7734
|
+
}
|
|
7365
7735
|
} catch (e2) {
|
|
7736
|
+
cleanupEnv?.();
|
|
7366
7737
|
consoleError(e2);
|
|
7367
7738
|
await rollback();
|
|
7368
7739
|
process14.exit(1);
|
|
@@ -7411,7 +7782,7 @@ async function pubm(options) {
|
|
|
7411
7782
|
}
|
|
7412
7783
|
|
|
7413
7784
|
// src/tasks/required-missing-information.ts
|
|
7414
|
-
import { ListrEnquirerPromptAdapter as
|
|
7785
|
+
import { ListrEnquirerPromptAdapter as ListrEnquirerPromptAdapter7 } from "@listr2/prompt-adapter-enquirer";
|
|
7415
7786
|
import semver2 from "semver";
|
|
7416
7787
|
var { RELEASE_TYPES, SemVer: SemVer2, prerelease: prerelease2 } = semver2;
|
|
7417
7788
|
var requiredMissingInformationTasks = (options) => createListr({
|
|
@@ -7423,7 +7794,7 @@ var requiredMissingInformationTasks = (options) => createListr({
|
|
|
7423
7794
|
skip: (ctx) => !!ctx.version,
|
|
7424
7795
|
task: async (ctx, task) => {
|
|
7425
7796
|
const currentVersion = await version();
|
|
7426
|
-
let nextVersion = await task.prompt(
|
|
7797
|
+
let nextVersion = await task.prompt(ListrEnquirerPromptAdapter7).run({
|
|
7427
7798
|
type: "select",
|
|
7428
7799
|
message: "Select SemVer increment or specify new version",
|
|
7429
7800
|
choices: RELEASE_TYPES.map((releaseType) => {
|
|
@@ -7438,7 +7809,7 @@ var requiredMissingInformationTasks = (options) => createListr({
|
|
|
7438
7809
|
name: "version"
|
|
7439
7810
|
});
|
|
7440
7811
|
if (nextVersion === "specify") {
|
|
7441
|
-
nextVersion = await task.prompt(
|
|
7812
|
+
nextVersion = await task.prompt(ListrEnquirerPromptAdapter7).run({
|
|
7442
7813
|
type: "input",
|
|
7443
7814
|
message: "Version",
|
|
7444
7815
|
name: "version"
|
|
@@ -7460,7 +7831,7 @@ var requiredMissingInformationTasks = (options) => createListr({
|
|
|
7460
7831
|
)
|
|
7461
7832
|
].filter((tag2) => tag2 !== defaultOptions.tag);
|
|
7462
7833
|
if (distTags.length <= 0) distTags.push("next");
|
|
7463
|
-
let tag = await task.prompt(
|
|
7834
|
+
let tag = await task.prompt(ListrEnquirerPromptAdapter7).run({
|
|
7464
7835
|
type: "select",
|
|
7465
7836
|
message: "Select the tag for this pre-release version in npm",
|
|
7466
7837
|
choices: distTags.map((distTag) => ({
|
|
@@ -7472,7 +7843,7 @@ var requiredMissingInformationTasks = (options) => createListr({
|
|
|
7472
7843
|
name: "tag"
|
|
7473
7844
|
});
|
|
7474
7845
|
if (tag === "specify") {
|
|
7475
|
-
tag = await task.prompt(
|
|
7846
|
+
tag = await task.prompt(ListrEnquirerPromptAdapter7).run({
|
|
7476
7847
|
type: "input",
|
|
7477
7848
|
message: "Tag",
|
|
7478
7849
|
name: "tag"
|
|
@@ -7558,6 +7929,11 @@ var publishOptions = [
|
|
|
7558
7929
|
description: "Run only publish task for latest tag",
|
|
7559
7930
|
options: { type: Boolean }
|
|
7560
7931
|
},
|
|
7932
|
+
{
|
|
7933
|
+
rawName: "--preflight",
|
|
7934
|
+
description: "Simulate CI publish locally (dry-run with token-based auth)",
|
|
7935
|
+
options: { type: Boolean }
|
|
7936
|
+
},
|
|
7561
7937
|
{
|
|
7562
7938
|
rawName: "-t, --tag <name>",
|
|
7563
7939
|
description: "Publish under a specific dist-tag",
|
|
@@ -7588,7 +7964,8 @@ function resolveCliOptions(options) {
|
|
|
7588
7964
|
skipBuild: !options.build,
|
|
7589
7965
|
registries: options.registry?.split(","),
|
|
7590
7966
|
skipPrerequisitesCheck: !options.preCheck,
|
|
7591
|
-
skipConditionsCheck: !options.conditionCheck
|
|
7967
|
+
skipConditionsCheck: !options.conditionCheck,
|
|
7968
|
+
preflight: options.preflight
|
|
7592
7969
|
};
|
|
7593
7970
|
}
|
|
7594
7971
|
var cli = cac("pubm");
|
|
@@ -7600,6 +7977,7 @@ registerSnapshotCommand(cli);
|
|
|
7600
7977
|
registerInitCommand(cli);
|
|
7601
7978
|
registerMigrateCommand(cli);
|
|
7602
7979
|
registerUpdateCommand(cli);
|
|
7980
|
+
registerSecretsCommand(cli);
|
|
7603
7981
|
var defaultCmd = cli.command("[version]", "Publish packages to registries");
|
|
7604
7982
|
for (const option of publishOptions) {
|
|
7605
7983
|
defaultCmd.option(option.rawName, option.description, option.options);
|
|
@@ -7615,7 +7993,9 @@ defaultCmd.action(
|
|
|
7615
7993
|
tag: options.tag
|
|
7616
7994
|
};
|
|
7617
7995
|
try {
|
|
7618
|
-
if (
|
|
7996
|
+
if (options.preflight) {
|
|
7997
|
+
context.version = nextVersion || "0.0.0-preflight";
|
|
7998
|
+
} else if (isCI3) {
|
|
7619
7999
|
if (options.publishOnly) {
|
|
7620
8000
|
const git = new Git();
|
|
7621
8001
|
const latestVersion = (await git.latestTag())?.slice(1);
|