@graphql-eslint/eslint-plugin 2.3.2-alpha-6c4312e.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
@@ -612,7 +612,7 @@ const rule = {
612
612
  ],
613
613
  },
614
614
  messages: {
615
- [ALPHABETIZE]: '"{{ currName }}" should be before "{{ prevName }}"',
615
+ [ALPHABETIZE]: '"{{ currName }}" should be before "{{ prevName }}".',
616
616
  },
617
617
  schema: {
618
618
  type: 'array',
@@ -669,9 +669,16 @@ const rule = {
669
669
  for (const node of nodes) {
670
670
  const currName = node.name.value;
671
671
  if (prevName && prevName > currName) {
672
+ const { start, end } = node.name.loc;
672
673
  const isVariableNode = node.kind === graphql.Kind.VARIABLE;
673
674
  context.report({
674
- loc: getLocation(node.loc, node.name.value, { offsetEnd: isVariableNode ? 0 : 1 }),
675
+ loc: {
676
+ start: {
677
+ line: start.line,
678
+ column: start.column - (isVariableNode ? 2 : 1),
679
+ },
680
+ end,
681
+ },
675
682
  messageId: ALPHABETIZE,
676
683
  data: isVariableNode
677
684
  ? {
@@ -737,35 +744,22 @@ const rule = {
737
744
  };
738
745
 
739
746
  const AVOID_DUPLICATE_FIELDS = 'AVOID_DUPLICATE_FIELDS';
740
- const ensureUnique = () => {
741
- const set = new Set();
742
- return {
743
- add: (item, onError) => {
744
- if (set.has(item)) {
745
- onError();
746
- }
747
- else {
748
- set.add(item);
749
- }
750
- },
751
- };
752
- };
753
747
  const rule$1 = {
754
748
  meta: {
755
749
  type: 'suggestion',
756
750
  docs: {
757
- 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.`,
758
752
  category: 'Stylistic Issues',
759
753
  url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/avoid-duplicate-fields.md',
760
754
  examples: [
761
755
  {
762
756
  title: 'Incorrect',
763
757
  code: /* GraphQL */ `
764
- query getUserDetails {
758
+ query {
765
759
  user {
766
- name # first
760
+ name
767
761
  email
768
- name # second
762
+ name # duplicate field
769
763
  }
770
764
  }
771
765
  `,
@@ -773,7 +767,7 @@ const rule$1 = {
773
767
  {
774
768
  title: 'Incorrect',
775
769
  code: /* GraphQL */ `
776
- query getUsers {
770
+ query {
777
771
  users(
778
772
  first: 100
779
773
  skip: 50
@@ -788,9 +782,11 @@ const rule$1 = {
788
782
  {
789
783
  title: 'Incorrect',
790
784
  code: /* GraphQL */ `
791
- query getUsers($first: Int!, $first: Int!) {
792
- # Duplicate variable
793
- users(first: 100, skip: 50, after: "cji629tngfgou0b73kt7vi5jo") {
785
+ query (
786
+ $first: Int!
787
+ $first: Int! # duplicate variable
788
+ ) {
789
+ users(first: $first, skip: 50) {
794
790
  id
795
791
  }
796
792
  }
@@ -799,58 +795,47 @@ const rule$1 = {
799
795
  ],
800
796
  },
801
797
  messages: {
802
- [AVOID_DUPLICATE_FIELDS]: `{{ type }} "{{ fieldName }}" defined multiple times.`,
798
+ [AVOID_DUPLICATE_FIELDS]: `{{ type }} "{{ fieldName }}" defined multiple times`,
803
799
  },
804
800
  schema: [],
805
801
  },
806
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
+ }
807
820
  return {
808
821
  OperationDefinition(node) {
809
- const uniqueCheck = ensureUnique();
810
- for (const arg of node.variableDefinitions || []) {
811
- uniqueCheck.add(arg.variable.name.value, () => {
812
- context.report({
813
- messageId: AVOID_DUPLICATE_FIELDS,
814
- data: {
815
- type: 'Operation variable',
816
- fieldName: arg.variable.name.value,
817
- },
818
- node: arg,
819
- });
820
- });
822
+ const set = new Set();
823
+ for (const varDef of node.variableDefinitions) {
824
+ checkNode(set, varDef.variable.name.value, 'Operation variable', varDef);
821
825
  }
822
826
  },
823
827
  Field(node) {
824
- const uniqueCheck = ensureUnique();
825
- for (const arg of node.arguments || []) {
826
- uniqueCheck.add(arg.name.value, () => {
827
- context.report({
828
- messageId: AVOID_DUPLICATE_FIELDS,
829
- data: {
830
- type: 'Field argument',
831
- fieldName: arg.name.value,
832
- },
833
- node: arg,
834
- });
835
- });
828
+ const set = new Set();
829
+ for (const arg of node.arguments) {
830
+ checkNode(set, arg.name.value, 'Field argument', arg);
836
831
  }
837
832
  },
838
833
  SelectionSet(node) {
839
834
  var _a;
840
- const uniqueCheck = ensureUnique();
841
- for (const selection of node.selections || []) {
835
+ const set = new Set();
836
+ for (const selection of node.selections) {
842
837
  if (selection.kind === graphql.Kind.FIELD) {
843
- const nameToCheck = ((_a = selection.alias) === null || _a === void 0 ? void 0 : _a.value) || selection.name.value;
844
- uniqueCheck.add(nameToCheck, () => {
845
- context.report({
846
- messageId: AVOID_DUPLICATE_FIELDS,
847
- data: {
848
- type: 'Field',
849
- fieldName: nameToCheck,
850
- },
851
- node: selection,
852
- });
853
- });
838
+ checkNode(set, ((_a = selection.alias) === null || _a === void 0 ? void 0 : _a.value) || selection.name.value, 'Field', selection);
854
839
  }
855
840
  }
856
841
  },
@@ -2023,10 +2008,7 @@ const rule$c = {
2023
2008
  if (!isEslintComment && line !== prev.line && next.kind === graphql.TokenKind.NAME && linesAfter < 2) {
2024
2009
  context.report({
2025
2010
  messageId: HASHTAG_COMMENT,
2026
- loc: {
2027
- start: { line, column },
2028
- end: { line, column },
2029
- },
2011
+ loc: getLocation({ start: { line, column } }),
2030
2012
  });
2031
2013
  }
2032
2014
  }
@@ -3786,25 +3768,7 @@ class GraphQLRuleTester extends eslint.RuleTester {
3786
3768
  return fs.readFileSync(path.resolve(__dirname, `../tests/mocks/${path$1}`), 'utf-8');
3787
3769
  }
3788
3770
  runGraphQLTests(name, rule, tests) {
3789
- const ruleTests = eslint.Linter.version.startsWith('8')
3790
- ? tests
3791
- : {
3792
- valid: tests.valid.map(test => {
3793
- if (typeof test === 'string') {
3794
- return test;
3795
- }
3796
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
3797
- const { name, ...testCaseOptions } = test;
3798
- return testCaseOptions;
3799
- }),
3800
- invalid: tests.invalid.map(test => {
3801
- // ESLint 7 throws an error on CI - Unexpected top-level property "name"
3802
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
3803
- const { name, ...testCaseOptions } = test;
3804
- return testCaseOptions;
3805
- }),
3806
- };
3807
- super.run(name, rule, ruleTests);
3771
+ super.run(name, rule, tests);
3808
3772
  // Skip snapshot testing if `expect` variable is not defined
3809
3773
  if (typeof expect === 'undefined') {
3810
3774
  return;
package/index.mjs CHANGED
@@ -606,7 +606,7 @@ const rule = {
606
606
  ],
607
607
  },
608
608
  messages: {
609
- [ALPHABETIZE]: '"{{ currName }}" should be before "{{ prevName }}"',
609
+ [ALPHABETIZE]: '"{{ currName }}" should be before "{{ prevName }}".',
610
610
  },
611
611
  schema: {
612
612
  type: 'array',
@@ -663,9 +663,16 @@ const rule = {
663
663
  for (const node of nodes) {
664
664
  const currName = node.name.value;
665
665
  if (prevName && prevName > currName) {
666
+ const { start, end } = node.name.loc;
666
667
  const isVariableNode = node.kind === Kind.VARIABLE;
667
668
  context.report({
668
- loc: getLocation(node.loc, node.name.value, { offsetEnd: isVariableNode ? 0 : 1 }),
669
+ loc: {
670
+ start: {
671
+ line: start.line,
672
+ column: start.column - (isVariableNode ? 2 : 1),
673
+ },
674
+ end,
675
+ },
669
676
  messageId: ALPHABETIZE,
670
677
  data: isVariableNode
671
678
  ? {
@@ -731,35 +738,22 @@ const rule = {
731
738
  };
732
739
 
733
740
  const AVOID_DUPLICATE_FIELDS = 'AVOID_DUPLICATE_FIELDS';
734
- const ensureUnique = () => {
735
- const set = new Set();
736
- return {
737
- add: (item, onError) => {
738
- if (set.has(item)) {
739
- onError();
740
- }
741
- else {
742
- set.add(item);
743
- }
744
- },
745
- };
746
- };
747
741
  const rule$1 = {
748
742
  meta: {
749
743
  type: 'suggestion',
750
744
  docs: {
751
- 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.`,
752
746
  category: 'Stylistic Issues',
753
747
  url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/avoid-duplicate-fields.md',
754
748
  examples: [
755
749
  {
756
750
  title: 'Incorrect',
757
751
  code: /* GraphQL */ `
758
- query getUserDetails {
752
+ query {
759
753
  user {
760
- name # first
754
+ name
761
755
  email
762
- name # second
756
+ name # duplicate field
763
757
  }
764
758
  }
765
759
  `,
@@ -767,7 +761,7 @@ const rule$1 = {
767
761
  {
768
762
  title: 'Incorrect',
769
763
  code: /* GraphQL */ `
770
- query getUsers {
764
+ query {
771
765
  users(
772
766
  first: 100
773
767
  skip: 50
@@ -782,9 +776,11 @@ const rule$1 = {
782
776
  {
783
777
  title: 'Incorrect',
784
778
  code: /* GraphQL */ `
785
- query getUsers($first: Int!, $first: Int!) {
786
- # Duplicate variable
787
- users(first: 100, skip: 50, after: "cji629tngfgou0b73kt7vi5jo") {
779
+ query (
780
+ $first: Int!
781
+ $first: Int! # duplicate variable
782
+ ) {
783
+ users(first: $first, skip: 50) {
788
784
  id
789
785
  }
790
786
  }
@@ -793,58 +789,47 @@ const rule$1 = {
793
789
  ],
794
790
  },
795
791
  messages: {
796
- [AVOID_DUPLICATE_FIELDS]: `{{ type }} "{{ fieldName }}" defined multiple times.`,
792
+ [AVOID_DUPLICATE_FIELDS]: `{{ type }} "{{ fieldName }}" defined multiple times`,
797
793
  },
798
794
  schema: [],
799
795
  },
800
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
+ }
801
814
  return {
802
815
  OperationDefinition(node) {
803
- const uniqueCheck = ensureUnique();
804
- for (const arg of node.variableDefinitions || []) {
805
- uniqueCheck.add(arg.variable.name.value, () => {
806
- context.report({
807
- messageId: AVOID_DUPLICATE_FIELDS,
808
- data: {
809
- type: 'Operation variable',
810
- fieldName: arg.variable.name.value,
811
- },
812
- node: arg,
813
- });
814
- });
816
+ const set = new Set();
817
+ for (const varDef of node.variableDefinitions) {
818
+ checkNode(set, varDef.variable.name.value, 'Operation variable', varDef);
815
819
  }
816
820
  },
817
821
  Field(node) {
818
- const uniqueCheck = ensureUnique();
819
- for (const arg of node.arguments || []) {
820
- uniqueCheck.add(arg.name.value, () => {
821
- context.report({
822
- messageId: AVOID_DUPLICATE_FIELDS,
823
- data: {
824
- type: 'Field argument',
825
- fieldName: arg.name.value,
826
- },
827
- node: arg,
828
- });
829
- });
822
+ const set = new Set();
823
+ for (const arg of node.arguments) {
824
+ checkNode(set, arg.name.value, 'Field argument', arg);
830
825
  }
831
826
  },
832
827
  SelectionSet(node) {
833
828
  var _a;
834
- const uniqueCheck = ensureUnique();
835
- for (const selection of node.selections || []) {
829
+ const set = new Set();
830
+ for (const selection of node.selections) {
836
831
  if (selection.kind === Kind.FIELD) {
837
- const nameToCheck = ((_a = selection.alias) === null || _a === void 0 ? void 0 : _a.value) || selection.name.value;
838
- uniqueCheck.add(nameToCheck, () => {
839
- context.report({
840
- messageId: AVOID_DUPLICATE_FIELDS,
841
- data: {
842
- type: 'Field',
843
- fieldName: nameToCheck,
844
- },
845
- node: selection,
846
- });
847
- });
832
+ checkNode(set, ((_a = selection.alias) === null || _a === void 0 ? void 0 : _a.value) || selection.name.value, 'Field', selection);
848
833
  }
849
834
  }
850
835
  },
@@ -2017,10 +2002,7 @@ const rule$c = {
2017
2002
  if (!isEslintComment && line !== prev.line && next.kind === TokenKind.NAME && linesAfter < 2) {
2018
2003
  context.report({
2019
2004
  messageId: HASHTAG_COMMENT,
2020
- loc: {
2021
- start: { line, column },
2022
- end: { line, column },
2023
- },
2005
+ loc: getLocation({ start: { line, column } }),
2024
2006
  });
2025
2007
  }
2026
2008
  }
@@ -3780,25 +3762,7 @@ class GraphQLRuleTester extends RuleTester {
3780
3762
  return readFileSync(resolve(__dirname, `../tests/mocks/${path}`), 'utf-8');
3781
3763
  }
3782
3764
  runGraphQLTests(name, rule, tests) {
3783
- const ruleTests = Linter.version.startsWith('8')
3784
- ? tests
3785
- : {
3786
- valid: tests.valid.map(test => {
3787
- if (typeof test === 'string') {
3788
- return test;
3789
- }
3790
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
3791
- const { name, ...testCaseOptions } = test;
3792
- return testCaseOptions;
3793
- }),
3794
- invalid: tests.invalid.map(test => {
3795
- // ESLint 7 throws an error on CI - Unexpected top-level property "name"
3796
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
3797
- const { name, ...testCaseOptions } = test;
3798
- return testCaseOptions;
3799
- }),
3800
- };
3801
- super.run(name, rule, ruleTests);
3765
+ super.run(name, rule, tests);
3802
3766
  // Skip snapshot testing if `expect` variable is not defined
3803
3767
  if (typeof expect === 'undefined') {
3804
3768
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@graphql-eslint/eslint-plugin",
3
- "version": "2.3.2-alpha-6c4312e.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>;
package/testkit.d.ts CHANGED
@@ -6,7 +6,6 @@ export declare type GraphQLESLintRuleListener<WithTypeInfo extends boolean = fal
6
6
  [K in keyof ASTKindToNode]?: (node: GraphQLESTreeNode<ASTKindToNode[K], WithTypeInfo>) => void;
7
7
  } & Record<string, any>;
8
8
  export declare type GraphQLValidTestCase<Options> = Omit<RuleTester.ValidTestCase, 'options' | 'parserOptions'> & {
9
- name: string;
10
9
  options?: Options;
11
10
  parserOptions?: ParserOptions;
12
11
  };