diff --git a/src/utils/update-checker.ts b/src/utils/update-checker.ts index dc3f152e..95d1076b 100644 --- a/src/utils/update-checker.ts +++ b/src/utils/update-checker.ts @@ -8,7 +8,8 @@ import * as os from 'os'; import * as https from 'https'; import { colored } from './helpers'; -const UPDATE_CHECK_FILE = path.join(os.homedir(), '.ccs', 'update-check.json'); +const CACHE_DIR = path.join(os.homedir(), '.ccs', 'cache'); +const UPDATE_CHECK_FILE = path.join(CACHE_DIR, 'update-check.json'); const CHECK_INTERVAL = 24 * 60 * 60 * 1000; // 24 hours const GITHUB_API_URL = 'https://api.github.com/repos/kaitranntt/ccs/releases/latest'; const NPM_REGISTRY_BASE = 'https://registry.npmjs.org/@kaitranntt/ccs'; @@ -208,9 +209,8 @@ export function readCache(): UpdateCache { */ export function writeCache(cache: UpdateCache): void { try { - const ccsDir = path.join(os.homedir(), '.ccs'); - if (!fs.existsSync(ccsDir)) { - fs.mkdirSync(ccsDir, { recursive: true, mode: 0o700 }); + if (!fs.existsSync(CACHE_DIR)) { + fs.mkdirSync(CACHE_DIR, { recursive: true, mode: 0o700 }); } fs.writeFileSync(UPDATE_CHECK_FILE, JSON.stringify(cache, null, 2), 'utf8'); diff --git a/src/web-server/usage-disk-cache.ts b/src/web-server/usage-disk-cache.ts index 2396c7be..c1ba8ee6 100644 --- a/src/web-server/usage-disk-cache.ts +++ b/src/web-server/usage-disk-cache.ts @@ -4,7 +4,7 @@ * Caches aggregated usage data to disk to avoid re-parsing 6000+ JSONL files * on every dashboard startup. Uses TTL-based invalidation with stale-while-revalidate. * - * Cache location: ~/.ccs/usage-cache.json + * Cache location: ~/.ccs/cache/usage.json * Default TTL: 5 minutes (configurable) */ @@ -15,7 +15,8 @@ import type { DailyUsage, MonthlyUsage, SessionUsage } from './usage-types'; // Cache configuration const CCS_DIR = path.join(os.homedir(), '.ccs'); -const CACHE_FILE = path.join(CCS_DIR, 'usage-cache.json'); +const CACHE_DIR = path.join(CCS_DIR, 'cache'); +const CACHE_FILE = path.join(CACHE_DIR, 'usage.json'); const CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes const STALE_TTL_MS = 7 * 24 * 60 * 60 * 1000; // 7 days (max age for stale data) @@ -33,11 +34,11 @@ export interface UsageDiskCache { const CACHE_VERSION = 2; /** - * Ensure ~/.ccs directory exists + * Ensure ~/.ccs/cache directory exists */ -function ensureCcsDir(): void { - if (!fs.existsSync(CCS_DIR)) { - fs.mkdirSync(CCS_DIR, { recursive: true }); +function ensureCacheDir(): void { + if (!fs.existsSync(CACHE_DIR)) { + fs.mkdirSync(CACHE_DIR, { recursive: true }); } } @@ -97,7 +98,7 @@ export function writeDiskCache( session: SessionUsage[] ): void { try { - ensureCcsDir(); + ensureCacheDir(); const cache: UsageDiskCache = { version: CACHE_VERSION, diff --git a/tests/unit/utils/update-checker-beta-channel.test.js b/tests/unit/utils/update-checker-beta-channel.test.js index c3ca8c15..f25520a9 100644 --- a/tests/unit/utils/update-checker-beta-channel.test.js +++ b/tests/unit/utils/update-checker-beta-channel.test.js @@ -275,7 +275,7 @@ describe('Beta Channel Implementation (Phase 3)', function () { latest_version: null, dismissed_version: null }; - mockFileSystem[path.join(os.homedir(), '.ccs', 'update-check.json')] = JSON.stringify(cacheData); + mockFileSystem[path.join(os.homedir(), '.ccs', 'cache', 'update-check.json')] = JSON.stringify(cacheData); }); it('should use latest tag when targetTag is "latest"', async function () { @@ -362,7 +362,7 @@ describe('Beta Channel Implementation (Phase 3)', function () { await updateCheckerModule.checkForUpdates('5.4.0', true, 'npm', 'dev'); // Check cache was updated with dev version - const cachePath = path.join(os.homedir(), '.ccs', 'update-check.json'); + const cachePath = path.join(os.homedir(), '.ccs', 'cache', 'update-check.json'); const cacheData = JSON.parse(mockFileSystem[cachePath]); assert.strictEqual(cacheData.latest_version, '5.5.0'); @@ -376,7 +376,7 @@ describe('Beta Channel Implementation (Phase 3)', function () { latest_version: '5.5.0', dismissed_version: null }; - mockFileSystem[path.join(os.homedir(), '.ccs', 'update-check.json')] = JSON.stringify(cacheData); + mockFileSystem[path.join(os.homedir(), '.ccs', 'cache', 'update-check.json')] = JSON.stringify(cacheData); // Call with force=false to use cache const result = await updateCheckerModule.checkForUpdates('5.4.0', false, 'npm', 'dev'); @@ -465,7 +465,7 @@ describe('Beta Channel Implementation (Phase 3)', function () { describe('Cache functionality', function () { it('should create cache directory if not exists', async function () { // Ensure no cache exists - const cacheDir = path.join(os.homedir(), '.ccs'); + const cacheDir = path.join(os.homedir(), '.ccs', 'cache'); delete mockFileSystem[cacheDir]; await updateCheckerModule.checkForUpdates('5.4.0', true, 'npm', 'latest'); @@ -481,7 +481,7 @@ describe('Beta Channel Implementation (Phase 3)', function () { latest_version: '5.5.0', dismissed_version: '5.5.0' }; - mockFileSystem[path.join(os.homedir(), '.ccs', 'update-check.json')] = JSON.stringify(cacheData); + mockFileSystem[path.join(os.homedir(), '.ccs', 'cache', 'update-check.json')] = JSON.stringify(cacheData); const result = await updateCheckerModule.checkForUpdates('5.4.1', false, 'npm', 'dev'); @@ -492,7 +492,7 @@ describe('Beta Channel Implementation (Phase 3)', function () { it('should handle corrupted cache gracefully', async function () { // Set up corrupted cache - mockFileSystem[path.join(os.homedir(), '.ccs', 'update-check.json')] = 'invalid json'; + mockFileSystem[path.join(os.homedir(), '.ccs', 'cache', 'update-check.json')] = 'invalid json'; // Should not throw error const result = await updateCheckerModule.checkForUpdates('5.4.0', true, 'npm', 'latest');