backend requirements onthe xustomer app
This commit is contained in:
97
utils/response_cx.go
Normal file
97
utils/response_cx.go
Normal file
@@ -0,0 +1,97 @@
|
||||
package utils
|
||||
|
||||
import "github.com/gofiber/fiber/v2"
|
||||
|
||||
// Customer-app (doormile_cx) response envelope.
|
||||
//
|
||||
// Deliberately a separate helper set from OK/List/Fail rather than a reuse of
|
||||
// them. The customer contract fixes three things the miler/console contract
|
||||
// does not: `message` is always present on success (empty string, never
|
||||
// omitted), the machine-readable code is nested under `error.code` rather than
|
||||
// sitting at the top level, and `total`/`nextCursor` ride the list envelope.
|
||||
// Serving one endpoint in one shape and its neighbour in another is exactly
|
||||
// what cost the miler client a release on /miler/verify-pin — so the customer
|
||||
// surface gets its own helpers and every /customer/* response goes through
|
||||
// them, auth included.
|
||||
|
||||
// CxErr* are the error codes in the customer contract. The client branches on
|
||||
// these; `message` is customer-safe English shown verbatim in the UI.
|
||||
const (
|
||||
CxErrInvalid = "invalid"
|
||||
CxErrInvalidName = "invalid_name"
|
||||
CxErrInvalidOtp = "invalid_otp"
|
||||
CxErrUnauthorized = "unauthorized"
|
||||
CxErrForbidden = "forbidden"
|
||||
CxErrNotFound = "not_found"
|
||||
CxErrConflict = "conflict"
|
||||
CxErrUnserviceable = "unserviceable"
|
||||
CxErrRateLimited = "rate_limited"
|
||||
CxErrServer = "server_error"
|
||||
)
|
||||
|
||||
// CxOK is the success envelope: {success, data, message}.
|
||||
func CxOK(c *fiber.Ctx, data interface{}) error {
|
||||
return c.JSON(fiber.Map{"success": true, "data": data, "message": ""})
|
||||
}
|
||||
|
||||
// CxCreated is CxOK with a 201.
|
||||
func CxCreated(c *fiber.Ctx, data interface{}) error {
|
||||
return c.Status(fiber.StatusCreated).
|
||||
JSON(fiber.Map{"success": true, "data": data, "message": ""})
|
||||
}
|
||||
|
||||
// CxList is the list envelope. data is always an array — never null, because
|
||||
// the client types it as a list and a null throws in the parser. nextCursor is
|
||||
// null when the page is the last one.
|
||||
func CxList(c *fiber.Ctx, data interface{}, total int, nextCursor *string) error {
|
||||
body := fiber.Map{
|
||||
"success": true,
|
||||
"data": data,
|
||||
"total": total,
|
||||
"nextCursor": nil,
|
||||
"message": "",
|
||||
}
|
||||
if nextCursor != nil && *nextCursor != "" {
|
||||
body["nextCursor"] = *nextCursor
|
||||
}
|
||||
return c.JSON(body)
|
||||
}
|
||||
|
||||
// CxFail is the error envelope: {success:false, message, error:{code}}. The
|
||||
// app funnels every failure into one retryable error state and renders
|
||||
// `message` verbatim, so callers must pass customer-safe English here — never
|
||||
// an enum key, a driver error or a wrapped stack.
|
||||
func CxFail(c *fiber.Ctx, status int, code, msg string) error {
|
||||
return c.Status(status).JSON(fiber.Map{
|
||||
"success": false,
|
||||
"message": msg,
|
||||
"error": fiber.Map{"code": code},
|
||||
})
|
||||
}
|
||||
|
||||
// Shorthands for the statuses the contract pins to a specific code.
|
||||
func CxBadRequest(c *fiber.Ctx, msg string) error {
|
||||
return CxFail(c, fiber.StatusBadRequest, CxErrInvalid, msg)
|
||||
}
|
||||
|
||||
func CxUnauthorized(c *fiber.Ctx, msg string) error {
|
||||
return CxFail(c, fiber.StatusUnauthorized, CxErrUnauthorized, msg)
|
||||
}
|
||||
|
||||
func CxForbidden(c *fiber.Ctx, msg string) error {
|
||||
return CxFail(c, fiber.StatusForbidden, CxErrForbidden, msg)
|
||||
}
|
||||
|
||||
func CxNotFound(c *fiber.Ctx, msg string) error {
|
||||
return CxFail(c, fiber.StatusNotFound, CxErrNotFound, msg)
|
||||
}
|
||||
|
||||
func CxConflict(c *fiber.Ctx, msg string) error {
|
||||
return CxFail(c, fiber.StatusConflict, CxErrConflict, msg)
|
||||
}
|
||||
|
||||
// CxInternal never leaks the underlying error to the customer. Log the real
|
||||
// one; the app shows this.
|
||||
func CxInternal(c *fiber.Ctx) error {
|
||||
return CxFail(c, fiber.StatusInternalServerError, CxErrServer, "Something went wrong")
|
||||
}
|
||||
Reference in New Issue
Block a user