UNPKG

context-rag

Version:

Get relevant project context for AI agents to save 90% of tokens. Lightweight CLI tool for semantic search on project codebases.

123 lines (110 loc) 3.42 kB
const fs = require('fs'); const path = require('path'); const chalk = require('chalk'); const CONFIG_FILE = '.context-rag.config.json'; /** * Load and validate configuration file * @param {Object} options - Loading options * @param {boolean} options.silent - Suppress console output when true * @returns {Object|null} Configuration object or null if not found */ async function loadConfig(options = {}) { const { silent = false } = options; try { if (!fs.existsSync(CONFIG_FILE)) { if (!silent) { console.log(chalk.yellow('⚠️ No configuration found. Run "context-rag init" first.')); } return null; } const configContent = fs.readFileSync(CONFIG_FILE, 'utf8'); const config = JSON.parse(configContent); // Validate required fields const requiredFields = [ 'index.include', 'embedder.type', 'search.engine' ]; const missingFields = []; for (const field of requiredFields) { if (!getNestedValue(config, field)) { missingFields.push(field); } } if (missingFields.length > 0) { if (!silent) { console.error(chalk.red('❌ Configuration validation failed:')); missingFields.forEach(field => { console.error(chalk.red(` Missing required field: ${field}`)); }); console.log(chalk.yellow('💡 Run "context-rag init" to regenerate configuration')); } return null; } // Validate cache directory exists const cacheDir = path.dirname(config.storage.path); if (!fs.existsSync(cacheDir)) { fs.mkdirSync(cacheDir, { recursive: true }); if (!silent) { console.log(chalk.green(`Created cache directory: ${cacheDir}`)); } } return config; } catch (error) { if (error instanceof SyntaxError) { if (!silent) { console.error(chalk.red('❌ Invalid JSON in configuration file:')); console.error(chalk.red(` ${error.message}`)); console.log(chalk.yellow('💡 Check your .context-rag.config.json file')); } return null; } throw error; } } /** * Save configuration to file * @param {Object} config - Configuration object to save */ async function saveConfig(config) { try { fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2)); } catch (error) { throw new Error(`Failed to save configuration: ${error.message}`); } } /** * Get nested value from object using dot notation * @param {Object} obj - Object to search in * @param {string} path - Dot notation path (e.g., 'index.include') * @returns {*} Value at path or undefined */ function getNestedValue(obj, path) { return path.split('.').reduce((current, key) => { return current && current[key] !== undefined ? current[key] : undefined; }, obj); } /** * Set nested value in object using dot notation * @param {Object} obj - Object to modify * @param {string} path - Dot notation path * @param {*} value - Value to set */ function setNestedValue(obj, path, value) { const keys = path.split('.'); const lastKey = keys.pop(); const target = keys.reduce((current, key) => { if (!current[key] || typeof current[key] !== 'object') { current[key] = {}; } return current[key]; }, obj); target[lastKey] = value; } module.exports = { loadConfig, saveConfig, getNestedValue, setNestedValue, CONFIG_FILE };