pub mod builder;
pub mod validator;
#[cfg(feature = "functions-runtime")]
pub mod loader;
#[cfg(test)]
mod tests;
use std::sync::Arc;
pub use builder::{ServerSubsystemsBuilder, SubsystemBuildError};
use fraiseql_functions::{FunctionObserver, triggers::TriggerRegistry};
pub use validator::{SubsystemConfigWarning, validate_subsystems_config};
use crate::schema::loader::{FunctionsConfig, SchemaStorageConfig};
pub struct StorageSubsystem {
pub state: fraiseql_storage::StorageState,
pub schema_config: SchemaStorageConfig,
}
pub struct FunctionsSubsystem {
pub observer: Arc<FunctionObserver>,
pub trigger_registry: TriggerRegistry,
pub module_registry: std::collections::HashMap<String, fraiseql_functions::FunctionModule>,
pub config: FunctionsConfig,
}
#[allow(missing_debug_implementations)] pub struct ServerSubsystems {
pub storage: Option<StorageSubsystem>,
pub functions: Option<FunctionsSubsystem>,
}
impl ServerSubsystems {
#[must_use]
pub const fn none() -> Self {
Self {
storage: None,
functions: None,
}
}
#[must_use]
pub const fn is_storage_enabled(&self) -> bool {
self.storage.is_some()
}
#[must_use]
pub const fn is_functions_enabled(&self) -> bool {
self.functions.is_some()
}
}
pub struct BeforeMutationHooks {
pub trigger_registry: TriggerRegistry,
pub module_registry: std::collections::HashMap<String, fraiseql_functions::FunctionModule>,
pub observer: std::sync::Arc<FunctionObserver>,
#[cfg(feature = "functions-runtime")]
pub dlq: std::sync::Arc<dyn fraiseql_observers::DeadLetterQueue>,
#[cfg(feature = "functions-runtime")]
pub dispatch_settings:
std::collections::HashMap<String, crate::routes::after_mutation::FunctionDispatchSetting>,
#[cfg(feature = "functions-runtime")]
pub sender_resolver: Option<std::sync::Arc<dyn fraiseql_functions::SenderIdentityResolver>>,
#[cfg(feature = "functions-runtime")]
pub email_transport: Option<std::sync::Arc<dyn fraiseql_functions::EmailTransport>>,
#[cfg(feature = "functions-runtime")]
pub idempotency_key: Option<std::sync::Arc<[u8]>>,
#[cfg(feature = "functions-runtime")]
pub run_as: std::collections::HashMap<String, fraiseql_functions::RunAs>,
}
impl BeforeMutationHooks {
#[must_use]
pub fn new(
trigger_registry: TriggerRegistry,
module_registry: std::collections::HashMap<String, fraiseql_functions::FunctionModule>,
observer: Arc<FunctionObserver>,
) -> Self {
Self {
trigger_registry,
module_registry,
observer,
#[cfg(feature = "functions-runtime")]
dlq: Arc::new(crate::observers::runtime::InMemoryDlq::new_with_max(None)),
#[cfg(feature = "functions-runtime")]
dispatch_settings: std::collections::HashMap::new(),
#[cfg(feature = "functions-runtime")]
sender_resolver: None,
#[cfg(feature = "functions-runtime")]
email_transport: None,
#[cfg(feature = "functions-runtime")]
idempotency_key: None,
#[cfg(feature = "functions-runtime")]
run_as: std::collections::HashMap::new(),
}
}
#[cfg(feature = "functions-runtime")]
#[must_use]
pub fn with_idempotency_key(mut self, key: Option<std::sync::Arc<[u8]>>) -> Self {
self.idempotency_key = key;
self
}
#[cfg(feature = "functions-runtime")]
#[must_use]
pub fn with_email(
mut self,
sender_resolver: Arc<dyn fraiseql_functions::SenderIdentityResolver>,
email_transport: Arc<dyn fraiseql_functions::EmailTransport>,
) -> Self {
self.sender_resolver = Some(sender_resolver);
self.email_transport = Some(email_transport);
self
}
#[cfg(feature = "functions-runtime")]
#[must_use]
pub fn with_dlq(mut self, dlq: Arc<dyn fraiseql_observers::DeadLetterQueue>) -> Self {
self.dlq = dlq;
self
}
}
#[cfg(feature = "functions-runtime")]
impl FunctionsSubsystem {
#[must_use]
pub fn into_before_mutation_hooks(self) -> BeforeMutationHooks {
use crate::routes::after_mutation::{DispatchDefaults, resolve_dispatch_settings};
let defaults = DispatchDefaults::from_env();
let dispatch_settings = resolve_dispatch_settings(&self.config.definitions, &defaults);
let dlq = std::sync::Arc::new(crate::observers::runtime::InMemoryDlq::new_with_max(
defaults.dlq_max_size,
));
let run_as = self
.config
.definitions
.iter()
.filter_map(|def| def.run_as.clone().map(|ceiling| (def.name.clone(), ceiling)))
.collect();
BeforeMutationHooks {
trigger_registry: self.trigger_registry,
module_registry: self.module_registry,
observer: self.observer,
dlq,
dispatch_settings,
sender_resolver: None,
email_transport: None,
idempotency_key: None,
run_as,
}
}
}