aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHayleigh Thompson <me@hayleigh.dev>2023-12-06 22:01:42 +0000
committerHayleigh Thompson <me@hayleigh.dev>2023-12-06 22:01:42 +0000
commit507257ef238fa59687d33893596539a1ee546426 (patch)
treee3003a17627306def28693fde78697748c572391
parent1231c522f4b85b8e1b224f8d14bba77166aa5c7e (diff)
downloadlustre-507257ef238fa59687d33893596539a1ee546426.tar.gz
lustre-507257ef238fa59687d33893596539a1ee546426.zip
:sparkles: Create a simple preview server for trying out lustre.
-rw-r--r--src/http.ffi.mjs90
-rw-r--r--src/http_ffi.erl76
-rw-r--r--src/lustre/try.gleam7
3 files changed, 173 insertions, 0 deletions
diff --git a/src/http.ffi.mjs b/src/http.ffi.mjs
new file mode 100644
index 0000000..56fd950
--- /dev/null
+++ b/src/http.ffi.mjs
@@ -0,0 +1,90 @@
+import { readFileSync } from "node:fs";
+import * as Fs from "node:fs/promises";
+import * as Http from "node:http";
+import * as Path from "node:path";
+import * as Process from "node:process";
+
+const cwd = Process.cwd();
+const root = Path.join(cwd, "build/dev/javascript");
+const toml = readFileSync(Path.join(cwd, "gleam.toml"), "utf-8");
+const name = toml.match(/name *= *"(.+)"/)[1];
+
+const html = `<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>Lustre preview server</title>
+
+ <script type="module">
+ import { main } from "./${name}/${name}.mjs"
+
+ document.addEventListener("DOMContentLoaded", () => {
+ main();
+ });
+ </script>
+</head>
+<body>
+ <div data-lustre-app></div>
+</body>
+</html>`;
+
+const server = Http.createServer((req, res) => {
+ switch (true) {
+ case req.url === "/": {
+ res.setHeader("Content-Type", "text/html");
+ res.statusCode = 200;
+ res.end(html);
+
+ break;
+ }
+
+ case req.url.endsWith(".js"):
+ case req.url.endsWith(".mjs"): {
+ Fs.readFile(Path.join(root, req.url), "utf-8")
+ .then((src) => {
+ res.setHeader("Content-Type", "application/javascript");
+ res.statusCode = 200;
+ res.end(src);
+ })
+ .catch((err) => {
+ res.statusCode = 404;
+ res.end(err);
+ });
+
+ break;
+ }
+
+ case req.url.endsWith(".css"): {
+ Fs.readFile(Path.join(root, req.url), "utf-8")
+ .then((src) => {
+ res.setHeader("Content-Type", "text/css");
+ res.statusCode = 200;
+ res.end(src);
+ })
+ .catch((err) => {
+ res.statusCode = 404;
+ res.end(err);
+ });
+
+ break;
+ }
+
+ default: {
+ Fs.readFile(Path.join(root, req.url), "utf-8")
+ .then((src) => {
+ res.setHeader("Content-Type", "text/plain");
+ res.statusCode = 200;
+ res.end(src);
+ })
+ .catch((err) => {
+ res.statusCode = 404;
+ res.end(err);
+ });
+ }
+ }
+});
+
+export const serve = (port) => {
+ server.listen(port, "localhost");
+};
diff --git a/src/http_ffi.erl b/src/http_ffi.erl
new file mode 100644
index 0000000..507ee06
--- /dev/null
+++ b/src/http_ffi.erl
@@ -0,0 +1,76 @@
+-module(http_ffi).
+-export([serve/1]).
+
+serve(Port) ->
+ {ok, Pattern} = re:compile("name *= *\"(?<Name>.+)\""),
+ {ok, Toml} = file:read_file("gleam.toml"),
+ {match, [Name]} = re:run(Toml, Pattern, [{capture, all_names, binary}]),
+
+ Html =
+ <<
+ "<!DOCTYPE html>\n"
+ "<html lang=\"en\">\n"
+ "<head>\n"
+ " <meta charset=\"UTF-8\">\n"
+ " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n"
+ " <title>Lustre preview server</title>\n"
+ "\n"
+ " <script type=\"module\">\n"
+ " import { main } from './",
+ Name/binary,
+ "/",
+ Name/binary,
+ ".mjs'\n"
+ "\n"
+ " document.addEventListener(\"DOMContentLoaded\", () => {\n"
+ " main();\n"
+ " });\n"
+ " </script>\n"
+ "</head>\n"
+ "<body>\n"
+ " <div data-lustre-app></div>\n"
+ "</body>\n"
+ "</html>"
+ >>,
+
+ file:write_file("build/dev/javascript/index.html", Html),
+
+ AbsPath =
+ string:trim(
+ filename:absname("build/dev/javascript"), trailing, "/."
+ ),
+
+ inets:start(),
+ Address = {127, 0, 0, 1},
+
+ {ok, Pid} =
+ httpd:start_service([
+ {bind_address, Address},
+ {document_root, AbsPath},
+ {server_root, AbsPath},
+ {directory_index, ["index.html"]},
+ {server_name, "localhost"},
+ {port, Port},
+ {default_type, "text/html"},
+ {mime_types, mime_types()},
+ {modules, [mod_alias, mod_dir, mod_get]}
+ ]),
+
+ receive
+ {From, shutdown} ->
+ ok = httpd:stop_service(Pid),
+ From ! done
+ end.
+
+mime_types() ->
+ [
+ {"html", "text/html"},
+ {"htm", "text/html"},
+ {"js", "text/javascript"},
+ {"mjs", "text/javascript"},
+ {"css", "text/css"},
+ {"gif", "image/gif"},
+ {"jpg", "image/jpeg"},
+ {"jpeg", "image/jpeg"},
+ {"png", "image/png"}
+ ].
diff --git a/src/lustre/try.gleam b/src/lustre/try.gleam
new file mode 100644
index 0000000..5984f30
--- /dev/null
+++ b/src/lustre/try.gleam
@@ -0,0 +1,7 @@
+pub fn main() {
+ serve(1234)
+}
+
+@external(erlang, "http_ffi", "serve")
+@external(javascript, "../http.ffi.mjs", "serve")
+fn serve(port: Int) -> Nil