Centralize `load(ids) => Node` on the Node
mxstbr opened this issue · comments
I don't know if this is possible, but defining .load
on every t.loadable
is seemingly unnecessary duplication since the node itself could define how to load itself.
I.e. instead of
builder.objectField(LaunchNode, 'rocket', (t) =>
t.loadable({
type: RocketNode,
resolve: (parent) => {
return parent.rocket.rocket_id
},
load: async (ids: string[]) => {
return Promise.all(ids.map((id) => rocketsDatasources.getOne(id)))
},
}),
)
It would be
const RocketNode = node('Rocket', rocketsDatasources).implement({
isTypeOf: () => true,
fields: (t) => ({
cost: t.exposeInt('cost_per_launch'),
country: t.exposeString('country'),
company: t.exposeString('company'),
description: t.exposeString('description'),
}),
// This data loader applies to all t.loadable definitions with RocketNode
load: async (ids: string[]) => {
return Promise.all(ids.map((id) => rocketsDatasources.getOne(id)))
},
}),
})
builder.objectField(LaunchNode, 'rocket', (t) =>
t.loadable({
type: RocketNode,
resolve: (parent) => {
return parent.rocket.rocket_id
},
}),
)
Then, the question becomes: do we still need the distinction between t.field
and t.loadable
or could we just have t.field
? That would further simplify the API surface area to:
builder.objectField(LaunchNode, 'rocket', (t) =>
t.field({
type: RocketNode,
resolve: (parent) => {
return parent.rocket.rocket_id
},
}),
)
This indeed works, I don't know why it did not work before
Amazing! @JoviDeCroock does this work outside of a datasource with a manual .load
definition too?
If you explicitly declare load
it won't work so it's needed on a t.field
, i.e. you need tor resolve the id
and it will go back to the node
So this wouldn't work? (without a datasource)
const RocketNode = node('Rocket').implement({
isTypeOf: () => true,
fields: (t) => ({
cost: t.int(),
country: t.string(),
company: t.string(),
description: t.string(),
}),
// This data loader applies to all t.loadable definitions with RocketNode
load: async (ids: string[]) => {
return Promise.all(ids.map((id) => getRocket(id)))
},
}),
})
builder.objectField(LaunchNode, 'rocket', (t) =>
t.loadable({
type: RocketNode,
resolve: (parent) => {
return parent.rocket.rocket_id
},
}),
)
I mean, it would but I don't see the point of it tbh 😅 so we would allow consumers to optionally override load
and not pass in a datasource
?