Skip to content

Commit ac709c0

Browse files
committed
Add test for federation mappers usage in reference
1 parent bdf4331 commit ac709c0

File tree

1 file changed

+182
-0
lines changed

1 file changed

+182
-0
lines changed
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
import '@graphql-codegen/testing';
2+
import { codegen } from '@graphql-codegen/core';
3+
import { parse } from 'graphql';
4+
import { TypeScriptResolversPluginConfig } from '../src/config.js';
5+
import { plugin } from '../src/index.js';
6+
7+
function generate({ schema, config }: { schema: string; config: TypeScriptResolversPluginConfig }) {
8+
return codegen({
9+
filename: 'graphql.ts',
10+
schema: parse(schema),
11+
documents: [],
12+
plugins: [{ 'typescript-resolvers': {} }],
13+
config,
14+
pluginMap: { 'typescript-resolvers': { plugin } },
15+
});
16+
}
17+
18+
describe('TypeScript Resolvers Plugin + Apollo Federation - mappers', () => {
19+
it('generates FederationTypes and use it for reference type', async () => {
20+
const federatedSchema = /* GraphQL */ `
21+
type Query {
22+
me: User
23+
}
24+
25+
type User @key(fields: "id") {
26+
id: ID!
27+
name: String
28+
}
29+
30+
type UserProfile {
31+
id: ID!
32+
user: User!
33+
}
34+
`;
35+
36+
const content = await generate({
37+
schema: federatedSchema,
38+
config: {
39+
federation: true,
40+
mappers: {
41+
User: './mappers#UserMapper',
42+
},
43+
},
44+
});
45+
46+
// User should have it
47+
expect(content).toMatchInlineSnapshot(`
48+
"import { GraphQLResolveInfo } from 'graphql';
49+
import { UserMapper } from './mappers';
50+
export type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
51+
52+
53+
export type ResolverTypeWrapper<T> = Promise<T> | T;
54+
55+
export type ReferenceResolver<TResult, TReference, TContext> = (
56+
reference: TReference,
57+
context: TContext,
58+
info: GraphQLResolveInfo
59+
) => Promise<TResult> | TResult;
60+
61+
type ScalarCheck<T, S> = S extends true ? T : NullableCheck<T, S>;
62+
type NullableCheck<T, S> = Maybe<T> extends T ? Maybe<ListCheck<NonNullable<T>, S>> : ListCheck<T, S>;
63+
type ListCheck<T, S> = T extends (infer U)[] ? NullableCheck<U, S>[] : GraphQLRecursivePick<T, S>;
64+
export type GraphQLRecursivePick<T, S> = { [K in keyof T & keyof S]: ScalarCheck<T[K], S[K]> };
65+
66+
67+
export type ResolverWithResolve<TResult, TParent, TContext, TArgs> = {
68+
resolve: ResolverFn<TResult, TParent, TContext, TArgs>;
69+
};
70+
export type Resolver<TResult, TParent = {}, TContext = {}, TArgs = {}> = ResolverFn<TResult, TParent, TContext, TArgs> | ResolverWithResolve<TResult, TParent, TContext, TArgs>;
71+
72+
export type ResolverFn<TResult, TParent, TContext, TArgs> = (
73+
parent: TParent,
74+
args: TArgs,
75+
context: TContext,
76+
info: GraphQLResolveInfo
77+
) => Promise<TResult> | TResult;
78+
79+
export type SubscriptionSubscribeFn<TResult, TParent, TContext, TArgs> = (
80+
parent: TParent,
81+
args: TArgs,
82+
context: TContext,
83+
info: GraphQLResolveInfo
84+
) => AsyncIterable<TResult> | Promise<AsyncIterable<TResult>>;
85+
86+
export type SubscriptionResolveFn<TResult, TParent, TContext, TArgs> = (
87+
parent: TParent,
88+
args: TArgs,
89+
context: TContext,
90+
info: GraphQLResolveInfo
91+
) => TResult | Promise<TResult>;
92+
93+
export interface SubscriptionSubscriberObject<TResult, TKey extends string, TParent, TContext, TArgs> {
94+
subscribe: SubscriptionSubscribeFn<{ [key in TKey]: TResult }, TParent, TContext, TArgs>;
95+
resolve?: SubscriptionResolveFn<TResult, { [key in TKey]: TResult }, TContext, TArgs>;
96+
}
97+
98+
export interface SubscriptionResolverObject<TResult, TParent, TContext, TArgs> {
99+
subscribe: SubscriptionSubscribeFn<any, TParent, TContext, TArgs>;
100+
resolve: SubscriptionResolveFn<TResult, any, TContext, TArgs>;
101+
}
102+
103+
export type SubscriptionObject<TResult, TKey extends string, TParent, TContext, TArgs> =
104+
| SubscriptionSubscriberObject<TResult, TKey, TParent, TContext, TArgs>
105+
| SubscriptionResolverObject<TResult, TParent, TContext, TArgs>;
106+
107+
export type SubscriptionResolver<TResult, TKey extends string, TParent = {}, TContext = {}, TArgs = {}> =
108+
| ((...args: any[]) => SubscriptionObject<TResult, TKey, TParent, TContext, TArgs>)
109+
| SubscriptionObject<TResult, TKey, TParent, TContext, TArgs>;
110+
111+
export type TypeResolveFn<TTypes, TParent = {}, TContext = {}> = (
112+
parent: TParent,
113+
context: TContext,
114+
info: GraphQLResolveInfo
115+
) => Maybe<TTypes> | Promise<Maybe<TTypes>>;
116+
117+
export type IsTypeOfResolverFn<T = {}, TContext = {}> = (obj: T, context: TContext, info: GraphQLResolveInfo) => boolean | Promise<boolean>;
118+
119+
export type NextResolverFn<T> = () => Promise<T>;
120+
121+
export type DirectiveResolverFn<TResult = {}, TParent = {}, TContext = {}, TArgs = {}> = (
122+
next: NextResolverFn<TResult>,
123+
parent: TParent,
124+
args: TArgs,
125+
context: TContext,
126+
info: GraphQLResolveInfo
127+
) => TResult | Promise<TResult>;
128+
129+
/** Mapping of federation types */
130+
export type FederationTypes = {
131+
User: User;
132+
};
133+
134+
135+
136+
/** Mapping between all available schema types and the resolvers types */
137+
export type ResolversTypes = {
138+
Query: ResolverTypeWrapper<{}>;
139+
User: ResolverTypeWrapper<UserMapper>;
140+
ID: ResolverTypeWrapper<Scalars['ID']['output']>;
141+
String: ResolverTypeWrapper<Scalars['String']['output']>;
142+
UserProfile: ResolverTypeWrapper<Omit<UserProfile, 'user'> & { user: ResolversTypes['User'] }>;
143+
Boolean: ResolverTypeWrapper<Scalars['Boolean']['output']>;
144+
};
145+
146+
/** Mapping between all available schema types and the resolvers parents */
147+
export type ResolversParentTypes = {
148+
Query: {};
149+
User: UserMapper;
150+
ID: Scalars['ID']['output'];
151+
String: Scalars['String']['output'];
152+
UserProfile: Omit<UserProfile, 'user'> & { user: ResolversParentTypes['User'] };
153+
Boolean: Scalars['Boolean']['output'];
154+
};
155+
156+
export type QueryResolvers<ContextType = any, ParentType extends ResolversParentTypes['Query'] = ResolversParentTypes['Query']> = {
157+
me?: Resolver<Maybe<ResolversTypes['User']>, ParentType, ContextType>;
158+
};
159+
160+
export type UserResolvers<ContextType = any, ParentType extends ResolversParentTypes['User'] = ResolversParentTypes['User'], FederationType extends FederationTypes['User'] = FederationTypes['User']> = {
161+
__resolveReference?: ReferenceResolver<Maybe<ResolversTypes['User']>, { __typename: 'User' } & GraphQLRecursivePick<FederationType, {"id":true}>, ContextType>;
162+
id?: Resolver<ResolversTypes['ID'], ParentType, ContextType>;
163+
name?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
164+
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
165+
};
166+
167+
export type UserProfileResolvers<ContextType = any, ParentType extends ResolversParentTypes['UserProfile'] = ResolversParentTypes['UserProfile']> = {
168+
id?: Resolver<ResolversTypes['ID'], ParentType, ContextType>;
169+
user?: Resolver<ResolversTypes['User'], ParentType, ContextType>;
170+
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
171+
};
172+
173+
export type Resolvers<ContextType = any> = {
174+
Query?: QueryResolvers<ContextType>;
175+
User?: UserResolvers<ContextType>;
176+
UserProfile?: UserProfileResolvers<ContextType>;
177+
};
178+
179+
"
180+
`);
181+
});
182+
});

0 commit comments

Comments
 (0)