Files
admin/.wiki/concepts/nvm-junction-ismain-gate-gotcha.md

77 lines
3.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: "nvm-junction isMain-gate gotcha — ESM main() молча не выполняется"
type: concept
tags: [node, esm, nvm, windows, junction, symlink, cli, gotcha, postmortem]
sources: []
related: [concepts/nvm-windows-node-switch.md]
updated: 2026-08-18
---
# nvm-junction isMain-gate gotcha
`import.meta.url === pathToFileURL(process.argv[1]).href` ломается, когда
`node` вызывается через junction/симлинк-префикс (nvm-windows, nvm/mise/volta
на *nix — те же грабли). Симптом: CLI-бинарь **молча no-op** — `--help`,
флаги, даже strict-parse ошибки: exit 0, пустой stdout для ЛЮБОГО вызова.
## Root cause
ESM резолвит `import.meta.url` в **realpath** файла, а `process.argv[1]`
держит **литеральный** путь из командной строки (через junction). Строки
разные → `main()` не вызывается, скрипт просто завершается.
Конкретика (найдено в CLI-F&F sched 2026-08-18):
```
C:\nvm4w\nodejs\node_modules\@sched\daemon\dist\cli.js --help
# junction C:\nvm4w\nodejs → realpath C:\Users\vitya\AppData\Local\nvm\v22.22.0
# import.meta.url = file:///C:/Users/vitya/AppData/Local/nvm/v22.22.0/.../cli.js (realpath)
# process.argv[1] = C:\nvm4w\nodejs\node_modules\@sched\daemon\dist\cli.js (literal)
# → != → main() не выполняется
```
Realpath-инвокация (`node <realpath>/cli.js`) работает идеально — поэтому
баг «плавающий»: у разработчика (из исходников) работает, у оператора
(global-установка под version-manager'ом) — нет.
## Фикс
Сравнивать realpath'ы обеих сторон:
```ts
import { realpathSync } from 'node:fs'
import { fileURLToPath } from 'node:url'
function isCliMain(argv1, metaUrl) {
if (!argv1) return false
return realpathSync(fileURLToPath(metaUrl)) === realpathSync(argv1)
}
```
TDD-покрытие: junction-регрессия через `fs.symlinkSync('junction')`,
real-path true, другой файл false, `argv1` undefined false. (sched
`apps/daemon/src/cli.ts`, коммит `bd38aab`, daemon 0.3.2.)
Альтернатива — не использовать isMain-гейт вовсе (как @sched/cli: бинарь
всегда main).
## Кого бьёт
Любой `bin` в npm-пакете с isMain-гейтом, установленный **глобально** под
version-manager'ом с junction/symlink-префиксом npm-рута:
- nvm-windows (`C:\nvm4w\nodejs` → junction на активную версию)
- nvm / volta / mise на *nix (симлинки в `~/.nvm/...`)
## Диагностика за 30 секунд
```
# из-под глобальной установки:
schedd --help # пусто, exit 0 → подозрение
node $(which schedd) --help # realpath-инвокация → полный help → подтверждено
```
## Проверено на Node 24
На Node 24.19.0 (nvm-windows, junction) тот же realpath-фикс работает:
`--help` полный, exit 0, stderr чист. См. [nvm-windows-node-switch](nvm-windows-node-switch.md).