///|
/// A GraphQL error entry: a message, an optional response path (string field
/// keys and integer list indices), and optional source locations.
pub(all) struct GqlError {
message : String
path : Array[Json]
locations : Array[Pos]
extensions : Map[String, Json]
}
///|
/// Build an error carrying only a message, for the request-level failures that
/// cannot be pinned to a point in the document (an empty document, an unknown
/// operation name).
pub fn GqlError::msg(message : String) -> GqlError {
{ message, path: [], locations: [], extensions: Map([]), }
}
///|
/// Build an error carrying a message and the position of the node it is about.
/// §7.1.2 requires `locations` on every error that can name one.
pub fn GqlError::at(message : String, pos : Pos) -> GqlError {
{ message, path: [], locations: [pos], extensions: Map([]), }
}
///|
/// Serialise an error to the GraphQL JSON error shape, omitting an empty path
/// or locations list.
pub fn GqlError::to_json(self : GqlError) -> Json {
let entries : Array[(String, Json)] = [("message", Json(self.message))]
if self.locations.length() > 0 {
let locs : Array[Json] = []
for p in self.locations {
locs.push(jobj([("line", Json(p.line)), ("column", Json(p.col))]))
}
entries.push(("locations", Json(locs)))
}
if self.path.length() > 0 {
entries.push(("path", Json(self.path)))
}
// A resolver-supplied `extensions` map (← GraphQL spec §7.1.2), emitted only
// when non-empty.
if !self.extensions.is_empty() {
entries.push(("extensions", Json(self.extensions)))
}
jobj(entries)
}