Go Library

GraphJin can be used as a library in an already existing project. The best part is that your API need not even be a GraphQL one. You can simply use GraphJin as an alternative to a GO ORM library or directly writing SQL. The following code is just a simple example for more detailed working examples checkout the GoDoc https://pkg.go.dev/github.com/dosco/graphjin/core

package main

import (
	"context"
	"database/sql"
	"net/http"

	"github.com/dosco/graphjin/core"
	"github.com/go-chi/chi"
	"github.com/go-chi/render"
	_ "github.com/jackc/pgx/v4/stdlib"
)

func Handler(gj *core.GraphJin) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		body, err := getBodyFromRequest(w, r)
		// check err

		ctx := context.WithValue(r.Context(), core.UserIDKey, GetYourUserID())

		res, err := gj.GraphQL(ctx, body.Query, body.Variables, nil)
		// check err

		render.JSON(w, r, res)
	}
}

func main() {
	dbConn, err := sql.Open("pgx", DB_URL)
	//check err

	gj, err := core.NewGraphJin(nil, dbConn)
	//check err

	r := chi.NewRouter()

	r.Post("/api", Handler(gj))

	StartServer()
}

Config Explained

The configuration is the same as that in yaml except for that it is obviously written in Go and is just about configuring the core package (aka GraphJin library). We’ve tried to ensure that the config file is self-documenting and easy to work with. A config object is not required GraphJin can learn your database structure and be useful even when a config is not provided.

conf := core.Config{
	//SecretKey is used to encrypt opaque values such as the cursor. Auto-generated if not set
	SecretKey: "[YOU_SHOULD_CHANGE_THIS]",

	//UseAllowList (aka production mode) when set to true ensures only queries lists
	//in the allow.list file can be used. All queries are pre-prepared so no compiling
	//happens and things are very fast.
	UseAllowList: false,

	//AllowListFile if the path to allow list file if not set the path is assumed
	//to be the same as the config path (allow.list)
	AllowListFile: "",

	//SetUserID forces the database session variable `user.id` to be set to the user id.
	//This variables can be used by triggers or other database functions
	SetUserID: false,

	//DefaultBlock ensures that in anonymous mode (role 'anon') all tables are blocked
	//from queries and mutations. To open access to tables in anonymous mode
	//they have to be added to the 'anon' role config.
	DefaultBlock: false,

	//Vars is a map of hardcoded variables that can be leveraged in your queries
	//(e.g. variable admin_id will be $admin_id in the query)
	Vars: map[string]string{
		"account_id": "sql:select account_id from users where id = $user_id",
		"team_id":    "123",
	},

	//Blocklist is a list of tables and columns that should be filtered out
	// from any and all queries
	Blocklist: []string{"password", "secrets", "credit_card_number"},

	//Tables contains all table specific configuration such as aliased tables
	//creating relationships between tables, etc
	Tables: []core.Table{},

	//RolesQuery if set enabled attributed based access control.
	//This query is use to fetch the user attributes that then dynamically define the users role.
	RolesQuery: "",

	//Roles contains all the configuration for all the roles you want to support `user` and `anon`
	//are two default roles. User role is for when a user ID is available and Anon when it's not.
	//If you're using the RolesQuery config to enable atribute based acess control then you
	// can add more custom roles.

	// Use .AddRoleTable(roleName, tableName, roleTableConfig) to set this.
	// example below
	Roles: []core.Role{}

	//Inflections is to add additionally singular to plural
	// mappings to the engine (eg. sheep: sheep)
	Inflections: map[string]string{},

	//Database schema name. Defaults to 'public'
	DBSchema: "",

	//Log warnings and other debug information
	Debug: false,
}

conf.AddRoleTable("user", "table_name", core.Query{
	Limit:            10,
	Filters:          []string{},
	Columns:          []string{},
	DisableFunctions: false,
	Block:            false,
});

conf.AddRoleTable("user", "table_name", core.Insert{
	Filters: []string{},
	Columns: []string{},
	Presets: map[string]string{},
	Block:   false,
})

...