MCPcopy Index your code
hub / github.com/npmx-dev/npmx.dev / execNpmInteractive

Function execNpmInteractive

cli/src/npm-client.ts:180–320  ·  view source on GitHub ↗

* PTY-based npm execution for interactive commands (uses node-pty). * * - Web OTP - either open URL in browser if openUrls is true or passes the URL to frontend. If no auth happened within AUTH_URL_TIMEOUT_MS kills the process to unlock the connector. * * - CLI OTP - if we get a classic OTP prom

(
  args: string[],
  options: ExecNpmOptions = {},
)

Source from the content-addressed store, hash-verified

178 * - CLI OTP - if we get a classic OTP prompt will either return OTP request to the frontend or will pass sent OTP if its provided
179 */
180async function execNpmInteractive(
181 args: string[],
182 options: ExecNpmOptions = {},
183): Promise<NpmExecResult> {
184 const openUrls = options.openUrls === true
185 const { promise, resolve } = Promise.withResolvers<NpmExecResult>()
186
187 // Lazy-load node-pty so the native addon is only required when interactive mode is actually used.
188 const pty = await import('@lydell/node-pty')
189
190 const npmArgs = options.otp ? [...args, '--otp', options.otp] : args
191
192 if (!options.silent) {
193 const displayCmd = options.otp
194 ? ['npm', ...args, '--otp', '******'].join(' ')
195 : ['npm', ...args].join(' ')
196 logCommand(`${displayCmd} (interactive/pty)`)
197 }
198
199 let output = ''
200 let resolved = false
201 let otpPromptSeen = false
202 let authUrlSeen = false
203 let enterSent = false
204 let authUrlTimeout: ReturnType<typeof setTimeout> | null = null
205 let authUrlTimedOut = false
206
207 const env = createNpmEnv()
208
209 // When openUrls is false, tell npm not to open the browser.
210 // npm still prints the auth URL and polls doneUrl
211 if (!openUrls) {
212 env.npm_config_browser = 'false'
213 }
214
215 const child = pty.spawn('npm', npmArgs, {
216 name: 'xterm-256color',
217 cols: 120,
218 rows: 30,
219 cwd: options.cwd,
220 env,
221 })
222
223 // General timeout: 5 minutes (covers non-auth interactive commands)
224 const timeout = setTimeout(() => {
225 if (resolved) return
226 logDebug('Interactive command timed out', { output })
227 child.kill()
228 }, 300000)
229
230 child.onData((data: string) => {
231 output += data
232 const clean = stripAnsi(data)
233 logDebug('pty data:', { text: clean.trim() })
234
235 const cleanAll = stripAnsi(output)
236
237 // Detect auth URL in output and notify the caller.

Callers 1

execNpmFunction · 0.85

Calls 11

logCommandFunction · 0.90
logErrorFunction · 0.90
logSuccessFunction · 0.90
createNpmEnvFunction · 0.85
detectOtpRequiredFunction · 0.85
detectAuthFailureFunction · 0.85
extractUrlsFunction · 0.85
filterNpmWarningsFunction · 0.85
killMethod · 0.80
writeMethod · 0.80
stripAnsiFunction · 0.70

Tested by

no test coverage detected