1use std::str::FromStr;
6
7use serde::Serialize;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
13#[serde(rename_all = "snake_case")]
14pub enum Kind {
15 Object,
16 Interface,
17 Union,
18 Enum,
19 InputObject,
20 Scalar,
21 Directive,
22 Field,
23 InputField,
24 EnumValue,
25 Query,
26 Mutation,
27 Subscription,
28}
29
30impl Kind {
31 pub fn as_str(self) -> &'static str {
32 match self {
33 Kind::Object => "object",
34 Kind::Interface => "interface",
35 Kind::Union => "union",
36 Kind::Enum => "enum",
37 Kind::InputObject => "input_object",
38 Kind::Scalar => "scalar",
39 Kind::Directive => "directive",
40 Kind::Field => "field",
41 Kind::InputField => "input_field",
42 Kind::EnumValue => "enum_value",
43 Kind::Query => "query",
44 Kind::Mutation => "mutation",
45 Kind::Subscription => "subscription",
46 }
47 }
48
49 pub fn weight(self) -> i64 {
52 match self {
53 Kind::Query | Kind::Mutation | Kind::Subscription => 60,
54 Kind::Object
55 | Kind::Interface
56 | Kind::Union
57 | Kind::Enum
58 | Kind::InputObject
59 | Kind::Scalar => 40,
60 Kind::Directive => 30,
61 Kind::Field | Kind::InputField => 20,
62 Kind::EnumValue => 10,
63 }
64 }
65}
66
67impl FromStr for Kind {
68 type Err = anyhow::Error;
69
70 fn from_str(s: &str) -> Result<Self, Self::Err> {
71 Ok(match s.to_lowercase().as_str() {
72 "object" | "objects" | "type" | "types" => Kind::Object,
73 "interface" | "interfaces" => Kind::Interface,
74 "union" | "unions" => Kind::Union,
75 "enum" | "enums" => Kind::Enum,
76 "input" | "input_object" | "input_objects" | "inputobject" => Kind::InputObject,
77 "scalar" | "scalars" => Kind::Scalar,
78 "directive" | "directives" => Kind::Directive,
79 "field" | "fields" => Kind::Field,
80 "input_field" | "input_fields" | "inputfield" => Kind::InputField,
81 "enum_value" | "enum_values" | "enumvalue" => Kind::EnumValue,
82 "query" | "queries" => Kind::Query,
83 "mutation" | "mutations" => Kind::Mutation,
84 "subscription" | "subscriptions" => Kind::Subscription,
85 other => anyhow::bail!(
86 "unknown kind {other:?} — valid: object, interface, union, enum, \
87 input_object, scalar, directive, field, input_field, enum_value, \
88 query, mutation, subscription (plurals ok)"
89 ),
90 })
91 }
92}
93
94#[derive(Debug, Clone, Serialize)]
96pub struct SchemaRecord {
97 pub path: String,
99 pub name: String,
101 pub kind: Kind,
102 #[serde(skip_serializing_if = "Option::is_none")]
104 pub parent: Option<String>,
105 #[serde(skip_serializing_if = "Option::is_none")]
107 pub type_ref: Option<String>,
108 #[serde(skip_serializing_if = "Vec::is_empty")]
110 pub args: Vec<String>,
111 #[serde(skip_serializing_if = "Option::is_none")]
112 pub description: Option<String>,
113 #[serde(skip_serializing_if = "Option::is_none")]
115 pub deprecated: Option<String>,
116 #[serde(skip_serializing_if = "Vec::is_empty")]
121 pub directives: Vec<String>,
122}
123
124#[derive(Default)]
129pub struct Roots {
130 pub query: Option<String>,
131 pub mutation: Option<String>,
132 pub subscription: Option<String>,
133}
134
135impl Roots {
136 pub fn field_kind(&self, type_name: &str) -> Kind {
139 if self.query.as_deref() == Some(type_name) {
140 Kind::Query
141 } else if self.mutation.as_deref() == Some(type_name) {
142 Kind::Mutation
143 } else if self.subscription.as_deref() == Some(type_name) {
144 Kind::Subscription
145 } else {
146 Kind::Field
147 }
148 }
149}