Is there a way to create nested queries with Connectors without using entities?
For example, for the given schema below, I would like to have byId and search to be nested within the WidgetMethods type for organization and namespacing purposes.
type Query {
widgets: WidgetMethods
}
type WidgetMethods {
byId(id: ID!): Widget!
@connect(
source: "widgets"
http: { GET: "/byId/{$args.id}" }
selection: """
id
name
description
"""
)
search(term: String!): [Widget!]
@connect(
source: "widgets"
http: { GET: "/search?term={$args.term}" }
selection: """
id
name
description
"""
)
}
type Widget {
id: ID!
name: String!
description: String
}
However, this schema causes the language server to throw the following error:
CONNECTORS_UNRESOLVED_FIELD: [template] No connector resolves field `Query.widgets`. It must have a `@connect` directive or appear in `@connect(selection:)`.
No matter what I do, I cannot come up with a Connector for the widgets field that will allow me to trigger the Connectors on the nested fields. I know I could move the Connectors up a level but then the widgets field would need to accept optional parameters for every possible query necessary for the child fields.
type Query {
widgets(id: ID, term: String): WidgetMethods
@connect(
source: "widgets"
http: { GET: "/byId/{$args.id}" }
selection: """
byId: {
id
name
description
}
"""
)
@connect(
source: "widgets"
http: { GET: "/search?term={$args.term}" }
selection: """
search: {
id
name
description
}
"""
)
}
type WidgetMethods {
byId: Widget!
search: [Widget!]
}
type Widget {
id: ID!
name: String!
description: String
}
Is there a way to accomplish this without grouping parameters and without using entities?
Hello! We have something on the roadmap for this and would love your feedback. The general idea is allow connectors that don’t make a network request, but just act as a kind of resolver in the router.
As you can see, there’s one gotcha about needing a useless field (because from the query planner’s perspective, Query.widgets returns a type with no fields, which isn’t valid GraphQL). But would that solve your use case?
Thanks for getting back to me! I love the idea of allowing connectors to not make a network request and I would definitely use that feature.
I do not think it solves the issue on its own though. I simulated your proposed solution with a connector that makes a network request and I got the following error:
error: Composition failed.
error[E029]: Encountered 2 build errors while trying to build a supergraph.
Caused by:
SATISFIABILITY_ERROR: The following supergraph API query:
{
widgets {
byId(id: "<any id>") {
...
}
}
}
cannot be satisfied by the subgraphs because:
- from subgraph "template":
- cannot find field "WidgetMethods.byId".
- cannot move to subgraph "template", which has field "WidgetMethods.byId", because type "WidgetMethods" has no @key defined in subgraph "template".
SATISFIABILITY_ERROR: The following supergraph API query:
{
widgets {
search(term: "A string value") {
...
}
}
}
cannot be satisfied by the subgraphs because:
- from subgraph "template":
- cannot find field "WidgetMethods.search".
- cannot move to subgraph "template", which has field "WidgetMethods.search", because type "WidgetMethods" has no @key defined in subgraph "template".
It seems like there would need to be an update to the compiler to be able to detect when connectors are applied to child types in the case they are not resolved from a parent type. It may even be desirable to have connectors on child types override ones on parent types if they are defined on both.
That tells the query planner how to deal with the relationship between the WidgetMethods returned by the root field and the WidgetMethods with a byId field. We would remove the need for this workaround when we tackle this roadmap item.
The workaround worked for me! I am not sure if my team will want to put it into production until the pattern is addressed by the roadmap item but it is definitely useful for prototyping solutions.