@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.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',
|
@@ -206,9 +233,14 @@ const loaderCache = new Proxy(Object.create(null), {
|
|
206
233
|
return true;
|
207
234
|
},
|
208
235
|
});
|
209
|
-
const
|
210
|
-
|
211
|
-
|
236
|
+
const TYPES_KINDS = [
|
237
|
+
Kind.OBJECT_TYPE_DEFINITION,
|
238
|
+
Kind.INTERFACE_TYPE_DEFINITION,
|
239
|
+
Kind.ENUM_TYPE_DEFINITION,
|
240
|
+
Kind.SCALAR_TYPE_DEFINITION,
|
241
|
+
Kind.INPUT_OBJECT_TYPE_DEFINITION,
|
242
|
+
Kind.UNION_TYPE_DEFINITION,
|
243
|
+
];
|
212
244
|
var CaseStyle;
|
213
245
|
(function (CaseStyle) {
|
214
246
|
CaseStyle["camelCase"] = "camelCase";
|
@@ -259,7 +291,7 @@ function getLocation(loc, fieldName = '', offset) {
|
|
259
291
|
}
|
260
292
|
|
261
293
|
function extractRuleName(stack) {
|
262
|
-
const match = (stack || '').match(/validation[
|
294
|
+
const match = (stack || '').match(/validation[/\\]rules[/\\](.*?)\.js:/) || [];
|
263
295
|
return match[1] || null;
|
264
296
|
}
|
265
297
|
function validateDoc(sourceNode, context, schema, documentNode, rules, ruleName = null) {
|
@@ -620,38 +652,48 @@ const rule = {
|
|
620
652
|
properties: {
|
621
653
|
fields: {
|
622
654
|
type: 'array',
|
623
|
-
|
655
|
+
uniqueItems: true,
|
656
|
+
minItems: 1,
|
657
|
+
items: {
|
624
658
|
enum: fieldsEnum,
|
625
659
|
},
|
626
|
-
description: 'Fields of `type`, `interface`, and `input
|
660
|
+
description: 'Fields of `type`, `interface`, and `input`',
|
627
661
|
},
|
628
662
|
values: {
|
629
663
|
type: 'array',
|
630
|
-
|
664
|
+
uniqueItems: true,
|
665
|
+
minItems: 1,
|
666
|
+
items: {
|
631
667
|
enum: valuesEnum,
|
632
668
|
},
|
633
|
-
description: 'Values of `enum
|
669
|
+
description: 'Values of `enum`',
|
634
670
|
},
|
635
671
|
selections: {
|
636
672
|
type: 'array',
|
637
|
-
|
673
|
+
uniqueItems: true,
|
674
|
+
minItems: 1,
|
675
|
+
items: {
|
638
676
|
enum: selectionsEnum,
|
639
677
|
},
|
640
|
-
description: 'Selections of operations (`query`, `mutation` and `subscription`) and `fragment
|
678
|
+
description: 'Selections of operations (`query`, `mutation` and `subscription`) and `fragment`',
|
641
679
|
},
|
642
680
|
variables: {
|
643
681
|
type: 'array',
|
644
|
-
|
682
|
+
uniqueItems: true,
|
683
|
+
minItems: 1,
|
684
|
+
items: {
|
645
685
|
enum: variablesEnum,
|
646
686
|
},
|
647
|
-
description: 'Variables of operations (`query`, `mutation` and `subscription`)
|
687
|
+
description: 'Variables of operations (`query`, `mutation` and `subscription`)',
|
648
688
|
},
|
649
689
|
arguments: {
|
650
690
|
type: 'array',
|
651
|
-
|
691
|
+
uniqueItems: true,
|
692
|
+
minItems: 1,
|
693
|
+
items: {
|
652
694
|
enum: argumentsEnum,
|
653
695
|
},
|
654
|
-
description: 'Arguments of fields and directives
|
696
|
+
description: 'Arguments of fields and directives',
|
655
697
|
},
|
656
698
|
},
|
657
699
|
},
|
@@ -682,7 +724,7 @@ const rule = {
|
|
682
724
|
const opts = context.options[0];
|
683
725
|
const fields = new Set((_a = opts.fields) !== null && _a !== void 0 ? _a : []);
|
684
726
|
const listeners = {};
|
685
|
-
const
|
727
|
+
const kinds = [
|
686
728
|
fields.has(Kind.OBJECT_TYPE_DEFINITION) && [Kind.OBJECT_TYPE_DEFINITION, Kind.OBJECT_TYPE_EXTENSION],
|
687
729
|
fields.has(Kind.INTERFACE_TYPE_DEFINITION) && [Kind.INTERFACE_TYPE_DEFINITION, Kind.INTERFACE_TYPE_EXTENSION],
|
688
730
|
fields.has(Kind.INPUT_OBJECT_TYPE_DEFINITION) && [
|
@@ -690,8 +732,9 @@ const rule = {
|
|
690
732
|
Kind.INPUT_OBJECT_TYPE_EXTENSION,
|
691
733
|
],
|
692
734
|
]
|
693
|
-
.
|
694
|
-
.
|
735
|
+
.filter(Boolean)
|
736
|
+
.flat();
|
737
|
+
const fieldsSelector = kinds.join(',');
|
695
738
|
const hasEnumValues = ((_b = opts.values) === null || _b === void 0 ? void 0 : _b[0]) === Kind.ENUM_TYPE_DEFINITION;
|
696
739
|
const selectionsSelector = (_c = opts.selections) === null || _c === void 0 ? void 0 : _c.join(',');
|
697
740
|
const hasVariables = ((_d = opts.variables) === null || _d === void 0 ? void 0 : _d[0]) === Kind.OPERATION_DEFINITION;
|
@@ -1091,6 +1134,9 @@ const rule$5 = {
|
|
1091
1134
|
},
|
1092
1135
|
};
|
1093
1136
|
|
1137
|
+
const isObjectType = (node) => [Kind.OBJECT_TYPE_DEFINITION, Kind.OBJECT_TYPE_EXTENSION].includes(node.type);
|
1138
|
+
const isQueryType = (node) => isObjectType(node) && node.name.value === 'Query';
|
1139
|
+
const isMutationType = (node) => isObjectType(node) && node.name.value === 'Mutation';
|
1094
1140
|
const rule$6 = {
|
1095
1141
|
meta: {
|
1096
1142
|
type: 'suggestion',
|
@@ -1131,6 +1177,7 @@ const rule$6 = {
|
|
1131
1177
|
schema: [
|
1132
1178
|
{
|
1133
1179
|
type: 'object',
|
1180
|
+
additionalProperties: false,
|
1134
1181
|
properties: {
|
1135
1182
|
checkInputType: {
|
1136
1183
|
type: 'boolean',
|
@@ -1153,24 +1200,22 @@ const rule$6 = {
|
|
1153
1200
|
description: 'Apply the rule to Mutations',
|
1154
1201
|
},
|
1155
1202
|
},
|
1156
|
-
additionalProperties: false,
|
1157
1203
|
},
|
1158
1204
|
],
|
1159
1205
|
},
|
1160
1206
|
create(context) {
|
1161
|
-
var _a;
|
1162
1207
|
const options = {
|
1163
|
-
caseSensitiveInputType: true,
|
1164
1208
|
checkInputType: false,
|
1165
|
-
|
1209
|
+
caseSensitiveInputType: true,
|
1166
1210
|
checkQueries: false,
|
1167
|
-
|
1211
|
+
checkMutations: true,
|
1212
|
+
...context.options[0],
|
1168
1213
|
};
|
1169
1214
|
const shouldCheckType = node => (options.checkMutations && isMutationType(node)) || (options.checkQueries && isQueryType(node));
|
1170
1215
|
const listeners = {
|
1171
|
-
'FieldDefinition > InputValueDefinition'
|
1172
|
-
|
1173
|
-
|
1216
|
+
'FieldDefinition > InputValueDefinition[name.value!=input]'(node) {
|
1217
|
+
if (shouldCheckType(node.parent.parent)) {
|
1218
|
+
const name = node.name.value;
|
1174
1219
|
context.report({
|
1175
1220
|
loc: getLocation(node.loc, name),
|
1176
1221
|
message: `Input "${name}" should be called "input"`,
|
@@ -1178,11 +1223,11 @@ const rule$6 = {
|
|
1178
1223
|
}
|
1179
1224
|
},
|
1180
1225
|
};
|
1181
|
-
if (options
|
1182
|
-
listeners['FieldDefinition > InputValueDefinition NamedType'] = node => {
|
1226
|
+
if (options.checkInputType) {
|
1227
|
+
listeners['FieldDefinition > InputValueDefinition NamedType'] = (node) => {
|
1183
1228
|
const findInputType = item => {
|
1184
1229
|
let currentNode = item;
|
1185
|
-
while (currentNode.type !==
|
1230
|
+
while (currentNode.type !== Kind.INPUT_VALUE_DEFINITION) {
|
1186
1231
|
currentNode = currentNode.parent;
|
1187
1232
|
}
|
1188
1233
|
return currentNode;
|
@@ -1399,69 +1444,40 @@ const rule$7 = {
|
|
1399
1444
|
},
|
1400
1445
|
};
|
1401
1446
|
|
1402
|
-
const
|
1403
|
-
|
1404
|
-
|
1405
|
-
|
1406
|
-
|
1407
|
-
|
1408
|
-
const acceptedStyles = [
|
1409
|
-
'camelCase',
|
1410
|
-
'PascalCase',
|
1411
|
-
'snake_case',
|
1412
|
-
'UPPER_CASE',
|
1447
|
+
const FIELDS_KINDS = [
|
1448
|
+
Kind.FIELD_DEFINITION,
|
1449
|
+
Kind.INPUT_VALUE_DEFINITION,
|
1450
|
+
Kind.VARIABLE_DEFINITION,
|
1451
|
+
Kind.ARGUMENT,
|
1452
|
+
Kind.DIRECTIVE_DEFINITION,
|
1413
1453
|
];
|
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
|
-
|
1441
|
-
if (forbiddenPrefixes.some(forbiddenPrefix => name.startsWith(forbiddenPrefix))) {
|
1442
|
-
return {
|
1443
|
-
ok: false,
|
1444
|
-
errorMessage: '{{nodeType}} "{{nodeName}}" should not have one of the following prefix(es): {{forbiddenPrefixes}}',
|
1445
|
-
};
|
1446
|
-
}
|
1447
|
-
if (forbiddenSuffixes.some(forbiddenSuffix => name.endsWith(forbiddenSuffix))) {
|
1448
|
-
return {
|
1449
|
-
ok: false,
|
1450
|
-
errorMessage: '{{nodeType}} "{{nodeName}}" should not have one of the following suffix(es): {{forbiddenSuffixes}}',
|
1451
|
-
};
|
1452
|
-
}
|
1453
|
-
if (!formats[style]) {
|
1454
|
-
return { ok: true };
|
1455
|
-
}
|
1456
|
-
const ok = new RegExp(formats[style]).test(name);
|
1457
|
-
if (ok) {
|
1458
|
-
return { ok: true };
|
1459
|
-
}
|
1460
|
-
return {
|
1461
|
-
ok: false,
|
1462
|
-
errorMessage: '{{nodeType}} name "{{nodeName}}" should be in {{format}} format',
|
1463
|
-
};
|
1464
|
-
}
|
1454
|
+
const KindToDisplayName = {
|
1455
|
+
// types
|
1456
|
+
[Kind.OBJECT_TYPE_DEFINITION]: 'Type',
|
1457
|
+
[Kind.INTERFACE_TYPE_DEFINITION]: 'Interface',
|
1458
|
+
[Kind.ENUM_TYPE_DEFINITION]: 'Enumerator',
|
1459
|
+
[Kind.SCALAR_TYPE_DEFINITION]: 'Scalar',
|
1460
|
+
[Kind.INPUT_OBJECT_TYPE_DEFINITION]: 'Input type',
|
1461
|
+
[Kind.UNION_TYPE_DEFINITION]: 'Union',
|
1462
|
+
// fields
|
1463
|
+
[Kind.FIELD_DEFINITION]: 'Field',
|
1464
|
+
[Kind.INPUT_VALUE_DEFINITION]: 'Input property',
|
1465
|
+
[Kind.VARIABLE_DEFINITION]: 'Variable',
|
1466
|
+
[Kind.ARGUMENT]: 'Argument',
|
1467
|
+
[Kind.DIRECTIVE_DEFINITION]: 'Directive',
|
1468
|
+
// rest
|
1469
|
+
[Kind.ENUM_VALUE_DEFINITION]: 'Enumeration value',
|
1470
|
+
[Kind.OPERATION_DEFINITION]: 'Operation',
|
1471
|
+
[Kind.FRAGMENT_DEFINITION]: 'Fragment',
|
1472
|
+
};
|
1473
|
+
const StyleToRegex = {
|
1474
|
+
camelCase: /^[a-z][\dA-Za-z]*$/,
|
1475
|
+
PascalCase: /^[A-Z][\dA-Za-z]*$/,
|
1476
|
+
snake_case: /^[a-z][\d_a-z]*[\da-z]$/,
|
1477
|
+
UPPER_CASE: /^[A-Z][\dA-Z_]*[\dA-Z]$/,
|
1478
|
+
};
|
1479
|
+
const ALLOWED_KINDS = Object.keys(KindToDisplayName).sort();
|
1480
|
+
const ALLOWED_STYLES = Object.keys(StyleToRegex);
|
1465
1481
|
const schemaOption$1 = {
|
1466
1482
|
oneOf: [{ $ref: '#/definitions/asString' }, { $ref: '#/definitions/asObject' }],
|
1467
1483
|
};
|
@@ -1476,89 +1492,120 @@ const rule$8 = {
|
|
1476
1492
|
examples: [
|
1477
1493
|
{
|
1478
1494
|
title: 'Incorrect',
|
1479
|
-
usage: [{
|
1495
|
+
usage: [{ types: 'PascalCase', fields: 'camelCase' }],
|
1480
1496
|
code: /* GraphQL */ `
|
1481
|
-
type
|
1482
|
-
|
1497
|
+
type user {
|
1498
|
+
first_name: String!
|
1483
1499
|
}
|
1484
1500
|
`,
|
1485
1501
|
},
|
1486
1502
|
{
|
1487
1503
|
title: 'Correct',
|
1488
|
-
usage: [{
|
1504
|
+
usage: [{ types: 'PascalCase', fields: 'camelCase' }],
|
1489
1505
|
code: /* GraphQL */ `
|
1490
|
-
type
|
1491
|
-
|
1506
|
+
type User {
|
1507
|
+
firstName: String
|
1492
1508
|
}
|
1493
1509
|
`,
|
1494
1510
|
},
|
1495
1511
|
],
|
1512
|
+
optionsForConfig: [
|
1513
|
+
{
|
1514
|
+
types: 'PascalCase',
|
1515
|
+
fields: 'camelCase',
|
1516
|
+
overrides: {
|
1517
|
+
EnumValueDefinition: 'UPPER_CASE',
|
1518
|
+
OperationDefinition: {
|
1519
|
+
style: 'PascalCase',
|
1520
|
+
forbiddenPrefixes: ['Query', 'Mutation', 'Subscription', 'Get'],
|
1521
|
+
forbiddenSuffixes: ['Query', 'Mutation', 'Subscription'],
|
1522
|
+
},
|
1523
|
+
FragmentDefinition: {
|
1524
|
+
style: 'PascalCase',
|
1525
|
+
forbiddenPrefixes: ['Fragment'],
|
1526
|
+
forbiddenSuffixes: ['Fragment'],
|
1527
|
+
},
|
1528
|
+
'FieldDefinition[parent.name.value=Query]': {
|
1529
|
+
forbiddenPrefixes: ['query', 'get'],
|
1530
|
+
forbiddenSuffixes: ['Query'],
|
1531
|
+
},
|
1532
|
+
'FieldDefinition[parent.name.value=Mutation]': {
|
1533
|
+
forbiddenPrefixes: ['mutation'],
|
1534
|
+
forbiddenSuffixes: ['Mutation'],
|
1535
|
+
},
|
1536
|
+
'FieldDefinition[parent.name.value=Subscription]': {
|
1537
|
+
forbiddenPrefixes: ['subscription'],
|
1538
|
+
forbiddenSuffixes: ['Subscription'],
|
1539
|
+
},
|
1540
|
+
},
|
1541
|
+
},
|
1542
|
+
],
|
1496
1543
|
},
|
1497
1544
|
schema: {
|
1498
1545
|
definitions: {
|
1499
1546
|
asString: {
|
1500
|
-
|
1501
|
-
description: `One of: ${
|
1502
|
-
enum: acceptedStyles,
|
1547
|
+
enum: ALLOWED_STYLES,
|
1548
|
+
description: `One of: ${ALLOWED_STYLES.map(t => `\`${t}\``).join(', ')}`,
|
1503
1549
|
},
|
1504
1550
|
asObject: {
|
1505
1551
|
type: 'object',
|
1552
|
+
additionalProperties: false,
|
1506
1553
|
properties: {
|
1507
|
-
style: {
|
1508
|
-
|
1509
|
-
|
1510
|
-
},
|
1511
|
-
prefix: {
|
1512
|
-
type: 'string',
|
1513
|
-
},
|
1514
|
-
suffix: {
|
1515
|
-
type: 'string',
|
1516
|
-
},
|
1554
|
+
style: { enum: ALLOWED_STYLES },
|
1555
|
+
prefix: { type: 'string' },
|
1556
|
+
suffix: { type: 'string' },
|
1517
1557
|
forbiddenPrefixes: {
|
1518
|
-
additionalItems: false,
|
1519
1558
|
type: 'array',
|
1559
|
+
uniqueItems: true,
|
1520
1560
|
minItems: 1,
|
1521
|
-
items: {
|
1522
|
-
type: 'string',
|
1523
|
-
},
|
1561
|
+
items: { type: 'string' },
|
1524
1562
|
},
|
1525
1563
|
forbiddenSuffixes: {
|
1526
|
-
additionalItems: false,
|
1527
1564
|
type: 'array',
|
1565
|
+
uniqueItems: true,
|
1528
1566
|
minItems: 1,
|
1529
|
-
items: {
|
1530
|
-
type: 'string',
|
1531
|
-
},
|
1567
|
+
items: { type: 'string' },
|
1532
1568
|
},
|
1533
1569
|
},
|
1534
1570
|
},
|
1535
1571
|
},
|
1536
|
-
$schema: 'http://json-schema.org/draft-04/schema#',
|
1537
1572
|
type: 'array',
|
1573
|
+
maxItems: 1,
|
1538
1574
|
items: {
|
1539
1575
|
type: 'object',
|
1576
|
+
additionalProperties: false,
|
1540
1577
|
properties: {
|
1541
|
-
|
1542
|
-
|
1543
|
-
|
1544
|
-
[Kind.INPUT_VALUE_DEFINITION]: schemaOption$1,
|
1545
|
-
[Kind.OBJECT_TYPE_DEFINITION]: schemaOption$1,
|
1546
|
-
[Kind.INTERFACE_TYPE_DEFINITION]: schemaOption$1,
|
1547
|
-
[Kind.ENUM_TYPE_DEFINITION]: schemaOption$1,
|
1548
|
-
[Kind.UNION_TYPE_DEFINITION]: schemaOption$1,
|
1549
|
-
[Kind.SCALAR_TYPE_DEFINITION]: schemaOption$1,
|
1550
|
-
[Kind.OPERATION_DEFINITION]: schemaOption$1,
|
1551
|
-
[Kind.FRAGMENT_DEFINITION]: schemaOption$1,
|
1552
|
-
QueryDefinition: schemaOption$1,
|
1553
|
-
leadingUnderscore: {
|
1554
|
-
type: 'string',
|
1555
|
-
enum: ['allow', 'forbid'],
|
1556
|
-
default: 'forbid',
|
1578
|
+
types: {
|
1579
|
+
...schemaOption$1,
|
1580
|
+
description: `Includes:\n\n${TYPES_KINDS.map(kind => `- \`${kind}\``).join('\n')}`,
|
1557
1581
|
},
|
1558
|
-
|
1559
|
-
|
1560
|
-
|
1561
|
-
|
1582
|
+
fields: {
|
1583
|
+
...schemaOption$1,
|
1584
|
+
description: `Includes:\n\n${FIELDS_KINDS.map(kind => `- \`${kind}\``).join('\n')}`,
|
1585
|
+
},
|
1586
|
+
allowLeadingUnderscore: {
|
1587
|
+
type: 'boolean',
|
1588
|
+
default: false,
|
1589
|
+
},
|
1590
|
+
allowTrailingUnderscore: {
|
1591
|
+
type: 'boolean',
|
1592
|
+
default: false,
|
1593
|
+
},
|
1594
|
+
overrides: {
|
1595
|
+
type: 'object',
|
1596
|
+
additionalProperties: false,
|
1597
|
+
description: [
|
1598
|
+
'May contain the following `ASTNode` names:',
|
1599
|
+
'',
|
1600
|
+
...ALLOWED_KINDS.map(kind => `- \`${kind}\``),
|
1601
|
+
'',
|
1602
|
+
"> It's also possible to use a [`selector`](https://eslint.org/docs/developer-guide/selectors) that starts with `ASTNode` name",
|
1603
|
+
'>',
|
1604
|
+
'> Example: pattern property `FieldDefinition[parent.name.value=Query]` will match only fields for type `Query`',
|
1605
|
+
].join('\n'),
|
1606
|
+
patternProperties: {
|
1607
|
+
[`^(${ALLOWED_KINDS.join('|')})(.+)?$`]: schemaOption$1,
|
1608
|
+
},
|
1562
1609
|
},
|
1563
1610
|
},
|
1564
1611
|
},
|
@@ -1566,136 +1613,83 @@ const rule$8 = {
|
|
1566
1613
|
},
|
1567
1614
|
create(context) {
|
1568
1615
|
const options = {
|
1569
|
-
|
1570
|
-
|
1571
|
-
...(context.options[0] || {}),
|
1616
|
+
overrides: {},
|
1617
|
+
...context.options[0],
|
1572
1618
|
};
|
1573
|
-
|
1574
|
-
|
1575
|
-
|
1576
|
-
|
1577
|
-
|
1578
|
-
|
1579
|
-
|
1580
|
-
|
1581
|
-
|
1582
|
-
|
1583
|
-
|
1584
|
-
}
|
1585
|
-
|
1619
|
+
function normalisePropertyOption(kind) {
|
1620
|
+
let style = options.overrides[kind];
|
1621
|
+
if (!style) {
|
1622
|
+
style = TYPES_KINDS.includes(kind) ? options.types : options.fields;
|
1623
|
+
}
|
1624
|
+
return typeof style === 'object' ? style : { style };
|
1625
|
+
}
|
1626
|
+
const checkNode = (selector) => (node) => {
|
1627
|
+
const { name } = node.kind === Kind.VARIABLE_DEFINITION ? node.variable : node;
|
1628
|
+
if (!name) {
|
1629
|
+
return;
|
1630
|
+
}
|
1631
|
+
const { prefix, suffix, forbiddenPrefixes, forbiddenSuffixes, style } = normalisePropertyOption(selector);
|
1632
|
+
const nodeType = KindToDisplayName[node.kind] || node.kind;
|
1633
|
+
const nodeName = name.value;
|
1634
|
+
const errorMessage = getErrorMessage();
|
1635
|
+
if (errorMessage) {
|
1586
1636
|
context.report({
|
1587
|
-
loc: getLocation(
|
1588
|
-
message:
|
1589
|
-
data: {
|
1590
|
-
prefix,
|
1591
|
-
suffix,
|
1592
|
-
format: style,
|
1593
|
-
forbiddenPrefixes: forbiddenPrefixes.join(', '),
|
1594
|
-
forbiddenSuffixes: forbiddenSuffixes.join(', '),
|
1595
|
-
nodeType,
|
1596
|
-
nodeName: node.value,
|
1597
|
-
},
|
1637
|
+
loc: getLocation(name.loc, name.value),
|
1638
|
+
message: `${nodeType} "${nodeName}" should ${errorMessage}`,
|
1598
1639
|
});
|
1599
1640
|
}
|
1600
|
-
|
1601
|
-
|
1602
|
-
|
1603
|
-
|
1604
|
-
}
|
1605
|
-
return {
|
1606
|
-
style: value,
|
1607
|
-
prefix: '',
|
1608
|
-
suffix: '',
|
1609
|
-
};
|
1610
|
-
};
|
1611
|
-
return {
|
1612
|
-
Name: node => {
|
1613
|
-
if (node.value.startsWith('_') && options.leadingUnderscore === 'forbid') {
|
1614
|
-
context.report({
|
1615
|
-
loc: getLocation(node.loc, node.value),
|
1616
|
-
message: 'Leading underscores are not allowed',
|
1617
|
-
});
|
1618
|
-
}
|
1619
|
-
if (node.value.endsWith('_') && options.trailingUnderscore === 'forbid') {
|
1620
|
-
context.report({
|
1621
|
-
loc: getLocation(node.loc, node.value),
|
1622
|
-
message: 'Trailing underscores are not allowed',
|
1623
|
-
});
|
1624
|
-
}
|
1625
|
-
},
|
1626
|
-
ObjectTypeDefinition: node => {
|
1627
|
-
if (options.ObjectTypeDefinition) {
|
1628
|
-
const property = normalisePropertyOption(options.ObjectTypeDefinition);
|
1629
|
-
checkNode(node.name, property, 'Type');
|
1630
|
-
}
|
1631
|
-
},
|
1632
|
-
InterfaceTypeDefinition: node => {
|
1633
|
-
if (options.InterfaceTypeDefinition) {
|
1634
|
-
const property = normalisePropertyOption(options.InterfaceTypeDefinition);
|
1635
|
-
checkNode(node.name, property, 'Interface');
|
1636
|
-
}
|
1637
|
-
},
|
1638
|
-
EnumTypeDefinition: node => {
|
1639
|
-
if (options.EnumTypeDefinition) {
|
1640
|
-
const property = normalisePropertyOption(options.EnumTypeDefinition);
|
1641
|
-
checkNode(node.name, property, 'Enumerator');
|
1642
|
-
}
|
1643
|
-
},
|
1644
|
-
InputObjectTypeDefinition: node => {
|
1645
|
-
if (options.InputObjectTypeDefinition) {
|
1646
|
-
const property = normalisePropertyOption(options.InputObjectTypeDefinition);
|
1647
|
-
checkNode(node.name, property, 'Input type');
|
1648
|
-
}
|
1649
|
-
},
|
1650
|
-
FieldDefinition: (node) => {
|
1651
|
-
if (options.QueryDefinition && isQueryType(node.parent)) {
|
1652
|
-
const property = normalisePropertyOption(options.QueryDefinition);
|
1653
|
-
checkNode(node.name, property, 'Query');
|
1641
|
+
function getErrorMessage() {
|
1642
|
+
let name = nodeName;
|
1643
|
+
if (options.allowLeadingUnderscore) {
|
1644
|
+
name = name.replace(/^_*/, '');
|
1654
1645
|
}
|
1655
|
-
if (options.
|
1656
|
-
|
1657
|
-
checkNode(node.name, property, 'Field');
|
1646
|
+
if (options.allowTrailingUnderscore) {
|
1647
|
+
name = name.replace(/_*$/, '');
|
1658
1648
|
}
|
1659
|
-
|
1660
|
-
|
1661
|
-
if (options.EnumValueDefinition) {
|
1662
|
-
const property = normalisePropertyOption(options.EnumValueDefinition);
|
1663
|
-
checkNode(node.name, property, 'Enumeration value');
|
1649
|
+
if (prefix && !name.startsWith(prefix)) {
|
1650
|
+
return `have "${prefix}" prefix`;
|
1664
1651
|
}
|
1665
|
-
|
1666
|
-
|
1667
|
-
if (options.InputValueDefinition) {
|
1668
|
-
const property = normalisePropertyOption(options.InputValueDefinition);
|
1669
|
-
checkNode(node.name, property, 'Input property');
|
1652
|
+
if (suffix && !name.endsWith(suffix)) {
|
1653
|
+
return `have "${suffix}" suffix`;
|
1670
1654
|
}
|
1671
|
-
|
1672
|
-
|
1673
|
-
|
1674
|
-
const property = normalisePropertyOption(options.OperationDefinition);
|
1675
|
-
if (node.name) {
|
1676
|
-
checkNode(node.name, property, 'Operation');
|
1677
|
-
}
|
1655
|
+
const forbiddenPrefix = forbiddenPrefixes === null || forbiddenPrefixes === void 0 ? void 0 : forbiddenPrefixes.find(prefix => name.startsWith(prefix));
|
1656
|
+
if (forbiddenPrefix) {
|
1657
|
+
return `not have "${forbiddenPrefix}" prefix`;
|
1678
1658
|
}
|
1679
|
-
|
1680
|
-
|
1681
|
-
|
1682
|
-
const property = normalisePropertyOption(options.FragmentDefinition);
|
1683
|
-
checkNode(node.name, property, 'Fragment');
|
1659
|
+
const forbiddenSuffix = forbiddenSuffixes === null || forbiddenSuffixes === void 0 ? void 0 : forbiddenSuffixes.find(suffix => name.endsWith(suffix));
|
1660
|
+
if (forbiddenSuffix) {
|
1661
|
+
return `not have "${forbiddenSuffix}" suffix`;
|
1684
1662
|
}
|
1685
|
-
|
1686
|
-
|
1687
|
-
if (options.ScalarTypeDefinition) {
|
1688
|
-
const property = normalisePropertyOption(options.ScalarTypeDefinition);
|
1689
|
-
checkNode(node.name, property, 'Scalar');
|
1663
|
+
if (style && !ALLOWED_STYLES.includes(style)) {
|
1664
|
+
return `be in one of the following options: ${ALLOWED_STYLES.join(', ')}`;
|
1690
1665
|
}
|
1691
|
-
|
1692
|
-
|
1693
|
-
|
1694
|
-
const property = normalisePropertyOption(options.UnionTypeDefinition);
|
1695
|
-
checkNode(node.name, property, 'Union');
|
1666
|
+
const caseRegex = StyleToRegex[style];
|
1667
|
+
if (caseRegex && !caseRegex.test(name)) {
|
1668
|
+
return `be in ${style} format`;
|
1696
1669
|
}
|
1697
|
-
}
|
1670
|
+
}
|
1698
1671
|
};
|
1672
|
+
const checkUnderscore = (node) => {
|
1673
|
+
const name = node.value;
|
1674
|
+
context.report({
|
1675
|
+
loc: getLocation(node.loc, name),
|
1676
|
+
message: `${name.startsWith('_') ? 'Leading' : 'Trailing'} underscores are not allowed`,
|
1677
|
+
});
|
1678
|
+
};
|
1679
|
+
const listeners = {};
|
1680
|
+
if (!options.allowLeadingUnderscore) {
|
1681
|
+
listeners['Name[value=/^_/]:matches([parent.kind!=Field], [parent.kind=Field][parent.alias])'] = checkUnderscore;
|
1682
|
+
}
|
1683
|
+
if (!options.allowTrailingUnderscore) {
|
1684
|
+
listeners['Name[value=/_$/]:matches([parent.kind!=Field], [parent.kind=Field][parent.alias])'] = checkUnderscore;
|
1685
|
+
}
|
1686
|
+
const selectors = new Set([options.types && TYPES_KINDS, options.fields && FIELDS_KINDS, Object.keys(options.overrides)]
|
1687
|
+
.flat()
|
1688
|
+
.filter(Boolean));
|
1689
|
+
for (const selector of selectors) {
|
1690
|
+
listeners[selector] = checkNode(selector);
|
1691
|
+
}
|
1692
|
+
return listeners;
|
1699
1693
|
},
|
1700
1694
|
};
|
1701
1695
|
|
@@ -2412,6 +2406,7 @@ function convertDescription(node) {
|
|
2412
2406
|
return [];
|
2413
2407
|
}
|
2414
2408
|
|
2409
|
+
// eslint-disable-next-line unicorn/better-regex
|
2415
2410
|
const DATE_REGEX = /^\d{2}\/\d{2}\/\d{4}$/;
|
2416
2411
|
const MESSAGE_REQUIRE_DATE = 'MESSAGE_REQUIRE_DATE';
|
2417
2412
|
const MESSAGE_INVALID_FORMAT = 'MESSAGE_INVALID_FORMAT';
|
@@ -3205,7 +3200,7 @@ const rule$n = {
|
|
3205
3200
|
acceptedIdNames: ['id'],
|
3206
3201
|
acceptedIdTypes: ['ID'],
|
3207
3202
|
exceptions: {},
|
3208
|
-
...
|
3203
|
+
...context.options[0],
|
3209
3204
|
};
|
3210
3205
|
return {
|
3211
3206
|
ObjectTypeDefinition(node) {
|