55 * Usage:
66 * node scripts/npmRelease.js --version 12.0.1 --tag next
77 * node scripts/npmRelease.js --version 12.0.1 --tag latest --otp 123456
8+ * node scripts/npmRelease.js --version 12.0.1 --tag latest --token <token>
89 *
910 * - Runs `npm dist-tag add` for every non-private workspace (same as CI publish)
10- * reusing the same OTP so you only get prompted once.
11+ * reusing the same OTP (when provided) so you only get prompted once.
12+ * - If no OTP is provided, npm uses the current auth flow (for example passkey).
13+ * - Token auth can be passed with `--token` or via `NODE_AUTH_TOKEN`/`NPM_TOKEN`.
1114 * - Pass `--dry-run` to see the commands without executing them.
1215 */
1316import process from "node:process" ;
14- import readline from "node:readline/promises" ;
1517import { parseArgs } from "node:util" ;
1618import { npm , yarn } from "../lib_dev/process.js" ;
1719
18- async function promptForOtp ( existingOtp ) {
19- if ( existingOtp ) {
20- return existingOtp ;
21- }
22- const rl = readline . createInterface ( {
23- input : process . stdin ,
24- output : process . stdout ,
25- } ) ;
26- const answer = await rl . question ( "npm one-time password: " ) ;
27- rl . close ( ) ;
28- return answer . trim ( ) ;
29- }
30-
3120async function getPublicWorkspaces ( ) {
3221 const { stdout } = await yarn ( "workspaces" , [
3322 "list" ,
@@ -41,15 +30,40 @@ async function getPublicWorkspaces() {
4130 . map ( entry => entry . name ) ;
4231}
4332
44- async function runDistTag ( pkgName , version , tag , otp , dryRun ) {
33+ function resolveAuth ( values ) {
34+ const otp = values . otp ?. trim ( ) || undefined ;
35+ const token =
36+ values . token ?. trim ( ) ||
37+ process . env . NODE_AUTH_TOKEN ?. trim ( ) ||
38+ process . env . NPM_TOKEN ?. trim ( ) ||
39+ undefined ;
40+
41+ if ( otp && token ) {
42+ throw new Error ( "Use either --otp or token auth, not both." ) ;
43+ }
44+
45+ return { otp, token } ;
46+ }
47+
48+ async function runDistTag ( pkgName , version , tag , otp , token , dryRun ) {
4549 const spec = `${ pkgName } @${ version } ` ;
46- const args = [ "dist-tag" , "add" , spec , tag , "--otp" , otp ] ;
50+ const args = [ "dist-tag" , "add" , spec , tag ] ;
51+ if ( otp ) {
52+ args . push ( "--otp" , otp ) ;
53+ }
4754 if ( dryRun ) {
4855 console . log ( `[dry-run] npm ${ args . join ( " " ) } ` ) ;
4956 return ;
5057 }
5158 console . log ( `Tagging ${ spec } as ${ tag } ...` ) ;
52- await npm ( "dist-tag" , [ "add" , spec , tag , "--otp" , otp ] , {
59+ const env = token
60+ ? {
61+ ...process . env ,
62+ NODE_AUTH_TOKEN : token ,
63+ }
64+ : process . env ;
65+ await npm ( "dist-tag" , args . slice ( 1 ) , {
66+ env,
5367 stdio : "inherit" ,
5468 throwOnFail : true ,
5569 } ) ;
@@ -64,12 +78,13 @@ async function main() {
6478 version : { type : "string" , short : "v" } ,
6579 tag : { type : "string" , short : "t" } ,
6680 otp : { type : "string" } ,
81+ token : { type : "string" } ,
6782 "dry-run" : { type : "boolean" } ,
6883 } ,
6984 } ) ;
7085 if ( ! values . version || ! values . tag ) {
7186 console . error (
72- "Usage: node scripts/npmRelease.js --version <version> --tag <tag> [--otp <code>] [--dry-run]" ,
87+ "Usage: node scripts/npmRelease.js --version <version> --tag <tag> [--otp <code> | --token <token> ] [--dry-run]" ,
7388 ) ;
7489 process . exitCode = 1 ;
7590 return ;
@@ -79,16 +94,14 @@ async function main() {
7994 throw new Error ( "No public workspaces found." ) ;
8095 }
8196
82- const otp = await promptForOtp ( values . otp ) ;
83- if ( ! otp ) {
84- throw new Error ( "OTP is required to publish dist-tags." ) ;
85- }
97+ const { otp, token } = resolveAuth ( values ) ;
8698 for ( const workspace of workspaces ) {
8799 await runDistTag (
88100 workspace ,
89101 values . version ,
90102 values . tag ,
91103 otp ,
104+ token ,
92105 Boolean ( values [ "dry-run" ] ) ,
93106 ) ;
94107 }
0 commit comments