import { Command } from 'commander'; import chalk from 'chalk'; import ora from 'ora'; import * as readline from 'readline'; import { Writable } from 'node:stream'; import { login, logout, whoami } from '../sdk/auth.js'; import type { Environment } from '../sdk/types.js'; import { printError, printSuccess, printJson } from './utils/output.js'; function prompt(question: string): Promise { const rl = readline.createInterface({ input: process.stdin, output: process.stdout, }); return new Promise((resolve) => { rl.question(question, (answer) => { rl.close(); resolve(answer.trim()); }); }); } function promptPassword(question: string): Promise { return new Promise((resolve) => { const mutedOutput = new Writable({ write(_chunk, _encoding, callback) { callback(); }, }); const rl = readline.createInterface({ input: process.stdin, output: mutedOutput, terminal: true, }); process.stdout.write(question); rl.question('', (answer) => { process.stdout.write('\n'); rl.close(); resolve(answer); }); }); } export function registerAuthCommands(program: Command): void { program .command('login') .description('Authenticate with Indemn platform') .option('--env ', 'Target environment') .action(async (options) => { try { const env = (options.env || process.env.INDEMN_ENV || 'dev') as Environment; if (env !== 'dev' && env !== 'production') { printError('Environment must be "dev" or "production"'); process.exit(1); } const email = await prompt('Email: '); if (!email) { printError('Email is required'); process.exit(1); } const password = await promptPassword('Password: '); if (!password) { printError('Password is required'); process.exit(1); } const spinner = ora('Authenticating...').start(); try { const result = await login(email, password, env, { mfaCodePrompt: async () => { spinner.stop(); console.log(chalk.yellow('MFA code sent to your email.')); const code = await prompt('MFA Code: '); if (!code) { throw new Error('MFA code is required'); } spinner.start('Verifying MFA code...'); return code; }, }); spinner.succeed('Authenticated successfully'); console.log(chalk.dim(` Org: ${result.orgId}`)); console.log(chalk.dim(` Environment: ${result.environment}`)); console.log(chalk.dim(` API Key: ${result.apiKey.substring(0, 12)}...`)); } catch (err) { spinner.fail('Authentication failed'); if (err instanceof Error) { printError(err.message); } else { printError(err); } process.exit(1); } } catch (err) { printError(err); process.exit(1); } }); program .command('logout') .description('Clear stored credentials') .action(() => { try { logout(); printSuccess('Logged out successfully. Credentials cleared.'); } catch (err) { printError(err); process.exit(1); } }); program .command('whoami') .description('Display current user and environment info') .option('--json', 'Output as JSON') .action((options) => { try { const info = whoami(); if (!info) { printError('Not authenticated. Run `indemn login` first.'); process.exit(1); } if (options.json) { printJson(info); return; } console.log(chalk.bold('Current Authentication')); console.log(` API Key: ${info.apiKey}`); console.log(` Org ID: ${info.orgId}`); console.log(` User ID: ${info.userId}`); console.log(` Environment: ${info.environment}`); console.log(` Copilot: ${info.hosts.copilot}`); console.log(` Evaluations: ${info.hosts.evaluations}`); console.log(` Middleware: ${info.hosts.middleware}`); } catch (err) { printError(err); process.exit(1); } }); }