A better Rust ATProto crate
1//! Extract AT Protocol lexicon schemas from compiled Rust types via inventory 2//! 3//! This example discovers types with `#[derive(LexiconSchema)]` via inventory 4//! and generates lexicon JSON files. This approach requires types to be linked 5//! into the binary at compile time. 6//! 7//! For workspace-wide schema extraction without linking requirements, 8//! use the `extract-schemas` binary or `WorkspaceDiscovery` API instead. 9 10use clap::Parser; 11use jacquard_lexgen::schema_extraction::{self, ExtractOptions, SchemaExtractor}; 12use miette::Result; 13 14/// Extract lexicon schemas from compiled Rust types via inventory 15#[derive(Parser, Debug)] 16#[command(name = "extract-inventory")] 17#[command(about = "Extract AT Protocol lexicon schemas from linked Rust types")] 18#[command(long_about = r#" 19Discovers types implementing LexiconSchema via inventory and generates 20lexicon JSON files. The binary only discovers types that are linked, 21so you need to import your schema types in this binary or a custom one. 22 23For workspace-wide extraction, use the extract-schemas binary instead. 24 25See: https://docs.rs/jacquard-lexgen/latest/jacquard_lexgen/schema_extraction/ 26"#)] 27struct Args { 28 /// Output directory for generated schema files 29 #[arg(short, long, default_value = "lexicons")] 30 output: String, 31 32 /// Verbose output 33 #[arg(short, long)] 34 verbose: bool, 35 36 /// Filter by NSID prefix (e.g., "app.bsky") 37 #[arg(short, long)] 38 filter: Option<String>, 39 40 /// Validate schemas before writing 41 #[arg(short = 'V', long, default_value = "true")] 42 validate: bool, 43 44 /// Pretty-print JSON output 45 #[arg(short, long, default_value = "true")] 46 pretty: bool, 47 48 /// Watch mode - regenerate on changes 49 #[arg(short, long)] 50 watch: bool, 51} 52 53fn main() -> Result<()> { 54 let args = Args::parse(); 55 56 // Simple case: use convenience function 57 if !args.watch && args.filter.is_none() && args.validate && args.pretty { 58 return schema_extraction::run(&args.output, args.verbose); 59 } 60 61 // Advanced case: use full options 62 let options = ExtractOptions { 63 output_dir: args.output.into(), 64 verbose: args.verbose, 65 filter: args.filter, 66 validate: args.validate, 67 pretty: args.pretty, 68 }; 69 70 let extractor = SchemaExtractor::new(options); 71 72 if args.watch { 73 extractor.watch()?; 74 } else { 75 extractor.extract_all()?; 76 } 77 78 Ok(()) 79}