Skip to content

Commit 2e7b8f7

Browse files
committed
feat(npmx-connector): add debug mode with extra logs, add one extra OTP case
1 parent cfd2822 commit 2e7b8f7

File tree

2 files changed

+17
-3
lines changed

2 files changed

+17
-3
lines changed

cli/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
"scripts": {
2929
"build": "tsdown",
3030
"dev": "NPMX_CLI_DEV=true node src/cli.ts",
31+
"dev:debug": "DEBUG=npmx-connector NPMX_CLI_DEV=true node src/cli.ts",
3132
"test:types": "tsc --noEmit"
3233
},
3334
"dependencies": {

cli/src/npm-client.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { tmpdir } from 'node:os'
77
import { join } from 'node:path'
88
import * as v from 'valibot'
99
import { PackageNameSchema, UsernameSchema, OrgNameSchema, ScopeTeamSchema } from './schemas.ts'
10-
import { logCommand, logSuccess, logError } from './logger.ts'
10+
import { logCommand, logSuccess, logError, logDebug } from './logger.ts'
1111

1212
const execFileAsync = promisify(execFile)
1313

@@ -75,10 +75,15 @@ function detectOtpRequired(stderr: string): boolean {
7575
'EOTP',
7676
'one-time password',
7777
'This operation requires a one-time password',
78+
'OTP required for authentication',
7879
'--otp=<code>',
7980
]
8081
const lowerStderr = stderr.toLowerCase()
81-
return otpPatterns.some(pattern => lowerStderr.includes(pattern.toLowerCase()))
82+
logDebug('Checking for OTP requirement in stderr:', stderr)
83+
logDebug('OTP patterns:', otpPatterns)
84+
const result = otpPatterns.some(pattern => lowerStderr.includes(pattern.toLowerCase()))
85+
logDebug('OTP required:', result)
86+
return result
8287
}
8388

8489
function detectAuthFailure(stderr: string): boolean {
@@ -96,7 +101,11 @@ function detectAuthFailure(stderr: string): boolean {
96101
'npm adduser',
97102
]
98103
const lowerStderr = stderr.toLowerCase()
99-
return authPatterns.some(pattern => lowerStderr.includes(pattern.toLowerCase()))
104+
logDebug('Checking for auth failure in stderr:', stderr)
105+
logDebug('Auth patterns:', authPatterns)
106+
const result = authPatterns.some(pattern => lowerStderr.includes(pattern.toLowerCase()))
107+
logDebug('Auth failure:', result)
108+
return result
100109
}
101110

102111
function filterNpmWarnings(stderr: string): string {
@@ -123,13 +132,16 @@ async function execNpm(
123132
}
124133

125134
try {
135+
logDebug('Executing npm command:', { command: 'npm', args: npmArgs })
126136
// Use execFile instead of exec to avoid shell injection vulnerabilities
127137
// execFile does not spawn a shell, so metacharacters are passed literally
128138
const { stdout, stderr } = await execFileAsync('npm', npmArgs, {
129139
timeout: 60000,
130140
env: { ...process.env, FORCE_COLOR: '0' },
131141
})
132142

143+
logDebug('Command succeeded:', { stdout, stderr })
144+
133145
if (!options.silent) {
134146
logSuccess('Done')
135147
}
@@ -142,6 +154,7 @@ async function execNpm(
142154
} catch (error) {
143155
const err = error as { stdout?: string; stderr?: string; code?: number }
144156
const stderr = err.stderr?.trim() ?? String(error)
157+
logDebug('Command failed:', { error, stdout: err.stdout, stderr: err.stderr, code: err.code })
145158
const requiresOtp = detectOtpRequired(stderr)
146159
const authFailure = detectAuthFailure(stderr)
147160

0 commit comments

Comments
 (0)