Skip to content

Commit ffd8158

Browse files
Switch schema types to use ReadonlyArrays (#3182)
1 parent 4d92729 commit ffd8158

File tree

6 files changed

+45
-41
lines changed

6 files changed

+45
-41
lines changed

src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ export type {
138138
GraphQLNamedType,
139139
GraphQLNamedInputType,
140140
GraphQLNamedOutputType,
141-
ThunkArray,
141+
ThunkReadonlyArray,
142142
ThunkObjMap,
143143
GraphQLSchemaConfig,
144144
GraphQLSchemaExtensions,

src/type/definition.ts

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -526,10 +526,12 @@ export function getNamedType(
526526
* Used while defining GraphQL types to allow for circular references in
527527
* otherwise immutable type definitions.
528528
*/
529-
export type ThunkArray<T> = (() => Array<T>) | Array<T>;
529+
export type ThunkReadonlyArray<T> = (() => ReadonlyArray<T>) | ReadonlyArray<T>;
530530
export type ThunkObjMap<T> = (() => ObjMap<T>) | ObjMap<T>;
531531

532-
function resolveArrayThunk<T>(thunk: ThunkArray<T>): Array<T> {
532+
function resolveReadonlyArrayThunk<T>(
533+
thunk: ThunkReadonlyArray<T>,
534+
): ReadonlyArray<T> {
533535
return typeof thunk === 'function' ? thunk() : thunk;
534536
}
535537

@@ -748,7 +750,7 @@ export class GraphQLObjectType<TSource = any, TContext = any> {
748750
extensionASTNodes: ReadonlyArray<ObjectTypeExtensionNode>;
749751

750752
private _fields: ThunkObjMap<GraphQLField<TSource, TContext>>;
751-
private _interfaces: ThunkArray<GraphQLInterfaceType>;
753+
private _interfaces: ThunkReadonlyArray<GraphQLInterfaceType>;
752754

753755
constructor(config: Readonly<GraphQLObjectTypeConfig<TSource, TContext>>) {
754756
this.name = config.name;
@@ -775,7 +777,7 @@ export class GraphQLObjectType<TSource = any, TContext = any> {
775777
return this._fields;
776778
}
777779

778-
getInterfaces(): Array<GraphQLInterfaceType> {
780+
getInterfaces(): ReadonlyArray<GraphQLInterfaceType> {
779781
if (typeof this._interfaces === 'function') {
780782
this._interfaces = this._interfaces();
781783
}
@@ -812,8 +814,8 @@ function defineInterfaces(
812814
config: Readonly<
813815
GraphQLObjectTypeConfig<any, any> | GraphQLInterfaceTypeConfig<any, any>
814816
>,
815-
): Array<GraphQLInterfaceType> {
816-
const interfaces = resolveArrayThunk(config.interfaces ?? []);
817+
): ReadonlyArray<GraphQLInterfaceType> {
818+
const interfaces = resolveReadonlyArrayThunk(config.interfaces ?? []);
817819
devAssert(
818820
Array.isArray(interfaces),
819821
`${config.name} interfaces must be an Array or a function which returns an Array.`,
@@ -920,7 +922,7 @@ export function argsToArgsConfig(
920922
export interface GraphQLObjectTypeConfig<TSource, TContext> {
921923
name: string;
922924
description?: Maybe<string>;
923-
interfaces?: ThunkArray<GraphQLInterfaceType>;
925+
interfaces?: ThunkReadonlyArray<GraphQLInterfaceType>;
924926
fields: ThunkObjMap<GraphQLFieldConfig<TSource, TContext>>;
925927
isTypeOf?: Maybe<GraphQLIsTypeOfFn<TSource, TContext>>;
926928
extensions?: Maybe<Readonly<GraphQLObjectTypeExtensions<TSource, TContext>>>;
@@ -930,7 +932,7 @@ export interface GraphQLObjectTypeConfig<TSource, TContext> {
930932

931933
interface GraphQLObjectTypeNormalizedConfig<TSource, TContext>
932934
extends GraphQLObjectTypeConfig<any, any> {
933-
interfaces: Array<GraphQLInterfaceType>;
935+
interfaces: ReadonlyArray<GraphQLInterfaceType>;
934936
fields: GraphQLFieldConfigMap<any, any>;
935937
extensions: Maybe<Readonly<GraphQLObjectTypeExtensions<TSource, TContext>>>;
936938
extensionASTNodes: ReadonlyArray<ObjectTypeExtensionNode>;
@@ -1112,7 +1114,7 @@ export class GraphQLInterfaceType {
11121114
extensionASTNodes: ReadonlyArray<InterfaceTypeExtensionNode>;
11131115

11141116
private _fields: ThunkObjMap<GraphQLField<any, any>>;
1115-
private _interfaces: ThunkArray<GraphQLInterfaceType>;
1117+
private _interfaces: ThunkReadonlyArray<GraphQLInterfaceType>;
11161118

11171119
constructor(config: Readonly<GraphQLInterfaceTypeConfig<any, any>>) {
11181120
this.name = config.name;
@@ -1139,7 +1141,7 @@ export class GraphQLInterfaceType {
11391141
return this._fields;
11401142
}
11411143

1142-
getInterfaces(): Array<GraphQLInterfaceType> {
1144+
getInterfaces(): ReadonlyArray<GraphQLInterfaceType> {
11431145
if (typeof this._interfaces === 'function') {
11441146
this._interfaces = this._interfaces();
11451147
}
@@ -1175,7 +1177,7 @@ export class GraphQLInterfaceType {
11751177
export interface GraphQLInterfaceTypeConfig<TSource, TContext> {
11761178
name: string;
11771179
description?: Maybe<string>;
1178-
interfaces?: ThunkArray<GraphQLInterfaceType>;
1180+
interfaces?: ThunkReadonlyArray<GraphQLInterfaceType>;
11791181
fields: ThunkObjMap<GraphQLFieldConfig<TSource, TContext>>;
11801182
/**
11811183
* Optionally provide a custom type resolver function. If one is not provided,
@@ -1190,7 +1192,7 @@ export interface GraphQLInterfaceTypeConfig<TSource, TContext> {
11901192

11911193
export interface GraphQLInterfaceTypeNormalizedConfig
11921194
extends GraphQLInterfaceTypeConfig<any, any> {
1193-
interfaces: Array<GraphQLInterfaceType>;
1195+
interfaces: ReadonlyArray<GraphQLInterfaceType>;
11941196
fields: GraphQLFieldConfigMap<any, any>;
11951197
extensions: Maybe<Readonly<GraphQLInterfaceTypeExtensions>>;
11961198
extensionASTNodes: ReadonlyArray<InterfaceTypeExtensionNode>;
@@ -1240,7 +1242,7 @@ export class GraphQLUnionType {
12401242
astNode: Maybe<UnionTypeDefinitionNode>;
12411243
extensionASTNodes: ReadonlyArray<UnionTypeExtensionNode>;
12421244

1243-
private _types: ThunkArray<GraphQLObjectType>;
1245+
private _types: ThunkReadonlyArray<GraphQLObjectType>;
12441246

12451247
constructor(config: Readonly<GraphQLUnionTypeConfig<any, any>>) {
12461248
this.name = config.name;
@@ -1259,7 +1261,7 @@ export class GraphQLUnionType {
12591261
);
12601262
}
12611263

1262-
getTypes(): Array<GraphQLObjectType> {
1264+
getTypes(): ReadonlyArray<GraphQLObjectType> {
12631265
if (typeof this._types === 'function') {
12641266
this._types = this._types();
12651267
}
@@ -1293,8 +1295,8 @@ export class GraphQLUnionType {
12931295

12941296
function defineTypes(
12951297
config: Readonly<GraphQLUnionTypeConfig<unknown, unknown>>,
1296-
): Array<GraphQLObjectType> {
1297-
const types = resolveArrayThunk(config.types);
1298+
): ReadonlyArray<GraphQLObjectType> {
1299+
const types = resolveReadonlyArrayThunk(config.types);
12981300
devAssert(
12991301
Array.isArray(types),
13001302
`Must provide Array of types or a function which returns such an array for Union ${config.name}.`,
@@ -1305,7 +1307,7 @@ function defineTypes(
13051307
export interface GraphQLUnionTypeConfig<TSource, TContext> {
13061308
name: string;
13071309
description?: Maybe<string>;
1308-
types: ThunkArray<GraphQLObjectType>;
1310+
types: ThunkReadonlyArray<GraphQLObjectType>;
13091311
/**
13101312
* Optionally provide a custom type resolver function. If one is not provided,
13111313
* the default implementation will call `isTypeOf` on each implementing
@@ -1319,7 +1321,7 @@ export interface GraphQLUnionTypeConfig<TSource, TContext> {
13191321

13201322
interface GraphQLUnionTypeNormalizedConfig
13211323
extends GraphQLUnionTypeConfig<any, any> {
1322-
types: Array<GraphQLObjectType>;
1324+
types: ReadonlyArray<GraphQLObjectType>;
13231325
extensions: Maybe<Readonly<GraphQLUnionTypeExtensions>>;
13241326
extensionASTNodes: ReadonlyArray<UnionTypeExtensionNode>;
13251327
}
@@ -1365,8 +1367,8 @@ export class GraphQLEnumType /* <T> */ {
13651367
astNode: Maybe<EnumTypeDefinitionNode>;
13661368
extensionASTNodes: ReadonlyArray<EnumTypeExtensionNode>;
13671369

1368-
private _values: Array<GraphQLEnumValue /* <T> */>;
1369-
private _valueLookup: Map<any /* T */, GraphQLEnumValue>;
1370+
private _values: ReadonlyArray<GraphQLEnumValue /* <T> */>;
1371+
private _valueLookup: ReadonlyMap<any /* T */, GraphQLEnumValue>;
13701372
private _nameLookup: ObjMap<GraphQLEnumValue>;
13711373

13721374
constructor(config: Readonly<GraphQLEnumTypeConfig /* <T> */>) {
@@ -1385,7 +1387,7 @@ export class GraphQLEnumType /* <T> */ {
13851387
devAssert(typeof config.name === 'string', 'Must provide name.');
13861388
}
13871389

1388-
getValues(): Array<GraphQLEnumValue /* <T> */> {
1390+
getValues(): ReadonlyArray<GraphQLEnumValue /* <T> */> {
13891391
return this._values;
13901392
}
13911393

@@ -1497,7 +1499,7 @@ function didYouMeanEnumValue(
14971499
function defineEnumValues(
14981500
typeName: string,
14991501
valueMap: GraphQLEnumValueConfigMap /* <T> */,
1500-
): Array<GraphQLEnumValue /* <T> */> {
1502+
): ReadonlyArray<GraphQLEnumValue /* <T> */> {
15011503
devAssert(
15021504
isPlainObj(valueMap),
15031505
`${typeName} values must be an object with value names as keys.`,

src/type/directives.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ export interface GraphQLDirectiveExtensions {
5656
export class GraphQLDirective {
5757
name: string;
5858
description: Maybe<string>;
59-
locations: Array<DirectiveLocationEnum>;
59+
locations: ReadonlyArray<DirectiveLocationEnum>;
6060
args: ReadonlyArray<GraphQLArgument>;
6161
isRepeatable: boolean;
6262
extensions: Maybe<Readonly<GraphQLDirectiveExtensions>>;
@@ -113,7 +113,7 @@ export class GraphQLDirective {
113113
export interface GraphQLDirectiveConfig {
114114
name: string;
115115
description?: Maybe<string>;
116-
locations: Array<DirectiveLocationEnum>;
116+
locations: ReadonlyArray<DirectiveLocationEnum>;
117117
args?: Maybe<GraphQLFieldConfigArgumentMap>;
118118
isRepeatable?: Maybe<boolean>;
119119
extensions?: Maybe<Readonly<GraphQLDirectiveExtensions>>;

src/type/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ export type {
7676
GraphQLNamedType,
7777
GraphQLNamedInputType,
7878
GraphQLNamedOutputType,
79-
ThunkArray,
79+
ThunkReadonlyArray,
8080
ThunkObjMap,
8181
GraphQLArgument,
8282
GraphQLArgumentConfig,

src/type/schema.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -287,8 +287,8 @@ export class GraphQLSchema {
287287
}
288288

289289
getImplementations(interfaceType: GraphQLInterfaceType): {
290-
objects: /* $ReadOnly */ Array<GraphQLObjectType>;
291-
interfaces: /* $ReadOnly */ Array<GraphQLInterfaceType>;
290+
objects: ReadonlyArray<GraphQLObjectType>;
291+
interfaces: ReadonlyArray<GraphQLInterfaceType>;
292292
} {
293293
const implementations = this._implementationsMap[interfaceType.name];
294294
return implementations ?? { objects: [], interfaces: [] };
@@ -336,7 +336,7 @@ export class GraphQLSchema {
336336
mutation: this.getMutationType(),
337337
subscription: this.getSubscriptionType(),
338338
types: Object.values(this.getTypeMap()),
339-
directives: this.getDirectives().slice(),
339+
directives: this.getDirectives(),
340340
extensions: this.extensions,
341341
astNode: this.astNode,
342342
extensionASTNodes: this.extensionASTNodes,
@@ -367,8 +367,8 @@ export interface GraphQLSchemaConfig extends GraphQLSchemaValidationOptions {
367367
query?: Maybe<GraphQLObjectType>;
368368
mutation?: Maybe<GraphQLObjectType>;
369369
subscription?: Maybe<GraphQLObjectType>;
370-
types?: Maybe<Array<GraphQLNamedType>>;
371-
directives?: Maybe<Array<GraphQLDirective>>;
370+
types?: Maybe<ReadonlyArray<GraphQLNamedType>>;
371+
directives?: Maybe<ReadonlyArray<GraphQLDirective>>;
372372
extensions?: Maybe<Readonly<GraphQLSchemaExtensions>>;
373373
astNode?: Maybe<SchemaDefinitionNode>;
374374
extensionASTNodes?: Maybe<ReadonlyArray<SchemaExtensionNode>>;
@@ -379,8 +379,8 @@ export interface GraphQLSchemaConfig extends GraphQLSchemaValidationOptions {
379379
*/
380380
export interface GraphQLSchemaNormalizedConfig extends GraphQLSchemaConfig {
381381
description: Maybe<string>;
382-
types: Array<GraphQLNamedType>;
383-
directives: Array<GraphQLDirective>;
382+
types: ReadonlyArray<GraphQLNamedType>;
383+
directives: ReadonlyArray<GraphQLDirective>;
384384
extensions: Maybe<Readonly<GraphQLSchemaExtensions>>;
385385
extensionASTNodes: ReadonlyArray<SchemaExtensionNode>;
386386
assumeValid: boolean;

src/utilities/buildASTSchema.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -78,15 +78,17 @@ export function buildASTSchema(
7878
}
7979
}
8080

81-
const { directives } = config;
82-
// If specified directives were not explicitly declared, add them.
83-
for (const stdDirective of specifiedDirectives) {
84-
if (directives.every((directive) => directive.name !== stdDirective.name)) {
85-
directives.push(stdDirective);
86-
}
87-
}
81+
const directives = [
82+
...config.directives,
83+
// If specified directives were not explicitly declared, add them.
84+
...specifiedDirectives.filter((stdDirective) =>
85+
config.directives.every(
86+
(directive) => directive.name !== stdDirective.name,
87+
),
88+
),
89+
];
8890

89-
return new GraphQLSchema(config);
91+
return new GraphQLSchema({ ...config, directives });
9092
}
9193

9294
/**

0 commit comments

Comments
 (0)