rusty_gql/
executor.rs

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}