graphql 16.8.1 → 16.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/index.d.ts +3 -0
  2. package/index.js +18 -0
  3. package/index.mjs +6 -3
  4. package/jsutils/instanceOf.js +6 -1
  5. package/jsutils/instanceOf.mjs +6 -1
  6. package/package.json +1 -1
  7. package/type/definition.d.ts +4 -1
  8. package/type/definition.js +29 -6
  9. package/type/definition.mjs +26 -6
  10. package/type/directives.d.ts +4 -0
  11. package/type/directives.js +15 -1
  12. package/type/directives.mjs +12 -0
  13. package/type/index.d.ts +1 -0
  14. package/type/index.js +6 -0
  15. package/type/index.mjs +2 -1
  16. package/type/introspection.js +8 -0
  17. package/type/introspection.mjs +8 -0
  18. package/type/validate.js +24 -0
  19. package/type/validate.mjs +24 -0
  20. package/utilities/buildClientSchema.js +1 -0
  21. package/utilities/buildClientSchema.mjs +1 -0
  22. package/utilities/coerceInputValue.js +25 -0
  23. package/utilities/coerceInputValue.mjs +25 -0
  24. package/utilities/extendSchema.js +10 -0
  25. package/utilities/extendSchema.mjs +9 -0
  26. package/utilities/getIntrospectionQuery.d.ts +6 -0
  27. package/utilities/getIntrospectionQuery.js +3 -0
  28. package/utilities/getIntrospectionQuery.mjs +3 -0
  29. package/utilities/introspectionFromSchema.js +1 -0
  30. package/utilities/introspectionFromSchema.mjs +1 -0
  31. package/utilities/printSchema.js +6 -1
  32. package/utilities/printSchema.mjs +6 -1
  33. package/utilities/valueFromAST.js +12 -0
  34. package/utilities/valueFromAST.mjs +12 -0
  35. package/validation/index.d.ts +2 -1
  36. package/validation/index.js +14 -0
  37. package/validation/index.mjs +3 -2
  38. package/validation/rules/MaxIntrospectionDepthRule.d.ts +5 -0
  39. package/validation/rules/MaxIntrospectionDepthRule.js +90 -0
  40. package/validation/rules/MaxIntrospectionDepthRule.mjs +77 -0
  41. package/validation/rules/ValuesOfCorrectTypeRule.js +88 -0
  42. package/validation/rules/ValuesOfCorrectTypeRule.mjs +83 -0
  43. package/validation/specifiedRules.d.ts +6 -0
  44. package/validation/specifiedRules.js +17 -1
  45. package/validation/specifiedRules.mjs +10 -1
  46. package/version.js +3 -3
  47. package/version.mjs +3 -3
