tmdb-kit 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/client.d.cts CHANGED
@@ -7,16 +7,24 @@ import { PeopleResource } from './resources/people.cjs';
7
7
  import { SearchResource } from './resources/search.cjs';
8
8
  import { TrendingResource } from './resources/trending.cjs';
9
9
  import { TVResource } from './resources/tv.cjs';
10
+ /**
11
+ * Options accepted when the caller supplies a custom transport.
12
+ *
13
+ * The transport owns authentication, so credentials are not required.
14
+ */
15
+ export type TMDBTransportOptions = Omit<TMDBClientOptions, 'accessToken' | 'apiKey'> & {
16
+ transport: TMDBTransport;
17
+ };
10
18
  /**
11
19
  * Options accepted by {@link createTMDB} and the {@link TMDBClient} constructor.
12
20
  *
13
- * Extends {@link TMDBClientOptions} with an optional {@link TMDBTransport} so
14
- * callers can plug in a custom transport (typically for tests, caching, or
15
- * instrumentation) without having to mock `fetch` or the factory itself.
21
+ * Either provide credentials for the built-in transport, or pass a custom
22
+ * {@link TMDBTransport} (typically for tests, caching, or instrumentation)
23
+ * without credentials.
16
24
  */
17
- export type TMDBFactoryOptions = TMDBClientOptions & {
25
+ export type TMDBFactoryOptions = (TMDBClientOptions & {
18
26
  transport?: TMDBTransport;
19
- };
27
+ }) | TMDBTransportOptions;
20
28
  /**
21
29
  * Main SDK entry point.
22
30
  *
package/dist/client.d.ts CHANGED
@@ -7,16 +7,24 @@ import { PeopleResource } from './resources/people.js';
7
7
  import { SearchResource } from './resources/search.js';
8
8
  import { TrendingResource } from './resources/trending.js';
9
9
  import { TVResource } from './resources/tv.js';
10
+ /**
11
+ * Options accepted when the caller supplies a custom transport.
12
+ *
13
+ * The transport owns authentication, so credentials are not required.
14
+ */
15
+ export type TMDBTransportOptions = Omit<TMDBClientOptions, 'accessToken' | 'apiKey'> & {
16
+ transport: TMDBTransport;
17
+ };
10
18
  /**
11
19
  * Options accepted by {@link createTMDB} and the {@link TMDBClient} constructor.
12
20
  *
13
- * Extends {@link TMDBClientOptions} with an optional {@link TMDBTransport} so
14
- * callers can plug in a custom transport (typically for tests, caching, or
15
- * instrumentation) without having to mock `fetch` or the factory itself.
21
+ * Either provide credentials for the built-in transport, or pass a custom
22
+ * {@link TMDBTransport} (typically for tests, caching, or instrumentation)
23
+ * without credentials.
16
24
  */
17
- export type TMDBFactoryOptions = TMDBClientOptions & {
25
+ export type TMDBFactoryOptions = (TMDBClientOptions & {
18
26
  transport?: TMDBTransport;
19
- };
27
+ }) | TMDBTransportOptions;
20
28
  /**
21
29
  * Main SDK entry point.
22
30
  *
package/dist/errors.d.cts CHANGED
@@ -21,6 +21,17 @@ export declare class TMDBError extends Error {
21
21
  export declare class TMDBRequestError extends TMDBError {
22
22
  constructor(message: string, options?: ErrorOptions);
23
23
  }
24
+ /**
25
+ * Thrown when a request exceeds the timeout supplied to `withTimeout()`.
26
+ *
27
+ * The timeout helper aborts the request's AbortSignal and converts the
28
+ * resulting abort into this error so timeouts are distinguishable from
29
+ * caller-initiated cancellation.
30
+ */
31
+ export declare class TMDBTimeoutError extends TMDBError {
32
+ readonly timeoutMs: number;
33
+ constructor(timeoutMs: number, message?: string);
34
+ }
24
35
  /** Thrown when TMDB returns a non-2xx response. */
