Skip to content

Commit 5cc54d0

Browse files
committed
feat[useOnResolve] add skipDefaultResolvers option
1 parent 4870a73 commit 5cc54d0

File tree

2 files changed

+58
-1
lines changed

2 files changed

+58
-1
lines changed

packages/plugins/on-resolve/src/index.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,13 @@ export type UseOnResolveOptions = {
4040
* @default true
4141
*/
4242
skipIntrospection?: boolean;
43+
44+
/**
45+
* Skip executing the `onResolve` hook on fields with default resolvers.
46+
*
47+
* @default false
48+
*/
49+
skipDefaultResolvers?: boolean;
4350
};
4451

4552
/**
@@ -49,7 +56,7 @@ export type UseOnResolveOptions = {
4956
*/
5057
export function useOnResolve<PluginContext extends Record<string, any> = {}>(
5158
onResolve: OnResolve<PluginContext>,
52-
opts: UseOnResolveOptions = { skipIntrospection: true },
59+
opts: UseOnResolveOptions = { skipIntrospection: true, skipDefaultResolvers: false },
5360
): Plugin<PluginContext> {
5461
const hasWrappedResolveSymbol = Symbol('hasWrappedResolve');
5562
return {
@@ -61,6 +68,7 @@ export function useOnResolve<PluginContext extends Record<string, any> = {}>(
6168
if ((!opts.skipIntrospection || !isIntrospectionType(type)) && isObjectType(type)) {
6269
for (const field of Object.values(type.getFields())) {
6370
if ((field as { [hasWrappedResolveSymbol]?: true })[hasWrappedResolveSymbol]) continue;
71+
if (opts.skipDefaultResolvers && !field.resolve) continue;
6472

6573
let resolver = (field.resolve || defaultFieldResolver) as Resolver<PluginContext>;
6674

packages/plugins/on-resolve/test/use-on-resolve.spec.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,20 @@ describe('useOnResolve', () => {
88
type Query {
99
value1: String!
1010
value2: String!
11+
obj: Obj!
12+
}
13+
14+
type Obj {
15+
field1: String!
1116
}
1217
`,
1318
resolvers: {
1419
Query: {
1520
value1: () => 'value1',
1621
value2: () => 'value2',
22+
obj: () => ({
23+
field1: 'field1',
24+
}),
1725
},
1826
},
1927
});
@@ -85,6 +93,47 @@ describe('useOnResolve', () => {
8593
expect(onResolveDoneFn).toHaveBeenCalledTimes(0);
8694
});
8795

96+
it('should invoke the callback for default resolvers when not skipping', async () => {
97+
const onResolveDoneFn = jest.fn();
98+
const onResolveFn = jest.fn((_opts: OnResolveOptions) => onResolveDoneFn);
99+
const testkit = createTestkit(
100+
[useOnResolve(onResolveFn, { skipDefaultResolvers: false })],
101+
schema,
102+
);
103+
104+
await testkit.execute('{ obj { field1 } }');
105+
106+
expect(onResolveFn).toHaveBeenCalledTimes(2);
107+
expect(onResolveDoneFn).toHaveBeenCalledTimes(2);
108+
109+
let i = 0;
110+
for (const field of ['obj', 'field1']) {
111+
expect(onResolveFn.mock.calls[i][0].context).toBeDefined();
112+
expect(onResolveFn.mock.calls[i][0].root).toBeDefined();
113+
expect(onResolveFn.mock.calls[i][0].args).toBeDefined();
114+
expect(onResolveFn.mock.calls[i][0].info).toBeDefined();
115+
expect(onResolveFn.mock.calls[i][0].info.fieldName).toBe(field);
116+
expect(onResolveFn.mock.calls[i][0].resolver).toBeInstanceOf(Function);
117+
expect(onResolveFn.mock.calls[i][0].replaceResolver).toBeInstanceOf(Function);
118+
119+
i++;
120+
}
121+
});
122+
123+
it('should not invoke the callback for default resolvers when skipping', async () => {
124+
const onResolveDoneFn = jest.fn();
125+
const onResolveFn = jest.fn((_opts: OnResolveOptions) => onResolveDoneFn);
126+
const testkit = createTestkit(
127+
[useOnResolve(onResolveFn, { skipDefaultResolvers: true })],
128+
schema,
129+
);
130+
131+
await testkit.execute('{ obj { field1 } }');
132+
133+
expect(onResolveFn).toHaveBeenCalledTimes(1);
134+
expect(onResolveDoneFn).toHaveBeenCalledTimes(1);
135+
});
136+
88137
it('should replace the result using the after hook', async () => {
89138
const testkit = createTestkit(
90139
[

0 commit comments

Comments
 (0)