Skip to content

Commit

Permalink
Typesafe append_to_response
Browse files Browse the repository at this point in the history
  • Loading branch information
JorrinKievit committed Aug 17, 2023
1 parent 67239ae commit c713673
Show file tree
Hide file tree
Showing 48 changed files with 603 additions and 1,336 deletions.
3 changes: 3 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"printWidth": 200
}
10 changes: 7 additions & 3 deletions apps/node-demo/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ import { TMDBNodeApi } from "tmdb-js-node";

const tmdbApi = new TMDBNodeApi("YOUR_API_KEY");

tmdbApi.v3.trending.getTrending("movie", "day").then((response) => {
console.log("GREAT SUCCESS", response.results.length);
});
tmdbApi.v3.movies
.getDetails(550, {
append_to_response: ["images", "videos"],
})
.then((response) => {
console.log(response.videos);
});
1 change: 0 additions & 1 deletion apps/web-demo/public/vite.svg

This file was deleted.

2 changes: 1 addition & 1 deletion apps/web-demo/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ function App() {
useEffect(() => {
const tmdbApi = new TMDBWebAPI("YOUR_API_KEY");
tmdbApi.v3.trending.getTrending("all", "day").then((res) => {
console.log(res)
console.log(res);
});
}, []);

Expand Down
12 changes: 6 additions & 6 deletions apps/web-demo/src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import './index.css'
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import "./index.css";

ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
<React.StrictMode>
<App />
</React.StrictMode>,
)
);
678 changes: 138 additions & 540 deletions packages/core/src/index.ts

Large diffs are not rendered by default.

191 changes: 191 additions & 0 deletions packages/core/src/types/append-to-response.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
import {
MoviesGetAccountStatesResponse,
MoviesGetAlternativeTitlesResponse,
MoviesGetChangesResponse,
MoviesGetCreditsResponse,
MoviesGetExternalIdsResponse,
MoviesGetImagesResponse,
MoviesGetKeywordsResponse,
MoviesGetLatestResponse,
MoviesGetListsResponse,
MoviesGetRecommendationsResponse,
MoviesGetReleaseDatesResponse,
MoviesGetReviewsResponse,
MoviesGetSimilarMoviesResponse,
MoviesGetTranslationsResponse,
MoviesGetVideosResponse,
MoviesGetWatchProvidersResponse,
PeopleGetChangesResponse,
PeopleGetCombinedCreditsResponse,
PeopleGetExternalIdsResponse,
PeopleGetImagesResponse,
PeopleGetLatestResponse,
PeopleGetMovieCreditsResponse,
PeopleGetTranslationsResponse,
TVGetAccountStatesResponse,
TVGetAggregateCreditsResponse,
TVGetAlternativeTitlesResponse,
TVGetChangesResponse,
TVGetContentRatingsResponse,
TVGetCreditsResponse,
TVGetEpisodeGroupsResponse,
TVGetExternalIdsResponse,
TVGetImagesResponse,
TVGetKeywordsResponse,
TVGetLatestResponse,
TVGetRecommendationsResponse,
TVGetReviewsResponse,
TVGetScreenedTheatricallyResponse,
TVGetSimilarTVShowsResponse,
TVGetTranslationsResponse,
TVGetVideosResponse,
TVGetWatchProvidersResponse,
TVSeasonsGetAccountStatesResponse,
TVSeasonsGetAggregateCreditsResponse,
TVSeasonsGetChangesResponse,
TVSeasonsGetCreditsResponse,
TVSeasonsGetImagesResponse,
TVSeasonsGetTranslationsResponse,
TVSeasonsGetVideosResponse,
TVEpisodesGetAccountStatesResponse,
TVEpisodesGetChangesResponse,
TVEpisodesGetCreditsResponse,
TVEpisodesGetImagesResponse,
TVEpisodesGetTranslationsResponse,
TVEpisodesGetVideosResponse,
} from "./v3";

export type MoviesAppendToResponse =
| "account_states"
| "alternative_titles"
| "changes"
| "credits"
| "external_ids"
| "images"
| "keywords"
| "latest"
| "lists"
| "recommendations"
| "release_dates"
| "reviews"
| "similar"
| "translations"
| "videos"
| "watch_providers";
export interface MoviesAppendToResponseTypes {
account_states: MoviesGetAccountStatesResponse;
alternative_titles: MoviesGetAlternativeTitlesResponse;
changes: MoviesGetChangesResponse;
credits: MoviesGetCreditsResponse;
external_ids: MoviesGetExternalIdsResponse;
images: MoviesGetImagesResponse;
keywords: MoviesGetKeywordsResponse;
latest: MoviesGetLatestResponse;
lists: MoviesGetListsResponse;
recommendations: MoviesGetRecommendationsResponse;
release_dates: MoviesGetReleaseDatesResponse;
reviews: MoviesGetReviewsResponse;
similar: MoviesGetSimilarMoviesResponse;
translations: MoviesGetTranslationsResponse;
videos: MoviesGetVideosResponse;
watch_providers: MoviesGetWatchProvidersResponse;
}

