@graphql-eslint/eslint-plugin 3.14.3 → 3.14.4-alpha-20221229151835-f439b5b

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. package/cjs/cache.js +3 -2
  2. package/cjs/documents.js +8 -5
  3. package/cjs/estree-converter/converter.js +1 -1
  4. package/cjs/parser.js +4 -2
  5. package/cjs/processor.js +4 -2
  6. package/cjs/rules/alphabetize.js +5 -3
  7. package/cjs/rules/graphql-js-validation.js +9 -6
  8. package/cjs/rules/input-name.js +5 -4
  9. package/cjs/rules/naming-convention.js +2 -2
  10. package/cjs/rules/no-case-insensitive-enum-values-duplicates.js +3 -2
  11. package/cjs/rules/no-duplicate-fields.js +2 -2
  12. package/cjs/rules/no-hashtag-description.js +3 -0
  13. package/cjs/rules/no-root-type.js +1 -1
  14. package/cjs/rules/no-typename-prefix.js +1 -1
  15. package/cjs/rules/no-unreachable-types.js +1 -1
  16. package/cjs/rules/relay-arguments.js +2 -1
  17. package/cjs/rules/relay-connection-types.js +2 -2
  18. package/cjs/rules/relay-edge-types.js +7 -4
  19. package/cjs/rules/relay-page-info.js +2 -1
  20. package/cjs/rules/require-deprecation-date.js +2 -2
  21. package/cjs/rules/require-deprecation-reason.js +2 -1
  22. package/cjs/rules/require-description.js +1 -1
  23. package/cjs/rules/require-field-of-type-query-in-mutation-result.js +1 -1
  24. package/cjs/rules/require-id-when-available.js +2 -1
  25. package/cjs/rules/require-nullable-fields-with-oneof.js +2 -2
  26. package/cjs/rules/require-type-pattern-with-oneof.js +2 -1
  27. package/cjs/rules/strict-id-in-types.js +4 -4
  28. package/cjs/rules/unique-fragment-name.js +1 -0
  29. package/cjs/schema.js +3 -1
  30. package/cjs/testkit.js +4 -7
  31. package/cjs/utils.js +11 -5
  32. package/esm/cache.js +3 -2
  33. package/esm/documents.js +8 -5
  34. package/esm/estree-converter/converter.js +1 -1
  35. package/esm/graphql-config.js +1 -1
  36. package/esm/parser.js +4 -2
  37. package/esm/processor.js +5 -3
  38. package/esm/rules/alphabetize.js +6 -4
  39. package/esm/rules/graphql-js-validation.js +9 -6
  40. package/esm/rules/input-name.js +5 -4
  41. package/esm/rules/naming-convention.js +3 -3
  42. package/esm/rules/no-case-insensitive-enum-values-duplicates.js +3 -2
  43. package/esm/rules/no-duplicate-fields.js +2 -2
  44. package/esm/rules/no-hashtag-description.js +3 -0
  45. package/esm/rules/no-root-type.js +2 -2
  46. package/esm/rules/no-typename-prefix.js +1 -1
  47. package/esm/rules/no-unreachable-types.js +1 -1
  48. package/esm/rules/relay-arguments.js +2 -1
  49. package/esm/rules/relay-connection-types.js +2 -2
  50. package/esm/rules/relay-edge-types.js +7 -4
  51. package/esm/rules/relay-page-info.js +2 -1
  52. package/esm/rules/require-deprecation-date.js +2 -2
  53. package/esm/rules/require-deprecation-reason.js +2 -1
  54. package/esm/rules/require-description.js +1 -1
  55. package/esm/rules/require-field-of-type-query-in-mutation-result.js +1 -1
  56. package/esm/rules/require-id-when-available.js +2 -1
  57. package/esm/rules/require-nullable-fields-with-oneof.js +2 -2
  58. package/esm/rules/require-type-pattern-with-oneof.js +2 -1
  59. package/esm/rules/strict-id-in-types.js +5 -5
  60. package/esm/rules/unique-fragment-name.js +1 -0
  61. package/esm/schema.js +3 -1
  62. package/esm/testkit.js +4 -7
  63. package/esm/utils.js +9 -4
  64. package/package.json +1 -1
  65. package/typings/cache.d.cts +1 -1
  66. package/typings/cache.d.ts +1 -1
  67. package/typings/estree-converter/types.d.cts +4 -4
  68. package/typings/estree-converter/types.d.ts +4 -4
  69. package/typings/estree-converter/utils.d.cts +2 -2
  70. package/typings/estree-converter/utils.d.ts +2 -2
  71. package/typings/rules/index.d.cts +68 -68
  72. package/typings/rules/index.d.ts +68 -68
  73. package/typings/testkit.d.cts +6 -4
  74. package/typings/testkit.d.ts +6 -4
  75. package/typings/types.d.cts +4 -3
  76. package/typings/types.d.ts +4 -3
  77. package/typings/utils.d.cts +8 -5
  78. package/typings/utils.d.ts +8 -5
