UNPKG

@voilajsx/appkit

Version:

Minimal and framework agnostic Node.js toolkit designed for AI agentic backend development

107 lines 4.08 kB
/** * Smart configuration management with automatic environment variable parsing * @module @voilajsx/appkit/config * @file src/config/config.ts * * @llm-rule WHEN: Building apps that need configuration from environment variables * @llm-rule AVOID: Manual env parsing or complex config files - this handles it automatically * @llm-rule NOTE: Uses UPPER_SNAKE_CASE convention (DATABASE_HOST → config.get('database.host')) */ export class ConfigClass { _config; /** * Creates a new, immutable Config instance * @llm-rule WHEN: App startup - need to parse environment variables into structured config * @llm-rule AVOID: Calling directly - always use configClass.get() instead * @llm-rule NOTE: Config is immutable and deeply frozen for safety */ constructor(initialConfig = {}) { // Make the config object deeply immutable for safety this._config = Object.freeze(this.deepFreeze(structuredClone(initialConfig))); } /** * Gets a specific configuration value using dot notation * @llm-rule WHEN: Accessing any config value from environment variables * @llm-rule AVOID: Accessing process.env directly - use this for type safety and defaults * @llm-rule NOTE: Returns typed values (strings, numbers, booleans) automatically */ get(path, defaultValue) { if (typeof path !== 'string' || !path) { return defaultValue; } const segments = path.split('.'); let current = this._config; for (const segment of segments) { if (current && typeof current === 'object' && segment in current) { current = current[segment]; } else { return defaultValue; } } return current; } /** * Checks if a configuration path exists * @llm-rule WHEN: Need to conditionally enable features based on config presence * @llm-rule AVOID: Using get() !== undefined - this is more explicit and readable */ has(path) { return this.get(path) !== undefined; } /** * Returns the entire, immutable configuration object * @llm-rule WHEN: Debugging config or passing entire config to other modules * @llm-rule AVOID: Using in production loops - expensive operation, cache the result */ getAll() { return this._config; } /** * Gets a required configuration value (throws if missing) * @llm-rule WHEN: App startup validation for critical config values * @llm-rule AVOID: Using in request handlers - expensive error creation * @llm-rule NOTE: Use this for database URLs, API keys, and other critical settings */ getRequired(path) { const value = this.get(path); if (value === undefined) { throw new Error(`Missing required configuration: "${path}". ` + `Set environment variable: ${this.pathToEnvVar(path)}`); } return value; } /** * Gets multiple configuration values at once * @llm-rule WHEN: Need several related config values for a module * @llm-rule AVOID: Multiple get() calls when you need many values - use this for performance */ getMany(paths) { const result = {}; for (const [key, path] of Object.entries(paths)) { const value = this.get(path); if (value !== undefined) { result[key] = value; } } return result; } /** * Deep freeze helper for immutability */ deepFreeze(obj) { Object.getOwnPropertyNames(obj).forEach((prop) => { if (obj[prop] !== null && (typeof obj[prop] === 'object' || typeof obj[prop] === 'function')) { this.deepFreeze(obj[prop]); } }); return Object.freeze(obj); } /** * Converts dot notation path to environment variable name */ pathToEnvVar(path) { return path.split('.').join('_').toUpperCase(); } } //# sourceMappingURL=config.js.map