@blumintinc/eslint-plugin-blumint 1.7.2 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +39 -62
  2. package/lib/index.js +37 -1
  3. package/lib/rules/enforce-assert-throws.js +48 -3
  4. package/lib/rules/enforce-assertSafe-object-key.d.ts +2 -0
  5. package/lib/rules/enforce-assertSafe-object-key.js +284 -0
  6. package/lib/rules/enforce-centralized-mock-firestore.js +193 -15
  7. package/lib/rules/enforce-firestore-facade.js +8 -0
  8. package/lib/rules/enforce-microdiff.d.ts +3 -0
  9. package/lib/rules/enforce-microdiff.js +379 -0
  10. package/lib/rules/enforce-mock-firestore.js +2 -2
  11. package/lib/rules/enforce-object-literal-as-const.d.ts +4 -0
  12. package/lib/rules/enforce-object-literal-as-const.js +88 -0
  13. package/lib/rules/enforce-positive-naming.d.ts +1 -0
  14. package/lib/rules/enforce-positive-naming.js +363 -0
  15. package/lib/rules/enforce-props-argument-name.d.ts +8 -0
  16. package/lib/rules/enforce-props-argument-name.js +182 -0
  17. package/lib/rules/enforce-render-hits-memoization.js +166 -17
  18. package/lib/rules/enforce-timestamp-now.d.ts +1 -0
  19. package/lib/rules/enforce-timestamp-now.js +223 -0
  20. package/lib/rules/enforce-verb-noun-naming.js +1 -0
  21. package/lib/rules/extract-global-constants.d.ts +1 -1
  22. package/lib/rules/extract-global-constants.js +109 -1
  23. package/lib/rules/global-const-style.js +3 -2
  24. package/lib/rules/no-always-true-false-conditions.d.ts +3 -0
  25. package/lib/rules/no-always-true-false-conditions.js +1202 -0
  26. package/lib/rules/no-firestore-jest-mock.js +27 -4
  27. package/lib/rules/no-mock-firebase-admin.js +21 -8
  28. package/lib/rules/no-type-assertion-returns.d.ts +9 -0
  29. package/lib/rules/no-type-assertion-returns.js +289 -0
  30. package/lib/rules/no-unnecessary-verb-suffix.d.ts +1 -0
  31. package/lib/rules/no-unnecessary-verb-suffix.js +203 -0
  32. package/lib/rules/no-unused-props.js +47 -1
  33. package/lib/rules/prefer-clone-deep.js +294 -22
  34. package/lib/rules/prefer-fragment-component.js +265 -34
  35. package/lib/rules/prefer-global-router-state-key.d.ts +5 -0
  36. package/lib/rules/prefer-global-router-state-key.js +89 -0
  37. package/lib/rules/prefer-utility-function-over-private-static.d.ts +1 -0
  38. package/lib/rules/prefer-utility-function-over-private-static.js +77 -0
  39. package/lib/rules/react-usememo-should-be-component.d.ts +1 -0
  40. package/lib/rules/react-usememo-should-be-component.js +256 -0
  41. package/package.json +5 -5
