agentic-qe
Version:
Agentic Quality Engineering Fleet System - AI-driven quality management platform
263 lines • 9.48 kB
JavaScript
;
/**
* Config - Configuration management for the AQE Fleet
*
* Handles loading and validation of fleet configuration from multiple sources
* including environment variables, config files, and defaults.
*/
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 (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__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.Config = void 0;
const fs_1 = require("fs");
const path_1 = require("path");
const yaml_1 = __importDefault(require("yaml"));
const dotenv_1 = __importDefault(require("dotenv"));
class Config {
constructor(config) {
this.config = config;
}
/**
* Load configuration from multiple sources
*/
static async load(configPath) {
// Load environment variables
dotenv_1.default.config();
// Default configuration
const defaultConfig = {
fleet: {
id: process.env.FLEET_ID || 'default-fleet',
name: process.env.FLEET_NAME || 'AQE Fleet',
maxAgents: parseInt(process.env.MAX_AGENTS || '10'),
heartbeatInterval: parseInt(process.env.HEARTBEAT_INTERVAL || '30000'),
taskTimeout: parseInt(process.env.TASK_TIMEOUT || '300000')
},
agents: [
{
type: 'test-executor',
count: parseInt(process.env.TEST_EXECUTOR_COUNT || '2'),
config: {}
},
{
type: 'quality-analyzer',
count: parseInt(process.env.QUALITY_ANALYZER_COUNT || '2'),
config: {}
},
{
type: 'performance-monitor',
count: parseInt(process.env.PERFORMANCE_MONITOR_COUNT || '1'),
config: {}
}
],
database: {
type: process.env.DB_TYPE || 'sqlite',
host: process.env.DB_HOST || 'localhost',
port: parseInt(process.env.DB_PORT || '5432'),
database: process.env.DB_NAME || 'agentic_qe',
username: process.env.DB_USER,
password: process.env.DB_PASSWORD,
filename: process.env.DB_FILENAME || './data/fleet.db'
},
logging: {
level: process.env.LOG_LEVEL || 'info',
format: process.env.LOG_FORMAT || 'json',
outputs: (process.env.LOG_OUTPUTS || 'console,file').split(',')
},
api: {
port: parseInt(process.env.API_PORT || '3000'),
host: process.env.API_HOST || '0.0.0.0',
cors: process.env.API_CORS === 'true',
rateLimit: {
windowMs: parseInt(process.env.RATE_LIMIT_WINDOW || '900000'), // 15 minutes
max: parseInt(process.env.RATE_LIMIT_MAX || '100')
}
},
security: {
apiKey: process.env.API_KEY,
jwtSecret: process.env.JWT_SECRET,
encryption: {
algorithm: process.env.ENCRYPTION_ALGORITHM || 'aes-256-gcm',
keyLength: parseInt(process.env.ENCRYPTION_KEY_LENGTH || '32')
}
}
};
// Load from config file if provided or exists
let fileConfig = {};
const configFilePath = configPath ||
process.env.CONFIG_FILE ||
(0, path_1.join)(process.cwd(), 'config', 'fleet.yaml');
if ((0, fs_1.existsSync)(configFilePath)) {
try {
const configFileContent = (0, fs_1.readFileSync)(configFilePath, 'utf8');
if (configFilePath.endsWith('.yaml') || configFilePath.endsWith('.yml')) {
fileConfig = yaml_1.default.parse(configFileContent);
}
else if (configFilePath.endsWith('.json')) {
fileConfig = JSON.parse(configFileContent);
}
}
catch (error) {
console.warn(`Failed to load config file ${configFilePath}:`, error);
}
}
// Merge configurations (file config overrides defaults, env vars override both)
const mergedConfig = Config.mergeConfigs(defaultConfig, fileConfig);
// Validate configuration
Config.validateConfig(mergedConfig);
// Create singleton instance
Config.instance = new Config(mergedConfig);
return mergedConfig;
}
/**
* Get configuration instance
*/
static getInstance() {
if (!Config.instance) {
throw new Error('Config not loaded. Call Config.load() first.');
}
return Config.instance;
}
/**
* Get full configuration
*/
getConfig() {
return this.config;
}
/**
* Get fleet configuration
*/
getFleetConfig() {
return this.config.fleet;
}
/**
* Get agents configuration
*/
getAgentsConfig() {
return this.config.agents;
}
/**
* Get database configuration
*/
getDatabaseConfig() {
return this.config.database;
}
/**
* Get logging configuration
*/
getLoggingConfig() {
return this.config.logging;
}
/**
* Get API configuration
*/
getApiConfig() {
return this.config.api;
}
/**
* Get security configuration
*/
getSecurityConfig() {
return this.config.security;
}
/**
* Deep merge configurations
*/
static mergeConfigs(base, override) {
const merged = { ...base };
if (override.fleet) {
merged.fleet = { ...merged.fleet, ...override.fleet };
}
if (override.agents) {
merged.agents = override.agents;
}
if (override.database) {
merged.database = { ...merged.database, ...override.database };
}
if (override.logging) {
merged.logging = { ...merged.logging, ...override.logging };
}
if (override.api) {
merged.api = { ...merged.api, ...override.api };
if (override.api.rateLimit) {
merged.api.rateLimit = { ...merged.api.rateLimit, ...override.api.rateLimit };
}
}
if (override.security) {
merged.security = { ...merged.security, ...override.security };
if (override.security.encryption) {
merged.security.encryption = { ...merged.security.encryption, ...override.security.encryption };
}
}
return merged;
}
/**
* Save configuration to file
*/
static async save(config, filePath) {
const fs = await Promise.resolve().then(() => __importStar(require('fs-extra')));
await fs.ensureDir(require('path').dirname(filePath));
await fs.writeJson(filePath, config, { spaces: 2 });
}
/**
* Validate configuration
*/
static validateConfig(config) {
// Validate fleet config
if (!config.fleet.id) {
throw new Error('Fleet ID is required');
}
if (config.fleet.maxAgents <= 0) {
throw new Error('Max agents must be greater than 0');
}
// Validate agents config
if (!Array.isArray(config.agents) || config.agents.length === 0) {
throw new Error('At least one agent configuration is required');
}
for (const agent of config.agents) {
if (!agent.type) {
throw new Error('Agent type is required');
}
if (agent.count <= 0) {
throw new Error('Agent count must be greater than 0');
}
}
// Validate database config
if (!config.database.database) {
throw new Error('Database name is required');
}
if (config.database.type === 'sqlite' && !config.database.filename) {
throw new Error('SQLite filename is required');
}
// Validate API config
if (config.api.port <= 0 || config.api.port > 65535) {
throw new Error('API port must be between 1 and 65535');
}
}
}
exports.Config = Config;
Config.instance = null;
//# sourceMappingURL=Config.js.map