Hi!
After playing around with DGraph, I really came to like its concepts of doing things. Especially in conjunction with the Lambda-Server it provides a lot of benefits.
Unfortunately the provided Lambda-Server did not fulfill all my needs. Due to the fact that you have to use webpack to use external libraries and some of these libraries not supporting webpack (e.g. firebase-admin), using the lambda server became cumbersome, as it would need another external service to serve the additional functionality.
That is why I sat down and wrote an alternative in Go dgraph-lambda-go.
It’s my first official Go project, so I hope I did not miss on any best practices in the development process. As of now I would say it’s in a Testing-Phase. I’m using it in my own project and it fulfilled all my needs for now, but you might have some more complex needs.
Features
- Resolvers on Fields, Queries and Mutations
- Global Middleware
- Middleware on specific resolvers
- Webhooks
Future plan:
- Middleware on resolver groups
- Generate resolvers and structs from the DGraph graphql schema.
How does it work (Basically Readme)
- To install dgraph-lambda-go run the command
go get github.com/schartey/dgraph-lambda-go
in your project directory. - Then initialize the project by running
go run github.com/schartey/dgraph-lambda-go init
.
Implement resolver functions and middleware
On startup this library provides a resolver.
err := api.RunServer(func(r *resolver.Resolver, gql *graphql.Client, dql *dgo.Dgraph) {
})
Within this startup function you can provide resolver functions and middleware. It’s best to first define the input and output structs for the resolver. For example CreateUserInput and UserData struct
type CreateUserInput struct {
Username string `json:"username"`
}
type UserData struct {
Id string `json:"id"`
Username string `json:"username"`
ComplexProperty string `json:"complexProperty"`
}
Then you can provide a resolver for fields, queries and mutations like this
// Field Resolver
r.ResolveFunc("UserData.complexProperty", func(ctx context.Context, input []byte, parents []byte, ah resolver.AuthHeader) (interface{}, error) {
var userParents []UserData
json.Unmarshal(parents, &userParents)
var complexProperties []string
for _, userParent := range userParents {
complexProperties = append(complexProperties, fmt.Sprintf("VeryComplex - %s", userParent.Id))
}
return complexProperties, nil
})
// Query/Mutation Resolver
r.ResolveFunc("Mutation.createUser", func(ctx context.Context, input []byte, parents []byte, ah resolver.AuthHeader) (interface{}, error) {
var createUserInput CreateUserInput
json.Unmarshal(input, &createUserInput)
// Do Something
user := UserData{
Id: "0x1",
Username: createUserInput.Username,
}
return user, nil
})
You can also provide global middleware, as well as middleware on specific resolvers
r.Use(func(hf resolver.HandlerFunc) resolver.HandlerFunc {
return func(c context.Context, b []byte, parents []byte, ah resolver.AuthHeader) (interface{}, error) {
// Authorization.
// Add user to context
return hf(c, b, parents, ah)
}
})
r.UseOnResolver("Mutation.createUser", func(hf resolver.HandlerFunc) resolver.HandlerFunc {
return func(c context.Context, b []byte, parents []byte, ah resolver.AuthHeader) (interface{}, error) {
// Validation .
return b, nil
}
})
Finally a webhook resolver is also provided on Types
r.WebHookFunc("UserData", func(ctx context.Context, event resolver.Event) error {
// Send E-Mail
return nil
})
Additionally a graphql and dql client connected to the dgraph server are provided, so you can query and make changes to the databases.
If you could provide some feedback I would appreciate it. As said, dgraph-lambda-go is my first open source project and I hope you like it.
Best regards