fakecloud_appsync/
schema.rs1use serde_json::{json, Value};
15
16pub fn type_names(sdl: &str) -> Vec<String> {
20 let mut names = Vec::new();
21 for line in sdl.lines() {
22 let t = line.trim();
23 for kw in [
24 "type ",
25 "input ",
26 "enum ",
27 "interface ",
28 "union ",
29 "scalar ",
30 ] {
31 if let Some(rest) = t.strip_prefix(kw) {
32 if let Some(name) = rest
33 .split(|c: char| c.is_whitespace() || c == '{' || c == '(' || c == '=')
34 .next()
35 {
36 if !name.is_empty() {
37 names.push(name.to_string());
38 }
39 }
40 }
41 }
42 }
43 names
44}
45
46pub fn introspection_bytes(sdl: &str, format: &str) -> Vec<u8> {
51 if format.eq_ignore_ascii_case("JSON") {
52 let types: Vec<Value> = type_names(sdl)
53 .into_iter()
54 .map(|n| json!({ "kind": "OBJECT", "name": n }))
55 .collect();
56 let doc = json!({
57 "__schema": {
58 "queryType": { "name": "Query" },
59 "types": types,
60 }
61 });
62 serde_json::to_vec(&doc).unwrap_or_default()
63 } else {
64 sdl.as_bytes().to_vec()
65 }
66}
67
68#[cfg(test)]
69mod tests {
70 use super::*;
71
72 #[test]
73 fn parses_type_names() {
74 let sdl =
75 "type Query { hello: String }\ntype Post { id: ID! }\ninput NewPost { t: String }";
76 let names = type_names(sdl);
77 assert!(names.contains(&"Query".to_string()));
78 assert!(names.contains(&"Post".to_string()));
79 assert!(names.contains(&"NewPost".to_string()));
80 }
81
82 #[test]
83 fn sdl_format_is_verbatim() {
84 let sdl = "type Query { hello: String }";
85 assert_eq!(introspection_bytes(sdl, "SDL"), sdl.as_bytes());
86 }
87
88 #[test]
89 fn json_format_lists_types() {
90 let sdl = "type Query { hello: String }";
91 let bytes = introspection_bytes(sdl, "JSON");
92 let v: Value = serde_json::from_slice(&bytes).unwrap();
93 assert_eq!(v["__schema"]["types"][0]["name"], json!("Query"));
94 }
95}