@graphql-eslint/eslint-plugin 3.14.4-alpha-20230111223410-a558ee8 → 3.14.4-alpha-20230111225020-02d9c28

Sign up to get free protection for your applications and to get access to all the features.
Files changed (156) hide show
  1. package/README.md +5 -288
  2. package/cjs/documents.js +2 -105
  3. package/cjs/graphql-config.js +1 -1
  4. package/cjs/parser.js +9 -3
  5. package/cjs/rules/alphabetize.js +1 -1
  6. package/cjs/rules/description-style.js +1 -1
  7. package/cjs/rules/graphql-js-validation.js +1 -1
  8. package/cjs/rules/input-name.js +4 -4
  9. package/cjs/rules/lone-executable-definition.js +1 -1
  10. package/cjs/rules/match-document-filename.js +2 -3
  11. package/cjs/rules/naming-convention.js +1 -1
  12. package/cjs/rules/no-anonymous-operations.js +1 -1
  13. package/cjs/rules/no-case-insensitive-enum-values-duplicates.js +1 -1
  14. package/cjs/rules/no-deprecated.js +1 -1
  15. package/cjs/rules/no-duplicate-fields.js +1 -1
  16. package/cjs/rules/no-hashtag-description.js +1 -1
  17. package/cjs/rules/no-one-place-fragments.js +1 -1
  18. package/cjs/rules/no-root-type.js +1 -1
  19. package/cjs/rules/no-scalar-result-type-on-mutation.js +1 -1
  20. package/cjs/rules/no-typename-prefix.js +1 -1
  21. package/cjs/rules/no-unreachable-types.js +1 -1
  22. package/cjs/rules/no-unused-fields.js +1 -1
  23. package/cjs/rules/relay-arguments.js +1 -1
  24. package/cjs/rules/relay-connection-types.js +1 -1
  25. package/cjs/rules/relay-edge-types.js +1 -1
  26. package/cjs/rules/relay-page-info.js +1 -1
  27. package/cjs/rules/require-deprecation-date.js +1 -1
  28. package/cjs/rules/require-deprecation-reason.js +1 -1
  29. package/cjs/rules/require-description.js +1 -1
  30. package/cjs/rules/require-field-of-type-query-in-mutation-result.js +1 -1
  31. package/cjs/rules/require-id-when-available.js +1 -1
  32. package/cjs/rules/require-nullable-fields-with-oneof.js +1 -1
  33. package/cjs/rules/require-type-pattern-with-oneof.js +1 -1
  34. package/cjs/rules/selection-set-depth.js +1 -1
  35. package/cjs/rules/strict-id-in-types.js +1 -1
  36. package/cjs/rules/unique-fragment-name.js +1 -1
  37. package/cjs/rules/unique-operation-name.js +1 -1
  38. package/cjs/siblings.js +113 -0
  39. package/cjs/utils.js +2 -1
  40. package/docs/README.md +1 -85
  41. package/docs/custom-rules.md +1 -184
  42. package/docs/deprecated-rules.md +1 -24
  43. package/docs/parser-options.md +1 -107
  44. package/docs/parser.md +1 -67
  45. package/esm/documents.js +2 -105
  46. package/esm/graphql-config.js +1 -1
  47. package/esm/parser.js +10 -4
  48. package/esm/rules/alphabetize.js +1 -1
  49. package/esm/rules/description-style.js +1 -1
  50. package/esm/rules/graphql-js-validation.js +1 -1
  51. package/esm/rules/input-name.js +4 -4
  52. package/esm/rules/lone-executable-definition.js +1 -1
  53. package/esm/rules/match-document-filename.js +3 -4
  54. package/esm/rules/naming-convention.js +1 -1
  55. package/esm/rules/no-anonymous-operations.js +1 -1
  56. package/esm/rules/no-case-insensitive-enum-values-duplicates.js +1 -1
  57. package/esm/rules/no-deprecated.js +1 -1
  58. package/esm/rules/no-duplicate-fields.js +1 -1
  59. package/esm/rules/no-hashtag-description.js +1 -1
  60. package/esm/rules/no-one-place-fragments.js +1 -1
  61. package/esm/rules/no-root-type.js +1 -1
  62. package/esm/rules/no-scalar-result-type-on-mutation.js +1 -1
  63. package/esm/rules/no-typename-prefix.js +1 -1
  64. package/esm/rules/no-unreachable-types.js +1 -1
  65. package/esm/rules/no-unused-fields.js +1 -1
  66. package/esm/rules/relay-arguments.js +1 -1
  67. package/esm/rules/relay-connection-types.js +1 -1
  68. package/esm/rules/relay-edge-types.js +1 -1
  69. package/esm/rules/relay-page-info.js +1 -1
  70. package/esm/rules/require-deprecation-date.js +1 -1
  71. package/esm/rules/require-deprecation-reason.js +1 -1
  72. package/esm/rules/require-description.js +1 -1
  73. package/esm/rules/require-field-of-type-query-in-mutation-result.js +1 -1
  74. package/esm/rules/require-id-when-available.js +1 -1
  75. package/esm/rules/require-nullable-fields-with-oneof.js +1 -1
  76. package/esm/rules/require-type-pattern-with-oneof.js +1 -1
  77. package/esm/rules/selection-set-depth.js +1 -1
  78. package/esm/rules/strict-id-in-types.js +1 -1
  79. package/esm/rules/unique-fragment-name.js +1 -1
  80. package/esm/rules/unique-operation-name.js +1 -1
  81. package/esm/siblings.js +109 -0
  82. package/esm/utils.js +1 -0
  83. package/package.json +1 -1
  84. package/typings/documents.d.cts +2 -20
  85. package/typings/documents.d.ts +2 -20
  86. package/typings/rules/input-name.d.cts +1 -1
  87. package/typings/rules/input-name.d.ts +1 -1
  88. package/typings/siblings.d.cts +22 -0
  89. package/typings/siblings.d.ts +22 -0
  90. package/typings/types.d.cts +3 -2
  91. package/typings/types.d.ts +3 -2
  92. package/typings/utils.d.cts +2 -1
  93. package/typings/utils.d.ts +2 -1
  94. package/docs/rules/alphabetize.md +0 -194
  95. package/docs/rules/description-style.md +0 -57
  96. package/docs/rules/executable-definitions.md +0 -20
  97. package/docs/rules/fields-on-correct-type.md +0 -23
  98. package/docs/rules/fragments-on-composite-type.md +0 -20
  99. package/docs/rules/input-name.md +0 -80
  100. package/docs/rules/known-argument-names.md +0 -23
  101. package/docs/rules/known-directives.md +0 -48
  102. package/docs/rules/known-fragment-names.md +0 -72
  103. package/docs/rules/known-type-names.md +0 -24
  104. package/docs/rules/lone-anonymous-operation.md +0 -20
  105. package/docs/rules/lone-executable-definition.md +0 -59
  106. package/docs/rules/lone-schema-definition.md +0 -19
  107. package/docs/rules/match-document-filename.md +0 -181
  108. package/docs/rules/naming-convention.md +0 -320
  109. package/docs/rules/no-anonymous-operations.md +0 -43
  110. package/docs/rules/no-case-insensitive-enum-values-duplicates.md +0 -46
  111. package/docs/rules/no-deprecated.md +0 -88
  112. package/docs/rules/no-duplicate-fields.md +0 -69
  113. package/docs/rules/no-fragment-cycles.md +0 -19
  114. package/docs/rules/no-hashtag-description.md +0 -62
  115. package/docs/rules/no-one-place-fragments.md +0 -51
  116. package/docs/rules/no-root-type.md +0 -55
  117. package/docs/rules/no-scalar-result-type-on-mutation.md +0 -39
  118. package/docs/rules/no-typename-prefix.md +0 -42
  119. package/docs/rules/no-undefined-variables.md +0 -20
  120. package/docs/rules/no-unreachable-types.md +0 -52
  121. package/docs/rules/no-unused-fields.md +0 -64
  122. package/docs/rules/no-unused-fragments.md +0 -20
  123. package/docs/rules/no-unused-variables.md +0 -20
  124. package/docs/rules/one-field-subscriptions.md +0 -19
  125. package/docs/rules/overlapping-fields-can-be-merged.md +0 -20
  126. package/docs/rules/possible-fragment-spread.md +0 -21
  127. package/docs/rules/possible-type-extension.md +0 -19
  128. package/docs/rules/provided-required-arguments.md +0 -21
  129. package/docs/rules/relay-arguments.md +0 -59
  130. package/docs/rules/relay-connection-types.md +0 -43
  131. package/docs/rules/relay-edge-types.md +0 -60
  132. package/docs/rules/relay-page-info.md +0 -34
  133. package/docs/rules/require-deprecation-date.md +0 -59
  134. package/docs/rules/require-deprecation-reason.md +0 -49
  135. package/docs/rules/require-description.md +0 -147
  136. package/docs/rules/require-field-of-type-query-in-mutation-result.md +0 -50
  137. package/docs/rules/require-id-when-available.md +0 -91
  138. package/docs/rules/require-nullable-fields-with-oneof.md +0 -38
  139. package/docs/rules/require-type-pattern-with-oneof.md +0 -39
  140. package/docs/rules/scalar-leafs.md +0 -23
  141. package/docs/rules/selection-set-depth.md +0 -86
  142. package/docs/rules/strict-id-in-types.md +0 -129
  143. package/docs/rules/unique-argument-names.md +0 -19
  144. package/docs/rules/unique-directive-names-per-location.md +0 -21
  145. package/docs/rules/unique-directive-names.md +0 -19
  146. package/docs/rules/unique-enum-value-names.md +0 -16
  147. package/docs/rules/unique-field-definition-names.md +0 -19
  148. package/docs/rules/unique-fragment-name.md +0 -52
  149. package/docs/rules/unique-input-field-names.md +0 -19
  150. package/docs/rules/unique-operation-name.md +0 -56
  151. package/docs/rules/unique-operation-types.md +0 -19
  152. package/docs/rules/unique-type-names.md +0 -19
  153. package/docs/rules/unique-variable-names.md +0 -19
  154. package/docs/rules/value-literals-of-correct-type.md +0 -22
  155. package/docs/rules/variables-are-input-types.md +0 -20
  156. package/docs/rules/variables-in-allowed-position.md +0 -19
