Skip to content

Commit 9bc7f50

Browse files
committed
Revert "create Unknow variant for fragment as default behaviour"
This reverts commit 20c8e6d.
1 parent 54aa497 commit 9bc7f50

File tree

8 files changed

+163
-10
lines changed

8 files changed

+163
-10
lines changed

graphql_client_cli/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ OPTIONS:
5757
-s, --schema-path <schema_path> Path to GraphQL schema file (.json or .graphql).
5858
-o, --selected-operation <selected_operation>
5959
Name of target query. If you don't set this parameter, cli generate all queries in query file.
60+
--fragments-other-variant
61+
Generate an Unknow variant for enums generated by fragments.
62+
6063
6164
ARGS:
6265
<query_path> Path to the GraphQL query file.

graphql_client_cli/src/generate.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ pub(crate) struct CliCodegenParams {
2121
pub module_visibility: Option<String>,
2222
pub output_directory: Option<PathBuf>,
2323
pub custom_scalars_module: Option<String>,
24+
pub fragments_other_variant: bool,
2425
}
2526

2627
pub(crate) fn generate_code(params: CliCodegenParams) -> CliResult<()> {
@@ -35,6 +36,7 @@ pub(crate) fn generate_code(params: CliCodegenParams) -> CliResult<()> {
3536
schema_path,
3637
selected_operation,
3738
custom_scalars_module,
39+
fragments_other_variant,
3840
} = params;
3941

4042
let deprecation_strategy = deprecation_strategy.as_ref().and_then(|s| s.parse().ok());
@@ -48,6 +50,8 @@ pub(crate) fn generate_code(params: CliCodegenParams) -> CliResult<()> {
4850
.into(),
4951
);
5052

53+
options.set_fragments_other_variant(fragments_other_variant);
54+
5155
if let Some(selected_operation) = selected_operation {
5256
options.set_operation_name(selected_operation);
5357
}

graphql_client_cli/src/main.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ enum Cli {
7777
/// --custom-scalars-module='crate::gql::custom_scalars'
7878
#[structopt(short = "p", long = "custom-scalars-module")]
7979
custom_scalars_module: Option<String>,
80+
/// A flag indicating if the enum representing the variants of a fragment union/interface should have a "other" variant
81+
/// --fragments-other-variant
82+
#[structopt(long = "fragments-other-variant")]
83+
fragments_other_variant: bool,
8084
},
8185
}
8286

@@ -109,6 +113,7 @@ fn main() -> CliResult<()> {
109113
schema_path,
110114
selected_operation,
111115
custom_scalars_module,
116+
fragments_other_variant,
112117
} => generate::generate_code(generate::CliCodegenParams {
113118
query_path,
114119
schema_path,
@@ -120,6 +125,7 @@ fn main() -> CliResult<()> {
120125
module_visibility,
121126
output_directory,
122127
custom_scalars_module,
128+
fragments_other_variant,
123129
}),
124130
}
125131
}

graphql_client_codegen/src/codegen/selection.rs

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ fn calculate_selection<'a>(
197197
name: variant_name_str.into(),
198198
variant_type: Some(variant_struct_name_str.clone().into()),
199199
on: struct_id,
200+
is_default_variant: false,
200201
});
201202

202203
let expanded_type = ExpandedType {
@@ -247,9 +248,19 @@ fn calculate_selection<'a>(
247248
name: variant_name_str.into(),
248249
on: struct_id,
249250
variant_type: None,
251+
is_default_variant: false,
250252
});
251253
}
252254
}
255+
256+
if *options.fragments_other_variant() {
257+
context.push_variant(ExpandedVariant {
258+
name: "Unknown".into(),
259+
on: struct_id,
260+
variant_type: None,
261+
is_default_variant: true,
262+
});
263+
}
253264
}
254265
}
255266

@@ -430,6 +441,7 @@ struct ExpandedVariant<'a> {
430441
name: Cow<'a, str>,
431442
variant_type: Option<Cow<'a, str>>,
432443
on: ResponseTypeId,
444+
is_default_variant: bool,
433445
}
434446

