Search query.
Page number.
Results per page.
Optional
token: stringOptional access token.
Optional
bypassCache: booleanOptional parameter to bypass cache.
Promise resolving to search results.
export async function searchManga(
search: string,
page: number = 1,
perPage: number = 50,
token?: string,
bypassCache?: boolean,
): Promise<SearchResult<AniListManga>> {
// We'll still use cache in the renderer process to minimize IPC calls
const cacheKey = generateCacheKey(search, page, perPage);
// Check if we should bypass the cache
if (!bypassCache && isCacheValid(searchCache, cacheKey)) {
console.log(`📋 Using cached search results for: "${search}"`);
return searchCache[cacheKey].data;
}
if (bypassCache) {
console.log(
`🚨 FORCE SEARCH: Bypassing cache for "${search}" in client.searchManga - will make API request`,
);
}
console.log(`🔍 Searching for manga: "${search}" (page ${page})`);
try {
// Updated type parameter to correctly handle potential nested data structure
const response = await request<{
data?: { Page: SearchResult<AniListManga>["Page"] };
Page?: SearchResult<AniListManga>["Page"];
}>(SEARCH_MANGA, { search, page, perPage }, token, undefined, bypassCache);
console.log("Query:", SEARCH_MANGA);
console.log("Variables:", { search, page, perPage, bypassCache });
console.log("🔍 searchManga response:", response);
// Validate the response structure before using it
if (!response || !response.data) {
console.error(
`Invalid API response when searching for "${search}":`,
response,
);
throw new Error(`Invalid API response: missing data property`);
}
// Check if the API response has a nested data object (response.data.data structure)
const responseData = response.data.data
? response.data.data
: response.data;
if (!responseData.Page) {
console.error(
`Invalid API response when searching for "${search}": missing Page property`,
responseData,
);
throw new Error(`Invalid API response: missing Page property`);
}
const result = { Page: responseData.Page };
// Ensure media array exists (even if empty)
if (!result.Page.media) {
result.Page.media = [];
}
// Log the number of results found
console.log(
`🔍 Found ${result.Page.media.length} manga for "${search}" (page ${page}/${result.Page.pageInfo?.lastPage || 1})`,
);
// Cache the results locally if not bypassing cache
if (!bypassCache) {
searchCache[cacheKey] = {
data: result,
timestamp: Date.now(),
};
// Persist the updated cache
persistSearchCache();
console.log(
`💾 Cached ${result.Page.media.length} results for "${search}"`,
);
} else {
console.log(
`🚨 FORCE SEARCH: Not caching results for "${search}" as bypassCache=true`,
);
}
// Signal to other components that a new search result is available
try {
// Notify any listeners that we have new search results
const event = new CustomEvent("anilist:search-results-updated", {
detail: {
search,
results: result.Page.media || [],
timestamp: Date.now(),
},
});
window.dispatchEvent(event);
} catch (e) {
console.error("Failed to dispatch search results event:", e);
}
return result;
} catch (error) {
console.error(`Error searching for manga: ${search}`, error);
// Return a valid but empty result to prevent crashing
const emptyResult: SearchResult<AniListManga> = {
Page: {
pageInfo: {
total: 0,
currentPage: page,
lastPage: 1,
hasNextPage: false,
perPage,
},
media: [],
},
};
return emptyResult;
}
}
Search for manga on AniList.