Repository: goadesign/goa
Pull request #3154 (2022-10-01 18:27:34)

Move ErrorNamer and GoaErrorNamer to Goa library
instead of re-generating the data structures in every transport package.

raphael: @ernesto-jimenez FYI

Patch:
diff --git a/grpc/codegen/server.go b/grpc/codegen/server.go
index 50ebda98..e5167d81 100644
--- a/grpc/codegen/server.go
+++ b/grpc/codegen/server.go
@@ -205,32 +205,6 @@ type {{ .ServerStruct }} struct {
 {{- end }}
 	{{ .PkgName }}.Unimplemented{{ .ServerInterface }}
 }
-
-// ErrorNamer is an interface implemented by generated error structs that
-// exposes the name of the error as defined in the expr.
-//
-// Deprecated: Use GoaErrorName - https://github.com/goadesign/goa/issues/3105
-type ErrorNamer interface {
-  ErrorName() string
-}
-
-// GoaErrorNamer is an interface implemented by generated error structs that
-// exposes the name of the error as defined in the design.
-type GoaErrorNamer interface {
-	GoaErrorName() string
-}
-
-type adaptErrorNamer struct {
-	ErrorNamer
-}
-
-func (err adaptErrorNamer) GoaErrorName() string {
-	return err.ErrorName()
-}
-
-func (err adaptErrorNamer) Error() string {
-	return err.ErrorNamer.(error).Error()
-}
 `
 
 // input: ServiceData
@@ -286,11 +260,11 @@ func (s *{{ .ServerStruct }}) {{ .Method.VarName }}(
 {{- define "handle_error" }}
 	if err != nil {
 	{{- if .Errors }}
-		var deprecatedErrorNamer ErrorNamer
-		if errors.As(err, &deprecatedErrorNamer) {
-			err = adaptErrorNamer{deprecatedErrorNamer}
+		var deprecated goa.ErrorNamer
+		if errors.As(err, &deprecated) {
+			err = goa.AdaptErrorNamer{deprecated}
 		}
-		var en GoaErrorNamer
+		var en goa.GoaErrorNamer
 		if errors.As(err, &en) {
 			switch en.GoaErrorName() {
 		{{- range .Errors }}
diff --git a/http/codegen/server.go b/http/codegen/server.go
index 5bea78e3..dfdd21bc 100644
--- a/http/codegen/server.go
+++ b/http/codegen/server.go
@@ -277,32 +277,6 @@ type {{ .ServerStruct }} struct {
 	{{ .VarName }} http.Handler
 	{{- end }}
 }
-
-// ErrorNamer is an interface implemented by generated error structs that
-// exposes the name of the error as defined in the design.
-//
-// Deprecated: Use GoaErrorName - https://github.com/goadesign/goa/issues/3105
-type ErrorNamer interface {
-	ErrorName() string
-}
-
-// GoaErrorNamer is an interface implemented by generated error structs that
-// exposes the name of the error as defined in the design.
-type GoaErrorNamer interface {
-	GoaErrorName() string
-}
-
-type adaptErrorNamer struct {
-	ErrorNamer
-}
-
-func (err adaptErrorNamer) GoaErrorName() string {
-	return err.ErrorName()
-}
-
-func (err adaptErrorNamer) Error() string {
-	return err.ErrorNamer.(error).Error()
-}
 `
 
 // input: ServiceData
