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
26// CLI argument parsing (shared with fraiseql-cli) — requires `cli` feature
27#[cfg(feature = "cli")]
28pub mod cli;
29// API key authentication
30pub mod api_key;
31// Token revocation
32pub mod token_revocation;
33
34// Original fraiseql-server modules
35pub mod api;
36pub mod error;
37pub mod extractors;
38#[cfg(feature = "federation")]
39pub mod federation;
40pub mod logging;
41pub mod middleware;
42pub mod routes;
43pub mod schema;
44pub mod server;
45pub mod server_config;
46pub mod subscriptions;
47pub mod url_guard;
48pub mod validation;
49
50// Renamed to avoid conflicts with runtime modules
51pub mod metrics_server;
52
53// fraiseql-runtime modules (merged)
54
55/// Runtime configuration types loaded from `fraiseql.toml` or environment variables.
56pub mod config;
57/// Resilience primitives: backpressure and retry policies.
58pub mod resilience;
59/// Utilities for distributed tracing, span propagation, and trace context formatting.
60#[cfg(feature = "federation")]
61pub mod tracing_utils;
62#[cfg(not(feature = "federation"))]
63pub mod tracing_utils {
64    //! Stub tracing utilities when federation is disabled.
65    use axum::http::HeaderMap;
66
67    /// Stub trace context extraction when federation is disabled.
68    #[allow(clippy::missing_const_for_fn)] // Reason: signature must match federation-enabled version which is not const
69    #[must_use]
70    pub fn extract_trace_context(_headers: &HeaderMap) -> Option<()> {
71        None
72    }
73}
74
75// Webhooks (extracted to fraiseql-webhooks crate) — optional, enable with `features = ["webhooks"]`
76// Authentication (extracted to fraiseql-auth crate) — optional, enable with `features =
77// ["auth"]`
78#[cfg(feature = "auth")]
79pub use fraiseql_auth as auth;
80#[cfg(feature = "webhooks")]
81pub use fraiseql_webhooks as webhooks;
82
83/// Stub auth types compiled when the `auth` feature is disabled.
84///
85/// These zero-sized types allow internal code that references `crate::auth::*` to compile
86/// in no-auth builds without requiring every call-site to be cfg-gated.  All stub methods
87/// are pure stubs that the compiler will dead-code-eliminate.
88#[cfg(not(feature = "auth"))]
89pub mod auth {
90    use std::sync::Arc;
91
92    /// Stub for `fraiseql_auth::state_encryption::StateEncryptionService`.
93    pub mod state_encryption {
94        /// Zero-sized stub; never instantiated when `auth` feature is off.
95        pub struct StateEncryptionService;
96        impl StateEncryptionService {
97            /// Stub: returns `None`.
98            ///
99            /// # Errors
100            ///
101            /// Currently infallible — always returns `Ok(None)`.
102            /// Errors may be returned when the `auth` feature is enabled.
103            pub fn from_compiled_schema(
104                _s: &serde_json::Value,
105            ) -> crate::Result<Option<std::sync::Arc<Self>>> {
106                Ok(None)
107            }
108        }
109    }
110
111    /// Stub for `fraiseql_auth::PkceStateStore`.
112    pub struct PkceStateStore;
113    impl PkceStateStore {
114        /// Stub: always returns `true` (in-memory).
115        pub fn is_in_memory(&self) -> bool {
116            true
117        }
118
119        /// Stub: no-op.
120        pub async fn cleanup_expired(&self) {}
121    }
122
123    /// Stub for `fraiseql_auth::OidcServerClient`.
124    pub struct OidcServerClient;
125    impl OidcServerClient {
126        /// Stub: always returns `None`.
127        pub fn from_compiled_schema(_schema_json: &serde_json::Value) -> Option<Arc<Self>> {
128            None
129        }
130    }
131}
132
133// Secrets management and encryption (extracted to fraiseql-secrets crate) — optional, enable with
134// `features = ["secrets"]`
135#[cfg(feature = "secrets")]
136pub use fraiseql_secrets::{encryption, secrets_manager};
137
138// TLS/SSL and encryption
139pub mod tls;
140
141// Observer management - optional
142#[cfg(feature = "observers")]
143pub mod observers;
144
145// Arrow Flight integration - optional
146#[cfg(feature = "arrow")]
147pub mod arrow;
148
149// MCP (Model Context Protocol) server - optional
150#[cfg(feature = "mcp")]
151pub mod mcp;
152
153// Connection pool management and auto-tuning
154pub mod pool;
155
156// Realtime WebSocket server — entity change streams (complementary to subscriptions/)
157pub mod realtime;
158
159// Object storage backends (local, S3, GCS, Azure Blob)
160pub mod storage;
161
162// Server subsystem assembly and lifecycle management
163pub mod subsystems;
164
165// Trusted documents (query allowlist)
166pub mod trusted_documents;
167
168// Multi-tenancy: pool factory, executor construction, health monitoring
169pub mod tenancy;
170
171// Usage aggregation: in-memory mutation counters fed by tracing events
172pub mod usage;
173
174// Testing utilities
175#[cfg(any(test, feature = "testing"))]
176pub mod testing;
177
178#[cfg(test)]
179mod tests;
180
181#[cfg(feature = "cli")]
182pub use cli::{Cli, ServerArgs};
183pub use logging::{
184    ErrorDetails, LogLevel, LogMetrics, RequestContext, RequestId, RequestLogger, SourceLocation,
185    StructuredLogEntry,
186};
187pub use metrics_server::{MetricsCollector, PrometheusMetrics};
188pub use schema::CompiledSchemaLoader;
189pub use server::Server;
190pub use server_config::ServerConfig;
191pub use tls::TlsSetup;
192pub use validation::{ComplexityValidationError, RequestValidator};
193
194/// Convenience re-exports for building a FraiseQL HTTP server.
195///
196/// Provides [`Server`], [`ServerConfig`], `CompiledSchema`, and [`RequestValidator`].
197///
198/// ```rust
199/// use fraiseql_server::prelude::*;
200/// ```
201pub mod prelude {
202    pub use fraiseql_core::schema::CompiledSchema;
203
204    pub use crate::{
205        ComplexityValidationError, RequestValidator, Server, ServerConfig, ServerError, TlsSetup,
206    };
207}
208
209/// Server error type.
210#[derive(Debug, thiserror::Error)]
211#[non_exhaustive]
212pub enum ServerError {
213    /// Server binding error.
214    #[error("Failed to bind server: {0}")]
215    BindError(String),
216
217    /// Configuration error.
218    #[error("Configuration error: {0}")]
219    ConfigError(String),
220
221    /// Error from the FraiseQL execution engine (parse, validate, execute, …).
222    ///
223    /// Wraps the canonical [`fraiseql_core::error::FraiseQLError`] so engine
224    /// failures bubble up through `ServerError` without losing the structured
225    /// payload. The original variant name (`RuntimeError`) collided with the
226    /// retired `fraiseql_error::RuntimeError` HTTP-shaped enum; `Engine`
227    /// reflects what the variant actually wraps.
228    #[error("Engine error: {0}")]
229    Engine(#[from] fraiseql_core::error::FraiseQLError),
230
231    /// IO error.
232    #[error("IO error: {0}")]
233    IoError(#[from] std::io::Error),
234
235    /// Database error.
236    #[error("Database error: {0}")]
237    Database(String),
238
239    /// Validation error.
240    #[error("Validation error: {0}")]
241    Validation(String),
242
243    /// Resource conflict error.
244    #[error("Conflict: {0}")]
245    Conflict(String),
246
247    /// Resource not found error.
248    #[error("Not found: {0}")]
249    NotFound(String),
250}
251
252/// Server result type.
253pub type Result<T> = std::result::Result<T, ServerError>;