andreas / ocaml-graphql-server

GraphQL servers in OCaml
MIT License
624 stars 60 forks source link

Custom errors #166

Closed dwwoelfel closed 5 years ago

dwwoelfel commented 5 years ago

Adds support for building a schema with a custom error type.

This allows users of ocaml-graphql-server to add extra error information in the extensions field of the error response.

OneGraph is using this in production to provide more context in the errors that we display to the user. For example, we provide hints if the user is not logged in (try https://www.onegraph.com/graphiql?shortenedId=41WMZX) and nicely format json errors from upstream APIs (try https://www.onegraph.com/graphiql?shortenedId=VJSMV7).

There is a test with an example schema module:

module Err = struct
  type t = | String of string | Extension of string * string
  let message_of_error t = match t with
    | String s -> s
    | Extension _ -> ""
  let extensions_of_error t = match t with
    | String _ -> []
    | Extension (k, v) -> [(k, `String v)]
end

module CustomErrorsSchema = Graphql_schema.Make (struct
  type +'a t = 'a

  let bind t f = f t
  let return t = t

  module Stream = struct
    type 'a t = 'a Seq.t

    let map t f = Seq.map f t
    let iter t f = Seq.iter f t
    let close _t = ()
  end
end) (Err)

Example resolver:

let schema = CustomErrorsSchema.(schema [
  io_field "string_error"
    ~typ:int
    ~args:Arg.[]
    ~resolve:(fun _ () -> Error (Err.String "error string"));
  io_field "extensions_error"
    ~typ:int
    ~args:Arg.[]
    ~resolve:(fun _ () -> Error (Err.Extension ("custom", "json")))
])
sgrove commented 5 years ago

Here's an example of how we use it to drive nice UI enhancements that react to user error states: https://www.youtube.com/watch?v=F7Sl41aS8Io

andreas commented 5 years ago

I'm fine with Field_error / field_error 😄 Thanks @dwwoelfel!