ani-client 1.8.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/index.d.mts +43 -5
- package/dist/index.d.ts +43 -5
- package/dist/index.js +75 -27
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +75 -27
- package/dist/index.mjs.map +1 -1
- package/package.json +13 -8
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/markdown.ts","../src/utils/index.ts","../src/cache/index.ts","../src/cache/redis.ts","../src/errors/index.ts","../src/queries/fragments.ts","../src/queries/media.ts","../src/queries/builders.ts","../src/queries/character.ts","../src/queries/metadata.ts","../src/queries/staff.ts","../src/queries/studio.ts","../src/queries/thread.ts","../src/queries/user.ts","../src/rate-limiter/index.ts","../src/client/character.ts","../src/types/character.ts","../src/types/lists.ts","../src/types/media.ts","../src/types/staff.ts","../src/types/studio.ts","../src/types/thread.ts","../src/types/user.ts","../src/client/media.ts","../src/client/staff.ts","../src/client/studio.ts","../src/client/thread.ts","../src/client/user.ts","../src/client/index.ts"],"names":["text","CharacterSort","CharacterRole","MediaListStatus","MediaListSort","MediaType","MediaSource","MediaFormat","MediaStatus","MediaSeason","MediaSort","AiringSort","MediaRelationType","RecommendationSort","StaffSort","StudioSort","ThreadSort","UserSort","data","query"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Parses AniList specific markdown into standard HTML.\n * Includes formatting for spoilers, images, videos (youtube/webm), headings,\n * lists, code blocks, and standard markdown elements.\n *\n * @security This function escapes HTML entities to prevent XSS attacks.\n * However, the output is still raw HTML — consumers should always use a\n * Content Security Policy and consider additional sanitization when rendering\n * user-generated content in a browser.\n *\n * @param text The AniList markdown text to parse\n * @returns The parsed HTML string\n */\n/** @internal Check that a URL uses a safe protocol (http/https). */\nfunction isSafeUrl(url: string): boolean {\n return /^https?:\\/\\//i.test(url);\n}\n\nexport function parseAniListMarkdown(text: string): string {\n if (!text) return \"\";\n\n let html = text;\n\n html = html\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n\n html = html.replace(/```([\\s\\S]*?)```/g, (_match, code: string) => {\n return `<pre><code>${code.trim()}</code></pre>`;\n });\n\n html = html.replace(/`([^`]+)`/g, \"<code>$1</code>\");\n\n html = html.replace(/~!(.*?)!~/gs, '<span class=\"anilist-spoiler\">$1</span>');\n\n html = html.replace(/~~~(.*?)~~~/gs, '<div class=\"anilist-center\">$1</div>');\n\n html = html.replace(/img(\\d+)\\((.*?)\\)/gi, (_match, width: string, url: string) =>\n isSafeUrl(url) ? `<img src=\"${url}\" width=\"${width}\" alt=\"\" class=\"anilist-image\" />` : \"\",\n );\n\n html = html.replace(/img\\((.*?)\\)/gi, (_match, url: string) =>\n isSafeUrl(url) ? `<img src=\"${url}\" alt=\"\" class=\"anilist-image\" />` : \"\",\n );\n\n html = html.replace(/youtube\\((.*?)\\)/gi, (_match, id: string) => {\n if (!/^[\\w-]+$/.test(id)) return \"\";\n return `<iframe src=\"https://www.youtube.com/embed/${id}\" frameborder=\"0\" allowfullscreen class=\"anilist-youtube\"></iframe>`;\n });\n\n html = html.replace(/webm\\((.*?)\\)/gi, (_match, url: string) =>\n isSafeUrl(url) ? `<video src=\"${url}\" controls class=\"anilist-webm\"></video>` : \"\",\n );\n\n html = html.replace(/^######\\s+(.+)$/gm, \"<h6>$1</h6>\");\n html = html.replace(/^#####\\s+(.+)$/gm, \"<h5>$1</h5>\");\n html = html.replace(/^####\\s+(.+)$/gm, \"<h4>$1</h4>\");\n html = html.replace(/^###\\s+(.+)$/gm, \"<h3>$1</h3>\");\n html = html.replace(/^##\\s+(.+)$/gm, \"<h2>$1</h2>\");\n html = html.replace(/^#\\s+(.+)$/gm, \"<h1>$1</h1>\");\n\n html = html.replace(/__(.*?)__/g, \"<strong>$1</strong>\");\n html = html.replace(/\\*\\*(.*?)\\*\\*/g, \"<strong>$1</strong>\");\n\n html = html.replace(/_(.*?)_/g, \"<em>$1</em>\");\n html = html.replace(/(?<!\\*)\\*(?!\\*)(.*?)(?<!\\*)\\*(?!\\*)/g, \"<em>$1</em>\");\n\n html = html.replace(/~~(.*?)~~/g, \"<del>$1</del>\");\n\n html = html.replace(/\\[(.*?)\\]\\((.*?)\\)/g, (_match, text: string, url: string) =>\n isSafeUrl(url) ? `<a href=\"${url}\" target=\"_blank\" rel=\"noopener noreferrer\">${text}</a>` : text,\n );\n\n html = html.replace(/\\r\\n/g, \"\\n\");\n const lines = html.split(\"\\n\");\n const processed: string[] = [];\n let listType: \"ul\" | \"ol\" | null = null;\n\n for (const line of lines) {\n const ulMatch = line.match(/^[\\s]*[-*]\\s+(.*)/);\n const olMatch = line.match(/^[\\s]*\\d+\\.\\s+(.*)/);\n\n if (ulMatch) {\n if (listType !== \"ul\") {\n if (listType) processed.push(`</${listType}>`);\n processed.push(\"<ul>\");\n listType = \"ul\";\n }\n processed.push(`<li>${ulMatch[1]}</li>`);\n } else if (olMatch) {\n if (listType !== \"ol\") {\n if (listType) processed.push(`</${listType}>`);\n processed.push(\"<ol>\");\n listType = \"ol\";\n }\n processed.push(`<li>${olMatch[1]}</li>`);\n } else {\n if (listType) {\n processed.push(`</${listType}>`);\n listType = null;\n }\n processed.push(line);\n }\n }\n if (listType) processed.push(`</${listType}>`);\n\n html = processed.join(\"\\n\");\n\n const paragraphs = html.split(/\\n{2,}/);\n html = paragraphs\n .map((p) => {\n const trimmed = p.trim();\n if (!trimmed) return \"\";\n const withBr = trimmed.replace(/\\n/g, \"<br />\");\n if (withBr.match(/^(<div|<iframe|<video|<img|<h[1-6]|<ul|<ol|<pre)/)) {\n return withBr;\n }\n return `<p>${withBr}</p>`;\n })\n .filter(Boolean)\n .join(\"\\n\");\n\n return html;\n}\n","/**\n * Utility functions for internal use.\n */\n\nconst WHITESPACE_RE = /\\s+/g;\n\n/**\n * Normalize a GraphQL query string by collapsing all whitespace.\n * Used for cache key generation and request body minification.\n *\n * @internal\n * @param query - The raw GraphQL query string\n * @returns The whitespace-normalized query\n */\nexport function normalizeQuery(query: string): string {\n return query.replace(WHITESPACE_RE, \" \").trim();\n}\n\n/**\n * Clamp a number to a maximum and minimum value.\n * Used internally to ensure perPage does not exceed AniList's limit of 50.\n *\n * @internal\n * @param value - The number to clamp\n * @returns The clamped number between 1 and 50\n */\nexport function clampPerPage(value: number): number {\n return Math.min(Math.max(value, 1), 50);\n}\n\n/**\n * Split an array into smaller chunks of a specific size.\n * Used internally for batching GraphQL queries.\n *\n * @internal\n * @param arr - The array to chunk\n * @param size - The maximum size of each chunk\n * @returns An array of chunks\n */\nexport function chunk<T>(arr: T[], size: number): T[][] {\n if (size < 1) throw new RangeError(\"chunk size must be >= 1\");\n const chunks: T[][] = [];\n for (let i = 0; i < arr.length; i += size) {\n chunks.push(arr.slice(i, i + size));\n }\n return chunks;\n}\n\n/**\n * Validate that a value is a finite positive integer (valid AniList ID).\n *\n * @internal\n * @param id - The ID to validate\n * @param label - Label for the error message (e.g. \"mediaId\")\n * @throws {RangeError} If the ID is not a finite positive integer\n */\nexport function validateId(id: number, label = \"id\"): void {\n if (!Number.isFinite(id) || !Number.isInteger(id) || id < 1) {\n throw new RangeError(`Invalid ${label}: expected a positive integer, got ${id}`);\n }\n}\n\n/**\n * Validate an array of IDs.\n *\n * @internal\n * @param ids - The IDs to validate\n * @param label - Label for the error message\n * @throws {RangeError} If any ID is not a finite positive integer\n */\nexport function validateIds(ids: number[], label = \"id\"): void {\n for (const id of ids) {\n validateId(id, label);\n }\n}\n\n/**\n * Deep-sort an object's keys recursively for deterministic JSON serialization.\n *\n * @internal\n */\nexport function sortObjectKeys(obj: unknown): unknown {\n if (obj === null || typeof obj !== \"object\") return obj;\n if (Array.isArray(obj)) return obj.map(sortObjectKeys);\n const sorted: Record<string, unknown> = {};\n for (const key of Object.keys(obj as Record<string, unknown>).sort()) {\n sorted[key] = sortObjectKeys((obj as Record<string, unknown>)[key]);\n }\n return sorted;\n}\n\nexport * from \"./markdown\";\n","import type { CacheAdapter, CacheOptions } from \"../types\";\nimport { normalizeQuery, sortObjectKeys } from \"../utils\";\n\n/**\n * Simple in-memory cache with configurable TTL, LRU eviction, and optional stale-while-revalidate.\n * Used internally by AniListClient to avoid redundant API calls.\n */\nexport type { CacheOptions };\n\n/** Cache performance statistics. */\nexport interface CacheStats {\n /** Total cache hits. */\n hits: number;\n /** Total cache misses. */\n misses: number;\n /** Stale entries returned (only with stale-while-revalidate). */\n stales: number;\n /** Hit rate as a ratio 0–1 (NaN if no requests yet). */\n hitRate: number;\n}\n\ninterface CacheEntry<T> {\n data: T;\n expiresAt: number;\n}\n\nconst ONE_DAY_MS = 24 * 60 * 60 * 1000;\n\nexport class MemoryCache implements CacheAdapter {\n private readonly ttl: number;\n private readonly maxSize: number;\n private readonly enabled: boolean;\n private readonly swrMs: number;\n private readonly store = new Map<string, CacheEntry<unknown>>();\n\n private _hits = 0;\n private _misses = 0;\n private _stales = 0;\n\n constructor(options: CacheOptions = {}) {\n this.ttl = options.ttl ?? ONE_DAY_MS;\n this.maxSize = options.maxSize ?? 500;\n this.enabled = options.enabled ?? true;\n this.swrMs = options.staleWhileRevalidateMs ?? 0;\n }\n\n /** Build a deterministic cache key from a query + variables pair. */\n static key(query: string, variables: Record<string, unknown>): string {\n const normalized = normalizeQuery(query);\n return `${normalized}|${JSON.stringify(sortObjectKeys(variables))}`;\n }\n\n /**\n * Retrieve a cached value, or `undefined` if missing / expired.\n * With stale-while-revalidate enabled, returns stale data within the grace window\n * and flags it so the caller can refresh in the background.\n */\n get<T>(key: string): T | undefined {\n if (!this.enabled) return undefined;\n const entry = this.store.get(key);\n if (!entry) {\n this._misses++;\n return undefined;\n }\n const now = Date.now();\n if (now > entry.expiresAt) {\n if (this.swrMs > 0 && now <= entry.expiresAt + this.swrMs) {\n this.store.delete(key);\n this.store.set(key, entry);\n this._stales++;\n return entry.data as T;\n }\n this.store.delete(key);\n this._misses++;\n return undefined;\n }\n this.store.delete(key);\n this.store.set(key, entry);\n this._hits++;\n return entry.data as T;\n }\n\n /** Store a value in the cache. */\n set<T>(key: string, data: T): void {\n if (!this.enabled) return;\n\n this.store.delete(key);\n\n if (this.maxSize > 0 && this.store.size >= this.maxSize) {\n const firstKey = this.store.keys().next().value;\n if (firstKey !== undefined) this.store.delete(firstKey);\n }\n\n this.store.set(key, { data, expiresAt: Date.now() + this.ttl });\n }\n\n /** Remove a specific entry. */\n delete(key: string): boolean {\n return this.store.delete(key);\n }\n\n /** Clear the entire cache and reset statistics. */\n clear(): void {\n this.store.clear();\n this._hits = 0;\n this._misses = 0;\n this._stales = 0;\n }\n\n /** Number of entries currently stored. */\n get size(): number | Promise<number> {\n return this.store.size;\n }\n\n /** Return all cache keys. */\n keys(): string[] {\n return [...this.store.keys()];\n }\n\n /**\n * Get cache performance statistics.\n *\n * @example\n * ```ts\n * const cache = new MemoryCache();\n * // ... after some usage ...\n * console.log(cache.stats);\n * // { hits: 42, misses: 8, stales: 0, hitRate: 0.84 }\n * ```\n */\n get stats(): CacheStats {\n const total = this._hits + this._misses + this._stales;\n return {\n hits: this._hits,\n misses: this._misses,\n stales: this._stales,\n hitRate: total === 0 ? Number.NaN : this._hits / total,\n };\n }\n\n /** Reset cache statistics without clearing stored data. */\n resetStats(): void {\n this._hits = 0;\n this._misses = 0;\n this._stales = 0;\n }\n\n /**\n * Remove all entries whose key matches the given pattern.\n *\n * - **String**: treated as a substring match (e.g. `\"Media\"` removes all keys containing `\"Media\"`).\n * - **RegExp**: tested against each key directly.\n *\n * @param pattern — A string (substring match) or RegExp.\n * @returns Number of entries removed.\n */\n invalidate(pattern: string | RegExp): number {\n const test =\n typeof pattern === \"string\" ? (key: string) => key.includes(pattern) : (key: string) => pattern.test(key);\n const toDelete: string[] = [];\n for (const key of this.store.keys()) {\n if (test(key)) toDelete.push(key);\n }\n for (const key of toDelete) this.store.delete(key);\n return toDelete.length;\n }\n}\n","import type { CacheAdapter } from \"../types\";\n\n/**\n * Minimal interface representing a Redis client.\n * Compatible with both `ioredis` and `redis` (node-redis v4+).\n */\nexport interface RedisLikeClient {\n get(key: string): Promise<string | null>;\n set(key: string, value: string, ...args: unknown[]): Promise<unknown>;\n del(...keys: (string | string[])[]): Promise<number>;\n keys(pattern: string): Promise<string[]>;\n /** Optional SCAN-based iteration — used when available to avoid blocking the server. */\n scanIterator?(options: { MATCH: string; COUNT?: number }): AsyncIterable<string>;\n}\n\nexport interface RedisCacheOptions {\n /** A Redis client instance (ioredis or node-redis). */\n client: RedisLikeClient;\n /** Key prefix to namespace ani-client entries (default: `\"ani:\"`) */\n prefix?: string;\n /** TTL in seconds (default: 86 400 = 24 h) */\n ttl?: number;\n}\n\n/**\n * Redis-backed cache adapter for AniListClient.\n *\n * @example\n * ```ts\n * import Redis from \"ioredis\";\n * import { AniListClient, RedisCache } from \"ani-client\";\n *\n * const redis = new Redis();\n * const client = new AniListClient({\n * cacheAdapter: new RedisCache({ client: redis }),\n * });\n * ```\n */\nexport class RedisCache implements CacheAdapter {\n private readonly client: RedisLikeClient;\n private readonly prefix: string;\n private readonly ttl: number;\n\n constructor(options: RedisCacheOptions) {\n this.client = options.client;\n this.prefix = options.prefix ?? \"ani:\";\n this.ttl = options.ttl ?? 86_400;\n }\n\n private prefixedKey(key: string): string {\n return `${this.prefix}${key}`;\n }\n\n async get<T>(key: string): Promise<T | undefined> {\n const raw = await this.client.get(this.prefixedKey(key));\n if (raw === null) return undefined;\n try {\n return JSON.parse(raw) as T;\n } catch {\n return undefined;\n }\n }\n\n async set<T>(key: string, data: T): Promise<void> {\n await this.client.set(this.prefixedKey(key), JSON.stringify(data), \"EX\", this.ttl);\n }\n\n async delete(key: string): Promise<boolean> {\n const count = await this.client.del(this.prefixedKey(key));\n return count > 0;\n }\n\n /**\n * Collect keys matching a pattern. Uses SCAN when available, falls back to KEYS.\n *\n * **Warning:** The `KEYS` fallback is O(N) and blocks the Redis server.\n * Provide a client with `scanIterator` support for production use.\n * @internal\n */\n private async collectKeys(pattern: string): Promise<string[]> {\n if (this.client.scanIterator) {\n const keys: string[] = [];\n for await (const key of this.client.scanIterator({ MATCH: pattern, COUNT: 100 })) {\n keys.push(key);\n }\n return keys;\n }\n return this.client.keys(pattern);\n }\n\n async clear(): Promise<void> {\n const keys = await this.collectKeys(`${this.prefix}*`);\n if (keys.length > 0) {\n await this.client.del(...keys);\n }\n }\n\n /**\n * Get the actual number of keys with this prefix in Redis.\n */\n get size(): Promise<number> {\n return this.getSize();\n }\n\n /** @internal */\n private async getSize(): Promise<number> {\n const keys = await this.collectKeys(`${this.prefix}*`);\n return keys.length;\n }\n\n async keys(): Promise<string[]> {\n const raw = await this.collectKeys(`${this.prefix}*`);\n return raw.map((k) => k.slice(this.prefix.length));\n }\n\n /**\n * Remove all entries whose key matches the given pattern.\n *\n * - **String**: treated as a substring match (e.g. `\"Media\"` removes all keys containing `\"Media\"`).\n * - **RegExp**: tested against each key directly.\n *\n * @param pattern — A string (substring match) or RegExp.\n * @returns Number of entries removed.\n */\n async invalidate(pattern: string | RegExp): Promise<number> {\n if (typeof pattern === \"string\") {\n const keys = await this.collectKeys(`${this.prefix}*${pattern}*`);\n if (keys.length === 0) return 0;\n return this.client.del(...keys);\n }\n\n const allKeys = await this.collectKeys(`${this.prefix}*`);\n const matching = allKeys.filter((k) => pattern.test(k.slice(this.prefix.length)));\n if (matching.length === 0) return 0;\n return this.client.del(...matching);\n }\n}\n","/**\n * Custom error class for AniList API errors.\n */\nexport class AniListError extends Error {\n /** HTTP status code returned by the API */\n public readonly status: number;\n /** Raw error body from the API response */\n public readonly errors: unknown[];\n\n constructor(message: string, status: number, errors: unknown[] = []) {\n super(message);\n this.name = \"AniListError\";\n this.status = status;\n this.errors = errors;\n Object.setPrototypeOf(this, AniListError.prototype);\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, AniListError);\n }\n }\n}\n","/**\n * Lightweight media fields — minimal payload for list/search contexts.\n * Does NOT include tags, studios, trailer, synonyms, or nextAiringEpisode.\n */\nexport const MEDIA_FIELDS_LIGHT = `\n id\n idMal\n title { romaji english native userPreferred }\n type\n format\n status\n coverImage { large medium color }\n bannerImage\n genres\n averageScore\n popularity\n favourites\n isAdult\n siteUrl\n season\n seasonYear\n episodes\n chapters\n nextAiringEpisode {\n id\n airingAt\n episode\n timeUntilAiring\n }\n`;\n\n/** Core media fields — always returned. Does NOT include relations (opt-in via include). */\nexport const MEDIA_FIELDS_BASE = `\n id\n idMal\n title { romaji english native userPreferred }\n type\n format\n status\n description(asHtml: false)\n startDate { year month day }\n endDate { year month day }\n season\n seasonYear\n episodes\n duration\n chapters\n volumes\n countryOfOrigin\n isLicensed\n source\n hashtag\n trailer { id site thumbnail }\n coverImage { extraLarge large medium color }\n bannerImage\n genres\n synonyms\n averageScore\n meanScore\n popularity\n favourites\n trending\n tags { id name description category rank isMediaSpoiler }\n studios { nodes { id name isAnimationStudio siteUrl } }\n isAdult\n siteUrl\n nextAiringEpisode {\n id\n airingAt\n episode\n mediaId\n timeUntilAiring\n }\n`;\n\nexport const RELATIONS_FIELDS = `\n relations {\n edges {\n relationType(version: 2)\n node {\n id\n title { romaji english native userPreferred }\n type\n format\n status\n coverImage { large medium }\n siteUrl\n }\n }\n }\n`;\n\n/** Full media fields with relations — used by existing queries for backward compat. */\nexport const MEDIA_FIELDS = `\n ${MEDIA_FIELDS_BASE}\n ${RELATIONS_FIELDS}\n`;\n\n/** Character fields without back-reference to media (used when embedding characters inside a Media query). */\nexport const CHARACTER_FIELDS_COMPACT = `\n id\n name { first middle last full native alternative }\n image { large medium }\n description(asHtml: false)\n gender\n dateOfBirth { year month day }\n age\n bloodType\n favourites\n siteUrl\n`;\n\nconst CHARACTER_MEDIA_NODES = `\n media(perPage: 10) {\n nodes {\n id\n title { romaji english native userPreferred }\n type\n coverImage { large medium }\n siteUrl\n }\n }\n`;\n\n/** Compact voice actor fields — lightweight subset for embedding inside character edges. */\nexport const VOICE_ACTOR_FIELDS_COMPACT = `\n id\n name { first middle last full native userPreferred }\n languageV2\n image { large medium }\n gender\n primaryOccupations\n siteUrl\n`;\n\nconst CHARACTER_MEDIA_EDGES_WITH_VA = `\n media(perPage: 10) {\n edges {\n voiceActors {\n ${VOICE_ACTOR_FIELDS_COMPACT}\n }\n node {\n id\n title { romaji english native userPreferred }\n type\n coverImage { large medium }\n siteUrl\n }\n }\n }\n`;\n\nexport const CHARACTER_FIELDS = `\n ${CHARACTER_FIELDS_COMPACT}\n ${CHARACTER_MEDIA_NODES}\n`;\n\nexport const CHARACTER_FIELDS_WITH_VA = `\n ${CHARACTER_FIELDS_COMPACT}\n ${CHARACTER_MEDIA_EDGES_WITH_VA}\n`;\n\nexport const STAFF_FIELDS = `\n id\n name { first middle last full native }\n language\n image { large medium }\n description(asHtml: false)\n primaryOccupations\n gender\n dateOfBirth { year month day }\n dateOfDeath { year month day }\n age\n yearsActive\n homeTown\n bloodType\n favourites\n siteUrl\n`;\n\nexport const STAFF_MEDIA_FIELDS = `\n staffMedia(perPage: $perPage, sort: [POPULARITY_DESC]) {\n nodes {\n id\n title { romaji english native userPreferred }\n type\n format\n status\n coverImage { extraLarge large medium color }\n bannerImage\n genres\n averageScore\n meanScore\n popularity\n favourites\n episodes\n trending\n hashtag\n season\n seasonYear\n startDate { year month day }\n endDate { year month day }\n nextAiringEpisode {\n id\n airingAt\n episode\n mediaId\n timeUntilAiring\n }\n studios {\n edges {\n node {\n name\n }\n }\n }\n siteUrl\n }\n }\n`;\n\nexport const USER_FIELDS = `\n id\n name\n about(asHtml: false)\n avatar { large medium }\n bannerImage\n isFollowing\n isFollower\n donatorTier\n donatorBadge\n createdAt\n siteUrl\n statistics {\n anime { count meanScore minutesWatched episodesWatched chaptersRead volumesRead }\n manga { count meanScore minutesWatched episodesWatched chaptersRead volumesRead }\n }\n`;\n\n/** Favorites fragment — lightweight fields for each favorite category. */\nexport const USER_FAVORITES_FIELDS = `\n favourites {\n anime(perPage: 25) {\n nodes {\n id\n title { romaji english native userPreferred }\n coverImage { large medium }\n type\n format\n siteUrl\n }\n }\n manga(perPage: 25) {\n nodes {\n id\n title { romaji english native userPreferred }\n coverImage { large medium }\n type\n format\n siteUrl\n }\n }\n characters(perPage: 25) {\n nodes {\n id\n name { full native }\n image { large medium }\n siteUrl\n }\n }\n staff(perPage: 25) {\n nodes {\n id\n name { full native }\n image { large medium }\n siteUrl\n }\n }\n studios(perPage: 25) {\n nodes {\n id\n name\n siteUrl\n }\n }\n }\n`;\n\nexport const MEDIA_LIST_FIELDS = `\n id\n mediaId\n status\n score(format: POINT_100)\n progress\n progressVolumes\n repeat\n priority\n private\n notes\n startedAt { year month day }\n completedAt { year month day }\n updatedAt\n createdAt\n media {\n ${MEDIA_FIELDS_BASE}\n }\n`;\n\nexport const STUDIO_FIELDS = `\n id\n name\n isAnimationStudio\n siteUrl\n favourites\n media(page: 1, perPage: 25, sort: POPULARITY_DESC) {\n pageInfo { total perPage currentPage lastPage hasNextPage }\n nodes {\n id\n title { romaji english native userPreferred }\n type\n format\n coverImage { large medium }\n siteUrl\n }\n }\n`;\n\nexport const THREAD_FIELDS = `\n id\n title\n body(asHtml: false)\n userId\n replyUserId\n replyCommentId\n replyCount\n viewCount\n isLocked\n isSticky\n isSubscribed\n repliedAt\n createdAt\n updatedAt\n siteUrl\n user {\n id\n name\n avatar { large medium }\n }\n replyUser {\n id\n name\n avatar { large medium }\n }\n categories {\n id\n name\n }\n mediaCategories {\n id\n title { romaji english native userPreferred }\n type\n coverImage { large medium }\n siteUrl\n }\n likes {\n id\n name\n }\n`;\n","import { MEDIA_FIELDS, MEDIA_FIELDS_BASE } from \"./fragments\";\n\nexport const QUERY_MEDIA_BY_ID = `\nquery ($id: Int!) {\n Media(id: $id) {\n ${MEDIA_FIELDS}\n }\n}`;\n\nexport const QUERY_MEDIA_SEARCH = `\nquery (\n $search: String,\n $type: MediaType,\n $format: MediaFormat,\n $status: MediaStatus,\n $season: MediaSeason,\n $seasonYear: Int,\n $genre: String,\n $tag: String,\n $genre_in: [String],\n $tag_in: [String],\n $genre_not_in: [String],\n $tag_not_in: [String],\n $isAdult: Boolean,\n $sort: [MediaSort],\n $page: Int,\n $perPage: Int\n) {\n Page(page: $page, perPage: $perPage) {\n pageInfo { total perPage currentPage lastPage hasNextPage }\n media(\n search: $search,\n type: $type,\n format: $format,\n status: $status,\n season: $season,\n seasonYear: $seasonYear,\n genre: $genre,\n tag: $tag,\n genre_in: $genre_in,\n tag_in: $tag_in,\n genre_not_in: $genre_not_in,\n tag_not_in: $tag_not_in,\n isAdult: $isAdult,\n sort: $sort\n ) {\n ${MEDIA_FIELDS_BASE}\n }\n }\n}`;\n\nexport const QUERY_TRENDING = `\nquery ($type: MediaType, $page: Int, $perPage: Int) {\n Page(page: $page, perPage: $perPage) {\n pageInfo { total perPage currentPage lastPage hasNextPage }\n media(type: $type, sort: TRENDING_DESC) {\n ${MEDIA_FIELDS_BASE}\n }\n }\n}`;\n\nexport const QUERY_AIRING_SCHEDULE = `\nquery ($airingAt_greater: Int, $airingAt_lesser: Int, $sort: [AiringSort], $page: Int, $perPage: Int) {\n Page(page: $page, perPage: $perPage) {\n pageInfo { total perPage currentPage lastPage hasNextPage }\n airingSchedules(airingAt_greater: $airingAt_greater, airingAt_lesser: $airingAt_lesser, sort: $sort) {\n id\n airingAt\n timeUntilAiring\n episode\n mediaId\n media {\n ${MEDIA_FIELDS_BASE}\n }\n }\n }\n}`;\n\nexport const QUERY_RECENT_CHAPTERS = `\nquery ($page: Int, $perPage: Int) {\n Page(page: $page, perPage: $perPage) {\n pageInfo { total perPage currentPage lastPage hasNextPage }\n media(type: MANGA, status: RELEASING, sort: UPDATED_AT_DESC) {\n ${MEDIA_FIELDS_BASE}\n }\n }\n}`;\n\nexport const QUERY_PLANNING = `\nquery ($type: MediaType, $sort: [MediaSort], $page: Int, $perPage: Int) {\n Page(page: $page, perPage: $perPage) {\n pageInfo { total perPage currentPage lastPage hasNextPage }\n media(type: $type, status: NOT_YET_RELEASED, sort: $sort) {\n ${MEDIA_FIELDS_BASE}\n }\n }\n}`;\n\nexport const QUERY_MEDIA_BY_SEASON = `\nquery ($season: MediaSeason!, $seasonYear: Int!, $type: MediaType, $sort: [MediaSort], $page: Int, $perPage: Int) {\n Page(page: $page, perPage: $perPage) {\n pageInfo { total perPage currentPage lastPage hasNextPage }\n media(season: $season, seasonYear: $seasonYear, type: $type, sort: $sort) {\n ${MEDIA_FIELDS_BASE}\n }\n }\n}`;\n\nexport const QUERY_MEDIA_BY_MAL_ID = `\nquery ($idMal: Int!, $type: MediaType) {\n Media(idMal: $idMal, type: $type) {\n ${MEDIA_FIELDS}\n }\n}`;\n\nexport const QUERY_RECOMMENDATIONS = `\nquery ($mediaId: Int!, $page: Int, $perPage: Int, $sort: [RecommendationSort]) {\n Media(id: $mediaId) {\n recommendations(page: $page, perPage: $perPage, sort: $sort) {\n pageInfo { total perPage currentPage lastPage hasNextPage }\n nodes {\n id\n rating\n userRating\n mediaRecommendation {\n id\n idMal\n title { romaji english native userPreferred }\n type\n format\n status\n coverImage { extraLarge large medium color }\n bannerImage\n genres\n averageScore\n meanScore\n popularity\n favourites\n siteUrl\n }\n user {\n id\n name\n avatar { large medium }\n }\n }\n }\n }\n}`;\n","import type { MediaIncludeOptions } from \"../types\";\nimport { clampPerPage } from \"../utils\";\nimport {\n CHARACTER_FIELDS,\n CHARACTER_FIELDS_COMPACT,\n MEDIA_FIELDS,\n MEDIA_FIELDS_BASE,\n RELATIONS_FIELDS,\n STAFF_FIELDS,\n VOICE_ACTOR_FIELDS_COMPACT,\n} from \"./fragments\";\nimport { QUERY_MEDIA_BY_ID } from \"./media\";\n\n/**\n * Build a `Media(id: $id)` query that optionally includes characters, staff,\n * relations, streaming episodes, external links, stats, and recommendations.\n *\n * When no include options are given, the query is identical to QUERY_MEDIA_BY_ID.\n *\n * @internal\n */\nexport function buildMediaByIdQuery(include?: MediaIncludeOptions): string {\n if (!include) return QUERY_MEDIA_BY_ID;\n\n const extra: string[] = [];\n\n if (include.relations !== false) {\n extra.push(RELATIONS_FIELDS);\n }\n\n if (include.characters) {\n const opts = typeof include.characters === \"object\" ? include.characters : {};\n const perPage = clampPerPage(opts.perPage ?? 25);\n const sortClause = opts.sort !== false ? \", sort: [ROLE, RELEVANCE, ID]\" : \"\";\n const voiceActorBlock = opts.voiceActors\n ? `\\n voiceActors {\n ${VOICE_ACTOR_FIELDS_COMPACT}\n }`\n : \"\";\n extra.push(`\n characters(perPage: ${perPage}${sortClause}) {\n edges {\n role\n node {\n ${CHARACTER_FIELDS_COMPACT}\n }${voiceActorBlock}\n }\n }`);\n }\n\n if (include.staff) {\n const opts = typeof include.staff === \"object\" ? include.staff : {};\n const perPage = clampPerPage(opts.perPage ?? 25);\n const sortClause = opts.sort !== false ? \", sort: [RELEVANCE, ID]\" : \"\";\n extra.push(`\n staff(perPage: ${perPage}${sortClause}) {\n edges {\n role\n node {\n ${STAFF_FIELDS}\n }\n }\n }`);\n }\n\n if (include.recommendations) {\n const perPage = clampPerPage(\n typeof include.recommendations === \"object\" ? (include.recommendations.perPage ?? 10) : 10,\n );\n extra.push(`\n recommendations(perPage: ${perPage}, sort: [RATING_DESC]) {\n nodes {\n id\n rating\n mediaRecommendation {\n id\n title { romaji english native userPreferred }\n type\n format\n coverImage { large medium }\n averageScore\n siteUrl\n }\n }\n }`);\n }\n\n if (include.streamingEpisodes) {\n extra.push(`\n streamingEpisodes {\n title\n thumbnail\n url\n site\n }`);\n }\n\n if (include.externalLinks) {\n extra.push(`\n externalLinks {\n id\n url\n site\n type\n icon\n color\n }`);\n }\n\n if (include.stats) {\n extra.push(`\n stats {\n scoreDistribution { score amount }\n statusDistribution { status amount }\n }`);\n }\n\n return `\nquery ($id: Int!) {\n Media(id: $id) {\n ${MEDIA_FIELDS_BASE}\n ${extra.join(\"\\n\")}\n }\n}`;\n}\n\n/** @internal Build a batched GraphQL query using aliases. */\nfunction buildBatchQuery(ids: number[], typeName: string, fields: string, prefix: string): string {\n const aliases = ids.map((id, i) => `${prefix}${i}: ${typeName}(id: ${id}) { ${fields} }`).join(\"\\n \");\n return `query {\\n ${aliases}\\n}`;\n}\n\nexport const buildBatchMediaQuery = (ids: number[]): string => buildBatchQuery(ids, \"Media\", MEDIA_FIELDS, \"m\");\n\nexport const buildBatchCharacterQuery = (ids: number[]): string =>\n buildBatchQuery(ids, \"Character\", CHARACTER_FIELDS, \"c\");\n\nexport const buildBatchStaffQuery = (ids: number[]): string => buildBatchQuery(ids, \"Staff\", STAFF_FIELDS, \"s\");\n","import { CHARACTER_FIELDS, CHARACTER_FIELDS_WITH_VA } from \"./fragments\";\n\nexport const QUERY_CHARACTER_BY_ID = `\nquery ($id: Int!) {\n Character(id: $id) {\n ${CHARACTER_FIELDS}\n }\n}`;\n\nexport const QUERY_CHARACTER_BY_ID_WITH_VA = `\nquery ($id: Int!) {\n Character(id: $id) {\n ${CHARACTER_FIELDS_WITH_VA}\n }\n}`;\n\nexport const QUERY_CHARACTER_SEARCH = `\nquery ($search: String, $sort: [CharacterSort], $page: Int, $perPage: Int) {\n Page(page: $page, perPage: $perPage) {\n pageInfo { total perPage currentPage lastPage hasNextPage }\n characters(search: $search, sort: $sort) {\n ${CHARACTER_FIELDS}\n }\n }\n}`;\n\nexport const QUERY_CHARACTER_SEARCH_WITH_VA = `\nquery ($search: String, $sort: [CharacterSort], $page: Int, $perPage: Int) {\n Page(page: $page, perPage: $perPage) {\n pageInfo { total perPage currentPage lastPage hasNextPage }\n characters(search: $search, sort: $sort) {\n ${CHARACTER_FIELDS_WITH_VA}\n }\n }\n}`;\n","export const QUERY_GENRES = `\nquery {\n GenreCollection\n}`;\n\nexport const QUERY_TAGS = `\nquery {\n MediaTagCollection {\n id\n name\n description\n category\n isAdult\n }\n}`;\n","import { STAFF_FIELDS, STAFF_MEDIA_FIELDS } from \"./fragments\";\n\nexport const QUERY_STAFF_BY_ID = `\nquery ($id: Int!) {\n Staff(id: $id) {\n ${STAFF_FIELDS}\n }\n}`;\n\nexport const QUERY_STAFF_BY_ID_WITH_MEDIA = `\nquery ($id: Int!, $perPage: Int) {\n Staff(id: $id) {\n ${STAFF_FIELDS}\n ${STAFF_MEDIA_FIELDS}\n }\n}`;\n\nexport const QUERY_STAFF_SEARCH = `\nquery ($search: String, $sort: [StaffSort], $page: Int, $perPage: Int) {\n Page(page: $page, perPage: $perPage) {\n pageInfo { total perPage currentPage lastPage hasNextPage }\n staff(search: $search, sort: $sort) {\n ${STAFF_FIELDS}\n }\n }\n}`;\n","import { clampPerPage } from \"../utils\";\nimport { MEDIA_FIELDS_LIGHT, STUDIO_FIELDS } from \"./fragments\";\n\nexport const QUERY_STUDIO_BY_ID = `\nquery ($id: Int!) {\n Studio(id: $id) {\n ${STUDIO_FIELDS}\n }\n}`;\n\n/**\n * Build a Studio-by-ID query with customisable media perPage.\n * @internal\n */\nexport function buildStudioByIdQuery(mediaPerPage?: number): string {\n if (mediaPerPage === undefined) return QUERY_STUDIO_BY_ID;\n const pp = clampPerPage(mediaPerPage);\n return `\nquery ($id: Int!) {\n Studio(id: $id) {\n id\n name\n isAnimationStudio\n siteUrl\n favourites\n media(page: 1, perPage: ${pp}, sort: POPULARITY_DESC) {\n pageInfo { total perPage currentPage lastPage hasNextPage }\n nodes {\n ${MEDIA_FIELDS_LIGHT}\n }\n }\n }\n}`;\n}\n\nexport const QUERY_STUDIO_SEARCH = `\nquery ($search: String, $sort: [StudioSort], $page: Int, $perPage: Int) {\n Page(page: $page, perPage: $perPage) {\n pageInfo { total perPage currentPage lastPage hasNextPage }\n studios(search: $search, sort: $sort) {\n ${STUDIO_FIELDS}\n }\n }\n}`;\n","import { THREAD_FIELDS } from \"./fragments\";\n\nexport const QUERY_THREAD_BY_ID = `\nquery ($id: Int!) {\n Thread(id: $id) {\n ${THREAD_FIELDS}\n }\n}`;\n\nexport const QUERY_THREAD_SEARCH = `\nquery ($search: String, $mediaCategoryId: Int, $categoryId: Int, $sort: [ThreadSort], $page: Int, $perPage: Int) {\n Page(page: $page, perPage: $perPage) {\n pageInfo { total perPage currentPage lastPage hasNextPage }\n threads(search: $search, mediaCategoryId: $mediaCategoryId, categoryId: $categoryId, sort: $sort) {\n ${THREAD_FIELDS}\n }\n }\n}`;\n","import { clampPerPage } from \"../utils\";\nimport { MEDIA_LIST_FIELDS, USER_FAVORITES_FIELDS, USER_FIELDS } from \"./fragments\";\n\nexport const QUERY_USER_BY_ID = `\nquery ($id: Int!) {\n User(id: $id) {\n ${USER_FIELDS}\n }\n}`;\n\nexport const QUERY_USER_BY_NAME = `\nquery ($name: String!) {\n User(name: $name) {\n ${USER_FIELDS}\n }\n}`;\n\nexport const QUERY_USER_SEARCH = `\nquery ($search: String, $sort: [UserSort], $page: Int, $perPage: Int) {\n Page(page: $page, perPage: $perPage) {\n pageInfo { total perPage currentPage lastPage hasNextPage }\n users(search: $search, sort: $sort) {\n ${USER_FIELDS}\n }\n }\n}`;\n\nexport const QUERY_USER_MEDIA_LIST = `\nquery ($userId: Int, $userName: String, $type: MediaType!, $status: MediaListStatus, $sort: [MediaListSort], $page: Int, $perPage: Int) {\n Page(page: $page, perPage: $perPage) {\n pageInfo { total perPage currentPage lastPage hasNextPage }\n mediaList(userId: $userId, userName: $userName, type: $type, status: $status, sort: $sort) {\n ${MEDIA_LIST_FIELDS}\n }\n }\n}`;\n\nexport const QUERY_USER_FAVORITES_BY_ID = `\nquery ($id: Int!) {\n User(id: $id) {\n id\n name\n ${USER_FAVORITES_FIELDS}\n }\n}`;\n\nexport const QUERY_USER_FAVORITES_BY_NAME = `\nquery ($name: String!) {\n User(name: $name) {\n id\n name\n ${USER_FAVORITES_FIELDS}\n }\n}`;\n\n/**\n * Build a User Favorites query with customisable perPage per category.\n * @internal\n */\nexport function buildUserFavoritesQuery(idOrName: \"id\" | \"name\", perPage = 25): string {\n const pp = clampPerPage(perPage);\n const varDecl = idOrName === \"id\" ? \"$id: Int!\" : \"$name: String!\";\n const selector = idOrName === \"id\" ? \"id: $id\" : \"name: $name\";\n return `\nquery (${varDecl}) {\n User(${selector}) {\n id\n name\n favourites {\n anime(perPage: ${pp}) {\n nodes {\n id\n title { romaji english native userPreferred }\n coverImage { large medium }\n type\n format\n siteUrl\n }\n }\n manga(perPage: ${pp}) {\n nodes {\n id\n title { romaji english native userPreferred }\n coverImage { large medium }\n type\n format\n siteUrl\n }\n }\n characters(perPage: ${pp}) {\n nodes {\n id\n name { full native }\n image { large medium }\n siteUrl\n }\n }\n staff(perPage: ${pp}) {\n nodes {\n id\n name { full native }\n image { large medium }\n siteUrl\n }\n }\n studios(perPage: ${pp}) {\n nodes {\n id\n name\n siteUrl\n }\n }\n }\n }\n}`;\n}\n","/**\n * Rate limiter with automatic retry for AniList API.\n *\n * AniList allows 90 requests per minute.\n * When a 429 (Too Many Requests) is received, the client\n * waits for the Retry-After header and retries automatically.\n */\n\nimport type { RateLimitOptions } from \"../types\";\nexport type { RateLimitOptions };\n\nexport class RateLimiter {\n private readonly maxRequests: number;\n private readonly windowMs: number;\n private readonly maxRetries: number;\n private readonly retryDelayMs: number;\n private readonly enabled: boolean;\n private readonly timeoutMs: number;\n private readonly retryOnNetworkError: boolean;\n private readonly retryStrategy?: (attempt: number, baseDelayMs: number) => number;\n\n /** @internal — sliding window: circular buffer of timestamps */\n private readonly timestamps: number[];\n private head = 0;\n private count = 0;\n /** @internal — active sleep timers for cleanup */\n private readonly activeTimers = new Set<ReturnType<typeof setTimeout>>();\n\n constructor(options: RateLimitOptions = {}) {\n this.maxRequests = options.maxRequests ?? 85;\n this.windowMs = options.windowMs ?? 60_000;\n this.maxRetries = options.maxRetries ?? 3;\n this.retryDelayMs = options.retryDelayMs ?? 2_000;\n this.enabled = options.enabled ?? true;\n this.timeoutMs = options.timeoutMs ?? 30_000;\n this.retryOnNetworkError = options.retryOnNetworkError ?? true;\n this.retryStrategy = options.retryStrategy;\n this.timestamps = new Array<number>(this.maxRequests).fill(0);\n }\n\n /**\n * Wait until it's safe to make a request (respects rate limit window).\n */\n async acquire(): Promise<void> {\n if (!this.enabled) return;\n\n if (this.count >= this.maxRequests) {\n const oldest = this.timestamps[this.head] as number;\n const elapsed = Date.now() - oldest;\n if (elapsed < this.windowMs) {\n const waitMs = this.windowMs - elapsed + 50;\n await this.sleep(waitMs);\n }\n }\n\n const now = Date.now();\n if (this.count < this.maxRequests) {\n this.timestamps[(this.head + this.count) % this.maxRequests] = now;\n this.count++;\n } else {\n this.timestamps[this.head] = now;\n this.head = (this.head + 1) % this.maxRequests;\n }\n }\n\n /**\n * Execute a fetch with automatic retry on 429 responses and network errors.\n * Uses exponential backoff with jitter for retry delays.\n */\n async fetchWithRetry(\n url: string,\n init: RequestInit,\n hooks?: {\n onRetry?: (attempt: number, reason: string, delayMs: number) => void;\n onRateLimit?: (retryAfterMs: number) => void;\n },\n ): Promise<Response> {\n await this.acquire();\n\n let lastResponse: Response | undefined;\n let lastError: unknown;\n\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n try {\n const res = await this.fetchWithTimeout(url, init);\n\n if (res.status !== 429) return res;\n\n lastResponse = res;\n if (attempt === this.maxRetries) break;\n\n const retryAfter = res.headers.get(\"Retry-After\");\n const delayMs = retryAfter ? Number.parseInt(retryAfter, 10) * 1000 : this.exponentialDelay(attempt);\n\n hooks?.onRateLimit?.(delayMs);\n hooks?.onRetry?.(attempt + 1, \"HTTP 429\", delayMs);\n\n await this.sleep(delayMs);\n await this.acquire();\n } catch (err) {\n lastError = err;\n\n if (this.retryOnNetworkError && isNetworkError(err) && attempt < this.maxRetries) {\n const delayMs = this.exponentialDelay(attempt);\n hooks?.onRetry?.(attempt + 1, `Network error: ${(err as Error).message}`, delayMs);\n await this.sleep(delayMs);\n await this.acquire();\n continue;\n }\n\n throw err;\n }\n }\n\n if (lastResponse) return lastResponse;\n /* v8 ignore next -- defensive fallback; unreachable in normal control flow */\n throw lastError ?? new Error(`Request failed after ${this.maxRetries} retries`);\n }\n\n /** @internal — Exponential backoff with jitter, capped at 30s (or custom strategy) */\n private exponentialDelay(attempt: number): number {\n if (this.retryStrategy) {\n return this.retryStrategy(attempt, this.retryDelayMs);\n }\n const base = this.retryDelayMs * 2 ** attempt;\n const jitter = Math.random() * 1000;\n return Math.min(base + jitter, 30_000);\n }\n\n /** @internal */\n private async fetchWithTimeout(url: string, init: RequestInit): Promise<Response> {\n if (this.timeoutMs <= 0) return fetch(url, init);\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeoutMs);\n\n const signals = [controller.signal, init.signal].filter(Boolean) as AbortSignal[];\n const combinedSignal = signals.length > 1 ? AbortSignal.any(signals) : signals[0];\n\n try {\n return await fetch(url, { ...init, signal: combinedSignal });\n } finally {\n clearTimeout(timer);\n }\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => {\n const timer = setTimeout(() => {\n this.activeTimers.delete(timer);\n resolve();\n }, ms);\n this.activeTimers.add(timer);\n });\n }\n\n /** Cancel all pending sleep timers and reset internal state. */\n dispose(): void {\n for (const timer of this.activeTimers) {\n clearTimeout(timer);\n }\n this.activeTimers.clear();\n this.head = 0;\n this.count = 0;\n this.timestamps.fill(0);\n }\n}\n\n/** Set of Node.js error codes that indicate a transient network failure. */\nconst RETRYABLE_NETWORK_CODES = new Set([\n \"ECONNRESET\",\n \"ECONNREFUSED\",\n \"ETIMEDOUT\",\n \"ENOTFOUND\",\n \"EAI_AGAIN\",\n \"UND_ERR_CONNECT_TIMEOUT\",\n \"UND_ERR_SOCKET\",\n]);\n\n/** @internal */\nfunction isNetworkError(err: unknown): boolean {\n if (err instanceof TypeError && err.message === \"fetch failed\") return true;\n const code = (err as NodeJS.ErrnoException)?.code;\n if (code && RETRYABLE_NETWORK_CODES.has(code)) return true;\n const cause = (err as { cause?: { code?: string } })?.cause?.code;\n if (cause && RETRYABLE_NETWORK_CODES.has(cause)) return true;\n return false;\n}\n","import {\n QUERY_CHARACTER_BY_ID,\n QUERY_CHARACTER_BY_ID_WITH_VA,\n QUERY_CHARACTER_SEARCH,\n QUERY_CHARACTER_SEARCH_WITH_VA,\n} from \"../queries\";\n\nimport type { Character, CharacterIncludeOptions, PagedResult, SearchCharacterOptions } from \"../types\";\n\nimport { clampPerPage, validateId } from \"../utils\";\nimport type { ClientBase } from \"./base\";\n\nexport async function getCharacter(\n client: ClientBase,\n id: number,\n include?: CharacterIncludeOptions,\n): Promise<Character> {\n validateId(id, \"characterId\");\n const query = include?.voiceActors ? QUERY_CHARACTER_BY_ID_WITH_VA : QUERY_CHARACTER_BY_ID;\n const data = await client.request<{ Character: Character }>(query, { id });\n return data.Character;\n}\n\nexport async function searchCharacters(\n client: ClientBase,\n options: SearchCharacterOptions = {},\n): Promise<PagedResult<Character>> {\n const { query: search, page = 1, perPage = 20, sort, voiceActors } = options;\n const gqlQuery = voiceActors ? QUERY_CHARACTER_SEARCH_WITH_VA : QUERY_CHARACTER_SEARCH;\n return client.pagedRequest<Character>(gqlQuery, { search, sort, page, perPage: clampPerPage(perPage) }, \"characters\");\n}\n","import type { FuzzyDate } from \"./common\";\nimport type { Media } from \"./media\";\nimport type { VoiceActor } from \"./staff\";\n\nexport enum CharacterSort {\n ID = \"ID\",\n ID_DESC = \"ID_DESC\",\n ROLE = \"ROLE\",\n ROLE_DESC = \"ROLE_DESC\",\n SEARCH_MATCH = \"SEARCH_MATCH\",\n FAVOURITES = \"FAVOURITES\",\n FAVOURITES_DESC = \"FAVOURITES_DESC\",\n}\n\nexport enum CharacterRole {\n MAIN = \"MAIN\",\n SUPPORTING = \"SUPPORTING\",\n BACKGROUND = \"BACKGROUND\",\n}\n\nexport interface CharacterName {\n first: string | null;\n middle: string | null;\n last: string | null;\n full: string | null;\n native: string | null;\n alternative: string[];\n}\n\nexport interface CharacterImage {\n large: string | null;\n medium: string | null;\n}\n\nexport type CharacterMediaNode = Pick<Media, \"id\" | \"title\" | \"type\" | \"coverImage\" | \"siteUrl\">;\n\nexport interface CharacterMediaEdge {\n node: CharacterMediaNode;\n voiceActors?: VoiceActor[];\n}\n\nexport interface Character {\n id: number;\n name: CharacterName;\n image: CharacterImage;\n description: string | null;\n gender: string | null;\n dateOfBirth: FuzzyDate | null;\n age: string | null;\n bloodType: string | null;\n favourites: number | null;\n siteUrl: string | null;\n media: {\n nodes?: CharacterMediaNode[];\n edges?: CharacterMediaEdge[];\n } | null;\n}\n\n/** Options for including extra data when fetching a character. */\nexport interface CharacterIncludeOptions {\n /** Include voice actors for each media the character appears in. */\n voiceActors?: boolean;\n}\n\nexport interface SearchCharacterOptions {\n query?: string;\n sort?: CharacterSort[];\n page?: number;\n perPage?: number;\n /** Include voice actors for each media the character appears in. */\n voiceActors?: boolean;\n}\n","import type { FuzzyDate } from \"./common\";\nimport type { Media, MediaType } from \"./media\";\n\nexport enum MediaListStatus {\n CURRENT = \"CURRENT\",\n PLANNING = \"PLANNING\",\n COMPLETED = \"COMPLETED\",\n DROPPED = \"DROPPED\",\n PAUSED = \"PAUSED\",\n REPEATING = \"REPEATING\",\n}\n\nexport enum MediaListSort {\n MEDIA_ID = \"MEDIA_ID\",\n MEDIA_ID_DESC = \"MEDIA_ID_DESC\",\n SCORE = \"SCORE\",\n SCORE_DESC = \"SCORE_DESC\",\n STATUS = \"STATUS\",\n STATUS_DESC = \"STATUS_DESC\",\n PROGRESS = \"PROGRESS\",\n PROGRESS_DESC = \"PROGRESS_DESC\",\n PROGRESS_VOLUMES = \"PROGRESS_VOLUMES\",\n PROGRESS_VOLUMES_DESC = \"PROGRESS_VOLUMES_DESC\",\n REPEAT = \"REPEAT\",\n REPEAT_DESC = \"REPEAT_DESC\",\n PRIORITY = \"PRIORITY\",\n PRIORITY_DESC = \"PRIORITY_DESC\",\n STARTED_ON = \"STARTED_ON\",\n STARTED_ON_DESC = \"STARTED_ON_DESC\",\n FINISHED_ON = \"FINISHED_ON\",\n FINISHED_ON_DESC = \"FINISHED_ON_DESC\",\n ADDED_TIME = \"ADDED_TIME\",\n ADDED_TIME_DESC = \"ADDED_TIME_DESC\",\n UPDATED_TIME = \"UPDATED_TIME\",\n UPDATED_TIME_DESC = \"UPDATED_TIME_DESC\",\n MEDIA_TITLE_ROMAJI = \"MEDIA_TITLE_ROMAJI\",\n MEDIA_TITLE_ROMAJI_DESC = \"MEDIA_TITLE_ROMAJI_DESC\",\n MEDIA_TITLE_ENGLISH = \"MEDIA_TITLE_ENGLISH\",\n MEDIA_TITLE_ENGLISH_DESC = \"MEDIA_TITLE_ENGLISH_DESC\",\n MEDIA_TITLE_NATIVE = \"MEDIA_TITLE_NATIVE\",\n MEDIA_TITLE_NATIVE_DESC = \"MEDIA_TITLE_NATIVE_DESC\",\n MEDIA_POPULARITY = \"MEDIA_POPULARITY\",\n MEDIA_POPULARITY_DESC = \"MEDIA_POPULARITY_DESC\",\n}\n\nexport interface MediaListEntry {\n id: number;\n mediaId: number;\n status: MediaListStatus;\n score: number | null;\n progress: number | null;\n progressVolumes: number | null;\n repeat: number | null;\n priority: number | null;\n private: boolean | null;\n notes: string | null;\n startedAt: FuzzyDate | null;\n completedAt: FuzzyDate | null;\n updatedAt: number | null;\n createdAt: number | null;\n media: Media;\n}\n\nexport interface GetUserMediaListOptions {\n /** User ID (provide either userId or userName) */\n userId?: number;\n /** Username (provide either userId or userName) */\n userName?: string;\n /** ANIME or MANGA */\n type: MediaType;\n /** Filter by list status (CURRENT, COMPLETED, etc.) */\n status?: MediaListStatus;\n /** Sort order */\n sort?: MediaListSort[];\n page?: number;\n perPage?: number;\n}\n","import type { Character, CharacterRole } from \"./character\";\nimport type { ExternalLink, FuzzyDate } from \"./common\";\nimport type { MediaListStatus } from \"./lists\";\nimport type { Staff, VoiceActor } from \"./staff\";\nimport type { StudioConnection } from \"./studio\";\nimport type { UserAvatar } from \"./user\";\n\nexport enum MediaType {\n ANIME = \"ANIME\",\n MANGA = \"MANGA\",\n}\n\nexport enum MediaSource {\n ORIGINAL = \"ORIGINAL\",\n MANGA = \"MANGA\",\n LIGHT_NOVEL = \"LIGHT_NOVEL\",\n VISUAL_NOVEL = \"VISUAL_NOVEL\",\n VIDEO_GAME = \"VIDEO_GAME\",\n OTHER = \"OTHER\",\n NOVEL = \"NOVEL\",\n DOUJINSHI = \"DOUJINSHI\",\n ANIME = \"ANIME\",\n WEB_NOVEL = \"WEB_NOVEL\",\n LIVE_ACTION = \"LIVE_ACTION\",\n GAME = \"GAME\",\n COMIC = \"COMIC\",\n MULTIMEDIA_PROJECT = \"MULTIMEDIA_PROJECT\",\n PICTURE_BOOK = \"PICTURE_BOOK\",\n}\n\nexport enum MediaFormat {\n TV = \"TV\",\n TV_SHORT = \"TV_SHORT\",\n MOVIE = \"MOVIE\",\n SPECIAL = \"SPECIAL\",\n OVA = \"OVA\",\n ONA = \"ONA\",\n MUSIC = \"MUSIC\",\n MANGA = \"MANGA\",\n NOVEL = \"NOVEL\",\n ONE_SHOT = \"ONE_SHOT\",\n}\n\nexport enum MediaStatus {\n FINISHED = \"FINISHED\",\n RELEASING = \"RELEASING\",\n NOT_YET_RELEASED = \"NOT_YET_RELEASED\",\n CANCELLED = \"CANCELLED\",\n HIATUS = \"HIATUS\",\n}\n\nexport enum MediaSeason {\n WINTER = \"WINTER\",\n SPRING = \"SPRING\",\n SUMMER = \"SUMMER\",\n FALL = \"FALL\",\n}\n\nexport enum MediaSort {\n ID = \"ID\",\n ID_DESC = \"ID_DESC\",\n TITLE_ROMAJI = \"TITLE_ROMAJI\",\n TITLE_ROMAJI_DESC = \"TITLE_ROMAJI_DESC\",\n TITLE_ENGLISH = \"TITLE_ENGLISH\",\n TITLE_ENGLISH_DESC = \"TITLE_ENGLISH_DESC\",\n TITLE_NATIVE = \"TITLE_NATIVE\",\n TITLE_NATIVE_DESC = \"TITLE_NATIVE_DESC\",\n TYPE = \"TYPE\",\n TYPE_DESC = \"TYPE_DESC\",\n FORMAT = \"FORMAT\",\n FORMAT_DESC = \"FORMAT_DESC\",\n START_DATE = \"START_DATE\",\n START_DATE_DESC = \"START_DATE_DESC\",\n END_DATE = \"END_DATE\",\n END_DATE_DESC = \"END_DATE_DESC\",\n SCORE = \"SCORE\",\n SCORE_DESC = \"SCORE_DESC\",\n POPULARITY = \"POPULARITY\",\n POPULARITY_DESC = \"POPULARITY_DESC\",\n TRENDING = \"TRENDING\",\n TRENDING_DESC = \"TRENDING_DESC\",\n EPISODES = \"EPISODES\",\n EPISODES_DESC = \"EPISODES_DESC\",\n DURATION = \"DURATION\",\n DURATION_DESC = \"DURATION_DESC\",\n STATUS = \"STATUS\",\n STATUS_DESC = \"STATUS_DESC\",\n FAVOURITES = \"FAVOURITES\",\n FAVOURITES_DESC = \"FAVOURITES_DESC\",\n UPDATED_AT = \"UPDATED_AT\",\n UPDATED_AT_DESC = \"UPDATED_AT_DESC\",\n SEARCH_MATCH = \"SEARCH_MATCH\",\n}\n\nexport enum AiringSort {\n ID = \"ID\",\n ID_DESC = \"ID_DESC\",\n MEDIA_ID = \"MEDIA_ID\",\n MEDIA_ID_DESC = \"MEDIA_ID_DESC\",\n TIME = \"TIME\",\n TIME_DESC = \"TIME_DESC\",\n EPISODE = \"EPISODE\",\n EPISODE_DESC = \"EPISODE_DESC\",\n}\n\nexport interface MediaTitle {\n romaji: string | null;\n english: string | null;\n native: string | null;\n userPreferred: string | null;\n}\n\nexport interface MediaCoverImage {\n extraLarge: string | null;\n large: string | null;\n medium: string | null;\n color: string | null;\n}\n\nexport interface MediaTrailer {\n id: string | null;\n site: string | null;\n thumbnail: string | null;\n}\n\nexport interface MediaTag {\n id: number;\n name: string;\n description: string | null;\n category: string | null;\n rank: number | null;\n isAdult: boolean | null;\n isMediaSpoiler: boolean | null;\n}\n\nexport enum MediaRelationType {\n ADAPTATION = \"ADAPTATION\",\n PREQUEL = \"PREQUEL\",\n SEQUEL = \"SEQUEL\",\n PARENT = \"PARENT\",\n SIDE_STORY = \"SIDE_STORY\",\n CHARACTER = \"CHARACTER\",\n SUMMARY = \"SUMMARY\",\n ALTERNATIVE = \"ALTERNATIVE\",\n SPIN_OFF = \"SPIN_OFF\",\n OTHER = \"OTHER\",\n SOURCE = \"SOURCE\",\n COMPILATION = \"COMPILATION\",\n CONTAINS = \"CONTAINS\",\n}\n\nexport interface MediaEdge {\n relationType: MediaRelationType;\n node: Pick<Media, \"id\" | \"title\" | \"type\" | \"format\" | \"status\" | \"coverImage\" | \"siteUrl\">;\n}\n\nexport interface MediaConnection {\n edges: MediaEdge[];\n}\n\nexport interface MediaCharacterEdge {\n role: CharacterRole;\n node: Omit<Character, \"media\">;\n voiceActors?: VoiceActor[];\n}\n\nexport interface MediaCharacterConnection {\n edges: MediaCharacterEdge[];\n}\n\nexport interface MediaStaffEdge {\n role: string;\n node: Staff;\n}\n\nexport interface MediaStaffConnection {\n edges: MediaStaffEdge[];\n}\n\nexport interface StreamingEpisode {\n title: string | null;\n thumbnail: string | null;\n url: string | null;\n site: string | null;\n}\n\nexport interface ScoreDistribution {\n score: number;\n amount: number;\n}\n\nexport interface StatusDistribution {\n status: MediaListStatus;\n amount: number;\n}\n\nexport interface MediaStats {\n scoreDistribution: ScoreDistribution[];\n statusDistribution: StatusDistribution[];\n}\n\nexport interface MediaRecommendationNode {\n id: number;\n rating: number | null;\n mediaRecommendation: Pick<Media, \"id\" | \"title\" | \"type\" | \"format\" | \"coverImage\" | \"averageScore\" | \"siteUrl\">;\n}\n\nexport interface NextAiringEpisode {\n id: number;\n airingAt: number;\n episode: number;\n mediaId: number;\n timeUntilAiring: number;\n}\n\nexport interface Media {\n id: number;\n idMal: number | null;\n title: MediaTitle;\n type: MediaType;\n format: MediaFormat | null;\n status: MediaStatus | null;\n description: string | null;\n startDate: FuzzyDate | null;\n endDate: FuzzyDate | null;\n season: MediaSeason | null;\n seasonYear: number | null;\n episodes: number | null;\n duration: number | null;\n chapters: number | null;\n volumes: number | null;\n countryOfOrigin: string | null;\n isLicensed: boolean | null;\n source: MediaSource | null;\n hashtag: string | null;\n trailer: MediaTrailer | null;\n coverImage: MediaCoverImage;\n bannerImage: string | null;\n genres: string[];\n synonyms: string[];\n averageScore: number | null;\n meanScore: number | null;\n popularity: number | null;\n favourites: number | null;\n trending: number | null;\n tags: MediaTag[];\n studios: StudioConnection;\n relations: MediaConnection | null;\n characters?: MediaCharacterConnection;\n staff?: MediaStaffConnection;\n streamingEpisodes?: StreamingEpisode[];\n externalLinks?: ExternalLink[];\n stats?: MediaStats;\n recommendations?: { nodes: MediaRecommendationNode[] };\n nextAiringEpisode: NextAiringEpisode | null;\n isAdult: boolean | null;\n siteUrl: string | null;\n}\n\nexport interface SearchMediaOptions {\n query?: string;\n type?: MediaType;\n format?: MediaFormat;\n status?: MediaStatus;\n season?: MediaSeason;\n seasonYear?: number;\n /** Single genre filter (kept for backward compat) */\n genre?: string;\n /** Single tag filter (kept for backward compat) */\n tag?: string;\n /** Filter by multiple genres (media must match ALL) */\n genres?: string[];\n /** Filter by multiple tags (media must match ALL) */\n tags?: string[];\n /** Exclude media with any of these genres */\n genresExclude?: string[];\n /** Exclude media with any of these tags */\n tagsExclude?: string[];\n isAdult?: boolean;\n sort?: MediaSort[];\n page?: number;\n perPage?: number;\n}\n\nexport interface GetAiringOptions {\n /** Only show episodes that aired after this UNIX timestamp */\n airingAtGreater?: number;\n /** Only show episodes that aired before this UNIX timestamp */\n airingAtLesser?: number;\n /** Sort order (default: TIME_DESC) */\n sort?: AiringSort[];\n page?: number;\n perPage?: number;\n}\n\nexport interface GetRecentChaptersOptions {\n /** Page number (default: 1) */\n page?: number;\n /** Results per page (default: 20, max 50) */\n perPage?: number;\n}\n\nexport interface GetPlanningOptions {\n /** Filter by ANIME or MANGA (returns both if omitted) */\n type?: MediaType;\n /** Sort order (default: POPULARITY_DESC) */\n sort?: MediaSort[];\n page?: number;\n perPage?: number;\n}\n\nexport enum RecommendationSort {\n ID = \"ID\",\n ID_DESC = \"ID_DESC\",\n RATING = \"RATING\",\n RATING_DESC = \"RATING_DESC\",\n}\n\nexport interface Recommendation {\n id: number;\n rating: number | null;\n userRating: string | null;\n mediaRecommendation: Media;\n user: {\n id: number;\n name: string;\n avatar: UserAvatar;\n } | null;\n}\n\nexport interface GetRecommendationsOptions {\n /** The AniList media ID to get recommendations for */\n mediaId: number;\n /** Sort order (default: RATING_DESC) */\n sort?: RecommendationSort[];\n page?: number;\n perPage?: number;\n}\n\nexport interface GetSeasonOptions {\n /** The season (WINTER, SPRING, SUMMER, FALL) */\n season: MediaSeason;\n /** The year */\n seasonYear: number;\n /** Filter by ANIME or MANGA (defaults to ANIME) */\n type?: MediaType;\n /** Sort order (default: POPULARITY_DESC) */\n sort?: MediaSort[];\n page?: number;\n perPage?: number;\n}\n\n/**\n * Options to include additional related data when fetching a media entry.\n * Pass `true` to include with defaults, or an object to customize.\n */\nexport interface MediaIncludeOptions {\n /** Include characters with their roles (MAIN, SUPPORTING, BACKGROUND).\n * `true` = 25 results sorted by role. Object form to customize. */\n characters?: boolean | { perPage?: number; sort?: boolean; voiceActors?: boolean };\n /** Include staff members with their roles.\n * `true` = 25 results sorted by relevance. Object form to customize. */\n staff?: boolean | { perPage?: number; sort?: boolean };\n /** Include relations (default: `true` for backward compat). Set to `false` to exclude. */\n relations?: boolean;\n /** Include streaming episode links (Crunchyroll, Funimation, etc.) */\n streamingEpisodes?: boolean;\n /** Include external links (MAL, official site, etc.) */\n externalLinks?: boolean;\n /** Include score & status distribution stats */\n stats?: boolean;\n /** Include user recommendations. `true` = 10 results, or customize with `{ perPage }`. */\n recommendations?: boolean | { perPage?: number };\n}\n\nexport interface AiringSchedule {\n id: number;\n airingAt: number;\n timeUntilAiring: number;\n episode: number;\n mediaId: number;\n media: Media;\n}\n\nexport type DayOfWeek = \"Monday\" | \"Tuesday\" | \"Wednesday\" | \"Thursday\" | \"Friday\" | \"Saturday\" | \"Sunday\";\n\nexport type WeeklySchedule = Record<DayOfWeek, AiringSchedule[]>;\n","import type { FuzzyDate } from \"./common\";\nimport type { MediaCoverImage, MediaFormat, MediaSeason, MediaStatus, MediaTitle, MediaType } from \"./media\";\n\nexport enum StaffSort {\n ID = \"ID\",\n ID_DESC = \"ID_DESC\",\n ROLE = \"ROLE\",\n ROLE_DESC = \"ROLE_DESC\",\n LANGUAGE = \"LANGUAGE\",\n LANGUAGE_DESC = \"LANGUAGE_DESC\",\n SEARCH_MATCH = \"SEARCH_MATCH\",\n FAVOURITES = \"FAVOURITES\",\n FAVOURITES_DESC = \"FAVOURITES_DESC\",\n RELEVANCE = \"RELEVANCE\",\n}\n\nexport interface StaffName {\n first: string | null;\n middle: string | null;\n last: string | null;\n full: string | null;\n native: string | null;\n}\n\nexport interface StaffImage {\n large: string | null;\n medium: string | null;\n}\n\n/** A media node returned inside `Staff.staffMedia`. */\nexport interface StaffMediaNode {\n id: number;\n title: MediaTitle;\n type: MediaType;\n format: MediaFormat | null;\n status: MediaStatus | null;\n coverImage: MediaCoverImage;\n bannerImage: string | null;\n genres: string[];\n averageScore: number | null;\n meanScore: number | null;\n popularity: number | null;\n favourites: number | null;\n episodes: number | null;\n trending: number | null;\n hashtag: string | null;\n season: MediaSeason | null;\n seasonYear: number | null;\n startDate: FuzzyDate | null;\n endDate: FuzzyDate | null;\n nextAiringEpisode: {\n id: number;\n airingAt: number;\n episode: number;\n mediaId: number;\n timeUntilAiring: number;\n } | null;\n studios: { edges: { node: { name: string } }[] } | null;\n siteUrl: string | null;\n}\n\nexport interface Staff {\n id: number;\n name: StaffName;\n language: string | null;\n image: StaffImage;\n description: string | null;\n primaryOccupations: string[];\n gender: string | null;\n dateOfBirth: FuzzyDate | null;\n dateOfDeath: FuzzyDate | null;\n age: string | null;\n yearsActive: number[];\n homeTown: string | null;\n bloodType: string | null;\n favourites: number | null;\n siteUrl: string | null;\n /** Media the staff member has worked on — only present when requested via include options. */\n staffMedia?: {\n nodes: StaffMediaNode[];\n } | null;\n}\n\n/** Options to include additional related data when fetching a staff member by ID. */\nexport interface StaffIncludeOptions {\n /** Include media the staff member has worked on.\n * `true` = 25 results sorted by popularity. Object form to customize. */\n media?: boolean | { perPage?: number; sort?: boolean };\n}\n\nexport interface SearchStaffOptions {\n query?: string;\n sort?: StaffSort[];\n page?: number;\n perPage?: number;\n}\n\n/** Compact voice actor data returned inside character edges. */\nexport interface VoiceActor extends Pick<Staff, \"id\" | \"image\" | \"gender\" | \"primaryOccupations\" | \"siteUrl\"> {\n name: StaffName & { userPreferred: string | null };\n languageV2: string | null;\n}\n","import type { PageInfo } from \"./common\";\nimport type { Media } from \"./media\";\n\nexport interface Studio {\n id: number;\n name: string;\n isAnimationStudio: boolean;\n siteUrl: string | null;\n favourites?: number | null;\n media?: {\n pageInfo: PageInfo;\n nodes: Pick<Media, \"id\" | \"title\" | \"type\" | \"format\" | \"coverImage\" | \"siteUrl\">[];\n } | null;\n}\n\nexport interface StudioConnection {\n nodes: Studio[];\n}\n\nexport enum StudioSort {\n ID = \"ID\",\n ID_DESC = \"ID_DESC\",\n NAME = \"NAME\",\n NAME_DESC = \"NAME_DESC\",\n SEARCH_MATCH = \"SEARCH_MATCH\",\n FAVOURITES = \"FAVOURITES\",\n FAVOURITES_DESC = \"FAVOURITES_DESC\",\n}\n\nexport interface SearchStudioOptions {\n query?: string;\n sort?: StudioSort[];\n page?: number;\n perPage?: number;\n}\n\n/**\n * Options for controlling embedded media when fetching a single studio.\n * Pass `{ media: { perPage: 50 } }` to fetch more media per studio.\n */\nexport interface StudioIncludeOptions {\n /** Customize the number of media returned. `true` = 25 (default), or `{ perPage }`. */\n media?: boolean | { perPage?: number };\n}\n","import type { MediaCoverImage, MediaTitle, MediaType } from \"./media\";\nimport type { UserAvatar } from \"./user\";\n\n/** Represents a forum thread on AniList. */\nexport interface Thread {\n id: number;\n title: string;\n body: string | null;\n userId: number;\n replyUserId: number | null;\n replyCommentId: number | null;\n replyCount: number;\n viewCount: number;\n isLocked: boolean;\n isSticky: boolean;\n isSubscribed: boolean;\n repliedAt: number | null;\n createdAt: number;\n updatedAt: number;\n siteUrl: string | null;\n user: {\n id: number;\n name: string;\n avatar: UserAvatar;\n } | null;\n replyUser: {\n id: number;\n name: string;\n avatar: UserAvatar;\n } | null;\n categories: ThreadCategory[] | null;\n mediaCategories: ThreadMediaCategory[] | null;\n likes: { id: number; name: string }[] | null;\n}\n\nexport interface ThreadCategory {\n id: number;\n name: string;\n}\n\nexport interface ThreadMediaCategory {\n id: number;\n title: MediaTitle;\n type: MediaType;\n coverImage: Pick<MediaCoverImage, \"large\" | \"medium\"> | null;\n siteUrl: string | null;\n}\n\n/** Sort options for thread queries. */\nexport enum ThreadSort {\n ID = \"ID\",\n ID_DESC = \"ID_DESC\",\n TITLE = \"TITLE\",\n TITLE_DESC = \"TITLE_DESC\",\n CREATED_AT = \"CREATED_AT\",\n CREATED_AT_DESC = \"CREATED_AT_DESC\",\n UPDATED_AT = \"UPDATED_AT\",\n UPDATED_AT_DESC = \"UPDATED_AT_DESC\",\n REPLIED_AT = \"REPLIED_AT\",\n REPLIED_AT_DESC = \"REPLIED_AT_DESC\",\n REPLY_COUNT = \"REPLY_COUNT\",\n REPLY_COUNT_DESC = \"REPLY_COUNT_DESC\",\n VIEW_COUNT = \"VIEW_COUNT\",\n VIEW_COUNT_DESC = \"VIEW_COUNT_DESC\",\n IS_STICKY = \"IS_STICKY\",\n SEARCH_MATCH = \"SEARCH_MATCH\",\n}\n\n/** Options for searching/listing threads. */\nexport interface SearchThreadOptions {\n /** Search query */\n query?: string;\n /** Filter by media ID */\n mediaId?: number;\n /** Filter by category ID */\n categoryId?: number;\n /** Sort order */\n sort?: ThreadSort[];\n /** Page number */\n page?: number;\n /** Results per page (max 50) */\n perPage?: number;\n}\n","import type { MediaCoverImage, MediaFormat, MediaTitle, MediaType } from \"./media\";\n\nexport enum UserSort {\n ID = \"ID\",\n ID_DESC = \"ID_DESC\",\n USERNAME = \"USERNAME\",\n USERNAME_DESC = \"USERNAME_DESC\",\n WATCHED_TIME = \"WATCHED_TIME\",\n WATCHED_TIME_DESC = \"WATCHED_TIME_DESC\",\n CHAPTERS_READ = \"CHAPTERS_READ\",\n CHAPTERS_READ_DESC = \"CHAPTERS_READ_DESC\",\n SEARCH_MATCH = \"SEARCH_MATCH\",\n}\n\nexport interface UserAvatar {\n large: string | null;\n medium: string | null;\n}\n\nexport interface UserStatistics {\n count: number;\n meanScore: number;\n minutesWatched: number;\n episodesWatched: number;\n chaptersRead: number;\n volumesRead: number;\n}\n\nexport interface User {\n id: number;\n name: string;\n about: string | null;\n avatar: UserAvatar;\n bannerImage: string | null;\n isFollowing: boolean | null;\n isFollower: boolean | null;\n donatorTier: number | null;\n donatorBadge: string | null;\n createdAt: number | null;\n siteUrl: string | null;\n statistics: {\n anime: UserStatistics;\n manga: UserStatistics;\n } | null;\n}\n\nexport interface SearchUserOptions {\n query?: string;\n sort?: UserSort[];\n page?: number;\n perPage?: number;\n}\n\nexport interface FavoriteMediaNode {\n id: number;\n title: MediaTitle;\n coverImage: Pick<MediaCoverImage, \"large\" | \"medium\">;\n type: MediaType | null;\n format: MediaFormat | null;\n siteUrl: string | null;\n}\n\nexport interface FavoriteCharacterNode {\n id: number;\n name: { full: string | null; native: string | null };\n image: { large: string | null; medium: string | null };\n siteUrl: string | null;\n}\n\nexport interface FavoriteStaffNode {\n id: number;\n name: { full: string | null; native: string | null };\n image: { large: string | null; medium: string | null };\n siteUrl: string | null;\n}\n\nexport interface FavoriteStudioNode {\n id: number;\n name: string;\n siteUrl: string | null;\n}\n\nexport interface UserFavorites {\n anime: FavoriteMediaNode[];\n manga: FavoriteMediaNode[];\n characters: FavoriteCharacterNode[];\n staff: FavoriteStaffNode[];\n studios: FavoriteStudioNode[];\n}\n\n/**\n * Options for controlling the number of results when fetching user favorites.\n */\nexport interface UserFavoritesOptions {\n /** Number of items per category (default: 25, max: 50). */\n perPage?: number;\n}\n","import {\n buildMediaByIdQuery,\n QUERY_AIRING_SCHEDULE,\n QUERY_MEDIA_BY_MAL_ID,\n QUERY_MEDIA_BY_SEASON,\n QUERY_MEDIA_SEARCH,\n QUERY_PLANNING,\n QUERY_RECENT_CHAPTERS,\n QUERY_RECOMMENDATIONS,\n QUERY_TRENDING,\n} from \"../queries\";\nimport type {\n AiringSchedule,\n DayOfWeek,\n GetAiringOptions,\n GetPlanningOptions,\n GetRecentChaptersOptions,\n GetRecommendationsOptions,\n GetSeasonOptions,\n Media,\n MediaIncludeOptions,\n PagedResult,\n Recommendation,\n SearchMediaOptions,\n WeeklySchedule,\n} from \"../types\";\nimport { MediaSort, MediaType } from \"../types\";\n\nimport { clampPerPage, validateId } from \"../utils\";\nimport type { ClientBase } from \"./base\";\n\nexport async function getMedia(client: ClientBase, id: number, include?: MediaIncludeOptions): Promise<Media> {\n validateId(id, \"mediaId\");\n const query = buildMediaByIdQuery(include);\n const data = await client.request<{ Media: Media }>(query, { id });\n return data.Media;\n}\n\nexport async function getMediaByMalId(client: ClientBase, malId: number, type?: MediaType): Promise<Media> {\n validateId(malId, \"malId\");\n const data = await client.request<{ Media: Media }>(QUERY_MEDIA_BY_MAL_ID, {\n idMal: malId,\n type,\n });\n return data.Media;\n}\n\nexport async function searchMedia(client: ClientBase, options: SearchMediaOptions = {}): Promise<PagedResult<Media>> {\n const { query: search, page = 1, perPage = 20, genres, tags, genresExclude, tagsExclude, ...filters } = options;\n return client.pagedRequest<Media>(\n QUERY_MEDIA_SEARCH,\n {\n search,\n ...filters,\n genre_in: genres,\n tag_in: tags,\n genre_not_in: genresExclude,\n tag_not_in: tagsExclude,\n page,\n perPage: clampPerPage(perPage),\n },\n \"media\",\n );\n}\n\nexport async function getTrending(\n client: ClientBase,\n type: MediaType = MediaType.ANIME,\n page = 1,\n perPage = 20,\n): Promise<PagedResult<Media>> {\n return client.pagedRequest<Media>(QUERY_TRENDING, { type, page, perPage: clampPerPage(perPage) }, \"media\");\n}\n\nexport async function getPopular(\n client: ClientBase,\n type: MediaType = MediaType.ANIME,\n page = 1,\n perPage = 20,\n): Promise<PagedResult<Media>> {\n return searchMedia(client, { type, sort: [MediaSort.POPULARITY_DESC], page, perPage });\n}\n\nexport async function getTopRated(\n client: ClientBase,\n type: MediaType = MediaType.ANIME,\n page = 1,\n perPage = 20,\n): Promise<PagedResult<Media>> {\n return searchMedia(client, { type, sort: [MediaSort.SCORE_DESC], page, perPage });\n}\n\nexport async function getAiredEpisodes(\n client: ClientBase,\n options: GetAiringOptions = {},\n): Promise<PagedResult<AiringSchedule>> {\n const now = Math.floor(Date.now() / 1000);\n return client.pagedRequest<AiringSchedule>(\n QUERY_AIRING_SCHEDULE,\n {\n airingAt_greater: options.airingAtGreater ?? now - 24 * 3600,\n airingAt_lesser: options.airingAtLesser ?? now,\n sort: options.sort,\n page: options.page ?? 1,\n perPage: clampPerPage(options.perPage ?? 20),\n },\n \"airingSchedules\",\n );\n}\n\n/**\n * @deprecated Use `getRecentlyUpdatedManga` instead. This alias will be removed in v2.\n */\nexport const getAiredChapters = getRecentlyUpdatedManga;\n\nexport async function getRecentlyUpdatedManga(\n client: ClientBase,\n options: GetRecentChaptersOptions = {},\n): Promise<PagedResult<Media>> {\n return client.pagedRequest<Media>(\n QUERY_RECENT_CHAPTERS,\n {\n page: options.page ?? 1,\n perPage: clampPerPage(options.perPage ?? 20),\n },\n \"media\",\n );\n}\n\nexport async function getPlanning(client: ClientBase, options: GetPlanningOptions = {}): Promise<PagedResult<Media>> {\n return client.pagedRequest<Media>(\n QUERY_PLANNING,\n {\n type: options.type,\n sort: options.sort ?? [MediaSort.POPULARITY_DESC],\n page: options.page ?? 1,\n perPage: clampPerPage(options.perPage ?? 20),\n },\n \"media\",\n );\n}\n\nexport async function getRecommendations(\n client: ClientBase,\n mediaId: number,\n options: Omit<GetRecommendationsOptions, \"mediaId\"> = {},\n): Promise<PagedResult<Recommendation>> {\n validateId(mediaId, \"mediaId\");\n const data = await client.request<{\n Media: {\n recommendations: {\n pageInfo: { total: number; perPage: number; currentPage: number; lastPage: number; hasNextPage: boolean };\n nodes: Recommendation[];\n };\n };\n }>(QUERY_RECOMMENDATIONS, {\n mediaId,\n page: options.page ?? 1,\n perPage: clampPerPage(options.perPage ?? 20),\n sort: options.sort,\n });\n\n return {\n pageInfo: data.Media.recommendations.pageInfo,\n results: data.Media.recommendations.nodes,\n };\n}\n\nexport async function getMediaBySeason(client: ClientBase, options: GetSeasonOptions): Promise<PagedResult<Media>> {\n return client.pagedRequest<Media>(\n QUERY_MEDIA_BY_SEASON,\n {\n season: options.season,\n seasonYear: options.seasonYear,\n type: options.type,\n sort: options.sort,\n page: options.page ?? 1,\n perPage: clampPerPage(options.perPage ?? 20),\n },\n \"media\",\n );\n}\n\nexport async function getWeeklySchedule(client: ClientBase, date: Date = new Date()): Promise<WeeklySchedule> {\n const schedule: WeeklySchedule = {\n Monday: [],\n Tuesday: [],\n Wednesday: [],\n Thursday: [],\n Friday: [],\n Saturday: [],\n Sunday: [],\n };\n\n const utcDay = date.getUTCDay();\n const diff = utcDay === 0 ? -6 : 1 - utcDay;\n const startOfWeek = new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate() + diff, 0, 0, 0));\n\n const endOfWeek = new Date(startOfWeek);\n endOfWeek.setUTCDate(startOfWeek.getUTCDate() + 6);\n endOfWeek.setUTCHours(23, 59, 59, 999);\n\n const startTimestamp = Math.floor(startOfWeek.getTime() / 1000);\n const endTimestamp = Math.floor(endOfWeek.getTime() / 1000);\n\n const iterator = client.paginate(\n (page) =>\n getAiredEpisodes(client, {\n airingAtGreater: startTimestamp,\n airingAtLesser: endTimestamp,\n page,\n perPage: 50,\n }),\n 20,\n );\n\n const names: DayOfWeek[] = [\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"];\n\n for await (const episode of iterator) {\n const epDate = new Date(episode.airingAt * 1000);\n const dayName = names[epDate.getUTCDay()];\n if (dayName) schedule[dayName].push(episode);\n }\n\n return schedule;\n}\n","import { QUERY_STAFF_BY_ID, QUERY_STAFF_BY_ID_WITH_MEDIA, QUERY_STAFF_SEARCH } from \"../queries\";\n\nimport type { PagedResult, SearchStaffOptions, Staff, StaffIncludeOptions } from \"../types\";\n\nimport { clampPerPage, validateId } from \"../utils\";\nimport type { ClientBase } from \"./base\";\n\nexport async function getStaff(client: ClientBase, id: number, include?: StaffIncludeOptions): Promise<Staff> {\n validateId(id, \"staffId\");\n if (include?.media) {\n const perPage = typeof include.media === \"object\" ? (include.media.perPage ?? 25) : 25;\n const data = await client.request<{ Staff: Staff }>(QUERY_STAFF_BY_ID_WITH_MEDIA, { id, perPage });\n return data.Staff;\n }\n const data = await client.request<{ Staff: Staff }>(QUERY_STAFF_BY_ID, { id });\n return data.Staff;\n}\n\nexport async function searchStaff(client: ClientBase, options: SearchStaffOptions = {}): Promise<PagedResult<Staff>> {\n const { query: search, page = 1, perPage = 20, sort } = options;\n return client.pagedRequest<Staff>(\n QUERY_STAFF_SEARCH,\n { search, sort, page, perPage: clampPerPage(perPage) },\n \"staff\",\n );\n}\n","import { buildStudioByIdQuery, QUERY_STUDIO_BY_ID, QUERY_STUDIO_SEARCH } from \"../queries\";\n\nimport type { PagedResult, SearchStudioOptions, Studio, StudioIncludeOptions } from \"../types\";\n\nimport { clampPerPage, validateId } from \"../utils\";\nimport type { ClientBase } from \"./base\";\n\nexport async function getStudio(client: ClientBase, id: number, include?: StudioIncludeOptions): Promise<Studio> {\n validateId(id, \"studioId\");\n if (include?.media) {\n const perPage = typeof include.media === \"object\" ? include.media.perPage : undefined;\n const query = buildStudioByIdQuery(perPage);\n const data = await client.request<{ Studio: Studio }>(query, { id });\n return data.Studio;\n }\n const data = await client.request<{ Studio: Studio }>(QUERY_STUDIO_BY_ID, { id });\n return data.Studio;\n}\n\nexport async function searchStudios(\n client: ClientBase,\n options: SearchStudioOptions = {},\n): Promise<PagedResult<Studio>> {\n const { query: search, page = 1, perPage = 20, sort } = options;\n return client.pagedRequest<Studio>(\n QUERY_STUDIO_SEARCH,\n {\n search,\n sort,\n page,\n perPage: clampPerPage(perPage),\n },\n \"studios\",\n );\n}\n","import { QUERY_THREAD_BY_ID, QUERY_THREAD_SEARCH } from \"../queries\";\nimport type { PagedResult, SearchThreadOptions, Thread } from \"../types\";\nimport { ThreadSort } from \"../types\";\nimport { clampPerPage, validateId } from \"../utils\";\nimport type { ClientBase } from \"./base\";\n\nexport async function getThread(client: ClientBase, id: number): Promise<Thread> {\n validateId(id, \"threadId\");\n const data = await client.request<{ Thread: Thread }>(QUERY_THREAD_BY_ID, { id });\n return data.Thread;\n}\n\nexport async function getRecentThreads(\n client: ClientBase,\n options: SearchThreadOptions = {},\n): Promise<PagedResult<Thread>> {\n const { query: search, page = 1, perPage = 20, sort, mediaId, categoryId } = options;\n return client.pagedRequest<Thread>(\n QUERY_THREAD_SEARCH,\n {\n search,\n mediaCategoryId: mediaId,\n categoryId,\n sort: sort ?? [ThreadSort.REPLIED_AT_DESC],\n page,\n perPage: clampPerPage(perPage),\n },\n \"threads\",\n );\n}\n","import {\n buildUserFavoritesQuery,\n QUERY_USER_BY_ID,\n QUERY_USER_BY_NAME,\n QUERY_USER_FAVORITES_BY_ID,\n QUERY_USER_FAVORITES_BY_NAME,\n QUERY_USER_MEDIA_LIST,\n QUERY_USER_SEARCH,\n} from \"../queries\";\nimport type {\n GetUserMediaListOptions,\n MediaListEntry,\n PagedResult,\n SearchUserOptions,\n User,\n UserFavorites,\n UserFavoritesOptions,\n} from \"../types\";\nimport { clampPerPage, validateId } from \"../utils\";\nimport type { ClientBase } from \"./base\";\n\nexport async function getUser(client: ClientBase, idOrName: number | string): Promise<User> {\n if (typeof idOrName === \"number\") {\n validateId(idOrName, \"userId\");\n const data = await client.request<{ User: User }>(QUERY_USER_BY_ID, { id: idOrName });\n return data.User;\n }\n const data = await client.request<{ User: User }>(QUERY_USER_BY_NAME, { name: idOrName });\n return data.User;\n}\n\nexport async function searchUsers(client: ClientBase, options: SearchUserOptions = {}): Promise<PagedResult<User>> {\n const { query: search, page = 1, perPage = 20, sort } = options;\n return client.pagedRequest<User>(QUERY_USER_SEARCH, { search, sort, page, perPage: clampPerPage(perPage) }, \"users\");\n}\n\nexport async function getUserMediaList(\n client: ClientBase,\n options: GetUserMediaListOptions,\n): Promise<PagedResult<MediaListEntry>> {\n if (!options.userId && !options.userName) {\n throw new TypeError(\"getUserMediaList requires either userId or userName\");\n }\n if (options.userId) {\n validateId(options.userId, \"userId\");\n }\n return client.pagedRequest<MediaListEntry>(\n QUERY_USER_MEDIA_LIST,\n {\n userId: options.userId,\n userName: options.userName,\n type: options.type,\n status: options.status,\n sort: options.sort,\n page: options.page ?? 1,\n perPage: clampPerPage(options.perPage ?? 20),\n },\n \"mediaList\",\n );\n}\n\ninterface RawFavourites {\n anime?: { nodes: UserFavorites[\"anime\"] };\n manga?: { nodes: UserFavorites[\"manga\"] };\n characters?: { nodes: UserFavorites[\"characters\"] };\n staff?: { nodes: UserFavorites[\"staff\"] };\n studios?: { nodes: UserFavorites[\"studios\"] };\n}\n\nexport async function getUserFavorites(\n client: ClientBase,\n idOrName: number | string,\n options?: UserFavoritesOptions,\n): Promise<UserFavorites> {\n const useBuilder = options?.perPage !== undefined;\n if (typeof idOrName === \"number\") {\n validateId(idOrName, \"userId\");\n const query = useBuilder ? buildUserFavoritesQuery(\"id\", options.perPage) : QUERY_USER_FAVORITES_BY_ID;\n const data = await client.request<{ User: { favourites: RawFavourites } }>(query, {\n id: idOrName,\n });\n return mapFavorites(data.User.favourites);\n }\n const query = useBuilder ? buildUserFavoritesQuery(\"name\", options.perPage) : QUERY_USER_FAVORITES_BY_NAME;\n const data = await client.request<{ User: { favourites: RawFavourites } }>(query, {\n name: idOrName,\n });\n return mapFavorites(data.User.favourites);\n}\n\nfunction mapFavorites(fav: RawFavourites): UserFavorites {\n return {\n anime: fav.anime?.nodes ?? [],\n manga: fav.manga?.nodes ?? [],\n characters: fav.characters?.nodes ?? [],\n staff: fav.staff?.nodes ?? [],\n studios: fav.studios?.nodes ?? [],\n };\n}\n","import { MemoryCache } from \"../cache\";\nimport { AniListError } from \"../errors\";\nimport {\n buildBatchCharacterQuery,\n buildBatchMediaQuery,\n buildBatchStaffQuery,\n QUERY_GENRES,\n QUERY_TAGS,\n} from \"../queries\";\nimport { RateLimiter } from \"../rate-limiter\";\nimport type {\n AiringSchedule,\n AniListClientOptions,\n AniListHooks,\n CacheAdapter,\n Character,\n CharacterIncludeOptions,\n GetAiringOptions,\n GetPlanningOptions,\n GetRecentChaptersOptions,\n GetRecommendationsOptions,\n GetSeasonOptions,\n GetUserMediaListOptions,\n Logger,\n Media,\n MediaIncludeOptions,\n MediaListEntry,\n MediaTag,\n MediaType,\n PagedResult,\n PageInfo,\n RateLimitInfo,\n Recommendation,\n ResponseMeta,\n SearchCharacterOptions,\n SearchMediaOptions,\n SearchStaffOptions,\n SearchStudioOptions,\n SearchThreadOptions,\n SearchUserOptions,\n Staff,\n StaffIncludeOptions,\n Studio,\n StudioIncludeOptions,\n Thread,\n User,\n UserFavorites,\n UserFavoritesOptions,\n WeeklySchedule,\n} from \"../types\";\nimport { chunk, normalizeQuery, validateIds } from \"../utils\";\n\nimport * as characterMethods from \"./character\";\nimport * as mediaMethods from \"./media\";\nimport * as staffMethods from \"./staff\";\nimport * as studioMethods from \"./studio\";\nimport * as threadMethods from \"./thread\";\nimport * as userMethods from \"./user\";\n\nconst DEFAULT_API_URL = \"https://graphql.anilist.co\";\n\ndeclare const __VERSION__: string;\n/** Injected at build time by tsup — falls back to `\"dev\"` in test/dev environments. */\nconst LIB_VERSION = typeof __VERSION__ !== \"undefined\" ? __VERSION__ : \"dev\";\n\n/**\n * Lightweight AniList GraphQL client with built-in caching and rate limiting.\n *\n * @example\n * ```ts\n * import { AniListClient } from \"ani-client\";\n *\n * const client = new AniListClient();\n * const anime = await client.getMedia(1);\n * console.log(anime.title.romaji);\n *\n * // Custom cache & rate limit options\n * const client2 = new AniListClient({\n * cache: { ttl: 1000 * 60 * 60 }, // 1 hour cache\n * rateLimit: { maxRequests: 60 },\n * });\n * ```\n */\nexport class AniListClient {\n private readonly apiUrl: string;\n private readonly headers: Record<string, string>;\n private readonly cacheAdapter: CacheAdapter;\n private readonly rateLimiter: RateLimiter;\n private readonly hooks: AniListHooks;\n private readonly logger?: Logger;\n private readonly signal?: AbortSignal;\n private readonly inFlight = new Map<string, Promise<unknown>>();\n private _rateLimitInfo?: RateLimitInfo;\n private _lastRequestMeta?: ResponseMeta;\n\n constructor(options: AniListClientOptions = {}) {\n this.apiUrl = options.apiUrl ?? DEFAULT_API_URL;\n this.headers = {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n \"User-Agent\": `ani-client/${LIB_VERSION}`,\n };\n if (options.token) {\n this.headers.Authorization = `Bearer ${options.token}`;\n }\n this.cacheAdapter = options.cacheAdapter ?? new MemoryCache(options.cache);\n this.rateLimiter = new RateLimiter(options.rateLimit);\n this.hooks = options.hooks ?? {};\n this.logger = options.logger;\n this.signal = options.signal;\n }\n\n /**\n * The current rate limit information from the last API response.\n * Updated after every non-cached request.\n */\n get rateLimitInfo(): RateLimitInfo | undefined {\n return this._rateLimitInfo;\n }\n\n /**\n * Metadata about the last request (duration, cache status, rate limit info).\n * Useful for debugging and monitoring.\n */\n get lastRequestMeta(): ResponseMeta | undefined {\n return this._lastRequestMeta;\n }\n\n /** @internal */\n async request<T>(query: string, variables: Record<string, unknown> = {}): Promise<T> {\n const cacheKey = MemoryCache.key(query, variables);\n\n const cached = await this.cacheAdapter.get<T>(cacheKey);\n if (cached !== undefined) {\n this.hooks.onCacheHit?.(cacheKey);\n this.logger?.debug(\"Cache hit\", { cacheKey });\n const meta: ResponseMeta = { durationMs: 0, fromCache: true };\n this._lastRequestMeta = meta;\n this.hooks.onResponse?.(query, 0, true);\n return cached;\n }\n\n const existing = this.inFlight.get(cacheKey);\n if (existing) return existing as Promise<T>;\n\n const promise = this.executeRequest<T>(query, variables, cacheKey);\n this.inFlight.set(cacheKey, promise);\n\n try {\n return await promise;\n } finally {\n this.inFlight.delete(cacheKey);\n }\n }\n\n /** @internal */\n private async executeRequest<T>(query: string, variables: Record<string, unknown>, cacheKey: string): Promise<T> {\n const start = Date.now();\n this.hooks.onRequest?.(query, variables);\n this.logger?.debug(\"API request\", { variables });\n\n const minifiedQuery = normalizeQuery(query);\n\n let res: Response;\n try {\n res = await this.rateLimiter.fetchWithRetry(\n this.apiUrl,\n {\n method: \"POST\",\n headers: this.headers,\n body: JSON.stringify({ query: minifiedQuery, variables }),\n signal: this.signal,\n },\n { onRetry: this.hooks.onRetry, onRateLimit: this.hooks.onRateLimit },\n );\n } catch (err) {\n const error =\n err instanceof AniListError\n ? err\n : new AniListError((err as Error).message ?? \"Network request failed\", 0, [err]);\n this.logger?.error(\"Request failed\", { error: error.message, status: error.status });\n this.hooks.onError?.(error, query, variables);\n throw error;\n }\n\n let json: { data?: T; errors?: unknown[] };\n try {\n json = (await res.json()) as { data?: T; errors?: unknown[] };\n } catch {\n const error = new AniListError(`Non-JSON response from AniList (HTTP ${res.status})`, res.status, []);\n this.logger?.error(\"Request failed\", { error: error.message, status: error.status });\n this.hooks.onError?.(error, query, variables);\n throw error;\n }\n\n if (!res.ok || json.errors) {\n const message =\n (json.errors as Array<{ message?: string }>)?.[0]?.message ?? `AniList API error (HTTP ${res.status})`;\n const error = new AniListError(message, res.status, json.errors ?? []);\n this.logger?.error(\"Request failed\", { error: error.message, status: error.status });\n this.hooks.onError?.(error, query, variables);\n throw error;\n }\n\n const rlLimit = res.headers.get(\"X-RateLimit-Limit\");\n const rlRemaining = res.headers.get(\"X-RateLimit-Remaining\");\n const rlReset = res.headers.get(\"X-RateLimit-Reset\");\n if (rlLimit && rlRemaining && rlReset) {\n this._rateLimitInfo = {\n limit: Number.parseInt(rlLimit, 10),\n remaining: Number.parseInt(rlRemaining, 10),\n reset: Number.parseInt(rlReset, 10),\n };\n }\n\n const durationMs = Date.now() - start;\n const data = json.data as T;\n await this.cacheAdapter.set(cacheKey, data);\n\n const meta: ResponseMeta = { durationMs, fromCache: false, rateLimitInfo: this._rateLimitInfo };\n this._lastRequestMeta = meta;\n this.logger?.debug(\"Request complete\", { durationMs, rateLimitInfo: this._rateLimitInfo });\n this.hooks.onResponse?.(query, durationMs, false, this._rateLimitInfo);\n return data;\n }\n\n /** @internal */\n async pagedRequest<T>(query: string, variables: Record<string, unknown>, field: string): Promise<PagedResult<T>> {\n const data = await this.request<{ Page: Record<string, unknown> & { pageInfo: PageInfo } }>(query, variables);\n const results = data.Page[field];\n if (!Array.isArray(results)) {\n throw new AniListError(`Unexpected response: missing field \"${field}\" in Page`, 0, []);\n }\n return { pageInfo: data.Page.pageInfo, results: results as T[] };\n }\n\n /**\n * Fetch a single media entry by its AniList ID.\n *\n * Optionally include related data (characters, staff, relations, etc.) via the `include` parameter.\n *\n * @param id - The AniList media ID\n * @param include - Optional related data to include\n */\n async getMedia(id: number, include?: MediaIncludeOptions): Promise<Media> {\n return mediaMethods.getMedia(this, id, include);\n }\n\n /**\n * Search for anime or manga.\n *\n * @param options - Search / filter parameters\n * @returns Paginated results with matching media\n */\n async searchMedia(options: SearchMediaOptions = {}): Promise<PagedResult<Media>> {\n return mediaMethods.searchMedia(this, options);\n }\n\n /** Get currently trending anime or manga. */\n async getTrending(type?: MediaType, page?: number, perPage?: number): Promise<PagedResult<Media>> {\n return mediaMethods.getTrending(this, type, page, perPage);\n }\n\n /** Get the most popular anime or manga. */\n async getPopular(type?: MediaType, page?: number, perPage?: number): Promise<PagedResult<Media>> {\n return mediaMethods.getPopular(this, type, page, perPage);\n }\n\n /** Get the highest-rated anime or manga. */\n async getTopRated(type?: MediaType, page?: number, perPage?: number): Promise<PagedResult<Media>> {\n return mediaMethods.getTopRated(this, type, page, perPage);\n }\n\n /** Get recently aired anime episodes. */\n async getAiredEpisodes(options: GetAiringOptions = {}): Promise<PagedResult<AiringSchedule>> {\n return mediaMethods.getAiredEpisodes(this, options);\n }\n\n /**\n * Get currently releasing manga sorted by most recently updated.\n *\n * @param options - Pagination parameters\n */\n async getRecentlyUpdatedManga(options: GetRecentChaptersOptions = {}): Promise<PagedResult<Media>> {\n return mediaMethods.getRecentlyUpdatedManga(this, options);\n }\n\n /**\n * @deprecated Use `getRecentlyUpdatedManga` instead. This alias will be removed in v2.\n */\n async getAiredChapters(options: GetRecentChaptersOptions = {}): Promise<PagedResult<Media>> {\n return this.getRecentlyUpdatedManga(options);\n }\n\n /**\n * Fetch a media entry by its MyAnimeList (MAL) ID.\n *\n * @param malId - The MyAnimeList ID\n * @param type - Optional media type to disambiguate (some MAL IDs map to both ANIME and MANGA)\n */\n async getMediaByMalId(malId: number, type?: MediaType): Promise<Media> {\n return mediaMethods.getMediaByMalId(this, malId, type);\n }\n\n /** Get the detailed schedule for the current week, sorted by day. */\n async getWeeklySchedule(date?: Date): Promise<WeeklySchedule> {\n return mediaMethods.getWeeklySchedule(this, date);\n }\n\n /** Get upcoming (not yet released) media. */\n async getPlanning(options: GetPlanningOptions = {}): Promise<PagedResult<Media>> {\n return mediaMethods.getPlanning(this, options);\n }\n\n /** Get recommendations for a specific media. */\n async getRecommendations(\n mediaId: number,\n options: Omit<GetRecommendationsOptions, \"mediaId\"> = {},\n ): Promise<PagedResult<Recommendation>> {\n return mediaMethods.getRecommendations(this, mediaId, options);\n }\n\n /** Get anime (or manga) for a specific season and year. */\n async getMediaBySeason(options: GetSeasonOptions): Promise<PagedResult<Media>> {\n return mediaMethods.getMediaBySeason(this, options);\n }\n\n /** Fetch a character by AniList ID. Pass `{ voiceActors: true }` to include VA data. */\n async getCharacter(id: number, include?: CharacterIncludeOptions): Promise<Character> {\n return characterMethods.getCharacter(this, id, include);\n }\n\n /** Search for characters by name. */\n async searchCharacters(options: SearchCharacterOptions = {}): Promise<PagedResult<Character>> {\n return characterMethods.searchCharacters(this, options);\n }\n\n /** Fetch a staff member by AniList ID. Pass `{ media: true }` or `{ media: { perPage } }` for media credits. */\n async getStaff(id: number, include?: StaffIncludeOptions): Promise<Staff> {\n return staffMethods.getStaff(this, id, include);\n }\n\n /** Search for staff (voice actors, directors, etc.). */\n async searchStaff(options: SearchStaffOptions = {}): Promise<PagedResult<Staff>> {\n return staffMethods.searchStaff(this, options);\n }\n\n /**\n * Fetch a user by AniList ID or username.\n *\n * @param idOrName - The AniList user ID (number) or username (string)\n */\n async getUser(idOrName: number | string): Promise<User> {\n return userMethods.getUser(this, idOrName);\n }\n\n /** Search for users by name. */\n async searchUsers(options: SearchUserOptions = {}): Promise<PagedResult<User>> {\n return userMethods.searchUsers(this, options);\n }\n\n /** Get a user's anime or manga list. */\n async getUserMediaList(options: GetUserMediaListOptions): Promise<PagedResult<MediaListEntry>> {\n return userMethods.getUserMediaList(this, options);\n }\n\n /**\n * Fetch a user's favorite anime, manga, characters, staff, and studios.\n *\n * @param idOrName - AniList user ID (number) or username (string)\n * @param options - Optional pagination options (perPage per category)\n * @returns The user's favorites grouped by category\n *\n * @example\n * ```typescript\n * const favs = await client.getUserFavorites(\"AniList\");\n * favs.anime.forEach(a => console.log(a.title.romaji));\n *\n * // Fetch more results per category\n * const moreResults = await client.getUserFavorites(1, { perPage: 50 });\n * ```\n */\n async getUserFavorites(idOrName: number | string, options?: UserFavoritesOptions): Promise<UserFavorites> {\n return userMethods.getUserFavorites(this, idOrName, options);\n }\n\n /**\n * Fetch a studio by its AniList ID.\n * Pass `include` to customise the number of media returned.\n *\n * @example\n * ```typescript\n * const studio = await client.getStudio(21, { media: { perPage: 50 } });\n * ```\n */\n async getStudio(id: number, include?: StudioIncludeOptions): Promise<Studio> {\n return studioMethods.getStudio(this, id, include);\n }\n\n /** Search for studios by name. */\n async searchStudios(options: SearchStudioOptions = {}): Promise<PagedResult<Studio>> {\n return studioMethods.searchStudios(this, options);\n }\n\n /** Fetch a forum thread by its AniList ID. */\n async getThread(id: number): Promise<Thread> {\n return threadMethods.getThread(this, id);\n }\n\n /** Get recent forum threads, optionally filtered by search, media, or category. */\n async getRecentThreads(options: SearchThreadOptions = {}): Promise<PagedResult<Thread>> {\n return threadMethods.getRecentThreads(this, options);\n }\n\n /** Get all available genres on AniList. */\n async getGenres(): Promise<string[]> {\n const data = await this.request<{ GenreCollection: string[] }>(QUERY_GENRES);\n return data.GenreCollection;\n }\n\n /** Get all available media tags on AniList. */\n async getTags(): Promise<MediaTag[]> {\n const data = await this.request<{ MediaTagCollection: MediaTag[] }>(QUERY_TAGS);\n return data.MediaTagCollection;\n }\n\n /** Execute an arbitrary GraphQL query against the AniList API. */\n async raw<T>(query: string, variables?: Record<string, unknown>): Promise<T> {\n return this.request<T>(query, variables ?? {});\n }\n\n /**\n * Auto-paginating async iterator. Yields individual items across all pages.\n *\n * @param fetchPage - A function that takes a page number and returns a `PagedResult<T>`\n * @param maxPages - Maximum number of pages to fetch (default: Infinity)\n */\n async *paginate<T>(\n fetchPage: (page: number) => Promise<PagedResult<T>>,\n maxPages = Number.POSITIVE_INFINITY,\n ): AsyncGenerator<T, void, undefined> {\n let page = 1;\n let hasNext = true;\n\n while (hasNext && page <= maxPages) {\n const result = await fetchPage(page);\n for (const item of result.results) {\n yield item;\n }\n hasNext = result.pageInfo.hasNextPage === true;\n page++;\n }\n }\n\n /** Fetch multiple media entries in a single API request. */\n async getMediaBatch(ids: number[]): Promise<Media[]> {\n if (ids.length === 0) return [];\n validateIds(ids, \"mediaId\");\n const [singleMediaId] = ids;\n if (ids.length === 1 && singleMediaId !== undefined) return [await this.getMedia(singleMediaId)];\n return this.executeBatch<Media>(ids, buildBatchMediaQuery, \"m\");\n }\n\n /** Fetch multiple characters in a single API request. */\n async getCharacterBatch(ids: number[]): Promise<Character[]> {\n if (ids.length === 0) return [];\n validateIds(ids, \"characterId\");\n const [singleCharId] = ids;\n if (ids.length === 1 && singleCharId !== undefined) return [await this.getCharacter(singleCharId)];\n return this.executeBatch<Character>(ids, buildBatchCharacterQuery, \"c\");\n }\n\n /** Fetch multiple staff members in a single API request. */\n async getStaffBatch(ids: number[]): Promise<Staff[]> {\n if (ids.length === 0) return [];\n validateIds(ids, \"staffId\");\n const [singleStaffId] = ids;\n if (ids.length === 1 && singleStaffId !== undefined) return [await this.getStaff(singleStaffId)];\n return this.executeBatch<Staff>(ids, buildBatchStaffQuery, \"s\");\n }\n\n /** @internal */\n private async executeBatch<T>(ids: number[], buildQuery: (ids: number[]) => string, prefix: string): Promise<T[]> {\n const chunks = chunk(ids, 50);\n const chunkResults = await Promise.all(\n chunks.map(async (idChunk) => {\n const query = buildQuery(idChunk);\n const data = await this.request<Record<string, T>>(query);\n return idChunk.map((_, i) => data[`${prefix}${i}`] as T);\n }),\n );\n return chunkResults.flat();\n }\n\n /** Clear the entire response cache. */\n async clearCache(): Promise<void> {\n await this.cacheAdapter.clear();\n }\n\n /** Number of entries currently in the cache. */\n async cacheSize(): Promise<number> {\n return this.cacheAdapter.size;\n }\n\n /** Remove cache entries whose key matches the given pattern. */\n async invalidateCache(pattern: string | RegExp): Promise<number> {\n if (this.cacheAdapter.invalidate) {\n return this.cacheAdapter.invalidate(pattern);\n }\n const allKeys = await this.cacheAdapter.keys();\n const regex = typeof pattern === \"string\" ? new RegExp(pattern) : pattern;\n let count = 0;\n for (const key of allKeys) {\n if (regex.test(key)) {\n await this.cacheAdapter.delete(key);\n count++;\n }\n }\n return count;\n }\n\n /** Clean up resources held by the client. */\n async destroy(): Promise<void> {\n await this.cacheAdapter.clear();\n this.inFlight.clear();\n this.rateLimiter.dispose();\n }\n\n /**\n * Return a scoped view of this client where every request uses the given `AbortSignal`.\n * The returned object shares the same cache, rate limiter, and hooks.\n *\n * @example\n * ```ts\n * const controller = new AbortController();\n * const media = await client.withSignal(controller.signal).getMedia(1);\n *\n * // Cancel all in-flight requests made through the scoped view\n * controller.abort();\n * ```\n */\n withSignal(signal: AbortSignal): AniListClient {\n const scoped = Object.create(this) as AniListClient;\n Object.defineProperty(scoped, \"signal\", { value: signal, configurable: true });\n return scoped;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/utils/markdown.ts","../src/utils/index.ts","../src/cache/index.ts","../src/cache/redis.ts","../src/errors/index.ts","../src/queries/fragments.ts","../src/queries/media.ts","../src/queries/builders.ts","../src/queries/character.ts","../src/queries/metadata.ts","../src/queries/staff.ts","../src/queries/studio.ts","../src/queries/thread.ts","../src/queries/user.ts","../src/rate-limiter/index.ts","../src/client/character.ts","../src/types/character.ts","../src/types/lists.ts","../src/types/media.ts","../src/types/staff.ts","../src/types/studio.ts","../src/types/thread.ts","../src/types/user.ts","../src/client/media.ts","../src/client/staff.ts","../src/client/studio.ts","../src/client/thread.ts","../src/client/user.ts","../src/client/index.ts"],"names":["text","CharacterSort","CharacterRole","MediaListStatus","MediaListSort","MediaType","MediaSource","MediaFormat","MediaStatus","MediaSeason","MediaSort","AiringSort","MediaRelationType","RecommendationSort","StaffSort","StudioSort","ThreadSort","UserSort","data","query"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Parses AniList specific markdown into standard HTML.\n * Includes formatting for spoilers, images, videos (youtube/webm), headings,\n * lists, code blocks, and standard markdown elements.\n *\n * @security This function escapes HTML entities to prevent XSS attacks.\n * However, the output is still raw HTML — consumers should always use a\n * Content Security Policy and consider additional sanitization when rendering\n * user-generated content in a browser.\n *\n * @param text The AniList markdown text to parse\n * @returns The parsed HTML string\n */\n/** @internal Check that a URL uses a safe protocol (http/https). */\nfunction isSafeUrl(url: string): boolean {\n return /^https?:\\/\\//i.test(url);\n}\n\nexport function parseAniListMarkdown(text: string): string {\n if (!text) return \"\";\n\n let html = text;\n\n html = html\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n\n html = html.replace(/```([\\s\\S]*?)```/g, (_match, code: string) => {\n return `<pre><code>${code.trim()}</code></pre>`;\n });\n\n html = html.replace(/`([^`]+)`/g, \"<code>$1</code>\");\n\n html = html.replace(/~!(.*?)!~/gs, '<span class=\"anilist-spoiler\">$1</span>');\n\n html = html.replace(/~~~(.*?)~~~/gs, '<div class=\"anilist-center\">$1</div>');\n\n html = html.replace(/img(\\d+)\\((.*?)\\)/gi, (_match, width: string, url: string) =>\n isSafeUrl(url) ? `<img src=\"${url}\" width=\"${width}\" alt=\"\" class=\"anilist-image\" />` : \"\",\n );\n\n html = html.replace(/img\\((.*?)\\)/gi, (_match, url: string) =>\n isSafeUrl(url) ? `<img src=\"${url}\" alt=\"\" class=\"anilist-image\" />` : \"\",\n );\n\n html = html.replace(/youtube\\((.*?)\\)/gi, (_match, id: string) => {\n if (!/^[\\w-]+$/.test(id)) return \"\";\n return `<iframe src=\"https://www.youtube.com/embed/${id}\" frameborder=\"0\" allowfullscreen class=\"anilist-youtube\"></iframe>`;\n });\n\n html = html.replace(/webm\\((.*?)\\)/gi, (_match, url: string) =>\n isSafeUrl(url) ? `<video src=\"${url}\" controls class=\"anilist-webm\"></video>` : \"\",\n );\n\n html = html.replace(/^######\\s+(.+)$/gm, \"<h6>$1</h6>\");\n html = html.replace(/^#####\\s+(.+)$/gm, \"<h5>$1</h5>\");\n html = html.replace(/^####\\s+(.+)$/gm, \"<h4>$1</h4>\");\n html = html.replace(/^###\\s+(.+)$/gm, \"<h3>$1</h3>\");\n html = html.replace(/^##\\s+(.+)$/gm, \"<h2>$1</h2>\");\n html = html.replace(/^#\\s+(.+)$/gm, \"<h1>$1</h1>\");\n\n html = html.replace(/__(.*?)__/g, \"<strong>$1</strong>\");\n html = html.replace(/\\*\\*(.*?)\\*\\*/g, \"<strong>$1</strong>\");\n\n html = html.replace(/_(.*?)_/g, \"<em>$1</em>\");\n html = html.replace(/(?<!\\*)\\*(?!\\*)(.*?)(?<!\\*)\\*(?!\\*)/g, \"<em>$1</em>\");\n\n html = html.replace(/~~(.*?)~~/g, \"<del>$1</del>\");\n\n html = html.replace(/\\[(.*?)\\]\\((.*?)\\)/g, (_match, text: string, url: string) =>\n isSafeUrl(url) ? `<a href=\"${url}\" target=\"_blank\" rel=\"noopener noreferrer\">${text}</a>` : text,\n );\n\n html = html.replace(/\\r\\n/g, \"\\n\");\n const lines = html.split(\"\\n\");\n const processed: string[] = [];\n let listType: \"ul\" | \"ol\" | null = null;\n\n for (const line of lines) {\n const ulMatch = line.match(/^[\\s]*[-*]\\s+(.*)/);\n const olMatch = line.match(/^[\\s]*\\d+\\.\\s+(.*)/);\n\n if (ulMatch) {\n if (listType !== \"ul\") {\n if (listType) processed.push(`</${listType}>`);\n processed.push(\"<ul>\");\n listType = \"ul\";\n }\n processed.push(`<li>${ulMatch[1]}</li>`);\n } else if (olMatch) {\n if (listType !== \"ol\") {\n if (listType) processed.push(`</${listType}>`);\n processed.push(\"<ol>\");\n listType = \"ol\";\n }\n processed.push(`<li>${olMatch[1]}</li>`);\n } else {\n if (listType) {\n processed.push(`</${listType}>`);\n listType = null;\n }\n processed.push(line);\n }\n }\n if (listType) processed.push(`</${listType}>`);\n\n html = processed.join(\"\\n\");\n\n const paragraphs = html.split(/\\n{2,}/);\n html = paragraphs\n .map((p) => {\n const trimmed = p.trim();\n if (!trimmed) return \"\";\n const withBr = trimmed.replace(/\\n/g, \"<br />\");\n if (withBr.match(/^(<div|<iframe|<video|<img|<h[1-6]|<ul|<ol|<pre)/)) {\n return withBr;\n }\n return `<p>${withBr}</p>`;\n })\n .filter(Boolean)\n .join(\"\\n\");\n\n return html;\n}\n","/**\n * Utility functions for internal use.\n */\n\nconst WHITESPACE_RE = /\\s+/g;\n\n/**\n * Normalize a GraphQL query string by collapsing all whitespace.\n * Used for cache key generation and request body minification.\n *\n * @internal\n * @param query - The raw GraphQL query string\n * @returns The whitespace-normalized query\n */\nexport function normalizeQuery(query: string): string {\n return query.replace(WHITESPACE_RE, \" \").trim();\n}\n\n/**\n * Clamp a number to a maximum and minimum value.\n * Used internally to ensure perPage does not exceed AniList's limit of 50.\n *\n * @internal\n * @param value - The number to clamp\n * @returns The clamped number between 1 and 50\n */\nexport function clampPerPage(value: number): number {\n return Math.min(Math.max(value, 1), 50);\n}\n\n/**\n * Split an array into smaller chunks of a specific size.\n * Used internally for batching GraphQL queries.\n *\n * @internal\n * @param arr - The array to chunk\n * @param size - The maximum size of each chunk\n * @returns An array of chunks\n */\nexport function chunk<T>(arr: T[], size: number): T[][] {\n if (size < 1) throw new RangeError(\"chunk size must be >= 1\");\n const chunks: T[][] = [];\n for (let i = 0; i < arr.length; i += size) {\n chunks.push(arr.slice(i, i + size));\n }\n return chunks;\n}\n\n/**\n * Validate that a value is a finite positive integer (valid AniList ID).\n *\n * @internal\n * @param id - The ID to validate\n * @param label - Label for the error message (e.g. \"mediaId\")\n * @throws {RangeError} If the ID is not a finite positive integer\n */\nexport function validateId(id: number, label = \"id\"): void {\n if (!Number.isFinite(id) || !Number.isInteger(id) || id < 1) {\n throw new RangeError(`Invalid ${label}: expected a positive integer, got ${id}`);\n }\n}\n\n/**\n * Validate an array of IDs.\n *\n * @internal\n * @param ids - The IDs to validate\n * @param label - Label for the error message\n * @throws {RangeError} If any ID is not a finite positive integer\n */\nexport function validateIds(ids: number[], label = \"id\"): void {\n for (const id of ids) {\n validateId(id, label);\n }\n}\n\n/**\n * Deep-sort an object's keys recursively for deterministic JSON serialization.\n *\n * @internal\n */\nexport function sortObjectKeys(obj: unknown): unknown {\n if (obj === null || typeof obj !== \"object\") return obj;\n if (Array.isArray(obj)) return obj.map(sortObjectKeys);\n const sorted: Record<string, unknown> = {};\n for (const key of Object.keys(obj as Record<string, unknown>).sort()) {\n sorted[key] = sortObjectKeys((obj as Record<string, unknown>)[key]);\n }\n return sorted;\n}\n\nexport * from \"./markdown\";\n","import type { CacheAdapter, CacheOptions } from \"../types\";\nimport { normalizeQuery, sortObjectKeys } from \"../utils\";\n\n/**\n * Simple in-memory cache with configurable TTL, LRU eviction, and optional stale-while-revalidate.\n * Used internally by AniListClient to avoid redundant API calls.\n */\nexport type { CacheOptions };\n\n/** Cache performance statistics. */\nexport interface CacheStats {\n /** Total cache hits. */\n hits: number;\n /** Total cache misses. */\n misses: number;\n /** Stale entries returned (only with stale-while-revalidate). */\n stales: number;\n /** Hit rate as a ratio 0–1 (NaN if no requests yet). */\n hitRate: number;\n}\n\ninterface CacheEntry<T> {\n data: T;\n expiresAt: number;\n}\n\nconst ONE_DAY_MS = 24 * 60 * 60 * 1000;\n\nexport class MemoryCache implements CacheAdapter {\n private readonly ttl: number;\n private readonly maxSize: number;\n private readonly enabled: boolean;\n private readonly swrMs: number;\n private readonly store = new Map<string, CacheEntry<unknown>>();\n\n private _hits = 0;\n private _misses = 0;\n private _stales = 0;\n\n constructor(options: CacheOptions = {}) {\n this.ttl = options.ttl ?? ONE_DAY_MS;\n this.maxSize = options.maxSize ?? 500;\n this.enabled = options.enabled ?? true;\n this.swrMs = options.staleWhileRevalidateMs ?? 0;\n }\n\n /** Build a deterministic cache key from a query + variables pair. */\n static key(query: string, variables: Record<string, unknown>): string {\n const normalized = normalizeQuery(query);\n return `${normalized}|${JSON.stringify(sortObjectKeys(variables))}`;\n }\n\n /**\n * Retrieve a cached value, or `undefined` if missing / expired.\n * With stale-while-revalidate enabled, returns stale data within the grace window\n * and flags it so the caller can refresh in the background.\n */\n get<T>(key: string): T | undefined {\n if (!this.enabled) return undefined;\n const entry = this.store.get(key);\n if (!entry) {\n this._misses++;\n return undefined;\n }\n const now = Date.now();\n if (now > entry.expiresAt) {\n if (this.swrMs > 0 && now <= entry.expiresAt + this.swrMs) {\n this.store.delete(key);\n this.store.set(key, entry);\n this._stales++;\n return entry.data as T;\n }\n this.store.delete(key);\n this._misses++;\n return undefined;\n }\n this.store.delete(key);\n this.store.set(key, entry);\n this._hits++;\n return entry.data as T;\n }\n\n /** Store a value in the cache. */\n set<T>(key: string, data: T): void {\n if (!this.enabled) return;\n\n this.store.delete(key);\n\n if (this.maxSize > 0 && this.store.size >= this.maxSize) {\n const firstKey = this.store.keys().next().value;\n if (firstKey !== undefined) this.store.delete(firstKey);\n }\n\n this.store.set(key, { data, expiresAt: Date.now() + this.ttl });\n }\n\n /** Remove a specific entry. */\n delete(key: string): boolean {\n return this.store.delete(key);\n }\n\n /** Clear the entire cache and reset statistics. */\n clear(): void {\n this.store.clear();\n this._hits = 0;\n this._misses = 0;\n this._stales = 0;\n }\n\n /** Number of entries currently stored. */\n get size(): number | Promise<number> {\n return this.store.size;\n }\n\n /** Return all cache keys. */\n keys(): string[] {\n return [...this.store.keys()];\n }\n\n /**\n * Get cache performance statistics.\n *\n * @example\n * ```ts\n * const cache = new MemoryCache();\n * // ... after some usage ...\n * console.log(cache.stats);\n * // { hits: 42, misses: 8, stales: 0, hitRate: 0.84 }\n * ```\n */\n get stats(): CacheStats {\n const total = this._hits + this._misses + this._stales;\n return {\n hits: this._hits,\n misses: this._misses,\n stales: this._stales,\n hitRate: total === 0 ? Number.NaN : this._hits / total,\n };\n }\n\n /** Reset cache statistics without clearing stored data. */\n resetStats(): void {\n this._hits = 0;\n this._misses = 0;\n this._stales = 0;\n }\n\n /**\n * Remove all entries whose key matches the given pattern.\n *\n * - **String**: treated as a substring match (e.g. `\"Media\"` removes all keys containing `\"Media\"`).\n * - **RegExp**: tested against each key directly.\n *\n * @param pattern — A string (substring match) or RegExp.\n * @returns Number of entries removed.\n */\n invalidate(pattern: string | RegExp): number {\n const test =\n typeof pattern === \"string\" ? (key: string) => key.includes(pattern) : (key: string) => pattern.test(key);\n const toDelete: string[] = [];\n for (const key of this.store.keys()) {\n if (test(key)) toDelete.push(key);\n }\n for (const key of toDelete) this.store.delete(key);\n return toDelete.length;\n }\n}\n","import type { CacheAdapter } from \"../types\";\n\n/**\n * Minimal interface representing a Redis client.\n * Compatible with both `ioredis` and `redis` (node-redis v4+).\n */\nexport interface RedisLikeClient {\n get(key: string): Promise<string | null>;\n set(key: string, value: string, ...args: unknown[]): Promise<unknown>;\n del(...keys: (string | string[])[]): Promise<number>;\n keys(pattern: string): Promise<string[]>;\n /** Optional SCAN-based iteration — used when available to avoid blocking the server. */\n scanIterator?(options: { MATCH: string; COUNT?: number }): AsyncIterable<string>;\n}\n\nexport interface RedisCacheOptions {\n /** A Redis client instance (ioredis or node-redis). */\n client: RedisLikeClient;\n /** Key prefix to namespace ani-client entries (default: `\"ani:\"`) */\n prefix?: string;\n /** TTL in seconds (default: 86 400 = 24 h) */\n ttl?: number;\n}\n\n/**\n * Redis-backed cache adapter for AniListClient.\n *\n * @example\n * ```ts\n * import Redis from \"ioredis\";\n * import { AniListClient, RedisCache } from \"ani-client\";\n *\n * const redis = new Redis();\n * const client = new AniListClient({\n * cacheAdapter: new RedisCache({ client: redis }),\n * });\n * ```\n */\nexport class RedisCache implements CacheAdapter {\n private readonly client: RedisLikeClient;\n private readonly prefix: string;\n private readonly ttl: number;\n\n constructor(options: RedisCacheOptions) {\n this.client = options.client;\n this.prefix = options.prefix ?? \"ani:\";\n this.ttl = options.ttl ?? 86_400;\n }\n\n private prefixedKey(key: string): string {\n return `${this.prefix}${key}`;\n }\n\n async get<T>(key: string): Promise<T | undefined> {\n const raw = await this.client.get(this.prefixedKey(key));\n if (raw === null) return undefined;\n try {\n return JSON.parse(raw) as T;\n } catch {\n return undefined;\n }\n }\n\n async set<T>(key: string, data: T): Promise<void> {\n await this.client.set(this.prefixedKey(key), JSON.stringify(data), \"EX\", this.ttl);\n }\n\n async delete(key: string): Promise<boolean> {\n const count = await this.client.del(this.prefixedKey(key));\n return count > 0;\n }\n\n /**\n * Collect keys matching a pattern. Uses SCAN when available, falls back to KEYS.\n *\n * **Warning:** The `KEYS` fallback is O(N) and blocks the Redis server.\n * Provide a client with `scanIterator` support for production use.\n * @internal\n */\n private async collectKeys(pattern: string): Promise<string[]> {\n if (this.client.scanIterator) {\n const keys: string[] = [];\n for await (const key of this.client.scanIterator({ MATCH: pattern, COUNT: 100 })) {\n keys.push(key);\n }\n return keys;\n }\n return this.client.keys(pattern);\n }\n\n async clear(): Promise<void> {\n const keys = await this.collectKeys(`${this.prefix}*`);\n if (keys.length > 0) {\n await this.client.del(...keys);\n }\n }\n\n /**\n * Get the actual number of keys with this prefix in Redis.\n */\n get size(): Promise<number> {\n return this.getSize();\n }\n\n /** @internal */\n private async getSize(): Promise<number> {\n const keys = await this.collectKeys(`${this.prefix}*`);\n return keys.length;\n }\n\n async keys(): Promise<string[]> {\n const raw = await this.collectKeys(`${this.prefix}*`);\n return raw.map((k) => k.slice(this.prefix.length));\n }\n\n /**\n * Remove all entries whose key matches the given pattern.\n *\n * - **String**: treated as a substring match (e.g. `\"Media\"` removes all keys containing `\"Media\"`).\n * - **RegExp**: tested against each key directly.\n *\n * @param pattern — A string (substring match) or RegExp.\n * @returns Number of entries removed.\n */\n async invalidate(pattern: string | RegExp): Promise<number> {\n if (typeof pattern === \"string\") {\n const keys = await this.collectKeys(`${this.prefix}*${pattern}*`);\n if (keys.length === 0) return 0;\n return this.client.del(...keys);\n }\n\n const allKeys = await this.collectKeys(`${this.prefix}*`);\n const matching = allKeys.filter((k) => pattern.test(k.slice(this.prefix.length)));\n if (matching.length === 0) return 0;\n return this.client.del(...matching);\n }\n}\n","/**\n * Custom error class for AniList API errors.\n */\nexport class AniListError extends Error {\n /** HTTP status code returned by the API */\n public readonly status: number;\n /** Raw error body from the API response */\n public readonly errors: unknown[];\n\n constructor(message: string, status: number, errors: unknown[] = []) {\n super(message);\n this.name = \"AniListError\";\n this.status = status;\n this.errors = errors;\n Object.setPrototypeOf(this, AniListError.prototype);\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, AniListError);\n }\n }\n}\n","/**\n * Lightweight media fields — minimal payload for list/search contexts.\n * Does NOT include tags, studios, trailer, synonyms, or nextAiringEpisode.\n */\nexport const MEDIA_FIELDS_LIGHT = `\n id\n idMal\n title { romaji english native userPreferred }\n type\n format\n status\n coverImage { large medium color }\n bannerImage\n genres\n averageScore\n popularity\n favourites\n isAdult\n siteUrl\n season\n seasonYear\n episodes\n chapters\n nextAiringEpisode {\n id\n airingAt\n episode\n timeUntilAiring\n }\n`;\n\n/** Core media fields — always returned. Does NOT include relations (opt-in via include). */\nexport const MEDIA_FIELDS_BASE = `\n id\n idMal\n title { romaji english native userPreferred }\n type\n format\n status\n description(asHtml: false)\n startDate { year month day }\n endDate { year month day }\n season\n seasonYear\n episodes\n duration\n chapters\n volumes\n countryOfOrigin\n isLicensed\n source\n hashtag\n trailer { id site thumbnail }\n coverImage { extraLarge large medium color }\n bannerImage\n genres\n synonyms\n averageScore\n meanScore\n popularity\n favourites\n trending\n tags { id name description category rank isMediaSpoiler }\n studios { nodes { id name isAnimationStudio siteUrl } }\n isAdult\n siteUrl\n nextAiringEpisode {\n id\n airingAt\n episode\n mediaId\n timeUntilAiring\n }\n`;\n\nexport const RELATIONS_FIELDS = `\n relations {\n edges {\n relationType(version: 2)\n node {\n id\n title { romaji english native userPreferred }\n type\n format\n status\n startDate { year month day }\n endDate { year month day }\n season\n seasonYear\n episodes\n chapters\n volumes\n coverImage { extraLarge large medium color }\n genres\n averageScore\n studios { nodes { id name isAnimationStudio siteUrl } }\n siteUrl\n }\n }\n }\n`;\n\n/** Full media fields with relations — used by existing queries for backward compat. */\nexport const MEDIA_FIELDS = `\n ${MEDIA_FIELDS_BASE}\n ${RELATIONS_FIELDS}\n`;\n\n/** Character fields without back-reference to media (used when embedding characters inside a Media query). */\nexport const CHARACTER_FIELDS_COMPACT = `\n id\n name { first middle last full native alternative }\n image { large medium }\n description(asHtml: false)\n gender\n dateOfBirth { year month day }\n age\n bloodType\n favourites\n siteUrl\n`;\n\nconst CHARACTER_MEDIA_NODES = `\n media(perPage: 10) {\n nodes {\n id\n title { romaji english native userPreferred }\n type\n coverImage { large medium }\n siteUrl\n }\n }\n`;\n\n/** Compact voice actor fields — lightweight subset for embedding inside character edges. */\nexport const VOICE_ACTOR_FIELDS_COMPACT = `\n id\n name { first middle last full native userPreferred }\n languageV2\n image { large medium }\n gender\n primaryOccupations\n siteUrl\n`;\n\nconst CHARACTER_MEDIA_EDGES_WITH_VA = `\n media(perPage: 10) {\n edges {\n voiceActors {\n ${VOICE_ACTOR_FIELDS_COMPACT}\n }\n node {\n id\n title { romaji english native userPreferred }\n type\n coverImage { large medium }\n siteUrl\n }\n }\n }\n`;\n\nexport const CHARACTER_FIELDS = `\n ${CHARACTER_FIELDS_COMPACT}\n ${CHARACTER_MEDIA_NODES}\n`;\n\nexport const CHARACTER_FIELDS_WITH_VA = `\n ${CHARACTER_FIELDS_COMPACT}\n ${CHARACTER_MEDIA_EDGES_WITH_VA}\n`;\n\nexport const STAFF_FIELDS = `\n id\n name { first middle last full native }\n language\n image { large medium }\n description(asHtml: false)\n primaryOccupations\n gender\n dateOfBirth { year month day }\n dateOfDeath { year month day }\n age\n yearsActive\n homeTown\n bloodType\n favourites\n siteUrl\n`;\n\nexport const STAFF_MEDIA_FIELDS = `\n staffMedia(perPage: $perPage, sort: [POPULARITY_DESC]) {\n nodes {\n id\n title { romaji english native userPreferred }\n type\n format\n status\n coverImage { extraLarge large medium color }\n bannerImage\n genres\n averageScore\n meanScore\n popularity\n favourites\n episodes\n trending\n hashtag\n season\n seasonYear\n startDate { year month day }\n endDate { year month day }\n nextAiringEpisode {\n id\n airingAt\n episode\n mediaId\n timeUntilAiring\n }\n studios {\n edges {\n node {\n name\n }\n }\n }\n siteUrl\n }\n }\n`;\n\nexport const USER_FIELDS = `\n id\n name\n about(asHtml: false)\n avatar { large medium }\n bannerImage\n isFollowing\n isFollower\n donatorTier\n donatorBadge\n createdAt\n siteUrl\n statistics {\n anime { count meanScore minutesWatched episodesWatched chaptersRead volumesRead }\n manga { count meanScore minutesWatched episodesWatched chaptersRead volumesRead }\n }\n`;\n\n/** Favorites fragment — lightweight fields for each favorite category. */\nexport const USER_FAVORITES_FIELDS = `\n favourites {\n anime(perPage: 25) {\n nodes {\n id\n title { romaji english native userPreferred }\n coverImage { large medium }\n type\n format\n siteUrl\n }\n }\n manga(perPage: 25) {\n nodes {\n id\n title { romaji english native userPreferred }\n coverImage { large medium }\n type\n format\n siteUrl\n }\n }\n characters(perPage: 25) {\n nodes {\n id\n name { full native }\n image { large medium }\n siteUrl\n }\n }\n staff(perPage: 25) {\n nodes {\n id\n name { full native }\n image { large medium }\n siteUrl\n }\n }\n studios(perPage: 25) {\n nodes {\n id\n name\n siteUrl\n }\n }\n }\n`;\n\nexport const MEDIA_LIST_FIELDS = `\n id\n mediaId\n status\n score(format: POINT_100)\n progress\n progressVolumes\n repeat\n priority\n private\n notes\n startedAt { year month day }\n completedAt { year month day }\n updatedAt\n createdAt\n media {\n ${MEDIA_FIELDS_BASE}\n }\n`;\n\nexport const STUDIO_FIELDS = `\n id\n name\n isAnimationStudio\n siteUrl\n favourites\n media(page: 1, perPage: 25, sort: POPULARITY_DESC) {\n pageInfo { total perPage currentPage lastPage hasNextPage }\n nodes {\n id\n title { romaji english native userPreferred }\n type\n format\n coverImage { large medium }\n siteUrl\n }\n }\n`;\n\nexport const THREAD_FIELDS = `\n id\n title\n body(asHtml: false)\n userId\n replyUserId\n replyCommentId\n replyCount\n viewCount\n isLocked\n isSticky\n isSubscribed\n repliedAt\n createdAt\n updatedAt\n siteUrl\n user {\n id\n name\n avatar { large medium }\n }\n replyUser {\n id\n name\n avatar { large medium }\n }\n categories {\n id\n name\n }\n mediaCategories {\n id\n title { romaji english native userPreferred }\n type\n coverImage { large medium }\n siteUrl\n }\n likes {\n id\n name\n }\n`;\n","import { MEDIA_FIELDS, MEDIA_FIELDS_BASE } from \"./fragments\";\n\nexport const QUERY_MEDIA_BY_ID = `\nquery ($id: Int!) {\n Media(id: $id) {\n ${MEDIA_FIELDS}\n }\n}`;\n\nexport const QUERY_MEDIA_SEARCH = `\nquery (\n $search: String,\n $countryOfOrigin: CountryCode,\n $type: MediaType,\n $format: MediaFormat,\n $format_in: [MediaFormat],\n $status: MediaStatus,\n $season: MediaSeason,\n $seasonYear: Int,\n $genre: String,\n $tag: String,\n $genre_in: [String],\n $tag_in: [String],\n $genre_not_in: [String],\n $tag_not_in: [String],\n $isAdult: Boolean,\n $sort: [MediaSort],\n $page: Int,\n $perPage: Int\n) {\n Page(page: $page, perPage: $perPage) {\n pageInfo { total perPage currentPage lastPage hasNextPage }\n media(\n search: $search,\n countryOfOrigin: $countryOfOrigin,\n type: $type,\n format: $format,\n format_in: $format_in,\n status: $status,\n season: $season,\n seasonYear: $seasonYear,\n genre: $genre,\n tag: $tag,\n genre_in: $genre_in,\n tag_in: $tag_in,\n genre_not_in: $genre_not_in,\n tag_not_in: $tag_not_in,\n isAdult: $isAdult,\n sort: $sort\n ) {\n ${MEDIA_FIELDS_BASE}\n }\n }\n}`;\n\nexport const QUERY_TRENDING = `\nquery ($type: MediaType, $isAdult: Boolean, $page: Int, $perPage: Int) {\n Page(page: $page, perPage: $perPage) {\n pageInfo { total perPage currentPage lastPage hasNextPage }\n media(type: $type, isAdult: $isAdult, sort: TRENDING_DESC) {\n ${MEDIA_FIELDS_BASE}\n }\n }\n}`;\n\nexport const QUERY_AIRING_SCHEDULE = `\nquery ($airingAt_greater: Int, $airingAt_lesser: Int, $isAdult: Boolean, $sort: [AiringSort], $page: Int, $perPage: Int) {\n Page(page: $page, perPage: $perPage) {\n pageInfo { total perPage currentPage lastPage hasNextPage }\n airingSchedules(airingAt_greater: $airingAt_greater, airingAt_lesser: $airingAt_lesser, sort: $sort) {\n id\n airingAt\n timeUntilAiring\n episode\n mediaId\n media(isAdult: $isAdult) {\n ${MEDIA_FIELDS_BASE}\n }\n }\n }\n}`;\n\nexport const QUERY_RECENT_CHAPTERS = `\nquery ($isAdult: Boolean $page: Int, $perPage: Int) {\n Page(page: $page, perPage: $perPage) {\n pageInfo { total perPage currentPage lastPage hasNextPage }\n media(type: MANGA, isAdult: $isAdult status: RELEASING, sort: UPDATED_AT_DESC) {\n ${MEDIA_FIELDS_BASE}\n }\n }\n}`;\n\nexport const QUERY_PLANNING = `\nquery ($type: MediaType, $isAdult: Boolean, $sort: [MediaSort], $page: Int, $perPage: Int) {\n Page(page: $page, perPage: $perPage) {\n pageInfo { total perPage currentPage lastPage hasNextPage }\n media(type: $type, isAdult: $isAdult, status: NOT_YET_RELEASED, sort: $sort) {\n ${MEDIA_FIELDS_BASE}\n }\n }\n}`;\n\nexport const QUERY_MEDIA_BY_SEASON = `\nquery (\n $season: MediaSeason!,\n $seasonYear: Int!,\n $type: MediaType,\n $isAdult: Boolean,\n $sort: [MediaSort],\n $page: Int,\n $perPage: Int\n) {\n Page(page: $page, perPage: $perPage) {\n pageInfo { total perPage currentPage lastPage hasNextPage }\n media(\n season: $season,\n seasonYear: $seasonYear,\n type: $type,\n isAdult: $isAdult,\n sort: $sort\n ) {\n ${MEDIA_FIELDS_BASE}\n }\n }\n}`;\n\nexport const QUERY_MEDIA_BY_MAL_ID = `\nquery ($idMal: Int!, $type: MediaType) {\n Media(idMal: $idMal, type: $type) {\n ${MEDIA_FIELDS}\n }\n}`;\n\nexport const QUERY_RECOMMENDATIONS = `\nquery ($mediaId: Int!, $page: Int, $perPage: Int, $sort: [RecommendationSort]) {\n Media(id: $mediaId) {\n recommendations(page: $page, perPage: $perPage, sort: $sort) {\n pageInfo { total perPage currentPage lastPage hasNextPage }\n nodes {\n id\n rating\n userRating\n mediaRecommendation {\n id\n idMal\n title { romaji english native userPreferred }\n type\n format\n status\n coverImage { extraLarge large medium color }\n bannerImage\n genres\n averageScore\n meanScore\n popularity\n favourites\n siteUrl\n }\n user {\n id\n name\n avatar { large medium }\n }\n }\n }\n }\n}`;\n","import type { MediaIncludeOptions } from \"../types\";\nimport { clampPerPage } from \"../utils\";\nimport {\n CHARACTER_FIELDS,\n CHARACTER_FIELDS_COMPACT,\n MEDIA_FIELDS,\n MEDIA_FIELDS_BASE,\n RELATIONS_FIELDS,\n STAFF_FIELDS,\n VOICE_ACTOR_FIELDS_COMPACT,\n} from \"./fragments\";\nimport { QUERY_MEDIA_BY_ID } from \"./media\";\n\n/**\n * Build a `Media(id: $id)` query that optionally includes characters, staff,\n * relations, streaming episodes, external links, stats, and recommendations.\n *\n * When no include options are given, the query is identical to QUERY_MEDIA_BY_ID.\n *\n * @internal\n */\nexport function buildMediaByIdQuery(include?: MediaIncludeOptions): string {\n if (!include) return QUERY_MEDIA_BY_ID;\n\n const extra: string[] = [];\n\n if (include.relations !== false) {\n extra.push(RELATIONS_FIELDS);\n }\n\n if (include.characters) {\n const opts = typeof include.characters === \"object\" ? include.characters : {};\n const perPage = clampPerPage(opts.perPage ?? 25);\n const sortClause = opts.sort !== false ? \", sort: [ROLE, RELEVANCE, ID]\" : \"\";\n const voiceActorBlock = opts.voiceActors\n ? `\\n voiceActors {\n ${VOICE_ACTOR_FIELDS_COMPACT}\n }`\n : \"\";\n extra.push(`\n characters(perPage: ${perPage}${sortClause}) {\n edges {\n role\n node {\n ${CHARACTER_FIELDS_COMPACT}\n }${voiceActorBlock}\n }\n }`);\n }\n\n if (include.staff) {\n const opts = typeof include.staff === \"object\" ? include.staff : {};\n const perPage = clampPerPage(opts.perPage ?? 25);\n const sortClause = opts.sort !== false ? \", sort: [RELEVANCE, ID]\" : \"\";\n extra.push(`\n staff(perPage: ${perPage}${sortClause}) {\n edges {\n role\n node {\n ${STAFF_FIELDS}\n }\n }\n }`);\n }\n\n if (include.recommendations) {\n const perPage = clampPerPage(\n typeof include.recommendations === \"object\" ? (include.recommendations.perPage ?? 10) : 10,\n );\n extra.push(`\n recommendations(perPage: ${perPage}, sort: [RATING_DESC]) {\n nodes {\n id\n rating\n mediaRecommendation {\n id\n title { romaji english native userPreferred }\n type\n format\n coverImage { large medium }\n averageScore\n siteUrl\n }\n }\n }`);\n }\n\n if (include.streamingEpisodes) {\n extra.push(`\n streamingEpisodes {\n title\n thumbnail\n url\n site\n }`);\n }\n\n if (include.externalLinks) {\n extra.push(`\n externalLinks {\n id\n url\n site\n type\n icon\n color\n }`);\n }\n\n if (include.stats) {\n extra.push(`\n stats {\n scoreDistribution { score amount }\n statusDistribution { status amount }\n }`);\n }\n\n return `\nquery ($id: Int!) {\n Media(id: $id) {\n ${MEDIA_FIELDS_BASE}\n ${extra.join(\"\\n\")}\n }\n}`;\n}\n\n/** @internal Build a batched GraphQL query using aliases. */\nfunction buildBatchQuery(ids: number[], typeName: string, fields: string, prefix: string): string {\n const aliases = ids.map((id, i) => `${prefix}${i}: ${typeName}(id: ${id}) { ${fields} }`).join(\"\\n \");\n return `query {\\n ${aliases}\\n}`;\n}\n\nexport const buildBatchMediaQuery = (ids: number[]): string => buildBatchQuery(ids, \"Media\", MEDIA_FIELDS, \"m\");\n\nexport const buildBatchCharacterQuery = (ids: number[]): string =>\n buildBatchQuery(ids, \"Character\", CHARACTER_FIELDS, \"c\");\n\nexport const buildBatchStaffQuery = (ids: number[]): string => buildBatchQuery(ids, \"Staff\", STAFF_FIELDS, \"s\");\n","import { CHARACTER_FIELDS, CHARACTER_FIELDS_WITH_VA } from \"./fragments\";\n\nexport const QUERY_CHARACTER_BY_ID = `\nquery ($id: Int!) {\n Character(id: $id) {\n ${CHARACTER_FIELDS}\n }\n}`;\n\nexport const QUERY_CHARACTER_BY_ID_WITH_VA = `\nquery ($id: Int!) {\n Character(id: $id) {\n ${CHARACTER_FIELDS_WITH_VA}\n }\n}`;\n\nexport const QUERY_CHARACTER_SEARCH = `\nquery ($search: String, $sort: [CharacterSort], $page: Int, $perPage: Int) {\n Page(page: $page, perPage: $perPage) {\n pageInfo { total perPage currentPage lastPage hasNextPage }\n characters(search: $search, sort: $sort) {\n ${CHARACTER_FIELDS}\n }\n }\n}`;\n\nexport const QUERY_CHARACTER_SEARCH_WITH_VA = `\nquery ($search: String, $sort: [CharacterSort], $page: Int, $perPage: Int) {\n Page(page: $page, perPage: $perPage) {\n pageInfo { total perPage currentPage lastPage hasNextPage }\n characters(search: $search, sort: $sort) {\n ${CHARACTER_FIELDS_WITH_VA}\n }\n }\n}`;\n","export const QUERY_GENRES = `\nquery {\n GenreCollection\n}`;\n\nexport const QUERY_TAGS = `\nquery {\n MediaTagCollection {\n id\n name\n description\n category\n isAdult\n }\n}`;\n","import { STAFF_FIELDS, STAFF_MEDIA_FIELDS } from \"./fragments\";\n\nexport const QUERY_STAFF_BY_ID = `\nquery ($id: Int!) {\n Staff(id: $id) {\n ${STAFF_FIELDS}\n }\n}`;\n\nexport const QUERY_STAFF_BY_ID_WITH_MEDIA = `\nquery ($id: Int!, $perPage: Int) {\n Staff(id: $id) {\n ${STAFF_FIELDS}\n ${STAFF_MEDIA_FIELDS}\n }\n}`;\n\nexport const QUERY_STAFF_SEARCH = `\nquery ($search: String, $sort: [StaffSort], $page: Int, $perPage: Int) {\n Page(page: $page, perPage: $perPage) {\n pageInfo { total perPage currentPage lastPage hasNextPage }\n staff(search: $search, sort: $sort) {\n ${STAFF_FIELDS}\n }\n }\n}`;\n","import { clampPerPage } from \"../utils\";\nimport { MEDIA_FIELDS_LIGHT, STUDIO_FIELDS } from \"./fragments\";\n\nexport const QUERY_STUDIO_BY_ID = `\nquery ($id: Int!) {\n Studio(id: $id) {\n ${STUDIO_FIELDS}\n }\n}`;\n\n/**\n * Build a Studio-by-ID query with customisable media perPage.\n * @internal\n */\nexport function buildStudioByIdQuery(mediaPerPage?: number): string {\n if (mediaPerPage === undefined) return QUERY_STUDIO_BY_ID;\n const pp = clampPerPage(mediaPerPage);\n return `\nquery ($id: Int!) {\n Studio(id: $id) {\n id\n name\n isAnimationStudio\n siteUrl\n favourites\n media(page: 1, perPage: ${pp}, sort: POPULARITY_DESC) {\n pageInfo { total perPage currentPage lastPage hasNextPage }\n nodes {\n ${MEDIA_FIELDS_LIGHT}\n }\n }\n }\n}`;\n}\n\nexport const QUERY_STUDIO_SEARCH = `\nquery ($search: String, $sort: [StudioSort], $page: Int, $perPage: Int) {\n Page(page: $page, perPage: $perPage) {\n pageInfo { total perPage currentPage lastPage hasNextPage }\n studios(search: $search, sort: $sort) {\n ${STUDIO_FIELDS}\n }\n }\n}`;\n","import { THREAD_FIELDS } from \"./fragments\";\n\nexport const QUERY_THREAD_BY_ID = `\nquery ($id: Int!) {\n Thread(id: $id) {\n ${THREAD_FIELDS}\n }\n}`;\n\nexport const QUERY_THREAD_SEARCH = `\nquery ($search: String, $mediaCategoryId: Int, $categoryId: Int, $sort: [ThreadSort], $page: Int, $perPage: Int) {\n Page(page: $page, perPage: $perPage) {\n pageInfo { total perPage currentPage lastPage hasNextPage }\n threads(search: $search, mediaCategoryId: $mediaCategoryId, categoryId: $categoryId, sort: $sort) {\n ${THREAD_FIELDS}\n }\n }\n}`;\n","import { clampPerPage } from \"../utils\";\nimport { MEDIA_LIST_FIELDS, USER_FAVORITES_FIELDS, USER_FIELDS } from \"./fragments\";\n\nexport const QUERY_USER_BY_ID = `\nquery ($id: Int!) {\n User(id: $id) {\n ${USER_FIELDS}\n }\n}`;\n\nexport const QUERY_USER_BY_NAME = `\nquery ($name: String!) {\n User(name: $name) {\n ${USER_FIELDS}\n }\n}`;\n\nexport const QUERY_USER_SEARCH = `\nquery ($search: String, $sort: [UserSort], $page: Int, $perPage: Int) {\n Page(page: $page, perPage: $perPage) {\n pageInfo { total perPage currentPage lastPage hasNextPage }\n users(search: $search, sort: $sort) {\n ${USER_FIELDS}\n }\n }\n}`;\n\nexport const QUERY_USER_MEDIA_LIST = `\nquery ($userId: Int, $userName: String, $type: MediaType!, $status: MediaListStatus, $sort: [MediaListSort], $page: Int, $perPage: Int) {\n Page(page: $page, perPage: $perPage) {\n pageInfo { total perPage currentPage lastPage hasNextPage }\n mediaList(userId: $userId, userName: $userName, type: $type, status: $status, sort: $sort) {\n ${MEDIA_LIST_FIELDS}\n }\n }\n}`;\n\nexport const QUERY_USER_FAVORITES_BY_ID = `\nquery ($id: Int!) {\n User(id: $id) {\n id\n name\n ${USER_FAVORITES_FIELDS}\n }\n}`;\n\nexport const QUERY_USER_FAVORITES_BY_NAME = `\nquery ($name: String!) {\n User(name: $name) {\n id\n name\n ${USER_FAVORITES_FIELDS}\n }\n}`;\n\n/**\n * Build a User Favorites query with customisable perPage per category.\n * @internal\n */\nexport function buildUserFavoritesQuery(idOrName: \"id\" | \"name\", perPage = 25): string {\n const pp = clampPerPage(perPage);\n const varDecl = idOrName === \"id\" ? \"$id: Int!\" : \"$name: String!\";\n const selector = idOrName === \"id\" ? \"id: $id\" : \"name: $name\";\n return `\nquery (${varDecl}) {\n User(${selector}) {\n id\n name\n favourites {\n anime(perPage: ${pp}) {\n nodes {\n id\n title { romaji english native userPreferred }\n coverImage { large medium }\n type\n format\n siteUrl\n }\n }\n manga(perPage: ${pp}) {\n nodes {\n id\n title { romaji english native userPreferred }\n coverImage { large medium }\n type\n format\n siteUrl\n }\n }\n characters(perPage: ${pp}) {\n nodes {\n id\n name { full native }\n image { large medium }\n siteUrl\n }\n }\n staff(perPage: ${pp}) {\n nodes {\n id\n name { full native }\n image { large medium }\n siteUrl\n }\n }\n studios(perPage: ${pp}) {\n nodes {\n id\n name\n siteUrl\n }\n }\n }\n }\n}`;\n}\n","/**\n * Rate limiter with automatic retry for AniList API.\n *\n * AniList allows 30 requests per minute.\n * When a 429 (Too Many Requests) is received, the client\n * waits for the Retry-After header and retries automatically.\n */\n\nimport type { RateLimitOptions } from \"../types\";\n\nexport type { RateLimitOptions };\n\nexport class RateLimiter {\n private readonly maxRequests: number;\n private readonly windowMs: number;\n private readonly maxRetries: number;\n private readonly retryDelayMs: number;\n private readonly enabled: boolean;\n private readonly timeoutMs: number;\n private readonly retryOnNetworkError: boolean;\n private readonly retryStrategy?: (attempt: number, baseDelayMs: number) => number;\n\n /** @internal — sliding window: circular buffer of timestamps */\n private readonly timestamps: number[];\n private head = 0;\n private count = 0;\n /** @internal — active sleep timers for cleanup */\n private readonly activeTimers = new Set<ReturnType<typeof setTimeout>>();\n\n constructor(options: RateLimitOptions = {}) {\n this.maxRequests = options.maxRequests ?? 25;\n this.windowMs = options.windowMs ?? 60_000;\n this.maxRetries = options.maxRetries ?? 3;\n this.retryDelayMs = options.retryDelayMs ?? 2_000;\n this.enabled = options.enabled ?? true;\n this.timeoutMs = options.timeoutMs ?? 30_000;\n this.retryOnNetworkError = options.retryOnNetworkError ?? true;\n this.retryStrategy = options.retryStrategy;\n this.timestamps = new Array<number>(this.maxRequests).fill(0);\n }\n\n /**\n * Wait until it's safe to make a request (respects rate limit window).\n */\n async acquire(): Promise<void> {\n if (!this.enabled) return;\n\n if (this.count >= this.maxRequests) {\n const oldest = this.timestamps[this.head] as number;\n const elapsed = Date.now() - oldest;\n if (elapsed < this.windowMs) {\n const waitMs = this.windowMs - elapsed + 50;\n await this.sleep(waitMs);\n }\n }\n\n const now = Date.now();\n if (this.count < this.maxRequests) {\n this.timestamps[(this.head + this.count) % this.maxRequests] = now;\n this.count++;\n } else {\n this.timestamps[this.head] = now;\n this.head = (this.head + 1) % this.maxRequests;\n }\n }\n\n /**\n * Execute a fetch with automatic retry on 429 responses and network errors.\n * Uses exponential backoff with jitter for retry delays.\n */\n async fetchWithRetry(\n url: string,\n init: RequestInit,\n hooks?: {\n onRetry?: (attempt: number, reason: string, delayMs: number) => void;\n onRateLimit?: (retryAfterMs: number) => void;\n },\n ): Promise<Response> {\n await this.acquire();\n\n let lastResponse: Response | undefined;\n let lastError: unknown;\n\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n try {\n const res = await this.fetchWithTimeout(url, init);\n\n if (res.status !== 429) return res;\n\n lastResponse = res;\n if (attempt === this.maxRetries) break;\n\n const retryAfter = res.headers.get(\"Retry-After\");\n const delayMs = retryAfter ? Number.parseInt(retryAfter, 10) * 1000 : this.exponentialDelay(attempt);\n\n hooks?.onRateLimit?.(delayMs);\n hooks?.onRetry?.(attempt + 1, \"HTTP 429\", delayMs);\n\n await this.sleep(delayMs);\n await this.acquire();\n } catch (err) {\n lastError = err;\n\n if (this.retryOnNetworkError && isNetworkError(err) && attempt < this.maxRetries) {\n const delayMs = this.exponentialDelay(attempt);\n hooks?.onRetry?.(attempt + 1, `Network error: ${(err as Error).message}`, delayMs);\n await this.sleep(delayMs);\n await this.acquire();\n continue;\n }\n\n throw err;\n }\n }\n\n if (lastResponse) return lastResponse;\n /* v8 ignore next -- defensive fallback; unreachable in normal control flow */\n throw lastError ?? new Error(`Request failed after ${this.maxRetries} retries`);\n }\n\n /** @internal — Exponential backoff with jitter, capped at 30s (or custom strategy) */\n private exponentialDelay(attempt: number): number {\n if (this.retryStrategy) {\n return this.retryStrategy(attempt, this.retryDelayMs);\n }\n const base = this.retryDelayMs * 2 ** attempt;\n const jitter = Math.random() * 1000;\n return Math.min(base + jitter, 30_000);\n }\n\n /** @internal */\n private async fetchWithTimeout(url: string, init: RequestInit): Promise<Response> {\n if (this.timeoutMs <= 0) return fetch(url, init);\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeoutMs);\n\n const signals = [controller.signal, init.signal].filter(Boolean) as AbortSignal[];\n const combinedSignal = signals.length > 1 ? AbortSignal.any(signals) : signals[0];\n\n try {\n return await fetch(url, { ...init, signal: combinedSignal });\n } finally {\n clearTimeout(timer);\n }\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => {\n const timer = setTimeout(() => {\n this.activeTimers.delete(timer);\n resolve();\n }, ms);\n this.activeTimers.add(timer);\n });\n }\n\n /** Cancel all pending sleep timers and reset internal state. */\n dispose(): void {\n for (const timer of this.activeTimers) {\n clearTimeout(timer);\n }\n this.activeTimers.clear();\n this.head = 0;\n this.count = 0;\n this.timestamps.fill(0);\n }\n}\n\n/** Set of Node.js error codes that indicate a transient network failure. */\nconst RETRYABLE_NETWORK_CODES = new Set([\n \"ECONNRESET\",\n \"ECONNREFUSED\",\n \"ETIMEDOUT\",\n \"ENOTFOUND\",\n \"EAI_AGAIN\",\n \"UND_ERR_CONNECT_TIMEOUT\",\n \"UND_ERR_SOCKET\",\n]);\n\n/** @internal */\nfunction isNetworkError(err: unknown): boolean {\n if (err instanceof TypeError && err.message === \"fetch failed\") return true;\n const code = (err as NodeJS.ErrnoException)?.code;\n if (code && RETRYABLE_NETWORK_CODES.has(code)) return true;\n const cause = (err as { cause?: { code?: string } })?.cause?.code;\n if (cause && RETRYABLE_NETWORK_CODES.has(cause)) return true;\n return false;\n}\n","import {\n QUERY_CHARACTER_BY_ID,\n QUERY_CHARACTER_BY_ID_WITH_VA,\n QUERY_CHARACTER_SEARCH,\n QUERY_CHARACTER_SEARCH_WITH_VA,\n} from \"../queries\";\n\nimport type { Character, CharacterIncludeOptions, PagedResult, SearchCharacterOptions } from \"../types\";\n\nimport { clampPerPage, validateId } from \"../utils\";\nimport type { ClientBase } from \"./base\";\n\nexport async function getCharacter(\n client: ClientBase,\n id: number,\n include?: CharacterIncludeOptions,\n): Promise<Character> {\n validateId(id, \"characterId\");\n const query = include?.voiceActors ? QUERY_CHARACTER_BY_ID_WITH_VA : QUERY_CHARACTER_BY_ID;\n const data = await client.request<{ Character: Character }>(query, { id });\n return data.Character;\n}\n\nexport async function searchCharacters(\n client: ClientBase,\n options: SearchCharacterOptions = {},\n): Promise<PagedResult<Character>> {\n const { query: search, page = 1, perPage = 20, sort, voiceActors } = options;\n const gqlQuery = voiceActors ? QUERY_CHARACTER_SEARCH_WITH_VA : QUERY_CHARACTER_SEARCH;\n return client.pagedRequest<Character>(gqlQuery, { search, sort, page, perPage: clampPerPage(perPage) }, \"characters\");\n}\n","import type { FuzzyDate } from \"./common\";\nimport type { Media } from \"./media\";\nimport type { VoiceActor } from \"./staff\";\n\nexport enum CharacterSort {\n ID = \"ID\",\n ID_DESC = \"ID_DESC\",\n ROLE = \"ROLE\",\n ROLE_DESC = \"ROLE_DESC\",\n SEARCH_MATCH = \"SEARCH_MATCH\",\n FAVOURITES = \"FAVOURITES\",\n FAVOURITES_DESC = \"FAVOURITES_DESC\",\n}\n\nexport enum CharacterRole {\n MAIN = \"MAIN\",\n SUPPORTING = \"SUPPORTING\",\n BACKGROUND = \"BACKGROUND\",\n}\n\nexport interface CharacterName {\n first: string | null;\n middle: string | null;\n last: string | null;\n full: string | null;\n native: string | null;\n alternative: string[];\n}\n\nexport interface CharacterImage {\n large: string | null;\n medium: string | null;\n}\n\nexport type CharacterMediaNode = Pick<Media, \"id\" | \"title\" | \"type\" | \"coverImage\" | \"siteUrl\">;\n\nexport interface CharacterMediaEdge {\n node: CharacterMediaNode;\n voiceActors?: VoiceActor[];\n}\n\nexport interface Character {\n id: number;\n name: CharacterName;\n image: CharacterImage;\n description: string | null;\n gender: string | null;\n dateOfBirth: FuzzyDate | null;\n age: string | null;\n bloodType: string | null;\n favourites: number | null;\n siteUrl: string | null;\n media: {\n nodes?: CharacterMediaNode[];\n edges?: CharacterMediaEdge[];\n } | null;\n}\n\n/** Options for including extra data when fetching a character. */\nexport interface CharacterIncludeOptions {\n /** Include voice actors for each media the character appears in. */\n voiceActors?: boolean;\n}\n\nexport interface SearchCharacterOptions {\n query?: string;\n sort?: CharacterSort[];\n page?: number;\n perPage?: number;\n /** Include voice actors for each media the character appears in. */\n voiceActors?: boolean;\n}\n","import type { FuzzyDate } from \"./common\";\nimport type { Media, MediaType } from \"./media\";\n\nexport enum MediaListStatus {\n CURRENT = \"CURRENT\",\n PLANNING = \"PLANNING\",\n COMPLETED = \"COMPLETED\",\n DROPPED = \"DROPPED\",\n PAUSED = \"PAUSED\",\n REPEATING = \"REPEATING\",\n}\n\nexport enum MediaListSort {\n MEDIA_ID = \"MEDIA_ID\",\n MEDIA_ID_DESC = \"MEDIA_ID_DESC\",\n SCORE = \"SCORE\",\n SCORE_DESC = \"SCORE_DESC\",\n STATUS = \"STATUS\",\n STATUS_DESC = \"STATUS_DESC\",\n PROGRESS = \"PROGRESS\",\n PROGRESS_DESC = \"PROGRESS_DESC\",\n PROGRESS_VOLUMES = \"PROGRESS_VOLUMES\",\n PROGRESS_VOLUMES_DESC = \"PROGRESS_VOLUMES_DESC\",\n REPEAT = \"REPEAT\",\n REPEAT_DESC = \"REPEAT_DESC\",\n PRIORITY = \"PRIORITY\",\n PRIORITY_DESC = \"PRIORITY_DESC\",\n STARTED_ON = \"STARTED_ON\",\n STARTED_ON_DESC = \"STARTED_ON_DESC\",\n FINISHED_ON = \"FINISHED_ON\",\n FINISHED_ON_DESC = \"FINISHED_ON_DESC\",\n ADDED_TIME = \"ADDED_TIME\",\n ADDED_TIME_DESC = \"ADDED_TIME_DESC\",\n UPDATED_TIME = \"UPDATED_TIME\",\n UPDATED_TIME_DESC = \"UPDATED_TIME_DESC\",\n MEDIA_TITLE_ROMAJI = \"MEDIA_TITLE_ROMAJI\",\n MEDIA_TITLE_ROMAJI_DESC = \"MEDIA_TITLE_ROMAJI_DESC\",\n MEDIA_TITLE_ENGLISH = \"MEDIA_TITLE_ENGLISH\",\n MEDIA_TITLE_ENGLISH_DESC = \"MEDIA_TITLE_ENGLISH_DESC\",\n MEDIA_TITLE_NATIVE = \"MEDIA_TITLE_NATIVE\",\n MEDIA_TITLE_NATIVE_DESC = \"MEDIA_TITLE_NATIVE_DESC\",\n MEDIA_POPULARITY = \"MEDIA_POPULARITY\",\n MEDIA_POPULARITY_DESC = \"MEDIA_POPULARITY_DESC\",\n}\n\nexport interface MediaListEntry {\n id: number;\n mediaId: number;\n status: MediaListStatus;\n score: number | null;\n progress: number | null;\n progressVolumes: number | null;\n repeat: number | null;\n priority: number | null;\n private: boolean | null;\n notes: string | null;\n startedAt: FuzzyDate | null;\n completedAt: FuzzyDate | null;\n updatedAt: number | null;\n createdAt: number | null;\n media: Media;\n}\n\nexport interface GetUserMediaListOptions {\n /** User ID (provide either userId or userName) */\n userId?: number;\n /** Username (provide either userId or userName) */\n userName?: string;\n /** ANIME or MANGA */\n type: MediaType;\n /** Filter by list status (CURRENT, COMPLETED, etc.) */\n status?: MediaListStatus;\n /** Sort order */\n sort?: MediaListSort[];\n page?: number;\n perPage?: number;\n}\n","import type { Character, CharacterRole } from \"./character\";\nimport type { ExternalLink, FuzzyDate } from \"./common\";\nimport type { MediaListStatus } from \"./lists\";\nimport type { Staff, VoiceActor } from \"./staff\";\nimport type { StudioConnection } from \"./studio\";\nimport type { UserAvatar } from \"./user\";\n\nexport enum MediaType {\n ANIME = \"ANIME\",\n MANGA = \"MANGA\",\n}\n\nexport enum MediaSource {\n ORIGINAL = \"ORIGINAL\",\n MANGA = \"MANGA\",\n LIGHT_NOVEL = \"LIGHT_NOVEL\",\n VISUAL_NOVEL = \"VISUAL_NOVEL\",\n VIDEO_GAME = \"VIDEO_GAME\",\n OTHER = \"OTHER\",\n NOVEL = \"NOVEL\",\n DOUJINSHI = \"DOUJINSHI\",\n ANIME = \"ANIME\",\n WEB_NOVEL = \"WEB_NOVEL\",\n LIVE_ACTION = \"LIVE_ACTION\",\n GAME = \"GAME\",\n COMIC = \"COMIC\",\n MULTIMEDIA_PROJECT = \"MULTIMEDIA_PROJECT\",\n PICTURE_BOOK = \"PICTURE_BOOK\",\n}\n\nexport enum MediaFormat {\n TV = \"TV\",\n TV_SHORT = \"TV_SHORT\",\n MOVIE = \"MOVIE\",\n SPECIAL = \"SPECIAL\",\n OVA = \"OVA\",\n ONA = \"ONA\",\n MUSIC = \"MUSIC\",\n MANGA = \"MANGA\",\n NOVEL = \"NOVEL\",\n ONE_SHOT = \"ONE_SHOT\",\n}\n\nexport enum MediaStatus {\n FINISHED = \"FINISHED\",\n RELEASING = \"RELEASING\",\n NOT_YET_RELEASED = \"NOT_YET_RELEASED\",\n CANCELLED = \"CANCELLED\",\n HIATUS = \"HIATUS\",\n}\n\nexport enum MediaSeason {\n WINTER = \"WINTER\",\n SPRING = \"SPRING\",\n SUMMER = \"SUMMER\",\n FALL = \"FALL\",\n}\n\nexport enum MediaSort {\n ID = \"ID\",\n ID_DESC = \"ID_DESC\",\n TITLE_ROMAJI = \"TITLE_ROMAJI\",\n TITLE_ROMAJI_DESC = \"TITLE_ROMAJI_DESC\",\n TITLE_ENGLISH = \"TITLE_ENGLISH\",\n TITLE_ENGLISH_DESC = \"TITLE_ENGLISH_DESC\",\n TITLE_NATIVE = \"TITLE_NATIVE\",\n TITLE_NATIVE_DESC = \"TITLE_NATIVE_DESC\",\n TYPE = \"TYPE\",\n TYPE_DESC = \"TYPE_DESC\",\n FORMAT = \"FORMAT\",\n FORMAT_DESC = \"FORMAT_DESC\",\n START_DATE = \"START_DATE\",\n START_DATE_DESC = \"START_DATE_DESC\",\n END_DATE = \"END_DATE\",\n END_DATE_DESC = \"END_DATE_DESC\",\n SCORE = \"SCORE\",\n SCORE_DESC = \"SCORE_DESC\",\n POPULARITY = \"POPULARITY\",\n POPULARITY_DESC = \"POPULARITY_DESC\",\n TRENDING = \"TRENDING\",\n TRENDING_DESC = \"TRENDING_DESC\",\n EPISODES = \"EPISODES\",\n EPISODES_DESC = \"EPISODES_DESC\",\n DURATION = \"DURATION\",\n DURATION_DESC = \"DURATION_DESC\",\n STATUS = \"STATUS\",\n STATUS_DESC = \"STATUS_DESC\",\n FAVOURITES = \"FAVOURITES\",\n FAVOURITES_DESC = \"FAVOURITES_DESC\",\n UPDATED_AT = \"UPDATED_AT\",\n UPDATED_AT_DESC = \"UPDATED_AT_DESC\",\n SEARCH_MATCH = \"SEARCH_MATCH\",\n}\n\nexport enum AiringSort {\n ID = \"ID\",\n ID_DESC = \"ID_DESC\",\n MEDIA_ID = \"MEDIA_ID\",\n MEDIA_ID_DESC = \"MEDIA_ID_DESC\",\n TIME = \"TIME\",\n TIME_DESC = \"TIME_DESC\",\n EPISODE = \"EPISODE\",\n EPISODE_DESC = \"EPISODE_DESC\",\n}\n\nexport interface MediaTitle {\n romaji: string | null;\n english: string | null;\n native: string | null;\n userPreferred: string | null;\n}\n\nexport interface MediaCoverImage {\n extraLarge: string | null;\n large: string | null;\n medium: string | null;\n color: string | null;\n}\n\nexport interface MediaTrailer {\n id: string | null;\n site: string | null;\n thumbnail: string | null;\n}\n\nexport interface MediaTag {\n id: number;\n name: string;\n description: string | null;\n category: string | null;\n rank: number | null;\n isAdult: boolean | null;\n isMediaSpoiler: boolean | null;\n}\n\nexport enum MediaRelationType {\n ADAPTATION = \"ADAPTATION\",\n PREQUEL = \"PREQUEL\",\n SEQUEL = \"SEQUEL\",\n PARENT = \"PARENT\",\n SIDE_STORY = \"SIDE_STORY\",\n CHARACTER = \"CHARACTER\",\n SUMMARY = \"SUMMARY\",\n ALTERNATIVE = \"ALTERNATIVE\",\n SPIN_OFF = \"SPIN_OFF\",\n OTHER = \"OTHER\",\n SOURCE = \"SOURCE\",\n COMPILATION = \"COMPILATION\",\n CONTAINS = \"CONTAINS\",\n}\n\nexport interface MediaEdge {\n relationType: MediaRelationType;\n node: Pick<Media, \"id\" | \"title\" | \"type\" | \"format\" | \"status\" | \"coverImage\" | \"siteUrl\">;\n}\n\nexport interface MediaConnection {\n edges: MediaEdge[];\n}\n\nexport interface MediaCharacterEdge {\n role: CharacterRole;\n node: Omit<Character, \"media\">;\n voiceActors?: VoiceActor[];\n}\n\nexport interface MediaCharacterConnection {\n edges: MediaCharacterEdge[];\n}\n\nexport interface MediaStaffEdge {\n role: string;\n node: Staff;\n}\n\nexport interface MediaStaffConnection {\n edges: MediaStaffEdge[];\n}\n\nexport interface StreamingEpisode {\n title: string | null;\n thumbnail: string | null;\n url: string | null;\n site: string | null;\n}\n\nexport interface ScoreDistribution {\n score: number;\n amount: number;\n}\n\nexport interface StatusDistribution {\n status: MediaListStatus;\n amount: number;\n}\n\nexport interface MediaStats {\n scoreDistribution: ScoreDistribution[];\n statusDistribution: StatusDistribution[];\n}\n\nexport interface MediaRecommendationNode {\n id: number;\n rating: number | null;\n mediaRecommendation: Pick<Media, \"id\" | \"title\" | \"type\" | \"format\" | \"coverImage\" | \"averageScore\" | \"siteUrl\">;\n}\n\nexport interface NextAiringEpisode {\n id: number;\n airingAt: number;\n episode: number;\n mediaId: number;\n timeUntilAiring: number;\n}\n\nexport interface Media {\n id: number;\n idMal: number | null;\n title: MediaTitle;\n type: MediaType;\n format: MediaFormat | null;\n status: MediaStatus | null;\n description: string | null;\n startDate: FuzzyDate | null;\n endDate: FuzzyDate | null;\n season: MediaSeason | null;\n seasonYear: number | null;\n episodes: number | null;\n duration: number | null;\n chapters: number | null;\n volumes: number | null;\n countryOfOrigin: string | null;\n isLicensed: boolean | null;\n source: MediaSource | null;\n hashtag: string | null;\n trailer: MediaTrailer | null;\n coverImage: MediaCoverImage;\n bannerImage: string | null;\n genres: string[];\n synonyms: string[];\n averageScore: number | null;\n meanScore: number | null;\n popularity: number | null;\n favourites: number | null;\n trending: number | null;\n tags: MediaTag[];\n studios: StudioConnection;\n relations: MediaConnection | null;\n characters?: MediaCharacterConnection;\n staff?: MediaStaffConnection;\n streamingEpisodes?: StreamingEpisode[];\n externalLinks?: ExternalLink[];\n stats?: MediaStats;\n recommendations?: { nodes: MediaRecommendationNode[] };\n nextAiringEpisode: NextAiringEpisode | null;\n isAdult: boolean | null;\n siteUrl: string | null;\n}\n\nexport interface SearchMediaOptions {\n /** Search Term */\n query?: string;\n /** Filter by country code (e.g., \"JP\", \"KR\") */\n countryOfOrigin?: string;\n /** Filter by Anime or Manga */\n type?: MediaType;\n /** Filter by format (For multiple formats: [MediaFormat.TV]) */\n format?: MediaFormat | MediaFormat[];\n /** Filter by status of Media */\n status?: MediaStatus;\n /** Filter by Season (Winter, Spring, Summer, Fall) */\n season?: MediaSeason;\n /** Filter by Year */\n seasonYear?: number;\n /** Single genre filter (kept for backward compat) */\n genre?: string;\n /** Single tag filter (kept for backward compat) */\n tag?: string;\n /** Filter by multiple genres (media must match ALL) */\n genres?: string[];\n /** Filter by multiple tags (media must match ALL) */\n tags?: string[];\n /** Exclude media with any of these genres */\n genresExclude?: string[];\n /** Exclude media with any of these tags */\n tagsExclude?: string[];\n /** Include or Exclude explicit content (default: false) */\n isAdult?: boolean;\n /** Sort order */\n sort?: MediaSort[];\n /** Page number */\n page?: number;\n /** Results per page (max 50) */\n perPage?: number;\n}\n\nexport interface GeneralMediaQueryOptions {\n /** Filter by Anime or Manga */\n type?: MediaType;\n /** Include or Exclude explicit content (default: false) */\n isAdult?: boolean;\n /** Page number */\n page?: number;\n /** Results per page (max 50) */\n perPage?: number;\n}\n\nexport interface GetAiringOptions {\n /** Only show episodes that aired after this UNIX timestamp */\n airingAtGreater?: number;\n /** Only show episodes that aired before this UNIX timestamp */\n airingAtLesser?: number;\n /** Include or Exclude explicit content (default: false) */\n isAdult?: boolean;\n /** Sort order (default: TIME_DESC) */\n sort?: AiringSort[];\n /** Page number */\n page?: number;\n /** Results per page (max 50) */\n perPage?: number;\n}\n\nexport interface GetRecentChaptersOptions {\n /** Include or Exclude explicit content (default: false) */\n isAdult?: boolean;\n /** Page number (default: 1) */\n page?: number;\n /** Results per page (default: 20, max 50) */\n perPage?: number;\n}\n\nexport interface GetPlanningOptions {\n /** Filter by ANIME or MANGA (returns both if omitted) */\n type?: MediaType;\n /** Include or Exclude explicit content (default: false) */\n isAdult?: boolean;\n /** Sort order (default: POPULARITY_DESC) */\n sort?: MediaSort[];\n /** Page number */\n page?: number;\n /** Results per page (max 50) */\n perPage?: number;\n}\n\nexport enum RecommendationSort {\n ID = \"ID\",\n ID_DESC = \"ID_DESC\",\n RATING = \"RATING\",\n RATING_DESC = \"RATING_DESC\",\n}\n\nexport interface Recommendation {\n id: number;\n rating: number | null;\n userRating: string | null;\n mediaRecommendation: Media;\n user: {\n id: number;\n name: string;\n avatar: UserAvatar;\n } | null;\n}\n\nexport interface GetRecommendationsOptions {\n /** The AniList media ID to get recommendations for */\n mediaId: number;\n /** Sort order (default: RATING_DESC) */\n sort?: RecommendationSort[];\n /** Page number */\n page?: number;\n /** Results per page (max 50) */\n perPage?: number;\n}\n\nexport interface GetSeasonOptions {\n /** The season (WINTER, SPRING, SUMMER, FALL) */\n season: MediaSeason;\n /** The year */\n seasonYear: number;\n /** Filter by ANIME or MANGA (defaults to ANIME) */\n type?: MediaType;\n /** Allow or disallow explicit content (defaults to False) */\n isAdult?: boolean;\n /** Sort order (default: POPULARITY_DESC) */\n sort?: MediaSort[];\n /** Page number */\n page?: number;\n /** Results per page (max 50) */\n perPage?: number;\n}\n\n/**\n * Options to include additional related data when fetching a media entry.\n * Pass `true` to include with defaults, or an object to customize.\n */\nexport interface MediaIncludeOptions {\n /** Include characters with their roles (MAIN, SUPPORTING, BACKGROUND).\n * `true` = 25 results sorted by role. Object form to customize. */\n characters?: boolean | { perPage?: number; sort?: boolean; voiceActors?: boolean };\n /** Include staff members with their roles.\n * `true` = 25 results sorted by relevance. Object form to customize. */\n staff?: boolean | { perPage?: number; sort?: boolean };\n /** Include relations (default: `true` for backward compat). Set to `false` to exclude. */\n relations?: boolean;\n /** Include streaming episode links (Crunchyroll, Funimation, etc.) */\n streamingEpisodes?: boolean;\n /** Include external links (MAL, official site, etc.) */\n externalLinks?: boolean;\n /** Include score & status distribution stats */\n stats?: boolean;\n /** Include user recommendations. `true` = 10 results, or customize with `{ perPage }`. */\n recommendations?: boolean | { perPage?: number };\n}\n\nexport interface AiringSchedule {\n id: number;\n airingAt: number;\n timeUntilAiring: number;\n episode: number;\n mediaId: number;\n media: Media;\n}\n\nexport type DayOfWeek = \"Monday\" | \"Tuesday\" | \"Wednesday\" | \"Thursday\" | \"Friday\" | \"Saturday\" | \"Sunday\";\n\nexport type WeeklySchedule = Record<DayOfWeek, AiringSchedule[]>;\n","import type { FuzzyDate } from \"./common\";\nimport type { MediaCoverImage, MediaFormat, MediaSeason, MediaStatus, MediaTitle, MediaType } from \"./media\";\n\nexport enum StaffSort {\n ID = \"ID\",\n ID_DESC = \"ID_DESC\",\n ROLE = \"ROLE\",\n ROLE_DESC = \"ROLE_DESC\",\n LANGUAGE = \"LANGUAGE\",\n LANGUAGE_DESC = \"LANGUAGE_DESC\",\n SEARCH_MATCH = \"SEARCH_MATCH\",\n FAVOURITES = \"FAVOURITES\",\n FAVOURITES_DESC = \"FAVOURITES_DESC\",\n RELEVANCE = \"RELEVANCE\",\n}\n\nexport interface StaffName {\n first: string | null;\n middle: string | null;\n last: string | null;\n full: string | null;\n native: string | null;\n}\n\nexport interface StaffImage {\n large: string | null;\n medium: string | null;\n}\n\n/** A media node returned inside `Staff.staffMedia`. */\nexport interface StaffMediaNode {\n id: number;\n title: MediaTitle;\n type: MediaType;\n format: MediaFormat | null;\n status: MediaStatus | null;\n coverImage: MediaCoverImage;\n bannerImage: string | null;\n genres: string[];\n averageScore: number | null;\n meanScore: number | null;\n popularity: number | null;\n favourites: number | null;\n episodes: number | null;\n trending: number | null;\n hashtag: string | null;\n season: MediaSeason | null;\n seasonYear: number | null;\n startDate: FuzzyDate | null;\n endDate: FuzzyDate | null;\n nextAiringEpisode: {\n id: number;\n airingAt: number;\n episode: number;\n mediaId: number;\n timeUntilAiring: number;\n } | null;\n studios: { edges: { node: { name: string } }[] } | null;\n siteUrl: string | null;\n}\n\nexport interface Staff {\n id: number;\n name: StaffName;\n language: string | null;\n image: StaffImage;\n description: string | null;\n primaryOccupations: string[];\n gender: string | null;\n dateOfBirth: FuzzyDate | null;\n dateOfDeath: FuzzyDate | null;\n age: string | null;\n yearsActive: number[];\n homeTown: string | null;\n bloodType: string | null;\n favourites: number | null;\n siteUrl: string | null;\n /** Media the staff member has worked on — only present when requested via include options. */\n staffMedia?: {\n nodes: StaffMediaNode[];\n } | null;\n}\n\n/** Options to include additional related data when fetching a staff member by ID. */\nexport interface StaffIncludeOptions {\n /** Include media the staff member has worked on.\n * `true` = 25 results sorted by popularity. Object form to customize. */\n media?: boolean | { perPage?: number; sort?: boolean };\n}\n\nexport interface SearchStaffOptions {\n query?: string;\n sort?: StaffSort[];\n page?: number;\n perPage?: number;\n}\n\n/** Compact voice actor data returned inside character edges. */\nexport interface VoiceActor extends Pick<Staff, \"id\" | \"image\" | \"gender\" | \"primaryOccupations\" | \"siteUrl\"> {\n name: StaffName & { userPreferred: string | null };\n languageV2: string | null;\n}\n","import type { PageInfo } from \"./common\";\nimport type { Media } from \"./media\";\n\nexport interface Studio {\n id: number;\n name: string;\n isAnimationStudio: boolean;\n siteUrl: string | null;\n favourites?: number | null;\n media?: {\n pageInfo: PageInfo;\n nodes: Pick<Media, \"id\" | \"title\" | \"type\" | \"format\" | \"coverImage\" | \"siteUrl\">[];\n } | null;\n}\n\nexport interface StudioConnection {\n nodes: Studio[];\n}\n\nexport enum StudioSort {\n ID = \"ID\",\n ID_DESC = \"ID_DESC\",\n NAME = \"NAME\",\n NAME_DESC = \"NAME_DESC\",\n SEARCH_MATCH = \"SEARCH_MATCH\",\n FAVOURITES = \"FAVOURITES\",\n FAVOURITES_DESC = \"FAVOURITES_DESC\",\n}\n\nexport interface SearchStudioOptions {\n query?: string;\n sort?: StudioSort[];\n page?: number;\n perPage?: number;\n}\n\n/**\n * Options for controlling embedded media when fetching a single studio.\n * Pass `{ media: { perPage: 50 } }` to fetch more media per studio.\n */\nexport interface StudioIncludeOptions {\n /** Customize the number of media returned. `true` = 25 (default), or `{ perPage }`. */\n media?: boolean | { perPage?: number };\n}\n","import type { MediaCoverImage, MediaTitle, MediaType } from \"./media\";\nimport type { UserAvatar } from \"./user\";\n\n/** Represents a forum thread on AniList. */\nexport interface Thread {\n id: number;\n title: string;\n body: string | null;\n userId: number;\n replyUserId: number | null;\n replyCommentId: number | null;\n replyCount: number;\n viewCount: number;\n isLocked: boolean;\n isSticky: boolean;\n isSubscribed: boolean;\n repliedAt: number | null;\n createdAt: number;\n updatedAt: number;\n siteUrl: string | null;\n user: {\n id: number;\n name: string;\n avatar: UserAvatar;\n } | null;\n replyUser: {\n id: number;\n name: string;\n avatar: UserAvatar;\n } | null;\n categories: ThreadCategory[] | null;\n mediaCategories: ThreadMediaCategory[] | null;\n likes: { id: number; name: string }[] | null;\n}\n\nexport interface ThreadCategory {\n id: number;\n name: string;\n}\n\nexport interface ThreadMediaCategory {\n id: number;\n title: MediaTitle;\n type: MediaType;\n coverImage: Pick<MediaCoverImage, \"large\" | \"medium\"> | null;\n siteUrl: string | null;\n}\n\n/** Sort options for thread queries. */\nexport enum ThreadSort {\n ID = \"ID\",\n ID_DESC = \"ID_DESC\",\n TITLE = \"TITLE\",\n TITLE_DESC = \"TITLE_DESC\",\n CREATED_AT = \"CREATED_AT\",\n CREATED_AT_DESC = \"CREATED_AT_DESC\",\n UPDATED_AT = \"UPDATED_AT\",\n UPDATED_AT_DESC = \"UPDATED_AT_DESC\",\n REPLIED_AT = \"REPLIED_AT\",\n REPLIED_AT_DESC = \"REPLIED_AT_DESC\",\n REPLY_COUNT = \"REPLY_COUNT\",\n REPLY_COUNT_DESC = \"REPLY_COUNT_DESC\",\n VIEW_COUNT = \"VIEW_COUNT\",\n VIEW_COUNT_DESC = \"VIEW_COUNT_DESC\",\n IS_STICKY = \"IS_STICKY\",\n SEARCH_MATCH = \"SEARCH_MATCH\",\n}\n\n/** Options for searching/listing threads. */\nexport interface SearchThreadOptions {\n /** Search query */\n query?: string;\n /** Filter by media ID */\n mediaId?: number;\n /** Filter by category ID */\n categoryId?: number;\n /** Sort order */\n sort?: ThreadSort[];\n /** Page number */\n page?: number;\n /** Results per page (max 50) */\n perPage?: number;\n}\n","import type { MediaCoverImage, MediaFormat, MediaTitle, MediaType } from \"./media\";\n\nexport enum UserSort {\n ID = \"ID\",\n ID_DESC = \"ID_DESC\",\n USERNAME = \"USERNAME\",\n USERNAME_DESC = \"USERNAME_DESC\",\n WATCHED_TIME = \"WATCHED_TIME\",\n WATCHED_TIME_DESC = \"WATCHED_TIME_DESC\",\n CHAPTERS_READ = \"CHAPTERS_READ\",\n CHAPTERS_READ_DESC = \"CHAPTERS_READ_DESC\",\n SEARCH_MATCH = \"SEARCH_MATCH\",\n}\n\nexport interface UserAvatar {\n large: string | null;\n medium: string | null;\n}\n\nexport interface UserStatistics {\n count: number;\n meanScore: number;\n minutesWatched: number;\n episodesWatched: number;\n chaptersRead: number;\n volumesRead: number;\n}\n\nexport interface User {\n id: number;\n name: string;\n about: string | null;\n avatar: UserAvatar;\n bannerImage: string | null;\n isFollowing: boolean | null;\n isFollower: boolean | null;\n donatorTier: number | null;\n donatorBadge: string | null;\n createdAt: number | null;\n siteUrl: string | null;\n statistics: {\n anime: UserStatistics;\n manga: UserStatistics;\n } | null;\n}\n\nexport interface SearchUserOptions {\n query?: string;\n sort?: UserSort[];\n page?: number;\n perPage?: number;\n}\n\nexport interface FavoriteMediaNode {\n id: number;\n title: MediaTitle;\n coverImage: Pick<MediaCoverImage, \"large\" | \"medium\">;\n type: MediaType | null;\n format: MediaFormat | null;\n siteUrl: string | null;\n}\n\nexport interface FavoriteCharacterNode {\n id: number;\n name: { full: string | null; native: string | null };\n image: { large: string | null; medium: string | null };\n siteUrl: string | null;\n}\n\nexport interface FavoriteStaffNode {\n id: number;\n name: { full: string | null; native: string | null };\n image: { large: string | null; medium: string | null };\n siteUrl: string | null;\n}\n\nexport interface FavoriteStudioNode {\n id: number;\n name: string;\n siteUrl: string | null;\n}\n\nexport interface UserFavorites {\n anime: FavoriteMediaNode[];\n manga: FavoriteMediaNode[];\n characters: FavoriteCharacterNode[];\n staff: FavoriteStaffNode[];\n studios: FavoriteStudioNode[];\n}\n\n/**\n * Options for controlling the number of results when fetching user favorites.\n */\nexport interface UserFavoritesOptions {\n /** Number of items per category (default: 25, max: 50). */\n perPage?: number;\n}\n","import {\n buildMediaByIdQuery,\n QUERY_AIRING_SCHEDULE,\n QUERY_MEDIA_BY_MAL_ID,\n QUERY_MEDIA_BY_SEASON,\n QUERY_MEDIA_SEARCH,\n QUERY_PLANNING,\n QUERY_RECENT_CHAPTERS,\n QUERY_RECOMMENDATIONS,\n QUERY_TRENDING,\n} from \"../queries\";\nimport type {\n AiringSchedule,\n DayOfWeek,\n GeneralMediaQueryOptions,\n GetAiringOptions,\n GetPlanningOptions,\n GetRecentChaptersOptions,\n GetRecommendationsOptions,\n GetSeasonOptions,\n Media,\n MediaIncludeOptions,\n PagedResult,\n Recommendation,\n SearchMediaOptions,\n WeeklySchedule,\n} from \"../types\";\nimport { MediaSort, MediaType } from \"../types\";\n\nimport { clampPerPage, validateId } from \"../utils\";\nimport type { ClientBase } from \"./base\";\n\nexport async function getMedia(client: ClientBase, id: number, include?: MediaIncludeOptions): Promise<Media> {\n validateId(id, \"mediaId\");\n const query = buildMediaByIdQuery(include);\n const data = await client.request<{ Media: Media }>(query, { id });\n return data.Media;\n}\n\nexport async function getMediaByMalId(client: ClientBase, malId: number, type?: MediaType): Promise<Media> {\n validateId(malId, \"malId\");\n const data = await client.request<{ Media: Media }>(QUERY_MEDIA_BY_MAL_ID, {\n idMal: malId,\n type,\n });\n return data.Media;\n}\n\nexport async function searchMedia(client: ClientBase, options: SearchMediaOptions = {}): Promise<PagedResult<Media>> {\n const {\n query: search,\n page = 1,\n perPage = 20,\n genres,\n tags,\n genresExclude,\n tagsExclude,\n format,\n ...filters\n } = options;\n return client.pagedRequest<Media>(\n QUERY_MEDIA_SEARCH,\n {\n search,\n ...filters,\n format: Array.isArray(format) ? undefined : format,\n format_in: Array.isArray(format) ? format : undefined,\n genre_in: genres,\n tag_in: tags,\n genre_not_in: genresExclude,\n tag_not_in: tagsExclude,\n page,\n perPage: clampPerPage(perPage),\n },\n \"media\",\n );\n}\n\nexport async function getTrending(client: ClientBase, options: GeneralMediaQueryOptions): Promise<PagedResult<Media>> {\n const { type = MediaType.ANIME, isAdult = false, page = 1, perPage = 20 } = options;\n return client.pagedRequest<Media>(QUERY_TRENDING, { type, isAdult, page, perPage: clampPerPage(perPage) }, \"media\");\n}\n\nexport async function getPopular(client: ClientBase, options: GeneralMediaQueryOptions): Promise<PagedResult<Media>> {\n const { type = MediaType.ANIME, isAdult = false, page = 1, perPage = 20 } = options;\n return searchMedia(client, { type, isAdult, sort: [MediaSort.POPULARITY_DESC], page, perPage });\n}\n\nexport async function getTopRated(client: ClientBase, options: GeneralMediaQueryOptions): Promise<PagedResult<Media>> {\n const { type = MediaType.ANIME, isAdult = false, page = 1, perPage = 20 } = options;\n return searchMedia(client, { type, isAdult, sort: [MediaSort.SCORE_DESC], page, perPage });\n}\n\nexport async function getAiredEpisodes(\n client: ClientBase,\n options: GetAiringOptions = {},\n): Promise<PagedResult<AiringSchedule>> {\n const now = Math.floor(Date.now() / 1000);\n return client.pagedRequest<AiringSchedule>(\n QUERY_AIRING_SCHEDULE,\n {\n airingAt_greater: options.airingAtGreater ?? now - 24 * 3600,\n airingAt_lesser: options.airingAtLesser ?? now,\n isAdult: options.isAdult ?? false,\n sort: options.sort,\n page: options.page ?? 1,\n perPage: clampPerPage(options.perPage ?? 20),\n },\n \"airingSchedules\",\n );\n}\n\n/**\n * @deprecated Use `getRecentlyUpdatedManga` instead. This alias will be removed in v2.\n */\nexport const getAiredChapters = getRecentlyUpdatedManga;\n\nexport async function getRecentlyUpdatedManga(\n client: ClientBase,\n options: GetRecentChaptersOptions = {},\n): Promise<PagedResult<Media>> {\n return client.pagedRequest<Media>(\n QUERY_RECENT_CHAPTERS,\n {\n isAdult: options.isAdult ?? false,\n page: options.page ?? 1,\n perPage: clampPerPage(options.perPage ?? 20),\n },\n \"media\",\n );\n}\n\nexport async function getPlanning(client: ClientBase, options: GetPlanningOptions = {}): Promise<PagedResult<Media>> {\n return client.pagedRequest<Media>(\n QUERY_PLANNING,\n {\n type: options.type,\n isAdult: options.isAdult ?? false,\n sort: options.sort ?? [MediaSort.POPULARITY_DESC],\n page: options.page ?? 1,\n perPage: clampPerPage(options.perPage ?? 20),\n },\n \"media\",\n );\n}\n\nexport async function getRecommendations(\n client: ClientBase,\n mediaId: number,\n options: Omit<GetRecommendationsOptions, \"mediaId\"> = {},\n): Promise<PagedResult<Recommendation>> {\n validateId(mediaId, \"mediaId\");\n const data = await client.request<{\n Media: {\n recommendations: {\n pageInfo: { total: number; perPage: number; currentPage: number; lastPage: number; hasNextPage: boolean };\n nodes: Recommendation[];\n };\n };\n }>(QUERY_RECOMMENDATIONS, {\n mediaId,\n page: options.page ?? 1,\n perPage: clampPerPage(options.perPage ?? 20),\n sort: options.sort,\n });\n\n return {\n pageInfo: data.Media.recommendations.pageInfo,\n results: data.Media.recommendations.nodes,\n };\n}\n\nexport async function getMediaBySeason(client: ClientBase, options: GetSeasonOptions): Promise<PagedResult<Media>> {\n return client.pagedRequest<Media>(\n QUERY_MEDIA_BY_SEASON,\n {\n season: options.season,\n seasonYear: options.seasonYear,\n type: options.type,\n isAdult: options.isAdult ?? false,\n sort: options.sort,\n page: options.page ?? 1,\n perPage: clampPerPage(options.perPage ?? 20),\n },\n \"media\",\n );\n}\n\nexport async function getWeeklySchedule(\n client: ClientBase,\n date: Date = new Date(),\n isAdult: boolean = false,\n): Promise<WeeklySchedule> {\n const schedule: WeeklySchedule = {\n Monday: [],\n Tuesday: [],\n Wednesday: [],\n Thursday: [],\n Friday: [],\n Saturday: [],\n Sunday: [],\n };\n\n const utcDay = date.getUTCDay();\n const diff = utcDay === 0 ? -6 : 1 - utcDay;\n const startOfWeek = new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate() + diff, 0, 0, 0));\n\n const endOfWeek = new Date(startOfWeek);\n endOfWeek.setUTCDate(startOfWeek.getUTCDate() + 6);\n endOfWeek.setUTCHours(23, 59, 59, 999);\n\n const startTimestamp = Math.floor(startOfWeek.getTime() / 1000);\n const endTimestamp = Math.floor(endOfWeek.getTime() / 1000);\n\n const iterator = client.paginate(\n (page) =>\n getAiredEpisodes(client, {\n airingAtGreater: startTimestamp,\n airingAtLesser: endTimestamp,\n isAdult,\n page,\n perPage: 50,\n }),\n 20,\n );\n\n const names: DayOfWeek[] = [\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"];\n\n for await (const episode of iterator) {\n const epDate = new Date(episode.airingAt * 1000);\n const dayName = names[epDate.getUTCDay()];\n if (dayName) schedule[dayName].push(episode);\n }\n\n return schedule;\n}\n","import { QUERY_STAFF_BY_ID, QUERY_STAFF_BY_ID_WITH_MEDIA, QUERY_STAFF_SEARCH } from \"../queries\";\n\nimport type { PagedResult, SearchStaffOptions, Staff, StaffIncludeOptions } from \"../types\";\n\nimport { clampPerPage, validateId } from \"../utils\";\nimport type { ClientBase } from \"./base\";\n\nexport async function getStaff(client: ClientBase, id: number, include?: StaffIncludeOptions): Promise<Staff> {\n validateId(id, \"staffId\");\n if (include?.media) {\n const perPage = typeof include.media === \"object\" ? (include.media.perPage ?? 25) : 25;\n const data = await client.request<{ Staff: Staff }>(QUERY_STAFF_BY_ID_WITH_MEDIA, { id, perPage });\n return data.Staff;\n }\n const data = await client.request<{ Staff: Staff }>(QUERY_STAFF_BY_ID, { id });\n return data.Staff;\n}\n\nexport async function searchStaff(client: ClientBase, options: SearchStaffOptions = {}): Promise<PagedResult<Staff>> {\n const { query: search, page = 1, perPage = 20, sort } = options;\n return client.pagedRequest<Staff>(\n QUERY_STAFF_SEARCH,\n { search, sort, page, perPage: clampPerPage(perPage) },\n \"staff\",\n );\n}\n","import { buildStudioByIdQuery, QUERY_STUDIO_BY_ID, QUERY_STUDIO_SEARCH } from \"../queries\";\n\nimport type { PagedResult, SearchStudioOptions, Studio, StudioIncludeOptions } from \"../types\";\n\nimport { clampPerPage, validateId } from \"../utils\";\nimport type { ClientBase } from \"./base\";\n\nexport async function getStudio(client: ClientBase, id: number, include?: StudioIncludeOptions): Promise<Studio> {\n validateId(id, \"studioId\");\n if (include?.media) {\n const perPage = typeof include.media === \"object\" ? include.media.perPage : undefined;\n const query = buildStudioByIdQuery(perPage);\n const data = await client.request<{ Studio: Studio }>(query, { id });\n return data.Studio;\n }\n const data = await client.request<{ Studio: Studio }>(QUERY_STUDIO_BY_ID, { id });\n return data.Studio;\n}\n\nexport async function searchStudios(\n client: ClientBase,\n options: SearchStudioOptions = {},\n): Promise<PagedResult<Studio>> {\n const { query: search, page = 1, perPage = 20, sort } = options;\n return client.pagedRequest<Studio>(\n QUERY_STUDIO_SEARCH,\n {\n search,\n sort,\n page,\n perPage: clampPerPage(perPage),\n },\n \"studios\",\n );\n}\n","import { QUERY_THREAD_BY_ID, QUERY_THREAD_SEARCH } from \"../queries\";\nimport type { PagedResult, SearchThreadOptions, Thread } from \"../types\";\nimport { ThreadSort } from \"../types\";\nimport { clampPerPage, validateId } from \"../utils\";\nimport type { ClientBase } from \"./base\";\n\nexport async function getThread(client: ClientBase, id: number): Promise<Thread> {\n validateId(id, \"threadId\");\n const data = await client.request<{ Thread: Thread }>(QUERY_THREAD_BY_ID, { id });\n return data.Thread;\n}\n\nexport async function getRecentThreads(\n client: ClientBase,\n options: SearchThreadOptions = {},\n): Promise<PagedResult<Thread>> {\n const { query: search, page = 1, perPage = 20, sort, mediaId, categoryId } = options;\n return client.pagedRequest<Thread>(\n QUERY_THREAD_SEARCH,\n {\n search,\n mediaCategoryId: mediaId,\n categoryId,\n sort: sort ?? [ThreadSort.REPLIED_AT_DESC],\n page,\n perPage: clampPerPage(perPage),\n },\n \"threads\",\n );\n}\n","import {\n buildUserFavoritesQuery,\n QUERY_USER_BY_ID,\n QUERY_USER_BY_NAME,\n QUERY_USER_FAVORITES_BY_ID,\n QUERY_USER_FAVORITES_BY_NAME,\n QUERY_USER_MEDIA_LIST,\n QUERY_USER_SEARCH,\n} from \"../queries\";\nimport type {\n GetUserMediaListOptions,\n MediaListEntry,\n PagedResult,\n SearchUserOptions,\n User,\n UserFavorites,\n UserFavoritesOptions,\n} from \"../types\";\nimport { clampPerPage, validateId } from \"../utils\";\nimport type { ClientBase } from \"./base\";\n\nexport async function getUser(client: ClientBase, idOrName: number | string): Promise<User> {\n if (typeof idOrName === \"number\") {\n validateId(idOrName, \"userId\");\n const data = await client.request<{ User: User }>(QUERY_USER_BY_ID, { id: idOrName });\n return data.User;\n }\n const data = await client.request<{ User: User }>(QUERY_USER_BY_NAME, { name: idOrName });\n return data.User;\n}\n\nexport async function searchUsers(client: ClientBase, options: SearchUserOptions = {}): Promise<PagedResult<User>> {\n const { query: search, page = 1, perPage = 20, sort } = options;\n return client.pagedRequest<User>(QUERY_USER_SEARCH, { search, sort, page, perPage: clampPerPage(perPage) }, \"users\");\n}\n\nexport async function getUserMediaList(\n client: ClientBase,\n options: GetUserMediaListOptions,\n): Promise<PagedResult<MediaListEntry>> {\n if (!options.userId && !options.userName) {\n throw new TypeError(\"getUserMediaList requires either userId or userName\");\n }\n if (options.userId) {\n validateId(options.userId, \"userId\");\n }\n return client.pagedRequest<MediaListEntry>(\n QUERY_USER_MEDIA_LIST,\n {\n userId: options.userId,\n userName: options.userName,\n type: options.type,\n status: options.status,\n sort: options.sort,\n page: options.page ?? 1,\n perPage: clampPerPage(options.perPage ?? 20),\n },\n \"mediaList\",\n );\n}\n\ninterface RawFavourites {\n anime?: { nodes: UserFavorites[\"anime\"] };\n manga?: { nodes: UserFavorites[\"manga\"] };\n characters?: { nodes: UserFavorites[\"characters\"] };\n staff?: { nodes: UserFavorites[\"staff\"] };\n studios?: { nodes: UserFavorites[\"studios\"] };\n}\n\nexport async function getUserFavorites(\n client: ClientBase,\n idOrName: number | string,\n options?: UserFavoritesOptions,\n): Promise<UserFavorites> {\n const useBuilder = options?.perPage !== undefined;\n if (typeof idOrName === \"number\") {\n validateId(idOrName, \"userId\");\n const query = useBuilder ? buildUserFavoritesQuery(\"id\", options.perPage) : QUERY_USER_FAVORITES_BY_ID;\n const data = await client.request<{ User: { favourites: RawFavourites } }>(query, {\n id: idOrName,\n });\n return mapFavorites(data.User.favourites);\n }\n const query = useBuilder ? buildUserFavoritesQuery(\"name\", options.perPage) : QUERY_USER_FAVORITES_BY_NAME;\n const data = await client.request<{ User: { favourites: RawFavourites } }>(query, {\n name: idOrName,\n });\n return mapFavorites(data.User.favourites);\n}\n\nfunction mapFavorites(fav: RawFavourites): UserFavorites {\n return {\n anime: fav.anime?.nodes ?? [],\n manga: fav.manga?.nodes ?? [],\n characters: fav.characters?.nodes ?? [],\n staff: fav.staff?.nodes ?? [],\n studios: fav.studios?.nodes ?? [],\n };\n}\n","import { MemoryCache } from \"../cache\";\nimport { AniListError } from \"../errors\";\nimport {\n buildBatchCharacterQuery,\n buildBatchMediaQuery,\n buildBatchStaffQuery,\n QUERY_GENRES,\n QUERY_TAGS,\n} from \"../queries\";\nimport { RateLimiter } from \"../rate-limiter\";\nimport type {\n AiringSchedule,\n AniListClientOptions,\n AniListHooks,\n CacheAdapter,\n Character,\n CharacterIncludeOptions,\n GeneralMediaQueryOptions,\n GetAiringOptions,\n GetPlanningOptions,\n GetRecentChaptersOptions,\n GetRecommendationsOptions,\n GetSeasonOptions,\n GetUserMediaListOptions,\n Logger,\n Media,\n MediaIncludeOptions,\n MediaListEntry,\n MediaTag,\n MediaType,\n PagedResult,\n PageInfo,\n RateLimitInfo,\n Recommendation,\n ResponseMeta,\n SearchCharacterOptions,\n SearchMediaOptions,\n SearchStaffOptions,\n SearchStudioOptions,\n SearchThreadOptions,\n SearchUserOptions,\n Staff,\n StaffIncludeOptions,\n Studio,\n StudioIncludeOptions,\n Thread,\n User,\n UserFavorites,\n UserFavoritesOptions,\n WeeklySchedule,\n} from \"../types\";\nimport { chunk, normalizeQuery, validateIds } from \"../utils\";\n\nimport * as characterMethods from \"./character\";\nimport * as mediaMethods from \"./media\";\nimport * as staffMethods from \"./staff\";\nimport * as studioMethods from \"./studio\";\nimport * as threadMethods from \"./thread\";\nimport * as userMethods from \"./user\";\n\nconst DEFAULT_API_URL = \"https://graphql.anilist.co\";\n\ndeclare const __VERSION__: string;\n/** Injected at build time by tsup — falls back to `\"dev\"` in test/dev environments. */\nconst LIB_VERSION = typeof __VERSION__ !== \"undefined\" ? __VERSION__ : \"dev\";\n\n/**\n * Lightweight AniList GraphQL client with built-in caching and rate limiting.\n *\n * @example\n * ```ts\n * import { AniListClient } from \"ani-client\";\n *\n * const client = new AniListClient();\n * const anime = await client.getMedia(1);\n * console.log(anime.title.romaji);\n *\n * // Custom cache & rate limit options\n * const client2 = new AniListClient({\n * cache: { ttl: 1000 * 60 * 60 }, // 1 hour cache\n * rateLimit: { maxRequests: 60 },\n * });\n * ```\n */\nexport class AniListClient {\n private readonly apiUrl: string;\n private readonly headers: Record<string, string>;\n private readonly cacheAdapter: CacheAdapter;\n private readonly rateLimiter: RateLimiter;\n private readonly hooks: AniListHooks;\n private readonly logger?: Logger;\n private readonly signal?: AbortSignal;\n private readonly inFlight = new Map<string, Promise<unknown>>();\n private _rateLimitInfo?: RateLimitInfo;\n private _lastRequestMeta?: ResponseMeta;\n\n constructor(options: AniListClientOptions = {}) {\n this.apiUrl = options.apiUrl ?? DEFAULT_API_URL;\n this.headers = {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n \"User-Agent\": `ani-client/${LIB_VERSION}`,\n };\n if (options.token) {\n this.headers.Authorization = `Bearer ${options.token}`;\n }\n this.cacheAdapter = options.cacheAdapter ?? new MemoryCache(options.cache);\n this.rateLimiter = new RateLimiter(options.rateLimit);\n this.hooks = options.hooks ?? {};\n this.logger = options.logger;\n this.signal = options.signal;\n }\n\n /**\n * The current rate limit information from the last API response.\n * Updated after every non-cached request.\n */\n get rateLimitInfo(): RateLimitInfo | undefined {\n return this._rateLimitInfo;\n }\n\n /**\n * Metadata about the last request (duration, cache status, rate limit info).\n * Useful for debugging and monitoring.\n */\n get lastRequestMeta(): ResponseMeta | undefined {\n return this._lastRequestMeta;\n }\n\n /** @internal */\n async request<T>(query: string, variables: Record<string, unknown> = {}): Promise<T> {\n const cacheKey = MemoryCache.key(query, variables);\n\n const cached = await this.cacheAdapter.get<T>(cacheKey);\n if (cached !== undefined) {\n this.hooks.onCacheHit?.(cacheKey);\n this.logger?.debug(\"Cache hit\", { cacheKey });\n const meta: ResponseMeta = { durationMs: 0, fromCache: true };\n this._lastRequestMeta = meta;\n this.hooks.onResponse?.(query, 0, true);\n return cached;\n }\n\n const existing = this.inFlight.get(cacheKey);\n if (existing) return existing as Promise<T>;\n\n const promise = this.executeRequest<T>(query, variables, cacheKey);\n this.inFlight.set(cacheKey, promise);\n\n try {\n return await promise;\n } finally {\n this.inFlight.delete(cacheKey);\n }\n }\n\n /** @internal */\n private async executeRequest<T>(query: string, variables: Record<string, unknown>, cacheKey: string): Promise<T> {\n const start = Date.now();\n this.hooks.onRequest?.(query, variables);\n this.logger?.debug(\"API request\", { variables });\n\n const minifiedQuery = normalizeQuery(query);\n\n let res: Response;\n try {\n res = await this.rateLimiter.fetchWithRetry(\n this.apiUrl,\n {\n method: \"POST\",\n headers: this.headers,\n body: JSON.stringify({ query: minifiedQuery, variables }),\n signal: this.signal,\n },\n { onRetry: this.hooks.onRetry, onRateLimit: this.hooks.onRateLimit },\n );\n } catch (err) {\n const error =\n err instanceof AniListError\n ? err\n : new AniListError((err as Error).message ?? \"Network request failed\", 0, [err]);\n this.logger?.error(\"Request failed\", { error: error.message, status: error.status });\n this.hooks.onError?.(error, query, variables);\n throw error;\n }\n\n let json: { data?: T; errors?: unknown[] };\n try {\n json = (await res.json()) as { data?: T; errors?: unknown[] };\n } catch {\n const error = new AniListError(`Non-JSON response from AniList (HTTP ${res.status})`, res.status, []);\n this.logger?.error(\"Request failed\", { error: error.message, status: error.status });\n this.hooks.onError?.(error, query, variables);\n throw error;\n }\n\n if (!res.ok || json.errors) {\n const message =\n (json.errors as Array<{ message?: string }>)?.[0]?.message ?? `AniList API error (HTTP ${res.status})`;\n const error = new AniListError(message, res.status, json.errors ?? []);\n this.logger?.error(\"Request failed\", { error: error.message, status: error.status });\n this.hooks.onError?.(error, query, variables);\n throw error;\n }\n\n const rlLimit = res.headers.get(\"X-RateLimit-Limit\");\n const rlRemaining = res.headers.get(\"X-RateLimit-Remaining\");\n const rlReset = res.headers.get(\"X-RateLimit-Reset\");\n if (rlLimit && rlRemaining && rlReset) {\n this._rateLimitInfo = {\n limit: Number.parseInt(rlLimit, 10),\n remaining: Number.parseInt(rlRemaining, 10),\n reset: Number.parseInt(rlReset, 10),\n };\n }\n\n const durationMs = Date.now() - start;\n const data = json.data as T;\n await this.cacheAdapter.set(cacheKey, data);\n\n const meta: ResponseMeta = { durationMs, fromCache: false, rateLimitInfo: this._rateLimitInfo };\n this._lastRequestMeta = meta;\n this.logger?.debug(\"Request complete\", { durationMs, rateLimitInfo: this._rateLimitInfo });\n this.hooks.onResponse?.(query, durationMs, false, this._rateLimitInfo);\n return data;\n }\n\n /** @internal */\n async pagedRequest<T>(query: string, variables: Record<string, unknown>, field: string): Promise<PagedResult<T>> {\n const data = await this.request<{ Page: Record<string, unknown> & { pageInfo: PageInfo } }>(query, variables);\n const results = data.Page[field];\n if (!Array.isArray(results)) {\n throw new AniListError(`Unexpected response: missing field \"${field}\" in Page`, 0, []);\n }\n return { pageInfo: data.Page.pageInfo, results: results as T[] };\n }\n\n /**\n * Fetch a single media entry by its AniList ID.\n *\n * Optionally include related data (characters, staff, relations, etc.) via the `include` parameter.\n *\n * @param id - The AniList media ID\n * @param include - Optional related data to include\n */\n async getMedia(id: number, include?: MediaIncludeOptions): Promise<Media> {\n return mediaMethods.getMedia(this, id, include);\n }\n\n /**\n * Search for anime or manga.\n *\n * @param options - Search / filter parameters\n * @returns Paginated results with matching media\n */\n async searchMedia(options: SearchMediaOptions = {}): Promise<PagedResult<Media>> {\n return mediaMethods.searchMedia(this, options);\n }\n\n /** Get currently trending anime or manga. */\n async getTrending(options: GeneralMediaQueryOptions = {}): Promise<PagedResult<Media>> {\n return mediaMethods.getTrending(this, options);\n }\n\n /** Get the most popular anime or manga. */\n async getPopular(options: GeneralMediaQueryOptions = {}): Promise<PagedResult<Media>> {\n return mediaMethods.getPopular(this, options);\n }\n\n /** Get the highest-rated anime or manga. */\n async getTopRated(options: GeneralMediaQueryOptions = {}): Promise<PagedResult<Media>> {\n return mediaMethods.getTopRated(this, options);\n }\n\n /** Get recently aired anime episodes. */\n async getAiredEpisodes(options: GetAiringOptions = {}): Promise<PagedResult<AiringSchedule>> {\n return mediaMethods.getAiredEpisodes(this, options);\n }\n\n /**\n * Get currently releasing manga sorted by most recently updated.\n *\n * @param options - Pagination parameters\n */\n async getRecentlyUpdatedManga(options: GetRecentChaptersOptions = {}): Promise<PagedResult<Media>> {\n return mediaMethods.getRecentlyUpdatedManga(this, options);\n }\n\n /**\n * @deprecated Use `getRecentlyUpdatedManga` instead. This alias will be removed in v2.\n */\n async getAiredChapters(options: GetRecentChaptersOptions = {}): Promise<PagedResult<Media>> {\n return this.getRecentlyUpdatedManga(options);\n }\n\n /**\n * Fetch a media entry by its MyAnimeList (MAL) ID.\n *\n * @param malId - The MyAnimeList ID\n * @param type - Optional media type to disambiguate (some MAL IDs map to both ANIME and MANGA)\n */\n async getMediaByMalId(malId: number, type?: MediaType): Promise<Media> {\n return mediaMethods.getMediaByMalId(this, malId, type);\n }\n\n /** Get the detailed schedule for the current week, sorted by day. */\n async getWeeklySchedule(date?: Date): Promise<WeeklySchedule> {\n return mediaMethods.getWeeklySchedule(this, date);\n }\n\n /** Get upcoming (not yet released) media. */\n async getPlanning(options: GetPlanningOptions = {}): Promise<PagedResult<Media>> {\n return mediaMethods.getPlanning(this, options);\n }\n\n /** Get recommendations for a specific media. */\n async getRecommendations(\n mediaId: number,\n options: Omit<GetRecommendationsOptions, \"mediaId\"> = {},\n ): Promise<PagedResult<Recommendation>> {\n return mediaMethods.getRecommendations(this, mediaId, options);\n }\n\n /** Get anime (or manga) for a specific season and year. */\n async getMediaBySeason(options: GetSeasonOptions): Promise<PagedResult<Media>> {\n return mediaMethods.getMediaBySeason(this, options);\n }\n\n /** Fetch a character by AniList ID. Pass `{ voiceActors: true }` to include VA data. */\n async getCharacter(id: number, include?: CharacterIncludeOptions): Promise<Character> {\n return characterMethods.getCharacter(this, id, include);\n }\n\n /** Search for characters by name. */\n async searchCharacters(options: SearchCharacterOptions = {}): Promise<PagedResult<Character>> {\n return characterMethods.searchCharacters(this, options);\n }\n\n /** Fetch a staff member by AniList ID. Pass `{ media: true }` or `{ media: { perPage } }` for media credits. */\n async getStaff(id: number, include?: StaffIncludeOptions): Promise<Staff> {\n return staffMethods.getStaff(this, id, include);\n }\n\n /** Search for staff (voice actors, directors, etc.). */\n async searchStaff(options: SearchStaffOptions = {}): Promise<PagedResult<Staff>> {\n return staffMethods.searchStaff(this, options);\n }\n\n /**\n * Fetch a user by AniList ID or username.\n *\n * @param idOrName - The AniList user ID (number) or username (string)\n */\n async getUser(idOrName: number | string): Promise<User> {\n return userMethods.getUser(this, idOrName);\n }\n\n /** Search for users by name. */\n async searchUsers(options: SearchUserOptions = {}): Promise<PagedResult<User>> {\n return userMethods.searchUsers(this, options);\n }\n\n /** Get a user's anime or manga list. */\n async getUserMediaList(options: GetUserMediaListOptions): Promise<PagedResult<MediaListEntry>> {\n return userMethods.getUserMediaList(this, options);\n }\n\n /**\n * Fetch a user's favorite anime, manga, characters, staff, and studios.\n *\n * @param idOrName - AniList user ID (number) or username (string)\n * @param options - Optional pagination options (perPage per category)\n * @returns The user's favorites grouped by category\n *\n * @example\n * ```typescript\n * const favs = await client.getUserFavorites(\"AniList\");\n * favs.anime.forEach(a => console.log(a.title.romaji));\n *\n * // Fetch more results per category\n * const moreResults = await client.getUserFavorites(1, { perPage: 50 });\n * ```\n */\n async getUserFavorites(idOrName: number | string, options?: UserFavoritesOptions): Promise<UserFavorites> {\n return userMethods.getUserFavorites(this, idOrName, options);\n }\n\n /**\n * Fetch a studio by its AniList ID.\n * Pass `include` to customise the number of media returned.\n *\n * @example\n * ```typescript\n * const studio = await client.getStudio(21, { media: { perPage: 50 } });\n * ```\n */\n async getStudio(id: number, include?: StudioIncludeOptions): Promise<Studio> {\n return studioMethods.getStudio(this, id, include);\n }\n\n /** Search for studios by name. */\n async searchStudios(options: SearchStudioOptions = {}): Promise<PagedResult<Studio>> {\n return studioMethods.searchStudios(this, options);\n }\n\n /** Fetch a forum thread by its AniList ID. */\n async getThread(id: number): Promise<Thread> {\n return threadMethods.getThread(this, id);\n }\n\n /** Get recent forum threads, optionally filtered by search, media, or category. */\n async getRecentThreads(options: SearchThreadOptions = {}): Promise<PagedResult<Thread>> {\n return threadMethods.getRecentThreads(this, options);\n }\n\n /** Get all available genres on AniList. */\n async getGenres(): Promise<string[]> {\n const data = await this.request<{ GenreCollection: string[] }>(QUERY_GENRES);\n return data.GenreCollection;\n }\n\n /** Get all available media tags on AniList. */\n async getTags(): Promise<MediaTag[]> {\n const data = await this.request<{ MediaTagCollection: MediaTag[] }>(QUERY_TAGS);\n return data.MediaTagCollection;\n }\n\n /** Execute an arbitrary GraphQL query against the AniList API. */\n async raw<T>(query: string, variables?: Record<string, unknown>): Promise<T> {\n return this.request<T>(query, variables ?? {});\n }\n\n /**\n * Auto-paginating async iterator. Yields individual items across all pages.\n *\n * @param fetchPage - A function that takes a page number and returns a `PagedResult<T>`\n * @param maxPages - Maximum number of pages to fetch (default: Infinity)\n */\n async *paginate<T>(\n fetchPage: (page: number) => Promise<PagedResult<T>>,\n maxPages = Number.POSITIVE_INFINITY,\n ): AsyncGenerator<T, void, undefined> {\n let page = 1;\n let hasNext = true;\n\n while (hasNext && page <= maxPages) {\n const result = await fetchPage(page);\n for (const item of result.results) {\n yield item;\n }\n hasNext = result.pageInfo.hasNextPage === true;\n page++;\n }\n }\n\n /** Fetch multiple media entries in a single API request. */\n async getMediaBatch(ids: number[]): Promise<Media[]> {\n if (ids.length === 0) return [];\n validateIds(ids, \"mediaId\");\n const [singleMediaId] = ids;\n if (ids.length === 1 && singleMediaId !== undefined) return [await this.getMedia(singleMediaId)];\n return this.executeBatch<Media>(ids, buildBatchMediaQuery, \"m\");\n }\n\n /** Fetch multiple characters in a single API request. */\n async getCharacterBatch(ids: number[]): Promise<Character[]> {\n if (ids.length === 0) return [];\n validateIds(ids, \"characterId\");\n const [singleCharId] = ids;\n if (ids.length === 1 && singleCharId !== undefined) return [await this.getCharacter(singleCharId)];\n return this.executeBatch<Character>(ids, buildBatchCharacterQuery, \"c\");\n }\n\n /** Fetch multiple staff members in a single API request. */\n async getStaffBatch(ids: number[]): Promise<Staff[]> {\n if (ids.length === 0) return [];\n validateIds(ids, \"staffId\");\n const [singleStaffId] = ids;\n if (ids.length === 1 && singleStaffId !== undefined) return [await this.getStaff(singleStaffId)];\n return this.executeBatch<Staff>(ids, buildBatchStaffQuery, \"s\");\n }\n\n /** @internal */\n private async executeBatch<T>(ids: number[], buildQuery: (ids: number[]) => string, prefix: string): Promise<T[]> {\n const chunks = chunk(ids, 50);\n const chunkResults = await Promise.all(\n chunks.map(async (idChunk) => {\n const query = buildQuery(idChunk);\n const data = await this.request<Record<string, T>>(query);\n return idChunk.map((_, i) => data[`${prefix}${i}`] as T);\n }),\n );\n return chunkResults.flat();\n }\n\n /** Clear the entire response cache. */\n async clearCache(): Promise<void> {\n await this.cacheAdapter.clear();\n }\n\n /** Number of entries currently in the cache. */\n async cacheSize(): Promise<number> {\n return this.cacheAdapter.size;\n }\n\n /** Remove cache entries whose key matches the given pattern. */\n async invalidateCache(pattern: string | RegExp): Promise<number> {\n if (this.cacheAdapter.invalidate) {\n return this.cacheAdapter.invalidate(pattern);\n }\n const allKeys = await this.cacheAdapter.keys();\n const regex = typeof pattern === \"string\" ? new RegExp(pattern) : pattern;\n let count = 0;\n for (const key of allKeys) {\n if (regex.test(key)) {\n await this.cacheAdapter.delete(key);\n count++;\n }\n }\n return count;\n }\n\n /** Clean up resources held by the client. */\n async destroy(): Promise<void> {\n await this.cacheAdapter.clear();\n this.inFlight.clear();\n this.rateLimiter.dispose();\n }\n\n /**\n * Return a scoped view of this client where every request uses the given `AbortSignal`.\n * The returned object shares the same cache, rate limiter, and hooks.\n *\n * @example\n * ```ts\n * const controller = new AbortController();\n * const media = await client.withSignal(controller.signal).getMedia(1);\n *\n * // Cancel all in-flight requests made through the scoped view\n * controller.abort();\n * ```\n */\n withSignal(signal: AbortSignal): AniListClient {\n const scoped = Object.create(this) as AniListClient;\n Object.defineProperty(scoped, \"signal\", { value: signal, configurable: true });\n return scoped;\n }\n}\n"]}
|