ani-client 1.0.0 → 1.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/README.md CHANGED
@@ -69,6 +69,8 @@ client.getMedia(1).then((anime) => console.log(anime.title.romaji));
69
69
  | `getMedia(id: number)` | Fetch a single anime / manga by ID |
70
70
  | `searchMedia(options?)` | Search & filter anime / manga |
71
71
  | `getTrending(type?, page?, perPage?)` | Get currently trending entries |
72
+ | `getMediaBySeason(options)` | Get all anime/manga for a given season & year |
73
+ | `getRecommendations(mediaId, options?)` | Get user recommendations for a media |
72
74
 
73
75
  ### Characters
74
76
 
@@ -90,6 +92,29 @@ client.getMedia(1).then((anime) => console.log(anime.title.romaji));
90
92
  | ----------------------------------- | ------------------------------------ |
91
93
  | `getUser(id: number)` | Fetch a user by ID |
92
94
  | `getUserByName(name: string)` | Fetch a user by username |
95
+ | `getUserMediaList(options)` | Get a user's anime or manga list |
96
+
97
+ ### Airing, Chapters & Planning
98
+
99
+ | Method | Description |
100
+ | ----------------------------------- | ------------------------------------ |
101
+ | `getAiredEpisodes(options?)` | Recently aired anime episodes (last 24 h by default) |
102
+ | `getAiredChapters(options?)` | Recently updated releasing manga |
103
+ | `getPlanning(options?)` | Upcoming not-yet-released anime / manga |
104
+
105
+ ### Studios
106
+
107
+ | Method | Description |
108
+ | ----------------------------------- | ------------------------------------ |
109
+ | `getStudio(id: number)` | Fetch a studio by ID |
110
+ | `searchStudios(options?)` | Search studios by name |
111
+
112
+ ### Genres & Tags
113
+
114
+ | Method | Description |
115
+ | ----------------------------------- | ------------------------------------ |
116
+ | `getGenres()` | List all available genres |
117
+ | `getTags()` | List all available media tags |
93
118
 
94
119
  ### Raw queries
95
120
 
@@ -97,6 +122,12 @@ client.getMedia(1).then((anime) => console.log(anime.title.romaji));
97
122
  | ----------------------------------- | ------------------------------------ |
98
123
  | `raw<T>(query, variables?)` | Execute any GraphQL query |
99
124
 
125
+ ### Pagination helper
126
+
127
+ | Method | Description |
128
+ | ----------------------------------- | ------------------------------------ |
129
+ | `paginate<T>(fetchPage, maxPages?)` | Auto-paginating async iterator |
130
+
100
131
  ### Cache management
101
132
 
102
133
  | Method / Property | Description |
@@ -138,6 +169,261 @@ const client = new AniListClient({
138
169
  });
