Skip to content

Commit 730c062

Browse files
committed
feat: add suffix option to resolvers which may generate different sub-types according to config. It allows to avoid Type name collision if you generate several resolvers from one with different configs.
Closes #268
1 parent a136386 commit 730c062

14 files changed

+233
-29
lines changed
+169
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
import { SchemaComposer } from 'graphql-compose';
2+
import { composeMongoose } from '../../index';
3+
import { mongoose } from '../../__mocks__/mongooseCommon';
4+
import { Document } from 'mongoose';
5+
6+
const schemaComposer = new SchemaComposer<{ req: any }>();
7+
8+
const UserSchema = new mongoose.Schema({
9+
_id: { type: Number },
10+
name: { type: String, required: true },
11+
age: { type: Number },
12+
});
13+
interface IUser extends Document {
14+
_id: number;
15+
name: string;
16+
age?: number;
17+
}
18+
19+
const UserModel = mongoose.model<IUser>('User', UserSchema);
20+
const UserTC = composeMongoose(UserModel, { schemaComposer });
21+
22+
schemaComposer.Query.addFields({
23+
userById: UserTC.mongooseResolvers.findById(),
24+
userFindOne: UserTC.mongooseResolvers.findOne(),
25+
});
26+
27+
// const schema = schemaComposer.buildSchema();
28+
// console.log(schemaComposer.toSDL());
29+
30+
beforeAll(async () => {
31+
await UserModel.base.createConnection();
32+
await UserModel.create({ _id: 1, name: 'User1' });
33+
});
34+
afterAll(() => UserModel.base.disconnect());
35+
36+
describe('issue #268 - Allow to provide `suffixes` for resolvers configs', () => {
37+
it('generate deferent resolvers with different configs', async () => {
38+
const createOne1 = UserTC.mongooseResolvers.createOne();
39+
expect(createOne1.getTypeName()).toBe('CreateOneUserPayload');
40+
expect(createOne1.getArgITC('record').toSDL()).toMatchInlineSnapshot(`
41+
"\\"\\"\\"\\"\\"\\"
42+
input CreateOneUserInput {
43+
name: String!
44+
age: Float
45+
}"
46+
`);
47+
48+
const createOne2 = UserTC.mongooseResolvers.createOne({
49+
suffix: 'Short',
50+
record: {
51+
removeFields: ['age'],
52+
},
53+
});
54+
expect(createOne2.getTypeName()).toBe('CreateOneUserShortPayload');
55+
expect(createOne2.getArgITC('record').toSDL()).toMatchInlineSnapshot(`
56+
"\\"\\"\\"\\"\\"\\"
57+
input CreateOneUserShortInput {
58+
_id: Int!
59+
name: String!
60+
}"
61+
`);
62+
});
63+
64+
it('Resolver:count', () => {
65+
const resolver = UserTC.mongooseResolvers.count({
66+
suffix: 'XXX',
67+
});
68+
expect(resolver.getArgTypeName('filter')).toBe('FilterCountUserXXXInput');
69+
});
70+
71+
it('Resolver:findMany', () => {
72+
const resolver = UserTC.mongooseResolvers.findMany({
73+
suffix: 'XXX',
74+
});
75+
expect(resolver.getArgTypeName('filter')).toBe('FilterFindManyUserXXXInput');
76+
expect(resolver.getArgTypeName('sort')).toBe('SortFindManyUserXXXInput');
77+
});
78+
79+
it('Resolver:findManyLean', () => {
80+
const resolver = UserTC.mongooseResolvers.findManyLean({
81+
suffix: 'XXX',
82+
});
83+
expect(resolver.getArgTypeName('filter')).toBe('FilterFindManyLeanUserXXXInput');
84+
expect(resolver.getArgTypeName('sort')).toBe('SortFindManyLeanUserXXXInput');
85+
});
86+
87+
it('Resolver:findOne', () => {
88+
const resolver = UserTC.mongooseResolvers.findOne({
89+
suffix: 'XXX',
90+
});
91+
expect(resolver.getArgTypeName('filter')).toBe('FilterFindOneUserXXXInput');
92+
expect(resolver.getArgTypeName('sort')).toBe('SortFindOneUserXXXInput');
93+
});
94+
95+
it('Resolver:findOneLean', () => {
96+
const resolver = UserTC.mongooseResolvers.findOneLean({
97+
suffix: 'XXX',
98+
});
99+
expect(resolver.getArgTypeName('filter')).toBe('FilterFindOneLeanUserXXXInput');
100+
expect(resolver.getArgTypeName('sort')).toBe('SortFindOneLeanUserXXXInput');
101+
});
102+
103+
it('Resolver:createMany', () => {
104+
const resolver = UserTC.mongooseResolvers.createMany({
105+
suffix: 'XXX',
106+
});
107+
expect(resolver.getTypeName()).toBe('CreateManyUserXXXPayload');
108+
expect(resolver.getArgTypeName('records')).toBe('[CreateManyUserXXXInput!]!');
109+
});
110+
111+
it('Resolver:createOne', () => {
112+
const resolver = UserTC.mongooseResolvers.createOne({
113+
suffix: 'XXX',
114+
});
115+
expect(resolver.getTypeName()).toBe('CreateOneUserXXXPayload');
116+
expect(resolver.getArgTypeName('record')).toBe('CreateOneUserXXXInput!');
117+
});
118+
119+
it('Resolver:removeById', () => {
120+
const resolver = UserTC.mongooseResolvers.removeById({
121+
suffix: 'XXX',
122+
});
123+
expect(resolver.getTypeName()).toBe('RemoveByIdUserXXXPayload');
124+
});
125+
126+
it('Resolver:removeMany', () => {
127+
const resolver = UserTC.mongooseResolvers.removeMany({
128+
suffix: 'XXX',
129+
});
130+
expect(resolver.getTypeName()).toBe('RemoveManyUserXXXPayload');
131+
});
132+
133+
it('Resolver:removeOne', () => {
134+
const resolver = UserTC.mongooseResolvers.removeOne({
135+
suffix: 'XXX',
136+
});
137+
expect(resolver.getTypeName()).toBe('RemoveOneUserXXXPayload');
138+
expect(resolver.getArgTypeName('filter')).toBe('FilterRemoveOneUserXXXInput');
139+
expect(resolver.getArgTypeName('sort')).toBe('SortRemoveOneUserXXXInput');
140+
});
141+
142+
it('Resolver:updateById', () => {
143+
const resolver = UserTC.mongooseResolvers.updateById({
144+
suffix: 'XXX',
145+
});
146+
expect(resolver.getTypeName()).toBe('UpdateByIdUserXXXPayload');
147+
expect(resolver.getArgTypeName('record')).toBe('UpdateByIdUserXXXInput!');
148+
});
149+
150+
it('Resolver:updateMany', () => {
151+
const resolver = UserTC.mongooseResolvers.updateMany({
152+
suffix: 'XXX',
153+
});
154+
expect(resolver.getTypeName()).toBe('UpdateManyUserXXXPayload');
155+
expect(resolver.getArgTypeName('record')).toBe('UpdateManyUserXXXInput!');
156+
expect(resolver.getArgTypeName('filter')).toBe('FilterUpdateManyUserXXXInput');
157+
expect(resolver.getArgTypeName('sort')).toBe('SortUpdateManyUserXXXInput');
158+
});
159+
160+
it('Resolver:updateOne', () => {
161+
const resolver = UserTC.mongooseResolvers.updateOne({
162+
suffix: 'XXX',
163+
});
164+
expect(resolver.getTypeName()).toBe('UpdateOneUserXXXPayload');
165+
expect(resolver.getArgTypeName('record')).toBe('UpdateOneUserXXXInput!');
166+
expect(resolver.getArgTypeName('filter')).toBe('FilterUpdateOneUserXXXInput');
167+
expect(resolver.getArgTypeName('sort')).toBe('SortUpdateOneUserXXXInput');
168+
});
169+
});

