Initial commit
This commit is contained in:
parent
c7ff93a1f7
commit
a1e4eb1dff
13 changed files with 917 additions and 2 deletions
91
src/backend/sockethandler.gleam
Normal file
91
src/backend/sockethandler.gleam
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
import gleam/erlang/process.{type Selector, type Subject}
|
||||
import gleam/http/request.{type Request}
|
||||
import gleam/http/response.{type Response}
|
||||
import gleam/json
|
||||
import gleam/option.{type Option, Some}
|
||||
import lustre
|
||||
import lustre/server_component
|
||||
import mist.{type Connection, type ResponseData}
|
||||
|
||||
pub fn serve(
|
||||
request: Request(Connection),
|
||||
component: lustre.App(start_args, model, msg),
|
||||
start_args: start_args,
|
||||
) -> Response(ResponseData) {
|
||||
mist.websocket(
|
||||
request:,
|
||||
on_init: init_socket(_, component, start_args),
|
||||
handler: loop_socket,
|
||||
on_close: close_socket,
|
||||
)
|
||||
}
|
||||
|
||||
type Socket(msg) {
|
||||
Socket(
|
||||
component: lustre.Runtime(msg),
|
||||
self: Subject(server_component.ClientMessage(msg)),
|
||||
)
|
||||
}
|
||||
|
||||
type SocketMessage(msg) =
|
||||
server_component.ClientMessage(msg)
|
||||
|
||||
type SocketInit(msg) =
|
||||
#(Socket(msg), Option(Selector(SocketMessage(msg))))
|
||||
|
||||
fn init_socket(
|
||||
_,
|
||||
component: lustre.App(start_args, model, msg),
|
||||
start_args: start_args,
|
||||
) -> SocketInit(msg) {
|
||||
let assert Ok(component) =
|
||||
lustre.start_server_component(component, start_args)
|
||||
|
||||
let self = process.new_subject()
|
||||
let selector = process.new_selector() |> process.select(self)
|
||||
|
||||
server_component.register_subject(self)
|
||||
|> lustre.send(to: component)
|
||||
|
||||
#(Socket(component:, self:), Some(selector))
|
||||
}
|
||||
|
||||
fn loop_socket(
|
||||
state: Socket(msg),
|
||||
message: mist.WebsocketMessage(SocketMessage(msg)),
|
||||
connection: mist.WebsocketConnection,
|
||||
) -> mist.Next(Socket(msg), SocketMessage(msg)) {
|
||||
case message {
|
||||
mist.Text(json) -> {
|
||||
case json.parse(json, server_component.runtime_message_decoder()) {
|
||||
Ok(runtime_message) -> lustre.send(state.component, runtime_message)
|
||||
Error(_) -> Nil
|
||||
}
|
||||
|
||||
mist.continue(state)
|
||||
}
|
||||
|
||||
mist.Binary(_) -> {
|
||||
mist.continue(state)
|
||||
}
|
||||
|
||||
mist.Custom(client_message) -> {
|
||||
let json = server_component.client_message_to_json(client_message)
|
||||
let assert Ok(_) = mist.send_text_frame(connection, json.to_string(json))
|
||||
|
||||
mist.continue(state)
|
||||
}
|
||||
|
||||
mist.Closed | mist.Shutdown -> {
|
||||
server_component.deregister_subject(state.self)
|
||||
|> lustre.send(to: state.component)
|
||||
|
||||
mist.stop()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn close_socket(state: Socket(msg)) -> Nil {
|
||||
server_component.deregister_subject(state.self)
|
||||
|> lustre.send(to: state.component)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue