@graphql-eslint/eslint-plugin 4.0.0-alpha.10 → 4.0.0-alpha.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/index.d.cts +3 -1
- package/cjs/meta.js +1 -1
- package/cjs/rules/index.d.cts +3 -1
- package/cjs/rules/naming-convention/index.js +3 -1
- package/cjs/rules/no-unused-fields/index.d.cts +24 -3
- package/cjs/rules/no-unused-fields/index.js +118 -8
- package/cjs/rules/require-selections/index.js +1 -1
- package/esm/index.d.ts +3 -1
- package/esm/meta.js +1 -1
- package/esm/rules/index.d.ts +3 -1
- package/esm/rules/naming-convention/index.js +3 -1
- package/esm/rules/no-unused-fields/index.d.ts +24 -3
- package/esm/rules/no-unused-fields/index.js +118 -8
- package/esm/rules/require-selections/index.js +1 -1
- package/index.browser.js +189 -77
- package/package.json +1 -1
package/cjs/index.d.cts
CHANGED
@@ -117,7 +117,9 @@ declare const _default: {
|
|
117
117
|
'no-scalar-result-type-on-mutation': GraphQLESLintRule;
|
118
118
|
'no-typename-prefix': GraphQLESLintRule;
|
119
119
|
'no-unreachable-types': GraphQLESLintRule;
|
120
|
-
'no-unused-fields': GraphQLESLintRule
|
120
|
+
'no-unused-fields': GraphQLESLintRule<{
|
121
|
+
ignoredFieldSelectors?: string[] | undefined;
|
122
|
+
}[]>;
|
121
123
|
'relay-arguments': GraphQLESLintRule<{
|
122
124
|
includeBoth: boolean;
|
123
125
|
}[], true>;
|
package/cjs/meta.js
CHANGED
package/cjs/rules/index.d.cts
CHANGED
@@ -81,7 +81,9 @@ declare const rules: {
|
|
81
81
|
'no-scalar-result-type-on-mutation': GraphQLESLintRule;
|
82
82
|
'no-typename-prefix': GraphQLESLintRule;
|
83
83
|
'no-unreachable-types': GraphQLESLintRule;
|
84
|
-
'no-unused-fields': GraphQLESLintRule
|
84
|
+
'no-unused-fields': GraphQLESLintRule<{
|
85
|
+
ignoredFieldSelectors?: string[] | undefined;
|
86
|
+
}[]>;
|
85
87
|
'relay-arguments': GraphQLESLintRule<{
|
86
88
|
includeBoth: boolean;
|
87
89
|
}[], true>;
|
@@ -384,12 +384,14 @@ ${_utilsjs.TYPES_KINDS.map((kind) => `- \`${kind}\``).join(`
|
|
384
384
|
};
|
385
385
|
}
|
386
386
|
}, checkUnderscore = (isLeading) => (node) => {
|
387
|
+
if (node.parent.kind === "Field" && node.parent.alias !== node)
|
388
|
+
return;
|
387
389
|
const suggestedName = node.value.replace(isLeading ? /^_+/ : /_+$/, "");
|
388
390
|
report(node, `${isLeading ? "Leading" : "Trailing"} underscores are not allowed`, [
|
389
391
|
suggestedName
|
390
392
|
]);
|
391
393
|
}, listeners = {};
|
392
|
-
allowLeadingUnderscore || (listeners["Name[value=/^_/]
|
394
|
+
allowLeadingUnderscore || (listeners["Name[value=/^_/]"] = checkUnderscore(!0)), allowTrailingUnderscore || (listeners["Name[value=/_$/]"] = checkUnderscore(!1));
|
393
395
|
const selectors = new Set(
|
394
396
|
[types && _utilsjs.TYPES_KINDS, Object.keys(restOptions)].flat().filter(_utilsjs.truthy)
|
395
397
|
);
|
@@ -1,13 +1,34 @@
|
|
1
|
+
import { FromSchema } from 'json-schema-to-ts';
|
1
2
|
import { GraphQLESLintRule } from '../../types.cjs';
|
2
3
|
import 'eslint';
|
3
4
|
import 'estree';
|
4
5
|
import 'graphql';
|
5
6
|
import 'graphql-config';
|
6
|
-
import 'json-schema-to-ts';
|
7
7
|
import '../../estree-converter/types.cjs';
|
8
8
|
import '../../siblings.cjs';
|
9
9
|
import '@graphql-tools/utils';
|
10
10
|
|
11
|
-
declare const
|
11
|
+
declare const schema: {
|
12
|
+
readonly type: "array";
|
13
|
+
readonly maxItems: 1;
|
14
|
+
readonly items: {
|
15
|
+
readonly type: "object";
|
16
|
+
readonly additionalProperties: false;
|
17
|
+
readonly properties: {
|
18
|
+
readonly ignoredFieldSelectors: {
|
19
|
+
readonly type: "array";
|
20
|
+
readonly uniqueItems: true;
|
21
|
+
readonly minItems: 1;
|
22
|
+
readonly description: string;
|
23
|
+
readonly items: {
|
24
|
+
readonly type: "string";
|
25
|
+
readonly pattern: "^\\[(.+)]$";
|
26
|
+
};
|
27
|
+
};
|
28
|
+
};
|
29
|
+
};
|
30
|
+
};
|
31
|
+
type RuleOptions = FromSchema<typeof schema>;
|
32
|
+
declare const rule: GraphQLESLintRule<RuleOptions>;
|
12
33
|
|
13
|
-
export { rule };
|
34
|
+
export { type RuleOptions, rule };
|
@@ -2,12 +2,105 @@
|
|
2
2
|
var _graphql = require('graphql');
|
3
3
|
var _cachejs = require('../../cache.js');
|
4
4
|
var _utilsjs = require('../../utils.js');
|
5
|
-
const RULE_ID = "no-unused-fields",
|
6
|
-
|
7
|
-
|
5
|
+
const RULE_ID = "no-unused-fields", RELAY_SCHEMA = (
|
6
|
+
/* GraphQL */
|
7
|
+
`
|
8
|
+
# Root Query Type
|
9
|
+
type Query {
|
10
|
+
user: User
|
11
|
+
}
|
12
|
+
|
13
|
+
# User Type
|
14
|
+
type User {
|
15
|
+
id: ID!
|
16
|
+
name: String!
|
17
|
+
friends(first: Int, after: String): FriendConnection!
|
18
|
+
}
|
19
|
+
|
20
|
+
# FriendConnection Type (Relay Connection)
|
21
|
+
type FriendConnection {
|
22
|
+
edges: [FriendEdge]
|
23
|
+
pageInfo: PageInfo!
|
24
|
+
}
|
25
|
+
|
26
|
+
# FriendEdge Type
|
27
|
+
type FriendEdge {
|
28
|
+
cursor: String!
|
29
|
+
node: Friend!
|
30
|
+
}
|
31
|
+
|
32
|
+
# Friend Type
|
33
|
+
type Friend {
|
34
|
+
id: ID!
|
35
|
+
name: String!
|
36
|
+
}
|
37
|
+
|
38
|
+
# PageInfo Type (Relay Pagination)
|
39
|
+
type PageInfo {
|
40
|
+
hasPreviousPage: Boolean!
|
41
|
+
hasNextPage: Boolean!
|
42
|
+
startCursor: String
|
43
|
+
endCursor: String
|
44
|
+
}
|
45
|
+
`
|
46
|
+
), RELAY_QUERY = (
|
47
|
+
/* GraphQL */
|
48
|
+
`
|
49
|
+
query {
|
50
|
+
user {
|
51
|
+
id
|
52
|
+
name
|
53
|
+
friends(first: 10) {
|
54
|
+
edges {
|
55
|
+
node {
|
56
|
+
id
|
57
|
+
name
|
58
|
+
}
|
59
|
+
}
|
60
|
+
}
|
61
|
+
}
|
62
|
+
}
|
63
|
+
`
|
64
|
+
), RELAY_DEFAULT_IGNORED_FIELD_SELECTORS = [
|
65
|
+
"[parent.name.value=PageInfo][name.value=/(endCursor|startCursor|hasNextPage|hasPreviousPage)/]",
|
66
|
+
"[parent.name.value=/Edge$/][name.value=cursor]",
|
67
|
+
"[parent.name.value=/Connection$/][name.value=pageInfo]"
|
68
|
+
], schema = {
|
69
|
+
type: "array",
|
70
|
+
maxItems: 1,
|
71
|
+
items: {
|
72
|
+
type: "object",
|
73
|
+
additionalProperties: !1,
|
74
|
+
properties: {
|
75
|
+
ignoredFieldSelectors: {
|
76
|
+
type: "array",
|
77
|
+
uniqueItems: !0,
|
78
|
+
minItems: 1,
|
79
|
+
description: [
|
80
|
+
"Fields that will be ignored and are allowed to be unused.",
|
81
|
+
"",
|
82
|
+
"E.g. The following selector will ignore all the relay pagination fields for every connection exposed in the schema:",
|
83
|
+
"```json",
|
84
|
+
JSON.stringify(RELAY_DEFAULT_IGNORED_FIELD_SELECTORS, null, 2),
|
85
|
+
"```",
|
86
|
+
"",
|
87
|
+
"> These fields are defined by ESLint [`selectors`](https://eslint.org/docs/developer-guide/selectors).",
|
88
|
+
"> Paste or drop code into the editor in [ASTExplorer](https://astexplorer.net) and inspect the generated AST to compose your selector."
|
89
|
+
].join(`
|
90
|
+
`),
|
91
|
+
items: {
|
92
|
+
type: "string",
|
93
|
+
pattern: "^\\[(.+)]$"
|
94
|
+
}
|
95
|
+
}
|
96
|
+
}
|
97
|
+
}
|
98
|
+
}, usedFieldsCache = new (0, _cachejs.ModuleCache)();
|
99
|
+
function getUsedFields(schema2, operations) {
|
100
|
+
const cachedValue = usedFieldsCache.get(schema2);
|
8
101
|
if (process.env.NODE_ENV !== "test" && cachedValue)
|
9
102
|
return cachedValue;
|
10
|
-
const usedFields = /* @__PURE__ */ Object.create(null), typeInfo = new (0, _graphql.TypeInfo)(
|
103
|
+
const usedFields = /* @__PURE__ */ Object.create(null), typeInfo = new (0, _graphql.TypeInfo)(schema2), visitor = _graphql.visitWithTypeInfo.call(void 0, typeInfo, {
|
11
104
|
Field(node) {
|
12
105
|
if (!typeInfo.getFieldDef())
|
13
106
|
return !1;
|
@@ -17,7 +110,7 @@ function getUsedFields(schema, operations) {
|
|
17
110
|
}), allDocuments = [...operations.getOperations(), ...operations.getFragments()];
|
18
111
|
for (const { document } of allDocuments)
|
19
112
|
_graphql.visit.call(void 0, document, visitor);
|
20
|
-
return usedFieldsCache.set(
|
113
|
+
return usedFieldsCache.set(schema2, usedFields), usedFields;
|
21
114
|
}
|
22
115
|
const rule = {
|
23
116
|
meta: {
|
@@ -79,17 +172,34 @@ const rule = {
|
|
79
172
|
}
|
80
173
|
`
|
81
174
|
)
|
175
|
+
},
|
176
|
+
{
|
177
|
+
title: "Correct (ignoring fields)",
|
178
|
+
usage: [{ ignoredFieldSelectors: RELAY_DEFAULT_IGNORED_FIELD_SELECTORS }],
|
179
|
+
code: (
|
180
|
+
/* GraphQL */
|
181
|
+
`
|
182
|
+
### 1\uFE0F\u20E3 YOUR SCHEMA
|
183
|
+
${RELAY_SCHEMA}
|
184
|
+
|
185
|
+
### 2\uFE0F\u20E3 YOUR QUERY
|
186
|
+
${RELAY_QUERY}
|
187
|
+
`
|
188
|
+
)
|
82
189
|
}
|
83
190
|
]
|
84
191
|
},
|
85
192
|
type: "suggestion",
|
86
|
-
schema
|
193
|
+
schema,
|
87
194
|
hasSuggestions: !0
|
88
195
|
},
|
89
196
|
create(context) {
|
90
|
-
const
|
197
|
+
const schema2 = _utilsjs.requireGraphQLSchemaFromContext.call(void 0, RULE_ID, context), siblingsOperations = _utilsjs.requireSiblingsOperations.call(void 0, RULE_ID, context), usedFields = getUsedFields(schema2, siblingsOperations), { ignoredFieldSelectors } = context.options[0] || {};
|
91
198
|
return {
|
92
|
-
|
199
|
+
[(ignoredFieldSelectors || []).reduce(
|
200
|
+
(acc, selector2) => `${acc}:not(${selector2})`,
|
201
|
+
"FieldDefinition"
|
202
|
+
)](node) {
|
93
203
|
const fieldName = node.name.value, parentTypeName = node.parent.name.value;
|
94
204
|
_optionalChain([usedFields, 'access', _ => _[parentTypeName], 'optionalAccess', _2 => _2.has, 'call', _3 => _3(fieldName)]) || context.report({
|
95
205
|
node: node.name,
|
@@ -104,7 +104,7 @@ Include it in your selection set{{ addition }}.`
|
|
104
104
|
schema
|
105
105
|
},
|
106
106
|
create(context) {
|
107
|
-
const schema2 = _utilsjs.requireGraphQLSchemaFromContext.call(void 0, RULE_ID, context), siblings = _utilsjs.requireSiblingsOperations.call(void 0, RULE_ID, context), { fieldName = DEFAULT_ID_FIELD_NAME } = context.options[0] || {}, idNames = _utils.asArray.call(void 0, fieldName), selector = "
|
107
|
+
const schema2 = _utilsjs.requireGraphQLSchemaFromContext.call(void 0, RULE_ID, context), siblings = _utilsjs.requireSiblingsOperations.call(void 0, RULE_ID, context), { fieldName = DEFAULT_ID_FIELD_NAME } = context.options[0] || {}, idNames = _utils.asArray.call(void 0, fieldName), selector = "SelectionSet[parent.kind!=/(^OperationDefinition|InlineFragment)$/]", typeInfo = new (0, _graphql.TypeInfo)(schema2);
|
108
108
|
function checkFragments(node) {
|
109
109
|
for (const selection of node.selections) {
|
110
110
|
if (selection.kind !== _graphql.Kind.FRAGMENT_SPREAD)
|
package/esm/index.d.ts
CHANGED
@@ -117,7 +117,9 @@ declare const _default: {
|
|
117
117
|
'no-scalar-result-type-on-mutation': GraphQLESLintRule;
|
118
118
|
'no-typename-prefix': GraphQLESLintRule;
|
119
119
|
'no-unreachable-types': GraphQLESLintRule;
|
120
|
-
'no-unused-fields': GraphQLESLintRule
|
120
|
+
'no-unused-fields': GraphQLESLintRule<{
|
121
|
+
ignoredFieldSelectors?: string[] | undefined;
|
122
|
+
}[]>;
|
121
123
|
'relay-arguments': GraphQLESLintRule<{
|
122
124
|
includeBoth: boolean;
|
123
125
|
}[], true>;
|
package/esm/meta.js
CHANGED
package/esm/rules/index.d.ts
CHANGED
@@ -81,7 +81,9 @@ declare const rules: {
|
|
81
81
|
'no-scalar-result-type-on-mutation': GraphQLESLintRule;
|
82
82
|
'no-typename-prefix': GraphQLESLintRule;
|
83
83
|
'no-unreachable-types': GraphQLESLintRule;
|
84
|
-
'no-unused-fields': GraphQLESLintRule
|
84
|
+
'no-unused-fields': GraphQLESLintRule<{
|
85
|
+
ignoredFieldSelectors?: string[] | undefined;
|
86
|
+
}[]>;
|
85
87
|
'relay-arguments': GraphQLESLintRule<{
|
86
88
|
includeBoth: boolean;
|
87
89
|
}[], true>;
|
@@ -384,12 +384,14 @@ ${TYPES_KINDS.map((kind) => `- \`${kind}\``).join(`
|
|
384
384
|
};
|
385
385
|
}
|
386
386
|
}, checkUnderscore = (isLeading) => (node) => {
|
387
|
+
if (node.parent.kind === "Field" && node.parent.alias !== node)
|
388
|
+
return;
|
387
389
|
const suggestedName = node.value.replace(isLeading ? /^_+/ : /_+$/, "");
|
388
390
|
report(node, `${isLeading ? "Leading" : "Trailing"} underscores are not allowed`, [
|
389
391
|
suggestedName
|
390
392
|
]);
|
391
393
|
}, listeners = {};
|
392
|
-
allowLeadingUnderscore || (listeners["Name[value=/^_/]
|
394
|
+
allowLeadingUnderscore || (listeners["Name[value=/^_/]"] = checkUnderscore(!0)), allowTrailingUnderscore || (listeners["Name[value=/_$/]"] = checkUnderscore(!1));
|
393
395
|
const selectors = new Set(
|
394
396
|
[types && TYPES_KINDS, Object.keys(restOptions)].flat().filter(truthy)
|
395
397
|
);
|
@@ -1,13 +1,34 @@
|
|
1
|
+
import { FromSchema } from 'json-schema-to-ts';
|
1
2
|
import { GraphQLESLintRule } from '../../types.js';
|
2
3
|
import 'eslint';
|
3
4
|
import 'estree';
|
4
5
|
import 'graphql';
|
5
6
|
import 'graphql-config';
|
6
|
-
import 'json-schema-to-ts';
|
7
7
|
import '../../estree-converter/types.js';
|
8
8
|
import '../../siblings.js';
|
9
9
|
import '@graphql-tools/utils';
|
10
10
|
|
11
|
-
declare const
|
11
|
+
declare const schema: {
|
12
|
+
readonly type: "array";
|
13
|
+
readonly maxItems: 1;
|
14
|
+
readonly items: {
|
15
|
+
readonly type: "object";
|
16
|
+
readonly additionalProperties: false;
|
17
|
+
readonly properties: {
|
18
|
+
readonly ignoredFieldSelectors: {
|
19
|
+
readonly type: "array";
|
20
|
+
readonly uniqueItems: true;
|
21
|
+
readonly minItems: 1;
|
22
|
+
readonly description: string;
|
23
|
+
readonly items: {
|
24
|
+
readonly type: "string";
|
25
|
+
readonly pattern: "^\\[(.+)]$";
|
26
|
+
};
|
27
|
+
};
|
28
|
+
};
|
29
|
+
};
|
30
|
+
};
|
31
|
+
type RuleOptions = FromSchema<typeof schema>;
|
32
|
+
declare const rule: GraphQLESLintRule<RuleOptions>;
|
12
33
|
|
13
|
-
export { rule };
|
34
|
+
export { type RuleOptions, rule };
|
@@ -2,12 +2,105 @@ import "../../chunk-UIAXBAMD.js";
|
|
2
2
|
import { TypeInfo, visit, visitWithTypeInfo } from "graphql";
|
3
3
|
import { ModuleCache } from "../../cache.js";
|
4
4
|
import { requireGraphQLSchemaFromContext, requireSiblingsOperations } from "../../utils.js";
|
5
|
-
const RULE_ID = "no-unused-fields",
|
6
|
-
|
7
|
-
|
5
|
+
const RULE_ID = "no-unused-fields", RELAY_SCHEMA = (
|
6
|
+
/* GraphQL */
|
7
|
+
`
|
8
|
+
# Root Query Type
|
9
|
+
type Query {
|
10
|
+
user: User
|
11
|
+
}
|
12
|
+
|
13
|
+
# User Type
|
14
|
+
type User {
|
15
|
+
id: ID!
|
16
|
+
name: String!
|
17
|
+
friends(first: Int, after: String): FriendConnection!
|
18
|
+
}
|
19
|
+
|
20
|
+
# FriendConnection Type (Relay Connection)
|
21
|
+
type FriendConnection {
|
22
|
+
edges: [FriendEdge]
|
23
|
+
pageInfo: PageInfo!
|
24
|
+
}
|
25
|
+
|
26
|
+
# FriendEdge Type
|
27
|
+
type FriendEdge {
|
28
|
+
cursor: String!
|
29
|
+
node: Friend!
|
30
|
+
}
|
31
|
+
|
32
|
+
# Friend Type
|
33
|
+
type Friend {
|
34
|
+
id: ID!
|
35
|
+
name: String!
|
36
|
+
}
|
37
|
+
|
38
|
+
# PageInfo Type (Relay Pagination)
|
39
|
+
type PageInfo {
|
40
|
+
hasPreviousPage: Boolean!
|
41
|
+
hasNextPage: Boolean!
|
42
|
+
startCursor: String
|
43
|
+
endCursor: String
|
44
|
+
}
|
45
|
+
`
|
46
|
+
), RELAY_QUERY = (
|
47
|
+
/* GraphQL */
|
48
|
+
`
|
49
|
+
query {
|
50
|
+
user {
|
51
|
+
id
|
52
|
+
name
|
53
|
+
friends(first: 10) {
|
54
|
+
edges {
|
55
|
+
node {
|
56
|
+
id
|
57
|
+
name
|
58
|
+
}
|
59
|
+
}
|
60
|
+
}
|
61
|
+
}
|
62
|
+
}
|
63
|
+
`
|
64
|
+
), RELAY_DEFAULT_IGNORED_FIELD_SELECTORS = [
|
65
|
+
"[parent.name.value=PageInfo][name.value=/(endCursor|startCursor|hasNextPage|hasPreviousPage)/]",
|
66
|
+
"[parent.name.value=/Edge$/][name.value=cursor]",
|
67
|
+
"[parent.name.value=/Connection$/][name.value=pageInfo]"
|
68
|
+
], schema = {
|
69
|
+
type: "array",
|
70
|
+
maxItems: 1,
|
71
|
+
items: {
|
72
|
+
type: "object",
|
73
|
+
additionalProperties: !1,
|
74
|
+
properties: {
|
75
|
+
ignoredFieldSelectors: {
|
76
|
+
type: "array",
|
77
|
+
uniqueItems: !0,
|
78
|
+
minItems: 1,
|
79
|
+
description: [
|
80
|
+
"Fields that will be ignored and are allowed to be unused.",
|
81
|
+
"",
|
82
|
+
"E.g. The following selector will ignore all the relay pagination fields for every connection exposed in the schema:",
|
83
|
+
"```json",
|
84
|
+
JSON.stringify(RELAY_DEFAULT_IGNORED_FIELD_SELECTORS, null, 2),
|
85
|
+
"```",
|
86
|
+
"",
|
87
|
+
"> These fields are defined by ESLint [`selectors`](https://eslint.org/docs/developer-guide/selectors).",
|
88
|
+
"> Paste or drop code into the editor in [ASTExplorer](https://astexplorer.net) and inspect the generated AST to compose your selector."
|
89
|
+
].join(`
|
90
|
+
`),
|
91
|
+
items: {
|
92
|
+
type: "string",
|
93
|
+
pattern: "^\\[(.+)]$"
|
94
|
+
}
|
95
|
+
}
|
96
|
+
}
|
97
|
+
}
|
98
|
+
}, usedFieldsCache = new ModuleCache();
|
99
|
+
function getUsedFields(schema2, operations) {
|
100
|
+
const cachedValue = usedFieldsCache.get(schema2);
|
8
101
|
if (process.env.NODE_ENV !== "test" && cachedValue)
|
9
102
|
return cachedValue;
|
10
|
-
const usedFields = /* @__PURE__ */ Object.create(null), typeInfo = new TypeInfo(
|
103
|
+
const usedFields = /* @__PURE__ */ Object.create(null), typeInfo = new TypeInfo(schema2), visitor = visitWithTypeInfo(typeInfo, {
|
11
104
|
Field(node) {
|
12
105
|
if (!typeInfo.getFieldDef())
|
13
106
|
return !1;
|
@@ -17,7 +110,7 @@ function getUsedFields(schema, operations) {
|
|
17
110
|
}), allDocuments = [...operations.getOperations(), ...operations.getFragments()];
|
18
111
|
for (const { document } of allDocuments)
|
19
112
|
visit(document, visitor);
|
20
|
-
return usedFieldsCache.set(
|
113
|
+
return usedFieldsCache.set(schema2, usedFields), usedFields;
|
21
114
|
}
|
22
115
|
const rule = {
|
23
116
|
meta: {
|
@@ -79,17 +172,34 @@ const rule = {
|
|
79
172
|
}
|
80
173
|
`
|
81
174
|
)
|
175
|
+
},
|
176
|
+
{
|
177
|
+
title: "Correct (ignoring fields)",
|
178
|
+
usage: [{ ignoredFieldSelectors: RELAY_DEFAULT_IGNORED_FIELD_SELECTORS }],
|
179
|
+
code: (
|
180
|
+
/* GraphQL */
|
181
|
+
`
|
182
|
+
### 1\uFE0F\u20E3 YOUR SCHEMA
|
183
|
+
${RELAY_SCHEMA}
|
184
|
+
|
185
|
+
### 2\uFE0F\u20E3 YOUR QUERY
|
186
|
+
${RELAY_QUERY}
|
187
|
+
`
|
188
|
+
)
|
82
189
|
}
|
83
190
|
]
|
84
191
|
},
|
85
192
|
type: "suggestion",
|
86
|
-
schema
|
193
|
+
schema,
|
87
194
|
hasSuggestions: !0
|
88
195
|
},
|
89
196
|
create(context) {
|
90
|
-
const
|
197
|
+
const schema2 = requireGraphQLSchemaFromContext(RULE_ID, context), siblingsOperations = requireSiblingsOperations(RULE_ID, context), usedFields = getUsedFields(schema2, siblingsOperations), { ignoredFieldSelectors } = context.options[0] || {};
|
91
198
|
return {
|
92
|
-
|
199
|
+
[(ignoredFieldSelectors || []).reduce(
|
200
|
+
(acc, selector2) => `${acc}:not(${selector2})`,
|
201
|
+
"FieldDefinition"
|
202
|
+
)](node) {
|
93
203
|
const fieldName = node.name.value, parentTypeName = node.parent.name.value;
|
94
204
|
usedFields[parentTypeName]?.has(fieldName) || context.report({
|
95
205
|
node: node.name,
|
@@ -104,7 +104,7 @@ Include it in your selection set{{ addition }}.`
|
|
104
104
|
schema
|
105
105
|
},
|
106
106
|
create(context) {
|
107
|
-
const schema2 = requireGraphQLSchemaFromContext(RULE_ID, context), siblings = requireSiblingsOperations(RULE_ID, context), { fieldName = DEFAULT_ID_FIELD_NAME } = context.options[0] || {}, idNames = asArray(fieldName), selector = "
|
107
|
+
const schema2 = requireGraphQLSchemaFromContext(RULE_ID, context), siblings = requireSiblingsOperations(RULE_ID, context), { fieldName = DEFAULT_ID_FIELD_NAME } = context.options[0] || {}, idNames = asArray(fieldName), selector = "SelectionSet[parent.kind!=/(^OperationDefinition|InlineFragment)$/]", typeInfo = new TypeInfo(schema2);
|
108
108
|
function checkFragments(node) {
|
109
109
|
for (const selection of node.selections) {
|
110
110
|
if (selection.kind !== Kind.FRAGMENT_SPREAD)
|
package/index.browser.js
CHANGED
@@ -341,8 +341,8 @@ function convertLocation(location) {
|
|
341
341
|
}
|
342
342
|
|
343
343
|
// src/estree-converter/converter.ts
|
344
|
-
function convertToESTree(node,
|
345
|
-
let typeInfo =
|
344
|
+
function convertToESTree(node, schema16) {
|
345
|
+
let typeInfo = schema16 && new TypeInfo(schema16), visitor = {
|
346
346
|
leave(node2, key, parent) {
|
347
347
|
let leadingComments = "description" in node2 && node2.description ? [
|
348
348
|
{
|
@@ -408,12 +408,12 @@ function requireSiblingsOperations(ruleId, context) {
|
|
408
408
|
return siblingOperations;
|
409
409
|
}
|
410
410
|
function requireGraphQLSchemaFromContext(ruleId, context) {
|
411
|
-
let { schema:
|
412
|
-
if (!
|
411
|
+
let { schema: schema16 } = context.sourceCode.parserServices;
|
412
|
+
if (!schema16)
|
413
413
|
throw new Error(
|
414
414
|
`Rule \`${ruleId}\` requires graphql-config \`schema\` field to be set and loaded. See https://the-guild.dev/graphql/config/docs/user/schema for more info`
|
415
415
|
);
|
416
|
-
return
|
416
|
+
return schema16;
|
417
417
|
}
|
418
418
|
var chalk = {
|
419
419
|
red: (str) => `\x1B[31m${str}\x1B[39m`,
|
@@ -635,7 +635,7 @@ function parseForESLint(code, options) {
|
|
635
635
|
`\`parserOptions.${key}\` was removed in graphql-eslint@4. Use physical graphql-config for setting schema and documents or \`parserOptions.graphQLConfig\` for programmatic usage.`
|
636
636
|
);
|
637
637
|
try {
|
638
|
-
let { filePath } = options, { document } = parseGraphQLSDL(filePath, code, { noLocation: !1 }), project,
|
638
|
+
let { filePath } = options, { document } = parseGraphQLSDL(filePath, code, { noLocation: !1 }), project, schema16, documents;
|
639
639
|
documents = [
|
640
640
|
parseGraphQLSDL(
|
641
641
|
"operation.graphql",
|
@@ -644,14 +644,14 @@ function parseForESLint(code, options) {
|
|
644
644
|
)
|
645
645
|
];
|
646
646
|
try {
|
647
|
-
|
647
|
+
schema16 = buildSchema(options.graphQLConfig.schema);
|
648
648
|
} catch (error) {
|
649
649
|
throw error instanceof Error && (error.message = `Error while loading schema: ${error.message}`), error;
|
650
650
|
}
|
651
|
-
let rootTree = convertToESTree(document,
|
651
|
+
let rootTree = convertToESTree(document, schema16);
|
652
652
|
return {
|
653
653
|
services: {
|
654
|
-
schema:
|
654
|
+
schema: schema16,
|
655
655
|
siblingOperations: getSiblings(documents)
|
656
656
|
},
|
657
657
|
ast: {
|
@@ -1118,14 +1118,14 @@ import {
|
|
1118
1118
|
import { validateSDL } from "graphql/validation/validate.js";
|
1119
1119
|
function validateDocument({
|
1120
1120
|
context,
|
1121
|
-
schema:
|
1121
|
+
schema: schema16 = null,
|
1122
1122
|
documentNode,
|
1123
1123
|
rule: rule35,
|
1124
1124
|
hasDidYouMeanSuggestions
|
1125
1125
|
}) {
|
1126
1126
|
if (documentNode.definitions.length !== 0)
|
1127
1127
|
try {
|
1128
|
-
let validationErrors =
|
1128
|
+
let validationErrors = schema16 ? validate(schema16, documentNode, [rule35]) : validateSDL(documentNode, null, [rule35]);
|
1129
1129
|
for (let error of validationErrors) {
|
1130
1130
|
let { line, column } = error.locations[0], sourceCode = context.getSourceCode(), { tokens } = sourceCode.ast, token = tokens.find(
|
1131
1131
|
(token2) => token2.loc.start.line === line && token2.loc.start.column === column - 1
|
@@ -1191,7 +1191,7 @@ var getFragmentDefsAndFragmentSpreads = (node) => {
|
|
1191
1191
|
ruleId,
|
1192
1192
|
rule: rule35,
|
1193
1193
|
getDocumentNode,
|
1194
|
-
schema:
|
1194
|
+
schema: schema16 = [],
|
1195
1195
|
hasDidYouMeanSuggestions
|
1196
1196
|
}, docs) => ({
|
1197
1197
|
[ruleId]: {
|
@@ -1204,16 +1204,16 @@ var getFragmentDefsAndFragmentSpreads = (node) => {
|
|
1204
1204
|
description: `${docs.description}
|
1205
1205
|
> This rule is a wrapper around a \`graphql-js\` validation function.`
|
1206
1206
|
},
|
1207
|
-
schema:
|
1207
|
+
schema: schema16,
|
1208
1208
|
hasSuggestions: hasDidYouMeanSuggestions
|
1209
1209
|
},
|
1210
1210
|
create(context) {
|
1211
1211
|
return {
|
1212
1212
|
Document(node) {
|
1213
|
-
let
|
1213
|
+
let schema17 = docs.requiresSchema ? requireGraphQLSchemaFromContext(ruleId, context) : null, documentNode = getDocumentNode ? getDocumentNode({ ruleId, context, node: node.rawNode() }) : node.rawNode();
|
1214
1214
|
validateDocument({
|
1215
1215
|
context,
|
1216
|
-
schema:
|
1216
|
+
schema: schema17,
|
1217
1217
|
documentNode,
|
1218
1218
|
rule: rule35,
|
1219
1219
|
hasDidYouMeanSuggestions
|
@@ -2509,12 +2509,14 @@ ${TYPES_KINDS.map((kind) => `- \`${kind}\``).join(`
|
|
2509
2509
|
};
|
2510
2510
|
}
|
2511
2511
|
}, checkUnderscore = (isLeading) => (node) => {
|
2512
|
+
if (node.parent.kind === "Field" && node.parent.alias !== node)
|
2513
|
+
return;
|
2512
2514
|
let suggestedName = node.value.replace(isLeading ? /^_+/ : /_+$/, "");
|
2513
2515
|
report(node, `${isLeading ? "Leading" : "Trailing"} underscores are not allowed`, [
|
2514
2516
|
suggestedName
|
2515
2517
|
]);
|
2516
2518
|
}, listeners = {};
|
2517
|
-
allowLeadingUnderscore || (listeners["Name[value=/^_/]
|
2519
|
+
allowLeadingUnderscore || (listeners["Name[value=/^_/]"] = checkUnderscore(!0)), allowTrailingUnderscore || (listeners["Name[value=/_$/]"] = checkUnderscore(!1));
|
2518
2520
|
let selectors = new Set(
|
2519
2521
|
[types && TYPES_KINDS, Object.keys(restOptions)].flat().filter(truthy)
|
2520
2522
|
);
|
@@ -3069,9 +3071,9 @@ var schema7 = {
|
|
3069
3071
|
schema: schema7
|
3070
3072
|
},
|
3071
3073
|
create(context) {
|
3072
|
-
let
|
3073
|
-
disallow.has("mutation") &&
|
3074
|
-
disallow.has("subscription") &&
|
3074
|
+
let schema16 = requireGraphQLSchemaFromContext("no-root-type", context), disallow = new Set(context.options[0].disallow), rootTypeNames = [
|
3075
|
+
disallow.has("mutation") && schema16.getMutationType(),
|
3076
|
+
disallow.has("subscription") && schema16.getSubscriptionType()
|
3075
3077
|
].filter(truthy).map((type) => type.name).join("|");
|
3076
3078
|
return rootTypeNames ? {
|
3077
3079
|
[`:matches(ObjectTypeDefinition, ObjectTypeExtension) > .name[value=/^(${rootTypeNames})$/]`](node) {
|
@@ -3130,13 +3132,13 @@ var RULE_ID8 = "no-scalar-result-type-on-mutation", rule13 = {
|
|
3130
3132
|
schema: []
|
3131
3133
|
},
|
3132
3134
|
create(context) {
|
3133
|
-
let
|
3135
|
+
let schema16 = requireGraphQLSchemaFromContext(RULE_ID8, context), mutationType = schema16.getMutationType();
|
3134
3136
|
return mutationType ? {
|
3135
3137
|
[[
|
3136
3138
|
`:matches(ObjectTypeDefinition, ObjectTypeExtension)[name.value=${mutationType.name}]`,
|
3137
3139
|
"> FieldDefinition > .gqlType Name"
|
3138
3140
|
].join(" ")](node) {
|
3139
|
-
let typeName = node.value, graphQLType =
|
3141
|
+
let typeName = node.value, graphQLType = schema16.getType(typeName);
|
3140
3142
|
if (isScalarType(graphQLType)) {
|
3141
3143
|
let fieldDef = node.parent;
|
3142
3144
|
for (; fieldDef.kind !== Kind12.FIELD_DEFINITION; )
|
@@ -3258,8 +3260,8 @@ var RULE_ID9 = "no-unreachable-types", KINDS = [
|
|
3258
3260
|
DirectiveLocation.INLINE_FRAGMENT,
|
3259
3261
|
DirectiveLocation.VARIABLE_DEFINITION
|
3260
3262
|
]);
|
3261
|
-
function getReachableTypes(
|
3262
|
-
let cachedValue = reachableTypesCache.get(
|
3263
|
+
function getReachableTypes(schema16) {
|
3264
|
+
let cachedValue = reachableTypesCache.get(schema16);
|
3263
3265
|
if (cachedValue)
|
3264
3266
|
return cachedValue;
|
3265
3267
|
let reachableTypes = /* @__PURE__ */ new Set(), collect = (node) => {
|
@@ -3267,9 +3269,9 @@ function getReachableTypes(schema15) {
|
|
3267
3269
|
if (reachableTypes.has(typeName))
|
3268
3270
|
return;
|
3269
3271
|
reachableTypes.add(typeName);
|
3270
|
-
let type =
|
3272
|
+
let type = schema16.getType(typeName) || schema16.getDirective(typeName);
|
3271
3273
|
if (isInterfaceType(type)) {
|
3272
|
-
let { objects, interfaces } =
|
3274
|
+
let { objects, interfaces } = schema16.getImplementations(type);
|
3273
3275
|
for (let { astNode } of [...objects, ...interfaces])
|
3274
3276
|
visit5(astNode, visitor);
|
3275
3277
|
} else type?.astNode && visit5(type.astNode, visitor);
|
@@ -3283,14 +3285,14 @@ function getReachableTypes(schema15) {
|
|
3283
3285
|
NamedType: collect
|
3284
3286
|
};
|
3285
3287
|
for (let type of [
|
3286
|
-
|
3288
|
+
schema16,
|
3287
3289
|
// visiting SchemaDefinition node
|
3288
|
-
|
3289
|
-
|
3290
|
-
|
3290
|
+
schema16.getQueryType(),
|
3291
|
+
schema16.getMutationType(),
|
3292
|
+
schema16.getSubscriptionType()
|
3291
3293
|
])
|
3292
3294
|
type?.astNode && visit5(type.astNode, visitor);
|
3293
|
-
for (let node of
|
3295
|
+
for (let node of schema16.getDirectives())
|
3294
3296
|
if (node.locations.some((location) => RequestDirectiveLocations.has(location))) {
|
3295
3297
|
reachableTypes.add(node.name);
|
3296
3298
|
for (let arg of node.args) {
|
@@ -3298,7 +3300,7 @@ function getReachableTypes(schema15) {
|
|
3298
3300
|
argTypeName && reachableTypes.add(argTypeName);
|
3299
3301
|
}
|
3300
3302
|
}
|
3301
|
-
return reachableTypesCache.set(
|
3303
|
+
return reachableTypesCache.set(schema16, reachableTypes), reachableTypes;
|
3302
3304
|
}
|
3303
3305
|
var rule15 = {
|
3304
3306
|
meta: {
|
@@ -3351,7 +3353,7 @@ var rule15 = {
|
|
3351
3353
|
hasSuggestions: !0
|
3352
3354
|
},
|
3353
3355
|
create(context) {
|
3354
|
-
let
|
3356
|
+
let schema16 = requireGraphQLSchemaFromContext(RULE_ID9, context), reachableTypes = getReachableTypes(schema16);
|
3355
3357
|
return {
|
3356
3358
|
[`:matches(${KINDS}) > .name`](node) {
|
3357
3359
|
let typeName = node.value;
|
@@ -3379,12 +3381,105 @@ var rule15 = {
|
|
3379
3381
|
|
3380
3382
|
// src/rules/no-unused-fields/index.ts
|
3381
3383
|
import { TypeInfo as TypeInfo2, visit as visit6, visitWithTypeInfo as visitWithTypeInfo2 } from "graphql";
|
3382
|
-
var RULE_ID10 = "no-unused-fields",
|
3383
|
-
|
3384
|
-
|
3384
|
+
var RULE_ID10 = "no-unused-fields", RELAY_SCHEMA = (
|
3385
|
+
/* GraphQL */
|
3386
|
+
`
|
3387
|
+
# Root Query Type
|
3388
|
+
type Query {
|
3389
|
+
user: User
|
3390
|
+
}
|
3391
|
+
|
3392
|
+
# User Type
|
3393
|
+
type User {
|
3394
|
+
id: ID!
|
3395
|
+
name: String!
|
3396
|
+
friends(first: Int, after: String): FriendConnection!
|
3397
|
+
}
|
3398
|
+
|
3399
|
+
# FriendConnection Type (Relay Connection)
|
3400
|
+
type FriendConnection {
|
3401
|
+
edges: [FriendEdge]
|
3402
|
+
pageInfo: PageInfo!
|
3403
|
+
}
|
3404
|
+
|
3405
|
+
# FriendEdge Type
|
3406
|
+
type FriendEdge {
|
3407
|
+
cursor: String!
|
3408
|
+
node: Friend!
|
3409
|
+
}
|
3410
|
+
|
3411
|
+
# Friend Type
|
3412
|
+
type Friend {
|
3413
|
+
id: ID!
|
3414
|
+
name: String!
|
3415
|
+
}
|
3416
|
+
|
3417
|
+
# PageInfo Type (Relay Pagination)
|
3418
|
+
type PageInfo {
|
3419
|
+
hasPreviousPage: Boolean!
|
3420
|
+
hasNextPage: Boolean!
|
3421
|
+
startCursor: String
|
3422
|
+
endCursor: String
|
3423
|
+
}
|
3424
|
+
`
|
3425
|
+
), RELAY_QUERY = (
|
3426
|
+
/* GraphQL */
|
3427
|
+
`
|
3428
|
+
query {
|
3429
|
+
user {
|
3430
|
+
id
|
3431
|
+
name
|
3432
|
+
friends(first: 10) {
|
3433
|
+
edges {
|
3434
|
+
node {
|
3435
|
+
id
|
3436
|
+
name
|
3437
|
+
}
|
3438
|
+
}
|
3439
|
+
}
|
3440
|
+
}
|
3441
|
+
}
|
3442
|
+
`
|
3443
|
+
), RELAY_DEFAULT_IGNORED_FIELD_SELECTORS = [
|
3444
|
+
"[parent.name.value=PageInfo][name.value=/(endCursor|startCursor|hasNextPage|hasPreviousPage)/]",
|
3445
|
+
"[parent.name.value=/Edge$/][name.value=cursor]",
|
3446
|
+
"[parent.name.value=/Connection$/][name.value=pageInfo]"
|
3447
|
+
], schema8 = {
|
3448
|
+
type: "array",
|
3449
|
+
maxItems: 1,
|
3450
|
+
items: {
|
3451
|
+
type: "object",
|
3452
|
+
additionalProperties: !1,
|
3453
|
+
properties: {
|
3454
|
+
ignoredFieldSelectors: {
|
3455
|
+
type: "array",
|
3456
|
+
uniqueItems: !0,
|
3457
|
+
minItems: 1,
|
3458
|
+
description: [
|
3459
|
+
"Fields that will be ignored and are allowed to be unused.",
|
3460
|
+
"",
|
3461
|
+
"E.g. The following selector will ignore all the relay pagination fields for every connection exposed in the schema:",
|
3462
|
+
"```json",
|
3463
|
+
JSON.stringify(RELAY_DEFAULT_IGNORED_FIELD_SELECTORS, null, 2),
|
3464
|
+
"```",
|
3465
|
+
"",
|
3466
|
+
"> These fields are defined by ESLint [`selectors`](https://eslint.org/docs/developer-guide/selectors).",
|
3467
|
+
"> Paste or drop code into the editor in [ASTExplorer](https://astexplorer.net) and inspect the generated AST to compose your selector."
|
3468
|
+
].join(`
|
3469
|
+
`),
|
3470
|
+
items: {
|
3471
|
+
type: "string",
|
3472
|
+
pattern: "^\\[(.+)]$"
|
3473
|
+
}
|
3474
|
+
}
|
3475
|
+
}
|
3476
|
+
}
|
3477
|
+
}, usedFieldsCache = new ModuleCache();
|
3478
|
+
function getUsedFields(schema16, operations) {
|
3479
|
+
let cachedValue = usedFieldsCache.get(schema16);
|
3385
3480
|
if (cachedValue)
|
3386
3481
|
return cachedValue;
|
3387
|
-
let usedFields = /* @__PURE__ */ Object.create(null), typeInfo = new TypeInfo2(
|
3482
|
+
let usedFields = /* @__PURE__ */ Object.create(null), typeInfo = new TypeInfo2(schema16), visitor = visitWithTypeInfo2(typeInfo, {
|
3388
3483
|
Field(node) {
|
3389
3484
|
if (!typeInfo.getFieldDef())
|
3390
3485
|
return !1;
|
@@ -3394,7 +3489,7 @@ function getUsedFields(schema15, operations) {
|
|
3394
3489
|
}), allDocuments = [...operations.getOperations(), ...operations.getFragments()];
|
3395
3490
|
for (let { document } of allDocuments)
|
3396
3491
|
visit6(document, visitor);
|
3397
|
-
return usedFieldsCache.set(
|
3492
|
+
return usedFieldsCache.set(schema16, usedFields), usedFields;
|
3398
3493
|
}
|
3399
3494
|
var rule16 = {
|
3400
3495
|
meta: {
|
@@ -3456,17 +3551,34 @@ var rule16 = {
|
|
3456
3551
|
}
|
3457
3552
|
`
|
3458
3553
|
)
|
3554
|
+
},
|
3555
|
+
{
|
3556
|
+
title: "Correct (ignoring fields)",
|
3557
|
+
usage: [{ ignoredFieldSelectors: RELAY_DEFAULT_IGNORED_FIELD_SELECTORS }],
|
3558
|
+
code: (
|
3559
|
+
/* GraphQL */
|
3560
|
+
`
|
3561
|
+
### 1\uFE0F\u20E3 YOUR SCHEMA
|
3562
|
+
${RELAY_SCHEMA}
|
3563
|
+
|
3564
|
+
### 2\uFE0F\u20E3 YOUR QUERY
|
3565
|
+
${RELAY_QUERY}
|
3566
|
+
`
|
3567
|
+
)
|
3459
3568
|
}
|
3460
3569
|
]
|
3461
3570
|
},
|
3462
3571
|
type: "suggestion",
|
3463
|
-
schema:
|
3572
|
+
schema: schema8,
|
3464
3573
|
hasSuggestions: !0
|
3465
3574
|
},
|
3466
3575
|
create(context) {
|
3467
|
-
let
|
3576
|
+
let schema16 = requireGraphQLSchemaFromContext(RULE_ID10, context), siblingsOperations = requireSiblingsOperations(RULE_ID10, context), usedFields = getUsedFields(schema16, siblingsOperations), { ignoredFieldSelectors } = context.options[0] || {};
|
3468
3577
|
return {
|
3469
|
-
|
3578
|
+
[(ignoredFieldSelectors || []).reduce(
|
3579
|
+
(acc, selector2) => `${acc}:not(${selector2})`,
|
3580
|
+
"FieldDefinition"
|
3581
|
+
)](node) {
|
3470
3582
|
let fieldName = node.name.value, parentTypeName = node.parent.name.value;
|
3471
3583
|
usedFields[parentTypeName]?.has(fieldName) || context.report({
|
3472
3584
|
node: node.name,
|
@@ -3489,7 +3601,7 @@ var rule16 = {
|
|
3489
3601
|
|
3490
3602
|
// src/rules/relay-arguments/index.ts
|
3491
3603
|
import { isScalarType as isScalarType2, Kind as Kind14 } from "graphql";
|
3492
|
-
var RULE_ID11 = "relay-arguments", MISSING_ARGUMENTS = "MISSING_ARGUMENTS",
|
3604
|
+
var RULE_ID11 = "relay-arguments", MISSING_ARGUMENTS = "MISSING_ARGUMENTS", schema9 = {
|
3493
3605
|
type: "array",
|
3494
3606
|
maxItems: 1,
|
3495
3607
|
items: {
|
@@ -3555,10 +3667,10 @@ var RULE_ID11 = "relay-arguments", MISSING_ARGUMENTS = "MISSING_ARGUMENTS", sche
|
|
3555
3667
|
messages: {
|
3556
3668
|
[MISSING_ARGUMENTS]: "A field that returns a Connection type must include forward pagination arguments (`first` and `after`), backward pagination arguments (`last` and `before`), or both."
|
3557
3669
|
},
|
3558
|
-
schema:
|
3670
|
+
schema: schema9
|
3559
3671
|
},
|
3560
3672
|
create(context) {
|
3561
|
-
let
|
3673
|
+
let schema16 = requireGraphQLSchemaFromContext(RULE_ID11, context), { includeBoth = !0 } = context.options[0] || {};
|
3562
3674
|
return {
|
3563
3675
|
"FieldDefinition > .gqlType Name[value=/Connection$/]"(node) {
|
3564
3676
|
let fieldNode = node.parent;
|
@@ -3576,7 +3688,7 @@ var RULE_ID11 = "relay-arguments", MISSING_ARGUMENTS = "MISSING_ARGUMENTS", sche
|
|
3576
3688
|
}
|
3577
3689
|
function checkField(typeName, argumentName) {
|
3578
3690
|
let argument = args[argumentName], hasArgument = !!argument, type = argument;
|
3579
|
-
if (hasArgument && type.gqlType.kind === Kind14.NON_NULL_TYPE && (type = type.gqlType), !(hasArgument && type.gqlType.kind === Kind14.NAMED_TYPE && (type.gqlType.name.value === typeName || typeName === "String" && isScalarType2(
|
3691
|
+
if (hasArgument && type.gqlType.kind === Kind14.NON_NULL_TYPE && (type = type.gqlType), !(hasArgument && type.gqlType.kind === Kind14.NAMED_TYPE && (type.gqlType.name.value === typeName || typeName === "String" && isScalarType2(schema16.getType(type.gqlType.name.value))))) {
|
3580
3692
|
let returnType = typeName === "String" ? "String or Scalar" : typeName;
|
3581
3693
|
context.report({
|
3582
3694
|
node: (argument || fieldNode).name,
|
@@ -3686,7 +3798,7 @@ import {
|
|
3686
3798
|
} from "graphql";
|
3687
3799
|
import { getDocumentNodeFromSchema } from "@graphql-tools/utils";
|
3688
3800
|
var RULE_ID12 = "relay-edge-types", MESSAGE_MUST_BE_OBJECT_TYPE = "MESSAGE_MUST_BE_OBJECT_TYPE", MESSAGE_MISSING_EDGE_SUFFIX = "MESSAGE_MISSING_EDGE_SUFFIX", MESSAGE_LIST_TYPE_ONLY_EDGE_TYPE = "MESSAGE_LIST_TYPE_ONLY_EDGE_TYPE", MESSAGE_SHOULD_IMPLEMENTS_NODE = "MESSAGE_SHOULD_IMPLEMENTS_NODE", edgeTypesCache;
|
3689
|
-
function getEdgeTypes(
|
3801
|
+
function getEdgeTypes(schema16) {
|
3690
3802
|
if (edgeTypesCache)
|
3691
3803
|
return edgeTypesCache;
|
3692
3804
|
let edgeTypes = /* @__PURE__ */ new Set(), visitor = {
|
@@ -3695,14 +3807,14 @@ function getEdgeTypes(schema15) {
|
|
3695
3807
|
return;
|
3696
3808
|
let edges = node.fields?.find((field) => field.name.value === "edges");
|
3697
3809
|
if (edges) {
|
3698
|
-
let edgesTypeName = getTypeName(edges), edgesType =
|
3810
|
+
let edgesTypeName = getTypeName(edges), edgesType = schema16.getType(edgesTypeName);
|
3699
3811
|
isObjectType2(edgesType) && edgeTypes.add(edgesTypeName);
|
3700
3812
|
}
|
3701
3813
|
}
|
3702
|
-
}, astNode = getDocumentNodeFromSchema(
|
3814
|
+
}, astNode = getDocumentNodeFromSchema(schema16);
|
3703
3815
|
return visit7(astNode, visitor), edgeTypesCache = edgeTypes, edgeTypesCache;
|
3704
3816
|
}
|
3705
|
-
var
|
3817
|
+
var schema10 = {
|
3706
3818
|
type: "array",
|
3707
3819
|
maxItems: 1,
|
3708
3820
|
items: {
|
@@ -3768,10 +3880,10 @@ var schema9 = {
|
|
3768
3880
|
[MESSAGE_LIST_TYPE_ONLY_EDGE_TYPE]: "A list type should only wrap an edge type.",
|
3769
3881
|
[MESSAGE_SHOULD_IMPLEMENTS_NODE]: "Edge type's field `node` must implement `Node` interface."
|
3770
3882
|
},
|
3771
|
-
schema:
|
3883
|
+
schema: schema10
|
3772
3884
|
},
|
3773
3885
|
create(context) {
|
3774
|
-
let
|
3886
|
+
let schema16 = requireGraphQLSchemaFromContext(RULE_ID12, context), edgeTypes = getEdgeTypes(schema16), options = {
|
3775
3887
|
withEdgeSuffix: !0,
|
3776
3888
|
shouldImplementNode: !0,
|
3777
3889
|
listTypeCanWrapOnlyEdgeType: !0,
|
@@ -3786,7 +3898,7 @@ var schema9 = {
|
|
3786
3898
|
else if (!isNamedOrNonNullNamed(nodeField.gqlType))
|
3787
3899
|
context.report({ node: nodeField.name, message: `Field \`node\` must ${message}` });
|
3788
3900
|
else if (options.shouldImplementNode) {
|
3789
|
-
let nodeReturnTypeName = getTypeName(nodeField.gqlType.rawNode()), type =
|
3901
|
+
let nodeReturnTypeName = getTypeName(nodeField.gqlType.rawNode()), type = schema16.getType(nodeReturnTypeName);
|
3790
3902
|
if (!isObjectType2(type))
|
3791
3903
|
return;
|
3792
3904
|
type.astNode.interfaces?.some((n) => n.name.value === "Node") || context.report({ node: node.name, messageId: MESSAGE_SHOULD_IMPLEMENTS_NODE });
|
@@ -3801,10 +3913,10 @@ var schema9 = {
|
|
3801
3913
|
return;
|
3802
3914
|
}
|
3803
3915
|
let typeName = getTypeName(cursorField.rawNode());
|
3804
|
-
(!isNamedOrNonNullNamed(cursorField.gqlType) || typeName !== "String" && !isScalarType3(
|
3916
|
+
(!isNamedOrNonNullNamed(cursorField.gqlType) || typeName !== "String" && !isScalarType3(schema16.getType(typeName))) && context.report({ node: cursorField.name, message: `Field \`cursor\` must ${message}` });
|
3805
3917
|
}, listeners = {
|
3806
3918
|
":matches(ObjectTypeDefinition, ObjectTypeExtension)[name.value=/Connection$/] > FieldDefinition[name.value=edges] > .gqlType Name"(node) {
|
3807
|
-
let type =
|
3919
|
+
let type = schema16.getType(node.value);
|
3808
3920
|
isObjectType2(type) || context.report({ node, messageId: MESSAGE_MUST_BE_OBJECT_TYPE });
|
3809
3921
|
},
|
3810
3922
|
":matches(ObjectTypeDefinition, ObjectTypeExtension)"(node) {
|
@@ -3863,8 +3975,8 @@ var RULE_ID13 = "relay-page-info", MESSAGE_MUST_EXIST = "MESSAGE_MUST_EXIST", ME
|
|
3863
3975
|
schema: []
|
3864
3976
|
},
|
3865
3977
|
create(context) {
|
3866
|
-
let
|
3867
|
-
return hasPageInfoChecked || (
|
3978
|
+
let schema16 = requireGraphQLSchemaFromContext(RULE_ID13, context);
|
3979
|
+
return hasPageInfoChecked || (schema16.getType("PageInfo") || context.report({
|
3868
3980
|
loc: REPORT_ON_FIRST_CHARACTER,
|
3869
3981
|
messageId: MESSAGE_MUST_EXIST
|
3870
3982
|
}), hasPageInfoChecked = !0), {
|
@@ -3878,7 +3990,7 @@ var RULE_ID13 = "relay-page-info", MESSAGE_MUST_EXIST = "MESSAGE_MUST_EXIST", ME
|
|
3878
3990
|
let field = fieldMap[fieldName], isAllowedType = !1;
|
3879
3991
|
if (field) {
|
3880
3992
|
let type = field.gqlType;
|
3881
|
-
typeName === "Boolean" ? isAllowedType = type.kind === Kind17.NON_NULL_TYPE && type.gqlType.kind === Kind17.NAMED_TYPE && type.gqlType.name.value === "Boolean" : type.kind === Kind17.NAMED_TYPE && (isAllowedType = type.name.value === "String" || isScalarType4(
|
3993
|
+
typeName === "Boolean" ? isAllowedType = type.kind === Kind17.NON_NULL_TYPE && type.gqlType.kind === Kind17.NAMED_TYPE && type.gqlType.name.value === "Boolean" : type.kind === Kind17.NAMED_TYPE && (isAllowedType = type.name.value === "String" || isScalarType4(schema16.getType(type.name.value)));
|
3882
3994
|
}
|
3883
3995
|
if (!isAllowedType) {
|
3884
3996
|
let returnType = typeName === "Boolean" ? "non-null Boolean" : "either String or Scalar, which can be null if there are no results";
|
@@ -3895,7 +4007,7 @@ var RULE_ID13 = "relay-page-info", MESSAGE_MUST_EXIST = "MESSAGE_MUST_EXIST", ME
|
|
3895
4007
|
};
|
3896
4008
|
|
3897
4009
|
// src/rules/require-deprecation-date/index.ts
|
3898
|
-
var DATE_REGEX = /^\d{2}\/\d{2}\/\d{4}$/, MESSAGE_REQUIRE_DATE = "MESSAGE_REQUIRE_DATE", MESSAGE_INVALID_FORMAT = "MESSAGE_INVALID_FORMAT", MESSAGE_INVALID_DATE = "MESSAGE_INVALID_DATE", MESSAGE_CAN_BE_REMOVED = "MESSAGE_CAN_BE_REMOVED",
|
4010
|
+
var DATE_REGEX = /^\d{2}\/\d{2}\/\d{4}$/, MESSAGE_REQUIRE_DATE = "MESSAGE_REQUIRE_DATE", MESSAGE_INVALID_FORMAT = "MESSAGE_INVALID_FORMAT", MESSAGE_INVALID_DATE = "MESSAGE_INVALID_DATE", MESSAGE_CAN_BE_REMOVED = "MESSAGE_CAN_BE_REMOVED", schema11 = {
|
3899
4011
|
type: "array",
|
3900
4012
|
maxItems: 1,
|
3901
4013
|
items: {
|
@@ -3961,7 +4073,7 @@ var DATE_REGEX = /^\d{2}\/\d{2}\/\d{4}$/, MESSAGE_REQUIRE_DATE = "MESSAGE_REQUIR
|
|
3961
4073
|
[MESSAGE_INVALID_DATE]: 'Invalid "{{ deletionDate }}" deletion date for {{ nodeName }}',
|
3962
4074
|
[MESSAGE_CAN_BE_REMOVED]: "{{ nodeName }} \u0441an be removed"
|
3963
4075
|
},
|
3964
|
-
schema:
|
4076
|
+
schema: schema11
|
3965
4077
|
},
|
3966
4078
|
create(context) {
|
3967
4079
|
return {
|
@@ -4091,7 +4203,7 @@ var RULE_ID14 = "require-description", ALLOWED_KINDS2 = [
|
|
4091
4203
|
Kind18.INPUT_VALUE_DEFINITION,
|
4092
4204
|
Kind18.ENUM_VALUE_DEFINITION,
|
4093
4205
|
Kind18.OPERATION_DEFINITION
|
4094
|
-
],
|
4206
|
+
], schema12 = {
|
4095
4207
|
type: "array",
|
4096
4208
|
minItems: 1,
|
4097
4209
|
maxItems: 1,
|
@@ -4199,14 +4311,14 @@ ${TYPES_KINDS.map((kind) => `- \`${kind}\``).join(`
|
|
4199
4311
|
messages: {
|
4200
4312
|
[RULE_ID14]: "Description is required for {{ nodeName }}"
|
4201
4313
|
},
|
4202
|
-
schema:
|
4314
|
+
schema: schema12
|
4203
4315
|
},
|
4204
4316
|
create(context) {
|
4205
4317
|
let { types, rootField, ...restOptions } = context.options[0] || {}, kinds = new Set(types ? TYPES_KINDS : []);
|
4206
4318
|
for (let [kind, isEnabled] of Object.entries(restOptions))
|
4207
4319
|
isEnabled ? kinds.add(kind) : kinds.delete(kind);
|
4208
4320
|
if (rootField) {
|
4209
|
-
let
|
4321
|
+
let schema16 = requireGraphQLSchemaFromContext(RULE_ID14, context), rootTypeNames = getRootTypeNames(schema16);
|
4210
4322
|
kinds.add(
|
4211
4323
|
`:matches(ObjectTypeDefinition, ObjectTypeExtension)[name.value=/^(${[
|
4212
4324
|
...rootTypeNames
|
@@ -4285,10 +4397,10 @@ var RULE_ID15 = "require-field-of-type-query-in-mutation-result", rule24 = {
|
|
4285
4397
|
schema: []
|
4286
4398
|
},
|
4287
4399
|
create(context) {
|
4288
|
-
let
|
4400
|
+
let schema16 = requireGraphQLSchemaFromContext(RULE_ID15, context), mutationType = schema16.getMutationType(), queryType = schema16.getQueryType();
|
4289
4401
|
return !mutationType || !queryType ? {} : {
|
4290
4402
|
[`:matches(ObjectTypeDefinition, ObjectTypeExtension)[name.value=${mutationType.name}] > FieldDefinition > .gqlType Name`](node) {
|
4291
|
-
let typeName = node.value, graphQLType =
|
4403
|
+
let typeName = node.value, graphQLType = schema16.getType(typeName);
|
4292
4404
|
if (isObjectType3(graphQLType)) {
|
4293
4405
|
let { fields } = graphQLType.astNode;
|
4294
4406
|
fields?.some((field) => getTypeName(field) === queryType.name) || context.report({
|
@@ -4523,8 +4635,8 @@ var RULE_ID18 = "require-nullable-result-in-root", rule27 = {
|
|
4523
4635
|
schema: []
|
4524
4636
|
},
|
4525
4637
|
create(context) {
|
4526
|
-
let
|
4527
|
-
[
|
4638
|
+
let schema16 = requireGraphQLSchemaFromContext(RULE_ID18, context), rootTypeNames = new Set(
|
4639
|
+
[schema16.getQueryType(), schema16.getMutationType()].filter(truthy).map((type) => type.name)
|
4528
4640
|
), sourceCode = context.getSourceCode();
|
4529
4641
|
return {
|
4530
4642
|
"ObjectTypeDefinition,ObjectTypeExtension"(node) {
|
@@ -4532,7 +4644,7 @@ var RULE_ID18 = "require-nullable-result-in-root", rule27 = {
|
|
4532
4644
|
for (let field of node.fields || []) {
|
4533
4645
|
if (field.gqlType.type !== Kind20.NON_NULL_TYPE || field.gqlType.gqlType.type !== Kind20.NAMED_TYPE)
|
4534
4646
|
continue;
|
4535
|
-
let name = field.gqlType.gqlType.name.value, type =
|
4647
|
+
let name = field.gqlType.gqlType.name.value, type = schema16.getType(name), resultType = type?.astNode ? getNodeName(type.astNode) : type?.name;
|
4536
4648
|
context.report({
|
4537
4649
|
node: field.gqlType,
|
4538
4650
|
messageId: RULE_ID18,
|
@@ -4567,7 +4679,7 @@ import {
|
|
4567
4679
|
visitWithTypeInfo as visitWithTypeInfo3
|
4568
4680
|
} from "graphql";
|
4569
4681
|
import { asArray } from "@graphql-tools/utils";
|
4570
|
-
var RULE_ID19 = "require-selections", DEFAULT_ID_FIELD_NAME = "id",
|
4682
|
+
var RULE_ID19 = "require-selections", DEFAULT_ID_FIELD_NAME = "id", schema13 = {
|
4571
4683
|
definitions: {
|
4572
4684
|
asString: {
|
4573
4685
|
type: "string"
|
@@ -4652,10 +4764,10 @@ var RULE_ID19 = "require-selections", DEFAULT_ID_FIELD_NAME = "id", schema12 = {
|
|
4652
4764
|
[RULE_ID19]: `Field{{ pluralSuffix }} {{ fieldName }} must be selected when it's available on a type.
|
4653
4765
|
Include it in your selection set{{ addition }}.`
|
4654
4766
|
},
|
4655
|
-
schema:
|
4767
|
+
schema: schema13
|
4656
4768
|
},
|
4657
4769
|
create(context) {
|
4658
|
-
let
|
4770
|
+
let schema16 = requireGraphQLSchemaFromContext(RULE_ID19, context), siblings = requireSiblingsOperations(RULE_ID19, context), { fieldName = DEFAULT_ID_FIELD_NAME } = context.options[0] || {}, idNames = asArray(fieldName), selector = "SelectionSet[parent.kind!=/(^OperationDefinition|InlineFragment)$/]", typeInfo = new TypeInfo3(schema16);
|
4659
4771
|
function checkFragments(node) {
|
4660
4772
|
for (let selection of node.selections) {
|
4661
4773
|
if (selection.kind !== Kind21.FRAGMENT_SPREAD)
|
@@ -4810,7 +4922,7 @@ var RULE_ID20 = "require-type-pattern-with-oneof", rule29 = {
|
|
4810
4922
|
// src/rules/selection-set-depth/index.ts
|
4811
4923
|
import { Kind as Kind22 } from "graphql";
|
4812
4924
|
import depthLimit from "graphql-depth-limit";
|
4813
|
-
var RULE_ID21 = "selection-set-depth",
|
4925
|
+
var RULE_ID21 = "selection-set-depth", schema14 = {
|
4814
4926
|
type: "array",
|
4815
4927
|
minItems: 1,
|
4816
4928
|
maxItems: 1,
|
@@ -4878,7 +4990,7 @@ var RULE_ID21 = "selection-set-depth", schema13 = {
|
|
4878
4990
|
recommended: !0,
|
4879
4991
|
configOptions: [{ maxDepth: 7 }]
|
4880
4992
|
},
|
4881
|
-
schema:
|
4993
|
+
schema: schema14
|
4882
4994
|
},
|
4883
4995
|
create(context) {
|
4884
4996
|
let siblings = null;
|
@@ -4939,7 +5051,7 @@ var RULE_ID21 = "selection-set-depth", schema13 = {
|
|
4939
5051
|
|
4940
5052
|
// src/rules/strict-id-in-types/index.ts
|
4941
5053
|
import { Kind as Kind23 } from "graphql";
|
4942
|
-
var RULE_ID22 = "strict-id-in-types",
|
5054
|
+
var RULE_ID22 = "strict-id-in-types", schema15 = {
|
4943
5055
|
type: "array",
|
4944
5056
|
maxItems: 1,
|
4945
5057
|
items: {
|
@@ -5047,7 +5159,7 @@ var RULE_ID22 = "strict-id-in-types", schema14 = {
|
|
5047
5159
|
}
|
5048
5160
|
]
|
5049
5161
|
},
|
5050
|
-
schema:
|
5162
|
+
schema: schema15
|
5051
5163
|
},
|
5052
5164
|
create(context) {
|
5053
5165
|
let options = {
|
@@ -5055,12 +5167,12 @@ var RULE_ID22 = "strict-id-in-types", schema14 = {
|
|
5055
5167
|
acceptedIdTypes: ["ID"],
|
5056
5168
|
exceptions: {},
|
5057
5169
|
...context.options[0]
|
5058
|
-
},
|
5170
|
+
}, schema16 = requireGraphQLSchemaFromContext(RULE_ID22, context);
|
5059
5171
|
return {
|
5060
5172
|
[`ObjectTypeDefinition[name.value!=/^(${[
|
5061
|
-
|
5062
|
-
|
5063
|
-
|
5173
|
+
schema16.getQueryType(),
|
5174
|
+
schema16.getMutationType(),
|
5175
|
+
schema16.getSubscriptionType()
|
5064
5176
|
].filter(truthy).map((type) => type.name).join("|")})$/]`](node) {
|
5065
5177
|
let typeName = node.name.value;
|
5066
5178
|
if (options.exceptions.types?.includes(typeName) || options.exceptions.suffixes?.some((suffix) => typeName.endsWith(suffix)))
|