UNPKG

hikma-engine

Version:

Code Knowledge Graph Indexer - A sophisticated TypeScript-based indexer that transforms Git repositories into multi-dimensional knowledge stores for AI agents

335 lines (334 loc) 15.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.apiConfig = void 0; const zod_1 = require("zod"); // Configuration schema for validation const ApiConfigSchema = zod_1.z.object({ server: zod_1.z.object({ port: zod_1.z.number().min(1000).max(65535).default(3000), host: zod_1.z.string().default('localhost'), timeout: zod_1.z.number().min(1000).max(300000).default(30000), // 30 seconds maxRequestSize: zod_1.z.string().default('10mb'), }), cors: zod_1.z.object({ enabled: zod_1.z.boolean().default(true), origins: zod_1.z.array(zod_1.z.string()).default(['*']), credentials: zod_1.z.boolean().default(false), methods: zod_1.z.array(zod_1.z.string()).default(['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS']), }), rateLimit: zod_1.z.object({ enabled: zod_1.z.boolean().default(true), windowMs: zod_1.z.number().min(1000).default(60000), // 1 minute maxRequests: zod_1.z.number().min(1).default(100), skipSuccessfulRequests: zod_1.z.boolean().default(false), skipFailedRequests: zod_1.z.boolean().default(false), }), cache: zod_1.z.object({ enabled: zod_1.z.boolean().default(true), ttl: zod_1.z.object({ semantic: zod_1.z.number().min(60).default(900), // 15 minutes structural: zod_1.z.number().min(60).default(1800), // 30 minutes git: zod_1.z.number().min(60).default(3600), // 60 minutes hybrid: zod_1.z.number().min(60).default(900), // 15 minutes comprehensive: zod_1.z.number().min(60).default(1200), // 20 minutes }), maxSize: zod_1.z.number().min(100).default(1000), }), search: zod_1.z.object({ limits: zod_1.z.object({ maxResults: zod_1.z.number().min(1).max(1000).default(100), defaultResults: zod_1.z.number().min(1).max(100).default(10), maxQueryLength: zod_1.z.number().min(10).max(2000).default(500), }), thresholds: zod_1.z.object({ minSimilarity: zod_1.z.number().min(0).max(1).default(0.1), maxSimilarity: zod_1.z.number().min(0).max(1).default(1.0), relevanceThreshold: zod_1.z.number().min(0).max(1).default(0.3), }), filters: zod_1.z.object({ allowedFileTypes: zod_1.z.array(zod_1.z.string()).default([ '.ts', '.js', '.tsx', '.jsx', '.py', '.java', '.go', '.cpp', '.c', '.h', '.cs', '.php', '.rb', '.rs', '.kt', '.swift', '.scala', '.clj', '.hs' ]), excludedDirectories: zod_1.z.array(zod_1.z.string()).default([ 'node_modules', 'dist', 'build', '.git', '.vscode', '.idea', 'coverage', 'tmp', 'temp', 'logs' ]), maxFileSize: zod_1.z.number().min(1024).default(1048576), // 1MB }), enhancement: zod_1.z.object({ syntaxHighlighting: zod_1.z.boolean().default(true), relatedFiles: zod_1.z.boolean().default(true), breadcrumbs: zod_1.z.boolean().default(true), relevanceExplanation: zod_1.z.boolean().default(true), maxContextLines: zod_1.z.number().min(0).max(20).default(5), }), }), monitoring: zod_1.z.object({ enabled: zod_1.z.boolean().default(true), healthCheck: zod_1.z.object({ enabled: zod_1.z.boolean().default(true), interval: zod_1.z.number().min(1000).default(30000), // 30 seconds timeout: zod_1.z.number().min(1000).default(5000), // 5 seconds }), metrics: zod_1.z.object({ enabled: zod_1.z.boolean().default(true), collectInterval: zod_1.z.number().min(1000).default(10000), // 10 seconds retentionPeriod: zod_1.z.number().min(3600).default(86400), // 24 hours }), alerts: zod_1.z.object({ enabled: zod_1.z.boolean().default(true), errorRateThreshold: zod_1.z.number().min(0).max(1).default(0.1), // 10% responseTimeThreshold: zod_1.z.number().min(100).default(5000), // 5 seconds cooldownPeriod: zod_1.z.number().min(60).default(300), // 5 minutes }), }), security: zod_1.z.object({ apiKey: zod_1.z.object({ enabled: zod_1.z.boolean().default(false), header: zod_1.z.string().default('X-API-Key'), keys: zod_1.z.array(zod_1.z.string()).default([]), }), jwt: zod_1.z.object({ enabled: zod_1.z.boolean().default(false), secret: zod_1.z.string().optional(), expiresIn: zod_1.z.string().default('1h'), algorithm: zod_1.z.string().default('HS256'), }), headers: zod_1.z.object({ contentSecurityPolicy: zod_1.z.boolean().default(true), xFrameOptions: zod_1.z.boolean().default(true), xContentTypeOptions: zod_1.z.boolean().default(true), referrerPolicy: zod_1.z.boolean().default(true), }), }), logging: zod_1.z.object({ level: zod_1.z.enum(['debug', 'info', 'warn', 'error']).default('info'), format: zod_1.z.enum(['json', 'text']).default('json'), includeRequestId: zod_1.z.boolean().default(true), includeTimestamp: zod_1.z.boolean().default(true), logRequests: zod_1.z.boolean().default(true), logResponses: zod_1.z.boolean().default(false), }), }); class ApiConfigService { constructor() { this.config = this.loadConfiguration(); } static getInstance() { if (!ApiConfigService.instance) { ApiConfigService.instance = new ApiConfigService(); } return ApiConfigService.instance; } loadConfiguration() { const envConfig = { server: { port: this.getEnvNumber('HIKMA_API_PORT', 3000), host: this.getEnvString('HIKMA_API_HOST', 'localhost'), timeout: this.getEnvNumber('HIKMA_API_TIMEOUT', 30000), maxRequestSize: this.getEnvString('HIKMA_API_MAX_REQUEST_SIZE', '10mb'), }, cors: { enabled: this.getEnvBoolean('HIKMA_API_CORS_ENABLED', true), origins: this.getEnvArray('HIKMA_API_CORS_ORIGINS', ['*']), credentials: this.getEnvBoolean('HIKMA_API_CORS_CREDENTIALS', false), methods: this.getEnvArray('HIKMA_API_CORS_METHODS', ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS']), }, rateLimit: { enabled: this.getEnvBoolean('HIKMA_API_RATE_LIMIT_ENABLED', true), windowMs: this.getEnvNumber('HIKMA_API_RATE_LIMIT_WINDOW_MS', 60000), maxRequests: this.getEnvNumber('HIKMA_API_RATE_LIMIT_MAX_REQUESTS', 100), skipSuccessfulRequests: this.getEnvBoolean('HIKMA_API_RATE_LIMIT_SKIP_SUCCESS', false), skipFailedRequests: this.getEnvBoolean('HIKMA_API_RATE_LIMIT_SKIP_FAILED', false), }, cache: { enabled: this.getEnvBoolean('HIKMA_API_CACHE_ENABLED', true), ttl: { semantic: this.getEnvNumber('HIKMA_API_CACHE_TTL_SEMANTIC', 900), structural: this.getEnvNumber('HIKMA_API_CACHE_TTL_STRUCTURAL', 1800), git: this.getEnvNumber('HIKMA_API_CACHE_TTL_GIT', 3600), hybrid: this.getEnvNumber('HIKMA_API_CACHE_TTL_HYBRID', 900), comprehensive: this.getEnvNumber('HIKMA_API_CACHE_TTL_COMPREHENSIVE', 1200), }, maxSize: this.getEnvNumber('HIKMA_API_CACHE_MAX_SIZE', 1000), }, search: { limits: { maxResults: this.getEnvNumber('HIKMA_API_SEARCH_MAX_RESULTS', 100), defaultResults: this.getEnvNumber('HIKMA_API_SEARCH_DEFAULT_RESULTS', 10), maxQueryLength: this.getEnvNumber('HIKMA_API_SEARCH_MAX_QUERY_LENGTH', 500), }, thresholds: { minSimilarity: this.getEnvNumber('HIKMA_API_SEARCH_MIN_SIMILARITY', 0.1), maxSimilarity: this.getEnvNumber('HIKMA_API_SEARCH_MAX_SIMILARITY', 1.0), relevanceThreshold: this.getEnvNumber('HIKMA_API_SEARCH_RELEVANCE_THRESHOLD', 0.3), }, filters: { allowedFileTypes: this.getEnvArray('HIKMA_API_SEARCH_ALLOWED_FILE_TYPES', [ '.ts', '.js', '.tsx', '.jsx', '.py', '.java', '.go', '.cpp', '.c', '.h', '.cs', '.php', '.rb', '.rs', '.kt', '.swift', '.scala', '.clj', '.hs' ]), excludedDirectories: this.getEnvArray('HIKMA_API_SEARCH_EXCLUDED_DIRECTORIES', [ 'node_modules', 'dist', 'build', '.git', '.vscode', '.idea', 'coverage', 'tmp', 'temp', 'logs' ]), maxFileSize: this.getEnvNumber('HIKMA_API_SEARCH_MAX_FILE_SIZE', 1048576), }, enhancement: { syntaxHighlighting: this.getEnvBoolean('HIKMA_API_SEARCH_SYNTAX_HIGHLIGHTING', true), relatedFiles: this.getEnvBoolean('HIKMA_API_SEARCH_RELATED_FILES', true), breadcrumbs: this.getEnvBoolean('HIKMA_API_SEARCH_BREADCRUMBS', true), relevanceExplanation: this.getEnvBoolean('HIKMA_API_SEARCH_RELEVANCE_EXPLANATION', true), maxContextLines: this.getEnvNumber('HIKMA_API_SEARCH_MAX_CONTEXT_LINES', 5), }, }, monitoring: { enabled: this.getEnvBoolean('HIKMA_API_MONITORING_ENABLED', true), healthCheck: { enabled: this.getEnvBoolean('HIKMA_API_HEALTH_CHECK_ENABLED', true), interval: this.getEnvNumber('HIKMA_API_HEALTH_CHECK_INTERVAL', 30000), timeout: this.getEnvNumber('HIKMA_API_HEALTH_CHECK_TIMEOUT', 5000), }, metrics: { enabled: this.getEnvBoolean('HIKMA_API_METRICS_ENABLED', true), collectInterval: this.getEnvNumber('HIKMA_API_METRICS_COLLECT_INTERVAL', 10000), retentionPeriod: this.getEnvNumber('HIKMA_API_METRICS_RETENTION_PERIOD', 86400), }, alerts: { enabled: this.getEnvBoolean('HIKMA_API_ALERTS_ENABLED', true), errorRateThreshold: this.getEnvNumber('HIKMA_API_ALERTS_ERROR_RATE_THRESHOLD', 0.1), responseTimeThreshold: this.getEnvNumber('HIKMA_API_ALERTS_RESPONSE_TIME_THRESHOLD', 5000), cooldownPeriod: this.getEnvNumber('HIKMA_API_ALERTS_COOLDOWN_PERIOD', 300), }, }, security: { apiKey: { enabled: this.getEnvBoolean('HIKMA_API_KEY_ENABLED', false), header: this.getEnvString('HIKMA_API_KEY_HEADER', 'X-API-Key'), keys: this.getEnvArray('HIKMA_API_KEYS', []), }, jwt: { enabled: this.getEnvBoolean('HIKMA_API_JWT_ENABLED', false), secret: this.getEnvString('HIKMA_API_JWT_SECRET'), expiresIn: this.getEnvString('HIKMA_API_JWT_EXPIRES_IN', '1h'), algorithm: this.getEnvString('HIKMA_API_JWT_ALGORITHM', 'HS256'), }, headers: { contentSecurityPolicy: this.getEnvBoolean('HIKMA_API_CSP_ENABLED', true), xFrameOptions: this.getEnvBoolean('HIKMA_API_X_FRAME_OPTIONS_ENABLED', true), xContentTypeOptions: this.getEnvBoolean('HIKMA_API_X_CONTENT_TYPE_OPTIONS_ENABLED', true), referrerPolicy: this.getEnvBoolean('HIKMA_API_REFERRER_POLICY_ENABLED', true), }, }, logging: { level: this.getEnvString('HIKMA_API_LOG_LEVEL', 'info'), format: this.getEnvString('HIKMA_API_LOG_FORMAT', 'json'), includeRequestId: this.getEnvBoolean('HIKMA_API_LOG_INCLUDE_REQUEST_ID', true), includeTimestamp: this.getEnvBoolean('HIKMA_API_LOG_INCLUDE_TIMESTAMP', true), logRequests: this.getEnvBoolean('HIKMA_API_LOG_REQUESTS', true), logResponses: this.getEnvBoolean('HIKMA_API_LOG_RESPONSES', false), }, }; try { return ApiConfigSchema.parse(envConfig); } catch (error) { console.error('Configuration validation failed:', error); throw new Error('Invalid API configuration'); } } getEnvString(key, defaultValue) { const value = process.env[key]; return value !== undefined ? value : defaultValue; } getEnvNumber(key, defaultValue) { const value = process.env[key]; if (value === undefined) return defaultValue; const parsed = parseInt(value, 10); return isNaN(parsed) ? defaultValue : parsed; } getEnvBoolean(key, defaultValue) { const value = process.env[key]; if (value === undefined) return defaultValue; return value.toLowerCase() === 'true'; } getEnvArray(key, defaultValue) { const value = process.env[key]; if (value === undefined) return defaultValue; return value.split(',').map(item => item.trim()).filter(item => item.length > 0); } getConfig() { return this.config; } updateConfig(updates) { this.config = ApiConfigSchema.parse({ ...this.config, ...updates, }); } getServerConfig() { return this.config.server; } getCorsConfig() { return this.config.cors; } getRateLimitConfig() { return this.config.rateLimit; } getCacheConfig() { return this.config.cache; } getSearchConfig() { return this.config.search; } getMonitoringConfig() { return this.config.monitoring; } getSecurityConfig() { return this.config.security; } getLoggingConfig() { return this.config.logging; } validateConfiguration() { try { ApiConfigSchema.parse(this.config); return true; } catch { return false; } } getConfigSummary() { return { server: { port: this.config.server.port, host: this.config.server.host, timeout: this.config.server.timeout, }, cache: { enabled: this.config.cache.enabled, }, security: { apiKey: this.config.security.apiKey.enabled, jwt: this.config.security.jwt.enabled, }, monitoring: { enabled: this.config.monitoring.enabled, healthCheck: this.config.monitoring.healthCheck.enabled, metrics: this.config.monitoring.metrics.enabled, }, rateLimit: { enabled: this.config.rateLimit.enabled, maxRequests: this.config.rateLimit.maxRequests, windowMs: this.config.rateLimit.windowMs, }, }; } } exports.apiConfig = ApiConfigService.getInstance(); exports.default = exports.apiConfig;