Refuctor dpts-error and dpts-config
This commit is contained in:
parent
7bebdf7490
commit
663cc6effc
40 changed files with 302 additions and 283 deletions
83
Cargo.lock
generated
83
Cargo.lock
generated
|
@ -113,12 +113,6 @@ dependencies = [
|
|||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.98"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487"
|
||||
|
||||
[[package]]
|
||||
name = "ascii_utils"
|
||||
version = "0.9.3"
|
||||
|
@ -381,9 +375,9 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
|||
|
||||
[[package]]
|
||||
name = "axum"
|
||||
version = "0.8.3"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de45108900e1f9b9242f7f2e254aa3e2c029c921c258fe9e6b4217eeebd54288"
|
||||
checksum = "021e862c184ae977658b36c4500f7feac3221ca5da43e3f25bd04ab6c79a29b5"
|
||||
dependencies = [
|
||||
"axum-core",
|
||||
"bytes",
|
||||
|
@ -792,35 +786,42 @@ version = "0.15.7"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b"
|
||||
|
||||
[[package]]
|
||||
name = "dpts"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"dpts-config",
|
||||
"dpts-csv",
|
||||
"dpts-database",
|
||||
"dpts-entity",
|
||||
"dpts-error",
|
||||
"dpts-migration",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dpts-cli"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"clap",
|
||||
"dpts",
|
||||
"dpts-core",
|
||||
"thiserror 2.0.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dpts-config"
|
||||
name = "dpts-client"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"dpts-core",
|
||||
"serde",
|
||||
"thiserror 2.0.12",
|
||||
"tokio",
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dpts-core"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"async-graphql",
|
||||
"axum",
|
||||
"chrono",
|
||||
"chrono-tz",
|
||||
"clap",
|
||||
"dotenv",
|
||||
"dpts-entity",
|
||||
"dpts-error",
|
||||
"dpts-migration",
|
||||
"iana-time-zone",
|
||||
"log",
|
||||
"sea-orm",
|
||||
"serde",
|
||||
"thiserror 2.0.12",
|
||||
|
@ -835,24 +836,8 @@ dependencies = [
|
|||
"chrono",
|
||||
"csv",
|
||||
"dpts-entity",
|
||||
"dpts-error",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dpts-database"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"async-graphql",
|
||||
"axum",
|
||||
"chrono",
|
||||
"dotenv",
|
||||
"dpts-config",
|
||||
"dpts-entity",
|
||||
"dpts-migration",
|
||||
"log",
|
||||
"sea-orm",
|
||||
"tokio",
|
||||
"thiserror 2.0.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -863,7 +848,6 @@ dependencies = [
|
|||
"axum",
|
||||
"chrono",
|
||||
"dotenv",
|
||||
"dpts-database",
|
||||
"dpts-migration",
|
||||
"log",
|
||||
"sea-orm",
|
||||
|
@ -871,16 +855,6 @@ dependencies = [
|
|||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dpts-error"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
"thiserror 2.0.12",
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dpts-migration"
|
||||
version = "0.1.0"
|
||||
|
@ -893,9 +867,14 @@ dependencies = [
|
|||
name = "dpts-server"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"chrono",
|
||||
"clap",
|
||||
"dpts",
|
||||
"dpts-core",
|
||||
"serde",
|
||||
"thiserror 2.0.12",
|
||||
"tokio",
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
27
Cargo.toml
27
Cargo.toml
|
@ -1,32 +1,17 @@
|
|||
[package]
|
||||
name = "dpts"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
[dependencies]
|
||||
dpts-config.workspace = true
|
||||
dpts-csv.workspace = true
|
||||
dpts-entity.workspace = true
|
||||
dpts-error.workspace = true
|
||||
dpts-migration.workspace = true
|
||||
dpts-database.workspace = true
|
||||
|
||||
[workspace]
|
||||
members = [".", "dpts-*"]
|
||||
members = ["dpts-*"]
|
||||
|
||||
[workspace.dependencies]
|
||||
dpts = { path = "." }
|
||||
dpts-config = { path = "dpts-config" }
|
||||
dpts-cli.path = "dpts-cli"
|
||||
dpts-client.path = "dpts-client"
|
||||
dpts-core = { path = "dpts-core" }
|
||||
dpts-csv = { path = "dpts-csv" }
|
||||
dpts-database = { path = "dpts-database" }
|
||||
dpts-entity = { path = "dpts-entity" }
|
||||
dpts-error = { path = "dpts-error" }
|
||||
dpts-migration = {path = "dpts-migration"}
|
||||
dpts-server.path = "dpts-server"
|
||||
chrono = {version = "0.4", features = ["serde"]}
|
||||
chrono-tz = {version = "0.10.3", features = ["serde"]}
|
||||
clap = "4.5"
|
||||
clap = {version = "4.5", features = ["derive"]}
|
||||
dotenv = "0.15.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
thiserror = "2.0.12"
|
||||
|
|
|
@ -6,6 +6,7 @@ edition.workspace = true
|
|||
repository.workspace = true
|
||||
|
||||
[dependencies]
|
||||
dpts = {workspace = true}
|
||||
dpts-core = {workspace = true}
|
||||
chrono = {workspace = true}
|
||||
clap = {workspace = true, features = ["derive"]}
|
||||
thiserror.workspace = true
|
8
dpts-cli/src/error.rs
Normal file
8
dpts-cli/src/error.rs
Normal file
|
@ -0,0 +1,8 @@
|
|||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum Error {
|
||||
#[error("Parse int error")]
|
||||
ParseInt(#[from] std::num::ParseIntError),
|
||||
#[error("Missing config value: ({0})")]
|
||||
MissingConfig(String)
|
||||
|
||||
}
|
|
@ -1,10 +1,12 @@
|
|||
//mod label;
|
||||
pub mod error;
|
||||
mod record;
|
||||
|
||||
|
||||
//use label::LabelArgs;
|
||||
use record::{RecordArgs,RecordAddArgs};
|
||||
|
||||
use dpts::error::Error;
|
||||
use error::Error;
|
||||
|
||||
use clap::{Args, CommandFactory, Parser, Subcommand};
|
||||
|
||||
|
@ -23,33 +25,14 @@ enum Command {
|
|||
Record(RecordArgs),
|
||||
}
|
||||
|
||||
fn try_parse() -> Result<Cli, Error> {
|
||||
Ok(try_parse_from(std::env::args_os())?)
|
||||
}
|
||||
|
||||
fn try_parse_from<I, T>(itr: I) -> Result<Cli, Error>
|
||||
where I: IntoIterator<Item=T>,
|
||||
T: Into<OsString> + Clone,
|
||||
{
|
||||
let os_string_vec: Vec<OsString> = itr.into_iter().map(|x| Into::<OsString>::into(x)).collect();
|
||||
Cli::try_parse_from(os_string_vec.clone()).or_else(|err| match err.kind() {
|
||||
clap::error::ErrorKind::InvalidSubcommand => {
|
||||
try_parse_from(vec![OsString::from("record"), OsString::from("add")].into_iter().chain(os_string_vec.clone().into_iter()))
|
||||
},
|
||||
_ => Err(err)?,
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Error> {
|
||||
let cli = try_parse();
|
||||
match cli {
|
||||
Err(_) => Ok(Cli::command().print_help()?),
|
||||
Ok(x) => match x.command {
|
||||
//Some(Commands::Add(x)) => x.run(),
|
||||
//Some(Commands::Label(x)) => x.run(),
|
||||
Command::Record(x) => x.run(),
|
||||
}
|
||||
let cli = Cli::parse();
|
||||
match cli.command {
|
||||
//Some(Commands::Add(x)) => x.run(),
|
||||
//Some(Commands::Label(x)) => x.run(),
|
||||
Command::Record(x) => x.run(),
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use chrono::prelude::*;
|
||||
use clap::{Args, Subcommand};
|
||||
use dpts::error::Error;
|
||||
use crate::error::Error;
|
||||
use std::str::FromStr;
|
||||
|
||||
#[derive(Args, Clone, Debug)]
|
||||
|
|
16
dpts-client/Cargo.toml
Normal file
16
dpts-client/Cargo.toml
Normal file
|
@ -0,0 +1,16 @@
|
|||
[package]
|
||||
name = "dpts-client"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[features]
|
||||
default = ["clap"]
|
||||
clap = ["dep:clap"]
|
||||
|
||||
[dependencies]
|
||||
clap = { workspace = true, optional = true }
|
||||
dpts-core.workspace = true
|
||||
serde.workspace = true
|
||||
thiserror.workspace = true
|
||||
tokio.workspace = true
|
||||
toml.workspace = true
|
|
@ -2,41 +2,19 @@ mod storage;
|
|||
|
||||
pub use storage::*;
|
||||
|
||||
use crate::error::Error;
|
||||
use serde::{
|
||||
Deserialize,
|
||||
Serialize
|
||||
};
|
||||
|
||||
use chrono_tz::{Tz, UTC};
|
||||
use tokio::sync::OnceCell;
|
||||
use crate::{get_host_time_zone_or_utc, Error};
|
||||
|
||||
pub static CLIENT_CONFIG: OnceClientConfig = OnceClientConfig::const_new();
|
||||
pub static CLIENT_CONFIG: OnceCell<ClientConfig> = OnceCell::const_new();
|
||||
|
||||
pub struct OnceClientConfig {
|
||||
inner: OnceCell<ClientConfig>,
|
||||
}
|
||||
|
||||
impl OnceClientConfig {
|
||||
const fn const_new() -> Self {
|
||||
Self {
|
||||
inner: OnceCell::const_new(),
|
||||
}
|
||||
}
|
||||
pub fn get(&self) -> Option<&ClientConfig> {
|
||||
self.inner.get()
|
||||
}
|
||||
pub async fn get_or_init<F, T>(&self, f: F) -> &ClientConfig where
|
||||
F: FnOnce() -> T,
|
||||
T: Future<Output = ClientConfig>
|
||||
{
|
||||
self.inner.get_or_init(f).await
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub struct ClientConfig {
|
||||
pub time_zone: Tz,
|
||||
pub storage: ClientStorageConfig,
|
||||
}
|
||||
|
||||
|
@ -44,7 +22,6 @@ impl TryFrom<&PartialClientConfig> for ClientConfig {
|
|||
type Error = Error;
|
||||
fn try_from(p: &PartialClientConfig) -> Result<ClientConfig, Self::Error> {
|
||||
Ok(ClientConfig{
|
||||
time_zone: p.time_zone.ok_or(Error::MissingConfig("time_zone".to_string()))?,
|
||||
storage: p.clone().storage.ok_or(Error::MissingConfig("storage".to_string()))?,
|
||||
})
|
||||
|
||||
|
@ -53,7 +30,6 @@ impl TryFrom<&PartialClientConfig> for ClientConfig {
|
|||
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct PartialClientConfig {
|
||||
pub time_zone: Option<Tz>,
|
||||
pub storage: Option<ClientStorageConfig>,
|
||||
}
|
||||
|
||||
|
@ -65,7 +41,6 @@ impl PartialClientConfig {
|
|||
impl Default for PartialClientConfig {
|
||||
fn default() -> Self {
|
||||
PartialClientConfig {
|
||||
time_zone: Some(get_host_time_zone_or_utc()),
|
||||
storage: None
|
||||
}
|
||||
}
|
||||
|
@ -83,7 +58,6 @@ mod tests {
|
|||
async fn get_empty_config_struct() -> &'static PartialClientConfig {
|
||||
EMPTY_CONFIG_STRUCT.get_or_init(|| async {
|
||||
PartialClientConfig{
|
||||
time_zone: None,
|
||||
storage: None,
|
||||
}
|
||||
}).await
|
||||
|
@ -109,7 +83,6 @@ storage = "local"
|
|||
async fn get_local_storage_client_config_struct() -> &'static PartialClientConfig {
|
||||
LOCAL_STORAGE_CONFIG_STRUCT.get_or_init(|| async {
|
||||
PartialClientConfig{
|
||||
time_zone: Some(UTC),
|
||||
storage: Some(ClientStorageConfig::Local),
|
||||
}
|
||||
}).await
|
||||
|
@ -136,7 +109,6 @@ access_key = "test"
|
|||
async fn get_remote_storage_client_config_struct() -> &'static PartialClientConfig {
|
||||
REMOTE_STORAGE_CONFIG_STRUCT.get_or_init(|| async {
|
||||
PartialClientConfig{
|
||||
time_zone: Some(UTC),
|
||||
storage: Some(ClientStorageConfig::Remote(ClientRemoteStorageConfig {
|
||||
endpoint: "https://example.com".to_string(),
|
||||
access_key: "test".to_string(),
|
|
@ -1,5 +1,4 @@
|
|||
use chrono_tz::{Tz, UTC};
|
||||
use crate::{get_host_time_zone_or_utc, Error};
|
||||
use crate::error::Error;
|
||||
use serde::{
|
||||
Deserialize,
|
||||
Serialize
|
|
@ -1,5 +1,7 @@
|
|||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum Error {
|
||||
#[error("Parse int error")]
|
||||
ParseInt(#[from] std::num::ParseIntError),
|
||||
#[error("Parse toml error")]
|
||||
TomlDe(#[from] toml::de::Error),
|
||||
#[error("Missing config value: ({0})")]
|
17
dpts-client/src/lib.rs
Normal file
17
dpts-client/src/lib.rs
Normal file
|
@ -0,0 +1,17 @@
|
|||
pub mod config;
|
||||
pub mod error;
|
||||
|
||||
pub fn add(left: u64, right: u64) -> u64 {
|
||||
left + right
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn it_works() {
|
||||
let result = add(2, 2);
|
||||
assert_eq!(result, 4);
|
||||
}
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
[package]
|
||||
name = "dpts-config"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
[features]
|
||||
default = ["client", "server"]
|
||||
client = []
|
||||
server = []
|
||||
test = []
|
||||
|
||||
[dependencies]
|
||||
chrono-tz.workspace = true
|
||||
dpts-entity.workspace = true
|
||||
dpts-error.workspace = true
|
||||
iana-time-zone = "0.1.63"
|
||||
sea-orm.workspace = true
|
||||
serde.workspace = true
|
||||
thiserror.workspace = true
|
||||
tokio.workspace = true
|
||||
toml.workspace = true
|
|
@ -1,38 +0,0 @@
|
|||
#[cfg(feature="client")]
|
||||
mod client;
|
||||
mod database;
|
||||
mod error;
|
||||
#[cfg(feature="server")]
|
||||
mod server;
|
||||
|
||||
#[cfg(feature="client")]
|
||||
pub use client::{
|
||||
ClientConfig,
|
||||
CLIENT_CONFIG,
|
||||
};
|
||||
|
||||
pub use database::{
|
||||
DatabaseConfig,
|
||||
PartialDatabaseConfig,
|
||||
};
|
||||
|
||||
pub use error::Error;
|
||||
|
||||
#[cfg(feature="server")]
|
||||
pub use server::{
|
||||
ServerConfig,
|
||||
PartialServerConfig,
|
||||
SERVER_CONFIG,
|
||||
};
|
||||
|
||||
use chrono_tz::{Tz, UTC};
|
||||
|
||||
fn get_host_time_zone_or_utc() -> Tz {
|
||||
match iana_time_zone::get_timezone() {
|
||||
Ok(x) => match x.parse(){
|
||||
Ok(x) => x,
|
||||
Err(_) => UTC
|
||||
},
|
||||
Err(_) => UTC
|
||||
}
|
||||
}
|
|
@ -1,29 +1,27 @@
|
|||
[package]
|
||||
name = "dpts-database"
|
||||
name = "dpts-core"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
[features]
|
||||
default = ["server", "client"]
|
||||
client = []
|
||||
server = []
|
||||
test = []
|
||||
default = ["clap",]
|
||||
clap = ["dep:clap"]
|
||||
|
||||
[dependencies]
|
||||
dpts-config.workspace = true
|
||||
dpts-entity = { workspace = true }
|
||||
dpts-migration = { workspace = true }
|
||||
async-graphql = {version = "7.0", features = ["chrono"]}
|
||||
async-graphql = { version = "7.0", features = ["chrono"] }
|
||||
axum = "0.8"
|
||||
chrono = {workspace = true}
|
||||
chrono-tz.workspace = true
|
||||
clap = { workspace = true, optional = true }
|
||||
dotenv = {workspace = true}
|
||||
dpts-entity = { workspace = true }
|
||||
dpts-migration = { workspace = true }
|
||||
iana-time-zone = "0.1.63"
|
||||
log = "0.4.27"
|
||||
sea-orm.workspace = true
|
||||
serde.workspace = true
|
||||
thiserror.workspace = true
|
||||
tokio.workspace = true
|
||||
|
||||
|
||||
|
||||
[dev-dependencies]
|
||||
dpts-config = { workspace = true, features = ["test"] }
|
||||
toml.workspace = true
|
|
@ -1,7 +1,10 @@
|
|||
use std::time::Duration;
|
||||
|
||||
#[cfg(feature="clap")]
|
||||
use clap::Args;
|
||||
use sea_orm::ConnectOptions;
|
||||
use serde::Deserialize;
|
||||
use tokio::sync::OnceCell;
|
||||
|
||||
use crate::Error;
|
||||
|
||||
|
@ -61,14 +64,26 @@ impl TryFrom<PartialDatabaseConfig> for DatabaseConfig{
|
|||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
|
||||
#[cfg_attr(feature="clap", 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 ))]
|
||||
pub connect_timeout: Option<Duration>,
|
||||
#[cfg_attr(feature="clap", arg(value_parser = parse_duration ))]
|
||||
pub acquire_timeout: Option<Duration>,
|
||||
#[cfg_attr(feature="clap", arg(value_parser = parse_duration ))]
|
||||
pub idle_timeout: Option<Duration>,
|
||||
#[cfg_attr(feature="clap", arg(value_parser = parse_duration ))]
|
||||
pub max_lifetime: Option<Duration>,
|
||||
pub sqlx_logging: Option<bool>
|
||||
}
|
||||
|
||||
#[cfg(feature="clap")]
|
||||
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();
|
32
dpts-core/src/config/global.rs
Normal file
32
dpts-core/src/config/global.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
use chrono_tz::Tz;
|
||||
#[cfg(feature="clap")]
|
||||
use clap::Args;
|
||||
use serde::Deserialize;
|
||||
use tokio::sync::OnceCell;
|
||||
|
||||
use crate::Error;
|
||||
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq)]
|
||||
pub struct GlobalConfig {
|
||||
pub time_zone: 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.ok_or(Error::MissingConfig("time_zone".to_string()))?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
|
||||
#[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();
|
14
dpts-core/src/config/mod.rs
Normal file
14
dpts-core/src/config/mod.rs
Normal file
|
@ -0,0 +1,14 @@
|
|||
mod database;
|
||||
mod global;
|
||||
|
||||
pub use database::{
|
||||
DatabaseConfig,
|
||||
PartialDatabaseConfig,
|
||||
DATABASE_CONFIG,
|
||||
};
|
||||
|
||||
pub use global::{
|
||||
GlobalConfig,
|
||||
PartialGlobalConfig,
|
||||
GLOBAL_CONFIG,
|
||||
};
|
|
@ -1,7 +1,10 @@
|
|||
use crate::config::{
|
||||
DATABASE_CONFIG,
|
||||
DatabaseConfig
|
||||
};
|
||||
use std::time::Duration;
|
||||
use sea_orm::{entity::*, query::*, ConnectOptions, Database, DatabaseConnection};
|
||||
use dpts_migration::{Migrator, MigratorTrait};
|
||||
use dpts_config::ServerConfig;
|
||||
|
||||
use tokio::sync::OnceCell;
|
||||
|
||||
|
@ -25,15 +28,15 @@ impl OnceDatabaseConnection {
|
|||
self.inner.get_or_init(f).await
|
||||
}
|
||||
|
||||
pub async fn get_or_init_with_server_config(&self, c: &ServerConfig) -> &DatabaseConnection {
|
||||
pub async fn get_or_init_with_server_config(&self, c: &DatabaseConfig) -> &DatabaseConnection {
|
||||
self.get_or_init( || async {
|
||||
let db = Database::connect(&c.database).await.unwrap();
|
||||
let db = Database::connect(c).await.unwrap();
|
||||
Migrator::fresh(&db).await.unwrap();
|
||||
db
|
||||
}).await
|
||||
}
|
||||
pub async fn get_or_init_with_static_server_config(&self) -> &DatabaseConnection {
|
||||
self.get_or_init_with_server_config(dpts_config::SERVER_CONFIG.get().unwrap()).await
|
||||
self.get_or_init_with_server_config(DATABASE_CONFIG.get().unwrap()).await
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
10
dpts-core/src/error.rs
Normal file
10
dpts-core/src/error.rs
Normal file
|
@ -0,0 +1,10 @@
|
|||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum Error {
|
||||
#[error("Parse int error")]
|
||||
ParseInt(#[from] std::num::ParseIntError),
|
||||
#[error("Parse toml error")]
|
||||
TomlDe(#[from] toml::de::Error),
|
||||
#[error("Missing config value: ({0})")]
|
||||
MissingConfig(String)
|
||||
|
||||
}
|
6
dpts-core/src/graphql/mod.rs
Normal file
6
dpts-core/src/graphql/mod.rs
Normal file
|
@ -0,0 +1,6 @@
|
|||
mod query;
|
||||
|
||||
mod response;
|
||||
|
||||
//pub use query::GraphqlQuery;
|
||||
//pub use response::GraphqlResponse;
|
0
dpts-core/src/graphql/response.rs
Normal file
0
dpts-core/src/graphql/response.rs
Normal file
11
dpts-core/src/lib.rs
Normal file
11
dpts-core/src/lib.rs
Normal file
|
@ -0,0 +1,11 @@
|
|||
pub mod config;
|
||||
mod database_connection;
|
||||
pub mod error;
|
||||
mod graphql;
|
||||
|
||||
pub use database_connection::*;
|
||||
pub use error::Error;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
}
|
|
@ -7,7 +7,7 @@ repository.workspace = true
|
|||
|
||||
[dependencies]
|
||||
dpts-entity = { workspace = true }
|
||||
dpts-error = { workspace = true }
|
||||
chrono = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
csv = "1.3.1"
|
||||
thiserror.workspace = true
|
||||
|
|
7
dpts-csv/src/error.rs
Normal file
7
dpts-csv/src/error.rs
Normal file
|
@ -0,0 +1,7 @@
|
|||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum Error {
|
||||
#[error("Parse int error")]
|
||||
ParseInt(#[from] std::num::ParseIntError),
|
||||
#[error("Missing config value: ({0})")]
|
||||
MissingConfig(String)
|
||||
}
|
|
@ -1,15 +1,15 @@
|
|||
pub mod error;
|
||||
mod reader;
|
||||
mod record;
|
||||
mod table;
|
||||
mod writer;
|
||||
|
||||
use error::Error;
|
||||
pub use reader::CsvReader;
|
||||
pub use record::CsvRecord;
|
||||
pub use table::CsvTable;
|
||||
pub use writer::CsvWriter;
|
||||
|
||||
use dpts_error::Error;
|
||||
|
||||
use chrono::{DateTime, NaiveDateTime};
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use chrono::{DateTime, NaiveDateTime};
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
use dpts_entity::RecordDetailModel;
|
||||
use dpts_error::Error;
|
||||
use crate::error::Error;
|
||||
|
||||
#[derive(Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct CsvRecord{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use dpts_error::Error;
|
||||
use crate::error::Error;
|
||||
use super::CsvRecord;
|
||||
pub struct CsvTable{
|
||||
inner: Vec<CsvRecord>
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
mod connection;
|
||||
|
||||
pub use connection::*;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
}
|
|
@ -24,7 +24,4 @@ features = [
|
|||
"sqlx-sqlite",
|
||||
"with-chrono",
|
||||
]
|
||||
default-features = false
|
||||
|
||||
[dev-dependencies]
|
||||
dpts-database = { workspace = true, features = ["test"] }
|
||||
default-features = false
|
|
@ -1,12 +0,0 @@
|
|||
[package]
|
||||
name = "dpts-error"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.98"
|
||||
thiserror = "2.0.12"
|
||||
clap.workspace = true
|
||||
toml.workspace = true
|
|
@ -1,23 +0,0 @@
|
|||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum Error {
|
||||
#[error("Parser error")]
|
||||
Clap(#[from] clap::Error),
|
||||
#[error("Parse int error")]
|
||||
ParseInt(#[from] std::num::ParseIntError),
|
||||
#[error("IO Error")]
|
||||
Io(#[from] std::io::Error),
|
||||
#[error("Parse toml error")]
|
||||
TomlDe(#[from] toml::de::Error),
|
||||
#[error("Missing config value: ({0})")]
|
||||
MissingConfig(String)
|
||||
|
||||
}
|
||||
|
||||
impl Error {
|
||||
pub fn print(&self) -> Result<(), Error> {
|
||||
match self {
|
||||
Error::Clap(x) => Ok(x.print()?),
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,6 +6,11 @@ edition.workspace = true
|
|||
repository.workspace = true
|
||||
|
||||
[dependencies]
|
||||
dpts = {workspace = true}
|
||||
dpts-core = {workspace = true}
|
||||
chrono = {workspace = true}
|
||||
clap = {workspace = true, features = ["derive"]}
|
||||
axum = "0.8.4"
|
||||
serde.workspace = true
|
||||
thiserror.workspace = true
|
||||
tokio.workspace = true
|
||||
toml.workspace = true
|
||||
|
|
29
dpts-server/src/args.rs
Normal file
29
dpts-server/src/args.rs
Normal file
|
@ -0,0 +1,29 @@
|
|||
use crate::config::PartialServerConfig;
|
||||
use clap::Parser;
|
||||
use dpts_core::config::{
|
||||
PartialDatabaseConfig,
|
||||
PartialGlobalConfig,
|
||||
};
|
||||
use std::{
|
||||
net::IpAddr,
|
||||
path::PathBuf,
|
||||
};
|
||||
|
||||
use crate::config::ServerConfig;
|
||||
|
||||
#[derive(Clone, Debug, Parser)]
|
||||
#[command(version, about, long_about = None)]
|
||||
pub struct Args {
|
||||
#[command(flatten)]
|
||||
pub server: PartialServerConfig,
|
||||
|
||||
#[command(flatten)]
|
||||
pub global: PartialGlobalConfig,
|
||||
|
||||
#[command(flatten)]
|
||||
pub database: PartialDatabaseConfig,
|
||||
|
||||
#[arg(short, long)]
|
||||
pub config_file: Option<PathBuf>,
|
||||
}
|
||||
|
|
@ -1,9 +1,7 @@
|
|||
use chrono_tz::{Tz, UTC};
|
||||
use crate::{
|
||||
get_host_time_zone_or_utc,
|
||||
DatabaseConfig,
|
||||
PartialDatabaseConfig,
|
||||
Error
|
||||
use crate::error::Error;
|
||||
|
||||
use dpts_core::config::{
|
||||
DatabaseConfig, GlobalConfig, PartialDatabaseConfig
|
||||
};
|
||||
use serde::Deserialize;
|
||||
use std::{
|
||||
|
@ -13,14 +11,37 @@ use std::{
|
|||
};
|
||||
use tokio::sync::OnceCell;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq)]
|
||||
pub struct Config {
|
||||
global: GlobalConfig,
|
||||
database: DatabaseConfig,
|
||||
server: ServerConfig,
|
||||
}
|
||||
|
||||
impl TryFrom<PartialConfig> for Config {
|
||||
type Error = Error;
|
||||
fn try_from(p: PartialConfig) -> Result<Config, Self::Error> {
|
||||
Ok(Config {
|
||||
global: p.global.ok_or(Error::MissingConfig("global".to_string()))?,
|
||||
database: p.database.ok_or(Error::MissingConfig("global".to_string()))?,
|
||||
server: p.server.ok_or(Error::MissingConfig("global".to_string()))?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq)]
|
||||
pub struct PartialConfig {
|
||||
global: Option<GlobalConfig>,
|
||||
database: Option<DatabaseConfig>,
|
||||
server: Option<ServerConfig>,
|
||||
}
|
||||
|
||||
pub static SERVER_CONFIG: OnceServerConfig = OnceServerConfig::const_new();
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq)]
|
||||
pub struct ServerConfig {
|
||||
pub listen_ips: Vec<IpAddr>,
|
||||
pub port: u16,
|
||||
pub time_zone: Tz,
|
||||
pub database: DatabaseConfig
|
||||
}
|
||||
|
||||
impl ServerConfig {
|
||||
|
@ -33,8 +54,6 @@ impl TryFrom<PartialServerConfig> for ServerConfig {
|
|||
Ok(ServerConfig{
|
||||
listen_ips: p.listen_ips.ok_or(Error::MissingConfig("listen_ips".to_string()))?,
|
||||
port: p.port.ok_or(Error::MissingConfig("port".to_string()))?,
|
||||
database: p.database.ok_or(Error::MissingConfig("database.*".to_string()))?.try_into()?,
|
||||
time_zone: p.time_zone.ok_or(Error::MissingConfig("time_zone".to_string()))?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -61,12 +80,13 @@ impl OnceServerConfig {
|
|||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq)]
|
||||
#[derive(clap::Args)]
|
||||
|
||||
pub struct PartialServerConfig {
|
||||
#[arg(short, long,)]
|
||||
pub listen_ips: Option<Vec<IpAddr>>,
|
||||
#[arg(short, long,)]
|
||||
pub port: Option<u16>,
|
||||
pub database: Option<PartialDatabaseConfig>,
|
||||
pub time_zone: Option<Tz>,
|
||||
}
|
||||
|
||||
impl PartialServerConfig {
|
||||
|
@ -81,8 +101,6 @@ impl Default for PartialServerConfig {
|
|||
PartialServerConfig {
|
||||
listen_ips: Some(vec!["127.0.0.1".parse().unwrap(), "::1".parse().unwrap()]),
|
||||
port: Some(3000),
|
||||
database: None,
|
||||
time_zone: Some(get_host_time_zone_or_utc())
|
||||
}
|
||||
}
|
||||
}
|
10
dpts-server/src/error.rs
Normal file
10
dpts-server/src/error.rs
Normal file
|
@ -0,0 +1,10 @@
|
|||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum Error {
|
||||
#[error("Parse int error")]
|
||||
ParseInt(#[from] std::num::ParseIntError),
|
||||
#[error("Parse toml error")]
|
||||
TomlDe(#[from] toml::de::Error),
|
||||
#[error("Missing config value: ({0})")]
|
||||
MissingConfig(String)
|
||||
|
||||
}
|
4
dpts-server/src/lib.rs
Normal file
4
dpts-server/src/lib.rs
Normal file
|
@ -0,0 +1,4 @@
|
|||
mod args;
|
||||
mod config;
|
||||
pub mod error;
|
||||
pub use args::Args;
|
|
@ -1,3 +1,8 @@
|
|||
use dpts_server::Args;
|
||||
|
||||
use clap::Parser;
|
||||
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
let args = Args::parse();
|
||||
println!("{:?}", args);
|
||||
}
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
pub use dpts_csv as csv;
|
||||
pub use dpts_entity as entity;
|
||||
pub use dpts_error as error;
|
||||
pub use dpts_migration as migration;
|
Loading…
Add table
Reference in a new issue