diff --git a/lazy-supplements-core/src/cache/entity/peer.rs b/lazy-supplements-core/src/cache/entity/peer.rs index 22d8dc3..87b8322 100644 --- a/lazy-supplements-core/src/cache/entity/peer.rs +++ b/lazy-supplements-core/src/cache/entity/peer.rs @@ -10,11 +10,11 @@ use serde::{Deserialize, Serialize}; use crate::data::value::{MultiaddrValue, PeerIdValue}; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Deserialize, Serialize)] #[sea_orm(table_name = "peer")] pub struct Model { #[sea_orm(primary_key)] - pub id: u32, + pub id: Uuid, #[sea_orm(indexed)] pub created_at: DateTimeUtc, #[sea_orm(indexed)] diff --git a/lazy-supplements-core/src/cache/migration/m20220101_000001_create_cache_tables.rs b/lazy-supplements-core/src/cache/migration/m20220101_000001_create_cache_tables.rs index 4ffd418..68dc716 100644 --- a/lazy-supplements-core/src/cache/migration/m20220101_000001_create_cache_tables.rs +++ b/lazy-supplements-core/src/cache/migration/m20220101_000001_create_cache_tables.rs @@ -42,7 +42,7 @@ impl TableMigration for Peer { Table::create() .table(Self::Table) .if_not_exists() - .col(pk_auto(Self::Id)) + .col(pk_uuid(Self::Id)) .col(string_len(Self::PeerId, 255)) .col(timestamp(Self::CreatedAt)) .col(timestamp(Self::UpdatedAt)) diff --git a/lazy-supplements-core/src/config/error.rs b/lazy-supplements-core/src/config/error.rs index 27f7e56..1d59bf8 100644 --- a/lazy-supplements-core/src/config/error.rs +++ b/lazy-supplements-core/src/config/error.rs @@ -2,4 +2,10 @@ pub enum ConfigError { #[error("missing config: {0}")] MissingConfig(String), + #[error("Io error: {0}")] + Io(#[from] std::io::Error), + #[error("Toml Deserialization Error")] + TomlDerialization(#[from] toml::de::Error), + #[error("Toml Serialization Error")] + TomlSerialization(#[from] toml::ser::Error), } \ No newline at end of file diff --git a/lazy-supplements-core/src/config/mod.rs b/lazy-supplements-core/src/config/mod.rs index 62e1c4d..79de80c 100644 --- a/lazy-supplements-core/src/config/mod.rs +++ b/lazy-supplements-core/src/config/mod.rs @@ -3,7 +3,7 @@ mod storage; mod p2p; use std::path::Path; -use crate::{error::Error, utils::{emptiable::Emptiable, mergeable::Mergeable}}; +use crate::{utils::{emptiable::Emptiable, mergeable::Mergeable}}; pub use error::ConfigError; use serde::{de::DeserializeOwned, Deserialize, Serialize}; @@ -19,7 +19,7 @@ pub trait PartialConfig: Emptiable + From + Mergeable { } -pub trait PartialCoreConfig: DeserializeOwned + Serialize { +pub trait BaseConfig: DeserializeOwned + Serialize { fn new() -> Self; fn from_toml(s: &str) -> Result { toml::from_str(s) @@ -27,7 +27,7 @@ pub trait PartialCoreConfig: DeserializeOwned + Serialize { fn into_toml(&self) -> Result { toml::to_string(self) } - async fn read_or_create(path: T) -> Result + async fn read_or_create(path: T) -> Result where T: AsRef { @@ -36,7 +36,7 @@ pub trait PartialCoreConfig: DeserializeOwned + Serialize { } Self::read_from(&path).await } - async fn read_from(path:T) -> Result + async fn read_from(path:T) -> Result where T: AsRef { @@ -46,7 +46,7 @@ pub trait PartialCoreConfig: DeserializeOwned + Serialize { let config: Self = toml::from_str(&content)?; Ok(config) } - async fn write_to(&self, path:T) -> Result<(), Error> + async fn write_to(&self, path:T) -> Result<(), ConfigError> where T: AsRef { diff --git a/lazy-supplements-core/src/config/p2p.rs b/lazy-supplements-core/src/config/p2p.rs index 3fa82dc..8863bd6 100644 --- a/lazy-supplements-core/src/config/p2p.rs +++ b/lazy-supplements-core/src/config/p2p.rs @@ -3,7 +3,8 @@ use std::{net::{IpAddr, Ipv4Addr}, ops, path::{Path, PathBuf}}; use base64::{prelude::BASE64_STANDARD, Engine}; #[cfg(feature="desktop")] use clap::Args; -use libp2p::{identity::{self, DecodingError, Keypair}, noise, ping, tcp, yamux, Swarm}; +use futures::StreamExt; +use libp2p::{identity::{self, DecodingError, Keypair}, noise, ping, swarm::SwarmEvent, tcp, yamux, Swarm}; use serde::{Deserialize, Serialize}; use tokio::{fs::File, io::{AsyncReadExt, AsyncWriteExt}}; use tracing_subscriber::EnvFilter; @@ -11,7 +12,7 @@ use tracing_subscriber::EnvFilter; use crate::{ config::PartialConfig, - error::Error, p2p, utils::emptiable::Emptiable + error::Error, p2p, utils::{emptiable::Emptiable, mergeable::Mergeable} }; static DEFAULT_P2P_LISTEN_IPS: &[IpAddr] = &[IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0))]; @@ -30,7 +31,7 @@ fn base64_to_keypair(base64: &str) -> Result { Ok(Keypair::from_protobuf_encoding(&vec)?) } -#[derive(Clone, Debug, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, Serialize,)] pub struct P2pConfig { #[serde(with = "keypair_parser")] pub secret: Keypair, @@ -39,7 +40,7 @@ pub struct P2pConfig { } impl P2pConfig { - pub async fn try_into_swarm (self) -> Result, Error> { + async fn try_into_swarm (self) -> Result, Error> { let mut swarm = libp2p::SwarmBuilder::with_existing_identity(self.secret) .with_tokio() .with_tcp( @@ -52,6 +53,22 @@ impl P2pConfig { swarm.listen_on("/ip4/0.0.0.0/tcp/0".parse()?)?; Ok(swarm) } + pub async fn launch_swarm(self) -> Result<(), Error>{ + let mut swarm = self.try_into_swarm().await?; + loop{ + let swarm_event = swarm.select_next_some().await; + tokio::spawn(async move{ + match swarm_event { + SwarmEvent::NewListenAddr { address, .. } => println!("Listening on {address:?}"), + SwarmEvent::Behaviour(event) => { + println!("{event:?}"); + event.run().await; + }, + _ => {} + } + }); + } + } } impl TryFrom for P2pConfig { @@ -86,7 +103,6 @@ mod keypair_parser { } #[cfg_attr(feature="desktop",derive(Args))] -#[cfg_attr(feature="macros", derive(Emptiable))] #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] pub struct PartialP2pConfig { #[cfg_attr(feature="desktop",arg(long))] @@ -123,7 +139,33 @@ impl Default for PartialP2pConfig { } } +impl Emptiable for PartialP2pConfig { + fn empty() -> Self { + Self{ + secret: None, + listen_ips: None, + port: None + } + } + fn is_empty(&self) -> bool { + self.secret.is_none() && self.listen_ips.is_none() && self.port.is_none() + } +} + +impl Mergeable for PartialP2pConfig { + fn merge(&mut self, mut other: Self) { + if let Some(x) = other.secret.take() { + let _ = self.secret.insert(x); + }; + if let Some(x) = other.listen_ips.take() { + let _ = self.listen_ips.insert(x); + }; + if let Some(x) = other.port.take() { + let _ = self.port.insert(x); + }; + } +} #[cfg(test)] diff --git a/lazy-supplements-core/src/config/storage.rs b/lazy-supplements-core/src/config/storage.rs index 5a0071b..3bf7329 100644 --- a/lazy-supplements-core/src/config/storage.rs +++ b/lazy-supplements-core/src/config/storage.rs @@ -5,7 +5,7 @@ use clap::Args; #[cfg(any(test, feature="test"))] use tempfile::tempdir; -use crate::{config::{ConfigError, PartialConfig}, utils::emptiable::Emptiable}; +use crate::{config::{ConfigError, PartialConfig}, utils::{emptiable::Emptiable, mergeable::Mergeable}}; use libp2p::mdns::Config; use serde::{Deserialize, Serialize}; @@ -50,7 +50,6 @@ impl TryFrom for StorageConfig { } } #[cfg_attr(feature="desktop", derive(Args))] -#[cfg_attr(feature="macros", derive(Emptiable))] #[derive(Clone, Debug, Deserialize, Serialize)] pub struct PartialStorageConfig { #[cfg_attr(feature="desktop", arg(long))] @@ -66,4 +65,27 @@ impl From for PartialStorageConfig { cache_directory: Some(config.cache_directory), } } +} + +impl Emptiable for PartialStorageConfig { + fn empty() -> Self { + Self { + data_directory: None, + cache_directory: None + } + } + + fn is_empty(&self) -> bool { + self.data_directory.is_none() && self.cache_directory.is_none() + } +} +impl Mergeable for PartialStorageConfig { + fn merge(&mut self, mut other: Self) { + if let Some(x) = other.data_directory.take() { + let _ = self.data_directory.insert(x); + }; + if let Some(x) = other.cache_directory.take() { + let _ = self.cache_directory.insert(x); + }; + } } \ No newline at end of file diff --git a/lazy-supplements-core/src/global/mod.rs b/lazy-supplements-core/src/global/mod.rs index 7cff42b..b6d2e0b 100644 --- a/lazy-supplements-core/src/global/mod.rs +++ b/lazy-supplements-core/src/global/mod.rs @@ -10,9 +10,9 @@ use sea_orm_migration::MigratorTrait; use tokio::sync::{OnceCell, RwLock, RwLockReadGuard, RwLockWriteGuard}; mod peers; -pub use peers::PEERS; +pub use peers::*; mod config; -pub use config::STORAGE_CONFIG; +pub use config::*; mod database_connection; pub use database_connection::*; use uuid::{ContextV7, Timestamp, Uuid}; diff --git a/lazy-supplements-core/src/utils/mergeable.rs b/lazy-supplements-core/src/utils/mergeable.rs index c7b614c..a7fdcce 100644 --- a/lazy-supplements-core/src/utils/mergeable.rs +++ b/lazy-supplements-core/src/utils/mergeable.rs @@ -1,3 +1,5 @@ +#[cfg(feature="macros")] +pub use lazy_supplements_macros::Mergeable; pub trait Mergeable: Sized { fn merge(&mut self, other: Self); } diff --git a/lazy-supplements-desktop/src/cli/args/config.rs b/lazy-supplements-desktop/src/cli/args/config.rs index 8e1b580..8dcf791 100644 --- a/lazy-supplements-desktop/src/cli/args/config.rs +++ b/lazy-supplements-desktop/src/cli/args/config.rs @@ -1,7 +1,7 @@ use std::{net::IpAddr, path::PathBuf}; use clap::Args; -use lazy_supplements_core::config::ConfigError; +use lazy_supplements_core::config::{BaseConfig, ConfigError}; use crate::config::{PartialP2pConfig, PartialStorageConfig}; #[cfg(unix)] use crate::config::PartialUnixConfig; @@ -9,46 +9,29 @@ use crate::config::PartialUnixConfig; use serde::{Deserialize, Serialize}; use crate::{ - config::PartialDesktopConfig, + config::DesktopBaseConfig, error::Error, - global::{DEFAULT_CONFIG_FILE_PATH, DEFAULT_PARTIAL_CORE_CONFIG,} + global::DEFAULT_CONFIG_FILE_PATH }; #[derive(Args, Clone, Debug)] pub struct ConfigArgs { - #[arg(short = "c", long = "config")] + #[arg(short = 'c', long = "config")] pub file_path: Option, #[arg(skip)] - pub file_content: Option>, + pub file_content: Option, #[command(flatten)] - pub args: PartialDesktopConfig, + pub args: DesktopBaseConfig, } impl ConfigArgs { pub fn get_file_path_or_default(&self) -> PathBuf { - self.file_path.unwrap_or(DEFAULT_CONFIG_FILE_PATH) + self.file_path.clone().unwrap_or((*DEFAULT_CONFIG_FILE_PATH).clone()) } - pub async fn get_or_read_file_content(&mut self) -> Result { + pub async fn get_or_read_file_content(&mut self) -> &mut DesktopBaseConfig { self.file_content.get_or_insert( - PartialDesktopConfig::read_from(self.get_config_path_or_default()).await - ).clone() - } - pub fn get_config_path_or_default(&self) -> PathBuf { - if let Some(x) = self.config.as_ref() { - x.clone() - } else { - DEFAULT_CONFIG_FILE_PATH.to_path_buf() - } - } - pub async fn try_into_partial_core_config(self) -> Result { - let mut config = PartialCoreConfig::read_from(self.get_config_path_or_default()).await?; - config.merge(self.core_config.into()); - Ok(config) - } - pub async fn try_into_core_config(self) -> Result { - let mut config = DEFAULT_PARTIAL_CORE_CONFIG.clone(); - config.merge(self.try_into_partial_core_config().await?); - config.try_into() + DesktopBaseConfig::read_from(self.get_file_path_or_default()).await.unwrap() + ) } } diff --git a/lazy-supplements-desktop/src/cli/device/mod.rs b/lazy-supplements-desktop/src/cli/device/mod.rs index 8632c0f..886ed95 100644 --- a/lazy-supplements-desktop/src/cli/device/mod.rs +++ b/lazy-supplements-desktop/src/cli/device/mod.rs @@ -12,14 +12,8 @@ pub use ping::DevicePingCommandArgs; pub use remove::DeviceRemoveCommandArgs; pub use scan::DeviceScanCommandArgs; -use std::{net::IpAddr, ops::Mul, path::PathBuf, str::FromStr}; - use clap::{Args, Parser, Subcommand}; -use crate::{cli::ServerArgs, error::Error}; - -use super::ConfigArgs; - #[derive(Debug, Args, Runnable)] pub struct DeviceCommandArgs { diff --git a/lazy-supplements-desktop/src/cli/server.rs b/lazy-supplements-desktop/src/cli/server.rs index 337de7a..1a04069 100644 --- a/lazy-supplements-desktop/src/cli/server.rs +++ b/lazy-supplements-desktop/src/cli/server.rs @@ -1,18 +1,18 @@ use clap::Args; +use lazy_supplements_core::utils::runnable::Runnable; use libp2p::{noise, ping, swarm::{NetworkBehaviour, SwarmEvent}, tcp, yamux, Swarm}; -use crate::{error::Error, global::GLOBAL}; +use crate::{error::Error, global::P2P_CONFIG}; use super::ConfigArgs; #[derive(Args, Debug)] -pub struct ServerArgs { +pub struct ServerCommandArgs { #[command(flatten)] config: ConfigArgs, } -impl ServerArgs { - pub async fn start_server(self) -> Result<(), Error>{ - let _ = crate::global::GLOBAL.get_or_init_core_config(self.config.try_into_core_config().await?).await; - GLOBAL.launch_swarm().await +impl Runnable for ServerCommandArgs { + async fn run(self) { + P2P_CONFIG.get_and_unwrap().clone().launch_swarm(); } } \ No newline at end of file diff --git a/lazy-supplements-desktop/src/config/mod.rs b/lazy-supplements-desktop/src/config/mod.rs index 4db9f5f..f01812e 100644 --- a/lazy-supplements-desktop/src/config/mod.rs +++ b/lazy-supplements-desktop/src/config/mod.rs @@ -4,8 +4,10 @@ pub mod unix; #[cfg(windows)] pub mod windows; +use clap::Args; pub use lazy_supplements_core::config::*; +use lazy_supplements_core::utils::{emptiable::Emptiable, mergeable::Mergeable}; use serde::{Deserialize, Serialize}; #[cfg(unix)] pub use unix::*; @@ -13,15 +15,18 @@ pub use unix::*; #[cfg(windows)] pub use windows::*; -#[derive(Debug, Deserialize, Serialize)] -pub struct PartialDesktopConfig { +#[derive(Args, Clone, Debug, Deserialize, Emptiable, Mergeable, Serialize)] +pub struct DesktopBaseConfig { + #[command(flatten)] p2p: PartialP2pConfig, + #[command(flatten)] storage: PartialStorageConfig, #[cfg(unix)] + #[command(flatten)] unix: PartialUnixConfig, } -impl PartialConfigRoot for PartialDesktopConfig { +impl BaseConfig for DesktopBaseConfig { fn new() -> Self { Self { p2p : PartialP2pConfig::empty().with_new_secret(), @@ -29,4 +34,20 @@ impl PartialConfigRoot for PartialDesktopConfig { unix: PartialUnixConfig::empty(), } } +} + +impl Into for &DesktopBaseConfig { + fn into(self) -> PartialP2pConfig { + self.p2p.clone() + } +} +impl Into for &DesktopBaseConfig { + fn into(self) -> PartialStorageConfig { + self.storage.clone() + } +} +impl Into for &DesktopBaseConfig { + fn into(self) -> PartialUnixConfig { + self.unix.clone() + } } \ No newline at end of file diff --git a/lazy-supplements-desktop/src/config/unix.rs b/lazy-supplements-desktop/src/config/unix.rs index c02d72f..bb922a8 100644 --- a/lazy-supplements-desktop/src/config/unix.rs +++ b/lazy-supplements-desktop/src/config/unix.rs @@ -1,6 +1,6 @@ use std::path::PathBuf; use clap::Args; -use lazy_supplements_core::config::PartialConfig; +use lazy_supplements_core::{config::PartialConfig, utils::{emptiable::Emptiable, mergeable::Mergeable}}; use libp2p::mdns::Config; use serde::{Deserialize, Serialize}; @@ -20,11 +20,17 @@ impl TryFrom for UnixConfig { } } -#[derive(Args, Clone, Debug, Deserialize, Serialize)] +#[derive(Args, Clone, Debug, Deserialize, Emptiable, Mergeable, Serialize)] pub struct PartialUnixConfig { pub socket_path: Option, } +impl Default for PartialUnixConfig { + fn default() -> Self { + todo!() + } +} + impl From for PartialUnixConfig { fn from(source: UnixConfig) -> Self { Self { @@ -33,19 +39,4 @@ impl From for PartialUnixConfig { } } -impl PartialConfig for PartialUnixConfig { - fn empty() -> Self { - Self { socket_path: None } - } - fn default() -> Self { - todo!() - } - fn is_empty(&self) -> bool { - self.socket_path.is_none() - } - fn merge(&mut self, other: Self) { - if let Some(x) = other.socket_path { - self.socket_path = Some(x); - }; - } -} \ No newline at end of file + diff --git a/lazy-supplements-desktop/src/global.rs b/lazy-supplements-desktop/src/global.rs index d5c1269..8abff0d 100644 --- a/lazy-supplements-desktop/src/global.rs +++ b/lazy-supplements-desktop/src/global.rs @@ -1,6 +1,5 @@ use std::{path::PathBuf, sync::LazyLock}; -use lazy_supplements_core::config::PartialCoreConfig; pub use lazy_supplements_core::global::*; pub static DEFAULT_DATA_DIR_PATH: LazyLock = LazyLock::new(|| { @@ -28,123 +27,3 @@ pub static DEFAULT_CONFIG_FILE_PATH: LazyLock = LazyLock::new(|| { pub static DEFAULT_DATABASE_FILE_PATH: LazyLock = LazyLock::new(|| { DEFAULT_DATA_DIR_PATH.join(&*DEFAULT_DATABASE_FILE_NAME) }); - -pub static DEFAULT_PARTIAL_CORE_CONFIG: LazyLock = LazyLock::new(|| { - PartialCoreConfig { - secret: None, - listen_ips: Some(DEFAULT_LISTEN_IPS.to_vec()), - port: Some(0), - } -}); - -pub struct Global { - pub p2p_config: OnceCell, - pub main_database: OnceCell, - pub cache_database: OnceCell, - pub peers: OnceCell>>, -} - -impl Global { - pub fn get_p2p_config(&self) -> Option<&P2pConfig> { - self.p2p_config.get() - } - pub async fn get_or_init_p2p_config(&self, config: P2pConfig) -> &P2pConfig { - self.p2p_config.get_or_init(|| async {config}).await - } - pub async fn get_or_init_peers(&self) -> &RwLock> { - self.peers.get_or_init(|| async { - RwLock::new(HashMap::new()) - }).await - } - pub async fn read_peers(&self) -> tokio::sync::RwLockReadGuard<'_, HashMap>{ - self.get_or_init_peers().await.read().await - } - pub async fn write_peers(&self) -> tokio::sync::RwLockWriteGuard<'_, HashMap>{ - self.get_or_init_peers().await.write().await - } - pub async fn launch_swarm(&self) -> Result<(), Error> { - let mut swarm = self.get_p2p_config().unwrap().clone().try_into_swarm().await?; - loop{ - let swarm_event = swarm.select_next_some().await; - tokio::spawn(async move{ - match swarm_event { - SwarmEvent::NewListenAddr { address, .. } => println!("Listening on {address:?}"), - SwarmEvent::Behaviour(event) => { - println!("{event:?}"); - event.run().await; - }, - _ => {} - } - }); - } - } -} - -impl GlobalDatabase for Global { - fn get_main_database(&self) -> Option<&DatabaseConnection> { - self.main_database.get() - } - async fn get_or_try_init_main_database(&self, path: T, _: U) -> Result<&DatabaseConnection, Error> - where - T: AsRef, - U: MigratorTrait, - { - let url = "sqlite://".to_string() + path.as_ref().to_str().unwrap() + "?mode=rwc"; - - Ok(self.main_database.get_or_try_init(|| async { - let db = Database::connect(&url).await?; - U::up(&db, None).await?; - Ok::(db) - }).await?) - } - fn get_cache_database(&self) -> Option<&DatabaseConnection> { - self.cache_database.get() - } - async fn get_or_try_init_cache_database(&self, path: T, _: U) -> Result<&DatabaseConnection, Error> - where - T: AsRef, - U: MigratorTrait, - { - let url = "sqlite://".to_string() + path.as_ref().to_str().unwrap() + "?mode=rwc"; - - Ok(self.cache_database.get_or_try_init(|| async { - let db = Database::connect(&url).await?; - U::up(&db, None).await?; - Ok::(db) - }).await?) - } - -} - - -#[cfg(test)] -pub use tests::{get_or_init_temporary_main_database, get_or_init_temporary_cache_database}; -#[cfg(test)] -pub mod tests { - use std::sync::LazyLock; - - use sea_orm_migration::MigratorTrait; - - use crate::{global::GLOBAL, cache::migration::CacheMigrator, data::migration::MainMigrator}; - - use super::*; - - pub async fn get_or_init_temporary_main_database() -> &'static DatabaseConnection { - GLOBAL.get_or_try_init_temporary_main_database(MainMigrator).await.unwrap() - } - pub async fn get_or_init_temporary_cache_database() -> &'static DatabaseConnection { - GLOBAL.get_or_try_init_temporary_cache_database(CacheMigrator).await.unwrap() - } - - #[tokio::test] - async fn connect_main_database () { - let db = get_or_init_temporary_main_database().await; - assert!(db.ping().await.is_ok()); - } - - #[tokio::test] - async fn connect_cache_database () { - let db = get_or_init_temporary_cache_database().await; - assert!(db.ping().await.is_ok()); - } -} \ No newline at end of file diff --git a/lazy-supplements-desktop/src/ipc/message/mod.rs b/lazy-supplements-desktop/src/ipc/message/mod.rs index e50c061..374ab09 100644 --- a/lazy-supplements-desktop/src/ipc/message/mod.rs +++ b/lazy-supplements-desktop/src/ipc/message/mod.rs @@ -2,16 +2,3 @@ mod response; mod request; pub use response::*; pub use request::*; - -pub trait IpcRequest { - type IpcResponse: IpcResponse; - async fn try_into_p2p_response(&self) -> Result { - - } -} - -pub trait IpcResponse { - type IpcRequest: IpcRequest; - async fn try_from_ipc_request(&self) -> Result; - -} \ No newline at end of file diff --git a/lazy-supplements-desktop/src/main.rs b/lazy-supplements-desktop/src/main.rs deleted file mode 100644 index a3b3f69..0000000 --- a/lazy-supplements-desktop/src/main.rs +++ /dev/null @@ -1,27 +0,0 @@ -use clap::{Parser, Subcommand}; -use lazy_supplements_desktop::{cli::{ConfigArgs, NodeArgs, NodeCommand, ServerArgs}, global::{Global, GLOBAL}, *}; - -#[derive(Debug, Parser)] -struct Cli { - #[command(subcommand)] - command: Command, - #[command(flatten)] - pub config: ConfigArgs, -} - -#[derive(Debug, Subcommand)] -enum Command { - Node(NodeArgs), - Server(ServerArgs), -} - - -#[tokio::main] -async fn main() { - let cli = Cli::parse(); - let _ = GLOBAL.get_or_init_core_config(cli.config.try_into_core_config().await.unwrap()).await; - match cli.command { - Command::Node(x) => x.run().await.unwrap(), - Command::Server(x) => x.start_server().await.unwrap(), - } -} \ No newline at end of file