3.3 KiB
title, type, tags, sources, related, updated
| title | type | tags | sources | related | updated | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| nvm-junction isMain-gate gotcha — ESM main() молча не выполняется | concept |
|
|
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'ы обеих сторон:
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.