UNPKG

vibe-coder-mcp

Version:

Production-ready MCP server with complete agent integration, multi-transport support, and comprehensive development automation tools for AI-assisted workflows.

232 lines (231 loc) 9 kB
import logger from '../../../logger.js'; import { AppError } from '../../../utils/errors.js'; export class DIContainer { services = new Map(); resolving = new Set(); scopedInstances = new Map(); register(token, factory, lifecycle = 'singleton', dependencies = []) { const tokenStr = typeof token === 'string' ? token : String(token); if (this.services.has(tokenStr)) { logger.warn(`Service ${tokenStr} is already registered. Overwriting.`); } this.services.set(tokenStr, { factory, lifecycle, dependencies }); logger.debug(`Registered service: ${tokenStr} with lifecycle: ${lifecycle}`); } singleton(token, factory, dependencies = []) { this.register(token, factory, 'singleton', dependencies); } transient(token, factory, dependencies = []) { this.register(token, factory, 'transient', dependencies); } scoped(token, factory, dependencies = []) { this.register(token, factory, 'scoped', dependencies); } async resolve(token) { const tokenStr = typeof token === 'string' ? token : String(token); return this.resolveInternal(tokenStr); } resolveSync(token) { const tokenStr = typeof token === 'string' ? token : String(token); return this.resolveInternalSync(tokenStr); } resolveInternalSync(token) { if (this.resolving.has(token)) { const cycle = Array.from(this.resolving).join(' -> ') + ' -> ' + token; throw new AppError(`Circular dependency detected: ${cycle}`, { cycle, token, errorCode: 'CIRCULAR_DEPENDENCY_ERROR' }); } const registration = this.services.get(token); if (!registration) { throw new AppError(`Service not registered: ${token}`, { token, errorCode: 'SERVICE_NOT_FOUND_ERROR' }); } switch (registration.lifecycle) { case 'singleton': if (registration.instance) { return registration.instance; } break; case 'scoped': if (this.scopedInstances.has(token)) { return this.scopedInstances.get(token); } break; case 'transient': break; } this.resolving.add(token); try { const instance = registration.factory(this); if (instance instanceof Promise) { throw new AppError(`Service ${token} requires async resolution. Use resolve() instead.`, { token, errorCode: 'SYNC_RESOLUTION_ERROR' }); } switch (registration.lifecycle) { case 'singleton': registration.instance = instance; break; case 'scoped': this.scopedInstances.set(token, instance); break; case 'transient': break; } logger.debug(`Resolved service synchronously: ${token}`); return instance; } finally { this.resolving.delete(token); } } async resolveInternal(token) { if (this.resolving.has(token)) { const cycle = Array.from(this.resolving).join(' -> ') + ' -> ' + token; throw new AppError(`Circular dependency detected: ${cycle}`, { cycle, token, errorCode: 'CIRCULAR_DEPENDENCY_ERROR' }); } const registration = this.services.get(token); if (!registration) { throw new AppError(`Service not registered: ${token}`, { token, errorCode: 'SERVICE_NOT_FOUND_ERROR' }); } switch (registration.lifecycle) { case 'singleton': if (registration.instance) { return registration.instance; } break; case 'scoped': if (this.scopedInstances.has(token)) { return this.scopedInstances.get(token); } break; case 'transient': break; } this.resolving.add(token); try { const instance = await registration.factory(this); switch (registration.lifecycle) { case 'singleton': registration.instance = instance; break; case 'scoped': this.scopedInstances.set(token, instance); break; case 'transient': break; } logger.debug(`Resolved service: ${token}`); return instance; } finally { this.resolving.delete(token); } } isRegistered(token) { const tokenStr = typeof token === 'string' ? token : String(token); return this.services.has(tokenStr); } getRegisteredServices() { return Array.from(this.services.keys()); } clearScoped() { this.scopedInstances.clear(); logger.debug('Cleared scoped service instances'); } dispose() { for (const [token, registration] of this.services) { if (registration.instance && typeof registration.instance.dispose === 'function') { try { registration.instance.dispose(); logger.debug(`Disposed service: ${token}`); } catch (error) { logger.error(`Error disposing service ${token}:`, error); } } } for (const registration of this.services.values()) { registration.instance = undefined; } this.scopedInstances.clear(); logger.debug('Disposed all service instances'); } validateDependencyGraph() { const visited = new Set(); const visiting = new Set(); const visit = (token) => { if (visiting.has(token)) { const cycle = Array.from(visiting).join(' -> ') + ' -> ' + token; throw new AppError(`Circular dependency detected in registration: ${cycle}`, { cycle, token, errorCode: 'CIRCULAR_DEPENDENCY_ERROR' }); } if (visited.has(token)) { return; } const registration = this.services.get(token); if (!registration) { return; } visiting.add(token); for (const dependency of registration.dependencies || []) { visit(dependency); } visiting.delete(token); visited.add(token); }; for (const token of this.services.keys()) { visit(token); } logger.debug('Dependency graph validation passed'); } getDependencyGraph() { const lines = []; for (const [token, registration] of this.services) { const deps = registration.dependencies || []; const lifecycle = registration.lifecycle; lines.push(`${token} (${lifecycle}): [${deps.join(', ')}]`); } return lines.join('\n'); } } export function createServiceToken(name) { return name; } let globalContainer = null; export function getContainer() { if (!globalContainer) { globalContainer = new DIContainer(); } return globalContainer; } export function setContainer(container) { globalContainer = container; } export function resetContainer() { if (globalContainer) { globalContainer.dispose(); } globalContainer = null; } export const ServiceTokens = { StorageManager: createServiceToken('StorageManager'), ConfigLoader: createServiceToken('ConfigLoader'), IdGenerator: createServiceToken('IdGenerator'), TaskOperations: createServiceToken('TaskOperations'), ProjectOperations: createServiceToken('ProjectOperations'), DependencyOperations: createServiceToken('DependencyOperations'), DecompositionService: createServiceToken('DecompositionService'), EpicService: createServiceToken('EpicService'), AgentOrchestrator: createServiceToken('AgentOrchestrator'), RDDEngine: createServiceToken('RDDEngine'), ContextEnrichmentService: createServiceToken('ContextEnrichmentService'), DependencyValidator: createServiceToken('DependencyValidator'), FileUtils: createServiceToken('FileUtils'), TaskFileManager: createServiceToken('TaskFileManager'), AtomicDetector: createServiceToken('AtomicDetector'), UnifiedLifecycleManager: createServiceToken('UnifiedLifecycleManager'), UnifiedTaskExecutionEngine: createServiceToken('UnifiedTaskExecutionEngine'), UnifiedStorageEngine: createServiceToken('UnifiedStorageEngine'), UnifiedSecurityEngine: createServiceToken('UnifiedSecurityEngine'), UnifiedOrchestrationEngine: createServiceToken('UnifiedOrchestrationEngine') };