Skip to content

Commit

Permalink
PR fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
VectorTetra committed Feb 4, 2025
1 parent 8c5a23c commit 0bd5eda
Show file tree
Hide file tree
Showing 6 changed files with 28 additions and 15 deletions.
6 changes: 4 additions & 2 deletions src/FSharp.Data.GraphQL.Server/ErrorTypes.fs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ namespace FSharp.Data.GraphQL
open System
open System.Collections.Generic
open FsToolkit.ErrorHandling
open FSharp.Data.GraphQL.Errors
open FSharp.Data.GraphQL.Types


type InputSource =
| Variable of VarDef : VarDef
| Argument of ArgDef : InputFieldDef
Expand Down Expand Up @@ -38,7 +40,7 @@ type internal CoercionError = {
yield KeyValuePair (CustomErrorFields.Kind, this.ErrorKind |> box)
match this.Path with
| [] -> ()
| path -> yield KeyValuePair (CustomErrorFields.Path, path |> List.rev |> box)
| path -> yield KeyValuePair (CustomErrorFields.Path, normalizedPathToObj(path))

match this.InputSource with
| Variable varDef ->
Expand Down Expand Up @@ -87,7 +89,7 @@ type internal CoercionErrorWrapper = {
yield KeyValuePair (CustomErrorFields.Kind, this.ErrorKind |> box)
match this.Path with
| [] -> ()
| path -> yield KeyValuePair (CustomErrorFields.Path, path |> List.rev |> box)
| path -> yield KeyValuePair (CustomErrorFields.Path, normalizedPathToObj(path))

match this.InputSource with
| Variable varDef ->
Expand Down
7 changes: 7 additions & 0 deletions src/FSharp.Data.GraphQL.Server/ErrorsProcessing.fs
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,10 @@ let splitSeqErrorsList (items: Result<'t, IGQLError list> list) =
else
let values = items |> getSeqValuesList
Ok values

let internal normalizedPath(fieldPath : FieldPath) =
fieldPath |> List.rev

let internal normalizedPathToObj(fieldPath : FieldPath) =
fieldPath |> List.rev |> box

10 changes: 5 additions & 5 deletions src/FSharp.Data.GraphQL.Server/Execution.fs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ let private createFieldContext objdef argDefs ctx (info: ExecutionInfo) (path :
Schema = ctx.Schema
Args = args
Variables = ctx.Variables
Path = path |> List.rev }
Path = normalizedPath path }
}

let private resolveField (execute: ExecuteField) (ctx: ResolveFieldContext) (parentValue: obj) =
Expand Down Expand Up @@ -136,7 +136,7 @@ let private raiseErrors errs = AsyncVal.wrap <| Error errs
/// Given an error e, call ParseError in the given context's Schema to convert it into
/// a list of one or more <see href="IGQLErrors">IGQLErrors</see>, then convert those
/// to a list of <see href="GQLProblemDetails">GQLProblemDetails</see>.
let private resolverError path ctx e = ctx.Schema.ParseError path e |> List.map (GQLProblemDetails.OfFieldExecutionError (path |> List.rev))
let private resolverError path ctx e = ctx.Schema.ParseError path e |> List.map (GQLProblemDetails.OfFieldExecutionError (normalizedPath path))
// Helper functions for generating more specific <see href="GQLProblemDetails">GQLProblemDetails</see>.
let private nullResolverError name path ctx = resolverError path ctx (GQLMessageException <| sprintf "Non-Null field %s resolved as a null!" name)
let private coercionError value tyName path ctx = resolverError path ctx (GQLMessageException <| sprintf "Value '%O' could not be coerced to scalar %s" value tyName)
Expand All @@ -148,7 +148,7 @@ let private streamListError name tyName path ctx = resolverError path ctx (GQLMe
let private resolved name v : AsyncVal<ResolverResult<KeyValuePair<string, obj>>> = KeyValuePair(name, box v) |> ResolverResult.data |> AsyncVal.wrap

let deferResults path (res : ResolverResult<obj>) : IObservable<GQLDeferredResponseContent> =
let formattedPath = path |> List.rev
let formattedPath = normalizedPath path
match res with
| Ok (data, deferred, errs) ->
let deferredData =
Expand Down Expand Up @@ -368,7 +368,7 @@ and private executeResolvers (ctx : ResolveFieldContext) (path : FieldPath) (par
match ctx.Context.Errors.TryGetValue ctx with
| true, errors ->
errors
|> Seq.map (GQLProblemDetails.OfFieldExecutionError (path |> List.rev))
|> Seq.map (GQLProblemDetails.OfFieldExecutionError (normalizedPath path))
|> Seq.toList
| false, _ -> []
match resolved with
Expand Down Expand Up @@ -462,7 +462,7 @@ let private executeQueryOrMutation (resultSet: (string * ExecutionInfo) []) (ctx
Schema = ctx.Schema
Args = args
Variables = ctx.Variables
Path = path |> List.rev }
Path = normalizedPath path }
let execute = ctx.FieldExecuteMap.GetExecute(ctx.ExecutionPlan.RootDef.Name, info.Definition.Name)
asyncVal {
let! result =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@
<ItemGroup>
<Compile Include="Ast.fs" />
<Compile Include="ReflectionHelper.fs" />
<Compile Include="ErrorsProcessing.fs" />
<Compile Include="ErrorTypes.fs" />
<Compile Include="ErrorMessages.fs" />
<Compile Include="ErrorsProcessing.fs" />
<Compile Include="Exceptions.fs" />
<Compile Include="TypeSystem.fs" />
<Compile Include="Values.fs" />
Expand Down
4 changes: 4 additions & 0 deletions src/FSharp.Data.GraphQL.Shared/TypeSystem.fs
Original file line number Diff line number Diff line change
Expand Up @@ -936,6 +936,10 @@ and ResolveFieldContext = {
member this.AddError (error : IGQLError) =
this.Context.AddError (this, error)

/// Remembers an error, so it can be included in the final response.
member this.AddError (errorMessage : string) =
this.Context.AddError (this, { new IGQLError with member _.Message = errorMessage } )

/// Tries to find an argument by provided name.
member this.TryArg (name : string) : 't option =
match Map.tryFind name this.Args with
Expand Down
14 changes: 7 additions & 7 deletions tests/FSharp.Data.GraphQL.Tests/ExecutionTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ let ``Execution handles errors: properly propagates errors`` () =
// executeResolvers/resolveWith, case 5
let resolvePartialSuccess (ctx : ResolveFieldContext) (_ : InnerNullableTest) =
ctx.AddError { new IGQLError with member _.Message = "Some non-critical error" }
"Success"
"Yes, Rico, Kaboom"
Define.Object<InnerNullableTest>(
"InnerPartialSuccess", [
Define.Field("kaboom", StringType, resolvePartialSuccess)
Expand All @@ -425,15 +425,15 @@ let ``Execution handles errors: properly propagates errors`` () =
NameValueLookup.ofList [
"inner", null
"partialSuccess", NameValueLookup.ofList [
"kaboom", "Success"
"kaboom", "Yes, Rico, Kaboom"
]
]
let expectedErrors = [
GQLProblemDetails.CreateWithKind ("Non-Null field kaboom resolved as a null!", Execution, [ box "inner"; "kaboom" ])
GQLProblemDetails.CreateWithKind ("Some non-critical error", Execution, [ box "partialSuccess"; "kaboom" ])
]
let result =
let variables = { Inner = { Kaboom = null }; InnerPartialSuccess = { Kaboom = "Success" } }
let variables = { Inner = { Kaboom = null }; InnerPartialSuccess = { Kaboom = "Yes, Rico, Kaboom" } }
sync <| Executor(schema).AsyncExecute("query Example { inner { kaboom } partialSuccess { kaboom } }", variables)
ensureDirect result <| fun data errors ->
result.DocumentId |> notEquals Unchecked.defaultof<int>
Expand Down Expand Up @@ -507,7 +507,7 @@ let ``Execution handles errors: additional error added when exception is rised i
GQLProblemDetails.CreateWithKind ("Non-critical error", Execution, [ box "inner"; "kaboom" ])
]
let result =
let variables = { Inner = { Kaboom = null }; InnerPartialSuccess = { Kaboom = "Success" } }
let variables = { Inner = { Kaboom = null }; InnerPartialSuccess = { Kaboom = "Yes, Rico, Kaboom" } }
sync <| Executor(schema).AsyncExecute("query Example { inner { kaboom } }", variables)
ensureDirect result <| fun data errors ->
result.DocumentId |> notEquals Unchecked.defaultof<int>
Expand Down Expand Up @@ -541,7 +541,7 @@ let ``Execution handles errors: additional error added when None returned from a
GQLProblemDetails.CreateWithKind ("Non-critical error", Execution, [ box "inner"; "kaboom" ])
]
let result =
let variables = { Inner = { Kaboom = null }; InnerPartialSuccess = { Kaboom = "Success" } }
let variables = { Inner = { Kaboom = null }; InnerPartialSuccess = { Kaboom = "Yes, Rico, Kaboom" } }
sync <| Executor(schema).AsyncExecute("query Example { inner { kaboom } }", variables)
ensureDirect result <| fun data errors ->
result.DocumentId |> notEquals Unchecked.defaultof<int>
Expand Down Expand Up @@ -571,7 +571,7 @@ let ``Execution handles errors: additional error added when exception is rised i
GQLProblemDetails.CreateWithKind ("Non-critical error", Execution, [ box "inner"; "kaboom" ])
]
let result =
let variables = { Inner = { Kaboom = "Explosion" }; InnerPartialSuccess = { Kaboom = "Success" } }
let variables = { Inner = { Kaboom = "Yes, Rico, Kaboom" }; InnerPartialSuccess = { Kaboom = "Yes, Rico, Kaboom" } }
sync <| Executor(schema).AsyncExecute("query Example { inner { kaboom } }", variables)
ensureRequestError result <| fun errors ->
result.DocumentId |> notEquals Unchecked.defaultof<int>
Expand Down Expand Up @@ -599,7 +599,7 @@ let ``Execution handles errors: additional error added and when null returned fr
GQLProblemDetails.CreateWithKind ("Non-critical error", Execution, [ box "inner"; "kaboom" ])
]
let result =
let variables = { Inner = { Kaboom = "Explosion" }; InnerPartialSuccess = { Kaboom = "Success" } }
let variables = { Inner = { Kaboom = "Yes, Rico, Kaboom" }; InnerPartialSuccess = { Kaboom = "Yes, Rico, Kaboom" } }
sync <| Executor(schema).AsyncExecute("query Example { inner { kaboom } }", variables)
ensureRequestError result <| fun errors ->
result.DocumentId |> notEquals Unchecked.defaultof<int>
Expand Down

0 comments on commit 0bd5eda

Please sign in to comment.