Skip to content

Commit

Permalink
Adds support for custom enum value resolvers (#508)
Browse files Browse the repository at this point in the history
* Add support for custom enum values

* Adds support for custom values in Enums on a schema

Signed-off-by: Sarah Weir <sweir27@gmail.com>

* Adds some extra tests around merged schemas

Signed-off-by: Sarah Weir <sweir27@gmail.com>

* Tighten the types on a custom Enum definition

* Adds an 'as any' to the type when it is known as an enum
  • Loading branch information
orta authored and Sashko Stubailo committed Nov 28, 2017
1 parent 499ab8e commit 907b8a1
Show file tree
Hide file tree
Showing 5 changed files with 343 additions and 181 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

### VNEXT

* ...
* Added basic support for custom Enums [Issue #363](https://github.com/apollographql/graphql-tools/issues/363) [PR #507](https://github.com/apollographql/graphql-tools/pull/507)


### v2.9.0

Expand Down
3 changes: 2 additions & 1 deletion src/Interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@ export type ITypeDefinitions = ITypedef | ITypedef[];
export type IResolverObject = {
[key: string]: GraphQLFieldResolver<any, any> | IResolverOptions;
};
export type IEnumResolver = { [key: string]: string };
export interface IResolvers {
[key: string]: (() => any) | IResolverObject | GraphQLScalarType;
[key: string]: (() => any) | IResolverObject | GraphQLScalarType | IEnumResolver;
}
export interface ILogger {
log: (message: string | Error) => void;
Expand Down
14 changes: 14 additions & 0 deletions src/schemaGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
// a bunch of utility functions into a separate utitlities folder, one file per function.

import {
GraphQLEnumType,
DocumentNode,
parse,
print,
Expand Down Expand Up @@ -372,6 +373,19 @@ function addResolveFunctionsToSchema(
return;
}

if (type instanceof GraphQLEnumType) {
// TODO: Remove once https://github.com/DefinitelyTyped/DefinitelyTyped/pull/21786
// is inside NPM
if (!(type as any).isValidValue(fieldName)) {
throw new SchemaError(
`${typeName}.${fieldName} was defined in resolvers, but enum is not in schema`,
);
}

type.getValue(fieldName)['value'] = resolveFunctions[typeName][fieldName];
return;
}

const fields = getFieldsForType(type);
if (!fields) {
if (allowResolversNotInSchema) {
Expand Down
68 changes: 68 additions & 0 deletions src/test/testMergeSchemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
subscriptionPubSubTrigger,
} from './testingSchemas';
import { forAwaitEach } from 'iterall';
import { makeExecutableSchema } from '../schemaGenerator';

const testCombinations = [
{ name: 'local', booking: localBookingSchema, property: localPropertySchema },
Expand Down Expand Up @@ -53,6 +54,22 @@ const scalarTest = `
}
`;


const enumTest = `
# A type that uses an Enum.
enum Color {
RED
}
schema {
query: Query
}
type Query {
color: Color
}
`;

const linkSchema = `
# A new type linking the Property type.
type LinkType {
Expand Down Expand Up @@ -107,6 +124,7 @@ testCombinations.forEach(async combination => {
propertySchema,
bookingSchema,
scalarTest,
enumTest,
linkSchema,
localSubscriptionSchema,
],
Expand All @@ -118,6 +136,9 @@ testCombinations.forEach(async combination => {
parseValue: value => value,
parseLiteral: () => null,
}),
Color: {
RED: '#EA3232'
},
Property: {
bookings: {
fragment: 'fragment PropertyFragment on Property { id }',
Expand Down Expand Up @@ -167,6 +188,9 @@ testCombinations.forEach(async combination => {
},
},
Query: {
color() {
return '#EA3232';
},
delegateInterfaceTest(parent, args, context, info) {
return mergeInfo.delegate(
'query',
Expand Down Expand Up @@ -322,6 +346,46 @@ testCombinations.forEach(async combination => {
expect(mergedResult).to.deep.equal(propertyResult);
});

it('works with custom enums', async () => {
const enumSchema = makeExecutableSchema({
typeDefs: enumTest,
resolvers: {
Color: {
RED: '#EA3232'
},
Query: {
color() {
return '#EA3232';
},
},
}
});
const enumResult = await graphql(
enumSchema,
`
query {
color
}
`,
);

const mergedResult = await graphql(
mergedSchema,
`
query {
color
}
`,
);

expect(enumResult).to.deep.equal({
data: {
color: 'RED',
},
});
expect(mergedResult).to.deep.equal(enumResult);
});

it('queries', async () => {
const propertyFragment = `
propertyById(id: "p1") {
Expand Down Expand Up @@ -1392,6 +1456,10 @@ bookingById(id: $b1) {
'A type that uses TestScalar.',
);

expect(mergedSchema.getType('Color').description).to.equal(
'A type that uses an Enum.',
);

expect(mergedSchema.getType('LinkType').description).to.equal(
'A new type linking the Property type.',
);
Expand Down
Loading

0 comments on commit 907b8a1

Please sign in to comment.