diff --git a/README.md b/README.md index d828b0e1..415e4d2a 100644 --- a/README.md +++ b/README.md @@ -299,6 +299,25 @@ val api: MyApi[fs2.Stream[IO, *]] = client.wire[MyApi[fs2.Stream[IO, *]]] ``` +### fetch (browser) + +This is useful when running in the browser, because it will have a smaller bundle-size then using the http4s client. + +Use with: +``` +libraryDependencies += "com.github.cornerman" %%% "sloth-jsdom-client" % "0.7.3" +``` + +In the client: +```scala +import sloth.Client +import sloth.ext.jsdom.client.HttpRpcTransport + +// for usual rpc +val client = Client[String, IO](HttpRpcTransport[IO]) +val api: MyApi[IO] = client.wire[MyApi[IO]] +``` + ## Experimental: Checksum for Apis Currently scala-2 only. diff --git a/build.sbt b/build.sbt index cd57906f..8d49603b 100644 --- a/build.sbt +++ b/build.sbt @@ -75,6 +75,19 @@ lazy val sloth = crossProject(JSPlatform, JVMPlatform) Nil ).jsSettings(jsSettings) +lazy val jsdomClient = project + .enablePlugins(ScalaJSPlugin) + .dependsOn(sloth.js) + .settings(commonSettings) + .settings(jsSettings) + .settings( + name := "sloth-jsdom-client", + libraryDependencies ++= + Deps.scalaJsDom.value :: + Deps.catsEffect.value :: + Nil + ) + lazy val http4sClient = crossProject(JSPlatform, JVMPlatform) .crossType(CrossType.Pure) .dependsOn(sloth) diff --git a/jsdomClient/src/main/scala/HttpRpcTransport.scala b/jsdomClient/src/main/scala/HttpRpcTransport.scala new file mode 100644 index 00000000..92fbdb82 --- /dev/null +++ b/jsdomClient/src/main/scala/HttpRpcTransport.scala @@ -0,0 +1,27 @@ +package sloth.ext.jsdom.client + +import cats.effect.Async +import cats.implicits._ +import sloth.{Request, RequestTransport} +import org.scalajs.dom + +import scala.scalajs.js +import scala.scalajs.js.JSConverters._ + +case class HttpRequestConfig( + baseUri: String = "/", + headers: Map[String, String] = Map.empty, +) + +object HttpRpcTransport { + def apply[F[_]: Async]: RequestTransport[String, F] = apply(HttpRequestConfig().pure[F]) + + def apply[F[_]: Async](config: F[HttpRequestConfig]): RequestTransport[String, F] = new RequestTransport[String, F] { + override def apply(request: Request[String]): F[String] = for { + config <- config + url = s"${config.baseUri}${request.path.mkString("/")}" + requestArgs = new dom.RequestInit { headers = config.headers.toJSDictionary; method = dom.HttpMethod.POST; body = request.payload } + result <- Async[F].fromThenable(Async[F].delay[js.Thenable[String]](dom.fetch(url, requestArgs).`then`[String](_.text()))) + } yield result + } +} diff --git a/project/Deps.scala b/project/Deps.scala index 1b9ec924..45b934d4 100644 --- a/project/Deps.scala +++ b/project/Deps.scala @@ -9,6 +9,7 @@ object Deps { val scalaReflect = dep("org.scala-lang" % "scala-reflect") val cats = dep("org.typelevel" %%% "cats-core" % "2.12.0") + val catsEffect = dep("org.typelevel" %%% "cats-effect" % "3.5.4") val chameleon = dep("com.github.cornerman" %%% "chameleon" % "0.4.1") val zioJson = dep("dev.zio" %%% "zio-json" % "0.7.0") @@ -27,4 +28,6 @@ object Deps { val dsl = dep("org.http4s" %%% "http4s-dsl" % version) val client = dep("org.http4s" %%% "http4s-client" % version) } + + val scalaJsDom = dep("org.scala-js" %%% "scalajs-dom" % "2.8.0") }