feat(trello): add basics of trello config model
Some checks failed
Test / build (map[name:nightly]) (push) Successful in 2m14s
Test / build (map[name:stable]) (push) Successful in 2m57s
Release Please / Release-plz (push) Failing after 21s

This commit is contained in:
Paul Campbell 2024-11-29 19:19:36 +00:00
parent de94004be3
commit c8f9780226
8 changed files with 190 additions and 155 deletions

View file

@ -1,32 +1,32 @@
// //
// use kxio::net::Response; use kxio::net::Response;
//
// use crate::{e, s};
// pub struct APIResult<T> { use crate::{e, s};
// pub text: String,
// pub result: Result<T, kxio::net::Error>,
// }
// impl<T: for<'a> serde::Deserialize<'a>> APIResult<T> { pub struct APIResult<T> {
// pub async fn new(response: kxio::net::Result<Response>) -> Self { pub text: String,
// match response { pub result: Result<T, kxio::net::Error>,
// Ok(response) => { }
// let text = response.text().await.unwrap_or_default();
// let text = if text.is_empty() { s!("null") } else { text }; impl<T: for<'a> serde::Deserialize<'a>> APIResult<T> {
// let result = serde_json::from_str::<T>(&text) pub async fn new(response: kxio::net::Result<Response>) -> Self {
// .map_err(|e| e.to_string()) match response {
// .map_err(|e| { Ok(response) => {
// e!("{e}: {text}"); let text = response.text().await.unwrap_or_default();
// e let text = if text.is_empty() { s!("null") } else { text };
// }) let result = serde_json::from_str::<T>(&text)
// .map_err(kxio::net::Error::from); .map_err(|e| e.to_string())
// Self { text, result } .map_err(|e| {
// } e!("{e}: {text}");
// Err(e) => Self { e
// text: s!(""), })
// result: Err(e), .map_err(kxio::net::Error::from);
// }, Self { text, result }
// } }
// } Err(e) => Self {
// } text: s!(""),
result: Err(e),
},
}
}
}

View file

