flutter-pro-max-cli 1.0.1 → 2.0.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 (89) hide show
  1. package/README.md +97 -16
  2. package/assets/data/flutter-performance.csv +36 -0
  3. package/assets/data/mobile-accessibility.csv +36 -0
  4. package/assets/{.shared/data → data}/patterns.csv +2 -1
  5. package/assets/data/ui-reasoning.csv +36 -0
  6. package/assets/{.claude/skills/flutter-pro-max/scripts → scripts}/core.py +20 -3
  7. package/assets/{.codex/skills/flutter-pro-max/scripts → scripts}/search.py +1 -1
  8. package/assets/templates/base/quick-reference.md +41 -0
  9. package/assets/templates/base/skill-content.md +179 -0
  10. package/assets/templates/platforms/agent.json +21 -0
  11. package/assets/templates/platforms/claude.json +21 -0
  12. package/assets/templates/platforms/codebuddy.json +18 -0
  13. package/assets/templates/platforms/codex.json +21 -0
  14. package/assets/templates/platforms/continue.json +21 -0
  15. package/assets/templates/platforms/copilot.json +18 -0
  16. package/assets/templates/platforms/cursor.json +18 -0
  17. package/assets/templates/platforms/gemini.json +21 -0
  18. package/assets/templates/platforms/kiro.json +18 -0
  19. package/assets/templates/platforms/opencode.json +21 -0
  20. package/assets/templates/platforms/qoder.json +18 -0
  21. package/assets/templates/platforms/roocode.json +18 -0
  22. package/assets/templates/platforms/trae.json +21 -0
  23. package/assets/templates/platforms/windsurf.json +18 -0
  24. package/dist/commands/init.js +13 -13
  25. package/dist/commands/update.d.ts +6 -0
  26. package/dist/commands/update.js +27 -0
  27. package/dist/commands/versions.d.ts +1 -0
  28. package/dist/commands/versions.js +36 -0
  29. package/dist/index.js +27 -1
  30. package/dist/types/index.d.ts +20 -1
  31. package/dist/types/index.js +4 -1
  32. package/dist/utils/detect.js +11 -1
  33. package/dist/utils/extract.d.ts +5 -0
  34. package/dist/utils/github.d.ts +11 -0
  35. package/dist/utils/github.js +81 -0
  36. package/dist/utils/template.d.ts +25 -0
  37. package/dist/utils/template.js +194 -0
  38. package/package.json +8 -4
  39. package/assets/.agent/workflows/flutter-pro-max.md +0 -165
  40. package/assets/.agent/workflows/scripts/core.py +0 -345
  41. package/assets/.agent/workflows/scripts/search.py +0 -106
  42. package/assets/.claude/skills/flutter-pro-max/SKILL.md +0 -165
  43. package/assets/.claude/skills/flutter-pro-max/scripts/search.py +0 -106
  44. package/assets/.codebuddy/commands/flutter-pro-max.md +0 -165
  45. package/assets/.codebuddy/commands/scripts/core.py +0 -345
  46. package/assets/.codebuddy/commands/scripts/search.py +0 -106
  47. package/assets/.codex/skills/flutter-pro-max/SKILL.md +0 -165
  48. package/assets/.codex/skills/flutter-pro-max/scripts/core.py +0 -345
  49. package/assets/.cursor/commands/flutter-pro-max.md +0 -165
  50. package/assets/.cursor/commands/scripts/core.py +0 -345
  51. package/assets/.cursor/commands/scripts/search.py +0 -106
  52. package/assets/.gemini/skills/flutter-pro-max/SKILL.md +0 -165
  53. package/assets/.gemini/skills/flutter-pro-max/scripts/core.py +0 -345
  54. package/assets/.gemini/skills/flutter-pro-max/scripts/search.py +0 -106
  55. package/assets/.github/prompts/flutter-pro-max.prompt.md +0 -165
  56. package/assets/.github/prompts/scripts/core.py +0 -345
  57. package/assets/.github/prompts/scripts/search.py +0 -106
  58. package/assets/.kiro/steering/flutter-pro-max.md +0 -164
  59. package/assets/.kiro/steering/scripts/core.py +0 -345
  60. package/assets/.kiro/steering/scripts/search.py +0 -106
  61. package/assets/.qoder/rules/flutter-pro-max.md +0 -164
  62. package/assets/.qoder/rules/scripts/core.py +0 -345
  63. package/assets/.qoder/rules/scripts/search.py +0 -106
  64. package/assets/.roo/commands/flutter-pro-max.md +0 -164
  65. package/assets/.roo/commands/scripts/core.py +0 -345
  66. package/assets/.roo/commands/scripts/search.py +0 -106
  67. package/assets/.shared/flutter-pro-max/SKILL.md +0 -165
  68. package/assets/.shared/flutter-pro-max/scripts/core.py +0 -341
  69. package/assets/.shared/flutter-pro-max/scripts/search.py +0 -106
  70. package/assets/.trae/skills/flutter-pro-max/SKILL.md +0 -165
  71. package/assets/.trae/skills/flutter-pro-max/scripts/core.py +0 -345
  72. package/assets/.trae/skills/flutter-pro-max/scripts/search.py +0 -106
  73. package/assets/.windsurf/workflows/flutter-pro-max.md +0 -165
  74. package/assets/.windsurf/workflows/scripts/core.py +0 -345
  75. package/assets/.windsurf/workflows/scripts/search.py +0 -106
  76. package/dist/utils/extract.js +0 -83
  77. /package/assets/{.shared/data → data}/architect.csv +0 -0
  78. /package/assets/{.shared/data → data}/charts.csv +0 -0
  79. /package/assets/{.shared/data → data}/colors.csv +0 -0
  80. /package/assets/{.shared/data → data}/icons.csv +0 -0
  81. /package/assets/{.shared/data → data}/landing.csv +0 -0
  82. /package/assets/{.shared/data → data}/name_convention.csv +0 -0
  83. /package/assets/{.shared/data → data}/package.csv +0 -0
  84. /package/assets/{.shared/data → data}/products.csv +0 -0
  85. /package/assets/{.shared/data → data}/prompts.csv +0 -0
  86. /package/assets/{.shared/data → data}/styles.csv +0 -0
  87. /package/assets/{.shared/data → data}/typography.csv +0 -0
  88. /package/assets/{.shared/data → data}/ux-guidelines.csv +0 -0
  89. /package/assets/{.shared/data → data}/widget.csv +0 -0
