Replace querystring with URLSearchParams

URLSearchParams has greater compatibility with browser code

Created new PageOptions and LocaleOptions for easier use
with URLSearchParams
This commit is contained in:
Tobias Karlsson
2023-03-08 14:00:04 +01:00
parent fe86aed01f
commit f8b5564d22
11 changed files with 113 additions and 68 deletions

View File

@@ -1,4 +1,3 @@
import querystring from 'querystring';
import { BaseEndpoint } from './base'; import { BaseEndpoint } from './base';
import { ChangeOptions, Changes } from '../types/changes'; import { ChangeOptions, Changes } from '../types/changes';
@@ -9,18 +8,23 @@ export class ChangeEndpoint extends BaseEndpoint {
} }
async movies(options?: ChangeOptions): Promise<Changes> { async movies(options?: ChangeOptions): Promise<Changes> {
const params = querystring.encode(options); const params = options
? new URLSearchParams(Object.entries(options)).toString()
: '';
return await this.api.get<Changes>(`/movie/changes?${params}`); return await this.api.get<Changes>(`/movie/changes?${params}`);
} }
async tvShows(options?: ChangeOptions): Promise<Changes> { async tvShows(options?: ChangeOptions): Promise<Changes> {
const params = querystring.stringify(options); const params = options
? new URLSearchParams(Object.entries(options)).toString()
: '';
return await this.api.get<Changes>(`/tv/changes?${params}`); return await this.api.get<Changes>(`/tv/changes?${params}`);
} }
async person(options?: ChangeOptions): Promise<Changes> { async person(options?: ChangeOptions): Promise<Changes> {
const params = querystring.stringify(options); const params = options
? new URLSearchParams(Object.entries(options)).toString()
: '';
return await this.api.get<Changes>(`/person/changes${params}`); return await this.api.get<Changes>(`/person/changes${params}`);
} }
} }

View File

@@ -1,10 +1,9 @@
import { MovieDiscoverResult, SortOption, TvShowDiscoverResult } from '../types'; import { MovieDiscoverResult, SortOption, TvShowDiscoverResult } from '../types';
import { BaseEndpoint } from './base'; import { BaseEndpoint } from './base';
import querystring, { ParsedUrlQueryInput } from 'querystring';
const BASE_DISCOVER = '/discover'; const BASE_DISCOVER = '/discover';
interface DiscoverQueryOptions extends ParsedUrlQueryInput{ interface DiscoverQueryOptions {
language?: string; language?: string;
sort_by?: SortOption; sort_by?: SortOption;
page?: number; page?: number;
@@ -66,12 +65,16 @@ export class DiscoverEndpoint extends BaseEndpoint {
} }
async movie(options?: MovieQueryOptions): Promise<MovieDiscoverResult> { async movie(options?: MovieQueryOptions): Promise<MovieDiscoverResult> {
const params = querystring.encode(options); const params = options
? new URLSearchParams(Object.entries(options)).toString()
: '';
return await this.api.get<MovieDiscoverResult>(`${BASE_DISCOVER}/movie?${params}`); return await this.api.get<MovieDiscoverResult>(`${BASE_DISCOVER}/movie?${params}`);
} }
async tvShow(options?: TvShowQueryOptions): Promise<TvShowDiscoverResult> { async tvShow(options?: TvShowQueryOptions): Promise<TvShowDiscoverResult> {
const params = querystring.encode(options); const params = options
? new URLSearchParams(Object.entries(options)).toString()
: '';
return await this.api.get<TvShowDiscoverResult>(`${BASE_DISCOVER}/tv?${params}`); return await this.api.get<TvShowDiscoverResult>(`${BASE_DISCOVER}/tv?${params}`);
} }
} }

View File

