@graphql-eslint/eslint-plugin 3.13.1 → 3.14.0-alpha-20221220000306-eefc8db

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.
Files changed (88) hide show
  1. package/documents.d.ts +3 -3
  2. package/estree-converter/types.d.ts +8 -8
  3. package/estree-converter/utils.d.ts +1 -1
  4. package/index.js +215 -91
  5. package/index.mjs +215 -91
  6. package/package.json +1 -1
  7. package/processor.d.ts +1 -1
  8. package/rules/alphabetize.d.ts +1 -1
  9. package/rules/description-style.d.ts +1 -1
  10. package/rules/graphql-js-validation.d.ts +1 -1
  11. package/rules/input-name.d.ts +1 -1
  12. package/rules/match-document-filename.d.ts +3 -3
  13. package/rules/naming-convention.d.ts +5 -5
  14. package/rules/no-root-type.d.ts +1 -1
  15. package/rules/relay-arguments.d.ts +1 -1
  16. package/rules/relay-edge-types.d.ts +1 -1
  17. package/rules/require-description.d.ts +2 -2
  18. package/rules/require-id-when-available.d.ts +1 -1
  19. package/rules/selection-set-depth.d.ts +1 -1
  20. package/rules/strict-id-in-types.d.ts +1 -1
  21. package/testkit.d.ts +3 -3
  22. package/types.d.ts +15 -15
  23. package/utils.d.ts +1 -1
  24. package/README.md +0 -266
  25. package/docs/README.md +0 -76
  26. package/docs/custom-rules.md +0 -148
  27. package/docs/deprecated-rules.md +0 -21
  28. package/docs/parser-options.md +0 -85
  29. package/docs/parser.md +0 -49
  30. package/docs/rules/alphabetize.md +0 -178
  31. package/docs/rules/description-style.md +0 -54
  32. package/docs/rules/executable-definitions.md +0 -17
  33. package/docs/rules/fields-on-correct-type.md +0 -17
  34. package/docs/rules/fragments-on-composite-type.md +0 -17
  35. package/docs/rules/input-name.md +0 -76
  36. package/docs/rules/known-argument-names.md +0 -17
  37. package/docs/rules/known-directives.md +0 -44
  38. package/docs/rules/known-fragment-names.md +0 -69
  39. package/docs/rules/known-type-names.md +0 -17
  40. package/docs/rules/lone-anonymous-operation.md +0 -17
  41. package/docs/rules/lone-schema-definition.md +0 -17
  42. package/docs/rules/match-document-filename.md +0 -156
  43. package/docs/rules/naming-convention.md +0 -300
  44. package/docs/rules/no-anonymous-operations.md +0 -39
  45. package/docs/rules/no-case-insensitive-enum-values-duplicates.md +0 -43
  46. package/docs/rules/no-deprecated.md +0 -85
  47. package/docs/rules/no-duplicate-fields.md +0 -65
  48. package/docs/rules/no-fragment-cycles.md +0 -17
  49. package/docs/rules/no-hashtag-description.md +0 -59
  50. package/docs/rules/no-root-type.md +0 -53
  51. package/docs/rules/no-scalar-result-type-on-mutation.md +0 -37
  52. package/docs/rules/no-typename-prefix.md +0 -39
  53. package/docs/rules/no-undefined-variables.md +0 -17
  54. package/docs/rules/no-unreachable-types.md +0 -49
  55. package/docs/rules/no-unused-fields.md +0 -62
  56. package/docs/rules/no-unused-fragments.md +0 -17
  57. package/docs/rules/no-unused-variables.md +0 -17
  58. package/docs/rules/one-field-subscriptions.md +0 -17
  59. package/docs/rules/overlapping-fields-can-be-merged.md +0 -17
  60. package/docs/rules/possible-fragment-spread.md +0 -17
  61. package/docs/rules/possible-type-extension.md +0 -15
  62. package/docs/rules/provided-required-arguments.md +0 -17
  63. package/docs/rules/relay-arguments.md +0 -57
  64. package/docs/rules/relay-connection-types.md +0 -42
  65. package/docs/rules/relay-edge-types.md +0 -56
  66. package/docs/rules/relay-page-info.md +0 -32
  67. package/docs/rules/require-deprecation-date.md +0 -57
  68. package/docs/rules/require-deprecation-reason.md +0 -47
  69. package/docs/rules/require-description.md +0 -115
  70. package/docs/rules/require-field-of-type-query-in-mutation-result.md +0 -47
  71. package/docs/rules/require-id-when-available.md +0 -88
  72. package/docs/rules/scalar-leafs.md +0 -17
  73. package/docs/rules/selection-set-depth.md +0 -76
  74. package/docs/rules/strict-id-in-types.md +0 -130
  75. package/docs/rules/unique-argument-names.md +0 -17
  76. package/docs/rules/unique-directive-names-per-location.md +0 -17
  77. package/docs/rules/unique-directive-names.md +0 -17
  78. package/docs/rules/unique-enum-value-names.md +0 -15
  79. package/docs/rules/unique-field-definition-names.md +0 -17
  80. package/docs/rules/unique-fragment-name.md +0 -51
  81. package/docs/rules/unique-input-field-names.md +0 -17
  82. package/docs/rules/unique-operation-name.md +0 -55
  83. package/docs/rules/unique-operation-types.md +0 -17
  84. package/docs/rules/unique-type-names.md +0 -17
  85. package/docs/rules/unique-variable-names.md +0 -17
  86. package/docs/rules/value-literals-of-correct-type.md +0 -17
  87. package/docs/rules/variables-are-input-types.md +0 -17
  88. package/docs/rules/variables-in-allowed-position.md +0 -17
