Working on some basic routes.
All checks were successful
/ Build and Release Application (push) Successful in 2m26s

This commit is contained in:
Pat Garrity 2026-05-11 22:08:09 -05:00
parent 87a6fd5398
commit 0969e94947
Signed by: pfm
GPG key ID: 5CA5D21BAB7F3A76
4 changed files with 90 additions and 20 deletions

View file

@ -31,7 +31,7 @@ val Deps = new {
val Gs = new { val Gs = new {
val Uuid: ModuleID = "gs" %% "gs-uuid-v0" % "0.4.2" val Uuid: ModuleID = "gs" %% "gs-uuid-v0" % "0.4.2"
val Std: ModuleID = "gs" %% "gs-std-core-v0" % "0.1.2" val Std: ModuleID = "gs" %% "gs-std-core-v0" % "0.1.3"
val Datagen: ModuleID = "gs" %% "gs-datagen-core-v0" % "0.4.1" val Datagen: ModuleID = "gs" %% "gs-datagen-core-v0" % "0.4.1"
} }
@ -44,6 +44,13 @@ val Deps = new {
val EmberServer: ModuleID = "org.http4s" %% "http4s-ember-server" % Version val EmberServer: ModuleID = "org.http4s" %% "http4s-ember-server" % Version
} }
val Circe = new {
private val Version: String = "0.14.15"
val Generic: ModuleID = "io.circe" %% "circe-generic" % Version
val Literal: ModuleID = "io.circe" %% "circe-literal" % Version
}
val Log4Cats = new { val Log4Cats = new {
val Slf4j: ModuleID = "org.typelevel" %% "log4cats-slf4j" % "2.8.0" val Slf4j: ModuleID = "org.typelevel" %% "log4cats-slf4j" % "2.8.0"
} }
@ -105,6 +112,8 @@ lazy val api = project
Deps.Http4s.Dsl, Deps.Http4s.Dsl,
Deps.Http4s.Circe, Deps.Http4s.Circe,
Deps.Http4s.EmberServer, Deps.Http4s.EmberServer,
Deps.Circe.Generic,
Deps.Circe.Literal,
Deps.Log4Cats.Slf4j, Deps.Log4Cats.Slf4j,
Deps.LogbackClassic Deps.LogbackClassic
) )

View file

@ -4,31 +4,24 @@ import cats.effect.ExitCode
import cats.effect.IO import cats.effect.IO
import cats.effect.IOApp import cats.effect.IOApp
import com.comcast.ip4s._ import com.comcast.ip4s._
import org.http4s.HttpRoutes import gs.respite.db.MemoryKeySpaceDb
import org.http4s.Method
import org.http4s.dsl.io.*
import org.http4s.ember.server.EmberServerBuilder import org.http4s.ember.server.EmberServerBuilder
import org.typelevel.log4cats.LoggerFactory import org.typelevel.log4cats.LoggerFactory
import org.typelevel.log4cats.slf4j.Slf4jFactory import org.typelevel.log4cats.slf4j.Slf4jFactory
object RespiteApi extends IOApp: object RespiteApi extends IOApp:
given CanEqual[Method, Method] = CanEqual.derived
given CanEqual[org.http4s.Uri.Path, org.http4s.Uri.Path] = CanEqual.derived
implicit val loggerFactory: LoggerFactory[IO] = Slf4jFactory.create[IO] implicit val loggerFactory: LoggerFactory[IO] = Slf4jFactory.create[IO]
private val RespiteService = HttpRoutes
.of[IO] { case GET -> Root =>
Ok("Hello, Respite!")
}
.orNotFound
override def run(args: List[String]): cats.effect.IO[ExitCode] = override def run(args: List[String]): cats.effect.IO[ExitCode] =
EmberServerBuilder for
.default[IO] db <- MemoryKeySpaceDb.initialize[IO]
.withHost(ipv4"0.0.0.0") exitCode <- EmberServerBuilder
.withPort(port"8080") .default[IO]
.withHttpApp(RespiteService) .withHost(ipv4"0.0.0.0")
.build .withPort(port"8080")
.use(_ => IO.never) .withHttpApp(new RespiteRoutes[IO](db).app)
.as(ExitCode.Success) .build
.use(_ => IO.never)
.as(ExitCode.Success)
yield exitCode

View file

@ -0,0 +1,40 @@
package gs.respite.api
import cats.effect.Async
import cats.syntax.all.*
import gs.respite.api.json.given
import gs.respite.db.KeySpaceDb
import gs.respite.model.Key
import gs.respite.model.Value
import org.http4s.EntityEncoder
import org.http4s.HttpApp
import org.http4s.HttpRoutes
import org.http4s.Method
import org.http4s.circe.*
import org.http4s.dsl.Http4sDsl
final class RespiteRoutes[F[_]: Async](
val db: KeySpaceDb[F]
) extends Http4sDsl[F]:
import RespiteRoutes.given
given EntityEncoder[F, Value] = jsonEncoderOf[Value]
val app: HttpApp[F] = HttpRoutes
.of[F] { case GET -> Root / "default" / key =>
for
result <- db.default.get(Key.string(key))
response <-
result match
case Some(value) => Ok(value)
case _ => NotFound()
yield response
}
.orNotFound
object RespiteRoutes:
given CanEqual[Method, Method] = CanEqual.derived
given CanEqual[org.http4s.Uri.Path, org.http4s.Uri.Path] = CanEqual.derived
end RespiteRoutes

View file

@ -0,0 +1,28 @@
package gs.respite.api.json
import gs.respite.model.BooleanValue
import gs.respite.model.ByteValue
import gs.respite.model.DateValue
import gs.respite.model.Int64Value
import gs.respite.model.StringValue
import gs.respite.model.UUIDValue
import gs.respite.model.Value
import gs.std.v0.core.Base64Encoder
import io.circe.Encoder
import io.circe.literal.*
given Encoder[Value] = Encoder.instance { (value: Value) =>
value match
case v: StringValue =>
json"""{"value": ${v.value}}"""
case v: BooleanValue =>
json"""{"value": ${v.value}}"""
case v: Int64Value =>
json"""{"value": ${v.value}}"""
case v: UUIDValue =>
json"""{"value": ${v.value.withDashes()}}"""
case v: DateValue =>
json"""{"value": ${v.value}}"""
case v: ByteValue =>
json"""{"value": ${Base64Encoder.encode(v.value).data}}"""
}