Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/just-cameron/tangled-cli. Automation-first CLI for Tangled.org
Something went wrong. Try again.
6.1 kB · 204 lines
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205import { mkdir, readFile, unlink, writeFile } from 'node:fs/promises';import { homedir } from 'node:os';import { dirname, join } from 'node:path';import { Command } from 'commander';import { simpleGit } from 'simple-git';import { type TangledConfig, loadConfig } from '../lib/config.js';
/** * Get Git root directory */async function getGitRoot(cwd: string = process.cwd()): Promise<string | null> { try { const git = simpleGit(cwd); const isRepo = await git.checkIsRepo(); if (!isRepo) { return null; } const root = await git.revparse(['--show-toplevel']); return root.trim(); } catch { return null; }}
/** * Set a config value */async function setConfigValue(key: string, value: string, global: boolean): Promise<void> { const configPath = global ? join(homedir(), '.tangledrc') : join((await getGitRoot()) || process.cwd(), '.tangledrc');
if (!global) { const gitRoot = await getGitRoot(); if (!gitRoot) { throw new Error('Not in a Git repository. Use --global or run from a Git repository.'); } }
// Load existing config let config: TangledConfig = {}; try { const content = await readFile(configPath, 'utf-8'); config = JSON.parse(content); } catch { // Config doesn't exist yet, start with empty object }
// Set the value config[key as keyof TangledConfig] = value as never;
// Write updated config await mkdir(dirname(configPath), { recursive: true }); await writeFile(configPath, `${JSON.stringify(config, null, 2)}\n`, 'utf-8');}
/** * Unset a config value */async function unsetConfigValue(key: string, global: boolean): Promise<void> { const configPath = global ? join(homedir(), '.tangledrc') : join((await getGitRoot()) || process.cwd(), '.tangledrc');
if (!global) { const gitRoot = await getGitRoot(); if (!gitRoot) { throw new Error('Not in a Git repository. Use --global or run from a Git repository.'); } }
// Load existing config let config: TangledConfig = {}; try { const content = await readFile(configPath, 'utf-8'); config = JSON.parse(content); } catch { // Config doesn't exist, nothing to unset return; }
// Remove the key delete config[key as keyof TangledConfig];
// If config is now empty, delete the file if (Object.keys(config).length === 0) { try { await unlink(configPath); } catch { // File might not exist } } else { // Write updated config await writeFile(configPath, `${JSON.stringify(config, null, 2)}\n`, 'utf-8'); }}
/** * Available configuration keys with their descriptions */const AVAILABLE_KEYS: Record<string, string> = { remote: 'Default Git remote to use when multiple tangled.org remotes exist',};
/** * Create the config command for managing Tangled CLI configuration */export function createConfigCommand(): Command { const config = new Command('config'); config.description('Manage Tangled CLI configuration');
// List available config keys config .command('list') .description('List all available configuration keys') .action(async () => { try { const cfg = await loadConfig();
console.log('Available configuration keys:\n'); for (const [key, description] of Object.entries(AVAILABLE_KEYS)) { const value = cfg[key as keyof TangledConfig]; const status = value ? `"${value}"` : '(not set)'; console.log(` ${key}`); console.log(` ${description}`); console.log(` Current value: ${status}\n`); } } catch (error) { console.error( `Failed to list config: ${error instanceof Error ? error.message : 'Unknown error'}` ); process.exit(1); } });
// Get current config config .command('get [key]') .description('Get configuration value (defaults to all)') .action(async (key?: string) => { try { const cfg = await loadConfig();
if (!key) { // Show all config values const keys = Object.keys(cfg) as Array<keyof TangledConfig>; if (keys.length === 0) { console.log('No configuration set'); return; } for (const k of keys) { console.log(`${k} = ${cfg[k] || '(not set)'}`); } } else { // Show specific key const value = cfg[key as keyof TangledConfig]; console.log(`${key} = ${value || '(not set)'}`); } } catch (error) { console.error( `Failed to get config: ${error instanceof Error ? error.message : 'Unknown error'}` ); process.exit(1); } });
// Set config value config .command('set <key> <value>') .option('-g, --global', 'Save to user config instead of local') .description('Set a configuration value') .action(async (key: string, value: string, options: { global?: boolean }) => { try { await setConfigValue(key, value, options.global ?? false); const scope = options.global ? 'user config (~/.tangledrc)' : 'local config (.tangledrc)'; console.log(`✓ Set ${key} to "${value}" in ${scope}`); } catch (error) { console.error( `Failed to set config: ${error instanceof Error ? error.message : 'Unknown error'}` ); process.exit(1); } });
// Unset config value config .command('unset <key>') .option('-g, --global', 'Clear from user config instead of local') .description('Clear a configuration value') .action(async (key: string, options: { global?: boolean }) => { try { await unsetConfigValue(key, options.global ?? false); const scope = options.global ? 'user config' : 'local config'; console.log(`✓ Cleared ${key} from ${scope}`); } catch (error) { console.error( `Failed to clear config: ${error instanceof Error ? error.message : 'Unknown error'}` ); process.exit(1); } });
return config;}