Add feature flag for compile wasm

This commit is contained in:
fluo10 2025-05-13 18:36:58 +09:00
parent 43f36b81a9
commit 5700d19a85
17 changed files with 52 additions and 167 deletions

3
Cargo.lock generated
View file

@ -2257,7 +2257,6 @@ dependencies = [
name = "progress-pile-client"
version = "0.1.0"
dependencies = [
"async-graphql",
"chrono",
"chrono-tz",
"clap",
@ -2278,7 +2277,6 @@ name = "progress-pile-core"
version = "0.1.0"
dependencies = [
"async-graphql",
"axum",
"chrono",
"chrono-tz",
"clap",
@ -2288,7 +2286,6 @@ dependencies = [
"iana-time-zone",
"log",
"sea-orm",
"sea-orm-migration",
"serde",
"thiserror 2.0.12",
"tokio",

View file

@ -10,13 +10,13 @@ dirs = "6.0.0"
dotenv = "0.15.0"
progress-pile-cli.path = "progress-pile-cli"
progress-pile-client.path = "progress-pile-client"
progress-pile-core = { path = "progress-pile-core" }
progress-pile-core = { path = "progress-pile-core", default-features = false}
progress-pile-migration = { path = "progress-pile-migration", default-features = false }
progress-pile-server.path = "progress-pile-server"
serde = { version = "1.0", features = ["derive"] }
tempfile = "3.20.0"
thiserror = "2.0.12"
tokio = "1.44.2"
tokio = {version = "1.44.2", features = ["macros", "sync"] }
toml = "0.8.22"
uuid = { version = "1.16.0", features = [ "serde", "v4" ] }

View file

@ -4,18 +4,18 @@ version = "0.1.0"
edition = "2024"
[features]
default = ["clap"]
clap = ["dep:clap"]
default = ["desktop"]
desktop = ["dep:clap", "progress-pile-core/desktop", "dep:progress-pile-migration", "dep:sea-orm", "tokio/io-util", "tokio/fs"]
wasm = []
[dependencies]
async-graphql.workspace = true
chrono.workspace = true
chrono-tz.workspace = true
clap = { workspace = true, optional = true }
dirs.workspace = true
progress-pile-core.workspace = true
progress-pile-migration = { workspace = true, features = ["client"]}
sea-orm.workspace = true
progress-pile-migration = { workspace = true, features = ["client"], optional = true}
sea-orm = { workspace = true, optional = true }
serde.workspace = true
thiserror.workspace = true
tokio.workspace = true

View file

@ -1,9 +1,9 @@
mod storage;
mod remote;
use std::{fmt::{Display, Formatter}, path::{Path, PathBuf}, str::FromStr};
pub use progress_pile_core::config::*;
pub use storage::*;
pub use remote::*;
use crate::error::Error;
use serde::{
@ -11,26 +11,24 @@ use serde::{
Serialize
};
use tokio::{fs::{self, File}, io::AsyncWriteExt, sync::OnceCell};
#[cfg(feature="desktop")]
use tokio::{fs::{self, File}, io::AsyncWriteExt};
pub static DEFAULT_CONFIG_FILE_NAME: &str = "dpts_client.toml";
pub static DEFAULT_CONFIG_DIR_NAME: &str = "dpts";
pub static CLIENT_CONFIG: OnceCell<ClientConfig> = OnceCell::const_new();
pub fn get_default_config_file_path() -> Result<PathBuf, Error> {
let config_dir = dirs::config_dir().ok_or(Error::DefaultConfigDir)?;
Ok(config_dir.join(DEFAULT_CONFIG_DIR_NAME).join(DEFAULT_CONFIG_FILE_NAME))
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct Config {
pub client: ClientConfig,
pub global: GlobalConfig,
pub struct ClientConfig {
pub remote: ClientRemoteConfig,
}
impl Config {
#[cfg(feature="desktop")]
impl ClientConfig {
pub async fn read_from_default_toml() -> Result<Self, Error> {
Ok(Self::read_from_toml(&get_default_config_file_path()?).await?)
}
@ -53,90 +51,9 @@ impl Config {
pub fn to_toml(&self) -> Result<String, Error> {
Ok(toml::to_string(self)?)
}
pub fn set_global(self) -> Result<(), Error> {
CLIENT_CONFIG.set(self.client)?;
GLOBAL_CONFIG.set(self.global)?;
Ok(())
}
pub fn from_global() -> Result<Self, Error> {
Ok(Self {
client: CLIENT_CONFIG.get().ok_or(Error::UninitializedOnceCell("CLIENT_CONFIG".to_string()))?.clone(),
global: GLOBAL_CONFIG.get().ok_or(Error::UninitializedOnceCell("GLOBAL_CONFIG".to_string()))?.clone(),
})
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct ClientConfig {
pub storage: ClientStorageConfig,
}
#[cfg(test)]
mod tests {
use super::*;
use chrono_tz::UTC;
use tokio::sync::OnceCell;
const LOCAL_STORAGE_CONFIG_TOML: &str = r#"[client]
storage = "local"
[global]
"#;
static LOCAL_STORAGE_CONFIG_STRUCT: OnceCell<Config> = OnceCell::const_new();
async fn get_local_storage_client_config_struct() -> &'static Config {
LOCAL_STORAGE_CONFIG_STRUCT.get_or_init(|| async {
Config{
client: ClientConfig{
storage: ClientStorageConfig::Local,
},
global: GlobalConfig { time_zone: None },
}
}).await
}
#[tokio::test]
async fn deserialize_local_storage_client_config() {
let config: Config = Config::from_toml(LOCAL_STORAGE_CONFIG_TOML).unwrap();
assert_eq!(&config, get_local_storage_client_config_struct().await);
}
#[tokio::test]
async fn serialize_local_storage_client_config() {
assert_eq!(LOCAL_STORAGE_CONFIG_TOML, get_local_storage_client_config_struct().await.to_toml().unwrap());
}
const REMOTE_STORAGE_CONFIG_TOML: &str = r#"[client.storage.remote]
endpoint = "https://example.com"
access_key = "test"
[global]
time_zone = "UTC"
"#;
static REMOTE_STORAGE_CONFIG_STRUCT: OnceCell<Config> = OnceCell::const_new();
async fn get_remote_storage_client_config_struct() -> &'static Config {
REMOTE_STORAGE_CONFIG_STRUCT.get_or_init(|| async {
Config{
client: ClientConfig {
storage: ClientStorageConfig::Remote(ClientRemoteStorageConfig {
endpoint: "https://example.com".to_string(),
access_key: "test".to_string(),
})
},
global: GlobalConfig { time_zone: Some(UTC) }
}
}).await
}
#[tokio::test]
async fn deserialize_remote_storage_client_config() { let config: Config = Config::from_toml(REMOTE_STORAGE_CONFIG_TOML).unwrap();
assert_eq!(&config, get_remote_storage_client_config_struct().await);
}
#[tokio::test]
async fn serialize_remote_storage_client_config() {
assert_eq!(REMOTE_STORAGE_CONFIG_TOML, get_remote_storage_client_config_struct().await.to_toml().unwrap());
}
}
}

View file

@ -10,8 +10,8 @@ use std::{
};
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct ClientRemoteStorageConfig {
#[serde(rename_all = "snake_case")]
pub struct ClientRemoteConfig {
pub endpoint: String,
pub access_key: String,
}

View file

@ -1,6 +1,5 @@
use core::time;
use async_graphql::*;
use chrono::Local;
use sea_orm::entity::{
*,

View file

@ -1,4 +1,3 @@
use async_graphql::*;
use chrono::Local;
use sea_orm::entity::{
*,

View file

@ -1,15 +1,18 @@
use crate::config::ClientConfig;
#[cfg(feature="desktop")]
use sea_orm::DatabaseConnection;
use tokio::sync::OnceCell;
#[cfg(feature="desktop")]
mod database;
pub static GLOBAL: Global = Global{
config: OnceCell::const_new(),
#[cfg(feature="desktop")]
database: OnceCell::const_new(),
};
pub struct Global {
config: OnceCell<ClientConfig>,
#[cfg(feature="desktop")]
database: OnceCell<DatabaseConnection>,
}

View file

@ -1,5 +1,6 @@
pub mod auth;
pub mod config;
#[cfg(feature="desktop")]
pub mod entity;
pub mod global;

View file

@ -6,14 +6,16 @@ license.workspace = true
repository.workspace = true
[features]
default = ["clap",]
clap = ["dep:clap"]
postgres = ["sea-orm/sqlx-postgres", "sea-orm/sqlx-postgres"]
server = ["clap", "postgres"]
default = ["desktop", "server"]
cli = ["dep:clap"]
desktop = ["cli", "sqlite", "fs"]
fs = []
sqlite = ["dep:sea-orm"]
postgres = ["sea-orm/sqlx-postgres"]
server = ["cli", "sqlite", "postgres", "fs"]
[dependencies]
async-graphql.workspace = true
axum = "0.8"
chrono = {workspace = true}
chrono-tz.workspace = true
clap = { workspace = true, optional = true }
@ -22,9 +24,9 @@ cynic = "3.10.0"
dotenv = {workspace = true}
iana-time-zone = "0.1.63"
log = "0.4.27"
sea-orm.workspace = true
sea-orm-migration.workspace = true
sea-orm = { workspace = true, optional = true }
serde.workspace = true
thiserror.workspace = true
tokio.workspace = true
toml.workspace = true

View file

@ -1,10 +1,9 @@
use std::time::Duration;
#[cfg(feature="clap")]
#[cfg(feature="cli")]
use clap::Args;
use sea_orm::ConnectOptions;
use serde::Deserialize;
use tokio::sync::OnceCell;
use crate::error::Error;
@ -64,26 +63,25 @@ impl TryFrom<PartialDatabaseConfig> for DatabaseConfig{
}
#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
#[cfg_attr(feature="clap", derive(Args))]
#[cfg_attr(feature="cli", derive(Args))]
pub struct PartialDatabaseConfig {
pub url: Option<String>,
pub max_connections: Option<u32>,
pub min_connections: Option<u32>,
#[cfg_attr(feature="clap", arg(value_parser = parse_duration ))]
#[cfg_attr(feature="cli", arg(value_parser = parse_duration ))]
pub connect_timeout: Option<Duration>,
#[cfg_attr(feature="clap", arg(value_parser = parse_duration ))]
#[cfg_attr(feature="cli", arg(value_parser = parse_duration ))]
pub acquire_timeout: Option<Duration>,
#[cfg_attr(feature="clap", arg(value_parser = parse_duration ))]
#[cfg_attr(feature="cli", arg(value_parser = parse_duration ))]
pub idle_timeout: Option<Duration>,
#[cfg_attr(feature="clap", arg(value_parser = parse_duration ))]
#[cfg_attr(feature="cli", arg(value_parser = parse_duration ))]
pub max_lifetime: Option<Duration>,
pub sqlx_logging: Option<bool>
}
#[cfg(feature="clap")]
#[cfg(feature="cli")]
fn parse_duration(arg: &str) -> Result<std::time::Duration, Error> {
let seconds = arg.parse()?;
Ok(std::time::Duration::from_secs(seconds))
}
pub static DATABASE_CONFIG: OnceCell<DatabaseConfig> = OnceCell::const_new();

View file

@ -1,32 +0,0 @@
use chrono_tz::Tz;
#[cfg(feature="clap")]
use clap::Args;
use serde::{Deserialize, Serialize};
use tokio::sync::OnceCell;
use crate::error::Error;
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct GlobalConfig {
pub time_zone: Option<Tz>,
}
impl TryFrom<PartialGlobalConfig> for GlobalConfig{
type Error = Error;
fn try_from(p: PartialGlobalConfig) -> Result<GlobalConfig, Self::Error> {
Ok(GlobalConfig{
time_zone: p.time_zone,
})
}
}
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
#[cfg_attr(feature="clap", derive(Args))]
pub struct PartialGlobalConfig {
#[cfg_attr(feature="clap", arg(short, long))]
pub time_zone: Option<Tz>,
}
pub static GLOBAL_CONFIG: OnceCell<GlobalConfig> = OnceCell::const_new();

View file

@ -1,14 +1,8 @@
#[cfg(any(feature="sqlite", feature="postgres"))]
mod database;
mod global;
#[cfg(any(feature="sqlite", feature="postgres"))]
pub use database::{
DatabaseConfig,
PartialDatabaseConfig,
DATABASE_CONFIG,
};
pub use global::{
GlobalConfig,
PartialGlobalConfig,
GLOBAL_CONFIG,
};

View file

@ -20,6 +20,7 @@ pub enum Error {
InitializingOnceCell(String),
#[error("Once cell is already Initialized: {0}")]
AlreadyInitializedOnceCell(String),
#[cfg(any(feature="postgres", feature="sqlite"))]
#[error("DB Error: {0}")]
Db(#[from]sea_orm::DbErr),
}

View file

@ -1,10 +1,15 @@
use chrono_tz::Tz;
use crate::{config::DatabaseConfig, error::Error};
#[cfg(feature="sea-orm")]
use crate::config::DatabaseConfig;
use crate::error::Error;
pub trait GlobalConfig<T> {
fn get_config(&self) -> Option<T>;
fn get_or_try_init_config(&self) -> Result<T, Error>;
fn get_or_try_init_config_from_file(&self) -> Result<T, Error>;
fn get_or_try_init_config_from_str(&self) -> Result<T, Error>;
#[cfg(feature="sea-orm")]
fn get_database_config(&self) -> Option<DatabaseConfig>;
fn get_time_zone(&self) -> Option<Tz>;
}

View file

@ -1,9 +1,6 @@
use crate::error::Error;
use sea_orm::{ConnectOptions, Database, DatabaseConnection, DbErr};
use sea_orm_migration::MigratorTrait;
use tokio::sync::OnceCell;
pub trait GlobalDatabase {
fn get_database(&self) -> Option<&DatabaseConnection>;
async fn get_or_try_init_database(&self) -> Result<&DatabaseConnection, Error>;

View file

@ -1,5 +1,9 @@
mod config;
#[cfg(any(feature="sqlite", feature="postgres"))]
mod database;
pub use config::GlobalConfig;
#[cfg(any(feature="sqlite", feature="postgres"))]
pub use database::GlobalDatabase;