@sun-asterisk/sunlint 1.3.16 → 1.3.17

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 (50) hide show
  1. package/config/rule-analysis-strategies.js +3 -3
  2. package/config/rules/enhanced-rules-registry.json +40 -20
  3. package/core/cli-action-handler.js +2 -2
  4. package/core/config-merger.js +28 -6
  5. package/core/constants/defaults.js +1 -1
  6. package/core/file-targeting-service.js +72 -4
  7. package/core/output-service.js +21 -4
  8. package/engines/heuristic-engine.js +5 -0
  9. package/package.json +1 -1
  10. package/rules/common/C002_no_duplicate_code/README.md +115 -0
  11. package/rules/common/C002_no_duplicate_code/analyzer.js +615 -219
  12. package/rules/common/C002_no_duplicate_code/test-cases/api-handlers.ts +64 -0
  13. package/rules/common/C002_no_duplicate_code/test-cases/data-processor.ts +46 -0
  14. package/rules/common/C002_no_duplicate_code/test-cases/good-example.tsx +40 -0
  15. package/rules/common/C002_no_duplicate_code/test-cases/product-service.ts +57 -0
  16. package/rules/common/C002_no_duplicate_code/test-cases/user-service.ts +49 -0
  17. package/rules/common/C008/analyzer.js +40 -0
  18. package/rules/common/C008/config.json +20 -0
  19. package/rules/common/C008/ts-morph-analyzer.js +1067 -0
  20. package/rules/common/C018_no_throw_generic_error/analyzer.js +1 -1
  21. package/rules/common/C018_no_throw_generic_error/symbol-based-analyzer.js +27 -3
  22. package/rules/common/C024_no_scatter_hardcoded_constants/symbol-based-analyzer.js +504 -162
  23. package/rules/common/C029_catch_block_logging/analyzer.js +499 -89
  24. package/rules/common/C033_separate_service_repository/README.md +131 -20
  25. package/rules/common/C033_separate_service_repository/analyzer.js +1 -1
  26. package/rules/common/C033_separate_service_repository/symbol-based-analyzer.js +417 -274
  27. package/rules/common/C041_no_sensitive_hardcode/analyzer.js +144 -254
  28. package/rules/common/C041_no_sensitive_hardcode/config.json +50 -0
  29. package/rules/common/C041_no_sensitive_hardcode/symbol-based-analyzer.js +575 -0
  30. package/rules/common/C067_no_hardcoded_config/analyzer.js +17 -16
  31. package/rules/common/C067_no_hardcoded_config/symbol-based-analyzer.js +3477 -659
  32. package/rules/docs/C002_no_duplicate_code.md +276 -11
  33. package/rules/index.js +5 -1
  34. package/rules/security/S006_no_plaintext_recovery_codes/analyzer.js +266 -88
  35. package/rules/security/S006_no_plaintext_recovery_codes/symbol-based-analyzer.js +805 -0
  36. package/rules/security/S010_no_insecure_encryption/README.md +78 -0
  37. package/rules/security/S010_no_insecure_encryption/analyzer.js +463 -398
  38. package/rules/security/S013_tls_enforcement/README.md +51 -0
  39. package/rules/security/S013_tls_enforcement/analyzer.js +99 -0
  40. package/rules/security/S013_tls_enforcement/config.json +41 -0
  41. package/rules/security/S013_tls_enforcement/symbol-based-analyzer.js +339 -0
  42. package/rules/security/S014_tls_version_enforcement/README.md +354 -0
  43. package/rules/security/S014_tls_version_enforcement/analyzer.js +118 -0
  44. package/rules/security/S014_tls_version_enforcement/config.json +56 -0
  45. package/rules/security/S014_tls_version_enforcement/symbol-based-analyzer.js +194 -0
  46. package/rules/security/S055_content_type_validation/analyzer.js +121 -279
  47. package/rules/security/S055_content_type_validation/symbol-based-analyzer.js +346 -0
  48. package/rules/tests/C002_no_duplicate_code.test.js +111 -22
  49. package/rules/common/C029_catch_block_logging/analyzer-smart-pipeline.js +0 -755
  50. package/rules/common/C041_no_sensitive_hardcode/ast-analyzer.js +0 -296
