@blumintinc/eslint-plugin-blumint 1.8.1 → 1.9.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/lib/index.js CHANGED
@@ -96,10 +96,11 @@ const enforce_css_media_queries_1 = require("./rules/enforce-css-media-queries")
96
96
  const omit_index_html_1 = require("./rules/omit-index-html");
97
97
  const enforce_id_capitalization_1 = require("./rules/enforce-id-capitalization");
98
98
  const no_unused_usestate_1 = require("./rules/no-unused-usestate");
99
+ const no_uuidv4_base62_as_key_1 = require("./rules/no-uuidv4-base62-as-key");
99
100
  module.exports = {
100
101
  meta: {
101
102
  name: '@blumintinc/eslint-plugin-blumint',
102
- version: '1.8.1',
103
+ version: '1.9.0',
103
104
  },
104
105
  parseOptions: {
105
106
  ecmaVersion: 2020,
@@ -134,6 +135,7 @@ module.exports = {
134
135
  '@blumintinc/blumint/no-misused-switch-case': 'error',
135
136
  '@blumintinc/blumint/no-unpinned-dependencies': 'error',
136
137
  '@blumintinc/blumint/no-unused-props': 'error',
138
+ '@blumintinc/blumint/no-uuidv4-base62-as-key': 'error',
137
139
  //'@blumintinc/blumint/no-useless-fragment': 'error',
138
140
  //'@blumintinc/blumint/prefer-fragment-shorthand': 'error',
139
141
  '@blumintinc/blumint/prefer-type-over-interface': 'error',
@@ -235,6 +237,7 @@ module.exports = {
235
237
  'no-unpinned-dependencies': no_unpinned_dependencies_1.noUnpinnedDependencies,
236
238
  'no-unused-props': no_unused_props_1.noUnusedProps,
237
239
  'no-useless-fragment': no_useless_fragment_1.noUselessFragment,
240
+ 'no-uuidv4-base62-as-key': no_uuidv4_base62_as_key_1.noUuidv4Base62AsKey,
238
241
  'prefer-fragment-shorthand': prefer_fragment_shorthand_1.preferFragmentShorthand,
239
242
  'prefer-type-over-interface': prefer_type_over_interface_1.preferTypeOverInterface,
240
243
  'require-memo': require_memo_1.requireMemo,
@@ -26,7 +26,7 @@ exports.enforceAssertSafeObjectKey = (0, createRule_1.createRule)({
26
26
  const addAssertSafeImport = (fixer) => {
27
27
  const program = context.getSourceCode().ast;
28
28
  const firstImport = program.body.find((node) => node.type === utils_1.AST_NODE_TYPES.ImportDeclaration);
29
- const importStatement = "import { assertSafe } from 'utils/assertions';\n";
29
+ const importStatement = "import { assertSafe } from 'functions/src/util/assertSafe';\n";
30
30
  if (firstImport) {
31
31
  return fixer.insertTextBefore(firstImport, importStatement);
32
32
  }
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.enforceIdCapitalization = void 0;
4
4
  const createRule_1 = require("../utils/createRule");
5
+ const utils_1 = require("@typescript-eslint/utils");
5
6
  /**
6
7
  * This rule ensures consistency in user-facing text by enforcing the use of "ID"
7
8
  * instead of "id" when referring to identifiers in UI labels, instructions,
@@ -26,12 +27,51 @@ exports.enforceIdCapitalization = (0, createRule_1.createRule)({
26
27
  // Regular expression to match standalone "id" surrounded by whitespace or punctuation
27
28
  // This ensures we only match "id" as a word, not as part of another word
28
29
  const idRegex = /(^|\s|[.,;:!?'"()\[\]{}])id(\s|$|[.,;:!?'"()\[\]{}])/g;
30
+ /**
31
+ * Check if a node is in a context that should be excluded from the rule
32
+ * (e.g., parameter names, property names, type definitions)
33
+ */
34
+ function isExcludedContext(node) {
35
+ // Check if the node is a property of an object pattern (destructuring)
36
+ if (node.parent &&
37
+ (node.parent.type === utils_1.AST_NODE_TYPES.Property ||
38
+ node.parent.type === utils_1.AST_NODE_TYPES.PropertyDefinition) &&
39
+ node.parent.key === node) {
40
+ return true;
41
+ }
42
+ // Check if the node is a parameter name
43
+ if (node.parent &&
44
+ (node.parent.type === utils_1.AST_NODE_TYPES.FunctionDeclaration ||
45
+ node.parent.type === utils_1.AST_NODE_TYPES.FunctionExpression ||
46
+ node.parent.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression) &&
47
+ node.parent.params.includes(node)) {
48
+ return true;
49
+ }
50
+ // Check if the node is part of a type definition
51
+ if (node.parent &&
52
+ (node.parent.type === utils_1.AST_NODE_TYPES.TSPropertySignature ||
53
+ node.parent.type === utils_1.AST_NODE_TYPES.TSParameterProperty ||
54
+ node.parent.type === utils_1.AST_NODE_TYPES.TSTypeAnnotation ||
55
+ node.parent.type === utils_1.AST_NODE_TYPES.TSTypeReference)) {
56
+ return true;
57
+ }
58
+ // Check if the node is a variable name
59
+ if (node.parent &&
60
+ node.parent.type === utils_1.AST_NODE_TYPES.VariableDeclarator &&
61
+ node.parent.id === node) {
62
+ return true;
63
+ }
64
+ return false;
65
+ }
29
66
  /**
30
67
  * Check if a string contains "id" as a standalone word and report if found
31
68
  */
32
69
  function checkForIdInString(node, value) {
33
70
  if (typeof value !== 'string')
34
71
  return;
72
+ // Skip checking if the node is in an excluded context
73
+ if (isExcludedContext(node))
74
+ return;
35
75
  // Reset the regex lastIndex to ensure consistent behavior
36
76
  idRegex.lastIndex = 0;
37
77
  // Check if the string contains "id" as a standalone word
@@ -45,13 +85,13 @@ exports.enforceIdCapitalization = (0, createRule_1.createRule)({
45
85
  node,
46
86
  messageId: 'enforceIdCapitalization',
47
87
  fix: (fixer) => {
48
- if (node.type === 'Literal') {
88
+ if (node.type === utils_1.AST_NODE_TYPES.Literal) {
49
89
  return fixer.replaceText(node, JSON.stringify(fixedText));
50
90
  }
51
- else if (node.type === 'JSXText') {
91
+ else if (node.type === utils_1.AST_NODE_TYPES.JSXText) {
52
92
  return fixer.replaceText(node, fixedText);
53
93
  }
54
- else if (node.type === 'TemplateElement') {
94
+ else if (node.type === utils_1.AST_NODE_TYPES.TemplateElement) {
55
95
  return fixer.replaceText(node, fixedText);
56
96
  }
57
97
  return fixer.replaceText(node, JSON.stringify(fixedText));
@@ -18,6 +18,36 @@ exports.enforceObjectLiteralAsConst = (0, createRule_1.createRule)({
18
18
  },
19
19
  defaultOptions: [],
20
20
  create(context) {
21
+ /**
22
+ * Checks if the node is inside a React hook like useMemo
23
+ */
24
+ function isInsideReactHook(ancestors) {
25
+ for (let i = 0; i < ancestors.length; i++) {
26
+ const ancestor = ancestors[i];
27
+ // Check for CallExpression (function call)
28
+ if (ancestor.type === 'CallExpression') {
29
+ const callee = ancestor.callee;
30
+ // Check if it's a hook like useMemo, useCallback, etc.
31
+ if (callee.type === 'Identifier' &&
32
+ (callee.name === 'useMemo' ||
33
+ callee.name === 'useCallback' ||
34
+ callee.name.startsWith('use'))) {
35
+ return true;
36
+ }
37
+ }
38
+ }
39
+ return false;
40
+ }
41
+ /**
42
+ * Checks if an array contains object literals that might be used as component props
43
+ */
44
+ function isArrayWithObjectLiterals(node) {
45
+ if (node.type !== 'ArrayExpression') {
46
+ return false;
47
+ }
48
+ // Check if any element in the array is an object literal
49
+ return node.elements.some((elem) => elem !== null && elem.type === 'ObjectExpression');
50
+ }
21
51
  return {
22
52
  ReturnStatement(node) {
23
53
  // Skip if there's no argument in the return statement
@@ -66,6 +96,13 @@ exports.enforceObjectLiteralAsConst = (0, createRule_1.createRule)({
66
96
  argument.elements.some((elem) => elem !== null && elem.type === 'SpreadElement'))) {
67
97
  return;
68
98
  }
99
+ // Skip arrays with object literals inside React hooks (likely component props)
100
+ if (isInsideReactHook(ancestors) &&
101
+ isArrayWithObjectLiterals(argument.type === 'TSAsExpression'
102
+ ? argument.expression
103
+ : argument)) {
104
+ return;
105
+ }
69
106
  // Report the issue and provide a fix
70
107
  context.report({
71
108
  node,
@@ -3,60 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.enforcePositiveNaming = void 0;
4
4
  const utils_1 = require("@typescript-eslint/utils");
5
5
  const createRule_1 = require("../utils/createRule");
6
- // Common negative prefixes and words to detect
7
- const NEGATIVE_PREFIXES = ['not', 'no', 'non', 'un', 'in', 'dis'];
8
- const NEGATIVE_WORDS = [
9
- 'invalid',
10
- 'disabled',
11
- 'incomplete',
12
- 'unpaid',
13
- 'inactive',
14
- 'disallowed',
15
- 'unauthorized',
16
- 'unverified',
17
- 'prevent',
18
- 'avoid',
19
- 'block',
20
- 'deny',
21
- 'reject',
22
- 'exclude',
23
- 'fail',
24
- 'missing',
25
- 'forbidden',
26
- 'impossible',
27
- 'error',
28
- 'broken',
29
- 'banned',
30
- 'restricted',
31
- 'limitation',
32
- 'limitation',
33
- 'blocked',
34
- 'prohibited',
35
- ];
36
- // Whitelist of acceptable negative terms (technical terms, common patterns)
37
- const ALLOWED_NEGATIVE_TERMS = new Set([
38
- 'isNaN',
39
- 'isNull',
40
- 'isUndefined',
41
- 'isEmpty',
42
- 'isOffline',
43
- 'isMissing',
44
- 'isOutOfStock',
45
- 'isOutOfBounds',
46
- 'isOffPeak',
47
- 'isNoticeable',
48
- 'hasNotification',
49
- 'isNoteworthy',
50
- 'isNone',
51
- 'isNegative',
52
- 'isNeutral',
53
- 'isNotification',
54
- 'isNote',
55
- 'hasNote',
56
- ]);
57
- // Map of negative terms to suggested positive alternatives
58
- const POSITIVE_ALTERNATIVES = {
59
- // Prefixes
6
+ // Common negative prefixes for boolean variables
7
+ const BOOLEAN_NEGATIVE_PREFIXES = ['not', 'no', 'non', 'un', 'in', 'dis'];
8
+ // Map of negative boolean terms to suggested positive alternatives
9
+ const BOOLEAN_POSITIVE_ALTERNATIVES = {
10
+ // Boolean prefixes
60
11
  'isNot': ['is'],
61
12
  'isUn': ['is'],
62
13
  'isDis': ['is'],
@@ -68,54 +19,13 @@ const POSITIVE_ALTERNATIVES = {
68
19
  'shouldNot': ['should'],
69
20
  'willNot': ['will'],
70
21
  'doesNot': ['does'],
71
- // Words
72
- 'isInvalid': ['isValid'],
73
- 'isDisabled': ['isEnabled'],
74
- 'isIncomplete': ['isComplete'],
75
- 'isUnpaid': ['isPaid', 'hasPaid'],
76
- 'isInactive': ['isActive'],
77
- 'isDisallowed': ['isAllowed'],
78
- 'isUnauthorized': ['isAuthorized'],
79
- 'isUnverified': ['isVerified'],
80
- 'isImpossible': ['isPossible'],
81
- 'isError': ['isSuccess', 'isValid'],
82
- 'isBroken': ['isWorking', 'isFunctional'],
83
- 'isBanned': ['isAllowed', 'isPermitted'],
84
- 'isRestricted': ['isAllowed', 'isAccessible'],
85
- 'isBlocked': ['isAllowed', 'isAccessible'],
86
- 'isProhibited': ['isAllowed', 'isPermitted'],
87
- 'prevent': ['allow', 'enable'],
88
- 'avoid': ['use', 'prefer'],
89
- 'block': ['allow', 'permit'],
90
- 'deny': ['allow', 'grant'],
91
- 'reject': ['accept', 'approve'],
92
- 'exclude': ['include'],
93
- 'fail': ['succeed', 'pass'],
94
- 'missing': ['present', 'available'],
95
- 'forbidden': ['allowed', 'permitted'],
96
- 'disabled': ['enabled'],
97
- 'incomplete': ['complete'],
98
- 'invalid': ['valid'],
99
- 'disallowed': ['allowed'],
100
- 'unauthorized': ['authorized'],
101
- 'unverified': ['verified'],
102
- 'inactive': ['active'],
103
- 'disabledFeatures': ['enabledFeatures'],
104
- 'inactiveUsers': ['activeUsers'],
105
- 'disableFeature': ['enableFeature'],
106
- 'disableAccount': ['enableAccount'],
107
- 'blockUser': ['allowUser'],
108
- 'preventAccess': ['allowAccess', 'enableAccess'],
109
- 'restrictAccess': ['allowAccess', 'grantAccess'],
110
- 'limitations': ['capabilities', 'features'],
111
- 'limitation': ['capability', 'feature'],
112
22
  };
113
23
  exports.enforcePositiveNaming = (0, createRule_1.createRule)({
114
24
  name: 'enforce-positive-naming',
115
25
  meta: {
116
26
  type: 'suggestion',
117
27
  docs: {
118
- description: 'Enforce positive variable naming patterns and avoid negative naming',
28
+ description: 'Enforce positive naming for boolean variables and avoid negations',
119
29
  recommended: 'error',
120
30
  },
121
31
  schema: [],
@@ -141,72 +51,43 @@ exports.enforcePositiveNaming = (0, createRule_1.createRule)({
141
51
  return {};
142
52
  }
143
53
  /**
144
- * Check if a name has negative connotations
54
+ * Check if a name has boolean negative naming
145
55
  */
146
- function hasNegativeNaming(name) {
147
- // Skip checking if the name is in the whitelist
148
- if (ALLOWED_NEGATIVE_TERMS.has(name)) {
149
- return { isNegative: false, alternatives: [] };
150
- }
56
+ function hasBooleanNegativeNaming(name) {
151
57
  // Check for exact matches in our alternatives map first
152
- if (POSITIVE_ALTERNATIVES[name]) {
153
- return { isNegative: true, alternatives: POSITIVE_ALTERNATIVES[name] };
58
+ if (BOOLEAN_POSITIVE_ALTERNATIVES[name]) {
59
+ return { isNegative: true, alternatives: BOOLEAN_POSITIVE_ALTERNATIVES[name] };
154
60
  }
155
- // Check for negative prefixes
156
- for (const prefix of NEGATIVE_PREFIXES) {
157
- // Check for patterns like isNot, hasNo, canNot, etc.
158
- const prefixPatterns = [
159
- { pattern: new RegExp(`^is${prefix}`, 'i'), key: `is${prefix.charAt(0).toUpperCase() + prefix.slice(1)}` },
160
- { pattern: new RegExp(`^has${prefix}`, 'i'), key: `has${prefix.charAt(0).toUpperCase() + prefix.slice(1)}` },
161
- { pattern: new RegExp(`^can${prefix}`, 'i'), key: `can${prefix.charAt(0).toUpperCase() + prefix.slice(1)}` },
162
- { pattern: new RegExp(`^should${prefix}`, 'i'), key: `should${prefix.charAt(0).toUpperCase() + prefix.slice(1)}` },
163
- { pattern: new RegExp(`^will${prefix}`, 'i'), key: `will${prefix.charAt(0).toUpperCase() + prefix.slice(1)}` },
164
- { pattern: new RegExp(`^does${prefix}`, 'i'), key: `does${prefix.charAt(0).toUpperCase() + prefix.slice(1)}` },
165
- ];
166
- for (const { pattern, key } of prefixPatterns) {
167
- if (pattern.test(name)) {
168
- // If we have a direct match for this pattern (like isNotVerified -> isVerified)
169
- const directMatch = POSITIVE_ALTERNATIVES[name];
170
- if (directMatch) {
171
- return { isNegative: true, alternatives: directMatch };
172
- }
173
- const alternatives = POSITIVE_ALTERNATIVES[key] || [];
174
- if (alternatives.length > 0) {
175
- // Suggest the positive version with the rest of the name
176
- const restOfName = name.replace(pattern, '');
177
- const suggestedAlternatives = alternatives.map(alt => `${alt}${restOfName.charAt(0).toUpperCase() + restOfName.slice(1)}`);
178
- return { isNegative: true, alternatives: suggestedAlternatives };
61
+ // Check for negative prefixes in boolean-like variables
62
+ if (name.startsWith('is') || name.startsWith('has') || name.startsWith('can') ||
63
+ name.startsWith('should') || name.startsWith('will') || name.startsWith('does')) {
64
+ for (const prefix of BOOLEAN_NEGATIVE_PREFIXES) {
65
+ // Check for patterns like isNot, hasNo, canNot, etc.
66
+ const prefixPatterns = [
67
+ { pattern: new RegExp(`^is${prefix}`, 'i'), key: `is${prefix.charAt(0).toUpperCase() + prefix.slice(1)}` },
68
+ { pattern: new RegExp(`^has${prefix}`, 'i'), key: `has${prefix.charAt(0).toUpperCase() + prefix.slice(1)}` },
69
+ { pattern: new RegExp(`^can${prefix}`, 'i'), key: `can${prefix.charAt(0).toUpperCase() + prefix.slice(1)}` },
70
+ { pattern: new RegExp(`^should${prefix}`, 'i'), key: `should${prefix.charAt(0).toUpperCase() + prefix.slice(1)}` },
71
+ { pattern: new RegExp(`^will${prefix}`, 'i'), key: `will${prefix.charAt(0).toUpperCase() + prefix.slice(1)}` },
72
+ { pattern: new RegExp(`^does${prefix}`, 'i'), key: `does${prefix.charAt(0).toUpperCase() + prefix.slice(1)}` },
73
+ ];
74
+ for (const { pattern, key } of prefixPatterns) {
75
+ if (pattern.test(name)) {
76
+ // If we have a direct match for this pattern (like isNotVerified -> isVerified)
77
+ const directMatch = BOOLEAN_POSITIVE_ALTERNATIVES[name];
78
+ if (directMatch) {
79
+ return { isNegative: true, alternatives: directMatch };
80
+ }
81
+ const alternatives = BOOLEAN_POSITIVE_ALTERNATIVES[key] || [];
82
+ if (alternatives.length > 0) {
83
+ // Suggest the positive version with the rest of the name
84
+ const restOfName = name.replace(pattern, '');
85
+ const suggestedAlternatives = alternatives.map(alt => `${alt}${restOfName.charAt(0).toUpperCase() + restOfName.slice(1)}`);
86
+ return { isNegative: true, alternatives: suggestedAlternatives };
87
+ }
88
+ return { isNegative: true, alternatives: ['a positive alternative'] };
179
89
  }
180
- return { isNegative: true, alternatives: ['a positive alternative'] };
181
- }
182
- }
183
- }
184
- // Check for exact negative words
185
- for (const word of NEGATIVE_WORDS) {
186
- if (name.toLowerCase() === word.toLowerCase()) {
187
- const alternatives = POSITIVE_ALTERNATIVES[word] || [];
188
- return {
189
- isNegative: true,
190
- alternatives: alternatives.length ? alternatives : ['a positive alternative']
191
- };
192
- }
193
- }
194
- // Check for negative words in camelCase/PascalCase
195
- for (const word of NEGATIVE_WORDS) {
196
- // Match the word at the beginning or after a capital letter
197
- const pattern = new RegExp(`(^|[A-Z])${word}($|[A-Z])`, 'i');
198
- if (pattern.test(name)) {
199
- // For compound names like isInvalid, check if we have a specific suggestion
200
- const exactMatch = `is${word.charAt(0).toUpperCase() + word.slice(1)}`;
201
- if (POSITIVE_ALTERNATIVES[exactMatch]) {
202
- return { isNegative: true, alternatives: POSITIVE_ALTERNATIVES[exactMatch] };
203
90
  }
204
- // Otherwise suggest general alternatives for the negative word
205
- const alternatives = POSITIVE_ALTERNATIVES[word] || [];
206
- return {
207
- isNegative: true,
208
- alternatives: alternatives.length ? alternatives : ['a positive alternative']
209
- };
210
91
  }
211
92
  }
212
93
  return { isNegative: false, alternatives: [] };
@@ -220,14 +101,41 @@ exports.enforcePositiveNaming = (0, createRule_1.createRule)({
220
101
  }
221
102
  return String(alternatives);
222
103
  }
104
+ /**
105
+ * Check if a node is likely to be a boolean
106
+ */
107
+ function isBooleanLike(node) {
108
+ // Check if the node has a boolean type annotation
109
+ if (node.type === utils_1.AST_NODE_TYPES.TSTypeAnnotation &&
110
+ node.typeAnnotation.type === utils_1.AST_NODE_TYPES.TSBooleanKeyword) {
111
+ return true;
112
+ }
113
+ // Check if the node is initialized with a boolean literal
114
+ if (node.parent?.type === utils_1.AST_NODE_TYPES.VariableDeclarator &&
115
+ node.parent.init?.type === utils_1.AST_NODE_TYPES.Literal &&
116
+ typeof node.parent.init.value === 'boolean') {
117
+ return true;
118
+ }
119
+ // Check if the node has a name that suggests it's a boolean
120
+ if (node.type === utils_1.AST_NODE_TYPES.Identifier &&
121
+ (node.name.startsWith('is') || node.name.startsWith('has') ||
122
+ node.name.startsWith('can') || node.name.startsWith('should') ||
123
+ node.name.startsWith('will') || node.name.startsWith('does'))) {
124
+ return true;
125
+ }
126
+ return false;
127
+ }
223
128
  /**
224
129
  * Check variable declarations for negative naming
225
130
  */
226
131
  function checkVariableDeclaration(node) {
227
132
  if (node.id.type !== utils_1.AST_NODE_TYPES.Identifier)
228
133
  return;
134
+ // Only check boolean-like variables
135
+ if (!isBooleanLike(node.id) && !isBooleanLike(node))
136
+ return;
229
137
  const variableName = node.id.name;
230
- const { isNegative, alternatives } = hasNegativeNaming(variableName);
138
+ const { isNegative, alternatives } = hasBooleanNegativeNaming(variableName);
231
139
  if (isNegative) {
232
140
  context.report({
233
141
  node: node.id,
@@ -263,7 +171,10 @@ exports.enforcePositiveNaming = (0, createRule_1.createRule)({
263
171
  }
264
172
  if (!functionName)
265
173
  return;
266
- const { isNegative, alternatives } = hasNegativeNaming(functionName);
174
+ // Only check boolean-returning functions
175
+ if (!isBooleanLike(node.id || node))
176
+ return;
177
+ const { isNegative, alternatives } = hasBooleanNegativeNaming(functionName);
267
178
  if (isNegative) {
268
179
  context.report({
269
180
  node: node.id || node,
@@ -281,8 +192,11 @@ exports.enforcePositiveNaming = (0, createRule_1.createRule)({
281
192
  function checkMethodDefinition(node) {
282
193
  if (node.key.type !== utils_1.AST_NODE_TYPES.Identifier)
283
194
  return;
195
+ // Only check boolean-returning methods
196
+ if (!isBooleanLike(node.key))
197
+ return;
284
198
  const methodName = node.key.name;
285
- const { isNegative, alternatives } = hasNegativeNaming(methodName);
199
+ const { isNegative, alternatives } = hasBooleanNegativeNaming(methodName);
286
200
  if (isNegative) {
287
201
  context.report({
288
202
  node: node.key,
@@ -300,8 +214,11 @@ exports.enforcePositiveNaming = (0, createRule_1.createRule)({
300
214
  function checkProperty(node) {
301
215
  if (node.key.type !== utils_1.AST_NODE_TYPES.Identifier)
302
216
  return;
217
+ // Only check boolean properties
218
+ if (!isBooleanLike(node.key))
219
+ return;
303
220
  const propertyName = node.key.name;
304
- const { isNegative, alternatives } = hasNegativeNaming(propertyName);
221
+ const { isNegative, alternatives } = hasBooleanNegativeNaming(propertyName);
305
222
  if (isNegative) {
306
223
  context.report({
307
224
  node: node.key,
@@ -319,8 +236,12 @@ exports.enforcePositiveNaming = (0, createRule_1.createRule)({
319
236
  function checkPropertySignature(node) {
320
237
  if (node.key.type !== utils_1.AST_NODE_TYPES.Identifier)
321
238
  return;
239
+ // Only check boolean properties
240
+ if (!isBooleanLike(node.key) &&
241
+ !(node.typeAnnotation?.typeAnnotation.type === utils_1.AST_NODE_TYPES.TSBooleanKeyword))
242
+ return;
322
243
  const propertyName = node.key.name;
323
- const { isNegative, alternatives } = hasNegativeNaming(propertyName);
244
+ const { isNegative, alternatives } = hasBooleanNegativeNaming(propertyName);
324
245
  if (isNegative) {
325
246
  context.report({
326
247
  node: node.key,
@@ -338,8 +259,11 @@ exports.enforcePositiveNaming = (0, createRule_1.createRule)({
338
259
  function checkParameter(node) {
339
260
  if (node.type !== utils_1.AST_NODE_TYPES.Identifier)
340
261
  return;
262
+ // Only check boolean parameters
263
+ if (!isBooleanLike(node))
264
+ return;
341
265
  const paramName = node.name;
342
- const { isNegative, alternatives } = hasNegativeNaming(paramName);
266
+ const { isNegative, alternatives } = hasBooleanNegativeNaming(paramName);
343
267
  if (isNegative) {
344
268
  context.report({
345
269
  node,
@@ -38,7 +38,7 @@ exports.enforceSingularTypeNames = (0, createRule_1.createRule)({
38
38
  if (name.length < 3)
39
39
  return false;
40
40
  // Skip checking if name ends with 'Props' or 'Params'
41
- if (name.endsWith('Props') || name.endsWith('Params'))
41
+ if (name.endsWith('Props') || name.endsWith('Params') || name.endsWith('Options') || name.endsWith('Settings'))
42
42
  return false;
43
43
  // Skip checking if name is already singular according to pluralize
44
44
  if (pluralize.isSingular(name))
@@ -1,5 +1 @@
1
- type Options = {
2
- allowClassInstances?: boolean;
3
- };
4
- export declare const noHungarian: import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleModule<"noHungarian", [Options], import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleListener>;
5
- export {};
1
+ export declare const noHungarian: import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleModule<"noHungarian", [], import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleListener>;