Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[GraphQL Plugin] Add ability for post-/pre- processing values #160

Open
wKich opened this issue Nov 16, 2022 · 0 comments
Open

[GraphQL Plugin] Add ability for post-/pre- processing values #160

wKich opened this issue Nov 16, 2022 · 0 comments

Comments

@wKich
Copy link
Member

wKich commented Nov 16, 2022

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant