graphql-go

repository·master·Indexed 27 days ago

https://github.com/graphql-go/graphql

A complete GraphQL implementation for Go that enables developers to build type-safe GraphQL schemas, define queries and mutations, and execute them against data sources. It provides support for defining Scalars, Objects, Interfaces, Unions, Enums, and InputObjects, as well as custom directives and an extension interface for augmenting the execution lifecycle.

Tokens
10.5K
Snippets
27
Records
87
Agent score
94%

What's inside graphql-go

  1. Use lifecycle hooks in an Extension

    master
    Extensions use a 'DidStart' pattern. When a lifecycle stage begins, the extension provides a DidStart method which returns a context.Context (to allow the extension to inject data into the request context) and a 'finish' function. This 'finish' function is then called by the engine when that specific stage concludes, allowing the extension to perform cleanup or collect metrics.
  2. Optimize repeated queries using PlanQuery and ExecutePlan

    master

    To avoid the overhead of re-planning the same GraphQL query every time it is executed, use the two-step execution process:

    1. Call PlanQuery with your Schema, AST, and OperationName to generate a *Plan.
    2. Call ExecutePlan using that *Plan and your ExecuteParams for every request.

    This is significantly faster for high-frequency queries than calling Execute() directly.

  3. Create a simple GraphQL schema and execute a query

    master

    This example demonstrates how to define a basic schema with a single field (hello) using graphql.Fields, create a schema with graphql.NewSchema, and execute a query using graphql.Do. The result is returned in a format that can be marshaled to JSON.

    package main
    
    import (
    	"encoding/json"
    	"fmt"
    	"log"
    
    	"github.com/graphql-go/graphql"
    )
    
    func main() {
    	// Schema
    	fields := graphql.Fields{
    		"hello": &graphql.Field{
    			Type: graphql.String,
    			Resolve: func(p graphql.ResolveParams) (interface{}, error) {
    				return "world", nil
    			},
    		},
    	}
    	rootQuery := graphql.ObjectConfig{Name: "RootQuery", Fields: fields}
    	schemaConfig := graphql.SchemaConfig{Query: graphql.NewObject(rootQuery)}
    	schema, err := graphql.NewSchema(schemaConfig)
    	if err != nil {
    		log.Fatalf("failed to create new schema, error: %v", err)
    	}
    
    	// Query
    	query := `
    		{
    			hello
    		}
    	`
    	params := graphql.Params{Schema: schema, RequestString: query}
    	r := graphql.Do(params)
    	if len(r.Errors) > 0 {
    		log.Fatalf("failed to execute graphql operation, errors: %+v", r.Errors)
    	}
    	rJSON, _ := json.Marshal(r)
    	fmt.Printf("%s \n", rJSON) // {"data":{"hello":"world"}}
    }
  4. Configure SchemaConfig

    master

    The SchemaConfig struct is used to define the root components and additional types of a GraphQL schema.

    Fields:

    • Query (*Object): The mandatory root query type.
    • Mutation (*Object): The optional root mutation type.
    • Subscription (*Object): The optional root subscription type.
    • Types ([]Type): A list of additional types to include in the schema.
    • Directives ([]*Directive): A list of directives to be represented and allowed. If empty, default directives are used.
    • Extensions ([]Extension): A list of schema extensions.
  5. Traverse AST using TypeInfo.Enter and TypeInfo.Leave

    master

    To maintain the state of the current type context during a recursive descent of a GraphQL AST, you must call Enter(node) when entering a node and Leave(node) when exiting a node.

    TypeInfo automatically manages internal stacks for types, parent types, input types, and field definitions based on the ast.Node kind (e.g., SelectionSet, Field, Argument, Directive).

  6. Execute a GraphQL query with Do()

    master
    The Do function is the primary high-level entry point for executing a GraphQL query. It handles parsing the request string, validating the query against a schema, and executing the resulting AST. It returns a *Result containing the data or a list of errors.
  7. Get suggestions for invalid input strings

    master

    Use suggestionList to return a filtered and sorted list of valid options based on their similarity to an invalid input string. It uses lexical distance to find the best matches within a calculated threshold.

    func suggestionList(input string, options []string) []string
  8. Inspect type properties with GetNamed and GetNullable

    master

    Use these utility functions to strip away modifiers from a Type:

    • GetNamed(ttype Type) Named: Returns the underlying type without List or NonNull wrappers.
    • GetNullable(ttype Type) Nullable: Returns the type inside a NonNull wrapper if it exists, otherwise returns the type itself.
  9. Validate variables in allowed positions

    master

    Use VariablesInAllowedPositionRule to verify that variables passed to field arguments conform to the expected type. It checks if the variable's defined type (considering default values which make a type effectively non-null) is a subtype of the type required by the position where the variable is used.

    func VariablesInAllowedPositionRule(context *ValidationContext) *ValidationRuleInstance