@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/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': 'error',
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 isObjectType = (node) => [Kind.OBJECT_TYPE_DEFINITION, Kind.OBJECT_TYPE_EXTENSION].includes(node.type);
209
- const isQueryType = (node) => isObjectType(node) && node.name.value === 'Query';
210
- const isMutationType = (node) => isObjectType(node) && node.name.value === 'Mutation';
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[/\\\\]rules[/\\\\](.*?)\.js:/) || [];
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
- contains: {
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
- contains: {
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
- contains: {
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
- contains: {
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
- contains: {
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 fieldsSelector = [
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
- .flat()
693
- .join(',');
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
- checkMutations: true,
1208
+ caseSensitiveInputType: true,
1165
1209
  checkQueries: false,
1166
- ...(_a = context === null || context === void 0 ? void 0 : context.options) === null || _a === void 0 ? void 0 : _a[0],
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': node => {
1171
- const name = node.name.value;
1172
- if (name !== 'input' && shouldCheckType(node.parent.parent)) {
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 === null || options === void 0 ? void 0 : options.checkInputType) {
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 !== 'InputValueDefinition') {
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 formats = {
1402
- camelCase: /^[a-z][^_]*$/g,
1403
- PascalCase: /^[A-Z][^_]*$/g,
1404
- snake_case: /^[a-z_][a-z0-9_]*$/g,
1405
- UPPER_CASE: /^[A-Z_][A-Z0-9_]*$/g,
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
- function checkNameFormat(params) {
1414
- const { value, style, leadingUnderscore, trailingUnderscore, suffix, prefix, forbiddenPrefixes, forbiddenSuffixes, } = params;
1415
- let name = value;
1416
- if (leadingUnderscore === 'allow') {
1417
- [, name] = name.match(/^_*(.*)$/);
1418
- }
1419
- if (trailingUnderscore === 'allow') {
1420
- name = name.replace(/_*$/, '');
1421
- }
1422
- if (prefix && !name.startsWith(prefix)) {
1423
- return {
1424
- ok: false,
1425
- errorMessage: '{{nodeType}} name "{{nodeName}}" should have "{{prefix}}" prefix',
1426
- };
1427
- }
1428
- if (suffix && !name.endsWith(suffix)) {
1429
- return {
1430
- ok: false,
1431
- errorMessage: '{{nodeType}} name "{{nodeName}}" should have "{{suffix}}" suffix',
1432
- };
1433
- }
1434
- if (style && !acceptedStyles.includes(style)) {
1435
- return {
1436
- ok: false,
1437
- errorMessage: `{{nodeType}} name "{{nodeName}}" should be in one of the following options: ${acceptedStyles.join(',')}`,
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: [{ ObjectTypeDefinition: 'PascalCase' }],
1494
+ usage: [{ types: 'PascalCase', fields: 'camelCase' }],
1479
1495
  code: /* GraphQL */ `
1480
- type someTypeName {
1481
- f: String!
1496
+ type user {
1497
+ first_name: String!
1482
1498
  }
1483
1499
  `,
1484
1500
  },
1485
1501
  {
1486
1502
  title: 'Correct',
1487
- usage: [{ FieldDefinition: 'camelCase', ObjectTypeDefinition: 'PascalCase' }],
1503
+ usage: [{ types: 'PascalCase', fields: 'camelCase' }],
1488
1504
  code: /* GraphQL */ `
1489
- type SomeTypeName {
1490
- someFieldName: String
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
- type: 'string',
1500
- description: `One of: ${acceptedStyles.map(t => `\`${t}\``).join(', ')}`,
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
- type: 'string',
1508
- enum: acceptedStyles,
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
- [Kind.FIELD_DEFINITION]: schemaOption$1,
1541
- [Kind.INPUT_OBJECT_TYPE_DEFINITION]: schemaOption$1,
1542
- [Kind.ENUM_VALUE_DEFINITION]: schemaOption$1,
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
- trailingUnderscore: {
1558
- type: 'string',
1559
- enum: ['allow', 'forbid'],
1560
- default: 'forbid',
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
- leadingUnderscore: 'forbid',
1569
- trailingUnderscore: 'forbid',
1570
- ...(context.options[0] || {}),
1615
+ overrides: {},
1616
+ ...context.options[0],
1571
1617
  };
1572
- const checkNode = (node, property, nodeType) => {
1573
- const { style, suffix = '', prefix = '', forbiddenPrefixes = [], forbiddenSuffixes = [] } = property;
1574
- const result = checkNameFormat({
1575
- value: node.value,
1576
- style,
1577
- leadingUnderscore: options.leadingUnderscore,
1578
- trailingUnderscore: options.trailingUnderscore,
1579
- prefix,
1580
- suffix,
1581
- forbiddenPrefixes,
1582
- forbiddenSuffixes,
1583
- });
1584
- if (result.ok === false) {
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(node.loc, node.value),
1587
- message: result.errorMessage,
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
- const normalisePropertyOption = (value) => {
1601
- if (typeof value === 'object') {
1602
- return value;
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 (node.value.endsWith('_') && options.trailingUnderscore === 'forbid') {
1619
- context.report({
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
- ObjectTypeDefinition: node => {
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
- InterfaceTypeDefinition: node => {
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
- EnumTypeDefinition: node => {
1638
- if (options.EnumTypeDefinition) {
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
- InputObjectTypeDefinition: node => {
1644
- if (options.InputObjectTypeDefinition) {
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
- FieldDefinition: (node) => {
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
- if (options.FieldDefinition && !isQueryType(node.parent)) {
1655
- const property = normalisePropertyOption(options.FieldDefinition);
1656
- checkNode(node.name, property, 'Field');
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.deprecationReason) {
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.deprecationReason) {
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: [Kind.OBJECT_TYPE_DEFINITION, Kind.FIELD_DEFINITION] }],
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: [Kind.OBJECT_TYPE_DEFINITION, Kind.FIELD_DEFINITION] }],
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
- ...(context.options[0] || {}),
3111
+ ...context.options[0],
3117
3112
  };
3118
3113
  return {
3119
3114
  ObjectTypeDefinition(node) {