entgql: How to get Edge Schema fields in GraphQL?
I defined three schemas: User, Tweet, and Like. Like is Edge Schema.
I want to send the following query using GraphQL. However, There is no liked_at in the graphql file.
users {
likedTweets {
id # ok
text #ok
likedAt # not ok
}
}
Please tell me how to get liked_at.
repository: https://github.com/nomikura/ent-example
Schema
type User struct {
ent.Schema
}
func (User) Fields() []ent.Field {
return []ent.Field{
field.String("name").
Default("Unknown"),
}
}
func (User) Edges() []ent.Edge {
return []ent.Edge{
edge.To("liked_tweets", Tweet.Type).
Through("likes", Like.Type),
}
}
func (User) Annotations() []schema.Annotation {
return []schema.Annotation{
entgql.QueryField(),
entgql.RelayConnection(),
}
}
type Tweet struct {
ent.Schema
}
func (Tweet) Fields() []ent.Field {
return []ent.Field{
field.Text("text"),
}
}
func (Tweet) Edges() []ent.Edge {
return []ent.Edge{
edge.From("liked_users", User.Type).
Ref("liked_tweets").
Through("likes", Like.Type),
}
}
type Like struct {
ent.Schema
}
func (Like) Annotations() []schema.Annotation {
return []schema.Annotation{
field.ID("user_id", "tweet_id"),
}
}
func (Like) Fields() []ent.Field {
return []ent.Field{
field.Time("liked_at").
Default(time.Now),
field.Int("user_id"),
field.Int("tweet_id"),
}
}
func (Like) Edges() []ent.Edge {
return []ent.Edge{
edge.To("user", User.Type).
Unique().
Required().
Field("user_id"),
edge.To("tweet", Tweet.Type).
Unique().
Required().
Field("tweet_id"),
}
}
Generated GraphQL file
directive @goField(forceResolver: Boolean, name: String) on FIELD_DEFINITION | INPUT_FIELD_DEFINITION
directive @goModel(model: String, models: [String!]) on OBJECT | INPUT_OBJECT | SCALAR | ENUM | INTERFACE | UNION
"""
Define a Relay Cursor type:
https://relay.dev/graphql/connections.htm#sec-Cursor
"""
scalar Cursor
"""
An object with an ID.
Follows the [Relay Global Object Identification Specification](https://relay.dev/graphql/objectidentification.htm)
"""
interface Node @goModel(model: "entdemo/ent.Noder") {
"""The id of the object."""
id: ID!
}
"""Possible directions in which to order a list of items when provided an `orderBy` argument."""
enum OrderDirection {
"""Specifies an ascending order for a given `orderBy` argument."""
ASC
"""Specifies a descending order for a given `orderBy` argument."""
DESC
}
"""
Information about pagination in a connection.
https://relay.dev/graphql/connections.htm#sec-undefined.PageInfo
"""
type PageInfo {
"""When paginating forwards, are there more items?"""
hasNextPage: Boolean!
"""When paginating backwards, are there more items?"""
hasPreviousPage: Boolean!
"""When paginating backwards, the cursor to continue."""
startCursor: Cursor
"""When paginating forwards, the cursor to continue."""
endCursor: Cursor
}
type Query {
"""Fetches an object given its ID."""
node(
"""ID of the object."""
id: ID!
): Node
"""Lookup nodes by a list of IDs."""
nodes(
"""The list of node IDs."""
ids: [ID!]!
): [Node]!
users(
"""Returns the elements in the list that come after the specified cursor."""
after: Cursor
"""Returns the first _n_ elements from the list."""
first: Int
"""Returns the elements in the list that come before the specified cursor."""
before: Cursor
"""Returns the last _n_ elements from the list."""
last: Int
): UserConnection!
}
type Tweet implements Node {
id: ID!
text: String!
likedUsers: [User!]
}
type User implements Node {
id: ID!
name: String!
likedTweets: [Tweet!]
}
"""A connection to a list of items."""
type UserConnection {
"""A list of edges."""
edges: [UserEdge]
"""Information to aid in pagination."""
pageInfo: PageInfo!
"""Identifies the total count of items in the connection."""
totalCount: Int!
}
"""An edge in a connection."""
type UserEdge {
"""The item at the end of the edge."""
node: User
"""A cursor for use in pagination."""
cursor: Cursor!
}
to a list of items."""
type UserConnection {
"""A list of edges."""
edges: [UserEdge]
"""Information to aid in pagination."""
pageInfo: PageInfo!
"""Identifies the total count of items in the connection."""
totalCount: Int!
}
"""An edge in a connection."""
type UserEdge {
"""The item at the end of the edge."""
node: User
"""A cursor for use in pagination."""
cursor: Cursor!
}
Hey @a8m ✋
Thank you for adding support for Relay Connection in Edge Schema in the previous pull request! (https://github.com/ent/contrib/pull/403)
I've tried it in https://github.com/nomikura/ent-example, but the codegen fails with the following error message.
$ go generate -x ./...
go run -mod=mod entc.go
2023/05/16 11:56:20 running ent codegen: entgql.RelayConnection() must be set on entity "Tweet" in order to define "User"."liked_tweets" as Relay Connection
exit status 1
gen/generate.go:3: running "go": exit status 1
Annotations have been added to the User schema, Tweet schema and Like schema. Could you advise on how to proceed for the codegen to succeed?
schema files: https://github.com/nomikura/ent-example/tree/main/ent/schema User schema:
func (User) Fields() []ent.Field {
return []ent.Field{
field.String("name").
Default("Unknown"),
}
}
func (User) Edges() []ent.Edge {
return []ent.Edge{
edge.To("liked_tweets", Tweet.Type).
Through("likes", Like.Type).
Annotations(entgql.RelayConnection()), // add
}
}
func (User) Annotations() []schema.Annotation {
return []schema.Annotation{
entgql.QueryField(),
entgql.RelayConnection(),
}
}
Tweet schema:
func (Tweet) Fields() []ent.Field {
return []ent.Field{
field.Text("text"),
}
}
func (Tweet) Edges() []ent.Edge {
return []ent.Edge{
edge.From("liked_users", User.Type).
Ref("liked_tweets").
Through("likes", Like.Type),
}
}
func (Tweet) Annotation() []schema.Annotation {
return []schema.Annotation{
entgql.RelayConnection(), // add
}
}
Like schema:
func (Like) Fields() []ent.Field {
return []ent.Field{
field.Time("liked_at").
Default(time.Now),
field.Int("user_id"),
field.Int("tweet_id"),
}
}
func (Like) Edges() []ent.Edge {
return []ent.Edge{
edge.To("user", User.Type).
Unique().
Required().
Field("user_id"),
edge.To("tweet", Tweet.Type).
Unique().
Required().
Field("tweet_id"),
}
}
func (Like) Annotation() []schema.Annotation {
return []schema.Annotation{
entgql.RelayConnection(), // add
}
}
Removing the compound ID field.ID("user_id", "tweet_id") and using the autogenerated ID allowed graphql generation to work correctly for me.