@tdanks2000/tmdb-wrapper 1.3.4 → 1.5.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 CHANGED
@@ -192,36 +192,97 @@ The wrapper also provides access to these additional endpoints:
192
192
 
193
193
  ## Image Handling
194
194
 
195
- The wrapper provides enhanced utilities for handling TMDB images:
195
+ ## Image Handling
196
+
197
+ The wrapper includes utilities to reliably construct TMDB image URLs, plus a convenience helper for TMDB `Image` objects.
198
+
199
+ ```typescript
200
+ import {
201
+ formImage,
202
+ getFullImagePath,
203
+ ImageSizes,
204
+ ImageFormats,
205
+ } from "@tdanks2000/tmdb-wrapper";
206
+ ```
207
+
208
+ ### `getFullImagePath(...)`
196
209
 
197
210
  ```typescript
198
- import { getFullImagePath, ImageSizes, ImageFormats } from '@tdanks2000/tmdb-wrapper';
211
+ getFullImagePath(
212
+ baseUrl: string, // e.g. "https://image.tmdb.org/t/p/"
213
+ fileSize: string, // e.g. ImageSizes.W500 or "w780"
214
+ imagePath: string, // e.g. "/abc123" or "/abc123.jpg"
215
+ format?: string // optional: ImageFormats.JPG / PNG / SVG
216
+ ): string
217
+ ```
218
+
219
+ Notes:
220
+ - `imagePath` can be with or without a leading `/` (both work).
221
+ - If `imagePath` is already an absolute URL (`https://...`), it’s returned unchanged.
222
+ - If you provide `format`, the extension is appended/replaced safely.
223
+ - If you omit `format`, the original path is preserved (no forced default extension).
224
+
225
+ ### `formImage(image, fileSize, format?)`
226
+
227
+ `formImage` is a small helper that reads `file_path` from a TMDB `Image` object and returns a ready-to-use URL. If the image object doesn’t include a `file_path`, it returns `undefined`.
228
+
229
+ ```typescript
230
+ formImage(
231
+ image: Image,
232
+ fileSize: ImageSizes,
233
+ format?: ImageFormats
234
+ ): string | undefined
235
+ ```
236
+
237
+ ### Examples
238
+
239
+ Poster path without extension (add one via `format`):
199
240
 
200
- // Example usage for movie poster
241
+ ```typescript
201
242
  const posterUrl = getFullImagePath(
202
- 'https://image.tmdb.org/t/p/',
203
- ImageSizes.W500,
204
- '/wwemzKWzjKYJFfCeiB57q3r4Bcm',
205
- ImageFormats.JPG
243
+ "https://image.tmdb.org/t/p/",
244
+ ImageSizes.W500,
245
+ "/wwemzKWzjKYJFfCeiB57q3r4Bcm",
246
+ ImageFormats.JPG,
206
247
  );
207
- // Results in: https://image.tmdb.org/t/p/w500/wwemzKWzjKYJFfCeiB57q3r4Bcm.jpg
248
+ // https://image.tmdb.org/t/p/w500/wwemzKWzjKYJFfCeiB57q3r4Bcm.jpg
249
+ ```
208
250
 
209
- // Example usage for profile image
251
+ Profile path that already includes an extension (no need to pass `format`):
252
+
253
+ ```typescript
210
254
  const profileUrl = getFullImagePath(
211
- 'https://image.tmdb.org/t/p/',
212
- ImageSizes.W185,
213
- '/5XBzD5WuTyVQZeS4VI25z2moMeY.jpg',
214
- ImageFormats.JPG
255
+ "https://image.tmdb.org/t/p/",
256
+ ImageSizes.W185,
257
+ "/5XBzD5WuTyVQZeS4VI25z2moMeY.jpg",
215
258
  );
216
- // Results in: https://image.tmdb.org/t/p/w185/5XBzD5WuTyVQZeS4VI25z2moMeY.jpg
259
+ // https://image.tmdb.org/t/p/w185/5XBzD5WuTyVQZeS4VI25z2moMeY.jpg
260
+ ```
261
+
262
+ Using `formImage` with a TMDB response image object:
263
+
264
+ ```typescript
265
+ const images = await tmdb.movies.getImages(550);
266
+ const poster = images.posters[0];
267
+
268
+ const posterUrl = formImage(poster, ImageSizes.W500);
269
+ // e.g. https://image.tmdb.org/t/p/w500/xxxxx.jpg
217
270
  ```
