Expand description
§Features
- A (comparatively) low-level AST for GraphQL grammar,
and high-level representation of
SchemaandExecutableDocument. - All three can be parsed (using
reed-parserinternally), 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-compilerOr 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
- Apache License, Version 2.0 (LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or https://opensource.org/licenses/MIT)
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
Documentis more permissive but lower-level thanSchemaorExecutableDocument. - 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
&strinputs 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, orFieldArgumentCoordinateat compile time. - name
- Create a
Namefrom a string literal or identifier, checked for validity at compile time. - ty
- Create a static
Typewith GraphQL-like syntax
Structs§
- Invalid
Name Error - Tried to create a
Namefrom 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.