Skip to content

Commit 2b4c4f0

Browse files
committed
fix: expose more of the queries::builders types.
A lot of these are used by the derives and will be useful for generating dynamic queries, but don't appear in the documentation because they're not public enough.
1 parent e70291b commit 2b4c4f0

File tree

3 files changed

+151
-1
lines changed

3 files changed

+151
-1
lines changed

cynic/src/queries/builders.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,7 @@ impl<'a, SchemaType, VariablesFields> InlineFragmentBuilder<'a, SchemaType, Vari
285285
}
286286
}
287287

288+
/// Builds an input (usually an argument or a type nested inside an argument) in a query
288289
pub struct InputBuilder<'a, SchemaType, VariablesFields> {
289290
destination: InputLiteralContainer<'a>,
290291
context: BuilderContext<'a>,
@@ -464,6 +465,7 @@ impl<'a> InputLiteralContainer<'a> {
464465
}
465466
}
466467

468+
/// Builds a directive in a query
467469
pub struct DirectiveBuilder<'a, DirectiveMarker, VariablesFields> {
468470
arguments: &'a mut Vec<Argument>,
469471
context: BuilderContext<'a>,

cynic/src/queries/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ use crate::QueryVariableLiterals;
1515

1616
pub use self::{
1717
ast::{Argument, InputLiteral, SelectionSet},
18-
builders::{SelectionBuilder, VariableMatch},
18+
builders::{
19+
DirectiveBuilder, FieldSelectionBuilder, InlineFragmentBuilder, InputBuilder,
20+
SelectionBuilder, VariableMatch,
21+
},
1922
flatten::FlattensInto,
2023
input_literal_ser::to_input_literal,
2124
recurse::Recursable,
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
//! An example using the GitHub API
2+
//!
3+
//! Note that this example pulls a schema from the `github_schema` crate.
4+
//! This is because the github schema is massive and compiling the output
5+
//! of `use_schema` is quite slow. Moving this into a separate crate
6+
//! means we won't have to recompile it every time this file changes
7+
//! and we'll only need to do so once per full build of cynic.
8+
//!
9+
//! You may want to do similar if you're also working with cynic & the
10+
//! github API.
11+
//!
12+
//! This example requires the `reqwest-blocking` feature to be active.
13+
14+
fn main() {
15+
let result = run_query();
16+
println!("{:?}", result);
17+
}
18+
19+
fn run_query() -> cynic::GraphQlResponse<PullRequestTitles> {
20+
use cynic::http::ReqwestBlockingExt;
21+
22+
let query = build_query();
23+
24+
let token = std::env::var("GITHUB_TOKEN").expect("GITHUB_TOKEN env var must be set");
25+
26+
reqwest::blocking::Client::new()
27+
.post("https://api.github.com/graphql")
28+
.header("Authorization", format!("Bearer {}", token))
29+
.header("User-Agent", "obmarg")
30+
.run_graphql(query)
31+
.unwrap()
32+
}
33+
34+
fn build_query() -> cynic::Operation<PullRequestTitles, PullRequestTitlesArguments> {
35+
use cynic::QueryBuilder;
36+
37+
PullRequestTitles::build(PullRequestTitlesArguments {
38+
pr_order: IssueOrder {
39+
direction: OrderDirection::Asc,
40+
field: IssueOrderField::CreatedAt,
41+
},
42+
})
43+
}
44+
45+
use github_schema as schema;
46+
47+
pub type DateTime = chrono::DateTime<chrono::Utc>;
48+
49+
#[derive(cynic::QueryVariables, Debug)]
50+
pub struct PullRequestTitlesArguments {
51+
pub pr_order: IssueOrder,
52+
}
53+
54+
#[derive(cynic::InputObject, Clone, Debug)]
55+
#[cynic(schema = "github", rename_all = "camelCase")]
56+
pub struct IssueOrder {
57+
pub direction: OrderDirection,
58+
pub field: IssueOrderField,
59+
}
60+
61+
#[derive(cynic::Enum, Clone, Copy, Debug)]
62+
#[cynic(schema = "github", rename_all = "SCREAMING_SNAKE_CASE")]
63+
pub enum OrderDirection {
64+
Asc,
65+
Desc,
66+
}
67+
68+
#[derive(cynic::Enum, Clone, Copy, Debug)]
69+
#[cynic(schema = "github", rename_all = "SCREAMING_SNAKE_CASE")]
70+
pub enum IssueOrderField {
71+
Comments,
72+
CreatedAt,
73+
UpdatedAt,
74+
}
75+
76+
#[derive(cynic::QueryFragment, Debug)]
77+
#[cynic(
78+
graphql_type = "Query",
79+
schema = "github",
80+
variables = "PullRequestTitlesArguments"
81+
)]
82+
pub struct PullRequestTitles {
83+
#[arguments(name = "cynic".to_string(), owner = "obmarg".to_string())]
84+
pub repository: Option<Repository>,
85+
}
86+
87+
#[derive(cynic::QueryFragment, Debug)]
88+
#[cynic(schema = "github", variables = "PullRequestTitlesArguments")]
89+
pub struct Repository {
90+
#[arguments(orderBy: $pr_order, first: 10)]
91+
pub pull_requests: PullRequestConnection,
92+
}
93+
94+
#[derive(cynic::QueryFragment, Debug)]
95+
#[cynic(schema = "github")]
96+
pub struct PullRequestConnection {
97+
#[cynic(flatten)]
98+
pub nodes: Vec<PullRequest>,
99+
}
100+
101+
#[derive(cynic::QueryFragment, Debug)]
102+
#[cynic(schema = "github")]
103+
pub struct PullRequest {
104+
pub title: String,
105+
pub created_at: DateTime,
106+
}
107+
108+
#[cfg(test)]
109+
mod test {
110+
use super::*;
111+
112+
#[test]
113+
fn snapshot_test_query() {
114+
// Running a snapshot test of the query building functionality as that gives us
115+
// a place to copy and paste the actual GQL we're using for running elsewhere,
116+
// and also helps ensure we don't change queries by mistake
117+
118+
let query = build_query();
119+
120+
insta::assert_snapshot!(query.query);
121+
}
122+
123+
#[test]
124+
#[ignore]
125+
fn test_running_query() {
126+
let result = run_query();
127+
if result.errors.is_some() {
128+
assert_eq!(result.errors.unwrap().len(), 0);
129+
}
130+
assert_eq!(
131+
result
132+
.data
133+
.as_ref()
134+
.unwrap()
135+
.repository
136+
.as_ref()
137+
.unwrap()
138+
.pull_requests
139+
.nodes
140+
.len(),
141+
10
142+
);
143+
insta::assert_debug_snapshot!(result.data);
144+
}
145+
}

0 commit comments

Comments
 (0)