From ca1f97b32aa3250717904cf48b5f5cedf0865242 Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Wed, 6 Oct 2021 14:46:19 +0000 Subject: [PATCH 1/7] Set base version to 0.1 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 678c2ae0..bfcdb6a2 100644 --- a/build.sbt +++ b/build.sbt @@ -23,7 +23,7 @@ import JSEnv._ name := "http4s-dom" -ThisBuild / baseVersion := "1.0" +ThisBuild / baseVersion := "0.1" ThisBuild / organization := "org.http4s" ThisBuild / organizationName := "http4s.org" From 2cebf2f194b047fd77e23b57e7bb2dce6a933d4c Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Wed, 6 Oct 2021 15:01:37 +0000 Subject: [PATCH 2/7] Merge the modules into one --- build.sbt | 43 ++++--------------- .../org/http4s/dom/DomEntityEncoder.scala | 0 .../scala/org/http4s/dom/FetchClient.scala | 0 .../org/http4s/dom/FetchClientBuilder.scala | 0 .../org/http4s/dom/FetchEventContext.scala | 0 .../scala/org/http4s/dom/FetchOptions.scala | 0 .../scala/org/http4s/dom/FetchReferrer.scala | 0 .../scala/org/http4s/dom/ServiceWorker.scala | 0 .../main/scala/org/http4s/dom/package.scala | 0 9 files changed, 8 insertions(+), 35 deletions(-) rename {core => dom}/src/main/scala/org/http4s/dom/DomEntityEncoder.scala (100%) rename {fetch-client => dom}/src/main/scala/org/http4s/dom/FetchClient.scala (100%) rename {fetch-client => dom}/src/main/scala/org/http4s/dom/FetchClientBuilder.scala (100%) rename {service-worker => dom}/src/main/scala/org/http4s/dom/FetchEventContext.scala (100%) rename {fetch-client => dom}/src/main/scala/org/http4s/dom/FetchOptions.scala (100%) rename {fetch-client => dom}/src/main/scala/org/http4s/dom/FetchReferrer.scala (100%) rename {service-worker => dom}/src/main/scala/org/http4s/dom/ServiceWorker.scala (100%) rename {core => dom}/src/main/scala/org/http4s/dom/package.scala (100%) diff --git a/build.sbt b/build.sbt index bfcdb6a2..52ca2e15 100644 --- a/build.sbt +++ b/build.sbt @@ -114,49 +114,22 @@ val munitVersion = "0.7.29" val munitCEVersion = "1.0.6" lazy val root = - project - .in(file(".")) - .aggregate(core, fetchClient, serviceWorker, tests) - .enablePlugins(NoPublishPlugin) + project.in(file(".")).aggregate(dom, tests).enablePlugins(NoPublishPlugin) -lazy val core = project - .in(file("core")) +lazy val dom = project + .in(file("dom")) .settings( - name := "http4s-dom-core", - description := "Base library for dom http4s client and apps", + name := "http4s-dom", + description := "http4s browser integrations", libraryDependencies ++= Seq( - "org.typelevel" %%% "cats-effect-kernel" % catsEffectVersion, + "org.typelevel" %%% "cats-effect" % catsEffectVersion, "co.fs2" %%% "fs2-core" % fs2Version, - "org.http4s" %%% "http4s-core" % http4sVersion, + "org.http4s" %%% "http4s-client" % http4sVersion, "org.scala-js" %%% "scalajs-dom" % scalaJSDomVersion ) ) .enablePlugins(ScalaJSPlugin) -lazy val fetchClient = project - .in(file("fetch-client")) - .settings( - name := "http4s-dom-fetch-client", - description := "browser fetch implementation for http4s clients", - libraryDependencies ++= Seq( - "org.http4s" %%% "http4s-client" % http4sVersion - ) - ) - .dependsOn(core) - .enablePlugins(ScalaJSPlugin) - -lazy val serviceWorker = project - .in(file("service-worker")) - .settings( - name := "http4s-dom-service-worker", - description := "browser service worker implementation for http4s apps", - libraryDependencies ++= Seq( - "org.typelevel" %%% "cats-effect" % catsEffectVersion - ) - ) - .dependsOn(core) - .enablePlugins(ScalaJSPlugin) - lazy val tests = project .in(file("tests")) .settings( @@ -169,5 +142,5 @@ lazy val tests = project "org.typelevel" %%% "munit-cats-effect-3" % munitCEVersion % Test ) ) - .dependsOn(serviceWorker, fetchClient % Test) + .dependsOn(dom) .enablePlugins(ScalaJSPlugin, BuildInfoPlugin, NoPublishPlugin) diff --git a/core/src/main/scala/org/http4s/dom/DomEntityEncoder.scala b/dom/src/main/scala/org/http4s/dom/DomEntityEncoder.scala similarity index 100% rename from core/src/main/scala/org/http4s/dom/DomEntityEncoder.scala rename to dom/src/main/scala/org/http4s/dom/DomEntityEncoder.scala diff --git a/fetch-client/src/main/scala/org/http4s/dom/FetchClient.scala b/dom/src/main/scala/org/http4s/dom/FetchClient.scala similarity index 100% rename from fetch-client/src/main/scala/org/http4s/dom/FetchClient.scala rename to dom/src/main/scala/org/http4s/dom/FetchClient.scala diff --git a/fetch-client/src/main/scala/org/http4s/dom/FetchClientBuilder.scala b/dom/src/main/scala/org/http4s/dom/FetchClientBuilder.scala similarity index 100% rename from fetch-client/src/main/scala/org/http4s/dom/FetchClientBuilder.scala rename to dom/src/main/scala/org/http4s/dom/FetchClientBuilder.scala diff --git a/service-worker/src/main/scala/org/http4s/dom/FetchEventContext.scala b/dom/src/main/scala/org/http4s/dom/FetchEventContext.scala similarity index 100% rename from service-worker/src/main/scala/org/http4s/dom/FetchEventContext.scala rename to dom/src/main/scala/org/http4s/dom/FetchEventContext.scala diff --git a/fetch-client/src/main/scala/org/http4s/dom/FetchOptions.scala b/dom/src/main/scala/org/http4s/dom/FetchOptions.scala similarity index 100% rename from fetch-client/src/main/scala/org/http4s/dom/FetchOptions.scala rename to dom/src/main/scala/org/http4s/dom/FetchOptions.scala diff --git a/fetch-client/src/main/scala/org/http4s/dom/FetchReferrer.scala b/dom/src/main/scala/org/http4s/dom/FetchReferrer.scala similarity index 100% rename from fetch-client/src/main/scala/org/http4s/dom/FetchReferrer.scala rename to dom/src/main/scala/org/http4s/dom/FetchReferrer.scala diff --git a/service-worker/src/main/scala/org/http4s/dom/ServiceWorker.scala b/dom/src/main/scala/org/http4s/dom/ServiceWorker.scala similarity index 100% rename from service-worker/src/main/scala/org/http4s/dom/ServiceWorker.scala rename to dom/src/main/scala/org/http4s/dom/ServiceWorker.scala diff --git a/core/src/main/scala/org/http4s/dom/package.scala b/dom/src/main/scala/org/http4s/dom/package.scala similarity index 100% rename from core/src/main/scala/org/http4s/dom/package.scala rename to dom/src/main/scala/org/http4s/dom/package.scala From e69f1a9f5204c00dcd78eb4d8a4b8f0bf7293281 Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Wed, 6 Oct 2021 15:09:09 +0000 Subject: [PATCH 3/7] Move encoders into package object --- .../org/http4s/dom/DomEntityEncoder.scala | 43 ------------------- .../main/scala/org/http4s/dom/package.scala | 19 ++++++++ 2 files changed, 19 insertions(+), 43 deletions(-) delete mode 100644 dom/src/main/scala/org/http4s/dom/DomEntityEncoder.scala diff --git a/dom/src/main/scala/org/http4s/dom/DomEntityEncoder.scala b/dom/src/main/scala/org/http4s/dom/DomEntityEncoder.scala deleted file mode 100644 index 7b674a0f..00000000 --- a/dom/src/main/scala/org/http4s/dom/DomEntityEncoder.scala +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2021 http4s.org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.http4s -package dom - -import cats.effect.kernel.Async -import fs2.Stream -import org.scalajs.dom.File -import org.scalajs.dom.experimental.ReadableStream - -import scala.scalajs.js.typedarray.Uint8Array - -object DomEntityEncoder { - - implicit def fileEncoder[F[_]](implicit F: Async[F]): EntityEncoder[F, File] = - EntityEncoder.entityBodyEncoder.contramap { file => - Stream - .bracketCase { - // lol, the facade is still broken. next time - F.delay(file.stream().asInstanceOf[ReadableStream[Uint8Array]]) - } { case (rs, exitCase) => closeReadableStream(rs, exitCase) } - .flatMap(fromReadableStream[F]) - } - - implicit def readableStreamEncoder[F[_]: Async] - : EntityEncoder[F, ReadableStream[Uint8Array]] = - EntityEncoder.entityBodyEncoder.contramap { rs => fromReadableStream(rs) } - -} diff --git a/dom/src/main/scala/org/http4s/dom/package.scala b/dom/src/main/scala/org/http4s/dom/package.scala index 84744983..0b936271 100644 --- a/dom/src/main/scala/org/http4s/dom/package.scala +++ b/dom/src/main/scala/org/http4s/dom/package.scala @@ -20,6 +20,8 @@ import cats.effect.kernel.Async import cats.effect.kernel.Resource import cats.syntax.all._ import fs2.Stream +import org.scalajs.dom.Blob +import org.scalajs.dom.File import org.scalajs.dom.experimental.ReadableStream import org.scalajs.dom.experimental.{Headers => DomHeaders} import org.scalajs.dom.experimental.{Response => DomResponse} @@ -29,6 +31,23 @@ import scala.scalajs.js.typedarray.Uint8Array package object dom { + implicit def fileEncoder[F[_]](implicit F: Async[F]): EntityEncoder[F, File] = + blobEncoder.narrow + + implicit def blobEncoder[F[_]](implicit F: Async[F]): EntityEncoder[F, Blob] = + EntityEncoder.entityBodyEncoder.contramap { blob => + Stream + .bracketCase { + // lol, the facade is still broken. next time + F.delay(blob.stream().asInstanceOf[ReadableStream[Uint8Array]]) + } { case (rs, exitCase) => closeReadableStream(rs, exitCase) } + .flatMap(fromReadableStream[F]) + } + + implicit def readableStreamEncoder[F[_]: Async] + : EntityEncoder[F, ReadableStream[Uint8Array]] = + EntityEncoder.entityBodyEncoder.contramap { rs => fromReadableStream(rs) } + private[dom] def fromResponse[F[_]](response: DomResponse)( implicit F: Async[F]): F[Response[F]] = F.fromEither(Status.fromInt(response.status)).map { status => From 53e61dbc1446458b2f7f3a29b5f41cbc9ecaf787 Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Wed, 6 Oct 2021 15:13:51 +0000 Subject: [PATCH 4/7] Internal refactoring --- dom/src/main/scala/org/http4s/dom/FetchClient.scala | 2 +- .../main/scala/org/http4s/dom/FetchEventContext.scala | 2 +- dom/src/main/scala/org/http4s/dom/package.scala | 9 +++++---- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/dom/src/main/scala/org/http4s/dom/FetchClient.scala b/dom/src/main/scala/org/http4s/dom/FetchClient.scala index 58dede6c..9f4c16b5 100644 --- a/dom/src/main/scala/org/http4s/dom/FetchClient.scala +++ b/dom/src/main/scala/org/http4s/dom/FetchClient.scala @@ -89,7 +89,7 @@ private[dom] object FetchClient { case (r, exitCase) => closeReadableStream(r.body, exitCase) } - .evalMap(fromResponse[F]) + .evalMap(fromDomResponse[F]) } } diff --git a/dom/src/main/scala/org/http4s/dom/FetchEventContext.scala b/dom/src/main/scala/org/http4s/dom/FetchEventContext.scala index 2ec5757e..1ac8c79c 100644 --- a/dom/src/main/scala/org/http4s/dom/FetchEventContext.scala +++ b/dom/src/main/scala/org/http4s/dom/FetchEventContext.scala @@ -45,7 +45,7 @@ object FetchEventContext { event.clientId, event.resultingClientId, OptionT(F.fromPromise(F.pure(event.preloadResponse)).map(_.toOption)) - .semiflatMap(fromResponse[F]) + .semiflatMap(fromDomResponse[F]) .value, supervisor ) diff --git a/dom/src/main/scala/org/http4s/dom/package.scala b/dom/src/main/scala/org/http4s/dom/package.scala index 0b936271..5184eab0 100644 --- a/dom/src/main/scala/org/http4s/dom/package.scala +++ b/dom/src/main/scala/org/http4s/dom/package.scala @@ -26,6 +26,7 @@ import org.scalajs.dom.experimental.ReadableStream import org.scalajs.dom.experimental.{Headers => DomHeaders} import org.scalajs.dom.experimental.{Response => DomResponse} +import scala.scalajs.js import scala.scalajs.js.JSConverters._ import scala.scalajs.js.typedarray.Uint8Array @@ -48,7 +49,7 @@ package object dom { : EntityEncoder[F, ReadableStream[Uint8Array]] = EntityEncoder.entityBodyEncoder.contramap { rs => fromReadableStream(rs) } - private[dom] def fromResponse[F[_]](response: DomResponse)( + private[dom] def fromDomResponse[F[_]](response: DomResponse)( implicit F: Async[F]): F[Response[F]] = F.fromEither(Status.fromInt(response.status)).map { status => Response[F]( @@ -96,13 +97,13 @@ package object dom { // This checks if the stream is locked before canceling it to avoid an error if (!rs.locked) exitCase match { case Resource.ExitCase.Succeeded => - rs.cancel(scalajs.js.undefined) + rs.cancel(js.undefined) case Resource.ExitCase.Errored(ex) => rs.cancel(ex.getLocalizedMessage()) case Resource.ExitCase.Canceled => - rs.cancel(scalajs.js.undefined) + rs.cancel(js.undefined) } - else scalajs.js.Promise.resolve[Unit](()) + else js.Promise.resolve[Unit](()) } }.void From 95d672d45bb9a77c553d8768f7e17489dd0c9e7c Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Wed, 6 Oct 2021 15:17:00 +0000 Subject: [PATCH 5/7] Build against http4s 0.23.5 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 52ca2e15..e4e2cb74 100644 --- a/build.sbt +++ b/build.sbt @@ -108,7 +108,7 @@ ThisBuild / Test / jsEnv := { val catsEffectVersion = "3.2.9" val fs2Version = "3.1.4" -val http4sVersion = "1.0.0-M27" +val http4sVersion = "0.23.5" val scalaJSDomVersion = "1.2.0" val munitVersion = "0.7.29" val munitCEVersion = "1.0.6" From a0ac4ab018f588b856f1c8b78dd908e9c5c75b9d Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Wed, 6 Oct 2021 15:26:29 +0000 Subject: [PATCH 6/7] Update README --- README.md | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 03310cfc..34fb2442 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,15 @@ # http4s-dom Use http4s in your browser with Scala.js! +Features: -### Modules +* A `Client` implementation backed by [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) +* A [`Service Worker`](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API) integration to install your `HttpRoutes` as a [`FetchEvent` handler](https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerGlobalScope/onfetch) +* Encoders for [`File`](https://developer.mozilla.org/en-US/docs/Web/API/File), [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) and [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) -* `core`: encoders for [`File`](https://developer.mozilla.org/en-US/docs/Web/API/File) and other [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream)s -* `fetch-client`: a `Client` implementation backed by [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) -* `service-worker`: install your `HttpRoutes` as a [`FetchEvent`](https://developer.mozilla.org/en-US/docs/Web/API/FetchEvent) listener ### Usage ```sbt -libraryDependencies ++= Seq( - "org.http4s" %%% "http4s-dom-core" % "1.0.0-M27", - "org.http4s" %%% "http4s-dom-fetch-client" % "1.0.0-M27", - "org.http4s" %%% "http4s-dom-service-worker" % "1.0.0-M27", -) +libraryDependencies += "org.http4s" %%% "http4s-dom" % "0.1.0" ``` From 181560d24a64d15ac219d67f7f82f49165805334 Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Wed, 6 Oct 2021 15:52:25 +0000 Subject: [PATCH 7/7] Regenerate workflow --- .github/workflows/ci.yml | 8 ++++---- build.sbt | 5 ++--- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index af87893d..188d65aa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,9 +9,9 @@ name: Continuous Integration on: pull_request: - branches: ['**'] + branches: [series/0.1] push: - branches: ['**'] + branches: [series/0.1] tags: [v*] env: @@ -58,7 +58,7 @@ jobs: - run: sbt ++${{ matrix.scala }} ci - name: Compress target directories - run: tar cf targets.tar target tests/target fetch-client/target service-worker/target core/target project/target + run: tar cf targets.tar target dom/target tests/target project/target - name: Upload target directories uses: actions/upload-artifact@v2 @@ -69,7 +69,7 @@ jobs: publish: name: Publish Artifacts needs: [build] - if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main') + if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v')) strategy: matrix: os: [ubuntu-latest] diff --git a/build.sbt b/build.sbt index e4e2cb74..7f29a480 100644 --- a/build.sbt +++ b/build.sbt @@ -31,8 +31,7 @@ ThisBuild / publishGithubUser := "armanbilge" ThisBuild / publishFullName := "Arman Bilge" enablePlugins(SonatypeCiReleasePlugin) -ThisBuild / spiewakCiReleaseSnapshots := true -ThisBuild / spiewakMainBranches := Seq("main") +ThisBuild / githubWorkflowTargetBranches := Seq("series/0.1") ThisBuild / homepage := Some(url("https://github.com/http4s/http4s-dom")) ThisBuild / scmInfo := Some( @@ -40,7 +39,7 @@ ThisBuild / scmInfo := Some( url("https://github.com/http4s/http4s-dom"), "https://github.com/http4s/http4s-dom.git")) -ThisBuild / crossScalaVersions := Seq( /*"3.0.2",*/ "2.12.15", "2.13.6") +ThisBuild / crossScalaVersions := Seq("2.12.15", "2.13.6") replaceCommandAlias("ci", CI.AllCIs.map(_.toString).mkString) addCommandAlias("ciFirefox", CI.Firefox.toString)