ani-client 1.4.0 → 1.4.2

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.mjs CHANGED
@@ -66,8 +66,7 @@ var CHARACTER_FIELDS_COMPACT = `
66
66
  favourites
67
67
  siteUrl
68
68
  `;
69
- var CHARACTER_FIELDS = `
70
- ${CHARACTER_FIELDS_COMPACT}
69
+ var CHARACTER_MEDIA_NODES = `
71
70
  media(perPage: 10) {
72
71
  nodes {
73
72
  id
@@ -78,6 +77,39 @@ var CHARACTER_FIELDS = `
78
77
  }
79
78
  }
80
79
  `;
80
+ var VOICE_ACTOR_FIELDS_COMPACT = `
81
+ id
82
+ name { first middle last full native userPreferred }
83
+ languageV2
84
+ image { large medium }
85
+ gender
86
+ primaryOccupations
87
+ siteUrl
88
+ `;
89
+ var CHARACTER_MEDIA_EDGES_WITH_VA = `
90
+ media(perPage: 10) {
91
+ edges {
92
+ voiceActors {
93
+ ${VOICE_ACTOR_FIELDS_COMPACT}
94
+ }
95
+ node {
96
+ id
97
+ title { romaji english native userPreferred }
98
+ type
99
+ coverImage { large medium }
100
+ siteUrl
101
+ }
102
+ }
103
+ }
104
+ `;
105
+ var CHARACTER_FIELDS = `
106
+ ${CHARACTER_FIELDS_COMPACT}
107
+ ${CHARACTER_MEDIA_NODES}
108
+ `;
109
+ var CHARACTER_FIELDS_WITH_VA = `
110
+ ${CHARACTER_FIELDS_COMPACT}
111
+ ${CHARACTER_MEDIA_EDGES_WITH_VA}
112
+ `;
81
113
  var STAFF_FIELDS = `
82
114
  id
83
115
  name { first middle last full native }
@@ -95,6 +127,46 @@ var STAFF_FIELDS = `
95
127
  favourites
96
128
  siteUrl
97
129
  `;
130
+ var STAFF_MEDIA_FIELDS = `
131
+ staffMedia(perPage: $perPage, sort: [POPULARITY_DESC]) {
132
+ nodes {
133
+ id
134
+ title { romaji english native userPreferred }
135
+ type
136
+ format
137
+ status
138
+ coverImage { extraLarge large medium color }
139
+ bannerImage
140
+ genres
141
+ averageScore
142
+ meanScore
143
+ popularity
144
+ favourites
145
+ episodes
146
+ trending
147
+ hashtag
148
+ season
149
+ seasonYear
150
+ startDate { year month day }
151
+ endDate { year month day }
152
+ nextAiringEpisode {
153
+ id
154
+ airingAt
155
+ episode
156
+ mediaId
157
+ timeUntilAiring
158
+ }
159
+ studios {
160
+ edges {
161
+ node {
162
+ name
163
+ }
164
+ }
165
+ }
166
+ siteUrl
167
+ }
168
+ }
169
+ `;
98
170
  var USER_FIELDS = `
99
171
  id
100
172
  name
@@ -166,6 +238,12 @@ query ($id: Int!) {
166
238
  ${CHARACTER_FIELDS}
167
239
  }
168
240
  }`;
241
+ var QUERY_CHARACTER_BY_ID_WITH_VA = `
242
+ query ($id: Int!) {
243
+ Character(id: $id) {
244
+ ${CHARACTER_FIELDS_WITH_VA}
245
+ }
246
+ }`;
169
247
  var QUERY_CHARACTER_SEARCH = `
170
248
  query ($search: String, $sort: [CharacterSort], $page: Int, $perPage: Int) {
171
249
  Page(page: $page, perPage: $perPage) {
@@ -175,14 +253,30 @@ query ($search: String, $sort: [CharacterSort], $page: Int, $perPage: Int) {
175
253
  }
176
254
  }
177
255
  }`;
256
+ var QUERY_CHARACTER_SEARCH_WITH_VA = `
257
+ query ($search: String, $sort: [CharacterSort], $page: Int, $perPage: Int) {
258
+ Page(page: $page, perPage: $perPage) {
259
+ pageInfo { total perPage currentPage lastPage hasNextPage }
260
+ characters(search: $search, sort: $sort) {
261
+ ${CHARACTER_FIELDS_WITH_VA}
262
+ }
263
+ }
264
+ }`;
178
265
  var QUERY_STAFF_BY_ID = `
179
266
  query ($id: Int!) {
180
267
  Staff(id: $id) {
181
268
  ${STAFF_FIELDS}
182
269
  }
183
270
  }`;
271
+ var QUERY_STAFF_BY_ID_WITH_MEDIA = `
272
+ query ($id: Int!, $perPage: Int) {
273
+ Staff(id: $id) {
274
+ ${STAFF_FIELDS}
275
+ ${STAFF_MEDIA_FIELDS}
276
+ }
277
+ }`;
184
278
  var QUERY_STAFF_SEARCH = `
185
- query ($search: String, $sort: [CharacterSort], $page: Int, $perPage: Int) {
279
+ query ($search: String, $sort: [StaffSort], $page: Int, $perPage: Int) {
186
280
  Page(page: $page, perPage: $perPage) {
187
281
  pageInfo { total perPage currentPage lastPage hasNextPage }
188
282
  staff(search: $search, sort: $sort) {
@@ -364,13 +458,17 @@ function buildMediaByIdQuery(include) {
364
458
  const opts = typeof include.characters === "object" ? include.characters : {};
365
459
  const perPage = opts.perPage ?? 25;
366
460
  const sortClause = opts.sort !== false ? ", sort: [ROLE, RELEVANCE, ID]" : "";
461
+ const voiceActorBlock = opts.voiceActors ? `
462
+ voiceActors {
463
+ ${VOICE_ACTOR_FIELDS_COMPACT}
464
+ }` : "";
367
465
  extra.push(`
368
466
  characters(perPage: ${perPage}${sortClause}) {
369
467
  edges {
370
468
  role
371
469
  node {
372
470
  ${CHARACTER_FIELDS_COMPACT}
373
- }
471
+ }${voiceActorBlock}
374
472
  }
375
473
  }`);
376
474
  }
@@ -890,6 +988,9 @@ var AniListClient = class {
890
988
  * // Include characters sorted by role, 25 results
891
989
  * const anime = await client.getMedia(1, { characters: true });
892
990
  *
991
+ * // Include characters with voice actors
992
+ * const anime = await client.getMedia(1, { characters: { voiceActors: true } });
993
+ *
893
994
  * // Full control
894
995
  * const anime = await client.getMedia(1, {
895
996
  * characters: { perPage: 50, sort: true },
@@ -927,7 +1028,11 @@ var AniListClient = class {
927
1028
  */
928
1029
  async searchMedia(options = {}) {
929
1030
  const { query: search, page = 1, perPage = 20, ...filters } = options;
930
- return this.pagedRequest(QUERY_MEDIA_SEARCH, { search, ...filters, page, perPage: this.clampPerPage(perPage) }, "media");
1031
+ return this.pagedRequest(
1032
+ QUERY_MEDIA_SEARCH,
1033
+ { search, ...filters, page, perPage: this.clampPerPage(perPage) },
1034
+ "media"
1035
+ );
931
1036
  }
932
1037
  /**
933
1038
  * Get currently trending anime or manga.
@@ -943,46 +1048,74 @@ var AniListClient = class {
943
1048
  * Fetch a character by AniList ID.
944
1049
  *
945
1050
  * @param id - The AniList character ID
1051
+ * @param include - Optional include options (e.g. voice actors)
946
1052
  * @returns The character object
947
1053
  *
948
1054
  * @example
949
1055
  * ```ts
950
1056
  * const spike = await client.getCharacter(1);
951
1057
  * console.log(spike.name.full); // "Spike Spiegel"
1058
+ *
1059
+ * // With voice actors
1060
+ * const spike = await client.getCharacter(1, { voiceActors: true });
1061
+ * spike.media?.edges?.forEach((e) => {
1062
+ * console.log(e.node.title.romaji);
1063
+ * e.voiceActors?.forEach((va) => console.log(` VA: ${va.name.full}`));
1064
+ * });
952
1065
  * ```
953
1066
  */
954
- async getCharacter(id) {
955
- const data = await this.request(QUERY_CHARACTER_BY_ID, { id });
1067
+ async getCharacter(id, include) {
1068
+ const query = include?.voiceActors ? QUERY_CHARACTER_BY_ID_WITH_VA : QUERY_CHARACTER_BY_ID;
1069
+ const data = await this.request(query, { id });
956
1070
  return data.Character;
957
1071
  }
958
1072
  /**
959
1073
  * Search for characters by name.
960
1074
  *
961
- * @param options - Search / pagination parameters
1075
+ * @param options - Search / pagination parameters (includes optional `voiceActors`)
962
1076
  * @returns Paginated results with matching characters
963
1077
  *
964
1078
  * @example
965
1079
  * ```ts
966
1080
  * const result = await client.searchCharacters({ query: "Luffy", perPage: 5 });
1081
+ *
1082
+ * // With voice actors
1083
+ * const result = await client.searchCharacters({ query: "Luffy", voiceActors: true });
967
1084
  * ```
968
1085
  */
969
1086
  async searchCharacters(options = {}) {
970
- const { query: search, page = 1, perPage = 20, ...rest } = options;
971
- return this.pagedRequest(QUERY_CHARACTER_SEARCH, { search, ...rest, page, perPage: this.clampPerPage(perPage) }, "characters");
1087
+ const { query: search, page = 1, perPage = 20, voiceActors, ...rest } = options;
1088
+ const gqlQuery = voiceActors ? QUERY_CHARACTER_SEARCH_WITH_VA : QUERY_CHARACTER_SEARCH;
1089
+ return this.pagedRequest(
1090
+ gqlQuery,
1091
+ { search, ...rest, page, perPage: this.clampPerPage(perPage) },
1092
+ "characters"
1093
+ );
972
1094
  }
973
1095
  /**
974
1096
  * Fetch a staff member by AniList ID.
975
1097
  *
976
1098
  * @param id - The AniList staff ID
1099
+ * @param include - Optional include options to fetch related data (e.g. media)
977
1100
  * @returns The staff object
978
1101
  *
979
1102
  * @example
980
1103
  * ```ts
981
1104
  * const staff = await client.getStaff(95001);
982
1105
  * console.log(staff.name.full);
1106
+ *
1107
+ * // With media the staff worked on
1108
+ * const staff = await client.getStaff(95001, { media: true });
1109
+ * staff.staffMedia?.nodes.forEach((m) => console.log(m.title.romaji));
983
1110
  * ```
984
1111
  */
985
- async getStaff(id) {
1112
+ async getStaff(id, include) {
1113
+ if (include?.media) {
1114
+ const opts = typeof include.media === "object" ? include.media : {};
1115
+ const perPage = opts.perPage ?? 25;
1116
+ const data2 = await this.request(QUERY_STAFF_BY_ID_WITH_MEDIA, { id, perPage });
1117
+ return data2.Staff;
1118
+ }
986
1119
  const data = await this.request(QUERY_STAFF_BY_ID, { id });
987
1120
  return data.Staff;
988
1121
  }
@@ -999,7 +1132,11 @@ var AniListClient = class {
999
1132
  */
1000
1133
  async searchStaff(options = {}) {
1001
1134
  const { query: search, page = 1, perPage = 20, sort } = options;
1002
- return this.pagedRequest(QUERY_STAFF_SEARCH, { search, sort, page, perPage: this.clampPerPage(perPage) }, "staff");
1135
+ return this.pagedRequest(
1136
+ QUERY_STAFF_SEARCH,
1137
+ { search, sort, page, perPage: this.clampPerPage(perPage) },
1138
+ "staff"
1139
+ );
1003
1140
  }
1004
1141
  /**
1005
1142
  * Fetch a user by AniList ID.