@@ -2,23 +2,38 @@
2
2
 
3
3
  ## Rule Description
4
4
 
5
- Enforces proper separation between Service and Repository layers in your application architecture:
5
+ **Mục tiêu:** Tách ràng business logic data access logic trong kiến trúc ứng dụng
6
6
 
7
- - **Services** should contain business logic and use repositories for data access
8
- - **Repositories** should contain only data access logic, no business rules
7
+ ### Nguyên tắc
8
+
9
+ - ✅ **Repository** chỉ chứa các phương thức truy vấn dữ liệu cơ bản (CRUD)
10
+ - ✅ **Service** chứa business logic và sử dụng Repository để truy vấn dữ liệu
11
+ - ✅ Mỗi Service nên có một Repository tương ứng
12
+ - ✅ Sử dụng dependency injection để inject Repository vào Service
13
+ - ❌ Tránh viết business logic trong Repository
14
+ - ❌ Service không nên trực tiếp gọi database/ORM
15
+
16
+ ### Lợi ích
17
+
18
+ - 🔄 Tăng khả năng tái sử dụng và test
19
+ - 🎯 Tách biệt rõ ràng giữa business logic và data access
20
+ - 🔧 Dễ dàng thay đổi implementation của data access layer
21
+ - 📈 Tăng tính maintainable của code
22
+ - ✨ Tuân thủ nguyên tắc Single Responsibility
9
23
 
10
24
  ## Architecture
11
25
 
12
- This rule uses a **hybrid analysis approach**:
26
+ Rule này sử dụng **hybrid analysis approach**:
13
27
 
14
- 1. **Primary: Symbol-based Analysis** (using ts-morph)
15
- - AST parsing and symbol resolution
16
- - Accurate detection of database operations
17
- - Excludes queue/job operations automatically
28
+ 1. **Primary: Symbol-based Analysis** (ts-morph AST)
29
+ - Phân tích semantic symbol resolution
30
+ - Phát hiện chính xác database operations
31
+ - Kiểm tra dependency injection patterns
32
+ - Phát hiện business logic trong Repository
18
33
 
19
34
  2. **Fallback: Regex-based Analysis**
20
- - Pattern matching for when symbol analysis fails
21
- - Handles edge cases and complex code structures
35
+ - Pattern matching khi symbol analysis không khả dụng
36
+ - Xử edge cases complex code structures
22
37
 
23
38
  ## Files Structure
24
39
 
@@ -33,20 +48,116 @@ C033_separate_service_repository/
33
48
 
34
49
  ## What this rule detects
35
50
 
36
- ### Violations in Service files:
37
- - Direct database calls (`repository.createQueryBuilder()`, `dataSource.createQueryBuilder()`)
38
- - Direct ORM operations (`entity.save()`, `entity.find()`)
39
- - SQL queries embedded in service methods
40
- - **Excludes**: Queue/job operations (`job.remove()`, `job.isFailed()`, etc.)
51
+ ### 🚫 Violations in Service files
52
+
53
+ - Direct database/ORM operations without Repository
54
+ - `findOne()`, `save()`, `update()`, `delete()`, `query()`
55
+ - `createQueryBuilder()`, `getRepository()`, `getConnection()`
56
+ - Service không inject Repository qua constructor
57
+ - Mixed business logic với data access trong cùng method
58
+
59
+ ### 🚫 Violations in Repository files
60
+
61
+ - Business logic trong Repository methods
62
+ - Method names chứa: `validate`, `calculate`, `process`, `transform`
63
+ - Logic phức tạp: nhiều if/else, loops (>2 control structures)
64
+ - Business calculations, validations, transformations
65
+ - Complex workflows và business rules
66
+
67
+ ### 🚫 Violations in Controller files
68
+
69
+ - Controller trực tiếp gọi database operations
70
+ - Bỏ qua Service layer
41
71
 
