ESLint plugin for Nx monorepos with boundary enforcement and dependency management rules.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
The enforce-module-boundaries rule is the cornerstone of Nx workspace integrity, ensuring proper separation of concerns and preventing architectural violations through comprehensive dependency analysis.
Validates import statements against configured dependency constraints, checking for proper module boundaries, circular dependencies, and tagging compliance.
/**
* ESLint rule that enforces module boundaries within Nx workspaces
* Rule name: "@nx/enforce-module-boundaries"
*/
interface EnforceModuleBoundariesRule {
name: "enforce-module-boundaries";
meta: {
type: "suggestion";
docs: {
description: "Ensure that module boundaries are respected within the monorepo";
};
fixable: "code";
schema: [EnforceModuleBoundariesOptions];
messages: Record<MessageIds, string>;
};
defaultOptions: [EnforceModuleBoundariesOptions];
create: (context: RuleContext) => RuleListener;
}Complete configuration interface for the enforce-module-boundaries rule.
interface EnforceModuleBoundariesOptions {
/** Array of allowed import patterns that bypass all boundary checks */
allow: string[];
/** Build target names used to determine buildable libraries */
buildTargets: string[];
/** Dependency constraints that define allowed relationships between projects */
depConstraints: DepConstraint[];
/** Enforce that libraries can only depend on other buildable libraries */
enforceBuildableLibDependency: boolean;
/** Allow projects to import from themselves (circular self-dependency) */
allowCircularSelfDependency: boolean;
/** Array of [source, target] project pairs to ignore for circular dependency checks */
ignoredCircularDependencies: Array<[string, string]>;
/** Project names exempt from dynamic dependency checks */
checkDynamicDependenciesExceptions: string[];
/** Prevent imports of transitive dependencies not declared in package.json */
banTransitiveDependencies: boolean;
/** Check for nested external imports beyond top-level package imports */
checkNestedExternalImports: boolean;
}Configuration for tag-based dependency rules and external import restrictions.
interface DepConstraint {
/** Source tag that this constraint applies to */
sourceTag: string;
/** If specified, projects with sourceTag can only depend on libraries with these tags */
onlyDependOnLibsWithTags?: string[];
/** If specified, projects with sourceTag cannot depend on libraries with these tags */
notDependOnLibsWithTags?: string[];
/** External imports that are banned for projects with this sourceTag */
bannedExternalImports?: string[];
/** Wildcard patterns for banned external imports */
bannedExternalImportsPatterns?: string[];
/** Allow specific external imports despite being in bannedExternalImports */
allowedExternalImports?: string[];
}
/** Union type for complex constraint combinations */
type ComboDepConstraint = {
allOf: DepConstraint[];
} | {
anyOf: DepConstraint[];
};The rule comes with sensible defaults for most Nx workspaces.
const DEFAULT_OPTIONS: EnforceModuleBoundariesOptions = {
allow: [],
buildTargets: ['build'],
depConstraints: [],
enforceBuildableLibDependency: false,
allowCircularSelfDependency: false,
checkDynamicDependenciesExceptions: [],
ignoredCircularDependencies: [],
banTransitiveDependencies: false,
checkNestedExternalImports: false
};All possible violation messages returned by the rule.
type MessageIds =
| "noRelativeOrAbsoluteImportsAcrossLibraries"
| "noRelativeOrAbsoluteExternals"
| "noSelfCircularDependencies"
| "noCircularDependencies"
| "noImportsOfApps"
| "noImportsOfE2e"
| "noImportOfNonBuildableLibraries"
| "noImportsOfLazyLoadedLibraries"
| "projectWithoutTagsCannotHaveDependencies"
| "bannedExternalImportsViolation"
| "nestedBannedExternalImportsViolation"
| "noTransitiveDependencies"
| "onlyTagsConstraintViolation"
| "emptyOnlyTagsConstraintViolation"
| "notTagsConstraintViolation";Usage Examples:
// Basic usage in ESLint config
{
rules: {
"@nx/enforce-module-boundaries": [
"error",
{
depConstraints: [
{
sourceTag: "scope:shared",
onlyDependOnLibsWithTags: ["scope:shared"]
},
{
sourceTag: "type:feature",
onlyDependOnLibsWithTags: ["type:ui", "type:data-access", "type:util"]
}
],
enforceBuildableLibDependency: true,
allow: ["^@myorg/shared-.*"]
}
]
}
}
// Complex constraints with banned imports
{
rules: {
"@nx/enforce-module-boundaries": [
"error",
{
depConstraints: [
{
sourceTag: "platform:web",
bannedExternalImports: ["react-native", "@react-native/*"],
onlyDependOnLibsWithTags: ["platform:web", "platform:shared"]
},
{
sourceTag: "scope:admin",
notDependOnLibsWithTags: ["scope:customer"],
bannedExternalImports: ["lodash"]
}
],
banTransitiveDependencies: true,
checkNestedExternalImports: true
}
]
}
}
// Ignoring specific circular dependencies
{
rules: {
"@nx/enforce-module-boundaries": [
"error",
{
allowCircularSelfDependency: true,
ignoredCircularDependencies: [
["project-a", "project-b"],
["legacy-lib", "legacy-utils"]
]
}
]
}
}The rule performs several types of validation:
The rule integrates deeply with Nx's project graph system:
Install with Tessl CLI
npx tessl i tessl/npm-nx--eslint-plugin