ani-client 2.0.3 → 2.1.1

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 CHANGED
@@ -7,13 +7,10 @@
7
7
  [![TypeScript](https://img.shields.io/badge/TypeScript-strict-blue)](https://www.typescriptlang.org/)
8
8
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
9
9
 
10
- > A fully typed, zero-dependency client for the [AniList](https://anilist.co) GraphQL API.
10
+ > A fully typed, zero-dependency client for the [AniList](https://anilist.co) GraphQL API.
11
+ > Supports Node.js, Bun, Deno, and modern browsers.
11
12
 
12
- **Showcase**: [See who's using ani-client](https://ani-client.js.org/showcase)
13
-
14
- **Support server** [Discord server](https://discord.gg/3P7twDurUD)
15
-
16
- ## Highlights
13
+ ## Features
17
14
 
18
15
  - **Zero dependencies** — uses the native `fetch` API
19
16
  - **Universal** — Node.js ≥ 20, Bun, Deno, and modern browsers
@@ -21,24 +18,23 @@
21
18
  - **LRU cache** with TTL, stale-while-revalidate, and hit/miss stats
22
19
  - **Rate-limit protection** with exponential backoff, retries, and custom strategies
23
20
  - **Request deduplication** — concurrent identical queries share a single in-flight request
24
- - **Batch queries** — fetch up to 50 media/characters/staff in one API call
25
- - **Paginated media relationships** — `getMediaCharacters()` and `getMediaStaff()` support paged results for large casts and staff listings
26
- - **Auto-pagination** — async iterator that yields items across pages
27
- - **AbortSignal support** — cancel globally or per-request with `withSignal()`
21
+ - **Batch queries** — fetch up to 50 media, characters, or staff in a single API call
22
+ - **Auto-pagination** — async iterator that yields items across all pages
23
+ - **AbortSignal support** — cancel globally or per-request via `withSignal()`
28
24
  - **Injectable logger** — plug in `console`, pino, winston, or any compatible logger
29
- - **Redis-ready** — swap the cache adapter with the built-in `RedisCache` for distributed setups
25
+ - **Redis-ready** — swap the in-memory cache with the built-in `RedisCache` adapter
30
26
 
31
- ## Install
27
+ ## Installation
32
28
 
33
29
  ```bash
34
30
  npm install ani-client
35
- # or
31
+ # pnpm
36
32
  pnpm add ani-client
37
- # or
33
+ # yarn
38
34
  yarn add ani-client
39
35
  ```
40
36
 
41
- ## Quick start
37
+ ## Quick Start
42
38
 
43
39
  ```ts
44
40
  import { AniListClient, MediaType } from "ani-client";
@@ -57,56 +53,51 @@ const results = await client.searchMedia({
57
53
  perPage: 10,
58
54
  });
59
55
 
60
- // Cross-platform lookup by MyAnimeList ID
56
+ // Lookup by MyAnimeList ID
61
57
  const fma = await client.getMediaByMalId(5114);
62
-
63
- // Paginated media relationships
64
- const characters = await client.getMediaCharacters(1, { page: 1, perPage: 25, voiceActors: true });
65
- const staff = await client.getMediaStaff(1, { page: 1, perPage: 25 });
66
58
  ```
67
59
 
68
- ## Features at a glance
60
+ ## Usage
69
61
 
70
- ### Caching & stale-while-revalidate
62
+ ### Caching
63
+
64
+ The client caches every response in memory by default. You can tune TTL, capacity, and enable stale-while-revalidate:
71
65
 
72
66
  ```ts
73
67
  const client = new AniListClient({
74
68
  cache: {
75
- ttl: 1000 * 60 * 5, // 5 min TTL
76
- maxSize: 200, // LRU capacity
77
- staleWhileRevalidateMs: 60_000, // serve stale for 1 min after expiry
69
+ ttl: 1000 * 60 * 5, // 5 min TTL
70
+ maxSize: 200, // LRU capacity
71
+ staleWhileRevalidateMs: 60_000, // serve stale for 1 min after expiry
78
72
  },
79
73
  });
80
74
 
81
- // Check cache performance
82
75
  console.log(client.cacheStats);
83
76
  // { hits: 42, misses: 8, stales: 2, hitRate: 0.84 }
84
77
  ```
85
78
 
86
- ### Per-request cancellation
79
+ For distributed setups, swap to the built-in Redis adapter:
87
80
 
88
81
  ```ts
89
- const controller = new AbortController();
90
- const scoped = client.withSignal(controller.signal);
82
+ import { AniListClient, RedisCache } from "ani-client";
83
+ import { createClient } from "redis";
91
84
 
92
- setTimeout(() => controller.abort(), 3_000);
93
- const anime = await scoped.getMedia(1);
94
- ```
95
-
96
- ### Structured logging
85
+ const redis = createClient();
86
+ await redis.connect();
97
87
 
98
- ```ts
99
- const client = new AniListClient({ logger: console });
100
- // debug: "API request" { query: "query { Media(id: 1) { ... } }" }
101
- // debug: "Request complete" { durationMs: 120, status: 200 }
88
+ const client = new AniListClient({
89
+ cacheAdapter: new RedisCache(redis),
90
+ });
102
91
  ```
103
92
 
104
- ### Rate limiting & retries
93
+ ### Rate Limiting
94
+
95
+ The client is pre-configured to stay within AniList's 30 req/min limit. You can override the defaults and provide a custom retry strategy:
105
96
 
106
97
  ```ts
107
98
  const client = new AniListClient({
108
99
  rateLimit: {
109
- maxRequests: 85,
100
+ maxRequests: 25,
110
101
  windowMs: 60_000,
111
102
  maxRetries: 3,
112
103
  retryOnNetworkError: true,
@@ -114,17 +105,26 @@ const client = new AniListClient({
114
105
  },
115
106
  });
116
107
 
108
+ // Inspect the rate limit state after any request
117
109
  console.log(client.rateLimitInfo);
118
- // { remaining: 82, limit: 85, reset: 1741104000 }
110
+ // { remaining: 22, limit: 25, reset: 1741104000 }
119
111
  ```
120
112
 
121
- ### Batch & pagination
113
+ ### Batch Requests
114
+
115
+ Fetch multiple entries in a single API call (chunks of 50):
122
116
 
123
117
  ```ts
124
- // Fetch 100 anime in 2 API calls (50 per batch)
125
- const batch = await client.getMediaBatch([1, 2, 3, /* ...up to 100 IDs */]);
118
+ const anime = await client.getMediaBatch([1, 5, 6, 20]);
119
+ const characters = await client.getCharacterBatch([1, 2, 3]);
120
+ const staff = await client.getStaffBatch([95269, 95270]);
121
+ ```
122
+
123
+ ### Auto-Pagination
124
+
125
+ Use the built-in async iterator to walk through all pages automatically:
126
126
 
127
- // Auto-paginate through all results
127
+ ```ts
128
128
  for await (const anime of client.paginate(
129
129
  (page) => client.searchMedia({ query: "Gundam", page, perPage: 50 }),
130
130
  5, // max 5 pages
@@ -133,32 +133,106 @@ for await (const anime of client.paginate(
133
133
  }
134
134
  ```
135
135
 
136
- ### Users, characters, studios & more
136
+ ### Request Cancellation
137
+
138
+ Scope any client instance to an `AbortSignal` for per-request cancellation:
139
+
140
+ ```ts
141
+ const controller = new AbortController();
142
+ const scoped = client.withSignal(controller.signal);
143
+
144
+ setTimeout(() => controller.abort(), 3_000);
145
+ const anime = await scoped.getMedia(1); // cancelled after 3s
146
+ ```
147
+
148
+ ### Logging
149
+
150
+ Pass any `console`-compatible logger to trace requests and cache events:
151
+
152
+ ```ts
153
+ const client = new AniListClient({ logger: console });
154
+ // debug: "API request" { variables: { id: 1 } }
155
+ // debug: "Request complete" { durationMs: 120 }
156
+ ```
157
+
158
+ ### Media Relationships
159
+
160
+ Paginated access to a media's characters and staff:
137
161
 
138
162
  ```ts
139
- const user = await client.getUser("AniList");
140
- const favs = await client.getUserFavorites("AniList", { perPage: 50 });
141
- const char = await client.getCharacter(1, { voiceActors: true });
142
- const characters = await client.getMediaCharacters(1, { page: 1, perPage: 25, voiceActors: true });
163
+ const characters = await client.getMediaCharacters(1, {
164
+ page: 1,
165
+ perPage: 25,
166
+ voiceActors: true,
167
+ });
168
+
143
169
  const staff = await client.getMediaStaff(1, { page: 1, perPage: 25 });
144
- const studio = await client.getStudio(21, { media: { perPage: 50 } });
170
+ ```
171
+
172
+ ### Users, Characters, Studios & More
173
+
174
+ ```ts
175
+ const user = await client.getUser("AniList");
176
+ const favs = await client.getUserFavorites("AniList", { perPage: 50 });
177
+ const char = await client.getCharacter(1, { voiceActors: true });
178
+ const studio = await client.getStudio(21, { media: { perPage: 50 } });
145
179
  const schedule = await client.getWeeklySchedule();
180
+ const review = await client.getReview(760);
181
+ ```
182
+
183
+ ### Error Handling
184
+
185
+ All API errors throw an `AniListError` with a `status` code and the raw GraphQL `errors` array:
186
+
187
+ ```ts
188
+ import { AniListError } from "ani-client";
189
+
190
+ try {
191
+ await client.getMedia(999999999);
192
+ } catch (e) {
193
+ if (e instanceof AniListError) {
194
+ console.error(e.message); // "Not Found"
195
+ console.error(e.status); // 404
196
+ console.error(e.errors); // raw GraphQL errors array
197
+ }
198
+ }
146
199
  ```
147
200
 
201
+ ### Lifecycle Hooks
202
+
203
+ Intercept requests, responses, cache events, and errors:
204
+
205
+ ```ts
206
+ const client = new AniListClient({
207
+ hooks: {
208
+ onRequest: (query, variables) => console.log("→", variables),
209
+ onResponse: (query, durationMs, fromCache) => console.log(`← ${durationMs}ms`),
210
+ onCacheHit: (key) => console.log("cache hit", key),
211
+ onRateLimit: (retryAfterMs) => console.warn(`rate limited, retrying in ${retryAfterMs}ms`),
212
+ onError: (error) => console.error(error.message),
213
+ },
214
+ });
215
+ ```
216
+
217
+ ## Requirements
218
+
219
+ | Runtime | Version |
220
+ |----------|--------------------|
221
+ | Node.js | ≥ 20 |
222
+ | Bun | ≥ 1.0 |
223
+ | Deno | ≥ 1.28 |
224
+ | Browsers | `fetch` + `AbortController` required |
225
+
148
226
  ## Documentation
149
227
 
150
- Full API reference, guides (caching, pagination, includes, hooks, etc.) and configuration examples:
228
+ Full API reference, configuration options, and guides (caching, pagination, hooks, Redis, etc.):
151
229
 
152
230
  **[ani-client.js.org](https://ani-client.js.org)**
153
231
 
154
- ## Requirements
232
+ ## Community
155
233
 
156
- | Runtime | Version |
157
- | --- | --- |
158
- | Node.js | ≥ 20 |
159
- | Bun | ≥ 1.0 |
160
- | Deno | ≥ 1.28 |
161
- | Browsers | Any with `fetch` + `AbortController` |
234
+ - 💬 [Discord server](https://discord.gg/3P7twDurUD)
235
+ - [Showcase see who's using ani-client](https://ani-client.js.org/showcase)
162
236
 
163
237
  ## Contributing
164
238
 
@@ -166,4 +240,4 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup, coding standards,
166
240
 
167
241
  ## License
168
242
 
169
- [MIT](LICENSE) © gonzyui
243
+ [MIT](LICENSE) © [gonzyui](https://github.com/gonzyui)
package/dist/index.d.mts CHANGED
@@ -603,7 +603,7 @@ declare enum MediaRelationType {
603
603
  }
604
604
  interface MediaEdge {
605
605
  relationType: MediaRelationType;
606
- node: Pick<Media, "id" | "title" | "type" | "format" | "status" | "startDate" | "endDate" | "season" | "seasonYear" | "episodes" | "chapters" | "volumes" | "coverImage" | "genres" | "averageScore" | "studios" | "siteUrl" | "nextAiringEpisode">;
606
+ node: Pick<Media, "id" | "title" | "type" | "format" | "status" | "startDate" | "endDate" | "season" | "seasonYear" | "episodes" | "chapters" | "volumes" | "coverImage" | "genres" | "averageScore" | "meanScore" | "studios" | "siteUrl" | "nextAiringEpisode">;
607
607
  }
608
608
  interface MediaConnection {
609
609
  edges: MediaEdge[];
@@ -644,7 +644,7 @@ interface MediaStats {
644
644
  interface MediaRecommendationNode {
645
645
  id: number;
646
646
  rating: number | null;
647
- mediaRecommendation: Pick<Media, "id" | "title" | "type" | "format" | "coverImage" | "averageScore" | "siteUrl">;
647
+ mediaRecommendation: Pick<Media, "id" | "title" | "type" | "format" | "coverImage" | "averageScore" | "meanScore" | "episodes" | "chapters" | "volumes" | "nextAiringEpisode" | "season" | "seasonYear" | "startDate" | "endDate" | "studios" | "genres" | "siteUrl">;
648
648
  }
649
649
  interface NextAiringEpisode {
650
650
  id: number;
@@ -727,6 +727,8 @@ interface SearchMediaOptions {
727
727
  tagsExclude?: string[];
728
728
  /** Include or Exclude explicit content (default: false) */
729
729
  isAdult?: boolean;
730
+ /** Exclude certain media entries by ID */
731
+ idNotIn?: number[];
730
732
  /** Sort order */
731
733
  sort?: MediaSort[];
732
734
  /** Page number */
@@ -739,6 +741,8 @@ interface GeneralMediaQueryOptions {
739
741
  type?: MediaType;
740
742
  /** Include or Exclude explicit content (default: false) */
741
743
  isAdult?: boolean;
744
+ /** Exclude certain media entries by ID */
745
+ idNotIn?: number[];
742
746
  /** Page number */
743
747
  page?: number;
744
748
  /** Results per page (max 50) */
@@ -749,8 +753,8 @@ interface GetAiringOptions {
749
753
  airingAtGreater?: number;
750
754
  /** Only show episodes that aired before this UNIX timestamp */
751
755
  airingAtLesser?: number;
752
- /** Include or Exclude explicit content (default: false) */
753
- isAdult?: boolean;
756
+ /** Exclude certain media entries by ID */
757
+ idNotIn?: number[];
754
758
  /** Sort order (default: TIME_DESC) */
755
759
  sort?: AiringSort[];
756
760
  /** Page number */
@@ -761,6 +765,8 @@ interface GetAiringOptions {
761
765
  interface GetRecentChaptersOptions {
762
766
  /** Include or Exclude explicit content (default: false) */
763
767
  isAdult?: boolean;
768
+ /** Exclude certain media entries by ID */
769
+ idNotIn?: number[];
764
770
  /** Page number (default: 1) */
765
771
  page?: number;
766
772
  /** Results per page (default: 20, max 50) */
@@ -771,6 +777,8 @@ interface GetPlanningOptions {
771
777
  type?: MediaType;
772
778
  /** Include or Exclude explicit content (default: false) */
773
779
  isAdult?: boolean;
780
+ /** Exclude certain media entries by ID */
781
+ idNotIn?: number[];
774
782
  /** Sort order (default: POPULARITY_DESC) */
775
783
  sort?: MediaSort[];
776
784
  /** Page number */
@@ -814,6 +822,8 @@ interface GetSeasonOptions {
814
822
  type?: MediaType;
815
823
  /** Allow or disallow explicit content (defaults to False) */
816
824
  isAdult?: boolean;
825
+ /** Exclude certain media entries by ID */
826
+ idNotIn?: number[];
817
827
  /** Sort order (default: POPULARITY_DESC) */
818
828
  sort?: MediaSort[];
819
829
  /** Page number */
@@ -942,6 +952,44 @@ interface SearchCharacterOptions {
942
952
  voiceActors?: boolean;
943
953
  }
944
954
 
955
+ declare enum ReviewSort {
956
+ ID = "ID",
957
+ ID_DESC = "ID_DESC",
958
+ SCORE = "SCORE",
959
+ SCORE_DESC = "SCORE_DESC",
960
+ RATING = "RATING",
961
+ RATING_DESC = "RATING_DESC",
962
+ CREATED_AT = "CREATED_AT",
963
+ CREATED_AT_DESC = "CREATED_AT_DESC",
964
+ UPDATED_AT = "UPDATED_AT",
965
+ UPDATED_AT_DESC = "UPDATED_AT_DESC"
966
+ }
967
+ interface Review {
968
+ id: number;
969
+ userId: number;
970
+ mediaId: number;
971
+ mediaType: "ANIME" | "MANGA";
972
+ summary: string;
973
+ body: string;
974
+ rating: number;
975
+ ratingAmount: number;
976
+ userRating: "UP_VOTE" | "DOWN_VOTE" | "NO_VOTE";
977
+ score: number;
978
+ private: boolean;
979
+ siteUrl: string;
980
+ createdAt: number;
981
+ updatedAt: number;
982
+ user: User;
983
+ media: Media;
984
+ }
985
+ interface SearchReviewOptions {
986
+ mediaId?: number;
987
+ userId?: number;
988
+ sort?: ReviewSort[];
989
+ page?: number;
990
+ perPage?: number;
991
+ }
992
+
945
993
  /** Represents a forum thread on AniList. */
946
994
  interface Thread {
947
995
  id: number;
@@ -1293,6 +1341,19 @@ declare class AniListClient {
1293
1341
  * ```
1294
1342
  */
1295
1343
  getUserFavorites(idOrName: number | string, options?: UserFavoritesOptions): Promise<UserFavorites>;
1344
+ /**
1345
+ * Fetch a review by its AniList ID.
1346
+ *
1347
+ * @param id - The AniList review ID
1348
+ */
1349
+ getReview(id: number): Promise<Review>;
1350
+ /**
1351
+ * Search for reviews with optional filters.
1352
+ *
1353
+ * @param options - Search and filter options
1354
+ * @returns Paginated results with matching reviews
1355
+ */
1356
+ searchReviews(options?: SearchReviewOptions): Promise<PagedResult<Review>>;
1296
1357
  /**
1297
1358
  * Fetch a studio by its AniList ID.
1298
1359
  * Pass `include` to customise the number of media returned.
@@ -1412,4 +1473,4 @@ declare class RateLimiter {
1412
1473
 
1413
1474
  declare function parseAniListMarkdown(text: string): string;
1414
1475
 
1415
- export { type AiringSchedule, AiringSort, AniListClient, type AniListClientOptions, AniListError, type AniListHooks, type CacheAdapter, type CacheOptions, type CacheStats, type Character, type CharacterImage, type CharacterIncludeOptions, type CharacterMediaEdge, type CharacterName, CharacterRole, CharacterSort, type DayOfWeek, type ExternalLink, type FavoriteCharacterNode, type FavoriteMediaNode, type FavoriteStaffNode, type FavoriteStudioNode, type FuzzyDate, type GetAiringOptions, type GetMediaCharactersOptions, type GetMediaStaffOptions, type GetPlanningOptions, type GetRecentChaptersOptions, type GetRecommendationsOptions, type GetSeasonOptions, type GetUserMediaListOptions, type Logger, type Media, type MediaCharacterConnection, type MediaCharacterEdge, type MediaConnection, type MediaCoverImage, type MediaEdge, MediaFormat, type MediaIncludeOptions, type MediaListEntry, MediaListSort, MediaListStatus, type MediaRecommendationNode, MediaRelationType, MediaSeason, MediaSort, MediaSource, type MediaStaffConnection, type MediaStaffEdge, type MediaStats, MediaStatus, type MediaTag, type MediaTitle, type MediaTrailer, MediaType, MemoryCache, type NextAiringEpisode, type PageInfo, type PagedResult, type RateLimitInfo, type RateLimitOptions, RateLimiter, type Recommendation, RecommendationSort, RedisCache, type RedisCacheOptions, type RedisLikeClient, type ResponseMeta, type ScoreDistribution, type SearchCharacterOptions, type SearchMediaOptions, type SearchStaffOptions, type SearchStudioOptions, type SearchThreadOptions, type SearchUserOptions, type Staff, type StaffImage, type StaffIncludeOptions, type StaffMediaNode, type StaffName, StaffSort, type StatusDistribution, type StreamingEpisode, type Studio, type StudioConnection, type StudioIncludeOptions, StudioSort, type Thread, type ThreadCategory, type ThreadMediaCategory, ThreadSort, type User, type UserAvatar, type UserFavorites, type UserFavoritesOptions, UserSort, type UserStatistics, type VoiceActor, type WeeklySchedule, parseAniListMarkdown };
1476
+ export { type AiringSchedule, AiringSort, AniListClient, type AniListClientOptions, AniListError, type AniListHooks, type CacheAdapter, type CacheOptions, type CacheStats, type Character, type CharacterImage, type CharacterIncludeOptions, type CharacterMediaEdge, type CharacterName, CharacterRole, CharacterSort, type DayOfWeek, type ExternalLink, type FavoriteCharacterNode, type FavoriteMediaNode, type FavoriteStaffNode, type FavoriteStudioNode, type FuzzyDate, type GetAiringOptions, type GetMediaCharactersOptions, type GetMediaStaffOptions, type GetPlanningOptions, type GetRecentChaptersOptions, type GetRecommendationsOptions, type GetSeasonOptions, type GetUserMediaListOptions, type Logger, type Media, type MediaCharacterConnection, type MediaCharacterEdge, type MediaConnection, type MediaCoverImage, type MediaEdge, MediaFormat, type MediaIncludeOptions, type MediaListEntry, MediaListSort, MediaListStatus, type MediaRecommendationNode, MediaRelationType, MediaSeason, MediaSort, MediaSource, type MediaStaffConnection, type MediaStaffEdge, type MediaStats, MediaStatus, type MediaTag, type MediaTitle, type MediaTrailer, MediaType, MemoryCache, type NextAiringEpisode, type PageInfo, type PagedResult, type RateLimitInfo, type RateLimitOptions, RateLimiter, type Recommendation, RecommendationSort, RedisCache, type RedisCacheOptions, type RedisLikeClient, type ResponseMeta, type Review, ReviewSort, type ScoreDistribution, type SearchCharacterOptions, type SearchMediaOptions, type SearchReviewOptions, type SearchStaffOptions, type SearchStudioOptions, type SearchThreadOptions, type SearchUserOptions, type Staff, type StaffImage, type StaffIncludeOptions, type StaffMediaNode, type StaffName, StaffSort, type StatusDistribution, type StreamingEpisode, type Studio, type StudioConnection, type StudioIncludeOptions, StudioSort, type Thread, type ThreadCategory, type ThreadMediaCategory, ThreadSort, type User, type UserAvatar, type UserFavorites, type UserFavoritesOptions, UserSort, type UserStatistics, type VoiceActor, type WeeklySchedule, parseAniListMarkdown };
package/dist/index.d.ts CHANGED
@@ -603,7 +603,7 @@ declare enum MediaRelationType {
603
603
  }
604
604
  interface MediaEdge {
605
605
  relationType: MediaRelationType;
606
- node: Pick<Media, "id" | "title" | "type" | "format" | "status" | "startDate" | "endDate" | "season" | "seasonYear" | "episodes" | "chapters" | "volumes" | "coverImage" | "genres" | "averageScore" | "studios" | "siteUrl" | "nextAiringEpisode">;
606
+ node: Pick<Media, "id" | "title" | "type" | "format" | "status" | "startDate" | "endDate" | "season" | "seasonYear" | "episodes" | "chapters" | "volumes" | "coverImage" | "genres" | "averageScore" | "meanScore" | "studios" | "siteUrl" | "nextAiringEpisode">;
607
607
  }
608
608
  interface MediaConnection {
609
609
  edges: MediaEdge[];
@@ -644,7 +644,7 @@ interface MediaStats {
644
644
  interface MediaRecommendationNode {
645
645
  id: number;
646
646
  rating: number | null;
647
- mediaRecommendation: Pick<Media, "id" | "title" | "type" | "format" | "coverImage" | "averageScore" | "siteUrl">;
647
+ mediaRecommendation: Pick<Media, "id" | "title" | "type" | "format" | "coverImage" | "averageScore" | "meanScore" | "episodes" | "chapters" | "volumes" | "nextAiringEpisode" | "season" | "seasonYear" | "startDate" | "endDate" | "studios" | "genres" | "siteUrl">;
648
648
  }
649
649
  interface NextAiringEpisode {
650
650
  id: number;
@@ -727,6 +727,8 @@ interface SearchMediaOptions {
727
727
  tagsExclude?: string[];
728
728
  /** Include or Exclude explicit content (default: false) */
729
729
  isAdult?: boolean;
730
+ /** Exclude certain media entries by ID */
731
+ idNotIn?: number[];
730
732
  /** Sort order */
731
733
  sort?: MediaSort[];
732
734
  /** Page number */
@@ -739,6 +741,8 @@ interface GeneralMediaQueryOptions {
739
741
  type?: MediaType;
740
742
  /** Include or Exclude explicit content (default: false) */
741
743
  isAdult?: boolean;
744
+ /** Exclude certain media entries by ID */
745
+ idNotIn?: number[];
742
746
  /** Page number */
743
747
  page?: number;
744
748
  /** Results per page (max 50) */
@@ -749,8 +753,8 @@ interface GetAiringOptions {
749
753
  airingAtGreater?: number;
750
754
  /** Only show episodes that aired before this UNIX timestamp */
751
755
  airingAtLesser?: number;
752
- /** Include or Exclude explicit content (default: false) */
753
- isAdult?: boolean;
756
+ /** Exclude certain media entries by ID */
757
+ idNotIn?: number[];
754
758
  /** Sort order (default: TIME_DESC) */
755
759
  sort?: AiringSort[];
756
760
  /** Page number */
@@ -761,6 +765,8 @@ interface GetAiringOptions {
761
765
  interface GetRecentChaptersOptions {
762
766
  /** Include or Exclude explicit content (default: false) */
763
767
  isAdult?: boolean;
768
+ /** Exclude certain media entries by ID */
769
+ idNotIn?: number[];
764
770
  /** Page number (default: 1) */
765
771
  page?: number;
766
772
  /** Results per page (default: 20, max 50) */
@@ -771,6 +777,8 @@ interface GetPlanningOptions {
771
777
  type?: MediaType;
772
778
  /** Include or Exclude explicit content (default: false) */
773
779
  isAdult?: boolean;
780
+ /** Exclude certain media entries by ID */
781
+ idNotIn?: number[];
774
782
  /** Sort order (default: POPULARITY_DESC) */
775
783
  sort?: MediaSort[];
776
784
  /** Page number */
@@ -814,6 +822,8 @@ interface GetSeasonOptions {
814
822
  type?: MediaType;
815
823
  /** Allow or disallow explicit content (defaults to False) */
816
824
  isAdult?: boolean;
825
+ /** Exclude certain media entries by ID */
826
+ idNotIn?: number[];
817
827
  /** Sort order (default: POPULARITY_DESC) */
818
828
  sort?: MediaSort[];
819
829
  /** Page number */
@@ -942,6 +952,44 @@ interface SearchCharacterOptions {
942
952
  voiceActors?: boolean;
943
953
  }
944
954
 
955
+ declare enum ReviewSort {
956
+ ID = "ID",
957
+ ID_DESC = "ID_DESC",
958
+ SCORE = "SCORE",
959
+ SCORE_DESC = "SCORE_DESC",
960
+ RATING = "RATING",
961
+ RATING_DESC = "RATING_DESC",
962
+ CREATED_AT = "CREATED_AT",
963
+ CREATED_AT_DESC = "CREATED_AT_DESC",
964
+ UPDATED_AT = "UPDATED_AT",
965
+ UPDATED_AT_DESC = "UPDATED_AT_DESC"
966
+ }
967
+ interface Review {
968
+ id: number;
969
+ userId: number;
970
+ mediaId: number;
971
+ mediaType: "ANIME" | "MANGA";
972
+ summary: string;
973
+ body: string;
974
+ rating: number;
975
+ ratingAmount: number;
976
+ userRating: "UP_VOTE" | "DOWN_VOTE" | "NO_VOTE";
977
+ score: number;
978
+ private: boolean;
979
+ siteUrl: string;
980
+ createdAt: number;
981
+ updatedAt: number;
982
+ user: User;
983
+ media: Media;
984
+ }
985
+ interface SearchReviewOptions {
986
+ mediaId?: number;
987
+ userId?: number;
988
+ sort?: ReviewSort[];
989
+ page?: number;
990
+ perPage?: number;
991
+ }
992
+
945
993
  /** Represents a forum thread on AniList. */
946
994
  interface Thread {
947
995
  id: number;
@@ -1293,6 +1341,19 @@ declare class AniListClient {
1293
1341
  * ```
1294
1342
  */
1295
1343
  getUserFavorites(idOrName: number | string, options?: UserFavoritesOptions): Promise<UserFavorites>;
1344
+ /**
1345
+ * Fetch a review by its AniList ID.
1346
+ *
1347
+ * @param id - The AniList review ID
1348
+ */
1349
+ getReview(id: number): Promise<Review>;
1350
+ /**
1351
+ * Search for reviews with optional filters.
1352
+ *
1353
+ * @param options - Search and filter options
1354
+ * @returns Paginated results with matching reviews
1355
+ */
1356
+ searchReviews(options?: SearchReviewOptions): Promise<PagedResult<Review>>;
1296
1357
  /**
1297
1358
  * Fetch a studio by its AniList ID.
1298
1359
  * Pass `include` to customise the number of media returned.
@@ -1412,4 +1473,4 @@ declare class RateLimiter {
1412
1473
 
1413
1474
  declare function parseAniListMarkdown(text: string): string;
1414
1475
 
1415
- export { type AiringSchedule, AiringSort, AniListClient, type AniListClientOptions, AniListError, type AniListHooks, type CacheAdapter, type CacheOptions, type CacheStats, type Character, type CharacterImage, type CharacterIncludeOptions, type CharacterMediaEdge, type CharacterName, CharacterRole, CharacterSort, type DayOfWeek, type ExternalLink, type FavoriteCharacterNode, type FavoriteMediaNode, type FavoriteStaffNode, type FavoriteStudioNode, type FuzzyDate, type GetAiringOptions, type GetMediaCharactersOptions, type GetMediaStaffOptions, type GetPlanningOptions, type GetRecentChaptersOptions, type GetRecommendationsOptions, type GetSeasonOptions, type GetUserMediaListOptions, type Logger, type Media, type MediaCharacterConnection, type MediaCharacterEdge, type MediaConnection, type MediaCoverImage, type MediaEdge, MediaFormat, type MediaIncludeOptions, type MediaListEntry, MediaListSort, MediaListStatus, type MediaRecommendationNode, MediaRelationType, MediaSeason, MediaSort, MediaSource, type MediaStaffConnection, type MediaStaffEdge, type MediaStats, MediaStatus, type MediaTag, type MediaTitle, type MediaTrailer, MediaType, MemoryCache, type NextAiringEpisode, type PageInfo, type PagedResult, type RateLimitInfo, type RateLimitOptions, RateLimiter, type Recommendation, RecommendationSort, RedisCache, type RedisCacheOptions, type RedisLikeClient, type ResponseMeta, type ScoreDistribution, type SearchCharacterOptions, type SearchMediaOptions, type SearchStaffOptions, type SearchStudioOptions, type SearchThreadOptions, type SearchUserOptions, type Staff, type StaffImage, type StaffIncludeOptions, type StaffMediaNode, type StaffName, StaffSort, type StatusDistribution, type StreamingEpisode, type Studio, type StudioConnection, type StudioIncludeOptions, StudioSort, type Thread, type ThreadCategory, type ThreadMediaCategory, ThreadSort, type User, type UserAvatar, type UserFavorites, type UserFavoritesOptions, UserSort, type UserStatistics, type VoiceActor, type WeeklySchedule, parseAniListMarkdown };
1476
+ export { type AiringSchedule, AiringSort, AniListClient, type AniListClientOptions, AniListError, type AniListHooks, type CacheAdapter, type CacheOptions, type CacheStats, type Character, type CharacterImage, type CharacterIncludeOptions, type CharacterMediaEdge, type CharacterName, CharacterRole, CharacterSort, type DayOfWeek, type ExternalLink, type FavoriteCharacterNode, type FavoriteMediaNode, type FavoriteStaffNode, type FavoriteStudioNode, type FuzzyDate, type GetAiringOptions, type GetMediaCharactersOptions, type GetMediaStaffOptions, type GetPlanningOptions, type GetRecentChaptersOptions, type GetRecommendationsOptions, type GetSeasonOptions, type GetUserMediaListOptions, type Logger, type Media, type MediaCharacterConnection, type MediaCharacterEdge, type MediaConnection, type MediaCoverImage, type MediaEdge, MediaFormat, type MediaIncludeOptions, type MediaListEntry, MediaListSort, MediaListStatus, type MediaRecommendationNode, MediaRelationType, MediaSeason, MediaSort, MediaSource, type MediaStaffConnection, type MediaStaffEdge, type MediaStats, MediaStatus, type MediaTag, type MediaTitle, type MediaTrailer, MediaType, MemoryCache, type NextAiringEpisode, type PageInfo, type PagedResult, type RateLimitInfo, type RateLimitOptions, RateLimiter, type Recommendation, RecommendationSort, RedisCache, type RedisCacheOptions, type RedisLikeClient, type ResponseMeta, type Review, ReviewSort, type ScoreDistribution, type SearchCharacterOptions, type SearchMediaOptions, type SearchReviewOptions, type SearchStaffOptions, type SearchStudioOptions, type SearchThreadOptions, type SearchUserOptions, type Staff, type StaffImage, type StaffIncludeOptions, type StaffMediaNode, type StaffName, StaffSort, type StatusDistribution, type StreamingEpisode, type Studio, type StudioConnection, type StudioIncludeOptions, StudioSort, type Thread, type ThreadCategory, type ThreadMediaCategory, ThreadSort, type User, type UserAvatar, type UserFavorites, type UserFavoritesOptions, UserSort, type UserStatistics, type VoiceActor, type WeeklySchedule, parseAniListMarkdown };