From 78505faf7526bd77f0ee5a698828971e2686f95c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E6=80=A7=E9=A9=8A?= Date: Thu, 2 Oct 2025 22:56:14 +0800 Subject: [PATCH] feat: move error into library --- gateway.json | 2 +- go.mod | 5 +- go.sum | 2 - internal/handler/auth/login_handler.go | 4 +- internal/handler/auth/register_handler.go | 2 +- internal/logic/auth/register_logic.go | 4 +- pkg/library/errs/code/category.go | 14 + pkg/library/errs/code/code.go | 75 +++ pkg/library/errs/code/messsage.go | 13 + pkg/library/errs/code/scope.go | 18 + pkg/library/errs/easy_func.go | 535 ++++++++++++++++++++++ pkg/library/errs/easy_func_test.go | 184 ++++++++ pkg/library/errs/error_code.go | 88 ++++ pkg/library/errs/errors.go | 214 +++++++++ pkg/library/errs/errors_test.go | 177 +++++++ pkg/member/domain/errors.go | 2 +- pkg/member/usecase/binding.go | 4 +- pkg/member/usecase/generate.go | 4 +- pkg/member/usecase/member.go | 4 +- pkg/member/usecase/member_test.go | 4 +- pkg/member/usecase/verify.go | 4 +- pkg/member/usecase/verify_google.go | 4 +- pkg/member/usecase/verify_google_test.go | 4 +- pkg/member/usecase/verify_line.go | 4 +- pkg/member/usecase/verify_test.go | 2 +- 25 files changed, 1345 insertions(+), 28 deletions(-) create mode 100644 pkg/library/errs/code/category.go create mode 100644 pkg/library/errs/code/code.go create mode 100644 pkg/library/errs/code/messsage.go create mode 100644 pkg/library/errs/code/scope.go create mode 100644 pkg/library/errs/easy_func.go create mode 100644 pkg/library/errs/easy_func_test.go create mode 100644 pkg/library/errs/error_code.go create mode 100644 pkg/library/errs/errors.go create mode 100644 pkg/library/errs/errors_test.go diff --git a/gateway.json b/gateway.json index ca217b9..12b283b 100644 --- a/gateway.json +++ b/gateway.json @@ -1148,7 +1148,7 @@ "url": "https://localhost:8888" } ], - "x-date": "2025-10-02 17:47:43", + "x-date": "2025-10-02 22:08:26", "x-description": "This is a go-doc generated swagger file.", "x-generator": "go-doc", "x-github": "https://github.com/danielchan-25/go-doc", diff --git a/go.mod b/go.mod index 40dae4b..5b26b59 100644 --- a/go.mod +++ b/go.mod @@ -2,8 +2,9 @@ module backend go 1.25.1 +replace backend/pkg/library/errs => ./pkg/library/errs + require ( - code.30cm.net/digimon/library-go/errs v1.2.14 code.30cm.net/digimon/library-go/utils/invited_code v1.2.5 github.com/alicebob/miniredis/v2 v2.35.0 github.com/shopspring/decimal v1.4.0 @@ -14,6 +15,7 @@ require ( go.mongodb.org/mongo-driver/v2 v2.3.0 go.uber.org/mock v0.4.0 golang.org/x/crypto v0.37.0 + google.golang.org/grpc v1.67.0 google.golang.org/protobuf v1.36.5 ) @@ -105,7 +107,6 @@ require ( golang.org/x/text v0.24.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect - google.golang.org/grpc v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 1b6fed2..379409a 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,3 @@ -code.30cm.net/digimon/library-go/errs v1.2.14 h1:Un9wcIIjjJW8D2i0ISf8ibzp9oNT4OqLsaSKW0T4RJU= -code.30cm.net/digimon/library-go/errs v1.2.14/go.mod h1:Hs4v7SbXNggDVBGXSYsFMjkii1qLF+rugrIpWePN4/o= code.30cm.net/digimon/library-go/utils/invited_code v1.2.5 h1:szWsI0K+1iEHmc/AtKx+5c7tDIc1AZdStvT0tVza1pg= code.30cm.net/digimon/library-go/utils/invited_code v1.2.5/go.mod h1:eHmWpbX6N6KXQ2xaY71uj5bwfzTaNL8pQc2njYo5Gj0= dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= diff --git a/internal/handler/auth/login_handler.go b/internal/handler/auth/login_handler.go index c7dbb37..3d048f1 100644 --- a/internal/handler/auth/login_handler.go +++ b/internal/handler/auth/login_handler.go @@ -5,8 +5,8 @@ import ( "backend/internal/logic/auth" "backend/internal/svc" "backend/internal/types" - "code.30cm.net/digimon/library-go/errs" - ers "code.30cm.net/digimon/library-go/errs" + "backend/pkg/library/errs" + ers "backend/pkg/library/errs" "net/http" "github.com/zeromicro/go-zero/rest/httpx" diff --git a/internal/handler/auth/register_handler.go b/internal/handler/auth/register_handler.go index 93e77b3..b67c267 100644 --- a/internal/handler/auth/register_handler.go +++ b/internal/handler/auth/register_handler.go @@ -2,7 +2,7 @@ package auth import ( "backend/internal/domain" - "code.30cm.net/digimon/library-go/errs" + "backend/pkg/library/errs" "net/http" "backend/internal/logic/auth" diff --git a/internal/logic/auth/register_logic.go b/internal/logic/auth/register_logic.go index 5ea914b..15a7094 100644 --- a/internal/logic/auth/register_logic.go +++ b/internal/logic/auth/register_logic.go @@ -5,8 +5,8 @@ import ( "backend/internal/types" mb "backend/pkg/member/domain/member" member "backend/pkg/member/domain/usecase" - "code.30cm.net/digimon/library-go/errs" - "code.30cm.net/digimon/library-go/errs/code" + "backend/pkg/library/errs" + "backend/pkg/library/errs/code" "context" "google.golang.org/protobuf/proto" "time" diff --git a/pkg/library/errs/code/category.go b/pkg/library/errs/code/category.go new file mode 100644 index 0000000..a43787f --- /dev/null +++ b/pkg/library/errs/code/category.go @@ -0,0 +1,14 @@ +package code + +// Category for general operations: 10 - 490 +const ( + _ = iota + CatInput uint32 = iota * 10 + CatDB + CatResource + CatGRPC + CatAuth + CatSystem + CatPubSub + CatService +) diff --git a/pkg/library/errs/code/code.go b/pkg/library/errs/code/code.go new file mode 100644 index 0000000..39d9700 --- /dev/null +++ b/pkg/library/errs/code/code.go @@ -0,0 +1,75 @@ +package code + +const ( + OK uint32 = 0 +) + +// 詳細代碼 - 輸入類 01x +const ( + _ = iota + CatInput + InvalidFormat // 無效格式 + NotValidImplementation // 非有效實現 + InvalidRange // 無效範圍 +) + +// 詳細代碼 - 資料庫類 02x +const ( + _ = iota + CatDB + DBError // 資料庫一般錯誤 + DBDataConvert // 資料轉換錯誤 + DBDuplicate // 資料重複 +) + +// 詳細代碼 - 資源類 03x +const ( + _ = iota + CatResource + ResourceNotFound // 資源未找到 + InvalidResourceFormat // 無效的資源格式 + ResourceAlreadyExist // 資源已存在 + ResourceInsufficient // 資源不足 + InsufficientPermission // 權限不足 + InvalidMeasurementID // 無效的測量ID + ResourceExpired // 資源過期 + ResourceMigrated // 資源已遷移 + InvalidResourceState // 無效的資源狀態 + InsufficientQuota // 配額不足 + ResourceHasMultiOwner // 資源有多個所有者 +) + +/* 詳細代碼 - GRPC */ +// GRPC 的詳細代碼使用 Go GRPC 的內建代碼。 +// 參考 "google.golang.org/grpc/codes" 獲取更多詳細資訊。 + +// 詳細代碼 - 驗證類 05x +const ( + _ = iota + CatAuth + Unauthorized // 未授權 + AuthExpired // 授權過期 + InvalidPosixTime // 無效的 POSIX 時間 + SigAndPayloadNotMatched // 簽名和載荷不匹配 + Forbidden // 禁止訪問 +) + +// 詳細代碼 - 系統類 06x +const ( + _ = iota + CatSystem + SystemInternalError // 系統內部錯誤 + SystemMaintainError // 系統維護錯誤 + SystemTimeoutError // 系統超時錯誤 +) + +// 詳細代碼 - PubSub 07x +const ( + _ = iota + CatPubSub + Publish // 發佈錯誤 + Consume // 消費錯誤 + MsgSizeTooLarge // 訊息過大 +) + +// 詳細代碼 - 特定服務類 08x +const ( + _ = iota + CatService + ArkInternal // Ark 內部錯誤 + ThirdParty + ArkHTTP400 // Ark HTTP 400 錯誤 +) diff --git a/pkg/library/errs/code/messsage.go b/pkg/library/errs/code/messsage.go new file mode 100644 index 0000000..84c9016 --- /dev/null +++ b/pkg/library/errs/code/messsage.go @@ -0,0 +1,13 @@ +package code + +// CatToStr collects general error messages for each Category +// It is used to send back to API caller +var CatToStr = map[uint32]string{ + CatInput: "Invalid Input Data", + CatDB: "Database Error", + CatResource: "Resource Error", + CatGRPC: "Internal Service Communication Error", + CatAuth: "Authentication Error", + CatService: "Internal Service Communication Error", + CatSystem: "System Error", +} diff --git a/pkg/library/errs/code/scope.go b/pkg/library/errs/code/scope.go new file mode 100644 index 0000000..5f35685 --- /dev/null +++ b/pkg/library/errs/code/scope.go @@ -0,0 +1,18 @@ +package code + +// Scope +const ( + Unset uint32 = iota + CloudEPPortalGW + CloudEPMember + CloudEPPermission + CloudEPNotification + CloudEPTweeting + CloudEPOrder + CloudEPFileStorage + CloudEPProduct + CloudEPSecKill + CloudEPCart + CloudEPComment + CloudEPReaction +) diff --git a/pkg/library/errs/easy_func.go b/pkg/library/errs/easy_func.go new file mode 100644 index 0000000..05b4d27 --- /dev/null +++ b/pkg/library/errs/easy_func.go @@ -0,0 +1,535 @@ +package errs + +import ( + "errors" + "fmt" + "strings" + + "backend/pkg/library/errs/code" + "github.com/zeromicro/go-zero/core/logx" + "google.golang.org/grpc/status" +) + +const ( + defaultDetailCode = 00 +) + +func newBuiltinGRPCErr(scope, detail uint32, msg string) *LibError { + return &LibError{ + category: code.CatGRPC, + code: detail, + scope: scope, + msg: msg, + } +} + +// FromError tries to let error as Err +// it supports to unwrap error that has Error +// return nil if failed to transfer +func FromError(err error) *LibError { + if err == nil { + return nil + } + + var e *LibError + if errors.As(err, &e) { + return e + } + + return nil +} + +// FromCode parses code as following 7 碼 +// Decimal: 1200314 +// 12 represents Scope +// 003 represents Category +// 14 represents Detail error code +func FromCode(code uint32) *LibError { + // 獲取 scope,前兩位數 + scope := code / 100000 + + // 獲取 detail,最後兩位數 + detail := code % 100 + + // 獲取 category,中間三位數 + category := (code / 100) % 1000 + + return &LibError{ + category: category * 100, // category 放大為三位數的整百數 + code: category*100 + detail, // 重構完整的 code + scope: scope, + msg: "", + } +} + +// FromGRPCError transfer error to Err +// useful for gRPC client +func FromGRPCError(err error) *LibError { + s, _ := status.FromError(err) + e := FromCode(uint32(s.Code())) + e.msg = s.Message() + + // For GRPC built-in code + if e.Scope() == code.Unset && e.Category() == 0 && e.Code() != code.OK { + e = newBuiltinGRPCErr(Scope, e.Code(), s.Message()) + } + + return e +} + +/*** System ***/ + +// SystemTimeoutError xxx6300 returns Error 系統超時 +func SystemTimeoutError(s ...string) *LibError { + return NewError(Scope, code.SystemTimeoutError, defaultDetailCode, fmt.Sprintf("%s", strings.Join(s, " "))) +} + +// SystemTimeoutErrorL logs error message and returns Err +func SystemTimeoutErrorL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { + e := SystemTimeoutError(s...) + if filed != nil { + l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) + } + l.WithCallerSkip(1).Error(e.Error()) + + return e +} + +// SystemInternalError xxx6100 returns Err struct +func SystemInternalError(s ...string) *LibError { + return NewError(Scope, code.SystemInternalError, defaultDetailCode, fmt.Sprintf("%s", strings.Join(s, " "))) +} + +// SystemInternalErrorL logs error message and returns Err +func SystemInternalErrorL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { + e := SystemInternalError(s...) + if filed != nil || len(filed) >= 0 { + l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) + } + l.WithCallerSkip(1).Error(e.Error()) + + return e +} + +/*** CatInput ***/ + +// InvalidFormat returns Err struct +func InvalidFormat(s ...string) *LibError { + return NewError(Scope, code.InvalidFormat, defaultDetailCode, fmt.Sprintf("%s", strings.Join(s, " "))) +} + +// InvalidFormatL logs error message and returns Err +func InvalidFormatL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { + e := InvalidFormat(s...) + if filed != nil || len(filed) >= 0 { + l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) + } + l.WithCallerSkip(1).Error(e.Error()) + + return e +} + +// InvalidRange returns Err struct +func InvalidRange(s ...string) *LibError { + return NewError(Scope, code.InvalidRange, defaultDetailCode, fmt.Sprintf("%s", strings.Join(s, " "))) +} + +// InvalidRangeL logs error message and returns Err +func InvalidRangeL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { + e := InvalidRange(s...) + if filed != nil || len(filed) >= 0 { + l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) + } + l.WithCallerSkip(1).Error(e.Error()) + + return e +} + +// NotValidImplementation returns Err struct +func NotValidImplementation(s ...string) *LibError { + return NewError(Scope, code.NotValidImplementation, defaultDetailCode, + fmt.Sprintf("%s", strings.Join(s, " "))) +} + +// NotValidImplementationL logs error message and returns Err +func NotValidImplementationL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { + e := NotValidImplementation(s...) + if filed != nil || len(filed) >= 0 { + l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) + } + l.WithCallerSkip(1).Error(e.Error()) + + return e +} + +/*** CatDB ***/ + +// DBError returns Err +func DBError(s ...string) *LibError { + return NewError(Scope, code.DBError, defaultDetailCode, fmt.Sprintf("%s", strings.Join(s, " "))) +} + +// DBErrorL logs error message and returns Err +func DBErrorL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { + e := DBError(s...) + if filed != nil || len(filed) >= 0 { + l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) + } + l.WithCallerSkip(1).Error(e.Error()) + return e +} + +// DBDataConvert returns Err +func DBDataConvert(s ...string) *LibError { + return NewError(Scope, code.DBDataConvert, defaultDetailCode, fmt.Sprintf("%s", strings.Join(s, " "))) +} + +// DBDataConvertL logs error message and returns Err +func DBDataConvertL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { + e := DBDataConvert(s...) + if filed != nil || len(filed) >= 0 { + l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) + } + l.WithCallerSkip(1).Error(e.Error()) + + return e +} + +// DBDuplicate returns Err +func DBDuplicate(s ...string) *LibError { + return NewError(Scope, code.DBDuplicate, defaultDetailCode, + fmt.Sprintf("%s", strings.Join(s, " "))) +} + +// DBDuplicateL logs error message and returns Err +func DBDuplicateL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { + e := DBDuplicate(s...) + if filed != nil || len(filed) >= 0 { + l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) + } + l.WithCallerSkip(1).Error(e.Error()) + + return e +} + +/*** CatResource ***/ + +// ResourceNotFound returns Err and logging +func ResourceNotFound(s ...string) *LibError { + return NewError(Scope, code.ResourceNotFound, defaultDetailCode, + fmt.Sprintf("%s", strings.Join(s, " "))) +} + +// ResourceNotFoundL logs error message and returns Err +func ResourceNotFoundL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { + e := ResourceNotFound(s...) + if filed != nil || len(filed) >= 0 { + l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) + } + l.WithCallerSkip(1).Error(e.Error()) + + return e +} + +// InvalidResourceFormat returns Err +func InvalidResourceFormat(s ...string) *LibError { + return NewError(Scope, code.InvalidResourceFormat, defaultDetailCode, + fmt.Sprintf("%s", strings.Join(s, " "))) +} + +// InvalidResourceFormatL logs error message and returns Err +func InvalidResourceFormatL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { + e := InvalidResourceFormat(s...) + if filed != nil || len(filed) >= 0 { + l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) + } + l.WithCallerSkip(1).Error(e.Error()) + + return e +} + +// InvalidResourceState returns status not correct. +// for example: company should be destroy, agent should be no-sensor/fail-install ... +func InvalidResourceState(s ...string) *LibError { + return NewError(Scope, code.InvalidResourceState, defaultDetailCode, + fmt.Sprintf("%s", strings.Join(s, " "))) +} + +// InvalidResourceStateL logs error message and returns status not correct. +func InvalidResourceStateL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { + e := InvalidResourceState(s...) + if filed != nil || len(filed) >= 0 { + l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) + } + l.WithCallerSkip(1).Error(e.Error()) + + return e +} + +func ResourceInsufficient(s ...string) *LibError { + return NewError(Scope, code.ResourceInsufficient, defaultDetailCode, + fmt.Sprintf("%s", strings.Join(s, " "))) +} + +func ResourceInsufficientL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { + e := ResourceInsufficient(s...) + if filed != nil || len(filed) >= 0 { + l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) + } + l.WithCallerSkip(1).Error(e.Error()) + + return e +} + +// InsufficientPermission returns Err +func InsufficientPermission(s ...string) *LibError { + return NewError(Scope, code.InsufficientPermission, + defaultDetailCode, + fmt.Sprintf("%s", strings.Join(s, " "))) +} + +// InsufficientPermissionL returns Err and log +func InsufficientPermissionL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { + e := InsufficientPermission(s...) + if filed != nil || len(filed) >= 0 { + l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) + } + l.WithCallerSkip(1).Error(e.Error()) + + return e +} + +// ResourceAlreadyExist returns Err +func ResourceAlreadyExist(s ...string) *LibError { + return NewError(Scope, code.ResourceAlreadyExist, defaultDetailCode, + fmt.Sprintf("%s", strings.Join(s, " "))) +} + +// ResourceAlreadyExistL logs error message and returns Err +func ResourceAlreadyExistL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { + e := ResourceAlreadyExist(s...) + if filed != nil || len(filed) >= 0 { + l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) + } + l.WithCallerSkip(1).Error(e.Error()) + + return e +} + +// InvalidMeasurementID returns Err +func InvalidMeasurementID(s ...string) *LibError { + return NewError(Scope, code.InvalidMeasurementID, defaultDetailCode, + fmt.Sprintf("%s", strings.Join(s, " "))) +} + +// InvalidMeasurementIDL logs error message and returns Err +func InvalidMeasurementIDL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { + e := InvalidMeasurementID(s...) + if filed != nil || len(filed) >= 0 { + l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) + } + l.WithCallerSkip(1).Error(e.Error()) + + return e +} + +// ResourceExpired returns Err +func ResourceExpired(s ...string) *LibError { + return NewError(Scope, code.ResourceExpired, + defaultDetailCode, fmt.Sprintf("%s", strings.Join(s, " "))) +} + +// ResourceExpiredL logs error message and returns Err +func ResourceExpiredL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { + e := ResourceExpired(s...) + if filed != nil || len(filed) >= 0 { + l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) + } + l.WithCallerSkip(1).Error(e.Error()) + + return e +} + +// ResourceMigrated returns Err +func ResourceMigrated(s ...string) *LibError { + return NewError(Scope, code.ResourceMigrated, defaultDetailCode, + fmt.Sprintf("%s", strings.Join(s, " "))) +} + +// ResourceMigratedL logs error message and returns Err +func ResourceMigratedL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { + e := ResourceMigrated(s...) + if filed != nil || len(filed) >= 0 { + l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) + } + l.WithCallerSkip(1).Error(e.Error()) + + return e +} + +// InsufficientQuota returns Err +func InsufficientQuota(s ...string) *LibError { + return NewError(Scope, code.InsufficientQuota, defaultDetailCode, + fmt.Sprintf("%s", strings.Join(s, " "))) +} + +// InsufficientQuotaL logs error message and returns Err +func InsufficientQuotaL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { + e := InsufficientQuota(s...) + if filed != nil || len(filed) >= 0 { + l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) + } + l.WithCallerSkip(1).Error(e.Error()) + + return e +} + +/*** CatAuth ***/ + +// Unauthorized returns Err +func Unauthorized(s ...string) *LibError { + return NewError(Scope, code.Unauthorized, defaultDetailCode, + fmt.Sprintf("%s", strings.Join(s, " "))) +} + +// UnauthorizedL logs error message and returns Err +func UnauthorizedL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { + e := Unauthorized(s...) + if filed != nil || len(filed) >= 0 { + l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) + } + l.WithCallerSkip(1).Error(e.Error()) + + return e +} + +// AuthExpired returns Err +func AuthExpired(s ...string) *LibError { + return NewError(Scope, code.AuthExpired, defaultDetailCode, + fmt.Sprintf("%s", strings.Join(s, " "))) +} + +// AuthExpiredL logs error message and returns Err +func AuthExpiredL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { + e := AuthExpired(s...) + if filed != nil || len(filed) >= 0 { + l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) + } + l.WithCallerSkip(1).Error(e.Error()) + + return e +} + +// InvalidPosixTime returns Err +func InvalidPosixTime(s ...string) *LibError { + return NewError(Scope, code.InvalidPosixTime, defaultDetailCode, + fmt.Sprintf("i%s", strings.Join(s, " "))) +} + +// InvalidPosixTimeL logs error message and returns Err +func InvalidPosixTimeL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { + e := InvalidPosixTime(s...) + if filed != nil || len(filed) >= 0 { + l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) + } + l.WithCallerSkip(1).Error(e.Error()) + + return e +} + +// SigAndPayloadNotMatched returns Err +func SigAndPayloadNotMatched(s ...string) *LibError { + return NewError(Scope, code.SigAndPayloadNotMatched, defaultDetailCode, + fmt.Sprintf("%s", strings.Join(s, " "))) +} + +// SigAndPayloadNotMatchedL logs error message and returns Err +func SigAndPayloadNotMatchedL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { + e := SigAndPayloadNotMatched(s...) + if filed != nil || len(filed) >= 0 { + l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) + } + l.WithCallerSkip(1).Error(e.Error()) + + return e +} + +// Forbidden returns Err +func Forbidden(s ...string) *LibError { + return NewError(Scope, code.Forbidden, defaultDetailCode, + fmt.Sprintf("%s", strings.Join(s, " "))) +} + +// ForbiddenL logs error message and returns Err +func ForbiddenL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { + e := Forbidden(s...) + if filed != nil || len(filed) >= 0 { + l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) + } + l.WithCallerSkip(1).Error(e.Error()) + + return e +} + +// IsAuthUnauthorizedError check the err is unauthorized error +func IsAuthUnauthorizedError(err *LibError) bool { + switch err.Code() / 100 { + case code.Unauthorized, code.AuthExpired, code.InvalidPosixTime, + code.SigAndPayloadNotMatched, code.Forbidden, + code.InvalidFormat, code.ResourceNotFound: + return true + default: + return false + } +} + +/*** CatPubSub ***/ + +// Publish returns Err +func Publish(s ...string) *LibError { + return NewError(Scope, code.Publish, defaultDetailCode, + fmt.Sprintf("%s", strings.Join(s, " "))) +} + +// PublishL logs error message and returns Err +func PublishL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { + e := Publish(s...) + if filed != nil || len(filed) >= 0 { + l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) + } + l.WithCallerSkip(1).Error(e.Error()) + return e +} + +// Consume returns Err +func Consume(s ...string) *LibError { + return NewError(Scope, code.Consume, defaultDetailCode, + fmt.Sprintf("%s", strings.Join(s, " "))) +} + +func ConsumeL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { + e := Consume(s...) + if filed != nil || len(filed) >= 0 { + l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) + } + l.WithCallerSkip(1).Error(e.Error()) + + return e +} + +// MsgSizeTooLarge returns Err +func MsgSizeTooLarge(s ...string) *LibError { + return NewError(Scope, code.MsgSizeTooLarge, defaultDetailCode, + fmt.Sprintf("%s", strings.Join(s, " "))) +} + +// MsgSizeTooLargeL logs error message and returns Err +func MsgSizeTooLargeL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { + e := MsgSizeTooLarge(s...) + if filed != nil || len(filed) >= 0 { + l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) + } + l.WithCallerSkip(1).Error(e.Error()) + + return e +} diff --git a/pkg/library/errs/easy_func_test.go b/pkg/library/errs/easy_func_test.go new file mode 100644 index 0000000..5ddcadd --- /dev/null +++ b/pkg/library/errs/easy_func_test.go @@ -0,0 +1,184 @@ +package errs + +import ( + "context" + "testing" + + "backend/pkg/library/errs/code" + "github.com/zeromicro/go-zero/core/logx" +) + +func TestFromError(t *testing.T) { + t.Run("nil error", func(t *testing.T) { + if err := FromError(nil); err != nil { + t.Errorf("expected nil, got %v", err) + } + }) + + t.Run("LibError type", func(t *testing.T) { + libErr := NewError(1, 200, 10, "test error") + if err := FromError(libErr); err != libErr { + t.Errorf("expected %v, got %v", libErr, err) + } + }) +} + +func TestFromCode(t *testing.T) { + tests := []struct { + name string + code uint32 + expected *LibError + }{ + {"valid code", 1200314, NewError(12, 3, 14, "")}, + {"invalid code", 9999999, NewError(99, 999, 99, "")}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := FromCode(tt.code) + if err.FullCode() != tt.expected.FullCode() { + t.Errorf("expected %v, got %v", tt.expected.FullCode(), err.FullCode()) + } + }) + } +} + +func TestSystemTimeoutError(t *testing.T) { + tests := []struct { + name string + input []string + expected string + }{ + {"single string", []string{"timeout"}, "timeout"}, + {"multiple strings", []string{"timeout", "occurred"}, "timeout occurred"}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := SystemTimeoutError(tt.input...) + if err.Error() != tt.expected { + t.Errorf("expected %s, got %s", tt.expected, err.Error()) + } + }) + } +} + +func TestSystemInternalErrorL(t *testing.T) { + tests := []struct { + name string + input []string + }{ + {"internal error", []string{"internal error"}}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ctx := context.TODO() + err := SystemInternalErrorL(logx.WithContext(ctx), nil, tt.input...) + if err.Error() != tt.input[0] { + t.Errorf("expected %s, got %s", tt.input[0], err.Error()) + } + }) + } +} + +func TestInvalidFormatL(t *testing.T) { + mockLogger := logx.WithContext(context.Background()) + tests := []struct { + name string + input []string + expected string + }{ + {"invalid format", []string{"invalid format"}, "invalid format"}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := InvalidFormatL(mockLogger, nil, tt.input...) + if err.Error() != tt.expected { + t.Errorf("expected %s, got %s", tt.expected, err.Error()) + } + }) + } +} + +func TestDBErrorL(t *testing.T) { + mockLogger := logx.WithContext(context.Background()) + tests := []struct { + name string + input []string + expected string + }{ + {"DB error", []string{"DB error"}, "DB error"}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := DBErrorL(mockLogger, nil, tt.input...) + if err.Error() != tt.expected { + t.Errorf("expected %s, got %s", tt.expected, err.Error()) + } + }) + } +} + +func TestResourceNotFoundL(t *testing.T) { + mockLogger := logx.WithContext(context.Background()) + tests := []struct { + name string + input []string + expected string + }{ + {"resource not found", []string{"resource not found"}, "resource not found"}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := ResourceNotFoundL(mockLogger, nil, tt.input...) + if err.Error() != tt.expected { + t.Errorf("expected %s, got %s", tt.expected, err.Error()) + } + }) + } +} + +func TestInsufficientPermissionL(t *testing.T) { + mockLogger := logx.WithContext(context.Background()) + tests := []struct { + name string + input []string + expected string + }{ + {"insufficient permission", []string{"permission denied"}, "permission denied"}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := InsufficientPermissionL(mockLogger, nil, tt.input...) + if err.Error() != tt.expected { + t.Errorf("expected %s, got %s", tt.expected, err.Error()) + } + }) + } +} + +func TestIsAuthUnauthorizedError(t *testing.T) { + tests := []struct { + name string + err *LibError + expected bool + }{ + {"Unauthorized error", NewError(1, code.Unauthorized, 0, ""), true}, + {"AuthExpired error", NewError(1, code.AuthExpired, 0, ""), true}, + {"Other error", NewError(1, code.ArkInternal, 0, ""), false}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + res := IsAuthUnauthorizedError(tt.err) + if res != tt.expected { + t.Errorf("expected %t, got %t", tt.expected, res) + } + }) + } +} diff --git a/pkg/library/errs/error_code.go b/pkg/library/errs/error_code.go new file mode 100644 index 0000000..d5125a4 --- /dev/null +++ b/pkg/library/errs/error_code.go @@ -0,0 +1,88 @@ +package errs + +import ( + "fmt" + "strings" + + "backend/pkg/library/errs/code" + "github.com/zeromicro/go-zero/core/logx" +) + +type ErrorCode uint32 + +func (e ErrorCode) ToUint32() uint32 { + return uint32(e) +} + +func ThirdPartyError(scope uint32, ec ErrorCode, s ...string) *LibError { + return NewError(scope, code.ThirdParty, ec.ToUint32(), fmt.Sprintf("thirty error: %s", strings.Join(s, " "))) +} + +func ThirdPartyErrorL(scope uint32, ec ErrorCode, + l logx.Logger, filed []logx.LogField, s ...string) *LibError { + e := ThirdPartyError(scope, ec, s...) + l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) + + return e +} + +func DatabaseErrorWithScope(scope uint32, ec ErrorCode, s ...string) *LibError { + return NewError(scope, code.DBError, ec.ToUint32(), strings.Join(s, " ")) +} + +func DatabaseErrorWithScopeL(scope uint32, + ec ErrorCode, + l logx.Logger, filed []logx.LogField, s ...string) *LibError { + e := DatabaseErrorWithScope(scope, ec, s...) + l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) + + return e +} + +func ResourceNotFoundWithScope(scope uint32, ec ErrorCode, s ...string) *LibError { + return NewError(scope, code.ResourceNotFound, ec.ToUint32(), fmt.Sprintf("resource not found: %s", strings.Join(s, " "))) +} + +func ResourceNotFoundWithScopeL(scope uint32, ec ErrorCode, + l logx.Logger, filed []logx.LogField, s ...string) *LibError { + e := ResourceNotFoundWithScope(scope, ec, s...) + l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) + + return e +} + +func InvalidRangeWithScope(scope uint32, ec ErrorCode, s ...string) *LibError { + return NewError(scope, code.CatInput, ec.ToUint32(), fmt.Sprintf("invalid range: %s", strings.Join(s, " "))) +} + +func InvalidRangeWithScopeL(scope uint32, ec ErrorCode, + l logx.Logger, filed []logx.LogField, s ...string) *LibError { + e := InvalidRangeWithScope(scope, ec, s...) + l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) + + return e +} + +func InvalidFormatWithScope(scope uint32, s ...string) *LibError { + return NewError(scope, code.CatInput, code.InvalidFormat, fmt.Sprintf("invalid range: %s", strings.Join(s, " "))) +} + +func InvalidFormatWithScopeL(scope uint32, + l logx.Logger, filed []logx.LogField, s ...string) *LibError { + e := InvalidFormatWithScope(scope, s...) + l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) + + return e +} + +func ForbiddenWithScope(scope uint32, ec ErrorCode, s ...string) *LibError { + return NewError(scope, code.Forbidden, ec.ToUint32(), fmt.Sprintf("forbidden: %s", strings.Join(s, " "))) +} + +func ForbiddenWithScopeL(scope uint32, ec ErrorCode, + l logx.Logger, filed []logx.LogField, s ...string) *LibError { + e := ForbiddenWithScope(scope, ec, s...) + l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) + + return e +} diff --git a/pkg/library/errs/errors.go b/pkg/library/errs/errors.go new file mode 100644 index 0000000..03a89f2 --- /dev/null +++ b/pkg/library/errs/errors.go @@ -0,0 +1,214 @@ +package errs + +import ( + "errors" + "fmt" + "net/http" + + "backend/pkg/library/errs/code" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +// Scope 全域變數應由服務或模組設置 +var Scope = code.Unset + +// LibError 7 碼,服務 2 碼,詳細錯誤 2 碼 ,Cat 3 碼 不參與,獨立的 code 組成為( 000 category + 00 detail) +type LibError struct { + scope uint32 // 系統代號,*100000 來操作,顯示時不夠會補足 7 位數, Library 定義 -> 輸入時都只要輸入兩位數 + category uint32 // 類別代碼 Library 定義 -> 不客製化業務訊息時,用這個大類別來給錯誤 3 碼 + code uint32 // 細項 ,每個 repo 裡自行定義 -> 一萬以下都可以 2 碼 + msg string // 顯示用的,給前端看的 Msg + internalErr error // 紀錄且包含真正的錯誤,通常用這個 +} + +// Error 是錯誤的介面 +// 私有屬性 "displayMsg" 的 getter 函數,這邊只顯示業務邏輯錯誤,因為可能會帶出去給客戶端 +// 要如何定位系統真的發生什麼錯?請使用 internalErr 來做定位,通常是會印 Log 的所以用這個 +func (e *LibError) Error() string { + if e == nil { + return "" + } + + return e.msg +} + +// Category 私有屬性 "category" 的 getter 函數 +func (e *LibError) Category() uint32 { + if e == nil { + return 0 + } + + return e.category +} + +// Scope 私有屬性 "scope" 的 getter 函數 +func (e *LibError) Scope() uint32 { + if e == nil { + return code.Unset + } + + return e.scope +} + +// Code 私有屬性 "code" 的 getter 函數 +func (e *LibError) Code() uint32 { + if e == nil { + return code.OK + } + + return e.code +} + +func (e *LibError) FullCode() uint32 { + if e == nil { + return 0 + } + + return e.Scope()*100000 + e.Code() +} + +// DisplayErrorCode 要顯示的 Error Code +func (e *LibError) DisplayErrorCode() string { + if e == nil { + return "000000" + } + + return fmt.Sprintf("%06d", e.FullCode()) +} + +// InternalError 帶入真正的 error +func (e *LibError) InternalError() error { + var err error = fmt.Errorf("failed to get internal error") + if e == nil { + return err + } + + if e.internalErr != nil { + err = e.internalErr + } + + return err +} + +// GeneralError 轉換 category 級別錯誤訊息,模糊化 +func (e *LibError) GeneralError() string { + if e == nil { + return "" + } + + errStr, ok := code.CatToStr[e.Category()] + if !ok { + return "" + } + + return errStr +} + +// Is 在執行 errors.Is() 時調用。 +// 除非你非常確定你在做什麼,否則不要直接使用這個函數。 +// 請使用 errors.Is 代替。 +// 此函數比較兩個錯誤變量是否都是 *Err,並且具有相同的 code(不檢查包裹的內部錯誤) +func (e *LibError) Is(f error) bool { + var err *LibError + ok := errors.As(f, &err) + if !ok { + return false + } + + return e.Code() == err.Code() +} + +// Unwrap 返回底層錯誤 +// 解除包裹錯誤的結果本身可能具有 Unwrap 方法; +// 我們稱通過反覆解除包裹產生的錯誤序列為錯誤鏈。 +func (e *LibError) Unwrap() error { + if e == nil { + return nil + } + + return e.internalErr +} + +// Wrap 將內部錯誤設置到 Err 結構 +func (e *LibError) Wrap(internalErr error) *LibError { + if e != nil { + e.internalErr = internalErr + } + + return e +} + +func (e *LibError) GRPCStatus() *status.Status { + if e == nil { + return status.New(codes.OK, "") + } + + return status.New(codes.Code(e.FullCode()), e.Error()) +} + +// HTTPStatus 返回對應的 HTTP 狀態碼 +func (e *LibError) HTTPStatus() int { + // 如果錯誤為空或錯誤碼為 OK,則返回 200 狀態碼 + if e == nil || e.Code() == code.OK { + return http.StatusOK + } + // 根據錯誤碼判斷對應的 HTTP 狀態碼 + switch e.Code() % 100 { + case code.ResourceInsufficient: + // 如果資源不足,返回 400 狀態碼 + return http.StatusBadRequest + case code.Unauthorized, code.InsufficientPermission: + // 如果未授權或權限不足,返回 401 狀態碼 + return http.StatusUnauthorized + case code.InsufficientQuota: + // 如果配額不足,返回 402 狀態碼 + return http.StatusPaymentRequired + case code.InvalidPosixTime, code.Forbidden: + // 如果時間無效或禁止訪問,返回 403 狀態碼 + return http.StatusForbidden + case code.ResourceNotFound: + // 如果資源未找到,返回 404 狀態碼 + return http.StatusNotFound + case code.ResourceAlreadyExist, code.InvalidResourceState: + // 如果資源已存在或狀態無效,返回 409 狀態碼 + return http.StatusConflict + case code.NotValidImplementation: + // 如果實現無效,返回 501 狀態碼 + return http.StatusNotImplemented + default: + // 如果沒有匹配的錯誤碼,則繼續下一步 + } + + // 根據錯誤的類別判斷對應的 HTTP 狀態碼 + switch e.Category() { + case code.CatInput: + // 如果錯誤屬於輸入錯誤類別,返回 400 狀態碼 + return http.StatusBadRequest + default: + // 如果沒有符合的條件,返回 500 狀態碼 + return http.StatusInternalServerError + } +} + +// NewError 創建新的 Error +// 確保 category 在 0 到 999 之間,將超出的 category 設為最大值 999 +// 確保 detail 在 0 到 99 之間,將超出的 detail 設為最大值 99 +func NewError(scope, category, detail uint32, displayMsg string) *LibError { + // 確保 category 在 0 到 999 之間 + if category > 999 { + category = 999 // 將超出的 category 設為最大值 999 + } + + // 確保 detail 在 0 到 99 之間 + if detail > 99 { + detail = 99 // 將超出的 detail 設為最大值 99 + } + + return &LibError{ + category: category, + code: category*100 + detail, + scope: scope, + msg: displayMsg, + } +} diff --git a/pkg/library/errs/errors_test.go b/pkg/library/errs/errors_test.go new file mode 100644 index 0000000..15e1f1e --- /dev/null +++ b/pkg/library/errs/errors_test.go @@ -0,0 +1,177 @@ +package errs + +import ( + "errors" + "net/http" + "testing" + + "backend/pkg/library/errs/code" + "google.golang.org/grpc/codes" +) + +func TestNewError(t *testing.T) { + tests := []struct { + name string + scope uint32 + category uint32 + detail uint32 + displayMsg string + expectedMsg string + expectedCat uint32 + expectedDet uint32 + }{ + {"valid error", 1, 200, 10, "test error", "test error", 200, 20010}, + {"category overflow", 1, 1000, 10, "test error", "test error", 999, 99910}, + {"detail overflow", 1, 200, 150, "test error", "test error", 200, 20099}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := NewError(tt.scope, tt.category, tt.detail, tt.displayMsg) + if err.Error() != tt.expectedMsg { + t.Errorf("expected %s, got %s", tt.expectedMsg, err.Error()) + } + if err.Category() != tt.expectedCat { + t.Errorf("expected category %d, got %d", tt.expectedCat, err.Category()) + } + if err.Code() != tt.expectedDet { + t.Errorf("expected code %d, got %d", tt.expectedDet, err.Code()) + } + }) + } +} + +func TestLibError_FullCode(t *testing.T) { + tests := []struct { + name string + scope uint32 + category uint32 + detail uint32 + expectedCode uint32 + }{ + {"valid code", 1, 200, 10, 120010}, + {"category overflow", 1, 1000, 10, 199910}, + {"detail overflow", 1, 200, 150, 120099}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := NewError(tt.scope, tt.category, tt.detail, "test") + if err.FullCode() != tt.expectedCode { + t.Errorf("expected %d, got %d", tt.expectedCode, err.FullCode()) + } + }) + } +} + +func TestLibError_HTTPStatus(t *testing.T) { + tests := []struct { + name string + err *LibError + expected int + }{ + {"bad request", NewError(1, code.CatService, code.ResourceInsufficient, "bad request"), http.StatusBadRequest}, + {"unauthorized", NewError(1, code.CatAuth, code.Unauthorized, "unauthorized"), http.StatusUnauthorized}, + {"forbidden", NewError(1, code.CatAuth, code.Forbidden, "forbidden"), http.StatusForbidden}, + {"not found", NewError(1, code.CatResource, code.ResourceNotFound, "not found"), http.StatusNotFound}, + {"internal server error", NewError(1, code.CatDB, 1095, "not found"), http.StatusInternalServerError}, + {"input err", NewError(1, code.CatInput, 1095, "not found"), http.StatusBadRequest}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if status := tt.err.HTTPStatus(); status != tt.expected { + t.Errorf("expected %d, got %d", tt.expected, status) + } + }) + } +} + +func TestLibError_Error(t *testing.T) { + err := NewError(0, 100, 5, "test error") + expected := "test error" + if err.Error() != expected { + t.Errorf("expected '%s', got '%s'", expected, err.Error()) + } +} + +func TestLibError_Is(t *testing.T) { + err1 := NewError(0, 1, 1, "error 1") + err2 := NewError(0, 1, 1, "error 2") + err3 := errors.New("other error") + + if !err1.Is(err2) { + t.Error("expected errors to be equal") + } + + if err1.Is(err3) { + t.Error("expected errors to not be equal") + } +} + +func TestLibError_DisplayErrorCode(t *testing.T) { + tests := []struct { + name string + err *LibError + expected string + }{ + {"valid code", NewError(1, 200, 10, "test error"), "120010"}, + {"nil error", nil, "000000"}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if code := tt.err.DisplayErrorCode(); code != tt.expected { + t.Errorf("expected %s, got %s", tt.expected, code) + } + }) + } +} + +func TestLibError_Unwrap(t *testing.T) { + originalErr := errors.New("original error") + libErr := NewError(0, 1, 1, "wrapped error").Wrap(originalErr) + + if unwrappedErr := libErr.Unwrap(); unwrappedErr != originalErr { + t.Errorf("expected original error, got %v", unwrappedErr) + } +} + +func TestLibError_InternalError(t *testing.T) { + tests := []struct { + name string + internalErr error + expected error + }{ + {"valid internal error", errors.New("internal"), errors.New("internal")}, + {"nil internal error", nil, errors.New("failed to get internal error")}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := NewError(1, 200, 10, "test").Wrap(tt.internalErr) + if internalErr := err.InternalError(); internalErr.Error() != tt.expected.Error() { + t.Errorf("expected %v, got %v", tt.expected, internalErr) + } + }) + } +} + +func TestLibError_GRPCStatus(t *testing.T) { + tests := []struct { + name string + err *LibError + expected codes.Code + }{ + {"valid GRPC status", NewError(1, 200, 10, "test error"), codes.Code(120010)}, + {"nil error", nil, codes.OK}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if status := tt.err.GRPCStatus().Code(); status != tt.expected { + t.Errorf("expected %d, got %d", tt.expected, status) + } + }) + } +} diff --git a/pkg/member/domain/errors.go b/pkg/member/domain/errors.go index 459ddcd..45641c2 100644 --- a/pkg/member/domain/errors.go +++ b/pkg/member/domain/errors.go @@ -1,6 +1,6 @@ package domain -import "code.30cm.net/digimon/library-go/errs" +import "backend/pkg/library/errs" // Verify Error Code const ( diff --git a/pkg/member/usecase/binding.go b/pkg/member/usecase/binding.go index a3afc63..5966624 100644 --- a/pkg/member/usecase/binding.go +++ b/pkg/member/usecase/binding.go @@ -9,8 +9,8 @@ import ( "backend/pkg/member/domain/entity" "backend/pkg/member/domain/usecase" - "code.30cm.net/digimon/library-go/errs" - "code.30cm.net/digimon/library-go/errs/code" + "backend/pkg/library/errs" + "backend/pkg/library/errs/code" "github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/stores/mon" ) diff --git a/pkg/member/usecase/generate.go b/pkg/member/usecase/generate.go index 887be46..93c68f6 100644 --- a/pkg/member/usecase/generate.go +++ b/pkg/member/usecase/generate.go @@ -7,8 +7,8 @@ import ( "backend/pkg/member/domain" "backend/pkg/member/domain/entity" - "code.30cm.net/digimon/library-go/errs" - "code.30cm.net/digimon/library-go/errs/code" + "backend/pkg/library/errs" + "backend/pkg/library/errs/code" GIDLib "code.30cm.net/digimon/library-go/utils/invited_code" "github.com/zeromicro/go-zero/core/logx" ) diff --git a/pkg/member/usecase/member.go b/pkg/member/usecase/member.go index a57c1f8..f8390e1 100644 --- a/pkg/member/usecase/member.go +++ b/pkg/member/usecase/member.go @@ -13,8 +13,8 @@ import ( "backend/pkg/member/domain/repository" "backend/pkg/member/domain/usecase" - "code.30cm.net/digimon/library-go/errs" - "code.30cm.net/digimon/library-go/errs/code" + "backend/pkg/library/errs" + "backend/pkg/library/errs/code" "github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/stores/mon" ) diff --git a/pkg/member/usecase/member_test.go b/pkg/member/usecase/member_test.go index 5a05ba2..b355b05 100644 --- a/pkg/member/usecase/member_test.go +++ b/pkg/member/usecase/member_test.go @@ -13,8 +13,8 @@ import ( mockRepo "backend/pkg/member/mock/repository" "backend/pkg/member/repository" - "code.30cm.net/digimon/library-go/errs" - "code.30cm.net/digimon/library-go/errs/code" + "backend/pkg/library/errs" + "backend/pkg/library/errs/code" "github.com/stretchr/testify/assert" "github.com/zeromicro/go-zero/core/stores/mon" "go.uber.org/mock/gomock" diff --git a/pkg/member/usecase/verify.go b/pkg/member/usecase/verify.go index 51f93ba..6fc8198 100644 --- a/pkg/member/usecase/verify.go +++ b/pkg/member/usecase/verify.go @@ -8,8 +8,8 @@ import ( "backend/pkg/member/domain/member" "backend/pkg/member/domain/usecase" - "code.30cm.net/digimon/library-go/errs" - "code.30cm.net/digimon/library-go/errs/code" + "backend/pkg/library/errs" + "backend/pkg/library/errs/code" ) func (use *MemberUseCase) GenerateRefreshCode(ctx context.Context, param usecase.GenerateRefreshCodeRequest) (usecase.GenerateRefreshCodeResponse, error) { diff --git a/pkg/member/usecase/verify_google.go b/pkg/member/usecase/verify_google.go index 4e0235c..7acaedc 100644 --- a/pkg/member/usecase/verify_google.go +++ b/pkg/member/usecase/verify_google.go @@ -13,8 +13,8 @@ import ( "backend/pkg/member/domain" "backend/pkg/member/domain/usecase" - "code.30cm.net/digimon/library-go/errs" - "code.30cm.net/digimon/library-go/errs/code" + "backend/pkg/library/errs" + "backend/pkg/library/errs/code" ) func (use *MemberUseCase) VerifyGoogleAuthResult(ctx context.Context, req usecase.VerifyAuthResultRequest) (usecase.GoogleTokenInfo, error) { diff --git a/pkg/member/usecase/verify_google_test.go b/pkg/member/usecase/verify_google_test.go index eaa24b9..bfe6dab 100644 --- a/pkg/member/usecase/verify_google_test.go +++ b/pkg/member/usecase/verify_google_test.go @@ -8,8 +8,8 @@ import ( "backend/pkg/member/domain" "backend/pkg/member/domain/usecase" - "code.30cm.net/digimon/library-go/errs" - "code.30cm.net/digimon/library-go/errs/code" + "backend/pkg/library/errs" + "backend/pkg/library/errs/code" "github.com/stretchr/testify/assert" ) diff --git a/pkg/member/usecase/verify_line.go b/pkg/member/usecase/verify_line.go index 9300ed5..5849fdf 100644 --- a/pkg/member/usecase/verify_line.go +++ b/pkg/member/usecase/verify_line.go @@ -11,8 +11,8 @@ import ( "backend/pkg/member/domain" "backend/pkg/member/domain/usecase" - "code.30cm.net/digimon/library-go/errs" - "code.30cm.net/digimon/library-go/errs/code" + "backend/pkg/library/errs" + "backend/pkg/library/errs/code" ) // LineCodeToAccessToken 透過 Line 授權碼換取 Access Token diff --git a/pkg/member/usecase/verify_test.go b/pkg/member/usecase/verify_test.go index f2e692e..db24859 100644 --- a/pkg/member/usecase/verify_test.go +++ b/pkg/member/usecase/verify_test.go @@ -11,7 +11,7 @@ import ( "backend/pkg/member/domain/usecase" mockRepo "backend/pkg/member/mock/repository" - "code.30cm.net/digimon/library-go/errs" + "backend/pkg/library/errs" "github.com/stretchr/testify/assert" "go.uber.org/mock/gomock" )