#![forbid(unsafe_code)]
#[cfg(feature = "cli")]
pub mod cli;
pub mod api_key;
pub mod service_account;
pub mod token_revocation;
pub mod api;
#[cfg(feature = "functions-runtime")]
pub mod cron;
pub mod error;
pub mod extractors;
#[cfg(feature = "federation")]
pub mod federation;
#[cfg_attr(not(feature = "functions-runtime"), allow(dead_code))]
mod function_metrics;
pub mod logging;
pub mod middleware;
#[cfg(feature = "functions-runtime")]
pub mod query_bridge;
pub mod routes;
pub mod schema;
pub mod server;
pub mod server_config;
#[cfg(feature = "sources")]
pub mod sources;
pub mod sql_source_check;
pub mod subscriptions;
pub mod url_guard;
pub mod validation;
pub mod metrics_server;
#[cfg(feature = "metrics")]
pub mod metrics_recorder;
pub mod config;
pub mod resilience;
#[cfg(feature = "federation")]
pub mod tracing_utils;
#[cfg(not(feature = "federation"))]
pub mod tracing_utils {
use axum::http::HeaderMap;
#[allow(clippy::missing_const_for_fn)] #[must_use]
pub fn extract_trace_context(_headers: &HeaderMap) -> Option<()> {
None
}
#[must_use]
pub fn extract_trace_id(headers: &HeaderMap) -> Option<String> {
let value = headers.get("traceparent")?.to_str().ok()?;
let trace_id = value.split('-').nth(1)?;
let valid = trace_id.len() == 32
&& trace_id.bytes().all(|b| b.is_ascii_hexdigit())
&& trace_id.bytes().any(|b| b != b'0');
valid.then(|| trace_id.to_ascii_lowercase())
}
#[must_use]
pub fn extract_trace_context_json(headers: &HeaderMap) -> Option<serde_json::Value> {
let traceparent = headers.get("traceparent")?.to_str().ok()?;
let mut parts = traceparent.split('-');
let (version, trace_id, parent_id, trace_flags) =
(parts.next()?, parts.next()?, parts.next()?, parts.next()?);
let is_hex =
|s: &str, len: usize| s.len() == len && s.bytes().all(|b| b.is_ascii_hexdigit());
let valid = is_hex(version, 2)
&& is_hex(trace_id, 32)
&& trace_id.bytes().any(|b| b != b'0')
&& is_hex(parent_id, 16)
&& is_hex(trace_flags, 2);
if !valid {
return None;
}
let mut obj = serde_json::Map::with_capacity(5);
obj.insert("version".to_owned(), version.to_ascii_lowercase().into());
obj.insert("trace_id".to_owned(), trace_id.to_ascii_lowercase().into());
obj.insert("parent_id".to_owned(), parent_id.to_ascii_lowercase().into());
obj.insert("trace_flags".to_owned(), trace_flags.to_ascii_lowercase().into());
if let Some(tracestate) = headers
.get("tracestate")
.and_then(|h| h.to_str().ok())
.map(str::trim)
.filter(|s| !s.is_empty())
{
obj.insert("tracestate".to_owned(), tracestate.into());
}
Some(serde_json::Value::Object(obj))
}
}
#[cfg(feature = "auth")]
pub use fraiseql_auth as auth;
#[cfg(feature = "webhooks")]
pub use fraiseql_webhooks as webhooks;
#[cfg(not(feature = "auth"))]
pub mod auth {
use std::sync::Arc;
pub mod state_encryption {
pub struct StateEncryptionService;
impl StateEncryptionService {
pub fn from_compiled_schema(
_s: &serde_json::Value,
) -> crate::Result<Option<std::sync::Arc<Self>>> {
Ok(None)
}
}
}
pub struct PkceStateStore;
impl PkceStateStore {
pub fn is_in_memory(&self) -> bool {
true
}
pub async fn cleanup_expired(&self) {}
}
pub struct OidcServerClient;
impl OidcServerClient {
pub fn from_compiled_schema(_schema_json: &serde_json::Value) -> Option<Arc<Self>> {
None
}
}
}
#[cfg(feature = "secrets")]
pub use fraiseql_secrets::{encryption, secrets_manager};
pub mod tls;
#[cfg(feature = "auth")]
pub mod identity;
#[cfg(feature = "observers")]
pub mod observers;
#[cfg(feature = "arrow")]
pub mod arrow;
#[cfg(feature = "mcp")]
pub mod mcp;
#[cfg(feature = "inbound")]
pub mod inbound;
pub mod pool;
pub mod storage;
pub mod subsystems;
pub mod trusted_documents;
pub mod tenancy;
pub mod usage;
#[cfg(any(test, feature = "testing"))]
pub mod testing;
#[cfg(test)]
mod tests;
#[cfg(feature = "cli")]
pub use cli::{Cli, ServerArgs};
pub use logging::{
ErrorDetails, LogLevel, LogMetrics, RequestContext, RequestId, RequestLogger, SourceLocation,
StructuredLogEntry,
};
pub use metrics_server::{MetricsCollector, PrometheusMetrics};
pub use schema::CompiledSchemaLoader;
pub use server::Server;
pub use server_config::ServerConfig;
pub use tls::TlsSetup;
pub use validation::{ComplexityValidationError, RequestValidator};
pub mod prelude {
pub use fraiseql_core::schema::CompiledSchema;
pub use crate::{
ComplexityValidationError, RequestValidator, Server, ServerConfig, ServerError, TlsSetup,
};
}
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum ServerError {
#[error("Failed to bind server: {0}")]
BindError(String),
#[error("Configuration error: {0}")]
ConfigError(String),
#[error("Engine error: {0}")]
Engine(#[from] fraiseql_core::error::FraiseQLError),
#[error("IO error: {0}")]
IoError(#[from] std::io::Error),
#[error("Database error: {0}")]
Database(String),
#[error("Validation error: {0}")]
Validation(String),
#[error("Conflict: {0}")]
Conflict(String),
#[error("Not found: {0}")]
NotFound(String),
}
pub type Result<T> = std::result::Result<T, ServerError>;