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

Change federation codegen to use output type where relevant. #9770

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/nervous-dots-give.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@graphql-codegen/typescript-resolvers': patch
'@graphql-codegen/plugin-helpers': patch
---

Update generation to use the external types for federation directives
10 changes: 2 additions & 8 deletions dev-test/test-schema/resolvers-federation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,19 +194,13 @@ export type UserResolvers<
> = {
__resolveReference?: ReferenceResolver<
Maybe<ResolversTypes['User']>,
{ __typename: 'User' } & (
| GraphQLRecursivePick<ParentType, { id: true }>
| GraphQLRecursivePick<ParentType, { name: true }>
),
{ __typename: 'User' } & (GraphQLRecursivePick<User, { id: true }> | GraphQLRecursivePick<User, { name: true }>),
ContextType
>;

email?: Resolver<
ResolversTypes['String'],
{ __typename: 'User' } & (
| GraphQLRecursivePick<ParentType, { id: true }>
| GraphQLRecursivePick<ParentType, { name: true }>
) &
{ __typename: 'User' } & (GraphQLRecursivePick<User, { id: true }> | GraphQLRecursivePick<User, { name: true }>) &
GraphQLRecursivePick<ParentType, { address: { city: true; lines: { line2: true } } }>,
ContextType
>;
Expand Down
58 changes: 29 additions & 29 deletions packages/plugins/typescript/resolvers/tests/federation.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,11 @@ describe('TypeScript Resolvers Plugin + Apollo Federation', () => {

// User should have it
expect(content).toBeSimilarStringTo(`
__resolveReference?: ReferenceResolver<Maybe<ResolversTypes['User']>, { __typename: 'User' } & GraphQLRecursivePick<ParentType, {"id":true}>, ContextType>;
__resolveReference?: ReferenceResolver<Maybe<ResolversTypes['User']>, { __typename: 'User' } & GraphQLRecursivePick<User, {"id":true}>, ContextType>;
`);
// Foo shouldn't because it doesn't have @key
// Book shouldn't because it doesn't have @key
expect(content).not.toBeSimilarStringTo(`
__resolveReference?: ReferenceResolver<Maybe<ResolversTypes['Book']>, { __typename: 'Book' } & GraphQLRecursivePick<ParentType, {"id":true}>, ContextType>;
__resolveReference?: ReferenceResolver<Maybe<ResolversTypes['Book']>, { __typename: 'Book' } & GraphQLRecursivePick<Book, {"id":true}>, ContextType>;
`);
});

Expand Down Expand Up @@ -84,11 +84,11 @@ describe('TypeScript Resolvers Plugin + Apollo Federation', () => {

// User should have it
expect(content).toBeSimilarStringTo(`
__resolveReference?: ReferenceResolver<Maybe<ResolversTypes['User']>, { __typename: 'User' } & GraphQLRecursivePick<ParentType, {"id":true}>, ContextType>;
__resolveReference?: ReferenceResolver<Maybe<ResolversTypes['User']>, { __typename: 'User' } & GraphQLRecursivePick<User, {"id":true}>, ContextType>;
`);
// Foo shouldn't because it doesn't have @key
// Book shouldn't because it doesn't have @key
expect(content).not.toBeSimilarStringTo(`
__resolveReference?: ReferenceResolver<Maybe<ResolversTypes['Book']>, { __typename: 'Book' } & GraphQLRecursivePick<ParentType, {"id":true}>, ContextType>;
__resolveReference?: ReferenceResolver<Maybe<ResolversTypes['Book']>, { __typename: 'Book' } & GraphQLRecursivePick<Book, {"id":true}>, ContextType>;
`);
});

Expand Down Expand Up @@ -125,18 +125,18 @@ describe('TypeScript Resolvers Plugin + Apollo Federation', () => {

expect(content).toBeSimilarStringTo(`
export type UserResolvers<ContextType = any, ParentType extends ResolversParentTypes['User'] = ResolversParentTypes['User']> = {
__resolveReference?: ReferenceResolver<Maybe<ResolversTypes['User']>, { __typename: 'User' } & GraphQLRecursivePick<ParentType, {"id":true}>, ContextType>;
id?: Resolver<ResolversTypes['ID'], { __typename: 'User' } & GraphQLRecursivePick<ParentType, {"id":true}>, ContextType>;
name?: Resolver<Maybe<ResolversTypes['Name']>, { __typename: 'User' } & GraphQLRecursivePick<ParentType, {"id":true}>, ContextType>;
__resolveReference?: ReferenceResolver<Maybe<ResolversTypes['User']>, { __typename: 'User' } & GraphQLRecursivePick<User, {"id":true}>, ContextType>;
id?: Resolver<ResolversTypes['ID'], { __typename: 'User' } & GraphQLRecursivePick<User, {"id":true}>, ContextType>;
name?: Resolver<Maybe<ResolversTypes['Name']>, { __typename: 'User' } & GraphQLRecursivePick<User, {"id":true}>, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
}
`);

expect(content).toBeSimilarStringTo(`
export type NameResolvers<ContextType = any, ParentType extends ResolversParentTypes['Name'] = ResolversParentTypes['Name']> = {
__resolveReference?: ReferenceResolver<Maybe<ResolversTypes['Name']>, { __typename: 'Name' } & GraphQLRecursivePick<ParentType, {"id":true}>, ContextType>;
first?: Resolver<ResolversTypes['String'], { __typename: 'Name' } & GraphQLRecursivePick<ParentType, {"id":true}>, ContextType>;
last?: Resolver<ResolversTypes['String'], { __typename: 'Name' } & GraphQLRecursivePick<ParentType, {"id":true}>, ContextType>;
__resolveReference?: ReferenceResolver<Maybe<ResolversTypes['Name']>, { __typename: 'Name' } & GraphQLRecursivePick<Name, {"id":true}>, ContextType>;
first?: Resolver<ResolversTypes['String'], { __typename: 'Name' } & GraphQLRecursivePick<Name, {"id":true}>, ContextType>;
last?: Resolver<ResolversTypes['String'], { __typename: 'Name' } & GraphQLRecursivePick<Name, {"id":true}>, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
}
`);
Expand Down Expand Up @@ -166,9 +166,9 @@ describe('TypeScript Resolvers Plugin + Apollo Federation', () => {
// User should have it
expect(content).toBeSimilarStringTo(`
export type UserResolvers<ContextType = any, ParentType extends ResolversParentTypes['User'] = ResolversParentTypes['User']> = {
__resolveReference?: ReferenceResolver<Maybe<ResolversTypes['User']>, { __typename: 'User' } & GraphQLRecursivePick<ParentType, {"id":true}>, ContextType>;
id?: Resolver<ResolversTypes['ID'], { __typename: 'User' } & GraphQLRecursivePick<ParentType, {"id":true}>, ContextType>;
username?: Resolver<Maybe<ResolversTypes['String']>, { __typename: 'User' } & GraphQLRecursivePick<ParentType, {"id":true}> & GraphQLRecursivePick<ParentType, {"name":true,"age":true}>, ContextType>;
__resolveReference?: ReferenceResolver<Maybe<ResolversTypes['User']>, { __typename: 'User' } & GraphQLRecursivePick<User, {"id":true}>, ContextType>;
id?: Resolver<ResolversTypes['ID'], { __typename: 'User' } & GraphQLRecursivePick<User, {"id":true}>, ContextType>;
username?: Resolver<Maybe<ResolversTypes['String']>, { __typename: 'User' } & GraphQLRecursivePick<User, {"id":true}> & GraphQLRecursivePick<User, {"name":true,"age":true}>, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};
`);
Expand Down Expand Up @@ -203,8 +203,8 @@ describe('TypeScript Resolvers Plugin + Apollo Federation', () => {

expect(content).toBeSimilarStringTo(`
export type UserResolvers<ContextType = any, ParentType extends ResolversParentTypes['User'] = ResolversParentTypes['User']> = {
__resolveReference?: ReferenceResolver<Maybe<ResolversTypes['User']>, { __typename: 'User' } & GraphQLRecursivePick<ParentType, {"id":true}>, ContextType>;
username?: Resolver<Maybe<ResolversTypes['String']>, { __typename: 'User' } & GraphQLRecursivePick<ParentType, {"id":true}> & GraphQLRecursivePick<ParentType, {"name":true,"age":true,"address":{"street":true}}>, ContextType>;
__resolveReference?: ReferenceResolver<Maybe<ResolversTypes['User']>, { __typename: 'User' } & GraphQLRecursivePick<User, {"id":true}>, ContextType>;
username?: Resolver<Maybe<ResolversTypes['String']>, { __typename: 'User' } & GraphQLRecursivePick<User, {"id":true}> & GraphQLRecursivePick<User, {"name":true,"age":true,"address":{"street":true}}>, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};
`);
Expand Down Expand Up @@ -236,8 +236,8 @@ describe('TypeScript Resolvers Plugin + Apollo Federation', () => {

expect(content).toBeSimilarStringTo(`
export type UserResolvers<ContextType = any, ParentType extends ResolversParentTypes['User'] = ResolversParentTypes['User']> = {
__resolveReference?: ReferenceResolver<Maybe<ResolversTypes['User']>, { __typename: 'User' } & GraphQLRecursivePick<ParentType, {"name":{"first":true,"last":true}}>, ContextType>;
username?: Resolver<Maybe<ResolversTypes['String']>, { __typename: 'User' } & GraphQLRecursivePick<ParentType, {"name":{"first":true,"last":true}}>, ContextType>;
__resolveReference?: ReferenceResolver<Maybe<ResolversTypes['User']>, { __typename: 'User' } & GraphQLRecursivePick<User, {"name":{"first":true,"last":true}}>, ContextType>;
username?: Resolver<Maybe<ResolversTypes['String']>, { __typename: 'User' } & GraphQLRecursivePick<User, {"name":{"first":true,"last":true}}>, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};
`);
Expand Down Expand Up @@ -269,7 +269,7 @@ describe('TypeScript Resolvers Plugin + Apollo Federation', () => {

expect(content).toBeSimilarStringTo(`
export type UserResolvers<ContextType = any, ParentType extends ResolversParentTypes['User'] = ResolversParentTypes['User']> = {
__resolveReference?: ReferenceResolver<Maybe<ResolversTypes['User']>, { __typename: 'User' } & GraphQLRecursivePick<ParentType, {"name":{"first":true,"last":true}}>, ContextType>;
__resolveReference?: ReferenceResolver<Maybe<ResolversTypes['User']>, { __typename: 'User' } & GraphQLRecursivePick<User, {"name":{"first":true,"last":true}}>, ContextType>;
name?: Resolver<ResolversTypes['Name'], ParentType, ContextType>;
username?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
Expand Down Expand Up @@ -316,7 +316,7 @@ describe('TypeScript Resolvers Plugin + Apollo Federation', () => {
expect(content).toBeSimilarStringTo(`
export type PersonResolvers<ContextType = any, ParentType extends ResolversParentTypes['Person'] = ResolversParentTypes['Person']> = {
__resolveType: TypeResolveFn<'User' | 'Admin', ParentType, ContextType>;
age?: Resolver<Maybe<ResolversTypes['Int']>, { __typename: 'User' | 'Admin' } & GraphQLRecursivePick<ParentType, {"name":{"first":true,"last":true}}>, ContextType>;
age?: Resolver<Maybe<ResolversTypes['Int']>, { __typename: 'User' | 'Admin' } & GraphQLRecursivePick<Person, {"name":{"first":true,"last":true}}>, ContextType>;
};
`);
});
Expand Down Expand Up @@ -348,9 +348,9 @@ describe('TypeScript Resolvers Plugin + Apollo Federation', () => {
// UserResolver should not have a resolver function of name field
expect(content).toBeSimilarStringTo(`
export type UserResolvers<ContextType = any, ParentType extends ResolversParentTypes['User'] = ResolversParentTypes['User']> = {
__resolveReference?: ReferenceResolver<Maybe<ResolversTypes['User']>, { __typename: 'User' } & GraphQLRecursivePick<ParentType, {"id":true}>, ContextType>;
id?: Resolver<ResolversTypes['ID'], { __typename: 'User' } & GraphQLRecursivePick<ParentType, {"id":true}>, ContextType>;
name?: Resolver<Maybe<ResolversTypes['String']>, { __typename: 'User' } & GraphQLRecursivePick<ParentType, {"id":true}>, ContextType>;
__resolveReference?: ReferenceResolver<Maybe<ResolversTypes['User']>, { __typename: 'User' } & GraphQLRecursivePick<User, {"id":true}>, ContextType>;
id?: Resolver<ResolversTypes['ID'], { __typename: 'User' } & GraphQLRecursivePick<User, {"id":true}>, ContextType>;
name?: Resolver<Maybe<ResolversTypes['String']>, { __typename: 'User' } & GraphQLRecursivePick<User, {"id":true}>, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};
`);
Expand Down Expand Up @@ -475,9 +475,9 @@ describe('TypeScript Resolvers Plugin + Apollo Federation', () => {
// User should have it
expect(content).toBeSimilarStringTo(`
export type UserResolvers<ContextType = any, ParentType extends ResolversParentTypes['User'] = ResolversParentTypes['User']> = {
__resolveReference?: ReferenceResolver<Maybe<ResolversTypes['User']>, { __typename: 'User' } & (GraphQLRecursivePick<ParentType, {"id":true}> | GraphQLRecursivePick<ParentType, {"name":true}>), ContextType>;
name?: Resolver<Maybe<ResolversTypes['String']>, { __typename: 'User' } & (GraphQLRecursivePick<ParentType, {"id":true}> | GraphQLRecursivePick<ParentType, {"name":true}>), ContextType>;
username?: Resolver<Maybe<ResolversTypes['String']>, { __typename: 'User' } & (GraphQLRecursivePick<ParentType, {"id":true}> | GraphQLRecursivePick<ParentType, {"name":true}>), ContextType>;
__resolveReference?: ReferenceResolver<Maybe<ResolversTypes['User']>, { __typename: 'User' } & (GraphQLRecursivePick<User, {"id":true}> | GraphQLRecursivePick<User, {"name":true}>), ContextType>;
name?: Resolver<Maybe<ResolversTypes['String']>, { __typename: 'User' } & (GraphQLRecursivePick<User, {"id":true}> | GraphQLRecursivePick<User, {"name":true}>), ContextType>;
username?: Resolver<Maybe<ResolversTypes['String']>, { __typename: 'User' } & (GraphQLRecursivePick<User, {"id":true}> | GraphQLRecursivePick<User, {"name":true}>), ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};
`);
Expand Down Expand Up @@ -561,7 +561,7 @@ describe('TypeScript Resolvers Plugin + Apollo Federation', () => {
expect(content).toBeSimilarStringTo(`type UnwrappedObject<T> = {`);
});

it('should add UnwrappedObject around ParentType for __resloveReference', async () => {
it('should use the output type directly for __resolveReference', async () => {
const federatedSchema = /* GraphQL */ `
type User @key(fields: "id") {
id: ID!
Expand All @@ -578,7 +578,7 @@ describe('TypeScript Resolvers Plugin + Apollo Federation', () => {

// __resolveReference should be unwrapped
expect(content).toBeSimilarStringTo(`
__resolveReference?: ReferenceResolver<Maybe<ResolversTypes['User']>, { __typename: 'User' } & GraphQLRecursivePick<UnwrappedObject<ParentType>, {"id":true}>, ContextType>;
__resolveReference?: ReferenceResolver<Maybe<ResolversTypes['User']>, { __typename: 'User' } & GraphQLRecursivePick<User, {"id":true}>, ContextType>;
`);
// but ID should not
expect(content).toBeSimilarStringTo(`id?: Resolver<ResolversTypes['ID'], ParentType, ContextType>`);
Expand Down
4 changes: 2 additions & 2 deletions packages/utils/plugins-helpers/src/federation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,12 +168,12 @@ export class ApolloFederation {

// Look for @requires and see what the service needs and gets
const requires = getDirectivesByName('requires', fieldNode).map(this.extractFieldSet);
const requiredFields = this.translateFieldSet(merge({}, ...requires), parentTypeSignature);
const requiredFields = this.translateFieldSet(merge({}, ...requires), parentType.name);

// @key() @key() - "primary keys" in Federation
const primaryKeys = keys.map(def => {
const fields = this.extractFieldSet(def);
return this.translateFieldSet(fields, parentTypeSignature);
return this.translateFieldSet(fields, parentType.name);
});

const [open, close] = primaryKeys.length > 1 ? ['(', ')'] : ['', ''];
Expand Down