diff --git a/src/utils/fileUtils.ts b/src/utils/fileUtils.ts new file mode 100644 index 0000000..960260a --- /dev/null +++ b/src/utils/fileUtils.ts @@ -0,0 +1,164 @@ +import * as fs from 'fs-extra'; +import * as path from 'path'; +import * as os from 'os'; +import * as yaml from 'js-yaml'; +import { UserConfig } from '../models/types'; + +const CONFIG_FILE_NAME = 'config.json'; +const LAYOUTS_DIR = 'layouts'; +const TEMPLATES_DIR = 'templates'; + +export class FileUtils { + private baseDir: string; + + constructor(baseDir?: string) { + this.baseDir = baseDir || this.getDefaultBaseDir(); + } + + private getDefaultBaseDir(): string { + const homeDir = os.homedir(); + return path.join(homeDir, '.config', 'terminal-layouts'); + } + + async initialize(): Promise { + await fs.ensureDir(this.baseDir); + await fs.ensureDir(path.join(this.baseDir, LAYOUTS_DIR)); + await fs.ensureDir(path.join(this.baseDir, TEMPLATES_DIR)); + + const configPath = path.join(this.baseDir, CONFIG_FILE_NAME); + if (!(await fs.pathExists(configPath))) { + const defaultConfig: UserConfig = { + layoutDir: path.join(this.baseDir, LAYOUTS_DIR), + defaultFormat: 'json', + gitSyncEnabled: true, + templatesDir: path.join(this.baseDir, TEMPLATES_DIR), + }; + await fs.writeJson(configPath, defaultConfig, { spaces: 2 }); + } + } + + getConfigPath(): string { + return path.join(this.baseDir, CONFIG_FILE_NAME); + } + + getLayoutsDir(): string { + return path.join(this.baseDir, LAYOUTS_DIR); + } + + getTemplatesDir(): string { + return path.join(this.baseDir, TEMPLATES_DIR); + } + + async readConfig(): Promise { + const configPath = this.getConfigPath(); + if (await fs.pathExists(configPath)) { + return fs.readJson(configPath) as Promise; + } + throw new Error(`Configuration file not found: ${configPath}`); + } + + async saveConfig(config: UserConfig): Promise { + const configPath = this.getConfigPath(); + await fs.writeJson(configPath, config, { spaces: 2 }); + } + + async readLayout(fileName: string): Promise { + const filePath = path.join(this.getLayoutsDir(), fileName); + const content = await fs.readFile(filePath, 'utf-8'); + + if (fileName.endsWith('.yaml') || fileName.endsWith('.yml')) { + return yaml.load(content); + } + return fs.readJson(filePath); + } + + async saveLayout(fileName: string, data: unknown, format: 'json' | 'yaml' = 'json'): Promise { + const layoutsDir = this.getLayoutsDir(); + let filePath: string; + + if (format === 'yaml') { + const yamlName = fileName.replace(/\.json$/, '.yaml'); + filePath = path.join(layoutsDir, yamlName); + const content = yaml.dump(data); + await fs.writeFile(filePath, content); + } else { + if (!fileName.endsWith('.json')) { + filePath = path.join(layoutsDir, `${fileName}.json`); + } else { + filePath = path.join(layoutsDir, fileName); + } + await fs.writeJson(filePath, data, { spaces: 2 }); + } + + return filePath; + } + + async deleteLayout(fileName: string): Promise { + const filePath = path.join(this.getLayoutsDir(), fileName); + if (await fs.pathExists(filePath)) { + await fs.remove(filePath); + } + } + + async listLayouts(): Promise { + const layoutsDir = this.getLayoutsDir(); + if (!(await fs.pathExists(layoutsDir))) { + return []; + } + + const files = await fs.readdir(layoutsDir); + return files.filter((file) => file.endsWith('.json') || file.endsWith('.yaml') || file.endsWith('.yml')); + } + + async readTemplate(fileName: string): Promise { + const filePath = path.join(this.getTemplatesDir(), fileName); + const content = await fs.readFile(filePath, 'utf-8'); + + if (fileName.endsWith('.yaml') || fileName.endsWith('.yml')) { + return yaml.load(content); + } + return fs.readJson(filePath); + } + + async saveTemplate(fileName: string, data: unknown): Promise { + const templatesDir = this.getTemplatesDir(); + const filePath = path.join(templatesDir, fileName.endsWith('.json') ? fileName : `${fileName}.json`); + await fs.writeJson(filePath, data, { spaces: 2 }); + return filePath; + } + + async listTemplates(): Promise { + const templatesDir = this.getTemplatesDir(); + if (!(await fs.pathExists(templatesDir))) { + return []; + } + + const files = await fs.readdir(templatesDir); + return files.filter((file) => file.endsWith('.json') || file.endsWith('.yaml') || file.endsWith('.yml')); + } + + async deleteTemplate(fileName: string): Promise { + const filePath = path.join(this.getTemplatesDir(), fileName); + if (await fs.pathExists(filePath)) { + await fs.remove(filePath); + } + } + + async fileExists(filePath: string): Promise { + return fs.pathExists(filePath); + } + + async readFile(filePath: string): Promise { + return fs.readFile(filePath, 'utf-8'); + } + + async writeFile(filePath: string, content: string): Promise { + await fs.writeFile(filePath, content); + } + + async ensureDir(dirPath: string): Promise { + await fs.ensureDir(dirPath); + } +} + +export const fileUtils = new FileUtils();