refactor: Add FullCtx which is Ctx with AppConfig
Some checks failed
Test / build (map[name:nightly]) (push) Failing after 28s
Test / build (map[name:stable]) (push) Failing after 31s

This commit is contained in:
Paul Campbell 2024-12-04 20:31:36 +00:00
parent ff4ad7ca60
commit 308c030f87
9 changed files with 125 additions and 124 deletions

View file

@ -4,27 +4,22 @@ use color_eyre::Result;
use crate::{ use crate::{
f, f,
nextcloud::model::{NextcloudBoardId, NextcloudHostname, NextcloudPassword, NextcloudUsername}, nextcloud::model::{NextcloudBoardId, NextcloudHostname, NextcloudPassword, NextcloudUsername},
s, Ctx, NAME, s,
trello::types::{
auth::{TrelloApiKey, TrelloApiSecret},
TrelloBoardName,
},
Ctx, NAME,
}; };
#[derive(Clone, Debug, derive_more::From, PartialEq, Eq, PartialOrd, Ord, serde::Deserialize)] #[derive(Clone, Debug, derive_more::From, PartialEq, Eq, serde::Deserialize)]
pub(crate) struct TrelloConfig { pub(crate) struct TrelloConfig {
pub(crate) api_key: String, pub(crate) api_key: TrelloApiKey,
pub(crate) api_secret: String, pub(crate) api_secret: TrelloApiSecret,
pub(crate) board_name: String, pub(crate) board_name: TrelloBoardName,
} }
#[derive( #[derive(Clone, Debug, derive_more::From, PartialEq, Eq, serde::Deserialize)]
Clone,
Debug,
derive_more::From,
PartialEq,
Eq,
PartialOrd,
Ord,
serde::Deserialize,
derive_more::Constructor,
)]
pub(crate) struct NextcloudConfig { pub(crate) struct NextcloudConfig {
pub(crate) hostname: NextcloudHostname, pub(crate) hostname: NextcloudHostname,
pub(crate) username: NextcloudUsername, pub(crate) username: NextcloudUsername,
@ -33,15 +28,7 @@ pub(crate) struct NextcloudConfig {
} }
#[derive( #[derive(
Clone, Clone, Debug, derive_more::From, PartialEq, Eq, derive_more::AsRef, serde::Deserialize,
Debug,
derive_more::From,
PartialEq,
Eq,
PartialOrd,
Ord,
derive_more::AsRef,
serde::Deserialize,
)] )]
pub struct AppConfig { pub struct AppConfig {
pub(crate) trello: TrelloConfig, pub(crate) trello: TrelloConfig,

View file

@ -2,6 +2,7 @@
use std::path::PathBuf; use std::path::PathBuf;
use clap::Parser; use clap::Parser;
use color_eyre::eyre::eyre;
pub use config::AppConfig; pub use config::AppConfig;
use kxio::{fs::FileSystem, net::Net}; use kxio::{fs::FileSystem, net::Net};
@ -11,7 +12,7 @@ mod init;
mod macros; mod macros;
pub mod nextcloud; pub mod nextcloud;
mod template; mod template;
// mod trello; mod trello;
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
@ -45,17 +46,38 @@ impl Default for Ctx {
} }
} }
#[derive(Clone)]
pub struct FullCtx {
pub fs: FileSystem,
pub net: Net,
pub cfg: AppConfig,
}
#[cfg_attr(test, mutants::skip)] #[cfg_attr(test, mutants::skip)]
pub async fn run(ctx: Ctx) -> color_eyre::Result<()> { pub async fn run(ctx: Ctx) -> color_eyre::Result<()> {
color_eyre::install()?; color_eyre::install()?;
let commands = Commands::parse(); let commands = Commands::parse();
let _cfg = config::AppConfig::load(&ctx)?; let cfg = AppConfig::load(&ctx);
match cfg {
Err(err) => {
if matches!(commands.command, Command::Init) {
init::run(&ctx)
} else {
Err(eyre!("Missing or invalid config: {err}"))
}
}
Ok(cfg) => {
let _ctx = FullCtx {
fs: ctx.fs,
net: ctx.net,
cfg,
};
match commands.command { match commands.command {
Command::Init => init::run(&ctx)?, Command::Init => Err(eyre!("Config file already exists. Not overwriting it.")),
Command::Check => todo!("check"), Command::Check => todo!("check"),
Command::Import => todo!("import"), Command::Import => todo!("import"),
}; }
}
Ok(()) }
} }

