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(OYN) :: {signal, binary(), OYN, fun((OYN) -> OYN)}.
-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>>
),
_pipe@9 = gleam@http@response:new(200),
_pipe@10 = gleam@http@response:set_body(
_pipe@9,
{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/binary>>/binary,
".mjs'
client()
</script>
</head>
<body></body>
</html>
"/utf8>>
)}
),
gleam@http@response:set_header(
_pipe@10,
<<"content-type"/utf8>>,
<<"text/html"/utf8>>
).
-spec decode_string(binary(), handler(OZB)) -> {ok, OZB} | {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@2 = (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),
_pipe@1 = gleam@http@response:set_body(
_pipe,
{bytes, gleam_stdlib:wrap_list(Response_string)}
),
gleam@http@response:set_header(
_pipe@1,
<<"Access-Control-Allow-Origin"/utf8>>,
<<"*"/utf8>>
)
end,
{ok, R}
end
)),
gleam@result:lazy_unwrap(
_pipe@2,
fun() -> _pipe@3 = gleam@http@response:new(400),
_pipe@4 = gleam@http@response:set_body(
_pipe@3,
{bytes,
gleam_stdlib:wrap_list(
<<"Invalid server signal call"/utf8>>
)}
),
gleam@http@response:set_header(
_pipe@4,
<<"Access-Control-Allow-Origin"/utf8>>,
<<"*"/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} ->
case begin
_pipe@1 = Extension@1,
gleam@string:lowercase(_pipe@1)
end of
<<"aac"/utf8>> ->
<<"audio/aac"/utf8>>;
<<"abw"/utf8>> ->
<<"application/x-abiword"/utf8>>;
<<"apng"/utf8>> ->
<<"image/apng"/utf8>>;
<<"arc"/utf8>> ->
<<"application/x-freearc"/utf8>>;
<<"avif"/utf8>> ->
<<"image/avif"/utf8>>;
<<"avi"/utf8>> ->
<<"video/x-msvideo"/utf8>>;
<<"azw"/utf8>> ->
<<"application/vnd.amazon.ebook"/utf8>>;
<<"bin"/utf8>> ->
<<"application/octet-stream"/utf8>>;
<<"bmp"/utf8>> ->
<<"image/bmp"/utf8>>;
<<"bz"/utf8>> ->
<<"application/x-bzip"/utf8>>;
<<"bz2"/utf8>> ->
<<"application/x-bzip2"/utf8>>;
<<"cda"/utf8>> ->
<<"application/x-cdf"/utf8>>;
<<"csh"/utf8>> ->
<<"application/x-csh"/utf8>>;
<<"css"/utf8>> ->
<<"text/css"/utf8>>;
<<"csv"/utf8>> ->
<<"text/csv"/utf8>>;
<<"doc"/utf8>> ->
<<"application/msword"/utf8>>;
<<"docx"/utf8>> ->
<<"application/vnd.openxmlformats-officedocument.wordprocessingml.document"/utf8>>;
<<"eot"/utf8>> ->
<<"application/vnd.ms-fontobject"/utf8>>;
<<"epub"/utf8>> ->
<<"application/epub+zip"/utf8>>;
<<"gz"/utf8>> ->
<<"application/gzip"/utf8>>;
<<"gif"/utf8>> ->
<<"image/gif"/utf8>>;
<<"htm"/utf8>> ->
<<"text/html"/utf8>>;
<<"html"/utf8>> ->
<<"text/html"/utf8>>;
<<"ico"/utf8>> ->
<<"image/vnd.microsoft.icon"/utf8>>;
<<"ics"/utf8>> ->
<<"text/calendar"/utf8>>;
<<"jar"/utf8>> ->
<<"application/java-archive"/utf8>>;
<<"jpeg"/utf8>> ->
<<"image/jpeg"/utf8>>;
<<"jpg"/utf8>> ->
<<"image/jpeg"/utf8>>;
<<"js"/utf8>> ->
<<"text/javascript"/utf8>>;
<<"json"/utf8>> ->
<<"application/json"/utf8>>;
<<"jsonld"/utf8>> ->
<<"application/ld+json"/utf8>>;
<<"mid"/utf8>> ->
<<"audio/midi"/utf8>>;
<<"midi"/utf8>> ->
<<"audio/midi"/utf8>>;
<<"mjs"/utf8>> ->
<<"text/javascript"/utf8>>;
<<"mp3"/utf8>> ->
<<"audio/mpeg"/utf8>>;
<<"mp4"/utf8>> ->
<<"video/mp4"/utf8>>;
<<"mpeg"/utf8>> ->
<<"video/mpeg"/utf8>>;
<<"mpkg"/utf8>> ->
<<"application/vnd.apple.installer+xml"/utf8>>;
<<"odp"/utf8>> ->
<<"application/vnd.oasis.opendocument.presentation"/utf8>>;
<<"ods"/utf8>> ->
<<"application/vnd.oasis.opendocument.spreadsheet"/utf8>>;
<<"odt"/utf8>> ->
<<"application/vnd.oasis.opendocument.text"/utf8>>;
<<"oga"/utf8>> ->
<<"audio/ogg"/utf8>>;
<<"ogv"/utf8>> ->
<<"video/ogg"/utf8>>;
<<"ogx"/utf8>> ->
<<"application/ogg"/utf8>>;
<<"opus"/utf8>> ->
<<"audio/opus"/utf8>>;
<<"otf"/utf8>> ->
<<"font/otf"/utf8>>;
<<"png"/utf8>> ->
<<"image/png"/utf8>>;
<<"pdf"/utf8>> ->
<<"application/pdf"/utf8>>;
<<"php"/utf8>> ->
<<"application/x-httpd-php"/utf8>>;
<<"ppt"/utf8>> ->
<<"application/vnd.ms-powerpoint"/utf8>>;
<<"pptx"/utf8>> ->
<<"application/vnd.openxmlformats-officedocument.presentationml.presentation"/utf8>>;
<<"rar"/utf8>> ->
<<"application/vnd.rar"/utf8>>;
<<"rtf"/utf8>> ->
<<"application/rtf"/utf8>>;
<<"sh"/utf8>> ->
<<"application/x-sh"/utf8>>;
<<"svg"/utf8>> ->
<<"image/svg+xml"/utf8>>;
<<"tar"/utf8>> ->
<<"application/x-tar"/utf8>>;
<<"tif"/utf8>> ->
<<"image/tiff"/utf8>>;
<<"tiff"/utf8>> ->
<<"image/tiff"/utf8>>;
<<"ts"/utf8>> ->
<<"video/mp2t"/utf8>>;
<<"ttf"/utf8>> ->
<<"font/ttf"/utf8>>;
<<"txt"/utf8>> ->
<<"text/plain"/utf8>>;
<<"vsd"/utf8>> ->
<<"application/vnd.visio"/utf8>>;
<<"wav"/utf8>> ->
<<"audio/wav"/utf8>>;
<<"weba"/utf8>> ->
<<"audio/webm"/utf8>>;
<<"webm"/utf8>> ->
<<"video/webm"/utf8>>;
<<"webp"/utf8>> ->
<<"image/webp"/utf8>>;
<<"woff"/utf8>> ->
<<"font/woff"/utf8>>;
<<"woff2"/utf8>> ->
<<"font/woff2"/utf8>>;
<<"xhtml"/utf8>> ->
<<"application/xhtml+xml"/utf8>>;
<<"xls"/utf8>> ->
<<"application/vnd.ms-excel"/utf8>>;
<<"xlsx"/utf8>> ->
<<"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"/utf8>>;
<<"xml"/utf8>> ->
<<"application/xml"/utf8>>;
<<"xul"/utf8>> ->
<<"application/vnd.mozilla.xul+xml"/utf8>>;
<<"zip"/utf8>> ->
<<"application/zip"/utf8>>;
<<".3gp"/utf8>> ->
<<"video/3gpp"/utf8>>;
<<".3g2"/utf8>> ->
<<"video/3gpp2"/utf8>>;
<<".7z"/utf8>> ->
<<"application/x-7z-compressed"/utf8>>;
_ ->
<<"text/plain"/utf8>>
end;
{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 => 40})
end,
gleam_erlang_ffi:sleep_forever().