139
170
  ```
140
171
 
172
+ ## Airing, Chapters & Planning
173
+
174
+ Fetch recently released content or see what's coming up next.
175
+
176
+ ### `getAiredEpisodes(options?)`
177
+
178
+ Returns anime episodes that recently aired (defaults to the **last 24 hours**).
179
+
180
+ | Option | Type | Default | Description |
181
+ | ----------------- | -------------- | -------------------- | -------------------------------------------- |
182
+ | `airingAtGreater` | `number` | `now - 24h` (UNIX) | Only episodes aired after this timestamp |
183
+ | `airingAtLesser` | `number` | `now` (UNIX) | Only episodes aired before this timestamp |
184
+ | `sort` | `AiringSort[]` | `["TIME_DESC"]` | Sort order |
185
+ | `page` | `number` | `1` | Page number |
186
+ | `perPage` | `number` | `20` | Results per page (max 50) |
187
+
188
+ ```ts
189
+ import { AniListClient } from "ani-client";
190
+
191
+ const client = new AniListClient();
192
+
193
+ // Episodes aired in the last 24 hours
194
+ const recent = await client.getAiredEpisodes();
195
+ recent.results.forEach((ep) =>
196
+ console.log(`${ep.media.title.romaji} — Episode ${ep.episode}`)
197
+ );
198
+
199
+ // Episodes aired in the last 7 days
200
+ const week = await client.getAiredEpisodes({
201
+ airingAtGreater: Math.floor(Date.now() / 1000) - 7 * 24 * 3600,
202
+ perPage: 50,
203
+ });
204
+ ```
205
+
206
+ ### `getAiredChapters(options?)`
207
+
208
+ Returns currently releasing manga, sorted by most recently updated — the closest proxy to "recently released chapters" (AniList does not expose individual chapter schedules).
209
+
210
+ | Option | Type | Default | Description |
211
+ | --------- | -------- | ------- | ----------------------- |
212
+ | `page` | `number` | `1` | Page number |
213
+ | `perPage` | `number` | `20` | Results per page (max 50) |
214
+
215
+ ```ts
216
+ const chapters = await client.getAiredChapters({ perPage: 10 });
217
+ chapters.results.forEach((m) =>
218
+ console.log(`${m.title.romaji} — ${m.chapters ?? "?"} chapters`)
219
+ );
220
+ ```
221
+
222
+ ### `getPlanning(options?)`
223
+
224
+ Returns anime and/or manga that are **not yet released**, sorted by popularity.
225
+
226
+ | Option | Type | Default | Description |
227
+ | --------- | ------------- | -------------------- | ---------------------------------- |
228
+ | `type` | `MediaType` | — | Filter by ANIME or MANGA (both if omitted) |
229
+ | `sort` | `MediaSort[]` | `["POPULARITY_DESC"]` | Sort order |
230
+ | `page` | `number` | `1` | Page number |
231
+ | `perPage` | `number` | `20` | Results per page (max 50) |
232
+
233
+ ```ts
234
+ import { MediaType } from "ani-client";
235
+
236
+ // Most anticipated upcoming anime
237
+ const upcoming = await client.getPlanning({ type: MediaType.ANIME, perPage: 10 });
238
+ upcoming.results.forEach((m) => console.log(m.title.romaji));
239
+
240
+ // All upcoming media (anime + manga)
241
+ const all = await client.getPlanning();
242
+ ```
243
+
244
+ ## Season charts
245
+
246
+ Fetch all anime (or manga) for a specific season and year.
247
+
248
+ ### `getMediaBySeason(options)`
249
+
250
+ | Option | Type | Default | Description |
251
+ | ------------ | -------------- | -------------------- | ---------------------------------------- |
252
+ | `season` | `MediaSeason` | **(required)** | WINTER, SPRING, SUMMER, or FALL |
253
+ | `seasonYear` | `number` | **(required)** | The year (e.g. 2026) |
254
+ | `type` | `MediaType` | `ANIME` | Filter by ANIME or MANGA |
255
+ | `sort` | `MediaSort[]` | `["POPULARITY_DESC"]`| Sort order |
256
+ | `page` | `number` | `1` | Page number |
257
+ | `perPage` | `number` | `20` | Results per page (max 50) |
258
+
259
+ ```ts
260
+ import { AniListClient, MediaSeason } from "ani-client";
261
+
262
+ const client = new AniListClient();
263
+
264
+ // All anime from Winter 2026
265
+ const winter2026 = await client.getMediaBySeason({
266
+ season: MediaSeason.WINTER,
267
+ seasonYear: 2026,
268
+ perPage: 25,
269
+ });
270
+ winter2026.results.forEach((m) => console.log(m.title.romaji));
271
+
272
+ // Spring 2025 manga
273
+ const spring = await client.getMediaBySeason({
274
+ season: MediaSeason.SPRING,
275
+ seasonYear: 2025,
276
+ type: MediaType.MANGA,
277
+ });
278
+ ```
279
+
280
+ ## User media lists
281
+
282
+ Fetch a user's anime or manga list, optionally filtered by status.
283
+
284
+ ### `getUserMediaList(options)`
285
+
286
+ | Option | Type | Default | Description |
287
+ | ---------- | ----------------- | -------------------- | ------------------------------------------ |
288
+ | `userId` | `number` | — | User ID (provide userId **or** userName) |
289
+ | `userName` | `string` | — | Username (provide userId **or** userName) |
290
+ | `type` | `MediaType` | **(required)** | ANIME or MANGA |
291
+ | `status` | `MediaListStatus` | — | Filter: CURRENT, COMPLETED, PLANNING, etc. |
292
+ | `sort` | `MediaListSort[]` | — | Sort order |
293
+ | `page` | `number` | `1` | Page number |
294
+ | `perPage` | `number` | `20` | Results per page (max 50) |
295
+
296
+ ```ts
297
+ import { AniListClient, MediaType, MediaListStatus } from "ani-client";
298
+
299
+ const client = new AniListClient();
300
+
301
+ // All anime on a user's list
302
+ const list = await client.getUserMediaList({
303
+ userName: "AniList",
304
+ type: MediaType.ANIME,
305
+ perPage: 10,
306
+ });
307
+ list.results.forEach((entry) =>
308
+ console.log(`${entry.media.title.romaji} — ${entry.score}/100`)
309
+ );
310
+
311
+ // Only completed anime
312
+ const completed = await client.getUserMediaList({
313
+ userName: "AniList",
314
+ type: MediaType.ANIME,
315
+ status: MediaListStatus.COMPLETED,
316
+ });
317
+
318
+ // By user ID
319
+ const byId = await client.getUserMediaList({
320
+ userId: 1,
321
+ type: MediaType.MANGA,
322
+ });
323
+ ```
324
+
325
+ ## Recommendations
326
+
327
+ Get user-submitted recommendations for a specific anime or manga.
328
+
329
+ ### `getRecommendations(mediaId, options?)`
330
+
331
+ | Option | Type | Default | Description |
332
+ | --------- | ---------------------- | ------------------ | ----------------------- |
333
+ | `sort` | `RecommendationSort[]` | `["RATING_DESC"]` | Sort order |
334
+ | `page` | `number` | `1` | Page number |
335
+ | `perPage` | `number` | `20` | Results per page |
336
+
337
+ ```ts
338
+ import { AniListClient } from "ani-client";
339
+
340
+ const client = new AniListClient();
341
+
342
+ // Recommendations for Cowboy Bebop
343
+ const recs = await client.getRecommendations(1);
344
+ recs.results.forEach((r) =>
345
+ console.log(`${r.mediaRecommendation.title.romaji} (rating: ${r.rating})`)
346
+ );
347
+
348
+ // With pagination
349
+ const page2 = await client.getRecommendations(20, { page: 2, perPage: 10 });
350
+ ```
351
+
352
+ ## Relations
353
+
354
+ All media objects now include a `relations` field with sequels, prequels, spin-offs, etc.
355
+
356
+ ```ts
357
+ const anime = await client.getMedia(1); // Cowboy Bebop
358
+ anime.relations?.edges.forEach((edge) =>
359
+ console.log(`${edge.relationType}: ${edge.node.title.romaji}`)
360
+ );
361
+ // SIDE_STORY: Cowboy Bebop: Tengoku no Tobira
362
+ ```
363
+
364
+ Available relation types: `ADAPTATION`, `PREQUEL`, `SEQUEL`, `PARENT`, `SIDE_STORY`, `CHARACTER`, `SUMMARY`, `ALTERNATIVE`, `SPIN_OFF`, `OTHER`, `SOURCE`, `COMPILATION`, `CONTAINS`.
365
+
366
+ ## Studios
367
+
368
+ Fetch or search for animation studios.
369
+
370
+ ### `getStudio(id)`
371
+
372
+ Returns the studio with its most popular productions.
373
+
374
+ ```ts
375
+ const studio = await client.getStudio(44); // Bones
376
+ console.log(studio.name); // "Bones"
377
+ console.log(studio.isAnimationStudio); // true
378
+ studio.media?.nodes.forEach((m) => console.log(m.title.romaji));
379
+ ```
380
+
381
+ ### `searchStudios(options?)`
382
+
383
+ | Option | Type | Default | Description |
384
+ | --------- | -------- | ------- | ----------------------- |
385
+ | `query` | `string` | — | Search term |
386
+ | `page` | `number` | `1` | Page number |
387
+ | `perPage` | `number` | `20` | Results per page |
388
+
389
+ ```ts
390
+ const result = await client.searchStudios({ query: "MAPPA" });
391
+ result.results.forEach((s) => console.log(s.name));
392
+ ```
393
+
394
+ ## Genres & Tags
395
+
396
+ List all genres and tags available on AniList.
397
+
398
+ ```ts
399
+ const genres = await client.getGenres();
400
+ console.log(genres); // ["Action", "Adventure", "Comedy", ...]
401
+
402
+ const tags = await client.getTags();
403
+ tags.forEach((t) => console.log(`${t.name} (${t.category})`));
404
+ ```
405
+
406
+ ## Auto-pagination
407
+
408
+ Use `paginate()` to iterate across all pages automatically with an async iterator.
409
+
410
+ ```ts
411
+ // Iterate over all search results
412
+ for await (const anime of client.paginate((page) =>
413
+ client.searchMedia({ query: "Gundam", page, perPage: 10 })
414
+ )) {
415
+ console.log(anime.title.romaji);
416
+ }
417
+
418
+ // Limit to 3 pages max
419
+ for await (const anime of client.paginate(
420
+ (page) => client.getTrending(MediaType.ANIME, page, 20),
421
+ 3,
422
+ )) {
423
+ console.log(anime.title.romaji);
424
+ }
425
+ ```
426
+
141
427
  ## Error handling
142
428
 
143
429
  All API errors throw an `AniListError` with:
@@ -168,8 +454,21 @@ import type {
168
454
  Character,
169
455
  Staff,
170
456
  User,
457
+ AiringSchedule,
458
+ MediaListEntry,
459
+ Recommendation,
460
+ StudioDetail,
461
+ MediaEdge,
462
+ MediaConnection,
171
463
  PagedResult,
172
464
  SearchMediaOptions,
465
+ SearchStudioOptions,
466
+ GetAiringOptions,
467
+ GetRecentChaptersOptions,
468
+ GetPlanningOptions,
469
+ GetSeasonOptions,
470
+ GetUserMediaListOptions,
471
+ GetRecommendationsOptions,
173
472
  } from "ani-client";
174
473
  ```
175
474