Skip to content

Commit 6a1614c

Browse files
authored
backport[v16]: Enable passing values configuration to GraphQLEnumType as a thunk (#4122)
1 parent 29144f7 commit 6a1614c

File tree

2 files changed

+50
-9
lines changed

2 files changed

+50
-9
lines changed

src/type/__tests__/enumType-test.ts

+25
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,14 @@ const ComplexEnum = new GraphQLEnumType({
3131
},
3232
});
3333

34+
const ThunkValuesEnum = new GraphQLEnumType({
35+
name: 'ThunkValues',
36+
values: () => ({
37+
A: { value: 'a' },
38+
B: { value: 'b' },
39+
}),
40+
});
41+
3442
const QueryType = new GraphQLObjectType({
3543
name: 'Query',
3644
fields: {
@@ -84,6 +92,15 @@ const QueryType = new GraphQLObjectType({
8492
return fromEnum;
8593
},
8694
},
95+
thunkValuesString: {
96+
type: GraphQLString,
97+
args: {
98+
fromEnum: { type: ThunkValuesEnum },
99+
},
100+
resolve(_source, { fromEnum }) {
101+
return fromEnum;
102+
},
103+
},
87104
},
88105
});
89106

@@ -400,6 +417,14 @@ describe('Type System: Enum Values', () => {
400417
});
401418
});
402419

420+
it('may have values specified via a callback', () => {
421+
const result = executeQuery('{ thunkValuesString(fromEnum: B) }');
422+
423+
expect(result).to.deep.equal({
424+
data: { thunkValuesString: 'b' },
425+
});
426+
});
427+
403428
it('can be introspected without error', () => {
404429
expect(() => introspectionFromSchema(schema)).to.not.throw();
405430
});

src/type/definition.ts

+25-9
Original file line numberDiff line numberDiff line change
@@ -1372,9 +1372,12 @@ export class GraphQLEnumType /* <T> */ {
13721372
astNode: Maybe<EnumTypeDefinitionNode>;
13731373
extensionASTNodes: ReadonlyArray<EnumTypeExtensionNode>;
13741374

1375-
private _values: ReadonlyArray<GraphQLEnumValue /* <T> */>;
1376-
private _valueLookup: ReadonlyMap<any /* T */, GraphQLEnumValue>;
1377-
private _nameLookup: ObjMap<GraphQLEnumValue>;
1375+
private _values:
1376+
| ReadonlyArray<GraphQLEnumValue /* <T> */>
1377+
| (() => GraphQLEnumValueConfigMap);
1378+
1379+
private _valueLookup: ReadonlyMap<any /* T */, GraphQLEnumValue> | null;
1380+
private _nameLookup: ObjMap<GraphQLEnumValue> | null;
13781381

13791382
constructor(config: Readonly<GraphQLEnumTypeConfig /* <T> */>) {
13801383
this.name = assertName(config.name);
@@ -1383,26 +1386,38 @@ export class GraphQLEnumType /* <T> */ {
13831386
this.astNode = config.astNode;
13841387
this.extensionASTNodes = config.extensionASTNodes ?? [];
13851388

1386-
this._values = defineEnumValues(this.name, config.values);
1387-
this._valueLookup = new Map(
1388-
this._values.map((enumValue) => [enumValue.value, enumValue]),
1389-
);
1390-
this._nameLookup = keyMap(this._values, (value) => value.name);
1389+
this._values =
1390+
typeof config.values === 'function'
1391+
? config.values
1392+
: defineEnumValues(this.name, config.values);
1393+
this._valueLookup = null;
1394+
this._nameLookup = null;
13911395
}
13921396

13931397
get [Symbol.toStringTag]() {
13941398
return 'GraphQLEnumType';
13951399
}
13961400

13971401
getValues(): ReadonlyArray<GraphQLEnumValue /* <T> */> {
1402+
if (typeof this._values === 'function') {
1403+
this._values = defineEnumValues(this.name, this._values());
1404+
}
13981405
return this._values;
13991406
}
14001407

14011408
getValue(name: string): Maybe<GraphQLEnumValue> {
1409+
if (this._nameLookup === null) {
1410+
this._nameLookup = keyMap(this.getValues(), (value) => value.name);
1411+
}
14021412
return this._nameLookup[name];
14031413
}
14041414

14051415
serialize(outputValue: unknown /* T */): Maybe<string> {
1416+
if (this._valueLookup === null) {
1417+
this._valueLookup = new Map(
1418+
this.getValues().map((enumValue) => [enumValue.value, enumValue]),
1419+
);
1420+
}
14061421
const enumValue = this._valueLookup.get(outputValue);
14071422
if (enumValue === undefined) {
14081423
throw new GraphQLError(
@@ -1527,13 +1542,14 @@ function defineEnumValues(
15271542
export interface GraphQLEnumTypeConfig {
15281543
name: string;
15291544
description?: Maybe<string>;
1530-
values: GraphQLEnumValueConfigMap /* <T> */;
1545+
values: ThunkObjMap<GraphQLEnumValueConfig /* <T> */>;
15311546
extensions?: Maybe<Readonly<GraphQLEnumTypeExtensions>>;
15321547
astNode?: Maybe<EnumTypeDefinitionNode>;
15331548
extensionASTNodes?: Maybe<ReadonlyArray<EnumTypeExtensionNode>>;
15341549
}
15351550

15361551
interface GraphQLEnumTypeNormalizedConfig extends GraphQLEnumTypeConfig {
1552+
values: ObjMap<GraphQLEnumValueConfig /* <T> */>;
15371553
extensions: Readonly<GraphQLEnumTypeExtensions>;
15381554
extensionASTNodes: ReadonlyArray<EnumTypeExtensionNode>;
15391555
}

0 commit comments

Comments
 (0)