Skip to main content

surrealdb_expr/expr/
graphql_config.rs

1//! GraphQL exposure configuration.
2//!
3//! `GraphQLConfig` selects which tables and functions a database exposes over
4//! GraphQL. It is shared vocabulary between the DEFINE CONFIG statement and
5//! the catalog's config definition; both planes persist it, so the revisioned
6//! shapes here are storage-stable.
7
8use revision::revisioned;
9use surrealdb_strand::Strand;
10
11use crate::expr::statements::info::InfoStructure;
12use crate::sql;
13use crate::val::{TableName, Value};
14
15#[revisioned(revision = 3)]
16#[derive(Clone, Debug, Default, Eq, PartialEq, Hash)]
17pub struct GraphQLConfig {
18	pub tables: GraphQLTablesConfig,
19	pub functions: GraphQLFunctionsConfig,
20	/// Maximum query nesting depth. `None` means no limit.
21	#[revision(start = 2)]
22	pub depth_limit: Option<u32>,
23	/// Maximum query complexity (total number of fields). `None` means no limit.
24	#[revision(start = 2)]
25	pub complexity_limit: Option<u32>,
26	/// Controls whether GraphQL schema introspection is enabled.
27	/// Defaults to `Auto` (introspection enabled).
28	#[revision(start = 3)]
29	pub introspection: GraphQLIntrospectionConfig,
30}
31
32impl InfoStructure for GraphQLConfig {
33	fn structure(self) -> Value {
34		Value::from(map!(
35			"tables" => self.tables.structure(),
36			"functions" => self.functions.structure(),
37			"depth_limit", if let Some(d) = self.depth_limit => Value::from(d as i64),
38			"complexity_limit", if let Some(c) = self.complexity_limit => Value::from(c as i64),
39			"introspection", if let GraphQLIntrospectionConfig::None = self.introspection => Value::None,
40		))
41	}
42}
43
44impl From<sql::statements::define::config::graphql::GraphQLConfig> for GraphQLConfig {
45	fn from(v: sql::statements::define::config::graphql::GraphQLConfig) -> Self {
46		GraphQLConfig {
47			tables: v.tables.into(),
48			functions: v.functions.into(),
49			depth_limit: v.depth_limit,
50			complexity_limit: v.complexity_limit,
51			introspection: v.introspection.into(),
52		}
53	}
54}
55
56impl From<GraphQLConfig> for sql::statements::define::config::graphql::GraphQLConfig {
57	fn from(v: GraphQLConfig) -> Self {
58		Self {
59			tables: v.tables.into(),
60			functions: v.functions.into(),
61			depth_limit: v.depth_limit,
62			complexity_limit: v.complexity_limit,
63			introspection: v.introspection.into(),
64		}
65	}
66}
67
68#[revisioned(revision = 1)]
69#[derive(Clone, Debug, Default, Eq, PartialEq, Hash)]
70pub enum GraphQLTablesConfig {
71	#[default]
72	None,
73	Auto,
74	Include(Vec<TableName>),
75	Exclude(Vec<TableName>),
76}
77
78impl InfoStructure for GraphQLTablesConfig {
79	fn structure(self) -> Value {
80		match self {
81			GraphQLTablesConfig::None => Value::None,
82			GraphQLTablesConfig::Auto => Value::String(Strand::new_static("AUTO")),
83			GraphQLTablesConfig::Include(ts) => Value::from(map!(
84				"include" => Value::Array(ts.into_iter().map(Value::Table).collect()),
85			)),
86			GraphQLTablesConfig::Exclude(ts) => Value::from(map!(
87				"exclude" => Value::Array(ts.into_iter().map(Value::Table).collect()),
88			)),
89		}
90	}
91}
92
93impl From<sql::statements::define::config::graphql::TablesConfig> for GraphQLTablesConfig {
94	fn from(v: sql::statements::define::config::graphql::TablesConfig) -> Self {
95		use sql::statements::define::config::graphql::TablesConfig;
96		match v {
97			TablesConfig::None => Self::None,
98			TablesConfig::Auto => Self::Auto,
99			TablesConfig::Include(cs) => {
100				Self::Include(cs.into_iter().map(|t| t.name.into()).collect())
101			}
102			TablesConfig::Exclude(cs) => {
103				Self::Exclude(cs.into_iter().map(|t| t.name.into()).collect())
104			}
105		}
106	}
107}
108
109impl From<GraphQLTablesConfig> for sql::statements::define::config::graphql::TablesConfig {
110	fn from(v: GraphQLTablesConfig) -> Self {
111		use sql::statements::define::config::graphql::TableConfig;
112		match v {
113			GraphQLTablesConfig::None => Self::None,
114			GraphQLTablesConfig::Auto => Self::Auto,
115			GraphQLTablesConfig::Include(cs) => Self::Include(
116				cs.into_iter()
117					.map(|t| TableConfig {
118						name: t.into(),
119					})
120					.collect(),
121			),
122			GraphQLTablesConfig::Exclude(cs) => Self::Exclude(
123				cs.into_iter()
124					.map(|t| TableConfig {
125						name: t.into(),
126					})
127					.collect(),
128			),
129		}
130	}
131}
132
133#[revisioned(revision = 1)]
134#[derive(Clone, Debug, Default, Eq, PartialEq, Hash)]
135pub enum GraphQLFunctionsConfig {
136	#[default]
137	None,
138	Auto,
139	Include(Vec<Strand>),
140	Exclude(Vec<Strand>),
141}
142
143impl InfoStructure for GraphQLFunctionsConfig {
144	fn structure(self) -> Value {
145		match self {
146			GraphQLFunctionsConfig::None => Value::None,
147			GraphQLFunctionsConfig::Auto => Value::String(Strand::new_static("AUTO")),
148			GraphQLFunctionsConfig::Include(fs) => Value::from(map!(
149				"include" => Value::Array(fs.into_iter().map(Value::from).collect()),
150			)),
151			GraphQLFunctionsConfig::Exclude(fs) => Value::from(map!(
152				"exclude" => Value::Array(fs.into_iter().map(Value::from).collect()),
153			)),
154		}
155	}
156}
157
158impl From<sql::statements::define::config::graphql::FunctionsConfig> for GraphQLFunctionsConfig {
159	fn from(v: sql::statements::define::config::graphql::FunctionsConfig) -> Self {
160		use sql::statements::define::config::graphql::FunctionsConfig;
161		match v {
162			FunctionsConfig::None => Self::None,
163			FunctionsConfig::Auto => Self::Auto,
164			FunctionsConfig::Include(cs) => Self::Include(cs),
165			FunctionsConfig::Exclude(cs) => Self::Exclude(cs),
166		}
167	}
168}
169
170impl From<GraphQLFunctionsConfig> for sql::statements::define::config::graphql::FunctionsConfig {
171	fn from(v: GraphQLFunctionsConfig) -> Self {
172		match v {
173			GraphQLFunctionsConfig::None => Self::None,
174			GraphQLFunctionsConfig::Auto => Self::Auto,
175			GraphQLFunctionsConfig::Include(cs) => Self::Include(cs),
176			GraphQLFunctionsConfig::Exclude(cs) => Self::Exclude(cs),
177		}
178	}
179}
180
181#[revisioned(revision = 1)]
182#[derive(Clone, Debug, Default, Eq, PartialEq, Hash)]
183pub enum GraphQLIntrospectionConfig {
184	#[default]
185	Auto,
186	None,
187}
188
189impl InfoStructure for GraphQLIntrospectionConfig {
190	fn structure(self) -> Value {
191		match self {
192			GraphQLIntrospectionConfig::Auto => Value::String(Strand::new_static("AUTO")),
193			GraphQLIntrospectionConfig::None => Value::None,
194		}
195	}
196}
197
198impl From<sql::statements::define::config::graphql::IntrospectionConfig>
199	for GraphQLIntrospectionConfig
200{
201	fn from(v: sql::statements::define::config::graphql::IntrospectionConfig) -> Self {
202		match v {
203			sql::statements::define::config::graphql::IntrospectionConfig::Auto => Self::Auto,
204			sql::statements::define::config::graphql::IntrospectionConfig::None => Self::None,
205		}
206	}
207}
208
209impl From<GraphQLIntrospectionConfig>
210	for sql::statements::define::config::graphql::IntrospectionConfig
211{
212	fn from(v: GraphQLIntrospectionConfig) -> Self {
213		match v {
214			GraphQLIntrospectionConfig::Auto => Self::Auto,
215			GraphQLIntrospectionConfig::None => Self::None,
216		}
217	}
218}