package/index.mjs CHANGED
@@ -215,7 +215,8 @@ const ARRAY_DEFAULT_OPTIONS = {
215
215
  };
216
216
  const englishJoinWords = words => new Intl.ListFormat('en-US', { type: 'disjunction' }).format(words);
217
217
 
218
- function validateDocument(context, schema = null, documentNode, rule) {
218
+ function validateDocument({ context, schema = null, documentNode, rule, hasDidYouMeanSuggestions, }) {
219
+ var _a;
219
220
  if (documentNode.definitions.length === 0) {
220
221
  return;
221
222
  }
@@ -239,9 +240,20 @@ function validateDocument(context, schema = null, documentNode, rule) {
239
240
  ? sourceCode.getNodeByRangeIndex(token.range[1] + 1).loc
240
241
  : token.loc;
241
242
  }
243
+ const didYouMeanContent = (_a = error.message.match(/Did you mean (?<content>.*)\?$/)) === null || _a === void 0 ? void 0 : _a.groups.content;
244
+ const matches = didYouMeanContent ? [...didYouMeanContent.matchAll(/"(?<name>[^"]*)"/g)] : [];
242
245
  context.report({
243
246
  loc,
244
247
  message: error.message,
248
+ suggest: hasDidYouMeanSuggestions
249
+ ? matches.map(match => {
250
+ const { name } = match.groups;
251
+ return {
252
+ desc: `Rename to \`${name}\``,
253
+ fix: fixer => fixer.replaceText(token, name),
254
+ };
255
+ })
256
+ : [],
245
257
  });
246
258
  }
247
259
  }
@@ -295,7 +307,7 @@ const handleMissingFragments = ({ ruleId, context, node }) => {
295
307
  }
296
308
  return node;
297
309
  };
298
- const validationToRule = (ruleId, ruleName, docs, getDocumentNode, schema = []) => {
310
+ const validationToRule = ({ ruleId, ruleName, getDocumentNode, schema = [], hasDidYouMeanSuggestions, }, docs) => {
299
311
  let ruleFn = null;
300
312
  try {
301
313
  ruleFn = require(`graphql/validation/rules/${ruleName}Rule`)[`${ruleName}Rule`];
@@ -319,6 +331,7 @@ const validationToRule = (ruleId, ruleName, docs, getDocumentNode, schema = [])
319
331
  description: `${docs.description}\n\n> This rule is a wrapper around a \`graphql-js\` validation function.`,
320
332
  },
321
333
  schema,
334
+ hasSuggestions: hasDidYouMeanSuggestions,
322
335
  },
323
336
  create(context) {
324
337
  if (!ruleFn) {
@@ -333,30 +346,79 @@ const validationToRule = (ruleId, ruleName, docs, getDocumentNode, schema = [])
333
346
  const documentNode = getDocumentNode
334
347
  ? getDocumentNode({ ruleId, context, node: node.rawNode() })
335
348
  : node.rawNode();
336
- validateDocument(context, schema, documentNode, ruleFn);
349
+ validateDocument({
350
+ context,
351
+ schema,
352
+ documentNode,
353
+ rule: ruleFn,
354
+ hasDidYouMeanSuggestions,
355
+ });
337
356
  },
338
357
  };
339
358
  },
340
359
  },
341
360
  };
342
361
  };
