Skip to content

Commit c1e55cb

Browse files
committed
Add support for directives applied on IDL&Schema
1 parent 14ec456 commit c1e55cb

File tree

6 files changed

+235
-36
lines changed

6 files changed

+235
-36
lines changed

src/type/__tests__/definition-test.js

Lines changed: 2 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

src/type/definition.js

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

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

269317
/**
270318
* Scalar Type Definition
@@ -286,13 +334,15 @@ function resolveThunk<T>(thunk: Thunk<T>): T {
286334
export class GraphQLScalarType {
287335
name: string;
288336
description: ?string;
337+
appliedDirectives: ?GraphQLAppliedDirectives;
289338

290339
_scalarConfig: GraphQLScalarTypeConfig<*, *>;
291340

292341
constructor(config: GraphQLScalarTypeConfig<*, *>) {
293342
assertValidName(config.name);
294343
this.name = config.name;
295344
this.description = config.description;
345+
this.appliedDirectives = config.appliedDirectives;
296346
invariant(
297347
typeof config.serialize === 'function',
298348
`${this.name} must provide "serialize" function. If this custom Scalar ` +
@@ -344,6 +394,7 @@ GraphQLScalarType.prototype.toJSON =
344394
export type GraphQLScalarTypeConfig<TInternal, TExternal> = {
345395
name: string;
346396
description?: ?string;
397+
appliedDirectives?: ?GraphQLAppliedDirectives;
347398
serialize: (value: mixed) => ?TExternal;
348399
parseValue?: (value: mixed) => ?TInternal;
349400
parseLiteral?: (valueNode: ValueNode) => ?TInternal;
@@ -391,6 +442,7 @@ export type GraphQLScalarTypeConfig<TInternal, TExternal> = {
391442
export class GraphQLObjectType {
392443
name: string;
393444
description: ?string;
445+
appliedDirectives: ?GraphQLAppliedDirectives;
394446
isTypeOf: ?GraphQLIsTypeOfFn<*, *>;
395447

396448
_typeConfig: GraphQLObjectTypeConfig<*, *>;
@@ -401,6 +453,7 @@ export class GraphQLObjectType {
401453
assertValidName(config.name, config.isIntrospection);
402454
this.name = config.name;
403455
this.description = config.description;
456+
this.appliedDirectives = config.appliedDirectives;
404457
if (config.isTypeOf) {
405458
invariant(
406459
typeof config.isTypeOf === 'function',
@@ -535,7 +588,8 @@ function defineFieldMap<TSource, TContext>(
535588
name: argName,
536589
description: arg.description === undefined ? null : arg.description,
537590
type: arg.type,
538-
defaultValue: arg.defaultValue
591+
defaultValue: arg.defaultValue,
592+
appliedDirectives: arg.appliedDirectives,
539593
};
540594
});
541595
}
@@ -560,6 +614,7 @@ export type GraphQLObjectTypeConfig<TSource, TContext> = {
560614
isTypeOf?: ?GraphQLIsTypeOfFn<TSource, TContext>;
561615
description?: ?string;
562616
isIntrospection?: boolean;
617+
appliedDirectives?: ?GraphQLAppliedDirectives;
563618
};
564619

565620
export type GraphQLTypeResolver<TSource, TContext> = (
@@ -602,6 +657,7 @@ export type GraphQLFieldConfig<TSource, TContext> = {
602657
resolve?: GraphQLFieldResolver<TSource, TContext>;
603658
deprecationReason?: ?string;
604659
description?: ?string;
660+
appliedDirectives?: ?GraphQLAppliedDirectives;
605661
};
606662

607663
export type GraphQLFieldConfigArgumentMap = {
@@ -612,6 +668,7 @@ export type GraphQLArgumentConfig = {
612668
type: GraphQLInputType;
613669
defaultValue?: mixed;
614670
description?: ?string;
671+
appliedDirectives?: ?GraphQLAppliedDirectives;
615672
};
616673

617674
export type GraphQLFieldConfigMap<TSource, TContext> = {
@@ -626,13 +683,15 @@ export type GraphQLField<TSource, TContext> = {
626683
resolve?: GraphQLFieldResolver<TSource, TContext>;
627684
isDeprecated?: boolean;
628685
deprecationReason?: ?string;
686+
appliedDirectives?: ?GraphQLAppliedDirectives;
629687
};
630688

631689
export type GraphQLArgument = {
632690
name: string;
633691
type: GraphQLInputType;
634692
defaultValue?: mixed;
635693
description?: ?string;
694+
appliedDirectives?: ?GraphQLAppliedDirectives;
636695
};
637696

638697
export type GraphQLFieldMap<TSource, TContext> = {
@@ -662,6 +721,7 @@ export type GraphQLFieldMap<TSource, TContext> = {
662721
export class GraphQLInterfaceType {
663722
name: string;
664723
description: ?string;
724+
appliedDirectives: ?GraphQLAppliedDirectives;
665725
resolveType: ?GraphQLTypeResolver<*, *>;
666726

667727
_typeConfig: GraphQLInterfaceTypeConfig<*, *>;
@@ -671,6 +731,7 @@ export class GraphQLInterfaceType {
671731
assertValidName(config.name);
672732
this.name = config.name;
673733
this.description = config.description;
734+
this.appliedDirectives = config.appliedDirectives;
674735
if (config.resolveType) {
675736
invariant(
676737
typeof config.resolveType === 'function',
@@ -708,7 +769,8 @@ export type GraphQLInterfaceTypeConfig<TSource, TContext> = {
708769
* Object type.
709770
*/
710771
resolveType?: ?GraphQLTypeResolver<TSource, TContext>,
711-
description?: ?string
772+
description?: ?string,
773+
appliedDirectives?: ?GraphQLAppliedDirectives,
712774
};
713775

