So i feel like my question is most likely a JS syntax question regarding classes and this
but my issue is directly related to graphql-tools
class SchemaDirectiveVisitor
which is used for creating custom directives in GraphQL.
A little context: When making a custom directive in GraphQL one way is to extend the SchemaDirectiveVisitor class provided by graphql-tools, and override any of their default methods which can be applied to different locations of a gql schema. More specifics can be seen here
In my specific case, i am using the method visitInputFieldDefinition
because i want to add some custom logic that will validate whether a user has permission to edit a particular field or not. The main issue with visitInputFieldDefinition
is that it only seems to be firing when the server is being built, since it has no resolver function. Meanwhile, other methods such as visitFieldDefinition
does have a resolve()
function that fires each time there is a new request with this directive.
What im trying to do is store some data in an array when visitInputFieldDefinition
is called which is when the server starts up, after it reads my gql schema. I am able to save some data in an array outside of the class, and then use that data in my resolve() function to determine whether to proceed or return an error. I am able to do this and it works, but MY QUESTION is actually on how can I obtain the same behavior but store this data somehow in a var within my class instead of on a global variable outside the class
So my code, simplified, looks something like this
//variable outside my class where i store in memory some data from class
let outsideVar = []
class RestrictFieldsDirective extends SchemaDirectiveVisitor {
visitFieldDefinition(field) {
const originalResolve = field.resolve || defaultFieldResolver;
field.resolve = async function(...args){
//Do Stuff here with the stored array
// return error or apply the resolver depending on data in array
if(outsideVar) //more complicated checks on data
return new ApolloError()
return resolve.apply()
}
}
visitInputFieldDefinition(field){
// Do stuff here to store data provided on application build when this method gets
called
outsideVar.push(someData)
}
}
As I mentioned, this approach is working fine for me, but i dont like the fact i have a global variable outside the class, when i would like to have it inside. I have tried to store it in a variable within the class, or even in another method within the class, but i have two issues
the class gets called multiple times when starting the server, so even if i manage to store the data within a var at the constructor level, it does not persist through multiple calls, it always gets reset if in
constructor()
i include something likethis.myVar = []
i dont seem to have access to
this
inside thefield.resolve()
function, and I can't figure out how to give it access to the classthis
so that i could either call another method or a class var such asthis.myVar
The question is mainly about a best practice, what would be a possible improvement to this that might avoid using an external global variable, or is there simply no way to do that and this approach can be deemed "correct".
Thanks for reading! Any discussion is welcome and useful!