View file

@ -4,6 +4,7 @@ use kxio::net::Net;
use crate::api_result::APIResult; use crate::api_result::APIResult;
use crate::{config::NextcloudConfig, f}; use crate::{config::NextcloudConfig, f};
use crate::nextcloud::model::{NextcloudHostname, NextcloudPassword, NextcloudUsername};
use model::{Board, Card, NextcloudBoardId, Stack}; use model::{Board, Card, NextcloudBoardId, Stack};
pub mod model; pub mod model;
@ -11,20 +12,19 @@ pub mod model;
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
pub(crate) struct DeckClient { pub(crate) struct DeckClient<'cfg> {
net: Net, net: Net,
hostname: String, hostname: &'cfg NextcloudHostname,
username: String, username: &'cfg NextcloudUsername,
password: String, password: &'cfg NextcloudPassword,
} }
impl<'cfg> DeckClient<'cfg> {
impl DeckClient { pub fn new(cfg: &'cfg NextcloudConfig, net: Net) -> Self {
pub fn new(cfg: &NextcloudConfig, net: Net) -> Self {
Self { Self {
net, net,
hostname: cfg.hostname.to_string(), hostname: &cfg.hostname,
username: cfg.username.to_string(), username: &cfg.username,
password: cfg.password.to_string(), password: &cfg.password,
} }
} }
@ -40,7 +40,7 @@ impl DeckClient {
APIResult::new( APIResult::new(
self.net self.net
.get(self.url("boards")) .get(self.url("boards"))
.basic_auth(&self.username, Some(&self.password)) .basic_auth(self.username.as_str(), Some(self.password.as_str()))
.header("accept", "application/json") .header("accept", "application/json")
.send() .send()
.await, .await,
@ -48,66 +48,16 @@ impl DeckClient {
.await .await
} }
pub async fn create_board(&self, title: &str, color: &str) -> APIResult<Board> {
APIResult::new(
self.net
.post(self.url("boards"))
.basic_auth(&self.username, Some(&self.password))
.header("accept", "application/json")
.body(
serde_json::json!({
"title": title,
"color": color
})
.to_string(),
)
.send()
.await,
)
.await
}
pub async fn get_stacks(&self, board_id: NextcloudBoardId) -> APIResult<Vec<Stack>> { pub async fn get_stacks(&self, board_id: NextcloudBoardId) -> APIResult<Vec<Stack>> {
APIResult::new( APIResult::new(
self.net self.net
.get(self.url(f!("boards/{board_id}/stacks"))) .get(self.url(f!("boards/{board_id}/stacks")))
.basic_auth(&self.username, Some(&self.password)) .basic_auth(self.username.as_str(), Some(self.password.as_str()))
.header("accept", "application/json") .header("accept", "application/json")
.send() .send()
.await, .await,
) )
.await .await
} }
pub async fn create_card(
&self,
board_id: i64,
stack_id: i64,
title: &str,
description: Option<&str>,
) -> APIResult<Card> {
let url = format!(
"https://{}/index.php/apps/deck/api/v1.0/boards/{}/stacks/{}/cards",
self.hostname, board_id, stack_id
);
let mut json = serde_json::json!({
"title": title,
});
if let Some(desc) = description {
json["description"] = serde_json::Value::String(desc.to_string());
}
APIResult::new(
self.net
.post(&url)
.basic_auth(&self.username, Some(&self.password))
.header("accept", "application/json")
.body(json.to_string())
.send()
.await,
)
.await
}
} }

View file

@ -17,7 +17,12 @@ mod config {
let username = NextcloudUsername::new("username"); let username = NextcloudUsername::new("username");
let password = NextcloudPassword::new("password"); let password = NextcloudPassword::new("password");
let board_id = NextcloudBoardId::new(2); let board_id = NextcloudBoardId::new(2);
let cfg = NextcloudConfig::new(hostname.clone(), username, password, board_id); let cfg = NextcloudConfig {
hostname: hostname.clone(),
username,
password,
board_id,
};
//when //when
//then //then
@ -31,7 +36,12 @@ mod config {
let username = NextcloudUsername::new("username"); let username = NextcloudUsername::new("username");
let password = NextcloudPassword::new("password"); let password = NextcloudPassword::new("password");
let board_id = NextcloudBoardId::new(2); let board_id = NextcloudBoardId::new(2);
let cfg = NextcloudConfig::new(hostname, username.clone(), password, board_id); let cfg = NextcloudConfig {
hostname,
username: username.clone(),
password,
board_id,
};
//when //when
//then //then
@ -45,7 +55,12 @@ mod config {
let username = NextcloudUsername::new("username"); let username = NextcloudUsername::new("username");
let password = NextcloudPassword::new("password"); let password = NextcloudPassword::new("password");
let board_id = NextcloudBoardId::new(2); let board_id = NextcloudBoardId::new(2);
let cfg = NextcloudConfig::new(hostname, username, password.clone(), board_id); let cfg = NextcloudConfig {
hostname,
username,
password: password.clone(),
board_id,
};
//when //when
//then //then
@ -59,7 +74,12 @@ mod config {
let username = NextcloudUsername::new("username"); let username = NextcloudUsername::new("username");
let password = NextcloudPassword::new("password"); let password = NextcloudPassword::new("password");
let board_id = NextcloudBoardId::new(2); let board_id = NextcloudBoardId::new(2);
let cfg = NextcloudConfig::new(hostname, username, password, board_id); let cfg = NextcloudConfig {
hostname,
username,
password,
board_id,
};
//when //when
//then //then
@ -208,6 +228,11 @@ mod given {
let username = NextcloudUsername::new("username"); let username = NextcloudUsername::new("username");
let password = NextcloudPassword::new("password"); let password = NextcloudPassword::new("password");
let board_id = NextcloudBoardId::new(2); let board_id = NextcloudBoardId::new(2);
NextcloudConfig::new(hostname, username, password, board_id) NextcloudConfig {
hostname,
username,
password,
board_id,
}
} }
} }

View file

@ -44,9 +44,9 @@ mod config {
config, config,
AppConfig { AppConfig {
trello: TrelloConfig { trello: TrelloConfig {
api_key: s!("trello-api-key"), api_key: s!("trello-api-key").into(),
api_secret: s!("trello-api-secret"), api_secret: s!("trello-api-secret").into(),
board_name: s!("trello-board-name"), board_name: s!("trello-board-name").into(),
}, },
nextcloud: NextcloudConfig { nextcloud: NextcloudConfig {
hostname: s!("nextcloud-hostname").into(), hostname: s!("nextcloud-hostname").into(),

View file

@ -0,0 +1,10 @@
[trello]
api_key = "trello-api-key"
api_secret = "trello-api-secret"
board_name = "trello-board-name"
[nextcloud]
hostname = "nextcloud-hostname"
username = "nextcloud-username"
password = "nextcloud-password"
board_id = 321

View file

@ -1,14 +1,14 @@
// //
pub mod api; // pub mod api;
pub mod types; pub mod types;
#[cfg(test)] // #[cfg(test)]
mod tests; // mod tests;
use crate::f; // use crate::f;
//
pub fn url(path: impl Into<String>) -> String { // pub fn url(path: impl Into<String>) -> String {
let path = path.into(); // let path = path.into();
assert!(path.starts_with("/")); // assert!(path.starts_with("/"));
f!("https://api.trello.com/1{path}") // f!("https://api.trello.com/1{path}")
} // }

View file

@ -1,6 +1,6 @@
//
use std::collections::HashMap; use std::collections::HashMap;
//
use derive_more::derive::Display; use derive_more::derive::Display;
use crate::newtype; use crate::newtype;

View file

@ -1,23 +1,30 @@
pub(crate) mod auth; pub(crate) mod auth;
pub(crate) mod board; // pub(crate) mod board;
// mod card; // mod card;
mod list; // mod list;
// mod new_card; // mod new_card;
use derive_more::derive::Display; use derive_more::derive::Display;
use crate::newtype; use crate::newtype;
newtype!(TrelloBoardId, String, Display, "Board ID"); // newtype!(TrelloBoardId, String, Display, "Board ID");
newtype!(TrelloBoardName, String, Display, "Board Name");
newtype!(TrelloListId, String, "List ID");
newtype!( newtype!(
TrelloListName, TrelloBoardName,
String, String,
Display, Display,
PartialOrd, PartialOrd,
Ord, Ord,
"List Name" "Board Name"
); );
newtype!(TrelloCardId, String, Display, "Card ID"); // newtype!(TrelloListId, String, "List ID");
newtype!(TrelloCardName, String, Display, "Card Name"); // newtype!(
// TrelloListName,
// String,
// Display,
// PartialOrd,
// Ord,
// "List Name"
// );
// newtype!(TrelloCardId, String, Display, "Card ID");
// newtype!(TrelloCardName, String, Display, "Card Name");