Config file structure
To get started, initialise your config:
rev-dep config init
Rev-dep automatically detects project context and creates scaffolding for each workspace package it discovers.
The config file can be named
rev-dep.config.json,rev-dep.config.jsonc,.rev-dep.config.json, or.rev-dep.config.jsoncdepending on your preference.
Top-level fields​
configVersion: Configuration version string$schema: JSON schema reference for validationconditionNames: custom condition order forpackage.jsonimports/exports resolution.customAssetExtensions: additional extensions that should be treated as resolvable imports.ignoreFiles: files excluded from analysis by rev-dep config, in addition to gitignored files.processIgnoredFiles: files that should still be processed even if gitignore or ignore patterns would normally skip them.nodeModulesResolution: controls whichpackage.jsonthird-party imports are validated against (and whether monorepo-root devDependencies count as available).rules: array of rules defining checks for different parts of the codebase. Typically single rule defines checks for single workspace package. However, you can have multiple rules with the samepathif that's needed.
Name
rulesmight be confusing, it's a bad design choice made at the beginning. This will be likely renamed toworkspacesorscopesin next major release to better reflect how it is actually being used.
Rule-level fields​
Each rule must define:
path- relative path to the workspace package that this rule applies to. Can be.for the root package.
And can additionally define:
followMonorepoPackages: Control monorepo package resolution.truefollows all workspace packages (default),falsedisables it, array follows only selected package names.prodEntryPoints: Rule-level production entry point patterns for detector defaultsdevEntryPoints: Rule-level development entry point patterns for detector defaultsignoreEntryPoints: Rule-level patterns for leftover entry points to exclude from reporting. Matching files are never reported as orphan files and their unused exports are not reported.
And any detector setup:
moduleBoundaries: Array of module boundary rulesrestrictedImportsDetection: Restrict importing denied files/modules from selected entry pointsrestrictedImportersDetection: Whitelist which entry points may transitively reach a set of files or modulesrestrictedDirectImportersDetection: Constrain which files may directly import a set of files or modules (non-transitive)importConventions: Array of import convention rulescircularImportsDetection: Circular import detection configurationorphanFilesDetection: Orphan files detection configurationunusedExportsDetection: Unused exports detection configurationunusedNodeModulesDetection: Unused node modules detection configurationmissingNodeModulesDetection: Missing node modules detection configurationdevDepsUsageOnProdDetection: Restricted dev dependencies usage detection configurationunresolvedImportsDetection: Unresolved imports detection configuration
Detectors can be defined as a single object or an array of objects. Defining multiple configurations for the same detector allows to run it multiple times with different settings (e.g., different entry points or different deny rules for restricted imports) within the same rule.
Compact detector syntax​
Detectors support a shorthand so simple configs stay short:
- Boolean. A detector that only needs to be switched on (no extra setup) can be written as a boolean.
"circularImportsDetection": trueenables it and"circularImportsDetection": falsedisables it — equivalent to{ "enabled": true }and{ "enabled": false }. - Optional
enabled. When a detector is configured with other options, theenabledflag is optional and defaults totrue."restrictedImportsDetection": { "entryPoints": ["src/index.ts"] }is enough to turn the check on; add"enabled": falseto keep the options but switch it off.
rev-dep config init writes configs in this compact form, and rev-dep config lint --fix rewrites an existing config to it (folding { "enabled": true } to true and dropping redundant enabled flags) without touching your comments or formatting — see the compact rule in Linting the config.
Quick Start configuration​
{
"nodeModulesResolution": { "resolutionType": "entry-package", "includeDevDepsFromRoot": false },
"rules": [
{
"path": ".",
"prodEntryPoints": ["src/main.tsx", "src/pages/**/*.tsx"],
"devEntryPoints": ["scripts/**", "**/*.test.*"],
"unusedExportsDetection": {
"autofix": true
},
"orphanFilesDetection": {
"autofix": true
},
"unusedNodeModulesDetection": true,
"circularImportsDetection": true,
"devDepsUsageOnProdDetection": {
"ignoreTypeImports": true
}
}
]
}
Add the $schema field (see the comprehensive example below) for editor autocomplete and validation.
Comprehensive Config Example​
Here's a comprehensive example showing all available properties:
{
"configVersion": "1.10",
// enables json autocompletion
"$schema": "https://github.com/jayu/rev-dep/blob/master/config-schema/1.10.schema.json?raw=true",
"conditionNames": ["import", "default"],
"ignoreFiles": ["**/*.test.*"],
"nodeModulesResolution": { "resolutionType": "entry-package", "includeDevDepsFromRoot": false },
"rules": [
{
"path": ".",
"followMonorepoPackages": true,
"prodEntryPoints": ["src/main.tsx", "src/pages/**/*.tsx", "src/server.ts"],
"devEntryPoints": ["scripts/**", "**/*.test.*"],
"ignoreEntryPoints": ["src/legacy/oldDashboard.tsx"],
"moduleBoundaries": [
{
"name": "ui-components",
"pattern": "src/components/**/*",
"allow": ["src/utils/**/*", "src/types/**/*"],
"deny": ["src/api/**/*"]
},
{
"name": "api-layer",
"pattern": "src/api/**/*",
"allow": ["src/utils/**/*", "src/types/**/*"],
"deny": ["src/components/**/*"]
}
],
"importConventions": [
{
"rule": "relative-internal-absolute-external",
"autofix": true,
"domains": [
{
"path": "src/features/auth",
"alias": "@auth",
"enabled": true
},
{
"path": "src/shared/ui",
"alias": "@ui-kit",
"enabled": false // checks disabled for this domain, but alias is still used for absolute imports from other domains
}
]
}
],
"circularImportsDetection": {
"enabled": true,
"ignoreTypeImports": true
},
"orphanFilesDetection": {
"enabled": true,
"ignoreTypeImports": true,
"graphExclude": ["**/*.test.*", "**/stories/**/*"],
"autofix": true
},
"unusedNodeModulesDetection": {
"enabled": true,
"includeModules": ["@myorg/**"],
"excludeModules": ["@types/**"],
"pkgJsonFieldsWithBinaries": ["scripts", "bin"],
"filesWithBinaries": ["scripts/check-something.sh"],
"filesWithModules": [".storybook/main.ts"],
"outputType": "groupByModule"
},
"missingNodeModulesDetection": {
"enabled": true,
"includeModules": ["lodash", "axios"],
"excludeModules": ["@types/**"],
"outputType": "groupByFile"
},
"unusedExportsDetection": {
"enabled": true,
"autofix": true,
"ignoreTypeExports": true,
"graphExclude": ["**/*.stories.tsx"],
"ignore": {
"src/types.ts": "B*",
"**/generated/**/*.ts": "*"
},
"ignoreFiles": ["**/*.generated.ts"],
"ignoreExports": ["default", "unused*"],
},
"unresolvedImportsDetection": {
"enabled": true,
"ignore": {
"src/index.ts": "legacy-*"
},
"ignoreFiles": ["**/*.generated.ts"],
"ignoreImports": ["@internal/*"]
},
"devDepsUsageOnProdDetection": {
"enabled": true,
"ignoreTypeImports": true
},
"restrictedImportsDetection": {
"enabled": true,
"entryPoints": ["src/server.ts", "src/server/**/*.ts"],
"graphExclude": ["some-file-coupling-other-files.ts"],
"denyFiles": ["**/*.tsx"],
"denyModules": ["react", "react-*"],
"ignoreMatches": ["src/server/allowed-view.tsx", "react-awesome-lib"],
"ignoreTypeImports": true
},
"restrictedImportersDetection": {
"enabled": true,
"files": ["src/legacy/**"],
"modules": ["moment", "@legacy/*"],
"allowedImporters": ["src/legacy-adapter.ts"],
"graphExclude": ["**/*.test.*"],
"ignoreMatches": ["src/legacy/public-api.ts"],
"ignoreTypeImports": true
}
}
]
}