79252545

Date: 2024-12-04 19:55:46
Score: 1
Natty:
Report link

To solve my problem I follow a example shared by @Gastón Schabas, I transformed my route object in a Class, create a ZLayer and insert it in a ZIO provide in a Main class :

package br.com.flashcards

import br.com.flashcards.adapter.endpoint.DeckEndpoint
import br.com.flashcards.config.EndpointConfig
import br.com.flashcards.core.service.impl.DeckService
import br.com.flashcards.core.service.query.impl.DeckQueryService
import sttp.tapir.server.interceptor.cors.CORSConfig.AllowedOrigin
import sttp.tapir.server.interceptor.cors.{CORSConfig, CORSInterceptor}
import sttp.tapir.server.ziohttp.{ZioHttpInterpreter, ZioHttpServerOptions}
import zio.*
import zio.http.*

object App extends ZIOAppDefault:

  override def run: ZIO[Any with ZIOAppArgs with Scope, Any, Any] =
    val options: ZioHttpServerOptions[Any] =
      ZioHttpServerOptions.customiseInterceptors
        .corsInterceptor(
          CORSInterceptor.customOrThrow(
            CORSConfig.default.copy(
              allowedOrigin = AllowedOrigin.All
            )
          )
        )
        .options

    (for {
      endpoints <- ZIO.service[EndpointConfig]
      httpApp = ZioHttpInterpreter(options).toHttp(endpoints.endpoints)
      actualPort <- Server.install(httpApp)
      _ <- Console.printLine(s"Application zio-flashcards started")
      _ <- Console.printLine(
        s"Go to http://localhost:8080/docs to open SwaggerUI"
      )
      _ <- ZIO.never
    } yield ())
      .provide(
        EndpointConfig.layer,
        DeckRoute.layer,
        DeckService.layer,
        DeckQueryService.layer,
        Server.defaultWithPort(8080)
      )
      .exitCode

my route. Obs: I refactored my traits with insert, update, delete and find in two traits, Read and Write Traits

package br.com.flashcards.adapter.endpoint

import br.com.flashcards.adapter.endpoint.doc.DeckDocEndpoint
import br.com.flashcards.adapter.endpoint.request.{
  DeckInsertRequest,
  DeckUpdateRequest
}
import br.com.flashcards.adapter.endpoint.response.error.DeckError
import br.com.flashcards.adapter.endpoint.response.{
  DeckDetailsResponse,
  DeckInsertedResponse,
  DeckListResponse,
  DeckUpdatedResponse
}
import br.com.flashcards.core.exception.DeckException
import br.com.flashcards.core.service.query.DeckRead
import br.com.flashcards.core.service.{
  DeckWrite,
  InsertDeckDomain,
  UpdateDeckDomain
}
import io.scalaland.chimney.dsl.*
import sttp.tapir.ztapir.*
import zio.*

import java.time.OffsetDateTime

case class DeckEndpoint(
    write: DeckWrite,
    read: DeckRead
):

  val endpoints: List[ZServerEndpoint[Any, Any]] =
    List(
      listRoute(),
      findByIdRoute(),
      insertRoute(),
      updateRoute(),
      deleteRoute()
    )

  private def listRoute(): ZServerEndpoint[Any, Any] =
    def listRouteLogic() =
      read
        .list()
        .mapBoth(
          _ => DeckError.GenericError("", "", 500, OffsetDateTime.now()),
          d => d.map(_.into[DeckListResponse].transform)
        )

    DeckDocEndpoint.listEndpoint.zServerLogic(_ => listRouteLogic())

  private def findByIdRoute(): ZServerEndpoint[Any, Any] =
    def findByIdRouteLogic(
        id: Long
    ) =
      read
        .findById(id)
        .mapBoth(
          _ => DeckError.GenericError("", "", 500, OffsetDateTime.now()),
          _.into[DeckDetailsResponse].transform
        )

    DeckDocEndpoint.findByIdEndpoint.zServerLogic(p => findByIdRouteLogic(p))

  private def insertRoute(): ZServerEndpoint[Any, Any] =
    def insertRouteLogic(
        request: DeckInsertRequest
    ) =
      write
        .insert(request.into[InsertDeckDomain].transform)
        .mapBoth(
          _ => DeckError.GenericError("", "", 500, OffsetDateTime.now()),
          _.into[DeckInsertedResponse].transform
        )

    DeckDocEndpoint.insertEndpoint.zServerLogic(p => insertRouteLogic(p))

  private def updateRoute(): ZServerEndpoint[Any, Any] =
    def updateRouteLogic(
        id: Long,
        request: DeckUpdateRequest
    ) =
      write
        .update(
          request.into[UpdateDeckDomain].withFieldConst(_.id, id).transform
        )
        .mapBoth(
          _ => DeckError.GenericError("", "", 500, OffsetDateTime.now()),
          _.into[DeckUpdatedResponse].transform
        )

    DeckDocEndpoint.updateEndpoint.zServerLogic(p =>
      updateRouteLogic(p._1, p._2)
    )

  private def deleteRoute(): ZServerEndpoint[Any, Any] =
    def deleteRouteLogic(
        id: Long
    ) =
      write
        .delete(id)
        .orElseFail(DeckError.GenericError("", "", 500, OffsetDateTime.now()))

    DeckDocEndpoint.deleteEndpoint.zServerLogic(p => deleteRouteLogic(p))

object DeckRoute:

  val layer: ZLayer[
    DeckWrite & DeckRead,
    DeckException,
    DeckRoute
  ] = ZLayer.fromFunction(DeckEndpoint(_, _))

Thank you :)

Reasons:
  • Blacklisted phrase (0.5): Thank you
  • Long answer (-1):
  • Has code block (-0.5):
  • User mentioned (1): @Gastón
  • Self-answer (0.5):
  • Low reputation (0.5):
Posted by: Jose Luiz Junior