aboutsummaryrefslogtreecommitdiff
path: root/src/lustre/cli/try.gleam
diff options
context:
space:
mode:
Diffstat (limited to 'src/lustre/cli/try.gleam')
-rw-r--r--src/lustre/cli/try.gleam108
1 files changed, 108 insertions, 0 deletions
diff --git a/src/lustre/cli/try.gleam b/src/lustre/cli/try.gleam
new file mode 100644
index 0000000..42f3854
--- /dev/null
+++ b/src/lustre/cli/try.gleam
@@ -0,0 +1,108 @@
+// IMPORTS ---------------------------------------------------------------------
+
+import gleam_community/ansi
+import gleam/int
+import gleam/io
+import gleam/result
+import glint.{type Command, CommandInput}
+import glint/flag
+import lustre/cli/project
+
+// TYPES -----------------------------------------------------------------------
+
+type Options {
+ /// It's important to remember that for Erlang, Gleam records have their field
+ /// names erased and they degenerate to tuples. This means that the order of
+ /// the fields is important!
+ Options(name: String, host: String, port: Int, no_styles: Bool)
+}
+
+type Error {
+ CompileError
+}
+
+// MAIN ------------------------------------------------------------------------
+
+pub fn run() -> Command(Nil) {
+ glint.command(fn(input) {
+ let CommandInput(_, flags, _) = input
+ let assert Ok(port) = flag.get_int(flags, port_flag_name)
+ let assert Ok(host) = flag.get_string(flags, host_flag_name)
+ let assert Ok(no_styles) = flag.get_bool(flags, no_styles_flag_name)
+
+ let result = {
+ let compile = result.replace_error(project.build(), CompileError)
+ use compiled <- result.try(compile)
+ let configuration = project.read_configuration(compiled)
+ let options = Options(configuration.name, host, port, no_styles)
+ serve(options, on_start(host, _), on_port_taken)
+ Ok(Nil)
+ }
+
+ case result {
+ Ok(_) -> Nil
+ Error(error) -> explain(error)
+ }
+ })
+ |> glint.flag(host_flag_name, host_flag())
+ |> glint.flag(port_flag_name, port_flag())
+ |> glint.flag(no_styles_flag_name, no_styles_flag())
+}
+
+// UTILS -----------------------------------------------------------------------
+
+fn explain(error: Error) -> Nil {
+ case error {
+ CompileError -> Nil
+ }
+}
+
+// GLINT FLAGS -----------------------------------------------------------------
+
+const host_flag_name = "host"
+
+fn host_flag() {
+ flag.string()
+ |> flag.default("localhost")
+ |> flag.description("The host to run the server on.")
+}
+
+const port_flag_name = "port"
+
+fn port_flag() {
+ flag.int()
+ |> flag.default(1234)
+ |> flag.description("The port to run the server on.")
+}
+
+const no_styles_flag_name = "no-styles"
+
+fn no_styles_flag() {
+ flag.bool()
+ |> flag.default(False)
+ |> flag.description("When false, lustre/ui's styles will not be included.")
+}
+
+// UTILS -----------------------------------------------------------------------
+
+fn on_start(host: String, port: Int) -> Nil {
+ let address = "http://" <> host <> ":" <> int.to_string(port)
+ io.println("✨ Server has been started at " <> ansi.bold(address))
+}
+
+fn on_port_taken(port) -> Nil {
+ io.println(
+ "🚨 Port "
+ <> ansi.bold(int.to_string(port))
+ <> " already in use, using next available port",
+ )
+}
+
+// EXTERNALS -------------------------------------------------------------------
+
+@external(erlang, "lustre_try_ffi", "serve")
+fn serve(
+ options: Options,
+ on_start: fn(Int) -> Nil,
+ on_port_taken: fn(Int) -> Nil,
+) -> Nil