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

Support Apollo Federation 2 #2251

Merged
merged 17 commits into from Jul 20, 2022

Conversation

greguintow
Copy link
Contributor

@greguintow greguintow commented Jun 16, 2022

PR Checklist

Please check if your PR fulfills the following requirements:

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Other... Please describe:

What is the current behavior?

Issue Number: #2141

This also fixes:

What is the new behavior?

Allows to add a property called useFed2 inside autoSchemaFile that will make the necessary schema changes to be considered a federation 2 schema:
https://github.com/greguintow/nestjs-graphql/blob/cb6090d766c78af96a628358c10d7efaca61ba9e/packages/apollo/tests/code-first-graphql-federation2/users-service/federation-users.module.ts#L12-L14

By default will add:

extend schema @link(url: "https://specs.apollo.dev/federation/v2.0", import: ["@key", "@shareable", "@external", "@override", "@requires"])

But that can be customized as useFed2 type is boolean | Federation2Config

Does this PR introduce a breaking change?

  • Yes
  • No

cc @trevor-scheer @hwillson

@ChrisBates
Copy link

As a suggestion, get rid of useFed2 and turn autoSchemaFile into boolean | SchemaFileConfig

Then SchemaFileConfig can be configurable to the role of the server - standard GQL, Federation Gateway, Subgraph, version, and whatever else might appear in the future.

Handle a autoShemaFile: true to default to the current standard functionality, and now there's a proper way to handle future changes.

@kamilmysliwiec
Copy link
Member

Thanks for your contribution @greguintow. I think @ChrisBates suggestion about using the autoSchemaFile makes sense & is more future-proof. Could you apply this change? 🤞

@greguintow
Copy link
Contributor Author

Thanks for your contribution @greguintow. I think @ChrisBates suggestion about using the autoSchemaFile makes sense & is more future-proof. Could you apply this change? 🤞

Thanks @kamilmysliwiec and @ChrisBates , I'll make the changes shortly

@greguintow
Copy link
Contributor Author

@kamilmysliwiec @ChrisBates I've finished the changes, please review it!

extend schema @link(url: "https://specs.apollo.dev/federation/v2.0", import: ["@key", "@shareable", "@external", "@override", "@requires"])
* ```
*/
useFed2?: UseFed2Value;
Copy link

@Teagan42 Teagan42 Jun 25, 2022

Choose a reason for hiding this comment

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

Not to be pedantic- but wouldn't federationVersion?: FederationVersion (an enum or similar) be more flexible to future changes?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@Teagan42 I think that we wouldn't have such a big change as we had with apollo federation 2 vs 1 in any near future. Due to to how is setup, I think would be best to just be like that

Choose a reason for hiding this comment

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

I agree with @Teagan42 - we don't know what the future brings, but we know for certain that Fed V2 won't be the latest version forever and we'll eventually need to deprecate a useFed2 property. At least federationVersion can have the default updated to adopt the current version, and overwritten for backward compatibility (where people need it).

Copy link

@Teagan42 Teagan42 Jun 27, 2022

Choose a reason for hiding this comment

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

In order to accommodate future changes, using a scalable/flexible pattern will shield the project from having to do deep refactoring. I added comments to your PR with some suggestions, future contributors will be thankful if you use a factory or provider pattern instead of rigid checks.

Copy link
Member

Choose a reason for hiding this comment

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

@greguintow Let me know if you're interested in making these changes, otherwise, I'll take over! 🙌

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@kamilmysliwiec I'd have time for it this weekend, if that's okay

GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloFederationDriver,
autoSchemaFile: {
useFed2: true,

Choose a reason for hiding this comment

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

[Change Request] federationVersion: 2

@@ -10,6 +10,7 @@ const config: Config.InitialOptions = {
moduleFileExtensions: ['js', 'json', 'ts'],
rootDir: '../.',
testRegex: '.spec.ts$',
testPathIgnorePatterns: ['.fed2-spec.ts$'],
Copy link

@Teagan42 Teagan42 Jun 27, 2022

Choose a reason for hiding this comment

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

[Change Request] .fed.$versions-spec.ts


const isApolloSubgraph2 = Number(apolloSubgraphVersion.split('.')[0]) >= 2;

Choose a reason for hiding this comment

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

[Change Request]
const apolloSubgraphVersion = Number(...)

[Suggestion]
const apolloSubgraphVersion = Number(/^(\d+)\..*/)

@@ -105,9 +114,49 @@ export class GraphQLFederationFactory {
options,
this.resolversExplorerService.getAllCtors(),
);
let typeDefs = isApolloSubgraph2

Choose a reason for hiding this comment

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

[Suggestion] SchemaPrinterFactory(version: number)


const useFed2 = getFederation2Info(options.autoSchemaFile);

if (useFed2 && isApolloSubgraph2) {

Choose a reason for hiding this comment

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

[Change Request] Pattern does not scale, implement a factory or mapping

options: T,
resolvers: Function[],
) {
const scalarsMap = this.scalarsExplorerService.getScalarsMap();
try {
const buildSchemaOptions = options.buildSchemaOptions || {};
const useFed2 = getFederation2Info(options.autoSchemaFile);

Choose a reason for hiding this comment

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

[Change Request] FederatedDirectivesProvider(version: number)

as: string;
}

export interface Federation2Config {

Choose a reason for hiding this comment

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

[Change Request] Utilize type composition

type FederationConfig1 = boolean
type FederationConfig2 = { ... }
type FederationConfig = FederationConfig1 | FederationConfig2

extend schema @link(url: "https://specs.apollo.dev/federation/v2.0", import: ["@key", "@shareable", "@external", "@override", "@requires"])
* ```
*/
useFed2?: UseFed2Value;