343
- const GRAPHQL_JS_VALIDATIONS = Object.assign({}, validationToRule('executable-definitions', 'ExecutableDefinitions', {
362
+ const GRAPHQL_JS_VALIDATIONS = Object.assign({}, validationToRule({
363
+ ruleId: 'executable-definitions',
364
+ ruleName: 'ExecutableDefinitions',
365
+ }, {
344
366
  category: 'Operations',
345
367
  description: 'A GraphQL document is only valid for execution if all definitions are either operation or fragment definitions.',
346
368
  requiresSchema: true,
347
- }), validationToRule('fields-on-correct-type', 'FieldsOnCorrectType', {
369
+ }), validationToRule({
370
+ ruleId: 'fields-on-correct-type',
371
+ ruleName: 'FieldsOnCorrectType',
372
+ hasDidYouMeanSuggestions: true,
373
+ }, {
348
374
  category: 'Operations',
349
375
  description: 'A GraphQL document is only valid if all fields selected are defined by the parent type, or are an allowed meta field such as `__typename`.',
350
376
  requiresSchema: true,
351
- }), validationToRule('fragments-on-composite-type', 'FragmentsOnCompositeTypes', {
377
+ }), validationToRule({
378
+ ruleId: 'fragments-on-composite-type',
379
+ ruleName: 'FragmentsOnCompositeTypes',
380
+ }, {
352
381
  category: 'Operations',
353
382
  description: 'Fragments use a type condition to determine if they apply, since fragments can only be spread into a composite type (object, interface, or union), the type condition must also be a composite type.',
354
383
  requiresSchema: true,
355
- }), validationToRule('known-argument-names', 'KnownArgumentNames', {
384
+ }), validationToRule({
385
+ ruleId: 'known-argument-names',
386
+ ruleName: 'KnownArgumentNames',
387
+ hasDidYouMeanSuggestions: true,
388
+ }, {
356
389
  category: ['Schema', 'Operations'],
357
390
  description: 'A GraphQL field is only valid if all supplied arguments are defined by that field.',
358
391
  requiresSchema: true,
359
- }), validationToRule('known-directives', 'KnownDirectives', {
392
+ }), validationToRule({
393
+ ruleId: 'known-directives',
394
+ ruleName: 'KnownDirectives',
395
+ getDocumentNode({ context, node: documentNode }) {
396
+ const { ignoreClientDirectives = [] } = context.options[0] || {};
397
+ if (ignoreClientDirectives.length === 0) {
398
+ return documentNode;
399
+ }
400
+ const filterDirectives = (node) => ({
401
+ ...node,
402
+ directives: node.directives.filter(directive => !ignoreClientDirectives.includes(directive.name.value)),
403
+ });
404
+ return visit(documentNode, {
405
+ Field: filterDirectives,
406
+ OperationDefinition: filterDirectives,
407
+ });
408
+ },
409
+ schema: {
410
+ type: 'array',
411
+ maxItems: 1,
412
+ items: {
413
+ type: 'object',
414
+ additionalProperties: false,
415
+ required: ['ignoreClientDirectives'],
416
+ properties: {
417
+ ignoreClientDirectives: ARRAY_DEFAULT_OPTIONS,
418
+ },
419
+ },
420
+ },
421
+ }, {
360
422
  category: ['Schema', 'Operations'],
361
423
  description: 'A GraphQL document is only valid if all `@directive`s are known by the schema and legally positioned.',
362
424
  requiresSchema: true,
@@ -373,31 +435,11 @@ const GRAPHQL_JS_VALIDATIONS = Object.assign({}, validationToRule('executable-de
373
435
  `,
374
436
  },
375
437
  ],
376
- }, ({ context, node: documentNode }) => {
377
- const { ignoreClientDirectives = [] } = context.options[0] || {};
378
- if (ignoreClientDirectives.length === 0) {
379
- return documentNode;
380
- }
381
- const filterDirectives = (node) => ({
382
- ...node,
383
- directives: node.directives.filter(directive => !ignoreClientDirectives.includes(directive.name.value)),
384
- });
385
- return visit(documentNode, {
386
- Field: filterDirectives,
387
- OperationDefinition: filterDirectives,
388
- });
438
+ }), validationToRule({
439
+ ruleId: 'known-fragment-names',
440
+ ruleName: 'KnownFragmentNames',
441
+ getDocumentNode: handleMissingFragments,
389
442
  }, {
390
- type: 'array',
391
- maxItems: 1,
392
- items: {
393
- type: 'object',
394
- additionalProperties: false,
395
- required: ['ignoreClientDirectives'],
396
- properties: {
397
- ignoreClientDirectives: ARRAY_DEFAULT_OPTIONS,
398
- },
399
- },
400
- }), validationToRule('known-fragment-names', 'KnownFragmentNames', {
401
443
  category: 'Operations',
402
444
  description: 'A GraphQL document is only valid if all `...Fragment` fragment spreads refer to fragments defined in the same document.',
403
445
  requiresSchema: true,
@@ -448,138 +490,220 @@ const GRAPHQL_JS_VALIDATIONS = Object.assign({}, validationToRule('executable-de
448
490
  `,
449
491
  },
450
492
  ],
451
- }, handleMissingFragments), validationToRule('known-type-names', 'KnownTypeNames', {
493
+ }), validationToRule({
494
+ ruleId: 'known-type-names',
495
+ ruleName: 'KnownTypeNames',
496
+ hasDidYouMeanSuggestions: true,
497
+ }, {
452
498
  category: ['Schema', 'Operations'],
453
499
  description: 'A GraphQL document is only valid if referenced types (specifically variable definitions and fragment conditions) are defined by the type schema.',
454
500
  requiresSchema: true,
455
- }), validationToRule('lone-anonymous-operation', 'LoneAnonymousOperation', {
501
+ }), validationToRule({
502
+ ruleId: 'lone-anonymous-operation',
503
+ ruleName: 'LoneAnonymousOperation',
504
+ }, {
456
505
  category: 'Operations',
457
506
  description: 'A GraphQL document is only valid if when it contains an anonymous operation (the query short-hand) that it contains only that one operation definition.',
458
507
  requiresSchema: true,
459
- }), validationToRule('lone-schema-definition', 'LoneSchemaDefinition', {
508
+ }), validationToRule({
509
+ ruleId: 'lone-schema-definition',
510
+ ruleName: 'LoneSchemaDefinition',
511
+ }, {
460
512
  category: 'Schema',
461
513
  description: 'A GraphQL document is only valid if it contains only one schema definition.',
462
- }), validationToRule('no-fragment-cycles', 'NoFragmentCycles', {
514
+ }), validationToRule({
515
+ ruleId: 'no-fragment-cycles',
516
+ ruleName: 'NoFragmentCycles',
517
+ }, {
463
518
  category: 'Operations',
464
519
  description: 'A GraphQL fragment is only valid when it does not have cycles in fragments usage.',
465
520
  requiresSchema: true,
466
- }), validationToRule('no-undefined-variables', 'NoUndefinedVariables', {
521
+ }), validationToRule({
522
+ ruleId: 'no-undefined-variables',
523
+ ruleName: 'NoUndefinedVariables',
524
+ getDocumentNode: handleMissingFragments,
525
+ }, {
467
526
  category: 'Operations',
468
527
  description: 'A GraphQL operation is only valid if all variables encountered, both directly and via fragment spreads, are defined by that operation.',
469
528
  requiresSchema: true,
470
529
  requiresSiblings: true,
471
- }, handleMissingFragments), validationToRule('no-unused-fragments', 'NoUnusedFragments', {
530
+ }), validationToRule({
531
+ ruleId: 'no-unused-fragments',
532
+ ruleName: 'NoUnusedFragments',
533
+ getDocumentNode: ({ ruleId, context, node }) => {
534
+ const siblings = requireSiblingsOperations(ruleId, context);
535
+ const FilePathToDocumentsMap = [
536
+ ...siblings.getOperations(),
537
+ ...siblings.getFragments(),
538
+ ].reduce((map, { filePath, document }) => {
539
+ var _a;
540
+ (_a = map[filePath]) !== null && _a !== void 0 ? _a : (map[filePath] = []);
541
+ map[filePath].push(document);
542
+ return map;
543
+ }, Object.create(null));
544
+ const getParentNode = (currentFilePath, node) => {
545
+ const { fragmentDefs } = getFragmentDefsAndFragmentSpreads(node);
546
+ if (fragmentDefs.size === 0) {
547
+ return node;
548
+ }
549
+ // skip iteration over documents for current filepath
550
+ delete FilePathToDocumentsMap[currentFilePath];
551
+ for (const [filePath, documents] of Object.entries(FilePathToDocumentsMap)) {
552
+ const missingFragments = getMissingFragments({
553
+ kind: Kind.DOCUMENT,
554
+ definitions: documents,
555
+ });
556
+ const isCurrentFileImportFragment = missingFragments.some(fragment => fragmentDefs.has(fragment));
557
+ if (isCurrentFileImportFragment) {
558
+ return getParentNode(filePath, {
559
+ kind: Kind.DOCUMENT,
560
+ definitions: [...node.definitions, ...documents],
561
+ });
562
+ }
563
+ }
564
+ return node;
565
+ };
566
+ return getParentNode(context.getFilename(), node);
567
+ },
568
+ }, {
472
569
  category: 'Operations',
473
570
  description: 'A GraphQL document is only valid if all fragment definitions are spread within operations, or spread within other fragments spread within operations.',
474
571
  requiresSchema: true,
475
572
  requiresSiblings: true,
476
- }, ({ ruleId, context, node }) => {
477
- const siblings = requireSiblingsOperations(ruleId, context);
478
- const FilePathToDocumentsMap = [
479
- ...siblings.getOperations(),
480
- ...siblings.getFragments(),
481
- ].reduce((map, { filePath, document }) => {
482
- var _a;
483
- (_a = map[filePath]) !== null && _a !== void 0 ? _a : (map[filePath] = []);
484
- map[filePath].push(document);
485
- return map;
486
- }, Object.create(null));
487
- const getParentNode = (currentFilePath, node) => {
488
- const { fragmentDefs } = getFragmentDefsAndFragmentSpreads(node);
489
- if (fragmentDefs.size === 0) {
490
- return node;
491
- }
492
- // skip iteration over documents for current filepath
493
- delete FilePathToDocumentsMap[currentFilePath];
494
- for (const [filePath, documents] of Object.entries(FilePathToDocumentsMap)) {
495
- const missingFragments = getMissingFragments({
496
- kind: Kind.DOCUMENT,
497
- definitions: documents,
498
- });
499
- const isCurrentFileImportFragment = missingFragments.some(fragment => fragmentDefs.has(fragment));
500
- if (isCurrentFileImportFragment) {
501
- return getParentNode(filePath, {
502
- kind: Kind.DOCUMENT,
503
- definitions: [...node.definitions, ...documents],
504
- });
505
- }
506
- }
507
- return node;
508
- };
509
- return getParentNode(context.getFilename(), node);
510
- }), validationToRule('no-unused-variables', 'NoUnusedVariables', {
573
+ }), validationToRule({
574
+ ruleId: 'no-unused-variables',
575
+ ruleName: 'NoUnusedVariables',
576
+ getDocumentNode: handleMissingFragments,
577
+ }, {
511
578
  category: 'Operations',
512
579
  description: 'A GraphQL operation is only valid if all variables defined by an operation are used, either directly or within a spread fragment.',
513
580
  requiresSchema: true,
514
581
  requiresSiblings: true,
515
- }, handleMissingFragments), validationToRule('overlapping-fields-can-be-merged', 'OverlappingFieldsCanBeMerged', {
582
+ }), validationToRule({
583
+ ruleId: 'overlapping-fields-can-be-merged',
584
+ ruleName: 'OverlappingFieldsCanBeMerged',
585
+ }, {
516
586
  category: 'Operations',
517
587
  description: 'A selection set is only valid if all fields (including spreading any fragments) either correspond to distinct response names or can be merged without ambiguity.',
518
588
  requiresSchema: true,
519
- }), validationToRule('possible-fragment-spread', 'PossibleFragmentSpreads', {
589
+ }), validationToRule({
590
+ ruleId: 'possible-fragment-spread',
591
+ ruleName: 'PossibleFragmentSpreads',
592
+ }, {
520
593
  category: 'Operations',
521
594
  description: 'A fragment spread is only valid if the type condition could ever possibly be true: if there is a non-empty intersection of the possible parent types, and possible types which pass the type condition.',
522
595
  requiresSchema: true,
523
- }), validationToRule('possible-type-extension', 'PossibleTypeExtensions', {
596
+ }), validationToRule({
597
+ ruleId: 'possible-type-extension',
598
+ ruleName: 'PossibleTypeExtensions',
599
+ hasDidYouMeanSuggestions: true,
600
+ }, {
524
601
  category: 'Schema',
525
602
  description: 'A type extension is only valid if the type is defined and has the same kind.',
526
603
  // TODO: add in graphql-eslint v4
527
604
  recommended: false,
528
605
  requiresSchema: true,
529
606
  isDisabledForAllConfig: true,
530
- }), validationToRule('provided-required-arguments', 'ProvidedRequiredArguments', {
607
+ }), validationToRule({
608
+ ruleId: 'provided-required-arguments',
609
+ ruleName: 'ProvidedRequiredArguments',
610
+ }, {
531
611
  category: ['Schema', 'Operations'],
532
612
  description: 'A field or directive is only valid if all required (non-null without a default value) field arguments have been provided.',
533
613
  requiresSchema: true,
534
- }), validationToRule('scalar-leafs', 'ScalarLeafs', {
614
+ }), validationToRule({
615
+ ruleId: 'scalar-leafs',
616
+ ruleName: 'ScalarLeafs',
617
+ hasDidYouMeanSuggestions: true,
618
+ }, {
535
619
  category: 'Operations',
536
620
  description: 'A GraphQL document is valid only if all leaf fields (fields without sub selections) are of scalar or enum types.',
537
621
  requiresSchema: true,
538
- }), validationToRule('one-field-subscriptions', 'SingleFieldSubscriptions', {
622
+ }), validationToRule({
623
+ ruleId: 'one-field-subscriptions',
624
+ ruleName: 'SingleFieldSubscriptions',
625
+ }, {
539
626
  category: 'Operations',
540
627
  description: 'A GraphQL subscription is valid only if it contains a single root field.',
541
628
  requiresSchema: true,
542
- }), validationToRule('unique-argument-names', 'UniqueArgumentNames', {
629
+ }), validationToRule({
630
+ ruleId: 'unique-argument-names',
631
+ ruleName: 'UniqueArgumentNames',
632
+ }, {
543
633
  category: 'Operations',
544
634
  description: 'A GraphQL field or directive is only valid if all supplied arguments are uniquely named.',
545
635
  requiresSchema: true,
546
- }), validationToRule('unique-directive-names', 'UniqueDirectiveNames', {
636
+ }), validationToRule({
637
+ ruleId: 'unique-directive-names',
638
+ ruleName: 'UniqueDirectiveNames',
639
+ }, {
547
640
  category: 'Schema',
548
641
  description: 'A GraphQL document is only valid if all defined directives have unique names.',
549
- }), validationToRule('unique-directive-names-per-location', 'UniqueDirectivesPerLocation', {
642
+ }), validationToRule({
643
+ ruleId: 'unique-directive-names-per-location',
644
+ ruleName: 'UniqueDirectivesPerLocation',
645
+ }, {
550
646
  category: ['Schema', 'Operations'],
551
647
  description: 'A GraphQL document is only valid if all non-repeatable directives at a given location are uniquely named.',
552
648
  requiresSchema: true,
553
- }), validationToRule('unique-enum-value-names', 'UniqueEnumValueNames', {
649
+ }), validationToRule({
650
+ ruleId: 'unique-enum-value-names',
651
+ ruleName: 'UniqueEnumValueNames',
652
+ }, {
554
653
  category: 'Schema',
555
654
  description: 'A GraphQL enum type is only valid if all its values are uniquely named.',
556
655
  recommended: false,
557
656
  isDisabledForAllConfig: true,
558
- }), validationToRule('unique-field-definition-names', 'UniqueFieldDefinitionNames', {
657
+ }), validationToRule({
658
+ ruleId: 'unique-field-definition-names',
659
+ ruleName: 'UniqueFieldDefinitionNames',
660
+ }, {
559
661
  category: 'Schema',
560
662
  description: 'A GraphQL complex type is only valid if all its fields are uniquely named.',
561
- }), validationToRule('unique-input-field-names', 'UniqueInputFieldNames', {
663
+ }), validationToRule({
664
+ ruleId: 'unique-input-field-names',
665
+ ruleName: 'UniqueInputFieldNames',
666
+ }, {
562
667
  category: 'Operations',
563
668
  description: 'A GraphQL input object value is only valid if all supplied fields are uniquely named.',
564
- }), validationToRule('unique-operation-types', 'UniqueOperationTypes', {
669
+ }), validationToRule({
670
+ ruleId: 'unique-operation-types',
671
+ ruleName: 'UniqueOperationTypes',
672
+ }, {
565
673
  category: 'Schema',
566
674
  description: 'A GraphQL document is only valid if it has only one type per operation.',
567
- }), validationToRule('unique-type-names', 'UniqueTypeNames', {
675
+ }), validationToRule({
676
+ ruleId: 'unique-type-names',
677
+ ruleName: 'UniqueTypeNames',
678
+ }, {
568
679
  category: 'Schema',
569
680
  description: 'A GraphQL document is only valid if all defined types have unique names.',
570
- }), validationToRule('unique-variable-names', 'UniqueVariableNames', {
681
+ }), validationToRule({
682
+ ruleId: 'unique-variable-names',
683
+ ruleName: 'UniqueVariableNames',
684
+ }, {
571
685
  category: 'Operations',
572
686
  description: 'A GraphQL operation is only valid if all its variables are uniquely named.',
573
687
  requiresSchema: true,
574
- }), validationToRule('value-literals-of-correct-type', 'ValuesOfCorrectType', {
688
+ }), validationToRule({
689
+ ruleId: 'value-literals-of-correct-type',
690
+ ruleName: 'ValuesOfCorrectType',
691
+ hasDidYouMeanSuggestions: true,
692
+ }, {
575
693
  category: 'Operations',
576
694
  description: 'A GraphQL document is only valid if all value literals are of the type expected at their position.',
577
695
  requiresSchema: true,
578
- }), validationToRule('variables-are-input-types', 'VariablesAreInputTypes', {
696
+ }), validationToRule({
697
+ ruleId: 'variables-are-input-types',
698
+ ruleName: 'VariablesAreInputTypes',
699
+ }, {
579
700
  category: 'Operations',
580
701
  description: 'A GraphQL operation is only valid if all the variables it defines are of input types (scalar, enum, or input object).',
581
702
  requiresSchema: true,
582
- }), validationToRule('variables-in-allowed-position', 'VariablesInAllowedPosition', {
703
+ }), validationToRule({
704
+ ruleId: 'variables-in-allowed-position',
705
+ ruleName: 'VariablesInAllowedPosition',
706
+ }, {
583
707
  category: 'Operations',
584
708
  description: 'Variables passed to field arguments conform to type.',
585
709
  requiresSchema: true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@graphql-eslint/eslint-plugin",
3
- "version": "3.13.1",
3
+ "version": "3.14.0-alpha-20221220000306-eefc8db",
4
4
  "description": "GraphQL plugin for ESLint",
5
5
  "sideEffects": false,
6
6
  "peerDependencies": {
package/processor.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Linter } from 'eslint';
2
- export declare type Block = Linter.ProcessorFile & {
2
+ export type Block = Linter.ProcessorFile & {
3
3
  lineOffset: number;
4
4
  offset: number;
5
5
  };
@@ -4,7 +4,7 @@ declare const valuesEnum: ['EnumTypeDefinition'];
4
4
  declare const selectionsEnum: ('OperationDefinition' | 'FragmentDefinition')[];
5
5
  declare const variablesEnum: ['OperationDefinition'];
6
6
  declare const argumentsEnum: ('FieldDefinition' | 'Field' | 'DirectiveDefinition' | 'Directive')[];
7
- export declare type AlphabetizeConfig = {
7
+ export type AlphabetizeConfig = {
8
8
  fields?: typeof fieldsEnum;
9
9
  values?: typeof valuesEnum;
10
10
  selections?: typeof selectionsEnum;
@@ -1,5 +1,5 @@
1
1
  import { GraphQLESLintRule } from '../types';
2
- declare type DescriptionStyleRuleConfig = {
2
+ type DescriptionStyleRuleConfig = {
3
3
  style: 'inline' | 'block';
4
4
  };
5
5
  declare const rule: GraphQLESLintRule<[DescriptionStyleRuleConfig]>;
@@ -1,2 +1,2 @@
1
- import type { GraphQLESLintRule } from '../types';
1
+ import { GraphQLESLintRule } from '../types';
2
2
  export declare const GRAPHQL_JS_VALIDATIONS: Record<string, GraphQLESLintRule>;
@@ -1,5 +1,5 @@
1
1
  import { GraphQLESLintRule } from '../types';
2
- declare type InputNameRuleConfig = {
2
+ type InputNameRuleConfig = {
3
3
  checkInputType?: boolean;
4
4
  caseSensitiveInputType?: boolean;
5
5
  checkQueries?: boolean;
@@ -1,12 +1,12 @@
1
1
  import { CaseStyle as _CaseStyle } from '../utils';
2
2
  import { GraphQLESLintRule } from '../types';
3
- declare type CaseStyle = _CaseStyle | 'matchDocumentStyle';
3
+ type CaseStyle = _CaseStyle | 'matchDocumentStyle';
4
4
  declare const ACCEPTED_EXTENSIONS: ['.gql', '.graphql'];
5
- declare type PropertySchema = {
5
+ type PropertySchema = {
6
6
  style?: CaseStyle;
7
7
  suffix?: string;
8
8
  };
9
- export declare type MatchDocumentFilenameRuleConfig = {
9
+ export type MatchDocumentFilenameRuleConfig = {
10
10
  fileExtension?: typeof ACCEPTED_EXTENSIONS[number];
11
11
  query?: CaseStyle | PropertySchema;
12
12
  mutation?: CaseStyle | PropertySchema;
@@ -15,9 +15,9 @@ declare const KindToDisplayName: {
15
15
  FragmentDefinition: string;
16
16
  VariableDefinition: string;
17
17
  };
18
- declare type AllowedKind = keyof typeof KindToDisplayName;
19
- declare type AllowedStyle = 'camelCase' | 'PascalCase' | 'snake_case' | 'UPPER_CASE';
20
- declare type PropertySchema = {
18
+ type AllowedKind = keyof typeof KindToDisplayName;
19
+ type AllowedStyle = 'camelCase' | 'PascalCase' | 'snake_case' | 'UPPER_CASE';
20
+ type PropertySchema = {
21
21
  style?: AllowedStyle;
22
22
  suffix?: string;
23
23
  prefix?: string;
@@ -25,8 +25,8 @@ declare type PropertySchema = {
25
25
  forbiddenSuffixes?: string[];
26
26
  ignorePattern?: string;
27
27
  };
28
- declare type Options = AllowedStyle | PropertySchema;
29
- export declare type NamingConventionRuleConfig = {
28
+ type Options = AllowedStyle | PropertySchema;
29
+ export type NamingConventionRuleConfig = {
30
30
  allowLeadingUnderscore?: boolean;
31
31
  allowTrailingUnderscore?: boolean;
32
32
  types?: Options;
@@ -1,6 +1,6 @@
1
1
  import type { GraphQLESLintRule } from '../types';
2
2
  declare const ROOT_TYPES: ('mutation' | 'subscription')[];
3
- declare type NoRootTypeConfig = {
3
+ type NoRootTypeConfig = {
4
4
  disallow: typeof ROOT_TYPES;
5
5
  };
6
6
  declare const rule: GraphQLESLintRule<[NoRootTypeConfig]>;
@@ -1,5 +1,5 @@
1
1
  import { GraphQLESLintRule } from '../types';
2
- export declare type RelayArgumentsConfig = {
2
+ export type RelayArgumentsConfig = {
3
3
  includeBoth?: boolean;
4
4
  };
5
5
  declare const rule: GraphQLESLintRule<[RelayArgumentsConfig], true>;
@@ -1,5 +1,5 @@
1
1
  import type { GraphQLESLintRule } from '../types';
2
- export declare type EdgeTypesConfig = {
2
+ export type EdgeTypesConfig = {
3
3
  withEdgeSuffix?: boolean;
4
4
  shouldImplementNode?: boolean;
5
5
  listTypeCanWrapOnlyEdgeType?: boolean;
@@ -1,8 +1,8 @@
1
1
  import { Kind } from 'graphql';
2
2
  import type { GraphQLESLintRule } from '../types';
3
3
  declare const ALLOWED_KINDS: readonly [Kind.OBJECT_TYPE_DEFINITION, Kind.INTERFACE_TYPE_DEFINITION, Kind.ENUM_TYPE_DEFINITION, Kind.SCALAR_TYPE_DEFINITION, Kind.INPUT_OBJECT_TYPE_DEFINITION, Kind.UNION_TYPE_DEFINITION, Kind.DIRECTIVE_DEFINITION, Kind.FIELD_DEFINITION, Kind.INPUT_VALUE_DEFINITION, Kind.ENUM_VALUE_DEFINITION, Kind.OPERATION_DEFINITION];
4
- declare type AllowedKind = typeof ALLOWED_KINDS[number];
5
- export declare type RequireDescriptionRuleConfig = {
4
+ type AllowedKind = typeof ALLOWED_KINDS[number];
5
+ export type RequireDescriptionRuleConfig = {
6
6
  types?: boolean;
7
7
  } & {
8
8
  [key in AllowedKind]?: boolean;
@@ -1,5 +1,5 @@
1
1
  import { GraphQLESLintRule } from '../types';
2
- export declare type RequireIdWhenAvailableRuleConfig = {
2
+ export type RequireIdWhenAvailableRuleConfig = {
3
3
  fieldName: string | string[];
4
4
  };
5
5
  declare const rule: GraphQLESLintRule<[RequireIdWhenAvailableRuleConfig], true>;
@@ -1,5 +1,5 @@
1
1
  import { GraphQLESLintRule } from '../types';
2
- export declare type SelectionSetDepthRuleConfig = {
2
+ export type SelectionSetDepthRuleConfig = {
3
3
  maxDepth: number;
4
4
  ignore?: string[];
5
5
  };
@@ -1,5 +1,5 @@
1
1
  import { GraphQLESLintRule } from '../types';
2
- export declare type StrictIdInTypesRuleConfig = {
2
+ export type StrictIdInTypesRuleConfig = {
3
3
  acceptedIdNames?: string[];
4
4
  acceptedIdTypes?: string[];
5
5
  exceptions?: {
package/testkit.d.ts CHANGED
@@ -2,14 +2,14 @@ import { RuleTester } from 'eslint';
2
2
  import type { ASTKindToNode } from 'graphql';
3
3
  import type { GraphQLESTreeNode } from './estree-converter';
4
4
  import type { GraphQLESLintRule, ParserOptions } from './types';
5
- export declare type GraphQLESLintRuleListener<WithTypeInfo extends boolean = false> = {
5
+ export type GraphQLESLintRuleListener<WithTypeInfo extends boolean = false> = {
6
6
  [K in keyof ASTKindToNode]?: (node: GraphQLESTreeNode<ASTKindToNode[K], WithTypeInfo>) => void;
7
7
  } & Record<string, any>;
8
- export declare type GraphQLValidTestCase<Options> = Omit<RuleTester.ValidTestCase, 'options' | 'parserOptions'> & {
8
+ export type GraphQLValidTestCase<Options> = Omit<RuleTester.ValidTestCase, 'options' | 'parserOptions'> & {
9
9
  options?: Options;
10
10
  parserOptions?: ParserOptions;
11
11
  };
12
- export declare type GraphQLInvalidTestCase<T> = GraphQLValidTestCase<T> & {
12
+ export type GraphQLInvalidTestCase<T> = GraphQLValidTestCase<T> & {
13
13
  errors: number | (RuleTester.TestCaseError | string)[];
14
14
  output?: string | null;
15
15
  };