Any suggestions on splitting generated.go into smaller files? I have a repo with a 256kB size restriction per file.
Render() function at https://github.com/99designs/gqlgen/blob/master/codegen/templates/templates.go#L61 looked like the code that can be refactored to split a single generated.go into multiple files. However, looking at a generated.go file for one query, biggest region is field.topl and this region alone can cross 256KB.
1: 21 // region ** generated!.gotpl **
2: 1666 // region * args.gotpl *
3: 1726 // region ** directives.gotpl **
4: 1730 // region ** field.gotpl *
5: 7009 // region ** input.gotpl *
6: 7031 // region ** interface.gotpl *
7: 7035 // region ** object.gotpl **
8: 8348 // region * type.gotpl *
I have a bit of a mystery here:
The generated ResolverRoot
interface looks like this:
type ResolverRoot interface {
Query() QueryResolver
Mutation() MutationResolver
}
In addition to the Mutation() MutationResolver
and Query() QueryResolver
that I expected, there are several more interfaces e.g
type ResolverRoot interface {
// a bunch of interfaces elided
Workstation() WorkstationResolver
}
These extra interfaces define some of the behaviour of a Relay "node" (generation of object identifiers) e.g
type WorkstationResolver interface {
ID(ctx context.Context, obj *Workstation) (string, error)
}
Both apps' GraphQL schemata look similar. For both, I was trying to implement a Relay spec-compliant API.
The first app (the one that did not generate the extra interfaces and behaved as I expected) has a schema that looks like this:
interface Node {
id : ID!
}
enum SortOrder {
ASC
DESC
}
type PageInfo {
hasNextPage: Boolean!
hasPreviousPage: Boolean!
startCursor: String
endCursor: String
}
type Organization implements Node {
id: ID!
name: String!
sladeCode: String!
}
type OrganizationEdge {
cursor: String
node: Organization
}
type OrganizationConnection {
edges: [OrganizationEdge]
pageInfo: PageInfo!
}
input OrganizationFilterInput {
search : String
name: String
sladeCode: String
}
input OrganizationSortInput {
name: SortOrder
sladeCode: SortOrder
}
# a bunch of similar types have been elided
type Query {
listOrganizations(
first: Int, after: String, last: Int, before: String,
filter: OrganizationFilterInput, sort: OrganizationSortInput): OrganizationConnection!
findOrganization(id: ID!): Organization!
# A bunch of fields elided here too
}
The schema in the second app follows the same patterns.
The mystery is - what caused the second app to generate all these extra interfaces?
I am on gqlgen v0.11.2
. What should I look at?
type Workstation struct{
ID uint64
...
}
// vs
type Workstation struct{
ID string
...
}
hey guys.. im using @goField(forceResolver: true) directive to generate resolvers for relations and i have a problem
Lets say that user has a country.
In graphql its not idiomatic to have countryId, in the object, only Country.
This means that in generated resolver function (I get *generated.User) who does not have country id.
This means that i cannot easily reuse my service GetCountryById
Something
both the id
and somethingId
Is there a way to hide a field from the API user? I'm trying to achieve sort of transient data passing without needing to fully reimplement every gql model I need this for. In an optimal world, I might have something like this (see @internal
):
// schema.graphql
type User {
"id is..."
id ID!
"dbUser is..."
dbUser DBUser @internal
}
scalar DBUser @goModel(model: "github.com/my/app/models.User")
// gql_models/generated.go
type User struct {
// id is...
id string `json:"id"`
// dbUser is...
dbUser models.User `json:"-"`
}
// resolvers/user_resolver.go
func (p userResolver) Friends(ctx context.Context, user *gql_models.User) ([]gql_models.User, error) {
// use internal details of dbUser to resolve
user.dbUser
...
}
The biggest win from this approach is that there is only one source of truth for my gql models (defined in the schema). AND we can spend time writing comprehensive documentation only once (in the schema file)
So, I ended up writing a second yml file with configuration for adding arbitrary fields to generated models
# Add transient fields to the generated glq model
models:
User:
DBUser: github.com/my/package/models.User
# # Place all added fields into their own embedded struct with the following field name
# field: Internals
Then, I used a very simple plugin built off of the modelgen.Plugin
to add these fields to the models during codegen. I will be experimenting to see if there are any "gotchas" that I might have missed with this approach.
User-MacBook-Pro:test-gql user$ go run github.com/99designs/gqlgen
validation failed: packages.Load: /Users/test-gql/schema.resolvers.go:12:73: NewTodo not declared by package models
/Users/test-gql/schema.resolvers.go:12:91: Todo not declared by package models
/Users/test-gql/schema.resolvers.go:16:63: Todo not declared by package models
/Users/test-gql/schema.resolvers.go:21:31: undeclared name: generated
/Users/test-gql/schema.resolvers.go:24:28: undeclared name: generated
exit status 1
User-MacBook-Pro:test-gql user$ go run server.go resolver.go generated.go
package main: found packages main (server.go) and test_gql (resolver.go) in /Users/test-gql
- models
- person.go
- pet.go
- generated.go
- resolver.go
- server.go
- schema.graphql
- gqlgen.yml
go run .