diff --git a/README.md b/README.md index 9057937..a688874 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ The project was built adapting clean arch concepts to the context of Next.js. It - **Domain:** Concentrates important information for business rules, such as entities, enums, errors, service, providers, protocols, and usecases contracts; -- **Infrastructure:** The implementation of service contracts, proviers, protocols and usecases is carried out; +- **Infrastructure:** The implementation of service contracts, proviers and protocols is carried out; - **Main:** In this layer, the factory pattern is carried out to instantiate the elements created in the infrastructure, in addition to aggregating project configurations such as environment variables and build settings; diff --git a/docs/images/architecture-diagram.png b/docs/images/architecture-diagram.png index e02701f..51a8cf8 100644 Binary files a/docs/images/architecture-diagram.png and b/docs/images/architecture-diagram.png differ diff --git a/package.json b/package.json index 7fb4886..75c953d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "quefilme", - "version": "0.0.6", + "version": "0.1.0", "private": true, "scripts": { "dev": "next dev", diff --git a/src/domain/usecases/getMovie.usecase.ts b/src/domain/usecases/getMovie.usecase.ts index ba5f0a8..f04354e 100644 --- a/src/domain/usecases/getMovie.usecase.ts +++ b/src/domain/usecases/getMovie.usecase.ts @@ -1,10 +1,10 @@ -import { MovieEntity } from "../entities"; +import { MoviesRepository } from "@/domain/repositories"; +import { GetMovieUsecase } from "@/domain/usecases/interfaces"; -export interface GetMovieUsecase { - exec: (params: GetMovieUsecase.Params) => Promise; -} +export class GetMovieUsecaseImpl implements GetMovieUsecase { + constructor(private readonly repository: MoviesRepository) {} -export namespace GetMovieUsecase { - export type Params = string; - export type Model = MovieEntity; + async exec(imdbID: GetMovieUsecase.Params): Promise { + return await this.repository.getMovie(imdbID); + } } diff --git a/src/domain/usecases/getMovieSuggestion.usecase.ts b/src/domain/usecases/getMovieSuggestion.usecase.ts index 5d7aae9..924e660 100644 --- a/src/domain/usecases/getMovieSuggestion.usecase.ts +++ b/src/domain/usecases/getMovieSuggestion.usecase.ts @@ -1,12 +1,30 @@ -import { ListMoviesEntity, MovieEntity } from "../entities"; +import { UnexpectedError } from "@/domain/errors"; +import { MoviesRepository } from "@/domain/repositories"; +import { AiService } from "@/domain/services"; +import { GetMovieSuggestionUsecase } from "@/domain/usecases/interfaces"; -export interface GetMovieSuggestionUsecase { - exec: ( +export class GetMovieSuggestionUsecaseImpl + implements GetMovieSuggestionUsecase +{ + constructor( + private readonly repository: MoviesRepository, + private readonly service: AiService, + ) {} + async exec( params: GetMovieSuggestionUsecase.Params, - ) => Promise; -} + ): Promise { + const listOfMovies = params.movies.map((movie) => movie.title).join(", "); + + const prompt = `Seja direto e siga exatamente o exemplo proposto a seguir após os dois pontos, me indique apenas um filme baseado na lista ${listOfMovies}, mas não pode ser nenhum dessa lista e nem repetir a sugestão anterior, seja criativo na escolha mas retorne algo que combine com os itens de lista, e coloque seu imdb CORRETO no final, ex: Cidade de Deus - tt0317248`; + + const promptResponse = await this.service.generateResponse(prompt); + + const parts = promptResponse?.split(" - "); + if (!parts || parts?.length < 2) { + throw new UnexpectedError(); + } + const suggestMovieImdb = parts[1]; -export namespace GetMovieSuggestionUsecase { - export type Params = ListMoviesEntity; - export type Model = MovieEntity; + return await this.repository.getMovie(suggestMovieImdb); + } } diff --git a/src/domain/usecases/getMovies.usecase.ts b/src/domain/usecases/getMovies.usecase.ts index 56c7a76..16783b5 100644 --- a/src/domain/usecases/getMovies.usecase.ts +++ b/src/domain/usecases/getMovies.usecase.ts @@ -1,10 +1,10 @@ -import { ListMoviesEntity } from "../entities"; +import { MoviesRepository } from "@/domain/repositories"; +import { GetMoviesUsecase } from "@/domain/usecases/interfaces"; -export interface GetMoviesUsecase { - exec: (params: GetMoviesUsecase.Params) => Promise; -} +export class GetMoviesUsecaseImpl implements GetMoviesUsecase { + constructor(private readonly repository: MoviesRepository) {} -export namespace GetMoviesUsecase { - export type Params = string; - export type Model = ListMoviesEntity; + async exec(title: GetMoviesUsecase.Params): Promise { + return await this.repository.getMovieList(title.trim().toLowerCase()); + } } diff --git a/src/domain/usecases/index.ts b/src/domain/usecases/index.ts index ac75294..4d1acf2 100644 --- a/src/domain/usecases/index.ts +++ b/src/domain/usecases/index.ts @@ -1,3 +1,2 @@ export * from "./getMovie.usecase"; export * from "./getMovies.usecase"; -export * from "./getMovieSuggestion.usecase"; diff --git a/src/domain/usecases/interfaces/getMovie.usecase.ts b/src/domain/usecases/interfaces/getMovie.usecase.ts new file mode 100644 index 0000000..ee76db5 --- /dev/null +++ b/src/domain/usecases/interfaces/getMovie.usecase.ts @@ -0,0 +1,10 @@ +import { MovieEntity } from "../../entities"; + +export interface GetMovieUsecase { + exec: (params: GetMovieUsecase.Params) => Promise; +} + +export namespace GetMovieUsecase { + export type Params = string; + export type Model = MovieEntity; +} diff --git a/src/domain/usecases/interfaces/getMovieSuggestion.usecase.ts b/src/domain/usecases/interfaces/getMovieSuggestion.usecase.ts new file mode 100644 index 0000000..6383a77 --- /dev/null +++ b/src/domain/usecases/interfaces/getMovieSuggestion.usecase.ts @@ -0,0 +1,12 @@ +import { ListMoviesEntity, MovieEntity } from "../../entities/"; + +export interface GetMovieSuggestionUsecase { + exec: ( + params: GetMovieSuggestionUsecase.Params, + ) => Promise; +} + +export namespace GetMovieSuggestionUsecase { + export type Params = ListMoviesEntity; + export type Model = MovieEntity; +} diff --git a/src/domain/usecases/interfaces/getMovies.usecase.ts b/src/domain/usecases/interfaces/getMovies.usecase.ts new file mode 100644 index 0000000..d60cf21 --- /dev/null +++ b/src/domain/usecases/interfaces/getMovies.usecase.ts @@ -0,0 +1,10 @@ +import { ListMoviesEntity } from "../../entities"; + +export interface GetMoviesUsecase { + exec: (params: GetMoviesUsecase.Params) => Promise; +} + +export namespace GetMoviesUsecase { + export type Params = string; + export type Model = ListMoviesEntity; +} diff --git a/src/infrastructure/usecases/index.ts b/src/domain/usecases/interfaces/index.ts similarity index 59% rename from src/infrastructure/usecases/index.ts rename to src/domain/usecases/interfaces/index.ts index 4d1acf2..ac75294 100644 --- a/src/infrastructure/usecases/index.ts +++ b/src/domain/usecases/interfaces/index.ts @@ -1,2 +1,3 @@ export * from "./getMovie.usecase"; export * from "./getMovies.usecase"; +export * from "./getMovieSuggestion.usecase"; diff --git a/src/infrastructure/usecases/getMovie.usecase.ts b/src/infrastructure/usecases/getMovie.usecase.ts deleted file mode 100644 index bd46a17..0000000 --- a/src/infrastructure/usecases/getMovie.usecase.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { MoviesRepository } from "@/domain/repositories"; -import { GetMovieUsecase } from "@/domain/usecases"; - -export class GetMovieUsecaseImpl implements GetMovieUsecase { - constructor(private readonly repository: MoviesRepository) {} - - async exec(imdbID: GetMovieUsecase.Params): Promise { - return await this.repository.getMovie(imdbID); - } -} diff --git a/src/infrastructure/usecases/getMovieSuggestion.usecase.ts b/src/infrastructure/usecases/getMovieSuggestion.usecase.ts deleted file mode 100644 index a942fbf..0000000 --- a/src/infrastructure/usecases/getMovieSuggestion.usecase.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { UnexpectedError } from "@/domain/errors"; -import { MoviesRepository } from "@/domain/repositories"; -import { AiService } from "@/domain/services"; -import { GetMovieSuggestionUsecase } from "@/domain/usecases"; - -export class GetMovieSuggestionUsecaseImpl - implements GetMovieSuggestionUsecase -{ - constructor( - private readonly repository: MoviesRepository, - private readonly service: AiService, - ) {} - async exec( - params: GetMovieSuggestionUsecase.Params, - ): Promise { - const listOfMovies = params.movies.map((movie) => movie.title).join(", "); - - const prompt = `Seja direto e siga exatamente o exemplo proposto a seguir após os dois pontos, me indique apenas um filme baseado na lista ${listOfMovies}, mas não pode ser nenhum dessa lista e nem repetir a sugestão anterior, seja criativo na escolha mas retorne algo que combine com os itens de lista, e coloque seu imdb CORRETO no final, ex: Cidade de Deus - tt0317248`; - - const promptResponse = await this.service.generateResponse(prompt); - - const parts = promptResponse?.split(" - "); - if (!parts || parts?.length < 2) { - throw new UnexpectedError(); - } - const suggestMovieImdb = parts[1]; - - return await this.repository.getMovie(suggestMovieImdb); - } -} diff --git a/src/infrastructure/usecases/getMovies.usecase.ts b/src/infrastructure/usecases/getMovies.usecase.ts deleted file mode 100644 index 35312a3..0000000 --- a/src/infrastructure/usecases/getMovies.usecase.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { MoviesRepository } from "@/domain/repositories"; -import { GetMoviesUsecase } from "@/domain/usecases"; - -export class GetMoviesUsecaseImpl implements GetMoviesUsecase { - constructor(private readonly repository: MoviesRepository) {} - - async exec(title: GetMoviesUsecase.Params): Promise { - return await this.repository.getMovieList(title.trim().toLowerCase()); - } -} diff --git a/src/main/factories/usecases/getMovie.factory.ts b/src/main/factories/usecases/getMovie.factory.ts index 01df307..3418640 100644 --- a/src/main/factories/usecases/getMovie.factory.ts +++ b/src/main/factories/usecases/getMovie.factory.ts @@ -1,6 +1,6 @@ -import { GetMovieUsecase } from "@/domain/usecases"; +import { GetMovieUsecase } from "@/domain/usecases/interfaces"; import { makeMoviesRepository } from "../repositories/movies.factory"; -import { GetMovieUsecaseImpl } from "@/infrastructure/usecases"; +import { GetMovieUsecaseImpl } from "@/domain/usecases"; export const makeGetMovieUsecase = (): GetMovieUsecase => new GetMovieUsecaseImpl(makeMoviesRepository()); diff --git a/src/main/factories/usecases/getMovieSuggestion.factory.ts b/src/main/factories/usecases/getMovieSuggestion.factory.ts index cb0d163..231a673 100644 --- a/src/main/factories/usecases/getMovieSuggestion.factory.ts +++ b/src/main/factories/usecases/getMovieSuggestion.factory.ts @@ -1,8 +1,8 @@ -import { GetMovieSuggestionUsecase } from "@/domain/usecases"; +import { GetMovieSuggestionUsecase } from "@/domain/usecases/interfaces"; import { makeMoviesRepository } from "../repositories/movies.factory"; import { makeAiService } from "../services/ai.factory"; -import { GetMovieSuggestionUsecaseImpl } from "@/infrastructure/usecases/getMovieSuggestion.usecase"; +import { GetMovieSuggestionUsecaseImpl } from "@/domain/usecases/getMovieSuggestion.usecase"; export const makeGetMovieSuggestionUsecase = (): GetMovieSuggestionUsecase => new GetMovieSuggestionUsecaseImpl(makeMoviesRepository(), makeAiService()); diff --git a/src/main/factories/usecases/getMovies.factory.ts b/src/main/factories/usecases/getMovies.factory.ts index 95297d9..e171562 100644 --- a/src/main/factories/usecases/getMovies.factory.ts +++ b/src/main/factories/usecases/getMovies.factory.ts @@ -1,6 +1,6 @@ -import { GetMoviesUsecase } from "@/domain/usecases"; +import { GetMoviesUsecase } from "@/domain/usecases/interfaces"; import { makeMoviesRepository } from "../repositories/movies.factory"; -import { GetMoviesUsecaseImpl } from "@/infrastructure/usecases"; +import { GetMoviesUsecaseImpl } from "@/domain/usecases"; export const makeGetMoviesUsecase = (): GetMoviesUsecase => new GetMoviesUsecaseImpl(makeMoviesRepository()); diff --git a/tests/infrastructure/usecases/getMovieSuggestionUsecaseImpl.spec.ts b/tests/infrastructure/usecases/getMovieSuggestionUsecaseImpl.spec.ts index 0014ad2..c65d916 100644 --- a/tests/infrastructure/usecases/getMovieSuggestionUsecaseImpl.spec.ts +++ b/tests/infrastructure/usecases/getMovieSuggestionUsecaseImpl.spec.ts @@ -9,7 +9,7 @@ import { import { ListMoviesEntity } from "@/domain/entities"; import { UnexpectedError } from "@/domain/errors"; import { AiServiceImpl } from "@/infrastructure/services"; -import { GetMovieSuggestionUsecaseImpl } from "@/infrastructure/usecases/getMovieSuggestion.usecase"; +import { GetMovieSuggestionUsecaseImpl } from "@/domain/usecases/getMovieSuggestion.usecase"; type SutTypes = { repository: ReturnType>; diff --git a/tests/infrastructure/usecases/getMovieUsecaseImpl.spec.ts b/tests/infrastructure/usecases/getMovieUsecaseImpl.spec.ts index 1e2d0fe..558b00e 100644 --- a/tests/infrastructure/usecases/getMovieUsecaseImpl.spec.ts +++ b/tests/infrastructure/usecases/getMovieUsecaseImpl.spec.ts @@ -2,7 +2,7 @@ import { MoviesRepositoryImpl } from "@/infrastructure/repositories"; import { mock } from "jest-mock-extended"; import { movieMock } from "../mocks/getMovieUsecaseImpl.mock"; -import { GetMovieUsecaseImpl } from "@/infrastructure/usecases"; +import { GetMovieUsecaseImpl } from "@/domain/usecases"; type SutTypes = { movieRepository: ReturnType>; diff --git a/tests/infrastructure/usecases/getMoviesUsecaseImpl.spec.ts b/tests/infrastructure/usecases/getMoviesUsecaseImpl.spec.ts index b7c3150..f215383 100644 --- a/tests/infrastructure/usecases/getMoviesUsecaseImpl.spec.ts +++ b/tests/infrastructure/usecases/getMoviesUsecaseImpl.spec.ts @@ -2,7 +2,7 @@ import { MoviesRepositoryImpl } from "@/infrastructure/repositories"; import { mock } from "jest-mock-extended"; import { listMoviesMock, movieMock } from "../mocks/getMovieUsecaseImpl.mock"; -import { GetMoviesUsecaseImpl } from "@/infrastructure/usecases"; +import { GetMoviesUsecaseImpl } from "@/domain/usecases"; type SutTypes = { movieRepository: ReturnType>; diff --git a/tests/main/factories/usecases/getMovie.spec.ts b/tests/main/factories/usecases/getMovie.spec.ts index a2ce5dd..1b473e0 100644 --- a/tests/main/factories/usecases/getMovie.spec.ts +++ b/tests/main/factories/usecases/getMovie.spec.ts @@ -2,7 +2,7 @@ import { MoviesRepositoryImpl } from "@/infrastructure/repositories"; import { MoviesRepository } from "@/domain/repositories"; import { GetMovieUsecase } from "@/domain/usecases"; import { AxiosHttpClient } from "@/infrastructure/http"; -import { GetMovieUsecaseImpl } from "@/infrastructure/usecases"; +import { GetMovieUsecaseImpl } from "@/domain/usecases"; type SutTypes = { axiosHttpClient: AxiosHttpClient; diff --git a/tests/main/factories/usecases/getMovieSuggestion.spec.ts b/tests/main/factories/usecases/getMovieSuggestion.spec.ts index 7036477..433b26a 100644 --- a/tests/main/factories/usecases/getMovieSuggestion.spec.ts +++ b/tests/main/factories/usecases/getMovieSuggestion.spec.ts @@ -6,7 +6,7 @@ import { GetMovieSuggestionUsecase, GetMoviesUsecase } from "@/domain/usecases"; import { AxiosHttpClient } from "@/infrastructure/http"; import { Environment } from "@/main/config"; import { AiServiceImpl } from "@/infrastructure/services"; -import { GetMovieSuggestionUsecaseImpl } from "@/infrastructure/usecases/getMovieSuggestion.usecase"; +import { GetMovieSuggestionUsecaseImpl } from "@/domain/usecases/getMovieSuggestion.usecase"; type SutTypes = { axiosHttpClient: AxiosHttpClient; diff --git a/tests/main/factories/usecases/getMovies.spec.ts b/tests/main/factories/usecases/getMovies.spec.ts index fc433af..b9b9a35 100644 --- a/tests/main/factories/usecases/getMovies.spec.ts +++ b/tests/main/factories/usecases/getMovies.spec.ts @@ -2,7 +2,7 @@ import { MoviesRepositoryImpl } from "@/infrastructure/repositories"; import { MoviesRepository } from "@/domain/repositories"; import { GetMoviesUsecase } from "@/domain/usecases"; import { AxiosHttpClient } from "@/infrastructure/http"; -import { GetMoviesUsecaseImpl } from "@/infrastructure/usecases"; +import { GetMoviesUsecaseImpl } from "@/domain/usecases"; type SutTypes = { axiosHttpClient: AxiosHttpClient;