@@ -111,6 +111,7 @@ let rec internal compileByType
111111
112112 let parametersMap =
113113 let typeMismatchParameters = HashSet ()
114+ let skippableMismatchParameters = HashSet ()
114115 let nullableMismatchParameters = HashSet ()
115116 let missingParameters = HashSet ()
116117
@@ -123,22 +124,32 @@ let rec internal compileByType
123124 |> Array.tryFind ( fun field -> field.Name = param.Name)
124125 with
125126 | Some field ->
127+ let isParameterSkippable = ReflectionHelper.isParameterSkippable param
126128 match field.TypeDef with
129+ | Nullable _ when field.IsSkippable <> isParameterSkippable ->
130+ skippableMismatchParameters.Add param.Name |> ignore
127131 | Nullable _ when
128- ReflectionHelper.isPrameterMandatory param
132+ not ( isParameterSkippable)
133+ && ReflectionHelper.isPrameterMandatory param
129134 && field.DefaultValue.IsNone
130135 ->
131136 nullableMismatchParameters.Add param.Name |> ignore
132137 | inputDef ->
133- let inputType , paramType = inputDef.Type, param.ParameterType
138+ let inputType , paramType =
139+ if isParameterSkippable then
140+ inputDef.Type, param.ParameterType.GenericTypeArguments.[ 0 ]
141+ else
142+ inputDef.Type, param.ParameterType
134143 if ReflectionHelper.isAssignableWithUnwrap inputType paramType then
135- allParameters.Add ( struct ( ValueSome field, param))
136- |> ignore
144+ allParameters.Add ( struct ( ValueSome field, param)) |> ignore
137145 else
138146 // TODO: Consider improving by specifying type mismatches
139147 typeMismatchParameters.Add param.Name |> ignore
140148 | None ->
141- if ReflectionHelper.isParameterOptional param then
149+ if
150+ ReflectionHelper.isParameterSkippable param
151+ || ReflectionHelper.isParameterOptional param
152+ then
142153 allParameters.Add <| struct ( ValueNone, param) |> ignore
143154 else
144155 missingParameters.Add param.Name |> ignore
@@ -157,6 +168,11 @@ let rec internal compileByType
157168 let ``params`` = String.Join ( " ', '" , nullableMismatchParameters)
158169 $" Input object %s {objDef.Name} refers to type '%O {objtype}', but constructor parameters for optional GraphQL fields '%s {``params``}' are not optional"
159170 InvalidInputTypeException ( message, nullableMismatchParameters.ToImmutableHashSet ())
171+ if skippableMismatchParameters.Any () then
172+ let message =
173+ let ``params`` = String.Join ( " ', '" , skippableMismatchParameters)
174+ $" Input object %s {objDef.Name} refers to type '%O {objtype}', but skippable '%s {``params``}' GraphQL fields and constructor parameters do not match"
175+ InvalidInputTypeException ( message, skippableMismatchParameters.ToImmutableHashSet ())
160176 if typeMismatchParameters.Any () then
161177 let message =
162178 let ``params`` = String.Join ( " ', '" , typeMismatchParameters)
@@ -204,15 +220,26 @@ let rec internal compileByType
204220 parametersMap
205221 |> Seq.map ( fun struct ( field , param ) ->
206222 match field with
207- | ValueSome field ->
208- match Map.tryFind field.Name props with
209- | None ->
210- Ok
211- <| wrapOptionalNone param.ParameterType field.TypeDef.Type
212- | Some prop ->
213- field.ExecuteInput prop variables
214- |> Result.map ( normalizeOptional param.ParameterType)
215- |> attachErrorExtensionsIfScalar inputSource inputObjectPath originalInputDef field
223+ | ValueSome field -> result {
224+ match Map.tryFind field.Name props with
225+ | None when field.IsSkippable -> return Activator.CreateInstance param.ParameterType
226+ | None -> return wrapOptionalNone param.ParameterType field.TypeDef.Type
227+ | Some prop ->
228+ let! value =
229+ field.ExecuteInput prop variables
230+ |> attachErrorExtensionsIfScalar inputSource inputObjectPath originalInputDef field
231+ if field.IsSkippable then
232+ let innerType = param.ParameterType.GenericTypeArguments[ 0 ]
233+ if not ( ReflectionHelper.isTypeOptional innerType) &&
234+ ( value = null || ( innerType.IsValueType && value = Activator.CreateInstance innerType))
235+ then
236+ return Activator.CreateInstance param.ParameterType
237+ else
238+ let ``include`` , _ = ReflectionHelper.ofSkippable param.ParameterType
239+ return normalizeOptional innerType value |> `` include ``
240+ else
241+ return normalizeOptional param.ParameterType value
242+ }
216243 | ValueNone -> Ok <| wrapOptionalNone param.ParameterType typeof< obj>)
217244 |> Seq.toList
218245
@@ -236,12 +263,25 @@ let rec internal compileByType
236263 parametersMap
237264 |> Seq.map ( fun struct ( field , param ) -> result {
238265 match field with
266+ | ValueSome field when field.IsSkippable && not ( objectFields.ContainsKey field.Name) ->
267+ return ( Activator.CreateInstance param.ParameterType)
239268 | ValueSome field ->
240269 let! value =
241270 field.ExecuteInput ( VariableName field.Name) objectFields
242271 // TODO: Take into account variable name
243272 |> attachErrorExtensionsIfScalar inputSource inputObjectPath originalInputDef field
244- return normalizeOptional param.ParameterType value
273+ if field.IsSkippable then
274+ let innerType = param.ParameterType.GenericTypeArguments[ 0 ]
275+ if not ( ReflectionHelper.isTypeOptional innerType) &&
276+ ( value = null || ( innerType.IsValueType && value = Activator.CreateInstance innerType))
277+ then
278+ return Activator.CreateInstance param.ParameterType
279+ else
280+ let normalizedValue = normalizeOptional innerType value
281+ let ``include`` , _ = ReflectionHelper.ofSkippable param.ParameterType
282+ return `` include `` normalizedValue
283+ else
284+ return normalizeOptional param.ParameterType value
245285 | ValueNone -> return wrapOptionalNone param.ParameterType typeof< obj>
246286 })
247287 |> Seq.toList
@@ -506,6 +546,7 @@ and private coerceVariableInputObject inputObjectPath (originalObjDef, objDef) (
506546 KeyValuePair ( field.Name, value)
507547 match input.TryGetProperty field.Name with
508548 | true , value -> coerce value |> ValueSome
549+ | false , _ when field.IsSkippable -> ValueNone
509550 | false , _ ->
510551 match field.DefaultValue with
511552 | Some value -> KeyValuePair ( field.Name, Ok value)
0 commit comments