2025-02-23

2025-02-24
This commit is contained in:
gcch 2025-02-23 16:09:48 +01:00
commit 0f52ff0cef
40 changed files with 846 additions and 75 deletions

30
src/libs/apis/clients.ts Normal file
View file

@ -0,0 +1,30 @@
import type { Input } from "@effect/platform/UrlParams";
import { FetchHttpClient, HttpClient, HttpClientRequest, Url, UrlParams } from "@effect/platform";
import { Effect, pipe } from "effect";
export const DebugHttpClient = pipe(
HttpClient.HttpClient,
Effect.andThen(HttpClient.tapRequest(Effect.logDebug)),
Effect.andThen(HttpClient.tap(Effect.logDebug)),
Effect.andThen(HttpClient.filterStatusOk),
HttpClient.withTracerPropagation(false),
Effect.provide(FetchHttpClient.layer),
);
export const createUrlWithParams = (stringUrl: string) => (params: Input) =>
Effect.gen(function*() {
const url = yield* Url.fromString(stringUrl);
const urlParams = UrlParams.fromInput(params);
return Url.setUrlParams(url, urlParams);
});
export const createGetHttpRequest = (url: URL): HttpClientRequest.HttpClientRequest =>
pipe(
HttpClientRequest.get(url),
HttpClientRequest.bearerToken(import.meta.env["VITE_TMDB_API_KEY"]),
HttpClientRequest.acceptJson,
);
export const executeHttpRequest = (request: HttpClientRequest.HttpClientRequest) =>
Effect.andThen(DebugHttpClient, client => client.execute(request));

23
src/libs/apis/requests.ts Normal file
View file

@ -0,0 +1,23 @@
import { HttpClient, HttpClientResponse } from "@effect/platform";
import { Effect, pipe } from "effect";
import { createGetHttpRequest, createUrlWithParams, DebugHttpClient } from "./clients";
import { TMDB_ROUTE_SEARCH_MOVIE } from "./routes";
import { TmdbMovieSearchQueryParams, TmdbMovieSearchResponse } from "./tmdb/schemas";
export const TmdbSearchMovie = (queryParams: TmdbMovieSearchQueryParams) =>
pipe(
Effect.gen(function*() {
const { ...args } = queryParams;
const client = yield* DebugHttpClient;
return pipe(
createUrlWithParams(TMDB_ROUTE_SEARCH_MOVIE)(args),
Effect.andThen(url => createGetHttpRequest(url)),
Effect.andThen(request => client.execute(request)),
// NOTE: Essentiel à désactiver pour des APIs externes
HttpClient.withTracerPropagation(false),
Effect.andThen(response => HttpClientResponse.schemaBodyJson(TmdbMovieSearchResponse)(response)),
);
}),
);

1
src/libs/apis/routes.ts Normal file
View file

@ -0,0 +1 @@
export const TMDB_ROUTE_SEARCH_MOVIE = "https://api.themoviedb.org/3/search/movie";

View file

@ -0,0 +1,9 @@
import type { TmdbMovieSearchQueryParams } from "./schemas";
export const DEFAULT_SEARCH_MOVIE_PARAMS: TmdbMovieSearchQueryParams = {
include_adult: false,
language: "fr",
page: 1,
query: "",
region: "fr-FR",
};

View file

@ -13,13 +13,13 @@ export class TmdbMovieSearchQueryParams extends Schema.Class<TmdbMovieSearchQuer
Schema.propertySignature,
Schema.withConstructorDefault(() => 1),
),
primary_release_year: Schema.NonEmptyString.pipe(Schema.length(4), Schema.optional),
primary_release_year: Schema.String.pipe(Schema.optional),
query: Schema.NonEmptyString,
region: Schema.NonEmptyString.pipe(
Schema.propertySignature,
Schema.withConstructorDefault(() => "fr"),
),
year: Schema.NonEmptyString.pipe(Schema.length(4), Schema.optional),
year: Schema.String.pipe(Schema.optional),
}) {}
export class TmdbMovieSearchResponse extends Schema.Class<TmdbMovieSearchResponse>("TmdbMovieSearchResponse")({
@ -35,7 +35,7 @@ export class TmdbMovieSearchResponse extends Schema.Class<TmdbMovieSearchRespons
overview: Schema.String,
popularity: Schema.Number,
poster_path: Schema.Union(Schema.String, Schema.Null),
release_date: Schema.NonEmptyString.pipe(Schema.length(10)),
release_date: Schema.String,
title: Schema.String,
video: Schema.Boolean,
vote_average: Schema.Number,