pub mod api;
mod commands;
mod storage;
mod tui;
mod types;
mod utils;
#[cfg(feature = "python")]
mod sync_api;
#[cfg(feature = "python")]
mod python_bindings;
pub use storage::PromptVault;
pub use types::{VersionMeta, VersionSelector};
pub use utils::default_vault_path;
#[cfg(feature = "python")]
pub use sync_api::SyncPromptManager;
pub fn run_cli_from_args(args: Vec<String>) -> anyhow::Result<()> {
use clap::Parser;
#[derive(Parser)]
#[command(author, version, about, long_about = None)]
struct Cli {
#[command(subcommand)]
command: Commands,
}
#[derive(clap::Subcommand)]
enum Commands {
Init {
#[arg(long)]
path: Option<String>,
},
Add {
content: String,
},
Update {
key: String,
content: String,
#[arg(short, long)]
message: Option<String>,
},
Get {
key: String,
selector: Option<String>,
#[arg(short, long)]
output: Option<String>,
},
History {
key: String,
},
Tag {
key: String,
tag: String,
version: Option<u64>,
},
Promote {
key: String,
tag: String,
},
Tui,
Edit {
key: String,
},
Dump {
output: String,
#[arg(long)]
password: Option<String>,
},
Resume {
input: String,
#[arg(long)]
password: Option<String>,
},
Delete {
key: String,
},
}
let cli_args = if !args.is_empty() {
args
} else {
vec!["promptpro".to_string()] };
let cli = Cli::try_parse_from(cli_args)?;
tokio::runtime::Runtime::new()?.block_on(async {
match cli.command {
Commands::Init { path } => commands::init(path).await,
Commands::Add { content } => commands::add(content).await,
Commands::Update { key, content, message } => commands::update(key, content, message).await,
Commands::Get { key, selector, output } => commands::get(key, selector, output).await,
Commands::History { key } => commands::history(key).await,
Commands::Tag { key, tag, version } => commands::tag(key, tag, version).await,
Commands::Promote { key, tag } => commands::promote(key, tag).await,
Commands::Tui => commands::tui().await,
Commands::Edit { key } => commands::edit(key).await,
Commands::Dump { output, password } => commands::dump(output, password).await,
Commands::Resume { input, password } => commands::resume(input, password).await,
Commands::Delete { key } => commands::delete(key).await,
}
})
}
use anyhow::Result;
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_library_api() -> Result<()> {
use tempfile::tempdir;
let dir = tempdir()?;
let vault = PromptVault::open(dir.path())?;
vault.add("greet", "hello world")?;
let text = vault.get("greet", VersionSelector::Latest)?;
assert_eq!(text, "hello world");
vault.update("greet", "hi there", Some("test update".to_string()))?;
let text = vault.get("greet", VersionSelector::Latest)?;
assert_eq!(text, "hi there");
vault.tag("greet", "stable", 1)?; let text = vault.get("greet", VersionSelector::Tag("stable"))?;
assert_eq!(text, "hello world");
let history = vault.history("greet")?;
assert_eq!(history.len(), 2);
Ok(())
}
}