Compare commits

...

3 Commits

Author SHA1 Message Date
506d276962 v0.0.581
All checks were successful
Build Docker and Deploy / Run goext test-suite (push) Successful in 3m39s
2025-06-25 10:28:54 +02:00
2a0cf84416 v0.0.580 Add IsZero() to generated ID types
All checks were successful
Build Docker and Deploy / Run goext test-suite (push) Successful in 2m33s
2025-06-16 08:40:07 +02:00
073aa84dd4 v0.0.579 fix StackSkip count on exerr zero-logger for Build()
All checks were successful
Build Docker and Deploy / Run goext test-suite (push) Successful in 2m29s
2025-06-13 16:53:47 +02:00
9 changed files with 89 additions and 41 deletions

View File

@@ -183,6 +183,10 @@ func (id {{.Name}}) CheckString() string {
return getCheckString(prefix{{.Name}}, string(id)) return getCheckString(prefix{{.Name}}, string(id))
} }
func (id {{.Name}}) IsZero() bool {
return id == ""
}
func (id {{.Name}}) Regex() rext.Regex { func (id {{.Name}}) Regex() rext.Regex {
return regex{{.Name}} return regex{{.Name}}
} }

View File

@@ -45,6 +45,10 @@ func (i {{.Name}}) AsAnyPtr() *{{$.AnyDef.Name}} {
} }
{{end}} {{end}}
func (i {{.Name}}) IsZero() bool {
return i == ""
}
func New{{.Name}}() {{.Name}} { func New{{.Name}}() {{.Name}} {
return {{.Name}}(primitive.NewObjectID().Hex()) return {{.Name}}(primitive.NewObjectID().Hex())
} }

View File

