1use crate::{
2 container::Container, context::build_context, error::GqlError, operation::build_operation,
3 request::Request, resolve_selection_parallelly, resolve_selection_serially, response::Response,
4 validation::apply_validation, OperationType, SelectionSetResolver,
5};
6
7pub async fn execute<
8 Query: SelectionSetResolver + 'static,
9 Mutation: SelectionSetResolver + 'static,
10 Subscription: SelectionSetResolver + 'static,
11>(
12 container: &Container<Query, Mutation, Subscription>,
13 request: Request,
14) -> Response {
15 let query_doc = match graphql_parser::parse_query::<String>(&request.query) {
16 Ok(doc) => doc,
17 Err(_) => {
18 let err = GqlError::new("failed to parse query", None);
19 return Response::from_errors(vec![err]);
20 }
21 };
22 let operation = build_operation(
23 &query_doc,
24 request.operation_name.clone(),
25 request.variables.clone(),
26 );
27
28 let operation = match operation {
29 Ok(op) => op,
30 Err(error) => return Response::from_errors(vec![error]),
31 };
32
33 if let Err(errors) = apply_validation(
34 &container.schema,
35 &query_doc,
36 Some(&request.variables),
37 &operation,
38 request.operation_name.as_deref(),
39 ) {
40 return Response::from_errors(errors);
41 }
42
43 let ctx = build_context(&container.schema, &operation);
44
45 let result = match operation.operation_type {
46 OperationType::Query => {
47 resolve_selection_parallelly(&ctx, &container.query_resolvers).await
48 }
49 OperationType::Mutation => {
50 resolve_selection_serially(&ctx, &container.mutation_resolvers).await
51 }
52 OperationType::Subscription => {
53 let error = GqlError::new("Subscription cannot execute from this path", None);
54 return Response::from_errors(vec![error]);
55 }
56 };
57
58 match result {
59 Ok(value) => {
60 if !ctx.operation.errors.lock().unwrap().is_empty() {
61 Response::from_data_and_errors(value, ctx.operation.errors.lock().unwrap().clone())
62 } else {
63 Response::new(value)
64 }
65 }
66 Err(error) => {
67 let mut errors = vec![error];
68 errors.extend(ctx.operation.errors.lock().unwrap().clone());
69 Response::from_errors(errors)
70 }
71 }
72}