diff --git a/CHANGELOG.md b/CHANGELOG.md
index b1fdec3be07..04bf1077700 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,9 @@
### Next
+- Fix visitEnumValue to allow modifying the enum value
+ [@danielrearden](https://github.com/danielrearden) in [#1003](https://github.com/ardatan/graphql-tools/pull/1391)
+
### 5.0.0
That is a major release where we went through all issues and PRs and got the library back into great shape.
diff --git a/src/test/directives.test.ts b/src/test/directives.test.ts
index e4010618f16..9cd4e6d39e2 100644
--- a/src/test/directives.test.ts
+++ b/src/test/directives.test.ts
@@ -1358,6 +1358,41 @@ describe('@directives', () => {
]);
});
+ test("can modify enum value's value", () => {
+ const schema = makeExecutableSchema({
+ typeDefs: `
+ directive @value(new: String!) on ENUM_VALUE
+
+ type Query {
+ device: Device
+ }
+
+ enum Device {
+ PHONE
+ TABLET
+ LAPTOP @value(new: "COMPUTER")
+ }`,
+
+ schemaDirectives: {
+ value: class extends SchemaDirectiveVisitor {
+ public visitEnumValue(value: GraphQLEnumValue): GraphQLEnumValue {
+ return {
+ ...value,
+ value: this.args.new,
+ };
+ }
+ },
+ },
+ });
+
+ const Device = schema.getType('Device') as GraphQLEnumType;
+ expect(Device.getValues().map((value) => value.value)).toEqual([
+ 'PHONE',
+ 'TABLET',
+ 'COMPUTER',
+ ]);
+ });
+
test('can swap names of GraphQLNamedType objects', () => {
const schema = makeExecutableSchema({
typeDefs: `
diff --git a/src/utils/visitSchema.ts b/src/utils/visitSchema.ts
index 282bc684aa0..ffb219eb839 100644
--- a/src/utils/visitSchema.ts
+++ b/src/utils/visitSchema.ts
@@ -14,6 +14,8 @@ import {
isUnionType,
isEnumType,
isInputType,
+ GraphQLEnumValue,
+ GraphQLEnumType,
} from 'graphql';
import {
@@ -24,6 +26,7 @@ import {
SchemaVisitorMap,
} from '../Interfaces';
import updateEachKey from '../esUtils/updateEachKey';
+import keyValMap from '../esUtils/keyValMap';
import { healSchema } from './heal';
import { SchemaVisitor } from './SchemaVisitor';
@@ -193,14 +196,40 @@ export function visitSchema(
}
if (isEnumType(type)) {
- const newEnum = callMethod('visitEnum', type);
+ let newEnum = callMethod('visitEnum', type);
if (newEnum != null) {
- updateEachKey(newEnum.getValues(), (value) =>
- callMethod('visitEnumValue', value, {
+ const newValues: Array = [];
+
+ updateEachKey(newEnum.getValues(), (value) => {
+ const newValue = callMethod('visitEnumValue', value, {
enumType: newEnum,
- }),
+ });
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
+ if (newValue) {
+ newValues.push(newValue);
+ }
+ });
+
+ // Recreate the enum type if any of the values changed
+ const valuesUpdated = newValues.some(
+ (value, index) => value !== newEnum.getValues()[index],
);
+ if (valuesUpdated) {
+ newEnum = new GraphQLEnumType({
+ ...(newEnum as GraphQLEnumType).toConfig(),
+ values: keyValMap(
+ newValues,
+ (value) => value.name,
+ (value) => ({
+ value: value.value,
+ deprecationReason: value.deprecationReason,
+ description: value.description,
+ astNode: value.astNode,
+ }),
+ ),
+ }) as GraphQLEnumType & T;
+ }
}
return newEnum;