@@ -5,12 +5,12 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/gin-gonic/gin"
"github.com/rs/zerolog"
"go.mongodb.org/mongo-driver/bson/primitive"
"git.blackforestbytes.com/BlackForestBytes/goext/dataext" "git.blackforestbytes.com/BlackForestBytes/goext/dataext"
"git.blackforestbytes.com/BlackForestBytes/goext/enums" "git.blackforestbytes.com/BlackForestBytes/goext/enums"
"git.blackforestbytes.com/BlackForestBytes/goext/langext" "git.blackforestbytes.com/BlackForestBytes/goext/langext"
"github.com/gin-gonic/gin"
"github.com/rs/zerolog"
"go.mongodb.org/mongo-driver/bson/primitive"
"net/http" "net/http"
"os" "os"
"runtime/debug" "runtime/debug"
@@ -445,6 +445,8 @@ func (b *Builder) BuildAsExerr(ctxs ...context.Context) *ExErr {
// The error also gets printed to stdout/stderr // The error also gets printed to stdout/stderr
// If the error is SevErr|SevFatal we also send it to the error-service // If the error is SevErr|SevFatal we also send it to the error-service
func (b *Builder) Output(ctx context.Context, g *gin.Context) { func (b *Builder) Output(ctx context.Context, g *gin.Context) {
warnOnPkgConfigNotInitialized()
if !b.containsGinData && g.Request != nil { if !b.containsGinData && g.Request != nil {
// Auto-Add gin metadata if the caller hasn't already done it // Auto-Add gin metadata if the caller hasn't already done it
b.GinReq(ctx, g, g.Request) b.GinReq(ctx, g, g.Request)
@@ -452,6 +454,12 @@ func (b *Builder) Output(ctx context.Context, g *gin.Context) {
b.CtxData(MethodOutput, ctx) b.CtxData(MethodOutput, ctx)
// this is only here to add one level to the trace
// so that .Build() and .Output() and .Print() have the same depth and our stack-skip logger can have the same skip-count
b.doOutput(ctx, g)
}
func (b *Builder) doOutput(ctx context.Context, g *gin.Context) {
b.errorData.Output(g) b.errorData.Output(g)
if (b.errorData.Severity == SevErr || b.errorData.Severity == SevFatal) && (pkgconfig.ZeroLogErrGinOutput || pkgconfig.ZeroLogAllGinOutput) { if (b.errorData.Severity == SevErr || b.errorData.Severity == SevFatal) && (pkgconfig.ZeroLogErrGinOutput || pkgconfig.ZeroLogAllGinOutput) {
@@ -472,6 +480,12 @@ func (b *Builder) Print(ctxs ...context.Context) Proxy {
b.CtxData(MethodPrint, dctx) b.CtxData(MethodPrint, dctx)
} }
// this is only here to add one level to the trace
// so that .Build() and .Output() and .Print() have the same depth and our stack-skip logger can have the same skip-count
return b.doPrint()
}
func (b *Builder) doPrint() Proxy {
if b.errorData.Severity == SevErr || b.errorData.Severity == SevFatal { if b.errorData.Severity == SevErr || b.errorData.Severity == SevFatal {
b.errorData.Log(pkgconfig.ZeroLogger.Error()) b.errorData.Log(pkgconfig.ZeroLogger.Error())
} else if b.errorData.Severity == SevWarn { } else if b.errorData.Severity == SevWarn {
@@ -501,13 +515,19 @@ func (b *Builder) Fatal(ctxs ...context.Context) {
b.CtxData(MethodFatal, dctx) b.CtxData(MethodFatal, dctx)
} }
b.errorData.Log(pkgconfig.ZeroLogger.WithLevel(zerolog.FatalLevel)) // this is only here to add one level to the trace
// so that .Build() and .Output() and .Print() have the same depth and our stack-skip logger can have the same skip-count
b.doLogFatal()
b.errorData.CallListener(MethodFatal, ListenerOpt{NoLog: b.noLog}) b.errorData.CallListener(MethodFatal, ListenerOpt{NoLog: b.noLog})
os.Exit(1) os.Exit(1)
} }
func (b *Builder) doLogFatal() {
b.errorData.Log(pkgconfig.ZeroLogger.WithLevel(zerolog.FatalLevel))
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
func (b *Builder) addMeta(key string, mdtype metaDataType, val interface{}) *Builder { func (b *Builder) addMeta(key string, mdtype metaDataType, val interface{}) *Builder {

View File

@@ -3,9 +3,9 @@ package exerr
import ( import (
"context" "context"
"fmt" "fmt"
"git.blackforestbytes.com/BlackForestBytes/goext/langext"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/rs/zerolog" "github.com/rs/zerolog"
"git.blackforestbytes.com/BlackForestBytes/goext/langext"
"net/http" "net/http"
"os" "os"
) )
@@ -119,7 +119,7 @@ func newDefaultLogger() zerolog.Logger {
multi := zerolog.MultiLevelWriter(cw) multi := zerolog.MultiLevelWriter(cw)
return zerolog.New(multi).With().Timestamp().CallerWithSkipFrameCount(4).Logger() return zerolog.New(multi).With().Timestamp().CallerWithSkipFrameCount(5).Logger()
} }
func Initialized() bool { func Initialized() bool {

2
go.mod
View File

@@ -48,7 +48,7 @@ require (
github.com/pelletier/go-toml/v2 v2.2.4 // indirect github.com/pelletier/go-toml/v2 v2.2.4 // 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.14 // indirect github.com/ugorji/go/codec v1.3.0 // 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

2
go.sum
View File

@@ -187,6 +187,8 @@ github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65E
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/ugorji/go/codec v1.2.14 h1:yOQvXCBc3Ij46LRkRoh4Yd5qK6LVOgi0bYOXfb7ifjw= github.com/ugorji/go/codec v1.2.14 h1:yOQvXCBc3Ij46LRkRoh4Yd5qK6LVOgi0bYOXfb7ifjw=
github.com/ugorji/go/codec v1.2.14/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/ugorji/go/codec v1.2.14/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/ugorji/go/codec v1.3.0 h1:Qd2W2sQawAfG8XSvzwhBeoGq71zXOC/Q1E9y/wUcsUA=
github.com/ugorji/go/codec v1.3.0/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4=
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY= github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=

View File

@@ -1,5 +1,5 @@
package goext package goext
const GoextVersion = "0.0.578" const GoextVersion = "0.0.581"
const GoextVersionTimestamp = "2025-06-11T14:37:51+0200" const GoextVersionTimestamp = "2025-06-25T10:28:54+0200"

24
langext/base64.go Normal file
View File

@@ -0,0 +1,24 @@
package langext
import (
"encoding/base64"
"strings"
)
// DecodeBase64Any decodes a base64 encoded string
// Works with all variants (std, url, imap), padded and unpadded and even ignores linrebreaks and indents
func DecodeBase64Any(data string) ([]byte, error) {
data = strings.ReplaceAll(data, "\n", "") // remove linebreaks and indents
data = strings.ReplaceAll(data, "\t", "") // remove linebreaks and indents
data = strings.ReplaceAll(data, " ", "") // remove linebreaks and indents
data = strings.ReplaceAll(data, ",", "/") // base64_imap --> base64_std
data = strings.ReplaceAll(data, "_", "/") // base64_url --> base64_std
data = strings.ReplaceAll(data, "-", "+") // base64_url --> base64_std
data = strings.ReplaceAll(data, "=", " ") // no padding
return base64.RawStdEncoding.DecodeString(data)
}

View File

@@ -1,57 +1,51 @@
package mongoext package mongoext
import ( import (
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/bsoncodec"
"go.mongodb.org/mongo-driver/bson/bsontype"
"go.mongodb.org/mongo-driver/bson/primitive"
"git.blackforestbytes.com/BlackForestBytes/goext/exerr" "git.blackforestbytes.com/BlackForestBytes/goext/exerr"
"git.blackforestbytes.com/BlackForestBytes/goext/langext" "git.blackforestbytes.com/BlackForestBytes/goext/langext"
"git.blackforestbytes.com/BlackForestBytes/goext/rfctime" "git.blackforestbytes.com/BlackForestBytes/goext/rfctime"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/bsoncodec"
"go.mongodb.org/mongo-driver/bson/primitive"
"reflect" "reflect"
) )
func CreateGoExtBsonRegistry() *bsoncodec.Registry { func CreateGoExtBsonRegistry() *bsoncodec.Registry {
rb := bsoncodec.NewRegistryBuilder() reg := bson.NewRegistry()
rb.RegisterTypeDecoder(reflect.TypeOf(rfctime.RFC3339Time{}), rfctime.RFC3339Time{}) reg.RegisterTypeDecoder(reflect.TypeOf(rfctime.RFC3339Time{}), rfctime.RFC3339Time{})
rb.RegisterTypeDecoder(reflect.TypeOf(&rfctime.RFC3339Time{}), rfctime.RFC3339Time{}) reg.RegisterTypeDecoder(reflect.TypeOf(&rfctime.RFC3339Time{}), rfctime.RFC3339Time{})
rb.RegisterTypeDecoder(reflect.TypeOf(rfctime.RFC3339NanoTime{}), rfctime.RFC3339NanoTime{}) reg.RegisterTypeDecoder(reflect.TypeOf(rfctime.RFC3339NanoTime{}), rfctime.RFC3339NanoTime{})
rb.RegisterTypeDecoder(reflect.TypeOf(&rfctime.RFC3339NanoTime{}), rfctime.RFC3339NanoTime{}) reg.RegisterTypeDecoder(reflect.TypeOf(&rfctime.RFC3339NanoTime{}), rfctime.RFC3339NanoTime{})
rb.RegisterTypeDecoder(reflect.TypeOf(rfctime.UnixTime{}), rfctime.UnixTime{}) reg.RegisterTypeDecoder(reflect.TypeOf(rfctime.UnixTime{}), rfctime.UnixTime{})
rb.RegisterTypeDecoder(reflect.TypeOf(&rfctime.UnixTime{}), rfctime.UnixTime{}) reg.RegisterTypeDecoder(reflect.TypeOf(&rfctime.UnixTime{}), rfctime.UnixTime{})
rb.RegisterTypeDecoder(reflect.TypeOf(rfctime.UnixMilliTime{}), rfctime.UnixMilliTime{}) reg.RegisterTypeDecoder(reflect.TypeOf(rfctime.UnixMilliTime{}), rfctime.UnixMilliTime{})
rb.RegisterTypeDecoder(reflect.TypeOf(&rfctime.UnixMilliTime{}), rfctime.UnixMilliTime{}) reg.RegisterTypeDecoder(reflect.TypeOf(&rfctime.UnixMilliTime{}), rfctime.UnixMilliTime{})
rb.RegisterTypeDecoder(reflect.TypeOf(rfctime.UnixNanoTime{}), rfctime.UnixNanoTime{}) reg.RegisterTypeDecoder(reflect.TypeOf(rfctime.UnixNanoTime{}), rfctime.UnixNanoTime{})
rb.RegisterTypeDecoder(reflect.TypeOf(&rfctime.UnixNanoTime{}), rfctime.UnixNanoTime{}) reg.RegisterTypeDecoder(reflect.TypeOf(&rfctime.UnixNanoTime{}), rfctime.UnixNanoTime{})
rb.RegisterTypeDecoder(reflect.TypeOf(rfctime.Date{}), rfctime.Date{}) reg.RegisterTypeDecoder(reflect.TypeOf(rfctime.Date{}), rfctime.Date{})
rb.RegisterTypeDecoder(reflect.TypeOf(&rfctime.Date{}), rfctime.Date{}) reg.RegisterTypeDecoder(reflect.TypeOf(&rfctime.Date{}), rfctime.Date{})
rb.RegisterTypeDecoder(reflect.TypeOf(rfctime.SecondsF64(0)), rfctime.SecondsF64(0)) reg.RegisterTypeDecoder(reflect.TypeOf(rfctime.SecondsF64(0)), rfctime.SecondsF64(0))
rb.RegisterTypeDecoder(reflect.TypeOf(langext.Ptr(rfctime.SecondsF64(0))), rfctime.SecondsF64(0)) reg.RegisterTypeDecoder(reflect.TypeOf(langext.Ptr(rfctime.SecondsF64(0))), rfctime.SecondsF64(0))
rb.RegisterTypeDecoder(reflect.TypeOf(exerr.ErrorCategory{}), exerr.ErrorCategory{}) reg.RegisterTypeDecoder(reflect.TypeOf(exerr.ErrorCategory{}), exerr.ErrorCategory{})
rb.RegisterTypeDecoder(reflect.TypeOf(langext.Ptr(exerr.ErrorCategory{})), exerr.ErrorCategory{}) reg.RegisterTypeDecoder(reflect.TypeOf(langext.Ptr(exerr.ErrorCategory{})), exerr.ErrorCategory{})
rb.RegisterTypeDecoder(reflect.TypeOf(exerr.ErrorSeverity{}), exerr.ErrorSeverity{}) reg.RegisterTypeDecoder(reflect.TypeOf(exerr.ErrorSeverity{}), exerr.ErrorSeverity{})
rb.RegisterTypeDecoder(reflect.TypeOf(langext.Ptr(exerr.ErrorSeverity{})), exerr.ErrorSeverity{}) reg.RegisterTypeDecoder(reflect.TypeOf(langext.Ptr(exerr.ErrorSeverity{})), exerr.ErrorSeverity{})
rb.RegisterTypeDecoder(reflect.TypeOf(exerr.ErrorType{}), exerr.ErrorType{}) reg.RegisterTypeDecoder(reflect.TypeOf(exerr.ErrorType{}), exerr.ErrorType{})
rb.RegisterTypeDecoder(reflect.TypeOf(langext.Ptr(exerr.ErrorType{})), exerr.ErrorType{}) reg.RegisterTypeDecoder(reflect.TypeOf(langext.Ptr(exerr.ErrorType{})), exerr.ErrorType{})
bsoncodec.DefaultValueEncoders{}.RegisterDefaultEncoders(rb)
bsoncodec.DefaultValueDecoders{}.RegisterDefaultDecoders(rb)
bson.PrimitiveCodecs{}.RegisterPrimitiveCodecs(rb)
// otherwise we get []primitve.E when unmarshalling into any // otherwise we get []primitve.E when unmarshalling into any
// which will result in {'key': .., 'value': ...}[] json when json-marshalling // which will result in {'key': .., 'value': ...}[] json when json-marshalling
rb.RegisterTypeMapEntry(bsontype.EmbeddedDocument, reflect.TypeOf(primitive.M{})) reg.RegisterTypeMapEntry(bson.TypeEmbeddedDocument, reflect.TypeOf(primitive.M{}))
return rb.Build() return reg
} }