UNPKG

ruch

Version:

Revolutionary React TypeScript CLI with hexagonal architecture & AI-powered development assistance. Create maintainable, scalable applications with domain-driven design and integrated AI tooling.

91 lines (75 loc) 3.35 kB
import fs from 'fs-extra'; import path from 'path'; import type { Logger } from './console-logger'; import type { PathUtils } from './path-utils'; import type { DomainGenerationOptions } from '../templates/domains'; import { getDomainFiles } from '../templates/domains'; export interface DomainFactoryDependencies { logger: Logger; pathUtils: PathUtils; generateDomainFiles: (domainName: string, options: DomainGenerationOptions) => Promise<void>; } export class DomainFactory { constructor(private dependencies: DomainFactoryDependencies) {} async createDomain(domainName: string, options: DomainGenerationOptions): Promise<void> { const { logger, pathUtils } = this.dependencies; // Domain name validation if (!this.validateDomainName(domainName)) { logger.error(`❌ Invalid domain name: "${domainName}"`); logger.error('💡 Domain names must be valid TypeScript identifiers:'); logger.error(' - Start with a letter'); logger.error(' - Contain only letters, numbers, and underscores'); logger.error(' - No hyphens, spaces, or special characters'); logger.error('📝 Examples: "user", "userProfile", "user_profile", "orderManagement"'); return; } const domainPath = pathUtils.getDomainPath(domainName); const domainsBasePath = pathUtils.getDomainsPath(); // Check if domain already exists if (await fs.pathExists(domainPath)) { logger.error(`Domain "${domainName}" already exists in ${domainPath}`); return; } try { // Create src/domains folder if it doesn't exist await fs.ensureDir(domainsBasePath); // Create domain structure logger.info(`Creating domain "${domainName}"...`); // Create all folders const folders = ['entities', 'ports', 'services', 'adapters', 'hooks']; if (options.withUi) folders.push('ui'); for (const folder of folders) { await fs.ensureDir(path.join(domainPath, folder)); } // Generate and write all files const files = getDomainFiles(domainName, options); for (const file of files) { await fs.writeFile(path.join(domainPath, file.path), file.content, 'utf8'); } // Display summary logger.success(`Domain "${domainName}" created successfully!`); logger.info(`Location: ${domainPath}`); logger.info('Generated structure:'); console.log(`├── entities/`); console.log(`├── ports/`); console.log(`├── services/`); console.log(`├── adapters/`); console.log(`├── hooks/`); if (options.withUi) console.log(`├── ui/`); console.log(`└── index.ts`); logger.info(`💡 You can now import the domain with: import { ... } from './src/domains/${domainName}'`); } catch (error) { logger.error(`Error creating domain: ${error instanceof Error ? error.message : 'Unknown error'}`); // Cleanup on error if (await fs.pathExists(domainPath)) { await fs.remove(domainPath); logger.info('Cleanup completed after error.'); } } } private validateDomainName(domainName: string): boolean { // Allow only valid TypeScript identifiers (no hyphens) const validNameRegex = /^[a-zA-Z_][a-zA-Z0-9_]*$/; return validNameRegex.test(domainName); } }