//! Weaver App main binary. #[allow(unused)] use dioxus::prelude::*; #[cfg(target_arch = "wasm32")] use lol_alloc::{FreeListAllocator, LockedAllocator}; #[cfg(feature = "server")] use std::sync::Arc; #[cfg(feature = "server")] use tower::Service; #[allow(unused)] use weaver_app::{App, CONFIG, SubdomainApp, SubdomainContext, fetch}; #[cfg(target_arch = "wasm32")] #[global_allocator] static ALLOCATOR: LockedAllocator = LockedAllocator::new(FreeListAllocator::new()); fn main() { // Set up better panic messages for wasm #[cfg(target_arch = "wasm32")] console_error_panic_hook::set_once(); // Set up tracing subscriber with both console output and log capture (wasm only) // Must happen before dioxus::launch so dioxus skips its own init #[cfg(all(target_arch = "wasm32", target_os = "unknown"))] { use tracing::Level; use tracing::subscriber::set_global_default; use tracing_subscriber::Registry; use tracing_subscriber::filter::EnvFilter; use tracing_subscriber::layer::SubscriberExt; let console_level = if cfg!(debug_assertions) { Level::TRACE } else { Level::INFO }; let wasm_layer = tracing_wasm::WASMLayer::new( tracing_wasm::WASMLayerConfigBuilder::new() .set_max_level(console_level) .build(), ); // Filter out noisy crates // Use weaver_app=trace for detailed editor debugging let filter = EnvFilter::new( "debug,weaver_app=trace,loro_internal=warn,jacquard_identity=info,jacquard_common=info,iroh=info,reqwest=warn", ); let reg = Registry::default() .with(filter) .with(wasm_layer) .with(weaver_app::components::editor::LogCaptureLayer); let _ = set_global_default(reg); } // Initialize telemetry (metrics + tracing) before server starts. // Loki task is spawned inside dioxus::serve where tokio runtime exists. // Wrapped in Arc so the FnMut closure can clone and take() on first call. #[cfg(feature = "server")] let loki_task = { use weaver_common::telemetry::{self, TelemetryConfig}; let config = TelemetryConfig::from_env("weaver-app"); std::sync::Arc::new(std::sync::Mutex::new(telemetry::init_sync(config))) }; #[cfg(feature = "server")] std::panic::set_hook(Box::new(|panic_info| { tracing::error!("PANIC: {:?}", panic_info); })); // Run `serve()` on the server only #[cfg(feature = "server")] dioxus::serve({ let loki_task = loki_task.clone(); move || { let loki_task = loki_task.clone(); async move { #[cfg(feature = "fullstack-server")] use axum::middleware; use axum::middleware::Next; use axum::{ Router, body::Body, extract::Request, response::Response, routing::get, }; use axum_extra::extract::Host; use jacquard::oauth::{client::OAuthClient, session::ClientData}; use std::convert::Infallible; use weaver_app::auth::AuthStore; use weaver_app::blobcache::BlobCache; use weaver_common::telemetry; // Spawn the Loki background task now that we're in tokio runtime if let Some(task) = loki_task.lock().unwrap().take() { telemetry::spawn_loki_task(task); } #[cfg(not(feature = "fullstack-server"))] let router = { Router::new() .merge(dioxus::server::router(App)) .layer(middleware::from_fn(telemetry::http_metrics)) .layer(tower_http::trace::TraceLayer::new_for_http()) }; #[cfg(feature = "fullstack-server")] let router = { let fetcher = Arc::new(fetch::Fetcher::new(OAuthClient::new( AuthStore::new(), ClientData::new_public(CONFIG.oauth.clone()), ))); let blob_cache = Arc::new(BlobCache::new(fetcher.clone())); axum::Router::new() .route("/favicon.ico", get(weaver_app::favicon)) .route("/metrics", get(|| async { telemetry::render() })) .serve_dioxus_application(ServeConfig::builder(), App) // Host context resolution. .layer(middleware::from_fn({ let fetcher = fetcher.clone(); move |req: Request, next: Next| { let fetcher = fetcher.clone(); async move { weaver_app::middleware::host_context_middleware( req, next, fetcher, ) .await } } })) // Insert fetcher and blob cache into extensions. .layer(middleware::from_fn({ let blob_cache = blob_cache.clone(); let fetcher = fetcher.clone(); move |mut req: Request, next: Next| { let blob_cache = blob_cache.clone(); let fetcher = fetcher.clone(); async move { req.extensions_mut().insert(blob_cache); req.extensions_mut().insert(fetcher); Ok::<_, Infallible>(next.run(req).await) } } })) // HTTP metrics (request count, duration) .layer(middleware::from_fn(telemetry::http_metrics)) .layer(tower_http::trace::TraceLayer::new_for_http()) }; Ok(router) } } }); #[cfg(not(feature = "server"))] dioxus::launch(App); }