@@ -1,5 +1,4 @@
import { BaseEndpoint } from './base'; import { BaseEndpoint } from './base';
import querystring from 'querystring';
import { ExternalIdOptions, FindResult } from '../types'; import { ExternalIdOptions, FindResult } from '../types';
export class FindEndpoint extends BaseEndpoint { export class FindEndpoint extends BaseEndpoint {
@@ -8,7 +7,7 @@ export class FindEndpoint extends BaseEndpoint {
} }
async byId(externalId: string, options: ExternalIdOptions): Promise<FindResult> { async byId(externalId: string, options: ExternalIdOptions): Promise<FindResult> {
const params = querystring.encode(options); const params = new URLSearchParams(Object.entries(options)).toString();
return await this.api.get<FindResult>(`/find/${externalId}?${params}`); return await this.api.get<FindResult>(`/find/${externalId}?${params}`);
} }
} }

View File

@@ -7,10 +7,12 @@ import {
Images, Images,
Keywords, Keywords,
LatestMovie, LatestMovie,
LocaleOptions,
MovieChanges, MovieChanges,
MovieDetails, MovieDetails,
MovieLists, MovieLists,
MoviesPlayingNow, MoviesPlayingNow,
PageOptions,
PopularMovies, PopularMovies,
Recommendations, Recommendations,
ReleaseDates, ReleaseDates,
@@ -21,7 +23,6 @@ import {
Videos, Videos,
WatchProviders, WatchProviders,
} from '../types'; } from '../types';
import querystring from 'querystring';
const BASE_MOVIE = '/movie'; const BASE_MOVIE = '/movie';
@@ -39,7 +40,9 @@ export class MoviesEndpoint extends BaseEndpoint{
} }
async changes(id: number, options?: ChangeOptions): Promise<MovieChanges>{ async changes(id: number, options?: ChangeOptions): Promise<MovieChanges>{
const params = querystring.encode(options); const params = options
? new URLSearchParams(Object.entries(options)).toString()
: '';
return await this.api.get<MovieChanges>(`${BASE_MOVIE}/${id}/changes?${params}`); return await this.api.get<MovieChanges>(`${BASE_MOVIE}/${id}/changes?${params}`);
} }
@@ -59,13 +62,17 @@ export class MoviesEndpoint extends BaseEndpoint{
return await this.api.get<Keywords>(`${BASE_MOVIE}/${id}/keywords`); return await this.api.get<Keywords>(`${BASE_MOVIE}/${id}/keywords`);
} }
async lists(id: number, options?: {page?: number}): Promise<MovieLists>{ async lists(id: number, options?: PageOptions): Promise<MovieLists>{
const params = querystring.encode(options); const params = options
? new URLSearchParams(Object.entries(options)).toString()
: '';
return await this.api.get<MovieLists>(`${BASE_MOVIE}/${id}/lists?${params}`); return await this.api.get<MovieLists>(`${BASE_MOVIE}/${id}/lists?${params}`);
} }
async recommendations(id: number, options?: {page?: number}): Promise<Recommendations>{ async recommendations(id: number, options?: PageOptions): Promise<Recommendations>{
const params = querystring.encode(options); const params = options
? new URLSearchParams(Object.entries(options)).toString()
: '';
return await this.api.get<Recommendations>(`${BASE_MOVIE}/${id}/recommendations?${params}`); return await this.api.get<Recommendations>(`${BASE_MOVIE}/${id}/recommendations?${params}`);
} }
@@ -73,13 +80,17 @@ export class MoviesEndpoint extends BaseEndpoint{
return await this.api.get<ReleaseDates>(`${BASE_MOVIE}/${id}/release_dates`); return await this.api.get<ReleaseDates>(`${BASE_MOVIE}/${id}/release_dates`);
} }
async reviews(id: number, options?: {page?: number}): Promise<Reviews>{ async reviews(id: number, options?: PageOptions): Promise<Reviews>{
const params = querystring.encode(options); const params = options
? new URLSearchParams(Object.entries(options)).toString()
: '';
return await this.api.get<Reviews>(`${BASE_MOVIE}/${id}/reviews?${params}`); return await this.api.get<Reviews>(`${BASE_MOVIE}/${id}/reviews?${params}`);
} }
async similar(id: number, options?: {page?: number}): Promise<SimilarMovies>{ async similar(id: number, options?: PageOptions): Promise<SimilarMovies>{
const params = querystring.encode(options); const params = options
? new URLSearchParams(Object.entries(options)).toString()
: '';
return await this.api.get<SimilarMovies>(`${BASE_MOVIE}/${id}/similar?${params}`); return await this.api.get<SimilarMovies>(`${BASE_MOVIE}/${id}/similar?${params}`);
} }
@@ -103,23 +114,31 @@ export class MoviesEndpoint extends BaseEndpoint{
return await this.api.get<LatestMovie>(`${BASE_MOVIE}/latest`); return await this.api.get<LatestMovie>(`${BASE_MOVIE}/latest`);
} }
async nowPlaying(options?: {page?: number, region?: string, language?: string}): Promise<MoviesPlayingNow>{ async nowPlaying(options?: LocaleOptions): Promise<MoviesPlayingNow>{
const params = querystring.encode(options); const params = options
? new URLSearchParams(Object.entries(options)).toString()
: '';
return await this.api.get<MoviesPlayingNow>(`${BASE_MOVIE}/now_playing?${params}`); return await this.api.get<MoviesPlayingNow>(`${BASE_MOVIE}/now_playing?${params}`);
} }
async popular(options?: {page?: number}): Promise<PopularMovies>{ async popular(options?: PageOptions): Promise<PopularMovies>{
const params = querystring.encode(options); const params = options
? new URLSearchParams(Object.entries(options)).toString()
: '';
return await this.api.get<PopularMovies>(`${BASE_MOVIE}/popular?${params}`); return await this.api.get<PopularMovies>(`${BASE_MOVIE}/popular?${params}`);
} }
async topRated(options?: {page?: number, region?: string, language?: string}): Promise<TopRatedMovies>{ async topRated(options?: LocaleOptions): Promise<TopRatedMovies>{
const params = querystring.encode(options); const params = options
? new URLSearchParams(Object.entries(options)).toString()
: '';
return await this.api.get<TopRatedMovies>(`${BASE_MOVIE}/top_rated?${params}`); return await this.api.get<TopRatedMovies>(`${BASE_MOVIE}/top_rated?${params}`);
} }
async upcoming(options?: {page?: number, region?: string, language?: string}): Promise<UpcomingMovies>{ async upcoming(options?: LocaleOptions): Promise<UpcomingMovies>{
const params = querystring.encode(options); const params = options
? new URLSearchParams(Object.entries(options)).toString()
: '';
return await this.api.get<UpcomingMovies>(`${BASE_MOVIE}/upcoming?${params}`); return await this.api.get<UpcomingMovies>(`${BASE_MOVIE}/upcoming?${params}`);
} }
} }

