import color from 'kleur' import { del, get, handleError, post } from '../http' import { resolveAppName } from '../name' interface EnvVar { key: string value: string } function parseKeyValue(keyOrKeyValue: string, valueArg?: string): { key: string, value: string } | null { if (valueArg !== undefined) { const key = keyOrKeyValue.trim() if (!key) { console.error('Key cannot be empty'); return null } return { key, value: valueArg } } const eqIndex = keyOrKeyValue.indexOf('=') if (eqIndex === -1) { console.error('Invalid format. Use: KEY value or KEY=value') return null } const key = keyOrKeyValue.slice(0, eqIndex).trim() if (!key) { console.error('Key cannot be empty'); return null } return { key, value: keyOrKeyValue.slice(eqIndex + 1) } } async function globalEnvSet(keyOrKeyValue: string, valueArg?: string) { const parsed = parseKeyValue(keyOrKeyValue, valueArg) if (!parsed) return const { key, value } = parsed try { const result = await post<{ ok: boolean, error?: string }>('/api/env', { key, value }) if (result?.ok) { console.log(color.green(`Set global ${color.bold(key.toUpperCase())}`)) } else { console.error(result?.error ?? 'Failed to set variable') } } catch (error) { handleError(error) } } export async function envList(name: string | undefined, opts: { global?: boolean }) { if (opts.global) { const vars = await get('/api/env') console.log(color.bold().cyan('Global Environment Variables')) console.log() if (!vars || vars.length === 0) { console.log(color.gray(' No global environment variables set')) return } for (const v of vars) { console.log(` ${color.bold(v.key)}=${color.gray(v.value)}`) } return } const appName = resolveAppName(name) if (!appName) return const [vars, globalVars] = await Promise.all([ get(`/api/apps/${appName}/env`), get('/api/env'), ]) if (!vars) { console.error(`App not found: ${appName}`) return } console.log(color.bold().cyan(`Environment Variables for ${appName}`)) console.log() const appKeys = new Set(vars.map(v => v.key)) if (vars.length === 0 && (!globalVars || globalVars.length === 0)) { console.log(color.gray(' No environment variables set')) return } for (const v of vars) { console.log(` ${color.bold(v.key)}=${color.gray(v.value)}`) } if (globalVars && globalVars.length > 0) { const inherited = globalVars.filter(v => !appKeys.has(v.key)) if (inherited.length > 0) { if (vars.length > 0) console.log() console.log(color.gray(' Inherited from global:')) for (const v of inherited) { console.log(` ${color.bold(v.key)}=${color.gray(v.value)}`) } } } } export async function envSet(name: string | undefined, keyOrKeyValue: string, valueArg: string | undefined, opts: { global?: boolean }) { // With --global, args shift: name becomes key, key becomes value if (opts.global) { const actualKey = name ?? keyOrKeyValue const actualValue = name ? keyOrKeyValue : valueArg return globalEnvSet(actualKey, actualValue) } const parsed = parseKeyValue(keyOrKeyValue, valueArg) if (!parsed) return const { key, value } = parsed const appName = resolveAppName(name) if (!appName) return try { const result = await post<{ ok: boolean, error?: string }>(`/api/apps/${appName}/env`, { key, value }) if (result?.ok) { console.log(color.green(`Set ${color.bold(key.toUpperCase())} for ${appName}`)) console.log(color.gray('App restarted to apply changes')) } else { console.error(result?.error ?? 'Failed to set variable') } } catch (error) { handleError(error) } } export async function envRm(name: string | undefined, key: string, opts: { global?: boolean }) { // With --global, args shift: name becomes key if (opts.global) { const actualKey = name ?? key if (!actualKey) { console.error('Key is required') return } const ok = await del(`/api/env/${actualKey.toUpperCase()}`) if (ok) { console.log(color.green(`Removed global ${color.bold(actualKey.toUpperCase())}`)) } return } if (!key) { console.error('Key is required') return } const appName = resolveAppName(name) if (!appName) return const ok = await del(`/api/apps/${appName}/env/${key.toUpperCase()}`) if (ok) { console.log(color.green(`Removed ${color.bold(key.toUpperCase())} from ${appName}`)) console.log(color.gray('App restarted to apply changes')) } }