zio / zio-http

A next-generation Scala framework for building scalable, correct, and efficient HTTP clients and servers
https://zio.dev/zio-http
Apache License 2.0
800 stars 403 forks source link

Endpoint Scala 3 API for union types output (#3125) #3156

Open 987Nabil opened 1 month ago

987Nabil commented 1 month ago

@jdegoes we can't get rid of alternator or combiner under the hood, since it is part of the codec. This PR is just a transformation on top of HttpCodec.Fallback. This also means, there is no need for the to implement the Endpoint methods that use Combiner, since the type is always an n-tuple. Scala 3 or 2.

Combiner could have only one generic tuple as hlist impl. in Scala 3 I guess, but there is not need to split 2 and 3 in my opinion. I don't think there is a significant performance benefit. And the Scala 2 version needs to be there anyway.

fixes #3125 /claim #3125

jdegoes commented 1 month ago

@987Nabil It's not clear to me how this looks in user-land code, can you provide a more complicated example?

987Nabil commented 1 month ago

Does this help?

import zio.http.*
import zio.http.codec.*
import zio.http.endpoint.*

import java.util.UUID

type NotFound[EntityId] = EntityId
type EntityId           = UUID

val union: ContentCodec[String | UUID | Boolean] =
  HttpCodec.content[String] || HttpCodec.content[UUID] || HttpCodec.content[Boolean]

val unionEndpoint =
  Endpoint(Method.GET / "api" / "complex-union")
    .outCodec(union)

val unionWithErrorEndpoint
    : Endpoint[Unit, Unit, NotFound[EntityId] | String, UUID | Unit, AuthType.None] =
  Endpoint(Method.GET / "api" / "union-with-error")
    .out[UUID]
    .orOut[Unit](Status.NoContent)
    .outError[NotFound[EntityId]](Status.NotFound)
    .orOutError[String](Status.BadRequest)

val impl = unionWithErrorEndpoint.implementEither { _ =>
  val result: Either[NotFound[EntityId] | String, UUID | Unit] = Left("error")
  result
}
jdegoes commented 1 month ago

@987Nabil I think this looks good but should be accompanied by documentation and at least one example. 🙏