@graphql-eslint/eslint-plugin 2.3.2-alpha-78e0315.0 → 2.3.2-alpha-6c8a706.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 {
17
+ query getUserDetails {
18
18
  user {
19
- name
19
+ name # first
20
20
  email
21
- name # duplicate field
21
+ name # second
22
22
  }
23
23
  }
24
24
  ```
@@ -28,7 +28,7 @@ query {
28
28
  ```graphql
29
29
  # eslint @graphql-eslint/avoid-duplicate-fields: 'error'
30
30
 
31
- query {
31
+ query getUsers {
32
32
  users(
33
33
  first: 100
34
34
  skip: 50
@@ -45,11 +45,9 @@ query {
45
45
  ```graphql
46
46
  # eslint @graphql-eslint/avoid-duplicate-fields: 'error'
47
47
 
48
- query (
49
- $first: Int!
50
- $first: Int! # duplicate variable
51
- ) {
52
- users(first: $first, skip: 50) {
48
+ query getUsers($first: Int!, $first: Int!) {
49
+ # Duplicate variable
50
+ users(first: 100, skip: 50, after: "cji629tngfgou0b73kt7vi5jo") {
53
51
  id
54
52
  }
55
53
  }
package/index.js CHANGED
@@ -275,7 +275,7 @@ function validateDoc(sourceNode, context, schema, documentNode, rules, ruleName
275
275
  for (const error of validationErrors) {
276
276
  const validateRuleName = ruleName || `[${extractRuleName(error.stack)}]`;
277
277
  context.report({
278
- loc: error.locations[0],
278
+ loc: getLocation({ start: error.locations[0] }),
279
279
  message: ruleName ? error.message : `${validateRuleName} ${error.message}`,
280
280
  });
281
281
  }
@@ -744,22 +744,35 @@ 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
+ };
747
760
  const rule$1 = {
748
761
  meta: {
749
762
  type: 'suggestion',
750
763
  docs: {
751
- description: `Checks for duplicate fields in selection set, variables in operation definition, or in arguments set of a field.`,
764
+ description: 'Checks for duplicate fields in selection set, variables in operation definition, or in arguments set of a field.',
752
765
  category: 'Stylistic Issues',
753
766
  url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/avoid-duplicate-fields.md',
754
767
  examples: [
755
768
  {
756
769
  title: 'Incorrect',
757
770
  code: /* GraphQL */ `
758
- query {
771
+ query getUserDetails {
759
772
  user {
760
- name
773
+ name # first
761
774
  email
762
- name # duplicate field
775
+ name # second
763
776
  }
764
777
  }
765
778
  `,
@@ -767,7 +780,7 @@ const rule$1 = {
767
780
  {
768
781
  title: 'Incorrect',
769
782
  code: /* GraphQL */ `
770
- query {
783
+ query getUsers {
771
784
  users(
772
785
  first: 100
773
786
  skip: 50
@@ -782,11 +795,9 @@ const rule$1 = {
782
795
  {
783
796
  title: 'Incorrect',
784
797
  code: /* GraphQL */ `
785
- query (
786
- $first: Int!
787
- $first: Int! # duplicate variable
788
- ) {
789
- users(first: $first, skip: 50) {
798
+ query getUsers($first: Int!, $first: Int!) {
799
+ # Duplicate variable
800
+ users(first: 100, skip: 50, after: "cji629tngfgou0b73kt7vi5jo") {
790
801
  id
791
802
  }
792
803
  }
@@ -795,47 +806,58 @@ const rule$1 = {
795
806
  ],
796
807
  },
797
808
  messages: {
798
- [AVOID_DUPLICATE_FIELDS]: `{{ type }} "{{ fieldName }}" defined multiple times`,
809
+ [AVOID_DUPLICATE_FIELDS]: `{{ type }} "{{ fieldName }}" defined multiple times.`,
799
810
  },
800
811
  schema: [],
801
812
  },
802
813
  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
- }
820
814
  return {
821
815
  OperationDefinition(node) {
822
- const set = new Set();
823
- for (const varDef of node.variableDefinitions) {
824
- checkNode(set, varDef.variable.name.value, 'Operation variable', varDef);
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
+ });
825
828
  }
826
829
  },
827
830
  Field(node) {
828
- const set = new Set();
829
- for (const arg of node.arguments) {
830
- checkNode(set, arg.name.value, 'Field argument', arg);
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
+ });
831
843
  }
832
844
  },
833
845
  SelectionSet(node) {
834
846
  var _a;
835
- const set = new Set();
836
- for (const selection of node.selections) {
847
+ const uniqueCheck = ensureUnique();
848
+ for (const selection of node.selections || []) {
837
849
  if (selection.kind === graphql.Kind.FIELD) {
838
- checkNode(set, ((_a = selection.alias) === null || _a === void 0 ? void 0 : _a.value) || selection.name.value, 'Field', selection);
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
+ });
839
861
  }
840
862
  }
841
863
  },
@@ -1028,23 +1050,13 @@ const rule$4 = {
1028
1050
  for (const field of node.fields) {
1029
1051
  const fieldName = field.name.value;
1030
1052
  if (fieldName.toLowerCase().startsWith(lowerTypeName)) {
1031
- const { start } = field.loc;
1032
1053
  context.report({
1033
1054
  data: {
1034
1055
  fieldName,
1035
1056
  typeName,
1036
1057
  },
1037
1058
  messageId: AVOID_TYPENAME_PREFIX,
1038
- loc: {
1039
- start: {
1040
- line: start.line,
1041
- column: start.column - 1,
1042
- },
1043
- end: {
1044
- line: start.line,
1045
- column: start.column - 1 + lowerTypeName.length,
1046
- },
1047
- },
1059
+ loc: getLocation(field.loc, lowerTypeName),
1048
1060
  });
1049
1061
  }
1050
1062
  }
@@ -1748,28 +1760,14 @@ const rule$9 = {
1748
1760
  },
1749
1761
  create(context) {
1750
1762
  return {
1751
- OperationDefinition(node) {
1752
- var _a;
1753
- const isAnonymous = (((_a = node.name) === null || _a === void 0 ? void 0 : _a.value) || '').length === 0;
1754
- if (isAnonymous) {
1755
- const { start } = node.loc;
1756
- context.report({
1757
- loc: {
1758
- start: {
1759
- column: start.column - 1,
1760
- line: start.line,
1761
- },
1762
- end: {
1763
- column: start.column - 1 + node.operation.length,
1764
- line: start.line,
1765
- },
1766
- },
1767
- data: {
1768
- operation: node.operation,
1769
- },
1770
- messageId: NO_ANONYMOUS_OPERATIONS,
1771
- });
1772
- }
1763
+ 'OperationDefinition[name=undefined]'(node) {
1764
+ context.report({
1765
+ loc: getLocation(node.loc, node.operation),
1766
+ data: {
1767
+ operation: node.operation,
1768
+ },
1769
+ messageId: NO_ANONYMOUS_OPERATIONS,
1770
+ });
1773
1771
  },
1774
1772
  };
1775
1773
  },
@@ -2008,7 +2006,10 @@ const rule$c = {
2008
2006
  if (!isEslintComment && line !== prev.line && next.kind === graphql.TokenKind.NAME && linesAfter < 2) {
2009
2007
  context.report({
2010
2008
  messageId: HASHTAG_COMMENT,
2011
- loc: getLocation({ start: { line, column } }),
2009
+ loc: {
2010
+ start: { line, column },
2011
+ end: { line, column },
2012
+ },
2012
2013
  });
2013
2014
  }
2014
2015
  }
@@ -2524,20 +2525,8 @@ const DESCRIBABLE_NODES = [
2524
2525
  function verifyRule(context, node) {
2525
2526
  if (node) {
2526
2527
  if (!node.description || !node.description.value || node.description.value.trim().length === 0) {
2527
- const { start, end } = ('name' in node ? node.name : node).loc;
2528
2528
  context.report({
2529
- loc: {
2530
- start: {
2531
- line: start.line,
2532
- column: start.column - 1,
2533
- },
2534
- end: {
2535
- line: end.line,
2536
- column:
2537
- // node.name don't exist on SchemaDefinition
2538
- 'name' in node ? end.column - 1 + node.name.value.length : end.column,
2539
- },
2540
- },
2529
+ loc: getLocation(('name' in node ? node.name : node).loc, 'name' in node ? node.name.value : 'schema'),
2541
2530
  messageId: REQUIRE_DESCRIPTION_ERROR,
2542
2531
  data: {
2543
2532
  nodeType: node.kind,
@@ -3008,7 +2997,7 @@ const rule$l = {
3008
2997
  getDocument: () => document,
3009
2998
  reportError: (error) => {
3010
2999
  context.report({
3011
- loc: error.locations[0],
3000
+ loc: getLocation({ start: error.locations[0] }),
3012
3001
  message: error.message,
3013
3002
  });
3014
3003
  },
package/index.mjs CHANGED
@@ -269,7 +269,7 @@ function validateDoc(sourceNode, context, schema, documentNode, rules, ruleName
269
269
  for (const error of validationErrors) {
270
270
  const validateRuleName = ruleName || `[${extractRuleName(error.stack)}]`;
271
271
  context.report({
272
- loc: error.locations[0],
272
+ loc: getLocation({ start: error.locations[0] }),
273
273
  message: ruleName ? error.message : `${validateRuleName} ${error.message}`,
274
274
  });
275
275
  }
@@ -738,22 +738,35 @@ 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
+ };
741
754
  const rule$1 = {
742
755
  meta: {
743
756
  type: 'suggestion',
744
757
  docs: {
745
- description: `Checks for duplicate fields in selection set, variables in operation definition, or in arguments set of a field.`,
758
+ description: 'Checks for duplicate fields in selection set, variables in operation definition, or in arguments set of a field.',
746
759
  category: 'Stylistic Issues',
747
760
  url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/avoid-duplicate-fields.md',
748
761
  examples: [
749
762
  {
750
763
  title: 'Incorrect',
751
764
  code: /* GraphQL */ `
752
- query {
765
+ query getUserDetails {
753
766
  user {
754
- name
767
+ name # first
755
768
  email
756
- name # duplicate field
769
+ name # second
757
770
  }
758
771
  }
759
772
  `,
@@ -761,7 +774,7 @@ const rule$1 = {
761
774
  {
762
775
  title: 'Incorrect',
763
776
  code: /* GraphQL */ `
764
- query {
777
+ query getUsers {
765
778
  users(
766
779
  first: 100
767
780
  skip: 50
@@ -776,11 +789,9 @@ const rule$1 = {
776
789
  {
777
790
  title: 'Incorrect',
778
791
  code: /* GraphQL */ `
779
- query (
780
- $first: Int!
781
- $first: Int! # duplicate variable
782
- ) {
783
- users(first: $first, skip: 50) {
792
+ query getUsers($first: Int!, $first: Int!) {
793
+ # Duplicate variable
794
+ users(first: 100, skip: 50, after: "cji629tngfgou0b73kt7vi5jo") {
784
795
  id
785
796
  }
786
797
  }
@@ -789,47 +800,58 @@ const rule$1 = {
789
800
  ],
790
801
  },
791
802
  messages: {
792
- [AVOID_DUPLICATE_FIELDS]: `{{ type }} "{{ fieldName }}" defined multiple times`,
803
+ [AVOID_DUPLICATE_FIELDS]: `{{ type }} "{{ fieldName }}" defined multiple times.`,
793
804
  },
794
805
  schema: [],
795
806
  },
796
807
  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
- }
814
808
  return {
815
809
  OperationDefinition(node) {
816
- const set = new Set();
817
- for (const varDef of node.variableDefinitions) {
818
- checkNode(set, varDef.variable.name.value, 'Operation variable', varDef);
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
+ });
819
822
  }
820
823
  },
821
824
  Field(node) {
822
- const set = new Set();
823
- for (const arg of node.arguments) {
824
- checkNode(set, arg.name.value, 'Field argument', arg);
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
+ });
825
837
  }
826
838
  },
827
839
  SelectionSet(node) {
828
840
  var _a;
829
- const set = new Set();
830
- for (const selection of node.selections) {
841
+ const uniqueCheck = ensureUnique();
842
+ for (const selection of node.selections || []) {
831
843
  if (selection.kind === Kind.FIELD) {
832
- checkNode(set, ((_a = selection.alias) === null || _a === void 0 ? void 0 : _a.value) || selection.name.value, 'Field', selection);
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
+ });
833
855
  }
834
856
  }
835
857
  },
@@ -1022,23 +1044,13 @@ const rule$4 = {
1022
1044
  for (const field of node.fields) {
1023
1045
  const fieldName = field.name.value;
1024
1046
  if (fieldName.toLowerCase().startsWith(lowerTypeName)) {
1025
- const { start } = field.loc;
1026
1047
  context.report({
1027
1048
  data: {
1028
1049
  fieldName,
1029
1050
  typeName,
1030
1051
  },
1031
1052
  messageId: AVOID_TYPENAME_PREFIX,
1032
- loc: {
1033
- start: {
1034
- line: start.line,
1035
- column: start.column - 1,
1036
- },
1037
- end: {
1038
- line: start.line,
1039
- column: start.column - 1 + lowerTypeName.length,
1040
- },
1041
- },
1053
+ loc: getLocation(field.loc, lowerTypeName),
1042
1054
  });
1043
1055
  }
1044
1056
  }
@@ -1742,28 +1754,14 @@ const rule$9 = {
1742
1754
  },
1743
1755
  create(context) {
1744
1756
  return {
1745
- OperationDefinition(node) {
1746
- var _a;
1747
- const isAnonymous = (((_a = node.name) === null || _a === void 0 ? void 0 : _a.value) || '').length === 0;
1748
- if (isAnonymous) {
1749
- const { start } = node.loc;
1750
- context.report({
1751
- loc: {
1752
- start: {
1753
- column: start.column - 1,
1754
- line: start.line,
1755
- },
1756
- end: {
1757
- column: start.column - 1 + node.operation.length,
1758
- line: start.line,
1759
- },
1760
- },
1761
- data: {
1762
- operation: node.operation,
1763
- },
1764
- messageId: NO_ANONYMOUS_OPERATIONS,
1765
- });
1766
- }
1757
+ 'OperationDefinition[name=undefined]'(node) {
1758
+ context.report({
1759
+ loc: getLocation(node.loc, node.operation),
1760
+ data: {
1761
+ operation: node.operation,
1762
+ },
1763
+ messageId: NO_ANONYMOUS_OPERATIONS,
1764
+ });
1767
1765
  },
1768
1766
  };
1769
1767
  },
@@ -2002,7 +2000,10 @@ const rule$c = {
2002
2000
  if (!isEslintComment && line !== prev.line && next.kind === TokenKind.NAME && linesAfter < 2) {
2003
2001
  context.report({
2004
2002
  messageId: HASHTAG_COMMENT,
2005
- loc: getLocation({ start: { line, column } }),
2003
+ loc: {
2004
+ start: { line, column },
2005
+ end: { line, column },
2006
+ },
2006
2007
  });
2007
2008
  }
2008
2009
  }
@@ -2518,20 +2519,8 @@ const DESCRIBABLE_NODES = [
2518
2519
  function verifyRule(context, node) {
2519
2520
  if (node) {
2520
2521
  if (!node.description || !node.description.value || node.description.value.trim().length === 0) {
2521
- const { start, end } = ('name' in node ? node.name : node).loc;
2522
2522
  context.report({
2523
- loc: {
2524
- start: {
2525
- line: start.line,
2526
- column: start.column - 1,
2527
- },
2528
- end: {
2529
- line: end.line,
2530
- column:
2531
- // node.name don't exist on SchemaDefinition
2532
- 'name' in node ? end.column - 1 + node.name.value.length : end.column,
2533
- },
2534
- },
2523
+ loc: getLocation(('name' in node ? node.name : node).loc, 'name' in node ? node.name.value : 'schema'),
2535
2524
  messageId: REQUIRE_DESCRIPTION_ERROR,
2536
2525
  data: {
2537
2526
  nodeType: node.kind,
@@ -3002,7 +2991,7 @@ const rule$l = {
3002
2991
  getDocument: () => document,
3003
2992
  reportError: (error) => {
3004
2993
  context.report({
3005
- loc: error.locations[0],
2994
+ loc: getLocation({ start: error.locations[0] }),
3006
2995
  message: error.message,
3007
2996
  });
3008
2997
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@graphql-eslint/eslint-plugin",
3
- "version": "2.3.2-alpha-78e0315.0",
3
+ "version": "2.3.2-alpha-6c8a706.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;
2
+ declare const rule: GraphQLESLintRule<[], false>;
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<any[], false>;
9
+ 'avoid-duplicate-fields': import("..").GraphQLESLintRule<[], 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>;