@@ -0,0 +1,194 @@
1
+ import { readFile, mkdir, writeFile, cp, access } from 'node:fs/promises';
2
+ import { join, dirname } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ const __dirname = dirname(fileURLToPath(import.meta.url));
5
+ // After build: dist/utils/template.js -> ../../assets = cli/assets ✓
6
+ const ASSETS_DIR = join(__dirname, '..', '..', 'assets');
7
+ // Map AIType to platform config file name
8
+ const AI_TO_PLATFORM = {
9
+ claude: 'claude',
10
+ cursor: 'cursor',
11
+ windsurf: 'windsurf',
12
+ antigravity: 'agent',
13
+ copilot: 'copilot',
14
+ kiro: 'kiro',
15
+ roocode: 'roocode',
16
+ codex: 'codex',
17
+ qoder: 'qoder',
18
+ gemini: 'gemini',
19
+ trae: 'trae',
20
+ codebuddy: 'codebuddy',
21
+ opencode: 'opencode',
22
+ continue: 'continue',
23
+ };
24
+ async function exists(path) {
25
+ try {
26
+ await access(path);
27
+ return true;
28
+ }
29
+ catch {
30
+ return false;
31
+ }
32
+ }
33
+ /**
34
+ * Load platform configuration from JSON file
35
+ */
36
+ export async function loadPlatformConfig(aiType) {
37
+ const platformName = AI_TO_PLATFORM[aiType];
38
+ if (!platformName) {
39
+ throw new Error(`Unknown AI type: ${aiType}`);
40
+ }
41
+ const configPath = join(ASSETS_DIR, 'templates', 'platforms', `${platformName}.json`);
42
+ const content = await readFile(configPath, 'utf-8');
43
+ return JSON.parse(content);
44
+ }
45
+ /**
46
+ * Load all available platform configs
47
+ */
48
+ export async function loadAllPlatformConfigs() {
49
+ const configs = new Map();
50
+ for (const [aiType, platformName] of Object.entries(AI_TO_PLATFORM)) {
51
+ try {
52
+ const config = await loadPlatformConfig(aiType);
53
+ configs.set(aiType, config);
54
+ }
55
+ catch {
56
+ // Skip if config doesn't exist
57
+ }
58
+ }
59
+ return configs;
60
+ }
61
+ /**
62
+ * Load a template file
63
+ */
64
+ async function loadTemplate(templateName) {
65
+ const templatePath = join(ASSETS_DIR, 'templates', templateName);
66
+ return readFile(templatePath, 'utf-8');
67
+ }
68
+ /**
69
+ * Render frontmatter section
70
+ */
71
+ function renderFrontmatter(frontmatter) {
72
+ if (!frontmatter)
73
+ return '';
74
+ const lines = ['---'];
75
+ for (const [key, value] of Object.entries(frontmatter)) {
76
+ // Quote values that contain special characters
77
+ if (value.includes(':') || value.includes('"') || value.includes('\n')) {
78
+ lines.push(`${key}: "${value.replace(/"/g, '\\"')}"`);
79
+ }
80
+ else {
81
+ lines.push(`${key}: ${value}`);
82
+ }
83
+ }
84
+ lines.push('---', '');
85
+ return lines.join('\n');
86
+ }
87
+ /**
88
+ * Render skill file content from template
89
+ */
90
+ export async function renderSkillFile(config) {
91
+ // Load base template
92
+ let content = await loadTemplate('base/skill-content.md');
93
+ // Load quick reference if needed
94
+ let quickReferenceContent = '';
95
+ if (config.sections.quickReference) {
96
+ quickReferenceContent = await loadTemplate('base/quick-reference.md');
97
+ // Replace script path in quick reference
98
+ quickReferenceContent = quickReferenceContent.replace(/\{\{SCRIPT_PATH\}\}/g, config.scriptPath);
99
+ }
100
+ // Build the final content
101
+ const frontmatter = renderFrontmatter(config.frontmatter);
102
+ // Replace placeholders
103
+ const quickRefWithNewline = quickReferenceContent ? '\n' + quickReferenceContent : '';
104
+ content = content
105
+ .replace(/\{\{TITLE\}\}/g, config.title)
106
+ .replace(/\{\{DESCRIPTION\}\}/g, config.description)
107
+ .replace(/\{\{SCRIPT_PATH\}\}/g, config.scriptPath)
108
+ .replace(/\{\{SKILL_OR_WORKFLOW\}\}/g, config.skillOrWorkflow)
109
+ .replace(/\{\{QUICK_REFERENCE\}\}/g, quickRefWithNewline);
110
+ return frontmatter + content;
111
+ }
112
+ /**
113
+ * Copy data and scripts to target directory
114
+ */
115
+ async function copyDataAndScripts(targetSkillDir) {
116
+ const dataSource = join(ASSETS_DIR, 'data');
117
+ const scriptsSource = join(ASSETS_DIR, 'scripts');
118
+ const dataTarget = join(targetSkillDir, 'data');
119
+ const scriptsTarget = join(targetSkillDir, 'scripts');
120
+ // Copy data
121
+ if (await exists(dataSource)) {
122
+ await mkdir(dataTarget, { recursive: true });
123
+ await cp(dataSource, dataTarget, { recursive: true });
124
+ }
125
+ // Copy scripts
126
+ if (await exists(scriptsSource)) {
127
+ await mkdir(scriptsTarget, { recursive: true });
128
+ await cp(scriptsSource, scriptsTarget, { recursive: true });
129
+ }
130
+ }
131
+ /**
132
+ * Ensure .shared folder exists with data and scripts
133
+ */
134
+ async function ensureSharedExists(targetDir) {
135
+ const sharedDir = join(targetDir, '.shared', 'flutter-pro-max');
136
+ // Check if already exists
137
+ if (await exists(sharedDir)) {
138
+ return false; // Already exists, didn't create
139
+ }
140
+ await mkdir(sharedDir, { recursive: true });
141
+ await copyDataAndScripts(sharedDir);
142
+ return true; // Created new
143
+ }
144
+ /**
145
+ * Generate platform files for a specific AI type
146
+ */
147
+ export async function generatePlatformFiles(targetDir, aiType) {
148
+ const config = await loadPlatformConfig(aiType);
149
+ const createdFolders = [];
150
+ // Determine full skill directory path
151
+ const skillDir = join(targetDir, config.folderStructure.root, config.folderStructure.skillPath);
152
+ // Create directory structure
153
+ await mkdir(skillDir, { recursive: true });
154
+ // Render and write skill file
155
+ const skillContent = await renderSkillFile(config);
156
+ const skillFilePath = join(skillDir, config.folderStructure.filename);
157
+ await writeFile(skillFilePath, skillContent, 'utf-8');
158
+ createdFolders.push(config.folderStructure.root);
159
+ // Handle data/scripts based on install type
160
+ if (config.installType === 'full') {
161
+ // Full install: copy data and scripts into the skill directory
162
+ await copyDataAndScripts(skillDir);
163
+ }
164
+ else {
165
+ // Reference install: ensure .shared exists
166
+ const createdShared = await ensureSharedExists(targetDir);
167
+ if (createdShared) {
168
+ createdFolders.push('.shared');
169
+ }
170
+ }
171
+ return createdFolders;
172
+ }
173
+ /**
174
+ * Generate files for all AI types
175
+ */
176
+ export async function generateAllPlatformFiles(targetDir) {
177
+ const allFolders = new Set();
178
+ for (const aiType of Object.keys(AI_TO_PLATFORM)) {
179
+ try {
180
+ const folders = await generatePlatformFiles(targetDir, aiType);
181
+ folders.forEach(f => allFolders.add(f));
182
+ }
183
+ catch {
184
+ // Skip if generation fails for a platform
185
+ }
186
+ }
187
+ return Array.from(allFolders);
188
+ }
189
+ /**
190
+ * Get list of supported AI types
191
+ */
192
+ export function getSupportedAITypes() {
193
+ return Object.keys(AI_TO_PLATFORM);
194
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flutter-pro-max-cli",
3
- "version": "1.0.1",
3
+ "version": "2.0.0",
4
4
  "description": "CLI to install Flutter Pro Max skill for AI coding assistants",
5
5
  "type": "module",
6
6
  "bin": {
@@ -12,9 +12,8 @@
12
12
  "LICENSE"
13
13
  ],
14
14
  "scripts": {
15
- "sync:assets": "bash scripts/sync-assets.sh",
16
- "build": "npm run sync:assets && tsc",
17
- "build:bun": "npm run sync:assets && bun build src/index.ts --outdir dist --target node",
15
+ "build": "tsc",
16
+ "build:bun": "bun build src/index.ts --outdir dist --target node",
18
17
  "dev": "npx ts-node --esm src/index.ts",
19
18
  "prepublishOnly": "npm run build"
20
19
  },
@@ -32,6 +31,11 @@
32
31
  "roocode",
33
32
  "codex",
34
33
  "qoder",
34
+ "gemini",
35
+ "opencode",
36
+ "continue",
37
+ "codebuddy",
38
+ "trae",
35
39
  "ai",
36
40
  "skill"
37
41
  ],
