not working: attempt to stream in websocket

added Vite proxy, tested with websocat, with direct js websocket.
the error seems to be Laminex related
This commit is contained in:
efim 2023-04-23 21:18:24 +04:00
parent 329dc6e8b2
commit bd46cd94b3
5 changed files with 91 additions and 17 deletions

View File

@ -32,11 +32,12 @@ lazy val frontend = project
*/
libraryDependencies += "org.scala-js" %%% "scalajs-dom" % "2.4.0",
libraryDependencies += "com.raquo" %%% "laminar" % "15.0.1",
libraryDependencies += "io.laminext" %%% "websocket" % "0.15.0"
libraryDependencies += "io.laminext" %%% "websocket-circe" % "0.15.0",
libraryDependencies += "io.laminext" %%% "fetch" % "0.15.0"
)
.dependsOn(common.js)
val circeVersion = "0.14.1"
val circeVersion = "0.14.5"
val http4sVersion = "1.0.0-M39"
lazy val backend = project

View File

@ -6,14 +6,10 @@ import io.circe._
object Models {
/** view of the single planning poker round
* @param players
* \- people who are currently playing
* @param allowedCards
* \- the cards values that can be used by players
* @param round
* \- state of the selected cards of the players
* @param canCloseRound
* \- whether current player has access to button to finish the round
* @param players - people who are currently playing
* @param allowedCards- the cards values that can be used by players
* @param round - state of the selected cards of the players
* @param canCloseRound - whether current player has access to button to finish the round
*/
final case class RoomStateView(
players: List[Player],
@ -25,9 +21,15 @@ object Models {
def playersCount: Int = players.size
}
given Encoder[Map[PlayerID, String]] = Encoder.encodeMap[PlayerID, String]
given Decoder[Map[PlayerID, String]] = Decoder.decodeMap[PlayerID, String]
given Codec[Map[PlayerID, String]] = Codec.from(summon[Decoder[Map[PlayerID, String]]], summon[Encoder[Map[PlayerID, String]]])
object RoomStateView {
given Encoder[Map[PlayerID, String]] = Encoder.encodeMap[PlayerID, String]
given Decoder[Map[PlayerID, String]] = Decoder.decodeMap[PlayerID, String]
given Codec[Map[PlayerID, String]] = Codec.from(summon[Decoder[Map[PlayerID, String]]], summon[Encoder[Map[PlayerID, String]]])
val empty = RoomStateView(
List.empty, PlayerID(0), List.empty, RoundState.Voting(None, List.empty), false
)
}
enum RoundState derives Codec.AsObject:

View File

@ -4,6 +4,7 @@ import scala.scalajs.js
import scala.scalajs.js.annotation.*
import com.raquo.laminar.api.L.{*, given}
import industries.sunshine.planningpoker.common.Models.*
import scala.concurrent.duration._
import org.scalajs.dom
@ -20,20 +21,59 @@ def PlanningPokerUrgh(): Unit =
object Main {
final case class AppState(
myId: Option[PlayerID]
myId: Option[PlayerID]
)
// TODO is this ok for state creation? link with auth component and use in another?
val appStateSignal = Var(AppState(Some(TestModels.me.id))).signal
val staticStateSignal = Var(TestModels.testRoom).signal
import io.laminext.websocket.circe.WebSocket._
import io.laminext.websocket.circe.webSocketReceiveBuilderSyntax
val roomStateWSStream = io.laminext.websocket.circe.WebSocket
.url("ws://0.0.0.0:5153/api/subscribe")
// .json[RoomStateView, Unit]
.build(
managed = true,
autoReconnect = false,
reconnectDelay = 1.second,
reconnectDelayOffline = 20.seconds,
reconnectRetries = 1
)
val stateStream = roomStateWSStream.received
// and what's the difference between EventStream and Signal???
val stateSignal =
stateStream.startWith(TestModels.testRoom, cacheInitialValue = true)
// NOTE let's try with fetch \ rest
// import io.laminext.fetch.Fetch
// import com.raquo.laminar.api.L._
// import scala.concurrent.ExecutionContext.Implicits.global
// val testRest = Fetch.get("http://0.0.0.0:5173/api/subscribe").text
import scala.scalajs.js.Dynamic.{global => g}
def appElement(): Element = {
div(
className := "w-screen h-screen flex flex-col justify-center items-center",
div(
className := "h-24 w-full flex flex-for justify-center items-center bg-green-200",
p(className := "text-2xl", "Here be header"),
className := "bg-yellow-400",
child.text <-- roomStateWSStream.events
.map { ev =>
{
val a = ev.toString()
g.console.warn(s"got state $a")
a
}
}
.startWith("BEFORE WS")
),
RoomView.renderRoom(staticStateSignal)
div(
className := "h-24 w-full flex flex-for justify-center items-center bg-green-200",
p(className := "text-2xl", "Here be header")
),
RoomView.renderRoom(staticStateSignal),
roomStateWSStream.connect
)
}
}

19
main.js
View File

@ -1,3 +1,22 @@
import './style.css'
import './frontend/target/scala-3.2.0/frontend-fastopt/main.js'
// import 'scalajs:main.js'
// // const socket = new WebSocket("/api/subscribe");
// const socket = new WebSocket("ws:0.0.0.0:5173/api/subscribe");
// socket.addEventListener("open", (event) => {
// console.log("!! WebSocket connected:", event);
// });
// socket.addEventListener("message", (event) => {
// console.log("!! WebSocket message received:", event);
// });
// socket.addEventListener("close", (event) => {
// console.log("!! WebSocket closed:", event);
// });
// socket.addEventListener("error", (event) => {
// console.log("!! WebSocket error:", event);
// });

View File

@ -3,4 +3,16 @@ import scalaJSPlugin from "@scala-js/vite-plugin-scalajs";
export default defineConfig({
plugins: [scalaJSPlugin()],
server: {
proxy: {
// Proxy all requests starting with /api to your backend server
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
ws: true, // Enable WebSocket proxying
rewrite: (path) => path.replace(/^\/api/, ''),
},
},
},
});