@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,181 @@
1
+ const noTsyringeRule = {
2
+ meta: {
3
+ type: "problem",
4
+ docs: {
5
+ description: "Verbietet die Verwendung von TSyringe und erzwingt NestJS Dependency Injection",
6
+ category: "Best Practices",
7
+ recommended: true,
8
+ },
9
+ fixable: "code",
10
+ schema: [],
11
+ messages: {
12
+ noTsyringeImport: "TSyringe-Imports sind verboten. Verwende stattdessen NestJS Dependency Injection mit @Injectable() aus '@nestjs/common'",
13
+ noTsyringeContainer: "TSyringe Container ist verboten. Verwende NestJS Module und Constructor Injection",
14
+ noTsyringeDecorator: "TSyringe @injectable() ist verboten. Verwende @Injectable() aus '@nestjs/common'",
15
+ requireNestjsInjectable: "Controller und Services müssen @Injectable() aus '@nestjs/common' verwenden",
16
+ noTsyringeResolve: "container.resolve() ist verboten. Verwende NestJS Constructor Injection",
17
+ },
18
+ },
19
+
20
+ create(context) {
21
+
22
+ let hasNestjsInjectableImport = false;
23
+ let hasInjectableDecorator = false;
24
+ let isControllerOrService = false;
25
+
26
+ return {
27
+ // Überprüfe Imports
28
+ ImportDeclaration(node) {
29
+ const source = node.source.value;
30
+
31
+ // Verbiete TSyringe-Imports
32
+ if (source === "tsyringe") {
33
+ context.report({
34
+ node,
35
+ messageId: "noTsyringeImport",
36
+ fix(fixer) {
37
+ // Entferne TSyringe-Import und ersetze durch NestJS
38
+ const specifiers = node.specifiers
39
+ .map(spec => spec.imported?.name || spec.local?.name)
40
+ .filter(name => name === "injectable" || name === "Injectable");
41
+
42
+ if (specifiers.includes("injectable") || specifiers.includes("Injectable")) {
43
+ return fixer.replaceText(
44
+ node,
45
+ 'import { Injectable } from "@nestjs/common";'
46
+ );
47
+ }
48
+
49
+ return fixer.remove(node);
50
+ },
51
+ });
52
+ }
53
+
54
+ // Überprüfe NestJS Injectable Import
55
+ if (source === "@nestjs/common") {
56
+ const injectableImport = node.specifiers.find(
57
+ spec => spec.imported?.name === "Injectable"
58
+ );
59
+ if (injectableImport) {
60
+ hasNestjsInjectableImport = true;
61
+ }
62
+ }
63
+ },
64
+
65
+ // Überprüfe Dekoratoren
66
+ Decorator(node) {
67
+ if (node.expression?.name === "injectable") {
68
+ context.report({
69
+ node,
70
+ messageId: "noTsyringeDecorator",
71
+ fix(fixer) {
72
+ return fixer.replaceText(node, "@Injectable()");
73
+ },
74
+ });
75
+ }
76
+
77
+ if (node.expression?.name === "Injectable" ||
78
+ (node.expression?.callee?.name === "Injectable")) {
79
+ hasInjectableDecorator = true;
80
+ }
81
+
82
+ if (node.expression?.name === "Controller" ||
83
+ node.expression?.name === "Service" ||
84
+ (node.expression?.callee?.name === "Controller")) {
85
+ isControllerOrService = true;
86
+ }
87
+ },
88
+
89
+ // Überprüfe TSyringe Container-Verwendung
90
+ MemberExpression(node) {
91
+ if (
92
+ node.object?.name === "container" &&
93
+ (node.property?.name === "resolve" ||
94
+ node.property?.name === "register" ||
95
+ node.property?.name === "registerInstance")
96
+ ) {
97
+ context.report({
98
+ node,
99
+ messageId: "noTsyringeContainer",
100
+ });
101
+ }
102
+ },
103
+
104
+ // Überprüfe am Ende der Datei
105
+ "Program:exit"() {
106
+ const filename = context.getFilename();
107
+ const isControllerFile = filename.includes("Controller.ts") && !filename.includes("test");
108
+ const isServiceFile = filename.includes("Service.ts") && !filename.includes("test");
109
+
110
+ // BaseController ausschließen
111
+ if (filename.includes("BaseController.ts")) {
112
+ return;
113
+ }
114
+
115
+ if ((isControllerFile || isServiceFile || isControllerOrService) &&
116
+ !hasInjectableDecorator &&
117
+ !filename.includes("test") &&
118
+ !filename.includes("spec")) {
119
+
120
+ // Finde die erste Klassen-Deklaration
121
+ const program = context.getSourceCode().ast;
122
+ const classDeclaration = program.body.find(node =>
123
+ node.type === "ExportDefaultDeclaration" &&
124
+ node.declaration?.type === "ClassDeclaration"
125
+ );
126
+
127
+ if (classDeclaration) {
128
+ context.report({
129
+ node: classDeclaration,
130
+ messageId: "requireNestjsInjectable",
131
+ fix(fixer) {
132
+ const fixes = [];
133
+
134
+ // Füge Injectable Import hinzu, falls nicht vorhanden
135
+ if (!hasNestjsInjectableImport) {
136
+ const imports = program.body.filter(node => node.type === "ImportDeclaration");
137
+ const nestjsImport = imports.find(imp => imp.source.value === "@nestjs/common");
138
+
139
+ if (nestjsImport) {
140
+ // Erweitere existierenden NestJS Import
141
+ const specifiers = nestjsImport.specifiers.map(spec => spec.imported?.name || spec.local?.name);
142
+ if (!specifiers.includes("Injectable")) {
143
+ const newSpecifiers = [...specifiers, "Injectable"].join(", ");
144
+ fixes.push(fixer.replaceText(
145
+ nestjsImport,
146
+ `import { ${newSpecifiers} } from "@nestjs/common";`
147
+ ));
148
+ }
149
+ } else {
150
+ // Füge neuen Injectable Import hinzu
151
+ const firstImport = imports[0];
152
+ if (firstImport) {
153
+ fixes.push(fixer.insertTextBefore(
154
+ firstImport,
155
+ 'import { Injectable } from "@nestjs/common";\n'
156
+ ));
157
+ }
158
+ }
159
+ }
160
+
161
+ // Füge @Injectable() Dekorator hinzu
162
+ fixes.push(fixer.insertTextBefore(
163
+ classDeclaration,
164
+ "@Injectable()\n"
165
+ ));
166
+
167
+ return fixes;
168
+ },
169
+ });
170
+ }
171
+ }
172
+ },
173
+ };
174
+ },
175
+ };
176
+
177
+ export default {
178
+ rules: {
179
+ "no-tsyringe": noTsyringeRule,
180
+ },
181
+ };
@@ -0,0 +1,175 @@
1
+ export default {
2
+ rules: {
3
+ "no-type-assertion": {
4
+ meta: {
5
+ type: "problem",
6
+ docs: {
7
+ description: "Verbietet Type Assertions mit 'as'",
8
+ category: "Best Practices",
9
+ recommended: true,
10
+ },
11
+ schema: [],
12
+ messages: {
13
+ noTypeAssertion: "Type Assertions mit 'as' sind verboten. Verwende stattdessen Typ-Guards oder Validierung.",
14
+ },
15
+ },
16
+
17
+ create(context) {
18
+ // Prüfe, ob wir in einer Validierungsfunktion sind
19
+ const isInValidationFunction = (node) => {
20
+ let current = node;
21
+ while (current) {
22
+ if (current.type === 'MethodDefinition' && current.key.name && current.key.name.includes('Valid')) {
23
+ return true;
24
+ }
25
+ if (current.type === 'FunctionDeclaration' && current.id.name && current.id.name.includes('Valid')) {
26
+ return true;
27
+ }
28
+ current = current.parent;
29
+ }
30
+ return false;
31
+ };
32
+
33
+ // Prüfe, ob wir in einer DTO-Entity-Mapping-Methode sind
34
+ const isInDtoEntityMappingMethod = (node) => {
35
+ let current = node;
36
+ while (current) {
37
+ if (current.type === 'MethodDefinition' && current.key.name &&
38
+ (current.key.name === 'fromEntity' || current.key.name === 'toEntity' || current.key.name === 'fromEntityArray')) {
39
+ return true;
40
+ }
41
+ if (current.type === 'FunctionDeclaration' && current.id.name &&
42
+ (current.id.name === 'fromEntity' || current.id.name === 'toEntity' || current.id.name === 'fromEntityArray')) {
43
+ return true;
44
+ }
45
+ current = current.parent;
46
+ }
47
+ return false;
48
+ };
49
+
50
+ // Prüfe, ob es sich um eine Conditional Type Assertion handelt
51
+ const isConditionalTypeAssertion = (node) => {
52
+ if (node.typeAnnotation && node.typeAnnotation.type === 'TSConditionalType') {
53
+ return true;
54
+ }
55
+ return false;
56
+ };
57
+
58
+ // Prüfe, ob es sich um eine Generic Type Assertion handelt
59
+ const isGenericTypeAssertion = (node) => {
60
+ if (node.typeAnnotation && node.typeAnnotation.type === 'TSTypeReference') {
61
+ // Prüfe auf generische Parameter
62
+ if (node.typeAnnotation.typeParameters && node.typeAnnotation.typeParameters.params) {
63
+ return true;
64
+ }
65
+ }
66
+ return false;
67
+ };
68
+
69
+ // Prüfe, ob es sich um eine DTO-Entity-Mapping Type Assertion handelt
70
+ const isDtoEntityMappingAssertion = (node) => {
71
+ if (node.typeAnnotation) {
72
+ const typeAnnotation = node.typeAnnotation;
73
+
74
+ // Prüfe auf Conditional Types mit "extends"
75
+ if (typeAnnotation.type === 'TSConditionalType') {
76
+ return true;
77
+ }
78
+
79
+ // Prüfe auf Type References mit generischen Parametern
80
+ if (typeAnnotation.type === 'TSTypeReference') {
81
+ // Prüfe auf "T extends" Pattern
82
+ if (typeAnnotation.typeName && typeAnnotation.typeName.name === 'T') {
83
+ return true;
84
+ }
85
+
86
+ // Prüfe auf EntityDto oder EntityDto<...> Pattern
87
+ if (typeAnnotation.typeName &&
88
+ typeAnnotation.typeName.name &&
89
+ (typeAnnotation.typeName.name.includes('EntityDto') ||
90
+ typeAnnotation.typeName.name.includes('Entity'))) {
91
+ return true;
92
+ }
93
+ }
94
+ }
95
+ return false;
96
+ };
97
+
98
+ return {
99
+ TSAsExpression(node) {
100
+ const filename = context.getFilename();
101
+
102
+ // Erlaube Type Assertions in bestimmten Dateien
103
+ if (filename.includes('BaseController.ts') ||
104
+ filename.includes('openapi.ts') ||
105
+ filename.includes('/setup/') ||
106
+ filename.includes('/config/')) {
107
+ return;
108
+ }
109
+
110
+ // Erlaube Type Assertions in Validierungsfunktionen
111
+ if (isInValidationFunction(node)) {
112
+ return;
113
+ }
114
+
115
+ // Erlaube Type Assertions in DTO-Entity-Mapping-Methoden
116
+ if (isInDtoEntityMappingMethod(node)) {
117
+ return;
118
+ }
119
+
120
+ // Erlaube Conditional Type Assertions (für Generics)
121
+ if (isConditionalTypeAssertion(node)) {
122
+ return;
123
+ }
124
+
125
+ // Erlaube Generic Type Assertions (für Generics)
126
+ if (isGenericTypeAssertion(node)) {
127
+ return;
128
+ }
129
+
130
+ // Erlaube DTO-Entity-Mapping Type Assertions (für Generics)
131
+ if (isDtoEntityMappingAssertion(node)) {
132
+ return;
133
+ }
134
+
135
+ context.report({
136
+ node,
137
+ messageId: "noTypeAssertion",
138
+ });
139
+ },
140
+ TSTypeAssertion(node) {
141
+ // Erlaube Type Assertions in Validierungsfunktionen
142
+ if (isInValidationFunction(node)) {
143
+ return;
144
+ }
145
+
146
+ // Erlaube Type Assertions in DTO-Entity-Mapping-Methoden
147
+ if (isInDtoEntityMappingMethod(node)) {
148
+ return;
149
+ }
150
+
151
+ // Erlaube Conditional Type Assertions (für Generics)
152
+ if (isConditionalTypeAssertion(node)) {
153
+ return;
154
+ }
155
+
156
+ // Erlaube Generic Type Assertions (für Generics)
157
+ if (isGenericTypeAssertion(node)) {
158
+ return;
159
+ }
160
+
161
+ // Erlaube DTO-Entity-Mapping Type Assertions (für Generics)
162
+ if (isDtoEntityMappingAssertion(node)) {
163
+ return;
164
+ }
165
+
166
+ context.report({
167
+ node,
168
+ messageId: "noTypeAssertion",
169
+ });
170
+ },
171
+ };
172
+ },
173
+ },
174
+ },
175
+ };
@@ -0,0 +1,121 @@
1
+ /**
2
+ * @fileoverview Verhindert undefined Properties in Entity-Klassen
3
+ * Entities sollten niemals undefined Properties haben - verwende stattdessen null oder entferne das Property
4
+ */
5
+
6
+ /** @type {import('eslint').Rule.RuleModule} */
7
+ const noUndefinedEntityPropertiesRule = {
8
+ meta: {
9
+ type: "problem",
10
+ docs: {
11
+ description: "Verhindert undefined Properties in Entity-Klassen",
12
+ category: "TypeORM",
13
+ recommended: true,
14
+ },
15
+ hasSuggestions: true,
16
+ schema: [],
17
+ messages: {
18
+ undefinedPropertyInEntity: "Entity '{{entityName}}' hat undefined Property '{{propertyName}}'. Verwende stattdessen '{{propertyName}}: {{type}} | null' oder entferne das Property.",
19
+ suggestUseNull: "Verwende '| null' statt 'undefined'",
20
+ suggestRemoveOptional: "Entferne das '?' und verwende '| null'",
21
+ },
22
+ },
23
+
24
+ create(context) {
25
+ const filename = context.getFilename();
26
+
27
+ // Nur Entity-Dateien prüfen
28
+ const isEntityFile = filename.includes("/entity/") || filename.includes("fixtures/");
29
+ const hasEntityExtension = filename.includes("Entity") && filename.endsWith(".ts");
30
+
31
+ if (!isEntityFile || !hasEntityExtension) {
32
+ return {};
33
+ }
34
+
35
+ return {
36
+ ClassDeclaration(node) {
37
+ const className = node.id?.name;
38
+
39
+ // Nur Entity-Klassen prüfen
40
+ if (!className || !className.endsWith("Entity")) {
41
+ return;
42
+ }
43
+
44
+ // Durchsuche alle Properties der Klasse
45
+ node.body.body.forEach(member => {
46
+ if (member.type === "PropertyDefinition" || member.type === "TSParameterProperty") {
47
+ const propertyName = member.key?.name;
48
+ const propertyType = member.typeAnnotation?.typeAnnotation;
49
+
50
+ if (!propertyName || !propertyType) {
51
+ return;
52
+ }
53
+
54
+ // Prüfe auf undefined in Union Types
55
+ if (propertyType.type === "TSUnionType") {
56
+ const hasUndefined = propertyType.types.some(type =>
57
+ type.type === "TSUndefinedKeyword"
58
+ );
59
+
60
+ if (hasUndefined) {
61
+ const typeString = context.getSourceCode().getText(propertyType);
62
+ const correctedType = typeString.replace(/\|\s*undefined/g, " | null");
63
+
64
+ context.report({
65
+ node: member,
66
+ messageId: "undefinedPropertyInEntity",
67
+ data: {
68
+ entityName: className,
69
+ propertyName,
70
+ type: correctedType.replace(/\|\s*null/g, "").trim()
71
+ },
72
+ suggest: [
73
+ {
74
+ desc: "Verwende '| null' statt 'undefined'",
75
+ fix(fixer) {
76
+ return fixer.replaceText(propertyType, correctedType);
77
+ }
78
+ }
79
+ ]
80
+ });
81
+ }
82
+ }
83
+
84
+ // Prüfe auf optional Properties (?) - diese sollten in Entities vermieden werden
85
+ if (member.optional) {
86
+ const typeString = context.getSourceCode().getText(propertyType);
87
+
88
+ context.report({
89
+ node: member,
90
+ messageId: "undefinedPropertyInEntity",
91
+ data: {
92
+ entityName: className,
93
+ propertyName,
94
+ type: typeString
95
+ },
96
+ suggest: [
97
+ {
98
+ desc: "Entferne das '?' und verwende '| null'",
99
+ fix(fixer) {
100
+ const newType = `${typeString} | null`;
101
+ return fixer.replaceTextRange(
102
+ [member.typeAnnotation.range[0], member.typeAnnotation.range[1]],
103
+ `: ${newType}`
104
+ );
105
+ }
106
+ }
107
+ ]
108
+ });
109
+ }
110
+ }
111
+ });
112
+ }
113
+ };
114
+ },
115
+ };
116
+
117
+ export default {
118
+ rules: {
119
+ "no-undefined-entity-properties": noUndefinedEntityPropertiesRule,
120
+ },
121
+ };
package/rules/node.js ADDED
@@ -0,0 +1,44 @@
1
+ // Node.js Rules
2
+ export default {
3
+ env: {
4
+ node: true
5
+ },
6
+
7
+ rules: {
8
+ // enforce return after a callback
9
+ 'callback-return': 'off',
10
+
11
+ // require all requires be top-level
12
+ // https://eslint.org/docs/rules/global-require
13
+ 'global-require': 'error',
14
+
15
+ // enforces error handling in callbacks (node environment)
16
+ 'handle-callback-err': 'off',
17
+
18
+ // disallow use of the Buffer() constructor
19
+ // https://eslint.org/docs/rules/no-buffer-constructor
20
+ 'no-buffer-constructor': 'error',
21
+
22
+ // disallow mixing regular variable and require declarations
23
+ 'no-mixed-requires': ['off', false],
24
+
25
+ // disallow use of new operator with the require function
26
+ 'no-new-require': 'error',
27
+
28
+ // disallow string concatenation with __dirname and __filename
29
+ // https://eslint.org/docs/rules/no-path-concat
30
+ 'no-path-concat': 'error',
31
+
32
+ // disallow use of process.env
33
+ 'no-process-env': 'off',
34
+
35
+ // disallow process.exit()
36
+ 'no-process-exit': 'off',
37
+
38
+ // restrict usage of specified node modules
39
+ 'no-restricted-modules': 'off',
40
+
41
+ // disallow use of synchronous methods (off by default)
42
+ 'no-sync': 'off',
43
+ }
44
+ };
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Perfectionist Rules
3
+ *
4
+ * Perfectionist-Regeln für konsistente Code-Formatierung
5
+ */
6
+
7
+ export default {
8
+ rules: {
9
+ // Perfectionist-Regeln
10
+ "perfectionist/sort-imports": ["error", {
11
+ type: "alphabetical",
12
+ order: "asc",
13
+ ignoreCase: true,
14
+ newlinesBetween: "always",
15
+ maxLineLength: undefined,
16
+ groups: [
17
+ "type",
18
+ ["builtin", "external"],
19
+ "internal-type",
20
+ "internal",
21
+ ["parent-type", "sibling-type", "index-type"],
22
+ ["parent", "sibling", "index"],
23
+ "object",
24
+ "unknown",
25
+ ],
26
+ }],
27
+ "perfectionist/sort-object-types": ["error", {
28
+ type: "alphabetical",
29
+ order: "asc",
30
+ ignoreCase: true,
31
+ }],
32
+ "perfectionist/sort-interfaces": ["error", {
33
+ type: "alphabetical",
34
+ order: "asc",
35
+ ignoreCase: true,
36
+ }],
37
+ "perfectionist/sort-enums": ["error", {
38
+ type: "alphabetical",
39
+ order: "asc",
40
+ ignoreCase: true,
41
+ }],
42
+ "perfectionist/sort-array-includes": ["error", {
43
+ type: "alphabetical",
44
+ order: "asc",
45
+ ignoreCase: true,
46
+ }],
47
+ },
48
+ };
49
+
50
+