@graphql-eslint/eslint-plugin 4.1.0-alpha-20241129085030-b075ada387ad44de7944517af78877c45bc8fd3b → 4.1.1-alpha-20241129095718-0cc689c0eb8b65d162f4c6d87030879fe63a105b

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.
package/cjs/index.d.cts CHANGED
@@ -98,10 +98,10 @@ declare const _default: {
98
98
  style?: ("camelCase" | "PascalCase" | "snake_case" | "UPPER_CASE") | undefined;
99
99
  suffix?: string | undefined;
100
100
  prefix?: string | undefined;
101
- forbiddenPattern?: {
101
+ forbiddenPatterns?: {
102
102
  [x: string]: unknown;
103
103
  }[] | undefined;
104
- requiredPattern?: {
104
+ requiredPatterns?: {
105
105
  [x: string]: unknown;
106
106
  }[] | undefined;
107
107
  forbiddenPrefixes?: string[] | undefined;
package/cjs/meta.js CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});const version = "4.1.0-alpha-20241129085030-b075ada387ad44de7944517af78877c45bc8fd3b";
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});const version = "4.1.1-alpha-20241129095718-0cc689c0eb8b65d162f4c6d87030879fe63a105b";
2
2
 
3
3
 
4
4
  exports.version = version;
@@ -61,10 +61,10 @@ declare const rules: {
61
61
  style?: ("camelCase" | "PascalCase" | "snake_case" | "UPPER_CASE") | undefined;
62
62
  suffix?: string | undefined;
63
63
  prefix?: string | undefined;
64
- forbiddenPattern?: {
64
+ forbiddenPatterns?: {
65
65
  [x: string]: unknown;
66
66
  }[] | undefined;
67
- requiredPattern?: {
67
+ requiredPatterns?: {
68
68
  [x: string]: unknown;
69
69
  }[] | undefined;
70
70
  forbiddenPrefixes?: string[] | undefined;
@@ -28,7 +28,7 @@ declare const schema: {
28
28
  readonly suffix: {
29
29
  readonly type: "string";
30
30
  };
31
- readonly forbiddenPattern: {
31
+ readonly forbiddenPatterns: {
32
32
  readonly items: {
33
33
  readonly type: "object";
34
34
  };
@@ -37,7 +37,7 @@ declare const schema: {
37
37
  readonly uniqueItems: true;
38
38
  readonly minItems: 1;
39
39
  };
40
- readonly requiredPattern: {
40
+ readonly requiredPatterns: {
41
41
  readonly items: {
42
42
  readonly type: "object";
43
43
  };
@@ -47,14 +47,14 @@ const KindToDisplayName = {
47
47
  style: { enum: ALLOWED_STYLES },
48
48
  prefix: { type: "string" },
49
49
  suffix: { type: "string" },
50
- forbiddenPattern: {
50
+ forbiddenPatterns: {
51
51
  ..._utilsjs.ARRAY_DEFAULT_OPTIONS,
52
52
  items: {
53
53
  type: "object"
54
54
  },
55
55
  description: "Should be of instance of `RegEx`"
56
56
  },
57
- requiredPattern: {
57
+ requiredPatterns: {
58
58
  ..._utilsjs.ARRAY_DEFAULT_OPTIONS,
59
59
  items: {
60
60
  type: "object"
@@ -63,19 +63,19 @@ const KindToDisplayName = {
63
63
  },
64
64
  forbiddenPrefixes: {
65
65
  ..._utilsjs.ARRAY_DEFAULT_OPTIONS,
66
- description: descriptionPrefixesSuffixes("forbiddenPattern")
66
+ description: descriptionPrefixesSuffixes("forbiddenPatterns")
67
67
  },
68
68
  forbiddenSuffixes: {
69
69
  ..._utilsjs.ARRAY_DEFAULT_OPTIONS,
70
- description: descriptionPrefixesSuffixes("forbiddenPattern")
70
+ description: descriptionPrefixesSuffixes("forbiddenPatterns")
71
71
  },
72
72
  requiredPrefixes: {
73
73
  ..._utilsjs.ARRAY_DEFAULT_OPTIONS,
74
- description: descriptionPrefixesSuffixes("requiredPattern")
74
+ description: descriptionPrefixesSuffixes("requiredPatterns")
75
75
  },
76
76
  requiredSuffixes: {
77
77
  ..._utilsjs.ARRAY_DEFAULT_OPTIONS,
78
- description: descriptionPrefixesSuffixes("requiredPattern")
78
+ description: descriptionPrefixesSuffixes("requiredPatterns")
79
79
  },
80
80
  ignorePattern: {
81
81
  type: "string",
@@ -101,7 +101,9 @@ ${_utilsjs.TYPES_KINDS.map((kind) => `- \`${kind}\``).join(`
101
101
  kind,
102
102
  {
103
103
  ...schemaOption,
104
- description: `Read more about this kind on [spec.graphql.org](https://spec.graphql.org/October2021/#${kind}).`
104
+ description: `> [!NOTE]
105
+ >
106
+ > Read more about this kind on [spec.graphql.org](https://spec.graphql.org/October2021/#${kind}).`
105
107
  }
106
108
  ])
107
109
  ),
@@ -328,7 +330,7 @@ ${_utilsjs.TYPES_KINDS.map((kind) => `- \`${kind}\``).join(`
328
330
  schema
329
331
  },
330
332
  create(context) {
331
- const options = context.options[0] || {}, { allowLeadingUnderscore, allowTrailingUnderscore, types, ...restOptions } = options;
333
+ const options = context.options[0] || {}, { allowLeadingUnderscore, allowTrailingUnderscore, types, ...restOptions } = options, ignoredNodes = /* @__PURE__ */ new Set();
332
334
  function normalisePropertyOption(kind) {
333
335
  const style = restOptions[kind] || types;
334
336
  return typeof style == "object" ? style : { style };
@@ -356,8 +358,8 @@ ${_utilsjs.TYPES_KINDS.map((kind) => `- \`${kind}\``).join(`
356
358
  ignorePattern,
357
359
  requiredPrefixes,
358
360
  requiredSuffixes,
359
- forbiddenPattern,
360
- requiredPattern
361
+ forbiddenPatterns,
362
+ requiredPatterns
361
363
  } = normalisePropertyOption(selector), nodeName = node.value, error = getError();
362
364
  if (error) {
363
365
  const { errorMessage, renameToNames } = error, [leadingUnderscores] = nodeName.match(/^_*/), [trailingUnderscores] = nodeName.match(/_*$/), suggestedNames = renameToNames.map(
@@ -371,8 +373,10 @@ ${_utilsjs.TYPES_KINDS.map((kind) => `- \`${kind}\``).join(`
371
373
  }
372
374
  function getError() {
373
375
  const name = nodeName.replace(/(^_+)|(_+$)/g, "");
374
- if (ignorePattern && new RegExp(ignorePattern, "u").test(name))
376
+ if (ignorePattern && new RegExp(ignorePattern, "u").test(name)) {
377
+ "name" in n && ignoredNodes.add(n.name);
375
378
  return;
379
+ }
376
380
  if (prefix && !name.startsWith(prefix))
377
381
  return {
378
382
  errorMessage: `have "${prefix}" prefix`,
@@ -383,15 +387,15 @@ ${_utilsjs.TYPES_KINDS.map((kind) => `- \`${kind}\``).join(`
383
387
  errorMessage: `have "${suffix}" suffix`,
384
388
  renameToNames: [name + suffix]
385
389
  };
386
- const forbidden = _optionalChain([forbiddenPattern, 'optionalAccess', _ => _.find, 'call', _2 => _2((pattern) => pattern.test(name))]);
390
+ const forbidden = _optionalChain([forbiddenPatterns, 'optionalAccess', _ => _.find, 'call', _2 => _2((pattern) => pattern.test(name))]);
387
391
  if (forbidden)
388
392
  return {
389
393
  errorMessage: `not contain the forbidden pattern "${forbidden}"`,
390
394
  renameToNames: [name.replace(forbidden, "")]
391
395
  };
392
- if (requiredPattern && !requiredPattern.some((pattern) => pattern.test(name)))
396
+ if (requiredPatterns && !requiredPatterns.some((pattern) => pattern.test(name)))
393
397
  return {
394
- errorMessage: `contain the required pattern: ${_utilsjs.englishJoinWords.call(void 0, requiredPattern.map((re) => re.source))}`,
398
+ errorMessage: `contain the required pattern: ${_utilsjs.englishJoinWords.call(void 0, requiredPatterns.map((re) => re.source))}`,
395
399
  renameToNames: []
396
400
  };
397
401
  const forbiddenPrefix = _optionalChain([forbiddenPrefixes, 'optionalAccess', _3 => _3.find, 'call', _4 => _4((prefix2) => name.startsWith(prefix2))]);
@@ -429,7 +433,7 @@ ${_utilsjs.TYPES_KINDS.map((kind) => `- \`${kind}\``).join(`
429
433
  };
430
434
  }
431
435
  }, checkUnderscore = (isLeading) => (node) => {
432
- if (node.parent.kind === "Field" && node.parent.alias !== node)
436
+ if (ignoredNodes.has(node) || node.parent.kind === "Field" && node.parent.alias !== node)
433
437
  return;
434
438
  const suggestedName = node.value.replace(isLeading ? /^_+/ : /_+$/, "");
435
439
  report(node, `${isLeading ? "Leading" : "Trailing"} underscores are not allowed`, [
@@ -82,9 +82,7 @@ const RULE_ID = "no-unused-fields", RELAY_SCHEMA = (
82
82
  "```json",
83
83
  JSON.stringify(RELAY_DEFAULT_IGNORED_FIELD_SELECTORS, null, 2),
84
84
  "```",
85
- "",
86
- "> These fields are defined by ESLint [`selectors`](https://eslint.org/docs/developer-guide/selectors).",
87
- "> Paste or drop code into the editor in [ASTExplorer](https://astexplorer.net) and inspect the generated AST to compose your selector."
85
+ _utilsjs.eslintSelectorsTip
88
86
  ].join(`
89
87
  `),
90
88
  items: {
@@ -15,8 +15,9 @@ type RuleOptions = [
15
15
  {
16
16
  [key in AllowedKind]?: boolean;
17
17
  } & {
18
- types?: boolean;
19
- rootField?: boolean;
18
+ types?: true;
19
+ rootField?: true;
20
+ ignoredSelectors?: string[];
20
21
  }
21
22
  ];
22
23
  declare const rule: GraphQLESLintRule<RuleOptions>;
@@ -1,5 +1,12 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }var _graphql = require('graphql');
2
2
  var _utils = require('@graphql-tools/utils');
3
+
4
+
5
+
6
+
7
+
8
+
9
+
3
10
  var _utilsjs = require('../../utils.js');
4
11
  const RULE_ID = "require-description", ALLOWED_KINDS = [
5
12
  ..._utilsjs.TYPES_KINDS,
@@ -19,18 +26,34 @@ const RULE_ID = "require-description", ALLOWED_KINDS = [
19
26
  properties: {
20
27
  types: {
21
28
  type: "boolean",
29
+ enum: [!0],
22
30
  description: `Includes:
23
31
  ${_utilsjs.TYPES_KINDS.map((kind) => `- \`${kind}\``).join(`
24
32
  `)}`
25
33
  },
26
34
  rootField: {
27
35
  type: "boolean",
36
+ enum: [!0],
28
37
  description: "Definitions within `Query`, `Mutation`, and `Subscription` root types."
29
38
  },
39
+ ignoredSelectors: {
40
+ ..._utilsjs.ARRAY_DEFAULT_OPTIONS,
41
+ description: ["Ignore specific selectors", _utilsjs.eslintSelectorsTip].join(`
42
+ `)
43
+ },
30
44
  ...Object.fromEntries(
31
45
  [...ALLOWED_KINDS].sort().map((kind) => {
32
- let description = `Read more about this kind on [spec.graphql.org](https://spec.graphql.org/October2021/#${kind}).`;
33
- return kind === _graphql.Kind.OPERATION_DEFINITION && (description += '\n> You must use only comment syntax `#` and not description syntax `"""` or `"`.'), [kind, { type: "boolean", description }];
46
+ let description = `> [!NOTE]
47
+ >
48
+ > Read more about this kind on [spec.graphql.org](https://spec.graphql.org/October2021/#${kind}).`;
49
+ return kind === _graphql.Kind.OPERATION_DEFINITION && (description += [
50
+ "",
51
+ "",
52
+ "> [!WARNING]",
53
+ ">",
54
+ '> You must use only comment syntax `#` and not description syntax `"""` or `"`.'
55
+ ].join(`
56
+ `)), [kind, { type: "boolean", description }];
34
57
  })
35
58
  )
36
59
  }
@@ -101,6 +124,36 @@ ${_utilsjs.TYPES_KINDS.map((kind) => `- \`${kind}\``).join(`
101
124
  }
102
125
  `
103
126
  )
127
+ },
128
+ {
129
+ title: "Correct",
130
+ usage: [
131
+ {
132
+ ignoredSelectors: [
133
+ "[type=ObjectTypeDefinition][name.value=PageInfo]",
134
+ "[type=ObjectTypeDefinition][name.value=/(Connection|Edge)$/]"
135
+ ]
136
+ }
137
+ ],
138
+ code: (
139
+ /* GraphQL */
140
+ `
141
+ type FriendConnection {
142
+ edges: [FriendEdge]
143
+ pageInfo: PageInfo!
144
+ }
145
+ type FriendEdge {
146
+ cursor: String!
147
+ node: Friend!
148
+ }
149
+ type PageInfo {
150
+ hasPreviousPage: Boolean!
151
+ hasNextPage: Boolean!
152
+ startCursor: String
153
+ endCursor: String
154
+ }
155
+ `
156
+ )
104
157
  }
105
158
  ],
106
159
  configOptions: [
@@ -119,7 +172,7 @@ ${_utilsjs.TYPES_KINDS.map((kind) => `- \`${kind}\``).join(`
119
172
  schema
120
173
  },
121
174
  create(context) {
122
- const { types, rootField, ...restOptions } = context.options[0] || {}, kinds = new Set(types ? _utilsjs.TYPES_KINDS : []);
175
+ const { types, rootField, ignoredSelectors = [], ...restOptions } = context.options[0] || {}, kinds = new Set(types ? _utilsjs.TYPES_KINDS : []);
123
176
  for (const [kind, isEnabled] of Object.entries(restOptions))
124
177
  isEnabled ? kinds.add(kind) : kinds.delete(kind);
125
178
  if (rootField) {
@@ -130,10 +183,11 @@ ${_utilsjs.TYPES_KINDS.map((kind) => `- \`${kind}\``).join(`
130
183
  ].join(",")})$/] > FieldDefinition`
131
184
  );
132
185
  }
133
- if (!kinds.size)
134
- throw new Error("At least one kind must be enabled");
186
+ let selector = `:matches(${[...kinds]})`;
187
+ for (const str of ignoredSelectors)
188
+ selector += `:not(${str})`;
135
189
  return {
136
- [[...kinds].join(",")](node) {
190
+ [selector](node) {
137
191
  let description = "";
138
192
  const isOperation = node.kind === _graphql.Kind.OPERATION_DEFINITION;
139
193
  if (isOperation) {
package/cjs/utils.d.cts CHANGED
@@ -41,5 +41,6 @@ type Truthy<T> = T extends '' | 0 | false | null | undefined ? never : T;
41
41
  declare function truthy<T>(value: T): value is Truthy<T>;
42
42
  declare function displayNodeName(node: GraphQLESTreeNode<ASTNode, boolean>): string;
43
43
  declare function getNodeName(node: GraphQLESTreeNode<ASTNode>): string;
44
+ declare const eslintSelectorsTip = "> [!TIP]\n>\n> These fields are defined by ESLint [`selectors`](https://eslint.org/docs/developer-guide/selectors).\n> Paste or drop code into the editor in [ASTExplorer](https://astexplorer.net) and inspect the generated AST to compose your selector.";
44
45
 
45
- export { ARRAY_DEFAULT_OPTIONS, CWD, type CaseStyle, REPORT_ON_FIRST_CHARACTER, TYPES_KINDS, VIRTUAL_DOCUMENT_REGEX, camelCase, convertCase, displayNodeName, englishJoinWords, getLocation, getNodeName, getTypeName, logger, pascalCase, requireGraphQLOperations, requireGraphQLSchema, slash, truthy };
46
+ export { ARRAY_DEFAULT_OPTIONS, CWD, type CaseStyle, REPORT_ON_FIRST_CHARACTER, TYPES_KINDS, VIRTUAL_DOCUMENT_REGEX, camelCase, convertCase, displayNodeName, englishJoinWords, eslintSelectorsTip, getLocation, getNodeName, getTypeName, logger, pascalCase, requireGraphQLOperations, requireGraphQLSchema, slash, truthy };
package/cjs/utils.js CHANGED
@@ -144,6 +144,10 @@ function getNodeName(node) {
144
144
  }
145
145
  return "";
146
146
  }
147
+ const eslintSelectorsTip = `> [!TIP]
148
+ >
149
+ > These fields are defined by ESLint [\`selectors\`](https://eslint.org/docs/developer-guide/selectors).
150
+ > Paste or drop code into the editor in [ASTExplorer](https://astexplorer.net) and inspect the generated AST to compose your selector.`;
147
151
 
148
152
 
149
153
 
@@ -163,4 +167,5 @@ function getNodeName(node) {
163
167
 
164
168
 
165
169
 
166
- exports.ARRAY_DEFAULT_OPTIONS = ARRAY_DEFAULT_OPTIONS; exports.CWD = CWD; exports.REPORT_ON_FIRST_CHARACTER = REPORT_ON_FIRST_CHARACTER; exports.TYPES_KINDS = TYPES_KINDS; exports.VIRTUAL_DOCUMENT_REGEX = VIRTUAL_DOCUMENT_REGEX; exports.camelCase = camelCase; exports.convertCase = convertCase; exports.displayNodeName = displayNodeName; exports.englishJoinWords = englishJoinWords; exports.getLocation = getLocation; exports.getNodeName = getNodeName; exports.getTypeName = getTypeName; exports.logger = logger; exports.pascalCase = pascalCase; exports.requireGraphQLOperations = requireGraphQLOperations; exports.requireGraphQLSchema = requireGraphQLSchema; exports.slash = slash; exports.truthy = truthy;
170
+
171
+ exports.ARRAY_DEFAULT_OPTIONS = ARRAY_DEFAULT_OPTIONS; exports.CWD = CWD; exports.REPORT_ON_FIRST_CHARACTER = REPORT_ON_FIRST_CHARACTER; exports.TYPES_KINDS = TYPES_KINDS; exports.VIRTUAL_DOCUMENT_REGEX = VIRTUAL_DOCUMENT_REGEX; exports.camelCase = camelCase; exports.convertCase = convertCase; exports.displayNodeName = displayNodeName; exports.englishJoinWords = englishJoinWords; exports.eslintSelectorsTip = eslintSelectorsTip; exports.getLocation = getLocation; exports.getNodeName = getNodeName; exports.getTypeName = getTypeName; exports.logger = logger; exports.pascalCase = pascalCase; exports.requireGraphQLOperations = requireGraphQLOperations; exports.requireGraphQLSchema = requireGraphQLSchema; exports.slash = slash; exports.truthy = truthy;
package/esm/index.d.ts CHANGED
@@ -98,10 +98,10 @@ declare const _default: {
98
98
  style?: ("camelCase" | "PascalCase" | "snake_case" | "UPPER_CASE") | undefined;
99
99
  suffix?: string | undefined;
100
100
  prefix?: string | undefined;
101
- forbiddenPattern?: {
101
+ forbiddenPatterns?: {
102
102
  [x: string]: unknown;
103
103
  }[] | undefined;
104
- requiredPattern?: {
104
+ requiredPatterns?: {
105
105
  [x: string]: unknown;
106
106
  }[] | undefined;
107
107
  forbiddenPrefixes?: string[] | undefined;
package/esm/meta.js CHANGED
@@ -1,4 +1,4 @@
1
- const version = "4.1.0-alpha-20241129085030-b075ada387ad44de7944517af78877c45bc8fd3b";
1
+ const version = "4.1.1-alpha-20241129095718-0cc689c0eb8b65d162f4c6d87030879fe63a105b";
2
2
  export {
3
3
  version
4
4
  };
@@ -61,10 +61,10 @@ declare const rules: {
61
61
  style?: ("camelCase" | "PascalCase" | "snake_case" | "UPPER_CASE") | undefined;
62
62
  suffix?: string | undefined;
63
63
  prefix?: string | undefined;
64
- forbiddenPattern?: {
64
+ forbiddenPatterns?: {
65
65
  [x: string]: unknown;
66
66
  }[] | undefined;
67
- requiredPattern?: {
67
+ requiredPatterns?: {
68
68
  [x: string]: unknown;
69
69
  }[] | undefined;
70
70
  forbiddenPrefixes?: string[] | undefined;
@@ -28,7 +28,7 @@ declare const schema: {
28
28
  readonly suffix: {
29
29
  readonly type: "string";
30
30
  };
31
- readonly forbiddenPattern: {
31
+ readonly forbiddenPatterns: {
32
32
  readonly items: {
33
33
  readonly type: "object";
34
34
  };
@@ -37,7 +37,7 @@ declare const schema: {
37
37
  readonly uniqueItems: true;
38
38
  readonly minItems: 1;
39
39
  };
40
- readonly requiredPattern: {
40
+ readonly requiredPatterns: {
41
41
  readonly items: {
42
42
  readonly type: "object";
43
43
  };
@@ -47,14 +47,14 @@ const KindToDisplayName = {
47
47
  style: { enum: ALLOWED_STYLES },
48
48
  prefix: { type: "string" },
49
49
  suffix: { type: "string" },
50
- forbiddenPattern: {
50
+ forbiddenPatterns: {
51
51
  ...ARRAY_DEFAULT_OPTIONS,
52
52
  items: {
53
53
  type: "object"
54
54
  },
55
55
  description: "Should be of instance of `RegEx`"
56
56
  },
57
- requiredPattern: {
57
+ requiredPatterns: {
58
58
  ...ARRAY_DEFAULT_OPTIONS,
59
59
  items: {
60
60
  type: "object"
@@ -63,19 +63,19 @@ const KindToDisplayName = {
63
63
  },
64
64
  forbiddenPrefixes: {
65
65
  ...ARRAY_DEFAULT_OPTIONS,
66
- description: descriptionPrefixesSuffixes("forbiddenPattern")
66
+ description: descriptionPrefixesSuffixes("forbiddenPatterns")
67
67
  },
68
68
  forbiddenSuffixes: {
69
69
  ...ARRAY_DEFAULT_OPTIONS,
70
- description: descriptionPrefixesSuffixes("forbiddenPattern")
70
+ description: descriptionPrefixesSuffixes("forbiddenPatterns")
71
71
  },
72
72
  requiredPrefixes: {
73
73
  ...ARRAY_DEFAULT_OPTIONS,
74
- description: descriptionPrefixesSuffixes("requiredPattern")
74
+ description: descriptionPrefixesSuffixes("requiredPatterns")
75
75
  },
76
76
  requiredSuffixes: {
77
77
  ...ARRAY_DEFAULT_OPTIONS,
78
- description: descriptionPrefixesSuffixes("requiredPattern")
78
+ description: descriptionPrefixesSuffixes("requiredPatterns")
79
79
  },
80
80
  ignorePattern: {
81
81
  type: "string",
@@ -101,7 +101,9 @@ ${TYPES_KINDS.map((kind) => `- \`${kind}\``).join(`
101
101
  kind,
102
102
  {
103
103
  ...schemaOption,
104
- description: `Read more about this kind on [spec.graphql.org](https://spec.graphql.org/October2021/#${kind}).`
104
+ description: `> [!NOTE]
105
+ >
106
+ > Read more about this kind on [spec.graphql.org](https://spec.graphql.org/October2021/#${kind}).`
105
107
  }
106
108
  ])
107
109
  ),
@@ -328,7 +330,7 @@ ${TYPES_KINDS.map((kind) => `- \`${kind}\``).join(`
328
330
  schema
329
331
  },
330
332
  create(context) {
331
- const options = context.options[0] || {}, { allowLeadingUnderscore, allowTrailingUnderscore, types, ...restOptions } = options;
333
+ const options = context.options[0] || {}, { allowLeadingUnderscore, allowTrailingUnderscore, types, ...restOptions } = options, ignoredNodes = /* @__PURE__ */ new Set();
332
334
  function normalisePropertyOption(kind) {
333
335
  const style = restOptions[kind] || types;
334
336
  return typeof style == "object" ? style : { style };
@@ -356,8 +358,8 @@ ${TYPES_KINDS.map((kind) => `- \`${kind}\``).join(`
356
358
  ignorePattern,
357
359
  requiredPrefixes,
358
360
  requiredSuffixes,
359
- forbiddenPattern,
360
- requiredPattern
361
+ forbiddenPatterns,
362
+ requiredPatterns
361
363
  } = normalisePropertyOption(selector), nodeName = node.value, error = getError();
362
364
  if (error) {
363
365
  const { errorMessage, renameToNames } = error, [leadingUnderscores] = nodeName.match(/^_*/), [trailingUnderscores] = nodeName.match(/_*$/), suggestedNames = renameToNames.map(
@@ -371,8 +373,10 @@ ${TYPES_KINDS.map((kind) => `- \`${kind}\``).join(`
371
373
  }
372
374
  function getError() {
373
375
  const name = nodeName.replace(/(^_+)|(_+$)/g, "");
374
- if (ignorePattern && new RegExp(ignorePattern, "u").test(name))
376
+ if (ignorePattern && new RegExp(ignorePattern, "u").test(name)) {
377
+ "name" in n && ignoredNodes.add(n.name);
375
378
  return;
379
+ }
376
380
  if (prefix && !name.startsWith(prefix))
377
381
  return {
378
382
  errorMessage: `have "${prefix}" prefix`,
@@ -383,15 +387,15 @@ ${TYPES_KINDS.map((kind) => `- \`${kind}\``).join(`
383
387
  errorMessage: `have "${suffix}" suffix`,
384
388
  renameToNames: [name + suffix]
385
389
  };
386
- const forbidden = forbiddenPattern?.find((pattern) => pattern.test(name));
390
+ const forbidden = forbiddenPatterns?.find((pattern) => pattern.test(name));
387
391
  if (forbidden)
388
392
  return {
389
393
  errorMessage: `not contain the forbidden pattern "${forbidden}"`,
390
394
  renameToNames: [name.replace(forbidden, "")]
391
395
  };
392
- if (requiredPattern && !requiredPattern.some((pattern) => pattern.test(name)))
396
+ if (requiredPatterns && !requiredPatterns.some((pattern) => pattern.test(name)))
393
397
  return {
394
- errorMessage: `contain the required pattern: ${englishJoinWords(requiredPattern.map((re) => re.source))}`,
398
+ errorMessage: `contain the required pattern: ${englishJoinWords(requiredPatterns.map((re) => re.source))}`,
395
399
  renameToNames: []
396
400
  };
397
401
  const forbiddenPrefix = forbiddenPrefixes?.find((prefix2) => name.startsWith(prefix2));
@@ -429,7 +433,7 @@ ${TYPES_KINDS.map((kind) => `- \`${kind}\``).join(`
429
433
  };
430
434
  }
431
435
  }, checkUnderscore = (isLeading) => (node) => {
432
- if (node.parent.kind === "Field" && node.parent.alias !== node)
436
+ if (ignoredNodes.has(node) || node.parent.kind === "Field" && node.parent.alias !== node)
433
437
  return;
434
438
  const suggestedName = node.value.replace(isLeading ? /^_+/ : /_+$/, "");
435
439
  report(node, `${isLeading ? "Leading" : "Trailing"} underscores are not allowed`, [
@@ -1,6 +1,6 @@
1
1
  import { TypeInfo, visit, visitWithTypeInfo } from "graphql";
2
2
  import { ModuleCache } from "../../cache.js";
3
- import { requireGraphQLOperations, requireGraphQLSchema } from "../../utils.js";
3
+ import { eslintSelectorsTip, requireGraphQLOperations, requireGraphQLSchema } from "../../utils.js";
4
4
  const RULE_ID = "no-unused-fields", RELAY_SCHEMA = (
5
5
  /* GraphQL */
6
6
  `
@@ -82,9 +82,7 @@ const RULE_ID = "no-unused-fields", RELAY_SCHEMA = (
82
82
  "```json",
83
83
  JSON.stringify(RELAY_DEFAULT_IGNORED_FIELD_SELECTORS, null, 2),
84
84
  "```",
85
- "",
86
- "> These fields are defined by ESLint [`selectors`](https://eslint.org/docs/developer-guide/selectors).",
87
- "> Paste or drop code into the editor in [ASTExplorer](https://astexplorer.net) and inspect the generated AST to compose your selector."
85
+ eslintSelectorsTip
88
86
  ].join(`
89
87
  `),
90
88
  items: {
@@ -15,8 +15,9 @@ type RuleOptions = [
15
15
  {
16
16
  [key in AllowedKind]?: boolean;
17
17
  } & {
18
- types?: boolean;
19
- rootField?: boolean;
18
+ types?: true;
19
+ rootField?: true;
20
+ ignoredSelectors?: string[];
20
21
  }
21
22
  ];
22
23
  declare const rule: GraphQLESLintRule<RuleOptions>;
@@ -1,6 +1,13 @@
1
1
  import { Kind, TokenKind } from "graphql";
2
2
  import { getRootTypeNames } from "@graphql-tools/utils";
3
- import { getLocation, getNodeName, requireGraphQLSchema, TYPES_KINDS } from "../../utils.js";
3
+ import {
4
+ ARRAY_DEFAULT_OPTIONS,
5
+ eslintSelectorsTip,
6
+ getLocation,
7
+ getNodeName,
8
+ requireGraphQLSchema,
9
+ TYPES_KINDS
10
+ } from "../../utils.js";
4
11
  const RULE_ID = "require-description", ALLOWED_KINDS = [
5
12
  ...TYPES_KINDS,
6
13
  Kind.DIRECTIVE_DEFINITION,
@@ -19,18 +26,34 @@ const RULE_ID = "require-description", ALLOWED_KINDS = [
19
26
  properties: {
20
27
  types: {
21
28
  type: "boolean",
29
+ enum: [!0],
22
30
  description: `Includes:
23
31
  ${TYPES_KINDS.map((kind) => `- \`${kind}\``).join(`
24
32
  `)}`
25
33
  },
26
34
  rootField: {
27
35
  type: "boolean",
36
+ enum: [!0],
28
37
  description: "Definitions within `Query`, `Mutation`, and `Subscription` root types."
29
38
  },
39
+ ignoredSelectors: {
40
+ ...ARRAY_DEFAULT_OPTIONS,
41
+ description: ["Ignore specific selectors", eslintSelectorsTip].join(`
42
+ `)
43
+ },
30
44
  ...Object.fromEntries(
31
45
  [...ALLOWED_KINDS].sort().map((kind) => {
32
- let description = `Read more about this kind on [spec.graphql.org](https://spec.graphql.org/October2021/#${kind}).`;
33
- return kind === Kind.OPERATION_DEFINITION && (description += '\n> You must use only comment syntax `#` and not description syntax `"""` or `"`.'), [kind, { type: "boolean", description }];
46
+ let description = `> [!NOTE]
47
+ >
48
+ > Read more about this kind on [spec.graphql.org](https://spec.graphql.org/October2021/#${kind}).`;
49
+ return kind === Kind.OPERATION_DEFINITION && (description += [
50
+ "",
51
+ "",
52
+ "> [!WARNING]",
53
+ ">",
54
+ '> You must use only comment syntax `#` and not description syntax `"""` or `"`.'
55
+ ].join(`
56
+ `)), [kind, { type: "boolean", description }];
34
57
  })
35
58
  )
36
59
  }
@@ -101,6 +124,36 @@ ${TYPES_KINDS.map((kind) => `- \`${kind}\``).join(`
101
124
  }
102
125
  `
103
126
  )
127
+ },
128
+ {
129
+ title: "Correct",
130
+ usage: [
131
+ {
132
+ ignoredSelectors: [
133
+ "[type=ObjectTypeDefinition][name.value=PageInfo]",
134
+ "[type=ObjectTypeDefinition][name.value=/(Connection|Edge)$/]"
135
+ ]
136
+ }
137
+ ],
138
+ code: (
139
+ /* GraphQL */
140
+ `
141
+ type FriendConnection {
142
+ edges: [FriendEdge]
143
+ pageInfo: PageInfo!
144
+ }
145
+ type FriendEdge {
146
+ cursor: String!
147
+ node: Friend!
148
+ }
149
+ type PageInfo {
150
+ hasPreviousPage: Boolean!
151
+ hasNextPage: Boolean!
152
+ startCursor: String
153
+ endCursor: String
154
+ }
155
+ `
156
+ )
104
157
  }
105
158
  ],
106
159
  configOptions: [
@@ -119,7 +172,7 @@ ${TYPES_KINDS.map((kind) => `- \`${kind}\``).join(`
119
172
  schema
120
173
  },
121
174
  create(context) {
122
- const { types, rootField, ...restOptions } = context.options[0] || {}, kinds = new Set(types ? TYPES_KINDS : []);
175
+ const { types, rootField, ignoredSelectors = [], ...restOptions } = context.options[0] || {}, kinds = new Set(types ? TYPES_KINDS : []);
123
176
  for (const [kind, isEnabled] of Object.entries(restOptions))
124
177
  isEnabled ? kinds.add(kind) : kinds.delete(kind);
125
178
  if (rootField) {
@@ -130,10 +183,11 @@ ${TYPES_KINDS.map((kind) => `- \`${kind}\``).join(`
130
183
  ].join(",")})$/] > FieldDefinition`
131
184
  );
132
185
  }
133
- if (!kinds.size)
134
- throw new Error("At least one kind must be enabled");
186
+ let selector = `:matches(${[...kinds]})`;
187
+ for (const str of ignoredSelectors)
188
+ selector += `:not(${str})`;
135
189
  return {
136
- [[...kinds].join(",")](node) {
190
+ [selector](node) {
137
191
  let description = "";
138
192
  const isOperation = node.kind === Kind.OPERATION_DEFINITION;
139
193
  if (isOperation) {
package/esm/utils.d.ts CHANGED
@@ -41,5 +41,6 @@ type Truthy<T> = T extends '' | 0 | false | null | undefined ? never : T;
41
41
  declare function truthy<T>(value: T): value is Truthy<T>;
42
42
  declare function displayNodeName(node: GraphQLESTreeNode<ASTNode, boolean>): string;
43
43
  declare function getNodeName(node: GraphQLESTreeNode<ASTNode>): string;
44
+ declare const eslintSelectorsTip = "> [!TIP]\n>\n> These fields are defined by ESLint [`selectors`](https://eslint.org/docs/developer-guide/selectors).\n> Paste or drop code into the editor in [ASTExplorer](https://astexplorer.net) and inspect the generated AST to compose your selector.";
44
45
 
45
- export { ARRAY_DEFAULT_OPTIONS, CWD, type CaseStyle, REPORT_ON_FIRST_CHARACTER, TYPES_KINDS, VIRTUAL_DOCUMENT_REGEX, camelCase, convertCase, displayNodeName, englishJoinWords, getLocation, getNodeName, getTypeName, logger, pascalCase, requireGraphQLOperations, requireGraphQLSchema, slash, truthy };
46
+ export { ARRAY_DEFAULT_OPTIONS, CWD, type CaseStyle, REPORT_ON_FIRST_CHARACTER, TYPES_KINDS, VIRTUAL_DOCUMENT_REGEX, camelCase, convertCase, displayNodeName, englishJoinWords, eslintSelectorsTip, getLocation, getNodeName, getTypeName, logger, pascalCase, requireGraphQLOperations, requireGraphQLSchema, slash, truthy };
package/esm/utils.js CHANGED
@@ -144,6 +144,10 @@ function getNodeName(node) {
144
144
  }
145
145
  return "";
146
146
  }
147
+ const eslintSelectorsTip = `> [!TIP]
148
+ >
149
+ > These fields are defined by ESLint [\`selectors\`](https://eslint.org/docs/developer-guide/selectors).
150
+ > Paste or drop code into the editor in [ASTExplorer](https://astexplorer.net) and inspect the generated AST to compose your selector.`;
147
151
  export {
148
152
  ARRAY_DEFAULT_OPTIONS,
149
153
  CWD,
@@ -154,6 +158,7 @@ export {
154
158
  convertCase,
155
159
  displayNodeName,
156
160
  englishJoinWords,
161
+ eslintSelectorsTip,
157
162
  getLocation,
158
163
  getNodeName,
159
164
  getTypeName,
package/index.browser.js CHANGED
@@ -150,7 +150,7 @@ function convertToESTree(node, schema16) {
150
150
  }
151
151
 
152
152
  // src/meta.ts
153
- var version = "4.1.0-alpha-20241129085030-b075ada387ad44de7944517af78877c45bc8fd3b";
153
+ var version = "4.1.1-alpha-20241129095718-0cc689c0eb8b65d162f4c6d87030879fe63a105b";
154
154
 
155
155
  // src/siblings.ts
156
156
  import {
@@ -305,6 +305,10 @@ function getNodeName(node) {
305
305
  }
306
306
  return "";
307
307
  }
308
+ var eslintSelectorsTip = `> [!TIP]
309
+ >
310
+ > These fields are defined by ESLint [\`selectors\`](https://eslint.org/docs/developer-guide/selectors).
311
+ > Paste or drop code into the editor in [ASTExplorer](https://astexplorer.net) and inspect the generated AST to compose your selector.`;
308
312
 
309
313
  // src/siblings.ts
310
314
  var siblingOperationsCache = /* @__PURE__ */ new Map();
@@ -1934,14 +1938,14 @@ var KindToDisplayName = {
1934
1938
  style: { enum: ALLOWED_STYLES },
1935
1939
  prefix: { type: "string" },
1936
1940
  suffix: { type: "string" },
1937
- forbiddenPattern: {
1941
+ forbiddenPatterns: {
1938
1942
  ...ARRAY_DEFAULT_OPTIONS,
1939
1943
  items: {
1940
1944
  type: "object"
1941
1945
  },
1942
1946
  description: "Should be of instance of `RegEx`"
1943
1947
  },
1944
- requiredPattern: {
1948
+ requiredPatterns: {
1945
1949
  ...ARRAY_DEFAULT_OPTIONS,
1946
1950
  items: {
1947
1951
  type: "object"
@@ -1950,19 +1954,19 @@ var KindToDisplayName = {
1950
1954
  },
1951
1955
  forbiddenPrefixes: {
1952
1956
  ...ARRAY_DEFAULT_OPTIONS,
1953
- description: descriptionPrefixesSuffixes("forbiddenPattern")
1957
+ description: descriptionPrefixesSuffixes("forbiddenPatterns")
1954
1958
  },
1955
1959
  forbiddenSuffixes: {
1956
1960
  ...ARRAY_DEFAULT_OPTIONS,
1957
- description: descriptionPrefixesSuffixes("forbiddenPattern")
1961
+ description: descriptionPrefixesSuffixes("forbiddenPatterns")
1958
1962
  },
1959
1963
  requiredPrefixes: {
1960
1964
  ...ARRAY_DEFAULT_OPTIONS,
1961
- description: descriptionPrefixesSuffixes("requiredPattern")
1965
+ description: descriptionPrefixesSuffixes("requiredPatterns")
1962
1966
  },
1963
1967
  requiredSuffixes: {
1964
1968
  ...ARRAY_DEFAULT_OPTIONS,
1965
- description: descriptionPrefixesSuffixes("requiredPattern")
1969
+ description: descriptionPrefixesSuffixes("requiredPatterns")
1966
1970
  },
1967
1971
  ignorePattern: {
1968
1972
  type: "string",
@@ -1988,7 +1992,9 @@ ${TYPES_KINDS.map((kind) => `- \`${kind}\``).join(`
1988
1992
  kind,
1989
1993
  {
1990
1994
  ...schemaOption2,
1991
- description: `Read more about this kind on [spec.graphql.org](https://spec.graphql.org/October2021/#${kind}).`
1995
+ description: `> [!NOTE]
1996
+ >
1997
+ > Read more about this kind on [spec.graphql.org](https://spec.graphql.org/October2021/#${kind}).`
1992
1998
  }
1993
1999
  ])
1994
2000
  ),
@@ -2215,7 +2221,7 @@ ${TYPES_KINDS.map((kind) => `- \`${kind}\``).join(`
2215
2221
  schema: schema6
2216
2222
  },
2217
2223
  create(context) {
2218
- let options = context.options[0] || {}, { allowLeadingUnderscore, allowTrailingUnderscore, types, ...restOptions } = options;
2224
+ let options = context.options[0] || {}, { allowLeadingUnderscore, allowTrailingUnderscore, types, ...restOptions } = options, ignoredNodes = /* @__PURE__ */ new Set();
2219
2225
  function normalisePropertyOption(kind) {
2220
2226
  let style = restOptions[kind] || types;
2221
2227
  return typeof style == "object" ? style : { style };
@@ -2243,8 +2249,8 @@ ${TYPES_KINDS.map((kind) => `- \`${kind}\``).join(`
2243
2249
  ignorePattern,
2244
2250
  requiredPrefixes,
2245
2251
  requiredSuffixes,
2246
- forbiddenPattern,
2247
- requiredPattern
2252
+ forbiddenPatterns,
2253
+ requiredPatterns
2248
2254
  } = normalisePropertyOption(selector), nodeName = node.value, error = getError();
2249
2255
  if (error) {
2250
2256
  let { errorMessage, renameToNames } = error, [leadingUnderscores] = nodeName.match(/^_*/), [trailingUnderscores] = nodeName.match(/_*$/), suggestedNames = renameToNames.map(
@@ -2258,8 +2264,10 @@ ${TYPES_KINDS.map((kind) => `- \`${kind}\``).join(`
2258
2264
  }
2259
2265
  function getError() {
2260
2266
  let name = nodeName.replace(/(^_+)|(_+$)/g, "");
2261
- if (ignorePattern && new RegExp(ignorePattern, "u").test(name))
2267
+ if (ignorePattern && new RegExp(ignorePattern, "u").test(name)) {
2268
+ "name" in n && ignoredNodes.add(n.name);
2262
2269
  return;
2270
+ }
2263
2271
  if (prefix && !name.startsWith(prefix))
2264
2272
  return {
2265
2273
  errorMessage: `have "${prefix}" prefix`,
@@ -2270,15 +2278,15 @@ ${TYPES_KINDS.map((kind) => `- \`${kind}\``).join(`
2270
2278
  errorMessage: `have "${suffix}" suffix`,
2271
2279
  renameToNames: [name + suffix]
2272
2280
  };
2273
- let forbidden = forbiddenPattern?.find((pattern) => pattern.test(name));
2281
+ let forbidden = forbiddenPatterns?.find((pattern) => pattern.test(name));
2274
2282
  if (forbidden)
2275
2283
  return {
2276
2284
  errorMessage: `not contain the forbidden pattern "${forbidden}"`,
2277
2285
  renameToNames: [name.replace(forbidden, "")]
2278
2286
  };
2279
- if (requiredPattern && !requiredPattern.some((pattern) => pattern.test(name)))
2287
+ if (requiredPatterns && !requiredPatterns.some((pattern) => pattern.test(name)))
2280
2288
  return {
2281
- errorMessage: `contain the required pattern: ${englishJoinWords(requiredPattern.map((re) => re.source))}`,
2289
+ errorMessage: `contain the required pattern: ${englishJoinWords(requiredPatterns.map((re) => re.source))}`,
2282
2290
  renameToNames: []
2283
2291
  };
2284
2292
  let forbiddenPrefix = forbiddenPrefixes?.find((prefix2) => name.startsWith(prefix2));
@@ -2316,7 +2324,7 @@ ${TYPES_KINDS.map((kind) => `- \`${kind}\``).join(`
2316
2324
  };
2317
2325
  }
2318
2326
  }, checkUnderscore = (isLeading) => (node) => {
2319
- if (node.parent.kind === "Field" && node.parent.alias !== node)
2327
+ if (ignoredNodes.has(node) || node.parent.kind === "Field" && node.parent.alias !== node)
2320
2328
  return;
2321
2329
  let suggestedName = node.value.replace(isLeading ? /^_+/ : /_+$/, "");
2322
2330
  report(node, `${isLeading ? "Leading" : "Trailing"} underscores are not allowed`, [
@@ -3281,9 +3289,7 @@ var RULE_ID10 = "no-unused-fields", RELAY_SCHEMA = (
3281
3289
  "```json",
3282
3290
  JSON.stringify(RELAY_DEFAULT_IGNORED_FIELD_SELECTORS, null, 2),
3283
3291
  "```",
3284
- "",
3285
- "> These fields are defined by ESLint [`selectors`](https://eslint.org/docs/developer-guide/selectors).",
3286
- "> Paste or drop code into the editor in [ASTExplorer](https://astexplorer.net) and inspect the generated AST to compose your selector."
3292
+ eslintSelectorsTip
3287
3293
  ].join(`
3288
3294
  `),
3289
3295
  items: {
@@ -4033,18 +4039,34 @@ var RULE_ID14 = "require-description", ALLOWED_KINDS2 = [
4033
4039
  properties: {
4034
4040
  types: {
4035
4041
  type: "boolean",
4042
+ enum: [!0],
4036
4043
  description: `Includes:
4037
4044
  ${TYPES_KINDS.map((kind) => `- \`${kind}\``).join(`
4038
4045
  `)}`
4039
4046
  },
4040
4047
  rootField: {
4041
4048
  type: "boolean",
4049
+ enum: [!0],
4042
4050
  description: "Definitions within `Query`, `Mutation`, and `Subscription` root types."
4043
4051
  },
4052
+ ignoredSelectors: {
4053
+ ...ARRAY_DEFAULT_OPTIONS,
4054
+ description: ["Ignore specific selectors", eslintSelectorsTip].join(`
4055
+ `)
4056
+ },
4044
4057
  ...Object.fromEntries(
4045
4058
  [...ALLOWED_KINDS2].sort().map((kind) => {
4046
- let description = `Read more about this kind on [spec.graphql.org](https://spec.graphql.org/October2021/#${kind}).`;
4047
- return kind === Kind17.OPERATION_DEFINITION && (description += '\n> You must use only comment syntax `#` and not description syntax `"""` or `"`.'), [kind, { type: "boolean", description }];
4059
+ let description = `> [!NOTE]
4060
+ >
4061
+ > Read more about this kind on [spec.graphql.org](https://spec.graphql.org/October2021/#${kind}).`;
4062
+ return kind === Kind17.OPERATION_DEFINITION && (description += [
4063
+ "",
4064
+ "",
4065
+ "> [!WARNING]",
4066
+ ">",
4067
+ '> You must use only comment syntax `#` and not description syntax `"""` or `"`.'
4068
+ ].join(`
4069
+ `)), [kind, { type: "boolean", description }];
4048
4070
  })
4049
4071
  )
4050
4072
  }
@@ -4115,6 +4137,36 @@ ${TYPES_KINDS.map((kind) => `- \`${kind}\``).join(`
4115
4137
  }
4116
4138
  `
4117
4139
  )
4140
+ },
4141
+ {
4142
+ title: "Correct",
4143
+ usage: [
4144
+ {
4145
+ ignoredSelectors: [
4146
+ "[type=ObjectTypeDefinition][name.value=PageInfo]",
4147
+ "[type=ObjectTypeDefinition][name.value=/(Connection|Edge)$/]"
4148
+ ]
4149
+ }
4150
+ ],
4151
+ code: (
4152
+ /* GraphQL */
4153
+ `
4154
+ type FriendConnection {
4155
+ edges: [FriendEdge]
4156
+ pageInfo: PageInfo!
4157
+ }
4158
+ type FriendEdge {
4159
+ cursor: String!
4160
+ node: Friend!
4161
+ }
4162
+ type PageInfo {
4163
+ hasPreviousPage: Boolean!
4164
+ hasNextPage: Boolean!
4165
+ startCursor: String
4166
+ endCursor: String
4167
+ }
4168
+ `
4169
+ )
4118
4170
  }
4119
4171
  ],
4120
4172
  configOptions: [
@@ -4133,7 +4185,7 @@ ${TYPES_KINDS.map((kind) => `- \`${kind}\``).join(`
4133
4185
  schema: schema12
4134
4186
  },
4135
4187
  create(context) {
4136
- let { types, rootField, ...restOptions } = context.options[0] || {}, kinds = new Set(types ? TYPES_KINDS : []);
4188
+ let { types, rootField, ignoredSelectors = [], ...restOptions } = context.options[0] || {}, kinds = new Set(types ? TYPES_KINDS : []);
4137
4189
  for (let [kind, isEnabled] of Object.entries(restOptions))
4138
4190
  isEnabled ? kinds.add(kind) : kinds.delete(kind);
4139
4191
  if (rootField) {
@@ -4144,10 +4196,11 @@ ${TYPES_KINDS.map((kind) => `- \`${kind}\``).join(`
4144
4196
  ].join(",")})$/] > FieldDefinition`
4145
4197
  );
4146
4198
  }
4147
- if (!kinds.size)
4148
- throw new Error("At least one kind must be enabled");
4199
+ let selector = `:matches(${[...kinds]})`;
4200
+ for (let str of ignoredSelectors)
4201
+ selector += `:not(${str})`;
4149
4202
  return {
4150
- [[...kinds].join(",")](node) {
4203
+ [selector](node) {
4151
4204
  let description = "", isOperation = node.kind === Kind17.OPERATION_DEFINITION;
4152
4205
  if (isOperation) {
4153
4206
  let rawNode = node.rawNode(), { prev, line } = rawNode.loc.startToken;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@graphql-eslint/eslint-plugin",
3
- "version": "4.1.0-alpha-20241129085030-b075ada387ad44de7944517af78877c45bc8fd3b",
3
+ "version": "4.1.1-alpha-20241129095718-0cc689c0eb8b65d162f4c6d87030879fe63a105b",
4
4
  "type": "module",
5
5
  "description": "GraphQL plugin for ESLint",
6
6
  "repository": "https://github.com/dimaMachina/graphql-eslint",