1 | var __extends = (this && this.__extends) || (function () {
|
2 | var extendStatics = function (d, b) {
|
3 | extendStatics = Object.setPrototypeOf ||
|
4 | ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
5 | function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
6 | return extendStatics(d, b);
|
7 | };
|
8 | return function (d, b) {
|
9 | extendStatics(d, b);
|
10 | function __() { this.constructor = d; }
|
11 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
12 | };
|
13 | })();
|
14 | var __spreadArrays = (this && this.__spreadArrays) || function () {
|
15 | for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
|
16 | for (var r = Array(s), k = 0, i = 0; i < il; i++)
|
17 | for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
|
18 | r[k] = a[j];
|
19 | return r;
|
20 | };
|
21 | Object.defineProperty(exports, "__esModule", { value: true });
|
22 | var graphql_1 = require("graphql");
|
23 | var values_1 = require("graphql/execution/values");
|
24 | var hasOwn = Object.prototype.hasOwnProperty;
|
25 | // Abstract base class of any visitor implementation, defining the available
|
26 | // visitor methods along with their parameter types, and providing a static
|
27 | // helper function for determining whether a subclass implements a given
|
28 | // visitor method, as opposed to inheriting one of the stubs defined here.
|
29 | var SchemaVisitor = /** @class */ (function () {
|
30 | function SchemaVisitor() {
|
31 | }
|
32 | // Determine if this SchemaVisitor (sub)class implements a particular
|
33 | // visitor method.
|
34 | SchemaVisitor.implementsVisitorMethod = function (methodName) {
|
35 | if (!methodName.startsWith('visit')) {
|
36 | return false;
|
37 | }
|
38 | var method = this.prototype[methodName];
|
39 | if (typeof method !== 'function') {
|
40 | return false;
|
41 | }
|
42 | if (this === SchemaVisitor) {
|
43 | // The SchemaVisitor class implements every visitor method.
|
44 | return true;
|
45 | }
|
46 | var stub = SchemaVisitor.prototype[methodName];
|
47 | if (method === stub) {
|
48 | // If this.prototype[methodName] was just inherited from SchemaVisitor,
|
49 | // then this class does not really implement the method.
|
50 | return false;
|
51 | }
|
52 | return true;
|
53 | };
|
54 | // Concrete subclasses of SchemaVisitor should override one or more of these
|
55 | // visitor methods, in order to express their interest in handling certain
|
56 | // schema types/locations. Each method may return null to remove the given
|
57 | // type from the schema, a non-null value of the same type to update the
|
58 | // type in the schema, or nothing to leave the type as it was.
|
59 | /* tslint:disable:no-empty */
|
60 | SchemaVisitor.prototype.visitSchema = function (schema) { };
|
61 | SchemaVisitor.prototype.visitScalar = function (scalar) { };
|
62 | SchemaVisitor.prototype.visitObject = function (object) { };
|
63 | SchemaVisitor.prototype.visitFieldDefinition = function (field, details) { };
|
64 | SchemaVisitor.prototype.visitArgumentDefinition = function (argument, details) { };
|
65 | SchemaVisitor.prototype.visitInterface = function (iface) { };
|
66 | SchemaVisitor.prototype.visitUnion = function (union) { };
|
67 | SchemaVisitor.prototype.visitEnum = function (type) { };
|
68 | SchemaVisitor.prototype.visitEnumValue = function (value, details) { };
|
69 | SchemaVisitor.prototype.visitInputObject = function (object) { };
|
70 | SchemaVisitor.prototype.visitInputFieldDefinition = function (field, details) { };
|
71 | return SchemaVisitor;
|
72 | }());
|
73 | exports.SchemaVisitor = SchemaVisitor;
|
74 | // Generic function for visiting GraphQLSchema objects.
|
75 | function visitSchema(schema,
|
76 | // To accommodate as many different visitor patterns as possible, the
|
77 | // visitSchema function does not simply accept a single instance of the
|
78 | // SchemaVisitor class, but instead accepts a function that takes the
|
79 | // current VisitableSchemaType object and the name of a visitor method and
|
80 | // returns an array of SchemaVisitor instances that implement the visitor
|
81 | // method and have an interest in handling the given VisitableSchemaType
|
82 | // object. In the simplest case, this function can always return an array
|
83 | // containing a single visitor object, without even looking at the type or
|
84 | // methodName parameters. In other cases, this function might sometimes
|
85 | // return an empty array to indicate there are no visitors that should be
|
86 | // applied to the given VisitableSchemaType object. For an example of a
|
87 | // visitor pattern that benefits from this abstraction, see the
|
88 | // SchemaDirectiveVisitor class below.
|
89 | visitorSelector) {
|
90 | // Helper function that calls visitorSelector and applies the resulting
|
91 | // visitors to the given type, with arguments [type, ...args].
|
92 | function callMethod(methodName, type) {
|
93 | var args = [];
|
94 | for (var _i = 2; _i < arguments.length; _i++) {
|
95 | args[_i - 2] = arguments[_i];
|
96 | }
|
97 | visitorSelector(type, methodName).every(function (visitor) {
|
98 | var newType = visitor[methodName].apply(visitor, __spreadArrays([type], args));
|
99 | if (typeof newType === 'undefined') {
|
100 | // Keep going without modifying type.
|
101 | return true;
|
102 | }
|
103 | if (methodName === 'visitSchema' ||
|
104 | type instanceof graphql_1.GraphQLSchema) {
|
105 | throw new Error("Method " + methodName + " cannot replace schema with " + newType);
|
106 | }
|
107 | if (newType === null) {
|
108 | // Stop the loop and return null form callMethod, which will cause
|
109 | // the type to be removed from the schema.
|
110 | type = null;
|
111 | return false;
|
112 | }
|
113 | // Update type to the new type returned by the visitor method, so that
|
114 | // later directives will see the new type, and callMethod will return
|
115 | // the final type.
|
116 | type = newType;
|
117 | return true;
|
118 | });
|
119 | // If there were no directives for this type object, or if all visitor
|
120 | // methods returned nothing, type will be returned unmodified.
|
121 | return type;
|
122 | }
|
123 | // Recursive helper function that calls any appropriate visitor methods for
|
124 | // each object in the schema, then traverses the object's children (if any).
|
125 | function visit(type) {
|
126 | if (type instanceof graphql_1.GraphQLSchema) {
|
127 | // Unlike the other types, the root GraphQLSchema object cannot be
|
128 | // replaced by visitor methods, because that would make life very hard
|
129 | // for SchemaVisitor subclasses that rely on the original schema object.
|
130 | callMethod('visitSchema', type);
|
131 | updateEachKey(type.getTypeMap(), function (namedType, typeName) {
|
132 | if (!typeName.startsWith('__')) {
|
133 | // Call visit recursively to let it determine which concrete
|
134 | // subclass of GraphQLNamedType we found in the type map. Because
|
135 | // we're using updateEachKey, the result of visit(namedType) may
|
136 | // cause the type to be removed or replaced.
|
137 | return visit(namedType);
|
138 | }
|
139 | });
|
140 | return type;
|
141 | }
|
142 | if (type instanceof graphql_1.GraphQLObjectType) {
|
143 | // Note that callMethod('visitObject', type) may not actually call any
|
144 | // methods, if there are no @directive annotations associated with this
|
145 | // type, or if this SchemaDirectiveVisitor subclass does not override
|
146 | // the visitObject method.
|
147 | var newObject = callMethod('visitObject', type);
|
148 | if (newObject) {
|
149 | visitFields(newObject);
|
150 | }
|
151 | return newObject;
|
152 | }
|
153 | if (type instanceof graphql_1.GraphQLInterfaceType) {
|
154 | var newInterface = callMethod('visitInterface', type);
|
155 | if (newInterface) {
|
156 | visitFields(newInterface);
|
157 | }
|
158 | return newInterface;
|
159 | }
|
160 | if (type instanceof graphql_1.GraphQLInputObjectType) {
|
161 | var newInputObject_1 = callMethod('visitInputObject', type);
|
162 | if (newInputObject_1) {
|
163 | updateEachKey(newInputObject_1.getFields(), function (field) {
|
164 | // Since we call a different method for input object fields, we
|
165 | // can't reuse the visitFields function here.
|
166 | return callMethod('visitInputFieldDefinition', field, {
|
167 | objectType: newInputObject_1,
|
168 | });
|
169 | });
|
170 | }
|
171 | return newInputObject_1;
|
172 | }
|
173 | if (type instanceof graphql_1.GraphQLScalarType) {
|
174 | return callMethod('visitScalar', type);
|
175 | }
|
176 | if (type instanceof graphql_1.GraphQLUnionType) {
|
177 | return callMethod('visitUnion', type);
|
178 | }
|
179 | if (type instanceof graphql_1.GraphQLEnumType) {
|
180 | var newEnum_1 = callMethod('visitEnum', type);
|
181 | if (newEnum_1) {
|
182 | updateEachKey(newEnum_1.getValues(), function (value) {
|
183 | return callMethod('visitEnumValue', value, {
|
184 | enumType: newEnum_1,
|
185 | });
|
186 | });
|
187 | }
|
188 | return newEnum_1;
|
189 | }
|
190 | throw new Error("Unexpected schema type: " + type);
|
191 | }
|
192 | function visitFields(type) {
|
193 | updateEachKey(type.getFields(), function (field) {
|
194 | // It would be nice if we could call visit(field) recursively here, but
|
195 | // GraphQLField is merely a type, not a value that can be detected using
|
196 | // an instanceof check, so we have to visit the fields in this lexical
|
197 | // context, so that TypeScript can validate the call to
|
198 | // visitFieldDefinition.
|
199 | var newField = callMethod('visitFieldDefinition', field, {
|
200 | // While any field visitor needs a reference to the field object, some
|
201 | // field visitors may also need to know the enclosing (parent) type,
|
202 | // perhaps to determine if the parent is a GraphQLObjectType or a
|
203 | // GraphQLInterfaceType. To obtain a reference to the parent, a
|
204 | // visitor method can have a second parameter, which will be an object
|
205 | // with an .objectType property referring to the parent.
|
206 | objectType: type,
|
207 | });
|
208 | if (newField && newField.args) {
|
209 | updateEachKey(newField.args, function (arg) {
|
210 | return callMethod('visitArgumentDefinition', arg, {
|
211 | // Like visitFieldDefinition, visitArgumentDefinition takes a
|
212 | // second parameter that provides additional context, namely the
|
213 | // parent .field and grandparent .objectType. Remember that the
|
214 | // current GraphQLSchema is always available via this.schema.
|
215 | field: newField,
|
216 | objectType: type,
|
217 | });
|
218 | });
|
219 | }
|
220 | return newField;
|
221 | });
|
222 | }
|
223 | visit(schema);
|
224 | // Return the original schema for convenience, even though it cannot have
|
225 | // been replaced or removed by the code above.
|
226 | return schema;
|
227 | }
|
228 | exports.visitSchema = visitSchema;
|
229 | // Update any references to named schema types that disagree with the named
|
230 | // types found in schema.getTypeMap().
|
231 | function healSchema(schema) {
|
232 | heal(schema);
|
233 | return schema;
|
234 | function heal(type) {
|
235 | if (type instanceof graphql_1.GraphQLSchema) {
|
236 | var originalTypeMap_1 = type.getTypeMap();
|
237 | var actualNamedTypeMap_1 = Object.create(null);
|
238 | // If any of the .name properties of the GraphQLNamedType objects in
|
239 | // schema.getTypeMap() have changed, the keys of the type map need to
|
240 | // be updated accordingly.
|
241 | each(originalTypeMap_1, function (namedType, typeName) {
|
242 | if (typeName.startsWith('__')) {
|
243 | return;
|
244 | }
|
245 | var actualName = namedType.name;
|
246 | if (actualName.startsWith('__')) {
|
247 | return;
|
248 | }
|
249 | if (hasOwn.call(actualNamedTypeMap_1, actualName)) {
|
250 | throw new Error("Duplicate schema type name " + actualName);
|
251 | }
|
252 | actualNamedTypeMap_1[actualName] = namedType;
|
253 | // Note: we are deliberately leaving namedType in the schema by its
|
254 | // original name (which might be different from actualName), so that
|
255 | // references by that name can be healed.
|
256 | });
|
257 | // Now add back every named type by its actual name.
|
258 | each(actualNamedTypeMap_1, function (namedType, typeName) {
|
259 | originalTypeMap_1[typeName] = namedType;
|
260 | });
|
261 | // Directive declaration argument types can refer to named types.
|
262 | each(type.getDirectives(), function (decl) {
|
263 | if (decl.args) {
|
264 | each(decl.args, function (arg) {
|
265 | arg.type = healType(arg.type);
|
266 | });
|
267 | }
|
268 | });
|
269 | each(originalTypeMap_1, function (namedType, typeName) {
|
270 | if (!typeName.startsWith('__')) {
|
271 | heal(namedType);
|
272 | }
|
273 | });
|
274 | updateEachKey(originalTypeMap_1, function (namedType, typeName) {
|
275 | // Dangling references to renamed types should remain in the schema
|
276 | // during healing, but must be removed now, so that the following
|
277 | // invariant holds for all names: schema.getType(name).name === name
|
278 | if (!typeName.startsWith('__') &&
|
279 | !hasOwn.call(actualNamedTypeMap_1, typeName)) {
|
280 | return null;
|
281 | }
|
282 | });
|
283 | }
|
284 | else if (type instanceof graphql_1.GraphQLObjectType) {
|
285 | healFields(type);
|
286 | each(type.getInterfaces(), function (iface) { return heal(iface); });
|
287 | }
|
288 | else if (type instanceof graphql_1.GraphQLInterfaceType) {
|
289 | healFields(type);
|
290 | }
|
291 | else if (type instanceof graphql_1.GraphQLInputObjectType) {
|
292 | each(type.getFields(), function (field) {
|
293 | field.type = healType(field.type);
|
294 | });
|
295 | }
|
296 | else if (type instanceof graphql_1.GraphQLScalarType) {
|
297 | // Nothing to do.
|
298 | }
|
299 | else if (type instanceof graphql_1.GraphQLUnionType) {
|
300 | updateEachKey(type.getTypes(), function (t) { return healType(t); });
|
301 | }
|
302 | else if (type instanceof graphql_1.GraphQLEnumType) {
|
303 | // Nothing to do.
|
304 | }
|
305 | else {
|
306 | throw new Error("Unexpected schema type: " + type);
|
307 | }
|
308 | }
|
309 | function healFields(type) {
|
310 | each(type.getFields(), function (field) {
|
311 | field.type = healType(field.type);
|
312 | if (field.args) {
|
313 | each(field.args, function (arg) {
|
314 | arg.type = healType(arg.type);
|
315 | });
|
316 | }
|
317 | });
|
318 | }
|
319 | function healType(type) {
|
320 | // Unwrap the two known wrapper types
|
321 | if (type instanceof graphql_1.GraphQLList) {
|
322 | type = new graphql_1.GraphQLList(healType(type.ofType));
|
323 | }
|
324 | else if (type instanceof graphql_1.GraphQLNonNull) {
|
325 | type = new graphql_1.GraphQLNonNull(healType(type.ofType));
|
326 | }
|
327 | else if (graphql_1.isNamedType(type)) {
|
328 | // If a type annotation on a field or an argument or a union member is
|
329 | // any `GraphQLNamedType` with a `name`, then it must end up identical
|
330 | // to `schema.getType(name)`, since `schema.getTypeMap()` is the source
|
331 | // of truth for all named schema types.
|
332 | var namedType = type;
|
333 | var officialType = schema.getType(namedType.name);
|
334 | if (officialType && namedType !== officialType) {
|
335 | return officialType;
|
336 | }
|
337 | }
|
338 | return type;
|
339 | }
|
340 | }
|
341 | exports.healSchema = healSchema;
|
342 | // This class represents a reusable implementation of a @directive that may
|
343 | // appear in a GraphQL schema written in Schema Definition Language.
|
344 | //
|
345 | // By overriding one or more visit{Object,Union,...} methods, a subclass
|
346 | // registers interest in certain schema types, such as GraphQLObjectType,
|
347 | // GraphQLUnionType, etc. When SchemaDirectiveVisitor.visitSchemaDirectives is
|
348 | // called with a GraphQLSchema object and a map of visitor subclasses, the
|
349 | // overidden methods of those subclasses allow the visitors to obtain
|
350 | // references to any type objects that have @directives attached to them,
|
351 | // enabling visitors to inspect or modify the schema as appropriate.
|
352 | //
|
353 | // For example, if a directive called @rest(url: "...") appears after a field
|
354 | // definition, a SchemaDirectiveVisitor subclass could provide meaning to that
|
355 | // directive by overriding the visitFieldDefinition method (which receives a
|
356 | // GraphQLField parameter), and then the body of that visitor method could
|
357 | // manipulate the field's resolver function to fetch data from a REST endpoint
|
358 | // described by the url argument passed to the @rest directive:
|
359 | //
|
360 | // const typeDefs = `
|
361 | // type Query {
|
362 | // people: [Person] @rest(url: "/api/v1/people")
|
363 | // }`;
|
364 | //
|
365 | // const schema = makeExecutableSchema({ typeDefs });
|
366 | //
|
367 | // SchemaDirectiveVisitor.visitSchemaDirectives(schema, {
|
368 | // rest: class extends SchemaDirectiveVisitor {
|
369 | // public visitFieldDefinition(field: GraphQLField<any, any>) {
|
370 | // const { url } = this.args;
|
371 | // field.resolve = () => fetch(url);
|
372 | // }
|
373 | // }
|
374 | // });
|
375 | //
|
376 | // The subclass in this example is defined as an anonymous class expression,
|
377 | // for brevity. A truly reusable SchemaDirectiveVisitor would most likely be
|
378 | // defined in a library using a named class declaration, and then exported for
|
379 | // consumption by other modules and packages.
|
380 | //
|
381 | // See below for a complete list of overridable visitor methods, their
|
382 | // parameter types, and more details about the properties exposed by instances
|
383 | // of the SchemaDirectiveVisitor class.
|
384 | var SchemaDirectiveVisitor = /** @class */ (function (_super) {
|
385 | __extends(SchemaDirectiveVisitor, _super);
|
386 | // Mark the constructor protected to enforce passing SchemaDirectiveVisitor
|
387 | // subclasses (not instances) to visitSchemaDirectives.
|
388 | function SchemaDirectiveVisitor(config) {
|
389 | var _this = _super.call(this) || this;
|
390 | _this.name = config.name;
|
391 | _this.args = config.args;
|
392 | _this.visitedType = config.visitedType;
|
393 | _this.schema = config.schema;
|
394 | _this.context = config.context;
|
395 | return _this;
|
396 | }
|
397 | // Override this method to return a custom GraphQLDirective (or modify one
|
398 | // already present in the schema) to enforce argument types, provide default
|
399 | // argument values, or specify schema locations where this @directive may
|
400 | // appear. By default, any declaration found in the schema will be returned.
|
401 | SchemaDirectiveVisitor.getDirectiveDeclaration = function (directiveName, schema) {
|
402 | return schema.getDirective(directiveName);
|
403 | };
|
404 | // Call SchemaDirectiveVisitor.visitSchemaDirectives to visit every
|
405 | // @directive in the schema and create an appropriate SchemaDirectiveVisitor
|
406 | // instance to visit the object decorated by the @directive.
|
407 | SchemaDirectiveVisitor.visitSchemaDirectives = function (schema, directiveVisitors,
|
408 | // Optional context object that will be available to all visitor instances
|
409 | // via this.context. Defaults to an empty null-prototype object.
|
410 | context) {
|
411 | if (context === void 0) { context = Object.create(null); }
|
412 | // If the schema declares any directives for public consumption, record
|
413 | // them here so that we can properly coerce arguments when/if we encounter
|
414 | // an occurrence of the directive while walking the schema below.
|
415 | var declaredDirectives = this.getDeclaredDirectives(schema, directiveVisitors);
|
416 | // Map from directive names to lists of SchemaDirectiveVisitor instances
|
417 | // created while visiting the schema.
|
418 | var createdVisitors = Object.create(null);
|
419 | Object.keys(directiveVisitors).forEach(function (directiveName) {
|
420 | createdVisitors[directiveName] = [];
|
421 | });
|
422 | function visitorSelector(type, methodName) {
|
423 | var visitors = [];
|
424 | var directiveNodes = type.astNode && type.astNode.directives;
|
425 | if (!directiveNodes) {
|
426 | return visitors;
|
427 | }
|
428 | directiveNodes.forEach(function (directiveNode) {
|
429 | var directiveName = directiveNode.name.value;
|
430 | if (!hasOwn.call(directiveVisitors, directiveName)) {
|
431 | return;
|
432 | }
|
433 | var visitorClass = directiveVisitors[directiveName];
|
434 | // Avoid creating visitor objects if visitorClass does not override
|
435 | // the visitor method named by methodName.
|
436 | if (!visitorClass.implementsVisitorMethod(methodName)) {
|
437 | return;
|
438 | }
|
439 | var decl = declaredDirectives[directiveName];
|
440 | var args;
|
441 | if (decl) {
|
442 | // If this directive was explicitly declared, use the declared
|
443 | // argument types (and any default values) to check, coerce, and/or
|
444 | // supply default values for the given arguments.
|
445 | args = values_1.getArgumentValues(decl, directiveNode);
|
446 | }
|
447 | else {
|
448 | // If this directive was not explicitly declared, just convert the
|
449 | // argument nodes to their corresponding JavaScript values.
|
450 | args = Object.create(null);
|
451 | directiveNode.arguments.forEach(function (arg) {
|
452 | args[arg.name.value] = valueFromASTUntyped(arg.value);
|
453 | });
|
454 | }
|
455 | // As foretold in comments near the top of the visitSchemaDirectives
|
456 | // method, this is where instances of the SchemaDirectiveVisitor class
|
457 | // get created and assigned names. While subclasses could override the
|
458 | // constructor method, the constructor is marked as protected, so
|
459 | // these are the only arguments that will ever be passed.
|
460 | visitors.push(new visitorClass({
|
461 | name: directiveName,
|
462 | args: args,
|
463 | visitedType: type,
|
464 | schema: schema,
|
465 | context: context,
|
466 | }));
|
467 | });
|
468 | if (visitors.length > 0) {
|
469 | visitors.forEach(function (visitor) {
|
470 | createdVisitors[visitor.name].push(visitor);
|
471 | });
|
472 | }
|
473 | return visitors;
|
474 | }
|
475 | visitSchema(schema, visitorSelector);
|
476 | // Automatically update any references to named schema types replaced
|
477 | // during the traversal, so implementors don't have to worry about that.
|
478 | healSchema(schema);
|
479 | return createdVisitors;
|
480 | };
|
481 | SchemaDirectiveVisitor.getDeclaredDirectives = function (schema, directiveVisitors) {
|
482 | var declaredDirectives = Object.create(null);
|
483 | each(schema.getDirectives(), function (decl) {
|
484 | declaredDirectives[decl.name] = decl;
|
485 | });
|
486 | // If the visitor subclass overrides getDirectiveDeclaration, and it
|
487 | // returns a non-null GraphQLDirective, use that instead of any directive
|
488 | // declared in the schema itself. Reasoning: if a SchemaDirectiveVisitor
|
489 | // goes to the trouble of implementing getDirectiveDeclaration, it should
|
490 | // be able to rely on that implementation.
|
491 | each(directiveVisitors, function (visitorClass, directiveName) {
|
492 | var decl = visitorClass.getDirectiveDeclaration(directiveName, schema);
|
493 | if (decl) {
|
494 | declaredDirectives[directiveName] = decl;
|
495 | }
|
496 | });
|
497 | each(declaredDirectives, function (decl, name) {
|
498 | if (!hasOwn.call(directiveVisitors, name)) {
|
499 | // SchemaDirectiveVisitors.visitSchemaDirectives might be called
|
500 | // multiple times with partial directiveVisitors maps, so it's not
|
501 | // necessarily an error for directiveVisitors to be missing an
|
502 | // implementation of a directive that was declared in the schema.
|
503 | return;
|
504 | }
|
505 | var visitorClass = directiveVisitors[name];
|
506 | each(decl.locations, function (loc) {
|
507 | var visitorMethodName = directiveLocationToVisitorMethodName(loc);
|
508 | if (SchemaVisitor.implementsVisitorMethod(visitorMethodName) &&
|
509 | !visitorClass.implementsVisitorMethod(visitorMethodName)) {
|
510 | // While visitor subclasses may implement extra visitor methods,
|
511 | // it's definitely a mistake if the GraphQLDirective declares itself
|
512 | // applicable to certain schema locations, and the visitor subclass
|
513 | // does not implement all the corresponding methods.
|
514 | throw new Error("SchemaDirectiveVisitor for @" + name + " must implement " + visitorMethodName + " method");
|
515 | }
|
516 | });
|
517 | });
|
518 | return declaredDirectives;
|
519 | };
|
520 | return SchemaDirectiveVisitor;
|
521 | }(SchemaVisitor));
|
522 | exports.SchemaDirectiveVisitor = SchemaDirectiveVisitor;
|
523 | // Convert a string like "FIELD_DEFINITION" to "visitFieldDefinition".
|
524 | function directiveLocationToVisitorMethodName(loc) {
|
525 | return 'visit' + loc.replace(/([^_]*)_?/g, function (wholeMatch, part) {
|
526 | return part.charAt(0).toUpperCase() + part.slice(1).toLowerCase();
|
527 | });
|
528 | }
|
529 | function each(arrayOrObject, callback) {
|
530 | Object.keys(arrayOrObject).forEach(function (key) {
|
531 | callback(arrayOrObject[key], key);
|
532 | });
|
533 | }
|
534 | // A more powerful version of each that has the ability to replace or remove
|
535 | // array or object keys.
|
536 | function updateEachKey(arrayOrObject,
|
537 | // The callback can return nothing to leave the key untouched, null to remove
|
538 | // the key from the array or object, or a non-null V to replace the value.
|
539 | callback) {
|
540 | var deletedCount = 0;
|
541 | Object.keys(arrayOrObject).forEach(function (key) {
|
542 | var result = callback(arrayOrObject[key], key);
|
543 | if (typeof result === 'undefined') {
|
544 | return;
|
545 | }
|
546 | if (result === null) {
|
547 | delete arrayOrObject[key];
|
548 | deletedCount++;
|
549 | return;
|
550 | }
|
551 | arrayOrObject[key] = result;
|
552 | });
|
553 | if (deletedCount > 0 && Array.isArray(arrayOrObject)) {
|
554 | // Remove any holes from the array due to deleted elements.
|
555 | arrayOrObject.splice(0).forEach(function (elem) {
|
556 | arrayOrObject.push(elem);
|
557 | });
|
558 | }
|
559 | }
|
560 | // Similar to the graphql-js function of the same name, slightly simplified:
|
561 | // https://github.com/graphql/graphql-js/blob/master/src/utilities/valueFromASTUntyped.js
|
562 | function valueFromASTUntyped(valueNode) {
|
563 | switch (valueNode.kind) {
|
564 | case graphql_1.Kind.NULL:
|
565 | return null;
|
566 | case graphql_1.Kind.INT:
|
567 | return parseInt(valueNode.value, 10);
|
568 | case graphql_1.Kind.FLOAT:
|
569 | return parseFloat(valueNode.value);
|
570 | case graphql_1.Kind.STRING:
|
571 | case graphql_1.Kind.ENUM:
|
572 | case graphql_1.Kind.BOOLEAN:
|
573 | return valueNode.value;
|
574 | case graphql_1.Kind.LIST:
|
575 | return valueNode.values.map(valueFromASTUntyped);
|
576 | case graphql_1.Kind.OBJECT:
|
577 | var obj_1 = Object.create(null);
|
578 | valueNode.fields.forEach(function (field) {
|
579 | obj_1[field.name.value] = valueFromASTUntyped(field.value);
|
580 | });
|
581 | return obj_1;
|
582 | /* istanbul ignore next */
|
583 | default:
|
584 | throw new Error('Unexpected value kind: ' + valueNode.kind);
|
585 | }
|
586 | }
|
587 | //# sourceMappingURL=schemaVisitor.js.map |
\ | No newline at end of file |