@@ -73,7 +73,7 @@ let objectData(ctx: PlanningContext, parentDef: ObjectDef, field: Field, include
73
73
| None ->
74
74
raise ( GraphQLException ( sprintf " No field '%s ' was defined in object definition '%s '" field.Name parentDef.Name))
75
75
76
- let abstractionData ( ctx : PlanningContext , parentDef : AbstractDef , field : Field , typeCondition : string option , includer : Includer ) : Map < string , PlanningData > =
76
+ let rec abstractionData ( ctx : PlanningContext ) ( parentDef : AbstractDef ) ( field : Field ) typeCondition includer : Map < string , PlanningData > =
77
77
let objDefs = ctx.Schema.GetPossibleTypes parentDef
78
78
match typeCondition with
79
79
| None ->
@@ -106,8 +106,12 @@ let abstractionData(ctx: PlanningContext, parentDef: AbstractDef, field: Field,
106
106
Map.ofList [ objDef.Name, data ]
107
107
| None -> Map.empty
108
108
| None ->
109
- let pname = parentDef :?> NamedDef
110
- raise ( GraphQLException ( sprintf " An abstract type '%s ' has no relation with a type named '%s '" pname.Name typeName))
109
+ match ctx.Schema.TryFindType typeName with
110
+ | Some ( Abstract abstractDef) ->
111
+ abstractionData ctx abstractDef field None includer
112
+ | _ ->
113
+ let pname = parentDef :?> NamedDef
114
+ raise ( GraphQLException ( sprintf " There is no object type named '%s ' that is a possible type of '%s '" typeName pname.Name))
111
115
112
116
let private directiveIncluder ( directive : Directive ) : Includer =
113
117
fun variables ->
@@ -121,17 +125,15 @@ let private directiveIncluder (directive: Directive) : Includer =
121
125
122
126
let incl : Includer = fun _ -> true
123
127
let excl : Includer = fun _ -> false
124
- let private getIncluder ( directives : Directive list ) : Includer =
128
+ let private getIncluder ( directives : Directive list ) topIncluder : Includer =
125
129
directives
126
130
|> List.fold ( fun acc directive ->
127
131
match directive.Name with
128
132
| " skip" ->
129
- let excluder = directiveIncluder directive >> not
130
- fun vars -> acc vars && excluder vars
133
+ fun vars -> acc vars && not ( directiveIncluder directive vars)
131
134
| " include" ->
132
- let includer = directiveIncluder directive
133
- fun vars -> acc vars && includer vars
134
- | _ -> acc) incl
135
+ fun vars -> acc vars && ( directiveIncluder directive vars)
136
+ | _ -> acc) topIncluder
135
137
136
138
let private doesFragmentTypeApply ( schema : ISchema ) fragment ( objectType : ObjectDef ) =
137
139
match fragment.TypeCondition with
@@ -142,7 +144,7 @@ let private doesFragmentTypeApply (schema: ISchema) fragment (objectType: Object
142
144
| Some conditionalType when conditionalType.Name = objectType.Name -> true
143
145
| Some ( Abstract conditionalType) -> schema.IsPossibleType conditionalType objectType
144
146
| _ -> false
145
-
147
+
146
148
let rec private plan ( ctx : PlanningContext ) ( data : PlanningData ) ( typedef : TypeDef ) : ExecutionPlanInfo =
147
149
match typedef with
148
150
| Leaf leafDef -> planLeaf ctx data leafDef
@@ -157,7 +159,8 @@ and private planSelection (ctx: PlanningContext) (data: PlanningData) (selection
157
159
selectionSet
158
160
|> List.fold( fun ( fields : ExecutionPlanInfo list ) selection ->
159
161
//FIXME: includer is not passed along from top level fragments (both inline and spreads)
160
- let includer = getIncluder selection.Directives
162
+ let includer = getIncluder selection.Directives data.Include
163
+ let innerData = { data with Include = includer }
161
164
match selection with
162
165
| Field field ->
163
166
let identifier = field.AliasOrName
@@ -176,13 +179,13 @@ and private planSelection (ctx: PlanningContext) (data: PlanningData) (selection
176
179
match ctx.Document.Definitions |> List.tryFind ( function FragmentDefinition f -> f.Name.Value = spreadName | _ -> false ) with
177
180
| Some ( FragmentDefinition fragment) when doesFragmentTypeApply ctx.Schema fragment parentDef ->
178
181
// retrieve fragment data just as it was normal selection set
179
- let ( SelectFields ( _ , fragmentFields )) = planSelection ctx data fragment.SelectionSet visitedFragments
182
+ let ( SelectFields ( _ , fragmentFields )) = planSelection ctx innerData fragment.SelectionSet visitedFragments
180
183
// filter out already existing fields
181
184
List.mergeBy ( fun field -> field.Data.Identifier) fields fragmentFields
182
185
| _ -> fields
183
186
| InlineFragment fragment when doesFragmentTypeApply ctx.Schema fragment parentDef ->
184
187
// retrieve fragment data just as it was normal selection set
185
- let ( SelectFields ( _ , fragmentFields )) = planSelection ctx data fragment.SelectionSet visitedFragments
188
+ let ( SelectFields ( _ , fragmentFields )) = planSelection ctx innerData fragment.SelectionSet visitedFragments
186
189
// filter out already existing fields
187
190
List.mergeBy ( fun field -> field.Data.Identifier) fields fragmentFields
188
191
| _ -> fields
@@ -200,10 +203,11 @@ and private planAbstraction (ctx:PlanningContext) (data: PlanningData) (selectio
200
203
let plannedTypeFields =
201
204
selectionSet
202
205
|> List.fold( fun ( fields : Map < string , ExecutionPlanInfo list >) selection ->
203
- let includer = getIncluder selection.Directives
206
+ let includer = getIncluder selection.Directives data.Include
207
+ let innerData = { data with Include = includer }
204
208
match selection with
205
209
| Field field ->
206
- abstractionData( ctx, parentDef, field, typeCondition, includer)
210
+ abstractionData ctx parentDef field typeCondition includer
207
211
|> Map.map ( fun typeName data -> [ plan ctx data data.Definition.Type ])
208
212
|> Map.merge ( fun typeName oldVal newVal -> oldVal @ newVal) fields
209
213
| FragmentSpread spread ->
@@ -215,13 +219,13 @@ and private planAbstraction (ctx:PlanningContext) (data: PlanningData) (selectio
215
219
match ctx.Document.Definitions |> List.tryFind ( function FragmentDefinition f -> f.Name.Value = spreadName | _ -> false ) with
216
220
| Some ( FragmentDefinition fragment) ->
217
221
// retrieve fragment data just as it was normal selection set
218
- let ( ResolveAbstraction ( _ , fragmentFields )) = planAbstraction ctx data fragment.SelectionSet visitedFragments fragment.TypeCondition
222
+ let ( ResolveAbstraction ( _ , fragmentFields )) = planAbstraction ctx innerData fragment.SelectionSet visitedFragments fragment.TypeCondition
219
223
// filter out already existing fields
220
224
Map.merge ( fun typeName oldVal newVal -> oldVal @ newVal) fields fragmentFields
221
225
| _ -> fields
222
226
| InlineFragment fragment ->
223
227
// retrieve fragment data just as it was normal selection set
224
- let ( ResolveAbstraction ( _ , fragmentFields )) = planAbstraction ctx data fragment.SelectionSet visitedFragments fragment.TypeCondition
228
+ let ( ResolveAbstraction ( _ , fragmentFields )) = planAbstraction ctx innerData fragment.SelectionSet visitedFragments fragment.TypeCondition
225
229
// filter out already existing fields
226
230
Map.merge ( fun typeName oldVal newVal -> oldVal @ newVal) fields fragmentFields
227
231
| _ -> fields
0 commit comments