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

Wrap mode for replace-field transform #3498

Closed
avallete opened this issue Jan 19, 2022 · 11 comments
Closed

Wrap mode for replace-field transform #3498

avallete opened this issue Jan 19, 2022 · 11 comments

Comments

@avallete
Copy link

Is your feature request related to a problem? Please describe.

I am currently using graphql-mesh as a proxy in front of an hasura. Since the schema.graphql is automatically generated by hasura API and sometimes mismatch what I would like to consume, it would be convenient to use the "replace-field" to "correct" the types of hasura.

Example:

type file {
    # This type is automatically generated by Hasura as a parameterizable query returning an array
    # Even if in code implementation, I do know this will always return an array of 1 element
    last_version(order_by: ....): [file_version!]
}
## What I would like to replace it by
type file {
    last_version: file_version!
}

Then into the resolver:

{
  last_version: next => async (root, args, context, info) => {
    // 'next' is the field resolve function
    const last_version = await next(root, args, context, info);
    return last_version[0];
  }
}

Describe the solution you'd like
As for now, the "replace-field" transform, only work properly with the "bare" mode, which is incompatible with an "already graphql" API. It would be perfect if it work the same with "wrap" mode, or if we had an alternative to achieve what I want to do.

Describe alternatives you've considered
I've tried to check on additional-resolvers but they don't seem fit to my need.

Additional context
From my tests, for now, the "replace-field" transform works well with "graphql" API as long as the "schema types rewriting" goes (I've been able to replace the type of last_version with the one I wanted). However, it does crash at runtime when trying to get the value.

@ardatan
Copy link
Owner

ardatan commented Jan 19, 2022

We'd love to accept a PR for this feature :)

@santino
Copy link
Contributor

santino commented Jan 19, 2022

@ardatan I think we should come back to the plan of splitting Replace Field transform with two different transforms.

The first step is to look at this PR which I had ready in Mid November (hence might need some updates, but it's there):
#3185

The second step is to look into the Hoist Field transform, which has a PR by @ntziolis in #2862
I haven't looked much into this yet, but assume it should be easy to get in.

I believe that Hoist Field transform might be enough to cover the use-case for this issue.

@santino
Copy link
Contributor

santino commented Jan 19, 2022

Actually, Hoist Field transform might not be enough for this use-case.

@avallete have you tried extending the schema to introduce a new field?
You can then add an additional resolver for this new field and finally use the filter schema transform to remove the field that you wanted to replace.

You can take a look at this guide for some references.
I assume you'd need to do something like this

# meshrc.yaml

  transforms:
    - filterSchema:
        filters:
          - File.!last_version

additionalTypeDefs: |
  extend type File {
    latest_version: file_version!
  }
additionalResolvers:
  - ./src/mesh/additional-resolvers.js
// src/mesh/additional-resolvers.js

const resolvers = {
  File: {
    latest_version: (root, args, context, info) => {
      return root.last_version[0];
    }
  }
}

module.exports = { resolvers };

It might sound like more work, but It's actually similar since even with the Replace field Transform you'd have to write the additional type and additional resolver.

I think this might help, but didn't try, so give it a go and let us know.

@avallete
Copy link
Author

@santino

Your solution works perfectly ! Thanks for your minimal example ! I did try something similar went I stumbled upon the guide that you linked but I wasn't able to make it work.

It may be a good thing to link with a similar example that you provided to the "replace-field" docs section. To explain that this is a good alternative for graphql api's.

@santino
Copy link
Contributor

santino commented Jan 19, 2022

Glad it worked.

Replace Field transform is very powerful, but I believe that with can cover most scenarios with better distributed Transforms, like Transforms Schema and Hoist Field.
Anything that's not covered by those can be most likely handled as I suggested here, with the addition of a new field/resolver.

Once we move forward with those Transforms, I will look into updating the documentation to hopefully make things more explicit.

@mbrowne
Copy link

mbrowne commented Mar 30, 2022

Is it possible to use this technique to override a field with a type that doesn't exist in the original schema?

For example...original schema:

type Artwork {
    id: ID!
    title: String!
}

Filter:

    transforms:
      - filterSchema:
          filters:
            - Artwork.!title

additionalTypeDefs:

extend type Artwork {
    title: TextDisplayField!
}

type TextDisplayField {
    label: String
    value: String!
}

This works fine if I override Artwork.title and set it to an Int type for example, but when I set the return type to TextDisplayField as shown above, I get this error:

No type was found for field node { kind: "Field", alias: undefined, name: { kind: "Name", value: "label" }, arguments: [], directives: [], selectionSet: undefined }

@santino
Copy link
Contributor

santino commented Mar 30, 2022

What you are describing seems mostly a schema extension rather than a field replacement.
I think you can still filter out the title sub-field like you are describing, then you can simply extend your schema to introduce a new title subfield.

The guide for schema extensions is here, take a look at it and have a play.
Let me know how you get on.

@mbrowne
Copy link

mbrowne commented Mar 30, 2022

Thanks...how would that be different from what I'm already doing, where I have extend type Artwork in additionalTypeDefs?

@mbrowne
Copy link

mbrowne commented Mar 31, 2022

Should I open a new issue about this? I'm just trying to use additionalTypeDefs and additionalResolvers in a simple way to override the existing field. It seems possible it could be a bug.

@ardatan
Copy link
Owner

ardatan commented Mar 31, 2022

Ok this issue seems too heated. So please create a new issue with a clear and minimal reproduction.

@ardatan ardatan closed this as completed Mar 31, 2022
@mbrowne
Copy link

mbrowne commented Mar 31, 2022

Ok I opened a new issue here:
#3788

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

4 participants