diff --git a/graphql_client_cli/src/graphql/introspection_query_with_isOneOf_specifiedByUrl.graphql b/graphql_client_cli/src/graphql/introspection_query_with_isOneOf_specifiedByUrl.graphql new file mode 100644 index 000000000..e78d209f9 --- /dev/null +++ b/graphql_client_cli/src/graphql/introspection_query_with_isOneOf_specifiedByUrl.graphql @@ -0,0 +1,101 @@ +query IntrospectionQueryWithIsOneOfSpecifiedByURL { + __schema { + queryType { + name + } + mutationType { + name + } + subscriptionType { + name + } + types { + ...FullTypeWithisOneOfSpecifiedByURL + } + directives { + name + description + locations + args { + ...InputValue + } + } + } +} + +fragment FullTypeWithisOneOfSpecifiedByURL on __Type { + kind + name + description + isOneOf + specifiedByURL + fields(includeDeprecated: true) { + name + description + args { + ...InputValue + } + type { + ...TypeRef + } + isDeprecated + deprecationReason + } + inputFields { + ...InputValue + } + interfaces { + ...TypeRef + } + enumValues(includeDeprecated: true) { + name + description + isDeprecated + deprecationReason + } + possibleTypes { + ...TypeRef + } +} + +fragment InputValue on __InputValue { + name + description + type { + ...TypeRef + } + defaultValue +} + +fragment TypeRef on __Type { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + } + } + } + } + } + } + } +} diff --git a/graphql_client_cli/src/graphql/introspection_query_with_is_one_of.graphql b/graphql_client_cli/src/graphql/introspection_query_with_is_one_of.graphql new file mode 100644 index 000000000..20faed646 --- /dev/null +++ b/graphql_client_cli/src/graphql/introspection_query_with_is_one_of.graphql @@ -0,0 +1,100 @@ +query IntrospectionQueryWithIsOneOf { + __schema { + queryType { + name + } + mutationType { + name + } + subscriptionType { + name + } + types { + ...FullTypeWithisOneOf + } + directives { + name + description + locations + args { + ...InputValue + } + } + } +} + +fragment FullTypeWithisOneOf on __Type { + kind + name + description + isOneOf + fields(includeDeprecated: true) { + name + description + args { + ...InputValue + } + type { + ...TypeRef + } + isDeprecated + deprecationReason + } + inputFields { + ...InputValue + } + interfaces { + ...TypeRef + } + enumValues(includeDeprecated: true) { + name + description + isDeprecated + deprecationReason + } + possibleTypes { + ...TypeRef + } +} + +fragment InputValue on __InputValue { + name + description + type { + ...TypeRef + } + defaultValue +} + +fragment TypeRef on __Type { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + } + } + } + } + } + } + } +} diff --git a/graphql_client_cli/src/graphql/introspection_query_with_specified_by.graphql b/graphql_client_cli/src/graphql/introspection_query_with_specified_by.graphql new file mode 100644 index 000000000..7c2db3b93 --- /dev/null +++ b/graphql_client_cli/src/graphql/introspection_query_with_specified_by.graphql @@ -0,0 +1,100 @@ +query IntrospectionQueryWithSpecifiedBy { + __schema { + queryType { + name + } + mutationType { + name + } + subscriptionType { + name + } + types { + ...FullTypeWithSpecifiedBy + } + directives { + name + description + locations + args { + ...InputValue + } + } + } +} + +fragment FullTypeWithSpecifiedBy on __Type { + kind + name + description + specifiedByURL + fields(includeDeprecated: true) { + name + description + args { + ...InputValue + } + type { + ...TypeRef + } + isDeprecated + deprecationReason + } + inputFields { + ...InputValue + } + interfaces { + ...TypeRef + } + enumValues(includeDeprecated: true) { + name + description + isDeprecated + deprecationReason + } + possibleTypes { + ...TypeRef + } +} + +fragment InputValue on __InputValue { + name + description + type { + ...TypeRef + } + defaultValue +} + +fragment TypeRef on __Type { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + } + } + } + } + } + } + } +} diff --git a/graphql_client_cli/src/graphql/introspection_schema.graphql b/graphql_client_cli/src/graphql/introspection_schema.graphql index 29f5587bf..c82bded4d 100644 --- a/graphql_client_cli/src/graphql/introspection_schema.graphql +++ b/graphql_client_cli/src/graphql/introspection_schema.graphql @@ -36,6 +36,14 @@ type __Type { # NON_NULL and LIST only ofType: __Type + + # may be non-null for custom SCALAR, otherwise null. + # https://spec.graphql.org/draft/#sec-Scalars.Custom-Scalars + specifiedByURL: String + specifiedBy: String + + # should be non-null for INPUT_OBJECT only + isOneOf: Boolean } type __Field { diff --git a/graphql_client_cli/src/introspection_queries.rs b/graphql_client_cli/src/introspection_queries.rs new file mode 100644 index 000000000..6b4b94dcf --- /dev/null +++ b/graphql_client_cli/src/introspection_queries.rs @@ -0,0 +1,41 @@ +use graphql_client::GraphQLQuery; + +#[derive(GraphQLQuery)] +#[graphql( + schema_path = "src/graphql/introspection_schema.graphql", + query_path = "src/graphql/introspection_query.graphql", + response_derives = "Serialize", + variable_derives = "Deserialize" +)] +#[allow(dead_code)] +pub struct IntrospectionQuery; + +#[derive(GraphQLQuery)] +#[graphql( + schema_path = "src/graphql/introspection_schema.graphql", + query_path = "src/graphql/introspection_query_with_is_one_of.graphql", + response_derives = "Serialize", + variable_derives = "Deserialize" +)] +#[allow(dead_code)] +pub struct IntrospectionQueryWithIsOneOf; + +#[derive(GraphQLQuery)] +#[graphql( + schema_path = "src/graphql/introspection_schema.graphql", + query_path = "src/graphql/introspection_query_with_specified_by.graphql", + response_derives = "Serialize", + variable_derives = "Deserialize" +)] +#[allow(dead_code)] +pub struct IntrospectionQueryWithSpecifiedBy; + +#[derive(GraphQLQuery)] +#[graphql( + schema_path = "src/graphql/introspection_schema.graphql", + query_path = "src/graphql/introspection_query_with_isOneOf_specifiedByUrl.graphql", + response_derives = "Serialize", + variable_derives = "Deserialize" +)] +#[allow(dead_code)] +pub struct IntrospectionQueryWithIsOneOfSpecifiedByURL; diff --git a/graphql_client_cli/src/introspect_schema.rs b/graphql_client_cli/src/introspection_schema.rs similarity index 82% rename from graphql_client_cli/src/introspect_schema.rs rename to graphql_client_cli/src/introspection_schema.rs index 62e62fbb5..137750505 100644 --- a/graphql_client_cli/src/introspect_schema.rs +++ b/graphql_client_cli/src/introspection_schema.rs @@ -1,19 +1,13 @@ use crate::error::Error; use crate::CliResult; -use graphql_client::GraphQLQuery; use reqwest::header::{HeaderMap, HeaderValue, ACCEPT, CONTENT_TYPE}; use std::path::PathBuf; use std::str::FromStr; -#[derive(GraphQLQuery)] -#[graphql( - schema_path = "src/graphql/introspection_schema.graphql", - query_path = "src/graphql/introspection_query.graphql", - response_derives = "Serialize", - variable_derives = "Deserialize" -)] -#[allow(dead_code)] -struct IntrospectionQuery; +use crate::introspection_queries::{ + introspection_query, introspection_query_with_is_one_of, + introspection_query_with_is_one_of_specified_by_url, introspection_query_with_specified_by, +}; pub fn introspect_schema( location: &str, @@ -21,6 +15,8 @@ pub fn introspect_schema( authorization: Option, headers: Vec
, no_ssl: bool, + is_one_of: bool, + specify_by_url: bool, ) -> CliResult<()> { use std::io::Write; @@ -29,12 +25,36 @@ pub fn introspect_schema( None => Box::new(std::io::stdout()), }; - let request_body: graphql_client::QueryBody<()> = graphql_client::QueryBody { + let mut request_body: graphql_client::QueryBody<()> = graphql_client::QueryBody { variables: (), query: introspection_query::QUERY, operation_name: introspection_query::OPERATION_NAME, }; + if is_one_of { + request_body = graphql_client::QueryBody { + variables: (), + query: introspection_query_with_is_one_of::QUERY, + operation_name: introspection_query_with_is_one_of::OPERATION_NAME, + } + } + + if specify_by_url { + request_body = graphql_client::QueryBody { + variables: (), + query: introspection_query_with_specified_by::QUERY, + operation_name: introspection_query_with_specified_by::OPERATION_NAME, + } + } + + if is_one_of && specify_by_url { + request_body = graphql_client::QueryBody { + variables: (), + query: introspection_query_with_is_one_of_specified_by_url::QUERY, + operation_name: introspection_query_with_is_one_of_specified_by_url::OPERATION_NAME, + } + } + let client = reqwest::blocking::Client::builder() .danger_accept_invalid_certs(no_ssl) .build()?; diff --git a/graphql_client_cli/src/main.rs b/graphql_client_cli/src/main.rs index 5fd1bcb1e..793671202 100644 --- a/graphql_client_cli/src/main.rs +++ b/graphql_client_cli/src/main.rs @@ -1,6 +1,7 @@ mod error; mod generate; -mod introspect_schema; +mod introspection_queries; +mod introspection_schema; use clap::Parser; use env_logger::fmt::{Color, Style, StyledValue}; @@ -29,11 +30,21 @@ enum Cli { /// Specify custom headers. /// --header 'X-Name: Value' #[clap(long = "header")] - headers: Vec, + headers: Vec, /// Disable ssl verification. /// Default value is false. #[clap(long = "no-ssl")] no_ssl: bool, + /// Introspection Option: is-one-of will enable the @oneOf directive in the introspection query. + /// This is an proposed feature and is not compatible with many GraphQL servers. + /// Default value is false. + #[clap(long = "is-one-of")] + is_one_of: bool, + /// Introspection Option: specify-by-url will enable the @specifiedByURL directive in the introspection query. + /// This is an proposed feature and is not compatible with many GraphQL servers. + /// Default value is false. + #[clap(long = "specify-by-url")] + specify_by_url: bool, }, #[clap(name = "generate")] Generate { @@ -93,12 +104,16 @@ fn main() -> CliResult<()> { authorization, headers, no_ssl, - } => introspect_schema::introspect_schema( + is_one_of, + specify_by_url, + } => introspection_schema::introspect_schema( &schema_location, output, authorization, headers, no_ssl, + is_one_of, + specify_by_url, ), Generate { variables_derives, diff --git a/graphql_client_codegen/src/codegen/selection.rs b/graphql_client_codegen/src/codegen/selection.rs index 5dd72e287..2ad054d95 100644 --- a/graphql_client_codegen/src/codegen/selection.rs +++ b/graphql_client_codegen/src/codegen/selection.rs @@ -391,7 +391,7 @@ struct ExpandedField<'a> { boxed: bool, } -impl<'a> ExpandedField<'a> { +impl ExpandedField<'_> { fn render(&self, options: &GraphQLClientCodegenOptions) -> Option { let ident = Ident::new(&self.rust_name, Span::call_site()); let qualified_type = decorate_type( @@ -457,7 +457,7 @@ struct ExpandedVariant<'a> { is_default_variant: bool, } -impl<'a> ExpandedVariant<'a> { +impl ExpandedVariant<'_> { fn render(&self) -> TokenStream { let name_ident = Ident::new(&self.name, Span::call_site()); let optional_type_ident = self.variant_type.as_ref().map(|variant_type| { diff --git a/graphql_client_codegen/src/generated_module.rs b/graphql_client_codegen/src/generated_module.rs index 4148d7e50..b225d001a 100644 --- a/graphql_client_codegen/src/generated_module.rs +++ b/graphql_client_codegen/src/generated_module.rs @@ -32,7 +32,7 @@ pub(crate) struct GeneratedModule<'a> { pub options: &'a crate::GraphQLClientCodegenOptions, } -impl<'a> GeneratedModule<'a> { +impl GeneratedModule<'_> { /// Generate the items for the variables and the response that will go inside the module. fn build_impls(&self) -> Result { Ok(crate::codegen::response_for_query(