Categorygithub.com/Oskang09/go-graph-loader
modulepackage
0.0.4
Repository: https://github.com/oskang09/go-graph-loader.git
Documentation: pkg.go.dev

# README

Go Graph Loader ( GGL )

go graph loader is a plugin for load the grahql by resolver and process scalar type with go struct definition instead of schema typing, and come with some simple extension like validator.

Tag & Method Signature

In this plugin we're using gql as graphql key loader and root as root object arguments loader. And about method signature we're following as per below, the responseType will be ur model definition so in order to let us to generate graphql response schema as well.

type Resolver struct {

}

func (*Resolver) Product(context.Context) (responseType, error) {

}

type ProductRequest struct {
    Merchant string `root:"merchant"`
    ID string `gql:"id"`
}

func (*Resolver) Product(context.Context, *ProductRequest) (responseType, error) {

}

Pre Resolver Method Signature

Pre resolver function mainly is let you can do injection on the context based on the response type, usually will use for context resolution for some high level ORM.

type Resolver struct {}

type responseType struct {}

func (rt *responseType) PreResolver(ctx context.Context) context.Context {
	log.Println("invoke preResolver")
	return ctx
}


func (*Resolver) Product(context.Context) (responseType, error) {

}

Model Definition

For model definition by default we're not exposing all the fields only the fields with gql tagged will be exposed. Other than that we did support for field resolver or custom resolver which mean we can add extra function on model.

Supported Primitive Types

1. bool
2. int, int8, int16, int32, int64
3. float32, float64
4. string
5. slice
6. array
7. map

Model Field Resolver

As per model field resolver, we can overriding the original field resolver which just exposing the value, with this we can customize based on the source of value. For method signature as per Tag & Method Signature mentioned it can be only context value or with custom request arguments/

type Product struct {
	ID   int64  `gql:"id"`
	Name string `gql:"name"`
        Price float64 `gql:"price"`
}

type ProductNameArgs struct {
    Extra string `gql:"name"`
}

func (product *Product) GGL_Name(ctx context.Context, args *ProductNameArgs) (string, error) {
	return product.Name + "-" + args.Extra, nil
}

func (product *Product) GGL_Price(ctx context.Context) (int64, error) {
	return int64(product.Price * 100), nil
}
{
    product {
        name(extra: "extraname")
        price
    }
}

Custom Field Resolver

For custom field resolver, we're not overriding the original field resolver but we create new resolver for itself with source of value. All the function will be camelCase when define in graphql query.

type Product struct {
	ID   int64  `gql:"id"`
	Name string `gql:"name"`
        Price float64 `gql:"price"`
}

func (product *Product) GGL_NameWithPrice(ctx context.Context) (string, error) {
	return fmt.Sprintf("%v=%v", product.Name, product.Price), nil
}
{
    product {
        name,
        price,
        nameWithPrice
    }
}

Code & Execution

package main

import (
	"context"
        "json"
        "log"

	ggl "github.com/Oskang09/go-graph-loader"
)

func main() {
    resolver := // your resolver struct which contains all the root functions

    manager := ggl.New()
    manager.RegisterSchema(resolver)

    // define your custom validator
    // so with this you can validate your incoming 
    // parameters with your own validator
    manager.RegisterValidator(nil)

    // magidoc template generator
    manager.WriteSchema("schema.json")
    manager.WriteMagidoc("magidoc.mjs", "schema.json")

    result := manager.Do().
        Query("{ product { name } }"). // set your query string
        Root(map[string]interface{}{"value":"some root value"}). // (optional) set your root object
        Execute(context.Background()) // your current context, it can be useful for tracking & tracing purpose

    if result.HasErrors() {
        log.Println(result.Errors)
    }
	bytes, _ := json.Marshal(result.Data)
	log.Println(string(bytes))
}

Error & Debugging

We did provide the error footprint while having definition error or schema error, so would help you a lot when debugging the issues.

PreResolver Siganture Error

2022/10/20 00:21:41 ————————————— Go Graph Loader —————————————
2022/10/20 00:21:41 | Package   | main
2022/10/20 00:21:41 | Struct    | Product
2022/10/20 00:21:41 | Type      | PRE_RESOLVER
2022/10/20 00:21:41 | Signature | func(*main.Product) context.Context
2022/10/20 00:21:41 ———————————————————————————————————————————
panic: go-graph-loader: invalid method signature is using for pre resolver function

Resolver Function Signature Error

2022/10/20 00:18:03 ————————————— Go Graph Loader —————————————
2022/10/20 00:18:03 | Package   | main
2022/10/20 00:18:03 | Struct    | Product
2022/10/20 00:18:03 | Type      | RESOLVER_METHOD
2022/10/20 00:18:03 | Signature | func(*main.Product, *main.ProductNameArgs) (string, error)
2022/10/20 00:18:03 ———————————————————————————————————————————
panic: go-graph-loader: invalid method signature is using for field resolver function

Documentation Tools

For documentating we will suggest go with magidoc since they will build documentation based on your server's introspection query result.

Development Roadmap

  • PreResolver to allow process context on Response Type
  • Error Tracing Footprint
  • Support int to int64, Support float32 to 64.
  • Support uint to uint64, need to specify custom scalar type since graphql doesn't have it
  • Allow generate schema for Subscription & Mutation
  • Add more examples & cookbook with some famous Go framework
  • Using AST Travesal to allow documentation on the Go model and reflect on Magidoc

# Packages

No description provided by the author

# Functions

No description provided by the author