@graphql-eslint/eslint-plugin 3.11.0-alpha-20220828135426-e9545b1 → 3.11.0-alpha-20220923192439-db921ff

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/README.md CHANGED
@@ -9,7 +9,7 @@ This project integrates GraphQL and ESLint, for a better developer experience.
9
9
  ## Key Features
10
10
 
11
11
  - 🚀 Integrates with ESLint core (as a ESTree parser)
12
- - 🚀 Works on `.graphql` files, `gql` usages and `/* GraphQL */` magic comments
12
+ - 🚀 Works on `.graphql` files, `gql` usages and `/* GraphQL */` magic comments
13
13
  - 🚀 Lints both GraphQL schema and GraphQL operations
14
14
  - 🚀 Extended type info for more advanced usages
15
15
  - 🚀 Supports ESLint directives (for example: `eslint-disable-next-line`)
@@ -188,7 +188,7 @@ See [docs/deprecated-rules.md](docs/deprecated-rules.md).
188
188
  |[`relay`](packages/plugin/src/configs/relay.json)|enables rules from Relay specification for schema (SDL) development|
189
189
  <!-- prettier-ignore-end -->
190
190
 
191
- > If you are in a project that develops the GraphQL schema, you'll need `schema` rules.
191
+ > If you are in a project that develops the GraphQL schema, you'll need `schema` rules.
192
192
 
193
193
  > If you are in a project that develops GraphQL operations (query/mutation/subscription), you'll need `operations` rules.
194
194
 
@@ -4,18 +4,9 @@
4
4
  "@graphql-eslint/alphabetize": [
5
5
  "error",
6
6
  {
7
- "fields": [
8
- "ObjectTypeDefinition",
9
- "InterfaceTypeDefinition",
10
- "InputObjectTypeDefinition"
11
- ],
7
+ "fields": ["ObjectTypeDefinition", "InterfaceTypeDefinition", "InputObjectTypeDefinition"],
12
8
  "values": ["EnumTypeDefinition"],
13
- "arguments": [
14
- "FieldDefinition",
15
- "Field",
16
- "DirectiveDefinition",
17
- "Directive"
18
- ]
9
+ "arguments": ["FieldDefinition", "Field", "DirectiveDefinition", "Directive"]
19
10
  }
20
11
  ],
21
12
  "@graphql-eslint/input-name": "error",
package/docs/README.md CHANGED
@@ -71,5 +71,6 @@ Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbs
71
71
  [variables-are-input-types](rules/variables-are-input-types.md)|A GraphQL operation is only valid if all the variables it defines are of input types (scalar, enum, or input object).|![recommended][]|🔮|
72
72
  [variables-in-allowed-position](rules/variables-in-allowed-position.md)|Variables passed to field arguments conform to type.|![recommended][]|🔮|
73
73
  <!-- prettier-ignore-end -->
74
+
74
75
  [recommended]: https://img.shields.io/badge/-recommended-green.svg
75
76
  [all]: https://img.shields.io/badge/-all-blue.svg
@@ -141,7 +141,7 @@ ruleTester.runGraphQLTests('my-rule', rule, {
141
141
  invalid: [
142
142
  {
143
143
  code: 'query invalid { foo }',
144
- errors: [{ message: 'Your error message.' }],
144
+ errors: [{ message: 'Your error message.' }]
145
145
  }
146
146
  ]
147
147
  })
