Skip to content

Commit 4c3186c

Browse files
committed
Add support for directives applied on IDL&Schema
1 parent 9033685 commit 4c3186c

File tree

7 files changed

+244
-46
lines changed

7 files changed

+244
-46
lines changed

src/type/__tests__/definition-test.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,8 @@ describe('Type System: Example', () => {
180180
description: undefined,
181181
isDeprecated: true,
182182
deprecationReason: 'Just because',
183-
value: 'foo'
183+
value: 'foo',
184+
appliedDirectives: undefined,
184185
});
185186
});
186187

@@ -200,13 +201,15 @@ describe('Type System: Example', () => {
200201
isDeprecated: false,
201202
deprecationReason: undefined,
202203
value: null,
204+
appliedDirectives: undefined,
203205
},
204206
{
205207
name: 'UNDEFINED',
206208
description: undefined,
207209
isDeprecated: false,
208210
deprecationReason: undefined,
209211
value: undefined,
212+
appliedDirectives: undefined,
210213
},
211214
]);
212215
});

src/type/definition.js

Lines changed: 78 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,54 @@ function resolveThunk<T>(thunk: Thunk<T>): T {
272272
return typeof thunk === 'function' ? thunk() : thunk;
273273
}
274274

275+
export class GraphQLAppliedDirectives {
276+
_appliedDirectivesConfig: GraphQLAppliedDirectivesConfig;
277+
_argsMap: GraphQLDirectiveArgsMap;
278+
279+
constructor(config: GraphQLAppliedDirectivesConfig) {
280+
invariant(
281+
isPlainObj(config),
282+
'Applied directives must be an object with directive names as keys.'
283+
);
284+
285+
this._appliedDirectivesConfig = config;
286+
this._argsMap = {};
287+
}
288+
289+
isApplied(directiveName: string): boolean {
290+
return Boolean(this._appliedDirectivesConfig[directiveName]);
291+
}
292+
293+
getAppliedDirectives(): Array<string> {
294+
return Object.keys(this._appliedDirectivesConfig);
295+
}
296+
297+
getDirectiveArgs(directiveName: string): ?{ [argName: string]: any } {
298+
if (this._argsMap[directiveName]) {
299+
return this._argsMap[directiveName];
300+
}
301+
const argsThunk = this._appliedDirectivesConfig[directiveName];
302+
const args = resolveThunk(argsThunk);
303+
if (!args) {
304+
return null;
305+
}
306+
invariant(
307+
isPlainObj(args),
308+
`@${directiveName} args must be an object with argument names as keys ` +
309+
'or a function which returns such an object.'
310+
);
311+
this._argsMap[directiveName] = args;
312+
return args;
313+
}
314+
}
315+
316+
type GraphQLDirectiveArgsMap = {
317+
[key: string]: { [argName: string]: any }
318+
};
319+
320+
type GraphQLAppliedDirectivesConfig = {
321+
[key: string]: Thunk<*>
322+
};
275323

