use crate::cli::args::actions::register::db::register_db;
use couchdb_orm::utils::{get_dir_entries, init_meta_dir, main_content};
use dialoguer::{theme::ColorfulTheme, MultiSelect};
use serde::{Deserialize, Serialize};
use std::fs;
use std::path::PathBuf;
use std::str::FromStr;
use thiserror::Error;
#[derive(Debug, Error, Serialize, Deserialize, Clone)]
#[error("RegisterDesignDocError: {0}")]
struct RegisterDesignDocError(String);
fn write_main_file(rootdir: &PathBuf) -> Result<(), Box<dyn std::error::Error>> {
let main_file_name: PathBuf =
PathBuf::from_str(&format!("{}/_meta/src/main.rs", rootdir.to_str().unwrap())).unwrap();
let main_content: String = main_content(rootdir)?;
fs::write(main_file_name, main_content)?;
Ok(())
}
fn write_design_doc_views_mod(
views_path: &str,
filename: &PathBuf,
rootdir: &PathBuf,
) -> Result<(), Box<dyn std::error::Error>> {
let design_docs_views_path: PathBuf = PathBuf::from_str(&views_path)?;
let mod_file_name: PathBuf = PathBuf::from_str(&format!("{}/mod.rs", views_path)).unwrap();
let available_design_doc_views: Vec<PathBuf> = fs::read_dir(&design_docs_views_path)?
.map(|res| res.map(|e| e.path()))
.collect::<Result<Vec<PathBuf>, std::io::Error>>()?;
let available_design_doc_views: Vec<&PathBuf> = available_design_doc_views
.iter()
.filter(|e| e.file_name().unwrap() != "mod.rs")
.filter(|e| e.is_file())
.collect();
let available_design_doc_views_mod_filenames: String = available_design_doc_views
.iter()
.map(|e| {
let mut s = e
.file_name()
.unwrap()
.to_str()
.unwrap()
.to_string()
.replace(".rs", ";");
s.push_str("\n");
format!("pub mod {}", s)
})
.collect();
let available_design_doc_views_enum: Vec<String> = available_design_doc_views
.iter()
.map(|e| {
e.file_name()
.unwrap()
.to_str()
.unwrap()
.to_string()
.replace(".rs", "")
})
.collect();
let filename_str: String = format!(
r#"{}"#,
filename
.file_name()
.unwrap()
.to_str()
.unwrap()
.to_string()
.replace(".rs", "")
);
let available_design_doc_views_enum: String = available_design_doc_views_enum.join(",\n");
let available_design_doc_views_list: Vec<String> = available_design_doc_views
.iter()
.map(|e| {
let s = e
.file_name()
.unwrap()
.to_str()
.unwrap()
.to_string()
.replace(".rs", "");
let s = format!(r#""{}""#, s);
s
})
.collect();
let available_design_doc_views_list: String = available_design_doc_views_list.join(",\n");
let available_design_doc_per_view_content: String = available_design_doc_views
.iter()
.map(|e| {
let s = e
.file_name()
.unwrap()
.to_str()
.unwrap()
.to_string()
.replace(".rs", "");
let mut st = format!(
include_str!("../../../../../../../static/templates/design_doc_view_get.tpl"),
s,
s
);
st.push_str("\n");
st
})
.collect();
let available_design_doc_view_content: String = format!(
include_str!("../../../../../../../static/templates/available_design_docs_views.tpl"),
available_design_doc_views_mod_filenames,
available_design_doc_views_enum,
available_design_doc_views_list,
available_design_doc_per_view_content
);
println!("available_design_doc_views_list: {:?}", available_design_doc_views_list);
fs::write(mod_file_name, available_design_doc_view_content)?;
write_main_file(rootdir)?;
Ok(())
}
fn write_design_doc_mod(
db_path: &str,
dest_name: &str,
rootdir: &PathBuf,
) -> Result<(), Box<dyn std::error::Error>> {
println!("db_path: {}", db_path);
let design_docs_path: PathBuf = PathBuf::from_str(&db_path)?;
let mod_file_name: PathBuf = PathBuf::from_str(&format!("{}/{}/mod.rs", db_path, dest_name)).unwrap();
let db_mod_file_name: PathBuf = PathBuf::from_str(&format!("{}/mod.rs", db_path)).unwrap();
let available_design_docs: Vec<PathBuf> = fs::read_dir(&design_docs_path)?
.map(|res| res.map(|e| e.path()))
.collect::<Result<Vec<PathBuf>, std::io::Error>>()?;
let available_design_docs: Vec<&PathBuf> = available_design_docs
.iter()
.filter(|e| e.is_dir())
.filter(|e| e.file_name().unwrap() != "mod.rs")
.collect();
let available_design_docs_mod_filenames: String = available_design_docs
.iter()
.map(|e| {
let mut s = e
.file_name()
.unwrap()
.to_str()
.unwrap()
.to_string()
.replace(".rs", "");
s.push_str(";\n");
format!("pub mod {}", s)
})
.collect();
let available_db_design_docs_mod_filenames: String = available_design_docs
.iter()
.map(|e| {
let mut s = e
.file_name()
.unwrap()
.to_str()
.unwrap()
.to_string()
.replace(".rs", ";");
s.push_str("\n");
format!("pub mod {};", s)
})
.collect();
let mut available_design_docs_enum: Vec<String> = available_design_docs
.iter()
.map(|e| {
e.file_name()
.unwrap()
.to_str()
.unwrap()
.to_string()
.replace(".rs", "")
})
.collect();
let filename_str: String = format!(
r#"{}"#,
dest_name
);
if !available_design_docs_enum.contains(&filename_str) {
available_design_docs_enum.push(filename_str.clone())
}
let available_design_docs_enum: String = available_design_docs_enum.join(",\n");
let mut available_design_docs_list: Vec<String> = available_design_docs
.iter()
.map(|e| {
let s = e
.file_name()
.unwrap()
.to_str()
.unwrap()
.to_string()
.replace(".rs", "");
let s = format!(r#""{}""#, s);
s
})
.collect();
let filename_str: String = format!(r#""{}""#, &filename_str);
if !available_design_docs_list.contains(&filename_str) {
available_design_docs_list.push(filename_str.clone());
}
let available_design_docs_list: String = available_design_docs_list.join(",\n");
let available_design_doc_content: String = String::from(
include_str!("../../../../../../../static/templates/available_design_docs.tpl")
);
let available_db_design_docs_content: String = format!(
include_str!("../../../../../../../static/templates/available_db_design_docs_mod.tpl"),
available_design_docs_mod_filenames,
available_design_docs_enum,
available_design_docs_list
);
fs::write(mod_file_name, available_design_doc_content)?;
fs::write(db_mod_file_name, available_db_design_docs_content)?;
write_main_file(rootdir)?;
Ok(())
}
fn write_design_doc_file(
db_path: &str,
db_name: &str,
filename: String,
override_version: bool,
rootdir: &PathBuf,
) -> Result<(), Box<dyn std::error::Error>> {
let dest_name: String = filename.replace(".rs", "");
write_design_doc_mod(db_path, &dest_name, rootdir)?;
Ok(())
}
fn create_views_folder(
db_path: &str,
db_name: &str,
filename: String,
override_version: bool,
rootdir: &PathBuf,
) -> Result<(), Box<dyn std::error::Error>> {
let dest_name: String = filename.replace(".rs", "");
let views_path: String = format!(
"{}/_meta/src/design_docs/{}/{}/views",
rootdir.to_str().unwrap(),
db_name,
dest_name,
);
fs::create_dir_all(&views_path)?;
let file_name: PathBuf = PathBuf::from_str(&format!(
"{}/{}/mod.rs",
db_path,
dest_name
))
.unwrap();
write_design_doc_views_mod(
&views_path,
&file_name,
rootdir
)
}
pub fn register_design_doc(
db_name: String,
name: String,
override_version: bool,
rootdir: &PathBuf,
) -> Result<(), Box<dyn std::error::Error>> {
init_meta_dir(&rootdir)?;
let db_path: PathBuf = PathBuf::from_str(&format!(
"{}/_meta/src/design_docs/{}",
rootdir.to_str().unwrap(),
db_name
))?;
register_db(&db_name, rootdir)?;
create_views_folder(
&db_path.to_str().unwrap(),
&db_name,
name.clone(),
override_version,
rootdir
)?;
write_design_doc_file(
&db_path.to_str().unwrap(),
&db_name,
name.clone(),
override_version,
rootdir,
)
}
pub fn write_view(
db_name: String,
name: String,
override_version: bool,
rootdir: &PathBuf,
view_name: String
) -> Result<(), Box<dyn std::error::Error>> {
let db_path: PathBuf = PathBuf::from_str(&format!(
"{}/_meta/src/design_docs/{}",
rootdir.to_str().unwrap(),
db_name
))?;
let views_path: String = format!(
"{}/_meta/src/design_docs/{}/{}/views",
rootdir.to_str().unwrap(),
db_name,
name,
);
let views_js_path: String = format!(
"{}/_meta/src/design_docs/{}/{}/views/js",
rootdir.to_str().unwrap(),
db_name,
name,
);
fs::create_dir_all(&views_js_path)?;
let js_file_name: PathBuf = PathBuf::from_str(&format!(
"{}/{}.js",
views_js_path,
view_name
))
.unwrap();
let rust_file_name: PathBuf = PathBuf::from_str(&format!(
"{}/{}.rs",
views_path,
view_name
))
.unwrap();
let design_doc_view_js_template: String = String::from(
include_str!("../../../../../../../static/templates/design_doc_view_js.tpl")
);
let design_doc_view_template: String = format!(
include_str!("../../../../../../../static/templates/design_doc_view.tpl"),
view_name
);
fs::write(js_file_name, design_doc_view_js_template)?;
fs::write(rust_file_name, design_doc_view_template)?;
create_views_folder(
&db_path.to_str().unwrap(),
&db_name,
name.clone(),
override_version,
rootdir
)
}
pub fn register_design_doc_view(
db_name: String,
name: String,
override_version: bool,
rootdir: &PathBuf,
view_name: String
) -> Result<(), Box<dyn std::error::Error>> {
init_meta_dir(&rootdir)?;
register_design_doc(
db_name.clone(),
name.clone(),
override_version.clone(),
&rootdir
)?;
write_view(
db_name,
name,
override_version,
rootdir,
view_name,
)
}