@@ -39,7 +39,8 @@ type User {
39
39
  # eslint @graphql-eslint/require-deprecation-date: 'error'
40
40
 
41
41
  type User {
42
- firstname: String @deprecated(reason: "Use 'firstName' instead", deletionDate: "25/12/2022")
42
+ firstname: String
43
+ @deprecated(reason: "Use 'firstName' instead", deletionDate: "25/12/2022")
43
44
  firstName: String
44
45
  }
45
46
  ```
package/index.js CHANGED
@@ -114,7 +114,7 @@ const getOnDiskFilepath = (filepath) => {
114
114
  }
115
115
  return filepath;
116
116
  };
117
- const getTypeName = (node) => ('type' in node ? getTypeName(node.type) : node.name.value);
117
+ const getTypeName = (node) => 'type' in node ? getTypeName(node.type) : node.name.value;
118
118
  const TYPES_KINDS = [
119
119
  graphql.Kind.OBJECT_TYPE_DEFINITION,
120
120
  graphql.Kind.INTERFACE_TYPE_DEFINITION,
@@ -189,7 +189,9 @@ function validateDocument(context, schema = null, documentNode, rule) {
189
189
  if (token) {
190
190
  loc =
191
191
  // if cursor on `@` symbol than use next node
192
- token.type === '@' ? sourceCode.getNodeByRangeIndex(token.range[1] + 1).loc : token.loc;
192
+ token.type === '@'
193
+ ? sourceCode.getNodeByRangeIndex(token.range[1] + 1).loc
194
+ : token.loc;
193
195
  }
194
196
  context.report({
195
197
  loc,
@@ -279,7 +281,9 @@ const validationToRule = (ruleId, ruleName, docs, getDocumentNode, schema = [])
279
281
  }
280
282
  return {
281
283
  Document(node) {
282
- const schema = docs.requiresSchema ? requireGraphQLSchemaFromContext(ruleId, context) : null;
284
+ const schema = docs.requiresSchema
285
+ ? requireGraphQLSchemaFromContext(ruleId, context)
286
+ : null;
283
287
  const documentNode = getDocumentNode
284
288
  ? getDocumentNode({ ruleId, context, node: node.rawNode() })
285
289
  : node.rawNode();
@@ -425,7 +429,10 @@ const GRAPHQL_JS_VALIDATIONS = Object.assign({}, validationToRule('executable-de
425
429
  requiresSiblings: true,
426
430
  }, ({ ruleId, context, node }) => {
427
431
  const siblings = requireSiblingsOperations(ruleId, context);
428
- const FilePathToDocumentsMap = [...siblings.getOperations(), ...siblings.getFragments()].reduce((map, { filePath, document }) => {
432
+ const FilePathToDocumentsMap = [
433
+ ...siblings.getOperations(),
434
+ ...siblings.getFragments(),
435
+ ].reduce((map, { filePath, document }) => {
429
436
  var _a;
430
437
  (_a = map[filePath]) !== null && _a !== void 0 ? _a : (map[filePath] = []);
431
438
  map[filePath].push(document);
@@ -705,14 +712,6 @@ const rule = {
705
712
  description: 'Definitions – `type`, `interface`, `enum`, `scalar`, `input`, `union` and `directive`.',
706
713
  default: false,
707
714
  },
708
- ignorePrefix: {
709
- type: 'array',
710
- default: [],
711
- },
712
- ignoreSuffix: {
713
- type: 'array',
714
- default: [],
715
- },
716
715
  },
717
716
  },
718
717
  },
@@ -751,7 +750,9 @@ const rule = {
751
750
  const [firstBeforeComment] = getBeforeComments(node);
752
751
  const [firstAfterComment] = sourceCode.getCommentsAfter(node);
753
752
  const from = firstBeforeComment || node;
754
- const to = firstAfterComment && isNodeAndCommentOnSameLine(node, firstAfterComment) ? firstAfterComment : node;
753
+ const to = firstAfterComment && isNodeAndCommentOnSameLine(node, firstAfterComment)
754
+ ? firstAfterComment
755
+ : node;
755
756
  return [from.range[0], to.range[1]];
756
757
  }
757
758
  function checkNodes(nodes) {
@@ -759,38 +760,24 @@ const rule = {
759
760
  // Starts from 1, ignore nodes.length <= 1
760
761
  for (let i = 1; i < nodes.length; i += 1) {
761
762
  const currNode = nodes[i];
762
- const currName = ('alias' in currNode && ((_a = currNode.alias) === null || _a === void 0 ? void 0 : _a.value)) || ('name' in currNode && ((_b = currNode.name) === null || _b === void 0 ? void 0 : _b.value));
763
+ const currName = ('alias' in currNode && ((_a = currNode.alias) === null || _a === void 0 ? void 0 : _a.value)) ||
764
+ ('name' in currNode && ((_b = currNode.name) === null || _b === void 0 ? void 0 : _b.value));
763
765
  if (!currName) {
764
766
  // we don't move unnamed current nodes
765
767
  continue;
766
768
  }
767
769
  const prevNode = nodes[i - 1];
768
- const prevName = ('alias' in prevNode && ((_c = prevNode.alias) === null || _c === void 0 ? void 0 : _c.value)) || ('name' in prevNode && ((_d = prevNode.name) === null || _d === void 0 ? void 0 : _d.value));
770
+ const prevName = ('alias' in prevNode && ((_c = prevNode.alias) === null || _c === void 0 ? void 0 : _c.value)) ||
771
+ ('name' in prevNode && ((_d = prevNode.name) === null || _d === void 0 ? void 0 : _d.value));
769
772
  if (prevName) {
770
- if ((opts.ignorePrefix || []).length > 0) {
771
- const shouldSkipIgnorePrefix = opts.ignorePrefix.some(prefix => prefix === prevName || prefix === currName || prevName.startsWith(prefix) || currName.startsWith(prefix));
772
- if (shouldSkipIgnorePrefix) {
773
- continue;
774
- }
775
- if (!shouldSkipIgnorePrefix) {
776
- console.error(`${opts.ignorePrefix} is not match to "${prevName}" or "${currName}"`);
777
- }
778
- }
779
- if ((opts.ignoreSuffix || []).length > 0) {
780
- const shouldSkipIgnoreSuffix = opts.ignoreSuffix.some(suffix => suffix === prevName || suffix === currName || prevName.endsWith(suffix) || currName.endsWith(suffix));
781
- if (shouldSkipIgnoreSuffix) {
782
- continue;
783
- }
784
- if (!shouldSkipIgnoreSuffix) {
785
- console.error(`${opts.ignoreSuffix} is not match to "${prevName}" or "${currName}"`);
786
- }
787
- }
788
773
  // Compare with lexicographic order
789
774
  const compareResult = prevName.localeCompare(currName);
790
775
  const shouldSort = compareResult === 1;
791
776
  if (!shouldSort) {
792
777
  const isSameName = compareResult === 0;
793
- if (!isSameName || !prevNode.kind.endsWith('Extension') || currNode.kind.endsWith('Extension')) {
778
+ if (!isSameName ||
779
+ !prevNode.kind.endsWith('Extension') ||
780
+ currNode.kind.endsWith('Extension')) {
794
781
  continue;
795
782
  }
796
783
  }
@@ -815,8 +802,14 @@ const rule = {
815
802
  const fields = new Set((_a = opts.fields) !== null && _a !== void 0 ? _a : []);
816
803
  const listeners = {};
817
804
  const kinds = [
818
- fields.has(graphql.Kind.OBJECT_TYPE_DEFINITION) && [graphql.Kind.OBJECT_TYPE_DEFINITION, graphql.Kind.OBJECT_TYPE_EXTENSION],
819
- fields.has(graphql.Kind.INTERFACE_TYPE_DEFINITION) && [graphql.Kind.INTERFACE_TYPE_DEFINITION, graphql.Kind.INTERFACE_TYPE_EXTENSION],
805
+ fields.has(graphql.Kind.OBJECT_TYPE_DEFINITION) && [
806
+ graphql.Kind.OBJECT_TYPE_DEFINITION,
807
+ graphql.Kind.OBJECT_TYPE_EXTENSION,
808
+ ],
809
+ fields.has(graphql.Kind.INTERFACE_TYPE_DEFINITION) && [
810
+ graphql.Kind.INTERFACE_TYPE_DEFINITION,
811
+ graphql.Kind.INTERFACE_TYPE_EXTENSION,
812
+ ],
820
813
  fields.has(graphql.Kind.INPUT_OBJECT_TYPE_DEFINITION) && [
821
814
  graphql.Kind.INPUT_OBJECT_TYPE_DEFINITION,
822
815
  graphql.Kind.INPUT_OBJECT_TYPE_EXTENSION,
@@ -1014,7 +1007,8 @@ const rule$2 = {
1014
1007
  checkMutations: true,
1015
1008
  ...context.options[0],
1016
1009
  };
1017
- const shouldCheckType = node => (options.checkMutations && isMutationType(node)) || (options.checkQueries && isQueryType(node));
1010
+ const shouldCheckType = node => (options.checkMutations && isMutationType(node)) ||
1011
+ (options.checkQueries && isQueryType(node));
1018
1012
  const listeners = {
1019
1013
  'FieldDefinition > InputValueDefinition[name.value!=input] > Name'(node) {
1020
1014
  if (shouldCheckType(node.parent.parent.parent)) {
@@ -1250,7 +1244,8 @@ const rule$3 = {
1250
1244
  const expectedExtension = options.fileExtension || fileExtension;
1251
1245
  let expectedFilename;
1252
1246
  if (option.style) {
1253
- expectedFilename = option.style === 'matchDocumentStyle' ? docName : convertCase(option.style, docName);
1247
+ expectedFilename =
1248
+ option.style === 'matchDocumentStyle' ? docName : convertCase(option.style, docName);
1254
1249
  }
1255
1250
  else {
1256
1251
  expectedFilename = filename;
@@ -1564,12 +1559,10 @@ const rule$4 = {
1564
1559
  };
1565
1560
  const listeners = {};
1566
1561
  if (!allowLeadingUnderscore) {
1567
- listeners['Name[value=/^_/]:matches([parent.kind!=Field], [parent.kind=Field][parent.alias])'] =
1568
- checkUnderscore(true);
1562
+ listeners['Name[value=/^_/]:matches([parent.kind!=Field], [parent.kind=Field][parent.alias])'] = checkUnderscore(true);
1569
1563
  }
1570
1564
  if (!allowTrailingUnderscore) {
1571
- listeners['Name[value=/_$/]:matches([parent.kind!=Field], [parent.kind=Field][parent.alias])'] =
1572
- checkUnderscore(false);
1565
+ listeners['Name[value=/_$/]:matches([parent.kind!=Field], [parent.kind=Field][parent.alias])'] = checkUnderscore(false);
1573
1566
  }
1574
1567
  const selectors = new Set([types && TYPES_KINDS, Object.keys(restOptions)].flat().filter(Boolean));
1575
1568
  for (const selector of selectors) {
@@ -1617,7 +1610,9 @@ const rule$5 = {
1617
1610
  return {
1618
1611
  'OperationDefinition[name=undefined]'(node) {
1619
1612
  const [firstSelection] = node.selectionSet.selections;
1620
- const suggestedName = firstSelection.kind === graphql.Kind.FIELD ? (firstSelection.alias || firstSelection.name).value : node.operation;
1613
+ const suggestedName = firstSelection.kind === graphql.Kind.FIELD
1614
+ ? (firstSelection.alias || firstSelection.name).value
1615
+ : node.operation;
1621
1616
  context.report({
1622
1617
  loc: getLocation(node.loc.start, node.operation),
1623
1618
  messageId: RULE_ID$1,
@@ -1678,7 +1673,8 @@ const rule$6 = {
1678
1673
  const selector = [graphql.Kind.ENUM_TYPE_DEFINITION, graphql.Kind.ENUM_TYPE_EXTENSION].join(',');
1679
1674
  return {
1680
1675
  [selector](node) {
1681
- const duplicates = node.values.filter((item, index, array) => array.findIndex(v => v.name.value.toLowerCase() === item.name.value.toLowerCase()) !== index);
1676
+ const duplicates = node.values.filter((item, index, array) => array.findIndex(v => v.name.value.toLowerCase() === item.name.value.toLowerCase()) !==
1677
+ index);
1682
1678
  for (const duplicate of duplicates) {
1683
1679
  const enumName = duplicate.name.value;
1684
1680
  context.report({
@@ -1988,7 +1984,10 @@ const rule$9 = {
1988
1984
  if (kind === graphql.TokenKind.COMMENT && prev && next) {
1989
1985
  const isEslintComment = value.trimStart().startsWith('eslint');
1990
1986
  const linesAfter = next.line - line;
1991
- if (!isEslintComment && line !== prev.line && next.kind === graphql.TokenKind.NAME && linesAfter < 2) {
1987
+ if (!isEslintComment &&
1988
+ line !== prev.line &&
1989
+ next.kind === graphql.TokenKind.NAME &&
1990
+ linesAfter < 2) {
1992
1991
  context.report({
1993
1992
  messageId: HASHTAG_COMMENT,
1994
1993
  loc: {
@@ -2697,7 +2696,8 @@ const rule$g = {
2697
2696
  }
2698
2697
  },
2699
2698
  ':matches(ObjectTypeDefinition, ObjectTypeExtension)[name.value=/Connection$/] > FieldDefinition[name.value=edges] > .gqlType'(node) {
2700
- const isListType = node.kind === graphql.Kind.LIST_TYPE || (node.kind === graphql.Kind.NON_NULL_TYPE && node.gqlType.kind === graphql.Kind.LIST_TYPE);
2699
+ const isListType = node.kind === graphql.Kind.LIST_TYPE ||
2700
+ (node.kind === graphql.Kind.NON_NULL_TYPE && node.gqlType.kind === graphql.Kind.LIST_TYPE);
2701
2701
  if (!isListType) {
2702
2702
  context.report({ node, messageId: EDGES_FIELD_MUST_RETURN_LIST_TYPE });
2703
2703
  }
@@ -2822,7 +2822,8 @@ const rule$h = {
2822
2822
  listTypeCanWrapOnlyEdgeType: true,
2823
2823
  ...context.options[0],
2824
2824
  };
2825
- const isNamedOrNonNullNamed = (node) => node.kind === graphql.Kind.NAMED_TYPE || (node.kind === graphql.Kind.NON_NULL_TYPE && node.gqlType.kind === graphql.Kind.NAMED_TYPE);
2825
+ const isNamedOrNonNullNamed = (node) => node.kind === graphql.Kind.NAMED_TYPE ||
2826
+ (node.kind === graphql.Kind.NON_NULL_TYPE && node.gqlType.kind === graphql.Kind.NAMED_TYPE);
2826
2827
  const checkNodeField = (node) => {
2827
2828
  const nodeField = node.fields.find(field => field.name.value === 'node');
2828
2829
  const message = 'return either a Scalar, Enum, Object, Interface, Union, or a non-null wrapper around one of those types.';
@@ -2966,7 +2967,8 @@ const rule$i = {
2966
2967
  type.gqlType.name.value === 'Boolean';
2967
2968
  }
2968
2969
  else if (type.kind === graphql.Kind.NAMED_TYPE) {
2969
- isAllowedType = type.name.value === 'String' || graphql.isScalarType(schema.getType(type.name.value));
2970
+ isAllowedType =
2971
+ type.name.value === 'String' || graphql.isScalarType(schema.getType(type.name.value));
2970
2972
  }
2971
2973
  }
2972
2974
  if (!isAllowedType) {
@@ -3183,7 +3185,8 @@ const rule$j = {
3183
3185
  title: 'Correct',
3184
3186
  code: /* GraphQL */ `
3185
3187
  type User {
3186
- firstname: String @deprecated(reason: "Use 'firstName' instead", deletionDate: "25/12/2022")
3188
+ firstname: String
3189
+ @deprecated(reason: "Use 'firstName' instead", deletionDate: "25/12/2022")
3187
3190
  firstName: String
3188
3191
  }
3189
3192
  `,
@@ -3422,7 +3425,8 @@ const rule$l = {
3422
3425
  ...Object.fromEntries([...ALLOWED_KINDS$1].sort().map(kind => {
3423
3426
  let description = `Read more about this kind on [spec.graphql.org](https://spec.graphql.org/October2021/#${kind}).`;
3424
3427
  if (kind === graphql.Kind.OPERATION_DEFINITION) {
3425
- description += '\n\n> You must use only comment syntax `#` and not description syntax `"""` or `"`.';
3428
+ description +=
3429
+ '\n\n> You must use only comment syntax `#` and not description syntax `"""` or `"`.';
3426
3430
  }
3427
3431
  return [kind, { type: 'boolean', description }];
3428
3432
  })),
