UNPKG

4.67 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 * strict-local
8 * @format
9 */
10'use strict';
11
12/**
13 * Creates a scope for a `Root`, with each argument mapped to a variable of the
14 * same name. Example:
15 *
16 * Query:
17 * query Foo($id: ID, $size: Int = 42) { ... }
18 *
19 * Scope:
20 * {
21 * id: $id,
22 * size: $size,
23 * }
24 *
25 * Note that even though a default value is defined for $size, the scope must
26 * assume that this could be overridden at runtime. The value cannot be decided
27 * statically and therefore is set to a variable.
28 */
29function getRootScope(definitions) {
30 var scope = {};
31 definitions.forEach(function (definition) {
32 scope[definition.name] = {
33 kind: 'Variable',
34 metadata: null,
35 variableName: definition.name,
36 type: definition.type
37 };
38 });
39 return scope;
40}
41/**
42 * Creates a scope for a `Fragment` by translating fragment spread arguments in
43 * the context of a parent scope into a new scope and validating them against
44 * the argument definitions.
45 *
46 *
47 * Parent Scope:
48 * {
49 * active: $parentActive
50 * }
51 *
52 * Fragment Spread:
53 * ...Bar(size: 42, enabled: $active)
54 *
55 * Fragment:
56 * fragment Bar on Foo @argumentDefinitions(
57 * id: {type: "ID"}
58 * size: {type: "Int"}
59 * enabled: {type: "Boolean}
60 * scale: {type: "Int", imports: "pixelRatio"}
61 * )
62 *
63 * Scope:
64 * {
65 * // No argument is provided for $id, it gets the default value which in this
66 * // case is `null`:
67 * id: null,
68 *
69 * // The parent passes 42 as a literal value for $size:
70 * size: 42,
71 *
72 * // The parent passes a variable as the value of $enabled. This variable is
73 * // resolved in the parent scope to the value $parentActive, which becomes
74 * // the value of $enabled:
75 * $enabled: $parentActive,
76 *
77 * // $scale imports pixelRatio from the root scope. Since any argument in a
78 * // root scope maps to a variable of the same name, that means the value of
79 * // pixelRatio in the root is $pixelRatio:
80 * $scale: $pixelRatio,
81 * }
82 */
83
84
85function getFragmentScope(definitions, args, parentScope, spread) {
86 var argMap = new Map();
87 args.forEach(function (arg) {
88 if (arg.value.kind === 'Literal') {
89 argMap.set(arg.name, arg.value);
90 } else if (arg.value.kind === 'Variable') {
91 argMap.set(arg.name, parentScope[arg.value.variableName]);
92 }
93 });
94 var fragmentScope = {};
95
96 var errors = require("./RelayCompilerError").eachWithErrors(definitions, function (definition) {
97 if (definition.kind === 'RootArgumentDefinition') {
98 if (argMap.has(definition.name)) {
99 var _ref;
100
101 var argNode = args.find(function (a) {
102 return a.name === definition.name;
103 });
104 throw require("./RelayCompilerError").createUserError("Unexpected argument '".concat(definition.name, "' supplied to fragment '").concat(spread.name, "'. @arguments may only be provided for variables defined in the fragment's @argumentDefinitions."), [(_ref = argNode === null || argNode === void 0 ? void 0 : argNode.loc) !== null && _ref !== void 0 ? _ref : spread.loc]);
105 }
106
107 fragmentScope[definition.name] = {
108 kind: 'Variable',
109 metadata: null,
110 variableName: definition.name,
111 type: definition.type
112 };
113 } else {
114 var arg = argMap.get(definition.name);
115
116 if (arg == null || arg.kind === 'Literal' && arg.value == null) {
117 // No variable or literal null was passed, fall back to default
118 // value.
119 if (definition.defaultValue == null && definition.type instanceof require("graphql").GraphQLNonNull) {
120 var _ref2;
121
122 var _argNode = args.find(function (a) {
123 return a.name === definition.name;
124 });
125
126 throw require("./RelayCompilerError").createUserError("No value found for required argument '".concat(definition.name, ": ").concat(String(definition.type), "' on fragment '").concat(spread.name, "'."), [(_ref2 = _argNode === null || _argNode === void 0 ? void 0 : _argNode.loc) !== null && _ref2 !== void 0 ? _ref2 : spread.loc]);
127 }
128
129 fragmentScope[definition.name] = {
130 kind: 'Literal',
131 value: definition.defaultValue
132 };
133 } else {
134 // Variable or non-null literal.
135 fragmentScope[definition.name] = arg;
136 }
137 }
138 });
139
140 if (errors != null && errors.length) {
141 throw require("./RelayCompilerError").createCombinedError(errors);
142 }
143
144 return fragmentScope;
145}
146
147module.exports = {
148 getFragmentScope: getFragmentScope,
149 getRootScope: getRootScope
150};
\No newline at end of file