@echoes-of-order/eslint-config 1.121.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 (171) hide show
  1. package/CHANGELOG.md +1093 -0
  2. package/configs/.gitkeep +1 -0
  3. package/configs/admin.js +203 -0
  4. package/configs/api-client.js +46 -0
  5. package/configs/backend.js +895 -0
  6. package/configs/domains.js +123 -0
  7. package/configs/frontend.js +30 -0
  8. package/configs/image-server.js +26 -0
  9. package/configs/ionos-proxy.js +372 -0
  10. package/configs/nestjs.js +156 -0
  11. package/configs/node.js +92 -0
  12. package/configs/react.js +111 -0
  13. package/configs/wiki.js +42 -0
  14. package/index.js +39 -0
  15. package/package.json +85 -0
  16. package/rules/.gitkeep +1 -0
  17. package/rules/__tests__/analyze-relation-usage.test.js.disabled +300 -0
  18. package/rules/__tests__/complexity.test.js.disabled +300 -0
  19. package/rules/__tests__/enforce-dto-factory-in-services.integration.test.js +226 -0
  20. package/rules/__tests__/enforce-dto-factory-in-services.test.js +177 -0
  21. package/rules/__tests__/enforce-entity-dto-create-no-id.integration.test.js +18 -0
  22. package/rules/__tests__/enforce-function-argument-count.test.js.disabled +300 -0
  23. package/rules/__tests__/enforce-repository-token-handling.test.js +58 -0
  24. package/rules/__tests__/english-only-code-strings.test.js.disabled +300 -0
  25. package/rules/__tests__/eslint-rules.integration.test.ts +350 -0
  26. package/rules/__tests__/integration-test-controller-response-dto.js +261 -0
  27. package/rules/__tests__/integration-test-dto-factory-in-services.js +260 -0
  28. package/rules/__tests__/integration-test-no-entity-type-casting.js +161 -0
  29. package/rules/__tests__/integration-test-typeorm-naming-conventions.js +501 -0
  30. package/rules/__tests__/test-config.js +33 -0
  31. package/rules/admin-controller-security.js +180 -0
  32. package/rules/analyze-relation-usage.js +687 -0
  33. package/rules/api-response-dto.js +174 -0
  34. package/rules/auth-guard-required.js +142 -0
  35. package/rules/backend-specific.js +36 -0
  36. package/rules/best-practices.js +421 -0
  37. package/rules/complexity.js +20 -0
  38. package/rules/controller-architecture.js +340 -0
  39. package/rules/controller-naming-conventions.js +190 -0
  40. package/rules/controller-readonly-restriction.js +148 -0
  41. package/rules/controller-swagger-complete.js +312 -0
  42. package/rules/controller-swagger-docs.js +119 -0
  43. package/rules/controller-swagger-english.js +320 -0
  44. package/rules/coordinate-naming.js +132 -0
  45. package/rules/custom-mui-button.js +135 -0
  46. package/rules/dead-code-detection-backend.js +50 -0
  47. package/rules/dead-code-detection-frontend.js +48 -0
  48. package/rules/dead-code-detection.js +71 -0
  49. package/rules/debug-controller-response-dto.js +79 -0
  50. package/rules/deprecate.js +8 -0
  51. package/rules/dto-annotation-property-consistency.js +111 -0
  52. package/rules/dto-entity-mapping-completeness.js +688 -0
  53. package/rules/dto-entity-swagger-separation.js +265 -0
  54. package/rules/dto-entity-type-consistency.js +352 -0
  55. package/rules/dto-entity-type-matching.js +519 -0
  56. package/rules/dto-naming-convention.js +98 -0
  57. package/rules/dto-visibility-modifiers.js +159 -0
  58. package/rules/enforce-api-versioning.js +122 -0
  59. package/rules/enforce-app-module-registration.js +179 -0
  60. package/rules/enforce-basecontroller.js +152 -0
  61. package/rules/enforce-body-request-dto.js +141 -0
  62. package/rules/enforce-controller-response-dto.js +349 -0
  63. package/rules/enforce-custom-error-classes.js +242 -0
  64. package/rules/enforce-database-transaction-safety.js +179 -0
  65. package/rules/enforce-dto-constructor.js +95 -0
  66. package/rules/enforce-dto-create-parameter-types.js +170 -0
  67. package/rules/enforce-dto-create-pattern.js +274 -0
  68. package/rules/enforce-dto-entity-creation.js +164 -0
  69. package/rules/enforce-dto-factory-in-services.js +188 -0
  70. package/rules/enforce-dto-from-entity-method.js +47 -0
  71. package/rules/enforce-dto-from-entity.js +314 -0
  72. package/rules/enforce-dto-naming-conventions.js +212 -0
  73. package/rules/enforce-dto-naming.js +176 -0
  74. package/rules/enforce-dto-usage-simple.js +114 -0
  75. package/rules/enforce-dto-usage.js +407 -0
  76. package/rules/enforce-eager-translation-loading.js +178 -0
  77. package/rules/enforce-entity-creation-pattern.js +137 -0
  78. package/rules/enforce-entity-dto-convert-method.js +157 -0
  79. package/rules/enforce-entity-dto-create-no-id.js +117 -0
  80. package/rules/enforce-entity-dto-extends-base.js +141 -0
  81. package/rules/enforce-entity-dto-from-request-dto-structure.js +113 -0
  82. package/rules/enforce-entity-dto-fromentity-complex.js +69 -0
  83. package/rules/enforce-entity-dto-fromentity-simple.js +69 -0
  84. package/rules/enforce-entity-dto-fromrequestdto-structure.js +262 -0
  85. package/rules/enforce-entity-dto-methods-restriction.js +159 -0
  86. package/rules/enforce-entity-dto-no-request-dto.js +102 -0
  87. package/rules/enforce-entity-dto-optional-auto-fields.js +101 -0
  88. package/rules/enforce-entity-dto-required-methods.js +248 -0
  89. package/rules/enforce-entity-factory-pattern.js +180 -0
  90. package/rules/enforce-entity-instantiation-in-toentity.js +125 -0
  91. package/rules/enforce-enum-for-playable-entities.js +95 -0
  92. package/rules/enforce-error-handling.js +257 -0
  93. package/rules/enforce-explicit-dto-types.js +118 -0
  94. package/rules/enforce-from-request-dto-usage.js +62 -0
  95. package/rules/enforce-generic-entity-dto.js +71 -0
  96. package/rules/enforce-inject-decorator.js +133 -0
  97. package/rules/enforce-lazy-type-loading.js +170 -0
  98. package/rules/enforce-module-existence.js +157 -0
  99. package/rules/enforce-nonentity-dto-create.js +107 -0
  100. package/rules/enforce-playable-entity-naming.js +108 -0
  101. package/rules/enforce-repository-token-handling.js +92 -0
  102. package/rules/enforce-request-dto-no-entity-dto.js +201 -0
  103. package/rules/enforce-request-dto-required-fields.js +217 -0
  104. package/rules/enforce-result-pattern.js +45 -0
  105. package/rules/enforce-service-relation-loading.js +116 -0
  106. package/rules/enforce-test-coverage.js +96 -0
  107. package/rules/enforce-toentity-conditional-assignment.js +132 -0
  108. package/rules/enforce-translations-required.js +203 -0
  109. package/rules/enforce-typeorm-naming-conventions.js +366 -0
  110. package/rules/enforce-vite-health-metrics.js +240 -0
  111. package/rules/entity-required-properties.js +321 -0
  112. package/rules/entity-to-dto-test.js +73 -0
  113. package/rules/enum-database-validation.js +149 -0
  114. package/rules/errors.js +190 -0
  115. package/rules/es6.js +204 -0
  116. package/rules/eslint-plugin-no-comments.js +44 -0
  117. package/rules/filename-class-name-match.js +62 -0
  118. package/rules/forbid-fromentity-outside-entity-folder.js +237 -0
  119. package/rules/function-params-newline.js +111 -0
  120. package/rules/imports.js +264 -0
  121. package/rules/jest.js +13 -0
  122. package/rules/jsx.js +16 -0
  123. package/rules/max-classes-per-file.js +49 -0
  124. package/rules/multiline-formatting.js +146 -0
  125. package/rules/no-blank-lines-between-decorators-and-properties.js +95 -0
  126. package/rules/no-comments.js +62 -0
  127. package/rules/no-dto-constructors.js +126 -0
  128. package/rules/no-dto-default-values.js +220 -0
  129. package/rules/no-dto-duplicates.js +127 -0
  130. package/rules/no-dto-in-entity.js +99 -0
  131. package/rules/no-dynamic-import-in-types.js +71 -0
  132. package/rules/no-dynamic-imports-in-controllers.js +95 -0
  133. package/rules/no-entity-imports-in-controllers.js +101 -0
  134. package/rules/no-entity-in-swagger-docs.js +139 -0
  135. package/rules/no-entity-type-casting.js +104 -0
  136. package/rules/no-fetch.js +77 -0
  137. package/rules/no-import-meta-env.js +151 -0
  138. package/rules/no-inline-styles.js +5 -0
  139. package/rules/no-magic-values.js +85 -0
  140. package/rules/no-partial-type.js +168 -0
  141. package/rules/no-relative-imports.js +31 -0
  142. package/rules/no-tsyringe.js +181 -0
  143. package/rules/no-type-assertion.js +175 -0
  144. package/rules/no-undefined-entity-properties.js +121 -0
  145. package/rules/node.js +44 -0
  146. package/rules/perfectionist.js +50 -0
  147. package/rules/performance-minimal.js +155 -0
  148. package/rules/performance.js +44 -0
  149. package/rules/pino-logger-format.js +200 -0
  150. package/rules/prefer-dto-classes.js +112 -0
  151. package/rules/prefer-dto-create-method.js +225 -0
  152. package/rules/promises.js +17 -0
  153. package/rules/react-hooks.js +15 -0
  154. package/rules/react.js +28 -0
  155. package/rules/regexp.js +70 -0
  156. package/rules/require-dto-response.js +81 -0
  157. package/rules/require-valid-relations.js +388 -0
  158. package/rules/result-pattern.js +162 -0
  159. package/rules/security.js +37 -0
  160. package/rules/service-architecture.js +148 -0
  161. package/rules/sonarjs.js +26 -0
  162. package/rules/strict.js +7 -0
  163. package/rules/style.js +611 -0
  164. package/rules/stylistic.js +93 -0
  165. package/rules/typeorm-column-type-validation.js +224 -0
  166. package/rules/typescript-advanced.js +113 -0
  167. package/rules/typescript-core.js +111 -0
  168. package/rules/typescript.js +146 -0
  169. package/rules/unicorn.js +168 -0
  170. package/rules/variables.js +51 -0
  171. package/rules/websocket-architecture.js +115 -0
