You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This PR is a proposition to solve a long standing DX issue: sharing data between ALL hooks of a plugin.
Context
Today, the only relyable way to share data between the hooks of a plugin is to use WeakMap with the GraphQL context as key:
functionusePlugin(): Plugin{newdataByContext=newWeakMap<any,{foo: string}>();return{onParse({ context }){dataByContext.set(context,{foo: 'bar');},onValidate({ context }){constdata=dataByContext(context);if(data){// We even have to check for its existence, even it should always be defined.console.log(data)}}}
In Yoga, it's even worse since in most Yoga specific hooks, the graphql context is not built yet, so the only thing shared by all hooks is the HTTP request:
functionusePlugin(): YogaPlugin{newdataByRequest=newWeakMap<Request,{foo: string}>();return{onRequestParse({ request }){dataByRequest.set(request,{foo: 'bar');},onValidate({ context }){constdata=dataByRequest(context.request);if(data){// We even have to check for its existence, even it should always be defined.console.log(data)}}}
But this can be misleading: If batching is enabled, multiple different operation will share the same data. We currently have multiple plugins that are using this technique and that are open to bugs when batching is enabled.
Proposition
My proposal is to add a dedicated API directly in the core of Envelop, Yoga and Hive to have a streamlined way of sharing data between hooks. While the WeakMap trick works, it's really not very good DX, and is very error prone.
The API would be a data field that will be present in ALL hooks (for Envelop hooks, but also Yoga and Hive hooks).
To emphases the fact that there is potentially multiple level of data sharing (operation wide, http request wide, subgraph execution wide), this data object would contain a field for each scope:
This data would then be available in all hooks, but depending of the hook, not all scopes will be available.
functionmyPlugin(): HivePlugin{return{onRequestParse({ data }){// only data.forRequest is available},onExecute({ data }){// both data.forRequest and data.forOperation are available},onSubgraphExecute({ data }){// all scopes are available: data.forRequest, data.forOperation and data.forSubgraphExecution},}
Of course, it will also imply adding generic types everywhere. And this is probably a bit tricky because it will imply adding more generics to existing Plugin type, which I'm not sure if it is non-breaking or not.
As a proof of concept, I've implemented the first step of this proposal: the Envelop scope (#2405)
The text was updated successfully, but these errors were encountered:
Description
This PR is a proposition to solve a long standing DX issue: sharing data between ALL hooks of a plugin.
Context
Today, the only relyable way to share data between the hooks of a plugin is to use
WeakMap
with the GraphQL context as key:In Yoga, it's even worse since in most Yoga specific hooks, the graphql context is not built yet, so the only thing shared by all hooks is the HTTP request:
But this can be misleading: If batching is enabled, multiple different operation will share the same data. We currently have multiple plugins that are using this technique and that are open to bugs when batching is enabled.
Proposition
My proposal is to add a dedicated API directly in the core of Envelop, Yoga and Hive to have a streamlined way of sharing data between hooks. While the
WeakMap
trick works, it's really not very good DX, and is very error prone.The API would be a
data
field that will be present in ALL hooks (for Envelop hooks, but also Yoga and Hive hooks).To emphases the fact that there is potentially multiple level of data sharing (operation wide, http request wide, subgraph execution wide), this
data
object would contain a field for each scope:This
data
would then be available in all hooks, but depending of the hook, not all scopes will be available.Of course, it will also imply adding generic types everywhere. And this is probably a bit tricky because it will imply adding more generics to existing Plugin type, which I'm not sure if it is non-breaking or not.
As a proof of concept, I've implemented the first step of this proposal: the Envelop scope (#2405)
The text was updated successfully, but these errors were encountered: