Skip to content

Commit 16a5140

Browse files
committed
Fix bugs with discrimTC resolvers, such as preferring model over scham dscriminators where present
1 parent d586798 commit 16a5140

File tree

2 files changed

+64
-39
lines changed

2 files changed

+64
-39
lines changed

src/enhancedDiscriminators/__tests__/eDiscriminatorTypeComposer-test.ts

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
GenerateResolverType,
77
} from '../../composeMongoose';
88
import { EDiscriminatorTypeComposer } from '../eDiscriminatorTypeComposer';
9-
import { Document, Model, Schema } from 'mongoose';
9+
import mongoose, { Document, Model, Schema } from 'mongoose';
1010

1111
const defaultDKey = 'type';
1212
const { CharacterModel } = getCharacterModels(defaultDKey);
@@ -80,15 +80,13 @@ describe('EDiscriminatorTypeComposer', () => {
8080

8181
describe('createFromModel errors', () => {
8282
it('should throw an error if it is called with no discriminators present', () => {
83+
const fakeModel = mongoose.model(
84+
'fakeModelEDiscrim',
85+
new Schema({ test: String, thingy: Boolean })
86+
);
87+
8388
const errorCall = () =>
84-
EDiscriminatorTypeComposer.createFromModel(
85-
{
86-
schema: new Schema({ test: String, thingy: Boolean }),
87-
},
88-
'noDiscrimType',
89-
schemaComposer,
90-
{}
91-
);
89+
EDiscriminatorTypeComposer.createFromModel(fakeModel, 'noDiscrimType', schemaComposer, {});
9290

9391
expect(errorCall).toThrowError('Discriminators should be present to use this function');
9492
});

src/enhancedDiscriminators/eDiscriminatorTypeComposer.ts

Lines changed: 57 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@ import {
66
ObjectTypeComposer,
77
ObjectTypeComposerFieldConfig,
88
ObjectTypeComposerFieldConfigDefinition,
9+
schemaComposer,
910
SchemaComposer,
1011
} from 'graphql-compose';
11-
import mongoose, { Document, Model } from 'mongoose';
12+
import { Document, Model, Schema } from 'mongoose';
1213
import { convertModelToGraphQL, MongoosePseudoModelT } from '../fieldsConverter';
1314
import { composeMongoose, ComposeMongooseOpts, GenerateResolverType } from '../composeMongoose';
1415

@@ -24,10 +25,10 @@ export function convertModelToGraphQLWithDiscriminators<TDoc extends Document, T
2425
// if includeNestedDiscriminators is true to indicate that convertModel should invoke this method
2526
opts.includeBaseDiscriminators = false;
2627

27-
if (!model.schema.discriminators) {
28+
if (!((model as Model<any, any>).discriminators || model.schema.discriminators)) {
2829
return convertModelToGraphQL(model, typeName, sc, opts);
2930
} else {
30-
return EDiscriminatorTypeComposer.createFromModel(model, typeName, sc, opts);
31+
return EDiscriminatorTypeComposer.createFromModel(model as Model<any, any>, typeName, sc, opts);
3132
}
3233
}
3334

@@ -41,9 +42,11 @@ export class EDiscriminatorTypeComposer<TSource, TContext> extends ObjectTypeCom
4142
> {
4243
discriminatorKey: string = '';
4344
discrimTCs: {
44-
[key: string]: ObjectTypeComposer<any, TContext> & {
45-
mongooseResolvers: GenerateResolverType<any, TContext>;
46-
};
45+
[key: string]:
46+
| (ObjectTypeComposer<any, TContext> & {
47+
mongooseResolvers: GenerateResolverType<any, TContext>;
48+
})
49+
| ObjectTypeComposer<any, TContext>;
4750
} = {};
4851

4952
BaseTC: ObjectTypeComposer<TSource, TContext>;
@@ -61,12 +64,12 @@ export class EDiscriminatorTypeComposer<TSource, TContext> extends ObjectTypeCom
6164
}
6265

6366
static createFromModel<TSrc = any, TCtx = any>(
64-
model: Model<any> | MongoosePseudoModelT,
67+
model: Model<any, any>,
6568
typeName: string,
6669
schemaComposer: SchemaComposer<TCtx>,
6770
opts: ComposeMongooseDiscriminatorsOpts<any>
6871
): EDiscriminatorTypeComposer<TSrc, TCtx> {
69-
if (!model.schema.discriminators) {
72+
if (!((model as Model<any, any>).discriminators || model.schema.discriminators)) {
7073
throw Error('Discriminators should be present to use this function');
7174
}
7275

@@ -89,7 +92,7 @@ export class EDiscriminatorTypeComposer<TSource, TContext> extends ObjectTypeCom
8992
baseTC.clone(baseDTC as ObjectTypeComposer<any, any>);
9093

9194
baseDTC.opts = { ...opts };
92-
baseDTC.discriminatorKey = (model as any).schema.options.discriminatorKey;
95+
baseDTC.discriminatorKey = (model as any).schema.get('discriminatorKey') || '__t';
9396
if (baseDTC.discriminatorKey === '__t') {
9497
throw Error(
9598
'A custom discriminator key must be set on the model options in mongoose for discriminator behaviour to function correctly'
@@ -100,13 +103,10 @@ export class EDiscriminatorTypeComposer<TSource, TContext> extends ObjectTypeCom
100103
baseDTC.DInterface.setInputTypeComposer(baseDTC.DInputObject.getInputTypeComposer());
101104
baseDTC.setInputTypeComposer(baseDTC.DInputObject.getInputTypeComposer());
102105

103-
baseDTC.setInterfaces([baseDTC.DInterface]);
106+
// baseDTC.setInterfaces([baseDTC.DInterface]);
104107
baseDTC._gqcInputTypeComposer = baseDTC.DInputObject._gqcInputTypeComposer;
105108
baseDTC.DInterface._gqcInputTypeComposer = baseDTC.DInputObject._gqcInputTypeComposer;
106109

107-
// discriminators an object containing all discriminators with key being DNames
108-
// import { EDiscriminatorTypeComposer } from './enhancedDiscriminators/index';baseDTC.DKeyETC = createAndSetDKeyETC(baseDTC, discriminators);
109-
110110
// reorderFields(baseDTC, baseDTC.opts.reorderFields, baseDTC.discriminatorKey);
111111
baseDTC.schemaComposer.addSchemaMustHaveType(baseDTC as any);
112112

@@ -117,25 +117,44 @@ export class EDiscriminatorTypeComposer<TSource, TContext> extends ObjectTypeCom
117117
}
118118

119119
_buildDiscriminatedInterface(
120-
model: Model<any> | MongoosePseudoModelT,
120+
model: Model<any, any>,
121121
baseTC: ObjectTypeComposer<any, TContext>
122122
): InterfaceTypeComposer<TSource, TContext> {
123123
const interfaceTC = this.DInterface;
124124
interfaceTC.removeOtherFields('');
125125
interfaceTC.setFields(baseTC.getFields());
126126
this.DInputObject.setFields(baseTC.getFields());
127127

128-
Object.keys((model as any).schema.discriminators).forEach((key) => {
129-
const discrimType = (model as any).schema.discriminators[key];
128+
const discriminators = model.discriminators || model.schema.discriminators;
130129

131-
// ensure valid type for calling convert
132-
const discrimModel =
133-
discrimType instanceof mongoose.Schema ? { schema: discrimType } : discrimType;
130+
if (!discriminators) {
131+
throw Error('Discriminators should be present to use this function');
132+
}
134133

135-
const discrimTC = composeMongoose(discrimModel, {
136-
...this.opts,
137-
name: this.getTypeName() + key,
138-
});
134+
Object.keys(discriminators).forEach((key) => {
135+
if (!discriminators[key]) {
136+
throw Error(
137+
`Discriminator Model of ${model.name} missing for discriminator with key of ${key}`
138+
);
139+
}
140+
141+
const discrimType = discriminators[key];
142+
143+
const discrimTC =
144+
discrimType instanceof Schema
145+
? convertModelToGraphQL(
146+
{ schema: discrimType },
147+
this.getTypeName() + key,
148+
schemaComposer,
149+
{
150+
...this.opts,
151+
name: this.getTypeName() + key,
152+
}
153+
)
154+
: composeMongoose(discrimType as Model<any>, {
155+
...this.opts,
156+
name: this.getTypeName() + key,
157+
});
139158

140159
// base OTC used for input schema must hold all child TC fields in the most loose way (so all types are accepted)
141160
// more detailed type checks are done on input object by mongoose itself
@@ -152,18 +171,13 @@ export class EDiscriminatorTypeComposer<TSource, TContext> extends ObjectTypeCom
152171
this.DInputObject.makeFieldNullable(
153172
discrimTC.getFieldNames().filter((field) => !baseTC.hasField(field))
154173
);
155-
discrimTC.makeFieldNonNull('_id');
156174

157175
// also set fields on master TC so it will have all possibilities for input workaround
158176

159-
const discrimVal = discrimType.discriminatorMapping.value;
160-
interfaceTC.addTypeResolver(
161-
discrimTC,
162-
(obj: any) => obj[this.discriminatorKey] === discrimVal
163-
);
177+
interfaceTC.addTypeResolver(discrimTC, (obj: any) => obj[this.discriminatorKey] === key);
164178

165179
// add TC to discrimTCs
166-
this.discrimTCs[discrimTC.getTypeName()] = discrimTC;
180+
this.discrimTCs[key] = discrimTC;
167181
});
168182

169183
return interfaceTC;
@@ -199,6 +213,19 @@ export class EDiscriminatorTypeComposer<TSource, TContext> extends ObjectTypeCom
199213
return this.DInputObject as any;
200214
}
201215

216+
getDiscriminatorTCs(): {
217+
[key: string]: ObjectTypeComposer<any, TContext> & {
218+
mongooseResolvers: GenerateResolverType<any, TContext>;
219+
};
220+
} {
221+
// check if mongooseResolvers are present
222+
if ((this.discrimTCs[Object.keys(this.discrimTCs)[0]] as any).mongooseResolvers) {
223+
return this.discrimTCs as any;
224+
} else {
225+
return {};
226+
}
227+
}
228+
202229
// OVERRIDES
203230
getTypeName(): string {
204231
return this.DInterface.getTypeName();

0 commit comments

Comments
 (0)