From 2fa53c4bebf3b412f616fb94c76a832d9d90db5b Mon Sep 17 00:00:00 2001 From: 42Atomys Date: Mon, 9 Sep 2024 18:44:23 +0200 Subject: [PATCH 1/2] feat: use go-sprout/sprout project for functions and remap to github url --- .devcontainer/devcontainer.json | 3 +- .devcontainer/docker-compose.yaml | 2 +- README.md | 4 +- cmd/serve.go | 4 +- go.mod | 9 +- go.sum | 23 +- internal/config/configuration.go | 4 +- internal/config/configuration_test.go | 4 +- internal/config/structs.go | 4 +- internal/server/middlewares.go | 4 +- internal/server/middlewares_test.go | 2 +- internal/server/serve.go | 4 +- internal/server/v1alpha1/handlers.go | 4 +- internal/server/v1alpha1/handlers_test.go | 8 +- main.go | 2 +- pkg/factory/f_compare_test.go | 2 +- pkg/factory/f_debug_test.go | 2 +- pkg/factory/f_generate_hmac_256_test.go | 2 +- pkg/factory/f_has_prefix_test.go | 2 +- pkg/factory/f_has_suffix_test.go | 2 +- pkg/factory/f_header_test.go | 2 +- pkg/factory/factory.go | 2 +- pkg/factory/factory_test.go | 2 +- pkg/factory/mapstructure_decode.go | 2 +- pkg/factory/structs.go | 2 +- pkg/formatting/formatter.go | 70 ++- pkg/formatting/formatter_test.go | 16 +- pkg/formatting/functions.go | 537 ---------------------- pkg/formatting/functions_is_to_test.go | 211 --------- pkg/formatting/functions_math_test.go | 182 -------- pkg/formatting/functions_test.go | 226 --------- pkg/storage/postgres/postgres.go | 4 +- pkg/storage/postgres/postgres_test.go | 2 +- pkg/storage/rabbitmq/rabbitmq.go | 2 +- pkg/storage/redis/redis.go | 2 +- pkg/storage/storage.go | 6 +- 36 files changed, 125 insertions(+), 1234 deletions(-) delete mode 100644 pkg/formatting/functions.go delete mode 100644 pkg/formatting/functions_is_to_test.go delete mode 100644 pkg/formatting/functions_math_test.go delete mode 100644 pkg/formatting/functions_test.go diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index afd2d51..41a9efd 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -77,7 +77,8 @@ "cschleiden.vscode-github-actions", "eamodio.gitlens", "jinliming2.vscode-go-template", - "quicktype.quicktype" + "quicktype.quicktype", + "golang.go" ] } }, diff --git a/.devcontainer/docker-compose.yaml b/.devcontainer/docker-compose.yaml index 0c6fc3b..64bf7de 100644 --- a/.devcontainer/docker-compose.yaml +++ b/.devcontainer/docker-compose.yaml @@ -1,7 +1,7 @@ version: '3.1' services: workspace: - image: mcr.microsoft.com/devcontainers/go:1.0.0-1.20-bookworm + image: mcr.microsoft.com/devcontainers/go:1-1.23 volumes: - ..:/workspace:cached environment: diff --git a/README.md b/README.md index 5904eaa..25229ae 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@

Webhooked

Release 🎉 - + Code Climate maintainability Codecov GitHub release (latest by date) @@ -9,7 +9,7 @@ GitHub Repo stars Docker Pull Docker Pull -Go Reference

+Go Reference

A webhook receiver on steroids. The process is simple, receive webhook from all over the world, and send it to your favorite pub/sub to process it immediately or later without losing any received data

