tmdb-kit 1.0.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +455 -196
- package/dist/cli.js +3823 -0
- package/dist/client.d.cts +71 -0
- package/dist/client.d.ts +71 -0
- package/dist/errors.d.cts +86 -0
- package/dist/errors.d.ts +86 -0
- package/dist/helpers/cache.d.cts +28 -0
- package/dist/helpers/cache.d.ts +28 -0
- package/dist/helpers/pagination.d.cts +35 -0
- package/dist/helpers/pagination.d.ts +35 -0
- package/dist/helpers/retry.d.cts +47 -0
- package/dist/helpers/retry.d.ts +47 -0
- package/dist/helpers/timeout.d.cts +20 -0
- package/dist/helpers/timeout.d.ts +20 -0
- package/dist/http.d.cts +80 -0
- package/dist/http.d.ts +80 -0
- package/dist/index.cjs +1115 -768
- package/dist/index.cjs.map +27 -1
- package/dist/index.d.cts +13 -783
- package/dist/index.d.ts +13 -783
- package/dist/index.js +1074 -744
- package/dist/index.js.map +27 -1
- package/dist/query.d.cts +91 -0
- package/dist/query.d.ts +91 -0
- package/dist/resources/configuration.d.cts +17 -0
- package/dist/resources/configuration.d.ts +17 -0
- package/dist/resources/genres.d.cts +13 -0
- package/dist/resources/genres.d.ts +13 -0
- package/dist/resources/images.d.cts +17 -0
- package/dist/resources/images.d.ts +17 -0
- package/dist/resources/movies.d.cts +21 -0
- package/dist/resources/movies.d.ts +21 -0
- package/dist/resources/people.d.cts +14 -0
- package/dist/resources/people.d.ts +14 -0
- package/dist/resources/search.d.cts +15 -0
- package/dist/resources/search.d.ts +15 -0
- package/dist/resources/trending.d.cts +23 -0
- package/dist/resources/trending.d.ts +23 -0
- package/dist/resources/tv.d.cts +30 -0
- package/dist/resources/tv.d.ts +30 -0
- package/dist/search-guards.d.cts +32 -0
- package/dist/search-guards.d.ts +32 -0
- package/dist/types.d.cts +550 -0
- package/dist/types.d.ts +550 -0
- package/package.json +26 -19
package/dist/index.js.map
CHANGED
|
@@ -1 +1,27 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["#apiKey","#accessToken","#baseUrl","#fetch","#headers","#createUrl","#createHeaders","#resolveFetch","#transport","#transport","#transport","#transform","#transport","#transport","#transport","#transport","#transport","#transport"],"sources":["../src/errors.ts","../src/query.ts","../src/http.ts","../src/resources/configuration.ts","../src/resources/genres.ts","../src/resources/images.ts","../src/resources/movies.ts","../src/resources/people.ts","../src/resources/search.ts","../src/resources/trending.ts","../src/resources/tv.ts","../src/client.ts","../src/search-guards.ts","../src/types.ts"],"sourcesContent":["import type { JsonValue } from './types'\n\n/** Raw TMDB error response body structure. */\nexport interface TMDBErrorResponseBody {\n success?: boolean\n status_code?: number\n status_message?: string\n}\n\n/** Options for constructing a {@link TMDBResponseError} or its subclasses. */\nexport interface TMDBResponseErrorOptions {\n body: JsonValue | undefined\n headers: Headers\n status: number\n statusText: string\n url: string\n}\n\n/** Base class for all SDK-originated errors. */\nexport class TMDBError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options)\n this.name = 'TMDBError'\n }\n}\n\n/** Thrown before a request is sent or when fetch itself rejects. */\nexport class TMDBRequestError extends TMDBError {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options)\n this.name = 'TMDBRequestError'\n }\n}\n\n/** Thrown when TMDB returns a non-2xx response. */\nexport class TMDBResponseError extends TMDBError {\n readonly body: JsonValue | undefined\n readonly headers: Headers\n readonly requestId: string | null\n readonly status: number\n readonly statusCode: number | undefined\n readonly statusMessage: string | undefined\n readonly statusText: string\n readonly url: string\n\n constructor(message: string, options: TMDBResponseErrorOptions) {\n super(message)\n this.name = 'TMDBResponseError'\n this.body = options.body\n this.headers = options.headers\n this.requestId = options.headers.get('x-request-id')\n this.status = options.status\n this.statusText = options.statusText\n this.url = options.url\n\n const body = isErrorResponseBody(options.body) ? options.body : undefined\n this.statusCode = body?.status_code\n this.statusMessage = body?.status_message\n }\n\n /** True when TMDB has asked the caller to back off (HTTP 429). */\n get isRateLimit(): boolean {\n return this.status === 429\n }\n\n /** True when the resource was not found (HTTP 404). */\n get isNotFound(): boolean {\n return this.status === 404\n }\n\n /** True when the request was rejected as unauthenticated (HTTP 401). */\n get isUnauthorized(): boolean {\n return this.status === 401\n }\n\n /** True when the request was rejected as forbidden (HTTP 403). */\n get isForbidden(): boolean {\n return this.status === 403\n }\n\n /** True when the upstream returned a 5xx server error. */\n get isServerError(): boolean {\n return this.status >= 500 && this.status < 600\n }\n}\n\nexport interface TMDBRateLimitErrorOptions extends TMDBResponseErrorOptions {\n /** Seconds to wait before retrying. Parsed from the `Retry-After` header. */\n retryAfter: number\n}\n\n/**\n * Thrown when TMDB returns HTTP 429.\n *\n * The SDK does NOT retry automatically — that decision is left to the\n * caller, since retry policies vary widely. Inspect `retryAfter` to\n * implement your own backoff.\n */\nexport class TMDBRateLimitError extends TMDBResponseError {\n readonly retryAfter: number\n\n constructor(message: string, options: TMDBRateLimitErrorOptions) {\n super(message, options)\n this.name = 'TMDBRateLimitError'\n this.retryAfter = options.retryAfter\n }\n}\n\n/**\n * Create the appropriate error instance for a non-2xx TMDB response.\n *\n * Returns a {@link TMDBRateLimitError} when the status is 429, otherwise\n * a generic {@link TMDBResponseError}. The error message is extracted from\n * the TMDB `status_message` field when available.\n */\nexport function createResponseError(\n options: TMDBResponseErrorOptions,\n): TMDBResponseError {\n const body = isErrorResponseBody(options.body) ? options.body : undefined\n const message = body?.status_message ?? `${options.status} ${options.statusText}`.trim()\n\n if (options.status === 429) {\n return new TMDBRateLimitError(message, {\n ...options,\n retryAfter: parseRetryAfter(options.headers.get('retry-after')),\n })\n }\n\n return new TMDBResponseError(message, options)\n}\n\n/**\n * Parse the `Retry-After` header into seconds. Accepts both delta-seconds\n * (e.g. \"5\") and HTTP-date forms (e.g. \"Wed, 21 Oct 2026 07:28:00 GMT\").\n * Falls back to 1 second when the header is missing or unparseable.\n */\nexport function parseRetryAfter(value: string | null | undefined): number {\n if (value === null || value === undefined) {\n return 1\n }\n\n const trimmed = value.trim()\n if (trimmed === '') {\n return 1\n }\n\n const seconds = Number(trimmed)\n if (Number.isFinite(seconds) && seconds >= 0) {\n return seconds\n }\n\n const date = Date.parse(trimmed)\n if (Number.isFinite(date)) {\n const deltaMs = date - Date.now()\n return Math.max(1, Math.ceil(deltaMs / 1000))\n }\n\n return 1\n}\n\n/** Check if a value has the shape of a TMDB error response body. */\nfunction isErrorResponseBody(value: unknown): value is TMDBErrorResponseBody {\n return typeof value === 'object' && value !== null\n}\n","import { TMDBRequestError } from './errors'\nimport type { ImageSize, RegionCode, LanguageCode, TrendingTimeWindow } from './types'\n\n/** Primitives allowed as query parameter values. */\nexport type QueryPrimitive = string | number | boolean\n\n/** A single query parameter value: primitive, array, or nullish. */\nexport type QueryValue = QueryPrimitive | readonly QueryPrimitive[] | null | undefined\n\n/** Key-value map of query parameters for API requests. */\nexport type QueryParams = Record<string, QueryValue>\n\n/** Default query parameters inherited from the client configuration. */\nexport interface QueryDefaults {\n language?: LanguageCode\n region?: RegionCode\n}\n\nexport const DEFAULT_API_BASE_URL = 'https://api.themoviedb.org/3'\nexport const DEFAULT_IMAGE_BASE_URL = 'https://image.tmdb.org/t/p'\n\n/**\n * Append query parameters to a URL object.\n *\n * - `undefined` and `null` values are skipped.\n * - Arrays are joined with commas (TMDB convention).\n * - All values are converted to strings.\n */\nexport function appendQuery(url: URL, query: QueryParams): void {\n for (const [key, value] of Object.entries(query)) {\n if (value === undefined || value === null) {\n continue\n }\n\n if (Array.isArray(value)) {\n url.searchParams.set(key, value.map(String).join(','))\n continue\n }\n\n url.searchParams.set(key, String(value))\n }\n}\n\n/**\n * Merge a language query parameter with client defaults.\n *\n * If `query.language` is set it takes precedence; otherwise the client's\n * default language is used.\n */\nexport function withLanguage(\n defaults: QueryDefaults,\n query: QueryParams,\n): QueryParams {\n const language = typeof query.language === 'string' ? query.language : defaults.language\n\n return {\n ...query,\n language,\n }\n}\n\n/**\n * Merge language and region defaults for list endpoints.\n *\n * Combines {@link withLanguage} with region fallback from client defaults.\n */\nexport function withListDefaults(\n defaults: QueryDefaults,\n query: QueryParams,\n): QueryParams {\n const region = typeof query.region === 'string' ? query.region : defaults.region\n\n return {\n ...withLanguage(defaults, query),\n region,\n }\n}\n\n/**\n * Convert a string or string array to a comma-separated list.\n *\n * Returns `undefined` if the input is `undefined` (skips the parameter).\n * TMDB uses comma-separated values for multi-value query parameters.\n */\nexport function toCommaList(value: string | readonly string[] | undefined): string | undefined {\n if (value === undefined) {\n return undefined\n }\n\n return typeof value === 'string' ? value : value.join(',')\n}\n\n/**\n * Validate and convert a numeric ID to a string for use in URL paths.\n *\n * @throws {TMDBRequestError} If `value` is not a positive integer.\n */\nexport function toId(value: number, name: string): string {\n if (!Number.isInteger(value) || value <= 0) {\n throw new TMDBRequestError(`${name} must be a positive integer`)\n }\n\n return String(value)\n}\n\n/**\n * Validate and trim a search query string.\n *\n * @throws {TMDBRequestError} If the query is empty after trimming.\n */\nexport function toSearchQuery(value: string): string {\n const query = value.trim()\n\n if (query.length === 0) {\n throw new TMDBRequestError('search query must not be empty')\n }\n\n return query\n}\n\n/**\n * Validate a trending time window value.\n *\n * @throws {TMDBRequestError} If `value` is not `\"day\"` or `\"week\"`.\n */\nexport function toTimeWindow(value: TrendingTimeWindow): TrendingTimeWindow {\n if (value !== 'day' && value !== 'week') {\n throw new TMDBRequestError('timeWindow must be either \"day\" or \"week\"')\n }\n\n return value\n}\n\nexport interface BuildImageUrlOptions {\n baseUrl?: string\n /**\n * Transform the resolved TMDB image URL before returning it. Use this to\n * route requests through a CDN, image proxy, or to add signatures.\n */\n transform?: (url: string) => string\n}\n\n/**\n * Build a full TMDB image URL from the path returned by API payloads.\n * Returns null for nullish image paths so UI code can branch naturally.\n */\nexport function buildImageUrl(\n path: string | null | undefined,\n size: ImageSize = 'original',\n options: BuildImageUrlOptions = {},\n): string | null {\n if (path === undefined || path === null || path.trim() === '') {\n return null\n }\n\n const baseUrl = normalizeBaseUrl(options.baseUrl ?? DEFAULT_IMAGE_BASE_URL)\n const normalizedPath = path.startsWith('/') ? path : `/${path}`\n const url = `${baseUrl}/${size}${normalizedPath}`\n\n return options.transform ? options.transform(url) : url\n}\n\n/**\n * Strip trailing slashes from a base URL to ensure consistent path joining.\n */\nexport function normalizeBaseUrl(baseUrl: string): string {\n return baseUrl.replace(/\\/+$/, '')\n}\n","import { createResponseError, TMDBRequestError } from './errors'\nimport {\n appendQuery,\n DEFAULT_API_BASE_URL,\n DEFAULT_IMAGE_BASE_URL,\n normalizeBaseUrl,\n type QueryDefaults,\n type QueryParams,\n} from './query'\nimport type { ImageUrlTransform } from './resources/images'\nimport type { JsonValue, LanguageCode, RegionCode } from './types'\n\nexport type { ImageUrlTransform }\n\n/**\n * A minimal fetch-like function signature. Any runtime's native `fetch`\n * or a test double conforming to this shape can be used.\n */\nexport type FetchLike = (input: string, init?: RequestInit) => Promise<Response>\n\nexport interface TMDBAccessTokenAuth {\n /** TMDB API Read Access Token. Sent as an Authorization Bearer header. */\n accessToken: string\n apiKey?: never\n}\n\nexport interface TMDBApiKeyAuth {\n /** Legacy v3 API key. Sent as api_key query parameter. */\n apiKey: string\n accessToken?: never\n}\n\nexport type TMDBAuth = TMDBAccessTokenAuth | TMDBApiKeyAuth\n\n/** Internal defaults resolved during client construction. */\nexport interface TMDBClientDefaults extends QueryDefaults {\n imageBaseUrl: string\n}\n\nexport interface TMDBImagesOptions {\n /**\n * Default transform applied to every URL produced by the ImagesHelper.\n * Use this to route TMDB image requests through a CDN, image proxy, or\n * to add signed query parameters. Individual calls can still override it\n * via ImagesHelper.url(path, size, { transform }).\n */\n transform?: ImageUrlTransform\n}\n\nexport type TMDBClientOptions = TMDBAuth & {\n /** Defaults to https://api.themoviedb.org/3. Useful for tests or proxies. */\n baseUrl?: string\n /** Inject a fetch implementation for tests, custom runtimes, or instrumentation. */\n fetch?: FetchLike\n /** Default language for endpoints that accept a language query parameter. */\n defaultLanguage?: LanguageCode\n /** Default region for movie list/search endpoints that accept a region query parameter. */\n defaultRegion?: RegionCode\n /** Custom image host. Defaults to https://image.tmdb.org/t/p. */\n imageBaseUrl?: string\n /** Image-helper configuration: host overrides and URL transforms. */\n images?: TMDBImagesOptions\n /** Additional headers merged into every request before authentication is applied. */\n headers?: HeadersInit\n}\n\n/** Per-request overrides applied when making a single API call. */\nexport interface TMDBRequestOptions {\n headers?: HeadersInit\n query?: QueryParams\n signal?: AbortSignal\n}\n\n/**\n * Transport abstraction for making HTTP requests to the TMDB API.\n *\n * The built-in {@link TMDBHttpClient} implements this interface. You can\n * provide a custom implementation via {@link TMDBFactoryOptions.transport}\n * for testing, caching, or instrumentation.\n */\nexport interface TMDBTransport {\n readonly defaults: TMDBClientDefaults\n get<T>(path: string, options?: TMDBRequestOptions): Promise<T>\n}\n\n/**\n * Built-in HTTP transport that uses the Fetch API.\n *\n * Handles authentication (API key or access token), URL construction,\n * request headers, and response parsing. Use the factory function\n * {@link createTMDB} instead of instantiating this directly.\n */\nexport class TMDBHttpClient implements TMDBTransport {\n readonly defaults: TMDBClientDefaults\n readonly imageTransform: ImageUrlTransform | undefined\n\n readonly #apiKey: string | undefined\n readonly #accessToken: string | undefined\n readonly #baseUrl: string\n readonly #fetch: FetchLike | undefined\n readonly #headers: HeadersInit | undefined\n\n constructor(options: TMDBClientOptions) {\n const accessToken = normalizeSecret('accessToken' in options ? options.accessToken : undefined)\n const apiKey = normalizeSecret('apiKey' in options ? options.apiKey : undefined)\n\n if (Boolean(accessToken) === Boolean(apiKey)) {\n throw new TMDBRequestError('Provide exactly one of accessToken or apiKey')\n }\n\n this.#accessToken = accessToken\n this.#apiKey = apiKey\n this.#baseUrl = normalizeBaseUrl(options.baseUrl ?? DEFAULT_API_BASE_URL)\n this.#fetch = options.fetch\n this.#headers = options.headers\n this.defaults = {\n imageBaseUrl: normalizeBaseUrl(options.imageBaseUrl ?? DEFAULT_IMAGE_BASE_URL),\n language: options.defaultLanguage,\n region: options.defaultRegion,\n }\n this.imageTransform = options.images?.transform\n }\n\n async get<T>(path: string, options: TMDBRequestOptions = {}): Promise<T> {\n const url = this.#createUrl(path, options.query ?? {})\n const headers = this.#createHeaders(options.headers)\n const fetchImpl = this.#resolveFetch()\n\n let response: Response\n\n try {\n response = await fetchImpl(url, {\n headers,\n method: 'GET',\n signal: options.signal,\n })\n } catch (error) {\n throw new TMDBRequestError(`TMDB request failed: ${String(error)}`, { cause: error })\n }\n\n const body = await readJson(response)\n\n if (!response.ok) {\n throw createResponseError({\n body,\n headers: response.headers,\n status: response.status,\n statusText: response.statusText,\n url,\n })\n }\n\n return body as T\n }\n\n #resolveFetch(): FetchLike {\n if (this.#fetch !== undefined) {\n return this.#fetch\n }\n\n const globalFetch = globalThis.fetch\n\n if (typeof globalFetch !== 'function') {\n throw new TMDBRequestError('No fetch implementation found. Pass options.fetch in this runtime.')\n }\n\n return globalFetch.bind(globalThis)\n }\n\n #createHeaders(headersInit: HeadersInit | undefined): Headers {\n const headers = new Headers(this.#headers)\n const requestHeaders = new Headers(headersInit)\n\n headers.set('Accept', 'application/json')\n\n for (const [key, value] of requestHeaders) {\n headers.set(key, value)\n }\n\n if (this.#accessToken !== undefined) {\n headers.set('Authorization', `Bearer ${this.#accessToken}`)\n }\n\n return headers\n }\n\n #createUrl(path: string, query: QueryParams): string {\n const relativePath = path.replace(/^\\/+/, '')\n const url = new URL(relativePath, `${this.#baseUrl}/`)\n\n appendQuery(url, {\n ...query,\n api_key: this.#apiKey,\n })\n\n return url.toString()\n }\n}\n\n/**\n * Read and parse a JSON response body.\n *\n * Returns `undefined` for empty responses. If the body is not valid JSON,\n * the raw text string is returned as-is (TMDB occasionally returns plain\n * text for certain error conditions).\n */\nasync function readJson(response: Response): Promise<JsonValue | undefined> {\n const text = await response.text()\n\n if (text.length === 0) {\n return undefined\n }\n\n try {\n return JSON.parse(text) as JsonValue\n } catch {\n return text\n }\n}\n\n/**\n * Normalize a secret value by trimming whitespace and treating empty\n * strings as undefined (not provided).\n */\nfunction normalizeSecret(value: string | undefined): string | undefined {\n const secret = value?.trim()\n return secret === '' ? undefined : secret\n}\n","import type { TMDBTransport } from '../http'\nimport type { Configuration, Country, JobDepartment, Language, Timezone } from '../types'\n\n/**\n * Access TMDB configuration data (image sizes, countries, languages, etc.).\n *\n * Obtained via `client.configuration`.\n */\nexport class ConfigurationResource {\n readonly #transport: TMDBTransport\n\n constructor(transport: TMDBTransport) {\n this.#transport = transport\n }\n\n details(): Promise<Configuration> {\n return this.#transport.get('/configuration')\n }\n\n countries(): Promise<Country[]> {\n return this.#transport.get('/configuration/countries')\n }\n\n jobs(): Promise<JobDepartment[]> {\n return this.#transport.get('/configuration/jobs')\n }\n\n languages(): Promise<Language[]> {\n return this.#transport.get('/configuration/languages')\n }\n\n primaryTranslations(): Promise<string[]> {\n return this.#transport.get('/configuration/primary_translations')\n }\n\n timezones(): Promise<Timezone[]> {\n return this.#transport.get('/configuration/timezones')\n }\n}\n","import type { TMDBTransport } from '../http'\nimport { withLanguage } from '../query'\nimport type { GenresResponse, LanguageOptions } from '../types'\n\n/**\n * Access TMDB genre lists for movies and TV shows.\n *\n * Obtained via `client.genres`.\n */\nexport class GenresResource {\n readonly #transport: TMDBTransport\n\n constructor(transport: TMDBTransport) {\n this.#transport = transport\n }\n\n movies(options: LanguageOptions = {}): Promise<GenresResponse> {\n return this.#transport.get('/genre/movie/list', {\n query: withLanguage(this.#transport.defaults, {\n language: options.language,\n }),\n })\n }\n\n tv(options: LanguageOptions = {}): Promise<GenresResponse> {\n return this.#transport.get('/genre/tv/list', {\n query: withLanguage(this.#transport.defaults, {\n language: options.language,\n }),\n })\n }\n}\n","import type { TMDBTransport } from '../http'\nimport { buildImageUrl } from '../query'\nimport type { ImageSize } from '../types'\n\n/** Function that transforms a TMDB image URL (e.g. for CDN proxying). */\nexport type ImageUrlTransform = (url: string) => string\n\n/**\n * Helper for constructing TMDB image URLs from API path values.\n *\n * Obtained via `client.images`. Supports optional URL transforms for\n * routing image requests through a CDN or proxy.\n */\nexport class ImagesHelper {\n readonly #transport: TMDBTransport\n readonly #transform: ImageUrlTransform | undefined\n\n constructor(transport: TMDBTransport, transform?: ImageUrlTransform) {\n this.#transport = transport\n this.#transform = transform\n }\n\n url(\n path: string | null | undefined,\n size: ImageSize = 'original',\n options: { transform?: ImageUrlTransform } = {},\n ): string | null {\n return buildImageUrl(path, size, {\n baseUrl: this.#transport.defaults.imageBaseUrl,\n transform: options.transform ?? this.#transform,\n })\n }\n}\n","import type { TMDBTransport } from '../http'\nimport { toCommaList, toId, withLanguage, withListDefaults, type QueryParams } from '../query'\nimport type {\n CreditsResponse,\n ImageQueryOptions,\n ImagesResponse,\n ListOptions,\n MovieDetails,\n MovieDetailsOptions,\n MovieSummary,\n PagedResponse,\n TMDBObject,\n VideosResponse,\n} from '../types'\n\n/**\n * Access TMDB movie endpoints (popular, top-rated, details, credits, etc.).\n *\n * Obtained via `client.movies`.\n */\nexport class MoviesResource {\n readonly #transport: TMDBTransport\n\n constructor(transport: TMDBTransport) {\n this.#transport = transport\n }\n\n popular(options: ListOptions = {}): Promise<PagedResponse<MovieSummary>> {\n return this.#transport.get('/movie/popular', {\n query: movieListQuery(this.#transport, options),\n })\n }\n\n topRated(options: ListOptions = {}): Promise<PagedResponse<MovieSummary>> {\n return this.#transport.get('/movie/top_rated', {\n query: movieListQuery(this.#transport, options),\n })\n }\n\n nowPlaying(options: ListOptions = {}): Promise<PagedResponse<MovieSummary>> {\n return this.#transport.get('/movie/now_playing', {\n query: movieListQuery(this.#transport, options),\n })\n }\n\n upcoming(options: ListOptions = {}): Promise<PagedResponse<MovieSummary>> {\n return this.#transport.get('/movie/upcoming', {\n query: movieListQuery(this.#transport, options),\n })\n }\n\n details<TAppend extends TMDBObject = TMDBObject>(\n movieId: number,\n options: MovieDetailsOptions = {},\n ): Promise<MovieDetails & TAppend> {\n return this.#transport.get(`/movie/${toId(movieId, 'movieId')}`, {\n query: withLanguage(this.#transport.defaults, {\n append_to_response: toCommaList(options.appendToResponse),\n language: options.language,\n }),\n })\n }\n\n credits(movieId: number, options: Pick<ListOptions, 'language'> = {}): Promise<CreditsResponse> {\n return this.#transport.get(`/movie/${toId(movieId, 'movieId')}/credits`, {\n query: withLanguage(this.#transport.defaults, {\n language: options.language,\n }),\n })\n }\n\n images(movieId: number, options: ImageQueryOptions = {}): Promise<ImagesResponse> {\n return this.#transport.get(`/movie/${toId(movieId, 'movieId')}/images`, {\n query: withLanguage(this.#transport.defaults, {\n include_image_language: toCommaList(options.includeImageLanguage),\n language: options.language,\n }),\n })\n }\n\n recommendations(movieId: number, options: ListOptions = {}): Promise<PagedResponse<MovieSummary>> {\n return this.#transport.get(`/movie/${toId(movieId, 'movieId')}/recommendations`, {\n query: movieListQuery(this.#transport, options),\n })\n }\n\n similar(movieId: number, options: ListOptions = {}): Promise<PagedResponse<MovieSummary>> {\n return this.#transport.get(`/movie/${toId(movieId, 'movieId')}/similar`, {\n query: movieListQuery(this.#transport, options),\n })\n }\n\n videos(movieId: number, options: Pick<ListOptions, 'language'> = {}): Promise<VideosResponse> {\n return this.#transport.get(`/movie/${toId(movieId, 'movieId')}/videos`, {\n query: withLanguage(this.#transport.defaults, {\n language: options.language,\n }),\n })\n }\n}\n\n/** Build query parameters for movie list endpoints. */\nfunction movieListQuery(transport: TMDBTransport, options: ListOptions): QueryParams {\n return withListDefaults(transport.defaults, {\n language: options.language,\n page: options.page,\n region: options.region,\n })\n}\n","import type { TMDBTransport } from '../http'\nimport { toId, withLanguage, type QueryParams } from '../query'\nimport type { LanguageOptions, ListOptions, PagedResponse, PersonDetails, PersonSummary } from '../types'\n\n/**\n * Access TMDB person (actor, director, etc.) endpoints.\n *\n * Obtained via `client.people`.\n */\nexport class PeopleResource {\n readonly #transport: TMDBTransport\n\n constructor(transport: TMDBTransport) {\n this.#transport = transport\n }\n\n popular(options: Omit<ListOptions, 'region'> = {}): Promise<PagedResponse<PersonSummary>> {\n return this.#transport.get('/person/popular', {\n query: peopleListQuery(this.#transport, options),\n })\n }\n\n details(personId: number, options: LanguageOptions = {}): Promise<PersonDetails> {\n return this.#transport.get(`/person/${toId(personId, 'personId')}`, {\n query: withLanguage(this.#transport.defaults, {\n language: options.language,\n }),\n })\n }\n}\n\n/** Build query parameters for person list endpoints. */\nfunction peopleListQuery(\n transport: TMDBTransport,\n options: Omit<ListOptions, 'region'>,\n): QueryParams {\n return withLanguage(transport.defaults, {\n language: options.language,\n page: options.page,\n })\n}\n","import type { TMDBTransport } from '../http'\nimport { toSearchQuery, withLanguage, withListDefaults, type QueryParams } from '../query'\nimport type {\n MovieSearchOptions,\n MovieSearchResult,\n MultiSearchOptions,\n PagedResponse,\n PersonSearchResult,\n SearchMultiResult,\n TVSearchOptions,\n TVSearchResult,\n} from '../types'\n\n/**\n * Search TMDB for movies, TV shows, people, or all media types.\n *\n * Obtained via `client.search`.\n */\nexport class SearchResource {\n readonly #transport: TMDBTransport\n\n constructor(transport: TMDBTransport) {\n this.#transport = transport\n }\n\n movies(query: string, options: MovieSearchOptions = {}): Promise<PagedResponse<MovieSearchResult>> {\n return this.#transport.get('/search/movie', {\n query: movieSearchQuery(this.#transport, query, options),\n })\n }\n\n tv(query: string, options: TVSearchOptions = {}): Promise<PagedResponse<TVSearchResult>> {\n return this.#transport.get('/search/tv', {\n query: tvSearchQuery(this.#transport, query, options),\n })\n }\n\n people(query: string, options: MultiSearchOptions = {}): Promise<PagedResponse<PersonSearchResult>> {\n return this.#transport.get('/search/person', {\n query: commonSearchQuery(this.#transport, query, options),\n })\n }\n\n async multi(\n query: string,\n options: MultiSearchOptions = {},\n ): Promise<PagedResponse<SearchMultiResult>> {\n const response = await this.#transport.get<PagedResponse<SearchMultiResult>>('/search/multi', {\n query: commonSearchQuery(this.#transport, query, options),\n })\n\n const excluded = options.exclude\n if (excluded === undefined || excluded.length === 0) {\n return response\n }\n\n const excludedSet = new Set<string>(excluded)\n return {\n ...response,\n results: response.results.filter((result) => !excludedSet.has(result.media_type)),\n }\n }\n}\n\n/** Build query parameters for movie search. */\nfunction movieSearchQuery(\n transport: TMDBTransport,\n query: string,\n options: MovieSearchOptions,\n): QueryParams {\n return withListDefaults(transport.defaults, {\n include_adult: options.includeAdult,\n language: options.language,\n page: options.page,\n primary_release_year: options.primaryReleaseYear,\n query: toSearchQuery(query),\n region: options.region,\n year: options.year,\n })\n}\n\n/** Build query parameters for TV search. */\nfunction tvSearchQuery(\n transport: TMDBTransport,\n query: string,\n options: TVSearchOptions,\n): QueryParams {\n return withLanguage(transport.defaults, {\n first_air_date_year: options.firstAirDateYear,\n include_adult: options.includeAdult,\n language: options.language,\n page: options.page,\n query: toSearchQuery(query),\n year: options.year,\n })\n}\n\n/** Build query parameters for person and multi-search. */\nfunction commonSearchQuery(\n transport: TMDBTransport,\n query: string,\n options: MultiSearchOptions,\n): QueryParams {\n return withLanguage(transport.defaults, {\n include_adult: options.includeAdult,\n language: options.language,\n page: options.page,\n query: toSearchQuery(query),\n })\n}\n","import type { TMDBTransport } from '../http'\nimport { toTimeWindow, withLanguage } from '../query'\nimport type {\n LanguageOptions,\n MovieSummary,\n PagedResponse,\n PersonSummary,\n TrendingResult,\n TrendingTimeWindow,\n TVSummary,\n} from '../types'\n\n/**\n * Access TMDB trending content (movies, TV, people) for day/week windows.\n *\n * Obtained via `client.trending`.\n */\nexport class TrendingResource {\n readonly #transport: TMDBTransport\n\n constructor(transport: TMDBTransport) {\n this.#transport = transport\n }\n\n all(\n timeWindow: TrendingTimeWindow = 'day',\n options: LanguageOptions = {},\n ): Promise<PagedResponse<TrendingResult>> {\n return this.#transport.get(`/trending/all/${toTimeWindow(timeWindow)}`, {\n query: withLanguage(this.#transport.defaults, {\n language: options.language,\n }),\n })\n }\n\n movies(\n timeWindow: TrendingTimeWindow = 'day',\n options: LanguageOptions = {},\n ): Promise<PagedResponse<MovieSummary & { media_type?: 'movie' }>> {\n return this.#transport.get(`/trending/movie/${toTimeWindow(timeWindow)}`, {\n query: withLanguage(this.#transport.defaults, {\n language: options.language,\n }),\n })\n }\n\n tv(\n timeWindow: TrendingTimeWindow = 'day',\n options: LanguageOptions = {},\n ): Promise<PagedResponse<TVSummary & { media_type?: 'tv' }>> {\n return this.#transport.get(`/trending/tv/${toTimeWindow(timeWindow)}`, {\n query: withLanguage(this.#transport.defaults, {\n language: options.language,\n }),\n })\n }\n\n people(\n timeWindow: TrendingTimeWindow = 'day',\n options: LanguageOptions = {},\n ): Promise<PagedResponse<PersonSummary & { media_type?: 'person' }>> {\n return this.#transport.get(`/trending/person/${toTimeWindow(timeWindow)}`, {\n query: withLanguage(this.#transport.defaults, {\n language: options.language,\n }),\n })\n }\n}\n","import type { TMDBTransport } from '../http'\nimport { toCommaList, toId, withLanguage, type QueryParams } from '../query'\nimport type {\n CreditsResponse,\n ImageQueryOptions,\n ImagesResponse,\n LanguageOptions,\n ListOptions,\n PagedResponse,\n TMDBObject,\n TVDetails,\n TVDetailsOptions,\n TVSeasonDetails,\n TVSeasonDetailsOptions,\n TVSummary,\n VideosResponse,\n} from '../types'\n\n/**\n * Access TMDB TV show endpoints (popular, top-rated, details, seasons, etc.).\n *\n * Obtained via `client.tv`.\n */\nexport class TVResource {\n readonly #transport: TMDBTransport\n\n constructor(transport: TMDBTransport) {\n this.#transport = transport\n }\n\n popular(options: Omit<ListOptions, 'region'> = {}): Promise<PagedResponse<TVSummary>> {\n return this.#transport.get('/tv/popular', {\n query: tvListQuery(this.#transport, options),\n })\n }\n\n topRated(options: Omit<ListOptions, 'region'> = {}): Promise<PagedResponse<TVSummary>> {\n return this.#transport.get('/tv/top_rated', {\n query: tvListQuery(this.#transport, options),\n })\n }\n\n airingToday(options: Omit<ListOptions, 'region'> = {}): Promise<PagedResponse<TVSummary>> {\n return this.#transport.get('/tv/airing_today', {\n query: tvListQuery(this.#transport, options),\n })\n }\n\n onTheAir(options: Omit<ListOptions, 'region'> = {}): Promise<PagedResponse<TVSummary>> {\n return this.#transport.get('/tv/on_the_air', {\n query: tvListQuery(this.#transport, options),\n })\n }\n\n details<TAppend extends TMDBObject = TMDBObject>(\n seriesId: number,\n options: TVDetailsOptions = {},\n ): Promise<TVDetails & TAppend> {\n return this.#transport.get(`/tv/${toId(seriesId, 'seriesId')}`, {\n query: withLanguage(this.#transport.defaults, {\n append_to_response: toCommaList(options.appendToResponse),\n language: options.language,\n }),\n })\n }\n\n credits(seriesId: number, options: LanguageOptions = {}): Promise<CreditsResponse> {\n return this.#transport.get(`/tv/${toId(seriesId, 'seriesId')}/credits`, {\n query: withLanguage(this.#transport.defaults, {\n language: options.language,\n }),\n })\n }\n\n images(seriesId: number, options: ImageQueryOptions = {}): Promise<ImagesResponse> {\n return this.#transport.get(`/tv/${toId(seriesId, 'seriesId')}/images`, {\n query: withLanguage(this.#transport.defaults, {\n include_image_language: toCommaList(options.includeImageLanguage),\n language: options.language,\n }),\n })\n }\n\n recommendations(seriesId: number, options: Omit<ListOptions, 'region'> = {}): Promise<PagedResponse<TVSummary>> {\n return this.#transport.get(`/tv/${toId(seriesId, 'seriesId')}/recommendations`, {\n query: tvListQuery(this.#transport, options),\n })\n }\n\n similar(seriesId: number, options: Omit<ListOptions, 'region'> = {}): Promise<PagedResponse<TVSummary>> {\n return this.#transport.get(`/tv/${toId(seriesId, 'seriesId')}/similar`, {\n query: tvListQuery(this.#transport, options),\n })\n }\n\n videos(seriesId: number, options: LanguageOptions = {}): Promise<VideosResponse> {\n return this.#transport.get(`/tv/${toId(seriesId, 'seriesId')}/videos`, {\n query: withLanguage(this.#transport.defaults, {\n language: options.language,\n }),\n })\n }\n\n seasonDetails<TAppend extends TMDBObject = TMDBObject>(\n seriesId: number,\n seasonNumber: number,\n options: TVSeasonDetailsOptions = {},\n ): Promise<TVSeasonDetails & TAppend> {\n return this.#transport.get(\n `/tv/${toId(seriesId, 'seriesId')}/season/${toId(seasonNumber, 'seasonNumber')}`,\n {\n query: withLanguage(this.#transport.defaults, {\n append_to_response: toCommaList(options.appendToResponse),\n language: options.language,\n }),\n },\n )\n }\n}\n\n/** Build query parameters for TV list endpoints. */\nfunction tvListQuery(\n transport: TMDBTransport,\n options: Omit<ListOptions, 'region'>,\n): QueryParams {\n return withLanguage(transport.defaults, {\n language: options.language,\n page: options.page,\n })\n}\n","import { TMDBHttpClient, type TMDBClientOptions, type TMDBRequestOptions, type TMDBTransport } from './http'\nimport { ConfigurationResource } from './resources/configuration'\nimport { GenresResource } from './resources/genres'\nimport { ImagesHelper } from './resources/images'\nimport { MoviesResource } from './resources/movies'\nimport { PeopleResource } from './resources/people'\nimport { SearchResource } from './resources/search'\nimport { TrendingResource } from './resources/trending'\nimport { TVResource } from './resources/tv'\n\n/**\n * Options accepted by {@link createTMDB} and the {@link TMDBClient} constructor.\n *\n * Extends {@link TMDBClientOptions} with an optional {@link TMDBTransport} so\n * callers can plug in a custom transport (typically for tests, caching, or\n * instrumentation) without having to mock `fetch` or the factory itself.\n */\nexport type TMDBFactoryOptions = TMDBClientOptions & {\n transport?: TMDBTransport\n}\n\n/**\n * Main SDK entry point.\n *\n * Resource properties are intentionally small and explicit. The SDK focuses on\n * common TMDB workflows first, while request<T>() keeps uncommon endpoints easy\n * to call without waiting for a generated surface area.\n */\nexport class TMDBClient {\n readonly configuration: ConfigurationResource\n readonly genres: GenresResource\n readonly images: ImagesHelper\n readonly movies: MoviesResource\n readonly people: PeopleResource\n readonly search: SearchResource\n readonly trending: TrendingResource\n readonly tv: TVResource\n\n readonly #transport: TMDBTransport\n\n constructor(options: TMDBFactoryOptions) {\n const { transport, images, ...httpOptions } = options\n // When the caller supplies a custom transport we still want to honor the\n // global images.transform option; otherwise read it back from the HTTP\n // client after it has been constructed.\n const fallbackTransform = images?.transform\n const builtInClient = transport === undefined ? new TMDBHttpClient({ ...httpOptions, images }) : undefined\n this.#transport = builtInClient ?? (transport as TMDBTransport)\n\n this.configuration = new ConfigurationResource(this.#transport)\n this.genres = new GenresResource(this.#transport)\n this.images = new ImagesHelper(\n this.#transport,\n builtInClient ? builtInClient.imageTransform : fallbackTransform,\n )\n this.movies = new MoviesResource(this.#transport)\n this.people = new PeopleResource(this.#transport)\n this.search = new SearchResource(this.#transport)\n this.trending = new TrendingResource(this.#transport)\n this.tv = new TVResource(this.#transport)\n }\n\n /**\n * Make a raw GET request to any TMDB endpoint.\n *\n * This is an escape hatch for endpoints not covered by the typed resource\n * helpers. The `path` should be relative to the API base URL (e.g.\n * `/movie/{id}/credits`). Response is parsed as JSON and cast to `T`.\n *\n * @param path - API path relative to the base URL (e.g. `/movie/123`)\n * @param options - Optional request-level overrides (headers, query, signal)\n * @returns Parsed JSON response typed as `T`\n */\n request<T>(path: string, options?: TMDBRequestOptions): Promise<T> {\n return this.#transport.get<T>(path, options)\n }\n}\n\n/**\n * Create a new {@link TMDBClient} instance.\n *\n * @example\n * ```ts\n * const tmdb = createTMDB({ accessToken: 'YOUR_TOKEN' })\n * const { results } = await tmdb.search.movies('Inception')\n * ```\n *\n * @param options - Authentication and configuration options\n * @returns A configured TMDBClient ready to make API calls\n */\nexport function createTMDB(options: TMDBFactoryOptions): TMDBClient {\n return new TMDBClient(options)\n}\n","import type {\n MovieMultiResult,\n MovieSearchResult,\n PersonMultiResult,\n PersonSearchResult,\n SearchMultiResult,\n TVMultiResult,\n TVSearchResult,\n} from './types'\n\n/**\n * Type guard that narrows a `search.multi()` result to a movie entry.\n *\n * The `media_type` field is required on every `/search/multi` payload by\n * TMDB, so this check is safe at runtime and produces a strictly typed\n * MovieSummary on the narrowed branch.\n */\nexport function isMovieSearchResult(\n result: SearchMultiResult,\n): result is MovieMultiResult\nexport function isMovieSearchResult(\n result: unknown,\n): result is MovieMultiResult\nexport function isMovieSearchResult(\n result: unknown,\n): result is MovieMultiResult {\n return isObjectWithMediaType(result, 'movie')\n}\n\n/** Type guard that narrows a `search.multi()` result to a TV entry. */\nexport function isTVSearchResult(\n result: SearchMultiResult,\n): result is TVMultiResult\nexport function isTVSearchResult(\n result: unknown,\n): result is TVMultiResult\nexport function isTVSearchResult(\n result: unknown,\n): result is TVMultiResult {\n return isObjectWithMediaType(result, 'tv')\n}\n\n/** Type guard that narrows a `search.multi()` result to a person entry. */\nexport function isPersonSearchResult(\n result: SearchMultiResult,\n): result is PersonMultiResult\nexport function isPersonSearchResult(\n result: unknown,\n): result is PersonMultiResult\nexport function isPersonSearchResult(\n result: unknown,\n): result is PersonMultiResult {\n return isObjectWithMediaType(result, 'person')\n}\n\n/**\n * Convenience alias: `isMovieSearchResult` works on a `search.movies()`\n * result (which already has the narrow type but is also tagged with\n * `media_type?: 'movie'`), as well as on multi-search results.\n */\nexport function isMovie(result: MovieSearchResult | SearchMultiResult): result is MovieMultiResult\nexport function isMovie(result: SearchMultiResult): result is MovieMultiResult\nexport function isMovie(result: unknown): result is MovieMultiResult\nexport function isMovie(result: unknown): result is MovieMultiResult {\n return isObjectWithMediaType(result, 'movie')\n}\n\n/** Type guard that narrows a search result to a TV entry. */\nexport function isTV(\n result: TVSearchResult | SearchMultiResult): result is TVMultiResult\nexport function isTV(result: SearchMultiResult): result is TVMultiResult\nexport function isTV(result: unknown): result is TVMultiResult\nexport function isTV(result: unknown): result is TVMultiResult {\n return isObjectWithMediaType(result, 'tv')\n}\n\n/** Type guard that narrows a search result to a person entry. */\nexport function isPerson(\n result: PersonSearchResult | SearchMultiResult): result is PersonMultiResult\nexport function isPerson(result: SearchMultiResult): result is PersonMultiResult\nexport function isPerson(result: unknown): result is PersonMultiResult\nexport function isPerson(result: unknown): result is PersonMultiResult {\n return isObjectWithMediaType(result, 'person')\n}\n\n/** Internal helper: check if a value is an object with a matching `media_type` field. */\nfunction isObjectWithMediaType(\n value: unknown,\n mediaType: 'movie' | 'tv' | 'person',\n): boolean {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'media_type' in value &&\n (value as { media_type: unknown }).media_type === mediaType\n )\n}\n","/** Primitive JSON values returned by TMDB. */\nexport type JsonPrimitive = string | number | boolean | null\n\n/** JSON object/array tree returned by TMDB for fields this SDK does not model yet. */\nexport type JsonValue = JsonPrimitive | JsonObject | JsonValue[]\n\nexport interface JsonObject {\n [key: string]: JsonValue | undefined\n}\n\n/** Escape hatch for append_to_response payloads and future TMDB fields. */\nexport type TMDBObject = Record<string, unknown>\n\n/** Date string in TMDB format (typically `YYYY-MM-DD`). */\nexport type TMDBDateString = string\n\n/** ISO 639-1 language code (e.g. `\"en\"`, `\"zh\"`). */\nexport type LanguageCode = string\n\n/** ISO 3166-1 country/region code (e.g. `\"US\"`, `\"CN\"`). */\nexport type RegionCode = string\n\n/** Supported media types for multi-search results. */\nexport type MediaType = 'movie' | 'tv' | 'person'\n\n/** Time window for trending endpoints: `\"day\"` or `\"week\"`. */\nexport type TrendingTimeWindow = 'day' | 'week'\n\nexport interface PagedResponse<T> {\n page: number\n results: T[]\n total_pages: number\n total_results: number\n}\n\nexport interface Genre {\n id: number\n name: string\n}\n\nexport interface ProductionCompany {\n id: number\n logo_path: string | null\n name: string\n origin_country: string\n}\n\nexport interface ProductionCountry {\n iso_3166_1: string\n name: string\n}\n\nexport interface SpokenLanguage {\n english_name: string\n iso_639_1: string\n name: string\n}\n\nexport interface CollectionSummary {\n id: number\n name: string\n poster_path: string | null\n backdrop_path: string | null\n}\n\nexport interface MovieSummary {\n adult: boolean\n backdrop_path: string | null\n genre_ids: number[]\n id: number\n original_language: string\n original_title: string\n overview: string\n popularity: number\n poster_path: string | null\n release_date: TMDBDateString\n title: string\n video: boolean\n vote_average: number\n vote_count: number\n}\n\nexport interface MovieDetails extends Omit<MovieSummary, 'genre_ids'> {\n belongs_to_collection: CollectionSummary | null\n budget: number\n genres: Genre[]\n homepage: string | null\n imdb_id: string | null\n production_companies: ProductionCompany[]\n production_countries: ProductionCountry[]\n revenue: number\n runtime: number | null\n spoken_languages: SpokenLanguage[]\n status: string\n tagline: string | null\n}\n\nexport interface TVSummary {\n adult?: boolean\n backdrop_path: string | null\n first_air_date: TMDBDateString\n genre_ids: number[]\n id: number\n name: string\n origin_country: string[]\n original_language: string\n original_name: string\n overview: string\n popularity: number\n poster_path: string | null\n vote_average: number\n vote_count: number\n}\n\nexport interface CreatedBy {\n id: number\n credit_id: string\n name: string\n gender: number\n profile_path: string | null\n}\n\nexport interface Network {\n id: number\n logo_path: string | null\n name: string\n origin_country: string\n}\n\nexport interface SeasonSummary {\n air_date: TMDBDateString | null\n episode_count: number\n id: number\n name: string\n overview: string\n poster_path: string | null\n season_number: number\n vote_average: number\n}\n\nexport interface EpisodeGuestStar {\n adult: boolean\n character: string\n credit_id: string\n gender: number | null\n id: number\n known_for_department: string\n name: string\n order: number\n original_name: string\n popularity: number\n profile_path: string | null\n}\n\nexport interface EpisodeSummary {\n air_date: TMDBDateString | null\n crew: CreditCrewMember[]\n episode_number: number\n episode_type: string\n guest_stars: EpisodeGuestStar[]\n id: number\n name: string\n overview: string\n production_code: string | null\n runtime: number | null\n season_number: number\n show_id: number\n still_path: string | null\n vote_average: number\n vote_count: number\n}\n\nexport interface TVSeasonDetails {\n _id: string\n air_date: TMDBDateString | null\n episodes: EpisodeSummary[]\n id: number\n name: string\n overview: string\n poster_path: string | null\n season_number: number\n vote_average: number\n}\n\nexport type TVSeasonAppendToResponse =\n | 'account_states'\n | 'aggregate_credits'\n | 'credits'\n | 'external_ids'\n | 'images'\n | 'translations'\n | 'videos'\n | (string & {})\n\nexport interface TVSeasonDetailsOptions extends LanguageOptions {\n appendToResponse?: TVSeasonAppendToResponse | readonly TVSeasonAppendToResponse[]\n}\n\nexport interface TVDetails extends Omit<TVSummary, 'genre_ids'> {\n created_by: CreatedBy[]\n episode_run_time: number[]\n genres: Genre[]\n homepage: string | null\n in_production: boolean\n languages: string[]\n last_air_date: TMDBDateString | null\n networks: Network[]\n number_of_episodes: number\n number_of_seasons: number\n production_companies: ProductionCompany[]\n production_countries: ProductionCountry[]\n seasons: SeasonSummary[]\n spoken_languages: SpokenLanguage[]\n status: string\n tagline: string | null\n type: string\n}\n\nexport interface PersonKnownForMovie extends MovieSummary {\n media_type: 'movie'\n}\n\nexport interface PersonKnownForTV extends TVSummary {\n media_type: 'tv'\n}\n\nexport type PersonKnownFor = PersonKnownForMovie | PersonKnownForTV\n\nexport interface PersonSummary {\n adult: boolean\n gender: number\n id: number\n known_for: PersonKnownFor[]\n known_for_department: string\n name: string\n original_name?: string\n popularity: number\n profile_path: string | null\n}\n\nexport interface PersonDetails extends Omit<PersonSummary, 'known_for'> {\n also_known_as: string[]\n biography: string\n birthday: TMDBDateString | null\n deathday: TMDBDateString | null\n homepage: string | null\n imdb_id: string | null\n place_of_birth: string | null\n}\n\nexport interface MovieSearchResult extends MovieSummary {\n media_type?: 'movie'\n}\n\nexport interface TVSearchResult extends TVSummary {\n media_type?: 'tv'\n}\n\nexport interface PersonSearchResult extends PersonSummary {\n media_type?: 'person'\n}\n\nexport type SearchMultiResult =\n | (MovieSummary & { media_type: 'movie' })\n | (TVSummary & { media_type: 'tv' })\n | (PersonSummary & { media_type: 'person' })\n\n/** A single multi-search result narrowed to a specific media type. */\nexport type MovieMultiResult = MovieSummary & { media_type: 'movie' }\nexport type TVMultiResult = TVSummary & { media_type: 'tv' }\nexport type PersonMultiResult = PersonSummary & { media_type: 'person' }\n\nexport type TrendingResult = SearchMultiResult\n\nexport interface CreditCastMember {\n adult?: boolean\n cast_id?: number\n character: string\n credit_id: string\n gender: number | null\n id: number\n known_for_department: string\n name: string\n order: number\n original_name: string\n popularity: number\n profile_path: string | null\n}\n\nexport interface CreditCrewMember {\n adult?: boolean\n credit_id: string\n department: string\n gender: number | null\n id: number\n job: string\n known_for_department: string\n name: string\n original_name: string\n popularity: number\n profile_path: string | null\n}\n\nexport interface CreditsResponse {\n id: number\n cast: CreditCastMember[]\n crew: CreditCrewMember[]\n}\n\nexport interface Video {\n id: string\n iso_3166_1: string\n iso_639_1: string\n key: string\n name: string\n official: boolean\n published_at: string\n site: string\n size: number\n type: string\n}\n\nexport interface VideosResponse {\n id: number\n results: Video[]\n}\n\nexport interface ImageItem {\n aspect_ratio: number\n height: number\n iso_639_1: string | null\n file_path: string\n vote_average: number\n vote_count: number\n width: number\n}\n\nexport interface ImagesResponse {\n id: number\n backdrops: ImageItem[]\n logos?: ImageItem[]\n posters: ImageItem[]\n}\n\nexport interface ConfigurationImages {\n base_url: string\n secure_base_url: string\n backdrop_sizes: string[]\n logo_sizes: string[]\n poster_sizes: string[]\n profile_sizes: string[]\n still_sizes: string[]\n}\n\nexport interface Configuration {\n images: ConfigurationImages\n change_keys: string[]\n}\n\nexport interface Country {\n iso_3166_1: string\n english_name: string\n native_name: string\n}\n\nexport interface Language {\n iso_639_1: string\n english_name: string\n name: string\n}\n\nexport interface Timezone {\n iso_3166_1: string\n zones: string[]\n}\n\nexport interface JobDepartment {\n department: string\n jobs: string[]\n}\n\nexport interface GenresResponse {\n genres: Genre[]\n}\n\nexport type BackdropSize = 'w300' | 'w780' | 'w1280' | 'original' | (string & {})\nexport type LogoSize = 'w45' | 'w92' | 'w154' | 'w185' | 'w300' | 'w500' | 'original' | (string & {})\nexport type PosterSize = 'w92' | 'w154' | 'w185' | 'w342' | 'w500' | 'w780' | 'original' | (string & {})\nexport type ProfileSize = 'w45' | 'w185' | 'h632' | 'original' | (string & {})\nexport type StillSize = 'w92' | 'w185' | 'w300' | 'original' | (string & {})\nexport type ImageSize = BackdropSize | LogoSize | PosterSize | ProfileSize | StillSize\n\n/**\n * Public set of image sizes TMDB currently documents. The SDK does not\n * pin to a static copy of the TMDB docs — TMDB has added new sizes in\n * the past (e.g. `h632` for profile) without notice — but exposing the\n * canonical list lets callers:\n *\n * - iterate over the set to build a size picker\n * - validate user-supplied sizes with `isKnownBackdropSize(...)` etc.\n * - type a variable as a \"known\" size without giving up the\n * `(string & {})` escape hatch for forward-compatibility\n *\n * If TMDB publishes a new size, the SDK will still accept it at runtime\n * (every helper is `(string & {})` permissive), but you will need to\n * add the literal to these constants to get autocomplete on it.\n */\nexport const KNOWN_BACKDROP_SIZES: readonly ['w300', 'w780', 'w1280', 'original'] = Object.freeze(['w300', 'w780', 'w1280', 'original'] as const)\nexport const KNOWN_LOGO_SIZES: readonly ['w45', 'w92', 'w154', 'w185', 'w300', 'w500', 'original'] = Object.freeze([\n 'w45',\n 'w92',\n 'w154',\n 'w185',\n 'w300',\n 'w500',\n 'original',\n] as const)\nexport const KNOWN_POSTER_SIZES: readonly ['w92', 'w154', 'w185', 'w342', 'w500', 'w780', 'original'] = Object.freeze([\n 'w92',\n 'w154',\n 'w185',\n 'w342',\n 'w500',\n 'w780',\n 'original',\n] as const)\nexport const KNOWN_PROFILE_SIZES: readonly ['w45', 'w185', 'h632', 'original'] = Object.freeze(['w45', 'w185', 'h632', 'original'] as const)\nexport const KNOWN_STILL_SIZES: readonly ['w92', 'w185', 'w300', 'original'] = Object.freeze(['w92', 'w185', 'w300', 'original'] as const)\n\nexport type KnownBackdropSize = (typeof KNOWN_BACKDROP_SIZES)[number]\nexport type KnownLogoSize = (typeof KNOWN_LOGO_SIZES)[number]\nexport type KnownPosterSize = (typeof KNOWN_POSTER_SIZES)[number]\nexport type KnownProfileSize = (typeof KNOWN_PROFILE_SIZES)[number]\nexport type KnownStillSize = (typeof KNOWN_STILL_SIZES)[number]\nexport type KnownImageSize =\n | KnownBackdropSize\n | KnownLogoSize\n | KnownPosterSize\n | KnownProfileSize\n | KnownStillSize\n\n/** Union of every documented image size. */\nexport const KNOWN_IMAGE_SIZES: readonly KnownImageSize[] = Object.freeze([\n ...KNOWN_BACKDROP_SIZES,\n ...KNOWN_LOGO_SIZES,\n ...KNOWN_POSTER_SIZES,\n ...KNOWN_PROFILE_SIZES,\n ...KNOWN_STILL_SIZES,\n] as const)\n\n/** O(1) membership check backed by a Set. */\nconst KNOWN_BACKDROP_SET: ReadonlySet<string> = new Set(KNOWN_BACKDROP_SIZES)\nconst KNOWN_LOGO_SET: ReadonlySet<string> = new Set(KNOWN_LOGO_SIZES)\nconst KNOWN_POSTER_SET: ReadonlySet<string> = new Set(KNOWN_POSTER_SIZES)\nconst KNOWN_PROFILE_SET: ReadonlySet<string> = new Set(KNOWN_PROFILE_SIZES)\nconst KNOWN_STILL_SET: ReadonlySet<string> = new Set(KNOWN_STILL_SIZES)\nconst KNOWN_IMAGE_SET: ReadonlySet<string> = new Set(KNOWN_IMAGE_SIZES)\n\nexport function isKnownBackdropSize(value: string): value is KnownBackdropSize {\n return KNOWN_BACKDROP_SET.has(value)\n}\n\nexport function isKnownLogoSize(value: string): value is KnownLogoSize {\n return KNOWN_LOGO_SET.has(value)\n}\n\nexport function isKnownPosterSize(value: string): value is KnownPosterSize {\n return KNOWN_POSTER_SET.has(value)\n}\n\nexport function isKnownProfileSize(value: string): value is KnownProfileSize {\n return KNOWN_PROFILE_SET.has(value)\n}\n\nexport function isKnownStillSize(value: string): value is KnownStillSize {\n return KNOWN_STILL_SET.has(value)\n}\n\n/** True if `value` is in any documented size set. */\nexport function isKnownImageSize(value: string): value is KnownImageSize {\n return KNOWN_IMAGE_SET.has(value)\n}\n\nexport type MovieAppendToResponse =\n | 'account_states'\n | 'alternative_titles'\n | 'changes'\n | 'credits'\n | 'external_ids'\n | 'images'\n | 'keywords'\n | 'lists'\n | 'recommendations'\n | 'release_dates'\n | 'reviews'\n | 'similar'\n | 'translations'\n | 'videos'\n | 'watch/providers'\n | (string & {})\n\nexport type TVAppendToResponse =\n | 'account_states'\n | 'aggregate_credits'\n | 'alternative_titles'\n | 'changes'\n | 'content_ratings'\n | 'credits'\n | 'episode_groups'\n | 'external_ids'\n | 'images'\n | 'keywords'\n | 'recommendations'\n | 'reviews'\n | 'screened_theatrically'\n | 'similar'\n | 'translations'\n | 'videos'\n | 'watch/providers'\n | (string & {})\n\nexport interface ListOptions {\n language?: LanguageCode\n page?: number\n region?: RegionCode\n}\n\nexport interface LanguageOptions {\n language?: LanguageCode\n}\n\nexport interface MovieDetailsOptions extends LanguageOptions {\n appendToResponse?: MovieAppendToResponse | readonly MovieAppendToResponse[]\n}\n\nexport interface TVDetailsOptions extends LanguageOptions {\n appendToResponse?: TVAppendToResponse | readonly TVAppendToResponse[]\n}\n\nexport interface MovieSearchOptions extends ListOptions {\n includeAdult?: boolean\n primaryReleaseYear?: string | number\n year?: string | number\n}\n\nexport interface TVSearchOptions extends Omit<ListOptions, 'region'> {\n firstAirDateYear?: string | number\n includeAdult?: boolean\n year?: string | number\n}\n\nexport interface MultiSearchOptions extends Omit<ListOptions, 'region'> {\n includeAdult?: boolean\n /**\n * Media types to exclude from a `search.multi()` response. Filtering is\n * performed client-side because the TMDB multi-search endpoint does not\n * support a server-side media_type filter.\n */\n exclude?: ReadonlyArray<MediaType>\n}\n\nexport interface ImageQueryOptions extends LanguageOptions {\n includeImageLanguage?: string | readonly string[]\n}\n"],"mappings":"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"}
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/errors.ts", "../src/query.ts", "../src/http.ts", "../src/resources/configuration.ts", "../src/resources/genres.ts", "../src/resources/images.ts", "../src/resources/movies.ts", "../src/resources/people.ts", "../src/resources/search.ts", "../src/resources/trending.ts", "../src/resources/tv.ts", "../src/client.ts", "../src/helpers/cache.ts", "../src/helpers/pagination.ts", "../src/helpers/retry.ts", "../src/helpers/timeout.ts", "../src/search-guards.ts", "../src/types.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import type { JsonValue } from './types'\n\n/** Raw TMDB error response body structure. */\nexport interface TMDBErrorResponseBody {\n success?: boolean\n status_code?: number\n status_message?: string\n}\n\n/** Options for constructing a {@link TMDBResponseError} or its subclasses. */\nexport interface TMDBResponseErrorOptions {\n body: JsonValue | undefined\n headers: Headers\n status: number\n statusText: string\n url: string\n}\n\n/** Base class for all SDK-originated errors. */\nexport class TMDBError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options)\n this.name = 'TMDBError'\n }\n}\n\n/** Thrown before a request is sent or when fetch itself rejects. */\nexport class TMDBRequestError extends TMDBError {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options)\n this.name = 'TMDBRequestError'\n }\n}\n\n/**\n * Thrown when a request exceeds the timeout supplied to `withTimeout()`.\n *\n * The timeout helper aborts the request's AbortSignal and converts the\n * resulting abort into this error so timeouts are distinguishable from\n * caller-initiated cancellation.\n */\nexport class TMDBTimeoutError extends TMDBError {\n readonly timeoutMs: number\n\n constructor(timeoutMs: number, message = `TMDB request timed out after ${timeoutMs}ms`) {\n super(message)\n this.name = 'TMDBTimeoutError'\n this.timeoutMs = timeoutMs\n }\n}\n\n/** Thrown when TMDB returns a non-2xx response. */\nexport class TMDBResponseError extends TMDBError {\n readonly body: JsonValue | undefined\n readonly headers: Headers\n readonly requestId: string | null\n readonly status: number\n readonly statusCode: number | undefined\n readonly statusMessage: string | undefined\n readonly statusText: string\n readonly url: string\n\n constructor(message: string, options: TMDBResponseErrorOptions) {\n super(message)\n this.name = 'TMDBResponseError'\n this.body = options.body\n this.headers = options.headers\n this.requestId = options.headers.get('x-request-id')\n this.status = options.status\n this.statusText = options.statusText\n this.url = options.url\n\n const body = isErrorResponseBody(options.body) ? options.body : undefined\n this.statusCode = body?.status_code\n this.statusMessage = body?.status_message\n }\n\n /** True when TMDB has asked the caller to back off (HTTP 429). */\n get isRateLimit(): boolean {\n return this.status === 429\n }\n\n /** True when the resource was not found (HTTP 404). */\n get isNotFound(): boolean {\n return this.status === 404\n }\n\n /** True when the request was rejected as unauthenticated (HTTP 401). */\n get isUnauthorized(): boolean {\n return this.status === 401\n }\n\n /** True when the request was rejected as forbidden (HTTP 403). */\n get isForbidden(): boolean {\n return this.status === 403\n }\n\n /** True when the upstream returned a 5xx server error. */\n get isServerError(): boolean {\n return this.status >= 500 && this.status < 600\n }\n}\n\nexport interface TMDBRateLimitErrorOptions extends TMDBResponseErrorOptions {\n /** Seconds to wait before retrying. Parsed from the `Retry-After` header. */\n retryAfter: number\n}\n\n/**\n * Thrown when TMDB returns HTTP 429.\n *\n * The SDK does NOT retry automatically — that decision is left to the\n * caller, since retry policies vary widely. Inspect `retryAfter` to\n * implement your own backoff, or use the optional `retry()` / `withRetry()`\n * helpers for a TMDB-aware default.\n */\nexport class TMDBRateLimitError extends TMDBResponseError {\n readonly retryAfter: number\n\n constructor(message: string, options: TMDBRateLimitErrorOptions) {\n super(message, options)\n this.name = 'TMDBRateLimitError'\n this.retryAfter = options.retryAfter\n }\n}\n\n/**\n * Create the appropriate error instance for a non-2xx TMDB response.\n *\n * Returns a {@link TMDBRateLimitError} when the status is 429, otherwise\n * a generic {@link TMDBResponseError}. The error message is extracted from\n * the TMDB `status_message` field when available.\n */\nexport function createResponseError(options: TMDBResponseErrorOptions): TMDBResponseError {\n const body = isErrorResponseBody(options.body) ? options.body : undefined\n const message = body?.status_message ?? `${options.status} ${options.statusText}`.trim()\n\n if (options.status === 429) {\n return new TMDBRateLimitError(message, {\n ...options,\n retryAfter: parseRetryAfter(options.headers.get('retry-after')),\n })\n }\n\n return new TMDBResponseError(message, options)\n}\n\n/**\n * Parse the `Retry-After` header into seconds. Accepts both delta-seconds\n * (e.g. \"5\") and HTTP-date forms (e.g. \"Wed, 21 Oct 2026 07:28:00 GMT\").\n * Falls back to 1 second when the header is missing or unparseable.\n */\nexport function parseRetryAfter(value: string | null | undefined): number {\n if (value === null || value === undefined) {\n return 1\n }\n\n const trimmed = value.trim()\n if (trimmed === '') {\n return 1\n }\n\n const seconds = Number(trimmed)\n if (Number.isFinite(seconds) && seconds >= 0) {\n return seconds\n }\n\n const date = Date.parse(trimmed)\n if (Number.isFinite(date)) {\n const deltaMs = date - Date.now()\n return Math.max(1, Math.ceil(deltaMs / 1000))\n }\n\n return 1\n}\n\n/** Check if a value has the shape of a TMDB error response body. */\nfunction isErrorResponseBody(value: unknown): value is TMDBErrorResponseBody {\n return typeof value === 'object' && value !== null\n}\n",
|
|
6
|
+
"import { TMDBRequestError } from './errors'\nimport type { ImageSize, RegionCode, LanguageCode, TrendingTimeWindow } from './types'\n\n/** Primitives allowed as query parameter values. */\nexport type QueryPrimitive = string | number | boolean\n\n/** A single query parameter value: primitive, array, or nullish. */\nexport type QueryValue = QueryPrimitive | readonly QueryPrimitive[] | null | undefined\n\n/** Key-value map of query parameters for API requests. */\nexport type QueryParams = Record<string, QueryValue>\n\n/** Default query parameters inherited from the client configuration. */\nexport interface QueryDefaults {\n language?: LanguageCode\n region?: RegionCode\n}\n\nexport const DEFAULT_API_BASE_URL = 'https://api.themoviedb.org/3'\nexport const DEFAULT_IMAGE_BASE_URL = 'https://image.tmdb.org/t/p'\n\n/**\n * Append query parameters to a URL object.\n *\n * - `undefined` and `null` values are skipped.\n * - Arrays are joined with commas (TMDB convention).\n * - All values are converted to strings.\n */\nexport function appendQuery(url: URL, query: QueryParams): void {\n for (const [key, value] of Object.entries(query)) {\n if (value === undefined || value === null) {\n continue\n }\n\n if (Array.isArray(value)) {\n url.searchParams.set(key, value.map(String).join(','))\n continue\n }\n\n url.searchParams.set(key, String(value))\n }\n}\n\n/**\n * Merge a language query parameter with client defaults.\n *\n * If `query.language` is set it takes precedence; otherwise the client's\n * default language is used.\n */\nexport function withLanguage(defaults: QueryDefaults, query: QueryParams): QueryParams {\n const language = typeof query.language === 'string' ? query.language : defaults.language\n\n return {\n ...query,\n language,\n }\n}\n\n/**\n * Merge language and region defaults for list endpoints.\n *\n * Combines {@link withLanguage} with region fallback from client defaults.\n */\nexport function withListDefaults(defaults: QueryDefaults, query: QueryParams): QueryParams {\n const region = typeof query.region === 'string' ? query.region : defaults.region\n\n return {\n ...withLanguage(defaults, query),\n region,\n }\n}\n\n/**\n * Convert a string or string array to a comma-separated list.\n *\n * Returns `undefined` if the input is `undefined` (skips the parameter).\n * TMDB uses comma-separated values for multi-value query parameters.\n */\nexport function toCommaList(value: string | readonly string[] | undefined): string | undefined {\n if (value === undefined) {\n return undefined\n }\n\n return typeof value === 'string' ? value : value.join(',')\n}\n\n/**\n * Validate and convert a numeric ID to a string for use in URL paths.\n *\n * @throws {TMDBRequestError} If `value` is not a positive integer.\n */\nexport function toId(value: number, name: string): string {\n if (!Number.isInteger(value) || value <= 0) {\n throw new TMDBRequestError(`${name} must be a positive integer`)\n }\n\n return String(value)\n}\n\n/**\n * Validate and convert a season number to a string for use in URL paths.\n *\n * Season `0` is valid and refers to specials.\n *\n * @throws {TMDBRequestError} If `value` is not a non-negative integer.\n */\nexport function toSeasonNumber(value: number): string {\n if (!Number.isInteger(value) || value < 0) {\n throw new TMDBRequestError('seasonNumber must be a non-negative integer')\n }\n\n return String(value)\n}\n\n/**\n * Validate and normalize a string identifier for use in URL paths.\n *\n * @throws {TMDBRequestError} If `value` is empty or contains non-identifier characters.\n */\nexport function toGroupId(value: string): string {\n const groupId = value.trim()\n\n if (!/^[A-Za-z0-9_-]+$/.test(groupId)) {\n throw new TMDBRequestError('groupId must be a non-empty identifier')\n }\n\n return groupId\n}\n\n/**\n * Validate and trim a search query string.\n *\n * @throws {TMDBRequestError} If the query is empty after trimming.\n */\nexport function toSearchQuery(value: string): string {\n const query = value.trim()\n\n if (query.length === 0) {\n throw new TMDBRequestError('search query must not be empty')\n }\n\n return query\n}\n\n/**\n * Validate a trending time window value.\n *\n * @throws {TMDBRequestError} If `value` is not `\"day\"` or `\"week\"`.\n */\nexport function toTimeWindow(value: TrendingTimeWindow): TrendingTimeWindow {\n if (value !== 'day' && value !== 'week') {\n throw new TMDBRequestError('timeWindow must be either \"day\" or \"week\"')\n }\n\n return value\n}\n\nexport interface BuildImageUrlOptions {\n baseUrl?: string\n /**\n * Transform the resolved TMDB image URL before returning it. Use this to\n * route requests through a CDN, image proxy, or to add signatures.\n */\n transform?: (url: string) => string\n}\n\n/**\n * Build a full TMDB image URL from the path returned by API payloads.\n * Returns null for nullish image paths so UI code can branch naturally.\n */\nexport function buildImageUrl(\n path: string | null | undefined,\n size: ImageSize = 'original',\n options: BuildImageUrlOptions = {},\n): string | null {\n if (path === undefined || path === null || path.trim() === '') {\n return null\n }\n\n const baseUrl = normalizeBaseUrl(options.baseUrl ?? DEFAULT_IMAGE_BASE_URL)\n const normalizedPath = path.startsWith('/') ? path : `/${path}`\n const url = `${baseUrl}/${size}${normalizedPath}`\n\n return options.transform ? options.transform(url) : url\n}\n\n/**\n * Strip trailing slashes from a base URL to ensure consistent path joining.\n */\nexport function normalizeBaseUrl(baseUrl: string): string {\n return baseUrl.replace(/\\/+$/, '')\n}\n",
|
|
7
|
+
"import { createResponseError, TMDBRequestError } from './errors'\nimport {\n appendQuery,\n DEFAULT_API_BASE_URL,\n DEFAULT_IMAGE_BASE_URL,\n normalizeBaseUrl,\n type QueryDefaults,\n type QueryParams,\n} from './query'\nimport type { ImageUrlTransform } from './resources/images'\nimport type { JsonValue, LanguageCode, RegionCode } from './types'\n\nexport type { ImageUrlTransform }\n\n/**\n * A minimal fetch-like function signature. Any runtime's native `fetch`\n * or a test double conforming to this shape can be used.\n */\nexport type FetchLike = (input: string, init?: RequestInit) => Promise<Response>\n\nexport interface TMDBAccessTokenAuth {\n /** TMDB API Read Access Token. Sent as an Authorization Bearer header. */\n accessToken: string\n apiKey?: never\n}\n\nexport interface TMDBApiKeyAuth {\n /** Legacy v3 API key. Sent as api_key query parameter. */\n apiKey: string\n accessToken?: never\n}\n\nexport type TMDBAuth = TMDBAccessTokenAuth | TMDBApiKeyAuth\n\n/** Internal defaults resolved during client construction. */\nexport interface TMDBClientDefaults extends QueryDefaults {\n imageBaseUrl: string\n}\n\nexport interface TMDBImagesOptions {\n /**\n * Default transform applied to every URL produced by the ImagesHelper.\n * Use this to route TMDB image requests through a CDN, image proxy, or\n * to add signed query parameters. Individual calls can still override it\n * via ImagesHelper.url(path, size, { transform }).\n */\n transform?: ImageUrlTransform\n}\n\nexport type TMDBClientOptions = TMDBAuth & {\n /** Defaults to https://api.themoviedb.org/3. Useful for tests or proxies. */\n baseUrl?: string\n /** Inject a fetch implementation for tests, custom runtimes, or instrumentation. */\n fetch?: FetchLike\n /** Default language for endpoints that accept a language query parameter. */\n defaultLanguage?: LanguageCode\n /** Default region for movie list/search endpoints that accept a region query parameter. */\n defaultRegion?: RegionCode\n /** Custom image host. Defaults to https://image.tmdb.org/t/p. */\n imageBaseUrl?: string\n /** Image-helper configuration: host overrides and URL transforms. */\n images?: TMDBImagesOptions\n /** Additional headers merged into every request before authentication is applied. */\n headers?: HeadersInit\n}\n\n/** Per-request overrides applied when making a single API call. */\nexport interface TMDBRequestOptions {\n headers?: HeadersInit\n query?: QueryParams\n signal?: AbortSignal\n}\n\n/**\n * Transport abstraction for making HTTP requests to the TMDB API.\n *\n * The built-in {@link TMDBHttpClient} implements this interface. You can\n * provide a custom implementation via {@link TMDBFactoryOptions.transport}\n * for testing, caching, or instrumentation.\n */\nexport interface TMDBTransport {\n readonly defaults: TMDBClientDefaults\n get<T>(path: string, options?: TMDBRequestOptions): Promise<T>\n}\n\n/**\n * Built-in HTTP transport that uses the Fetch API.\n *\n * Handles authentication (API key or access token), URL construction,\n * request headers, and response parsing. Use the factory function\n * {@link createTMDB} instead of instantiating this directly.\n */\nexport class TMDBHttpClient implements TMDBTransport {\n readonly defaults: TMDBClientDefaults\n readonly imageTransform: ImageUrlTransform | undefined\n\n readonly #apiKey: string | undefined\n readonly #accessToken: string | undefined\n readonly #baseUrl: string\n readonly #fetch: FetchLike | undefined\n readonly #headers: HeadersInit | undefined\n\n constructor(options: TMDBClientOptions) {\n const accessToken = normalizeSecret('accessToken' in options ? options.accessToken : undefined)\n const apiKey = normalizeSecret('apiKey' in options ? options.apiKey : undefined)\n\n if (Boolean(accessToken) === Boolean(apiKey)) {\n throw new TMDBRequestError('Provide exactly one of accessToken or apiKey')\n }\n\n this.#accessToken = accessToken\n this.#apiKey = apiKey\n this.#baseUrl = normalizeBaseUrl(options.baseUrl ?? DEFAULT_API_BASE_URL)\n this.#fetch = options.fetch\n this.#headers = options.headers\n this.defaults = {\n imageBaseUrl: normalizeBaseUrl(options.imageBaseUrl ?? DEFAULT_IMAGE_BASE_URL),\n language: options.defaultLanguage,\n region: options.defaultRegion,\n }\n this.imageTransform = options.images?.transform\n }\n\n async get<T>(path: string, options: TMDBRequestOptions = {}): Promise<T> {\n const url = this.#createUrl(path, options.query ?? {})\n const headers = this.#createHeaders(options.headers)\n const fetchImpl = this.#resolveFetch()\n\n let response: Response\n\n try {\n response = await fetchImpl(url, {\n headers,\n method: 'GET',\n signal: options.signal,\n })\n } catch (error) {\n throw new TMDBRequestError(`TMDB request failed: ${String(error)}`, { cause: error })\n }\n\n const body = await readJson(response)\n\n if (!response.ok) {\n throw createResponseError({\n body,\n headers: response.headers,\n status: response.status,\n statusText: response.statusText,\n url,\n })\n }\n\n return body as T\n }\n\n #resolveFetch(): FetchLike {\n if (this.#fetch !== undefined) {\n return this.#fetch\n }\n\n const globalFetch = globalThis.fetch\n\n if (typeof globalFetch !== 'function') {\n throw new TMDBRequestError(\n 'No fetch implementation found. Pass options.fetch in this runtime.',\n )\n }\n\n return globalFetch.bind(globalThis)\n }\n\n #createHeaders(headersInit: HeadersInit | undefined): Headers {\n const headers = new Headers(this.#headers)\n const requestHeaders = new Headers(headersInit)\n\n headers.set('Accept', 'application/json')\n\n for (const [key, value] of requestHeaders) {\n headers.set(key, value)\n }\n\n if (this.#accessToken !== undefined) {\n headers.set('Authorization', `Bearer ${this.#accessToken}`)\n }\n\n return headers\n }\n\n #createUrl(path: string, query: QueryParams): string {\n const relativePath = path.replace(/^\\/+/, '')\n const url = new URL(relativePath, `${this.#baseUrl}/`)\n\n appendQuery(url, {\n ...query,\n api_key: this.#apiKey,\n })\n\n return url.toString()\n }\n}\n\n/**\n * Read and parse a JSON response body.\n *\n * Returns `undefined` for empty responses. If the body is not valid JSON,\n * the raw text string is returned as-is (TMDB occasionally returns plain\n * text for certain error conditions).\n */\nasync function readJson(response: Response): Promise<JsonValue | undefined> {\n const text = await response.text()\n\n if (text.length === 0) {\n return undefined\n }\n\n try {\n return JSON.parse(text) as JsonValue\n } catch {\n return text\n }\n}\n\n/**\n * Normalize a secret value by trimming whitespace and treating empty\n * strings as undefined (not provided).\n */\nfunction normalizeSecret(value: string | undefined): string | undefined {\n const secret = value?.trim()\n return secret === '' ? undefined : secret\n}\n",
|
|
8
|
+
"import type { TMDBTransport } from '../http'\nimport type {\n Configuration,\n Country,\n JobDepartment,\n Language,\n RequestOptions,\n Timezone,\n} from '../types'\n\n/**\n * Access TMDB configuration data (image sizes, countries, languages, etc.).\n *\n * Obtained via `client.configuration`.\n */\nexport class ConfigurationResource {\n readonly #transport: TMDBTransport\n\n constructor(transport: TMDBTransport) {\n this.#transport = transport\n }\n\n details(options: RequestOptions = {}): Promise<Configuration> {\n return this.#transport.get('/configuration', { signal: options.signal })\n }\n\n countries(options: RequestOptions = {}): Promise<Country[]> {\n return this.#transport.get('/configuration/countries', { signal: options.signal })\n }\n\n jobs(options: RequestOptions = {}): Promise<JobDepartment[]> {\n return this.#transport.get('/configuration/jobs', { signal: options.signal })\n }\n\n languages(options: RequestOptions = {}): Promise<Language[]> {\n return this.#transport.get('/configuration/languages', { signal: options.signal })\n }\n\n primaryTranslations(options: RequestOptions = {}): Promise<string[]> {\n return this.#transport.get('/configuration/primary_translations', {\n signal: options.signal,\n })\n }\n\n timezones(options: RequestOptions = {}): Promise<Timezone[]> {\n return this.#transport.get('/configuration/timezones', { signal: options.signal })\n }\n}\n",
|
|
9
|
+
"import type { TMDBTransport } from '../http'\nimport { withLanguage } from '../query'\nimport type { GenresResponse, LanguageOptions } from '../types'\n\n/**\n * Access TMDB genre lists for movies and TV shows.\n *\n * Obtained via `client.genres`.\n */\nexport class GenresResource {\n readonly #transport: TMDBTransport\n\n constructor(transport: TMDBTransport) {\n this.#transport = transport\n }\n\n movies(options: LanguageOptions = {}): Promise<GenresResponse> {\n return this.#transport.get('/genre/movie/list', {\n query: withLanguage(this.#transport.defaults, {\n language: options.language,\n }),\n signal: options.signal,\n })\n }\n\n tv(options: LanguageOptions = {}): Promise<GenresResponse> {\n return this.#transport.get('/genre/tv/list', {\n query: withLanguage(this.#transport.defaults, {\n language: options.language,\n }),\n signal: options.signal,\n })\n }\n}\n",
|
|
10
|
+
"import type { TMDBTransport } from '../http'\nimport { buildImageUrl } from '../query'\nimport type { ImageSize } from '../types'\n\n/** Function that transforms a TMDB image URL (e.g. for CDN proxying). */\nexport type ImageUrlTransform = (url: string) => string\n\n/**\n * Helper for constructing TMDB image URLs from API path values.\n *\n * Obtained via `client.images`. Supports optional URL transforms for\n * routing image requests through a CDN or proxy.\n */\nexport class ImagesHelper {\n readonly #transport: TMDBTransport\n readonly #transform: ImageUrlTransform | undefined\n\n constructor(transport: TMDBTransport, transform?: ImageUrlTransform) {\n this.#transport = transport\n this.#transform = transform\n }\n\n url(\n path: string | null | undefined,\n size: ImageSize = 'original',\n options: { transform?: ImageUrlTransform } = {},\n ): string | null {\n return buildImageUrl(path, size, {\n baseUrl: this.#transport.defaults.imageBaseUrl,\n transform: options.transform ?? this.#transform,\n })\n }\n}\n",
|
|
11
|
+
"import type { TMDBTransport } from '../http'\nimport { toCommaList, toId, withLanguage, withListDefaults, type QueryParams } from '../query'\nimport type {\n CreditsResponse,\n ImageQueryOptions,\n ImagesResponse,\n LanguageOptions,\n ListOptions,\n MovieDetails,\n MovieDetailsOptions,\n MovieSummary,\n PagedResponse,\n TMDBObject,\n VideosResponse,\n} from '../types'\n\n/**\n * Access TMDB movie endpoints (popular, top-rated, details, credits, etc.).\n *\n * Obtained via `client.movies`.\n */\nexport class MoviesResource {\n readonly #transport: TMDBTransport\n\n constructor(transport: TMDBTransport) {\n this.#transport = transport\n }\n\n popular(options: ListOptions = {}): Promise<PagedResponse<MovieSummary>> {\n return this.#transport.get('/movie/popular', {\n query: movieListQuery(this.#transport, options),\n signal: options.signal,\n })\n }\n\n topRated(options: ListOptions = {}): Promise<PagedResponse<MovieSummary>> {\n return this.#transport.get('/movie/top_rated', {\n query: movieListQuery(this.#transport, options),\n signal: options.signal,\n })\n }\n\n nowPlaying(options: ListOptions = {}): Promise<PagedResponse<MovieSummary>> {\n return this.#transport.get('/movie/now_playing', {\n query: movieListQuery(this.#transport, options),\n signal: options.signal,\n })\n }\n\n upcoming(options: ListOptions = {}): Promise<PagedResponse<MovieSummary>> {\n return this.#transport.get('/movie/upcoming', {\n query: movieListQuery(this.#transport, options),\n signal: options.signal,\n })\n }\n\n details<TAppend extends TMDBObject = TMDBObject>(\n movieId: number,\n options: MovieDetailsOptions = {},\n ): Promise<MovieDetails & TAppend> {\n return this.#transport.get(`/movie/${toId(movieId, 'movieId')}`, {\n query: withLanguage(this.#transport.defaults, {\n append_to_response: toCommaList(options.appendToResponse),\n language: options.language,\n }),\n signal: options.signal,\n })\n }\n\n credits(movieId: number, options: LanguageOptions = {}): Promise<CreditsResponse> {\n return this.#transport.get(`/movie/${toId(movieId, 'movieId')}/credits`, {\n query: withLanguage(this.#transport.defaults, {\n language: options.language,\n }),\n signal: options.signal,\n })\n }\n\n images(movieId: number, options: ImageQueryOptions = {}): Promise<ImagesResponse> {\n return this.#transport.get(`/movie/${toId(movieId, 'movieId')}/images`, {\n query: withLanguage(this.#transport.defaults, {\n include_image_language: toCommaList(options.includeImageLanguage),\n language: options.language,\n }),\n signal: options.signal,\n })\n }\n\n recommendations(\n movieId: number,\n options: ListOptions = {},\n ): Promise<PagedResponse<MovieSummary>> {\n return this.#transport.get(`/movie/${toId(movieId, 'movieId')}/recommendations`, {\n query: movieListQuery(this.#transport, options),\n signal: options.signal,\n })\n }\n\n similar(movieId: number, options: ListOptions = {}): Promise<PagedResponse<MovieSummary>> {\n return this.#transport.get(`/movie/${toId(movieId, 'movieId')}/similar`, {\n query: movieListQuery(this.#transport, options),\n signal: options.signal,\n })\n }\n\n videos(movieId: number, options: LanguageOptions = {}): Promise<VideosResponse> {\n return this.#transport.get(`/movie/${toId(movieId, 'movieId')}/videos`, {\n query: withLanguage(this.#transport.defaults, {\n language: options.language,\n }),\n signal: options.signal,\n })\n }\n}\n\n/** Build query parameters for movie list endpoints. */\nfunction movieListQuery(transport: TMDBTransport, options: ListOptions): QueryParams {\n return withListDefaults(transport.defaults, {\n language: options.language,\n page: options.page,\n region: options.region,\n })\n}\n",
|
|
12
|
+
"import type { TMDBTransport } from '../http'\nimport { toId, withLanguage, type QueryParams } from '../query'\nimport type {\n LanguageOptions,\n ListOptions,\n PagedResponse,\n PersonCombinedCreditsResponse,\n PersonDetails,\n PersonSummary,\n} from '../types'\n\n/**\n * Access TMDB person (actor, director, etc.) endpoints.\n *\n * Obtained via `client.people`.\n */\nexport class PeopleResource {\n readonly #transport: TMDBTransport\n\n constructor(transport: TMDBTransport) {\n this.#transport = transport\n }\n\n popular(options: Omit<ListOptions, 'region'> = {}): Promise<PagedResponse<PersonSummary>> {\n return this.#transport.get('/person/popular', {\n query: peopleListQuery(this.#transport, options),\n signal: options.signal,\n })\n }\n\n details(personId: number, options: LanguageOptions = {}): Promise<PersonDetails> {\n return this.#transport.get(`/person/${toId(personId, 'personId')}`, {\n query: withLanguage(this.#transport.defaults, {\n language: options.language,\n }),\n signal: options.signal,\n })\n }\n\n combinedCredits(\n personId: number,\n options: LanguageOptions = {},\n ): Promise<PersonCombinedCreditsResponse> {\n return this.#transport.get(`/person/${toId(personId, 'personId')}/combined_credits`, {\n query: withLanguage(this.#transport.defaults, {\n language: options.language,\n }),\n signal: options.signal,\n })\n }\n}\n\n/** Build query parameters for person list endpoints. */\nfunction peopleListQuery(\n transport: TMDBTransport,\n options: Omit<ListOptions, 'region'>,\n): QueryParams {\n return withLanguage(transport.defaults, {\n language: options.language,\n page: options.page,\n })\n}\n",
|
|
13
|
+
"import type { TMDBTransport } from '../http'\nimport { toSearchQuery, withLanguage, withListDefaults, type QueryParams } from '../query'\nimport type {\n MovieSearchOptions,\n MovieSearchResult,\n MultiSearchOptions,\n PagedResponse,\n PersonSearchResult,\n SearchMultiResult,\n TVSearchOptions,\n TVSearchResult,\n} from '../types'\n\n/**\n * Search TMDB for movies, TV shows, people, or all media types.\n *\n * Obtained via `client.search`.\n */\nexport class SearchResource {\n readonly #transport: TMDBTransport\n\n constructor(transport: TMDBTransport) {\n this.#transport = transport\n }\n\n movies(\n query: string,\n options: MovieSearchOptions = {},\n ): Promise<PagedResponse<MovieSearchResult>> {\n return this.#transport.get('/search/movie', {\n query: movieSearchQuery(this.#transport, query, options),\n signal: options.signal,\n })\n }\n\n tv(query: string, options: TVSearchOptions = {}): Promise<PagedResponse<TVSearchResult>> {\n return this.#transport.get('/search/tv', {\n query: tvSearchQuery(this.#transport, query, options),\n signal: options.signal,\n })\n }\n\n people(\n query: string,\n options: MultiSearchOptions = {},\n ): Promise<PagedResponse<PersonSearchResult>> {\n return this.#transport.get('/search/person', {\n query: commonSearchQuery(this.#transport, query, options),\n signal: options.signal,\n })\n }\n\n async multi(\n query: string,\n options: MultiSearchOptions = {},\n ): Promise<PagedResponse<SearchMultiResult>> {\n const response = await this.#transport.get<PagedResponse<SearchMultiResult>>('/search/multi', {\n query: commonSearchQuery(this.#transport, query, options),\n signal: options.signal,\n })\n\n const excluded = options.exclude\n if (excluded === undefined || excluded.length === 0) {\n return response\n }\n\n const excludedSet = new Set<string>(excluded)\n return {\n ...response,\n results: response.results.filter((result) => !excludedSet.has(result.media_type)),\n }\n }\n}\n\n/** Build query parameters for movie search. */\nfunction movieSearchQuery(\n transport: TMDBTransport,\n query: string,\n options: MovieSearchOptions,\n): QueryParams {\n return withListDefaults(transport.defaults, {\n include_adult: options.includeAdult,\n language: options.language,\n page: options.page,\n primary_release_year: options.primaryReleaseYear,\n query: toSearchQuery(query),\n region: options.region,\n year: options.year,\n })\n}\n\n/** Build query parameters for TV search. */\nfunction tvSearchQuery(\n transport: TMDBTransport,\n query: string,\n options: TVSearchOptions,\n): QueryParams {\n return withLanguage(transport.defaults, {\n first_air_date_year: options.firstAirDateYear,\n include_adult: options.includeAdult,\n language: options.language,\n page: options.page,\n query: toSearchQuery(query),\n year: options.year,\n })\n}\n\n/** Build query parameters for person and multi-search. */\nfunction commonSearchQuery(\n transport: TMDBTransport,\n query: string,\n options: MultiSearchOptions,\n): QueryParams {\n return withLanguage(transport.defaults, {\n include_adult: options.includeAdult,\n language: options.language,\n page: options.page,\n query: toSearchQuery(query),\n })\n}\n",
|
|
14
|
+
"import type { TMDBTransport } from '../http'\nimport { toTimeWindow, withLanguage } from '../query'\nimport type {\n ListOptions,\n MovieSummary,\n PagedResponse,\n PersonSummary,\n TrendingResult,\n TrendingTimeWindow,\n TVSummary,\n} from '../types'\n\ntype TrendingOptions = Omit<ListOptions, 'region'>\n\n/**\n * Access TMDB trending content (movies, TV, people) for day/week windows.\n *\n * Obtained via `client.trending`.\n */\nexport class TrendingResource {\n readonly #transport: TMDBTransport\n\n constructor(transport: TMDBTransport) {\n this.#transport = transport\n }\n\n all(\n timeWindow: TrendingTimeWindow = 'day',\n options: TrendingOptions = {},\n ): Promise<PagedResponse<TrendingResult>> {\n return this.#transport.get(`/trending/all/${toTimeWindow(timeWindow)}`, {\n query: withLanguage(this.#transport.defaults, {\n language: options.language,\n page: options.page,\n }),\n signal: options.signal,\n })\n }\n\n movies(\n timeWindow: TrendingTimeWindow = 'day',\n options: TrendingOptions = {},\n ): Promise<PagedResponse<MovieSummary & { media_type?: 'movie' }>> {\n return this.#transport.get(`/trending/movie/${toTimeWindow(timeWindow)}`, {\n query: withLanguage(this.#transport.defaults, {\n language: options.language,\n page: options.page,\n }),\n signal: options.signal,\n })\n }\n\n tv(\n timeWindow: TrendingTimeWindow = 'day',\n options: TrendingOptions = {},\n ): Promise<PagedResponse<TVSummary & { media_type?: 'tv' }>> {\n return this.#transport.get(`/trending/tv/${toTimeWindow(timeWindow)}`, {\n query: withLanguage(this.#transport.defaults, {\n language: options.language,\n page: options.page,\n }),\n signal: options.signal,\n })\n }\n\n people(\n timeWindow: TrendingTimeWindow = 'day',\n options: TrendingOptions = {},\n ): Promise<PagedResponse<PersonSummary & { media_type?: 'person' }>> {\n return this.#transport.get(`/trending/person/${toTimeWindow(timeWindow)}`, {\n query: withLanguage(this.#transport.defaults, {\n language: options.language,\n page: options.page,\n }),\n signal: options.signal,\n })\n }\n}\n",
|
|
15
|
+
"import type { TMDBTransport } from '../http'\nimport {\n toCommaList,\n toGroupId,\n toId,\n toSeasonNumber,\n withLanguage,\n type QueryParams,\n} from '../query'\nimport type {\n AggregateCreditsResponse,\n CreditsResponse,\n EpisodeDetails,\n EpisodeDetailsOptions,\n EpisodeGroupDetails,\n EpisodeGroupsResponse,\n ImageQueryOptions,\n ImagesResponse,\n LanguageOptions,\n ListOptions,\n PagedResponse,\n SeasonImagesResponse,\n TMDBObject,\n TVDetails,\n TVDetailsOptions,\n TVSeasonDetails,\n TVSeasonDetailsOptions,\n TVSummary,\n VideosResponse,\n} from '../types'\n\n/**\n * Access TMDB TV show endpoints (popular, top-rated, details, seasons, etc.).\n *\n * Obtained via `client.tv`.\n */\nexport class TVResource {\n readonly #transport: TMDBTransport\n\n constructor(transport: TMDBTransport) {\n this.#transport = transport\n }\n\n popular(options: Omit<ListOptions, 'region'> = {}): Promise<PagedResponse<TVSummary>> {\n return this.#transport.get('/tv/popular', {\n query: tvListQuery(this.#transport, options),\n signal: options.signal,\n })\n }\n\n topRated(options: Omit<ListOptions, 'region'> = {}): Promise<PagedResponse<TVSummary>> {\n return this.#transport.get('/tv/top_rated', {\n query: tvListQuery(this.#transport, options),\n signal: options.signal,\n })\n }\n\n airingToday(options: Omit<ListOptions, 'region'> = {}): Promise<PagedResponse<TVSummary>> {\n return this.#transport.get('/tv/airing_today', {\n query: tvListQuery(this.#transport, options),\n signal: options.signal,\n })\n }\n\n onTheAir(options: Omit<ListOptions, 'region'> = {}): Promise<PagedResponse<TVSummary>> {\n return this.#transport.get('/tv/on_the_air', {\n query: tvListQuery(this.#transport, options),\n signal: options.signal,\n })\n }\n\n details<TAppend extends TMDBObject = TMDBObject>(\n seriesId: number,\n options: TVDetailsOptions = {},\n ): Promise<TVDetails & TAppend> {\n return this.#transport.get(`/tv/${toId(seriesId, 'seriesId')}`, {\n query: withLanguage(this.#transport.defaults, {\n append_to_response: toCommaList(options.appendToResponse),\n language: options.language,\n }),\n signal: options.signal,\n })\n }\n\n credits(seriesId: number, options: LanguageOptions = {}): Promise<CreditsResponse> {\n return this.#transport.get(`/tv/${toId(seriesId, 'seriesId')}/credits`, {\n query: withLanguage(this.#transport.defaults, {\n language: options.language,\n }),\n signal: options.signal,\n })\n }\n\n images(seriesId: number, options: ImageQueryOptions = {}): Promise<ImagesResponse> {\n return this.#transport.get(`/tv/${toId(seriesId, 'seriesId')}/images`, {\n query: withLanguage(this.#transport.defaults, {\n include_image_language: toCommaList(options.includeImageLanguage),\n language: options.language,\n }),\n signal: options.signal,\n })\n }\n\n recommendations(\n seriesId: number,\n options: Omit<ListOptions, 'region'> = {},\n ): Promise<PagedResponse<TVSummary>> {\n return this.#transport.get(`/tv/${toId(seriesId, 'seriesId')}/recommendations`, {\n query: tvListQuery(this.#transport, options),\n signal: options.signal,\n })\n }\n\n similar(\n seriesId: number,\n options: Omit<ListOptions, 'region'> = {},\n ): Promise<PagedResponse<TVSummary>> {\n return this.#transport.get(`/tv/${toId(seriesId, 'seriesId')}/similar`, {\n query: tvListQuery(this.#transport, options),\n signal: options.signal,\n })\n }\n\n videos(seriesId: number, options: LanguageOptions = {}): Promise<VideosResponse> {\n return this.#transport.get(`/tv/${toId(seriesId, 'seriesId')}/videos`, {\n query: withLanguage(this.#transport.defaults, {\n language: options.language,\n }),\n signal: options.signal,\n })\n }\n\n seasonDetails<TAppend extends TMDBObject = TMDBObject>(\n seriesId: number,\n seasonNumber: number,\n options: TVSeasonDetailsOptions = {},\n ): Promise<TVSeasonDetails & TAppend> {\n return this.#transport.get(\n `/tv/${toId(seriesId, 'seriesId')}/season/${toSeasonNumber(seasonNumber)}`,\n {\n query: withLanguage(this.#transport.defaults, {\n append_to_response: toCommaList(options.appendToResponse),\n language: options.language,\n }),\n signal: options.signal,\n },\n )\n }\n\n seasonCredits(\n seriesId: number,\n seasonNumber: number,\n options: LanguageOptions = {},\n ): Promise<CreditsResponse> {\n return this.#transport.get(\n `/tv/${toId(seriesId, 'seriesId')}/season/${toSeasonNumber(seasonNumber)}/credits`,\n {\n query: withLanguage(this.#transport.defaults, {\n language: options.language,\n }),\n signal: options.signal,\n },\n )\n }\n\n seasonAggregateCredits(\n seriesId: number,\n seasonNumber: number,\n options: LanguageOptions = {},\n ): Promise<AggregateCreditsResponse> {\n return this.#transport.get(\n `/tv/${toId(seriesId, 'seriesId')}/season/${toSeasonNumber(seasonNumber)}/aggregate_credits`,\n {\n query: withLanguage(this.#transport.defaults, {\n language: options.language,\n }),\n signal: options.signal,\n },\n )\n }\n\n seasonImages(\n seriesId: number,\n seasonNumber: number,\n options: ImageQueryOptions = {},\n ): Promise<SeasonImagesResponse> {\n return this.#transport.get(\n `/tv/${toId(seriesId, 'seriesId')}/season/${toSeasonNumber(seasonNumber)}/images`,\n {\n query: withLanguage(this.#transport.defaults, {\n include_image_language: toCommaList(options.includeImageLanguage),\n language: options.language,\n }),\n signal: options.signal,\n },\n )\n }\n\n seasonVideos(\n seriesId: number,\n seasonNumber: number,\n options: LanguageOptions = {},\n ): Promise<VideosResponse> {\n return this.#transport.get(\n `/tv/${toId(seriesId, 'seriesId')}/season/${toSeasonNumber(seasonNumber)}/videos`,\n {\n query: withLanguage(this.#transport.defaults, {\n language: options.language,\n }),\n signal: options.signal,\n },\n )\n }\n\n episodeDetails<TAppend extends TMDBObject = TMDBObject>(\n seriesId: number,\n seasonNumber: number,\n episodeNumber: number,\n options: EpisodeDetailsOptions = {},\n ): Promise<EpisodeDetails & TAppend> {\n return this.#transport.get(\n `/tv/${toId(seriesId, 'seriesId')}/season/${toSeasonNumber(seasonNumber)}/episode/${toId(episodeNumber, 'episodeNumber')}`,\n {\n query: withLanguage(this.#transport.defaults, {\n append_to_response: toCommaList(options.appendToResponse),\n language: options.language,\n }),\n signal: options.signal,\n },\n )\n }\n\n aggregateCredits(\n seriesId: number,\n options: LanguageOptions = {},\n ): Promise<AggregateCreditsResponse> {\n return this.#transport.get(`/tv/${toId(seriesId, 'seriesId')}/aggregate_credits`, {\n query: withLanguage(this.#transport.defaults, {\n language: options.language,\n }),\n signal: options.signal,\n })\n }\n\n episodeGroups(seriesId: number, options: LanguageOptions = {}): Promise<EpisodeGroupsResponse> {\n return this.#transport.get(`/tv/${toId(seriesId, 'seriesId')}/episode_groups`, {\n query: withLanguage(this.#transport.defaults, {\n language: options.language,\n }),\n signal: options.signal,\n })\n }\n\n episodeGroup(groupId: string, options: LanguageOptions = {}): Promise<EpisodeGroupDetails> {\n return this.#transport.get(`/tv/episode_group/${toGroupId(groupId)}`, {\n query: withLanguage(this.#transport.defaults, {\n language: options.language,\n }),\n signal: options.signal,\n })\n }\n}\n\n/** Build query parameters for TV list endpoints. */\nfunction tvListQuery(transport: TMDBTransport, options: Omit<ListOptions, 'region'>): QueryParams {\n return withLanguage(transport.defaults, {\n language: options.language,\n page: options.page,\n })\n}\n",
|
|
16
|
+
"import {\n TMDBHttpClient,\n type TMDBClientOptions,\n type TMDBRequestOptions,\n type TMDBTransport,\n} from './http'\nimport { ConfigurationResource } from './resources/configuration'\nimport { GenresResource } from './resources/genres'\nimport { ImagesHelper } from './resources/images'\nimport { MoviesResource } from './resources/movies'\nimport { PeopleResource } from './resources/people'\nimport { SearchResource } from './resources/search'\nimport { TrendingResource } from './resources/trending'\nimport { TVResource } from './resources/tv'\n\n/**\n * Options accepted when the caller supplies a custom transport.\n *\n * The transport owns authentication, so credentials are not required.\n */\nexport type TMDBTransportOptions = Omit<TMDBClientOptions, 'accessToken' | 'apiKey'> & {\n transport: TMDBTransport\n}\n\n/**\n * Options accepted by {@link createTMDB} and the {@link TMDBClient} constructor.\n *\n * Either provide credentials for the built-in transport, or pass a custom\n * {@link TMDBTransport} (typically for tests, caching, or instrumentation)\n * without credentials.\n */\nexport type TMDBFactoryOptions =\n (TMDBClientOptions & { transport?: TMDBTransport }) | TMDBTransportOptions\n\n/**\n * Main SDK entry point.\n *\n * Resource properties are intentionally small and explicit. The SDK focuses on\n * common TMDB workflows first, while request<T>() keeps uncommon endpoints easy\n * to call without waiting for a generated surface area.\n */\nexport class TMDBClient {\n readonly configuration: ConfigurationResource\n readonly genres: GenresResource\n readonly images: ImagesHelper\n readonly movies: MoviesResource\n readonly people: PeopleResource\n readonly search: SearchResource\n readonly trending: TrendingResource\n readonly tv: TVResource\n\n readonly #transport: TMDBTransport\n\n constructor(options: TMDBFactoryOptions) {\n // When the caller supplies a custom transport we still want to honor the\n // global images.transform option; otherwise read it back from the HTTP\n // client after it has been constructed.\n let imageTransform = options.images?.transform\n\n if (options.transport === undefined) {\n // Transport-only options always define a transport, so this branch has credentials.\n const builtInClient = new TMDBHttpClient(options as TMDBClientOptions)\n this.#transport = builtInClient\n imageTransform = builtInClient.imageTransform\n } else {\n this.#transport = options.transport\n }\n\n this.configuration = new ConfigurationResource(this.#transport)\n this.genres = new GenresResource(this.#transport)\n this.images = new ImagesHelper(this.#transport, imageTransform)\n this.movies = new MoviesResource(this.#transport)\n this.people = new PeopleResource(this.#transport)\n this.search = new SearchResource(this.#transport)\n this.trending = new TrendingResource(this.#transport)\n this.tv = new TVResource(this.#transport)\n }\n\n /**\n * Make a raw GET request to any TMDB endpoint.\n *\n * This is an escape hatch for endpoints not covered by the typed resource\n * helpers. The `path` should be relative to the API base URL (e.g.\n * `/movie/{id}/credits`). Response is parsed as JSON and cast to `T`.\n *\n * @param path - API path relative to the base URL (e.g. `/movie/123`)\n * @param options - Optional request-level overrides (headers, query, signal)\n * @returns Parsed JSON response typed as `T`\n */\n request<T>(path: string, options?: TMDBRequestOptions): Promise<T> {\n return this.#transport.get<T>(path, options)\n }\n}\n\n/**\n * Create a new {@link TMDBClient} instance.\n *\n * @example\n * ```ts\n * const tmdb = createTMDB({ accessToken: 'YOUR_TOKEN' })\n * const { results } = await tmdb.search.movies('Inception')\n * ```\n *\n * @param options - Authentication and configuration options\n * @returns A configured TMDBClient ready to make API calls\n */\nexport function createTMDB(options: TMDBFactoryOptions): TMDBClient {\n return new TMDBClient(options)\n}\n",
|
|
17
|
+
"import type { TMDBRequestOptions, TMDBTransport } from '../http'\nimport type { QueryParams } from '../query'\n\nexport interface MemoryCacheOptions {\n /** Entry lifetime in milliseconds. Defaults to 300000 (5 minutes). */\n ttlMs?: number\n /** Maximum number of cached responses. Defaults to 100. */\n maxEntries?: number\n}\n\nexport type MemoryCacheTransport<T extends TMDBTransport = TMDBTransport> = T & {\n /** Remove every cached response. */\n clear(): void\n}\n\ninterface CacheEntry {\n expiresAt: number\n value: unknown\n}\n\n/**\n * Wrap a transport with a small in-memory LRU cache.\n *\n * Only successful responses are cached. The key includes the path, sorted\n * query parameters, and sorted headers, so language, region, and header\n * variants never collide. Signals are intentionally excluded from the key.\n * Use one cache per client or credential: authentication is not part of the\n * key.\n *\n * ```ts\n * const http = new TMDBHttpClient({ accessToken })\n * const tmdb = createTMDB({\n * transport: withMemoryCache(http, { ttlMs: 60_000, maxEntries: 200 }),\n * })\n * ```\n */\nexport function withMemoryCache<T extends TMDBTransport>(\n transport: T,\n options: MemoryCacheOptions = {},\n): MemoryCacheTransport<T> {\n const ttlMs = options.ttlMs ?? 5 * 60_000\n const maxEntries = options.maxEntries ?? 100\n\n if (!Number.isFinite(ttlMs) || ttlMs <= 0) {\n throw new RangeError('ttlMs must be a positive number')\n }\n if (!Number.isInteger(maxEntries) || maxEntries < 1) {\n throw new RangeError('maxEntries must be a positive integer')\n }\n\n const entries = new Map<string, CacheEntry>()\n\n return {\n ...transport,\n async get<U>(path: string, requestOptions: TMDBRequestOptions = {}): Promise<U> {\n const key = cacheKey(path, requestOptions)\n const cached = entries.get(key)\n\n if (cached !== undefined) {\n if (cached.expiresAt > Date.now()) {\n // Refresh the LRU position.\n entries.delete(key)\n entries.set(key, cached)\n return cached.value as U\n }\n entries.delete(key)\n }\n\n const value = await transport.get<U>(path, requestOptions)\n entries.set(key, { expiresAt: Date.now() + ttlMs, value })\n evictOverflow(entries, maxEntries)\n return value\n },\n clear() {\n entries.clear()\n },\n }\n}\n\nfunction cacheKey(path: string, options: TMDBRequestOptions): string {\n return `${path}?${serializeQuery(options.query)}|${serializeHeaders(options.headers)}`\n}\n\nfunction serializeQuery(query: QueryParams | undefined): string {\n if (query === undefined) {\n return ''\n }\n\n return Object.entries(query)\n .filter(([, value]) => value !== undefined && value !== null)\n .sort(([left], [right]) => left.localeCompare(right))\n .map(\n ([key, value]) =>\n `${key}=${Array.isArray(value) ? value.map(String).join(',') : String(value)}`,\n )\n .join('&')\n}\n\nfunction serializeHeaders(headers: HeadersInit | undefined): string {\n if (headers === undefined) {\n return ''\n }\n\n return [...new Headers(headers)]\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([key, value]) => `${key}:${value}`)\n .join('|')\n}\n\nfunction evictOverflow(entries: Map<string, CacheEntry>, maxEntries: number): void {\n while (entries.size > maxEntries) {\n // The loop condition guarantees at least one key.\n entries.delete(entries.keys().next().value as string)\n }\n}\n",
|
|
18
|
+
"import type { PagedResponse } from '../types'\n\n/** Fetches a single page. The caller closes over its own query options. */\nexport interface PageFetcher<T> {\n (page: number): Promise<PagedResponse<T>>\n}\n\nexport interface PaginateOptions {\n /** First page to request. Defaults to 1. */\n startPage?: number\n /** Last page to request, inclusive. Defaults to 500, TMDB's documented cap. */\n endPage?: number\n /** Cancels the iteration before the next request. */\n signal?: AbortSignal\n}\n\n/**\n * Iterate a paged TMDB endpoint page by page.\n *\n * Stops when the API reports the last page, when a page has no results,\n * when `endPage` is reached, or when the signal is aborted. Yields nothing\n * when `endPage` is lower than `startPage`. The fetcher\n * receives the page number and should forward the signal to the SDK:\n *\n * ```ts\n * for await (const page of paginate((page) => tmdb.movies.popular({ page, signal }))) {\n * console.log(page.page, page.results.length)\n * }\n * ```\n */\nexport async function* paginate<T>(\n fetchPage: PageFetcher<T>,\n options: PaginateOptions = {},\n): AsyncGenerator<PagedResponse<T>, void, undefined> {\n const startPage = options.startPage ?? 1\n const endPage = options.endPage ?? 500\n assertPositiveInteger(startPage, 'startPage')\n assertPositiveInteger(endPage, 'endPage')\n\n for (let page = startPage; page <= endPage; page += 1) {\n options.signal?.throwIfAborted()\n\n const response = await fetchPage(page)\n yield response\n\n if (response.results.length === 0 || page >= response.total_pages) {\n return\n }\n }\n}\n\n/**\n * Iterate a paged TMDB endpoint item by item.\n *\n * Built on {@link paginate}; use `paginate` directly when you need page\n * metadata such as `total_pages`.\n */\nexport async function* paginateItems<T>(\n fetchPage: PageFetcher<T>,\n options: PaginateOptions = {},\n): AsyncGenerator<T, void, undefined> {\n for await (const page of paginate(fetchPage, options)) {\n yield* page.results\n }\n}\n\nfunction assertPositiveInteger(value: number, name: string): void {\n if (!Number.isInteger(value) || value < 1) {\n throw new RangeError(`${name} must be a positive integer`)\n }\n}\n",
|
|
19
|
+
"import {\n parseRetryAfter,\n TMDBRateLimitError,\n TMDBRequestError,\n TMDBResponseError,\n TMDBTimeoutError,\n} from '../errors'\nimport type { TMDBRequestOptions, TMDBTransport } from '../http'\n\nexport interface RetryInfo {\n /** Zero-based attempt number that failed. */\n attempt: number\n /** Delay before the next attempt, in milliseconds. */\n delayMs: number\n error: unknown\n}\n\nexport interface RetryOptions {\n /** Retries after the first attempt. Defaults to 2. */\n retries?: number\n /** Base delay for exponential backoff in milliseconds. Defaults to 250. */\n baseDelayMs?: number\n /** Maximum exponential backoff delay in milliseconds. Defaults to 10000. */\n maxDelayMs?: number\n /** Exponential backoff factor. Defaults to 2. */\n factor?: number\n /** Apply full jitter to exponential delays. Defaults to true. */\n jitter?: boolean\n /** Cancels the delay and any further attempts. */\n signal?: AbortSignal\n /** Replaces the default retry predicate. */\n retryOn?: (error: unknown, attempt: number) => boolean\n /** Observes each retry decision without changing it. */\n onRetry?: (info: RetryInfo) => void\n}\n\n/** Retry-After values above this ceiling are clamped to keep callers responsive. */\nconst MAX_RETRY_AFTER_MS = 60_000\n\n/**\n * Retry an async task using TMDB-aware defaults.\n *\n * Retries 429 and any response that carries `Retry-After`, retries 408 and\n * 5xx responses plus network failures with exponential backoff, and never\n * retries other 4xx responses, validation errors, aborts, or timeouts. All\n * TMDB requests are GETs, so the helper is safe for every resource method.\n */\nexport async function retry<T>(task: () => Promise<T>, options: RetryOptions = {}): Promise<T> {\n const retries = options.retries ?? 2\n if (!Number.isInteger(retries) || retries < 0) {\n throw new RangeError('retries must be a non-negative integer')\n }\n\n const retryOn = options.retryOn ?? shouldRetry\n const signal = options.signal\n\n if (signal?.aborted) {\n throw signal.reason\n }\n\n for (let attempt = 0; ; attempt += 1) {\n try {\n return await task()\n } catch (error) {\n if (signal?.aborted) {\n throw signal.reason\n }\n if (attempt >= retries || !retryOn(error, attempt)) {\n throw error\n }\n\n const delayMs = retryDelay(error, attempt, options)\n options.onRetry?.({ attempt, delayMs, error })\n await sleep(delayMs, signal)\n }\n }\n}\n\n/**\n * Wrap a transport so every request uses {@link retry}.\n *\n * ```ts\n * const http = new TMDBHttpClient({ accessToken })\n * const tmdb = createTMDB({ transport: withRetry(http, { retries: 3 }) })\n * ```\n *\n * A wrapper-level `signal` and a per-request `signal` are combined, so\n * aborting either cancels the call. Extra transport members are preserved.\n */\nexport function withRetry<T extends TMDBTransport>(transport: T, options: RetryOptions = {}): T {\n return {\n ...transport,\n get<U>(path: string, requestOptions?: TMDBRequestOptions): Promise<U> {\n const { cleanup, signal } = combineSignals(options.signal, requestOptions?.signal)\n const effectiveOptions = signal === undefined ? requestOptions : { ...requestOptions, signal }\n\n return retry(() => transport.get<U>(path, effectiveOptions), {\n ...options,\n signal,\n }).finally(cleanup)\n },\n }\n}\n\nfunction shouldRetry(error: unknown): boolean {\n if (error instanceof TMDBRateLimitError) {\n return true\n }\n if (error instanceof TMDBResponseError) {\n return error.isServerError || error.status === 408\n }\n if (error instanceof TMDBTimeoutError) {\n return false\n }\n if (error instanceof TMDBRequestError) {\n if (error.cause === undefined || error.cause instanceof TMDBTimeoutError) {\n return false\n }\n return !isAbortError(error.cause)\n }\n return false\n}\n\nfunction retryDelay(error: unknown, attempt: number, options: RetryOptions): number {\n const retryAfter = retryAfterMs(error)\n if (retryAfter !== undefined) {\n return Math.min(Math.max(retryAfter, 0), MAX_RETRY_AFTER_MS)\n }\n\n if (error instanceof TMDBRateLimitError) {\n return Math.min(Math.max(error.retryAfter * 1000, 0), MAX_RETRY_AFTER_MS)\n }\n\n const baseDelayMs = options.baseDelayMs ?? 250\n const maxDelayMs = options.maxDelayMs ?? 10_000\n const factor = options.factor ?? 2\n const delay = Math.min(maxDelayMs, baseDelayMs * factor ** attempt)\n\n return options.jitter === false ? delay : Math.random() * delay\n}\n\nfunction retryAfterMs(error: unknown): number | undefined {\n if (!(error instanceof TMDBResponseError)) {\n return undefined\n }\n\n const header = error.headers.get('retry-after')\n if (header === null || header.trim() === '') {\n return undefined\n }\n\n return parseRetryAfter(header) * 1000\n}\n\n/**\n * Combine a wrapper-level signal with a per-request signal.\n *\n * `AbortSignal.any()` requires Node 20.3+, while the package supports Node 18,\n * so the fallback keeps both signals wired to one controller. The cleanup\n * function detaches the listeners once the request settles.\n */\nfunction combineSignals(\n first: AbortSignal | undefined,\n second: AbortSignal | undefined,\n): { cleanup: () => void; signal: AbortSignal | undefined } {\n if (first === undefined || second === undefined || first === second) {\n return { cleanup: noop, signal: first ?? second }\n }\n\n const controller = new AbortController()\n const onAbort = () => controller.abort((first.aborted ? first : second).reason)\n\n first.addEventListener('abort', onAbort, { once: true })\n second.addEventListener('abort', onAbort, { once: true })\n\n // Either signal may have aborted between the guard above and registration.\n if (first.aborted || second.aborted) {\n onAbort()\n }\n\n return {\n cleanup() {\n first.removeEventListener('abort', onAbort)\n second.removeEventListener('abort', onAbort)\n },\n signal: controller.signal,\n }\n}\n\nfunction noop(): void {}\n\nfunction isAbortError(error: unknown): boolean {\n return (\n typeof error === 'object' &&\n error !== null &&\n 'name' in error &&\n (error as { name?: unknown }).name === 'AbortError'\n )\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n const onAbort = () => {\n clearTimeout(timer)\n signal?.removeEventListener('abort', onAbort)\n reject(signal!.reason)\n }\n\n const timer = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort)\n resolve()\n }, ms)\n\n signal?.addEventListener('abort', onAbort, { once: true })\n\n // The signal may have fired before the listener was registered.\n if (signal?.aborted) {\n onAbort()\n }\n })\n}\n",
|
|
20
|
+
"import { TMDBTimeoutError } from '../errors'\n\nexport interface TimeoutOptions {\n /** Parent signal. Aborting it cancels the task with the same reason. */\n signal?: AbortSignal\n /** Custom message for the TMDBTimeoutError. */\n message?: string\n}\n\n/**\n * Run a task with an AbortSignal-backed timeout.\n *\n * The task must forward the provided signal to the SDK for cancellation to\n * take effect. Timeouts are reported as {@link TMDBTimeoutError}; aborts from\n * the parent signal keep the parent's reason.\n *\n * ```ts\n * const movie = await withTimeout(5_000, (signal) =>\n * tmdb.movies.details(550, { signal }),\n * )\n * ```\n */\nexport async function withTimeout<T>(\n timeoutMs: number,\n task: (signal: AbortSignal) => Promise<T>,\n options: TimeoutOptions = {},\n): Promise<T> {\n if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {\n throw new RangeError('timeoutMs must be a positive number')\n }\n\n const parent = options.signal\n const controller = new AbortController()\n const timeoutError = new TMDBTimeoutError(timeoutMs, options.message)\n const onAbort = () => controller.abort(parent!.reason)\n\n // Register first, then check, so an abort cannot slip through the gap.\n parent?.addEventListener('abort', onAbort, { once: true })\n if (parent?.aborted) {\n parent.removeEventListener('abort', onAbort)\n throw parent.reason\n }\n\n const timer = setTimeout(() => controller.abort(timeoutError), timeoutMs)\n\n try {\n return await task(controller.signal)\n } catch (error) {\n if (controller.signal.reason === timeoutError) {\n throw timeoutError\n }\n if (parent?.aborted) {\n throw parent.reason\n }\n throw error\n } finally {\n clearTimeout(timer)\n parent?.removeEventListener('abort', onAbort)\n }\n}\n",
|
|
21
|
+
"import type {\n MovieMultiResult,\n MovieSearchResult,\n PersonMultiResult,\n PersonSearchResult,\n SearchMultiResult,\n TVMultiResult,\n TVSearchResult,\n} from './types'\n\n/**\n * Type guard that narrows a `search.multi()` result to a movie entry.\n *\n * The `media_type` field is required on every `/search/multi` payload by\n * TMDB, so this check is safe at runtime and produces a strictly typed\n * MovieSummary on the narrowed branch.\n */\nexport function isMovieSearchResult(result: SearchMultiResult): result is MovieMultiResult\nexport function isMovieSearchResult(result: unknown): result is MovieMultiResult\nexport function isMovieSearchResult(result: unknown): result is MovieMultiResult {\n return isObjectWithMediaType(result, 'movie')\n}\n\n/** Type guard that narrows a `search.multi()` result to a TV entry. */\nexport function isTVSearchResult(result: SearchMultiResult): result is TVMultiResult\nexport function isTVSearchResult(result: unknown): result is TVMultiResult\nexport function isTVSearchResult(result: unknown): result is TVMultiResult {\n return isObjectWithMediaType(result, 'tv')\n}\n\n/** Type guard that narrows a `search.multi()` result to a person entry. */\nexport function isPersonSearchResult(result: SearchMultiResult): result is PersonMultiResult\nexport function isPersonSearchResult(result: unknown): result is PersonMultiResult\nexport function isPersonSearchResult(result: unknown): result is PersonMultiResult {\n return isObjectWithMediaType(result, 'person')\n}\n\n/**\n * Convenience alias: `isMovieSearchResult` works on a `search.movies()`\n * result (which already has the narrow type but is also tagged with\n * `media_type?: 'movie'`), as well as on multi-search results.\n */\nexport function isMovie(result: MovieSearchResult | SearchMultiResult): result is MovieMultiResult\nexport function isMovie(result: SearchMultiResult): result is MovieMultiResult\nexport function isMovie(result: unknown): result is MovieMultiResult\nexport function isMovie(result: unknown): result is MovieMultiResult {\n return isObjectWithMediaType(result, 'movie')\n}\n\n/** Type guard that narrows a search result to a TV entry. */\nexport function isTV(result: TVSearchResult | SearchMultiResult): result is TVMultiResult\nexport function isTV(result: SearchMultiResult): result is TVMultiResult\nexport function isTV(result: unknown): result is TVMultiResult\nexport function isTV(result: unknown): result is TVMultiResult {\n return isObjectWithMediaType(result, 'tv')\n}\n\n/** Type guard that narrows a search result to a person entry. */\nexport function isPerson(\n result: PersonSearchResult | SearchMultiResult,\n): result is PersonMultiResult\nexport function isPerson(result: SearchMultiResult): result is PersonMultiResult\nexport function isPerson(result: unknown): result is PersonMultiResult\nexport function isPerson(result: unknown): result is PersonMultiResult {\n return isObjectWithMediaType(result, 'person')\n}\n\n/** Internal helper: check if a value is an object with a matching `media_type` field. */\nfunction isObjectWithMediaType(value: unknown, mediaType: 'movie' | 'tv' | 'person'): boolean {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'media_type' in value &&\n (value as { media_type: unknown }).media_type === mediaType\n )\n}\n",
|
|
22
|
+
"/** Primitive JSON values returned by TMDB. */\nexport type JsonPrimitive = string | number | boolean | null\n\n/** JSON object/array tree returned by TMDB for fields this SDK does not model yet. */\nexport type JsonValue = JsonPrimitive | JsonObject | JsonValue[]\n\nexport interface JsonObject {\n [key: string]: JsonValue | undefined\n}\n\n/** Escape hatch for append_to_response payloads and future TMDB fields. */\nexport type TMDBObject = Record<string, unknown>\n\n/** Date string in TMDB format (typically `YYYY-MM-DD`). */\nexport type TMDBDateString = string\n\n/** ISO 639-1 language code (e.g. `\"en\"`, `\"zh\"`). */\nexport type LanguageCode = string\n\n/** ISO 3166-1 country/region code (e.g. `\"US\"`, `\"CN\"`). */\nexport type RegionCode = string\n\n/** Supported media types for multi-search results. */\nexport type MediaType = 'movie' | 'tv' | 'person'\n\n/** Time window for trending endpoints: `\"day\"` or `\"week\"`. */\nexport type TrendingTimeWindow = 'day' | 'week'\n\nexport interface PagedResponse<T> {\n page: number\n results: T[]\n total_pages: number\n total_results: number\n}\n\nexport interface Genre {\n id: number\n name: string\n}\n\nexport interface ProductionCompany {\n id: number\n logo_path: string | null\n name: string\n origin_country: string\n}\n\nexport interface ProductionCountry {\n iso_3166_1: string\n name: string\n}\n\nexport interface SpokenLanguage {\n english_name: string\n iso_639_1: string\n name: string\n}\n\nexport interface CollectionSummary {\n id: number\n name: string\n poster_path: string | null\n backdrop_path: string | null\n}\n\nexport interface MovieSummary {\n adult: boolean\n backdrop_path: string | null\n genre_ids: number[]\n id: number\n original_language: string\n original_title: string\n overview: string\n popularity: number\n poster_path: string | null\n release_date: TMDBDateString\n title: string\n video: boolean\n vote_average: number\n vote_count: number\n}\n\nexport interface MovieDetails extends Omit<MovieSummary, 'genre_ids'> {\n belongs_to_collection: CollectionSummary | null\n budget: number\n genres: Genre[]\n homepage: string | null\n imdb_id: string | null\n production_companies: ProductionCompany[]\n production_countries: ProductionCountry[]\n revenue: number\n runtime: number | null\n spoken_languages: SpokenLanguage[]\n status: string\n tagline: string | null\n}\n\nexport interface TVSummary {\n adult?: boolean\n backdrop_path: string | null\n first_air_date: TMDBDateString\n genre_ids: number[]\n id: number\n name: string\n origin_country: string[]\n original_language: string\n original_name: string\n overview: string\n popularity: number\n poster_path: string | null\n vote_average: number\n vote_count: number\n}\n\nexport interface CreatedBy {\n id: number\n credit_id: string\n name: string\n gender: number\n profile_path: string | null\n}\n\nexport interface Network {\n id: number\n logo_path: string | null\n name: string\n origin_country: string\n}\n\nexport interface SeasonSummary {\n air_date: TMDBDateString | null\n episode_count: number\n id: number\n name: string\n overview: string\n poster_path: string | null\n season_number: number\n vote_average: number\n}\n\nexport interface EpisodeGuestStar {\n adult: boolean\n character: string\n credit_id: string\n gender: number | null\n id: number\n known_for_department: string\n name: string\n order: number\n original_name: string\n popularity: number\n profile_path: string | null\n}\n\nexport interface EpisodeSummary {\n air_date: TMDBDateString | null\n crew: CreditCrewMember[]\n episode_number: number\n episode_type: string\n guest_stars: EpisodeGuestStar[]\n id: number\n name: string\n overview: string\n production_code: string | null\n runtime: number | null\n season_number: number\n show_id: number\n still_path: string | null\n vote_average: number\n vote_count: number\n}\n\nexport interface TVSeasonDetails {\n _id: string\n air_date: TMDBDateString | null\n episodes: EpisodeSummary[]\n id: number\n name: string\n overview: string\n poster_path: string | null\n season_number: number\n vote_average: number\n}\n\nexport type TVSeasonAppendToResponse =\n | 'account_states'\n | 'aggregate_credits'\n | 'credits'\n | 'external_ids'\n | 'images'\n | 'translations'\n | 'videos'\n | (string & {})\n\nexport interface TVSeasonDetailsOptions extends LanguageOptions {\n appendToResponse?: TVSeasonAppendToResponse | readonly TVSeasonAppendToResponse[]\n}\n\n/**\n * Episode details endpoint payload. Unlike {@link EpisodeSummary}, the\n * single-episode endpoint does not return `show_id`.\n */\nexport type EpisodeDetails = Omit<EpisodeSummary, 'show_id'>\n\nexport type EpisodeAppendToResponse =\n | 'account_states'\n | 'credits'\n | 'external_ids'\n | 'images'\n | 'translations'\n | 'videos'\n | (string & {})\n\nexport interface EpisodeDetailsOptions extends LanguageOptions {\n appendToResponse?: EpisodeAppendToResponse | readonly EpisodeAppendToResponse[]\n}\n\nexport interface AggregateRole {\n credit_id: string\n character: string\n episode_count: number\n}\n\nexport interface AggregateJob {\n credit_id: string\n job: string\n episode_count: number\n}\n\nexport interface AggregateCastMember {\n adult?: boolean\n gender: number | null\n id: number\n known_for_department: string\n name: string\n order: number\n original_name: string\n popularity: number\n profile_path: string | null\n roles: AggregateRole[]\n total_episode_count: number\n}\n\nexport interface AggregateCrewMember {\n adult?: boolean\n department: string\n gender: number | null\n id: number\n jobs: AggregateJob[]\n known_for_department: string\n name: string\n original_name: string\n popularity: number\n profile_path: string | null\n total_episode_count: number\n}\n\nexport interface AggregateCreditsResponse {\n id: number\n cast: AggregateCastMember[]\n crew: AggregateCrewMember[]\n}\n\nexport interface EpisodeGroupSummary {\n description: string\n episode_count: number\n group_count: number\n id: string\n name: string\n network: Network | null\n type: number\n}\n\nexport interface EpisodeGroupsResponse {\n id: number\n results: EpisodeGroupSummary[]\n}\n\nexport interface EpisodeGroupEpisode {\n air_date: TMDBDateString | null\n episode_number: number\n episode_type: string\n id: number\n name: string\n order: number\n overview: string\n production_code: string | null\n runtime: number | null\n season_number: number\n show_id: number\n still_path: string | null\n vote_average: number\n vote_count: number\n}\n\nexport interface EpisodeGroup {\n id: string\n name: string\n order: number\n locked: boolean\n episodes: EpisodeGroupEpisode[]\n}\n\nexport interface EpisodeGroupDetails extends EpisodeGroupSummary {\n groups: EpisodeGroup[]\n}\n\nexport interface TVDetails extends Omit<TVSummary, 'genre_ids'> {\n created_by: CreatedBy[]\n episode_run_time: number[]\n genres: Genre[]\n homepage: string | null\n in_production: boolean\n languages: string[]\n last_air_date: TMDBDateString | null\n networks: Network[]\n number_of_episodes: number\n number_of_seasons: number\n production_companies: ProductionCompany[]\n production_countries: ProductionCountry[]\n seasons: SeasonSummary[]\n spoken_languages: SpokenLanguage[]\n status: string\n tagline: string | null\n type: string\n}\n\nexport interface PersonKnownForMovie extends MovieSummary {\n media_type: 'movie'\n}\n\nexport interface PersonKnownForTV extends TVSummary {\n media_type: 'tv'\n}\n\nexport type PersonKnownFor = PersonKnownForMovie | PersonKnownForTV\n\nexport interface PersonSummary {\n adult: boolean\n gender: number\n id: number\n known_for: PersonKnownFor[]\n known_for_department: string\n name: string\n original_name?: string\n popularity: number\n profile_path: string | null\n}\n\nexport interface PersonDetails extends Omit<PersonSummary, 'known_for'> {\n also_known_as: string[]\n biography: string\n birthday: TMDBDateString | null\n deathday: TMDBDateString | null\n homepage: string | null\n imdb_id: string | null\n place_of_birth: string | null\n}\n\nexport interface PersonCombinedCastMovie extends MovieSummary {\n character: string\n credit_id: string\n media_type: 'movie'\n order?: number\n}\n\nexport interface PersonCombinedCastTV extends TVSummary {\n character: string\n credit_id: string\n episode_count?: number\n media_type: 'tv'\n}\n\nexport type PersonCombinedCast = PersonCombinedCastMovie | PersonCombinedCastTV\n\nexport interface PersonCombinedCrewMovie extends MovieSummary {\n credit_id: string\n department: string\n job: string\n media_type: 'movie'\n}\n\nexport interface PersonCombinedCrewTV extends TVSummary {\n credit_id: string\n department: string\n job: string\n media_type: 'tv'\n}\n\nexport type PersonCombinedCrew = PersonCombinedCrewMovie | PersonCombinedCrewTV\n\nexport interface PersonCombinedCreditsResponse {\n cast: PersonCombinedCast[]\n crew: PersonCombinedCrew[]\n id: number\n}\n\nexport interface MovieSearchResult extends MovieSummary {\n media_type?: 'movie'\n}\n\nexport interface TVSearchResult extends TVSummary {\n media_type?: 'tv'\n}\n\nexport interface PersonSearchResult extends PersonSummary {\n media_type?: 'person'\n}\n\nexport type SearchMultiResult =\n | (MovieSummary & { media_type: 'movie' })\n | (TVSummary & { media_type: 'tv' })\n | (PersonSummary & { media_type: 'person' })\n\n/** A single multi-search result narrowed to a specific media type. */\nexport type MovieMultiResult = MovieSummary & { media_type: 'movie' }\nexport type TVMultiResult = TVSummary & { media_type: 'tv' }\nexport type PersonMultiResult = PersonSummary & { media_type: 'person' }\n\nexport type TrendingResult = SearchMultiResult\n\nexport interface CreditCastMember {\n adult?: boolean\n cast_id?: number\n character: string\n credit_id: string\n gender: number | null\n id: number\n known_for_department: string\n name: string\n order: number\n original_name: string\n popularity: number\n profile_path: string | null\n}\n\nexport interface CreditCrewMember {\n adult?: boolean\n credit_id: string\n department: string\n gender: number | null\n id: number\n job: string\n known_for_department: string\n name: string\n original_name: string\n popularity: number\n profile_path: string | null\n}\n\nexport interface CreditsResponse {\n id: number\n cast: CreditCastMember[]\n crew: CreditCrewMember[]\n}\n\nexport interface Video {\n id: string\n iso_3166_1: string\n iso_639_1: string\n key: string\n name: string\n official: boolean\n published_at: string\n site: string\n size: number\n type: string\n}\n\nexport interface VideosResponse {\n id: number\n results: Video[]\n}\n\nexport interface ImageItem {\n aspect_ratio: number\n height: number\n iso_639_1: string | null\n file_path: string\n vote_average: number\n vote_count: number\n width: number\n}\n\nexport interface ImagesResponse {\n id: number\n backdrops: ImageItem[]\n logos?: ImageItem[]\n posters: ImageItem[]\n}\n\nexport interface SeasonImagesResponse {\n id: number\n posters: ImageItem[]\n}\n\nexport interface ConfigurationImages {\n base_url: string\n secure_base_url: string\n backdrop_sizes: string[]\n logo_sizes: string[]\n poster_sizes: string[]\n profile_sizes: string[]\n still_sizes: string[]\n}\n\nexport interface Configuration {\n images: ConfigurationImages\n change_keys: string[]\n}\n\nexport interface Country {\n iso_3166_1: string\n english_name: string\n native_name: string\n}\n\nexport interface Language {\n iso_639_1: string\n english_name: string\n name: string\n}\n\nexport interface Timezone {\n iso_3166_1: string\n zones: string[]\n}\n\nexport interface JobDepartment {\n department: string\n jobs: string[]\n}\n\nexport interface GenresResponse {\n genres: Genre[]\n}\n\nexport type BackdropSize = 'w300' | 'w780' | 'w1280' | 'original' | (string & {})\nexport type LogoSize =\n 'w45' | 'w92' | 'w154' | 'w185' | 'w300' | 'w500' | 'original' | (string & {})\nexport type PosterSize =\n 'w92' | 'w154' | 'w185' | 'w342' | 'w500' | 'w780' | 'original' | (string & {})\nexport type ProfileSize = 'w45' | 'w185' | 'h632' | 'original' | (string & {})\nexport type StillSize = 'w92' | 'w185' | 'w300' | 'original' | (string & {})\nexport type ImageSize = BackdropSize | LogoSize | PosterSize | ProfileSize | StillSize\n\n/**\n * Public set of image sizes TMDB currently documents. The SDK does not\n * pin to a static copy of the TMDB docs — TMDB has added new sizes in\n * the past (e.g. `h632` for profile) without notice — but exposing the\n * canonical list lets callers:\n *\n * - iterate over the set to build a size picker\n * - validate user-supplied sizes with `isKnownBackdropSize(...)` etc.\n * - type a variable as a \"known\" size without giving up the\n * `(string & {})` escape hatch for forward-compatibility\n *\n * If TMDB publishes a new size, the SDK will still accept it at runtime\n * (every helper is `(string & {})` permissive), but you will need to\n * add the literal to these constants to get autocomplete on it.\n */\nexport const KNOWN_BACKDROP_SIZES: readonly ['w300', 'w780', 'w1280', 'original'] = Object.freeze([\n 'w300',\n 'w780',\n 'w1280',\n 'original',\n] as const)\nexport const KNOWN_LOGO_SIZES: readonly ['w45', 'w92', 'w154', 'w185', 'w300', 'w500', 'original'] =\n Object.freeze(['w45', 'w92', 'w154', 'w185', 'w300', 'w500', 'original'] as const)\nexport const KNOWN_POSTER_SIZES: readonly [\n 'w92',\n 'w154',\n 'w185',\n 'w342',\n 'w500',\n 'w780',\n 'original',\n] = Object.freeze(['w92', 'w154', 'w185', 'w342', 'w500', 'w780', 'original'] as const)\nexport const KNOWN_PROFILE_SIZES: readonly ['w45', 'w185', 'h632', 'original'] = Object.freeze([\n 'w45',\n 'w185',\n 'h632',\n 'original',\n] as const)\nexport const KNOWN_STILL_SIZES: readonly ['w92', 'w185', 'w300', 'original'] = Object.freeze([\n 'w92',\n 'w185',\n 'w300',\n 'original',\n] as const)\n\nexport type KnownBackdropSize = (typeof KNOWN_BACKDROP_SIZES)[number]\nexport type KnownLogoSize = (typeof KNOWN_LOGO_SIZES)[number]\nexport type KnownPosterSize = (typeof KNOWN_POSTER_SIZES)[number]\nexport type KnownProfileSize = (typeof KNOWN_PROFILE_SIZES)[number]\nexport type KnownStillSize = (typeof KNOWN_STILL_SIZES)[number]\nexport type KnownImageSize =\n KnownBackdropSize | KnownLogoSize | KnownPosterSize | KnownProfileSize | KnownStillSize\n\n/** Union of every documented image size. */\nexport const KNOWN_IMAGE_SIZES: readonly KnownImageSize[] = Object.freeze([\n ...KNOWN_BACKDROP_SIZES,\n ...KNOWN_LOGO_SIZES,\n ...KNOWN_POSTER_SIZES,\n ...KNOWN_PROFILE_SIZES,\n ...KNOWN_STILL_SIZES,\n] as const)\n\n/** O(1) membership check backed by a Set. */\nconst KNOWN_BACKDROP_SET: ReadonlySet<string> = new Set(KNOWN_BACKDROP_SIZES)\nconst KNOWN_LOGO_SET: ReadonlySet<string> = new Set(KNOWN_LOGO_SIZES)\nconst KNOWN_POSTER_SET: ReadonlySet<string> = new Set(KNOWN_POSTER_SIZES)\nconst KNOWN_PROFILE_SET: ReadonlySet<string> = new Set(KNOWN_PROFILE_SIZES)\nconst KNOWN_STILL_SET: ReadonlySet<string> = new Set(KNOWN_STILL_SIZES)\nconst KNOWN_IMAGE_SET: ReadonlySet<string> = new Set(KNOWN_IMAGE_SIZES)\n\nexport function isKnownBackdropSize(value: string): value is KnownBackdropSize {\n return KNOWN_BACKDROP_SET.has(value)\n}\n\nexport function isKnownLogoSize(value: string): value is KnownLogoSize {\n return KNOWN_LOGO_SET.has(value)\n}\n\nexport function isKnownPosterSize(value: string): value is KnownPosterSize {\n return KNOWN_POSTER_SET.has(value)\n}\n\nexport function isKnownProfileSize(value: string): value is KnownProfileSize {\n return KNOWN_PROFILE_SET.has(value)\n}\n\nexport function isKnownStillSize(value: string): value is KnownStillSize {\n return KNOWN_STILL_SET.has(value)\n}\n\n/** True if `value` is in any documented size set. */\nexport function isKnownImageSize(value: string): value is KnownImageSize {\n return KNOWN_IMAGE_SET.has(value)\n}\n\nexport type MovieAppendToResponse =\n | 'account_states'\n | 'alternative_titles'\n | 'changes'\n | 'credits'\n | 'external_ids'\n | 'images'\n | 'keywords'\n | 'lists'\n | 'recommendations'\n | 'release_dates'\n | 'reviews'\n | 'similar'\n | 'translations'\n | 'videos'\n | 'watch/providers'\n | (string & {})\n\nexport type TVAppendToResponse =\n | 'account_states'\n | 'aggregate_credits'\n | 'alternative_titles'\n | 'changes'\n | 'content_ratings'\n | 'credits'\n | 'episode_groups'\n | 'external_ids'\n | 'images'\n | 'keywords'\n | 'recommendations'\n | 'reviews'\n | 'screened_theatrically'\n | 'similar'\n | 'translations'\n | 'videos'\n | 'watch/providers'\n | (string & {})\n\n/** Per-request options shared by every resource method. */\nexport interface RequestOptions {\n /** AbortSignal used to cancel the underlying request. */\n signal?: AbortSignal\n}\n\nexport interface ListOptions extends RequestOptions {\n language?: LanguageCode\n page?: number\n region?: RegionCode\n}\n\nexport interface LanguageOptions extends RequestOptions {\n language?: LanguageCode\n}\n\nexport interface MovieDetailsOptions extends LanguageOptions {\n appendToResponse?: MovieAppendToResponse | readonly MovieAppendToResponse[]\n}\n\nexport interface TVDetailsOptions extends LanguageOptions {\n appendToResponse?: TVAppendToResponse | readonly TVAppendToResponse[]\n}\n\nexport interface MovieSearchOptions extends ListOptions {\n includeAdult?: boolean\n primaryReleaseYear?: string | number\n year?: string | number\n}\n\nexport interface TVSearchOptions extends Omit<ListOptions, 'region'> {\n firstAirDateYear?: string | number\n includeAdult?: boolean\n year?: string | number\n}\n\nexport interface MultiSearchOptions extends Omit<ListOptions, 'region'> {\n includeAdult?: boolean\n /**\n * Media types to exclude from a `search.multi()` response. Filtering is\n * performed client-side because the TMDB multi-search endpoint does not\n * support a server-side media_type filter.\n */\n exclude?: ReadonlyArray<MediaType>\n}\n\nexport interface ImageQueryOptions extends LanguageOptions {\n includeImageLanguage?: string | readonly string[]\n}\n"
|
|
23
|
+
],
|
|
24
|
+
"mappings": "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",
|
|
25
|
+
"debugId": "24603BBDC4DA497C64756E2164756E21",
|
|
26
|
+
"names": []
|
|
27
|
+
}
|
package/dist/query.d.cts
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import type { ImageSize, RegionCode, LanguageCode, TrendingTimeWindow } from './types.cjs';
|
|
2
|
+
/** Primitives allowed as query parameter values. */
|
|
3
|
+
export type QueryPrimitive = string | number | boolean;
|
|
4
|
+
/** A single query parameter value: primitive, array, or nullish. */
|
|
5
|
+
export type QueryValue = QueryPrimitive | readonly QueryPrimitive[] | null | undefined;
|
|
6
|
+
/** Key-value map of query parameters for API requests. */
|
|
7
|
+
export type QueryParams = Record<string, QueryValue>;
|
|
8
|
+
/** Default query parameters inherited from the client configuration. */
|
|
9
|
+
export interface QueryDefaults {
|
|
10
|
+
language?: LanguageCode;
|
|
11
|
+
region?: RegionCode;
|
|
12
|
+
}
|
|
13
|
+
export declare const DEFAULT_API_BASE_URL = "https://api.themoviedb.org/3";
|
|
14
|
+
export declare const DEFAULT_IMAGE_BASE_URL = "https://image.tmdb.org/t/p";
|
|
15
|
+
/**
|
|
16
|
+
* Append query parameters to a URL object.
|
|
17
|
+
*
|
|
18
|
+
* - `undefined` and `null` values are skipped.
|
|
19
|
+
* - Arrays are joined with commas (TMDB convention).
|
|
20
|
+
* - All values are converted to strings.
|
|
21
|
+
*/
|
|
22
|
+
export declare function appendQuery(url: URL, query: QueryParams): void;
|
|
23
|
+
/**
|
|
24
|
+
* Merge a language query parameter with client defaults.
|
|
25
|
+
*
|
|
26
|
+
* If `query.language` is set it takes precedence; otherwise the client's
|
|
27
|
+
* default language is used.
|
|
28
|
+
*/
|
|
29
|
+
export declare function withLanguage(defaults: QueryDefaults, query: QueryParams): QueryParams;
|
|
30
|
+
/**
|
|
31
|
+
* Merge language and region defaults for list endpoints.
|
|
32
|
+
*
|
|
33
|
+
* Combines {@link withLanguage} with region fallback from client defaults.
|
|
34
|
+
*/
|
|
35
|
+
export declare function withListDefaults(defaults: QueryDefaults, query: QueryParams): QueryParams;
|
|
36
|
+
/**
|
|
37
|
+
* Convert a string or string array to a comma-separated list.
|
|
38
|
+
*
|
|
39
|
+
* Returns `undefined` if the input is `undefined` (skips the parameter).
|
|
40
|
+
* TMDB uses comma-separated values for multi-value query parameters.
|
|
41
|
+
*/
|
|
42
|
+
export declare function toCommaList(value: string | readonly string[] | undefined): string | undefined;
|
|
43
|
+
/**
|
|
44
|
+
* Validate and convert a numeric ID to a string for use in URL paths.
|
|
45
|
+
*
|
|
46
|
+
* @throws {TMDBRequestError} If `value` is not a positive integer.
|
|
47
|
+
*/
|
|
48
|
+
export declare function toId(value: number, name: string): string;
|
|
49
|
+
/**
|
|
50
|
+
* Validate and convert a season number to a string for use in URL paths.
|
|
51
|
+
*
|
|
52
|
+
* Season `0` is valid and refers to specials.
|
|
53
|
+
*
|
|
54
|
+
* @throws {TMDBRequestError} If `value` is not a non-negative integer.
|
|
55
|
+
*/
|
|
56
|
+
export declare function toSeasonNumber(value: number): string;
|
|
57
|
+
/**
|
|
58
|
+
* Validate and normalize a string identifier for use in URL paths.
|
|
59
|
+
*
|
|
60
|
+
* @throws {TMDBRequestError} If `value` is empty or contains non-identifier characters.
|
|
61
|
+
*/
|
|
62
|
+
export declare function toGroupId(value: string): string;
|
|
63
|
+
/**
|
|
64
|
+
* Validate and trim a search query string.
|
|
65
|
+
*
|
|
66
|
+
* @throws {TMDBRequestError} If the query is empty after trimming.
|
|
67
|
+
*/
|
|
68
|
+
export declare function toSearchQuery(value: string): string;
|
|
69
|
+
/**
|
|
70
|
+
* Validate a trending time window value.
|
|
71
|
+
*
|
|
72
|
+
* @throws {TMDBRequestError} If `value` is not `"day"` or `"week"`.
|
|
73
|
+
*/
|
|
74
|
+
export declare function toTimeWindow(value: TrendingTimeWindow): TrendingTimeWindow;
|
|
75
|
+
export interface BuildImageUrlOptions {
|
|
76
|
+
baseUrl?: string;
|
|
77
|
+
/**
|
|
78
|
+
* Transform the resolved TMDB image URL before returning it. Use this to
|
|
79
|
+
* route requests through a CDN, image proxy, or to add signatures.
|
|
80
|
+
*/
|
|
81
|
+
transform?: (url: string) => string;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Build a full TMDB image URL from the path returned by API payloads.
|
|
85
|
+
* Returns null for nullish image paths so UI code can branch naturally.
|
|
86
|
+
*/
|
|
87
|
+
export declare function buildImageUrl(path: string | null | undefined, size?: ImageSize, options?: BuildImageUrlOptions): string | null;
|
|
88
|
+
/**
|
|
89
|
+
* Strip trailing slashes from a base URL to ensure consistent path joining.
|
|
90
|
+
*/
|
|
91
|
+
export declare function normalizeBaseUrl(baseUrl: string): string;
|