postport 0.1.1

Publish your backend documentation from a Postman Collection as a static website with an interactive API
Documentation
use crate::config::get_configuration;
use crate::markup;
use crate::postman::{ApiResponse, Collection, Item};
use std::fs;

/// Loops through items recursively, Postman doesn't have a field for what type the item is,
/// the item can be a request, response vector or a folder containing more nested items.
/// Using Option<> to recursively loop, where the absence of a new nested item is the break point
fn loop_items(items: &Vec<Item>, page: &mut String, links: &mut String, loop_iter: &mut i8) {
    for item in items {
        // If request convert JSON to markup
        if let Some(request) = &item.request {
            let path_markup = markup::request(&item, &request);
            page.push_str(&path_markup);
        // If response vector, convert response to markup
        } else if let Some(responses) = &item.responses {
            let response_markup = markup::response(responses);
            page.push_str(&response_markup);
        // Otherwise must be folder
        } else {
            let (folder, link) = markup::folder(item, *loop_iter);
            page.push_str(&folder);
            links.push_str(&link);
            // If there is another nested item, recursively run loop_items
            if let Some(item) = &item.item {
                *loop_iter += 1;
                loop_items(&item, page, links, loop_iter)
            }
        }
    }
    *loop_iter -= 1;
}

/// Check the config, get the collection from the Postman API if collection_from_api == true,
/// else get the collection from the local disk
pub fn get_collection() -> Collection {
    let config = get_configuration();
    let data: String;
    let collection: Collection;
    if config.collection_from_api {
        println!("Reading from Postman remotely");
        let client = reqwest::blocking::Client::new();
        let mut collection_route = "https://api.getpostman.com/collections/".to_string();
        collection_route.push_str(&config.collection_id);
        data = client
            .get(collection_route)
            .header("X-API-Key", config.postman_api_key)
            .send()
            .expect("Unable to retrieve Response from the Postman API")
            .text()
            .expect("Unable to parse text from Response body");
        let api_response: ApiResponse =
            serde_json::from_str(&data).expect("JSON was not well-formatted");
        collection = api_response.collection;
        return collection;
    } else {
        println!("Reading from local file at: {}", config.collection_path);
        data = fs::read_to_string(config.collection_path).expect("Failed to read file");
        collection = serde_json::from_str(&data).expect("JSON was not well-formatted");
        return collection;
    }
}

/// Run the recursive function to parse the collection, storing the results
/// in mutable `&String`'s
pub fn parse_collection(collection: &Collection) -> (String, String) {
    let mut header_int = 1;
    let mut page = String::new();
    let mut links = String::new();
    // Recursively parse collection
    loop_items(&collection.item, &mut page, &mut links, &mut header_int);
    (page, links)
}

/// Write files to static site, backup collection depending on config
pub fn write_to_disk(page: &String, links: &String, collection: &Collection) {
    let config = get_configuration();
    fs::write("./site/src/pages/postport.svelte", page).expect("Unable to write file");
    fs::write("./site/src/components/links.svelte", links).expect("Unable to write file");
    if config.backup_collection {
        fs::write(
            config.backup_path,
            serde_json::to_string_pretty(&collection).expect("Unable to parse JSON to string"),
        )
        .expect("Unable to write file");
    }
}