UNPKG

9.7 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.TypeInfo = void 0;
7
8var _find = _interopRequireDefault(require("../polyfills/find"));
9
10var _kinds = require("../language/kinds");
11
12var _definition = require("../type/definition");
13
14var _introspection = require("../type/introspection");
15
16var _typeFromAST = require("./typeFromAST");
17
18function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
19
20/**
21 * TypeInfo is a utility class which, given a GraphQL schema, can keep track
22 * of the current field and type definitions at any point in a GraphQL document
23 * AST during a recursive descent by calling `enter(node)` and `leave(node)`.
24 */
25var TypeInfo =
26/*#__PURE__*/
27function () {
28 function TypeInfo(schema, // NOTE: this experimental optional second parameter is only needed in order
29 // to support non-spec-compliant codebases. You should never need to use it.
30 // It may disappear in the future.
31 getFieldDefFn, // Initial type may be provided in rare cases to facilitate traversals
32 // beginning somewhere other than documents.
33 initialType) {
34 this._schema = schema;
35 this._typeStack = [];
36 this._parentTypeStack = [];
37 this._inputTypeStack = [];
38 this._fieldDefStack = [];
39 this._defaultValueStack = [];
40 this._directive = null;
41 this._argument = null;
42 this._enumValue = null;
43 this._getFieldDef = getFieldDefFn || getFieldDef;
44
45 if (initialType) {
46 if ((0, _definition.isInputType)(initialType)) {
47 this._inputTypeStack.push(initialType);
48 }
49
50 if ((0, _definition.isCompositeType)(initialType)) {
51 this._parentTypeStack.push(initialType);
52 }
53
54 if ((0, _definition.isOutputType)(initialType)) {
55 this._typeStack.push(initialType);
56 }
57 }
58 }
59
60 var _proto = TypeInfo.prototype;
61
62 _proto.getType = function getType() {
63 if (this._typeStack.length > 0) {
64 return this._typeStack[this._typeStack.length - 1];
65 }
66 };
67
68 _proto.getParentType = function getParentType() {
69 if (this._parentTypeStack.length > 0) {
70 return this._parentTypeStack[this._parentTypeStack.length - 1];
71 }
72 };
73
74 _proto.getInputType = function getInputType() {
75 if (this._inputTypeStack.length > 0) {
76 return this._inputTypeStack[this._inputTypeStack.length - 1];
77 }
78 };
79
80 _proto.getParentInputType = function getParentInputType() {
81 if (this._inputTypeStack.length > 1) {
82 return this._inputTypeStack[this._inputTypeStack.length - 2];
83 }
84 };
85
86 _proto.getFieldDef = function getFieldDef() {
87 if (this._fieldDefStack.length > 0) {
88 return this._fieldDefStack[this._fieldDefStack.length - 1];
89 }
90 };
91
92 _proto.getDefaultValue = function getDefaultValue() {
93 if (this._defaultValueStack.length > 0) {
94 return this._defaultValueStack[this._defaultValueStack.length - 1];
95 }
96 };
97
98 _proto.getDirective = function getDirective() {
99 return this._directive;
100 };
101
102 _proto.getArgument = function getArgument() {
103 return this._argument;
104 };
105
106 _proto.getEnumValue = function getEnumValue() {
107 return this._enumValue;
108 };
109
110 _proto.enter = function enter(node) {
111 var schema = this._schema; // Note: many of the types below are explicitly typed as "mixed" to drop
112 // any assumptions of a valid schema to ensure runtime types are properly
113 // checked before continuing since TypeInfo is used as part of validation
114 // which occurs before guarantees of schema and document validity.
115
116 switch (node.kind) {
117 case _kinds.Kind.SELECTION_SET:
118 {
119 var namedType = (0, _definition.getNamedType)(this.getType());
120
121 this._parentTypeStack.push((0, _definition.isCompositeType)(namedType) ? namedType : undefined);
122
123 break;
124 }
125
126 case _kinds.Kind.FIELD:
127 {
128 var parentType = this.getParentType();
129 var fieldDef;
130 var fieldType;
131
132 if (parentType) {
133 fieldDef = this._getFieldDef(schema, parentType, node);
134
135 if (fieldDef) {
136 fieldType = fieldDef.type;
137 }
138 }
139
140 this._fieldDefStack.push(fieldDef);
141
142 this._typeStack.push((0, _definition.isOutputType)(fieldType) ? fieldType : undefined);
143
144 break;
145 }
146
147 case _kinds.Kind.DIRECTIVE:
148 this._directive = schema.getDirective(node.name.value);
149 break;
150
151 case _kinds.Kind.OPERATION_DEFINITION:
152 {
153 var type;
154
155 if (node.operation === 'query') {
156 type = schema.getQueryType();
157 } else if (node.operation === 'mutation') {
158 type = schema.getMutationType();
159 } else if (node.operation === 'subscription') {
160 type = schema.getSubscriptionType();
161 }
162
163 this._typeStack.push((0, _definition.isObjectType)(type) ? type : undefined);
164
165 break;
166 }
167
168 case _kinds.Kind.INLINE_FRAGMENT:
169 case _kinds.Kind.FRAGMENT_DEFINITION:
170 {
171 var typeConditionAST = node.typeCondition;
172 var outputType = typeConditionAST ? (0, _typeFromAST.typeFromAST)(schema, typeConditionAST) : (0, _definition.getNamedType)(this.getType());
173
174 this._typeStack.push((0, _definition.isOutputType)(outputType) ? outputType : undefined);
175
176 break;
177 }
178
179 case _kinds.Kind.VARIABLE_DEFINITION:
180 {
181 var inputType = (0, _typeFromAST.typeFromAST)(schema, node.type);
182
183 this._inputTypeStack.push((0, _definition.isInputType)(inputType) ? inputType : undefined);
184
185 break;
186 }
187
188 case _kinds.Kind.ARGUMENT:
189 {
190 var argDef;
191 var argType;
192 var fieldOrDirective = this.getDirective() || this.getFieldDef();
193
194 if (fieldOrDirective) {
195 argDef = (0, _find.default)(fieldOrDirective.args, function (arg) {
196 return arg.name === node.name.value;
197 });
198
199 if (argDef) {
200 argType = argDef.type;
201 }
202 }
203
204 this._argument = argDef;
205
206 this._defaultValueStack.push(argDef ? argDef.defaultValue : undefined);
207
208 this._inputTypeStack.push((0, _definition.isInputType)(argType) ? argType : undefined);
209
210 break;
211 }
212
213 case _kinds.Kind.LIST:
214 {
215 var listType = (0, _definition.getNullableType)(this.getInputType());
216 var itemType = (0, _definition.isListType)(listType) ? listType.ofType : listType; // List positions never have a default value.
217
218 this._defaultValueStack.push(undefined);
219
220 this._inputTypeStack.push((0, _definition.isInputType)(itemType) ? itemType : undefined);
221
222 break;
223 }
224
225 case _kinds.Kind.OBJECT_FIELD:
226 {
227 var objectType = (0, _definition.getNamedType)(this.getInputType());
228 var inputFieldType;
229 var inputField;
230
231 if ((0, _definition.isInputObjectType)(objectType)) {
232 inputField = objectType.getFields()[node.name.value];
233
234 if (inputField) {
235 inputFieldType = inputField.type;
236 }
237 }
238
239 this._defaultValueStack.push(inputField ? inputField.defaultValue : undefined);
240
241 this._inputTypeStack.push((0, _definition.isInputType)(inputFieldType) ? inputFieldType : undefined);
242
243 break;
244 }
245
246 case _kinds.Kind.ENUM:
247 {
248 var enumType = (0, _definition.getNamedType)(this.getInputType());
249 var enumValue;
250
251 if ((0, _definition.isEnumType)(enumType)) {
252 enumValue = enumType.getValue(node.value);
253 }
254
255 this._enumValue = enumValue;
256 break;
257 }
258 }
259 };
260
261 _proto.leave = function leave(node) {
262 switch (node.kind) {
263 case _kinds.Kind.SELECTION_SET:
264 this._parentTypeStack.pop();
265
266 break;
267
268 case _kinds.Kind.FIELD:
269 this._fieldDefStack.pop();
270
271 this._typeStack.pop();
272
273 break;
274
275 case _kinds.Kind.DIRECTIVE:
276 this._directive = null;
277 break;
278
279 case _kinds.Kind.OPERATION_DEFINITION:
280 case _kinds.Kind.INLINE_FRAGMENT:
281 case _kinds.Kind.FRAGMENT_DEFINITION:
282 this._typeStack.pop();
283
284 break;
285
286 case _kinds.Kind.VARIABLE_DEFINITION:
287 this._inputTypeStack.pop();
288
289 break;
290
291 case _kinds.Kind.ARGUMENT:
292 this._argument = null;
293
294 this._defaultValueStack.pop();
295
296 this._inputTypeStack.pop();
297
298 break;
299
300 case _kinds.Kind.LIST:
301 case _kinds.Kind.OBJECT_FIELD:
302 this._defaultValueStack.pop();
303
304 this._inputTypeStack.pop();
305
306 break;
307
308 case _kinds.Kind.ENUM:
309 this._enumValue = null;
310 break;
311 }
312 };
313
314 return TypeInfo;
315}();
316/**
317 * Not exactly the same as the executor's definition of getFieldDef, in this
318 * statically evaluated environment we do not always have an Object type,
319 * and need to handle Interface and Union types.
320 */
321
322
323exports.TypeInfo = TypeInfo;
324
325function getFieldDef(schema, parentType, fieldNode) {
326 var name = fieldNode.name.value;
327
328 if (name === _introspection.SchemaMetaFieldDef.name && schema.getQueryType() === parentType) {
329 return _introspection.SchemaMetaFieldDef;
330 }
331
332 if (name === _introspection.TypeMetaFieldDef.name && schema.getQueryType() === parentType) {
333 return _introspection.TypeMetaFieldDef;
334 }
335
336 if (name === _introspection.TypeNameMetaFieldDef.name && (0, _definition.isCompositeType)(parentType)) {
337 return _introspection.TypeNameMetaFieldDef;
338 }
339
340 if ((0, _definition.isObjectType)(parentType) || (0, _definition.isInterfaceType)(parentType)) {
341 return parentType.getFields()[name];
342 }
343}