use crate::{platform::Context, workers::serve::Server, AsyncHandle};
#[derive(
Clone,
Debug,
Default,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
clap::Parser,
serde::Deserialize,
serde::Serialize,
)]
pub struct ServeCmd {
#[clap(subcommand)]
pub args: Option<ServeOpts>,
#[clap(long, short = 'H')]
pub host: Option<String>,
#[clap(long, short)]
pub port: Option<u16>,
#[clap(long, short)]
pub workdir: Option<String>,
}
#[derive(
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
clap::Subcommand,
serde::Deserialize,
serde::Serialize,
)]
pub enum ServeOpts {
Run {
#[clap(long, short)]
prefix: Option<String>,
},
}
impl ServeCmd {
pub fn new() -> Self {
clap::Parser::parse()
}
pub fn args(&self) -> Option<&ServeOpts> {
self.args.as_ref()
}
pub fn addr(&self) -> Option<core::net::SocketAddr> {
let addr = format!("{}:{}", self.host()?, self.port()?)
.parse()
.unwrap();
Some(addr)
}
pub fn host(&self) -> Option<&str> {
self.host.as_deref()
}
pub fn port(&self) -> Option<u16> {
self.port
}
#[tracing::instrument(skip_all, name = "handle", target = "serve")]
pub async fn handle<Ctx>(self, ctx: &mut Ctx) -> <Self as AsyncHandle<Ctx>>::Output
where
Self: AsyncHandle<Ctx>,
Ctx: core::fmt::Debug,
{
<Self as AsyncHandle<Ctx>>::handle(self, ctx).await
}
}
#[async_trait::async_trait]
impl AsyncHandle<Context> for ServeCmd {
type Output = anyhow::Result<()>;
async fn handle(self, ctx: &mut Context) -> Self::Output {
if let Some(host) = self.host {
ctx.config_mut().network_mut().set_host(host);
}
if let Some(port) = self.port {
ctx.config_mut().network_mut().set_port(port);
}
ctx.config_mut().set_some_workdir(self.workdir);
let addr = ctx.config().network().address();
let scope = ctx.config().scope().clone();
let server = Server::new(addr.as_socket_addr(), scope);
tokio::join!(server.serve());
Ok(())
}
}