@graphql-eslint/eslint-plugin 2.4.0-alpha-0a1c477.0 → 3.0.0-alpha-5388f29.0
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/configs/all.d.ts +29 -1
- package/configs/index.d.ts +58 -2
- package/configs/recommended.d.ts +29 -1
- package/docs/rules/alphabetize.md +35 -10
- package/docs/rules/description-style.md +2 -2
- package/docs/rules/match-document-filename.md +7 -7
- package/docs/rules/naming-convention.md +54 -83
- package/docs/rules/no-deprecated.md +2 -2
- package/docs/rules/strict-id-in-types.md +4 -4
- package/estree-parser/converter.d.ts +3 -2
- package/index.js +256 -261
- package/index.mjs +256 -261
- package/package.json +1 -1
- package/rules/alphabetize.d.ts +5 -6
- package/rules/index.d.ts +122 -20
- package/rules/naming-convention.d.ts +32 -25
- package/rules/require-description.d.ts +1 -2
- package/testkit.d.ts +1 -1
- package/utils.d.ts +2 -7
package/index.mjs
CHANGED
@@ -29,7 +29,34 @@ const recommendedConfig = {
|
|
29
29
|
'@graphql-eslint/known-type-names': 'error',
|
30
30
|
'@graphql-eslint/lone-anonymous-operation': 'error',
|
31
31
|
'@graphql-eslint/lone-schema-definition': 'error',
|
32
|
-
'@graphql-eslint/naming-convention':
|
32
|
+
'@graphql-eslint/naming-convention': [
|
33
|
+
'error',
|
34
|
+
{
|
35
|
+
types: 'PascalCase',
|
36
|
+
fields: 'camelCase',
|
37
|
+
overrides: {
|
38
|
+
EnumValueDefinition: 'UPPER_CASE',
|
39
|
+
OperationDefinition: {
|
40
|
+
style: 'PascalCase',
|
41
|
+
forbiddenPrefixes: ['Query', 'Mutation', 'Subscription', 'Get'],
|
42
|
+
forbiddenSuffixes: ['Query', 'Mutation', 'Subscription'],
|
43
|
+
},
|
44
|
+
FragmentDefinition: { style: 'PascalCase', forbiddenPrefixes: ['Fragment'], forbiddenSuffixes: ['Fragment'] },
|
45
|
+
'FieldDefinition[parent.name.value=Query]': {
|
46
|
+
forbiddenPrefixes: ['query', 'get'],
|
47
|
+
forbiddenSuffixes: ['Query'],
|
48
|
+
},
|
49
|
+
'FieldDefinition[parent.name.value=Mutation]': {
|
50
|
+
forbiddenPrefixes: ['mutation'],
|
51
|
+
forbiddenSuffixes: ['Mutation'],
|
52
|
+
},
|
53
|
+
'FieldDefinition[parent.name.value=Subscription]': {
|
54
|
+
forbiddenPrefixes: ['subscription'],
|
55
|
+
forbiddenSuffixes: ['Subscription'],
|
56
|
+
},
|
57
|
+
},
|
58
|
+
},
|
59
|
+
],
|
33
60
|
'@graphql-eslint/no-anonymous-operations': 'error',
|
34
61
|
'@graphql-eslint/no-case-insensitive-enum-values-duplicates': 'error',
|
35
62
|
'@graphql-eslint/no-fragment-cycles': 'error',
|
@@ -205,9 +232,14 @@ const loaderCache = new Proxy(Object.create(null), {
|
|
205
232
|
return true;
|
206
233
|
},
|
207
234
|
});
|
208
|
-
const
|
209
|
-
|
210
|
-
|
235
|
+
const TYPES_KINDS = [
|
236
|
+
Kind.OBJECT_TYPE_DEFINITION,
|
237
|
+
Kind.INTERFACE_TYPE_DEFINITION,
|
238
|
+
Kind.ENUM_TYPE_DEFINITION,
|
239
|
+
Kind.SCALAR_TYPE_DEFINITION,
|
240
|
+
Kind.INPUT_OBJECT_TYPE_DEFINITION,
|
241
|
+
Kind.UNION_TYPE_DEFINITION,
|
242
|
+
];
|
211
243
|
var CaseStyle;
|
212
244
|
(function (CaseStyle) {
|
213
245
|
CaseStyle["camelCase"] = "camelCase";
|
@@ -258,7 +290,7 @@ function getLocation(loc, fieldName = '', offset) {
|
|
258
290
|
}
|
259
291
|
|
260
292
|
function extractRuleName(stack) {
|
261
|
-
const match = (stack || '').match(/validation[
|
293
|
+
const match = (stack || '').match(/validation[/\\]rules[/\\](.*?)\.js:/) || [];
|
262
294
|
return match[1] || null;
|
263
295
|
}
|
264
296
|
function validateDoc(sourceNode, context, schema, documentNode, rules, ruleName = null) {
|
@@ -619,38 +651,48 @@ const rule = {
|
|
619
651
|
properties: {
|
620
652
|
fields: {
|
621
653
|
type: 'array',
|
622
|
-
|
654
|
+
uniqueItems: true,
|
655
|
+
minItems: 1,
|
656
|
+
items: {
|
623
657
|
enum: fieldsEnum,
|
624
658
|
},
|
625
|
-
description: 'Fields of `type`, `interface`, and `input
|
659
|
+
description: 'Fields of `type`, `interface`, and `input`',
|
626
660
|
},
|
627
661
|
values: {
|
628
662
|
type: 'array',
|
629
|
-
|
663
|
+
uniqueItems: true,
|
664
|
+
minItems: 1,
|
665
|
+
items: {
|
630
666
|
enum: valuesEnum,
|
631
667
|
},
|
632
|
-
description: 'Values of `enum
|
668
|
+
description: 'Values of `enum`',
|
633
669
|
},
|
634
670
|
selections: {
|
635
671
|
type: 'array',
|
636
|
-
|
672
|
+
uniqueItems: true,
|
673
|
+
minItems: 1,
|
674
|
+
items: {
|
637
675
|
enum: selectionsEnum,
|
638
676
|
},
|
639
|
-
description: 'Selections of operations (`query`, `mutation` and `subscription`) and `fragment
|
677
|
+
description: 'Selections of operations (`query`, `mutation` and `subscription`) and `fragment`',
|
640
678
|
},
|
641
679
|
variables: {
|
642
680
|
type: 'array',
|
643
|
-
|
681
|
+
uniqueItems: true,
|
682
|
+
minItems: 1,
|
683
|
+
items: {
|
644
684
|
enum: variablesEnum,
|
645
685
|
},
|
646
|
-
description: 'Variables of operations (`query`, `mutation` and `subscription`)
|
686
|
+
description: 'Variables of operations (`query`, `mutation` and `subscription`)',
|
647
687
|
},
|
648
688
|
arguments: {
|
649
689
|
type: 'array',
|
650
|
-
|
690
|
+
uniqueItems: true,
|
691
|
+
minItems: 1,
|
692
|
+
items: {
|
651
693
|
enum: argumentsEnum,
|
652
694
|
},
|
653
|
-
description: 'Arguments of fields and directives
|
695
|
+
description: 'Arguments of fields and directives',
|
654
696
|
},
|
655
697
|
},
|
656
698
|
},
|
@@ -681,7 +723,7 @@ const rule = {
|
|
681
723
|
const opts = context.options[0];
|
682
724
|
const fields = new Set((_a = opts.fields) !== null && _a !== void 0 ? _a : []);
|
683
725
|
const listeners = {};
|
684
|
-
const
|
726
|
+
const kinds = [
|
685
727
|
fields.has(Kind.OBJECT_TYPE_DEFINITION) && [Kind.OBJECT_TYPE_DEFINITION, Kind.OBJECT_TYPE_EXTENSION],
|
686
728
|
fields.has(Kind.INTERFACE_TYPE_DEFINITION) && [Kind.INTERFACE_TYPE_DEFINITION, Kind.INTERFACE_TYPE_EXTENSION],
|
687
729
|
fields.has(Kind.INPUT_OBJECT_TYPE_DEFINITION) && [
|
@@ -689,8 +731,9 @@ const rule = {
|
|
689
731
|
Kind.INPUT_OBJECT_TYPE_EXTENSION,
|
690
732
|
],
|
691
733
|
]
|
692
|
-
.
|
693
|
-
.
|
734
|
+
.filter(Boolean)
|
735
|
+
.flat();
|
736
|
+
const fieldsSelector = kinds.join(',');
|
694
737
|
const hasEnumValues = ((_b = opts.values) === null || _b === void 0 ? void 0 : _b[0]) === Kind.ENUM_TYPE_DEFINITION;
|
695
738
|
const selectionsSelector = (_c = opts.selections) === null || _c === void 0 ? void 0 : _c.join(',');
|
696
739
|
const hasVariables = ((_d = opts.variables) === null || _d === void 0 ? void 0 : _d[0]) === Kind.OPERATION_DEFINITION;
|
@@ -1090,6 +1133,9 @@ const rule$5 = {
|
|
1090
1133
|
},
|
1091
1134
|
};
|
1092
1135
|
|
1136
|
+
const isObjectType = (node) => [Kind.OBJECT_TYPE_DEFINITION, Kind.OBJECT_TYPE_EXTENSION].includes(node.type);
|
1137
|
+
const isQueryType = (node) => isObjectType(node) && node.name.value === 'Query';
|
1138
|
+
const isMutationType = (node) => isObjectType(node) && node.name.value === 'Mutation';
|
1093
1139
|
const rule$6 = {
|
1094
1140
|
meta: {
|
1095
1141
|
type: 'suggestion',
|
@@ -1130,6 +1176,7 @@ const rule$6 = {
|
|
1130
1176
|
schema: [
|
1131
1177
|
{
|
1132
1178
|
type: 'object',
|
1179
|
+
additionalProperties: false,
|
1133
1180
|
properties: {
|
1134
1181
|
checkInputType: {
|
1135
1182
|
type: 'boolean',
|
@@ -1152,24 +1199,22 @@ const rule$6 = {
|
|
1152
1199
|
description: 'Apply the rule to Mutations',
|
1153
1200
|
},
|
1154
1201
|
},
|
1155
|
-
additionalProperties: false,
|
1156
1202
|
},
|
1157
1203
|
],
|
1158
1204
|
},
|
1159
1205
|
create(context) {
|
1160
|
-
var _a;
|
1161
1206
|
const options = {
|
1162
|
-
caseSensitiveInputType: true,
|
1163
1207
|
checkInputType: false,
|
1164
|
-
|
1208
|
+
caseSensitiveInputType: true,
|
1165
1209
|
checkQueries: false,
|
1166
|
-
|
1210
|
+
checkMutations: true,
|
1211
|
+
...context.options[0],
|
1167
1212
|
};
|
1168
1213
|
const shouldCheckType = node => (options.checkMutations && isMutationType(node)) || (options.checkQueries && isQueryType(node));
|
1169
1214
|
const listeners = {
|
1170
|
-
'FieldDefinition > InputValueDefinition'
|
1171
|
-
|
1172
|
-
|
1215
|
+
'FieldDefinition > InputValueDefinition[name.value!=input]'(node) {
|
1216
|
+
if (shouldCheckType(node.parent.parent)) {
|
1217
|
+
const name = node.name.value;
|
1173
1218
|
context.report({
|
1174
1219
|
loc: getLocation(node.loc, name),
|
1175
1220
|
message: `Input "${name}" should be called "input"`,
|
@@ -1177,11 +1222,11 @@ const rule$6 = {
|
|
1177
1222
|
}
|
1178
1223
|
},
|
1179
1224
|
};
|
1180
|
-
if (options
|
1181
|
-
listeners['FieldDefinition > InputValueDefinition NamedType'] = node => {
|
1225
|
+
if (options.checkInputType) {
|
1226
|
+
listeners['FieldDefinition > InputValueDefinition NamedType'] = (node) => {
|
1182
1227
|
const findInputType = item => {
|
1183
1228
|
let currentNode = item;
|
1184
|
-
while (currentNode.type !==
|
1229
|
+
while (currentNode.type !== Kind.INPUT_VALUE_DEFINITION) {
|
1185
1230
|
currentNode = currentNode.parent;
|
1186
1231
|
}
|
1187
1232
|
return currentNode;
|
@@ -1398,69 +1443,40 @@ const rule$7 = {
|
|
1398
1443
|
},
|
1399
1444
|
};
|
1400
1445
|
|
1401
|
-
const
|
1402
|
-
|
1403
|
-
|
1404
|
-
|
1405
|
-
|
1406
|
-
|
1407
|
-
const acceptedStyles = [
|
1408
|
-
'camelCase',
|
1409
|
-
'PascalCase',
|
1410
|
-
'snake_case',
|
1411
|
-
'UPPER_CASE',
|
1446
|
+
const FIELDS_KINDS = [
|
1447
|
+
Kind.FIELD_DEFINITION,
|
1448
|
+
Kind.INPUT_VALUE_DEFINITION,
|
1449
|
+
Kind.VARIABLE_DEFINITION,
|
1450
|
+
Kind.ARGUMENT,
|
1451
|
+
Kind.DIRECTIVE_DEFINITION,
|
1412
1452
|
];
|
1413
|
-
|
1414
|
-
|
1415
|
-
|
1416
|
-
|
1417
|
-
|
1418
|
-
|
1419
|
-
|
1420
|
-
|
1421
|
-
|
1422
|
-
|
1423
|
-
|
1424
|
-
|
1425
|
-
|
1426
|
-
|
1427
|
-
|
1428
|
-
|
1429
|
-
|
1430
|
-
|
1431
|
-
|
1432
|
-
|
1433
|
-
|
1434
|
-
|
1435
|
-
|
1436
|
-
|
1437
|
-
|
1438
|
-
|
1439
|
-
|
1440
|
-
if (forbiddenPrefixes.some(forbiddenPrefix => name.startsWith(forbiddenPrefix))) {
|
1441
|
-
return {
|
1442
|
-
ok: false,
|
1443
|
-
errorMessage: '{{nodeType}} "{{nodeName}}" should not have one of the following prefix(es): {{forbiddenPrefixes}}',
|
1444
|
-
};
|
1445
|
-
}
|
1446
|
-
if (forbiddenSuffixes.some(forbiddenSuffix => name.endsWith(forbiddenSuffix))) {
|
1447
|
-
return {
|
1448
|
-
ok: false,
|
1449
|
-
errorMessage: '{{nodeType}} "{{nodeName}}" should not have one of the following suffix(es): {{forbiddenSuffixes}}',
|
1450
|
-
};
|
1451
|
-
}
|
1452
|
-
if (!formats[style]) {
|
1453
|
-
return { ok: true };
|
1454
|
-
}
|
1455
|
-
const ok = new RegExp(formats[style]).test(name);
|
1456
|
-
if (ok) {
|
1457
|
-
return { ok: true };
|
1458
|
-
}
|
1459
|
-
return {
|
1460
|
-
ok: false,
|
1461
|
-
errorMessage: '{{nodeType}} name "{{nodeName}}" should be in {{format}} format',
|
1462
|
-
};
|
1463
|
-
}
|
1453
|
+
const KindToDisplayName = {
|
1454
|
+
// types
|
1455
|
+
[Kind.OBJECT_TYPE_DEFINITION]: 'Type',
|
1456
|
+
[Kind.INTERFACE_TYPE_DEFINITION]: 'Interface',
|
1457
|
+
[Kind.ENUM_TYPE_DEFINITION]: 'Enumerator',
|
1458
|
+
[Kind.SCALAR_TYPE_DEFINITION]: 'Scalar',
|
1459
|
+
[Kind.INPUT_OBJECT_TYPE_DEFINITION]: 'Input type',
|
1460
|
+
[Kind.UNION_TYPE_DEFINITION]: 'Union',
|
1461
|
+
// fields
|
1462
|
+
[Kind.FIELD_DEFINITION]: 'Field',
|
1463
|
+
[Kind.INPUT_VALUE_DEFINITION]: 'Input property',
|
1464
|
+
[Kind.VARIABLE_DEFINITION]: 'Variable',
|
1465
|
+
[Kind.ARGUMENT]: 'Argument',
|
1466
|
+
[Kind.DIRECTIVE_DEFINITION]: 'Directive',
|
1467
|
+
// rest
|
1468
|
+
[Kind.ENUM_VALUE_DEFINITION]: 'Enumeration value',
|
1469
|
+
[Kind.OPERATION_DEFINITION]: 'Operation',
|
1470
|
+
[Kind.FRAGMENT_DEFINITION]: 'Fragment',
|
1471
|
+
};
|
1472
|
+
const StyleToRegex = {
|
1473
|
+
camelCase: /^[a-z][\dA-Za-z]*$/,
|
1474
|
+
PascalCase: /^[A-Z][\dA-Za-z]*$/,
|
1475
|
+
snake_case: /^[a-z][\d_a-z]*[\da-z]$/,
|
1476
|
+
UPPER_CASE: /^[A-Z][\dA-Z_]*[\dA-Z]$/,
|
1477
|
+
};
|
1478
|
+
const ALLOWED_KINDS = Object.keys(KindToDisplayName).sort();
|
1479
|
+
const ALLOWED_STYLES = Object.keys(StyleToRegex);
|
1464
1480
|
const schemaOption$1 = {
|
1465
1481
|
oneOf: [{ $ref: '#/definitions/asString' }, { $ref: '#/definitions/asObject' }],
|
1466
1482
|
};
|
@@ -1475,89 +1491,120 @@ const rule$8 = {
|
|
1475
1491
|
examples: [
|
1476
1492
|
{
|
1477
1493
|
title: 'Incorrect',
|
1478
|
-
usage: [{
|
1494
|
+
usage: [{ types: 'PascalCase', fields: 'camelCase' }],
|
1479
1495
|
code: /* GraphQL */ `
|
1480
|
-
type
|
1481
|
-
|
1496
|
+
type user {
|
1497
|
+
first_name: String!
|
1482
1498
|
}
|
1483
1499
|
`,
|
1484
1500
|
},
|
1485
1501
|
{
|
1486
1502
|
title: 'Correct',
|
1487
|
-
usage: [{
|
1503
|
+
usage: [{ types: 'PascalCase', fields: 'camelCase' }],
|
1488
1504
|
code: /* GraphQL */ `
|
1489
|
-
type
|
1490
|
-
|
1505
|
+
type User {
|
1506
|
+
firstName: String
|
1491
1507
|
}
|
1492
1508
|
`,
|
1493
1509
|
},
|
1494
1510
|
],
|
1511
|
+
optionsForConfig: [
|
1512
|
+
{
|
1513
|
+
types: 'PascalCase',
|
1514
|
+
fields: 'camelCase',
|
1515
|
+
overrides: {
|
1516
|
+
EnumValueDefinition: 'UPPER_CASE',
|
1517
|
+
OperationDefinition: {
|
1518
|
+
style: 'PascalCase',
|
1519
|
+
forbiddenPrefixes: ['Query', 'Mutation', 'Subscription', 'Get'],
|
1520
|
+
forbiddenSuffixes: ['Query', 'Mutation', 'Subscription'],
|
1521
|
+
},
|
1522
|
+
FragmentDefinition: {
|
1523
|
+
style: 'PascalCase',
|
1524
|
+
forbiddenPrefixes: ['Fragment'],
|
1525
|
+
forbiddenSuffixes: ['Fragment'],
|
1526
|
+
},
|
1527
|
+
'FieldDefinition[parent.name.value=Query]': {
|
1528
|
+
forbiddenPrefixes: ['query', 'get'],
|
1529
|
+
forbiddenSuffixes: ['Query'],
|
1530
|
+
},
|
1531
|
+
'FieldDefinition[parent.name.value=Mutation]': {
|
1532
|
+
forbiddenPrefixes: ['mutation'],
|
1533
|
+
forbiddenSuffixes: ['Mutation'],
|
1534
|
+
},
|
1535
|
+
'FieldDefinition[parent.name.value=Subscription]': {
|
1536
|
+
forbiddenPrefixes: ['subscription'],
|
1537
|
+
forbiddenSuffixes: ['Subscription'],
|
1538
|
+
},
|
1539
|
+
},
|
1540
|
+
},
|
1541
|
+
],
|
1495
1542
|
},
|
1496
1543
|
schema: {
|
1497
1544
|
definitions: {
|
1498
1545
|
asString: {
|
1499
|
-
|
1500
|
-
description: `One of: ${
|
1501
|
-
enum: acceptedStyles,
|
1546
|
+
enum: ALLOWED_STYLES,
|
1547
|
+
description: `One of: ${ALLOWED_STYLES.map(t => `\`${t}\``).join(', ')}`,
|
1502
1548
|
},
|
1503
1549
|
asObject: {
|
1504
1550
|
type: 'object',
|
1551
|
+
additionalProperties: false,
|
1505
1552
|
properties: {
|
1506
|
-
style: {
|
1507
|
-
|
1508
|
-
|
1509
|
-
},
|
1510
|
-
prefix: {
|
1511
|
-
type: 'string',
|
1512
|
-
},
|
1513
|
-
suffix: {
|
1514
|
-
type: 'string',
|
1515
|
-
},
|
1553
|
+
style: { enum: ALLOWED_STYLES },
|
1554
|
+
prefix: { type: 'string' },
|
1555
|
+
suffix: { type: 'string' },
|
1516
1556
|
forbiddenPrefixes: {
|
1517
|
-
additionalItems: false,
|
1518
1557
|
type: 'array',
|
1558
|
+
uniqueItems: true,
|
1519
1559
|
minItems: 1,
|
1520
|
-
items: {
|
1521
|
-
type: 'string',
|
1522
|
-
},
|
1560
|
+
items: { type: 'string' },
|
1523
1561
|
},
|
1524
1562
|
forbiddenSuffixes: {
|
1525
|
-
additionalItems: false,
|
1526
1563
|
type: 'array',
|
1564
|
+
uniqueItems: true,
|
1527
1565
|
minItems: 1,
|
1528
|
-
items: {
|
1529
|
-
type: 'string',
|
1530
|
-
},
|
1566
|
+
items: { type: 'string' },
|
1531
1567
|
},
|
1532
1568
|
},
|
1533
1569
|
},
|
1534
1570
|
},
|
1535
|
-
$schema: 'http://json-schema.org/draft-04/schema#',
|
1536
1571
|
type: 'array',
|
1572
|
+
maxItems: 1,
|
1537
1573
|
items: {
|
1538
1574
|
type: 'object',
|
1575
|
+
additionalProperties: false,
|
1539
1576
|
properties: {
|
1540
|
-
|
1541
|
-
|
1542
|
-
|
1543
|
-
[Kind.INPUT_VALUE_DEFINITION]: schemaOption$1,
|
1544
|
-
[Kind.OBJECT_TYPE_DEFINITION]: schemaOption$1,
|
1545
|
-
[Kind.INTERFACE_TYPE_DEFINITION]: schemaOption$1,
|
1546
|
-
[Kind.ENUM_TYPE_DEFINITION]: schemaOption$1,
|
1547
|
-
[Kind.UNION_TYPE_DEFINITION]: schemaOption$1,
|
1548
|
-
[Kind.SCALAR_TYPE_DEFINITION]: schemaOption$1,
|
1549
|
-
[Kind.OPERATION_DEFINITION]: schemaOption$1,
|
1550
|
-
[Kind.FRAGMENT_DEFINITION]: schemaOption$1,
|
1551
|
-
QueryDefinition: schemaOption$1,
|
1552
|
-
leadingUnderscore: {
|
1553
|
-
type: 'string',
|
1554
|
-
enum: ['allow', 'forbid'],
|
1555
|
-
default: 'forbid',
|
1577
|
+
types: {
|
1578
|
+
...schemaOption$1,
|
1579
|
+
description: `Includes:\n\n${TYPES_KINDS.map(kind => `- \`${kind}\``).join('\n')}`,
|
1556
1580
|
},
|
1557
|
-
|
1558
|
-
|
1559
|
-
|
1560
|
-
|
1581
|
+
fields: {
|
1582
|
+
...schemaOption$1,
|
1583
|
+
description: `Includes:\n\n${FIELDS_KINDS.map(kind => `- \`${kind}\``).join('\n')}`,
|
1584
|
+
},
|
1585
|
+
allowLeadingUnderscore: {
|
1586
|
+
type: 'boolean',
|
1587
|
+
default: false,
|
1588
|
+
},
|
1589
|
+
allowTrailingUnderscore: {
|
1590
|
+
type: 'boolean',
|
1591
|
+
default: false,
|
1592
|
+
},
|
1593
|
+
overrides: {
|
1594
|
+
type: 'object',
|
1595
|
+
additionalProperties: false,
|
1596
|
+
description: [
|
1597
|
+
'May contain the following `ASTNode` names:',
|
1598
|
+
'',
|
1599
|
+
...ALLOWED_KINDS.map(kind => `- \`${kind}\``),
|
1600
|
+
'',
|
1601
|
+
"> It's also possible to use a [`selector`](https://eslint.org/docs/developer-guide/selectors) that starts with `ASTNode` name",
|
1602
|
+
'>',
|
1603
|
+
'> Example: pattern property `FieldDefinition[parent.name.value=Query]` will match only fields for type `Query`',
|
1604
|
+
].join('\n'),
|
1605
|
+
patternProperties: {
|
1606
|
+
[`^(${ALLOWED_KINDS.join('|')})(.+)?$`]: schemaOption$1,
|
1607
|
+
},
|
1561
1608
|
},
|
1562
1609
|
},
|
1563
1610
|
},
|
@@ -1565,136 +1612,83 @@ const rule$8 = {
|
|
1565
1612
|
},
|
1566
1613
|
create(context) {
|
1567
1614
|
const options = {
|
1568
|
-
|
1569
|
-
|
1570
|
-
...(context.options[0] || {}),
|
1615
|
+
overrides: {},
|
1616
|
+
...context.options[0],
|
1571
1617
|
};
|
1572
|
-
|
1573
|
-
|
1574
|
-
|
1575
|
-
|
1576
|
-
|
1577
|
-
|
1578
|
-
|
1579
|
-
|
1580
|
-
|
1581
|
-
|
1582
|
-
|
1583
|
-
}
|
1584
|
-
|
1618
|
+
function normalisePropertyOption(kind) {
|
1619
|
+
let style = options.overrides[kind];
|
1620
|
+
if (!style) {
|
1621
|
+
style = TYPES_KINDS.includes(kind) ? options.types : options.fields;
|
1622
|
+
}
|
1623
|
+
return typeof style === 'object' ? style : { style };
|
1624
|
+
}
|
1625
|
+
const checkNode = (selector) => (node) => {
|
1626
|
+
const { name } = node.kind === Kind.VARIABLE_DEFINITION ? node.variable : node;
|
1627
|
+
if (!name) {
|
1628
|
+
return;
|
1629
|
+
}
|
1630
|
+
const { prefix, suffix, forbiddenPrefixes, forbiddenSuffixes, style } = normalisePropertyOption(selector);
|
1631
|
+
const nodeType = KindToDisplayName[node.kind] || node.kind;
|
1632
|
+
const nodeName = name.value;
|
1633
|
+
const errorMessage = getErrorMessage();
|
1634
|
+
if (errorMessage) {
|
1585
1635
|
context.report({
|
1586
|
-
loc: getLocation(
|
1587
|
-
message:
|
1588
|
-
data: {
|
1589
|
-
prefix,
|
1590
|
-
suffix,
|
1591
|
-
format: style,
|
1592
|
-
forbiddenPrefixes: forbiddenPrefixes.join(', '),
|
1593
|
-
forbiddenSuffixes: forbiddenSuffixes.join(', '),
|
1594
|
-
nodeType,
|
1595
|
-
nodeName: node.value,
|
1596
|
-
},
|
1636
|
+
loc: getLocation(name.loc, name.value),
|
1637
|
+
message: `${nodeType} "${nodeName}" should ${errorMessage}`,
|
1597
1638
|
});
|
1598
1639
|
}
|
1599
|
-
|
1600
|
-
|
1601
|
-
|
1602
|
-
|
1603
|
-
}
|
1604
|
-
return {
|
1605
|
-
style: value,
|
1606
|
-
prefix: '',
|
1607
|
-
suffix: '',
|
1608
|
-
};
|
1609
|
-
};
|
1610
|
-
return {
|
1611
|
-
Name: node => {
|
1612
|
-
if (node.value.startsWith('_') && options.leadingUnderscore === 'forbid') {
|
1613
|
-
context.report({
|
1614
|
-
loc: getLocation(node.loc, node.value),
|
1615
|
-
message: 'Leading underscores are not allowed',
|
1616
|
-
});
|
1640
|
+
function getErrorMessage() {
|
1641
|
+
let name = nodeName;
|
1642
|
+
if (options.allowLeadingUnderscore) {
|
1643
|
+
name = name.replace(/^_*/, '');
|
1617
1644
|
}
|
1618
|
-
if (
|
1619
|
-
|
1620
|
-
loc: getLocation(node.loc, node.value),
|
1621
|
-
message: 'Trailing underscores are not allowed',
|
1622
|
-
});
|
1645
|
+
if (options.allowTrailingUnderscore) {
|
1646
|
+
name = name.replace(/_*$/, '');
|
1623
1647
|
}
|
1624
|
-
|
1625
|
-
|
1626
|
-
if (options.ObjectTypeDefinition) {
|
1627
|
-
const property = normalisePropertyOption(options.ObjectTypeDefinition);
|
1628
|
-
checkNode(node.name, property, 'Type');
|
1648
|
+
if (prefix && !name.startsWith(prefix)) {
|
1649
|
+
return `have "${prefix}" prefix`;
|
1629
1650
|
}
|
1630
|
-
|
1631
|
-
|
1632
|
-
if (options.InterfaceTypeDefinition) {
|
1633
|
-
const property = normalisePropertyOption(options.InterfaceTypeDefinition);
|
1634
|
-
checkNode(node.name, property, 'Interface');
|
1651
|
+
if (suffix && !name.endsWith(suffix)) {
|
1652
|
+
return `have "${suffix}" suffix`;
|
1635
1653
|
}
|
1636
|
-
|
1637
|
-
|
1638
|
-
|
1639
|
-
const property = normalisePropertyOption(options.EnumTypeDefinition);
|
1640
|
-
checkNode(node.name, property, 'Enumerator');
|
1654
|
+
const forbiddenPrefix = forbiddenPrefixes === null || forbiddenPrefixes === void 0 ? void 0 : forbiddenPrefixes.find(prefix => name.startsWith(prefix));
|
1655
|
+
if (forbiddenPrefix) {
|
1656
|
+
return `not have "${forbiddenPrefix}" prefix`;
|
1641
1657
|
}
|
1642
|
-
|
1643
|
-
|
1644
|
-
|
1645
|
-
const property = normalisePropertyOption(options.InputObjectTypeDefinition);
|
1646
|
-
checkNode(node.name, property, 'Input type');
|
1658
|
+
const forbiddenSuffix = forbiddenSuffixes === null || forbiddenSuffixes === void 0 ? void 0 : forbiddenSuffixes.find(suffix => name.endsWith(suffix));
|
1659
|
+
if (forbiddenSuffix) {
|
1660
|
+
return `not have "${forbiddenSuffix}" suffix`;
|
1647
1661
|
}
|
1648
|
-
|
1649
|
-
|
1650
|
-
if (options.QueryDefinition && isQueryType(node.parent)) {
|
1651
|
-
const property = normalisePropertyOption(options.QueryDefinition);
|
1652
|
-
checkNode(node.name, property, 'Query');
|
1662
|
+
if (style && !ALLOWED_STYLES.includes(style)) {
|
1663
|
+
return `be in one of the following options: ${ALLOWED_STYLES.join(', ')}`;
|
1653
1664
|
}
|
1654
|
-
|
1655
|
-
|
1656
|
-
|
1657
|
-
}
|
1658
|
-
},
|
1659
|
-
EnumValueDefinition: node => {
|
1660
|
-
if (options.EnumValueDefinition) {
|
1661
|
-
const property = normalisePropertyOption(options.EnumValueDefinition);
|
1662
|
-
checkNode(node.name, property, 'Enumeration value');
|
1665
|
+
const caseRegex = StyleToRegex[style];
|
1666
|
+
if (caseRegex && !caseRegex.test(name)) {
|
1667
|
+
return `be in ${style} format`;
|
1663
1668
|
}
|
1664
|
-
}
|
1665
|
-
InputValueDefinition: node => {
|
1666
|
-
if (options.InputValueDefinition) {
|
1667
|
-
const property = normalisePropertyOption(options.InputValueDefinition);
|
1668
|
-
checkNode(node.name, property, 'Input property');
|
1669
|
-
}
|
1670
|
-
},
|
1671
|
-
OperationDefinition: node => {
|
1672
|
-
if (options.OperationDefinition) {
|
1673
|
-
const property = normalisePropertyOption(options.OperationDefinition);
|
1674
|
-
if (node.name) {
|
1675
|
-
checkNode(node.name, property, 'Operation');
|
1676
|
-
}
|
1677
|
-
}
|
1678
|
-
},
|
1679
|
-
FragmentDefinition: node => {
|
1680
|
-
if (options.FragmentDefinition) {
|
1681
|
-
const property = normalisePropertyOption(options.FragmentDefinition);
|
1682
|
-
checkNode(node.name, property, 'Fragment');
|
1683
|
-
}
|
1684
|
-
},
|
1685
|
-
ScalarTypeDefinition: node => {
|
1686
|
-
if (options.ScalarTypeDefinition) {
|
1687
|
-
const property = normalisePropertyOption(options.ScalarTypeDefinition);
|
1688
|
-
checkNode(node.name, property, 'Scalar');
|
1689
|
-
}
|
1690
|
-
},
|
1691
|
-
UnionTypeDefinition: node => {
|
1692
|
-
if (options.UnionTypeDefinition) {
|
1693
|
-
const property = normalisePropertyOption(options.UnionTypeDefinition);
|
1694
|
-
checkNode(node.name, property, 'Union');
|
1695
|
-
}
|
1696
|
-
},
|
1669
|
+
}
|
1697
1670
|
};
|
1671
|
+
const checkUnderscore = (node) => {
|
1672
|
+
const name = node.value;
|
1673
|
+
context.report({
|
1674
|
+
loc: getLocation(node.loc, name),
|
1675
|
+
message: `${name.startsWith('_') ? 'Leading' : 'Trailing'} underscores are not allowed`,
|
1676
|
+
});
|
1677
|
+
};
|
1678
|
+
const listeners = {};
|
1679
|
+
if (!options.allowLeadingUnderscore) {
|
1680
|
+
listeners['Name[value=/^_/]:matches([parent.kind!=Field], [parent.kind=Field][parent.alias])'] = checkUnderscore;
|
1681
|
+
}
|
1682
|
+
if (!options.allowTrailingUnderscore) {
|
1683
|
+
listeners['Name[value=/_$/]:matches([parent.kind!=Field], [parent.kind=Field][parent.alias])'] = checkUnderscore;
|
1684
|
+
}
|
1685
|
+
const selectors = new Set([options.types && TYPES_KINDS, options.fields && FIELDS_KINDS, Object.keys(options.overrides)]
|
1686
|
+
.flat()
|
1687
|
+
.filter(Boolean));
|
1688
|
+
for (const selector of selectors) {
|
1689
|
+
listeners[selector] = checkNode(selector);
|
1690
|
+
}
|
1691
|
+
return listeners;
|
1698
1692
|
},
|
1699
1693
|
};
|
1700
1694
|
|
@@ -1885,7 +1879,7 @@ const rule$b = {
|
|
1885
1879
|
requireGraphQLSchemaFromContext('no-deprecated', context);
|
1886
1880
|
const typeInfo = node.typeInfo();
|
1887
1881
|
if (typeInfo && typeInfo.enumValue) {
|
1888
|
-
if (typeInfo.enumValue.
|
1882
|
+
if (typeInfo.enumValue.isDeprecated) {
|
1889
1883
|
const enumValueName = node.value;
|
1890
1884
|
context.report({
|
1891
1885
|
loc: getLocation(node.loc, enumValueName),
|
@@ -1902,7 +1896,7 @@ const rule$b = {
|
|
1902
1896
|
requireGraphQLSchemaFromContext('no-deprecated', context);
|
1903
1897
|
const typeInfo = node.typeInfo();
|
1904
1898
|
if (typeInfo && typeInfo.fieldDef) {
|
1905
|
-
if (typeInfo.fieldDef.
|
1899
|
+
if (typeInfo.fieldDef.isDeprecated) {
|
1906
1900
|
const fieldName = node.name.value;
|
1907
1901
|
context.report({
|
1908
1902
|
loc: getLocation(node.loc, fieldName),
|
@@ -2320,6 +2314,7 @@ function convertDescription(node) {
|
|
2320
2314
|
return [];
|
2321
2315
|
}
|
2322
2316
|
|
2317
|
+
// eslint-disable-next-line unicorn/better-regex
|
2323
2318
|
const DATE_REGEX = /^\d{2}\/\d{2}\/\d{4}$/;
|
2324
2319
|
const MESSAGE_REQUIRE_DATE = 'MESSAGE_REQUIRE_DATE';
|
2325
2320
|
const MESSAGE_INVALID_FORMAT = 'MESSAGE_INVALID_FORMAT';
|
@@ -2517,7 +2512,7 @@ const rule$i = {
|
|
2517
2512
|
examples: [
|
2518
2513
|
{
|
2519
2514
|
title: 'Incorrect',
|
2520
|
-
usage: [{ on: [
|
2515
|
+
usage: [{ on: ['ObjectTypeDefinition', 'FieldDefinition'] }],
|
2521
2516
|
code: /* GraphQL */ `
|
2522
2517
|
type someTypeName {
|
2523
2518
|
name: String
|
@@ -2526,7 +2521,7 @@ const rule$i = {
|
|
2526
2521
|
},
|
2527
2522
|
{
|
2528
2523
|
title: 'Correct',
|
2529
|
-
usage: [{ on: [
|
2524
|
+
usage: [{ on: ['ObjectTypeDefinition', 'FieldDefinition'] }],
|
2530
2525
|
code: /* GraphQL */ `
|
2531
2526
|
"""
|
2532
2527
|
Some type description
|
@@ -3113,7 +3108,7 @@ const rule$m = {
|
|
3113
3108
|
acceptedIdNames: ['id'],
|
3114
3109
|
acceptedIdTypes: ['ID'],
|
3115
3110
|
exceptions: {},
|
3116
|
-
...
|
3111
|
+
...context.options[0],
|
3117
3112
|
};
|
3118
3113
|
return {
|
3119
3114
|
ObjectTypeDefinition(node) {
|