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
JavaScript
"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;