package lu.foyer import lu.foyer.clients.ClientState import zio.* import zio.Console.* import zio.http.* import zio.schema.* import zio.http.endpoint.* import zio.http.codec.* import java.net.URI import zio.http.endpoint.openapi.OpenAPIGen import zio.http.endpoint.openapi.SwaggerUI import zio.http.codec.PathCodec.path case class JsonApiResponseSingle[T]( data: JsonApiResponseEntity[T], links: JsonApiResponseLinks) derives Schema case class JsonApiResponseMultiple[T]( data: List[JsonApiResponseEntity[T]], links: JsonApiResponseLinks, meta: JsonApiResponseMeta) derives Schema case class JsonApiResponseLinks( self: String, first: Option[String] = None, prev: Option[String] = None, next: Option[String] = None, last: Option[String] = None) derives Schema case class JsonApiResponseMeta(totalRecords: Int, totalPages: Int) derives Schema final case class JsonApiResponseEntity[T](id: String, `type`: String, attributes: T) derives Schema case class Page(number: Int, size: Int, totals: Boolean) val pageParams = (HttpCodec.query[Option[Int]]("page[number]") & HttpCodec.query[Option[Int]]("page[size]") & HttpCodec.query[Option[Boolean]]("page[totals]")) .transform[Page]((number, size, totals) => Page(number.getOrElse(0), size.getOrElse(50), totals.getOrElse(false)) )(p => (Some(p._1), Some(p._2), Some(p._3))) object ClientsController: private val fetchMany = Endpoint(Method.GET / "clients").query(pageParams).out[JsonApiResponseMultiple[ClientState]] private val fetchManyRoute = fetchMany.implement(page => ZIO.succeed( JsonApiResponseMultiple[ClientState]( List.empty, JsonApiResponseLinks("https://api.example.org"), meta = JsonApiResponseMeta(0, 1) ) ) ) val endpoints = List(fetchMany) val routes = Routes(fetchManyRoute) object App extends ZIOAppDefault: val openAPI = OpenAPIGen.fromEndpoints(ClientsController.endpoints) val routes = ClientsController.routes ++ SwaggerUI.routes("docs" / "openapi", openAPI) override def run = Server.serve(routes).provide(Server.default)