import type { DIContainer, ServiceToken } from './types' export type { ServiceToken } from './types' interface ServiceRegistration { service: any scope: 'singleton' | 'transient' instance?: any } /** * Dependency Injection Container * Manages service registration and injection across modules */ export class DIContainerImpl implements DIContainer { private services = new Map() /** * Register a service in the container */ provide(token: ServiceToken, service: T, scope: 'singleton' | 'transient' = 'singleton'): void { this.services.set(token, { service, scope, instance: scope === 'singleton' ? service : undefined }) } /** * Inject a service from the container */ inject(token: ServiceToken): T | undefined { const registration = this.services.get(token) if (!registration) { return undefined } if (registration.scope === 'singleton') { return registration.instance as T } // For transient services, create new instance // Note: This assumes the service is a constructor function if (typeof registration.service === 'function') { try { return new registration.service() as T } catch (error) { console.error(`Error creating transient service for token ${String(token)}:`, error) return undefined } } return registration.service as T } /** * Remove a service from the container */ remove(token: ServiceToken): boolean { return this.services.delete(token) } /** * Clear all services */ clear(): void { this.services.clear() } /** * Get all registered service tokens */ getRegisteredTokens(): ServiceToken[] { return Array.from(this.services.keys()) } /** * Check if a service is registered */ has(token: ServiceToken): boolean { return this.services.has(token) } /** * Get service registration info */ getServiceInfo(token: ServiceToken): { scope: string; hasInstance: boolean } | undefined { const registration = this.services.get(token) if (!registration) { return undefined } return { scope: registration.scope, hasInstance: registration.instance !== undefined } } } // Global DI container instance export const container = new DIContainerImpl() // Service token constants export const SERVICE_TOKENS = { // Core services EVENT_BUS: Symbol('eventBus'), ROUTER: Symbol('router'), // Nostr services RELAY_HUB: Symbol('relayHub'), NOSTR_CLIENT_HUB: Symbol('nostrClientHub'), // Auth services AUTH_SERVICE: Symbol('authService'), // Market services MARKET_STORE: Symbol('marketStore'), PAYMENT_MONITOR: Symbol('paymentMonitor'), // Chat services CHAT_SERVICE: Symbol('chatService'), // Events services EVENTS_SERVICE: Symbol('eventsService'), } as const // Type-safe injection helpers export function injectService(token: ServiceToken): T { const service = container.inject(token) if (!service) { throw new Error(`Service not found for token: ${String(token)}`) } return service } export function tryInjectService(token: ServiceToken): T | undefined { return container.inject(token) }