@notjustcoders/ioc-arise
Version:
Arise type-safe IoC containers from your code. Zero overhead, zero coupling.
110 lines • 4.44 kB
JavaScript
;
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