ani-client 1.8.0 → 1.8.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 +1 -3
- package/dist/index.d.mts +326 -322
- package/dist/index.d.ts +326 -322
- package/dist/index.js +367 -356
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +367 -356
- package/dist/index.mjs.map +1 -1
- package/package.json +23 -6
package/README.md
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
# ani-client
|
|
2
2
|
|
|
3
|
-

|
|
4
|
-
|
|
5
3
|
[](https://github.com/gonzyui/ani-client/actions/workflows/ci.yml)
|
|
6
4
|
[](https://www.npmjs.com/package/ani-client)
|
|
7
5
|
[](https://www.npmjs.com/package/ani-client)
|
|
8
|
-
[](https://codecov.io/gh/gonzyui/ani-client)
|
|
9
7
|
[](https://www.typescriptlang.org/)
|
|
10
8
|
[](LICENSE)
|
|
11
9
|
|
package/dist/index.d.mts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
interface PageInfo {
|
|
2
2
|
total: number | null;
|
|
3
|
-
perPage: number
|
|
4
|
-
currentPage: number
|
|
5
|
-
lastPage: number
|
|
6
|
-
hasNextPage: boolean
|
|
3
|
+
perPage: number;
|
|
4
|
+
currentPage: number;
|
|
5
|
+
lastPage: number;
|
|
6
|
+
hasNextPage: boolean;
|
|
7
7
|
}
|
|
8
8
|
interface PagedResult<T> {
|
|
9
9
|
pageInfo: PageInfo;
|
|
@@ -155,6 +155,78 @@ interface AniListClientOptions {
|
|
|
155
155
|
logger?: Logger;
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
+
declare enum MediaListStatus {
|
|
159
|
+
CURRENT = "CURRENT",
|
|
160
|
+
PLANNING = "PLANNING",
|
|
161
|
+
COMPLETED = "COMPLETED",
|
|
162
|
+
DROPPED = "DROPPED",
|
|
163
|
+
PAUSED = "PAUSED",
|
|
164
|
+
REPEATING = "REPEATING"
|
|
165
|
+
}
|
|
166
|
+
declare enum MediaListSort {
|
|
167
|
+
MEDIA_ID = "MEDIA_ID",
|
|
168
|
+
MEDIA_ID_DESC = "MEDIA_ID_DESC",
|
|
169
|
+
SCORE = "SCORE",
|
|
170
|
+
SCORE_DESC = "SCORE_DESC",
|
|
171
|
+
STATUS = "STATUS",
|
|
172
|
+
STATUS_DESC = "STATUS_DESC",
|
|
173
|
+
PROGRESS = "PROGRESS",
|
|
174
|
+
PROGRESS_DESC = "PROGRESS_DESC",
|
|
175
|
+
PROGRESS_VOLUMES = "PROGRESS_VOLUMES",
|
|
176
|
+
PROGRESS_VOLUMES_DESC = "PROGRESS_VOLUMES_DESC",
|
|
177
|
+
REPEAT = "REPEAT",
|
|
178
|
+
REPEAT_DESC = "REPEAT_DESC",
|
|
179
|
+
PRIORITY = "PRIORITY",
|
|
180
|
+
PRIORITY_DESC = "PRIORITY_DESC",
|
|
181
|
+
STARTED_ON = "STARTED_ON",
|
|
182
|
+
STARTED_ON_DESC = "STARTED_ON_DESC",
|
|
183
|
+
FINISHED_ON = "FINISHED_ON",
|
|
184
|
+
FINISHED_ON_DESC = "FINISHED_ON_DESC",
|
|
185
|
+
ADDED_TIME = "ADDED_TIME",
|
|
186
|
+
ADDED_TIME_DESC = "ADDED_TIME_DESC",
|
|
187
|
+
UPDATED_TIME = "UPDATED_TIME",
|
|
188
|
+
UPDATED_TIME_DESC = "UPDATED_TIME_DESC",
|
|
189
|
+
MEDIA_TITLE_ROMAJI = "MEDIA_TITLE_ROMAJI",
|
|
190
|
+
MEDIA_TITLE_ROMAJI_DESC = "MEDIA_TITLE_ROMAJI_DESC",
|
|
191
|
+
MEDIA_TITLE_ENGLISH = "MEDIA_TITLE_ENGLISH",
|
|
192
|
+
MEDIA_TITLE_ENGLISH_DESC = "MEDIA_TITLE_ENGLISH_DESC",
|
|
193
|
+
MEDIA_TITLE_NATIVE = "MEDIA_TITLE_NATIVE",
|
|
194
|
+
MEDIA_TITLE_NATIVE_DESC = "MEDIA_TITLE_NATIVE_DESC",
|
|
195
|
+
MEDIA_POPULARITY = "MEDIA_POPULARITY",
|
|
196
|
+
MEDIA_POPULARITY_DESC = "MEDIA_POPULARITY_DESC"
|
|
197
|
+
}
|
|
198
|
+
interface MediaListEntry {
|
|
199
|
+
id: number;
|
|
200
|
+
mediaId: number;
|
|
201
|
+
status: MediaListStatus;
|
|
202
|
+
score: number | null;
|
|
203
|
+
progress: number | null;
|
|
204
|
+
progressVolumes: number | null;
|
|
205
|
+
repeat: number | null;
|
|
206
|
+
priority: number | null;
|
|
207
|
+
private: boolean | null;
|
|
208
|
+
notes: string | null;
|
|
209
|
+
startedAt: FuzzyDate | null;
|
|
210
|
+
completedAt: FuzzyDate | null;
|
|
211
|
+
updatedAt: number | null;
|
|
212
|
+
createdAt: number | null;
|
|
213
|
+
media: Media;
|
|
214
|
+
}
|
|
215
|
+
interface GetUserMediaListOptions {
|
|
216
|
+
/** User ID (provide either userId or userName) */
|
|
217
|
+
userId?: number;
|
|
218
|
+
/** Username (provide either userId or userName) */
|
|
219
|
+
userName?: string;
|
|
220
|
+
/** ANIME or MANGA */
|
|
221
|
+
type: MediaType;
|
|
222
|
+
/** Filter by list status (CURRENT, COMPLETED, etc.) */
|
|
223
|
+
status?: MediaListStatus;
|
|
224
|
+
/** Sort order */
|
|
225
|
+
sort?: MediaListSort[];
|
|
226
|
+
page?: number;
|
|
227
|
+
perPage?: number;
|
|
228
|
+
}
|
|
229
|
+
|
|
158
230
|
declare enum StaffSort {
|
|
159
231
|
ID = "ID",
|
|
160
232
|
ID_DESC = "ID_DESC",
|
|
@@ -259,139 +331,6 @@ interface VoiceActor extends Pick<Staff, "id" | "image" | "gender" | "primaryOcc
|
|
|
259
331
|
languageV2: string | null;
|
|
260
332
|
}
|
|
261
333
|
|
|
262
|
-
declare enum CharacterSort {
|
|
263
|
-
ID = "ID",
|
|
264
|
-
ID_DESC = "ID_DESC",
|
|
265
|
-
ROLE = "ROLE",
|
|
266
|
-
ROLE_DESC = "ROLE_DESC",
|
|
267
|
-
SEARCH_MATCH = "SEARCH_MATCH",
|
|
268
|
-
FAVOURITES = "FAVOURITES",
|
|
269
|
-
FAVOURITES_DESC = "FAVOURITES_DESC"
|
|
270
|
-
}
|
|
271
|
-
declare enum CharacterRole {
|
|
272
|
-
MAIN = "MAIN",
|
|
273
|
-
SUPPORTING = "SUPPORTING",
|
|
274
|
-
BACKGROUND = "BACKGROUND"
|
|
275
|
-
}
|
|
276
|
-
interface CharacterName {
|
|
277
|
-
first: string | null;
|
|
278
|
-
middle: string | null;
|
|
279
|
-
last: string | null;
|
|
280
|
-
full: string | null;
|
|
281
|
-
native: string | null;
|
|
282
|
-
alternative: string[];
|
|
283
|
-
}
|
|
284
|
-
interface CharacterImage {
|
|
285
|
-
large: string | null;
|
|
286
|
-
medium: string | null;
|
|
287
|
-
}
|
|
288
|
-
type CharacterMediaNode = Pick<Media, "id" | "title" | "type" | "coverImage" | "siteUrl">;
|
|
289
|
-
interface CharacterMediaEdge {
|
|
290
|
-
node: CharacterMediaNode;
|
|
291
|
-
voiceActors?: VoiceActor[];
|
|
292
|
-
}
|
|
293
|
-
interface Character {
|
|
294
|
-
id: number;
|
|
295
|
-
name: CharacterName;
|
|
296
|
-
image: CharacterImage;
|
|
297
|
-
description: string | null;
|
|
298
|
-
gender: string | null;
|
|
299
|
-
dateOfBirth: FuzzyDate | null;
|
|
300
|
-
age: string | null;
|
|
301
|
-
bloodType: string | null;
|
|
302
|
-
favourites: number | null;
|
|
303
|
-
siteUrl: string | null;
|
|
304
|
-
media: {
|
|
305
|
-
nodes?: CharacterMediaNode[];
|
|
306
|
-
edges?: CharacterMediaEdge[];
|
|
307
|
-
} | null;
|
|
308
|
-
}
|
|
309
|
-
/** Options for including extra data when fetching a character. */
|
|
310
|
-
interface CharacterIncludeOptions {
|
|
311
|
-
/** Include voice actors for each media the character appears in. */
|
|
312
|
-
voiceActors?: boolean;
|
|
313
|
-
}
|
|
314
|
-
interface SearchCharacterOptions {
|
|
315
|
-
query?: string;
|
|
316
|
-
sort?: CharacterSort[];
|
|
317
|
-
page?: number;
|
|
318
|
-
perPage?: number;
|
|
319
|
-
/** Include voice actors for each media the character appears in. */
|
|
320
|
-
voiceActors?: boolean;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
declare enum MediaListStatus {
|
|
324
|
-
CURRENT = "CURRENT",
|
|
325
|
-
PLANNING = "PLANNING",
|
|
326
|
-
COMPLETED = "COMPLETED",
|
|
327
|
-
DROPPED = "DROPPED",
|
|
328
|
-
PAUSED = "PAUSED",
|
|
329
|
-
REPEATING = "REPEATING"
|
|
330
|
-
}
|
|
331
|
-
declare enum MediaListSort {
|
|
332
|
-
MEDIA_ID = "MEDIA_ID",
|
|
333
|
-
MEDIA_ID_DESC = "MEDIA_ID_DESC",
|
|
334
|
-
SCORE = "SCORE",
|
|
335
|
-
SCORE_DESC = "SCORE_DESC",
|
|
336
|
-
STATUS = "STATUS",
|
|
337
|
-
STATUS_DESC = "STATUS_DESC",
|
|
338
|
-
PROGRESS = "PROGRESS",
|
|
339
|
-
PROGRESS_DESC = "PROGRESS_DESC",
|
|
340
|
-
PROGRESS_VOLUMES = "PROGRESS_VOLUMES",
|
|
341
|
-
PROGRESS_VOLUMES_DESC = "PROGRESS_VOLUMES_DESC",
|
|
342
|
-
REPEAT = "REPEAT",
|
|
343
|
-
REPEAT_DESC = "REPEAT_DESC",
|
|
344
|
-
PRIORITY = "PRIORITY",
|
|
345
|
-
PRIORITY_DESC = "PRIORITY_DESC",
|
|
346
|
-
STARTED_ON = "STARTED_ON",
|
|
347
|
-
STARTED_ON_DESC = "STARTED_ON_DESC",
|
|
348
|
-
FINISHED_ON = "FINISHED_ON",
|
|
349
|
-
FINISHED_ON_DESC = "FINISHED_ON_DESC",
|
|
350
|
-
ADDED_TIME = "ADDED_TIME",
|
|
351
|
-
ADDED_TIME_DESC = "ADDED_TIME_DESC",
|
|
352
|
-
UPDATED_TIME = "UPDATED_TIME",
|
|
353
|
-
UPDATED_TIME_DESC = "UPDATED_TIME_DESC",
|
|
354
|
-
MEDIA_TITLE_ROMAJI = "MEDIA_TITLE_ROMAJI",
|
|
355
|
-
MEDIA_TITLE_ROMAJI_DESC = "MEDIA_TITLE_ROMAJI_DESC",
|
|
356
|
-
MEDIA_TITLE_ENGLISH = "MEDIA_TITLE_ENGLISH",
|
|
357
|
-
MEDIA_TITLE_ENGLISH_DESC = "MEDIA_TITLE_ENGLISH_DESC",
|
|
358
|
-
MEDIA_TITLE_NATIVE = "MEDIA_TITLE_NATIVE",
|
|
359
|
-
MEDIA_TITLE_NATIVE_DESC = "MEDIA_TITLE_NATIVE_DESC",
|
|
360
|
-
MEDIA_POPULARITY = "MEDIA_POPULARITY",
|
|
361
|
-
MEDIA_POPULARITY_DESC = "MEDIA_POPULARITY_DESC"
|
|
362
|
-
}
|
|
363
|
-
interface MediaListEntry {
|
|
364
|
-
id: number;
|
|
365
|
-
mediaId: number;
|
|
366
|
-
status: MediaListStatus;
|
|
367
|
-
score: number | null;
|
|
368
|
-
progress: number | null;
|
|
369
|
-
progressVolumes: number | null;
|
|
370
|
-
repeat: number | null;
|
|
371
|
-
priority: number | null;
|
|
372
|
-
private: boolean | null;
|
|
373
|
-
notes: string | null;
|
|
374
|
-
startedAt: FuzzyDate | null;
|
|
375
|
-
completedAt: FuzzyDate | null;
|
|
376
|
-
updatedAt: number | null;
|
|
377
|
-
createdAt: number | null;
|
|
378
|
-
media: Media;
|
|
379
|
-
}
|
|
380
|
-
interface GetUserMediaListOptions {
|
|
381
|
-
/** User ID (provide either userId or userName) */
|
|
382
|
-
userId?: number;
|
|
383
|
-
/** Username (provide either userId or userName) */
|
|
384
|
-
userName?: string;
|
|
385
|
-
/** ANIME or MANGA */
|
|
386
|
-
type: MediaType;
|
|
387
|
-
/** Filter by list status (CURRENT, COMPLETED, etc.) */
|
|
388
|
-
status?: MediaListStatus;
|
|
389
|
-
/** Sort order */
|
|
390
|
-
sort?: MediaListSort[];
|
|
391
|
-
page?: number;
|
|
392
|
-
perPage?: number;
|
|
393
|
-
}
|
|
394
|
-
|
|
395
334
|
interface Studio {
|
|
396
335
|
id: number;
|
|
397
336
|
name: string;
|
|
@@ -644,6 +583,7 @@ interface MediaTag {
|
|
|
644
583
|
description: string | null;
|
|
645
584
|
category: string | null;
|
|
646
585
|
rank: number | null;
|
|
586
|
+
isAdult: boolean | null;
|
|
647
587
|
isMediaSpoiler: boolean | null;
|
|
648
588
|
}
|
|
649
589
|
declare enum MediaRelationType {
|
|
@@ -885,57 +825,118 @@ interface AiringSchedule {
|
|
|
885
825
|
type DayOfWeek = "Monday" | "Tuesday" | "Wednesday" | "Thursday" | "Friday" | "Saturday" | "Sunday";
|
|
886
826
|
type WeeklySchedule = Record<DayOfWeek, AiringSchedule[]>;
|
|
887
827
|
|
|
888
|
-
|
|
889
|
-
interface Thread {
|
|
890
|
-
id: number;
|
|
891
|
-
title: string;
|
|
892
|
-
body: string | null;
|
|
893
|
-
userId: number;
|
|
894
|
-
replyUserId: number | null;
|
|
895
|
-
replyCommentId: number | null;
|
|
896
|
-
replyCount: number;
|
|
897
|
-
viewCount: number;
|
|
898
|
-
isLocked: boolean;
|
|
899
|
-
isSticky: boolean;
|
|
900
|
-
isSubscribed: boolean;
|
|
901
|
-
repliedAt: number | null;
|
|
902
|
-
createdAt: number;
|
|
903
|
-
updatedAt: number;
|
|
904
|
-
siteUrl: string | null;
|
|
905
|
-
user: {
|
|
906
|
-
id: number;
|
|
907
|
-
name: string;
|
|
908
|
-
avatar: UserAvatar;
|
|
909
|
-
} | null;
|
|
910
|
-
replyUser: {
|
|
911
|
-
id: number;
|
|
912
|
-
name: string;
|
|
913
|
-
avatar: UserAvatar;
|
|
914
|
-
} | null;
|
|
915
|
-
categories: ThreadCategory[] | null;
|
|
916
|
-
mediaCategories: ThreadMediaCategory[] | null;
|
|
917
|
-
likes: {
|
|
918
|
-
id: number;
|
|
919
|
-
name: string;
|
|
920
|
-
}[] | null;
|
|
921
|
-
}
|
|
922
|
-
interface ThreadCategory {
|
|
923
|
-
id: number;
|
|
924
|
-
name: string;
|
|
925
|
-
}
|
|
926
|
-
interface ThreadMediaCategory {
|
|
927
|
-
id: number;
|
|
928
|
-
title: MediaTitle;
|
|
929
|
-
type: MediaType;
|
|
930
|
-
coverImage: Pick<MediaCoverImage, "large" | "medium"> | null;
|
|
931
|
-
siteUrl: string | null;
|
|
932
|
-
}
|
|
933
|
-
/** Sort options for thread queries. */
|
|
934
|
-
declare enum ThreadSort {
|
|
828
|
+
declare enum CharacterSort {
|
|
935
829
|
ID = "ID",
|
|
936
830
|
ID_DESC = "ID_DESC",
|
|
937
|
-
|
|
938
|
-
|
|
831
|
+
ROLE = "ROLE",
|
|
832
|
+
ROLE_DESC = "ROLE_DESC",
|
|
833
|
+
SEARCH_MATCH = "SEARCH_MATCH",
|
|
834
|
+
FAVOURITES = "FAVOURITES",
|
|
835
|
+
FAVOURITES_DESC = "FAVOURITES_DESC"
|
|
836
|
+
}
|
|
837
|
+
declare enum CharacterRole {
|
|
838
|
+
MAIN = "MAIN",
|
|
839
|
+
SUPPORTING = "SUPPORTING",
|
|
840
|
+
BACKGROUND = "BACKGROUND"
|
|
841
|
+
}
|
|
842
|
+
interface CharacterName {
|
|
843
|
+
first: string | null;
|
|
844
|
+
middle: string | null;
|
|
845
|
+
last: string | null;
|
|
846
|
+
full: string | null;
|
|
847
|
+
native: string | null;
|
|
848
|
+
alternative: string[];
|
|
849
|
+
}
|
|
850
|
+
interface CharacterImage {
|
|
851
|
+
large: string | null;
|
|
852
|
+
medium: string | null;
|
|
853
|
+
}
|
|
854
|
+
type CharacterMediaNode = Pick<Media, "id" | "title" | "type" | "coverImage" | "siteUrl">;
|
|
855
|
+
interface CharacterMediaEdge {
|
|
856
|
+
node: CharacterMediaNode;
|
|
857
|
+
voiceActors?: VoiceActor[];
|
|
858
|
+
}
|
|
859
|
+
interface Character {
|
|
860
|
+
id: number;
|
|
861
|
+
name: CharacterName;
|
|
862
|
+
image: CharacterImage;
|
|
863
|
+
description: string | null;
|
|
864
|
+
gender: string | null;
|
|
865
|
+
dateOfBirth: FuzzyDate | null;
|
|
866
|
+
age: string | null;
|
|
867
|
+
bloodType: string | null;
|
|
868
|
+
favourites: number | null;
|
|
869
|
+
siteUrl: string | null;
|
|
870
|
+
media: {
|
|
871
|
+
nodes?: CharacterMediaNode[];
|
|
872
|
+
edges?: CharacterMediaEdge[];
|
|
873
|
+
} | null;
|
|
874
|
+
}
|
|
875
|
+
/** Options for including extra data when fetching a character. */
|
|
876
|
+
interface CharacterIncludeOptions {
|
|
877
|
+
/** Include voice actors for each media the character appears in. */
|
|
878
|
+
voiceActors?: boolean;
|
|
879
|
+
}
|
|
880
|
+
interface SearchCharacterOptions {
|
|
881
|
+
query?: string;
|
|
882
|
+
sort?: CharacterSort[];
|
|
883
|
+
page?: number;
|
|
884
|
+
perPage?: number;
|
|
885
|
+
/** Include voice actors for each media the character appears in. */
|
|
886
|
+
voiceActors?: boolean;
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
/** Represents a forum thread on AniList. */
|
|
890
|
+
interface Thread {
|
|
891
|
+
id: number;
|
|
892
|
+
title: string;
|
|
893
|
+
body: string | null;
|
|
894
|
+
userId: number;
|
|
895
|
+
replyUserId: number | null;
|
|
896
|
+
replyCommentId: number | null;
|
|
897
|
+
replyCount: number;
|
|
898
|
+
viewCount: number;
|
|
899
|
+
isLocked: boolean;
|
|
900
|
+
isSticky: boolean;
|
|
901
|
+
isSubscribed: boolean;
|
|
902
|
+
repliedAt: number | null;
|
|
903
|
+
createdAt: number;
|
|
904
|
+
updatedAt: number;
|
|
905
|
+
siteUrl: string | null;
|
|
906
|
+
user: {
|
|
907
|
+
id: number;
|
|
908
|
+
name: string;
|
|
909
|
+
avatar: UserAvatar;
|
|
910
|
+
} | null;
|
|
911
|
+
replyUser: {
|
|
912
|
+
id: number;
|
|
913
|
+
name: string;
|
|
914
|
+
avatar: UserAvatar;
|
|
915
|
+
} | null;
|
|
916
|
+
categories: ThreadCategory[] | null;
|
|
917
|
+
mediaCategories: ThreadMediaCategory[] | null;
|
|
918
|
+
likes: {
|
|
919
|
+
id: number;
|
|
920
|
+
name: string;
|
|
921
|
+
}[] | null;
|
|
922
|
+
}
|
|
923
|
+
interface ThreadCategory {
|
|
924
|
+
id: number;
|
|
925
|
+
name: string;
|
|
926
|
+
}
|
|
927
|
+
interface ThreadMediaCategory {
|
|
928
|
+
id: number;
|
|
929
|
+
title: MediaTitle;
|
|
930
|
+
type: MediaType;
|
|
931
|
+
coverImage: Pick<MediaCoverImage, "large" | "medium"> | null;
|
|
932
|
+
siteUrl: string | null;
|
|
933
|
+
}
|
|
934
|
+
/** Sort options for thread queries. */
|
|
935
|
+
declare enum ThreadSort {
|
|
936
|
+
ID = "ID",
|
|
937
|
+
ID_DESC = "ID_DESC",
|
|
938
|
+
TITLE = "TITLE",
|
|
939
|
+
TITLE_DESC = "TITLE_DESC",
|
|
939
940
|
CREATED_AT = "CREATED_AT",
|
|
940
941
|
CREATED_AT_DESC = "CREATED_AT_DESC",
|
|
941
942
|
UPDATED_AT = "UPDATED_AT",
|
|
@@ -965,6 +966,145 @@ interface SearchThreadOptions {
|
|
|
965
966
|
perPage?: number;
|
|
966
967
|
}
|
|
967
968
|
|
|
969
|
+
/** Cache performance statistics. */
|
|
970
|
+
interface CacheStats {
|
|
971
|
+
/** Total cache hits. */
|
|
972
|
+
hits: number;
|
|
973
|
+
/** Total cache misses. */
|
|
974
|
+
misses: number;
|
|
975
|
+
/** Stale entries returned (only with stale-while-revalidate). */
|
|
976
|
+
stales: number;
|
|
977
|
+
/** Hit rate as a ratio 0–1 (NaN if no requests yet). */
|
|
978
|
+
hitRate: number;
|
|
979
|
+
}
|
|
980
|
+
declare class MemoryCache implements CacheAdapter {
|
|
981
|
+
private readonly ttl;
|
|
982
|
+
private readonly maxSize;
|
|
983
|
+
private readonly enabled;
|
|
984
|
+
private readonly swrMs;
|
|
985
|
+
private readonly store;
|
|
986
|
+
private _hits;
|
|
987
|
+
private _misses;
|
|
988
|
+
private _stales;
|
|
989
|
+
constructor(options?: CacheOptions);
|
|
990
|
+
/** Build a deterministic cache key from a query + variables pair. */
|
|
991
|
+
static key(query: string, variables: Record<string, unknown>): string;
|
|
992
|
+
/**
|
|
993
|
+
* Retrieve a cached value, or `undefined` if missing / expired.
|
|
994
|
+
* With stale-while-revalidate enabled, returns stale data within the grace window
|
|
995
|
+
* and flags it so the caller can refresh in the background.
|
|
996
|
+
*/
|
|
997
|
+
get<T>(key: string): T | undefined;
|
|
998
|
+
/** Store a value in the cache. */
|
|
999
|
+
set<T>(key: string, data: T): void;
|
|
1000
|
+
/** Remove a specific entry. */
|
|
1001
|
+
delete(key: string): boolean;
|
|
1002
|
+
/** Clear the entire cache and reset statistics. */
|
|
1003
|
+
clear(): void;
|
|
1004
|
+
/** Number of entries currently stored. */
|
|
1005
|
+
get size(): number | Promise<number>;
|
|
1006
|
+
/** Return all cache keys. */
|
|
1007
|
+
keys(): string[];
|
|
1008
|
+
/**
|
|
1009
|
+
* Get cache performance statistics.
|
|
1010
|
+
*
|
|
1011
|
+
* @example
|
|
1012
|
+
* ```ts
|
|
1013
|
+
* const cache = new MemoryCache();
|
|
1014
|
+
* // ... after some usage ...
|
|
1015
|
+
* console.log(cache.stats);
|
|
1016
|
+
* // { hits: 42, misses: 8, stales: 0, hitRate: 0.84 }
|
|
1017
|
+
* ```
|
|
1018
|
+
*/
|
|
1019
|
+
get stats(): CacheStats;
|
|
1020
|
+
/** Reset cache statistics without clearing stored data. */
|
|
1021
|
+
resetStats(): void;
|
|
1022
|
+
/**
|
|
1023
|
+
* Remove all entries whose key matches the given pattern.
|
|
1024
|
+
*
|
|
1025
|
+
* - **String**: treated as a substring match (e.g. `"Media"` removes all keys containing `"Media"`).
|
|
1026
|
+
* - **RegExp**: tested against each key directly.
|
|
1027
|
+
*
|
|
1028
|
+
* @param pattern — A string (substring match) or RegExp.
|
|
1029
|
+
* @returns Number of entries removed.
|
|
1030
|
+
*/
|
|
1031
|
+
invalidate(pattern: string | RegExp): number;
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
/**
|
|
1035
|
+
* Minimal interface representing a Redis client.
|
|
1036
|
+
* Compatible with both `ioredis` and `redis` (node-redis v4+).
|
|
1037
|
+
*/
|
|
1038
|
+
interface RedisLikeClient {
|
|
1039
|
+
get(key: string): Promise<string | null>;
|
|
1040
|
+
set(key: string, value: string, ...args: unknown[]): Promise<unknown>;
|
|
1041
|
+
del(...keys: (string | string[])[]): Promise<number>;
|
|
1042
|
+
keys(pattern: string): Promise<string[]>;
|
|
1043
|
+
/** Optional SCAN-based iteration — used when available to avoid blocking the server. */
|
|
1044
|
+
scanIterator?(options: {
|
|
1045
|
+
MATCH: string;
|
|
1046
|
+
COUNT?: number;
|
|
1047
|
+
}): AsyncIterable<string>;
|
|
1048
|
+
}
|
|
1049
|
+
interface RedisCacheOptions {
|
|
1050
|
+
/** A Redis client instance (ioredis or node-redis). */
|
|
1051
|
+
client: RedisLikeClient;
|
|
1052
|
+
/** Key prefix to namespace ani-client entries (default: `"ani:"`) */
|
|
1053
|
+
prefix?: string;
|
|
1054
|
+
/** TTL in seconds (default: 86 400 = 24 h) */
|
|
1055
|
+
ttl?: number;
|
|
1056
|
+
}
|
|
1057
|
+
/**
|
|
1058
|
+
* Redis-backed cache adapter for AniListClient.
|
|
1059
|
+
*
|
|
1060
|
+
* @example
|
|
1061
|
+
* ```ts
|
|
1062
|
+
* import Redis from "ioredis";
|
|
1063
|
+
* import { AniListClient, RedisCache } from "ani-client";
|
|
1064
|
+
*
|
|
1065
|
+
* const redis = new Redis();
|
|
1066
|
+
* const client = new AniListClient({
|
|
1067
|
+
* cacheAdapter: new RedisCache({ client: redis }),
|
|
1068
|
+
* });
|
|
1069
|
+
* ```
|
|
1070
|
+
*/
|
|
1071
|
+
declare class RedisCache implements CacheAdapter {
|
|
1072
|
+
private readonly client;
|
|
1073
|
+
private readonly prefix;
|
|
1074
|
+
private readonly ttl;
|
|
1075
|
+
constructor(options: RedisCacheOptions);
|
|
1076
|
+
private prefixedKey;
|
|
1077
|
+
get<T>(key: string): Promise<T | undefined>;
|
|
1078
|
+
set<T>(key: string, data: T): Promise<void>;
|
|
1079
|
+
delete(key: string): Promise<boolean>;
|
|
1080
|
+
/**
|
|
1081
|
+
* Collect keys matching a pattern. Uses SCAN when available, falls back to KEYS.
|
|
1082
|
+
*
|
|
1083
|
+
* **Warning:** The `KEYS` fallback is O(N) and blocks the Redis server.
|
|
1084
|
+
* Provide a client with `scanIterator` support for production use.
|
|
1085
|
+
* @internal
|
|
1086
|
+
*/
|
|
1087
|
+
private collectKeys;
|
|
1088
|
+
clear(): Promise<void>;
|
|
1089
|
+
/**
|
|
1090
|
+
* Get the actual number of keys with this prefix in Redis.
|
|
1091
|
+
*/
|
|
1092
|
+
get size(): Promise<number>;
|
|
1093
|
+
/** @internal */
|
|
1094
|
+
private getSize;
|
|
1095
|
+
keys(): Promise<string[]>;
|
|
1096
|
+
/**
|
|
1097
|
+
* Remove all entries whose key matches the given pattern.
|
|
1098
|
+
*
|
|
1099
|
+
* - **String**: treated as a substring match (e.g. `"Media"` removes all keys containing `"Media"`).
|
|
1100
|
+
* - **RegExp**: tested against each key directly.
|
|
1101
|
+
*
|
|
1102
|
+
* @param pattern — A string (substring match) or RegExp.
|
|
1103
|
+
* @returns Number of entries removed.
|
|
1104
|
+
*/
|
|
1105
|
+
invalidate(pattern: string | RegExp): Promise<number>;
|
|
1106
|
+
}
|
|
1107
|
+
|
|
968
1108
|
/**
|
|
969
1109
|
* Lightweight AniList GraphQL client with built-in caching and rate limiting.
|
|
970
1110
|
*
|
|
@@ -1167,142 +1307,6 @@ declare class AniListError extends Error {
|
|
|
1167
1307
|
constructor(message: string, status: number, errors?: unknown[]);
|
|
1168
1308
|
}
|
|
1169
1309
|
|
|
1170
|
-
/** Cache performance statistics. */
|
|
1171
|
-
interface CacheStats {
|
|
1172
|
-
/** Total cache hits. */
|
|
1173
|
-
hits: number;
|
|
1174
|
-
/** Total cache misses. */
|
|
1175
|
-
misses: number;
|
|
1176
|
-
/** Stale entries returned (only with stale-while-revalidate). */
|
|
1177
|
-
stales: number;
|
|
1178
|
-
/** Hit rate as a ratio 0–1 (NaN if no requests yet). */
|
|
1179
|
-
hitRate: number;
|
|
1180
|
-
}
|
|
1181
|
-
declare class MemoryCache implements CacheAdapter {
|
|
1182
|
-
private readonly ttl;
|
|
1183
|
-
private readonly maxSize;
|
|
1184
|
-
private readonly enabled;
|
|
1185
|
-
private readonly swrMs;
|
|
1186
|
-
private readonly store;
|
|
1187
|
-
private _hits;
|
|
1188
|
-
private _misses;
|
|
1189
|
-
private _stales;
|
|
1190
|
-
constructor(options?: CacheOptions);
|
|
1191
|
-
/** Build a deterministic cache key from a query + variables pair. */
|
|
1192
|
-
static key(query: string, variables: Record<string, unknown>): string;
|
|
1193
|
-
/**
|
|
1194
|
-
* Retrieve a cached value, or `undefined` if missing / expired.
|
|
1195
|
-
* With stale-while-revalidate enabled, returns stale data within the grace window
|
|
1196
|
-
* and flags it so the caller can refresh in the background.
|
|
1197
|
-
*/
|
|
1198
|
-
get<T>(key: string): T | undefined;
|
|
1199
|
-
/** Store a value in the cache. */
|
|
1200
|
-
set<T>(key: string, data: T): void;
|
|
1201
|
-
/** Remove a specific entry. */
|
|
1202
|
-
delete(key: string): boolean;
|
|
1203
|
-
/** Clear the entire cache and reset statistics. */
|
|
1204
|
-
clear(): void;
|
|
1205
|
-
/** Number of entries currently stored. */
|
|
1206
|
-
get size(): number | Promise<number>;
|
|
1207
|
-
/** Return all cache keys. */
|
|
1208
|
-
keys(): string[];
|
|
1209
|
-
/**
|
|
1210
|
-
* Get cache performance statistics.
|
|
1211
|
-
*
|
|
1212
|
-
* @example
|
|
1213
|
-
* ```ts
|
|
1214
|
-
* const cache = new MemoryCache();
|
|
1215
|
-
* // ... after some usage ...
|
|
1216
|
-
* console.log(cache.stats);
|
|
1217
|
-
* // { hits: 42, misses: 8, stales: 0, hitRate: 0.84 }
|
|
1218
|
-
* ```
|
|
1219
|
-
*/
|
|
1220
|
-
get stats(): CacheStats;
|
|
1221
|
-
/** Reset cache statistics without clearing stored data. */
|
|
1222
|
-
resetStats(): void;
|
|
1223
|
-
/**
|
|
1224
|
-
* Remove all entries whose key matches the given pattern.
|
|
1225
|
-
*
|
|
1226
|
-
* - **String**: treated as a substring match (e.g. `"Media"` removes all keys containing `"Media"`).
|
|
1227
|
-
* - **RegExp**: tested against each key directly.
|
|
1228
|
-
*
|
|
1229
|
-
* @param pattern — A string (substring match) or RegExp.
|
|
1230
|
-
* @returns Number of entries removed.
|
|
1231
|
-
*/
|
|
1232
|
-
invalidate(pattern: string | RegExp): number;
|
|
1233
|
-
}
|
|
1234
|
-
|
|
1235
|
-
/**
|
|
1236
|
-
* Minimal interface representing a Redis client.
|
|
1237
|
-
* Compatible with both `ioredis` and `redis` (node-redis v4+).
|
|
1238
|
-
*/
|
|
1239
|
-
interface RedisLikeClient {
|
|
1240
|
-
get(key: string): Promise<string | null>;
|
|
1241
|
-
set(key: string, value: string, ...args: unknown[]): Promise<unknown>;
|
|
1242
|
-
del(...keys: (string | string[])[]): Promise<number>;
|
|
1243
|
-
keys(pattern: string): Promise<string[]>;
|
|
1244
|
-
/** Optional SCAN-based iteration — used when available to avoid blocking the server. */
|
|
1245
|
-
scanIterator?(options: {
|
|
1246
|
-
MATCH: string;
|
|
1247
|
-
COUNT?: number;
|
|
1248
|
-
}): AsyncIterable<string>;
|
|
1249
|
-
}
|
|
1250
|
-
interface RedisCacheOptions {
|
|
1251
|
-
/** A Redis client instance (ioredis or node-redis). */
|
|
1252
|
-
client: RedisLikeClient;
|
|
1253
|
-
/** Key prefix to namespace ani-client entries (default: `"ani:"`) */
|
|
1254
|
-
prefix?: string;
|
|
1255
|
-
/** TTL in seconds (default: 86 400 = 24 h) */
|
|
1256
|
-
ttl?: number;
|
|
1257
|
-
}
|
|
1258
|
-
/**
|
|
1259
|
-
* Redis-backed cache adapter for AniListClient.
|
|
1260
|
-
*
|
|
1261
|
-
* @example
|
|
1262
|
-
* ```ts
|
|
1263
|
-
* import Redis from "ioredis";
|
|
1264
|
-
* import { AniListClient, RedisCache } from "ani-client";
|
|
1265
|
-
*
|
|
1266
|
-
* const redis = new Redis();
|
|
1267
|
-
* const client = new AniListClient({
|
|
1268
|
-
* cacheAdapter: new RedisCache({ client: redis }),
|
|
1269
|
-
* });
|
|
1270
|
-
* ```
|
|
1271
|
-
*/
|
|
1272
|
-
declare class RedisCache implements CacheAdapter {
|
|
1273
|
-
private readonly client;
|
|
1274
|
-
private readonly prefix;
|
|
1275
|
-
private readonly ttl;
|
|
1276
|
-
constructor(options: RedisCacheOptions);
|
|
1277
|
-
private prefixedKey;
|
|
1278
|
-
get<T>(key: string): Promise<T | undefined>;
|
|
1279
|
-
set<T>(key: string, data: T): Promise<void>;
|
|
1280
|
-
delete(key: string): Promise<boolean>;
|
|
1281
|
-
/**
|
|
1282
|
-
* Collect keys matching a pattern. Uses SCAN when available, falls back to KEYS.
|
|
1283
|
-
*
|
|
1284
|
-
* **Warning:** The `KEYS` fallback is O(N) and blocks the Redis server.
|
|
1285
|
-
* Provide a client with `scanIterator` support for production use.
|
|
1286
|
-
* @internal
|
|
1287
|
-
*/
|
|
1288
|
-
private collectKeys;
|
|
1289
|
-
clear(): Promise<void>;
|
|
1290
|
-
/**
|
|
1291
|
-
* Get the actual number of keys with this prefix in Redis.
|
|
1292
|
-
*/
|
|
1293
|
-
get size(): Promise<number>;
|
|
1294
|
-
/** @internal */
|
|
1295
|
-
private getSize;
|
|
1296
|
-
keys(): Promise<string[]>;
|
|
1297
|
-
/**
|
|
1298
|
-
* Remove all entries whose key matches the given glob pattern.
|
|
1299
|
-
*
|
|
1300
|
-
* @param pattern — A glob pattern (e.g. `"*Media*"`)
|
|
1301
|
-
* @returns Number of entries removed.
|
|
1302
|
-
*/
|
|
1303
|
-
invalidate(pattern: string | RegExp): Promise<number>;
|
|
1304
|
-
}
|
|
1305
|
-
|
|
1306
1310
|
/**
|
|
1307
1311
|
* Rate limiter with automatic retry for AniList API.
|
|
1308
1312
|
*
|