feat: add type safety to AniList fetching methods

This commit is contained in:
2025-12-06 08:09:58 -05:00
parent 3508f3461b
commit c35e18218a

View File

@@ -1,3 +1,4 @@
import type { TypedDocumentNode } from "@graphql-typed-document-node/core";
import { DurableObject } from "cloudflare:workers";
import { type ResultOf } from "gql.tada";
import { print } from "graphql";
@@ -34,11 +35,11 @@ export class AnilistDurableObject extends DurableObject {
super(state, env);
this.state = state;
}
async fetch(request: Request): Promise<Response> {
async fetch(request: Request) {
return new Response("Not found", { status: 404 });
}
async getTitle(id: number, token?: string): Promise<any> {
async getTitle(id: number, token?: string) {
const storageKey = id.toString();
const cache = await this.state.storage.get(storageKey);
if (cache) {
@@ -71,7 +72,7 @@ export class AnilistDurableObject extends DurableObject {
return media;
}
async getNextEpisodeAiringAt(id: number): Promise<any> {
async getNextEpisodeAiringAt(id: number) {
const storageKey = `next_airing:${id}`;
const TTL = 60 * 60 * 1000;
@@ -87,7 +88,7 @@ export class AnilistDurableObject extends DurableObject {
);
}
async search(query: string, page: number, limit: number): Promise<any> {
async search(query: string, page: number, limit: number) {
const storageKey = `search:${JSON.stringify({ query, page, limit })}`;
const TTL = 60 * 60 * 1000;
return this.handleCachedRequest(
@@ -110,7 +111,7 @@ export class AnilistDurableObject extends DurableObject {
nextSeason: any,
nextYear: number,
limit: number,
): Promise<any> {
) {
// No caching for browse popular as it returns a Response object in the original code?
// Wait, the original code had caching logic but it was commented out or mixed?
// The original code returned a Response directly for BrowsePopular without caching in the switch case,
@@ -129,11 +130,7 @@ export class AnilistDurableObject extends DurableObject {
});
}
async nextSeasonPopular(
nextSeason: any,
nextYear: number,
limit: number,
): Promise<any> {
async nextSeasonPopular(nextSeason: any, nextYear: number, limit: number) {
const storageKey = `next_season:${JSON.stringify({ nextSeason, nextYear, limit })}`;
const TTL = 60 * 60 * 1000;
return this.handleCachedRequest(
@@ -154,7 +151,7 @@ export class AnilistDurableObject extends DurableObject {
limit: number,
season: any,
seasonYear: number,
): Promise<any> {
) {
// The original code had unreachable cache logic.
// I will implement it with caching if possible, but let's follow the pattern.
// Actually, let's enable caching as it seems intended.
@@ -175,7 +172,7 @@ export class AnilistDurableObject extends DurableObject {
);
}
async getTrendingTitles(page: number, limit: number): Promise<any> {
async getTrendingTitles(page: number, limit: number) {
const storageKey = `trending:${JSON.stringify({ page, limit })}`;
const TTL = 60 * 60 * 1000;
return this.handleCachedRequest(
@@ -195,7 +192,7 @@ export class AnilistDurableObject extends DurableObject {
page: number,
airingAtLowerBound: number,
airingAtUpperBound: number,
): Promise<any> {
) {
const storageKey = `upcoming:${JSON.stringify({ page, airingAtLowerBound, airingAtUpperBound })}`;
const TTL = 60 * 60 * 1000;
return this.handleCachedRequest(
@@ -212,7 +209,7 @@ export class AnilistDurableObject extends DurableObject {
);
}
async getUser(token: string): Promise<any> {
async getUser(token: string) {
const storageKey = `user:${token}`;
// 1 month
const TTL = 60 * 60 * 24 * 30 * 1000;
@@ -226,7 +223,7 @@ export class AnilistDurableObject extends DurableObject {
);
}
async getUserProfile(token: string): Promise<any> {
async getUserProfile(token: string) {
const data = await this.fetchFromAnilist(
GetUserProfileQuery,
{ token },
@@ -239,7 +236,7 @@ export class AnilistDurableObject extends DurableObject {
titleId: number,
episodeNumber: number,
token: string,
): Promise<any> {
) {
const data = await this.fetchFromAnilist(
MarkEpisodeAsWatchedMutation,
{ titleId, episodeNumber },
@@ -248,7 +245,7 @@ export class AnilistDurableObject extends DurableObject {
return data?.SaveMediaListEntry;
}
async markTitleAsWatched(titleId: number, token: string): Promise<any> {
async markTitleAsWatched(titleId: number, token: string) {
const data = await this.fetchFromAnilist(
MarkTitleAsWatchedMutation,
{ titleId },
@@ -258,9 +255,9 @@ export class AnilistDurableObject extends DurableObject {
}
// Helper to handle caching logic
async handleCachedRequest(
async handleCachedRequest<T>(
key: string,
fetcher: () => Promise<any>,
fetcher: () => Promise<T>,
ttl?: number,
) {
const cache = await this.state.storage.get(key);
@@ -294,11 +291,11 @@ export class AnilistDurableObject extends DurableObject {
}
}
async fetchFromAnilist(
query: any,
variables: any,
async fetchFromAnilist<Result = any, Variables = any>(
query: TypedDocumentNode<Result, Variables>,
variables: Variables,
token?: string | undefined,
): Promise<any> {
): Promise<Result> {
const headers: any = {
"Content-Type": "application/json",
};