Skip to content
This repository has been archived by the owner on Apr 15, 2020. It is now read-only.

Commit

Permalink
fix(stitching): nested enums
Browse files Browse the repository at this point in the history
  • Loading branch information
yaacovCR committed Jun 16, 2019
1 parent d8d418a commit 0cd8b96
Show file tree
Hide file tree
Showing 9 changed files with 104 additions and 117 deletions.
71 changes: 71 additions & 0 deletions src/stitching/checkResultAndHandleErrors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import {
GraphQLResolveInfo,
responsePathAsArray,
getNullableType,
isObjectType,
isListType,
isEnumType,
ExecutionResult,
GraphQLError,
} from 'graphql';
import { getResponseKeyFromInfo } from './getResponseKeyFromInfo';
import {
relocatedError,
combineErrors,
annotateWithChildrenErrors
} from './errors';

export function checkResultAndHandleErrors(
result: ExecutionResult,
info: GraphQLResolveInfo,
responseKey?: string
): any {
if (!responseKey) {
responseKey = getResponseKeyFromInfo(info);
}

if (!result.data) {
if (result.errors) {
throw relocatedError(
combineErrors(result.errors),
info.fieldNodes,
responsePathAsArray(info.path)
);
} else {
return null;
}
}

return handleResult(info, result.data[responseKey], result.errors || []);
}

export function handleResult(
info: GraphQLResolveInfo,
resultObject: any,
errors: ReadonlyArray<GraphQLError>
): any {
if (!resultObject) {
if (errors.length) {
throw relocatedError(
combineErrors(errors),
info.fieldNodes,
responsePathAsArray(info.path)
);
} else {
return null;
}
}

const nullableType = getNullableType(info.returnType);

if (isObjectType(nullableType) || isListType(nullableType)) {
annotateWithChildrenErrors(resultObject, errors);
} else if (isEnumType(nullableType)) {
const value = nullableType.getValue(resultObject);
if (value) {
return value.value;
}
}

return resultObject;
}
35 changes: 5 additions & 30 deletions src/stitching/defaultMergedResolver.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,12 @@
import {
GraphQLFieldResolver,
responsePathAsArray,
getNullableType,
isObjectType,
isListType
} from 'graphql';
import {
getErrorsFromParent,
annotateWithChildrenErrors,
combineErrors,
relocatedError
} from './errors';
import { GraphQLFieldResolver } from 'graphql';
import { getErrorsFromParent } from './errors';
import { handleResult } from './checkResultAndHandleErrors';
import { getResponseKeyFromInfo } from './getResponseKeyFromInfo';

