@graphql-eslint/eslint-plugin 4.3.0 → 4.3.1-alpha-20241207204625-6a4230707a78900a6339b03afe904b9dd6c31561
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/cache.js +6 -2
- package/cjs/configs/operations-all.js +2 -2
- package/cjs/configs/schema-all.js +2 -2
- package/cjs/configs/schema-recommended.js +1 -1
- package/cjs/documents.js +13 -7
- package/cjs/estree-converter/converter.js +17 -8
- package/cjs/estree-converter/utils.js +22 -9
- package/cjs/graphql-config.js +13 -6
- package/cjs/index.d.cts +18 -4
- package/cjs/meta.js +1 -1
- package/cjs/parser.js +36 -9
- package/cjs/processor.js +48 -20
- package/cjs/rules/alphabetize/index.js +99 -47
- package/cjs/rules/description-style/index.js +10 -6
- package/cjs/rules/graphql-js-validation.js +142 -108
- package/cjs/rules/index.d.cts +18 -4
- package/cjs/rules/input-name/index.js +51 -38
- package/cjs/rules/lone-executable-definition/index.js +15 -6
- package/cjs/rules/match-document-filename/index.d.cts +4 -3
- package/cjs/rules/match-document-filename/index.js +63 -37
- package/cjs/rules/naming-convention/index.d.cts +6 -10
- package/cjs/rules/naming-convention/index.js +146 -57
- package/cjs/rules/no-anonymous-operations/index.js +8 -5
- package/cjs/rules/no-deprecated/index.js +27 -13
- package/cjs/rules/no-duplicate-fields/index.js +15 -8
- package/cjs/rules/no-hashtag-description/index.js +18 -10
- package/cjs/rules/no-one-place-fragments/index.js +17 -10
- package/cjs/rules/no-root-type/index.js +15 -8
- package/cjs/rules/no-scalar-result-type-on-mutation/index.js +20 -12
- package/cjs/rules/no-typename-prefix/index.js +25 -21
- package/cjs/rules/no-unreachable-types/index.js +34 -17
- package/cjs/rules/no-unused-fields/index.js +56 -30
- package/cjs/rules/relay-arguments/index.js +31 -13
- package/cjs/rules/relay-connection-types/index.js +31 -9
- package/cjs/rules/relay-edge-types/index.js +84 -41
- package/cjs/rules/relay-page-info/index.js +31 -14
- package/cjs/rules/require-deprecation-date/index.js +20 -9
- package/cjs/rules/require-deprecation-reason/index.js +8 -5
- package/cjs/rules/require-description/index.d.cts +79 -13
- package/cjs/rules/require-description/index.js +67 -49
- package/cjs/rules/require-field-of-type-query-in-mutation-result/index.js +21 -10
- package/cjs/rules/require-import-fragment/index.js +20 -11
- package/cjs/rules/require-nullable-fields-with-oneof/index.js +12 -5
- package/cjs/rules/require-nullable-result-in-root/index.js +32 -27
- package/cjs/rules/require-selections/index.js +88 -46
- package/cjs/rules/require-type-pattern-with-oneof/index.js +14 -10
- package/cjs/rules/selection-set-depth/index.js +19 -10
- package/cjs/rules/strict-id-in-types/index.js +32 -19
- package/cjs/rules/unique-enum-value-names/index.js +4 -3
- package/cjs/rules/unique-fragment-name/index.js +25 -18
- package/cjs/rules/unique-operation-name/index.js +5 -5
- package/cjs/schema.js +14 -8
- package/cjs/siblings.js +60 -32
- package/cjs/utils.js +23 -9
- package/esm/cache.js +6 -2
- package/esm/configs/operations-all.js +2 -2
- package/esm/configs/schema-all.js +2 -2
- package/esm/configs/schema-recommended.js +1 -1
- package/esm/documents.js +13 -7
- package/esm/estree-converter/converter.js +17 -8
- package/esm/estree-converter/utils.js +22 -9
- package/esm/graphql-config.js +13 -6
- package/esm/index.d.ts +19 -5
- package/esm/meta.js +1 -1
- package/esm/parser.js +36 -9
- package/esm/processor.js +48 -20
- package/esm/rules/alphabetize/index.js +99 -47
- package/esm/rules/description-style/index.js +10 -6
- package/esm/rules/graphql-js-validation.js +142 -108
- package/esm/rules/index.d.ts +19 -5
- package/esm/rules/input-name/index.js +51 -38
- package/esm/rules/lone-executable-definition/index.js +15 -6
- package/esm/rules/match-document-filename/index.d.ts +4 -3
- package/esm/rules/match-document-filename/index.js +63 -37
- package/esm/rules/naming-convention/index.d.ts +6 -10
- package/esm/rules/naming-convention/index.js +146 -57
- package/esm/rules/no-anonymous-operations/index.js +8 -5
- package/esm/rules/no-deprecated/index.js +27 -13
- package/esm/rules/no-duplicate-fields/index.js +15 -8
- package/esm/rules/no-hashtag-description/index.js +18 -10
- package/esm/rules/no-one-place-fragments/index.js +17 -10
- package/esm/rules/no-root-type/index.js +15 -8
- package/esm/rules/no-scalar-result-type-on-mutation/index.js +20 -12
- package/esm/rules/no-typename-prefix/index.js +25 -21
- package/esm/rules/no-unreachable-types/index.js +34 -17
- package/esm/rules/no-unused-fields/index.js +56 -30
- package/esm/rules/relay-arguments/index.js +31 -13
- package/esm/rules/relay-connection-types/index.js +31 -9
- package/esm/rules/relay-edge-types/index.js +84 -41
- package/esm/rules/relay-page-info/index.js +31 -14
- package/esm/rules/require-deprecation-date/index.js +20 -9
- package/esm/rules/require-deprecation-reason/index.js +8 -5
- package/esm/rules/require-description/index.d.ts +79 -13
- package/esm/rules/require-description/index.js +67 -49
- package/esm/rules/require-field-of-type-query-in-mutation-result/index.js +21 -10
- package/esm/rules/require-import-fragment/index.js +20 -11
- package/esm/rules/require-nullable-fields-with-oneof/index.js +12 -5
- package/esm/rules/require-nullable-result-in-root/index.js +32 -27
- package/esm/rules/require-selections/index.js +88 -46
- package/esm/rules/require-type-pattern-with-oneof/index.js +14 -10
- package/esm/rules/selection-set-depth/index.js +19 -10
- package/esm/rules/strict-id-in-types/index.js +32 -19
- package/esm/rules/unique-enum-value-names/index.js +4 -3
- package/esm/rules/unique-fragment-name/index.js +25 -18
- package/esm/rules/unique-operation-name/index.js +5 -5
- package/esm/schema.js +15 -8
- package/esm/siblings.js +60 -32
- package/esm/utils.js +23 -9
- package/index.browser.js +1838 -1135
- package/package.json +1 -1
@@ -3,25 +3,29 @@
|
|
3
3
|
var _graphql = require('graphql');
|
4
4
|
var _lodashlowercase = require('lodash.lowercase'); var _lodashlowercase2 = _interopRequireDefault(_lodashlowercase);
|
5
5
|
var _utilsjs = require('../../utils.js');
|
6
|
-
const RULE_ID = "alphabetize"
|
6
|
+
const RULE_ID = "alphabetize";
|
7
|
+
const fieldsEnum = [
|
7
8
|
_graphql.Kind.OBJECT_TYPE_DEFINITION,
|
8
9
|
_graphql.Kind.INTERFACE_TYPE_DEFINITION,
|
9
10
|
_graphql.Kind.INPUT_OBJECT_TYPE_DEFINITION
|
10
|
-
]
|
11
|
+
];
|
12
|
+
const selectionsEnum = [
|
11
13
|
_graphql.Kind.OPERATION_DEFINITION,
|
12
14
|
_graphql.Kind.FRAGMENT_DEFINITION
|
13
|
-
]
|
15
|
+
];
|
16
|
+
const argumentsEnum = [
|
14
17
|
_graphql.Kind.FIELD_DEFINITION,
|
15
18
|
_graphql.Kind.FIELD,
|
16
19
|
_graphql.Kind.DIRECTIVE_DEFINITION,
|
17
20
|
_graphql.Kind.DIRECTIVE
|
18
|
-
]
|
21
|
+
];
|
22
|
+
const schema = {
|
19
23
|
type: "array",
|
20
24
|
minItems: 1,
|
21
25
|
maxItems: 1,
|
22
26
|
items: {
|
23
27
|
type: "object",
|
24
|
-
additionalProperties:
|
28
|
+
additionalProperties: false,
|
25
29
|
minProperties: 1,
|
26
30
|
properties: {
|
27
31
|
fields: {
|
@@ -66,12 +70,12 @@ const RULE_ID = "alphabetize", fieldsEnum = [
|
|
66
70
|
"- `id` stands for field with name `id`",
|
67
71
|
"- `*` stands for everything else",
|
68
72
|
"- `{` stands for fields `selection set`"
|
69
|
-
].join(
|
70
|
-
`)
|
73
|
+
].join("\n")
|
71
74
|
}
|
72
75
|
}
|
73
76
|
}
|
74
|
-
}
|
77
|
+
};
|
78
|
+
const rule = {
|
75
79
|
meta: {
|
76
80
|
type: "suggestion",
|
77
81
|
fixable: "code",
|
@@ -112,7 +116,7 @@ const RULE_ID = "alphabetize", fieldsEnum = [
|
|
112
116
|
},
|
113
117
|
{
|
114
118
|
title: "Incorrect",
|
115
|
-
usage: [{ values:
|
119
|
+
usage: [{ values: true }],
|
116
120
|
code: (
|
117
121
|
/* GraphQL */
|
118
122
|
`
|
@@ -127,7 +131,7 @@ const RULE_ID = "alphabetize", fieldsEnum = [
|
|
127
131
|
},
|
128
132
|
{
|
129
133
|
title: "Correct",
|
130
|
-
usage: [{ values:
|
134
|
+
usage: [{ values: true }],
|
131
135
|
code: (
|
132
136
|
/* GraphQL */
|
133
137
|
`
|
@@ -176,18 +180,18 @@ const RULE_ID = "alphabetize", fieldsEnum = [
|
|
176
180
|
configOptions: {
|
177
181
|
schema: [
|
178
182
|
{
|
179
|
-
definitions:
|
183
|
+
definitions: true,
|
180
184
|
fields: fieldsEnum,
|
181
|
-
values:
|
185
|
+
values: true,
|
182
186
|
arguments: argumentsEnum,
|
183
187
|
groups: ["id", "*", "createdAt", "updatedAt"]
|
184
188
|
}
|
185
189
|
],
|
186
190
|
operations: [
|
187
191
|
{
|
188
|
-
definitions:
|
192
|
+
definitions: true,
|
189
193
|
selections: selectionsEnum,
|
190
|
-
variables:
|
194
|
+
variables: true,
|
191
195
|
arguments: [_graphql.Kind.FIELD, _graphql.Kind.DIRECTIVE],
|
192
196
|
groups: ["...", "id", "*", "{"]
|
193
197
|
}
|
@@ -206,43 +210,65 @@ const RULE_ID = "alphabetize", fieldsEnum = [
|
|
206
210
|
}
|
207
211
|
function getBeforeComments(node) {
|
208
212
|
const commentsBefore = sourceCode.getCommentsBefore(node);
|
209
|
-
if (commentsBefore.length === 0)
|
213
|
+
if (commentsBefore.length === 0) {
|
210
214
|
return [];
|
215
|
+
}
|
211
216
|
const tokenBefore = sourceCode.getTokenBefore(node);
|
212
|
-
if (tokenBefore)
|
217
|
+
if (tokenBefore) {
|
213
218
|
return commentsBefore.filter((comment) => !isNodeAndCommentOnSameLine(tokenBefore, comment));
|
214
|
-
|
219
|
+
}
|
220
|
+
const filteredComments = [];
|
221
|
+
const nodeLine = node.loc.start.line;
|
215
222
|
for (let i = commentsBefore.length - 1; i >= 0; i -= 1) {
|
216
223
|
const comment = commentsBefore[i];
|
217
|
-
if (nodeLine - comment.loc.start.line - filteredComments.length > 1)
|
224
|
+
if (nodeLine - comment.loc.start.line - filteredComments.length > 1) {
|
218
225
|
break;
|
226
|
+
}
|
219
227
|
filteredComments.unshift(comment);
|
220
228
|
}
|
221
229
|
return filteredComments;
|
222
230
|
}
|
223
231
|
function getRangeWithComments(node) {
|
224
|
-
node.kind === _graphql.Kind.VARIABLE
|
225
|
-
|
232
|
+
if (node.kind === _graphql.Kind.VARIABLE) {
|
233
|
+
node = node.parent;
|
234
|
+
}
|
235
|
+
const [firstBeforeComment] = getBeforeComments(node);
|
236
|
+
const [firstAfterComment] = sourceCode.getCommentsAfter(node);
|
237
|
+
const from = firstBeforeComment || node;
|
238
|
+
const to = firstAfterComment && isNodeAndCommentOnSameLine(node, firstAfterComment) ? firstAfterComment : node;
|
226
239
|
return [from.range[0], to.range[1]];
|
227
240
|
}
|
228
241
|
function checkNodes(nodes = []) {
|
229
242
|
for (let i = 1; i < nodes.length; i += 1) {
|
230
|
-
const currNode = nodes[i]
|
231
|
-
|
243
|
+
const currNode = nodes[i];
|
244
|
+
const currName = getName(currNode);
|
245
|
+
if (!currName) {
|
232
246
|
continue;
|
233
|
-
|
247
|
+
}
|
248
|
+
const prevNode = nodes[i - 1];
|
249
|
+
const prevName = getName(prevNode);
|
234
250
|
if (prevName) {
|
235
|
-
const compareResult = prevName.localeCompare(currName)
|
236
|
-
|
251
|
+
const compareResult = prevName.localeCompare(currName);
|
252
|
+
const { groups } = opts;
|
253
|
+
let shouldSortByGroup = false;
|
237
254
|
if (_optionalChain([groups, 'optionalAccess', _ => _.length])) {
|
238
|
-
if (!groups.includes("*"))
|
255
|
+
if (!groups.includes("*")) {
|
239
256
|
throw new Error("`groups` option should contain `*` string.");
|
240
|
-
|
241
|
-
|
257
|
+
}
|
258
|
+
const indexForPrev = getIndex({ node: prevNode, groups });
|
259
|
+
const indexForCurr = getIndex({ node: currNode, groups });
|
260
|
+
shouldSortByGroup = indexForPrev - indexForCurr > 0;
|
261
|
+
if (indexForPrev < indexForCurr) {
|
262
|
+
continue;
|
263
|
+
}
|
264
|
+
}
|
265
|
+
const shouldSort = compareResult === 1;
|
266
|
+
if (!shouldSortByGroup && !shouldSort) {
|
267
|
+
const isSameName = compareResult === 0;
|
268
|
+
if (!isSameName || !prevNode.kind.endsWith("Extension") || currNode.kind.endsWith("Extension")) {
|
242
269
|
continue;
|
270
|
+
}
|
243
271
|
}
|
244
|
-
if (!shouldSortByGroup && !(compareResult === 1) && (!(compareResult === 0) || !prevNode.kind.endsWith("Extension") || currNode.kind.endsWith("Extension")))
|
245
|
-
continue;
|
246
272
|
}
|
247
273
|
context.report({
|
248
274
|
// @ts-expect-error can't be undefined
|
@@ -253,11 +279,13 @@ const RULE_ID = "alphabetize", fieldsEnum = [
|
|
253
279
|
prevNode: prevName ? _utilsjs.displayNodeName.call(void 0, prevNode) : _lodashlowercase2.default.call(void 0, prevNode.kind)
|
254
280
|
},
|
255
281
|
*fix(fixer) {
|
256
|
-
const prevRange = getRangeWithComments(prevNode)
|
282
|
+
const prevRange = getRangeWithComments(prevNode);
|
283
|
+
const currRange = getRangeWithComments(currNode);
|
257
284
|
yield fixer.replaceTextRange(
|
258
285
|
prevRange,
|
259
286
|
sourceCode.getText({ range: currRange })
|
260
|
-
)
|
287
|
+
);
|
288
|
+
yield fixer.replaceTextRange(
|
261
289
|
currRange,
|
262
290
|
sourceCode.getText({ range: prevRange })
|
263
291
|
);
|
@@ -265,7 +293,10 @@ const RULE_ID = "alphabetize", fieldsEnum = [
|
|
265
293
|
});
|
266
294
|
}
|
267
295
|
}
|
268
|
-
const opts = context.options[0]
|
296
|
+
const opts = context.options[0];
|
297
|
+
const fields = new Set(_nullishCoalesce(opts.fields, () => ( [])));
|
298
|
+
const listeners = {};
|
299
|
+
const kinds = [
|
269
300
|
fields.has(_graphql.Kind.OBJECT_TYPE_DEFINITION) && [
|
270
301
|
_graphql.Kind.OBJECT_TYPE_DEFINITION,
|
271
302
|
_graphql.Kind.OBJECT_TYPE_EXTENSION
|
@@ -278,24 +309,42 @@ const RULE_ID = "alphabetize", fieldsEnum = [
|
|
278
309
|
_graphql.Kind.INPUT_OBJECT_TYPE_DEFINITION,
|
279
310
|
_graphql.Kind.INPUT_OBJECT_TYPE_EXTENSION
|
280
311
|
]
|
281
|
-
].filter((v) => !!v).flat()
|
282
|
-
|
283
|
-
|
284
|
-
|
312
|
+
].filter((v) => !!v).flat();
|
313
|
+
const fieldsSelector = kinds.join(",");
|
314
|
+
const selectionsSelector = _optionalChain([opts, 'access', _2 => _2.selections, 'optionalAccess', _3 => _3.join, 'call', _4 => _4(",")]);
|
315
|
+
const argumentsSelector = _optionalChain([opts, 'access', _5 => _5.arguments, 'optionalAccess', _6 => _6.join, 'call', _7 => _7(",")]);
|
316
|
+
if (fieldsSelector) {
|
317
|
+
listeners[fieldsSelector] = (node) => {
|
318
|
+
checkNodes(node.fields);
|
319
|
+
};
|
320
|
+
}
|
321
|
+
if (opts.values) {
|
285
322
|
const enumValuesSelector = [_graphql.Kind.ENUM_TYPE_DEFINITION, _graphql.Kind.ENUM_TYPE_EXTENSION].join(",");
|
286
323
|
listeners[enumValuesSelector] = (node) => {
|
287
324
|
checkNodes(node.values);
|
288
325
|
};
|
289
326
|
}
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
}
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
327
|
+
if (selectionsSelector) {
|
328
|
+
listeners[`:matches(${selectionsSelector}) SelectionSet`] = (node) => {
|
329
|
+
checkNodes(node.selections);
|
330
|
+
};
|
331
|
+
}
|
332
|
+
if (opts.variables) {
|
333
|
+
listeners.OperationDefinition = (node) => {
|
334
|
+
checkNodes(_optionalChain([node, 'access', _8 => _8.variableDefinitions, 'optionalAccess', _9 => _9.map, 'call', _10 => _10((varDef) => varDef.variable)]));
|
335
|
+
};
|
336
|
+
}
|
337
|
+
if (argumentsSelector) {
|
338
|
+
listeners[argumentsSelector] = (node) => {
|
339
|
+
checkNodes(node.arguments);
|
340
|
+
};
|
341
|
+
}
|
342
|
+
if (opts.definitions) {
|
343
|
+
listeners.Document = (node) => {
|
344
|
+
checkNodes(node.definitions);
|
345
|
+
};
|
346
|
+
}
|
347
|
+
return listeners;
|
299
348
|
}
|
300
349
|
};
|
301
350
|
function getIndex({
|
@@ -303,7 +352,10 @@ function getIndex({
|
|
303
352
|
groups
|
304
353
|
}) {
|
305
354
|
let index = groups.indexOf(getName(node));
|
306
|
-
|
355
|
+
if (index === -1 && "selectionSet" in node && node.selectionSet) index = groups.indexOf("{");
|
356
|
+
if (index === -1 && node.kind === _graphql.Kind.FRAGMENT_SPREAD) index = groups.indexOf("...");
|
357
|
+
if (index === -1) index = groups.indexOf("*");
|
358
|
+
return index;
|
307
359
|
}
|
308
360
|
function getName(node) {
|
309
361
|
return "alias" in node && _optionalChain([node, 'access', _11 => _11.alias, 'optionalAccess', _12 => _12.value]) || //
|
@@ -4,7 +4,7 @@ const schema = {
|
|
4
4
|
maxItems: 1,
|
5
5
|
items: {
|
6
6
|
type: "object",
|
7
|
-
additionalProperties:
|
7
|
+
additionalProperties: false,
|
8
8
|
minProperties: 1,
|
9
9
|
properties: {
|
10
10
|
style: {
|
@@ -13,10 +13,11 @@ const schema = {
|
|
13
13
|
}
|
14
14
|
}
|
15
15
|
}
|
16
|
-
}
|
16
|
+
};
|
17
|
+
const rule = {
|
17
18
|
meta: {
|
18
19
|
type: "suggestion",
|
19
|
-
hasSuggestions:
|
20
|
+
hasSuggestions: true,
|
20
21
|
docs: {
|
21
22
|
examples: [
|
22
23
|
{
|
@@ -49,12 +50,13 @@ const schema = {
|
|
49
50
|
description: "Require all comments to follow the same style (either block or inline).",
|
50
51
|
category: "Schema",
|
51
52
|
url: "https://the-guild.dev/graphql/eslint/rules/description-style",
|
52
|
-
recommended:
|
53
|
+
recommended: true
|
53
54
|
},
|
54
55
|
schema
|
55
56
|
},
|
56
57
|
create(context) {
|
57
|
-
const { style = "block" } = context.options[0] || {}
|
58
|
+
const { style = "block" } = context.options[0] || {};
|
59
|
+
const isBlock = style === "block";
|
58
60
|
return {
|
59
61
|
[`.description[type=StringValue][block!=${isBlock}]`](node) {
|
60
62
|
context.report({
|
@@ -66,7 +68,9 @@ const schema = {
|
|
66
68
|
{
|
67
69
|
desc: `Change to ${isBlock ? "block" : "inline"} style description`,
|
68
70
|
fix(fixer) {
|
69
|
-
const
|
71
|
+
const sourceCode = context.getSourceCode();
|
72
|
+
const originalText = sourceCode.getText(node);
|
73
|
+
const newText = isBlock ? originalText.replace(/(^")|("$)/g, '"""') : originalText.replace(/(^""")|("""$)/g, '"').replace(/\s+/g, " ");
|
70
74
|
return fixer.replaceText(node, newText);
|
71
75
|
}
|
72
76
|
}
|