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.

164 lines (139 loc) 4.77 kB
import fs from 'fs-extra'; import path from 'path'; import { logger } from '../utils/logger'; import { getDomainsSourceDirectoryPath } from '../utils/paths'; import type { FileSystem } from '../utils/file-operations'; import { validateFileExists, readDirectory, getFileMetadata } from '../utils/file-operations'; import type { Logger } from '../utils/logging'; import { logError, logNoDomainsFound, logDomainsListed } from '../utils/logging'; // Types interface DomainStructure { name: string; path: string; folders: string[]; } interface DomainDisplay { icon: string; name: string; folders: Array<{ icon: string; name: string; }>; } // Pure functions const buildDomainDirectoryPath = (basePath: string, domainName: string): string => path.join(basePath, domainName); const isDirectory = (stats: fs.Stats): boolean => stats.isDirectory(); const sortDomainFolders = (folders: string[]): string[] => { const folderOrder = ['entities', 'ports', 'services', 'adapters', 'hooks', 'ui']; return folders.sort((a, b) => { const aIndex = folderOrder.indexOf(a); const bIndex = folderOrder.indexOf(b); if (aIndex === -1 && bIndex === -1) return a.localeCompare(b); if (aIndex === -1) return 1; if (bIndex === -1) return -1; return aIndex - bIndex; }); }; const getDomainDisplayIcon = (index: number, total: number): string => index === total - 1 ? '└──' : '├──'; const getFolderDisplayIcon = (folderIndex: number, totalFolders: number, isLastDomain: boolean): string => { if (folderIndex === totalFolders - 1 && isLastDomain) return ' └──'; if (folderIndex === totalFolders - 1) return '│ └──'; if (isLastDomain) return ' ├──'; return '│ ├──'; }; // Domain operations const getDomainFolderStructure = async ( fileSystem: FileSystem, domainPath: string ): Promise<string[]> => { const directoryEntries = await fileSystem.readdir(domainPath); const domainFolders: string[] = []; for (const entry of directoryEntries) { const entryPath = path.join(domainPath, entry); const stats = await fileSystem.stat(entryPath); if (isDirectory(stats)) { domainFolders.push(entry); } } return sortDomainFolders(domainFolders); }; const analyzeDomainStructures = async ( fileSystem: FileSystem, basePath: string, entries: string[] ): Promise<DomainStructure[]> => { const domainStructures: DomainStructure[] = []; for (const entry of entries) { const entryPath = buildDomainDirectoryPath(basePath, entry); const stats = await fileSystem.stat(entryPath); if (isDirectory(stats)) { const folders = await getDomainFolderStructure(fileSystem, entryPath); domainStructures.push({ name: entry, path: entryPath, folders }); } } return domainStructures; }; // Display operations const formatDomainDisplay = ( domain: DomainStructure, index: number, total: number ): DomainDisplay => { const icon = getDomainDisplayIcon(index, total); const folders = domain.folders.map((folder, folderIndex) => ({ icon: getFolderDisplayIcon(folderIndex, domain.folders.length, index === total - 1), name: folder })); return { icon, name: domain.name, folders }; }; const displayDomainStructure = (log: Logger, display: DomainDisplay): void => { log.log(`${display.icon} 📁 ${display.name}`); display.folders.forEach(folder => { log.log(`${folder.icon} 📂 ${folder.name}`); }); }; const displayDomainSeparator = (log: Logger, index: number, total: number): void => { if (index < total - 1) { log.log('│'); } }; // Main function export const listDomains = async ( fileSystem: FileSystem = fs, log: Logger = logger ): Promise<void> => { const domainsSourcePath = getDomainsSourceDirectoryPath(); try { if (!(await fileSystem.exists(domainsSourcePath))) { logNoDomainsFound(log, domainsSourcePath); return; } const directoryEntries = await fileSystem.readdir(domainsSourcePath); const domainStructures = await analyzeDomainStructures(fileSystem, domainsSourcePath, directoryEntries); if (domainStructures.length === 0) { logNoDomainsFound(log, domainsSourcePath); return; } logDomainsListed(log, domainStructures.length, domainsSourcePath); log.log(''); domainStructures.forEach((domain, index) => { const display = formatDomainDisplay(domain, index, domainStructures.length); displayDomainStructure(log, display); displayDomainSeparator(log, index, domainStructures.length); }); log.log(''); } catch (error: unknown) { logError(log, `Error reading domains: ${error instanceof Error ? error.message : 'Unknown error'}`); } };