use std::sync::Arc; use axum::{Json, Router, extract::State, http::StatusCode, response::IntoResponse}; use jacquard::{ api::com_atproto::identity::resolve_did::{ResolveDidOutput, ResolveDidRequest}, identity::{JacquardResolver, resolver::IdentityResolver}, types::value::to_data, }; use jacquard_axum::{ExtractXrpc, IntoRouter}; use miette::{IntoDiagnostic, Result}; use tracing_subscriber::EnvFilter; #[axum_macros::debug_handler] async fn resolve_did( State(state): State>, ExtractXrpc(args): ExtractXrpc, ) -> Result>, XrpcErrorResponse> { let doc = state .resolver .resolve_did_doc_owned(&args.did) .await .map_err(|_| XrpcErrorResponse::internal_server_error())?; Ok(ResolveDidOutput { did_doc: to_data(&doc).map_err(|_| XrpcErrorResponse::internal_server_error())?, extra_data: Default::default(), } .into()) } #[tokio::main] async fn main() -> Result<()> { tracing_subscriber::fmt() .with_timer(tracing_subscriber::fmt::time::UtcTime::rfc_3339()) .with_env_filter(EnvFilter::from_env("QDPDS_LOG")) .init(); let app = Router::new() .route("/", axum::routing::get(|| async { "hello world!" })) .merge(ResolveDidRequest::into_router(resolve_did)) .with_state(Arc::new(AppState::new())) .layer(tower_http::trace::TraceLayer::new_for_http()); let listener = tokio::net::TcpListener::bind("0.0.0.0:3000") .await .into_diagnostic()?; axum::serve(listener, app).await.into_diagnostic()?; Ok(()) } pub struct XrpcErrorResponse { error: XrpcError, pub status: StatusCode, } impl XrpcErrorResponse { pub fn internal_server_error() -> Self { Self { error: XrpcError { error: "InternalServerError".to_string(), message: None, }, status: StatusCode::INTERNAL_SERVER_ERROR, } } } #[derive(serde::Deserialize, serde::Serialize)] pub struct XrpcError { pub error: String, #[serde(skip_serializing_if = "std::option::Option::is_none")] pub message: Option, } impl IntoResponse for XrpcErrorResponse { fn into_response(self) -> axum::response::Response { Json(self.error).into_response() } } pub struct AppState { pub resolver: JacquardResolver, } impl AppState { pub fn new() -> Self { Self { resolver: jacquard::identity::slingshot_resolver_default(), } } }