@libar-dev/eslint-plugin-directives
v0.2.0
Published
ESLint plugin for architectural directives — self-documenting, structured alternatives to eslint-disable comments
Maintainers
Readme
@libar-dev/eslint-plugin-directives
ESLint plugin for architectural directives — self-documenting, structured alternatives to eslint-disable comments.
What are Architectural Directives?
Instead of suppressing lint errors with // eslint-disable-next-line, architectural directives document why a deviation exists:
// Bad: opaque suppression
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type Wrapper<T extends any> = { value: T };
// Good: self-documenting directive
// @architectural-directive: library-generic-constraint
// Reason: Generic constraint requires any for library-level type abstraction
type Wrapper<T extends any> = { value: T };Directives serve as both documentation and ESLint suppressions — no eslint-disable needed.
Installation
npm install --save-dev @libar-dev/eslint-plugin-directivesPeer dependencies: eslint ^8.0.0 || ^9.0.0, @typescript-eslint/parser ^8.18.0
Usage
ESLint Flat Config
import directivesPlugin from '@libar-dev/eslint-plugin-directives';
export default [
{
plugins: { directives: directivesPlugin },
rules: {
'directives/no-explicit-any': 'error',
'directives/no-eslint-disable': 'error',
'directives/no-unused-type-imports': 'warn',
},
},
];Using the Recommended Config
import directivesPlugin from '@libar-dev/eslint-plugin-directives';
export default [
{
plugins: { directives: directivesPlugin },
rules: {
...directivesPlugin.configs.recommended.rules,
},
},
];The recommended config enables no-explicit-any and no-eslint-disable at "error" severity.
Rules
directives/no-eslint-disable
Prevents // eslint-disable comments. Requires architectural directives instead.
Built-in allowed directives: adapter-contract, library-generic-constraint, spec-driven-stub
// Error: eslint-disable without directive
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const x: any = value;
// OK: architectural directive present
// @architectural-directive: adapter-contract
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const x: any = externalApi.getValue();directives/no-explicit-any
Prevents explicit any types in TypeScript annotations, as any casts, z.any(), and v.any().
Built-in allowed directives: library-generic-constraint, test-any-type-handling, intersection-fallback, adapter-contract, spec-driven-stub
For v.any(): schema-compatibility
For z.any(): test-any-type-handling, schema-compatibility
// Error
const x: any = 5;
const y = value as any;
// OK: directive present
// @architectural-directive: library-generic-constraint
type Wrapper<T extends any> = { value: T };Automatically skips test files (.test.ts, .spec.ts) and generated files (.d.ts, _generated/).
directives/no-unused-type-imports
Detects unused import type declarations.
Built-in allowed directives: spec-driven-stub
// Error: Foo is never used
import type { Foo } from './types.js';
// OK: directive documents intentional stub
// @architectural-directive: spec-driven-stub
// Reason: Types defined per feature spec, used when implementation completes
import type { FutureEvent } from './types.js';Custom Directives
All rules accept an additionalDirectives option for project-specific directives:
rules: {
'directives/no-explicit-any': ['error', {
additionalDirectives: ['convex-compatibility', 'legacy-api-workaround'],
}],
'directives/no-eslint-disable': ['error', {
additionalDirectives: ['environment-access-safe'],
}],
}Then in your code:
// @architectural-directive: convex-compatibility
// Reason: Convex type system requires any for this field
const schema = v.any();Built-in Directive Types
| Directive | Category | Used By |
|-----------|----------|---------|
| library-generic-constraint | type-level | no-explicit-any, no-eslint-disable |
| intersection-fallback | type-level | no-explicit-any |
| test-any-type-handling | testing | no-explicit-any |
| adapter-contract | behavioral | no-explicit-any, no-eslint-disable |
| schema-compatibility | validation | no-explicit-any |
| spec-driven-stub | design | no-unused-type-imports, no-eslint-disable |
API Exports
The package also exports utilities for building custom ESLint rules with directive support:
import {
// Directive detection
hasArchitecturalDirective,
hasPrecedingDirective,
// File context analysis
analyzeFileContext,
// Registry
ARCHITECTURAL_DIRECTIVES,
getDirectiveMetadata,
getDirectivesByCategory,
isValidDirectiveType,
} from '@libar-dev/eslint-plugin-directives';
// Types
import type {
FileContext,
DirectiveType,
DirectiveCategory,
DirectiveMetadata,
} from '@libar-dev/eslint-plugin-directives';License
MIT
