summaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
Diffstat (limited to 'utils')
-rw-r--r--utils/shortcuts/error.go25
-rw-r--r--utils/shortcuts/flash.go31
-rw-r--r--utils/shortcuts/helpers.go111
-rw-r--r--utils/shortcuts/redirect.go36
-rw-r--r--utils/shortcuts/render.go28
5 files changed, 231 insertions, 0 deletions
diff --git a/utils/shortcuts/error.go b/utils/shortcuts/error.go
new file mode 100644
index 0000000..efbf2c1
--- /dev/null
+++ b/utils/shortcuts/error.go
@@ -0,0 +1,25 @@
+package shortcuts
+
+import (
+ "cafe/types"
+ "cafe/utils/meta"
+ "errors"
+
+ "github.com/gofiber/fiber/v2"
+)
+
+func BuildErrorMessage(err error, alternateString string) error {
+ if err != nil {
+ return err
+ }
+
+ return errors.New(alternateString)
+}
+
+func RenderError(error types.TemplateError) error {
+ meta.SetPageTitle(error.Context, error.PageTitle)
+ return RenderWithStatus(error.Context, "error", fiber.Map{
+ "ErrorTitle": error.PageTitle,
+ "ErrorMessage": error.ErrorMessage.Error(),
+ }, error.StatusCode)
+}
diff --git a/utils/shortcuts/flash.go b/utils/shortcuts/flash.go
new file mode 100644
index 0000000..ffb0afc
--- /dev/null
+++ b/utils/shortcuts/flash.go
@@ -0,0 +1,31 @@
+package shortcuts
+
+import (
+ "cafe/session"
+
+ "github.com/gofiber/fiber/v2"
+)
+
+const flashKey = "__flash__"
+
+func flash(ctx *fiber.Ctx, data any) error {
+ normalized, err := normalizeBind(data)
+ if err != nil {
+ return err
+ }
+
+ return session.Set(ctx, flashKey, normalized)
+}
+
+func consumeFlash(ctx *fiber.Ctx) (any, error) {
+ value, err := session.Get(ctx, flashKey)
+ if err != nil || value == nil {
+ return nil, err
+ }
+
+ if err := session.Delete(ctx, flashKey); err != nil {
+ return nil, err
+ }
+
+ return value, nil
+}
diff --git a/utils/shortcuts/helpers.go b/utils/shortcuts/helpers.go
new file mode 100644
index 0000000..7fee04e
--- /dev/null
+++ b/utils/shortcuts/helpers.go
@@ -0,0 +1,111 @@
+package shortcuts
+
+import (
+ "fmt"
+ "maps"
+ "reflect"
+ "strings"
+
+ "github.com/gofiber/fiber/v2"
+)
+
+func structValue(data any) (reflect.Value, error) {
+ v := reflect.ValueOf(data)
+ if v.Kind() == reflect.Pointer {
+ v = v.Elem()
+ }
+
+ if v.Kind() != reflect.Struct {
+ return reflect.Value{}, fmt.Errorf("unsupported bind type %T; must be struct or *struct", data)
+ }
+
+ return v, nil
+}
+
+func mapStruct(v reflect.Value) map[string]any {
+ t := v.Type()
+ result := make(map[string]any, v.NumField())
+
+ for i := 0; i < v.NumField(); i++ {
+ field := t.Field(i)
+ if !field.IsExported() {
+ continue
+ }
+
+ result[getFieldKey(field)] = v.Field(i).Interface()
+ }
+
+ return result
+}
+
+func getFieldKey(field reflect.StructField) string {
+ key := field.Name
+ tag := field.Tag.Get("json")
+
+ if tag == "" || tag == "-" {
+ return key
+ }
+
+ if idx := strings.IndexByte(tag, ','); idx >= 0 {
+ if idx > 0 {
+ return tag[:idx]
+ }
+ return key
+ }
+
+ return tag
+}
+
+func normalizeBind(data any) (fiber.Map, error) {
+ if data == nil {
+ return nil, nil
+ }
+
+ switch v := data.(type) {
+ case fiber.Map:
+ return v, nil
+ case map[string]any:
+ return fiber.Map(v), nil
+ default:
+ return structToMap(v)
+ }
+}
+
+func structToMap(data any) (fiber.Map, error) {
+ v, err := structValue(data)
+ if err != nil {
+ return nil, err
+ }
+ return fiber.Map(mapStruct(v)), nil
+}
+
+func mergeFlash(ctx *fiber.Ctx, bind fiber.Map) error {
+ flash, err := consumeFlash(ctx)
+ if err != nil || flash == nil {
+ return err
+ }
+
+ flashMap, err := normalizeBind(flash)
+ if err != nil {
+ return err
+ }
+
+ maps.Copy(bind, flashMap)
+ return nil
+}
+
+func mergeUserValues(ctx *fiber.Ctx, bind fiber.Map) {
+ ctx.Context().VisitUserValues(func(key []byte, value any) {
+ bind[string(key)] = value
+ })
+}
+
+func mergeData(bind fiber.Map, data any) error {
+ dataMap, err := normalizeBind(data)
+ if err != nil {
+ return err
+ }
+
+ maps.Copy(bind, dataMap)
+ return nil
+}
diff --git a/utils/shortcuts/redirect.go b/utils/shortcuts/redirect.go
new file mode 100644
index 0000000..9c75679
--- /dev/null
+++ b/utils/shortcuts/redirect.go
@@ -0,0 +1,36 @@
+package shortcuts
+
+import (
+ "cafe/utils/urls"
+
+ "github.com/gofiber/fiber/v2"
+)
+
+func Redirect(ctx *fiber.Ctx, routeName string) error {
+ path, ok := urls.GetFullPath(routeName)
+ if !ok {
+ return fiber.ErrNotFound
+ }
+ return ctx.Redirect(path)
+}
+
+func RedirectWithStatus(ctx *fiber.Ctx, routeName string, statusCode int) error {
+ path, ok := urls.GetFullPath(routeName)
+ if !ok {
+ return fiber.ErrNotFound
+ }
+ return ctx.Redirect(path, statusCode)
+}
+
+func RedirectTo(route string) fiber.Handler {
+ return func(ctx *fiber.Ctx) error {
+ return Redirect(ctx, route)
+ }
+}
+
+func RedirectWithFlash(context *fiber.Ctx, routeName string, data fiber.Map) error {
+ if err := flash(context, data); err != nil {
+ return err
+ }
+ return Redirect(context, routeName)
+}
diff --git a/utils/shortcuts/render.go b/utils/shortcuts/render.go
new file mode 100644
index 0000000..7862b91
--- /dev/null
+++ b/utils/shortcuts/render.go
@@ -0,0 +1,28 @@
+package shortcuts
+
+import (
+ "github.com/gofiber/fiber/v2"
+)
+
+func Render(ctx *fiber.Ctx, template string, data any) error {
+ bind := make(fiber.Map)
+
+ if err := mergeFlash(ctx, bind); err != nil {
+ return err
+ }
+
+ mergeUserValues(ctx, bind)
+
+ if data != nil {
+ if err := mergeData(bind, data); err != nil {
+ return err
+ }
+ }
+
+ return ctx.Render(template, bind)
+}
+
+func RenderWithStatus(ctx *fiber.Ctx, template string, data any, statusCode int) error {
+ ctx.Status(statusCode)
+ return Render(ctx, template, data)
+}