@graphql-eslint/eslint-plugin 3.14.3 → 3.14.4-alpha-20221229152648-0a153c6

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