@lorenzopant/tmdb 1.17.2 → 1.17.4

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.
Files changed (4) hide show
  1. package/README.md +19 -19
  2. package/dist/index.d.ts +261 -113
  3. package/dist/index.js +103 -41
  4. package/package.json +31 -38
package/README.md CHANGED
@@ -28,23 +28,23 @@ yard add @lorenzopant/tmdb
28
28
  ## Usage
29
29
 
30
30
  ```typescript
31
- import { TMDB } from '@lorenzopant/tmdb';
31
+ import { TMDB } from "@lorenzopant/tmdb";
32
32
 
33
- const tmdb = new TMDB('your_access_token');
33
+ const tmdb = new TMDB("your_access_token");
34
34
 
35
35
  async function searchMovies() {
36
- try {
37
- const movies = await tmdb.search.movies({ query: 'Fight Club' });
38
- console.log(movies);
39
- } catch (error) {
40
- if (error instanceof TMDBError) {
41
- console.error('TMDB Error:', error.message);
42
- console.error('HTTP Status:', error.http_status_code);
43
- console.error('TMDB Status Code:', error.tmdb_status_code);
44
- } else {
45
- console.error('Unknown error:', error);
46
- }
47
- }
36
+ try {
37
+ const movies = await tmdb.search.movies({ query: "Fight Club" });
38
+ console.log(movies);
39
+ } catch (error) {
40
+ if (error instanceof TMDBError) {
41
+ console.error("TMDB Error:", error.message);
42
+ console.error("HTTP Status:", error.http_status_code);
43
+ console.error("TMDB Status Code:", error.tmdb_status_code);
44
+ } else {
45
+ console.error("Unknown error:", error);
46
+ }
47
+ }
48
48
  }
49
49
 
50
50
  searchMovies();
@@ -77,11 +77,11 @@ Custom logger:
77
77
 
78
78
  ```typescript
79
79
  const tmdb = new TMDB("your_access_token", {
80
- logger: (entry) => {
81
- if (entry.type === "response") {
82
- console.log("TMDB:", entry.endpoint, entry.status, entry.durationMs);
83
- }
84
- },
80
+ logger: (entry) => {
81
+ if (entry.type === "response") {
82
+ console.log("TMDB:", entry.endpoint, entry.status, entry.durationMs);
83
+ }
84
+ },
85
85
  });
