sourceafJsonRpc::JsonRpcErr.fan

using util::JsonOutStream

** Represents an error when calling RPC.
** 
** Errors thrown by the endpoints result in an 'JsonRpcErr' with a 'code' of 'applicationError'.
const class JsonRpcErr : Err {
    
    static const Int parseError         := -32700
    static const Int invalidRequest     := -32600
    static const Int methodNotFound     := -32601
    static const Int invalidParams      := -32602
    static const Int internalError      := -32603
    static const Int applicationError   := -32500
    
    ** A Number that indicates the error type that occurred.
    const Int code
    
    ** A Primitive or Structured value that contains additional information about the error.
    const Obj? data
    
    new make(Int code, Str msg, Obj? dataOrCause := null) : super(msg, dataOrCause as Err) {
        this.code = code
        this.data = dataOrCause is Err ? null : dataOrCause
    }
    
    @NoDoc
    static new fromObj([Str:Obj?]? obj) {
        if (obj == null)    return null
        
        code := (obj["code"] as Num).toInt
        msg  :=  obj["message"]
        data :=  obj["data"]
        
        return JsonRpcErr(code, msg, data)
    }
    
    @NoDoc
    Str:Obj? toJsonObj() {
        Str:Obj?[:] {
            it.ordered = true
            add("code",     code)
            add("message",  msg)
            
            if (data != null)
                try {
                    // make sure we'll be able to serialise the data, we don't want errors in our err handlers!
                    // note that @Serializable objects are written out as their serialised strings
                    JsonOutStream.writeJsonToStr(data)
                    add("data", data)
                } catch (Err err)
                    add("data", "Bad Err Data: ${err}")
            else
                if (cause != null)
                    add("data", [
                        "type"  : cause.typeof.qname,
                        "msg"   : cause.toStr,      // Err.toStr holds more than Err.msg
                        "trace" : cause.traceToStr
                    ])
        }
    }
}