Skip to content

fix(cli): use a shared cross-platform npm process resolver without shell#2257

Open
MathurAditya724 wants to merge 5 commits intonpmx-dev:mainfrom
MathurAditya724:patch-5
Open

fix(cli): use a shared cross-platform npm process resolver without shell#2257
MathurAditya724 wants to merge 5 commits intonpmx-dev:mainfrom
MathurAditya724:patch-5

Conversation

@MathurAditya724
Copy link
Contributor

@MathurAditya724 MathurAditya724 commented Mar 24, 2026

Summary

Fixes the Windows connector auth flow while avoiding shell-based npm execution and DEP0190 warnings.

What changed

  • Added a shared npm process resolver in cli/src/npm-process.ts.
  • Routed npm invocations through this resolver in:
    • cli/src/cli.ts (npm login)
    • cli/src/npm-client.ts (non-interactive npm exec + package publish path)
  • Kept interactive PTY execution using npm directly.
  • On Windows, npm now runs via cmd.exe /d /s /c npm ... (no shell: true, no direct npm.cmd spawn).
  • Cleaned up an unused exported type to satisfy unused-code checks.

Why

The previous approach removed DEP0190 warnings but caused Windows runtime failures (spawn EINVAL) in login flow.
Using a centralized, explicit cross-platform command resolver keeps behavior consistent and avoids shell-based execution.

Closes #2216

@vercel
Copy link

vercel bot commented Mar 24, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
docs.npmx.dev Ready Ready Preview, Comment Mar 24, 2026 10:44am
npmx.dev Ready Ready Preview, Comment Mar 24, 2026 10:44am
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
npmx-lunaria Ignored Ignored Mar 24, 2026 10:44am

Request Review

@codecov
Copy link

codecov bot commented Mar 24, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ All tests successful. No failed tests found.

📢 Thoughts on this report? Let us know!

@mynameistito
Copy link

Dam I got nerd sniped!