Choose a reason for hiding this comment

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

[Change Request] federationConfig: FederationConfig

import { isString, isObject } from '@nestjs/common/utils/shared.utils';
import { AutoSchemaFileValue, UseFed2Value } from '../interfaces';

export function getPathForAutoSchemaFile(

Choose a reason for hiding this comment

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

[Change Request] Factory or Provider pattern

@cristian-moreno-ruiz
Copy link

Can't get a federation working currently, are there any news on this PR? Which are the latest versions I can use to make a federated graph work with nestjs otherwise?

@NeutronScott12
Copy link

Can't get a federation working currently, are there any news on this PR? Which are the latest versions I can use to make a federated graph work with nestjs otherwise?

I use "@apollo/federation": "^0.36.1", "@nestjs/graphql": "^10.0.18", "graphql": "^15.7.2", you have to avoid apollo federation 2 packages and not go above 15.7 in graphql.

@cristian-moreno-ruiz
Copy link

Can't get a federation working currently, are there any news on this PR? Which are the latest versions I can use to make a federated graph work with nestjs otherwise?

I use "@apollo/federation": "^0.36.1", "@nestjs/graphql": "^10.0.18", "graphql": "^15.7.2", you have to avoid apollo federation 2 packages and not go above 15.7 in graphql.

Turns out I was using @apollo/subgraph: 2.0.5, looks like this was the issue, thanks!

@hwillson
Copy link
Contributor

@NeutronScott12 @cristian-moreno-ruiz just to note, @apollo/federation is an older package and doesn't support Federation 2. It will work for now as along as you aren't using Federation 2 specific features. @apollo/subgraph is the new Federation 2 package which this PR will add support for.

@kamilmysliwiec
Copy link
Member

@greguintow Let me know if you're busy and if so, I'll take over & address the proposed changes! 🙌

@greguintow
Copy link
Contributor Author

@greguintow Let me know if you're busy and if so, I'll take over & address the proposed changes! 🙌

@kamilmysliwiec Yeah, I'm busy at the moment, please take over

@ProductOfAmerica
Copy link

ProductOfAmerica commented Mar 5, 2023

I'm so confused... is this working or not? Documentation says it should "just work" by using federation: 2, yet I'm getting this error: ERROR GraphQLSchemaValidationError: Unknown directive "@link".

Edit: Fixed by adding the @apollo/subgraph package. Whoops!

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

Successfully merging this pull request may close these issues.

None yet

8 participants