Compare commits

...

27 Commits

Author SHA1 Message Date
dcb5d3d7cd v0.0.444 change gin values in exerr auto meta to not include dots in keys (fucks up mongo)
Some checks failed
Build Docker and Deploy / Run goext test-suite (push) Failing after 3m9s
2024-05-03 13:24:08 +02:00
15a639f85a v0.0.443 fix wmo.List with pageSize==0
Some checks failed
Build Docker and Deploy / Run goext test-suite (push) Failing after 3m9s
2024-05-03 11:56:29 +02:00
303bd04649 v0.0.442
All checks were successful
Build Docker and Deploy / Run goext test-suite (push) Successful in 2m0s
2024-04-29 17:24:10 +02:00
7bda674939 v0.0.441
Some checks failed
Build Docker and Deploy / Run goext test-suite (push) Failing after 2m29s
2024-04-29 17:19:55 +02:00
126d4fbd0b v0.0.440 improve exerr.toJson
Some checks failed
Build Docker and Deploy / Run goext test-suite (push) Failing after 2m54s
2024-04-29 16:03:58 +02:00
fed8bccaab v0.0.439
All checks were successful
Build Docker and Deploy / Run goext test-suite (push) Successful in 1m38s
2024-04-25 11:47:16 +02:00
47b6a6b508 v0.0.438
All checks were successful
Build Docker and Deploy / Run goext test-suite (push) Successful in 3m20s
2024-04-25 11:40:01 +02:00
764ce79a71 v0.0.437 properly handle $group in wmo extraModPipeline
Some checks failed
Build Docker and Deploy / Run goext test-suite (push) Failing after 3m23s
2024-04-23 16:12:17 +02:00
b876c64ba2 v0.0.436
All checks were successful
Build Docker and Deploy / Run goext test-suite (push) Successful in 1m56s
2024-04-18 14:09:26 +02:00
8d52b41f57 v0.0.435 add ConvertStructToMapOpt.MaxDepth
All checks were successful
Build Docker and Deploy / Run goext test-suite (push) Successful in 2m39s
2024-04-15 12:55:44 +02:00
f47e2a33fe v0.0.434
All checks were successful
Build Docker and Deploy / Run goext test-suite (push) Successful in 1m13s
2024-04-15 10:43:26 +02:00
9321938dad v0.0.433 fix exerr missing gindata when using ginext.Error and add config for Output logging to stderr
All checks were successful
Build Docker and Deploy / Run goext test-suite (push) Successful in 4m0s
2024-04-15 10:25:30 +02:00
3828d601a2 v0.0.432 better handling of unmarshall-able values in exerr meta
All checks were successful
Build Docker and Deploy / Run goext test-suite (push) Successful in 2m12s
2024-04-13 22:08:45 +02:00
2e713c808d v0.0.431
Some checks failed
Build Docker and Deploy / Run goext test-suite (push) Failing after 1m10s
2024-04-10 15:29:59 +02:00
6602f86b43 v0.0.430
Some checks failed
Build Docker and Deploy / Run goext test-suite (push) Has been cancelled
2024-04-10 15:27:41 +02:00
24d9f0fdc7 v0.0.429
All checks were successful
Build Docker and Deploy / Run goext test-suite (push) Successful in 3m23s
2024-04-08 16:33:44 +02:00
8446b2da22 v0.0.428
Some checks failed
Build Docker and Deploy / Run goext test-suite (push) Has been cancelled
2024-04-08 16:32:34 +02:00
758e5a67b5 v0.0.427
All checks were successful
Build Docker and Deploy / Run goext test-suite (push) Successful in 3m30s
2024-04-07 15:10:21 +02:00
678ddd7124 v0.0.426 fix JsonOpt
All checks were successful
Build Docker and Deploy / Run goext test-suite (push) Successful in 3m57s
2024-04-01 16:03:00 +02:00
36b71dfaf3 v0.0.425 ArrAppend
All checks were successful
Build Docker and Deploy / Run goext test-suite (push) Successful in 2m25s
2024-03-30 14:24:53 +01:00
9491b72b8d v0.0.424 timeext.SubtractYears
All checks were successful
Build Docker and Deploy / Run goext test-suite (push) Successful in 3m29s
2024-03-30 03:01:55 +01:00
6c4af4006b v0.0.423 fix createPaginationPipeline - different primary and secondary sort keys broke mongo ??!?? - it actually only sorted by the secondary condition (ignoring the primary?)
All checks were successful
Build Docker and Deploy / Run goext test-suite (push) Successful in 1m32s
2024-03-24 15:25:52 +01:00
8bf3a337cf v0.0.422
All checks were successful
Build Docker and Deploy / Run goext test-suite (push) Successful in 1m29s
2024-03-23 20:29:46 +01:00
16146494dc v0.0.421
Some checks failed
Build Docker and Deploy / Run goext test-suite (push) Failing after 32s
2024-03-23 20:28:51 +01:00
b0e443ad99 v0.0.420
Some checks failed
Build Docker and Deploy / Run goext test-suite (push) Failing after 36s
2024-03-23 18:01:41 +01:00
9955eacf96 v0.0.419 JsonOpt
Some checks failed
Build Docker and Deploy / Run goext test-suite (push) Failing after 39s
2024-03-23 17:49:56 +01:00
f0347a9435 v0.0.418 fix tests?
All checks were successful
Build Docker and Deploy / Run goext test-suite (push) Successful in 3m1s
2024-03-20 09:42:06 +01:00
26 changed files with 482 additions and 66 deletions

59
dataext/optional.go Normal file
View File

@@ -0,0 +1,59 @@
package dataext
import (
"encoding/json"
"errors"
)
type JsonOpt[T any] struct {
isSet bool
value T
}
// MarshalJSON returns m as the JSON encoding of m.
func (m JsonOpt[T]) MarshalJSON() ([]byte, error) {
if !m.isSet {
return []byte("null"), nil // actually this would be undefined - but undefined is not valid JSON
}
return json.Marshal(m.value)
}
// UnmarshalJSON sets *m to a copy of data.
func (m *JsonOpt[T]) UnmarshalJSON(data []byte) error {
if m == nil {
return errors.New("JsonOpt: UnmarshalJSON on nil pointer")
}
m.isSet = true
return json.Unmarshal(data, &m.value)
}
func (m JsonOpt[T]) IsSet() bool {
return m.isSet
}
func (m JsonOpt[T]) IsUnset() bool {
return !m.isSet
}
func (m JsonOpt[T]) Value() (T, bool) {
if !m.isSet {
return *new(T), false
}
return m.value, true
}
func (m JsonOpt[T]) ValueOrNil() *T {
if !m.isSet {
return nil
}
return &m.value
}
func (m JsonOpt[T]) MustValue() T {
if !m.isSet {
panic("value not set")
}
return m.value
}

View File

