@@ -13,17 +13,19 @@ use crate::{
13
13
schema:: { Schema , TypeId } ,
14
14
type_qualifiers:: GraphqlTypeQualifier ,
15
15
GraphQLClientCodegenOptions ,
16
+ GeneralError ,
16
17
} ;
17
18
use heck:: * ;
18
19
use proc_macro2:: { Ident , Span , TokenStream } ;
19
20
use quote:: { quote, ToTokens } ;
20
21
use std:: borrow:: Cow ;
22
+ use syn:: Path ;
21
23
22
24
pub ( crate ) fn render_response_data_fields < ' a > (
23
25
operation_id : OperationId ,
24
26
options : & ' a GraphQLClientCodegenOptions ,
25
27
query : & ' a BoundQuery < ' a > ,
26
- ) -> ExpandedSelection < ' a > {
28
+ ) -> Result < ExpandedSelection < ' a > , GeneralError > {
27
29
let operation = query. query . get_operation ( operation_id) ;
28
30
let mut expanded_selection = ExpandedSelection {
29
31
query,
@@ -38,6 +40,18 @@ pub(crate) fn render_response_data_fields<'a>(
38
40
name : Cow :: Borrowed ( "ResponseData" ) ,
39
41
} ) ;
40
42
43
+ if let Some ( custom_response_type) = options. custom_response_type ( ) {
44
+ if operation. selection_set . len ( ) == 1 {
45
+ let selection_id = operation. selection_set [ 0 ] ;
46
+ let selection_field = query. query . get_selection ( selection_id) . as_selected_field ( )
47
+ . ok_or_else ( || GeneralError ( format ! ( "Custom response type {custom_response_type} will only work on fields" ) ) ) ?;
48
+ calculate_custom_response_type_selection ( & mut expanded_selection, response_data_type_id, custom_response_type, selection_id, selection_field) ;
49
+ return Ok ( expanded_selection) ;
50
+ } else {
51
+ return Err ( GeneralError ( format ! ( "Custom response type {custom_response_type} requires single selection field" ) ) ) ;
52
+ }
53
+ }
54
+
41
55
calculate_selection (
42
56
& mut expanded_selection,
43
57
& operation. selection_set ,
@@ -46,7 +60,38 @@ pub(crate) fn render_response_data_fields<'a>(
46
60
options,
47
61
) ;
48
62
49
- expanded_selection
63
+ Ok ( expanded_selection)
64
+ }
65
+
66
+ fn calculate_custom_response_type_selection < ' a > (
67
+ context : & mut ExpandedSelection < ' a > ,
68
+ struct_id : ResponseTypeId ,
69
+ custom_response_type : & ' a String ,
70
+ selection_id : SelectionId ,
71
+ field : & ' a SelectedField )
72
+ {
73
+ let ( graphql_name, rust_name) = context. field_name ( field) ;
74
+ let struct_name_string = full_path_prefix ( selection_id, context. query ) ;
75
+ let field = context. query . schema . get_field ( field. field_id ) ;
76
+ context. push_field ( ExpandedField {
77
+ struct_id,
78
+ graphql_name : Some ( graphql_name) ,
79
+ rust_name,
80
+ field_type_qualifiers : & field. r#type . qualifiers ,
81
+ field_type : struct_name_string. clone ( ) . into ( ) ,
82
+ flatten : false ,
83
+ boxed : false ,
84
+ deprecation : field. deprecation ( ) ,
85
+ } ) ;
86
+
87
+ let struct_id = context. push_type ( ExpandedType {
88
+ name : struct_name_string. into ( ) ,
89
+ } ) ;
90
+ context. push_type_alias ( TypeAlias {
91
+ name : custom_response_type. as_str ( ) ,
92
+ struct_id,
93
+ boxed : false ,
94
+ } ) ;
50
95
}
51
96
52
97
pub ( super ) fn render_fragment < ' a > (
@@ -557,14 +602,14 @@ impl<'a> ExpandedSelection<'a> {
557
602
558
603
// If the type is aliased, stop here.
559
604
if let Some ( alias) = self . aliases . iter ( ) . find ( |alias| alias. struct_id == type_id) {
560
- let fragment_name = Ident :: new ( alias. name , Span :: call_site ( ) ) ;
561
- let fragment_name = if alias. boxed {
562
- quote ! ( Box <#fragment_name >)
605
+ let type_name = syn :: parse_str :: < Path > ( alias. name ) . unwrap ( ) ;
606
+ let type_name = if alias. boxed {
607
+ quote ! ( Box <#type_name >)
563
608
} else {
564
- quote ! ( #fragment_name )
609
+ quote ! ( #type_name )
565
610
} ;
566
611
let item = quote ! {
567
- pub type #struct_name = #fragment_name ;
612
+ pub type #struct_name = #type_name ;
568
613
} ;
569
614
items. push ( item) ;
570
615
continue ;
0 commit comments