@sun-asterisk/sunlint 1.0.6 → 1.0.7

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 (165) hide show
  1. package/CHANGELOG.md +108 -169
  2. package/README.md +7 -1
  3. package/config/presets/beginner.json +1 -1
  4. package/config/presets/ci.json +3 -2
  5. package/config/presets/recommended.json +1 -1
  6. package/config/presets/strict.json +3 -2
  7. package/config/rules-registry.json +60 -0
  8. package/config/sunlint-schema.json +0 -7
  9. package/config/typescript/eslint.config.js +4 -0
  10. package/core/config-manager.js +9 -8
  11. package/core/config-merger.js +12 -0
  12. package/core/file-targeting-service.js +1 -6
  13. package/core/rule-mapping-service.js +8 -0
  14. package/package.json +2 -5
  15. package/cli-legacy.js +0 -355
  16. package/docs/AI.md +0 -163
  17. package/docs/ARCHITECTURE.md +0 -78
  18. package/docs/CI-CD-GUIDE.md +0 -315
  19. package/docs/COMMAND-EXAMPLES.md +0 -256
  20. package/docs/DEBUG.md +0 -86
  21. package/docs/DISTRIBUTION.md +0 -153
  22. package/docs/ENHANCED_FILE_TARGETING.md +0 -0
  23. package/docs/ESLINT-INTEGRATION-STRATEGY.md +0 -392
  24. package/docs/ESLINT_INTEGRATION.md +0 -238
  25. package/docs/FILE_TARGETING_COMPARISON.md +0 -0
  26. package/docs/FOLDER_STRUCTURE.md +0 -59
  27. package/docs/HEURISTIC_VS_AI.md +0 -113
  28. package/docs/README.md +0 -32
  29. package/docs/RELEASE_GUIDE.md +0 -230
  30. package/docs/RULE-RESPONSIBILITY-MATRIX.md +0 -204
  31. package/eslint-integration/.eslintrc.js +0 -98
  32. package/eslint-integration/cli.js +0 -35
  33. package/eslint-integration/eslint-plugin-custom/c002-no-duplicate-code.js +0 -204
  34. package/eslint-integration/eslint-plugin-custom/c003-no-vague-abbreviations.js +0 -246
  35. package/eslint-integration/eslint-plugin-custom/c006-function-name-verb-noun.js +0 -207
  36. package/eslint-integration/eslint-plugin-custom/c010-limit-block-nesting.js +0 -90
  37. package/eslint-integration/eslint-plugin-custom/c013-no-dead-code.js +0 -43
  38. package/eslint-integration/eslint-plugin-custom/c014-abstract-dependency-preferred.js +0 -38
  39. package/eslint-integration/eslint-plugin-custom/c017-limit-constructor-logic.js +0 -39
  40. package/eslint-integration/eslint-plugin-custom/c018-no-generic-throw.js +0 -335
  41. package/eslint-integration/eslint-plugin-custom/c023-no-duplicate-variable-name-in-scope.js +0 -142
  42. package/eslint-integration/eslint-plugin-custom/c027-limit-function-nesting.js +0 -50
  43. package/eslint-integration/eslint-plugin-custom/c029-catch-block-logging.js +0 -80
  44. package/eslint-integration/eslint-plugin-custom/c030-use-custom-error-classes.js +0 -294
  45. package/eslint-integration/eslint-plugin-custom/c034-no-implicit-return.js +0 -34
  46. package/eslint-integration/eslint-plugin-custom/c035-no-empty-catch.js +0 -32
  47. package/eslint-integration/eslint-plugin-custom/c041-no-config-inline.js +0 -64
  48. package/eslint-integration/eslint-plugin-custom/c042-boolean-name-prefix.js +0 -406
  49. package/eslint-integration/eslint-plugin-custom/c043-no-console-or-print.js +0 -300
  50. package/eslint-integration/eslint-plugin-custom/c047-no-duplicate-retry-logic.js +0 -239
  51. package/eslint-integration/eslint-plugin-custom/c048-no-var-declaration.js +0 -31
  52. package/eslint-integration/eslint-plugin-custom/index.js +0 -155
  53. package/eslint-integration/eslint-plugin-custom/package.json +0 -13
  54. package/eslint-integration/eslint-plugin-custom/package.json.bak +0 -9
  55. package/eslint-integration/eslint-plugin-custom/s003-no-unvalidated-redirect.js +0 -86
  56. package/eslint-integration/eslint-plugin-custom/s005-no-origin-auth.js +0 -95
  57. package/eslint-integration/eslint-plugin-custom/s006-activation-recovery-secret-not-plaintext.js +0 -69
  58. package/eslint-integration/eslint-plugin-custom/s008-crypto-agility.js +0 -62
  59. package/eslint-integration/eslint-plugin-custom/s009-no-insecure-crypto.js +0 -103
  60. package/eslint-integration/eslint-plugin-custom/s010-no-insecure-random-in-sensitive-context.js +0 -123
  61. package/eslint-integration/eslint-plugin-custom/s011-no-insecure-uuid.js +0 -66
  62. package/eslint-integration/eslint-plugin-custom/s012-hardcode-secret.js +0 -71
  63. package/eslint-integration/eslint-plugin-custom/s014-insecure-tls-version.js +0 -50
  64. package/eslint-integration/eslint-plugin-custom/s015-insecure-tls-certificate.js +0 -43
  65. package/eslint-integration/eslint-plugin-custom/s016-sensitive-query-parameter.js +0 -59
  66. package/eslint-integration/eslint-plugin-custom/s017-no-sql-injection.js +0 -193
  67. package/eslint-integration/eslint-plugin-custom/s018-positive-input-validation.js +0 -56
  68. package/eslint-integration/eslint-plugin-custom/s019-no-raw-user-input-in-email.js +0 -113
  69. package/eslint-integration/eslint-plugin-custom/s020-no-eval-dynamic-execution.js +0 -89
  70. package/eslint-integration/eslint-plugin-custom/s022-output-encoding.js +0 -78
  71. package/eslint-integration/eslint-plugin-custom/s023-no-json-injection.js +0 -300
  72. package/eslint-integration/eslint-plugin-custom/s025-server-side-input-validation.js +0 -217
  73. package/eslint-integration/eslint-plugin-custom/s026-json-schema-validation.js +0 -68
  74. package/eslint-integration/eslint-plugin-custom/s027-no-hardcoded-secrets.js +0 -80
  75. package/eslint-integration/eslint-plugin-custom/s029-require-csrf-protection.js +0 -79
  76. package/eslint-integration/eslint-plugin-custom/s030-no-directory-browsing.js +0 -78
  77. package/eslint-integration/eslint-plugin-custom/s033-require-samesite-cookie.js +0 -80
  78. package/eslint-integration/eslint-plugin-custom/s034-require-host-cookie-prefix.js +0 -77
  79. package/eslint-integration/eslint-plugin-custom/s035-cookie-specific-path.js +0 -74
  80. package/eslint-integration/eslint-plugin-custom/s036-no-unsafe-file-include.js +0 -68
  81. package/eslint-integration/eslint-plugin-custom/s037-require-anti-cache-headers.js +0 -70
  82. package/eslint-integration/eslint-plugin-custom/s038-no-version-disclosure.js +0 -74
  83. package/eslint-integration/eslint-plugin-custom/s039-no-session-token-in-url.js +0 -63
  84. package/eslint-integration/eslint-plugin-custom/s041-require-session-invalidate-on-logout.js +0 -211
  85. package/eslint-integration/eslint-plugin-custom/s042-require-periodic-reauthentication.js +0 -294
  86. package/eslint-integration/eslint-plugin-custom/s043-terminate-sessions-on-password-change.js +0 -254
  87. package/eslint-integration/eslint-plugin-custom/s044-require-full-session-for-sensitive-operations.js +0 -292
  88. package/eslint-integration/eslint-plugin-custom/s045-anti-automation-controls.js +0 -46
  89. package/eslint-integration/eslint-plugin-custom/s046-secure-notification-on-auth-change.js +0 -44
  90. package/eslint-integration/eslint-plugin-custom/s047-secure-random-passwords.js +0 -108
  91. package/eslint-integration/eslint-plugin-custom/s048-password-credential-recovery.js +0 -54
  92. package/eslint-integration/eslint-plugin-custom/s050-session-token-weak-hash.js +0 -94
  93. package/eslint-integration/eslint-plugin-custom/s052-secure-random-authentication-code.js +0 -66
  94. package/eslint-integration/eslint-plugin-custom/s054-verification-default-account.js +0 -109
  95. package/eslint-integration/eslint-plugin-custom/s055-verification-rest-check-the-incoming-content-type.js +0 -143
  96. package/eslint-integration/eslint-plugin-custom/s057-utc-logging.js +0 -54
  97. package/eslint-integration/eslint-plugin-custom/s058-no-ssrf.js +0 -73
  98. package/eslint-integration/eslint-plugin-custom/t002-interface-prefix-i.js +0 -42
  99. package/eslint-integration/eslint-plugin-custom/t003-ts-ignore-reason.js +0 -48
  100. package/eslint-integration/eslint-plugin-custom/t004-interface-public-only.js +0 -160
  101. package/eslint-integration/eslint-plugin-custom/t007-no-fn-in-constructor.js +0 -52
  102. package/eslint-integration/eslint-plugin-custom/t011-no-real-time-dependency.js +0 -175
  103. package/eslint-integration/eslint-plugin-custom/t019-no-empty-type.js +0 -95
  104. package/eslint-integration/eslint-plugin-custom/t025-no-nested-union-tuple.js +0 -48
  105. package/eslint-integration/eslint-plugin-custom/t026-limit-nested-generics.js +0 -377
  106. package/eslint-integration/eslint.config.js +0 -125
  107. package/eslint-integration/eslint.config.simple.js +0 -24
  108. package/eslint-integration/package.json +0 -23
  109. package/eslint-integration/sample.ts +0 -53
  110. package/eslint-integration/test-s003.js +0 -5
  111. package/eslint-integration/tsconfig.json +0 -27
  112. package/examples/.github/workflows/code-quality.yml +0 -111
  113. package/examples/README.md +0 -69
  114. package/examples/basic-typescript-demo/.eslintrc.json +0 -18
  115. package/examples/basic-typescript-demo/.next/cache/eslint/.cache_1othrmo +0 -1
  116. package/examples/basic-typescript-demo/.sunlint.json +0 -29
  117. package/examples/basic-typescript-demo/eslint.config.mjs +0 -37
  118. package/examples/basic-typescript-demo/next-env.d.ts +0 -5
  119. package/examples/basic-typescript-demo/next.config.mjs +0 -4
  120. package/examples/basic-typescript-demo/package-lock.json +0 -5656
  121. package/examples/basic-typescript-demo/package.json +0 -34
  122. package/examples/basic-typescript-demo/src/app/layout.tsx +0 -18
  123. package/examples/basic-typescript-demo/src/app/page.tsx +0 -48
  124. package/examples/basic-typescript-demo/src/config.ts +0 -14
  125. package/examples/basic-typescript-demo/src/good-practices.ts +0 -58
  126. package/examples/basic-typescript-demo/src/types.generated.ts +0 -13
  127. package/examples/basic-typescript-demo/src/user.test.ts +0 -19
  128. package/examples/basic-typescript-demo/src/violations.ts +0 -61
  129. package/examples/basic-typescript-demo/test-config-priority.sh +0 -0
  130. package/examples/basic-typescript-demo/test-file-targeting.sh +0 -0
  131. package/examples/basic-typescript-demo/tsconfig.json +0 -27
  132. package/examples/enhanced-config.json +0 -0
  133. package/examples/eslint-integration-demo/.eslintrc.js +0 -38
  134. package/examples/eslint-integration-demo/.sunlint.json +0 -42
  135. package/examples/eslint-integration-demo/next-env.d.ts +0 -5
  136. package/examples/eslint-integration-demo/next.config.js +0 -8
  137. package/examples/eslint-integration-demo/package-lock.json +0 -5740
  138. package/examples/eslint-integration-demo/package.json +0 -37
  139. package/examples/eslint-integration-demo/src/api.test.ts +0 -20
  140. package/examples/eslint-integration-demo/src/conflict-test.tsx +0 -44
  141. package/examples/eslint-integration-demo/src/naming-conflicts.ts +0 -50
  142. package/examples/eslint-integration-demo/test-file-targeting.sh +0 -0
  143. package/examples/eslint-integration-demo/tsconfig.json +0 -26
  144. package/examples/file-targeting-demo/global.d.ts +0 -11
  145. package/examples/file-targeting-demo/jest.config.js +0 -8
  146. package/examples/file-targeting-demo/sample.ts +0 -53
  147. package/examples/file-targeting-demo/src/server.js +0 -11
  148. package/examples/file-targeting-demo/src/server.test.js +0 -11
  149. package/examples/file-targeting-demo/src/types.d.ts +0 -4
  150. package/examples/file-targeting-demo/src/types.generated.ts +0 -10
  151. package/examples/file-targeting-demo/user-service.test.ts +0 -15
  152. package/examples/file-targeting-demo/user-service.ts +0 -13
  153. package/examples/file-targeting-demo/utils.js +0 -15
  154. package/examples/multi-language-project/.eslintrc.json +0 -38
  155. package/examples/multi-language-project/package.json +0 -37
  156. package/examples/multi-language-project/src/sample.ts +0 -39
  157. package/examples/rule-test-fixtures/README.md +0 -67
  158. package/examples/rule-test-fixtures/rules/C006_function_naming/clean/typescript-clean.ts +0 -64
  159. package/examples/rule-test-fixtures/rules/C006_function_naming/violations/dart-violations.dart +0 -56
  160. package/examples/rule-test-fixtures/rules/C006_function_naming/violations/typescript-violations.ts +0 -47
  161. package/examples/rule-test-fixtures/rules/C019_log_level_usage/clean/typescript-clean.ts +0 -93
  162. package/examples/rule-test-fixtures/rules/C019_log_level_usage/violations/dart-violations.dart +0 -75
  163. package/examples/rule-test-fixtures/rules/C019_log_level_usage/violations/typescript-violations.ts +0 -84
  164. package/examples/rule-test-fixtures/rules/C029_catch_block_logging/clean/typescript-clean.ts +0 -0
  165. package/examples/rule-test-fixtures/rules/C029_catch_block_logging/violations/typescript-violations.ts +0 -37