// Resolver that knows how to:
// a) handle aliases for proxied schemas
// b) handle errors from proxied schemas
// c) handle external to internal enum coversion
const defaultMergedResolver: GraphQLFieldResolver<any, any> = (parent, args, context, info) => {
if (!parent) {
return null;
Expand All @@ -30,23 +21,7 @@ const defaultMergedResolver: GraphQLFieldResolver<any, any> = (parent, args, con
return parent[info.fieldName];
}

let result = parent[responseKey];

// if null, throw all possible errors
if (!result && errors.length) {
throw relocatedError(
combineErrors(errors),
info.fieldNodes,
responsePathAsArray(info.path)
);
}

const nullableType = getNullableType(info.returnType);
if (isObjectType(nullableType) || isListType(nullableType)) {
annotateWithChildrenErrors(result, errors);
}

return result;
return handleResult(info, parent[responseKey], errors);
};

export default defaultMergedResolver;
8 changes: 0 additions & 8 deletions src/stitching/delegateToSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import {
GraphQLSchema,
ExecutionResult,
NameNode,
isEnumType,
} from 'graphql';

import { Operation, Request, IDelegateToSchemaOptions } from '../Interfaces';
Expand All @@ -31,7 +30,6 @@ import CheckResultAndHandleErrors from '../transforms/CheckResultAndHandleErrors
import mapAsyncIterator from './mapAsyncIterator';
import ExpandAbstractTypes from '../transforms/ExpandAbstractTypes';
import ReplaceFieldWithFragment from '../transforms/ReplaceFieldWithFragment';
import ConvertEnumResponse from '../transforms/ConvertEnumResponse';

export default function delegateToSchema(
options: IDelegateToSchemaOptions | GraphQLSchema,
Expand Down Expand Up @@ -85,12 +83,6 @@ async function delegateToSchemaImplementation(
new CheckResultAndHandleErrors(info, options.fieldName),
]);

if (isEnumType(options.info.returnType)) {
transforms = transforms.concat(
new ConvertEnumResponse(options.info.returnType),
);
}

const processedRequest = applyRequestTransforms(rawRequest, transforms);

if (!options.skipValidation) {
Expand Down
38 changes: 0 additions & 38 deletions src/stitching/errors.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
import {
GraphQLResolveInfo,
responsePathAsArray,
getNullableType,
isObjectType,
isListType,
ExecutionResult,
GraphQLError,
ASTNode
} from 'graphql';
import { getResponseKeyFromInfo } from './getResponseKeyFromInfo';

export let ERROR_SYMBOL: any;
if (
Expand Down Expand Up @@ -116,37 +109,6 @@ class CombinedError extends Error {
}
}

export function checkResultAndHandleErrors(
result: ExecutionResult,
info: GraphQLResolveInfo,
responseKey?: string
): any {
if (!responseKey) {
responseKey = getResponseKeyFromInfo(info);
}

if (!result.data || !result.data[responseKey]) {
if (result.errors) {
throw relocatedError(
combineErrors(result.errors),
info.fieldNodes,
responsePathAsArray(info.path)
);
} else {
return null;
}
}

result.errors = result.errors || [];

let resultObject = result.data[responseKey];
const nullableType = getNullableType(info.returnType);
if (isObjectType(nullableType) || isListType(nullableType)) {
annotateWithChildrenErrors(resultObject, result.errors);
}
return resultObject;
}

export function combineErrors(errors: ReadonlyArray<GraphQLError>): GraphQLError | CombinedError {
if (errors.length === 1) {
return new GraphQLError(
Expand Down
2 changes: 1 addition & 1 deletion src/stitching/makeRemoteExecutableSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import { makeExecutableSchema } from '../makeExecutableSchema';
import { recreateType } from './schemaRecreation';
import resolveParentFromTypename from './resolveFromParentTypename';
import defaultMergedResolver from './defaultMergedResolver';
import { checkResultAndHandleErrors } from './errors';
import { checkResultAndHandleErrors } from './checkResultAndHandleErrors';
import { observableToAsyncIterable } from './observableToAsyncIterable';

export type ResolverFn = (
Expand Down
2 changes: 1 addition & 1 deletion src/test/testErrors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import { assert } from 'chai';
import { GraphQLResolveInfo, GraphQLError } from 'graphql';
import {
relocatedError,
checkResultAndHandleErrors,
getErrorsFromParent,
ERROR_SYMBOL
} from '../stitching/errors';
import { checkResultAndHandleErrors } from '../stitching/checkResultAndHandleErrors';

import 'mocha';

Expand Down
45 changes: 25 additions & 20 deletions src/test/testMergeSchemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,13 +97,19 @@ let enumTest = `
TEST @deprecated(reason: "This is deprecated")
}
type EnumWrapper {
color: Color
numericEnum: NumericEnum
}
schema {
query: Query
}
type Query {
color: Color
numericEnum: NumericEnum
wrappedEnum: EnumWrapper
}
`;

Expand All @@ -125,6 +131,12 @@ enumSchema = makeExecutableSchema({
numericEnum() {
return 1;
},
wrappedEnum() {
return {
color: '#EA3232',
numericEnum: 1
};
},
},
},
});
Expand Down Expand Up @@ -532,27 +544,8 @@ testCombinations.forEach(async combination => {
});

it('works with custom enums', async () => {
const localSchema = makeExecutableSchema({
typeDefs: enumTest,
resolvers: {
Color: {
RED: '#EA3232',
},
NumericEnum: {
TEST: 1,
},
Query: {
color() {
return '#EA3232';
},
numericEnum() {
return 1;
},
},
},
});
const enumResult = await graphql(
localSchema,
enumSchema,
`
query {
color
Expand All @@ -571,6 +564,10 @@ testCombinations.forEach(async combination => {
description
}
}
wrappedEnum {
color
numericEnum
}
}
`,
);
Expand All @@ -595,6 +592,10 @@ testCombinations.forEach(async combination => {
description
}
}
wrappedEnum {
color
numericEnum
}
}
`,
);
Expand All @@ -621,6 +622,10 @@ testCombinations.forEach(async combination => {
},
],
},
wrappedEnum: {
color: 'RED',
numericEnum: 'TEST',
},
},
});
expect(mergedResult).to.deep.equal(enumResult);
Expand Down
2 changes: 1 addition & 1 deletion src/transforms/CheckResultAndHandleErrors.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { GraphQLResolveInfo } from 'graphql';
import { checkResultAndHandleErrors } from '../stitching/errors';
import { checkResultAndHandleErrors } from '../stitching/checkResultAndHandleErrors';
import { Transform } from './transforms';

export default class CheckResultAndHandleErrors implements Transform {
Expand Down
18 changes: 0 additions & 18 deletions src/transforms/ConvertEnumResponse.ts

This file was deleted.

0 comments on commit 0cd8b96

Please sign in to comment.