ani-client 2.1.4 → 2.2.0
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/dist/index.d.mts +28 -13
- package/dist/index.d.ts +28 -13
- package/dist/index.js +213 -44
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +213 -44
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -133,6 +133,7 @@ var NormalizedCache = class {
|
|
|
133
133
|
_hits = 0;
|
|
134
134
|
_misses = 0;
|
|
135
135
|
_stales = 0;
|
|
136
|
+
gcTimeout;
|
|
136
137
|
constructor(options = {}) {
|
|
137
138
|
this.ttl = options.ttl ?? 24 * 60 * 60 * 1e3;
|
|
138
139
|
this.maxSize = options.maxSize ?? 500;
|
|
@@ -244,8 +245,10 @@ var NormalizedCache = class {
|
|
|
244
245
|
this.queryStore.delete(key);
|
|
245
246
|
if (this.maxSize > 0 && this.queryStore.size >= this.maxSize) {
|
|
246
247
|
const firstKey = this.queryStore.keys().next().value;
|
|
247
|
-
if (firstKey !== void 0)
|
|
248
|
-
|
|
248
|
+
if (firstKey !== void 0) {
|
|
249
|
+
this.queryStore.delete(firstKey);
|
|
250
|
+
}
|
|
251
|
+
this.scheduleGc();
|
|
249
252
|
}
|
|
250
253
|
this.queryStore.set(key, { data: normalizedData, expiresAt: Date.now() + this.ttl });
|
|
251
254
|
}
|
|
@@ -253,6 +256,10 @@ var NormalizedCache = class {
|
|
|
253
256
|
return this.queryStore.delete(key);
|
|
254
257
|
}
|
|
255
258
|
clear() {
|
|
259
|
+
if (this.gcTimeout) {
|
|
260
|
+
clearTimeout(this.gcTimeout);
|
|
261
|
+
this.gcTimeout = void 0;
|
|
262
|
+
}
|
|
256
263
|
this.queryStore.clear();
|
|
257
264
|
this.entityStore.clear();
|
|
258
265
|
this._hits = 0;
|
|
@@ -289,6 +296,16 @@ var NormalizedCache = class {
|
|
|
289
296
|
this._misses = 0;
|
|
290
297
|
this._stales = 0;
|
|
291
298
|
}
|
|
299
|
+
scheduleGc() {
|
|
300
|
+
if (this.gcTimeout) return;
|
|
301
|
+
this.gcTimeout = setTimeout(() => {
|
|
302
|
+
this.gc();
|
|
303
|
+
this.gcTimeout = void 0;
|
|
304
|
+
}, 500);
|
|
305
|
+
if (typeof this.gcTimeout.unref === "function") {
|
|
306
|
+
this.gcTimeout.unref();
|
|
307
|
+
}
|
|
308
|
+
}
|
|
292
309
|
/**
|
|
293
310
|
* Garbage-collect orphaned entities that are no longer referenced by any query.
|
|
294
311
|
* Called automatically on LRU eviction to prevent unbounded entity store growth.
|
|
@@ -1181,8 +1198,7 @@ query ($mediaId: Int!, $page: Int, $perPage: Int, $sort: [RecommendationSort]) {
|
|
|
1181
1198
|
}`;
|
|
1182
1199
|
|
|
1183
1200
|
// src/queries/builders.ts
|
|
1184
|
-
function
|
|
1185
|
-
if (!include) return QUERY_MEDIA_BY_ID;
|
|
1201
|
+
function buildMediaIncludeQuery(include) {
|
|
1186
1202
|
const extra = [];
|
|
1187
1203
|
if (include.relations !== false) {
|
|
1188
1204
|
extra.push(RELATIONS_FIELDS);
|
|
@@ -1257,14 +1273,172 @@ function buildMediaByIdQuery(include) {
|
|
|
1257
1273
|
statusDistribution { status amount }
|
|
1258
1274
|
}`);
|
|
1259
1275
|
}
|
|
1276
|
+
return extra;
|
|
1277
|
+
}
|
|
1278
|
+
function buildMediaByIdQuery(include) {
|
|
1279
|
+
if (!include) return QUERY_MEDIA_BY_ID;
|
|
1260
1280
|
return `
|
|
1261
1281
|
query ($id: Int!) {
|
|
1262
1282
|
Media(id: $id) {
|
|
1263
1283
|
${MEDIA_FIELDS_BASE}
|
|
1264
|
-
${
|
|
1284
|
+
${buildMediaIncludeQuery(include).join("\n")}
|
|
1265
1285
|
}
|
|
1266
1286
|
}`;
|
|
1267
1287
|
}
|
|
1288
|
+
function buildSearchMediaQuery(include) {
|
|
1289
|
+
if (!include) return QUERY_MEDIA_SEARCH;
|
|
1290
|
+
return `
|
|
1291
|
+
query (
|
|
1292
|
+
$search: String,
|
|
1293
|
+
$countryOfOrigin: CountryCode,
|
|
1294
|
+
$type: MediaType,
|
|
1295
|
+
$format: MediaFormat,
|
|
1296
|
+
$format_in: [MediaFormat],
|
|
1297
|
+
$status: MediaStatus,
|
|
1298
|
+
$season: MediaSeason,
|
|
1299
|
+
$seasonYear: Int,
|
|
1300
|
+
$genre: String,
|
|
1301
|
+
$tag: String,
|
|
1302
|
+
$genre_in: [String],
|
|
1303
|
+
$tag_in: [String],
|
|
1304
|
+
$genre_not_in: [String],
|
|
1305
|
+
$tag_not_in: [String],
|
|
1306
|
+
$isAdult: Boolean,
|
|
1307
|
+
$idNotIn: [Int],
|
|
1308
|
+
$sort: [MediaSort],
|
|
1309
|
+
$page: Int,
|
|
1310
|
+
$perPage: Int
|
|
1311
|
+
) {
|
|
1312
|
+
Page(page: $page, perPage: $perPage) {
|
|
1313
|
+
pageInfo { total perPage currentPage lastPage hasNextPage }
|
|
1314
|
+
media(
|
|
1315
|
+
search: $search,
|
|
1316
|
+
countryOfOrigin: $countryOfOrigin,
|
|
1317
|
+
type: $type,
|
|
1318
|
+
format: $format,
|
|
1319
|
+
format_in: $format_in,
|
|
1320
|
+
status: $status,
|
|
1321
|
+
season: $season,
|
|
1322
|
+
seasonYear: $seasonYear,
|
|
1323
|
+
genre: $genre,
|
|
1324
|
+
tag: $tag,
|
|
1325
|
+
genre_in: $genre_in,
|
|
1326
|
+
tag_in: $tag_in,
|
|
1327
|
+
genre_not_in: $genre_not_in,
|
|
1328
|
+
tag_not_in: $tag_not_in,
|
|
1329
|
+
isAdult: $isAdult,
|
|
1330
|
+
id_not_in: $idNotIn,
|
|
1331
|
+
sort: $sort
|
|
1332
|
+
) {
|
|
1333
|
+
${MEDIA_FIELDS_BASE}
|
|
1334
|
+
${buildMediaIncludeQuery(include).join("\n")}
|
|
1335
|
+
}
|
|
1336
|
+
}
|
|
1337
|
+
}`;
|
|
1338
|
+
}
|
|
1339
|
+
function buildGetTrendingQuery(include) {
|
|
1340
|
+
if (!include) return QUERY_TRENDING;
|
|
1341
|
+
return `
|
|
1342
|
+
query (
|
|
1343
|
+
$type: MediaType,
|
|
1344
|
+
$isAdult: Boolean,
|
|
1345
|
+
$idNotIn: [Int],
|
|
1346
|
+
$page: Int,
|
|
1347
|
+
$perPage: Int
|
|
1348
|
+
) {
|
|
1349
|
+
Page(page: $page, perPage: $perPage) {
|
|
1350
|
+
pageInfo { total perPage currentPage lastPage hasNextPage }
|
|
1351
|
+
media(
|
|
1352
|
+
type: $type,
|
|
1353
|
+
isAdult: $isAdult,
|
|
1354
|
+
id_not_in: $idNotIn,
|
|
1355
|
+
sort: TRENDING_DESC
|
|
1356
|
+
) {
|
|
1357
|
+
${MEDIA_FIELDS_BASE}
|
|
1358
|
+
${buildMediaIncludeQuery(include).join("\n")}
|
|
1359
|
+
}
|
|
1360
|
+
}
|
|
1361
|
+
}`;
|
|
1362
|
+
}
|
|
1363
|
+
function buildGetMediaBySeasonQuery(include) {
|
|
1364
|
+
if (!include) return QUERY_MEDIA_BY_SEASON;
|
|
1365
|
+
return `
|
|
1366
|
+
query (
|
|
1367
|
+
$season: MediaSeason!,
|
|
1368
|
+
$seasonYear: Int!,
|
|
1369
|
+
$type: MediaType,
|
|
1370
|
+
$isAdult: Boolean,
|
|
1371
|
+
$idNotIn: [Int],
|
|
1372
|
+
$sort: [MediaSort],
|
|
1373
|
+
$page: Int,
|
|
1374
|
+
$perPage: Int
|
|
1375
|
+
) {
|
|
1376
|
+
Page(page: $page, perPage: $perPage) {
|
|
1377
|
+
pageInfo { total perPage currentPage lastPage hasNextPage }
|
|
1378
|
+
media(
|
|
1379
|
+
season: $season,
|
|
1380
|
+
seasonYear: $seasonYear,
|
|
1381
|
+
type: $type,
|
|
1382
|
+
isAdult: $isAdult,
|
|
1383
|
+
id_not_in: $idNotIn,
|
|
1384
|
+
sort: $sort
|
|
1385
|
+
) {
|
|
1386
|
+
${MEDIA_FIELDS_BASE}
|
|
1387
|
+
${buildMediaIncludeQuery(include).join("\n")}
|
|
1388
|
+
}
|
|
1389
|
+
}
|
|
1390
|
+
}`;
|
|
1391
|
+
}
|
|
1392
|
+
function buildGetRecentlyUpdatedMangaQuery(include) {
|
|
1393
|
+
if (!include) return QUERY_RECENT_CHAPTERS;
|
|
1394
|
+
return `
|
|
1395
|
+
query (
|
|
1396
|
+
$isAdult: Boolean,
|
|
1397
|
+
$idNotIn: [Int],
|
|
1398
|
+
$page: Int,
|
|
1399
|
+
$perPage: Int
|
|
1400
|
+
) {
|
|
1401
|
+
Page(page: $page, perPage: $perPage) {
|
|
1402
|
+
pageInfo { total perPage currentPage lastPage hasNextPage }
|
|
1403
|
+
media(
|
|
1404
|
+
type: MANGA,
|
|
1405
|
+
isAdult: $isAdult,
|
|
1406
|
+
id_not_in: $idNotIn,
|
|
1407
|
+
status: RELEASING,
|
|
1408
|
+
sort: UPDATED_AT_DESC
|
|
1409
|
+
) {
|
|
1410
|
+
${MEDIA_FIELDS_BASE}
|
|
1411
|
+
${buildMediaIncludeQuery(include).join("\n")}
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
}`;
|
|
1415
|
+
}
|
|
1416
|
+
function buildGetPlanningQuery(include) {
|
|
1417
|
+
if (!include) return QUERY_PLANNING;
|
|
1418
|
+
return `
|
|
1419
|
+
query (
|
|
1420
|
+
$type: MediaType,
|
|
1421
|
+
$isAdult: Boolean,
|
|
1422
|
+
$idNotIn: [Int],
|
|
1423
|
+
$sort: [MediaSort],
|
|
1424
|
+
$page: Int,
|
|
1425
|
+
$perPage: Int
|
|
1426
|
+
) {
|
|
1427
|
+
Page(page: $page, perPage: $perPage) {
|
|
1428
|
+
pageInfo { total perPage currentPage lastPage hasNextPage }
|
|
1429
|
+
media(
|
|
1430
|
+
type: $type,
|
|
1431
|
+
isAdult: $isAdult,
|
|
1432
|
+
id_not_in: $idNotIn,
|
|
1433
|
+
status: NOT_YET_RELEASED,
|
|
1434
|
+
sort: $sort
|
|
1435
|
+
) {
|
|
1436
|
+
${MEDIA_FIELDS_BASE}
|
|
1437
|
+
${buildMediaIncludeQuery(include).join("\n")}
|
|
1438
|
+
}
|
|
1439
|
+
}
|
|
1440
|
+
}`;
|
|
1441
|
+
}
|
|
1268
1442
|
function buildMediaCharactersQuery(options = {}) {
|
|
1269
1443
|
const sortClause = options.sort === false ? "" : ", sort: [ROLE, RELEVANCE, ID]";
|
|
1270
1444
|
const voiceActorBlock = options.voiceActors ? `
|
|
@@ -2066,7 +2240,7 @@ async function getMediaByMalId(client, malId, type) {
|
|
|
2066
2240
|
});
|
|
2067
2241
|
return data.Media;
|
|
2068
2242
|
}
|
|
2069
|
-
async function searchMedia(client, options = {}) {
|
|
2243
|
+
async function searchMedia(client, options = {}, include) {
|
|
2070
2244
|
const {
|
|
2071
2245
|
query: search,
|
|
2072
2246
|
page = 1,
|
|
@@ -2078,8 +2252,9 @@ async function searchMedia(client, options = {}) {
|
|
|
2078
2252
|
format,
|
|
2079
2253
|
...filters
|
|
2080
2254
|
} = options;
|
|
2255
|
+
const query = buildSearchMediaQuery(include);
|
|
2081
2256
|
return client.pagedRequest(
|
|
2082
|
-
|
|
2257
|
+
query,
|
|
2083
2258
|
{
|
|
2084
2259
|
search,
|
|
2085
2260
|
...filters,
|
|
@@ -2095,21 +2270,18 @@ async function searchMedia(client, options = {}) {
|
|
|
2095
2270
|
"media"
|
|
2096
2271
|
);
|
|
2097
2272
|
}
|
|
2098
|
-
async function getTrending(client, options) {
|
|
2273
|
+
async function getTrending(client, options, include) {
|
|
2099
2274
|
const { type = "ANIME" /* ANIME */, isAdult = false, idNotIn = [], page = 1, perPage = 20 } = options;
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
{ type, isAdult, idNotIn, page, perPage: clampPerPage(perPage) },
|
|
2103
|
-
"media"
|
|
2104
|
-
);
|
|
2275
|
+
const query = buildGetTrendingQuery(include);
|
|
2276
|
+
return client.pagedRequest(query, { type, isAdult, idNotIn, page, perPage: clampPerPage(perPage) }, "media");
|
|
2105
2277
|
}
|
|
2106
|
-
async function getPopular(client, options) {
|
|
2278
|
+
async function getPopular(client, options, include) {
|
|
2107
2279
|
const { type = "ANIME" /* ANIME */, isAdult = false, idNotIn = [], page = 1, perPage = 20 } = options;
|
|
2108
|
-
return searchMedia(client, { type, isAdult, idNotIn, sort: ["POPULARITY_DESC" /* POPULARITY_DESC */], page, perPage });
|
|
2280
|
+
return searchMedia(client, { type, isAdult, idNotIn, sort: ["POPULARITY_DESC" /* POPULARITY_DESC */], page, perPage }, include);
|
|
2109
2281
|
}
|
|
2110
|
-
async function getTopRated(client, options) {
|
|
2282
|
+
async function getTopRated(client, options, include) {
|
|
2111
2283
|
const { type = "ANIME" /* ANIME */, isAdult = false, idNotIn = [], page = 1, perPage = 20 } = options;
|
|
2112
|
-
return searchMedia(client, { type, isAdult, idNotIn, sort: ["SCORE_DESC" /* SCORE_DESC */], page, perPage });
|
|
2284
|
+
return searchMedia(client, { type, isAdult, idNotIn, sort: ["SCORE_DESC" /* SCORE_DESC */], page, perPage }, include);
|
|
2113
2285
|
}
|
|
2114
2286
|
async function getAiredEpisodes(client, options = {}) {
|
|
2115
2287
|
const now = Math.floor(Date.now() / 1e3);
|
|
@@ -2126,9 +2298,10 @@ async function getAiredEpisodes(client, options = {}) {
|
|
|
2126
2298
|
"airingSchedules"
|
|
2127
2299
|
);
|
|
2128
2300
|
}
|
|
2129
|
-
async function getRecentlyUpdatedManga(client, options = {}) {
|
|
2301
|
+
async function getRecentlyUpdatedManga(client, options = {}, include) {
|
|
2302
|
+
const query = buildGetRecentlyUpdatedMangaQuery(include);
|
|
2130
2303
|
return client.pagedRequest(
|
|
2131
|
-
|
|
2304
|
+
query,
|
|
2132
2305
|
{
|
|
2133
2306
|
isAdult: options.isAdult ?? false,
|
|
2134
2307
|
idNotIn: options.idNotIn ?? [],
|
|
@@ -2138,9 +2311,10 @@ async function getRecentlyUpdatedManga(client, options = {}) {
|
|
|
2138
2311
|
"media"
|
|
2139
2312
|
);
|
|
2140
2313
|
}
|
|
2141
|
-
async function getPlanning(client, options = {}) {
|
|
2314
|
+
async function getPlanning(client, options = {}, include) {
|
|
2315
|
+
const query = buildGetPlanningQuery(include);
|
|
2142
2316
|
return client.pagedRequest(
|
|
2143
|
-
|
|
2317
|
+
query,
|
|
2144
2318
|
{
|
|
2145
2319
|
type: options.type,
|
|
2146
2320
|
isAdult: options.isAdult ?? false,
|
|
@@ -2165,9 +2339,10 @@ async function getRecommendations(client, mediaId, options = {}) {
|
|
|
2165
2339
|
results: data.Media.recommendations.nodes
|
|
2166
2340
|
};
|
|
2167
2341
|
}
|
|
2168
|
-
async function getMediaBySeason(client, options) {
|
|
2342
|
+
async function getMediaBySeason(client, options, include) {
|
|
2343
|
+
const query = buildGetMediaBySeasonQuery(include);
|
|
2169
2344
|
return client.pagedRequest(
|
|
2170
|
-
|
|
2345
|
+
query,
|
|
2171
2346
|
{
|
|
2172
2347
|
season: options.season,
|
|
2173
2348
|
seasonYear: options.seasonYear,
|
|
@@ -2364,7 +2539,7 @@ function mapFavorites(fav) {
|
|
|
2364
2539
|
|
|
2365
2540
|
// src/client/index.ts
|
|
2366
2541
|
var DEFAULT_API_URL = "https://graphql.anilist.co";
|
|
2367
|
-
var LIB_VERSION = "2.
|
|
2542
|
+
var LIB_VERSION = "2.2.0" ;
|
|
2368
2543
|
var AniListClient = class {
|
|
2369
2544
|
apiUrl;
|
|
2370
2545
|
headers;
|
|
@@ -2534,20 +2709,20 @@ var AniListClient = class {
|
|
|
2534
2709
|
* @param options - Search / filter parameters
|
|
2535
2710
|
* @returns Paginated results with matching media
|
|
2536
2711
|
*/
|
|
2537
|
-
async searchMedia(options = {}) {
|
|
2538
|
-
return searchMedia(this, options);
|
|
2712
|
+
async searchMedia(options = {}, include) {
|
|
2713
|
+
return searchMedia(this, options, include);
|
|
2539
2714
|
}
|
|
2540
2715
|
/** Get currently trending anime or manga. */
|
|
2541
|
-
async getTrending(options = {}) {
|
|
2542
|
-
return getTrending(this, options);
|
|
2716
|
+
async getTrending(options = {}, include) {
|
|
2717
|
+
return getTrending(this, options, include);
|
|
2543
2718
|
}
|
|
2544
2719
|
/** Get the most popular anime or manga. */
|
|
2545
|
-
async getPopular(options = {}) {
|
|
2546
|
-
return getPopular(this, options);
|
|
2720
|
+
async getPopular(options = {}, include) {
|
|
2721
|
+
return getPopular(this, options, include);
|
|
2547
2722
|
}
|
|
2548
2723
|
/** Get the highest-rated anime or manga. */
|
|
2549
|
-
async getTopRated(options = {}) {
|
|
2550
|
-
return getTopRated(this, options);
|
|
2724
|
+
async getTopRated(options = {}, include) {
|
|
2725
|
+
return getTopRated(this, options, include);
|
|
2551
2726
|
}
|
|
2552
2727
|
/** Get recently aired anime episodes. */
|
|
2553
2728
|
async getAiredEpisodes(options = {}) {
|
|
@@ -2558,14 +2733,8 @@ var AniListClient = class {
|
|
|
2558
2733
|
*
|
|
2559
2734
|
* @param options - Pagination parameters
|
|
2560
2735
|
*/
|
|
2561
|
-
async getRecentlyUpdatedManga(options = {}) {
|
|
2562
|
-
return getRecentlyUpdatedManga(this, options);
|
|
2563
|
-
}
|
|
2564
|
-
/**
|
|
2565
|
-
* @deprecated Use `getRecentlyUpdatedManga()` instead. This alias will be removed in v3.
|
|
2566
|
-
*/
|
|
2567
|
-
async getAiredChapters(options = {}) {
|
|
2568
|
-
return this.getRecentlyUpdatedManga(options);
|
|
2736
|
+
async getRecentlyUpdatedManga(options = {}, include) {
|
|
2737
|
+
return getRecentlyUpdatedManga(this, options, include);
|
|
2569
2738
|
}
|
|
2570
2739
|
/**
|
|
2571
2740
|
* Fetch a media entry by its MyAnimeList (MAL) ID.
|
|
@@ -2581,16 +2750,16 @@ var AniListClient = class {
|
|
|
2581
2750
|
return getWeeklySchedule(this, date, idNotIn);
|
|
2582
2751
|
}
|
|
2583
2752
|
/** Get upcoming (not yet released) media. */
|
|
2584
|
-
async getPlanning(options = {}) {
|
|
2585
|
-
return getPlanning(this, options);
|
|
2753
|
+
async getPlanning(options = {}, include) {
|
|
2754
|
+
return getPlanning(this, options, include);
|
|
2586
2755
|
}
|
|
2587
2756
|
/** Get recommendations for a specific media. */
|
|
2588
2757
|
async getRecommendations(mediaId, options = {}) {
|
|
2589
2758
|
return getRecommendations(this, mediaId, options);
|
|
2590
2759
|
}
|
|
2591
2760
|
/** Get anime (or manga) for a specific season and year. */
|
|
2592
|
-
async getMediaBySeason(options) {
|
|
2593
|
-
return getMediaBySeason(this, options);
|
|
2761
|
+
async getMediaBySeason(options, include) {
|
|
2762
|
+
return getMediaBySeason(this, options, include);
|
|
2594
2763
|
}
|
|
2595
2764
|
/** Fetch a character by AniList ID. Pass `{ voiceActors: true }` to include VA data. */
|
|
2596
2765
|
async getCharacter(id, include) {
|