Skip to main content
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.