123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853 |
- package api
- import (
- "encoding/json"
- "fmt"
- "net/url"
- "regexp"
- "strconv"
- "strings"
- "time"
- "git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/api/errs"
- "github.com/davecgh/go-spew/spew"
- "github.com/eugeniucarvalho/validator"
- "github.com/kataras/iris/v12/context"
- "go.mongodb.org/mongo-driver/bson"
- "go.mongodb.org/mongo-driver/bson/primitive"
- "go.mongodb.org/mongo-driver/mongo"
- )
- var (
- AcceptJson = regexp.MustCompile("^application/json")
- Environment = map[string]interface{}{}
- ToReference = references{}
- )
- type references struct {
- }
- func (this *references) True() *bool {
- value := true
- return &value
- }
- func (this *references) False() *bool {
- value := false
- return &value
- }
- func (this *references) String(value string) *string {
- return &value
- }
- func (this *references) Bool(value bool) *bool {
- return &value
- }
- type ModeInterface interface {
- Mode() string
- }
- type PatchHistoryRegister struct {
- Id primitive.ObjectID `bson:"_id" json:"-"`
- CreatedAt int64 `bson:"createdAt" json:"-"`
- CreatedBy string `bson:"createdBy" json:"-"`
- Parent string `bson:"parent" json:"-"`
- ApiTags []string `bson:"apiTags" json:"-"`
- }
- type EntityModel struct {
- Mode string `bson:"-" json:"-"`
- ApplicationVersion *string `bson:"appVersion,omitempty" json:"-"`
- Deleted *bool `bson:"deleted,omitempty" json:"-"`
- DeletedIn *int64 `bson:"deletedIn,omitempty" json:"-"`
- }
- // type DotNotation struct {
- // Rules map[string]interface{} `bson:",inline" json:"-"`
- // }
- // func (model *DotNotation) DotNotation() map[string]interface{} {
- // if model.Rules == nil {
- // model.Rules = map[string]interface{}{}
- // }
- // return model.Rules
- // }
- func UserIDString(ctx context.Context) (id string, err *errs.Error) {
- if user, ok := ctx.Values().Get("$user.ref").(map[string]interface{}); ok {
- id = user["id"].(primitive.ObjectID).Hex()
- return
- }
- err = errs.Internal().Details(&errs.Detail{
- Message: "Invalid user instance",
- })
- return
- }
- func (model *EntityModel) SetMode(mode string) {
- model.Mode = mode
- switch mode {
- case "create":
- model.ApplicationVersion = &BuildVersion
- deleted := false
- model.Deleted = &deleted
- case "update":
- if model.Deleted == nil {
- deleted := false
- model.Deleted = &deleted
- }
- case "patch":
- // if model.Deleted == nil {
- // deleted := false
- // model.Deleted = &deleted
- // }
- // case "delete":
- // case "undelete":
- }
- }
- func GetIDString(input interface{}) (string, *errs.Error) {
- if value, converted := input.(string); converted {
- return value, nil
- }
- if value, converted := input.(*primitive.ObjectID); converted {
- return value.Hex(), nil
- }
- if value, converted := input.(primitive.ObjectID); converted {
- return value.Hex(), nil
- }
- return "", errs.Internal().Details(&errs.Detail{
- Reason: fmt.Sprintf("Can't convert ID into string. Invalid type '%T", input),
- })
- }
- func NowUnix() int64 {
- return time.Now().Unix()
- }
- func GetUser(ctx context.Context) interface{} {
- return ctx.Values().Get("$user.ref")
- }
- func (model *EntityModel) SetDeleted(deleted bool) {
- var deletedIn = int64(0)
- model.Deleted = &deleted
- if *model.Deleted {
- deletedIn = time.Now().Unix()
- }
- model.DeletedIn = &deletedIn
- }
- type CorsOptions struct {
- ExposeHeaders []string
- AllowHeaders []string
- AllowMethods []string
- AllowOrigin []string
- }
- type GetManyResponse struct {
- ResultSizeEstimate int `json:"resultSizeEstimate"` // Estimativa do numero total de itens.
- NextPageToken string `json:"nextPageToken"` // Referência para a proxima pagina de resultados.
- Itens interface{} `json:"itens"` // Lista contento os elementos da resposta.
- }
- var (
- // ParamsFlag map[string]*ParamFlag
- CorsDefaultOptions = CorsOptions{
- AllowOrigin: []string{"*"},
- // AllowOrigin: []string{"http://localhost:4200"},
- AllowMethods: []string{"OPTIONS", "GET", "POST", "PUT", "DELETE", "PATCH"},
- AllowHeaders: []string{"Authorization", "Content-Type", "Origin", "Host", "x-api-build"},
- ExposeHeaders: []string{"X-total-count"},
- }
- BuildVersion = "0"
- ApiVersion = "0"
- // Armazena os mimes dos arquivos consultados
- // MimeCache = xmap.NewMS2S()
- replaceEmpty = regexp.MustCompile(`\s+`)
- // pageTokenRegex = regexp.MustCompile(`(?P<ids>\w+):(?P<idc>\w+):(?P<page>\d{1,6})`)
- pageTokenRegex = regexp.MustCompile(`(?P<idc>[\w-]+):(?P<count>\d+)`)
- replaceIndex = regexp.MustCompile(`\.\d+\.`)
- )
- func init() {
- // fmt.Println("Register validation functions")
- // err := Validator.RegisterValidation("req", func(f validator.FieldLevel) bool {
- // fmt.Println("Running req validation")
- // spew.Dump(f)
- // return true
- // })
- validator.RegisterValidator("requiredOnCreate", func(i interface{}, o interface{}, v *validator.ValidatorOption) error {
- if schema, ok := o.(ModeInterface); ok {
- fmt.Println("requiredOnCreate ->", schema.Mode())
- switch schema.Mode() {
- case "create":
- if i == nil {
- return fmt.Errorf("")
- }
- case "update":
- }
- }
- return nil
- })
- // Validator.RegisterValidation("req",
- // func(fl validator.FieldLevel) bool {
- // // func(v *validator.Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
- // // func(v *validator.Validate, param string) bool {
- // // return passwordRegex.MatchString(field.String())
- // })
- // if err != nil {
- // panic(err)
- // }
- }
- func Panic() {
- if err := recover(); err != nil {
- LogError(0, err.(error).Error())
- }
- }
- func Validate(i interface{}) *errs.Error {
- // if err := Validator.Struct(i); err != nil {
- // fmt.Println("VALIDATE", result, err)
- // spew.Dump(i)
- if errors, valid := validator.Struct(i); !valid {
- err := errs.InvalidArgument()
- // er := Error(ERR_INVALID_PARAM, "Invalid params")
- for _, e := range errors {
- err.Details(&errs.Detail{
- Dominio: "global",
- Reason: "invalidParameter",
- Message: e.Message,
- // Message: fmt.Sprintf("%+v", e.Message),
- // LocationType:,
- // Location :,
- })
- }
- // if _, ok := err.(*validator.InvalidValidationError); ok {
- // fmt.Println("INvalid")
- // er.LastDescription().Message = err.Error()
- // } else {
- // for _, err := range err.(validator.ValidationErrors) {
- // switch err.Tag() {
- // case "required":
- // }
- // er.Add(&ErrDescription{
- // Dominio: "global",
- // Reason: "invalidParameter",
- // Message: fmt.Sprintf("%+v", err),
- // // LocationType:,
- // // Location :,
- // })
- // // fmt.Println("1", err.Namespace())
- // // fmt.Println("2", err.Field())
- // // fmt.Println("3", err.StructNamespace()) // can differ when a custom TagNameFunc is registered or
- // // fmt.Println("4", err.StructField()) // by passing alt name to ReportError like below
- // // fmt.Println("5", err.Tag())
- // // fmt.Println("6", err.ActualTag())
- // // fmt.Println("7", err.Kind())
- // // fmt.Println("8", err.Type())
- // // fmt.Println("9", err.Value())
- // // fmt.Println("10", err.Param())
- // // fmt.Println("-------------")
- // }
- // }
- return err
- // from here you can create your own error messages in whatever language you wish
- }
- return nil
- }
- // ApiResponse é a estrutura padrão de respostas
- // Apenas os campos preenchidos serão retornados
- type ApiResponse struct {
- Entity interface{} `json:"entity,omitempty"`
- List interface{} `json:"list,omitempty"`
- NextPageToken string `json:"nextPageToken,omitempty"`
- ResultSizeEstimate int `json:"resultSizeEstimate,omitempty"`
- }
- // func ErroCtxHandler(ctx context.Context, err *errs.Error) {
- // if accept := ctx.GetHeader("Accept"); AcceptJson.Match([]byte(accept)) {
- // ctx.JSON(err)
- // } else {
- // ctx.ViewData("", err)
- // }
- // }
- func finalizeRequest(ctx context.Context, resp interface{}, err *errs.Error) {
- var (
- status = 200
- accept = ctx.Request().Header.Get("accept")
- types = strings.Split(accept, ",")
- )
- defer func() {
- ctx.StopExecution()
- if err != nil {
- ctx.Application().Logger().Error(err.Error())
- if description := err.LastDescription(); description != nil {
- err.Stack.Print()
- // ctx.Application().Logger().Error(fmt.Printf("%s\n%s\n", description.Reason, description.Message))
- }
- // ctx.Application().Logger().Error()
- spew.Dump(err)
- }
- fmt.Println("defer of finalizeRequest")
- if r := recover(); r != nil {
- fmt.Println("Recovered in f", r)
- }
- }()
- if err != nil {
- status = err.HttpStatus
- // fmt.Println(status, err.Message, "------------------------------------------\n")
- // spew.Dump(err)
- // debbug
- // err.Stack.Print()
- resp = err
- abortTransaction(ctx)
- // fmt.Println("------------------------------------------\n", status)
- // spew.Dump(err)
- // fmt.Println("------------------------------------------\n", status)
- }
- ctx.Values().Set("res", resp)
- ctx.Header("x-api-build", BuildVersion)
- // fmt.Println("error")
- // spew.Dump(resp)
- // spew.Dump(types)
- // spew.Dump(ctx.Request().Header)
- ctx.StatusCode(status)
- for _, mime := range types {
- switch mime {
- case "application/json":
- ctx.JSON(resp)
- return
- }
- }
- // default response case
- ctx.WriteString("")
- }
- // Call encapsula e trata os erros para cada requisição.
- func CallAction(id string, fn func(context.Context) (interface{}, *errs.Error)) func(context.Context) {
- return func(ctx context.Context) {
- var (
- err *errs.Error
- resp interface{}
- finalize = true
- )
- defer func() {
- if !ctx.IsStopped() {
- if _err := recover(); _err != nil {
- err = errs.Internal().Details(&errs.Detail{
- Message: "",
- Location: fmt.Sprintf("call.action.%s", id),
- LocationType: "application.pipe.resource.stage",
- Reason: _err.(error).Error(),
- })
- }
- if finalize {
- finalizeRequest(ctx, resp, err)
- }
- }
- }()
- fmt.Println("apply -> ", id)
- if resp, err = fn(ctx); err != nil {
- return
- }
- if !ctx.IsStopped() {
- if resp != nil {
- err = commitTransaction(ctx)
- } else {
- ctx.Next()
- finalize = false
- }
- }
- return
- }
- }
- func abortTransaction(ctx context.Context) (err *errs.Error) {
- return transactionHandler(ctx, "abort")
- }
- func commitTransaction(ctx context.Context) (err *errs.Error) {
- return transactionHandler(ctx, "commit")
- }
- func transactionHandler(ctx context.Context, action string) (err *errs.Error) {
- var (
- localErr error
- operation func() error
- )
- contextSession := GetSessionContext(ctx)
- if contextSession == nil {
- return
- }
- switch action {
- case "abort":
- operation = func() error { return contextSession.AbortTransaction(contextSession) }
- case "commit":
- operation = func() error { return contextSession.CommitTransaction(contextSession) }
- }
- try := 4
- for {
- if localErr = operation(); localErr == nil {
- fmt.Println(action, "executed ")
- return
- }
- if try == 0 {
- return
- }
- try--
- fmt.Println(action, "transaction error loop ")
- // time.Sleep(4 * time.Second)
- // retry operation when command contains TransientTransactionError
- // if cmdErr, ok := localErr.(mongo.CommandError); ok && cmdErr.HasErrorLabel("TransientTransactionError") {
- if cmdErr, ok := localErr.(mongo.CommandError); ok {
- fmt.Println(action, cmdErr)
- if cmdErr.HasErrorLabel("TransientTransactionError") {
- continue
- }
- }
- }
- if localErr != nil {
- err = errs.Internal().Details(&errs.Detail{
- Message: localErr.Error(),
- })
- }
- return
- }
- func ReadJson(ctx context.Context, entity interface{}) (err *errs.Error) {
- if err := ctx.ReadJSON(entity); err != nil {
- err = errs.DataCaps().Details(&errs.Detail{
- Message: err.Error(),
- })
- }
- return
- }
- func MgoSortBson(fields []string) *bson.M {
- order := bson.M{}
- for _, field := range fields {
- n := 1
- if field != "" {
- fmt.Printf("sort '%c'\n", field[0])
- switch field[0] {
- case '+':
- field = field[1:]
- case '-':
- n = -1
- field = field[1:]
- default:
- panic(fmt.Sprintf("Invalid sort field %s.", field))
- }
- }
- if field == "" {
- panic("Sort: empty field name")
- }
- field = string(replaceIndex.ReplaceAll([]byte(field), []byte(".")))
- order[field] = n
- }
- return &order
- }
- func MgoSort(ctx context.Context, field string) []string {
- result := []string{}
- if fields := Q(ctx, field, ""); fields != "" {
- sort := string(replaceEmpty.ReplaceAll([]byte(fields), []byte("")))
- result = strings.Split(sort, ",")
- }
- // return nil
- return result
- }
- func MgoFieldsCtx(ctx context.Context, field string) *bson.M {
- return MgoFields(Q(ctx, field, ""))
- }
- func MgoFields(fields string) (projection *bson.M) {
- // fmt.Printf("MgoFields '%s'\n", fields)
- if fields != "" {
- projection = &bson.M{}
- for _, v := range strings.Split(fields, ",") {
- (*projection)[v] = 1
- }
- // spew.Dump(projection)
- }
- return
- }
- func MgoQuery(ctx context.Context, field string) (*bson.M, *errs.Error) {
- return MgoQueryString(ctx, Q(ctx, field, ""))
- }
- func MgoQueryString(ctx context.Context, query string) (*bson.M, *errs.Error) {
- var (
- selector = make(bson.M)
- // id = "_id"
- err error
- )
- // Unmarshal json query if any
- if query != "" {
- if err = bson.UnmarshalExtJSON([]byte(query), true, &selector); err != nil {
- // return nil, Error(ERR_GENERAL, err.Error())
- return nil, errs.Internal().Details(&errs.Detail{
- Message: err.Error(),
- })
- }
- if query, err = url.QueryUnescape(query); err != nil {
- return nil, errs.Internal().Details(&errs.Detail{
- Message: err.Error(),
- })
- // return nil, Error(ERR_GENERAL, err.Error())
- }
- if err = json.Unmarshal([]byte(query), &selector); err != nil {
- // return nil, Error(ERR_GENERAL, err.Error())
- return nil, errs.Internal().Details(&errs.Detail{
- Message: err.Error(),
- })
- }
- // if selector, err = mejson.Unmarshal(selector); err != nil {
- // return nil, Error(ERR_GENERAL, err.Error())
- // }
- }
- // Transform string HexId to ObjectIdHex
- // if selid, _ := selector[id].(string); selid != "" {
- // if bson.IsObjectIdHex(selid) {
- // selector[id] = bson.ObjectIdHex(selid)
- // }
- // // else {
- // // selector[id] = selid
- // // }
- // }
- return &selector, nil
- }
- func DefaultCorsHandler() func(ctx context.Context) {
- return Cors(CorsDefaultOptions)
- }
- func Cors(opt CorsOptions) func(ctx context.Context) {
- return func(ctx context.Context) {
-
- ctx.Header("Access-Control-Allow-Credentials", "true")
- if len(opt.AllowOrigin) > 0 {
- // ctx.Header("Access-Control-Allow-Origin", strings.Join(opt.AllowOrigin, ","))
- // ctx.Header("Access-Control-Allow-Origin", "*")
- // ctx.Header("Origin", "*")
- ctx.Header("Access-Control-Allow-Origin", ctx.GetHeader("Origin"))
- }
- if len(opt.AllowMethods) > 0 {
- ctx.Header("Access-Control-Allow-Methods", strings.Join(opt.AllowMethods, ","))
- }
- if len(opt.AllowHeaders) > 0 {
- ctx.Header("Access-Control-Allow-Headers", strings.Join(opt.AllowHeaders, ","))
- }
- if len(opt.ExposeHeaders) > 0 {
- ctx.Header("Access-Control-Expose-Headers", strings.Join(opt.ExposeHeaders, ","))
- }
- ctx.Next()
- }
- }
- // Retorna um valor de um parametro no path da url.
- func P(ctx context.Context, name string, def string) string {
- val := ctx.Params().Get(name)
- if val == "" {
- val = def
- }
- return val
- }
- //Retorna um valor de um parametro da query. Ex: ?x=1
- func Q(ctx context.Context, name string, def string) string {
- val := ctx.URLParam(name)
- if val == "" {
- val = def
- }
- return val
- }
- //Retorna um valor de um parametro da query
- func QInt(ctx context.Context, name string, def int) int {
- val, e := strconv.Atoi(Q(ctx, name, ""))
- if e != nil {
- val = def
- }
- return val
- }
- // Retorna um valor de um parametro do post.
- func F(ctx context.Context, name string, def interface{}) interface{} {
- var val interface{}
- val = ctx.FormValue(name)
- if val == "" {
- val = def
- }
- return val
- }
- func LogError(code int, m string) {
- log("31", fmt.Sprintf("[ERROR| %d] %s", code, m))
- }
- func LogInfo(code int, m string) {
- log("34", fmt.Sprintf("[INFO| %d] %s", code, m))
- }
- func LogWarning(code int, m string) {
- log("35", fmt.Sprintf("[WARNING| %d] %s", code, m))
- }
- func log(color string, m string) {
- fmt.Printf("\x1b[%s;1m%s\x1b[0m\n", color, m)
- }
- // func ParseRequestTest(ctx context.Context) {
- // var (
- // err error
- // filter = &Filter{
- // MaxResults: QInt(ctx, "maxResults", 10),
- // }
- // oid primitive.ObjectID
- // )
- // // parse parameter of path
- // id := P(ctx, "userId", "")
- // if oid, err = primitive.ObjectIDFromHex(id); err != nil {
- // filter.UserId = oid
- // }
- // id = P(ctx, "id", "")
- // if oid, err = primitive.ObjectIDFromHex(id); err != nil {
- // filter.Id = oid
- // }
- // // filter.PageToken.Parse(Q(ctx, "nextPageToken", ""))
- // if filter.Query, err = MgoQuery(ctx, "q"); err != nil {
- // goto Error
- // }
- // filter.Format = Q(ctx, "format", "full")
- // filter.Sort = MgoSortBson(MgoSort(ctx, "sort"))
- // filter.Fields = MgoFieldsCtx(ctx, "fields")
- // Error:
- // if err != nil {
- // ErroCtxHandler(
- // ctx,
- // // Error(ERR_INVALID_PARAM, err.Error()),
- // errs.Internal().Details(&errs.Detail{
- // Message: err.Error(),
- // }),
- // )
- // return
- // }
- // ctx.Values().Set("$filter", filter)
- // ctx.Next()
- // }
- // func MapError(erro *errs.Error) *errs.Error {
- // if strings.Contains(erro.Message, "E11000") {
- // return errs.AlreadyExists().Details(&errs.Detail{
- // Message: "DUPLICATED_ITEM",
- // })
- // } else if strings.Contains(erro.Message, "no documents in result") {
- // return errs.Internal().Details(&errs.Detail{
- // Message: "NOT_FOUND",
- // })
- // }
- // return erro
- // }
- // type PageToken struct {
- // // StartID string
- // // CurrentID string
- // Cursor string
- // NewCursor string
- // Page int
- // Count int
- // }
- // // Encode cria um novo token formatado
- // func (p *PageToken) Encode() string {
- // out := ""
- // if p.NewCursor != "" {
- // out = base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%d", p.NewCursor, p.Count)))
- // }
- // return out
- // // return string([]byte(fmt.Sprintf("%s:%d", p.NewCursor, p.Count)))
- // }
- // // HasToken determina se a requisição apresenta um token de paginacao
- // func (p *PageToken) HasToken() bool {
- // return p.Cursor != ""
- // }
- // // func (p *PageToken) GetBsonID() bson.ObjectId {
- // // if !bson.IsObjectIdHex(p.ID) {
- // // return nil
- // // }
- // // return bson.ObjectIdHex(p.ID)
- // // }
- // func (p *PageToken) Parse(s string) error {
- // var (
- // decoded []byte
- // err error
- // )
- // if decoded, err = base64.StdEncoding.DecodeString(s); err != nil {
- // return err
- // }
- // match := pageTokenRegex.FindStringSubmatch(string(decoded))
- // if len(match) != 3 {
- // return fmt.Errorf("Invalid Page Token")
- // }
- // p.Cursor = match[1]
- // // p.Page, err = strconv.Atoi(match[2])
- // p.Count, err = strconv.Atoi(match[2])
- // return err
- // }
- // Layout aplica o path do layout
- // func Layout(ctx context.Context) {
- // ctx.ViewLayout(ViewScript(ctx, "layout/layout.html"))
- // ctx.Next()
- // }
- // // ViewScript devolve o path do arquivo de script a ser renderizaco
- // func ViewScript(ctx context.Context, filename string) string {
- // var (
- // base string
- // ok bool
- // )
- // domain := strings.Split(ctx.Request().Host, ":")[0]
- // if base, ok = TemplateDomainMap[domain]; !ok {
- // base = "default"
- // }
- // return base + "/" + filename
- // }
- // defer func() {
- // var (
- // erro *errs.Error
- // // ok bool
- // err error
- // )
- // if err = recover(); err != nil {
- // if erro, ok = err.(*errs.Error); !ok {
- // erro = Error(ERR_GENERAL, err.Error())
- // }
- // ErroCtxHandler(ctx, erro)
- // }
- // // ctx.Header("Accept", "application/json")
- // // spew.Dump(err)
- // }()
- // func CallAction(f func(context.Context, *ApiResponse) *errs.Error) func(ctx context.Context) {
- // return func(ctx context.Context) {
- // var (
- // err *errs.Error
- // response = &ApiResponse{}
- // )
- // if err = f(ctx, response); err != nil {
- // ErroCtxHandler(ctx, err)
- // return
- // }
- // ctx.JSON(response)
- // }
- // }
- // Verifica se existe alguma pagina para ser carragada.
- // func UpdateCursorResponse(models *Mongo, f *Filter, resp interface{}) bool {
- // count := f.PageToken.Count
- // // Se não foi encontrado nenhum registro
- // if count > 0 {
- // resp.ResultSizeEstimate = count
- // resp.NextPageToken = f.PageToken.Encode()
- // return true
- // }
- // return false
- // }
|