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.
163 lines (140 loc) • 4.6 kB
text/typescript
import path from 'path';
import fs from 'fs-extra';
import fsPromises from 'fs/promises';
import fsSync from 'fs';
// Types
export interface FileSystem {
writeFile: typeof fs.writeFile;
readFile: typeof fs.readFile;
readdir: typeof fs.readdir;
stat: typeof fs.stat;
remove: typeof fs.remove;
mkdir: typeof fs.mkdir;
exists: (filePath: string) => Promise<boolean>;
// Alias pour la compatibilité avec fs-extra
pathExists: (filePath: string) => Promise<boolean>;
ensureDir: typeof fs.ensureDir;
}
export const createFileSystem = (): FileSystem => {
const existsImpl = async (filePath: string): Promise<boolean> => {
try {
await fsPromises.access(filePath);
return true;
} catch {
return false;
}
};
return {
writeFile: fs.writeFile,
readFile: fs.readFile,
readdir: fs.readdir,
stat: fs.stat,
remove: fs.remove,
mkdir: fs.mkdir,
ensureDir: fs.ensureDir,
exists: existsImpl,
pathExists: existsImpl, // Alias pour compatibilité
};
};
export const validateFileExists = async (fileSystem: FileSystem, filePath: string): Promise<boolean> => {
return await fileSystem.exists(filePath);
};
export const ensureDirectoryExists = async (fileSystem: FileSystem, dirPath: string): Promise<void> => {
const exists = await fileSystem.exists(dirPath);
if (!exists) {
await fileSystem.mkdir(dirPath, { recursive: true });
}
};
export const writeFileContent = async (
fileSystem: FileSystem,
filePath: string,
content: string,
encoding: BufferEncoding = 'utf8'
): Promise<void> => {
const dir = path.dirname(filePath);
await ensureDirectoryExists(fileSystem, dir);
await fileSystem.writeFile(filePath, content, encoding);
};
export const readFile = async (
fileSystem: FileSystem,
filePath: string,
encoding: BufferEncoding = 'utf8'
): Promise<string> => {
return await fileSystem.readFile(filePath, encoding);
};
export const fileExists = (filePath: string): boolean => {
return fsSync.existsSync(filePath);
};
// Utility functions for common operations
export const createBackupFile = async (
fileSystem: FileSystem,
originalPath: string
): Promise<string> => {
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
const backupPath = `${originalPath}.backup-${timestamp}`;
const exists = await validateFileExists(fileSystem, originalPath);
if (exists) {
const content = await readFile(fileSystem, originalPath);
await writeFileContent(fileSystem, backupPath, content);
}
return backupPath;
};
export const removeFile = async (
fileSystem: FileSystem,
filePath: string
): Promise<void> => {
const exists = await validateFileExists(fileSystem, filePath);
if (exists) {
await fileSystem.remove(filePath);
}
};
// Legacy exports for backward compatibility
export const createDirectory = async (dirPath: string): Promise<void> => {
const fileSystem = createFileSystem();
await ensureDirectoryExists(fileSystem, dirPath);
};
export const writeFile = async (filePath: string, content: string): Promise<void> => {
const fileSystem = createFileSystem();
await writeFileContent(fileSystem, filePath, content);
};
export const readDirectory = async (dirPath: string): Promise<string[]> => {
const fileSystem = createFileSystem();
return await fileSystem.readdir(dirPath);
};
export const getFileMetadata = async (filePath: string) => {
const fileSystem = createFileSystem();
return await fileSystem.stat(filePath);
};
export const buildFilePath = (...segments: string[]): string => {
return path.join(...segments);
};
export interface FileOperationResult {
success: boolean;
error?: string;
}
// Pure functions for validation
export const validateDomainName = (domainName: string): boolean => {
return /^[a-zA-Z0-9-_]+$/.test(domainName);
};
// Pure functions for error handling
export const getErrorMessage = (error: unknown): string => {
return error instanceof Error ? error.message : 'Unknown error';
};
// Pure functions for file operations with results
export const executeFileOperationWithErrorHandling = async <T>(
operation: () => Promise<T>
): Promise<FileOperationResult> => {
try {
await operation();
return { success: true };
} catch (error) {
return {
success: false,
error: getErrorMessage(error)
};
}
};
export const getDomainPath = (basePath: string, domainName: string): string =>
path.join(basePath, 'src', 'domains', domainName);
export const getDomainsBasePath = (basePath: string): string =>
path.join(basePath, 'src', 'domains');