UNPKG

@notjustcoders/ioc-arise

Version:

Arise type-safe IoC containers from your code. Zero overhead, zero coupling.

110 lines 4.44 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ImportGenerator = void 0; class ImportGenerator { constructor(classes) { this.aliasMap = new Map(); this.classes = classes; this.generateAliases(); } /** * Detects name collisions and generates unique aliases for colliding class names. */ generateAliases() { const nameToClasses = new Map(); // Group classes by name to detect collisions for (const classInfo of this.classes) { if (!nameToClasses.has(classInfo.name)) { nameToClasses.set(classInfo.name, []); } nameToClasses.get(classInfo.name).push(classInfo); } // Generate aliases for colliding names for (const [className, classList] of nameToClasses) { if (classList.length > 1) { // Name collision detected - generate unique aliases for (let i = 1; i < classList.length; i++) { const classInfo = classList[i]; if (classInfo) { const alias = this.generateUniqueAlias(className, classInfo.importPath, i); this.aliasMap.set(classInfo.importPath, alias); } } } } } /** * Generates a unique alias based on the class name and its module path. */ generateUniqueAlias(className, importPath, index) { // Extract module name from import path (e.g., './user/CreateItemUseCase' -> 'User') const pathParts = importPath.split('/'); let moduleName = ''; // Find the module directory name (the part before the class file) for (let i = pathParts.length - 2; i >= 0; i--) { const part = pathParts[i]; if (part && part !== '.' && part !== '..') { // Sanitize the module name to ensure it's a valid variable name const sanitized = part.replace(/[^a-zA-Z0-9]/g, ''); if (sanitized) { moduleName = sanitized.charAt(0).toUpperCase() + sanitized.slice(1); break; } } } // If we couldn't extract a meaningful module name, use index if (!moduleName) { moduleName = `Module${index + 1}`; } // Ensure the final alias is a valid Pascal case variable name const alias = `${moduleName}${className}`; return alias.replace(/[^a-zA-Z0-9]/g, ''); } /** * Gets the alias for a class, or returns the original name if no alias exists. */ getClassAlias(classInfo) { return this.aliasMap.get(classInfo.importPath) || classInfo.name; } /** * Gets the alias for a class by its import path. */ getClassAliasByPath(importPath) { return this.aliasMap.get(importPath) || ''; } /** * Checks if a class has an alias (i.e., was involved in a name collision). */ hasAlias(classInfo) { return this.aliasMap.has(classInfo.importPath); } generateImports() { const importSet = new Set(); const classMap = new Map(this.classes.map(c => [c.name, c])); // Add imports for all managed classes with aliases if needed for (const classInfo of this.classes) { const alias = this.getClassAlias(classInfo); if (alias !== classInfo.name) { // Use alias for colliding imports importSet.add(`import { ${classInfo.name} as ${alias} } from '${classInfo.importPath}';`); } else { // No collision, use original name importSet.add(`import { ${classInfo.name} } from '${classInfo.importPath}';`); } } // Add imports for unmanaged dependencies for (const classInfo of this.classes) { for (const dep of classInfo.dependencies) { // If dependency is not a managed class, we need to import it if (!classMap.has(dep.name)) { //TODO: Think about this // importSet.add(`import { ${dep.name} } from '${dep.importPath}';`); } } } return Array.from(importSet).join('\n'); } } exports.ImportGenerator = ImportGenerator; //# sourceMappingURL=import-generator.js.map