stellation_backend_cli/
cli.rs1use std::env;
2use std::net::ToSocketAddrs;
3use std::path::PathBuf;
4
5use anyhow::{anyhow, Context};
6use clap::Parser;
7use stellation_backend::ServerAppProps;
8use stellation_backend_tower::{Frontend, Server, TowerEndpoint, TowerRenderRequest};
9use stellation_bridge::links::{Link, PhantomLink};
10use stellation_core::dev::StctlMetadata;
11use typed_builder::TypedBuilder;
12use yew::BaseComponent;
13
14#[derive(Parser)]
15struct Arguments {
16 #[arg(long, default_value = "localhost:5000", env = "STELLATION_LISTEN_ADDR")]
18 listen_addr: String,
19 #[arg(long, env = "STELLATION_FRONTEND_DIR")]
21 frontend_dir: Option<PathBuf>,
22}
23
24#[derive(Debug, TypedBuilder)]
26pub struct Cli<COMP, CTX = (), L = PhantomLink>
27where
28 COMP: BaseComponent,
29{
30 endpoint: TowerEndpoint<COMP, CTX, L>,
31}
32
33impl<COMP, CTX, L> Cli<COMP, CTX, L>
34where
35 COMP: BaseComponent<Properties = ServerAppProps<CTX, TowerRenderRequest<CTX>>>,
36 CTX: 'static,
37 L: 'static + Link,
38{
39 pub async fn run(self) -> anyhow::Result<()> {
41 let Self { mut endpoint } = self;
42
43 let args = Arguments::parse();
44
45 let meta = match env::var(StctlMetadata::ENV_NAME) {
47 Ok(m) => Some(StctlMetadata::from_json(&m).context("failed to load metadata")?),
48 Err(_) => None,
49 };
50
51 let addr = meta
52 .as_ref()
53 .map(|m| m.listen_addr.as_str())
54 .unwrap_or_else(|| args.listen_addr.as_str());
55
56 if let Some(ref p) = args.frontend_dir {
57 endpoint = endpoint.with_frontend(Frontend::new_path(p));
58 }
59
60 if let Some(ref meta) = meta {
61 endpoint = endpoint
62 .with_frontend(Frontend::new_path(&meta.frontend_dev_build_dir))
63 .with_auto_refresh();
64 }
65
66 let listen_addr = addr
67 .to_socket_addrs()
68 .context("failed to parse address")
69 .and_then(|m| {
70 m.into_iter()
71 .next()
72 .ok_or_else(|| anyhow!("failed to parse address"))
73 })?;
74
75 tracing::info!("Listening at: http://{}/", addr);
76
77 Server::<()>::bind(listen_addr)
78 .serve_service(endpoint.into_tower_service())
79 .await?;
80
81 Ok(())
82 }
83}