1use crate::ast::Value;
7use anyhow::{anyhow, Result};
8use std::collections::HashMap;
9use std::fmt;
10
11#[derive(Debug, Clone, PartialEq)]
13pub enum GraphQLType {
14 Scalar(ScalarType),
15 Object(ObjectType),
16 Interface(InterfaceType),
17 Union(UnionType),
18 Enum(EnumType),
19 InputObject(InputObjectType),
20 List(Box<GraphQLType>),
21 NonNull(Box<GraphQLType>),
22}
23
24impl GraphQLType {
25 pub fn name(&self) -> &str {
26 match self {
27 GraphQLType::Scalar(s) => &s.name,
28 GraphQLType::Object(o) => &o.name,
29 GraphQLType::Interface(i) => &i.name,
30 GraphQLType::Union(u) => &u.name,
31 GraphQLType::Enum(e) => &e.name,
32 GraphQLType::InputObject(io) => &io.name,
33 GraphQLType::List(inner) => inner.name(),
34 GraphQLType::NonNull(inner) => inner.name(),
35 }
36 }
37
38 pub fn is_nullable(&self) -> bool {
39 !matches!(self, GraphQLType::NonNull(_))
40 }
41
42 pub fn is_list(&self) -> bool {
43 matches!(self, GraphQLType::List(_))
44 }
45
46 pub fn is_scalar(&self) -> bool {
47 matches!(self, GraphQLType::Scalar(_))
48 }
49
50 pub fn is_object(&self) -> bool {
51 matches!(self, GraphQLType::Object(_))
52 }
53}
54
55impl fmt::Display for GraphQLType {
56 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57 match self {
58 GraphQLType::Scalar(s) => write!(f, "{}", s.name),
59 GraphQLType::Object(o) => write!(f, "{}", o.name),
60 GraphQLType::Interface(i) => write!(f, "{}", i.name),
61 GraphQLType::Union(u) => write!(f, "{}", u.name),
62 GraphQLType::Enum(e) => write!(f, "{}", e.name),
63 GraphQLType::InputObject(io) => write!(f, "{}", io.name),
64 GraphQLType::List(inner) => write!(f, "[{inner}]"),
65 GraphQLType::NonNull(inner) => write!(f, "{inner}!"),
66 }
67 }
68}
69
70#[derive(Debug, Clone)]
72pub struct ScalarType {
73 pub name: String,
74 pub description: Option<String>,
75 pub serialize: fn(&Value) -> Result<Value>,
76 pub parse_value: fn(&Value) -> Result<Value>,
77 pub parse_literal: fn(&Value) -> Result<Value>,
78}
79
80impl PartialEq for ScalarType {
81 fn eq(&self, other: &Self) -> bool {
82 self.name == other.name && self.description == other.description
83 }
85}
86
87impl ScalarType {
88 pub fn new(name: String) -> Self {
89 Self {
90 name,
91 description: None,
92 serialize: |v| Ok(v.clone()),
93 parse_value: |v| Ok(v.clone()),
94 parse_literal: |v| Ok(v.clone()),
95 }
96 }
97
98 pub fn with_description(mut self, description: String) -> Self {
99 self.description = Some(description);
100 self
101 }
102
103 pub fn with_serializer(mut self, serialize: fn(&Value) -> Result<Value>) -> Self {
104 self.serialize = serialize;
105 self
106 }
107
108 pub fn with_value_parser(mut self, parse_value: fn(&Value) -> Result<Value>) -> Self {
109 self.parse_value = parse_value;
110 self
111 }
112
113 pub fn with_literal_parser(mut self, parse_literal: fn(&Value) -> Result<Value>) -> Self {
114 self.parse_literal = parse_literal;
115 self
116 }
117}
118
119#[derive(Debug, Clone, PartialEq)]
121pub struct ObjectType {
122 pub name: String,
123 pub description: Option<String>,
124 pub fields: HashMap<String, FieldType>,
125 pub interfaces: Vec<String>,
126}
127
128impl ObjectType {
129 pub fn new(name: String) -> Self {
130 Self {
131 name,
132 description: None,
133 fields: HashMap::new(),
134 interfaces: Vec::new(),
135 }
136 }
137
138 pub fn with_description(mut self, description: String) -> Self {
139 self.description = Some(description);
140 self
141 }
142
143 pub fn with_field(mut self, name: String, field: FieldType) -> Self {
144 self.fields.insert(name, field);
145 self
146 }
147
148 pub fn with_interface(mut self, interface: String) -> Self {
149 self.interfaces.push(interface);
150 self
151 }
152}
153
154#[derive(Debug, Clone, PartialEq)]
156pub struct FieldType {
157 pub name: String,
158 pub description: Option<String>,
159 pub field_type: GraphQLType,
160 pub arguments: HashMap<String, ArgumentType>,
161}
162
163impl FieldType {
164 pub fn new(name: String, field_type: GraphQLType) -> Self {
165 Self {
166 name,
167 description: None,
168 field_type,
169 arguments: HashMap::new(),
170 }
171 }
172
173 pub fn with_description(mut self, description: String) -> Self {
174 self.description = Some(description);
175 self
176 }
177
178 pub fn with_argument(mut self, name: String, argument: ArgumentType) -> Self {
179 self.arguments.insert(name, argument);
180 self
181 }
182}
183
184#[derive(Debug, Clone, PartialEq)]
186pub struct ArgumentType {
187 pub name: String,
188 pub description: Option<String>,
189 pub argument_type: GraphQLType,
190 pub default_value: Option<Value>,
191}
192
193impl ArgumentType {
194 pub fn new(name: String, argument_type: GraphQLType) -> Self {
195 Self {
196 name,
197 description: None,
198 argument_type,
199 default_value: None,
200 }
201 }
202
203 pub fn with_description(mut self, description: String) -> Self {
204 self.description = Some(description);
205 self
206 }
207
208 pub fn with_default_value(mut self, default_value: Value) -> Self {
209 self.default_value = Some(default_value);
210 self
211 }
212}
213
214#[derive(Debug, Clone, PartialEq)]
216pub struct InterfaceType {
217 pub name: String,
218 pub description: Option<String>,
219 pub fields: HashMap<String, FieldType>,
220 pub interfaces: Vec<String>,
221}
222
223impl InterfaceType {
224 pub fn new(name: String) -> Self {
225 Self {
226 name,
227 description: None,
228 fields: HashMap::new(),
229 interfaces: Vec::new(),
230 }
231 }
232
233 pub fn with_description(mut self, description: String) -> Self {
234 self.description = Some(description);
235 self
236 }
237
238 pub fn with_field(mut self, name: String, field: FieldType) -> Self {
239 self.fields.insert(name, field);
240 self
241 }
242}
243
244#[derive(Debug, Clone, PartialEq)]
246pub struct UnionType {
247 pub name: String,
248 pub description: Option<String>,
249 pub types: Vec<String>,
250}
251
252impl UnionType {
253 pub fn new(name: String) -> Self {
254 Self {
255 name,
256 description: None,
257 types: Vec::new(),
258 }
259 }
260
261 pub fn with_description(mut self, description: String) -> Self {
262 self.description = Some(description);
263 self
264 }
265
266 pub fn with_type(mut self, type_name: String) -> Self {
267 self.types.push(type_name);
268 self
269 }
270}
271
272#[derive(Debug, Clone, PartialEq)]
274pub struct EnumType {
275 pub name: String,
276 pub description: Option<String>,
277 pub values: HashMap<String, EnumValue>,
278}
279
280impl EnumType {
281 pub fn new(name: String) -> Self {
282 Self {
283 name,
284 description: None,
285 values: HashMap::new(),
286 }
287 }
288
289 pub fn with_description(mut self, description: String) -> Self {
290 self.description = Some(description);
291 self
292 }
293
294 pub fn with_value(mut self, name: String, value: EnumValue) -> Self {
295 self.values.insert(name, value);
296 self
297 }
298}
299
300#[derive(Debug, Clone, PartialEq)]
302pub struct EnumValue {
303 pub name: String,
304 pub description: Option<String>,
305 pub value: Value,
306 pub deprecated: Option<String>,
307}
308
309impl EnumValue {
310 pub fn new(name: String, value: Value) -> Self {
311 Self {
312 name,
313 description: None,
314 value,
315 deprecated: None,
316 }
317 }
318
319 pub fn with_description(mut self, description: String) -> Self {
320 self.description = Some(description);
321 self
322 }
323
324 pub fn with_deprecation(mut self, reason: String) -> Self {
325 self.deprecated = Some(reason);
326 self
327 }
328}
329
330#[derive(Debug, Clone, PartialEq)]
332pub struct InputObjectType {
333 pub name: String,
334 pub description: Option<String>,
335 pub fields: HashMap<String, InputFieldType>,
336}
337
338impl InputObjectType {
339 pub fn new(name: String) -> Self {
340 Self {
341 name,
342 description: None,
343 fields: HashMap::new(),
344 }
345 }
346
347 pub fn with_description(mut self, description: String) -> Self {
348 self.description = Some(description);
349 self
350 }
351
352 pub fn with_field(mut self, name: String, field: InputFieldType) -> Self {
353 self.fields.insert(name, field);
354 self
355 }
356}
357
358#[derive(Debug, Clone, PartialEq)]
360pub struct InputFieldType {
361 pub name: String,
362 pub description: Option<String>,
363 pub field_type: GraphQLType,
364 pub default_value: Option<Value>,
365}
366
367impl InputFieldType {
368 pub fn new(name: String, field_type: GraphQLType) -> Self {
369 Self {
370 name,
371 description: None,
372 field_type,
373 default_value: None,
374 }
375 }
376
377 pub fn with_description(mut self, description: String) -> Self {
378 self.description = Some(description);
379 self
380 }
381
382 pub fn with_default_value(mut self, default_value: Value) -> Self {
383 self.default_value = Some(default_value);
384 self
385 }
386}
387
388pub struct BuiltinScalars;
390
391impl BuiltinScalars {
392 pub fn string() -> ScalarType {
393 ScalarType::new("String".to_string())
394 .with_description("The `String` scalar type represents textual data, represented as UTF-8 character sequences.".to_string())
395 .with_serializer(|v| match v {
396 Value::StringValue(s) => Ok(Value::StringValue(s.clone())),
397 _ => Err(anyhow!("Cannot serialize {:?} as String", v)),
398 })
399 .with_value_parser(|v| match v {
400 Value::StringValue(_) => Ok(v.clone()),
401 _ => Err(anyhow!("Cannot parse {:?} as String", v)),
402 })
403 .with_literal_parser(|v| match v {
404 Value::StringValue(_) => Ok(v.clone()),
405 _ => Err(anyhow!("Cannot parse literal {:?} as String", v)),
406 })
407 }
408
409 pub fn int() -> ScalarType {
410 ScalarType::new("Int".to_string())
411 .with_description(
412 "The `Int` scalar type represents non-fractional signed whole numeric values."
413 .to_string(),
414 )
415 .with_serializer(|v| match v {
416 Value::IntValue(i) => Ok(Value::IntValue(*i)),
417 _ => Err(anyhow!("Cannot serialize {:?} as Int", v)),
418 })
419 .with_value_parser(|v| match v {
420 Value::IntValue(_) => Ok(v.clone()),
421 _ => Err(anyhow!("Cannot parse {:?} as Int", v)),
422 })
423 .with_literal_parser(|v| match v {
424 Value::IntValue(_) => Ok(v.clone()),
425 _ => Err(anyhow!("Cannot parse literal {:?} as Int", v)),
426 })
427 }
428
429 pub fn float() -> ScalarType {
430 ScalarType::new("Float".to_string())
431 .with_description(
432 "The `Float` scalar type represents signed double-precision fractional values."
433 .to_string(),
434 )
435 .with_serializer(|v| match v {
436 Value::FloatValue(f) => Ok(Value::FloatValue(*f)),
437 Value::IntValue(i) => Ok(Value::FloatValue(*i as f64)),
438 _ => Err(anyhow!("Cannot serialize {:?} as Float", v)),
439 })
440 .with_value_parser(|v| match v {
441 Value::FloatValue(_) => Ok(v.clone()),
442 Value::IntValue(i) => Ok(Value::FloatValue(*i as f64)),
443 _ => Err(anyhow!("Cannot parse {:?} as Float", v)),
444 })
445 .with_literal_parser(|v| match v {
446 Value::FloatValue(_) => Ok(v.clone()),
447 Value::IntValue(i) => Ok(Value::FloatValue(*i as f64)),
448 _ => Err(anyhow!("Cannot parse literal {:?} as Float", v)),
449 })
450 }
451
452 pub fn boolean() -> ScalarType {
453 ScalarType::new("Boolean".to_string())
454 .with_description("The `Boolean` scalar type represents `true` or `false`.".to_string())
455 .with_serializer(|v| match v {
456 Value::BooleanValue(b) => Ok(Value::BooleanValue(*b)),
457 _ => Err(anyhow!("Cannot serialize {:?} as Boolean", v)),
458 })
459 .with_value_parser(|v| match v {
460 Value::BooleanValue(_) => Ok(v.clone()),
461 _ => Err(anyhow!("Cannot parse {:?} as Boolean", v)),
462 })
463 .with_literal_parser(|v| match v {
464 Value::BooleanValue(_) => Ok(v.clone()),
465 _ => Err(anyhow!("Cannot parse literal {:?} as Boolean", v)),
466 })
467 }
468
469 pub fn id() -> ScalarType {
470 ScalarType::new("ID".to_string())
471 .with_description("The `ID` scalar type represents a unique identifier.".to_string())
472 .with_serializer(|v| match v {
473 Value::StringValue(s) => Ok(Value::StringValue(s.clone())),
474 Value::IntValue(i) => Ok(Value::StringValue(i.to_string())),
475 _ => Err(anyhow!("Cannot serialize {:?} as ID", v)),
476 })
477 .with_value_parser(|v| match v {
478 Value::StringValue(_) => Ok(v.clone()),
479 Value::IntValue(i) => Ok(Value::StringValue(i.to_string())),
480 _ => Err(anyhow!("Cannot parse {:?} as ID", v)),
481 })
482 .with_literal_parser(|v| match v {
483 Value::StringValue(_) => Ok(v.clone()),
484 Value::IntValue(i) => Ok(Value::StringValue(i.to_string())),
485 _ => Err(anyhow!("Cannot parse literal {:?} as ID", v)),
486 })
487 }
488}
489
490#[derive(Debug, Clone)]
492pub struct Schema {
493 pub query_type: Option<String>,
494 pub mutation_type: Option<String>,
495 pub subscription_type: Option<String>,
496 pub types: HashMap<String, GraphQLType>,
497 pub directives: HashMap<String, DirectiveType>,
498}
499
500impl Schema {
501 pub fn new() -> Self {
502 let mut schema = Self {
503 query_type: None,
504 mutation_type: None,
505 subscription_type: None,
506 types: HashMap::new(),
507 directives: HashMap::new(),
508 };
509
510 schema.add_type(GraphQLType::Scalar(BuiltinScalars::string()));
512 schema.add_type(GraphQLType::Scalar(BuiltinScalars::int()));
513 schema.add_type(GraphQLType::Scalar(BuiltinScalars::float()));
514 schema.add_type(GraphQLType::Scalar(BuiltinScalars::boolean()));
515 schema.add_type(GraphQLType::Scalar(BuiltinScalars::id()));
516
517 schema
518 }
519
520 pub fn add_type(&mut self, graphql_type: GraphQLType) {
521 let name = graphql_type.name().to_string();
522 self.types.insert(name, graphql_type);
523 }
524
525 pub fn get_type(&self, name: &str) -> Option<&GraphQLType> {
526 self.types.get(name)
527 }
528
529 pub fn set_query_type(&mut self, type_name: String) {
530 self.query_type = Some(type_name);
531 }
532
533 pub fn set_mutation_type(&mut self, type_name: String) {
534 self.mutation_type = Some(type_name);
535 }
536
537 pub fn set_subscription_type(&mut self, type_name: String) {
538 self.subscription_type = Some(type_name);
539 }
540}
541
542impl Default for Schema {
543 fn default() -> Self {
544 Self::new()
545 }
546}
547
548#[derive(Debug, Clone, PartialEq)]
550pub struct DirectiveType {
551 pub name: String,
552 pub description: Option<String>,
553 pub locations: Vec<DirectiveLocation>,
554 pub arguments: HashMap<String, ArgumentType>,
555 pub repeatable: bool,
556}
557
558#[derive(Debug, Clone, PartialEq)]
560pub enum DirectiveLocation {
561 Query,
562 Mutation,
563 Subscription,
564 Field,
565 FragmentDefinition,
566 FragmentSpread,
567 InlineFragment,
568 VariableDefinition,
569 Schema,
570 Scalar,
571 Object,
572 FieldDefinition,
573 ArgumentDefinition,
574 Interface,
575 Union,
576 Enum,
577 EnumValue,
578 InputObject,
579 InputFieldDefinition,
580}