UNPKG

@ace-sdk/cli

Version:

ACE CLI - Command-line tool for intelligent pattern learning and playbook management

163 lines 5.71 kB
/** * Device Management Commands * * Commands for managing authorized devices. * * @package @ace-sdk/cli * @since 3.6.0 */ import chalk from 'chalk'; import * as readline from 'readline/promises'; import { stdin, stdout } from 'process'; import { globalOptions } from '../cli.js'; import { Logger } from '../services/logger.js'; import { listDevices, renameDevice, removeDevice, getDeviceLimit, getOrCreateDeviceId } from '@ace-sdk/core'; /** * Format relative time from ISO date string */ function formatRelativeTime(isoDate) { const date = new Date(isoDate); const now = new Date(); const diffMs = now.getTime() - date.getTime(); const diffMins = Math.floor(diffMs / 60000); const diffHours = Math.floor(diffMins / 60); const diffDays = Math.floor(diffHours / 24); if (diffMins < 1) return 'just now'; if (diffMins === 1) return '1 minute ago'; if (diffMins < 60) return `${diffMins} minutes ago`; if (diffHours === 1) return '1 hour ago'; if (diffHours < 24) return `${diffHours} hours ago`; if (diffDays === 1) return '1 day ago'; return `${diffDays} days ago`; } /** * Handle error with proper formatting */ function handleError(logger, error, message) { if (logger.isJson()) { logger.output({ error: error instanceof Error ? error.message : String(error) }); } else { logger.error(message, error instanceof Error ? error : String(error)); } process.exit(1); } /** * ace-cli devices list * List all authorized devices for the current user */ export async function devicesListCommand() { const logger = new Logger(globalOptions); const spinner = logger.spinner('Fetching devices...'); try { const devices = await listDevices(); const currentDeviceId = getOrCreateDeviceId(); spinner?.succeed(); if (logger.isJson()) { logger.output({ devices, current_device_id: currentDeviceId }); return; } if (devices.length === 0) { logger.info(chalk.dim('No devices found.')); return; } logger.info(chalk.bold(`\nYour Devices (${devices.length}):\n`)); for (const device of devices) { const isCurrent = device.device_id === currentDeviceId; const icon = isCurrent ? '📍' : '💻'; const name = device.device_name || chalk.dim('Unnamed device'); const currentBadge = isCurrent ? chalk.cyan(' ← this device') : ''; logger.info(` ${icon} ${chalk.bold(name)}${currentBadge}`); logger.info(` ID: ${chalk.dim(device.device_id)}`); logger.info(` Last active: ${formatRelativeTime(device.last_seen_at)}`); logger.info(` Clients: ${device.clients.length > 0 ? device.clients.join(', ') : chalk.dim('none')}`); logger.info(''); } } catch (error) { spinner?.fail(); handleError(logger, error, 'Failed to list devices'); } } /** * ace-cli devices rename <id> <name> * Rename a device for easier identification */ export async function devicesRenameCommand(deviceId, newName) { const logger = new Logger(globalOptions); const spinner = logger.spinner(`Renaming device to "${newName}"...`); try { const device = await renameDevice(deviceId, newName); spinner?.succeed(); if (logger.isJson()) { logger.output({ success: true, device }); return; } logger.success(`Device renamed to "${newName}"`); } catch (error) { spinner?.fail(); handleError(logger, error, 'Failed to rename device'); } } /** * ace-cli devices remove <id> * Remove a device and revoke all its sessions */ export async function devicesRemoveCommand(deviceId, options) { const logger = new Logger(globalOptions); try { // Confirmation unless --yes if (!options.yes && !logger.isJson()) { const rl = readline.createInterface({ input: stdin, output: stdout }); const answer = await rl.question(chalk.yellow('⚠️ This will revoke all sessions on this device. Continue? (y/N): ')); rl.close(); if (answer.toLowerCase() !== 'y' && answer.toLowerCase() !== 'yes') { logger.info(chalk.dim('Cancelled')); return; } } const spinner = logger.spinner('Removing device...'); const result = await removeDevice(deviceId); spinner?.succeed(); if (logger.isJson()) { logger.output({ success: true, revoked_count: result.revoked_count }); return; } logger.success(`Device removed. ${result.revoked_count} session(s) revoked.`); } catch (error) { handleError(logger, error, 'Failed to remove device'); } } /** * ace-cli devices limit * Show device limit information */ export async function devicesLimitCommand() { const logger = new Logger(globalOptions); const spinner = logger.spinner('Fetching device limit...'); try { const limit = await getDeviceLimit(); spinner?.succeed(); if (logger.isJson()) { logger.output(limit); return; } logger.info(chalk.bold('\nDevice Limit:')); logger.info(` Used: ${limit.current_devices} of ${limit.max_devices}`); logger.info(` Custom limit: ${limit.is_custom ? 'Yes' : 'No (default)'}`); logger.info(''); } catch (error) { spinner?.fail(); handleError(logger, error, 'Failed to get device limit'); } } //# sourceMappingURL=devices.js.map