Skip to content

Commit c5ea420

Browse files
committed
preliminary refactor for unions. common field names now appear in the union type in reponse to #44
1 parent c1cf473 commit c5ea420

File tree

2 files changed

+32
-39
lines changed

2 files changed

+32
-39
lines changed

src/@types/buildTypeWeights.d.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,12 @@ export interface TypeWeightSet {
3131
type Variables = {
3232
[index: string]: readonly unknown;
3333
};
34+
35+
// Type for use when getting fields for union types
36+
type FieldMap = {
37+
[index: string]: {
38+
type: GraphQLOutputType;
39+
weight?: FieldWeight;
40+
resolveTo?: string;
41+
};
42+
};

src/analysis/buildTypeWeights.ts

Lines changed: 23 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import {
1717
ValueNode,
1818
GraphQLUnionType,
1919
GraphQLFieldMap,
20-
GraphQLField,
2120
} from 'graphql';
2221
import { ObjMap } from 'graphql/jsutils/ObjMap';
2322
import { GraphQLSchema } from 'graphql/type/schema';
@@ -28,6 +27,8 @@ import {
2827
Variables,
2928
Type,
3029
Fields,
30+
FieldWeight,
31+
FieldMap,
3132
} from '../@types/buildTypeWeights';
3233

3334
export const KEYWORDS = ['first', 'last', 'limit'];
@@ -158,10 +159,6 @@ function parseObjectFields(
158159
// Users must query union types using inline fragments to resolve field specific to one of the types in the union
159160
// however, if a type is shared by all types in the union it can be queried outside of the inline fragment
160161
// any common fields should be added to fields on the union type itself in addition to the comprising types
161-
// Get all types in the union
162-
// iterate through all types creating a set of type names
163-
// add resulting set to fields
164-
// FIXME: What happens if two types share a name that resolve to different types => invalid query?
165162
result.fields[field] = {
166163
resolveTo: fieldType.name.toLocaleLowerCase(),
167164
};
@@ -230,11 +227,8 @@ function parseTypes(schema: GraphQLSchema, typeWeights: TypeWeightSet): TypeWeig
230227
}
231228
});
232229

233-
type FieldMap = { [index: string]: GraphQLOutputType };
234-
type CommonFields = { [index: string]: Type };
235-
236230
unions.forEach((unionType: GraphQLUnionType) => {
237-
/** Start with the fields for the first object. Store fieldnamd and type
231+
/** Start with the fields for the first object. Store fieldname, type, weight and resolve to for later use
238232
* reduce by selecting fields common to each type
239233
* compare both fieldname and output type accounting for lists and non-nulls
240234
* for object
@@ -249,9 +243,17 @@ function parseTypes(schema: GraphQLSchema, typeWeights: TypeWeightSet): TypeWeig
249243
const types: FieldMap[] = unionType.getTypes().map((objectType: GraphQLObjectType) => {
250244
const fields: GraphQLFieldMap<any, any> = objectType.getFields();
251245

252-
const fieldMap: { [index: string]: GraphQLOutputType } = {};
246+
const fieldMap: FieldMap = {};
253247
Object.keys(fields).forEach((field: string) => {
254-
fieldMap[field] = fields[field].type;
248+
// Get the weight of this field on from parent type on the root typeWeight object.
249+
// this only exists for scalars and lists (which resolve to a function);
250+
const { weight, resolveTo } = result[objectType.name.toLowerCase()].fields[field];
251+
252+
fieldMap[field] = {
253+
type: fields[field].type,
254+
weight, // will only be undefined for object types
255+
resolveTo,
256+
};
255257
});
256258
return fieldMap;
257259
});
@@ -261,7 +263,7 @@ function parseTypes(schema: GraphQLSchema, typeWeights: TypeWeightSet): TypeWeig
261263
const commonFields: FieldMap = {};
262264
Object.keys(prev).forEach((field: string) => {
263265
if (fieldMap[field]) {
264-
if (compareTypes(prev[field], fieldMap[field])) {
266+
if (compareTypes(prev[field].type, fieldMap[field].type)) {
265267
// they match add the type to the next set
266268
commonFields[field] = prev[field];
267269
}
@@ -274,48 +276,30 @@ function parseTypes(schema: GraphQLSchema, typeWeights: TypeWeightSet): TypeWeig
274276
const fieldTypes: Fields = {};
275277

276278
Object.keys(common).forEach((field: string) => {
277-
// if a scalar => weight
278-
// object => resolveTo
279-
// list => // resolveTo + weight(function)
280-
const current = common[field];
279+
// scalar => weight
280+
// list => resolveTo + weight(function)
281+
// fields that resolve to objects do not need to appear on the union type
282+
const current = common[field].type;
281283
if (isScalarType(current)) {
282284
fieldTypes[field] = {
283-
weight: typeWeights.scalar,
285+
weight: common[field].weight,
284286
};
285-
}
286-
// else if (isObjectType(current)) {
287-
// fieldTypes[field] = {
288-
// resolveTo: current.name,
289-
// };
290-
// }
291-
else if (isListType(current)) {
292-
throw new Error('list types not supported on unions');
287+
} else if (isListType(current)) {
293288
fieldTypes[field] = {
294-
resolveTo: 'test', // get resolve type problem is recursive data structure (i.e. list of lists)
295-
// weight: TODO: Get the function for resolving
289+
resolveTo: common[field].resolveTo,
290+
weight: common[field].weight,
296291
};
297292
} else if (isNonNullType(current)) {
298293
throw new Error('non null types not supported on unions');
299294
// TODO: also a recursive data structure
300295
} else {
301-
throw new Error('Unandled union type. Should never get here');
296+
throw new Error('Unhandled union type. Should never get here');
302297
}
303298
});
304299
result[unionType.name.toLowerCase()] = {
305300
fields: fieldTypes,
306301
weight: typeWeights.object,
307302
};
308-
309-
//
310-
// objects are not. they exist at the root.
311-
// FIXME: Is it worth adding objects as a field?
312-
// yes, I think so => refactor fieldNode parser
313-
// if it resolves to object then add commonFields set
314-
// i think we have this already.
315-
// double check the non-null tests
316-
// commonFields.add({
317-
// weight,
318-
// });
319303
});
320304

321305
return result;

0 commit comments

Comments
 (0)