dto-lib/common.go

261 lines
7.4 KiB
Go
Raw Normal View History

2020-12-29 18:21:36 +01:00
/*
* Copyright (c) 2020 Alex <alex@webz.asia>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @author Alex <alex@webz.asia>
* @copyright Copyright (c) 2020 Alex <alex@webz.asia>
* @since 29.12.2020
*
*/
package dtoLib
import (
"errors"
"fmt"
"net/http"
"net/url"
"github.com/go-convert/fields"
)
type PaginationContainer struct {
Pagination Pagination `json:"pagination"`
}
type Pagination struct {
Page int `json:"page"`
PerPage int `json:"per_page"`
Total int `json:"total"`
}
type ApiResponse struct {
Code int32 `json:"code"`
Type string `json:"type"`
Message string `json:"message"`
Data interface{} `json:"data"`
*PaginationContainer
}
type ApiErrorResponse struct {
Code int32 `json:"code"`
Type string `json:"type"`
Message string `json:"message"`
Errors []error `json:"errors"`
Data interface{} `json:"data"`
}
type SearchParams url.Values
// AllApiResponses returns full map of map ApiResponse structure
func AllApiResponses() map[string]map[string]ApiResponse {
return responseMap
}
// AddNewApiResponse adds new api response by name, returns error if already exists
func AddNewApiResponse(name string, response map[string]ApiResponse) error {
if _, ok := responseMap[name]; ok {
return errors.New("this name already exists")
}
responseMap[name] = response
return nil
}
// AllApiErrorResponses returns full map of map ApiErrorResponse structure
func AllApiErrorResponses() map[string]map[string]ApiErrorResponse {
return errorResponseMap
}
// AddNewApiErrorResponse adds new error api response by name, returns error if already exists
func AddNewApiErrorResponse(name string, response map[string]ApiErrorResponse) error {
if _, ok := errorResponseMap[name]; ok {
return errors.New("this name already exists")
}
errorResponseMap[name] = response
return nil
}
// NotCreated returns http response code and error response object
func NotCreated(name string, errors []error) (int, ApiErrorResponse) {
response, ok := errorResponseMap[name][StatusNotCreated]
if ok {
response.Errors = errors
if len(errors) == 1 {
response.Data = errors[0].Error()
}
} else {
// fallback to other response, have to support it by default
return FallbackToFailedError(name, errors)
}
return http.StatusNotAcceptable, response
}
// Created returns http response code and regular response object
func Created(name string, data interface{}) (int, ApiResponse) {
response, ok := responseMap[name][StatusCreated]
if ok {
response.Data = data
} else {
// fallback to other response, have to support it by default
return FallbackToFailed(name)
}
return http.StatusCreated, response
}
// NotUpdated returns http response code and error response object
func NotUpdated(name string, errors []error) (int, ApiErrorResponse) {
response, ok := errorResponseMap[name][StatusNotUpdated]
if ok {
response.Errors = errors
if len(errors) == 1 {
response.Data = errors[0].Error()
}
} else {
// fallback to other response, have to support it by default
return FallbackToFailedError(name, errors)
}
return http.StatusNotAcceptable, response
}
// Updated returns http response code and regular response object
func Updated(name string, data interface{}) (int, ApiResponse) {
response, ok := responseMap[name][StatusUpdated]
if ok {
response.Data = data
} else {
// fallback to other response, have to support it by default
return FallbackToFailed(name)
}
return http.StatusAccepted, response
}
// NotDeleted returns http response code and error response object
func NotDeleted(name string, errors []error) (int, ApiErrorResponse) {
response, ok := errorResponseMap[name][StatusNotDeleted]
if ok {
response.Errors = errors
if len(errors) == 1 {
response.Data = errors[0].Error()
}
} else {
// fallback to other response, have to support it by default
return FallbackToFailedError(name, errors)
}
return http.StatusNotFound, response
}
// Deleted returns http response code and regular response object
func Deleted(name string, data interface{}) (int, ApiResponse) {
response, ok := responseMap[name][StatusDeleted]
if ok {
response.Data = data
} else {
// fallback to other response, have to support it by default
return FallbackToFailed(name)
}
return http.StatusOK, response
}
// NotFound returns http response code and error response object
func NotFound(name string, errors []error) (int, ApiErrorResponse) {
response, ok := errorResponseMap[name][StatusNotFound]
if ok {
response.Errors = errors
if len(errors) == 1 {
response.Data = errors[0].Error()
}
} else {
// fallback to other response, have to support it by default
return FallbackToFailedError(name, errors)
}
return http.StatusNotFound, response
}
// Found returns http response code and regular response object(found data and pagination)
func Found(name string, data interface{}, pagination interface{}) (int, ApiResponse) {
response, ok := responseMap[name][StatusFound]
if ok {
response.Data = data
} else {
// fallback to other response, have to support it by default
return FallbackToFailed(name)
}
if nil != pagination {
dtoPagination := &Pagination{}
fields.Сonvert(pagination, "pagination", dtoPagination)
response.PaginationContainer = &PaginationContainer{Pagination: *dtoPagination}
}
return http.StatusOK, response
}
// Ok returns http response code and regular response object
func Ok(name string, data interface{}) (int, ApiResponse) {
response, ok := responseMap[name][StatusOk]
if ok {
response.Data = data
} else {
// fallback to other response, have to support it by default
return FallbackToFailed(name)
}
return http.StatusOK, response
}
// Failed returns http response code and error response object
func Failed(name string, errors []error) (int, ApiErrorResponse) {
response, ok := errorResponseMap[name][StatusFailed]
if ok {
response.Errors = errors
if len(errors) == 1 {
response.Data = errors[0].Error()
}
} else {
// fallback to other response, have to support it by default
return FallbackToFailedError(name, errors)
}
return http.StatusInternalServerError, response
}
// FallbackToFailedError returns http response code and error response object as a fallback to predefined failed error response
func FallbackToFailedError(name string, errs []error) (int, ApiErrorResponse) {
errs = append(errs, fmt.Errorf("fallback to failed - no proper response for '%s' type", name))
response := errorResponseMap[TypeSystem][StatusFailed]
response.Errors = errs
if len(errs) == 1 {
response.Data = errs[0].Error()
}
return http.StatusInternalServerError, response
}
// FallbackToFailed returns http response code and regular response object as a fallback to predefined failed response
func FallbackToFailed(name string) (int, ApiResponse) {
response := responseMap[TypeSystem][StatusFailed]
response.Data = fmt.Errorf("fallback to failed - no proper response for '%s' type", name).(interface{})
return http.StatusInternalServerError, response
}