ani-client 1.5.1 → 1.6.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 +41 -3
- package/dist/index.d.mts +126 -5
- package/dist/index.d.ts +126 -5
- package/dist/index.js +276 -51
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +276 -51
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -5
package/README.md
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
# ani-client
|
|
1
|
+
# ani-client
|
|
2
2
|
|
|
3
|
+

|
|
3
4
|
[](https://github.com/gonzyui/ani-client/actions/workflows/ci.yml)
|
|
4
5
|
[](https://www.npmjs.com/package/ani-client)
|
|
5
6
|
[](LICENSE)
|
|
6
7
|
|
|
7
8
|
> A simple, typed client to fetch anime, manga, character, staff and user data from [AniList](https://anilist.co).
|
|
8
9
|
|
|
9
|
-
✨ **Showcase**: [Check here](https://
|
|
10
|
+
✨ **Showcase**: [Check here](https://ani-client.js.org/showcase) to see which projects use this package!
|
|
10
11
|
|
|
11
12
|
- **Zero dependencies** — uses the native `fetch` API
|
|
12
13
|
- **Universal** — Node.js ≥ 20, Bun, Deno and modern browsers
|
|
@@ -17,7 +18,7 @@
|
|
|
17
18
|
|
|
18
19
|
The full API reference, usage guide, and configuration examples are available on our official documentation website!
|
|
19
20
|
|
|
20
|
-
**[👉 View the full documentation here](https://
|
|
21
|
+
**[👉 View the full documentation here](https://ani-client.js.org)**
|
|
21
22
|
|
|
22
23
|
## Install
|
|
23
24
|
|
|
@@ -55,6 +56,43 @@ const results = await client.searchMedia({
|
|
|
55
56
|
console.log(results.results.map((m) => m.title.english));
|
|
56
57
|
```
|
|
57
58
|
|
|
59
|
+
### Fetch user favorites
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
const favs = await client.getUserFavorites("AniList");
|
|
63
|
+
|
|
64
|
+
favs.anime.forEach((a) => console.log(a.title.romaji));
|
|
65
|
+
favs.characters.forEach((c) => console.log(c.name.full));
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Monitor rate limits
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
const client = new AniListClient({
|
|
72
|
+
rateLimit: {
|
|
73
|
+
retryStrategy: (attempt) => (attempt + 1) * 1000, // linear backoff
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
await client.getMedia(1);
|
|
78
|
+
|
|
79
|
+
const info = client.rateLimitInfo;
|
|
80
|
+
console.log(`${info?.remaining}/${info?.limit} requests remaining`);
|
|
81
|
+
|
|
82
|
+
const meta = client.lastRequestMeta;
|
|
83
|
+
console.log(`${meta?.durationMs}ms, cache: ${meta?.fromCache}`);
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Cancel requests
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
const controller = new AbortController();
|
|
90
|
+
const client = new AniListClient({ signal: controller.signal });
|
|
91
|
+
|
|
92
|
+
setTimeout(() => controller.abort(), 5_000);
|
|
93
|
+
await client.getMedia(1); // aborted after 5s
|
|
94
|
+
```
|
|
95
|
+
|
|
58
96
|
## Contributing
|
|
59
97
|
|
|
60
98
|
See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup, coding standards, and how to submit changes.
|
package/dist/index.d.mts
CHANGED
|
@@ -67,6 +67,16 @@ interface RateLimitOptions {
|
|
|
67
67
|
timeoutMs?: number;
|
|
68
68
|
/** Retry on network errors like ECONNRESET / ETIMEDOUT (default: true) */
|
|
69
69
|
retryOnNetworkError?: boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Custom retry delay strategy. Receives the attempt number (0-based) and the base delay,
|
|
72
|
+
* and should return the delay in ms before retrying.
|
|
73
|
+
* When omitted, the default exponential backoff with jitter is used.
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* // Linear backoff: 1s, 2s, 3s, ...
|
|
77
|
+
* retryStrategy: (attempt) => (attempt + 1) * 1000
|
|
78
|
+
*/
|
|
79
|
+
retryStrategy?: (attempt: number, baseDelayMs: number) => number;
|
|
70
80
|
}
|
|
71
81
|
/** Event hooks for logging, debugging, and monitoring. */
|
|
72
82
|
interface AniListHooks {
|
|
@@ -79,7 +89,27 @@ interface AniListHooks {
|
|
|
79
89
|
/** Called when a request is retried (429 or network error). */
|
|
80
90
|
onRetry?: (attempt: number, reason: string, delayMs: number) => void;
|
|
81
91
|
/** Called when a request completes. */
|
|
82
|
-
onResponse?: (query: string, durationMs: number, fromCache: boolean) => void;
|
|
92
|
+
onResponse?: (query: string, durationMs: number, fromCache: boolean, rateLimitInfo?: RateLimitInfo) => void;
|
|
93
|
+
/** Called when a request fails with an error. */
|
|
94
|
+
onError?: (error: Error, query: string, variables: Record<string, unknown>) => void;
|
|
95
|
+
}
|
|
96
|
+
/** Rate limit information parsed from AniList API response headers. */
|
|
97
|
+
interface RateLimitInfo {
|
|
98
|
+
/** Maximum number of requests allowed per window. */
|
|
99
|
+
limit: number;
|
|
100
|
+
/** Remaining requests in the current window. */
|
|
101
|
+
remaining: number;
|
|
102
|
+
/** UNIX timestamp (seconds) when the rate limit window resets. */
|
|
103
|
+
reset: number;
|
|
104
|
+
}
|
|
105
|
+
/** Metadata about the last request, useful for debugging and monitoring. */
|
|
106
|
+
interface ResponseMeta {
|
|
107
|
+
/** Duration of the request in milliseconds. */
|
|
108
|
+
durationMs: number;
|
|
109
|
+
/** Whether the response was served from cache. */
|
|
110
|
+
fromCache: boolean;
|
|
111
|
+
/** Rate limit information from the API response headers (not present for cached responses). */
|
|
112
|
+
rateLimitInfo?: RateLimitInfo;
|
|
83
113
|
}
|
|
84
114
|
interface AniListClientOptions {
|
|
85
115
|
/** Optional AniList OAuth token for authenticated requests */
|
|
@@ -94,6 +124,8 @@ interface AniListClientOptions {
|
|
|
94
124
|
rateLimit?: RateLimitOptions;
|
|
95
125
|
/** Event hooks for logging, debugging, and monitoring */
|
|
96
126
|
hooks?: AniListHooks;
|
|
127
|
+
/** Optional AbortSignal to cancel all requests made by this client */
|
|
128
|
+
signal?: AbortSignal;
|
|
97
129
|
}
|
|
98
130
|
|
|
99
131
|
declare enum StaffSort {
|
|
@@ -409,6 +441,58 @@ interface SearchUserOptions {
|
|
|
409
441
|
page?: number;
|
|
410
442
|
perPage?: number;
|
|
411
443
|
}
|
|
444
|
+
interface FavoriteMediaNode {
|
|
445
|
+
id: number;
|
|
446
|
+
title: {
|
|
447
|
+
romaji: string | null;
|
|
448
|
+
english: string | null;
|
|
449
|
+
native: string | null;
|
|
450
|
+
userPreferred: string | null;
|
|
451
|
+
};
|
|
452
|
+
coverImage: {
|
|
453
|
+
large: string | null;
|
|
454
|
+
medium: string | null;
|
|
455
|
+
};
|
|
456
|
+
type: string | null;
|
|
457
|
+
format: string | null;
|
|
458
|
+
siteUrl: string | null;
|
|
459
|
+
}
|
|
460
|
+
interface FavoriteCharacterNode {
|
|
461
|
+
id: number;
|
|
462
|
+
name: {
|
|
463
|
+
full: string | null;
|
|
464
|
+
native: string | null;
|
|
465
|
+
};
|
|
466
|
+
image: {
|
|
467
|
+
large: string | null;
|
|
468
|
+
medium: string | null;
|
|
469
|
+
};
|
|
470
|
+
siteUrl: string | null;
|
|
471
|
+
}
|
|
472
|
+
interface FavoriteStaffNode {
|
|
473
|
+
id: number;
|
|
474
|
+
name: {
|
|
475
|
+
full: string | null;
|
|
476
|
+
native: string | null;
|
|
477
|
+
};
|
|
478
|
+
image: {
|
|
479
|
+
large: string | null;
|
|
480
|
+
medium: string | null;
|
|
481
|
+
};
|
|
482
|
+
siteUrl: string | null;
|
|
483
|
+
}
|
|
484
|
+
interface FavoriteStudioNode {
|
|
485
|
+
id: number;
|
|
486
|
+
name: string;
|
|
487
|
+
siteUrl: string | null;
|
|
488
|
+
}
|
|
489
|
+
interface UserFavorites {
|
|
490
|
+
anime: FavoriteMediaNode[];
|
|
491
|
+
manga: FavoriteMediaNode[];
|
|
492
|
+
characters: FavoriteCharacterNode[];
|
|
493
|
+
staff: FavoriteStaffNode[];
|
|
494
|
+
studios: FavoriteStudioNode[];
|
|
495
|
+
}
|
|
412
496
|
|
|
413
497
|
declare enum MediaType {
|
|
414
498
|
ANIME = "ANIME",
|
|
@@ -877,8 +961,21 @@ declare class AniListClient {
|
|
|
877
961
|
private readonly cacheAdapter;
|
|
878
962
|
private readonly rateLimiter;
|
|
879
963
|
private readonly hooks;
|
|
964
|
+
private readonly signal?;
|
|
880
965
|
private readonly inFlight;
|
|
966
|
+
private _rateLimitInfo?;
|
|
967
|
+
private _lastRequestMeta?;
|
|
881
968
|
constructor(options?: AniListClientOptions);
|
|
969
|
+
/**
|
|
970
|
+
* The current rate limit information from the last API response.
|
|
971
|
+
* Updated after every non-cached request.
|
|
972
|
+
*/
|
|
973
|
+
get rateLimitInfo(): RateLimitInfo | undefined;
|
|
974
|
+
/**
|
|
975
|
+
* Metadata about the last request (duration, cache status, rate limit info).
|
|
976
|
+
* Useful for debugging and monitoring.
|
|
977
|
+
*/
|
|
978
|
+
get lastRequestMeta(): ResponseMeta | undefined;
|
|
882
979
|
/** @internal */
|
|
883
980
|
request<T>(query: string, variables?: Record<string, unknown>): Promise<T>;
|
|
884
981
|
/** @internal */
|
|
@@ -937,6 +1034,19 @@ declare class AniListClient {
|
|
|
937
1034
|
searchUsers(options?: SearchUserOptions): Promise<PagedResult<User>>;
|
|
938
1035
|
/** Get a user's anime or manga list. */
|
|
939
1036
|
getUserMediaList(options: GetUserMediaListOptions): Promise<PagedResult<MediaListEntry>>;
|
|
1037
|
+
/**
|
|
1038
|
+
* Fetch a user's favorite anime, manga, characters, staff, and studios.
|
|
1039
|
+
*
|
|
1040
|
+
* @param idOrName - AniList user ID (number) or username (string)
|
|
1041
|
+
* @returns The user's favorites grouped by category
|
|
1042
|
+
*
|
|
1043
|
+
* @example
|
|
1044
|
+
* ```typescript
|
|
1045
|
+
* const favs = await client.getUserFavorites("AniList");
|
|
1046
|
+
* favs.anime.forEach(a => console.log(a.title.romaji));
|
|
1047
|
+
* ```
|
|
1048
|
+
*/
|
|
1049
|
+
getUserFavorites(idOrName: number | string): Promise<UserFavorites>;
|
|
940
1050
|
/** Fetch a studio by its AniList ID. */
|
|
941
1051
|
getStudio(id: number): Promise<Studio>;
|
|
942
1052
|
/** Search for studios by name. */
|
|
@@ -969,7 +1079,7 @@ declare class AniListClient {
|
|
|
969
1079
|
/** Clear the entire response cache. */
|
|
970
1080
|
clearCache(): Promise<void>;
|
|
971
1081
|
/** Number of entries currently in the cache. */
|
|
972
|
-
|
|
1082
|
+
cacheSize(): Promise<number>;
|
|
973
1083
|
/** Remove cache entries whose key matches the given pattern. */
|
|
974
1084
|
invalidateCache(pattern: string | RegExp): Promise<number>;
|
|
975
1085
|
/** Clean up resources held by the client. */
|
|
@@ -1106,10 +1216,13 @@ declare class RateLimiter {
|
|
|
1106
1216
|
private readonly enabled;
|
|
1107
1217
|
private readonly timeoutMs;
|
|
1108
1218
|
private readonly retryOnNetworkError;
|
|
1219
|
+
private readonly retryStrategy?;
|
|
1109
1220
|
/** @internal — sliding window: circular buffer of timestamps */
|
|
1110
1221
|
private readonly timestamps;
|
|
1111
1222
|
private head;
|
|
1112
1223
|
private count;
|
|
1224
|
+
/** @internal — active sleep timers for cleanup */
|
|
1225
|
+
private readonly activeTimers;
|
|
1113
1226
|
constructor(options?: RateLimitOptions);
|
|
1114
1227
|
/**
|
|
1115
1228
|
* Wait until it's safe to make a request (respects rate limit window).
|
|
@@ -1123,20 +1236,28 @@ declare class RateLimiter {
|
|
|
1123
1236
|
onRetry?: (attempt: number, reason: string, delayMs: number) => void;
|
|
1124
1237
|
onRateLimit?: (retryAfterMs: number) => void;
|
|
1125
1238
|
}): Promise<Response>;
|
|
1126
|
-
/** @internal — Exponential backoff with jitter, capped at 30s */
|
|
1239
|
+
/** @internal — Exponential backoff with jitter, capped at 30s (or custom strategy) */
|
|
1127
1240
|
private exponentialDelay;
|
|
1128
1241
|
/** @internal */
|
|
1129
1242
|
private fetchWithTimeout;
|
|
1130
1243
|
private sleep;
|
|
1244
|
+
/** Cancel all pending sleep timers and reset internal state. */
|
|
1245
|
+
dispose(): void;
|
|
1131
1246
|
}
|
|
1132
1247
|
|
|
1133
1248
|
/**
|
|
1134
1249
|
* Parses AniList specific markdown into standard HTML.
|
|
1135
|
-
* Includes formatting for spoilers, images, videos (youtube/webm),
|
|
1250
|
+
* Includes formatting for spoilers, images, videos (youtube/webm), headings,
|
|
1251
|
+
* lists, code blocks, and standard markdown elements.
|
|
1252
|
+
*
|
|
1253
|
+
* @security This function escapes HTML entities to prevent XSS attacks.
|
|
1254
|
+
* However, the output is still raw HTML — consumers should always use a
|
|
1255
|
+
* Content Security Policy and consider additional sanitization when rendering
|
|
1256
|
+
* user-generated content in a browser.
|
|
1136
1257
|
*
|
|
1137
1258
|
* @param text The AniList markdown text to parse
|
|
1138
1259
|
* @returns The parsed HTML string
|
|
1139
1260
|
*/
|
|
1140
1261
|
declare function parseAniListMarkdown(text: string): string;
|
|
1141
1262
|
|
|
1142
|
-
export { type AiringSchedule, AiringSort, AniListClient, type AniListClientOptions, AniListError, type AniListHooks, type CacheAdapter, type CacheOptions, type Character, type CharacterImage, type CharacterIncludeOptions, type CharacterMediaEdge, type CharacterName, CharacterRole, CharacterSort, type DayOfWeek, type ExternalLink, type FuzzyDate, type GetAiringOptions, type GetPlanningOptions, type GetRecentChaptersOptions, type GetRecommendationsOptions, type GetSeasonOptions, type GetUserMediaListOptions, 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 RateLimitOptions, RateLimiter, type Recommendation, RecommendationSort, RedisCache, type RedisCacheOptions, type RedisLikeClient, 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 Thread, type ThreadCategory, type ThreadMediaCategory, ThreadSort, type User, type UserAvatar, UserSort, type UserStatistics, type VoiceActor, type WeeklySchedule, parseAniListMarkdown };
|
|
1263
|
+
export { type AiringSchedule, AiringSort, AniListClient, type AniListClientOptions, AniListError, type AniListHooks, type CacheAdapter, type CacheOptions, 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 GetPlanningOptions, type GetRecentChaptersOptions, type GetRecommendationsOptions, type GetSeasonOptions, type GetUserMediaListOptions, 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 Thread, type ThreadCategory, type ThreadMediaCategory, ThreadSort, type User, type UserAvatar, type UserFavorites, UserSort, type UserStatistics, type VoiceActor, type WeeklySchedule, parseAniListMarkdown };
|
package/dist/index.d.ts
CHANGED
|
@@ -67,6 +67,16 @@ interface RateLimitOptions {
|
|
|
67
67
|
timeoutMs?: number;
|
|
68
68
|
/** Retry on network errors like ECONNRESET / ETIMEDOUT (default: true) */
|
|
69
69
|
retryOnNetworkError?: boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Custom retry delay strategy. Receives the attempt number (0-based) and the base delay,
|
|
72
|
+
* and should return the delay in ms before retrying.
|
|
73
|
+
* When omitted, the default exponential backoff with jitter is used.
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* // Linear backoff: 1s, 2s, 3s, ...
|
|
77
|
+
* retryStrategy: (attempt) => (attempt + 1) * 1000
|
|
78
|
+
*/
|
|
79
|
+
retryStrategy?: (attempt: number, baseDelayMs: number) => number;
|
|
70
80
|
}
|
|
71
81
|
/** Event hooks for logging, debugging, and monitoring. */
|
|
72
82
|
interface AniListHooks {
|
|
@@ -79,7 +89,27 @@ interface AniListHooks {
|
|
|
79
89
|
/** Called when a request is retried (429 or network error). */
|
|
80
90
|
onRetry?: (attempt: number, reason: string, delayMs: number) => void;
|
|
81
91
|
/** Called when a request completes. */
|
|
82
|
-
onResponse?: (query: string, durationMs: number, fromCache: boolean) => void;
|
|
92
|
+
onResponse?: (query: string, durationMs: number, fromCache: boolean, rateLimitInfo?: RateLimitInfo) => void;
|
|
93
|
+
/** Called when a request fails with an error. */
|
|
94
|
+
onError?: (error: Error, query: string, variables: Record<string, unknown>) => void;
|
|
95
|
+
}
|
|
96
|
+
/** Rate limit information parsed from AniList API response headers. */
|
|
97
|
+
interface RateLimitInfo {
|
|
98
|
+
/** Maximum number of requests allowed per window. */
|
|
99
|
+
limit: number;
|
|
100
|
+
/** Remaining requests in the current window. */
|
|
101
|
+
remaining: number;
|
|
102
|
+
/** UNIX timestamp (seconds) when the rate limit window resets. */
|
|
103
|
+
reset: number;
|
|
104
|
+
}
|
|
105
|
+
/** Metadata about the last request, useful for debugging and monitoring. */
|
|
106
|
+
interface ResponseMeta {
|
|
107
|
+
/** Duration of the request in milliseconds. */
|
|
108
|
+
durationMs: number;
|
|
109
|
+
/** Whether the response was served from cache. */
|
|
110
|
+
fromCache: boolean;
|
|
111
|
+
/** Rate limit information from the API response headers (not present for cached responses). */
|
|
112
|
+
rateLimitInfo?: RateLimitInfo;
|
|
83
113
|
}
|
|
84
114
|
interface AniListClientOptions {
|
|
85
115
|
/** Optional AniList OAuth token for authenticated requests */
|
|
@@ -94,6 +124,8 @@ interface AniListClientOptions {
|
|
|
94
124
|
rateLimit?: RateLimitOptions;
|
|
95
125
|
/** Event hooks for logging, debugging, and monitoring */
|
|
96
126
|
hooks?: AniListHooks;
|
|
127
|
+
/** Optional AbortSignal to cancel all requests made by this client */
|
|
128
|
+
signal?: AbortSignal;
|
|
97
129
|
}
|
|
98
130
|
|
|
99
131
|
declare enum StaffSort {
|
|
@@ -409,6 +441,58 @@ interface SearchUserOptions {
|
|
|
409
441
|
page?: number;
|
|
410
442
|
perPage?: number;
|
|
411
443
|
}
|
|
444
|
+
interface FavoriteMediaNode {
|
|
445
|
+
id: number;
|
|
446
|
+
title: {
|
|
447
|
+
romaji: string | null;
|
|
448
|
+
english: string | null;
|
|
449
|
+
native: string | null;
|
|
450
|
+
userPreferred: string | null;
|
|
451
|
+
};
|
|
452
|
+
coverImage: {
|
|
453
|
+
large: string | null;
|
|
454
|
+
medium: string | null;
|
|
455
|
+
};
|
|
456
|
+
type: string | null;
|
|
457
|
+
format: string | null;
|
|
458
|
+
siteUrl: string | null;
|
|
459
|
+
}
|
|
460
|
+
interface FavoriteCharacterNode {
|
|
461
|
+
id: number;
|
|
462
|
+
name: {
|
|
463
|
+
full: string | null;
|
|
464
|
+
native: string | null;
|
|
465
|
+
};
|
|
466
|
+
image: {
|
|
467
|
+
large: string | null;
|
|
468
|
+
medium: string | null;
|
|
469
|
+
};
|
|
470
|
+
siteUrl: string | null;
|
|
471
|
+
}
|
|
472
|
+
interface FavoriteStaffNode {
|
|
473
|
+
id: number;
|
|
474
|
+
name: {
|
|
475
|
+
full: string | null;
|
|
476
|
+
native: string | null;
|
|
477
|
+
};
|
|
478
|
+
image: {
|
|
479
|
+
large: string | null;
|
|
480
|
+
medium: string | null;
|
|
481
|
+
};
|
|
482
|
+
siteUrl: string | null;
|
|
483
|
+
}
|
|
484
|
+
interface FavoriteStudioNode {
|
|
485
|
+
id: number;
|
|
486
|
+
name: string;
|
|
487
|
+
siteUrl: string | null;
|
|
488
|
+
}
|
|
489
|
+
interface UserFavorites {
|
|
490
|
+
anime: FavoriteMediaNode[];
|
|
491
|
+
manga: FavoriteMediaNode[];
|
|
492
|
+
characters: FavoriteCharacterNode[];
|
|
493
|
+
staff: FavoriteStaffNode[];
|
|
494
|
+
studios: FavoriteStudioNode[];
|
|
495
|
+
}
|
|
412
496
|
|
|
413
497
|
declare enum MediaType {
|
|
414
498
|
ANIME = "ANIME",
|
|
@@ -877,8 +961,21 @@ declare class AniListClient {
|
|
|
877
961
|
private readonly cacheAdapter;
|
|
878
962
|
private readonly rateLimiter;
|
|
879
963
|
private readonly hooks;
|
|
964
|
+
private readonly signal?;
|
|
880
965
|
private readonly inFlight;
|
|
966
|
+
private _rateLimitInfo?;
|
|
967
|
+
private _lastRequestMeta?;
|
|
881
968
|
constructor(options?: AniListClientOptions);
|
|
969
|
+
/**
|
|
970
|
+
* The current rate limit information from the last API response.
|
|
971
|
+
* Updated after every non-cached request.
|
|
972
|
+
*/
|
|
973
|
+
get rateLimitInfo(): RateLimitInfo | undefined;
|
|
974
|
+
/**
|
|
975
|
+
* Metadata about the last request (duration, cache status, rate limit info).
|
|
976
|
+
* Useful for debugging and monitoring.
|
|
977
|
+
*/
|
|
978
|
+
get lastRequestMeta(): ResponseMeta | undefined;
|
|
882
979
|
/** @internal */
|
|
883
980
|
request<T>(query: string, variables?: Record<string, unknown>): Promise<T>;
|
|
884
981
|
/** @internal */
|
|
@@ -937,6 +1034,19 @@ declare class AniListClient {
|
|
|
937
1034
|
searchUsers(options?: SearchUserOptions): Promise<PagedResult<User>>;
|
|
938
1035
|
/** Get a user's anime or manga list. */
|
|
939
1036
|
getUserMediaList(options: GetUserMediaListOptions): Promise<PagedResult<MediaListEntry>>;
|
|
1037
|
+
/**
|
|
1038
|
+
* Fetch a user's favorite anime, manga, characters, staff, and studios.
|
|
1039
|
+
*
|
|
1040
|
+
* @param idOrName - AniList user ID (number) or username (string)
|
|
1041
|
+
* @returns The user's favorites grouped by category
|
|
1042
|
+
*
|
|
1043
|
+
* @example
|
|
1044
|
+
* ```typescript
|
|
1045
|
+
* const favs = await client.getUserFavorites("AniList");
|
|
1046
|
+
* favs.anime.forEach(a => console.log(a.title.romaji));
|
|
1047
|
+
* ```
|
|
1048
|
+
*/
|
|
1049
|
+
getUserFavorites(idOrName: number | string): Promise<UserFavorites>;
|
|
940
1050
|
/** Fetch a studio by its AniList ID. */
|
|
941
1051
|
getStudio(id: number): Promise<Studio>;
|
|
942
1052
|
/** Search for studios by name. */
|
|
@@ -969,7 +1079,7 @@ declare class AniListClient {
|
|
|
969
1079
|
/** Clear the entire response cache. */
|
|
970
1080
|
clearCache(): Promise<void>;
|
|
971
1081
|
/** Number of entries currently in the cache. */
|
|
972
|
-
|
|
1082
|
+
cacheSize(): Promise<number>;
|
|
973
1083
|
/** Remove cache entries whose key matches the given pattern. */
|
|
974
1084
|
invalidateCache(pattern: string | RegExp): Promise<number>;
|
|
975
1085
|
/** Clean up resources held by the client. */
|
|
@@ -1106,10 +1216,13 @@ declare class RateLimiter {
|
|
|
1106
1216
|
private readonly enabled;
|
|
1107
1217
|
private readonly timeoutMs;
|
|
1108
1218
|
private readonly retryOnNetworkError;
|
|
1219
|
+
private readonly retryStrategy?;
|
|
1109
1220
|
/** @internal — sliding window: circular buffer of timestamps */
|
|
1110
1221
|
private readonly timestamps;
|
|
1111
1222
|
private head;
|
|
1112
1223
|
private count;
|
|
1224
|
+
/** @internal — active sleep timers for cleanup */
|
|
1225
|
+
private readonly activeTimers;
|
|
1113
1226
|
constructor(options?: RateLimitOptions);
|
|
1114
1227
|
/**
|
|
1115
1228
|
* Wait until it's safe to make a request (respects rate limit window).
|
|
@@ -1123,20 +1236,28 @@ declare class RateLimiter {
|
|
|
1123
1236
|
onRetry?: (attempt: number, reason: string, delayMs: number) => void;
|
|
1124
1237
|
onRateLimit?: (retryAfterMs: number) => void;
|
|
1125
1238
|
}): Promise<Response>;
|
|
1126
|
-
/** @internal — Exponential backoff with jitter, capped at 30s */
|
|
1239
|
+
/** @internal — Exponential backoff with jitter, capped at 30s (or custom strategy) */
|
|
1127
1240
|
private exponentialDelay;
|
|
1128
1241
|
/** @internal */
|
|
1129
1242
|
private fetchWithTimeout;
|
|
1130
1243
|
private sleep;
|
|
1244
|
+
/** Cancel all pending sleep timers and reset internal state. */
|
|
1245
|
+
dispose(): void;
|
|
1131
1246
|
}
|
|
1132
1247
|
|
|
1133
1248
|
/**
|
|
1134
1249
|
* Parses AniList specific markdown into standard HTML.
|
|
1135
|
-
* Includes formatting for spoilers, images, videos (youtube/webm),
|
|
1250
|
+
* Includes formatting for spoilers, images, videos (youtube/webm), headings,
|
|
1251
|
+
* lists, code blocks, and standard markdown elements.
|
|
1252
|
+
*
|
|
1253
|
+
* @security This function escapes HTML entities to prevent XSS attacks.
|
|
1254
|
+
* However, the output is still raw HTML — consumers should always use a
|
|
1255
|
+
* Content Security Policy and consider additional sanitization when rendering
|
|
1256
|
+
* user-generated content in a browser.
|
|
1136
1257
|
*
|
|
1137
1258
|
* @param text The AniList markdown text to parse
|
|
1138
1259
|
* @returns The parsed HTML string
|
|
1139
1260
|
*/
|
|
1140
1261
|
declare function parseAniListMarkdown(text: string): string;
|
|
1141
1262
|
|
|
1142
|
-
export { type AiringSchedule, AiringSort, AniListClient, type AniListClientOptions, AniListError, type AniListHooks, type CacheAdapter, type CacheOptions, type Character, type CharacterImage, type CharacterIncludeOptions, type CharacterMediaEdge, type CharacterName, CharacterRole, CharacterSort, type DayOfWeek, type ExternalLink, type FuzzyDate, type GetAiringOptions, type GetPlanningOptions, type GetRecentChaptersOptions, type GetRecommendationsOptions, type GetSeasonOptions, type GetUserMediaListOptions, 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 RateLimitOptions, RateLimiter, type Recommendation, RecommendationSort, RedisCache, type RedisCacheOptions, type RedisLikeClient, 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 Thread, type ThreadCategory, type ThreadMediaCategory, ThreadSort, type User, type UserAvatar, UserSort, type UserStatistics, type VoiceActor, type WeeklySchedule, parseAniListMarkdown };
|
|
1263
|
+
export { type AiringSchedule, AiringSort, AniListClient, type AniListClientOptions, AniListError, type AniListHooks, type CacheAdapter, type CacheOptions, 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 GetPlanningOptions, type GetRecentChaptersOptions, type GetRecommendationsOptions, type GetSeasonOptions, type GetUserMediaListOptions, 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 Thread, type ThreadCategory, type ThreadMediaCategory, ThreadSort, type User, type UserAvatar, type UserFavorites, UserSort, type UserStatistics, type VoiceActor, type WeeklySchedule, parseAniListMarkdown };
|