@@ -0,0 +1,379 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.enforceMicrodiff = void 0;
4
+ const utils_1 = require("@typescript-eslint/utils");
5
+ const createRule_1 = require("../utils/createRule");
6
+ exports.enforceMicrodiff = (0, createRule_1.createRule)({
7
+ name: 'enforce-microdiff',
8
+ meta: {
9
+ type: 'suggestion',
10
+ docs: {
11
+ description: 'Enforce using microdiff for object and array comparison operations',
12
+ recommended: 'error',
13
+ },
14
+ fixable: 'code',
15
+ schema: [],
16
+ messages: {
17
+ enforceMicrodiff: 'Use the microdiff library for object and array comparison operations',
18
+ enforceMicrodiffImport: 'Import diff from microdiff instead of {{importSource}}',
19
+ },
20
+ },
21
+ defaultOptions: [],
22
+ create(context) {
23
+ const sourceCode = context.getSourceCode();
24
+ const importedDiffLibraries = new Map();
25
+ const importedFunctions = new Map(); // Map of imported function names to their sources
26
+ let hasMicrodiffImport = false;
27
+ const reportedNodes = new Set();
28
+ // Add a specific set to track which import names are used
29
+ const usedImportNames = new Set();
30
+ // Check if a node is an object or array type
31
+ function isObjectOrArrayType(node) {
32
+ if (node.type === utils_1.AST_NODE_TYPES.ArrayExpression ||
33
+ node.type === utils_1.AST_NODE_TYPES.ObjectExpression) {
34
+ return true;
35
+ }
36
+ // For identifiers, we'll make a simple assumption based on naming conventions
37
+ if (node.type === utils_1.AST_NODE_TYPES.Identifier) {
38
+ const name = node.name.toLowerCase();
39
+ // Names that likely represent objects or arrays
40
+ if (name.includes('obj') ||
41
+ name.includes('config') ||
42
+ name.includes('options') ||
43
+ name.includes('data') ||
44
+ name.includes('state') ||
45
+ name.includes('props') ||
46
+ name.includes('items') ||
47
+ name.includes('array') ||
48
+ name.includes('list') ||
49
+ name.endsWith('s')) {
50
+ return true;
51
+ }
52
+ }
53
+ // For member expressions, assume they could be objects/arrays
54
+ if (node.type === utils_1.AST_NODE_TYPES.MemberExpression) {
55
+ return true;
56
+ }
57
+ return false;
58
+ }
59
+ return {
60
+ // Track imports of diffing libraries
61
+ ImportDeclaration(node) {
62
+ const importSource = node.source.value;
63
+ // Check for microdiff import
64
+ if (importSource === 'microdiff') {
65
+ hasMicrodiffImport = true;
66
+ return;
67
+ }
68
+ // Track other diffing libraries
69
+ if ([
70
+ 'deep-diff',
71
+ 'fast-diff',
72
+ 'diff',
73
+ 'deep-object-diff',
74
+ 'fast-deep-equal',
75
+ 'fast-deep-equal/es6',
76
+ ].includes(importSource)) {
77
+ // Track imported function names and their sources
78
+ node.specifiers.forEach((specifier) => {
79
+ if (specifier.type === utils_1.AST_NODE_TYPES.ImportSpecifier &&
80
+ (specifier.imported.name === 'diff' ||
81
+ specifier.imported.name === 'diffArrays' ||
82
+ specifier.imported.name === 'detailedDiff')) {
83
+ // Track the local name (which could be different due to renaming)
84
+ const localName = specifier.local.name;
85
+ importedFunctions.set(localName, importSource);
86
+ }
87
+ else if (importSource === 'fast-deep-equal' ||
88
+ importSource === 'fast-deep-equal/es6') {
89
+ // Handle default imports for fast-deep-equal
90
+ if (specifier.type === utils_1.AST_NODE_TYPES.ImportDefaultSpecifier) {
91
+ importedFunctions.set(specifier.local.name, importSource);
92
+ }
93
+ }
94
+ });
95
+ // Report all competing diffing libraries right away
96
+ context.report({
97
+ node,
98
+ messageId: 'enforceMicrodiffImport',
99
+ data: {
100
+ importSource,
101
+ },
102
+ fix(fixer) {
103
+ // If we already have a microdiff import, just remove this import
104
+ if (hasMicrodiffImport) {
105
+ return fixer.remove(node);
106
+ }
107
+ // Otherwise, replace with microdiff import
108
+ return fixer.replaceText(node, `import { diff } from 'microdiff';`);
109
+ },
110
+ });
111
+ // Check if importing a diff function or a known equality library
112
+ const hasDiffImport = node.specifiers.some((specifier) => {
113
+ if (specifier.type === utils_1.AST_NODE_TYPES.ImportSpecifier) {
114
+ return (specifier.imported.name === 'diff' ||
115
+ specifier.imported.name === 'diffArrays' ||
116
+ specifier.imported.name === 'detailedDiff');
117
+ }
118
+ return false;
119
+ });
120
+ if (hasDiffImport ||
121
+ importSource === 'fast-deep-equal' ||
122
+ importSource === 'fast-deep-equal/es6') {
123
+ importedDiffLibraries.set(importSource, node);
124
+ }
125
+ }
126
+ },
127
+ // Check for usage of other diffing libraries
128
+ CallExpression(node) {
129
+ // Skip if we've already reported this node
130
+ if (reportedNodes.has(node)) {
131
+ return;
132
+ }
133
+ const { callee } = node;
134
+ // Check for direct calls to imported diff functions
135
+ if (callee.type === utils_1.AST_NODE_TYPES.Identifier) {
136
+ const name = callee.name;
137
+ // Check if this is a function we specifically imported from a diff library
138
+ if (importedFunctions.has(name)) {
139
+ usedImportNames.add(name);
140
+ // Always report it if it's from a tracked library
141
+ reportedNodes.add(node);
142
+ context.report({
143
+ node,
144
+ messageId: 'enforceMicrodiff',
145
+ fix(fixer) {
146
+ return fixer.replaceText(callee, 'diff');
147
+ },
148
+ });
149
+ return;
150
+ }
151
+ // Check known diff function names
152
+ const isDiffFunction = [
153
+ 'deepDiff',
154
+ 'fastDiff',
155
+ 'diffArrays',
156
+ 'detailedDiff',
157
+ 'fastDeepEqual',
158
+ 'isEqual',
159
+ ].includes(name);
160
+ if (isDiffFunction) {
161
+ // Track this import name as used
162
+ usedImportNames.add(name);
163
+ // Check if we have at least 2 arguments that are objects or arrays
164
+ if (node.arguments.length >= 2 &&
165
+ isObjectOrArrayType(node.arguments[0]) &&
166
+ isObjectOrArrayType(node.arguments[1])) {
167
+ reportedNodes.add(node);
168
+ context.report({
169
+ node,
170
+ messageId: 'enforceMicrodiff',
171
+ fix(fixer) {
172
+ // When handling fast-diff and similar libraries, need to ensure the function name is replaced
173
+ return fixer.replaceText(callee, 'diff');
174
+ },
175
+ });
176
+ }
177
+ }
178
+ }
179
+ // Check for lodash difference functions
180
+ if (callee.type === utils_1.AST_NODE_TYPES.MemberExpression &&
181
+ callee.object.type === utils_1.AST_NODE_TYPES.Identifier &&
182
+ callee.object.name === '_') {
183
+ const property = callee.property;
184
+ if (property.type === utils_1.AST_NODE_TYPES.Identifier &&
185
+ ['difference', 'differenceBy', 'differenceWith'].includes(property.name)) {
186
+ reportedNodes.add(node);
187
+ context.report({
188
+ node,
189
+ messageId: 'enforceMicrodiff',
190
+ fix(fixer) {
191
+ // Replace with microdiff
192
+ return fixer.replaceText(node, `diff(${node.arguments
193
+ .map((arg) => sourceCode.getText(arg))
194
+ .join(', ')})`);
195
+ },
196
+ });
197
+ }
198
+ }
199
+ },
200
+ // Check for manual object comparison patterns
201
+ BinaryExpression(node) {
202
+ // Skip if we've already reported this node or its parent function
203
+ if (reportedNodes.has(node)) {
204
+ return;
205
+ }
206
+ // Find the parent function or method
207
+ let current = node;
208
+ while (current &&
209
+ current.type !== utils_1.AST_NODE_TYPES.FunctionDeclaration &&
210
+ current.type !== utils_1.AST_NODE_TYPES.ArrowFunctionExpression) {
211
+ current = current.parent;
212
+ }
213
+ // If we already reported the parent function, skip this node
214
+ if (current && reportedNodes.has(current)) {
215
+ return;
216
+ }
217
+ // Check for JSON.stringify comparison pattern
218
+ if ((node.operator === '===' || node.operator === '!==') &&
219
+ node.left.type === utils_1.AST_NODE_TYPES.CallExpression &&
220
+ node.right.type === utils_1.AST_NODE_TYPES.CallExpression) {
221
+ const isJsonStringify = (expr) => {
222
+ return (expr.callee.type === utils_1.AST_NODE_TYPES.MemberExpression &&
223
+ expr.callee.object.type === utils_1.AST_NODE_TYPES.Identifier &&
224
+ expr.callee.object.name === 'JSON' &&
225
+ expr.callee.property.type === utils_1.AST_NODE_TYPES.Identifier &&
226
+ expr.callee.property.name === 'stringify');
227
+ };
228
+ if (isJsonStringify(node.left) && isJsonStringify(node.right)) {
229
+ const leftArg = node.left.arguments[0];
230
+ const rightArg = node.right.arguments[0];
231
+ if (isObjectOrArrayType(leftArg) && isObjectOrArrayType(rightArg)) {
232
+ reportedNodes.add(node);
233
+ const isEqual = node.operator === '===';
234
+ context.report({
235
+ node,
236
+ messageId: 'enforceMicrodiff',
237
+ fix(fixer) {
238
+ // Find the containing function to add the import
239
+ let functionNode = node;
240
+ while (functionNode &&
241
+ functionNode.type !== utils_1.AST_NODE_TYPES.FunctionDeclaration &&
242
+ functionNode.type !==
243
+ utils_1.AST_NODE_TYPES.ArrowFunctionExpression &&
244
+ functionNode.type !== utils_1.AST_NODE_TYPES.Program) {
245
+ functionNode = functionNode.parent;
246
+ }
247
+ // If we found a program node and microdiff isn't imported,
248
+ // we'll need to add the import manually
249
+ if (functionNode &&
250
+ functionNode.type === utils_1.AST_NODE_TYPES.Program &&
251
+ !hasMicrodiffImport) {
252
+ // Need to add an import
253
+ const importFix = fixer.insertTextBeforeRange([0, 0], "import { diff } from 'microdiff';\n\n");
254
+ // Replace JSON.stringify comparison
255
+ const compareFix = fixer.replaceText(node, `diff(${sourceCode.getText(leftArg)}, ${sourceCode.getText(rightArg)})${isEqual ? '.length === 0' : '.length > 0'}`);
256
+ return [importFix, compareFix];
257
+ }
258
+ // Otherwise just replace the comparison
259
+ return fixer.replaceText(node, `diff(${sourceCode.getText(leftArg)}, ${sourceCode.getText(rightArg)})${isEqual ? '.length === 0' : '.length > 0'}`);
260
+ },
261
+ });
262
+ }
263
+ }
264
+ }
265
+ },
266
+ // Check for custom deep comparison functions
267
+ FunctionDeclaration(node) {
268
+ // Skip if we've already reported this node
269
+ if (reportedNodes.has(node)) {
270
+ return;
271
+ }
272
+ // Look for functions that might be implementing diff logic
273
+ if (node.id &&
274
+ [
275
+ 'detectChanges',
276
+ 'hasConfigChanged',
277
+ 'compareObjects',
278
+ 'compareArrays',
279
+ 'findChanges',
280
+ 'detectDifferences',
281
+ 'hasStateChanged',
282
+ 'stateHasUpdated',
283
+ 'arrayHasChanged',
284
+ 'settingsChanged',
285
+ ].includes(node.id.name)) {
286
+ // Check if function has two parameters that might be objects/arrays
287
+ if (node.params.length >= 2) {
288
+ const body = node.body;
289
+ const bodyText = sourceCode.getText(body);
290
+ // Check if the function body contains a JSON.stringify comparison
291
+ if (node.id.name === 'hasConfigChanged' &&
292
+ bodyText.includes('JSON.stringify') &&
293
+ bodyText.includes('!==')) {
294
+ reportedNodes.add(node);
295
+ const param1 = sourceCode.getText(node.params[0]);
296
+ const param2 = sourceCode.getText(node.params[1]);
297
+ context.report({
298
+ node,
299
+ messageId: 'enforceMicrodiff',
300
+ fix(fixer) {
301
+ // Create a new version of the function with microdiff
302
+ const newFunctionBody = `{
303
+ return diff(${param1}, ${param2}).length > 0;
304
+ }`;
305
+ if (!hasMicrodiffImport) {
306
+ // Create a new import statement
307
+ return fixer.replaceText(node, `import { diff } from 'microdiff';\n\nfunction ${node.id?.name}(${param1}, ${param2}) ${newFunctionBody}`);
308
+ }
309
+ else {
310
+ // Just replace the function body
311
+ return fixer.replaceText(body, newFunctionBody);
312
+ }
313
+ },
314
+ });
315
+ return;
316
+ }
317
+ // Look for patterns that suggest object/array comparison
318
+ const hasComparisonLogic = bodyText.includes('JSON.stringify') ||
319
+ bodyText.includes('Object.keys') ||
320
+ bodyText.includes('for (') ||
321
+ bodyText.includes('.some(') ||
322
+ bodyText.includes('.every(');
323
+ if (hasComparisonLogic) {
324
+ reportedNodes.add(node);
325
+ context.report({
326
+ node,
327
+ messageId: 'enforceMicrodiff',
328
+ });
329
+ }
330
+ }
331
+ }
332
+ },
333
+ // Check for custom deep comparison in arrow functions
334
+ ArrowFunctionExpression(node) {
335
+ // Skip if we've already reported this node
336
+ if (reportedNodes.has(node)) {
337
+ return;
338
+ }
339
+ // Only check arrow functions assigned to variables with comparison-like names
340
+ const parent = node.parent;
341
+ if (parent &&
342
+ parent.type === utils_1.AST_NODE_TYPES.VariableDeclarator &&
343
+ parent.id.type === utils_1.AST_NODE_TYPES.Identifier &&
344
+ [
345
+ 'detectChanges',
346
+ 'hasConfigChanged',
347
+ 'compareObjects',
348
+ 'compareArrays',
349
+ 'findChanges',
350
+ 'detectDifferences',
351
+ 'hasStateChanged',
352
+ 'stateHasUpdated',
353
+ 'arrayHasChanged',
354
+ 'settingsChanged',
355
+ ].includes(parent.id.name)) {
356
+ // Check if function has two parameters that might be objects/arrays
357
+ if (node.params.length >= 2) {
358
+ const body = node.body;
359
+ // Look for patterns that suggest object/array comparison
360
+ const bodyText = sourceCode.getText(body);
361
+ const hasComparisonLogic = bodyText.includes('JSON.stringify') ||
362
+ bodyText.includes('Object.keys') ||
363
+ bodyText.includes('for (') ||
364
+ bodyText.includes('.some(') ||
365
+ bodyText.includes('.every(');
366
+ if (hasComparisonLogic) {
367
+ reportedNodes.add(node);
368
+ context.report({
369
+ node,
370
+ messageId: 'enforceMicrodiff',
371
+ });
372
+ }
373
+ }
374
+ }
375
+ },
376
+ };
377
+ },
378
+ });
379
+ //# sourceMappingURL=enforce-microdiff.js.map
@@ -18,8 +18,8 @@ exports.enforceFirestoreMock = (0, createRule_1.createRule)({
18
18
  },
19
19
  schema: [],
20
20
  messages: {
21
- noManualFirestoreMock: 'Use mockFirestore from __mocks__/functions/src/config/mockFirestore instead of manually mocking Firestore. Replace `jest.mock("firebase-admin", () => ({ firestore: () => ({ /* mock */ }) }))` with `import { mockFirestore } from "__mocks__/functions/src/config/mockFirestore"; jest.mock("firebase-admin", () => mockFirestore)`.',
22
- noMockFirebase: 'Use mockFirestore from __mocks__/functions/src/config/mockFirestore instead of mockFirebase. Replace `import { mockFirebase } from "firestore-jest-mock"` with `import { mockFirestore } from "__mocks__/functions/src/config/mockFirestore"`.',
21
+ noManualFirestoreMock: 'Use mockFirestore from __test-utils__/mockFirestore instead of manually mocking Firestore. Replace `jest.mock("firebase-admin", () => ({ firestore: () => ({ /* mock */ }) }))` with `import { mockFirestore } from "__test-utils__/mockFirestore"; jest.mock("firebase-admin", () => mockFirestore)`.',
22
+ noMockFirebase: 'Use mockFirestore from __test-utils__/mockFirestore instead of mockFirebase. Replace `import { mockFirebase } from "firestore-jest-mock"` with `import { mockFirestore } from "__test-utils__/mockFirestore"`.',
23
23
  },
24
24
  },
