@graphql-eslint/eslint-plugin 2.5.0-alpha-e34c5d6.0 → 3.0.0-alpha-3168a9b.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/strict-id-in-types.md +4 -4
- package/index.js +252 -257
- package/index.mjs +252 -257
- package/package.json +7 -7
- package/rules/index.d.ts +117 -15
- package/rules/naming-convention.d.ts +32 -25
- package/utils.d.ts +2 -7
package/index.js
CHANGED
@@ -35,7 +35,34 @@ const recommendedConfig = {
|
|
35
35
|
'@graphql-eslint/known-type-names': 'error',
|
36
36
|
'@graphql-eslint/lone-anonymous-operation': 'error',
|
37
37
|
'@graphql-eslint/lone-schema-definition': 'error',
|
38
|
-
'@graphql-eslint/naming-convention':
|
38
|
+
'@graphql-eslint/naming-convention': [
|
39
|
+
'error',
|
40
|
+
{
|
41
|
+
types: 'PascalCase',
|
42
|
+
fields: 'camelCase',
|
43
|
+
overrides: {
|
44
|
+
EnumValueDefinition: 'UPPER_CASE',
|
45
|
+
OperationDefinition: {
|
46
|
+
style: 'PascalCase',
|
47
|
+
forbiddenPrefixes: ['Query', 'Mutation', 'Subscription', 'Get'],
|
48
|
+
forbiddenSuffixes: ['Query', 'Mutation', 'Subscription'],
|
49
|
+
},
|
50
|
+
FragmentDefinition: { style: 'PascalCase', forbiddenPrefixes: ['Fragment'], forbiddenSuffixes: ['Fragment'] },
|
51
|
+
'FieldDefinition[parent.name.value=Query]': {
|
52
|
+
forbiddenPrefixes: ['query', 'get'],
|
53
|
+
forbiddenSuffixes: ['Query'],
|
54
|
+
},
|
55
|
+
'FieldDefinition[parent.name.value=Mutation]': {
|
56
|
+
forbiddenPrefixes: ['mutation'],
|
57
|
+
forbiddenSuffixes: ['Mutation'],
|
58
|
+
},
|
59
|
+
'FieldDefinition[parent.name.value=Subscription]': {
|
60
|
+
forbiddenPrefixes: ['subscription'],
|
61
|
+
forbiddenSuffixes: ['Subscription'],
|
62
|
+
},
|
63
|
+
},
|
64
|
+
},
|
65
|
+
],
|
39
66
|
'@graphql-eslint/no-anonymous-operations': 'error',
|
40
67
|
'@graphql-eslint/no-case-insensitive-enum-values-duplicates': 'error',
|
41
68
|
'@graphql-eslint/no-fragment-cycles': 'error',
|
@@ -212,9 +239,14 @@ const loaderCache = new Proxy(Object.create(null), {
|
|
212
239
|
return true;
|
213
240
|
},
|
214
241
|
});
|
215
|
-
const
|
216
|
-
|
217
|
-
|
242
|
+
const TYPES_KINDS = [
|
243
|
+
graphql.Kind.OBJECT_TYPE_DEFINITION,
|
244
|
+
graphql.Kind.INTERFACE_TYPE_DEFINITION,
|
245
|
+
graphql.Kind.ENUM_TYPE_DEFINITION,
|
246
|
+
graphql.Kind.SCALAR_TYPE_DEFINITION,
|
247
|
+
graphql.Kind.INPUT_OBJECT_TYPE_DEFINITION,
|
248
|
+
graphql.Kind.UNION_TYPE_DEFINITION,
|
249
|
+
];
|
218
250
|
var CaseStyle;
|
219
251
|
(function (CaseStyle) {
|
220
252
|
CaseStyle["camelCase"] = "camelCase";
|
@@ -265,7 +297,7 @@ function getLocation(loc, fieldName = '', offset) {
|
|
265
297
|
}
|
266
298
|
|
267
299
|
function extractRuleName(stack) {
|
268
|
-
const match = (stack || '').match(/validation[
|
300
|
+
const match = (stack || '').match(/validation[/\\]rules[/\\](.*?)\.js:/) || [];
|
269
301
|
return match[1] || null;
|
270
302
|
}
|
271
303
|
function validateDoc(sourceNode, context, schema, documentNode, rules, ruleName = null) {
|
@@ -626,38 +658,48 @@ const rule = {
|
|
626
658
|
properties: {
|
627
659
|
fields: {
|
628
660
|
type: 'array',
|
629
|
-
|
661
|
+
uniqueItems: true,
|
662
|
+
minItems: 1,
|
663
|
+
items: {
|
630
664
|
enum: fieldsEnum,
|
631
665
|
},
|
632
|
-
description: 'Fields of `type`, `interface`, and `input
|
666
|
+
description: 'Fields of `type`, `interface`, and `input`',
|
633
667
|
},
|
634
668
|
values: {
|
635
669
|
type: 'array',
|
636
|
-
|
670
|
+
uniqueItems: true,
|
671
|
+
minItems: 1,
|
672
|
+
items: {
|
637
673
|
enum: valuesEnum,
|
638
674
|
},
|
639
|
-
description: 'Values of `enum
|
675
|
+
description: 'Values of `enum`',
|
640
676
|
},
|
641
677
|
selections: {
|
642
678
|
type: 'array',
|
643
|
-
|
679
|
+
uniqueItems: true,
|
680
|
+
minItems: 1,
|
681
|
+
items: {
|
644
682
|
enum: selectionsEnum,
|
645
683
|
},
|
646
|
-
description: 'Selections of operations (`query`, `mutation` and `subscription`) and `fragment
|
684
|
+
description: 'Selections of operations (`query`, `mutation` and `subscription`) and `fragment`',
|
647
685
|
},
|
648
686
|
variables: {
|
649
687
|
type: 'array',
|
650
|
-
|
688
|
+
uniqueItems: true,
|
689
|
+
minItems: 1,
|
690
|
+
items: {
|
651
691
|
enum: variablesEnum,
|
652
692
|
},
|
653
|
-
description: 'Variables of operations (`query`, `mutation` and `subscription`)
|
693
|
+
description: 'Variables of operations (`query`, `mutation` and `subscription`)',
|
654
694
|
},
|
655
695
|
arguments: {
|
656
696
|
type: 'array',
|
657
|
-
|
697
|
+
uniqueItems: true,
|
698
|
+
minItems: 1,
|
699
|
+
items: {
|
658
700
|
enum: argumentsEnum,
|
659
701
|
},
|
660
|
-
description: 'Arguments of fields and directives
|
702
|
+
description: 'Arguments of fields and directives',
|
661
703
|
},
|
662
704
|
},
|
663
705
|
},
|
@@ -688,7 +730,7 @@ const rule = {
|
|
688
730
|
const opts = context.options[0];
|
689
731
|
const fields = new Set((_a = opts.fields) !== null && _a !== void 0 ? _a : []);
|
690
732
|
const listeners = {};
|
691
|
-
const
|
733
|
+
const kinds = [
|
692
734
|
fields.has(graphql.Kind.OBJECT_TYPE_DEFINITION) && [graphql.Kind.OBJECT_TYPE_DEFINITION, graphql.Kind.OBJECT_TYPE_EXTENSION],
|
693
735
|
fields.has(graphql.Kind.INTERFACE_TYPE_DEFINITION) && [graphql.Kind.INTERFACE_TYPE_DEFINITION, graphql.Kind.INTERFACE_TYPE_EXTENSION],
|
694
736
|
fields.has(graphql.Kind.INPUT_OBJECT_TYPE_DEFINITION) && [
|
@@ -696,8 +738,9 @@ const rule = {
|
|
696
738
|
graphql.Kind.INPUT_OBJECT_TYPE_EXTENSION,
|
697
739
|
],
|
698
740
|
]
|
699
|
-
.
|
700
|
-
.
|
741
|
+
.filter(Boolean)
|
742
|
+
.flat();
|
743
|
+
const fieldsSelector = kinds.join(',');
|
701
744
|
const hasEnumValues = ((_b = opts.values) === null || _b === void 0 ? void 0 : _b[0]) === graphql.Kind.ENUM_TYPE_DEFINITION;
|
702
745
|
const selectionsSelector = (_c = opts.selections) === null || _c === void 0 ? void 0 : _c.join(',');
|
703
746
|
const hasVariables = ((_d = opts.variables) === null || _d === void 0 ? void 0 : _d[0]) === graphql.Kind.OPERATION_DEFINITION;
|
@@ -1097,6 +1140,9 @@ const rule$5 = {
|
|
1097
1140
|
},
|
1098
1141
|
};
|
1099
1142
|
|
1143
|
+
const isObjectType = (node) => [graphql.Kind.OBJECT_TYPE_DEFINITION, graphql.Kind.OBJECT_TYPE_EXTENSION].includes(node.type);
|
1144
|
+
const isQueryType = (node) => isObjectType(node) && node.name.value === 'Query';
|
1145
|
+
const isMutationType = (node) => isObjectType(node) && node.name.value === 'Mutation';
|
1100
1146
|
const rule$6 = {
|
1101
1147
|
meta: {
|
1102
1148
|
type: 'suggestion',
|
@@ -1137,6 +1183,7 @@ const rule$6 = {
|
|
1137
1183
|
schema: [
|
1138
1184
|
{
|
1139
1185
|
type: 'object',
|
1186
|
+
additionalProperties: false,
|
1140
1187
|
properties: {
|
1141
1188
|
checkInputType: {
|
1142
1189
|
type: 'boolean',
|
@@ -1159,24 +1206,22 @@ const rule$6 = {
|
|
1159
1206
|
description: 'Apply the rule to Mutations',
|
1160
1207
|
},
|
1161
1208
|
},
|
1162
|
-
additionalProperties: false,
|
1163
1209
|
},
|
1164
1210
|
],
|
1165
1211
|
},
|
1166
1212
|
create(context) {
|
1167
|
-
var _a;
|
1168
1213
|
const options = {
|
1169
|
-
caseSensitiveInputType: true,
|
1170
1214
|
checkInputType: false,
|
1171
|
-
|
1215
|
+
caseSensitiveInputType: true,
|
1172
1216
|
checkQueries: false,
|
1173
|
-
|
1217
|
+
checkMutations: true,
|
1218
|
+
...context.options[0],
|
1174
1219
|
};
|
1175
1220
|
const shouldCheckType = node => (options.checkMutations && isMutationType(node)) || (options.checkQueries && isQueryType(node));
|
1176
1221
|
const listeners = {
|
1177
|
-
'FieldDefinition > InputValueDefinition'
|
1178
|
-
|
1179
|
-
|
1222
|
+
'FieldDefinition > InputValueDefinition[name.value!=input]'(node) {
|
1223
|
+
if (shouldCheckType(node.parent.parent)) {
|
1224
|
+
const name = node.name.value;
|
1180
1225
|
context.report({
|
1181
1226
|
loc: getLocation(node.loc, name),
|
1182
1227
|
message: `Input "${name}" should be called "input"`,
|
@@ -1184,11 +1229,11 @@ const rule$6 = {
|
|
1184
1229
|
}
|
1185
1230
|
},
|
1186
1231
|
};
|
1187
|
-
if (options
|
1188
|
-
listeners['FieldDefinition > InputValueDefinition NamedType'] = node => {
|
1232
|
+
if (options.checkInputType) {
|
1233
|
+
listeners['FieldDefinition > InputValueDefinition NamedType'] = (node) => {
|
1189
1234
|
const findInputType = item => {
|
1190
1235
|
let currentNode = item;
|
1191
|
-
while (currentNode.type !==
|
1236
|
+
while (currentNode.type !== graphql.Kind.INPUT_VALUE_DEFINITION) {
|
1192
1237
|
currentNode = currentNode.parent;
|
1193
1238
|
}
|
1194
1239
|
return currentNode;
|
@@ -1405,69 +1450,40 @@ const rule$7 = {
|
|
1405
1450
|
},
|
1406
1451
|
};
|
1407
1452
|
|
1408
|
-
const
|
1409
|
-
|
1410
|
-
|
1411
|
-
|
1412
|
-
|
1413
|
-
|
1414
|
-
const acceptedStyles = [
|
1415
|
-
'camelCase',
|
1416
|
-
'PascalCase',
|
1417
|
-
'snake_case',
|
1418
|
-
'UPPER_CASE',
|
1453
|
+
const FIELDS_KINDS = [
|
1454
|
+
graphql.Kind.FIELD_DEFINITION,
|
1455
|
+
graphql.Kind.INPUT_VALUE_DEFINITION,
|
1456
|
+
graphql.Kind.VARIABLE_DEFINITION,
|
1457
|
+
graphql.Kind.ARGUMENT,
|
1458
|
+
graphql.Kind.DIRECTIVE_DEFINITION,
|
1419
1459
|
];
|
1420
|
-
|
1421
|
-
|
1422
|
-
|
1423
|
-
|
1424
|
-
|
1425
|
-
|
1426
|
-
|
1427
|
-
|
1428
|
-
|
1429
|
-
|
1430
|
-
|
1431
|
-
|
1432
|
-
|
1433
|
-
|
1434
|
-
|
1435
|
-
|
1436
|
-
|
1437
|
-
|
1438
|
-
|
1439
|
-
|
1440
|
-
|
1441
|
-
|
1442
|
-
|
1443
|
-
|
1444
|
-
|
1445
|
-
|
1446
|
-
|
1447
|
-
if (forbiddenPrefixes.some(forbiddenPrefix => name.startsWith(forbiddenPrefix))) {
|
1448
|
-
return {
|
1449
|
-
ok: false,
|
1450
|
-
errorMessage: '{{nodeType}} "{{nodeName}}" should not have one of the following prefix(es): {{forbiddenPrefixes}}',
|
1451
|
-
};
|
1452
|
-
}
|
1453
|
-
if (forbiddenSuffixes.some(forbiddenSuffix => name.endsWith(forbiddenSuffix))) {
|
1454
|
-
return {
|
1455
|
-
ok: false,
|
1456
|
-
errorMessage: '{{nodeType}} "{{nodeName}}" should not have one of the following suffix(es): {{forbiddenSuffixes}}',
|
1457
|
-
};
|
1458
|
-
}
|
1459
|
-
if (!formats[style]) {
|
1460
|
-
return { ok: true };
|
1461
|
-
}
|
1462
|
-
const ok = new RegExp(formats[style]).test(name);
|
1463
|
-
if (ok) {
|
1464
|
-
return { ok: true };
|
1465
|
-
}
|
1466
|
-
return {
|
1467
|
-
ok: false,
|
1468
|
-
errorMessage: '{{nodeType}} name "{{nodeName}}" should be in {{format}} format',
|
1469
|
-
};
|
1470
|
-
}
|
1460
|
+
const KindToDisplayName = {
|
1461
|
+
// types
|
1462
|
+
[graphql.Kind.OBJECT_TYPE_DEFINITION]: 'Type',
|
1463
|
+
[graphql.Kind.INTERFACE_TYPE_DEFINITION]: 'Interface',
|
1464
|
+
[graphql.Kind.ENUM_TYPE_DEFINITION]: 'Enumerator',
|
1465
|
+
[graphql.Kind.SCALAR_TYPE_DEFINITION]: 'Scalar',
|
1466
|
+
[graphql.Kind.INPUT_OBJECT_TYPE_DEFINITION]: 'Input type',
|
1467
|
+
[graphql.Kind.UNION_TYPE_DEFINITION]: 'Union',
|
1468
|
+
// fields
|
1469
|
+
[graphql.Kind.FIELD_DEFINITION]: 'Field',
|
1470
|
+
[graphql.Kind.INPUT_VALUE_DEFINITION]: 'Input property',
|
1471
|
+
[graphql.Kind.VARIABLE_DEFINITION]: 'Variable',
|
1472
|
+
[graphql.Kind.ARGUMENT]: 'Argument',
|
1473
|
+
[graphql.Kind.DIRECTIVE_DEFINITION]: 'Directive',
|
1474
|
+
// rest
|
1475
|
+
[graphql.Kind.ENUM_VALUE_DEFINITION]: 'Enumeration value',
|
1476
|
+
[graphql.Kind.OPERATION_DEFINITION]: 'Operation',
|
1477
|
+
[graphql.Kind.FRAGMENT_DEFINITION]: 'Fragment',
|
1478
|
+
};
|
1479
|
+
const StyleToRegex = {
|
1480
|
+
camelCase: /^[a-z][\dA-Za-z]*$/,
|
1481
|
+
PascalCase: /^[A-Z][\dA-Za-z]*$/,
|
1482
|
+
snake_case: /^[a-z][\d_a-z]*[\da-z]$/,
|
1483
|
+
UPPER_CASE: /^[A-Z][\dA-Z_]*[\dA-Z]$/,
|
1484
|
+
};
|
1485
|
+
const ALLOWED_KINDS = Object.keys(KindToDisplayName).sort();
|
1486
|
+
const ALLOWED_STYLES = Object.keys(StyleToRegex);
|
1471
1487
|
const schemaOption$1 = {
|
1472
1488
|
oneOf: [{ $ref: '#/definitions/asString' }, { $ref: '#/definitions/asObject' }],
|
1473
1489
|
};
|
@@ -1482,89 +1498,120 @@ const rule$8 = {
|
|
1482
1498
|
examples: [
|
1483
1499
|
{
|
1484
1500
|
title: 'Incorrect',
|
1485
|
-
usage: [{
|
1501
|
+
usage: [{ types: 'PascalCase', fields: 'camelCase' }],
|
1486
1502
|
code: /* GraphQL */ `
|
1487
|
-
type
|
1488
|
-
|
1503
|
+
type user {
|
1504
|
+
first_name: String!
|
1489
1505
|
}
|
1490
1506
|
`,
|
1491
1507
|
},
|
1492
1508
|
{
|
1493
1509
|
title: 'Correct',
|
1494
|
-
usage: [{
|
1510
|
+
usage: [{ types: 'PascalCase', fields: 'camelCase' }],
|
1495
1511
|
code: /* GraphQL */ `
|
1496
|
-
type
|
1497
|
-
|
1512
|
+
type User {
|
1513
|
+
firstName: String
|
1498
1514
|
}
|
1499
1515
|
`,
|
1500
1516
|
},
|
1501
1517
|
],
|
1518
|
+
optionsForConfig: [
|
1519
|
+
{
|
1520
|
+
types: 'PascalCase',
|
1521
|
+
fields: 'camelCase',
|
1522
|
+
overrides: {
|
1523
|
+
EnumValueDefinition: 'UPPER_CASE',
|
1524
|
+
OperationDefinition: {
|
1525
|
+
style: 'PascalCase',
|
1526
|
+
forbiddenPrefixes: ['Query', 'Mutation', 'Subscription', 'Get'],
|
1527
|
+
forbiddenSuffixes: ['Query', 'Mutation', 'Subscription'],
|
1528
|
+
},
|
1529
|
+
FragmentDefinition: {
|
1530
|
+
style: 'PascalCase',
|
1531
|
+
forbiddenPrefixes: ['Fragment'],
|
1532
|
+
forbiddenSuffixes: ['Fragment'],
|
1533
|
+
},
|
1534
|
+
'FieldDefinition[parent.name.value=Query]': {
|
1535
|
+
forbiddenPrefixes: ['query', 'get'],
|
1536
|
+
forbiddenSuffixes: ['Query'],
|
1537
|
+
},
|
1538
|
+
'FieldDefinition[parent.name.value=Mutation]': {
|
1539
|
+
forbiddenPrefixes: ['mutation'],
|
1540
|
+
forbiddenSuffixes: ['Mutation'],
|
1541
|
+
},
|
1542
|
+
'FieldDefinition[parent.name.value=Subscription]': {
|
1543
|
+
forbiddenPrefixes: ['subscription'],
|
1544
|
+
forbiddenSuffixes: ['Subscription'],
|
1545
|
+
},
|
1546
|
+
},
|
1547
|
+
},
|
1548
|
+
],
|
1502
1549
|
},
|
1503
1550
|
schema: {
|
1504
1551
|
definitions: {
|
1505
1552
|
asString: {
|
1506
|
-
|
1507
|
-
description: `One of: ${
|
1508
|
-
enum: acceptedStyles,
|
1553
|
+
enum: ALLOWED_STYLES,
|
1554
|
+
description: `One of: ${ALLOWED_STYLES.map(t => `\`${t}\``).join(', ')}`,
|
1509
1555
|
},
|
1510
1556
|
asObject: {
|
1511
1557
|
type: 'object',
|
1558
|
+
additionalProperties: false,
|
1512
1559
|
properties: {
|
1513
|
-
style: {
|
1514
|
-
|
1515
|
-
|
1516
|
-
},
|
1517
|
-
prefix: {
|
1518
|
-
type: 'string',
|
1519
|
-
},
|
1520
|
-
suffix: {
|
1521
|
-
type: 'string',
|
1522
|
-
},
|
1560
|
+
style: { enum: ALLOWED_STYLES },
|
1561
|
+
prefix: { type: 'string' },
|
1562
|
+
suffix: { type: 'string' },
|
1523
1563
|
forbiddenPrefixes: {
|
1524
|
-
additionalItems: false,
|
1525
1564
|
type: 'array',
|
1565
|
+
uniqueItems: true,
|
1526
1566
|
minItems: 1,
|
1527
|
-
items: {
|
1528
|
-
type: 'string',
|
1529
|
-
},
|
1567
|
+
items: { type: 'string' },
|
1530
1568
|
},
|
1531
1569
|
forbiddenSuffixes: {
|
1532
|
-
additionalItems: false,
|
1533
1570
|
type: 'array',
|
1571
|
+
uniqueItems: true,
|
1534
1572
|
minItems: 1,
|
1535
|
-
items: {
|
1536
|
-
type: 'string',
|
1537
|
-
},
|
1573
|
+
items: { type: 'string' },
|
1538
1574
|
},
|
1539
1575
|
},
|
1540
1576
|
},
|
1541
1577
|
},
|
1542
|
-
$schema: 'http://json-schema.org/draft-04/schema#',
|
1543
1578
|
type: 'array',
|
1579
|
+
maxItems: 1,
|
1544
1580
|
items: {
|
1545
1581
|
type: 'object',
|
1582
|
+
additionalProperties: false,
|
1546
1583
|
properties: {
|
1547
|
-
|
1548
|
-
|
1549
|
-
|
1550
|
-
[graphql.Kind.INPUT_VALUE_DEFINITION]: schemaOption$1,
|
1551
|
-
[graphql.Kind.OBJECT_TYPE_DEFINITION]: schemaOption$1,
|
1552
|
-
[graphql.Kind.INTERFACE_TYPE_DEFINITION]: schemaOption$1,
|
1553
|
-
[graphql.Kind.ENUM_TYPE_DEFINITION]: schemaOption$1,
|
1554
|
-
[graphql.Kind.UNION_TYPE_DEFINITION]: schemaOption$1,
|
1555
|
-
[graphql.Kind.SCALAR_TYPE_DEFINITION]: schemaOption$1,
|
1556
|
-
[graphql.Kind.OPERATION_DEFINITION]: schemaOption$1,
|
1557
|
-
[graphql.Kind.FRAGMENT_DEFINITION]: schemaOption$1,
|
1558
|
-
QueryDefinition: schemaOption$1,
|
1559
|
-
leadingUnderscore: {
|
1560
|
-
type: 'string',
|
1561
|
-
enum: ['allow', 'forbid'],
|
1562
|
-
default: 'forbid',
|
1584
|
+
types: {
|
1585
|
+
...schemaOption$1,
|
1586
|
+
description: `Includes:\n\n${TYPES_KINDS.map(kind => `- \`${kind}\``).join('\n')}`,
|
1563
1587
|
},
|
1564
|
-
|
1565
|
-
|
1566
|
-
|
1567
|
-
|
1588
|
+
fields: {
|
1589
|
+
...schemaOption$1,
|
1590
|
+
description: `Includes:\n\n${FIELDS_KINDS.map(kind => `- \`${kind}\``).join('\n')}`,
|
1591
|
+
},
|
1592
|
+
allowLeadingUnderscore: {
|
1593
|
+
type: 'boolean',
|
1594
|
+
default: false,
|
1595
|
+
},
|
1596
|
+
allowTrailingUnderscore: {
|
1597
|
+
type: 'boolean',
|
1598
|
+
default: false,
|
1599
|
+
},
|
1600
|
+
overrides: {
|
1601
|
+
type: 'object',
|
1602
|
+
additionalProperties: false,
|
1603
|
+
description: [
|
1604
|
+
'May contain the following `ASTNode` names:',
|
1605
|
+
'',
|
1606
|
+
...ALLOWED_KINDS.map(kind => `- \`${kind}\``),
|
1607
|
+
'',
|
1608
|
+
"> It's also possible to use a [`selector`](https://eslint.org/docs/developer-guide/selectors) that starts with `ASTNode` name",
|
1609
|
+
'>',
|
1610
|
+
'> Example: pattern property `FieldDefinition[parent.name.value=Query]` will match only fields for type `Query`',
|
1611
|
+
].join('\n'),
|
1612
|
+
patternProperties: {
|
1613
|
+
[`^(${ALLOWED_KINDS.join('|')})(.+)?$`]: schemaOption$1,
|
1614
|
+
},
|
1568
1615
|
},
|
1569
1616
|
},
|
1570
1617
|
},
|
@@ -1572,136 +1619,83 @@ const rule$8 = {
|
|
1572
1619
|
},
|
1573
1620
|
create(context) {
|
1574
1621
|
const options = {
|
1575
|
-
|
1576
|
-
|
1577
|
-
...(context.options[0] || {}),
|
1622
|
+
overrides: {},
|
1623
|
+
...context.options[0],
|
1578
1624
|
};
|
1579
|
-
|
1580
|
-
|
1581
|
-
|
1582
|
-
|
1583
|
-
|
1584
|
-
|
1585
|
-
|
1586
|
-
|
1587
|
-
|
1588
|
-
|
1589
|
-
|
1590
|
-
}
|
1591
|
-
|
1625
|
+
function normalisePropertyOption(kind) {
|
1626
|
+
let style = options.overrides[kind];
|
1627
|
+
if (!style) {
|
1628
|
+
style = TYPES_KINDS.includes(kind) ? options.types : options.fields;
|
1629
|
+
}
|
1630
|
+
return typeof style === 'object' ? style : { style };
|
1631
|
+
}
|
1632
|
+
const checkNode = (selector) => (node) => {
|
1633
|
+
const { name } = node.kind === graphql.Kind.VARIABLE_DEFINITION ? node.variable : node;
|
1634
|
+
if (!name) {
|
1635
|
+
return;
|
1636
|
+
}
|
1637
|
+
const { prefix, suffix, forbiddenPrefixes, forbiddenSuffixes, style } = normalisePropertyOption(selector);
|
1638
|
+
const nodeType = KindToDisplayName[node.kind] || node.kind;
|
1639
|
+
const nodeName = name.value;
|
1640
|
+
const errorMessage = getErrorMessage();
|
1641
|
+
if (errorMessage) {
|
1592
1642
|
context.report({
|
1593
|
-
loc: getLocation(
|
1594
|
-
message:
|
1595
|
-
data: {
|
1596
|
-
prefix,
|
1597
|
-
suffix,
|
1598
|
-
format: style,
|
1599
|
-
forbiddenPrefixes: forbiddenPrefixes.join(', '),
|
1600
|
-
forbiddenSuffixes: forbiddenSuffixes.join(', '),
|
1601
|
-
nodeType,
|
1602
|
-
nodeName: node.value,
|
1603
|
-
},
|
1643
|
+
loc: getLocation(name.loc, name.value),
|
1644
|
+
message: `${nodeType} "${nodeName}" should ${errorMessage}`,
|
1604
1645
|
});
|
1605
1646
|
}
|
1606
|
-
|
1607
|
-
|
1608
|
-
|
1609
|
-
|
1610
|
-
}
|
1611
|
-
return {
|
1612
|
-
style: value,
|
1613
|
-
prefix: '',
|
1614
|
-
suffix: '',
|
1615
|
-
};
|
1616
|
-
};
|
1617
|
-
return {
|
1618
|
-
Name: node => {
|
1619
|
-
if (node.value.startsWith('_') && options.leadingUnderscore === 'forbid') {
|
1620
|
-
context.report({
|
1621
|
-
loc: getLocation(node.loc, node.value),
|
1622
|
-
message: 'Leading underscores are not allowed',
|
1623
|
-
});
|
1624
|
-
}
|
1625
|
-
if (node.value.endsWith('_') && options.trailingUnderscore === 'forbid') {
|
1626
|
-
context.report({
|
1627
|
-
loc: getLocation(node.loc, node.value),
|
1628
|
-
message: 'Trailing underscores are not allowed',
|
1629
|
-
});
|
1630
|
-
}
|
1631
|
-
},
|
1632
|
-
ObjectTypeDefinition: node => {
|
1633
|
-
if (options.ObjectTypeDefinition) {
|
1634
|
-
const property = normalisePropertyOption(options.ObjectTypeDefinition);
|
1635
|
-
checkNode(node.name, property, 'Type');
|
1636
|
-
}
|
1637
|
-
},
|
1638
|
-
InterfaceTypeDefinition: node => {
|
1639
|
-
if (options.InterfaceTypeDefinition) {
|
1640
|
-
const property = normalisePropertyOption(options.InterfaceTypeDefinition);
|
1641
|
-
checkNode(node.name, property, 'Interface');
|
1642
|
-
}
|
1643
|
-
},
|
1644
|
-
EnumTypeDefinition: node => {
|
1645
|
-
if (options.EnumTypeDefinition) {
|
1646
|
-
const property = normalisePropertyOption(options.EnumTypeDefinition);
|
1647
|
-
checkNode(node.name, property, 'Enumerator');
|
1648
|
-
}
|
1649
|
-
},
|
1650
|
-
InputObjectTypeDefinition: node => {
|
1651
|
-
if (options.InputObjectTypeDefinition) {
|
1652
|
-
const property = normalisePropertyOption(options.InputObjectTypeDefinition);
|
1653
|
-
checkNode(node.name, property, 'Input type');
|
1654
|
-
}
|
1655
|
-
},
|
1656
|
-
FieldDefinition: (node) => {
|
1657
|
-
if (options.QueryDefinition && isQueryType(node.parent)) {
|
1658
|
-
const property = normalisePropertyOption(options.QueryDefinition);
|
1659
|
-
checkNode(node.name, property, 'Query');
|
1647
|
+
function getErrorMessage() {
|
1648
|
+
let name = nodeName;
|
1649
|
+
if (options.allowLeadingUnderscore) {
|
1650
|
+
name = name.replace(/^_*/, '');
|
1660
1651
|
}
|
1661
|
-
if (options.
|
1662
|
-
|
1663
|
-
checkNode(node.name, property, 'Field');
|
1652
|
+
if (options.allowTrailingUnderscore) {
|
1653
|
+
name = name.replace(/_*$/, '');
|
1664
1654
|
}
|
1665
|
-
|
1666
|
-
|
1667
|
-
if (options.EnumValueDefinition) {
|
1668
|
-
const property = normalisePropertyOption(options.EnumValueDefinition);
|
1669
|
-
checkNode(node.name, property, 'Enumeration value');
|
1655
|
+
if (prefix && !name.startsWith(prefix)) {
|
1656
|
+
return `have "${prefix}" prefix`;
|
1670
1657
|
}
|
1671
|
-
|
1672
|
-
|
1673
|
-
if (options.InputValueDefinition) {
|
1674
|
-
const property = normalisePropertyOption(options.InputValueDefinition);
|
1675
|
-
checkNode(node.name, property, 'Input property');
|
1658
|
+
if (suffix && !name.endsWith(suffix)) {
|
1659
|
+
return `have "${suffix}" suffix`;
|
1676
1660
|
}
|
1677
|
-
|
1678
|
-
|
1679
|
-
|
1680
|
-
const property = normalisePropertyOption(options.OperationDefinition);
|
1681
|
-
if (node.name) {
|
1682
|
-
checkNode(node.name, property, 'Operation');
|
1683
|
-
}
|
1661
|
+
const forbiddenPrefix = forbiddenPrefixes === null || forbiddenPrefixes === void 0 ? void 0 : forbiddenPrefixes.find(prefix => name.startsWith(prefix));
|
1662
|
+
if (forbiddenPrefix) {
|
1663
|
+
return `not have "${forbiddenPrefix}" prefix`;
|
1684
1664
|
}
|
1685
|
-
|
1686
|
-
|
1687
|
-
|
1688
|
-
const property = normalisePropertyOption(options.FragmentDefinition);
|
1689
|
-
checkNode(node.name, property, 'Fragment');
|
1665
|
+
const forbiddenSuffix = forbiddenSuffixes === null || forbiddenSuffixes === void 0 ? void 0 : forbiddenSuffixes.find(suffix => name.endsWith(suffix));
|
1666
|
+
if (forbiddenSuffix) {
|
1667
|
+
return `not have "${forbiddenSuffix}" suffix`;
|
1690
1668
|
}
|
1691
|
-
|
1692
|
-
|
1693
|
-
if (options.ScalarTypeDefinition) {
|
1694
|
-
const property = normalisePropertyOption(options.ScalarTypeDefinition);
|
1695
|
-
checkNode(node.name, property, 'Scalar');
|
1669
|
+
if (style && !ALLOWED_STYLES.includes(style)) {
|
1670
|
+
return `be in one of the following options: ${ALLOWED_STYLES.join(', ')}`;
|
1696
1671
|
}
|
1697
|
-
|
1698
|
-
|
1699
|
-
|
1700
|
-
const property = normalisePropertyOption(options.UnionTypeDefinition);
|
1701
|
-
checkNode(node.name, property, 'Union');
|
1672
|
+
const caseRegex = StyleToRegex[style];
|
1673
|
+
if (caseRegex && !caseRegex.test(name)) {
|
1674
|
+
return `be in ${style} format`;
|
1702
1675
|
}
|
1703
|
-
}
|
1676
|
+
}
|
1704
1677
|
};
|
1678
|
+
const checkUnderscore = (node) => {
|
1679
|
+
const name = node.value;
|
1680
|
+
context.report({
|
1681
|
+
loc: getLocation(node.loc, name),
|
1682
|
+
message: `${name.startsWith('_') ? 'Leading' : 'Trailing'} underscores are not allowed`,
|
1683
|
+
});
|
1684
|
+
};
|
1685
|
+
const listeners = {};
|
1686
|
+
if (!options.allowLeadingUnderscore) {
|
1687
|
+
listeners['Name[value=/^_/]:matches([parent.kind!=Field], [parent.kind=Field][parent.alias])'] = checkUnderscore;
|
1688
|
+
}
|
1689
|
+
if (!options.allowTrailingUnderscore) {
|
1690
|
+
listeners['Name[value=/_$/]:matches([parent.kind!=Field], [parent.kind=Field][parent.alias])'] = checkUnderscore;
|
1691
|
+
}
|
1692
|
+
const selectors = new Set([options.types && TYPES_KINDS, options.fields && FIELDS_KINDS, Object.keys(options.overrides)]
|
1693
|
+
.flat()
|
1694
|
+
.filter(Boolean));
|
1695
|
+
for (const selector of selectors) {
|
1696
|
+
listeners[selector] = checkNode(selector);
|
1697
|
+
}
|
1698
|
+
return listeners;
|
1705
1699
|
},
|
1706
1700
|
};
|
1707
1701
|
|
@@ -2418,6 +2412,7 @@ function convertDescription(node) {
|
|
2418
2412
|
return [];
|
2419
2413
|
}
|
2420
2414
|
|
2415
|
+
// eslint-disable-next-line unicorn/better-regex
|
2421
2416
|
const DATE_REGEX = /^\d{2}\/\d{2}\/\d{4}$/;
|
2422
2417
|
const MESSAGE_REQUIRE_DATE = 'MESSAGE_REQUIRE_DATE';
|
2423
2418
|
const MESSAGE_INVALID_FORMAT = 'MESSAGE_INVALID_FORMAT';
|
@@ -3211,7 +3206,7 @@ const rule$n = {
|
|
3211
3206
|
acceptedIdNames: ['id'],
|
3212
3207
|
acceptedIdTypes: ['ID'],
|
3213
3208
|
exceptions: {},
|
3214
|
-
...
|
3209
|
+
...context.options[0],
|
3215
3210
|
};
|
3216
3211
|
return {
|
3217
3212
|
ObjectTypeDefinition(node) {
|