diff --git a/.gitignore b/.gitignore
index 69be759..d7da0b5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,4 +2,3 @@
.vs
testapi.txt
/postman
-*.json
diff --git a/README.md b/README.md
index 93f56d0..6930149 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
-
+
diff --git a/imgs/saved_request.png b/imgs/saved_request.png
index edee01b..8dc0740 100644
Binary files a/imgs/saved_request.png and b/imgs/saved_request.png differ
diff --git a/src/app.rs b/src/app.rs
index c261732..be037e8 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -67,12 +67,18 @@ impl<'a> Default for App<'a> {
state: None,
current_screen: Screen::Home,
response: None,
- db: Box::new(DB::new().unwrap()),
+ db: Box::new(DB::new().expect("Failed to create database")),
}
}
}
impl<'a> App<'a> {
+ fn new_test_db() -> Self {
+ Self {
+ db: Box::new(DB::new_test().expect("Failed to create database")),
+ ..Default::default()
+ }
+ }
pub fn new() -> Self {
Self::default()
}
@@ -185,7 +191,7 @@ impl<'a> App<'a> {
}
Some(
Screen::InputMenu(_)
- | Screen::CmdMenu(_)
+ | Screen::CmdMenu { .. }
| Screen::ColMenu(_)
| Screen::KeysMenu(_),
) => self.go_back_screen(),
@@ -335,8 +341,9 @@ impl<'a> App<'a> {
match collection {
Ok(collection) => {
let name = collection.info.name.clone();
+ let description = collection.info.description.clone();
let cmds: Vec = collection.into();
- self.db.add_collection(&name, cmds.as_slice())
+ self.db.add_collection(&name, &description, cmds.as_slice())
}
Err(e) => Err(e.into()),
}
@@ -375,7 +382,7 @@ impl<'a> App<'a> {
pub fn delete_item(&mut self, ind: i32) -> Result<(), rusqlite::Error> {
match self.current_screen {
- Screen::CmdMenu(_) => self.db.as_ref().delete_command(ind),
+ Screen::CmdMenu { .. } => self.db.as_ref().delete_command(ind),
Screen::KeysMenu(_) => self.db.as_ref().delete_key(ind),
Screen::ViewSavedCollections => self.db.as_ref().delete_collection(ind),
_ => Ok(()),
@@ -453,7 +460,7 @@ impl<'a> App<'a> {
#[cfg(test)]
pub mod tests {
use super::App;
- use crate::request::curl::AuthKind;
+ use crate::request::curl::{AuthKind, Curl};
#[test]
fn test_basic_get_method() {
@@ -767,4 +774,32 @@ pub mod tests {
std::fs::remove_file("test.txt").unwrap();
let _ = std::fs::remove_file("cookie-jar");
}
+ #[test]
+ fn test_import_postman_collection() {
+ let mut app = App::new_test_db();
+ let path = "test_collection.json";
+ let res = app.import_postman_collection(path);
+ let file = std::fs::File::open(path).unwrap();
+ let collection: crate::database::postman::PostmanCollection =
+ serde_json::from_reader(file).unwrap();
+ assert_eq!(collection.info.name.clone().as_str(), "Test Collection");
+ let cmds: Vec = collection.into();
+ let db = app.db.as_ref();
+ let collections = db.get_collections().unwrap();
+ let commands = db.get_commands(None).unwrap();
+ let command = commands[0].clone();
+ let curl: Curl = serde_json::from_str(command.get_curl_json()).unwrap();
+ assert!(res.is_ok());
+ assert_eq!(collections.len(), 1);
+ assert_eq!(commands.len(), cmds.len());
+ assert_eq!(curl.get_method().to_string(), "POST");
+ assert_eq!(curl.get_url(), "https://echo.getpostman.com/post");
+ assert_eq!(
+ curl.headers,
+ Some(vec![
+ String::from("Content-Type: application/json"),
+ String::from("Host: echo.getpostman.com")
+ ])
+ );
+ }
}
diff --git a/src/database/db.rs b/src/database/db.rs
index 1338203..2d50a0a 100644
--- a/src/database/db.rs
+++ b/src/database/db.rs
@@ -11,16 +11,20 @@ use std::{
#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
pub struct SavedCommand {
- id: i32,
+ pub id: i32,
command: String,
+ pub description: Option,
+ pub label: Option,
curl_json: String,
- collection_id: Option,
+ pub collection_id: Option,
+ pub collection_name: Option,
}
#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
pub struct SavedCollection {
id: i32,
- name: String,
+ pub name: String,
+ pub description: Option,
}
impl Display for SavedCollection {
@@ -42,6 +46,23 @@ pub struct DB {
}
impl DB {
+ pub fn new_test() -> Result {
+ let conn = Connection::open_in_memory()?;
+ conn.execute(
+ "CREATE TABLE commands (id INTEGER PRIMARY KEY, command TEXT, label TEXT, description TEXT, curl_json TEXT, collection_id INT);",
+ params![],
+ )?;
+ conn.execute(
+ "CREATE TABLE keys (id INTEGER PRIMARY KEY, key TEXT, label TEXT);",
+ params![],
+ )?;
+ conn.execute(
+ "CREATE TABLE collections (id INTEGER PRIMARY KEY, name TEXT, description TEXT);",
+ params![],
+ )?;
+ Ok(DB { conn })
+ }
+
pub fn new() -> Result {
let mut _path: PathBuf = PathBuf::new();
if std::env::var("CUTE_DB_PATH").is_ok() {
@@ -79,7 +100,7 @@ impl DB {
conn.execute("BEGIN;", params![])?;
// collection_id needs to be nullable
conn.execute(
- "CREATE TABLE IF NOT EXISTS commands (id INTEGER PRIMARY KEY, command TEXT, curl_json TEXT, collection_id INT NULL);",
+ "CREATE TABLE IF NOT EXISTS commands (id INTEGER PRIMARY KEY, label TEXT, description TEXT, command TEXT, curl_json TEXT, collection_id INT);",
params![],
)?;
@@ -89,7 +110,7 @@ impl DB {
)?;
conn.execute(
- "CREATE TABLE IF NOT EXISTS collections (id INTEGER PRIMARY KEY, name TEXT);",
+ "CREATE TABLE IF NOT EXISTS collections (id INTEGER PRIMARY KEY, name TEXT, description TEXT);",
params![],
)?;
@@ -106,6 +127,18 @@ impl DB {
Ok(())
}
+ pub fn set_collection_description(
+ &self,
+ id: i32,
+ description: &str,
+ ) -> Result<(), rusqlite::Error> {
+ let mut stmt = self
+ .conn
+ .prepare("UPDATE collections SET description = ? WHERE id = ?")?;
+ stmt.execute(params![description, id])?;
+ Ok(())
+ }
+
pub fn get_number_of_commands_in_collection(&self, id: i32) -> Result {
let mut stmt = self
.conn
@@ -115,45 +148,48 @@ impl DB {
}
#[rustfmt::skip]
- pub fn add_collection(&self, name: &str, commands: &[SavedCommand]) -> Result<(), Box> {
+ pub fn add_collection(&self, name: &str, desc: &str, commands: &[SavedCommand]) -> Result<(), Box> {
let mut stmt = self
.conn
- .prepare("INSERT INTO collections (name) VALUES (?1)")?;
- let _ = stmt.execute(params![name])?;
- let mut stmt = self
- .conn
- .prepare("SELECT id FROM collections WHERE name = ?1")?;
- let id: i32 = stmt.query_row(params![name], |row| row.get(0))?;
+ .prepare("INSERT INTO collections (name, description) VALUES (?1, ?2)")?;
+ let id = stmt.insert(params![name, desc])?;
for command in commands {
- self.add_command_from_collection(&command.command, &command.curl_json, id)?;
+ self.add_command_from_collection(&command.command, command.label.as_deref(), command.description.as_deref(), &command.curl_json, id as i32)?;
}
Ok(())
}
pub fn get_command_by_id(&self, id: i32) -> Result {
- let mut stmt = self
- .conn
- .prepare("SELECT id, command, curl_json, collection_id from commands WHERE id = ?1")?;
+ let mut stmt = self.conn.prepare(
+ "SELECT cmd.id, cmd.command, cmd.label, cmd.description, cmd.curl_json, cmd.collection_id, col.name as collection_name FROM commands cmd LEFT JOIN collections col ON cmd.collection_id = col.id WHERE cmd.id = ?"
+ )?;
stmt.query_row(params![id], |row| {
Ok(SavedCommand {
id: row.get(0)?,
command: row.get(1)?,
- curl_json: row.get(2)?,
- collection_id: row.get(3)?,
+ label: row.get(2)?,
+ description: row.get(3)?,
+ curl_json: row.get(4)?,
+ collection_id: row.get(5)?,
+ collection_name: row.get(6)?,
})
})
}
- pub fn get_collection_by_id(&self, id: i32) -> Result {
+ pub fn get_collection_by_id(&self, id: i32) -> Result {
let mut stmt = self
.conn
- .prepare("SELECT id, name FROM collections WHERE id = ?")?;
- let collection = stmt.query_row(params![id], |row| {
- Ok(SavedCollection {
- id: row.get(0)?,
- name: row.get(1)?,
+ .prepare("SELECT id, name, description FROM collections WHERE id = ?")
+ .map_err(|_| "No Collection".to_string())?;
+ let collection = stmt
+ .query_row(params![id], |row| {
+ Ok(SavedCollection {
+ id: row.get(0)?,
+ name: row.get(1)?,
+ description: row.get(2)?,
+ })
})
- })?;
+ .map_err(|_| ("No Collection".to_string()))?;
Ok(collection)
}
@@ -166,11 +202,14 @@ impl DB {
}
pub fn get_collections(&self) -> Result> {
- let mut stmt = self.conn.prepare("SELECT id, name FROM collections")?;
+ let mut stmt = self
+ .conn
+ .prepare("SELECT id, name, description FROM collections")?;
let rows = stmt.query_map(params![], |row| {
Ok(SavedCollection {
id: row.get(0)?,
name: row.get(1)?,
+ description: row.get(2)?,
})
})?;
Ok(rows
@@ -188,25 +227,55 @@ impl DB {
&self,
command: &str,
json_str: String,
- col_name: Option,
+ col_id: Option,
) -> Result<(), rusqlite::Error> {
let mut stmt = self.conn.prepare(
"INSERT INTO commands (command, curl_json, collection_id) VALUES (?1, ?2, ?3)",
)?;
- let _ = stmt.execute(params![command, &json_str, col_name])?;
+ let _ = stmt.execute(params![command, &json_str, col_id])?;
Ok(())
}
+ pub fn set_command_description(
+ &self,
+ id: i32,
+ description: &str,
+ ) -> Result