25
36
  export declare class TMDBResponseError extends TMDBError {
26
37
  readonly body: JsonValue | undefined;
@@ -52,7 +63,8 @@ export interface TMDBRateLimitErrorOptions extends TMDBResponseErrorOptions {
52
63
  *
53
64
  * The SDK does NOT retry automatically — that decision is left to the
54
65
  * caller, since retry policies vary widely. Inspect `retryAfter` to
55
- * implement your own backoff.
66
+ * implement your own backoff, or use the optional `retry()` / `withRetry()`
67
+ * helpers for a TMDB-aware default.
56
68
  */
57
69
  export declare class TMDBRateLimitError extends TMDBResponseError {
58
70
  readonly retryAfter: number;
package/dist/errors.d.ts CHANGED
@@ -21,6 +21,17 @@ export declare class TMDBError extends Error {
21
21
  export declare class TMDBRequestError extends TMDBError {
22
22
  constructor(message: string, options?: ErrorOptions);
23
23
  }
24
+ /**
25
+ * Thrown when a request exceeds the timeout supplied to `withTimeout()`.
26
+ *
27
+ * The timeout helper aborts the request's AbortSignal and converts the
28
+ * resulting abort into this error so timeouts are distinguishable from
29
+ * caller-initiated cancellation.
30
+ */
31
+ export declare class TMDBTimeoutError extends TMDBError {
32
+ readonly timeoutMs: number;
33
+ constructor(timeoutMs: number, message?: string);
34
+ }
24
35
  /** Thrown when TMDB returns a non-2xx response. */
25
36
  export declare class TMDBResponseError extends TMDBError {
26
37
  readonly body: JsonValue | undefined;
@@ -52,7 +63,8 @@ export interface TMDBRateLimitErrorOptions extends TMDBResponseErrorOptions {
52
63
  *
53
64
  * The SDK does NOT retry automatically — that decision is left to the
54
65
  * caller, since retry policies vary widely. Inspect `retryAfter` to
55
- * implement your own backoff.
66
+ * implement your own backoff, or use the optional `retry()` / `withRetry()`
67
+ * helpers for a TMDB-aware default.
56
68
  */
57
69
  export declare class TMDBRateLimitError extends TMDBResponseError {
58
70
  readonly retryAfter: number;
@@ -0,0 +1,28 @@
1
+ import type { TMDBTransport } from '../http.cjs';
2
+ export interface MemoryCacheOptions {
3
+ /** Entry lifetime in milliseconds. Defaults to 300000 (5 minutes). */
4
+ ttlMs?: number;
5
+ /** Maximum number of cached responses. Defaults to 100. */
6
+ maxEntries?: number;
7
+ }
8
+ export type MemoryCacheTransport<T extends TMDBTransport = TMDBTransport> = T & {
9
+ /** Remove every cached response. */
10
+ clear(): void;
11
+ };
12
+ /**
13
+ * Wrap a transport with a small in-memory LRU cache.
14
+ *
15
+ * Only successful responses are cached. The key includes the path, sorted
16
+ * query parameters, and sorted headers, so language, region, and header
17
+ * variants never collide. Signals are intentionally excluded from the key.
18
+ * Use one cache per client or credential: authentication is not part of the
19
+ * key.
20
+ *
21
+ * ```ts
22
+ * const http = new TMDBHttpClient({ accessToken })
23
+ * const tmdb = createTMDB({
24
+ * transport: withMemoryCache(http, { ttlMs: 60_000, maxEntries: 200 }),
25
+ * })
26
+ * ```
27
+ */
28
+ export declare function withMemoryCache<T extends TMDBTransport>(transport: T, options?: MemoryCacheOptions): MemoryCacheTransport<T>;
@@ -0,0 +1,28 @@
1
+ import type { TMDBTransport } from '../http.js';
2
+ export interface MemoryCacheOptions {
3
+ /** Entry lifetime in milliseconds. Defaults to 300000 (5 minutes). */
4
+ ttlMs?: number;
5
+ /** Maximum number of cached responses. Defaults to 100. */
6
+ maxEntries?: number;
7
+ }
8
+ export type MemoryCacheTransport<T extends TMDBTransport = TMDBTransport> = T & {
9
+ /** Remove every cached response. */
10
+ clear(): void;
11
+ };
12
+ /**
13
+ * Wrap a transport with a small in-memory LRU cache.
14
+ *
15
+ * Only successful responses are cached. The key includes the path, sorted
16
+ * query parameters, and sorted headers, so language, region, and header
17
+ * variants never collide. Signals are intentionally excluded from the key.
18
+ * Use one cache per client or credential: authentication is not part of the
19
+ * key.
20
+ *
21
+ * ```ts
22
+ * const http = new TMDBHttpClient({ accessToken })
23
+ * const tmdb = createTMDB({
24
+ * transport: withMemoryCache(http, { ttlMs: 60_000, maxEntries: 200 }),
25
+ * })
26
+ * ```
27
+ */
28
+ export declare function withMemoryCache<T extends TMDBTransport>(transport: T, options?: MemoryCacheOptions): MemoryCacheTransport<T>;
@@ -0,0 +1,35 @@
1
+ import type { PagedResponse } from '../types.cjs';
2
+ /** Fetches a single page. The caller closes over its own query options. */
3
+ export interface PageFetcher<T> {
4
+ (page: number): Promise<PagedResponse<T>>;
5
+ }
6
+ export interface PaginateOptions {
7
+ /** First page to request. Defaults to 1. */
8
+ startPage?: number;
9
+ /** Last page to request, inclusive. Defaults to 500, TMDB's documented cap. */
10
+ endPage?: number;
11
+ /** Cancels the iteration before the next request. */
12
+ signal?: AbortSignal;
13
+ }
14
+ /**
15
+ * Iterate a paged TMDB endpoint page by page.
16
+ *
17
+ * Stops when the API reports the last page, when a page has no results,
18
+ * when `endPage` is reached, or when the signal is aborted. Yields nothing
19
+ * when `endPage` is lower than `startPage`. The fetcher
20
+ * receives the page number and should forward the signal to the SDK:
21
+ *
22
+ * ```ts
23
+ * for await (const page of paginate((page) => tmdb.movies.popular({ page, signal }))) {
24
+ * console.log(page.page, page.results.length)
25
+ * }
26
+ * ```
27
+ */
28
+ export declare function paginate<T>(fetchPage: PageFetcher<T>, options?: PaginateOptions): AsyncGenerator<PagedResponse<T>, void, undefined>;
29
+ /**
30
+ * Iterate a paged TMDB endpoint item by item.
31
+ *
32
+ * Built on {@link paginate}; use `paginate` directly when you need page
33
+ * metadata such as `total_pages`.
34
+ */
35
+ export declare function paginateItems<T>(fetchPage: PageFetcher<T>, options?: PaginateOptions): AsyncGenerator<T, void, undefined>;
@@ -0,0 +1,35 @@
1
+ import type { PagedResponse } from '../types.js';
2
+ /** Fetches a single page. The caller closes over its own query options. */
3
+ export interface PageFetcher<T> {
4
+ (page: number): Promise<PagedResponse<T>>;
5
+ }
6
+ export interface PaginateOptions {
7
+ /** First page to request. Defaults to 1. */
8
+ startPage?: number;
9
+ /** Last page to request, inclusive. Defaults to 500, TMDB's documented cap. */
10
+ endPage?: number;
11
+ /** Cancels the iteration before the next request. */
12
+ signal?: AbortSignal;
13
+ }
14
+ /**
15
+ * Iterate a paged TMDB endpoint page by page.
16
+ *
17
+ * Stops when the API reports the last page, when a page has no results,
18
+ * when `endPage` is reached, or when the signal is aborted. Yields nothing
19
+ * when `endPage` is lower than `startPage`. The fetcher
20
+ * receives the page number and should forward the signal to the SDK:
21
+ *
22
+ * ```ts
23
+ * for await (const page of paginate((page) => tmdb.movies.popular({ page, signal }))) {
24
+ * console.log(page.page, page.results.length)
25
+ * }
26
+ * ```
27
+ */
28
+ export declare function paginate<T>(fetchPage: PageFetcher<T>, options?: PaginateOptions): AsyncGenerator<PagedResponse<T>, void, undefined>;
29
+ /**
30
+ * Iterate a paged TMDB endpoint item by item.
31
+ *
32
+ * Built on {@link paginate}; use `paginate` directly when you need page
33
+ * metadata such as `total_pages`.
34
+ */
35
+ export declare function paginateItems<T>(fetchPage: PageFetcher<T>, options?: PaginateOptions): AsyncGenerator<T, void, undefined>;
@@ -0,0 +1,47 @@
1
+ import type { TMDBTransport } from '../http.cjs';
2
+ export interface RetryInfo {
3
+ /** Zero-based attempt number that failed. */
4
+ attempt: number;
5
+ /** Delay before the next attempt, in milliseconds. */
6
+ delayMs: number;
7
+ error: unknown;
8
+ }
9
+ export interface RetryOptions {
10
+ /** Retries after the first attempt. Defaults to 2. */
11
+ retries?: number;
12
+ /** Base delay for exponential backoff in milliseconds. Defaults to 250. */
13
+ baseDelayMs?: number;
14
+ /** Maximum exponential backoff delay in milliseconds. Defaults to 10000. */
15
+ maxDelayMs?: number;
16
+ /** Exponential backoff factor. Defaults to 2. */
17
+ factor?: number;
18
+ /** Apply full jitter to exponential delays. Defaults to true. */
19
+ jitter?: boolean;
20
+ /** Cancels the delay and any further attempts. */
21
+ signal?: AbortSignal;
22
+ /** Replaces the default retry predicate. */
23
+ retryOn?: (error: unknown, attempt: number) => boolean;
24
+ /** Observes each retry decision without changing it. */
25
+ onRetry?: (info: RetryInfo) => void;
26
+ }
27
+ /**
28
+ * Retry an async task using TMDB-aware defaults.
29
+ *
30
+ * Retries 429 and any response that carries `Retry-After`, retries 408 and
31
+ * 5xx responses plus network failures with exponential backoff, and never
32
+ * retries other 4xx responses, validation errors, aborts, or timeouts. All
33
+ * TMDB requests are GETs, so the helper is safe for every resource method.
34
+ */
35
+ export declare function retry<T>(task: () => Promise<T>, options?: RetryOptions): Promise<T>;
36
+ /**
37
+ * Wrap a transport so every request uses {@link retry}.
38
+ *
39
+ * ```ts
40
+ * const http = new TMDBHttpClient({ accessToken })
41
+ * const tmdb = createTMDB({ transport: withRetry(http, { retries: 3 }) })
42
+ * ```
43
+ *
44
+ * A wrapper-level `signal` and a per-request `signal` are combined, so
45
+ * aborting either cancels the call. Extra transport members are preserved.
46
+ */
47
+ export declare function withRetry<T extends TMDBTransport>(transport: T, options?: RetryOptions): T;
@@ -0,0 +1,47 @@
1
+ import type { TMDBTransport } from '../http.js';
2
+ export interface RetryInfo {
3
+ /** Zero-based attempt number that failed. */
4
+ attempt: number;
5
+ /** Delay before the next attempt, in milliseconds. */
6
+ delayMs: number;
7
+ error: unknown;
8
+ }
9
+ export interface RetryOptions {
10
+ /** Retries after the first attempt. Defaults to 2. */
11
+ retries?: number;
12
+ /** Base delay for exponential backoff in milliseconds. Defaults to 250. */
13
+ baseDelayMs?: number;
14
+ /** Maximum exponential backoff delay in milliseconds. Defaults to 10000. */
15
+ maxDelayMs?: number;
16
+ /** Exponential backoff factor. Defaults to 2. */
17
+ factor?: number;
18
+ /** Apply full jitter to exponential delays. Defaults to true. */
19
+ jitter?: boolean;
20
+ /** Cancels the delay and any further attempts. */
21
+ signal?: AbortSignal;
22
+ /** Replaces the default retry predicate. */
23
+ retryOn?: (error: unknown, attempt: number) => boolean;
24
+ /** Observes each retry decision without changing it. */
25
+ onRetry?: (info: RetryInfo) => void;
26
+ }
27
+ /**
28
+ * Retry an async task using TMDB-aware defaults.
29
+ *
30
+ * Retries 429 and any response that carries `Retry-After`, retries 408 and
31
+ * 5xx responses plus network failures with exponential backoff, and never
32
+ * retries other 4xx responses, validation errors, aborts, or timeouts. All
33
+ * TMDB requests are GETs, so the helper is safe for every resource method.
34
+ */
35
+ export declare function retry<T>(task: () => Promise<T>, options?: RetryOptions): Promise<T>;
36
+ /**
37
+ * Wrap a transport so every request uses {@link retry}.
38
+ *
39
+ * ```ts
40
+ * const http = new TMDBHttpClient({ accessToken })
41
+ * const tmdb = createTMDB({ transport: withRetry(http, { retries: 3 }) })
42
+ * ```
43
+ *
44
+ * A wrapper-level `signal` and a per-request `signal` are combined, so
45
+ * aborting either cancels the call. Extra transport members are preserved.
46
+ */
47
+ export declare function withRetry<T extends TMDBTransport>(transport: T, options?: RetryOptions): T;
@@ -0,0 +1,20 @@
1
+ export interface TimeoutOptions {
2
+ /** Parent signal. Aborting it cancels the task with the same reason. */
3
+ signal?: AbortSignal;
4
+ /** Custom message for the TMDBTimeoutError. */
5
+ message?: string;
6
+ }
7
+ /**
8
+ * Run a task with an AbortSignal-backed timeout.
9
+ *
10
+ * The task must forward the provided signal to the SDK for cancellation to
11
+ * take effect. Timeouts are reported as {@link TMDBTimeoutError}; aborts from
12
+ * the parent signal keep the parent's reason.
13
+ *
14
+ * ```ts
15
+ * const movie = await withTimeout(5_000, (signal) =>
16
+ * tmdb.movies.details(550, { signal }),
17
+ * )
18
+ * ```
19
+ */
20
+ export declare function withTimeout<T>(timeoutMs: number, task: (signal: AbortSignal) => Promise<T>, options?: TimeoutOptions): Promise<T>;
@@ -0,0 +1,20 @@
1
+ export interface TimeoutOptions {
2
+ /** Parent signal. Aborting it cancels the task with the same reason. */
3
+ signal?: AbortSignal;
4
+ /** Custom message for the TMDBTimeoutError. */
5
+ message?: string;
6
+ }
7
+ /**
8
+ * Run a task with an AbortSignal-backed timeout.
9
+ *
10
+ * The task must forward the provided signal to the SDK for cancellation to
11
+ * take effect. Timeouts are reported as {@link TMDBTimeoutError}; aborts from
12
+ * the parent signal keep the parent's reason.
13
+ *
14
+ * ```ts
15
+ * const movie = await withTimeout(5_000, (signal) =>
16
+ * tmdb.movies.details(550, { signal }),
17
+ * )
18
+ * ```
19
+ */
20
+ export declare function withTimeout<T>(timeoutMs: number, task: (signal: AbortSignal) => Promise<T>, options?: TimeoutOptions): Promise<T>;