diff --git a/src/core/parser.ts b/src/core/parser.ts new file mode 100644 index 0000000..e4b73fe --- /dev/null +++ b/src/core/parser.ts @@ -0,0 +1,68 @@ +import * as dotenv from 'dotenv'; +import * as fs from 'fs'; +import * as path from 'path'; +import { ParsedEnv } from './types'; + +export function parseEnvFile(envPath: string): ParsedEnv { + if (!fs.existsSync(envPath)) { + throw new Error(`Environment file not found: ${envPath}`); + } + + const content = fs.readFileSync(envPath, 'utf-8'); + const parsed = dotenv.parse(content); + + const flat: Record = {}; + const nested: Record = {}; + + for (const [key, value] of Object.entries(parsed)) { + flat[key] = value; + setNestedValue(nested, key, value); + } + + return { flat, nested }; +} + +function setNestedValue(obj: Record, key: string, value: string): void { + const parts = key.split('_'); + let current = obj; + + for (let i = 0; i < parts.length - 1; i++) { + const part = parts[i]; + if (!(part in current)) { + current[part] = {}; + } + current = current[part] as Record; + } + + current[parts[parts.length - 1]] = value; +} + +export function parseNestedValue(obj: Record, key: string): unknown { + const parts = key.split('_'); + let current: unknown = obj; + + for (const part of parts) { + if (current === null || current === undefined) { + return undefined; + } + current = (current as Record)[part]; + } + + return current; +} + +export function findEnvFiles(dir: string): string[] { + const results: string[] = []; + const entries = fs.readdirSync(dir, { withFileTypes: true }); + + for (const entry of entries) { + const fullPath = path.join(dir, entry.name); + if (entry.isFile() && entry.name === '.env') { + results.push(fullPath); + } else if (entry.isDirectory() && !entry.name.startsWith('.') && !entry.name.startsWith('node_modules')) { + results.push(...findEnvFiles(fullPath)); + } + } + + return results; +}