@@ -1229,11 +1203,11 @@ const errorEncoderT = `{{ printf "%s returns an encoder for errors returned by t
 func {{ .ErrorEncoder }}(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder, formatter func(ctx context.Context, err error) goahttp.Statuser) func(context.Context, http.ResponseWriter, error) error {
 	encodeError := goahttp.ErrorEncoder(encoder, formatter)
 	return func(ctx context.Context, w http.ResponseWriter, v error) error {
-		var deprecatedErrorNamer ErrorNamer
-		if errors.As(v, &deprecatedErrorNamer) {
-			v = adaptErrorNamer{deprecatedErrorNamer}
+		var deprecated goa.ErrorNamer
+		if errors.As(v, &deprecated) {
+			v = goa.AdaptErrorNamer{deprecated}
 		}
-		var en GoaErrorNamer
+		var en goa.GoaErrorNamer
 		if !errors.As(v, &en) {
 			return encodeError(ctx, w, v)
 		}
diff --git a/pkg/error.go b/pkg/error.go
index 3d4c12b3..4672c3fc 100644
--- a/pkg/error.go
+++ b/pkg/error.go
@@ -34,6 +34,26 @@ type (
 		// err holds the original error if exists.
 		err error
 	}
+
+	// ErrorNamer is an interface implemented by generated error structs that
+	// exposes the name of the error as defined in the expr.
+	//
+	// Deprecated: Use GoaErrorName - https://github.com/goadesign/goa/issues/3105
+	ErrorNamer interface {
+		ErrorName() string
+	}
+
+	// GoaErrorNamer is an interface implemented by generated error structs that
+	// exposes the name of the error as defined in the design.
+	GoaErrorNamer interface {
+		GoaErrorName() string
+	}
+
+	// AdaptErrorNamer makes deprecated ErrorNamer interface compatible with
+	// GoaErrorNamer.
+	AdaptErrorNamer struct {
+		ErrorNamer
+	}
 )
 
 const (
@@ -254,6 +274,16 @@ func (e *ServiceError) GoaErrorName() string { return e.ErrorName() }
 
 func (e *ServiceError) Unwrap() error { return e.err }
 
+// GoaErrorName returns the error name as defined in the design.
+func (err AdaptErrorNamer) GoaErrorName() string {
+	return err.ErrorName()
+}
+
+// Error is the error message.
+func (err AdaptErrorNamer) Error() string {
+	return err.ErrorNamer.(error).Error()
+}
+
 func withField(field string, err *ServiceError) *ServiceError {
 	err.Field = &field
 	return err


Test patch:
diff --git a/grpc/codegen/testdata/server_interface_code.go b/grpc/codegen/testdata/server_interface_code.go
index 1c5e18f1..4656acae 100644
--- a/grpc/codegen/testdata/server_interface_code.go
+++ b/grpc/codegen/testdata/server_interface_code.go
@@ -58,11 +58,11 @@ func (s *Server) MethodUnaryRPCWithErrors(ctx context.Context, message *service_
 	ctx = context.WithValue(ctx, goa.ServiceKey, "ServiceUnaryRPCWithErrors")
 	resp, err := s.MethodUnaryRPCWithErrorsH.Handle(ctx, message)
 	if err != nil {
-		var deprecatedErrorNamer ErrorNamer
-		if errors.As(err, &deprecatedErrorNamer) {
-			err = adaptErrorNamer{deprecatedErrorNamer}
+		var deprecated goa.ErrorNamer
+		if errors.As(err, &deprecated) {
+			err = goa.AdaptErrorNamer{deprecated}
 		}
-		var en GoaErrorNamer
+		var en goa.GoaErrorNamer
 		if errors.As(err, &en) {
 			switch en.GoaErrorName() {
 			case "timeout":
@@ -96,11 +96,11 @@ func (s *Server) MethodUnaryRPCWithOverridingErrors(ctx context.Context, message
 	ctx = context.WithValue(ctx, goa.ServiceKey, "ServiceUnaryRPCWithOverridingErrors")
 	resp, err := s.MethodUnaryRPCWithOverridingErrorsH.Handle(ctx, message)
 	if err != nil {
-		var deprecatedErrorNamer ErrorNamer
-		if errors.As(err, &deprecatedErrorNamer) {
-			err = adaptErrorNamer{deprecatedErrorNamer}
+		var deprecated goa.ErrorNamer
+		if errors.As(err, &deprecated) {
+			err = goa.AdaptErrorNamer{deprecated}
 		}
-		var en GoaErrorNamer
+		var en goa.GoaErrorNamer
 		if errors.As(err, &en) {
 			switch en.GoaErrorName() {
 			case "overridden":
@@ -239,11 +239,11 @@ func (s *Server) MethodBidirectionalStreamingRPCWithErrors(stream service_bidire
 	ctx = context.WithValue(ctx, goa.ServiceKey, "ServiceBidirectionalStreamingRPCWithErrors")
 	_, err := s.MethodBidirectionalStreamingRPCWithErrorsH.Decode(ctx, nil)
 	if err != nil {
-		var deprecatedErrorNamer ErrorNamer
-		if errors.As(err, &deprecatedErrorNamer) {
-			err = adaptErrorNamer{deprecatedErrorNamer}
+		var deprecated goa.ErrorNamer
+		if errors.As(err, &deprecated) {
+			err = goa.AdaptErrorNamer{deprecated}
 		}
-		var en GoaErrorNamer
+		var en goa.GoaErrorNamer
 		if errors.As(err, &en) {
 			switch en.GoaErrorName() {
 			case "timeout":
@@ -261,11 +261,11 @@ func (s *Server) MethodBidirectionalStreamingRPCWithErrors(stream service_bidire
 	}
 	err = s.MethodBidirectionalStreamingRPCWithErrorsH.Handle(ctx, ep)
 	if err != nil {
-		var deprecatedErrorNamer ErrorNamer
-		if errors.As(err, &deprecatedErrorNamer) {
-			err = adaptErrorNamer{deprecatedErrorNamer}
+		var deprecated goa.ErrorNamer
+		if errors.As(err, &deprecated) {
+			err = goa.AdaptErrorNamer{deprecated}
 		}
-		var en GoaErrorNamer
+		var en goa.GoaErrorNamer
 		if errors.As(err, &en) {
 			switch en.GoaErrorName() {
 			case "timeout":
diff --git a/http/codegen/testdata/error_encoder_code.go b/http/codegen/testdata/error_encoder_code.go
index d9189555..8a0c6ebb 100644
--- a/http/codegen/testdata/error_encoder_code.go
+++ b/http/codegen/testdata/error_encoder_code.go
@@ -6,11 +6,11 @@ var PrimitiveErrorResponseEncoderCode = `// EncodeMethodPrimitiveErrorResponseEr
 func EncodeMethodPrimitiveErrorResponseError(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder, formatter func(ctx context.Context, err error) goahttp.Statuser) func(context.Context, http.ResponseWriter, error) error {
 	encodeError := goahttp.ErrorEncoder(encoder, formatter)
 	return func(ctx context.Context, w http.ResponseWriter, v error) error {
-		var deprecatedErrorNamer ErrorNamer
-		if errors.As(v, &deprecatedErrorNamer) {
-			v = adaptErrorNamer{deprecatedErrorNamer}
+		var deprecated goa.ErrorNamer
+		if errors.As(v, &deprecated) {
+			v = goa.AdaptErrorNamer{deprecated}
 		}
-		var en GoaErrorNamer
+		var en goa.GoaErrorNamer
 		if !errors.As(v, &en) {
 			return encodeError(ctx, w, v)
 		}
@@ -44,11 +44,11 @@ var PrimitiveErrorInResponseHeaderEncoderCode = `// EncodeMethodPrimitiveErrorIn
 func EncodeMethodPrimitiveErrorInResponseHeaderError(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder, formatter func(ctx context.Context, err error) goahttp.Statuser) func(context.Context, http.ResponseWriter, error) error {
 	encodeError := goahttp.ErrorEncoder(encoder, formatter)
 	return func(ctx context.Context, w http.ResponseWriter, v error) error {
-		var deprecatedErrorNamer ErrorNamer
-		if errors.As(v, &deprecatedErrorNamer) {
-			v = adaptErrorNamer{deprecatedErrorNamer}
+		var deprecated goa.ErrorNamer
+		if errors.As(v, &deprecated) {
+			v = goa.AdaptErrorNamer{deprecated}
 		}
-		var en GoaErrorNamer
+		var en goa.GoaErrorNamer
 		if !errors.As(v, &en) {
 			return encodeError(ctx, w, v)
 		}
@@ -88,11 +88,11 @@ var APIPrimitiveErrorResponseEncoderCode = `// EncodeMethodAPIPrimitiveErrorResp
 func EncodeMethodAPIPrimitiveErrorResponseError(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder, formatter func(ctx context.Context, err error) goahttp.Statuser) func(context.Context, http.ResponseWriter, error) error {
 	encodeError := goahttp.ErrorEncoder(encoder, formatter)
 	return func(ctx context.Context, w http.ResponseWriter, v error) error {
-		var deprecatedErrorNamer ErrorNamer
-		if errors.As(v, &deprecatedErrorNamer) {
-			v = adaptErrorNamer{deprecatedErrorNamer}
+		var deprecated goa.ErrorNamer
+		if errors.As(v, &deprecated) {
+			v = goa.AdaptErrorNamer{deprecated}
 		}
-		var en GoaErrorNamer
+		var en goa.GoaErrorNamer
 		if !errors.As(v, &en) {
 			return encodeError(ctx, w, v)
 		}
@@ -130,11 +130,11 @@ var DefaultErrorResponseEncoderCode = `// EncodeMethodDefaultErrorResponseError
 func EncodeMethodDefaultErrorResponseError(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder, formatter func(ctx context.Context, err error) goahttp.Statuser) func(context.Context, http.ResponseWriter, error) error {
 	encodeError := goahttp.ErrorEncoder(encoder, formatter)
 	return func(ctx context.Context, w http.ResponseWriter, v error) error {
-		var deprecatedErrorNamer ErrorNamer
-		if errors.As(v, &deprecatedErrorNamer) {
-			v = adaptErrorNamer{deprecatedErrorNamer}
+		var deprecated goa.ErrorNamer
+		if errors.As(v, &deprecated) {
+			v = goa.AdaptErrorNamer{deprecated}
 		}
-		var en GoaErrorNamer
+		var en goa.GoaErrorNamer
 		if !errors.As(v, &en) {
 			return encodeError(ctx, w, v)
 		}
@@ -164,11 +164,11 @@ var DefaultErrorResponseWithContentTypeEncoderCode = `// EncodeMethodDefaultErro
 func EncodeMethodDefaultErrorResponseError(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder, formatter func(ctx context.Context, err error) goahttp.Statuser) func(context.Context, http.ResponseWriter, error) error {
 	encodeError := goahttp.ErrorEncoder(encoder, formatter)
 	return func(ctx context.Context, w http.ResponseWriter, v error) error {
-		var deprecatedErrorNamer ErrorNamer
-		if errors.As(v, &deprecatedErrorNamer) {
-			v = adaptErrorNamer{deprecatedErrorNamer}
+		var deprecated goa.ErrorNamer
+		if errors.As(v, &deprecated) {
+			v = goa.AdaptErrorNamer{deprecated}
 		}
-		var en GoaErrorNamer
+		var en goa.GoaErrorNamer
 		if !errors.As(v, &en) {
 			return encodeError(ctx, w, v)
 		}
@@ -199,11 +199,11 @@ var ServiceErrorResponseEncoderCode = `// EncodeMethodServiceErrorResponseError
 func EncodeMethodServiceErrorResponseError(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder, formatter func(ctx context.Context, err error) goahttp.Statuser) func(context.Context, http.ResponseWriter, error) error {
 	encodeError := goahttp.ErrorEncoder(encoder, formatter)
 	return func(ctx context.Context, w http.ResponseWriter, v error) error {
-		var deprecatedErrorNamer ErrorNamer
-		if errors.As(v, &deprecatedErrorNamer) {
-			v = adaptErrorNamer{deprecatedErrorNamer}
+		var deprecated goa.ErrorNamer
+		if errors.As(v, &deprecated) {
+			v = goa.AdaptErrorNamer{deprecated}
 		}
-		var en GoaErrorNamer
+		var en goa.GoaErrorNamer
 		if !errors.As(v, &en) {
 			return encodeError(ctx, w, v)
 		}
@@ -246,11 +246,11 @@ var ServiceErrorResponseWithContentTypeEncoderCode = `// EncodeMethodServiceErro
 func EncodeMethodServiceErrorResponseError(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder, formatter func(ctx context.Context, err error) goahttp.Statuser) func(context.Context, http.ResponseWriter, error) error {
 	encodeError := goahttp.ErrorEncoder(encoder, formatter)
 	return func(ctx context.Context, w http.ResponseWriter, v error) error {
-		var deprecatedErrorNamer ErrorNamer
-		if errors.As(v, &deprecatedErrorNamer) {
-			v = adaptErrorNamer{deprecatedErrorNamer}
+		var deprecated goa.ErrorNamer
+		if errors.As(v, &deprecated) {
+			v = goa.AdaptErrorNamer{deprecated}
 		}
-		var en GoaErrorNamer
+		var en goa.GoaErrorNamer
 		if !errors.As(v, &en) {
 			return encodeError(ctx, w, v)
 		}
@@ -294,11 +294,11 @@ var NoBodyErrorResponseEncoderCode = `// EncodeMethodServiceErrorResponseError r
 func EncodeMethodServiceErrorResponseError(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder, formatter func(ctx context.Context, err error) goahttp.Statuser) func(context.Context, http.ResponseWriter, error) error {
 	encodeError := goahttp.ErrorEncoder(encoder, formatter)
 	return func(ctx context.Context, w http.ResponseWriter, v error) error {
-		var deprecatedErrorNamer ErrorNamer
-		if errors.As(v, &deprecatedErrorNamer) {
-			v = adaptErrorNamer{deprecatedErrorNamer}
+		var deprecated goa.ErrorNamer
+		if errors.As(v, &deprecated) {
+			v = goa.AdaptErrorNamer{deprecated}
 		}
-		var en GoaErrorNamer
+		var en goa.GoaErrorNamer
 		if !errors.As(v, &en) {
 			return encodeError(ctx, w, v)
 		}
@@ -324,11 +324,11 @@ var NoBodyErrorResponseWithContentTypeEncoderCode = `// EncodeMethodServiceError
 func EncodeMethodServiceErrorResponseError(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder, formatter func(ctx context.Context, err error) goahttp.Statuser) func(context.Context, http.ResponseWriter, error) error {
 	encodeError := goahttp.ErrorEncoder(encoder, formatter)
 	return func(ctx context.Context, w http.ResponseWriter, v error) error {
-		var deprecatedErrorNamer ErrorNamer
-		if errors.As(v, &deprecatedErrorNamer) {
-			v = adaptErrorNamer{deprecatedErrorNamer}
+		var deprecated goa.ErrorNamer
+		if errors.As(v, &deprecated) {
+			v = goa.AdaptErrorNamer{deprecated}
 		}
-		var en GoaErrorNamer
+		var en goa.GoaErrorNamer
 		if !errors.As(v, &en) {
 			return encodeError(ctx, w, v)
 		}
@@ -356,11 +356,11 @@ var EmptyErrorResponseBodyEncoderCode = `// EncodeMethodEmptyErrorResponseBodyEr
 func EncodeMethodEmptyErrorResponseBodyError(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder, formatter func(ctx context.Context, err error) goahttp.Statuser) func(context.Context, http.ResponseWriter, error) error {
 	encodeError := goahttp.ErrorEncoder(encoder, formatter)
 	return func(ctx context.Context, w http.ResponseWriter, v error) error {
-		var deprecatedErrorNamer ErrorNamer
-		if errors.As(v, &deprecatedErrorNamer) {
-			v = adaptErrorNamer{deprecatedErrorNamer}
+		var deprecated goa.ErrorNamer
+		if errors.As(v, &deprecated) {
+			v = goa.AdaptErrorNamer{deprecated}
 		}
-		var en GoaErrorNamer
+		var en goa.GoaErrorNamer
 		if !errors.As(v, &en) {
 			return encodeError(ctx, w, v)
 		}
@@ -413,11 +413,11 @@ var EmptyCustomErrorResponseBodyEncoderCode = `// EncodeMethodEmptyCustomErrorRe
 func EncodeMethodEmptyCustomErrorResponseBodyError(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder, formatter func(ctx context.Context, err error) goahttp.Statuser) func(context.Context, http.ResponseWriter, error) error {
 	encodeError := goahttp.ErrorEncoder(encoder, formatter)
 	return func(ctx context.Context, w http.ResponseWriter, v error) error {
-		var deprecatedErrorNamer ErrorNamer
-		if errors.As(v, &deprecatedErrorNamer) {
-			v = adaptErrorNamer{deprecatedErrorNamer}
+		var deprecated goa.ErrorNamer
+		if errors.As(v, &deprecated) {
+			v = goa.AdaptErrorNamer{deprecated}
 		}
-		var en GoaErrorNamer
+		var en goa.GoaErrorNamer
 		if !errors.As(v, &en) {
 			return encodeError(ctx, w, v)
 		}