@@ -0,0 +1,155 @@
1
+ export default {
2
+ rules: {
3
+ // Kritische Regex Performance - nur funktionierende Regeln
4
+ "regexp/confusing-quantifier": "error",
5
+ "regexp/control-character-escape": "error",
6
+ "regexp/negation": "error",
7
+ "regexp/no-dupe-characters-character-class": "error",
8
+ "regexp/no-dupe-disjunctions": "error",
9
+ "regexp/no-empty-alternative": "error",
10
+ "regexp/no-empty-capturing-group": "error",
11
+ "regexp/no-empty-character-class": "error",
12
+ "regexp/no-empty-group": "error",
13
+ "regexp/no-empty-lookarounds-assertion": "error",
14
+ "regexp/no-escape-backspace": "error",
15
+ "regexp/no-invalid-regexp": "error",
16
+ "regexp/no-lazy-ends": "error",
17
+ "regexp/no-misleading-capturing-group": "error",
18
+ "regexp/no-misleading-unicode-character": "error",
19
+ "regexp/no-missing-g-flag": "error",
20
+ "regexp/no-potentially-useless-backreference": "error",
21
+ "regexp/no-super-linear-backtracking": "error",
22
+ "regexp/no-super-linear-move": "error",
23
+ "regexp/no-trivially-nested-assertion": "error",
24
+ "regexp/no-trivially-nested-quantifier": "error",
25
+ "regexp/no-unused-capturing-group": "error",
26
+ "regexp/no-useless-assertions": "error",
27
+ "regexp/no-useless-backreference": "error",
28
+ "regexp/no-useless-character-class": "error",
29
+ "regexp/no-useless-dollar-replacements": "error",
30
+ "regexp/no-useless-escape": "error",
31
+ "regexp/no-useless-flag": "error",
32
+ "regexp/no-useless-lazy": "error",
33
+ "regexp/no-useless-quantifier": "error",
34
+ "regexp/no-useless-range": "error",
35
+ "regexp/no-useless-two-nums-quantifier": "error",
36
+ "regexp/no-zero-quantifier": "error",
37
+ "regexp/optimal-lookaround-quantifier": "error",
38
+ "regexp/optimal-quantifier-concatenation": "error",
39
+ "regexp/prefer-lookaround": "error",
40
+ "regexp/prefer-named-backreference": "error",
41
+ "regexp/prefer-named-capture-group": "error",
42
+ "regexp/prefer-named-replacement": "error",
43
+ "regexp/prefer-plus-quantifier": "error",
44
+ "regexp/prefer-predefined-assertion": "error",
45
+ "regexp/prefer-quantifier": "error",
46
+ "regexp/prefer-range": "error",
47
+ "regexp/prefer-regexp-exec": "error",
48
+ "regexp/prefer-regexp-test": "error",
49
+ "regexp/prefer-result-array-groups": "error",
50
+ "regexp/prefer-set-operation": "error",
51
+ "regexp/prefer-star-quantifier": "error",
52
+ "regexp/prefer-unicode-codepoint-escapes": "error",
53
+ "regexp/require-unicode-regexp": "error",
54
+ "regexp/simplify-set-operations": "error",
55
+ "regexp/sort-alternatives": "error",
56
+ "regexp/sort-character-class-elements": "error",
57
+ "regexp/sort-flags": "error",
58
+ "regexp/strict": "error",
59
+ "regexp/use-ignore-case": "error",
60
+
61
+ // Performance-kritische Standard-Regeln
62
+ "no-await-in-loop": "error",
63
+ "no-constant-binary-expression": "error",
64
+ "no-unreachable-loop": "error",
65
+ "prefer-const": "error",
66
+ "no-var": "error",
67
+ "prefer-template": "error",
68
+ "prefer-spread": "error",
69
+ "prefer-rest-params": "error",
70
+ "prefer-arrow-callback": ["error", {
71
+ "allowNamedFunctions": false,
72
+ "allowUnboundThis": true
73
+ }],
74
+ "object-shorthand": "error",
75
+ "prefer-destructuring": ["error", {
76
+ "VariableDeclarator": {
77
+ "array": false,
78
+ "object": true
79
+ },
80
+ "AssignmentExpression": {
81
+ "array": true,
82
+ "object": false
83
+ }
84
+ }],
85
+
86
+ // Memory-Management
87
+ "no-implied-eval": "error",
88
+ "no-new-func": "error",
89
+ "no-new-object": "error",
90
+ "no-new-wrappers": "error",
91
+ "no-array-constructor": "error",
92
+
93
+ // Kritische Unicorn-Regeln (nur funktionierende)
94
+ "unicorn/better-regex": "error",
95
+ "unicorn/catch-error-name": "error",
96
+ "unicorn/error-message": "error",
97
+ "unicorn/escape-case": "error",
98
+ "unicorn/explicit-length-check": "error",
99
+ "unicorn/new-for-builtins": "error",
100
+ "unicorn/no-abusive-eslint-disable": "error",
101
+ "unicorn/no-console-spaces": "error",
102
+ "unicorn/no-empty-file": "error",
103
+ "unicorn/no-hex-escape": "error",
104
+ "unicorn/no-instanceof-array": "error",
105
+ "unicorn/no-new-array": "error",
106
+ "unicorn/no-new-buffer": "error",
107
+ "unicorn/no-process-exit": "error",
108
+ "unicorn/no-static-only-class": "error",
109
+ "unicorn/no-this-assignment": "error",
110
+ "unicorn/no-typeof-undefined": "error",
111
+ "unicorn/no-unnecessary-await": "error",
112
+ "unicorn/no-useless-length-check": "error",
113
+ "unicorn/no-useless-spread": "error",
114
+ "unicorn/no-zero-fractions": "error",
115
+ "unicorn/number-literal-case": "error",
116
+ "unicorn/prefer-array-find": "error",
117
+ "unicorn/prefer-array-flat": "error",
118
+ "unicorn/prefer-array-flat-map": "error",
119
+ "unicorn/prefer-array-index-of": "error",
120
+ "unicorn/prefer-array-some": "error",
121
+ "unicorn/prefer-at": "error",
122
+ "unicorn/prefer-code-point": "error",
123
+ "unicorn/prefer-date-now": "error",
124
+ "unicorn/prefer-default-parameters": "error",
125
+ "unicorn/prefer-includes": "error",
126
+ "unicorn/prefer-json-parse-buffer": "error",
127
+ "unicorn/prefer-logical-operator-over-ternary": "error",
128
+ "unicorn/prefer-math-trunc": "error",
129
+ "unicorn/prefer-modern-math-apis": "error",
130
+ "unicorn/prefer-module": "error",
131
+ "unicorn/prefer-native-coercion-functions": "error",
132
+ "unicorn/prefer-negative-index": "error",
133
+ "unicorn/prefer-node-protocol": "error",
134
+ "unicorn/prefer-number-properties": "error",
135
+ "unicorn/prefer-object-from-entries": "error",
136
+ "unicorn/prefer-optional-catch-binding": "error",
137
+ "unicorn/prefer-prototype-methods": "error",
138
+ "unicorn/prefer-reflect-apply": "error",
139
+ "unicorn/prefer-regexp-test": "error",
140
+ "unicorn/prefer-set-has": "error",
141
+ "unicorn/prefer-set-size": "error",
142
+ "unicorn/prefer-string-replace-all": "error",
143
+ "unicorn/prefer-string-slice": "error",
144
+ "unicorn/prefer-string-starts-ends-with": "error",
145
+ "unicorn/prefer-string-trim-start-end": "error",
146
+ "unicorn/prefer-switch": "error",
147
+ "unicorn/prefer-ternary": "error",
148
+ "unicorn/prefer-top-level-await": "error",
149
+ "unicorn/prefer-type-error": "error",
150
+ "unicorn/require-array-join-separator": "error",
151
+ "unicorn/require-number-to-fixed-digits-argument": "error",
152
+ "unicorn/switch-case-braces": "error",
153
+ "unicorn/throw-new-error": "error",
154
+ },
155
+ };
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Performance Rules
3
+ *
4
+ * Performance-kritische Regeln für Backend-Anwendungen
5
+ * Ursprünglich aus dem Image-Server
6
+ */
7
+
8
+ export default {
9
+ rules: {
10
+ // Performance-kritische Standard-Regeln
11
+ "no-await-in-loop": "error",
12
+ "no-constant-binary-expression": "error",
13
+ "no-unreachable-loop": "error",
14
+ "prefer-const": "error",
15
+ "no-var": "error",
16
+ "prefer-template": "error",
17
+ "prefer-spread": "error",
18
+ "prefer-rest-params": "error",
19
+ "prefer-arrow-callback": ["error", {
20
+ "allowNamedFunctions": false,
21
+ "allowUnboundThis": true
22
+ }],
23
+ "object-shorthand": "error",
24
+ "prefer-destructuring": ["error", {
25
+ "VariableDeclarator": {
26
+ "array": false,
27
+ "object": true
28
+ },
29
+ "AssignmentExpression": {
30
+ "array": true,
31
+ "object": false
32
+ }
33
+ }],
34
+
35
+ // Memory-Management
36
+ "no-implied-eval": "error",
37
+ "no-new-func": "error",
38
+ "no-new-object": "error",
39
+ "no-new-wrappers": "error",
40
+ "no-array-constructor": "error",
41
+ },
42
+ };
43
+
44
+
@@ -0,0 +1,200 @@
1
+ /**
2
+ * @fileoverview Enforce Pino logger format: logger.method({ object }, 'message')
3
+ * @author Echoes of Order Team
4
+ *
5
+ * This rule enforces:
6
+ * 1. Object must be first argument, message second
7
+ * 2. Error objects can be passed directly in the 'error' property - the logger wrapper will extract message and stack automatically
8
+ * 3. For error logs, if 'error' is an Error object, 'stack' is not required (auto-extracted)
9
+ */
10
+
11
+ "use strict";
12
+
13
+ export default {
14
+ meta: {
15
+ type: "problem",
16
+ docs: {
17
+ description: "Enforce Pino logger format: logger.method({ object }, 'message') - object first, then message. Error objects are automatically serialized.",
18
+ category: "Best Practices",
19
+ recommended: true,
20
+ },
21
+ messages: {
22
+ wrongOrder: "Logger call must use Pino format: logger.{{method}}({ error }, 'message') - object first, then message. Found message first.",
23
+ missingObject: "Logger call must include an object as first parameter: logger.{{method}}({ error }, 'message').",
24
+ tooManyArgs: "Logger call should have exactly 2 arguments: logger.{{method}}({ error }, 'message').",
25
+ deprecatedProperty: "Use '{{correct}}' instead of '{{wrong}}' in logger object.",
26
+ errorMustBeShorthand: "logger.error() must be called with exactly { error } as first parameter. Use: logger.error({ error }, 'message').",
27
+ },
28
+ schema: [],
29
+ fixable: "code",
30
+ },
31
+
32
+ create(context) {
33
+ const loggerMethods = ["error", "warn", "info", "debug", "trace", "fatal"];
34
+
35
+ const deprecatedPropertyMappings = {
36
+ err: "error",
37
+ msg: "message",
38
+ stackTrace: "stack",
39
+ errorMsg: "error",
40
+ errorMessage: "error",
41
+ };
42
+
43
+ function isLoggerCall(node) {
44
+ return (
45
+ node.callee.type === "MemberExpression" &&
46
+ node.callee.object.type === "Identifier" &&
47
+ node.callee.object.name === "logger" &&
48
+ node.callee.property.type === "Identifier" &&
49
+ loggerMethods.includes(node.callee.property.name)
50
+ );
51
+ }
52
+
53
+ function isObjectExpression(arg) {
54
+ return arg && arg.type === "ObjectExpression";
55
+ }
56
+
57
+ function isStringLiteral(arg) {
58
+ return (
59
+ arg &&
60
+ ((arg.type === "Literal" && typeof arg.value === "string") ||
61
+ arg.type === "TemplateLiteral")
62
+ );
63
+ }
64
+
65
+ function checkObjectProperties(objectNode, methodName) {
66
+ if (!objectNode || objectNode.type !== "ObjectExpression") {
67
+ return;
68
+ }
69
+
70
+ const properties = objectNode.properties;
71
+
72
+ // For error logs, enforce strict pattern: { error }
73
+ if (methodName === "error") {
74
+ // Check that there is exactly one property and it's 'error' as shorthand
75
+ if (properties.length !== 1) {
76
+ context.report({
77
+ node: objectNode,
78
+ messageId: "errorMustBeShorthand",
79
+ fix(fixer) {
80
+ return fixer.replaceText(objectNode, "{ error }");
81
+ },
82
+ });
83
+ return;
84
+ }
85
+
86
+ const errorProp = properties[0];
87
+
88
+ // Must be a Property node
89
+ if (errorProp.type !== "Property") {
90
+ context.report({
91
+ node: objectNode,
92
+ messageId: "errorMustBeShorthand",
93
+ fix(fixer) {
94
+ return fixer.replaceText(objectNode, "{ error }");
95
+ },
96
+ });
97
+ return;
98
+ }
99
+
100
+ // Must be named 'error'
101
+ if (errorProp.key.type !== "Identifier" || errorProp.key.name !== "error") {
102
+ context.report({
103
+ node: objectNode,
104
+ messageId: "errorMustBeShorthand",
105
+ fix(fixer) {
106
+ return fixer.replaceText(objectNode, "{ error }");
107
+ },
108
+ });
109
+ return;
110
+ }
111
+
112
+ // Must be shorthand property (error, not error: something)
113
+ if (!errorProp.shorthand) {
114
+ context.report({
115
+ node: errorProp,
116
+ messageId: "errorMustBeShorthand",
117
+ fix(fixer) {
118
+ return fixer.replaceText(objectNode, "{ error }");
119
+ },
120
+ });
121
+ return;
122
+ }
123
+ }
124
+
125
+ // For other log methods, check deprecated properties
126
+ for (const prop of properties) {
127
+ if (prop.type === "Property" && prop.key.type === "Identifier") {
128
+ const propName = prop.key.name;
129
+
130
+ if (deprecatedPropertyMappings[propName]) {
131
+ context.report({
132
+ node: prop,
133
+ messageId: "deprecatedProperty",
134
+ data: {
135
+ wrong: propName,
136
+ correct: deprecatedPropertyMappings[propName],
137
+ },
138
+ });
139
+ }
140
+ }
141
+ }
142
+ }
143
+
144
+ return {
145
+ CallExpression(node) {
146
+ if (!isLoggerCall(node)) {
147
+ return;
148
+ }
149
+
150
+ const methodName = node.callee.property.name;
151
+ const args = node.arguments;
152
+
153
+ if (args.length === 0) {
154
+ return;
155
+ }
156
+
157
+ if (args.length > 2) {
158
+ context.report({
159
+ node,
160
+ messageId: "tooManyArgs",
161
+ data: { method: methodName },
162
+ });
163
+ return;
164
+ }
165
+
166
+ const firstArg = args[0];
167
+ const secondArg = args[1];
168
+
169
+ if (args.length === 1) {
170
+ if (isStringLiteral(firstArg)) {
171
+ context.report({
172
+ node,
173
+ messageId: "missingObject",
174
+ data: { method: methodName },
175
+ });
176
+ }
177
+ return;
178
+ }
179
+
180
+ if (isStringLiteral(firstArg) && isObjectExpression(secondArg)) {
181
+ context.report({
182
+ node,
183
+ messageId: "wrongOrder",
184
+ data: { method: methodName },
185
+ });
186
+ }
187
+
188
+ if (!isObjectExpression(firstArg)) {
189
+ context.report({
190
+ node,
191
+ messageId: "missingObject",
192
+ data: { method: methodName },
193
+ });
194
+ }
195
+
196
+ checkObjectProperties(firstArg, methodName);
197
+ },
198
+ };
199
+ },
200
+ };
@@ -0,0 +1,112 @@
1
+ /**
2
+ * @fileoverview Erzwingt die Verwendung von DTO-Klassen anstelle von Interfaces
3
+ */
4
+
5
+ "use strict";
6
+
7
+ const preferDtoClassesRule = {
8
+ meta: {
9
+ type: "suggestion",
10
+ docs: {
11
+ description: "Erzwingt die Verwendung von DTO-Klassen anstelle von Interfaces für Datenübertragung",
12
+ category: "Best Practices",
13
+ recommended: true,
14
+ },
15
+ fixable: null,
16
+ schema: [],
17
+ messages: {
18
+ preferDtoClass: "Interface '{{interfaceName}}' sollte als DTO-Klasse implementiert werden. DTO-Klassen bieten Runtime-Validierung, bessere Type Safety und Konsistenz.",
19
+ useFactoryFunction: "Wenn ein Interface für '{{interfaceName}}' notwendig ist (z.B. interne Types), füge eine Factory-Funktion hinzu: 'export const create{{interfaceName}} = (...) => ({ ... });'",
20
+ },
21
+ },
22
+
23
+ create(context) {
24
+ const filename = context.getFilename();
25
+
26
+ // Nur DTO-Dateien prüfen
27
+ if (!filename.includes("/dto/") || filename.includes("test") || filename.includes("spec")) {
28
+ return {};
29
+ }
30
+
31
+ // Identifiziere DTO-Interfaces
32
+ function isDtoInterface(interfaceName) {
33
+ return (
34
+ interfaceName.endsWith("Dto") ||
35
+ interfaceName.endsWith("DTO") ||
36
+ interfaceName.includes("Request") ||
37
+ interfaceName.includes("Response") ||
38
+ interfaceName.includes("Create") ||
39
+ interfaceName.includes("Update") ||
40
+ interfaceName.includes("Delete") ||
41
+ interfaceName.includes("Model") ||
42
+ interfaceName.includes("Data")
43
+ );
44
+ }
45
+
46
+ // Ausnahmen für akzeptable Interface-Verwendungen
47
+ function isAcceptableInterface(interfaceName, context) {
48
+ const internalTypePatterns = [
49
+ "Type", "Config", "Options", "Settings", "Props", "State"
50
+ ];
51
+
52
+ const componentPatterns = [
53
+ "Component", "Hook", "Context"
54
+ ];
55
+
56
+ return (
57
+ internalTypePatterns.some(pattern => interfaceName.includes(pattern)) ||
58
+ componentPatterns.some(pattern => interfaceName.includes(pattern)) ||
59
+ filename.includes("/types/") || // Reine Type-Definitionen
60
+ filename.includes("/model/") // Business Models
61
+ );
62
+ }
63
+
64
+ return {
65
+ TSInterfaceDeclaration(node) {
66
+ const interfaceName = node.id.name;
67
+
68
+ if (isDtoInterface(interfaceName) && !isAcceptableInterface(interfaceName, context)) {
69
+ // Prüfe, ob eine Factory-Funktion existiert
70
+ const sourceCode = context.getSourceCode();
71
+ const text = sourceCode.getText();
72
+ const hasFactoryFunction = text.includes(`create${interfaceName}`) ||
73
+ text.includes(`new${interfaceName}`);
74
+
75
+ if (!hasFactoryFunction) {
76
+ context.report({
77
+ node,
78
+ messageId: "preferDtoClass",
79
+ data: { interfaceName }
80
+ });
81
+ } else {
82
+ // Warnung mit Hinweis auf Factory-Pattern
83
+ context.report({
84
+ node,
85
+ messageId: "useFactoryFunction",
86
+ data: { interfaceName }
87
+ });
88
+ }
89
+ }
90
+ },
91
+
92
+ // Prüfe auch Type-Aliase
93
+ TSTypeAliasDeclaration(node) {
94
+ const typeName = node.id.name;
95
+
96
+ if (isDtoInterface(typeName) && !isAcceptableInterface(typeName, context)) {
97
+ context.report({
98
+ node,
99
+ messageId: "preferDtoClass",
100
+ data: { interfaceName: typeName }
101
+ });
102
+ }
103
+ }
104
+ };
105
+ }
106
+ };
107
+
108
+ export default {
109
+ rules: {
110
+ "prefer-dto-classes": preferDtoClassesRule,
111
+ },
112
+ };