pubz 0.2.5 → 0.2.8
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/dist/cli.js +108 -7
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -308,13 +308,57 @@ async function multiSelect(message, options, allSelectedByDefault = true) {
|
|
|
308
308
|
});
|
|
309
309
|
}
|
|
310
310
|
|
|
311
|
-
// src/
|
|
311
|
+
// src/auth.ts
|
|
312
312
|
import { spawn } from "node:child_process";
|
|
313
|
+
async function checkNpmAuth(registry) {
|
|
314
|
+
return new Promise((resolve2) => {
|
|
315
|
+
const proc = spawn("npm", ["whoami", "--registry", registry], {
|
|
316
|
+
stdio: ["inherit", "pipe", "pipe"]
|
|
317
|
+
});
|
|
318
|
+
let stdout = "";
|
|
319
|
+
let stderr = "";
|
|
320
|
+
proc.stdout?.on("data", (data) => {
|
|
321
|
+
stdout += data.toString();
|
|
322
|
+
});
|
|
323
|
+
proc.stderr?.on("data", (data) => {
|
|
324
|
+
stderr += data.toString();
|
|
325
|
+
});
|
|
326
|
+
proc.on("close", (code) => {
|
|
327
|
+
if (code === 0 && stdout.trim()) {
|
|
328
|
+
resolve2({ authenticated: true, username: stdout.trim() });
|
|
329
|
+
} else {
|
|
330
|
+
resolve2({ authenticated: false });
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
async function npmLogin(registry) {
|
|
336
|
+
return new Promise((resolve2) => {
|
|
337
|
+
const proc = spawn("npm", ["login", "--registry", registry], {
|
|
338
|
+
stdio: "inherit"
|
|
339
|
+
});
|
|
340
|
+
proc.on("close", (code) => {
|
|
341
|
+
if (code === 0) {
|
|
342
|
+
resolve2({ success: true });
|
|
343
|
+
} else {
|
|
344
|
+
resolve2({ success: false, error: "Login failed or was cancelled" });
|
|
345
|
+
}
|
|
346
|
+
});
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
async function promptForOtp() {
|
|
350
|
+
console.log("");
|
|
351
|
+
const code = await prompt(`${cyan("?")} Enter OTP code from your authenticator: `);
|
|
352
|
+
return code.trim();
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// src/publish.ts
|
|
356
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
313
357
|
import { readFile as readFile2, stat as stat3 } from "node:fs/promises";
|
|
314
358
|
import { join as join3 } from "node:path";
|
|
315
359
|
function run(command, args, cwd) {
|
|
316
360
|
return new Promise((resolve2) => {
|
|
317
|
-
const proc =
|
|
361
|
+
const proc = spawn2(command, args, {
|
|
318
362
|
cwd,
|
|
319
363
|
stdio: ["inherit", "pipe", "pipe"]
|
|
320
364
|
});
|
|
@@ -381,18 +425,35 @@ async function verifyBuild(pkg) {
|
|
|
381
425
|
}
|
|
382
426
|
return { success: true };
|
|
383
427
|
}
|
|
384
|
-
|
|
428
|
+
function isOtpError(output) {
|
|
429
|
+
return output.includes("EOTP") || output.includes("one-time password");
|
|
430
|
+
}
|
|
431
|
+
async function publishPackage(pkg, registry, context, dryRun) {
|
|
385
432
|
if (dryRun) {
|
|
386
433
|
console.log(` [DRY RUN] Would publish ${pkg.name}@${pkg.version} to ${registry}`);
|
|
387
434
|
return { success: true };
|
|
388
435
|
}
|
|
389
436
|
console.log(`Publishing ${pkg.name}@${pkg.version}...`);
|
|
390
437
|
const args = ["publish", "--registry", registry, "--access", "public"];
|
|
391
|
-
if (otp) {
|
|
392
|
-
args.push("--otp", otp);
|
|
438
|
+
if (context.otp) {
|
|
439
|
+
args.push("--otp", context.otp);
|
|
440
|
+
}
|
|
441
|
+
let result = await run("npm", args, pkg.path);
|
|
442
|
+
if (result.code !== 0 && isOtpError(result.output) && context.onOtpRequired) {
|
|
443
|
+
const otpCode = await context.onOtpRequired();
|
|
444
|
+
if (otpCode) {
|
|
445
|
+
context.otp = otpCode;
|
|
446
|
+
const retryArgs = ["publish", "--registry", registry, "--access", "public", "--otp", otpCode];
|
|
447
|
+
result = await run("npm", retryArgs, pkg.path);
|
|
448
|
+
}
|
|
393
449
|
}
|
|
394
|
-
const result = await run("npm", args, pkg.path);
|
|
395
450
|
if (result.code !== 0) {
|
|
451
|
+
if (isOtpError(result.output)) {
|
|
452
|
+
return {
|
|
453
|
+
success: false,
|
|
454
|
+
error: `2FA OTP required. Use --otp flag or run interactively.`
|
|
455
|
+
};
|
|
456
|
+
}
|
|
396
457
|
return { success: false, error: `Failed to publish ${pkg.name}` };
|
|
397
458
|
}
|
|
398
459
|
console.log(` ${pkg.name} published successfully`);
|
|
@@ -777,6 +838,42 @@ async function main() {
|
|
|
777
838
|
console.log("");
|
|
778
839
|
console.log(`Publishing to: ${cyan(registry)}`);
|
|
779
840
|
console.log("");
|
|
841
|
+
if (!options.dryRun) {
|
|
842
|
+
console.log(cyan("Verifying npm authentication..."));
|
|
843
|
+
const authResult = await checkNpmAuth(registry);
|
|
844
|
+
if (!authResult.authenticated) {
|
|
845
|
+
if (options.ci) {
|
|
846
|
+
console.error(red(bold("Error:")) + " Not authenticated to npm.");
|
|
847
|
+
console.log("");
|
|
848
|
+
console.log(muted("In CI mode, you need to configure authentication:"));
|
|
849
|
+
console.log(muted(" - Set NPM_TOKEN environment variable"));
|
|
850
|
+
console.log(muted(" - Or configure .npmrc with auth token"));
|
|
851
|
+
console.log(muted(" - Or use OIDC Trusted Publishing"));
|
|
852
|
+
closePrompt();
|
|
853
|
+
process.exit(1);
|
|
854
|
+
}
|
|
855
|
+
console.log("");
|
|
856
|
+
console.log(yellow("Not logged in to npm.") + " Starting login...");
|
|
857
|
+
console.log("");
|
|
858
|
+
const loginResult = await npmLogin(registry);
|
|
859
|
+
if (!loginResult.success) {
|
|
860
|
+
console.error(red(bold("Login failed:")) + ` ${loginResult.error}`);
|
|
861
|
+
closePrompt();
|
|
862
|
+
process.exit(1);
|
|
863
|
+
}
|
|
864
|
+
const verifyAuth = await checkNpmAuth(registry);
|
|
865
|
+
if (!verifyAuth.authenticated) {
|
|
866
|
+
console.error(red(bold("Error:")) + " Login did not complete successfully.");
|
|
867
|
+
closePrompt();
|
|
868
|
+
process.exit(1);
|
|
869
|
+
}
|
|
870
|
+
console.log("");
|
|
871
|
+
console.log(green("Logged in as") + ` ${cyan(verifyAuth.username ?? "unknown")}`);
|
|
872
|
+
} else {
|
|
873
|
+
console.log(green("Authenticated as") + ` ${cyan(authResult.username ?? "unknown")}`);
|
|
874
|
+
}
|
|
875
|
+
console.log("");
|
|
876
|
+
}
|
|
780
877
|
if (!options.skipBuild) {
|
|
781
878
|
console.log(bold(cyan("Step 2:")) + " Building Packages");
|
|
782
879
|
console.log(dim("─".repeat(30)));
|
|
@@ -838,8 +935,12 @@ async function main() {
|
|
|
838
935
|
console.log("");
|
|
839
936
|
console.log(cyan("Publishing packages..."));
|
|
840
937
|
console.log("");
|
|
938
|
+
const publishContext = {
|
|
939
|
+
otp: options.otp,
|
|
940
|
+
onOtpRequired: options.ci ? undefined : promptForOtp
|
|
941
|
+
};
|
|
841
942
|
for (const pkg of packages) {
|
|
842
|
-
const result = await publishPackage(pkg, registry,
|
|
943
|
+
const result = await publishPackage(pkg, registry, publishContext, options.dryRun);
|
|
843
944
|
if (!result.success) {
|
|
844
945
|
console.error(red(bold("Failed to publish")) + ` ${cyan(pkg.name)}: ${result.error}`);
|
|
845
946
|
console.log("");
|