src/resolvers/count.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import type { ExtendedResolveParams } from './index';
55
import { beforeQueryHelper } from './helpers/beforeQueryHelper';
66

77
export interface CountResolverOpts {
8+
/** If you want to generate different resolvers you may avoid Type name collision by adding a suffix to type names */
9+
suffix?: string;
810
/** Customize input-type for `filter` argument. If `false` then arg will be removed. */
911
filter?: FilterHelperArgsOpts | false;
1012
}
@@ -35,7 +37,7 @@ export function count<TSource = any, TContext = any, TDoc extends Document = any
3537
args: {
3638
...filterHelperArgs(tc, model, {
3739
prefix: 'FilterCount',
38-
suffix: 'Input',
40+
suffix: `${opts?.suffix || ''}Input`,
3941
...opts?.filter,
4042
}),
4143
},

src/resolvers/createMany.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import { validateManyAndThrow } from './helpers/validate';
66
import { payloadRecordIds, PayloadRecordIdsHelperOpts } from './helpers/payloadRecordId';
77

88
export interface CreateManyResolverOpts {
9+
/** If you want to generate different resolvers you may avoid Type name collision by adding a suffix to type names */
10+
suffix?: string;
911
/** Customize input-type for `records` argument. */
1012
records?: RecordHelperArgsOpts;
1113
/** Customize payload.recordIds field. If false, then this field will be removed. */
@@ -42,7 +44,7 @@ export function createMany<TSource = any, TContext = any, TDoc extends Document
4244
}
4345
}
4446