276324
/**
277325
* Scalar Type Definition
@@ -293,13 +341,15 @@ function resolveThunk<T>(thunk: Thunk<T>): T {
293341
export class GraphQLScalarType {
294342
name: string;
295343
description: ?string;
344+
appliedDirectives: ?GraphQLAppliedDirectives;
296345

297346
_scalarConfig: GraphQLScalarTypeConfig<*, *>;
298347

299348
constructor(config: GraphQLScalarTypeConfig<*, *>) {
300349
assertValidName(config.name);
301350
this.name = config.name;
302351
this.description = config.description;
352+
this.appliedDirectives = config.appliedDirectives;
303353
invariant(
304354
typeof config.serialize === 'function',
305355
`${this.name} must provide "serialize" function. If this custom Scalar ` +
@@ -351,6 +401,7 @@ GraphQLScalarType.prototype.toJSON =
351401
export type GraphQLScalarTypeConfig<TInternal, TExternal> = {
352402
name: string;
353403
description?: ?string;
404+
appliedDirectives?: ?GraphQLAppliedDirectives;
354405
serialize: (value: mixed) => ?TExternal;
355406
parseValue?: (value: mixed) => ?TInternal;
356407
parseLiteral?: (valueNode: ValueNode) => ?TInternal;
@@ -398,6 +449,7 @@ export type GraphQLScalarTypeConfig<TInternal, TExternal> = {
398449
export class GraphQLObjectType {
399450
name: string;
400451
description: ?string;
452+
appliedDirectives: ?GraphQLAppliedDirectives;
401453
isTypeOf: ?GraphQLIsTypeOfFn<*, *>;
402454

403455
_typeConfig: GraphQLObjectTypeConfig<*, *>;
@@ -408,6 +460,7 @@ export class GraphQLObjectType {
408460
assertValidName(config.name, config.isIntrospection);
409461
this.name = config.name;
410462
this.description = config.description;
463+
this.appliedDirectives = config.appliedDirectives;
411464
if (config.isTypeOf) {
412465
invariant(
413466
typeof config.isTypeOf === 'function',
@@ -549,7 +602,8 @@ function defineFieldMap<TSource, TContext>(
549602
name: argName,
550603
description: arg.description === undefined ? null : arg.description,
551604
type: arg.type,
552-
defaultValue: arg.defaultValue
605+
defaultValue: arg.defaultValue,
606+
appliedDirectives: arg.appliedDirectives,
553607
};
554608
});
555609
}
@@ -574,6 +628,7 @@ export type GraphQLObjectTypeConfig<TSource, TContext> = {
574628
isTypeOf?: ?GraphQLIsTypeOfFn<TSource, TContext>;
575629
description?: ?string;
576630
isIntrospection?: boolean;
631+
appliedDirectives?: ?GraphQLAppliedDirectives;
577632
};
578633

579634
export type GraphQLTypeResolver<TSource, TContext> = (
@@ -616,6 +671,7 @@ export type GraphQLFieldConfig<TSource, TContext> = {
616671
resolve?: GraphQLFieldResolver<TSource, TContext>;
617672
deprecationReason?: ?string;
618673
description?: ?string;
674+
appliedDirectives?: ?GraphQLAppliedDirectives;
619675
};
620676

621677
export type GraphQLFieldConfigArgumentMap = {
@@ -626,6 +682,7 @@ export type GraphQLArgumentConfig = {
626682
type: GraphQLInputType;
627683
defaultValue?: mixed;
628684
description?: ?string;
685+
appliedDirectives?: ?GraphQLAppliedDirectives;
629686
};
630687

631688
export type GraphQLFieldConfigMap<TSource, TContext> = {
@@ -640,13 +697,15 @@ export type GraphQLField<TSource, TContext> = {
640697
resolve?: GraphQLFieldResolver<TSource, TContext>;
641698
isDeprecated?: boolean;
642699
deprecationReason?: ?string;
700+
appliedDirectives?: ?GraphQLAppliedDirectives;
643701
};
644702

645703
export type GraphQLArgument = {
646704
name: string;
647705
type: GraphQLInputType;
648706
defaultValue?: mixed;
649707
description?: ?string;
708+
appliedDirectives?: ?GraphQLAppliedDirectives;
650709
};
651710

652711
export type GraphQLFieldMap<TSource, TContext> = {
@@ -676,6 +735,7 @@ export type GraphQLFieldMap<TSource, TContext> = {
676735
export class GraphQLInterfaceType {
677736
name: string;
678737
description: ?string;
738+
appliedDirectives: ?GraphQLAppliedDirectives;
679739
resolveType: ?GraphQLTypeResolver<*, *>;
680740

681741
_typeConfig: GraphQLInterfaceTypeConfig<*, *>;
@@ -685,6 +745,7 @@ export class GraphQLInterfaceType {
685745
assertValidName(config.name);
686746
this.name = config.name;
687747
this.description = config.description;
748+
this.appliedDirectives = config.appliedDirectives;
688749
if (config.resolveType) {
689750
invariant(
690751
typeof config.resolveType === 'function',
@@ -722,7 +783,8 @@ export type GraphQLInterfaceTypeConfig<TSource, TContext> = {
722783
* Object type.
723784
*/
724785
resolveType?: ?GraphQLTypeResolver<TSource, TContext>,
725-
description?: ?string
786+
description?: ?string,
787+
appliedDirectives?: ?GraphQLAppliedDirectives,
726788
};
727789

728790

