Repository navigation
refactor: import Node built-ins with the node: prefix - #657
Merged
sirmalloc merged 2 commits intoOct 6, 2026
Merged
Conversation
The codebase mixed two styles for Node's own modules: a handful of files
imported 'node:fs', 'node:os' and friends while the rest used bare ids
such as 'fs' and 'child_process'. Use the node: prefix everywhere, so
each import says plainly that it is Node's module and cannot resolve to
an npm package of the same name.
This covers static imports and re-exports, type-only imports, dynamic
import(), require() (including the script the Custom Command widget
hands to a child runtime and the scripts tests write to disk), and
vi.mock() ids in tests. Vitest and Bun resolve 'child_process' and
'node:child_process' to the same module, for both mocks and spies, so
every mock still applies to the code under test. ESLint's import order
moved five imports to keep builtins sorted.
No behavior change. The bundle already loads node: imports, and every
Node version that can load the bundle also supports require('node:...').
Owner
|
Restored the two unprefixed We plan to raise the minimum to at least Node 20, alongside a custom launcher that shows an update message in the status line for users running older versions. All other imports retain the |
pcvelz
added a commit
to pcvelz/ccstatusline-usage
that referenced
this pull request
Oct 11, 2026
Upstream: label prefixes editable with e (sirmalloc#601, sirmalloc#666), Session Cost Rate (sirmalloc#671) and Extra Usage Daily Budget (sirmalloc#672) widgets, own-lock-only usage lock clearing (sirmalloc#624), NO_PROXY and request deadlines, terminal control-sequence sanitizing, git hardening and linear-time parsing, shared searchable option editor (sirmalloc#649) and widget base classes (sirmalloc#646-sirmalloc#654), node: imports (sirmalloc#657), Number.* globals lint (sirmalloc#645), test waits on redraw instead of fixed delays (sirmalloc#652). Hand edits outside conflicts: - src/widgets/shared/searchable-option-editor.tsx: compat fix - ports the fork's ref-based input handling (Enter picks from what was just typed) into upstream's new shared editor - src/utils/usage-fetch.ts: compat fix - fork's fetchFreshUsageData uses upstream's clearOwnUsageLock (sirmalloc#624) instead of the removed clearUsageLock - src/widgets/ApiUsage.tsx, src/widgets/Battery.ts: compat fix - Number.isNaN/Number.parseInt for upstream's no-restricted-globals rule - src/utils/__tests__/usage-prefetch.test.ts: compat fix - mock renamed to upstream's mockFetchUsage - src/tui/components/__tests__/PowerlineSetup.test.ts, src/tui/components/__tests__/StatusLinePreview.test.ts, src/tui/components/__tests__/TerminalWidthMenu.test.ts: compat fix - drop the fork's flushInk import, unused after upstream's waitFor switch - README.md: upstream notes linked docs/USAGE.md (deleted in the fork); inlined the proxy and workspace-trust text instead; upstream's own release-note entries not taken - .fork-keep-deleted: src/widgets/FableWeeklyUsage.ts (upstream widget, unregistered in the fork, which ships WeeklyFableUsage.ts) - src/widgets/WeeklyFableUsage.ts: compat fix - adopts upstream's shared getUsagePercentWidgetEditorDisplay, which carries the time-cursor modifier - src/tui/__tests__/App.test.ts: fork deviation - one extra down-arrow for the fork's Off Hours main-menu row - src/widgets/__tests__/CacheTimer.test.ts, src/widgets/CacheTimer.ts: compat fix - emoji toggle moved from e to o because upstream reserves e for edit-label - src/widgets/AgentAddress.ts: split the session-title guard into its own if (same behaviour) so the .fork-invariants nameSource guard matches again - docs/test-retirements.md: ledger for tests upstream renamed or replaced
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Every import of a Node.js built-in module now uses the
node:prefix:'fs'→'node:fs','child_process'→'node:child_process', and likewise forpath,os,crypto,https,module,url,util,events,ttyandstring_decoder. That covers 84 files (30 runtime/script files, 54 test files) and 203 lines. Nothing visible changes and there's no behavior change.Why
mainmixes both styles. Seven runtime files (custom-command.ts,git.ts,git-review-cache.ts,jsonl-blocks.ts,jsonl-cache.ts,jsonl-metrics.ts,CurrentWorkingDir.tsx) and 19 test files already import withnode:, and two more tests use it inrequire(). Meanwhile 30 runtime/script files and 54 test files use bare ids, and 13 files mix both styles in the same import block (for example,git.tsimports'child_process'next to'node:fs').The prefix says plainly that a module is Node's own and can't resolve to an npm package of the same name. Using one style also ends the per-file choice.
The published bundle already contains
node:imports, because Bun keeps them as written indist/. So the minimum Node version the package needs doesn't change (details under How).How
Every form a module id takes was converted:
import/export ... from, includingimport typeimport()(ccstatusline.ts,powerline.ts)require(): the script the Custom Command widget passes to a child runtime with-e, and the helper scripts tests write to disk and runvi.mock()ids in testsESLint's
import-x/orderkeeps builtins and packages in one alphabetized group, so its auto-fix moved five imports (https-proxy-agentnow sorts beforenode:*, andnode:cryptobeforenode:fs). No other edits.Mocks. The only built-in mocked by id is
child_process, in 30 test files, and all 30 now usevi.mock('node:child_process', ...), the same id the code under test imports. I checked under both Bun's test runner and Vitest on Node that a mock registered under either id applies to static and dynamic imports of both'child_process'and'node:child_process'. Neither runner applies mocks tocreateRequire()calls, so the three tests that userequire('node:child_process')to reach the realexecFileSyncpast the mock still get the real one.vi.spyOnon a module namespace sees the same object for'os'and'node:os'in both runners. As a control, I pointed each of the 30 mocks at an unused built-in (node:dgram), and 29 files then failed when run alone, so their mocks are in effect. The other one,CompactionCounter.test.ts, passes either way onmaintoo; its mock is a guard those tests never reach.Minimum Node version. The Custom Command child script now does
require('node:child_process'), andrequire()acceptsnode:only from Node 16.0 (and 14.18).main's bundle already needs Node 16.6, because its entry chunk callsArray.prototype.atat module load (inget-east-asian-width). Official Node 16.5.0 fails to load bothmainand this branch with the sameambiguousRanges.at is not a function. Node 16.6.0 renders a Custom Command line identically on both.Demo
No demo: nothing visible changes.
Testing
bun run lint: passes.bun test(Bun 1.4.2): 2358 pass, 0 fail, 5210expect()calls across 148 files, the same totals asmain. The JUnit reports matchmaintest by test, assertion counts included.node node_modules/vitest/vitest.mjs run --reporter=json): this branch has 2336 tests, 2185 passed, 151 failed in 17 files. A cleanmaingives the same 151 failures in 17 files, matching test by test; the failures come from spying on Node built-ins, which Node forbids. The only difference: two files that fail at load on both quote the mock id in their error message (No "spawn" export is defined on the "node:child_process" mock). A firstmainrun also failed 5 timing-sensitive TUI/process tests that passed on rerun; this branch had none of them.runtime-check.sh refactor/node-protocol-imports, which builds this branch andmain):echo hello-from-cmd) renders byte-for-byte the same onmainand this branch under Bun 1.4.2, Node 26.10.0 and Node 16.6.0.require('module').builtinModules, in anyfrom/import/import()/require()/vi.mock()position, matches nothing. Searching for any quoted built-in name at all finds only the'url'editor-mode literal insrc/widgets/Link.tsx, which isn't a module id.