couchdb-orm 0.1.6

couchdb-orm Copyright (C) 2020-2023 OpenToolAdd This program comes with ABSOLUTELY NO WARRANTY; This is free software, and you are welcome to redistribute it under certain conditions; type `show-license' for details. A CLI ORM to manage some Databases operations like migration, schema creation, etc.... For the moment it only handle CouchDB.
Documentation
// Copyright (C) 2020-2023  OpenToolAdd
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
// contact: contact@tool-add.com

use crate::regexes::COUCHDB_DB_RULE;
use awc::Client;
use crate::structs::DesignDoc;

pub mod errors;

use errors::DesignDocCreateError;

pub async fn create_design_doc(
    client: &Client,
    db_name: &str,
    host: &str,
    design_doc_name: &str,
    mut design_doc: DesignDoc,
) -> Result<bool, Box<dyn std::error::Error>> {
    // @TODO
    // Get the data to send
    // println!("{:?}", design_doc);
    if !COUCHDB_DB_RULE.is_match(db_name) {
        return Err(Box::new(DesignDocCreateError::new(&format!(
            "{} string doesn't respect the regex rule {}",
            db_name,
            COUCHDB_DB_RULE.as_str()
        ))));
    }
    let uri: String = format!("{}/{}/_design/{}", host, db_name, design_doc_name);
    // get the _rev value for update
    match client.get(&uri).send().await {
        Ok(mut response) => {
            let bytes: Vec<u8> = response.body().await?.iter().cloned().collect();
            let json_design_doc: serde_json::Value = serde_json::from_str(std::str::from_utf8(bytes.as_slice()).unwrap()).unwrap();
            // println!("{:?}", json_design_doc);
            // replace the " because it converts to double string...
            // assign it to the design doc
            design_doc.rev = match json_design_doc.get("_rev") {
                Some(r) => Some(r.to_string().replace("\"", "")),
                None => None
            };
            let design_doc_json: String = serde_json::to_string(&design_doc)?;
            // println!("{:?}", design_doc_json);
            // send the data
            match client.put(&uri).send_body(design_doc_json).await {
                Ok(mut response) => {
                    // println!("{:?}", response);
                    if response.status().as_u16() >= 400 {
                        let bytes: Vec<u8> = response.body().await?.iter().cloned().collect();
                        let error: serde_json::Value =
                            serde_json::from_str(std::str::from_utf8(bytes.as_slice()).unwrap()).unwrap();
                        Err(Box::new(DesignDocCreateError::new(&format!(
                            "Error with the request to {}: error: \n{}",
                            &uri, error
                        ))))
                    } else {
                        Ok(true)
                    }
                }
                Err(error) => Err(Box::new(DesignDocCreateError::new(&format!(
                    "Error with the request to {}: error: \n{}",
                    host, error
                )))),
            }
        }
        Err(error) => Err(Box::new(DesignDocCreateError::new(&format!(
            "Error with the request to {}: error: \n{}",
            uri, error
        ))))
    }
}

// #[cfg(test)]
// mod tests {
//     extern crate actix_web;
//     extern crate wiremock;

//     use super::*;
//     use actix_web::test;
//     use dotenv::dotenv;
//     use serde_json::Value;
//     use std::error::Error;

//     use wiremock::matchers::{method, path};
//     use wiremock::{Mock, MockServer, ResponseTemplate};

//     #[actix_rt::test]
//     async fn create_db_regex_error_test() {
//         let client: Client = Client::default();
//         let box_result: Box<dyn Error> = create_db(&client, "Test", "").await.unwrap_err();
//         let result: &DesignDocCreateError = box_result.downcast_ref().unwrap();
//         assert_eq!(
//             format!("{}", result),
//             format!(
//                 "DesignDocCreateError: {} string doesn't respect the regex rule {}",
//                 "Test",
//                 COUCHDB_DB_RULE.as_str()
//             )
//         );

//         let box_result: Box<dyn Error> = create_db(&client, "testT", "").await.unwrap_err();
//         let result: &DesignDocCreateError = box_result.downcast_ref().unwrap();
//         assert_eq!(
//             format!("{}", result),
//             format!(
//                 "DesignDocCreateError: {} string doesn't respect the regex rule {}",
//                 "testT",
//                 COUCHDB_DB_RULE.as_str()
//             )
//         )
//     }

//     #[actix_rt::test]
//     async fn create_db_http_error_test() {
//         let mock_server = MockServer::start().await;
//         // Some JSON input data as a &str. Maybe this comes from the user.
//         let data = r#"
//         {
//             "error": "test error"
//         }"#;

//         let response_template: ResponseTemplate =
//             ResponseTemplate::new(400).set_body_raw(data.as_bytes(), "application/json");
//         Mock::given(method("PUT"))
//             .and(path("/test"))
//             .respond_with(response_template)
//             .mount(&mock_server)
//             .await;

//         let error: serde_json::Value = serde_json::from_str(data).unwrap();

//         let client: Client = Client::default();
//         let host: String = mock_server.uri();

//         let box_result: Box<dyn Error> = create_db(&client, "test", &host).await.unwrap_err();
//         let result: &DesignDocCreateError = box_result.downcast_ref().unwrap();
//         assert_eq!(
//             format!("{}", result),
//             format!(
//                 "DesignDocCreateError: Error with the request to {}: error: \n{}",
//                 format!("{}/{}", host, "test"),
//                 error
//             )
//         )
//     }

//     #[actix_rt::test]
//     async fn create_db_test() {
//         let mock_server = MockServer::start().await;
//         Mock::given(method("PUT"))
//             .and(path("/test"))
//             .respond_with(ResponseTemplate::new(200))
//             .mount(&mock_server)
//             .await;

//         let client: Client = Client::default();
//         let host: String = mock_server.uri();
//         println!("test host: {}", host);
//         assert_eq!(create_db(&client, "test", &host).await.unwrap(), true);
//     }
// }