massbit_sol/generator/
graphql.rs

1use crate::generator::Generator;
2use crate::schema::{Schema, Variant};
3use lazy_static::lazy_static;
4use std::collections::{BTreeMap, HashMap};
5use std::fmt::Write;
6
7lazy_static! {
8    // https://www.codingame.com/playgrounds/365/getting-started-with-rust/primitive-data-types
9    // pub static ref PRIMITIVE_DATA_TYPES: Vec<&'static str> = vec![
10    //     "bool", "char", "i8", "u8", "i16", "u16", "i32", "u32", "i64", "u64", "isize", "usize", "f32",
11    //     "f64", "str", //Not support yet
12    //     "NonZeroU8", "NonZeroU32", "NonZeroU64", "NonZeroU128",
13    //     "NonZeroI8", "NonZeroI32", "NonZeroI64", "NonZeroI128",
14    //     "array", "slice", "tuple",
15    // ];
16
17    // https://kotiri.com/2018/01/31/postgresql-diesel-rust-types.html
18    pub static ref MAPPING_RUST_TYPES_TO_DB: HashMap<&'static str, &'static str> = HashMap::from([
19        ("bool", "Bool"),
20        //The graph generator postgres sql only handles with bigint
21        ("i8", "BigInt"),
22        ("u8", "BigInt"),
23        ("i16", "BigInt"),
24        ("u16", "BigInt"),
25        ("NonZeroU8", "BigInt"),
26        ("NonZeroU16", "BigInt"),
27        ("NonZeroI8", "BigInt"),
28        ("NonZeroI16", "BigInt"),
29
30        ("i32", "Integer"),
31        ("u32", "Integer"),
32        ("NonZeroI32", "Integer"),
33        ("NonZeroU32", "Integer"),
34
35
36        ("i64", "BigInt"),
37        ("u64", "BigInt"),
38        ("isize", "BigInt"),
39        ("usize", "BigInt"),
40        ("usize", "BigInt"),
41        ("NonZeroU64", "BigInt"),
42        ("NonZeroU128", "BigInt"),
43        ("NonZeroUsize", "BigInt"),
44        ("NonZeroI64", "BigInt"),
45        ("NonZeroI128", "BigInt"),
46        ("NonZeroIsize", "BigInt"),
47
48        ("f32", "Float"),
49
50        ("f64", "Double"),
51
52        ("str", "String"),
53        ("String", "String"),
54        ("char", "String"),
55    ]);
56    pub static ref MAPPING_DB_TYPES_TO_RUST: HashMap<&'static str, &'static str> = HashMap::from([
57        ("Bool", "bool"),
58
59        ("SmallInt", "i64"),
60        ("Integer", "i64"),
61        ("BigInt", "i64"),
62
63        ("Float", "f32"),
64
65        ("Double", "f64"),
66
67        ("String", "String"),
68    ]);
69
70    pub static ref DEFAULT_TYPE_DB : &'static str = "String";
71}
72
73impl<'a> Generator<'a> {
74    pub fn generate_graphql_schema(&self, schema: &Schema) -> String {
75        let mut out = String::new();
76        if let Some(variants) = &schema.variants {
77            // List instruction
78            for variant in variants {
79                // Write table if there is inner_type
80                let variant_entity = self.generate_variant_entity(variant, &self.definitions);
81                let _ = writeln!(out, "{}", &variant_entity);
82                // Get definitions
83                // if let Some(sub_schema) = self.definitions.get(&inner_type) {
84                //     // get a table corresponding to sub_schema
85                //     let str_entity: String =
86                //         Schema::gen_entity_db(sub_schema, inner_type, instruction.name);
87                //     writeln!(out, "{}", str_entity);
88                // } else if MAPPING_RUST_TYPES_TO_DB.contains_key(inner_type.as_str()) {
89                //     let str_entity: String =
90                //         Schema::gen_entity_db(&Schema::default(), inner_type, instruction.name);
91                //     writeln!(out, "{}", str_entity);
92                // }
93            }
94        }
95        out
96    }
97    fn generate_variant_entity(
98        &self,
99        variant: &Variant,
100        definitions: &BTreeMap<String, Schema>,
101    ) -> String {
102        let mut entity_properties: Vec<String> = vec![String::from("id: ID!")];
103        //Account assigment
104        if let Some(accounts) = &variant.accounts {
105            for account in accounts {
106                entity_properties.push(format!("\t{}: String", account.name));
107            }
108        }
109        if let Some(inner_type) = &variant.inner_type {
110            if let Some(def) = definitions.get(inner_type.as_str()) {
111                if let Some(properties) = &def.properties {
112                    for property in properties {
113                        let db_type = MAPPING_RUST_TYPES_TO_DB
114                            .get(property.data_type.as_str())
115                            .unwrap_or(&*DEFAULT_TYPE_DB);
116                        if property.array_length.is_some() {
117                            entity_properties.push(format!("\t{}: [{}]", &property.name, db_type));
118                        } else {
119                            entity_properties.push(format!("\t{}: {}", &property.name, db_type));
120                        }
121                    }
122                }
123            } else if let Some(db_type) = MAPPING_RUST_TYPES_TO_DB.get(inner_type.as_str()) {
124                //Inner type is primitive. Store is as an value field
125                entity_properties.push(format!("\tvalue: {}", db_type));
126            }
127        }
128        format!(
129            r#"type {} @entity {{
130    {entity_properties}
131}}"#,
132            &variant.name,
133            entity_properties = entity_properties.join(",\n")
134        )
135    }
136    // pub fn gen_entity_db(schema: &Schema, entity_type: String, entity_name: String) -> String {
137    //     let mut entity_properties: Vec<String> = vec![String::from("\tid: ID!")];
138    //     match MAPPING_RUST_TYPES_TO_DB.get(entity_type.as_str()) {
139    //         Some(db_type) => {
140    //             entity_properties.push(format!("\tvalue: {}", db_type));
141    //         }
142    //         None => {
143    //             if let Some(properties) = &schema.properties {
144    //                 for property in properties {
145    //                     match property.array_length {
146    //                         Some(_array_length) => {
147    //                             let db_type = MAPPING_RUST_TYPES_TO_DB
148    //                                 .get(property.data_type.as_str())
149    //                                 .unwrap_or(&*DEFAULT_TYPE_DB);
150    //                             entity_properties
151    //                                 .push(format!("\t{}: [{}]", &property.name, db_type));
152    //                         }
153    //                         None => {
154    //                             let db_type = MAPPING_RUST_TYPES_TO_DB
155    //                                 .get(property.data_type.as_str())
156    //                                 .unwrap_or(&*DEFAULT_TYPE_DB);
157    //                             entity_properties
158    //                                 .push(format!("\t{}: {}", &property.name, db_type));
159    //                         }
160    //                     }
161    //                 }
162    //             }
163    //         }
164    //     };
165    //     format!(
166    //         r#"type {} @entity {{
167    //             {entity_properties}
168    //         }}"#,
169    //         &entity_name,
170    //         entity_properties = entity_properties.join(",\n")
171    //     )
172    // }
173}