@@ -18,17 +18,23 @@ function loadCredentials() {
1818 return { } ;
1919}
2020
21+ function normalizeCredentialValue ( value ) {
22+ if ( typeof value !== "string" ) return "" ;
23+ return value . replace ( / \r / g, "" ) . trim ( ) ;
24+ }
25+
2126function saveCredential ( key , value ) {
2227 fs . mkdirSync ( CREDS_DIR , { recursive : true , mode : 0o700 } ) ;
2328 const creds = loadCredentials ( ) ;
24- creds [ key ] = value ;
29+ creds [ key ] = normalizeCredentialValue ( value ) ;
2530 fs . writeFileSync ( CREDS_FILE , JSON . stringify ( creds , null , 2 ) , { mode : 0o600 } ) ;
2631}
2732
2833function getCredential ( key ) {
29- if ( process . env [ key ] ) return process . env [ key ] ;
34+ if ( process . env [ key ] ) return normalizeCredentialValue ( process . env [ key ] ) ;
3035 const creds = loadCredentials ( ) ;
31- return creds [ key ] || null ;
36+ const value = normalizeCredentialValue ( creds [ key ] ) ;
37+ return value || null ;
3238}
3339
3440function promptSecret ( question ) {
@@ -73,7 +79,10 @@ function promptSecret(question) {
7379 }
7480
7581 if ( ch === "\u0008" || ch === "\u007f" ) {
76- answer = answer . slice ( 0 , - 1 ) ;
82+ if ( answer . length > 0 ) {
83+ answer = answer . slice ( 0 , - 1 ) ;
84+ output . write ( "\b \b" ) ;
85+ }
7786 continue ;
7887 }
7988
@@ -91,6 +100,7 @@ function promptSecret(question) {
91100
92101 if ( ch >= " " ) {
93102 answer += ch ;
103+ output . write ( "*" ) ;
94104 }
95105 }
96106 }
@@ -125,7 +135,10 @@ function prompt(question, opts = {}) {
125135 return ;
126136 }
127137 const rl = readline . createInterface ( { input : process . stdin , output : process . stderr } ) ;
128- rl . question ( question , ( answer ) => {
138+ let finished = false ;
139+ function finish ( fn , value ) {
140+ if ( finished ) return ;
141+ finished = true ;
129142 rl . close ( ) ;
130143 if ( ! process . stdin . isTTY ) {
131144 if ( typeof process . stdin . pause === "function" ) {
@@ -135,7 +148,15 @@ function prompt(question, opts = {}) {
135148 process . stdin . unref ( ) ;
136149 }
137150 }
138- resolve ( answer . trim ( ) ) ;
151+ fn ( value ) ;
152+ }
153+ rl . on ( "SIGINT" , ( ) => {
154+ const err = Object . assign ( new Error ( "Prompt interrupted" ) , { code : "SIGINT" } ) ;
155+ finish ( reject , err ) ;
156+ process . kill ( process . pid , "SIGINT" ) ;
157+ } ) ;
158+ rl . question ( question , ( answer ) => {
159+ finish ( resolve , answer . trim ( ) ) ;
139160 } ) ;
140161 } ) ;
141162}
@@ -158,11 +179,20 @@ async function ensureApiKey() {
158179 console . log ( " └─────────────────────────────────────────────────────────────────┘" ) ;
159180 console . log ( "" ) ;
160181
161- key = await prompt ( " NVIDIA API Key: " , { secret : true } ) ;
182+ while ( true ) {
183+ key = normalizeCredentialValue ( await prompt ( " NVIDIA API Key: " , { secret : true } ) ) ;
162184
163- if ( ! key || ! key . startsWith ( "nvapi-" ) ) {
164- console . error ( " Invalid key. Must start with nvapi-" ) ;
165- process . exit ( 1 ) ;
185+ if ( ! key ) {
186+ console . error ( " NVIDIA API Key is required." ) ;
187+ continue ;
188+ }
189+
190+ if ( ! key . startsWith ( "nvapi-" ) ) {
191+ console . error ( " Invalid key. Must start with nvapi-" ) ;
192+ continue ;
193+ }
194+
195+ break ;
166196 }
167197
168198 saveCredential ( "NVIDIA_API_KEY" , key ) ;
@@ -229,6 +259,7 @@ module.exports = {
229259 CREDS_DIR ,
230260 CREDS_FILE ,
231261 loadCredentials,
262+ normalizeCredentialValue,
232263 saveCredential,
233264 getCredential,
234265 prompt,
0 commit comments