package/cjs/cache.js CHANGED
@@ -15,11 +15,12 @@ class ModuleCache {
15
15
  log('setting entry for', cacheKey);
16
16
  }
17
17
  get(cacheKey, settings = { lifetime: 10 /* seconds */ }) {
18
- if (!this.map.has(cacheKey)) {
18
+ const value = this.map.get(cacheKey);
19
+ if (!value) {
19
20
  log('cache miss for', cacheKey);
20
21
  return;
21
22
  }
22
- const { lastSeen, result } = this.map.get(cacheKey);
23
+ const { lastSeen, result } = value;
23
24
  // check freshness
24
25
  if (process.env.NODE /* don't check for ESLint CLI */ ||
25
26
  process.hrtime(lastSeen)[0] < settings.lifetime) {
package/cjs/documents.js CHANGED
@@ -13,7 +13,7 @@ const handleVirtualPath = (documents) => {
13
13
  const filepathMap = Object.create(null);
14
14
  return documents.map(source => {
15
15
  var _a;
16
- const { location } = source;
16
+ const location = source.location;
17
17
  if (['.gql', '.graphql'].some(extension => location.endsWith(extension))) {
18
18
  return source;
19
19
  }
@@ -74,15 +74,17 @@ function getDocuments(project) {
74
74
  // Since the siblings array is cached, we can use it as cache key.
75
75
  // We should get the same array reference each time we get
76
76
  // to this point for the same graphql project
77
- if (siblingOperationsCache.has(siblings)) {
78
- return siblingOperationsCache.get(siblings);
77
+ const value = siblingOperationsCache.get(siblings);
78
+ if (value) {
79
+ return value;
79
80
  }
80
81
  let fragmentsCache = null;
81
82
  const getFragments = () => {
83
+ var _a;
82
84
  if (fragmentsCache === null) {
83
85
  const result = [];
84
86
  for (const source of siblings) {
85
- for (const definition of source.document.definitions) {
87
+ for (const definition of ((_a = source.document) === null || _a === void 0 ? void 0 : _a.definitions) || []) {
86
88
  if (definition.kind === graphql_1.Kind.FRAGMENT_DEFINITION) {
87
89
  result.push({
88
90
  filePath: source.location,
@@ -97,10 +99,11 @@ function getDocuments(project) {
97
99
  };
98
100
  let cachedOperations = null;
99
101
  const getOperations = () => {
102
+ var _a;
100
103
  if (cachedOperations === null) {
101
104
  const result = [];
102
105
  for (const source of siblings) {
103
- for (const definition of source.document.definitions) {
106
+ for (const definition of ((_a = source.document) === null || _a === void 0 ? void 0 : _a.definitions) || []) {
104
107
  if (definition.kind === graphql_1.Kind.OPERATION_DEFINITION) {
105
108
  result.push({
106
109
  filePath: source.location,
@@ -4,7 +4,7 @@ exports.convertToESTree = void 0;
4
4
  const graphql_1 = require("graphql");
5
5
  const utils_js_1 = require("./utils.js");
6
6
  function convertToESTree(node, schema) {
7
- const typeInfo = schema ? new graphql_1.TypeInfo(schema) : null;
7
+ const typeInfo = schema && new graphql_1.TypeInfo(schema);
8
8
  const visitor = {
9
9
  leave(node, key, parent) {
10
10
  const leadingComments = 'description' in node && node.description
package/cjs/parser.js CHANGED
@@ -25,7 +25,7 @@ function parseForESLint(code, options) {
25
25
  const realFilepath = filePath.replace(utils_js_1.VIRTUAL_DOCUMENT_REGEX, '');
26
26
  const project = gqlConfig.getProjectForFile(realFilepath);
27
27
  const schema = (0, schema_js_1.getSchema)(project, options.schemaOptions);
28
- const rootTree = (0, index_js_1.convertToESTree)(document, schema instanceof graphql_1.GraphQLSchema ? schema : null);
28
+ const rootTree = (0, index_js_1.convertToESTree)(document, schema instanceof graphql_1.GraphQLSchema ? schema : undefined);
29
29
  return {
30
30
  services: {
31
31
  schema,
@@ -43,7 +43,9 @@ function parseForESLint(code, options) {
43
43
  };
44
44
  }
45
45
  catch (error) {
46
- error.message = `[graphql-eslint] ${error.message}`;
46
+ if (error instanceof Error) {
47
+ error.message = `[graphql-eslint] ${error.message}`;
48
+ }
47
49
  // In case of GraphQL parser error, we report it to ESLint as a parser error that matches the requirements
48
50
  // of ESLint. This will make sure to display it correctly in IDEs and lint results.
49
51
  if (error instanceof graphql_1.GraphQLError) {
package/cjs/processor.js CHANGED
@@ -26,7 +26,7 @@ exports.processor = {
26
26
  ...modules.map(({ identifier }) => identifier),
27
27
  ...(0, utils_1.asArray)(globalGqlIdentifierName),
28
28
  gqlMagicComment,
29
- ].filter(Boolean)),
29
+ ].filter(utils_js_1.truthy)),
30
30
  ];
31
31
  }
32
32
  if (keywords.every(keyword => !code.includes(keyword))) {
@@ -48,7 +48,9 @@ exports.processor = {
48
48
  return [...blocks, code /* source code must be provided and be last */];
49
49
  }
50
50
  catch (error) {
51
- error.message = `[graphql-eslint] Error while preprocessing "${(0, path_1.relative)(utils_js_1.CWD, filePath)}" file\n\n${error.message}`;
51
+ if (error instanceof Error) {
52
+ error.message = `[graphql-eslint] Error while preprocessing "${(0, path_1.relative)(utils_js_1.CWD, filePath)}" file\n\n${error.message}`;
53
+ }
52
54
  // eslint-disable-next-line no-console
53
55
  console.error(error);
54
56
  // in case of parsing error return code as is
@@ -228,7 +228,7 @@ exports.rule = {
228
228
  : node;
229
229
  return [from.range[0], to.range[1]];
230
230
  }
231
- function checkNodes(nodes) {
231
+ function checkNodes(nodes = []) {
232
232
  var _a, _b, _c, _d;
233
233
  // Starts from 1, ignore nodes.length <= 1
234
234
  for (let i = 1; i < nodes.length; i += 1) {
@@ -273,6 +273,7 @@ exports.rule = {
273
273
  }
274
274
  }
275
275
  context.report({
276
+ // @ts-expect-error can't be undefined
276
277
  node: ('alias' in currNode && currNode.alias) || currNode.name,
277
278
  messageId: RULE_ID,
278
279
  data: {
@@ -305,7 +306,7 @@ exports.rule = {
305
306
  graphql_1.Kind.INPUT_OBJECT_TYPE_EXTENSION,
306
307
  ],
307
308
  ]
308
- .filter(Boolean)
309
+ .filter(utils_js_1.truthy)
309
310
  .flat();
310
311
  const fieldsSelector = kinds.join(',');
311
312
  const hasEnumValues = ((_b = opts.values) === null || _b === void 0 ? void 0 : _b[0]) === graphql_1.Kind.ENUM_TYPE_DEFINITION;
@@ -330,7 +331,8 @@ exports.rule = {
330
331
  }
331
332
  if (hasVariables) {
332
333
  listeners.OperationDefinition = (node) => {
333
- checkNodes(node.variableDefinitions.map(varDef => varDef.variable));
334
+ var _a;
335
+ checkNodes((_a = node.variableDefinitions) === null || _a === void 0 ? void 0 : _a.map(varDef => varDef.variable));
334
336
  };
335
337
  }
336
338
  if (argumentsSelector) {
@@ -46,10 +46,10 @@ function validateDocument({ context, schema = null, documentNode, rule, hasDidYo
46
46
  });
47
47
  }
48
48
  }
49
- catch (e) {
49
+ catch (error) {
50
50
  context.report({
51
51
  loc: utils_js_1.REPORT_ON_FIRST_CHARACTER,
52
- message: e.message,
52
+ message: error.message,
53
53
  });
54
54
  }
55
55
  }
@@ -186,10 +186,13 @@ exports.GRAPHQL_JS_VALIDATIONS = Object.assign({}, validationToRule({
186
186
  if (ignoreClientDirectives.length === 0) {
187
187
  return documentNode;
188
188
  }
189
- const filterDirectives = (node) => ({
190
- ...node,
191
- directives: node.directives.filter(directive => !ignoreClientDirectives.includes(directive.name.value)),
192
- });
189
+ const filterDirectives = (node) => {
190
+ var _a;
191
+ return ({
192
+ ...node,
193
+ directives: (_a = node.directives) === null || _a === void 0 ? void 0 : _a.filter(directive => !ignoreClientDirectives.includes(directive.name.value)),
194
+ });
195
+ };
193
196
  return (0, graphql_1.visit)(documentNode, {
194
197
  Field: filterDirectives,
195
198
  OperationDefinition: filterDirectives,
@@ -79,12 +79,12 @@ exports.rule = {
79
79
  const options = {
80
80
  checkInputType: false,
81
81
  caseSensitiveInputType: true,
82
- checkQueries: false,
83
82
  checkMutations: true,
84
83
  ...context.options[0],
85
84
  };
86
- const shouldCheckType = node => (options.checkMutations && isMutationType(node)) ||
87
- (options.checkQueries && isQueryType(node));
85
+ const shouldCheckType = (node) => (options.checkMutations && isMutationType(node)) ||
86
+ (options.checkQueries && isQueryType(node)) ||
87
+ false;
88
88
  const listeners = {
89
89
  'FieldDefinition > InputValueDefinition[name.value!=input] > Name'(node) {
90
90
  if (shouldCheckType(node.parent.parent.parent)) {
@@ -104,9 +104,10 @@ exports.rule = {
104
104
  };
105
105
  if (options.checkInputType) {
106
106
  listeners['FieldDefinition > InputValueDefinition NamedType'] = (node) => {
107
- const findInputType = item => {
107
+ const findInputType = (item) => {
108
108
  let currentNode = item;
109
109
  while (currentNode.type !== graphql_1.Kind.INPUT_VALUE_DEFINITION) {
110
+ // @ts-expect-error TODO try fix type error
110
111
  currentNode = currentNode.parent;
111
112
  }
112
113
  return currentNode;
@@ -215,7 +215,7 @@ exports.rule = {
215
215
  const options = context.options[0] || {};
216
216
  const { allowLeadingUnderscore, allowTrailingUnderscore, types, ...restOptions } = options;
217
217
  function normalisePropertyOption(kind) {
218
- const style = restOptions[kind] || types;
218
+ const style = (restOptions[kind] || types);
219
219
  return typeof style === 'object' ? style : { style };
220
220
  }
221
221
  function report(node, message, suggestedName) {
@@ -301,7 +301,7 @@ exports.rule = {
301
301
  if (!allowTrailingUnderscore) {
302
302
  listeners['Name[value=/_$/]:matches([parent.kind!=Field], [parent.kind=Field][parent.alias])'] = checkUnderscore(false);
303
303
  }
304
- const selectors = new Set([types && utils_js_1.TYPES_KINDS, Object.keys(restOptions)].flat().filter(Boolean));
304
+ const selectors = new Set([types && utils_js_1.TYPES_KINDS, Object.keys(restOptions)].flat().filter(utils_js_1.truthy));
305
305
  for (const selector of selectors) {
306
306
  listeners[selector] = checkNode(selector);
307
307
  }
@@ -40,9 +40,10 @@ exports.rule = {
40
40
  const selector = [graphql_1.Kind.ENUM_TYPE_DEFINITION, graphql_1.Kind.ENUM_TYPE_EXTENSION].join(',');
41
41
  return {
42
42
  [selector](node) {
43
- const duplicates = node.values.filter((item, index, array) => array.findIndex(v => v.name.value.toLowerCase() === item.name.value.toLowerCase()) !==
43
+ var _a;
44
+ const duplicates = (_a = node.values) === null || _a === void 0 ? void 0 : _a.filter((item, index, array) => array.findIndex(v => v.name.value.toLowerCase() === item.name.value.toLowerCase()) !==
44
45
  index);
45
- for (const duplicate of duplicates) {
46
+ for (const duplicate of duplicates || []) {
46
47
  const enumName = duplicate.name.value;
47
48
  context.report({
48
49
  node: duplicate.name,
@@ -89,13 +89,13 @@ exports.rule = {
89
89
  return {
90
90
  OperationDefinition(node) {
91
91
  const set = new Set();
92
- for (const varDef of node.variableDefinitions) {
92
+ for (const varDef of node.variableDefinitions || []) {
93
93
  checkNode(set, varDef.variable.name);
94
94
  }
95
95
  },
96
96
  Field(node) {
97
97
  const set = new Set();
98
- for (const arg of node.arguments) {
98
+ for (const arg of node.arguments || []) {
99
99
  checkNode(set, arg.name);
100
100
  }
101
101
  },
@@ -81,6 +81,9 @@ exports.rule = {
81
81
  });
82
82
  }
83
83
  }
84
+ if (!next) {
85
+ break;
86
+ }
84
87
  token = next;
85
88
  }
86
89
  },
@@ -60,7 +60,7 @@ exports.rule = {
60
60
  disallow.has('mutation') && schema.getMutationType(),
61
61
  disallow.has('subscription') && schema.getSubscriptionType(),
62
62
  ]
63
- .filter(Boolean)
63
+ .filter(utils_js_1.truthy)
64
64
  .map(type => type.name)
65
65
  .join('|');
66
66
  if (!rootTypeNames) {
@@ -40,7 +40,7 @@ exports.rule = {
40
40
  'ObjectTypeDefinition, ObjectTypeExtension, InterfaceTypeDefinition, InterfaceTypeExtension'(node) {
41
41
  const typeName = node.name.value;
42
42
  const lowerTypeName = typeName.toLowerCase();
43
- for (const field of node.fields) {
43
+ for (const field of node.fields || []) {
44
44
  const fieldName = field.name.value;
45
45
  if (fieldName.toLowerCase().startsWith(lowerTypeName)) {
46
46
  context.report({
@@ -52,7 +52,7 @@ function getReachableTypes(schema) {
52
52
  (0, graphql_1.visit)(astNode, visitor);
53
53
  }
54
54
  }
55
- else if (type.astNode) {
55
+ else if (type === null || type === void 0 ? void 0 : type.astNode) {
56
56
  // astNode can be undefined for ID, String, Boolean
57
57
  (0, graphql_1.visit)(type.astNode, visitor);
58
58
  }
@@ -72,11 +72,12 @@ exports.rule = {
72
72
  const { includeBoth = true } = context.options[0] || {};
73
73
  return {
74
74
  'FieldDefinition > .gqlType Name[value=/Connection$/]'(node) {
75
+ var _a;
75
76
  let fieldNode = node.parent;
76
77
  while (fieldNode.kind !== graphql_1.Kind.FIELD_DEFINITION) {
77
78
  fieldNode = fieldNode.parent;
78
79
  }
79
- const args = Object.fromEntries(fieldNode.arguments.map(argument => [argument.name.value, argument]));
80
+ const args = Object.fromEntries(((_a = fieldNode.arguments) === null || _a === void 0 ? void 0 : _a.map(argument => [argument.name.value, argument])) || []);
80
81
  const hasForwardPagination = Boolean(args.first && args.after);
81
82
  const hasBackwardPagination = Boolean(args.last && args.before);
82
83
  if (!hasForwardPagination && !hasBackwardPagination) {
@@ -20,8 +20,8 @@ exports.NON_OBJECT_TYPES = [
20
20
  graphql_1.Kind.INTERFACE_TYPE_EXTENSION,
21
21
  ];
22
22
  const notConnectionTypesSelector = `:matches(${exports.NON_OBJECT_TYPES})[name.value=/Connection$/] > .name`;
23
- const hasEdgesField = (node) => node.fields.some(field => field.name.value === 'edges');
24
- const hasPageInfoField = (node) => node.fields.some(field => field.name.value === 'pageInfo');
23
+ const hasEdgesField = (node) => { var _a; return (_a = node.fields) === null || _a === void 0 ? void 0 : _a.some(field => field.name.value === 'edges'); };
24
+ const hasPageInfoField = (node) => { var _a; return (_a = node.fields) === null || _a === void 0 ? void 0 : _a.some(field => field.name.value === 'pageInfo'); };
25
25
  exports.rule = {
26
26
  meta: {
27
27
  type: 'problem',
@@ -19,12 +19,13 @@ function getEdgeTypes(schema) {
19
19
  const edgeTypes = new Set();
20
20
  const visitor = {
21
21
  ObjectTypeDefinition(node) {
22
+ var _a;
22
23
  const typeName = node.name.value;
23
24
  const hasConnectionSuffix = typeName.endsWith('Connection');
24
25
  if (!hasConnectionSuffix) {
25
26
  return;
26
27
  }
27
- const edges = node.fields.find(field => field.name.value === 'edges');
28
+ const edges = (_a = node.fields) === null || _a === void 0 ? void 0 : _a.find(field => field.name.value === 'edges');
28
29
  if (edges) {
29
30
  const edgesTypeName = (0, utils_js_1.getTypeName)(edges);
30
31
  const edgesType = schema.getType(edgesTypeName);
@@ -116,7 +117,8 @@ exports.rule = {
116
117
  const isNamedOrNonNullNamed = (node) => node.kind === graphql_1.Kind.NAMED_TYPE ||
117
118
  (node.kind === graphql_1.Kind.NON_NULL_TYPE && node.gqlType.kind === graphql_1.Kind.NAMED_TYPE);
118
119
  const checkNodeField = (node) => {
119
- const nodeField = node.fields.find(field => field.name.value === 'node');
120
+ var _a, _b;
121
+ const nodeField = (_a = node.fields) === null || _a === void 0 ? void 0 : _a.find(field => field.name.value === 'node');
120
122
  const message = 'return either a Scalar, Enum, Object, Interface, Union, or a non-null wrapper around one of those types.';
121
123
  if (!nodeField) {
122
124
  context.report({
@@ -133,14 +135,15 @@ exports.rule = {
133
135
  if (!(0, graphql_1.isObjectType)(type)) {
134
136
  return;
135
137
  }
136
- const implementsNode = type.astNode.interfaces.some(n => n.name.value === 'Node');
138
+ const implementsNode = (_b = type.astNode.interfaces) === null || _b === void 0 ? void 0 : _b.some(n => n.name.value === 'Node');
137
139
  if (!implementsNode) {
138
140
  context.report({ node: node.name, messageId: MESSAGE_SHOULD_IMPLEMENTS_NODE });
139
141
  }
140
142
  }
141
143
  };
142
144
  const checkCursorField = (node) => {
143
- const cursorField = node.fields.find(field => field.name.value === 'cursor');
145
+ var _a;
146
+ const cursorField = (_a = node.fields) === null || _a === void 0 ? void 0 : _a.find(field => field.name.value === 'cursor');
144
147
  const message = 'return either a String, Scalar, or a non-null wrapper wrapper around one of those types.';
145
148
  if (!cursorField) {
146
149
  context.report({
@@ -61,7 +61,8 @@ exports.rule = {
61
61
  context.report({ node, messageId: MESSAGE_MUST_BE_OBJECT_TYPE });
62
62
  },
63
63
  'ObjectTypeDefinition[name.value=PageInfo]'(node) {
64
- const fieldMap = Object.fromEntries(node.fields.map(field => [field.name.value, field]));
64
+ var _a;
65
+ const fieldMap = Object.fromEntries(((_a = node.fields) === null || _a === void 0 ? void 0 : _a.map(field => [field.name.value, field])) || []);
65
66
  const checkField = (fieldName, typeName) => {
66
67
  const field = fieldMap[fieldName];
67
68
  let isAllowedType = false;
@@ -71,9 +71,9 @@ exports.rule = {
71
71
  create(context) {
72
72
  return {
73
73
  'Directive[name.value=deprecated]'(node) {
74
- var _a;
74
+ var _a, _b;
75
75
  const argName = ((_a = context.options[0]) === null || _a === void 0 ? void 0 : _a.argumentName) || 'deletionDate';
76
- const deletionDateNode = node.arguments.find(arg => arg.name.value === argName);
76
+ const deletionDateNode = (_b = node.arguments) === null || _b === void 0 ? void 0 : _b.find(arg => arg.name.value === argName);
77
77
  if (!deletionDateNode) {
78
78
  context.report({
79
79
  node: node.name,
@@ -42,7 +42,8 @@ exports.rule = {
42
42
  create(context) {
43
43
  return {
44
44
  'Directive[name.value=deprecated]'(node) {
45
- const reasonArgument = node.arguments.find(arg => arg.name.value === 'reason');
45
+ var _a;
46
+ const reasonArgument = (_a = node.arguments) === null || _a === void 0 ? void 0 : _a.find(arg => arg.name.value === 'reason');
46
47
  const value = reasonArgument && String((0, index_js_1.valueFromNode)(reasonArgument.value)).trim();
47
48
  if (!value) {
48
49
  context.report({
@@ -167,7 +167,7 @@ exports.rule = {
167
167
  if (isOperation) {
168
168
  const rawNode = node.rawNode();
169
169
  const { prev, line } = rawNode.loc.startToken;
170
- if (prev.kind === graphql_1.TokenKind.COMMENT) {
170
+ if ((prev === null || prev === void 0 ? void 0 : prev.kind) === graphql_1.TokenKind.COMMENT) {
171
171
  const value = prev.value.trim();
172
172
  const linesBefore = line - prev.line;
173
173
  if (!value.startsWith('eslint') && linesBefore === 1) {
@@ -58,7 +58,7 @@ exports.rule = {
58
58
  const graphQLType = schema.getType(typeName);
59
59
  if ((0, graphql_1.isObjectType)(graphQLType)) {
60
60
  const { fields } = graphQLType.astNode;
61
- const hasQueryType = fields.some(field => (0, utils_js_1.getTypeName)(field) === queryType.name);
61
+ const hasQueryType = fields === null || fields === void 0 ? void 0 : fields.some(field => (0, utils_js_1.getTypeName)(field) === queryType.name);
62
62
  if (!hasQueryType) {
63
63
  context.report({
64
64
  node,
@@ -108,7 +108,8 @@ exports.rule = {
108
108
  }
109
109
  const checkedFragmentSpreads = new Set();
110
110
  const visitor = (0, graphql_1.visitWithTypeInfo)(typeInfo, {
111
- SelectionSet(node, key, parent) {
111
+ SelectionSet(node, key, _parent) {
112
+ const parent = _parent;
112
113
  if (parent.kind === graphql_1.Kind.FRAGMENT_DEFINITION) {
113
114
  checkedFragmentSpreads.add(parent.name.value);
114
115
  }
@@ -38,7 +38,7 @@ exports.rule = {
38
38
  },
39
39
  create(context) {
40
40
  return {
41
- 'Directive[name.value=oneOf]'({ parent, }) {
41
+ 'Directive[name.value=oneOf]'({ parent }) {
42
42
  const isTypeOrInput = [
43
43
  graphql_1.Kind.OBJECT_TYPE_DEFINITION,
44
44
  graphql_1.Kind.INPUT_OBJECT_TYPE_DEFINITION,
@@ -46,7 +46,7 @@ exports.rule = {
46
46
  if (!isTypeOrInput) {
47
47
  return;
48
48
  }
49
- for (const field of parent.fields) {
49
+ for (const field of parent.fields || []) {
50
50
  if (field.gqlType.kind === graphql_1.Kind.NON_NULL_TYPE) {
51
51
  context.report({
52
52
  node: field.name,
@@ -41,9 +41,10 @@ exports.rule = {
41
41
  create(context) {
42
42
  return {
43
43
  'Directive[name.value=oneOf][parent.kind=ObjectTypeDefinition]'({ parent, }) {
44
+ var _a;
44
45
  const requiredFields = ['error', 'ok'];
45
46
  for (const fieldName of requiredFields) {
46
- if (!parent.fields.some(field => field.name.value === fieldName)) {
47
+ if (!((_a = parent.fields) === null || _a === void 0 ? void 0 : _a.some(field => field.name.value === fieldName))) {
47
48
  context.report({
48
49
  node: parent.name,
49
50
  messageId: RULE_ID,
@@ -122,19 +122,19 @@ exports.rule = {
122
122
  schema.getMutationType(),
123
123
  schema.getSubscriptionType(),
124
124
  ]
125
- .filter(Boolean)
125
+ .filter(utils_js_1.truthy)
126
126
  .map(type => type.name);
127
127
  const selector = `ObjectTypeDefinition[name.value!=/^(${rootTypeNames.join('|')})$/]`;
128
128
  return {
129
129
  [selector](node) {
130
- var _a, _b;
130
+ var _a, _b, _c;
131
131
  const typeName = node.name.value;
132
132
  const shouldIgnoreNode = ((_a = options.exceptions.types) === null || _a === void 0 ? void 0 : _a.includes(typeName)) ||
133
133
  ((_b = options.exceptions.suffixes) === null || _b === void 0 ? void 0 : _b.some(suffix => typeName.endsWith(suffix)));
134
134
  if (shouldIgnoreNode) {
135
135
  return;
136
136
  }
137
- const validIds = node.fields.filter(field => {
137
+ const validIds = (_c = node.fields) === null || _c === void 0 ? void 0 : _c.filter(field => {
138
138
  const fieldNode = field.rawNode();
139
139
  const isValidIdName = options.acceptedIdNames.includes(fieldNode.name.value);
140
140
  // To be a valid type, it must be non-null and one of the accepted types.
@@ -148,7 +148,7 @@ exports.rule = {
148
148
  // Usually, there should be only one unique identifier field per type.
149
149
  // Some clients allow multiple fields to be used. If more people need this,
150
150
  // we can extend this rule later.
151
- if (validIds.length !== 1) {
151
+ if ((validIds === null || validIds === void 0 ? void 0 : validIds.length) !== 1) {
152
152
  const pluralNamesSuffix = options.acceptedIdNames.length > 1 ? 's' : '';
153
153
  const pluralTypesSuffix = options.acceptedIdTypes.length > 1 ? 's' : '';
154
154
  context.report({
@@ -27,6 +27,7 @@ const checkNode = (context, node, ruleId) => {
27
27
  .map(f => `\t${(0, path_1.relative)(utils_js_1.CWD, f.filePath.replace(utils_js_1.VIRTUAL_DOCUMENT_REGEX, ''))}`)
28
28
  .join('\n'),
29
29
  },
30
+ // @ts-expect-error name will exist
30
31
  node: node.name,
31
32
  });
32
33
  }
package/cjs/schema.js CHANGED
@@ -34,7 +34,9 @@ function getSchema(project, schemaOptions) {
34
34
  schemaCache.set(schemaKey, schema);
35
35
  }
36
36
  catch (error) {
37
- error.message = chalk_1.default.red(`Error while loading schema: ${error.message}`);
37
+ if (error instanceof Error) {
38
+ error.message = chalk_1.default.red(`Error while loading schema: ${error.message}`);
39
+ }
38
40
  schema = error;
39
41
  }
40
42
  return schema;
package/cjs/testkit.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.GraphQLRuleTester = void 0;
4
- /* eslint-env jest */
4
+ /* eslint-env vitest */
5
5
  const fs_1 = require("fs");
6
6
  const path_1 = require("path");
7
7
  const eslint_1 = require("eslint");
@@ -60,7 +60,7 @@ class GraphQLRuleTester extends eslint_1.RuleTester {
60
60
  // continue;
61
61
  // }
62
62
  //
63
- // const verifyConfig = getVerifyConfig(ruleId, this.config, testCase);
63
+ // const verifyConfig = getVerifyConfig<Options>(ruleId, this.config, testCase);
64
64
  // defineParser(linter, verifyConfig.parser);
65
65
  //
66
66
  // const messages = linter.verify(code, verifyConfig, { filename });
@@ -94,11 +94,10 @@ class GraphQLRuleTester extends eslint_1.RuleTester {
94
94
  }
95
95
  const codeWithMessage = printCode(code, message, 1);
96
96
  messageForSnapshot.push(printWithIndex('#### ❌ Error', index, messages.length), indentCode(codeWithMessage));
97
- const { suggestions } = message;
98
97
  // Don't print suggestions in snapshots for too big codes
99
- if (suggestions && (code.match(/\n/g) || '').length < 1000) {
98
+ if (message.suggestions && (code.match(/\n/g) || '').length < 1000) {
100
99
  for (const [i, suggestion] of message.suggestions.entries()) {
101
- const title = printWithIndex('#### 💡 Suggestion', i, suggestions.length, suggestion.desc);
100
+ const title = printWithIndex('#### 💡 Suggestion', i, message.suggestions.length, suggestion.desc);
102
101
  const output = applyFix(code, suggestion.fix);
103
102
  const codeFrame = printCode(output, { line: 0, column: 0 });
104
103
  messageForSnapshot.push(title, indentCode(codeFrame, 2));
@@ -111,9 +110,7 @@ class GraphQLRuleTester extends eslint_1.RuleTester {
111
110
  messageForSnapshot.push('#### 🔧 Autofix output', indentCode(printCode(output)));
112
111
  }
113
112
  }
114
- // @ts-expect-error -- we should import `vitest` but somebody could use globals from `jest`
115
113
  it(name || `Invalid #${idx + 1}`, () => {
116
- // @ts-expect-error -- ^ same
117
114
  expect(messageForSnapshot.join('\n\n')).toMatchSnapshot();
118
115
  });
119
116
  }
package/cjs/utils.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- 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.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 graphql_1 = require("graphql");
6
6
  const lodash_lowercase_1 = tslib_1.__importDefault(require("lodash.lowercase"));
@@ -25,16 +25,18 @@ function requireGraphQLSchemaFromContext(ruleId, context) {
25
25
  }
26
26
  exports.requireGraphQLSchemaFromContext = requireGraphQLSchemaFromContext;
27
27
  exports.logger = {
28
+ error: (...args) =>
28
29
  // eslint-disable-next-line no-console
29
- error: (...args) => console.error(chalk_1.default.red('error'), '[graphql-eslint]', (0, chalk_1.default)(...args)),
30
+ console.error(chalk_1.default.red('error'), '[graphql-eslint]', (0, chalk_1.default)(...args)),
31
+ warn: (...args) =>
30
32
  // eslint-disable-next-line no-console
31
- warn: (...args) => console.warn(chalk_1.default.yellow('warning'), '[graphql-eslint]', (0, chalk_1.default)(...args)),
33
+ console.warn(chalk_1.default.yellow('warning'), '[graphql-eslint]', (0, chalk_1.default)(...args)),
32
34
  };
33
35
  const normalizePath = (path) => (path || '').replace(/\\/g, '/');
34
36
  exports.normalizePath = normalizePath;
35
37
  exports.VIRTUAL_DOCUMENT_REGEX = /\/\d+_document.graphql$/;
36
38
  exports.CWD = process.cwd();
37
- const getTypeName = (node) => 'type' in node ? (0, exports.getTypeName)(node.type) : node.name.value;
39
+ const getTypeName = (node) => 'type' in node ? (0, exports.getTypeName)(node.type) : 'name' in node && node.name ? node.name.value : '';
38
40
  exports.getTypeName = getTypeName;
39
41
  exports.TYPES_KINDS = [
40
42
  graphql_1.Kind.OBJECT_TYPE_DEFINITION,
@@ -92,5 +94,9 @@ exports.ARRAY_DEFAULT_OPTIONS = {
92
94
  type: 'string',
93
95
  },
94
96
  };
95
- const englishJoinWords = words => new Intl.ListFormat('en-US', { type: 'disjunction' }).format(words);
97
+ const englishJoinWords = (words) => new Intl.ListFormat('en-US', { type: 'disjunction' }).format(words);
96
98
  exports.englishJoinWords = englishJoinWords;
99
+ function truthy(value) {
100
+ return Boolean(value);
101
+ }
102
+ exports.truthy = truthy;
package/esm/cache.js CHANGED
@@ -11,11 +11,12 @@ export class ModuleCache {
11
11
  log('setting entry for', cacheKey);
12
12
  }
13
13
  get(cacheKey, settings = { lifetime: 10 /* seconds */ }) {
14
- if (!this.map.has(cacheKey)) {
14
+ const value = this.map.get(cacheKey);
15
+ if (!value) {
15
16
  log('cache miss for', cacheKey);
16
17
  return;
17
18
  }
18
- const { lastSeen, result } = this.map.get(cacheKey);
19
+ const { lastSeen, result } = value;
19
20
  // check freshness
20
21
  if (process.env.NODE /* don't check for ESLint CLI */ ||
21
22
  process.hrtime(lastSeen)[0] < settings.lifetime) {