package/index.d.ts CHANGED
@@ -54,6 +54,7 @@ export {
54
54
  GraphQLSkipDirective,
55
55
  GraphQLDeprecatedDirective,
56
56
  GraphQLSpecifiedByDirective,
57
+ GraphQLOneOfDirective,
57
58
  TypeKind,
58
59
  DEFAULT_DEPRECATION_REASON,
59
60
  introspectionTypes,
@@ -300,6 +301,7 @@ export {
300
301
  validate,
301
302
  ValidationContext,
302
303
  specifiedRules,
304
+ recommendedRules,
303
305
  ExecutableDefinitionsRule,
304
306
  FieldsOnCorrectTypeRule,
305
307
  FragmentsOnCompositeTypesRule,
@@ -326,6 +328,7 @@ export {
326
328
  ValuesOfCorrectTypeRule,
327
329
  VariablesAreInputTypesRule,
328
330
  VariablesInAllowedPositionRule,
331
+ MaxIntrospectionDepthRule,
329
332
  LoneSchemaDefinitionRule,
330
333
  UniqueOperationTypesRule,
331
334
  UniqueTypeNamesRule,
package/index.js CHANGED
@@ -147,6 +147,12 @@ Object.defineProperty(exports, 'GraphQLObjectType', {
147
147
  return _index.GraphQLObjectType;
148
148
  },
149
149
  });
150
+ Object.defineProperty(exports, 'GraphQLOneOfDirective', {
151
+ enumerable: true,
152
+ get: function () {
153
+ return _index.GraphQLOneOfDirective;
154
+ },
155
+ });
150
156
  Object.defineProperty(exports, 'GraphQLScalarType', {
151
157
  enumerable: true,
152
158
  get: function () {
@@ -237,6 +243,12 @@ Object.defineProperty(exports, 'LoneSchemaDefinitionRule', {
237
243
  return _index4.LoneSchemaDefinitionRule;
238
244
  },
239
245
  });
246
+ Object.defineProperty(exports, 'MaxIntrospectionDepthRule', {
247
+ enumerable: true,
248
+ get: function () {
249
+ return _index4.MaxIntrospectionDepthRule;
250
+ },
251
+ });
240
252
  Object.defineProperty(exports, 'NoDeprecatedCustomRule', {
241
253
  enumerable: true,
242
254
  get: function () {
@@ -1131,6 +1143,12 @@ Object.defineProperty(exports, 'printType', {
1131
1143
  return _index6.printType;
1132
1144
  },
1133
1145
  });
1146
+ Object.defineProperty(exports, 'recommendedRules', {
1147
+ enumerable: true,
1148
+ get: function () {
1149
+ return _index4.recommendedRules;
1150
+ },
1151
+ });
1134
1152
  Object.defineProperty(exports, 'resolveObjMapThunk', {
1135
1153
  enumerable: true,
1136
1154
  get: function () {
package/index.mjs CHANGED
@@ -55,7 +55,8 @@ export {
55
55
  GraphQLIncludeDirective,
56
56
  GraphQLSkipDirective,
57
57
  GraphQLDeprecatedDirective,
58
- GraphQLSpecifiedByDirective, // "Enum" of Type Kinds
58
+ GraphQLSpecifiedByDirective,
59
+ GraphQLOneOfDirective, // "Enum" of Type Kinds
59
60
  TypeKind, // Constant Deprecation Reason
60
61
  DEFAULT_DEPRECATION_REASON, // GraphQL Types for introspection.
61
62
  introspectionTypes,
@@ -171,7 +172,8 @@ export {
171
172
  export {
172
173
  validate,
173
174
  ValidationContext, // All validation rules in the GraphQL Specification.
174
- specifiedRules, // Individual validation rules.
175
+ specifiedRules,
176
+ recommendedRules, // Individual validation rules.
175
177
  ExecutableDefinitionsRule,
176
178
  FieldsOnCorrectTypeRule,
177
179
  FragmentsOnCompositeTypesRule,
@@ -197,7 +199,8 @@ export {
197
199
  UniqueVariableNamesRule,
198
200
  ValuesOfCorrectTypeRule,
199
201
  VariablesAreInputTypesRule,
200
- VariablesInAllowedPositionRule, // SDL-specific validation rules
202
+ VariablesInAllowedPositionRule,
203
+ MaxIntrospectionDepthRule, // SDL-specific validation rules
201
204
  LoneSchemaDefinitionRule,
202
205
  UniqueOperationTypesRule,
203
206
  UniqueTypeNamesRule,
@@ -7,16 +7,21 @@ exports.instanceOf = void 0;
7
7
 
8
8
  var _inspect = require('./inspect.js');
9
9
 
10
+ /* c8 ignore next 3 */
11
+ const isProduction =
12
+ globalThis.process && // eslint-disable-next-line no-undef
13
+ process.env.NODE_ENV === 'production';
10
14
  /**
11
15
  * A replacement for instanceof which includes an error warning when multi-realm
12
16
  * constructors are detected.
13
17
  * See: https://expressjs.com/en/advanced/best-practice-performance.html#set-node_env-to-production
14
18
  * See: https://webpack.js.org/guides/production/
15
19
  */
20
+
16
21
  const instanceOf =
17
22
  /* c8 ignore next 6 */
18
23
  // FIXME: https://github.com/graphql/graphql-js/issues/2317
19
- globalThis.process && globalThis.process.env.NODE_ENV === 'production'
24
+ isProduction
20
25
  ? function instanceOf(value, constructor) {
21
26
  return value instanceof constructor;
22
27
  }
@@ -1,4 +1,9 @@
1
1
  import { inspect } from './inspect.mjs';
2
+ /* c8 ignore next 3 */
3
+
4
+ const isProduction =
5
+ globalThis.process && // eslint-disable-next-line no-undef
6
+ process.env.NODE_ENV === 'production';
2
7
  /**
3
8
  * A replacement for instanceof which includes an error warning when multi-realm
4
9
  * constructors are detected.
@@ -9,7 +14,7 @@ import { inspect } from './inspect.mjs';
9
14
  export const instanceOf =
10
15
  /* c8 ignore next 6 */
11
16
  // FIXME: https://github.com/graphql/graphql-js/issues/2317
12
- globalThis.process && globalThis.process.env.NODE_ENV === 'production'
17
+ isProduction
13
18
  ? function instanceOf(value, constructor) {
14
19
  return value instanceof constructor;
15
20
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "graphql",
3
- "version": "16.8.1",
3
+ "version": "16.9.0",
4
4
  "description": "A Query Language and Runtime which can target any service.",
5
5
  "license": "MIT",
6
6
  "main": "index",
@@ -789,12 +789,13 @@ export declare class GraphQLEnumType {
789
789
  export interface GraphQLEnumTypeConfig {
790
790
  name: string;
791
791
  description?: Maybe<string>;
792
- values: GraphQLEnumValueConfigMap;
792
+ values: ThunkObjMap<GraphQLEnumValueConfig>;
793
793
  extensions?: Maybe<Readonly<GraphQLEnumTypeExtensions>>;
794
794
  astNode?: Maybe<EnumTypeDefinitionNode>;
795
795
  extensionASTNodes?: Maybe<ReadonlyArray<EnumTypeExtensionNode>>;
796
796
  }
797
797
  interface GraphQLEnumTypeNormalizedConfig extends GraphQLEnumTypeConfig {
798
+ values: ObjMap<GraphQLEnumValueConfig>;
798
799
  extensions: Readonly<GraphQLEnumTypeExtensions>;
799
800
  extensionASTNodes: ReadonlyArray<EnumTypeExtensionNode>;
800
801
  }
@@ -865,6 +866,7 @@ export declare class GraphQLInputObjectType {
865
866
  extensions: Readonly<GraphQLInputObjectTypeExtensions>;
866
867
  astNode: Maybe<InputObjectTypeDefinitionNode>;
867
868
  extensionASTNodes: ReadonlyArray<InputObjectTypeExtensionNode>;
869
+ isOneOf: boolean;
868
870
  private _fields;
869
871
  constructor(config: Readonly<GraphQLInputObjectTypeConfig>);
870
872
  get [Symbol.toStringTag](): string;
@@ -880,6 +882,7 @@ export interface GraphQLInputObjectTypeConfig {
880
882
  extensions?: Maybe<Readonly<GraphQLInputObjectTypeExtensions>>;
881
883
  astNode?: Maybe<InputObjectTypeDefinitionNode>;
882
884
  extensionASTNodes?: Maybe<ReadonlyArray<InputObjectTypeExtensionNode>>;
885
+ isOneOf?: boolean;
883
886
  }
884
887
  interface GraphQLInputObjectTypeNormalizedConfig
885
888
  extends GraphQLInputObjectTypeConfig {
@@ -1077,11 +1077,12 @@ class GraphQLEnumType {
1077
1077
  _config$extensionASTN5 !== void 0
1078
1078
  ? _config$extensionASTN5
1079
1079
  : [];
1080
- this._values = defineEnumValues(this.name, config.values);
1081
- this._valueLookup = new Map(
1082
- this._values.map((enumValue) => [enumValue.value, enumValue]),
1083
- );
1084
- this._nameLookup = (0, _keyMap.keyMap)(this._values, (value) => value.name);
1080
+ this._values =
1081
+ typeof config.values === 'function'
1082
+ ? config.values
1083
+ : defineEnumValues(this.name, config.values);
1084
+ this._valueLookup = null;
1085
+ this._nameLookup = null;
1085
1086
  }
1086
1087
 
1087
1088
  get [Symbol.toStringTag]() {
@@ -1089,14 +1090,31 @@ class GraphQLEnumType {
1089
1090
  }
1090
1091
 
1091
1092
  getValues() {
1093
+ if (typeof this._values === 'function') {
1094
+ this._values = defineEnumValues(this.name, this._values());
1095
+ }
1096
+
1092
1097
  return this._values;
1093
1098
  }
1094
1099
 
1095
1100
  getValue(name) {
1101
+ if (this._nameLookup === null) {
1102
+ this._nameLookup = (0, _keyMap.keyMap)(
1103
+ this.getValues(),
1104
+ (value) => value.name,
1105
+ );
1106
+ }
1107
+
1096
1108
  return this._nameLookup[name];
1097
1109
  }
1098
1110
 
1099
1111
  serialize(outputValue) {
1112
+ if (this._valueLookup === null) {
1113
+ this._valueLookup = new Map(
1114
+ this.getValues().map((enumValue) => [enumValue.value, enumValue]),
1115
+ );
1116
+ }
1117
+
1100
1118
  const enumValue = this._valueLookup.get(outputValue);
1101
1119
 
1102
1120
  if (enumValue === undefined) {
@@ -1253,7 +1271,7 @@ function defineEnumValues(typeName, valueMap) {
1253
1271
  */
1254
1272
  class GraphQLInputObjectType {
1255
1273
  constructor(config) {
1256
- var _config$extensionASTN6;
1274
+ var _config$extensionASTN6, _config$isOneOf;
1257
1275
 
1258
1276
  this.name = (0, _assertName.assertName)(config.name);
1259
1277
  this.description = config.description;
@@ -1264,6 +1282,10 @@ class GraphQLInputObjectType {
1264
1282
  _config$extensionASTN6 !== void 0
1265
1283
  ? _config$extensionASTN6
1266
1284
  : [];
1285
+ this.isOneOf =
1286
+ (_config$isOneOf = config.isOneOf) !== null && _config$isOneOf !== void 0
1287
+ ? _config$isOneOf
1288
+ : false;
1267
1289
  this._fields = defineInputFieldMap.bind(undefined, config);
1268
1290
  }
1269
1291
 
@@ -1295,6 +1317,7 @@ class GraphQLInputObjectType {
1295
1317
  extensions: this.extensions,
1296
1318
  astNode: this.astNode,
1297
1319
  extensionASTNodes: this.extensionASTNodes,
1320
+ isOneOf: this.isOneOf,
1298
1321
  };
1299
1322
  }
1300
1323
 
@@ -926,11 +926,12 @@ export class GraphQLEnumType {
926
926
  _config$extensionASTN5 !== void 0
927
927
  ? _config$extensionASTN5
928
928
  : [];
929
- this._values = defineEnumValues(this.name, config.values);
930
- this._valueLookup = new Map(
931
- this._values.map((enumValue) => [enumValue.value, enumValue]),
932
- );
933
- this._nameLookup = keyMap(this._values, (value) => value.name);
929
+ this._values =
930
+ typeof config.values === 'function'
931
+ ? config.values
932
+ : defineEnumValues(this.name, config.values);
933
+ this._valueLookup = null;
934
+ this._nameLookup = null;
934
935
  }
935
936
 
936
937
  get [Symbol.toStringTag]() {
@@ -938,14 +939,28 @@ export class GraphQLEnumType {
938
939
  }
939
940
 
940
941
  getValues() {
942
+ if (typeof this._values === 'function') {
943
+ this._values = defineEnumValues(this.name, this._values());
944
+ }
945
+
941
946
  return this._values;
942
947
  }
943
948
 
944
949
  getValue(name) {
950
+ if (this._nameLookup === null) {
951
+ this._nameLookup = keyMap(this.getValues(), (value) => value.name);
952
+ }
953
+
945
954
  return this._nameLookup[name];
946
955
  }
947
956
 
948
957
  serialize(outputValue) {
958
+ if (this._valueLookup === null) {
959
+ this._valueLookup = new Map(
960
+ this.getValues().map((enumValue) => [enumValue.value, enumValue]),
961
+ );
962
+ }
963
+
949
964
  const enumValue = this._valueLookup.get(outputValue);
950
965
 
951
966
  if (enumValue === undefined) {
@@ -1093,7 +1108,7 @@ function defineEnumValues(typeName, valueMap) {
1093
1108
  */
1094
1109
  export class GraphQLInputObjectType {
1095
1110
  constructor(config) {
1096
- var _config$extensionASTN6;
1111
+ var _config$extensionASTN6, _config$isOneOf;
1097
1112
 
1098
1113
  this.name = assertName(config.name);
1099
1114
  this.description = config.description;
@@ -1104,6 +1119,10 @@ export class GraphQLInputObjectType {
1104
1119
  _config$extensionASTN6 !== void 0
1105
1120
  ? _config$extensionASTN6
1106
1121
  : [];
1122
+ this.isOneOf =
1123
+ (_config$isOneOf = config.isOneOf) !== null && _config$isOneOf !== void 0
1124
+ ? _config$isOneOf
1125
+ : false;
1107
1126
  this._fields = defineInputFieldMap.bind(undefined, config);
1108
1127
  }
1109
1128
 
@@ -1135,6 +1154,7 @@ export class GraphQLInputObjectType {
1135
1154
  extensions: this.extensions,
1136
1155
  astNode: this.astNode,
1137
1156
  extensionASTNodes: this.extensionASTNodes,
1157
+ isOneOf: this.isOneOf,
1138
1158
  };
1139
1159
  }
1140
1160
 
@@ -76,6 +76,10 @@ export declare const GraphQLDeprecatedDirective: GraphQLDirective;
76
76
  * Used to provide a URL for specifying the behavior of custom scalar definitions.
77
77
  */
78
78
  export declare const GraphQLSpecifiedByDirective: GraphQLDirective;
79
+ /**
80
+ * Used to indicate an Input Object is a OneOf Input Object.
81
+ */
82
+ export declare const GraphQLOneOfDirective: GraphQLDirective;
79
83
  /**
80
84
  * The full list of specified directives.
81
85
  */
@@ -5,6 +5,7 @@ Object.defineProperty(exports, '__esModule', {
5
5
  });
6
6
  exports.GraphQLSpecifiedByDirective =
7
7
  exports.GraphQLSkipDirective =
8
+ exports.GraphQLOneOfDirective =
8
9
  exports.GraphQLIncludeDirective =
9
10
  exports.GraphQLDirective =
10
11
  exports.GraphQLDeprecatedDirective =
@@ -207,15 +208,28 @@ const GraphQLSpecifiedByDirective = new GraphQLDirective({
207
208
  },
208
209
  });
209
210
  /**
210
- * The full list of specified directives.
211
+ * Used to indicate an Input Object is a OneOf Input Object.
211
212
  */
212
213
 
213
214
  exports.GraphQLSpecifiedByDirective = GraphQLSpecifiedByDirective;
215
+ const GraphQLOneOfDirective = new GraphQLDirective({
216
+ name: 'oneOf',
217
+ description:
218
+ 'Indicates exactly one field must be supplied and this field must not be `null`.',
219
+ locations: [_directiveLocation.DirectiveLocation.INPUT_OBJECT],
220
+ args: {},
221
+ });
222
+ /**
223
+ * The full list of specified directives.
224
+ */
225
+
226
+ exports.GraphQLOneOfDirective = GraphQLOneOfDirective;
214
227
  const specifiedDirectives = Object.freeze([
215
228
  GraphQLIncludeDirective,
216
229
  GraphQLSkipDirective,
217
230
  GraphQLDeprecatedDirective,
218
231
  GraphQLSpecifiedByDirective,
232
+ GraphQLOneOfDirective,
219
233
  ]);
220
234
  exports.specifiedDirectives = specifiedDirectives;
221
235
 
@@ -175,6 +175,17 @@ export const GraphQLSpecifiedByDirective = new GraphQLDirective({
175
175
  },
176
176
  },
177
177
  });
178
+ /**
179
+ * Used to indicate an Input Object is a OneOf Input Object.
180
+ */
181
+
182
+ export const GraphQLOneOfDirective = new GraphQLDirective({
183
+ name: 'oneOf',
184
+ description:
185
+ 'Indicates exactly one field must be supplied and this field must not be `null`.',
186
+ locations: [DirectiveLocation.INPUT_OBJECT],
187
+ args: {},
188
+ });
178
189
  /**
179
190
  * The full list of specified directives.
180
191
  */
@@ -184,6 +195,7 @@ export const specifiedDirectives = Object.freeze([
184
195
  GraphQLSkipDirective,
185
196
  GraphQLDeprecatedDirective,
186
197
  GraphQLSpecifiedByDirective,
198
+ GraphQLOneOfDirective,
187
199
  ]);
188
200
  export function isSpecifiedDirective(directive) {
189
201
  return specifiedDirectives.some(({ name }) => name === directive.name);
package/type/index.d.ts CHANGED
@@ -113,6 +113,7 @@ export {
113
113
  GraphQLSkipDirective,
114
114
  GraphQLDeprecatedDirective,
115
115
  GraphQLSpecifiedByDirective,
116
+ GraphQLOneOfDirective,
116
117
  DEFAULT_DEPRECATION_REASON,
117
118
  } from './directives';
118
119
  export type {
package/type/index.js CHANGED
@@ -99,6 +99,12 @@ Object.defineProperty(exports, 'GraphQLObjectType', {
99
99
  return _definition.GraphQLObjectType;
100
100
  },
101
101
  });
102
+ Object.defineProperty(exports, 'GraphQLOneOfDirective', {
103
+ enumerable: true,
104
+ get: function () {
105
+ return _directives.GraphQLOneOfDirective;
106
+ },
107
+ });
102
108
  Object.defineProperty(exports, 'GraphQLScalarType', {
103
109
  enumerable: true,
104
110
  get: function () {
package/type/index.mjs CHANGED
@@ -64,7 +64,8 @@ export {
64
64
  GraphQLIncludeDirective,
65
65
  GraphQLSkipDirective,
66
66
  GraphQLDeprecatedDirective,
67
- GraphQLSpecifiedByDirective, // Constant Deprecation Reason
67
+ GraphQLSpecifiedByDirective,
68
+ GraphQLOneOfDirective, // Constant Deprecation Reason
68
69
  DEFAULT_DEPRECATION_REASON,
69
70
  } from './directives.mjs';
70
71
  // Common built-in scalar instances.
@@ -373,6 +373,14 @@ const __Type = new _definition.GraphQLObjectType({
373
373
  type: __Type,
374
374
  resolve: (type) => ('ofType' in type ? type.ofType : undefined),
375
375
  },
376
+ isOneOf: {
377
+ type: _scalars.GraphQLBoolean,
378
+ resolve: (type) => {
379
+ if ((0, _definition.isInputObjectType)(type)) {
380
+ return type.isOneOf;
381
+ }
382
+ },
383
+ },
376
384
  }),
377
385
  });
378
386
 
@@ -326,6 +326,14 @@ export const __Type = new GraphQLObjectType({
326
326
  type: __Type,
327
327
  resolve: (type) => ('ofType' in type ? type.ofType : undefined),
328
328
  },
329
+ isOneOf: {
330
+ type: GraphQLBoolean,
331
+ resolve: (type) => {
332
+ if (isInputObjectType(type)) {
333
+ return type.isOneOf;
334
+ }
335
+ },
336
+ },
329
337
  }),
330
338
  });
331
339
  export const __Field = new GraphQLObjectType({
package/type/validate.js CHANGED
@@ -568,6 +568,30 @@ function validateInputFields(context, inputObj) {
568
568
  ],
569
569
  );
570
570
  }
571
+
572
+ if (inputObj.isOneOf) {
573
+ validateOneOfInputObjectField(inputObj, field, context);
574
+ }
575
+ }
576
+ }
577
+
578
+ function validateOneOfInputObjectField(type, field, context) {
579
+ if ((0, _definition.isNonNullType)(field.type)) {
580
+ var _field$astNode4;
581
+
582
+ context.reportError(
583
+ `OneOf input field ${type.name}.${field.name} must be nullable.`,
584
+ (_field$astNode4 = field.astNode) === null || _field$astNode4 === void 0
585
+ ? void 0
586
+ : _field$astNode4.type,
587
+ );
588
+ }
589
+
590
+ if (field.defaultValue !== undefined) {
591
+ context.reportError(
592
+ `OneOf input field ${type.name}.${field.name} cannot have a default value.`,
593
+ field.astNode,
594
+ );
571
595
  }
572
596
  }
573
597
 
package/type/validate.mjs CHANGED
@@ -547,6 +547,30 @@ function validateInputFields(context, inputObj) {
547
547
  ],
548
548
  );
549
549
  }
550
+
551
+ if (inputObj.isOneOf) {
552
+ validateOneOfInputObjectField(inputObj, field, context);
553
+ }
554
+ }
555
+ }
556
+
557
+ function validateOneOfInputObjectField(type, field, context) {
558
+ if (isNonNullType(field.type)) {
559
+ var _field$astNode4;
560
+
561
+ context.reportError(
562
+ `OneOf input field ${type.name}.${field.name} must be nullable.`,
563
+ (_field$astNode4 = field.astNode) === null || _field$astNode4 === void 0
564
+ ? void 0
565
+ : _field$astNode4.type,
566
+ );
567
+ }
568
+
569
+ if (field.defaultValue !== undefined) {
570
+ context.reportError(
571
+ `OneOf input field ${type.name}.${field.name} cannot have a default value.`,
572
+ field.astNode,
573
+ );
550
574
  }
551
575
  }
552
576
 
@@ -279,6 +279,7 @@ function buildClientSchema(introspection, options) {
279
279
  name: inputObjectIntrospection.name,
280
280
  description: inputObjectIntrospection.description,
281
281
  fields: () => buildInputValueDefMap(inputObjectIntrospection.inputFields),
282
+ isOneOf: inputObjectIntrospection.isOneOf,
282
283
  });
283
284
  }
284
285
 
@@ -265,6 +265,7 @@ export function buildClientSchema(introspection, options) {
265
265
  name: inputObjectIntrospection.name,
266
266
  description: inputObjectIntrospection.description,
267
267
  fields: () => buildInputValueDefMap(inputObjectIntrospection.inputFields),
268
+ isOneOf: inputObjectIntrospection.isOneOf,
268
269
  });
269
270
  }
270
271
 
@@ -139,6 +139,31 @@ function coerceInputValueImpl(inputValue, type, onError, path) {
139
139
  }
140
140
  }
141
141
 
142
+ if (type.isOneOf) {
143
+ const keys = Object.keys(coercedValue);
144
+
145
+ if (keys.length !== 1) {
146
+ onError(
147
+ (0, _Path.pathToArray)(path),
148
+ inputValue,
149
+ new _GraphQLError.GraphQLError(
150
+ `Exactly one key must be specified for OneOf type "${type.name}".`,
151
+ ),
152
+ );
153
+ }
154
+
155
+ const key = keys[0];
156
+ const value = coercedValue[key];
157
+
158
+ if (value === null) {
159
+ onError(
160
+ (0, _Path.pathToArray)(path).concat(key),
161
+ value,
162
+ new _GraphQLError.GraphQLError(`Field "${key}" must be non-null.`),
163
+ );
164
+ }
165
+ }
166
+
142
167
  return coercedValue;
143
168
  }
144
169
 
@@ -124,6 +124,31 @@ function coerceInputValueImpl(inputValue, type, onError, path) {
124
124
  }
125
125
  }
126
126
 
127
+ if (type.isOneOf) {
128
+ const keys = Object.keys(coercedValue);
129
+
130
+ if (keys.length !== 1) {
131
+ onError(
132
+ pathToArray(path),
133
+ inputValue,
134
+ new GraphQLError(
135
+ `Exactly one key must be specified for OneOf type "${type.name}".`,
136
+ ),
137
+ );
138
+ }
139
+
140
+ const key = keys[0];
141
+ const value = coercedValue[key];
142
+
143
+ if (value === null) {
144
+ onError(
145
+ pathToArray(path).concat(key),
146
+ value,
147
+ new GraphQLError(`Field "${key}" must be non-null.`),
148
+ );
149
+ }
150
+ }
151
+
127
152
  return coercedValue;
128
153
  }
129
154
 
@@ -757,6 +757,7 @@ function extendSchemaImpl(schemaConfig, documentAST, options) {
757
757
  fields: () => buildInputFieldMap(allNodes),
758
758
  astNode,
759
759
  extensionASTNodes,
760
+ isOneOf: isOneOf(astNode),
760
761
  });
761
762
  }
762
763
  }
@@ -796,3 +797,12 @@ function getSpecifiedByURL(node) {
796
797
  ? void 0
797
798
  : specifiedBy.url;
798
799
  }
800
+ /**
801
+ * Given an input object node, returns if the node should be OneOf.
802
+ */
803
+
804
+ function isOneOf(node) {
805
+ return Boolean(
806
+ (0, _values.getDirectiveValues)(_directives.GraphQLOneOfDirective, node),
807
+ );
808
+ }
@@ -29,6 +29,7 @@ import {
29
29
  import {
30
30
  GraphQLDeprecatedDirective,
31
31
  GraphQLDirective,
32
+ GraphQLOneOfDirective,
32
33
  GraphQLSpecifiedByDirective,
33
34
  } from '../type/directives.mjs';
34
35
  import {
@@ -755,6 +756,7 @@ export function extendSchemaImpl(schemaConfig, documentAST, options) {
755
756
  fields: () => buildInputFieldMap(allNodes),
756
757
  astNode,
757
758
  extensionASTNodes,
759
+ isOneOf: isOneOf(astNode),
758
760
  });
759
761
  }
760
762
  }
@@ -787,3 +789,10 @@ function getSpecifiedByURL(node) {
787
789
  ? void 0
788
790
  : specifiedBy.url;
789
791
  }
792
+ /**
793
+ * Given an input object node, returns if the node should be OneOf.
794
+ */
795
+
796
+ function isOneOf(node) {
797
+ return Boolean(getDirectiveValues(GraphQLOneOfDirective, node));
798
+ }