const KEY_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/; function unquote(value: string): string { const trimmed = value.trim(); if ( (trimmed.startsWith('"') && trimmed.endsWith('"')) || (trimmed.startsWith("'") && trimmed.endsWith("'")) ) { const inner = trimmed.slice(1, -1); if (trimmed.startsWith('"')) { return inner.replace(/\\n/g, '\n').replace(/\\"/g, '"').replace(/\\\\/g, '\\'); } return inner; } return trimmed; } export function parseDotenv(content: string): { vars: Record; errors: string[]; } { const vars: Record = {}; const errors: string[] = []; const lines = content.split(/\r?\n/); lines.forEach((line, index) => { const trimmed = line.trim(); if (!trimmed || trimmed.startsWith('#')) return; const withoutExport = trimmed.startsWith('export ') ? trimmed.slice(7).trim() : trimmed; const eqIndex = withoutExport.indexOf('='); if (eqIndex === -1) { errors.push(`Line ${index + 1}: missing '='`); return; } const key = withoutExport.slice(0, eqIndex).trim(); const rawValue = withoutExport.slice(eqIndex + 1); if (!KEY_PATTERN.test(key)) { errors.push(`Line ${index + 1}: invalid key "${key}"`); return; } vars[key] = unquote(rawValue); }); return { vars, errors }; }