apollo-parser
Add this to your Cargo.toml
to start using apollo-compiler
:
```toml
[dependencies] apollo-compiler = "0.4.0" ```
Or using [cargo-edit]:
bash
cargo add apollo-compiler
apollo-compiler
is built using [salsa
] to provide a
memoised query system on top of the AST produced by apollo-parser
.
The idea is that all relationships between GraphQL types are pre-established and pre-computed, so you are able to always find the reference to say a field Type, or a Directive.
You can get started with apollo-compiler
:
```rust
use apollo_compiler::ApolloCompiler;
let input = r#" interface Pet { name: String }
type Dog implements Pet { name: String nickname: String barkVolume: Int }
type Cat implements Pet { name: String nickname: String meowVolume: Int }
union CatOrDog = Cat | Dog
type Human { name: String pets: [Pet] }
type Query { human: Human } "#;
let ctx = ApolloCompiler::new(input); let diagnostics = ctx.validate(); for diagnostic in &diagnostics { // this will pretty-print diagnostics using the miette crate. println!("{}", diagnostic); } assert!(diagnostics.is_empty()); ```
```rust use apollo_compiler::{ApolloCompiler, hir, DocumentDatabase}; use miette::Result;
fn main() -> Result<()> { let input = r#" query getProduct { topProducts { type } ... vipCustomer }
#fragment definition where we want to know the field types.
fragment vipCustomer on User {
id
name
profilePic(size: 50)
}
type Query {
topProducts: Product
customer: User
}
type Product {
type: String
price(setPrice: Int): Int
}
type User {
id: ID
name: String
profilePic(size: Int): URL
}
scalar URL @specifiedBy(url: "https://tools.ietf.org/html/rfc3986")
"#;
let ctx = ApolloCompiler::new(input);
let diagnostics = ctx.validate();
for diagnostic in &diagnostics {
println!("{}", diagnostic);
}
assert!(diagnostics.is_empty());
let op = ctx.db.find_operation_by_name(String::from("getProduct")).expect("getProduct query does not exist");
let fragment_in_op: Vec<hir::FragmentDefinition> = op.selection_set().selection().iter().filter_map(|sel| match sel {
hir::Selection::FragmentSpread(frag) => {
Some(frag.fragment(&ctx.db)?.as_ref().clone())
}
_ => None
}).collect();
let fragment_fields: Vec<hir::Field> = fragment_in_op.iter().flat_map(|frag| frag.selection_set().fields()).collect();
let field_ty: Vec<String> = fragment_fields
.iter()
.filter_map(|f| Some(f.ty(&ctx.db)?.name()))
.collect();
assert_eq!(field_ty, ["ID", "String", "URL"]);
Ok(())
} ```
```rust use apollo_compiler::{ApolloCompiler, hir, HirDatabase}; use anyhow::{anyhow, Result};
fn main() -> Result<()> { let input = r#" query getProduct { size topProducts { name inStock } }
type Query {
topProducts: Product
name: String
size: Int
}
type Product {
inStock: Boolean @join__field(graph: INVENTORY)
name: String @join__field(graph: PRODUCTS)
price: Int
shippingEstimate: Int
upc: String!
weight: Int
}
"#;
let ctx = ApolloCompiler::new(input);
let diagnostics = ctx.validate();
for diagnostic in &diagnostics {
println!("{}", diagnostic);
}
assert!(diagnostics.is_empty());
let ctx = ApolloCompiler::new(input);
let diagnostics = ctx.validate();
for diagnostic in &diagnostics {
println!("{}", diagnostic);
}
assert!(diagnostics.is_empty());
let operations = ctx.db.operations();
let get_product_op = operations
.iter()
.find(|op| op.name() == Some("getProduct")).expect("getProduct query does not exist");
let op_fields = get_product_op.fields(&ctx.db);
let in_stock_field = op_fields
.iter()
.find(|f| f.name() == "topProducts")
.expect("topProducts field does not exist")
.selection_set()
.field("inStock")
.expect("inStock field does not exist")
.field_definition(&ctx.db)
.expect("field definition does not exist");
let in_stock_directive: Vec<&str> = in_stock_field
.directives()
.iter()
.map(|dir| dir.name())
.collect();
assert_eq!(in_stock_directive, ["join__field"]);
Ok(())
} ```
```rust use apollo_compiler::ApolloCompiler;
let input = r#" query { cat { name } }
query getPet { cat { owner { name } } }
query getPet { cat { treat } }
subscription sub { newMessage { body sender } disallowedSecondRootField }
type Query { cat: Pet }
type Subscription { newMessage: Result }
interface Pet { name: String }
type Dog implements Pet { name: String nickname: String barkVolume: Int }
type Cat implements Pet { name: String nickname: String meowVolume: Int }
union CatOrDog = Cat | Dog "#;
let ctx = ApolloCompiler::new(input); let diagnostics = ctx.validate(); for diagnostic in &diagnostics { println!("{}", diagnostic) } assert_eq!(diagnostics.len(), 5) ```
Licensed under either of
at your option.