@archlinter/cli 0.1.0 → 0.1.3

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.
Files changed (2) hide show
  1. package/README.md +551 -0
  2. package/package.json +9 -8
package/README.md ADDED
@@ -0,0 +1,551 @@
1
+ <p align="center">
2
+ <img src="docs/assets/logo.svg" height="128" alt="archlint logo" />
3
+ </p>
4
+
5
+ <h1 align="center">archlint</h1>
6
+
7
+ <p align="center">
8
+ <strong>Fast, AST-based architecture smell detector for TypeScript/JavaScript projects</strong>
9
+ </p>
10
+
11
+ <p align="center">
12
+ <a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT"></a>
13
+ <a href="https://www.rust-lang.org/"><img src="https://img.shields.io/badge/rust-%23000000.svg?style=flat&logo=rust&logoColor=white" alt="Rust"></a>
14
+ </p>
15
+
16
+ A powerful CLI tool for detecting 30+ types of architectural smells in TypeScript/JavaScript codebases. Built with Rust and `oxc` parser for maximum performance.
17
+
18
+ ## Why archlint?
19
+
20
+ Modern codebases grow complex fast. archlint helps you:
21
+
22
+ - 🔍 **Detect architectural problems early** before they become technical debt
23
+ - 🎯 **Framework-aware analysis** with presets for NestJS, Next.js, React, oclif
24
+ - ⚡ **Blazingly fast** - analyzes 200+ files in under 5 seconds
25
+ - 📊 **Actionable insights** - clear explanations, severity scores, and refactoring recommendations
26
+ - 🔄 **Watch mode** for real-time feedback during development
27
+ - 🧠 **Smart caching** for instant re-runs
28
+
29
+ ## Features
30
+
31
+ ### 30+ Architectural Smell Detectors
32
+
33
+ **Dependency & Structure Issues:**
34
+
35
+ - Cyclic dependencies (file-level and type-level)
36
+ - Hub modules (too many connections)
37
+ - God modules (doing too much)
38
+ - Dead code (unused exports)
39
+ - Orphan types (disconnected from codebase)
40
+
41
+ **Design Quality Issues:**
42
+
43
+ - Low cohesion (LCOM metric)
44
+ - High coupling
45
+ - Layer violations (domain/application/infrastructure)
46
+ - SDP violations (Stable Dependencies Principle)
47
+ - Feature envy, shotgun surgery
48
+
49
+ **Code Organization Issues:**
50
+
51
+ - Barrel file abuse
52
+ - Scattered modules/configs
53
+ - Primitive obsession
54
+ - Long parameter lists
55
+ - Deep nesting
56
+
57
+ **Framework-Specific Issues:**
58
+
59
+ - Test leakage (test code in production)
60
+ - Side-effect imports
61
+ - Vendor coupling
62
+ - Unstable interfaces
63
+ - Shared mutable state
64
+
65
+ ### Framework Intelligence
66
+
67
+ Built-in presets that understand framework patterns:
68
+
69
+ - **NestJS**: Knows controllers are entry points, modules can have high coupling
70
+ - **Next.js**: Understands pages/API routes, relaxes barrel file rules
71
+ - **React**: Aware of component patterns, skips irrelevant checks
72
+ - **oclif**: Recognizes CLI commands and hooks
73
+
74
+ ### Output Formats
75
+
76
+ - **Table** (default) - clean terminal output with colors
77
+ - **Markdown** - detailed reports with Mermaid dependency graphs
78
+ - **JSON** - machine-readable for CI/CD integration
79
+
80
+ ### Developer Experience
81
+
82
+ - **Watch mode** with debouncing for live feedback
83
+ - **Smart caching** using content hashes
84
+ - **Severity filtering** (low/medium/high/critical)
85
+ - **Selective detector runs** (include/exclude specific checks)
86
+ - **Git integration** for churn analysis
87
+ - **CI-friendly** quiet mode
88
+
89
+ ## Installation
90
+
91
+ ### From source
92
+
93
+ ```bash
94
+ git clone https://github.com/yourusername/archlint.git
95
+ cd archlint
96
+ cargo build --release
97
+ cargo install --path .
98
+ ```
99
+
100
+ ### Using Cargo
101
+
102
+ ```bash
103
+ cargo install archlint
104
+ ```
105
+
106
+ ## Quick Start
107
+
108
+ ### Basic scan
109
+
110
+ ```bash
111
+ archlint scan ./my-project
112
+ ```
113
+
114
+ ### With configuration
115
+
116
+ ```bash
117
+ archlint scan ./my-project --config archlint.yaml
118
+ ```
119
+
120
+ ### Watch mode for development
121
+
122
+ ```bash
123
+ archlint watch --debounce 500 --clear
124
+ ```
125
+
126
+ ### Export report
127
+
128
+ ```bash
129
+ # Markdown with diagrams
130
+ archlint scan ./my-project --format markdown --report architecture-report.md
131
+
132
+ # JSON for CI/CD
133
+ archlint scan ./my-project --format json --report report.json
134
+ # Or use the shorter --json flag
135
+ archlint scan ./my-project --json --report report.json
136
+ ```
137
+
138
+ ### Filter by severity
139
+
140
+ ```bash
141
+ archlint scan --min-severity high
142
+ ```
143
+
144
+ ### Run specific detectors
145
+
146
+ ```bash
147
+ archlint scan --detectors cycles,god_module,dead_code
148
+ ```
149
+
150
+ ### Exclude detectors
151
+
152
+ ```bash
153
+ archlint scan --exclude-detectors barrel_file_abuse,lcom
154
+ ```
155
+
156
+ ## Configuration
157
+
158
+ Create `archlint.yaml` in your project root:
159
+
160
+ ```yaml
161
+ # Files/directories to ignore
162
+ ignore:
163
+ - '**/*.test.ts'
164
+ - '**/*.spec.ts'
165
+ - '**/__tests__/**'
166
+ - '**/__mocks__/**'
167
+ - '**/node_modules/**'
168
+ - '**/dist/**'
169
+
170
+ # Path aliases (from tsconfig.json)
171
+ aliases:
172
+ '@/*': 'src/*'
173
+ '@components/*': 'src/components/*'
174
+ '@utils/*': 'src/utils/*'
175
+
176
+ # Entry points (won't be marked as dead code)
177
+ entry_points:
178
+ - 'src/main.ts'
179
+ - 'src/index.ts'
180
+ - '**/*.e2e.ts'
181
+ - '**/pages/**' # Next.js pages
182
+
183
+ # Detector thresholds
184
+ thresholds:
185
+ god_module:
186
+ fan_in: 10 # Max incoming dependencies
187
+ fan_out: 10 # Max outgoing dependencies
188
+ churn: 20 # Max git commits
189
+
190
+ hub_module:
191
+ fan_in: 15
192
+ fan_out: 15
193
+
194
+ high_coupling:
195
+ max_dependencies: 15
196
+
197
+ lcom:
198
+ threshold: 0.8 # 0-1 scale (higher = worse cohesion)
199
+
200
+ deep_nesting:
201
+ max_depth: 4
202
+
203
+ long_params:
204
+ max_params: 5
205
+
206
+ complexity:
207
+ max_complexity: 15
208
+
209
+ # Framework detection (auto-detected, can override)
210
+ frameworks:
211
+ - nestjs
212
+ - react
213
+
214
+ # Layer architecture (for layer_violation detector)
215
+ layers:
216
+ - name: domain
217
+ paths: ['**/domain/**']
218
+ can_import: []
219
+
220
+ - name: application
221
+ paths: ['**/application/**', '**/use-cases/**']
222
+ can_import: ['domain']
223
+
224
+ - name: infrastructure
225
+ paths: ['**/infrastructure/**', '**/adapters/**']
226
+ can_import: ['domain', 'application']
227
+
228
+ - name: presentation
229
+ paths: ['**/controllers/**', '**/api/**']
230
+ can_import: ['application', 'domain']
231
+
232
+ # Severity overrides
233
+ severity:
234
+ cycles: critical
235
+ god_module: high
236
+ dead_code: low
237
+ barrel_file_abuse: medium
238
+ ```
239
+
240
+ ## Available Detectors
241
+
242
+ Run `archlint detectors list` to see all detectors with descriptions.
243
+
244
+ | Detector | Description | Default Enabled |
245
+ | ------------------------ | ---------------------------------------------- | --------------- |
246
+ | `cycles` | Circular dependencies between files | ✅ |
247
+ | `circular_type_deps` | Type-level circular dependencies | ✅ |
248
+ | `god_module` | Modules with too many responsibilities | ✅ |
249
+ | `hub_module` | Hub-like modules with high connectivity | ✅ |
250
+ | `dead_code` | Unused exports | ✅ |
251
+ | `dead_symbols` | Unused local functions and variables | ✅ |
252
+ | `orphan_types` | Types not connected to codebase | ✅ |
253
+ | `lcom` | Low cohesion in classes (LCOM4 metric) | ✅ |
254
+ | `high_coupling` | Files with too many dependencies | ✅ |
255
+ | `layer_violation` | Architectural layer violations | ⚠️ Framework |
256
+ | `sdp_violation` | Stable Dependencies Principle violations | ⚠️ Framework |
257
+ | `barrel_file_abuse` | Barrel files causing unnecessary coupling | ✅ |
258
+ | `scattered_module` | Related functionality scattered across files | ✅ |
259
+ | `scattered_config` | Configuration spread across codebase | ✅ |
260
+ | `feature_envy` | Methods using more of another class | ✅ |
261
+ | `shotgun_surgery` | Changes requiring modifications in many places | ✅ |
262
+ | `primitive_obsession` | Overuse of primitives vs domain objects | ✅ |
263
+ | `long_params` | Functions with too many parameters | ✅ |
264
+ | `deep_nesting` | Deeply nested code blocks | ✅ |
265
+ | `complexity` | High cyclomatic complexity | ✅ |
266
+ | `side_effect_import` | Imports with side effects | ✅ |
267
+ | `test_leakage` | Test code leaking into production | ✅ |
268
+ | `vendor_coupling` | Tight coupling to external libraries | ✅ |
269
+ | `unstable_interface` | Frequently changing public interfaces | ✅ |
270
+ | `shared_mutable_state` | Shared mutable state between modules | ✅ |
271
+ | `abstractness_violation` | Pain/Useless zones (I+A metric) | ✅ |
272
+ | `package_cycle` | Cyclic dependencies between packages | ✅ |
273
+
274
+ ## Example Output
275
+
276
+ ### Table Format (Default)
277
+
278
+ ```
279
+ ╭─────────────────────────────────────────────────────────────────────────╮
280
+ │ Architecture Smell Report │
281
+ ├─────────────────────────────────────────────────────────────────────────┤
282
+ │ Files analyzed: 247 │
283
+ │ Smells detected: 12 │
284
+ │ Total issues: 18 │
285
+ ╰─────────────────────────────────────────────────────────────────────────╯
286
+
287
+ ╭───────────────┬──────────────────────────────┬──────────┬─────────────╮
288
+ │ Severity │ Smell │ File │ Score │
289
+ ├───────────────┼──────────────────────────────┼──────────┼─────────────┤
290
+ │ 🔴 CRITICAL │ Cyclic Dependency │ a.ts │ 95 │
291
+ │ │ │ b.ts │ │
292
+ │ │ │ c.ts │ │
293
+ ├───────────────┼──────────────────────────────┼──────────┼─────────────┤
294
+ │ 🟠 HIGH │ God Module │ utils.ts │ 87 │
295
+ │ │ Fan-in: 23, Fan-out: 15 │ │ │
296
+ ├───────────────┼──────────────────────────────┼──────────┼─────────────┤
297
+ │ 🟡 MEDIUM │ Low Cohesion (LCOM) │ user.ts │ 65 │
298
+ │ │ LCOM4: 0.85 │ │ │
299
+ ╰───────────────┴──────────────────────────────┴──────────┴─────────────╯
300
+ ```
301
+
302
+ ### Markdown Format
303
+
304
+ ### Markdown Format
305
+
306
+ See full example with Mermaid diagrams in generated reports.
307
+
308
+ ## CLI Reference
309
+
310
+ ```bash
311
+ # Scan commands
312
+ archlint scan [PATH] # Scan project
313
+ --config <FILE> # Config file path
314
+ --format <table|markdown|json> # Output format
315
+ --json # Shortcut for --format json (automatically enables --quiet)
316
+ --report <FILE> # Save to file (default: stdout)
317
+ --no-diagram # Disable Mermaid diagrams
318
+ --all # Run all detectors (including disabled)
319
+ --detectors <IDS> # Only run specific detectors
320
+ --exclude-detectors <IDS> # Exclude specific detectors
321
+ --min-severity <low|medium|high|critical> # Filter by severity
322
+ --min-score <SCORE> # Filter by score (0-100)
323
+ --quiet # CI-friendly mode (no progress bars)
324
+ --verbose # Detailed output
325
+ --no-cache # Disable caching
326
+
327
+ # Watch mode
328
+ archlint watch # Watch for changes
329
+ --debounce <MS> # Debounce time (default: 300ms)
330
+ --clear # Clear screen on re-run
331
+ --ignore <PATTERN> # Additional ignore patterns
332
+ [all scan options] # Accepts all scan options
333
+
334
+ # Detector management
335
+ archlint detectors list # List all available detectors
336
+
337
+ # Cache management
338
+ archlint cache clear # Clear analysis cache
339
+ ```
340
+
341
+ ## Performance
342
+
343
+ - **Fast**: ~200 files analyzed in under 5 seconds
344
+ - **Parallel**: Uses Rayon for multi-threaded analysis
345
+ - **Cached**: Content-based caching (SHA256) for instant re-runs
346
+ - **Efficient**: AST parsing with `oxc` (faster than Babel/SWC)
347
+ - **Low memory**: Streaming analysis, no full AST kept in memory
348
+
349
+ ## Framework Support
350
+
351
+ ### NestJS
352
+
353
+ - Controllers/Modules recognized as entry points
354
+ - Relaxed coupling rules for modules/repositories
355
+ - SDP and layer violation checks enabled
356
+ - Ignores NestJS-specific decorators in LCOM
357
+
358
+ ### Next.js
359
+
360
+ - Pages and API routes as entry points
361
+ - Barrel file rules relaxed (common pattern)
362
+ - Layer violation checks disabled
363
+
364
+ ### React
365
+
366
+ - Components recognized by naming patterns
367
+ - LCOM checks disabled (not applicable)
368
+ - Scattered module checks relaxed
369
+
370
+ ### oclif
371
+
372
+ - CLI commands/hooks as entry points
373
+ - Appropriate checks for CLI patterns
374
+
375
+ ## Use Cases
376
+
377
+ ### 🚀 CI/CD Integration
378
+
379
+ ```yaml
380
+ # .github/workflows/architecture.yml
381
+ - name: Architecture Check
382
+ run: |
383
+ archlint scan --format json --report arch-report.json --min-severity high
384
+ if [ $(jq '.summary.total_issues' arch-report.json) -gt 0 ]; then
385
+ exit 1
386
+ fi
387
+ ```
388
+
389
+ ### 🔄 Pre-commit Hook
390
+
391
+ ```bash
392
+ # .git/hooks/pre-commit
393
+ #!/bin/bash
394
+ archlint scan --quiet --min-severity critical
395
+ ```
396
+
397
+ ### 📊 Regular Architecture Audits
398
+
399
+ ```bash
400
+ # Generate weekly reports
401
+ archlint scan --format markdown --report "reports/$(date +%Y-%m-%d).md"
402
+ ```
403
+
404
+ ### 🧹 Refactoring Guidance
405
+
406
+ ```bash
407
+ # Find high-priority issues
408
+ archlint scan --min-score 80 --format table
409
+
410
+ # Focus on specific problems
411
+ archlint scan --detectors cycles,god_module,high_coupling
412
+ ```
413
+
414
+ ## Comparison with Other Tools
415
+
416
+ | Feature | archlint | madge | dependency-cruiser | ts-unused-exports | ArchUnit (Java) |
417
+ | ---------------- | -------- | --------- | ------------------ | ----------------- | --------------- |
418
+ | Language | TS/JS | TS/JS | TS/JS | TS/JS | Java |
419
+ | Circular deps | ✅ | ✅ | ✅ | ❌ | ✅ |
420
+ | Dead code | ✅ | ❌ | ❌ | ✅ | ❌ |
421
+ | God modules | ✅ | ❌ | ❌ | ❌ | ⚠️ Custom rules |
422
+ | LCOM/Cohesion | ✅ | ❌ | ❌ | ❌ | ⚠️ Custom rules |
423
+ | Layer violations | ✅ | ❌ | ✅ | ❌ | ✅ |
424
+ | Framework-aware | ✅ | ❌ | ⚠️ Limited | ❌ | ✅ |
425
+ | Watch mode | ✅ | ✅ | ✅ | ❌ | ❌ |
426
+ | AST-based | ✅ (oxc) | ⚠️ (slow) | ✅ | ✅ | ✅ |
427
+ | Performance | ⚡ <5s | 🐌 ~30s | 🚀 ~10s | ⚡ ~5s | N/A |
428
+ | 30+ detectors | ✅ | ❌ | ❌ | ❌ | ⚠️ Custom |
429
+
430
+ **Key differentiators:**
431
+
432
+ - **Comprehensive**: 30+ architectural smell detectors vs competitors' narrow focus
433
+ - **Fast**: Rust + oxc parser = 5-10x faster than JS-based tools
434
+ - **Smart**: Framework-aware analysis (NestJS, Next.js, React, oclif)
435
+ - **Actionable**: Severity scores, explanations, and refactoring recommendations
436
+ - **Modern**: Type-level cycle detection, abstractness metrics, SDP violations
437
+
438
+ ## Architecture
439
+
440
+ ```
441
+ archlint
442
+ ├── scanner # File discovery with .gitignore support
443
+ ├── parser # AST parsing (oxc) + dependency extraction
444
+ ├── resolver # Path resolution (aliases, node_modules)
445
+ ├── graph # Dependency graph (petgraph)
446
+ ├── detectors # 30+ smell detectors
447
+ ├── framework # Framework detection & presets
448
+ ├── engine # Analysis orchestration
449
+ ├── metrics # Code metrics (LCOM, complexity, etc.)
450
+ ├── cache # Content-based caching
451
+ └── report # Output formatters (table, markdown, json)
452
+ ```
453
+
454
+ ## Contributing
455
+
456
+ Contributions welcome! Areas for improvement:
457
+
458
+ - [ ] More detectors (data clumps, speculative generality, etc.)
459
+ - [ ] Support for other languages (Python, Go, Java)
460
+ - [ ] HTML interactive reports
461
+ - [ ] VS Code extension
462
+ - [ ] Auto-fix suggestions
463
+ - [ ] More framework presets (Angular, Vue, Svelte)
464
+
465
+ ### Adding a Detector
466
+
467
+ ```rust
468
+ use crate::framework::detector::{Detector, DetectorMetadata, Smell};
469
+ use inventory::submit;
470
+
471
+ pub struct MyDetector;
472
+
473
+ impl Detector for MyDetector {
474
+ fn metadata(&self) -> DetectorMetadata {
475
+ DetectorMetadata {
476
+ id: "my_detector",
477
+ name: "My Detector",
478
+ description: "Detects something bad",
479
+ severity: crate::framework::detector::Severity::Medium,
480
+ enabled_by_default: true,
481
+ }
482
+ }
483
+
484
+ fn detect(&self, context: &crate::engine::context::Context) -> Vec<Smell> {
485
+ // Your detection logic here
486
+ vec![]
487
+ }
488
+ }
489
+
490
+ submit! { &MyDetector as &dyn Detector }
491
+ ```
492
+
493
+ ## Roadmap
494
+
495
+ - [x] Core detectors (cycles, god modules, dead code)
496
+ - [x] Framework detection (NestJS, Next.js, React)
497
+ - [x] Watch mode
498
+ - [x] Caching
499
+ - [x] 30+ detectors
500
+ - [ ] Auto-fix suggestions
501
+ - [ ] VS Code extension
502
+ - [ ] HTML reports with interactive graphs
503
+ - [ ] Python/Go support
504
+ - [ ] Trend analysis (track metrics over time)
505
+ - [ ] Integration with SonarQube/CodeClimate
506
+
507
+ ## Troubleshooting
508
+
509
+ ### Parser errors
510
+
511
+ ```bash
512
+ # Enable verbose logging
513
+ RUST_LOG=debug archlint scan --verbose
514
+ ```
515
+
516
+ ### Slow analysis
517
+
518
+ ```bash
519
+ # Check cache status
520
+ ls -lh .smell-lens-cache/
521
+
522
+ # Clear cache if stale
523
+ archlint cache clear
524
+
525
+ # Use --quiet to disable progress bars
526
+ archlint scan --quiet
527
+ ```
528
+
529
+ ### False positives
530
+
531
+ ```yaml
532
+ # Adjust thresholds in archlint.yaml
533
+ thresholds:
534
+ god_module:
535
+ fan_in: 20 # Increase threshold
536
+ ```
537
+
538
+ ## License
539
+
540
+ MIT License - see [LICENSE](LICENSE) for details.
541
+
542
+ ## Credits
543
+
544
+ - Built with [oxc](https://oxc-project.github.io/) - blazingly fast JS/TS parser
545
+ - Inspired by [ArchUnit](https://www.archunit.org/), [madge](https://github.com/pahen/madge), [dependency-cruiser](https://github.com/sverweij/dependency-cruiser)
546
+ - Academic foundations: Robert C. Martin's stability metrics, LCOM4 cohesion metric
547
+
548
+ ## Contact
549
+
550
+ - Issues: [GitHub Issues](https://github.com/yourusername/archlint/issues)
551
+ - Discussions: [GitHub Discussions](https://github.com/yourusername/archlint/discussions)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@archlinter/cli",
3
- "version": "0.1.0",
3
+ "version": "0.1.3",
4
4
  "description": "Fast architecture smell detector for TypeScript/JavaScript",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -17,15 +17,16 @@
17
17
  },
18
18
  "files": [
19
19
  "bin",
20
- "scripts"
20
+ "scripts",
21
+ "README.md"
21
22
  ],
22
23
  "optionalDependencies": {
23
- "@archlinter/cli-darwin-arm64": "workspace:*",
24
- "@archlinter/cli-darwin-x64": "workspace:*",
25
- "@archlinter/cli-linux-x64": "workspace:*",
26
- "@archlinter/cli-linux-arm64": "workspace:*",
27
- "@archlinter/cli-linux-x64-musl": "workspace:*",
28
- "@archlinter/cli-win32-x64": "workspace:*"
24
+ "@archlinter/cli-darwin-arm64": "0.1.3",
25
+ "@archlinter/cli-darwin-x64": "0.1.3",
26
+ "@archlinter/cli-linux-x64": "0.1.3",
27
+ "@archlinter/cli-linux-arm64": "0.1.3",
28
+ "@archlinter/cli-linux-x64-musl": "0.1.3",
29
+ "@archlinter/cli-win32-x64": "0.1.3"
29
30
  },
30
31
  "engines": {
31
32
  "node": ">=18"