graphql-client
graphql-client copied to clipboard
Error in importing .graphql files generated in the build process
I am trying to use a .graphql file generated in the build process using build.rs instead of a static one.
However, changing lines
#[derive(GraphQLQuery)]
#[graphql(
schema_path = "src/schema.graphql",
query_path = "src/query.graphql",
)]
struct Something;
into
#[derive(GraphQLQuery)]
#[graphql(
schema_path = concat!(env!("OUT_DIR"), "/schema.graphql"),
query_path = "src/query.graphql",
)]
struct Something;
results in a following error (and subsequent errors).
error: proc-macro derive panicked
--> src/main.rs:8:10
|
8 | #[derive(GraphQLQuery)]
| ^^^^^^^^^^^^
|
= help: message: Attribute is well formatted: Error("expected literal")
(Is this a limitation of this library or a syntactic limitation of Rust?)
IMHO generating and importing .graphql files is not a rare case and it would be nice if we can have such code or some other alternative options. (If graphql-rust already have some ways to do this, sorry.)
Many thanks,
Hi there! This is indeed not supported, but this is an interesting use case. I will mark this as a feature, and let's keep this issue as the place to discuss this use case.
One question we should clarify: do build scripts run before proc macros? I m pretty sure it happens in this order but I'm not 100% sure.
@tomhoule Thank you very much!
Yes. Build scripts run before normal compilation process of .rs files including proc macros.
My build.rs is just as simple as following code (just a downloader) and this creates target/debug/build/<package>-<hash>/out/schema.graphql correctly before cargo aborts with the error reported above.
use anyhow::*;
fn main() -> std::result::Result<(), anyhow::Error> {
let url = "https://example.com/path/to/schema.graphql";
let mut resp = reqwest::get(url)?;
let out_dir = std::env::var_os("OUT_DIR").unwrap();
let schema_file_path = std::path::Path::new(&out_dir).join("schema.graphql");
let mut schema_file = std::fs::File::create(schema_file_path)?;
resp.copy_to(&mut schema_file)?;
println!("cargo:rerun-if-changed=build.rs");
Ok(())
}
Yes it seems to me like we could support this. Unfortunately I personally don't have a lot of time to work on graphql-client these days, but I would be happy to review a PR :) I'll post here if I find the time to work on this myself.
Maybe something like a special variable that we would detect in the attributes, something like:
#[derive(GraphQLQuery)]
#[graphql(
schema_path = "${OUT_DIR}/union_schema.graphql",
query_path = "${OUT_DIR}/union_query.graphql",
)]
pub struct UnionQuery;
(or something less ugly)
In Rust 1.54.0, function-like macros become able to be used in attributes like this:
#[path = concat!(env!("OUT_DIR"), "/generated.rs")]
mod generated;
So, how about syntax like this (as I showed in this issue first)?
#[derive(GraphQLQuery)]
#[graphql(
schema_path = concat!(env!("OUT_DIR"), "/union_schema.graphql"),
query_path = concat!(env!("OUT_DIR"), "/union_query.graphql"),
)]
pub struct UnionQuery;
This notation is more verbose than an idea in the above comment, but is flexible and compatible with the notation that can be used for attributes included in Rust itself. If it is good, I would like to try to implement.