fix(windows): probe fnm's real default alias dir for Node fallback (#11359)

* fix(windows): probe fnm's real default alias dir for Node fallback

On Windows, fnm stores the default alias under FNM_DIR, else
%APPDATA%\fnm (legacy ~\.fnm), and node.exe sits directly in
aliases\default with no bin subdir. Probe those dirs and append them to
PATH so fnm's default only backfills a missing Node instead of shadowing
an inherited one.

Fixes #11356

Co-authored-by: niceSprite <16523864+iFwu@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>

* test: keep onTestFinished callbacks returning void

---------

Co-authored-by: Neil <neil@stably.ai>
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
niceSprite
2026-10-27 06:08:14 -07:00
committed by GitHub
co-authored by niceSprite Claude Neil
parent 62d9eb635b
commit 27a8963806
6 changed files with 74 additions and 5 deletions
+28 -1
View File
@@ -1,7 +1,7 @@
import { chmodSync, mkdtempSync, mkdirSync, rmSync, writeFileSync } from 'node:fs'
import { tmpdir } from 'node:os'
import { delimiter, dirname, join } from 'node:path'
import { afterEach, describe, expect, it, onTestFinished } from 'vitest'
import { afterEach, describe, expect, it, onTestFinished, vi } from 'vitest'
import {
getVersionManagerBinPaths,
withCliRuntimeOnPath,
@@ -319,6 +319,33 @@ describe('getVersionManagerBinPaths', () => {
expect(paths).toContain(join(root, '.local', 'bin'))
expect(paths).toContain(join(root, 'AppData', 'Roaming', 'npm'))
})
it('uses the Windows fnm default alias layout, honoring FNM_DIR (stablyai/orca#11356)', () => {
const root = makeCommandFixture('orca-vm-paths-')
const appDataAlias = join(root, 'AppData', 'Roaming', 'fnm', 'aliases', 'default')
vi.stubEnv('FNM_DIR', '')
vi.stubEnv('APPDATA', '')
onTestFinished(() => {
vi.unstubAllEnvs()
})
const paths = getVersionManagerBinPaths({ platform: 'win32', homePath: root })
expect(paths).toContain(appDataAlias)
expect(paths).not.toContain(join(root, '.fnm', 'aliases', 'default', 'bin'))
const redirectedAppData = join(root, 'redirected')
const redirectedAlias = join(redirectedAppData, 'fnm', 'aliases', 'default')
vi.stubEnv('APPDATA', redirectedAppData)
expect(getVersionManagerBinPaths({ platform: 'win32', homePath: root })).toContain(
redirectedAlias
)
const fnmDir = join(root, 'custom-fnm')
vi.stubEnv('FNM_DIR', fnmDir)
const overridden = getVersionManagerBinPaths({ platform: 'win32', homePath: root })
expect(overridden).toContain(join(fnmDir, 'aliases', 'default'))
expect(overridden).not.toContain(redirectedAlias)
})
})
describe('withCliRuntimeOnPath', () => {