Проверка регистра
devtoolz case-check находит импорты, чей регистр не совпадает с реальным именем файла на диске.
devtoolz case-check [paths...] [options]Windows и macOS по умолчанию не различают регистр в путях файловой системы, так что import './foo' при реальном файле Foo.ts открывается без единой жалобы — ровно до того момента, пока тот же код не соберётся на Linux CI, где регистр важен. Проверяется каждый сегмент пути, не только имя самого файла (./Utils/helper при реальной директории utils/ — тоже находка, не только конечный файл), плюс импорт без расширения (import './Foo' сверяется по общему префиксу без расширения, реальный файл может быть Foo.ts).
Реальный вывод — файл переименован из Helper.ts в helper.ts, импорт не обновлён:
🧰 devtoolz, reporting for duty
Scanned 2 files.
1 case mismatch found:
src/main.ts:1:23 ./helper.js → ./Helper.js
(pass --fix -y to apply, or --fix --diff to preview the fix)Алиасы tsconfig.json
Алиасы из compilerOptions.paths/baseUrl резолвятся так же, как обычные относительные импорты — tsconfig.json автоопределяется в --cwd по умолчанию, либо задаётся явно через --tsconfig. Найденное через алиас несовпадение помечается отдельно и не переписывается --fix:
🧰 devtoolz
Scanned 2 files.
1 case mismatch found:
src/main.ts:1:23 @/utils/format.js → ./Utils/format.js (alias, not auto-fixed)Причина — переписывать @/utils/format.js на реальный регистр означало бы поменять и сам алиас на что-то, что уже не совпадает с тем, что заводили в tsconfig.json; безопаснее сообщить и оставить решение человеку.
Опции
--fix
Переписать несовпадающий специфайер на реальный регистр (алиас-резолвленные исключены, см. выше). Изначально написанное расширение сохраняется — меняется только регистр самого имени. Сам по себе --fix ничего не пишет без -y/--yes, для единообразия с остальными командами.
Превью фикса (--fix --diff --dry-run):
🧰 devtoolz — chores, automated
Scanned 2 files.
1 case mismatch found:
src/main.ts:1:23 ./helper.js → ./Helper.js
Would fix 1 import(s) in 1 file(s) — pass -y to apply.
── src/main.ts (1 import) ────────────────────────────────────────────
@@ -1,3 +1,3 @@
-import { greet } from './helper.js'
+import { greet } from './Helper.js'
console.log(greet('world'))Применённый фикс (--fix -y):
🧰 devtoolz — chores, automated
Scanned 2 files.
1 case mismatch found:
src/main.ts:1:23 ./helper.js → ./Helper.js
Fixed 1 import(s) in 1 file(s).--tsconfig <path>
tsconfig.json, из которого читать алиасы путей (по умолчанию автоопределяется в --cwd).
--dry-run
Показать превью без записи на диск.
-y, --yes
Реально применить фикс.
--diff
Unified diff по каждому изменённому файлу.
--cwd <path>
Корень, от которого резолвятся относительные пути.
--ext <list>
Через запятую, какие расширения обрабатывать. По умолчанию: .ts,.tsx,.js,.jsx,.cjs,.mjs,.vue.
--ignore <glob>
Дополнительный паттерн игнорирования (повторяемый) поверх встроенных дефолтов.
--no-respect-gitignore
Не учитывать .gitignore проекта.
Известные ограничения
- Голые импорты пакетов (
import 'lodash') — вне области действия,node_modulesне проверяется. - Регистро-нечувствительная файловая система может вообще не зафиксировать переименование файла как изменение в git локально — инструмент сверяется с тем, что реально лежит на диске прямо сейчас, а не с git-историей; это ограничение самого метода, не баг.
- Subpath-импорты (
#internal/...,imports-карта вpackage.json) пока не поддерживаются.
Пример:
devtoolz case-check src # только найти
devtoolz case-check src --fix --diff --dry-run # превью фикса
devtoolz case-check src --fix -y # применить
devtoolz case-check src --tsconfig ./tsconfig.app.json --fix -y