export type PeopleAppendToResponse = "changes" | "combined_credits" | "external_ids" | "images" | "latest" | "movie_credits" | "tv_credits" | "translations";
export interface PeopleAppendToResponseTypes {
changes: PeopleGetChangesResponse;
combined_credits: PeopleGetCombinedCreditsResponse;
external_ids: PeopleGetExternalIdsResponse;
images: PeopleGetImagesResponse;
latest: PeopleGetLatestResponse;
movie_credits: PeopleGetMovieCreditsResponse;
tv_credits: TVGetCreditsResponse;
translations: PeopleGetTranslationsResponse;
}

export type TVAppendToResponse =
| "account_states"
| "aggregate_credits"
| "alternative_titles"
| "changes"
| "content_ratings"
| "credits"
| "episode_groups"
| "external_ids"
| "images"
| "keywords"
| "latest"
| "recommendations"
| "reviews"
| "screened_theatrically"
| "similar"
| "translations"
| "videos";
export interface TVAppendToResponseTypes {
account_states: TVGetAccountStatesResponse;
aggregate_credits: TVGetAggregateCreditsResponse;
alternative_titles: TVGetAlternativeTitlesResponse;
changes: TVGetChangesResponse;
content_ratings: TVGetContentRatingsResponse;
credits: TVGetCreditsResponse;
episode_groups: TVGetEpisodeGroupsResponse;
external_ids: TVGetExternalIdsResponse;
images: TVGetImagesResponse;
keywords: TVGetKeywordsResponse;
latest: TVGetLatestResponse;
recommendations: TVGetRecommendationsResponse;
reviews: TVGetReviewsResponse;
screened_theatrically: TVGetScreenedTheatricallyResponse;
similar: TVGetSimilarTVShowsResponse;
translations: TVGetTranslationsResponse;
videos: TVGetVideosResponse;
watch_providers: TVGetWatchProvidersResponse;
}

export type TVSeasonsAppendToResponse = "account_states" | "aggregate_credits" | "changes" | "credits" | "external_ids" | "images" | "translations" | "videos" | "watch_providers";
export interface TVSeasonsAppendToResponseTypes {
account_states: TVSeasonsGetAccountStatesResponse;
aggregate_credits: TVSeasonsGetAggregateCreditsResponse;
changes: TVSeasonsGetChangesResponse;
credits: TVSeasonsGetCreditsResponse;
external_ids: TVGetExternalIdsResponse;
images: TVSeasonsGetImagesResponse;
translations: TVSeasonsGetTranslationsResponse;
videos: TVSeasonsGetVideosResponse;
watch_providers: TVGetWatchProvidersResponse;
}

export type TVEpisodesAppendToResponse = "account_states" | "changes" | "credits" | "external_ids" | "images" | "translations" | "videos";
export interface TVEpisodesAppendToResponseTypes {
account_states: TVEpisodesGetAccountStatesResponse;
changes: TVEpisodesGetChangesResponse;
credits: TVEpisodesGetCreditsResponse;
external_ids: TVGetExternalIdsResponse;
images: TVEpisodesGetImagesResponse;
translations: TVEpisodesGetTranslationsResponse;
videos: TVEpisodesGetVideosResponse;
}

type ResponseTypeFor<T> = T extends keyof MoviesAppendToResponseTypes
? MoviesAppendToResponseTypes[T]
: T extends keyof TVAppendToResponseTypes
? TVAppendToResponseTypes[T]
: T extends keyof PeopleAppendToResponseTypes
? PeopleAppendToResponseTypes[T]
: T extends keyof TVSeasonsAppendToResponseTypes
? TVSeasonsAppendToResponseTypes[T]
: T extends keyof TVEpisodesAppendToResponseTypes
? TVEpisodesAppendToResponseTypes[T]
: never;

type ExtractValidKeys<T> = T extends (infer U)[] ? U : never;

