pzzld-server 0.0.2

A production ready server optimized for WASM applications
Documentation
/*
    Appellation: serve <module>
    Contrib: FL03 <jo3mccain@icloud.com>
*/
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);
        }
        // update the workdir; if it was set
        ctx.config_mut().set_some_workdir(self.workdir);
        // get a reference to the network address
        let addr = ctx.config().network().address();
        // get a reference to the scope
        let scope = ctx.config().scope().clone();
        // create a new server instance
        let server = Server::new(addr.as_socket_addr(), scope);
        // start the server
        tokio::join!(server.serve());
        Ok(())
    }
}