Skip to content

Instantly share code, notes, and snippets.

@dacr
Last active June 15, 2024 17:18
Show Gist options
  • Save dacr/1fc311878e5a575161a4b7ddb8a61411 to your computer and use it in GitHub Desktop.
Save dacr/1fc311878e5a575161a4b7ddb8a61411 to your computer and use it in GitHub Desktop.
tapir with iron/jsoniter for data validity and better documentation / published by https://github.com/dacr/code-examples-manager #a98827ba-f873-4597-8321-57c5b0f37a6a/13a8a6d8fa369d29757432f7ce24713f83c9acfb
// summary : tapir with iron/jsoniter for data validity and better documentation
// keywords : scala, zio, tapir, iron, jsoniter, @testable, @exclusive
// publish : gist
// authors : David Crosson
// license : Apache NON-AI License Version 2.0 (https://raw.githubusercontent.com/non-ai-licenses/non-ai-licenses/main/NON-AI-APACHE2)
// id : a98827ba-f873-4597-8321-57c5b0f37a6a
// created-on : 2024-06-07T07:57:09+02:00
// managed-by : https://github.com/dacr/code-examples-manager
// run-with : scala-cli $file
// test-with : curl -L http://127.0.0.1:8080/hello/david
// ---------------------
//> using scala "3.4.2"
//> using dep "com.softwaremill.sttp.tapir::tapir-zio:1.10.9"
//> using dep "com.softwaremill.sttp.tapir::tapir-zio-http-server:1.10.9"
//> using dep "com.softwaremill.sttp.tapir::tapir-iron:1.10.9"
//> using dep "com.softwaremill.sttp.tapir::tapir-jsoniter-scala:1.10.9"
//> using dep "com.softwaremill.sttp.tapir::tapir-swagger-ui-bundle:1.10.9"
//> using dep "io.github.iltotore::iron-jsoniter:2.5.0"
//> using dep "com.github.plokhotnyuk.jsoniter-scala::jsoniter-scala-core:2.30.1"
//> using dep "com.github.plokhotnyuk.jsoniter-scala::jsoniter-scala-macros:2.30.1"
// ---------------------
import zio.*
import zio.http.Server
import com.github.plokhotnyuk.jsoniter_scala.macros.*
import com.github.plokhotnyuk.jsoniter_scala.core.*
import io.github.iltotore.iron.*
import io.github.iltotore.iron.constraint.all.*
import io.github.iltotore.iron.jsoniter.given
import sttp.tapir.ztapir.*
import sttp.tapir.server.ziohttp.ZioHttpInterpreter
import sttp.tapir.swagger.bundle.SwaggerInterpreter
import sttp.tapir.json.jsoniter.*
import sttp.tapir.Schema
import sttp.tapir.generic.auto.*
import sttp.tapir.codec.iron.given
import sttp.apispec.openapi.Info
object WebApp extends ZIOAppDefault {
//type Name = String :| (Not[Empty] & Alphanumeric) // //DescribedAs "name should not be empty and only made of alphanumeric characters"
type Name = String :| (MinLength[3] & MaxLength[64])
type Age = Int :| Positive // DescribedAs "Age should be positive"
type NickName = String :| (MinLength[3] & MaxLength[6])
//type NickNames = List[NickName] :| MinLength[1]
type NickNames = List[NickName] :| Not[Empty]
enum Gender derives ConfiguredJsonValueCodec {
case Female, Male, Other
}
case class Salute(
name: Name,
age: Int :| Positive, /*DescribedAs "Age should be positive"*/
gender: Option[Gender],
nicknames: NickNames
) derives ConfiguredJsonValueCodec
case class Greeting(message: String) derives ConfiguredJsonValueCodec
// --------------------------------------------------
def helloLogic(salute: Salute): UIO[Greeting] = ZIO.succeed(Greeting("hello"))
val helloEndPoint =
endpoint
.tag("Greetings")
.name("hello")
.description("Returns greeting")
.post
.in("hello")
.in(jsonBody[Salute])
.out(jsonBody[Greeting])
val helloRoute = helloEndPoint.zServerLogic[Any](helloLogic)
// --------------------------------------------------
val apiDocRoute =
SwaggerInterpreter()
.fromServerEndpoints(
List(helloRoute),
Info(title = "Greeting API", version = "1.0", description = Some("Everything required to be polite"))
)
// --------------------------------------------------
val routes = ZioHttpInterpreter().toHttp(List(helloRoute) ++ apiDocRoute)
val server = for {
_ <- ZIO.log("API documentation : http://127.0.0.1:8080/docs")
_ <- Server.serve(routes)
} yield ()
override def run = server.provide(Server.default)
}
WebApp.main(Array.empty)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment