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

Build Federated Schemas From Existing Schema #3013

Closed
wants to merge 13 commits into from
Closed

Build Federated Schemas From Existing Schema #3013

wants to merge 13 commits into from

Conversation

j
Copy link

@j j commented Jul 8, 2019

Hello!

So I'm implementing federation in type-graphql and saw that there's some improvements that I feel will make 3rd party libraries not using typeDefs & resolver maps for creating schemas.

This adds the ability to pass in an existing GraphQLSchema object and does the following if the argument passed to buildFederatedSchema is an instance of GraphQLSchema:

  1. Iterates over the schema's type's to get a map of the "resolveReference" functions
    1a. First checks type's resolveReference property
    1b. Checks if type has a field named __resolveReference (also deletes this field after saving the function)
  2. Creates the federation specific object types
  3. Adds the resolvers found in the schema using addResolversToSchema

Everything else stays the same. I ended up creating a utility function to all of the tests to automatically test a wrapped version of the federated schema as well as included one manual one.

This will make federation support super easy for projects like type-graphql instead of doing printSchema hacks, converting to typeDefs and plucking resolvers out to then be re-converted to SDL and schema, etc. We can then not have federation as a dependency but instead require @apollo/federation on our own app and expose the federated server.

References:
MichalLytek/type-graphql#369

Example Usage in type-graphql: MichalLytek/type-graphql@9bbed68

@j j changed the title [federation] add support for building federated schemas from existing… [Federation] add support for building federated schemas from existing schemas Jul 8, 2019
@j
Copy link
Author

j commented Jul 9, 2019

@JacksonKearl Thoughts on this?

@j
Copy link
Author

j commented Jul 10, 2019

I implemented directives into type-graphql and it made it super easy to build federated graphs this way. Here's a full working example: MichalLytek/type-graphql@9bbed68

@JacksonKearl JacksonKearl self-assigned this Jul 12, 2019
@JacksonKearl JacksonKearl requested a review from jbaxleyiii July 12, 2019 17:04
Copy link

@JacksonKearl JacksonKearl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey! Super exciting to see this coming together, it will be great to be able to federate services from even more backends. I left a few initial comments, and pinging @jbaxleyiii for a more complete review.

@j
Copy link
Author

j commented Jul 13, 2019

I can cleanup the tests. I wrapped them all just to quickly reuse the tests in place then another wrapped call which is the schema instance.

@j
Copy link
Author

j commented Jul 16, 2019

@JacksonKearl thoughts?

@j
Copy link
Author

j commented Jul 16, 2019

@JacksonKearl I cleaned the implementation up. It should be more clear on what's going on. Let me know what you think. /cc @jbaxleyiii

We feature-locked our API until this is implemented so we can move to federated services, so I'm willing to fix changes in near real time. And others using the type-graphql library will benefit from this soon! :)

Also, when graphql-js implements extensions configuration, this can be cleaned up even more. Right now I have to extract federation specific resolvers from field configuration and type properties to later remap them. When extensions comes along, then resolveReference can be invoked directly from the extensions property of the type and type.toConfig() and technically addResolversToSchema won't need to be called on already constructed schemas... it would just work! :)

@j j changed the title [Federation] add support for building federated schemas from existing schemas Build Federated Schemas From Existing Schema Jul 18, 2019
@j
Copy link
Author

j commented Jul 19, 2019

