@graphql-eslint/eslint-plugin 2.3.0-alpha-4c161e5.0 → 2.3.1
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/README.md +1 -1
- package/docs/README.md +1 -1
- package/docs/custom-rules.md +2 -2
- package/docs/rules/alphabetize.md +6 -1
- package/docs/rules/avoid-duplicate-fields.md +6 -1
- package/docs/rules/avoid-operation-name-prefix.md +5 -1
- package/docs/rules/avoid-scalar-result-type-on-mutation.md +6 -1
- package/docs/rules/avoid-typename-prefix.md +6 -1
- package/docs/rules/description-style.md +6 -1
- package/docs/rules/executable-definitions.md +6 -1
- package/docs/rules/fields-on-correct-type.md +6 -1
- package/docs/rules/fragments-on-composite-type.md +6 -1
- package/docs/rules/input-name.md +6 -1
- package/docs/rules/known-argument-names.md +6 -1
- package/docs/rules/known-directives.md +6 -1
- package/docs/rules/known-fragment-names.md +6 -1
- package/docs/rules/known-type-names.md +6 -1
- package/docs/rules/lone-anonymous-operation.md +6 -1
- package/docs/rules/lone-schema-definition.md +6 -1
- package/docs/rules/match-document-filename.md +6 -1
- package/docs/rules/naming-convention.md +6 -1
- package/docs/rules/no-anonymous-operations.md +6 -1
- package/docs/rules/no-case-insensitive-enum-values-duplicates.md +5 -1
- package/docs/rules/no-deprecated.md +6 -1
- package/docs/rules/no-fragment-cycles.md +6 -1
- package/docs/rules/no-hashtag-description.md +6 -1
- package/docs/rules/no-operation-name-suffix.md +5 -1
- package/docs/rules/no-undefined-variables.md +6 -1
- package/docs/rules/no-unreachable-types.md +6 -1
- package/docs/rules/no-unused-fields.md +6 -1
- package/docs/rules/no-unused-fragments.md +6 -1
- package/docs/rules/no-unused-variables.md +6 -1
- package/docs/rules/one-field-subscriptions.md +6 -1
- package/docs/rules/overlapping-fields-can-be-merged.md +6 -1
- package/docs/rules/possible-fragment-spread.md +6 -1
- package/docs/rules/possible-type-extension.md +6 -1
- package/docs/rules/provided-required-arguments.md +6 -1
- package/docs/rules/require-deprecation-date.md +6 -1
- package/docs/rules/require-deprecation-reason.md +6 -1
- package/docs/rules/require-description.md +6 -1
- package/docs/rules/require-field-of-type-query-in-mutation-result.md +6 -1
- package/docs/rules/require-id-when-available.md +6 -1
- package/docs/rules/scalar-leafs.md +6 -1
- package/docs/rules/selection-set-depth.md +6 -1
- package/docs/rules/strict-id-in-types.md +6 -1
- package/docs/rules/unique-argument-names.md +6 -1
- package/docs/rules/unique-directive-names-per-location.md +6 -1
- package/docs/rules/unique-directive-names.md +6 -1
- package/docs/rules/unique-enum-value-names.md +6 -1
- package/docs/rules/unique-field-definition-names.md +6 -1
- package/docs/rules/unique-fragment-name.md +6 -1
- package/docs/rules/unique-input-field-names.md +6 -1
- package/docs/rules/unique-operation-name.md +6 -1
- package/docs/rules/unique-operation-types.md +6 -1
- package/docs/rules/unique-type-names.md +6 -1
- package/docs/rules/unique-variable-names.md +6 -1
- package/docs/rules/value-literals-of-correct-type.md +6 -1
- package/docs/rules/variables-are-input-types.md +6 -1
- package/docs/rules/variables-in-allowed-position.md +6 -1
- package/estree-parser/estree-ast.d.ts +2 -2
- package/index.js +77 -35
- package/index.mjs +77 -35
- package/package.json +1 -1
- package/types.d.ts +2 -0
package/index.mjs
CHANGED
@@ -286,6 +286,7 @@ const validationToRule = (name, ruleName, docs, getDocumentNode) => {
|
|
286
286
|
meta: {
|
287
287
|
docs: {
|
288
288
|
...docs,
|
289
|
+
graphQLJSRuleName: ruleName,
|
289
290
|
category: 'Validation',
|
290
291
|
recommended: true,
|
291
292
|
requiresSchema,
|
@@ -314,6 +315,14 @@ const validationToRule = (name, ruleName, docs, getDocumentNode) => {
|
|
314
315
|
},
|
315
316
|
};
|
316
317
|
};
|
318
|
+
const importFiles = (context) => {
|
319
|
+
const code = context.getSourceCode().text;
|
320
|
+
if (!isGraphQLImportFile(code)) {
|
321
|
+
return null;
|
322
|
+
}
|
323
|
+
// Import documents because file contains '#import' comments
|
324
|
+
return processImport(context.getFilename());
|
325
|
+
};
|
317
326
|
const GRAPHQL_JS_VALIDATIONS = Object.assign({}, validationToRule('executable-definitions', 'ExecutableDefinitions', {
|
318
327
|
description: `A GraphQL document is only valid for execution if all definitions are either operation or fragment definitions.`,
|
319
328
|
}), validationToRule('fields-on-correct-type', 'FieldsOnCorrectType', {
|
@@ -390,14 +399,7 @@ const GRAPHQL_JS_VALIDATIONS = Object.assign({}, validationToRule('executable-de
|
|
390
399
|
\``,
|
391
400
|
},
|
392
401
|
],
|
393
|
-
},
|
394
|
-
const code = context.getSourceCode().text;
|
395
|
-
if (!isGraphQLImportFile(code)) {
|
396
|
-
return null;
|
397
|
-
}
|
398
|
-
// Import documents because file contains '#import' comments
|
399
|
-
return processImport(context.getFilename());
|
400
|
-
}), validationToRule('known-type-names', 'KnownTypeNames', {
|
402
|
+
}, importFiles), validationToRule('known-type-names', 'KnownTypeNames', {
|
401
403
|
description: `A GraphQL document is only valid if referenced types (specifically variable definitions and fragment conditions) are defined by the type schema.`,
|
402
404
|
}), validationToRule('lone-anonymous-operation', 'LoneAnonymousOperation', {
|
403
405
|
description: `A GraphQL document is only valid if when it contains an anonymous operation (the query short-hand) that it contains only that one operation definition.`,
|
@@ -408,7 +410,7 @@ const GRAPHQL_JS_VALIDATIONS = Object.assign({}, validationToRule('executable-de
|
|
408
410
|
description: `A GraphQL fragment is only valid when it does not have cycles in fragments usage.`,
|
409
411
|
}), validationToRule('no-undefined-variables', 'NoUndefinedVariables', {
|
410
412
|
description: `A GraphQL operation is only valid if all variables encountered, both directly and via fragment spreads, are defined by that operation.`,
|
411
|
-
}), validationToRule('no-unused-fragments', 'NoUnusedFragments', {
|
413
|
+
}, importFiles), validationToRule('no-unused-fragments', 'NoUnusedFragments', {
|
412
414
|
description: `A GraphQL document is only valid if all fragment definitions are spread within operations, or spread within other fragments spread within operations.`,
|
413
415
|
requiresSiblings: true,
|
414
416
|
}, context => {
|
@@ -439,7 +441,7 @@ const GRAPHQL_JS_VALIDATIONS = Object.assign({}, validationToRule('executable-de
|
|
439
441
|
return getParentNode(context.getFilename());
|
440
442
|
}), validationToRule('no-unused-variables', 'NoUnusedVariables', {
|
441
443
|
description: `A GraphQL operation is only valid if all variables defined by an operation are used, either directly or within a spread fragment.`,
|
442
|
-
}), validationToRule('overlapping-fields-can-be-merged', 'OverlappingFieldsCanBeMerged', {
|
444
|
+
}, importFiles), validationToRule('overlapping-fields-can-be-merged', 'OverlappingFieldsCanBeMerged', {
|
443
445
|
description: `A selection set is only valid if all fields (including spreading any fragments) either correspond to distinct response names or can be merged without ambiguity.`,
|
444
446
|
}), validationToRule('possible-fragment-spread', 'PossibleFragmentSpreads', {
|
445
447
|
description: `A fragment spread is only valid if the type condition could ever possibly be true: if there is a non-empty intersection of the possible parent types, and possible types which pass the type condition.`,
|
@@ -649,10 +651,7 @@ const rule = {
|
|
649
651
|
line: start.line,
|
650
652
|
column: start.column - (isVariableNode ? 2 : 1),
|
651
653
|
},
|
652
|
-
end
|
653
|
-
line: end.line,
|
654
|
-
column: end.column,
|
655
|
-
},
|
654
|
+
end,
|
656
655
|
},
|
657
656
|
messageId: ALPHABETIZE,
|
658
657
|
data: isVariableNode
|
@@ -783,6 +782,7 @@ const rule$1 = {
|
|
783
782
|
messages: {
|
784
783
|
[AVOID_DUPLICATE_FIELDS]: `{{ type }} "{{ fieldName }}" defined multiple times.`,
|
785
784
|
},
|
785
|
+
schema: [],
|
786
786
|
},
|
787
787
|
create(context) {
|
788
788
|
return {
|
@@ -902,15 +902,16 @@ const rule$2 = {
|
|
902
902
|
const testKeyword = caseSensitive ? keyword : keyword.toLowerCase();
|
903
903
|
const testName = caseSensitive ? node.name.value : node.name.value.toLowerCase();
|
904
904
|
if (testName.startsWith(testKeyword)) {
|
905
|
+
const { start } = node.name.loc;
|
905
906
|
context.report({
|
906
907
|
loc: {
|
907
908
|
start: {
|
908
|
-
line:
|
909
|
-
column:
|
909
|
+
line: start.line,
|
910
|
+
column: start.column - 1,
|
910
911
|
},
|
911
912
|
end: {
|
912
|
-
line:
|
913
|
-
column:
|
913
|
+
line: start.line,
|
914
|
+
column: start.column - 1 + testKeyword.length,
|
914
915
|
},
|
915
916
|
},
|
916
917
|
data: {
|
@@ -953,6 +954,7 @@ const rule$3 = {
|
|
953
954
|
},
|
954
955
|
],
|
955
956
|
},
|
957
|
+
schema: [],
|
956
958
|
},
|
957
959
|
create(context) {
|
958
960
|
const schema = requireGraphQLSchemaFromContext('avoid-scalar-result-type-on-mutation', context);
|
@@ -1008,22 +1010,33 @@ const rule$4 = {
|
|
1008
1010
|
messages: {
|
1009
1011
|
[AVOID_TYPENAME_PREFIX]: `Field "{{ fieldName }}" starts with the name of the parent type "{{ typeName }}"`,
|
1010
1012
|
},
|
1013
|
+
schema: [],
|
1011
1014
|
},
|
1012
1015
|
create(context) {
|
1013
1016
|
return {
|
1014
1017
|
'ObjectTypeDefinition, ObjectTypeExtension, InterfaceTypeDefinition, InterfaceTypeExtension'(node) {
|
1015
1018
|
const typeName = node.name.value;
|
1016
|
-
const lowerTypeName =
|
1019
|
+
const lowerTypeName = typeName.toLowerCase();
|
1017
1020
|
for (const field of node.fields) {
|
1018
|
-
const fieldName = field.name.value
|
1019
|
-
if (fieldName
|
1021
|
+
const fieldName = field.name.value;
|
1022
|
+
if (fieldName.toLowerCase().startsWith(lowerTypeName)) {
|
1023
|
+
const { start } = field.loc;
|
1020
1024
|
context.report({
|
1021
|
-
node: field.name,
|
1022
1025
|
data: {
|
1023
1026
|
fieldName,
|
1024
1027
|
typeName,
|
1025
1028
|
},
|
1026
1029
|
messageId: AVOID_TYPENAME_PREFIX,
|
1030
|
+
loc: {
|
1031
|
+
start: {
|
1032
|
+
line: start.line,
|
1033
|
+
column: start.column - 1,
|
1034
|
+
},
|
1035
|
+
end: {
|
1036
|
+
line: start.line,
|
1037
|
+
column: start.column - 1 + lowerTypeName.length,
|
1038
|
+
},
|
1039
|
+
},
|
1027
1040
|
});
|
1028
1041
|
}
|
1029
1042
|
}
|
@@ -1721,20 +1734,24 @@ const rule$9 = {
|
|
1721
1734
|
messages: {
|
1722
1735
|
[NO_ANONYMOUS_OPERATIONS]: `Anonymous GraphQL operations are forbidden. Please make sure to name your {{ operation }}!`,
|
1723
1736
|
},
|
1737
|
+
schema: [],
|
1724
1738
|
},
|
1725
1739
|
create(context) {
|
1726
1740
|
return {
|
1727
1741
|
OperationDefinition(node) {
|
1728
|
-
|
1742
|
+
var _a;
|
1743
|
+
const isAnonymous = (((_a = node.name) === null || _a === void 0 ? void 0 : _a.value) || '').length === 0;
|
1744
|
+
if (isAnonymous) {
|
1745
|
+
const { start } = node.loc;
|
1729
1746
|
context.report({
|
1730
1747
|
loc: {
|
1731
1748
|
start: {
|
1732
|
-
column:
|
1733
|
-
line:
|
1749
|
+
column: start.column - 1,
|
1750
|
+
line: start.line,
|
1734
1751
|
},
|
1735
1752
|
end: {
|
1736
|
-
column:
|
1737
|
-
line:
|
1753
|
+
column: start.column - 1 + node.operation.length,
|
1754
|
+
line: start.line,
|
1738
1755
|
},
|
1739
1756
|
},
|
1740
1757
|
data: {
|
@@ -1784,6 +1801,7 @@ const rule$a = {
|
|
1784
1801
|
messages: {
|
1785
1802
|
[ERROR_MESSAGE_ID]: `Case-insensitive enum values duplicates are not allowed! Found: "{{ found }}"`,
|
1786
1803
|
},
|
1804
|
+
schema: [],
|
1787
1805
|
},
|
1788
1806
|
create(context) {
|
1789
1807
|
return {
|
@@ -1878,6 +1896,7 @@ const rule$b = {
|
|
1878
1896
|
messages: {
|
1879
1897
|
[NO_DEPRECATED]: `This {{ type }} is marked as deprecated in your GraphQL schema {{ reason }}`,
|
1880
1898
|
},
|
1899
|
+
schema: [],
|
1881
1900
|
},
|
1882
1901
|
create(context) {
|
1883
1902
|
return {
|
@@ -1964,6 +1983,7 @@ const rule$c = {
|
|
1964
1983
|
],
|
1965
1984
|
},
|
1966
1985
|
type: 'suggestion',
|
1986
|
+
schema: [],
|
1967
1987
|
},
|
1968
1988
|
create(context) {
|
1969
1989
|
return {
|
@@ -2024,15 +2044,28 @@ const rule$d = {
|
|
2024
2044
|
messages: {
|
2025
2045
|
[NO_OPERATION_NAME_SUFFIX]: `Unnecessary "{{ invalidSuffix }}" suffix in your operation name!`,
|
2026
2046
|
},
|
2047
|
+
schema: [],
|
2027
2048
|
},
|
2028
2049
|
create(context) {
|
2029
2050
|
return {
|
2030
2051
|
'OperationDefinition, FragmentDefinition'(node) {
|
2031
|
-
|
2032
|
-
|
2033
|
-
|
2052
|
+
var _a;
|
2053
|
+
const name = ((_a = node.name) === null || _a === void 0 ? void 0 : _a.value) || '';
|
2054
|
+
if (name.length > 0) {
|
2055
|
+
const invalidSuffix = 'operation' in node ? node.operation : 'fragment';
|
2056
|
+
if (name.toLowerCase().endsWith(invalidSuffix)) {
|
2057
|
+
const { start, end } = node.name.loc;
|
2034
2058
|
context.report({
|
2035
|
-
|
2059
|
+
loc: {
|
2060
|
+
start: {
|
2061
|
+
column: start.column - 1 + name.length - invalidSuffix.length,
|
2062
|
+
line: start.line,
|
2063
|
+
},
|
2064
|
+
end: {
|
2065
|
+
column: end.column - 1 + name.length,
|
2066
|
+
line: end.line,
|
2067
|
+
},
|
2068
|
+
},
|
2036
2069
|
data: {
|
2037
2070
|
invalidSuffix,
|
2038
2071
|
},
|
@@ -2089,6 +2122,7 @@ const rule$e = {
|
|
2089
2122
|
},
|
2090
2123
|
fixable: 'code',
|
2091
2124
|
type: 'suggestion',
|
2125
|
+
schema: [],
|
2092
2126
|
},
|
2093
2127
|
create(context) {
|
2094
2128
|
const reachableTypes = requireReachableTypesFromContext(RULE_NAME, context);
|
@@ -2180,6 +2214,7 @@ const rule$f = {
|
|
2180
2214
|
},
|
2181
2215
|
fixable: 'code',
|
2182
2216
|
type: 'suggestion',
|
2217
|
+
schema: [],
|
2183
2218
|
},
|
2184
2219
|
create(context) {
|
2185
2220
|
const usedFields = requireUsedFieldsFromContext(RULE_NAME$1, context);
|
@@ -2445,6 +2480,7 @@ const rule$h = {
|
|
2445
2480
|
],
|
2446
2481
|
},
|
2447
2482
|
type: 'suggestion',
|
2483
|
+
schema: [],
|
2448
2484
|
},
|
2449
2485
|
create(context) {
|
2450
2486
|
return {
|
@@ -2481,15 +2517,18 @@ const DESCRIBABLE_NODES = [
|
|
2481
2517
|
function verifyRule(context, node) {
|
2482
2518
|
if (node) {
|
2483
2519
|
if (!node.description || !node.description.value || node.description.value.trim().length === 0) {
|
2520
|
+
const { start, end } = ('name' in node ? node.name : node).loc;
|
2484
2521
|
context.report({
|
2485
2522
|
loc: {
|
2486
2523
|
start: {
|
2487
|
-
line:
|
2488
|
-
column:
|
2524
|
+
line: start.line,
|
2525
|
+
column: start.column - 1,
|
2489
2526
|
},
|
2490
2527
|
end: {
|
2491
|
-
line:
|
2492
|
-
column:
|
2528
|
+
line: end.line,
|
2529
|
+
column:
|
2530
|
+
// node.name don't exist on SchemaDefinition
|
2531
|
+
'name' in node ? end.column - 1 + node.name.value.length : end.column,
|
2493
2532
|
},
|
2494
2533
|
},
|
2495
2534
|
messageId: REQUIRE_DESCRIPTION_ERROR,
|
@@ -2603,6 +2642,7 @@ const rule$j = {
|
|
2603
2642
|
},
|
2604
2643
|
],
|
2605
2644
|
},
|
2645
|
+
schema: [],
|
2606
2646
|
},
|
2607
2647
|
create(context) {
|
2608
2648
|
const schema = requireGraphQLSchemaFromContext(RULE_NAME$2, context);
|
@@ -3222,6 +3262,7 @@ const rule$n = {
|
|
3222
3262
|
messages: {
|
3223
3263
|
[UNIQUE_FRAGMENT_NAME]: 'Fragment named "{{ documentName }}" already defined in:\n{{ summary }}',
|
3224
3264
|
},
|
3265
|
+
schema: [],
|
3225
3266
|
},
|
3226
3267
|
create(context) {
|
3227
3268
|
return {
|
@@ -3284,6 +3325,7 @@ const rule$o = {
|
|
3284
3325
|
messages: {
|
3285
3326
|
[UNIQUE_OPERATION_NAME]: 'Operation named "{{ documentName }}" already defined in:\n{{ summary }}',
|
3286
3327
|
},
|
3328
|
+
schema: [],
|
3287
3329
|
},
|
3288
3330
|
create(context) {
|
3289
3331
|
return {
|
package/package.json
CHANGED
package/types.d.ts
CHANGED
@@ -56,9 +56,11 @@ export declare type RuleDocsInfo<T> = Rule.RuleMetaData & {
|
|
56
56
|
usage?: T;
|
57
57
|
}[];
|
58
58
|
optionsForConfig?: T;
|
59
|
+
graphQLJSRuleName?: string;
|
59
60
|
};
|
60
61
|
};
|
61
62
|
export declare type GraphQLESLintRule<Options = any[], WithTypeInfo extends boolean = false> = {
|
62
63
|
create(context: GraphQLESLintRuleContext<Options>): GraphQLESLintRuleListener<WithTypeInfo>;
|
63
64
|
meta: Rule.RuleMetaData & RuleDocsInfo<Options>;
|
64
65
|
};
|
66
|
+
export declare type ValueOf<T> = T[keyof T];
|