@@ -3740,7 +3744,6 @@ const RULE_ID$d = 'selection-set-depth';
3740
3744
  const rule$o = {
3741
3745
  meta: {
3742
3746
  type: 'suggestion',
3743
- // eslint-disable-next-line eslint-plugin/require-meta-has-suggestions -- optional since we can't provide fixes for fragments located in separate files
3744
3747
  hasSuggestions: true,
3745
3748
  docs: {
3746
3749
  category: 'Operations',
@@ -3977,7 +3980,11 @@ const rule$p = {
3977
3980
  ...context.options[0],
3978
3981
  };
3979
3982
  const schema = requireGraphQLSchemaFromContext(RULE_ID$e, context);
3980
- const rootTypeNames = [schema.getQueryType(), schema.getMutationType(), schema.getSubscriptionType()]
3983
+ const rootTypeNames = [
3984
+ schema.getQueryType(),
3985
+ schema.getMutationType(),
3986
+ schema.getSubscriptionType(),
3987
+ ]
3981
3988
  .filter(Boolean)
3982
3989
  .map(type => type.name);
3983
3990
  const selector = `ObjectTypeDefinition[name.value!=/^(${rootTypeNames.join('|')})$/]`;
@@ -3995,7 +4002,8 @@ const rule$p = {
3995
4002
  const isValidIdName = options.acceptedIdNames.includes(fieldNode.name.value);
3996
4003
  // To be a valid type, it must be non-null and one of the accepted types.
3997
4004
  let isValidIdType = false;
3998
- if (fieldNode.type.kind === graphql.Kind.NON_NULL_TYPE && fieldNode.type.type.kind === graphql.Kind.NAMED_TYPE) {
4005
+ if (fieldNode.type.kind === graphql.Kind.NON_NULL_TYPE &&
4006
+ fieldNode.type.type.kind === graphql.Kind.NAMED_TYPE) {
3999
4007
  isValidIdType = options.acceptedIdTypes.includes(fieldNode.type.type.name.value);
4000
4008
  }
4001
4009
  return isValidIdName && isValidIdType;
@@ -4020,7 +4028,9 @@ const RULE_ID$f = 'unique-fragment-name';
4020
4028
  const checkNode = (context, node, ruleId) => {
4021
4029
  const documentName = node.name.value;
4022
4030
  const siblings = requireSiblingsOperations(ruleId, context);
4023
- const siblingDocuments = node.kind === graphql.Kind.FRAGMENT_DEFINITION ? siblings.getFragment(documentName) : siblings.getOperation(documentName);
4031
+ const siblingDocuments = node.kind === graphql.Kind.FRAGMENT_DEFINITION
4032
+ ? siblings.getFragment(documentName)
4033
+ : siblings.getOperation(documentName);
4024
4034
  const filepath = context.getFilename();
4025
4035
  const conflictingDocuments = siblingDocuments.filter(f => {
4026
4036
  var _a;
@@ -4416,7 +4426,9 @@ function parseForESLint(code, options = {}) {
4416
4426
  const filePath = options.filePath || '';
4417
4427
  const realFilepath = filePath && getOnDiskFilepath(filePath);
4418
4428
  const gqlConfig = loadGraphQLConfig(options);
4419
- const projectForFile = realFilepath ? gqlConfig.getProjectForFile(realFilepath) : gqlConfig.getDefault();
4429
+ const projectForFile = realFilepath
4430
+ ? gqlConfig.getProjectForFile(realFilepath)
4431
+ : gqlConfig.getDefault();
4420
4432
  const schema = getSchema(projectForFile, options);
4421
4433
  const siblingOperations = getSiblingOperations(projectForFile);
4422
4434
  const { document } = utils.parseGraphQLSDL(filePath, code, {
package/index.mjs CHANGED
@@ -108,7 +108,7 @@ const getOnDiskFilepath = (filepath) => {
108
108
  }
109
109
  return filepath;
110
110
  };
111
- const getTypeName = (node) => ('type' in node ? getTypeName(node.type) : node.name.value);
111
+ const getTypeName = (node) => 'type' in node ? getTypeName(node.type) : node.name.value;
112
112
  const TYPES_KINDS = [
113
113
  Kind.OBJECT_TYPE_DEFINITION,
114
114
  Kind.INTERFACE_TYPE_DEFINITION,
@@ -183,7 +183,9 @@ function validateDocument(context, schema = null, documentNode, rule) {
183
183
  if (token) {
184
184
  loc =
185
185
  // if cursor on `@` symbol than use next node
186
- token.type === '@' ? sourceCode.getNodeByRangeIndex(token.range[1] + 1).loc : token.loc;
186
+ token.type === '@'
187
+ ? sourceCode.getNodeByRangeIndex(token.range[1] + 1).loc
188
+ : token.loc;
187
189
  }
188
190
  context.report({
189
191
  loc,
@@ -273,7 +275,9 @@ const validationToRule = (ruleId, ruleName, docs, getDocumentNode, schema = [])
273
275
  }
274
276
  return {
275
277
  Document(node) {
276
- const schema = docs.requiresSchema ? requireGraphQLSchemaFromContext(ruleId, context) : null;
278
+ const schema = docs.requiresSchema
279
+ ? requireGraphQLSchemaFromContext(ruleId, context)
280
+ : null;
277
281
  const documentNode = getDocumentNode
278
282
  ? getDocumentNode({ ruleId, context, node: node.rawNode() })
279
283
  : node.rawNode();
@@ -419,7 +423,10 @@ const GRAPHQL_JS_VALIDATIONS = Object.assign({}, validationToRule('executable-de
419
423
  requiresSiblings: true,
420
424
  }, ({ ruleId, context, node }) => {
421
425
  const siblings = requireSiblingsOperations(ruleId, context);
422
- const FilePathToDocumentsMap = [...siblings.getOperations(), ...siblings.getFragments()].reduce((map, { filePath, document }) => {
426
+ const FilePathToDocumentsMap = [
427
+ ...siblings.getOperations(),
428
+ ...siblings.getFragments(),
429
+ ].reduce((map, { filePath, document }) => {
423
430
  var _a;
424
431
  (_a = map[filePath]) !== null && _a !== void 0 ? _a : (map[filePath] = []);
425
432
  map[filePath].push(document);
@@ -699,14 +706,6 @@ const rule = {
699
706
  description: 'Definitions – `type`, `interface`, `enum`, `scalar`, `input`, `union` and `directive`.',
700
707
  default: false,
701
708
  },
702
- ignorePrefix: {
703
- type: 'array',
704
- default: [],
705
- },
706
- ignoreSuffix: {
707
- type: 'array',
708
- default: [],
709
- },
710
709
  },
711
710
  },
712
711
  },
@@ -745,7 +744,9 @@ const rule = {
745
744
  const [firstBeforeComment] = getBeforeComments(node);
746
745
  const [firstAfterComment] = sourceCode.getCommentsAfter(node);
747
746
  const from = firstBeforeComment || node;
748
- const to = firstAfterComment && isNodeAndCommentOnSameLine(node, firstAfterComment) ? firstAfterComment : node;
747
+ const to = firstAfterComment && isNodeAndCommentOnSameLine(node, firstAfterComment)
748
+ ? firstAfterComment
749
+ : node;
749
750
  return [from.range[0], to.range[1]];
750
751
  }
751
752
  function checkNodes(nodes) {
@@ -753,38 +754,24 @@ const rule = {
753
754
  // Starts from 1, ignore nodes.length <= 1
754
755
  for (let i = 1; i < nodes.length; i += 1) {
755
756
  const currNode = nodes[i];
756
- const currName = ('alias' in currNode && ((_a = currNode.alias) === null || _a === void 0 ? void 0 : _a.value)) || ('name' in currNode && ((_b = currNode.name) === null || _b === void 0 ? void 0 : _b.value));
757
+ const currName = ('alias' in currNode && ((_a = currNode.alias) === null || _a === void 0 ? void 0 : _a.value)) ||
758
+ ('name' in currNode && ((_b = currNode.name) === null || _b === void 0 ? void 0 : _b.value));
757
759
  if (!currName) {
758
760
  // we don't move unnamed current nodes
759
761
  continue;
760
762
  }
761
763
  const prevNode = nodes[i - 1];
762
- const prevName = ('alias' in prevNode && ((_c = prevNode.alias) === null || _c === void 0 ? void 0 : _c.value)) || ('name' in prevNode && ((_d = prevNode.name) === null || _d === void 0 ? void 0 : _d.value));
764
+ const prevName = ('alias' in prevNode && ((_c = prevNode.alias) === null || _c === void 0 ? void 0 : _c.value)) ||
765
+ ('name' in prevNode && ((_d = prevNode.name) === null || _d === void 0 ? void 0 : _d.value));
763
766
  if (prevName) {
764
- if ((opts.ignorePrefix || []).length > 0) {
765
- const shouldSkipIgnorePrefix = opts.ignorePrefix.some(prefix => prefix === prevName || prefix === currName || prevName.startsWith(prefix) || currName.startsWith(prefix));
766
- if (shouldSkipIgnorePrefix) {
767
- continue;
768
- }
769
- if (!shouldSkipIgnorePrefix) {
770
- console.error(`${opts.ignorePrefix} is not match to "${prevName}" or "${currName}"`);
771
- }
772
- }
773
- if ((opts.ignoreSuffix || []).length > 0) {
774
- const shouldSkipIgnoreSuffix = opts.ignoreSuffix.some(suffix => suffix === prevName || suffix === currName || prevName.endsWith(suffix) || currName.endsWith(suffix));
775
- if (shouldSkipIgnoreSuffix) {
776
- continue;
777
- }
778
- if (!shouldSkipIgnoreSuffix) {
779
- console.error(`${opts.ignoreSuffix} is not match to "${prevName}" or "${currName}"`);
780
- }
781
- }
782
767
  // Compare with lexicographic order
783
768
  const compareResult = prevName.localeCompare(currName);
784
769
  const shouldSort = compareResult === 1;
785
770
  if (!shouldSort) {
786
771
  const isSameName = compareResult === 0;
787
- if (!isSameName || !prevNode.kind.endsWith('Extension') || currNode.kind.endsWith('Extension')) {
772
+ if (!isSameName ||
773
+ !prevNode.kind.endsWith('Extension') ||
774
+ currNode.kind.endsWith('Extension')) {
788
775
  continue;
789
776
  }
790
777
  }
@@ -809,8 +796,14 @@ const rule = {
809
796
  const fields = new Set((_a = opts.fields) !== null && _a !== void 0 ? _a : []);
810
797
  const listeners = {};
811
798
  const kinds = [
812
- fields.has(Kind.OBJECT_TYPE_DEFINITION) && [Kind.OBJECT_TYPE_DEFINITION, Kind.OBJECT_TYPE_EXTENSION],
813
- fields.has(Kind.INTERFACE_TYPE_DEFINITION) && [Kind.INTERFACE_TYPE_DEFINITION, Kind.INTERFACE_TYPE_EXTENSION],
799
+ fields.has(Kind.OBJECT_TYPE_DEFINITION) && [
800
+ Kind.OBJECT_TYPE_DEFINITION,
801
+ Kind.OBJECT_TYPE_EXTENSION,
802
+ ],
803
+ fields.has(Kind.INTERFACE_TYPE_DEFINITION) && [
804
+ Kind.INTERFACE_TYPE_DEFINITION,
805
+ Kind.INTERFACE_TYPE_EXTENSION,
806
+ ],
814
807
  fields.has(Kind.INPUT_OBJECT_TYPE_DEFINITION) && [
815
808
  Kind.INPUT_OBJECT_TYPE_DEFINITION,
816
809
  Kind.INPUT_OBJECT_TYPE_EXTENSION,
@@ -1008,7 +1001,8 @@ const rule$2 = {
1008
1001
  checkMutations: true,
1009
1002
  ...context.options[0],
1010
1003
  };
1011
- const shouldCheckType = node => (options.checkMutations && isMutationType(node)) || (options.checkQueries && isQueryType(node));
1004
+ const shouldCheckType = node => (options.checkMutations && isMutationType(node)) ||
1005
+ (options.checkQueries && isQueryType(node));
1012
1006
  const listeners = {
1013
1007
  'FieldDefinition > InputValueDefinition[name.value!=input] > Name'(node) {
1014
1008
  if (shouldCheckType(node.parent.parent.parent)) {
@@ -1244,7 +1238,8 @@ const rule$3 = {
1244
1238
  const expectedExtension = options.fileExtension || fileExtension;
1245
1239
  let expectedFilename;
1246
1240
  if (option.style) {
1247
- expectedFilename = option.style === 'matchDocumentStyle' ? docName : convertCase(option.style, docName);
1241
+ expectedFilename =
1242
+ option.style === 'matchDocumentStyle' ? docName : convertCase(option.style, docName);
1248
1243
  }
1249
1244
  else {
1250
1245
  expectedFilename = filename;
@@ -1558,12 +1553,10 @@ const rule$4 = {
1558
1553
  };
1559
1554
  const listeners = {};
1560
1555
  if (!allowLeadingUnderscore) {
1561
- listeners['Name[value=/^_/]:matches([parent.kind!=Field], [parent.kind=Field][parent.alias])'] =
1562
- checkUnderscore(true);
1556
+ listeners['Name[value=/^_/]:matches([parent.kind!=Field], [parent.kind=Field][parent.alias])'] = checkUnderscore(true);
1563
1557
  }
1564
1558
  if (!allowTrailingUnderscore) {
1565
- listeners['Name[value=/_$/]:matches([parent.kind!=Field], [parent.kind=Field][parent.alias])'] =
1566
- checkUnderscore(false);
1559
+ listeners['Name[value=/_$/]:matches([parent.kind!=Field], [parent.kind=Field][parent.alias])'] = checkUnderscore(false);
1567
1560
  }
1568
1561
  const selectors = new Set([types && TYPES_KINDS, Object.keys(restOptions)].flat().filter(Boolean));
1569
1562
  for (const selector of selectors) {
@@ -1611,7 +1604,9 @@ const rule$5 = {
1611
1604
  return {
1612
1605
  'OperationDefinition[name=undefined]'(node) {
1613
1606
  const [firstSelection] = node.selectionSet.selections;
1614
- const suggestedName = firstSelection.kind === Kind.FIELD ? (firstSelection.alias || firstSelection.name).value : node.operation;
1607
+ const suggestedName = firstSelection.kind === Kind.FIELD
1608
+ ? (firstSelection.alias || firstSelection.name).value
1609
+ : node.operation;
1615
1610
  context.report({
1616
1611
  loc: getLocation(node.loc.start, node.operation),
1617
1612
  messageId: RULE_ID$1,
@@ -1672,7 +1667,8 @@ const rule$6 = {
1672
1667
  const selector = [Kind.ENUM_TYPE_DEFINITION, Kind.ENUM_TYPE_EXTENSION].join(',');
1673
1668
  return {
1674
1669
  [selector](node) {
1675
- const duplicates = node.values.filter((item, index, array) => array.findIndex(v => v.name.value.toLowerCase() === item.name.value.toLowerCase()) !== index);
1670
+ const duplicates = node.values.filter((item, index, array) => array.findIndex(v => v.name.value.toLowerCase() === item.name.value.toLowerCase()) !==
1671
+ index);
1676
1672
  for (const duplicate of duplicates) {
1677
1673
  const enumName = duplicate.name.value;
1678
1674
  context.report({
@@ -1982,7 +1978,10 @@ const rule$9 = {
1982
1978
  if (kind === TokenKind.COMMENT && prev && next) {
1983
1979
  const isEslintComment = value.trimStart().startsWith('eslint');
1984
1980
  const linesAfter = next.line - line;
1985
- if (!isEslintComment && line !== prev.line && next.kind === TokenKind.NAME && linesAfter < 2) {
1981
+ if (!isEslintComment &&
1982
+ line !== prev.line &&
1983
+ next.kind === TokenKind.NAME &&
1984
+ linesAfter < 2) {
1986
1985
  context.report({
1987
1986
  messageId: HASHTAG_COMMENT,
1988
1987
  loc: {
@@ -2691,7 +2690,8 @@ const rule$g = {
2691
2690
  }
2692
2691
  },
2693
2692
  ':matches(ObjectTypeDefinition, ObjectTypeExtension)[name.value=/Connection$/] > FieldDefinition[name.value=edges] > .gqlType'(node) {
2694
- const isListType = node.kind === Kind.LIST_TYPE || (node.kind === Kind.NON_NULL_TYPE && node.gqlType.kind === Kind.LIST_TYPE);
2693
+ const isListType = node.kind === Kind.LIST_TYPE ||
2694
+ (node.kind === Kind.NON_NULL_TYPE && node.gqlType.kind === Kind.LIST_TYPE);
2695
2695
  if (!isListType) {
2696
2696
  context.report({ node, messageId: EDGES_FIELD_MUST_RETURN_LIST_TYPE });
2697
2697
  }
@@ -2816,7 +2816,8 @@ const rule$h = {
2816
2816
  listTypeCanWrapOnlyEdgeType: true,
2817
2817
  ...context.options[0],
2818
2818
  };
2819
- const isNamedOrNonNullNamed = (node) => node.kind === Kind.NAMED_TYPE || (node.kind === Kind.NON_NULL_TYPE && node.gqlType.kind === Kind.NAMED_TYPE);
2819
+ const isNamedOrNonNullNamed = (node) => node.kind === Kind.NAMED_TYPE ||
2820
+ (node.kind === Kind.NON_NULL_TYPE && node.gqlType.kind === Kind.NAMED_TYPE);
2820
2821
  const checkNodeField = (node) => {
2821
2822
  const nodeField = node.fields.find(field => field.name.value === 'node');
2822
2823
  const message = 'return either a Scalar, Enum, Object, Interface, Union, or a non-null wrapper around one of those types.';
@@ -2960,7 +2961,8 @@ const rule$i = {
2960
2961
  type.gqlType.name.value === 'Boolean';
2961
2962
  }
2962
2963
  else if (type.kind === Kind.NAMED_TYPE) {
2963
- isAllowedType = type.name.value === 'String' || isScalarType(schema.getType(type.name.value));
2964
+ isAllowedType =
2965
+ type.name.value === 'String' || isScalarType(schema.getType(type.name.value));
2964
2966
  }
2965
2967
  }
2966
2968
  if (!isAllowedType) {
@@ -3177,7 +3179,8 @@ const rule$j = {
3177
3179
  title: 'Correct',
3178
3180
  code: /* GraphQL */ `
3179
3181
  type User {
3180
- firstname: String @deprecated(reason: "Use 'firstName' instead", deletionDate: "25/12/2022")
3182
+ firstname: String
3183
+ @deprecated(reason: "Use 'firstName' instead", deletionDate: "25/12/2022")
3181
3184
  firstName: String
3182
3185
  }
3183
3186
  `,
@@ -3416,7 +3419,8 @@ const rule$l = {
3416
3419
  ...Object.fromEntries([...ALLOWED_KINDS$1].sort().map(kind => {
3417
3420
  let description = `Read more about this kind on [spec.graphql.org](https://spec.graphql.org/October2021/#${kind}).`;
3418
3421
  if (kind === Kind.OPERATION_DEFINITION) {
3419
- description += '\n\n> You must use only comment syntax `#` and not description syntax `"""` or `"`.';
3422
+ description +=
3423
+ '\n\n> You must use only comment syntax `#` and not description syntax `"""` or `"`.';
3420
3424
  }
3421
3425
  return [kind, { type: 'boolean', description }];
3422
3426
  })),
@@ -3734,7 +3738,6 @@ const RULE_ID$d = 'selection-set-depth';
3734
3738
  const rule$o = {
3735
3739
  meta: {
3736
3740
  type: 'suggestion',
3737
- // eslint-disable-next-line eslint-plugin/require-meta-has-suggestions -- optional since we can't provide fixes for fragments located in separate files
3738
3741
  hasSuggestions: true,
3739
3742
  docs: {
3740
3743
  category: 'Operations',
@@ -3971,7 +3974,11 @@ const rule$p = {
3971
3974
  ...context.options[0],
3972
3975
  };
3973
3976
  const schema = requireGraphQLSchemaFromContext(RULE_ID$e, context);
3974
- const rootTypeNames = [schema.getQueryType(), schema.getMutationType(), schema.getSubscriptionType()]
3977
+ const rootTypeNames = [
3978
+ schema.getQueryType(),
3979
+ schema.getMutationType(),
3980
+ schema.getSubscriptionType(),
3981
+ ]
3975
3982
  .filter(Boolean)
3976
3983
  .map(type => type.name);
3977
3984
  const selector = `ObjectTypeDefinition[name.value!=/^(${rootTypeNames.join('|')})$/]`;
@@ -3989,7 +3996,8 @@ const rule$p = {
3989
3996
  const isValidIdName = options.acceptedIdNames.includes(fieldNode.name.value);
3990
3997
  // To be a valid type, it must be non-null and one of the accepted types.
3991
3998
  let isValidIdType = false;
3992
- if (fieldNode.type.kind === Kind.NON_NULL_TYPE && fieldNode.type.type.kind === Kind.NAMED_TYPE) {
3999
+ if (fieldNode.type.kind === Kind.NON_NULL_TYPE &&
4000
+ fieldNode.type.type.kind === Kind.NAMED_TYPE) {
3993
4001
  isValidIdType = options.acceptedIdTypes.includes(fieldNode.type.type.name.value);
3994
4002
  }
3995
4003
  return isValidIdName && isValidIdType;
@@ -4014,7 +4022,9 @@ const RULE_ID$f = 'unique-fragment-name';
4014
4022
  const checkNode = (context, node, ruleId) => {
4015
4023
  const documentName = node.name.value;
4016
4024
  const siblings = requireSiblingsOperations(ruleId, context);
4017
- const siblingDocuments = node.kind === Kind.FRAGMENT_DEFINITION ? siblings.getFragment(documentName) : siblings.getOperation(documentName);
4025
+ const siblingDocuments = node.kind === Kind.FRAGMENT_DEFINITION
4026
+ ? siblings.getFragment(documentName)
4027
+ : siblings.getOperation(documentName);
4018
4028
  const filepath = context.getFilename();
4019
4029
  const conflictingDocuments = siblingDocuments.filter(f => {
4020
4030
  var _a;
@@ -4410,7 +4420,9 @@ function parseForESLint(code, options = {}) {
4410
4420
  const filePath = options.filePath || '';
4411
4421
  const realFilepath = filePath && getOnDiskFilepath(filePath);
4412
4422
  const gqlConfig = loadGraphQLConfig(options);
4413
- const projectForFile = realFilepath ? gqlConfig.getProjectForFile(realFilepath) : gqlConfig.getDefault();
4423
+ const projectForFile = realFilepath
4424
+ ? gqlConfig.getProjectForFile(realFilepath)
4425
+ : gqlConfig.getDefault();
4414
4426
  const schema = getSchema(projectForFile, options);
4415
4427
  const siblingOperations = getSiblingOperations(projectForFile);
4416
4428
  const { document } = parseGraphQLSDL(filePath, code, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@graphql-eslint/eslint-plugin",
3
- "version": "3.11.0-alpha-20220828135426-e9545b1",
3
+ "version": "3.11.0-alpha-20220923192439-db921ff",
4
4
  "description": "GraphQL plugin for ESLint",
5
5
  "sideEffects": false,
6
6
  "peerDependencies": {
@@ -11,8 +11,6 @@ export declare type AlphabetizeConfig = {
11
11
  variables?: typeof variablesEnum;
12
12
  arguments?: typeof argumentsEnum;
13
13
  definitions?: boolean;
14
- ignorePrefix?: string[];
15
- ignoreSuffix?: string[];
16
14
  };
17
15
  declare const rule: GraphQLESLintRule<[AlphabetizeConfig]>;
18
16
  export default rule;
package/types.d.ts CHANGED
@@ -47,26 +47,29 @@ export declare type GraphQLESLintRuleContext<Options = any[]> = Omit<Rule.RuleCo
47
47
  };
48
48
  export declare type CategoryType = 'Schema' | 'Operations';
49
49
  export declare type RuleDocsInfo<T> = {
50
- docs: Omit<Rule.RuleMetaData['docs'], 'category'> & {
51
- category: CategoryType | CategoryType[];
52
- requiresSchema?: true;
53
- requiresSiblings?: true;
54
- examples?: {
55
- title: string;
56
- code: string;
57
- usage?: T;
58
- }[];
59
- configOptions?: T | {
60
- schema?: T;
61
- operations?: T;
62
- };
63
- graphQLJSRuleName?: string;
64
- isDisabledForAllConfig?: true;
50
+ description: string;
51
+ category: CategoryType | CategoryType[];
52
+ recommended?: boolean;
53
+ url: string;
54
+ requiresSchema?: true;
55
+ requiresSiblings?: true;
56
+ examples?: {
57
+ title: string;
58
+ code: string;
59
+ usage?: T;
60
+ }[];
61
+ configOptions?: T | {
62
+ schema?: T;
63
+ operations?: T;
65
64
  };
65
+ graphQLJSRuleName?: string;
66
+ isDisabledForAllConfig?: true;
66
67
  };
67
68
  export declare type GraphQLESLintRule<Options = any[], WithTypeInfo extends boolean = false> = {
68
69
  create(context: GraphQLESLintRuleContext<Options>): GraphQLESLintRuleListener<WithTypeInfo>;
69
- meta: Omit<Rule.RuleMetaData, 'docs'> & RuleDocsInfo<Options>;
70
+ meta: Omit<Rule.RuleMetaData, 'docs'> & {
71
+ docs: RuleDocsInfo<Options>;
72
+ };
70
73
  };
71
74
  export declare type ValueOf<T> = T[keyof T];
72
75
  declare type Id<T> = {} & {