toes env -g
This commit is contained in:
parent
e8a638d11d
commit
8f37274cee
|
|
@ -7,11 +7,62 @@ interface EnvVar {
|
||||||
value: string
|
value: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function envList(name: string | undefined) {
|
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<EnvVar[]>('/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)
|
const appName = resolveAppName(name)
|
||||||
if (!appName) return
|
if (!appName) return
|
||||||
|
|
||||||
const vars = await get<EnvVar[]>(`/api/apps/${appName}/env`)
|
const [vars, globalVars] = await Promise.all([
|
||||||
|
get<EnvVar[]>(`/api/apps/${appName}/env`),
|
||||||
|
get<EnvVar[]>('/api/env'),
|
||||||
|
])
|
||||||
|
|
||||||
if (!vars) {
|
if (!vars) {
|
||||||
console.error(`App not found: ${appName}`)
|
console.error(`App not found: ${appName}`)
|
||||||
return
|
return
|
||||||
|
|
@ -20,7 +71,9 @@ export async function envList(name: string | undefined) {
|
||||||
console.log(color.bold().cyan(`Environment Variables for ${appName}`))
|
console.log(color.bold().cyan(`Environment Variables for ${appName}`))
|
||||||
console.log()
|
console.log()
|
||||||
|
|
||||||
if (vars.length === 0) {
|
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'))
|
console.log(color.gray(' No environment variables set'))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -28,31 +81,30 @@ export async function envList(name: string | undefined) {
|
||||||
for (const v of vars) {
|
for (const v of vars) {
|
||||||
console.log(` ${color.bold(v.key)}=${color.gray(v.value)}`)
|
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) {
|
export async function envSet(name: string | undefined, keyOrKeyValue: string, valueArg: string | undefined, opts: { global?: boolean }) {
|
||||||
let key: string
|
// With --global, args shift: name becomes key, key becomes value
|
||||||
let value: string
|
if (opts.global) {
|
||||||
|
const actualKey = name ?? keyOrKeyValue
|
||||||
if (valueArg !== undefined) {
|
const actualValue = name ? keyOrKeyValue : valueArg
|
||||||
// KEY value format
|
return globalEnvSet(actualKey, actualValue)
|
||||||
key = keyOrKeyValue.trim()
|
|
||||||
value = valueArg
|
|
||||||
} else {
|
|
||||||
// KEY=value format
|
|
||||||
const eqIndex = keyOrKeyValue.indexOf('=')
|
|
||||||
if (eqIndex === -1) {
|
|
||||||
console.error('Invalid format. Use: KEY value or KEY=value')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
key = keyOrKeyValue.slice(0, eqIndex).trim()
|
|
||||||
value = keyOrKeyValue.slice(eqIndex + 1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!key) {
|
const parsed = parseKeyValue(keyOrKeyValue, valueArg)
|
||||||
console.error('Key cannot be empty')
|
if (!parsed) return
|
||||||
return
|
const { key, value } = parsed
|
||||||
}
|
|
||||||
|
|
||||||
const appName = resolveAppName(name)
|
const appName = resolveAppName(name)
|
||||||
if (!appName) return
|
if (!appName) return
|
||||||
|
|
@ -70,7 +122,21 @@ export async function envSet(name: string | undefined, keyOrKeyValue: string, va
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function envRm(name: string | undefined, key: string) {
|
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) {
|
if (!key) {
|
||||||
console.error('Key is required')
|
console.error('Key is required')
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -231,6 +231,7 @@ const env = program
|
||||||
.helpGroup('Config:')
|
.helpGroup('Config:')
|
||||||
.description('Manage environment variables')
|
.description('Manage environment variables')
|
||||||
.argument('[name]', 'app name (uses current directory if omitted)')
|
.argument('[name]', 'app name (uses current directory if omitted)')
|
||||||
|
.option('-g, --global', 'manage global variables shared by all apps')
|
||||||
.action(envList)
|
.action(envList)
|
||||||
|
|
||||||
env
|
env
|
||||||
|
|
@ -239,6 +240,7 @@ env
|
||||||
.argument('[name]', 'app name (uses current directory if omitted)')
|
.argument('[name]', 'app name (uses current directory if omitted)')
|
||||||
.argument('<key>', 'variable name')
|
.argument('<key>', 'variable name')
|
||||||
.argument('[value]', 'variable value (or use KEY=value format)')
|
.argument('[value]', 'variable value (or use KEY=value format)')
|
||||||
|
.option('-g, --global', 'set a global variable shared by all apps')
|
||||||
.action(envSet)
|
.action(envSet)
|
||||||
|
|
||||||
env
|
env
|
||||||
|
|
@ -246,6 +248,7 @@ env
|
||||||
.description('Remove an environment variable')
|
.description('Remove an environment variable')
|
||||||
.argument('[name]', 'app name (uses current directory if omitted)')
|
.argument('[name]', 'app name (uses current directory if omitted)')
|
||||||
.argument('<key>', 'variable name to remove')
|
.argument('<key>', 'variable name to remove')
|
||||||
|
.option('-g, --global', 'remove a global variable')
|
||||||
.action(envRm)
|
.action(envRm)
|
||||||
|
|
||||||
program
|
program
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user