435447
impl<'a> ExpandedVariant<'a> {
@@ -440,7 +452,14 @@ impl<'a> ExpandedVariant<'a> {
440452
quote!((#ident))
441453
});
442454

443-
quote!(#name_ident #optional_type_ident)
455+
if self.is_default_variant {
456+
quote! {
457+
#[serde(other)]
458+
#name_ident #optional_type_ident
459+
}
460+
} else {
461+
quote!(#name_ident #optional_type_ident)
462+
}
444463
}
445464
}
446465

@@ -538,14 +557,12 @@ impl<'a> ExpandedSelection<'a> {
538557
// of the variants.
539558
if fields.peek().is_none() {
540559
let item = quote! {
541-
#response_derives
542-
#[serde(tag = "__typename")]
543-
pub enum #struct_name {
544-
#(#on_variants,)*
545-
#[serde(other)]
546-
Unknown,
547-
}
548-
};
560+
#response_derives
561+
#[serde(tag = "__typename")]
562+
pub enum #struct_name {
563+
#(#on_variants),*
564+
}
565+
};
549566
items.push(item);
550567
continue;
551568
}

graphql_client_codegen/src/codegen_options.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ pub struct GraphQLClientCodegenOptions {
4343
custom_scalars_module: Option<syn::Path>,
4444
/// List of externally defined enum types. Type names must match those used in the schema exactly.
4545
extern_enums: Vec<String>,
46+
/// Flag to trigger generation of Other variant for fragments Enum
47+
fragments_other_variant: bool,
4648
}
4749

4850
impl GraphQLClientCodegenOptions {
@@ -62,6 +64,7 @@ impl GraphQLClientCodegenOptions {
6264
normalization: Normalization::None,
6365
custom_scalars_module: Default::default(),
6466
extern_enums: Default::default(),
67+
fragments_other_variant: Default::default(),
6568
}
6669
}
6770

@@ -200,4 +203,14 @@ impl GraphQLClientCodegenOptions {
200203
pub fn set_extern_enums(&mut self, enums: Vec<String>) {
201204
self.extern_enums = enums;
202205
}
206+
207+
/// Set the graphql client codegen options's fragments other variant.
208+
pub fn set_fragments_other_variant(&mut self, fragments_other_variant: bool) {
209+
self.fragments_other_variant = fragments_other_variant;
210+
}
211+
212+
/// Get a reference to the graphql client codegen options's fragments other variant.
213+
pub fn fragments_other_variant(&self) -> &bool {
214+
&self.fragments_other_variant
215+
}
203216
}

