@eduardbar/drift 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -18,6 +18,16 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
18
18
 
19
19
  ---
20
20
 
21
+ ## [0.7.0] - 2026-02-24
22
+
23
+ ### Added
24
+ - `eslint-plugin-drift` — separate npm package exposing all 26 drift rules as ESLint 9 flat config rules
25
+ - Each rule wraps drift's AST engine via `analyzeFile()` with a shared ts-morph `Project` instance
26
+ - Per-file result cache (max 100 entries) to prevent redundant analysis in watch mode
27
+ - `recommended` config array enabling all 26 rules at their canonical drift severity
28
+
29
+ ---
30
+
21
31
  ## [0.5.0] — 2026-02-24
22
32
 
23
33
  ### Added
package/assets/og.svg CHANGED
@@ -1,105 +1,105 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 630" width="1200" height="630">
2
- <defs>
3
- <linearGradient id="bg" x1="0%" y1="0%" x2="100%" y2="100%">
4
- <stop offset="0%" style="stop-color:#0a0a0f"/>
5
- <stop offset="100%" style="stop-color:#0f0f1a"/>
6
- </linearGradient>
7
- <linearGradient id="accent" x1="0%" y1="0%" x2="100%" y2="0%">
8
- <stop offset="0%" style="stop-color:#6366f1"/>
9
- <stop offset="100%" style="stop-color:#8b5cf6"/>
10
- </linearGradient>
11
- <linearGradient id="glow" x1="0%" y1="0%" x2="100%" y2="100%">
12
- <stop offset="0%" style="stop-color:#6366f1;stop-opacity:0.15"/>
13
- <stop offset="100%" style="stop-color:#8b5cf6;stop-opacity:0.05"/>
14
- </linearGradient>
15
- <filter id="blur-glow">
16
- <feGaussianBlur stdDeviation="40" result="blur"/>
17
- <feComposite in="SourceGraphic" in2="blur" operator="over"/>
18
- </filter>
19
- <filter id="soft-glow">
20
- <feGaussianBlur stdDeviation="3" result="blur"/>
21
- <feComposite in="SourceGraphic" in2="blur" operator="over"/>
22
- </filter>
23
- </defs>
24
-
25
- <!-- Background -->
26
- <rect width="1200" height="630" fill="url(#bg)"/>
27
-
28
- <!-- Ambient glow top-left -->
29
- <ellipse cx="200" cy="200" rx="300" ry="250" fill="url(#glow)" filter="url(#blur-glow)" opacity="0.8"/>
30
-
31
- <!-- Ambient glow bottom-right -->
32
- <ellipse cx="1050" cy="480" rx="280" ry="220" fill="url(#glow)" filter="url(#blur-glow)" opacity="0.6"/>
33
-
34
- <!-- Grid lines subtle -->
35
- <line x1="0" y1="210" x2="1200" y2="210" stroke="#ffffff" stroke-opacity="0.03" stroke-width="1"/>
36
- <line x1="0" y1="420" x2="1200" y2="420" stroke="#ffffff" stroke-opacity="0.03" stroke-width="1"/>
37
- <line x1="300" y1="0" x2="300" y2="630" stroke="#ffffff" stroke-opacity="0.03" stroke-width="1"/>
38
- <line x1="900" y1="0" x2="900" y2="630" stroke="#ffffff" stroke-opacity="0.03" stroke-width="1"/>
39
-
40
- <!-- Left accent bar -->
41
- <rect x="72" y="180" width="4" height="270" rx="2" fill="url(#accent)"/>
42
-
43
- <!-- Main title "drift" -->
44
- <text x="102" y="310" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', monospace" font-size="120" font-weight="700" fill="#ffffff" letter-spacing="-4">drift</text>
45
-
46
- <!-- Subtitle -->
47
- <text x="104" y="370" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif" font-size="24" font-weight="400" fill="#94a3b8" letter-spacing="0.5">Detect silent technical debt left by AI-generated code.</text>
48
-
49
- <!-- Terminal block right side -->
50
- <rect x="680" y="165" width="448" height="300" rx="12" fill="#0d0d18" stroke="#ffffff" stroke-opacity="0.08" stroke-width="1"/>
51
-
52
- <!-- Terminal header bar -->
53
- <rect x="680" y="165" width="448" height="40" rx="12" fill="#1a1a2e"/>
54
- <rect x="680" y="185" width="448" height="20" fill="#1a1a2e"/>
55
-
56
- <!-- Terminal dots -->
57
- <circle cx="710" cy="185" r="6" fill="#ff5f57"/>
58
- <circle cx="730" cy="185" r="6" fill="#febc2e"/>
59
- <circle cx="750" cy="185" r="6" fill="#28c840"/>
60
-
61
- <!-- Terminal text -->
62
- <text x="700" y="235" font-family="'Cascadia Code', 'Fira Code', 'Consolas', monospace" font-size="13" fill="#6366f1">$</text>
63
- <text x="716" y="235" font-family="'Cascadia Code', 'Fira Code', 'Consolas', monospace" font-size="13" fill="#e2e8f0"> npx @eduardbar/drift scan ./src</text>
64
-
65
- <text x="700" y="265" font-family="'Cascadia Code', 'Fira Code', 'Consolas', monospace" font-size="13" fill="#64748b"> drift — vibe coding debt detector</text>
66
-
67
- <text x="700" y="295" font-family="'Cascadia Code', 'Fira Code', 'Consolas', monospace" font-size="13" fill="#64748b"> Score </text>
68
- <text x="755" y="295" font-family="'Cascadia Code', 'Fira Code', 'Consolas', monospace" font-size="13" font-weight="700" fill="#ef4444"> 67</text>
69
- <text x="779" y="295" font-family="'Cascadia Code', 'Fira Code', 'Consolas', monospace" font-size="13" fill="#64748b">/100 HIGH</text>
70
-
71
- <text x="700" y="320" font-family="'Cascadia Code', 'Fira Code', 'Consolas', monospace" font-size="11" fill="#475569"> 4 file(s) · 5 errors · 12 warnings</text>
72
-
73
- <text x="700" y="352" font-family="'Cascadia Code', 'Fira Code', 'Consolas', monospace" font-size="11" fill="#64748b"> src/api/users.ts</text>
74
- <text x="700" y="371" font-family="'Cascadia Code', 'Fira Code', 'Consolas', monospace" font-size="11" fill="#ef4444"> ✖ </text>
75
- <text x="720" y="371" font-family="'Cascadia Code', 'Fira Code', 'Consolas', monospace" font-size="11" fill="#ef4444">large-file</text>
76
- <text x="800" y="371" font-family="'Cascadia Code', 'Fira Code', 'Consolas', monospace" font-size="11" fill="#94a3b8"> 412 lines detected</text>
77
-
78
- <text x="700" y="390" font-family="'Cascadia Code', 'Fira Code', 'Consolas', monospace" font-size="11" fill="#eab308"> ▲ </text>
79
- <text x="720" y="390" font-family="'Cascadia Code', 'Fira Code', 'Consolas', monospace" font-size="11" fill="#eab308">catch-swallow</text>
80
- <text x="820" y="390" font-family="'Cascadia Code', 'Fira Code', 'Consolas', monospace" font-size="11" fill="#94a3b8"> empty catch block</text>
81
-
82
- <text x="700" y="409" font-family="'Cascadia Code', 'Fira Code', 'Consolas', monospace" font-size="11" fill="#eab308"> ▲ </text>
83
- <text x="720" y="409" font-family="'Cascadia Code', 'Fira Code', 'Consolas', monospace" font-size="11" fill="#eab308">any-abuse</text>
84
- <text x="793" y="409" font-family="'Cascadia Code', 'Fira Code', 'Consolas', monospace" font-size="11" fill="#94a3b8"> explicit any type</text>
85
-
86
- <text x="700" y="440" font-family="'Cascadia Code', 'Fira Code', 'Consolas', monospace" font-size="11" fill="#22c55e"> ◦ </text>
87
- <text x="720" y="440" font-family="'Cascadia Code', 'Fira Code', 'Consolas', monospace" font-size="11" fill="#64748b">no-return-type</text>
88
- <text x="830" y="440" font-family="'Cascadia Code', 'Fira Code', 'Consolas', monospace" font-size="11" fill="#475569"> missing return type</text>
89
-
90
- <!-- Badges row -->
91
- <rect x="104" y="405" width="100" height="26" rx="5" fill="#1e1e3a" stroke="#6366f1" stroke-opacity="0.4" stroke-width="1"/>
92
- <text x="154" y="423" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif" font-size="12" fill="#818cf8" text-anchor="middle">TypeScript</text>
93
-
94
- <rect x="214" y="405" width="72" height="26" rx="5" fill="#1e1e3a" stroke="#6366f1" stroke-opacity="0.4" stroke-width="1"/>
95
- <text x="250" y="423" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif" font-size="12" fill="#818cf8" text-anchor="middle">ts-morph</text>
96
-
97
- <rect x="296" y="405" width="52" height="26" rx="5" fill="#1e1e3a" stroke="#6366f1" stroke-opacity="0.4" stroke-width="1"/>
98
- <text x="322" y="423" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif" font-size="12" fill="#818cf8" text-anchor="middle">MIT</text>
99
-
100
- <!-- Author -->
101
- <text x="104" y="520" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif" font-size="16" fill="#334155">github.com/eduardbar/drift</text>
102
-
103
- <!-- Bottom accent line -->
104
- <rect x="0" y="622" width="1200" height="8" fill="url(#accent)" opacity="0.7"/>
105
- </svg>
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 630" width="1200" height="630">
2
+ <defs>
3
+ <linearGradient id="bg" x1="0%" y1="0%" x2="100%" y2="100%">
4
+ <stop offset="0%" style="stop-color:#0a0a0f"/>
5
+ <stop offset="100%" style="stop-color:#0f0f1a"/>
6
+ </linearGradient>
7
+ <linearGradient id="accent" x1="0%" y1="0%" x2="100%" y2="0%">
8
+ <stop offset="0%" style="stop-color:#6366f1"/>
9
+ <stop offset="100%" style="stop-color:#8b5cf6"/>
10
+ </linearGradient>
11
+ <linearGradient id="glow" x1="0%" y1="0%" x2="100%" y2="100%">
12
+ <stop offset="0%" style="stop-color:#6366f1;stop-opacity:0.15"/>
13
+ <stop offset="100%" style="stop-color:#8b5cf6;stop-opacity:0.05"/>
14
+ </linearGradient>
15
+ <filter id="blur-glow">
16
+ <feGaussianBlur stdDeviation="40" result="blur"/>
17
+ <feComposite in="SourceGraphic" in2="blur" operator="over"/>
18
+ </filter>
19
+ <filter id="soft-glow">
20
+ <feGaussianBlur stdDeviation="3" result="blur"/>
21
+ <feComposite in="SourceGraphic" in2="blur" operator="over"/>
22
+ </filter>
23
+ </defs>
24
+
25
+ <!-- Background -->
26
+ <rect width="1200" height="630" fill="url(#bg)"/>
27
+
28
+ <!-- Ambient glow top-left -->
29
+ <ellipse cx="200" cy="200" rx="300" ry="250" fill="url(#glow)" filter="url(#blur-glow)" opacity="0.8"/>
30
+
31
+ <!-- Ambient glow bottom-right -->
32
+ <ellipse cx="1050" cy="480" rx="280" ry="220" fill="url(#glow)" filter="url(#blur-glow)" opacity="0.6"/>
33
+
34
+ <!-- Grid lines subtle -->
35
+ <line x1="0" y1="210" x2="1200" y2="210" stroke="#ffffff" stroke-opacity="0.03" stroke-width="1"/>
36
+ <line x1="0" y1="420" x2="1200" y2="420" stroke="#ffffff" stroke-opacity="0.03" stroke-width="1"/>
37
+ <line x1="300" y1="0" x2="300" y2="630" stroke="#ffffff" stroke-opacity="0.03" stroke-width="1"/>
38
+ <line x1="900" y1="0" x2="900" y2="630" stroke="#ffffff" stroke-opacity="0.03" stroke-width="1"/>
39
+
40
+ <!-- Left accent bar -->
41
+ <rect x="72" y="180" width="4" height="270" rx="2" fill="url(#accent)"/>
42
+
43
+ <!-- Main title "drift" -->
44
+ <text x="102" y="310" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', monospace" font-size="120" font-weight="700" fill="#ffffff" letter-spacing="-4">drift</text>
45
+
46
+ <!-- Subtitle -->
47
+ <text x="104" y="370" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif" font-size="24" font-weight="400" fill="#94a3b8" letter-spacing="0.5">Detect silent technical debt left by AI-generated code.</text>
48
+
49
+ <!-- Terminal block right side -->
50
+ <rect x="680" y="165" width="448" height="300" rx="12" fill="#0d0d18" stroke="#ffffff" stroke-opacity="0.08" stroke-width="1"/>
51
+
52
+ <!-- Terminal header bar -->
53
+ <rect x="680" y="165" width="448" height="40" rx="12" fill="#1a1a2e"/>
54
+ <rect x="680" y="185" width="448" height="20" fill="#1a1a2e"/>
55
+
56
+ <!-- Terminal dots -->
57
+ <circle cx="710" cy="185" r="6" fill="#ff5f57"/>
58
+ <circle cx="730" cy="185" r="6" fill="#febc2e"/>
59
+ <circle cx="750" cy="185" r="6" fill="#28c840"/>
60
+
61
+ <!-- Terminal text -->
62
+ <text x="700" y="235" font-family="'Cascadia Code', 'Fira Code', 'Consolas', monospace" font-size="13" fill="#6366f1">$</text>
63
+ <text x="716" y="235" font-family="'Cascadia Code', 'Fira Code', 'Consolas', monospace" font-size="13" fill="#e2e8f0"> npx @eduardbar/drift scan ./src</text>
64
+
65
+ <text x="700" y="265" font-family="'Cascadia Code', 'Fira Code', 'Consolas', monospace" font-size="13" fill="#64748b"> drift — vibe coding debt detector</text>
66
+
67
+ <text x="700" y="295" font-family="'Cascadia Code', 'Fira Code', 'Consolas', monospace" font-size="13" fill="#64748b"> Score </text>
68
+ <text x="755" y="295" font-family="'Cascadia Code', 'Fira Code', 'Consolas', monospace" font-size="13" font-weight="700" fill="#ef4444"> 67</text>
69
+ <text x="779" y="295" font-family="'Cascadia Code', 'Fira Code', 'Consolas', monospace" font-size="13" fill="#64748b">/100 HIGH</text>
70
+
71
+ <text x="700" y="320" font-family="'Cascadia Code', 'Fira Code', 'Consolas', monospace" font-size="11" fill="#475569"> 4 file(s) · 5 errors · 12 warnings</text>
72
+
73
+ <text x="700" y="352" font-family="'Cascadia Code', 'Fira Code', 'Consolas', monospace" font-size="11" fill="#64748b"> src/api/users.ts</text>
74
+ <text x="700" y="371" font-family="'Cascadia Code', 'Fira Code', 'Consolas', monospace" font-size="11" fill="#ef4444"> ✖ </text>
75
+ <text x="720" y="371" font-family="'Cascadia Code', 'Fira Code', 'Consolas', monospace" font-size="11" fill="#ef4444">large-file</text>
76
+ <text x="800" y="371" font-family="'Cascadia Code', 'Fira Code', 'Consolas', monospace" font-size="11" fill="#94a3b8"> 412 lines detected</text>
77
+
78
+ <text x="700" y="390" font-family="'Cascadia Code', 'Fira Code', 'Consolas', monospace" font-size="11" fill="#eab308"> ▲ </text>
79
+ <text x="720" y="390" font-family="'Cascadia Code', 'Fira Code', 'Consolas', monospace" font-size="11" fill="#eab308">catch-swallow</text>
80
+ <text x="820" y="390" font-family="'Cascadia Code', 'Fira Code', 'Consolas', monospace" font-size="11" fill="#94a3b8"> empty catch block</text>
81
+
82
+ <text x="700" y="409" font-family="'Cascadia Code', 'Fira Code', 'Consolas', monospace" font-size="11" fill="#eab308"> ▲ </text>
83
+ <text x="720" y="409" font-family="'Cascadia Code', 'Fira Code', 'Consolas', monospace" font-size="11" fill="#eab308">any-abuse</text>
84
+ <text x="793" y="409" font-family="'Cascadia Code', 'Fira Code', 'Consolas', monospace" font-size="11" fill="#94a3b8"> explicit any type</text>
85
+
86
+ <text x="700" y="440" font-family="'Cascadia Code', 'Fira Code', 'Consolas', monospace" font-size="11" fill="#22c55e"> ◦ </text>
87
+ <text x="720" y="440" font-family="'Cascadia Code', 'Fira Code', 'Consolas', monospace" font-size="11" fill="#64748b">no-return-type</text>
88
+ <text x="830" y="440" font-family="'Cascadia Code', 'Fira Code', 'Consolas', monospace" font-size="11" fill="#475569"> missing return type</text>
89
+
90
+ <!-- Badges row -->
91
+ <rect x="104" y="405" width="100" height="26" rx="5" fill="#1e1e3a" stroke="#6366f1" stroke-opacity="0.4" stroke-width="1"/>
92
+ <text x="154" y="423" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif" font-size="12" fill="#818cf8" text-anchor="middle">TypeScript</text>
93
+
94
+ <rect x="214" y="405" width="72" height="26" rx="5" fill="#1e1e3a" stroke="#6366f1" stroke-opacity="0.4" stroke-width="1"/>
95
+ <text x="250" y="423" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif" font-size="12" fill="#818cf8" text-anchor="middle">ts-morph</text>
96
+
97
+ <rect x="296" y="405" width="52" height="26" rx="5" fill="#1e1e3a" stroke="#6366f1" stroke-opacity="0.4" stroke-width="1"/>
98
+ <text x="322" y="423" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif" font-size="12" fill="#818cf8" text-anchor="middle">MIT</text>
99
+
100
+ <!-- Author -->
101
+ <text x="104" y="520" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif" font-size="16" fill="#334155">github.com/eduardbar/drift</text>
102
+
103
+ <!-- Bottom accent line -->
104
+ <rect x="0" y="622" width="1200" height="8" fill="url(#accent)" opacity="0.7"/>
105
+ </svg>
@@ -1,5 +1,9 @@
1
1
  import { SourceFile } from 'ts-morph';
