Skip to content

[Feature Request] Apollo Federation Support #297

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

Open
nihalgonsalves opened this issue Oct 28, 2019 · 8 comments
Open

[Feature Request] Apollo Federation Support #297

nihalgonsalves opened this issue Oct 28, 2019 · 8 comments

Comments

@nihalgonsalves
Copy link

Apollo Federation makes uses of some custom directives:

https://www.apollographql.com/docs/apollo-server/federation/federation-spec/

Version and Environment Details

Operation system: macOS

IDE name and version: IntelliJ IDEA Ultimate 2019.2

Plugin version: 2.2.0

Expected Behaviour

  1. The following directives should not produce errors:

    directive @external on FIELD_DEFINITION
    directive @requires(fields: _FieldSet!) on FIELD_DEFINITION
    directive @provides(fields: _FieldSet!) on FIELD_DEFINITION
    directive @key(fields: _FieldSet!) on OBJECT | INTERFACE
    directive @extends on OBJECT | INTERFACE

    (These directives must NOT be in the GraphQL file itself)

  2. An extend type TypeName should be allowed to exist without the base type, as the base type may be defined by another service

Actual Behaviour

  1. Error: Unknown directive "XXX"
  2. Error: The extension 'TypeName' type [@x:x] is missing its base underlying type

Steps to Reproduce / Link to Repo with Reproduction and Instructions

type InternalType @key(fields: "id") {
  id: ID!
  xyz: String!
  externalObject: ExternalType @requires(fields: "xyz") @provides(fields: "foo")
}

# In reality you need EITHER extend OR @extends
# depending on which server this schema is defined in
# (Apollo Server allows extend, graphql-java requires @extends)
extend type ExternalType @key(fields: "id") @extends {
  id: ID! @external
  foo: String! @external
  bar: String! @external
  baz: String!
}
@jimkyndemeyer
Copy link
Collaborator

Hi Nihal.

Thanks for using the plugin.

Like you mention, these directives are custom, and the plugin only ships with the directives that are described in the GraphQL spec. This is intentional, as new GraphQL frameworks appear all the time. For this reason you have to declare framework directives yourself, and ensure that they're picked up as part of schema discovery. You can look at an example at https://github.com/jimkyndemeyer/graphql-config-examples/tree/master/extend-client-fields-and-directives which shows how to work with the @client Apollo directive.

Extending non-existing types violates the GraphQL Spec https://graphql.github.io/graphql-spec/June2018/#sec-Object-Extensions validation "The named type must already be defined and must be an Object type." As such, graphql-java which this plugin is based on works correctly, so I'm not sure how we would go about adding support for this. Potentially the validation needs to be configurable as it makes sense to enforce it for other use cases.

I noted one interesting comment in your code example:

# (Apollo Server allows extend, graphql-java requires @extends)

If you declared your directives as expected, and used @extends I believe the plugin would work as is.

Best regards,
Jim

@nihalgonsalves
Copy link
Author

Thanks for the detailed response! I completely understand that you wouldn't want to add these directives by default.

However, since Apollo Federation has gathered quite a bit of support (including graphql-ruby, graphql-java, graphql-kotlin, gqlgen (go), graphene (python), and graphql-dotnet), I believe it would make sense to integrate this here so that users can easily build Federated schemas.

Regarding the extend: while building an API with graphql-java, this is fine as you have to use @extends, however, Apollo Server users would use extend type for Federation, so it would be nice to have the option to turn off the base type validation in this case. I suppose this would however involve contributing to graphql-java and making it possible to turn off this validation here: SchemaTypeChecker.java#L74

@paulschwarz
Copy link

Looking at the examples of how to configure and extend the plugin (https://github.com/jimkyndemeyer/graphql-config-examples) perhaps a boilerplate example for Apollo Federation would help people get started.

@quintstoffers
Copy link

quintstoffers commented Sep 17, 2020

If you declared your directives as expected, and used @extends I believe the plugin would work as is.

Perhaps I'm doing something wrong, but declaring a type in service A and then extending it using @extends (which is also supported by Apollo) in service B does result in an error:

Service A

    type Foo @key(fields: "id") {
        id: ID!
    }

Service B

    type Foo @extends @key(fields: "id") {
        id: ID! @external
    }

Directives

directive @key(fields: _FieldSet!) on OBJECT | INTERFACE
directive @extends on OBJECT | INTERFACE

'Foo' type [@66:5] tried to redefine existing 'Foo' type [@13:5]

EDIT:

As a workaround I made some slight changes to my structure and .graphqlconfig. I created a directory remote where I define extended remote types using the @extend directive. The rest of the service uses the extend keyword to add additional fields. In .graphqlconfig I exclude the remote directories using **/remote/**.

@vepanimas
Copy link
Collaborator

vepanimas commented Sep 17, 2020

@quintstoffers some work has been done recently in this PR #374 in 2.6.0, and we plan to continue our work on the schema splitting in different scenarios, but that's a huge amount of work. At this point, a dependency on the underlying graphql-java library is more a problem, than a time-saver.

One of the next steps I believe would be disabling this kind of error 'Foo' type [@66:5] tried to redefine existing 'Foo' type [@13:5] (there are also more possible "something duplicated" errors) and implementing native inspections, which could be configurable and will honor semantics of different frameworks.

@smyrick
Copy link
Contributor

smyrick commented Dec 8, 2022

For those looking Federation 1 directives can now be toggled on with the new setting: #499

Federation 2 support and more importantly @link is not yet enabled: #627

@dbanty
Copy link

dbanty commented Feb 7, 2023

It looks like Federation 2 support is included in plugin version 3.4.0! Make sure to enable the setting in Languages & Frameworks > GraphQL, there's a checkbox called "Federation" (or just search settings for "Federation").

@pfyod
Copy link

pfyod commented May 16, 2023

It would be great if the fields attribute in @requires / @provides and @key had syntax highlighting and auto-completion in the editor. E.g. here:

type A {
    foo: String
}

type B {
    a: A
    bar: String @requires(fields: 
    """
    a {
        foo
    }
    """)
}

fields content should should be navigable / auto-completable like a GraphQL query.

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

No branches or pull requests

8 participants