Const
Check if a specific manga title is in cache
Force a sync of the caches
Reset all caches (both in-memory and localStorage)
Clear cache entry for a specific manga title
The manga title to clear from cache
boolean True if an entry was cleared, false if no entry was found
Clear cache entries for multiple manga titles at once
Array of manga titles to clear from cache
number Number of cache entries cleared
export const cacheDebugger = {
/**
* Get a summary of the current cache status
*/
getCacheStatus(): {
inMemoryCache: number;
localStorage: {
mangaCache: number;
searchCache: number;
};
} {
// Check in-memory cache
const inMemoryCount = Object.keys(mangaCache).length;
// Check localStorage
let storedMangaCount = 0;
let storedSearchCount = 0;
if (typeof window !== "undefined") {
try {
const mangaCacheData = localStorage.getItem("anilist_manga_cache");
if (mangaCacheData) {
const parsed = JSON.parse(mangaCacheData);
storedMangaCount = Object.keys(parsed).length;
}
const searchCacheData = localStorage.getItem("anilist_search_cache");
if (searchCacheData) {
const parsed = JSON.parse(searchCacheData);
storedSearchCount = Object.keys(parsed).length;
}
} catch (e) {
console.error("Error checking localStorage cache:", e);
}
}
return {
inMemoryCache: inMemoryCount,
localStorage: {
mangaCache: storedMangaCount,
searchCache: storedSearchCount,
},
};
},
/**
* Check if a specific manga title is in cache
*/
checkMangaInCache(title: string): {
found: boolean;
cacheKey: string;
entry?: {
mangaCount: number;
timestamp: number;
age: string;
};
} {
const cacheKey = generateCacheKey(title);
const entry = mangaCache[cacheKey];
if (!entry) {
return { found: false, cacheKey };
}
// Calculate age
const ageMs = Date.now() - entry.timestamp;
const ageMinutes = Math.floor(ageMs / 60000);
let age: string;
if (ageMinutes < 60) {
age = `${ageMinutes} minute(s)`;
} else if (ageMinutes < 1440) {
age = `${Math.floor(ageMinutes / 60)} hour(s)`;
} else {
age = `${Math.floor(ageMinutes / 1440)} day(s)`;
}
return {
found: true,
cacheKey,
entry: {
mangaCount: entry.manga.length,
timestamp: entry.timestamp,
age,
},
};
},
/**
* Force a sync of the caches
*/
forceSyncCaches(): void {
syncWithClientCache();
console.log("Cache sync forced, current status:");
console.log(this.getCacheStatus());
},
/**
* Reset all caches (both in-memory and localStorage)
*/
resetAllCaches(): void {
// Clear in-memory cache
clearMangaCache();
// Clear localStorage caches
if (typeof window !== "undefined") {
try {
localStorage.removeItem("anilist_manga_cache");
localStorage.removeItem("anilist_search_cache");
console.log("All AniList caches have been cleared");
} catch (e) {
console.error("Error clearing localStorage caches:", e);
}
}
},
/**
* Clear cache entry for a specific manga title
* @param title The manga title to clear from cache
* @returns boolean True if an entry was cleared, false if no entry was found
*/
clearCacheEntryForTitle(title: string): boolean {
// Generate cache key for the title
const mainKey = generateCacheKey(title);
let cleared = false;
// Check if we have this entry in the cache
if (mangaCache[mainKey]) {
delete mangaCache[mainKey];
cleared = true;
}
// Try alternate forms of the title (English title/native title)
// This should only match EXACT English/Native titles, not partial matches
const titleLower = title.toLowerCase().trim();
// Track entries to remove (to avoid modifying while iterating)
const keysToRemove: string[] = [];
// Look for entries that may be this exact manga but stored under a different title variant
Object.keys(mangaCache).forEach((key) => {
if (key === mainKey) return; // Skip the main key we already handled
// Check if this cache entry is for this specific manga (by exact title match)
const entries = mangaCache[key].manga;
for (const manga of entries) {
if (!manga.title) continue;
// Only compare exact matches for English/romaji titles
const romajiTitle = manga.title.romaji
? manga.title.romaji.toLowerCase().trim()
: "";
const englishTitle = manga.title.english
? manga.title.english.toLowerCase().trim()
: "";
// Only delete if it's an exact title match, not partial matches
if (
(romajiTitle && romajiTitle === titleLower) ||
(englishTitle && englishTitle === titleLower)
) {
keysToRemove.push(key);
break; // No need to check other manga in this entry
}
}
});
// Remove the entries outside the loop to avoid concurrent modification
if (keysToRemove.length > 0) {
keysToRemove.forEach((key) => {
delete mangaCache[key];
});
cleared = true;
}
// Save the updated cache if we cleared anything
if (cleared) {
saveCache();
}
return cleared;
},
/**
* Clear cache entries for multiple manga titles at once
* @param titles Array of manga titles to clear from cache
* @returns number Number of cache entries cleared
*/
clearCacheForTitles(titles: string[]): number {
if (!titles || titles.length === 0) return 0;
console.log(`Clearing cache for ${titles.length} manga titles...`);
let entriesCleared = 0;
let notFoundCount = 0;
// Process all titles in a batch
titles.forEach((title) => {
if (this.clearCacheEntryForTitle(title)) {
entriesCleared++;
} else {
notFoundCount++;
}
});
console.log(
`Cleared ${entriesCleared} cache entries (${notFoundCount} titles had no existing cache entries)`,
);
return entriesCleared;
},
clearAllCaches() {
// Clear in-memory cache
Object.keys(mangaCache).forEach((key) => {
delete mangaCache[key];
});
// Clear localStorage caches
try {
localStorage.removeItem("anilist_manga_cache");
localStorage.removeItem("anilist_search_cache");
console.log("All AniList caches cleared successfully");
} catch (e) {
console.error("Error clearing localStorage caches:", e);
}
return this.getCacheStatus();
},
printCacheKeysFor(title: string) {
const key = generateCacheKey(title);
console.log(`Cache key for "${title}": ${key}`);
// Check if we have a cache entry for this title
if (mangaCache[key]) {
console.log(
`Found in-memory cache entry for "${title}" with ${mangaCache[key].manga.length} results`,
);
} else {
console.log(`No in-memory cache entry found for "${title}"`);
}
return key;
},
dumpCache() {
return {
...mangaCache,
};
},
};
Debug and troubleshoot the cache status. Exposes functions to check and diagnose cache issues.