2
- import type { FileReport, DriftConfig } from './types.js';
2
+ import type { DriftIssue, FileReport, DriftConfig } from './types.js';
3
+ export declare const RULE_WEIGHTS: Record<string, {
4
+ severity: DriftIssue['severity'];
5
+ weight: number;
6
+ }>;
3
7
  export declare function analyzeFile(file: SourceFile): FileReport;
4
8
  export declare function analyzeProject(targetPath: string, config?: DriftConfig): FileReport[];
5
9
  //# sourceMappingURL=analyzer.d.ts.map
package/dist/analyzer.js CHANGED
@@ -2,7 +2,7 @@ import * as fs from 'node:fs';
2
2
  import * as path from 'node:path';
3
3
  import { Project, SyntaxKind, } from 'ts-morph';
4
4
  // Rules and their drift score weight
5
- const RULE_WEIGHTS = {
5
+ export const RULE_WEIGHTS = {
6
6
  'large-file': { severity: 'error', weight: 20 },
7
7
  'large-function': { severity: 'error', weight: 15 },
8
8
  'debug-leftover': { severity: 'warning', weight: 10 },
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- export { analyzeProject, analyzeFile } from './analyzer.js';
1
+ export { analyzeProject, analyzeFile, RULE_WEIGHTS } from './analyzer.js';
2
2
  export { buildReport, formatMarkdown } from './reporter.js';
3
3
  export { computeDiff } from './diff.js';
4
- export type { DriftReport, FileReport, DriftIssue, DriftDiff, FileDiff } from './types.js';
4
+ export type { DriftReport, FileReport, DriftIssue, DriftDiff, FileDiff, DriftConfig } from './types.js';
5
5
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- export { analyzeProject, analyzeFile } from './analyzer.js';
1
+ export { analyzeProject, analyzeFile, RULE_WEIGHTS } from './analyzer.js';
2
2
  export { buildReport, formatMarkdown } from './reporter.js';
3
3
  export { computeDiff } from './diff.js';
4
4
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eduardbar/drift",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "Detect silent technical debt left by AI-generated code",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -0,0 +1,88 @@
1
+ # eslint-plugin-drift
2
+
3
+ ESLint plugin that exposes [drift](https://github.com/eduardbar/drift)'s 26 technical debt rules as standard ESLint rules, compatible with ESLint 9 flat config.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install --save-dev eslint-plugin-drift eslint
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### Recommended config (all 26 rules)
14
+
15
+ In your `eslint.config.js` (or `eslint.config.mjs`):
16
+
17
+ ```js
18
+ import drift from 'eslint-plugin-drift'
19
+
20
+ export default [
21
+ ...drift.configs.recommended,
22
+ ]
23
+ ```
24
+
25
+ ### Manual config (pick individual rules)
26
+
27
+ ```js
28
+ import drift from 'eslint-plugin-drift'
29
+
30
+ export default [
31
+ {
32
+ plugins: { drift },
33
+ rules: {
34
+ 'drift/large-file': 'error',
35
+ 'drift/large-function': 'error',
36
+ 'drift/any-abuse': 'warn',
37
+ 'drift/magic-number': 'warn',
38
+ },
39
+ },
40
+ ]
41
+ ```
42
+
43
+ ## Rules
44
+
45
+ | Rule | Severity | Description |
46
+ |------|----------|-------------|
47
+ | `drift/large-file` | error | Files over 300 lines |
48
+ | `drift/large-function` | error | Functions over 50 lines |
49
+ | `drift/duplicate-function-name` | error | Near-identical function names |
50
+ | `drift/high-complexity` | error | Cyclomatic complexity > 10 |
51
+ | `drift/circular-dependency` | error | Circular import chains |
52
+ | `drift/layer-violation` | error | Prohibited architectural layer imports |
53
+ | `drift/debug-leftover` | warn | console.log, TODO, FIXME in production |
54
+ | `drift/dead-code` | warn | Unused imports |
55
+ | `drift/any-abuse` | warn | Explicit `any` type |
56
+ | `drift/catch-swallow` | warn | Empty catch blocks |
57
+ | `drift/comment-contradiction` | warn | Comments that restate the code |
58
+ | `drift/deep-nesting` | warn | Nesting depth > 3 |
59
+ | `drift/too-many-params` | warn | Functions with more than 4 parameters |
60
+ | `drift/high-coupling` | warn | Files importing from more than 10 modules |
61
+ | `drift/promise-style-mix` | warn | Mixed async/await and .then() |
62
+ | `drift/unused-export` | warn | Exports never imported anywhere |
63
+ | `drift/dead-file` | warn | Files never imported |
64
+ | `drift/unused-dependency` | warn | Packages in package.json never used |
65
+ | `drift/cross-boundary-import` | warn | Cross-module boundary imports |
66
+ | `drift/hardcoded-config` | warn | Hardcoded URLs, IPs, connection strings |
67
+ | `drift/inconsistent-error-handling` | warn | Mixed try/catch and .catch() |
68
+ | `drift/unnecessary-abstraction` | warn | Single-use interfaces and abstract classes |
69
+ | `drift/naming-inconsistency` | warn | Mixed camelCase and snake_case |
70
+ | `drift/no-return-type` | warn | Missing explicit return types |
71
+ | `drift/magic-number` | warn | Numeric literals in logic |
72
+ | `drift/over-commented` | warn | Comments exceed 40% of function lines |
73
+
74
+ ## How it works
75
+
76
+ The plugin runs drift's AST analysis engine on each `.ts`/`.tsx` file when ESLint processes it. Results are cached per file so each file is analyzed once regardless of how many rules are enabled.
77
+
78
+ > **Note:** This plugin analyzes files individually. Cross-file rules (`unused-export`, `dead-file`, `unused-dependency`) work best when running `drift scan` on the full project for comprehensive cross-file analysis.
79
+
80
+ ## Requirements
81
+
82
+ - ESLint 9+
83
+ - Node.js 18+
84
+ - TypeScript or JavaScript project
85
+
86
+ ## License
87
+
88
+ MIT — [Eduard Barrera](https://github.com/eduardbar)