@@ -309,27 +309,27 @@ func (b *Builder) Errs(key string, val []error) *Builder {
func (b *Builder) GinReq(ctx context.Context, g *gin.Context, req *http.Request) *Builder { func (b *Builder) GinReq(ctx context.Context, g *gin.Context, req *http.Request) *Builder {
if v := ctx.Value("start_timestamp"); v != nil { if v := ctx.Value("start_timestamp"); v != nil {
if t, ok := v.(time.Time); ok { if t, ok := v.(time.Time); ok {
b.Time("ctx.startTimestamp", t) b.Time("ctx_startTimestamp", t)
b.Time("ctx.endTimestamp", time.Now()) b.Time("ctx_endTimestamp", time.Now())
} }
} }
b.Str("gin.method", req.Method) b.Str("gin_method", req.Method)
b.Str("gin.path", g.FullPath()) b.Str("gin_path", g.FullPath())
b.Strs("gin.header", extractHeader(g.Request.Header)) b.Strs("gin_header", extractHeader(g.Request.Header))
if req.URL != nil { if req.URL != nil {
b.Str("gin.url", req.URL.String()) b.Str("gin_url", req.URL.String())
} }
if ctxVal := g.GetString("apiversion"); ctxVal != "" { if ctxVal := g.GetString("apiversion"); ctxVal != "" {
b.Str("gin.context.apiversion", ctxVal) b.Str("gin_context_apiversion", ctxVal)
} }
if ctxVal := g.GetString("uid"); ctxVal != "" { if ctxVal := g.GetString("uid"); ctxVal != "" {
b.Str("gin.context.uid", ctxVal) b.Str("gin_context_uid", ctxVal)
} }
if ctxVal := g.GetString("fcmId"); ctxVal != "" { if ctxVal := g.GetString("fcmId"); ctxVal != "" {
b.Str("gin.context.fcmid", ctxVal) b.Str("gin_context_fcmid", ctxVal)
} }
if ctxVal := g.GetString("reqid"); ctxVal != "" { if ctxVal := g.GetString("reqid"); ctxVal != "" {
b.Str("gin.context.reqid", ctxVal) b.Str("gin_context_reqid", ctxVal)
} }
if req.Method != "GET" && req.Body != nil { if req.Method != "GET" && req.Body != nil {
@@ -340,12 +340,12 @@ func (b *Builder) GinReq(ctx context.Context, g *gin.Context, req *http.Request)
var prettyJSON bytes.Buffer var prettyJSON bytes.Buffer
err = json.Indent(&prettyJSON, bin, "", " ") err = json.Indent(&prettyJSON, bin, "", " ")
if err == nil { if err == nil {
b.Str("gin.body", string(prettyJSON.Bytes())) b.Str("gin_body", string(prettyJSON.Bytes()))
} else { } else {
b.Bytes("gin.body", bin) b.Bytes("gin_body", bin)
} }
} else { } else {
b.Str("gin.body", fmt.Sprintf("[[%v bytes | %s]]", len(bin), req.Header.Get("Content-Type"))) b.Str("gin_body", fmt.Sprintf("[[%v bytes | %s]]", len(bin), req.Header.Get("Content-Type")))
} }
} }
} }
@@ -355,9 +355,9 @@ func (b *Builder) GinReq(ctx context.Context, g *gin.Context, req *http.Request)
if brc, ok := req.Body.(dataext.BufferedReadCloser); ok { if brc, ok := req.Body.(dataext.BufferedReadCloser); ok {
if bin, err := brc.BufferedAll(); err == nil { if bin, err := brc.BufferedAll(); err == nil {
if len(bin) < 16*1024 { if len(bin) < 16*1024 {
b.Bytes("gin.body", bin) b.Bytes("gin_body", bin)
} else { } else {
b.Str("gin.body", fmt.Sprintf("[[%v bytes | %s]]", len(bin), req.Header.Get("Content-Type"))) b.Str("gin_body", fmt.Sprintf("[[%v bytes | %s]]", len(bin), req.Header.Get("Content-Type")))
} }
} }
} }
@@ -441,9 +441,9 @@ func (b *Builder) Output(ctx context.Context, g *gin.Context) {
b.errorData.Output(g) b.errorData.Output(g)
if b.errorData.Severity == SevErr || b.errorData.Severity == SevFatal { if (b.errorData.Severity == SevErr || b.errorData.Severity == SevFatal) && (pkgconfig.ZeroLogErrGinOutput || pkgconfig.ZeroLogAllGinOutput) {
b.errorData.Log(stackSkipLogger.Error()) b.errorData.Log(stackSkipLogger.Error())
} else if b.errorData.Severity == SevWarn { } else if (b.errorData.Severity == SevWarn) && (pkgconfig.ZeroLogAllGinOutput) {
b.errorData.Log(stackSkipLogger.Warn()) b.errorData.Log(stackSkipLogger.Warn())
} }

View File

@@ -181,7 +181,7 @@ func getReflectedMetaValues(value interface{}, remainingDepth int) map[string]Me
jsonval, err := json.Marshal(value) jsonval, err := json.Marshal(value)
if err != nil { if err != nil {
panic(err) // gets recovered later up return map[string]MetaValue{"": {DataType: MDTString, Value: fmt.Sprintf("Failed to Marshal %T:\n%+v", value, value)}}
} }
return map[string]MetaValue{"": {DataType: MDTString, Value: string(jsonval)}} return map[string]MetaValue{"": {DataType: MDTString, Value: string(jsonval)}}

View File

@@ -14,6 +14,8 @@ type ErrorPackageConfig struct {
ExtendGinOutput func(err *ExErr, json map[string]any) // (Optionally) extend the gin output with more fields ExtendGinOutput func(err *ExErr, json map[string]any) // (Optionally) extend the gin output with more fields
ExtendGinDataOutput func(err *ExErr, depth int, json map[string]any) // (Optionally) extend the gin `__data` output with more fields ExtendGinDataOutput func(err *ExErr, depth int, json map[string]any) // (Optionally) extend the gin `__data` output with more fields
DisableErrorWrapping bool // Disables the exerr.Wrap()...Build() function - will always return the original error DisableErrorWrapping bool // Disables the exerr.Wrap()...Build() function - will always return the original error
ZeroLogErrGinOutput bool // autom print zerolog logs on ginext.Error() / .Output(gin) (for SevErr and SevFatal)
ZeroLogAllGinOutput bool // autom print zerolog logs on ginext.Error() / .Output(gin) (for all Severities)
} }
type ErrorPackageConfigInit struct { type ErrorPackageConfigInit struct {
@@ -25,6 +27,8 @@ type ErrorPackageConfigInit struct {
ExtendGinOutput func(err *ExErr, json map[string]any) ExtendGinOutput func(err *ExErr, json map[string]any)
ExtendGinDataOutput func(err *ExErr, depth int, json map[string]any) ExtendGinDataOutput func(err *ExErr, depth int, json map[string]any)
DisableErrorWrapping *bool DisableErrorWrapping *bool
ZeroLogErrGinOutput *bool
ZeroLogAllGinOutput *bool
} }
var initialized = false var initialized = false
@@ -38,6 +42,8 @@ var pkgconfig = ErrorPackageConfig{
ExtendGinOutput: func(err *ExErr, json map[string]any) {}, ExtendGinOutput: func(err *ExErr, json map[string]any) {},
ExtendGinDataOutput: func(err *ExErr, depth int, json map[string]any) {}, ExtendGinDataOutput: func(err *ExErr, depth int, json map[string]any) {},
DisableErrorWrapping: false, DisableErrorWrapping: false,
ZeroLogErrGinOutput: true,
ZeroLogAllGinOutput: false,
} }
// Init initializes the exerr packages // Init initializes the exerr packages
@@ -67,6 +73,8 @@ func Init(cfg ErrorPackageConfigInit) {
ExtendGinOutput: ego, ExtendGinOutput: ego,
ExtendGinDataOutput: egdo, ExtendGinDataOutput: egdo,
DisableErrorWrapping: langext.Coalesce(cfg.DisableErrorWrapping, pkgconfig.DisableErrorWrapping), DisableErrorWrapping: langext.Coalesce(cfg.DisableErrorWrapping, pkgconfig.DisableErrorWrapping),
ZeroLogAllGinOutput: langext.Coalesce(cfg.ZeroLogAllGinOutput, pkgconfig.ZeroLogAllGinOutput),
ZeroLogErrGinOutput: langext.Coalesce(cfg.ZeroLogErrGinOutput, pkgconfig.ZeroLogErrGinOutput),
} }
initialized = true initialized = true

