mirror of
https://github.com/tiennm99/ccs.git
synced 2026-07-16 02:11:28 +00:00
Issue #1161. Sweeps 127 files to import from src/config/config-loader-facade.ts instead of unified-config-loader or utils/config-manager directly. WRITE callers (32 files): replaced raw saveUnifiedConfig / mutateUnifiedConfig / updateUnifiedConfig calls with the facade's cache-coherent wrappers saveConfig / mutateConfig / updateConfig. This fixes a latent stale-cache window where direct writes through the underlying loader bypassed the facade's memoization. READ callers (95 files): mechanical import-path migration only — function names unchanged because the facade re-exports them. No behavior change. Also updated: - tests/unit/utils/browser/browser-setup.test.ts (DI interface rename) - src/management/checks/image-analysis-check.ts (dynamic import rename) - src/web-server/health-service.ts (dynamic require rename) - src/ccs.ts (path prefix fix from sweep script) After sweep: zero raw write callers remain outside src/config/. Direct imports of config-manager remain only for symbols not in the facade (getConfigPath, getCcsDirSource, etc). Behavior unchanged; full suite passes 1824/1824. Out of scope: switching loadOrCreateUnifiedConfig() callers to getCachedConfig() — needs per-callsite cache-safety analysis. Tracked as follow-up. Refs #1161
88 lines
2.8 KiB
TypeScript
88 lines
2.8 KiB
TypeScript
/**
|
|
* Remove Command Handler
|
|
*
|
|
* Removes a saved profile and its instance directory.
|
|
*/
|
|
|
|
import * as fs from 'fs';
|
|
import * as path from 'path';
|
|
import { initUI, color, ok, fail, info } from '../../utils/ui';
|
|
import { InteractivePrompt } from '../../utils/prompt';
|
|
|
|
import { exitWithError } from '../../errors';
|
|
import { ExitCode } from '../../errors/exit-codes';
|
|
import { CommandContext, parseArgs } from './types';
|
|
import { isUnifiedMode } from '../../config/config-loader-facade';
|
|
|
|
/**
|
|
* Handle the remove command
|
|
*/
|
|
export async function handleRemove(ctx: CommandContext, args: string[]): Promise<void> {
|
|
await initUI();
|
|
const { profileName, yes } = parseArgs(args);
|
|
|
|
if (!profileName) {
|
|
console.log(fail('Profile name is required'));
|
|
console.log('');
|
|
console.log(`Usage: ${color('ccs auth remove <profile> [--yes]', 'command')}`);
|
|
exitWithError('Profile name is required', ExitCode.PROFILE_ERROR);
|
|
}
|
|
|
|
// Check existence in both legacy and unified
|
|
const existsLegacy = ctx.registry.hasProfile(profileName);
|
|
const existsUnified = ctx.registry.hasAccountUnified(profileName);
|
|
|
|
if (!existsLegacy && !existsUnified) {
|
|
console.log(fail(`Profile not found: ${profileName}`));
|
|
exitWithError(`Profile not found: ${profileName}`, ExitCode.PROFILE_ERROR);
|
|
}
|
|
|
|
try {
|
|
// Get instance path and session count for impact display
|
|
const instancePath = ctx.instanceMgr.getInstancePath(profileName);
|
|
let sessionCount = 0;
|
|
|
|
try {
|
|
const sessionsDir = path.join(instancePath, 'session-env');
|
|
if (fs.existsSync(sessionsDir)) {
|
|
const files = fs.readdirSync(sessionsDir);
|
|
sessionCount = files.filter((f) => f.endsWith('.json')).length;
|
|
}
|
|
} catch (_e) {
|
|
// Ignore errors counting sessions
|
|
}
|
|
|
|
// Display impact
|
|
console.log('');
|
|
console.log(`Profile '${color(profileName, 'command')}' will be permanently deleted.`);
|
|
console.log(` Instance path: ${instancePath}`);
|
|
console.log(` Sessions: ${sessionCount} conversation${sessionCount !== 1 ? 's' : ''}`);
|
|
console.log('');
|
|
|
|
// Interactive confirmation (or --yes flag)
|
|
const confirmed =
|
|
yes || (await InteractivePrompt.confirm('Delete this profile?', { default: false })); // Default to NO (safe)
|
|
|
|
if (!confirmed) {
|
|
console.log(info('Cancelled'));
|
|
process.exit(0);
|
|
}
|
|
|
|
// Delete instance
|
|
await ctx.instanceMgr.deleteInstance(profileName);
|
|
|
|
// Delete profile from appropriate config
|
|
if (isUnifiedMode() && existsUnified) {
|
|
ctx.registry.removeAccountUnified(profileName);
|
|
}
|
|
if (existsLegacy) {
|
|
ctx.registry.deleteProfile(profileName);
|
|
}
|
|
|
|
console.log(ok(`Profile removed: ${profileName}`));
|
|
console.log('');
|
|
} catch (error) {
|
|
exitWithError(`Failed to remove profile: ${(error as Error).message}`, ExitCode.GENERAL_ERROR);
|
|
}
|
|
}
|