1 | import { valueFromAST, valueFromASTUntyped } from 'graphql';
|
2 | import { getArgumentValues } from './getArgumentValues.js';
|
3 | import { memoize1 } from './memoize.js';
|
4 | export function getDirectiveExtensions(directableObj, schema, pathToDirectivesInExtensions = ['directives']) {
|
5 | const directiveExtensions = {};
|
6 | if (directableObj.extensions) {
|
7 | let directivesInExtensions = directableObj.extensions;
|
8 | for (const pathSegment of pathToDirectivesInExtensions) {
|
9 | directivesInExtensions = directivesInExtensions?.[pathSegment];
|
10 | }
|
11 | if (directivesInExtensions != null) {
|
12 | for (const directiveNameProp in directivesInExtensions) {
|
13 | const directiveObjs = directivesInExtensions[directiveNameProp];
|
14 | const directiveName = directiveNameProp;
|
15 | if (Array.isArray(directiveObjs)) {
|
16 | for (const directiveObj of directiveObjs) {
|
17 | let existingDirectiveExtensions = directiveExtensions[directiveName];
|
18 | if (!existingDirectiveExtensions) {
|
19 | existingDirectiveExtensions = [];
|
20 | directiveExtensions[directiveName] = existingDirectiveExtensions;
|
21 | }
|
22 | existingDirectiveExtensions.push(directiveObj);
|
23 | }
|
24 | }
|
25 | else {
|
26 | let existingDirectiveExtensions = directiveExtensions[directiveName];
|
27 | if (!existingDirectiveExtensions) {
|
28 | existingDirectiveExtensions = [];
|
29 | directiveExtensions[directiveName] = existingDirectiveExtensions;
|
30 | }
|
31 | existingDirectiveExtensions.push(directiveObjs);
|
32 | }
|
33 | }
|
34 | }
|
35 | }
|
36 | const memoizedStringify = memoize1(obj => JSON.stringify(obj));
|
37 | const astNodes = [];
|
38 | if (directableObj.astNode) {
|
39 | astNodes.push(directableObj.astNode);
|
40 | }
|
41 | if (directableObj.extensionASTNodes) {
|
42 | astNodes.push(...directableObj.extensionASTNodes);
|
43 | }
|
44 | for (const astNode of astNodes) {
|
45 | if (astNode.directives?.length) {
|
46 | for (const directive of astNode.directives) {
|
47 | const directiveName = directive.name.value;
|
48 | let existingDirectiveExtensions = directiveExtensions[directiveName];
|
49 | if (!existingDirectiveExtensions) {
|
50 | existingDirectiveExtensions = [];
|
51 | directiveExtensions[directiveName] = existingDirectiveExtensions;
|
52 | }
|
53 | const directiveInSchema = schema?.getDirective(directiveName);
|
54 | let value = {};
|
55 | if (directiveInSchema) {
|
56 | value = getArgumentValues(directiveInSchema, directive);
|
57 | }
|
58 | if (directive.arguments) {
|
59 | for (const argNode of directive.arguments) {
|
60 | const argName = argNode.name.value;
|
61 | if (value[argName] == null) {
|
62 | const argInDirective = directiveInSchema?.args.find(arg => arg.name === argName);
|
63 | if (argInDirective) {
|
64 | value[argName] = valueFromAST(argNode.value, argInDirective.type);
|
65 | }
|
66 | }
|
67 | if (value[argName] == null) {
|
68 | value[argName] = valueFromASTUntyped(argNode.value);
|
69 | }
|
70 | }
|
71 | }
|
72 | if (astNodes.length > 0 && existingDirectiveExtensions.length > 0) {
|
73 | const valStr = memoizedStringify(value);
|
74 | if (existingDirectiveExtensions.some(val => memoizedStringify(val) === valStr)) {
|
75 | continue;
|
76 | }
|
77 | }
|
78 | existingDirectiveExtensions.push(value);
|
79 | }
|
80 | }
|
81 | }
|
82 | return directiveExtensions;
|
83 | }
|