Skip to content

Commit 87d1d4d

Browse files
SimonSapinlrlna
andauthored
Another docs & API pass (#945)
Co-authored-by: Iryna Shestak <[email protected]>
1 parent 80ce031 commit 87d1d4d

21 files changed

+212
-211
lines changed

ARCHITECTURE.md

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ This document gives an overview of how various bits of `apollo-rs` work together
77
theme for Rust as a language, and we want to make sure that all component APIs
88
we provide are aligned with these principles.
99

10-
2. **Stability and reliability.** Spec-compliant, and idempotent APIs which,
11-
when complete, can be used safely in enterprise-grade codebases.
10+
2. **Stability and reliability.** Spec-compliant and idempotent APIs
11+
which can be used safely in enterprise-grade codebases.
1212

1313
3. **Diagnostics.** The tools are to be written in a way that will allow us to
1414
produce detailed diagnostics. It does not panic or return early if there is a
@@ -20,19 +20,17 @@ maintaining this project.
2020
4. **Extensibility.** The parser is written to work with different use cases in
2121
our budding Rust GraphQL ecosystem, be it building schema-diagnostics for Rover,
2222
or writing out query planning and composition algorithms in Rust. These all have
23-
quite different requirements when it comes to CST manipulation. We wanted to
23+
quite different requirements when it comes to document manipulation. We wanted to
2424
make sure we account for them early on.
2525

2626
## `apollo-parser`
2727

2828
`apollo-parser` is the parser crate of `apollo-rs`. Its job is to take GraphQL
29-
queries or schemas as input and produce an Concrete Syntax Tree (CST). Users of
30-
apollo-parser can then programmatically traverse the CST to get information
31-
about their input.
29+
queries or schemas as string input and produce an Concrete Syntax Tree (CST).
30+
Users of apollo-parser can then programmatically traverse the CST to get information
31+
about their input.
3232

33-
There are three main components of `apollo-parser`: the lexer, the parser, and the analyser. We already have the lexer and the parser, and the analyser is in the process of getting written.
34-
35-
![An overview of apollo-parser diagram. We initially start of with input data. A Lexer performs lexical analysis on the data and produces tokens. Tokens get syntactically analysed by the parser, first into an untyped syntax tree, then into a typed syntax tree. "Future Work" indicates that a typed syntax tree will be semantically analysed by the "Analyser" to produce a semantic model.](images/apollo-parser-overview.png)
33+
There are two main components of `apollo-parser`: the lexer and the parser.
3634

3735
`apollo-parser` is a hand-written recursive-descent parser. This is a type of
3836
parser that starts from the top of a file and recursively walks its way down
@@ -66,7 +64,8 @@ if has_exponent || has_fractional {
6664
}
6765
```
6866

69-
The lexer returns a `Vec<Token>` and `Vec<Error>` that the parser then uses to create a tree. If the error vec is empty, we can be sure that the input is lexically correct!
67+
The lexer is an iterator of `Result<Token, Error>` that the parser then uses to create a tree.
68+
If no error is emitted, we can be sure that the input is lexically correct!
7069

7170
### Parser
7271
The next step in our parsing pipeline is the parser. The parser’s job is to take the tokens produced by the lexer and create nodes with information and relationships that in the end make up a syntax tree. Much like with the lexer, the parser is error resilient. Syntactic errors, such as a missing `Name` in a `ScalarDefinition`, are added to parser’s error vector while the parser carries on parsing.

README.md

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<h1><code>apollo-rs</code></h1>
33

44
<p>
5-
<strong>Rust tooling for low-level manipulation of the GraphQL language.</strong>
5+
<strong>Rust tooling for manipulation of the GraphQL language.</strong>
66
</p>
77
</div>
88

@@ -14,26 +14,23 @@ these libraries is specific to Apollo, and can freely be used by other
1414
projects which need standards-compliant GraphQL tooling written in Rust. The
1515
following crates currently exist:
1616

17-
* [**`apollo-compiler`**](crates/apollo-compiler/) - a library to compile and semantically analyze GraphQL query language.
18-
* [**`apollo-parser`**](crates/apollo-parser) - a library to parse the GraphQL query language.
19-
* [**`apollo-smith`**](crates/apollo-smith) - a test case generator to test GraphQL code (SDL).
17+
* [**`apollo-compiler`**](crates/apollo-compiler/) - a library to manipulate, semantically analyze, and validate GraphQL schema definition and query language
18+
* [**`apollo-parser`**](crates/apollo-parser) - a library to parse the GraphQL (used by `apollo-compiler`)
19+
* [**`apollo-smith`**](crates/apollo-smith) - a test case generator to deterministically produce arbitrary GraphQL documents
2020

2121
Please check out their respective READMEs for usage examples.
2222

2323
## Status
24-
`apollo-rs` is a work in progress. Please check out the
25-
[ROADMAP](ROADMAP.md) for upcoming features we are working on building.
26-
27-
If you do end up trying out `apollo-rs` and run into trouble, we encourage you
28-
to open an [issue].
24+
`apollo-rs` is a living project that keeps evolving and is being used in production.
25+
If you try out `apollo-rs` and run into trouble, we encourage you to open an [issue].
2926

3027
## Design Principles
3128
1. **Prioritizing developer experience.** Elegant and ergonomic APIs is the
3229
theme for Rust as a language, and we want to make sure that all component APIs
3330
we provide are aligned with these principles.
3431

35-
2. **Stability and reliability.** Spec-compliant, and idempotent APIs which,
36-
when complete, can be used safely in enterprise-grade codebases.
32+
2. **Stability and reliability.** Spec-compliant, and idempotent APIs
33+
which can be used safely in enterprise-grade codebases.
3734

3835
3. **Diagnostics.** The tools are to be written in a way that will allow us to
3936
produce detailed diagnostics. It does not panic or return early if there is a
@@ -45,7 +42,7 @@ maintaining this project.
4542
4. **Extensibility.** The parser is written to work with different use cases in
4643
our budding Rust GraphQL ecosystem, be it building schema-diagnostics for Rover,
4744
or writing out query planning and composition algorithms in Rust. These all have
48-
quite different requirements when it comes to AST manipulation. We wanted to
45+
quite different requirements when it comes to document manipulation. We wanted to
4946
make sure we account for them early on.
5047

5148
## Rust versions

ROADMAP.md

Lines changed: 0 additions & 25 deletions
This file was deleted.

crates/apollo-compiler/README.md

Lines changed: 12 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@
2525
created or modified programatically,
2626
and serialized.
2727
* Validation of schemas and executable documents, as defined [in the GraphQL specification][val].
28+
* Execution of the [schema introspection][introsp] portion of queries.
2829

2930
[val]: https://spec.graphql.org/October2021/#sec-Validation
31+
[introsp]: https://spec.graphql.org/October2021/#sec-Introspection
3032

3133
## Getting started
3234
Add the dependency to start using `apollo-compiler`:
@@ -53,39 +55,19 @@ Older version may or may not be compatible.
5355
You can get started with `apollo-compiler`:
5456
```rust
5557
use apollo_compiler::Schema;
58+
use apollo_compiler::ExecutableDocument;
5659

57-
let input = r#"
58-
interface Pet {
59-
name: String
60-
}
61-
62-
type Dog implements Pet {
63-
name: String
64-
nickname: String
65-
barkVolume: Int
66-
}
67-
68-
type Cat implements Pet {
69-
name: String
70-
nickname: String
71-
meowVolume: Int
72-
}
73-
74-
union CatOrDog = Cat | Dog
75-
76-
type Human {
77-
name: String
78-
pets: [Pet]
79-
}
80-
60+
let sdl = r#"
8161
type Query {
82-
human: Human
62+
field: Int
8363
}
8464
"#;
65+
let query = "{ field }";
8566

8667
/// In case of validation errors, the panic message will be nicely formatted
8768
/// to point at relevant parts of the source file(s)
88-
let schema = Schema::parse_and_validate(input, "document.graphql").unwrap();
69+
let schema = Schema::parse_and_validate(sdl, "sdl.graphql").unwrap();
70+
let doc = ExecutableDocument::parse_and_validate(&schema, query, "query.graphql").unwrap();
8971
```
9072

9173
### Examples
@@ -147,31 +129,22 @@ use apollo_compiler::{Schema, ExecutableDocument, Node, executable};
147129
let schema_input = r#"
148130
type Query {
149131
topProducts: Product
150-
name: String
151-
size: Int
152132
}
153133
154134
type Product {
155135
inStock: Boolean @join__field(graph: INVENTORY)
156136
name: String @join__field(graph: PRODUCTS)
157-
price: Int
158-
shippingEstimate: Int
159-
upc: String!
160-
weight: Int
161137
}
162138
163139
enum join__Graph {
164140
INVENTORY,
165141
PRODUCTS,
166142
}
167-
scalar join__FieldSet
168-
directive @join__field(graph: join__Graph, requires: join__FieldSet, provides: join__FieldSet) on FIELD_DEFINITION
143+
directive @join__field(graph: join__Graph) on FIELD_DEFINITION
169144
"#;
170145
let query_input = r#"
171146
query getProduct {
172-
size
173147
topProducts {
174-
name
175148
inStock
176149
}
177150
}
@@ -206,63 +179,11 @@ assert_eq!(in_stock_directive, ["join__field"]);
206179

207180
#### Printing diagnostics for a faulty GraphQL document
208181
```rust
209-
let input = r#"
210-
query {
211-
cat {
212-
name
213-
}
214-
}
215-
216-
query getPet {
217-
cat {
218-
owner {
219-
name
220-
}
221-
}
222-
}
223-
224-
query getPet {
225-
cat {
226-
treat
227-
}
228-
}
182+
use apollo_compiler::parser::Parser;
229183

230-
subscription sub {
231-
newMessage {
232-
body
233-
sender
234-
}
235-
disallowedSecondRootField
236-
}
237-
238-
type Query {
239-
cat: Pet
240-
}
241-
242-
type Subscription {
243-
newMessage: Result
244-
}
245-
246-
interface Pet {
247-
name: String
248-
}
249-
250-
type Dog implements Pet {
251-
name: String
252-
nickname: String
253-
barkVolume: Int
254-
}
255-
256-
type Cat implements Pet {
257-
name: String
258-
nickname: String
259-
meowVolume: Int
260-
}
261-
262-
union CatOrDog = Cat | Dog
263-
"#;
184+
let input = "{ ... }";
264185

265-
if let Err(diagnostics) = apollo_compiler::parse_mixed_validate(input, "document.graphql") {
186+
if let Err(diagnostics) = Parser::new().parse_mixed_validate(input, "document.graphql") {
266187
println!("{diagnostics}")
267188
}
268189
```

crates/apollo-compiler/examples/file_watcher.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use anyhow::anyhow;
22
use anyhow::Result;
3+
use apollo_compiler::parser::Parser;
34
use apollo_compiler::validation::Valid;
45
use apollo_compiler::ExecutableDocument;
56
use apollo_compiler::Schema;
@@ -112,7 +113,9 @@ impl FileWatcher {
112113
src_path: PathBuf,
113114
) -> Result<PathBuf, anyhow::Error> {
114115
let full_path = fs::canonicalize(&src_path)?;
115-
let doc = apollo_compiler::parse_mixed_validate(proposed_document, src_path).unwrap();
116+
let doc = Parser::new()
117+
.parse_mixed_validate(proposed_document, src_path)
118+
.unwrap();
116119
self.manifest.insert(full_path.clone(), doc);
117120
Ok(full_path)
118121
}

crates/apollo-compiler/examples/hello_world.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use apollo_compiler::executable;
2+
use apollo_compiler::parser::Parser;
23
use apollo_compiler::Node;
34
use std::fs;
45
use std::path::Path;
@@ -7,7 +8,7 @@ fn compile_query() -> Option<Node<executable::Fragment>> {
78
let file = Path::new("crates/apollo-compiler/examples/query_with_errors.graphql");
89
let src = fs::read_to_string(file).expect("Could not read schema file.");
910

10-
let (_, document) = apollo_compiler::parse_mixed_validate(src, file).unwrap();
11+
let (_, document) = Parser::new().parse_mixed_validate(src, file).unwrap();
1112
let operation_names: Vec<_> = document
1213
.operations
1314
.named

crates/apollo-compiler/examples/multi_source_validation.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use apollo_compiler::parse_mixed_validate;
1+
use apollo_compiler::parser::Parser;
22
use apollo_compiler::ExecutableDocument;
33
use apollo_compiler::Schema;
44
use std::fs;
@@ -19,7 +19,9 @@ fn compile_from_dir() -> io::Result<()> {
1919
for entry in fs::read_dir(dir)? {
2020
let entry = entry?;
2121
let src = fs::read_to_string(entry.path()).expect("Could not read document file.");
22-
let (_schema, _executable) = parse_mixed_validate(&src, entry.path()).unwrap();
22+
let (_schema, _executable) = Parser::new()
23+
.parse_mixed_validate(&src, entry.path())
24+
.unwrap();
2325
}
2426
}
2527
Ok(())

crates/apollo-compiler/examples/validate.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use apollo_compiler::parser::Parser;
12
use std::io::Read;
23
use std::process::ExitCode;
34

@@ -19,7 +20,7 @@ fn main() -> ExitCode {
1920
),
2021
};
2122

22-
match apollo_compiler::parse_mixed_validate(source, filename) {
23+
match Parser::new().parse_mixed_validate(source, filename) {
2324
Ok((_schema, _executable)) => ExitCode::SUCCESS,
2425
Err(errors) => {
2526
eprintln!("{errors:?}");

0 commit comments

Comments
 (0)