Skip to content

chore: normalize Node builtin imports to the node: prefix#307

Open
jaredglaser wants to merge 1 commit into
mainfrom
claude/node-vs-bun-modules-f8qgep
Open

chore: normalize Node builtin imports to the node: prefix#307
jaredglaser wants to merge 1 commit into
mainfrom
claude/node-vs-bun-modules-f8qgep

Conversation

@jaredglaser

@jaredglaser jaredglaser commented Jun 21, 2026

Copy link
Copy Markdown
Owner

What

Adds the node: prefix to every bare Node builtin import specifier across 26 files (crypto, fs, fs/promises, path, stream, readline, child_process, url), plus the dynamic await import('crypto') in git-tokens.functions.tsx. Specifier strings only, no logic changes (43 insertions / 43 deletions, fully symmetric).

Why

This started from the question "should we replace node: APIs with Bun alternatives?" The conclusion was no: Bun implements node:* natively and recommends the prefixed form, and swapping src/ to Bun.* APIs would couple shared code to Bun for negligible benefit. The genuinely useful cleanup was the opposite direction: most of the codebase already uses the node: prefix, but ~26 files used bare specifiers. This change makes them consistent.

Background: the "run dev under Bun" idea was tried and dropped

A second change was scoped to make bun dev run under Bun (via bun --bun vite) so dev matches the prod/worker runtime. During validation it was found to break the dev server: it boots (VITE ready) but returns HTTP 500 on every request because Nitro's Vite dev entry wires websocket support through crossws, whose Node adapter rejects the Bun runtime. That isn't a quick/safe fix (disabling websockets would break real features), so the dev-runtime change was reverted and is not part of this PR. Dev stays on Node, prod stays on Bun, and src/ remains runtime-agnostic, which is exactly why the node: builtins (not Bun.*) are the right call.

How to reproduce the dev-under-Bun failure locally

This PR does NOT contain these changes. Apply them yourself to observe the issue:

  1. In package.json, change the dev script:

    -    "dev": "vite dev --port 3000",
    +    "dev": "bun --bun vite dev --port 3000",

    The --bun flag overrides the vite binary's #!/usr/bin/env node shebang and forces the Bun runtime. Without it, bun dev still runs Vite under Node.

  2. Make sure deps are installed (bun run setup), then start dev:

    bun dev

    It boots fine:

    $ bun --bun vite dev --port 3000
      VITE v8.0.16  ready in ~3000 ms
      ➜  Local:   http://localhost:3000/
    
  3. Hit any route and watch it fail:

    curl -i http://localhost:3000/

    Returns HTTP/1.1 500, and the dev server stdout prints:

    error: [crossws] Using Node.js adapter in an incompatible environment.
        at nodeAdapter (node_modules/crossws/dist/_chunks/node.mjs:25:17)
        at nitro/dist/runtime/internal/vite/dev-entry.mjs:21:52
    
  4. Revert the package.json change to get a working dev server again.

Root cause: vite.config.ts enables nitro({ ..., features: { websocket: true } }). Nitro's Vite dev entry instantiates the crossws Node adapter for websocket support, and that adapter throws when it detects a non-Node runtime (Bun). The web server only runs under Bun in production (Dockerfile: bun .output/server/index.mjs), where this dev-only Nitro path isn't used, so prod is unaffected.

Possible paths to actually enable it (out of scope here, would need investigation): a Nitro Bun/dev preset or a crossws Bun adapter, or gating features.websocket per-environment if dev websockets aren't needed.

Verification

  • bun run typecheck:all passes.
  • bun run test:all: identical results before and after (2479 pass / 396 fail), and identical to the base commit. The pre-existing failures are unrelated environment/mock-isolation issues, not introduced here.

🤖 Generated with Claude Code

Add the node: prefix to every bare Node builtin import specifier across
26 files (crypto, fs, fs/promises, path, stream, readline, child_process,
url) plus the dynamic await import('crypto'). Specifier strings only, no
logic changes. Matches the node: prefix already used elsewhere and Bun's
recommended form for builtins.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FxgTwf24W7eq49v7fV7CdD
@coderabbitai

coderabbitai Bot commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

All Node.js built-in module imports across 26 source and test files are updated from bare specifiers (fs, path, crypto, stream, readline, child_process, url) to explicit node:-prefixed specifiers. No functional logic, exported APIs, or test assertions are changed.

Changes

node: specifier migration

Layer / File(s) Summary
Production source imports
.github/scripts/triage-issues.ts, scripts/download-icons.ts, src/data/git-tokens.functions.tsx, src/lib/auth/login-handler.ts, src/lib/auth/logout-handler.ts, src/lib/database/migrate.ts, src/lib/parsers/text-parser.ts, src/lib/stream-utils.ts, src/lib/test/stream-utils.ts, src/lib/test/tmp-dir.ts
Bare Node.js module specifiers (fs, path, crypto, stream, readline, child_process, url, fs/promises) replaced with node:-prefixed equivalents across all production and script source files.
Test file imports
agent/src/__tests__/stacks.test.ts, src/lib/auth/__tests__/*, src/lib/config/__tests__/git-config.test.ts, src/lib/database/__tests__/migrate.test.ts, src/lib/deploy/__tests__/stack-repo-writer.test.ts, src/lib/git/__tests__/*, src/lib/parsers/__tests__/text-parser.test.ts, src/lib/test/__tests__/stream-utils.test.ts
All test files apply the same node: prefix migration for fs, path, crypto, and stream imports without altering any test logic or assertions.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~3 minutes

Poem

🐇 Hop hop, a tidy spree,
node: prefixes, plain to see.
From crypto to node:crypto we go,
fs, path, and stream join the show.
No logic changed, just strings made right —
The warren gleams in explicit light! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'chore: normalize Node builtin imports to the node: prefix' clearly and accurately summarizes the main change across 26 files, making it easy for teammates to understand the PR's primary purpose.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/node-vs-bun-modules-f8qgep

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.

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.

2 participants