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

Sign up to get free protection for your applications and to get access to all the features.
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
  };