View File

@@ -15,10 +15,10 @@ func (ee *ExErr) toJson(depth int, applyExtendListener bool, outputMeta bool) la
ginJson["id"] = ee.UniqueID ginJson["id"] = ee.UniqueID
} }
if ee.Category != CatWrap { if ee.Category != CatWrap {
ginJson["category"] = ee.Category ginJson["category"] = ee.Category.Category
} }
if ee.Type != TypeWrap { if ee.Type != TypeWrap {
ginJson["type"] = ee.Type ginJson["type"] = ee.Type.Key
} }
if ee.StatusCode != nil { if ee.StatusCode != nil {
ginJson["statuscode"] = ee.StatusCode ginJson["statuscode"] = ee.StatusCode
@@ -30,7 +30,7 @@ func (ee *ExErr) toJson(depth int, applyExtendListener bool, outputMeta bool) la
ginJson["caller"] = ee.Caller ginJson["caller"] = ee.Caller
} }
if ee.Severity != SevErr { if ee.Severity != SevErr {
ginJson["severity"] = ee.Severity ginJson["severity"] = ee.Severity.Severity
} }
if ee.Timestamp != (time.Time{}) { if ee.Timestamp != (time.Time{}) {
ginJson["time"] = ee.Timestamp.Format(time.RFC3339) ginJson["time"] = ee.Timestamp.Format(time.RFC3339)

View File

@@ -19,6 +19,7 @@ type GinWrapper struct {
engine *gin.Engine engine *gin.Engine
suppressGinLogs bool suppressGinLogs bool
opt Options
allowCors bool allowCors bool
ginDebug bool ginDebug bool
bufferBody bool bufferBody bool
@@ -37,13 +38,15 @@ type ginRouteSpec struct {
} }
type Options struct { type Options struct {
AllowCors *bool // Add cors handler to allow all CORS requests on the default http methods AllowCors *bool // Add cors handler to allow all CORS requests on the default http methods
GinDebug *bool // Set gin.debug to true (adds more logs) GinDebug *bool // Set gin.debug to true (adds more logs)
SuppressGinLogs *bool // Suppress our custom gin logs (even if GinDebug == true) SuppressGinLogs *bool // Suppress our custom gin logs (even if GinDebug == true)
BufferBody *bool // Buffers the input body stream, this way the ginext error handler can later include the whole request body BufferBody *bool // Buffers the input body stream, this way the ginext error handler can later include the whole request body
Timeout *time.Duration // The default handler timeout Timeout *time.Duration // The default handler timeout
ListenerBeforeRequest []func(g *gin.Context) // Register listener that are called before the handler method ListenerBeforeRequest []func(g *gin.Context) // Register listener that are called before the handler method
ListenerAfterRequest []func(g *gin.Context, resp HTTPResponse) // Register listener that are called after the handler method ListenerAfterRequest []func(g *gin.Context, resp HTTPResponse) // Register listener that are called after the handler method
DebugTrimHandlerPrefixes []string // Trim these prefixes from the handler names in the debug print
DebugReplaceHandlerNames map[string]string // Replace handler names in debug output
} }
// NewEngine creates a new (wrapped) ginEngine // NewEngine creates a new (wrapped) ginEngine
@@ -52,6 +55,7 @@ func NewEngine(opt Options) *GinWrapper {
wrapper := &GinWrapper{ wrapper := &GinWrapper{
engine: engine, engine: engine,
opt: opt,
suppressGinLogs: langext.Coalesce(opt.SuppressGinLogs, false), suppressGinLogs: langext.Coalesce(opt.SuppressGinLogs, false),
allowCors: langext.Coalesce(opt.AllowCors, false), allowCors: langext.Coalesce(opt.AllowCors, false),
ginDebug: langext.Coalesce(opt.GinDebug, true), ginDebug: langext.Coalesce(opt.GinDebug, true),
@@ -185,6 +189,18 @@ func (w *GinWrapper) cleanMiddlewareName(fname string) string {
} }
} }
for _, pfx := range w.opt.DebugTrimHandlerPrefixes {
if strings.HasPrefix(fname, pfx) {
fname = fname[len(pfx):]
}
}
for k, v := range langext.ForceMap(w.opt.DebugReplaceHandlerNames) {
if strings.EqualFold(fname, k) {
fname = v
}
}
return fname return fname
} }

View File

