Packages

A server side for glare, the web framework based on SolidJS, adding server signals and more.

Current section

Files

Jump to
meadow src server.erl
Raw

src/server.erl

-module(server).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([server/1]).
-export_type([handler/1]).
-type handler(QDW) :: {signal, binary(), QDW, fun((QDW) -> QDW)}.
-spec serve_page(
gleam@http@request:request(mist@internal@http:connection()),
list(binary())
) -> gleam@http@response:response(mist:response_data()).
serve_page(_, Path) ->
Project_name = begin
_pipe = simplifile:current_directory(),
_pipe@1 = gleam@result:nil_error(_pipe),
_pipe@4 = gleam@result:then(_pipe@1, fun(Dir) -> _pipe@2 = Dir,
_pipe@3 = gleam@string:split(_pipe@2, <<"/build"/utf8>>),
gleam@list:first(_pipe@3) end),
_pipe@7 = gleam@result:then(_pipe@4, fun(Dir@1) -> _pipe@5 = Dir@1,
_pipe@6 = gleam@string:split(_pipe@5, <<"/"/utf8>>),
gleam@list:last(_pipe@6) end),
_pipe@8 = gleam@result:nil_error(_pipe@7),
gleam@result:unwrap(_pipe@8, <<"PROJECT_NAME_ERROR"/utf8>>)
end,
File_path = gleam@string:join(
[<<"meadow"/utf8>>, Project_name, <<"web"/utf8>> | Path],
<<"/"/utf8>>
),
File_path@1 = case begin
_pipe@9 = Path,
gleam@list:is_empty(_pipe@9)
end of
true ->
<<File_path/binary, "/index"/utf8>>;
false ->
File_path
end,
_pipe@10 = gleam@http@response:new(200),
_pipe@11 = gleam@http@response:set_body(
_pipe@10,
{bytes,
gleam_stdlib:wrap_list(
<<<<"<!DOCTYPE html>
<html lang=\"en\">
<head>
<meta charset=\"UTF-8\" />
<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />
<title>Index</title>
<script type=\"module\">
import { client } from '/"/utf8,
File_path@1/binary>>/binary,
".mjs'
client()
</script>
</head>
<body></body>
</html>
"/utf8>>
)}
),
gleam@http@response:set_header(
_pipe@11,
<<"content-type"/utf8>>,
<<"text/html"/utf8>>
).
-spec decode_string(binary(), handler(QEK)) -> {ok, QEK} | {error, nil}.
decode_string(Request_string, Handler) ->
_pipe@10 = case begin
_pipe = gleam@dynamic:from(erlang:element(3, Handler)),
gleam@dynamic:classify(_pipe)
end of
<<"Bool"/utf8>> ->
_pipe@1 = (Request_string =:= <<"true"/utf8>>),
_pipe@2 = gleam@dynamic:from(_pipe@1),
{ok, _pipe@2};
<<"Int"/utf8>> ->
_pipe@3 = gleam@int:parse(Request_string),
gleam@result:map(_pipe@3, fun gleam@dynamic:from/1);
<<"Float"/utf8>> ->
_pipe@4 = gleam@float:parse(Request_string),
gleam@result:map(_pipe@4, fun gleam@dynamic:from/1);
<<"List"/utf8>> ->
{ok,
gleam@dynamic:from(
begin
_pipe@5 = Request_string,
_pipe@6 = gleam@string:drop_left(_pipe@5, 1),
_pipe@7 = gleam@string:drop_right(_pipe@6, 1),
_pipe@8 = gleam@string:split(_pipe@7, <<","/utf8>>),
_pipe@9 = gleam@list:map(
_pipe@8,
fun gleam@string:trim/1
),
gleam@list:map(
_pipe@9,
fun(_capture) ->
decode_string(_capture, Handler)
end
)
end
)};
<<"String"/utf8>> ->
{ok, gleam@dynamic:from(Request_string)};
_ ->
{error, nil}
end,
gleam@result:map(_pipe@10, fun gleam@dynamic:unsafe_coerce/1).
-spec handle_server_signal(binary(), handler(any())) -> gleam@http@response:response(mist:response_data()).
handle_server_signal(Request_string, Handler) ->
_pipe@1 = (gleam@result:'try'(
decode_string(Request_string, Handler),
fun(Request_value) ->
Response_value = (erlang:element(4, Handler))(Request_value),
Response_string = gleam@erlang:format(Response_value),
R = begin
_pipe = gleam@http@response:new(200),
gleam@http@response:set_body(
_pipe,
{bytes, gleam_stdlib:wrap_list(Response_string)}
)
end,
{ok, R}
end
)),
gleam@result:lazy_unwrap(
_pipe@1,
fun() -> _pipe@2 = gleam@http@response:new(400),
gleam@http@response:set_body(
_pipe@2,
{bytes,
gleam_stdlib:wrap_list(
<<"Invalid server signal call"/utf8>>
)}
) end
).
-spec get_content_type(binary()) -> binary().
get_content_type(File_path) ->
case gleam@string:split(File_path, <<"."/utf8>>) of
[_ | Extension] ->
case begin
_pipe = Extension,
gleam@list:last(_pipe)
end of
{ok, Extension@1} ->
_pipe@1 = Extension@1,
_pipe@2 = gleam@string:lowercase(_pipe@1),
marceau:extension_to_mime_type(_pipe@2);
{error, _} ->
<<"text/plain"/utf8>>
end;
_ ->
<<"text/plain"/utf8>>
end.
-spec serve_file(
gleam@http@request:request(mist@internal@http:connection()),
list(binary())
) -> gleam@http@response:response(mist:response_data()).
serve_file(_, Path) ->
File_path = gleam@string:join(
[<<"build"/utf8>>, <<"dev"/utf8>>, <<"javascript"/utf8>> | Path],
<<"/"/utf8>>
),
_pipe = simplifile:verify_is_file(File_path),
_pipe@1 = gleam@result:nil_error(_pipe),
_pipe@3 = gleam@result:then(
_pipe@1,
fun(_) -> _pipe@2 = mist:send_file(File_path, 0, none),
gleam@result:nil_error(_pipe@2) end
),
_pipe@6 = gleam@result:map(
_pipe@3,
fun(File) ->
Content_type = get_content_type(File_path),
_pipe@4 = gleam@http@response:new(200),
_pipe@5 = gleam@http@response:prepend_header(
_pipe@4,
<<"content-type"/utf8>>,
Content_type
),
gleam@http@response:set_body(_pipe@5, File)
end
),
gleam@result:lazy_unwrap(
_pipe@6,
fun() -> _pipe@7 = gleam@http@response:new(404),
gleam@http@response:set_body(
_pipe@7,
{bytes, gleam@bytes_builder:new()}
) end
).
-spec server(list(handler(any()))) -> nil.
server(Handlers) ->
Not_found = begin
_pipe = gleam@http@response:new(404),
gleam@http@response:set_body(_pipe, {bytes, gleam@bytes_builder:new()})
end,
_assert_subject = begin
_pipe@1 = fun(Req) -> case gleam@http@request:path_segments(Req) of
[<<"server-signal"/utf8>>, Name, Value] ->
case gleam@list:find(
Handlers,
fun(H) -> erlang:element(2, H) =:= Name end
) of
{error, _} ->
Not_found;
{ok, Handler} ->
handle_server_signal(Value, Handler)
end;
[<<"meadow"/utf8>> | Segments] ->
serve_file(Req, Segments);
Segments@1 ->
serve_page(Req, Segments@1)
end end,
_pipe@2 = mist:new(_pipe@1),
_pipe@3 = mist:port(_pipe@2, 3000),
mist:start_http(_pipe@3)
end,
{ok, _} = case _assert_subject of
{ok, _} -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"server"/utf8>>,
function => <<"server"/utf8>>,
line => 42})
end,
gleam_erlang_ffi:sleep_forever().