@@ -1,165 +0,0 @@
1
- ---
2
- name: flutter-pro-max
3
- description: Chuyên gia Flutter với kiến thức sâu về Clean Architecture, Performance và Modern Dart 3
4
- ---
5
-
6
- # Flutter Pro Max - Flutter Design Intelligence
7
-
8
- Searchable database của Flutter widgets, packages, design patterns, architecture guidelines, và best practices.
9
-
10
- ## Prerequisites
11
-
12
- Chỉ cần Python (không cần pip install):
13
-
14
- ```bash
15
- python3 --version || python --version
16
- ```
17
-
18
- ---
19
-
20
- ## How to Use This Skill
21
-
22
- Khi user yêu cầu Flutter work (design, build, create, implement, review, fix, improve), follow workflow này:
23
-
24
- ### Step 1: Analyze User Requirements
25
-
26
- Trích xuất thông tin từ request:
27
- - **Architecture**: Clean Architecture, Feature-First, DDD
28
- - **State Management**: Riverpod (default), Bloc, Provider
29
- - **UI Components**: Widgets, Layouts, Animations
30
- - **Package needs**: Networking, Database, Security, etc.
31
-
32
- ### Step 2: Search Relevant Data
33
-
34
- Sử dụng `search.py` để tìm kiếm (auto-detect domain):
35
-
36
- ```bash
37
- python3 .agent/workflows/scripts/search.py "<keyword>" --top 5
38
- ```
39
-
40
- **Với domain cụ thể:**
41
- ```bash
42
- python3 .agent/workflows/scripts/search.py "<keyword>" --domain widget --top 5
43
- python3 .agent/workflows/scripts/search.py "<keyword>" --domain package --top 5
44
- ```
45
-
46
- **Với stack filter (loại bỏ conflicts):**
47
- ```bash
48
- python3 .agent/workflows/scripts/search.py "<keyword>" --stack riverpod --top 5
49
- ```
50
-
51
- **Available domains:** `widget`, `package`, `pattern`, `architect`, `chart`, `color`, `typography`, `style`, `ux`, `icon`, `landing`, `naming`, `product`, `prompt`
52
-
53
- **Available stacks:** `riverpod`, `bloc`, `provider`
54
-
55
- ### Step 3: Apply Technical Standards
56
-
57
- Luôn tuân thủ các tiêu chuẩn:
58
-
59
- #### Dart 3 Modern Syntax
60
- ```dart
61
- // ✅ Records
62
- (String name, int age) getUserInfo() => ('John', 25);
63
-
64
- // ✅ Pattern Matching
65
- String getMessage(UIState state) => switch (state) {
66
- LoadingState() => 'Loading...',
67
- DataState(data: var d) => 'Data: $d',
68
- ErrorState(message: var m) => 'Error: $m',
69
- };
70
- ```
71
-
72
- #### Performance Rules
73
- - Luôn dùng `const` constructor khi có thể
74
- - Ưu tiên `SizedBox` hơn `Container` cho spacing
75
- - Dùng `ListView.builder` thay vì `ListView` + `children`
76
-
77
- #### State Management
78
- - **Default**: Riverpod với `riverpod_generator`
79
- - **Alternative**: Bloc (khi user yêu cầu)
80
-
81
- ---
82
-
83
- ## Search Reference
84
-
85
- ### Available Data
86
-
87
- | Domain | File | Content |
88
- |--------|------|---------|
89
- | Widgets | `widget.csv` | 65+ Flutter widgets với pro-tips |
90
- | Packages | `package.csv` | 100+ packages với best practices |
91
- | Patterns | `patterns.csv` | 100+ design patterns với code snippets |
92
- | Architecture | `architect.csv` | Clean Architecture layer paths |
93
- | Charts | `charts.csv` | Chart type recommendations |
94
- | Colors | `colors.csv` | Color palettes by product type |
95
- | Typography | `typography.csv` | Font pairings |
96
- | Styles | `styles.csv` | UI style guidelines |
97
- | UX Guidelines | `ux-guidelines.csv` | UX best practices |
98
- | Icons | `icons.csv` | Icon recommendations |
99
- | Landing | `landing.csv` | Landing page patterns |
100
- | Naming | `name_convention.csv` | Naming conventions |
101
- | Products | `products.csv` | Product type styling |
102
- | Prompts | `prompts.csv` | AI prompt templates |
103
-
104
- ### Search Examples
105
-
106
- ```bash
107
- # Auto-detect domain
108
- python3 .agent/workflows/scripts/search.py "ListView" --top 5
109
-
110
- # Specific domain
111
- python3 .agent/workflows/scripts/search.py "network http" --domain package --top 5
112
-
113
- # Stack filter
114
- python3 .agent/workflows/scripts/search.py "state" --stack riverpod --top 5
115
-
116
- # JSON output
117
- python3 .agent/workflows/scripts/search.py "login" --json --top 3
118
- ```
119
-
120
- ---
121
-
122
- ## Example Workflow
123
-
124
- **User Request:** "Tạo màn hình đăng nhập với Riverpod"
125
-
126
- 1. **Search widgets:**
127
- ```bash
128
- python3 .agent/workflows/scripts/search.py "form input" --domain widget --top 5
129
- ```
130
-
131
- 2. **Search patterns:**
132
- ```bash
133
- python3 .agent/workflows/scripts/search.py "authentication login" --domain pattern --top 5
134
- ```
135
-
136
- 3. **Search packages:**
137
- ```bash
138
- python3 .agent/workflows/scripts/search.py "validation" --domain package --stack riverpod --top 5
139
- ```
140
-
141
- 4. **Apply results** to generate code với Riverpod state management
142
-
143
- ---
144
-
145
- ## Pre-Delivery Checklist
146
-
147
- ### Code Quality
148
- - [ ] Sử dụng `const` constructors
149
- - [ ] Sound Null Safety (không dùng `!` bừa bãi)
150
- - [ ] Dart 3 syntax (Records, Pattern Matching)
151
-
152
- ### Performance
153
- - [ ] `ListView.builder` cho lists dài
154
- - [ ] `SizedBox` thay vì `Container` cho spacing
155
- - [ ] `const` widgets được đánh dấu
156
-
157
- ### Architecture
158
- - [ ] Tuân thủ Clean Architecture layers
159
- - [ ] Dependency Injection đúng cách
160
- - [ ] Repository pattern cho data access
161
-
162
- ### State Management
163
- - [ ] Riverpod providers được tổ chức hợp lý
164
- - [ ] Không leak state giữa các features
165
- - [ ] Error handling với AsyncValue