25
25
  defaultOptions: [],
@@ -0,0 +1,4 @@
1
+ import { TSESTree } from '@typescript-eslint/utils';
2
+ export declare const enforceObjectLiteralAsConst: import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleModule<"enforceAsConst", never[], {
3
+ ReturnStatement(node: TSESTree.ReturnStatement): void;
4
+ }>;
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.enforceObjectLiteralAsConst = void 0;
4
+ const createRule_1 = require("../utils/createRule");
5
+ exports.enforceObjectLiteralAsConst = (0, createRule_1.createRule)({
6
+ name: 'enforce-object-literal-as-const',
7
+ meta: {
8
+ type: 'suggestion',
9
+ docs: {
10
+ description: 'Enforce that object literals returned from functions should be marked with `as const` to ensure type safety and immutability.',
11
+ recommended: 'error',
12
+ },
13
+ fixable: 'code',
14
+ messages: {
15
+ enforceAsConst: 'Object literals returned from functions should be marked with `as const` to ensure type safety and immutability',
16
+ },
17
+ schema: [],
18
+ },
19
+ defaultOptions: [],
20
+ create(context) {
21
+ return {
22
+ ReturnStatement(node) {
23
+ // Skip if there's no argument in the return statement
24
+ if (!node.argument) {
25
+ return;
26
+ }
27
+ // Check if the return statement is inside a function
28
+ const sourceCode = context.getSourceCode();
29
+ // Use context.getAncestors() for now, but note it's deprecated
30
+ // We'll need to update this when upgrading to ESLint v9
31
+ const ancestors = context.getAncestors();
32
+ const isInFunction = ancestors.some((ancestor) => ancestor.type === 'FunctionDeclaration' ||
33
+ ancestor.type === 'ArrowFunctionExpression' ||
34
+ ancestor.type === 'FunctionExpression' ||
35
+ ancestor.type === 'MethodDefinition');
36
+ if (!isInFunction) {
37
+ return;
38
+ }
39
+ // Check if the return value is an object or array literal
40
+ const { argument } = node;
41
+ // Skip if the return value already has 'as const' assertion
42
+ if (argument.type === 'TSAsExpression') {
43
+ const tsAsExpression = argument;
44
+ // Check if the type annotation is 'const'
45
+ if (tsAsExpression.typeAnnotation.type === 'TSTypeReference' &&
46
+ tsAsExpression.typeAnnotation.typeName.type === 'Identifier' &&
47
+ tsAsExpression.typeAnnotation.typeName.name === 'const') {
48
+ return;
49
+ }
50
+ // If it has another type assertion but not 'as const', we still need to check
51
+ // if the expression is an object/array literal
52
+ if (tsAsExpression.expression.type !== 'ObjectExpression' &&
53
+ tsAsExpression.expression.type !== 'ArrayExpression') {
54
+ return;
55
+ }
56
+ }
57
+ else if (argument.type !== 'ObjectExpression' &&
58
+ argument.type !== 'ArrayExpression') {
59
+ // Skip if not an object/array literal and not a type assertion
60
+ return;
61
+ }
62
+ // Skip if the return value uses spread operator
63
+ if ((argument.type === 'ObjectExpression' &&
64
+ argument.properties.some((prop) => prop.type === 'SpreadElement')) ||
65
+ (argument.type === 'ArrayExpression' &&
66
+ argument.elements.some((elem) => elem !== null && elem.type === 'SpreadElement'))) {
67
+ return;
68
+ }
69
+ // Report the issue and provide a fix
70
+ context.report({
71
+ node,
72
+ messageId: 'enforceAsConst',
73
+ fix(fixer) {
74
+ const text = sourceCode.getText(argument);
75
+ // If it's already a type assertion but not 'as const'
76
+ if (argument.type === 'TSAsExpression') {
77
+ // Get the expression part (before the 'as')
78
+ const expressionText = sourceCode.getText(argument.expression);
79
+ return fixer.replaceText(argument, `${expressionText} as const`);
80
+ }
81
+ return fixer.replaceText(argument, `${text} as const`);
82
+ },
83
+ });
84
+ },
85
+ };
86
+ },
87
+ });
88
+ //# sourceMappingURL=enforce-object-literal-as-const.js.map
@@ -0,0 +1 @@
1
+ export declare const enforcePositiveNaming: import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleModule<"avoidNegativeNaming", [], import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleListener>;