use std::collections::HashMap; use serde::Serialize; use crate::Value; /// Generate the page for GraphQL Playground /// /// # Example /// /// ```rust /// use async_graphql::http::*; /// /// playground_source(GraphQLPlaygroundConfig::new("http://localhost:8000")); /// ``` pub fn playground_source(config: GraphQLPlaygroundConfig) -> String { r##" GraphQL Playground
Loading GraphQL Playground
"##.replace("GRAPHQL_PLAYGROUND_CONFIG", &match serde_json::to_string(&config) { Ok(str) => str, Err(_) => "{}".to_string() }) } /// Config for GraphQL Playground #[derive(Serialize)] #[serde(rename_all = "camelCase")] pub struct GraphQLPlaygroundConfig<'a> { endpoint: &'a str, subscription_endpoint: Option<&'a str>, headers: Option>, settings: Option>, } impl<'a> GraphQLPlaygroundConfig<'a> { /// Create a config for GraphQL playground. pub fn new(endpoint: &'a str) -> Self { Self { endpoint, subscription_endpoint: None, headers: Default::default(), settings: Default::default(), } } /// Set subscription endpoint, for example: `ws://localhost:8000`. #[must_use] pub fn subscription_endpoint(mut self, endpoint: &'a str) -> Self { self.subscription_endpoint = Some(endpoint); self } /// Set HTTP header for per query. #[must_use] pub fn with_header(mut self, name: &'a str, value: &'a str) -> Self { if let Some(headers) = &mut self.headers { headers.insert(name, value); } else { let mut headers = HashMap::new(); headers.insert(name, value); self.headers = Some(headers); } self } /// Set Playground setting for per query. /// /// ``` /// # use async_graphql::Value; /// # use async_graphql::http::GraphQLPlaygroundConfig; /// GraphQLPlaygroundConfig::new("/api/graphql") /// .with_setting("setting", false) /// .with_setting("other", Value::Null); /// ``` #[must_use] pub fn with_setting(mut self, name: &'a str, value: impl Into) -> Self { let value = value.into(); if let Some(settings) = &mut self.settings { settings.insert(name, value); } else { let mut settings = HashMap::new(); settings.insert(name, value); self.settings = Some(settings); } self } } #[cfg(test)] mod tests { use indexmap::IndexMap; use super::*; #[test] fn test_with_setting_can_use_any_json_value() { let settings = GraphQLPlaygroundConfig::new("") .with_setting("string", "string") .with_setting("bool", false) .with_setting("number", 10) .with_setting("null", Value::Null) .with_setting("array", Vec::from([1, 2, 3])) .with_setting("object", IndexMap::new()); let json = serde_json::to_value(settings).unwrap(); let settings = json["settings"].as_object().unwrap(); assert!(settings["string"].as_str().is_some()); assert!(settings["bool"].as_bool().is_some()); assert!(settings["number"].as_u64().is_some()); assert!(settings["null"].as_null().is_some()); assert!(settings["array"].as_array().is_some()); assert!(settings["object"].as_object().is_some()); } }