graphql_tools/introspection/
introspection.rs1use 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 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}