@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/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',
@@ -206,9 +233,14 @@ const loaderCache = new Proxy(Object.create(null), {
206
233
  return true;
207
234
  },
208
235
  });
209
- const isObjectType = (node) => [Kind.OBJECT_TYPE_DEFINITION, Kind.OBJECT_TYPE_EXTENSION].includes(node.type);
210
- const isQueryType = (node) => isObjectType(node) && node.name.value === 'Query';
211
- const isMutationType = (node) => isObjectType(node) && node.name.value === 'Mutation';
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[/\\\\]rules[/\\\\](.*?)\.js:/) || [];
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
- contains: {
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
- contains: {
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
- contains: {
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
- contains: {
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
- contains: {
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 fieldsSelector = [
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
- .flat()
694
- .join(',');
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
- checkMutations: true,
1209
+ caseSensitiveInputType: true,
1166
1210
  checkQueries: false,
1167
- ...(_a = context === null || context === void 0 ? void 0 : context.options) === null || _a === void 0 ? void 0 : _a[0],
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': node => {
1172
- const name = node.name.value;
1173
- if (name !== 'input' && shouldCheckType(node.parent.parent)) {
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 === null || options === void 0 ? void 0 : options.checkInputType) {
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 !== 'InputValueDefinition') {
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 formats = {
1403
- camelCase: /^[a-z][^_]*$/g,
1404
- PascalCase: /^[A-Z][^_]*$/g,
1405
- snake_case: /^[a-z_][a-z0-9_]*$/g,
1406
- UPPER_CASE: /^[A-Z_][A-Z0-9_]*$/g,
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
- function checkNameFormat(params) {
1415
- const { value, style, leadingUnderscore, trailingUnderscore, suffix, prefix, forbiddenPrefixes, forbiddenSuffixes, } = params;
1416
- let name = value;
1417
- if (leadingUnderscore === 'allow') {
1418
- [, name] = name.match(/^_*(.*)$/);
1419
- }
1420
- if (trailingUnderscore === 'allow') {
1421
- name = name.replace(/_*$/, '');
1422
- }
1423
- if (prefix && !name.startsWith(prefix)) {
1424
- return {
1425
- ok: false,
1426
- errorMessage: '{{nodeType}} name "{{nodeName}}" should have "{{prefix}}" prefix',
1427
- };
1428
- }
1429
- if (suffix && !name.endsWith(suffix)) {
1430
- return {
1431
- ok: false,
1432
- errorMessage: '{{nodeType}} name "{{nodeName}}" should have "{{suffix}}" suffix',
1433
- };
1434
- }
1435
- if (style && !acceptedStyles.includes(style)) {
1436
- return {
1437
- ok: false,
1438
- errorMessage: `{{nodeType}} name "{{nodeName}}" should be in one of the following options: ${acceptedStyles.join(',')}`,
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: [{ ObjectTypeDefinition: 'PascalCase' }],
1495
+ usage: [{ types: 'PascalCase', fields: 'camelCase' }],
1480
1496
  code: /* GraphQL */ `
1481
- type someTypeName {
1482
- f: String!
1497
+ type user {
1498
+ first_name: String!
1483
1499
  }
1484
1500
  `,
1485
1501
  },
1486
1502
  {
1487
1503
  title: 'Correct',
1488
- usage: [{ FieldDefinition: 'camelCase', ObjectTypeDefinition: 'PascalCase' }],
1504
+ usage: [{ types: 'PascalCase', fields: 'camelCase' }],
1489
1505
  code: /* GraphQL */ `
1490
- type SomeTypeName {
1491
- someFieldName: String
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
- type: 'string',
1501
- description: `One of: ${acceptedStyles.map(t => `\`${t}\``).join(', ')}`,
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
- type: 'string',
1509
- enum: acceptedStyles,
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
- [Kind.FIELD_DEFINITION]: schemaOption$1,
1542
- [Kind.INPUT_OBJECT_TYPE_DEFINITION]: schemaOption$1,
1543
- [Kind.ENUM_VALUE_DEFINITION]: schemaOption$1,
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
- trailingUnderscore: {
1559
- type: 'string',
1560
- enum: ['allow', 'forbid'],
1561
- default: 'forbid',
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
- leadingUnderscore: 'forbid',
1570
- trailingUnderscore: 'forbid',
1571
- ...(context.options[0] || {}),
1616
+ overrides: {},
1617
+ ...context.options[0],
1572
1618
  };
1573
- const checkNode = (node, property, nodeType) => {
1574
- const { style, suffix = '', prefix = '', forbiddenPrefixes = [], forbiddenSuffixes = [] } = property;
1575
- const result = checkNameFormat({
1576
- value: node.value,
1577
- style,
1578
- leadingUnderscore: options.leadingUnderscore,
1579
- trailingUnderscore: options.trailingUnderscore,
1580
- prefix,
1581
- suffix,
1582
- forbiddenPrefixes,
1583
- forbiddenSuffixes,
1584
- });
1585
- if (result.ok === false) {
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(node.loc, node.value),
1588
- message: result.errorMessage,
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
- const normalisePropertyOption = (value) => {
1602
- if (typeof value === 'object') {
1603
- return value;
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.FieldDefinition && !isQueryType(node.parent)) {
1656
- const property = normalisePropertyOption(options.FieldDefinition);
1657
- checkNode(node.name, property, 'Field');
1646
+ if (options.allowTrailingUnderscore) {
1647
+ name = name.replace(/_*$/, '');
1658
1648
  }
1659
- },
1660
- EnumValueDefinition: node => {
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
- InputValueDefinition: node => {
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
- OperationDefinition: node => {
1673
- if (options.OperationDefinition) {
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
- FragmentDefinition: node => {
1681
- if (options.FragmentDefinition) {
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
- ScalarTypeDefinition: node => {
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
- UnionTypeDefinition: node => {
1693
- if (options.UnionTypeDefinition) {
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
- ...(context.options[0] || {}),
3203
+ ...context.options[0],
3209
3204
  };
3210
3205
  return {
3211
3206
  ObjectTypeDefinition(node) {