nginx_discovery/lib.rs
1//! # nginx-discovery
2//!
3//! Discover and introspect NGINX configurations with ease.
4//!
5//! This crate provides three levels of API for working with NGINX configurations:
6//!
7//! 1. **High-level Discovery API**: Simple methods for common use cases
8//! 2. **Mid-level Extractors**: Type-safe directive extraction
9//! 3. **Low-level Parser**: Direct AST access for custom processing
10//!
11//! ## Quick Start
12//!
13//! ```
14//! use nginx_discovery::prelude::*;
15//!
16//! # fn main() -> nginx_discovery::Result<()> {
17//! // Parse configuration text
18//! let config = r"
19//! http {
20//! access_log /var/log/nginx/access.log;
21//! }
22//! ";
23//!
24//! let discovery = NginxDiscovery::from_config_text(config)?;
25//!
26//! // Get access logs
27//! for log in discovery.access_logs() {
28//! println!("Log: {}", log.path.display());
29//! }
30//!
31//! // Get all server names
32//! for name in discovery.server_names() {
33//! println!("Server: {}", name);
34//! }
35//! # Ok(())
36//! # }
37//! ```
38//!
39//! ## Feature Flags
40//!
41//! - `system` (default): System interaction (detect nginx, run nginx -T)
42//! - `serde`: JSON/YAML serialization support
43//! - `visitor`: Visitor pattern for AST traversal
44//! - `includes`: Include directive resolution
45//! - `cli`: Command-line interface (binary only)
46//!
47//! ## Examples
48//!
49//! ### Extract Log Files
50//!
51//! ```
52//! use nginx_discovery::prelude::*;
53//!
54//! # fn main() -> nginx_discovery::Result<()> {
55//! let config = r"
56//! access_log /var/log/nginx/access.log combined;
57//! log_format combined '$remote_addr $request';
58//! ";
59//!
60//! let discovery = NginxDiscovery::from_config_text(config)?;
61//! let logs = discovery.access_logs();
62//!
63//! for log in logs {
64//! println!("Path: {}", log.path.display());
65//! if let Some(format_name) = &log.format_name {
66//! println!("Format: {}", format_name);
67//! }
68//! }
69//! # Ok(())
70//! # }
71//! ```
72//!
73//! ### Parse from File
74//!
75//! ```no_run
76//! use nginx_discovery::prelude::*;
77//!
78//! # fn main() -> nginx_discovery::Result<()> {
79//! let discovery = NginxDiscovery::from_config_file("/etc/nginx/nginx.conf")?;
80//! let logs = discovery.access_logs();
81//! println!("Found {} access logs", logs.len());
82//! # Ok(())
83//! # }
84//! ```
85//!
86//! ### Mid-level API
87//!
88//! ```
89//! use nginx_discovery::{parse, extract};
90//!
91//! # fn main() -> nginx_discovery::Result<()> {
92//! let config_text = "access_log /var/log/nginx/access.log;";
93//! let config = parse(config_text)?;
94//!
95//! let logs = extract::access_logs(&config)?;
96//! assert_eq!(logs.len(), 1);
97//! # Ok(())
98//! # }
99//! ```
100//!
101//! ### Low-level Parser
102//!
103//! ```
104//! use nginx_discovery::parse;
105//!
106//! # fn main() -> nginx_discovery::Result<()> {
107//! let config = parse("user nginx;")?;
108//! assert_eq!(config.directives.len(), 1);
109//! assert_eq!(config.directives[0].name(), "user");
110//! # Ok(())
111//! # }
112//! ```
113
114#![warn(missing_docs)]
115#![warn(clippy::all)]
116#![warn(clippy::pedantic)]
117#![cfg_attr(docsrs, feature(doc_cfg))]
118
119// Public modules
120pub mod ast;
121pub mod error;
122pub mod error_builder;
123pub mod extract;
124pub mod parser;
125
126#[cfg(feature = "system")]
127#[cfg_attr(docsrs, doc(cfg(feature = "system")))]
128pub mod system;
129
130pub mod types;
131
132#[cfg(feature = "visitor")]
133#[cfg_attr(docsrs, doc(cfg(feature = "visitor")))]
134pub mod visitor;
135
136#[cfg(feature = "serde")]
137pub mod export;
138
139#[cfg(feature = "network")]
140pub mod network;
141
142// High-level API
143mod discovery;
144pub use discovery::NginxDiscovery;
145
146// Re-exports for convenience
147pub use error::{Error, Result};
148pub use parser::parse;
149
150/// Commonly used imports for quick setup
151///
152/// ```rust
153/// use nginx_discovery::prelude::*;
154/// ```
155pub mod prelude {
156 pub use crate::discovery::NginxDiscovery;
157 pub use crate::error::{Error, Result};
158 pub use crate::error_builder::ErrorBuilder;
159 pub use crate::parser::{Lexer, Parser, Token, TokenKind};
160 pub use crate::types::*;
161}
162
163#[cfg(test)]
164mod tests {
165 use super::*;
166
167 #[test]
168 fn test_basic_parse() {
169 let config = r"
170 user nginx;
171 worker_processes auto;
172 ";
173
174 let result = parse(config);
175 assert!(result.is_ok());
176
177 let config = result.unwrap();
178 assert_eq!(config.directives.len(), 2);
179 assert_eq!(config.directives[0].name(), "user");
180 assert_eq!(config.directives[1].name(), "worker_processes");
181 }
182
183 #[test]
184 fn test_discovery_from_text() {
185 let config = "user nginx;";
186 let discovery = NginxDiscovery::from_config_text(config);
187 assert!(discovery.is_ok());
188 }
189
190 #[test]
191 fn test_prelude_imports() {
192 use crate::prelude::*;
193
194 let config = "user nginx;";
195 let discovery = NginxDiscovery::from_config_text(config).unwrap();
196 assert_eq!(discovery.config().directives.len(), 1);
197 }
198}