pub use crate::introspection::*;
pub use crate::optimizer::*;
pub use crate::validation::*;
pub mod components {
pub mod optimization {
pub use crate::optimizer::*;
}
pub mod introspection {
pub use crate::introspection::*;
}
pub mod validation {
pub use crate::validation::*;
}
}
pub mod performance {
use std::collections::HashMap;
use std::time::{Duration, Instant};
#[derive(Debug, Clone)]
pub struct QueryMetrics {
pub query_hash: String,
pub execution_time: Duration,
pub complexity_score: usize,
pub depth: usize,
pub cache_hit: bool,
pub timestamp: Instant,
}
impl QueryMetrics {
pub fn new(
query_hash: String,
execution_time: Duration,
complexity_score: usize,
depth: usize,
cache_hit: bool,
) -> Self {
Self {
query_hash,
execution_time,
complexity_score,
depth,
cache_hit,
timestamp: Instant::now(),
}
}
}
#[derive(Debug, Default)]
pub struct PerformanceTracker {
metrics: Vec<QueryMetrics>,
slow_queries: Vec<QueryMetrics>,
slow_query_threshold: Duration,
}
impl PerformanceTracker {
pub fn new() -> Self {
Self {
metrics: Vec::new(),
slow_queries: Vec::new(),
slow_query_threshold: Duration::from_millis(1000), }
}
pub fn with_slow_query_threshold(mut self, threshold: Duration) -> Self {
self.slow_query_threshold = threshold;
self
}
pub fn record_query(&mut self, metrics: QueryMetrics) {
if metrics.execution_time > self.slow_query_threshold {
self.slow_queries.push(metrics.clone());
}
self.metrics.push(metrics);
}
pub fn get_average_execution_time(&self) -> Option<Duration> {
if self.metrics.is_empty() {
return None;
}
let total: Duration = self.metrics.iter().map(|m| m.execution_time).sum();
Some(total / self.metrics.len() as u32)
}
pub fn get_cache_hit_rate(&self) -> f64 {
if self.metrics.is_empty() {
return 0.0;
}
let cache_hits = self.metrics.iter().filter(|m| m.cache_hit).count();
cache_hits as f64 / self.metrics.len() as f64
}
pub fn get_slow_queries(&self) -> &[QueryMetrics] {
&self.slow_queries
}
pub fn get_complexity_distribution(&self) -> HashMap<usize, usize> {
let mut distribution = HashMap::new();
for metric in &self.metrics {
let bucket = (metric.complexity_score / 100) * 100; *distribution.entry(bucket).or_insert(0) += 1;
}
distribution
}
}
}
pub mod security {
pub struct SecurityPatterns;
impl SecurityPatterns {
pub fn has_dangerous_patterns(query: &str) -> bool {
let dangerous_keywords = [
"__schema",
"__type",
"mutation",
"subscription",
"introspection",
];
let query_lower = query.to_lowercase();
dangerous_keywords
.iter()
.any(|&keyword| query_lower.contains(keyword))
}
pub fn extract_operation_names(query: &str) -> Vec<String> {
let mut operations = Vec::new();
for line in query.lines() {
let line = line.trim();
if line.starts_with("query ")
|| line.starts_with("mutation ")
|| line.starts_with("subscription ")
{
if let Some(name_start) = line.find(' ') {
if let Some(name_end) = line[name_start + 1..].find([' ', '(', '{']) {
let name = &line[name_start + 1..name_start + 1 + name_end];
if !name.is_empty() {
operations.push(name.to_string());
}
}
}
}
}
operations
}
pub fn recommended_validation_config(
environment: Environment,
) -> crate::validation::ValidationConfig {
match environment {
Environment::Development => crate::validation::ValidationConfig {
max_depth: 15,
max_complexity: 2000,
max_aliases: 100,
max_root_fields: 50,
disable_introspection: false,
max_fragments: 100,
..Default::default()
},
Environment::Production => crate::validation::ValidationConfig {
max_depth: 8,
max_complexity: 1000,
max_aliases: 20,
max_root_fields: 15,
disable_introspection: true,
max_fragments: 25,
..Default::default()
},
Environment::Testing => crate::validation::ValidationConfig {
max_depth: 20,
max_complexity: 5000,
max_aliases: 200,
max_root_fields: 100,
disable_introspection: false,
max_fragments: 200,
..Default::default()
},
}
}
}
#[derive(Debug, Clone, Copy)]
pub enum Environment {
Development,
Production,
Testing,
}
}