@@ -753,6 +815,7 @@ export type GraphQLInterfaceTypeConfig<TSource, TContext> = {
753815
export class GraphQLUnionType {
754816
name: string;
755817
description: ?string;
818+
appliedDirectives: ?GraphQLAppliedDirectives;
756819
resolveType: ?GraphQLTypeResolver<*, *>;
757820

758821
_typeConfig: GraphQLUnionTypeConfig<*, *>;
@@ -763,6 +826,7 @@ export class GraphQLUnionType {
763826
assertValidName(config.name);
764827
this.name = config.name;
765828
this.description = config.description;
829+
this.appliedDirectives = config.appliedDirectives;
766830
if (config.resolveType) {
767831
invariant(
768832
typeof config.resolveType === 'function',
@@ -839,6 +903,7 @@ export type GraphQLUnionTypeConfig<TSource, TContext> = {
839903
*/
840904
resolveType?: ?GraphQLTypeResolver<TSource, TContext>;
841905
description?: ?string;
906+
appliedDirectives?: ?GraphQLAppliedDirectives;
842907
};
843908

844909

@@ -867,6 +932,7 @@ export type GraphQLUnionTypeConfig<TSource, TContext> = {
867932
export class GraphQLEnumType/* <T> */ {
868933
name: string;
869934
description: ?string;
935+
appliedDirectives: ?GraphQLAppliedDirectives;
870936

871937
_enumConfig: GraphQLEnumTypeConfig/* <T> */;
872938
_values: Array<GraphQLEnumValue/* <T> */>;
@@ -877,6 +943,7 @@ export class GraphQLEnumType/* <T> */ {
877943
this.name = config.name;
878944
assertValidName(config.name, config.isIntrospection);
879945
this.description = config.description;
946+
this.appliedDirectives = config.appliedDirectives;
880947
this._values = defineEnumValues(this, config.values);
881948
this._enumConfig = config;
882949
}
@@ -983,6 +1050,7 @@ function defineEnumValues(
9831050
description: value.description,
9841051
isDeprecated: Boolean(value.deprecationReason),
9851052
deprecationReason: value.deprecationReason,
1053+
appliedDirectives: value.appliedDirectives,
9861054
value: value.hasOwnProperty('value') ? value.value : valueName,
9871055
};
9881056
});
@@ -992,6 +1060,7 @@ export type GraphQLEnumTypeConfig/* <T> */ = {
9921060
name: string;
9931061
values: GraphQLEnumValueConfigMap/* <T> */;
9941062
description?: ?string;
1063+
appliedDirectives?: ?GraphQLAppliedDirectives;
9951064
isIntrospection?: boolean;
9961065
};
9971066

@@ -1003,13 +1072,15 @@ export type GraphQLEnumValueConfig/* <T> */ = {
10031072
value?: any/* T */;
10041073
deprecationReason?: ?string;
10051074
description?: ?string;
1075+
appliedDirectives?: ?GraphQLAppliedDirectives;
10061076
};
10071077

10081078
export type GraphQLEnumValue/* <T> */ = {
10091079
name: string;
10101080
description: ?string;
10111081
isDeprecated?: boolean;
10121082
deprecationReason: ?string;
1083+
appliedDirectives: ?GraphQLAppliedDirectives;
10131084
value: any/* T */;
10141085
};
10151086

@@ -1038,6 +1109,7 @@ export type GraphQLEnumValue/* <T> */ = {
10381109
export class GraphQLInputObjectType {
10391110
name: string;
10401111
description: ?string;
1112+
appliedDirectives: ?GraphQLAppliedDirectives;
10411113

10421114
_typeConfig: GraphQLInputObjectTypeConfig;
10431115
_fields: GraphQLInputFieldMap;
@@ -1046,6 +1118,7 @@ export class GraphQLInputObjectType {
10461118
assertValidName(config.name);
10471119
this.name = config.name;
10481120
this.description = config.description;
1121+
this.appliedDirectives = config.appliedDirectives;
10491122
this._typeConfig = config;
10501123
}
10511124

@@ -1105,12 +1178,14 @@ export type GraphQLInputObjectTypeConfig = {
11051178
name: string;
11061179
fields: Thunk<GraphQLInputFieldConfigMap>;
11071180
description?: ?string;
1181+
appliedDirectives?: ?GraphQLAppliedDirectives;
11081182
};
11091183

11101184
export type GraphQLInputFieldConfig = {
11111185
type: GraphQLInputType;
11121186
defaultValue?: mixed;
11131187
description?: ?string;
1188+
appliedDirectives?: ?GraphQLAppliedDirectives;
11141189
};
11151190

11161191
export type GraphQLInputFieldConfigMap = {
@@ -1122,6 +1197,7 @@ export type GraphQLInputField = {
11221197
type: GraphQLInputType;
11231198
defaultValue?: mixed;
11241199
description?: ?string;
1200+
appliedDirectives?: ?GraphQLAppliedDirectives;
11251201
};
11261202

11271203
export type GraphQLInputFieldMap = {

0 commit comments

Comments
 (0)