Lustre's CLI and development tooling: zero-config dev server, bundling, and scaffolding.
at main 2.7 kB view raw
1import filepath 2import gleam/bool 3import gleam/bytes_builder 4import gleam/http/request.{type Request, Request} 5import gleam/http/response.{type Response} 6import gleam/httpc 7import gleam/option.{type Option, None, Some} 8import gleam/result 9import gleam/string 10import gleam/uri.{type Uri} 11import glint 12import lustre_dev_tools/cli.{type Cli, do} 13import lustre_dev_tools/cli/flag 14import lustre_dev_tools/error.{IncompleteProxy, InvalidProxyTarget} 15import mist 16import tom 17 18// TYPES ----------------------------------------------------------------------- 19 20pub type Proxy { 21 Proxy(from: String, to: Uri) 22} 23 24// 25 26pub fn middleware( 27 req: Request(mist.Connection), 28 proxy: Option(Proxy), 29 k: fn() -> Response(mist.ResponseData), 30) -> Response(mist.ResponseData) { 31 case proxy { 32 None -> k() 33 Some(Proxy(from, to)) -> { 34 use <- bool.lazy_guard(!string.starts_with(req.path, from), k) 35 let internal_error = 36 response.new(500) 37 |> response.set_body(mist.Bytes(bytes_builder.new())) 38 39 let assert Some(host) = to.host 40 let path = 41 req.path 42 |> string.replace(from, "") 43 |> filepath.join(to.path, _) 44 let assert Ok(req) = mist.read_body(req, 100 * 1024 * 1024) 45 46 Request(..req, host: host, port: to.port, path: path) 47 |> httpc.send_bits 48 |> result.map(response.map(_, bytes_builder.from_bit_array)) 49 |> result.map(response.map(_, mist.Bytes)) 50 |> result.unwrap(internal_error) 51 } 52 } 53} 54 55pub fn get() -> Cli(Option(Proxy)) { 56 use from <- do(get_proxy_from()) 57 use to <- do(get_proxy_to()) 58 59 case from, to { 60 Some(from), Some(to) -> cli.return(Some(Proxy(from, to))) 61 Some(_), None -> cli.throw(IncompleteProxy(["proxy-to"])) 62 None, Some(_) -> cli.throw(IncompleteProxy(["proxy-from"])) 63 None, None -> cli.return(None) 64 } 65} 66 67fn get_proxy_from() -> Cli(Option(String)) { 68 use flags <- do(cli.get_flags()) 69 use config <- do(cli.get_config()) 70 71 let flag = result.nil_error(glint.get_flag(flags, flag.proxy_from())) 72 let toml = 73 result.nil_error( 74 tom.get_string(config.toml, ["lustre-dev", "start", "proxy", "from"]), 75 ) 76 77 result.or(flag, toml) 78 |> option.from_result 79 |> cli.return 80} 81 82fn get_proxy_to() -> Cli(Option(Uri)) { 83 use flags <- do(cli.get_flags()) 84 use config <- do(cli.get_config()) 85 86 let flag = result.nil_error(glint.get_flag(flags, flag.proxy_to())) 87 let toml = 88 result.nil_error( 89 tom.get_string(config.toml, ["lustre-dev", "start", "proxy", "to"]), 90 ) 91 92 let from = result.or(flag, toml) 93 use <- bool.guard(from == Error(Nil), cli.return(None)) 94 let assert Ok(from) = from 95 96 case uri.parse(from) { 97 Ok(from) -> cli.return(Some(from)) 98 Error(_) -> cli.throw(InvalidProxyTarget(from)) 99 } 100}