diff --git a/cmd/serve.go b/cmd/serve.go index 0a234fe..2b19885 100644 --- a/cmd/serve.go +++ b/cmd/serve.go @@ -27,8 +27,8 @@ import ( "github.com/rs/zerolog/log" "github.com/spf13/cobra" - "atomys.codes/webhooked/internal/config" - "atomys.codes/webhooked/internal/server" + "github.com/42atomys/webhooked/internal/config" + "github.com/42atomys/webhooked/internal/server" ) var ( diff --git a/go.mod b/go.mod index 90b3860..2cce256 100644 --- a/go.mod +++ b/go.mod @@ -1,9 +1,10 @@ -module atomys.codes/webhooked +module github.com/42atomys/webhooked -go 1.20 +go 1.23 require ( github.com/go-redis/redis/v8 v8.11.5 + github.com/go-sprout/sprout v0.6.0-rc1 github.com/gorilla/mux v1.8.1 github.com/jmoiron/sqlx v1.3.5 github.com/knadh/koanf v1.5.0 @@ -17,13 +18,13 @@ require ( ) require ( + dario.cat/mergo v1.0.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/kr/text v0.2.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.19 // indirect github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect @@ -33,8 +34,10 @@ require ( github.com/prometheus/client_model v0.5.0 // indirect github.com/prometheus/common v0.45.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect + github.com/spf13/cast v1.6.0 // indirect github.com/spf13/pflag v1.0.5 // indirect golang.org/x/sys v0.15.0 // indirect + golang.org/x/text v0.16.0 // indirect google.golang.org/protobuf v1.33.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index a995bd4..cbfb38c 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,7 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -37,7 +39,6 @@ github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -52,6 +53,8 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7 github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= @@ -65,6 +68,8 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= +github.com/go-sprout/sprout v0.6.0-rc1 h1:J6boyYLwDGylYtMuKEvV0oA/gAqEprZZ6oc10bLkbW0= +github.com/go-sprout/sprout v0.6.0-rc1/go.mod h1:P6ETppcGn1BR0HZ8r+660aP2hJH7xiamIGiWjA+AE4o= 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-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -100,6 +105,7 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= @@ -166,6 +172,7 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -217,9 +224,12 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/npillmayer/nestext v0.1.3/go.mod h1:h2lrijH8jpicr25dFY+oAJLyzlya6jhnuG+zWp9L0Uk= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= +github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.7.0 h1:7utD74fnzVc/cpcyy8sjrlFr5vYpypUixARcHIMIGuI= @@ -258,6 +268,7 @@ github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3c github.com/rhnvrm/simples3 v0.6.1/go.mod h1:Y+3vYm2V7Y4VijFoJHHTrja6OgPrJ2cBti8dPGkC3sA= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0= github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= @@ -269,6 +280,8 @@ github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= +github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= @@ -277,6 +290,8 @@ github.com/streadway/amqp v1.1.0 h1:py12iX8XSyI7aN/3dUT8DFIDJazNJsVJdxNVEpnQTZM= github.com/streadway/amqp v1.1.0/go.mod h1:WYSrTEYHOXHd0nwFeUXAe2G2hRnQT+deZJJf88uS9Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -325,6 +340,7 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -380,7 +396,8 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -431,8 +448,10 @@ gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUy gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/internal/config/configuration.go b/internal/config/configuration.go index 6bd41cd..7c68121 100644 --- a/internal/config/configuration.go +++ b/internal/config/configuration.go @@ -15,8 +15,8 @@ import ( "github.com/mitchellh/mapstructure" "github.com/rs/zerolog/log" - "atomys.codes/webhooked/pkg/factory" - "atomys.codes/webhooked/pkg/storage" + "github.com/42atomys/webhooked/pkg/factory" + "github.com/42atomys/webhooked/pkg/storage" ) var ( diff --git a/internal/config/configuration_test.go b/internal/config/configuration_test.go index 7cad635..dc051c1 100644 --- a/internal/config/configuration_test.go +++ b/internal/config/configuration_test.go @@ -6,8 +6,8 @@ import ( "github.com/stretchr/testify/assert" - "atomys.codes/webhooked/internal/valuable" - "atomys.codes/webhooked/pkg/factory" + "github.com/42atomys/webhooked/internal/valuable" + "github.com/42atomys/webhooked/pkg/factory" ) func TestLoad(t *testing.T) { diff --git a/internal/config/structs.go b/internal/config/structs.go index e98c41e..d02e59e 100644 --- a/internal/config/structs.go +++ b/internal/config/structs.go @@ -1,8 +1,8 @@ package config import ( - "atomys.codes/webhooked/pkg/factory" - "atomys.codes/webhooked/pkg/storage" + "github.com/42atomys/webhooked/pkg/factory" + "github.com/42atomys/webhooked/pkg/storage" ) // Configuration is the struct contains all the configuration diff --git a/internal/server/middlewares.go b/internal/server/middlewares.go index 227da4c..39666fb 100644 --- a/internal/server/middlewares.go +++ b/internal/server/middlewares.go @@ -11,10 +11,10 @@ import ( "github.com/prometheus/client_golang/prometheus/promauto" "github.com/rs/zerolog/log" - "atomys.codes/webhooked/internal/config" + "github.com/42atomys/webhooked/internal/config" ) -//statusRecorder to record the status code from the ResponseWriter +// statusRecorder to record the status code from the ResponseWriter type statusRecorder struct { http.ResponseWriter statusCode int diff --git a/internal/server/middlewares_test.go b/internal/server/middlewares_test.go index a7a8840..3b92db7 100644 --- a/internal/server/middlewares_test.go +++ b/internal/server/middlewares_test.go @@ -8,7 +8,7 @@ import ( "github.com/prometheus/client_golang/prometheus/testutil" "github.com/stretchr/testify/suite" - "atomys.codes/webhooked/internal/config" + "github.com/42atomys/webhooked/internal/config" ) func init() { diff --git a/internal/server/serve.go b/internal/server/serve.go index 4370606..baacad4 100644 --- a/internal/server/serve.go +++ b/internal/server/serve.go @@ -8,8 +8,8 @@ import ( "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/rs/zerolog/log" - "atomys.codes/webhooked/internal/config" - v1alpha1 "atomys.codes/webhooked/internal/server/v1alpha1" + "github.com/42atomys/webhooked/internal/config" + v1alpha1 "github.com/42atomys/webhooked/internal/server/v1alpha1" ) // APIVersion is the interface for all supported API versions diff --git a/internal/server/v1alpha1/handlers.go b/internal/server/v1alpha1/handlers.go index aa0682e..3f4b44f 100644 --- a/internal/server/v1alpha1/handlers.go +++ b/internal/server/v1alpha1/handlers.go @@ -10,8 +10,8 @@ import ( "github.com/rs/zerolog" "github.com/rs/zerolog/log" - "atomys.codes/webhooked/internal/config" - "atomys.codes/webhooked/pkg/formatting" + "github.com/42atomys/webhooked/internal/config" + "github.com/42atomys/webhooked/pkg/formatting" ) // Server is the server instance for the v1alpha1 version diff --git a/internal/server/v1alpha1/handlers_test.go b/internal/server/v1alpha1/handlers_test.go index 1d435f9..089aed6 100644 --- a/internal/server/v1alpha1/handlers_test.go +++ b/internal/server/v1alpha1/handlers_test.go @@ -11,10 +11,10 @@ import ( "github.com/rs/zerolog/log" "github.com/stretchr/testify/assert" - "atomys.codes/webhooked/internal/config" - "atomys.codes/webhooked/internal/valuable" - "atomys.codes/webhooked/pkg/factory" - "atomys.codes/webhooked/pkg/storage" + "github.com/42atomys/webhooked/internal/config" + "github.com/42atomys/webhooked/internal/valuable" + "github.com/42atomys/webhooked/pkg/factory" + "github.com/42atomys/webhooked/pkg/storage" ) func TestNewServer(t *testing.T) { diff --git a/main.go b/main.go index a4c005c..aec18e6 100644 --- a/main.go +++ b/main.go @@ -27,7 +27,7 @@ import ( "github.com/rs/zerolog" "github.com/rs/zerolog/log" - "atomys.codes/webhooked/cmd" + "github.com/42atomys/webhooked/cmd" ) func init() { diff --git a/pkg/factory/f_compare_test.go b/pkg/factory/f_compare_test.go index 3487bd9..0545f51 100644 --- a/pkg/factory/f_compare_test.go +++ b/pkg/factory/f_compare_test.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/suite" - "atomys.codes/webhooked/internal/valuable" + "github.com/42atomys/webhooked/internal/valuable" ) type testSuiteFactoryCompare struct { diff --git a/pkg/factory/f_debug_test.go b/pkg/factory/f_debug_test.go index 5e698ba..8f82eb4 100644 --- a/pkg/factory/f_debug_test.go +++ b/pkg/factory/f_debug_test.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/suite" - "atomys.codes/webhooked/internal/valuable" + "github.com/42atomys/webhooked/internal/valuable" ) type testSuiteFactoryDebug struct { diff --git a/pkg/factory/f_generate_hmac_256_test.go b/pkg/factory/f_generate_hmac_256_test.go index dea20f0..8f53cb7 100644 --- a/pkg/factory/f_generate_hmac_256_test.go +++ b/pkg/factory/f_generate_hmac_256_test.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/suite" - "atomys.codes/webhooked/internal/valuable" + "github.com/42atomys/webhooked/internal/valuable" ) type testSuiteFactoryGenerateHMAC256 struct { diff --git a/pkg/factory/f_has_prefix_test.go b/pkg/factory/f_has_prefix_test.go index a9c79b8..80a2d77 100644 --- a/pkg/factory/f_has_prefix_test.go +++ b/pkg/factory/f_has_prefix_test.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/suite" - "atomys.codes/webhooked/internal/valuable" + "github.com/42atomys/webhooked/internal/valuable" ) type testSuiteFactoryHasPrefix struct { diff --git a/pkg/factory/f_has_suffix_test.go b/pkg/factory/f_has_suffix_test.go index 249a549..caef2da 100644 --- a/pkg/factory/f_has_suffix_test.go +++ b/pkg/factory/f_has_suffix_test.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/suite" - "atomys.codes/webhooked/internal/valuable" + "github.com/42atomys/webhooked/internal/valuable" ) type testSuiteFactoryHasSuffix struct { diff --git a/pkg/factory/f_header_test.go b/pkg/factory/f_header_test.go index 34692ac..0de6d15 100644 --- a/pkg/factory/f_header_test.go +++ b/pkg/factory/f_header_test.go @@ -7,7 +7,7 @@ import ( "github.com/stretchr/testify/suite" - "atomys.codes/webhooked/internal/valuable" + "github.com/42atomys/webhooked/internal/valuable" ) type testSuiteFactoryHeader struct { diff --git a/pkg/factory/factory.go b/pkg/factory/factory.go index 542a5fa..f1c462f 100644 --- a/pkg/factory/factory.go +++ b/pkg/factory/factory.go @@ -11,7 +11,7 @@ import ( "github.com/rs/zerolog/log" - "atomys.codes/webhooked/internal/valuable" + "github.com/42atomys/webhooked/internal/valuable" ) const ctxPipeline contextKey = "pipeline" diff --git a/pkg/factory/factory_test.go b/pkg/factory/factory_test.go index 922af35..70b249b 100644 --- a/pkg/factory/factory_test.go +++ b/pkg/factory/factory_test.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/suite" - "atomys.codes/webhooked/internal/valuable" + "github.com/42atomys/webhooked/internal/valuable" ) type fakeFactory struct{} diff --git a/pkg/factory/mapstructure_decode.go b/pkg/factory/mapstructure_decode.go index 6c27c2e..7820140 100644 --- a/pkg/factory/mapstructure_decode.go +++ b/pkg/factory/mapstructure_decode.go @@ -4,7 +4,7 @@ import ( "fmt" "reflect" - "atomys.codes/webhooked/internal/valuable" + "github.com/42atomys/webhooked/internal/valuable" ) // DecodeHook is a mapstructure.DecodeHook that serializes diff --git a/pkg/factory/structs.go b/pkg/factory/structs.go index aebad32..0b73581 100644 --- a/pkg/factory/structs.go +++ b/pkg/factory/structs.go @@ -5,7 +5,7 @@ import ( "reflect" "sync" - "atomys.codes/webhooked/internal/valuable" + "github.com/42atomys/webhooked/internal/valuable" ) // contextKey is used to define context key inside the factory package diff --git a/pkg/formatting/formatter.go b/pkg/formatting/formatter.go index 6bfe078..1d7bd38 100644 --- a/pkg/formatting/formatter.go +++ b/pkg/formatting/formatter.go @@ -7,13 +7,29 @@ import ( "net/http" "sync" "text/template" + + "github.com/go-sprout/sprout" + "github.com/go-sprout/sprout/registry/checksum" + "github.com/go-sprout/sprout/registry/conversion" + "github.com/go-sprout/sprout/registry/encoding" + "github.com/go-sprout/sprout/registry/env" + "github.com/go-sprout/sprout/registry/maps" + "github.com/go-sprout/sprout/registry/numeric" + "github.com/go-sprout/sprout/registry/random" + "github.com/go-sprout/sprout/registry/reflect" + "github.com/go-sprout/sprout/registry/regexp" + "github.com/go-sprout/sprout/registry/slices" + "github.com/go-sprout/sprout/registry/std" + "github.com/go-sprout/sprout/registry/strings" + "github.com/go-sprout/sprout/registry/time" ) type Formatter struct { tmplString string - mu sync.RWMutex // protect following field amd template parsing - data map[string]interface{} + mu sync.RWMutex // protect following field amd template parsing + data map[string]interface{} + fnHandler sprout.Handler // sprout handler for template functions } var ( @@ -27,26 +43,38 @@ var ( ErrNoTemplate = fmt.Errorf("no template defined") ) -// NewWithTemplate returns a new Formatter instance. It takes the template -// string as a parameter. The template string is the string that will be used -// to render the template. The data is the map of data that will be used to -// render the template. -// ! DEPRECATED: use New() and WithTemplate() instead -func NewWithTemplate(tmplString string) *Formatter { - return &Formatter{ - tmplString: tmplString, - data: make(map[string]interface{}), - mu: sync.RWMutex{}, - } +// Global buffer pool to reduce buffer allocations +var bufPool = sync.Pool{ + New: func() interface{} { + return new(bytes.Buffer) + }, } // New returns a new Formatter instance. It takes no parameters. The template // string must be set using the WithTemplate method. The data is the map of data // that will be used to render the template. func New() *Formatter { + fh := sprout.New() + _ = fh.AddRegistries( + checksum.NewRegistry(), + conversion.NewRegistry(), + encoding.NewRegistry(), + env.NewRegistry(), + maps.NewRegistry(), + numeric.NewRegistry(), + random.NewRegistry(), + reflect.NewRegistry(), + regexp.NewRegistry(), + slices.NewRegistry(), + std.NewRegistry(), + strings.NewRegistry(), + time.NewRegistry(), + ) + return &Formatter{ - data: make(map[string]interface{}), - mu: sync.RWMutex{}, + data: make(map[string]interface{}), + mu: sync.RWMutex{}, + fnHandler: fh, } } @@ -93,21 +121,21 @@ func (d *Formatter) Render() (string, error) { return "", ErrNoTemplate } - t := template.New("formattingTmpl").Funcs(funcMap()) + t := template.New("formattingTmpl").Funcs(d.fnHandler.Build()) t, err := t.Parse(d.tmplString) if err != nil { return "", fmt.Errorf("error in your template: %s", err.Error()) } - buf := new(bytes.Buffer) + // Reuse buffer to reduce allocations + buf := bufPool.Get().(*bytes.Buffer) + buf.Reset() + defer bufPool.Put(buf) + if err := t.Execute(buf, d.data); err != nil { return "", fmt.Errorf("error while filling your template: %s", err.Error()) } - if buf.String() == "" { - return "", fmt.Errorf("template cannot be rendered, check your template") - } - return buf.String(), nil } diff --git a/pkg/formatting/formatter_test.go b/pkg/formatting/formatter_test.go index af41fbc..7c1d7c7 100644 --- a/pkg/formatting/formatter_test.go +++ b/pkg/formatting/formatter_test.go @@ -22,11 +22,6 @@ func TestNewWithTemplate(t *testing.T) { assert.NotNil(tmpl) assert.Equal("{{ .Payload }}", tmpl.tmplString) assert.Equal(0, len(tmpl.data)) - - tmpl = NewWithTemplate("{{ .Payload }}") - assert.NotNil(tmpl) - assert.Equal("{{ .Payload }}", tmpl.tmplString) - assert.Equal(0, len(tmpl.data)) } func Test_WithData(t *testing.T) { @@ -91,8 +86,8 @@ func Test_Render(t *testing.T) { { "customData": {{ toJson .CustomData }}, "metadata": { - "testID": "{{ .Request.Header | getHeader "X-Test" }}", - "deliveryID": "{{ .Request.Header | getHeader "X-Delivery" | default "unknown" }}" + "testID": "{{ .Request.Header.Get "X-Test" }}", + "deliveryID": "{{ .Request.Header.Get "X-Delivery" | default "unknown" }}" }, {{ with $payload := fromJson .Payload }} "payload": { @@ -142,13 +137,14 @@ func Test_Render(t *testing.T) { assert.Equal("", str) // Test with template with invalid format sended to a function - tmpl = New().WithTemplate(`{{ lookup "test" .Payload }}`).WithPayload([]byte(`{"test": "test"}`)) + templateStringToTest := `{{ .Payload | dig "test" }}` + tmpl = New().WithTemplate(templateStringToTest).WithPayload([]byte(`{"test": "test"}`)) assert.NotNil(tmpl) - assert.Equal(`{{ lookup "test" .Payload }}`, tmpl.tmplString) + assert.Equal(templateStringToTest, tmpl.tmplString) str, err = tmpl.Render() assert.Error(err) - assert.Contains(err.Error(), "template cannot be rendered, check your template") + assert.Contains(err.Error(), "last argument must be a map[string]any") assert.Equal("", str) } diff --git a/pkg/formatting/functions.go b/pkg/formatting/functions.go deleted file mode 100644 index abc05ab..0000000 --- a/pkg/formatting/functions.go +++ /dev/null @@ -1,537 +0,0 @@ -package formatting - -import ( - "encoding/json" - "fmt" - "math" - "net/http" - "reflect" - "strconv" - "strings" - "text/template" - "time" - - "github.com/rs/zerolog/log" -) - -// funcMap is the map of functions that can be used in templates. -// The key is the name of the function and the value is the function itself. -// This is required for the template.New() function to parse the function. -func funcMap() template.FuncMap { - return template.FuncMap{ - // Core functions - "default": dft, - "empty": empty, - "coalesce": coalesce, - "toJson": toJson, - "toPrettyJson": toPrettyJson, - "fromJson": fromJson, - "ternary": ternary, - "lookup": lookup, - - // Headers manipulation functions - "getHeader": getHeader, - - // Time manipulation functions - "formatTime": formatTime, - "parseTime": parseTime, - - // Casting functions - "toString": toString, - "toInt": toInt, - "toFloat": toFloat, - "toBool": toBool, - - // Is functions - "isNumber": isNumber, - "isString": isString, - "isBool": isBool, - "isNull": isNull, - - // Math functions - "add": mathAdd, - "sub": mathSub, - "mul": mathMul, - "div": mathDiv, - "mod": mathMod, - "pow": mathPow, - "max": mathMax, - "min": mathMin, - "sqrt": mathSqrt, - } -} - -// dft returns the default value if the given value is empty. -// If the given value is not empty, it is returned as is. -func dft(dft interface{}, given ...interface{}) interface{} { - - if empty(given) || empty(given[0]) { - return dft - } - return given[0] -} - -// empty returns true if the given value is empty. -// It supports any type. -func empty(given interface{}) bool { - g := reflect.ValueOf(given) - if !g.IsValid() { - return true - } - - switch g.Kind() { - default: - return g.IsNil() - case reflect.Array, reflect.Slice, reflect.Map, reflect.String: - return g.Len() == 0 - case reflect.Bool: - return !g.IsValid() - case reflect.Complex64, reflect.Complex128: - return g.Complex() == 0 - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return g.Int() == 0 - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return g.Uint() == 0 - case reflect.Float32, reflect.Float64: - return g.Float() == 0 - case reflect.Struct: - return g.NumField() == 0 - } -} - -// coalesce returns the first value not empty in the given list. -// If all values are empty, it returns nil. -func coalesce(v ...interface{}) interface{} { - for _, val := range v { - if !isNull(val) { - return val - } - } - return nil -} - -// toJson returns the given value as a JSON string. -// If the given value is nil, it returns an empty string. -func toJson(v interface{}) string { - output, err := json.Marshal(v) - if err != nil { - log.Error().Err(err).Msg("Failed to marshal to JSON") - } - return string(output) -} - -// toPrettyJson returns the given value as a pretty JSON string indented with -// 2 spaces. If the given value is nil, it returns an empty string. -func toPrettyJson(v interface{}) string { - output, err := json.MarshalIndent(v, "", " ") - if err != nil { - log.Error().Err(err).Msg("Failed to marshal to JSON") - } - return string(output) -} - -// fromJson returns the given JSON string as a map[string]interface{}. -// If the given value is nil, it returns an empty map. -func fromJson(v interface{}) map[string]interface{} { - if isNull(v) { - return map[string]interface{}{} - } - - if v, ok := v.(map[string]interface{}); ok { - return v - } - - var output = map[string]interface{}{} - var err error - if bytes, ok := v.([]byte); ok { - err = json.Unmarshal(bytes, &output) - } else { - err = json.Unmarshal([]byte(v.(string)), &output) - } - if err != nil { - log.Error().Err(err).Msg("Failed to unmarshal JSON") - } - return output -} - -// ternary returns `isTrue` if `condition` is true, otherwise returns `isFalse`. -func ternary(isTrue interface{}, isFalse interface{}, condition bool) interface{} { - if condition { - return isTrue - } - - return isFalse -} - -// lookup recursively navigates through nested data structures based on a dot-separated path. -func lookup(path string, data interface{}) interface{} { - keys := strings.Split(path, ".") - - if path == "" { - return data - } - - // Navigate through the data for each key. - current := data - for _, key := range keys { - switch val := current.(type) { - case map[string]interface{}: - // If the current value is a map and the key exists, proceed to the next level. - if next, ok := val[key]; ok { - current = next - } else { - // Key not found - log.Logger.Warn().Str("path", path).Msg("Key are not found on the object") - return nil - } - default: - // If the current type is not a map or we've reached a non-navigable point - return nil - } - } - - // If the final value is a string, return it; otherwise - return current -} - -// getHeader returns the value of the given header. If the header is not found, -// it returns an empty string. -func getHeader(name string, headers *http.Header) string { - if headers == nil { - log.Error().Msg("headers are nil. Returning empty string") - return "" - } - return headers.Get(name) -} - -// formatTime returns the given time formatted with the given layout. -// If the given time is invalid, it returns an empty string. -func formatTime(t interface{}, fromLayout, tolayout string) string { - if isNull(t) { - log.Error().Msg("time is nil. Returning empty string") - return "" - } - - if tolayout == "" { - tolayout = time.RFC3339 - } - - parsedTime := parseTime(t, fromLayout) - if parsedTime.IsZero() { - log.Error().Msgf("Failed to parse time [%v] with layout [%s]", t, fromLayout) - return "" - } - - return parsedTime.Format(tolayout) -} - -// parseTime returns the given time parsed with the given layout. -// If the given time is invalid, it returns an time.Time{}. -func parseTime(t interface{}, layout string) time.Time { - if isNull(t) { - return time.Time{} - } - - var parsedTime time.Time - var err error - switch reflect.ValueOf(t).Kind() { - default: - t, ok := t.(time.Time) - if ok { - parsedTime = t - } else { - parsedTime = time.Time{} - } - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - parsedTime = time.Unix(int64(toInt(t)), 0) - case reflect.String: - parsedTime, err = time.Parse(layout, toString(t)) - } - - if err != nil { - log.Error().Err(err).Msg("Failed to parse time") - return time.Time{} - } - - return parsedTime -} - -// isNumber returns true if the given value is a number, otherwise returns false. -func isNumber(n interface{}) bool { - if isNull(n) { - return false - } - - g := reflect.ValueOf(n) - switch g.Kind() { - default: - return false - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return true - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - return true - case reflect.Float32, reflect.Float64: - return !math.IsNaN(g.Float()) && !(math.IsInf(g.Float(), 1) || math.IsInf(g.Float(), -1)) - case reflect.Uintptr: - return false - } -} - -// isString returns true if the given value is a string, otherwise returns false. -func isString(n interface{}) bool { - if isNull(n) { - return false - } - - switch n.(type) { - default: - if _, ok := n.(fmt.Stringer); ok { - return true - } - return false - case string, []byte: - return true - } -} - -// isBool returns true if the given value is a bool, otherwise returns false. -func isBool(n interface{}) bool { - if isNull(n) { - return false - } - - switch n.(type) { - default: - return false - case string, []byte, fmt.Stringer: - _, err := strconv.ParseBool(toString(n)) - return err == nil - case bool: - return true - } -} - -// isNull returns true if the given value is nil or empty, otherwise returns false. -func isNull(n interface{}) bool { - if n == nil || empty(n) { - return true - } - - return false -} - -// toString returns the given value as a string. -// If the given value is nil, it returns an empty string. -func toString(n interface{}) string { - if isNull(n) { - return "" - } - - switch n := n.(type) { - default: - g := reflect.ValueOf(n) - switch g.Kind() { - default: - return "" - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return strconv.FormatInt(g.Int(), 10) - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - return strconv.FormatUint(g.Uint(), 10) - case reflect.Float32, reflect.Float64: - return strconv.FormatFloat(g.Float(), 'f', -1, 64) - case reflect.Bool: - return strconv.FormatBool(g.Bool()) - } - case string, []byte: - return fmt.Sprintf("%s", n) - case fmt.Stringer: - return n.String() - } -} - -// toInt returns the given value as an int. -// If the given value is nil, it returns 0. -func toInt(n interface{}) int { - if isNull(n) { - return 0 - } - - i, err := strconv.Atoi(toString(n)) - if err != nil { - log.Error().Err(err).Msgf("Failed to convert [%v] to int", n) - return 0 - } - - return i -} - -// toFloat returns the given value as a float. -// If the given value is nil, it returns 0. -func toFloat(n interface{}) float64 { - if isNull(n) { - return 0 - } - - f, err := strconv.ParseFloat(toString(n), 64) - if err != nil { - log.Error().Err(err).Msgf("Failed to convert [%v] to float", n) - return 0 - } - - return f -} - -// toBool returns the given value as a bool. -// If the given value is nil, it returns false. -func toBool(n interface{}) bool { - if isNull(n) { - return false - } - - b, err := strconv.ParseBool(toString(n)) - if err != nil { - log.Error().Err(err).Msgf("Failed to convert [%v] to bool", n) - return false - } - - return b -} - -// mathAdd returns the sum of the given numbers. -// If any of the given numbers is not a number, it returns 0. -func mathAdd(numbers ...interface{}) float64 { - var sum float64 - for _, n := range numbers { - sum += toFloat(n) - } - return sum -} - -// mathSub returns the difference of the given numbers. -// If any of the given numbers is not a number, it returns 0. -func mathSub(numbers ...interface{}) float64 { - var diff float64 - for i, n := range numbers { - f := toFloat(n) - - if i == 0 { - diff = f - continue - } - - diff -= f - } - return diff -} - -// mathMul returns the product of the given numbers. -// If any of the given numbers is not a number, it returns 0. -func mathMul(numbers ...interface{}) float64 { - var product float64 - for _, n := range numbers { - p := toFloat(n) - - if product == 0 { - product = p - continue - } - - product *= p - } - return product -} - -// mathDiv returns the quotient of the given numbers. -// If any of the given numbers is not a number, it returns 0. -func mathDiv(numbers ...interface{}) float64 { - var quotient float64 - for i, n := range numbers { - d := toFloat(n) - - if i == 0 { - quotient = d - continue - } - - quotient /= d - } - return quotient -} - -// mathMod returns the remainder of the given numbers. -// If any of the given numbers is not a number, it returns 0. -func mathMod(numbers ...interface{}) float64 { - var remainder float64 - for i, n := range numbers { - m := toFloat(n) - - if i == 0 { - remainder = m - continue - } - - remainder = math.Mod(remainder, m) - } - return remainder -} - -// mathPow returns the power of the given numbers. -// If any of the given numbers is not a number, it returns 0. -func mathPow(numbers ...interface{}) float64 { - var power float64 - for i, n := range numbers { - p := toFloat(n) - - if i == 0 { - power = p - continue - } - - power = math.Pow(power, p) - } - return power -} - -// mathSqrt returns the square root of the given number. -// If the given number is not a number, it returns 0. -func mathSqrt(number interface{}) float64 { - return math.Sqrt(toFloat(number)) -} - -// mathMin returns the minimum of the given numbers. -// If any of the given numbers is not a number, it returns 0. -func mathMin(numbers ...interface{}) float64 { - var min float64 - for i, n := range numbers { - num := toFloat(n) - - if i == 0 { - min = num - continue - } - - if num < min { - min = num - } - } - return min -} - -// mathMax returns the maximum of the given numbers. -// If any of the given numbers is not a number, it returns 0. -func mathMax(numbers ...interface{}) float64 { - var max float64 - for i, n := range numbers { - num := toFloat(n) - - if i == 0 { - max = num - continue - } - - if num > max { - max = num - } - } - return max -} diff --git a/pkg/formatting/functions_is_to_test.go b/pkg/formatting/functions_is_to_test.go deleted file mode 100644 index badb038..0000000 --- a/pkg/formatting/functions_is_to_test.go +++ /dev/null @@ -1,211 +0,0 @@ -package formatting - -import ( - "bytes" - "fmt" - "math" - "net/http/httptest" - "testing" - "time" - - "github.com/stretchr/testify/assert" -) - -func TestIsNumber(t *testing.T) { - // Test with nil value - assert.False(t, isNumber(nil)) - - // Test with invalid value - assert.False(t, isNumber(math.NaN())) - assert.False(t, isNumber(math.Inf(1))) - assert.False(t, isNumber(math.Inf(-1))) - assert.False(t, isNumber(complex(1, 2))) - - // Test with integer values - assert.True(t, isNumber(int(42))) - assert.True(t, isNumber(int8(42))) - assert.True(t, isNumber(int16(42))) - assert.True(t, isNumber(int32(42))) - assert.True(t, isNumber(int64(42))) - assert.True(t, isNumber(uint(42))) - assert.True(t, isNumber(uint8(42))) - assert.True(t, isNumber(uint16(42))) - assert.True(t, isNumber(uint32(42))) - assert.True(t, isNumber(uint64(42))) - assert.False(t, isNumber(uintptr(42))) - - // Test with floating-point values - assert.True(t, isNumber(float32(3.14))) - assert.True(t, isNumber(float64(3.14))) - -} - -type customStringer struct { - str string -} - -func (s customStringer) String() string { - return s.str -} - -func TestIsString(t *testing.T) { - // Test with nil value - assert.False(t, isString(nil)) - - // Test with empty value - assert.False(t, isString("")) - assert.False(t, isString([]byte{})) - assert.False(t, isString(struct{}{})) - - // Test with non-empty value - assert.True(t, isString("test")) - assert.True(t, isString([]byte("test"))) - assert.True(t, isString(fmt.Sprintf("%v", 42))) - assert.True(t, isString(customStringer{})) - assert.True(t, isString(time.Now())) - assert.False(t, isString(42)) - assert.False(t, isString(3.14)) - assert.False(t, isString([]int{1, 2, 3})) - assert.False(t, isString(httptest.NewRecorder())) - assert.False(t, isString(struct{ String string }{String: "test"})) - assert.False(t, isString(map[string]string{"foo": "bar"})) -} - -func TestIsBool(t *testing.T) { - // Test with a bool value - assert.True(t, isBool(true)) - assert.True(t, isBool(false)) - - // Test with a string value - assert.True(t, isBool("true")) - assert.True(t, isBool("false")) - assert.True(t, isBool("TRUE")) - assert.True(t, isBool("FALSE")) - assert.False(t, isBool("foo")) - assert.False(t, isBool("")) - - // Test with a []byte value - assert.True(t, isBool([]byte("true"))) - assert.True(t, isBool([]byte("false"))) - assert.True(t, isBool([]byte("TRUE"))) - assert.True(t, isBool([]byte("FALSE"))) - assert.False(t, isBool([]byte("foo"))) - assert.False(t, isBool([]byte(""))) - - // Test with a fmt.Stringer value - assert.True(t, isBool(fmt.Sprintf("%v", true))) - assert.True(t, isBool(fmt.Sprintf("%v", false))) - assert.False(t, isBool(fmt.Sprintf("%v", 42))) - - // Test with other types - assert.False(t, isBool(nil)) - assert.False(t, isBool(42)) - assert.False(t, isBool(3.14)) - assert.False(t, isBool([]int{1, 2, 3})) - assert.False(t, isBool(map[string]string{"foo": "bar"})) - assert.False(t, isBool(struct{ Foo string }{Foo: "bar"})) -} - -func TestIsNull(t *testing.T) { - // Test with nil value - assert.True(t, isNull(nil)) - - // Test with empty value - assert.True(t, isNull("")) - assert.True(t, isNull([]int{})) - assert.True(t, isNull(map[string]string{})) - assert.True(t, isNull(struct{}{})) - - // Test with non-empty value - assert.False(t, isNull("test")) - assert.False(t, isNull(42)) - assert.False(t, isNull(3.14)) - assert.False(t, isNull([]int{1, 2, 3})) - assert.False(t, isNull(map[string]string{"foo": "bar"})) - assert.False(t, isNull(struct{ Foo string }{Foo: "bar"})) - assert.False(t, isNull(time.Now())) - assert.False(t, isNull(httptest.NewRecorder())) -} - -func TestToString(t *testing.T) { - // Test with nil value - assert.Equal(t, "", toString(nil)) - - // Test with invalid value - buf := new(bytes.Buffer) - assert.Equal(t, "", toString(buf)) - - // Test with string value - assert.Equal(t, "test", toString("test")) - assert.Equal(t, "test", toString([]byte("test"))) - assert.Equal(t, "42", toString(fmt.Sprintf("%v", 42))) - assert.Equal(t, "", toString(struct{ String string }{String: "test"})) - assert.Equal(t, "", toString(struct{}{})) - - // Test with fmt.Stringer value - assert.Equal(t, "test", toString(customStringer{str: "test"})) - assert.Equal(t, "", toString(customStringer{})) - - // Test with other types - assert.Equal(t, "42", toString(42)) - assert.Equal(t, "42", toString(uint(42))) - assert.Equal(t, "3.14", toString(3.14)) - assert.Equal(t, "true", toString(true)) - assert.Equal(t, "false", toString(false)) - assert.Equal(t, "2009-11-10 23:00:00 +0000 UTC", toString(time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC))) -} - -func TestToInt(t *testing.T) { - // Test with nil value - assert.Equal(t, 0, toInt(nil)) - - // Test with invalid value - assert.Equal(t, 0, toInt("test")) - assert.Equal(t, 0, toInt([]byte("test"))) - assert.Equal(t, 0, toInt(struct{ Int int }{Int: 42})) - assert.Equal(t, 0, toInt(new(bytes.Buffer))) - - // Test with valid value - assert.Equal(t, 42, toInt(42)) - assert.Equal(t, -42, toInt("-42")) - assert.Equal(t, 0, toInt("0")) - assert.Equal(t, 123456789, toInt("123456789")) -} - -func TestToFloat(t *testing.T) { - // Test with nil value - assert.Equal(t, 0.0, toFloat(nil)) - - // Test with invalid value - assert.Equal(t, 0.0, toFloat("test")) - assert.Equal(t, 0.0, toFloat([]byte("test"))) - assert.Equal(t, 0.0, toFloat(struct{ Float float64 }{Float: 42})) - assert.Equal(t, 0.0, toFloat(new(bytes.Buffer))) - - // Test with valid value - assert.Equal(t, 42.0, toFloat(42)) - assert.Equal(t, -42.0, toFloat("-42")) - assert.Equal(t, 0.0, toFloat("0")) - assert.Equal(t, 123456789.0, toFloat("123456789")) - assert.Equal(t, 3.14, toFloat(3.14)) - assert.Equal(t, 2.71828, toFloat("2.71828")) -} - -func TestToBool(t *testing.T) { - // Test with nil value - assert.False(t, toBool(nil)) - - // Test with invalid value - assert.False(t, toBool("test")) - assert.False(t, toBool([]byte("test"))) - assert.False(t, toBool(struct{ Bool bool }{Bool: true})) - assert.False(t, toBool(new(bytes.Buffer))) - - // Test with valid value - assert.True(t, toBool(true)) - assert.True(t, toBool("true")) - assert.True(t, toBool("1")) - assert.False(t, toBool(false)) - assert.False(t, toBool("false")) - assert.False(t, toBool("0")) -} diff --git a/pkg/formatting/functions_math_test.go b/pkg/formatting/functions_math_test.go deleted file mode 100644 index 3942077..0000000 --- a/pkg/formatting/functions_math_test.go +++ /dev/null @@ -1,182 +0,0 @@ -package formatting - -import ( - "bytes" - "math" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestMathAdd(t *testing.T) { - // Test with nil value - assert.Equal(t, 0.0, mathAdd(nil)) - - // Test with invalid value - assert.Equal(t, 0.0, mathAdd("test")) - assert.Equal(t, 0.0, mathAdd([]byte("test"))) - assert.Equal(t, 0.0, mathAdd(struct{ Float float64 }{Float: 42})) - assert.Equal(t, 0.0, mathAdd(new(bytes.Buffer))) - - // Test with valid value - assert.Equal(t, 42.0, mathAdd(42)) - assert.Equal(t, 0.0, mathAdd()) - assert.Equal(t, 6.0, mathAdd(1, 2, 3)) - assert.Equal(t, 10.0, mathAdd(1, 2, "3", 4)) - assert.Equal(t, 3.14, mathAdd(3.14)) - assert.Equal(t, 5.0, mathAdd(2, 3.0)) -} - -func TestMathSub(t *testing.T) { - // Test with nil value - assert.Equal(t, 0.0, mathSub(nil)) - - // Test with invalid value - assert.Equal(t, 0.0, mathSub("test")) - assert.Equal(t, 0.0, mathSub([]byte("test"))) - assert.Equal(t, 0.0, mathSub(struct{ Float float64 }{Float: 42})) - assert.Equal(t, 0.0, mathSub(new(bytes.Buffer))) - - // Test with valid value - assert.Equal(t, 42.0, mathSub(42)) - assert.Equal(t, 0.0, mathSub()) - assert.Equal(t, -4.0, mathSub(1, 2, 3)) - assert.Equal(t, -8.0, mathSub(1, 2, "3", 4)) - assert.Equal(t, 3.14, mathSub(3.14)) - assert.Equal(t, -1.0, mathSub(2, 3.0)) -} - -func TestMathMul(t *testing.T) { - // Test with nil value - assert.Equal(t, 0.0, mathMul(nil)) - - // Test with invalid value - assert.Equal(t, 0.0, mathMul("test")) - assert.Equal(t, 0.0, mathMul([]byte("test"))) - assert.Equal(t, 0.0, mathMul(struct{ Float float64 }{Float: 42})) - assert.Equal(t, 0.0, mathMul(new(bytes.Buffer))) - assert.Equal(t, 0.0, mathMul()) - - // Test with valid value - assert.Equal(t, 42.0, mathMul(42)) - assert.Equal(t, 6.0, mathMul(1, 2, 3)) - assert.Equal(t, 24.0, mathMul(1, 2, "3", 4)) - assert.Equal(t, 3.14, mathMul(3.14)) - assert.Equal(t, 6.0, mathMul(2, 3.0)) -} - -func TestMathDiv(t *testing.T) { - // Test with nil value - assert.Equal(t, 0.0, mathDiv(nil)) - - // Test with invalid value - assert.Equal(t, 0.0, mathDiv("test")) - assert.Equal(t, 0.0, mathDiv([]byte("test"))) - assert.Equal(t, 0.0, mathDiv(struct{ Float float64 }{Float: 42})) - assert.Equal(t, 0.0, mathDiv(new(bytes.Buffer))) - - // Test with valid value - assert.Equal(t, 42.0, mathDiv(42)) - assert.Equal(t, 0.0, mathDiv()) - assert.Equal(t, 0.16666666666666666, mathDiv(1, 2, 3)) - assert.Equal(t, 0.041666666666666664, mathDiv(1, 2, "3", 4)) - assert.Equal(t, 3.14, mathDiv(3.14)) - assert.Equal(t, 0.6666666666666666, mathDiv(2, 3.0)) -} - -func TestMathMod(t *testing.T) { - // Test with nil value - assert.Equal(t, 0.0, mathMod(nil)) - - // Test with invalid value - assert.Equal(t, 0.0, mathMod("test")) - assert.Equal(t, 0.0, mathMod([]byte("test"))) - assert.Equal(t, 0.0, mathMod(struct{ Float float64 }{Float: 42})) - assert.Equal(t, 0.0, mathMod(new(bytes.Buffer))) - - // Test with valid value - assert.Equal(t, 42.0, mathMod(42)) - assert.Equal(t, 0.0, mathMod()) - assert.Equal(t, 1.0, mathMod(10, 3, 2)) - assert.Equal(t, 0.0, mathMod(10, 2)) - assert.Equal(t, 1.0, mathMod(10, 3)) - assert.Equal(t, 0.0, mathMod(10, 5)) - assert.Equal(t, 0.5, mathMod(10.5, 2)) -} - -func TestMathPow(t *testing.T) { - // Test with nil value - assert.Equal(t, 0.0, mathPow(nil)) - - // Test with invalid value - assert.Equal(t, 0.0, mathPow("test")) - assert.Equal(t, 0.0, mathPow([]byte("test"))) - assert.Equal(t, 0.0, mathPow(struct{ Float float64 }{Float: 42})) - assert.Equal(t, 0.0, mathPow(new(bytes.Buffer))) - assert.Equal(t, 0.0, mathPow()) - - // Test with valid value - assert.Equal(t, 2.0, mathPow(2)) - assert.Equal(t, 8.0, mathPow(2, 3)) - assert.Equal(t, 64.0, mathPow(2, 3, 2)) - assert.Equal(t, 1.0, mathPow(2, 0)) - assert.Equal(t, 0.25, mathPow(2, -2)) - assert.Equal(t, 27.0, mathPow(3, "3")) - assert.Equal(t, 4.0, mathPow(2, 2.0)) -} - -func TestMathSqrt(t *testing.T) { - // Test with nil value - assert.Equal(t, 0.0, mathSqrt(nil)) - - // Test with invalid value - assert.Equal(t, 0.0, mathSqrt("test")) - assert.Equal(t, 0.0, mathSqrt([]byte("test"))) - assert.Equal(t, 0.0, mathSqrt(struct{ Float float64 }{Float: 42})) - assert.Equal(t, 0.0, mathSqrt(new(bytes.Buffer))) - - // Test with valid value - assert.Equal(t, 2.0, mathSqrt(4)) - assert.Equal(t, 3.0, mathSqrt(9)) - assert.Equal(t, 0.0, mathSqrt(0)) - assert.Equal(t, math.Sqrt(2), mathSqrt(2)) - assert.Equal(t, math.Sqrt(0.5), mathSqrt(0.5)) -} - -func TestMathMin(t *testing.T) { - // Test with nil value - assert.Equal(t, 0.0, mathMin(nil)) - - // Test with invalid value - assert.Equal(t, 0.0, mathMin("test")) - assert.Equal(t, 0.0, mathMin([]byte("test"))) - assert.Equal(t, 0.0, mathMin(struct{ Float float64 }{Float: 42})) - assert.Equal(t, 0.0, mathMin(new(bytes.Buffer))) - - // Test with valid value - assert.Equal(t, 1.0, mathMin(1)) - assert.Equal(t, 2.0, mathMin(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)) - assert.Equal(t, -1.0, mathMin(-1, 0, 1)) - assert.Equal(t, 0.0, mathMin(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) - assert.Equal(t, 0.5, mathMin(1, 0.5, 2)) - assert.Equal(t, -2.0, mathMin(2, -2, 0)) -} - -func TestMathMax(t *testing.T) { - // Test with nil value - assert.Equal(t, 0.0, mathMax(nil)) - - // Test with invalid value - assert.Equal(t, 0.0, mathMax("test")) - assert.Equal(t, 0.0, mathMax([]byte("test"))) - assert.Equal(t, 0.0, mathMax(struct{ Float float64 }{Float: 42})) - assert.Equal(t, 0.0, mathMax(new(bytes.Buffer))) - - // Test with valid value - assert.Equal(t, 1.0, mathMax(1)) - assert.Equal(t, 12.0, mathMax(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)) - assert.Equal(t, 1.0, mathMax(-1, 0, 1)) - assert.Equal(t, 0.0, mathMax(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) - assert.Equal(t, 2.0, mathMax(1, 0.5, 2)) - assert.Equal(t, 2.0, mathMax(2, -2, 0)) -} diff --git a/pkg/formatting/functions_test.go b/pkg/formatting/functions_test.go deleted file mode 100644 index 46fb8bb..0000000 --- a/pkg/formatting/functions_test.go +++ /dev/null @@ -1,226 +0,0 @@ -package formatting - -import ( - "net/http/httptest" - "testing" - "time" - - "github.com/stretchr/testify/assert" -) - -func Test_funcMap(t *testing.T) { - assert := assert.New(t) - - funcMap := funcMap() - assert.Contains(funcMap, "default") - assert.NotContains(funcMap, "dft") - assert.Contains(funcMap, "empty") - assert.Contains(funcMap, "coalesce") - assert.Contains(funcMap, "toJson") - assert.Contains(funcMap, "toPrettyJson") - assert.Contains(funcMap, "ternary") - assert.Contains(funcMap, "getHeader") -} - -func Test_dft(t *testing.T) { - assert := assert.New(t) - - assert.Equal("test", dft("default", "test")) - assert.Equal("default", dft("default", nil)) - assert.Equal("default", dft("default", "")) -} - -func Test_empty(t *testing.T) { - assert := assert.New(t) - - assert.True(empty("")) - assert.True(empty(nil)) - assert.False(empty("test")) - assert.False(empty(true)) - assert.False(empty(false)) - assert.True(empty(0 + 0i)) - assert.False(empty(2 + 4i)) - assert.True(empty([]int{})) - assert.False(empty([]int{1})) - assert.True(empty(map[string]string{})) - assert.False(empty(map[string]string{"test": "test"})) - assert.True(empty(map[string]interface{}{})) - assert.False(empty(map[string]interface{}{"test": "test"})) - assert.True(empty(0)) - assert.False(empty(-1)) - assert.False(empty(1)) - assert.True(empty(uint32(0))) - assert.False(empty(uint32(1))) - assert.True(empty(float64(0.0))) - assert.False(empty(float64(1.0))) - assert.True(empty(struct{}{})) - assert.False(empty(struct{ Test string }{Test: "test"})) - - ptr := &struct{ Test string }{Test: "test"} - assert.False(empty(ptr)) -} - -func Test_coalesce(t *testing.T) { - assert := assert.New(t) - - assert.Equal("test", coalesce("test", "default")) - assert.Equal("default", coalesce("", "default")) - assert.Equal("default", coalesce(nil, "default")) - assert.Equal(nil, coalesce(nil, nil)) -} - -func Test_toJson(t *testing.T) { - assert := assert.New(t) - - assert.Equal("{\"test\":\"test\"}", toJson(map[string]string{"test": "test"})) - assert.Equal("{\"test\":\"test\"}", toJson(map[string]interface{}{"test": "test"})) - assert.Equal("null", toJson(nil)) - assert.Equal("", toJson(map[string]interface{}{"test": func() {}})) -} - -func Test_toPrettyJson(t *testing.T) { - assert := assert.New(t) - - assert.Equal("{\n \"test\": \"test\"\n}", toPrettyJson(map[string]string{"test": "test"})) - assert.Equal("{\n \"test\": \"test\"\n}", toPrettyJson(map[string]interface{}{"test": "test"})) - assert.Equal("null", toPrettyJson(nil)) - assert.Equal("", toPrettyJson(map[string]interface{}{"test": func() {}})) -} - -func Test_fromJson(t *testing.T) { - assert := assert.New(t) - - assert.Equal(map[string]interface{}{"test": "test"}, fromJson("{\"test\":\"test\"}")) - assert.Equal(map[string]interface{}{"test": map[string]interface{}{"foo": true}}, fromJson("{\"test\":{\"foo\":true}}")) - assert.Equal(map[string]interface{}{}, fromJson(nil)) - assert.Equal(map[string]interface{}{"test": 1}, fromJson(map[string]interface{}{"test": 1})) - assert.Equal(map[string]interface{}{}, fromJson("")) - assert.Equal(map[string]interface{}{"test": "test"}, fromJson([]byte("{\"test\":\"test\"}"))) - assert.Equal(map[string]interface{}{}, fromJson([]byte("\\\\"))) - - var result = fromJson("{\"test\":\"test\"}") - assert.Equal(result["test"], "test") -} - -func Test_ternary(t *testing.T) { - assert := assert.New(t) - - header := httptest.NewRecorder().Header() - - header.Set("X-Test", "test") - assert.Equal("test", getHeader("X-Test", &header)) - assert.Equal("", getHeader("X-Undefined", &header)) - assert.Equal("", getHeader("", &header)) - assert.Equal("", getHeader("", nil)) -} - -func TestLookup(t *testing.T) { - // Initialize the assert helper - assert := assert.New(t) - - // Example of nested data structure for testing - testData := map[string]interface{}{ - "user": map[string]interface{}{ - "details": map[string]interface{}{ - "name": "John Doe", - "age": 30, - }, - "email": "john.doe@example.com", - }, - "empty": map[string]interface{}{}, - } - - // Test cases - tests := []struct { - path string - data interface{} - expected interface{} - }{ - // Test successful lookups - {"user.details.name", testData, "John Doe"}, - {"user.email", testData, "john.doe@example.com"}, - // Test unsuccessful lookups - {"user.details.phone", testData, nil}, - {"user.location.city", testData, nil}, - // Test edge cases - {"", testData, testData}, - {"user..name", testData, nil}, - {"nonexistent", testData, nil}, - // Test with non-map data - {"user", []interface{}{}, nil}, - } - - // Run test cases - for _, test := range tests { - t.Run(test.path, func(t *testing.T) { - result := lookup(test.path, test.data) - assert.Equal(test.expected, result, "Lookup should return the expected value.") - }) - } -} - -func Test_getHeader(t *testing.T) { - assert := assert.New(t) - - assert.Equal(true, ternary(true, false, true)) - assert.Equal(false, ternary(true, false, false)) - assert.Equal("true string", ternary("true string", "false string", true)) - assert.Equal("false string", ternary("true string", "false string", false)) - assert.Equal(nil, ternary(nil, nil, false)) -} - -func Test_formatTime(t *testing.T) { - assert := assert.New(t) - - teaTime := parseTime("2023-01-01T08:42:00Z", time.RFC3339) - assert.Equal("Sun Jan 1 08:42:00 UTC 2023", formatTime(teaTime, time.RFC3339, time.UnixDate)) - - teaTime = parseTime("Mon Jan 01 08:42:00 UTC 2023", time.UnixDate) - assert.Equal("2023-01-01T08:42:00Z", formatTime(teaTime, time.UnixDate, time.RFC3339)) - - // from unix - teaTime = parseTime("2023-01-01T08:42:00Z", time.RFC3339) - assert.Equal("Sun Jan 1 08:42:00 UTC 2023", formatTime(teaTime.Unix(), "", time.UnixDate)) - - assert.Equal("", formatTime("INVALID_TIME", "", "")) - assert.Equal("", formatTime(nil, "", "")) -} - -func TestParseTime(t *testing.T) { - // Test with nil value - assert.Equal(t, time.Time{}, parseTime(nil, "")) - // Test with invalid value - assert.Equal(t, time.Time{}, parseTime("test", "")) - assert.Equal(t, time.Time{}, parseTime(true, "")) - assert.Equal(t, time.Time{}, parseTime([]byte("test"), "")) - assert.Equal(t, time.Time{}, parseTime(struct{ Time time.Time }{Time: time.Now()}, "")) - assert.Equal(t, time.Time{}, parseTime(httptest.NewRecorder(), "")) - assert.Equal(t, time.Time{}, parseTime("INVALID_TIME", "")) - assert.Equal(t, time.Time{}, parseTime("", "")) - assert.Equal(t, time.Time{}, parseTime("", "INVALID_LAYOUT")) - - // Test with valid value - teaTime := time.Date(2023, 1, 1, 8, 42, 0, 0, time.UTC) - assert.Equal(t, teaTime, parseTime("2023-01-01T08:42:00Z", time.RFC3339)) - assert.Equal(t, teaTime, parseTime("Mon Jan 01 08:42:00 UTC 2023", time.UnixDate)) - assert.Equal(t, teaTime, parseTime("Monday, 01-Jan-23 08:42:00 UTC", time.RFC850)) - assert.Equal(t, teaTime, parseTime("2023/01/01 08h42m00", "2006/01/02 15h04m05")) - teaTime = time.Date(2023, 1, 1, 8, 42, 0, 0, time.Local) - assert.Equal(t, teaTime, parseTime(teaTime.Unix(), "")) - - assert.Equal(t, time.Unix(1234567890, 0), parseTime(int64(1234567890), "")) - assert.Equal(t, time.Time{}, parseTime(int32(0), "")) - assert.Equal(t, time.Time{}, parseTime(int16(0), "")) - assert.Equal(t, time.Time{}, parseTime(int8(0), "")) - assert.Equal(t, time.Time{}, parseTime(int(0), "")) - assert.Equal(t, time.Time{}, parseTime(uint(0), "")) - assert.Equal(t, time.Time{}, parseTime(uint32(0), "")) - assert.Equal(t, time.Time{}, parseTime(uint64(0), "")) - assert.Equal(t, time.Time{}, parseTime(float32(0), "")) - assert.Equal(t, time.Time{}, parseTime(float64(0), "")) - assert.Equal(t, time.Time{}, parseTime("", "")) - assert.Equal(t, time.Time{}, parseTime("invalid", "")) - assert.Equal(t, time.Time{}, parseTime("2006-01-02 15:04:05", "")) - assert.Equal(t, time.Date(2022, 12, 31, 0, 0, 0, 0, time.UTC), parseTime("2022-12-31", "2006-01-02")) - assert.Equal(t, time.Date(2022, 12, 31, 23, 59, 59, 0, time.UTC), parseTime("2022-12-31 23:59:59", "2006-01-02 15:04:05")) -} diff --git a/pkg/storage/postgres/postgres.go b/pkg/storage/postgres/postgres.go index 9429fcb..36bf275 100644 --- a/pkg/storage/postgres/postgres.go +++ b/pkg/storage/postgres/postgres.go @@ -8,8 +8,8 @@ import ( _ "github.com/lib/pq" "github.com/rs/zerolog/log" - "atomys.codes/webhooked/internal/valuable" - "atomys.codes/webhooked/pkg/formatting" + "github.com/42atomys/webhooked/internal/valuable" + "github.com/42atomys/webhooked/pkg/formatting" ) // storage is the struct contains client and config diff --git a/pkg/storage/postgres/postgres_test.go b/pkg/storage/postgres/postgres_test.go index bd4463d..cfddc79 100644 --- a/pkg/storage/postgres/postgres_test.go +++ b/pkg/storage/postgres/postgres_test.go @@ -6,7 +6,7 @@ import ( "os" "testing" - "atomys.codes/webhooked/pkg/formatting" + "github.com/42atomys/webhooked/pkg/formatting" "github.com/jmoiron/sqlx" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/suite" diff --git a/pkg/storage/rabbitmq/rabbitmq.go b/pkg/storage/rabbitmq/rabbitmq.go index 0d63b99..e19802f 100644 --- a/pkg/storage/rabbitmq/rabbitmq.go +++ b/pkg/storage/rabbitmq/rabbitmq.go @@ -8,7 +8,7 @@ import ( "github.com/rs/zerolog/log" "github.com/streadway/amqp" - "atomys.codes/webhooked/internal/valuable" + "github.com/42atomys/webhooked/internal/valuable" ) // storage is the struct contains client and config diff --git a/pkg/storage/redis/redis.go b/pkg/storage/redis/redis.go index 836caaa..bce564b 100644 --- a/pkg/storage/redis/redis.go +++ b/pkg/storage/redis/redis.go @@ -6,7 +6,7 @@ import ( "github.com/go-redis/redis/v8" - "atomys.codes/webhooked/internal/valuable" + "github.com/42atomys/webhooked/internal/valuable" ) type storage struct { diff --git a/pkg/storage/storage.go b/pkg/storage/storage.go index d446a4e..58018bd 100644 --- a/pkg/storage/storage.go +++ b/pkg/storage/storage.go @@ -4,9 +4,9 @@ import ( "context" "fmt" - "atomys.codes/webhooked/pkg/storage/postgres" - "atomys.codes/webhooked/pkg/storage/rabbitmq" - "atomys.codes/webhooked/pkg/storage/redis" + "github.com/42atomys/webhooked/pkg/storage/postgres" + "github.com/42atomys/webhooked/pkg/storage/rabbitmq" + "github.com/42atomys/webhooked/pkg/storage/redis" ) // Pusher is the interface for storage pusher From e71b3298554243925396814f732ea9fa9d701ad7 Mon Sep 17 00:00:00 2001 From: 42Atomys Date: Sun, 15 Sep 2024 16:35:37 +0200 Subject: [PATCH 2/2] docs: remove getHeader from documentation --- README.md | 4 ++-- .../integrations/webhooked_config.integration.yaml | 6 +++--- tests/loadtesting/webhooks.tests.yaml | 8 ++++---- tests/template.tpl | 8 ++++---- tests/webhooks.tests.yaml | 14 +++++++------- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 25229ae..cd3ac41 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,7 @@ specs: "config": "{{ toJson .Config }}", "metadata": { "specName": "{{ .Spec.Name }}", - "deliveryID": "{{ .Request.Header | getHeader "X-Delivery" | default "unknown" }}" + "deliveryID": "{{ .Request.Header.Get "X-Delivery" | default "unknown" }}" }, "payload": {{ .Payload }} } @@ -113,7 +113,7 @@ specs: formatting: templateString: | { - "deliveryID": "{{ .Request.Header | getHeader "X-Delivery" | default "unknown" }}" + "deliveryID": "{{ .Request.Header.Get "X-Delivery" | default "unknown" }}" } httpCode: 200 contentType: application/json diff --git a/tests/integrations/webhooked_config.integration.yaml b/tests/integrations/webhooked_config.integration.yaml index c9571c0..722fe5f 100644 --- a/tests/integrations/webhooked_config.integration.yaml +++ b/tests/integrations/webhooked_config.integration.yaml @@ -46,7 +46,7 @@ specs: formatting: templateString: | { - "contentType": "{{ .Request.Header | getHeader "Content-Type" }}", + "contentType": "{{ .Request.Header.Get "Content-Type" }}", "data": {{ .Payload }} } storage: @@ -66,7 +66,7 @@ specs: entrypointUrl: /integration/basic-response response: formatting: - templateString: '{{ fromJson .Payload | lookup "id" }}' + templateString: '{{ fromJson .Payload | dig "id" }}' httpCode: 200 security: - header: @@ -139,4 +139,4 @@ specs: # In which database do you want to store your data database: 0 # The key where you want to send the data - key: integration:advanced-formatted-usage \ No newline at end of file + key: integration:advanced-formatted-usage diff --git a/tests/loadtesting/webhooks.tests.yaml b/tests/loadtesting/webhooks.tests.yaml index 5aa523c..73258f3 100644 --- a/tests/loadtesting/webhooks.tests.yaml +++ b/tests/loadtesting/webhooks.tests.yaml @@ -22,10 +22,10 @@ specs: "config": "{{ toJson .Config }}", "storage": {{ toJson .Storage }}, "metadata": { - "model": "{{ .Request.Header | getHeader "X-Model" }}", - "event": "{{ .Request.Header | getHeader "X-Event" }}", - "deliveryID": "{{ .Request.Header | getHeader "X-Delivery" | default "unknown" }}" + "model": "{{ .Request.Header.Get "X-Model" }}", + "event": "{{ .Request.Header.Get "X-Event" }}", + "deliveryID": "{{ .Request.Header.Get "X-Delivery" | default "unknown" }}" }, "payload": {{ .Payload }} } - storage: [] \ No newline at end of file + storage: [] diff --git a/tests/template.tpl b/tests/template.tpl index 2e26a84..791c5a5 100644 --- a/tests/template.tpl +++ b/tests/template.tpl @@ -2,9 +2,9 @@ "config": "{{ toJson .Config }}", "storage": {{ toJson .Storage }}, "metadata": { - "model": "{{ .Request.Header | getHeader "X-Model" }}", - "event": "{{ .Request.Header | getHeader "X-Event" }}", - "deliveryID": "{{ .Request.Header | getHeader "X-Delivery" | default "unknown" }}" + "model": "{{ .Request.Header.Get "X-Model" }}", + "event": "{{ .Request.Header.Get "X-Event" }}", + "deliveryID": "{{ .Request.Header.Get "X-Delivery" | default "unknown" }}" }, "payload": {{ .Payload }} -} \ No newline at end of file +} diff --git a/tests/webhooks.tests.yaml b/tests/webhooks.tests.yaml index 7c2271f..404604c 100644 --- a/tests/webhooks.tests.yaml +++ b/tests/webhooks.tests.yaml @@ -27,9 +27,9 @@ specs: "config": "{{ toJson .Config }}", "storage": {{ toJson .Storage }}, "metadata": { - "model": "{{ .Request.Header | getHeader "X-Model" }}", - "event": "{{ .Request.Header | getHeader "X-Event" }}", - "deliveryID": "{{ .Request.Header | getHeader "X-Delivery" | default "unknown" }}" + "model": "{{ .Request.Header.Get "X-Model" }}", + "event": "{{ .Request.Header.Get "X-Event" }}", + "deliveryID": "{{ .Request.Header.Get "X-Delivery" | default "unknown" }}" }, "payload": {{ .Payload }} } @@ -46,7 +46,7 @@ specs: storage: '{{ toJson .Storage }}' metadata: | { - "model": "{{ .Request.Header | getHeader "X-Model" }}", - "event": "{{ .Request.Header | getHeader "X-Event" }}", - "deliveryID": "{{ .Request.Header | getHeader "X-Delivery" | default "unknown" }}" - } \ No newline at end of file + "model": "{{ .Request.Header.Get "X-Model" }}", + "event": "{{ .Request.Header.Get "X-Event" }}", + "deliveryID": "{{ .Request.Header.Get "X-Delivery" | default "unknown" }}" + }