@blumintinc/eslint-plugin-blumint 1.16.2 → 1.17.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.
- package/README.md +21 -0
- package/lib/index.js +64 -1
- package/lib/rules/enforce-boolean-naming-prefixes.js +30 -14
- package/lib/rules/enforce-cloud-function-id-length.d.ts +5 -0
- package/lib/rules/enforce-cloud-function-id-length.js +104 -0
- package/lib/rules/enforce-is-prefix-validators.d.ts +13 -0
- package/lib/rules/enforce-is-prefix-validators.js +304 -0
- package/lib/rules/enforce-m3-sentence-case.d.ts +12 -0
- package/lib/rules/enforce-m3-sentence-case.js +430 -0
- package/lib/rules/enforce-snapshot-state-narrowing.d.ts +10 -0
- package/lib/rules/enforce-snapshot-state-narrowing.js +281 -0
- package/lib/rules/enforce-types-directory-placement.d.ts +9 -0
- package/lib/rules/enforce-types-directory-placement.js +276 -0
- package/lib/rules/no-direct-function-state.d.ts +8 -0
- package/lib/rules/no-direct-function-state.js +285 -0
- package/lib/rules/no-fill-template-mutation.d.ts +1 -0
- package/lib/rules/no-fill-template-mutation.js +324 -0
- package/lib/rules/no-portal-inside-tooltip.d.ts +10 -0
- package/lib/rules/no-portal-inside-tooltip.js +219 -0
- package/lib/rules/no-redundant-boolean-callback-props.d.ts +11 -0
- package/lib/rules/no-redundant-boolean-callback-props.js +355 -0
- package/lib/rules/no-satisfies-in-frontend-bundle.d.ts +8 -0
- package/lib/rules/no-satisfies-in-frontend-bundle.js +126 -0
- package/lib/rules/no-single-dismiss-dialog-button.d.ts +7 -0
- package/lib/rules/no-single-dismiss-dialog-button.js +127 -0
- package/lib/rules/no-stablehash-react-nodes.d.ts +1 -0
- package/lib/rules/no-stablehash-react-nodes.js +325 -0
- package/lib/rules/parallelize-loop-awaits.d.ts +8 -0
- package/lib/rules/parallelize-loop-awaits.js +582 -0
- package/lib/rules/prefer-flat-transform-each-keys.d.ts +1 -0
- package/lib/rules/prefer-flat-transform-each-keys.js +228 -0
- package/lib/rules/prefer-getter-over-parameterless-method.d.ts +1 -0
- package/lib/rules/prefer-getter-over-parameterless-method.js +44 -0
- package/lib/rules/prefer-spread-over-reassembly.d.ts +5 -0
- package/lib/rules/prefer-spread-over-reassembly.js +401 -0
- package/lib/rules/prefer-sx-prop-over-system-props.d.ts +9 -0
- package/lib/rules/prefer-sx-prop-over-system-props.js +401 -0
- package/lib/rules/prefer-use-base62-id.d.ts +8 -0
- package/lib/rules/prefer-use-base62-id.js +483 -0
- package/lib/rules/prefer-use-theme.d.ts +1 -0
- package/lib/rules/prefer-use-theme.js +206 -0
- package/lib/rules/prefer-utility-function-own-file.d.ts +9 -0
- package/lib/rules/prefer-utility-function-own-file.js +505 -0
- package/lib/rules/require-props-composition.d.ts +10 -0
- package/lib/rules/require-props-composition.js +433 -0
- package/lib/rules/require-server-timestamp-for-firestore-dates.d.ts +9 -0
- package/lib/rules/require-server-timestamp-for-firestore-dates.js +313 -0
- package/package.json +1 -1
- package/release-manifest.json +190 -0
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.preferSxPropOverSystemProps = void 0;
|
|
4
|
+
const utils_1 = require("@typescript-eslint/utils");
|
|
5
|
+
const createRule_1 = require("../utils/createRule");
|
|
6
|
+
/**
|
|
7
|
+
* The canonical set of MUI system props that are deprecated in favor of `sx`.
|
|
8
|
+
* These are all props that MUI resolves via its system/styled engine and will
|
|
9
|
+
* remove in the next major release. Deliberately excludes props that serve a
|
|
10
|
+
* dual role as real component API (e.g. `spacing`, `direction` on Stack,
|
|
11
|
+
* Grid breakpoint props).
|
|
12
|
+
*/
|
|
13
|
+
const MUI_SYSTEM_PROPS = new Set([
|
|
14
|
+
// Spacing — margin
|
|
15
|
+
'm',
|
|
16
|
+
'mt',
|
|
17
|
+
'mr',
|
|
18
|
+
'mb',
|
|
19
|
+
'ml',
|
|
20
|
+
'mx',
|
|
21
|
+
'my',
|
|
22
|
+
// Spacing — padding
|
|
23
|
+
'p',
|
|
24
|
+
'pt',
|
|
25
|
+
'pr',
|
|
26
|
+
'pb',
|
|
27
|
+
'pl',
|
|
28
|
+
'px',
|
|
29
|
+
'py',
|
|
30
|
+
// Sizing
|
|
31
|
+
'width',
|
|
32
|
+
'height',
|
|
33
|
+
'minWidth',
|
|
34
|
+
'maxWidth',
|
|
35
|
+
'minHeight',
|
|
36
|
+
'maxHeight',
|
|
37
|
+
'boxSizing',
|
|
38
|
+
// Display / overflow / visibility
|
|
39
|
+
'display',
|
|
40
|
+
'displayPrint',
|
|
41
|
+
'overflow',
|
|
42
|
+
'textOverflow',
|
|
43
|
+
'visibility',
|
|
44
|
+
'whiteSpace',
|
|
45
|
+
// Flexbox
|
|
46
|
+
'flexDirection',
|
|
47
|
+
'flexWrap',
|
|
48
|
+
'justifyContent',
|
|
49
|
+
'justifyItems',
|
|
50
|
+
'justifySelf',
|
|
51
|
+
'alignItems',
|
|
52
|
+
'alignContent',
|
|
53
|
+
'alignSelf',
|
|
54
|
+
'order',
|
|
55
|
+
'flex',
|
|
56
|
+
'flexGrow',
|
|
57
|
+
'flexShrink',
|
|
58
|
+
'flexBasis',
|
|
59
|
+
// CSS Grid
|
|
60
|
+
'gap',
|
|
61
|
+
'rowGap',
|
|
62
|
+
'columnGap',
|
|
63
|
+
'gridColumn',
|
|
64
|
+
'gridRow',
|
|
65
|
+
'gridArea',
|
|
66
|
+
'gridAutoFlow',
|
|
67
|
+
'gridAutoColumns',
|
|
68
|
+
'gridAutoRows',
|
|
69
|
+
'gridTemplateColumns',
|
|
70
|
+
'gridTemplateRows',
|
|
71
|
+
'gridTemplateAreas',
|
|
72
|
+
// Positioning
|
|
73
|
+
'position',
|
|
74
|
+
'top',
|
|
75
|
+
'right',
|
|
76
|
+
'bottom',
|
|
77
|
+
'left',
|
|
78
|
+
'zIndex',
|
|
79
|
+
// Color / background
|
|
80
|
+
'color',
|
|
81
|
+
'bgcolor',
|
|
82
|
+
// Borders
|
|
83
|
+
'border',
|
|
84
|
+
'borderTop',
|
|
85
|
+
'borderRight',
|
|
86
|
+
'borderBottom',
|
|
87
|
+
'borderLeft',
|
|
88
|
+
'borderColor',
|
|
89
|
+
'borderTopColor',
|
|
90
|
+
'borderRightColor',
|
|
91
|
+
'borderBottomColor',
|
|
92
|
+
'borderLeftColor',
|
|
93
|
+
'borderRadius',
|
|
94
|
+
// Shadows
|
|
95
|
+
'boxShadow',
|
|
96
|
+
// Typography
|
|
97
|
+
'typography',
|
|
98
|
+
'fontFamily',
|
|
99
|
+
'fontSize',
|
|
100
|
+
'fontStyle',
|
|
101
|
+
'fontWeight',
|
|
102
|
+
'letterSpacing',
|
|
103
|
+
'lineHeight',
|
|
104
|
+
'textAlign',
|
|
105
|
+
'textTransform',
|
|
106
|
+
]);
|
|
107
|
+
/**
|
|
108
|
+
* Default MUI component names to check. The user can extend this via options.
|
|
109
|
+
*/
|
|
110
|
+
const DEFAULT_MUI_COMPONENTS = new Set([
|
|
111
|
+
'Box',
|
|
112
|
+
'Stack',
|
|
113
|
+
'Typography',
|
|
114
|
+
'Grid',
|
|
115
|
+
'Paper',
|
|
116
|
+
'Container',
|
|
117
|
+
'Card',
|
|
118
|
+
'CardContent',
|
|
119
|
+
'CardActions',
|
|
120
|
+
'Button',
|
|
121
|
+
'IconButton',
|
|
122
|
+
'Chip',
|
|
123
|
+
'Avatar',
|
|
124
|
+
'Badge',
|
|
125
|
+
'Divider',
|
|
126
|
+
'List',
|
|
127
|
+
'ListItem',
|
|
128
|
+
'ListItemText',
|
|
129
|
+
'ListItemIcon',
|
|
130
|
+
'Menu',
|
|
131
|
+
'MenuItem',
|
|
132
|
+
'Drawer',
|
|
133
|
+
'Dialog',
|
|
134
|
+
'DialogTitle',
|
|
135
|
+
'DialogContent',
|
|
136
|
+
'DialogActions',
|
|
137
|
+
'Tabs',
|
|
138
|
+
'Tab',
|
|
139
|
+
'AppBar',
|
|
140
|
+
'Toolbar',
|
|
141
|
+
]);
|
|
142
|
+
/**
|
|
143
|
+
* Props that must never be moved to `sx` because they are genuine component
|
|
144
|
+
* API props, not MUI system styling shorthands. `direction` and `spacing` are
|
|
145
|
+
* the most critical — they control Stack's layout via MUI internals.
|
|
146
|
+
*/
|
|
147
|
+
const DEFAULT_ALLOWED_PROPS = new Set([
|
|
148
|
+
'direction',
|
|
149
|
+
'spacing',
|
|
150
|
+
'container',
|
|
151
|
+
'item',
|
|
152
|
+
'xs',
|
|
153
|
+
'sm',
|
|
154
|
+
'md',
|
|
155
|
+
'lg',
|
|
156
|
+
'xl',
|
|
157
|
+
'variant',
|
|
158
|
+
'component',
|
|
159
|
+
'ref',
|
|
160
|
+
'key',
|
|
161
|
+
'children',
|
|
162
|
+
'id',
|
|
163
|
+
'className',
|
|
164
|
+
'style',
|
|
165
|
+
'divider',
|
|
166
|
+
'useFlexGap',
|
|
167
|
+
'columns',
|
|
168
|
+
'wrap',
|
|
169
|
+
'rowSpacing',
|
|
170
|
+
'columnSpacing',
|
|
171
|
+
'zeroMinWidth',
|
|
172
|
+
'offset',
|
|
173
|
+
'size', // Grid size (MUI v6+)
|
|
174
|
+
]);
|
|
175
|
+
/** Get the component name from a JSX opening element (handles namespaced like Mui.Box). */
|
|
176
|
+
function getComponentName(node) {
|
|
177
|
+
const { name } = node;
|
|
178
|
+
if (name.type === utils_1.AST_NODE_TYPES.JSXIdentifier) {
|
|
179
|
+
return name.name;
|
|
180
|
+
}
|
|
181
|
+
if (name.type === utils_1.AST_NODE_TYPES.JSXMemberExpression) {
|
|
182
|
+
if (name.property.type === utils_1.AST_NODE_TYPES.JSXIdentifier) {
|
|
183
|
+
return name.property.name;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
/** True when the first character is uppercase (i.e. a React/MUI component). */
|
|
189
|
+
function isUpperCase(name) {
|
|
190
|
+
return (name.length > 0 &&
|
|
191
|
+
name[0] === name[0].toUpperCase() &&
|
|
192
|
+
name[0] !== name[0].toLowerCase());
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Convert a string value to a single-quoted JS string literal.
|
|
196
|
+
* Used when building sx property values from JSX string attributes.
|
|
197
|
+
*/
|
|
198
|
+
function toSingleQuoted(value) {
|
|
199
|
+
const str = String(value);
|
|
200
|
+
const escaped = str.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
|
|
201
|
+
return `'${escaped}'`;
|
|
202
|
+
}
|
|
203
|
+
/** Serialize a JSX attribute value node back to source text for use inside sx={{ ... }}. */
|
|
204
|
+
function attrValueToSxValue(attr, sourceCode) {
|
|
205
|
+
const { value } = attr;
|
|
206
|
+
if (value === null) {
|
|
207
|
+
// Boolean shorthand — value is `true`
|
|
208
|
+
return 'true';
|
|
209
|
+
}
|
|
210
|
+
if (value.type === utils_1.AST_NODE_TYPES.Literal) {
|
|
211
|
+
// String literal attribute: display="flex" → 'flex'
|
|
212
|
+
return toSingleQuoted(value.value);
|
|
213
|
+
}
|
|
214
|
+
if (value.type === utils_1.AST_NODE_TYPES.JSXExpressionContainer) {
|
|
215
|
+
if (value.expression.type === utils_1.AST_NODE_TYPES.JSXEmptyExpression) {
|
|
216
|
+
return 'undefined';
|
|
217
|
+
}
|
|
218
|
+
// Numeric, expression, object, array, etc. — preserve raw source
|
|
219
|
+
return sourceCode.getText(value.expression);
|
|
220
|
+
}
|
|
221
|
+
return sourceCode.getText(value);
|
|
222
|
+
}
|
|
223
|
+
exports.preferSxPropOverSystemProps = (0, createRule_1.createRule)({
|
|
224
|
+
name: 'prefer-sx-prop-over-system-props',
|
|
225
|
+
meta: {
|
|
226
|
+
type: 'suggestion',
|
|
227
|
+
docs: {
|
|
228
|
+
description: 'Enforce using the MUI `sx` prop instead of deprecated system props (e.g. `mt`, `display`, `flexDirection`) on MUI components.',
|
|
229
|
+
recommended: 'error',
|
|
230
|
+
},
|
|
231
|
+
fixable: 'code',
|
|
232
|
+
schema: [
|
|
233
|
+
{
|
|
234
|
+
type: 'object',
|
|
235
|
+
properties: {
|
|
236
|
+
components: {
|
|
237
|
+
type: 'array',
|
|
238
|
+
items: { type: 'string' },
|
|
239
|
+
},
|
|
240
|
+
allowedProps: {
|
|
241
|
+
type: 'array',
|
|
242
|
+
items: { type: 'string' },
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
additionalProperties: false,
|
|
246
|
+
},
|
|
247
|
+
],
|
|
248
|
+
messages: {
|
|
249
|
+
preferSxProp: 'MUI system prop "{{prop}}" is deprecated. Move it into the `sx` prop instead.',
|
|
250
|
+
},
|
|
251
|
+
},
|
|
252
|
+
defaultOptions: [{}],
|
|
253
|
+
create(context, [options]) {
|
|
254
|
+
const componentSet = options.components
|
|
255
|
+
? new Set(options.components)
|
|
256
|
+
: DEFAULT_MUI_COMPONENTS;
|
|
257
|
+
const extraAllowed = options.allowedProps
|
|
258
|
+
? new Set(options.allowedProps)
|
|
259
|
+
: new Set();
|
|
260
|
+
function isAllowedProp(name) {
|
|
261
|
+
if (DEFAULT_ALLOWED_PROPS.has(name))
|
|
262
|
+
return true;
|
|
263
|
+
if (extraAllowed.has(name))
|
|
264
|
+
return true;
|
|
265
|
+
if (/^on[A-Z]/.test(name))
|
|
266
|
+
return true;
|
|
267
|
+
if (name.startsWith('aria-') || name.startsWith('data-'))
|
|
268
|
+
return true;
|
|
269
|
+
return false;
|
|
270
|
+
}
|
|
271
|
+
function isSystemProp(name) {
|
|
272
|
+
return MUI_SYSTEM_PROPS.has(name) && !isAllowedProp(name);
|
|
273
|
+
}
|
|
274
|
+
return {
|
|
275
|
+
JSXOpeningElement(node) {
|
|
276
|
+
const componentName = getComponentName(node);
|
|
277
|
+
if (!componentName)
|
|
278
|
+
return;
|
|
279
|
+
if (!isUpperCase(componentName))
|
|
280
|
+
return;
|
|
281
|
+
if (!componentSet.has(componentName))
|
|
282
|
+
return;
|
|
283
|
+
const systemPropAttrs = [];
|
|
284
|
+
let sxAttr = null;
|
|
285
|
+
for (const attr of node.attributes) {
|
|
286
|
+
if (attr.type !== utils_1.AST_NODE_TYPES.JSXAttribute)
|
|
287
|
+
continue;
|
|
288
|
+
if (attr.name.type !== utils_1.AST_NODE_TYPES.JSXIdentifier)
|
|
289
|
+
continue;
|
|
290
|
+
const name = attr.name.name;
|
|
291
|
+
if (name === 'sx') {
|
|
292
|
+
sxAttr = attr;
|
|
293
|
+
}
|
|
294
|
+
else if (isSystemProp(name)) {
|
|
295
|
+
systemPropAttrs.push(attr);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
if (systemPropAttrs.length === 0)
|
|
299
|
+
return;
|
|
300
|
+
const sourceCode = context.getSourceCode();
|
|
301
|
+
const fullSource = sourceCode.getText();
|
|
302
|
+
/**
|
|
303
|
+
* Remove an attribute AND the whitespace that precedes it so the
|
|
304
|
+
* output does not accumulate extra spaces between attributes.
|
|
305
|
+
*/
|
|
306
|
+
function removeAttrWithLeadingSpace(fixer, attr) {
|
|
307
|
+
const range = attr.range ?? [0, 0];
|
|
308
|
+
const [start, end] = range;
|
|
309
|
+
// Walk backwards from the attribute start to consume any whitespace
|
|
310
|
+
let wsStart = start;
|
|
311
|
+
while (wsStart > 0 && /\s/.test(fullSource[wsStart - 1])) {
|
|
312
|
+
wsStart--;
|
|
313
|
+
}
|
|
314
|
+
return fixer.removeRange([wsStart, end]);
|
|
315
|
+
}
|
|
316
|
+
// Report each system prop. Only the first carries the fixer to avoid
|
|
317
|
+
// overlapping fix ranges on the same element.
|
|
318
|
+
systemPropAttrs.forEach((attr, index) => {
|
|
319
|
+
const propName = attr.name.type === utils_1.AST_NODE_TYPES.JSXIdentifier
|
|
320
|
+
? attr.name.name
|
|
321
|
+
: '';
|
|
322
|
+
context.report({
|
|
323
|
+
node: attr,
|
|
324
|
+
messageId: 'preferSxProp',
|
|
325
|
+
data: { prop: propName },
|
|
326
|
+
fix: index === 0
|
|
327
|
+
? (fixer) => {
|
|
328
|
+
const sc = sourceCode;
|
|
329
|
+
const newEntries = systemPropAttrs
|
|
330
|
+
.map((a) => {
|
|
331
|
+
const key = a.name.type === utils_1.AST_NODE_TYPES.JSXIdentifier
|
|
332
|
+
? a.name.name
|
|
333
|
+
: sc.getText(a.name);
|
|
334
|
+
const val = attrValueToSxValue(a, sc);
|
|
335
|
+
return `${key}: ${val}`;
|
|
336
|
+
})
|
|
337
|
+
.join(', ');
|
|
338
|
+
const fixes = [];
|
|
339
|
+
if (sxAttr === null) {
|
|
340
|
+
// No existing sx — replace the first system prop with sx={{...}}
|
|
341
|
+
// and delete the rest (including their leading whitespace).
|
|
342
|
+
fixes.push(fixer.replaceText(systemPropAttrs[0], `sx={{ ${newEntries} }}`));
|
|
343
|
+
for (let i = 1; i < systemPropAttrs.length; i++) {
|
|
344
|
+
fixes.push(removeAttrWithLeadingSpace(fixer, systemPropAttrs[i]));
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
else if (sxAttr.value?.type ===
|
|
348
|
+
utils_1.AST_NODE_TYPES.JSXExpressionContainer &&
|
|
349
|
+
sxAttr.value.expression.type ===
|
|
350
|
+
utils_1.AST_NODE_TYPES.ObjectExpression) {
|
|
351
|
+
// Existing sx={{ ... }} — merge system props at the front.
|
|
352
|
+
const existingObj = sxAttr.value.expression;
|
|
353
|
+
const existingProps = existingObj.properties;
|
|
354
|
+
if (existingProps.length === 0) {
|
|
355
|
+
fixes.push(fixer.replaceText(existingObj, `{ ${newEntries} }`));
|
|
356
|
+
}
|
|
357
|
+
else {
|
|
358
|
+
fixes.push(fixer.insertTextBefore(existingProps[0], `${newEntries}, `));
|
|
359
|
+
}
|
|
360
|
+
for (const a of systemPropAttrs) {
|
|
361
|
+
fixes.push(removeAttrWithLeadingSpace(fixer, a));
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
else if (sxAttr.value?.type ===
|
|
365
|
+
utils_1.AST_NODE_TYPES.JSXExpressionContainer &&
|
|
366
|
+
sxAttr.value.expression.type ===
|
|
367
|
+
utils_1.AST_NODE_TYPES.ArrayExpression) {
|
|
368
|
+
// sx={[...]} — prepend a new object as the first array element.
|
|
369
|
+
const arr = sxAttr.value.expression;
|
|
370
|
+
if (arr.elements.length === 0) {
|
|
371
|
+
fixes.push(fixer.replaceText(arr, `[{ ${newEntries} }]`));
|
|
372
|
+
}
|
|
373
|
+
else {
|
|
374
|
+
fixes.push(fixer.insertTextBefore(arr.elements[0], `{ ${newEntries} }, `));
|
|
375
|
+
}
|
|
376
|
+
for (const a of systemPropAttrs) {
|
|
377
|
+
fixes.push(removeAttrWithLeadingSpace(fixer, a));
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
else if (sxAttr.value !== null) {
|
|
381
|
+
// sx is a variable/expression — spread it: sx={{ entries, ...expr }}
|
|
382
|
+
const innerExpr = sxAttr.value.type ===
|
|
383
|
+
utils_1.AST_NODE_TYPES.JSXExpressionContainer
|
|
384
|
+
? sc.getText(sxAttr.value
|
|
385
|
+
.expression)
|
|
386
|
+
: sc.getText(sxAttr.value);
|
|
387
|
+
fixes.push(fixer.replaceText(sxAttr, `sx={{ ${newEntries}, ...${innerExpr} }}`));
|
|
388
|
+
for (const a of systemPropAttrs) {
|
|
389
|
+
fixes.push(removeAttrWithLeadingSpace(fixer, a));
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
return fixes;
|
|
393
|
+
}
|
|
394
|
+
: null,
|
|
395
|
+
});
|
|
396
|
+
});
|
|
397
|
+
},
|
|
398
|
+
};
|
|
399
|
+
},
|
|
400
|
+
});
|
|
401
|
+
//# sourceMappingURL=prefer-sx-prop-over-system-props.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
type Options = [
|
|
2
|
+
{
|
|
3
|
+
targetPaths?: string[];
|
|
4
|
+
}
|
|
5
|
+
];
|
|
6
|
+
type MessageIds = 'preferUseBase62IdHook' | 'preferUseBase62IdTopLevel' | 'preferUseBase62IdUseMemo';
|
|
7
|
+
export declare const preferUseBase62Id: import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleModule<MessageIds, Options, import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleListener>;
|
|
8
|
+
export {};
|