42
- ### Violations in Repository files:
43
- - Complex business logic (filtering, calculations, validations)
44
- - Business rules and workflows
45
- - Complex conditional logic for data processing
72
+ ### 🚫 Architecture violations
73
+
74
+ - Service Repository cùng trong một file
75
+ - Không tách biệt concerns ràng
46
76
 
47
77
  ## Examples
48
78
 
49
- See test cases in the standard test fixtures location:
79
+ ### BAD: Service directly accessing database
80
+
81
+ ```typescript
82
+ // service-bad.ts
83
+ class UserService {
84
+ async getUser(id: string) {
85
+ // VIOLATION: Direct database access in Service
86
+ return await this.dataSource
87
+ .getRepository(User)
88
+ .findOne({ where: { id } });
89
+ }
90
+ }
91
+ ```
92
+
93
+ ### ✅ GOOD: Service uses Repository
94
+
95
+ ```typescript
96
+ // user.service.ts
97
+ class UserService {
98
+ constructor(
99
+ private readonly userRepository: UserRepository // DI
100
+ ) {}
101
+
102
+ async getUser(id: string) {
103
+ return await this.userRepository.findById(id);
104
+ }
105
+
106
+ async validateAndCreateUser(data: CreateUserDto) {
107
+ // Business logic in Service
108
+ this.validate(data);
109
+ const user = this.transform(data);
110
+ return await this.userRepository.create(user);
111
+ }
112
+ }
113
+
114
+ // user.repository.ts
115
+ class UserRepository {
116
+ // Only CRUD operations
117
+ async findById(id: string) {
118
+ return await this.db.users.findOne({ where: { id } });
119
+ }
120
+
121
+ async create(user: User) {
122
+ return await this.db.users.save(user);
123
+ }
124
+ }
125
+ ```
126
+
127
+ ### ❌ BAD: Repository with business logic
128
+
129
+ ```typescript
130
+ // repository-bad.ts
131
+ class UserRepository {
132
+ async validateAndSave(user: User) {
133
+ // VIOLATION: Business logic in Repository
134
+ if (user.age < 18) {
135
+ throw new Error('User must be 18+');
136
+ }
137
+
138
+ if (!user.email.includes('@')) {
139
+ throw new Error('Invalid email');
140
+ }
141
+
142
+ return await this.save(user);
143
+ }
144
+ }
145
+ ```
146
+
147
+ ### ✅ GOOD: Repository only handles data access
148
+
149
+ ```typescript
150
+ // repository-good.ts
151
+ class UserRepository {
152
+ // Simple CRUD - no business logic
153
+ async save(user: User) {
154
+ return await this.db.users.save(user);
155
+ }
156
+
157
+ async findByEmail(email: string) {
158
+ return await this.db.users.findOne({ where: { email } });
159
+ }
160
+ }
50
161
 
51
162
  - **Violations**: `examples/rule-test-fixtures/rules/C033_separate_service_repository/violations/test-cases.js`
52
163
  - **Clean code**: `examples/rule-test-fixtures/rules/C033_separate_service_repository/clean/good-examples.js`
@@ -82,7 +82,7 @@ class C033Analyzer {
82
82
  // 1. Try Symbol-based analysis first (primary)
83
83
  if (this.config.useSymbolBased && this.semanticEngine?.project) {
84
84
  try {
85
- const sourceFile = this.semanticEngine.project.getSourceFileByFilePath(filePath);
85
+ const sourceFile = this.semanticEngine.project.getSourceFile(filePath);
86
86
  if (sourceFile) {
87
87
  const violations = await this.symbolBasedAnalyzer.analyzeFileWithSymbols(filePath, options);
88
88