[WIP] mongodb service
This commit is contained in:
parent
4966c8fbcc
commit
b2ea87f9ba
14 changed files with 380 additions and 32 deletions
58
example/cmd/app/main.go
Normal file
58
example/cmd/app/main.go
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"flag"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
|
||||||
|
"go.mongodb.org/mongo-driver/mongo"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
|
|
||||||
|
"github.com/neonxp/geezer"
|
||||||
|
"github.com/neonxp/geezer/services/mongodb"
|
||||||
|
|
||||||
|
"github.com/neonxp/geezer/example/services/hello"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
listen string
|
||||||
|
mongoURI string
|
||||||
|
mongoDB string
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
flag.StringVar(&listen, "listen", ":3000", "Host and port to listen (ex: '0.0.0.0:3000')")
|
||||||
|
flag.StringVar(&mongoURI, "mongo", "mongodb://localhost:27017/", "MongoDB connection uri (ex: 'mongodb://user:pass@sample.host:27017/')")
|
||||||
|
flag.StringVar(&mongoDB, "mongo_db", "geezer", "Database name")
|
||||||
|
flag.Parse()
|
||||||
|
ctx, cancel := signal.NotifyContext(context.Background(), os.Kill, os.Interrupt)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
// MongoDB connection
|
||||||
|
client, err := mongo.Connect(context.Background(), options.Client().ApplyURI(mongoURI))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
defer client.Disconnect(context.Background())
|
||||||
|
db := client.Database(mongoDB)
|
||||||
|
|
||||||
|
app := geezer.NewHttpKernel()
|
||||||
|
|
||||||
|
hello.RegisterHooks(app) // Register hooks
|
||||||
|
_ = app.Register(hello.ServiceName, &hello.Service{}) // Register service as external handler
|
||||||
|
|
||||||
|
_ = app.Register("test", mongodb.New[Product](db.Collection("test"))) // Register mongodb crud service
|
||||||
|
|
||||||
|
log.Printf("Started on %s\n", listen)
|
||||||
|
srv := http.Server{Addr: listen, Handler: app}
|
||||||
|
go func() {
|
||||||
|
<-ctx.Done()
|
||||||
|
srv.Close()
|
||||||
|
}()
|
||||||
|
if err := srv.ListenAndServe(); err != http.ErrServerClosed {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
}
|
11
example/cmd/app/product.go
Normal file
11
example/cmd/app/product.go
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "go.mongodb.org/mongo-driver/bson/primitive"
|
||||||
|
|
||||||
|
type Product struct {
|
||||||
|
ID primitive.ObjectID `json:"-" bson:"_id,omitempty"`
|
||||||
|
ProductID int `json:"productId"`
|
||||||
|
ProductName string `json:"productName"`
|
||||||
|
Price int `json:"price"`
|
||||||
|
Tags []string `json:"tags"`
|
||||||
|
}
|
18
example/services/hello/hooks.go
Normal file
18
example/services/hello/hooks.go
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
package hello
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/neonxp/geezer"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RegisterHooks(app geezer.AppKernel) {
|
||||||
|
app.Hook(ServiceName, geezer.HookBefore, geezer.HookFind, func(ctx *geezer.HookContext) error {
|
||||||
|
log.Printf("Hook before find")
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
app.Hook(ServiceName, geezer.HookAfter, geezer.HookFind, func(ctx *geezer.HookContext) error {
|
||||||
|
log.Printf("Hook after find")
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
56
example/services/hello/service.go
Normal file
56
example/services/hello/service.go
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
package hello
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/neonxp/geezer"
|
||||||
|
"github.com/neonxp/geezer/render"
|
||||||
|
)
|
||||||
|
|
||||||
|
const ServiceName = "hello"
|
||||||
|
|
||||||
|
type Service struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Service) Find(ctx context.Context, params geezer.Params) (render.Renderer, error) {
|
||||||
|
//TODO implement me
|
||||||
|
log.Printf("Find params=%+v", params)
|
||||||
|
return render.Text("text/html", "Hello, world!"), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Service) Get(ctx context.Context, id string, params geezer.Params) (render.Renderer, error) {
|
||||||
|
//TODO implement me
|
||||||
|
log.Printf("Get id=%s params=%+v", id, params)
|
||||||
|
return nil, geezer.ErrMethodNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Service) Create(ctx context.Context, data geezer.Data, params geezer.Params) (render.Renderer, error) {
|
||||||
|
//TODO implement me
|
||||||
|
log.Printf("Create data=%s params=%+v", data, params)
|
||||||
|
return nil, geezer.ErrMethodNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Service) Update(ctx context.Context, id string, data geezer.Data, params geezer.Params) (render.Renderer, error) {
|
||||||
|
//TODO implement me
|
||||||
|
log.Printf("Update id=%s data=%s params=%+v", id, data, params)
|
||||||
|
return nil, geezer.ErrMethodNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Service) Patch(ctx context.Context, id string, data geezer.Data, params geezer.Params) (render.Renderer, error) {
|
||||||
|
//TODO implement me
|
||||||
|
log.Printf("Patch id=%s data=%s params=%+v", id, data, params)
|
||||||
|
return nil, geezer.ErrMethodNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Service) Remove(ctx context.Context, id string, params geezer.Params) error {
|
||||||
|
//TODO implement me
|
||||||
|
log.Printf("Remove id=%s params=%+v", id, params)
|
||||||
|
return geezer.ErrMethodNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Service) Setup(app geezer.AppKernel, path string) error {
|
||||||
|
//TODO implement me
|
||||||
|
log.Printf("Setup path=%s", path)
|
||||||
|
return nil
|
||||||
|
}
|
19
example/test.http
Normal file
19
example/test.http
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
POST http://localhost:3000/test
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"productId": 123,
|
||||||
|
"productName": "test",
|
||||||
|
"price": 123,
|
||||||
|
"tags": [
|
||||||
|
"one", "two", "three"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
###
|
||||||
|
|
||||||
|
GET http://localhost:3000/test/62017d3fbfd5a64b46077ece
|
||||||
|
|
||||||
|
###
|
||||||
|
|
||||||
|
GET http://localhost:3000/test?price=123
|
21
go.mod
21
go.mod
|
@ -1,3 +1,24 @@
|
||||||
module github.com/neonxp/geezer
|
module github.com/neonxp/geezer
|
||||||
|
|
||||||
go 1.18
|
go 1.18
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/xeipuuv/gojsonschema v1.2.0
|
||||||
|
go.mongodb.org/mongo-driver v1.8.3
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/go-stack/stack v1.8.0 // indirect
|
||||||
|
github.com/golang/snappy v0.0.1 // indirect
|
||||||
|
github.com/klauspost/compress v1.13.6 // indirect
|
||||||
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
|
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
|
||||||
|
github.com/xdg-go/scram v1.0.2 // indirect
|
||||||
|
github.com/xdg-go/stringprep v1.0.2 // indirect
|
||||||
|
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
|
||||||
|
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||||
|
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
|
||||||
|
golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f // indirect
|
||||||
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e // indirect
|
||||||
|
golang.org/x/text v0.3.5 // indirect
|
||||||
|
)
|
||||||
|
|
63
go.sum
Normal file
63
go.sum
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
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=
|
||||||
|
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
|
||||||
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
|
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
|
||||||
|
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
|
github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
|
||||||
|
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
|
||||||
|
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||||
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
|
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/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
||||||
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||||
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
|
||||||
|
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||||
|
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
|
||||||
|
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||||
|
github.com/xdg-go/scram v1.0.2 h1:akYIkZ28e6A96dkWNJQu3nmCzH3YfwMPQExUYDaRv7w=
|
||||||
|
github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs=
|
||||||
|
github.com/xdg-go/stringprep v1.0.2 h1:6iq84/ryjjeRmMJwxutI51F2GIPlP5BfTvXHeYjyhBc=
|
||||||
|
github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM=
|
||||||
|
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
|
||||||
|
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||||
|
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
|
||||||
|
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
|
||||||
|
github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
|
||||||
|
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
|
||||||
|
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=
|
||||||
|
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
|
||||||
|
go.mongodb.org/mongo-driver v1.8.3 h1:TDKlTkGDKm9kkJVUOAXDK5/fkqKHJVwYQSpoRfB43R4=
|
||||||
|
go.mongodb.org/mongo-driver v1.8.3/go.mod h1:0sQWfOeY63QTntERDJJ/0SuKK0T1uVSgKCuAROlKEPY=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f h1:aZp0e2vLN4MToVqnjNEYEtrEA8RH8U8FN1CU7JgqsPU=
|
||||||
|
golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||||
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=
|
||||||
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
|
||||||
|
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
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=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
2
hook.go
2
hook.go
|
@ -33,7 +33,7 @@ var hookTypeFromMethod = map[Method]HookType{
|
||||||
}
|
}
|
||||||
|
|
||||||
type HookContext struct {
|
type HookContext struct {
|
||||||
App Kernel
|
App AppKernel
|
||||||
Path []string
|
Path []string
|
||||||
Method Method
|
Method Method
|
||||||
Type HookLifecycle
|
Type HookLifecycle
|
||||||
|
|
|
@ -8,12 +8,12 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type HttpKernel struct {
|
type HttpKernel struct {
|
||||||
Kernel
|
AppKernel
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHttpKernel() *HttpKernel {
|
func NewHttpKernel() *HttpKernel {
|
||||||
return &HttpKernel{
|
return &HttpKernel{
|
||||||
Kernel: newKernel(),
|
AppKernel: newKernel(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +57,6 @@ func (s *HttpKernel) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
params := Params{
|
params := Params{
|
||||||
Ctx: ctx,
|
|
||||||
Path: parts,
|
Path: parts,
|
||||||
Query: Values(u.Query()),
|
Query: Values(u.Query()),
|
||||||
Headers: Values(r.Header),
|
Headers: Values(r.Header),
|
||||||
|
@ -72,7 +71,7 @@ func (s *HttpKernel) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
defer r.Body.Close()
|
defer r.Body.Close()
|
||||||
data := Data(b)
|
data := Data(b)
|
||||||
|
|
||||||
result, err := s.Call(method, name, id, data, params)
|
result, err := s.Call(ctx, method, name, id, data, params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == ErrMethodNotFound {
|
if err == ErrMethodNotFound {
|
||||||
w.WriteHeader(http.StatusNotFound)
|
w.WriteHeader(http.StatusNotFound)
|
||||||
|
|
35
kernel.go
35
kernel.go
|
@ -1,6 +1,7 @@
|
||||||
package geezer
|
package geezer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
@ -12,19 +13,19 @@ var (
|
||||||
ErrMethodNotFound = errors.New("method not found")
|
ErrMethodNotFound = errors.New("method not found")
|
||||||
)
|
)
|
||||||
|
|
||||||
type defaultKernel struct {
|
type kernel struct {
|
||||||
routes map[string]Service
|
routes map[string]Service
|
||||||
hooks map[string]map[HookLifecycle]map[HookType][]Hook
|
hooks map[string]map[HookLifecycle]map[HookType][]Hook
|
||||||
}
|
}
|
||||||
|
|
||||||
func newKernel() *defaultKernel {
|
func newKernel() *kernel {
|
||||||
return &defaultKernel{
|
return &kernel{
|
||||||
routes: map[string]Service{},
|
routes: map[string]Service{},
|
||||||
hooks: map[string]map[HookLifecycle]map[HookType][]Hook{},
|
hooks: map[string]map[HookLifecycle]map[HookType][]Hook{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *defaultKernel) Register(name string, service Service) error {
|
func (s *kernel) Register(name string, service Service) error {
|
||||||
name = strings.ToLower(name)
|
name = strings.ToLower(name)
|
||||||
s.routes[name] = service
|
s.routes[name] = service
|
||||||
if _, exist := s.hooks[name]; !exist {
|
if _, exist := s.hooks[name]; !exist {
|
||||||
|
@ -36,7 +37,7 @@ func (s *defaultKernel) Register(name string, service Service) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *defaultKernel) Hook(service string, lifecycle HookLifecycle, hookType HookType, hook Hook) {
|
func (s *kernel) Hook(service string, lifecycle HookLifecycle, hookType HookType, hook Hook) {
|
||||||
service = strings.ToLower(service)
|
service = strings.ToLower(service)
|
||||||
if _, exist := s.hooks[service]; !exist {
|
if _, exist := s.hooks[service]; !exist {
|
||||||
s.hooks[service] = map[HookLifecycle]map[HookType][]Hook{}
|
s.hooks[service] = map[HookLifecycle]map[HookType][]Hook{}
|
||||||
|
@ -50,14 +51,14 @@ func (s *defaultKernel) Hook(service string, lifecycle HookLifecycle, hookType H
|
||||||
s.hooks[service][lifecycle][hookType] = append(s.hooks[service][lifecycle][hookType], hook)
|
s.hooks[service][lifecycle][hookType] = append(s.hooks[service][lifecycle][hookType], hook)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *defaultKernel) Service(name string) Service {
|
func (s *kernel) Service(name string) Service {
|
||||||
if service, exist := s.routes[name]; exist {
|
if service, exist := s.routes[name]; exist {
|
||||||
return service
|
return service
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *defaultKernel) Call(method Method, name, id string, data Data, params Params) (render.Renderer, error) {
|
func (s *kernel) Call(ctx context.Context, method Method, name, id string, data Data, params Params) (render.Renderer, error) {
|
||||||
name = strings.ToLower(name)
|
name = strings.ToLower(name)
|
||||||
service := s.Service(name)
|
service := s.Service(name)
|
||||||
if service == nil {
|
if service == nil {
|
||||||
|
@ -70,24 +71,24 @@ func (s *defaultKernel) Call(method Method, name, id string, data Data, params P
|
||||||
}
|
}
|
||||||
switch hookCtx.Method {
|
switch hookCtx.Method {
|
||||||
case MethodFind:
|
case MethodFind:
|
||||||
result, err = service.Find(hookCtx.Params)
|
result, err = service.Find(ctx, hookCtx.Params)
|
||||||
case MethodGet:
|
case MethodGet:
|
||||||
result, err = service.Get(hookCtx.ID, hookCtx.Params)
|
result, err = service.Get(ctx, hookCtx.ID, hookCtx.Params)
|
||||||
case MethodCreate:
|
case MethodCreate:
|
||||||
result, err = service.Create(hookCtx.Data, hookCtx.Params)
|
result, err = service.Create(ctx, hookCtx.Data, hookCtx.Params)
|
||||||
case MethodUpdate:
|
case MethodUpdate:
|
||||||
result, err = service.Update(hookCtx.ID, hookCtx.Data, hookCtx.Params)
|
result, err = service.Update(ctx, hookCtx.ID, hookCtx.Data, hookCtx.Params)
|
||||||
case MethodPatch:
|
case MethodPatch:
|
||||||
result, err = service.Patch(hookCtx.ID, hookCtx.Data, hookCtx.Params)
|
result, err = service.Patch(ctx, hookCtx.ID, hookCtx.Data, hookCtx.Params)
|
||||||
case MethodRemove:
|
case MethodRemove:
|
||||||
err = service.Remove(hookCtx.ID, hookCtx.Params)
|
err = service.Remove(ctx, hookCtx.ID, hookCtx.Params)
|
||||||
default:
|
default:
|
||||||
return nil, ErrMethodNotFound
|
return nil, ErrMethodNotFound
|
||||||
}
|
}
|
||||||
return s.callAfterHooks(method, name, hookCtx, result, err)
|
return s.callAfterHooks(method, name, hookCtx, result, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *defaultKernel) callBeforeHooks(method Method, name string, id string, data Data, params Params) (*HookContext, render.Renderer, error) {
|
func (s *kernel) callBeforeHooks(method Method, name string, id string, data Data, params Params) (*HookContext, render.Renderer, error) {
|
||||||
var beforeHooks []Hook
|
var beforeHooks []Hook
|
||||||
if hooks, ok := s.hooks[name][HookBefore]; ok {
|
if hooks, ok := s.hooks[name][HookBefore]; ok {
|
||||||
if allHooks, ok := hooks[HookAll]; ok {
|
if allHooks, ok := hooks[HookAll]; ok {
|
||||||
|
@ -117,7 +118,7 @@ func (s *defaultKernel) callBeforeHooks(method Method, name string, id string, d
|
||||||
return hookCtx, nil, nil
|
return hookCtx, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *defaultKernel) callAfterHooks(method Method, name string, hookCtx *HookContext, result render.Renderer, err error) (render.Renderer, error) {
|
func (s *kernel) callAfterHooks(method Method, name string, hookCtx *HookContext, result render.Renderer, err error) (render.Renderer, error) {
|
||||||
var afterHooks []Hook
|
var afterHooks []Hook
|
||||||
if hooks, ok := s.hooks[name][HookAfter]; ok {
|
if hooks, ok := s.hooks[name][HookAfter]; ok {
|
||||||
if allHooks, ok := hooks[HookAll]; ok {
|
if allHooks, ok := hooks[HookAll]; ok {
|
||||||
|
@ -154,9 +155,9 @@ func (s *defaultKernel) callAfterHooks(method Method, name string, hookCtx *Hook
|
||||||
return hookCtx.Result, hookCtx.Err
|
return hookCtx.Result, hookCtx.Err
|
||||||
}
|
}
|
||||||
|
|
||||||
type Kernel interface {
|
type AppKernel interface {
|
||||||
Register(name string, service Service) error
|
Register(name string, service Service) error
|
||||||
Hook(service string, lifecycle HookLifecycle, hookType HookType, hook Hook)
|
Hook(service string, lifecycle HookLifecycle, hookType HookType, hook Hook)
|
||||||
Service(name string) Service
|
Service(name string) Service
|
||||||
Call(method Method, name, id string, data Data, params Params) (render.Renderer, error)
|
Call(ctx context.Context, method Method, name, id string, data Data, params Params) (render.Renderer, error)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
package geezer
|
package geezer
|
||||||
|
|
||||||
import "context"
|
|
||||||
|
|
||||||
type Params struct {
|
type Params struct {
|
||||||
Ctx context.Context
|
|
||||||
Path []string
|
Path []string
|
||||||
Query Values
|
Query Values
|
||||||
Headers Values
|
Headers Values
|
||||||
|
|
15
service.go
15
service.go
|
@ -1,19 +1,20 @@
|
||||||
package geezer
|
package geezer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/neonxp/geezer/render"
|
"github.com/neonxp/geezer/render"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Service interface {
|
type Service interface {
|
||||||
Find(params Params) (render.Renderer, error)
|
Find(ctx context.Context, params Params) (render.Renderer, error)
|
||||||
Get(id string, params Params) (render.Renderer, error)
|
Get(ctx context.Context, id string, params Params) (render.Renderer, error)
|
||||||
Create(data Data, params Params) (render.Renderer, error)
|
Create(ctx context.Context, data Data, params Params) (render.Renderer, error)
|
||||||
Update(id string, data Data, params Params) (render.Renderer, error)
|
Update(ctx context.Context, id string, data Data, params Params) (render.Renderer, error)
|
||||||
Patch(id string, data Data, params Params) (render.Renderer, error)
|
Patch(ctx context.Context, id string, data Data, params Params) (render.Renderer, error)
|
||||||
Remove(id string, params Params) error
|
Remove(ctx context.Context, id string, params Params) error
|
||||||
Setup(app Kernel, path string) error
|
Setup(app AppKernel, path string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type Method int
|
type Method int
|
||||||
|
|
6
services/mongodb/models.go
Normal file
6
services/mongodb/models.go
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
package mongodb
|
||||||
|
|
||||||
|
type InsertResult struct {
|
||||||
|
ID any `json:"id"`
|
||||||
|
Item any `json:"item"`
|
||||||
|
}
|
98
services/mongodb/service.go
Normal file
98
services/mongodb/service.go
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
package mongodb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo"
|
||||||
|
|
||||||
|
"github.com/neonxp/geezer"
|
||||||
|
"github.com/neonxp/geezer/render"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Service[T any] struct {
|
||||||
|
collection *mongo.Collection
|
||||||
|
}
|
||||||
|
|
||||||
|
func New[T any](collection *mongo.Collection) *Service[T] {
|
||||||
|
return &Service[T]{collection: collection}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Service[T]) Find(ctx context.Context, params geezer.Params) (render.Renderer, error) {
|
||||||
|
var model []*T
|
||||||
|
where := bson.D{}
|
||||||
|
for k, v := range params.Query {
|
||||||
|
where = append(where, bson.E{Key: k, Value: v[0]})
|
||||||
|
}
|
||||||
|
cursor, err := s.collection.Find(ctx, where)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for cursor.Next(ctx) {
|
||||||
|
r := new(T)
|
||||||
|
if err := cursor.Decode(r); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
model = append(model, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
return render.JSON(model), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Service[T]) Get(ctx context.Context, id string, params geezer.Params) (render.Renderer, error) {
|
||||||
|
var model T
|
||||||
|
oid, err := primitive.ObjectIDFromHex(id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
sr := s.collection.FindOne(ctx, bson.M{"_id": oid})
|
||||||
|
if err := sr.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := sr.Decode(&model); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return render.JSON(model), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Service[T]) Create(ctx context.Context, data geezer.Data, params geezer.Params) (render.Renderer, error) {
|
||||||
|
var model T
|
||||||
|
if err := json.Unmarshal(data, &model); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ir, err := s.collection.InsertOne(ctx, model)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return render.JSON(InsertResult{
|
||||||
|
ID: ir.InsertedID,
|
||||||
|
Item: model,
|
||||||
|
}), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Service[T]) Update(ctx context.Context, id string, data geezer.Data, params geezer.Params) (render.Renderer, error) {
|
||||||
|
//TODO implement me
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Service[T]) Patch(ctx context.Context, id string, data geezer.Data, params geezer.Params) (render.Renderer, error) {
|
||||||
|
//TODO implement me
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Service[T]) Remove(ctx context.Context, id string, params geezer.Params) error {
|
||||||
|
oid, err := primitive.ObjectIDFromHex(id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = s.collection.DeleteOne(ctx, bson.M{"_id": oid})
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Service[T]) Setup(app geezer.AppKernel, path string) error {
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Reference in a new issue