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

NewResolverPlugin issue #48

Open
sjhitchner opened this issue Dec 29, 2020 · 11 comments
Open

NewResolverPlugin issue #48

sjhitchner opened this issue Dec 29, 2020 · 11 comments
Labels
question Further information is requested

Comments

@sjhitchner
Copy link
Contributor

Hey, finally got time to come back to using gqlgen-sqlboiler.

I'm running into another issue.

Here is my convert_plugin.go

package main

import (
	"fmt"
	"os"

	"github.com/99designs/gqlgen/api"
	"github.com/99designs/gqlgen/codegen/config"
	gbgen "github.com/web-ridge/gqlgen-sqlboiler/v3"
)

func main() {
	cfg, err := config.LoadConfigFromDefaultLocations()
	if err != nil {
		fmt.Fprintln(os.Stderr, "failed to load config", err.Error())
		os.Exit(2)
	}

	output := gbgen.Config{
		Directory: "generated/graphql/helpers",
		// Directory:   "helpers", // supports root or sub directories
		PackageName: "helpers",
	}

	backend := gbgen.Config{
		Directory: "generated/db/models",
		// Directory:   "models",
		PackageName: "models",
	}

	frontend := gbgen.Config{
		Directory: "generated/graphql/models",
		// Directory:   "graphql_models",
		PackageName: "gqlmodels",
	}

	if err = gbgen.SchemaWrite(
		gbgen.SchemaConfig{
			BoilerModelDirectory: backend,
			// Directives:           []string{"IsAuthenticated"},
			// GenerateBatchCreate:  false, // Not implemented yet
			GenerateMutations:   true,
			GenerateBatchDelete: false,
			GenerateBatchUpdate: false,
		},
		"schema/schema.graphqls",
		gbgen.SchemaGenerateConfig{
			MergeSchema: false, // uses three way merge to keep your customization
		},
	); err != nil {
		fmt.Println("error while trying to generate schema.graphql")
		fmt.Fprintln(os.Stderr, err.Error())
		os.Exit(3)
	}

	if err = api.Generate(cfg,
		api.AddPlugin(gbgen.NewConvertPlugin(
			output,   // directory where convert.go, convert_input.go and preload.go should live
			backend,  // directory where sqlboiler files are put
			frontend, // directory where gqlgen models live
			gbgen.ConvertPluginConfig{
				//UseReflectWorkaroundForSubModelFilteringInPostgresIssue25: true, // see issue #25 on GitHub
			},
		)),
		api.AddPlugin(gbgen.NewResolverPlugin(
			output,
			backend,
			frontend,
			"", // leave empty if you don't have auth
		)),
	); err != nil {
		fmt.Println("error while trying generate resolver and converts")
		fmt.Fprintln(os.Stderr, err.Error())
		os.Exit(3)
	}
}

When I run it I get the following output/error

% go run convert_plugin.go
...
9:53PM DBG write GraphQL schema to disk bytes=36923 file=schema/schema.graphqls
9:53PM DBG [convert] get boiler models
9:53PM DBG [convert] get extra's from schema
9:53PM DBG [convert] get model with information
9:53PM DBG [convert] render preload.gotpl
9:53PM DBG [convert] render convert.gotpl
9:53PM DBG [convert] render convert_input.gotpl
9:53PM DBG [convert] render filter.gotpl
9:53PM DBG [convert] render sort.gotpl
9:54PM DBG [resolver] get boiler models
9:54PM DBG [resolver] get models with information
9:54PM DBG [resolver] generate file
error while trying generate resolver and converts
resolvergen: convert.gotpl: template: convert.gotpl:30:18: executing "convert.gotpl" at <.Enums>: can't evaluate field Enums in type *gbgen.ResolverBuild
exit status 3

It seems strange to me that the resolver is using the convert.gotpl so I dug in a little further.

This Render statement doesn't include a Template option is this ok?

