Skip to main content

fraiseql_server/
lib.rs

1//! FraiseQL HTTP Server
2//!
3//! HTTP server for FraiseQL v2 compiled GraphQL execution engine.
4//!
5//! # Architecture
6//!
7//! The server exposes a GraphQL HTTP endpoint that:
8//! 1. Receives GraphQL queries via POST
9//! 2. Executes queries using the runtime Executor
10//! 3. Returns GraphQL-compliant JSON responses
11//!
12//! # Features
13//!
14//! - GraphQL endpoint (`/graphql`)
15//! - Health check endpoint (`/health`)
16//! - Schema introspection endpoint (`/introspection`)
17//! - CORS support
18//! - Compression (gzip, br, zstd)
19//! - Request tracing
20//! - APQ (Automatic Persisted Queries)
21//! - Query caching
22//! - Authentication middleware (optional)
23
24#![forbid(unsafe_code)]
25// Allowing missing_docs to focus on actionable warnings
26#![allow(missing_docs)]
27#![warn(clippy::all)]
28#![warn(clippy::pedantic)]
29// Allow common pedantic lints that are too noisy for this codebase
30#![allow(clippy::struct_excessive_bools)] // ServerConfig uses bools for flags
31#![allow(clippy::cast_possible_truncation)] // Intentional u128->u64 casts for metrics
32#![allow(clippy::cast_precision_loss)] // Intentional f64 conversions for averages
33#![allow(clippy::doc_markdown)] // Would require extensive backtick additions
34#![allow(clippy::module_name_repetitions)] // Common in Rust APIs
35#![allow(clippy::must_use_candidate)] // Too noisy for builder methods
36#![allow(clippy::missing_errors_doc)] // Would require extensive doc additions
37#![allow(clippy::missing_panics_doc)] // Would require extensive doc additions
38#![allow(clippy::needless_pass_by_value)] // Sometimes clearer API
39#![allow(clippy::unused_async)] // Placeholder for future async work
40#![allow(clippy::similar_names)] // Variable naming style
41#![allow(clippy::unused_self)] // Often needed for trait consistency
42#![allow(clippy::match_same_arms)] // Sometimes clearer to be explicit
43#![allow(clippy::double_must_use)] // CorsLayer already has must_use
44#![allow(clippy::unnecessary_wraps)] // Sometimes needed for API consistency
45#![allow(clippy::return_self_not_must_use)] // Builder pattern doesn't always need #[must_use]
46#![allow(clippy::too_many_lines)] // Some functions are necessarily long
47#![allow(clippy::cast_sign_loss)] // Intentional signed->unsigned conversions
48#![allow(clippy::missing_fields_in_debug)] // Some fields are intentionally excluded from Debug
49#![allow(clippy::default_trait_access)] // Style preference
50#![allow(clippy::wildcard_imports)] // Used in tests
51#![allow(clippy::items_after_statements)] // Sometimes clearer to define items near usage
52#![allow(clippy::no_effect_underscore_binding)] // Used for future placeholders
53#![allow(clippy::cast_possible_wrap)] // Intentional for timestamp conversions
54#![allow(clippy::struct_field_names)] // Field naming style
55#![allow(clippy::single_char_pattern)] // String patterns are clearer
56#![allow(clippy::elidable_lifetime_names)] // Explicit lifetimes are clearer
57#![allow(clippy::manual_let_else)] // Style preference
58#![allow(clippy::redundant_closure)] // Sometimes clearer to have explicit closure
59#![allow(clippy::unchecked_time_subtraction)] // Checked arithmetic overkill for durations
60#![allow(clippy::uninlined_format_args)] // Style preference
61#![allow(clippy::unnested_or_patterns)] // Style preference
62#![allow(clippy::used_underscore_binding)] // Intentional placeholder bindings
63#![allow(clippy::cast_lossless)] // Explicit casts are clearer
64#![allow(clippy::format_push_string)] // Sometimes clearer than write!
65#![allow(clippy::if_same_then_else)] // Sometimes intentional for clarity
66#![allow(clippy::ignored_unit_patterns)] // Style preference
67#![allow(clippy::map_unwrap_or)] // Style preference
68#![allow(clippy::redundant_closure_for_method_calls)] // Style preference
69#![allow(clippy::single_match_else)] // Sometimes clearer than if-let
70#![allow(clippy::unnecessary_debug_formatting)] // Debug is useful for logging
71#![allow(clippy::useless_format)] // Sometimes needed for type inference
72#![allow(clippy::float_cmp)] // Test assertions with exact float comparison are intentional
73
74// Original fraiseql-server modules
75pub mod api;
76pub mod error;
77pub mod extractors;
78pub mod federation;
79pub mod logging;
80pub mod middleware;
81pub mod performance;
82pub mod routes;
83pub mod schema;
84pub mod server;
85pub mod server_config;
86pub mod subscriptions;
87pub mod validation;
88
89// Renamed to avoid conflicts with runtime modules
90pub mod metrics_server;
91pub mod tracing_server;
92
93// fraiseql-runtime modules (merged)
94pub mod config;
95pub mod lifecycle;
96pub mod observability;
97pub mod operational;
98pub mod resilience;
99pub mod runtime_state;
100pub mod tracing_utils;
101
102// fraiseql-webhooks modules (merged)
103pub mod webhooks;
104
105// fraiseql-files modules (merged)
106pub mod files;
107
108// Authentication modules
109pub mod auth;
110
111// Secrets management
112pub mod secrets;
113
114// Phase 12: Secrets Manager Interface
115pub mod secrets_manager;
116
117// Field-level encryption for sensitive database fields
118pub mod encryption;
119
120// Backup and disaster recovery
121pub mod backup;
122
123// TLS/SSL and encryption
124pub mod tls;
125pub mod tls_listener;
126
127// Observer management - optional
128#[cfg(feature = "observers")]
129pub mod observers;
130
131// Arrow Flight integration - optional
132#[cfg(feature = "arrow")]
133pub mod arrow;
134
135// Testing utilities
136#[cfg(any(test, feature = "testing"))]
137pub mod testing;
138
139pub use logging::{
140    ErrorDetails, LogLevel, LogMetrics, RequestContext, RequestId, RequestLogger, SourceLocation,
141    StructuredLogEntry,
142};
143pub use metrics_server::{MetricsCollector, PrometheusMetrics};
144pub use performance::{
145    OperationProfile, PerformanceMonitor, PerformanceStats, PerformanceTimer, QueryPerformance,
146};
147pub use schema::CompiledSchemaLoader;
148pub use secrets::SecretManager;
149pub use server::Server;
150pub use server_config::ServerConfig;
151pub use tls::TlsSetup;
152pub use tracing_server::{SpanStatus, TraceContext, TraceEvent, TraceParseError, TraceSpan};
153pub use validation::{RequestValidator, ValidationError};
154
155/// Server error type.
156#[derive(Debug, thiserror::Error)]
157pub enum ServerError {
158    /// Server binding error.
159    #[error("Failed to bind server: {0}")]
160    BindError(String),
161
162    /// Configuration error.
163    #[error("Configuration error: {0}")]
164    ConfigError(String),
165
166    /// Runtime error.
167    #[error("Runtime error: {0}")]
168    RuntimeError(#[from] fraiseql_core::error::FraiseQLError),
169
170    /// IO error.
171    #[error("IO error: {0}")]
172    IoError(#[from] std::io::Error),
173
174    /// Database error.
175    #[error("Database error: {0}")]
176    Database(String),
177
178    /// Validation error.
179    #[error("Validation error: {0}")]
180    Validation(String),
181
182    /// Resource conflict error.
183    #[error("Conflict: {0}")]
184    Conflict(String),
185
186    /// Resource not found error.
187    #[error("Not found: {0}")]
188    NotFound(String),
189}
190
191/// Server result type.
192pub type Result<T> = std::result::Result<T, ServerError>;