import type { Command } from 'commander'; import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'fs'; import { dirname } from 'path'; import { createInterface } from 'readline/promises'; import { parse } from 'yaml'; import { getConfigPath } from './shared.js'; import { createPrompter } from './setup/prompts.js'; import { ConfigBuilder } from './setup/config.js'; import { runFirstRunWizard, runMenu } from './setup/orchestrator.js'; import { runGoogleAuth } from './setup/automation.js'; export async function runSetup(configPath: string): Promise { const rl = createInterface({ input: process.stdin, output: process.stdout }); const p = createPrompter(rl); try { if (existsSync(configPath)) { // Existing config → menu mode const raw = readFileSync(configPath, 'utf-8'); const parsed = parse(raw) ?? {}; const builder = ConfigBuilder.fromObject(parsed); await runMenu(p, builder); saveConfig(configPath, builder, p); await runGoogleAuth(p, builder.build()); } else { // No config → first-run wizard const builder = await runFirstRunWizard(p); saveConfig(configPath, builder, p); await runGoogleAuth(p, builder.build()); const shouldStart = await p.confirm('Start Flynn now?', true); if (shouldStart) { rl.close(); const { startDaemon } = await import('../daemon/index.js'); const { loadConfig } = await import('../config/index.js'); const config = loadConfig(configPath); const daemon = await startDaemon(config); await new Promise(resolve => daemon.lifecycle.onShutdown(async () => resolve())); return; } const wantMore = await p.confirm('Configure more features?', false); if (wantMore) { const raw = readFileSync(configPath, 'utf-8'); const parsed = parse(raw) ?? {}; const menuBuilder = ConfigBuilder.fromObject(parsed); await runMenu(p, menuBuilder); saveConfig(configPath, menuBuilder, p); await runGoogleAuth(p, menuBuilder.build()); } } } finally { rl.close(); } } function saveConfig(configPath: string, builder: ConfigBuilder, p: { println(msg?: string): void }): void { const dir = dirname(configPath); mkdirSync(dir, { recursive: true }); writeFileSync(configPath, builder.toYaml(), 'utf-8'); p.println(); p.println(`✓ Config saved to ${configPath}`); } export function registerSetupCommand(program: Command): void { program .command('setup') .description('Interactive setup wizard') .option('-c, --config ', 'Config file path') .action(async (opts: { config?: string }) => { const configPath = opts.config ?? getConfigPath(); await runSetup(configPath); }); }