this repo has no description
lustre frontent oat-ui gleam
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

:construction: add mist server

+157 -2
+36
Containerfile
··· 1 + ARG GLEAM_VERSION=v1.15.4 2 + ARG ERLANG_VERSION=28.4.2 3 + 4 + # builder stage ---------------------------------------------------------------- 5 + FROM ghcr.io/gleam-lang/gleam:${GLEAM_VERSION}-scratch as gleam 6 + FROM docker.io/erlang:${ERLANG_VERSION}-alpine as builder 7 + 8 + COPY --from=gleam /bin/gleam /bin/gleam 9 + 10 + COPY ./shared /build/shared 11 + COPY ./client /build/client 12 + COPY ./server /build/server 13 + 14 + WORKDIR /build/shared 15 + RUN gleam deps download 16 + 17 + WORKDIR /build/client 18 + RUN gleam deps download 19 + 20 + WORKDIR /build/server 21 + RUN gleam deps download 22 + 23 + WORKDIR /build/client 24 + RUN gleam run -m lustre/dev build 25 + 26 + WORKDIR /build/server 27 + RUN gleam export erlang-shipment 28 + 29 + # runtime stage ---------------------------------------------------------------- 30 + FROM docker.io/erlang:${ERLANG_VERSION}-alpine 31 + COPY --from=builder /build/server/build/erlang-shipment /app 32 + 33 + EXPOSE 8000 34 + WORKDIR /app 35 + ENTRYPOINT ["/app/entrypoint.sh"] 36 + CMD ["run"]
+6
client/justfile
··· 1 + @_default: 2 + just --list 3 + 4 + # Build CSS and JS runtime 5 + build: 6 + gleam run -m lustre/dev build
+9
justfile
··· 1 + mod client 2 + mod server 3 + mod shared 4 + 5 + set quiet 6 + 7 + # List available recipes 8 + _default: 9 + just --list
+3
server/gleam.toml
··· 18 18 wisp = ">= 2.2.2 and < 3.0.0" 19 19 mist = ">= 6.0.3 and < 7.0.0" 20 20 gleam_otp = ">= 1.2.0 and < 2.0.0" 21 + gleam_erlang = ">= 1.3.0 and < 2.0.0" 22 + filepath = ">= 1.1.2 and < 2.0.0" 23 + envoy = ">= 1.2.0 and < 2.0.0" 21 24 22 25 [dev_dependencies] 23 26 gleeunit = ">= 1.0.0 and < 2.0.0"
+3
server/manifest.toml
··· 27 27 ] 28 28 29 29 [requirements] 30 + envoy = { version = ">= 1.2.0 and < 2.0.0" } 31 + filepath = { version = ">= 1.1.2 and < 2.0.0" } 32 + gleam_erlang = { version = ">= 1.3.0 and < 2.0.0" } 30 33 gleam_otp = { version = ">= 1.2.0 and < 2.0.0" } 31 34 gleam_stdlib = { version = ">= 0.44.0 and < 2.0.0" } 32 35 gleeunit = { version = ">= 1.0.0 and < 2.0.0" }
+24 -2
server/src/server.gleam
··· 1 - import gleam/io 1 + import envoy 2 + import filepath as path 3 + import gleam/erlang/process 4 + import gleam/result 5 + import server/context.{Context} 6 + import server/router 7 + import server/supervision_tree 8 + import wisp 2 9 3 10 pub fn main() -> Nil { 4 - io.println("Hello from server!") 11 + wisp.configure_logger() 12 + 13 + let assert Ok(static_directory) = static_directory() 14 + let assert Ok(secret_key) = envoy.get("SECRET_KEY") 15 + 16 + let ctx = Context(static_directory:, secret_key:) 17 + let handler = router.handle_request(_, ctx) 18 + let assert Ok(_) = supervision_tree.start(handler, secret_key) 19 + 20 + process.sleep_forever() 21 + } 22 + 23 + /// Path to the application priv directory 24 + pub fn static_directory() -> Result(String, Nil) { 25 + use priv <- result.map(wisp.priv_directory("server")) 26 + path.join(priv, "static") 5 27 }
+8
server/src/server/context.gleam
··· 1 + pub type Context { 2 + Context( 3 + /// Path to the application's priv directory 4 + static_directory: String, 5 + /// Secret used for hashing cookies and passwords 6 + secret_key: String, 7 + ) 8 + }
+27
server/src/server/root.gleam
··· 1 + import lustre/attribute as attr 2 + import lustre/element 3 + import lustre/element/html 4 + import server/context.{type Context} 5 + import wisp.{type Request, type Response} 6 + 7 + pub fn handle_request(_req: Request, _ctx: Context) -> Response { 8 + let viewport_meta = 9 + html.meta([ 10 + attr.name("viewport"), 11 + attr.content("width=device-width, initial-scale=1"), 12 + ]) 13 + 14 + let html_head = 15 + html.head([], [ 16 + html.title([], "BFD"), 17 + viewport_meta, 18 + html.script([attr.type_("module"), attr.src("/static/client.js")], ""), 19 + html.link([attr.rel("stylesheet"), attr.href("/static/client.css")]), 20 + ]) 21 + 22 + let html_body = html.body([attr.id("app")], []) 23 + 24 + html.html([], [html_head, html_body]) 25 + |> element.to_document_string() 26 + |> wisp.html_response(200) 27 + }
+23
server/src/server/router.gleam
··· 1 + import server/context.{type Context} 2 + import server/root 3 + import wisp.{type Request, type Response} 4 + 5 + pub fn handle_request(req: Request, ctx: Context) -> Response { 6 + use req <- middleware(req, ctx) 7 + root.handle_request(req, ctx) 8 + } 9 + 10 + fn middleware( 11 + req: Request, 12 + ctx: Context, 13 + next: fn(Request) -> Response, 14 + ) -> Response { 15 + let req = wisp.method_override(req) 16 + use <- wisp.log_request(req) 17 + use <- wisp.rescue_crashes() 18 + use req <- wisp.handle_head(req) 19 + use req <- wisp.csrf_known_header_protection(req) 20 + use <- wisp.serve_static(req, "/static", ctx.static_directory) 21 + 22 + next(req) 23 + }
+18
server/src/server/supervision_tree.gleam
··· 1 + import gleam/otp/static_supervisor as supervisor 2 + import mist 3 + import wisp.{type Request, type Response} 4 + import wisp/wisp_mist 5 + 6 + pub fn start(http_handler: fn(Request) -> Response, secret_key: String) { 7 + let handler = wisp_mist.handler(http_handler, secret_key) 8 + 9 + let mist_builder = 10 + handler 11 + |> mist.new() 12 + |> mist.bind("0.0.0.0") 13 + |> mist.port(8000) 14 + 15 + supervisor.new(supervisor.OneForOne) 16 + |> supervisor.add(mist.supervised(mist_builder)) 17 + |> supervisor.start 18 + }