dependency-injection-patternslisted
Install: claude install-skill kookr-ai/kookr
# Dependency Injection Patterns
Rules for wiring dependencies that are testable, visible, and proportional to codebase size.
**Research:** `docs/deepresearch/reports/Dependency Injection Patterns for TypeScript.md`
## Non-Negotiable Rules
| # | Rule | Violation Example | Correct Pattern |
|---|------|-------------------|-----------------|
| 1 | **Constructor injection only** | `private db = new Database()` inside class | `constructor(private readonly db: Database)` |
| 2 | **No service locators** | `ServiceLocator.get<Database>('database')` | Explicit constructor parameter |
| 3 | **Single composition root** | `new X(new Y(new Z()))` in controllers | All wiring in `main.ts` or `container.ts` |
| 4 | **Explicit lifetimes** | New DB pool per request | Singleton for pools; scoped for request context |
| 5 | **No circular dependencies** | `A -> B -> A` | Extract interface; use layered architecture (domain <- app <- infra) |
| 6 | **DI only at I/O boundaries** | `@Injectable()` on pure utility function | Pure functions stay plain functions |
| 7 | **No framework decorators in domain** | `@Injectable()` in `domain/user.service.ts` | Domain depends on interfaces only; decorators in infra layer |
| 8 | **Mock via constructor, not vi.mock** | `vi.mock('../database')` for unit tests | `new UserService(mockDb, mockEmail)` |
| 9 | **Scale container to codebase** | InversifyJS + reflection for 5 classes | Manual wiring for <15 classes; lightweight container for medium |
| 10 | **Rule