diff --git a/DOCUMENTATION.md b/DOCUMENTATION.md new file mode 100644 index 0000000..296f9ef --- /dev/null +++ b/DOCUMENTATION.md @@ -0,0 +1,1328 @@ +# TMDB-TS - Comprehensive Documentation + +## Table of Contents + +1. [Overview](#overview) +2. [Architecture](#architecture) +3. [Installation](#installation) +4. [Quick Start](#quick-start) +5. [Core Components](#core-components) +6. [API Endpoints](#api-endpoints) +7. [Type System](#type-system) +8. [Advanced Usage](#advanced-usage) +9. [Error Handling](#error-handling) +10. [Best Practices](#best-practices) + +--- + +## Overview + +**tmdb-ts** is a TypeScript library that provides a fully-typed wrapper around The Movie Database (TMDB) API v3. It simplifies interaction with the TMDB API by offering: + +- **Type Safety**: Complete TypeScript type definitions for all API responses +- **Modern Authentication**: Uses JWT Bearer token authentication (no need for API keys in URLs) +- **Modular Design**: Organized endpoints for different resource types +- **Promise-based**: Modern async/await support +- **Zero Configuration**: Simple instantiation with access token + +### Key Features + +- ✅ Full TypeScript support with comprehensive type definitions +- ✅ All TMDB API v3 endpoints covered +- ✅ Automatic query parameter parsing +- ✅ Error handling with typed error responses +- ✅ Support for append_to_response functionality +- ✅ Cross-platform fetch implementation via cross-fetch + +--- + +## Architecture + +### Project Structure + +``` +tmdb-ts/ +├── src/ +│ ├── api.ts # Core HTTP client +│ ├── tmdb.ts # Main TMDB class +│ ├── index.ts # Public exports +│ ├── common/ +│ │ └── constants.ts # API base URLs and constants +│ ├── endpoints/ # Endpoint implementations +│ │ ├── base.ts # Base endpoint class +│ │ ├── movies.ts # Movie-related endpoints +│ │ ├── tv-shows.ts # TV show endpoints +│ │ ├── people.ts # People/cast endpoints +│ │ ├── search.ts # Search endpoints +│ │ ├── credits.ts # Credits endpoints +│ │ ├── genres.ts # Genre endpoints +│ │ ├── discover.ts # Discover endpoints +│ │ ├── trending.ts # Trending endpoints +│ │ ├── collections.ts # Collection endpoints +│ │ ├── companies.ts # Company endpoints +│ │ ├── networks.ts # Network endpoints +│ │ ├── keywords.ts # Keyword endpoints +│ │ ├── configuration.ts # Configuration endpoints +│ │ ├── certifications.ts# Certification endpoints +│ │ ├── changes.ts # Change tracking endpoints +│ │ ├── account.ts # Account endpoints +│ │ ├── review.ts # Review endpoints +│ │ ├── watch-providers.ts# Watch provider endpoints +│ │ ├── tv-seasons.ts # TV season endpoints +│ │ ├── tv-episode.ts # TV episode endpoints +│ │ └── find.ts # External ID lookup +│ ├── types/ # TypeScript type definitions +│ │ ├── index.ts # Main type exports +│ │ ├── options.ts # Query option types +│ │ ├── movies.ts # Movie-related types +│ │ ├── tv-shows.ts # TV show types +│ │ ├── people.ts # People/person types +│ │ ├── credits.ts # Credits types +│ │ ├── search.ts # Search result types +│ │ └── [other types] # Additional type definitions +│ └── utils/ # Utility functions +│ ├── parseOptions.ts # Query parameter parser +│ ├── getImagePath.ts # Image URL helper +│ └── index.ts # Utility exports +├── package.json +├── tsconfig.json +└── README.md +``` + +### Design Patterns + +#### 1. **Lazy Instantiation Pattern** +```typescript +class TMDB { + get movies(): MoviesEndpoint { + return new MoviesEndpoint(this.accessToken); + } +} +``` +Endpoints are instantiated on-demand via getter properties, keeping memory footprint low. + +#### 2. **Base Endpoint Pattern** +```typescript +abstract class BaseEndpoint { + protected api: Api; + constructor(protected readonly accessToken: string) { + this.api = new Api(accessToken); + } +} +``` +All endpoints extend a base class that provides HTTP client access. + +#### 3. **Type-safe Append Pattern** +```typescript +type AppendToResponse +``` +Compile-time type safety for dynamic API response composition. + +--- + +## Installation + +```bash +# Using npm +npm install tmdb-ts + +# Using yarn +yarn add tmdb-ts + +# Using pnpm +pnpm add tmdb-ts + +# Using bun +bun add tmdb-ts +``` + +### Requirements + +- Node.js >= 14.x +- TypeScript >= 4.5 (for type definitions) + +--- + +## Quick Start + +### 1. Get TMDB Access Token + +1. Create an account at [themoviedb.org](https://www.themoviedb.org/) +2. Go to Settings → API +3. Generate an API Read Access Token (JWT) + +### 2. Basic Usage + +```typescript +import { TMDB } from 'tmdb-ts'; + +// Initialize the client +const tmdb = new TMDB('your_access_token_here'); + +// Search for movies +async function searchMovies() { + try { + const results = await tmdb.search.movies({ + query: 'Inception' + }); + console.log(results.results); + } catch (error) { + console.error('Error:', error); + } +} + +// Get movie details +async function getMovieDetails() { + const movie = await tmdb.movies.details(550); // Fight Club + console.log(movie.title, movie.overview); +} +``` + +--- + +## Core Components + +### 1. TMDB Class + +The main entry point for all API interactions. + +```typescript +class TMDB { + constructor(accessToken: string); + + // Endpoint accessors (getters) + get movies(): MoviesEndpoint; + get tvShows(): TvShowsEndpoint; + get people(): PeopleEndpoint; + get search(): SearchEndpoint; + get credits(): CreditsEndpoint; + get discover(): DiscoverEndpoint; + get genres(): GenreEndpoint; + get trending(): TrendingEndpoint; + get collections(): CollectionsEndpoint; + get companies(): CompaniesEndpoint; + get networks(): NetworksEndpoint; + get keywords(): KeywordsEndpoint; + get configuration(): ConfigurationEndpoint; + get certifications(): CertificationEndpoint; + get changes(): ChangeEndpoint; + get account(): AccountEndpoint; + get review(): ReviewEndpoint; + get watchProviders(): WatchProvidersEndpoint; + get tvSeasons(): TvSeasonsEndpoint; + get tvEpisode(): TvEpisodesEndpoint; + get find(): FindEndpoint; +} +``` + +### 2. Api Class + +Internal HTTP client handling all requests. + +```typescript +class Api { + constructor(accessToken: string); + + async get(path: string, options?: Record): Promise; +} +``` + +**Features:** +- Automatically adds Bearer token authentication +- Converts options object to URL query parameters +- Returns typed responses +- Throws typed errors on failure + +### 3. BaseEndpoint Class + +Abstract base class for all endpoint implementations. + +```typescript +abstract class BaseEndpoint { + protected api: Api; + constructor(protected readonly accessToken: string); +} +``` + +--- + +## API Endpoints + +### Movies Endpoint + +Comprehensive movie-related operations. + +#### Methods + +```typescript +class MoviesEndpoint { + // Get detailed information about a movie + async details( + id: number, + appendToResponse?: T, + language?: string + ): Promise>; + + // Get alternative titles for a movie + async alternativeTitles(id: number): Promise; + + // Get the recent changes for a movie + async changes(id: number, options?: ChangeOption): Promise>; + + // Get the cast and crew for a movie + async credits(id: number, options?: LanguageOption): Promise; + + // Get external IDs for a movie + async externalIds(id: number): Promise; + + // Get images for a movie + async images(id: number, options?: MoviesImageSearchOptions): Promise; + + // Get keywords for a movie + async keywords(id: number): Promise; + + // Get lists that this movie belongs to + async lists(id: number, options?: LanguageOption & PageOption): Promise; + + // Get movie recommendations + async recommendations(id: number, options?: LanguageOption & PageOption): Promise; + + // Get release dates for a movie + async releaseDates(id: number): Promise; + + // Get user reviews for a movie + async reviews(id: number, options?: LanguageOption & PageOption): Promise; + + // Get similar movies + async similar(id: number, options?: LanguageOption & PageOption): Promise; + + // Get translations for a movie + async translations(id: number): Promise; + + // Get videos (trailers, teasers) for a movie + async videos(id: number, options?: LanguageOption): Promise; + + // Get watch providers for a movie + async watchProviders(id: number): Promise; + + // Get the latest movie + async latest(): Promise; + + // Get movies now playing in theaters + async nowPlaying(options?: PageOption & LanguageOption & RegionOption): Promise; + + // Get popular movies + async popular(options?: LanguageOption & PageOption): Promise; + + // Get top rated movies + async topRated(options?: PageOption & LanguageOption & RegionOption): Promise; + + // Get upcoming movies + async upcoming(options?: PageOption & LanguageOption & RegionOption): Promise; +} +``` + +#### Examples + +```typescript +// Basic movie details +const movie = await tmdb.movies.details(550); +console.log(movie.title, movie.release_date); + +// Movie details with additional data (append_to_response) +const movieWithExtras = await tmdb.movies.details( + 550, + ['credits', 'videos', 'images'], + 'en-US' +); +console.log(movieWithExtras.credits.cast); +console.log(movieWithExtras.videos.results); + +// Get movie credits +const credits = await tmdb.movies.credits(550); +console.log('Director:', credits.crew.find(c => c.job === 'Director')?.name); + +// Search for similar movies +const similar = await tmdb.movies.similar(550, { page: 1 }); +console.log('Similar movies:', similar.results.map(m => m.title)); + +// Get popular movies +const popular = await tmdb.movies.popular({ language: 'en-US', page: 1 }); +``` + +### TV Shows Endpoint + +TV series and episode management. + +```typescript +class TvShowsEndpoint { + // Get TV show details + async details( + id: number, + appendToResponse?: T, + language?: string + ): Promise>; + + // Get aggregate credits (all seasons) + async aggregateCredits(id: number, options?: LanguageOption): Promise; + + // Get alternative titles + async alternativeTitles(id: number): Promise; + + // Get changes for a TV show + async changes(id: number, options?: ChangeOption): Promise>; + + // Get content ratings + async contentRatings(id: number): Promise; + + // Get credits for a TV show + async credits(id: number, options?: LanguageOption): Promise; + + // Get episode groups + async episodeGroups(id: number): Promise; + + // Get external IDs + async externalIds(id: number): Promise; + + // Get images + async images(id: number, options?: LanguageOption): Promise; + + // Get keywords + async keywords(id: number): Promise; + + // Get recommendations + async recommendations(id: number, options?: LanguageOption & PageOption): Promise; + + // Get reviews + async reviews(id: number, options?: LanguageOption & PageOption): Promise; + + // Get screened theatrically episodes + async screenedTheatrically(id: number): Promise; + + // Get similar TV shows + async similar(id: number, options?: LanguageOption & PageOption): Promise; + + // Get translations + async translations(id: number): Promise; + + // Get videos + async videos(id: number, options?: LanguageOption): Promise; + + // Get watch providers + async watchProviders(id: number): Promise; + + // Get latest TV show + async latest(): Promise; + + // Get TV shows airing today + async airingToday(options?: PageOption & LanguageOption & TimezoneOption): Promise; + + // Get TV shows on the air + async onTheAir(options?: PageOption & LanguageOption & TimezoneOption): Promise; + + // Get popular TV shows + async popular(options?: LanguageOption & PageOption): Promise; + + // Get top rated TV shows + async topRated(options?: LanguageOption & PageOption): Promise; +} +``` + +### People Endpoint + +Person/celebrity information and credits. + +```typescript +class PeopleEndpoint { + // Get person details + async details( + id: number, + appendToResponse?: T, + language?: string + ): Promise>; + + // Get changes for a person + async changes(id: number, options?: ChangeOption): Promise>; + + // Get movie credits for a person + async movieCredits(id: number, options?: LanguageOption): Promise; + + // Get TV show credits for a person + async tvShowCredits(id: number, options?: LanguageOption): Promise; + + // Get combined movie and TV credits + async combinedCredits(id: number, options?: LanguageOption): Promise; + + // Get external IDs for a person + async externalId(id: number): Promise; + + // Get images for a person + async images(id: number): Promise; + + // Get tagged images (deprecated) + async taggedImages(id: number, options?: PageOption): Promise; + + // Get translations + async translation(id: number): Promise; + + // Get the latest person + async latest(): Promise; + + // Get popular people + async popular(options?: LanguageOption & PageOption): Promise; +} +``` + +#### Examples + +```typescript +// Get person details +const person = await tmdb.people.details(287); // Brad Pitt +console.log(person.name, person.biography); + +// Get person with movie credits +const personWithCredits = await tmdb.people.details( + 287, + ['movie_credits', 'tv_credits'] +); +console.log('Movies:', personWithCredits.movie_credits.cast); + +// Get combined credits +const credits = await tmdb.people.combinedCredits(287); +console.log('All credits:', [...credits.cast, ...credits.crew]); + +// Get popular people +const popularPeople = await tmdb.people.popular({ page: 1 }); +``` + +### Search Endpoint + +Search across all content types. + +```typescript +class SearchEndpoint { + // Search for companies + async companies(options: { query: string } & PageOption): Promise; + + // Search for collections + async collections(options: { query: string } & PageOption & LanguageOption): Promise; + + // Search for keywords + async keywords(options: { query: string } & PageOption): Promise; + + // Search for movies + async movies(options: MovieSearchOptions): Promise; + + // Multi search (movies, TV shows, people) + async multi(options: { query: string } & PageOption & LanguageOption): Promise; + + // Search for people + async people(options: { query: string } & PageOption & LanguageOption): Promise; + + // Search for TV shows + async tvShows(options: TvShowSearchOptions): Promise; +} +``` + +#### Examples + +```typescript +// Search movies +const movies = await tmdb.search.movies({ + query: 'Matrix', + year: 1999, + page: 1 +}); + +// Multi-search (searches movies, TV, people) +const results = await tmdb.search.multi({ + query: 'Tom Hanks' +}); + +// Search TV shows +const tvShows = await tmdb.search.tvShows({ + query: 'Breaking Bad', + first_air_date_year: 2008 +}); + +// Search people +const people = await tmdb.search.people({ + query: 'Leonardo DiCaprio' +}); +``` + +### Credits Endpoint + +Individual credit information. + +```typescript +class CreditsEndpoint { + // Get detailed information about a credit + async getById(id: string): Promise; +} +``` + +### Discover Endpoint + +Discover movies and TV shows with filtering. + +```typescript +class DiscoverEndpoint { + // Discover movies + async movies(options?: DiscoverMoviesOptions): Promise; + + // Discover TV shows + async tvShows(options?: DiscoverTvShowsOptions): Promise; +} +``` + +#### Examples + +```typescript +// Discover movies with filters +const action = await tmdb.discover.movies({ + with_genres: '28', // Action genre + 'vote_average.gte': 7, + sort_by: 'popularity.desc', + page: 1 +}); + +// Discover TV shows +const comedy = await tmdb.discover.tvShows({ + with_genres: '35', // Comedy genre + 'first_air_date.gte': '2020-01-01', + sort_by: 'vote_average.desc' +}); +``` + +### Trending Endpoint + +Get trending content. + +```typescript +class TrendingEndpoint { + // Get trending content + async trending( + mediaType: 'all' | 'movie' | 'tv' | 'person', + timeWindow: 'day' | 'week', + options?: PageOption & LanguageOption + ): Promise; +} +``` + +### Configuration Endpoint + +Get TMDB system configuration. + +```typescript +class ConfigurationEndpoint { + // Get API configuration (image base URLs, etc.) + async getApiConfiguration(): Promise; + + // Get list of countries + async getCountries(): Promise; + + // Get list of jobs + async getJobs(): Promise; + + // Get list of languages + async getLanguages(): Promise; + + // Get list of primary translations + async getPrimaryTranslations(): Promise; + + // Get list of timezones + async getTimezones(): Promise; +} +``` + +### Other Endpoints + +- **Collections**: Movie collection information +- **Companies**: Production company details +- **Networks**: TV network information +- **Keywords**: Keyword details +- **Genres**: Genre lists for movies and TV +- **Certifications**: Content rating certifications +- **Changes**: Track content changes +- **Account**: User account operations +- **Review**: Review details +- **Watch Providers**: Streaming availability +- **TV Seasons**: Season-specific information +- **TV Episodes**: Episode-specific information +- **Find**: Lookup by external IDs (IMDb, TVDb, etc.) + +--- + +## Type System + +### Core Types + +#### Movie Types + +```typescript +interface Movie { + id: number; + title: string; + original_title: string; + overview: string; + release_date: string; + poster_path: string; + backdrop_path: string; + genre_ids: number[]; + adult: boolean; + original_language: string; + popularity: number; + vote_count: number; + vote_average: number; + video: boolean; +} + +interface MovieDetails extends Omit { + belongs_to_collection?: BelongsToCollection; + budget: number; + genres: Genre[]; + homepage: string; + imdb_id: string | null; + production_companies: ProductionCompany[]; + production_countries: ProductionCountry[]; + revenue: number; + runtime: number; + spoken_languages: SpokenLanguage[]; + status: string; + tagline: string; +} +``` + +#### TV Show Types + +```typescript +interface TV { + id: number; + name: string; + original_name: string; + overview: string; + first_air_date: string; + poster_path: string; + backdrop_path: string; + genre_ids: number[]; + origin_country: string[]; + adult: boolean; + original_language: string; + popularity: number; + vote_count: number; + vote_average: number; +} + +interface TvShowDetails extends Omit { + created_by: Creator[]; + episode_run_time: number[]; + genres: Genre[]; + homepage: string; + in_production: boolean; + languages: string[]; + last_air_date: string; + last_episode_to_air: Episode; + next_episode_to_air: Episode; + networks: Network[]; + number_of_episodes: number; + number_of_seasons: number; + production_companies: ProductionCompany[]; + production_countries: ProductionCountry[]; + seasons: Season[]; + spoken_languages: SpokenLanguage[]; + status: string; + tagline: string; + type: string; +} +``` + +#### Person Types + +```typescript +interface Person { + id: number; + name: string; + original_name: string; + profile_path: string; + adult: boolean; + known_for_department: string; + gender: number; + popularity: number; + known_for: KnownFor[]; +} + +interface PersonDetails { + id: number; + name: string; + biography: string; + birthday: string; + deathday: string; + place_of_birth: string; + profile_path: string; + adult: boolean; + known_for_department: string; + gender: number; + popularity: number; + also_known_as: string[]; + imdb_id: string; + homepage: string; +} +``` + +#### Credits Types + +```typescript +interface Cast { + adult: boolean; + gender: number; + id: number; + known_for_department: string; + name: string; + original_name: string; + popularity: number; + profile_path: string; + cast_id: number; + character: string; + credit_id: string; + order: number; +} + +interface Crew { + adult: boolean; + gender: number; + id: number; + known_for_department: string; + name: string; + original_name: string; + popularity: number; + profile_path: string; + credit_id: string; + department: string; + job: string; +} + +interface Credits { + id: number; + cast: Cast[]; + crew: Crew[]; +} +``` + +### Option Types + +```typescript +// Language options +interface LanguageOption { + language?: AvailableLanguage; // e.g., 'en-US', 'fr-FR' +} + +// Pagination +interface PageOption { + page?: number; +} + +// Region filtering +interface RegionOption { + region?: string; // ISO 3166-1 code +} + +// Date range for changes +interface ChangeOption extends PageOption { + start_date?: string; // YYYY-MM-DD + end_date?: string; // YYYY-MM-DD +} + +// Timezone +interface TimezoneOption { + timezone?: string; // e.g., 'America/New_York' +} +``` + +### Append to Response + +The `AppendToResponse` type enables type-safe dynamic response composition: + +```typescript +type AppendToResponseMovieKey = + | 'images' + | 'videos' + | 'credits' + | 'recommendations' + | 'reviews' + | 'similar' + | 'lists' + | 'release_dates' + | 'alternative_titles' + | 'external_ids' + | 'translations' + | 'watch/providers' + | 'keywords'; + +// Usage +const movie = await tmdb.movies.details(550, ['credits', 'videos']); +// TypeScript knows movie.credits and movie.videos exist! +``` + +### Error Response + +```typescript +interface ErrorResponse { + status_code: number; + status_message: string; + success: boolean; +} +``` + +--- + +## Advanced Usage + +### Append to Response + +Reduce API calls by requesting multiple resources in one request: + +```typescript +// Single request for movie with credits, videos, and images +const movie = await tmdb.movies.details( + 550, + ['credits', 'videos', 'images', 'recommendations'] +); + +// All data is available in the response +console.log(movie.title); +console.log(movie.credits.cast); +console.log(movie.videos.results); +console.log(movie.images.posters); +console.log(movie.recommendations.results); +``` + +### Pagination + +```typescript +// Get multiple pages of results +async function getAllPopularMovies() { + const allMovies = []; + let page = 1; + let totalPages = 1; + + do { + const response = await tmdb.movies.popular({ page }); + allMovies.push(...response.results); + totalPages = response.total_pages; + page++; + } while (page <= totalPages && page <= 10); // Limit to 10 pages + + return allMovies; +} +``` + +### Language Support + +```typescript +// Get movie details in different languages +const movieEN = await tmdb.movies.details(550, undefined, 'en-US'); +const movieFR = await tmdb.movies.details(550, undefined, 'fr-FR'); +const movieES = await tmdb.movies.details(550, undefined, 'es-ES'); + +console.log(movieEN.title); // "Fight Club" +console.log(movieFR.title); // "Fight Club" (French title) +console.log(movieES.title); // "El club de la lucha" +``` + +### Image URLs + +```typescript +import { getImagePath } from 'tmdb-ts'; + +// Get configuration first +const config = await tmdb.configuration.getApiConfiguration(); +const baseUrl = config.images.secure_base_url; + +// Helper function to build image URLs +function getFullImagePath(path: string, size: string = 'original'): string { + return `${baseUrl}${size}${path}`; +} + +// Usage +const movie = await tmdb.movies.details(550); +const posterUrl = getFullImagePath(movie.poster_path, 'w500'); +const backdropUrl = getFullImagePath(movie.backdrop_path, 'w1280'); +``` + +### Discover with Complex Filters + +```typescript +// Discover action movies from 2020 with high ratings +const movies = await tmdb.discover.movies({ + with_genres: '28', // Action + 'primary_release_date.gte': '2020-01-01', + 'primary_release_date.lte': '2020-12-31', + 'vote_average.gte': 7.0, + 'vote_count.gte': 100, + sort_by: 'popularity.desc', + page: 1, + language: 'en-US' +}); +``` + +### Search with Filters + +```typescript +// Search movies with year filter +const movies = await tmdb.search.movies({ + query: 'Star Wars', + year: 1977, + include_adult: false, + page: 1 +}); + +// Search TV shows with first air date year +const tvShows = await tmdb.search.tvShows({ + query: 'Friends', + first_air_date_year: 1994 +}); +``` + +### Find by External ID + +```typescript +// Find movie/TV show by IMDb ID +const result = await tmdb.find.byId('tt0137523', { // Fight Club IMDb ID + external_source: 'imdb_id' +}); + +console.log(result.movie_results); +console.log(result.tv_results); +``` + +### Get Trending Content + +```typescript +// Get trending movies today +const trendingToday = await tmdb.trending.trending('movie', 'day'); + +// Get trending TV shows this week +const trendingWeek = await tmdb.trending.trending('tv', 'week'); + +// Get all trending (movies, TV, people) +const trendingAll = await tmdb.trending.trending('all', 'week'); +``` + +--- + +## Error Handling + +### Error Types + +```typescript +interface ErrorResponse { + status_code: number; + status_message: string; + success: boolean; +} +``` + +### Handling Errors + +```typescript +try { + const movie = await tmdb.movies.details(999999999); +} catch (error) { + const tmdbError = error as ErrorResponse; + + console.error(`Error ${tmdbError.status_code}: ${tmdbError.status_message}`); + + // Handle specific error codes + switch (tmdbError.status_code) { + case 7: + console.error('Invalid API key'); + break; + case 34: + console.error('Resource not found'); + break; + default: + console.error('Unknown error'); + } +} +``` + +### Common Error Codes + +| Code | Description | +|------|-------------| +| 7 | Invalid API key | +| 34 | The resource you requested could not be found | +| 404 | Not Found | +| 401 | Invalid credentials | + +--- + +## Best Practices + +### 1. Reuse TMDB Instance + +```typescript +// ❌ Bad: Creating new instances +async function getMovie() { + const tmdb = new TMDB(token); + return await tmdb.movies.details(550); +} + +// ✅ Good: Reuse instance +const tmdb = new TMDB(token); + +async function getMovie() { + return await tmdb.movies.details(550); +} +``` + +### 2. Use Append to Response + +```typescript +// ❌ Bad: Multiple requests +const movie = await tmdb.movies.details(550); +const credits = await tmdb.movies.credits(550); +const videos = await tmdb.movies.videos(550); + +// ✅ Good: Single request +const movie = await tmdb.movies.details(550, ['credits', 'videos']); +console.log(movie.credits, movie.videos); +``` + +### 3. Handle Errors Gracefully + +```typescript +async function safeMovieDetails(id: number) { + try { + return await tmdb.movies.details(id); + } catch (error) { + console.error('Failed to fetch movie:', error); + return null; + } +} +``` + +### 4. Type Your Responses + +```typescript +import type { MovieDetails, Credits } from 'tmdb-ts'; + +async function getMovieWithCredits(id: number): Promise { + return await tmdb.movies.details(id, ['credits']); +} +``` + +### 5. Cache Configuration + +```typescript +// Cache configuration to avoid repeated requests +let cachedConfig: Configuration | null = null; + +async function getConfig(): Promise { + if (!cachedConfig) { + cachedConfig = await tmdb.configuration.getApiConfiguration(); + } + return cachedConfig; +} +``` + +### 6. Environment Variables + +```typescript +// Use environment variables for tokens +const tmdb = new TMDB(process.env.TMDB_ACCESS_TOKEN!); +``` + +### 7. Rate Limiting + +```typescript +// Implement rate limiting for bulk operations +async function fetchMoviesWithDelay(ids: number[]) { + const movies = []; + + for (const id of ids) { + movies.push(await tmdb.movies.details(id)); + // Add delay to avoid rate limits + await new Promise(resolve => setTimeout(resolve, 100)); + } + + return movies; +} +``` + +### 8. Batch Operations + +```typescript +// Process items in batches +async function fetchMoviesBatch(ids: number[], batchSize: number = 10) { + const results = []; + + for (let i = 0; i < ids.length; i += batchSize) { + const batch = ids.slice(i, i + batchSize); + const batchResults = await Promise.all( + batch.map(id => tmdb.movies.details(id)) + ); + results.push(...batchResults); + } + + return results; +} +``` + +--- + +## Full Examples + +### Movie Search Application + +```typescript +import { TMDB } from 'tmdb-ts'; + +const tmdb = new TMDB(process.env.TMDB_ACCESS_TOKEN!); + +interface MovieSearchResult { + id: number; + title: string; + year: number; + rating: number; + posterUrl: string; +} + +async function searchMovies(query: string): Promise { + try { + // Get configuration for image URLs + const config = await tmdb.configuration.getApiConfiguration(); + const baseUrl = config.images.secure_base_url; + + // Search for movies + const response = await tmdb.search.movies({ query, page: 1 }); + + // Transform results + return response.results.map(movie => ({ + id: movie.id, + title: movie.title, + year: new Date(movie.release_date).getFullYear(), + rating: movie.vote_average, + posterUrl: movie.poster_path + ? `${baseUrl}w500${movie.poster_path}` + : '' + })); + } catch (error) { + console.error('Search failed:', error); + return []; + } +} + +// Usage +const results = await searchMovies('Inception'); +console.log(results); +``` + +### TV Show Tracker + +```typescript +async function getTvShowInfo(id: number) { + const show = await tmdb.tvShows.details(id, [ + 'credits', + 'videos', + 'recommendations' + ]); + + return { + title: show.name, + overview: show.overview, + seasons: show.number_of_seasons, + episodes: show.number_of_episodes, + status: show.status, + nextEpisode: show.next_episode_to_air, + cast: show.credits.cast.slice(0, 10), + trailer: show.videos.results.find(v => v.type === 'Trailer'), + similar: show.recommendations.results.slice(0, 5) + }; +} +``` + +### Person Profile + +```typescript +async function getPersonProfile(id: number) { + const person = await tmdb.people.details(id, [ + 'movie_credits', + 'tv_credits', + 'external_ids' + ]); + + // Get top-rated movies + const topMovies = person.movie_credits.cast + .sort((a, b) => b.vote_average - a.vote_average) + .slice(0, 10); + + return { + name: person.name, + biography: person.biography, + birthday: person.birthday, + birthplace: person.place_of_birth, + knownFor: person.known_for_department, + topMovies: topMovies, + socialMedia: { + imdb: person.external_ids.imdb_id, + instagram: person.external_ids.instagram_id, + twitter: person.external_ids.twitter_id + } + }; +} +``` + +### Recommendation Engine + +```typescript +async function getMovieRecommendations(movieId: number, limit: number = 10) { + // Get similar movies + const similar = await tmdb.movies.similar(movieId, { page: 1 }); + + // Get recommendations + const recommendations = await tmdb.movies.recommendations(movieId, { page: 1 }); + + // Combine and deduplicate + const allMovies = [...similar.results, ...recommendations.results]; + const uniqueMovies = Array.from( + new Map(allMovies.map(m => [m.id, m])).values() + ); + + // Sort by popularity and limit + return uniqueMovies + .sort((a, b) => b.popularity - a.popularity) + .slice(0, limit); +} +``` + +--- + +## API Reference Quick Links + +- [TMDB API Documentation](https://developers.themoviedb.org/3) +- [TMDB Authentication](https://developers.themoviedb.org/3/authentication) +- [Image Configuration](https://developers.themoviedb.org/3/configuration/get-api-configuration) +- [Language Codes](https://developers.themoviedb.org/3/configuration/get-languages) + +--- + +## Contributing + +This library is a wrapper around the TMDB API. For issues or feature requests, please refer to the official repository. + +--- + +## License + +MIT License - See LICENSE.md for details + +--- + +## Support + +For questions and support: +- GitHub Issues: [tmdb-ts issues](https://github.com/blakejoy/tmdb-ts/issues) +- TMDB Forums: [The Movie Database Forums](https://www.themoviedb.org/talk) +- TMDB API Docs: [TMDB API Documentation](https://developers.themoviedb.org/3)