diff options
Diffstat (limited to 'utils/shortcuts')
| -rw-r--r-- | utils/shortcuts/error.go | 51 | ||||
| -rw-r--r-- | utils/shortcuts/functions.go | 110 | ||||
| -rw-r--r-- | utils/shortcuts/messages.go | 5 | ||||
| -rw-r--r-- | utils/shortcuts/render.go | 108 |
4 files changed, 145 insertions, 129 deletions
diff --git a/utils/shortcuts/error.go b/utils/shortcuts/error.go index 71fa4bd..c22e6b2 100644 --- a/utils/shortcuts/error.go +++ b/utils/shortcuts/error.go @@ -1,29 +1,44 @@ package shortcuts -import ( - "dove/enums" - "dove/types" +import "github.com/gofiber/fiber/v2" - "github.com/gofiber/fiber/v2" +type ErrorKind string + +const ( + BadRequest ErrorKind = "bad_request" + Forbidden ErrorKind = "forbidden" + Internal ErrorKind = "internal" + NotFound ErrorKind = "not_found" + Unauthorized ErrorKind = "unauthorized" + Unprocessable ErrorKind = "unprocessable" ) -var statusMap = map[enums.ErrorKind]int{ - enums.BadRequest: fiber.StatusBadRequest, - enums.Forbidden: fiber.StatusForbidden, - enums.Internal: fiber.StatusInternalServerError, - enums.NotFound: fiber.StatusNotFound, - enums.Unauthorized: fiber.StatusUnauthorized, - enums.Unprocessable: fiber.StatusUnprocessableEntity, +type Error struct { + Kind ErrorKind + Message string +} + +func (self *Error) Error() string { + return self.Message +} + +var statusMap = map[ErrorKind]int{ + BadRequest: fiber.StatusBadRequest, + Forbidden: fiber.StatusForbidden, + Internal: fiber.StatusInternalServerError, + NotFound: fiber.StatusNotFound, + Unauthorized: fiber.StatusUnauthorized, + Unprocessable: fiber.StatusUnprocessableEntity, } -func ServiceError(kind enums.ErrorKind, message string) *types.ServiceError { - return &types.ServiceError{ +func ServiceError(kind ErrorKind, message string) *Error { + return &Error{ Kind: kind, Message: message, } } -func HandleError(context *fiber.Ctx, serviceError *types.ServiceError) error { +func HandleError(context *fiber.Ctx, serviceError *Error) error { statusCode, exists := statusMap[serviceError.Kind] if !exists { statusCode = fiber.StatusInternalServerError @@ -34,13 +49,13 @@ func HandleError(context *fiber.Ctx, serviceError *types.ServiceError) error { }, statusCode) } -func BadRequest(context *fiber.Ctx, err error) error { +func BadRequestError(context *fiber.Ctx, err error) error { return RenderWithStatus(context, "error", fiber.Map{ "ErrorMessage": err.Error(), }, fiber.StatusBadRequest) } -func Forbidden(context *fiber.Ctx, err error) error { +func ForbiddenError(context *fiber.Ctx, err error) error { return RenderWithStatus(context, "error", fiber.Map{ "ErrorMessage": err.Error(), }, fiber.StatusForbidden) @@ -52,13 +67,13 @@ func InternalServerError(context *fiber.Ctx, err error) error { }, fiber.StatusInternalServerError) } -func NotFound(context *fiber.Ctx, err error) error { +func NotFoundError(context *fiber.Ctx, err error) error { return RenderWithStatus(context, "error", fiber.Map{ "ErrorMessage": err.Error(), }, fiber.StatusNotFound) } -func Unauthorized(context *fiber.Ctx, err error) error { +func UnauthorizedError(context *fiber.Ctx, err error) error { return RenderWithStatus(context, "error", fiber.Map{ "ErrorMessage": err.Error(), }, fiber.StatusUnauthorized) diff --git a/utils/shortcuts/functions.go b/utils/shortcuts/functions.go deleted file mode 100644 index 3e76a9a..0000000 --- a/utils/shortcuts/functions.go +++ /dev/null @@ -1,110 +0,0 @@ -package shortcuts - -import ( - "fmt" - "maps" - "path" - "reflect" - "strings" - - "dove/messages" - "dove/utils/errors" - - "github.com/gofiber/fiber/v2" -) - -func resolveTemplate(context *fiber.Ctx, templateName string) string { - switch { - case context.Get("HX-Request") == "true" && context.Get("HX-Boosted") != "true": - directory := path.Dir(templateName) - filename := path.Base(templateName) - return fmt.Sprintf("%s/htmx/%s.htmx", directory, filename) - default: - return templateName - } -} - -func mergeContextValues(context *fiber.Ctx, targetMap fiber.Map) { - context.Context().VisitUserValues(func(key []byte, value any) { - targetMap[string(key)] = value - }) -} - -func mergeBindData(targetMap fiber.Map, data any) error { - normalizedData, normalizeError := normalizeToMap(data) - if normalizeError != nil { - return normalizeError - } - - maps.Copy(targetMap, normalizedData) - return nil -} - -func normalizeToMap(data any) (fiber.Map, error) { - switch typedData := data.(type) { - case fiber.Map: - return typedData, nil - case map[string]any: - return fiber.Map(typedData), nil - default: - return convertStructToMap(data) - } -} - -func convertStructToMap(data any) (fiber.Map, error) { - structValue := reflect.ValueOf(data) - - switch structValue.Kind() { - case reflect.Pointer: - structValue = structValue.Elem() - } - - switch structValue.Kind() { - case reflect.Struct: - return extractStructFields(structValue), nil - default: - return nil, errors.Error(messages.ShortcutUnsupportedBindType) - } -} - -func extractStructFields(structValue reflect.Value) fiber.Map { - structType := structValue.Type() - fieldMap := make(fiber.Map, structValue.NumField()) - - for fieldIndex := range structType.NumField() { - fieldDescriptor := structType.Field(fieldIndex) - - if !fieldDescriptor.IsExported() { - continue - } - - fieldKey := resolveFieldKey(fieldDescriptor) - fieldMap[fieldKey] = structValue.Field(fieldIndex).Interface() - } - - return fieldMap -} - -func resolveFieldKey(fieldDescriptor reflect.StructField) string { - jsonTag := fieldDescriptor.Tag.Get("json") - - switch { - case jsonTag == "" || jsonTag == "-": - return fieldDescriptor.Name - default: - return extractTagName(jsonTag, fieldDescriptor.Name) - } -} - -func extractTagName(jsonTag string, fallbackName string) string { - separatorIndex := strings.IndexByte(jsonTag, ',') - - switch { - case separatorIndex < 0: - return jsonTag - case separatorIndex > 0: - return jsonTag[:separatorIndex] - default: - return fallbackName - } -}
\ No newline at end of file diff --git a/utils/shortcuts/messages.go b/utils/shortcuts/messages.go new file mode 100644 index 0000000..92df139 --- /dev/null +++ b/utils/shortcuts/messages.go @@ -0,0 +1,5 @@ +package shortcuts + +const ( + UnsupportedBindType = "Bind data must be a struct, *struct, fiber.Map, or map[string]any." +) diff --git a/utils/shortcuts/render.go b/utils/shortcuts/render.go index e91ccfa..89779cf 100644 --- a/utils/shortcuts/render.go +++ b/utils/shortcuts/render.go @@ -1,6 +1,16 @@ package shortcuts -import "github.com/gofiber/fiber/v2" +import ( + "fmt" + "maps" + "path" + "reflect" + "strings" + + "dove/utils/errors" + + "github.com/gofiber/fiber/v2" +) func Render(context *fiber.Ctx, templateName string, data any) error { templateData := make(fiber.Map) @@ -20,3 +30,99 @@ func RenderWithStatus(context *fiber.Ctx, templateName string, data any, statusC context.Status(statusCode) return Render(context, templateName, data) } + +func resolveTemplate(context *fiber.Ctx, templateName string) string { + switch { + case context.Get("HX-Request") == "true" && context.Get("HX-Boosted") != "true": + directory := path.Dir(templateName) + filename := path.Base(templateName) + return fmt.Sprintf("%s/htmx/%s.htmx", directory, filename) + default: + return templateName + } +} + +func mergeContextValues(context *fiber.Ctx, targetMap fiber.Map) { + context.Context().VisitUserValues(func(key []byte, value any) { + targetMap[string(key)] = value + }) +} + +func mergeBindData(targetMap fiber.Map, data any) error { + normalizedData, normalizeError := normalizeToMap(data) + if normalizeError != nil { + return normalizeError + } + + maps.Copy(targetMap, normalizedData) + return nil +} + +func normalizeToMap(data any) (fiber.Map, error) { + switch typedData := data.(type) { + case fiber.Map: + return typedData, nil + case map[string]any: + return fiber.Map(typedData), nil + default: + return convertStructToMap(data) + } +} + +func convertStructToMap(data any) (fiber.Map, error) { + structValue := reflect.ValueOf(data) + + switch structValue.Kind() { + case reflect.Pointer: + structValue = structValue.Elem() + } + + switch structValue.Kind() { + case reflect.Struct: + return extractStructFields(structValue), nil + default: + return nil, errors.Error(UnsupportedBindType) + } +} + +func extractStructFields(structValue reflect.Value) fiber.Map { + structType := structValue.Type() + fieldMap := make(fiber.Map, structValue.NumField()) + + for fieldIndex := range structType.NumField() { + fieldDescriptor := structType.Field(fieldIndex) + + if !fieldDescriptor.IsExported() { + continue + } + + fieldKey := resolveFieldKey(fieldDescriptor) + fieldMap[fieldKey] = structValue.Field(fieldIndex).Interface() + } + + return fieldMap +} + +func resolveFieldKey(fieldDescriptor reflect.StructField) string { + jsonTag := fieldDescriptor.Tag.Get("json") + + switch { + case jsonTag == "" || jsonTag == "-": + return fieldDescriptor.Name + default: + return extractTagName(jsonTag, fieldDescriptor.Name) + } +} + +func extractTagName(jsonTag string, fallbackName string) string { + separatorIndex := strings.IndexByte(jsonTag, ',') + + switch { + case separatorIndex < 0: + return jsonTag + case separatorIndex > 0: + return jsonTag[:separatorIndex] + default: + return fallbackName + } +} |
