I’m a bit confused about lacinia’s support for directives. They are parsed, and I believe you can access them in resolvers, but is it also possible to add global behaviour to them?
For example, GitHub’s schema defines a custom @possibleTypes
directive that constraints inputs of type ID
to references to particular concrete or abstract types, say @possibleTypes(concreteTypes: ["User"])
. Is that something I can do in Lacinia?
How about wrapping all of your resolvers before handing the schema to compile
?
This is what I'm working at; however I think ultimately there will be a callback that allows you to wrap all resolvers in the schema that have directives on them, so that we could leverage the new APIs recently introduced to expose directives.
At some point, we either need to add some new abstractions to allow directives to manipulate the intermediate representation of the schemas and queries, or document and stabilize the data structures that are present.
The goal would be that application-specific directives could do anything the built in @include and @skip directives do (though note that those are called out specially in the spec).
In any case, currently left as an exercise for the reader.
Hmm yeah, I could wrap all my mutations, and check ID’s to be of some particular concrete type (as far as I can tell, there are no resolvers for input types, so has to be mutations I guess). I found GHs example with the custom directive pretty elegant, so I was also wondering whether that was possible too ^^
For queries, you can check the all the arguments in the field resolvers, no? @lennart.buit
Right, yeah. I can add validation logic to all my mutation resolvers to check that global id’s are of the correct types. I was hoping to do it declaratively & automatically generate validation logic. For example, this is a simple mutation in ‘GH’ style (as per their publicly available schema), so I was specifically wondering whether I could implement a similar directive with Lacinia:
mutation {
addLabelToLabelable(input: AddLabelToLabelableInput!): AddLabelToLabelablePayload!
}
type AddLabelToLabelablePayload {
labelable: Labelable
}
input AddLabelToLabelableInput {
id: ID! @possibleTypes(abstractType: "Labelable") # Validation failure if you give some global id that is not considered Labelable. I'd assume automatically checked.
label: String
}
(I thought it was an interesting approach, so I was just wondering whether it is possible, haha 🙂!)
For an easy API, I see this in the manual: > Directive support is evolving quickly; full support for directives, including argument type validation, is forthcoming (emphasis mine)
Otherwise, if you can't wait, changing line 54 would enable you to add your own validations: https://github.com/walmartlabs/lacinia/blob/master/src/com/walmartlabs/lacinia.clj#L30-L62
I think I may be able to combine both :thinking_face:, do indeed map over the mutation resolvers, and generate new ones that check in the selections whether there are directives and if so check the validation rules of those directives on inputs (I’m hopeful that https://github.com/walmartlabs/lacinia/pull/335 helps me in that!). Thanks!