45-
const outputTypeName = `CreateMany${tc.getTypeName()}Payload`;
47+
const outputTypeName = `CreateMany${tc.getTypeName()}${opts?.suffix || ''}Payload`;
4648
const outputType = tc.schemaComposer.getOrCreateOTC(outputTypeName, (t) => {
4749
t.setFields({
4850
...payloadRecordIds(tc, opts?.recordIds),
@@ -67,7 +69,7 @@ export function createMany<TSource = any, TContext = any, TDoc extends Document
6769
records: {
6870
type: (recordHelperArgs(tc, {
6971
prefix: 'CreateMany',
70-
suffix: 'Input',
72+
suffix: `${opts?.suffix || ''}Input`,
7173
removeFields: ['id', '_id'],
7274
isRequired: true,
7375
requiredFields,

src/resolvers/createOne.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { validateAndThrow } from './helpers/validate';
77
import { PayloadRecordIdHelperOpts, payloadRecordId } from './helpers/payloadRecordId';
88

99
export interface CreateOneResolverOpts {
10-
// TODO: add description
10+
/** If you want to generate different resolvers you may avoid Type name collision by adding a suffix to type names */
1111
suffix?: string;
1212
/** Customize input-type for `record` argument */
1313
record?: RecordHelperArgsOpts;

src/resolvers/findMany.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ import type { ExtendedResolveParams } from './index';
1919
import { beforeQueryHelper } from './helpers/beforeQueryHelper';
2020

2121
export interface FindManyResolverOpts {
22+
/** If you want to generate different resolvers you may avoid Type name collision by adding a suffix to type names */
23+
suffix?: string;
2224
/** Customize input-type for `filter` argument. If `false` then arg will be removed. */
2325
filter?: FilterHelperArgsOpts | false;
2426
sort?: SortHelperArgsOpts | false;
@@ -55,15 +57,15 @@ export function findMany<TSource = any, TContext = any, TDoc extends Document =
5557
args: {
5658
...filterHelperArgs(tc, model, {
5759
prefix: 'FilterFindMany',
58-
suffix: 'Input',
60+
suffix: `${opts?.suffix || ''}Input`,
5961
...opts?.filter,
6062
}),
6163
...skipHelperArgs(),
6264
...limitHelperArgs({
6365
...opts?.limit,
6466
}),
6567
...sortHelperArgs(tc, model, {
66-
sortTypeName: `SortFindMany${tc.getTypeName()}Input`,
68+
sortTypeName: `SortFindMany${tc.getTypeName()}${opts?.suffix || ''}Input`,
6769
...opts?.sort,
6870
}),
6971
},

src/resolvers/findManyLean.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import type { ExtendedResolveParams } from './index';
2121
import { beforeQueryHelperLean } from './helpers/beforeQueryHelper';
2222

2323
export interface FindManyLeanResolverOpts {
24+
/** If you want to generate different resolvers you may avoid Type name collision by adding a suffix to type names */
25+
suffix?: string;
2426
/** Customize input-type for `filter` argument. If `false` then arg will be removed. */
2527
filter?: FilterHelperArgsOpts | false;
2628
sort?: SortHelperArgsOpts | false;
@@ -60,15 +62,15 @@ export function findManyLean<TSource = any, TContext = any, TDoc extends Documen
6062
args: {
6163
...filterHelperArgs(tc, model, {
6264
prefix: 'FilterFindManyLean',
63-
suffix: 'Input',
65+
suffix: `${opts?.suffix || ''}Input`,
6466
...opts?.filter,
6567
}),
6668
...skipHelperArgs(),
6769
...limitHelperArgs({
6870
...opts?.limit,
6971
}),
7072
...sortHelperArgs(tc, model, {
71-
sortTypeName: `SortFindManyLean${tc.getTypeName()}Input`,
73+
sortTypeName: `SortFindManyLean${tc.getTypeName()}${opts?.suffix || ''}Input`,
7274
...opts?.sort,
7375
}),
7476
},

src/resolvers/findOne.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import type { ExtendedResolveParams } from './index';
1616
import { beforeQueryHelper } from './helpers/beforeQueryHelper';
1717

1818
export interface FindOneResolverOpts {
19+
/** If you want to generate different resolvers you may avoid Type name collision by adding a suffix to type names */
20+
suffix?: string;
1921
/** Customize input-type for `filter` argument. If `false` then arg will be removed. */
2022
filter?: FilterHelperArgsOpts | false;
2123
sort?: SortHelperArgsOpts | false;
@@ -50,12 +52,12 @@ export function findOne<TSource = any, TContext = any, TDoc extends Document = a
5052
args: {
5153
...filterHelperArgs(tc, model, {
5254
prefix: 'FilterFindOne',
53-
suffix: 'Input',
55+
suffix: `${opts?.suffix || ''}Input`,
5456
...opts?.filter,
5557
}),
5658
...skipHelperArgs(),
5759
...sortHelperArgs(tc, model, {
58-
sortTypeName: `SortFindOne${tc.getTypeName()}Input`,
60+
sortTypeName: `SortFindOne${tc.getTypeName()}${opts?.suffix || ''}Input`,
5961
...opts?.sort,
6062
}),
6163
},

src/resolvers/findOneLean.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ import type { ExtendedResolveParams } from './index';
1818
import { beforeQueryHelperLean } from './helpers/beforeQueryHelper';
1919

2020
export interface FindOneLeanResolverOpts {
21+
/** If you want to generate different resolvers you may avoid Type name collision by adding a suffix to type names */
22+
suffix?: string;
2123
/** Customize input-type for `filter` argument. If `false` then arg will be removed. */
2224
filter?: FilterHelperArgsOpts | false;
2325
sort?: SortHelperArgsOpts | false;
@@ -55,12 +57,12 @@ export function findOneLean<TSource = any, TContext = any, TDoc extends Document
5557
args: {
5658
...filterHelperArgs(tc, model, {
5759
prefix: 'FilterFindOneLean',
58-
suffix: 'Input',
60+
suffix: `${opts?.suffix || ''}Input`,
5961
...opts?.filter,
6062
}),
6163
...skipHelperArgs(),
6264
...sortHelperArgs(tc, model, {
63-
sortTypeName: `SortFindOneLean${tc.getTypeName()}Input`,
65+
sortTypeName: `SortFindOneLean${tc.getTypeName()}${opts?.suffix || ''}Input`,
6466
...opts?.sort,
6567
}),
6668
},

src/resolvers/removeById.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import { addErrorCatcherField } from './helpers/errorCatcher';
77
import { PayloadRecordIdHelperOpts, payloadRecordId } from './helpers/payloadRecordId';
88

99
export interface RemoveByIdResolverOpts {
10+
/** If you want to generate different resolvers you may avoid Type name collision by adding a suffix to type names */
11+
suffix?: string;
1012
/** Customize payload.recordId field. If false, then this field will be removed. */
1113
recordId?: PayloadRecordIdHelperOpts | false;
1214
}
@@ -32,7 +34,7 @@ export function removeById<TSource = any, TContext = any, TDoc extends Document
3234

3335
const findByIdResolver = findById(model, tc);
3436

35-
const outputTypeName = `RemoveById${tc.getTypeName()}Payload`;
37+
const outputTypeName = `RemoveById${tc.getTypeName()}${opts?.suffix || ''}Payload`;
3638
const outputType = tc.schemaComposer.getOrCreateOTC(outputTypeName, (t) => {
3739
t.setFields({
3840
...payloadRecordId(tc, opts?.recordId),

src/resolvers/removeMany.ts

+16-3
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,23 @@
11
import type { Resolver, ObjectTypeComposer } from 'graphql-compose';
22
import type { Model, Document } from 'mongoose';
3-
import { filterHelperArgs, filterHelper, prepareAliases, FilterHelperArgsOpts } from './helpers';
3+
import {
4+
filterHelperArgs,
5+
filterHelper,
6+
prepareAliases,
7+
FilterHelperArgsOpts,
8+
limitHelperArgs,
9+
LimitHelperArgsOpts,
10+
} from './helpers';
411
import type { ExtendedResolveParams } from './index';
512
import { beforeQueryHelper } from './helpers/beforeQueryHelper';
613
import { addErrorCatcherField } from './helpers/errorCatcher';
714

815
export interface RemoveManyResolverOpts {
16+
/** If you want to generate different resolvers you may avoid Type name collision by adding a suffix to type names */
17+
suffix?: string;
918
/** Customize input-type for `filter` argument. If `false` then arg will be removed. */
1019
filter?: FilterHelperArgsOpts | false;
20+
limit?: LimitHelperArgsOpts | false;
1121
}
1222

1323
type TArgs = {
@@ -29,7 +39,7 @@ export function removeMany<TSource = any, TContext = any, TDoc extends Document
2939
);
3040
}
3141

32-
const outputTypeName = `RemoveMany${tc.getTypeName()}Payload`;
42+
const outputTypeName = `RemoveMany${tc.getTypeName()}${opts?.suffix || ''}Payload`;
3343
const outputType = tc.schemaComposer.getOrCreateOTC(outputTypeName, (t) => {
3444
t.addFields({
3545
numAffected: {
@@ -52,10 +62,13 @@ export function removeMany<TSource = any, TContext = any, TDoc extends Document
5262
args: {
5363
...filterHelperArgs(tc, model, {
5464
prefix: 'FilterRemoveMany',
55-
suffix: 'Input',
65+
suffix: `${opts?.suffix || ''}Input`,
5666
isRequired: true,
5767
...opts?.filter,
5868
}),
69+
...limitHelperArgs({
70+
...opts?.limit,
71+
}),
5972
},
6073
resolve: (async (resolveParams: ExtendedResolveParams<TDoc>) => {
6174
const filterData = resolveParams?.args?.filter;

0 commit comments

Comments
 (0)