View File

@@ -1,10 +1,8 @@
import { ChangeOptions, ExternalIds, Image, PeopleTranslations, PersonChanges, PersonCombinedCredits, PersonDetail, PersonMovieCredit, PersonTvShowCredit, PopularPersons, TaggedImages } from '../types'; import { ChangeOptions, ExternalIds, Image, PageOptions, PeopleTranslations, PersonChanges, PersonCombinedCredits, PersonDetail, PersonMovieCredit, PersonTvShowCredit, PopularPersons, TaggedImages } from '../types';
import { BaseEndpoint } from './base'; import { BaseEndpoint } from './base';
import querystring from 'querystring';
const BASE_PERSON = '/person'; const BASE_PERSON = '/person';
export class PeopleEndpoint extends BaseEndpoint { export class PeopleEndpoint extends BaseEndpoint {
constructor(accessToken: string) { constructor(accessToken: string) {
super(accessToken); super(accessToken);
@@ -15,7 +13,9 @@ export class PeopleEndpoint extends BaseEndpoint {
} }
async changes(id: number, options? : ChangeOptions): Promise<PersonChanges> { async changes(id: number, options? : ChangeOptions): Promise<PersonChanges> {
const params = querystring.encode(options); const params = options == undefined
? undefined
: new URLSearchParams(Object.entries(options)).toString();
return await this.api.get<PersonChanges>(`${BASE_PERSON}/${id}/changes?${params}`); return await this.api.get<PersonChanges>(`${BASE_PERSON}/${id}/changes?${params}`);
} }
@@ -39,8 +39,10 @@ export class PeopleEndpoint extends BaseEndpoint {
return await this.api.get<{id: number, profiles: Image[]}>(`${BASE_PERSON}/${id}/images`) return await this.api.get<{id: number, profiles: Image[]}>(`${BASE_PERSON}/${id}/images`)
} }
async taggedImages(id: number, options?: {page?: number}): Promise<TaggedImages>{ async taggedImages(id: number, options?: PageOptions): Promise<TaggedImages>{
const params = querystring.encode(options); const params = options == undefined
? undefined
: new URLSearchParams(Object.entries(options)).toString();
return await this.api.get<TaggedImages>(`${BASE_PERSON}/${id}/tagged_images?${params}`); return await this.api.get<TaggedImages>(`${BASE_PERSON}/${id}/tagged_images?${params}`);
} }
@@ -52,8 +54,10 @@ export class PeopleEndpoint extends BaseEndpoint {
return await this.api.get<PersonDetail>(`${BASE_PERSON}/latest`); return await this.api.get<PersonDetail>(`${BASE_PERSON}/latest`);
} }
async popular(options?: {page?: number}): Promise<PopularPersons>{ async popular(options?: PageOptions): Promise<PopularPersons>{
const params = querystring.encode(options); const params = options == undefined
? undefined
: new URLSearchParams(Object.entries(options)).toString();
return await this.api.get<PopularPersons>(`${BASE_PERSON}/popular?${params}`); return await this.api.get<PopularPersons>(`${BASE_PERSON}/popular?${params}`);
} }
} }

