Skip to content

Introduce code generation from .graphql files for making queries #52

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Jun 2, 2020

Conversation

Enrico2
Copy link
Contributor

@Enrico2 Enrico2 commented May 29, 2020

Josh and Alex want to make the CLI make some GraphQL requests.

We have a plan to use https://github.com/graphql-rust/graphql-client with its code generation features along with a schema that we'll keep up to date as a build phase.

To unblock them, this PR adds 2 example queries and tests to show how this works.

I verified this works locally by using my personal api key and removing the should_panic.

Their existing code saves the api key on the file system after authenticating.
We should therefore create a Client instance that's instantiated with the api key auth creates.

See the documentation for the library we're using and see examples here: https://github.com/graphql-rust/graphql-client/tree/master/graphql_client/tests

@Enrico2 Enrico2 force-pushed the ran/gql_codegen branch 2 times, most recently from bef8e85 to 9eb4991 Compare May 29, 2020 21:40
Copy link
Contributor

@queerviolet queerviolet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! Couple of small things.

static PROD_GQL_API_URL: &str = "https://engine-graphql.apollographql.com/api/graphql";

pub struct Client {
personal_api_key: String,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any reason not to call this api_key?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking that somewhere else in the code we're going to ask the user to use their personal api key obtained from https://engine.apollographql.com/user-settings but actually this code specifically can take any type of API key so I'll rename.

Ok(response_body.data.and_then(|data| data.me))
}

mod tests {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe these would be better as documentation tests? Then we get documentation!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like we could also mark them no_run

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good suggestion! They really are just there for documentation :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something is not working as expected with the doctests. I tried moving these over and my first hint that they're not working is that IntelliJ doesn't render them as rust code, but as simple comments. So I tried adding a compilation error in them, and everything still passes.
I went to read some docs and couldn't for the life of me figure out how to do this.
I took this example

/// First line is a short summary describing function.
///
/// The next lines present detailed documentation. Code blocks start with
/// triple backquotes and have implicit `fn main()` inside
/// and `extern crate <cratename>`. Assume we're testing `doccomments` crate:
///
/// ```
/// let result = doccomments::add(2, 3);
/// assert_eq!(res, 5);
/// ```
pub fn add(a: i32, b: i32) -> i32 {
    a + b
}

and changed the last line from result to res in the assert to make it not compile, and everything still passes. I tried putting this block in main.rs too just to make sure.

I then tried putting that add block in a different crate (something I set up locally, the minigrep project from The Book) and IT RENDERS THERE. I seriously am lost on this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow.. Figured this out. So I tried running this:

$ cargo test --doc

And got the response:

error: no library targets found in package `apollo-cli`

So, we have as main.rs but no lib.rs -- I created that file and moved all of the mod ___; from main.rs to lib.rs and NOW DOCTESTS WORK.

🤦

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking about this, I'd rather not introduce a lib.rs just yet for the sole purpose of doctests. It forces us to mark some modules as public just that main could use them. So, I think I'll keep the code as is so that tests will compile.

@Enrico2
Copy link
Contributor Author

Enrico2 commented May 31, 2020

No clue how Github is counting lines..
image

@Enrico2 Enrico2 requested a review from queerviolet May 31, 2020 21:48
@jbaxleyiii
Copy link
Contributor

@Enrico2 I have some thoughts on this that I'll leave today

@Enrico2 Enrico2 force-pushed the ran/gql_codegen branch from 6957167 to 5c39e92 Compare June 1, 2020 16:32
Copy link
Contributor

@jbaxleyiii jbaxleyiii left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You and I caught up in our call today but my biggest point of feedback is I'd like the schema to be gitignored to reduce change noise in the repo and to reduce the amount of uneeded information (i.e we only use a very small portion of the schema).

Otherwise, I'm so very excited for this as I'm sure @AlexanderMann and @jsegaran are!

@@ -0,0 +1,16 @@
{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this used instead of a build.rs script?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh sorry, I should have clarified. This is specifically for IntelliJ's graphql plugin integration. It allows for code highlighting when writing queries and some other features.

.reqwest
.post(&self.uri.to_string())
.header("Content-Type", "application/json")
.header("apollographql-client-name", "internal-apollo-cli")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to treat this as a new version of the Apollo CLI or a new product all together?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No preference, whatever you think is best..

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔 I think it would be cool to keep it the same and watch the stats roll over in Graph Manager!

.send()?;

let response_body: Response<Q::ResponseData> = res.json()?;
Ok(response_body)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing this doesn't do is handle GraphQL errors (i.e. { errors }). What is the type of ResponseData here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

response_body is of type:

pub struct Response<Data> {
    /// The absent, partial or complete response data.
    pub data: Option<Data>,
    /// The top-level errors returned by the server.
    pub errors: Option<Vec<Error>>,
}

ResponseData is codegen'd based on the query, in our case it's a struct with a single service field.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are queries are here for example purposes, we should definitely error check once we have real queries (and then we can delete these)

@Enrico2
Copy link
Contributor Author

Enrico2 commented Jun 1, 2020

@jbaxleyiii

You and I caught up in our call today but my biggest point of feedback is I'd like the schema to be gitignored to reduce change noise in the repo and to reduce the amount of uneeded information (i.e we only use a very small portion of the schema).

Yes, although for this PR to unblock @AlexanderMann and @jsegaran, let's check it in so that they're not blocked on the build script we discussed, once I do that one, I'll remove the schema from the repo and .gitignore it.

@Enrico2 Enrico2 requested a review from jbaxleyiii June 1, 2020 20:32
@Enrico2
Copy link
Contributor Author

Enrico2 commented Jun 2, 2020

Since this is not approved yet, I might actually change it a bit if apollographql/rover#55 lands first.

@Enrico2 Enrico2 force-pushed the ran/gql_codegen branch from 5b61227 to 6394e5e Compare June 2, 2020 19:16
@Enrico2 Enrico2 force-pushed the ran/gql_codegen branch from 28775c7 to ceaf0b7 Compare June 2, 2020 22:49
@Enrico2
Copy link
Contributor Author

Enrico2 commented Jun 2, 2020

Much better :)
image

@Enrico2 Enrico2 merged commit 282eb11 into master Jun 2, 2020
@Enrico2 Enrico2 deleted the ran/gql_codegen branch June 2, 2020 23:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants