import { AxiosError, AxiosInstance, AxiosResponseHeaders } from 'axios'; import { CommentSortByMedia, ListQueryByType, RecommendedPeriod, ReleasesCountry, UpdatedStartDate } from '../trakt'; import { buildUrl } from './buildUrl'; import { TraktHttpError } from './error'; export interface Filters { /** * Search titles and descriptions. * @example batman */ query?: string; /** * 4 digit year or range of years. * @example 2016 */ years?: string; /** * Genre slugs. * @example action * @see {@link Genre.slug | Genre slug} */ genres?: string[]; /** * 2 character language code. * @example en */ languages?: string[]; /** * 2 character country code. * @example us */ countries?: string[]; /** * Range in minutes. * @example 30-90 */ runtimes?: string; /** * Studio slugs. * @example marvel-studios */ studios?: string[]; } /** * Pagination Options */ export interface Pagination { /** * Current page */ page: number; /** * Items per page */ limit: number; } /** * Pagination Response Obj */ export interface PaginationResponse extends Pagination { /** * Total number of pages */ pageCount: number; /** * Total number of items */ itemCount: number; } export interface ApiResponse { /** * Reponse data */ data?: T; /** * Pagination info */ pagination?: PaginationResponse; /** * API response headers * * @remarks * Can be useful for things like cache control, ratelimiting, or general debuging */ headers: AxiosResponseHeaders | Partial & { 'set-cookie'?: string[] | undefined }>; /** * Error object in the event of an error */ error?: TraktHttpError; } export interface FetchOptions { /** * Token to access trakt api */ accessToken?: string; /** * Pagination settings */ pagination?: Pagination; /** * filter options */ filters?: Filters; /** * Period to pull from */ period?: RecommendedPeriod; /** * Start date */ startDate?: UpdatedStartDate; /** * Specify country to look for */ country?: ReleasesCountry; /** * Specify a language */ language?: string; /** * Sorting options * * (This is just the most inclusive type, not always this permissive.) */ sort?: CommentSortByMedia; /** * Types of lists one can query by */ type?: ListQueryByType; } /** * Custom fetch func for calling trakt api * @param client axios instance * @param url trakt api uri * @param accessToken access token for oauth related actions * @returns Specified type or undefined * @internal */ export async function fetch(client: AxiosInstance, url: string, options?: FetchOptions): Promise> { try { const response = await client.get(buildUrl(url, options), { headers: options !== undefined && options.accessToken !== undefined ? { Authorization: `Bearer ${options.accessToken}` } : undefined, // parseJson: (text: string) => Bourne.parse(text), }); const res: ApiResponse = { data: response.data, headers: response.headers, }; if ( response.headers['X-Pagination-Page'] !== undefined && response.headers['X-Pagination-Limit'] !== undefined && response.headers['X-Pagination-Page-Count'] !== undefined && response.headers['X-Pagination-Item-Count'] !== undefined ) { res.pagination = { page: parseInt(response.headers['X-Pagination-Page']), limit: parseInt(response.headers['X-Pagination-Limit']), pageCount: parseInt(response.headers['X-Pagination-Page-Count']), itemCount: parseInt(response.headers['X-Pagination-Item-Count']), }; } return res; } catch (e) { if (e instanceof AxiosError && e.response !== undefined) { // throw new TraktHttpError(e.response.status, e.response.data, e.response.headers); return { error: new TraktHttpError(e.response.status, e.response.data, e.response.headers), headers: e.response.headers, }; } // console.error(e); throw e; } }