ani-client 2.1.2 → 2.1.3
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 +7 -1
- 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 +18 -243
- package/dist/index.d.ts +18 -243
- package/dist/index.js +47 -8
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +47 -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
package/README.md
CHANGED
|
@@ -236,7 +236,13 @@ Full API reference, configuration options, and guides (caching, pagination, hook
|
|
|
236
236
|
|
|
237
237
|
## Contributing
|
|
238
238
|
|
|
239
|
-
|
|
239
|
+
Contributions are welcome.
|
|
240
|
+
|
|
241
|
+
Before opening an issue or a pull request, please read:
|
|
242
|
+
- [CONTRIBUTING.md](CONTRIBUTING.md)
|
|
243
|
+
- [SECURITY.md](SECURITY.md)
|
|
244
|
+
|
|
245
|
+
This repository also includes GitHub issue templates and a pull request template to help keep reports and contributions consistent.
|
|
240
246
|
|
|
241
247
|
## License
|
|
242
248
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { f as RedisCache, g as RedisCacheOptions, h as RedisLikeClient } from '../redis-AFbnh0Xa.mjs';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { f as RedisCache, g as RedisCacheOptions, h as RedisLikeClient } from '../redis-AFbnh0Xa.js';
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/cache/redis.ts
|
|
4
|
+
var RedisCache = class {
|
|
5
|
+
client;
|
|
6
|
+
prefix;
|
|
7
|
+
ttl;
|
|
8
|
+
constructor(options) {
|
|
9
|
+
this.client = options.client;
|
|
10
|
+
this.prefix = options.prefix ?? "ani:";
|
|
11
|
+
this.ttl = options.ttl ?? 86400;
|
|
12
|
+
}
|
|
13
|
+
prefixedKey(key) {
|
|
14
|
+
return `${this.prefix}${key}`;
|
|
15
|
+
}
|
|
16
|
+
async get(key) {
|
|
17
|
+
const raw = await this.client.get(this.prefixedKey(key));
|
|
18
|
+
if (raw === null) return void 0;
|
|
19
|
+
try {
|
|
20
|
+
return JSON.parse(raw);
|
|
21
|
+
} catch {
|
|
22
|
+
return void 0;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
async set(key, data) {
|
|
26
|
+
await this.client.set(this.prefixedKey(key), JSON.stringify(data), "EX", this.ttl);
|
|
27
|
+
}
|
|
28
|
+
async delete(key) {
|
|
29
|
+
const count = await this.client.del(this.prefixedKey(key));
|
|
30
|
+
return count > 0;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Collect keys matching a pattern. Uses SCAN when available, falls back to KEYS.
|
|
34
|
+
*
|
|
35
|
+
* **Warning:** The `KEYS` fallback is O(N) and blocks the Redis server.
|
|
36
|
+
* Provide a client with `scanIterator` support for production use.
|
|
37
|
+
* @internal
|
|
38
|
+
*/
|
|
39
|
+
async collectKeys(pattern) {
|
|
40
|
+
if (this.client.scanIterator) {
|
|
41
|
+
const keys = [];
|
|
42
|
+
for await (const key of this.client.scanIterator({ MATCH: pattern, COUNT: 100 })) {
|
|
43
|
+
keys.push(key);
|
|
44
|
+
}
|
|
45
|
+
return keys;
|
|
46
|
+
}
|
|
47
|
+
return this.client.keys(pattern);
|
|
48
|
+
}
|
|
49
|
+
async clear() {
|
|
50
|
+
const keys = await this.collectKeys(`${this.prefix}*`);
|
|
51
|
+
if (keys.length > 0) {
|
|
52
|
+
await this.client.del(...keys);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Get the actual number of keys with this prefix in Redis.
|
|
57
|
+
*/
|
|
58
|
+
get size() {
|
|
59
|
+
return this.getSize();
|
|
60
|
+
}
|
|
61
|
+
/** @internal */
|
|
62
|
+
async getSize() {
|
|
63
|
+
const keys = await this.collectKeys(`${this.prefix}*`);
|
|
64
|
+
return keys.length;
|
|
65
|
+
}
|
|
66
|
+
async keys() {
|
|
67
|
+
const raw = await this.collectKeys(`${this.prefix}*`);
|
|
68
|
+
return raw.map((k) => k.slice(this.prefix.length));
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Remove all entries whose key matches the given pattern.
|
|
72
|
+
*
|
|
73
|
+
* - **String**: treated as a substring match (e.g. `"Media"` removes all keys containing `"Media"`).
|
|
74
|
+
* - **RegExp**: tested against each key directly.
|
|
75
|
+
*
|
|
76
|
+
* @param pattern — A string (substring match) or RegExp.
|
|
77
|
+
* @returns Number of entries removed.
|
|
78
|
+
*/
|
|
79
|
+
async invalidate(pattern) {
|
|
80
|
+
if (typeof pattern === "string") {
|
|
81
|
+
const keys = await this.collectKeys(`${this.prefix}*${pattern}*`);
|
|
82
|
+
if (keys.length === 0) return 0;
|
|
83
|
+
return this.client.del(...keys);
|
|
84
|
+
}
|
|
85
|
+
const allKeys = await this.collectKeys(`${this.prefix}*`);
|
|
86
|
+
const matching = allKeys.filter((k) => pattern.test(k.slice(this.prefix.length)));
|
|
87
|
+
if (matching.length === 0) return 0;
|
|
88
|
+
return this.client.del(...matching);
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
exports.RedisCache = RedisCache;
|
|
93
|
+
//# sourceMappingURL=redis.js.map
|
|
94
|
+
//# sourceMappingURL=redis.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/cache/redis.ts"],"names":[],"mappings":"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","file":"redis.js","sourcesContent":["import type { CacheAdapter } from \"../types\";\n\n/**\n * Minimal interface representing a Redis client.\n * Compatible with both `ioredis` and `redis` (node-redis v4+).\n */\nexport interface RedisLikeClient {\n get(key: string): Promise<string | null>;\n set(key: string, value: string, ...args: unknown[]): Promise<unknown>;\n del(...keys: (string | string[])[]): Promise<number>;\n keys(pattern: string): Promise<string[]>;\n /** Optional SCAN-based iteration — used when available to avoid blocking the server. */\n scanIterator?(options: { MATCH: string; COUNT?: number }): AsyncIterable<string>;\n}\n\nexport interface RedisCacheOptions {\n /** A Redis client instance (ioredis or node-redis). */\n client: RedisLikeClient;\n /** Key prefix to namespace ani-client entries (default: `\"ani:\"`) */\n prefix?: string;\n /** TTL in seconds (default: 86 400 = 24 h) */\n ttl?: number;\n}\n\n/**\n * Redis-backed cache adapter for AniListClient.\n *\n * @example\n * ```ts\n * import Redis from \"ioredis\";\n * import { AniListClient, RedisCache } from \"ani-client\";\n *\n * const redis = new Redis();\n * const client = new AniListClient({\n * cacheAdapter: new RedisCache({ client: redis }),\n * });\n * ```\n */\nexport class RedisCache implements CacheAdapter {\n private readonly client: RedisLikeClient;\n private readonly prefix: string;\n private readonly ttl: number;\n\n constructor(options: RedisCacheOptions) {\n this.client = options.client;\n this.prefix = options.prefix ?? \"ani:\";\n this.ttl = options.ttl ?? 86_400;\n }\n\n private prefixedKey(key: string): string {\n return `${this.prefix}${key}`;\n }\n\n async get<T>(key: string): Promise<T | undefined> {\n const raw = await this.client.get(this.prefixedKey(key));\n if (raw === null) return undefined;\n try {\n return JSON.parse(raw) as T;\n } catch {\n return undefined;\n }\n }\n\n async set<T>(key: string, data: T): Promise<void> {\n await this.client.set(this.prefixedKey(key), JSON.stringify(data), \"EX\", this.ttl);\n }\n\n async delete(key: string): Promise<boolean> {\n const count = await this.client.del(this.prefixedKey(key));\n return count > 0;\n }\n\n /**\n * Collect keys matching a pattern. Uses SCAN when available, falls back to KEYS.\n *\n * **Warning:** The `KEYS` fallback is O(N) and blocks the Redis server.\n * Provide a client with `scanIterator` support for production use.\n * @internal\n */\n private async collectKeys(pattern: string): Promise<string[]> {\n if (this.client.scanIterator) {\n const keys: string[] = [];\n for await (const key of this.client.scanIterator({ MATCH: pattern, COUNT: 100 })) {\n keys.push(key);\n }\n return keys;\n }\n return this.client.keys(pattern);\n }\n\n async clear(): Promise<void> {\n const keys = await this.collectKeys(`${this.prefix}*`);\n if (keys.length > 0) {\n await this.client.del(...keys);\n }\n }\n\n /**\n * Get the actual number of keys with this prefix in Redis.\n */\n get size(): Promise<number> {\n return this.getSize();\n }\n\n /** @internal */\n private async getSize(): Promise<number> {\n const keys = await this.collectKeys(`${this.prefix}*`);\n return keys.length;\n }\n\n async keys(): Promise<string[]> {\n const raw = await this.collectKeys(`${this.prefix}*`);\n return raw.map((k) => k.slice(this.prefix.length));\n }\n\n /**\n * Remove all entries whose key matches the given pattern.\n *\n * - **String**: treated as a substring match (e.g. `\"Media\"` removes all keys containing `\"Media\"`).\n * - **RegExp**: tested against each key directly.\n *\n * @param pattern — A string (substring match) or RegExp.\n * @returns Number of entries removed.\n */\n async invalidate(pattern: string | RegExp): Promise<number> {\n if (typeof pattern === \"string\") {\n const keys = await this.collectKeys(`${this.prefix}*${pattern}*`);\n if (keys.length === 0) return 0;\n return this.client.del(...keys);\n }\n\n const allKeys = await this.collectKeys(`${this.prefix}*`);\n const matching = allKeys.filter((k) => pattern.test(k.slice(this.prefix.length)));\n if (matching.length === 0) return 0;\n return this.client.del(...matching);\n }\n}\n"]}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// src/cache/redis.ts
|
|
2
|
+
var RedisCache = class {
|
|
3
|
+
client;
|
|
4
|
+
prefix;
|
|
5
|
+
ttl;
|
|
6
|
+
constructor(options) {
|
|
7
|
+
this.client = options.client;
|
|
8
|
+
this.prefix = options.prefix ?? "ani:";
|
|
9
|
+
this.ttl = options.ttl ?? 86400;
|
|
10
|
+
}
|
|
11
|
+
prefixedKey(key) {
|
|
12
|
+
return `${this.prefix}${key}`;
|
|
13
|
+
}
|
|
14
|
+
async get(key) {
|
|
15
|
+
const raw = await this.client.get(this.prefixedKey(key));
|
|
16
|
+
if (raw === null) return void 0;
|
|
17
|
+
try {
|
|
18
|
+
return JSON.parse(raw);
|
|
19
|
+
} catch {
|
|
20
|
+
return void 0;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
async set(key, data) {
|
|
24
|
+
await this.client.set(this.prefixedKey(key), JSON.stringify(data), "EX", this.ttl);
|
|
25
|
+
}
|
|
26
|
+
async delete(key) {
|
|
27
|
+
const count = await this.client.del(this.prefixedKey(key));
|
|
28
|
+
return count > 0;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Collect keys matching a pattern. Uses SCAN when available, falls back to KEYS.
|
|
32
|
+
*
|
|
33
|
+
* **Warning:** The `KEYS` fallback is O(N) and blocks the Redis server.
|
|
34
|
+
* Provide a client with `scanIterator` support for production use.
|
|
35
|
+
* @internal
|
|
36
|
+
*/
|
|
37
|
+
async collectKeys(pattern) {
|
|
38
|
+
if (this.client.scanIterator) {
|
|
39
|
+
const keys = [];
|
|
40
|
+
for await (const key of this.client.scanIterator({ MATCH: pattern, COUNT: 100 })) {
|
|
41
|
+
keys.push(key);
|
|
42
|
+
}
|
|
43
|
+
return keys;
|
|
44
|
+
}
|
|
45
|
+
return this.client.keys(pattern);
|
|
46
|
+
}
|
|
47
|
+
async clear() {
|
|
48
|
+
const keys = await this.collectKeys(`${this.prefix}*`);
|
|
49
|
+
if (keys.length > 0) {
|
|
50
|
+
await this.client.del(...keys);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Get the actual number of keys with this prefix in Redis.
|
|
55
|
+
*/
|
|
56
|
+
get size() {
|
|
57
|
+
return this.getSize();
|
|
58
|
+
}
|
|
59
|
+
/** @internal */
|
|
60
|
+
async getSize() {
|
|
61
|
+
const keys = await this.collectKeys(`${this.prefix}*`);
|
|
62
|
+
return keys.length;
|
|
63
|
+
}
|
|
64
|
+
async keys() {
|
|
65
|
+
const raw = await this.collectKeys(`${this.prefix}*`);
|
|
66
|
+
return raw.map((k) => k.slice(this.prefix.length));
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Remove all entries whose key matches the given pattern.
|
|
70
|
+
*
|
|
71
|
+
* - **String**: treated as a substring match (e.g. `"Media"` removes all keys containing `"Media"`).
|
|
72
|
+
* - **RegExp**: tested against each key directly.
|
|
73
|
+
*
|
|
74
|
+
* @param pattern — A string (substring match) or RegExp.
|
|
75
|
+
* @returns Number of entries removed.
|
|
76
|
+
*/
|
|
77
|
+
async invalidate(pattern) {
|
|
78
|
+
if (typeof pattern === "string") {
|
|
79
|
+
const keys = await this.collectKeys(`${this.prefix}*${pattern}*`);
|
|
80
|
+
if (keys.length === 0) return 0;
|
|
81
|
+
return this.client.del(...keys);
|
|
82
|
+
}
|
|
83
|
+
const allKeys = await this.collectKeys(`${this.prefix}*`);
|
|
84
|
+
const matching = allKeys.filter((k) => pattern.test(k.slice(this.prefix.length)));
|
|
85
|
+
if (matching.length === 0) return 0;
|
|
86
|
+
return this.client.del(...matching);
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export { RedisCache };
|
|
91
|
+
//# sourceMappingURL=redis.mjs.map
|
|
92
|
+
//# sourceMappingURL=redis.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/cache/redis.ts"],"names":[],"mappings":";AAsCO,IAAM,aAAN,MAAyC;AAAA,EAC7B,MAAA;AAAA,EACA,MAAA;AAAA,EACA,GAAA;AAAA,EAEjB,YAAY,OAAA,EAA4B;AACtC,IAAA,IAAA,CAAK,SAAS,OAAA,CAAQ,MAAA;AACtB,IAAA,IAAA,CAAK,MAAA,GAAS,QAAQ,MAAA,IAAU,MAAA;AAChC,IAAA,IAAA,CAAK,GAAA,GAAM,QAAQ,GAAA,IAAO,KAAA;AAAA,EAC5B;AAAA,EAEQ,YAAY,GAAA,EAAqB;AACvC,IAAA,OAAO,CAAA,EAAG,IAAA,CAAK,MAAM,CAAA,EAAG,GAAG,CAAA,CAAA;AAAA,EAC7B;AAAA,EAEA,MAAM,IAAO,GAAA,EAAqC;AAChD,IAAA,MAAM,GAAA,GAAM,MAAM,IAAA,CAAK,MAAA,CAAO,IAAI,IAAA,CAAK,WAAA,CAAY,GAAG,CAAC,CAAA;AACvD,IAAA,IAAI,GAAA,KAAQ,MAAM,OAAO,MAAA;AACzB,IAAA,IAAI;AACF,MAAA,OAAO,IAAA,CAAK,MAAM,GAAG,CAAA;AAAA,IACvB,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,MAAA;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAM,GAAA,CAAO,GAAA,EAAa,IAAA,EAAwB;AAChD,IAAA,MAAM,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,IAAA,CAAK,WAAA,CAAY,GAAG,CAAA,EAAG,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA,EAAG,IAAA,EAAM,KAAK,GAAG,CAAA;AAAA,EACnF;AAAA,EAEA,MAAM,OAAO,GAAA,EAA+B;AAC1C,IAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,MAAA,CAAO,IAAI,IAAA,CAAK,WAAA,CAAY,GAAG,CAAC,CAAA;AACzD,IAAA,OAAO,KAAA,GAAQ,CAAA;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAc,YAAY,OAAA,EAAoC;AAC5D,IAAA,IAAI,IAAA,CAAK,OAAO,YAAA,EAAc;AAC5B,MAAA,MAAM,OAAiB,EAAC;AACxB,MAAA,WAAA,MAAiB,GAAA,IAAO,IAAA,CAAK,MAAA,CAAO,YAAA,CAAa,EAAE,OAAO,OAAA,EAAS,KAAA,EAAO,GAAA,EAAK,CAAA,EAAG;AAChF,QAAA,IAAA,CAAK,KAAK,GAAG,CAAA;AAAA,MACf;AACA,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA;AAAA,EACjC;AAAA,EAEA,MAAM,KAAA,GAAuB;AAC3B,IAAA,MAAM,OAAO,MAAM,IAAA,CAAK,YAAY,CAAA,EAAG,IAAA,CAAK,MAAM,CAAA,CAAA,CAAG,CAAA;AACrD,IAAA,IAAI,IAAA,CAAK,SAAS,CAAA,EAAG;AACnB,MAAA,MAAM,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,GAAG,IAAI,CAAA;AAAA,IAC/B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,IAAA,GAAwB;AAC1B,IAAA,OAAO,KAAK,OAAA,EAAQ;AAAA,EACtB;AAAA;AAAA,EAGA,MAAc,OAAA,GAA2B;AACvC,IAAA,MAAM,OAAO,MAAM,IAAA,CAAK,YAAY,CAAA,EAAG,IAAA,CAAK,MAAM,CAAA,CAAA,CAAG,CAAA;AACrD,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,EACd;AAAA,EAEA,MAAM,IAAA,GAA0B;AAC9B,IAAA,MAAM,MAAM,MAAM,IAAA,CAAK,YAAY,CAAA,EAAG,IAAA,CAAK,MAAM,CAAA,CAAA,CAAG,CAAA;AACpD,IAAA,OAAO,GAAA,CAAI,IAAI,CAAC,CAAA,KAAM,EAAE,KAAA,CAAM,IAAA,CAAK,MAAA,CAAO,MAAM,CAAC,CAAA;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,WAAW,OAAA,EAA2C;AAC1D,IAAA,IAAI,OAAO,YAAY,QAAA,EAAU;AAC/B,MAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,WAAA,CAAY,GAAG,IAAA,CAAK,MAAM,CAAA,CAAA,EAAI,OAAO,CAAA,CAAA,CAAG,CAAA;AAChE,MAAA,IAAI,IAAA,CAAK,MAAA,KAAW,CAAA,EAAG,OAAO,CAAA;AAC9B,MAAA,OAAO,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,GAAG,IAAI,CAAA;AAAA,IAChC;AAEA,IAAA,MAAM,UAAU,MAAM,IAAA,CAAK,YAAY,CAAA,EAAG,IAAA,CAAK,MAAM,CAAA,CAAA,CAAG,CAAA;AACxD,IAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,MAAA,CAAO,CAAC,CAAA,KAAM,OAAA,CAAQ,IAAA,CAAK,CAAA,CAAE,KAAA,CAAM,IAAA,CAAK,MAAA,CAAO,MAAM,CAAC,CAAC,CAAA;AAChF,IAAA,IAAI,QAAA,CAAS,MAAA,KAAW,CAAA,EAAG,OAAO,CAAA;AAClC,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,GAAG,QAAQ,CAAA;AAAA,EACpC;AACF","file":"redis.mjs","sourcesContent":["import type { CacheAdapter } from \"../types\";\n\n/**\n * Minimal interface representing a Redis client.\n * Compatible with both `ioredis` and `redis` (node-redis v4+).\n */\nexport interface RedisLikeClient {\n get(key: string): Promise<string | null>;\n set(key: string, value: string, ...args: unknown[]): Promise<unknown>;\n del(...keys: (string | string[])[]): Promise<number>;\n keys(pattern: string): Promise<string[]>;\n /** Optional SCAN-based iteration — used when available to avoid blocking the server. */\n scanIterator?(options: { MATCH: string; COUNT?: number }): AsyncIterable<string>;\n}\n\nexport interface RedisCacheOptions {\n /** A Redis client instance (ioredis or node-redis). */\n client: RedisLikeClient;\n /** Key prefix to namespace ani-client entries (default: `\"ani:\"`) */\n prefix?: string;\n /** TTL in seconds (default: 86 400 = 24 h) */\n ttl?: number;\n}\n\n/**\n * Redis-backed cache adapter for AniListClient.\n *\n * @example\n * ```ts\n * import Redis from \"ioredis\";\n * import { AniListClient, RedisCache } from \"ani-client\";\n *\n * const redis = new Redis();\n * const client = new AniListClient({\n * cacheAdapter: new RedisCache({ client: redis }),\n * });\n * ```\n */\nexport class RedisCache implements CacheAdapter {\n private readonly client: RedisLikeClient;\n private readonly prefix: string;\n private readonly ttl: number;\n\n constructor(options: RedisCacheOptions) {\n this.client = options.client;\n this.prefix = options.prefix ?? \"ani:\";\n this.ttl = options.ttl ?? 86_400;\n }\n\n private prefixedKey(key: string): string {\n return `${this.prefix}${key}`;\n }\n\n async get<T>(key: string): Promise<T | undefined> {\n const raw = await this.client.get(this.prefixedKey(key));\n if (raw === null) return undefined;\n try {\n return JSON.parse(raw) as T;\n } catch {\n return undefined;\n }\n }\n\n async set<T>(key: string, data: T): Promise<void> {\n await this.client.set(this.prefixedKey(key), JSON.stringify(data), \"EX\", this.ttl);\n }\n\n async delete(key: string): Promise<boolean> {\n const count = await this.client.del(this.prefixedKey(key));\n return count > 0;\n }\n\n /**\n * Collect keys matching a pattern. Uses SCAN when available, falls back to KEYS.\n *\n * **Warning:** The `KEYS` fallback is O(N) and blocks the Redis server.\n * Provide a client with `scanIterator` support for production use.\n * @internal\n */\n private async collectKeys(pattern: string): Promise<string[]> {\n if (this.client.scanIterator) {\n const keys: string[] = [];\n for await (const key of this.client.scanIterator({ MATCH: pattern, COUNT: 100 })) {\n keys.push(key);\n }\n return keys;\n }\n return this.client.keys(pattern);\n }\n\n async clear(): Promise<void> {\n const keys = await this.collectKeys(`${this.prefix}*`);\n if (keys.length > 0) {\n await this.client.del(...keys);\n }\n }\n\n /**\n * Get the actual number of keys with this prefix in Redis.\n */\n get size(): Promise<number> {\n return this.getSize();\n }\n\n /** @internal */\n private async getSize(): Promise<number> {\n const keys = await this.collectKeys(`${this.prefix}*`);\n return keys.length;\n }\n\n async keys(): Promise<string[]> {\n const raw = await this.collectKeys(`${this.prefix}*`);\n return raw.map((k) => k.slice(this.prefix.length));\n }\n\n /**\n * Remove all entries whose key matches the given pattern.\n *\n * - **String**: treated as a substring match (e.g. `\"Media\"` removes all keys containing `\"Media\"`).\n * - **RegExp**: tested against each key directly.\n *\n * @param pattern — A string (substring match) or RegExp.\n * @returns Number of entries removed.\n */\n async invalidate(pattern: string | RegExp): Promise<number> {\n if (typeof pattern === \"string\") {\n const keys = await this.collectKeys(`${this.prefix}*${pattern}*`);\n if (keys.length === 0) return 0;\n return this.client.del(...keys);\n }\n\n const allKeys = await this.collectKeys(`${this.prefix}*`);\n const matching = allKeys.filter((k) => pattern.test(k.slice(this.prefix.length)));\n if (matching.length === 0) return 0;\n return this.client.del(...matching);\n }\n}\n"]}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,170 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
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, 85 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
|
-
}
|
|
1
|
+
import { F as FuzzyDate, P as PageInfo, E as ExternalLink, C as CacheAdapter, a as CacheOptions, b as PagedResult, A as AniListClientOptions, R as RateLimitInfo, c as ResponseMeta, d as RateLimitOptions } from './redis-AFbnh0Xa.mjs';
|
|
2
|
+
export { e as AniListHooks, L as Logger, f as RedisCache, g as RedisCacheOptions, h as RedisLikeClient } from './redis-AFbnh0Xa.mjs';
|
|
168
3
|
|
|
169
4
|
declare enum MediaListStatus {
|
|
170
5
|
CURRENT = "CURRENT",
|
|
@@ -1120,6 +955,11 @@ declare class NormalizedCache implements CacheAdapter {
|
|
|
1120
955
|
entitiesCount: number;
|
|
1121
956
|
};
|
|
1122
957
|
resetStats(): void;
|
|
958
|
+
/**
|
|
959
|
+
* Garbage-collect orphaned entities that are no longer referenced by any query.
|
|
960
|
+
* Called automatically on LRU eviction to prevent unbounded entity store growth.
|
|
961
|
+
*/
|
|
962
|
+
gc(): number;
|
|
1123
963
|
}
|
|
1124
964
|
|
|
1125
965
|
/** Cache performance statistics. */
|
|
@@ -1146,13 +986,10 @@ declare class MemoryCache implements CacheAdapter {
|
|
|
1146
986
|
/** Build a deterministic cache key from a query + variables pair. */
|
|
1147
987
|
static key(query: string, variables: Record<string, unknown>): string;
|
|
1148
988
|
/**
|
|
1149
|
-
* Retrieve a cached value
|
|
989
|
+
* Retrieve a cached value and its stale status.
|
|
1150
990
|
* With stale-while-revalidate enabled, returns stale data within the grace window
|
|
1151
991
|
* and flags it so the caller can refresh in the background.
|
|
1152
992
|
*/
|
|
1153
|
-
/**
|
|
1154
|
-
* Retrieve a cached value and its stale status.
|
|
1155
|
-
*/
|
|
1156
993
|
getWithMeta<T>(key: string): {
|
|
1157
994
|
data: T;
|
|
1158
995
|
stale: boolean;
|
|
@@ -1195,77 +1032,15 @@ declare class MemoryCache implements CacheAdapter {
|
|
|
1195
1032
|
}
|
|
1196
1033
|
|
|
1197
1034
|
/**
|
|
1198
|
-
*
|
|
1199
|
-
*
|
|
1200
|
-
*/
|
|
1201
|
-
interface RedisLikeClient {
|
|
1202
|
-
get(key: string): Promise<string | null>;
|
|
1203
|
-
set(key: string, value: string, ...args: unknown[]): Promise<unknown>;
|
|
1204
|
-
del(...keys: (string | string[])[]): Promise<number>;
|
|
1205
|
-
keys(pattern: string): Promise<string[]>;
|
|
1206
|
-
/** Optional SCAN-based iteration — used when available to avoid blocking the server. */
|
|
1207
|
-
scanIterator?(options: {
|
|
1208
|
-
MATCH: string;
|
|
1209
|
-
COUNT?: number;
|
|
1210
|
-
}): AsyncIterable<string>;
|
|
1211
|
-
}
|
|
1212
|
-
interface RedisCacheOptions {
|
|
1213
|
-
/** A Redis client instance (ioredis or node-redis). */
|
|
1214
|
-
client: RedisLikeClient;
|
|
1215
|
-
/** Key prefix to namespace ani-client entries (default: `"ani:"`) */
|
|
1216
|
-
prefix?: string;
|
|
1217
|
-
/** TTL in seconds (default: 86 400 = 24 h) */
|
|
1218
|
-
ttl?: number;
|
|
1219
|
-
}
|
|
1220
|
-
/**
|
|
1221
|
-
* Redis-backed cache adapter for AniListClient.
|
|
1035
|
+
* Base interface for the client context shared by all domain method modules.
|
|
1036
|
+
* Exposes only the internal request methods that domain functions need.
|
|
1222
1037
|
*
|
|
1223
|
-
* @
|
|
1224
|
-
* ```ts
|
|
1225
|
-
* import Redis from "ioredis";
|
|
1226
|
-
* import { AniListClient, RedisCache } from "ani-client";
|
|
1227
|
-
*
|
|
1228
|
-
* const redis = new Redis();
|
|
1229
|
-
* const client = new AniListClient({
|
|
1230
|
-
* cacheAdapter: new RedisCache({ client: redis }),
|
|
1231
|
-
* });
|
|
1232
|
-
* ```
|
|
1038
|
+
* @internal
|
|
1233
1039
|
*/
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
constructor(options: RedisCacheOptions);
|
|
1239
|
-
private prefixedKey;
|
|
1240
|
-
get<T>(key: string): Promise<T | undefined>;
|
|
1241
|
-
set<T>(key: string, data: T): Promise<void>;
|
|
1242
|
-
delete(key: string): Promise<boolean>;
|
|
1243
|
-
/**
|
|
1244
|
-
* Collect keys matching a pattern. Uses SCAN when available, falls back to KEYS.
|
|
1245
|
-
*
|
|
1246
|
-
* **Warning:** The `KEYS` fallback is O(N) and blocks the Redis server.
|
|
1247
|
-
* Provide a client with `scanIterator` support for production use.
|
|
1248
|
-
* @internal
|
|
1249
|
-
*/
|
|
1250
|
-
private collectKeys;
|
|
1251
|
-
clear(): Promise<void>;
|
|
1252
|
-
/**
|
|
1253
|
-
* Get the actual number of keys with this prefix in Redis.
|
|
1254
|
-
*/
|
|
1255
|
-
get size(): Promise<number>;
|
|
1256
|
-
/** @internal */
|
|
1257
|
-
private getSize;
|
|
1258
|
-
keys(): Promise<string[]>;
|
|
1259
|
-
/**
|
|
1260
|
-
* Remove all entries whose key matches the given pattern.
|
|
1261
|
-
*
|
|
1262
|
-
* - **String**: treated as a substring match (e.g. `"Media"` removes all keys containing `"Media"`).
|
|
1263
|
-
* - **RegExp**: tested against each key directly.
|
|
1264
|
-
*
|
|
1265
|
-
* @param pattern — A string (substring match) or RegExp.
|
|
1266
|
-
* @returns Number of entries removed.
|
|
1267
|
-
*/
|
|
1268
|
-
invalidate(pattern: string | RegExp): Promise<number>;
|
|
1040
|
+
interface ClientBase {
|
|
1041
|
+
request<T>(query: string, variables?: Record<string, unknown>): Promise<T>;
|
|
1042
|
+
pagedRequest<T>(query: string, variables: Record<string, unknown>, field: string): Promise<PagedResult<T>>;
|
|
1043
|
+
paginate<T>(fetchPage: (page: number) => Promise<PagedResult<T>>, maxPages?: number): AsyncGenerator<T, void, undefined>;
|
|
1269
1044
|
}
|
|
1270
1045
|
|
|
1271
1046
|
/**
|
|
@@ -1286,7 +1061,7 @@ declare class RedisCache implements CacheAdapter {
|
|
|
1286
1061
|
* });
|
|
1287
1062
|
* ```
|
|
1288
1063
|
*/
|
|
1289
|
-
declare class AniListClient {
|
|
1064
|
+
declare class AniListClient implements ClientBase {
|
|
1290
1065
|
private readonly apiUrl;
|
|
1291
1066
|
private readonly headers;
|
|
1292
1067
|
private readonly cacheAdapter;
|
|
@@ -1358,7 +1133,7 @@ declare class AniListClient {
|
|
|
1358
1133
|
*/
|
|
1359
1134
|
getMediaByMalId(malId: number, type?: MediaType): Promise<Media>;
|
|
1360
1135
|
/** Get the detailed schedule for the current week, sorted by day. */
|
|
1361
|
-
getWeeklySchedule(date?: Date): Promise<WeeklySchedule>;
|
|
1136
|
+
getWeeklySchedule(date?: Date, idNotIn?: number[]): Promise<WeeklySchedule>;
|
|
1362
1137
|
/** Get upcoming (not yet released) media. */
|
|
1363
1138
|
getPlanning(options?: GetPlanningOptions): Promise<PagedResult<Media>>;
|
|
1364
1139
|
/** Get recommendations for a specific media. */
|
|
@@ -1532,4 +1307,4 @@ declare class RateLimiter {
|
|
|
1532
1307
|
|
|
1533
1308
|
declare function parseAniListMarkdown(text: string): string;
|
|
1534
1309
|
|
|
1535
|
-
export { type AiringSchedule, AiringSort, AniListClient,
|
|
1310
|
+
export { type AiringSchedule, AiringSort, AniListClient, AniListClientOptions, AniListError, CacheAdapter, CacheOptions, type CacheStats, type Character, type CharacterImage, type CharacterIncludeOptions, type CharacterMediaEdge, type CharacterName, CharacterRole, CharacterSort, type DayOfWeek, ExternalLink, type FavoriteCharacterNode, type FavoriteMediaNode, type FavoriteStaffNode, type FavoriteStudioNode, FuzzyDate, type GetAiringOptions, type GetMediaCharactersOptions, type GetMediaStaffOptions, 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, NormalizedCache, PageInfo, PagedResult, RateLimitInfo, RateLimitOptions, RateLimiter, type Recommendation, RecommendationSort, 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 };
|