Skip to content

Commit 17fb449

Browse files
committed
Update produceType.js
1 parent 1262dbd commit 17fb449

File tree

2 files changed

+120
-43
lines changed

2 files changed

+120
-43
lines changed
Lines changed: 51 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
/* @flow */
12

3+
import { parse } from 'graphql/language';
24
import {
35
GraphQLScalarType,
46
GraphQLInt,
@@ -8,60 +10,88 @@ import {
810
GraphQLID,
911
GraphQLList,
1012
GraphQLNonNull,
13+
__Schema,
14+
__Directive,
15+
__DirectiveLocation,
16+
__Type,
17+
__Field,
18+
__InputValue,
19+
__EnumValue,
20+
__TypeKind,
1121
} from 'graphql/type';
12-
import { parse } from 'graphql/language';
13-
import produceType, { getNamedTypeAST, buildWrappedType } from '../produceType';
22+
import produceType, { getNamedTypeNode, buildWrappedType } from '../produceType';
1423

15-
const [{ type: innerTypeAST }, { type: wrappedTypeAST }] = parse(`
24+
const [{ type: wrappedTypeNode }, { type: wrapperTypeNode }] = (parse(`
1625
type Ints {
1726
int: Int
1827
nonNullListOfNonNullInt: [Int!]!
1928
}
20-
`, { noLocation: true }).definitions[0].fields;
29+
`, { noLocation: true }).definitions[0]: any).fields;
2130
const wrappedType = new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(GraphQLInt)));
2231

