ani-client 1.4.0 → 1.4.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 +28 -4
- package/dist/index.d.mts +50 -4
- package/dist/index.d.ts +50 -4
- package/dist/index.js +90 -11
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +90 -11
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -182,7 +182,7 @@ The second parameter of `getMedia()` lets you opt-in to additional data. By defa
|
|
|
182
182
|
|
|
183
183
|
| Option | Type | Default | Description |
|
|
184
184
|
| --- | --- | --- | --- |
|
|
185
|
-
| `characters` | `boolean \| { perPage?, sort? }` | — | Characters with their roles (MAIN, SUPPORTING, BACKGROUND) |
|
|
185
|
+
| `characters` | `boolean \| { perPage?, sort?, voiceActors? }` | — | Characters with their roles (MAIN, SUPPORTING, BACKGROUND). Set `voiceActors: true` to include VA data. |
|
|
186
186
|
| `staff` | `boolean \| { perPage?, sort? }` | — | Staff members with their roles |
|
|
187
187
|
| `relations` | `boolean` | `true` | Sequels, prequels, adaptations, etc. Set `false` to exclude |
|
|
188
188
|
| `streamingEpisodes` | `boolean` | — | Streaming links (Crunchyroll, Funimation, etc.) |
|
|
@@ -202,6 +202,17 @@ const anime = await client.getMedia(1, {
|
|
|
202
202
|
characters: { perPage: 50, sort: false },
|
|
203
203
|
});
|
|
204
204
|
|
|
205
|
+
// Include voice actors alongside characters
|
|
206
|
+
const anime = await client.getMedia(1, {
|
|
207
|
+
characters: { voiceActors: true },
|
|
208
|
+
});
|
|
209
|
+
anime.characters?.edges.forEach((e) => {
|
|
210
|
+
console.log(e.node.name.full);
|
|
211
|
+
e.voiceActors?.forEach((va) =>
|
|
212
|
+
console.log(` VA: ${va.name.full} (${va.languageV2})`)
|
|
213
|
+
);
|
|
214
|
+
});
|
|
215
|
+
|
|
205
216
|
// Staff members
|
|
206
217
|
const anime = await client.getMedia(1, { staff: true });
|
|
207
218
|
anime.staff?.edges.forEach((e) =>
|
|
@@ -230,12 +241,24 @@ const anime = await client.getMedia(1, {
|
|
|
230
241
|
|
|
231
242
|
| Method | Description |
|
|
232
243
|
| --- | --- |
|
|
233
|
-
| `getCharacter(id)` | Fetch a character by ID |
|
|
234
|
-
| `searchCharacters(options?)` | Search characters by name |
|
|
244
|
+
| `getCharacter(id, include?)` | Fetch a character by ID, optionally with voice actors |
|
|
245
|
+
| `searchCharacters(options?)` | Search characters by name, optionally with voice actors |
|
|
235
246
|
|
|
236
247
|
```ts
|
|
237
248
|
const spike = await client.getCharacter(1);
|
|
238
249
|
const results = await client.searchCharacters({ query: "Luffy", perPage: 5 });
|
|
250
|
+
|
|
251
|
+
// With voice actors
|
|
252
|
+
const spike = await client.getCharacter(1, { voiceActors: true });
|
|
253
|
+
spike.media?.edges?.forEach((e) => {
|
|
254
|
+
console.log(e.node.title.romaji);
|
|
255
|
+
e.voiceActors?.forEach((va) =>
|
|
256
|
+
console.log(` VA: ${va.name.full} (${va.languageV2})`)
|
|
257
|
+
);
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
// Search with voice actors
|
|
261
|
+
const result = await client.searchCharacters({ query: "Luffy", voiceActors: true });
|
|
239
262
|
```
|
|
240
263
|
|
|
241
264
|
### Staff
|
|
@@ -538,9 +561,10 @@ All types and enums are exported:
|
|
|
538
561
|
|
|
539
562
|
```ts
|
|
540
563
|
import type {
|
|
541
|
-
Media, Character, Staff, User,
|
|
564
|
+
Media, Character, Staff, User, VoiceActor,
|
|
542
565
|
AiringSchedule, MediaListEntry, Recommendation, StudioDetail,
|
|
543
566
|
MediaEdge, MediaConnection, MediaCharacterEdge, MediaCharacterConnection,
|
|
567
|
+
CharacterMediaEdge, CharacterIncludeOptions,
|
|
544
568
|
MediaStaffEdge, MediaStaffConnection, MediaIncludeOptions,
|
|
545
569
|
StreamingEpisode, ExternalLink, MediaStats, MediaRecommendationNode,
|
|
546
570
|
PageInfo, PagedResult,
|
package/dist/index.d.mts
CHANGED
|
@@ -159,9 +159,27 @@ interface CharacterImage {
|
|
|
159
159
|
large: string | null;
|
|
160
160
|
medium: string | null;
|
|
161
161
|
}
|
|
162
|
+
/** Compact voice actor data returned inside character edges. */
|
|
163
|
+
interface VoiceActor {
|
|
164
|
+
id: number;
|
|
165
|
+
name: {
|
|
166
|
+
first: string | null;
|
|
167
|
+
middle: string | null;
|
|
168
|
+
last: string | null;
|
|
169
|
+
full: string | null;
|
|
170
|
+
native: string | null;
|
|
171
|
+
userPreferred: string | null;
|
|
172
|
+
};
|
|
173
|
+
languageV2: string | null;
|
|
174
|
+
image: StaffImage;
|
|
175
|
+
gender: string | null;
|
|
176
|
+
primaryOccupations: string[];
|
|
177
|
+
siteUrl: string | null;
|
|
178
|
+
}
|
|
162
179
|
interface MediaCharacterEdge {
|
|
163
180
|
role: CharacterRole;
|
|
164
181
|
node: Omit<Character, "media">;
|
|
182
|
+
voiceActors?: VoiceActor[];
|
|
165
183
|
}
|
|
166
184
|
interface MediaCharacterConnection {
|
|
167
185
|
edges: MediaCharacterEdge[];
|
|
@@ -248,6 +266,11 @@ interface Media {
|
|
|
248
266
|
isAdult: boolean | null;
|
|
249
267
|
siteUrl: string | null;
|
|
250
268
|
}
|
|
269
|
+
type CharacterMediaNode = Pick<Media, "id" | "title" | "type" | "coverImage" | "siteUrl">;
|
|
270
|
+
interface CharacterMediaEdge {
|
|
271
|
+
node: CharacterMediaNode;
|
|
272
|
+
voiceActors?: VoiceActor[];
|
|
273
|
+
}
|
|
251
274
|
interface Character {
|
|
252
275
|
id: number;
|
|
253
276
|
name: CharacterName;
|
|
@@ -260,9 +283,15 @@ interface Character {
|
|
|
260
283
|
favourites: number | null;
|
|
261
284
|
siteUrl: string | null;
|
|
262
285
|
media: {
|
|
263
|
-
nodes
|
|
286
|
+
nodes?: CharacterMediaNode[];
|
|
287
|
+
edges?: CharacterMediaEdge[];
|
|
264
288
|
} | null;
|
|
265
289
|
}
|
|
290
|
+
/** Options for including extra data when fetching a character. */
|
|
291
|
+
interface CharacterIncludeOptions {
|
|
292
|
+
/** Include voice actors for each media the character appears in. */
|
|
293
|
+
voiceActors?: boolean;
|
|
294
|
+
}
|
|
266
295
|
interface StaffName {
|
|
267
296
|
first: string | null;
|
|
268
297
|
middle: string | null;
|
|
@@ -354,6 +383,8 @@ interface SearchCharacterOptions {
|
|
|
354
383
|
sort?: CharacterSort[];
|
|
355
384
|
page?: number;
|
|
356
385
|
perPage?: number;
|
|
386
|
+
/** Include voice actors for each media the character appears in. */
|
|
387
|
+
voiceActors?: boolean;
|
|
357
388
|
}
|
|
358
389
|
interface SearchStaffOptions {
|
|
359
390
|
query?: string;
|
|
@@ -523,6 +554,7 @@ interface MediaIncludeOptions {
|
|
|
523
554
|
characters?: boolean | {
|
|
524
555
|
perPage?: number;
|
|
525
556
|
sort?: boolean;
|
|
557
|
+
voiceActors?: boolean;
|
|
526
558
|
};
|
|
527
559
|
/** Include staff members with their roles.
|
|
528
560
|
* `true` = 25 results sorted by relevance. Object form to customize. */
|
|
@@ -676,6 +708,9 @@ declare class AniListClient {
|
|
|
676
708
|
* // Include characters sorted by role, 25 results
|
|
677
709
|
* const anime = await client.getMedia(1, { characters: true });
|
|
678
710
|
*
|
|
711
|
+
* // Include characters with voice actors
|
|
712
|
+
* const anime = await client.getMedia(1, { characters: { voiceActors: true } });
|
|
713
|
+
*
|
|
679
714
|
* // Full control
|
|
680
715
|
* const anime = await client.getMedia(1, {
|
|
681
716
|
* characters: { perPage: 50, sort: true },
|
|
@@ -720,24 +755,35 @@ declare class AniListClient {
|
|
|
720
755
|
* Fetch a character by AniList ID.
|
|
721
756
|
*
|
|
722
757
|
* @param id - The AniList character ID
|
|
758
|
+
* @param include - Optional include options (e.g. voice actors)
|
|
723
759
|
* @returns The character object
|
|
724
760
|
*
|
|
725
761
|
* @example
|
|
726
762
|
* ```ts
|
|
727
763
|
* const spike = await client.getCharacter(1);
|
|
728
764
|
* console.log(spike.name.full); // "Spike Spiegel"
|
|
765
|
+
*
|
|
766
|
+
* // With voice actors
|
|
767
|
+
* const spike = await client.getCharacter(1, { voiceActors: true });
|
|
768
|
+
* spike.media?.edges?.forEach((e) => {
|
|
769
|
+
* console.log(e.node.title.romaji);
|
|
770
|
+
* e.voiceActors?.forEach((va) => console.log(` VA: ${va.name.full}`));
|
|
771
|
+
* });
|
|
729
772
|
* ```
|
|
730
773
|
*/
|
|
731
|
-
getCharacter(id: number): Promise<Character>;
|
|
774
|
+
getCharacter(id: number, include?: CharacterIncludeOptions): Promise<Character>;
|
|
732
775
|
/**
|
|
733
776
|
* Search for characters by name.
|
|
734
777
|
*
|
|
735
|
-
* @param options - Search / pagination parameters
|
|
778
|
+
* @param options - Search / pagination parameters (includes optional `voiceActors`)
|
|
736
779
|
* @returns Paginated results with matching characters
|
|
737
780
|
*
|
|
738
781
|
* @example
|
|
739
782
|
* ```ts
|
|
740
783
|
* const result = await client.searchCharacters({ query: "Luffy", perPage: 5 });
|
|
784
|
+
*
|
|
785
|
+
* // With voice actors
|
|
786
|
+
* const result = await client.searchCharacters({ query: "Luffy", voiceActors: true });
|
|
741
787
|
* ```
|
|
742
788
|
*/
|
|
743
789
|
searchCharacters(options?: SearchCharacterOptions): Promise<PagedResult<Character>>;
|
|
@@ -1161,4 +1207,4 @@ declare class RateLimiter {
|
|
|
1161
1207
|
private sleep;
|
|
1162
1208
|
}
|
|
1163
1209
|
|
|
1164
|
-
export { type AiringSchedule, AiringSort, AniListClient, type AniListClientOptions, AniListError, type AniListHooks, type CacheAdapter, type CacheOptions, type Character, type CharacterImage, type CharacterName, CharacterRole, CharacterSort, 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, type MediaStaffConnection, type MediaStaffEdge, type MediaStats, MediaStatus, type MediaTag, type MediaTitle, type MediaTrailer, MediaType, MemoryCache, 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 Staff, type StaffImage, type StaffName, type StatusDistribution, type StreamingEpisode, type Studio, type StudioConnection, type StudioDetail, type User, type UserAvatar, type UserStatistics };
|
|
1210
|
+
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 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, type MediaStaffConnection, type MediaStaffEdge, type MediaStats, MediaStatus, type MediaTag, type MediaTitle, type MediaTrailer, MediaType, MemoryCache, 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 Staff, type StaffImage, type StaffName, type StatusDistribution, type StreamingEpisode, type Studio, type StudioConnection, type StudioDetail, type User, type UserAvatar, type UserStatistics, type VoiceActor };
|
package/dist/index.d.ts
CHANGED
|
@@ -159,9 +159,27 @@ interface CharacterImage {
|
|
|
159
159
|
large: string | null;
|
|
160
160
|
medium: string | null;
|
|
161
161
|
}
|
|
162
|
+
/** Compact voice actor data returned inside character edges. */
|
|
163
|
+
interface VoiceActor {
|
|
164
|
+
id: number;
|
|
165
|
+
name: {
|
|
166
|
+
first: string | null;
|
|
167
|
+
middle: string | null;
|
|
168
|
+
last: string | null;
|
|
169
|
+
full: string | null;
|
|
170
|
+
native: string | null;
|
|
171
|
+
userPreferred: string | null;
|
|
172
|
+
};
|
|
173
|
+
languageV2: string | null;
|
|
174
|
+
image: StaffImage;
|
|
175
|
+
gender: string | null;
|
|
176
|
+
primaryOccupations: string[];
|
|
177
|
+
siteUrl: string | null;
|
|
178
|
+
}
|
|
162
179
|
interface MediaCharacterEdge {
|
|
163
180
|
role: CharacterRole;
|
|
164
181
|
node: Omit<Character, "media">;
|
|
182
|
+
voiceActors?: VoiceActor[];
|
|
165
183
|
}
|
|
166
184
|
interface MediaCharacterConnection {
|
|
167
185
|
edges: MediaCharacterEdge[];
|
|
@@ -248,6 +266,11 @@ interface Media {
|
|
|
248
266
|
isAdult: boolean | null;
|
|
249
267
|
siteUrl: string | null;
|
|
250
268
|
}
|
|
269
|
+
type CharacterMediaNode = Pick<Media, "id" | "title" | "type" | "coverImage" | "siteUrl">;
|
|
270
|
+
interface CharacterMediaEdge {
|
|
271
|
+
node: CharacterMediaNode;
|
|
272
|
+
voiceActors?: VoiceActor[];
|
|
273
|
+
}
|
|
251
274
|
interface Character {
|
|
252
275
|
id: number;
|
|
253
276
|
name: CharacterName;
|
|
@@ -260,9 +283,15 @@ interface Character {
|
|
|
260
283
|
favourites: number | null;
|
|
261
284
|
siteUrl: string | null;
|
|
262
285
|
media: {
|
|
263
|
-
nodes
|
|
286
|
+
nodes?: CharacterMediaNode[];
|
|
287
|
+
edges?: CharacterMediaEdge[];
|
|
264
288
|
} | null;
|
|
265
289
|
}
|
|
290
|
+
/** Options for including extra data when fetching a character. */
|
|
291
|
+
interface CharacterIncludeOptions {
|
|
292
|
+
/** Include voice actors for each media the character appears in. */
|
|
293
|
+
voiceActors?: boolean;
|
|
294
|
+
}
|
|
266
295
|
interface StaffName {
|
|
267
296
|
first: string | null;
|
|
268
297
|
middle: string | null;
|
|
@@ -354,6 +383,8 @@ interface SearchCharacterOptions {
|
|
|
354
383
|
sort?: CharacterSort[];
|
|
355
384
|
page?: number;
|
|
356
385
|
perPage?: number;
|
|
386
|
+
/** Include voice actors for each media the character appears in. */
|
|
387
|
+
voiceActors?: boolean;
|
|
357
388
|
}
|
|
358
389
|
interface SearchStaffOptions {
|
|
359
390
|
query?: string;
|
|
@@ -523,6 +554,7 @@ interface MediaIncludeOptions {
|
|
|
523
554
|
characters?: boolean | {
|
|
524
555
|
perPage?: number;
|
|
525
556
|
sort?: boolean;
|
|
557
|
+
voiceActors?: boolean;
|
|
526
558
|
};
|
|
527
559
|
/** Include staff members with their roles.
|
|
528
560
|
* `true` = 25 results sorted by relevance. Object form to customize. */
|
|
@@ -676,6 +708,9 @@ declare class AniListClient {
|
|
|
676
708
|
* // Include characters sorted by role, 25 results
|
|
677
709
|
* const anime = await client.getMedia(1, { characters: true });
|
|
678
710
|
*
|
|
711
|
+
* // Include characters with voice actors
|
|
712
|
+
* const anime = await client.getMedia(1, { characters: { voiceActors: true } });
|
|
713
|
+
*
|
|
679
714
|
* // Full control
|
|
680
715
|
* const anime = await client.getMedia(1, {
|
|
681
716
|
* characters: { perPage: 50, sort: true },
|
|
@@ -720,24 +755,35 @@ declare class AniListClient {
|
|
|
720
755
|
* Fetch a character by AniList ID.
|
|
721
756
|
*
|
|
722
757
|
* @param id - The AniList character ID
|
|
758
|
+
* @param include - Optional include options (e.g. voice actors)
|
|
723
759
|
* @returns The character object
|
|
724
760
|
*
|
|
725
761
|
* @example
|
|
726
762
|
* ```ts
|
|
727
763
|
* const spike = await client.getCharacter(1);
|
|
728
764
|
* console.log(spike.name.full); // "Spike Spiegel"
|
|
765
|
+
*
|
|
766
|
+
* // With voice actors
|
|
767
|
+
* const spike = await client.getCharacter(1, { voiceActors: true });
|
|
768
|
+
* spike.media?.edges?.forEach((e) => {
|
|
769
|
+
* console.log(e.node.title.romaji);
|
|
770
|
+
* e.voiceActors?.forEach((va) => console.log(` VA: ${va.name.full}`));
|
|
771
|
+
* });
|
|
729
772
|
* ```
|
|
730
773
|
*/
|
|
731
|
-
getCharacter(id: number): Promise<Character>;
|
|
774
|
+
getCharacter(id: number, include?: CharacterIncludeOptions): Promise<Character>;
|
|
732
775
|
/**
|
|
733
776
|
* Search for characters by name.
|
|
734
777
|
*
|
|
735
|
-
* @param options - Search / pagination parameters
|
|
778
|
+
* @param options - Search / pagination parameters (includes optional `voiceActors`)
|
|
736
779
|
* @returns Paginated results with matching characters
|
|
737
780
|
*
|
|
738
781
|
* @example
|
|
739
782
|
* ```ts
|
|
740
783
|
* const result = await client.searchCharacters({ query: "Luffy", perPage: 5 });
|
|
784
|
+
*
|
|
785
|
+
* // With voice actors
|
|
786
|
+
* const result = await client.searchCharacters({ query: "Luffy", voiceActors: true });
|
|
741
787
|
* ```
|
|
742
788
|
*/
|
|
743
789
|
searchCharacters(options?: SearchCharacterOptions): Promise<PagedResult<Character>>;
|
|
@@ -1161,4 +1207,4 @@ declare class RateLimiter {
|
|
|
1161
1207
|
private sleep;
|
|
1162
1208
|
}
|
|
1163
1209
|
|
|
1164
|
-
export { type AiringSchedule, AiringSort, AniListClient, type AniListClientOptions, AniListError, type AniListHooks, type CacheAdapter, type CacheOptions, type Character, type CharacterImage, type CharacterName, CharacterRole, CharacterSort, 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, type MediaStaffConnection, type MediaStaffEdge, type MediaStats, MediaStatus, type MediaTag, type MediaTitle, type MediaTrailer, MediaType, MemoryCache, 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 Staff, type StaffImage, type StaffName, type StatusDistribution, type StreamingEpisode, type Studio, type StudioConnection, type StudioDetail, type User, type UserAvatar, type UserStatistics };
|
|
1210
|
+
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 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, type MediaStaffConnection, type MediaStaffEdge, type MediaStats, MediaStatus, type MediaTag, type MediaTitle, type MediaTrailer, MediaType, MemoryCache, 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 Staff, type StaffImage, type StaffName, type StatusDistribution, type StreamingEpisode, type Studio, type StudioConnection, type StudioDetail, type User, type UserAvatar, type UserStatistics, type VoiceActor };
|
package/dist/index.js
CHANGED
|
@@ -68,8 +68,7 @@ var CHARACTER_FIELDS_COMPACT = `
|
|
|
68
68
|
favourites
|
|
69
69
|
siteUrl
|
|
70
70
|
`;
|
|
71
|
-
var
|
|
72
|
-
${CHARACTER_FIELDS_COMPACT}
|
|
71
|
+
var CHARACTER_MEDIA_NODES = `
|
|
73
72
|
media(perPage: 10) {
|
|
74
73
|
nodes {
|
|
75
74
|
id
|
|
@@ -80,6 +79,39 @@ var CHARACTER_FIELDS = `
|
|
|
80
79
|
}
|
|
81
80
|
}
|
|
82
81
|
`;
|
|
82
|
+
var VOICE_ACTOR_FIELDS_COMPACT = `
|
|
83
|
+
id
|
|
84
|
+
name { first middle last full native userPreferred }
|
|
85
|
+
languageV2
|
|
86
|
+
image { large medium }
|
|
87
|
+
gender
|
|
88
|
+
primaryOccupations
|
|
89
|
+
siteUrl
|
|
90
|
+
`;
|
|
91
|
+
var CHARACTER_MEDIA_EDGES_WITH_VA = `
|
|
92
|
+
media(perPage: 10) {
|
|
93
|
+
edges {
|
|
94
|
+
voiceActors {
|
|
95
|
+
${VOICE_ACTOR_FIELDS_COMPACT}
|
|
96
|
+
}
|
|
97
|
+
node {
|
|
98
|
+
id
|
|
99
|
+
title { romaji english native userPreferred }
|
|
100
|
+
type
|
|
101
|
+
coverImage { large medium }
|
|
102
|
+
siteUrl
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
`;
|
|
107
|
+
var CHARACTER_FIELDS = `
|
|
108
|
+
${CHARACTER_FIELDS_COMPACT}
|
|
109
|
+
${CHARACTER_MEDIA_NODES}
|
|
110
|
+
`;
|
|
111
|
+
var CHARACTER_FIELDS_WITH_VA = `
|
|
112
|
+
${CHARACTER_FIELDS_COMPACT}
|
|
113
|
+
${CHARACTER_MEDIA_EDGES_WITH_VA}
|
|
114
|
+
`;
|
|
83
115
|
var STAFF_FIELDS = `
|
|
84
116
|
id
|
|
85
117
|
name { first middle last full native }
|
|
@@ -168,6 +200,12 @@ query ($id: Int!) {
|
|
|
168
200
|
${CHARACTER_FIELDS}
|
|
169
201
|
}
|
|
170
202
|
}`;
|
|
203
|
+
var QUERY_CHARACTER_BY_ID_WITH_VA = `
|
|
204
|
+
query ($id: Int!) {
|
|
205
|
+
Character(id: $id) {
|
|
206
|
+
${CHARACTER_FIELDS_WITH_VA}
|
|
207
|
+
}
|
|
208
|
+
}`;
|
|
171
209
|
var QUERY_CHARACTER_SEARCH = `
|
|
172
210
|
query ($search: String, $sort: [CharacterSort], $page: Int, $perPage: Int) {
|
|
173
211
|
Page(page: $page, perPage: $perPage) {
|
|
@@ -177,6 +215,15 @@ query ($search: String, $sort: [CharacterSort], $page: Int, $perPage: Int) {
|
|
|
177
215
|
}
|
|
178
216
|
}
|
|
179
217
|
}`;
|
|
218
|
+
var QUERY_CHARACTER_SEARCH_WITH_VA = `
|
|
219
|
+
query ($search: String, $sort: [CharacterSort], $page: Int, $perPage: Int) {
|
|
220
|
+
Page(page: $page, perPage: $perPage) {
|
|
221
|
+
pageInfo { total perPage currentPage lastPage hasNextPage }
|
|
222
|
+
characters(search: $search, sort: $sort) {
|
|
223
|
+
${CHARACTER_FIELDS_WITH_VA}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}`;
|
|
180
227
|
var QUERY_STAFF_BY_ID = `
|
|
181
228
|
query ($id: Int!) {
|
|
182
229
|
Staff(id: $id) {
|
|
@@ -184,7 +231,7 @@ query ($id: Int!) {
|
|
|
184
231
|
}
|
|
185
232
|
}`;
|
|
186
233
|
var QUERY_STAFF_SEARCH = `
|
|
187
|
-
query ($search: String, $sort: [
|
|
234
|
+
query ($search: String, $sort: [StaffSort], $page: Int, $perPage: Int) {
|
|
188
235
|
Page(page: $page, perPage: $perPage) {
|
|
189
236
|
pageInfo { total perPage currentPage lastPage hasNextPage }
|
|
190
237
|
staff(search: $search, sort: $sort) {
|
|
@@ -366,13 +413,17 @@ function buildMediaByIdQuery(include) {
|
|
|
366
413
|
const opts = typeof include.characters === "object" ? include.characters : {};
|
|
367
414
|
const perPage = opts.perPage ?? 25;
|
|
368
415
|
const sortClause = opts.sort !== false ? ", sort: [ROLE, RELEVANCE, ID]" : "";
|
|
416
|
+
const voiceActorBlock = opts.voiceActors ? `
|
|
417
|
+
voiceActors {
|
|
418
|
+
${VOICE_ACTOR_FIELDS_COMPACT}
|
|
419
|
+
}` : "";
|
|
369
420
|
extra.push(`
|
|
370
421
|
characters(perPage: ${perPage}${sortClause}) {
|
|
371
422
|
edges {
|
|
372
423
|
role
|
|
373
424
|
node {
|
|
374
425
|
${CHARACTER_FIELDS_COMPACT}
|
|
375
|
-
}
|
|
426
|
+
}${voiceActorBlock}
|
|
376
427
|
}
|
|
377
428
|
}`);
|
|
378
429
|
}
|
|
@@ -892,6 +943,9 @@ var AniListClient = class {
|
|
|
892
943
|
* // Include characters sorted by role, 25 results
|
|
893
944
|
* const anime = await client.getMedia(1, { characters: true });
|
|
894
945
|
*
|
|
946
|
+
* // Include characters with voice actors
|
|
947
|
+
* const anime = await client.getMedia(1, { characters: { voiceActors: true } });
|
|
948
|
+
*
|
|
895
949
|
* // Full control
|
|
896
950
|
* const anime = await client.getMedia(1, {
|
|
897
951
|
* characters: { perPage: 50, sort: true },
|
|
@@ -929,7 +983,11 @@ var AniListClient = class {
|
|
|
929
983
|
*/
|
|
930
984
|
async searchMedia(options = {}) {
|
|
931
985
|
const { query: search, page = 1, perPage = 20, ...filters } = options;
|
|
932
|
-
return this.pagedRequest(
|
|
986
|
+
return this.pagedRequest(
|
|
987
|
+
QUERY_MEDIA_SEARCH,
|
|
988
|
+
{ search, ...filters, page, perPage: this.clampPerPage(perPage) },
|
|
989
|
+
"media"
|
|
990
|
+
);
|
|
933
991
|
}
|
|
934
992
|
/**
|
|
935
993
|
* Get currently trending anime or manga.
|
|
@@ -945,32 +1003,49 @@ var AniListClient = class {
|
|
|
945
1003
|
* Fetch a character by AniList ID.
|
|
946
1004
|
*
|
|
947
1005
|
* @param id - The AniList character ID
|
|
1006
|
+
* @param include - Optional include options (e.g. voice actors)
|
|
948
1007
|
* @returns The character object
|
|
949
1008
|
*
|
|
950
1009
|
* @example
|
|
951
1010
|
* ```ts
|
|
952
1011
|
* const spike = await client.getCharacter(1);
|
|
953
1012
|
* console.log(spike.name.full); // "Spike Spiegel"
|
|
1013
|
+
*
|
|
1014
|
+
* // With voice actors
|
|
1015
|
+
* const spike = await client.getCharacter(1, { voiceActors: true });
|
|
1016
|
+
* spike.media?.edges?.forEach((e) => {
|
|
1017
|
+
* console.log(e.node.title.romaji);
|
|
1018
|
+
* e.voiceActors?.forEach((va) => console.log(` VA: ${va.name.full}`));
|
|
1019
|
+
* });
|
|
954
1020
|
* ```
|
|
955
1021
|
*/
|
|
956
|
-
async getCharacter(id) {
|
|
957
|
-
const
|
|
1022
|
+
async getCharacter(id, include) {
|
|
1023
|
+
const query = include?.voiceActors ? QUERY_CHARACTER_BY_ID_WITH_VA : QUERY_CHARACTER_BY_ID;
|
|
1024
|
+
const data = await this.request(query, { id });
|
|
958
1025
|
return data.Character;
|
|
959
1026
|
}
|
|
960
1027
|
/**
|
|
961
1028
|
* Search for characters by name.
|
|
962
1029
|
*
|
|
963
|
-
* @param options - Search / pagination parameters
|
|
1030
|
+
* @param options - Search / pagination parameters (includes optional `voiceActors`)
|
|
964
1031
|
* @returns Paginated results with matching characters
|
|
965
1032
|
*
|
|
966
1033
|
* @example
|
|
967
1034
|
* ```ts
|
|
968
1035
|
* const result = await client.searchCharacters({ query: "Luffy", perPage: 5 });
|
|
1036
|
+
*
|
|
1037
|
+
* // With voice actors
|
|
1038
|
+
* const result = await client.searchCharacters({ query: "Luffy", voiceActors: true });
|
|
969
1039
|
* ```
|
|
970
1040
|
*/
|
|
971
1041
|
async searchCharacters(options = {}) {
|
|
972
|
-
const { query: search, page = 1, perPage = 20, ...rest } = options;
|
|
973
|
-
|
|
1042
|
+
const { query: search, page = 1, perPage = 20, voiceActors, ...rest } = options;
|
|
1043
|
+
const gqlQuery = voiceActors ? QUERY_CHARACTER_SEARCH_WITH_VA : QUERY_CHARACTER_SEARCH;
|
|
1044
|
+
return this.pagedRequest(
|
|
1045
|
+
gqlQuery,
|
|
1046
|
+
{ search, ...rest, page, perPage: this.clampPerPage(perPage) },
|
|
1047
|
+
"characters"
|
|
1048
|
+
);
|
|
974
1049
|
}
|
|
975
1050
|
/**
|
|
976
1051
|
* Fetch a staff member by AniList ID.
|
|
@@ -1001,7 +1076,11 @@ var AniListClient = class {
|
|
|
1001
1076
|
*/
|
|
1002
1077
|
async searchStaff(options = {}) {
|
|
1003
1078
|
const { query: search, page = 1, perPage = 20, sort } = options;
|
|
1004
|
-
return this.pagedRequest(
|
|
1079
|
+
return this.pagedRequest(
|
|
1080
|
+
QUERY_STAFF_SEARCH,
|
|
1081
|
+
{ search, sort, page, perPage: this.clampPerPage(perPage) },
|
|
1082
|
+
"staff"
|
|
1083
|
+
);
|
|
1005
1084
|
}
|
|
1006
1085
|
/**
|
|
1007
1086
|
* Fetch a user by AniList ID.
|