Skip to content

Latest commit

 

History

History

apollo-parser

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

apollo-parser

A parser for the GraphQL language.

Crates.io version Download docs.rs docs

Features

  • Typed GraphQL Concrete Syntax Tree as per October 2021 specification
  • Error resilience
    • lexing and parsing does not fail or panic if a lexical or a syntax error is found
  • GraphQL lexer
  • GraphQL parser

Getting started

Add the dependency to start using apollo-parser:

cargo add apollo-parser

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

# Just an example, change to the necessary package version.
[dependencies]
apollo-parser = "0.8.3"

Rust versions

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

Usage

apollo-parser is built to parse both GraphQL schemas and queries according to the latest October 2021 specification. It produces a typed syntax tree that then can be walked, extracting all the necessary information. You can quick start with:

use apollo_parser::Parser;

let input = "union SearchResult = Photo | Person | Cat | Dog";
let parser = Parser::new(input);
let cst = parser.parse();

apollo-parser is built to be error-resilient. This means we don't abort parsing (or lexing) if an error occurs. That means parser.parse() will always produce a CST (Concrete Syntax Tree), and it will be accompanied by any errors that are encountered:

use apollo_parser::Parser;

let input = "union SearchResult = Photo | Person | Cat | Dog";
let parser = Parser::new(input);
let cst = parser.parse();

// cst.errors() returns an iterator with the errors encountered during lexing and parsing
assert_eq!(0, cst.errors().len());

// cst.document() gets the Document, or root node, of the tree that you can
// start iterating on.
let doc = cst.document();

Examples

Two examples outlined here:

The examples directory in this repository has a few more useful implementations such as:

Get field names in an object

use apollo_parser::{cst, Parser};

let input = "
type ProductDimension {
  size: String
  weight: Float @tag(name: \"hi from inventory value type field\")
}
";
let parser = Parser::new(input);
let cst = parser.parse();
assert_eq!(0, cst.errors().len());

let doc = cst.document();

for def in doc.definitions() {
    if let cst::Definition::ObjectTypeDefinition(object_type) = def {
        assert_eq!(object_type.name().unwrap().text(), "ProductDimension");
        for field_def in object_type.fields_definition().unwrap().field_definitions() {
            println!("{}", field_def.name().unwrap().text()); // size weight
        }
    }
}

Get variables used in a query

use apollo_parser::{cst, Parser};

let input = "
  query GraphQuery($graph_id: ID!, $variant: String) {
    service(id: $graph_id) {
      schema(tag: $variant) {
        document
      }
    }
  }
  ";

  let parser = Parser::new(input);
  let cst = parser.parse();
  assert_eq!(0, cst.errors().len());

  let doc = cst.document();

  for def in doc.definitions() {
      if let cst::Definition::OperationDefinition(op_def) = def {
          assert_eq!(op_def.name().unwrap().text(), "GraphQuery");

          let variable_defs = op_def.variable_definitions();
          let variables: Vec<String> = variable_defs
              .iter()
              .map(|v| v.variable_definitions())
              .flatten()
              .filter_map(|v| Some(v.variable()?.text().to_string()))
              .collect();
          assert_eq!(
              variables.as_slice(),
              ["graph_id".to_string(), "variant".to_string()]
          );
      }
  }

License

Licensed under either of

at your option.