From 76fce15e32ec53c3894abf91aa92779682c9f5aa Mon Sep 17 00:00:00 2001 From: jdl Date: Sat, 13 Jun 2026 14:46:55 +0200 Subject: [PATCH] WIP --- hub/errs/db.go | 33 +++++++++++++++++++++++++++ hub/errs/types.go | 57 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 hub/errs/db.go create mode 100644 hub/errs/types.go diff --git a/hub/errs/db.go b/hub/errs/db.go new file mode 100644 index 0000000..85e4b61 --- /dev/null +++ b/hub/errs/db.go @@ -0,0 +1,33 @@ +package errs + +import ( + "database/sql" + "errors" + "log" + + sqlite3 "github.com/mattn/go-sqlite3" +) + +func DB(err error) error { + if err == nil { + return nil + } + + if _, ok := err.(*Error); ok { + return err + } + + if err == sql.ErrNoRows { + return ErrNotFound + } + + var se sqlite3.Error + if errors.As(err, &se) { + switch se.ExtendedCode { + case sqlite3.ErrConstraintUnique, sqlite3.ErrConstraintPrimaryKey: + return ErrAlreadyExists + } + } + log.Printf("Unexpected error: %v", err) + return ErrUnexpected +} diff --git a/hub/errs/types.go b/hub/errs/types.go new file mode 100644 index 0000000..fbd9cf7 --- /dev/null +++ b/hub/errs/types.go @@ -0,0 +1,57 @@ +package errs + +import ( + "fmt" + "net/http" +) + +type Error struct { + Code int + Msg string +} + +func (e *Error) Error() string { + return fmt.Sprintf("[%d] %s", e.Code, e.Msg) +} + +var ( + ErrUnexpected = Internal.WithMsg("Unexpected internal error.") + ErrNotFound = NotFound.WithMsg("Not found.") + ErrAlreadyExists = Conflict.WithMsg("AlreadyExists.") + + // Validation errors. + ErrInvalidIP = BadRequest.WithMsg("Invalid IP.") + ErrInvalidPeerIP = BadRequest.WithMsg("Invalid peer IP.") + ErrNonPrivateIP = BadRequest.WithMsg("Non-private IP.") + ErrInvalidPort = BadRequest.WithMsg("Invalid port.") + ErrInvalidNetName = BadRequest.WithMsg("Invalid network name.") + ErrNetNameNotLocal = BadRequest.WithMsg("Network name must end with .local.") + ErrInvalidPeerName = BadRequest.WithMsg("Invalid peer name.") +) + +// ---------------------------------------------------------------------------- + +type Type struct { + Code int + Msg string +} + +func (t Type) WithErr(err error) *Error { + return &Error{Code: t.Code, Msg: err.Error()} +} + +func (t Type) WithMsg(msg string) *Error { + return &Error{Code: t.Code, Msg: msg} +} + +func (t Type) WithMsgf(msg string, args ...any) *Error { + return &Error{Code: t.Code, Msg: fmt.Sprintf(msg, args...)} +} + +var ( + Internal = Type{Code: http.StatusInternalServerError} + NotAuthorized = Type{Code: http.StatusUnauthorized} + NotFound = Type{Code: http.StatusNotFound} + BadRequest = Type{Code: http.StatusBadRequest} + Conflict = Type{Code: http.StatusConflict} +)