1 | import arrayFrom from "../../polyfills/arrayFrom.mjs";
|
2 | import didYouMean from "../../jsutils/didYouMean.mjs";
|
3 | import suggestionList from "../../jsutils/suggestionList.mjs";
|
4 | import naturalCompare from "../../jsutils/naturalCompare.mjs";
|
5 | import { GraphQLError } from "../../error/GraphQLError.mjs";
|
6 | import { isObjectType, isInterfaceType, isAbstractType } from "../../type/definition.mjs";
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 | export function FieldsOnCorrectTypeRule(context) {
|
15 | return {
|
16 | Field: function Field(node) {
|
17 | var type = context.getParentType();
|
18 |
|
19 | if (type) {
|
20 | var fieldDef = context.getFieldDef();
|
21 |
|
22 | if (!fieldDef) {
|
23 |
|
24 | var schema = context.getSchema();
|
25 | var fieldName = node.name.value;
|
26 |
|
27 | var suggestion = didYouMean('to use an inline fragment on', getSuggestedTypeNames(schema, type, fieldName));
|
28 |
|
29 | if (suggestion === '') {
|
30 | suggestion = didYouMean(getSuggestedFieldNames(type, fieldName));
|
31 | }
|
32 |
|
33 |
|
34 | context.reportError(new GraphQLError("Cannot query field \"".concat(fieldName, "\" on type \"").concat(type.name, "\".") + suggestion, node));
|
35 | }
|
36 | }
|
37 | }
|
38 | };
|
39 | }
|
40 |
|
41 |
|
42 |
|
43 |
|
44 |
|
45 |
|
46 | function getSuggestedTypeNames(schema, type, fieldName) {
|
47 | if (!isAbstractType(type)) {
|
48 |
|
49 | return [];
|
50 | }
|
51 |
|
52 | var suggestedTypes = new Set();
|
53 | var usageCount = Object.create(null);
|
54 |
|
55 | for (var _i2 = 0, _schema$getPossibleTy2 = schema.getPossibleTypes(type); _i2 < _schema$getPossibleTy2.length; _i2++) {
|
56 | var possibleType = _schema$getPossibleTy2[_i2];
|
57 |
|
58 | if (!possibleType.getFields()[fieldName]) {
|
59 | continue;
|
60 | }
|
61 |
|
62 |
|
63 | suggestedTypes.add(possibleType);
|
64 | usageCount[possibleType.name] = 1;
|
65 |
|
66 | for (var _i4 = 0, _possibleType$getInte2 = possibleType.getInterfaces(); _i4 < _possibleType$getInte2.length; _i4++) {
|
67 | var _usageCount$possibleI;
|
68 |
|
69 | var possibleInterface = _possibleType$getInte2[_i4];
|
70 |
|
71 | if (!possibleInterface.getFields()[fieldName]) {
|
72 | continue;
|
73 | }
|
74 |
|
75 |
|
76 | suggestedTypes.add(possibleInterface);
|
77 | usageCount[possibleInterface.name] = ((_usageCount$possibleI = usageCount[possibleInterface.name]) !== null && _usageCount$possibleI !== void 0 ? _usageCount$possibleI : 0) + 1;
|
78 | }
|
79 | }
|
80 |
|
81 | return arrayFrom(suggestedTypes).sort(function (typeA, typeB) {
|
82 |
|
83 | var usageCountDiff = usageCount[typeB.name] - usageCount[typeA.name];
|
84 |
|
85 | if (usageCountDiff !== 0) {
|
86 | return usageCountDiff;
|
87 | }
|
88 |
|
89 |
|
90 | if (isInterfaceType(typeA) && schema.isSubType(typeA, typeB)) {
|
91 | return -1;
|
92 | }
|
93 |
|
94 | if (isInterfaceType(typeB) && schema.isSubType(typeB, typeA)) {
|
95 | return 1;
|
96 | }
|
97 |
|
98 | return naturalCompare(typeA.name, typeB.name);
|
99 | }).map(function (x) {
|
100 | return x.name;
|
101 | });
|
102 | }
|
103 |
|
104 |
|
105 |
|
106 |
|
107 |
|
108 |
|
109 | function getSuggestedFieldNames(type, fieldName) {
|
110 | if (isObjectType(type) || isInterfaceType(type)) {
|
111 | var possibleFieldNames = Object.keys(type.getFields());
|
112 | return suggestionList(fieldName, possibleFieldNames);
|
113 | }
|
114 |
|
115 |
|
116 | return [];
|
117 | }
|