web-ridge / gqlgen-sqlboiler Goto Github PK
View Code? Open in Web Editor NEWThis is a plugin for gqlgen to generate converts + filter queries and resolvers for sqlboiler
License: MIT License
This is a plugin for gqlgen to generate converts + filter queries and resolvers for sqlboiler
License: MIT License
For the following schema and generated query mods, sqlboiler returns an error
SELECT * FROM "deal" WHERE (creator_id = $1 AND EXISTS(SELECT 1 FROM "user" WHERE (id = $1)));
[8875fd38-b75d-45a7-a5a1-cbee58c8716d 8875fd38-b75d-45a7-a5a1-cbee58c8716d]
{"level":"error","error":"models: failed to assign all query results to Deal slice: bind failed to execute query: pq: got 2 parameters but the statement requires 1","time":"2020-05-11T07:27:58-04:00","message":"Could not list deals"}
If comment subQueryMods := UserWhereToMods(m, !hasForeignKeyInRoot)
part from function below it seem to start working
func UserWhereSubqueryToMods(m *graphql_models.UserWhere, foreignColumn string) []qm.QueryMod {
if m == nil {
return nil
}
var queryMods []qm.QueryMod
queryMods = append(queryMods)
// if foreign key exist so we can filter on ID in the root table instead of subquery
hasForeignKeyInRoot := foreignColumn != ""
if hasForeignKeyInRoot {
queryMods = append(queryMods, IDFilterToMods(m.ID, foreignColumn)...)
}
subQueryMods := UserWhereToMods(m, !hasForeignKeyInRoot)
if len(subQueryMods) > 0 {
subQuery := models.Users(append(subQueryMods, qm.Select("1"))...)
queryMods = appendSubQuery(queryMods, subQuery.Query)
}
return queryMods
}
type Deal {
id: ID!
creator: User!
negotiation: Negotiation
agreement: Agreement
updatedAt: Int!
createdAt: Int!
agreements: [Agreement]
appointments: [Appointment]
negotiations: [Negotiation]
userDeals: [UserDeal]
}
input DealFilter {
search: String
where: DealWhere
}
input DealWhere {
id: IDFilter
creator: UserWhere
negotiation: NegotiationWhere
agreement: AgreementWhere
updatedAt: IntFilter
createdAt: IntFilter
agreements: AgreementWhere
appointments: AppointmentWhere
negotiations: NegotiationWhere
userDeals: UserDealWhere
or: DealWhere
and: DealWhere
}
type Query {
deals(filter: DealFilter): [Deal!]!
}
We now have some check for userId, organizationId, userOrganizationId which are used at webRidge.
This won't work for other thing like authorId, or creatorId. User from a GraphQL api is generally not allowed to put this field inside of the api, this field needs to be resolved based on auth context or something else.
We need to support his use case by deprecating the userId, organizationId, userOrganizationId fields https://github.com/web-ridge/gqlgen-sqlboiler/blob/master/resolver.gotpl#L110.
Instead user would be allowed to put a resolver config object inside the convert_plugin.go
Instead of
api.AddPlugin(gbgen.NewResolverPlugin(
convertHelpersDir,
sqlboilerDir,
gqlgenModelDir,
"github.com/yourauth/implementation" // leave empty if you don't have auth
)),
Maybe something like this
api.AddPlugin(gbgen.NewResolverPlugin(
convertHelpersDir,
sqlboilerDir,
gqlgenModelDir,
&gqlgen.ResolverConfig{
[]CustomImport{
{
Alias: "auth",
Package: "github.com/yourauth/implementation",
},
},
[]ResolveIDs{
{
BoilerColumnName: "userID",
Resolver: "auth.UserIDFromContext",
NullResolver: "auth.NullableUserIDFromContext",
},
}
)),
Since you are fighting my own battles (gqlgen and go) can I ask you how are you dealing with the hot topic of validations?
E.g. from your example:
input ImageCreateInput {
postId: ID!
views: Int
originalUrl: String
}
how to validate that e.g. views
is max = 30
or originalUrl != ""
?
When I filter on
query{
flowBlocks(filter:{
where: {
block:{
title:{
equalTo: "Wat wil je reinigen?"
}
}
}
}){
id
flow{
title
}
block{
id
title
organization{
id
}
}
}
}
It results in the following query:
SELECT *
FROM `flow_block`
WHERE `flow_block`.`organization_id` = 1
AND ( EXISTS(SELECT 1
FROM `block`
WHERE ( title = 'Wat wil je reinigen?' )) );
This results in all almost all flowblocks returning while it should only return flowblocks which contain a block with this title so the query should be:
SELECT *
FROM `flow_block`
WHERE `flow_block`.`organization_id` = 1
AND ( EXISTS(SELECT 1
FROM `block`
WHERE ( title = 'Wat wil je reinigen?' )
AND `flow_block`.`block_id` = `block`.`id`) );
Hey, trying out your library and experiencing a few issues. Looking for help debugging what's going on.
I'm assuming there is something strange with my DB schema (Postgres). Wondering if you can offer any advice on how to debug. Using this library will save me tons of time. Happy to dig in but thought you might see some obvious issues.
When I run the plugin I get the following panic
% go run convert_plugin.go
[convert] get boiler models
[convert] get extra's from schema
[convert] get model with information
[WARN] boiler name not available for RecipeBatch.Additives
[WARN] boiler name not available for RecipeBatch.Fragrances
[WARN] boiler name not available for RecipeBatch.Lipids
[WARN] boiler type not available for Lye
[WARN] boiler name not available for RecipeBatch.Lye
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x8 pc=0x130bcda]
goroutine 1 [running]:
github.com/web-ridge/gqlgen-sqlboiler/v2.getConvertConfig(0x0, 0x0, 0x0, 0xc00010d440, 0xc0008fb680, 0x1, 0x13edb77, 0x26, 0xc0008edfa0, 0x17, ...)
/Users/steve/src/github.com/sjhitchner/gqlgen-sqlboiler/convert.go:863 +0x78a
github.com/web-ridge/gqlgen-sqlboiler/v2.enhanceModelsWithFields(0x0, 0x0, 0x0, 0xc00029c5c0, 0xc0000d0c60, 0xc000301400, 0x6c, 0x80)
/Users/steve/src/github.com/sjhitchner/gqlgen-sqlboiler/convert.go:455 +0xa89
github.com/web-ridge/gqlgen-sqlboiler/v2.GetModelsWithInformation(0x0, 0x0, 0x0, 0xc0000d0c60, 0xc000358000, 0x12, 0x12, 0x0, 0x5, 0x8)
/Users/steve/src/github.com/sjhitchner/gqlgen-sqlboiler/convert.go:158 +0xe2
github.com/web-ridge/gqlgen-sqlboiler/v2.(*ConvertPlugin).MutateConfig(0xc0001a4310, 0xc0000d0c60, 0xc0001a4310, 0x27870a8)
/Users/steve/src/github.com/sjhitchner/gqlgen-sqlboiler/convert.go:193 +0x491
github.com/99designs/gqlgen/api.Generate(0xc0000d0c60, 0xc0000eff48, 0x2, 0x2, 0x1, 0x1)
/Users/steve/go/pkg/mod/github.com/99designs/[email protected]/api/generate.go:65 +0x676
main.main()
/Users/steve/src/github.com/sjhitchner/soapcalc/backend/convert_plugin.go:34 +0x255
exit status 2
There is panic is because field.BoilerField.Relationship.Name
is nil. Should this ever happen?
https://github.com/web-ridge/gqlgen-sqlboiler/blob/main/convert.go#L863
I wrapped that line in a nil check to stop the panic but get the following error when I run the plugin again.
[resolver] generate file
error!!
resolvergen: convert.gotpl: template: convert.gotpl:27:19: executing "convert.gotpl" at <$.Backend.Directory>: can't evaluate field Backend in type *gqlgen_sqlboiler.ResolverBuild
exit status 3
This is the plugin configuration
output := gbgen.Config{
Directory: "generated/graphql/helpers",
PackageName: "helpers",
}
backend := gbgen.Config{
Directory: "generated/db/models",
PackageName: "models",
}
frontend := gbgen.Config{
Directory: "generated/graphql/models",
PackageName: "gmodels",
}
I used the https://github.com/web-ridge/sqlboiler-graphql-schema
library is generate my graphql schema and got a similar nil error
https://github.com/web-ridge/sqlboiler-graphql-schema/blob/main/main.go#L714
relationType := boilerField.Relationship.Name
Which I changed to
relationType := boilerField.RelationshipName
This change successfully generated a valid schema but needed a few edits to deal with pluralizations, and remove relationships that I didn't want to expose.
I could post the DB schema and graphql schema but the files are over 1000 lines.
Library is very cool. Glad to help out debugging!
func BooleanFilterToMods(m *graphql_models.BooleanFilter, column string) []qm.QueryMod {
return nil
}
8:15PM DBG [resolver] generate file
8:15PM ERR could not parse golang file error="src.go:1:1: expected 'package', found 'EOF'"
error while trying generate resolver and converts
resolver-webridge: errors while writing template to E:/server/resolver.go writeError: ,
contentError: formatting: 38:14: unknown escape sequence, importError: E:/server/resolver.go:38:14: unknown escape sequence
exit status 3
And this is the contents of Resolver.go:
"
package
"
It looks like there is a typo in go.mod
as v0.1.2
is the latest published version of github.com/gertd/go-pluralize
In some cases function itself assigned instead of its result.
In other cases it just inserts coma
Some referenced functions do not actually exist in boilergql
package
We have also failed some difficulties with referencing ID type. For some reason gqlgen-sqlboiler
generates it as uint
even though in models generated by sqlboiler
it definitely specified as string
Samples of the issue
Works the same as convert overrides looks in package for other resolver names, if they exist it will still generate the resolver but the overrided resolver will be commented out
I'll try to explain myself fully.
In my current code, I do the following when sending data to the client;
Here is the external model being constructed from the database model
I use the unique UUID as the identifier when referring to it on the end client.
Example uID:
'90c1939d-3414-11eb-8ffe-0242ac120005'
Do a three-way-diff merge for changes and let user choose parts of code which should not take over generated code.
{defaultNameOfResolver}_custom.go
Every function which is stated there will be skipped in generation.
Do we have an example of how to manage a one-to-many model?
Example: an invoice with multiple rows. When I create or update an invoice the rows are saved or modified or deleted at the same time.
It would be nice to sort on columns maybe even more than 1 if you want it. And would be cool if it was type safe in graphql schema.
sort: {
by: [name]
type: ASC | DESC
}
Your work is amazing!
It feels like every line of code is sweaty. ๐
A huge thank you for all this.
In a few hours I want to start a project with this.
convert_plugin.go
I have to write an additional argument for gbgen.NewConvertPlugin
. What should I write there?I undertake to write documentation for every single thing I learn, day after day: explanations that maybe those who created it take for granted, recipes for routine things etc.
But we have to decide where to write them: one thing that doesn't steal more than 10 minutes of setup. A Gitbook on github pages?
How to write business logic after all the generation?
Example:
If I'm creating a Player for a Team I wanna check if Team has enough "space" before (in a simple DB transaction).
Is this eventuality considered? I think so, of course. I just don't know where to start. ๐ข
Have you ever needed to use something for tenants in the DB?
Something like https://github.com/influitive/apartment for Rails.
Quite simply adding WHERE tenant_id = [ID]
to each DB query and the same for insert/update/delete queries.
Thanks again for this huge huge huge work! ๐
We need to fix filters when model has string primary id's instead of uints
#12 (comment)
Piggy backing off my issue on your examples: web-ridge/gqlgen-sqlboiler-examples#2
and this issue: #3
Is this library able to work outside of the GOPATH while using modules?
I created a simple example that attempts to use postgres. Unfortunately, I haven't been able to get it to work at all. It panics everytime I go go run convert_plugin.go
go run convert_plugin.go
[convert] get boiler models
[convert] get extra's from schema
[convert] get model with information
[convert] render preload.gotpl
renderError template.gotpl: template: template.gotpl:26:3: executing "template.gotpl" at <reserveImport $.BackendModelsPath>: error calling reserveImport: empty ambient import
[convert] render convert.gotpl
renderError template.gotpl: template: template.gotpl:27:3: executing "template.gotpl" at <reserveImport $.BackendModelsPath>: error calling reserveImport: empty ambient import
[convert] render convert_input.gotpl
renderError template.gotpl: template: template.gotpl:27:3: executing "template.gotpl" at <reserveImport $.BackendModelsPath>: error calling reserveImport: empty ambient import
[convert] render filter.gotpl
renderError template.gotpl: template: template.gotpl:26:3: executing "template.gotpl" at <reserveImport $.BackendModelsPath>: error calling reserveImport: empty ambient import
panic: recursive or concurrent call to RenderToFile detected
Would love some insight here.
Example prpoject: https://github.com/randallmlough/gql-boil-psql
mods := boilergql.GetPreloadModsWithLevel(ctx, AgreementPreloadMap, AgreementPayloadPreloadLevels.Agreement)
There is expected one more argument level
E.g. it understands if
organization{
galleryItemId:
}
galleryItem{
id:
}
But not
organization{
logoId:
}
galleryItem{
id:
}
type IDFilter struct {
EqualTo *string `json:"equalTo"`
NotEqualTo *string `json:"notEqualTo"`
In []string `json:"in"`
NotIn []string `json:"notIn"`
}
func IDFilterToMods(m *graphql_models.IDFilter, column string) []qm.QueryMod {
if m == nil {
return nil
}
var queryMods []qm.QueryMod
if m.EqualTo != nil {
queryMods = append(queryMods, qmhelper.Where(column, qmhelper.EQ, boilergql.IDToBoiler(*m.EqualTo)))
}
if m.NotEqualTo != nil {
queryMods = append(queryMods, qmhelper.Where(column, qmhelper.NEQ, boilergql.IDToBoiler(*m.NotEqualTo)))
}
if len(m.In) > 0 {
queryMods = append(queryMods, qm.WhereIn(column+in, boilergql.IDsToBoilerInterfaces(m.In)...))
}
if len(m.NotIn) > 0 {
queryMods = append(queryMods, qm.WhereIn(column+notIn, boilergql.IDsToBoilerInterfaces(m.NotIn)...))
}
return queryMods
}
expected
func IDFilterToMods(m *graphql_models.IDFilter, column string) []qm.QueryMod {
if m == nil {
return nil
}
var queryMods []qm.QueryMod
if m.EqualTo != nil {
queryMods = append(queryMods, qmhelper.Where(column, qmhelper.EQ, *m.EqualTo))
}
if m.NotEqualTo != nil {
queryMods = append(queryMods, qmhelper.Where(column, qmhelper.NEQ, *m.NotEqualTo))
}
if len(m.In) > 0 {
queryMods = append(queryMods, qm.WhereIn(column+in, boilergql.IDsToInterfaces(m.In)...))
}
if len(m.NotIn) > 0 {
queryMods = append(queryMods, qm.WhereIn(column+notIn, boilergql.IDsToInterfaces(m.NotIn)...))
}
return queryMods
}
undefined: boilergql.PointerIntToTimeTime
graph/helpers/convert.go:238:14: undefined: boilergql.PgeoNullPointToInt
graph/helpers/convert.go:451:14: undefined: boilergql.NullDotFloat32ToPointerFloat64
graph/helpers/convert.go:452:14: undefined: boilergql.NullDotInt16ToPointerInt
graph/helpers/convert.go:500:19: undefined: boilergql.NullDotFloat32ToPointerFloat64
graph/helpers/convert.go:501:19: undefined: boilergql.NullDotInt16ToPointerInt
graph/helpers/convert.go:502:19: undefined: boilergql.NullDotFloat32ToPointerFloat64
graph/helpers/convert.go:503:19: undefined: boilergql.NullDotInt16ToPointerInt
graph/helpers/convert_input.go:186:3: cannot use boilergql.IDToNullBoiler(boilergql.PointerStringToString(m.MeetingID)) (type null.Uint) as type null.String in field value
graph/helpers/convert_input.go:254:3: cannot use boilergql.IDToNullBoiler(boilergql.PointerStringToString(m.MeetingID)) (type null.Uint) as type null.String in field value
graph/helpers/convert_input.go:256:14: undefined: boilergql.PointerIntToTimeTime
I got a wrong schema which I think it is caused due to bug while parsing the boiler struct. As you see below I have a field UserID which is not parsed correctly and eventually results to wrong generated field and empty type. Some other irrelevant part of the structs are omitted.
sqlboiler:
type Member struct {
UserID int `boil:"user_id" json:"user_id" toml:"user_id" yaml:"user_id"`
Username string `boil:"username" json:"username" toml:"username" yaml:"username"`
RealName string `boil:"real_name" json:"real_name" toml:"real_name" yaml:"real_name"`
}
generated
type Member {
user: !
username: String!
realName: String!
}
Following transformation functions not declared by package boilergql ("github.com/web-ridge/utils-go/boilergql/v3/convert.go")
Float32ToFloat64
Float64ToFloat32
PointerFloat64ToFloat32
PointerIntToInt8
PointerIntToUint
UintToString
StringToUint
PointerStringToUint
PointerStringToNullDotJSON
PointerStringToTypesJSON
StringToTypesJSON
TypesJSONToString
Special case this one, In order to get the SQLBoiler type, null.JSON to pass the schema step, I added a condition to output the json type as a string field.
Not sure how to fix this problem, I was thinking the library could just send out the value of the json object as a string, or undefined/empty if !Valid or null (github.com/volatiletech/null/v8/json.go)
UserIDFromContext
seems to be required with 2 different returns types:
Is issue coming from our schema? or it something generated inappropriately?
If I attempt to put the outputted helpers dir as a sub directory, for example graph/helpers
then the helpers package name will be package graph/helpers
which obviously doesn't work
func main() {
cfg, err := config.LoadConfigFromDefaultLocations()
if err != nil {
fmt.Fprintln(os.Stderr, "failed to load config", err.Error())
os.Exit(2)
}
convertHelpersDir := "graph/helpers"
sqlboilerDir := "models"
gqlgenModelDir := "graphql_models"
err = api.Generate(cfg,
api.AddPlugin(gbgen.NewConvertPlugin(
convertHelpersDir, // directory where convert.go, convert_input.go and preload.go should live
sqlboilerDir, // directory where sqlboiler files are put
gqlgenModelDir, // directory where gqlgen models live
)),
// ...
Preload generating generates too much preload code. We need something else at runtime to prevent too much generated clutter: https://github.com/web-ridge/gqlgen-sqlboiler-examples/blob/master/social-network/helpers/preload.go
{"level":"error","error":"obj type should be *Type, *[]Type, or *[]*Type but was \"[]boilergql.RemovedStringID\"","time":"2020-05-22T20:19:54Z","message":"could not delete dealSearchStates"}
Generated code is
var IDsToRemove []boilergql.RemovedStringID
if err := dm.UserSocials(mods...).Bind(ctx, r.db, IDsToRemove); err != nil {
log.Error().Err(err).Msg(publicUserSocialBatchDeleteError)
return nil, errors.New(publicUserSocialBatchDeleteError)
}
expected code
var IDsToRemove []boilergql.RemovedStringID
if err := dm.UserSocials(mods...).Bind(ctx, r.db, &IDsToRemove); err != nil {
log.Error().Err(err).Msg(publicUserSocialBatchDeleteError)
return nil, errors.New(publicUserSocialBatchDeleteError)
}
Thanks for this amazing library!
Currently when executing go run convert_plugin.go
I'm getting the following error
panic: recursive or concurrent call to RenderToFile detected
my gqlgen.yml looks like this
schema:
- schema.graphql
exec:
filename: graphql/generated.go
package: graphql
model:
filename: graphql/models/generated_models.go
package: gqlmodels
resolver:
filename: graphql/resolver.go
type: Resolver
any idea why this would be an issue?
Implement https://graphql.org/learn/global-object-identification/ to fully support Relay.dev and other specs
Saw your issue at 99designs/gqlgen#646, i can't use LGPL. Can you do MIT (same license as gqlgen)?
I'm getting this error now:
9:43PM DBG write GraphQL schema to disk bytes=7869 file=schema.graphql
9:43PM DBG [convert] get boiler models
9:43PM DBG [convert] get extra's from schema
9:43PM DBG [convert] get model with information
9:43PM WRN no models found in graphql so skipping generation
9:43PM DBG [resolver] get boiler models
9:43PM DBG [resolver] get models with information
9:43PM DBG [resolver] generate file
error while trying generate resolver and converts
validation failed: packages.Load: resolver.go:6:2: package api_gqlgen_sqlboiler/helpers is not in GOROOT (c:\go\src\api_gqlgen_sqlboiler\helpers)
C:\api-gqlgen-sqlboiler\resolver.go:6:4: could not import api_gqlgen_sqlboiler/helpers (invalid package name: "")
C:\api-gqlgen-sqlboiler\resolver.go:19:10: undeclared name: queryResolver
C:\api-gqlgen-sqlboiler\resolver.go:19:77: Node not declared by package graphql_models
C:\api-gqlgen-sqlboiler\resolver.go:6:2: "api_gqlgen_sqlboiler/helpers" imported but not used
exit status 3
I'm using this go.mod file:
module api_gqlgen_sqlboiler
go 1.15
require(...)
It would be nice to be able to customize the package the helper package / funcs return. From what I can tell it will always assume the package name is graphql_models
even if I change the directory to be app
as shown below.
func main() {
cfg, err := config.LoadConfigFromDefaultLocations()
if err != nil {
fmt.Fprintln(os.Stderr, "failed to load config", err.Error())
os.Exit(2)
}
convertHelpersDir := "helpers"
sqlboilerDir := "models"
gqlgenModelDir := "app"
err = api.Generate(cfg,
api.AddPlugin(gbgen.NewConvertPlugin(
convertHelpersDir, // directory where convert.go, convert_input.go and preload.go should live
sqlboilerDir, // directory where sqlboiler files are put
gqlgenModelDir, // directory where gqlgen models live
)),
If this package name could be customized or at least respect the gqlgenModelDir
variable that would be nice
https://github.com/web-ridge/gqlgen-sqlboiler/blob/master/convert.gotpl#L31
I see some fields in the schema.graphql
are written everytime in different order.
input UserWhere {
id: IDFilter
email: StringFilter
password: StringFilter
updatedAt: IntFilter // this is here now
createdAt: IntFilter
}
input UserWhere {
id: IDFilter
email: StringFilter
password: StringFilter
createdAt: IntFilter
updatedAt: IntFilter // this is here now
}
And so on...
This is a problem as you can imagine.
when i run convert_plugin.go after setting up everything i encounter this error
[covert] render filter.gotp; renderError template.gotpl: template: template.gotpl:27:3: executing "template.gotpl" at <reserveImport $.BackendModelsPath>: error calling reserveImport: empty ambient import
Model with composite primary key incorrectly referred to by non existent single field "ID"
Take a model with two primary keys called "ThreadVote"
ThreadID
UserID
CreatedAt
Vote
Parts of the generated code incorrectly assumes that it has a single primary key called ID,
For example instead of
dm.ThreadVoteWhere.ThreadID AND dm.ThreadVoteWhere.UserID
It refers to the table by
dm.ThreadVoteWhere.ID.EQ(dbID)
Key translations in mutations are also not generated
For example;
dbID := ThreadVoteID(id)
Does not exist.
Following the new Readme I'm getting this error:
failed to load config file does not exist
.
I think we need a config file but there is no mention in the Readme.
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?
Line 191 in 049ffb3
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?
cd example/social-network && go run convert_plugin.go
go: gitlab.com/webridge-git/[email protected]: reading https://goproxy.cn/gitlab.com/webridge-git/api/@v/v0.0.0-20181123203207-501884b46b27.mod: 404 Not Found
Does gqlgen-sqlboiler currently support the generation of offset pagination resolvers?
I see that sqlboiler-graphql-schema can generate a schema with offset pagination support but the resolvers are not getting created when I run convert.
I didn't see the generation of pagination resolvers on the roadmap or done, so I figured I would ask to see if I'm just missing something or if this feature is not available.
Thanks.
Not sure if this is the right place for the issue. So direct me if I'm wrong. But as the resolver is generated by gqlgen-sqlboiler
it might be the right spot.
Example below returns all fields from the database, but should return empty list
query {
deals(filter: {
where: {
creator: {
id: {
#equalTo: ""
}
}
}
}){
id
}
}
When we re-run the go run convert_plugin.go
there is everytime changes since maps are random in golang. That means that there is a lot of diff change while in reality nothing has changed only the order of preloads.
From v3:
9:52PM DBG write GraphQL schema to disk bytes=6293 file=schema.graphql
9:52PM DBG [convert] get boiler models
9:52PM DBG [convert] get extra's from schema
9:52PM DBG [convert] get model with information
9:52PM DBG [convert] render preload.gotpl
9:52PM DBG [convert] render convert.gotpl
9:52PM DBG [convert] render convert_input.gotpl
9:52PM DBG [convert] render filter.gotpl
9:52PM DBG [convert] render sort.gotpl
9:52PM DBG [resolver] get boiler models
9:52PM DBG [resolver] get models with information
9:52PM DBG [resolver] generate file
error while trying generate resolver and converts
validation failed: packages.Load: C:\api-gqlgen-sqlboiler\resolver.go:129:25: RemovedIDsToBoilerInt64 not declared by package boilergql
C:\api-gqlgen-sqlboiler\resolver.go:136:18: Int64IDsToGraphQL not declared by package boilergql
C:\api-gqlgen-sqlboiler\resolver.go:245:25: RemovedIDsToBoilerInt64 not declared by package boilergql
C:\api-gqlgen-sqlboiler\resolver.go:252:18: Int64IDsToGraphQL not declared by package boilergql
C:\api-gqlgen-sqlboiler\resolver.go:361:25: RemovedIDsToBoilerInt64 not declared by package boilergql
C:\api-gqlgen-sqlboiler\resolver.go:368:18: Int64IDsToGraphQL not declared by package boilergql
exit status 3
I think it should be possible to have a blacklist/whitelist for the models I want to convert from sqlboiler ones.
Is it already possible today?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.