Add user command

This commit is contained in:
fluo10 2025-05-08 06:33:08 +09:00
parent ba84742a13
commit 4b3484e7d3
24 changed files with 418 additions and 123 deletions

181
Cargo.lock generated
View file

@ -486,6 +486,12 @@ version = "1.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89e25b6adfb930f02d1981565a6e5d9c547ac15a96606256d3b59040e5cd4ca3"
[[package]]
name = "beef"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1"
[[package]]
name = "bitflags"
version = "2.9.0"
@ -618,7 +624,7 @@ dependencies = [
"anstream",
"anstyle",
"clap_lex",
"strsim",
"strsim 0.11.1",
]
[[package]]
@ -746,6 +752,59 @@ dependencies = [
"memchr",
]
[[package]]
name = "cynic"
version = "3.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c99c59968c8aa7f90d84240ab6ded4d3864125ce36b5b044554542cebc974946"
dependencies = [
"cynic-proc-macros",
"ref-cast",
"serde",
"static_assertions",
"thiserror 1.0.69",
]
[[package]]
name = "cynic-codegen"
version = "3.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "332695dddff7f260dfda1e97502b6440d443816f576994548b7751494991d2e3"
dependencies = [
"cynic-parser",
"darling",
"once_cell",
"ouroboros",
"proc-macro2",
"quote",
"strsim 0.10.0",
"syn 2.0.100",
"thiserror 1.0.69",
]
[[package]]
name = "cynic-parser"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cbb0f21f2f8d3134c2e887a16564c165694231f48b6ae2769193299081ecf662"
dependencies = [
"indexmap",
"lalrpop-util",
"logos",
]
[[package]]
name = "cynic-proc-macros"
version = "3.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7880789c425a73aff3ba286b2a9c794f330d4770769a42a1493d6175e4606c1"
dependencies = [
"cynic-codegen",
"darling",
"quote",
"syn 2.0.100",
]
[[package]]
name = "darling"
version = "0.20.11"
@ -766,7 +825,7 @@ dependencies = [
"ident_case",
"proc-macro2",
"quote",
"strsim",
"strsim 0.11.1",
"syn 2.0.100",
]
@ -810,6 +869,27 @@ dependencies = [
"subtle",
]
[[package]]
name = "dirs"
version = "6.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e"
dependencies = [
"dirs-sys",
]
[[package]]
name = "dirs-sys"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab"
dependencies = [
"libc",
"option-ext",
"redox_users",
"windows-sys 0.59.0",
]
[[package]]
name = "displaydoc"
version = "0.2.5"
@ -852,6 +932,7 @@ version = "0.1.0"
dependencies = [
"chrono-tz",
"clap",
"dirs",
"dpts-core",
"serde",
"thiserror 2.0.12",
@ -869,6 +950,7 @@ dependencies = [
"chrono-tz",
"clap",
"csv",
"cynic",
"dotenv",
"dpts-migration",
"iana-time-zone",
@ -1602,6 +1684,15 @@ dependencies = [
"log",
]
[[package]]
name = "lalrpop-util"
version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8d05b3fe34b8bd562c338db725dfa9beb9451a48f65f129ccb9538b48d2c93b"
dependencies = [
"rustversion",
]
[[package]]
name = "lazy_static"
version = "1.5.0"
@ -1623,6 +1714,16 @@ version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9627da5196e5d8ed0b0495e61e518847578da83483c37288316d9b2e03a7f72"
[[package]]
name = "libredox"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
dependencies = [
"bitflags",
"libc",
]
[[package]]
name = "libsqlite3-sys"
version = "0.30.1"
@ -1671,6 +1772,39 @@ dependencies = [
"value-bag",
]
[[package]]
name = "logos"
version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7251356ef8cb7aec833ddf598c6cb24d17b689d20b993f9d11a3d764e34e6458"
dependencies = [
"logos-derive",
]
[[package]]
name = "logos-codegen"
version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59f80069600c0d66734f5ff52cc42f2dabd6b29d205f333d61fd7832e9e9963f"
dependencies = [
"beef",
"fnv",
"lazy_static",
"proc-macro2",
"quote",
"regex-syntax 0.8.5",
"syn 2.0.100",
]
[[package]]
name = "logos-derive"
version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24fb722b06a9dc12adb0963ed585f19fc61dc5413e6a9be9422ef92c091e731d"
dependencies = [
"logos-codegen",
]
[[package]]
name = "matchers"
version = "0.1.0"
@ -1868,6 +2002,12 @@ dependencies = [
"vcpkg",
]
[[package]]
name = "option-ext"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
[[package]]
name = "ordered-float"
version = "4.6.0"
@ -2258,6 +2398,37 @@ dependencies = [
"bitflags",
]
[[package]]
name = "redox_users"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b"
dependencies = [
"getrandom 0.2.16",
"libredox",
"thiserror 2.0.12",
]
[[package]]
name = "ref-cast"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a0ae411dbe946a674d89546582cea4ba2bb8defac896622d6496f14c23ba5cf"
dependencies = [
"ref-cast-impl",
]
[[package]]
name = "ref-cast-impl"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
]
[[package]]
name = "regex"
version = "1.11.1"
@ -2980,6 +3151,12 @@ dependencies = [
"unicode-properties",
]
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "strsim"
version = "0.11.1"

View file

@ -11,6 +11,7 @@ dpts-server = { path = "dpts-server" }
chrono = {version = "0.4", features = ["serde"]}
chrono-tz = {version = "0.10.3", features = ["serde"]}
clap = {version = "4.5", features = ["derive"]}
dirs = "6.0.0"
dotenv = "0.15.0"
serde = { version = "1.0", features = ["derive"] }
thiserror = "2.0.12"

View file

@ -1,20 +0,0 @@
#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error("Parse int error")]
ParseInt(#[from] std::num::ParseIntError),
#[error("Missing config value: ({0})")]
MissingConfig(String),
#[error("Parse toml error")]
TomlDe(#[from] toml::de::Error),
}
impl From<dpts_client::error::Error> for Error {
fn from(e: dpts_client::error::Error) -> Self {
match e {
dpts_client::error::Error::TomlDe(x)=> Self::TomlDe(x),
dpts_client::error::Error::ParseInt(x) => Self::ParseInt(x),
dpts_client::error::Error::MissingConfig(x) => Self::MissingConfig(x),
}
}
}

View file

@ -3,11 +3,7 @@ use chrono_tz::Tz;
use crate::error::Error;
use dpts_client::auth::try_login;
use dpts_client::config::{
Config,
ClientConfig,
ClientRemoteStorageConfig,
ClientStorageConfig,
PartialGlobalConfig
ClientConfig, ClientRemoteStorageConfig, ClientStorageConfig, Config, GlobalConfig, PartialGlobalConfig
};
#[derive(Args, Clone, Debug)]
@ -17,10 +13,10 @@ pub struct InitArgs {
}
impl InitArgs {
pub fn run(self) -> Result<(), Error> {
pub async fn run(self) -> Result<(), Error> {
match self.command {
InitCommand::Local(x) => x.run(),
InitCommand::Remote(x) => x.run(),
InitCommand::Local(x) => x.run().await,
InitCommand::Remote(x) => x.run().await,
}
}
}
@ -33,11 +29,14 @@ enum InitCommand {
#[derive(Args, Clone, Debug)]
pub struct InitLocalArgs {
#[arg(short, long)]
pub time_zone: Option<Tz>,
#[arg(short, long)]
pub force: bool
}
impl InitLocalArgs {
pub fn run(self) -> Result<(), Error> {
pub async fn run(self) -> Result<(), Error> {
unimplemented!()
}
}
@ -51,13 +50,15 @@ pub struct InitRemoteArgs {
pub password: String,
#[arg(short, long)]
pub time_zone: Option<Tz>,
#[arg(short, long)]
pub force: bool,
}
impl InitRemoteArgs {
pub fn run(self) -> Result<(), Error> {
pub async fn run(self) -> Result<(), Error> {
let token: String = try_login(&self.user_name, &self.password, &self.endpoint)?;
let config: Config = Config{
global: PartialGlobalConfig {
global: GlobalConfig {
time_zone: self.time_zone.clone()
},
client: ClientConfig {
@ -67,6 +68,6 @@ impl InitRemoteArgs {
}),
}
};
todo!() // Write config
config.write_to_default_toml().await
}
}

View file

@ -1,8 +1,9 @@
//mod label;
pub mod error;
mod init;
mod record;
mod user;
pub use dpts_client::error;
//use label::LabelArgs;
@ -33,7 +34,7 @@ async fn main() -> Result<(), Error> {
let cli = Cli::parse();
match cli.command {
//Some(Commands::Add(x)) => x.run(),
Command::Init(x) => x.run(),
Command::Init(x) => x.run().await,
//Some(Commands::Label(x)) => x.run(),
Command::Record(x) => x.run(),

45
dpts-cli/src/user.rs Normal file
View file

@ -0,0 +1,45 @@
use clap::{Args, Subcommand};
use crate::error::Error;
use dpts_client::config::Config;
#[derive(Args, Clone, Debug)]
pub struct UserArgs {
#[command(subcommand)]
pub command: UserCommand,
}
impl UserArgs {
pub async fn run(self) -> Result<(), Error> {
Config::read_from_default_toml().await?.set_global();
match self.command {
UserCommand::Add(x) => x.add().await,
UserCommand::List => todo!(),
UserCommand::Modify(x) => x.modify().await,
}
}
}
#[derive(Clone, Debug, Subcommand)]
enum UserCommand {
List,
Add(UserDataArgs),
Modify(UserDataArgs)
}
#[derive(Args, Clone, Debug)]
pub struct UserDataArgs {
#[arg(short, long)]
pub user_name: String,
#[arg(short, long)]
pub password: String,
}
impl UserDataArgs {
pub async fn add(self) -> Result<(), Error> {
todo!()
}
pub async fn modify(self) -> Result<(), Error> {
todo!()
}
}

View file

@ -10,6 +10,7 @@ clap = ["dep:clap"]
[dependencies]
chrono-tz.workspace = true
clap = { workspace = true, optional = true }
dirs.workspace = true
dpts-core.workspace = true
serde.workspace = true
thiserror.workspace = true

View file

@ -1,27 +1,72 @@
mod storage;
use std::{fmt::{Display, Formatter}, path::{Path, PathBuf}, str::FromStr};
pub use dpts_core::config::*;
pub use storage::*;
use crate::error::Error;
use serde::{
Deserialize,
Serialize
};
use tokio::sync::OnceCell;
use tokio::{fs::{self, File}, io::AsyncWriteExt, sync::OnceCell};
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: PartialGlobalConfig,
pub global: GlobalConfig,
}
impl Config {
pub async fn read_from_default_toml() -> Result<Self, Error> {
Ok(Self::read_from_toml(&get_default_config_file_path()?).await?)
}
pub async fn write_to_default_toml(&self) -> Result<(), Error> {
Ok(self.write_to_toml(&get_default_config_file_path()?).await?)
}
pub async fn write_to_toml(&self, p: &Path) -> Result<(), Error> {
let toml = self.to_toml()?;
let mut file = File::create(p).await?;
file.write_all(toml.as_bytes()).await?;
Ok(())
}
pub async fn read_from_toml(p: &Path) -> Result<Self, Error> {
let raw = fs::read_to_string(p).await?;
Ok(Self::from_toml(&raw)?)
}
pub fn from_toml(s: &str) -> Result<Self, Error> {
Ok(toml::from_str(s)?)
}
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,
@ -47,19 +92,19 @@ storage = "local"
client: ClientConfig{
storage: ClientStorageConfig::Local,
},
global: PartialGlobalConfig { time_zone: None },
global: GlobalConfig { time_zone: None },
}
}).await
}
#[tokio::test]
async fn deserialize_local_storage_client_config() {
let config: Config = toml::from_str(LOCAL_STORAGE_CONFIG_TOML).unwrap();
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, toml::to_string(get_local_storage_client_config_struct().await).unwrap());
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]
@ -80,19 +125,18 @@ time_zone = "UTC"
access_key: "test".to_string(),
})
},
global: PartialGlobalConfig { time_zone: Some(UTC) }
global: GlobalConfig { time_zone: Some(UTC) }
}
}).await
}
#[tokio::test]
async fn deserialize_remote_storage_client_config() {
let config: Config = toml::from_str(REMOTE_STORAGE_CONFIG_TOML).unwrap();
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, toml::to_string(get_remote_storage_client_config_struct().await).unwrap());
assert_eq!(REMOTE_STORAGE_CONFIG_TOML, get_remote_storage_client_config_struct().await.to_toml().unwrap());
}
}

View file

@ -1,10 +0,0 @@
#[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)
}

View file

@ -1,8 +1,7 @@
pub mod auth;
pub mod config;
pub mod error;
use error::Error;
pub use dpts_core::error;

View file

@ -16,6 +16,7 @@ chrono = {workspace = true}
chrono-tz.workspace = true
clap = { workspace = true, optional = true }
csv = "1.3.1"
cynic = "3.10.0"
dotenv = {workspace = true}
dpts-migration = { workspace = true }
iana-time-zone = "0.1.63"

View file

@ -9,14 +9,14 @@ use crate::Error;
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct GlobalConfig {
pub time_zone: Tz,
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.ok_or(Error::MissingConfig("time_zone".to_string()))?,
time_zone: p.time_zone,
})
}
}

View file

@ -5,6 +5,7 @@ mod user;
pub use user::{
ActiveModel as UserActiveModel,
Column as UserColumn,
Entity as UserEntity,
Model as UserModel,
};

View file

@ -2,6 +2,9 @@ use async_graphql::SimpleObject;
use chrono::{DateTime, FixedOffset,};
use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize};
use crate::error::Error;
use crate::DATABASE_CONNECTION;
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, SimpleObject, Deserialize)]
#[sea_orm(table_name = "user")]
@ -17,6 +20,22 @@ pub struct Model {
pub updated_at: DateTimeWithTimeZone,
}
impl Entity {
pub async fn find_by_name(user_name: &str) -> Result<Option<Model>, Error> {
Ok(Entity::find()
.filter(Column::LoginName.contains(user_name))
.one(DATABASE_CONNECTION.get().unwrap())
.await?
)
}
pub async fn find_all() -> Result<Vec<Model>, Error> {
Ok(Entity::find()
.all(DATABASE_CONNECTION.get().unwrap())
.await?
)
}
}
#[derive(Copy, Clone, Debug, DeriveRelation, EnumIter)]
pub enum Relation {
#[sea_orm(has_many = "super::record_header::Entity")]
@ -36,5 +55,10 @@ impl Related<super::record_tag::Entity> for Model {
Relation::RecordTag.def()
}
}
impl ActiveModel {
pub async fn create_user(login_name: &str, password: &str) -> Result<Model, Error>{
todo!()
}
}
impl ActiveModelBehavior for ActiveModel {}
impl ActiveModelBehavior for ActiveModel {}

View file

@ -1,10 +1,32 @@
#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error("IO error")]
Io(#[from] std::io::Error),
#[error("Parse int error")]
ParseInt(#[from] std::num::ParseIntError),
#[error("Parse toml error")]
#[error("Deserialize toml error")]
TomlDe(#[from] toml::de::Error),
#[error("Serialize toml error")]
TomlSer(#[from] toml::ser::Error),
#[error("Missing config value: ({0})")]
MissingConfig(String)
MissingConfig(String),
#[error("Cannot get default config directory")]
DefaultConfigDir,
#[error("Uninitialized global var: {0}")]
UninitializedOnceCell(String),
#[error("Once cell is initializing: {0}")]
InitializingOnceCell(String),
#[error("Once cell is already Initialized: {0}")]
AlreadyInitializedOnceCell(String),
#[error("DB Error: {0}")]
Db(#[from]sea_orm::DbErr),
}
impl<T> From<tokio::sync::SetError<T>> for Error{
fn from(e: tokio::sync::SetError<T>) -> Self {
match e {
tokio::sync::SetError::AlreadyInitializedError(_) => Self::AlreadyInitializedOnceCell(std::any::type_name::<T>().to_string()),
tokio::sync::SetError::InitializingError(_) => Self::InitializingOnceCell(std::any::type_name::<T>().to_string())
}
}
}

View file

@ -1,10 +1,6 @@
mod mutation;
mod query;
mod record_detail;
mod record_header;
mod record_tag;
mod user;
pub use mutation::Mutation;
pub use query::Query;
pub use user::UserObject;
pub use user::PartialUser;

View file

@ -1,10 +0,0 @@
use async_graphql::*;
pub struct Mutation;
#[Object]
impl Mutation {
async fn login(&self, username:String, password: String) -> Result<String> {
todo!()
}
}

View file

@ -1,18 +0,0 @@
use async_graphql::{
*,
http::GraphiQLSource,
};
use axum::{
response::{Html, IntoResponse},
routing::get,
Router,
};
use super::user::UserObject;
pub struct Query;
#[Object]
impl Query {
pub async fn user(&self, username: String) -> Result<Option<UserObject>> {
todo!()
}
}

View file

@ -1,27 +1,27 @@
use async_graphql::*;
use chrono::{DateTime, FixedOffset};
use crate::entity::UserModel;
pub struct UserObject {
pub id: i32,
#[derive(SimpleObject)]
pub struct PartialUser {
pub id: Option<i32>,
pub login_name: Option<String>,
pub created_at: Option<DateTime<FixedOffset>>,
pub updated_at: Option<DateTime<FixedOffset>>,
}
#[Object]
impl UserObject {
async fn id(&self) -> i32 {
todo!()
}
async fn login_name(&self) -> Option<String> {
todo!()
}
async fn created_at(&self) -> Option<DateTime<FixedOffset>> {
todo!()
}
async fn updated_at(&self) -> Option<DateTime<FixedOffset>> {
todo!()
}
#[derive(SimpleObject)]
pub struct Users{
users: Vec<UserModel>
}
pub struct CreateUser {
login_name: String,
password: String,
}
pub struct ModifyUser {
login_name: Option<String>,
password: Option<String>,
}

View file

@ -1,10 +1,15 @@
mod mutation;
mod query;
pub use dpts_core::graphql::*;
pub use mutation::Mutation;
pub use query::Query;
use async_graphql::{EmptySubscription, Schema};
use async_graphql_axum::GraphQL;
use axum::{routing::get, Router};
use dpts_core::graphql::{
Query,
Mutation,
};
pub fn build_schema() -> Schema<Query, Mutation, EmptySubscription>{
Schema::build(Query, Mutation, EmptySubscription).finish()

View file

@ -0,0 +1,16 @@
use async_graphql::*;
use dpts_core::entity::UserModel;
use crate::{auth::try_hash_password, entity::UserActiveModel};
pub struct Mutation;
#[Object]
impl Mutation {
async fn login(&self, username:String, password: String) -> Result<String> {
todo!()
}
async fn create_user(&self, username:String, password: String) -> Result<UserModel> {
todo!()
}
}

View file

@ -0,0 +1,22 @@
use async_graphql::{
*,
http::GraphiQLSource,
};
use axum::{
response::{Html, IntoResponse},
routing::get,
Router,
};
use crate::{entity::{UserEntity, UserModel},};
pub struct Query;
#[Object]
impl Query {
pub async fn user(&self, user_name: String) -> Result<Option<UserModel>> {
Ok(UserEntity::find_by_name(&user_name).await?)
}
pub async fn users(&self) -> Result<Vec<UserModel>> {
Ok(UserEntity::find_all().await?)
}
}

View file

@ -12,7 +12,7 @@ use async_graphql_axum::{
};
use axum::{routing::get, Router};
use crate::graphql::build_service;
use dpts_core::entity as entity;
pub fn build_app() -> Router {

View file

@ -1,9 +1,6 @@
use async_graphql::{http::{playground_source, GraphQLPlaygroundConfig}, *};
use async_graphql_axum::GraphQL;
use dpts_core::graphql::{
Mutation,
Query,
};
use dpts_server::{build_app, Args};
use axum::{response::{Html, IntoResponse}, routing::get, Router};
use clap::Parser;