@ -3,6 +3,13 @@ use color_eyre::Result;
use crate::{f, s, Ctx, NAME}; use crate::{f, s, Ctx, NAME};
#[derive(Clone, Debug, derive_more::From, PartialEq, Eq, PartialOrd, Ord, serde::Deserialize)]
pub struct TrelloConfig {
pub api_key: String,
pub api_secret: String,
pub board_name: String,
}
#[derive( #[derive(
Clone, Clone,
Debug, Debug,
@ -14,7 +21,9 @@ use crate::{f, s, Ctx, NAME};
derive_more::AsRef, derive_more::AsRef,
serde::Deserialize, serde::Deserialize,
)] )]
pub struct AppConfig {} pub struct AppConfig {
pub trello: TrelloConfig,
}
impl AppConfig { impl AppConfig {
pub fn load(ctx: &Ctx) -> Result<Self> { pub fn load(ctx: &Ctx) -> Result<Self> {
let file = ctx.fs.base().join(f!("{NAME}.toml")); let file = ctx.fs.base().join(f!("{NAME}.toml"));

View file

@ -4,12 +4,12 @@ use std::path::PathBuf;
use clap::Parser; use clap::Parser;
use kxio::{fs::FileSystem, net::Net}; use kxio::{fs::FileSystem, net::Net};
mod api_result; // mod api_result;
mod config; mod config;
mod init; mod init;
mod macros; mod macros;
mod template; mod template;
mod trello; // mod trello;
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;

View file

@ -9,19 +9,41 @@ use crate::{config::AppConfig, f, NAME};
mod config { mod config {
use super::*; use super::*;
use crate::config::TrelloConfig;
use crate::s;
#[test] #[test]
fn load_config() { fn load_config() {
//given //given
let fs = given::a_filesystem(); let fs = given::a_filesystem();
let file = fs.base().join(f!("{}.toml", NAME)); let file = fs.base().join(f!("{}.toml", NAME));
fs.file(&file).write("").expect("write file"); fs.file(&file)
.write(
[
"[trello]",
"api_key = \"trello-api-key\"",
"api_secret = \"trello-api-secret\"",
"board_name = \"trello-board-name\"",
]
.join("\n"),
)
.expect("write file");
let ctx = given::a_context(fs.as_real(), given::a_network().into()); let ctx = given::a_context(fs.as_real(), given::a_network().into());
//when //when
let_assert!(Ok(config) = AppConfig::load(&ctx)); let_assert!(Ok(config) = AppConfig::load(&ctx));
//then //then
assert_eq!(config, AppConfig {}); assert_eq!(
config,
AppConfig {
trello: TrelloConfig {
api_key: s!("trello-api-key"),
api_secret: s!("trello-api-secret"),
board_name: s!("trello-board-name"),
}
}
);
} }
} }

View file

@ -1,54 +1,54 @@
// //
// use kxio::net::Net; use kxio::net::Net;
// use crate::api_result::APIResult; use crate::api_result::APIResult;
// use crate::{ use crate::{
// f, f,
// trello::{ trello::{
// types::{TrelloAuth, board::TrelloBoard}, types::{auth::TrelloAuth, board::TrelloBoard},
// url, url,
// }, },
// }; };
//
// /// Get lists from named board that Member belongs to /// Get lists from named board that Member belongs to
// /// ///
// /// Get Boards that Member belongs to /// Get Boards that Member belongs to
// /// https://developer.atlassian.com/cloud/trello/rest/api-group-members/#api-members-id-boards-get /// https://developer.atlassian.com/cloud/trello/rest/api-group-members/#api-members-id-boards-get
// /// /members/{id}/boards /// /members/{id}/boards
// /// ///
// /// Lists the boards that the user is a member of. /// Lists the boards that the user is a member of.
// /// ///
// /// Request /// Request
// /// ///
// /// Path parameters /// Path parameters
// /// ///
// /// - id TrelloID REQUIRED /// - id TrelloID REQUIRED
// /// ///
// /// ///
// /// Query parameters /// Query parameters
// /// ///
// /// - fields string /// - fields string
// /// Default: all /// Default: all
// /// Valid values: id, name, desc, descData, closed, idMemberCreator, idOrganization, pinned, url, shortUrl, prefs, labelNames, starred, limits, memberships, enterpriseOwned /// Valid values: id, name, desc, descData, closed, idMemberCreator, idOrganization, pinned, url, shortUrl, prefs, labelNames, starred, limits, memberships, enterpriseOwned
// /// ///
// /// - lists string /// - lists string
// /// Which lists to include with the boards. One of: all, closed, none, open /// Which lists to include with the boards. One of: all, closed, none, open
// /// Default: none /// Default: none
// /// Valid values: all, closed, none, open /// Valid values: all, closed, none, open
// /// ///
// /// curl --request GET \ /// curl --request GET \
// /// --url "https://api.trello.com/1/members/$TRELLO_USERNAME/boards?key=$TRELLO_KEY&token=$TRELLO_SECRET&lists=open" \ /// --url "https://api.trello.com/1/members/$TRELLO_USERNAME/boards?key=$TRELLO_KEY&token=$TRELLO_SECRET&lists=open" \
// /// --header 'Accept: application/json' /// --header 'Accept: application/json'
// pub async fn get_boards_that_member_belongs_to( pub async fn get_boards_that_member_belongs_to(
// auth: &TrelloAuth, auth: &TrelloAuth,
// net: &Net, net: &Net,
// ) -> APIResult<Vec<TrelloBoard>> { ) -> APIResult<Vec<TrelloBoard>> {
// APIResult::new( APIResult::new(
// net.get(url(f!("/members/{}/boards?lists=open", **auth.user()))) net.get(url(f!("/members/{}/boards?lists=open", **auth.user())))
// .headers(auth.into()) .headers(auth.into())
// .header("Accept", "application/json") .header("Accept", "application/json")
// .send() .send()
// .await, .await,
// ) )
// .await .await
// } }

View file

@ -1,15 +1,16 @@
// use kxio::net::MockNet; //
use kxio::net::MockNet;
// use crate::trello::types::auth::{TrelloApiKey, TrelloApiSecret, TrelloAuth, TrelloUser}; use crate::trello::types::auth::{TrelloApiKey, TrelloApiSecret, TrelloAuth, TrelloUser};
// pub(crate) fn a_network() -> MockNet { pub(crate) fn a_network() -> MockNet {
// kxio::net::mock() kxio::net::mock()
// } }
// pub(crate) fn an_auth() -> TrelloAuth { pub(crate) fn an_auth() -> TrelloAuth {
// TrelloAuth::new( TrelloAuth::new(
// TrelloApiKey::new("foo"), TrelloApiKey::new("foo"),
// TrelloApiSecret::new("bar"), TrelloApiSecret::new("bar"),
// TrelloUser::new("baz"), TrelloUser::new("baz"),
// ) )
// } }

View file

@ -1,59 +1,62 @@
// use super::*; // use super::*;
use super::*;
mod given; mod given;
// type TestResult = color_eyre::Result<()>; type TestResult = color_eyre::Result<()>;
mod members { mod members {
// use std::collections::HashMap; use std::collections::HashMap;
// use kxio::net::StatusCode; use kxio::net::StatusCode;
// use serde_json::json; use serde_json::json;
// use crate::{ use crate::{
// s, s,
// trello::{ trello::{
// // api::members::get_boards_that_member_belongs_to, api::members::get_boards_that_member_belongs_to,
// types::{board::TrelloBoard, TrelloBoardId, TrelloBoardName}, types::{board::TrelloBoard, TrelloBoardId, TrelloBoardName},
// }, },
// }; };
// use super::*; use super::*;
//
// #[tokio::test] #[tokio::test]
// async fn get_member_boards() -> TestResult { async fn get_member_boards() -> TestResult {
// //given //given
// let net = given::a_network(); let net = given::a_network();
// let auth = given::an_auth(); let auth = given::an_auth();
//
// net.on() net.on()
// .get("https://api.trello.com/1/members/baz/boards?lists=open") .get("https://api.trello.com/1/members/baz/boards?lists=open")
// .headers(HashMap::from([ .headers(HashMap::from([
// ( (
// s!("authorization"), s!("authorization"),
// s!("OAuth oauth_consumer_key=\"foo\", oauth_token=\"bar\""), s!("OAuth oauth_consumer_key=\"foo\", oauth_token=\"bar\""),
// ), ),
// (s!("accept"), s!("application/json")), (s!("accept"), s!("application/json")),
// ])) ]))
// .respond(StatusCode::OK) .respond(StatusCode::OK)
// .body(s!(json!([ .body(s!(json!([
// {"id": "1", "name": "board-1", "lists":[]} {"id": "1", "name": "board-1", "lists":[]}
// ])))?; ])))?;
//
// //when //when
// let result = get_boards_that_member_belongs_to(&auth, &net.into()).await; let result = get_boards_that_member_belongs_to(&auth, &net.into())
// .await
// assert_eq!( .result?;
// result.result?,
// vec![TrelloBoard::new( assert_eq!(
// TrelloBoardId::new("1"), result,
// TrelloBoardName::new("board-1"), vec![TrelloBoard::new(
// vec![] TrelloBoardId::new("1"),
// )] TrelloBoardName::new("board-1"),
// ); vec![]
// )]
// //then );
// Ok(())
// } //then
Ok(())
}
} }

View file

@ -5,10 +5,10 @@ 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}")
// } }