714776

@@ -739,6 +801,7 @@ export type GraphQLInterfaceTypeConfig<TSource, TContext> = {
739801
export class GraphQLUnionType {
740802
name: string;
741803
description: ?string;
804+
appliedDirectives: ?GraphQLAppliedDirectives;
742805
resolveType: ?GraphQLTypeResolver<*, *>;
743806

744807
_typeConfig: GraphQLUnionTypeConfig<*, *>;
@@ -749,6 +812,7 @@ export class GraphQLUnionType {
749812
assertValidName(config.name);
750813
this.name = config.name;
751814
this.description = config.description;
815+
this.appliedDirectives = config.appliedDirectives;
752816
if (config.resolveType) {
753817
invariant(
754818
typeof config.resolveType === 'function',
@@ -819,6 +883,7 @@ export type GraphQLUnionTypeConfig<TSource, TContext> = {
819883
*/
820884
resolveType?: ?GraphQLTypeResolver<TSource, TContext>;
821885
description?: ?string;
886+
appliedDirectives?: ?GraphQLAppliedDirectives;
822887
};
823888

824889

@@ -847,6 +912,7 @@ export type GraphQLUnionTypeConfig<TSource, TContext> = {
847912
export class GraphQLEnumType/* <T> */ {
848913
name: string;
849914
description: ?string;
915+
appliedDirectives: ?GraphQLAppliedDirectives;
850916

851917
_enumConfig: GraphQLEnumTypeConfig/* <T> */;
852918
_values: Array<GraphQLEnumValue/* <T> */>;
@@ -857,6 +923,7 @@ export class GraphQLEnumType/* <T> */ {
857923
this.name = config.name;
858924
assertValidName(config.name, config.isIntrospection);
859925
this.description = config.description;
926+
this.appliedDirectives = config.appliedDirectives;
860927
this._values = defineEnumValues(this, config.values);
861928
this._enumConfig = config;
862929
}
@@ -958,6 +1025,7 @@ function defineEnumValues(
9581025
description: value.description,
9591026
isDeprecated: Boolean(value.deprecationReason),
9601027
deprecationReason: value.deprecationReason,
1028+
appliedDirectives: value.appliedDirectives,
9611029
value: isNullish(value.value) ? valueName : value.value,
9621030
};
9631031
});
@@ -967,6 +1035,7 @@ export type GraphQLEnumTypeConfig/* <T> */ = {
9671035
name: string;
9681036
values: GraphQLEnumValueConfigMap/* <T> */;
9691037
description?: ?string;
1038+
appliedDirectives?: ?GraphQLAppliedDirectives;
9701039
isIntrospection?: boolean;
9711040
};
9721041

@@ -978,13 +1047,15 @@ export type GraphQLEnumValueConfig/* <T> */ = {
9781047
value?: any/* T */;
9791048
deprecationReason?: ?string;
9801049
description?: ?string;
1050+
appliedDirectives?: ?GraphQLAppliedDirectives;
9811051
};
9821052

9831053
export type GraphQLEnumValue/* <T> */ = {
9841054
name: string;
9851055
description: ?string;
9861056
isDeprecated?: boolean;
9871057
deprecationReason: ?string;
1058+
appliedDirectives: ?GraphQLAppliedDirectives;
9881059
value: any/* T */;
9891060
};
9901061

@@ -1013,6 +1084,7 @@ export type GraphQLEnumValue/* <T> */ = {
10131084
export class GraphQLInputObjectType {
10141085
name: string;
10151086
description: ?string;
1087+
appliedDirectives: ?GraphQLAppliedDirectives;
10161088

10171089
_typeConfig: GraphQLInputObjectTypeConfig;
10181090
_fields: GraphQLInputFieldMap;
@@ -1021,6 +1093,7 @@ export class GraphQLInputObjectType {
10211093
assertValidName(config.name);
10221094
this.name = config.name;
10231095
this.description = config.description;
1096+
this.appliedDirectives = config.appliedDirectives;
10241097
this._typeConfig = config;
10251098
}
10261099

@@ -1080,12 +1153,14 @@ export type GraphQLInputObjectTypeConfig = {
10801153
name: string;
10811154
fields: Thunk<GraphQLInputFieldConfigMap>;
10821155
description?: ?string;
1156+
appliedDirectives?: ?GraphQLAppliedDirectives;
10831157
};
10841158

10851159
export type GraphQLInputFieldConfig = {
10861160
type: GraphQLInputType;
10871161
defaultValue?: mixed;
10881162
description?: ?string;
1163+
appliedDirectives?: ?GraphQLAppliedDirectives;
10891164
};
10901165

10911166
export type GraphQLInputFieldConfigMap = {
@@ -1097,6 +1172,7 @@ export type GraphQLInputField = {
10971172
type: GraphQLInputType;
10981173
defaultValue?: mixed;
10991174
description?: ?string;
1175+
appliedDirectives?: ?GraphQLAppliedDirectives;
11001176
};
11011177

11021178
export type GraphQLInputFieldMap = {

0 commit comments

Comments
 (0)