Skip to content

Commit b60d243

Browse files
committed
refactor(discriminator): move DiscriminatorTypeComposer to own file
1 parent 5500456 commit b60d243

File tree

8 files changed

+247
-246
lines changed

8 files changed

+247
-246
lines changed

src/__tests__/composeWithMongooseDiscriminators-test.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,8 @@ import {
88
} from 'graphql-compose';
99
import { getCharacterModels } from '../__mocks__/characterModels';
1010
import { MovieModel } from '../__mocks__/movieModel';
11-
import {
12-
composeWithMongooseDiscriminators,
13-
DiscriminatorTypeComposer,
14-
} from '../composeWithMongooseDiscriminators';
11+
import { composeWithMongooseDiscriminators } from '../composeWithMongooseDiscriminators';
12+
import { DiscriminatorTypeComposer } from '../discriminators';
1513

1614
beforeAll(() => MovieModel.base.connect());
1715
afterAll(() => MovieModel.base.disconnect());

src/composeWithMongooseDiscriminators.js

Lines changed: 1 addition & 235 deletions
Original file line numberDiff line numberDiff line change
@@ -1,241 +1,7 @@
11
/* @flow */
22

3-
import type { ComposeFieldConfigMap } from 'graphql-compose';
4-
import {
5-
EnumTypeComposer,
6-
graphql,
7-
schemaComposer,
8-
SchemaComposer,
9-
TypeComposer,
10-
} from 'graphql-compose';
11-
import type { GraphQLFieldConfigMap } from 'graphql-compose/lib/graphql';
12-
import type {
13-
ComposePartialFieldConfigAsObject,
14-
RelationOpts,
15-
} from 'graphql-compose/lib/TypeComposer';
163
import { Model } from 'mongoose';
17-
import type { TypeConverterOpts } from './composeWithMongoose';
18-
import { composeWithMongoose } from './composeWithMongoose';
19-
import { composeChildTC } from './discriminators';
20-
import { mergeCustomizationOptions } from './discriminators/merge-customization-options';
21-
import { prepareBaseResolvers } from './discriminators/prepare-resolvers/prepareBaseResolvers';
22-
import { reorderFields } from './discriminators/utils';
23-
24-
const { GraphQLInterfaceType } = graphql;
25-
26-
export type Options = {
27-
test_disTypes?: boolean,
28-
reorderFields?: boolean | string[], // true order: _id, DKey, DInterfaceFields, DiscriminatorFields
29-
customizationOptions?: TypeConverterOpts,
30-
};
31-
32-
type Discriminators = {
33-
[DName: string]: any,
34-
};
35-
36-
// sets the values on DKey enum TC
37-
function setDKeyETCValues(discriminators: Discriminators): any {
38-
const values: { [propName: string]: { value: string } } = {};
39-
40-
for (const DName in discriminators) {
41-
if (discriminators.hasOwnProperty(DName)) {
42-
values[DName] = {
43-
value: DName,
44-
};
45-
}
46-
}
47-
48-
return values;
49-
}
50-
51-
// creates an enum from discriminator names
52-
// then sets this enum type as the discriminator key field type
53-
function createAndSetDKeyETC(dTC: DiscriminatorTypeComposer, discriminators: Discriminators) {
54-
const DKeyETC = EnumTypeComposer.create({
55-
name: `EnumDKey${dTC.getDBaseName()}${dTC.getDKey()[0].toUpperCase() +
56-
dTC.getDKey().substr(1)}`,
57-
values: setDKeyETCValues(discriminators),
58-
});
59-
60-
// set on Output
61-
dTC.extendField(dTC.getDKey(), {
62-
type: () => DKeyETC,
63-
});
64-
65-
// set on Input
66-
dTC.getInputTypeComposer().extendField(dTC.getDKey(), {
67-
type: () => DKeyETC,
68-
});
69-
70-
return DKeyETC;
71-
}
72-
73-
function getBaseTCFieldsWithTypes(baseTC: TypeComposer) {
74-
const baseFields = baseTC.getFieldNames();
75-
const baseFieldsWithTypes: GraphQLFieldConfigMap<any, any> = {};
76-
77-
for (const field of baseFields) {
78-
baseFieldsWithTypes[field] = baseTC.getFieldConfig(field);
79-
}
80-
81-
return baseFieldsWithTypes;
82-
}
83-
84-
function createDInterface(baseModelTC: DiscriminatorTypeComposer): GraphQLInterfaceType {
85-
return new GraphQLInterfaceType({
86-
name: `${baseModelTC.getDBaseName()}Interface`,
87-
88-
resolveType: (value: any) => {
89-
const childDName = value[baseModelTC.getDKey()];
90-
91-
if (childDName) {
92-
return baseModelTC.schemaComposer.getTC(childDName).getType();
93-
}
94-
95-
// as fallback return BaseModelTC
96-
return baseModelTC.schemaComposer.getTC(baseModelTC.getTypeName()).getType();
97-
},
98-
// hoisting issue solved, get at time :)
99-
fields: () => getBaseTCFieldsWithTypes(baseModelTC),
100-
});
101-
}
102-
103-
export class DiscriminatorTypeComposer extends TypeComposer {
104-
modelName: string;
105-
106-
discriminatorKey: string;
107-
108-
DKeyETC: EnumTypeComposer;
109-
110-
schemaComposer: SchemaComposer<any>;
111-
112-
opts: Options;
113-
114-
DInterface: GraphQLInterfaceType;
115-
116-
discriminators: Discriminators;
117-
118-
childTCs: TypeComposer[];
119-
120-
constructor(baseModel: Model, opts?: any) {
121-
if (!baseModel || !(baseModel: any).discriminators) {
122-
throw Error('Discriminator Key not Set, Use composeWithMongoose for Normal Collections');
123-
}
124-
125-
opts = { // eslint-disable-line
126-
reorderFields: true,
127-
customizationOptions: {
128-
schemaComposer,
129-
},
130-
...opts,
131-
};
132-
133-
super(composeWithMongoose(baseModel, opts.customizationOptions).gqType);
134-
135-
// !ORDER MATTERS
136-
this.opts = opts;
137-
this.modelName = (baseModel: any).modelName;
138-
this.discriminatorKey = (baseModel: any).schema.get('discriminatorKey') || '__t';
139-
140-
// discriminants and object containing all discriminants with key
141-
// key being their DNames
142-
this.discriminators = (baseModel: any).discriminators;
143-
144-
this.childTCs = [];
145-
this.schemaComposer =
146-
opts.customizationOptions && opts.customizationOptions.schemaComposer
147-
? opts.customizationOptions.schemaComposer
148-
: schemaComposer;
149-
this.setTypeName(this.modelName);
150-
this.DKeyETC = createAndSetDKeyETC(this, this.discriminators);
151-
152-
reorderFields(this, (this.opts: any).reorderFields, this.discriminatorKey);
153-
154-
this.DInterface = createDInterface(this);
155-
this.setInterfaces([this.DInterface]);
156-
157-
this.schemaComposer.addSchemaMustHaveType(this);
158-
159-
// prepare Base Resolvers
160-
prepareBaseResolvers(this);
161-
}
162-
163-
getDKey(): string {
164-
return this.discriminatorKey;
165-
}
166-
167-
getDKeyETC(): EnumTypeComposer {
168-
return this.DKeyETC;
169-
}
170-
171-
getDBaseName(): string {
172-
return this.modelName;
173-
}
174-
175-
getDInterface(): GraphQLInterfaceType {
176-
return this.DInterface;
177-
}
178-
179-
hasChildTC(DName: string): boolean {
180-
return !!this.childTCs.find(ch => ch.getTypeName() === DName);
181-
}
182-
183-
// add fields only to DInterface, baseTC, childTC
184-
addDFields(newDFields: ComposeFieldConfigMap<any, any>): this {
185-
super.addFields(newDFields);
186-
187-
for (const childTC of this.childTCs) {
188-
childTC.addFields(newDFields);
189-
}
190-
191-
return this;
192-
}
193-
194-
extendDField(
195-
fieldName: string,
196-
partialFieldConfig: ComposePartialFieldConfigAsObject<any, any>
197-
): this {
198-
super.extendField(fieldName, partialFieldConfig);
199-
200-
for (const childTC of this.childTCs) {
201-
childTC.extendField(fieldName, partialFieldConfig);
202-
}
203-
204-
return this;
205-
}
206-
207-
// relations with args are a bit hard to manage as interfaces i believe as of now do not
208-
// support field args. Well if one wants to have use args, you setType for resolver as this
209-
// this = this DiscriminantTypeComposer
210-
// NOTE, those relations will be propagated to the childTypeComposers and you can use normally.
211-
// FixMe: Note, You must use this function after creating all discriminators
212-
addDRelation(fieldName: string, relationOpts: RelationOpts<any, any>): this {
213-
this.addRelation(fieldName, relationOpts);
214-
215-
for (const childTC of this.childTCs) {
216-
childTC.addRelation(fieldName, relationOpts);
217-
}
218-
219-
return this;
220-
}
221-
222-
/* eslint no-use-before-define: 0 */
223-
discriminator(childModel: Model, opts?: TypeConverterOpts): TypeComposer {
224-
const customizationOpts = mergeCustomizationOptions(
225-
(this.opts: any).customizationOptions,
226-
opts
227-
);
228-
229-
let childTC = composeWithMongoose(childModel, customizationOpts);
230-
231-
childTC = composeChildTC(this, childTC, this.opts);
232-
233-
this.schemaComposer.addSchemaMustHaveType(childTC);
234-
this.childTCs.push(childTC);
235-
236-
return childTC;
237-
}
238-
}
4+
import { Options, DiscriminatorTypeComposer } from './discriminators';
2395

2406
export function composeWithMongooseDiscriminators(
2417
baseModel: Model,

0 commit comments

Comments
 (0)