218
271
 
219
- The utility supports all TMDB image sizes and formats:
272
+ Override the output extension (append/replace) with `format`:
273
+
274
+ ```typescript
275
+ const posterPngUrl = formImage(poster, ImageSizes.W500, ImageFormats.PNG);
276
+ ```
277
+
278
+ ### Sizes & formats
279
+
280
+ This package exports common presets:
220
281
 
221
- - **Sizes**: W45, W92, W154, W185, W300, W342, W500, W780, W1280, Original
222
- - **Formats**: JPG, PNG, SVG
282
+ - **Sizes**: `ImageSizes.ORIGINAL`, `W500`, `W300`, `W185`, `W92`, `H632`
283
+ - **Formats**: `ImageFormats.JPG`, `PNG`, `SVG`
223
284
 
224
- ## Examples
285
+ TMDB can support additional sizes depending on their configuration; you can also pass any valid TMDB size string directly (e.g. `"w780"`, `"w1280"`).
225
286
 
226
287
  ### Searching for Content
227
288
 
package/dist/index.cjs CHANGED
@@ -114,9 +114,32 @@ let ReleaseDateType = /* @__PURE__ */ function(ReleaseDateType$1) {
114
114
  //#endregion
115
115
  //#region src/utils/api.ts
116
116
  const BASE_URL_V3 = "https://api.themoviedb.org/3";
117
+ /**
118
+ * Lightweight TMDB v3 API client.
119
+ *
120
+ * - Sends requests to `https://api.themoviedb.org/3`.
121
+ * - Supports authentication via:
122
+ * - v4 API Read Access Token (Bearer), and/or
123
+ * - v3 API key via `api_key` query parameter.
124
+ *
125
+ * Notes:
126
+ * - Many endpoints accept either method depending on your TMDB settings.
127
+ * - When an API key is present, it is appended as `api_key` in the query string.
128
+ */
117
129
  var API = class {
130
+ /**
131
+ * Optional v3 API key (sent as `api_key` query param).
132
+ */
118
133
  apiKey;
134
+ /**
135
+ * Optional v4 read access token (sent as `Authorization: Bearer ...`).
136
+ */
119
137
  accessToken;
138
+ /**
139
+ * Create a new API client.
140
+ *
141
+ * @param {TokenType} auth - Authentication information.
142
+ */
120
143
  constructor(auth) {
121
144
  if (typeof auth === "string") this.accessToken = auth;
122
145
  else {
@@ -125,9 +148,16 @@ var API = class {
125
148
  }
126
149
  }
127
150
  /**
128
- * Generic GET:
129
- * @template T — response type
130
- * @template O options (query params) type
151
+ * Generic HTTP GET request.
152
+ *
153
+ * @template T - Response JSON type.
154
+ * @template O - Query options (query params) type.
155
+ *
156
+ * @param {string} path - The TMDB path beginning with `/`, e.g. `/movie/550`.
157
+ * @param {O} [options] - Query parameters to serialize.
158
+ *
159
+ * @returns {Promise<T>} Resolves with parsed JSON typed as `T`.
160
+ * @throws {ErrorResponse} Rejects with parsed TMDB error payload when `response.ok` is false.
131
161
  */
132
162
  async get(path, options) {
133
163
  const rawOptions = {
@@ -149,6 +179,16 @@ var API = class {
149
179
  return await response.json();
150
180
  }
151
181
  };
182
+ /**
183
+ * Serializes an options object into a query string.
184
+ *
185
+ * - Skips `undefined` and `null`.
186
+ * - Arrays are expanded into repeated keys:
187
+ * `{ with_genres: ["12", "16"] }` -> `with_genres=12&with_genres=16`
188
+ *
189
+ * @param {Record<string, unknown>} [options] - Options to serialize.
190
+ * @returns {string} Query string without the leading `?`.
191
+ */
152
192
  const parseOptions = (options) => {
153
193
  if (!options) return "";
154
194
  const entries = [];
@@ -162,31 +202,7 @@ const parseOptions = (options) => {
162
202
 
163
203
  //#endregion
164
204
  //#region src/utils/getimagePath.ts
165
- /**
166
- * Utility method to construct full url for image
167
- * based on configuration
168
- *
169
- * https://developers.themoviedb.org/3/getting-started/images
170
- * @param {string} baseUrl base image url (e.g., 'https://image.tmdb.org/t/p/')
171
- * @param {string} fileSize file size (e.g., 'original', 'w500')
172
- * @param {string} imagePath raw image path
173
- * @param {string} format override image format (e.g., 'svg', 'png', 'jpg')
174
- * @returns {string} The complete image URL
175
- */
176
- const getFullImagePath = (baseUrl, fileSize, imagePath, format) => {
177
- if (!imagePath) return "";
178
- const hasExtension = imagePath.includes(".");
179
- if (hasExtension) {
180
- const imagePathArr = imagePath.split(".");
181
- const imageFormat$1 = format || imagePathArr[1];
182
- return `${baseUrl}${fileSize}${imagePathArr[0]}.${imageFormat$1}`;
183
- }
184
- const imageFormat = format || "jpg";
185
- return `${baseUrl}${fileSize}${imagePath}.${imageFormat}`;
186
- };
187
- /**
188
- * Common image sizes available in TMDB
189
- */
205
+ const TMDB_IMAGE_BASE_URL = "https://image.tmdb.org/t/p/";
190
206
  const ImageSizes = {
191
207
  ORIGINAL: "original",
192
208
  W500: "w500",
@@ -195,19 +211,67 @@ const ImageSizes = {
195
211
  W92: "w92",
196
212
  H632: "h632"
197
213
  };
198
- /**
199
- * Image formats supported by TMDB
200
- */
201
214
  const ImageFormats = {
202
215
  JPG: "jpg",
203
216
  PNG: "png",
204
217
  SVG: "svg"
205
218
  };
219
+ const isAbsoluteUrl = (value) => /^https?:\/\//i.test(value);
220
+ const normalizeBaseUrl = (baseUrl) => baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
221
+ const normalizeSize = (size) => size.replace(/^\/+|\/+$/g, "");
222
+ const normalizePath = (path) => path.startsWith("/") ? path : `/${path}`;
223
+ const setExtension = (path, format) => {
224
+ const lastSlash = path.lastIndexOf("/");
225
+ const lastDot = path.lastIndexOf(".");
226
+ const hasExt = lastDot > lastSlash;
227
+ if (!hasExt) return `${path}.${format}`;
228
+ return `${path.slice(0, lastDot + 1)}${format}`;
229
+ };
230
+ /**
231
+ * Constructs a TMDB image URL.
232
+ *
233
+ * - Keeps paths as-is unless `format` is provided (then it replaces/appends
234
+ * the extension safely using the last dot after the last slash).
235
+ * - Handles leading/trailing slashes robustly.
236
+ * - If `imagePath` is already an absolute URL, it is returned unchanged.
237
+ */
238
+ const getFullImagePath = (baseUrl, fileSize, imagePath, format) => {
239
+ if (!imagePath) return "";
240
+ if (isAbsoluteUrl(imagePath)) return imagePath;
241
+ const base = normalizeBaseUrl(baseUrl);
242
+ const size = normalizeSize(fileSize);
243
+ let path = normalizePath(imagePath);
244
+ if (format) path = setExtension(path, format);
245
+ return `${base}${size}${path}`;
246
+ };
247
+ /**
248
+ * Convenience helper for TMDB `Image` objects.
249
+ */
250
+ const formImage = (image, fileSize, format) => {
251
+ const path = image?.file_path;
252
+ if (!path) return void 0;
253
+ return getFullImagePath(TMDB_IMAGE_BASE_URL, fileSize, path, format);
254
+ };
206
255
 
207
256
  //#endregion
208
257
  //#region src/@types/models/baseEndpoint.ts
258
+ /**
259
+ * Base class for all TMDB API endpoints.
260
+ *
261
+ * Provides a configured {@link API} client instance to subclasses.
262
+ */
209
263
  var BaseEndpoint = class {
264
+ /**
265
+ * Low-level HTTP client wrapper used by all endpoints.
266
+ */
210
267
  api;
268
+ /**
269
+ * Create a new endpoint instance.
270
+ *
271
+ * @param {TokenType} auth - Authentication information.
272
+ * - If a string: treated as a v4 API Read Access Token (Bearer token).
273
+ * - If an object: can include an API key and/or access token, depending on your {@link TokenType}.
274
+ */
211
275
  constructor(auth) {
212
276
  this.auth = auth;
213
277
  this.api = new API(auth);
@@ -218,11 +282,20 @@ var BaseEndpoint = class {
218
282
  //#region src/endpoints/account.ts
219
283
  /**
220
284
  * Represents an endpoint for retrieving account details.
285
+ *
286
+ * TMDB v3 reference:
287
+ * - GET /account/{account_id}
288
+ *
289
+ * Note:
290
+ * TMDB does not expose a generic "GET /account" for account details. You must
291
+ * provide an `account_id`. Most apps obtain it from an auth flow and then cache
292
+ * it for subsequent requests.
221
293
  */
222
294
  var AccountEndpoint = class extends BaseEndpoint {
223
295
  /**
224
296
  * Constructs a new AccountEndpoint instance.
225
- * @param {string} access_token - The access token used for authentication.
297
+ *
298
+ * @param {TokenType} access_token - The access token used for authentication.
226
299
  */
227
300
  constructor(access_token) {
228
301
  super(access_token);
@@ -230,10 +303,14 @@ var AccountEndpoint = class extends BaseEndpoint {
230
303
  }
231
304
  /**
232
305
  * Retrieves account details asynchronously.
306
+ *
307
+ * TMDB: GET /account/{account_id}
308
+ *
309
+ * @param {number} accountId - The TMDB account ID.
233
310
  * @returns {Promise<AccountDetails>} A Promise that resolves with the account details.
234
311
  */
235
- async details() {
236
- return await this.api.get("/account");
312
+ details(accountId) {
313
+ return this.api.get(`/account/${accountId}`);
237
314
  }
238
315
  };
239
316
 
@@ -241,11 +318,16 @@ var AccountEndpoint = class extends BaseEndpoint {
241
318
  //#region src/endpoints/certification.ts
242
319
  /**
243
320
  * Represents an endpoint for retrieving certifications for movies and TV shows.
321
+ *
322
+ * TMDB v3 reference:
323
+ * - GET /certification/movie/list
324
+ * - GET /certification/tv/list
244
325
  */
245
326
  var CertificationEndpoint = class extends BaseEndpoint {
246
327
  /**
247
328
  * Constructs a new CertificationEndpoint instance.
248
- * @param {string} access_token - The access token used for authentication.
329
+ *
330
+ * @param {TokenType} access_token - The access token used for authentication.
249
331
  */
250
332
  constructor(access_token) {
251
333
  super(access_token);
@@ -253,17 +335,23 @@ var CertificationEndpoint = class extends BaseEndpoint {
253
335
  }
254
336
  /**
255
337
  * Retrieves certifications for movies asynchronously.
338
+ *
339
+ * TMDB: GET /certification/movie/list
340
+ *
256
341
  * @returns {Promise<Certifications>} A Promise that resolves with the certifications for movies.
257
342
  */
258
- async movies() {
259
- return await this.api.get("/certification/movie/list");
343
+ movies() {
344
+ return this.api.get("/certification/movie/list");
260
345
  }
261
346
  /**
262
347
  * Retrieves certifications for TV shows asynchronously.
348
+ *
349
+ * TMDB: GET /certification/tv/list
350
+ *
263
351
  * @returns {Promise<Certifications>} A Promise that resolves with the certifications for TV shows.
264
352
  */
265
- async tv() {
266
- return await this.api.get("/certification/tv/list");
353
+ tv() {
354
+ return this.api.get("/certification/tv/list");
267
355
  }
268
356
  };
269
357
 
@@ -271,11 +359,17 @@ var CertificationEndpoint = class extends BaseEndpoint {
271
359
  //#region src/endpoints/changes.ts
272
360
  /**
273
361
  * Represents an endpoint for retrieving changes in movies, TV shows, and persons.
362
+ *
363
+ * TMDB v3 reference:
364
+ * - GET /movie/changes
365
+ * - GET /tv/changes
366
+ * - GET /person/changes
274
367
  */
275
368
  var ChangeEndpoint = class extends BaseEndpoint {
276
369
  /**
277
370
  * Constructs a new ChangeEndpoint instance.
278
- * @param {string} access_token - The access token used for authentication.
371
+ *
372
+ * @param {TokenType} access_token - The access token used for authentication.
279
373
  */
280
374
  constructor(access_token) {
281
375
  super(access_token);
@@ -283,27 +377,36 @@ var ChangeEndpoint = class extends BaseEndpoint {
283
377
  }
284
378
  /**
285
379
  * Retrieves changes in movies asynchronously.
380
+ *
381
+ * TMDB: GET /movie/changes
382
+ *
286
383
  * @param {ChangeOption} [options] - Optional parameters for filtering the changes.
287
384
  * @returns {Promise<MediaChanges>} A Promise that resolves with the changes in movies.
288
385
  */
289
- async movies(options) {
290
- return await this.api.get("/movie/changes", options);
386
+ movies(options) {
387
+ return this.api.get("/movie/changes", options);
291
388
  }
292
389
  /**
293
390
  * Retrieves changes in TV shows asynchronously.
391
+ *
392
+ * TMDB: GET /tv/changes
393
+ *
294
394
  * @param {ChangeOption} [options] - Optional parameters for filtering the changes.
295
395
  * @returns {Promise<MediaChanges>} A Promise that resolves with the changes in TV shows.
296
396
  */
297
- async tv(options) {
298
- return await this.api.get("/tv/changes", options);
397
+ tv(options) {
398
+ return this.api.get("/tv/changes", options);
299
399
  }
300
400
  /**
301
401
  * Retrieves changes related to persons asynchronously.
402
+ *
403
+ * TMDB: GET /person/changes
404
+ *
302
405
  * @param {ChangeOption} [options] - Optional parameters for filtering the changes.
303
406
  * @returns {Promise<MediaChanges>} A Promise that resolves with the changes related to persons.
304
407
  */
305
- async person(options) {
306
- return await this.api.get("/person/changes", options);
408
+ person(options) {
409
+ return this.api.get("/person/changes", options);
307
410
  }
308
411
  };
309
412
 
@@ -447,11 +550,16 @@ var CreditsEndpoint = class extends BaseEndpoint {
447
550
  const BASE_DISCOVER = "/discover";
448
551
  /**
449
552
  * Represents an endpoint for discovering movies and TV shows based on various criteria.
553
+ *
554
+ * TMDB v3 reference:
555
+ * - GET /discover/movie
556
+ * - GET /discover/tv
450
557
  */
451
558
  var DiscoverEndpoint = class extends BaseEndpoint {
452
559
  /**
453
560
  * Constructs a new DiscoverEndpoint instance.
454
- * @param {string} access_token - The access token used for authentication.
561
+ *
562
+ * @param {TokenType} access_token - The access token used for authentication.
455
563
  */
456
564
  constructor(access_token) {
457
565
  super(access_token);
@@ -459,19 +567,25 @@ var DiscoverEndpoint = class extends BaseEndpoint {
459
567
  }
460
568
  /**
461
569
  * Retrieves a list of movies based on the provided query options asynchronously.
570
+ *
571
+ * TMDB: GET /discover/movie
572
+ *
462
573
  * @param {MovieQueryOptions} [options] - Optional parameters for refining the movie discovery.
463
574
  * @returns {Promise<MovieDiscoverResult>} A Promise that resolves with the movie discovery results.
464
575
  */
465
- async movie(options) {
466
- return await this.api.get(`${BASE_DISCOVER}/movie`, options);
576
+ movie(options) {
577
+ return this.api.get(`${BASE_DISCOVER}/movie`, options);
467
578
  }
468
579
  /**
469
580
  * Retrieves a list of TV shows based on the provided query options asynchronously.
581
+ *
582
+ * TMDB: GET /discover/tv
583
+ *
470
584
  * @param {TvShowQueryOptions} [options] - Optional parameters for refining the TV show discovery.
471
585
  * @returns {Promise<TvShowDiscoverResult>} A Promise that resolves with the TV show discovery results.
472
586
  */
473
- async tvShow(options) {
474
- return await this.api.get(`${BASE_DISCOVER}/tv`, options);
587
+ tvShow(options) {
588
+ return this.api.get(`${BASE_DISCOVER}/tv`, options);
475
589
  }
476
590
  };
477
591
 
@@ -1570,5 +1684,7 @@ exports.ProfileSizes = ProfileSizes;
1570
1684
  exports.ReleaseDateType = ReleaseDateType;
1571
1685
  exports.StillSizes = StillSizes;
1572
1686
  exports.TMDB = TMDB;
1687
+ exports.TMDB_IMAGE_BASE_URL = TMDB_IMAGE_BASE_URL;
1688
+ exports.formImage = formImage;
1573
1689
  exports.getFullImagePath = getFullImagePath;
1574
1690
  exports.parseOptions = parseOptions;