Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

doc: fix mistakes in v2 tutorial #785

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
160 changes: 83 additions & 77 deletions v2/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ import (
"fmt"

"github.com/cespare/xxhash/v2"

"github.com/wundergraph/graphql-go-tools/v2/pkg/ast"
"github.com/wundergraph/graphql-go-tools/v2/pkg/astnormalization"
"github.com/wundergraph/graphql-go-tools/v2/pkg/astparser"
Expand Down Expand Up @@ -101,7 +102,7 @@ func ExampleParsePrintDocument() {
if err != nil {
panic(err)
}
fmt.Println(out.String()) // Output: query { hello }
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The operation type (query) is no longer part of the output. It wasn't clear to me whether this is intentional or not.

fmt.Println(out) // Output: { hello }
}

/*
Expand Down Expand Up @@ -138,7 +139,7 @@ func ExampleParseComplexDocument() {
if err != nil {
panic(err)
}
fmt.Println(out.String()) // Output: query { hello foo { bar } }
fmt.Println(out) // Output: {hello foo {bar}}
}

/*
Expand Down Expand Up @@ -173,11 +174,11 @@ func ExamplePrintWithIndentation() {
panic(err)
}
fmt.Println(out)
// Output: query {
// hello
// foo {
// bar
// }
// Output: {
// hello
// foo {
// bar
// }
// }
}

Expand Down Expand Up @@ -221,9 +222,9 @@ func ExampleParseOperationNameAndType() {
continue
}
operationCount++
name := document.RootOperationTypeDefinitionNameString(node.Ref)
name := document.OperationDefinitionNameString(node.Ref)
operationNames = append(operationNames, name)
operationType := document.RootOperationTypeDefinitions[node.Ref].OperationType
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RootOperationTypeDefinitions is an empty slice here. Likewise, it wasn't clear to me whether this is intentional or not.

operationType := document.OperationDefinitions[node.Ref].OperationType
operationTypes = append(operationTypes, operationType)
}

Expand Down Expand Up @@ -335,10 +336,10 @@ func ExampleNormalizeDocument() {

fmt.Println(out)
// Output: query MyQuery {
// hello
// foo {
// bar
// }
// hello
// foo {
// bar
// }
// }
}

Expand All @@ -353,14 +354,17 @@ Alright. Let's do it!
*/

func ExampleValidateDocument() {
schemaDocument := ast.NewSmallDocument()
operationDocument := ast.NewSmallDocument()
operationDocument := ast.NewSmallDocument() // replace with the "document" from ExampleNormalizeDocument
schemaDocument := ast.NewSmallDocument() // replace with the "schemaDocument" from ExampleNormalizeDocument
report := &operationreport.Report{}

validator := astvalidation.DefaultOperationValidator()
validator.Validate(schemaDocument, operationDocument, report)
validator.Validate(operationDocument, schemaDocument, report)
if report.HasErrors() {
panic(report.Error())
}

fmt.Println("Valid")
}

/*
Expand All @@ -373,18 +377,9 @@ Let's take a look!
*/

func ExampleGenerateCacheKey() {
operationDocument := ast.NewSmallDocument()
schemaDocument := ast.NewSmallDocument()
report := &operationreport.Report{}
operationDocument := ast.NewSmallDocument() // replace with the "document" from ExampleNormalizeDocument
schemaDocument := ast.NewSmallDocument() // replace with the "schemaDocument" from ExampleNormalizeDocument

normalizer := astnormalization.NewWithOpts(
astnormalization.WithExtractVariables(),
astnormalization.WithInlineFragmentSpreads(),
astnormalization.WithRemoveFragmentDefinitions(),
astnormalization.WithRemoveNotMatchingOperationDefinitions(),
)

normalizer.NormalizeNamedOperation(operationDocument, schemaDocument, []byte("MyQuery"), report)
printer := &astprinter.Printer{}
keyGen := xxhash.New()
err := printer.Print(operationDocument, schemaDocument, keyGen)
Expand All @@ -401,7 +396,7 @@ func ExampleGenerateCacheKey() {
}

key := keyGen.Sum64()
fmt.Printf("%x", key) // Output: {cache key}
fmt.Printf("%x\n", key) // Output: {cache key}
}

/*
Expand All @@ -419,17 +414,10 @@ func ExampleGenerateCacheKeyWithStaticOperationName() {

staticOperationName := []byte("O")

operationDocument := ast.NewSmallDocument()
schemaDocument := ast.NewSmallDocument()
operationDocument := ast.NewSmallDocument() // replace with the "document" from ExampleNormalizeDocument
schemaDocument := ast.NewSmallDocument() // replace with the "schemaDocument" from ExampleNormalizeDocument
report := &operationreport.Report{}

normalizer := astnormalization.NewWithOpts(
astnormalization.WithExtractVariables(),
astnormalization.WithInlineFragmentSpreads(),
astnormalization.WithRemoveFragmentDefinitions(),
astnormalization.WithRemoveNotMatchingOperationDefinitions(),
)

// First, we add the static operation name to the document and get an "address" to the byte slice (string) in the document
// We cannot just add a string to an AST because the AST only stores references to byte slices
// Storing strings in AST nodes would be very inefficient and would require a lot of allocations
Expand All @@ -448,6 +436,13 @@ func ExampleGenerateCacheKeyWithStaticOperationName() {
operationDocument.OperationDefinitions[node.Ref].Name = nameRef
}

normalizer := astnormalization.NewWithOpts(
astnormalization.WithExtractVariables(),
astnormalization.WithInlineFragmentSpreads(),
astnormalization.WithRemoveFragmentDefinitions(),
astnormalization.WithRemoveNotMatchingOperationDefinitions(),
)

// Now we can normalize the modified document
// All Operations that don't have the name O will be removed
normalizer.NormalizeNamedOperation(operationDocument, schemaDocument, staticOperationName, report)
Expand All @@ -465,7 +460,7 @@ func ExampleGenerateCacheKeyWithStaticOperationName() {
}

key := keyGen.Sum64()
fmt.Printf("%x", key) // Output: {cache key}
fmt.Printf("%x\n", key) // Output: {cache key}
}

/*
Expand Down Expand Up @@ -495,51 +490,62 @@ so that the planner knows how to create an execution plan for the DataSource and
*/

func ExamplePlanOperation() {
staticDataSource, err := plan.NewDataSourceConfiguration[staticdatasource.Configuration](
"StaticDataSource",
&staticdatasource.Factory[staticdatasource.Configuration]{},
&plan.DataSourceMetadata{
RootNodes: []plan.TypeField{
{
TypeName: "Query",
FieldNames: []string{"hello"},
},
},
},
staticdatasource.Configuration{
Data: `{"hello":"world"}`,
},
)

config := plan.Configuration{
DataSources: []plan.DataSource{
staticDataSource,
},
Fields: []plan.FieldConfiguration{
{
TypeName: "Query", // attach this config to the Query type and the field hello
FieldName: "hello",
DisableDefaultMapping: true, // disable the default mapping for this field which only applies to GraphQL APIs
Path: []string{"hello"}, // returns the value of the field "hello" from the JSON data
},
},
IncludeInfo: true,
}
staticDataSource, err := plan.NewDataSourceConfiguration(
"StaticDataSource",
&staticdatasource.Factory[staticdatasource.Configuration]{},
&plan.DataSourceMetadata{
RootNodes: plan.TypeFields{
{
TypeName: "Query",
FieldNames: []string{"hello", "foo"},
},
},
ChildNodes: plan.TypeFields{
{
TypeName: "Foo",
FieldNames: []string{"bar"},
},
},
Comment on lines +503 to +508
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without defining child nodes, the plan action fails with

panic: internal: nodesResolvableVisitor: could not select the datasource to resolve Query.foo on a path query.foo

},
staticdatasource.Configuration{
Data: `{"hello":"world"}`,
},
)
if err != nil {
panic(err)
}
panic(err)
}

operationDocument := ast.NewSmallDocument() // containing the following query: query O { hello }
config := plan.Configuration{
DataSources: []plan.DataSource{
staticDataSource,
},
Fields: []plan.FieldConfiguration{
{
TypeName: "Query", // attach this config to the Query type and the field hello
FieldName: "hello",
DisableDefaultMapping: true, // disable the default mapping for this field which only applies to GraphQL APIs
Path: []string{"hello"}, // returns the value of the field "hello" from the JSON data
},
},
IncludeInfo: true,
}

// Assumes a document containing the following query: query O { hello }
// Replace with the "operationDocument" from ExampleGenerateCacheKeyWithStaticOperationName
operationDocument := ast.NewSmallDocument()
// Assumes a document containing the following schema: type Query { hello: String }
// Replace with the "schemaDocument" from ExampleGenerateCacheKeyWithStaticOperationName
schemaDocument := ast.NewSmallDocument()

report := &operationreport.Report{}
operationName := "O"

planner := plan.NewPlanner(context.Background(), config)
operationName := "O"
planner, err := plan.NewPlanner(config)
executionPlan := planner.Plan(operationDocument, schemaDocument, operationName, report)
if report.HasErrors() {
panic(report.Error())
}
fmt.Printf("%+v", executionPlan) // Output: Plan...
fmt.Printf("%#+v\n", executionPlan) // Output: Plan...
}

/*
Expand All @@ -548,8 +554,8 @@ This plan can now be executed by using the Resolver.
*/

func ExampleExecuteOperation() {
var preparedPlan plan.Plan
resolver := resolve.New(context.Background(), true)
var preparedPlan plan.Plan // replace with the "executionPlan" from ExamplePlanOperation
resolver := resolve.New(context.Background(), resolve.ResolverOptions{})

ctx := resolve.NewContext(context.Background())

Expand All @@ -560,7 +566,7 @@ func ExampleExecuteOperation() {
if err != nil {
panic(err)
}
fmt.Println(out.String()) // Output: {"data":{"hello":"world"}}
fmt.Println(out) // Output: {"data":{"hello":"world"}}
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am still getting an error instead of the suggested output here:

{"errors":[{"message":"String cannot represent non-string value: \"\"","path":[]}],"data":null}

I'll need more time to trace why this is happening, so in case the cause is obvious to someone, feel free to point me in the right direction.

case *plan.SubscriptionResponsePlan:
// this is a Query, so we ignore Subscriptions for now, but they are supported
}
Expand Down