tmdb-kit 1.1.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 +243 -79
- package/dist/cli.js +1068 -377
- package/dist/client.d.cts +13 -5
- package/dist/client.d.ts +13 -5
- package/dist/errors.d.cts +13 -1
- package/dist/errors.d.ts +13 -1
- package/dist/helpers/cache.d.cts +28 -0
- package/dist/helpers/cache.d.ts +28 -0
- package/dist/helpers/pagination.d.cts +35 -0
- package/dist/helpers/pagination.d.ts +35 -0
- package/dist/helpers/retry.d.cts +47 -0
- package/dist/helpers/retry.d.ts +47 -0
- package/dist/helpers/timeout.d.cts +20 -0
- package/dist/helpers/timeout.d.ts +20 -0
- package/dist/index.cjs +422 -54
- package/dist/index.cjs.map +18 -14
- package/dist/index.d.cts +7 -2
- package/dist/index.d.ts +7 -2
- package/dist/index.js +422 -54
- package/dist/index.js.map +18 -14
- package/dist/query.d.cts +14 -0
- package/dist/query.d.ts +14 -0
- package/dist/resources/configuration.d.cts +7 -7
- package/dist/resources/configuration.d.ts +7 -7
- package/dist/resources/movies.d.cts +3 -3
- package/dist/resources/movies.d.ts +3 -3
- package/dist/resources/tv.d.cts +9 -1
- package/dist/resources/tv.d.ts +9 -1
- package/dist/types.d.cts +100 -2
- package/dist/types.d.ts +100 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -13,6 +13,15 @@ class TMDBRequestError extends TMDBError {
|
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
class TMDBTimeoutError extends TMDBError {
|
|
17
|
+
timeoutMs;
|
|
18
|
+
constructor(timeoutMs, message = `TMDB request timed out after ${timeoutMs}ms`) {
|
|
19
|
+
super(message);
|
|
20
|
+
this.name = "TMDBTimeoutError";
|
|
21
|
+
this.timeoutMs = timeoutMs;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
16
25
|
class TMDBResponseError extends TMDBError {
|
|
17
26
|
body;
|
|
18
27
|
headers;
|
|
@@ -135,6 +144,19 @@ function toId(value, name) {
|
|
|
135
144
|
}
|
|
136
145
|
return String(value);
|
|
137
146
|
}
|
|
147
|
+
function toSeasonNumber(value) {
|
|
148
|
+
if (!Number.isInteger(value) || value < 0) {
|
|
149
|
+
throw new TMDBRequestError("seasonNumber must be a non-negative integer");
|
|
150
|
+
}
|
|
151
|
+
return String(value);
|
|
152
|
+
}
|
|
153
|
+
function toGroupId(value) {
|
|
154
|
+
const groupId = value.trim();
|
|
155
|
+
if (!/^[A-Za-z0-9_-]+$/.test(groupId)) {
|
|
156
|
+
throw new TMDBRequestError("groupId must be a non-empty identifier");
|
|
157
|
+
}
|
|
158
|
+
return groupId;
|
|
159
|
+
}
|
|
138
160
|
function toSearchQuery(value) {
|
|
139
161
|
const query = value.trim();
|
|
140
162
|
if (query.length === 0) {
|
|
@@ -268,23 +290,25 @@ class ConfigurationResource {
|
|
|
268
290
|
constructor(transport) {
|
|
269
291
|
this.#transport = transport;
|
|
270
292
|
}
|
|
271
|
-
details() {
|
|
272
|
-
return this.#transport.get("/configuration");
|
|
293
|
+
details(options = {}) {
|
|
294
|
+
return this.#transport.get("/configuration", { signal: options.signal });
|
|
273
295
|
}
|
|
274
|
-
countries() {
|
|
275
|
-
return this.#transport.get("/configuration/countries");
|
|
296
|
+
countries(options = {}) {
|
|
297
|
+
return this.#transport.get("/configuration/countries", { signal: options.signal });
|
|
276
298
|
}
|
|
277
|
-
jobs() {
|
|
278
|
-
return this.#transport.get("/configuration/jobs");
|
|
299
|
+
jobs(options = {}) {
|
|
300
|
+
return this.#transport.get("/configuration/jobs", { signal: options.signal });
|
|
279
301
|
}
|
|
280
|
-
languages() {
|
|
281
|
-
return this.#transport.get("/configuration/languages");
|
|
302
|
+
languages(options = {}) {
|
|
303
|
+
return this.#transport.get("/configuration/languages", { signal: options.signal });
|
|
282
304
|
}
|
|
283
|
-
primaryTranslations() {
|
|
284
|
-
return this.#transport.get("/configuration/primary_translations"
|
|
305
|
+
primaryTranslations(options = {}) {
|
|
306
|
+
return this.#transport.get("/configuration/primary_translations", {
|
|
307
|
+
signal: options.signal
|
|
308
|
+
});
|
|
285
309
|
}
|
|
286
|
-
timezones() {
|
|
287
|
-
return this.#transport.get("/configuration/timezones");
|
|
310
|
+
timezones(options = {}) {
|
|
311
|
+
return this.#transport.get("/configuration/timezones", { signal: options.signal });
|
|
288
312
|
}
|
|
289
313
|
}
|
|
290
314
|
|
|
@@ -298,14 +322,16 @@ class GenresResource {
|
|
|
298
322
|
return this.#transport.get("/genre/movie/list", {
|
|
299
323
|
query: withLanguage(this.#transport.defaults, {
|
|
300
324
|
language: options.language
|
|
301
|
-
})
|
|
325
|
+
}),
|
|
326
|
+
signal: options.signal
|
|
302
327
|
});
|
|
303
328
|
}
|
|
304
329
|
tv(options = {}) {
|
|
305
330
|
return this.#transport.get("/genre/tv/list", {
|
|
306
331
|
query: withLanguage(this.#transport.defaults, {
|
|
307
332
|
language: options.language
|
|
308
|
-
})
|
|
333
|
+
}),
|
|
334
|
+
signal: options.signal
|
|
309
335
|
});
|
|
310
336
|
}
|
|
311
337
|
}
|
|
@@ -334,22 +360,26 @@ class MoviesResource {
|
|
|
334
360
|
}
|
|
335
361
|
popular(options = {}) {
|
|
336
362
|
return this.#transport.get("/movie/popular", {
|
|
337
|
-
query: movieListQuery(this.#transport, options)
|
|
363
|
+
query: movieListQuery(this.#transport, options),
|
|
364
|
+
signal: options.signal
|
|
338
365
|
});
|
|
339
366
|
}
|
|
340
367
|
topRated(options = {}) {
|
|
341
368
|
return this.#transport.get("/movie/top_rated", {
|
|
342
|
-
query: movieListQuery(this.#transport, options)
|
|
369
|
+
query: movieListQuery(this.#transport, options),
|
|
370
|
+
signal: options.signal
|
|
343
371
|
});
|
|
344
372
|
}
|
|
345
373
|
nowPlaying(options = {}) {
|
|
346
374
|
return this.#transport.get("/movie/now_playing", {
|
|
347
|
-
query: movieListQuery(this.#transport, options)
|
|
375
|
+
query: movieListQuery(this.#transport, options),
|
|
376
|
+
signal: options.signal
|
|
348
377
|
});
|
|
349
378
|
}
|
|
350
379
|
upcoming(options = {}) {
|
|
351
380
|
return this.#transport.get("/movie/upcoming", {
|
|
352
|
-
query: movieListQuery(this.#transport, options)
|
|
381
|
+
query: movieListQuery(this.#transport, options),
|
|
382
|
+
signal: options.signal
|
|
353
383
|
});
|
|
354
384
|
}
|
|
355
385
|
details(movieId, options = {}) {
|
|
@@ -357,14 +387,16 @@ class MoviesResource {
|
|
|
357
387
|
query: withLanguage(this.#transport.defaults, {
|
|
358
388
|
append_to_response: toCommaList(options.appendToResponse),
|
|
359
389
|
language: options.language
|
|
360
|
-
})
|
|
390
|
+
}),
|
|
391
|
+
signal: options.signal
|
|
361
392
|
});
|
|
362
393
|
}
|
|
363
394
|
credits(movieId, options = {}) {
|
|
364
395
|
return this.#transport.get(`/movie/${toId(movieId, "movieId")}/credits`, {
|
|
365
396
|
query: withLanguage(this.#transport.defaults, {
|
|
366
397
|
language: options.language
|
|
367
|
-
})
|
|
398
|
+
}),
|
|
399
|
+
signal: options.signal
|
|
368
400
|
});
|
|
369
401
|
}
|
|
370
402
|
images(movieId, options = {}) {
|
|
@@ -372,24 +404,28 @@ class MoviesResource {
|
|
|
372
404
|
query: withLanguage(this.#transport.defaults, {
|
|
373
405
|
include_image_language: toCommaList(options.includeImageLanguage),
|
|
374
406
|
language: options.language
|
|
375
|
-
})
|
|
407
|
+
}),
|
|
408
|
+
signal: options.signal
|
|
376
409
|
});
|
|
377
410
|
}
|
|
378
411
|
recommendations(movieId, options = {}) {
|
|
379
412
|
return this.#transport.get(`/movie/${toId(movieId, "movieId")}/recommendations`, {
|
|
380
|
-
query: movieListQuery(this.#transport, options)
|
|
413
|
+
query: movieListQuery(this.#transport, options),
|
|
414
|
+
signal: options.signal
|
|
381
415
|
});
|
|
382
416
|
}
|
|
383
417
|
similar(movieId, options = {}) {
|
|
384
418
|
return this.#transport.get(`/movie/${toId(movieId, "movieId")}/similar`, {
|
|
385
|
-
query: movieListQuery(this.#transport, options)
|
|
419
|
+
query: movieListQuery(this.#transport, options),
|
|
420
|
+
signal: options.signal
|
|
386
421
|
});
|
|
387
422
|
}
|
|
388
423
|
videos(movieId, options = {}) {
|
|
389
424
|
return this.#transport.get(`/movie/${toId(movieId, "movieId")}/videos`, {
|
|
390
425
|
query: withLanguage(this.#transport.defaults, {
|
|
391
426
|
language: options.language
|
|
392
|
-
})
|
|
427
|
+
}),
|
|
428
|
+
signal: options.signal
|
|
393
429
|
});
|
|
394
430
|
}
|
|
395
431
|
}
|
|
@@ -409,21 +445,24 @@ class PeopleResource {
|
|
|
409
445
|
}
|
|
410
446
|
popular(options = {}) {
|
|
411
447
|
return this.#transport.get("/person/popular", {
|
|
412
|
-
query: peopleListQuery(this.#transport, options)
|
|
448
|
+
query: peopleListQuery(this.#transport, options),
|
|
449
|
+
signal: options.signal
|
|
413
450
|
});
|
|
414
451
|
}
|
|
415
452
|
details(personId, options = {}) {
|
|
416
453
|
return this.#transport.get(`/person/${toId(personId, "personId")}`, {
|
|
417
454
|
query: withLanguage(this.#transport.defaults, {
|
|
418
455
|
language: options.language
|
|
419
|
-
})
|
|
456
|
+
}),
|
|
457
|
+
signal: options.signal
|
|
420
458
|
});
|
|
421
459
|
}
|
|
422
460
|
combinedCredits(personId, options = {}) {
|
|
423
461
|
return this.#transport.get(`/person/${toId(personId, "personId")}/combined_credits`, {
|
|
424
462
|
query: withLanguage(this.#transport.defaults, {
|
|
425
463
|
language: options.language
|
|
426
|
-
})
|
|
464
|
+
}),
|
|
465
|
+
signal: options.signal
|
|
427
466
|
});
|
|
428
467
|
}
|
|
429
468
|
}
|
|
@@ -442,22 +481,26 @@ class SearchResource {
|
|
|
442
481
|
}
|
|
443
482
|
movies(query, options = {}) {
|
|
444
483
|
return this.#transport.get("/search/movie", {
|
|
445
|
-
query: movieSearchQuery(this.#transport, query, options)
|
|
484
|
+
query: movieSearchQuery(this.#transport, query, options),
|
|
485
|
+
signal: options.signal
|
|
446
486
|
});
|
|
447
487
|
}
|
|
448
488
|
tv(query, options = {}) {
|
|
449
489
|
return this.#transport.get("/search/tv", {
|
|
450
|
-
query: tvSearchQuery(this.#transport, query, options)
|
|
490
|
+
query: tvSearchQuery(this.#transport, query, options),
|
|
491
|
+
signal: options.signal
|
|
451
492
|
});
|
|
452
493
|
}
|
|
453
494
|
people(query, options = {}) {
|
|
454
495
|
return this.#transport.get("/search/person", {
|
|
455
|
-
query: commonSearchQuery(this.#transport, query, options)
|
|
496
|
+
query: commonSearchQuery(this.#transport, query, options),
|
|
497
|
+
signal: options.signal
|
|
456
498
|
});
|
|
457
499
|
}
|
|
458
500
|
async multi(query, options = {}) {
|
|
459
501
|
const response = await this.#transport.get("/search/multi", {
|
|
460
|
-
query: commonSearchQuery(this.#transport, query, options)
|
|
502
|
+
query: commonSearchQuery(this.#transport, query, options),
|
|
503
|
+
signal: options.signal
|
|
461
504
|
});
|
|
462
505
|
const excluded = options.exclude;
|
|
463
506
|
if (excluded === undefined || excluded.length === 0) {
|
|
@@ -511,7 +554,8 @@ class TrendingResource {
|
|
|
511
554
|
query: withLanguage(this.#transport.defaults, {
|
|
512
555
|
language: options.language,
|
|
513
556
|
page: options.page
|
|
514
|
-
})
|
|
557
|
+
}),
|
|
558
|
+
signal: options.signal
|
|
515
559
|
});
|
|
516
560
|
}
|
|
517
561
|
movies(timeWindow = "day", options = {}) {
|
|
@@ -519,7 +563,8 @@ class TrendingResource {
|
|
|
519
563
|
query: withLanguage(this.#transport.defaults, {
|
|
520
564
|
language: options.language,
|
|
521
565
|
page: options.page
|
|
522
|
-
})
|
|
566
|
+
}),
|
|
567
|
+
signal: options.signal
|
|
523
568
|
});
|
|
524
569
|
}
|
|
525
570
|
tv(timeWindow = "day", options = {}) {
|
|
@@ -527,7 +572,8 @@ class TrendingResource {
|
|
|
527
572
|
query: withLanguage(this.#transport.defaults, {
|
|
528
573
|
language: options.language,
|
|
529
574
|
page: options.page
|
|
530
|
-
})
|
|
575
|
+
}),
|
|
576
|
+
signal: options.signal
|
|
531
577
|
});
|
|
532
578
|
}
|
|
533
579
|
people(timeWindow = "day", options = {}) {
|
|
@@ -535,7 +581,8 @@ class TrendingResource {
|
|
|
535
581
|
query: withLanguage(this.#transport.defaults, {
|
|
536
582
|
language: options.language,
|
|
537
583
|
page: options.page
|
|
538
|
-
})
|
|
584
|
+
}),
|
|
585
|
+
signal: options.signal
|
|
539
586
|
});
|
|
540
587
|
}
|
|
541
588
|
}
|
|
@@ -548,22 +595,26 @@ class TVResource {
|
|
|
548
595
|
}
|
|
549
596
|
popular(options = {}) {
|
|
550
597
|
return this.#transport.get("/tv/popular", {
|
|
551
|
-
query: tvListQuery(this.#transport, options)
|
|
598
|
+
query: tvListQuery(this.#transport, options),
|
|
599
|
+
signal: options.signal
|
|
552
600
|
});
|
|
553
601
|
}
|
|
554
602
|
topRated(options = {}) {
|
|
555
603
|
return this.#transport.get("/tv/top_rated", {
|
|
556
|
-
query: tvListQuery(this.#transport, options)
|
|
604
|
+
query: tvListQuery(this.#transport, options),
|
|
605
|
+
signal: options.signal
|
|
557
606
|
});
|
|
558
607
|
}
|
|
559
608
|
airingToday(options = {}) {
|
|
560
609
|
return this.#transport.get("/tv/airing_today", {
|
|
561
|
-
query: tvListQuery(this.#transport, options)
|
|
610
|
+
query: tvListQuery(this.#transport, options),
|
|
611
|
+
signal: options.signal
|
|
562
612
|
});
|
|
563
613
|
}
|
|
564
614
|
onTheAir(options = {}) {
|
|
565
615
|
return this.#transport.get("/tv/on_the_air", {
|
|
566
|
-
query: tvListQuery(this.#transport, options)
|
|
616
|
+
query: tvListQuery(this.#transport, options),
|
|
617
|
+
signal: options.signal
|
|
567
618
|
});
|
|
568
619
|
}
|
|
569
620
|
details(seriesId, options = {}) {
|
|
@@ -571,14 +622,16 @@ class TVResource {
|
|
|
571
622
|
query: withLanguage(this.#transport.defaults, {
|
|
572
623
|
append_to_response: toCommaList(options.appendToResponse),
|
|
573
624
|
language: options.language
|
|
574
|
-
})
|
|
625
|
+
}),
|
|
626
|
+
signal: options.signal
|
|
575
627
|
});
|
|
576
628
|
}
|
|
577
629
|
credits(seriesId, options = {}) {
|
|
578
630
|
return this.#transport.get(`/tv/${toId(seriesId, "seriesId")}/credits`, {
|
|
579
631
|
query: withLanguage(this.#transport.defaults, {
|
|
580
632
|
language: options.language
|
|
581
|
-
})
|
|
633
|
+
}),
|
|
634
|
+
signal: options.signal
|
|
582
635
|
});
|
|
583
636
|
}
|
|
584
637
|
images(seriesId, options = {}) {
|
|
@@ -586,32 +639,103 @@ class TVResource {
|
|
|
586
639
|
query: withLanguage(this.#transport.defaults, {
|
|
587
640
|
include_image_language: toCommaList(options.includeImageLanguage),
|
|
588
641
|
language: options.language
|
|
589
|
-
})
|
|
642
|
+
}),
|
|
643
|
+
signal: options.signal
|
|
590
644
|
});
|
|
591
645
|
}
|
|
592
646
|
recommendations(seriesId, options = {}) {
|
|
593
647
|
return this.#transport.get(`/tv/${toId(seriesId, "seriesId")}/recommendations`, {
|
|
594
|
-
query: tvListQuery(this.#transport, options)
|
|
648
|
+
query: tvListQuery(this.#transport, options),
|
|
649
|
+
signal: options.signal
|
|
595
650
|
});
|
|
596
651
|
}
|
|
597
652
|
similar(seriesId, options = {}) {
|
|
598
653
|
return this.#transport.get(`/tv/${toId(seriesId, "seriesId")}/similar`, {
|
|
599
|
-
query: tvListQuery(this.#transport, options)
|
|
654
|
+
query: tvListQuery(this.#transport, options),
|
|
655
|
+
signal: options.signal
|
|
600
656
|
});
|
|
601
657
|
}
|
|
602
658
|
videos(seriesId, options = {}) {
|
|
603
659
|
return this.#transport.get(`/tv/${toId(seriesId, "seriesId")}/videos`, {
|
|
604
660
|
query: withLanguage(this.#transport.defaults, {
|
|
605
661
|
language: options.language
|
|
606
|
-
})
|
|
662
|
+
}),
|
|
663
|
+
signal: options.signal
|
|
607
664
|
});
|
|
608
665
|
}
|
|
609
666
|
seasonDetails(seriesId, seasonNumber, options = {}) {
|
|
610
|
-
return this.#transport.get(`/tv/${toId(seriesId, "seriesId")}/season/${
|
|
667
|
+
return this.#transport.get(`/tv/${toId(seriesId, "seriesId")}/season/${toSeasonNumber(seasonNumber)}`, {
|
|
611
668
|
query: withLanguage(this.#transport.defaults, {
|
|
612
669
|
append_to_response: toCommaList(options.appendToResponse),
|
|
613
670
|
language: options.language
|
|
614
|
-
})
|
|
671
|
+
}),
|
|
672
|
+
signal: options.signal
|
|
673
|
+
});
|
|
674
|
+
}
|
|
675
|
+
seasonCredits(seriesId, seasonNumber, options = {}) {
|
|
676
|
+
return this.#transport.get(`/tv/${toId(seriesId, "seriesId")}/season/${toSeasonNumber(seasonNumber)}/credits`, {
|
|
677
|
+
query: withLanguage(this.#transport.defaults, {
|
|
678
|
+
language: options.language
|
|
679
|
+
}),
|
|
680
|
+
signal: options.signal
|
|
681
|
+
});
|
|
682
|
+
}
|
|
683
|
+
seasonAggregateCredits(seriesId, seasonNumber, options = {}) {
|
|
684
|
+
return this.#transport.get(`/tv/${toId(seriesId, "seriesId")}/season/${toSeasonNumber(seasonNumber)}/aggregate_credits`, {
|
|
685
|
+
query: withLanguage(this.#transport.defaults, {
|
|
686
|
+
language: options.language
|
|
687
|
+
}),
|
|
688
|
+
signal: options.signal
|
|
689
|
+
});
|
|
690
|
+
}
|
|
691
|
+
seasonImages(seriesId, seasonNumber, options = {}) {
|
|
692
|
+
return this.#transport.get(`/tv/${toId(seriesId, "seriesId")}/season/${toSeasonNumber(seasonNumber)}/images`, {
|
|
693
|
+
query: withLanguage(this.#transport.defaults, {
|
|
694
|
+
include_image_language: toCommaList(options.includeImageLanguage),
|
|
695
|
+
language: options.language
|
|
696
|
+
}),
|
|
697
|
+
signal: options.signal
|
|
698
|
+
});
|
|
699
|
+
}
|
|
700
|
+
seasonVideos(seriesId, seasonNumber, options = {}) {
|
|
701
|
+
return this.#transport.get(`/tv/${toId(seriesId, "seriesId")}/season/${toSeasonNumber(seasonNumber)}/videos`, {
|
|
702
|
+
query: withLanguage(this.#transport.defaults, {
|
|
703
|
+
language: options.language
|
|
704
|
+
}),
|
|
705
|
+
signal: options.signal
|
|
706
|
+
});
|
|
707
|
+
}
|
|
708
|
+
episodeDetails(seriesId, seasonNumber, episodeNumber, options = {}) {
|
|
709
|
+
return this.#transport.get(`/tv/${toId(seriesId, "seriesId")}/season/${toSeasonNumber(seasonNumber)}/episode/${toId(episodeNumber, "episodeNumber")}`, {
|
|
710
|
+
query: withLanguage(this.#transport.defaults, {
|
|
711
|
+
append_to_response: toCommaList(options.appendToResponse),
|
|
712
|
+
language: options.language
|
|
713
|
+
}),
|
|
714
|
+
signal: options.signal
|
|
715
|
+
});
|
|
716
|
+
}
|
|
717
|
+
aggregateCredits(seriesId, options = {}) {
|
|
718
|
+
return this.#transport.get(`/tv/${toId(seriesId, "seriesId")}/aggregate_credits`, {
|
|
719
|
+
query: withLanguage(this.#transport.defaults, {
|
|
720
|
+
language: options.language
|
|
721
|
+
}),
|
|
722
|
+
signal: options.signal
|
|
723
|
+
});
|
|
724
|
+
}
|
|
725
|
+
episodeGroups(seriesId, options = {}) {
|
|
726
|
+
return this.#transport.get(`/tv/${toId(seriesId, "seriesId")}/episode_groups`, {
|
|
727
|
+
query: withLanguage(this.#transport.defaults, {
|
|
728
|
+
language: options.language
|
|
729
|
+
}),
|
|
730
|
+
signal: options.signal
|
|
731
|
+
});
|
|
732
|
+
}
|
|
733
|
+
episodeGroup(groupId, options = {}) {
|
|
734
|
+
return this.#transport.get(`/tv/episode_group/${toGroupId(groupId)}`, {
|
|
735
|
+
query: withLanguage(this.#transport.defaults, {
|
|
736
|
+
language: options.language
|
|
737
|
+
}),
|
|
738
|
+
signal: options.signal
|
|
615
739
|
});
|
|
616
740
|
}
|
|
617
741
|
}
|
|
@@ -634,13 +758,17 @@ class TMDBClient {
|
|
|
634
758
|
tv;
|
|
635
759
|
#transport;
|
|
636
760
|
constructor(options) {
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
761
|
+
let imageTransform = options.images?.transform;
|
|
762
|
+
if (options.transport === undefined) {
|
|
763
|
+
const builtInClient = new TMDBHttpClient(options);
|
|
764
|
+
this.#transport = builtInClient;
|
|
765
|
+
imageTransform = builtInClient.imageTransform;
|
|
766
|
+
} else {
|
|
767
|
+
this.#transport = options.transport;
|
|
768
|
+
}
|
|
641
769
|
this.configuration = new ConfigurationResource(this.#transport);
|
|
642
770
|
this.genres = new GenresResource(this.#transport);
|
|
643
|
-
this.images = new ImagesHelper(this.#transport,
|
|
771
|
+
this.images = new ImagesHelper(this.#transport, imageTransform);
|
|
644
772
|
this.movies = new MoviesResource(this.#transport);
|
|
645
773
|
this.people = new PeopleResource(this.#transport);
|
|
646
774
|
this.search = new SearchResource(this.#transport);
|
|
@@ -654,6 +782,238 @@ class TMDBClient {
|
|
|
654
782
|
function createTMDB(options) {
|
|
655
783
|
return new TMDBClient(options);
|
|
656
784
|
}
|
|
785
|
+
// src/helpers/cache.ts
|
|
786
|
+
function withMemoryCache(transport, options = {}) {
|
|
787
|
+
const ttlMs = options.ttlMs ?? 5 * 60000;
|
|
788
|
+
const maxEntries = options.maxEntries ?? 100;
|
|
789
|
+
if (!Number.isFinite(ttlMs) || ttlMs <= 0) {
|
|
790
|
+
throw new RangeError("ttlMs must be a positive number");
|
|
791
|
+
}
|
|
792
|
+
if (!Number.isInteger(maxEntries) || maxEntries < 1) {
|
|
793
|
+
throw new RangeError("maxEntries must be a positive integer");
|
|
794
|
+
}
|
|
795
|
+
const entries = new Map;
|
|
796
|
+
return {
|
|
797
|
+
...transport,
|
|
798
|
+
async get(path, requestOptions = {}) {
|
|
799
|
+
const key = cacheKey(path, requestOptions);
|
|
800
|
+
const cached = entries.get(key);
|
|
801
|
+
if (cached !== undefined) {
|
|
802
|
+
if (cached.expiresAt > Date.now()) {
|
|
803
|
+
entries.delete(key);
|
|
804
|
+
entries.set(key, cached);
|
|
805
|
+
return cached.value;
|
|
806
|
+
}
|
|
807
|
+
entries.delete(key);
|
|
808
|
+
}
|
|
809
|
+
const value = await transport.get(path, requestOptions);
|
|
810
|
+
entries.set(key, { expiresAt: Date.now() + ttlMs, value });
|
|
811
|
+
evictOverflow(entries, maxEntries);
|
|
812
|
+
return value;
|
|
813
|
+
},
|
|
814
|
+
clear() {
|
|
815
|
+
entries.clear();
|
|
816
|
+
}
|
|
817
|
+
};
|
|
818
|
+
}
|
|
819
|
+
function cacheKey(path, options) {
|
|
820
|
+
return `${path}?${serializeQuery(options.query)}|${serializeHeaders(options.headers)}`;
|
|
821
|
+
}
|
|
822
|
+
function serializeQuery(query) {
|
|
823
|
+
if (query === undefined) {
|
|
824
|
+
return "";
|
|
825
|
+
}
|
|
826
|
+
return Object.entries(query).filter(([, value]) => value !== undefined && value !== null).sort(([left], [right]) => left.localeCompare(right)).map(([key, value]) => `${key}=${Array.isArray(value) ? value.map(String).join(",") : String(value)}`).join("&");
|
|
827
|
+
}
|
|
828
|
+
function serializeHeaders(headers) {
|
|
829
|
+
if (headers === undefined) {
|
|
830
|
+
return "";
|
|
831
|
+
}
|
|
832
|
+
return [...new Headers(headers)].sort(([left], [right]) => left.localeCompare(right)).map(([key, value]) => `${key}:${value}`).join("|");
|
|
833
|
+
}
|
|
834
|
+
function evictOverflow(entries, maxEntries) {
|
|
835
|
+
while (entries.size > maxEntries) {
|
|
836
|
+
entries.delete(entries.keys().next().value);
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
// src/helpers/pagination.ts
|
|
840
|
+
async function* paginate(fetchPage, options = {}) {
|
|
841
|
+
const startPage = options.startPage ?? 1;
|
|
842
|
+
const endPage = options.endPage ?? 500;
|
|
843
|
+
assertPositiveInteger(startPage, "startPage");
|
|
844
|
+
assertPositiveInteger(endPage, "endPage");
|
|
845
|
+
for (let page = startPage;page <= endPage; page += 1) {
|
|
846
|
+
options.signal?.throwIfAborted();
|
|
847
|
+
const response = await fetchPage(page);
|
|
848
|
+
yield response;
|
|
849
|
+
if (response.results.length === 0 || page >= response.total_pages) {
|
|
850
|
+
return;
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
async function* paginateItems(fetchPage, options = {}) {
|
|
855
|
+
for await (const page of paginate(fetchPage, options)) {
|
|
856
|
+
yield* page.results;
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
function assertPositiveInteger(value, name) {
|
|
860
|
+
if (!Number.isInteger(value) || value < 1) {
|
|
861
|
+
throw new RangeError(`${name} must be a positive integer`);
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
// src/helpers/retry.ts
|
|
865
|
+
var MAX_RETRY_AFTER_MS = 60000;
|
|
866
|
+
async function retry(task, options = {}) {
|
|
867
|
+
const retries = options.retries ?? 2;
|
|
868
|
+
if (!Number.isInteger(retries) || retries < 0) {
|
|
869
|
+
throw new RangeError("retries must be a non-negative integer");
|
|
870
|
+
}
|
|
871
|
+
const retryOn = options.retryOn ?? shouldRetry;
|
|
872
|
+
const signal = options.signal;
|
|
873
|
+
if (signal?.aborted) {
|
|
874
|
+
throw signal.reason;
|
|
875
|
+
}
|
|
876
|
+
for (let attempt = 0;; attempt += 1) {
|
|
877
|
+
try {
|
|
878
|
+
return await task();
|
|
879
|
+
} catch (error) {
|
|
880
|
+
if (signal?.aborted) {
|
|
881
|
+
throw signal.reason;
|
|
882
|
+
}
|
|
883
|
+
if (attempt >= retries || !retryOn(error, attempt)) {
|
|
884
|
+
throw error;
|
|
885
|
+
}
|
|
886
|
+
const delayMs = retryDelay(error, attempt, options);
|
|
887
|
+
options.onRetry?.({ attempt, delayMs, error });
|
|
888
|
+
await sleep(delayMs, signal);
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
function withRetry(transport, options = {}) {
|
|
893
|
+
return {
|
|
894
|
+
...transport,
|
|
895
|
+
get(path, requestOptions) {
|
|
896
|
+
const { cleanup, signal } = combineSignals(options.signal, requestOptions?.signal);
|
|
897
|
+
const effectiveOptions = signal === undefined ? requestOptions : { ...requestOptions, signal };
|
|
898
|
+
return retry(() => transport.get(path, effectiveOptions), {
|
|
899
|
+
...options,
|
|
900
|
+
signal
|
|
901
|
+
}).finally(cleanup);
|
|
902
|
+
}
|
|
903
|
+
};
|
|
904
|
+
}
|
|
905
|
+
function shouldRetry(error) {
|
|
906
|
+
if (error instanceof TMDBRateLimitError) {
|
|
907
|
+
return true;
|
|
908
|
+
}
|
|
909
|
+
if (error instanceof TMDBResponseError) {
|
|
910
|
+
return error.isServerError || error.status === 408;
|
|
911
|
+
}
|
|
912
|
+
if (error instanceof TMDBTimeoutError) {
|
|
913
|
+
return false;
|
|
914
|
+
}
|
|
915
|
+
if (error instanceof TMDBRequestError) {
|
|
916
|
+
if (error.cause === undefined || error.cause instanceof TMDBTimeoutError) {
|
|
917
|
+
return false;
|
|
918
|
+
}
|
|
919
|
+
return !isAbortError(error.cause);
|
|
920
|
+
}
|
|
921
|
+
return false;
|
|
922
|
+
}
|
|
923
|
+
function retryDelay(error, attempt, options) {
|
|
924
|
+
const retryAfter = retryAfterMs(error);
|
|
925
|
+
if (retryAfter !== undefined) {
|
|
926
|
+
return Math.min(Math.max(retryAfter, 0), MAX_RETRY_AFTER_MS);
|
|
927
|
+
}
|
|
928
|
+
if (error instanceof TMDBRateLimitError) {
|
|
929
|
+
return Math.min(Math.max(error.retryAfter * 1000, 0), MAX_RETRY_AFTER_MS);
|
|
930
|
+
}
|
|
931
|
+
const baseDelayMs = options.baseDelayMs ?? 250;
|
|
932
|
+
const maxDelayMs = options.maxDelayMs ?? 1e4;
|
|
933
|
+
const factor = options.factor ?? 2;
|
|
934
|
+
const delay = Math.min(maxDelayMs, baseDelayMs * factor ** attempt);
|
|
935
|
+
return options.jitter === false ? delay : Math.random() * delay;
|
|
936
|
+
}
|
|
937
|
+
function retryAfterMs(error) {
|
|
938
|
+
if (!(error instanceof TMDBResponseError)) {
|
|
939
|
+
return;
|
|
940
|
+
}
|
|
941
|
+
const header = error.headers.get("retry-after");
|
|
942
|
+
if (header === null || header.trim() === "") {
|
|
943
|
+
return;
|
|
944
|
+
}
|
|
945
|
+
return parseRetryAfter(header) * 1000;
|
|
946
|
+
}
|
|
947
|
+
function combineSignals(first, second) {
|
|
948
|
+
if (first === undefined || second === undefined || first === second) {
|
|
949
|
+
return { cleanup: noop, signal: first ?? second };
|
|
950
|
+
}
|
|
951
|
+
const controller = new AbortController;
|
|
952
|
+
const onAbort = () => controller.abort((first.aborted ? first : second).reason);
|
|
953
|
+
first.addEventListener("abort", onAbort, { once: true });
|
|
954
|
+
second.addEventListener("abort", onAbort, { once: true });
|
|
955
|
+
if (first.aborted || second.aborted) {
|
|
956
|
+
onAbort();
|
|
957
|
+
}
|
|
958
|
+
return {
|
|
959
|
+
cleanup() {
|
|
960
|
+
first.removeEventListener("abort", onAbort);
|
|
961
|
+
second.removeEventListener("abort", onAbort);
|
|
962
|
+
},
|
|
963
|
+
signal: controller.signal
|
|
964
|
+
};
|
|
965
|
+
}
|
|
966
|
+
function noop() {}
|
|
967
|
+
function isAbortError(error) {
|
|
968
|
+
return typeof error === "object" && error !== null && "name" in error && error.name === "AbortError";
|
|
969
|
+
}
|
|
970
|
+
function sleep(ms, signal) {
|
|
971
|
+
return new Promise((resolve, reject) => {
|
|
972
|
+
const onAbort = () => {
|
|
973
|
+
clearTimeout(timer);
|
|
974
|
+
signal?.removeEventListener("abort", onAbort);
|
|
975
|
+
reject(signal.reason);
|
|
976
|
+
};
|
|
977
|
+
const timer = setTimeout(() => {
|
|
978
|
+
signal?.removeEventListener("abort", onAbort);
|
|
979
|
+
resolve();
|
|
980
|
+
}, ms);
|
|
981
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
982
|
+
if (signal?.aborted) {
|
|
983
|
+
onAbort();
|
|
984
|
+
}
|
|
985
|
+
});
|
|
986
|
+
}
|
|
987
|
+
// src/helpers/timeout.ts
|
|
988
|
+
async function withTimeout(timeoutMs, task, options = {}) {
|
|
989
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
|
|
990
|
+
throw new RangeError("timeoutMs must be a positive number");
|
|
991
|
+
}
|
|
992
|
+
const parent = options.signal;
|
|
993
|
+
const controller = new AbortController;
|
|
994
|
+
const timeoutError = new TMDBTimeoutError(timeoutMs, options.message);
|
|
995
|
+
const onAbort = () => controller.abort(parent.reason);
|
|
996
|
+
parent?.addEventListener("abort", onAbort, { once: true });
|
|
997
|
+
if (parent?.aborted) {
|
|
998
|
+
parent.removeEventListener("abort", onAbort);
|
|
999
|
+
throw parent.reason;
|
|
1000
|
+
}
|
|
1001
|
+
const timer = setTimeout(() => controller.abort(timeoutError), timeoutMs);
|
|
1002
|
+
try {
|
|
1003
|
+
return await task(controller.signal);
|
|
1004
|
+
} catch (error) {
|
|
1005
|
+
if (controller.signal.reason === timeoutError) {
|
|
1006
|
+
throw timeoutError;
|
|
1007
|
+
}
|
|
1008
|
+
if (parent?.aborted) {
|
|
1009
|
+
throw parent.reason;
|
|
1010
|
+
}
|
|
1011
|
+
throw error;
|
|
1012
|
+
} finally {
|
|
1013
|
+
clearTimeout(timer);
|
|
1014
|
+
parent?.removeEventListener("abort", onAbort);
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
657
1017
|
// src/search-guards.ts
|
|
658
1018
|
function isMovieSearchResult(result) {
|
|
659
1019
|
return isObjectWithMediaType(result, "movie");
|
|
@@ -737,9 +1097,11 @@ export {
|
|
|
737
1097
|
KNOWN_STILL_SIZES,
|
|
738
1098
|
TMDBClient,
|
|
739
1099
|
TMDBError,
|
|
1100
|
+
TMDBHttpClient,
|
|
740
1101
|
TMDBRateLimitError,
|
|
741
1102
|
TMDBRequestError,
|
|
742
1103
|
TMDBResponseError,
|
|
1104
|
+
TMDBTimeoutError,
|
|
743
1105
|
buildImageUrl,
|
|
744
1106
|
createTMDB,
|
|
745
1107
|
isKnownBackdropSize,
|
|
@@ -753,8 +1115,14 @@ export {
|
|
|
753
1115
|
isPerson,
|
|
754
1116
|
isPersonSearchResult,
|
|
755
1117
|
isTV,
|
|
756
|
-
isTVSearchResult
|
|
1118
|
+
isTVSearchResult,
|
|
1119
|
+
paginate,
|
|
1120
|
+
paginateItems,
|
|
1121
|
+
retry,
|
|
1122
|
+
withMemoryCache,
|
|
1123
|
+
withRetry,
|
|
1124
|
+
withTimeout
|
|
757
1125
|
};
|
|
758
1126
|
|
|
759
|
-
//# debugId=
|
|
1127
|
+
//# debugId=24603BBDC4DA497C64756E2164756E21
|
|
760
1128
|
//# sourceMappingURL=index.js.map
|