View File

@@ -1,11 +1,10 @@
import { BaseEndpoint } from './base'; import { BaseEndpoint } from './base';
import querystring, { ParsedUrlQueryInput } from 'querystring';
import { Search } from '../types/search'; import { Search } from '../types/search';
import { Collection, Company, Movie, Person, TV } from '../types'; import { Collection, Company, Movie, Person, TV } from '../types';
const BASE_SEARCH = '/search'; const BASE_SEARCH = '/search';
export interface SearchOptions extends ParsedUrlQueryInput { export interface SearchOptions {
query: string; query: string;
page?: number; page?: number;
} }
@@ -31,35 +30,34 @@ export class SearchEndpoint extends BaseEndpoint {
} }
async companies(options: SearchOptions): Promise<Search<Company>>{ async companies(options: SearchOptions): Promise<Search<Company>>{
const params = querystring.encode(options); const params = new URLSearchParams(Object.entries(options)).toString();
return await this.api.get<Search<Company>>(`${BASE_SEARCH}/company?${params}`); return await this.api.get<Search<Company>>(`${BASE_SEARCH}/company?${params}`);
} }
async collections(options: SearchOptions): Promise<Search<Collection>>{ async collections(options: SearchOptions): Promise<Search<Collection>>{
const params = querystring.encode(options); const params = new URLSearchParams(Object.entries(options)).toString();
return await this.api.get<Search<Collection>>(`${BASE_SEARCH}/collection?${params}`); return await this.api.get<Search<Collection>>(`${BASE_SEARCH}/collection?${params}`);
} }
async keywords(options: SearchOptions): Promise<Search<{ id: string, name: string }>>{ async keywords(options: SearchOptions): Promise<Search<{ id: string, name: string }>>{
const params = querystring.encode(options); const params = new URLSearchParams(Object.entries(options)).toString();
return await this.api.get<Search<{ id: string, name: string }>>(`${BASE_SEARCH}/keyword?${params}`); return await this.api.get<Search<{ id: string, name: string }>>(`${BASE_SEARCH}/keyword?${params}`);
} }
async movies(options: MovieSearchOptions): Promise<Search<Movie>>{ async movies(options: MovieSearchOptions): Promise<Search<Movie>>{
const params = querystring.encode(options); const params = new URLSearchParams(Object.entries(options)).toString();
return await this.api.get<Search<Movie>>(`${BASE_SEARCH}/movie?${params}`); return await this.api.get<Search<Movie>>(`${BASE_SEARCH}/movie?${params}`);
} }
async people(options: PeopleSearchOptions): Promise<Search<Person>>{ async people(options: PeopleSearchOptions): Promise<Search<Person>>{
const params = querystring.encode(options); const params = new URLSearchParams(Object.entries(options)).toString();
return await this.api.get<Search<Person>>(`${BASE_SEARCH}/person?${params}`); return await this.api.get<Search<Person>>(`${BASE_SEARCH}/person?${params}`);
} }
// TODO: Multi search // TODO: Multi search
async tvShows(options: TvSearchOptions): Promise<Search<TV>>{ async tvShows(options: TvSearchOptions): Promise<Search<TV>>{
const params = querystring.encode(options); const params = new URLSearchParams(Object.entries(options)).toString();
return await this.api.get<Search<TV>>(`${BASE_SEARCH}/tv?${params}`); return await this.api.get<Search<TV>>(`${BASE_SEARCH}/tv?${params}`);
} }
} }

