From 4dfd4c53d36ba3bebc5f12f431d8676f7b986640 Mon Sep 17 00:00:00 2001 From: "Gerasimos (Makis) Maropoulos" Date: Sat, 9 Apr 2022 14:51:34 +0300 Subject: [PATCH] new minor features --- HISTORY.md | 4 + _examples/project/api/configuration.go | 4 +- _examples/project/api/router.go | 19 +- _examples/project/go.mod | 19 +- _examples/project/go.sum | 47 ++-- _examples/project/pkg/database/database.go | 9 + _examples/project/server.yml | 1 + _examples/project/user/repository.go | 8 +- aliases.go | 7 + context/context.go | 26 +++ middleware/methodoverride/methodoverride.go | 4 + middleware/modrevision/modrevision.go | 102 ++++++++ x/pagination/pagination.go | 246 ++++++++++++++++++++ x/reflex/{reflectx.go => reflex.go} | 0 14 files changed, 455 insertions(+), 41 deletions(-) create mode 100644 _examples/project/pkg/database/database.go create mode 100644 middleware/modrevision/modrevision.go create mode 100644 x/pagination/pagination.go rename x/reflex/{reflectx.go => reflex.go} (100%) diff --git a/HISTORY.md b/HISTORY.md index 4b08299a..64c6df8f 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -28,6 +28,10 @@ The codebase for Dependency Injection, Internationalization and localization and ## Fixes and Improvements +- Add new [x/pagination](x/pagination/pagination.go) sub-package which supports generics code (go 1.18+). +- Add new [middleware/modrevision](middleware/modrevision) middleware (example at [_examples/project/api/router.go]_examples/project/api/router.go). +- Add `iris.BuildRevision` and `iris.BuildTime` to embrace the new go's 1.18 debug build information. + - Add `Context.SetJSONOptions` to customize on a higher level the JSON options on `Context.JSON` calls. - Add new [auth](auth) sub-package which helps on any user type auth using JWT (access & refresh tokens) and a cookie (optional). diff --git a/_examples/project/api/configuration.go b/_examples/project/api/configuration.go index d7cc2cc7..3acff670 100644 --- a/_examples/project/api/configuration.go +++ b/_examples/project/api/configuration.go @@ -12,6 +12,7 @@ import ( // for our server, including the Iris one. type Configuration struct { ServerName string `yaml:"ServerName"` + Env string `yaml:"Env"` // The server's host, if empty, defaults to 0.0.0.0 Host string `yaml:"Host"` // The server's port, e.g. 80 @@ -27,7 +28,8 @@ type Configuration struct { // If not empty a request logger is registered, // note that this will cost a lot in performance, use it only for debug. RequestLog string `yaml:"RequestLog"` - + // The database connection string. + ConnString string `yaml:"ConnString"` // Iris specific configuration. Iris iris.Configuration `yaml:"Iris"` } diff --git a/_examples/project/api/router.go b/_examples/project/api/router.go index abd681be..c5668b7f 100644 --- a/_examples/project/api/router.go +++ b/_examples/project/api/router.go @@ -1,22 +1,31 @@ package api import ( + "time" + "github.com/username/project/api/users" + "github.com/username/project/pkg/database" "github.com/username/project/user" - "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/middleware/modrevision" ) // buildRouter is the most important part of your server. // All root endpoints are registered here. func (srv *Server) buildRouter() { // Add a simple health route. - srv.Any("/health", func(ctx iris.Context) { - ctx.Writef("%s\n\nOK", srv.String()) - }) + srv.Any("/health", modrevision.New(modrevision.Options{ + ServerName: srv.config.ServerName, + Env: srv.config.Env, + Developer: "kataras", + TimeLocation: time.FixedZone("Greece/Athens", 10800), + })) api := srv.Party("/api") - api.RegisterDependency(user.NewRepository) + api.RegisterDependency( + database.Open(srv.config.ConnString), + user.NewRepository, + ) api.PartyConfigure("/user", new(users.API)) } diff --git a/_examples/project/go.mod b/_examples/project/go.mod index 60fa8b9d..9219b965 100644 --- a/_examples/project/go.mod +++ b/_examples/project/go.mod @@ -2,6 +2,8 @@ module github.com/username/project go 1.17 +replace github.com/kataras/iris/v12 => ../../ + require ( github.com/kataras/golog v0.1.7 github.com/kataras/iris/v12 v12.2.0-alpha6.0.20220224214946-37c766fef748 @@ -16,11 +18,10 @@ require ( github.com/Shopify/goreferrer v0.0.0-20210630161223-536fa16abd6f // indirect github.com/andybalholm/brotli v1.0.4 // indirect github.com/aymerick/douceur v0.2.0 // indirect - github.com/aymerick/raymond v2.0.2+incompatible // indirect github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385 // indirect github.com/fatih/structs v1.1.0 // indirect github.com/flosch/pongo2/v4 v4.0.2 // indirect - github.com/goccy/go-json v0.9.4 // indirect + github.com/goccy/go-json v0.9.7-0.20220325155717-3a4ad3198047 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/uuid v1.3.0 // indirect github.com/gorilla/css v1.0.0 // indirect @@ -33,13 +34,15 @@ require ( github.com/kataras/pio v0.0.10 // indirect github.com/kataras/sitemap v0.0.5 // indirect github.com/kataras/tunnel v0.0.3 // indirect - github.com/klauspost/compress v1.14.3 // indirect + github.com/klauspost/compress v1.15.1 // indirect + github.com/mailgun/raymond/v2 v2.0.46 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/microcosm-cc/bluemonday v1.0.18 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/schollz/closestmatch v2.1.0+incompatible // indirect + github.com/sirupsen/logrus v1.8.1 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/tdewolff/minify/v2 v2.10.0 // indirect github.com/tdewolff/parse/v2 v2.5.27 // indirect @@ -47,11 +50,11 @@ require ( github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect github.com/yosssi/ace v0.0.5 // indirect - golang.org/x/crypto v0.0.0-20220214200702-86341886e292 // indirect - golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect - golang.org/x/sys v0.0.0-20220209214540-3681064d5158 // indirect + golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29 // indirect + golang.org/x/net v0.0.0-20220401154927-543a649e0bdd // indirect + golang.org/x/sys v0.0.0-20220330033206-e17cdc41300f // indirect golang.org/x/text v0.3.7 // indirect - golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect - google.golang.org/protobuf v1.27.1 // indirect + golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 // indirect + google.golang.org/protobuf v1.28.0 // indirect gopkg.in/ini.v1 v1.66.4 // indirect ) diff --git a/_examples/project/go.sum b/_examples/project/go.sum index 6194b69a..4d893ed4 100644 --- a/_examples/project/go.sum +++ b/_examples/project/go.sum @@ -74,8 +74,6 @@ github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= -github.com/aymerick/raymond v2.0.2+incompatible h1:VEp3GpgdAnv9B2GFyTvqgcKvY+mfKMjPOA3SbKLtnU0= -github.com/aymerick/raymond v2.0.2+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= @@ -140,8 +138,8 @@ github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2 github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/goccy/go-json v0.9.4 h1:L8MLKG2mvVXiQu07qB6hmfqeSYQdOnqPot2GhsIwIaI= -github.com/goccy/go-json v0.9.4/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/goccy/go-json v0.9.7-0.20220325155717-3a4ad3198047 h1:SMQ4NGzEnbUgyY0ids2HuBTOFSUPOjL3GRh5l7zwrvk= +github.com/goccy/go-json v0.9.7-0.20220325155717-3a4ad3198047/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= @@ -194,7 +192,7 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -224,7 +222,7 @@ github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pf github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= -github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= @@ -262,7 +260,7 @@ github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1: github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/iris-contrib/httpexpect/v2 v2.0.5 h1:b2Orx2FXRhnmZil4td66C8zzkHnssSoFQP2HQtyktJg= +github.com/iris-contrib/httpexpect/v2 v2.3.1 h1:A69ilxKGW1jDRKK5UAhjTL4uJYh3RjD4qzt9vNZ7fpY= github.com/iris-contrib/jade v1.1.4 h1:WoYdfyJFfZIUgqNAeOyRfTNQZOksSlZ6+FnXR3AEpX0= github.com/iris-contrib/jade v1.1.4/go.mod h1:EDqR+ur9piDl6DUgs6qRrlfzmlx/D5UybogqrXvJTBE= github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw= @@ -281,8 +279,6 @@ github.com/kataras/blocks v0.0.5 h1:jFrsHEDfXZhHTbhkNWgMgpfEQNj1Bwr1IYEYZ9Xxoxg= github.com/kataras/blocks v0.0.5/go.mod h1:kcJIuvuA8QmGKFLHIZHdCAPCjcE85IhttzXd6W+ayfE= github.com/kataras/golog v0.1.7 h1:0TY5tHn5L5DlRIikepcaRR/6oInIr9AiWsxzt0vvlBE= github.com/kataras/golog v0.1.7/go.mod h1:jOSQ+C5fUqsNSwurB/oAHq1IFSb0KI3l6GMa7xB6dZA= -github.com/kataras/iris/v12 v12.2.0-alpha6.0.20220224214946-37c766fef748 h1:8zXAxFQUMY11OkYq2qzSJRwnEpJVBjJfg2yswDESJrk= -github.com/kataras/iris/v12 v12.2.0-alpha6.0.20220224214946-37c766fef748/go.mod h1:41s7glJCO96To+fzPzTYn1ttaxlcBnYvp0iOccd0oGE= github.com/kataras/pio v0.0.10 h1:b0qtPUqOpM2O+bqa5wr2O6dN4cQNwSmFd6HQqgVae0g= github.com/kataras/pio v0.0.10/go.mod h1:gS3ui9xSD+lAUpbYnjOGiQyY7sUMJO+EHpiRzhtZ5no= github.com/kataras/sitemap v0.0.5 h1:4HCONX5RLgVy6G4RkYOV3vKNcma9p236LdGOipJsaFE= @@ -291,8 +287,8 @@ github.com/kataras/tunnel v0.0.3 h1:+8eHXujPD3wLnqTbYtPGa/3/Jc+Eq+bsPwEGTeFBB00= github.com/kataras/tunnel v0.0.3/go.mod h1:VOlCoaUE5zN1buE+yAjWCkjfQ9hxGuhomKLsjei/5Zs= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.14.3 h1:DQv1WP+iS4srNjibdnHtqu8JNWCDMluj5NzPnFJsnvk= -github.com/klauspost/compress v1.14.3/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/compress v1.15.1 h1:y9FcTHGyrebwfP0ZZqFiaxTaiDnUrGkJkI+f583BL1A= +github.com/klauspost/compress v1.15.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= @@ -303,6 +299,8 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/mailgun/raymond/v2 v2.0.46 h1:aOYHhvTpF5USySJ0o7cpPno/Uh2I5qg2115K25A+Ft4= +github.com/mailgun/raymond/v2 v2.0.46/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/matryer/try v0.0.0-20161228173917-9ac251b645a2/go.mod h1:0KeJpeMD6o+O4hW7qJOT7vyQPKrWmj26uf5wMc/IiIs= @@ -363,7 +361,6 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= @@ -371,10 +368,11 @@ github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43 github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk= github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= 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.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= @@ -392,8 +390,8 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tdewolff/minify/v2 v2.10.0 h1:ovVAHUcjfGrBDf1EIvsodRUVJiZK/28mMose08B7k14= github.com/tdewolff/minify/v2 v2.10.0/go.mod h1:6XAjcHM46pFcRE0eztigFPm0Q+Cxsw8YhEWT+rDkcZM= @@ -445,8 +443,8 @@ golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220214200702-86341886e292 h1:f+lwQ+GtmgoY+A2YaQxlSOnDjXcQ7ZRLWOHbC6HtRqE= -golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29 h1:tkVvjkPTB7pnW3jnid7kNyAMPVWllTNOf/qKDze4p9o= +golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -525,8 +523,8 @@ golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220401154927-543a649e0bdd h1:zYlwaUHTmxuf6H7hwO2dgwqozQmH7zf4x+/qql4oVWc= +golang.org/x/net v0.0.0-20220401154927-543a649e0bdd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= 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-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -620,8 +618,8 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158 h1:rm+CHSpPEEW2IsXUib1ThaHIjuBVZjxNgSKmBLFfD4c= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220330033206-e17cdc41300f h1:rlezHXNlxYWvBCzNses9Dlc7nGFaNMJeqLolcmQSSZY= +golang.org/x/sys v0.0.0-20220330033206-e17cdc41300f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -636,8 +634,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= -golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 h1:M73Iuj3xbbb9Uk1DYhzydthsj6oOd6l9bpuFcNoUvTs= +golang.org/x/time v0.0.0-20220224211638-0e9765cccd65/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= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -839,8 +837,9 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/_examples/project/pkg/database/database.go b/_examples/project/pkg/database/database.go new file mode 100644 index 00000000..80e5687c --- /dev/null +++ b/_examples/project/pkg/database/database.go @@ -0,0 +1,9 @@ +package database + +type DB struct { + /* ... */ +} + +func Open(connString string) *DB { + return &DB{} +} diff --git a/_examples/project/server.yml b/_examples/project/server.yml index 1edcd1a8..0784028a 100644 --- a/_examples/project/server.yml +++ b/_examples/project/server.yml @@ -1,4 +1,5 @@ ServerName: My Project +Env: development Host: 0.0.0.0 Port: 80 EnableCompression: true diff --git a/_examples/project/user/repository.go b/_examples/project/user/repository.go index 4ec98547..99c67a12 100644 --- a/_examples/project/user/repository.go +++ b/_examples/project/user/repository.go @@ -1,12 +1,14 @@ package user +import "github.com/username/project/pkg/database" + type Repository interface { // Repo methods here... } type repo struct { // Hold database instance here: e.g. - // *mydatabase_pkg.DB + db *database.DB } -func NewRepository( /* *mydatabase_pkg.DB */ ) Repository { - return &repo{ /* db: db */ } +func NewRepository(db *database.DB) Repository { + return &repo{db: db} } diff --git a/aliases.go b/aliases.go index 6c18ebcb..89416580 100644 --- a/aliases.go +++ b/aliases.go @@ -14,6 +14,13 @@ import ( "github.com/kataras/iris/v12/view" ) +var ( + // BuildRevision holds the vcs commit id information. + BuildRevision = context.BuildRevision + // BuildTime holds the vcs commit time information. + BuildTime = context.BuildTime +) + // SameSite attributes. const ( SameSiteDefaultMode = http.SameSiteDefaultMode diff --git a/context/context.go b/context/context.go index 01e63c2c..8b726012 100644 --- a/context/context.go +++ b/context/context.go @@ -19,6 +19,7 @@ import ( "path/filepath" "reflect" "regexp" + "runtime/debug" "sort" "strconv" "strings" @@ -45,6 +46,31 @@ import ( "gopkg.in/yaml.v3" ) +var ( + // BuildRevision holds the vcs commit id information. + BuildRevision string + // BuildTime holds the vcs commit time information. + BuildTime string +) + +func init() { + if info, ok := debug.ReadBuildInfo(); ok { + for _, setting := range info.Settings { + if BuildRevision != "" && BuildTime != "" { + break + } + + if setting.Key == "vcs.revision" { + BuildRevision = setting.Value + } + + if setting.Key == "vcs.time" { + BuildTime = setting.Key + } + } + } +} + type ( // BodyDecoder is an interface which any struct can implement in order to customize the decode action // from ReadJSON and ReadXML diff --git a/middleware/methodoverride/methodoverride.go b/middleware/methodoverride/methodoverride.go index d6c2fbce..032b6833 100644 --- a/middleware/methodoverride/methodoverride.go +++ b/middleware/methodoverride/methodoverride.go @@ -9,6 +9,10 @@ import ( "github.com/kataras/iris/v12/core/router" ) +func init() { + context.SetHandlerName("iris/middleware/methodoverride.*", "iris.methodoverride") +} + type options struct { getters []GetterFunc methods []string diff --git a/middleware/modrevision/modrevision.go b/middleware/modrevision/modrevision.go new file mode 100644 index 00000000..ca40b620 --- /dev/null +++ b/middleware/modrevision/modrevision.go @@ -0,0 +1,102 @@ +package modrevision + +import ( + "fmt" + "strings" + "time" + + "github.com/kataras/iris/v12/context" +) + +func init() { + context.SetHandlerName("iris/middleware/modrevision.*", "iris.modrevision") +} + +// Options holds the necessary values to render the server name, environment and build information. +// See the `New` package-level function. +type Options struct { + // The ServerName, e.g. Iris Server. + ServerName string + // The Environment, e.g. development. + Env string + // The Developer, e.g. kataras. + Developer string + // True to display the build time as unix (seconds). + UnixTime bool + // A non nil time location value to customize the display of the build time. + TimeLocation *time.Location +} + +type modRevision struct { + options Options + + buildTime string + buildRevision string + + contents []byte +} + +// New returns an Iris Handler which renders +// the server name (env), build information (if available) +// and an OK message. The handler displays simple debug information such as build commit id and time. +// It does NOT render information about the Go language itself or any operating system confgiuration +// for security reasons. +// +// Example Code: +// app.Get("/health", modrevision.New(modrevision.Options{ +// ServerName: "Iris Server", +// Env: "development", +// Developer: "kataras", +// TimeLocation: time.FixedZone("Greece/Athens", 10800), +// })) +func New(opts Options) context.Handler { + bTime, bRevision := context.BuildTime, context.BuildRevision + if opts.UnixTime { + if t, err := time.Parse(time.RFC3339, bTime); err == nil { + bTime = fmt.Sprintf("%d", t.Unix()) + } + } else if opts.TimeLocation != nil { + if t, err := time.Parse(time.RFC3339, bTime); err == nil { + bTime = t.In(opts.TimeLocation).String() + } + } + + m := &modRevision{ + options: opts, + + buildTime: bTime, + buildRevision: bRevision, + } + + contents := []byte(m.String()) + if len(contents) > 0 { + contents = append(contents, []byte("\n\nOK")...) + } else { + contents = []byte("OK") + } + + return func(ctx *context.Context) { + ctx.Write(contents) + } +} + +// String returns the server name and its running environment or an empty string +// of the given server name is empty. +func (m *modRevision) String() string { + if name := m.options.ServerName; name != "" { + if env := m.options.Env; env != "" { + name += fmt.Sprintf(" (%s)", env) + } + + if m.buildRevision != "" && m.buildTime != "" { + buildTitle := ">>>> build" // if we ever want an emoji, there is one: \U0001f4bb + tab := strings.Repeat(" ", len(buildTitle)) + name += fmt.Sprintf("\n\n%[1]s\n%srevision %s\n[1]sbuildtime %s\n[1]sdeveloper %s", tab, + buildTitle, m.buildRevision, m.buildTime, m.options.Developer) + } + + return name + } + + return "" +} diff --git a/x/pagination/pagination.go b/x/pagination/pagination.go new file mode 100644 index 00000000..8becf6b9 --- /dev/null +++ b/x/pagination/pagination.go @@ -0,0 +1,246 @@ +//go:build go1.18 + +/* +Until go version 2, we can't really apply the type alias feature on a generic type or function, +so keep it separated on x/pagination. + +import "github.com/kataras/iris/v12/context" + +type ListResponse[T any] = context.ListResponse[T] +OR +type ListResponse = context.ListResponse doesn't work. + +The only workable thing for generic aliases is when you know the type e.g. +type ListResponse = context.ListResponse[any] but that doesn't fit us. +*/ + +package iris + +import ( + "math" + "net/http" + "strconv" +) + +var ( + // MaxSize defines the max size of items to display. + MaxSize = 100000 + // DefaultSize defines the default size when ListOptions.Size is zero. + DefaultSize = MaxSize +) + +// ListOptions is the list request object which should be provided by the client through +// URL Query. Then the server passes that options to a database query, +// including any custom filters may be given from the request body and, +// then the server responds back with a `Context.JSON(NewList(...))` response based +// on the database query's results. +type ListOptions struct { + // Current page number. + // If Page > 0 then: + // Limit = DefaultLimit + // Offset = DefaultLimit * Page + // If Page == 0 then no actual data is return, + // internally we must check for this value + // because in postgres LIMIT 0 returns the columns but with an empty set. + Page int `json:"page" url:"page"` + // The elements to get, this modifies the LIMIT clause, + // this Size can't be higher than the MaxSize. + // If Size is zero then size is set to DefaultSize. + Size int `json:"size" url:"size"` +} + +// GetLimit returns the LIMIT value of a query. +func (opts ListOptions) GetLimit() int { + if opts.Size > 0 && opts.Size < MaxSize { + return opts.Size + } + + return DefaultSize +} + +// GetLimit returns the OFFSET value of a query. +func (opts ListOptions) GetOffset() int { + if opts.Page > 1 { + return (opts.Page - 1) * opts.GetLimit() + } + + return 0 +} + +// GetCurrentPage returns the Page or 1. +func (opts ListOptions) GetCurrentPage() int { + current := opts.Page + if current == 0 { + current = 1 + } + + return current +} + +// GetNextPage returns the next page, current page + 1. +func (opts ListOptions) GetNextPage() int { + return opts.GetCurrentPage() + 1 +} + +// Bind binds the ListOptions values to a request value. +// It should be used as an x/client.RequestOption to fire requests +// on a server that supports pagination. +func (opts ListOptions) Bind(r *http.Request) error { + page := strconv.Itoa(opts.GetCurrentPage()) + size := strconv.Itoa(opts.GetLimit()) + + q := r.URL.Query() + q.Set("page", page) + q.Set("size", size) + return nil +} + +// List is the http response of a server handler which should render +// items with pagination support. +type List[T any] struct { + CurrentPage int `json:"current_page"` // the current page. + PageSize int `json:"page_size"` // the total amount of the entities return. + TotalPages int `json:"total_pages"` // the total number of pages based on page, size and total count. + TotalItems int64 `json:"total_items"` // the total number of rows. + HasNextPage bool `json:"has_next_page"` // true if more data can be fetched, depending on the current page * page size and total pages. + Filter any `json:"filter"` // if any filter data. + Items []T `json:"items"` // Items is empty array if no objects returned. Do NOT modify from outside. +} + +// NewList returns a new List response which holds +// the current page, page size, total pages, total items count, any custom filter +// and the items array. +// +// Example Code: +// +// import "github.com/kataras/iris/v12/x/pagination" +// ...more code +// +// type User struct { +// Firstname string `json:"firstname"` +// Lastname string `json:"lastname"` +// } +// +// type ExtraUser struct { +// User +// ExtraData string +// } +// +// func main() { +// users := []User{ +// {"Gerasimos", "Maropoulos"}, +// {"Efi", "Kwfidou"}, +// } +// +// t := pagination.NewList(users, 100, nil, pagination.ListOptions{ +// Page: 1, +// Size: 50, +// }) +// +// // Optionally, transform a T list of objects to a V list of objects. +// v, err := pagination.TransformList(t, func(u User) (ExtraUser, error) { +// return ExtraUser{ +// User: u, +// ExtraData: "test extra data", +// }, nil +// }) +// if err != nil { panic(err) } +// +// paginationJSON, err := json.MarshalIndent(v, "", " ") +// if err!=nil { panic(err) } +// fmt.Println(paginationJSON) +// } +func NewList[T any](items []T, totalCount int64, filter any, opts ListOptions) *List[T] { + pageSize := opts.GetLimit() + + n := len(items) + if n == 0 || pageSize <= 0 { + return &List[T]{ + CurrentPage: 1, + PageSize: 0, + TotalItems: 0, + TotalPages: 0, + Filter: filter, + Items: make([]T, 0), + } + } + + numberOfPages := int(roundUp(float64(totalCount)/float64(pageSize), 0)) + if numberOfPages <= 0 { + numberOfPages = 1 + } + + var hasNextPage bool + + currentPage := opts.GetCurrentPage() + if totalCount == 0 { + currentPage = 1 + } + + if n > 0 { + hasNextPage = currentPage < numberOfPages + } + + return &List[T]{ + CurrentPage: currentPage, + PageSize: n, + TotalPages: numberOfPages, + TotalItems: totalCount, + HasNextPage: hasNextPage, + Filter: filter, + Items: items, + } +} + +// TransformList accepts a List response and converts to a list of V items. +// T => from +// V => to +// +// Example Code: +// +// listOfUsers := pagination.NewList(...) +// newListOfExtraUsers, err := pagination.TransformList(listOfUsers, func(u User) (ExtraUser, error) { +// return ExtraUser{ +// User: u, +// ExtraData: "test extra data", +// }, nil +// }) +func TransformList[T any, V any](list *List[T], transform func(T) (V, error)) (*List[V], error) { + if list == nil { + return &List[V]{ + CurrentPage: 1, + PageSize: 0, + TotalItems: 0, + TotalPages: 0, + Filter: nil, + Items: make([]V, 0), + }, nil + } + + items := list.Items + + toItems := make([]V, 0, len(items)) + for _, fromItem := range items { + toItem, err := transform(fromItem) + if err != nil { + return nil, err + } + + toItems = append(toItems, toItem) + } + + newList := &List[V]{ + CurrentPage: list.CurrentPage, + PageSize: list.PageSize, + TotalItems: list.TotalItems, + TotalPages: list.TotalPages, + Filter: list.Filter, + Items: toItems, + } + return newList, nil +} + +func roundUp(input float64, places float64) float64 { + pow := math.Pow(10, places) + return math.Ceil(pow*input) / pow +} diff --git a/x/reflex/reflectx.go b/x/reflex/reflex.go similarity index 100% rename from x/reflex/reflectx.go rename to x/reflex/reflex.go