@graphql-eslint/eslint-plugin 2.3.2-alpha-759bc9e.0 → 2.3.2-alpha-5497183.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -14,11 +14,11 @@ Checks for duplicate fields in selection set, variables in operation definition,
14
14
  ```graphql
15
15
  # eslint @graphql-eslint/avoid-duplicate-fields: 'error'
16
16
 
17
- query getUserDetails {
17
+ query {
18
18
  user {
19
- name # first
19
+ name
20
20
  email
21
- name # second
21
+ name # duplicate field
22
22
  }
23
23
  }
24
24
  ```
@@ -28,7 +28,7 @@ query getUserDetails {
28
28
  ```graphql
29
29
  # eslint @graphql-eslint/avoid-duplicate-fields: 'error'
30
30
 
31
- query getUsers {
31
+ query {
32
32
  users(
33
33
  first: 100
34
34
  skip: 50
@@ -45,9 +45,11 @@ query getUsers {
45
45
  ```graphql
46
46
  # eslint @graphql-eslint/avoid-duplicate-fields: 'error'
47
47
 
48
- query getUsers($first: Int!, $first: Int!) {
49
- # Duplicate variable
50
- users(first: 100, skip: 50, after: "cji629tngfgou0b73kt7vi5jo") {
48
+ query (
49
+ $first: Int!
50
+ $first: Int! # duplicate variable
51
+ ) {
52
+ users(first: $first, skip: 50) {
51
53
  id
52
54
  }
53
55
  }
package/index.js CHANGED
@@ -744,35 +744,22 @@ const rule = {
744
744
  };
745
745
 
746
746
  const AVOID_DUPLICATE_FIELDS = 'AVOID_DUPLICATE_FIELDS';
747
- const ensureUnique = () => {
748
- const set = new Set();
749
- return {
750
- add: (item, onError) => {
751
- if (set.has(item)) {
752
- onError();
753
- }
754
- else {
755
- set.add(item);
756
- }
757
- },
758
- };
759
- };
760
747
  const rule$1 = {
761
748
  meta: {
762
749
  type: 'suggestion',
763
750
  docs: {
764
- description: 'Checks for duplicate fields in selection set, variables in operation definition, or in arguments set of a field.',
751
+ description: `Checks for duplicate fields in selection set, variables in operation definition, or in arguments set of a field.`,
765
752
  category: 'Stylistic Issues',
766
753
  url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/avoid-duplicate-fields.md',
767
754
  examples: [
768
755
  {
769
756
  title: 'Incorrect',
770
757
  code: /* GraphQL */ `
771
- query getUserDetails {
758
+ query {
772
759
  user {
773
- name # first
760
+ name
774
761
  email
775
- name # second
762
+ name # duplicate field
776
763
  }
777
764
  }
778
765
  `,
@@ -780,7 +767,7 @@ const rule$1 = {
780
767
  {
781
768
  title: 'Incorrect',
782
769
  code: /* GraphQL */ `
783
- query getUsers {
770
+ query {
784
771
  users(
785
772
  first: 100
786
773
  skip: 50
@@ -795,9 +782,11 @@ const rule$1 = {
795
782
  {
796
783
  title: 'Incorrect',
797
784
  code: /* GraphQL */ `
798
- query getUsers($first: Int!, $first: Int!) {
799
- # Duplicate variable
800
- users(first: 100, skip: 50, after: "cji629tngfgou0b73kt7vi5jo") {
785
+ query (
786
+ $first: Int!
787
+ $first: Int! # duplicate variable
788
+ ) {
789
+ users(first: $first, skip: 50) {
801
790
  id
802
791
  }
803
792
  }
@@ -806,58 +795,47 @@ const rule$1 = {
806
795
  ],
807
796
  },
808
797
  messages: {
809
- [AVOID_DUPLICATE_FIELDS]: `{{ type }} "{{ fieldName }}" defined multiple times.`,
798
+ [AVOID_DUPLICATE_FIELDS]: `{{ type }} "{{ fieldName }}" defined multiple times`,
810
799
  },
811
800
  schema: [],
812
801
  },
813
802
  create(context) {
803
+ function checkNode(usedFields, fieldName, type, node) {
804
+ if (usedFields.has(fieldName)) {
805
+ context.report({
806
+ loc: getLocation((node.kind === graphql.Kind.FIELD && node.alias ? node.alias : node).loc, fieldName, {
807
+ offsetEnd: node.kind === graphql.Kind.VARIABLE_DEFINITION ? 0 : 1,
808
+ }),
809
+ messageId: AVOID_DUPLICATE_FIELDS,
810
+ data: {
811
+ type,
812
+ fieldName,
813
+ },
814
+ });
815
+ }
816
+ else {
817
+ usedFields.add(fieldName);
818
+ }
819
+ }
814
820
  return {
815
821
  OperationDefinition(node) {
816
- const uniqueCheck = ensureUnique();
817
- for (const arg of node.variableDefinitions || []) {
818
- uniqueCheck.add(arg.variable.name.value, () => {
819
- context.report({
820
- messageId: AVOID_DUPLICATE_FIELDS,
821
- data: {
822
- type: 'Operation variable',
823
- fieldName: arg.variable.name.value,
824
- },
825
- node: arg,
826
- });
827
- });
822
+ const set = new Set();
823
+ for (const varDef of node.variableDefinitions) {
824
+ checkNode(set, varDef.variable.name.value, 'Operation variable', varDef);
828
825
  }
829
826
  },
830
827
  Field(node) {
831
- const uniqueCheck = ensureUnique();
832
- for (const arg of node.arguments || []) {
833
- uniqueCheck.add(arg.name.value, () => {
834
- context.report({
835
- messageId: AVOID_DUPLICATE_FIELDS,
836
- data: {
837
- type: 'Field argument',
838
- fieldName: arg.name.value,
839
- },
840
- node: arg,
841
- });
842
- });
828
+ const set = new Set();
829
+ for (const arg of node.arguments) {
830
+ checkNode(set, arg.name.value, 'Field argument', arg);
843
831
  }
844
832
  },
845
833
  SelectionSet(node) {
846
834
  var _a;
847
- const uniqueCheck = ensureUnique();
848
- for (const selection of node.selections || []) {
835
+ const set = new Set();
836
+ for (const selection of node.selections) {
849
837
  if (selection.kind === graphql.Kind.FIELD) {
850
- const nameToCheck = ((_a = selection.alias) === null || _a === void 0 ? void 0 : _a.value) || selection.name.value;
851
- uniqueCheck.add(nameToCheck, () => {
852
- context.report({
853
- messageId: AVOID_DUPLICATE_FIELDS,
854
- data: {
855
- type: 'Field',
856
- fieldName: nameToCheck,
857
- },
858
- node: selection,
859
- });
860
- });
838
+ checkNode(set, ((_a = selection.alias) === null || _a === void 0 ? void 0 : _a.value) || selection.name.value, 'Field', selection);
861
839
  }
862
840
  }
863
841
  },
@@ -2030,10 +2008,7 @@ const rule$c = {
2030
2008
  if (!isEslintComment && line !== prev.line && next.kind === graphql.TokenKind.NAME && linesAfter < 2) {
2031
2009
  context.report({
2032
2010
  messageId: HASHTAG_COMMENT,
2033
- loc: {
2034
- start: { line, column },
2035
- end: { line, column },
2036
- },
2011
+ loc: getLocation({ start: { line, column } }),
2037
2012
  });
2038
2013
  }
2039
2014
  }
@@ -2516,15 +2491,17 @@ const rule$h = {
2516
2491
  },
2517
2492
  create(context) {
2518
2493
  return {
2519
- 'Directive[name.value=deprecated]'(node) {
2520
- const args = node.arguments || [];
2521
- const reasonArg = args.find(arg => arg.name && arg.name.value === 'reason');
2522
- const value = reasonArg ? String(valueFromNode(reasonArg.value) || '').trim() : null;
2523
- if (!value) {
2524
- context.report({
2525
- loc: getLocation(node.loc, node.name.value, { offsetEnd: 0 }),
2526
- message: 'Directive "@deprecated" must have a reason!',
2527
- });
2494
+ Directive(node) {
2495
+ if (node && node.name && node.name.value === 'deprecated') {
2496
+ const args = node.arguments || [];
2497
+ const reasonArg = args.find(arg => arg.name && arg.name.value === 'reason');
2498
+ const value = reasonArg ? String(valueFromNode(reasonArg.value) || '').trim() : null;
2499
+ if (!value) {
2500
+ context.report({
2501
+ node: node.name,
2502
+ message: 'Directive "@deprecated" must have a reason!',
2503
+ });
2504
+ }
2528
2505
  }
2529
2506
  },
2530
2507
  };
@@ -2681,22 +2658,18 @@ const rule$j = {
2681
2658
  if (!mutationType || !queryType) {
2682
2659
  return {};
2683
2660
  }
2684
- const selector = [
2685
- `:matches(${graphql.Kind.OBJECT_TYPE_DEFINITION}, ${graphql.Kind.OBJECT_TYPE_EXTENSION})[name.value=${mutationType.name}]`,
2686
- '>',
2687
- graphql.Kind.FIELD_DEFINITION,
2688
- graphql.Kind.NAMED_TYPE,
2689
- ].join(' ');
2661
+ const selector = `:matches(${graphql.Kind.OBJECT_TYPE_DEFINITION}, ${graphql.Kind.OBJECT_TYPE_EXTENSION})[name.value=${mutationType.name}] > ${graphql.Kind.FIELD_DEFINITION}`;
2690
2662
  return {
2691
2663
  [selector](node) {
2692
- const typeName = node.name.value;
2664
+ const rawNode = node.rawNode();
2665
+ const typeName = getTypeName(rawNode);
2693
2666
  const graphQLType = schema.getType(typeName);
2694
2667
  if (graphql.isObjectType(graphQLType)) {
2695
2668
  const { fields } = graphQLType.astNode;
2696
2669
  const hasQueryType = fields.some(field => getTypeName(field) === queryType.name);
2697
2670
  if (!hasQueryType) {
2698
2671
  context.report({
2699
- loc: getLocation(node.loc, typeName),
2672
+ node,
2700
2673
  message: `Mutation result type "${graphQLType.name}" must contain field of type "${queryType.name}".`,
2701
2674
  });
2702
2675
  }
package/index.mjs CHANGED
@@ -738,35 +738,22 @@ const rule = {
738
738
  };
739
739
 
740
740
  const AVOID_DUPLICATE_FIELDS = 'AVOID_DUPLICATE_FIELDS';
741
- const ensureUnique = () => {
742
- const set = new Set();
743
- return {
744
- add: (item, onError) => {
745
- if (set.has(item)) {
746
- onError();
747
- }
748
- else {
749
- set.add(item);
750
- }
751
- },
752
- };
753
- };
754
741
  const rule$1 = {
755
742
  meta: {
756
743
  type: 'suggestion',
757
744
  docs: {
758
- description: 'Checks for duplicate fields in selection set, variables in operation definition, or in arguments set of a field.',
745
+ description: `Checks for duplicate fields in selection set, variables in operation definition, or in arguments set of a field.`,
759
746
  category: 'Stylistic Issues',
760
747
  url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/avoid-duplicate-fields.md',
761
748
  examples: [
762
749
  {
763
750
  title: 'Incorrect',
764
751
  code: /* GraphQL */ `
765
- query getUserDetails {
752
+ query {
766
753
  user {
767
- name # first
754
+ name
768
755
  email
769
- name # second
756
+ name # duplicate field
770
757
  }
771
758
  }
772
759
  `,
@@ -774,7 +761,7 @@ const rule$1 = {
774
761
  {
775
762
  title: 'Incorrect',
776
763
  code: /* GraphQL */ `
777
- query getUsers {
764
+ query {
778
765
  users(
779
766
  first: 100
780
767
  skip: 50
@@ -789,9 +776,11 @@ const rule$1 = {
789
776
  {
790
777
  title: 'Incorrect',
791
778
  code: /* GraphQL */ `
792
- query getUsers($first: Int!, $first: Int!) {
793
- # Duplicate variable
794
- users(first: 100, skip: 50, after: "cji629tngfgou0b73kt7vi5jo") {
779
+ query (
780
+ $first: Int!
781
+ $first: Int! # duplicate variable
782
+ ) {
783
+ users(first: $first, skip: 50) {
795
784
  id
796
785
  }
797
786
  }
@@ -800,58 +789,47 @@ const rule$1 = {
800
789
  ],
801
790
  },
802
791
  messages: {
803
- [AVOID_DUPLICATE_FIELDS]: `{{ type }} "{{ fieldName }}" defined multiple times.`,
792
+ [AVOID_DUPLICATE_FIELDS]: `{{ type }} "{{ fieldName }}" defined multiple times`,
804
793
  },
805
794
  schema: [],
806
795
  },
807
796
  create(context) {
797
+ function checkNode(usedFields, fieldName, type, node) {
798
+ if (usedFields.has(fieldName)) {
799
+ context.report({
800
+ loc: getLocation((node.kind === Kind.FIELD && node.alias ? node.alias : node).loc, fieldName, {
801
+ offsetEnd: node.kind === Kind.VARIABLE_DEFINITION ? 0 : 1,
802
+ }),
803
+ messageId: AVOID_DUPLICATE_FIELDS,
804
+ data: {
805
+ type,
806
+ fieldName,
807
+ },
808
+ });
809
+ }
810
+ else {
811
+ usedFields.add(fieldName);
812
+ }
813
+ }
808
814
  return {
809
815
  OperationDefinition(node) {
810
- const uniqueCheck = ensureUnique();
811
- for (const arg of node.variableDefinitions || []) {
812
- uniqueCheck.add(arg.variable.name.value, () => {
813
- context.report({
814
- messageId: AVOID_DUPLICATE_FIELDS,
815
- data: {
816
- type: 'Operation variable',
817
- fieldName: arg.variable.name.value,
818
- },
819
- node: arg,
820
- });
821
- });
816
+ const set = new Set();
817
+ for (const varDef of node.variableDefinitions) {
818
+ checkNode(set, varDef.variable.name.value, 'Operation variable', varDef);
822
819
  }
823
820
  },
824
821
  Field(node) {
825
- const uniqueCheck = ensureUnique();
826
- for (const arg of node.arguments || []) {
827
- uniqueCheck.add(arg.name.value, () => {
828
- context.report({
829
- messageId: AVOID_DUPLICATE_FIELDS,
830
- data: {
831
- type: 'Field argument',
832
- fieldName: arg.name.value,
833
- },
834
- node: arg,
835
- });
836
- });
822
+ const set = new Set();
823
+ for (const arg of node.arguments) {
824
+ checkNode(set, arg.name.value, 'Field argument', arg);
837
825
  }
838
826
  },
839
827
  SelectionSet(node) {
840
828
  var _a;
841
- const uniqueCheck = ensureUnique();
842
- for (const selection of node.selections || []) {
829
+ const set = new Set();
830
+ for (const selection of node.selections) {
843
831
  if (selection.kind === Kind.FIELD) {
844
- const nameToCheck = ((_a = selection.alias) === null || _a === void 0 ? void 0 : _a.value) || selection.name.value;
845
- uniqueCheck.add(nameToCheck, () => {
846
- context.report({
847
- messageId: AVOID_DUPLICATE_FIELDS,
848
- data: {
849
- type: 'Field',
850
- fieldName: nameToCheck,
851
- },
852
- node: selection,
853
- });
854
- });
832
+ checkNode(set, ((_a = selection.alias) === null || _a === void 0 ? void 0 : _a.value) || selection.name.value, 'Field', selection);
855
833
  }
856
834
  }
857
835
  },
@@ -2024,10 +2002,7 @@ const rule$c = {
2024
2002
  if (!isEslintComment && line !== prev.line && next.kind === TokenKind.NAME && linesAfter < 2) {
2025
2003
  context.report({
2026
2004
  messageId: HASHTAG_COMMENT,
2027
- loc: {
2028
- start: { line, column },
2029
- end: { line, column },
2030
- },
2005
+ loc: getLocation({ start: { line, column } }),
2031
2006
  });
2032
2007
  }
2033
2008
  }
@@ -2510,15 +2485,17 @@ const rule$h = {
2510
2485
  },
2511
2486
  create(context) {
2512
2487
  return {
2513
- 'Directive[name.value=deprecated]'(node) {
2514
- const args = node.arguments || [];
2515
- const reasonArg = args.find(arg => arg.name && arg.name.value === 'reason');
2516
- const value = reasonArg ? String(valueFromNode(reasonArg.value) || '').trim() : null;
2517
- if (!value) {
2518
- context.report({
2519
- loc: getLocation(node.loc, node.name.value, { offsetEnd: 0 }),
2520
- message: 'Directive "@deprecated" must have a reason!',
2521
- });
2488
+ Directive(node) {
2489
+ if (node && node.name && node.name.value === 'deprecated') {
2490
+ const args = node.arguments || [];
2491
+ const reasonArg = args.find(arg => arg.name && arg.name.value === 'reason');
2492
+ const value = reasonArg ? String(valueFromNode(reasonArg.value) || '').trim() : null;
2493
+ if (!value) {
2494
+ context.report({
2495
+ node: node.name,
2496
+ message: 'Directive "@deprecated" must have a reason!',
2497
+ });
2498
+ }
2522
2499
  }
2523
2500
  },
2524
2501
  };
@@ -2675,22 +2652,18 @@ const rule$j = {
2675
2652
  if (!mutationType || !queryType) {
2676
2653
  return {};
2677
2654
  }
2678
- const selector = [
2679
- `:matches(${Kind.OBJECT_TYPE_DEFINITION}, ${Kind.OBJECT_TYPE_EXTENSION})[name.value=${mutationType.name}]`,
2680
- '>',
2681
- Kind.FIELD_DEFINITION,
2682
- Kind.NAMED_TYPE,
2683
- ].join(' ');
2655
+ const selector = `:matches(${Kind.OBJECT_TYPE_DEFINITION}, ${Kind.OBJECT_TYPE_EXTENSION})[name.value=${mutationType.name}] > ${Kind.FIELD_DEFINITION}`;
2684
2656
  return {
2685
2657
  [selector](node) {
2686
- const typeName = node.name.value;
2658
+ const rawNode = node.rawNode();
2659
+ const typeName = getTypeName(rawNode);
2687
2660
  const graphQLType = schema.getType(typeName);
2688
2661
  if (isObjectType$1(graphQLType)) {
2689
2662
  const { fields } = graphQLType.astNode;
2690
2663
  const hasQueryType = fields.some(field => getTypeName(field) === queryType.name);
2691
2664
  if (!hasQueryType) {
2692
2665
  context.report({
2693
- loc: getLocation(node.loc, typeName),
2666
+ node,
2694
2667
  message: `Mutation result type "${graphQLType.name}" must contain field of type "${queryType.name}".`,
2695
2668
  });
2696
2669
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@graphql-eslint/eslint-plugin",
3
- "version": "2.3.2-alpha-759bc9e.0",
3
+ "version": "2.3.2-alpha-5497183.0",
4
4
  "sideEffects": false,
5
5
  "peerDependencies": {
6
6
  "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0"
@@ -1,3 +1,3 @@
1
1
  import { GraphQLESLintRule } from '../types';
2
- declare const rule: GraphQLESLintRule<[], false>;
2
+ declare const rule: GraphQLESLintRule;
3
3
  export default rule;
package/rules/index.d.ts CHANGED
@@ -6,7 +6,7 @@ export declare const rules: {
6
6
  variables?: "OperationDefinition"[];
7
7
  arguments?: ("Field" | "Directive" | "FieldDefinition" | "DirectiveDefinition")[];
8
8
  }], false>;
9
- 'avoid-duplicate-fields': import("..").GraphQLESLintRule<[], false>;
9
+ 'avoid-duplicate-fields': import("..").GraphQLESLintRule<any[], false>;
10
10
  'avoid-operation-name-prefix': import("..").GraphQLESLintRule<import("./avoid-operation-name-prefix").AvoidOperationNamePrefixConfig, false>;
11
11
  'avoid-scalar-result-type-on-mutation': import("..").GraphQLESLintRule<any[], false>;
12
12
  'avoid-typename-prefix': import("..").GraphQLESLintRule<any[], false>;