flutter-pro-max-cli 2.3.3 → 2.3.5
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/assets/templates/base/rules/01_skill_usage.md +6 -1
- package/assets/templates/base/rules/02_code_quality.md +6 -1
- package/assets/templates/base/rules/03_interaction_flow.md +6 -1
- package/assets/templates/base/rules/04_app_consistency.md +6 -1
- package/assets/templates/base/rules/05_error_handling.md +6 -1
- package/assets/templates/base/rules/06_testing.md +6 -1
- package/assets/templates/base/rules/07_performance.md +17 -2
- package/assets/templates/base/rules/08_security.md +6 -1
- package/assets/templates/base/rules/09_state_management.md +6 -1
- package/assets/templates/base/rules/10_naming_conventions.md +6 -1
- package/assets/templates/base/rules/11_accessibility.md +6 -1
- package/assets/templates/base/rules/12_network_resiliency.md +22 -0
- package/assets/templates/base/rules/13_offline_first.md +25 -0
- package/assets/templates/base/rules/14_ui_graceful_degradation.md +23 -0
- package/assets/templates/base/rules/15_state_lifecycle.md +30 -0
- package/dist/utils/template.js +9 -2
- package/package.json +1 -1
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Tự động sử dụng skill search trước khi viết code Flutter
|
|
3
|
+
globs: *
|
|
4
|
+
---
|
|
5
|
+
|
|
1
6
|
# Rule: Tự động sử dụng Skill
|
|
2
7
|
|
|
3
8
|
> Kích hoạt: Khi làm việc với Flutter/Dart files
|
|
@@ -19,4 +24,4 @@
|
|
|
19
24
|
User request → Search skill (≥2 domains) → Đọc kết quả → Áp dụng vào code
|
|
20
25
|
```
|
|
21
26
|
|
|
22
|
-
> ⚠️ Viết code Flutter mà không tham khảo skill trước = thiếu context = code chất lượng thấp.
|
|
27
|
+
> ⚠️ Viết code Flutter mà không tham khảo skill trước = thiếu context = code chất lượng thấp.
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Tiêu chuẩn Code Quality, Think-Before-Code, Hard Constraints
|
|
3
|
+
globs: lib/**/*.dart
|
|
4
|
+
---
|
|
5
|
+
|
|
1
6
|
# Rule: Code Quality & Hard Constraints
|
|
2
7
|
|
|
3
8
|
> Kích hoạt: Khi tạo/chỉnh sửa files `.dart`
|
|
@@ -47,4 +52,4 @@
|
|
|
47
52
|
| Hardcode colors, padding, font sizes | Dùng `Theme.of(context)`, design tokens, constants |
|
|
48
53
|
| Business logic trong Widget `build()` | Tách vào UseCase / Service / Provider |
|
|
49
54
|
|
|
50
|
-
> 🔴 **REUSE > CREATE.** Không bao giờ tạo file mới mà không kiểm tra codebase hiện tại trước.
|
|
55
|
+
> 🔴 **REUSE > CREATE.** Không bao giờ tạo file mới mà không kiểm tra codebase hiện tại trước.
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Quy trình làm việc ABCR (Audit-Block-Critique-Refactor) khi nhận request
|
|
3
|
+
globs: *
|
|
4
|
+
---
|
|
5
|
+
|
|
1
6
|
# Rule: Interaction Flow (ABCR)
|
|
2
7
|
|
|
3
8
|
> Kích hoạt: Khi review, refactor, hoặc fix bugs
|
|
@@ -18,4 +23,4 @@ Khi nhận request liên quan đến code hiện tại, luôn tuân thủ quy tr
|
|
|
18
23
|
| User yêu cầu tạo file mới | ⚠️ Chỉ AUDIT các file liên quan |
|
|
19
24
|
| User hỏi kiến thức chung | ❌ Không cần ABCR |
|
|
20
25
|
|
|
21
|
-
> 💡 **Mục đích:** Không bao giờ thêm code rác lên code rác. Fix nền tảng trước.
|
|
26
|
+
> 💡 **Mục đích:** Không bao giờ thêm code rác lên code rác. Fix nền tảng trước.
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Đảm bảo tính nhất quán (Consistency) của UI, Design Tokens, Widget Patterns
|
|
3
|
+
globs: lib/presentation/**/*.dart, lib/ui/**/*.dart, lib/widgets/**/*.dart
|
|
4
|
+
---
|
|
5
|
+
|
|
1
6
|
# Rule: App Consistency
|
|
2
7
|
|
|
3
8
|
> Kích hoạt: Khi tạo UI, thêm screen, hoặc chỉnh sửa widget
|
|
@@ -55,4 +60,4 @@ abstract class AppSpacing {
|
|
|
55
60
|
}
|
|
56
61
|
```
|
|
57
62
|
|
|
58
|
-
> 🔴 **Khi có nghi ngờ:** Mở screen hiện tại có cùng chức năng → copy exact spacing và layout pattern. **Không sáng tạo riêng.**
|
|
63
|
+
> 🔴 **Khi có nghi ngờ:** Mở screen hiện tại có cùng chức năng → copy exact spacing và layout pattern. **Không sáng tạo riêng.**
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Xử lý lỗi, Try-catch, Result pattern, Không fail im lặng
|
|
3
|
+
globs: lib/data/**/*.dart, lib/services/**/*.dart, lib/repositories/**/*.dart, lib/domain/**/*.dart
|
|
4
|
+
---
|
|
5
|
+
|
|
1
6
|
# Rule: Error Handling
|
|
2
7
|
|
|
3
8
|
> Kích hoạt: Khi viết logic xử lý dữ liệu, API calls, hoặc async operations
|
|
@@ -40,4 +45,4 @@ Future<Result<User>> fetchUser(String id) async {
|
|
|
40
45
|
| Throw generic `Exception('Error')` | Tạo custom exceptions có context |
|
|
41
46
|
| Ignore `StackTrace` | Luôn log cả `stackTrace` để debug |
|
|
42
47
|
|
|
43
|
-
> 🔴 **Mỗi `try` phải có `catch` có ý nghĩa.** Log + User message + Recovery action.
|
|
48
|
+
> 🔴 **Mỗi `try` phải có `catch` có ý nghĩa.** Log + User message + Recovery action.
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Viết Unit Test, Widget Test, Integration Test
|
|
3
|
+
globs: test/**/*.dart, lib/**/*.dart
|
|
4
|
+
---
|
|
5
|
+
|
|
1
6
|
# Rule: Testing
|
|
2
7
|
|
|
3
8
|
> Kích hoạt: Khi tạo feature mới, fix bug, hoặc refactor logic
|
|
@@ -45,4 +50,4 @@ test('should return user when API succeeds', () async {
|
|
|
45
50
|
- Mỗi test case chỉ test 1 behavior
|
|
46
51
|
- Tên test mô tả behavior: `should [expected] when [condition]`
|
|
47
52
|
|
|
48
|
-
> 🔴 **Fix bug?** Viết test reproduce bug TRƯỚC, rồi mới fix.
|
|
53
|
+
> 🔴 **Fix bug?** Viết test reproduce bug TRƯỚC, rồi mới fix.
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Tối ưu hiệu năng, const, ListView.builder, Async computation
|
|
3
|
+
globs: lib/presentation/**/*.dart, lib/ui/**/*.dart, lib/widgets/**/*.dart
|
|
4
|
+
---
|
|
5
|
+
|
|
1
6
|
# Rule: Performance
|
|
2
7
|
|
|
3
8
|
> Kích hoạt: Khi viết widget, xử lý danh sách, hoặc async operations
|
|
@@ -37,11 +42,21 @@ ValueListenableBuilder<int>(
|
|
|
37
42
|
);
|
|
38
43
|
```
|
|
39
44
|
|
|
45
|
+
### 4. Performance (Bài toán Scale)
|
|
46
|
+
|
|
47
|
+
Code chạy mượt ở 10 items có thể crash app ở 10,000 items. Lỗi tràn RAM (OOM - Out of Memory) thường âm thầm và khó debug.
|
|
48
|
+
|
|
49
|
+
| Quy mô | Giải pháp Render |
|
|
50
|
+
|--------|------------------|
|
|
51
|
+
| Ít items (< 20) | `Column` bọc trong `SingleChildScrollView` (Có thể chấp nhận) |
|
|
52
|
+
| Nhiều items (Hàng ngàn) | **BẮT BUỘC** dùng `ListView.builder` kết hợp Pagination/Infinite Scroll |
|
|
53
|
+
| Bảng dữ liệu lớn | PaginatedDataTable hoặc Virtualized Lists |
|
|
54
|
+
|
|
40
55
|
### Checklist trước ship
|
|
41
56
|
|
|
42
57
|
- [ ] Tất cả widget có `const` constructor nếu có thể
|
|
43
58
|
- [ ] ListView/GridView dùng `.builder` hoặc `.separated`
|
|
59
|
+
- [ ] Màn hình danh sách có hỗ trợ phân trang (Pagination) nếu data có thể phình to
|
|
44
60
|
- [ ] Không có `print()` còn sót (dùng `developer.log`)
|
|
45
|
-
- [ ] Images có loading/error builders
|
|
46
61
|
|
|
47
|
-
> 🔴 **Nếu list > 20 items → BẮT BUỘC dùng `.builder`.**
|
|
62
|
+
> 🔴 **Nếu list > 20 items → BẮT BUỘC dùng `.builder`.** Luôn tự hỏi: *"Nếu user có 1 triệu record thì sao?"*
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Bảo mật, API Keys, Authentication, Data Protection
|
|
3
|
+
globs: lib/data/**/*.dart, lib/services/**/*.dart, lib/core/env/*.dart
|
|
4
|
+
---
|
|
5
|
+
|
|
1
6
|
# Rule: Security
|
|
2
7
|
|
|
3
8
|
> Kích hoạt: Khi xử lý authentication, API keys, user data, hoặc storage
|
|
@@ -38,4 +43,4 @@
|
|
|
38
43
|
- Timeout cho mọi API call (30s max)
|
|
39
44
|
- Không trust user input từ deep links
|
|
40
45
|
|
|
41
|
-
> 🔴 **Mỗi lần thêm API key hay xử lý auth**, kiểm tra checklist trên.
|
|
46
|
+
> 🔴 **Mỗi lần thêm API key hay xử lý auth**, kiểm tra checklist trên.
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Quản lý state theo cấp độ (Native-first), ValueNotifier
|
|
3
|
+
globs: lib/presentation/**/*.dart, lib/ui/**/*.dart
|
|
4
|
+
---
|
|
5
|
+
|
|
1
6
|
# Rule: State Management
|
|
2
7
|
|
|
3
8
|
> Kích hoạt: Khi quản lý state trong widget, screen, hoặc app-level
|
|
@@ -51,4 +56,4 @@ class CartNotifier extends ChangeNotifier {
|
|
|
51
56
|
}
|
|
52
57
|
```
|
|
53
58
|
|
|
54
|
-
> ⚠️ **KHÔNG tự ý thêm Riverpod/Bloc/GetX.** Hỏi user trước nếu cần escalate.
|
|
59
|
+
> ⚠️ **KHÔNG tự ý thêm Riverpod/Bloc/GetX.** Hỏi user trước nếu cần escalate.
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Quy tắc đặt tên (Naming), Cấu trúc thư mục (Folder Structure), Git Commit
|
|
3
|
+
globs: lib/**/*.dart, test/**/*.dart
|
|
4
|
+
---
|
|
5
|
+
|
|
1
6
|
# Rule: Naming & Conventions
|
|
2
7
|
|
|
3
8
|
> Kích hoạt: Khi tạo files, classes, functions, hoặc variables
|
|
@@ -67,4 +72,4 @@ test(auth): add login use case unit tests
|
|
|
67
72
|
| `test` | Thêm/sửa tests |
|
|
68
73
|
| `chore` | Config, dependencies, tooling |
|
|
69
74
|
|
|
70
|
-
> 🔴 **Đặt tên file/class sai convention?** Rename ngay, không để nợ.
|
|
75
|
+
> 🔴 **Đặt tên file/class sai convention?** Rename ngay, không để nợ.
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Tiêu chuẩn tiếp cận (Accessibility), Semantics, Contrast
|
|
3
|
+
globs: lib/presentation/**/*.dart, lib/widgets/**/*.dart
|
|
4
|
+
---
|
|
5
|
+
|
|
1
6
|
# Rule: Accessibility
|
|
2
7
|
|
|
3
8
|
> Kích hoạt: Khi tạo UI, interactive elements, hoặc form inputs
|
|
@@ -53,4 +58,4 @@ Image.network(
|
|
|
53
58
|
| Navigation | Focus order hợp lý |
|
|
54
59
|
| Colors | Không dùng màu là cách duy nhất truyền thông tin |
|
|
55
60
|
|
|
56
|
-
> 🔴 **Mỗi `IconButton` PHẢI có `tooltip`.** Mỗi `Image` PHẢI có `semanticLabel`.
|
|
61
|
+
> 🔴 **Mỗi `IconButton` PHẢI có `tooltip`.** Mỗi `Image` PHẢI có `semanticLabel`.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Xử lý Network Failures, Tránh bão Request, Exponential Backoff, Circuit Breaker
|
|
3
|
+
globs: lib/data/**/*.dart, lib/services/**/*.dart, lib/repositories/**/*.dart
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Rule: Network & API Resiliency
|
|
7
|
+
|
|
8
|
+
> Kích hoạt: Khi viết API calls, cấu hình HTTP clients (Dio/Http), xử lý timeout
|
|
9
|
+
|
|
10
|
+
## Nguyên tắc: Tránh bão Request
|
|
11
|
+
|
|
12
|
+
Khi API lỗi do server quá tải, **TUYỆT ĐỐI KHÔNG** dùng vòng lặp retry vô tội vạ, vì sẽ tạo thêm gánh nặng làm sập hẳn server đang "thở oxy".
|
|
13
|
+
|
|
14
|
+
### Giải pháp bắt buộc
|
|
15
|
+
|
|
16
|
+
| Tình huống | Kỹ thuật áp dụng |
|
|
17
|
+
|------------|------------------|
|
|
18
|
+
| Lỗi 5xx / Timeout | **Exponential Backoff**: Tăng thời gian chờ sau mỗi lần thử (vd: 1s, 2s, 4s, 8s...) |
|
|
19
|
+
| Server chết liên tục | **Circuit Breaker**: Ngắt hoàn toàn request trong 1 khoảng thời gian nhất định để server phục hồi. |
|
|
20
|
+
| Mạng chập chờn | Cảnh báo UI thanh lịch (Snackbar / Retry button), không quăng exception đỏ màn hình. |
|
|
21
|
+
|
|
22
|
+
> 🔴 **Luôn tự hỏi:** *"Nếu API endpoint này sập, app của mình có sập theo hay không bị treo cứng không?"*
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Tư duy Offline-First, Cache dữ liệu, Đồng bộ ngầm, Xử lý khi mất mạng
|
|
3
|
+
globs: lib/data/**/*.dart, lib/repositories/**/*.dart, lib/presentation/**/*.dart
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Rule: Offline-First Experience
|
|
7
|
+
|
|
8
|
+
> Kích hoạt: Khi thiết kế luồng dữ liệu, fetch data cho màn hình chính (Dashboard, List)
|
|
9
|
+
|
|
10
|
+
## Nguyên tắc: Sống sót không cần mạng
|
|
11
|
+
|
|
12
|
+
Khi thiết bị lọt vào vùng mất mạng, **TUYỆT ĐỐI KHÔNG** để vòng xoay loading chạy vô tận hoặc văng ra màn hình trắng trơn.
|
|
13
|
+
|
|
14
|
+
### Kiến trúc Offline-First
|
|
15
|
+
|
|
16
|
+
1. **Lớp Cache Cache:** Bắt buộc có Local DB (SQLite, Isar, Hive) để lưu dữ liệu quan trọng.
|
|
17
|
+
2. **Luồng ưu tiên Local:**
|
|
18
|
+
- Khi mở màn hình: Load data từ Local DB hiển thị lên UI **ngay lập tức**.
|
|
19
|
+
- Kích hoạt đồng bộ ngầm (background fetch) với server.
|
|
20
|
+
- Khi có data mới từ server: Cập nhật DB nội bộ, luồng stream tự động đẩy data thiết kế mới lên UI một cách mượt mà.
|
|
21
|
+
|
|
22
|
+
### Checklist Offline
|
|
23
|
+
- [ ] Mở app khi ngắt Wi-Fi vẫn thấy được dữ liệu cũ.
|
|
24
|
+
- [ ] Thao tác (Like, Xoá, Nút bấm) được lưu tạm hàng đợi (Queue) để sync lại khi có mạng.
|
|
25
|
+
- [ ] Có thông báo tinh tế báo hiệu đang xài ở chế độ Offline.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Xử lý Graceful Degradation, Fallback UI khi component/dữ liệu lỗi
|
|
3
|
+
globs: lib/presentation/**/*.dart, lib/ui/**/*.dart, lib/widgets/**/*.dart
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Rule: Graceful Degradation (UI Fallback)
|
|
7
|
+
|
|
8
|
+
> Kích hoạt: Khi build UI components, handle Image Network, List Items
|
|
9
|
+
|
|
10
|
+
## Nguyên tắc: Lỗi cục bộ không được sập toàn cục
|
|
11
|
+
|
|
12
|
+
Khi một thành phần UI hoặc dữ liệu bị fail, **đừng làm sập cả màn hình**. Tính thanh lịch của app nằm ở việc fallback giấu lỗi.
|
|
13
|
+
|
|
14
|
+
### Các Fallback Pattern Bắt Buộc
|
|
15
|
+
|
|
16
|
+
| Lỗi Component | Giải pháp UI (Fallback) |
|
|
17
|
+
|---------------|-------------------------|
|
|
18
|
+
| Hình ảnh (Avatar, Banner) lỗi tải (CDN down/404) | Hiển thị Default Image Icon, Placeholder, hoặc Chữ cái đầu của Tên (Initials Avatar). |
|
|
19
|
+
| 1 Item lỗi trong ListView | Hiển thị `ErrorItemWidget` nhỏ cho riêng dòng đó, thay vì ném Exception break toàn list. |
|
|
20
|
+
| Font chữ không tải được | Cấu hình Fallback về System Font mặc định. |
|
|
21
|
+
| Widget tương tác lỗi | Vô hiệu hoá (Disable) nút bấm đó và đổi màu xám thay vì crash khi bấm. |
|
|
22
|
+
|
|
23
|
+
> 🔴 **Quy tắc vàng:** Luôn định nghĩa thuộc tính `errorBuilder` cho mọi Network Image.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Xử lý Vòng đời thiêt bị (Lifecycle), Orientation Change, Background State
|
|
3
|
+
globs: lib/presentation/**/*.dart, lib/logic/**/*.dart, lib/providers/**/*.dart
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Rule: State & Lifecycle Resilience
|
|
7
|
+
|
|
8
|
+
> Kích hoạt: Khi quản lý State (Bloc/Provider/Riverpod), xử lý orientation, handle app background state
|
|
9
|
+
|
|
10
|
+
## Nguyên tắc: Chống hao pin & lag vô ích
|
|
11
|
+
|
|
12
|
+
Quản lý vòng đời (lifecycle) kém sẽ làm máy nóng, lag và hao pin nhanh chóng, đặc biệt trên thiết bị Android yếu.
|
|
13
|
+
|
|
14
|
+
### Xử lý Lifecycle Events
|
|
15
|
+
|
|
16
|
+
1. **Xoay màn hình (Orientation Change):**
|
|
17
|
+
- Việc xoay dọc/ngang không được làm trigger lại các API requests.
|
|
18
|
+
- State phải được giữ nguyên bằng cơ chế State Management chuyên biệt, widget chỉ rebuild UI Layout.
|
|
19
|
+
|
|
20
|
+
2. **App chuyển vào nền (Backgrounded):**
|
|
21
|
+
- Lập tức ngắt (Pause/Cancel) các Streams liên tục (như vị trí GPS, socket).
|
|
22
|
+
- Tạm dừng các `Timer` đếm ngược.
|
|
23
|
+
|
|
24
|
+
3. **Memory Warning (Cảnh báo RAM):**
|
|
25
|
+
- Clear cache hình ảnh trong bộ nhớ (ví dụ: xoá cache network images).
|
|
26
|
+
- Giải phóng tài nguyên memory lớn không dùng tới.
|
|
27
|
+
|
|
28
|
+
### Rò rỉ bộ nhớ (Memory Leaks)
|
|
29
|
+
- Luôn gọi `dispose()` trên các Controller (AnimationController, ScrollController, TextEditingController).
|
|
30
|
+
- Đảm bảo huỷ (cancel) StreamSubscription khi Widget bị huỷ.
|
package/dist/utils/template.js
CHANGED
|
@@ -172,11 +172,15 @@ async function generateRulesFile(targetDir, config) {
|
|
|
172
172
|
}
|
|
173
173
|
existing += '\n\n';
|
|
174
174
|
}
|
|
175
|
+
// Helper to strip YAML frontmatter for appended files
|
|
176
|
+
const stripFrontmatter = (content) => {
|
|
177
|
+
return content.replace(/^---\n[\s\S]*?\n---\n+/, '');
|
|
178
|
+
};
|
|
175
179
|
// Concatenate all rule files
|
|
176
180
|
const allRules = ['# Flutter Pro Max — Agent Rules\n'];
|
|
177
181
|
for (const file of ruleFiles) {
|
|
178
182
|
const content = await readFile(join(rulesDir, file), 'utf-8');
|
|
179
|
-
allRules.push(content);
|
|
183
|
+
allRules.push(stripFrontmatter(content));
|
|
180
184
|
}
|
|
181
185
|
await writeFile(rulesFilePath, existing + allRules.join('\n---\n\n'), 'utf-8');
|
|
182
186
|
}
|
|
@@ -184,9 +188,12 @@ async function generateRulesFile(targetDir, config) {
|
|
|
184
188
|
// Create mode: generate separate files in rules directory
|
|
185
189
|
const rulesTargetDir = dirname(join(targetDir, config.rulesFile.path));
|
|
186
190
|
await mkdir(rulesTargetDir, { recursive: true });
|
|
191
|
+
// If rulesFile.path ends with .mdc, we use .mdc extension for files
|
|
192
|
+
const useMdc = config.rulesFile.path.endsWith('.mdc');
|
|
187
193
|
for (const file of ruleFiles) {
|
|
188
194
|
const content = await readFile(join(rulesDir, file), 'utf-8');
|
|
189
|
-
const
|
|
195
|
+
const targetExt = useMdc ? '.mdc' : '.md';
|
|
196
|
+
const targetPath = join(rulesTargetDir, file.replace(/\.md$/, targetExt));
|
|
190
197
|
await writeFile(targetPath, content, 'utf-8');
|
|
191
198
|
}
|
|
192
199
|
}
|