[GraphQL Plugin] Add ability for post-/pre- processing values
Motivation
Some times you want to modify a value that comes from the backstage catalog. You probably would add a resolver for specific field, but you couldn't. It's because if you use @field or @relation directives for that field, the graphql plugin will add a resolver and your resolver will conflict with it.
Approach
We can add pre and post hooks that duplicate schema structure:
const hooks = {
pre: {
Entity: (entity: Entity) => ({ ...entity, id: encodeEntityId(entity) }),
post: {
Component: {
tag: (tag: string, entity: Entity) => ({ id: encodeId({ key: 'tag.label', value: tag }), label: tag })
}
}
}
Here you can see that in pre.Entity hook we add new field id to the entity. There is no reason to add field specific pre-hooks. But maybe it should be better to rename them to interfaces and fields hooks. For the post.Component.tag field we change a type from string to { id: string, label: string } and then new value is used as a result of resolver. The idea is use pre hook for adding/removing fields from source object and post for transforming a specific field value.
With graphql best practice fetching data at field level https://medium.com/paypal-tech/graphql-resolvers-best-practices-cd36fdbcef55 it makes difficult to use post hooks on fields with @relation directives. And pre hooks are more suitable for this case.
Alternative approach
Instead of having that structure we can allow to pass an array of transformers:
const preHooks = [
{
predicate: (interface: string, entity: Entity) => interface == 'Entity', /* isSpecificEntity(entity) */
transform: (entity: Entity) => ({ ...entity, id: encodeEntityId(entity) })
}
]
const postHooks = [
{
predicate: (field: string, interface: string, entity: Entity) => interface == 'Component' && field == 'tag',
transform: (value: any, entity: Entity) => ({ id: encodeId({ key: 'tag.label', value: tag }), label: tag })
}
]
I'd like the first variant, but, the second one is more flexible, it allows apply transformations according a data.