Skip to content

Commit 429c4fb

Browse files
Copilotxperiandri
andcommitted
Support GraphQL error extensions in OperationError
Agent-Logs-Url: https://github.com/fsprojects/FSharp.Data.GraphQL/sessions/f7ecc729-e334-47b1-8577-9f252b9417f2 Co-authored-by: xperiandri <2365592+xperiandri@users.noreply.github.com>
1 parent 5d62dba commit 429c4fb

1 file changed

Lines changed: 48 additions & 10 deletions

File tree

src/FSharp.Data.GraphQL.Client/BaseTypes.fs

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,23 @@ type SchemaFieldInfo =
2626
/// A type alias to represent a Type name.
2727
type TypeName = string
2828

29+
/// Contains data about a GQL operation error.
30+
type OperationErrorLocation =
31+
{ /// The source line of the GraphQL operation document where the error occurred.
32+
Line : int
33+
/// The source column of the GraphQL operation document where the error occurred.
34+
Column : int }
35+
2936
/// Contains data about a GQL operation error.
3037
type OperationError =
3138
{ /// The description of the error that happened in the operation.
3239
Message : string
40+
/// The source locations in the GraphQL operation document where the error occurred.
41+
Locations : OperationErrorLocation []
3342
/// The path to the field that produced the error while resolving its value.
34-
Path : obj [] }
43+
Path : obj []
44+
/// Extension data attached to the error.
45+
Extensions : Map<string, obj> }
3546

3647
/// Contains helpers to build HTTP header sequences to be used in GraphQLProvider Run methods.
3748
module HttpHeaders =
@@ -394,17 +405,44 @@ module internal JsonValueHelper =
394405
|> Array.map (firstUpper >> mapFieldValue)
395406

396407
let getErrors (errors : JsonValue []) =
408+
let tryFindField fieldName (fields : (string * JsonValue) []) =
409+
fields |> Array.tryFind (fun (name, _) -> name = fieldName) |> Option.map snd
410+
411+
let parsePath = function
412+
| Some (JsonValue.Array path) ->
413+
let pathMapper = function
414+
| JsonValue.String x -> box x
415+
| JsonValue.Integer x -> box x
416+
| _ -> failwith "Error parsing response errors. An item in the path is neither a String nor a Number."
417+
path |> Array.map pathMapper
418+
| Some JsonValue.Null | None -> [||]
419+
| _ -> failwith "Error parsing response errors. Path field must be an Array."
420+
421+
let parseLocations = function
422+
| Some (JsonValue.Array locations) ->
423+
let parseLocation = function
424+
| JsonValue.Record locationFields ->
425+
match tryFindField "line" locationFields, tryFindField "column" locationFields with
426+
| Some (JsonValue.Integer line), Some (JsonValue.Integer column) -> { Line = line; Column = column }
427+
| _ -> failwith "Error parsing response errors. A location item must contain Integer fields named \"line\" and \"column\"."
428+
| _ -> failwith "Error parsing response errors. A location item is not a Record."
429+
locations |> Array.map parseLocation
430+
| Some JsonValue.Null | None -> [||]
431+
| _ -> failwith "Error parsing response errors. Locations field must be an Array."
432+
433+
let parseExtensions = function
434+
| Some (JsonValue.Record fields) -> Serialization.deserializeMap fields
435+
| Some JsonValue.Null | None -> Map.empty
436+
| _ -> failwith "Error parsing response errors. Extensions field must be a Record."
437+
397438
let errorMapper = function
398439
| JsonValue.Record fields ->
399-
match fields |> Array.tryFind (fun (name, _) -> name = "message"), fields |> Array.tryFind (fun (name, _) -> name = "path") with
400-
| Some (_, JsonValue.String message), Some (_, JsonValue.Array path) ->
401-
let pathMapper = function
402-
| JsonValue.String x -> box x
403-
| JsonValue.Integer x -> box x
404-
| _ -> failwith "Error parsing response errors. A item in the path is neither a String or a Number."
405-
{ Message = message; Path = Array.map pathMapper path }
406-
| Some (_, JsonValue.String message), None->
407-
{ Message = message; Path = [||]}
440+
match tryFindField "message" fields with
441+
| Some (JsonValue.String message) ->
442+
{ Message = message
443+
Locations = tryFindField "locations" fields |> parseLocations
444+
Path = tryFindField "path" fields |> parsePath
445+
Extensions = tryFindField "extensions" fields |> parseExtensions }
408446
| _ -> failwith "Error parsing response errors. Unsupported errors field format."
409447
| other -> failwithf "Error parsing response errors. Expected error to be a Record type, but it is %s." (other.ToString())
410448
Array.map errorMapper errors

0 commit comments

Comments
 (0)