View File

@@ -9,7 +9,9 @@ import {
Images, Images,
Keywords, Keywords,
LatestTvShows, LatestTvShows,
LocaleOptions,
OnTheAir, OnTheAir,
PageOptions,
PopularTvShows, PopularTvShows,
Recommendations, Recommendations,
Reviews, Reviews,
@@ -24,7 +26,6 @@ import {
Videos, Videos,
WatchProviders, WatchProviders,
} from '../types'; } from '../types';
import querystring from 'querystring';
const BASE_TV = '/tv'; const BASE_TV = '/tv';
@@ -42,7 +43,9 @@ export class TvShowsEndpoint extends BaseEndpoint{
} }
async changes(id: number, options?: ChangeOptions): Promise<TvShowChanges>{ async changes(id: number, options?: ChangeOptions): Promise<TvShowChanges>{
const params = querystring.encode(options); const params = options == undefined
? undefined
: new URLSearchParams(Object.entries(options)).toString();
return await this.api.get<TvShowChanges>(`${BASE_TV}/${id}/changes?${params}`); return await this.api.get<TvShowChanges>(`${BASE_TV}/${id}/changes?${params}`);
} }
@@ -74,13 +77,17 @@ export class TvShowsEndpoint extends BaseEndpoint{
return await this.api.get<Keywords>(`${BASE_TV}/${id}/keywords`); return await this.api.get<Keywords>(`${BASE_TV}/${id}/keywords`);
} }
async recommendations(id: number, options?: {page?: number}): Promise<Recommendations>{ async recommendations(id: number, options?: PageOptions): Promise<Recommendations>{
const params = querystring.encode(options); const params = options == undefined
? undefined
: new URLSearchParams(Object.entries(options)).toString();
return await this.api.get<Recommendations>(`${BASE_TV}/${id}/recommendations?${params}`); return await this.api.get<Recommendations>(`${BASE_TV}/${id}/recommendations?${params}`);
} }
async reviews(id: number, options?: {page?: number}): Promise<Reviews>{ async reviews(id: number, options?: PageOptions): Promise<Reviews>{
const params = querystring.encode(options); const params = options == undefined
? undefined
: new URLSearchParams(Object.entries(options)).toString();
return await this.api.get<Reviews>(`${BASE_TV}/${id}/reviews?${params}`); return await this.api.get<Reviews>(`${BASE_TV}/${id}/reviews?${params}`);
} }
@@ -88,8 +95,10 @@ export class TvShowsEndpoint extends BaseEndpoint{
return await this.api.get<ScreenedTheatrically>(`${BASE_TV}/${id}/screened_theatrically`); return await this.api.get<ScreenedTheatrically>(`${BASE_TV}/${id}/screened_theatrically`);
} }
async similar(id: number, options?: {page?: number}): Promise<SimilarTvShows>{ async similar(id: number, options?: PageOptions): Promise<SimilarTvShows>{
const params = querystring.encode(options); const params = options == undefined
? undefined
: new URLSearchParams(Object.entries(options)).toString();
return await this.api.get<SimilarTvShows>(`${BASE_TV}/${id}/similar?${params}`); return await this.api.get<SimilarTvShows>(`${BASE_TV}/${id}/similar?${params}`);
} }
@@ -117,21 +126,24 @@ export class TvShowsEndpoint extends BaseEndpoint{
return await this.api.get<OnTheAir>(`${BASE_TV}/on_the_air`); return await this.api.get<OnTheAir>(`${BASE_TV}/on_the_air`);
} }
async airingToday(options?: {page?: number, region?: string, language?: string}): Promise<TvShowsAiringToday>{ async airingToday(options?: LocaleOptions): Promise<TvShowsAiringToday>{
const params = querystring.encode(options); const params = options == undefined
? undefined
: new URLSearchParams(Object.entries(options)).toString();
return await this.api.get<TvShowsAiringToday>(`${BASE_TV}/airing_today?${params}`); return await this.api.get<TvShowsAiringToday>(`${BASE_TV}/airing_today?${params}`);
} }
async popular(options?: {page?: number}): Promise<PopularTvShows>{ async popular(options?: PageOptions): Promise<PopularTvShows>{
const params = querystring.encode(options); const params = options == undefined
? undefined
: new URLSearchParams(Object.entries(options)).toString();
return await this.api.get<PopularTvShows>(`${BASE_TV}/popular?${params}`); return await this.api.get<PopularTvShows>(`${BASE_TV}/popular?${params}`);
} }
async topRated(options?: {page?: number, region?: string, language?: string}): Promise<TopRatedTvShows>{ async topRated(options?: LocaleOptions): Promise<TopRatedTvShows>{
const params = querystring.encode(options); const params = options == undefined
? undefined
: new URLSearchParams(Object.entries(options)).toString();
return await this.api.get<TopRatedTvShows>(`${BASE_TV}/top_rated?${params}`); return await this.api.get<TopRatedTvShows>(`${BASE_TV}/top_rated?${params}`);
} }
} }

