Skip to content

Commit 10e3604

Browse files
authored
Merge pull request #116 from http4s/feature/ws-client-docs
WebSocket client docs/example
2 parents a236060 + 25dd93c commit 10e3604

File tree

7 files changed

+153
-74
lines changed

7 files changed

+153
-74
lines changed

README.md

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
# http4s-dom
22

3-
Use http4s in your browser with Scala.js! Check out the [live example](https://http4s.github.io/http4s-dom/) in the docs.
4-
3+
Use http4s in your browser with Scala.js! Check out the [interactive examples](https://http4s.github.io/http4s-dom/) in the docs.
54

65
Features:
76

8-
* A [`Client` implementation](https://www.javadoc.io/doc/org.http4s/http4s-dom_sjs1_2.13/latest/org/http4s/dom/FetchClientBuilder.html) backed by [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)
9-
* A [`Service Worker` integration](https://www.javadoc.io/doc/org.http4s/http4s-dom_sjs1_2.13/latest/org/http4s/dom/ServiceWorker$.html) to install your `HttpRoutes` as a [`FetchEvent` handler](https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerGlobalScope/onfetch)
7+
* A [`Client` implementation](fetch.md) backed by [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)
8+
* A [`WSClient` implementation](websocket.md) backed by [`WebSocket`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket$.html)
9+
* A [`Service Worker` integration](serviceworker.md) to install your `HttpRoutes` as a [`FetchEvent` handler](https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerGlobalScope/onfetch)
1010
* 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)
1111

1212
Notably, http4s-dom can also be used to create _serverless_ apps with [Cloudflare Workers](https://workers.cloudflare.com) which have adopted the same APIs used in the browser!
@@ -17,8 +17,5 @@ Notably, http4s-dom can also be used to create _serverless_ apps with [Cloudflar
1717

1818
```scala
1919
// Supports http4s 0.23.x and scala-js-dom 2.x
20-
libraryDependencies += "org.http4s" %%% "http4s-dom" % "0.2.0"
21-
22-
// Or, for compatibility with scala-js-dom 1.x
23-
libraryDependencies += "org.http4s" %%% "http4s-dom" % "0.1.0"
20+
libraryDependencies += "org.http4s" %%% "http4s-dom" % "0.2.1"
2421
```

docs/README.md

Lines changed: 0 additions & 66 deletions
This file was deleted.

docs/directory.conf

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
laika.navigationOrder = [
2+
index.md
3+
fetch.md
4+
websocket.md
5+
serviceworker.md
6+
]

docs/fetch.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Fetch Client
2+
3+
The [`FetchClientBuilder`](https://www.javadoc.io/doc/org.http4s/http4s-dom_sjs1_2.13/latest/org/http4s/dom/FetchClientBuilder.html) creates a standard http4s [`Client`](https://http4s.org/v0.23/api/org/http4s/client/client) that is described in the [http4s documentation](https://http4s.org/v0.23/client/).
4+
5+
## Example
6+
7+
```scala mdoc:js
8+
<div style="text-align:center">
9+
<h3 style="padding:10px">
10+
I'm bored.
11+
</h3>
12+
<button id="button">Fetch Activity</button>
13+
<p style="padding:10px" id="activity"></p>
14+
</div>
15+
---
16+
import cats.effect._
17+
import cats.effect.unsafe.implicits._
18+
import io.circe.generic.auto._
19+
import org.http4s.circe.CirceEntityCodec._
20+
import org.http4s.dom._
21+
import org.scalajs.dom._
22+
23+
val client = FetchClientBuilder[IO].create
24+
25+
val activityElement = document.getElementById("activity")
26+
27+
case class Activity(activity: String)
28+
29+
val fetchActivity: IO[Unit] = for {
30+
_ <- IO(activityElement.innerHTML = "<i>fetching...</i>")
31+
activity <- client.expect[Activity]("https://www.boredapi.com/api/activity")
32+
_ <- IO(activityElement.innerHTML = activity.activity)
33+
} yield ()
34+
35+
val button = document.getElementById("button").asInstanceOf[html.Button]
36+
37+
button.onclick = _ => fetchActivity.unsafeRunAndForget()
38+
```

docs/index.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# http4s-dom
2+
3+
Use http4s in your browser with Scala.js!
4+
Features:
5+
6+
* A [`Client` implementation](fetch.md) backed by [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)
7+
* A [`WSClient` implementation](websocket.md) backed by [`WebSocket`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket$.html)
8+
* A [`Service Worker` integration](serviceworker.md) to install your `HttpRoutes` as a [`FetchEvent` handler](https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerGlobalScope/onfetch)
9+
* 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)
10+
11+
Notably, http4s-dom can also be used to create _serverless_ apps with [Cloudflare Workers](https://workers.cloudflare.com) which have adopted the same APIs used in the browser!
12+
13+
## Installation
14+
15+
[![http4s-dom Scala version support](https://index.scala-lang.org/http4s/http4s-dom/http4s-dom/latest.svg)](https://index.scala-lang.org/http4s/http4s-dom/http4s-dom)
16+
17+
```scala
18+
// Supports http4s 0.23.x and scala-js-dom 2.x
19+
libraryDependencies += "org.http4s" %%% "http4s-dom" % "@VERSION@"
20+
21+
// recommended, brings in the latest client module
22+
libraryDependencies += "org.http4s" %%% "http4s-client" % "@HTTP4S_VERSION@"
23+
24+
// optional, for JSON support
25+
libraryDependencies += "org.http4s" %%% "http4s-circe" % "@HTTP4S_VERSION@"
26+
libraryDependencies += "io.circe" %%% "circe-generic" % "@CIRCE_VERSION@"
27+
```

docs/serviceworker.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Service Worker "Server"
2+
3+
The [`ServiceWorker`](https://www.javadoc.io/doc/org.http4s/http4s-dom_sjs1_2.13/latest/org/http4s/dom/ServiceWorker$.html) `FetchEvent` listener integrates directly with [http4s services](https://http4s.org/v0.23/service/). You can use it to run a "proxy server" as a background process in the browser that can intercept and respond to requests made by the `FetchClient`.
4+
5+
## Example
6+
7+
Coming soon!

docs/websocket.md

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# WebSocket Client
2+
3+
The [`WebSocketClient`](https://www.javadoc.io/doc/org.http4s/http4s-dom_sjs1_2.13/latest/org/http4s/dom/WSClient$.html) creates a standard http4s [`WSClientHighLevel`](https://http4s.org/v0.23/api/org/http4s/client/client).
4+
5+
## Example
6+
7+
```scala mdoc:js
8+
<div>
9+
<h3>Send Text Frame</h3>
10+
<input id="message" size="64" type="text">
11+
<button id="button">Send</button>
12+
</div>
13+
<div style="display: flex">
14+
<div style="flex: 50%">
15+
<h3>Sent</h3>
16+
<div id="sent" style="width: 100%"></div>
17+
</div>
18+
<div style="flex: 50%">
19+
<h3>Received</h3>
20+
<div id="received" style="width: 100%"></div>
21+
</div>
22+
</div>
23+
---
24+
import cats.effect._
25+
import cats.effect.unsafe.implicits._
26+
import org.http4s.client.websocket._
27+
import org.http4s.dom._
28+
import org.http4s.syntax.all._
29+
import org.scalajs.dom._
30+
31+
val message = document.getElementById("message").asInstanceOf[html.Input]
32+
val button = document.getElementById("button").asInstanceOf[html.Button]
33+
val sent = document.getElementById("sent").asInstanceOf[html.Element]
34+
val received = document.getElementById("received").asInstanceOf[html.Element]
35+
36+
val request = WSRequest(uri"wss://ws.postman-echo.com/raw")
37+
val app = WebSocketClient[IO].connectHighLevel(request).use { conn =>
38+
39+
def log(e: html.Element, text: String): IO[Unit] =
40+
IO {
41+
val p = document.createElement("p")
42+
p.innerHTML = text
43+
e.appendChild(p)
44+
()
45+
}
46+
47+
val sendMessage: IO[Unit] = for {
48+
text <- IO(message.value)
49+
frame = WSFrame.Text(text)
50+
_ <- conn.send(frame)
51+
_ <- log(sent, frame.toString)
52+
} yield ()
53+
54+
val receiveMessages: IO[Unit] =
55+
conn.receiveStream
56+
.evalTap(frame => log(received, frame.toString))
57+
.compile
58+
.drain
59+
60+
val logCloseFrame: IO[Unit] =
61+
conn.closeFrame.get.flatMap(frame => log(received, frame.toString))
62+
63+
val registerOnClick = IO(button.onclick = _ => sendMessage.unsafeRunAndForget())
64+
val deregisterOnClick = IO(button.onclick = null)
65+
66+
registerOnClick *> receiveMessages *> logCloseFrame *> deregisterOnClick
67+
}
68+
69+
app.unsafeRunAndForget()
70+
```

0 commit comments

Comments
 (0)