@@ -1,6 +1,7 @@
package ginext package ginext
import ( import (
"context"
"fmt" "fmt"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"gogs.mikescher.com/BlackForestBytes/goext/exerr" "gogs.mikescher.com/BlackForestBytes/goext/exerr"
@@ -410,7 +411,8 @@ func (j jsonAPIErrResponse) Write(g *gin.Context) {
for _, v := range j.cookies { for _, v := range j.cookies {
g.SetCookie(v.name, v.value, v.maxAge, v.path, v.domain, v.secure, v.httpOnly) g.SetCookie(v.name, v.value, v.maxAge, v.path, v.domain, v.secure, v.httpOnly)
} }
j.err.Output(g)
exerr.Get(j.err).Output(context.Background(), g)
j.err.CallListener(exerr.MethodOutput) j.err.CallListener(exerr.MethodOutput)
} }

31
go.mod
View File

@@ -1,34 +1,37 @@
module gogs.mikescher.com/BlackForestBytes/goext module gogs.mikescher.com/BlackForestBytes/goext
go 1.21 go 1.22
require ( require (
github.com/gin-gonic/gin v1.9.1 github.com/gin-gonic/gin v1.9.1
github.com/glebarez/go-sqlite v1.22.0 // only needed for tests -.- github.com/glebarez/go-sqlite v1.22.0 // only needed for tests -.-
github.com/jmoiron/sqlx v1.3.5 github.com/jmoiron/sqlx v1.4.0
github.com/rs/xid v1.5.0 github.com/rs/xid v1.5.0
github.com/rs/zerolog v1.32.0 github.com/rs/zerolog v1.32.0
go.mongodb.org/mongo-driver v1.14.0 go.mongodb.org/mongo-driver v1.15.0
golang.org/x/crypto v0.21.0 golang.org/x/crypto v0.22.0
golang.org/x/sys v0.18.0 golang.org/x/sys v0.19.0
golang.org/x/term v0.18.0 golang.org/x/term v0.19.0
) )
require ( require (
github.com/bytedance/sonic v1.11.3 // indirect github.com/bytedance/sonic v1.11.6 // indirect
github.com/bytedance/sonic/loader v0.1.1 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
github.com/chenzhuoyu/iasm v0.9.1 // indirect github.com/chenzhuoyu/iasm v0.9.1 // indirect
github.com/cloudwego/base64x v0.1.4 // indirect
github.com/cloudwego/iasm v0.2.0 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect github.com/dustin/go-humanize v1.0.1 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.19.0 // indirect github.com/go-playground/validator/v10 v10.20.0 // indirect
github.com/goccy/go-json v0.10.2 // indirect github.com/goccy/go-json v0.10.2 // indirect
github.com/golang/snappy v0.0.4 // indirect github.com/golang/snappy v0.0.4 // indirect
github.com/google/uuid v1.5.0 // indirect github.com/google/uuid v1.5.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.17.7 // indirect github.com/klauspost/compress v1.17.8 // indirect
github.com/klauspost/cpuid/v2 v2.2.7 // indirect github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/leodido/go-urn v1.4.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-colorable v0.1.13 // indirect
@@ -36,19 +39,19 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/montanaflynn/stats v0.7.1 // indirect github.com/montanaflynn/stats v0.7.1 // indirect
github.com/pelletier/go-toml/v2 v2.2.0 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect github.com/ugorji/go/codec v1.2.12 // indirect
github.com/xdg-go/pbkdf2 v1.0.0 // indirect github.com/xdg-go/pbkdf2 v1.0.0 // indirect
github.com/xdg-go/scram v1.1.2 // indirect github.com/xdg-go/scram v1.1.2 // indirect
github.com/xdg-go/stringprep v1.0.4 // indirect github.com/xdg-go/stringprep v1.0.4 // indirect
github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect github.com/youmark/pkcs8 v0.0.0-20240424034433-3c2c7870ae76 // indirect
golang.org/x/arch v0.7.0 // indirect golang.org/x/arch v0.7.0 // indirect
golang.org/x/net v0.22.0 // indirect golang.org/x/net v0.24.0 // indirect
golang.org/x/sync v0.6.0 // indirect golang.org/x/sync v0.7.0 // indirect
golang.org/x/text v0.14.0 // indirect golang.org/x/text v0.14.0 // indirect
google.golang.org/protobuf v1.33.0 // indirect google.golang.org/protobuf v1.34.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
modernc.org/libc v1.37.6 // indirect modernc.org/libc v1.37.6 // indirect
modernc.org/mathutil v1.6.0 // indirect modernc.org/mathutil v1.6.0 // indirect

51
go.sum
View File

@@ -1,3 +1,4 @@
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM= github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM=
github.com/bytedance/sonic v1.10.2 h1:GQebETVBxYB7JGWJtLBi07OVzWwt+8dWA00gEVW2ZFE= github.com/bytedance/sonic v1.10.2 h1:GQebETVBxYB7JGWJtLBi07OVzWwt+8dWA00gEVW2ZFE=
@@ -10,6 +11,15 @@ github.com/bytedance/sonic v1.11.2 h1:ywfwo0a/3j9HR8wsYGWsIWl2mvRsI950HyoxiBERw5
github.com/bytedance/sonic v1.11.2/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4= github.com/bytedance/sonic v1.11.2/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4=
github.com/bytedance/sonic v1.11.3 h1:jRN+yEjakWh8aK5FzrciUHG8OFXK+4/KrAX/ysEtHAA= github.com/bytedance/sonic v1.11.3 h1:jRN+yEjakWh8aK5FzrciUHG8OFXK+4/KrAX/ysEtHAA=
github.com/bytedance/sonic v1.11.3/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4= github.com/bytedance/sonic v1.11.3/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4=
github.com/bytedance/sonic v1.11.4 h1:8+OMLSSDDm2/qJc6ld5K5Sm62NK9VHcUKk0NzBoMAM4=
github.com/bytedance/sonic v1.11.4/go.mod h1:YrWEqYtlBPS6LUA0vpuG79a1trsh4Ae41uWUWUreHhE=
github.com/bytedance/sonic v1.11.5 h1:G00FYjjqll5iQ1PYXynbg/hyzqBqavH8Mo9/oTopd9k=
github.com/bytedance/sonic v1.11.5/go.mod h1:X2PC2giUdj/Cv2lliWFLk6c/DUQok5rViJSemeB0wDw=
github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
github.com/bytedance/sonic/loader v0.1.0/go.mod h1:UmRT+IRTGKz/DAkzcEGzyVqQFJ7H9BqwBO3pm9H/+HY=
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0= github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0=
@@ -17,6 +27,17 @@ github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpV
github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog= github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog=
github.com/chenzhuoyu/iasm v0.9.1 h1:tUHQJXo3NhBqw6s33wkGn9SP3bvrWLdlVIJ3hQBL7P0= github.com/chenzhuoyu/iasm v0.9.1 h1:tUHQJXo3NhBqw6s33wkGn9SP3bvrWLdlVIJ3hQBL7P0=
github.com/chenzhuoyu/iasm v0.9.1/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog= github.com/chenzhuoyu/iasm v0.9.1/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog=
github.com/cloudwego/base64x v0.1.0 h1:Tg5q9tq1khq9Y9UwfoC6zkHK0FypN2GLDvhqFceOL8U=
github.com/cloudwego/base64x v0.1.0/go.mod h1:lM8nFiNbg74QgesNo6EAtv8N9tlRjBWExmHoNDa3PkU=
github.com/cloudwego/base64x v0.1.3 h1:b5J/l8xolB7dyDTTmhJP2oTs5LdrjyrUFuNxdfq5hAg=
github.com/cloudwego/base64x v0.1.3/go.mod h1:1+1K5BUHIQzyapgpF7LwvOGAEDicKtt1umPV+aN8pi8=
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
github.com/cloudwego/iasm v0.0.9/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
github.com/cloudwego/iasm v0.1.0 h1:q0OuhwWDMyi3nlrQ6kIr0Yx0c3FI6cq/OZWKodIDdz8=
github.com/cloudwego/iasm v0.1.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@@ -45,8 +66,12 @@ github.com/go-playground/validator/v10 v10.18.0 h1:BvolUXjp4zuvkZ5YN5t7ebzbhlUtP
github.com/go-playground/validator/v10 v10.18.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/go-playground/validator/v10 v10.18.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/go-playground/validator/v10 v10.19.0 h1:ol+5Fu+cSq9JD7SoSqe04GMI92cbn0+wvQ3bZ8b/AU4= github.com/go-playground/validator/v10 v10.19.0 h1:ol+5Fu+cSq9JD7SoSqe04GMI92cbn0+wvQ3bZ8b/AU4=
github.com/go-playground/validator/v10 v10.19.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/go-playground/validator/v10 v10.19.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8=
github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
@@ -64,6 +89,8 @@ github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g= github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g=
github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ=
github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o=
github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
@@ -73,6 +100,8 @@ github.com/klauspost/compress v1.17.6 h1:60eq2E/jlfwQXtvZEeBUYADs+BwKBWURIY+Gj2e
github.com/klauspost/compress v1.17.6/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/klauspost/compress v1.17.6/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg=
github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU=
github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc= github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc=
github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
@@ -85,6 +114,7 @@ github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0= github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
@@ -94,6 +124,7 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v1.14.19 h1:fhGleo2h1p8tVChob4I9HpmVFIAkKGpiukdrgQbWfGI= github.com/mattn/go-sqlite3 v1.14.19 h1:fhGleo2h1p8tVChob4I9HpmVFIAkKGpiukdrgQbWfGI=
github.com/mattn/go-sqlite3 v1.14.19/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/mattn/go-sqlite3 v1.14.19/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -106,6 +137,10 @@ github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOS
github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
github.com/pelletier/go-toml/v2 v2.2.0 h1:QLgLl2yMN7N+ruc31VynXs1vhMZa7CeHHejIeBAsoHo= github.com/pelletier/go-toml/v2 v2.2.0 h1:QLgLl2yMN7N+ruc31VynXs1vhMZa7CeHHejIeBAsoHo=
github.com/pelletier/go-toml/v2 v2.2.0/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/pelletier/go-toml/v2 v2.2.0/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
github.com/pelletier/go-toml/v2 v2.2.1 h1:9TA9+T8+8CUCO2+WYnDLCgrYi9+omqKXyjDtosvtEhg=
github.com/pelletier/go-toml/v2 v2.2.1/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@@ -144,11 +179,15 @@ github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gi
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a h1:fZHgsYlfvtyqToslyjUt3VOPF4J7aK/3MPcK7xp3PDk= github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a h1:fZHgsYlfvtyqToslyjUt3VOPF4J7aK/3MPcK7xp3PDk=
github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a/go.mod h1:ul22v+Nro/R083muKhosV54bj5niojjWZvU8xrevuH4= github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a/go.mod h1:ul22v+Nro/R083muKhosV54bj5niojjWZvU8xrevuH4=
github.com/youmark/pkcs8 v0.0.0-20240424034433-3c2c7870ae76 h1:tBiBTKHnIjovYoLX/TPkcf+OjqqKGQrPtGT3Foz+Pgo=
github.com/youmark/pkcs8 v0.0.0-20240424034433-3c2c7870ae76/go.mod h1:SQliXeA7Dhkt//vS29v3zpbEwoa+zb2Cn5xj5uO4K5U=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.mongodb.org/mongo-driver v1.13.1 h1:YIc7HTYsKndGK4RFzJ3covLz1byri52x0IoMB0Pt/vk= go.mongodb.org/mongo-driver v1.13.1 h1:YIc7HTYsKndGK4RFzJ3covLz1byri52x0IoMB0Pt/vk=
go.mongodb.org/mongo-driver v1.13.1/go.mod h1:wcDf1JBCXy2mOW0bWHwO/IOYqdca1MPCwDtFu/Z9+eo= go.mongodb.org/mongo-driver v1.13.1/go.mod h1:wcDf1JBCXy2mOW0bWHwO/IOYqdca1MPCwDtFu/Z9+eo=
go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80= go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80=
go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c=
go.mongodb.org/mongo-driver v1.15.0 h1:rJCKC8eEliewXjZGf0ddURtl7tTVy1TK3bfl0gkUSLc=
go.mongodb.org/mongo-driver v1.15.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc= golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc=
golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
@@ -166,6 +205,8 @@ golang.org/x/crypto v0.20.0 h1:jmAMJJZXr5KiCw05dfYK9QnqaqKLYXijU23lsEdcQqg=
golang.org/x/crypto v0.20.0/go.mod h1:Xwo95rrVNIoSMx9wa1JroENMToLWn3RNVrTBpLHgZPQ= golang.org/x/crypto v0.20.0/go.mod h1:Xwo95rrVNIoSMx9wa1JroENMToLWn3RNVrTBpLHgZPQ=
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
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=
@@ -180,10 +221,14 @@ golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
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.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -201,6 +246,8 @@ golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
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.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE=
@@ -209,6 +256,8 @@ golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q=
golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
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.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@@ -228,6 +277,8 @@ google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4=
google.golang.org/protobuf v1.34.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@@ -1,5 +1,5 @@
package goext package goext
const GoextVersion = "0.0.417" const GoextVersion = "0.0.444"
const GoextVersionTimestamp = "2024-03-20T08:58:59+0100" const GoextVersionTimestamp = "2024-05-03T13:24:08+0200"

View File

@@ -453,6 +453,15 @@ func ArrConcat[T any](arr ...[]T) []T {
return r return r
} }
// ArrAppend works similar to append(x, y, z) - but doe snot touch the old array and creates a new one
func ArrAppend[T any](arr []T, add ...T) []T {
r := ArrCopy(arr)
for _, v := range add {
r = append(r, v)
}
return r
}
// ArrCopy does a shallow copy of the 'in' array // ArrCopy does a shallow copy of the 'in' array
func ArrCopy[T any](in []T) []T { func ArrCopy[T any](in []T) []T {
out := make([]T, len(in)) out := make([]T, len(in))
@@ -468,6 +477,10 @@ func ArrRemove[T comparable](arr []T, needle T) []T {
return arr return arr
} }
func ArrRemoveAt[T any](arr []T, idx int) []T {
return append(arr[:idx], arr[idx+1:]...)
}
func ArrExcept[T comparable](arr []T, needles ...T) []T { func ArrExcept[T comparable](arr []T, needles ...T) []T {
r := make([]T, 0, len(arr)) r := make([]T, 0, len(arr))
rmlist := ArrToSet(needles) rmlist := ArrToSet(needles)

View File

@@ -63,3 +63,51 @@ func PatchRemJson[JV string | []byte](rawjson JV, key string) (JV, error) {
return JV(newjson), nil return JV(newjson), nil
} }
func MarshalJsonOrPanic(v any) string {
bin, err := json.Marshal(v)
if err != nil {
panic(err)
}
return string(bin)
}
func MarshalJsonOrDefault(v any, def string) string {
bin, err := json.Marshal(v)
if err != nil {
return def
}
return string(bin)
}
func MarshalJsonOrNil(v any) *string {
bin, err := json.Marshal(v)
if err != nil {
return nil
}
return Ptr(string(bin))
}
func MarshalJsonIndentOrPanic(v any, prefix, indent string) string {
bin, err := json.MarshalIndent(v, prefix, indent)
if err != nil {
panic(err)
}
return string(bin)
}
func MarshalJsonIndentOrDefault(v any, prefix, indent string, def string) string {
bin, err := json.MarshalIndent(v, prefix, indent)
if err != nil {
return def
}
return string(bin)
}
func MarshalJsonIndentOrNil(v any, prefix, indent string) *string {
bin, err := json.MarshalIndent(v, prefix, indent)
if err != nil {
return nil
}
return Ptr(string(bin))
}

19
langext/object.go Normal file
View File

@@ -0,0 +1,19 @@
package langext
import "encoding/json"
func DeepCopyByJson[T any](v T) (T, error) {
bin, err := json.Marshal(v)
if err != nil {
return *new(T), err
}
var result T
err = json.Unmarshal(bin, &result)
if err != nil {
return *new(T), err
}
return result, nil
}

View File

@@ -27,6 +27,10 @@ func DblPtrNil[T any]() **T {
return &v return &v
} }
func ArrPtr[T any](v ...T) *[]T {
return &v
}
func PtrInt32(v int32) *int32 { func PtrInt32(v int32) *int32 {
return &v return &v
} }

View File

@@ -2,29 +2,44 @@ package reflectext
import ( import (
"encoding/json" "encoding/json"
"gogs.mikescher.com/BlackForestBytes/goext/langext"
"reflect" "reflect"
) )
type ConvertStructToMapOpt struct { type ConvertStructToMapOpt struct {
KeepJsonMarshalTypes bool KeepJsonMarshalTypes bool
MaxDepth *int
} }
func ConvertStructToMap(v any, opts ...ConvertStructToMapOpt) any { func ConvertStructToMap(v any, opts ...ConvertStructToMapOpt) map[string]any {
opt := ConvertStructToMapOpt{} opt := ConvertStructToMapOpt{}
if len(opts) > 0 { if len(opts) > 0 {
opt = opts[0] opt = opts[0]
} }
return reflectToMap(reflect.ValueOf(v), opt)
res := reflectToMap(reflect.ValueOf(v), 1, opt)
if v, ok := res.(map[string]any); ok {
return v
} else if langext.IsNil(res) {
return nil
} else {
panic("not an object")
}
} }
func reflectToMap(fv reflect.Value, opt ConvertStructToMapOpt) any { func reflectToMap(fv reflect.Value, depth int, opt ConvertStructToMapOpt) any {
if opt.MaxDepth != nil && depth > *opt.MaxDepth {
return fv.Interface()
}
if fv.Kind() == reflect.Ptr { if fv.Kind() == reflect.Ptr {
if fv.IsNil() { if fv.IsNil() {
return nil return nil
} else { } else {
return reflectToMap(fv.Elem(), opt) return reflectToMap(fv.Elem(), depth, opt)
} }
} }
@@ -41,7 +56,7 @@ func reflectToMap(fv reflect.Value, opt ConvertStructToMapOpt) any {
arrlen := fv.Len() arrlen := fv.Len()
arr := make([]any, arrlen) arr := make([]any, arrlen)
for i := 0; i < arrlen; i++ { for i := 0; i < arrlen; i++ {
arr[i] = reflectToMap(fv.Index(i), opt) arr[i] = reflectToMap(fv.Index(i), depth+1, opt)
} }
return arr return arr
@@ -52,7 +67,7 @@ func reflectToMap(fv reflect.Value, opt ConvertStructToMapOpt) any {
arrlen := fv.Len() arrlen := fv.Len()
arr := make([]any, arrlen) arr := make([]any, arrlen)
for i := 0; i < arrlen; i++ { for i := 0; i < arrlen; i++ {
arr[i] = reflectToMap(fv.Index(i), opt) arr[i] = reflectToMap(fv.Index(i), depth+1, opt)
} }
return arr return arr
@@ -75,7 +90,7 @@ func reflectToMap(fv reflect.Value, opt ConvertStructToMapOpt) any {
for i := 0; i < fv.NumField(); i++ { for i := 0; i < fv.NumField(); i++ {
if fv.Type().Field(i).IsExported() { if fv.Type().Field(i).IsExported() {
res[fv.Type().Field(i).Name] = reflectToMap(fv.Field(i), opt) res[fv.Type().Field(i).Name] = reflectToMap(fv.Field(i), depth+1, opt)
} }
} }

View File

@@ -0,0 +1,42 @@
package reflectext
import (
"fmt"
"gogs.mikescher.com/BlackForestBytes/goext/langext"
"testing"
"time"
)
func TestConvertStructToMap(t *testing.T) {
type tst struct {
FieldA int
FieldB string
FieldC time.Time
FieldD []float64
FieldE1 *int
FieldE2 **int
FieldE3 *int
FieldE4 **int
FieldE5 *int
FieldE6 **int
}
value := tst{
FieldA: 123,
FieldB: "hello",
FieldC: time.Date(2020, 05, 12, 8, 30, 0, 0, time.UTC),
FieldD: []float64{1, 2, 3, 4, 5, 6, 7},
FieldE1: nil,
FieldE2: nil,
FieldE3: langext.Ptr(12),
FieldE4: langext.DblPtr(12),
FieldE5: nil,
FieldE6: langext.DblPtrNil[int](),
}
valueOut := ConvertStructToMap(value, ConvertStructToMapOpt{KeepJsonMarshalTypes: true})
fmt.Printf("%+v\n", valueOut)
}

View File

@@ -47,9 +47,3 @@ func TestGetMapField(t *testing.T) {
tst.AssertEqual(t, fmt.Sprint(GetMapField[PseudoInt](maany2, "Test")), "12 true") tst.AssertEqual(t, fmt.Sprint(GetMapField[PseudoInt](maany2, "Test")), "12 true")
tst.AssertEqual(t, fmt.Sprint(GetMapField[PseudoInt](maany2, "Test2")), "0 false") tst.AssertEqual(t, fmt.Sprint(GetMapField[PseudoInt](maany2, "Test2")), "0 false")
} }
func main2() {
}
func main() {
}

View File

@@ -8,6 +8,7 @@ import (
"go.mongodb.org/mongo-driver/bson/bsoncodec" "go.mongodb.org/mongo-driver/bson/bsoncodec"
"go.mongodb.org/mongo-driver/bson/bsonrw" "go.mongodb.org/mongo-driver/bson/bsonrw"
"go.mongodb.org/mongo-driver/bson/bsontype" "go.mongodb.org/mongo-driver/bson/bsontype"
"gogs.mikescher.com/BlackForestBytes/goext/langext"
"reflect" "reflect"
"time" "time"
) )
@@ -245,6 +246,13 @@ func NewRFC3339(t time.Time) RFC3339Time {
return RFC3339Time(t) return RFC3339Time(t)
} }
func NewRFC3339Ptr(t *time.Time) *RFC3339Time {
if t == nil {
return nil
}
return langext.Ptr(RFC3339Time(*t))
}
func NowRFC3339() RFC3339Time { func NowRFC3339() RFC3339Time {
return RFC3339Time(time.Now()) return RFC3339Time(time.Now())
} }

View File

@@ -8,6 +8,7 @@ import (
"go.mongodb.org/mongo-driver/bson/bsoncodec" "go.mongodb.org/mongo-driver/bson/bsoncodec"
"go.mongodb.org/mongo-driver/bson/bsonrw" "go.mongodb.org/mongo-driver/bson/bsonrw"
"go.mongodb.org/mongo-driver/bson/bsontype" "go.mongodb.org/mongo-driver/bson/bsontype"
"gogs.mikescher.com/BlackForestBytes/goext/langext"
"reflect" "reflect"
"time" "time"
) )
@@ -245,6 +246,13 @@ func NewRFC3339Nano(t time.Time) RFC3339NanoTime {
return RFC3339NanoTime(t) return RFC3339NanoTime(t)
} }
func NewRFC3339NanoPtr(t *time.Time) *RFC3339NanoTime {
if t == nil {
return nil
}
return langext.Ptr(RFC3339NanoTime(*t))
}
func NowRFC3339Nano() RFC3339NanoTime { func NowRFC3339Nano() RFC3339NanoTime {
return RFC3339NanoTime(time.Now()) return RFC3339NanoTime(time.Now())
} }

View File

@@ -8,6 +8,7 @@ import (
"go.mongodb.org/mongo-driver/bson/bsoncodec" "go.mongodb.org/mongo-driver/bson/bsoncodec"
"go.mongodb.org/mongo-driver/bson/bsonrw" "go.mongodb.org/mongo-driver/bson/bsonrw"
"go.mongodb.org/mongo-driver/bson/bsontype" "go.mongodb.org/mongo-driver/bson/bsontype"
"gogs.mikescher.com/BlackForestBytes/goext/langext"
"reflect" "reflect"
"strconv" "strconv"
"time" "time"
@@ -239,6 +240,13 @@ func NewUnix(t time.Time) UnixTime {
return UnixTime(t) return UnixTime(t)
} }
func NewUnixPtr(t *time.Time) *UnixTime {
if t == nil {
return nil
}
return langext.Ptr(UnixTime(*t))
}
func NowUnix() UnixTime { func NowUnix() UnixTime {
return UnixTime(time.Now()) return UnixTime(time.Now())
} }

View File

@@ -8,6 +8,7 @@ import (
"go.mongodb.org/mongo-driver/bson/bsoncodec" "go.mongodb.org/mongo-driver/bson/bsoncodec"
"go.mongodb.org/mongo-driver/bson/bsonrw" "go.mongodb.org/mongo-driver/bson/bsonrw"
"go.mongodb.org/mongo-driver/bson/bsontype" "go.mongodb.org/mongo-driver/bson/bsontype"
"gogs.mikescher.com/BlackForestBytes/goext/langext"
"reflect" "reflect"
"strconv" "strconv"
"time" "time"
@@ -239,6 +240,13 @@ func NewUnixMilli(t time.Time) UnixMilliTime {
return UnixMilliTime(t) return UnixMilliTime(t)
} }
func NewUnixMilliPtr(t *time.Time) *UnixMilliTime {
if t == nil {
return nil
}
return langext.Ptr(UnixMilliTime(*t))
}
func NowUnixMilli() UnixMilliTime { func NowUnixMilli() UnixMilliTime {
return UnixMilliTime(time.Now()) return UnixMilliTime(time.Now())
} }

View File

@@ -8,6 +8,7 @@ import (
"go.mongodb.org/mongo-driver/bson/bsoncodec" "go.mongodb.org/mongo-driver/bson/bsoncodec"
"go.mongodb.org/mongo-driver/bson/bsonrw" "go.mongodb.org/mongo-driver/bson/bsonrw"
"go.mongodb.org/mongo-driver/bson/bsontype" "go.mongodb.org/mongo-driver/bson/bsontype"
"gogs.mikescher.com/BlackForestBytes/goext/langext"
"reflect" "reflect"
"strconv" "strconv"
"time" "time"
@@ -239,6 +240,13 @@ func NewUnixNano(t time.Time) UnixNanoTime {
return UnixNanoTime(t) return UnixNanoTime(t)
} }
func NewUnixNanoPtr(t *time.Time) *UnixNanoTime {
if t == nil {
return nil
}
return langext.Ptr(UnixNanoTime(*t))
}
func NowUnixNano() UnixNanoTime { func NowUnixNano() UnixNanoTime {
return UnixNanoTime(time.Now()) return UnixNanoTime(time.Now())
} }

View File

@@ -146,3 +146,37 @@ func UnixFloatSeconds(v float64) time.Time {
func FloorTime(t time.Time) time.Time { func FloorTime(t time.Time) time.Time {
return time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location()) return time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location())
} }
func SubtractYears(t time.Time, yearCount float64, tz *time.Location) time.Time {
t = t.In(tz)
if yearCount < 0 {
return AddYears(t, -yearCount, tz)
}
intCount, floatCount := math.Modf(yearCount)
t.AddDate(-int(intCount), 0, 0)
t0 := TimeToYearStart(t, tz)
t1 := TimeToYearEnd(t, tz)
return t.Add(time.Duration(float64(t1.Sub(t0)) * floatCount * -1))
}
func AddYears(t time.Time, yearCount float64, tz *time.Location) time.Time {
t = t.In(tz)
if yearCount < 0 {
return SubtractYears(t, -yearCount, tz)
}
intCount, floatCount := math.Modf(yearCount)
t.AddDate(int(intCount), 0, 0)
t0 := TimeToYearStart(t, tz)
t1 := TimeToYearEnd(t, tz)
return t.Add(time.Duration(float64(t1.Sub(t0)) * floatCount))
}

View File

@@ -125,3 +125,17 @@ func (c *Coll[TData]) createToken(fieldPrimary string, dirPrimary ct.SortDirecti
Extra: ct.Extra{}, Extra: ct.Extra{},
}, nil }, nil
} }
func (c *Coll[TData]) needsDoubleSort(ctx context.Context) bool {
for _, ppl := range c.extraModPipeline {
for _, stage := range ppl(ctx) {
for _, bsone := range stage {
if bsone.Key == "$group" {
// a group stage in extraModPipeline results in unsorted data, which means the caller must sort again after these pipeline stages...
return true
}
}
}
}
return false
}

