rvlib-ts-tools
v0.3.3
Published
Toolbelt for TypeScript repos using absolute import specifiers with explicit extensions (repo-root paths, or package names in multi-package repos): fearless renames, import normalization with a CI gate, fast circular-dependency detection. Runs on Bun.
Readme
rvlib-ts-tools
Toolbelt for TypeScript repos that use absolute repo-root import specifiers with explicit extensions:
import { Foo } from 'src/features/foo/Foo.ts'Because the specifier IS the file's repo-relative path, imports become exact string search keys — so renames, normalization, and dependency analysis are reliable string operations, no resolver or language server needed. Runs on Bun.
Works on both repo shapes:
- single-package repo — every specifier is a repo-root path (
'src/...'). - multi-package repo — sub-folders with their own named package.json are auto-discovered. Files inside them are addressed by package name (
'my-lib/src/foo.ts'), which resolves identically in-repo (tsconfigpaths) and inside consumers' node_modules once published. One canonical rule: package-name form when the target lives in a sub-package, repo-root form otherwise.
Install
bun add -d rvlib-ts-toolsCommands
bunx rvt rename <src> <dst> [-x] # safe file/folder rename — rewrites every path ref
bunx rvt imports [--check|--fix] # normalize imports to absolute-with-extension
bunx rvt cycles [max] # count circular imports; exit 1 when count > maxrvt renameis a dry-run by default: it shows every file that changes (and flags suspicious substring matches) before you pass-xto apply. Moves the file withgit mvand rewrites all references in one shot.rvt imports --checkis a CI gate: exit 1 when any import needs a change or fails to resolve on disk.--fixrewrites in place. Pass file paths to fix just those files (handy as an editor on-save hook).rvt cycles 3fails when more than 3 elementary cycles exist — use it as a ratchet in CI and lower the number over time. Type-only imports do not count. Runs on a bare checkout in about a second, no install step.
Configuration
Zero-config by default:
- roots (which top-level dirs are crawled and which specifier prefixes are yours): read from the tsconfig
pathskeys ("src/*"→src), falling back tosrc/scripts. Entries can be top-level globs ("rv-*"). - packages: auto-discovered by walking the roots for named package.json files — no configuration.
- skip:
node_modules,.git,dist,build,cjs,outalways.
Override per repo via a rvt field in package.json:
{
"rvt": {
"roots": ["src", "scripts", "infra"],
"skip": ["src/legacy", "src/generated"] // bare names match any segment; paths are prefixes
}
}The tsconfig this expects
{
"compilerOptions": {
"module": "nodenext",
"moduleResolution": "nodenext",
"allowImportingTsExtensions": true,
"noEmit": true,
"paths": { "src/*": ["./src/*"] }
}
}Library use
Every command is also an exported function:
import { findCircularDependencies, runImports, runRename, loadConfig } from 'rvlib-ts-tools'
const cycles = findCircularDependencies(loadConfig())Suggested package.json scripts
{
"scripts": {
"rename": "rvt rename",
"imports:check": "rvt imports --check",
"imports:fix": "rvt imports --fix",
"cycles": "rvt cycles 1"
}
}