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
-
+
@@ -9,7 +9,7 @@
-
+
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" }}"
+ }