23-
describe('getNamedTypeAST()', () => {
24-
it('should work', () => {
25-
expect(getNamedTypeAST(wrappedTypeAST)).toEqual(innerTypeAST);
32+
describe('getNamedTypeNode()', () => {
33+
test('gets wrapped type nodes', () => {
34+
expect(getNamedTypeNode(wrapperTypeNode)).toEqual(wrappedTypeNode);
2635
});
2736
});
2837

2938
describe('buildWrappedType()', () => {
30-
it('should work', () => {
31-
expect(buildWrappedType(GraphQLInt, wrappedTypeAST)).toEqual(wrappedType);
39+
test('wraps types', () => {
40+
expect(buildWrappedType(GraphQLInt, wrapperTypeNode)).toEqual(wrappedType);
3241
});
3342
});
3443

3544
describe('produceType()', () => {
36-
const customTypeAST = parse(`
45+
const customTypeNode: any = parse(`
3746
scalar UUID
3847
`).definitions[0];
3948
const UUID = new GraphQLScalarType({ name: 'UUID', serialize: String });
4049

41-
it('should produce GraphQL scalars', () => {
42-
const typeAST = parse(`
43-
type Scalars {
50+
test('produces GraphQL inner types', () => {
51+
const typeNode: any = parse(`
52+
type InnerTypes {
4453
int: Int
4554
float: Float
4655
string: String
4756
boolean: Boolean
4857
id: ID
58+
schema: __Schema,
59+
directive: __Directive,
60+
directiveLocation: __DirectiveLocation,
61+
type: __Type,
62+
field: __Field,
63+
inputValue: __InputValue,
64+
enumValue: __EnumValue,
65+
typeKind: __TypeKind,
4966
}
5067
`).definitions[0];
51-
expect(typeAST.fields.map(({ type }) => type).map(produceType))
52-
.toEqual([GraphQLInt, GraphQLFloat, GraphQLString, GraphQLBoolean, GraphQLID]);
68+
expect(typeNode.fields.map(({ type }) => type).map(produceType)).toEqual([
69+
GraphQLInt,
70+
GraphQLFloat,
71+
GraphQLString,
72+
GraphQLBoolean,
73+
GraphQLID,
74+
__Schema,
75+
__Directive,
76+
__DirectiveLocation,
77+
__Type,
78+
__Field,
79+
__InputValue,
80+
__EnumValue,
81+
__TypeKind,
82+
]);
5383
});
5484

55-
it('should produce GraphQL type wrappers', () => {
56-
expect(produceType(wrappedTypeAST, [])).toEqual(wrappedType);
85+
test('produces GraphQL type wrappers', () => {
86+
expect(produceType(wrapperTypeNode, [])).toEqual(wrappedType);
5787
});
5888

59-
it('should produce custom types', () => {
60-
expect(produceType(customTypeAST, [UUID])).toEqual(UUID);
89+
test('produces custom types', () => {
90+
expect(produceType(customTypeNode, [UUID])).toEqual(UUID);
6191
});
6292

63-
it('should throw if it can\'t produce the type', () => {
64-
expect(() => produceType(customTypeAST, []))
93+
test('throws if it can\'t produce the type', () => {
94+
expect(() => produceType(customTypeNode, []))
6595
.toThrowError('Type "UUID" not found.');
6696
});
6797
});

src/build/produceType.js

Lines changed: 69 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,95 @@
1+
/* @flow */
2+
13
import {
4+
type GraphQLType,
5+
type GraphQLNamedType,
26
GraphQLInt,
37
GraphQLFloat,
48
GraphQLString,
59
GraphQLBoolean,
610
GraphQLID,
711
GraphQLList,
812
GraphQLNonNull,
13+
__Schema,
14+
__Directive,
15+
__DirectiveLocation,
16+
__Type,
17+
__Field,
18+
__InputValue,
19+
__EnumValue,
20+
__TypeKind,
921
} from 'graphql/type';
10-
import { Kind } from 'graphql/language';
11-
import resolveThunk from './resolveThunk';
22+
import { type TypeNode, type NamedTypeNode, Kind } from 'graphql/language';
23+
import invariant from './invariant';
24+
import resolveThunk, { type Thunk } from './resolveThunk';
1225

1326
const { LIST_TYPE, NON_NULL_TYPE } = Kind;
1427

15-
const scalarTypeMap = {
28+
/**
29+
* Mirror of [innerTypeMap]{@link https://github.com/graphql/graphql-js/blob/master/src/utilities/buildASTSchema.js#L228}.
30+
*/
31+
const innerTypeMap = {
1632
Int: GraphQLInt,
1733
Float: GraphQLFloat,
1834
String: GraphQLString,
1935
Boolean: GraphQLBoolean,
2036
ID: GraphQLID,
37+
__Schema,
38+
__Directive,
39+
__DirectiveLocation,
40+
__Type,
41+
__Field,
42+
__InputValue,
43+
__EnumValue,
44+
__TypeKind,
2145
};
2246

23-
export const getNamedTypeAST = (typeAST) => {
24-
let namedTypeAST = typeAST;
25-
while (namedTypeAST.kind === LIST_TYPE || namedTypeAST.kind === NON_NULL_TYPE) {
26-
namedTypeAST = namedTypeAST.type;
47+
/**
48+
* Retrieves the wrapped type AST given a wrapper type (GraphQLNonNull or GraphQLList) AST.
49+
*
50+
* Mirror of [getNamedTypeNode]{@link https://github.com/graphql/graphql-js/blob/master/src/utilities/buildASTSchema.js#L120}.
51+
*/
52+
export function getNamedTypeNode(typeNode: TypeNode): NamedTypeNode {
53+
let namedType = typeNode;
54+
while (namedType.kind === LIST_TYPE || namedType.kind === NON_NULL_TYPE) {
55+
namedType = namedType.type;
2756
}
28-
return namedTypeAST;
29-
};
57+
return namedType;
58+
}
3059

31-
export const buildWrappedType = (innerType, typeAST) => {
32-
if (typeAST.kind === LIST_TYPE) {
33-
return new GraphQLList(buildWrappedType(innerType, typeAST.type));
60+
/**
61+
* Builds a GraphQL wrapper type (GraphQLNonNull or GraphQLList) given the type to wrap and the AST
62+
* of the wrapper type.
63+
*
64+
* Mirror of [buildWrappedType]{@link https://github.com/graphql/graphql-js/blob/master/src/utilities/buildASTSchema.js#L105}.
65+
*/
66+
export function buildWrappedType(innerType: GraphQLType, inputTypeNode: TypeNode): GraphQLType {
67+
if (inputTypeNode.kind === LIST_TYPE) {
68+
return new GraphQLList(buildWrappedType(innerType, inputTypeNode.type));
3469
}
35-
if (typeAST.kind === NON_NULL_TYPE) {
36-
return new GraphQLNonNull(buildWrappedType(innerType, typeAST.type));
70+
if (inputTypeNode.kind === NON_NULL_TYPE) {
71+
const wrappedType = buildWrappedType(innerType, inputTypeNode.type);
72+
invariant(!(wrappedType instanceof GraphQLNonNull), 'No nesting nonnull.');
73+
return new GraphQLNonNull(wrappedType);
3774
}
3875
return innerType;
39-
};
76+
}
77+
78+
/**
79+
* Retrieves or builds a GraphQLType given the type AST and a thunk of GraphQLNamedType
80+
* dependencies.
81+
*/
82+
export default function produceType(
83+
typeNode: TypeNode,
84+
typeDependencies: Thunk<Array<GraphQLNamedType>>,
85+
): GraphQLType {
86+
const typeName = getNamedTypeNode(typeNode).name.value;
87+
88+
if (innerTypeMap[typeName]) return buildWrappedType(innerTypeMap[typeName], typeNode);
89+
90+
const type = resolveThunk(typeDependencies).find(({ name }) => name === typeName);
91+
92+
invariant(type, `Type "${typeName}" not found.`);
4093

41-
export default function produceType(typeAST, types) {
42-
const namedTypeAST = getNamedTypeAST(typeAST);
43-
const typeName = namedTypeAST.name.value;
44-
if (scalarTypeMap[typeName]) return buildWrappedType(scalarTypeMap[typeName], typeAST);
45-
const maybeType = resolveThunk(types).find(({ name }) => name === typeName);
46-
if (maybeType) return buildWrappedType(maybeType, typeAST);
47-
throw new Error(`Type "${typeName}" not found.`);
94+
return buildWrappedType(type, typeNode);
4895
}

0 commit comments

Comments
 (0)