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