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 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: Pick<Media, "id" | "title" | "type" | "coverImage" | "siteUrl">[];
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: Pick<Media, "id" | "title" | "type" | "coverImage" | "siteUrl">[];
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 CHARACTER_FIELDS = `
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: [CharacterSort], $page: Int, $perPage: Int) {
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(QUERY_MEDIA_SEARCH, { search, ...filters, page, perPage: this.clampPerPage(perPage) }, "media");
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 data = await this.request(QUERY_CHARACTER_BY_ID, { id });
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
- return this.pagedRequest(QUERY_CHARACTER_SEARCH, { search, ...rest, page, perPage: this.clampPerPage(perPage) }, "characters");
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(QUERY_STAFF_SEARCH, { search, sort, page, perPage: this.clampPerPage(perPage) }, "staff");
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.