@graphql-eslint/eslint-plugin 4.0.0-alpha.10 → 4.0.0-alpha.11
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 +4 -2
- package/cjs/meta.js +1 -1
- package/cjs/rules/index.d.cts +4 -2
- package/cjs/rules/no-unused-fields/index.d.cts +24 -3
- package/cjs/rules/no-unused-fields/index.js +118 -8
- package/esm/index.d.ts +4 -2
- package/esm/meta.js +1 -1
- package/esm/rules/index.d.ts +4 -2
- package/esm/rules/no-unused-fields/index.d.ts +24 -3
- package/esm/rules/no-unused-fields/index.js +118 -8
- package/index.browser.js +186 -76
- package/package.json +1 -1
package/cjs/index.d.cts
CHANGED
|
@@ -48,10 +48,10 @@ declare const _default: {
|
|
|
48
48
|
};
|
|
49
49
|
rules: {
|
|
50
50
|
alphabetize: GraphQLESLintRule<{
|
|
51
|
+
values?: boolean | undefined;
|
|
51
52
|
definitions?: boolean | undefined;
|
|
52
53
|
selections?: ("OperationDefinition" | "FragmentDefinition")[] | undefined;
|
|
53
54
|
arguments?: ("Field" | "Directive" | "FieldDefinition" | "DirectiveDefinition")[] | undefined;
|
|
54
|
-
values?: boolean | undefined;
|
|
55
55
|
fields?: ("ObjectTypeDefinition" | "InterfaceTypeDefinition" | "InputObjectTypeDefinition")[] | undefined;
|
|
56
56
|
variables?: boolean | undefined;
|
|
57
57
|
groups?: string[] | undefined;
|
|
@@ -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
|
@@ -12,10 +12,10 @@ import 'json-schema-to-ts';
|
|
|
12
12
|
|
|
13
13
|
declare const rules: {
|
|
14
14
|
alphabetize: GraphQLESLintRule<{
|
|
15
|
+
values?: boolean | undefined;
|
|
15
16
|
definitions?: boolean | undefined;
|
|
16
17
|
selections?: ("OperationDefinition" | "FragmentDefinition")[] | undefined;
|
|
17
18
|
arguments?: ("Field" | "Directive" | "FieldDefinition" | "DirectiveDefinition")[] | undefined;
|
|
18
|
-
values?: boolean | undefined;
|
|
19
19
|
fields?: ("ObjectTypeDefinition" | "InterfaceTypeDefinition" | "InputObjectTypeDefinition")[] | undefined;
|
|
20
20
|
variables?: boolean | undefined;
|
|
21
21
|
groups?: string[] | undefined;
|
|
@@ -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>;
|
|
@@ -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,
|
package/esm/index.d.ts
CHANGED
|
@@ -48,10 +48,10 @@ declare const _default: {
|
|
|
48
48
|
};
|
|
49
49
|
rules: {
|
|
50
50
|
alphabetize: GraphQLESLintRule<{
|
|
51
|
-
values?: boolean | undefined;
|
|
52
51
|
definitions?: boolean | undefined;
|
|
53
52
|
selections?: ("OperationDefinition" | "FragmentDefinition")[] | undefined;
|
|
54
53
|
arguments?: ("Field" | "Directive" | "FieldDefinition" | "DirectiveDefinition")[] | undefined;
|
|
54
|
+
values?: boolean | undefined;
|
|
55
55
|
fields?: ("ObjectTypeDefinition" | "InterfaceTypeDefinition" | "InputObjectTypeDefinition")[] | undefined;
|
|
56
56
|
variables?: boolean | undefined;
|
|
57
57
|
groups?: string[] | undefined;
|
|
@@ -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
|
@@ -12,10 +12,10 @@ import 'json-schema-to-ts';
|
|
|
12
12
|
|
|
13
13
|
declare const rules: {
|
|
14
14
|
alphabetize: GraphQLESLintRule<{
|
|
15
|
-
values?: boolean | undefined;
|
|
16
15
|
definitions?: boolean | undefined;
|
|
17
16
|
selections?: ("OperationDefinition" | "FragmentDefinition")[] | undefined;
|
|
18
17
|
arguments?: ("Field" | "Directive" | "FieldDefinition" | "DirectiveDefinition")[] | undefined;
|
|
18
|
+
values?: boolean | undefined;
|
|
19
19
|
fields?: ("ObjectTypeDefinition" | "InterfaceTypeDefinition" | "InputObjectTypeDefinition")[] | undefined;
|
|
20
20
|
variables?: boolean | undefined;
|
|
21
21
|
groups?: string[] | undefined;
|
|
@@ -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>;
|
|
@@ -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,
|
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
|
|
@@ -3069,9 +3069,9 @@ var schema7 = {
|
|
|
3069
3069
|
schema: schema7
|
|
3070
3070
|
},
|
|
3071
3071
|
create(context) {
|
|
3072
|
-
let
|
|
3073
|
-
disallow.has("mutation") &&
|
|
3074
|
-
disallow.has("subscription") &&
|
|
3072
|
+
let schema16 = requireGraphQLSchemaFromContext("no-root-type", context), disallow = new Set(context.options[0].disallow), rootTypeNames = [
|
|
3073
|
+
disallow.has("mutation") && schema16.getMutationType(),
|
|
3074
|
+
disallow.has("subscription") && schema16.getSubscriptionType()
|
|
3075
3075
|
].filter(truthy).map((type) => type.name).join("|");
|
|
3076
3076
|
return rootTypeNames ? {
|
|
3077
3077
|
[`:matches(ObjectTypeDefinition, ObjectTypeExtension) > .name[value=/^(${rootTypeNames})$/]`](node) {
|
|
@@ -3130,13 +3130,13 @@ var RULE_ID8 = "no-scalar-result-type-on-mutation", rule13 = {
|
|
|
3130
3130
|
schema: []
|
|
3131
3131
|
},
|
|
3132
3132
|
create(context) {
|
|
3133
|
-
let
|
|
3133
|
+
let schema16 = requireGraphQLSchemaFromContext(RULE_ID8, context), mutationType = schema16.getMutationType();
|
|
3134
3134
|
return mutationType ? {
|
|
3135
3135
|
[[
|
|
3136
3136
|
`:matches(ObjectTypeDefinition, ObjectTypeExtension)[name.value=${mutationType.name}]`,
|
|
3137
3137
|
"> FieldDefinition > .gqlType Name"
|
|
3138
3138
|
].join(" ")](node) {
|
|
3139
|
-
let typeName = node.value, graphQLType =
|
|
3139
|
+
let typeName = node.value, graphQLType = schema16.getType(typeName);
|
|
3140
3140
|
if (isScalarType(graphQLType)) {
|
|
3141
3141
|
let fieldDef = node.parent;
|
|
3142
3142
|
for (; fieldDef.kind !== Kind12.FIELD_DEFINITION; )
|
|
@@ -3258,8 +3258,8 @@ var RULE_ID9 = "no-unreachable-types", KINDS = [
|
|
|
3258
3258
|
DirectiveLocation.INLINE_FRAGMENT,
|
|
3259
3259
|
DirectiveLocation.VARIABLE_DEFINITION
|
|
3260
3260
|
]);
|
|
3261
|
-
function getReachableTypes(
|
|
3262
|
-
let cachedValue = reachableTypesCache.get(
|
|
3261
|
+
function getReachableTypes(schema16) {
|
|
3262
|
+
let cachedValue = reachableTypesCache.get(schema16);
|
|
3263
3263
|
if (cachedValue)
|
|
3264
3264
|
return cachedValue;
|
|
3265
3265
|
let reachableTypes = /* @__PURE__ */ new Set(), collect = (node) => {
|
|
@@ -3267,9 +3267,9 @@ function getReachableTypes(schema15) {
|
|
|
3267
3267
|
if (reachableTypes.has(typeName))
|
|
3268
3268
|
return;
|
|
3269
3269
|
reachableTypes.add(typeName);
|
|
3270
|
-
let type =
|
|
3270
|
+
let type = schema16.getType(typeName) || schema16.getDirective(typeName);
|
|
3271
3271
|
if (isInterfaceType(type)) {
|
|
3272
|
-
let { objects, interfaces } =
|
|
3272
|
+
let { objects, interfaces } = schema16.getImplementations(type);
|
|
3273
3273
|
for (let { astNode } of [...objects, ...interfaces])
|
|
3274
3274
|
visit5(astNode, visitor);
|
|
3275
3275
|
} else type?.astNode && visit5(type.astNode, visitor);
|
|
@@ -3283,14 +3283,14 @@ function getReachableTypes(schema15) {
|
|
|
3283
3283
|
NamedType: collect
|
|
3284
3284
|
};
|
|
3285
3285
|
for (let type of [
|
|
3286
|
-
|
|
3286
|
+
schema16,
|
|
3287
3287
|
// visiting SchemaDefinition node
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3288
|
+
schema16.getQueryType(),
|
|
3289
|
+
schema16.getMutationType(),
|
|
3290
|
+
schema16.getSubscriptionType()
|
|
3291
3291
|
])
|
|
3292
3292
|
type?.astNode && visit5(type.astNode, visitor);
|
|
3293
|
-
for (let node of
|
|
3293
|
+
for (let node of schema16.getDirectives())
|
|
3294
3294
|
if (node.locations.some((location) => RequestDirectiveLocations.has(location))) {
|
|
3295
3295
|
reachableTypes.add(node.name);
|
|
3296
3296
|
for (let arg of node.args) {
|
|
@@ -3298,7 +3298,7 @@ function getReachableTypes(schema15) {
|
|
|
3298
3298
|
argTypeName && reachableTypes.add(argTypeName);
|
|
3299
3299
|
}
|
|
3300
3300
|
}
|
|
3301
|
-
return reachableTypesCache.set(
|
|
3301
|
+
return reachableTypesCache.set(schema16, reachableTypes), reachableTypes;
|
|
3302
3302
|
}
|
|
3303
3303
|
var rule15 = {
|
|
3304
3304
|
meta: {
|
|
@@ -3351,7 +3351,7 @@ var rule15 = {
|
|
|
3351
3351
|
hasSuggestions: !0
|
|
3352
3352
|
},
|
|
3353
3353
|
create(context) {
|
|
3354
|
-
let
|
|
3354
|
+
let schema16 = requireGraphQLSchemaFromContext(RULE_ID9, context), reachableTypes = getReachableTypes(schema16);
|
|
3355
3355
|
return {
|
|
3356
3356
|
[`:matches(${KINDS}) > .name`](node) {
|
|
3357
3357
|
let typeName = node.value;
|
|
@@ -3379,12 +3379,105 @@ var rule15 = {
|
|
|
3379
3379
|
|
|
3380
3380
|
// src/rules/no-unused-fields/index.ts
|
|
3381
3381
|
import { TypeInfo as TypeInfo2, visit as visit6, visitWithTypeInfo as visitWithTypeInfo2 } from "graphql";
|
|
3382
|
-
var RULE_ID10 = "no-unused-fields",
|
|
3383
|
-
|
|
3384
|
-
|
|
3382
|
+
var RULE_ID10 = "no-unused-fields", RELAY_SCHEMA = (
|
|
3383
|
+
/* GraphQL */
|
|
3384
|
+
`
|
|
3385
|
+
# Root Query Type
|
|
3386
|
+
type Query {
|
|
3387
|
+
user: User
|
|
3388
|
+
}
|
|
3389
|
+
|
|
3390
|
+
# User Type
|
|
3391
|
+
type User {
|
|
3392
|
+
id: ID!
|
|
3393
|
+
name: String!
|
|
3394
|
+
friends(first: Int, after: String): FriendConnection!
|
|
3395
|
+
}
|
|
3396
|
+
|
|
3397
|
+
# FriendConnection Type (Relay Connection)
|
|
3398
|
+
type FriendConnection {
|
|
3399
|
+
edges: [FriendEdge]
|
|
3400
|
+
pageInfo: PageInfo!
|
|
3401
|
+
}
|
|
3402
|
+
|
|
3403
|
+
# FriendEdge Type
|
|
3404
|
+
type FriendEdge {
|
|
3405
|
+
cursor: String!
|
|
3406
|
+
node: Friend!
|
|
3407
|
+
}
|
|
3408
|
+
|
|
3409
|
+
# Friend Type
|
|
3410
|
+
type Friend {
|
|
3411
|
+
id: ID!
|
|
3412
|
+
name: String!
|
|
3413
|
+
}
|
|
3414
|
+
|
|
3415
|
+
# PageInfo Type (Relay Pagination)
|
|
3416
|
+
type PageInfo {
|
|
3417
|
+
hasPreviousPage: Boolean!
|
|
3418
|
+
hasNextPage: Boolean!
|
|
3419
|
+
startCursor: String
|
|
3420
|
+
endCursor: String
|
|
3421
|
+
}
|
|
3422
|
+
`
|
|
3423
|
+
), RELAY_QUERY = (
|
|
3424
|
+
/* GraphQL */
|
|
3425
|
+
`
|
|
3426
|
+
query {
|
|
3427
|
+
user {
|
|
3428
|
+
id
|
|
3429
|
+
name
|
|
3430
|
+
friends(first: 10) {
|
|
3431
|
+
edges {
|
|
3432
|
+
node {
|
|
3433
|
+
id
|
|
3434
|
+
name
|
|
3435
|
+
}
|
|
3436
|
+
}
|
|
3437
|
+
}
|
|
3438
|
+
}
|
|
3439
|
+
}
|
|
3440
|
+
`
|
|
3441
|
+
), RELAY_DEFAULT_IGNORED_FIELD_SELECTORS = [
|
|
3442
|
+
"[parent.name.value=PageInfo][name.value=/(endCursor|startCursor|hasNextPage|hasPreviousPage)/]",
|
|
3443
|
+
"[parent.name.value=/Edge$/][name.value=cursor]",
|
|
3444
|
+
"[parent.name.value=/Connection$/][name.value=pageInfo]"
|
|
3445
|
+
], schema8 = {
|
|
3446
|
+
type: "array",
|
|
3447
|
+
maxItems: 1,
|
|
3448
|
+
items: {
|
|
3449
|
+
type: "object",
|
|
3450
|
+
additionalProperties: !1,
|
|
3451
|
+
properties: {
|
|
3452
|
+
ignoredFieldSelectors: {
|
|
3453
|
+
type: "array",
|
|
3454
|
+
uniqueItems: !0,
|
|
3455
|
+
minItems: 1,
|
|
3456
|
+
description: [
|
|
3457
|
+
"Fields that will be ignored and are allowed to be unused.",
|
|
3458
|
+
"",
|
|
3459
|
+
"E.g. The following selector will ignore all the relay pagination fields for every connection exposed in the schema:",
|
|
3460
|
+
"```json",
|
|
3461
|
+
JSON.stringify(RELAY_DEFAULT_IGNORED_FIELD_SELECTORS, null, 2),
|
|
3462
|
+
"```",
|
|
3463
|
+
"",
|
|
3464
|
+
"> These fields are defined by ESLint [`selectors`](https://eslint.org/docs/developer-guide/selectors).",
|
|
3465
|
+
"> Paste or drop code into the editor in [ASTExplorer](https://astexplorer.net) and inspect the generated AST to compose your selector."
|
|
3466
|
+
].join(`
|
|
3467
|
+
`),
|
|
3468
|
+
items: {
|
|
3469
|
+
type: "string",
|
|
3470
|
+
pattern: "^\\[(.+)]$"
|
|
3471
|
+
}
|
|
3472
|
+
}
|
|
3473
|
+
}
|
|
3474
|
+
}
|
|
3475
|
+
}, usedFieldsCache = new ModuleCache();
|
|
3476
|
+
function getUsedFields(schema16, operations) {
|
|
3477
|
+
let cachedValue = usedFieldsCache.get(schema16);
|
|
3385
3478
|
if (cachedValue)
|
|
3386
3479
|
return cachedValue;
|
|
3387
|
-
let usedFields = /* @__PURE__ */ Object.create(null), typeInfo = new TypeInfo2(
|
|
3480
|
+
let usedFields = /* @__PURE__ */ Object.create(null), typeInfo = new TypeInfo2(schema16), visitor = visitWithTypeInfo2(typeInfo, {
|
|
3388
3481
|
Field(node) {
|
|
3389
3482
|
if (!typeInfo.getFieldDef())
|
|
3390
3483
|
return !1;
|
|
@@ -3394,7 +3487,7 @@ function getUsedFields(schema15, operations) {
|
|
|
3394
3487
|
}), allDocuments = [...operations.getOperations(), ...operations.getFragments()];
|
|
3395
3488
|
for (let { document } of allDocuments)
|
|
3396
3489
|
visit6(document, visitor);
|
|
3397
|
-
return usedFieldsCache.set(
|
|
3490
|
+
return usedFieldsCache.set(schema16, usedFields), usedFields;
|
|
3398
3491
|
}
|
|
3399
3492
|
var rule16 = {
|
|
3400
3493
|
meta: {
|
|
@@ -3456,17 +3549,34 @@ var rule16 = {
|
|
|
3456
3549
|
}
|
|
3457
3550
|
`
|
|
3458
3551
|
)
|
|
3552
|
+
},
|
|
3553
|
+
{
|
|
3554
|
+
title: "Correct (ignoring fields)",
|
|
3555
|
+
usage: [{ ignoredFieldSelectors: RELAY_DEFAULT_IGNORED_FIELD_SELECTORS }],
|
|
3556
|
+
code: (
|
|
3557
|
+
/* GraphQL */
|
|
3558
|
+
`
|
|
3559
|
+
### 1\uFE0F\u20E3 YOUR SCHEMA
|
|
3560
|
+
${RELAY_SCHEMA}
|
|
3561
|
+
|
|
3562
|
+
### 2\uFE0F\u20E3 YOUR QUERY
|
|
3563
|
+
${RELAY_QUERY}
|
|
3564
|
+
`
|
|
3565
|
+
)
|
|
3459
3566
|
}
|
|
3460
3567
|
]
|
|
3461
3568
|
},
|
|
3462
3569
|
type: "suggestion",
|
|
3463
|
-
schema:
|
|
3570
|
+
schema: schema8,
|
|
3464
3571
|
hasSuggestions: !0
|
|
3465
3572
|
},
|
|
3466
3573
|
create(context) {
|
|
3467
|
-
let
|
|
3574
|
+
let schema16 = requireGraphQLSchemaFromContext(RULE_ID10, context), siblingsOperations = requireSiblingsOperations(RULE_ID10, context), usedFields = getUsedFields(schema16, siblingsOperations), { ignoredFieldSelectors } = context.options[0] || {};
|
|
3468
3575
|
return {
|
|
3469
|
-
|
|
3576
|
+
[(ignoredFieldSelectors || []).reduce(
|
|
3577
|
+
(acc, selector2) => `${acc}:not(${selector2})`,
|
|
3578
|
+
"FieldDefinition"
|
|
3579
|
+
)](node) {
|
|
3470
3580
|
let fieldName = node.name.value, parentTypeName = node.parent.name.value;
|
|
3471
3581
|
usedFields[parentTypeName]?.has(fieldName) || context.report({
|
|
3472
3582
|
node: node.name,
|
|
@@ -3489,7 +3599,7 @@ var rule16 = {
|
|
|
3489
3599
|
|
|
3490
3600
|
// src/rules/relay-arguments/index.ts
|
|
3491
3601
|
import { isScalarType as isScalarType2, Kind as Kind14 } from "graphql";
|
|
3492
|
-
var RULE_ID11 = "relay-arguments", MISSING_ARGUMENTS = "MISSING_ARGUMENTS",
|
|
3602
|
+
var RULE_ID11 = "relay-arguments", MISSING_ARGUMENTS = "MISSING_ARGUMENTS", schema9 = {
|
|
3493
3603
|
type: "array",
|
|
3494
3604
|
maxItems: 1,
|
|
3495
3605
|
items: {
|
|
@@ -3555,10 +3665,10 @@ var RULE_ID11 = "relay-arguments", MISSING_ARGUMENTS = "MISSING_ARGUMENTS", sche
|
|
|
3555
3665
|
messages: {
|
|
3556
3666
|
[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
3667
|
},
|
|
3558
|
-
schema:
|
|
3668
|
+
schema: schema9
|
|
3559
3669
|
},
|
|
3560
3670
|
create(context) {
|
|
3561
|
-
let
|
|
3671
|
+
let schema16 = requireGraphQLSchemaFromContext(RULE_ID11, context), { includeBoth = !0 } = context.options[0] || {};
|
|
3562
3672
|
return {
|
|
3563
3673
|
"FieldDefinition > .gqlType Name[value=/Connection$/]"(node) {
|
|
3564
3674
|
let fieldNode = node.parent;
|
|
@@ -3576,7 +3686,7 @@ var RULE_ID11 = "relay-arguments", MISSING_ARGUMENTS = "MISSING_ARGUMENTS", sche
|
|
|
3576
3686
|
}
|
|
3577
3687
|
function checkField(typeName, argumentName) {
|
|
3578
3688
|
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(
|
|
3689
|
+
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
3690
|
let returnType = typeName === "String" ? "String or Scalar" : typeName;
|
|
3581
3691
|
context.report({
|
|
3582
3692
|
node: (argument || fieldNode).name,
|
|
@@ -3686,7 +3796,7 @@ import {
|
|
|
3686
3796
|
} from "graphql";
|
|
3687
3797
|
import { getDocumentNodeFromSchema } from "@graphql-tools/utils";
|
|
3688
3798
|
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(
|
|
3799
|
+
function getEdgeTypes(schema16) {
|
|
3690
3800
|
if (edgeTypesCache)
|
|
3691
3801
|
return edgeTypesCache;
|
|
3692
3802
|
let edgeTypes = /* @__PURE__ */ new Set(), visitor = {
|
|
@@ -3695,14 +3805,14 @@ function getEdgeTypes(schema15) {
|
|
|
3695
3805
|
return;
|
|
3696
3806
|
let edges = node.fields?.find((field) => field.name.value === "edges");
|
|
3697
3807
|
if (edges) {
|
|
3698
|
-
let edgesTypeName = getTypeName(edges), edgesType =
|
|
3808
|
+
let edgesTypeName = getTypeName(edges), edgesType = schema16.getType(edgesTypeName);
|
|
3699
3809
|
isObjectType2(edgesType) && edgeTypes.add(edgesTypeName);
|
|
3700
3810
|
}
|
|
3701
3811
|
}
|
|
3702
|
-
}, astNode = getDocumentNodeFromSchema(
|
|
3812
|
+
}, astNode = getDocumentNodeFromSchema(schema16);
|
|
3703
3813
|
return visit7(astNode, visitor), edgeTypesCache = edgeTypes, edgeTypesCache;
|
|
3704
3814
|
}
|
|
3705
|
-
var
|
|
3815
|
+
var schema10 = {
|
|
3706
3816
|
type: "array",
|
|
3707
3817
|
maxItems: 1,
|
|
3708
3818
|
items: {
|
|
@@ -3768,10 +3878,10 @@ var schema9 = {
|
|
|
3768
3878
|
[MESSAGE_LIST_TYPE_ONLY_EDGE_TYPE]: "A list type should only wrap an edge type.",
|
|
3769
3879
|
[MESSAGE_SHOULD_IMPLEMENTS_NODE]: "Edge type's field `node` must implement `Node` interface."
|
|
3770
3880
|
},
|
|
3771
|
-
schema:
|
|
3881
|
+
schema: schema10
|
|
3772
3882
|
},
|
|
3773
3883
|
create(context) {
|
|
3774
|
-
let
|
|
3884
|
+
let schema16 = requireGraphQLSchemaFromContext(RULE_ID12, context), edgeTypes = getEdgeTypes(schema16), options = {
|
|
3775
3885
|
withEdgeSuffix: !0,
|
|
3776
3886
|
shouldImplementNode: !0,
|
|
3777
3887
|
listTypeCanWrapOnlyEdgeType: !0,
|
|
@@ -3786,7 +3896,7 @@ var schema9 = {
|
|
|
3786
3896
|
else if (!isNamedOrNonNullNamed(nodeField.gqlType))
|
|
3787
3897
|
context.report({ node: nodeField.name, message: `Field \`node\` must ${message}` });
|
|
3788
3898
|
else if (options.shouldImplementNode) {
|
|
3789
|
-
let nodeReturnTypeName = getTypeName(nodeField.gqlType.rawNode()), type =
|
|
3899
|
+
let nodeReturnTypeName = getTypeName(nodeField.gqlType.rawNode()), type = schema16.getType(nodeReturnTypeName);
|
|
3790
3900
|
if (!isObjectType2(type))
|
|
3791
3901
|
return;
|
|
3792
3902
|
type.astNode.interfaces?.some((n) => n.name.value === "Node") || context.report({ node: node.name, messageId: MESSAGE_SHOULD_IMPLEMENTS_NODE });
|
|
@@ -3801,10 +3911,10 @@ var schema9 = {
|
|
|
3801
3911
|
return;
|
|
3802
3912
|
}
|
|
3803
3913
|
let typeName = getTypeName(cursorField.rawNode());
|
|
3804
|
-
(!isNamedOrNonNullNamed(cursorField.gqlType) || typeName !== "String" && !isScalarType3(
|
|
3914
|
+
(!isNamedOrNonNullNamed(cursorField.gqlType) || typeName !== "String" && !isScalarType3(schema16.getType(typeName))) && context.report({ node: cursorField.name, message: `Field \`cursor\` must ${message}` });
|
|
3805
3915
|
}, listeners = {
|
|
3806
3916
|
":matches(ObjectTypeDefinition, ObjectTypeExtension)[name.value=/Connection$/] > FieldDefinition[name.value=edges] > .gqlType Name"(node) {
|
|
3807
|
-
let type =
|
|
3917
|
+
let type = schema16.getType(node.value);
|
|
3808
3918
|
isObjectType2(type) || context.report({ node, messageId: MESSAGE_MUST_BE_OBJECT_TYPE });
|
|
3809
3919
|
},
|
|
3810
3920
|
":matches(ObjectTypeDefinition, ObjectTypeExtension)"(node) {
|
|
@@ -3863,8 +3973,8 @@ var RULE_ID13 = "relay-page-info", MESSAGE_MUST_EXIST = "MESSAGE_MUST_EXIST", ME
|
|
|
3863
3973
|
schema: []
|
|
3864
3974
|
},
|
|
3865
3975
|
create(context) {
|
|
3866
|
-
let
|
|
3867
|
-
return hasPageInfoChecked || (
|
|
3976
|
+
let schema16 = requireGraphQLSchemaFromContext(RULE_ID13, context);
|
|
3977
|
+
return hasPageInfoChecked || (schema16.getType("PageInfo") || context.report({
|
|
3868
3978
|
loc: REPORT_ON_FIRST_CHARACTER,
|
|
3869
3979
|
messageId: MESSAGE_MUST_EXIST
|
|
3870
3980
|
}), hasPageInfoChecked = !0), {
|
|
@@ -3878,7 +3988,7 @@ var RULE_ID13 = "relay-page-info", MESSAGE_MUST_EXIST = "MESSAGE_MUST_EXIST", ME
|
|
|
3878
3988
|
let field = fieldMap[fieldName], isAllowedType = !1;
|
|
3879
3989
|
if (field) {
|
|
3880
3990
|
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(
|
|
3991
|
+
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
3992
|
}
|
|
3883
3993
|
if (!isAllowedType) {
|
|
3884
3994
|
let returnType = typeName === "Boolean" ? "non-null Boolean" : "either String or Scalar, which can be null if there are no results";
|
|
@@ -3895,7 +4005,7 @@ var RULE_ID13 = "relay-page-info", MESSAGE_MUST_EXIST = "MESSAGE_MUST_EXIST", ME
|
|
|
3895
4005
|
};
|
|
3896
4006
|
|
|
3897
4007
|
// 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",
|
|
4008
|
+
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
4009
|
type: "array",
|
|
3900
4010
|
maxItems: 1,
|
|
3901
4011
|
items: {
|
|
@@ -3961,7 +4071,7 @@ var DATE_REGEX = /^\d{2}\/\d{2}\/\d{4}$/, MESSAGE_REQUIRE_DATE = "MESSAGE_REQUIR
|
|
|
3961
4071
|
[MESSAGE_INVALID_DATE]: 'Invalid "{{ deletionDate }}" deletion date for {{ nodeName }}',
|
|
3962
4072
|
[MESSAGE_CAN_BE_REMOVED]: "{{ nodeName }} \u0441an be removed"
|
|
3963
4073
|
},
|
|
3964
|
-
schema:
|
|
4074
|
+
schema: schema11
|
|
3965
4075
|
},
|
|
3966
4076
|
create(context) {
|
|
3967
4077
|
return {
|
|
@@ -4091,7 +4201,7 @@ var RULE_ID14 = "require-description", ALLOWED_KINDS2 = [
|
|
|
4091
4201
|
Kind18.INPUT_VALUE_DEFINITION,
|
|
4092
4202
|
Kind18.ENUM_VALUE_DEFINITION,
|
|
4093
4203
|
Kind18.OPERATION_DEFINITION
|
|
4094
|
-
],
|
|
4204
|
+
], schema12 = {
|
|
4095
4205
|
type: "array",
|
|
4096
4206
|
minItems: 1,
|
|
4097
4207
|
maxItems: 1,
|
|
@@ -4199,14 +4309,14 @@ ${TYPES_KINDS.map((kind) => `- \`${kind}\``).join(`
|
|
|
4199
4309
|
messages: {
|
|
4200
4310
|
[RULE_ID14]: "Description is required for {{ nodeName }}"
|
|
4201
4311
|
},
|
|
4202
|
-
schema:
|
|
4312
|
+
schema: schema12
|
|
4203
4313
|
},
|
|
4204
4314
|
create(context) {
|
|
4205
4315
|
let { types, rootField, ...restOptions } = context.options[0] || {}, kinds = new Set(types ? TYPES_KINDS : []);
|
|
4206
4316
|
for (let [kind, isEnabled] of Object.entries(restOptions))
|
|
4207
4317
|
isEnabled ? kinds.add(kind) : kinds.delete(kind);
|
|
4208
4318
|
if (rootField) {
|
|
4209
|
-
let
|
|
4319
|
+
let schema16 = requireGraphQLSchemaFromContext(RULE_ID14, context), rootTypeNames = getRootTypeNames(schema16);
|
|
4210
4320
|
kinds.add(
|
|
4211
4321
|
`:matches(ObjectTypeDefinition, ObjectTypeExtension)[name.value=/^(${[
|
|
4212
4322
|
...rootTypeNames
|
|
@@ -4285,10 +4395,10 @@ var RULE_ID15 = "require-field-of-type-query-in-mutation-result", rule24 = {
|
|
|
4285
4395
|
schema: []
|
|
4286
4396
|
},
|
|
4287
4397
|
create(context) {
|
|
4288
|
-
let
|
|
4398
|
+
let schema16 = requireGraphQLSchemaFromContext(RULE_ID15, context), mutationType = schema16.getMutationType(), queryType = schema16.getQueryType();
|
|
4289
4399
|
return !mutationType || !queryType ? {} : {
|
|
4290
4400
|
[`:matches(ObjectTypeDefinition, ObjectTypeExtension)[name.value=${mutationType.name}] > FieldDefinition > .gqlType Name`](node) {
|
|
4291
|
-
let typeName = node.value, graphQLType =
|
|
4401
|
+
let typeName = node.value, graphQLType = schema16.getType(typeName);
|
|
4292
4402
|
if (isObjectType3(graphQLType)) {
|
|
4293
4403
|
let { fields } = graphQLType.astNode;
|
|
4294
4404
|
fields?.some((field) => getTypeName(field) === queryType.name) || context.report({
|
|
@@ -4523,8 +4633,8 @@ var RULE_ID18 = "require-nullable-result-in-root", rule27 = {
|
|
|
4523
4633
|
schema: []
|
|
4524
4634
|
},
|
|
4525
4635
|
create(context) {
|
|
4526
|
-
let
|
|
4527
|
-
[
|
|
4636
|
+
let schema16 = requireGraphQLSchemaFromContext(RULE_ID18, context), rootTypeNames = new Set(
|
|
4637
|
+
[schema16.getQueryType(), schema16.getMutationType()].filter(truthy).map((type) => type.name)
|
|
4528
4638
|
), sourceCode = context.getSourceCode();
|
|
4529
4639
|
return {
|
|
4530
4640
|
"ObjectTypeDefinition,ObjectTypeExtension"(node) {
|
|
@@ -4532,7 +4642,7 @@ var RULE_ID18 = "require-nullable-result-in-root", rule27 = {
|
|
|
4532
4642
|
for (let field of node.fields || []) {
|
|
4533
4643
|
if (field.gqlType.type !== Kind20.NON_NULL_TYPE || field.gqlType.gqlType.type !== Kind20.NAMED_TYPE)
|
|
4534
4644
|
continue;
|
|
4535
|
-
let name = field.gqlType.gqlType.name.value, type =
|
|
4645
|
+
let name = field.gqlType.gqlType.name.value, type = schema16.getType(name), resultType = type?.astNode ? getNodeName(type.astNode) : type?.name;
|
|
4536
4646
|
context.report({
|
|
4537
4647
|
node: field.gqlType,
|
|
4538
4648
|
messageId: RULE_ID18,
|
|
@@ -4567,7 +4677,7 @@ import {
|
|
|
4567
4677
|
visitWithTypeInfo as visitWithTypeInfo3
|
|
4568
4678
|
} from "graphql";
|
|
4569
4679
|
import { asArray } from "@graphql-tools/utils";
|
|
4570
|
-
var RULE_ID19 = "require-selections", DEFAULT_ID_FIELD_NAME = "id",
|
|
4680
|
+
var RULE_ID19 = "require-selections", DEFAULT_ID_FIELD_NAME = "id", schema13 = {
|
|
4571
4681
|
definitions: {
|
|
4572
4682
|
asString: {
|
|
4573
4683
|
type: "string"
|
|
@@ -4652,10 +4762,10 @@ var RULE_ID19 = "require-selections", DEFAULT_ID_FIELD_NAME = "id", schema12 = {
|
|
|
4652
4762
|
[RULE_ID19]: `Field{{ pluralSuffix }} {{ fieldName }} must be selected when it's available on a type.
|
|
4653
4763
|
Include it in your selection set{{ addition }}.`
|
|
4654
4764
|
},
|
|
4655
|
-
schema:
|
|
4765
|
+
schema: schema13
|
|
4656
4766
|
},
|
|
4657
4767
|
create(context) {
|
|
4658
|
-
let
|
|
4768
|
+
let schema16 = requireGraphQLSchemaFromContext(RULE_ID19, context), siblings = requireSiblingsOperations(RULE_ID19, context), { fieldName = DEFAULT_ID_FIELD_NAME } = context.options[0] || {}, idNames = asArray(fieldName), selector = "OperationDefinition SelectionSet[parent.kind!=/(^OperationDefinition|InlineFragment)$/]", typeInfo = new TypeInfo3(schema16);
|
|
4659
4769
|
function checkFragments(node) {
|
|
4660
4770
|
for (let selection of node.selections) {
|
|
4661
4771
|
if (selection.kind !== Kind21.FRAGMENT_SPREAD)
|
|
@@ -4810,7 +4920,7 @@ var RULE_ID20 = "require-type-pattern-with-oneof", rule29 = {
|
|
|
4810
4920
|
// src/rules/selection-set-depth/index.ts
|
|
4811
4921
|
import { Kind as Kind22 } from "graphql";
|
|
4812
4922
|
import depthLimit from "graphql-depth-limit";
|
|
4813
|
-
var RULE_ID21 = "selection-set-depth",
|
|
4923
|
+
var RULE_ID21 = "selection-set-depth", schema14 = {
|
|
4814
4924
|
type: "array",
|
|
4815
4925
|
minItems: 1,
|
|
4816
4926
|
maxItems: 1,
|
|
@@ -4878,7 +4988,7 @@ var RULE_ID21 = "selection-set-depth", schema13 = {
|
|
|
4878
4988
|
recommended: !0,
|
|
4879
4989
|
configOptions: [{ maxDepth: 7 }]
|
|
4880
4990
|
},
|
|
4881
|
-
schema:
|
|
4991
|
+
schema: schema14
|
|
4882
4992
|
},
|
|
4883
4993
|
create(context) {
|
|
4884
4994
|
let siblings = null;
|
|
@@ -4939,7 +5049,7 @@ var RULE_ID21 = "selection-set-depth", schema13 = {
|
|
|
4939
5049
|
|
|
4940
5050
|
// src/rules/strict-id-in-types/index.ts
|
|
4941
5051
|
import { Kind as Kind23 } from "graphql";
|
|
4942
|
-
var RULE_ID22 = "strict-id-in-types",
|
|
5052
|
+
var RULE_ID22 = "strict-id-in-types", schema15 = {
|
|
4943
5053
|
type: "array",
|
|
4944
5054
|
maxItems: 1,
|
|
4945
5055
|
items: {
|
|
@@ -5047,7 +5157,7 @@ var RULE_ID22 = "strict-id-in-types", schema14 = {
|
|
|
5047
5157
|
}
|
|
5048
5158
|
]
|
|
5049
5159
|
},
|
|
5050
|
-
schema:
|
|
5160
|
+
schema: schema15
|
|
5051
5161
|
},
|
|
5052
5162
|
create(context) {
|
|
5053
5163
|
let options = {
|
|
@@ -5055,12 +5165,12 @@ var RULE_ID22 = "strict-id-in-types", schema14 = {
|
|
|
5055
5165
|
acceptedIdTypes: ["ID"],
|
|
5056
5166
|
exceptions: {},
|
|
5057
5167
|
...context.options[0]
|
|
5058
|
-
},
|
|
5168
|
+
}, schema16 = requireGraphQLSchemaFromContext(RULE_ID22, context);
|
|
5059
5169
|
return {
|
|
5060
5170
|
[`ObjectTypeDefinition[name.value!=/^(${[
|
|
5061
|
-
|
|
5062
|
-
|
|
5063
|
-
|
|
5171
|
+
schema16.getQueryType(),
|
|
5172
|
+
schema16.getMutationType(),
|
|
5173
|
+
schema16.getSubscriptionType()
|
|
5064
5174
|
].filter(truthy).map((type) => type.name).join("|")})$/]`](node) {
|
|
5065
5175
|
let typeName = node.name.value;
|
|
5066
5176
|
if (options.exceptions.types?.includes(typeName) || options.exceptions.suffixes?.some((suffix) => typeName.endsWith(suffix)))
|