Current section

Files

Jump to
sprocket src docs.gleam
Raw

src/docs.gleam

import gleam/int
import gleam/string
import gleam/option.{None}
import gleam/result
import gleam/bit_string
import gleam/otp/actor
import gleam/erlang/os
import gleam/erlang/process
import gleam/http/service.{Service}
import gleam/http/request.{Request}
import gleam/http/response.{Response}
import gleam/http.{Get}
import gleam/bit_builder.{BitBuilder}
import mist.{Connection, ResponseData}
import sprocket/cassette.{Cassette, LiveService}
import docs/routes
import docs/app_context.{AppContext}
import docs/utils/logger
pub fn main() {
logger.configure_backend()
let port = load_port()
let ca = cassette.start(None)
let router = routes.stack(AppContext(ca))
fn(req: Request(Connection)) -> Response(ResponseData) {
case req.method, request.path_segments(req) {
Get, ["live"] -> live_service(req, ca)
_, _ -> http_service(req, router)
}
}
|> mist.new
|> mist.port(port)
|> mist.start_http
string.concat(["Listening on localhost:", int.to_string(port), " ✨"])
|> logger.info
process.sleep_forever()
}
fn live_service(req: Request(Connection), ca: Cassette) {
let live_service = cassette.live_service(ca)
let selector = process.new_selector()
mist.websocket(req)
|> mist.with_state(Nil)
|> mist.selecting(selector)
|> mist.on_message(fn(state, conn, message) {
handle_ws_message(state, conn, message, live_service)
})
|> mist.upgrade
}
fn handle_ws_message(state: Nil, conn, message, live_service) {
let LiveService(id, on_msg, _on_init, on_close) = live_service
case message {
mist.Text(msg) -> {
let assert Ok(msg) = bit_string.to_string(msg)
let _ =
on_msg(
msg,
id,
fn(msg) {
let assert Ok(_) =
mist.send_text_frame(conn, bit_string.from_string(msg))
Ok(Nil)
},
)
actor.continue(state)
}
mist.Closed | mist.Shutdown -> {
let _ = on_close(id)
actor.Stop(process.Normal)
}
_ -> {
logger.info("Received unsupported websocket message type")
actor.continue(state)
}
}
}
fn http_service(
req: Request(Connection),
router: Service(BitString, BitBuilder),
) -> Response(ResponseData) {
req
|> mist.read_body(1024 * 1024 * 10)
|> result.map(fn(http_req: Request(BitString)) {
http_req
|> router()
|> mist_response()
})
|> result.unwrap(
response.new(500)
|> response.set_body(mist.Bytes(bit_builder.new())),
)
}
fn mist_response(response: Response(BitBuilder)) -> Response(ResponseData) {
response.new(response.status)
|> response.set_body(mist.Bytes(response.body))
}
fn load_port() -> Int {
os.get_env("PORT")
|> result.then(int.parse)
|> result.unwrap(3000)
}