diff --git a/adapters/adapters_test.go b/adapters/adapters_test.go index 3f4e6bab..66cf5788 100644 --- a/adapters/adapters_test.go +++ b/adapters/adapters_test.go @@ -20,7 +20,8 @@ import ( "github.com/danielgtaylor/huma/v2/humatest" "github.com/gin-gonic/gin" "github.com/go-chi/chi/v5" - "github.com/gofiber/fiber/v2" + fiberV2 "github.com/gofiber/fiber/v2" + "github.com/gofiber/fiber/v3" "github.com/gorilla/mux" "github.com/julienschmidt/httprouter" "github.com/labstack/echo/v4" @@ -103,7 +104,8 @@ func TestAdapters(t *testing.T) { assert.Equal(t, 1, v.ProtoMajor) assert.Equal(t, 1, v.ProtoMinor) } else { - assert.Equal(t, "http", v.Proto) + // Fiber adapters (both v2 and v3) don't populate ProtoMajor/ProtoMinor + assert.Contains(t, []string{"http", "HTTP/1.1"}, v.Proto) } // Make sure huma.WithValue works correctly @@ -131,6 +133,9 @@ func TestAdapters(t *testing.T) { {"fiber", func() huma.API { return wrap(humafiber.New(fiber.New(), config()), true, func(ctx huma.Context) { humafiber.Unwrap(ctx) }) }}, + {"fiber-v2", func() huma.API { + return wrap(humafiber.NewV2(fiberV2.New(), config()), true, func(ctx huma.Context) { humafiber.UnwrapV2(ctx) }) + }}, {"go", func() huma.API { return wrap(humago.New(http.NewServeMux(), config()), false, func(ctx huma.Context) { humago.Unwrap(ctx) }) }}, diff --git a/adapters/humafiber/humafiber.go b/adapters/humafiber/humafiber.go index bb2373f4..4ea3de56 100644 --- a/adapters/humafiber/humafiber.go +++ b/adapters/humafiber/humafiber.go @@ -12,7 +12,7 @@ import ( "time" "github.com/danielgtaylor/huma/v2" - "github.com/gofiber/fiber/v2" + "github.com/gofiber/fiber/v3" ) // Unwrap extracts the underlying Fiber context from a Huma context. If passed a @@ -20,7 +20,7 @@ import ( // of the underlying Fiber/fasthttp libraries and how that impacts // memory-safety: https://docs.gofiber.io/#zero-allocation. Do not keep // references to the underlying context or its values! -func Unwrap(ctx huma.Context) *fiber.Ctx { +func Unwrap(ctx huma.Context) fiber.Ctx { for { if c, ok := ctx.(interface{ Unwrap() huma.Context }); ok { ctx = c.Unwrap() @@ -42,14 +42,14 @@ type fiberAdapter struct { type fiberWrapper struct { op *huma.Operation status int - orig *fiber.Ctx + orig fiber.Ctx ctx context.Context } -// check that fiberCtx implements huma.Context +// check that fiberWrapper implements huma.Context var _ huma.Context = &fiberWrapper{} -func (c *fiberWrapper) Unwrap() *fiber.Ctx { +func (c *fiberWrapper) Unwrap() fiber.Ctx { return c.orig } @@ -74,7 +74,7 @@ func (c *fiberWrapper) Host() string { } func (c *fiberWrapper) RemoteAddr() string { - return c.orig.Context().RemoteAddr().String() + return c.orig.RequestCtx().RemoteAddr().String() } func (c *fiberWrapper) URL() url.URL { @@ -120,7 +120,7 @@ func (c *fiberWrapper) SetReadDeadline(deadline time.Time) error { // 2. Set the Fiber app's `BodyLimit` to some small value like `1` // Fiber will only call the request handler for streaming once the limit is // reached. This is annoying but currently how things work. - return c.orig.Context().Conn().SetReadDeadline(deadline) + return c.orig.RequestCtx().Conn().SetReadDeadline(deadline) } func (c *fiberWrapper) SetStatus(code int) { @@ -132,6 +132,7 @@ func (c *fiberWrapper) SetStatus(code int) { func (c *fiberWrapper) Status() int { return c.status } + func (c *fiberWrapper) AppendHeader(name string, value string) { c.orig.Append(name, value) } @@ -141,11 +142,11 @@ func (c *fiberWrapper) SetHeader(name string, value string) { } func (c *fiberWrapper) BodyWriter() io.Writer { - return c.orig.Context() + return c.orig.RequestCtx() } func (c *fiberWrapper) TLS() *tls.ConnectionState { - return c.orig.Context().TLSConnectionState() + return c.orig.RequestCtx().TLSConnectionState() } func (c *fiberWrapper) Version() huma.ProtoVersion { @@ -155,11 +156,11 @@ func (c *fiberWrapper) Version() huma.ProtoVersion { } type router interface { - Add(method, path string, handlers ...fiber.Handler) fiber.Router + Add(methods []string, path string, handler any, handlers ...any) fiber.Router } type requestTester interface { - Test(*http.Request, ...int) (*http.Response, error) + Test(*http.Request, ...fiber.TestConfig) (*http.Response, error) } type contextWrapperValue struct { @@ -194,9 +195,9 @@ func (a *fiberAdapter) Handle(op *huma.Operation, handler func(huma.Context)) { path := op.Path path = strings.ReplaceAll(path, "{", ":") path = strings.ReplaceAll(path, "}", "") - a.router.Add(op.Method, path, func(c *fiber.Ctx) error { + a.router.Add([]string{op.Method}, path, func(c fiber.Ctx) error { var values []*contextWrapperValue - c.Context().VisitUserValuesAll(func(key, value any) { + c.RequestCtx().VisitUserValuesAll(func(key, value any) { values = append(values, &contextWrapperValue{ Key: key, Value: value, @@ -207,7 +208,7 @@ func (a *fiberAdapter) Handle(op *huma.Operation, handler func(huma.Context)) { orig: c, ctx: &contextWrapper{ values: values, - Context: c.UserContext(), + Context: c.Context(), }, }) return nil @@ -215,8 +216,6 @@ func (a *fiberAdapter) Handle(op *huma.Operation, handler func(huma.Context)) { } func (a *fiberAdapter) ServeHTTP(w http.ResponseWriter, r *http.Request) { - // b, _ := httputil.DumpRequest(r, true) - // fmt.Println(string(b)) resp, err := a.tester.Test(r) if resp != nil && resp.Body != nil { defer func() { @@ -236,10 +235,12 @@ func (a *fiberAdapter) ServeHTTP(w http.ResponseWriter, r *http.Request) { _, _ = io.Copy(w, resp.Body) } +// New creates a new Huma API using the Fiber adapter. func New(r *fiber.App, config huma.Config) huma.API { return huma.NewAPI(config, &fiberAdapter{tester: r, router: r}) } +// NewWithGroup creates a new Huma API using the Fiber adapter with a route group. func NewWithGroup(r *fiber.App, g fiber.Router, config huma.Config) huma.API { return huma.NewAPI(config, &fiberAdapter{tester: r, router: g}) } diff --git a/adapters/humafiber/humafiber_context_test.go b/adapters/humafiber/humafiber_context_test.go index d5c1fe64..424b32dd 100644 --- a/adapters/humafiber/humafiber_context_test.go +++ b/adapters/humafiber/humafiber_context_test.go @@ -16,7 +16,7 @@ import ( "github.com/danielgtaylor/huma/v2" "github.com/danielgtaylor/huma/v2/adapters/humafiber" - "github.com/gofiber/fiber/v2" + "github.com/gofiber/fiber/v3" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -64,7 +64,7 @@ const ( HelloPath = "/hello" ) -func PingHandler(c *fiber.Ctx) error { +func PingHandler(c fiber.Ctx) error { return c.SendStatus(fiber.StatusOK) } @@ -192,21 +192,21 @@ func HelloResponseValidate(t *testing.T, expected HelloResponseBody, response *h } } -func FiberMiddlewareUserValue(c *fiber.Ctx) error { +func FiberMiddlewareUserValue(c fiber.Ctx) error { headers := c.GetReqHeaders() if values, found := headers[HeaderNameFiberUserValue]; found && len(values) > 0 { - c.Context().SetUserValue(contextValueFiberUserValue, values[0]) + c.Locals(contextValueFiberUserValue, values[0]) } return c.Next() } -func FiberMiddlewareUserContext(c *fiber.Ctx) error { +func FiberMiddlewareUserContext(c fiber.Ctx) error { headers := c.GetReqHeaders() if values, found := headers[HeaderNameFiberUserContext]; found && len(values) > 0 { - var original = c.UserContext() + var original = c.Context() var result = context.WithValue(original, contextValueFiberUserContext, values[0]) - c.SetUserContext(result) - defer c.SetUserContext(original) + c.SetContext(result) + defer c.SetContext(original) } return c.Next() } @@ -236,9 +236,7 @@ func TestHumaFiber(t *testing.T) { require.NotZero(t, port) server := fmt.Sprintf("http://localhost:%d", port) - app := fiber.New(fiber.Config{ - DisableStartupMessage: true, - }) + app := fiber.New() app.Use(FiberMiddlewareUserValue) app.Use(FiberMiddlewareUserContext) RegisterPing(app) diff --git a/adapters/humafiber/humafiber_test.go b/adapters/humafiber/humafiber_test.go index 1538d9d2..119f18ce 100644 --- a/adapters/humafiber/humafiber_test.go +++ b/adapters/humafiber/humafiber_test.go @@ -6,7 +6,7 @@ import ( "testing" "github.com/danielgtaylor/huma/v2" - "github.com/gofiber/fiber/v2" + "github.com/gofiber/fiber/v3" ) func BenchmarkHumaFiber(b *testing.B) { @@ -48,7 +48,7 @@ func BenchmarkNotHuma(b *testing.B) { r := fiber.New() - r.Get("/foo/:id", func(c *fiber.Ctx) error { + r.Get("/foo/:id", func(c fiber.Ctx) error { return c.JSON(&GreetingOutput{"Hello, " + c.Params("id")}) }) diff --git a/adapters/humafiber/humafiber_v2.go b/adapters/humafiber/humafiber_v2.go new file mode 100644 index 00000000..a4808a60 --- /dev/null +++ b/adapters/humafiber/humafiber_v2.go @@ -0,0 +1,248 @@ +package humafiber + +import ( + "bytes" + "context" + "crypto/tls" + "io" + "mime/multipart" + "net/http" + "net/url" + "strings" + "time" + + "github.com/danielgtaylor/huma/v2" + fiberV2 "github.com/gofiber/fiber/v2" +) + +// UnwrapV2 extracts the underlying Fiber v2 context from a Huma context. If +// passed a context from a different adapter it will panic. Keep in mind the +// limitations of the underlying Fiber/fasthttp libraries and how that impacts +// memory-safety: https://docs.gofiber.io/#zero-allocation. Do not keep +// references to the underlying context or its values! +func UnwrapV2(ctx huma.Context) *fiberV2.Ctx { + for { + if c, ok := ctx.(interface{ Unwrap() huma.Context }); ok { + ctx = c.Unwrap() + continue + } + break + } + if c, ok := ctx.(*fiberV2Wrapper); ok { + return c.Unwrap() + } + panic("not a humafiber v2 context") +} + +type fiberV2Adapter struct { + tester requestTesterV2 + router routerV2 +} + +type fiberV2Wrapper struct { + op *huma.Operation + status int + orig *fiberV2.Ctx + ctx context.Context +} + +// check that fiberV2Wrapper implements huma.Context +var _ huma.Context = &fiberV2Wrapper{} + +func (c *fiberV2Wrapper) Unwrap() *fiberV2.Ctx { + return c.orig +} + +func (c *fiberV2Wrapper) Operation() *huma.Operation { + return c.op +} + +func (c *fiberV2Wrapper) Matched() string { + return c.orig.Route().Path +} + +func (c *fiberV2Wrapper) Context() context.Context { + return c.ctx +} + +func (c *fiberV2Wrapper) Method() string { + return c.orig.Method() +} + +func (c *fiberV2Wrapper) Host() string { + return c.orig.Hostname() +} + +func (c *fiberV2Wrapper) RemoteAddr() string { + return c.orig.Context().RemoteAddr().String() +} + +func (c *fiberV2Wrapper) URL() url.URL { + u, _ := url.Parse(string(c.orig.Request().RequestURI())) + return *u +} + +func (c *fiberV2Wrapper) Param(name string) string { + return c.orig.Params(name) +} + +func (c *fiberV2Wrapper) Query(name string) string { + return c.orig.Query(name) +} + +func (c *fiberV2Wrapper) Header(name string) string { + return c.orig.Get(name) +} + +func (c *fiberV2Wrapper) EachHeader(cb func(name, value string)) { + for name, values := range c.orig.Request().Header.All() { + for _, value := range values { + cb(string(name), string(value)) + } + } +} + +func (c *fiberV2Wrapper) BodyReader() io.Reader { + var orig = c.orig + if orig.App().Server().StreamRequestBody { + // Streaming is enabled, so send the reader. + return orig.Request().BodyStream() + } + return bytes.NewReader(orig.BodyRaw()) +} + +func (c *fiberV2Wrapper) GetMultipartForm() (*multipart.Form, error) { + return c.orig.MultipartForm() +} + +func (c *fiberV2Wrapper) SetReadDeadline(deadline time.Time) error { + // Note: for this to work properly you need to do two things: + // 1. Set the Fiber app's `StreamRequestBody` to `true` + // 2. Set the Fiber app's `BodyLimit` to some small value like `1` + // Fiber will only call the request handler for streaming once the limit is + // reached. This is annoying but currently how things work. + return c.orig.Context().Conn().SetReadDeadline(deadline) +} + +func (c *fiberV2Wrapper) SetStatus(code int) { + var orig = c.orig + c.status = code + orig.Status(code) +} + +func (c *fiberV2Wrapper) Status() int { + return c.status +} + +func (c *fiberV2Wrapper) AppendHeader(name string, value string) { + c.orig.Append(name, value) +} + +func (c *fiberV2Wrapper) SetHeader(name string, value string) { + c.orig.Set(name, value) +} + +func (c *fiberV2Wrapper) BodyWriter() io.Writer { + return c.orig.Context() +} + +func (c *fiberV2Wrapper) TLS() *tls.ConnectionState { + return c.orig.Context().TLSConnectionState() +} + +func (c *fiberV2Wrapper) Version() huma.ProtoVersion { + return huma.ProtoVersion{ + Proto: c.orig.Protocol(), + } +} + +type routerV2 interface { + Add(method, path string, handlers ...fiberV2.Handler) fiberV2.Router +} + +type requestTesterV2 interface { + Test(*http.Request, ...int) (*http.Response, error) +} + +type contextV2WrapperValue struct { + Key any + Value any +} + +type contextV2Wrapper struct { + values []*contextV2WrapperValue + context.Context +} + +var ( + _ context.Context = &contextV2Wrapper{} +) + +func (c *contextV2Wrapper) Value(key any) any { + var raw = c.Context.Value(key) + if raw != nil { + return raw + } + for _, pair := range c.values { + if pair.Key == key { + return pair.Value + } + } + return nil +} + +func (a *fiberV2Adapter) Handle(op *huma.Operation, handler func(huma.Context)) { + // Convert {param} to :param + path := op.Path + path = strings.ReplaceAll(path, "{", ":") + path = strings.ReplaceAll(path, "}", "") + a.router.Add(op.Method, path, func(c *fiberV2.Ctx) error { + var values []*contextV2WrapperValue + c.Context().VisitUserValuesAll(func(key, value any) { + values = append(values, &contextV2WrapperValue{ + Key: key, + Value: value, + }) + }) + handler(&fiberV2Wrapper{ + op: op, + orig: c, + ctx: &contextV2Wrapper{ + values: values, + Context: c.UserContext(), + }, + }) + return nil + }) +} + +func (a *fiberV2Adapter) ServeHTTP(w http.ResponseWriter, r *http.Request) { + resp, err := a.tester.Test(r) + if resp != nil && resp.Body != nil { + defer func() { + _ = resp.Body.Close() + }() + } + if err != nil { + panic(err) + } + h := w.Header() + for k, v := range resp.Header { + for item := range v { + h.Add(k, v[item]) + } + } + w.WriteHeader(resp.StatusCode) + _, _ = io.Copy(w, resp.Body) +} + +// NewV2 creates a new Huma API using the Fiber v2.x adapter. +func NewV2(r *fiberV2.App, config huma.Config) huma.API { + return huma.NewAPI(config, &fiberV2Adapter{tester: r, router: r}) +} + +// NewV2WithGroup creates a new Huma API using the Fiber v2.x adapter with a +// route group. +func NewV2WithGroup(r *fiberV2.App, g fiberV2.Router, config huma.Config) huma.API { + return huma.NewAPI(config, &fiberV2Adapter{tester: r, router: g}) +} diff --git a/adapters/humafiber/humafiber_v2_context_test.go b/adapters/humafiber/humafiber_v2_context_test.go new file mode 100644 index 00000000..997634f2 --- /dev/null +++ b/adapters/humafiber/humafiber_v2_context_test.go @@ -0,0 +1,203 @@ +package humafiber_test + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "net" + "net/http" + "os/signal" + "sync" + "syscall" + "testing" + "time" + + "github.com/danielgtaylor/huma/v2" + "github.com/danielgtaylor/huma/v2/adapters/humafiber" + fiberV2 "github.com/gofiber/fiber/v2" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func PingHandlerV2(c *fiberV2.Ctx) error { + return c.SendStatus(fiberV2.StatusOK) +} + +func RegisterPingV2(app *fiberV2.App) { + _ = app.Get(PingPath, PingHandlerV2) +} + +func FiberMiddlewareUserValueV2(c *fiberV2.Ctx) error { + headers := c.GetReqHeaders() + if values, found := headers[HeaderNameFiberUserValue]; found && len(values) > 0 { + c.Context().SetUserValue(contextValueFiberUserValue, values[0]) + } + return c.Next() +} + +func FiberMiddlewareUserContextV2(c *fiberV2.Ctx) error { + headers := c.GetReqHeaders() + if values, found := headers[HeaderNameFiberUserContext]; found && len(values) > 0 { + var original = c.UserContext() + var result = context.WithValue(original, contextValueFiberUserContext, values[0]) + c.SetUserContext(result) + defer c.SetUserContext(original) + } + return c.Next() +} + +func TestHumaFiberV2(t *testing.T) { + ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) + defer cancel() + + var wait sync.WaitGroup + defer wait.Wait() + + timeout := time.Millisecond * 10 + retries := 10 + simulator := SimulateAccessToContextOutsideHandler(ctx, &wait, timeout, retries) + + ln, err := net.Listen("tcp4", "127.0.0.1:0") + require.NoError(t, err) + port := ln.Addr().(*net.TCPAddr).Port + require.NotZero(t, port) + server := fmt.Sprintf("http://localhost:%d", port) + + app := fiberV2.New(fiberV2.Config{ + DisableStartupMessage: true, + }) + app.Use(FiberMiddlewareUserValueV2) + app.Use(FiberMiddlewareUserContextV2) + RegisterPingV2(app) + + config := huma.DefaultConfig("hello", "1.0.0") + api := humafiber.NewV2(app, config) + api.UseMiddleware(HumaMiddleware) + huma.Register(api, HelloOperation(), HelloHandler(simulator)) + + wait.Add(1) + go func() { + defer wait.Done() + err := app.Listener(ln) + assert.NoError(t, err) + }() + defer wait.Wait() + + err = WaitPing(ctx, server, timeout) + require.NoError(t, err) + + name := "Bob" + message := fmt.Sprintf("Hello, %s!", name) + requestBody, err := json.Marshal(HelloRequestBody{ + Name: name, + }) + require.NoError(t, err) + assert.NotEmpty(t, requestBody) + requestBodyReader := bytes.NewReader(requestBody) + expected := HelloResponseBody{ + Message: message, + FiberUserValue: "one", + FiberUserContext: "two", + Huma: "three", + } + + request, err := http.NewRequestWithContext(ctx, fiberV2.MethodPost, server+HelloPath, requestBodyReader) + require.NoError(t, err) + request.Header.Add(HeaderNameFiberUserValue, "one") + request.Header.Add(HeaderNameFiberUserContext, "two") + request.Header.Add(HeaderNameHuma, "three") + query := request.URL.Query() + query.Add("huma-fiber-delay", timeout.String()) + request.URL.RawQuery = query.Encode() + + // simple check + response, err := http.DefaultClient.Do(request) + if response != nil && response.Body != nil { + defer func() { + _ = response.Body.Close() + }() + } + require.NoError(t, err) + HelloResponseValidate(t, expected, response) + + // check that delay works + doneFirst := make(chan bool) + wait.Add(1) + go func() { + defer wait.Done() + defer close(doneFirst) + response, err := http.DefaultClient.Do(request) + if response != nil && response.Body != nil { + defer func() { + _ = response.Body.Close() + }() + } + assert.NoError(t, err) + HelloResponseValidate(t, expected, response) + }() + select { + case <-ctx.Done(): + return + case <-doneFirst: + assert.Fail(t, "expected other branch") + default: + // ok + } + select { + case <-ctx.Done(): + return + case <-doneFirst: + // ok + case <-time.After(timeout * 2): + assert.Fail(t, "expected other branch") + } + + // check graceful shutdown + doneSecond := make(chan bool) + wait.Add(1) + go func() { + defer wait.Done() + defer close(doneSecond) + response, err := http.DefaultClient.Do(request) + if response != nil && response.Body != nil { + defer func() { + _ = response.Body.Close() + }() + } + assert.NoError(t, err) + HelloResponseValidate(t, expected, response) + }() + + // perform shutdown + doneShutdown := make(chan bool) + wait.Add(1) + go func() { + defer wait.Done() + defer close(doneShutdown) + time.Sleep(timeout) // delay before shutdown to start request processing + err := app.ShutdownWithContext(ctx) + assert.NoError(t, err) + time.Sleep(timeout) // delay after shutdown to catch request processing + }() + + // request should be handled + select { + case <-ctx.Done(): + return + case <-doneSecond: + // ok + case <-doneShutdown: + assert.Fail(t, "expected other branch") + } + + // shutdown should be handled + select { + case <-ctx.Done(): + return + case <-doneShutdown: + // ok + } + + wait.Wait() +} diff --git a/adapters/humafiber/humafiber_v2_test.go b/adapters/humafiber/humafiber_v2_test.go new file mode 100644 index 00000000..8a76752e --- /dev/null +++ b/adapters/humafiber/humafiber_v2_test.go @@ -0,0 +1,61 @@ +package humafiber + +import ( + "context" + "net/http" + "testing" + + "github.com/danielgtaylor/huma/v2" + fiberV2 "github.com/gofiber/fiber/v2" +) + +func BenchmarkHumaFiberV2(b *testing.B) { + type GreetingInput struct { + ID string `path:"id"` + } + + type GreetingOutput struct { + Body struct { + Greeting string `json:"greeting"` + } + } + + r := fiberV2.New() + api := NewV2(r, huma.DefaultConfig("Test API", "1.0.0")) + + huma.Register(api, huma.Operation{ + OperationID: "greet", + Method: http.MethodGet, + Path: "/foo/{id}", + }, func(ctx context.Context, input *GreetingInput) (*GreetingOutput, error) { + resp := &GreetingOutput{} + resp.Body.Greeting = "Hello, " + input.ID + return resp, nil + }) + + b.ResetTimer() + b.ReportAllocs() + req, _ := http.NewRequest(http.MethodGet, "/foo/123", nil) + for i := 0; i < b.N; i++ { + r.Test(req) + } +} + +func BenchmarkNotHumaV2(b *testing.B) { + type GreetingOutput struct { + Greeting string `json:"greeting"` + } + + r := fiberV2.New() + + r.Get("/foo/:id", func(c *fiberV2.Ctx) error { + return c.JSON(&GreetingOutput{"Hello, " + c.Params("id")}) + }) + + b.ResetTimer() + b.ReportAllocs() + req, _ := http.NewRequest(http.MethodGet, "/foo/123", nil) + for i := 0; i < b.N; i++ { + r.Test(req) + } +} diff --git a/go.mod b/go.mod index 29717df5..b506f2ff 100644 --- a/go.mod +++ b/go.mod @@ -5,14 +5,15 @@ go 1.25.0 require ( github.com/danielgtaylor/shorthand/v2 v2.2.0 github.com/evanphx/json-patch/v5 v5.9.11 - github.com/fxamacker/cbor/v2 v2.9.0 - github.com/gin-gonic/gin v1.11.0 + github.com/fxamacker/cbor/v2 v2.9.1 + github.com/gin-gonic/gin v1.12.0 github.com/go-chi/chi/v5 v5.2.5 github.com/gofiber/fiber/v2 v2.52.12 + github.com/gofiber/fiber/v3 v3.1.0 github.com/google/uuid v1.6.0 github.com/gorilla/mux v1.8.1 github.com/julienschmidt/httprouter v1.3.0 - github.com/labstack/echo/v4 v4.15.0 + github.com/labstack/echo/v4 v4.15.1 github.com/spf13/cobra v1.10.2 github.com/spf13/pflag v1.0.10 github.com/stretchr/testify v1.11.1 @@ -20,38 +21,41 @@ require ( ) require ( - github.com/andybalholm/brotli v1.2.0 // indirect - github.com/bytedance/gopkg v0.1.3 // indirect + github.com/andybalholm/brotli v1.2.1 // indirect + github.com/bytedance/gopkg v0.1.4 // indirect github.com/bytedance/sonic v1.15.0 // indirect - github.com/bytedance/sonic/loader v0.5.0 // indirect + github.com/bytedance/sonic/loader v0.5.1 // indirect github.com/clipperhouse/uax29/v2 v2.7.0 // indirect github.com/cloudwego/base64x v0.1.6 // indirect github.com/danielgtaylor/mexpr v1.9.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/gabriel-vasile/mimetype v1.4.13 // indirect - github.com/gin-contrib/sse v1.1.0 // indirect + github.com/gin-contrib/sse v1.1.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/validator/v10 v10.30.1 // indirect - github.com/goccy/go-json v0.10.5 // indirect + github.com/go-playground/validator/v10 v10.30.2 // indirect + github.com/goccy/go-json v0.10.6 // indirect github.com/goccy/go-yaml v1.19.2 // indirect + github.com/gofiber/schema v1.7.0 // indirect + github.com/gofiber/utils/v2 v2.0.2 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.18.4 // indirect + github.com/klauspost/compress v1.18.5 // indirect github.com/klauspost/cpuid/v2 v2.3.0 // indirect - github.com/kr/text v0.2.0 // indirect github.com/labstack/gommon v0.4.2 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-runewidth v0.0.20 // indirect + github.com/mattn/go-runewidth v0.0.21 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/pelletier/go-toml/v2 v2.2.4 // indirect + github.com/pelletier/go-toml/v2 v2.3.0 // indirect + github.com/philhofer/fwd v1.2.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/quic-go/qpack v0.6.0 // indirect github.com/quic-go/quic-go v0.59.0 // indirect github.com/rogpeppe/go-internal v1.14.1 // indirect + github.com/tinylib/msgp v1.6.3 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.3.1 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect @@ -59,12 +63,12 @@ require ( github.com/valyala/fasttemplate v1.2.2 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/xyproto/randomstring v1.2.0 // indirect - go.uber.org/mock v0.6.0 // indirect - golang.org/x/arch v0.24.0 // indirect - golang.org/x/crypto v0.48.0 // indirect - golang.org/x/net v0.50.0 // indirect - golang.org/x/sys v0.41.0 // indirect - golang.org/x/text v0.34.0 // indirect + go.mongodb.org/mongo-driver/v2 v2.5.0 // indirect + golang.org/x/arch v0.25.0 // indirect + golang.org/x/crypto v0.49.0 // indirect + golang.org/x/net v0.52.0 // indirect + golang.org/x/sys v0.42.0 // indirect + golang.org/x/text v0.35.0 // indirect google.golang.org/protobuf v1.36.11 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index cfa176f9..df545f19 100644 --- a/go.sum +++ b/go.sum @@ -1,17 +1,16 @@ -github.com/andybalholm/brotli v1.2.0 h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwToPjQ= -github.com/andybalholm/brotli v1.2.0/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY= -github.com/bytedance/gopkg v0.1.3 h1:TPBSwH8RsouGCBcMBktLt1AymVo2TVsBVCY4b6TnZ/M= -github.com/bytedance/gopkg v0.1.3/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM= +github.com/andybalholm/brotli v1.2.1 h1:R+f5xP285VArJDRgowrfb9DqL18yVK0gKAW/F+eTWro= +github.com/andybalholm/brotli v1.2.1/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY= +github.com/bytedance/gopkg v0.1.4 h1:oZnQwnX82KAIWb7033bEwtxvTqXcYMxDBaQxo5JJHWM= +github.com/bytedance/gopkg v0.1.4/go.mod h1:v1zWfPm21Fb+OsyXN2VAHdL6TBb2L88anLQgdyje6R4= github.com/bytedance/sonic v1.15.0 h1:/PXeWFaR5ElNcVE84U0dOHjiMHQOwNIx3K4ymzh/uSE= github.com/bytedance/sonic v1.15.0/go.mod h1:tFkWrPz0/CUCLEF4ri4UkHekCIcdnkqXw9VduqpJh0k= -github.com/bytedance/sonic/loader v0.5.0 h1:gXH3KVnatgY7loH5/TkeVyXPfESoqSBSBEiDd5VjlgE= -github.com/bytedance/sonic/loader v0.5.0/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo= +github.com/bytedance/sonic/loader v0.5.1 h1:Ygpfa9zwRCCKSlrp5bBP/b/Xzc3VxsAW+5NIYXrOOpI= +github.com/bytedance/sonic/loader v0.5.1/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo= github.com/clipperhouse/uax29/v2 v2.7.0 h1:+gs4oBZ2gPfVrKPthwbMzWZDaAFPGYK72F0NJv2v7Vk= github.com/clipperhouse/uax29/v2 v2.7.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM= github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M= github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/danielgtaylor/mexpr v1.9.1 h1:nA9bsGRmNlJeVCPFgGf7WhrLuKag/+iWfOaJ03iKFPI= github.com/danielgtaylor/mexpr v1.9.1/go.mod h1:kAivYNRnBeE/IJinqBvVFvLrX54xX//9zFYwADo4Bc8= github.com/danielgtaylor/shorthand/v2 v2.2.0 h1:hVsemdRq6v3JocP6YRTfu9rOoghZI9PFmkngdKqzAVQ= @@ -21,14 +20,14 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU= github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM= -github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM= -github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= +github.com/fxamacker/cbor/v2 v2.9.1 h1:2rWm8B193Ll4VdjsJY28jxs70IdDsHRWgQYAI80+rMQ= +github.com/fxamacker/cbor/v2 v2.9.1/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= github.com/gabriel-vasile/mimetype v1.4.13 h1:46nXokslUBsAJE/wMsp5gtO500a4F3Nkz9Ufpk2AcUM= github.com/gabriel-vasile/mimetype v1.4.13/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s= -github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w= -github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM= -github.com/gin-gonic/gin v1.11.0 h1:OW/6PLjyusp2PPXtyxKHU0RbX6I/l28FTdDlae5ueWk= -github.com/gin-gonic/gin v1.11.0/go.mod h1:+iq/FyxlGzII0KHiBGjuNn4UNENUlKbGlNmc+W50Dls= +github.com/gin-contrib/sse v1.1.1 h1:uGYpNwTacv5R68bSGMapo62iLTRa9l5zxGCps4hK6ko= +github.com/gin-contrib/sse v1.1.1/go.mod h1:QXzuVkA0YO7o/gun03UI1Q+FTI8ZV/n5t03kIQAI89s= +github.com/gin-gonic/gin v1.12.0 h1:b3YAbrZtnf8N//yjKeU2+MQsh2mY5htkZidOM7O0wG8= +github.com/gin-gonic/gin v1.12.0/go.mod h1:VxccKfsSllpKshkBWgVgRniFFAzFb9csfngsqANjnLc= github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug= github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= @@ -37,14 +36,20 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.30.1 h1:f3zDSN/zOma+w6+1Wswgd9fLkdwy06ntQJp0BBvFG0w= -github.com/go-playground/validator/v10 v10.30.1/go.mod h1:oSuBIQzuJxL//3MelwSLD5hc2Tu889bF0Idm9Dg26cM= -github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= -github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= +github.com/go-playground/validator/v10 v10.30.2 h1:JiFIMtSSHb2/XBUbWM4i/MpeQm9ZK2xqPNk8vgvu5JQ= +github.com/go-playground/validator/v10 v10.30.2/go.mod h1:mAf2pIOVXjTEBrwUMGKkCWKKPs9NheYGabeB04txQSc= +github.com/goccy/go-json v0.10.6 h1:p8HrPJzOakx/mn/bQtjgNjdTcN+/S6FcG2CTtQOrHVU= +github.com/goccy/go-json v0.10.6/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM= github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/gofiber/fiber/v2 v2.52.12 h1:0LdToKclcPOj8PktUdIKo9BUohjjwfnQl42Dhw8/WUw= github.com/gofiber/fiber/v2 v2.52.12/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw= +github.com/gofiber/fiber/v3 v3.1.0 h1:1p4I820pIa+FGxfwWuQZ5rAyX0WlGZbGT6Hnuxt6hKY= +github.com/gofiber/fiber/v3 v3.1.0/go.mod h1:n2nYQovvL9z3Too/FGOfgtERjW3GQcAUqgfoezGBZdU= +github.com/gofiber/schema v1.7.0 h1:yNM+FNRZjyYEli9Ey0AXRBrAY9jTnb+kmGs3lJGPvKg= +github.com/gofiber/schema v1.7.0/go.mod h1:A/X5Ffyru4p9eBdp99qu+nzviHzQiZ7odLT+TwxWhbk= +github.com/gofiber/utils/v2 v2.0.2 h1:ShRRssz0F3AhTlAQcuEj54OEDtWF7+HJDwEi/aa6QLI= +github.com/gofiber/utils/v2 v2.0.2/go.mod h1:+9Ub4NqQ+IaJoTliq5LfdmOJAA/Hzwf4pXOxOa3RrJ0= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -58,16 +63,16 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c= -github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4= +github.com/klauspost/compress v1.18.5 h1:/h1gH5Ce+VWNLSWqPzOVn6XBO+vJbCNGvjoaGBFW2IE= +github.com/klauspost/compress v1.18.5/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/labstack/echo/v4 v4.15.0 h1:hoRTKWcnR5STXZFe9BmYun9AMTNeSbjHi2vtDuADJ24= -github.com/labstack/echo/v4 v4.15.0/go.mod h1:xmw1clThob0BSVRX1CRQkGQ/vjwcpOMjQZSZa9fKA/c= +github.com/labstack/echo/v4 v4.15.1 h1:S9keusg26gZpjMmPqB5hOEvNKnmd1lNmcHrbbH2lnFs= +github.com/labstack/echo/v4 v4.15.1/go.mod h1:xmw1clThob0BSVRX1CRQkGQ/vjwcpOMjQZSZa9fKA/c= github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0= github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= @@ -76,15 +81,17 @@ github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHP github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.20 h1:WcT52H91ZUAwy8+HUkdM3THM6gXqXuLJi9O3rjcQQaQ= -github.com/mattn/go-runewidth v0.0.20/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= +github.com/mattn/go-runewidth v0.0.21 h1:jJKAZiQH+2mIinzCJIaIG9Be1+0NR+5sz/lYEEjdM8w= +github.com/mattn/go-runewidth v0.0.21/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= 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/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= -github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= +github.com/pelletier/go-toml/v2 v2.3.0 h1:k59bC/lIZREW0/iVaQR8nDHxVq8OVlIzYCOJf421CaM= +github.com/pelletier/go-toml/v2 v2.3.0/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= +github.com/philhofer/fwd v1.2.0 h1:e6DnBTl7vGY+Gz322/ASL4Gyp1FspeMvx1RNDoToZuM= +github.com/philhofer/fwd v1.2.0/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM= 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/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8= @@ -94,6 +101,8 @@ github.com/quic-go/quic-go v0.59.0/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRC github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/shamaton/msgpack/v3 v3.1.0 h1:jsk0vEAqVvvS9+fTZ5/EcQ9tz860c9pWxJ4Iwecz8gU= +github.com/shamaton/msgpack/v3 v3.1.0/go.mod h1:DcQG8jrdrQCIxr3HlMYkiXdMhK+KfN2CitkyzsQV4uc= github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= @@ -110,6 +119,8 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/tinylib/msgp v1.6.3 h1:bCSxiTz386UTgyT1i0MSCvdbWjVW+8sG3PjkGsZQt4s= +github.com/tinylib/msgp v1.6.3/go.mod h1:RSp0LW9oSxFut3KzESt5Voq4GVWyS+PSulT77roAqEA= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/ugorji/go/codec v1.3.1 h1:waO7eEiFDwidsBN6agj1vJQ4AG7lh2yqXyOXqhgQuyY= @@ -126,20 +137,22 @@ github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xyproto/randomstring v1.2.0 h1:y7PXAEBM3XlwJjPG2JQg4voxBYZ4+hPgRdGKCfU8wik= github.com/xyproto/randomstring v1.2.0/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= +go.mongodb.org/mongo-driver/v2 v2.5.0 h1:yXUhImUjjAInNcpTcAlPHiT7bIXhshCTL3jVBkF3xaE= +go.mongodb.org/mongo-driver/v2 v2.5.0/go.mod h1:yOI9kBsufol30iFsl1slpdq1I0eHPzybRWdyYUs8K/0= go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y= go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= -golang.org/x/arch v0.24.0 h1:qlJ3M9upxvFfwRM51tTg3Yl+8CP9vCC1E7vlFpgv99Y= -golang.org/x/arch v0.24.0/go.mod h1:dNHoOeKiyja7GTvF9NJS1l3Z2yntpQNzgrjh1cU103A= -golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= -golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= -golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60= -golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM= +golang.org/x/arch v0.25.0 h1:qnk6Ksugpi5Bz32947rkUgDt9/s5qvqDPl/gBKdMJLE= +golang.org/x/arch v0.25.0/go.mod h1:0X+GdSIP+kL5wPmpK7sdkEVTt2XoYP0cSjQSbZBwOi8= +golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= +golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= +golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0= +golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= -golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk= -golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA= +golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo= +golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8= +golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=