UNPKG

24.5 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, '__esModule', {
4 value: true,
5});
6exports.extendSchema = extendSchema;
7exports.extendSchemaImpl = extendSchemaImpl;
8
9var _devAssert = require('../jsutils/devAssert.js');
10
11var _inspect = require('../jsutils/inspect.js');
12
13var _invariant = require('../jsutils/invariant.js');
14
15var _keyMap = require('../jsutils/keyMap.js');
16
17var _mapValue = require('../jsutils/mapValue.js');
18
19var _kinds = require('../language/kinds.js');
20
21var _predicates = require('../language/predicates.js');
22
23var _definition = require('../type/definition.js');
24
25var _directives = require('../type/directives.js');
26
27var _introspection = require('../type/introspection.js');
28
29var _scalars = require('../type/scalars.js');
30
31var _schema = require('../type/schema.js');
32
33var _validate = require('../validation/validate.js');
34
35var _values = require('../execution/values.js');
36
37var _valueFromAST = require('./valueFromAST.js');
38
39/**
40 * Produces a new schema given an existing schema and a document which may
41 * contain GraphQL type extensions and definitions. The original schema will
42 * remain unaltered.
43 *
44 * Because a schema represents a graph of references, a schema cannot be
45 * extended without effectively making an entire copy. We do not know until it's
46 * too late if subgraphs remain unchanged.
47 *
48 * This algorithm copies the provided schema, applying extensions while
49 * producing the copy. The original schema remains unaltered.
50 */
51function extendSchema(schema, documentAST, options) {
52 (0, _schema.assertSchema)(schema);
53 (documentAST != null && documentAST.kind === _kinds.Kind.DOCUMENT) ||
54 (0, _devAssert.devAssert)(false, 'Must provide valid Document AST.');
55
56 if (
57 (options === null || options === void 0 ? void 0 : options.assumeValid) !==
58 true &&
59 (options === null || options === void 0
60 ? void 0
61 : options.assumeValidSDL) !== true
62 ) {
63 (0, _validate.assertValidSDLExtension)(documentAST, schema);
64 }
65
66 const schemaConfig = schema.toConfig();
67 const extendedConfig = extendSchemaImpl(schemaConfig, documentAST, options);
68 return schemaConfig === extendedConfig
69 ? schema
70 : new _schema.GraphQLSchema(extendedConfig);
71}
72/**
73 * @internal
74 */
75
76function extendSchemaImpl(schemaConfig, documentAST, options) {
77 var _schemaDef, _schemaDef$descriptio, _schemaDef2, _options$assumeValid;
78
79 // Collect the type definitions and extensions found in the document.
80 const typeDefs = [];
81 const typeExtensionsMap = Object.create(null); // New directives and types are separate because a directives and types can
82 // have the same name. For example, a type named "skip".
83
84 const directiveDefs = [];
85 let schemaDef; // Schema extensions are collected which may add additional operation types.
86
87 const schemaExtensions = [];
88
89 for (const def of documentAST.definitions) {
90 if (def.kind === _kinds.Kind.SCHEMA_DEFINITION) {
91 schemaDef = def;
92 } else if (def.kind === _kinds.Kind.SCHEMA_EXTENSION) {
93 schemaExtensions.push(def);
94 } else if ((0, _predicates.isTypeDefinitionNode)(def)) {
95 typeDefs.push(def);
96 } else if ((0, _predicates.isTypeExtensionNode)(def)) {
97 const extendedTypeName = def.name.value;
98 const existingTypeExtensions = typeExtensionsMap[extendedTypeName];
99 typeExtensionsMap[extendedTypeName] = existingTypeExtensions
100 ? existingTypeExtensions.concat([def])
101 : [def];
102 } else if (def.kind === _kinds.Kind.DIRECTIVE_DEFINITION) {
103 directiveDefs.push(def);
104 }
105 } // If this document contains no new types, extensions, or directives then
106 // return the same unmodified GraphQLSchema instance.
107
108 if (
109 Object.keys(typeExtensionsMap).length === 0 &&
110 typeDefs.length === 0 &&
111 directiveDefs.length === 0 &&
112 schemaExtensions.length === 0 &&
113 schemaDef == null
114 ) {
115 return schemaConfig;
116 }
117
118 const typeMap = Object.create(null);
119
120 for (const existingType of schemaConfig.types) {
121 typeMap[existingType.name] = extendNamedType(existingType);
122 }
123
124 for (const typeNode of typeDefs) {
125 var _stdTypeMap$name;
126
127 const name = typeNode.name.value;
128 typeMap[name] =
129 (_stdTypeMap$name = stdTypeMap[name]) !== null &&
130 _stdTypeMap$name !== void 0
131 ? _stdTypeMap$name
132 : buildType(typeNode);
133 }
134
135 const operationTypes = {
136 // Get the extended root operation types.
137 query: schemaConfig.query && replaceNamedType(schemaConfig.query),
138 mutation: schemaConfig.mutation && replaceNamedType(schemaConfig.mutation),
139 subscription:
140 schemaConfig.subscription && replaceNamedType(schemaConfig.subscription),
141 // Then, incorporate schema definition and all schema extensions.
142 ...(schemaDef && getOperationTypes([schemaDef])),
143 ...getOperationTypes(schemaExtensions),
144 }; // Then produce and return a Schema config with these types.
145
146 return {
147 description:
148 (_schemaDef = schemaDef) === null || _schemaDef === void 0
149 ? void 0
150 : (_schemaDef$descriptio = _schemaDef.description) === null ||
151 _schemaDef$descriptio === void 0
152 ? void 0
153 : _schemaDef$descriptio.value,
154 ...operationTypes,
155 types: Object.values(typeMap),
156 directives: [
157 ...schemaConfig.directives.map(replaceDirective),
158 ...directiveDefs.map(buildDirective),
159 ],
160 extensions: Object.create(null),
161 astNode:
162 (_schemaDef2 = schemaDef) !== null && _schemaDef2 !== void 0
163 ? _schemaDef2
164 : schemaConfig.astNode,
165 extensionASTNodes: schemaConfig.extensionASTNodes.concat(schemaExtensions),
166 assumeValid:
167 (_options$assumeValid =
168 options === null || options === void 0
169 ? void 0
170 : options.assumeValid) !== null && _options$assumeValid !== void 0
171 ? _options$assumeValid
172 : false,
173 }; // Below are functions used for producing this schema that have closed over
174 // this scope and have access to the schema, cache, and newly defined types.
175
176 function replaceType(type) {
177 if ((0, _definition.isListType)(type)) {
178 // @ts-expect-error
179 return new _definition.GraphQLList(replaceType(type.ofType));
180 }
181
182 if ((0, _definition.isNonNullType)(type)) {
183 // @ts-expect-error
184 return new _definition.GraphQLNonNull(replaceType(type.ofType));
185 } // @ts-expect-error FIXME
186
187 return replaceNamedType(type);
188 }
189
190 function replaceNamedType(type) {
191 // Note: While this could make early assertions to get the correctly
192 // typed values, that would throw immediately while type system
193 // validation with validateSchema() will produce more actionable results.
194 return typeMap[type.name];
195 }
196
197 function replaceDirective(directive) {
198 const config = directive.toConfig();
199 return new _directives.GraphQLDirective({
200 ...config,
201 args: (0, _mapValue.mapValue)(config.args, extendArg),
202 });
203 }
204
205 function extendNamedType(type) {
206 if (
207 (0, _introspection.isIntrospectionType)(type) ||
208 (0, _scalars.isSpecifiedScalarType)(type)
209 ) {
210 // Builtin types are not extended.
211 return type;
212 }
213
214 if ((0, _definition.isScalarType)(type)) {
215 return extendScalarType(type);
216 }
217
218 if ((0, _definition.isObjectType)(type)) {
219 return extendObjectType(type);
220 }
221
222 if ((0, _definition.isInterfaceType)(type)) {
223 return extendInterfaceType(type);
224 }
225
226 if ((0, _definition.isUnionType)(type)) {
227 return extendUnionType(type);
228 }
229
230 if ((0, _definition.isEnumType)(type)) {
231 return extendEnumType(type);
232 }
233
234 if ((0, _definition.isInputObjectType)(type)) {
235 return extendInputObjectType(type);
236 }
237 /* c8 ignore next 3 */
238 // Not reachable, all possible type definition nodes have been considered.
239
240 false ||
241 (0, _invariant.invariant)(
242 false,
243 'Unexpected type: ' + (0, _inspect.inspect)(type),
244 );
245 }
246
247 function extendInputObjectType(type) {
248 var _typeExtensionsMap$co;
249
250 const config = type.toConfig();
251 const extensions =
252 (_typeExtensionsMap$co = typeExtensionsMap[config.name]) !== null &&
253 _typeExtensionsMap$co !== void 0
254 ? _typeExtensionsMap$co
255 : [];
256 return new _definition.GraphQLInputObjectType({
257 ...config,
258 fields: () => ({
259 ...(0, _mapValue.mapValue)(config.fields, (field) => ({
260 ...field,
261 type: replaceType(field.type),
262 })),
263 ...buildInputFieldMap(extensions),
264 }),
265 extensionASTNodes: config.extensionASTNodes.concat(extensions),
266 });
267 }
268
269 function extendEnumType(type) {
270 var _typeExtensionsMap$ty;
271
272 const config = type.toConfig();
273 const extensions =
274 (_typeExtensionsMap$ty = typeExtensionsMap[type.name]) !== null &&
275 _typeExtensionsMap$ty !== void 0
276 ? _typeExtensionsMap$ty
277 : [];
278 return new _definition.GraphQLEnumType({
279 ...config,
280 values: { ...config.values, ...buildEnumValueMap(extensions) },
281 extensionASTNodes: config.extensionASTNodes.concat(extensions),
282 });
283 }
284
285 function extendScalarType(type) {
286 var _typeExtensionsMap$co2;
287
288 const config = type.toConfig();
289 const extensions =
290 (_typeExtensionsMap$co2 = typeExtensionsMap[config.name]) !== null &&
291 _typeExtensionsMap$co2 !== void 0
292 ? _typeExtensionsMap$co2
293 : [];
294 let specifiedByURL = config.specifiedByURL;
295
296 for (const extensionNode of extensions) {
297 var _getSpecifiedByURL;
298
299 specifiedByURL =
300 (_getSpecifiedByURL = getSpecifiedByURL(extensionNode)) !== null &&
301 _getSpecifiedByURL !== void 0
302 ? _getSpecifiedByURL
303 : specifiedByURL;
304 }
305
306 return new _definition.GraphQLScalarType({
307 ...config,
308 specifiedByURL,
309 extensionASTNodes: config.extensionASTNodes.concat(extensions),
310 });
311 }
312
313 function extendObjectType(type) {
314 var _typeExtensionsMap$co3;
315
316 const config = type.toConfig();
317 const extensions =
318 (_typeExtensionsMap$co3 = typeExtensionsMap[config.name]) !== null &&
319 _typeExtensionsMap$co3 !== void 0
320 ? _typeExtensionsMap$co3
321 : [];
322 return new _definition.GraphQLObjectType({
323 ...config,
324 interfaces: () => [
325 ...type.getInterfaces().map(replaceNamedType),
326 ...buildInterfaces(extensions),
327 ],
328 fields: () => ({
329 ...(0, _mapValue.mapValue)(config.fields, extendField),
330 ...buildFieldMap(extensions),
331 }),
332 extensionASTNodes: config.extensionASTNodes.concat(extensions),
333 });
334 }
335
336 function extendInterfaceType(type) {
337 var _typeExtensionsMap$co4;
338
339 const config = type.toConfig();
340 const extensions =
341 (_typeExtensionsMap$co4 = typeExtensionsMap[config.name]) !== null &&
342 _typeExtensionsMap$co4 !== void 0
343 ? _typeExtensionsMap$co4
344 : [];
345 return new _definition.GraphQLInterfaceType({
346 ...config,
347 interfaces: () => [
348 ...type.getInterfaces().map(replaceNamedType),
349 ...buildInterfaces(extensions),
350 ],
351 fields: () => ({
352 ...(0, _mapValue.mapValue)(config.fields, extendField),
353 ...buildFieldMap(extensions),
354 }),
355 extensionASTNodes: config.extensionASTNodes.concat(extensions),
356 });
357 }
358
359 function extendUnionType(type) {
360 var _typeExtensionsMap$co5;
361
362 const config = type.toConfig();
363 const extensions =
364 (_typeExtensionsMap$co5 = typeExtensionsMap[config.name]) !== null &&
365 _typeExtensionsMap$co5 !== void 0
366 ? _typeExtensionsMap$co5
367 : [];
368 return new _definition.GraphQLUnionType({
369 ...config,
370 types: () => [
371 ...type.getTypes().map(replaceNamedType),
372 ...buildUnionTypes(extensions),
373 ],
374 extensionASTNodes: config.extensionASTNodes.concat(extensions),
375 });
376 }
377
378 function extendField(field) {
379 return {
380 ...field,
381 type: replaceType(field.type),
382 args: field.args && (0, _mapValue.mapValue)(field.args, extendArg),
383 };
384 }
385
386 function extendArg(arg) {
387 return { ...arg, type: replaceType(arg.type) };
388 }
389
390 function getOperationTypes(nodes) {
391 const opTypes = {};
392
393 for (const node of nodes) {
394 var _node$operationTypes;
395
396 // FIXME: https://github.com/graphql/graphql-js/issues/2203
397 const operationTypesNodes =
398 /* c8 ignore next */
399 (_node$operationTypes = node.operationTypes) !== null &&
400 _node$operationTypes !== void 0
401 ? _node$operationTypes
402 : [];
403
404 for (const operationType of operationTypesNodes) {
405 // Note: While this could make early assertions to get the correctly
406 // typed values below, that would throw immediately while type system
407 // validation with validateSchema() will produce more actionable results.
408 // @ts-expect-error
409 opTypes[operationType.operation] = getNamedType(operationType.type);
410 }
411 }
412
413 return opTypes;
414 }
415
416 function getNamedType(node) {
417 var _stdTypeMap$name2;
418
419 const name = node.name.value;
420 const type =
421 (_stdTypeMap$name2 = stdTypeMap[name]) !== null &&
422 _stdTypeMap$name2 !== void 0
423 ? _stdTypeMap$name2
424 : typeMap[name];
425
426 if (type === undefined) {
427 throw new Error(`Unknown type: "${name}".`);
428 }
429
430 return type;
431 }
432
433 function getWrappedType(node) {
434 if (node.kind === _kinds.Kind.LIST_TYPE) {
435 return new _definition.GraphQLList(getWrappedType(node.type));
436 }
437
438 if (node.kind === _kinds.Kind.NON_NULL_TYPE) {
439 return new _definition.GraphQLNonNull(getWrappedType(node.type));
440 }
441
442 return getNamedType(node);
443 }
444
445 function buildDirective(node) {
446 var _node$description;
447
448 return new _directives.GraphQLDirective({
449 name: node.name.value,
450 description:
451 (_node$description = node.description) === null ||
452 _node$description === void 0
453 ? void 0
454 : _node$description.value,
455 // @ts-expect-error
456 locations: node.locations.map(({ value }) => value),
457 isRepeatable: node.repeatable,
458 args: buildArgumentMap(node.arguments),
459 astNode: node,
460 });
461 }
462
463 function buildFieldMap(nodes) {
464 const fieldConfigMap = Object.create(null);
465
466 for (const node of nodes) {
467 var _node$fields;
468
469 // FIXME: https://github.com/graphql/graphql-js/issues/2203
470 const nodeFields =
471 /* c8 ignore next */
472 (_node$fields = node.fields) !== null && _node$fields !== void 0
473 ? _node$fields
474 : [];
475
476 for (const field of nodeFields) {
477 var _field$description;
478
479 fieldConfigMap[field.name.value] = {
480 // Note: While this could make assertions to get the correctly typed
481 // value, that would throw immediately while type system validation
482 // with validateSchema() will produce more actionable results.
483 type: getWrappedType(field.type),
484 description:
485 (_field$description = field.description) === null ||
486 _field$description === void 0
487 ? void 0
488 : _field$description.value,
489 args: buildArgumentMap(field.arguments),
490 deprecationReason: getDeprecationReason(field),
491 astNode: field,
492 };
493 }
494 }
495
496 return fieldConfigMap;
497 }
498
499 function buildArgumentMap(args) {
500 // FIXME: https://github.com/graphql/graphql-js/issues/2203
501 const argsNodes =
502 /* c8 ignore next */
503 args !== null && args !== void 0 ? args : [];
504 const argConfigMap = Object.create(null);
505
506 for (const arg of argsNodes) {
507 var _arg$description;
508
509 // Note: While this could make assertions to get the correctly typed
510 // value, that would throw immediately while type system validation
511 // with validateSchema() will produce more actionable results.
512 const type = getWrappedType(arg.type);
513 argConfigMap[arg.name.value] = {
514 type,
515 description:
516 (_arg$description = arg.description) === null ||
517 _arg$description === void 0
518 ? void 0
519 : _arg$description.value,
520 defaultValue: (0, _valueFromAST.valueFromAST)(arg.defaultValue, type),
521 deprecationReason: getDeprecationReason(arg),
522 astNode: arg,
523 };
524 }
525
526 return argConfigMap;
527 }
528
529 function buildInputFieldMap(nodes) {
530 const inputFieldMap = Object.create(null);
531
532 for (const node of nodes) {
533 var _node$fields2;
534
535 // FIXME: https://github.com/graphql/graphql-js/issues/2203
536 const fieldsNodes =
537 /* c8 ignore next */
538 (_node$fields2 = node.fields) !== null && _node$fields2 !== void 0
539 ? _node$fields2
540 : [];
541
542 for (const field of fieldsNodes) {
543 var _field$description2;
544
545 // Note: While this could make assertions to get the correctly typed
546 // value, that would throw immediately while type system validation
547 // with validateSchema() will produce more actionable results.
548 const type = getWrappedType(field.type);
549 inputFieldMap[field.name.value] = {
550 type,
551 description:
552 (_field$description2 = field.description) === null ||
553 _field$description2 === void 0
554 ? void 0
555 : _field$description2.value,
556 defaultValue: (0, _valueFromAST.valueFromAST)(
557 field.defaultValue,
558 type,
559 ),
560 deprecationReason: getDeprecationReason(field),
561 astNode: field,
562 };
563 }
564 }
565
566 return inputFieldMap;
567 }
568
569 function buildEnumValueMap(nodes) {
570 const enumValueMap = Object.create(null);
571
572 for (const node of nodes) {
573 var _node$values;
574
575 // FIXME: https://github.com/graphql/graphql-js/issues/2203
576 const valuesNodes =
577 /* c8 ignore next */
578 (_node$values = node.values) !== null && _node$values !== void 0
579 ? _node$values
580 : [];
581
582 for (const value of valuesNodes) {
583 var _value$description;
584
585 enumValueMap[value.name.value] = {
586 description:
587 (_value$description = value.description) === null ||
588 _value$description === void 0
589 ? void 0
590 : _value$description.value,
591 deprecationReason: getDeprecationReason(value),
592 astNode: value,
593 };
594 }
595 }
596
597 return enumValueMap;
598 }
599
600 function buildInterfaces(nodes) {
601 // Note: While this could make assertions to get the correctly typed
602 // values below, that would throw immediately while type system
603 // validation with validateSchema() will produce more actionable results.
604 // @ts-expect-error
605 return nodes.flatMap(
606 // FIXME: https://github.com/graphql/graphql-js/issues/2203
607 (node) => {
608 var _node$interfaces$map, _node$interfaces;
609
610 return (
611 /* c8 ignore next */
612 (_node$interfaces$map =
613 (_node$interfaces = node.interfaces) === null ||
614 _node$interfaces === void 0
615 ? void 0
616 : _node$interfaces.map(getNamedType)) !== null &&
617 _node$interfaces$map !== void 0
618 ? _node$interfaces$map
619 : []
620 );
621 },
622 );
623 }
624
625 function buildUnionTypes(nodes) {
626 // Note: While this could make assertions to get the correctly typed
627 // values below, that would throw immediately while type system
628 // validation with validateSchema() will produce more actionable results.
629 // @ts-expect-error
630 return nodes.flatMap(
631 // FIXME: https://github.com/graphql/graphql-js/issues/2203
632 (node) => {
633 var _node$types$map, _node$types;
634
635 return (
636 /* c8 ignore next */
637 (_node$types$map =
638 (_node$types = node.types) === null || _node$types === void 0
639 ? void 0
640 : _node$types.map(getNamedType)) !== null &&
641 _node$types$map !== void 0
642 ? _node$types$map
643 : []
644 );
645 },
646 );
647 }
648
649 function buildType(astNode) {
650 var _typeExtensionsMap$na;
651
652 const name = astNode.name.value;
653 const extensionASTNodes =
654 (_typeExtensionsMap$na = typeExtensionsMap[name]) !== null &&
655 _typeExtensionsMap$na !== void 0
656 ? _typeExtensionsMap$na
657 : [];
658
659 switch (astNode.kind) {
660 case _kinds.Kind.OBJECT_TYPE_DEFINITION: {
661 var _astNode$description;
662
663 const allNodes = [astNode, ...extensionASTNodes];
664 return new _definition.GraphQLObjectType({
665 name,
666 description:
667 (_astNode$description = astNode.description) === null ||
668 _astNode$description === void 0
669 ? void 0
670 : _astNode$description.value,
671 interfaces: () => buildInterfaces(allNodes),
672 fields: () => buildFieldMap(allNodes),
673 astNode,
674 extensionASTNodes,
675 });
676 }
677
678 case _kinds.Kind.INTERFACE_TYPE_DEFINITION: {
679 var _astNode$description2;
680
681 const allNodes = [astNode, ...extensionASTNodes];
682 return new _definition.GraphQLInterfaceType({
683 name,
684 description:
685 (_astNode$description2 = astNode.description) === null ||
686 _astNode$description2 === void 0
687 ? void 0
688 : _astNode$description2.value,
689 interfaces: () => buildInterfaces(allNodes),
690 fields: () => buildFieldMap(allNodes),
691 astNode,
692 extensionASTNodes,
693 });
694 }
695
696 case _kinds.Kind.ENUM_TYPE_DEFINITION: {
697 var _astNode$description3;
698
699 const allNodes = [astNode, ...extensionASTNodes];
700 return new _definition.GraphQLEnumType({
701 name,
702 description:
703 (_astNode$description3 = astNode.description) === null ||
704 _astNode$description3 === void 0
705 ? void 0
706 : _astNode$description3.value,
707 values: buildEnumValueMap(allNodes),
708 astNode,
709 extensionASTNodes,
710 });
711 }
712
713 case _kinds.Kind.UNION_TYPE_DEFINITION: {
714 var _astNode$description4;
715
716 const allNodes = [astNode, ...extensionASTNodes];
717 return new _definition.GraphQLUnionType({
718 name,
719 description:
720 (_astNode$description4 = astNode.description) === null ||
721 _astNode$description4 === void 0
722 ? void 0
723 : _astNode$description4.value,
724 types: () => buildUnionTypes(allNodes),
725 astNode,
726 extensionASTNodes,
727 });
728 }
729
730 case _kinds.Kind.SCALAR_TYPE_DEFINITION: {
731 var _astNode$description5;
732
733 return new _definition.GraphQLScalarType({
734 name,
735 description:
736 (_astNode$description5 = astNode.description) === null ||
737 _astNode$description5 === void 0
738 ? void 0
739 : _astNode$description5.value,
740 specifiedByURL: getSpecifiedByURL(astNode),
741 astNode,
742 extensionASTNodes,
743 });
744 }
745
746 case _kinds.Kind.INPUT_OBJECT_TYPE_DEFINITION: {
747 var _astNode$description6;
748
749 const allNodes = [astNode, ...extensionASTNodes];
750 return new _definition.GraphQLInputObjectType({
751 name,
752 description:
753 (_astNode$description6 = astNode.description) === null ||
754 _astNode$description6 === void 0
755 ? void 0
756 : _astNode$description6.value,
757 fields: () => buildInputFieldMap(allNodes),
758 astNode,
759 extensionASTNodes,
760 });
761 }
762 }
763 }
764}
765
766const stdTypeMap = (0, _keyMap.keyMap)(
767 [..._scalars.specifiedScalarTypes, ..._introspection.introspectionTypes],
768 (type) => type.name,
769);
770/**
771 * Given a field or enum value node, returns the string value for the
772 * deprecation reason.
773 */
774
775function getDeprecationReason(node) {
776 const deprecated = (0, _values.getDirectiveValues)(
777 _directives.GraphQLDeprecatedDirective,
778 node,
779 ); // @ts-expect-error validated by `getDirectiveValues`
780
781 return deprecated === null || deprecated === void 0
782 ? void 0
783 : deprecated.reason;
784}
785/**
786 * Given a scalar node, returns the string value for the specifiedByURL.
787 */
788
789function getSpecifiedByURL(node) {
790 const specifiedBy = (0, _values.getDirectiveValues)(
791 _directives.GraphQLSpecifiedByDirective,
792 node,
793 ); // @ts-expect-error validated by `getDirectiveValues`
794
795 return specifiedBy === null || specifiedBy === void 0
796 ? void 0
797 : specifiedBy.url;
798}