View File

@@ -36,6 +36,14 @@ func (c *Coll[TData]) Find(ctx context.Context, filter bson.M, opts ...*options.
pipeline = langext.ArrConcat(pipeline, ppl(ctx)) pipeline = langext.ArrConcat(pipeline, ppl(ctx))
} }
if c.needsDoubleSort(ctx) {
for _, opt := range opts {
if opt != nil && opt.Sort != nil {
pipeline = append(pipeline, bson.D{{Key: "$sort", Value: opt.Sort}})
}
}
}
for _, opt := range opts { for _, opt := range opts {
if opt != nil && opt.Projection != nil { if opt != nil && opt.Projection != nil {
pipeline = append(pipeline, bson.D{{Key: "$project", Value: opt.Projection}}) pipeline = append(pipeline, bson.D{{Key: "$project", Value: opt.Projection}})

View File

@@ -14,6 +14,10 @@ func (c *Coll[TData]) List(ctx context.Context, filter ct.Filter, pageSize *int,
return make([]TData, 0), ct.End(), nil return make([]TData, 0), ct.End(), nil
} }
if pageSize != nil && *pageSize == 0 {
return make([]TData, 0), inTok, nil // fast track, we return an empty list and do not advance the cursor token
}
pipeline := mongo.Pipeline{} pipeline := mongo.Pipeline{}
pf1 := "_id" pf1 := "_id"
pd1 := ct.SortASC pd1 := ct.SortASC
@@ -35,7 +39,7 @@ func (c *Coll[TData]) List(ctx context.Context, filter ct.Filter, pageSize *int,
sortDirSecondary = nil sortDirSecondary = nil
} }
paginationPipeline, err := createPaginationPipeline(c, inTok, sortPrimary, sortDirPrimary, sortSecondary, sortDirSecondary, pageSize) paginationPipeline, doubleSortPipeline, err := createPaginationPipeline(c, inTok, sortPrimary, sortDirPrimary, sortSecondary, sortDirSecondary, pageSize)
if err != nil { if err != nil {
return nil, ct.CursorToken{}, exerr. return nil, ct.CursorToken{}, exerr.
Wrap(err, "failed to create pagination"). Wrap(err, "failed to create pagination").
@@ -56,6 +60,10 @@ func (c *Coll[TData]) List(ctx context.Context, filter ct.Filter, pageSize *int,
pipeline = langext.ArrConcat(pipeline, ppl(ctx)) pipeline = langext.ArrConcat(pipeline, ppl(ctx))
} }
if c.needsDoubleSort(ctx) {
pipeline = langext.ArrConcat(pipeline, doubleSortPipeline)
}
cursor, err := c.coll.Aggregate(ctx, pipeline) cursor, err := c.coll.Aggregate(ctx, pipeline)
if err != nil { if err != nil {
return nil, ct.CursorToken{}, exerr.Wrap(err, "mongo-aggregation failed").Any("pipeline", pipeline).Str("collection", c.Name()).Build() return nil, ct.CursorToken{}, exerr.Wrap(err, "mongo-aggregation failed").Any("pipeline", pipeline).Str("collection", c.Name()).Build()
@@ -136,14 +144,50 @@ func (c *Coll[TData]) ListWithCount(ctx context.Context, filter ct.Filter, pageS
return data, token, count, nil return data, token, count, nil
} }
func createPaginationPipeline[TData any](coll *Coll[TData], token ct.CursorToken, fieldPrimary string, sortPrimary ct.SortDirection, fieldSecondary *string, sortSecondary *ct.SortDirection, pageSize *int) ([]bson.D, error) { func (c *Coll[TData]) ListAllIDs(ctx context.Context, filter ct.RawFilter) ([]string, error) {
type idObject struct {
ID string `bson:"_id"`
}
pipelineFilter := mongo.Pipeline{}
if filter != nil {
pipelineFilter = filter.FilterQuery()
}
extrModPipelineResolved := mongo.Pipeline{}
for _, ppl := range c.extraModPipeline {
extrModPipelineResolved = langext.ArrConcat(extrModPipelineResolved, ppl(ctx))
}
pipelineProjectIDs := mongo.Pipeline{}
pipelineProjectIDs = append(pipelineProjectIDs, bson.D{{Key: "$project", Value: bson.M{"_id": 1}}})
pipelineList := langext.ArrConcat(pipelineFilter, extrModPipelineResolved, pipelineProjectIDs)
cursorList, err := c.coll.Aggregate(ctx, pipelineList)
if err != nil {
return nil, exerr.Wrap(err, "mongo-aggregation failed").Any("pipeline", pipelineList).Str("collection", c.Name()).Build()
}
var res []idObject
err = cursorList.All(ctx, &res)
if err != nil {
return nil, exerr.Wrap(err, "failed to decode entities").Any("pipeline", pipelineList).Str("collection", c.Name()).Build()
}
return langext.ArrMap(res, func(v idObject) string { return v.ID }), nil
}
func createPaginationPipeline[TData any](coll *Coll[TData], token ct.CursorToken, fieldPrimary string, sortPrimary ct.SortDirection, fieldSecondary *string, sortSecondary *ct.SortDirection, pageSize *int) ([]bson.D, []bson.D, error) {
cond := bson.A{} cond := bson.A{}
sort := bson.D{} sort := bson.D{}
valuePrimary, err := coll.getTokenValueAsMongoType(token.ValuePrimary, fieldPrimary) valuePrimary, err := coll.getTokenValueAsMongoType(token.ValuePrimary, fieldPrimary)
if err != nil { if err != nil {
return 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 sortPrimary == ct.SortASC {
@@ -160,7 +204,7 @@ func createPaginationPipeline[TData any](coll *Coll[TData], token ct.CursorToken
valueSecondary, err := coll.getTokenValueAsMongoType(token.ValueSecondary, *fieldSecondary) valueSecondary, err := coll.getTokenValueAsMongoType(token.ValueSecondary, *fieldSecondary)
if err != nil { if err != nil {
return 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 *sortSecondary == ct.SortASC {
@@ -171,7 +215,7 @@ func createPaginationPipeline[TData any](coll *Coll[TData], token ct.CursorToken
bson.M{*fieldSecondary: bson.M{"$gt": valueSecondary}}, bson.M{*fieldSecondary: bson.M{"$gt": valueSecondary}},
}}) }})
sort = append(sort, bson.E{Key: fieldPrimary, Value: +1}) sort = append(sort, bson.E{Key: *fieldSecondary, Value: +1})
} else if *sortSecondary == ct.SortDESC { } else if *sortSecondary == ct.SortDESC {
@@ -181,7 +225,7 @@ func createPaginationPipeline[TData any](coll *Coll[TData], token ct.CursorToken
bson.M{*fieldSecondary: bson.M{"$lt": valueSecondary}}, bson.M{*fieldSecondary: bson.M{"$lt": valueSecondary}},
}}) }})
sort = append(sort, bson.E{Key: fieldPrimary, Value: -1}) sort = append(sort, bson.E{Key: *fieldSecondary, Value: -1})
} }
} }
@@ -203,15 +247,17 @@ func createPaginationPipeline[TData any](coll *Coll[TData], token ct.CursorToken
} else { } else {
return nil, exerr.New(exerr.TypeInternal, "unknown ct mode: "+string(token.Mode)).Any("token.Mode", token.Mode).Build() return nil, nil, exerr.New(exerr.TypeInternal, "unknown ct mode: "+string(token.Mode)).Any("token.Mode", token.Mode).Build()
} }
pipeline = append(pipeline, bson.D{{Key: "$sort", Value: sort}}) pipeline = append(pipeline, bson.D{{Key: "$sort", Value: sort}})
pipelineSort := mongo.Pipeline{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)}})
} }
return pipeline, nil return pipeline, pipelineSort, nil
} }