Files
flynn/src/cli/shared.ts
T

67 lines
2.1 KiB
TypeScript

import { loadConfig } from '../config/index.js';
import type { Config } from '../config/index.js';
import { resolve } from 'path';
import { homedir } from 'os';
/** Get the config file path from env or default location. */
export function getConfigPath(): string {
return process.env.FLYNN_CONFIG ?? resolve(homedir(), '.config/flynn/config.yaml');
}
/** Get the data directory path. */
export function getDataDir(): string {
return resolve(homedir(), '.local/share/flynn');
}
/** Load config without throwing. Returns { config } or { error }. */
export function loadConfigSafe(configPath?: string): { config?: Config; error?: string } {
const path = configPath ?? getConfigPath();
try {
const config = loadConfig(path);
return { config };
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
return { error: `Failed to load config from ${path}: ${message}` };
}
}
/** Deep-clone config and replace sensitive fields with '***'. */
export function redactSecrets(config: Record<string, unknown>): Record<string, unknown> {
const sensitiveKeys = ['bot_token', 'api_key', 'auth_token'];
function redact(obj: unknown): unknown {
if (obj === null || obj === undefined) return obj;
if (Array.isArray(obj)) return obj.map(redact);
if (typeof obj === 'object') {
const result: Record<string, unknown> = {};
for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {
if (sensitiveKeys.includes(key) && typeof value === 'string') {
result[key] = '***';
} else {
result[key] = redact(value);
}
}
return result;
}
return obj;
}
return redact(config) as Record<string, unknown>;
}
/** Format output for terminal display. */
export function formatStatus(
status: 'pass' | 'fail' | 'warn' | 'skip',
label: string,
detail?: string,
): string {
const icons: Record<string, string> = {
pass: '\x1b[32m[PASS]\x1b[0m',
fail: '\x1b[31m[FAIL]\x1b[0m',
warn: '\x1b[33m[WARN]\x1b[0m',
skip: '\x1b[2m[SKIP]\x1b[0m',
};
const suffix = detail ? ` ${detail}` : '';
return `${icons[status]} ${label}${suffix}`;
}