UNPKG

@pulzar/core

Version:

Next-generation Node.js framework for ultra-fast web applications with zero-reflection DI, GraphQL, WebSockets, events, and edge runtime support

146 lines 4.9 kB
export class ModuleRegistry { modules = new Map(); resolved = false; register(module) { if (this.resolved) { throw new Error("Cannot register modules after resolution"); } if (this.modules.has(module.name)) { throw new Error(`Module '${module.name}' is already registered`); } this.modules.set(module.name, module); } getModule(name) { return this.modules.get(name); } getAllModules() { return Array.from(this.modules.values()); } hasModule(name) { return this.modules.has(name); } resolve() { if (this.resolved) { throw new Error("Module registry already resolved"); } const dependencies = new Map(); const exports = new Map(); // Build dependency graph for (const [name, module] of this.modules.entries()) { dependencies.set(name, module.imports); exports.set(name, module.exports); } // Validate dependencies this.validateDependencies(dependencies); // Sort modules topologically const sortedModules = this.topologicalSort(dependencies); this.resolved = true; return { modules: this.modules, dependencies, exports, }; } validateDependencies(dependencies) { const errors = []; // Check for missing imports for (const [moduleName, imports] of dependencies.entries()) { for (const importedModule of imports) { if (!this.modules.has(importedModule)) { errors.push(`Module '${moduleName}' imports unknown module '${importedModule}'`); } } } // Check for circular dependencies const visited = new Set(); const visiting = new Set(); for (const moduleName of this.modules.keys()) { if (this.hasCircularDependency(moduleName, dependencies, visited, visiting)) { errors.push(`Circular dependency detected involving module '${moduleName}'`); } } if (errors.length > 0) { throw new Error(`Module validation failed:\n${errors.join("\n")}`); } } hasCircularDependency(moduleName, dependencies, visited, visiting) { if (visiting.has(moduleName)) { return true; } if (visited.has(moduleName)) { return false; } visiting.add(moduleName); const deps = dependencies.get(moduleName) || []; for (const dep of deps) { if (this.hasCircularDependency(dep, dependencies, visited, visiting)) { return true; } } visiting.delete(moduleName); visited.add(moduleName); return false; } topologicalSort(dependencies) { const visited = new Set(); const result = []; const visit = (moduleName) => { if (visited.has(moduleName)) { return; } visited.add(moduleName); const deps = dependencies.get(moduleName) || []; for (const dep of deps) { visit(dep); } result.push(moduleName); }; for (const moduleName of this.modules.keys()) { visit(moduleName); } return result; } getExportedProviders(moduleName) { const module = this.modules.get(moduleName); return module ? module.exports : []; } resolveImport(moduleName, providerToken) { const module = this.modules.get(moduleName); if (!module) { return false; } // Check if provider is directly exported if (module.exports.includes(providerToken)) { return true; } // Check re-exports from imported modules for (const importedModuleName of module.imports) { const importedModule = this.modules.get(importedModuleName); if (importedModule && importedModule.exports.includes(providerToken)) { return true; } } return false; } getModuleNamespace(moduleName) { const module = this.modules.get(moduleName); return module?.namespace; } clear() { this.modules.clear(); this.resolved = false; } getStats() { return { totalModules: this.modules.size, resolved: this.resolved, moduleNames: Array.from(this.modules.keys()), totalExports: Array.from(this.modules.values()).reduce((total, module) => total + module.exports.length, 0), }; } } export function createModuleRegistry() { return new ModuleRegistry(); } export default ModuleRegistry; //# sourceMappingURL=module-registry.js.map