Luca Brunner·
Got a clean Inversify container with singleton/scoped/transient lifetimes mapped out for me
Builds a complete DI container setup with service registration, lifetime management, and module organization.
Dependency Injection Container Architect
You are an architect setting up dependency injection for a {{project_scale}} project. Design and implement the complete DI system.
## Project Context
- Language: {{programming_language}}
- Framework: {{framework}}
- DI library: {{di_library}} (TSyringe, Inversify, Wire, Dig, python-dependency-injector, etc.)
- Architecture: {{architecture}} (Clean, Hexagonal, Onion, Layered)
## Service Inventory
```
{{service_inventory}}
```
## DI Requirements
1. **Container Configuration** - Complete registration of all services with correct lifetimes:
- Singleton (database, cache, config)
- Scoped (HTTP request context, user session)
- Transient (use case handlers, validators)
2. **Module Organization** - Grouped by domain/layer (Infrastructure, Application, Domain)
3. **Interface Registration** - Bind abstractions to implementations
4. **Factory Registrations** - For services needing runtime configuration
5. **Conditional Registration** - Different implementations per environment
6. **Decorators/Attributes** - Language-idiomatic DI decoration on classes
7. **Composition Root** - Single entry point wiring everything
8. **Verification** - Container validation ensuring all dependencies resolvable
9. **Interceptors/Middleware** - Cross-cutting concerns (logging, caching, auth)
10. **Test Overrides** - Easy mock substitution for testing
## Output
1. Complete container setup code
2. ASCII diagram showing dependency graph
3. Registration code for each layer/module
4. Example service class showing DI decoration
5. Test demonstrating mock substitution
6. Common pitfalls and how to avoid them
Ergebnisse
DI container for a large TypeScript + NestJS app using Inversify, clean architecture. Lifetimes mapped per concern.
## Dependency graph
```
CreateOrderUseCase (transient)
│ depends on
▼
OrderRepository (scoped) ──▶ PrismaClient (singleton)
│
▼
PaymentGateway (singleton) ──▶ HttpClient (singleton)
```
```typescript
// container.ts
const container = new Container();
// Infrastructure — one instance for the app lifetime
container.bind(TYPES.Prisma).to(PrismaClient).inSingletonScope();
container.bind<PaymentGateway>(TYPES.Gateway).to(StripeGateway).inSingletonScope();
// Application — fresh per request
container.bind<OrderRepository>(TYPES.OrderRepo).to(PgOrderRepository).inRequestScope();
// Use cases — transient, cheap to construct
container.bind(CreateOrderUseCase).toSelf().inTransientScope();
// Conditional binding per environment
if (env.NODE_ENV !== "prod") {
container.rebind<PaymentGateway>(TYPES.Gateway).to(FakeGateway);
}
```
```typescript
// Test override — swap a mock in one line
container.rebind<PaymentGateway>(TYPES.Gateway).toConstantValue(mockGateway);
```
**Pitfall:** injecting a request-scoped repo into a singleton silently captures the first request's context — the container's `container.isBound` validation at boot catches this. Composition root is the single `container.ts`; nothing else imports concretions.
Modell: Claude Sonnet 4
25 Likes12 SavesScore: 22
1 Kommentar
Emily Chen·
The fact that it flagged the latent bug instead of just rewriting is the real win.