dto-lib/common.go

261 lines
7.4 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 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"
"git.webz.asia/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
}