UNPKG

@notjustcoders/ioc-arise

Version:

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

161 lines • 7.96 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.generateCommand = void 0; const commander_1 = require("commander"); const path_1 = require("path"); const fs_1 = require("fs"); const analyser_1 = require("../analyser"); const generator_1 = require("../generator"); const configManager_1 = require("../utils/configManager"); const configValidator_1 = require("../utils/configValidator"); const index_js_1 = require("../errors/index.js"); const moduleResolver_1 = require("../utils/moduleResolver"); const one_logger_client_sdk_1 = require("@notjustcoders/one-logger-client-sdk"); exports.generateCommand = new commander_1.Command('generate') .description('Generate IoC container from TypeScript classes') .option('-s, --source <dir>', 'Source directory to scan', '.') .option('-o, --output <file>', 'Output file path', 'container.gen.ts') .option('-i, --interface <pattern>', 'Interface name pattern to match (regex)') .option('-e, --exclude <patterns...>', 'Exclude patterns for files') .option('--check-cycles', 'Only check for circular dependencies without generating') .option('--verbose', 'Enable verbose logging') .action(async (options) => { try { await (0, one_logger_client_sdk_1.initializeOneLogger)({ name: "ioc-maker", description: "ioc-maker", tracer: { batchSize: 1, }, isDev: process.env.NODE_ENV === "development", }); // Initialize config manager with the source directory const initialSourceDir = (0, path_1.resolve)(options.source); const configManager = new configManager_1.ConfigManager(initialSourceDir); // Validate config if present if (configManager.hasConfigFile()) { const config = configManager.getConfig(); if (!configValidator_1.ConfigValidator.validateAndLog(config, configManager.getConfigPath())) { process.exit(1); } } // Merge CLI options with config file const mergedOptions = configManager.mergeWithCliOptions(options); const sourceDir = (0, path_1.resolve)(mergedOptions.source); const outputPath = (0, path_1.resolve)(sourceDir, mergedOptions.output); if (configManager.hasConfigFile() && mergedOptions.verbose) { console.log(`šŸ“‹ Using config file: ${configManager.getConfigPath()}`); } // Initialize module resolver if modules are configured let moduleResolver = null; if (mergedOptions.modules && Object.keys(mergedOptions.modules).length > 0) { moduleResolver = new moduleResolver_1.ModuleResolver(mergedOptions.modules, sourceDir); if (mergedOptions.verbose) { console.log(`šŸ—ļø Module support enabled with ${Object.keys(mergedOptions.modules).length} modules`); } } if (!(0, fs_1.existsSync)(sourceDir)) { const error = index_js_1.ErrorFactory.sourceDirectoryNotFound(sourceDir); console.error(`āŒ ${index_js_1.ErrorUtils.formatForConsole(error)}`); process.exit(1); } if (mergedOptions.verbose) { console.log(`šŸ” Scanning directory: ${sourceDir}`); console.log(`šŸ“ Output file: ${outputPath}`); if (mergedOptions.interface) { console.log(`šŸŽÆ Interface pattern: ${mergedOptions.interface}`); } } console.log("šŸš€ Starting analysis..."); // Analyze the project const classes = await (0, analyser_1.analyzeProject)(sourceDir, { sourceDir, interfacePattern: mergedOptions.interface, excludePatterns: mergedOptions.exclude }); console.log("analysis results", classes); if (classes.length === 0) { const error = index_js_1.ErrorFactory.noClassesFound(mergedOptions.interface || 'interfaces with "implements" keyword'); console.error(`āŒ ${index_js_1.ErrorUtils.formatForConsole(error)}`); process.exit(1); return; } // Group classes by modules if module resolver is available let moduleGroupedClasses; if (moduleResolver) { moduleGroupedClasses = moduleResolver.groupClassesByModule(classes); if (mergedOptions.verbose) { console.log(`\nšŸ“‹ Found ${classes.length} classes organized into ${moduleGroupedClasses.size} modules:`); for (const [moduleName, moduleClasses] of moduleGroupedClasses) { console.log(`\n šŸ“¦ ${moduleName} (${moduleClasses.length} classes):`); moduleClasses.forEach(cls => { console.log(` • ${cls.name} (${cls.dependencies.length} dependencies)`); if (cls.dependencies.length > 0) { console.log(` Dependencies: ${cls.dependencies.map(dep => dep.name).join(', ')}`); } }); } } } else { // Backward compatibility: single default module moduleGroupedClasses = new Map([['CoreModule', classes]]); if (mergedOptions.verbose) { console.log(`\nšŸ“‹ Found ${classes.length} classes:`); classes.forEach(cls => { console.log(` • ${cls.name} (${cls.dependencies.length} dependencies)`); if (cls.dependencies.length > 0) { console.log(` Dependencies: ${cls.dependencies.map(dep => dep.name).join(', ')}`); } }); } } // Check for circular dependencies const cycles = (0, generator_1.detectCircularDependencies)(classes); if (cycles.length > 0) { const firstCycle = cycles[0]; if (firstCycle && firstCycle.length > 0) { const className = firstCycle[0] || 'unknown'; const error = index_js_1.ErrorFactory.circularDependency(className, firstCycle); console.error(`āŒ ${index_js_1.ErrorUtils.formatForConsole(error)}`); if (cycles.length > 1) { console.error('\n Additional cycles:'); cycles.slice(1).forEach((cycle, index) => { console.error(` ${index + 2}. ${cycle.join(' → ')}`); }); } } else { console.error('āŒ Circular dependencies detected but cycle information is incomplete'); } process.exit(1); } if (mergedOptions.checkCycles) { console.log('āœ… No circular dependencies found.'); return; } // Generate container file (0, generator_1.generateContainerFile)(moduleGroupedClasses, outputPath); console.log(`āœ… Container generated successfully!`); console.log(` File: ${outputPath}`); console.log(` Classes: ${classes.length}`); if (mergedOptions.verbose) { console.log('\nšŸŽ‰ You can now import and use your container:'); console.log(' import { container } from "./container.gen";'); console.log(' const userService = container.userService;'); } // Force process exit to prevent hanging due to one-logger SDK process.exit(0); } catch (error) { if (index_js_1.ErrorUtils.isIoCError(error)) { console.error(`āŒ ${index_js_1.ErrorUtils.formatForConsole(error)}`); } else { const wrappedError = index_js_1.ErrorFactory.unexpectedError(error); console.error(`āŒ ${index_js_1.ErrorUtils.formatForConsole(wrappedError)}`); } process.exit(1); } }); //# sourceMappingURL=generate.js.map