99designs / 99designs/gqlgen

Force Generating Models Doesn't Work with Go Field Force Resolver Directive

未关闭
#3,241 0 条评论 2 个 reaction 已指派 0 人 在 GitHub 查看
主要语言
Go
星标
10.8k
派生
1.3k
平均合并
2 天 36 分钟
30 天内合并 PR
26

描述

### What happened?

I am building a GraphQL schema that makes a lot of use of interfaces and relations, where my internal models don't quite match up with the GQL representation so I need GQLGen to generate these models. For that I used the `@goModel(forceGenerate: true)` directive on my model which works fine.

However, the schema also has a lot of relations that need to be returned in field resolvers which is where I would want to use the `@goField(forceResolver: true)` directive.

If I combine the two it seems no model is generated, and GQLGen errors out with:

```go
merging type systems failed: unable to bind to interface: github.com/Dan6erbond/gqlgen-force-directives-playground/models.PrivateTodo does not satisfy the interface github.com/Dan6erbond/gqlgen-force-directives-playground/graph/model.Todo
exit status 1
graph\resolver.go:1: running "go": exit status 1
```

### What did you expect?

I expected GQLGen to generate the models and the resolvers.

Without the `@goField` directive it works fine, I get these models:

```go
type PrivateTodo struct {
ID string `json:"id"`
Text string `json:"text"`
Done bool `json:"done"`
User *User `json:"user"`
}

func (PrivateTodo) IsTodo() {}

type ProjectTodo struct {
ID string `json:"id"`
Text string `json:"text"`
Done bool `json:"done"`
User *User `json:"user"`
Project *Project `json:"project"`
}

func (ProjectTodo) IsTodo() {}
```

The current workaround I have is configuring the models and resolvers via the `gqlgen.yml` file, but with how large our API is, it's getting bloated and I'd prefer to make use of directives.

### Minimal graphql.schema and models to reproduce

Schema:

```gql
directive @goModel(
model: String
models: [String!]
forceGenerate: Boolean
) on OBJECT | INPUT_OBJECT | SCALAR | ENUM | INTERFACE | UNION

directive @goField(
forceResolver: Boolean
name: String
omittable: Boolean
) on INPUT_FIELD_DEFINITION | FIELD_DEFINITION

directive @goTag(
key: String!
value: String
) on INPUT_FIELD_DEFINITION | FIELD_DEFINITION

directive @goExtraField(
name: String
type: String!
overrideTags: String
description: String
) on OBJECT | INPUT_OBJECT

interface Todo
@goModel(
model: "github.com/Dan6erbond/gqlgen-force-directives-playground/graph/model.Todo"
) {
id: ID!
text: String!
done: Boolean!
user: User!
}

type PrivateTodo implements Todo @goModel(forceGenerate: true) {
id: ID!
text: String!
done: Boolean!
user: User! @goField(forceResolver: true)
}

type ProjectTodo implements Todo @goModel(forceGenerate: true) {
id: ID!
text: String!
done: Boolean!
user: User! @goField(forceResolver: true)
project: Project! @goField(forceResolver: true)
}

type User {
id: ID!
name: String!
}

type Project {
id: ID!
name: String!
}

type Query {
todos: [Todo!]!
}

input NewTodo {
text: String!
userId: String!
}

type Mutation {
createTodo(input: NewTodo!): Todo!
}
```

Models:

```go
package models

type Todo struct {
Type string
PrivateTodo
ProjectTodo
}

type PrivateTodo struct {
Text string
Done bool
UserID uint
}

type ProjectTodo struct {
Text string
Done bool
UserID uint
ProjectID uint
}
```

> **Important**: Enable the autobinding on the models folder so that GQLGen skips generating the `PrivateTodo` and `ProjectTodo` models by default.
> ```yml
> autobind:
> - "github.com/Dan6erbond/gqlgen-force-directives-playground/graph/model"
> - "github.com/Dan6erbond/gqlgen-force-directives-playground/models"
> ```

I have a sandbox repo [here](https://github.com/Dan6erbond/gqlgen-force-directives-playground) that showcases the issue on `main` and shows the workaround on [`feature/without-force-resolver`](https://github.com/Dan6erbond/gqlgen-force-directives-playground/tree/feature/without-force-resolver).

### versions
- `go run github.com/99designs/gqlgen version`: v0.17.49
- `go version`: go version go1.22.3 windows/amd64

贡献指南

打开贡献指南

评估

这个 Issue 还没有评估数据。

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。