graphql_query_builder/
lib.rs1mod enums;
2pub mod json;
3pub use enums::{input_values::Values, OperationType};
4
5type Fields = Vec<SelectionSet>;
6type Arguments = std::collections::HashMap<&'static str, Values>;
7
8#[derive(Clone, Debug)]
9pub struct SelectionSet {
10 pub operation: &'static str,
11 pub alias: Option<&'static str>,
12 pub fields: Option<Fields>,
13 pub arguments: Option<Arguments>,
14 pub is_union: bool,
15}
16
17pub fn tabs(level: usize) -> String {
18 "\t".repeat(level)
19}
20
21pub struct Builder;
22
23impl Builder {
24 pub fn new(operation: OperationType, selection_set: &SelectionSet) -> String {
25 Self::generate_field(
26 0,
27 SelectionSet {
28 operation: operation.into(),
29 alias: None,
30 fields: Some(vec![selection_set.clone()]),
31 arguments: None,
32 is_union: false,
33 },
34 )
35 }
36
37 fn parse_arguments(args: &Arguments) -> Vec<String> {
38 args.into_iter()
39 .map(|(key, value)| match value {
40 Values::Int(value) => format!("{}: {}", key, value),
41 Values::Float(_) => todo!(),
42 Values::String(value) => format!("{}: \"{}\"", key, value),
43 Values::Boolean(value) => format!("{}: {}", key, value),
44 Values::Null => format!("{}: null", key),
45 Values::Enum(values) => {
46 for value in values {
47 match value {
48 &"null" | &"true" | &"false" => {
49 panic!("{key} cannot contain {value} value")
50 }
51 _ => (),
52 }
53 }
54 format!("{}: [{}]", key, values.join(", "))
55 }
56 Values::List(value) => format!(
57 "{}: [{}]",
58 key,
59 value
60 .iter()
61 .map(|i| i.to_string())
62 .collect::<Vec<String>>()
63 .join(", ")
64 ),
65 Values::Object => todo!(),
66 })
67 .collect()
68 }
69
70 fn generate_field(level: usize, field: SelectionSet) -> String {
71 let tabs = tabs(level);
72 let operation = field.operation;
73 let union = if field.is_union { "... on " } else { "" };
74 let alias = if let Some(alias) = field.alias {
75 format!("{}: ", alias)
76 } else {
77 String::from("")
78 };
79 let arguments = if let Some(args) = field.arguments {
80 format!("({})", Self::parse_arguments(&args).join(", "))
81 } else {
82 String::from("")
83 };
84 let sub_field = if let Some(sf) = field.fields {
85 let sub_field = Self::map_fields(level, sf).join("\n");
86 format!(" {{\n{sub_field}\n{tabs}}}")
87 } else {
88 String::from("")
89 };
90 format!("{tabs}{union}{alias}{operation}{arguments}{sub_field}")
91 }
92 fn map_fields(level: usize, selection_sets: Fields) -> Vec<String> {
93 selection_sets
94 .clone()
95 .into_iter()
96 .map(|field| Self::generate_field(level + 1, field))
97 .collect()
98 }
99}