Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
fad2e4ff6d
|
|||
|
e12764c0a2
|
|||
|
53aa8c05b0
|
|||
|
4f96907758
|
@@ -108,7 +108,7 @@ func (e {{.EnumTypeName}}) PackageName() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e {{.EnumTypeName}}) Meta() enums.EnumMetaValue {
|
func (e {{.EnumTypeName}}) Meta() enums.EnumMetaValue {
|
||||||
{{if $hasDescr}} return enums.EnumMetaValue{VarName: e.VarName(), Value: e, Description: langext.Ptr(e.Description())} {{else}} return enums.EnumMetaValue{VarName: e.VarName(), Value: e, Description: nil} {{end}}
|
{{if $hasDescr}} return enums.EnumMetaValue{VarName: e.VarName(), Value: e, Description: new(e.Description())} {{else}} return enums.EnumMetaValue{VarName: e.VarName(), Value: e, Description: nil} {{end}}
|
||||||
}
|
}
|
||||||
|
|
||||||
{{if $hasDescr}}
|
{{if $hasDescr}}
|
||||||
@@ -122,7 +122,7 @@ func (e {{.EnumTypeName}}) DataMeta() enums.EnumDataMetaValue {
|
|||||||
return enums.EnumDataMetaValue{
|
return enums.EnumDataMetaValue{
|
||||||
VarName: e.VarName(),
|
VarName: e.VarName(),
|
||||||
Value: e,
|
Value: e,
|
||||||
{{if $hasDescr}} Description: langext.Ptr(e.Description()), {{else}} Description: nil, {{end}}
|
{{if $hasDescr}} Description: new(e.Description()), {{else}} Description: nil, {{end}}
|
||||||
Data: map[string]any{
|
Data: map[string]any{
|
||||||
{{ range $datakey, $datatype := $enumdef | generalDataKeys }} "{{ $datakey }}": e.Data().{{ $datakey | godatakey }},
|
{{ range $datakey, $datatype := $enumdef | generalDataKeys }} "{{ $datakey }}": e.Data().{{ $datakey | godatakey }},
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ package {{.PkgName}}
|
|||||||
|
|
||||||
import "go.mongodb.org/mongo-driver/v2/bson"
|
import "go.mongodb.org/mongo-driver/v2/bson"
|
||||||
import "git.blackforestbytes.com/BlackForestBytes/goext/exerr"
|
import "git.blackforestbytes.com/BlackForestBytes/goext/exerr"
|
||||||
|
import "git.blackforestbytes.com/BlackForestBytes/goext/wmo"
|
||||||
|
|
||||||
const ChecksumIDGenerator = "{{.Checksum}}" // GoExtVersion: {{.GoextVersion}}
|
const ChecksumIDGenerator = "{{.Checksum}}" // GoExtVersion: {{.GoextVersion}}
|
||||||
|
|
||||||
@@ -52,4 +53,6 @@ func New{{.Name}}() {{.Name}} {
|
|||||||
return {{.Name}}(bson.NewObjectID().Hex())
|
return {{.Name}}(bson.NewObjectID().Hex())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ wmo.MongoEntityID = (*{{.Name}})(nil)
|
||||||
|
|
||||||
{{end}}
|
{{end}}
|
||||||
@@ -3,10 +3,11 @@ package cursortoken
|
|||||||
import (
|
import (
|
||||||
"encoding/base32"
|
"encoding/base32"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"git.blackforestbytes.com/BlackForestBytes/goext/exerr"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"git.blackforestbytes.com/BlackForestBytes/goext/exerr"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CursorToken interface {
|
type CursorToken interface {
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.blackforestbytes.com/BlackForestBytes/goext/langext"
|
|
||||||
"git.blackforestbytes.com/BlackForestBytes/goext/tst"
|
"git.blackforestbytes.com/BlackForestBytes/goext/tst"
|
||||||
"github.com/xuri/excelize/v2"
|
"github.com/xuri/excelize/v2"
|
||||||
)
|
)
|
||||||
@@ -70,7 +69,7 @@ func TestInitNewFileAndStyles(t *testing.T) {
|
|||||||
func TestAddColumn(t *testing.T) {
|
func TestAddColumn(t *testing.T) {
|
||||||
em, _ := NewExcelMapper[testRow]()
|
em, _ := NewExcelMapper[testRow]()
|
||||||
em.AddColumn("Name", nil, nil, func(r testRow) any { return r.Name })
|
em.AddColumn("Name", nil, nil, func(r testRow) any { return r.Name })
|
||||||
em.AddColumn("Age", nil, langext.Ptr(12.0), func(r testRow) any { return r.Age })
|
em.AddColumn("Age", nil, new(12.0), func(r testRow) any { return r.Age })
|
||||||
|
|
||||||
tst.AssertEqual(t, len(em.colDefinitions), 2)
|
tst.AssertEqual(t, len(em.colDefinitions), 2)
|
||||||
tst.AssertEqual(t, em.colDefinitions[0].header, "Name")
|
tst.AssertEqual(t, em.colDefinitions[0].header, "Name")
|
||||||
@@ -109,7 +108,7 @@ func TestAddColumnErr(t *testing.T) {
|
|||||||
func TestAddWorksheetHeader(t *testing.T) {
|
func TestAddWorksheetHeader(t *testing.T) {
|
||||||
em, _ := NewExcelMapper[testRow]()
|
em, _ := NewExcelMapper[testRow]()
|
||||||
em.AddWorksheetHeader("Title 1", nil)
|
em.AddWorksheetHeader("Title 1", nil)
|
||||||
em.AddWorksheetHeader("Title 2", langext.Ptr(7))
|
em.AddWorksheetHeader("Title 2", new(7))
|
||||||
|
|
||||||
tst.AssertEqual(t, len(em.wsHeader), 2)
|
tst.AssertEqual(t, len(em.wsHeader), 2)
|
||||||
tst.AssertEqual(t, em.wsHeader[0].V1, "Title 1")
|
tst.AssertEqual(t, em.wsHeader[0].V1, "Title 1")
|
||||||
@@ -291,7 +290,7 @@ func TestBuildWithColumnWidthAndStyle(t *testing.T) {
|
|||||||
f, err := em.InitNewFile("S")
|
f, err := em.InitNewFile("S")
|
||||||
tst.AssertNoErr(t, err)
|
tst.AssertNoErr(t, err)
|
||||||
|
|
||||||
em.AddColumn("Name", em.StyleHeader, langext.Ptr(20.5), func(r testRow) any { return r.Name })
|
em.AddColumn("Name", em.StyleHeader, new(20.5), func(r testRow) any { return r.Name })
|
||||||
|
|
||||||
err = em.BuildSingleSheet(f, "S", []testRow{{Name: "Alice"}})
|
err = em.BuildSingleSheet(f, "S", []testRow{{Name: "Alice"}})
|
||||||
tst.AssertNoErr(t, err)
|
tst.AssertNoErr(t, err)
|
||||||
|
|||||||
+25
-25
@@ -2,17 +2,19 @@ package ginext
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/rs/zerolog/log"
|
|
||||||
"git.blackforestbytes.com/BlackForestBytes/goext/langext"
|
|
||||||
"git.blackforestbytes.com/BlackForestBytes/goext/mathext"
|
|
||||||
"git.blackforestbytes.com/BlackForestBytes/goext/rext"
|
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"git.blackforestbytes.com/BlackForestBytes/goext/exerr"
|
||||||
|
"git.blackforestbytes.com/BlackForestBytes/goext/langext"
|
||||||
|
"git.blackforestbytes.com/BlackForestBytes/goext/mathext"
|
||||||
|
"git.blackforestbytes.com/BlackForestBytes/goext/rext"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
type GinWrapper struct {
|
type GinWrapper struct {
|
||||||
@@ -103,7 +105,10 @@ func NewEngine(opt Options) *GinWrapper {
|
|||||||
return wrapper
|
return wrapper
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *GinWrapper) ListenAndServeHTTP(addr string, postInit func(port string)) (chan error, *http.Server) {
|
// ListenAndServeHTTP
|
||||||
|
// returns nil, nil, err if something went wrong during init
|
||||||
|
// returns $chan, $server, nil if init was successful ( later errors come through chan )
|
||||||
|
func (w *GinWrapper) ListenAndServeHTTP(addr string, postInit func(port string)) (chan error, *http.Server, error) {
|
||||||
|
|
||||||
w.DebugPrintRoutes()
|
w.DebugPrintRoutes()
|
||||||
|
|
||||||
@@ -114,30 +119,25 @@ func (w *GinWrapper) ListenAndServeHTTP(addr string, postInit func(port string))
|
|||||||
|
|
||||||
errChan := make(chan error)
|
errChan := make(chan error)
|
||||||
|
|
||||||
go func() {
|
ln, err := net.Listen("tcp", httpserver.Addr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, exerr.Wrap(err, "").Build()
|
||||||
|
}
|
||||||
|
|
||||||
ln, err := net.Listen("tcp", httpserver.Addr)
|
_, port, err := net.SplitHostPort(ln.Addr().String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errChan <- err
|
return nil, nil, exerr.Wrap(err, "").Build()
|
||||||
return
|
}
|
||||||
}
|
|
||||||
|
|
||||||
_, port, err := net.SplitHostPort(ln.Addr().String())
|
log.Info().Str("address", httpserver.Addr).Msg("HTTP-Server started on http://localhost:" + port)
|
||||||
if err != nil {
|
|
||||||
errChan <- err
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Info().Str("address", httpserver.Addr).Msg("HTTP-Server started on http://localhost:" + port)
|
if postInit != nil {
|
||||||
|
postInit(port) // the net.Listener a few lines above is at this point actually already buffering requests
|
||||||
|
}
|
||||||
|
|
||||||
if postInit != nil {
|
go func() { errChan <- httpserver.Serve(ln) }()
|
||||||
postInit(port) // the net.Listener a few lines above is at this point actually already buffering requests
|
|
||||||
}
|
|
||||||
|
|
||||||
errChan <- httpserver.Serve(ln)
|
return errChan, httpserver, nil
|
||||||
}()
|
|
||||||
|
|
||||||
return errChan, httpserver
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *GinWrapper) DebugPrintRoutes() {
|
func (w *GinWrapper) DebugPrintRoutes() {
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ require (
|
|||||||
github.com/rs/xid v1.6.0
|
github.com/rs/xid v1.6.0
|
||||||
github.com/rs/zerolog v1.35.1
|
github.com/rs/zerolog v1.35.1
|
||||||
go.mongodb.org/mongo-driver/v2 v2.6.0
|
go.mongodb.org/mongo-driver/v2 v2.6.0
|
||||||
golang.org/x/crypto v0.50.0
|
golang.org/x/crypto v0.52.0
|
||||||
golang.org/x/sys v0.43.0
|
golang.org/x/sys v0.45.0
|
||||||
golang.org/x/term v0.42.0
|
golang.org/x/term v0.43.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
@@ -49,7 +49,7 @@ require (
|
|||||||
github.com/ncruces/go-strftime v1.0.0 // indirect
|
github.com/ncruces/go-strftime v1.0.0 // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.3.1 // indirect
|
github.com/pelletier/go-toml/v2 v2.3.1 // indirect
|
||||||
github.com/quic-go/qpack v0.6.0 // indirect
|
github.com/quic-go/qpack v0.6.0 // indirect
|
||||||
github.com/quic-go/quic-go v0.59.0 // indirect
|
github.com/quic-go/quic-go v0.59.1 // indirect
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||||
github.com/richardlehane/mscfb v1.0.6 // indirect
|
github.com/richardlehane/mscfb v1.0.6 // indirect
|
||||||
github.com/richardlehane/msoleps v1.0.6 // indirect
|
github.com/richardlehane/msoleps v1.0.6 // indirect
|
||||||
@@ -62,10 +62,10 @@ require (
|
|||||||
github.com/xuri/efp v0.0.1 // indirect
|
github.com/xuri/efp v0.0.1 // indirect
|
||||||
github.com/xuri/nfp v0.0.2-0.20250530014748-2ddeb826f9a9 // indirect
|
github.com/xuri/nfp v0.0.2-0.20250530014748-2ddeb826f9a9 // indirect
|
||||||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
|
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
|
||||||
golang.org/x/arch v0.26.0 // indirect
|
golang.org/x/arch v0.27.0 // indirect
|
||||||
golang.org/x/image v0.39.0 // indirect
|
golang.org/x/image v0.41.0 // indirect
|
||||||
golang.org/x/net v0.53.0 // indirect
|
golang.org/x/net v0.55.0 // indirect
|
||||||
golang.org/x/text v0.36.0 // indirect
|
golang.org/x/text v0.37.0 // indirect
|
||||||
google.golang.org/protobuf v1.36.11 // indirect
|
google.golang.org/protobuf v1.36.11 // indirect
|
||||||
modernc.org/libc v1.72.0 // indirect
|
modernc.org/libc v1.72.0 // indirect
|
||||||
modernc.org/mathutil v1.7.1 // indirect
|
modernc.org/mathutil v1.7.1 // indirect
|
||||||
|
|||||||
@@ -101,6 +101,8 @@ github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8=
|
|||||||
github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII=
|
github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII=
|
||||||
github.com/quic-go/quic-go v0.59.0 h1:OLJkp1Mlm/aS7dpKgTc6cnpynnD2Xg7C1pwL6vy/SAw=
|
github.com/quic-go/quic-go v0.59.0 h1:OLJkp1Mlm/aS7dpKgTc6cnpynnD2Xg7C1pwL6vy/SAw=
|
||||||
github.com/quic-go/quic-go v0.59.0/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU=
|
github.com/quic-go/quic-go v0.59.0/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU=
|
||||||
|
github.com/quic-go/quic-go v0.59.1 h1:0Gmua0HW1Tv7ANR7hUYwRyD0MG5OJfgvYSZasGZzBic=
|
||||||
|
github.com/quic-go/quic-go v0.59.1/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
github.com/richardlehane/mscfb v1.0.6 h1:eN3bvvZCp00bs7Zf52bxNwAx5lJDBK1tCuH19qq5aC8=
|
github.com/richardlehane/mscfb v1.0.6 h1:eN3bvvZCp00bs7Zf52bxNwAx5lJDBK1tCuH19qq5aC8=
|
||||||
@@ -154,22 +156,37 @@ go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
|
|||||||
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
|
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
|
||||||
golang.org/x/arch v0.26.0 h1:jZ6dpec5haP/fUv1kLCbuJy6dnRrfX6iVK08lZBFpk4=
|
golang.org/x/arch v0.26.0 h1:jZ6dpec5haP/fUv1kLCbuJy6dnRrfX6iVK08lZBFpk4=
|
||||||
golang.org/x/arch v0.26.0/go.mod h1:0X+GdSIP+kL5wPmpK7sdkEVTt2XoYP0cSjQSbZBwOi8=
|
golang.org/x/arch v0.26.0/go.mod h1:0X+GdSIP+kL5wPmpK7sdkEVTt2XoYP0cSjQSbZBwOi8=
|
||||||
|
golang.org/x/arch v0.27.0 h1:0WNVcR8u9yFz8j5FvdHpgwNp3FS5U4guYdzHwEiGjoU=
|
||||||
|
golang.org/x/arch v0.27.0/go.mod h1:0X+GdSIP+kL5wPmpK7sdkEVTt2XoYP0cSjQSbZBwOi8=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI=
|
golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI=
|
||||||
golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q=
|
golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q=
|
||||||
|
golang.org/x/crypto v0.51.0 h1:IBPXwPfKxY7cWQZ38ZCIRPI50YLeevDLlLnyC5wRGTI=
|
||||||
|
golang.org/x/crypto v0.51.0/go.mod h1:8AdwkbraGNABw2kOX6YFPs3WM22XqI4EXEd8g+x7Oc8=
|
||||||
|
golang.org/x/crypto v0.52.0 h1:RMs7fP2rXdep0CftQlK8Uf+kibLm7qkCcradZWYz988=
|
||||||
|
golang.org/x/crypto v0.52.0/go.mod h1:1QgfPxDqh0T2M/elOJtp9RvuR95kVjir0e6/BvEmGbc=
|
||||||
golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
golang.org/x/image v0.39.0 h1:skVYidAEVKgn8lZ602XO75asgXBgLj9G/FE3RbuPFww=
|
golang.org/x/image v0.39.0 h1:skVYidAEVKgn8lZ602XO75asgXBgLj9G/FE3RbuPFww=
|
||||||
golang.org/x/image v0.39.0/go.mod h1:sIbmppfU+xFLPIG0FoVUTvyBMmgng1/XAMhQ2ft0hpA=
|
golang.org/x/image v0.39.0/go.mod h1:sIbmppfU+xFLPIG0FoVUTvyBMmgng1/XAMhQ2ft0hpA=
|
||||||
|
golang.org/x/image v0.40.0 h1:Tw4GyDXMo+daZN1znreBRC3VayR1aLFUyUEOLUdW1a8=
|
||||||
|
golang.org/x/image v0.40.0/go.mod h1:uIc348UZMSvS5Z65CVZ7iDPaNobNFEPeJ4kbqTOszmA=
|
||||||
|
golang.org/x/image v0.41.0 h1:8wS72eGJMJaBxK6okTzd4WaXumUlTVlb753MlsSvTCo=
|
||||||
|
golang.org/x/image v0.41.0/go.mod h1:uIc348UZMSvS5Z65CVZ7iDPaNobNFEPeJ4kbqTOszmA=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/mod v0.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI=
|
golang.org/x/mod v0.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI=
|
||||||
golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY=
|
golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY=
|
||||||
|
golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA=
|
golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA=
|
||||||
golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs=
|
golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs=
|
||||||
|
golang.org/x/net v0.54.0 h1:2zJIZAxAHV/OHCDTCOHAYehQzLfSXuf/5SoL/Dv6w/w=
|
||||||
|
golang.org/x/net v0.54.0/go.mod h1:Sj4oj8jK6XmHpBZU/zWHw3BV3abl4Kvi+Ut7cQcY+cQ=
|
||||||
|
golang.org/x/net v0.55.0 h1:bcvxaJn3e1U6InsFWt1JUq1aSjnRxLzT2rtD2KfkDF8=
|
||||||
|
golang.org/x/net v0.55.0/go.mod h1:L5U2KuzuOe1lY7Z+aWVIKK6qEeJXnXV9yzGA+WCHJww=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
|
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
|
||||||
@@ -181,21 +198,30 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI=
|
golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI=
|
||||||
golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||||
|
golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ=
|
||||||
|
golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||||
|
golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY=
|
||||||
|
golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY=
|
golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY=
|
||||||
golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY=
|
golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY=
|
||||||
|
golang.org/x/term v0.43.0 h1:S4RLU2sB31O/NCl+zFN9Aru9A/Cq2aqKpTZJ6B+DwT4=
|
||||||
|
golang.org/x/term v0.43.0/go.mod h1:lrhlHNdQJHO+1qVYiHfFKVuVioJIheAc3fBSMFYEIsk=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||||
golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
|
golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
|
||||||
golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
|
golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
|
||||||
|
golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc=
|
||||||
|
golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
golang.org/x/tools v0.43.0 h1:12BdW9CeB3Z+J/I/wj34VMl8X+fEXBxVR90JeMX5E7s=
|
golang.org/x/tools v0.43.0 h1:12BdW9CeB3Z+J/I/wj34VMl8X+fEXBxVR90JeMX5E7s=
|
||||||
golang.org/x/tools v0.43.0/go.mod h1:uHkMso649BX2cZK6+RpuIPXS3ho2hZo4FVwfoy1vIk0=
|
golang.org/x/tools v0.43.0/go.mod h1:uHkMso649BX2cZK6+RpuIPXS3ho2hZo4FVwfoy1vIk0=
|
||||||
|
golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||||
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||||
|
|||||||
+2
-2
@@ -1,5 +1,5 @@
|
|||||||
package goext
|
package goext
|
||||||
|
|
||||||
const GoextVersion = "0.0.637"
|
const GoextVersion = "0.0.641"
|
||||||
|
|
||||||
const GoextVersionTimestamp = "2026-05-06T16:11:01+0200"
|
const GoextVersionTimestamp = "2026-05-22T22:06:05+0200"
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ func DblPtrNil[T any]() **T {
|
|||||||
return &v
|
return &v
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:fix inline
|
|
||||||
func ArrPtr[T any](v ...T) *[]T {
|
func ArrPtr[T any](v ...T) *[]T {
|
||||||
return new(v)
|
return new(v)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,14 +7,23 @@ import (
|
|||||||
ct "git.blackforestbytes.com/BlackForestBytes/goext/cursortoken"
|
ct "git.blackforestbytes.com/BlackForestBytes/goext/cursortoken"
|
||||||
"git.blackforestbytes.com/BlackForestBytes/goext/exerr"
|
"git.blackforestbytes.com/BlackForestBytes/goext/exerr"
|
||||||
"git.blackforestbytes.com/BlackForestBytes/goext/langext"
|
"git.blackforestbytes.com/BlackForestBytes/goext/langext"
|
||||||
|
"go.mongodb.org/mongo-driver/v2/bson"
|
||||||
"go.mongodb.org/mongo-driver/v2/mongo"
|
"go.mongodb.org/mongo-driver/v2/mongo"
|
||||||
)
|
)
|
||||||
|
|
||||||
type EntityID interface {
|
type EntityID interface {
|
||||||
MarshalBSONValue() (byte, []byte, error)
|
MarshalBSONValue() (byte, []byte, error)
|
||||||
|
IsZero() bool
|
||||||
String() string
|
String() string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type MongoEntityID interface {
|
||||||
|
EntityID
|
||||||
|
|
||||||
|
ObjID() (bson.ObjectID, error)
|
||||||
|
Valid() bool
|
||||||
|
}
|
||||||
|
|
||||||
type Decodable interface {
|
type Decodable interface {
|
||||||
Decode(v any) error
|
Decode(v any) error
|
||||||
}
|
}
|
||||||
|
|||||||
+55
-25
@@ -401,14 +401,18 @@ func createPaginationPipeline[TData any](coll *Coll[TData], token ct.CTKeySort,
|
|||||||
return nil, nil, exerr.Wrap(err, "failed to get (primary) token-value as mongo-type").Build()
|
return nil, nil, exerr.Wrap(err, "failed to get (primary) token-value as mongo-type").Build()
|
||||||
}
|
}
|
||||||
|
|
||||||
if sortPrimary == ct.SortASC {
|
if isValidTokenValue(valuePrimary) {
|
||||||
// We sort ASC on <field> - so we want all entries newer ($gt) than the $primary
|
|
||||||
cond = append(cond, bson.M{fieldPrimary: bson.M{"$gt": valuePrimary}})
|
if sortPrimary == ct.SortASC {
|
||||||
sort = append(sort, bson.E{Key: fieldPrimary, Value: +1})
|
// We sort ASC on <field> - so we want all entries newer ($gt) than the $primary
|
||||||
} else if sortPrimary == ct.SortDESC {
|
cond = append(cond, bson.M{fieldPrimary: bson.M{"$gt": valuePrimary}})
|
||||||
// We sort DESC on <field> - so we want all entries older ($lt) than the $primary
|
sort = append(sort, bson.E{Key: fieldPrimary, Value: +1})
|
||||||
cond = append(cond, bson.M{fieldPrimary: bson.M{"$lt": valuePrimary}})
|
} else if sortPrimary == ct.SortDESC {
|
||||||
sort = append(sort, bson.E{Key: fieldPrimary, Value: -1})
|
// We sort DESC on <field> - so we want all entries older ($lt) than the $primary
|
||||||
|
cond = append(cond, bson.M{fieldPrimary: bson.M{"$lt": valuePrimary}})
|
||||||
|
sort = append(sort, bson.E{Key: fieldPrimary, Value: -1})
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if fieldSecondary != nil && sortSecondary != nil && *fieldSecondary != fieldPrimary {
|
if fieldSecondary != nil && sortSecondary != nil && *fieldSecondary != fieldPrimary {
|
||||||
@@ -418,25 +422,29 @@ func createPaginationPipeline[TData any](coll *Coll[TData], token ct.CTKeySort,
|
|||||||
return nil, nil, exerr.Wrap(err, "failed to get (secondary) token-value as mongo-type").Build()
|
return nil, nil, exerr.Wrap(err, "failed to get (secondary) token-value as mongo-type").Build()
|
||||||
}
|
}
|
||||||
|
|
||||||
if *sortSecondary == ct.SortASC {
|
if isValidTokenValue(valueSecondary) {
|
||||||
|
|
||||||
// the conflict-resolution condition, for entries with the _same_ <field> as the $primary we take the ones with a greater $secondary (= newer)
|
if *sortSecondary == ct.SortASC {
|
||||||
cond = append(cond, bson.M{"$and": bson.A{
|
|
||||||
bson.M{"$or": bson.A{bson.M{fieldPrimary: valuePrimary}, bson.M{fieldPrimary: nil}, bson.M{fieldPrimary: bson.M{"$exists": false}}}},
|
|
||||||
bson.M{*fieldSecondary: bson.M{"$gt": valueSecondary}},
|
|
||||||
}})
|
|
||||||
|
|
||||||
sort = append(sort, bson.E{Key: *fieldSecondary, Value: +1})
|
// the conflict-resolution condition, for entries with the _same_ <field> as the $primary we take the ones with a greater $secondary (= newer)
|
||||||
|
cond = append(cond, bson.M{"$and": bson.A{
|
||||||
|
bson.M{"$or": bson.A{bson.M{fieldPrimary: valuePrimary}, bson.M{fieldPrimary: nil}, bson.M{fieldPrimary: bson.M{"$exists": false}}}},
|
||||||
|
bson.M{*fieldSecondary: bson.M{"$gt": valueSecondary}},
|
||||||
|
}})
|
||||||
|
|
||||||
} else if *sortSecondary == ct.SortDESC {
|
sort = append(sort, bson.E{Key: *fieldSecondary, Value: +1})
|
||||||
|
|
||||||
// the conflict-resolution condition, for entries with the _same_ <field> as the $primary we take the ones with a smaller $secondary (= older)
|
} else if *sortSecondary == ct.SortDESC {
|
||||||
cond = append(cond, bson.M{"$and": bson.A{
|
|
||||||
bson.M{"$or": bson.A{bson.M{fieldPrimary: valuePrimary}, bson.M{fieldPrimary: nil}, bson.M{fieldPrimary: bson.M{"$exists": false}}}},
|
|
||||||
bson.M{*fieldSecondary: bson.M{"$lt": valueSecondary}},
|
|
||||||
}})
|
|
||||||
|
|
||||||
sort = append(sort, bson.E{Key: *fieldSecondary, Value: -1})
|
// the conflict-resolution condition, for entries with the _same_ <field> as the $primary we take the ones with a smaller $secondary (= older)
|
||||||
|
cond = append(cond, bson.M{"$and": bson.A{
|
||||||
|
bson.M{"$or": bson.A{bson.M{fieldPrimary: valuePrimary}, bson.M{fieldPrimary: nil}, bson.M{fieldPrimary: bson.M{"$exists": false}}}},
|
||||||
|
bson.M{*fieldSecondary: bson.M{"$lt": valueSecondary}},
|
||||||
|
}})
|
||||||
|
|
||||||
|
sort = append(sort, bson.E{Key: *fieldSecondary, Value: -1})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -449,7 +457,9 @@ func createPaginationPipeline[TData any](coll *Coll[TData], token ct.CTKeySort,
|
|||||||
|
|
||||||
} else if token.Mode == ct.CTMNormal {
|
} else if token.Mode == ct.CTMNormal {
|
||||||
|
|
||||||
pipeline = append(pipeline, bson.D{{Key: "$match", Value: bson.M{"$or": cond}}})
|
if len(cond) > 0 {
|
||||||
|
pipeline = append(pipeline, bson.D{{Key: "$match", Value: bson.M{"$or": cond}}})
|
||||||
|
}
|
||||||
|
|
||||||
} else if token.Mode == ct.CTMEnd {
|
} else if token.Mode == ct.CTMEnd {
|
||||||
|
|
||||||
@@ -462,9 +472,15 @@ func createPaginationPipeline[TData any](coll *Coll[TData], token ct.CTKeySort,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pipeline = append(pipeline, bson.D{{Key: "$sort", Value: sort}})
|
if len(sort) > 0 {
|
||||||
|
pipeline = append(pipeline, bson.D{{Key: "$sort", Value: sort}})
|
||||||
|
}
|
||||||
|
|
||||||
pipelineSort := mongo.Pipeline{bson.D{{Key: "$sort", Value: sort}}}
|
pipelineSort := mongo.Pipeline{}
|
||||||
|
|
||||||
|
if len(sort) > 0 {
|
||||||
|
pipelineSort = append(pipelineSort, bson.D{{Key: "$sort", Value: sort}})
|
||||||
|
}
|
||||||
|
|
||||||
if pageSize != nil {
|
if pageSize != nil {
|
||||||
pipeline = append(pipeline, bson.D{{Key: "$limit", Value: int64(*pageSize + 1)}})
|
pipeline = append(pipeline, bson.D{{Key: "$limit", Value: int64(*pageSize + 1)}})
|
||||||
@@ -473,6 +489,20 @@ func createPaginationPipeline[TData any](coll *Coll[TData], token ct.CTKeySort,
|
|||||||
return pipeline, pipelineSort, nil
|
return pipeline, pipelineSort, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isValidTokenValue(val any) bool {
|
||||||
|
|
||||||
|
// special handling for Mongo EntityIDs
|
||||||
|
// We want to prevent failing late (in mongoDB layer) when client sends invalid IDs as token values
|
||||||
|
|
||||||
|
if mongoID, ok := val.(MongoEntityID); ok {
|
||||||
|
if !mongoID.Valid() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func createSortOnlyPipeline(fieldPrimary string, sortPrimary ct.SortDirection, fieldSecondary *string, sortSecondary *ct.SortDirection) ([]bson.D, error) {
|
func createSortOnlyPipeline(fieldPrimary string, sortPrimary ct.SortDirection, fieldSecondary *string, sortSecondary *ct.SortDirection) ([]bson.D, error) {
|
||||||
|
|
||||||
sort := bson.D{}
|
sort := bson.D{}
|
||||||
|
|||||||
@@ -0,0 +1,107 @@
|
|||||||
|
package wmo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
ct "git.blackforestbytes.com/BlackForestBytes/goext/cursortoken"
|
||||||
|
"git.blackforestbytes.com/BlackForestBytes/goext/exerr"
|
||||||
|
"git.blackforestbytes.com/BlackForestBytes/goext/langext"
|
||||||
|
"git.blackforestbytes.com/BlackForestBytes/goext/rfctime"
|
||||||
|
"git.blackforestbytes.com/BlackForestBytes/goext/tst"
|
||||||
|
"go.mongodb.org/mongo-driver/v2/bson"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TestExampleID string //@id:type
|
||||||
|
|
||||||
|
func (i TestExampleID) MarshalBSONValue() (byte, []byte, error) {
|
||||||
|
if objId, err := bson.ObjectIDFromHex(string(i)); err == nil {
|
||||||
|
tp, data, err := bson.MarshalValue(objId)
|
||||||
|
return byte(tp), data, err
|
||||||
|
} else {
|
||||||
|
return 0, nil, exerr.New(exerr.TypeMarshalEntityID, "Failed to marshal UserID("+i.String()+") to ObjectId").Str("value", string(i)).Type("type", i).Build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i TestExampleID) String() string {
|
||||||
|
return string(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i TestExampleID) ObjID() (bson.ObjectID, error) {
|
||||||
|
return bson.ObjectIDFromHex(string(i))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i TestExampleID) Valid() bool {
|
||||||
|
_, err := bson.ObjectIDFromHex(string(i))
|
||||||
|
return err == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i TestExampleID) IsZero() bool {
|
||||||
|
return i == ""
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ MongoEntityID = (*TestExampleID)(nil)
|
||||||
|
|
||||||
|
func TestCreatePaginationPipelineWithInvalidObjectIDValue(t *testing.T) {
|
||||||
|
//
|
||||||
|
// {"v1":"2026-05-16T21:44:13.16Z","v2":"6a08e52d144a332c2e2d067b","dir":"DESC","dir2":"DESC","size":50}
|
||||||
|
strtok := "tok_PMRHMMJCHIRDEMBSGYWTANJNGE3FIMRRHI2DIORRGMXDCNS2EIWCE5RSEI5CENTBGA4GKNJSMQYTINDBGMZTEYZSMUZGIMBWG5RCELBCMRUXEIR2EJCEKU2DEIWCEZDJOIZCEORCIRCVGQZCFQRHG2L2MURDUNJQPU======"
|
||||||
|
|
||||||
|
tok, err := ct.Decode(strtok)
|
||||||
|
if err != nil {
|
||||||
|
t.Error("Failed to decode token:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type obj struct {
|
||||||
|
ID TestExampleID `bson:"_id"`
|
||||||
|
Created rfctime.RFC3339NanoTime `bson:"created"`
|
||||||
|
}
|
||||||
|
|
||||||
|
coll := Coll[obj]{coll: nil}
|
||||||
|
coll.init()
|
||||||
|
|
||||||
|
paginationPipeline, doubleSortPipeline, err := createPaginationPipeline[obj](&coll, tok.(ct.CTKeySort), "_id", ct.SortDESC, new("_id"), new(ct.SortDESC), new(15))
|
||||||
|
if err != nil {
|
||||||
|
t.Error("Failed to create pagination Pipeline:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//fmt.Printf("# paginationPipeline:\n%+v\n\n", string(langext.Must(json.Marshal(paginationPipeline))))
|
||||||
|
//fmt.Printf("# doubleSortPipeline:\n%+v\n\n", string(langext.Must(json.Marshal(doubleSortPipeline))))
|
||||||
|
|
||||||
|
tst.AssertEqual(t, string(langext.Must(json.Marshal(paginationPipeline))), `[{"$limit":16}]`) // wrong (_id with wrong date type) fields are not used
|
||||||
|
tst.AssertEqual(t, string(langext.Must(json.Marshal(doubleSortPipeline))), `[]`) // wrong (_id with wrong date type) fields are not used
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreatePaginationPipelineWithValidObjectIDValue(t *testing.T) {
|
||||||
|
//
|
||||||
|
// {"v1":"6a08e52d144a332c2e2d067b","v2":"6a08e52d144a332c2e2d067b","dir":"DESC","dir2":"DESC","size":50}
|
||||||
|
strtok := "tok_PMFCAIBAEARHMMJCHIQCENTBGA4GKNJSMQYTINDBGMZTEYZSMUZGIMBWG5RCELAKEAQCAIBCOYZCEORAEI3GCMBYMU2TEZBRGQ2GCMZTGJRTEZJSMQYDMN3CEIWAUIBAEAQCEZDJOIRDUIBCIRCVGQZCFQFCAIBAEARGI2LSGIRDUIBCIRCVGQZCFQFCAIBAEARHG2L2MURDUIBVGAFH2==="
|
||||||
|
|
||||||
|
tok, err := ct.Decode(strtok)
|
||||||
|
if err != nil {
|
||||||
|
t.Error("Failed to decode token:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type obj struct {
|
||||||
|
ID TestExampleID `bson:"_id"`
|
||||||
|
Created rfctime.RFC3339NanoTime `bson:"created"`
|
||||||
|
}
|
||||||
|
|
||||||
|
coll := Coll[obj]{coll: nil}
|
||||||
|
coll.init()
|
||||||
|
|
||||||
|
paginationPipeline, doubleSortPipeline, err := createPaginationPipeline[obj](&coll, tok.(ct.CTKeySort), "_id", ct.SortDESC, new("_id"), new(ct.SortDESC), new(15))
|
||||||
|
if err != nil {
|
||||||
|
t.Error("Failed to create pagination Pipeline:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//fmt.Printf("# paginationPipeline:\n%+v\n\n", string(langext.Must(json.Marshal(paginationPipeline))))
|
||||||
|
//fmt.Printf("# doubleSortPipeline:\n%+v\n\n", string(langext.Must(json.Marshal(doubleSortPipeline))))
|
||||||
|
|
||||||
|
tst.AssertEqual(t, string(langext.Must(json.Marshal(paginationPipeline))), `[{"$match":{"$or":[{"_id":{"$lt":"6a08e52d144a332c2e2d067b"}}]}},{"$sort":{"_id":-1}},{"$limit":16}]`)
|
||||||
|
tst.AssertEqual(t, string(langext.Must(json.Marshal(doubleSortPipeline))), `[{"$sort":{"_id":-1}}]`)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user