Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add some documentation to graphql_query/ in trustfall_core #138

Merged
merged 6 commits into from
Feb 11, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions trustfall_core/src/graphql_query/directives.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//! Directives in GraphQL can be identified by staring with `@`. While
//! `trustfall_core` doesn't support all GraphQL directives, some are available.
use std::{collections::HashSet, convert::TryFrom, num::NonZeroUsize, sync::Arc};

use async_graphql_parser::{types::Directive, Positioned};
Expand All @@ -9,14 +11,38 @@ use crate::ir::{Operation, TransformationKind};

use super::error::ParseError;

/// An argument as passed to the `value` array, for example for a `@filter`
/// directive (see [FilterDirective]).
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum OperatorArgument {
/// Reference to a variable provided to the query. Variable names are always
/// prefixed with `$`.
VariableRef(Arc<str>),

/// Reference to a `@tag`ed value encountered elsewhere
/// in the query. Tag names are always prefixed with `%`.
TagRef(Arc<str>),
}

/// A GraphQL `@filter` directive.
///
/// The following GraphQL filter directive and Rust instance would be
/// equivalent:
///
/// ```graphql
/// @filter(op: ">=", value: ["$some_value"])
/// ```
///
/// and
///
/// ```ignore
/// FilterDirective {
/// operation: Operation::GreaterThanOrEqual(OperatorArgument::VariableRef(Arc::new("$some_value"), 1))
/// }
/// ```
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
pub(crate) struct FilterDirective {
/// Describes which operation should be made by the filter
pub operation: Operation<(), OperatorArgument>,
}

Expand Down Expand Up @@ -152,8 +178,21 @@ impl TryFrom<&Positioned<Directive>> for FilterDirective {
}
}

/// A GraphQL `@output` directive.
///
/// For example, the following GraphQL and Rust would be equivalent:
/// ```graphql
/// @output(name: "betterName")
/// ```
///
/// and
///
/// ```ignore
/// OutputDirective { name: Some(Arc::new("betterName"))}
/// ```
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
pub(crate) struct OutputDirective {
/// The name that should be used for this field when it is given as output
#[serde(default, skip_serializing_if = "Option::is_none")]
pub name: Option<Arc<str>>,
}
Expand Down Expand Up @@ -214,8 +253,21 @@ impl TryFrom<&Positioned<Directive>> for OutputDirective {
}
}

/// A GraphQL `@transform` directive.
///
/// For example, the following GraphQL and Rust would be equivalent:
/// ```graphql
/// @transform(op: "count")
/// ```
///
/// and
///
/// ```ignore
/// TransformDirective { kind: TransformationKind::Count }
/// ```
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
pub(crate) struct TransformDirective {
/// The `op` in a GraphQL `@transform`
pub kind: TransformationKind,
}

Expand Down Expand Up @@ -277,6 +329,18 @@ impl TryFrom<&Positioned<Directive>> for TransformDirective {
}
}

/// A GraphQL `@tag` directive.
///
/// For example, the following GraphQL and Rust would be equivalent:
/// ```graphql
/// @tag(name: "%tag_name")
/// ```
///
/// and
///
/// ```ignore
/// TagDirective { name: Some(Arc::new("%tag_name"))}
/// ```
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
pub(crate) struct TagDirective {
#[serde(default, skip_serializing_if = "Option::is_none")]
Expand Down Expand Up @@ -337,6 +401,7 @@ impl TryFrom<&Positioned<Directive>> for TagDirective {
}
}

/// A GraphQL `@optional` directive.
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
pub(crate) struct OptionalDirective {}

Expand All @@ -357,6 +422,7 @@ impl TryFrom<&Positioned<Directive>> for OptionalDirective {
}
}

/// A GraphQL `@fold` directive.
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
pub(crate) struct FoldDirective {}

Expand All @@ -377,6 +443,18 @@ impl TryFrom<&Positioned<Directive>> for FoldDirective {
}
}

/// A GraphQL `@recurse` directive.
///
/// For example, the following GraphQL and Rust would be equivalent:
/// ```graphql
/// @recurse(depth: 1)
/// ```
///
/// and
///
/// ```ignore
/// RecurseDirective { depth: NonZeroUsize::new(1usize)}
/// ```
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
pub(crate) struct RecurseDirective {
pub depth: NonZeroUsize,
Expand Down
1 change: 1 addition & 0 deletions trustfall_core/src/graphql_query/error.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//! Errors from parsing GraphQL
use async_graphql_parser::Pos;
use async_graphql_value::Value;
use serde::{ser::Error as SerError, Deserialize, Serialize, Serializer};
Expand Down
1 change: 1 addition & 0 deletions trustfall_core/src/graphql_query/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//! Translating GraphQL queries to Rust types
pub(crate) mod directives;
pub mod error;
pub(crate) mod query;
5 changes: 5 additions & 0 deletions trustfall_core/src/graphql_query/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ impl ParsedDirective {
}
}

/// Attempts to extract the query root from an [ExecutableDocument]
///
/// May return [ParseError] if the query is empty, there is no query root, or
/// the query root is not formatted properly
fn try_get_query_root(document: &ExecutableDocument) -> Result<&Positioned<Field>, ParseError> {
if let Some(v) = document.fragments.values().next() {
return Err(ParseError::DocumentContainsNonInlineFragments(v.pos));
Expand Down Expand Up @@ -507,6 +511,7 @@ fn make_transform_group(
})
}

/// Parses a query document. May fail if a query root is missing (see [try_get_query_root](try_get_query_root))
pub(crate) fn parse_document(document: &ExecutableDocument) -> Result<Query, ParseError> {
let query_root = try_get_query_root(document)?;

Expand Down