@@ -13,17 +13,19 @@ use crate::{
1313 schema:: { Schema , TypeId } ,
1414 type_qualifiers:: GraphqlTypeQualifier ,
1515 GraphQLClientCodegenOptions ,
16+ GeneralError ,
1617} ;
1718use heck:: * ;
1819use proc_macro2:: { Ident , Span , TokenStream } ;
1920use quote:: { quote, ToTokens } ;
2021use std:: borrow:: Cow ;
22+ use syn:: Path ;
2123
2224pub ( crate ) fn render_response_data_fields < ' a > (
2325 operation_id : OperationId ,
2426 options : & ' a GraphQLClientCodegenOptions ,
2527 query : & ' a BoundQuery < ' a > ,
26- ) -> ExpandedSelection < ' a > {
28+ ) -> Result < ExpandedSelection < ' a > , GeneralError > {
2729 let operation = query. query . get_operation ( operation_id) ;
2830 let mut expanded_selection = ExpandedSelection {
2931 query,
@@ -38,6 +40,18 @@ pub(crate) fn render_response_data_fields<'a>(
3840 name : Cow :: Borrowed ( "ResponseData" ) ,
3941 } ) ;
4042
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+
4155 calculate_selection (
4256 & mut expanded_selection,
4357 & operation. selection_set ,
@@ -46,7 +60,38 @@ pub(crate) fn render_response_data_fields<'a>(
4660 options,
4761 ) ;
4862
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+ } ) ;
5095}
5196
5297pub ( super ) fn render_fragment < ' a > (
@@ -557,14 +602,14 @@ impl<'a> ExpandedSelection<'a> {
557602
558603 // If the type is aliased, stop here.
559604 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 >)
563608 } else {
564- quote ! ( #fragment_name )
609+ quote ! ( #type_name )
565610 } ;
566611 let item = quote ! {
567- pub type #struct_name = #fragment_name ;
612+ pub type #struct_name = #type_name ;
568613 } ;
569614 items. push ( item) ;
570615 continue ;
0 commit comments