export type AppendToResponseType<
AppendToResponse extends (MoviesAppendToResponse | TVAppendToResponse | PeopleAppendToResponse | TVSeasonsAppendToResponse | TVEpisodesAppendToResponse)[] | undefined,
> = AppendToResponse extends undefined
? Record<string, never>
: {
[K in ExtractValidKeys<AppendToResponse> & keyof MoviesAppendToResponseTypes]: MoviesAppendToResponseTypes[K];
} & {
[K in ExtractValidKeys<AppendToResponse>]: ResponseTypeFor<K>;
};
1 change: 1 addition & 0 deletions packages/core/src/types/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from "./v3";
export * from "./v4";
export * from "./error";
export * from "./append-to-response";
12 changes: 8 additions & 4 deletions packages/core/src/types/v3/movies/get-details.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export interface MoviesGetDetailsResponse {
import { AppendToResponseType, MoviesAppendToResponse } from "../../append-to-response";

export type MoviesGetDetailsResponse = {
adult: boolean;
backdrop_path: string;
belongs_to_collection: null;
Expand All @@ -24,7 +26,7 @@ export interface MoviesGetDetailsResponse {
video: boolean;
vote_average: number;
vote_count: number;
}
};

export interface MoviesGetDetailsGenre {
id: number;
Expand All @@ -48,7 +50,9 @@ export interface MoviesGetDetailsSpokenLanguage {
name: string;
}

export interface MoviesGetDetailsParams {
export interface MoviesGetDetailsParams<T extends MoviesAppendToResponse[]> {
language?: string;
append_to_response?: string;
append_to_response?: T;
}

export type GetDetailsResponse<AppendToResponse extends MoviesAppendToResponse[] | undefined> = MoviesGetDetailsResponse & AppendToResponseType<AppendToResponse>;
6 changes: 4 additions & 2 deletions packages/core/src/types/v3/people/get-details.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { PeopleAppendToResponse } from "../../append-to-response";

export interface PeopleGetDetailsResponse {
birthday: string;
known_for_department: string;
Expand All @@ -15,7 +17,7 @@ export interface PeopleGetDetailsResponse {
homepage: null;
}

export interface PeopleGetDetailsParams {
export interface PeopleGetDetailsParams<T extends PeopleAppendToResponse[]> {
language?: string;
append_to_response?: string;
append_to_response?: T;
}
2 changes: 1 addition & 1 deletion packages/core/src/types/v3/trending/get-trending.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,4 @@ export interface TrendingGetTrendingResult {
export interface TrendingGetTrendingParams {
media_type: "all" | "movie" | "tv" | "person";
time_window: "day" | "week";
}
}
6 changes: 4 additions & 2 deletions packages/core/src/types/v3/tv-episodes/get-details.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { TVEpisodesAppendToResponse } from "../../append-to-response";

export interface TVEpisodesGetDetailsResponse {
air_date: string;
crew: TVEpisodesGetDetailsCrew[];
Expand Down Expand Up @@ -31,7 +33,7 @@ export interface TVEpisodesGetDetailsGuestStar {
profile_path: string;
}

export interface TVEpisodesGetDetailsParams {
export interface TVEpisodesGetDetailsParams<T extends TVEpisodesAppendToResponse[]> {
language?: string;
append_to_response?: string;
append_to_response?: T;
}
6 changes: 4 additions & 2 deletions packages/core/src/types/v3/tv-seasons/get-details.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { TVSeasonsAppendToResponse } from "../../append-to-response";

export interface TVSeasonsGetDetailsResponse {
_id: string;
air_date: string;
Expand Down Expand Up @@ -40,7 +42,7 @@ export interface TVSeasonsGetDetailsCrew {
character?: string;
}

export interface TVSeasonsGetDetailsParams {
export interface TVSeasonsGetDetailsParams<T extends TVSeasonsAppendToResponse[]> {
language?: string;
append_to_response?: string;
append_to_response?: T;
}
6 changes: 4 additions & 2 deletions packages/core/src/types/v3/tv/get-details.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { TVAppendToResponse } from "../../append-to-response";

export interface TVGetDetailsResponse {
backdrop_path: string;
created_by: TVGetDetailsCreatedBy[];
Expand Down Expand Up @@ -86,7 +88,7 @@ export interface TVGetDetailsSpokenLanguage {
name: string;
}

export interface TVGetDetailsParams {
export interface TVGetDetailsParams<T extends TVAppendToResponse[]> {
language?: string;
append_to_response?: string;
append_to_response?: T;
}
5 changes: 1 addition & 4 deletions packages/core/src/types/v3/tv/get-watch-providers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@ export interface TVGetWatchProvidersResponse {
}

export interface TVGetWatchProvidersResults {
[key: string]:
| TVGetWatchProvidersAr
| TVGetWatchProvidersAt
| TVGetWatchProvidersRu;
[key: string]: TVGetWatchProvidersAr | TVGetWatchProvidersAt | TVGetWatchProvidersRu;
}

export interface TVGetWatchProvidersAr {
Expand Down
22 changes: 12 additions & 10 deletions packages/core/src/utils/api.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
export const buildV3Url = <TParams>(
apiKey: string,
url: string,
params?: TParams
) => {
export const buildV3Url = <TParams>(apiKey: string, url: string, params?: TParams) => {
const searchParams = new URLSearchParams();
if (params) {
for (const [key, value] of Object.entries(params)) {
searchParams.append(key, value as string);
if (Array.isArray(value)) {
searchParams.append(key, value.join(","));
} else {
searchParams.append(key, value as string);
}
}
}
const urlEndpoint = `${url}?api_key=${apiKey}${
params ? `&${searchParams.toString()}` : ""
}`;
const urlEndpoint = `${url}?api_key=${apiKey}${params ? `&${searchParams.toString()}` : ""}`;
return urlEndpoint;
};

export const buildV4Url = <TParams>(url: string, params?: TParams) => {
const searchParams = new URLSearchParams();
if (params) {
for (const [key, value] of Object.entries(params)) {
searchParams.append(key, value as string);
if (Array.isArray(value)) {
searchParams.append(key, value.join(","));
} else {
searchParams.append(key, value as string);
}
}
}
const urlEndpoint = `${url}${params ? `?${searchParams.toString()}` : ""}`;
Expand Down
Loading

0 comments on commit c713673

Please sign in to comment.