UNPKG

revit-cli

Version:

A scalable CLI tool for Revit communication and data manipulation

382 lines 13.3 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ConfigManager = void 0; const fs = __importStar(require("fs-extra")); const path = __importStar(require("path")); const os = __importStar(require("os")); const yaml = __importStar(require("yaml")); const inquirer_1 = __importDefault(require("inquirer")); const logger_1 = require("../utils/logger"); /** * Manages configuration for the CLI and tools */ class ConfigManager { constructor() { this.defaultConfig = { revit: { apiUrl: 'http://localhost:8080', timeout: 30000, retries: 3 }, plugins: { directories: [ path.join(process.cwd(), 'plugins'), path.join(os.homedir(), '.revit-cli', 'plugins') ], disabled: [] }, logging: { level: 'info' }, tools: {} }; this.logger = new logger_1.Logger(); this.configPath = this.getDefaultConfigPath(); this.config = { ...this.defaultConfig }; } /** * Initialize the configuration manager */ async initialize() { this.logger.debug('Initializing Configuration Manager...'); try { await this.ensureConfigDirectory(); await this.loadConfig(); this.logger.debug('Configuration Manager initialized'); } catch (error) { this.logger.error('Failed to initialize Configuration Manager:', error); throw error; } } /** * Get the default configuration file path */ getDefaultConfigPath() { const configDir = path.join(os.homedir(), '.revit-cli'); return path.join(configDir, 'config.json'); } /** * Ensure the configuration directory exists */ async ensureConfigDirectory() { const configDir = path.dirname(this.configPath); await fs.ensureDir(configDir); } /** * Load configuration from file */ async loadConfig() { try { if (await fs.pathExists(this.configPath)) { const fileContent = await fs.readFile(this.configPath, 'utf-8'); let loadedConfig; // Support both JSON and YAML formats if (this.configPath.endsWith('.yaml') || this.configPath.endsWith('.yml')) { loadedConfig = yaml.parse(fileContent); } else { loadedConfig = JSON.parse(fileContent); } // Merge with default config this.config = this.mergeConfig(this.defaultConfig, loadedConfig); this.logger.debug(`Configuration loaded from ${this.configPath}`); } else { // Create default config file await this.saveConfig(); this.logger.info(`Created default configuration at ${this.configPath}`); } } catch (error) { this.logger.warn(`Failed to load config from ${this.configPath}, using defaults:`, error); this.config = { ...this.defaultConfig }; } } /** * Save configuration to file */ async saveConfig() { try { await this.ensureConfigDirectory(); let content; if (this.configPath.endsWith('.yaml') || this.configPath.endsWith('.yml')) { content = yaml.stringify(this.config, { indent: 2 }); } else { content = JSON.stringify(this.config, null, 2); } await fs.writeFile(this.configPath, content, 'utf-8'); this.logger.debug(`Configuration saved to ${this.configPath}`); } catch (error) { this.logger.error('Failed to save configuration:', error); throw error; } } /** * Deep merge two configuration objects */ mergeConfig(defaultConfig, userConfig) { const merged = { ...defaultConfig }; for (const [key, value] of Object.entries(userConfig)) { if (value !== null && typeof value === 'object' && !Array.isArray(value)) { merged[key] = { ...merged[key], ...value }; } else { merged[key] = value; } } return merged; } /** * Get the current configuration */ getConfig() { return { ...this.config }; } /** * Get a specific configuration value */ get(path, defaultValue) { const keys = path.split('.'); let current = this.config; for (const key of keys) { if (current && typeof current === 'object' && key in current) { current = current[key]; } else { return defaultValue; } } return current; } /** * Set a configuration value */ async set(path, value) { const keys = path.split('.'); let current = this.config; for (let i = 0; i < keys.length - 1; i++) { const key = keys[i]; if (!(key in current) || typeof current[key] !== 'object') { current[key] = {}; } current = current[key]; } const lastKey = keys[keys.length - 1]; current[lastKey] = value; await this.saveConfig(); this.logger.debug(`Configuration updated: ${path} = ${JSON.stringify(value)}`); } /** * Interactive configuration editor */ async editConfig() { try { const questions = [ { type: 'input', name: 'revitApiUrl', message: 'Revit API URL:', default: this.config.revit?.apiUrl || '' }, { type: 'number', name: 'revitTimeout', message: 'Revit API Timeout (ms):', default: this.config.revit?.timeout || 30000 }, { type: 'number', name: 'revitRetryAttempts', message: 'Revit API Retry Attempts:', default: this.config.revit?.retries || 3 }, { type: 'list', name: 'loggingLevel', message: 'Logging Level:', choices: ['debug', 'info', 'warn', 'error'], default: this.config.logging?.level || 'info' }, { type: 'input', name: 'loggingFile', message: 'Log File Path (optional):', default: this.config.logging?.file || '' } ]; const answers = await inquirer_1.default.prompt(questions); // Update configuration if (this.config.revit) { this.config.revit.apiUrl = answers.revitApiUrl; this.config.revit.timeout = answers.revitTimeout; this.config.revit.retries = answers.revitRetryAttempts; } if (this.config.logging) { this.config.logging.level = answers.loggingLevel; if (answers.loggingFile) { this.config.logging.file = answers.loggingFile; } } await this.saveConfig(); console.log('Configuration updated successfully!'); } catch (error) { this.logger.error('Failed to edit configuration:', error); throw error; } } /** * Set custom configuration file path */ setConfigPath(configPath) { this.configPath = path.resolve(configPath); this.logger.debug(`Configuration path set to: ${this.configPath}`); } /** * Reset configuration to defaults */ async resetToDefaults() { this.config = { ...this.defaultConfig }; await this.saveConfig(); this.logger.info('Configuration reset to defaults'); } /** * Interactive configuration editing */ async editInteractive() { const inquirer = await Promise.resolve().then(() => __importStar(require('inquirer'))); const questions = [ { type: 'input', name: 'revitApiUrl', message: 'Revit API URL:', default: this.config.revit?.apiUrl || '' }, { type: 'number', name: 'revitTimeout', message: 'Revit API Timeout (ms):', default: this.config.revit?.timeout || 30000 }, { type: 'number', name: 'revitRetryAttempts', message: 'Revit API Retry Attempts:', default: this.config.revit?.retries || 3 }, { type: 'list', name: 'loggingLevel', message: 'Logging Level:', choices: ['debug', 'info', 'warn', 'error'], default: this.config.logging?.level || 'info' }, { type: 'input', name: 'loggingFile', message: 'Log File Path (optional):', default: this.config.logging?.file || '' } ]; const answers = await inquirer.default.prompt(questions); // Update configuration if (this.config.revit) { this.config.revit.apiUrl = answers.revitApiUrl; this.config.revit.timeout = answers.revitTimeout; this.config.revit.retries = answers.revitRetryAttempts; } if (this.config.logging) { this.config.logging.level = answers.loggingLevel; if (answers.loggingFile) { this.config.logging.file = answers.loggingFile; } } await this.saveConfig(); console.log('Configuration updated successfully!'); } /** * Validate configuration */ validateConfig() { const errors = []; // Validate Revit configuration if (!this.config.revit?.apiUrl) { errors.push('Revit API URL is required'); } if (this.config.revit?.timeout && this.config.revit.timeout < 1000) { errors.push('Revit API timeout must be at least 1000ms'); } if (this.config.revit?.retries && this.config.revit.retries < 0) { errors.push('Revit API retry attempts must be non-negative'); } // Validate logging configuration const validLogLevels = ['debug', 'info', 'warn', 'error']; if (this.config.logging?.level && !validLogLevels.includes(this.config.logging.level)) { errors.push(`Invalid logging level: ${this.config.logging.level}`); } return { isValid: errors.length === 0, errors }; } /** * Get tool-specific configuration */ getToolConfig(toolName) { return this.config.tools?.[toolName] || {}; } /** * Set tool-specific configuration */ async setToolConfig(toolName, config) { if (!this.config.tools) { this.config.tools = {}; } this.config.tools[toolName] = config; await this.saveConfig(); } } exports.ConfigManager = ConfigManager; //# sourceMappingURL=config-manager.js.map