graphql_tools/introspection/
introspection.rs

1use std::io;
2
3use serde::{Deserialize, Serialize};
4use serde_json::{Result, Value};
5
6#[derive(Serialize, Deserialize, Debug)]
7pub struct IntrospectionQuery {
8    pub __schema: IntrospectionSchema,
9}
10
11#[derive(Serialize, Deserialize, Debug)]
12pub struct IntrospectionScalarType {
13    pub name: String,
14    pub description: Option<String>,
15    #[serde(rename = "specifiedByURL")]
16    pub specified_by_url: Option<String>,
17}
18
19#[derive(Serialize, Deserialize, Debug)]
20pub struct IntrospectionInputValue {
21    pub name: String,
22    pub description: Option<String>,
23    #[serde(rename = "defaultValue")]
24    pub default_value: Option<Value>,
25    #[serde(rename = "isDeprecated")]
26    pub is_deprecated: Option<bool>,
27    #[serde(rename = "deprecationReason")]
28    pub deprecation_reason: Option<String>,
29    #[serde(rename = "type")]
30    pub type_ref: Option<IntrospectionInputTypeRef>,
31}
32
33#[derive(Serialize, Deserialize, Debug)]
34#[serde(tag = "kind")]
35pub struct IntrospectionField {
36    pub name: String,
37    pub description: Option<String>,
38    pub args: Vec<IntrospectionInputValue>,
39    #[serde(rename = "isDeprecated")]
40    pub is_deprecated: Option<bool>,
41    #[serde(rename = "deprecationReason")]
42    pub deprecation_reason: Option<String>,
43    #[serde(rename = "type")]
44    pub type_ref: IntrospectionOutputTypeRef,
45}
46
47#[derive(Serialize, Deserialize, Debug)]
48pub struct IntrospectionObjectType {
49    pub name: String,
50    pub description: Option<String>,
51    pub fields: Vec<IntrospectionField>,
52    pub interfaces: Vec<IntrospectionNamedTypeRef>,
53}
54
55#[derive(Serialize, Deserialize, Debug)]
56pub struct IntrospectionInterfaceType {
57    pub name: String,
58    pub description: Option<String>,
59    pub fields: Vec<IntrospectionField>,
60    pub interfaces: Option<Vec<IntrospectionNamedTypeRef>>,
61    #[serde(rename = "possibleTypes")]
62    pub possible_types: Vec<IntrospectionNamedTypeRef>,
63}
64
65#[derive(Serialize, Deserialize, Debug)]
66pub struct IntrospectionUnionType {
67    pub name: String,
68    pub description: Option<String>,
69    #[serde(rename = "possibleTypes")]
70    pub possible_types: Vec<IntrospectionNamedTypeRef>,
71}
72
73#[derive(Serialize, Deserialize, Debug)]
74pub struct IntrospectionEnumValue {
75    pub name: String,
76    pub description: Option<String>,
77    #[serde(rename = "isDeprecated")]
78    pub is_deprecated: Option<bool>,
79    #[serde(rename = "deprecationReason")]
80    pub deprecation_reason: Option<String>,
81}
82
83#[derive(Serialize, Deserialize, Debug)]
84pub struct IntrospectionEnumType {
85    pub name: String,
86    pub description: Option<String>,
87    #[serde(rename = "enumValues")]
88    pub enum_values: Vec<IntrospectionEnumValue>,
89}
90
91#[derive(Serialize, Deserialize, Debug)]
92pub struct IntrospectionInputObjectType {
93    pub name: String,
94    pub description: Option<String>,
95    #[serde(rename = "inputFields")]
96    pub input_fields: Vec<IntrospectionInputValue>,
97}
98
99#[derive(Serialize, Deserialize, Debug)]
100#[serde(tag = "kind")]
101pub enum IntrospectionType {
102    SCALAR(IntrospectionScalarType),
103    OBJECT(IntrospectionObjectType),
104    INTERFACE(IntrospectionInterfaceType),
105    UNION(IntrospectionUnionType),
106    ENUM(IntrospectionEnumType),
107    INPUT_OBJECT(IntrospectionInputObjectType),
108}
109
110impl IntrospectionType {
111    pub fn name(&self) -> &String {
112        match &self {
113            IntrospectionType::ENUM(e) => &e.name,
114            IntrospectionType::OBJECT(o) => &o.name,
115            IntrospectionType::INPUT_OBJECT(io) => &io.name,
116            IntrospectionType::INTERFACE(i) => &i.name,
117            IntrospectionType::SCALAR(s) => &s.name,
118            IntrospectionType::UNION(u) => &u.name,
119        }
120    }
121}
122
123#[derive(Serialize, Deserialize, Debug)]
124#[serde(tag = "kind")]
125pub enum IntrospectionInputType {
126    SCALAR(IntrospectionScalarType),
127    ENUM(IntrospectionEnumType),
128    INPUT_OBJECT(IntrospectionInputObjectType),
129}
130
131#[derive(Serialize, Deserialize, Debug)]
132#[serde(tag = "kind")]
133pub enum IntrospectionOutputType {
134    SCALAR(IntrospectionScalarType),
135    OBJECT(IntrospectionObjectType),
136    INTERFACE(IntrospectionInterfaceType),
137    UNION(IntrospectionUnionType),
138    ENUM(IntrospectionEnumType),
139}
140
141#[derive(Serialize, Deserialize, Debug)]
142pub struct IntrospectionNamedTypeRef {
143    pub name: String,
144}
145
146#[derive(Serialize, Deserialize, Debug)]
147#[serde(tag = "kind")]
148pub enum IntrospectionOutputTypeRef {
149    SCALAR(IntrospectionNamedTypeRef),
150    LIST {
151        #[serde(rename = "ofType")]
152        of_type: Option<Box<IntrospectionOutputTypeRef>>,
153    },
154    NON_NULL {
155        #[serde(rename = "ofType")]
156        of_type: Option<Box<IntrospectionOutputTypeRef>>,
157    },
158    ENUM(IntrospectionNamedTypeRef),
159    INPUT_OBJECT(IntrospectionNamedTypeRef),
160    UNION(IntrospectionNamedTypeRef),
161    OBJECT(IntrospectionNamedTypeRef),
162    INTERFACE(IntrospectionNamedTypeRef),
163}
164
165#[derive(Serialize, Deserialize, Debug)]
166#[serde(tag = "kind")]
167pub enum IntrospectionInputTypeRef {
168    LIST {
169        #[serde(rename = "ofType")]
170        of_type: Option<Box<IntrospectionInputTypeRef>>,
171    },
172    NON_NULL {
173        #[serde(rename = "ofType")]
174        of_type: Option<Box<IntrospectionInputTypeRef>>,
175    },
176    SCALAR(IntrospectionNamedTypeRef),
177    ENUM(IntrospectionNamedTypeRef),
178    INPUT_OBJECT(IntrospectionNamedTypeRef),
179}
180
181#[derive(Serialize, Deserialize, Debug)]
182pub struct IntrospectionSchema {
183    pub description: Option<String>,
184    #[serde(rename = "queryType")]
185    pub query_type: IntrospectionNamedTypeRef,
186    #[serde(rename = "mutationType")]
187    pub mutation_type: Option<IntrospectionNamedTypeRef>,
188    #[serde(rename = "subscriptionType")]
189    pub subscription_type: Option<IntrospectionNamedTypeRef>,
190    pub types: Vec<IntrospectionType>,
191    pub directives: Vec<IntrospectionDirective>,
192}
193
194#[derive(Serialize, Deserialize, Debug)]
195pub enum DirectiveLocation {
196    QUERY,
197    MUTATION,
198    SUBSCRIPTION,
199    FIELD,
200    FRAGMENT_DEFINITION,
201    FRAGMENT_SPREAD,
202    INLINE_FRAGMENT,
203    VARIABLE_DEFINITION,
204    /** Type System Definitions */
205    SCHEMA,
206    SCALAR,
207    OBJECT,
208    FIELD_DEFINITION,
209    ARGUMENT_DEFINITION,
210    INTERFACE,
211    UNION,
212    ENUM,
213    ENUM_VALUE,
214    INPUT_OBJECT,
215    INPUT_FIELD_DEFINITION,
216}
217
218#[derive(Serialize, Deserialize, Debug)]
219pub struct IntrospectionDirective {
220    pub name: String,
221    pub description: Option<String>,
222    #[serde(rename = "isRepeatable")]
223    pub is_repeatable: Option<bool>,
224    pub locations: Vec<DirectiveLocation>,
225    pub args: Vec<IntrospectionInputValue>,
226}
227
228pub fn parse_introspection_from_string(input: &str) -> Result<IntrospectionQuery> {
229    serde_json::from_str(input)
230}
231
232pub fn parse_introspection<R>(input: R) -> Result<IntrospectionQuery>
233where
234    R: io::Read,
235{
236    serde_json::from_reader::<R, IntrospectionQuery>(input)
237}
238
239#[test]
240fn test_product_introspection() {
241    use std::fs::File;
242    let json_file = File::open("./src/introspection/test_files/product_introspection.json")
243        .expect("failed to open json file");
244    parse_introspection(json_file).expect("failed to parse introspection json");
245}
246
247#[test]
248fn test_github_introspection() {
249    use std::fs::File;
250    let json_file = File::open("./src/introspection/test_files/github_introspection.json")
251        .expect("failed to open json file");
252    parse_introspection(json_file).expect("failed to parse introspection json");
253}
254
255#[test]
256fn test_shopify_introspection() {
257    use std::fs::File;
258    let json_file = File::open("./src/introspection/test_files/shopify_introspection.json")
259        .expect("failed to open json file");
260    parse_introspection(json_file).expect("failed to parse introspection json");
261}