#![cfg(feature = "ssr")] pub mod oidc; use arc_swap::ArcSwap; use axum::extract::FromRef; use leptos::prelude::LeptosOptions; use std::collections::HashMap; use std::sync::Arc; use crate::content::Question; #[derive(Clone)] pub struct AppState { pub leptos_options: LeptosOptions, pub nats: async_nats::Client, /// JetStream context - source of every NATS KV bucket this app /// reads/writes (applicants, and whatever a `ResourceSpec` names). pub jetstream: async_nats::jetstream::Context, /// Swapped out wholesale on a `content::CONTENT_RELOAD_SUBJECT` /// message (see `content::watch_for_reload`) - readers never hold /// a lock, just an atomic pointer load, so a reload never blocks or /// is blocked by an in-flight request. pub questions: Arc>>, /// Every bucket's event-sourced state graph, loaded from /// `aggregates.yaml` (see `content::load_aggregates_from_gitea`) and /// hot-swapped alongside `questions` on the same reload. A bucket /// with no entry here isn't event-sourced - plain KV mutate-in-place /// still works (see `answers.rs`). pub aggregates: Arc>>, /// Site branding from the content repo's optional `site.yaml` /// (title, wordmark, hero kind) - hot-swapped with `questions`/ /// `aggregates` on the same reload. Default = the historical uhhm /// look. pub site: Arc>, /// `scheme://host` of the Gitea instance content is loaded from /// (see `content::gitea_api_base`) - kept alongside `questions` /// rather than re-derived per call, since `resolve_gitea_repo` needs /// it too and has no other reason to see `CONTENT_REPO` itself. pub gitea_base: String, /// `{gitea}/api/v1/repos/{owner}/{repo}/raw` and the branch - what /// `content::site_asset_handler` proxies content-shipped assets from. pub content_raw_base: String, pub content_branch: String, pub oidc: Arc, /// `None` when `GARAGE_*` env vars aren't set - uploads are the one /// optional feature, everything else works without Garage. pub garage: Option, } impl FromRef for LeptosOptions { fn from_ref(state: &AppState) -> Self { state.leptos_options.clone() } }