UNPKG

cmte

Version:

Design by Committee™ except it's just you and LLMs

125 lines (115 loc) 3.49 kB
import fs from 'fs/promises'; import path from 'path'; import { logger } from "./logger.js"; /** * Ensures a directory exists, creating it if necessary * @param directoryPath Path to the directory */ export async function ensureDir(directoryPath) { try { await fs.mkdir(directoryPath, { recursive: true }); logger.debug(`Directory ensured: ${directoryPath}`); } catch (error) { logger.error(`Failed to create directory: ${directoryPath}`, { error }); throw error; } } /** * Reads a file and returns its contents * @param filePath Path to the file * @returns File contents as string */ export async function readFile(filePath) { try { const content = await fs.readFile(filePath, 'utf8'); logger.debug(`File read: ${filePath}`); return content; } catch (error) { logger.error(`Failed to read file: ${filePath}`, { error }); throw new Error(`Unable to read file at ${filePath}: ${error.message}`); } } /** * Writes content to a file, creating directories if needed * @param filePath Path to the file * @param content Content to write */ export async function writeFile(filePath, content) { try { // Ensure the directory exists await ensureDir(path.dirname(filePath)); // Write the file await fs.writeFile(filePath, content, 'utf8'); logger.debug(`File written: ${filePath}`); } catch (error) { logger.error(`Failed to write file: ${filePath}`, { error }); throw new Error(`Unable to write file at ${filePath}: ${error.message}`); } } /** * Checks if a file exists * @param filePath Path to the file * @returns True if file exists, false otherwise */ export async function fileExists(filePath) { try { await fs.access(filePath, fs.constants.F_OK); return true; } catch { return false; } } /** * Lists files in a directory matching a pattern * @param directoryPath Path to the directory * @param pattern Optional regex pattern to filter files * @returns Array of file paths */ export async function listFiles(directoryPath, pattern) { try { const files = await fs.readdir(directoryPath); let filePaths = files.map(file => path.join(directoryPath, file)); // Filter by pattern if provided if (pattern) { filePaths = filePaths.filter(filePath => pattern.test(filePath)); } return filePaths; } catch (error) { logger.error(`Failed to list files in directory: ${directoryPath}`, { error }); throw new Error(`Unable to list files in ${directoryPath}: ${error.message}`); } } /** * Resolves path strings with placeholders using a context object * @param pathTemplate Path template or object with path templates * @param context Context object with values for placeholders * @returns Resolved path string or object */ export function resolvePath(pathTemplate, context) { // If pathTemplate is an object, recursively resolve its values if (typeof pathTemplate === 'object' && pathTemplate !== null) { const result = {}; for (const [key, value] of Object.entries(pathTemplate)) { result[key] = resolvePath(value, context); } return result; } // If pathTemplate is a string, resolve placeholders if (typeof pathTemplate === 'string') { return pathTemplate.replace(/\{\{([^}]+)\}\}/g, (_, key) => { return context[key] !== undefined ? context[key] : `{{${key}}}`; }); } // Return unchanged for other types return pathTemplate; }