GO
TOC
Add GraphJin
link
Add Graphjin to your GO application.
go get github.com/dosco/graphjin/core/v3
# When enabled GraphJin runs with production level security defaults.
# For example only queries from saved in the queries folder can be used.
production: true
config := core.Config{ Production: true, DefaultLimit: 50 }
Using GraphJin
link
import "github.com/dosco/graphjin/core/v3"
// config can be read in from a file
config, err := NewConfig("./config", "dev.yml")
// or config can be a go struct
// config := core.Config{ Production: true, DefaultLimit: 50 }
gj, err := core.NewGraphJin(config, db)
Whats db
?
link
Its the database client, currently we only support any database driver library for MySQL and Postgres that works with the Go sql.DB
interface.
import "database/sql"
import _ "github.com/jackc/pgx/v4/stdlib"
db, err := sql.Open("pgx", "postgres://postgres:@localhost:5432/example_db")
Your first query
link
// graphql query
query := `
query getPost {
posts(id: $id) {
id
title
author {
id
full_name
}
}
}`
// context with user id set to 1
ctx = context.WithValue(context.Background(), core.UserIDKey, 1)
// variables id set to 3
vars := json.RawMessage(`{ "id": 3 }`)
// execute the query
res, err := sg.GraphQL(ctx, query, vars, nil)
If you would rather use a .gql
or .graphql
file for the query then place it under ./config/queries
and use the queryByName
API instead. Filename must be the query name with a graphql extension
query getPost {
posts(id: $id) {
id
title
author {
id
full_name
}
}
}
res, err := gj.GraphQLByName(ctx, "getPosts", vars, nil)
Get the result
fmt.Println(string(res.Data));
{
"post": {
"id": 3,
"title": "My Third Blog Post",
"author": {
"id": 5,
"full_name": "Andy Anderson"
}
}
}
Using subscriptions
link
Did you ever need to have database changes streamed back to you in realtime. For example new sales that happened, comments added to a blog post, new likes that you want to stream back over websockets, whatever. This is not easy to implement efficiently. But with GraphJin its just as easy as making the above query and is designed to be very efficient.
A subscription query is just a normal query with the prefix subscription
. Use the subscribe
API that works similar to query
in production mode
only allows you to use queries from the queries folder.
// graphql query
query := `
query getPost {
posts(id: $id) {
id
title
author {
id
full_name
}
}
}`
// context with user id set to 1
ctx = context.WithValue(context.Background(), core.UserIDKey, 1)
// variables id set to 3
vars := json.RawMessage(`{ "id": 3 }`)
m, err := gj.Subscribe(ctx, query, vars, nil);
Alterntively you can use the subscribeByName
API which is similar to the queryByName
API.
// context with user id set to 1
ctx = context.WithValue(context.Background(), core.UserIDKey, 1)
// variables id set to 3
vars := json.RawMessage(`{ "id": 3 }`)
m, err := gj.SubscribeByName(ctx, "getPost", vars, nil);
Getting the updates back from a subscription is a little different you have to use a callback since the results keep coming.
for {
msg := <-m.Result
fmt.Println(string(res.Data))
}
{
"post": {
"id": 3,
"title": "My Third Blog Post",
"author": {
"id": 5,
"full_name": "Andy Anderson"
}
}
}
{
"post": {
"id": 3,
"title": "I just changed the title",
"author": {
"id": 5,
"full_name": "Andy Anderson"
}
}
}
{
"post": {
"id": 3,
"title": "Changed it again",
"author": {
"id": 5,
"full_name": "Andy A."
}
}
}
Using the service
link
GraphJin has two packages core
whih contains the core compiler and serv
which contains the standalone service. One way to not have to build your own service and get the flexibility of using your own app is to use the serv
package with your own code. This also means that you get cache headers (etags), compression, rate limiting all of this good stuff for free. The following http and websocket handlers are exposed for you to use:
gjs.GraphQL(nil)
gjs.REST(nil)
gjs.WebUI("/webui/", "/graphql")
Below is an example app to see how all this comes together.
import (
"log"
"net/http"
"path/filepath"
"github.com/dosco/graphjin/serv/v3"
"github.com/go-chi/chi/v5"
)
func main() {
// create the router
r := chi.NewRouter()
// readin graphjin config
conf, err := serv.ReadInConfig(filepath.Join("./config", "dev.yml"))
if err != nil {
panic(err)
}
// create the graphjin service
gjs, err := serv.NewGraphJinService(conf)
if err != nil {
log.Fatal(err)
}
// attach the graphql http handler
r.Handle("/graphql", gjs.GraphQL(nil))
// attach the rest http handler
r.Handle("/rest/*", gjs.REST(nil))
// attach the webui http handler
r.Handle("/webui/*", gjs.WebUI("/webui/", "/graphql"))
// add your own http handlers
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Welcome to the webshop!"))
})
http.ListenAndServe(":8080", r)
}