@@ -1,294 +0,0 @@
1
- /**
2
- * Custom ESLint rule for: C030 – Dùng custom error class thay vì dùng lỗi hệ thống trực tiếp
3
- * Rule ID: custom/c030
4
- * Purpose: Enforce using custom error classes instead of generic Error class for better error handling and categorization
5
- */
6
-
7
- const c030Rule = {
8
- meta: {
9
- type: "suggestion",
10
- docs: {
11
- description: "Use custom error classes instead of generic Error class",
12
- recommended: true
13
- },
14
- schema: [
15
- {
16
- type: "object",
17
- properties: {
18
- allowGenericInTests: {
19
- type: "boolean",
20
- description: "Whether to allow generic Error in test files (default: true)"
21
- },
22
- allowedBuiltinErrors: {
23
- type: "array",
24
- items: { type: "string" },
25
- description: "Built-in error types that are allowed (e.g., TypeError, RangeError)"
26
- },
27
- customErrorClasses: {
28
- type: "array",
29
- items: { type: "string" },
30
- description: "Custom error class names that are recommended"
31
- },
32
- allowRethrow: {
33
- type: "boolean",
34
- description: "Whether to allow rethrowing caught errors (default: true)"
35
- },
36
- strictMode: {
37
- type: "boolean",
38
- description: "Enable strict mode - only custom errors allowed (default: false)"
39
- },
40
- requireErrorCode: {
41
- type: "boolean",
42
- description: "Require custom errors to have error codes (default: true)"
43
- },
44
- requireStatusCode: {
45
- type: "boolean",
46
- description: "Require custom errors for HTTP to have status codes (default: false)"
47
- }
48
- },
49
- additionalProperties: false
50
- }
51
- ],
52
- messages: {
53
- useCustomError: "Use custom error class instead of generic 'Error'. Consider using specific error types like ValidationError, NotFoundError, BusinessRuleError, etc. Vietnamese: 'Dùng custom error class thay vì Error generic'",
54
- useSpecificBuiltin: "Consider using a more specific built-in error type like TypeError, RangeError, or a custom error class. Vietnamese: 'Cân nhắc dùng built-in error cụ thể hơn hoặc custom error class'",
55
- missingErrorCode: "Custom error class should include an error code property. Vietnamese: 'Custom error class nên có thuộc tính error code'",
56
- missingStatusCode: "HTTP-related error class should include a status code property. Vietnamese: 'Error class liên quan HTTP nên có thuộc tính status code'",
57
- preferCustomError: "Prefer custom error classes for better error categorization and handling. Vietnamese: 'Ưu tiên custom error classes để phân loại và xử lý lỗi tốt hơn'"
58
- },
59
- fixable: null
60
- },
61
-
62
- create(context) {
63
- const options = context.options[0] || {};
64
-
65
- // Default configuration
66
- const allowGenericInTests = options.allowGenericInTests !== false;
67
- const allowedBuiltinErrors = new Set(options.allowedBuiltinErrors || [
68
- 'TypeError', 'RangeError', 'SyntaxError', 'ReferenceError', 'URIError', 'EvalError'
69
- ]);
70
- const customErrorClasses = new Set(options.customErrorClasses || [
71
- 'ValidationError', 'NotFoundError', 'BusinessRuleError', 'BusinessError',
72
- 'ExternalServiceError', 'AuthenticationError', 'AuthorizationError',
73
- 'NetworkError', 'DatabaseError', 'ConfigurationError', 'TimeoutError'
74
- ]);
75
- const allowRethrow = options.allowRethrow !== false;
76
- const strictMode = options.strictMode || false;
77
- const requireErrorCode = options.requireErrorCode !== false;
78
- const requireStatusCode = options.requireStatusCode || false;
79
-
80
- const sourceCode = context.getSourceCode();
81
- const filename = context.getFilename();
82
-
83
- function isTestFile() {
84
- if (!allowGenericInTests) return false;
85
-
86
- const testPatterns = ['.test.', '.spec.', '__tests__', '/test/', '/tests/', '.e2e.', '.stories.'];
87
- return testPatterns.some(pattern => filename.includes(pattern));
88
- }
89
-
90
- function isRethrowStatement(node) {
91
- if (!allowRethrow) return false;
92
-
93
- // Check if throwing a caught error parameter
94
- if (node.argument && node.argument.type === 'Identifier') {
95
- // Look for catch clauses in parent scopes
96
- let parent = node.parent;
97
- while (parent) {
98
- if (parent.type === 'CatchClause' &&
99
- parent.param &&
100
- parent.param.name === node.argument.name) {
101
- return true;
102
- }
103
- parent = parent.parent;
104
- }
105
- }
106
-
107
- return false;
108
- }
109
-
110
- function getErrorClassName(node) {
111
- if (!node.argument) return null;
112
-
113
- if (node.argument.type === 'NewExpression' && node.argument.callee) {
114
- if (node.argument.callee.type === 'Identifier') {
115
- return node.argument.callee.name;
116
- }
117
- if (node.argument.callee.type === 'MemberExpression' &&
118
- node.argument.callee.property &&
119
- node.argument.callee.property.type === 'Identifier') {
120
- return node.argument.callee.property.name;
121
- }
122
- }
123
-
124
- return null;
125
- }
126
-
127
- function isCustomErrorClass(className) {
128
- if (!className) return false;
129
-
130
- // Check if it's a known custom error class
131
- if (customErrorClasses.has(className)) return true;
132
-
133
- // Check if it follows custom error naming patterns
134
- const customErrorPatterns = [
135
- /Error$/, // Ends with 'Error'
136
- /Exception$/, // Ends with 'Exception'
137
- /Failure$/, // Ends with 'Failure'
138
- /Fault$/ // Ends with 'Fault'
139
- ];
140
-
141
- return customErrorPatterns.some(pattern =>
142
- pattern.test(className) &&
143
- !allowedBuiltinErrors.has(className) &&
144
- className !== 'Error'
145
- );
146
- }
147
-
148
- function checkErrorClassDefinition(node) {
149
- // Check if custom error class has required properties
150
- if (node.type === 'ClassDeclaration' &&
151
- node.id &&
152
- isCustomErrorClass(node.id.name)) {
153
-
154
- const className = node.id.name;
155
- const classBody = node.body.body;
156
-
157
- if (requireErrorCode) {
158
- const hasErrorCode = classBody.some(member => {
159
- if (member.type === 'PropertyDefinition' || member.type === 'ClassProperty') {
160
- return member.key && member.key.name === 'code';
161
- }
162
- if (member.type === 'MethodDefinition' && member.kind === 'constructor') {
163
- // Check if constructor sets error code
164
- const constructorBody = member.value.body.body;
165
- return constructorBody.some(stmt => {
166
- if (stmt.type === 'ExpressionStatement' &&
167
- stmt.expression.type === 'AssignmentExpression' &&
168
- stmt.expression.left.type === 'MemberExpression' &&
169
- stmt.expression.left.property.name === 'code') {
170
- return true;
171
- }
172
- return false;
173
- });
174
- }
175
- return false;
176
- });
177
-
178
- if (!hasErrorCode) {
179
- context.report({
180
- node: node.id,
181
- messageId: "missingErrorCode"
182
- });
183
- }
184
- }
185
-
186
- if (requireStatusCode && /http|api|web|service/i.test(className.toLowerCase())) {
187
- const hasStatusCode = classBody.some(member => {
188
- if (member.type === 'PropertyDefinition' || member.type === 'ClassProperty') {
189
- return member.key && (member.key.name === 'statusCode' || member.key.name === 'status');
190
- }
191
- if (member.type === 'MethodDefinition' && member.kind === 'constructor') {
192
- // Check if constructor sets status code
193
- const constructorBody = member.value.body.body;
194
- return constructorBody.some(stmt => {
195
- if (stmt.type === 'ExpressionStatement' &&
196
- stmt.expression.type === 'AssignmentExpression' &&
197
- stmt.expression.left.type === 'MemberExpression' &&
198
- (stmt.expression.left.property.name === 'statusCode' ||
199
- stmt.expression.left.property.name === 'status')) {
200
- return true;
201
- }
202
- return false;
203
- });
204
- }
205
- return false;
206
- });
207
-
208
- if (!hasStatusCode) {
209
- context.report({
210
- node: node.id,
211
- messageId: "missingStatusCode"
212
- });
213
- }
214
- }
215
- }
216
- }
217
-
218
- return {
219
- ThrowStatement(node) {
220
- // Skip test files if allowed
221
- if (isTestFile()) return;
222
-
223
- // Skip rethrow statements if allowed
224
- if (isRethrowStatement(node)) return;
225
-
226
- const errorClassName = getErrorClassName(node);
227
-
228
- // Check for generic Error usage
229
- if (errorClassName === 'Error') {
230
- context.report({
231
- node: node.argument,
232
- messageId: "useCustomError"
233
- });
234
- return;
235
- }
236
-
237
- // In strict mode, only custom errors are allowed
238
- if (strictMode && errorClassName) {
239
- if (!isCustomErrorClass(errorClassName) && !allowedBuiltinErrors.has(errorClassName)) {
240
- context.report({
241
- node: node.argument,
242
- messageId: "preferCustomError"
243
- });
244
- }
245
- }
246
-
247
- // Check for other built-in errors that could be more specific
248
- if (allowedBuiltinErrors.has(errorClassName) && !strictMode) {
249
- // Only suggest if it's a generic built-in error
250
- if (['TypeError', 'RangeError'].includes(errorClassName)) {
251
- context.report({
252
- node: node.argument,
253
- messageId: "useSpecificBuiltin"
254
- });
255
- }
256
- }
257
- },
258
-
259
- ClassDeclaration(node) {
260
- checkErrorClassDefinition(node);
261
- },
262
-
263
- // Check for Promise.reject with generic Error
264
- 'CallExpression[callee.type="MemberExpression"][callee.object.name="Promise"][callee.property.name="reject"]'(node) {
265
- if (isTestFile()) return;
266
-
267
- const arg = node.arguments[0];
268
- if (arg && arg.type === 'NewExpression' &&
269
- arg.callee && arg.callee.name === 'Error') {
270
- context.report({
271
- node: arg,
272
- messageId: "useCustomError"
273
- });
274
- }
275
- },
276
-
277
- // Check for async function error throwing
278
- 'AwaitExpression > CallExpression[callee.type="MemberExpression"][callee.property.name="reject"]'(node) {
279
- if (isTestFile()) return;
280
-
281
- const arg = node.arguments[0];
282
- if (arg && arg.type === 'NewExpression' &&
283
- arg.callee && arg.callee.name === 'Error') {
284
- context.report({
285
- node: arg,
286
- messageId: "useCustomError"
287
- });
288
- }
289
- }
290
- };
291
- }
292
- };
293
-
294
- module.exports = c030Rule;
@@ -1,34 +0,0 @@
1
- /**
2
- * Custom ESLint rule for: C034 – Do not use implicit return in arrow functions
3
- * Rule ID: custom/c034
4
- * Goal: Avoid using arrow functions with implicit return as they can be hard to read, use explicit return with braces
5
- */
6
-
7
- module.exports = {
8
- meta: {
9
- type: "suggestion",
10
- docs: {
11
- description: "Do not use implicit return in arrow functions",
12
- recommended: false
13
- },
14
- schema: [],
15
- messages: {
16
- implicitReturn: "Do not use implicit return. Use explicit return with {{ braces }}."
17
- }
18
- },
19
- create(context) {
20
- return {
21
- ArrowFunctionExpression(node) {
22
- if (node.body && node.body.type !== "BlockStatement") {
23
- context.report({
24
- node,
25
- messageId: "implicitReturn",
26
- data: {
27
- braces: "{ ... }"
28
- }
29
- });
30
- }
31
- }
32
- };
33
- }
34
- };
@@ -1,32 +0,0 @@
1
- /**
2
- * Custom ESLint rule for: C035 – No empty catch blocks (without error handling or logging)
3
- * Rule ID: custom/c035
4
- * Purpose: Prevent silently swallowing errors in catch blocks without logging or handling them
5
- */
6
-
7
- module.exports = {
8
- meta: {
9
- type: "problem",
10
- docs: {
11
- description: "No empty catch blocks (without error handling or logging)",
12
- recommended: true
13
- },
14
- schema: [],
15
- messages: {
16
- emptyCatch: "Empty catch blocks are not allowed. Errors should be logged or handled explicitly."
17
- }
18
- },
19
- create(context) {
20
- return {
21
- CatchClause(node) {
22
- const body = node.body && node.body.body;
23
- if (Array.isArray(body) && body.length === 0) {
24
- context.report({
25
- node,
26
- messageId: "emptyCatch"
27
- });
28
- }
29
- }
30
- };
31
- }
32
- };
@@ -1,64 +0,0 @@
1
- /**
2
- * Custom ESLint rule for: C041 – Do not hardcode constants scattered throughout logic
3
- * Rule ID: custom/c041
4
- * Purpose: Enforce centralized configuration management by preventing scattered constant declarations
5
- */
6
-
7
- module.exports = {
8
- meta: {
9
- type: "suggestion",
10
- docs: {
11
- description: "Do not hardcode constants scattered throughout logic",
12
- recommended: false
13
- },
14
- schema: [],
15
- messages: {
16
- inlineConfig: "Do not hardcode configuration values. Move them to a centralized config file."
17
- }
18
- },
19
- create(context) {
20
- const suspiciousPatterns = [
21
- /password/i,
22
- /secret/i,
23
- /api[_-]?key/i,
24
- /auth[_-]?token/i,
25
- /access[_-]?token/i,
26
- /localhost/i,
27
- /127\.0\.0\.1/,
28
- /http:\/\//i,
29
- /https:\/\//i,
30
- /db[_-]?(url|uri|name|conn)/i,
31
- /conn(ect)?ion[_-]?string/i
32
- ];
33
-
34
- function reportIfHardcoded(node, value) {
35
- if (typeof value !== "string") return;
36
- for (const pattern of suspiciousPatterns) {
37
- if (pattern.test(value)) {
38
- context.report({
39
- node,
40
- messageId: "inlineConfig",
41
- data: { value }
42
- });
43
- break;
44
- }
45
- }
46
- }
47
-
48
- return {
49
- Literal(node) {
50
- if (typeof node.value === "string") {
51
- reportIfHardcoded(node, node.value);
52
- }
53
- },
54
- TemplateLiteral(node) {
55
- if (
56
- node.quasis.length === 1 &&
57
- typeof node.quasis[0].value.raw === "string"
58
- ) {
59
- reportIfHardcoded(node, node.quasis[0].value.raw);
60
- }
61
- }
62
- };
63
- }
64
- };