mirror of
https://github.com/tiennm99/ccs.git
synced 2026-07-18 06:17:13 +00:00
- extract create, list, show, remove, default command handlers - extract types.ts with CommandContext and parseArgs - slim auth-commands.ts from 725 to 235 lines (68% reduction) - add barrel exports at commands/index.ts and auth/index.ts
139 lines
4.2 KiB
TypeScript
139 lines
4.2 KiB
TypeScript
/**
|
|
* List Command Handler
|
|
*
|
|
* Lists all saved profiles from both legacy and unified config.
|
|
*/
|
|
|
|
import { ProfileMetadata } from '../../types';
|
|
import { initUI, header, color, dim, warn, table } from '../../utils/ui';
|
|
import { exitWithError } from '../../errors';
|
|
import { ExitCode } from '../../errors/exit-codes';
|
|
import { CommandContext, ListOutput, parseArgs, formatRelativeTime } from './types';
|
|
|
|
/**
|
|
* Handle the list command
|
|
*/
|
|
export async function handleList(ctx: CommandContext, args: string[]): Promise<void> {
|
|
await initUI();
|
|
const { verbose, json } = parseArgs(args);
|
|
|
|
try {
|
|
// Get profiles from both legacy (profiles.json) and unified config (config.yaml)
|
|
const legacyProfiles = ctx.registry.getAllProfiles();
|
|
const unifiedAccounts = ctx.registry.getAllAccountsUnified();
|
|
|
|
// Merge profiles: unified config takes precedence
|
|
const profiles: Record<string, ProfileMetadata> = { ...legacyProfiles };
|
|
for (const [name, account] of Object.entries(unifiedAccounts)) {
|
|
profiles[name] = {
|
|
type: 'account',
|
|
created: account.created,
|
|
last_used: account.last_used,
|
|
};
|
|
}
|
|
|
|
const defaultProfile = ctx.registry.getDefaultUnified() ?? ctx.registry.getDefaultProfile();
|
|
const profileNames = Object.keys(profiles);
|
|
|
|
// JSON output mode
|
|
if (json) {
|
|
const output: ListOutput = {
|
|
version: ctx.version,
|
|
profiles: profileNames.map((name) => {
|
|
const profile = profiles[name];
|
|
const isDefault = name === defaultProfile;
|
|
const instancePath = ctx.instanceMgr.getInstancePath(name);
|
|
|
|
return {
|
|
name: name,
|
|
type: profile.type || 'account',
|
|
is_default: isDefault,
|
|
created: profile.created,
|
|
last_used: profile.last_used || null,
|
|
instance_path: instancePath,
|
|
};
|
|
}),
|
|
};
|
|
console.log(JSON.stringify(output, null, 2));
|
|
return;
|
|
}
|
|
|
|
// Human-readable output
|
|
if (profileNames.length === 0) {
|
|
console.log(warn('No account profiles found'));
|
|
console.log('');
|
|
console.log('To create your first profile:');
|
|
console.log(` ${color('ccs auth create <profile>', 'command')}`);
|
|
console.log('');
|
|
console.log('Example:');
|
|
console.log(` ${color('ccs auth create work', 'command')}`);
|
|
console.log('');
|
|
return;
|
|
}
|
|
|
|
console.log(header('Saved Account Profiles'));
|
|
console.log('');
|
|
|
|
// Sort by last_used (descending), then alphabetically
|
|
const sorted = profileNames.sort((a, b) => {
|
|
const aProfile = profiles[a];
|
|
const bProfile = profiles[b];
|
|
|
|
// Default first
|
|
if (a === defaultProfile) return -1;
|
|
if (b === defaultProfile) return 1;
|
|
|
|
// Then by last_used
|
|
if (aProfile.last_used && bProfile.last_used) {
|
|
return new Date(bProfile.last_used).getTime() - new Date(aProfile.last_used).getTime();
|
|
}
|
|
if (aProfile.last_used) return -1;
|
|
if (bProfile.last_used) return 1;
|
|
|
|
// Then alphabetically
|
|
return a.localeCompare(b);
|
|
});
|
|
|
|
// Build table rows
|
|
const rows: string[][] = sorted.map((name) => {
|
|
const profile = profiles[name];
|
|
const isDefault = name === defaultProfile;
|
|
|
|
// Status column
|
|
const status = isDefault ? color('[OK] default', 'success') : color('[OK]', 'success');
|
|
|
|
// Last used column
|
|
let lastUsed = '-';
|
|
if (profile.last_used) {
|
|
lastUsed = formatRelativeTime(new Date(profile.last_used));
|
|
}
|
|
|
|
const row = [color(name, isDefault ? 'primary' : 'info'), profile.type || 'account', status];
|
|
|
|
if (verbose) {
|
|
row.push(lastUsed);
|
|
}
|
|
|
|
return row;
|
|
});
|
|
|
|
// Headers
|
|
const headers = verbose
|
|
? ['Profile', 'Type', 'Status', 'Last Used']
|
|
: ['Profile', 'Type', 'Status'];
|
|
|
|
// Print table
|
|
console.log(
|
|
table(rows, {
|
|
head: headers,
|
|
colWidths: verbose ? [15, 12, 15, 12] : [15, 12, 15],
|
|
})
|
|
);
|
|
console.log('');
|
|
console.log(dim(`Total: ${profileNames.length} profile(s)`));
|
|
console.log('');
|
|
} catch (error) {
|
|
exitWithError(`Failed to list profiles: ${(error as Error).message}`, ExitCode.GENERAL_ERROR);
|
|
}
|
|
}
|