@abernix thoughts on this PR? We really want to start moving our existing servers to federation without having to use the resolvers + SDL method. Right now, you almost HAVE to convert schema to SDL + resolvers which is pretty ugly :(

@jbaxleyiii
Copy link
Contributor

@j we are going to do another pass of reviews first of next week. A few of us are out of office right now which is why there has been some delay on this review! Thank you so much for working on this, very excited to get it merged in

@j
Copy link
Author

j commented Jul 19, 2019

@jbaxleyiii Sounds good! This is going to help adoption a ton! Thanks! 🏄

@ldiego08
Copy link

Ah, this is amazing!

@j
Copy link
Author

j commented Jul 25, 2019

@ldiego08 thanks! Federation support in type-graphql will be 100% compatible when this is merged and MichalLytek/type-graphql#369 (which is pretty much done) 👍

@j
Copy link
Author

j commented Jul 26, 2019

@JacksonKearl it's saying there's changes requested still but I don't see any. I thought I resolved them all. :\

// GraphQLSchema and transform it to a federated schema.
if (modulesOrSDLOrSchema instanceof GraphQLSchema) {
return transformFederatedSchema(modulesOrSDLOrSchema, [
extractFederationResolvers(modulesOrSDLOrSchema),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this needs to be an array of GraphQLResolverMap.

// support for preserving the *uses* of federation directives while removing
// their *definitions* from the sdl.
const sdl = printSchema(schema);
const resolvers = modules
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternatively, we could merge resolvers from all modules here, so we can simplify transformFederatedSchema.

return undefined;
});

(Array.isArray(resolvers) ? resolvers : [resolvers]).forEach(map =>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be simplified if we always pass in a merged GraphQLResolverMap.

Copy link
Author

@j j Jul 31, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@martijnwalraven I was trying to keep the logic the same as what is currently happening where we're iterating over the modules and calling addResolversToSchema when module.resolvers is defined. How do you propose I merge resolvers without adding too much logic into this method. Do I iterate over resolvers, check if it's a scalar type and over-ride, otherwise do a "merge"?

@martijnwalraven
Copy link
Contributor

Note that we may soon be able to remove these workarounds and switch to using extensions instead, perhaps as soon as the end of this month: graphql/graphql-js#1527 (comment)

@pierreis
Copy link

Thank you! ♥️

@ldiego08
Copy link

💪

@joeldevelops
Copy link

+1 on this. There is a ticket at work that I'm blocked on while waiting for this PR. Trying to migrate our backend codebase to the future 💻

@eole1712
Copy link

How can I help u guys ?
Really excited to make this work, so we can start to implement federation support on type-graphql !

@snys98
Copy link

snys98 commented Aug 23, 2019

It's been about a month... I wish I could help but what is really blocking this?

@j
Copy link
Author

j commented Aug 26, 2019

@JacksonKearl I keep getting these pings of people wanting this. What are your thoughts to move forward? Extensions is out in graphql-js, so this can be cleaned up.

@trevor-scheer
Copy link
Member

@j apologies for the delay on this. We've had some discussions about upgrading the graphql version within federation and have decided that we'd like to go forward with it as we'll be using the extensions API ourselves in the near future. Are you still interested in simplifying the implementation here (and upgrading graphql peerDep to ^14.5.0)? If so, we'd love to move forward with this PR!

@itsezc
Copy link

itsezc commented Oct 22, 2019

Are there currently any updates with regards to this?

@pierreis
Copy link

pierreis commented Nov 8, 2019

Is there any way we can help this PR moving forward?

@LexSwed
Copy link

LexSwed commented Nov 21, 2019

Just to bring attention to this PR
@tjwallace do you need any help with that?

@Superd22
Copy link

@j 's fork seems to have disappeared from his GitHub, i've taken the liberty of taking his branch and rebasing on master on my own fork.

We've been using this PR internally for the last few months and would love to see it makes its way to upstream. @trevor-scheer @jbaxleyiii is the rebase enough or do you guys need the graphql-js bump & extensions rewrite to go through with it ?

@j
Copy link
Author

j commented Jan 7, 2020

Oops, @Superd22 I went on a cleaning spree. I for some reason had >200 forks. Thanks. I haven't had time to implement this as we decided this was too new and aren't implementing it at this time.

@bjanjua-inmoment
Copy link

@Superd22 / @j Great work on this. Has there been any progress with getting this into the main Apollo Server build? @Superd22 Would you have time to make a new PR for this?

@stephtr
Copy link

stephtr commented Mar 14, 2020

Would it be possible to merge this PR as it is (apart from resolving the conflicts) and work on the extensions rewrite later when someone has time?

@nivas-everest
Copy link

@j Any update on this PR. I have a similar requirement in my project. When can we expect this to be production-ready?

@j
Copy link
Author

j commented Apr 6, 2020

@nivas-everest We since then decided to not use federation until it's proven. It shouldn't be hard to build atop this.

@stephtr
Copy link

stephtr commented Apr 13, 2020

@nivas-everest We since then decided to not use federation until it's proven. It shouldn't be hard to build atop this.

If one doesn't have any experience with this codebase, at least for me it's unfortunately difficult to follow. How exactly do the extensions fit in?

@abernix abernix closed this Jun 24, 2020
@dijbi
Copy link

dijbi commented Jun 24, 2020

Fixed with an upcoming update ?

@abernix
Copy link
Member

abernix commented Jun 24, 2020

This was an unintentional closing. Please stand-by and see #4304 for more details.

(While I could put the branch back in place and re-open this right now, I'd prefer to let GitHub Support diagnose what might have gone wrong and try to explain why only a portion of pull-requests were re-targeted and the rest closed, in order to make sure the (somewhat recently introduced) pull-request re-targeting feature is working properly for other GitHub users.)

@abernix
Copy link
Member

abernix commented Jun 25, 2020

This is one of 5 PRs that I was unable to re-open after the process described #4304. The 4 others I couldn't re-open were because they had already been re-opened, and this was because the source branch had been deleted.

To preserve this, I've re-opened this as a new PR, myself, from the same ref (refs/pull/3013/head) in #4310. Please see/follow that PR for details, I'm going to lock this one to hopefully migrate the conversation there going forward. So sorry for the noise!

@apollographql apollographql locked and limited conversation to collaborators Jun 25, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.