View File

@@ -1,5 +1,3 @@
import { ParsedUrlQueryInput } from 'querystring';
export interface Change { export interface Change {
id: number; id: number;
adult: boolean | undefined; adult: boolean | undefined;
@@ -12,7 +10,7 @@ export interface Changes{
total_results: number; total_results: number;
} }
export interface ChangeOptions extends ParsedUrlQueryInput { export interface ChangeOptions {
end_date?: string; end_date?: string;
start_date?: string; start_date?: string;
page?: number; page?: number;

View File

@@ -1,4 +1,3 @@
import { ParsedUrlQueryInput } from 'querystring';
import { Episode, Media, MediaType, Movie, Person, Season, TV } from '.'; import { Episode, Media, MediaType, Movie, Person, Season, TV } from '.';
export type ExternalSource = export type ExternalSource =
@@ -11,7 +10,7 @@ export type ExternalSource =
| 'twitter_id' | 'twitter_id'
| 'instagram_id'; | 'instagram_id';
export interface ExternalIdOptions extends ParsedUrlQueryInput { export interface ExternalIdOptions {
external_source: ExternalSource; external_source: ExternalSource;
language?: string; language?: string;
} }

View File

@@ -6,6 +6,7 @@ export * from './movies';
export * from './search'; export * from './search';
export * from './tv-shows'; export * from './tv-shows';
export * from './watch-providers'; export * from './watch-providers';
export * from './page';
export * from './people'; export * from './people';
export * from './discover'; export * from './discover';
export * from './review'; export * from './review';

8
src/types/page.ts Normal file
View File

@@ -0,0 +1,8 @@
export interface PageOptions {
page?: number;
}
export interface LocaleOptions extends PageOptions {
region?: string;
language?: string;
}