@notjustcoders/ioc-arise
Version:
Arise type-safe IoC containers from your code. Zero overhead, zero coupling.
145 lines • 6.83 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.SplitFileWriter = void 0;
const fs_1 = require("fs");
const path_1 = require("path");
const index_js_1 = require("../../errors/index.js");
const import_generator_js_1 = require("../import-generator.js");
const index_js_2 = require("../shared/index.js");
/**
* Handles writing split module files when there are more than 3 modules.
* Each module gets its own <moduleName>.gen.ts file, plus a main container.gen.ts aggregator.
*/
class SplitFileWriter {
constructor(outputPath) {
this.outputPath = outputPath;
this.outputDir = (0, path_1.dirname)(outputPath);
}
/**
* Writes split module files and main aggregator file.
*/
writeSplitModules(moduleGroupedClasses, sortedModules, moduleDependencies, moduleContainerFunctionGenerator, moduleInstantiationGenerator, globalImportGenerator) {
// Ensure output directory exists
(0, fs_1.mkdirSync)(this.outputDir, { recursive: true });
// Write individual module files
for (const moduleName of sortedModules) {
const moduleClasses = moduleGroupedClasses.get(moduleName);
if (!moduleClasses)
continue;
const moduleFilePath = (0, path_1.join)(this.outputDir, `${moduleName}.gen.ts`);
const moduleContent = this.generateModuleFileContent(moduleName, moduleClasses, moduleDependencies, moduleContainerFunctionGenerator, moduleInstantiationGenerator, globalImportGenerator);
try {
(0, fs_1.writeFileSync)(moduleFilePath, moduleContent, 'utf-8');
}
catch (error) {
throw index_js_1.ErrorFactory.fileWriteError(moduleFilePath, error instanceof Error ? error.message : String(error));
}
}
// Write main aggregator file
const aggregatorContent = this.generateAggregatorFileContent(sortedModules, moduleDependencies);
try {
(0, fs_1.writeFileSync)(this.outputPath, aggregatorContent, 'utf-8');
}
catch (error) {
throw index_js_1.ErrorFactory.fileWriteError(this.outputPath, error instanceof Error ? error.message : String(error));
}
}
/**
* Generates content for an individual module file.
*/
generateModuleFileContent(moduleName, moduleClasses, moduleDependencies, moduleContainerFunctionGenerator, moduleInstantiationGenerator, globalImportGenerator) {
// Create a module-specific import generator
const moduleImportGenerator = new import_generator_js_1.ImportGenerator(moduleClasses);
const moduleImports = moduleImportGenerator.generateImports();
// Generate module container function
const moduleContainerFunctions = moduleContainerFunctionGenerator.generateModuleContainerFunctions([moduleName], moduleDependencies);
// Generate module dependencies import statements
const moduleDeps = moduleDependencies.get(moduleName) || new Set();
const dependencyImports = this.generateDependencyImports(moduleDeps);
// Generate module type definitions
const moduleTypeExport = this.generateModuleTypeExport(moduleName);
return [
moduleImports,
dependencyImports,
'',
moduleContainerFunctions.join('\n\n'),
'',
moduleTypeExport
].filter(line => line.trim() !== '').join('\n');
}
/**
* Generates dependency import statements for a module.
*/
generateDependencyImports(moduleDeps) {
if (moduleDeps.size === 0)
return '';
const imports = Array.from(moduleDeps).map(depModule => `import { create${depModule}Container } from './${depModule}.gen';`);
return imports.join('\n');
}
/**
* Generates type export for a module.
*/
generateModuleTypeExport(moduleName) {
const functionName = `create${moduleName}Container`;
return `export { ${functionName} };
export type ${moduleName}Container = ReturnType<typeof ${functionName}>;`;
}
/**
* Generates content for the main aggregator file.
*/
generateAggregatorFileContent(sortedModules, moduleDependencies) {
// Generate imports for all module files
const moduleImports = sortedModules.map(moduleName => `import { create${moduleName}Container } from './${moduleName}.gen';`).join('\n');
// Generate module instantiations in dependency order
const moduleInstantiations = this.generateModuleInstantiationsForAggregator(sortedModules, moduleDependencies);
// Generate aggregated container
const aggregatedContainer = this.generateAggregatedContainerForSplit(sortedModules);
// Generate type export with path utilities and preserve onInit
const typeExport = index_js_2.InstantiationUtils.generateModularContainerTypeExportWithPathUtils(this.outputPath);
return [
moduleImports,
'',
moduleInstantiations.join('\n'),
'',
aggregatedContainer,
'',
typeExport
].join('\n');
}
/**
* Generates module instantiations for the aggregator file.
*/
generateModuleInstantiationsForAggregator(sortedModules, moduleDependencies) {
const instantiations = [];
for (const moduleName of sortedModules) {
const moduleDeps = moduleDependencies.get(moduleName) || new Set();
const moduleVarName = this.toCamelCase(moduleName) + 'Container';
const moduleFunctionName = `create${moduleName}Container`;
const functionArgs = Array.from(moduleDeps).map(depModule => this.toCamelCase(depModule) + 'Container');
const functionCall = functionArgs.length > 0
? `${moduleFunctionName}(${functionArgs.join(', ')})`
: `${moduleFunctionName}()`;
instantiations.push(`const ${moduleVarName} = ${functionCall};`);
}
return instantiations;
}
/**
* Generates the aggregated container for split files.
*/
generateAggregatedContainerForSplit(sortedModules) {
const moduleExports = sortedModules.map(moduleName => {
const moduleVarName = this.toCamelCase(moduleName) + 'Container';
const moduleKey = this.toCamelCase(moduleName);
return ` ${moduleKey}: ${moduleVarName}`;
});
return `export const container = {\n${moduleExports.join(',\n')}\n};`;
}
/**
* Converts a string to camelCase.
*/
toCamelCase(str) {
return str.charAt(0).toLowerCase() + str.slice(1).replace(/[^a-zA-Z0-9]/g, '');
}
}
exports.SplitFileWriter = SplitFileWriter;
//# sourceMappingURL=split-file-writer.js.map