Library Usage
The adrs-core crate provides a Rust library for working with ADRs programmatically.
Installation
Add to your Cargo.toml:
[dependencies]
adrs-core = "0.4"
Basic Usage
Opening a Repository
use adrs_core::Repository; use std::path::Path; fn main() -> anyhow::Result<()> { // Open existing repository let repo = Repository::open(Path::new("."))?; // Or create with defaults if it doesn't exist let repo = Repository::open_or_default(Path::new("."))?; Ok(()) }
Listing ADRs
use adrs_core::Repository; fn main() -> anyhow::Result<()> { let repo = Repository::open(Path::new("."))?; for adr in repo.list()? { println!("{}: {} [{}]", adr.number, adr.title, adr.status); } Ok(()) }
Creating an ADR
use adrs_core::{Repository, Adr, AdrStatus}; fn main() -> anyhow::Result<()> { let repo = Repository::open(Path::new("."))?; let adr = Adr::new( repo.next_number()?, "Use PostgreSQL for persistence".to_string(), ); let path = repo.create(&adr)?; println!("Created: {}", path.display()); Ok(()) }
Finding an ADR
use adrs_core::Repository; fn main() -> anyhow::Result<()> { let repo = Repository::open(Path::new("."))?; // By number let adr = repo.get(1)?; // By search term (fuzzy) let adr = repo.find("postgresql")?; Ok(()) }
Linking ADRs
use adrs_core::{Repository, LinkKind}; fn main() -> anyhow::Result<()> { let repo = Repository::open(Path::new("."))?; repo.link( 3, // source LinkKind::Amends, // link type 1, // target LinkKind::AmendedBy, // reverse link type )?; Ok(()) }
Configuration
Loading Configuration
use adrs_core::{Config, discover}; use std::path::Path; fn main() -> anyhow::Result<()> { // Discover configuration from current directory let discovered = discover(Path::new("."))?; println!("Project root: {}", discovered.root.display()); println!("ADR directory: {}", discovered.config.adr_dir.display()); println!("Source: {:?}", discovered.source); Ok(()) }
Creating Configuration
#![allow(unused)] fn main() { use adrs_core::Config; let config = Config { adr_dir: "decisions".into(), mode: adrs_core::ConfigMode::NextGen, ..Default::default() }; }
Templates
Using Built-in Templates
use adrs_core::{TemplateEngine, TemplateFormat, TemplateVariant, Adr}; fn main() -> anyhow::Result<()> { let engine = TemplateEngine::new(TemplateFormat::Madr, TemplateVariant::Minimal); let adr = Adr::new(1, "My Decision".to_string()); let content = engine.render(&adr)?; println!("{}", content); Ok(()) }
Custom Templates
use adrs_core::{TemplateEngine, Adr}; use std::path::Path; fn main() -> anyhow::Result<()> { let engine = TemplateEngine::from_file(Path::new("templates/custom.md"))?; let adr = Adr::new(1, "My Decision".to_string()); let content = engine.render(&adr)?; Ok(()) }
Parsing ADRs
Parse from File
use adrs_core::Parser; use std::path::Path; fn main() -> anyhow::Result<()> { let parser = Parser::new(); let adr = parser.parse_file(Path::new("doc/adr/0001-record-decisions.md"))?; println!("Title: {}", adr.title); println!("Status: {}", adr.status); println!("Date: {:?}", adr.date); for link in &adr.links { println!("Link: {} -> ADR {}", link.kind, link.target); } Ok(()) }
Parse from String
use adrs_core::Parser; fn main() -> anyhow::Result<()> { let content = r#" 1. Use PostgreSQL Date: 2024-01-15 # Status Accepted # Context We need a database. # Decision Use PostgreSQL. # Consequences None significant. "#; let parser = Parser::new(); let adr = parser.parse(content, Some(1))?; Ok(()) }
Health Checks
use adrs_core::{Repository, doctor_check}; fn main() -> anyhow::Result<()> { let repo = Repository::open(Path::new("."))?; let report = doctor_check(&repo)?; for diagnostic in &report.diagnostics { println!("[{:?}] {}: {}", diagnostic.severity, diagnostic.check, diagnostic.message ); } if report.has_errors() { std::process::exit(1); } Ok(()) }
Types
AdrStatus
#![allow(unused)] fn main() { use adrs_core::AdrStatus; let status = AdrStatus::Accepted; let status = AdrStatus::Superseded; let status = AdrStatus::Custom("In Review".to_string()); }
LinkKind
#![allow(unused)] fn main() { use adrs_core::LinkKind; let kind = LinkKind::Supersedes; let kind = LinkKind::AmendedBy; let kind = LinkKind::Custom("Depends on".to_string()); }
Error Handling
The library uses thiserror for error types:
use adrs_core::{Repository, Error}; fn main() { match Repository::open(Path::new(".")) { Ok(repo) => { /* use repo */ } Err(Error::NotFound(path)) => { eprintln!("ADR repository not found at {}", path.display()); } Err(e) => { eprintln!("Error: {}", e); } } }
Feature Flags
The adrs-core crate has no optional features currently. All functionality is included by default.
API Documentation
Full API documentation is available on docs.rs.