@@ -27,7 +27,7 @@ exports.rule = {
27
27
  docs: {
28
28
  category: 'Schema',
29
29
  description: 'Disallow using root types `mutation` and/or `subscription`.',
30
- url: 'https://github.com/B2o5T/graphql-eslint/blob/master/docs/rules/no-root-type.md',
30
+ url: 'https://the-guild.dev/graphql/eslint/rules/no-root-type',
31
31
  requiresSchema: true,
32
32
  isDisabledForAllConfig: true,
33
33
  examples: [
@@ -11,7 +11,7 @@ exports.rule = {
11
11
  docs: {
12
12
  category: 'Schema',
13
13
  description: 'Avoid scalar result type on mutation type to make sure to return a valid state.',
14
- url: `https://github.com/B2o5T/graphql-eslint/blob/master/docs/rules/${RULE_ID}.md`,
14
+ url: `https://the-guild.dev/graphql/eslint/rules/${RULE_ID}`,
15
15
  requiresSchema: true,
16
16
  examples: [
17
17
  {
@@ -10,7 +10,7 @@ exports.rule = {
10
10
  category: 'Schema',
11
11
  description: 'Enforces users to avoid using the type name in a field name while defining your schema.',
12
12
  recommended: true,
13
- url: 'https://github.com/B2o5T/graphql-eslint/blob/master/docs/rules/no-typename-prefix.md',
13
+ url: 'https://the-guild.dev/graphql/eslint/rules/no-typename-prefix',
14
14
  examples: [
15
15
  {
16
16
  title: 'Incorrect',
@@ -93,7 +93,7 @@ exports.rule = {
93
93
  docs: {
94
94
  description: 'Requires all types to be reachable at some level by root level fields.',
95
95
  category: 'Schema',
96
- url: `https://github.com/B2o5T/graphql-eslint/blob/master/docs/rules/${RULE_ID}.md`,
96
+ url: `https://the-guild.dev/graphql/eslint/rules/${RULE_ID}`,
97
97
  requiresSchema: true,
98
98
  examples: [
99
99
  {
@@ -42,7 +42,7 @@ exports.rule = {
42
42
  docs: {
43
43
  description: 'Requires all fields to be used at some level by siblings operations.',
44
44
  category: 'Schema',
45
- url: `https://github.com/B2o5T/graphql-eslint/blob/master/docs/rules/${RULE_ID}.md`,
45
+ url: `https://the-guild.dev/graphql/eslint/rules/${RULE_ID}`,
46
46
  requiresSiblings: true,
47
47
  requiresSchema: true,
48
48
  isDisabledForAllConfig: true,
@@ -41,7 +41,7 @@ exports.rule = {
41
41
  '- `last` takes a non-negative integer',
42
42
  '- `before` takes the Cursor type',
43
43
  ].join('\n'),
44
- url: `https://github.com/B2o5T/graphql-eslint/blob/master/docs/rules/${RULE_ID}.md`,
44
+ url: `https://the-guild.dev/graphql/eslint/rules/${RULE_ID}`,
45
45
  examples: [
46
46
  {
47
47
  title: 'Incorrect',
@@ -35,7 +35,7 @@ exports.rule = {
35
35
  '- Connection type must contain a field `edges` that return a list type that wraps an edge type',
36
36
  '- Connection type must contain a field `pageInfo` that return a non-null `PageInfo` Object type',
37
37
  ].join('\n'),
38
- url: 'https://github.com/B2o5T/graphql-eslint/blob/master/docs/rules/relay-connection-types.md',
38
+ url: 'https://the-guild.dev/graphql/eslint/rules/relay-connection-types',
39
39
  isDisabledForAllConfig: true,
40
40
  examples: [
41
41
  {
@@ -82,7 +82,7 @@ exports.rule = {
82
82
  "- Edge type's field `node` must implement `Node` interface _(optional)_",
83
83
  '- A list type should only wrap an edge type _(optional)_',
84
84
  ].join('\n'),
85
- url: `https://github.com/B2o5T/graphql-eslint/blob/master/docs/rules/${RULE_ID}.md`,
85
+ url: `https://the-guild.dev/graphql/eslint/rules/${RULE_ID}`,
86
86
  isDisabledForAllConfig: true,
87
87
  requiresSchema: true,
88
88
  examples: [
@@ -21,7 +21,7 @@ exports.rule = {
21
21
  '- `PageInfo` must contain fields `hasPreviousPage` and `hasNextPage`, that return non-null Boolean',
22
22
  '- `PageInfo` must contain fields `startCursor` and `endCursor`, that return either String or Scalar, which can be null if there are no results',
23
23
  ].join('\n'),
24
- url: `https://github.com/B2o5T/graphql-eslint/blob/master/docs/rules/${RULE_ID}.md`,
24
+ url: `https://the-guild.dev/graphql/eslint/rules/${RULE_ID}`,
25
25
  examples: [
26
26
  {
27
27
  title: 'Correct',
@@ -28,7 +28,7 @@ exports.rule = {
28
28
  docs: {
29
29
  category: 'Schema',
30
30
  description: 'Require deletion date on `@deprecated` directive. Suggest removing deprecated things after deprecated date.',
31
- url: 'https://github.com/B2o5T/graphql-eslint/blob/master/docs/rules/require-deprecation-date.md',
31
+ url: 'https://the-guild.dev/graphql/eslint/rules/require-deprecation-date',
32
32
  examples: [
33
33
  {
34
34
  title: 'Incorrect',
@@ -7,7 +7,7 @@ exports.rule = {
7
7
  docs: {
8
8
  description: 'Require all deprecation directives to specify a reason.',
9
9
  category: 'Schema',
10
- url: 'https://github.com/B2o5T/graphql-eslint/blob/master/docs/rules/require-deprecation-reason.md',
10
+ url: 'https://the-guild.dev/graphql/eslint/rules/require-deprecation-reason',
11
11
  recommended: true,
12
12
  examples: [
13
13
  {
@@ -74,7 +74,7 @@ exports.rule = {
74
74
  docs: {
75
75
  category: 'Schema',
76
76
  description: 'Enforce descriptions in type definitions and operations.',
77
- url: `https://github.com/B2o5T/graphql-eslint/blob/master/docs/rules/${RULE_ID}.md`,
77
+ url: `https://the-guild.dev/graphql/eslint/rules/${RULE_ID}`,
78
78
  examples: [
79
79
  {
80
80
  title: 'Incorrect',
@@ -10,7 +10,7 @@ exports.rule = {
10
10
  docs: {
11
11
  category: 'Schema',
12
12
  description: 'Allow the client in one round-trip not only to call mutation but also to get a wagon of data to update their application.\n> Currently, no errors are reported for result type `union`, `interface` and `scalar`.',
13
- url: `https://github.com/B2o5T/graphql-eslint/blob/master/docs/rules/${RULE_ID}.md`,
13
+ url: `https://the-guild.dev/graphql/eslint/rules/${RULE_ID}`,
14
14
  requiresSchema: true,
15
15
  examples: [
16
16
  {
@@ -34,7 +34,7 @@ exports.rule = {
34
34
  docs: {
35
35
  category: 'Operations',
36
36
  description: 'Enforce selecting specific fields when they are available on the GraphQL type.',
37
- url: `https://github.com/B2o5T/graphql-eslint/blob/master/docs/rules/${RULE_ID}.md`,
37
+ url: `https://the-guild.dev/graphql/eslint/rules/${RULE_ID}`,
38
38
  requiresSchema: true,
39
39
  requiresSiblings: true,
40
40
  examples: [
@@ -9,7 +9,7 @@ exports.rule = {
9
9
  docs: {
10
10
  category: 'Schema',
11
11
  description: 'Require `input` or `type` fields to be non-nullable with `@oneOf` directive.',
12
- url: `https://github.com/B2o5T/graphql-eslint/blob/master/docs/rules/${RULE_ID}.md`,
12
+ url: `https://the-guild.dev/graphql/eslint/rules/${RULE_ID}`,
13
13
  examples: [
14
14
  {
15
15
  title: 'Incorrect',
@@ -8,7 +8,7 @@ exports.rule = {
8
8
  docs: {
9
9
  category: 'Schema',
10
10
  description: 'Enforce types with `@oneOf` directive have `error` and `ok` fields.',
11
- url: `https://github.com/B2o5T/graphql-eslint/blob/master/docs/rules/${RULE_ID}.md`,
11
+ url: `https://the-guild.dev/graphql/eslint/rules/${RULE_ID}`,
12
12
  examples: [
13
13
  {
14
14
  title: 'Correct',
@@ -29,7 +29,7 @@ exports.rule = {
29
29
  docs: {
30
30
  category: 'Operations',
31
31
  description: 'Limit the complexity of the GraphQL operations solely by their depth. Based on [graphql-depth-limit](https://npmjs.com/package/graphql-depth-limit).',
32
- url: `https://github.com/B2o5T/graphql-eslint/blob/master/docs/rules/${RULE_ID}.md`,
32
+ url: `https://the-guild.dev/graphql/eslint/rules/${RULE_ID}`,
33
33
  requiresSiblings: true,
34
34
  examples: [
35
35
  {
@@ -43,7 +43,7 @@ exports.rule = {
43
43
  description: 'Requires output types to have one unique identifier unless they do not have a logical one. Exceptions can be used to ignore output types that do not have unique identifiers.',
44
44
  category: 'Schema',
45
45
  recommended: true,
46
- url: `https://github.com/B2o5T/graphql-eslint/blob/master/docs/rules/${RULE_ID}.md`,
46
+ url: `https://the-guild.dev/graphql/eslint/rules/${RULE_ID}`,
47
47
  requiresSchema: true,
48
48
  examples: [
49
49
  {
@@ -39,7 +39,7 @@ exports.rule = {
39
39
  docs: {
40
40
  category: 'Operations',
41
41
  description: 'Enforce unique fragment names across your project.',
42
- url: `https://github.com/B2o5T/graphql-eslint/blob/master/docs/rules/${RULE_ID}.md`,
42
+ url: `https://the-guild.dev/graphql/eslint/rules/${RULE_ID}`,
43
43
  requiresSiblings: true,
44
44
  examples: [
45
45
  {
@@ -9,7 +9,7 @@ exports.rule = {
9
9
  docs: {
10
10
  category: 'Operations',
11
11
  description: 'Enforce unique operation names across your project.',
12
- url: `https://github.com/B2o5T/graphql-eslint/blob/master/docs/rules/${RULE_ID}.md`,
12
+ url: `https://the-guild.dev/graphql/eslint/rules/${RULE_ID}`,
13
13
  requiresSiblings: true,
14
14
  examples: [
15
15
  {
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getSiblings = void 0;
4
+ const utils_1 = require("@graphql-tools/utils");
5
+ const graphql_1 = require("graphql");
6
+ const documents_js_1 = require("./documents.js");
7
+ const utils_js_1 = require("./utils.js");
8
+ const siblingOperationsCache = new Map();
9
+ function getSiblings(project, documents) {
10
+ const siblings = project
11
+ ? (0, documents_js_1.getDocuments)(project)
12
+ : typeof documents === 'string'
13
+ ? [(0, utils_1.parseGraphQLSDL)('operation.graphql', documents, { noLocation: true })]
14
+ : [];
15
+ if (siblings.length === 0) {
16
+ let printed = false;
17
+ const noopWarn = () => {
18
+ if (!printed) {
19
+ utils_js_1.logger.warn('getSiblingOperations was called without any operations. Make sure to set "parserOptions.operations" to make this feature available!');
20
+ printed = true;
21
+ }
22
+ return [];
23
+ };
24
+ return {
25
+ available: false,
26
+ getFragment: noopWarn,
27
+ getFragments: noopWarn,
28
+ getFragmentByType: noopWarn,
29
+ getFragmentsInUse: noopWarn,
30
+ getOperation: noopWarn,
31
+ getOperations: noopWarn,
32
+ getOperationByType: noopWarn,
33
+ };
34
+ }
35
+ // Since the siblings array is cached, we can use it as cache key.
36
+ // We should get the same array reference each time we get
37
+ // to this point for the same graphql project
38
+ const value = siblingOperationsCache.get(siblings);
39
+ if (value) {
40
+ return value;
41
+ }
42
+ let fragmentsCache = null;
43
+ const getFragments = () => {
44
+ var _a;
45
+ if (fragmentsCache === null) {
46
+ const result = [];
47
+ for (const source of siblings) {
48
+ for (const definition of ((_a = source.document) === null || _a === void 0 ? void 0 : _a.definitions) || []) {
49
+ if (definition.kind === graphql_1.Kind.FRAGMENT_DEFINITION) {
50
+ result.push({
51
+ filePath: source.location,
52
+ document: definition,
53
+ });
54
+ }
55
+ }
56
+ }
57
+ fragmentsCache = result;
58
+ }
59
+ return fragmentsCache;
60
+ };
61
+ let cachedOperations = null;
62
+ const getOperations = () => {
63
+ var _a;
64
+ if (cachedOperations === null) {
65
+ const result = [];
66
+ for (const source of siblings) {
67
+ for (const definition of ((_a = source.document) === null || _a === void 0 ? void 0 : _a.definitions) || []) {
68
+ if (definition.kind === graphql_1.Kind.OPERATION_DEFINITION) {
69
+ result.push({
70
+ filePath: source.location,
71
+ document: definition,
72
+ });
73
+ }
74
+ }
75
+ }
76
+ cachedOperations = result;
77
+ }
78
+ return cachedOperations;
79
+ };
80
+ const getFragment = (name) => getFragments().filter(f => { var _a; return ((_a = f.document.name) === null || _a === void 0 ? void 0 : _a.value) === name; });
81
+ const collectFragments = (selectable, recursive, collected = new Map()) => {
82
+ (0, graphql_1.visit)(selectable, {
83
+ FragmentSpread(spread) {
84
+ const fragmentName = spread.name.value;
85
+ const [fragment] = getFragment(fragmentName);
86
+ if (!fragment) {
87
+ utils_js_1.logger.warn(`Unable to locate fragment named "${fragmentName}", please make sure it's loaded using "parserOptions.operations"`);
88
+ return;
89
+ }
90
+ if (!collected.has(fragmentName)) {
91
+ collected.set(fragmentName, fragment.document);
92
+ if (recursive) {
93
+ collectFragments(fragment.document, recursive, collected);
94
+ }
95
+ }
96
+ },
97
+ });
98
+ return collected;
99
+ };
100
+ const siblingOperations = {
101
+ available: true,
102
+ getFragment,
103
+ getFragments,
104
+ getFragmentByType: typeName => getFragments().filter(f => { var _a, _b; return ((_b = (_a = f.document.typeCondition) === null || _a === void 0 ? void 0 : _a.name) === null || _b === void 0 ? void 0 : _b.value) === typeName; }),
105
+ getFragmentsInUse: (selectable, recursive = true) => Array.from(collectFragments(selectable, recursive).values()),
106
+ getOperation: name => getOperations().filter(o => { var _a; return ((_a = o.document.name) === null || _a === void 0 ? void 0 : _a.value) === name; }),
107
+ getOperations,
108
+ getOperationByType: type => getOperations().filter(o => o.document.operation === type),
109
+ };
110
+ siblingOperationsCache.set(siblings, siblingOperations);
111
+ return siblingOperations;
112
+ }
113
+ exports.getSiblings = getSiblings;
package/cjs/utils.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.truthy = exports.englishJoinWords = exports.ARRAY_DEFAULT_OPTIONS = exports.REPORT_ON_FIRST_CHARACTER = exports.getLocation = exports.convertCase = exports.camelCase = exports.pascalCase = exports.TYPES_KINDS = exports.getTypeName = exports.CWD = exports.VIRTUAL_DOCUMENT_REGEX = exports.normalizePath = exports.logger = exports.requireGraphQLSchemaFromContext = exports.requireSiblingsOperations = void 0;
3
+ exports.truthy = exports.englishJoinWords = exports.ARRAY_DEFAULT_OPTIONS = exports.REPORT_ON_FIRST_CHARACTER = exports.getLocation = exports.convertCase = exports.camelCase = exports.pascalCase = exports.TYPES_KINDS = exports.getTypeName = exports.IS_BROWSER = exports.CWD = exports.VIRTUAL_DOCUMENT_REGEX = exports.normalizePath = exports.logger = exports.requireGraphQLSchemaFromContext = exports.requireSiblingsOperations = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const chalk_1 = tslib_1.__importDefault(require("chalk"));
6
6
  const graphql_1 = require("graphql");
@@ -36,6 +36,7 @@ const normalizePath = (path) => (path || '').replace(/\\/g, '/');
36
36
  exports.normalizePath = normalizePath;
37
37
  exports.VIRTUAL_DOCUMENT_REGEX = /\/\d+_document.graphql$/;
38
38
  exports.CWD = process.cwd();
39
+ exports.IS_BROWSER = typeof window !== 'undefined';
39
40
  const getTypeName = (node) => 'type' in node ? (0, exports.getTypeName)(node.type) : 'name' in node && node.name ? node.name.value : '';
40
41
  exports.getTypeName = getTypeName;
41
42
  exports.TYPES_KINDS = [
package/docs/README.md CHANGED
@@ -1,85 +1 @@
1
- # Available Rules
2
-
3
- Each rule has emojis denoting:
4
-
5
- - 📄 if the rule applies to schema documents
6
- - 📦 if the rule applies to operations
7
- - 🚀 `graphql-eslint` rule
8
- - 🔮 `graphql-js` rule
9
- - 🔧 if some problems reported by the rule are automatically fixable by the `--fix`
10
- [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) option
11
- - 💡 if some problems reported by the rule are manually fixable by editor
12
- [suggestions](https://eslint.org/docs/developer-guide/working-with-rules#providing-suggestions)
13
-
14
- <!-- 🚨 IMPORTANT! Do not manually modify this table. Run: `yarn generate:docs` -->
15
- <!-- prettier-ignore-start -->
16
- Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|Description|&nbsp;&nbsp;&nbsp;&nbsp;Config&nbsp;&nbsp;&nbsp;&nbsp;|📄&nbsp;/&nbsp;📦|🚀&nbsp;/&nbsp;🔮|🔧&nbsp;/&nbsp;💡
17
- -|-|:-:|:-:|:-:|:-:
18
- [alphabetize](rules/alphabetize.md)|Enforce arrange in alphabetical order for type fields, enum values, input object fields, operation selections and more.|![all][]|📄 📦|🚀|🔧
19
- [description-style](rules/description-style.md)|Require all comments to follow the same style (either block or inline).|![recommended][]|📄|🚀|💡
20
- [executable-definitions](rules/executable-definitions.md)|A GraphQL document is only valid for execution if all definitions are either operation or fragment definitions.|![recommended][]|📦|🔮|
21
- [fields-on-correct-type](rules/fields-on-correct-type.md)|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`.|![recommended][]|📦|🔮|💡
22
- [fragments-on-composite-type](rules/fragments-on-composite-type.md)|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.|![recommended][]|📦|🔮|
23
- [input-name](rules/input-name.md)|Require mutation argument to be always called "input" and input type to be called Mutation name + "Input".|![all][]|📄|🚀|💡
24
- [known-argument-names](rules/known-argument-names.md)|A GraphQL field is only valid if all supplied arguments are defined by that field.|![recommended][]|📄 📦|🔮|💡
25
- [known-directives](rules/known-directives.md)|A GraphQL document is only valid if all `@directive`s are known by the schema and legally positioned.|![recommended][]|📄 📦|🔮|
26
- [known-fragment-names](rules/known-fragment-names.md)|A GraphQL document is only valid if all `...Fragment` fragment spreads refer to fragments defined in the same document.|![recommended][]|📦|🔮|
27
- [known-type-names](rules/known-type-names.md)|A GraphQL document is only valid if referenced types (specifically variable definitions and fragment conditions) are defined by the type schema.|![recommended][]|📄 📦|🔮|💡
28
- [lone-anonymous-operation](rules/lone-anonymous-operation.md)|A GraphQL document that contains an anonymous operation (the `query` short-hand) is only valid if it contains only that one operation definition.|![recommended][]|📦|🔮|
29
- [lone-executable-definition](rules/lone-executable-definition.md)|Require queries, mutations, subscriptions or fragments to be located in separate files.|![all][]|📦|🚀|
30
- [lone-schema-definition](rules/lone-schema-definition.md)|A GraphQL document is only valid if it contains only one schema definition.|![recommended][]|📄|🔮|
31
- [match-document-filename](rules/match-document-filename.md)|This rule allows you to enforce that the file name should match the operation name.|![all][]|📦|🚀|
32
- [naming-convention](rules/naming-convention.md)|Require names to follow specified conventions.|![recommended][]|📄 📦|🚀|💡
33
- [no-anonymous-operations](rules/no-anonymous-operations.md)|Require name for your GraphQL operations. This is useful since most GraphQL client libraries are using the operation name for caching purposes.|![recommended][]|📦|🚀|💡
34
- [no-case-insensitive-enum-values-duplicates](rules/no-case-insensitive-enum-values-duplicates.md)|Disallow case-insensitive enum values duplicates.|![recommended][]|📄|🚀|💡
35
- [no-deprecated](rules/no-deprecated.md)|Enforce that deprecated fields or enum values are not in use by operations.|![recommended][]|📦|🚀|💡
36
- [no-duplicate-fields](rules/no-duplicate-fields.md)|Checks for duplicate fields in selection set, variables in operation definition, or in arguments set of a field.|![recommended][]|📦|🚀|💡
37
- [no-fragment-cycles](rules/no-fragment-cycles.md)|A GraphQL fragment is only valid when it does not have cycles in fragments usage.|![recommended][]|📦|🔮|
38
- [no-hashtag-description](rules/no-hashtag-description.md)|Requires to use `"""` or `"` for adding a GraphQL description instead of `#`.|![recommended][]|📄|🚀|💡
39
- [no-one-place-fragments](rules/no-one-place-fragments.md)|Disallow fragments that are used only in one place.|![all][]|📦|🚀|
40
- [no-root-type](rules/no-root-type.md)|Disallow using root types `mutation` and/or `subscription`.||📄|🚀|💡
41
- [no-scalar-result-type-on-mutation](rules/no-scalar-result-type-on-mutation.md)|Avoid scalar result type on mutation type to make sure to return a valid state.|![all][]|📄|🚀|💡
42
- [no-typename-prefix](rules/no-typename-prefix.md)|Enforces users to avoid using the type name in a field name while defining your schema.|![recommended][]|📄|🚀|💡
43
- [no-undefined-variables](rules/no-undefined-variables.md)|A GraphQL operation is only valid if all variables encountered, both directly and via fragment spreads, are defined by that operation.|![recommended][]|📦|🔮|
44
- [no-unreachable-types](rules/no-unreachable-types.md)|Requires all types to be reachable at some level by root level fields.|![recommended][]|📄|🚀|💡
45
- [no-unused-fields](rules/no-unused-fields.md)|Requires all fields to be used at some level by siblings operations.||📄|🚀|💡
46
- [no-unused-fragments](rules/no-unused-fragments.md)|A GraphQL document is only valid if all fragment definitions are spread within operations, or spread within other fragments spread within operations.|![recommended][]|📦|🔮|
47
- [no-unused-variables](rules/no-unused-variables.md)|A GraphQL operation is only valid if all variables defined by an operation are used, either directly or within a spread fragment.|![recommended][]|📦|🔮|
48
- [one-field-subscriptions](rules/one-field-subscriptions.md)|A GraphQL subscription is valid only if it contains a single root field.|![recommended][]|📦|🔮|
49
- [overlapping-fields-can-be-merged](rules/overlapping-fields-can-be-merged.md)|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.|![recommended][]|📦|🔮|
50
- [possible-fragment-spread](rules/possible-fragment-spread.md)|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.|![recommended][]|📦|🔮|
51
- [possible-type-extension](rules/possible-type-extension.md)|A type extension is only valid if the type is defined and has the same kind.||📄|🔮|💡
52
- [provided-required-arguments](rules/provided-required-arguments.md)|A field or directive is only valid if all required (non-null without a default value) field arguments have been provided.|![recommended][]|📄 📦|🔮|
53
- [relay-arguments](rules/relay-arguments.md)|Set of rules to follow Relay specification for Arguments.|![relay][]|📄|🚀|
54
- [relay-connection-types](rules/relay-connection-types.md)|Set of rules to follow Relay specification for Connection types.|![relay][]|📄|🚀|
55
- [relay-edge-types](rules/relay-edge-types.md)|Set of rules to follow Relay specification for Edge types.|![relay][]|📄|🚀|
56
- [relay-page-info](rules/relay-page-info.md)|Set of rules to follow Relay specification for `PageInfo` object.|![relay][]|📄|🚀|
57
- [require-deprecation-date](rules/require-deprecation-date.md)|Require deletion date on `@deprecated` directive. Suggest removing deprecated things after deprecated date.|![all][]|📄|🚀|💡
58
- [require-deprecation-reason](rules/require-deprecation-reason.md)|Require all deprecation directives to specify a reason.|![recommended][]|📄|🚀|
59
- [require-description](rules/require-description.md)|Enforce descriptions in type definitions and operations.|![recommended][]|📄|🚀|
60
- [require-field-of-type-query-in-mutation-result](rules/require-field-of-type-query-in-mutation-result.md)|Allow the client in one round-trip not only to call mutation but also to get a wagon of data to update their application.|![all][]|📄|🚀|
61
- [require-id-when-available](rules/require-id-when-available.md)|Enforce selecting specific fields when they are available on the GraphQL type.|![recommended][]|📦|🚀|💡
62
- [require-nullable-fields-with-oneof](rules/require-nullable-fields-with-oneof.md)|Require `input` or `type` fields to be non-nullable with `@oneOf` directive.|![all][]|📄|🚀|
63
- [require-type-pattern-with-oneof](rules/require-type-pattern-with-oneof.md)|Enforce types with `@oneOf` directive have `error` and `ok` fields.|![all][]|📄|🚀|
64
- [scalar-leafs](rules/scalar-leafs.md)|A GraphQL document is valid only if all leaf fields (fields without sub selections) are of scalar or enum types.|![recommended][]|📦|🔮|💡
65
- [selection-set-depth](rules/selection-set-depth.md)|Limit the complexity of the GraphQL operations solely by their depth. Based on [graphql-depth-limit](https://npmjs.com/package/graphql-depth-limit).|![recommended][]|📦|🚀|💡
66
- [strict-id-in-types](rules/strict-id-in-types.md)|Requires output types to have one unique identifier unless they do not have a logical one. Exceptions can be used to ignore output types that do not have unique identifiers.|![recommended][]|📄|🚀|
67
- [unique-argument-names](rules/unique-argument-names.md)|A GraphQL field or directive is only valid if all supplied arguments are uniquely named.|![recommended][]|📦|🔮|
68
- [unique-directive-names](rules/unique-directive-names.md)|A GraphQL document is only valid if all defined directives have unique names.|![recommended][]|📄|🔮|
69
- [unique-directive-names-per-location](rules/unique-directive-names-per-location.md)|A GraphQL document is only valid if all non-repeatable directives at a given location are uniquely named.|![recommended][]|📄 📦|🔮|
70
- [unique-enum-value-names](rules/unique-enum-value-names.md)|A GraphQL enum type is only valid if all its values are uniquely named.||📄|🔮|
71
- [unique-field-definition-names](rules/unique-field-definition-names.md)|A GraphQL complex type is only valid if all its fields are uniquely named.|![recommended][]|📄|🔮|
72
- [unique-fragment-name](rules/unique-fragment-name.md)|Enforce unique fragment names across your project.|![all][]|📦|🚀|
73
- [unique-input-field-names](rules/unique-input-field-names.md)|A GraphQL input object value is only valid if all supplied fields are uniquely named.|![recommended][]|📦|🔮|
74
- [unique-operation-name](rules/unique-operation-name.md)|Enforce unique operation names across your project.|![all][]|📦|🚀|
75
- [unique-operation-types](rules/unique-operation-types.md)|A GraphQL document is only valid if it has only one type per operation.|![recommended][]|📄|🔮|
76
- [unique-type-names](rules/unique-type-names.md)|A GraphQL document is only valid if all defined types have unique names.|![recommended][]|📄|🔮|
77
- [unique-variable-names](rules/unique-variable-names.md)|A GraphQL operation is only valid if all its variables are uniquely named.|![recommended][]|📦|🔮|
78
- [value-literals-of-correct-type](rules/value-literals-of-correct-type.md)|A GraphQL document is only valid if all value literals are of the type expected at their position.|![recommended][]|📦|🔮|💡
79
- [variables-are-input-types](rules/variables-are-input-types.md)|A GraphQL operation is only valid if all the variables it defines are of input types (scalar, enum, or input object).|![recommended][]|📦|🔮|
80
- [variables-in-allowed-position](rules/variables-in-allowed-position.md)|Variables passed to field arguments conform to type.|![recommended][]|📦|🔮|
81
- <!-- prettier-ignore-end -->
82
-
83
- [recommended]: https://img.shields.io/badge/-recommended-green.svg
84
- [all]: https://img.shields.io/badge/-all-blue.svg
85
- [relay]: https://img.shields.io/badge/-relay-orange.svg
1
+ website/src/pages/rules/index.mdx
@@ -1,184 +1 @@
1
- # Writing Custom Rules
2
-
3
- To get started with your own rules, start by understanding how
4
- [ESLint custom rules works](https://eslint.org/docs/developer-guide/working-with-rules).
5
-
6
- `graphql-eslint` converts the [GraphQL AST](https://graphql.org/graphql-js/language) into
7
- [ESTree structure](https://github.com/estree/estree), so it allows you to easily travel the GraphQL
8
- AST tree easily.
9
-
10
- You can visit any GraphQL AST node in your custom rules, and report this as error. You don't need to
11
- have special handlers for code-files, since `graphql-eslint` extracts usages of `gql` and magic
12
- `/* GraphQL */` comments automatically, and runs it through the parser, and eventually it knows to
13
- adjust errors location to fit in your code files original location.
14
-
15
- You can explore the GraphQL AST for a given input on
16
- [astexplorer.net](https://astexplorer.net/#/gist/e72aaccc1e57cbba41659d73cabbf75c/f10ee29317a31ff8012a21762a382c4a03c34d40).
17
-
18
- ## Getting Started
19
-
20
- Start by creating a
21
- [simple ESLint rule file](https://eslint.org/docs/developer-guide/working-with-rules), and choose
22
- the AST nodes you wish to visit. It can either be a
23
- [simple AST node `Kind`](https://github.com/graphql/graphql-js/blob/master/src/language/kinds.d.ts)
24
- or a complex [ESLint selector](https://eslint.org/docs/developer-guide/selectors) that allows you to
25
- travel and filter AST nodes.
26
-
27
- We recommend you to read the [graphql-eslint parser documentation](parser.md) before getting
28
- started, to understand the differences between the AST structures.
29
-
30
- The `graphql-eslint` comes with a TypeScript wrapper for ESLint rules, and provides a testkit to
31
- simplify testing process with GraphQL schemas, so you can use that by importing `GraphQLESLintRule`
32
- type. But if you wish to use JavaScript - that's fine :)
33
-
34
- Here's an example for a simple rule that reports on anonymous GraphQL operations:
35
-
36
- ```ts
37
- import { GraphQLESLintRule } from '@graphql-eslint/eslint-plugin'
38
-
39
- const rule: GraphQLESLintRule = {
40
- create(context) {
41
- return {
42
- OperationDefinition(node) {
43
- if (!node.name?.value) {
44
- context.report({
45
- node,
46
- message: 'Oops, name is required!'
47
- })
48
- }
49
- }
50
- }
51
- }
52
- }
53
- ```
54
-
55
- So what happens here?
56
-
57
- 1. `@graphql-eslint/eslint-plugin` handles the parsing process for your GraphQL content. It will
58
- load the GraphQL files (either from code files or from `.graphql` files with SDL), parse it using
59
- GraphQL parser, converts it to ESTree structure and let ESLint do the rest.
60
- 1. Your rule is being loaded by ESLint, and executes just like any other ESLint rule.
61
- 1. Our custom rule asks ESLint to run our function for every `OperationDefinition` found.
62
- 1. If the `OperationDefinition` node doesn't have a valid `name` - we report an error to ESLint.
63
-
64
- #### More Examples
65
-
66
- You can scan the `packages/plugin/src/rules` directory in this repo for references for implementing
67
- rules. It coverts most of the use-cases and concepts of rules.
68
-
69
- ## Accessing original GraphQL AST nodes
70
-
71
- Since our parser converts GraphQL AST to ESTree structure, there are some minor differences in the
72
- structure of the objects. If you are using TypeScript, and you typed your rule with
73
- `GraphQLESLintRule` - you'll see that each `node` is a bit different from the AST nodes of GraphQL
74
- (you can read more about that in [graphql-eslint parser documentation](parser.md)).
75
-
76
- If you need access to the original GraphQL AST `node`, you can use `.rawNode()` method on each node
77
- you get from the AST structure of ESLint.
78
-
79
- This is useful if you wish to use other GraphQL tools that works with the original GraphQL AST
80
- objects.
81
-
82
- Here's an example for using original `graphql-js` validate method to validate `OperationDefinition`:
83
-
84
- ```ts
85
- import { requireGraphQLSchemaFromContext } from '@graphql-eslint/eslint-plugin'
86
- import { validate } from 'graphql'
87
-
88
- export const rule = {
89
- create(context) {
90
- return {
91
- OperationDefinition(node) {
92
- const schema = requireGraphQLSchemaFromContext(context)
93
-
94
- validate(context, schema, {
95
- kind: Kind.DOCUMENT,
96
- definitions: [node.rawNode()]
97
- })
98
- }
99
- }
100
- }
101
- }
102
- ```
103
-
104
- ## `TypeInfo` / `GraphQLSchema`
105
-
106
- If you provide GraphQL schema in your ESLint configuration, it will get loaded automatically, and
107
- become available in your rules in two ways:
108
-
109
- 1. You'll be able to access the loaded `GraphQLSchema` object.
110
- 2. In every visited node, you'll be able to use `.typeInfo()` method to get an object with complete
111
- type information on your visited node (see
112
- [TypeInfo documentation](https://graphql.org/graphql-js/utilities/#typeinfo)).
113
-
114
- #### Getting `GraphQLSchema`
115
-
116
- To mark your ESLint rules as a rule that needs access to GraphQL schema, start by running
117
- `requireGraphQLSchemaFromContext` from the plugin package, it will make sure to return a schema, or
118
- throw an error for the user about the missing schema.
119
-
120
- ```ts
121
- const schema = requireGraphQLSchemaFromContext(context)
122
- ```
123
-
124
- #### Accessing TypeInfo
125
-
126
- If schema is provided and loaded successfully, the `typeInfo` will be available to use. Otherwise -
127
- it will be `undefined`. If your plugin requires `typeInfo` in order to operate and run, make sure to
128
- call `requireGraphQLSchemaFromContext` - it will validate that the schema is loaded.
129
-
130
- `typeInfo` is provided on every node, based on the type of that node, for example, to access the
131
- `GraphQLOutputType` while you are visiting a `SelectionSet` node, you can do:
132
-
133
- ```ts
134
- import { requireGraphQLSchemaFromContext } from '@graphql-eslint/eslint-plugin'
135
-
136
- export const rule = {
137
- create(context) {
138
- requireGraphQLSchemaFromContext('your-rule-name', context)
139
-
140
- return {
141
- SelectionSet(node) {
142
- const typeInfo = node.typeInfo()
143
- if (typeInfo.gqlType) {
144
- console.log(`The GraphQLOutputType is: ${typeInfo.gqlType}`)
145
- }
146
- }
147
- }
148
- }
149
- }
150
- ```
151
-
152
- The structure of the return value of `.typeInfo()` is
153
- [defined here](https://github.com/B2o5T/graphql-eslint/blob/master/packages/plugin/src/estree-converter/converter.ts#L32-L40).
154
- So based on the `node` you are using, you'll get a different values on `.typeInfo()` result.
155
-
156
- ## Testing your rules
157
-
158
- To test your rules, you can either use the wrapped `GraphQLRuleTester` from this library, or use the
159
- built-it [`RuleTester`](https://eslint.org/docs/developer-guide/working-with-rules#rule-unit-tests)
160
- of ESLint.
161
-
162
- The wrapped `GraphQLRuleTester` provides built-in configured parser, and a schema loader, if you
163
- need to test your rule with a loaded schema.
164
-
165
- ```ts
166
- import { GraphQLRuleTester } from '@graphql-eslint/eslint-plugin'
167
- import { rule } from './my-rule'
168
-
169
- const ruleTester = new GraphQLRuleTester()
170
-
171
- ruleTester.runGraphQLTests('my-rule', rule, {
172
- valid: [
173
- {
174
- code: 'query something { foo }'
175
- }
176
- ],
177
- invalid: [
178
- {
179
- code: 'query invalid { foo }',
180
- errors: [{ message: 'Your error message.' }]
181
- }
182
- ]
183
- })
184
- ```
1
+ website/src/pages/docs/custom-rules.mdx