ani-client 2.1.2 → 2.1.4
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 +10 -2
- package/dist/cache/redis.d.mts +1 -0
- package/dist/cache/redis.d.ts +1 -0
- package/dist/cache/redis.js +94 -0
- package/dist/cache/redis.js.map +1 -0
- package/dist/cache/redis.mjs +92 -0
- package/dist/cache/redis.mjs.map +1 -0
- package/dist/index.d.mts +20 -245
- package/dist/index.d.ts +20 -245
- package/dist/index.js +50 -8
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +50 -8
- package/dist/index.mjs.map +1 -1
- package/dist/redis-AFbnh0Xa.d.mts +243 -0
- package/dist/redis-AFbnh0Xa.d.ts +243 -0
- package/package.json +6 -1
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
interface PageInfo {
|
|
2
|
+
total: number | null;
|
|
3
|
+
perPage: number;
|
|
4
|
+
currentPage: number;
|
|
5
|
+
lastPage: number;
|
|
6
|
+
hasNextPage: boolean;
|
|
7
|
+
}
|
|
8
|
+
interface PagedResult<T> {
|
|
9
|
+
pageInfo: PageInfo;
|
|
10
|
+
results: T[];
|
|
11
|
+
}
|
|
12
|
+
interface FuzzyDate {
|
|
13
|
+
year: number | null;
|
|
14
|
+
month: number | null;
|
|
15
|
+
day: number | null;
|
|
16
|
+
}
|
|
17
|
+
interface ExternalLink {
|
|
18
|
+
id: number;
|
|
19
|
+
url: string | null;
|
|
20
|
+
site: string;
|
|
21
|
+
type: string | null;
|
|
22
|
+
icon: string | null;
|
|
23
|
+
color: string | null;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Interface that all cache adapters must implement.
|
|
27
|
+
* Methods may return sync values or Promises — the client awaits all calls.
|
|
28
|
+
*/
|
|
29
|
+
interface CacheAdapter {
|
|
30
|
+
/** Retrieve a cached value, or `undefined` if missing / expired. */
|
|
31
|
+
get<T>(key: string): T | undefined | Promise<T | undefined>;
|
|
32
|
+
/**
|
|
33
|
+
* Retrieve a cached value along with its stale status (for stale-while-revalidate).
|
|
34
|
+
* If implemented, the client will use this to trigger background revalidation.
|
|
35
|
+
*/
|
|
36
|
+
getWithMeta?<T>(key: string): {
|
|
37
|
+
data: T;
|
|
38
|
+
stale: boolean;
|
|
39
|
+
} | undefined | Promise<{
|
|
40
|
+
data: T;
|
|
41
|
+
stale: boolean;
|
|
42
|
+
} | undefined>;
|
|
43
|
+
/** Store a value in the cache. */
|
|
44
|
+
set<T>(key: string, data: T): void | Promise<void>;
|
|
45
|
+
/** Remove a specific entry. Returns `true` if the key existed. */
|
|
46
|
+
delete(key: string): boolean | Promise<boolean>;
|
|
47
|
+
/** Clear the entire cache. */
|
|
48
|
+
clear(): void | Promise<void>;
|
|
49
|
+
/** Number of entries currently stored. */
|
|
50
|
+
readonly size: number | Promise<number>;
|
|
51
|
+
/** Return all cache keys. */
|
|
52
|
+
keys(): string[] | Promise<string[]>;
|
|
53
|
+
/** Bulk-remove entries matching a pattern. Optional — the client provides a fallback. */
|
|
54
|
+
invalidate?(pattern: string | RegExp): number | Promise<number>;
|
|
55
|
+
}
|
|
56
|
+
/** Cache configuration options. */
|
|
57
|
+
interface CacheOptions {
|
|
58
|
+
/** Time-to-live in milliseconds (default: 86 400 000 = 24h) */
|
|
59
|
+
ttl?: number;
|
|
60
|
+
/** Maximum number of cached entries (default: 500, 0 = unlimited) */
|
|
61
|
+
maxSize?: number;
|
|
62
|
+
/** Set to false to disable caching entirely */
|
|
63
|
+
enabled?: boolean;
|
|
64
|
+
/**
|
|
65
|
+
* Stale-while-revalidate grace period in milliseconds (default: 0 = disabled).
|
|
66
|
+
* When set, expired entries are still returned within the grace window,
|
|
67
|
+
* allowing the caller to refresh in the background.
|
|
68
|
+
*/
|
|
69
|
+
staleWhileRevalidateMs?: number;
|
|
70
|
+
}
|
|
71
|
+
/** Rate limiter configuration options. */
|
|
72
|
+
interface RateLimitOptions {
|
|
73
|
+
/** Max requests per window (default: 25) */
|
|
74
|
+
maxRequests?: number;
|
|
75
|
+
/** Window size in ms (default: 60 000) */
|
|
76
|
+
windowMs?: number;
|
|
77
|
+
/** Max retries on 429 (default: 3) */
|
|
78
|
+
maxRetries?: number;
|
|
79
|
+
/** Retry delay in ms when Retry-After header is absent (default: 2000) */
|
|
80
|
+
retryDelayMs?: number;
|
|
81
|
+
/** Set to false to disable rate limiting entirely */
|
|
82
|
+
enabled?: boolean;
|
|
83
|
+
/** Timeout per request in ms (default: 30 000). 0 = no timeout. */
|
|
84
|
+
timeoutMs?: number;
|
|
85
|
+
/** Retry on network errors like ECONNRESET / ETIMEDOUT (default: true) */
|
|
86
|
+
retryOnNetworkError?: boolean;
|
|
87
|
+
/**
|
|
88
|
+
* Custom retry delay strategy. Receives the attempt number (0-based) and the base delay,
|
|
89
|
+
* and should return the delay in ms before retrying.
|
|
90
|
+
* When omitted, the default exponential backoff with jitter is used.
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* // Linear backoff: 1s, 2s, 3s, ...
|
|
94
|
+
* retryStrategy: (attempt) => (attempt + 1) * 1000
|
|
95
|
+
*/
|
|
96
|
+
retryStrategy?: (attempt: number, baseDelayMs: number) => number;
|
|
97
|
+
}
|
|
98
|
+
/** Event hooks for logging, debugging, and monitoring. */
|
|
99
|
+
interface AniListHooks {
|
|
100
|
+
/** Called before every API request. */
|
|
101
|
+
onRequest?: (query: string, variables: Record<string, unknown>) => void;
|
|
102
|
+
/** Called when a response is served from cache. */
|
|
103
|
+
onCacheHit?: (key: string) => void;
|
|
104
|
+
/** Called when the rate limiter enforces a wait (429 received). */
|
|
105
|
+
onRateLimit?: (retryAfterMs: number) => void;
|
|
106
|
+
/** Called when a request is retried (429 or network error). */
|
|
107
|
+
onRetry?: (attempt: number, reason: string, delayMs: number) => void;
|
|
108
|
+
/** Called when a request completes. */
|
|
109
|
+
onResponse?: (query: string, durationMs: number, fromCache: boolean, rateLimitInfo?: RateLimitInfo) => void;
|
|
110
|
+
/** Called when a request fails with an error. */
|
|
111
|
+
onError?: (error: Error, query: string, variables: Record<string, unknown>) => void;
|
|
112
|
+
}
|
|
113
|
+
/** Rate limit information parsed from AniList API response headers. */
|
|
114
|
+
interface RateLimitInfo {
|
|
115
|
+
/** Maximum number of requests allowed per window. */
|
|
116
|
+
limit: number;
|
|
117
|
+
/** Remaining requests in the current window. */
|
|
118
|
+
remaining: number;
|
|
119
|
+
/** UNIX timestamp (seconds) when the rate limit window resets. */
|
|
120
|
+
reset: number;
|
|
121
|
+
}
|
|
122
|
+
/** Metadata about the last request, useful for debugging and monitoring. */
|
|
123
|
+
interface ResponseMeta {
|
|
124
|
+
/** Duration of the request in milliseconds. */
|
|
125
|
+
durationMs: number;
|
|
126
|
+
/** Whether the response was served from cache. */
|
|
127
|
+
fromCache: boolean;
|
|
128
|
+
/** Rate limit information from the API response headers (not present for cached responses). */
|
|
129
|
+
rateLimitInfo?: RateLimitInfo;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Minimal logger interface for structured log output.
|
|
133
|
+
* Compatible with `console`, `pino`, `winston`, etc.
|
|
134
|
+
*/
|
|
135
|
+
interface Logger {
|
|
136
|
+
debug(message: string, ...args: unknown[]): void;
|
|
137
|
+
info(message: string, ...args: unknown[]): void;
|
|
138
|
+
warn(message: string, ...args: unknown[]): void;
|
|
139
|
+
error(message: string, ...args: unknown[]): void;
|
|
140
|
+
}
|
|
141
|
+
interface AniListClientOptions {
|
|
142
|
+
/** Optional AniList OAuth token for authenticated requests */
|
|
143
|
+
token?: string;
|
|
144
|
+
/** Custom API endpoint (defaults to https://graphql.anilist.co) */
|
|
145
|
+
apiUrl?: string;
|
|
146
|
+
/** Cache configuration (enabled by default, 24h TTL) */
|
|
147
|
+
cache?: CacheOptions;
|
|
148
|
+
/** Custom cache adapter (e.g. RedisCache). Takes precedence over `cache`. */
|
|
149
|
+
cacheAdapter?: CacheAdapter;
|
|
150
|
+
/** Rate limiter configuration (enabled by default, 25 req/min) */
|
|
151
|
+
rateLimit?: RateLimitOptions;
|
|
152
|
+
/** Event hooks for logging, debugging, and monitoring */
|
|
153
|
+
hooks?: AniListHooks;
|
|
154
|
+
/** Optional AbortSignal to cancel all requests made by this client */
|
|
155
|
+
signal?: AbortSignal;
|
|
156
|
+
/**
|
|
157
|
+
* Optional logger for structured log output.
|
|
158
|
+
* Accepts any object with `debug`, `info`, `warn`, `error` methods.
|
|
159
|
+
* Compatible with `console`, `pino`, `winston`, etc.
|
|
160
|
+
*
|
|
161
|
+
* @example
|
|
162
|
+
* ```ts
|
|
163
|
+
* const client = new AniListClient({ logger: console });
|
|
164
|
+
* ```
|
|
165
|
+
*/
|
|
166
|
+
logger?: Logger;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Minimal interface representing a Redis client.
|
|
171
|
+
* Compatible with both `ioredis` and `redis` (node-redis v4+).
|
|
172
|
+
*/
|
|
173
|
+
interface RedisLikeClient {
|
|
174
|
+
get(key: string): Promise<string | null>;
|
|
175
|
+
set(key: string, value: string, ...args: unknown[]): Promise<unknown>;
|
|
176
|
+
del(...keys: (string | string[])[]): Promise<number>;
|
|
177
|
+
keys(pattern: string): Promise<string[]>;
|
|
178
|
+
/** Optional SCAN-based iteration — used when available to avoid blocking the server. */
|
|
179
|
+
scanIterator?(options: {
|
|
180
|
+
MATCH: string;
|
|
181
|
+
COUNT?: number;
|
|
182
|
+
}): AsyncIterable<string>;
|
|
183
|
+
}
|
|
184
|
+
interface RedisCacheOptions {
|
|
185
|
+
/** A Redis client instance (ioredis or node-redis). */
|
|
186
|
+
client: RedisLikeClient;
|
|
187
|
+
/** Key prefix to namespace ani-client entries (default: `"ani:"`) */
|
|
188
|
+
prefix?: string;
|
|
189
|
+
/** TTL in seconds (default: 86 400 = 24 h) */
|
|
190
|
+
ttl?: number;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Redis-backed cache adapter for AniListClient.
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* ```ts
|
|
197
|
+
* import Redis from "ioredis";
|
|
198
|
+
* import { AniListClient, RedisCache } from "ani-client";
|
|
199
|
+
*
|
|
200
|
+
* const redis = new Redis();
|
|
201
|
+
* const client = new AniListClient({
|
|
202
|
+
* cacheAdapter: new RedisCache({ client: redis }),
|
|
203
|
+
* });
|
|
204
|
+
* ```
|
|
205
|
+
*/
|
|
206
|
+
declare class RedisCache implements CacheAdapter {
|
|
207
|
+
private readonly client;
|
|
208
|
+
private readonly prefix;
|
|
209
|
+
private readonly ttl;
|
|
210
|
+
constructor(options: RedisCacheOptions);
|
|
211
|
+
private prefixedKey;
|
|
212
|
+
get<T>(key: string): Promise<T | undefined>;
|
|
213
|
+
set<T>(key: string, data: T): Promise<void>;
|
|
214
|
+
delete(key: string): Promise<boolean>;
|
|
215
|
+
/**
|
|
216
|
+
* Collect keys matching a pattern. Uses SCAN when available, falls back to KEYS.
|
|
217
|
+
*
|
|
218
|
+
* **Warning:** The `KEYS` fallback is O(N) and blocks the Redis server.
|
|
219
|
+
* Provide a client with `scanIterator` support for production use.
|
|
220
|
+
* @internal
|
|
221
|
+
*/
|
|
222
|
+
private collectKeys;
|
|
223
|
+
clear(): Promise<void>;
|
|
224
|
+
/**
|
|
225
|
+
* Get the actual number of keys with this prefix in Redis.
|
|
226
|
+
*/
|
|
227
|
+
get size(): Promise<number>;
|
|
228
|
+
/** @internal */
|
|
229
|
+
private getSize;
|
|
230
|
+
keys(): Promise<string[]>;
|
|
231
|
+
/**
|
|
232
|
+
* Remove all entries whose key matches the given pattern.
|
|
233
|
+
*
|
|
234
|
+
* - **String**: treated as a substring match (e.g. `"Media"` removes all keys containing `"Media"`).
|
|
235
|
+
* - **RegExp**: tested against each key directly.
|
|
236
|
+
*
|
|
237
|
+
* @param pattern — A string (substring match) or RegExp.
|
|
238
|
+
* @returns Number of entries removed.
|
|
239
|
+
*/
|
|
240
|
+
invalidate(pattern: string | RegExp): Promise<number>;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
export { type AniListClientOptions as A, type CacheAdapter as C, type ExternalLink as E, type FuzzyDate as F, type Logger as L, type PageInfo as P, type RateLimitInfo as R, type CacheOptions as a, type PagedResult as b, type ResponseMeta as c, type RateLimitOptions as d, type AniListHooks as e, RedisCache as f, type RedisCacheOptions as g, type RedisLikeClient as h };
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
interface PageInfo {
|
|
2
|
+
total: number | null;
|
|
3
|
+
perPage: number;
|
|
4
|
+
currentPage: number;
|
|
5
|
+
lastPage: number;
|
|
6
|
+
hasNextPage: boolean;
|
|
7
|
+
}
|
|
8
|
+
interface PagedResult<T> {
|
|
9
|
+
pageInfo: PageInfo;
|
|
10
|
+
results: T[];
|
|
11
|
+
}
|
|
12
|
+
interface FuzzyDate {
|
|
13
|
+
year: number | null;
|
|
14
|
+
month: number | null;
|
|
15
|
+
day: number | null;
|
|
16
|
+
}
|
|
17
|
+
interface ExternalLink {
|
|
18
|
+
id: number;
|
|
19
|
+
url: string | null;
|
|
20
|
+
site: string;
|
|
21
|
+
type: string | null;
|
|
22
|
+
icon: string | null;
|
|
23
|
+
color: string | null;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Interface that all cache adapters must implement.
|
|
27
|
+
* Methods may return sync values or Promises — the client awaits all calls.
|
|
28
|
+
*/
|
|
29
|
+
interface CacheAdapter {
|
|
30
|
+
/** Retrieve a cached value, or `undefined` if missing / expired. */
|
|
31
|
+
get<T>(key: string): T | undefined | Promise<T | undefined>;
|
|
32
|
+
/**
|
|
33
|
+
* Retrieve a cached value along with its stale status (for stale-while-revalidate).
|
|
34
|
+
* If implemented, the client will use this to trigger background revalidation.
|
|
35
|
+
*/
|
|
36
|
+
getWithMeta?<T>(key: string): {
|
|
37
|
+
data: T;
|
|
38
|
+
stale: boolean;
|
|
39
|
+
} | undefined | Promise<{
|
|
40
|
+
data: T;
|
|
41
|
+
stale: boolean;
|
|
42
|
+
} | undefined>;
|
|
43
|
+
/** Store a value in the cache. */
|
|
44
|
+
set<T>(key: string, data: T): void | Promise<void>;
|
|
45
|
+
/** Remove a specific entry. Returns `true` if the key existed. */
|
|
46
|
+
delete(key: string): boolean | Promise<boolean>;
|
|
47
|
+
/** Clear the entire cache. */
|
|
48
|
+
clear(): void | Promise<void>;
|
|
49
|
+
/** Number of entries currently stored. */
|
|
50
|
+
readonly size: number | Promise<number>;
|
|
51
|
+
/** Return all cache keys. */
|
|
52
|
+
keys(): string[] | Promise<string[]>;
|
|
53
|
+
/** Bulk-remove entries matching a pattern. Optional — the client provides a fallback. */
|
|
54
|
+
invalidate?(pattern: string | RegExp): number | Promise<number>;
|
|
55
|
+
}
|
|
56
|
+
/** Cache configuration options. */
|
|
57
|
+
interface CacheOptions {
|
|
58
|
+
/** Time-to-live in milliseconds (default: 86 400 000 = 24h) */
|
|
59
|
+
ttl?: number;
|
|
60
|
+
/** Maximum number of cached entries (default: 500, 0 = unlimited) */
|
|
61
|
+
maxSize?: number;
|
|
62
|
+
/** Set to false to disable caching entirely */
|
|
63
|
+
enabled?: boolean;
|
|
64
|
+
/**
|
|
65
|
+
* Stale-while-revalidate grace period in milliseconds (default: 0 = disabled).
|
|
66
|
+
* When set, expired entries are still returned within the grace window,
|
|
67
|
+
* allowing the caller to refresh in the background.
|
|
68
|
+
*/
|
|
69
|
+
staleWhileRevalidateMs?: number;
|
|
70
|
+
}
|
|
71
|
+
/** Rate limiter configuration options. */
|
|
72
|
+
interface RateLimitOptions {
|
|
73
|
+
/** Max requests per window (default: 25) */
|
|
74
|
+
maxRequests?: number;
|
|
75
|
+
/** Window size in ms (default: 60 000) */
|
|
76
|
+
windowMs?: number;
|
|
77
|
+
/** Max retries on 429 (default: 3) */
|
|
78
|
+
maxRetries?: number;
|
|
79
|
+
/** Retry delay in ms when Retry-After header is absent (default: 2000) */
|
|
80
|
+
retryDelayMs?: number;
|
|
81
|
+
/** Set to false to disable rate limiting entirely */
|
|
82
|
+
enabled?: boolean;
|
|
83
|
+
/** Timeout per request in ms (default: 30 000). 0 = no timeout. */
|
|
84
|
+
timeoutMs?: number;
|
|
85
|
+
/** Retry on network errors like ECONNRESET / ETIMEDOUT (default: true) */
|
|
86
|
+
retryOnNetworkError?: boolean;
|
|
87
|
+
/**
|
|
88
|
+
* Custom retry delay strategy. Receives the attempt number (0-based) and the base delay,
|
|
89
|
+
* and should return the delay in ms before retrying.
|
|
90
|
+
* When omitted, the default exponential backoff with jitter is used.
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* // Linear backoff: 1s, 2s, 3s, ...
|
|
94
|
+
* retryStrategy: (attempt) => (attempt + 1) * 1000
|
|
95
|
+
*/
|
|
96
|
+
retryStrategy?: (attempt: number, baseDelayMs: number) => number;
|
|
97
|
+
}
|
|
98
|
+
/** Event hooks for logging, debugging, and monitoring. */
|
|
99
|
+
interface AniListHooks {
|
|
100
|
+
/** Called before every API request. */
|
|
101
|
+
onRequest?: (query: string, variables: Record<string, unknown>) => void;
|
|
102
|
+
/** Called when a response is served from cache. */
|
|
103
|
+
onCacheHit?: (key: string) => void;
|
|
104
|
+
/** Called when the rate limiter enforces a wait (429 received). */
|
|
105
|
+
onRateLimit?: (retryAfterMs: number) => void;
|
|
106
|
+
/** Called when a request is retried (429 or network error). */
|
|
107
|
+
onRetry?: (attempt: number, reason: string, delayMs: number) => void;
|
|
108
|
+
/** Called when a request completes. */
|
|
109
|
+
onResponse?: (query: string, durationMs: number, fromCache: boolean, rateLimitInfo?: RateLimitInfo) => void;
|
|
110
|
+
/** Called when a request fails with an error. */
|
|
111
|
+
onError?: (error: Error, query: string, variables: Record<string, unknown>) => void;
|
|
112
|
+
}
|
|
113
|
+
/** Rate limit information parsed from AniList API response headers. */
|
|
114
|
+
interface RateLimitInfo {
|
|
115
|
+
/** Maximum number of requests allowed per window. */
|
|
116
|
+
limit: number;
|
|
117
|
+
/** Remaining requests in the current window. */
|
|
118
|
+
remaining: number;
|
|
119
|
+
/** UNIX timestamp (seconds) when the rate limit window resets. */
|
|
120
|
+
reset: number;
|
|
121
|
+
}
|
|
122
|
+
/** Metadata about the last request, useful for debugging and monitoring. */
|
|
123
|
+
interface ResponseMeta {
|
|
124
|
+
/** Duration of the request in milliseconds. */
|
|
125
|
+
durationMs: number;
|
|
126
|
+
/** Whether the response was served from cache. */
|
|
127
|
+
fromCache: boolean;
|
|
128
|
+
/** Rate limit information from the API response headers (not present for cached responses). */
|
|
129
|
+
rateLimitInfo?: RateLimitInfo;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Minimal logger interface for structured log output.
|
|
133
|
+
* Compatible with `console`, `pino`, `winston`, etc.
|
|
134
|
+
*/
|
|
135
|
+
interface Logger {
|
|
136
|
+
debug(message: string, ...args: unknown[]): void;
|
|
137
|
+
info(message: string, ...args: unknown[]): void;
|
|
138
|
+
warn(message: string, ...args: unknown[]): void;
|
|
139
|
+
error(message: string, ...args: unknown[]): void;
|
|
140
|
+
}
|
|
141
|
+
interface AniListClientOptions {
|
|
142
|
+
/** Optional AniList OAuth token for authenticated requests */
|
|
143
|
+
token?: string;
|
|
144
|
+
/** Custom API endpoint (defaults to https://graphql.anilist.co) */
|
|
145
|
+
apiUrl?: string;
|
|
146
|
+
/** Cache configuration (enabled by default, 24h TTL) */
|
|
147
|
+
cache?: CacheOptions;
|
|
148
|
+
/** Custom cache adapter (e.g. RedisCache). Takes precedence over `cache`. */
|
|
149
|
+
cacheAdapter?: CacheAdapter;
|
|
150
|
+
/** Rate limiter configuration (enabled by default, 25 req/min) */
|
|
151
|
+
rateLimit?: RateLimitOptions;
|
|
152
|
+
/** Event hooks for logging, debugging, and monitoring */
|
|
153
|
+
hooks?: AniListHooks;
|
|
154
|
+
/** Optional AbortSignal to cancel all requests made by this client */
|
|
155
|
+
signal?: AbortSignal;
|
|
156
|
+
/**
|
|
157
|
+
* Optional logger for structured log output.
|
|
158
|
+
* Accepts any object with `debug`, `info`, `warn`, `error` methods.
|
|
159
|
+
* Compatible with `console`, `pino`, `winston`, etc.
|
|
160
|
+
*
|
|
161
|
+
* @example
|
|
162
|
+
* ```ts
|
|
163
|
+
* const client = new AniListClient({ logger: console });
|
|
164
|
+
* ```
|
|
165
|
+
*/
|
|
166
|
+
logger?: Logger;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Minimal interface representing a Redis client.
|
|
171
|
+
* Compatible with both `ioredis` and `redis` (node-redis v4+).
|
|
172
|
+
*/
|
|
173
|
+
interface RedisLikeClient {
|
|
174
|
+
get(key: string): Promise<string | null>;
|
|
175
|
+
set(key: string, value: string, ...args: unknown[]): Promise<unknown>;
|
|
176
|
+
del(...keys: (string | string[])[]): Promise<number>;
|
|
177
|
+
keys(pattern: string): Promise<string[]>;
|
|
178
|
+
/** Optional SCAN-based iteration — used when available to avoid blocking the server. */
|
|
179
|
+
scanIterator?(options: {
|
|
180
|
+
MATCH: string;
|
|
181
|
+
COUNT?: number;
|
|
182
|
+
}): AsyncIterable<string>;
|
|
183
|
+
}
|
|
184
|
+
interface RedisCacheOptions {
|
|
185
|
+
/** A Redis client instance (ioredis or node-redis). */
|
|
186
|
+
client: RedisLikeClient;
|
|
187
|
+
/** Key prefix to namespace ani-client entries (default: `"ani:"`) */
|
|
188
|
+
prefix?: string;
|
|
189
|
+
/** TTL in seconds (default: 86 400 = 24 h) */
|
|
190
|
+
ttl?: number;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Redis-backed cache adapter for AniListClient.
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* ```ts
|
|
197
|
+
* import Redis from "ioredis";
|
|
198
|
+
* import { AniListClient, RedisCache } from "ani-client";
|
|
199
|
+
*
|
|
200
|
+
* const redis = new Redis();
|
|
201
|
+
* const client = new AniListClient({
|
|
202
|
+
* cacheAdapter: new RedisCache({ client: redis }),
|
|
203
|
+
* });
|
|
204
|
+
* ```
|
|
205
|
+
*/
|
|
206
|
+
declare class RedisCache implements CacheAdapter {
|
|
207
|
+
private readonly client;
|
|
208
|
+
private readonly prefix;
|
|
209
|
+
private readonly ttl;
|
|
210
|
+
constructor(options: RedisCacheOptions);
|
|
211
|
+
private prefixedKey;
|
|
212
|
+
get<T>(key: string): Promise<T | undefined>;
|
|
213
|
+
set<T>(key: string, data: T): Promise<void>;
|
|
214
|
+
delete(key: string): Promise<boolean>;
|
|
215
|
+
/**
|
|
216
|
+
* Collect keys matching a pattern. Uses SCAN when available, falls back to KEYS.
|
|
217
|
+
*
|
|
218
|
+
* **Warning:** The `KEYS` fallback is O(N) and blocks the Redis server.
|
|
219
|
+
* Provide a client with `scanIterator` support for production use.
|
|
220
|
+
* @internal
|
|
221
|
+
*/
|
|
222
|
+
private collectKeys;
|
|
223
|
+
clear(): Promise<void>;
|
|
224
|
+
/**
|
|
225
|
+
* Get the actual number of keys with this prefix in Redis.
|
|
226
|
+
*/
|
|
227
|
+
get size(): Promise<number>;
|
|
228
|
+
/** @internal */
|
|
229
|
+
private getSize;
|
|
230
|
+
keys(): Promise<string[]>;
|
|
231
|
+
/**
|
|
232
|
+
* Remove all entries whose key matches the given pattern.
|
|
233
|
+
*
|
|
234
|
+
* - **String**: treated as a substring match (e.g. `"Media"` removes all keys containing `"Media"`).
|
|
235
|
+
* - **RegExp**: tested against each key directly.
|
|
236
|
+
*
|
|
237
|
+
* @param pattern — A string (substring match) or RegExp.
|
|
238
|
+
* @returns Number of entries removed.
|
|
239
|
+
*/
|
|
240
|
+
invalidate(pattern: string | RegExp): Promise<number>;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
export { type AniListClientOptions as A, type CacheAdapter as C, type ExternalLink as E, type FuzzyDate as F, type Logger as L, type PageInfo as P, type RateLimitInfo as R, type CacheOptions as a, type PagedResult as b, type ResponseMeta as c, type RateLimitOptions as d, type AniListHooks as e, RedisCache as f, type RedisCacheOptions as g, type RedisLikeClient as h };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ani-client",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.4",
|
|
4
4
|
"description": "A simple and typed client to fetch anime, manga, characters and user data from AniList",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -10,6 +10,11 @@
|
|
|
10
10
|
"types": "./dist/index.d.ts",
|
|
11
11
|
"import": "./dist/index.mjs",
|
|
12
12
|
"require": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./redis": {
|
|
15
|
+
"types": "./dist/redis.d.ts",
|
|
16
|
+
"import": "./dist/redis.mjs",
|
|
17
|
+
"require": "./dist/redis.js"
|
|
13
18
|
}
|
|
14
19
|
},
|
|
15
20
|
"files": [
|