diff options
Diffstat (limited to 'utils/shortcuts')
| -rw-r--r-- | utils/shortcuts/error.go | 65 | ||||
| -rw-r--r-- | utils/shortcuts/functions.go | 97 | ||||
| -rw-r--r-- | utils/shortcuts/redirect.go | 25 | ||||
| -rw-r--r-- | utils/shortcuts/render.go | 22 |
4 files changed, 209 insertions, 0 deletions
diff --git a/utils/shortcuts/error.go b/utils/shortcuts/error.go new file mode 100644 index 0000000..71fa4bd --- /dev/null +++ b/utils/shortcuts/error.go @@ -0,0 +1,65 @@ +package shortcuts + +import ( + "dove/enums" + "dove/types" + + "github.com/gofiber/fiber/v2" +) + +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, +} + +func ServiceError(kind enums.ErrorKind, message string) *types.ServiceError { + return &types.ServiceError{ + Kind: kind, + Message: message, + } +} + +func HandleError(context *fiber.Ctx, serviceError *types.ServiceError) error { + statusCode, exists := statusMap[serviceError.Kind] + if !exists { + statusCode = fiber.StatusInternalServerError + } + + return RenderWithStatus(context, "error", fiber.Map{ + "ErrorMessage": serviceError.Message, + }, statusCode) +} + +func BadRequest(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 { + return RenderWithStatus(context, "error", fiber.Map{ + "ErrorMessage": err.Error(), + }, fiber.StatusForbidden) +} + +func InternalServerError(context *fiber.Ctx, err error) error { + return RenderWithStatus(context, "error", fiber.Map{ + "ErrorMessage": err.Error(), + }, fiber.StatusInternalServerError) +} + +func NotFound(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 { + return RenderWithStatus(context, "error", fiber.Map{ + "ErrorMessage": err.Error(), + }, fiber.StatusUnauthorized) +} diff --git a/utils/shortcuts/functions.go b/utils/shortcuts/functions.go new file mode 100644 index 0000000..df00dcf --- /dev/null +++ b/utils/shortcuts/functions.go @@ -0,0 +1,97 @@ +package shortcuts + +import ( + "maps" + "reflect" + "strings" + + "dove/messages" + "dove/utils/errors" + + "github.com/gofiber/fiber/v2" +) + +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/redirect.go b/utils/shortcuts/redirect.go new file mode 100644 index 0000000..627538d --- /dev/null +++ b/utils/shortcuts/redirect.go @@ -0,0 +1,25 @@ +package shortcuts + +import ( + "dove/utils/urls" + + "github.com/gofiber/fiber/v2" +) + +func Redirect(context *fiber.Ctx, routeName string) error { + fullPath, exists := urls.GetFullPath(routeName) + if !exists { + return fiber.ErrNotFound + } + + return context.Redirect(fullPath) +} + +func RedirectWithStatus(context *fiber.Ctx, routeName string, statusCode int) error { + fullPath, exists := urls.GetFullPath(routeName) + if !exists { + return fiber.ErrNotFound + } + + return context.Redirect(fullPath, statusCode) +}
\ No newline at end of file diff --git a/utils/shortcuts/render.go b/utils/shortcuts/render.go new file mode 100644 index 0000000..29c7a8f --- /dev/null +++ b/utils/shortcuts/render.go @@ -0,0 +1,22 @@ +package shortcuts + +import "github.com/gofiber/fiber/v2" + +func Render(context *fiber.Ctx, templateName string, data any) error { + templateData := make(fiber.Map) + + mergeContextValues(context, templateData) + + if data != nil { + if mergeError := mergeBindData(templateData, data); mergeError != nil { + return mergeError + } + } + + return context.Render(templateName, templateData) +} + +func RenderWithStatus(context *fiber.Ctx, templateName string, data any, statusCode int) error { + context.Status(statusCode) + return Render(context, templateName, data) +} |