graphql_client_codegen/src/tests/mod.rs

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,9 @@ fn fragments_other_variant_should_generate_unknown_other_variant() {
4646
.expect("Parse foobars schema");
4747
let schema = Schema::from(schema);
4848

49-
let options = GraphQLClientCodegenOptions::new(CodegenMode::Cli);
49+
let mut options = GraphQLClientCodegenOptions::new(CodegenMode::Cli);
5050

51+
options.set_fragments_other_variant(true);
5152
let query = crate::query::resolve(&schema, &query).unwrap();
5253

5354
for (_id, operation) in query.operations() {
@@ -67,6 +68,45 @@ fn fragments_other_variant_should_generate_unknown_other_variant() {
6768
Ok(_) => {
6869
// Rust keywords should be escaped / renamed now
6970
assert!(generated_code.contains("# [serde (other)] Unknown"));
71+
assert!(generated_code.contains("Unknown"));
72+
}
73+
Err(e) => {
74+
panic!("Error: {}\n Generated content: {}\n", e, &generated_code);
75+
}
76+
};
77+
}
78+
}
79+
80+
#[test]
81+
fn fragments_other_variant_false_should_not_generate_unknown_other_variant() {
82+
let query_string = include_str!("foobars_query.graphql");
83+
let query = graphql_parser::parse_query(query_string).expect("Parse foobars query");
84+
let schema = graphql_parser::parse_schema(include_str!("foobars_schema.graphql"))
85+
.expect("Parse foobars schema");
86+
let schema = Schema::from(schema);
87+
88+
let options = GraphQLClientCodegenOptions::new(CodegenMode::Cli);
89+
90+
let query = crate::query::resolve(&schema, &query).unwrap();
91+
92+
for (_id, operation) in query.operations() {
93+
let generated_tokens = generated_module::GeneratedModule {
94+
query_string,
95+
schema: &schema,
96+
operation: &operation.name,
97+
resolved_query: &query,
98+
options: &options,
99+
}
100+
.to_token_stream()
101+
.expect("Generate foobars module");
102+
let generated_code = generated_tokens.to_string();
103+
104+
let r: syn::parse::Result<proc_macro2::TokenStream> = syn::parse2(generated_tokens);
105+
match r {
106+
Ok(_) => {
107+
// Rust keywords should be escaped / renamed now
108+
assert!(!generated_code.contains("# [serde (other)] Unknown"));
109+
assert!(!generated_code.contains("Unknown"));
70110
}
71111
Err(e) => {
72112
panic!("Error: {}\n Generated content: {}\n", e, &generated_code);

graphql_query_derive/src/attributes.rs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::str::FromStr;
2+
13
use graphql_client_codegen::deprecation::DeprecationStrategy;
24
use graphql_client_codegen::normalization::Normalization;
35

@@ -94,6 +96,13 @@ pub fn extract_normalization(ast: &syn::DeriveInput) -> Result<Normalization, sy
9496
.map_err(|_| syn::Error::new_spanned(ast, NORMALIZATION_ERROR))
9597
}
9698

99+
pub fn extract_fragments_other_variant(ast: &syn::DeriveInput) -> bool {
100+
extract_attr(&ast, "fragments_other_variant")
101+
.ok()
102+
.and_then(|s| FromStr::from_str(s.as_str()).ok())
103+
.unwrap_or(false)
104+
}
105+
97106
#[cfg(test)]
98107
mod test {
99108
use super::*;
@@ -151,4 +160,63 @@ mod test {
151160
Err(e) => assert_eq!(&format!("{}", e), DEPRECATION_ERROR),
152161
};
153162
}
163+
164+
#[test]
165+
fn test_fragments_other_variant_set_to_true() {
166+
let input = "
167+
#[derive(GraphQLQuery)]
168+
#[graphql(
169+
schema_path = \"x\",
170+
query_path = \"x\",
171+
fragments_other_variant = \"true\",
172+
)]
173+
struct MyQuery;
174+
";
175+
let parsed = syn::parse_str(input).unwrap();
176+
assert_eq!(extract_fragments_other_variant(&parsed), true);
177+
}
178+
179+
#[test]
180+
fn test_fragments_other_variant_set_to_false() {
181+
let input = "
182+
#[derive(GraphQLQuery)]
183+
#[graphql(
184+
schema_path = \"x\",
185+
query_path = \"x\",
186+
fragments_other_variant = \"false\",
187+
)]
188+
struct MyQuery;
189+
";
190+
let parsed = syn::parse_str(input).unwrap();
191+
assert_eq!(extract_fragments_other_variant(&parsed), false);
192+
}
193+
194+
#[test]
195+
fn test_fragments_other_variant_set_to_invalid() {
196+
let input = "
197+
#[derive(GraphQLQuery)]
198+
#[graphql(
199+
schema_path = \"x\",
200+
query_path = \"x\",
201+
fragments_other_variant = \"invalid\",
202+
)]
203+
struct MyQuery;
204+
";
205+
let parsed = syn::parse_str(input).unwrap();
206+
assert_eq!(extract_fragments_other_variant(&parsed), false);
207+
}
208+
209+
#[test]
210+
fn test_fragments_other_variant_unset() {
211+
let input = "
212+
#[derive(GraphQLQuery)]
213+
#[graphql(
214+
schema_path = \"x\",
215+
query_path = \"x\",
216+
)]
217+
struct MyQuery;
218+
";
219+
let parsed = syn::parse_str(input).unwrap();
220+
assert_eq!(extract_fragments_other_variant(&parsed), false);
221+
}
154222
}

graphql_query_derive/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,11 @@ fn build_graphql_client_derive_options(
6363
let response_derives = attributes::extract_attr(input, "response_derives").ok();
6464
let custom_scalars_module = attributes::extract_attr(input, "custom_scalars_module").ok();
6565
let extern_enums = attributes::extract_attr_list(input, "extern_enums").ok();
66+
let fragments_other_variant: bool = attributes::extract_fragments_other_variant(input);
6667

6768
let mut options = GraphQLClientCodegenOptions::new(CodegenMode::Derive);
6869
options.set_query_file(query_path);
70+
options.set_fragments_other_variant(fragments_other_variant);
6971

7072
if let Some(variables_derives) = variables_derives {
7173
options.set_variables_derives(variables_derives);

0 commit comments

Comments
 (0)