86
86
  ```
87
87
 
package/dist/index.d.ts CHANGED
@@ -25,9 +25,9 @@ type ChangeItem = {
25
25
  /** Timestamp of when the change occurred (ISO 8601 format) */
26
26
  time: string;
27
27
  /** ISO 639-1 language code associated with the change */
28
- iso_639_1?: string | null;
28
+ iso_639_1?: string;
29
29
  /** ISO 3166-1 country code associated with the change */
30
- iso_3166_1?: string | null;
30
+ iso_3166_1?: string;
31
31
  /** The changed data object (structure varies by change type) */
32
32
  value: object | string;
33
33
  /** The original data object (structure varies by change type) */
@@ -132,7 +132,7 @@ type GenresResponse = {
132
132
  */
133
133
  type ProductionCompany = {
134
134
  id: number;
135
- logo_path: string | null;
135
+ logo_path?: string;
136
136
  name: string;
137
137
  origin_country: string;
138
138
  };
@@ -157,21 +157,21 @@ type SpokenLanguage = {
157
157
  type MovieCollection = {
158
158
  id: number;
159
159
  name: string;
160
- poster_path?: string | null;
161
- backdrop_path?: string | null;
160
+ poster_path?: string;
161
+ backdrop_path?: string;
162
162
  };
163
163
  /**
164
164
  * Represents common class for cast and crew types
165
165
  */
166
166
  type Credit = {
167
167
  adult: boolean;
168
- gender: number | null;
168
+ gender?: number;
169
169
  id: number;
170
170
  known_for_department: string;
171
171
  name: string;
172
172
  original_name: string;
173
173
  popularity: number;
174
- profile_path?: string | null;
174
+ profile_path?: string;
175
175
  credit_id: string;
176
176
  };
177
177
  /**
@@ -272,11 +272,11 @@ type WatchMonetizationType = "flatrate" | "free" | "ads" | "rent" | "buy";
272
272
  */
273
273
  type BaseKnownForItem = {
274
274
  adult: boolean;
275
- backdrop_path: string | null;
275
+ backdrop_path?: string;
276
276
  id: number;
277
277
  original_language: string;
278
278
  overview: string;
279
- poster_path: string | null;
279
+ poster_path?: string;
280
280
  genre_ids: number[];
281
281
  popularity: number;
282
282
  vote_average: number;
@@ -446,7 +446,7 @@ type ImageItem = {
446
446
  /** Image height in pixels */
447
447
  height: number;
448
448
  /** ISO 639-1 language code if image contains text, null otherwise */
449
- iso_639_1?: string | null;
449
+ iso_639_1?: string;
450
450
  /** Relative path to the image file (append to base URL) */
451
451
  file_path: string;
452
452
  /** Average user rating for this image */
@@ -580,6 +580,40 @@ type ImagesConfig = {
580
580
  default_image_sizes?: Partial<DefaultImageSizesConfig>;
581
581
  };
582
582
 
583
+ /**
584
+ * Represents a generic error or an error specific to the TMDB (The Movie Database) API.
585
+ * This error class extends the built-in `Error` class and includes additional
586
+ * properties to provide more context about the error.
587
+ */
588
+ declare class TMDBError extends Error {
589
+ /**
590
+ * The status code returned by the TMDB API.
591
+ * If the value is `-1`, it indicates a library-specific error rather than a TMDB API error.
592
+ * @reference https://developer.themoviedb.org/docs/errors - code
593
+ */
594
+ tmdb_status_code: number;
595
+ /**
596
+ * A descriptive message providing details about the error.
597
+ * If the error is specific to the TMDB API, this message will be derived from the API response
598
+ * @reference https://developer.themoviedb.org/docs/errors - message
599
+ */
600
+ message: string;
601
+ /**
602
+ * The HTTP status code associated with the error.
603
+ * If the error is specific to the TMDB API, this code will be derived from the API response.
604
+ * @reference https://developer.themoviedb.org/docs/errors - HTTP Status
605
+ */
606
+ http_status_code: number;
607
+ /**
608
+ * Creates an instance of `TMDBError`.
609
+ *
610
+ * @param message - A descriptive message providing details about the error.
611
+ * @param http_status - The HTTP status code associated with the error.
612
+ * @param tmdb_status_code - (Optional) The status code returned by the TMDB API. Defaults to `-1` for library-specific errors.
613
+ */
614
+ constructor(message: string, http_status: number, tmdb_status_code?: number);
615
+ }
616
+
583
617
  type TMDBLoggerEntry = {
584
618
  type: "request" | "response" | "error";
585
619
  method: "GET";
@@ -1350,6 +1384,81 @@ declare const TIMEZONE_DATA: readonly [{
1350
1384
  readonly zones: readonly ["Africa/Maputo"];
1351
1385
  }];
1352
1386
 
1387
+ /**
1388
+ * Context object passed to every request interceptor before a TMDB API call is made.
1389
+ * Interceptors may return a modified copy of this object to override the endpoint or params,
1390
+ * or return `void` / `undefined` to leave the request unchanged.
1391
+ */
1392
+ type RequestInterceptorContext = {
1393
+ /** The API path being requested, e.g. `"/movie/550"`. */
1394
+ endpoint: string;
1395
+ /** Query parameters that will be appended to the URL. Mutating this object has no effect — return a new context instead. */
1396
+ params: Record<string, unknown>;
1397
+ /** The HTTP method. Currently always `"GET"`. */
1398
+ method: "GET";
1399
+ };
1400
+ /**
1401
+ * A function that runs before each TMDB API request.
1402
+ *
1403
+ * - Return `void` / `undefined` to leave the request unchanged.
1404
+ * - Return a (partial) {@link RequestInterceptorContext} to override `endpoint` and/or `params`.
1405
+ * - Async interceptors are awaited in order.
1406
+ *
1407
+ * @example
1408
+ * ```ts
1409
+ * const tmdb = new TMDB(token, {
1410
+ * interceptors: {
1411
+ * request: (ctx) => {
1412
+ * console.log(`[TMDB] ${ctx.method} ${ctx.endpoint}`, ctx.params);
1413
+ * },
1414
+ * },
1415
+ * });
1416
+ * ```
1417
+ */
1418
+ type RequestInterceptor = (context: RequestInterceptorContext) => RequestInterceptorContext | void | Promise<RequestInterceptorContext | void>;
1419
+ /**
1420
+ * Called after every successful TMDB API response, before data is returned to the caller.
1421
+ *
1422
+ * - Receives the parsed response as `unknown` (the interceptor is not aware of the specific type).
1423
+ * - Return the data (same shape) to pass it through — or return `void` to fall back to the original.
1424
+ * - Designed for side effects: logging, caching, image URL enrichment.
1425
+ * - Must **not** change the shape of the returned data.
1426
+ *
1427
+ * @example
1428
+ * ```ts
1429
+ * const tmdb = new TMDB(token, {
1430
+ * interceptors: {
1431
+ * response: {
1432
+ * onSuccess: (data) => {
1433
+ * myCache.set(data);
1434
+ * },
1435
+ * },
1436
+ * },
1437
+ * });
1438
+ * ```
1439
+ */
1440
+ type ResponseSuccessInterceptor = (data: unknown) => unknown | void | Promise<unknown | void>;
1441
+ /**
1442
+ * Called after a TMDB API error has been normalised into a {@link TMDBError}.
1443
+ *
1444
+ * - Receives a typed `TMDBError` — never raw `unknown`.
1445
+ * - Return `void` — this hook is for side effects only (logging, toast notifications, Sentry).
1446
+ * - The `TMDBError` is **always re-thrown** after the interceptor runs; you cannot suppress it.
1447
+ *
1448
+ * @example
1449
+ * ```ts
1450
+ * const tmdb = new TMDB(token, {
1451
+ * interceptors: {
1452
+ * response: {
1453
+ * onError: (error) => {
1454
+ * Sentry.captureException(error);
1455
+ * },
1456
+ * },
1457
+ * },
1458
+ * });
1459
+ * ```
1460
+ */
1461
+ type ResponseErrorInterceptor = (error: TMDBError) => void | Promise<void>;
1353
1462
  type TMDBOptions = {
1354
1463
  /**
1355
1464
  * The language to use for requests (ISO 639-1 code)
@@ -1390,6 +1499,38 @@ type TMDBOptions = {
1390
1499
  * @default true
1391
1500
  */
1392
1501
  deduplication?: boolean;
1502
+ /**
1503
+ * Interceptors that run at specific points in the request lifecycle.
1504
+ *
1505
+ * `request` interceptors are called **before** every API request, in the order
1506
+ * they are provided. Each interceptor receives a {@link RequestInterceptorContext}
1507
+ * and may optionally return a modified context to change the endpoint or params.
1508
+ *
1509
+ * @example
1510
+ * ```ts
1511
+ * const tmdb = new TMDB(token, {
1512
+ * interceptors: {
1513
+ * request: [
1514
+ * (ctx) => console.log(`→ ${ctx.endpoint}`),
1515
+ * (ctx) => ({ ...ctx, params: { ...ctx.params, include_adult: false } }),
1516
+ * ],
1517
+ * },
1518
+ * });
1519
+ * ```
1520
+ */
1521
+ interceptors?: {
1522
+ request?: RequestInterceptor | RequestInterceptor[];
1523
+ /**
1524
+ * Response lifecycle hooks.
1525
+ *
1526
+ * - `onSuccess` — runs after every successful response, before data is returned.
1527
+ * - `onError` — runs after a {@link TMDBError} is created; always re-throws after.
1528
+ */
1529
+ response?: {
1530
+ onSuccess?: ResponseSuccessInterceptor;
1531
+ onError?: ResponseErrorInterceptor;
1532
+ };
1533
+ };
1393
1534
  };
1394
1535
 
1395
1536
  /**
@@ -1459,7 +1600,7 @@ declare enum DiscoverTVType {
1459
1600
  * A TV result item as returned by discover endpoints.
1460
1601
  */
1461
1602
  type DiscoverTVResultItem = {
1462
- backdrop_path: string | null;
1603
+ backdrop_path?: string;
1463
1604
  first_air_date: string;
1464
1605
  genre_ids: number[];
1465
1606
  id: number;
@@ -1469,7 +1610,7 @@ type DiscoverTVResultItem = {
1469
1610
  original_name: string;
1470
1611
  overview: string;
1471
1612
  popularity: number;
1472
- poster_path: string | null;
1613
+ poster_path?: string;
1473
1614
  vote_average: number;
1474
1615
  vote_count: number;
1475
1616
  };
@@ -1565,7 +1706,7 @@ type CollectionResultItem = {
1565
1706
  /** Collection overview/description */
1566
1707
  overview: string;
1567
1708
  /** Path to poster image */
1568
- poster_path?: string | null;
1709
+ poster_path?: string;
1569
1710
  };
1570
1711
  /**
1571
1712
  * Company information in search results
@@ -1574,7 +1715,7 @@ type CompanyResultItem = {
1574
1715
  /** Unique company identifier */
1575
1716
  id: number;
1576
1717
  /** Path to company logo image */
1577
- logo_path?: string | null;
1718
+ logo_path?: string;
1578
1719
  /** Company name */
1579
1720
  name: string;
1580
1721
  /** ISO 3166-1 country code of company's origin */
@@ -1603,7 +1744,7 @@ type PersonResultItem = {
1603
1744
  /** TMDB popularity score based on views, votes, and activity */
1604
1745
  popularity: number;
1605
1746
  /** Path to person's profile image */
1606
- profile_path?: string | null;
1747
+ profile_path?: string;
1607
1748
  /** List of notable movies or TV shows the person is known for */
1608
1749
  known_for: KnownForItem[];
1609
1750
  };
@@ -1616,7 +1757,7 @@ type PersonResultItem = {
1616
1757
  */
1617
1758
  type TVSeriesResultItem = {
1618
1759
  /** Relative path to the backdrop image for the series (nullable on some responses). */
1619
- backdrop_path?: string | null;
1760
+ backdrop_path?: string;
1620
1761
  /** First air date of the series (YYYY-MM-DD). */
1621
1762
  first_air_date: string;
1622
1763
  /** Array of genre ids associated with the series. */
@@ -1634,7 +1775,7 @@ type TVSeriesResultItem = {
1634
1775
  /** Popularity score as returned by TMDB. */
1635
1776
  popularity: number;
1636
1777
  /** Relative path to the poster image for the series (nullable on some responses). */
1637
- poster_path?: string | null;
1778
+ poster_path?: string;
1638
1779
  /** Average vote score for the series. */
1639
1780
  vote_average: number;
1640
1781
  /** Total number of votes the series has received. */
@@ -1647,7 +1788,7 @@ type TVSeriesResultItem = {
1647
1788
  */
1648
1789
  type MovieResultItem = {
1649
1790
  /** Path to backdrop image */
1650
- backdrop_path?: string | null;
1791
+ backdrop_path?: string;
1651
1792
  /** Unique movie identifier */
1652
1793
  id: number;
1653
1794
  /** Movie title (localized) */
@@ -1657,7 +1798,7 @@ type MovieResultItem = {
1657
1798
  /** Plot synopsis/overview */
1658
1799
  overview: string;
1659
1800
  /** Path to poster image */
1660
- poster_path?: string | null;
1801
+ poster_path?: string;
1661
1802
  /** Whether the movie is marked as adult content */
1662
1803
  adult: boolean;
1663
1804
  /** Original language of the movie (ISO 639-1 code) */
@@ -1804,19 +1945,19 @@ type MovieDetails = {
1804
1945
  /** Whether the movie is marked as adult content */
1805
1946
  adult: boolean;
1806
1947
  /** Path to backdrop image, null if not available */
1807
- backdrop_path: string | null;
1948
+ backdrop_path?: string;
1808
1949
  /** Collection the movie belongs to (e.g., "The Lord of the Rings Collection"), null if standalone */
1809
- belongs_to_collection: MovieCollection | null;
1950
+ belongs_to_collection?: MovieCollection;
1810
1951
  /** Production budget in US dollars */
1811
1952
  budget: number;
1812
1953
  /** Array of genres associated with the movie */
1813
1954
  genres: Genre[];
1814
1955
  /** Official homepage URL, null if not available */
1815
- homepage: string | null;
1956
+ homepage?: string;
1816
1957
  /** Unique movie identifier in TMDB */
1817
1958
  id: number;
1818
1959
  /** IMDb identifier (e.g., "tt0133093"), null if not linked */
1819
- imdb_id: string | null;
1960
+ imdb_id?: string;
1820
1961
  /** Array of origin country codes (ISO 3166-1) */
1821
1962
  origin_country: string[];
1822
1963
  /** Original language of the movie (ISO 639-1 code) */
@@ -1824,11 +1965,11 @@ type MovieDetails = {
1824
1965
  /** Original title in the original language */
1825
1966
  original_title: string;
1826
1967
  /** Plot synopsis/overview, null if not available */
1827
- overview: string | null;
1968
+ overview?: string;
1828
1969
  /** Popularity score calculated by TMDB */
1829
1970
  popularity: number;
1830
1971
  /** Path to poster image, null if not available */
1831
- poster_path: string | null;
1972
+ poster_path?: string;
1832
1973
  /** Array of companies that produced the movie */
1833
1974
  production_companies: ProductionCompany[];
1834
1975
  /** Array of countries where the movie was produced */
@@ -1838,13 +1979,13 @@ type MovieDetails = {
1838
1979
  /** Box office revenue in US dollars */
1839
1980
  revenue: number;
1840
1981
  /** Runtime in minutes, null if not set */
1841
- runtime: number | null;
1982
+ runtime?: number;
1842
1983
  /** Array of languages spoken in the movie */
1843
1984
  spoken_languages: SpokenLanguage[];
1844
1985
  /** Release status (e.g., "Released", "Post Production", "In Production") */
1845
1986
  status: string;
1846
1987
  /** Movie tagline/slogan, null if not available */
1847
- tagline: string | null;
1988
+ tagline?: string;
1848
1989
  /** Movie title (localized if language parameter was provided) */
1849
1990
  title: string;
1850
1991
  /** Whether a video is available on TMDB */
@@ -1917,13 +2058,13 @@ type MovieExternalIDs = {
1917
2058
  /** Movie identifier in TMDB */
1918
2059
  id: number;
1919
2060
  /** IMDb identifier (e.g., "tt0133093"), null if not available */
1920
- imdb_id?: string | null;
2061
+ imdb_id?: string;
1921
2062
  /** Facebook page identifier, null if not available */
1922
- facebook_id?: string | null;
2063
+ facebook_id?: string;
1923
2064
  /** Twitter/X handle, null if not available */
1924
- twitter_id?: string | null;
2065
+ twitter_id?: string;
1925
2066
  /** Instagram handle, null if not available */
1926
- instagram_id?: string | null;
2067
+ instagram_id?: string;
1927
2068
  };
1928
2069
  /**
1929
2070
  * Collection of movie images (backdrops, logos, posters)
@@ -2126,9 +2267,9 @@ type NetworkImages = ImagesResult<OrganizationImage, "logos">;
2126
2267
  */
2127
2268
  type Network = NetworkItem & {
2128
2269
  /** The city or location of the network's headquarters, if available. */
2129
- headquarters?: string | null;
2270
+ headquarters?: string;
2130
2271
  /** The URL of the network's official homepage, if available. */
2131
- homepage?: string | null;
2272
+ homepage?: string;
2132
2273
  };
2133
2274
  /**
2134
2275
  * Base parameters required by all network endpoints.
@@ -2145,7 +2286,7 @@ type NetworkBaseParams = {
2145
2286
  */
2146
2287
  type TVSeriesDetails = {
2147
2288
  /** The path to the backdrop image, or null if not available */
2148
- backdrop_path: string | null;
2289
+ backdrop_path?: string;
2149
2290
  /** Array of creators who developed the TV show */
2150
2291
  created_by: Pick<Credit, "id" | "credit_id" | "gender" | "name" | "profile_path">[];
2151
2292
  /** Array of typical episode runtimes in minutes */
@@ -2155,7 +2296,7 @@ type TVSeriesDetails = {
2155
2296
  /** Array of genres associated with the TV show */
2156
2297
  genres: Genre[];
2157
2298
  /** The official homepage URL for the TV show, or null if not available */
2158
- homepage: string | null;
2299
+ homepage?: string;
2159
2300
  /** The unique identifier for the TV show */
2160
2301
  id: number;
2161
2302
  /** Indicates whether the TV show is currently in production */
@@ -2165,7 +2306,7 @@ type TVSeriesDetails = {
2165
2306
  /** The date the most recent episode aired */
2166
2307
  last_air_date: string;
2167
2308
  /** Details of the last episode that aired, if available */
2168
- last_episode_to_air?: TVEpisodeItem | null;
2309
+ last_episode_to_air?: TVEpisodeItem;
2169
2310
  /** The title of the TV show */
2170
2311
  name: string;
2171
2312
  /** Details of the next episode to air, if available */
@@ -2183,11 +2324,11 @@ type TVSeriesDetails = {
2183
2324
  /** The original title of the TV show */
2184
2325
  original_name: string;
2185
2326
  /** A brief description or summary of the TV show, or null if not available */
2186
- overview: string | null;
2327
+ overview?: string;
2187
2328
  /** The popularity score of the TV show */
2188
2329
  popularity: number;
2189
2330
  /** The path to the poster image, or null if not available */
2190
- poster_path: string | null;
2331
+ poster_path?: string;
2191
2332
  /** Array of companies that produced the TV show */
2192
2333
  production_companies?: ProductionCompany[];
2193
2334
  /** Array of countries where the TV show was produced */
@@ -2217,19 +2358,19 @@ type TVEpisodeItem = {
2217
2358
  /** The total number of votes received for the episode */
2218
2359
  vote_count: number;
2219
2360
  /** The date the episode first aired */
2220
- air_date?: string | null;
2361
+ air_date?: string;
2221
2362
  /** The episode number within its season */
2222
2363
  episode_number: number;
2223
2364
  /** The production code used internally during filming */
2224
- production_code?: string | null;
2365
+ production_code?: string;
2225
2366
  /** The runtime of the episode in minutes */
2226
- runtime?: number | null;
2367
+ runtime?: number;
2227
2368
  /** The season number this episode belongs to */
2228
2369
  season_number: number;
2229
2370
  /** The unique identifier of the TV show this episode belongs to */
2230
2371
  show_id: number;
2231
2372
  /** The path to the episode's still image (screenshot) */
2232
- still_path?: string | null;
2373
+ still_path?: string;
2233
2374
  };
2234
2375
  type TVSeasonItem = {
2235
2376
  /** The date the season first aired, or null if not available */
@@ -2388,23 +2529,23 @@ type TVExternalIDs = {
2388
2529
  /** TV series identifier in TMDB */
2389
2530
  id: number;
2390
2531
  /** IMDb identifier (e.g., "tt0944947"), null if not available */
2391
- imdb_id?: string | null;
2532
+ imdb_id?: string;
2392
2533
  /** Freebase MID identifier (deprecated), null if not available */
2393
- freebase_mid?: string | null;
2534
+ freebase_mid?: string;
2394
2535
  /** Freebase ID (deprecated), null if not available */
2395
- freebase_id?: string | null;
2536
+ freebase_id?: string;
2396
2537
  /** TheTVDB identifier, null if not available */
2397
- tvdb_id?: number | null;
2538
+ tvdb_id?: number;
2398
2539
  /** TVRage identifier (service discontinued), null if not available */
2399
- tvrage_id?: number | null;
2540
+ tvrage_id?: number;
2400
2541
  /** Wikidata identifier (e.g., "Q23572"), null if not available */
2401
- wikidata_id?: string | null;
2542
+ wikidata_id?: string;
2402
2543
  /** Facebook page identifier, null if not available */
2403
- facebook_id?: string | null;
2544
+ facebook_id?: string;
2404
2545
  /** Instagram handle, null if not available */
2405
- instagram_id?: string | null;
2546
+ instagram_id?: string;
2406
2547
  /** Twitter/X handle, null if not available */
2407
- twitter_id?: string | null;
2548
+ twitter_id?: string;
2408
2549
  };
2409
2550
  /**
2410
2551
  * Images related to a TV show.
@@ -2614,7 +2755,7 @@ type TVSeasonEpisode = TVEpisodeItem & {
2614
2755
  */
2615
2756
  type TVSeason = {
2616
2757
  /** ISO 8601 date when the season first aired */
2617
- air_date?: string | null;
2758
+ air_date?: string;
2618
2759
  /** Array of episodes in this season */
2619
2760
  episodes: TVSeasonEpisode[];
2620
2761
  /** Unique TMDB identifier for the season */
@@ -2626,7 +2767,7 @@ type TVSeason = {
2626
2767
  /** Season overview/description */
2627
2768
  overview: string;
2628
2769
  /** Relative path to the season poster */
2629
- poster_path?: string | null;
2770
+ poster_path?: string;
2630
2771
  /** Season number within the TV show */
2631
2772
  season_number: number;
2632
2773
  /** Average user rating (0–10) */
@@ -2678,8 +2819,8 @@ type TVSeasonExternalIDs = Pick<TVExternalIDs, "id" | "freebase_mid" | "freebase
2678
2819
  type TVSeasonImages = ImagesResult<ImageItem, "posters">;
2679
2820
  /** Translation data for a TV season. */
2680
2821
  type TVSeasonTranslationData = {
2681
- name?: string | null;
2682
- overview?: string | null;
2822
+ name?: string;
2823
+ overview?: string;
2683
2824
  };
2684
2825
  /** Collection of all available translations for a TV season. */
2685
2826
  type TVSeasonTranslations = TranslationResults<TVSeasonTranslationData>;
@@ -2727,13 +2868,13 @@ type TVEpisode = {
2727
2868
  /** Unique TMDB identifier for this episode */
2728
2869
  id: number;
2729
2870
  /** Production code assigned by the production company, if available */
2730
- production_code?: string | null;
2871
+ production_code?: string;
2731
2872
  /** Runtime of the episode in minutes */
2732
2873
  runtime: number;
2733
2874
  /** Season number this episode belongs to (1-based) */
2734
2875
  season_number: number;
2735
2876
  /** Relative path to the episode still/image (e.g. `"/abc123.jpg"`), or null if none */
2736
- still_path?: string | null;
2877
+ still_path?: string;
2737
2878
  /** Average user rating of the episode (0-10 scale) */
2738
2879
  vote_average: number;
2739
2880
  /** Total number of user votes for the episode */
@@ -2771,8 +2912,8 @@ type TVEpisodeExternalIDs = Omit<TVExternalIDs, "facebook_id" | "instagram_id" |
2771
2912
  type TVEpisodeImages = ImagesResult<ImageItem, "stills">;
2772
2913
  type TVEpisodeTranslations = TranslationResults<TVEpisodeTranslationData>;
2773
2914
  type TVEpisodeTranslationData = {
2774
- name?: string | null;
2775
- overview?: string | null;
2915
+ name?: string;
2916
+ overview?: string;
2776
2917
  };
2777
2918
  type TVEpisodeVideos = VideoResults;
2778
2919
  /**
@@ -2817,7 +2958,7 @@ type Collection = {
2817
2958
  /** Short description or synopsis of the collection */
2818
2959
  overview: string;
2819
2960
  /** Relative path to the collection's poster image on TMDB, if available (sanitized nulls become undefined) */
2820
- poster_path?: string | null;
2961
+ poster_path?: string;
2821
2962
  /** Relative path to the collection's backdrop image on TMDB, if available (sanitized nulls become undefined) */
2822
2963
  backdrop_path?: string | null;
2823
2964
  /** Ordered list of media items that make up the collection */
@@ -2877,7 +3018,7 @@ type CompanySummary = {
2877
3018
  /** Unique company identifier */
2878
3019
  id: number;
2879
3020
  /** Relative path to the company logo */
2880
- logo_path?: string | null;
3021
+ logo_path?: string;
2881
3022
  /** Company display name */
2882
3023
  name: string;
2883
3024
  };
@@ -2892,9 +3033,9 @@ type Company = CompanySummary & {
2892
3033
  /** Company headquarters location */
2893
3034
  headquarters: string;
2894
3035
  /** Official company homepage */
2895
- homepage: string | null;
3036
+ homepage?: string;
2896
3037
  /** Parent company, if TMDB links one */
2897
- parent_company?: CompanySummary | null;
3038
+ parent_company?: CompanySummary;
2898
3039
  };
2899
3040
  /**
2900
3041
  * A single alternative company name entry.
@@ -2961,9 +3102,9 @@ type TVEpisodeGroupDetailsItem = {
2961
3102
  */
2962
3103
  type TVEpisodeGroupEpisode = Omit<TVEpisode, "guest_stars" | "runtime"> & {
2963
3104
  /** Production code for the episode, if available */
2964
- production_code?: string | null;
3105
+ production_code?: string;
2965
3106
  /** Path to the episode still image, if available */
2966
- still_path?: string | null;
3107
+ still_path?: string;
2967
3108
  };
2968
3109
  /**
2969
3110
  * Supported episode group type identifiers.
@@ -2998,11 +3139,11 @@ type FindByIDParams = {
2998
3139
  };
2999
3140
  type FindMediaResultBase = {
3000
3141
  adult: boolean;
3001
- backdrop_path: string | null;
3142
+ backdrop_path?: string;
3002
3143
  id: number;
3003
3144
  original_language: string;
3004
3145
  overview: string;
3005
- poster_path: string | null;
3146
+ poster_path?: string;
3006
3147
  popularity: number;
3007
3148
  vote_average: number;
3008
3149
  vote_count: number;
@@ -3022,14 +3163,14 @@ type FindMovieResultItem = FindMediaResultBase & {
3022
3163
  */
3023
3164
  type FindPersonResultItem = {
3024
3165
  adult: boolean;
3025
- gender: number | null;
3166
+ gender?: number;
3026
3167
  id: number;
3027
3168
  known_for_department: string;
3028
3169
  media_type: "person";
3029
3170
  name: string;
3030
3171
  original_name: string;
3031
3172
  popularity: number;
3032
- profile_path: string | null;
3173
+ profile_path?: string;
3033
3174
  };
3034
3175
  /**
3035
3176
  * TV series item returned inside `tv_results`.
@@ -3054,7 +3195,7 @@ type FindTVEpisodeResultItem = {
3054
3195
  production_code: string;
3055
3196
  season_number: number;
3056
3197
  show_id: number;
3057
- still_path: string | null;
3198
+ still_path?: string;
3058
3199
  vote_average: number;
3059
3200
  vote_count: number;
3060
3201
  };
@@ -3068,7 +3209,7 @@ type FindTVSeasonResultItem = {
3068
3209
  media_type: "tv_season";
3069
3210
  name: string;
3070
3211
  overview: string;
3071
- poster_path: string | null;
3212
+ poster_path?: string;
3072
3213
  season_number: number;
3073
3214
  };
3074
3215
  /**
@@ -3148,7 +3289,7 @@ type CreditDetailsMediaBase = {
3148
3289
  /** Indicates whether the title is marked for adult content. */
3149
3290
  adult: boolean;
3150
3291
  /** Relative path to the backdrop image, if available. */
3151
- backdrop_path?: string | null;
3292
+ backdrop_path?: string;
3152
3293
  /** Character name when the credit belongs to cast. */
3153
3294
  character?: string;
3154
3295
  /** Genre identifiers attached to the media item. */
@@ -3160,7 +3301,7 @@ type CreditDetailsMediaBase = {
3160
3301
  /** Plot summary. */
3161
3302
  overview: string;
3162
3303
  /** Relative path to the poster image, if available. */
3163
- poster_path?: string | null;
3304
+ poster_path?: string;
3164
3305
  /** Popularity score. */
3165
3306
  popularity: number;
3166
3307
  /** Average vote score. */
@@ -3190,7 +3331,7 @@ type CreditDetailsTVEpisode = {
3190
3331
  /** Indicates whether the episode is marked for adult content. */
3191
3332
  adult: boolean;
3192
3333
  /** Episode air date in ISO 8601 format, if available. */
3193
- air_date?: string | null;
3334
+ air_date?: string;
3194
3335
  /** Episode number within the season. */
3195
3336
  episode_number: number;
3196
3337
  /** Episode type reported by TMDB. */
@@ -3204,11 +3345,11 @@ type CreditDetailsTVEpisode = {
3204
3345
  /** Production code if available. */
3205
3346
  production_code: string;
3206
3347
  /** Runtime in minutes, if available. */
3207
- runtime?: number | null;
3348
+ runtime?: number;
3208
3349
  /** Season number for the episode. */
3209
3350
  season_number: number;
3210
3351
  /** Episode still image path, if available. */
3211
- still_path?: string | null;
3352
+ still_path?: string;
3212
3353
  /** Average vote score. */
3213
3354
  vote_average: number;
3214
3355
  /** Total vote count. */
@@ -3219,7 +3360,7 @@ type CreditDetailsTVEpisode = {
3219
3360
  */
3220
3361
  type CreditDetailsTVSeason = {
3221
3362
  /** Season air date in ISO 8601 format, if available. */
3222
- air_date?: string | null;
3363
+ air_date?: string;
3223
3364
  /** Total number of episodes in the season. */
3224
3365
  episode_count: number;
3225
3366
  /** Unique season identifier. */
@@ -3229,7 +3370,7 @@ type CreditDetailsTVSeason = {
3229
3370
  /** Plot summary. */
3230
3371
  overview: string;
3231
3372
  /** Relative path to the season poster, if available. */
3232
- poster_path?: string | null;
3373
+ poster_path?: string;
3233
3374
  /** Season number within the series. */
3234
3375
  season_number: number;
3235
3376
  /** Average vote score. */
@@ -3529,9 +3670,19 @@ declare class ApiClient {
3529
3670
  */
3530
3671
  private inflightRequests;
3531
3672
  private deduplication;
3673
+ private requestInterceptors;
3674
+ private onSuccessInterceptor?;
3675
+ private onErrorInterceptor?;
3532
3676
  constructor(accessToken: string, options?: {
3533
3677
  logger?: boolean | TMDBLoggerFn;
3534
3678
  deduplication?: boolean;
3679
+ interceptors?: {
3680
+ request?: RequestInterceptor | RequestInterceptor[];
3681
+ response?: {
3682
+ onSuccess?: ResponseSuccessInterceptor;
3683
+ onError?: ResponseErrorInterceptor;
3684
+ };
3685
+ };
3535
3686
  });
3536
3687
  /**
3537
3688
  * Builds a stable, order-independent cache key for a request.
@@ -3541,6 +3692,11 @@ declare class ApiClient {
3541
3692
  * `{ language, page }` and `{ page, language }` produce the same key.
3542
3693
  */
3543
3694
  private buildRequestKey;
3695
+ /**
3696
+ * Serializes request params once so URL construction and deduplication keys stay aligned.
3697
+ * `undefined` values are intentionally skipped because they are not sent to TMDB.
3698
+ */
3699
+ private serializeParams;
3544
3700
  /**
3545
3701
  * Makes an authenticated GET request to the TMDB API, returning the parsed and
3546
3702
  * null-sanitised response.
@@ -3553,6 +3709,11 @@ declare class ApiClient {
3553
3709
  * `TMDBOptions.deduplication = false`.
3554
3710
  */
3555
3711
  request<T>(endpoint: string, params?: Record<string, unknown | undefined>): Promise<T>;
3712
+ /**
3713
+ * Runs all registered request interceptors in order, threading the context through each one.
3714
+ * If an interceptor returns a new context, it replaces the current context for the next interceptor.
3715
+ */
3716
+ private runRequestInterceptors;
3556
3717
  /**
3557
3718
  * The actual fetch + response-parsing pipeline. Called by `request()` only when no
3558
3719
  * matching in-flight promise exists. Handles URL construction, auth headers, logging,
@@ -5048,40 +5209,27 @@ declare class TMDB {
5048
5209
  constructor(accessToken: string, options?: TMDBOptions);
5049
5210
  }
5050
5211
 
5051
- /**
5052
- * Represents a generic error or an error specific to the TMDB (The Movie Database) API.
5053
- * This error class extends the built-in `Error` class and includes additional
5054
- * properties to provide more context about the error.
5055
- */
5056
- declare class TMDBError extends Error {
5057
- /**
5058
- * The status code returned by the TMDB API.
5059
- * If the value is `-1`, it indicates a library-specific error rather than a TMDB API error.
5060
- * @reference https://developer.themoviedb.org/docs/errors - code
5061
- */
5062
- tmdb_status_code: number;
5063
- /**
5064
- * A descriptive message providing details about the error.
5065
- * If the error is specific to the TMDB API, this message will be derived from the API response
5066
- * @reference https://developer.themoviedb.org/docs/errors - message
5067
- */
5068
- message: string;
5069
- /**
5070
- * The HTTP status code associated with the error.
5071
- * If the error is specific to the TMDB API, this code will be derived from the API response.
5072
- * @reference https://developer.themoviedb.org/docs/errors - HTTP Status
5073
- */
5074
- http_status_code: number;
5075
- /**
5076
- * Creates an instance of `TMDBError`.
5077
- *
5078
- * @param message - A descriptive message providing details about the error.
5079
- * @param http_status - The HTTP status code associated with the error.
5080
- * @param tmdb_status_code - (Optional) The status code returned by the TMDB API. Defaults to `-1` for library-specific errors.
5081
- */
5082
- constructor(message: string, http_status: number, tmdb_status_code?: number);
5083
- }
5084
-
5085
5212
  declare function isJwt(token: string): boolean;
5086
5213
 
5087
- export { type AlternativeName, type AlternativeNamesResult, type AlternativeTitle, BACKDROP_SIZES, type BackdropSize, type Cast, type CertificationItem, type Certifications, type Change, type ChangeItem, type ChangeResultItem, type Changes, type Collection, type CollectionBaseParam, type CollectionDetailsParams, type CollectionImages, type CollectionImagesParams, type CollectionItem, type CollectionResultItem, type CollectionTranslationData, type CollectionTranslations, type Company, type CompanyAlternativeName, type CompanyAlternativeNames, type CompanyAlternativeNamesParams, type CompanyBaseParam, type CompanyDetailsParams, type CompanyImages, type CompanyImagesParams, type CompanyResultItem, type CompanySummary, type ConfigurationCountriesParams, type ConfigurationCountry, type ConfigurationJob, type ConfigurationLanguage, type ConfigurationResponse, type ConfigurationTimezone, type ContentRating, type CountryISO3166_1, type Credit, type CreditBaseParam, type CreditDetails, type CreditDetailsMedia, type CreditDetailsMovieMedia, type CreditDetailsParams, type CreditDetailsPerson, type CreditDetailsTVEpisode, type CreditDetailsTVMedia, type CreditDetailsTVSeason, type Crew, type DateRange, type DefaultImageSizesConfig, type DiscoverFilterExpression, type DiscoverMovieParams, type DiscoverMovieSortBy, type DiscoverTVParams, type DiscoverTVResultItem, type DiscoverTVSortBy, DiscoverTVStatus, DiscoverTVType, type FileType, type FindByIDParams, type FindExternalSource, type FindMovieResultItem, type FindPersonResultItem, type FindResults, type FindTVEpisodeResultItem, type FindTVResultItem, type FindTVSeasonResultItem, type Genre, type GenresResponse, IMAGE_BASE_URL, IMAGE_SECURE_BASE_URL, type ImageCollectionKey, type ImageConfiguration, type ImageItem, type ImageSize, type ImageSizeTypes, type ImagesConfig, type ImagesResult, type Keyword, type KeywordBaseParam, type KeywordDetailsParams, type KeywordMoviesParams, type KeywordResultItem, type KnownForItem, type KnownForMovie, type KnownForTV, LOGO_SIZES, type Language, type LanguageISO6391, type LiteralUnion, type LogoSize, type MediaType, type MediaWatchProviders, type MovieAlternativeTitles, type MovieAlternativeTitlesParams, type MovieAppendToResponseNamespace, type MovieAppendableMap, type MovieChanges, type MovieChangesParams, type MovieCollection, type MovieCredits, type MovieCreditsParams, type MovieDetails, type MovieDetailsParams, type MovieDetailsWithAppends, type MovieExternalIDs, type MovieExternalIDsParams, type MovieImages, type MovieImagesParams, type MovieKeywords, type MovieKeywordsParams, type MovieListParams, type MovieRecommendations, type MovieRecommendationsParams, type MovieReleaseDate, type MovieReleaseDateResult, type MovieReleaseDates, type MovieReleaseDatesParams, type MovieResultItem, type MovieReviews, type MovieReviewsParams, type MovieSimilar, type MovieSimilarParams, type MovieTranslationData, type MovieTranslations, type MovieTranslationsParams, type MovieVideos, type MovieVideosParams, type MovieWatchProvidersParams, type MultiSearchResultItem, type Network, type NetworkBaseParams, type NetworkImages, type NetworkItem, type OrganizationImage, POSTER_SIZES, PROFILE_SIZES, type PaginatedResponse, type PeopleListParams, type PersonAppendToResponseNamespace, type PersonAppendableMap, type PersonBaseParam, type PersonChanges, type PersonChangesParams, type PersonCombinedCastCredit, type PersonCombinedCredits, type PersonCombinedCrewCredit, type PersonCreditsParams, type PersonDetails, type PersonDetailsParams, type PersonDetailsWithAppends, type PersonExternalIDs, type PersonExternalIDsParams, type PersonImages, type PersonImagesParams, type PersonMovieCastCredit, type PersonMovieCredits, type PersonMovieCrewCredit, type PersonResultItem, type PersonTVCastCredit, type PersonTVCredits, type PersonTVCrewCredit, type PersonTaggedImage, type PersonTaggedImageMedia, type PersonTaggedImages, type PersonTaggedImagesParams, type PersonTranslationData, type PersonTranslations, type PersonTranslationsParams, type PosterSize, type Prettify, type PrimaryTranslations, type ProductionCompany, type ProductionCountry, type ProfileSize, type Review, type ReviewAuthorDetails, type ReviewDetails, type ReviewDetailsParams, STILL_SIZES, type SearchCollectionsParams, type SearchCompanyParams, type SearchKeywordsParams, type SearchMoviesParams, type SearchMultiParams, type SearchPersonParams, type SearchTVSeriesParams, type SpokenLanguage, type StillSize, TMDB, TMDBCountries, TMDBError, TMDBLogger, type TMDBLoggerEntry, type TMDBLoggerFn, type TMDBOptions, type TMDBQueryParams, type TVAggregateCredits, type TVAggregateCreditsCastItem, type TVAggregateCreditsCrewItem, type TVAggregateCreditsParams, type TVAlternativeTitles, type TVAppendToResponseNamespace, type TVAppendableMap, type TVBaseParam, type TVChangeParams, type TVContentRatings, type TVCreditJob, type TVCreditRole, type TVCredits, type TVCreditsParams, type TVDetailsParams, type TVDetailsWithAppends, type TVEpisode, type TVEpisodeAppendToResponseNamespace, type TVEpisodeAppendableMap, type TVEpisodeBaseParams, type TVEpisodeCredits, type TVEpisodeCreditsParams, type TVEpisodeDetailsParams, type TVEpisodeDetailsWithAppends, type TVEpisodeExternalIDs, type TVEpisodeGroupDetails, type TVEpisodeGroupDetailsItem, type TVEpisodeGroupEpisode, type TVEpisodeGroupItem, type TVEpisodeGroupParams, TVEpisodeGroupType, type TVEpisodeGroups, type TVEpisodeId, type TVEpisodeImages, type TVEpisodeImagesParams, type TVEpisodeItem, type TVEpisodeTranslationData, type TVEpisodeTranslations, type TVEpisodeVideos, type TVExternalIDs, type TVImageItem, type TVImages, type TVImagesParams, type TVKeywords, type TVRecommendations, type TVRecommendationsParams, type TVReviews, type TVReviewsParams, type TVScreenedTheatrically, type TVScreeningItem, type TVSeason, type TVSeasonAggregateCredits, type TVSeasonAggregateCreditsParams, type TVSeasonAppendToResponseNamespace, type TVSeasonAppendableMap, type TVSeasonBaseParams, type TVSeasonChanges, type TVSeasonChangesParams, type TVSeasonCredits, type TVSeasonCreditsParams, type TVSeasonDetailsParams, type TVSeasonDetailsWithAppends, type TVSeasonEpisode, type TVSeasonExternalIDs, type TVSeasonId, type TVSeasonImages, type TVSeasonImagesParams, type TVSeasonItem, type TVSeasonTranslationData, type TVSeasonTranslations, type TVSeasonVideos, type TVSeasonVideosParams, type TVSeasonWatchProvidersParams, type TVSeriesChanges, type TVSeriesDetails, type TVSeriesListItem, type TVSeriesListParams, type TVSeriesLists, type TVSeriesListsParams, type TVSeriesResultItem, type TVSimilar, type TVSimilarParams, type TVTranslationData, type TVTranslations, type TVVideos, type Timezone, type Translation, type TranslationResults, type TrendingAllResult, type TrendingMovieResult, type TrendingParams, type TrendingPersonResult, type TrendingTVResult, type TrendingTimeWindow, type VideoItem, type VideoResults, type WatchMonetizationType, type WatchProvider, type WatchProviderDisplayPriorities, type WatchProviderItem, type WatchProviderListItem, type WatchProviderListParams, type WatchProviderListResponse, type WatchProviderRegionsParams, type WatchProviderRegionsResponse, type WithLanguage, type WithLanguagePage, type WithPage, type WithPageAndDateRange, type WithParams, type WithRegion, isJwt, isKnownForMovie, isKnownForTV };
5214
+ /** Utility type guard to check if an object has a poster_path property */
5215
+ declare function hasPosterPath(data: unknown): data is {
5216
+ poster_path: string;
5217
+ };
5218
+ /** Utility type guard to check if an object has a backdrop_path property */
5219
+ declare function hasBackdropPath(data: unknown): data is {
5220
+ backdrop_path: string;
5221
+ };
5222
+ /** Utility type guard to check if an object has a profile_path property */
5223
+ declare function hasProfilePath(data: unknown): data is {
5224
+ profile_path: string;
5225
+ };
5226
+ /** Utility type guard to check if an object has a still_path property */
5227
+ declare function hasStillPath(data: unknown): data is {
5228
+ still_path: string;
5229
+ };
5230
+ /** Utility type guard to check if an object has a logo_path property */
5231
+ declare function hasLogoPath(data: unknown): data is {
5232
+ logo_path: string;
5233
+ };
5234
+
5235
+ export { type AlternativeName, type AlternativeNamesResult, type AlternativeTitle, BACKDROP_SIZES, type BackdropSize, type Cast, type CertificationItem, type Certifications, type Change, type ChangeItem, type ChangeResultItem, type Changes, type Collection, type CollectionBaseParam, type CollectionDetailsParams, type CollectionImages, type CollectionImagesParams, type CollectionItem, type CollectionResultItem, type CollectionTranslationData, type CollectionTranslations, type Company, type CompanyAlternativeName, type CompanyAlternativeNames, type CompanyAlternativeNamesParams, type CompanyBaseParam, type CompanyDetailsParams, type CompanyImages, type CompanyImagesParams, type CompanyResultItem, type CompanySummary, type ConfigurationCountriesParams, type ConfigurationCountry, type ConfigurationJob, type ConfigurationLanguage, type ConfigurationResponse, type ConfigurationTimezone, type ContentRating, type CountryISO3166_1, type Credit, type CreditBaseParam, type CreditDetails, type CreditDetailsMedia, type CreditDetailsMovieMedia, type CreditDetailsParams, type CreditDetailsPerson, type CreditDetailsTVEpisode, type CreditDetailsTVMedia, type CreditDetailsTVSeason, type Crew, type DateRange, type DefaultImageSizesConfig, type DiscoverFilterExpression, type DiscoverMovieParams, type DiscoverMovieSortBy, type DiscoverTVParams, type DiscoverTVResultItem, type DiscoverTVSortBy, DiscoverTVStatus, DiscoverTVType, type FileType, type FindByIDParams, type FindExternalSource, type FindMovieResultItem, type FindPersonResultItem, type FindResults, type FindTVEpisodeResultItem, type FindTVResultItem, type FindTVSeasonResultItem, type Genre, type GenresResponse, IMAGE_BASE_URL, IMAGE_SECURE_BASE_URL, type ImageCollectionKey, type ImageConfiguration, type ImageItem, type ImageSize, type ImageSizeTypes, type ImagesConfig, type ImagesResult, type Keyword, type KeywordBaseParam, type KeywordDetailsParams, type KeywordMoviesParams, type KeywordResultItem, type KnownForItem, type KnownForMovie, type KnownForTV, LOGO_SIZES, type Language, type LanguageISO6391, type LiteralUnion, type LogoSize, type MediaType, type MediaWatchProviders, type MovieAlternativeTitles, type MovieAlternativeTitlesParams, type MovieAppendToResponseNamespace, type MovieAppendableMap, type MovieChanges, type MovieChangesParams, type MovieCollection, type MovieCredits, type MovieCreditsParams, type MovieDetails, type MovieDetailsParams, type MovieDetailsWithAppends, type MovieExternalIDs, type MovieExternalIDsParams, type MovieImages, type MovieImagesParams, type MovieKeywords, type MovieKeywordsParams, type MovieListParams, type MovieRecommendations, type MovieRecommendationsParams, type MovieReleaseDate, type MovieReleaseDateResult, type MovieReleaseDates, type MovieReleaseDatesParams, type MovieResultItem, type MovieReviews, type MovieReviewsParams, type MovieSimilar, type MovieSimilarParams, type MovieTranslationData, type MovieTranslations, type MovieTranslationsParams, type MovieVideos, type MovieVideosParams, type MovieWatchProvidersParams, type MultiSearchResultItem, type Network, type NetworkBaseParams, type NetworkImages, type NetworkItem, type OrganizationImage, POSTER_SIZES, PROFILE_SIZES, type PaginatedResponse, type PeopleListParams, type PersonAppendToResponseNamespace, type PersonAppendableMap, type PersonBaseParam, type PersonChanges, type PersonChangesParams, type PersonCombinedCastCredit, type PersonCombinedCredits, type PersonCombinedCrewCredit, type PersonCreditsParams, type PersonDetails, type PersonDetailsParams, type PersonDetailsWithAppends, type PersonExternalIDs, type PersonExternalIDsParams, type PersonImages, type PersonImagesParams, type PersonMovieCastCredit, type PersonMovieCredits, type PersonMovieCrewCredit, type PersonResultItem, type PersonTVCastCredit, type PersonTVCredits, type PersonTVCrewCredit, type PersonTaggedImage, type PersonTaggedImageMedia, type PersonTaggedImages, type PersonTaggedImagesParams, type PersonTranslationData, type PersonTranslations, type PersonTranslationsParams, type PosterSize, type Prettify, type PrimaryTranslations, type ProductionCompany, type ProductionCountry, type ProfileSize, type RequestInterceptor, type RequestInterceptorContext, type ResponseErrorInterceptor, type ResponseSuccessInterceptor, type Review, type ReviewAuthorDetails, type ReviewDetails, type ReviewDetailsParams, STILL_SIZES, type SearchCollectionsParams, type SearchCompanyParams, type SearchKeywordsParams, type SearchMoviesParams, type SearchMultiParams, type SearchPersonParams, type SearchTVSeriesParams, type SpokenLanguage, type StillSize, TMDB, TMDBCountries, TMDBError, TMDBLogger, type TMDBLoggerEntry, type TMDBLoggerFn, type TMDBOptions, type TMDBQueryParams, type TVAggregateCredits, type TVAggregateCreditsCastItem, type TVAggregateCreditsCrewItem, type TVAggregateCreditsParams, type TVAlternativeTitles, type TVAppendToResponseNamespace, type TVAppendableMap, type TVBaseParam, type TVChangeParams, type TVContentRatings, type TVCreditJob, type TVCreditRole, type TVCredits, type TVCreditsParams, type TVDetailsParams, type TVDetailsWithAppends, type TVEpisode, type TVEpisodeAppendToResponseNamespace, type TVEpisodeAppendableMap, type TVEpisodeBaseParams, type TVEpisodeCredits, type TVEpisodeCreditsParams, type TVEpisodeDetailsParams, type TVEpisodeDetailsWithAppends, type TVEpisodeExternalIDs, type TVEpisodeGroupDetails, type TVEpisodeGroupDetailsItem, type TVEpisodeGroupEpisode, type TVEpisodeGroupItem, type TVEpisodeGroupParams, TVEpisodeGroupType, type TVEpisodeGroups, type TVEpisodeId, type TVEpisodeImages, type TVEpisodeImagesParams, type TVEpisodeItem, type TVEpisodeTranslationData, type TVEpisodeTranslations, type TVEpisodeVideos, type TVExternalIDs, type TVImageItem, type TVImages, type TVImagesParams, type TVKeywords, type TVRecommendations, type TVRecommendationsParams, type TVReviews, type TVReviewsParams, type TVScreenedTheatrically, type TVScreeningItem, type TVSeason, type TVSeasonAggregateCredits, type TVSeasonAggregateCreditsParams, type TVSeasonAppendToResponseNamespace, type TVSeasonAppendableMap, type TVSeasonBaseParams, type TVSeasonChanges, type TVSeasonChangesParams, type TVSeasonCredits, type TVSeasonCreditsParams, type TVSeasonDetailsParams, type TVSeasonDetailsWithAppends, type TVSeasonEpisode, type TVSeasonExternalIDs, type TVSeasonId, type TVSeasonImages, type TVSeasonImagesParams, type TVSeasonItem, type TVSeasonTranslationData, type TVSeasonTranslations, type TVSeasonVideos, type TVSeasonVideosParams, type TVSeasonWatchProvidersParams, type TVSeriesChanges, type TVSeriesDetails, type TVSeriesListItem, type TVSeriesListParams, type TVSeriesLists, type TVSeriesListsParams, type TVSeriesResultItem, type TVSimilar, type TVSimilarParams, type TVTranslationData, type TVTranslations, type TVVideos, type Timezone, type Translation, type TranslationResults, type TrendingAllResult, type TrendingMovieResult, type TrendingParams, type TrendingPersonResult, type TrendingTVResult, type TrendingTimeWindow, type VideoItem, type VideoResults, type WatchMonetizationType, type WatchProvider, type WatchProviderDisplayPriorities, type WatchProviderItem, type WatchProviderListItem, type WatchProviderListParams, type WatchProviderListResponse, type WatchProviderRegionsParams, type WatchProviderRegionsResponse, type WithLanguage, type WithLanguagePage, type WithPage, type WithPageAndDateRange, type WithParams, type WithRegion, hasBackdropPath, hasLogoPath, hasPosterPath, hasProfilePath, hasStillPath, isJwt, isKnownForMovie, isKnownForTV };
package/dist/index.js CHANGED
@@ -126,6 +126,23 @@ function isJwt(token) {
126
126
  return true;
127
127
  }
128
128
 
129
+ // src/utils/index.ts
130
+ function hasPosterPath(data) {
131
+ return typeof data === "object" && data !== null && "poster_path" in data && typeof data.poster_path === "string";
132
+ }
133
+ function hasBackdropPath(data) {
134
+ return typeof data === "object" && data !== null && "backdrop_path" in data && typeof data.backdrop_path === "string";
135
+ }
136
+ function hasProfilePath(data) {
137
+ return typeof data === "object" && data !== null && "profile_path" in data && typeof data.profile_path === "string";
138
+ }
139
+ function hasStillPath(data) {
140
+ return typeof data === "object" && data !== null && "still_path" in data && typeof data.still_path === "string";
141
+ }
142
+ function hasLogoPath(data) {
143
+ return typeof data === "object" && data !== null && "logo_path" in data && typeof data.logo_path === "string";
144
+ }
145
+
129
146
  // src/client.ts
130
147
  var ApiClient = class {
131
148
  accessToken;
@@ -139,10 +156,17 @@ var ApiClient = class {
139
156
  */
140
157
  inflightRequests = /* @__PURE__ */ new Map();
141
158
  deduplication;
159
+ requestInterceptors;
160
+ onSuccessInterceptor;
161
+ onErrorInterceptor;
142
162
  constructor(accessToken, options = {}) {
143
163
  this.accessToken = accessToken;
144
164
  this.logger = TMDBLogger.from(options.logger);
145
165
  this.deduplication = options.deduplication !== false;
166
+ const raw = options.interceptors?.request;
167
+ this.requestInterceptors = raw == null ? [] : Array.isArray(raw) ? raw : [raw];
168
+ this.onSuccessInterceptor = options.interceptors?.response?.onSuccess;
169
+ this.onErrorInterceptor = options.interceptors?.response?.onError;
146
170
  }
147
171
  /**
148
172
  * Builds a stable, order-independent cache key for a request.
@@ -152,9 +176,19 @@ var ApiClient = class {
152
176
  * `{ language, page }` and `{ page, language }` produce the same key.
153
177
  */
154
178
  buildRequestKey(endpoint, params) {
155
- const definedEntries = Object.entries(params).filter(([, v]) => v !== void 0).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => `${k}=${String(v)}`);
179
+ const definedEntries = this.serializeParams(params).sort(([a], [b]) => a.localeCompare(b)).map(([key, value]) => `${key}=${value}`);
156
180
  return definedEntries.length > 0 ? `${endpoint}?${definedEntries.join("&")}` : endpoint;
157
181
  }
182
+ /**
183
+ * Serializes request params once so URL construction and deduplication keys stay aligned.
184
+ * `undefined` values are intentionally skipped because they are not sent to TMDB.
185
+ */
186
+ serializeParams(params) {
187
+ return Object.entries(params).flatMap(([key, value]) => {
188
+ if (value === void 0) return [];
189
+ return [[key, String(value)]];
190
+ });
191
+ }
158
192
  /**
159
193
  * Makes an authenticated GET request to the TMDB API, returning the parsed and
160
194
  * null-sanitised response.
@@ -177,17 +211,31 @@ var ApiClient = class {
177
211
  this.inflightRequests.set(key, promise);
178
212
  return promise;
179
213
  }
214
+ /**
215
+ * Runs all registered request interceptors in order, threading the context through each one.
216
+ * If an interceptor returns a new context, it replaces the current context for the next interceptor.
217
+ */
218
+ async runRequestInterceptors(context) {
219
+ let current = context;
220
+ for (const interceptor of this.requestInterceptors) {
221
+ const result = await interceptor(current);
222
+ if (result != null) current = result;
223
+ }
224
+ return current;
225
+ }
180
226
  /**
181
227
  * The actual fetch + response-parsing pipeline. Called by `request()` only when no
182
228
  * matching in-flight promise exists. Handles URL construction, auth headers, logging,
183
229
  * error mapping, and null sanitisation.
184
230
  */
185
231
  async doRequest(endpoint, params) {
232
+ const ctx = await this.runRequestInterceptors({ endpoint, params, method: "GET" });
233
+ endpoint = ctx.endpoint;
234
+ params = ctx.params;
186
235
  const url = new URL(`${this.baseUrl}${endpoint}`);
187
236
  const jwt = isJwt(this.accessToken);
188
- for (const [key, value] of Object.entries(params)) {
189
- if (value === void 0) continue;
190
- url.searchParams.append(key, String(value));
237
+ for (const [key, value] of this.serializeParams(params)) {
238
+ url.searchParams.append(key, value);
191
239
  }
192
240
  if (!jwt) {
193
241
  url.searchParams.append("api_key", this.accessToken);
@@ -218,7 +266,12 @@ var ApiClient = class {
218
266
  });
219
267
  throw error;
220
268
  }
221
- if (!res.ok) await this.handleError(res, endpoint);
269
+ if (!res.ok) {
270
+ await this.handleError(res, endpoint).catch(async (err) => {
271
+ if (this.onErrorInterceptor) await this.onErrorInterceptor(err);
272
+ throw err;
273
+ });
274
+ }
222
275
  this.logger?.log({
223
276
  type: "response",
224
277
  method: "GET",
@@ -228,7 +281,12 @@ var ApiClient = class {
228
281
  durationMs: Date.now() - startedAt
229
282
  });
230
283
  const data = await res.json();
231
- return this.sanitizeNulls(data);
284
+ const sanitized = this.sanitizeNulls(data);
285
+ if (this.onSuccessInterceptor) {
286
+ const result = await this.onSuccessInterceptor(sanitized);
287
+ return result !== void 0 ? result : sanitized;
288
+ }
289
+ return sanitized;
232
290
  }
233
291
  /**
234
292
  * Recursively converts null values to undefined in API responses.
@@ -554,7 +612,7 @@ var CompaniesAPI = class extends TMDBAPIBase {
554
612
  */
555
613
  async details(params) {
556
614
  const endpoint = this.companyPath(params.company_id);
557
- return this.client.request(endpoint, params);
615
+ return this.client.request(endpoint);
558
616
  }
559
617
  /**
560
618
  * Alternative names
@@ -567,7 +625,7 @@ var CompaniesAPI = class extends TMDBAPIBase {
567
625
  */
568
626
  async alternative_names(params) {
569
627
  const endpoint = `${this.companyPath(params.company_id)}${ENDPOINTS.COMPANIES.ALTERNATIVE_NAMES}`;
570
- return this.client.request(endpoint, params);
628
+ return this.client.request(endpoint);
571
629
  }
572
630
  /**
573
631
  * Images
@@ -581,9 +639,9 @@ var CompaniesAPI = class extends TMDBAPIBase {
581
639
  * @reference https://developer.themoviedb.org/reference/company-images
582
640
  */
583
641
  async images(params) {
584
- const endpoint = `${this.companyPath(params.company_id)}${ENDPOINTS.COMPANIES.IMAGES}`;
585
- const requestParams = this.withLanguage(params) ?? params;
586
- return this.client.request(endpoint, requestParams);
642
+ const { company_id, ...rest } = params;
643
+ const endpoint = `${this.companyPath(company_id)}${ENDPOINTS.COMPANIES.IMAGES}`;
644
+ return this.client.request(endpoint, this.withLanguage(rest));
587
645
  }
588
646
  };
589
647
 
@@ -603,9 +661,9 @@ var CreditsAPI = class extends TMDBAPIBase {
603
661
  * @reference https://developer.themoviedb.org/reference/credit-details
604
662
  */
605
663
  async details(params) {
606
- const endpoint = this.creditPath(params.credit_id);
607
- const requestParams = this.withLanguage(params) ?? params;
608
- return this.client.request(endpoint, requestParams);
664
+ const { credit_id, ...rest } = params;
665
+ const endpoint = this.creditPath(credit_id);
666
+ return this.client.request(endpoint, this.withLanguage(rest));
609
667
  }
610
668
  };
611
669
 
@@ -625,9 +683,9 @@ var CollectionsAPI = class extends TMDBAPIBase {
625
683
  * @reference https://developer.themoviedb.org/reference/collection-details
626
684
  */
627
685
  async details(params) {
628
- const { language = this.defaultOptions.language, ...rest } = params;
629
- const endpoint = this.collectionPath(params.collection_id);
630
- return this.client.request(endpoint, { language, ...rest });
686
+ const { language = this.defaultOptions.language, collection_id } = params;
687
+ const endpoint = this.collectionPath(collection_id);
688
+ return this.client.request(endpoint, { language });
631
689
  }
632
690
  /**
633
691
  * Images
@@ -642,9 +700,9 @@ var CollectionsAPI = class extends TMDBAPIBase {
642
700
  * @reference https://developer.themoviedb.org/reference/collection-images
643
701
  */
644
702
  async images(params) {
645
- const endpoint = `${this.collectionPath(params.collection_id)}${ENDPOINTS.COLLECTIONS.IMAGES}`;
646
- const requestParams = this.withLanguage(params) ?? params;
647
- return this.client.request(endpoint, requestParams);
703
+ const { collection_id, ...rest } = params;
704
+ const endpoint = `${this.collectionPath(collection_id)}${ENDPOINTS.COLLECTIONS.IMAGES}`;
705
+ return this.client.request(endpoint, this.withLanguage(rest));
648
706
  }
649
707
  /**
650
708
  * Translations
@@ -657,7 +715,7 @@ var CollectionsAPI = class extends TMDBAPIBase {
657
715
  */
658
716
  async translations(params) {
659
717
  const endpoint = `${this.collectionPath(params.collection_id)}${ENDPOINTS.COLLECTIONS.TRANSLATIONS}`;
660
- return this.client.request(endpoint, params);
718
+ return this.client.request(endpoint);
661
719
  }
662
720
  };
663
721
 
@@ -869,7 +927,7 @@ var KeywordsAPI = class extends TMDBAPIBase {
869
927
  */
870
928
  async details(params) {
871
929
  const endpoint = this.keywordPath(params.keyword_id);
872
- return this.client.request(endpoint, params);
930
+ return this.client.request(endpoint);
873
931
  }
874
932
  /**
875
933
  * Movies
@@ -885,8 +943,9 @@ var KeywordsAPI = class extends TMDBAPIBase {
885
943
  * @reference https://developer.themoviedb.org/reference/keyword-movies
886
944
  */
887
945
  async movies(params) {
888
- const endpoint = `${this.keywordPath(params.keyword_id)}${ENDPOINTS.KEYWORDS.MOVIES}`;
889
- const requestParams = this.withLanguage(params);
946
+ const { keyword_id, ...rest } = params;
947
+ const endpoint = `${this.keywordPath(keyword_id)}${ENDPOINTS.KEYWORDS.MOVIES}`;
948
+ const requestParams = this.withLanguage(rest);
890
949
  return this.client.request(endpoint, requestParams);
891
950
  }
892
951
  };
@@ -976,9 +1035,9 @@ var MoviesAPI = class extends TMDBAPIBase {
976
1035
  * @reference https://developer.themoviedb.org/reference/movie-details
977
1036
  */
978
1037
  async details(params) {
979
- const { language = this.defaultOptions.language, ...rest } = params;
980
- const endpoint = this.moviePath(params.movie_id);
981
- return this.client.request(endpoint, { language, ...rest });
1038
+ const { language = this.defaultOptions.language, movie_id, append_to_response } = params;
1039
+ const endpoint = this.moviePath(movie_id);
1040
+ return this.client.request(endpoint, { language, append_to_response });
982
1041
  }
983
1042
  /**
984
1043
  * Alternative Titles
@@ -991,8 +1050,9 @@ var MoviesAPI = class extends TMDBAPIBase {
991
1050
  * @reference https://developer.themoviedb.org/reference/movie-alternative-titles
992
1051
  */
993
1052
  async alternative_titles(params) {
994
- const endpoint = this.movieSubPath(params.movie_id, ENDPOINTS.MOVIES.ALTERNATIVE_TITLES);
995
- return this.client.request(endpoint, params);
1053
+ const { movie_id, ...rest } = params;
1054
+ const endpoint = this.movieSubPath(movie_id, ENDPOINTS.MOVIES.ALTERNATIVE_TITLES);
1055
+ return this.client.request(endpoint, rest);
996
1056
  }
997
1057
  /**
998
1058
  * Credits
@@ -1053,8 +1113,9 @@ var MoviesAPI = class extends TMDBAPIBase {
1053
1113
  * @reference https://developer.themoviedb.org/reference/movie-changes
1054
1114
  */
1055
1115
  async changes(params) {
1056
- const endpoint = this.movieSubPath(params.movie_id, ENDPOINTS.MOVIES.CHANGES);
1057
- return this.client.request(endpoint, params);
1116
+ const { movie_id, ...rest } = params;
1117
+ const endpoint = this.movieSubPath(movie_id, ENDPOINTS.MOVIES.CHANGES);
1118
+ return this.client.request(endpoint, rest);
1058
1119
  }
1059
1120
  /**
1060
1121
  * Images
@@ -1793,7 +1854,7 @@ var NetworksAPI = class extends TMDBAPIBase {
1793
1854
  */
1794
1855
  async details(params) {
1795
1856
  const endpoint = this.networkPath(params.network_id);
1796
- return this.client.request(endpoint, params);
1857
+ return this.client.request(endpoint);
1797
1858
  }
1798
1859
  /**
1799
1860
  * Alternative names
@@ -1806,7 +1867,7 @@ var NetworksAPI = class extends TMDBAPIBase {
1806
1867
  */
1807
1868
  async alternative_names(params) {
1808
1869
  const endpoint = `${this.networkPath(params.network_id)}${ENDPOINTS.NETWORKS.ALTERNATIVE_NAMES}`;
1809
- return this.client.request(endpoint, params);
1870
+ return this.client.request(endpoint);
1810
1871
  }
1811
1872
  /**
1812
1873
  * Images
@@ -1869,8 +1930,8 @@ var TVEpisodesAPI = class extends TMDBAPIBase {
1869
1930
  * @reference https://developer.themoviedb.org/reference/tv-episode-changes-by-id
1870
1931
  */
1871
1932
  async changes(params) {
1872
- const endpoint = `${ENDPOINTS.TV_SERIES.DETAILS}/${ENDPOINTS.TV_EPISODES.DETAILS}/${params.episode_id}/${ENDPOINTS.TV_EPISODES.CHANGES}`;
1873
- return this.client.request(endpoint, { ...params });
1933
+ const endpoint = `${ENDPOINTS.TV_SERIES.DETAILS}${ENDPOINTS.TV_EPISODES.DETAILS}/${params.episode_id}${ENDPOINTS.TV_EPISODES.CHANGES}`;
1934
+ return this.client.request(endpoint);
1874
1935
  }
1875
1936
  /**
1876
1937
  * Credits
@@ -2215,10 +2276,7 @@ var PeopleListsAPI = class extends TMDBAPIBase {
2215
2276
  * @reference https://developer.themoviedb.org/reference/person-popular-list
2216
2277
  */
2217
2278
  async popular(params = {}) {
2218
- return this.client.request(
2219
- ENDPOINTS.PEOPLE_LISTS.POPULAR,
2220
- this.withLanguage(params) ?? params
2221
- );
2279
+ return this.client.request(ENDPOINTS.PEOPLE_LISTS.POPULAR, this.withLanguage(params));
2222
2280
  }
2223
2281
  };
2224
2282
 
@@ -2389,7 +2447,11 @@ var TMDB = class {
2389
2447
  constructor(accessToken, options = {}) {
2390
2448
  if (!accessToken) throw new Error(Errors.NO_ACCESS_TOKEN);
2391
2449
  this.options = options;
2392
- this.client = new ApiClient(accessToken, { logger: options.logger, deduplication: options.deduplication });
2450
+ this.client = new ApiClient(accessToken, {
2451
+ logger: options.logger,
2452
+ deduplication: options.deduplication,
2453
+ interceptors: options.interceptors
2454
+ });
2393
2455
  this.movies = new MoviesAPI(this.client, this.options);
2394
2456
  this.movie_lists = new MovieListsAPI(this.client, this.options);
2395
2457
  this.search = new SearchAPI(this.client, this.options);
@@ -3718,4 +3780,4 @@ var TVEpisodeGroupType = /* @__PURE__ */ ((TVEpisodeGroupType2) => {
3718
3780
  return TVEpisodeGroupType2;
3719
3781
  })(TVEpisodeGroupType || {});
3720
3782
 
3721
- export { BACKDROP_SIZES, DiscoverTVStatus, DiscoverTVType, IMAGE_BASE_URL, IMAGE_SECURE_BASE_URL, LOGO_SIZES, POSTER_SIZES, PROFILE_SIZES, STILL_SIZES, TMDB, TMDBCountries, TMDBError, TMDBLogger, TVEpisodeGroupType, isJwt, isKnownForMovie, isKnownForTV };
3783
+ export { BACKDROP_SIZES, DiscoverTVStatus, DiscoverTVType, IMAGE_BASE_URL, IMAGE_SECURE_BASE_URL, LOGO_SIZES, POSTER_SIZES, PROFILE_SIZES, STILL_SIZES, TMDB, TMDBCountries, TMDBError, TMDBLogger, TVEpisodeGroupType, hasBackdropPath, hasLogoPath, hasPosterPath, hasProfilePath, hasStillPath, isJwt, isKnownForMovie, isKnownForTV };
package/package.json CHANGED
@@ -1,25 +1,44 @@
1
1
  {
2
2
  "name": "@lorenzopant/tmdb",
3
- "version": "1.17.2",
3
+ "version": "1.17.4",
4
4
  "type": "module",
5
5
  "description": "A completely type-safe The Movie Database (TMDB) API wrapper for typescript applications.",
6
- "main": "dist/index.js",
7
- "types": "dist/index.d.ts",
8
- "files": [
9
- "dist",
10
- "README.md"
6
+ "keywords": [
7
+ "api",
8
+ "movies",
9
+ "tmdb",
10
+ "typescript"
11
11
  ],
12
+ "homepage": "https://lorenzopant-tmdb-docs.vercel.app",
13
+ "bugs": {
14
+ "url": "https://github.com/lorenzopant/tmdb/issues"
15
+ },
16
+ "license": "MIT",
17
+ "author": "Lorenzo Pantano",
12
18
  "repository": {
13
19
  "type": "git",
14
20
  "url": "git+https://github.com/lorenzopant/tmdb"
15
21
  },
16
- "homepage": "https://lorenzopant-tmdb-docs.vercel.app",
17
- "bugs": {
18
- "url": "https://github.com/lorenzopant/tmdb/issues"
22
+ "files": [
23
+ "dist",
24
+ "README.md"
25
+ ],
26
+ "main": "dist/index.js",
27
+ "types": "dist/index.d.ts",
28
+ "exports": {
29
+ ".": {
30
+ "import": "./dist/index.js",
31
+ "types": "./dist/index.d.ts"
32
+ },
33
+ "./types": {
34
+ "import": "./dist/index.js",
35
+ "types": "./dist/index.d.ts"
36
+ }
19
37
  },
20
38
  "scripts": {
21
39
  "build": "tsup",
22
40
  "dev": "tsup --watch",
41
+ "format": "oxfmt .",
23
42
  "typecheck": "tsc --noEmit",
24
43
  "test": "vitest",
25
44
  "test:unit": "vitest run --exclude '**/*.integration.test.ts'",
@@ -27,34 +46,18 @@
27
46
  "test:ui": "vitest --ui",
28
47
  "test:coverage": "vitest --coverage",
29
48
  "prepare": "husky",
30
- "lint": "eslint .",
49
+ "lint": "oxlint .",
50
+ "lint:check": "oxlint --type-aware --type-check .",
31
51
  "release": "pnpm release:patch",
32
52
  "release:patch": "pnpm version patch --git-tag-version && git push --follow-tags",
33
53
  "release:minor": "pnpm version minor --git-tag-version && git push --follow-tags",
34
54
  "release:major": "pnpm version major --git-tag-version && git push --follow-tags"
35
55
  },
36
- "author": "Lorenzo Pantano",
37
- "license": "MIT",
38
- "keywords": [
39
- "tmdb",
40
- "typescript",
41
- "api",
42
- "movies"
43
- ],
44
- "packageManager": "pnpm@8.8.0",
45
56
  "devDependencies": {
46
- "@eslint/compat": "^2.0.0",
47
- "@eslint/eslintrc": "^3.3.1",
48
- "@eslint/js": "^9.30.0",
49
57
  "@types/node": "^22.19.11",
50
- "@typescript-eslint/eslint-plugin": "^8.35.0",
51
- "@typescript-eslint/parser": "^8.35.0",
52
58
  "@vitest/coverage-v8": "^4.0.9",
53
59
  "@vitest/ui": "^4.0.10",
54
60
  "dotenv": "^16.5.0",
55
- "eslint": "^9.30.0",
56
- "eslint-config-prettier": "^10.1.5",
57
- "eslint-plugin-import": "^2.32.0",
58
61
  "husky": "^9.1.7",
59
62
  "release-it": "^19.0.3",
60
63
  "release-it-pnpm": "^4.6.6",
@@ -62,23 +65,13 @@
62
65
  "tsup": "^8.5.1",
63
66
  "tsx": "^4.21.0",
64
67
  "typescript": "^5.8.3",
65
- "typescript-eslint": "^8.35.0",
66
68
  "vite": "^7.0.0",
67
69
  "vitest": "^4.0.9"
68
70
  },
71
+ "packageManager": "pnpm@8.8.0",
69
72
  "pnpm": {
70
73
  "overrides": {
71
74
  "basic-ftp": "5.2.0"
72
75
  }
73
- },
74
- "exports": {
75
- ".": {
76
- "import": "./dist/index.js",
77
- "types": "./dist/index.d.ts"
78
- },
79
- "./types": {
80
- "import": "./dist/index.js",
81
- "types": "./dist/index.d.ts"
82
- }
83
76
  }
84
77
  }