Lmk if ya need a test on Windows (if you're not also on Windows / have a windows machine)

@MathurAditya724
Copy link
Contributor Author

if you have a windows machine, go ahead, more the testers the better. I don't have one, so was planning to ask my friend today evening, will mention how that went.

@mynameistito
Copy link

Checking it out now, are you in the discord? @MathurAditya724

there is a few issues with your implementation.

@MathurAditya724
Copy link
Contributor Author

yes, I'm .n1ghtmare.

@mynameistito
Copy link

mynameistito commented Mar 24, 2026

As stated on Discord, the changes you made seemed to have caused some issues;

my output with your changes
PS F:\GitHub\temp\npmx.dev\cli> npmx-connector
┌   npmx connector
│
▲  This allows npmx.dev to access your npm cli and any authenticated contexts.
│
◇  Do you accept?
│  Yes
│
●  Checking npm authentication...
│
▲  Not logged in to npm. Starting npm login...

Error: spawn EINVAL
    at ChildProcess.spawn (node:internal/child_process:421:11)
    at spawn (node:child_process:796:9)
    at file:///F:/GitHub/temp/npmx.dev/cli/dist/cli.mjs:16:17
    at new Promise (<anonymous>)
    at runNpmLogin (file:///F:/GitHub/temp/npmx.dev/cli/dist/cli.mjs:15:9)
    at Object.run (file:///F:/GitHub/temp/npmx.dev/cli/dist/cli.mjs:54:31)
    at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
    at async runCommand (file:///F:/GitHub/temp/npmx.dev/node_modules/.pnpm/citty@0.2.1/node_modules/
citty/dist/index.mjs:188:47)
    at async runMain (file:///F:/GitHub/temp/npmx.dev/node_modules/.pnpm/citty@0.2.1/node_modules/cit
ty/dist/index.mjs:285:10) {
  errno: -4071,
  code: 'EINVAL',
  syscall: 'spawn'
}

I asked Claude to fix up the issues and this was the Fix that the model proposed and I tested it manually and seems to work as intended;

Fix suggested by Claude Opus 4.6 Lines 15, through 21
// ~/cli.ts
-const NPM_COMMAND = process.platform === 'win32' ? 'npm.cmd' : 'npm'
-
 async function runNpmLogin(): Promise<boolean> {
   return new Promise(resolve => {
-    const child = spawn(NPM_COMMAND, ['login', `--registry=${NPM_REGISTRY_URL}`], {
-      stdio: 'inherit',
-    })
+
+    const loginArgs = ['login', `--registry=${NPM_REGISTRY_URL}`]
+    const child =
+      process.platform === 'win32'
+        ? spawn('cmd.exe', ['/c', 'npm', ...loginArgs], { stdio: 'inherit' })
+        : spawn('npm', loginArgs, { stdio: 'inherit' })

Routing through cmd.exe /c npm on Windows avoids both EINVAL and the DEP0190 warning — no .cmd file is spawned directly, and no shell: true is needed.

Might be good to get some more eyes on it though.

@mynameistito
Copy link

mynameistito commented Mar 24, 2026

Seems to work as intended now;

Whilst Logged in to npmjs;

PS F:\GitHub\temp\npmx.dev\cli> bun run build
$ tsdown
ℹ tsdown v0.21.4 powered by rolldown v1.0.0-rc.9
ℹ config file: F:\GitHub\temp\npmx.dev\cli\tsdown.config.ts
ℹ entry: src\index.ts, src\cli.ts
ℹ target: node24.0.0
ℹ tsconfig: tsconfig.json

 WARN  `external` is deprecated. Use `deps.neverBundle` instead.

ℹ Build start
ℹ Granting execute permission to dist\cli.mjs
ℹ dist\cli.mjs                       2.62 kB │ gzip:  1.23 kB
ℹ dist\index.mjs                     0.17 kB │ gzip:  0.14 kB
ℹ dist\server-FP9KQp94.mjs.map      81.93 kB │ gzip: 18.58 kB
ℹ dist\server-FP9KQp94.mjs          40.86 kB │ gzip:  9.61 kB
ℹ dist\cli.mjs.map                   4.53 kB │ gzip:  1.91 kB
ℹ dist\index.d.mts.map               2.16 kB │ gzip:  0.67 kB
ℹ dist\node-pty-PmtOFpde.d.mts.map   1.45 kB │ gzip:  0.65 kB
ℹ dist\index.d.mts                   5.20 kB │ gzip:  1.60 kB
ℹ dist\cli.d.mts                     0.01 kB │ gzip:  0.03 kB
ℹ dist\node-pty-PmtOFpde.d.mts       1.52 kB │ gzip:  0.59 kB
ℹ 10 files, total: 140.45 kB
✔ Build complete in 678ms
PS F:\GitHub\temp\npmx.dev\cli> bun install
bun install v1.3.11 (af24e281)

Checked 57 installs across 83 packages (no changes) [11.00ms]
PS F:\GitHub\temp\npmx.dev\cli> bun run build
$ tsdown
ℹ tsdown v0.21.4 powered by rolldown v1.0.0-rc.9
ℹ config file: F:\GitHub\temp\npmx.dev\cli\tsdown.config.ts
ℹ entry: src\index.ts, src\cli.ts
ℹ target: node24.0.0
ℹ tsconfig: tsconfig.json

 WARN  `external` is deprecated. Use `deps.neverBundle` instead.

ℹ Build start
ℹ Cleaning 11 files
ℹ Granting execute permission to dist\cli.mjs
ℹ dist\cli.mjs                       2.62 kB │ gzip:  1.23 kB
ℹ dist\index.mjs                     0.17 kB │ gzip:  0.14 kB
ℹ dist\server-FP9KQp94.mjs.map      81.93 kB │ gzip: 18.58 kB
ℹ dist\server-FP9KQp94.mjs          40.86 kB │ gzip:  9.61 kB
ℹ dist\cli.mjs.map                   4.53 kB │ gzip:  1.91 kB
ℹ dist\index.d.mts.map               2.16 kB │ gzip:  0.67 kB
ℹ dist\node-pty-PmtOFpde.d.mts.map   1.45 kB │ gzip:  0.65 kB
ℹ dist\index.d.mts                   5.20 kB │ gzip:  1.60 kB
ℹ dist\cli.d.mts                     0.01 kB │ gzip:  0.03 kB
ℹ dist\node-pty-PmtOFpde.d.mts       1.52 kB │ gzip:  0.59 kB
ℹ 10 files, total: 140.45 kB
✔ Build complete in 627ms
PS F:\GitHub\temp\npmx.dev\cli> bun link
bun link v1.3.11 (af24e281)
Success! Registered "npmx-connector"

To use npmx-connector in a project, run:
  bun link npmx-connector

Or add it in dependencies in your package.json file:
  "npmx-connector": "link:npmx-connector"
PS F:\GitHub\temp\npmx.dev\cli> npmx-connector
┌   npmx connector
│
▲  This allows npmx.dev to access your npm cli and any authenticated contexts.
│
◇  Do you accept?
│  Yes
│
●  Checking npm authentication...
│
●  Authenticated as: mynameistito
│
◇  Click to connect ──────────────────────────────────────────────────────────╮
│                                                                             │
│  Open: https://npmx.dev/?token=$TOKEN&port=31415  │
│                                                                             │
│  Or paste token manually: $TOKEN                  │
│                                                                             │
├─────────────────────────────────────────────────────────────────────────────╯
➜ Listening on: http://127.0.0.1:31415/
│
●  Waiting for connection... (Press Ctrl+C to stop)
Server closed successfully.
PS F:\GitHub\temp\npmx.dev\cli>

Without being logged into npmjs;

PS F:\GitHub\temp\npmx.dev\cli> npmx-connector
┌   npmx connector
│
▲  This allows npmx.dev to access your npm cli and any authenticated contexts.
│
◇  Do you accept?
│  Yes
│
●  Checking npm authentication...
│
▲  Not logged in to npm. Starting npm login...

npm notice Log in on https://registry.npmjs.org/
Login at:
https://www.npmjs.com/login?next=/login/cli/$UUID
Press ENTER to open in the browser...
/

However, there was an issue when trying to originally build on src/server.ts L 90 which doesnt seem to be related to your changes;

-export function createConnectorApp(expectedToken: string) {
+export function createConnectorApp(expectedToken: string): H3 {

@RYGRIT
Copy link
Contributor

RYGRIT commented Mar 24, 2026

Thanks for tackling this!

Directly spawning npm.cmd on Windows isn’t safe — see Node.js issue #58763 and the docs: .cmd/.bat files can’t be executed directly on Windows, they need a shell. Using args + shell: true triggers DEP0190 because args are just space-joined.

I’d recommend using cmd.exe /c npm ... on Windows.

@MathurAditya724 MathurAditya724 changed the title fix(cli): avoid DEP0190 warning on Windows by using npm.cmd instead of shell execution fix(cli): use a shared cross-platform npm process resolver without shell Mar 24, 2026
@MathurAditya724
Copy link
Contributor Author

@RYGRIT just changed the approach, thanks to @mynameistito, and update the PR title and description to better reflect what we have done

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 24, 2026

📝 Walkthrough

Walkthrough

This PR introduces platform-specific npm command resolution to eliminate the Node.js DEP0190 deprecation warning. A new utility module npm-process.ts exports resolveNpmProcessCommand(), which handles platform differences: on Windows, it invokes npm through cmd.exe with appropriate arguments; on other platforms, it directly calls npm. The cli.ts and npm-client.ts files are updated to use this utility instead of directly spawning npm with shell: true, centralising platform handling and removing the security-relevant deprecation warning.

Possibly related PRs

Suggested reviewers

  • danielroe
  • ghostdevv
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes implement platform-aware npm command selection and remove shell-based execution, directly addressing issue #2216's requirement to eliminate the DEP0190 warning by avoiding shell: true.
Out of Scope Changes check ✅ Passed All code changes are scoped to npm process handling across three files (cli.ts, npm-client.ts, npm-process.ts) and directly support the DEP0190 warning fix without unrelated modifications.
Description check ✅ Passed The pull request description clearly explains the changes made, the rationale (avoiding DEP0190 warnings and shell-based execution), and references the closed issue.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
cli/src/npm-client.ts (1)

336-337: Please route the PTY path through the same resolver as well.

These two call sites now use resolveNpmProcessCommand(), but execNpmInteractive() still hardcodes pty.spawn('npm', npmArgs, ...) at Line 213. On Windows, Node documents that .cmd entrypoints need a terminal/cmd.exe, and node-pty’s own Windows example launches a shell rather than a raw command, so the interactive OTP/browser-auth branch is still on a different launcher. Please wire it through the same resolver, or an equivalent PTY-safe wrapper, so Windows behaviour stays consistent. (nodejs.org)

Also applies to: 611-612


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e08d4647-5925-49aa-87af-4b52453a8238

📥 Commits

Reviewing files that changed from the base of the PR and between 84a7fc9 and d35ff2f.

📒 Files selected for processing (3)
  • cli/src/cli.ts
  • cli/src/npm-client.ts
  • cli/src/npm-process.ts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG - cli win] DEP0190 deprecation warning

3 participants