err := templates.Render(templates.Options{

Locally I modified that file to

		err := templates.Render(templates.Options{
			Template:    getTemplate("resolver.gotpl"),
			PackageName: data.Config.Resolver.Package,
			PackageDoc: `
				// This file will be automatically regenerated based on the schema, any resolver implementations
				// will be copied through when generating and any unknown code will be moved to the end.`,
			Filename: filename,
			Data:     resolverBuild,
			Packages: data.Config.Packages,
		})

When I run convert_plugin.go using the modified file I get the following output

% go run convert_plugin.go
...
9:57PM DBG write GraphQL schema to disk bytes=36923 file=schema/schema.graphqls
9:58PM DBG [convert] get boiler models
9:58PM DBG [convert] get extra's from schema
9:58PM DBG [convert] get model with information
9:58PM DBG [convert] render preload.gotpl
9:58PM DBG [convert] render convert.gotpl
9:58PM DBG [convert] render convert_input.gotpl
9:58PM DBG [convert] render filter.gotpl
9:58PM DBG [convert] render sort.gotpl
gofmt failed on schema.resolvers.go: /Users/steve/src/github.com/sjhitchner/soapcalc/backend/graphql/resolver/schema.resolvers.go:475:8: expected 'IDENT', found '=' (and 607 more errors)
9:58PM DBG [resolver] get boiler models
9:58PM DBG [resolver] get models with information
9:58PM DBG [resolver] generate file
gofmt failed on schema.resolvers.go: /Users/steve/src/github.com/sjhitchner/soapcalc/backend/graphql/resolver/schema.resolvers.go:64:8: expected 'IDENT', found '=' (and 911 more errors)
error while trying generate resolver and converts
validation failed: packages.Load: /Users/steve/src/github.com/sjhitchner/soapcalc/backend/graphql/resolver/schema.resolvers.go:64:8: expected 'IDENT', found '='
/Users/steve/src/github.com/sjhitchner/soapcalc/backend/graphql/resolver/schema.resolvers.go:64:8: missing constant value
/Users/steve/src/github.com/sjhitchner/soapcalc/backend/graphql/resolver/schema.resolvers.go:64:10: expected ';', found ""
/Users/steve/src/github.com/sjhitchner/soapcalc/backend/graphql/resolver/schema.resolvers.go:69:8: expected 'IDENT', found '='
/Users/steve/src/github.com/sjhitchner/soapcalc/backend/graphql/resolver/schema.resolvers.go:69:8: missing constant value
/Users/steve/src/github.com/sjhitchner/soapcalc/backend/graphql/resolver/schema.resolvers.go:69:10: expected ';', found ""
/Users/steve/src/github.com/sjhitchner/soapcalc/backend/graphql/resolver/schema.resolvers.go:74:8: expected 'IDENT', found '='
/Users/steve/src/github.com/sjhitchner/soapcalc/backend/graphql/resolver/schema.resolvers.go:74:8: missing constant value
/Users/steve/src/github.com/sjhitchner/soapcalc/backend/graphql/resolver/schema.resolvers.go:74:10: expected ';', found ""
/Users/steve/src/github.com/sjhitchner/soapcalc/backend/graphql/resolver/schema.resolvers.go:79:8: expected 'IDENT', found '='
/Users/steve/src/github.com/sjhitchner/soapcalc/backend/graphql/resolver/schema.resolvers.go:79:8: missing constant value
/Users/steve/src/github.com/sjhitchner/soapcalc/backend/graphql/resolver/schema.resolvers.go:79:10: expected ';', found ""

It looks like the template executes correctly but the resolver code generated are not valid Go.

const inputKey = "input"

const  = ""

	func (r *mutationResolver) CreateAdditive (ctx context.Context, input gmodels.AdditiveCreateInput) (*gmodels.AdditivePayload, error) {
	}

const  = ""

	func (r *mutationResolver) UpdateAdditive (ctx context.Context, id string, input gmodels.AdditiveUpdateInput) (*gmodels.AdditivePayload, error) {
	}

const  = ""

	func (r *mutationResolver) DeleteAdditive (ctx context.Context, id string) (*gmodels.AdditiveDeletePayload, error) {
	}

const  = ""

	func (r *mutationResolver) CreateAdditiveInventory (ctx context.Context, input gmodels.AdditiveInventoryCreateInput) (*gmodels.AdditiveInventoryPayload, error) {
	}

const  = ""

	func (r *mutationResolver) UpdateAdditiveInventory (ctx context.Context, id string, input gmodels.AdditiveInventoryUpdateInput) (*gmodels.AdditiveInventoryPayload, error) {
	}

Any ideas?

@RichardLindhout
Copy link
Member

Maybe I should release the development version today it has a lot of bug fixes. Anyway the code you send should never be called since multiple schemas are not supported yet (but is there since I copied code).

I will release a new version today where the resolver and template code is simplified!

@sjhitchner
Copy link
Contributor Author

Awesome, looking forward to the updated version. I'll take a look through the code today and try to understand why it's entering the multiple schema block.

Also, I have one other question. It is possible to disable generating an edges/connections schema in v3? For my particular projects edges/connections add unneeded complexity. I took a look through the code but didn't see an obvious flag.

Thanks again!

@RichardLindhout
Copy link
Member

It should be in gqlgen.yml, in the new version it does not look at this file but generates only 1 file for now.

@sjhitchner I think I'll keep the edges since we need them. I won't work on disabling this via a flag. But feel free to make a pull request which has a flag for this or something like that but be sure to make it for everything (the schema generator + resolver + converts)

Most of the time pagination is needed after a while in a project so I think it's good + it's fast with cursor-based pagination out of the box e.t.c.

Do you not need pagination or do you think the connections/edges are just too complex? ( I agree on that, but it has some reasons for that)

@RichardLindhout
Copy link
Member

I forgot about this, I'll try to release tomorrow!

@sjhitchner
Copy link
Contributor Author

I definitely think pagination support is essential. The edges/connections model does provide that but with much more complex queries. I believe React/Relay requires edges/connections. But I've just used Apollo client so far which seems much simpler (I am NOT an expert with JS/React, so my opinions might be invalid).

I've added pagination in the past by adding limit and from parameters on the list options. That seemed to work fine and give me the functionality I needed.

I can see the reason to conform to a more industry standard approach. I just was curious if library supported removing them.

@RichardLindhout
Copy link
Member

Yeah to be honest with you I think the Relay specification is overengineered to handle very niche cases. But if you have them you can query the cursor on them. The arguments to the connections are simplified since relay does not support both forward and backward pagination as arguments.

So if you have first: 10, after: "sljdflksj==" it will use forward pagination and last:10 before: "slsl==" it will use backward pagination.

It implements the following spec: https://relay.dev/graphql/connections.htm

@RichardLindhout
Copy link
Member

New version is released. Please follow upgrade notes and let me know if this fixed it for you.

cfg, err := config.LoadConfigFromDefaultLocations() (convert_plugin.go) should be placed after if err := gbgen.SchemaWrite(gbgen.SchemaConfig{

Like in the updated README.md maybe this resulted in your error.

@RichardLindhout RichardLindhout added the question Further information is requested label Dec 30, 2020
@sjhitchner
Copy link
Contributor Author

Awesome, thanks for the update. Definitely making some progress but I have encountered a few more issues I'm trying to sort out.

Missing imports:

.../helpers/convert.go
.../helpers/convert_input.go
.../helpers/filter.go
.../helpers/sort.go
../helpers/preload.go

Are missing the graphql model and db model import statements in my case:

gqlmodels github.com/sjhitchner/soapcalc/backend/generated/graphql/models"
dbmodels github.com/sjhitchner/soapcalc/backend/generated/db/models"

Also resolver.go needs to import the generated graphql code

// needs to import "gm github.com/sjhitchner/soapcalc/backend/generated/graphql"

func (r *Resolver) Mutation() fm.MutationResolver { return &mutationResolver{r} }     // should be gm not fm
func (r *Resolver) Query() fm.QueryResolver       { return &queryResolver{r} }             // should be gm not fm

type mutationResolver struct{ *Resolver }
type queryResolver struct{ *Resolver }

I think this may be just be template issues.

Making the manual changes above I get everything to compile and runs!

@sjhitchner
Copy link
Contributor Author

I think this fixes the issues I was experiencing in the above post

#50

@sjhitchner
Copy link
Contributor Author

The only issue I'm facing right now is that when I run the plugin go run convert_plugin.go two resolver files are generated

resolver.go
schema.resolver.go

There are a number of errors about how various objects are defined twice and schema.resolver.go is missing a number of imports.

If, after running the plugin, I delete schema.resolver.go everything compiles.

Is it expected behaviour for both resolvers to be generated. If not, any ideas what I have misconfigured?

@RichardLindhout
Copy link
Member

I think the gqlgen file should only contain this for the resolver key

resolver:
  filename: resolver.go
  type: Resolver

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants