cli.rs
1 use std::{fs, path::Path}; 2 3 use anstyle::{AnsiColor, Style}; 4 use apibara_observability::init_opentelemetry; 5 use apibara_script::{Script, ScriptOptions}; 6 use clap::builder::Styles; 7 use error_stack::{report, Result, ResultExt}; 8 use tokio_util::sync::CancellationToken; 9 10 use crate::{SinkError, SinkErrorReportExt, SinkErrorResultExt}; 11 12 pub fn load_script_from_path(path: &Path, options: ScriptOptions) -> Result<Script, SinkError> { 13 let path = path.to_string_lossy(); 14 load_script(&path, options) 15 } 16 17 /// Load a script from a file. 18 pub fn load_script(path: &str, options: ScriptOptions) -> Result<Script, SinkError> { 19 let Ok(_) = fs::metadata(path) else { 20 return Err(SinkError::load_script(&format!( 21 "script file not found: {}", 22 path 23 ))); 24 }; 25 26 let current_dir = std::env::current_dir().load_script("failed to get current directory")?; 27 28 let script = Script::from_file(path, current_dir, options).map_err(|err| { 29 report!(err).load_script(&format!("failed to load script at path: {}", path)) 30 })?; 31 32 Ok(script) 33 } 34 35 /// Initialize opentelemetry and the sigint (ctrl-c) handler. 36 pub fn initialize_sink(ct: CancellationToken) -> Result<(), SinkError> { 37 init_opentelemetry() 38 .map_err(|err| report!(err).configuration("failed to initialize opentelemetry"))?; 39 40 set_ctrlc_handler(ct).map_err(|err| report!(err).fatal("failed to setup ctrl-c handler"))?; 41 42 Ok(()) 43 } 44 45 /// Connect the cancellation token to the ctrl-c handler. 46 pub fn set_ctrlc_handler(ct: CancellationToken) -> Result<(), ctrlc::Error> { 47 ctrlc::set_handler({ 48 move || { 49 ct.cancel(); 50 } 51 }) 52 .attach_printable("failed to register ctrl-c handler")?; 53 54 Ok(()) 55 } 56 57 /// A clap style for all Apibara CLI applications. 58 pub fn apibara_cli_style() -> Styles { 59 Styles::styled() 60 .header(Style::new().bold().fg_color(Some(AnsiColor::Yellow.into()))) 61 .error(Style::new().bold().fg_color(Some(AnsiColor::Red.into()))) 62 .usage(Style::new().bold().fg_color(Some(AnsiColor::Yellow.into()))) 63 .literal(Style::new().fg_color(Some(AnsiColor::BrightCyan.into()))) 64 .placeholder(Style::new()) 65 .valid(Style::new().fg_color(Some(AnsiColor::BrightBlue.into()))) 66 .invalid( 67 Style::new() 68 .underline() 69 .fg_color(Some(AnsiColor::Red.into())), 70 ) 71 }