Skip to main content

Crate reed_compiler

Crate reed_compiler 

Source
Expand description

reed-compiler

Reed logo

A query-based compiler for the GraphQL query language.

Crates.io version Download docs.rs docs

§Features

  • A (comparatively) low-level AST for GraphQL grammar, and high-level representation of Schema and ExecutableDocument.
  • All three can be parsed (using reed-parser internally), created or modified programatically, and serialized.
  • Validation of schemas and executable documents, as defined in the GraphQL specification.
  • Execution of the schema introspection portion of queries.

§Getting started

Add the dependency to start using reed-compiler:

cargo add reed-compiler

Or add this to your Cargo.toml for a manual installation:

# Just an example, change to the necessary package version.
[dependencies]
reed-compiler = "0.1.0"

§Rust versions

reed-compiler is tested on the latest stable version of Rust. Older version may or may not be compatible.

§Usage

You can get started with reed-compiler:

use reed_compiler::Schema;
use reed_compiler::ExecutableDocument;

let sdl = r#"
  type Query {
    field: Int
  }
"#;
let query = "{ field }";

/// In case of validation errors, the panic message will be nicely formatted
/// to point at relevant parts of the source file(s)
let schema = Schema::parse_and_validate(sdl, "sdl.graphql").unwrap();
let doc = ExecutableDocument::parse_and_validate(&schema, query, "query.graphql").unwrap();

§Examples

§Accessing fragment definition field types
use reed_compiler::{Schema, ExecutableDocument, Node, executable};

let schema_input = r#"
type User {
  id: ID
  name: String
  profilePic(size: Int): URL
}

schema { query: User }

scalar URL @specifiedBy(url: "https://tools.ietf.org/html/rfc3986")
"#;
let query_input = r#"
query getUser {
  ... vipCustomer
}

#fragment definition where we want to know the field types.
fragment vipCustomer on User {
  id
  name
  profilePic(size: 50)
}
"#;

let schema = Schema::parse_and_validate(schema_input, "schema.graphql").unwrap();
let document = ExecutableDocument::parse_and_validate(&schema, query_input, "query.graphql")
    .unwrap();

let op = document.operations.get(Some("getUser")).expect("getUser query does not exist");
let fragment_in_op = op.selection_set.selections.iter().filter_map(|sel| match sel {
    executable::Selection::FragmentSpread(spread) => {
        Some(document.fragments.get(&spread.fragment_name)?.as_ref())
    }
    _ => None
}).collect::<Vec<&executable::Fragment>>();

let fragment_fields = fragment_in_op.iter().flat_map(|frag| {
    frag.selection_set.fields()
}).collect::<Vec<&Node<executable::Field>>>();
let field_ty = fragment_fields
    .iter()
    .map(|f| f.ty().inner_named_type().as_str())
    .collect::<Vec<&str>>();
assert_eq!(field_ty, ["ID", "String", "URL"]);
§Get a directive defined on a field used in a query operation definition.
use reed_compiler::{Schema, ExecutableDocument, Node, executable};

let schema_input = r#"
type Query {
  topProducts: Product
}

type Product {
  inStock: Boolean @join__field(graph: INVENTORY)
  name: String @join__field(graph: PRODUCTS)
}

enum join__Graph {
  INVENTORY,
  PRODUCTS,
}
directive @join__field(graph: join__Graph) on FIELD_DEFINITION
"#;
let query_input = r#"
query getProduct {
  topProducts {
    inStock
  }
}
"#;

let schema = Schema::parse_and_validate(schema_input, "schema.graphql").unwrap();
let document = ExecutableDocument::parse_and_validate(&schema, query_input, "query.graphql")
    .unwrap();

let get_product_op = document
    .operations
    .get(Some("getProduct"))
    .expect("getProduct query does not exist");

let in_stock_field = &get_product_op
    .selection_set
    .fields()
    .find(|f| f.name == "topProducts")
    .expect("topProducts field does not exist")
    .selection_set
    .fields()
    .find(|f| f.name == "inStock")
    .expect("inStock field does not exist")
    .definition;
let in_stock_directive: Vec<_> = in_stock_field
    .directives
    .iter()
    .map(|dir| &dir.name)
    .collect();
assert_eq!(in_stock_directive, ["join__field"]);
§Printing diagnostics for a faulty GraphQL document
use reed_compiler::parser::Parser;

let input = "{ ... }";

if let Err(diagnostics) = Parser::new().parse_mixed_validate(input, "document.graphql") {
    println!("{diagnostics}")
}

§License

Licensed under either of

at your option.

§Upstream provenance

Reed Compiler 0.1.0 is derived from Apollo Compiler 1.33.0 at upstream revision 5ebcc40bdf6919843c122e9a76b241689edcd6ef. The source corrections used to establish Reed are maintained in this crate and its regression tests. Package and crate paths, the parser dependency, documentation, workspace rustfmt layout, and regression tests are adapted for Reed; the compiler public API and module organization are retained.

Re-exports§

pub use self::executable::ExecutableDocument;
pub use self::schema::Schema;

Modules§

ast
Abstract Syntax Tree for GraphQL documents. An AST Document is more permissive but lower-level than Schema or ExecutableDocument.
collections
Type aliases for hashing-based collections configured with a specific hasher, as used in various places thorough the API
coordinate
Parsing and printing for schema coordinates as described in the RFC.
diagnostic
Pretty-printable diagnostic reports for errors that reference GraphQL documents.
executable
High-level representation of an executable document, which can contain operations and fragments.
introspection
Partial execition of the schema introspection portion of a query
parser
APIs related to parsing &str inputs as GraphQL syntax.
request
GraphQL requests
resolvers
GraphQL execution based on callbacks resolving one field at a time.
response
GraphQL responses
schema
High-level representation of a GraphQL type system document a.k.a. schema.
validation
Supporting APIs for GraphQL validation and other kinds of errors.

Macros§

coord
Create a DirectiveCoordinate, DirectiveArgumentCoordinate, TypeCoordinate, TypeAttributeCoordinate, or FieldArgumentCoordinate at compile time.
name
Create a Name from a string literal or identifier, checked for validity at compile time.
ty
Create a static Type with GraphQL-like syntax

Structs§

InvalidNameError
Tried to create a Name from a string that is not in valid GraphQL name syntax.
Name
A GraphQL Name identifier
Node
A thread-safe reference-counted smart pointer for GraphQL nodes.