UNPKG

40.3 kBJavaScriptView Raw
1/**
2 * Copyright (c) Facebook, Inc. and its affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 *
7 *
8 * @format
9 */
10'use strict';
11
12var _objectSpread2 = require("@babel/runtime/helpers/interopRequireDefault")(require("@babel/runtime/helpers/objectSpread"));
13
14var _toConsumableArray2 = require("@babel/runtime/helpers/interopRequireDefault")(require("@babel/runtime/helpers/toConsumableArray"));
15
16var ARGUMENT_DEFINITIONS = 'argumentDefinitions';
17var ARGUMENTS = 'arguments';
18/**
19 * @internal
20 *
21 * This directive is not intended for use by developers directly. To set a field
22 * handle in product code use a compiler plugin.
23 */
24
25var CLIENT_FIELD = '__clientField';
26var CLIENT_FIELD_HANDLE = 'handle';
27var CLIENT_FIELD_KEY = 'key';
28var CLIENT_FIELD_FILTERS = 'filters';
29var INCLUDE = 'include';
30var SKIP = 'skip';
31var IF = 'if';
32/**
33 * Transforms GraphQL text into Relay Compiler's internal, strongly-typed
34 * intermediate representation (IR).
35 */
36
37function parse(schema, text, filename) {
38 var ast = require("graphql").parse(new (require("graphql").Source)(text, filename)); // TODO T24511737 figure out if this is dangerous
39
40
41 schema = require("graphql").extendSchema(schema, ast, {
42 assumeValid: true
43 });
44 var parser = new RelayParser(schema, ast.definitions);
45 return parser.transform();
46}
47/**
48 * Transforms untyped GraphQL parse trees (ASTs) into Relay Compiler's
49 * internal, strongly-typed intermediate representation (IR).
50 */
51
52
53function transform(schema, definitions) {
54 return require("./GraphQLCompilerProfiler").run('RelayParser.transform', function () {
55 var parser = new RelayParser(schema, definitions);
56 return parser.transform();
57 });
58}
59/**
60 * @private
61 */
62
63
64var RelayParser =
65/*#__PURE__*/
66function () {
67 function RelayParser(schema, definitions) {
68 var _this = this;
69
70 this._definitions = new Map(); // leaving this configurable to make it easy to experiment w changing later
71
72 this._getFieldDefinition = require("./getFieldDefinition").getFieldDefinitionLegacy;
73 this._schema = schema;
74 var duplicated = new Set();
75 definitions.forEach(function (def) {
76 if (require("./GraphQLSchemaUtils").isExecutableDefinitionAST(def)) {
77 var name = getName(def);
78
79 if (_this._definitions.has(name)) {
80 duplicated.add(name);
81 return;
82 }
83
84 _this._definitions.set(name, def);
85 }
86 });
87
88 if (duplicated.size) {
89 throw new Error('RelayParser: Encountered duplicate defintitions for one or more ' + 'documents: each document must have a unique name. Duplicated documents:\n' + Array.from(duplicated, function (name) {
90 return "- ".concat(name);
91 }).join('\n'));
92 }
93 }
94
95 var _proto = RelayParser.prototype;
96
97 _proto.transform = function transform() {
98 var _this2 = this;
99
100 var errors;
101 var nodes = [];
102 var entries = new Map(); // Construct a mapping of name to definition ast + variable definitions.
103 // This allows the subsequent AST -> IR tranformation to reference the
104 // defined arguments of referenced fragments.
105
106 errors = require("./RelayCompilerError").eachWithErrors(this._definitions, function (_ref2) {
107 var name = _ref2[0],
108 definition = _ref2[1];
109
110 var variableDefinitions = _this2._buildArgumentDefinitions(definition);
111
112 entries.set(name, {
113 definition: definition,
114 variableDefinitions: variableDefinitions
115 });
116 }); // Convert the ASTs to IR.
117
118 if (errors == null) {
119 errors = require("./RelayCompilerError").eachWithErrors(entries.values(), function (_ref3) {
120 var definition = _ref3.definition,
121 variableDefinitions = _ref3.variableDefinitions;
122 var node = parseDefinition(_this2._schema, _this2._getFieldDefinition, entries, definition, variableDefinitions);
123 nodes.push(node);
124 });
125 }
126
127 if (errors != null && errors.length !== 0) {
128 throw require("./RelayCompilerError").createCombinedError(errors, 'RelayParser');
129 }
130
131 return nodes;
132 };
133 /**
134 * Constructs a mapping of variable names to definitions for the given
135 * operation/fragment definition.
136 */
137
138
139 _proto._buildArgumentDefinitions = function _buildArgumentDefinitions(definition) {
140 switch (definition.kind) {
141 case 'OperationDefinition':
142 return this._buildOperationArgumentDefinitions(definition);
143
144 case 'FragmentDefinition':
145 return this._buildFragmentArgumentDefinitions(definition);
146
147 default:
148 definition;
149 throw require("./RelayCompilerError").createCompilerError("Unexpected ast kind '".concat(definition.kind, "'."), [definition]);
150 }
151 };
152 /**
153 * Constructs a mapping of variable names to definitions using the
154 * variables defined in `@argumentDefinitions`.
155 */
156
157
158 _proto._buildFragmentArgumentDefinitions = function _buildFragmentArgumentDefinitions(fragment) {
159 var _this3 = this;
160
161 var variableDirectives = (fragment.directives || []).filter(function (directive) {
162 return getName(directive) === ARGUMENT_DEFINITIONS;
163 });
164
165 if (!variableDirectives.length) {
166 return new Map();
167 }
168
169 if (variableDirectives.length !== 1) {
170 throw require("./RelayCompilerError").createUserError("Directive @".concat(ARGUMENT_DEFINITIONS, " may be defined at most once per ") + 'fragment.', null, variableDirectives);
171 }
172
173 var variableDirective = variableDirectives[0]; // $FlowIssue: refining directly on `variableDirective.arguments` doesn't
174 // work, below accesses all report arguments could still be null/undefined.
175
176 var args = variableDirective.arguments;
177
178 if (variableDirective == null || !Array.isArray(args)) {
179 return new Map();
180 }
181
182 if (!args.length) {
183 throw require("./RelayCompilerError").createUserError("Directive @".concat(ARGUMENT_DEFINITIONS, " requires arguments: remove the ") + 'directive to skip defining local variables for this fragment.', null, [variableDirective]);
184 }
185
186 var variables = new Map();
187 args.forEach(function (arg) {
188 var argName = getName(arg);
189 var previousVariable = variables.get(argName);
190
191 if (previousVariable != null) {
192 throw require("./RelayCompilerError").createUserError("Duplicate definition for variable '$".concat(argName, "'."), null, [previousVariable.ast, arg]);
193 }
194
195 var value = transformLiteralValue(arg.value, arg);
196
197 if (Array.isArray(value) || typeof value !== 'object' || value === null || typeof value.type !== 'string') {
198 throw require("./RelayCompilerError").createUserError("Expected definition for variable '$".concat(argName, "' to be an object ") + "with the shape: '{type: string, defaultValue?: mixed, nonNull?: " + "boolean, list?: boolean}'.", null, [arg.value]);
199 }
200
201 var unknownKeys = Object.keys(value).filter(function (key) {
202 return key !== 'type' && key !== 'defaultValue' && key !== 'nonNull' && key !== 'list';
203 });
204
205 if (unknownKeys.length !== 0) {
206 var unknownKeysString = "'" + unknownKeys.join("', '") + "'";
207 throw require("./RelayCompilerError").createUserError("Expected definition for variable '$".concat(argName, "' to be an object ") + "with the following shape: '{type: string, defaultValue?: mixed, " + "nonNull?: boolean, list?: boolean}', got unknown key(s) " + "".concat(unknownKeysString, "."), null, [arg]);
208 }
209
210 var typeAST = require("graphql").parseType(String(value.type));
211
212 var type = require("graphql").assertInputType(require("./GraphQLSchemaUtils").getTypeFromAST(_this3._schema, typeAST));
213
214 variables.set(argName, {
215 ast: arg,
216 defaultValue: value.defaultValue != null ? value.defaultValue : null,
217 defined: true,
218 name: argName,
219 type: type
220 });
221 });
222 return variables;
223 };
224 /**
225 * Constructs a mapping of variable names to definitions using the
226 * standard GraphQL syntax for variable definitions.
227 */
228
229
230 _proto._buildOperationArgumentDefinitions = function _buildOperationArgumentDefinitions(operation) {
231 var _this4 = this;
232
233 var variableDefinitions = new Map();
234 (operation.variableDefinitions || []).forEach(function (def) {
235 var name = getName(def.variable);
236
237 var type = require("graphql").assertInputType(require("./GraphQLSchemaUtils").getTypeFromAST(_this4._schema, def.type));
238
239 var defaultValue = def.defaultValue ? transformLiteralValue(def.defaultValue, def) : null;
240 var previousDefinition = variableDefinitions.get(name);
241
242 if (previousDefinition != null) {
243 throw require("./RelayCompilerError").createUserError("Duplicate definition for variable '$".concat(name, "'."), null, [previousDefinition.ast, def]);
244 }
245
246 variableDefinitions.set(name, {
247 ast: def,
248 defaultValue: defaultValue,
249 defined: true,
250 name: name,
251 type: type
252 });
253 });
254 return variableDefinitions;
255 };
256
257 return RelayParser;
258}();
259/**
260 * @private
261 */
262
263
264function parseDefinition(schema, getFieldDefinition, entries, definition, variableDefinitions) {
265 var parser = new GraphQLDefinitionParser(schema, getFieldDefinition, entries, definition, variableDefinitions);
266 return parser.transform();
267}
268/**
269 * @private
270 */
271
272
273var GraphQLDefinitionParser =
274/*#__PURE__*/
275function () {
276 function GraphQLDefinitionParser(schema, getFieldDefinition, entries, definition, variableDefinitions) {
277 this._definition = definition;
278 this._entries = entries;
279 this._getFieldDefinition = getFieldDefinition;
280 this._schema = schema;
281 this._variableDefinitions = variableDefinitions;
282 this._unknownVariables = new Map();
283 }
284
285 var _proto2 = GraphQLDefinitionParser.prototype;
286
287 _proto2.transform = function transform() {
288 var definition = this._definition;
289
290 switch (definition.kind) {
291 case 'OperationDefinition':
292 return this._transformOperation(definition);
293
294 case 'FragmentDefinition':
295 return this._transformFragment(definition);
296
297 default:
298 definition;
299 throw require("./RelayCompilerError").createCompilerError("Unsupported definition type ".concat(definition.kind), [definition]);
300 }
301 };
302
303 _proto2._getErrorContext = function _getErrorContext() {
304 var message = "document `".concat(getName(this._definition), "`");
305
306 if (this._definition.loc && this._definition.loc.source) {
307 message += " file: `".concat(this._definition.loc.source.name, "`");
308 }
309
310 return message;
311 };
312
313 _proto2._recordAndVerifyVariableReference = function _recordAndVerifyVariableReference(variable, name, usedAsType) {
314 // Special case for variables used in @arguments where we currently
315 // aren't guaranteed to be able to resolve the type.
316 if (usedAsType == null) {
317 if (!this._variableDefinitions.has(name) && !this._unknownVariables.has(name)) {
318 this._unknownVariables.set(name, {
319 ast: variable,
320 type: null
321 });
322 }
323
324 return;
325 }
326
327 var variableDefinition = this._variableDefinitions.get(name);
328
329 if (variableDefinition != null) {
330 // If the variable is defined, all usages must be compatible
331 var effectiveType = variableDefinition.type;
332
333 if (variableDefinition.defaultValue != null) {
334 // If a default value is defined then it is guaranteed to be used
335 // at runtime such that the effective type of the variable is non-null
336 effectiveType = new (require("graphql").GraphQLNonNull)(require("./GraphQLSchemaUtils").getNullableType(effectiveType));
337 }
338
339 if (!require("graphql").isTypeSubTypeOf(this._schema, effectiveType, usedAsType)) {
340 throw require("./RelayCompilerError").createUserError("Variable '$".concat(name, "' was defined as type '").concat(String(variableDefinition.type), "' but used in a location expecting the type '").concat(String(usedAsType), "'"), null, [variableDefinition.ast, variable]);
341 }
342 } else {
343 var previous = this._unknownVariables.get(name);
344
345 if (!previous || !previous.type) {
346 // No previous usage, current type is strongest
347 this._unknownVariables.set(name, {
348 ast: variable,
349 type: usedAsType
350 });
351 } else {
352 var previousType = previous.type,
353 previousVariable = previous.ast;
354
355 if (!(require("graphql").isTypeSubTypeOf(this._schema, usedAsType, previousType) || require("graphql").isTypeSubTypeOf(this._schema, previousType, usedAsType))) {
356 throw require("./RelayCompilerError").createUserError("Variable '$".concat(name, "' was used in locations expecting the conflicting types '").concat(String(previousType), "' and '").concat(String(usedAsType), "'. Source: ").concat(this._getErrorContext()), null, [previousVariable, variable]);
357 } // If the new used type has stronger requirements, use that type as reference,
358 // otherwise keep referencing the previous type
359
360
361 if (require("graphql").isTypeSubTypeOf(this._schema, usedAsType, previousType)) {
362 this._unknownVariables.set(name, {
363 ast: variable,
364 type: usedAsType
365 });
366 }
367 }
368 }
369 };
370
371 _proto2._transformFragment = function _transformFragment(fragment) {
372 var directives = this._transformDirectives((fragment.directives || []).filter(function (directive) {
373 return getName(directive) !== ARGUMENT_DEFINITIONS;
374 }));
375
376 var type = require("graphql").assertCompositeType(require("./GraphQLSchemaUtils").getTypeFromAST(this._schema, fragment.typeCondition));
377
378 var selections = this._transformSelections(fragment.selectionSet, type);
379
380 var argumentDefinitions = (0, _toConsumableArray2["default"])(buildArgumentDefinitions(this._variableDefinitions));
381 var _iteratorNormalCompletion = true;
382 var _didIteratorError = false;
383 var _iteratorError = undefined;
384
385 try {
386 for (var _iterator = this._unknownVariables[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
387 var _step$value = _step.value,
388 name = _step$value[0],
389 variableReference = _step$value[1];
390 argumentDefinitions.push({
391 kind: 'RootArgumentDefinition',
392 loc: buildLocation(variableReference.ast.loc),
393 metadata: null,
394 name: name,
395 // $FlowFixMe - could be null
396 type: variableReference.type
397 });
398 }
399 } catch (err) {
400 _didIteratorError = true;
401 _iteratorError = err;
402 } finally {
403 try {
404 if (!_iteratorNormalCompletion && _iterator["return"] != null) {
405 _iterator["return"]();
406 }
407 } finally {
408 if (_didIteratorError) {
409 throw _iteratorError;
410 }
411 }
412 }
413
414 return {
415 kind: 'Fragment',
416 directives: directives,
417 loc: buildLocation(fragment.loc),
418 metadata: null,
419 name: getName(fragment),
420 selections: selections,
421 type: type,
422 argumentDefinitions: argumentDefinitions
423 };
424 };
425
426 _proto2._transformOperation = function _transformOperation(definition) {
427 var name = getName(definition);
428
429 var directives = this._transformDirectives(definition.directives || []);
430
431 var type;
432 var operation;
433
434 switch (definition.operation) {
435 case 'query':
436 operation = 'query';
437 type = require("graphql").assertCompositeType(this._schema.getQueryType());
438 break;
439
440 case 'mutation':
441 operation = 'mutation';
442 type = require("graphql").assertCompositeType(this._schema.getMutationType());
443 break;
444
445 case 'subscription':
446 operation = 'subscription';
447 type = require("graphql").assertCompositeType(this._schema.getSubscriptionType());
448 break;
449
450 default:
451 definition.operation;
452 throw require("./RelayCompilerError").createCompilerError("Unknown ast kind '".concat(definition.operation, "'. Source: ").concat(this._getErrorContext(), "."), null, [definition]);
453 }
454
455 if (!definition.selectionSet) {
456 throw require("./RelayCompilerError").createUserError("Expected operation to have selections. Source: ".concat(this._getErrorContext()), null, [definition]);
457 }
458
459 var selections = this._transformSelections(definition.selectionSet, type);
460
461 var argumentDefinitions = buildArgumentDefinitions(this._variableDefinitions);
462
463 if (this._unknownVariables.size !== 0) {
464 throw require("./RelayCompilerError").createUserError("Query '".concat(name, "' references undefined variables."), null, Array.from(this._unknownVariables.values(), function (variableReference) {
465 return variableReference.ast;
466 }));
467 }
468
469 return {
470 kind: 'Root',
471 operation: operation,
472 loc: buildLocation(definition.loc),
473 metadata: null,
474 name: name,
475 argumentDefinitions: argumentDefinitions,
476 directives: directives,
477 selections: selections,
478 type: type
479 };
480 };
481
482 _proto2._transformSelections = function _transformSelections(selectionSet, parentType) {
483 var _this5 = this;
484
485 return selectionSet.selections.map(function (selection) {
486 var node;
487
488 if (selection.kind === 'Field') {
489 node = _this5._transformField(selection, parentType);
490 } else if (selection.kind === 'FragmentSpread') {
491 node = _this5._transformFragmentSpread(selection, parentType);
492 } else if (selection.kind === 'InlineFragment') {
493 node = _this5._transformInlineFragment(selection, parentType);
494 } else {
495 selection.kind;
496 throw require("./RelayCompilerError").createCompilerError("Unknown ast kind '".concat(selection.kind, "'. Source: ").concat(_this5._getErrorContext(), "."), [selection]);
497 }
498
499 var _this5$_splitConditio = _this5._splitConditions(node.directives),
500 conditions = _this5$_splitConditio[0],
501 directives = _this5$_splitConditio[1];
502
503 var conditionalNodes = applyConditions(conditions, // $FlowFixMe(>=0.28.0)
504 [(0, _objectSpread2["default"])({}, node, {
505 directives: directives
506 })]);
507
508 if (conditionalNodes.length !== 1) {
509 throw require("./RelayCompilerError").createCompilerError("Expected exactly one condition node. Source: ".concat(_this5._getErrorContext()), null, selection.directives);
510 }
511
512 return conditionalNodes[0];
513 });
514 };
515
516 _proto2._transformInlineFragment = function _transformInlineFragment(fragment, parentType) {
517 var typeCondition = require("graphql").assertCompositeType(fragment.typeCondition ? require("./GraphQLSchemaUtils").getTypeFromAST(this._schema, fragment.typeCondition) : parentType);
518
519 var directives = this._transformDirectives(fragment.directives || []);
520
521 var selections = this._transformSelections(fragment.selectionSet, typeCondition);
522
523 return {
524 kind: 'InlineFragment',
525 directives: directives,
526 loc: buildLocation(fragment.loc),
527 metadata: null,
528 selections: selections,
529 typeCondition: typeCondition
530 };
531 };
532
533 _proto2._transformFragmentSpread = function _transformFragmentSpread(fragmentSpread, parentType) {
534 var _this6 = this;
535
536 var fragmentName = getName(fragmentSpread);
537
538 var _partitionArray = partitionArray(fragmentSpread.directives || [], function (directive) {
539 return getName(directive) !== ARGUMENTS;
540 }),
541 otherDirectives = _partitionArray[0],
542 argumentDirectives = _partitionArray[1];
543
544 if (argumentDirectives.length > 1) {
545 throw require("./RelayCompilerError").createUserError("Directive @".concat(ARGUMENTS, " may be used at most once per a fragment spread. ") + "Source: ".concat(this._getErrorContext()), null, argumentDirectives);
546 }
547
548 var fragmentDefinition = this._entries.get(fragmentName);
549
550 var fragmentArgumentDefinitions = fragmentDefinition === null || fragmentDefinition === void 0 ? void 0 : fragmentDefinition.variableDefinitions;
551 var args;
552
553 if (argumentDirectives.length) {
554 args = (argumentDirectives[0].arguments || []).map(function (arg) {
555 var _ref;
556
557 var argName = getName(arg);
558 var argValue = arg.value;
559 var argumentDefinition = fragmentArgumentDefinitions != null ? fragmentArgumentDefinitions.get(argName) : null;
560 var argumentType = (_ref = argumentDefinition === null || argumentDefinition === void 0 ? void 0 : argumentDefinition.type) !== null && _ref !== void 0 ? _ref : null;
561
562 if (argValue.kind === 'Variable') {
563 // TODO: check the type of the variable and use the type
564 return {
565 kind: 'Argument',
566 loc: buildLocation(arg.loc),
567 metadata: null,
568 name: argName,
569 value: _this6._transformVariable(argValue, null),
570 type: null
571 };
572 } else {
573 if (argumentType == null) {
574 var _this$_entries$get;
575
576 throw require("./RelayCompilerError").createUserError("Literal @".concat(ARGUMENTS, " values are only supported when the ") + "argument is defined with @".concat(ARGUMENT_DEFINITIONS, ". Check ") + "the definition of fragment '".concat(fragmentName, "'."), null, [arg.value, (_this$_entries$get = _this6._entries.get(fragmentName)) === null || _this$_entries$get === void 0 ? void 0 : _this$_entries$get.definition].filter(Boolean));
577 }
578
579 var _value = _this6._transformValue(argValue, argumentType);
580
581 return {
582 kind: 'Argument',
583 loc: buildLocation(arg.loc),
584 metadata: null,
585 name: argName,
586 value: _value,
587 type: argumentType
588 };
589 }
590 });
591 }
592
593 var directives = this._transformDirectives(otherDirectives);
594
595 return {
596 kind: 'FragmentSpread',
597 args: args || [],
598 metadata: null,
599 loc: buildLocation(fragmentSpread.loc),
600 name: fragmentName,
601 directives: directives
602 };
603 };
604
605 _proto2._transformField = function _transformField(field, parentType) {
606 var name = getName(field);
607
608 var fieldDef = this._getFieldDefinition(this._schema, parentType, name, field);
609
610 if (fieldDef == null) {
611 throw require("./RelayCompilerError").createUserError("Unknown field '".concat(name, "' on type '").concat(String(parentType), "'. Source: ").concat(this._getErrorContext()), null, [field]);
612 }
613
614 var alias = field.alias ? field.alias.value : null;
615
616 var args = this._transformArguments(field.arguments || [], fieldDef.args);
617
618 var _partitionArray2 = partitionArray(field.directives || [], function (directive) {
619 return getName(directive) !== CLIENT_FIELD;
620 }),
621 otherDirectives = _partitionArray2[0],
622 clientFieldDirectives = _partitionArray2[1];
623
624 var directives = this._transformDirectives(otherDirectives);
625
626 var type = require("graphql").assertOutputType(fieldDef.type);
627
628 var handles = this._transformHandle(name, args, clientFieldDirectives);
629
630 if (require("graphql").isLeafType(require("graphql").getNamedType(type))) {
631 if (field.selectionSet && field.selectionSet.selections && field.selectionSet.selections.length) {
632 throw require("./RelayCompilerError").createUserError("Expected no selections for scalar field '".concat(name, "'. Source: ").concat(this._getErrorContext()), null, [field]);
633 }
634
635 return {
636 kind: 'ScalarField',
637 alias: alias,
638 args: args,
639 directives: directives,
640 handles: handles,
641 loc: buildLocation(field.loc),
642 metadata: null,
643 name: name,
644 type: assertScalarFieldType(type)
645 };
646 } else {
647 var selections = field.selectionSet ? this._transformSelections(field.selectionSet, type) : null;
648
649 if (selections == null || selections.length === 0) {
650 throw require("./RelayCompilerError").createUserError("Expected at least one selection for non-scalar field '".concat(name, "' on type '").concat(String(type), "'. Source: ").concat(this._getErrorContext(), "."), null, [field]);
651 }
652
653 return {
654 kind: 'LinkedField',
655 alias: alias,
656 args: args,
657 directives: directives,
658 handles: handles,
659 loc: buildLocation(field.loc),
660 metadata: null,
661 name: name,
662 selections: selections,
663 type: type
664 };
665 }
666 };
667
668 _proto2._transformHandle = function _transformHandle(fieldName, fieldArgs, clientFieldDirectives) {
669 var _this7 = this;
670
671 var handles;
672 clientFieldDirectives.forEach(function (clientFieldDirective) {
673 var handleArgument = (clientFieldDirective.arguments || []).find(function (arg) {
674 return getName(arg) === CLIENT_FIELD_HANDLE;
675 });
676
677 if (handleArgument) {
678 var name = null;
679
680 var key = require("./DefaultHandleKey").DEFAULT_HANDLE_KEY;
681
682 var filters = null;
683 var maybeHandle = transformLiteralValue(handleArgument.value, handleArgument);
684
685 if (typeof maybeHandle !== 'string') {
686 throw require("./RelayCompilerError").createUserError("Expected a string literal argument for the @".concat(CLIENT_FIELD, " directive. ") + "Source: ".concat(_this7._getErrorContext()), null, [handleArgument.value]);
687 }
688
689 name = maybeHandle;
690 var keyArgument = (clientFieldDirective.arguments || []).find(function (arg) {
691 return getName(arg) === CLIENT_FIELD_KEY;
692 });
693
694 if (keyArgument) {
695 var maybeKey = transformLiteralValue(keyArgument.value, keyArgument);
696
697 if (typeof maybeKey !== 'string') {
698 throw require("./RelayCompilerError").createUserError("Expected a string literal argument for the @".concat(CLIENT_FIELD, " directive. ") + "Source: ".concat(_this7._getErrorContext()), null, [keyArgument.value]);
699 }
700
701 key = maybeKey;
702 }
703
704 var filtersArgument = (clientFieldDirective.arguments || []).find(function (arg) {
705 return getName(arg) === CLIENT_FIELD_FILTERS;
706 });
707
708 if (filtersArgument) {
709 var maybeFilters = transformLiteralValue(filtersArgument.value, filtersArgument);
710
711 if (!(Array.isArray(maybeFilters) && maybeFilters.every(function (filter) {
712 return typeof filter === 'string' && fieldArgs.some(function (fieldArg) {
713 return fieldArg.name === filter;
714 });
715 }))) {
716 throw require("./RelayCompilerError").createUserError("Expected an array of argument names on field '".concat(fieldName, "'. ") + "Source: ".concat(_this7._getErrorContext()), null, [filtersArgument.value]);
717 } // $FlowFixMe
718
719
720 filters = maybeFilters;
721 }
722
723 handles = handles || [];
724 handles.push({
725 name: name,
726 key: key,
727 filters: filters
728 });
729 }
730 });
731 return handles;
732 };
733
734 _proto2._transformDirectives = function _transformDirectives(directives) {
735 var _this8 = this;
736
737 return directives.map(function (directive) {
738 var name = getName(directive);
739
740 var directiveDef = _this8._schema.getDirective(name);
741
742 if (directiveDef == null) {
743 throw require("./RelayCompilerError").createUserError("Unknown directive '".concat(name, "'. Source: ").concat(_this8._getErrorContext()), null, [directive]);
744 }
745
746 var args = _this8._transformArguments(directive.arguments || [], directiveDef.args);
747
748 return {
749 kind: 'Directive',
750 loc: buildLocation(directive.loc),
751 metadata: null,
752 name: name,
753 args: args
754 };
755 });
756 };
757
758 _proto2._transformArguments = function _transformArguments(args, argumentDefinitions) {
759 var _this9 = this;
760
761 return args.map(function (arg) {
762 var argName = getName(arg);
763 var argDef = argumentDefinitions.find(function (def) {
764 return def.name === argName;
765 });
766
767 if (argDef == null) {
768 throw require("./RelayCompilerError").createUserError("Unknown argument '".concat(argName, "'. Source: ").concat(_this9._getErrorContext()), null, [arg]);
769 }
770
771 var value = _this9._transformValue(arg.value, argDef.type);
772
773 return {
774 kind: 'Argument',
775 loc: buildLocation(arg.loc),
776 metadata: null,
777 name: argName,
778 value: value,
779 type: argDef.type
780 };
781 });
782 };
783
784 _proto2._splitConditions = function _splitConditions(mixedDirectives) {
785 var _this10 = this;
786
787 var _partitionArray3 = partitionArray(mixedDirectives, function (directive) {
788 return directive.name === INCLUDE || directive.name === SKIP;
789 }),
790 conditionDirectives = _partitionArray3[0],
791 otherDirectives = _partitionArray3[1];
792
793 var conditions = conditionDirectives.map(function (directive) {
794 var passingValue = directive.name === INCLUDE;
795 var arg = directive.args[0];
796
797 if (arg == null || arg.name !== IF) {
798 throw require("./RelayCompilerError").createUserError("Expected an 'if' argument to @".concat(directive.name, ". Source: ").concat(_this10._getErrorContext()), [directive.loc]);
799 }
800
801 if (!(arg.value.kind === 'Variable' || arg.value.kind === 'Literal')) {
802 throw require("./RelayCompilerError").createUserError("Expected the 'if' argument to @".concat(directive.name, " to be a variable or literal. Source: ").concat(_this10._getErrorContext()), [directive.loc]);
803 }
804
805 return {
806 kind: 'Condition',
807 condition: arg.value,
808 loc: directive.loc,
809 metadata: null,
810 passingValue: passingValue,
811 selections: []
812 };
813 });
814 var sortedConditions = conditions.sort(function (a, b) {
815 if (a.condition.kind === 'Variable' && b.condition.kind === 'Variable') {
816 return a.condition.variableName < b.condition.variableName ? -1 : a.condition.variableName > b.condition.variableName ? 1 : 0;
817 } else {
818 // sort literals earlier, variables later
819 return a.condition.kind === 'Variable' ? 1 : b.condition.kind === 'Variable' ? -1 : 0;
820 }
821 });
822 return [sortedConditions, otherDirectives];
823 };
824
825 _proto2._transformVariable = function _transformVariable(ast, usedAsType) {
826 var variableName = getName(ast);
827
828 this._recordAndVerifyVariableReference(ast, variableName, usedAsType);
829
830 return {
831 kind: 'Variable',
832 loc: buildLocation(ast.loc),
833 metadata: null,
834 variableName: variableName,
835 type: usedAsType
836 };
837 };
838 /**
839 * Transforms and validates argument values according to the expected
840 * type.
841 */
842
843
844 _proto2._transformValue = function _transformValue(ast, type) {
845 if (ast.kind === 'Variable') {
846 // Special case variables since there is no value to parse
847 return this._transformVariable(ast, type);
848 } else if (ast.kind === 'NullValue') {
849 // Special case null literals since there is no value to parse
850 if (type instanceof require("graphql").GraphQLNonNull) {
851 throw require("./RelayCompilerError").createUserError("Expected a value matching type '".concat(String(type), "'."), null, [ast]);
852 }
853
854 return {
855 kind: 'Literal',
856 loc: buildLocation(ast.loc),
857 metadata: null,
858 value: null
859 };
860 } else {
861 return this._transformNonNullLiteral(ast, type);
862 }
863 };
864 /**
865 * Transforms and validates non-null literal (non-variable) values
866 * according to the expected type.
867 */
868
869
870 _proto2._transformNonNullLiteral = function _transformNonNullLiteral(ast, type) {
871 var _this11 = this;
872
873 // Transform the value based on the type without a non-null wrapper.
874 // Note that error messages should still use the original `type`
875 // since that accurately describes to the user what the expected
876 // type is (using nullableType would suggest that `null` is legal
877 // even when it may not be, for example).
878 var nullableType = require("./GraphQLSchemaUtils").getNullableType(type);
879
880 if (nullableType instanceof require("graphql").GraphQLList) {
881 if (ast.kind !== 'ListValue') {
882 // Parse singular (non-list) values flowing into a list type
883 // as scalars, ie without wrapping them in an array.
884 return this._transformValue(ast, nullableType.ofType);
885 }
886
887 var itemType = require("graphql").assertInputType(nullableType.ofType);
888
889 var literalList = [];
890 var items = [];
891 var areAllItemsScalar = true;
892 ast.values.forEach(function (item) {
893 var itemValue = _this11._transformValue(item, itemType);
894
895 if (itemValue.kind === 'Literal') {
896 literalList.push(itemValue.value);
897 }
898
899 items.push(itemValue);
900 areAllItemsScalar = areAllItemsScalar && itemValue.kind === 'Literal';
901 });
902
903 if (areAllItemsScalar) {
904 return {
905 kind: 'Literal',
906 loc: buildLocation(ast.loc),
907 metadata: null,
908 value: literalList
909 };
910 } else {
911 return {
912 kind: 'ListValue',
913 loc: buildLocation(ast.loc),
914 metadata: null,
915 items: items
916 };
917 }
918 } else if (nullableType instanceof require("graphql").GraphQLInputObjectType) {
919 var objectType = nullableType;
920
921 if (ast.kind !== 'ObjectValue') {
922 throw require("./RelayCompilerError").createUserError("Expected a value matching type '".concat(String(type), "'."), null, [ast]);
923 }
924
925 var literalObject = {};
926 var fields = [];
927 var areAllFieldsScalar = true;
928 ast.fields.forEach(function (field) {
929 var fieldName = getName(field);
930 var fieldConfig = objectType.getFields()[fieldName];
931
932 if (fieldConfig == null) {
933 throw require("./RelayCompilerError").createUserError("Uknown field '".concat(fieldName, "' on type '").concat(String(type), "'."), null, [field]);
934 }
935
936 var fieldType = require("graphql").assertInputType(fieldConfig.type);
937
938 var fieldValue = _this11._transformValue(field.value, fieldType);
939
940 if (fieldValue.kind === 'Literal') {
941 literalObject[field.name.value] = fieldValue.value;
942 }
943
944 fields.push({
945 kind: 'ObjectFieldValue',
946 loc: buildLocation(field.loc),
947 metadata: null,
948 name: fieldName,
949 value: fieldValue
950 });
951 areAllFieldsScalar = areAllFieldsScalar && fieldValue.kind === 'Literal';
952 });
953
954 if (areAllFieldsScalar) {
955 return {
956 kind: 'Literal',
957 loc: buildLocation(ast.loc),
958 metadata: null,
959 value: literalObject
960 };
961 } else {
962 return {
963 kind: 'ObjectValue',
964 loc: buildLocation(ast.loc),
965 metadata: null,
966 fields: fields
967 };
968 }
969 } else if (nullableType === require("graphql").GraphQLID) {
970 // GraphQLID's parseLiteral() always returns the string value. However
971 // the int/string distinction may be important at runtime, so this
972 // transform parses int/string literals into the corresponding JS types.
973 if (ast.kind === 'IntValue') {
974 return {
975 kind: 'Literal',
976 loc: buildLocation(ast.loc),
977 metadata: null,
978 value: parseInt(ast.value, 10)
979 };
980 } else if (ast.kind === 'StringValue') {
981 return {
982 kind: 'Literal',
983 loc: buildLocation(ast.loc),
984 metadata: null,
985 value: ast.value
986 };
987 } else {
988 throw require("./RelayCompilerError").createUserError("Invalid value, expected a value matching type '".concat(String(type), "'."), null, [ast]);
989 }
990 } else if (nullableType instanceof require("graphql").GraphQLScalarType || nullableType instanceof require("graphql").GraphQLEnumType) {
991 var _value2 = nullableType.parseLiteral(ast);
992
993 if (_value2 == null) {
994 // parseLiteral() should return a non-null JavaScript value
995 // if the ast value is valid for the type.
996 throw require("./RelayCompilerError").createUserError("Expected a value matching type '".concat(String(type), "'."), null, [ast]);
997 }
998
999 return {
1000 kind: 'Literal',
1001 loc: buildLocation(ast.loc),
1002 metadata: null,
1003 value: _value2
1004 };
1005 } else {
1006 nullableType;
1007 throw require("./RelayCompilerError").createCompilerError("Unsupported type '".concat(String(type), "' for input value, expected a GraphQLList, ") + 'GraphQLInputObjectType, GraphQLEnumType, or GraphQLScalarType.', null, [ast]);
1008 }
1009 };
1010
1011 return GraphQLDefinitionParser;
1012}();
1013/**
1014 * @private
1015 */
1016
1017
1018function transformLiteralValue(ast, context) {
1019 switch (ast.kind) {
1020 case 'IntValue':
1021 return parseInt(ast.value, 10);
1022
1023 case 'FloatValue':
1024 return parseFloat(ast.value);
1025
1026 case 'StringValue':
1027 return ast.value;
1028
1029 case 'BooleanValue':
1030 // Note: duplicated because Flow does not understand fall-through cases
1031 return ast.value;
1032
1033 case 'EnumValue':
1034 // Note: duplicated because Flow does not understand fall-through cases
1035 return ast.value;
1036
1037 case 'ListValue':
1038 return ast.values.map(function (item) {
1039 return transformLiteralValue(item, context);
1040 });
1041
1042 case 'NullValue':
1043 return null;
1044
1045 case 'ObjectValue':
1046 {
1047 var objectValue = {};
1048 ast.fields.forEach(function (field) {
1049 var fieldName = getName(field);
1050 var value = transformLiteralValue(field.value, context);
1051 objectValue[fieldName] = value;
1052 });
1053 return objectValue;
1054 }
1055
1056 case 'Variable':
1057 throw require("./RelayCompilerError").createUserError('Unexpected variable where a literal (static) value is required.', null, [ast, context]);
1058
1059 default:
1060 ast.kind;
1061 throw require("./RelayCompilerError").createCompilerError("Unknown ast kind '".concat(ast.kind, "'."), [ast]);
1062 }
1063}
1064/**
1065 * @private
1066 */
1067
1068
1069function buildArgumentDefinitions(variables) {
1070 return Array.from(variables.values(), function (_ref4) {
1071 var ast = _ref4.ast,
1072 name = _ref4.name,
1073 type = _ref4.type,
1074 defaultValue = _ref4.defaultValue;
1075 return {
1076 kind: 'LocalArgumentDefinition',
1077 loc: buildLocation(ast.loc),
1078 metadata: null,
1079 name: name,
1080 type: type,
1081 defaultValue: defaultValue
1082 };
1083 });
1084}
1085/**
1086 * @private
1087 */
1088
1089
1090function buildLocation(loc) {
1091 if (loc == null) {
1092 return {
1093 kind: 'Unknown'
1094 };
1095 }
1096
1097 return {
1098 kind: 'Source',
1099 start: loc.start,
1100 end: loc.end,
1101 source: loc.source
1102 };
1103}
1104/**
1105 * @private
1106 */
1107
1108
1109function isScalarFieldType(type) {
1110 var namedType = require("graphql").getNamedType(type);
1111
1112 return namedType instanceof require("graphql").GraphQLScalarType || namedType instanceof require("graphql").GraphQLEnumType;
1113}
1114/**
1115 * @private
1116 */
1117
1118
1119function assertScalarFieldType(type) {
1120 if (!isScalarFieldType(type)) {
1121 throw require("./RelayCompilerError").createUserError("Expected a scalar field type, got type '".concat(String(type), "'."));
1122 }
1123
1124 return type;
1125}
1126/**
1127 * @private
1128 */
1129
1130
1131function applyConditions(conditions, selections) {
1132 var nextSelections = selections;
1133 conditions.forEach(function (condition) {
1134 nextSelections = [(0, _objectSpread2["default"])({}, condition, {
1135 selections: nextSelections
1136 })];
1137 });
1138 return nextSelections;
1139}
1140/**
1141 * @private
1142 */
1143
1144
1145function getName(ast) {
1146 var _ast$name;
1147
1148 var name = (_ast$name = ast.name) === null || _ast$name === void 0 ? void 0 : _ast$name.value;
1149
1150 if (typeof name !== 'string') {
1151 throw require("./RelayCompilerError").createCompilerError("Expected ast node to have a 'name'.", null, [ast]);
1152 }
1153
1154 return name;
1155}
1156/**
1157 * Partitions an array given a predicate. All elements satisfying the predicate
1158 * are part of the first returned array, and all elements that don't are in the
1159 * second.
1160 *
1161 * @private
1162 */
1163
1164
1165function partitionArray(array, predicate) {
1166 var first = [];
1167 var second = [];
1168
1169 for (var i = 0; i < array.length; i++) {
1170 var item = array[i];
1171
1172 if (predicate(item)) {
1173 first.push(item);
1174 } else {
1175 second.push(item);
1176 }
1177 }
1178
1179 return [first, second];
1180}
1181
1182module.exports = {
1183 parse: parse,
1184 transform: transform
1185};
\No newline at end of file