Skip to content

Commit 5004b1d

Browse files
committed
feat: customization option resolvers.*.filter.operators now accept true value, it enables operators for all fields in resolver filter (by default operators added only for indexed fields). Also change generated typenames for Operators' types.
1 parent 74e1b2d commit 5004b1d

File tree

4 files changed

+183
-144
lines changed

4 files changed

+183
-144
lines changed

src/__tests__/github_issues/250-test.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,16 @@ beforeAll(async () => {
2525
});
2626
afterAll(() => UserModel.base.disconnect());
2727

28-
const UserTC = composeWithMongoose(UserModel);
28+
const UserTC = composeWithMongoose(UserModel, {
29+
resolvers: {
30+
findMany: {
31+
filter: {
32+
operators: true,
33+
},
34+
},
35+
},
36+
});
37+
// console.log(UserTC.getResolver('findOne').getArgITC('filter').toSDL({ deep: true }));
2938
schemaComposer.Query.addFields({
3039
findMany: UserTC.getResolver('findMany'),
3140
});

src/resolvers/helpers/__tests__/filterOperators-test.ts

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -39,28 +39,41 @@ beforeEach(() => {
3939
describe('Resolver helper `filter` ->', () => {
4040
describe('_createOperatorsField()', () => {
4141
it('should add OPERATORS_FIELDNAME to filterType', () => {
42-
_createOperatorsField(itc, 'OperatorsTypeName', UserModel, {});
42+
_createOperatorsField(itc, UserModel, {
43+
baseTypeName: 'TypeNameOperators',
44+
});
4345
expect(itc.hasField(OPERATORS_FIELDNAME)).toBe(true);
44-
expect(itc.getFieldTC(OPERATORS_FIELDNAME).getTypeName()).toBe('OperatorsTypeName');
46+
expect(itc.getFieldTC(OPERATORS_FIELDNAME).getTypeName()).toBe('TypeNameOperators');
4547
});
4648
it('should have only provided fields via options', () => {
47-
_createOperatorsField(itc, 'OperatorsTypeName', UserModel, { age: ['lt'] });
49+
_createOperatorsField(itc, UserModel, {
50+
baseTypeName: 'TypeNameOperators',
51+
operators: {
52+
age: ['lt'],
53+
},
54+
});
4855
const operatorsTC = itc.getFieldITC(OPERATORS_FIELDNAME);
4956
expect(operatorsTC.hasField('age')).toBe(true);
5057
});
5158
it('should have only provided operators via options for field', () => {
52-
_createOperatorsField(itc, 'OperatorsTypeName', UserModel, {
53-
age: ['lt', 'gte'],
59+
_createOperatorsField(itc, UserModel, {
60+
baseTypeName: 'TypeNameOperators',
61+
operators: {
62+
age: ['lt', 'gte'],
63+
},
5464
});
5565
const operatorsTC = itc.getFieldITC(OPERATORS_FIELDNAME);
5666
const ageTC = operatorsTC.getFieldITC('age');
5767
expect(ageTC.getFieldNames()).toEqual(expect.arrayContaining(['lt', 'gte']));
5868
});
5969
it('should handle nested fields recursively', () => {
60-
_createOperatorsField(itc, 'OperatorsTypeName', UserModel, {
61-
age: ['lt', 'gte'],
62-
billingAddress: { country: ['nin'], state: ['in'] },
63-
} as any);
70+
_createOperatorsField(itc, UserModel, {
71+
baseTypeName: 'TypeNameOperators',
72+
operators: {
73+
age: ['lt', 'gte'],
74+
billingAddress: { country: ['nin'], state: ['in'] },
75+
},
76+
});
6477
const operatorsTC = itc.getFieldITC(OPERATORS_FIELDNAME);
6578
const billingAddressTC = operatorsTC.getFieldITC('billingAddress');
6679

@@ -90,16 +103,16 @@ describe('Resolver helper `filter` ->', () => {
90103
});
91104
it('should reuse existed operatorsType', () => {
92105
const existedITC = itc.schemaComposer.getOrCreateITC('ExistedType');
93-
_createOperatorsField(itc, 'ExistedType', UserModel, {});
106+
_createOperatorsField(itc, UserModel, { baseTypeName: 'ExistedType' });
94107
expect(itc.getFieldType(OPERATORS_FIELDNAME)).toBe(existedITC.getType());
95108
});
96109
});
97110

98111
describe('addFilterOperators()', () => {
99112
it('should add OPERATORS_FIELDNAME via _createOperatorsField()', () => {
100-
addFilterOperators(itc, UserModel, {});
113+
addFilterOperators(itc, UserModel, { baseTypeName: 'UserFilter', suffix: 'Input' });
101114
expect(itc.hasField(OPERATORS_FIELDNAME)).toBe(true);
102-
expect(itc.getFieldTC(OPERATORS_FIELDNAME).getTypeName()).toBe('OperatorsUserFilterInput');
115+
expect(itc.getFieldTC(OPERATORS_FIELDNAME).getTypeName()).toBe('UserFilterOperatorsInput');
103116
});
104117
it('should add OR field', () => {
105118
addFilterOperators(itc, UserModel, {});
@@ -119,16 +132,30 @@ describe('Resolver helper `filter` ->', () => {
119132
const fields = itc.getFieldNames();
120133
expect(fields).toEqual(expect.arrayContaining(['name']));
121134
expect(itc.hasField('_operators')).toBe(true);
122-
expect(itc.getFieldITC('_operators').getFieldNames()).toEqual(['name']);
135+
expect(itc.getFieldITC('_operators').getFieldNames()).toEqual([
136+
'_id',
137+
'employment',
138+
'name',
139+
'billingAddress',
140+
]);
123141
expect(itc.getFieldITC('_operators').getFieldITC('name').getFieldNames()).toEqual(['exists']);
124142
});
125143
it('should respect operators configuration and allow onlyIndexed', () => {
126144
// By default when using onlyIndex, add all indexed fields, then if operators are supplied allow them as well
127-
addFilterOperators(itc, UserModel, { onlyIndexed: true, operators: { name: ['exists'] } });
145+
addFilterOperators(itc, UserModel, {
146+
baseTypeName: 'User',
147+
onlyIndexed: true,
148+
operators: { name: ['exists'] },
149+
});
128150
const fields = itc.getFieldNames();
129151
expect(fields).toEqual(expect.arrayContaining(['name']));
130152
expect(itc.hasField('_operators')).toBe(true);
131-
expect(itc.getFieldITC('_operators').getFieldNames()).toEqual(['_id', 'employment', 'name']);
153+
expect(itc.getFieldITC('_operators').getFieldNames()).toEqual([
154+
'_id',
155+
'employment',
156+
'name',
157+
'billingAddress',
158+
]);
132159
expect(itc.getFieldITC('_operators').getFieldITC('name').getFieldNames()).toEqual(['exists']);
133160
expect(itc.getFieldITC('_operators').getFieldITC('employment').getFieldNames()).toEqual([
134161
'gt',

src/resolvers/helpers/filter.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,22 @@ import { ObjectTypeComposer, ObjectTypeComposerArgumentConfigMap } from 'graphql
44
import type { Model } from 'mongoose';
55
import { isObject, toMongoFilterDottedObject, getIndexedFieldNamesForGraphQL } from '../../utils';
66
import type { ExtendedResolveParams } from '../index';
7-
import { FilterOperatorsOpts, addFilterOperators, processFilterOperators } from './filterOperators';
7+
import {
8+
FieldsOperatorsConfig,
9+
addFilterOperators,
10+
processFilterOperators,
11+
} from './filterOperators';
812
import type { AliasesMap } from './aliases';
913
import { makeFieldsRecursiveNullable } from '../../utils/makeFieldsRecursiveNullable';
1014

1115
export type FilterHelperArgsOpts = {
1216
prefix?: string;
1317
suffix?: string;
18+
baseTypeName?: string;
1419
isRequired?: boolean;
1520
onlyIndexed?: boolean;
1621
requiredFields?: string | string[];
17-
operators?: FilterOperatorsOpts | false;
22+
operators?: FieldsOperatorsConfig | false;
1823
removeFields?: string | string[];
1924
};
2025

@@ -79,6 +84,9 @@ export const filterHelperArgs = (
7984
return {};
8085
}
8186

87+
if (!opts.baseTypeName) {
88+
opts.baseTypeName = typeComposer.getTypeName();
89+
}
8290
addFilterOperators(itc, model, opts);
8391

8492
return {

0 commit comments

Comments
 (0)