github.com/storacha/go-ucanto@v0.7.2/server/error.go (about) 1 package server 2 3 import ( 4 "fmt" 5 "strings" 6 7 "github.com/storacha/go-ucanto/core/ipld" 8 "github.com/storacha/go-ucanto/core/result/failure" 9 sdm "github.com/storacha/go-ucanto/server/datamodel" 10 "github.com/storacha/go-ucanto/ucan" 11 ) 12 13 type HandlerNotFoundError[Caveats any] interface { 14 failure.Failure 15 Capability() ucan.Capability[Caveats] 16 } 17 18 type handlerNotFoundError[Caveats any] struct { 19 capability ucan.Capability[Caveats] 20 } 21 22 func (h handlerNotFoundError[C]) Capability() ucan.Capability[C] { 23 return h.capability 24 } 25 26 func (h handlerNotFoundError[C]) Error() string { 27 return fmt.Sprintf("service does not implement {can: \"%s\"} handler", h.capability.Can()) 28 } 29 30 func (h handlerNotFoundError[C]) Name() string { 31 return "HandlerNotFoundError" 32 } 33 34 func (h handlerNotFoundError[C]) ToIPLD() (ipld.Node, error) { 35 name := h.Name() 36 37 mdl := sdm.HandlerNotFoundErrorModel{ 38 Error: true, 39 Name: &name, 40 Message: h.Error(), 41 Capability: sdm.CapabilityModel{ 42 Can: h.capability.Can(), 43 With: h.capability.With(), 44 }, 45 } 46 return ipld.WrapWithRecovery(&mdl, sdm.HandlerNotFoundErrorType()) 47 } 48 49 func NewHandlerNotFoundError[Caveats any](capability ucan.Capability[Caveats]) HandlerNotFoundError[Caveats] { 50 return handlerNotFoundError[Caveats]{capability} 51 } 52 53 type HandlerExecutionError[Caveats any] interface { 54 failure.Failure 55 failure.WithStackTrace 56 Cause() error 57 Capability() ucan.Capability[Caveats] 58 } 59 60 type handlerExecutionError[Caveats any] struct { 61 cause error 62 capability ucan.Capability[Caveats] 63 } 64 65 func (h handlerExecutionError[C]) Capability() ucan.Capability[C] { 66 return h.capability 67 } 68 69 func (h handlerExecutionError[C]) Cause() error { 70 return h.cause 71 } 72 73 func (h handlerExecutionError[C]) Error() string { 74 return fmt.Sprintf("service handler {can: \"%s\"} error: %s", h.capability.Can(), h.cause.Error()) 75 } 76 77 func (h handlerExecutionError[C]) Name() string { 78 return "HandlerExecutionError" 79 } 80 81 func (h handlerExecutionError[C]) Stack() string { 82 var stack string 83 if serr, ok := h.cause.(failure.WithStackTrace); ok { 84 stack = serr.Stack() 85 } 86 return stack 87 } 88 89 func (h handlerExecutionError[C]) ToIPLD() (ipld.Node, error) { 90 name := h.Name() 91 stack := h.Stack() 92 93 var cname string 94 if ncause, ok := h.cause.(failure.Named); ok { 95 cname = ncause.Name() 96 } 97 98 var cstack string 99 if scause, ok := h.cause.(failure.WithStackTrace); ok { 100 cstack = scause.Stack() 101 } 102 103 mdl := sdm.HandlerExecutionErrorModel{ 104 Error: true, 105 Name: &name, 106 Message: h.Error(), 107 Stack: &stack, 108 Cause: sdm.FailureModel{ 109 Name: &cname, 110 Message: h.cause.Error(), 111 Stack: &cstack, 112 }, 113 Capability: sdm.CapabilityModel{ 114 Can: h.capability.Can(), 115 With: h.capability.With(), 116 }, 117 } 118 return ipld.WrapWithRecovery(&mdl, sdm.HandlerExecutionErrorType()) 119 } 120 121 func NewHandlerExecutionError[Caveats any](cause error, capability ucan.Capability[Caveats]) HandlerExecutionError[Caveats] { 122 return handlerExecutionError[Caveats]{cause, capability} 123 } 124 125 type InvocationCapabilityError interface { 126 failure.Failure 127 Capabilities() []ucan.Capability[any] 128 } 129 130 type invocationCapabilityError struct { 131 capabilities []ucan.Capability[any] 132 } 133 134 func (i invocationCapabilityError) Capabilities() []ucan.Capability[any] { 135 return i.capabilities 136 } 137 138 func (i invocationCapabilityError) Error() string { 139 return "Invocation is required to have a single capability." 140 } 141 142 func (i invocationCapabilityError) Name() string { 143 return "InvocationCapabilityError" 144 } 145 146 func (i invocationCapabilityError) ToIPLD() (ipld.Node, error) { 147 name := i.Name() 148 var capmdls []sdm.CapabilityModel 149 for _, cap := range i.Capabilities() { 150 capmdls = append(capmdls, sdm.CapabilityModel{ 151 Can: cap.Can(), 152 With: cap.With(), 153 }) 154 } 155 156 mdl := sdm.InvocationCapabilityErrorModel{ 157 Error: true, 158 Name: &name, 159 Message: i.Error(), 160 Capabilities: capmdls, 161 } 162 return ipld.WrapWithRecovery(&mdl, sdm.InvocationCapabilityErrorType()) 163 } 164 165 func NewInvocationCapabilityError(capabilities []ucan.Capability[any]) InvocationCapabilityError { 166 return invocationCapabilityError{capabilities} 167 } 168 169 type InvalidAudienceError struct { 170 expected []ucan.Principal 171 actual ucan.Principal 172 } 173 174 func (i InvalidAudienceError) Error() string { 175 expectedStr := make([]string, 0, len(i.expected)) 176 for _, e := range i.expected { 177 expectedStr = append(expectedStr, e.DID().String()) 178 } 179 180 return fmt.Sprintf("Invalid audience: expected %s, got %s", strings.Join(expectedStr, " or "), i.actual.DID().String()) 181 } 182 183 func (i InvalidAudienceError) Name() string { 184 return "InvalidAudienceError" 185 } 186 187 func (i InvalidAudienceError) ToIPLD() (ipld.Node, error) { 188 name := i.Name() 189 mdl := sdm.InvalidAudienceErrorModel{ 190 Error: true, 191 Name: &name, 192 Message: i.Error(), 193 } 194 return ipld.WrapWithRecovery(&mdl, sdm.InvalidAudienceErrorType()) 195 } 196 197 func NewInvalidAudienceError(actual ucan.Principal, expected ...ucan.Principal) InvalidAudienceError { 198 return InvalidAudienceError{expected, actual} 199 }