feat: add type safety to AniList fetching methods

This commit is contained in:
2025-12-06 08:09:58 -05:00
parent 9b5cc7ea62
commit cc4f518de7

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";
@@ -35,11 +36,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) {
@@ -75,7 +76,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;
@@ -91,7 +92,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(
@@ -114,7 +115,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,
@@ -133,11 +134,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(
@@ -158,7 +155,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.
@@ -179,7 +176,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(
@@ -199,7 +196,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(
@@ -216,7 +213,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;
@@ -230,7 +227,7 @@ export class AnilistDurableObject extends DurableObject {
);
}
async getUserProfile(token: string): Promise<any> {
async getUserProfile(token: string) {
const data = await this.fetchFromAnilist(
GetUserProfileQuery,
{ token },
@@ -243,7 +240,7 @@ export class AnilistDurableObject extends DurableObject {
titleId: number,
episodeNumber: number,
token: string,
): Promise<any> {
) {
const data = await this.fetchFromAnilist(
MarkEpisodeAsWatchedMutation,
{ titleId, episodeNumber },
@@ -252,7 +249,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 },
@@ -289,9 +286,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);
@@ -325,11 +322,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",
};