@appiq/flutter-workflow 1.1.0 โ 1.3.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.
- package/CHANGELOG.md +106 -0
- package/agents/claude/cubit-agent.md +63 -0
- package/agents/claude/data-agent.md +93 -0
- package/agents/claude/domain-agent.md +76 -0
- package/agents/claude/initial-flow-agent.md +55 -0
- package/agents/claude/orchestrator.md +41 -0
- package/agents/claude/po-agent.md +42 -0
- package/agents/claude/security-agent.md +91 -0
- package/agents/claude/test-agent.md +114 -0
- package/agents/claude/ui-agent.md +56 -0
- package/agents/data-agent.md +20 -13
- package/agents/initial-flow-agent.md +342 -0
- package/bin/cli.js +61 -3
- package/package.json +2 -2
- package/templates/additional_cubit_req.md +357 -0
- package/templates/additional_data_req.md +480 -0
- package/templates/additional_domain_req.md +431 -0
- package/templates/additional_ui_req.md +205 -0
package/bin/cli.js
CHANGED
@@ -54,7 +54,8 @@ const AGENTS = [
|
|
54
54
|
'domain-agent',
|
55
55
|
'data-agent',
|
56
56
|
'security-agent',
|
57
|
-
'test-agent'
|
57
|
+
'test-agent',
|
58
|
+
'initial-flow-agent'
|
58
59
|
];
|
59
60
|
|
60
61
|
program
|
@@ -122,8 +123,13 @@ program
|
|
122
123
|
// Create target directory
|
123
124
|
await fs.ensureDir(targetDir);
|
124
125
|
|
125
|
-
// Copy agents
|
126
|
-
|
126
|
+
// Copy agents - use different source for Claude Desktop
|
127
|
+
let sourceDir;
|
128
|
+
if (ide === 'Claude Desktop') {
|
129
|
+
sourceDir = path.join(__dirname, '../agents/claude');
|
130
|
+
} else {
|
131
|
+
sourceDir = path.join(__dirname, '../agents');
|
132
|
+
}
|
127
133
|
|
128
134
|
for (const agent of AGENTS) {
|
129
135
|
const sourceFile = path.join(sourceDir, `${agent}.md`);
|
@@ -139,6 +145,27 @@ program
|
|
139
145
|
const featuresDir = path.join(docsDir, 'features');
|
140
146
|
await fs.ensureDir(featuresDir);
|
141
147
|
|
148
|
+
// Copy additional requirement templates
|
149
|
+
const templatesDir = path.join(__dirname, '../templates');
|
150
|
+
const targetTemplatesDir = path.join(currentDir, 'docs', 'additional_requirements');
|
151
|
+
await fs.ensureDir(targetTemplatesDir);
|
152
|
+
|
153
|
+
const additionalTemplates = [
|
154
|
+
'additional_ui_req.md',
|
155
|
+
'additional_cubit_req.md',
|
156
|
+
'additional_domain_req.md',
|
157
|
+
'additional_data_req.md'
|
158
|
+
];
|
159
|
+
|
160
|
+
for (const template of additionalTemplates) {
|
161
|
+
const sourceTemplate = path.join(templatesDir, template);
|
162
|
+
const targetTemplate = path.join(targetTemplatesDir, template);
|
163
|
+
|
164
|
+
if (await fs.pathExists(sourceTemplate)) {
|
165
|
+
await fs.copy(sourceTemplate, targetTemplate);
|
166
|
+
}
|
167
|
+
}
|
168
|
+
|
142
169
|
// Create sample feature documentation
|
143
170
|
const sampleFeatureContent = `---
|
144
171
|
name: SampleFeature
|
@@ -147,6 +174,7 @@ domain: open
|
|
147
174
|
data: open
|
148
175
|
security: open
|
149
176
|
test: open
|
177
|
+
initial_flow: open
|
150
178
|
status: open
|
151
179
|
---
|
152
180
|
|
@@ -163,6 +191,20 @@ Describe your feature here. This will be analyzed by the PO Agent to create deta
|
|
163
191
|
- Any technical considerations
|
164
192
|
- Dependencies
|
165
193
|
- Performance requirements
|
194
|
+
|
195
|
+
## Additional Requirements
|
196
|
+
After basic implementation, you can use additional requirement templates:
|
197
|
+
- docs/additional_requirements/additional_ui_req.md - Role-based UI and access control
|
198
|
+
- docs/additional_requirements/additional_cubit_req.md - Advanced state management and provider setup
|
199
|
+
- docs/additional_requirements/additional_domain_req.md - Complex business rules and domain logic
|
200
|
+
- docs/additional_requirements/additional_data_req.md - Supabase MCP integration and advanced data patterns
|
201
|
+
|
202
|
+
## Integration Setup
|
203
|
+
Use the Initial Flow Agent for:
|
204
|
+
- Dependency injection configuration
|
205
|
+
- Provider setup and initialization
|
206
|
+
- Integration testing and validation
|
207
|
+
- Error prevention and troubleshooting
|
166
208
|
`;
|
167
209
|
|
168
210
|
await fs.writeFile(
|
@@ -184,6 +226,7 @@ Describe your feature here. This will be analyzed by the PO Agent to create deta
|
|
184
226
|
|
185
227
|
console.log(chalk.gray('\\n๐ Created directories:'));
|
186
228
|
console.log(chalk.gray(' ๐ docs/features/ - Feature documentation and status tracking'));
|
229
|
+
console.log(chalk.gray(' ๐ docs/additional_requirements/ - Advanced requirement templates'));
|
187
230
|
|
188
231
|
console.log(chalk.bold.yellow('\\n๐ Next Steps:'));
|
189
232
|
console.log(chalk.gray('1. Create your feature documentation in docs/features/'));
|
@@ -199,6 +242,7 @@ Describe your feature here. This will be analyzed by the PO Agent to create deta
|
|
199
242
|
console.log(chalk.gray(' ๐๏ธ Data Agent - Backend integration specialist'));
|
200
243
|
console.log(chalk.gray(' ๐ Security Agent - Security and compliance expert'));
|
201
244
|
console.log(chalk.gray(' ๐งช Test Agent - Testing pyramid implementation'));
|
245
|
+
console.log(chalk.gray(' ๐ Initial Flow Agent - Provider setup and integration specialist'));
|
202
246
|
|
203
247
|
} catch (error) {
|
204
248
|
console.error(chalk.red('โ Installation failed:'), error.message);
|
@@ -287,6 +331,7 @@ domain: open
|
|
287
331
|
data: open
|
288
332
|
security: open
|
289
333
|
test: open
|
334
|
+
initial_flow: open
|
290
335
|
status: open
|
291
336
|
---
|
292
337
|
|
@@ -317,6 +362,19 @@ As a [user type], I want [functionality] so that [benefit].
|
|
317
362
|
- UI/UX requirements
|
318
363
|
- Screen designs
|
319
364
|
- User flow
|
365
|
+
|
366
|
+
## Additional Requirements (Optional)
|
367
|
+
Use these templates after basic implementation for advanced features:
|
368
|
+
- docs/additional_requirements/additional_ui_req.md - Role-based access control
|
369
|
+
- docs/additional_requirements/additional_cubit_req.md - Advanced state management
|
370
|
+
- docs/additional_requirements/additional_domain_req.md - Complex business logic
|
371
|
+
- docs/additional_requirements/additional_data_req.md - Supabase MCP integration
|
372
|
+
|
373
|
+
## Integration Setup
|
374
|
+
After implementation, use Initial Flow Agent for:
|
375
|
+
- Complete dependency injection setup
|
376
|
+
- Provider hierarchy configuration
|
377
|
+
- Integration testing and validation
|
320
378
|
`;
|
321
379
|
|
322
380
|
const fileName = name.toLowerCase().replace(/[^a-z0-9]/gi, '-');
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "@appiq/flutter-workflow",
|
3
|
-
"version": "1.
|
4
|
-
"description": "๐ Professional Flutter development with AI-powered agents following Clean Architecture principles - Automated agent-based feature development system by AppIQ Solutions",
|
3
|
+
"version": "1.3.0",
|
4
|
+
"description": "๐ [BETA] Professional Flutter development with AI-powered agents following Clean Architecture principles - Automated agent-based feature development system by AppIQ Solutions",
|
5
5
|
"main": "bin/cli.js",
|
6
6
|
"bin": {
|
7
7
|
"appiq-workflow": "bin/cli.js"
|
@@ -0,0 +1,357 @@
|
|
1
|
+
# Additional Cubit Requirements - State Management Integration
|
2
|
+
|
3
|
+
This template defines additional state management requirements, provider setup, and integration patterns for your feature.
|
4
|
+
|
5
|
+
## State Management Architecture
|
6
|
+
|
7
|
+
### Cubit Integration Pattern
|
8
|
+
```dart
|
9
|
+
// Feature-specific state management structure
|
10
|
+
lib/features/{feature}/presentation/cubit/
|
11
|
+
โโโ {feature}_cubit.dart // Main cubit implementation
|
12
|
+
โโโ {feature}_state.dart // State definitions
|
13
|
+
โโโ {feature}_event.dart // Events (if using BLoC pattern)
|
14
|
+
```
|
15
|
+
|
16
|
+
### Global State Dependencies
|
17
|
+
- [ ] Authentication state integration
|
18
|
+
- [ ] User role state management
|
19
|
+
- [ ] Theme/settings state access
|
20
|
+
- [ ] Navigation state coordination
|
21
|
+
- [ ] Network connectivity state
|
22
|
+
- [ ] Offline/online state management
|
23
|
+
|
24
|
+
## Provider Setup Requirements
|
25
|
+
|
26
|
+
### Main App Provider Configuration
|
27
|
+
```dart
|
28
|
+
// Add to main.dart MultiBlocProvider
|
29
|
+
MultiBlocProvider(
|
30
|
+
providers: [
|
31
|
+
// Existing providers...
|
32
|
+
BlocProvider<{Feature}Cubit>(
|
33
|
+
create: (context) => GetIt.instance<{Feature}Cubit>(),
|
34
|
+
),
|
35
|
+
// Additional feature dependencies...
|
36
|
+
],
|
37
|
+
child: MyApp(),
|
38
|
+
)
|
39
|
+
```
|
40
|
+
|
41
|
+
### Dependency Injection Setup
|
42
|
+
```dart
|
43
|
+
// Add to dependency injection configuration
|
44
|
+
void configureDependencies() {
|
45
|
+
// Repository registration
|
46
|
+
getIt.registerLazySingleton<{Feature}Repository>(
|
47
|
+
() => {Feature}RepositoryImpl(
|
48
|
+
remoteDataSource: getIt(),
|
49
|
+
localDataSource: getIt(),
|
50
|
+
networkInfo: getIt(),
|
51
|
+
),
|
52
|
+
);
|
53
|
+
|
54
|
+
// Use case registration
|
55
|
+
getIt.registerLazySingleton(() => Get{Feature}UseCase(getIt()));
|
56
|
+
getIt.registerLazySingleton(() => Create{Feature}UseCase(getIt()));
|
57
|
+
getIt.registerLazySingleton(() => Update{Feature}UseCase(getIt()));
|
58
|
+
getIt.registerLazySingleton(() => Delete{Feature}UseCase(getIt()));
|
59
|
+
|
60
|
+
// Cubit registration
|
61
|
+
getIt.registerFactory<{Feature}Cubit>(
|
62
|
+
() => {Feature}Cubit(
|
63
|
+
get{Feature}UseCase: getIt(),
|
64
|
+
create{Feature}UseCase: getIt(),
|
65
|
+
update{Feature}UseCase: getIt(),
|
66
|
+
delete{Feature}UseCase: getIt(),
|
67
|
+
),
|
68
|
+
);
|
69
|
+
}
|
70
|
+
```
|
71
|
+
|
72
|
+
## State Initialization Requirements
|
73
|
+
|
74
|
+
### Initial State Setup
|
75
|
+
```dart
|
76
|
+
class {Feature}Cubit extends Cubit<{Feature}State> {
|
77
|
+
{Feature}Cubit({
|
78
|
+
required this.get{Feature}UseCase,
|
79
|
+
required this.create{Feature}UseCase,
|
80
|
+
required this.update{Feature}UseCase,
|
81
|
+
required this.delete{Feature}UseCase,
|
82
|
+
}) : super(const {Feature}State.initial());
|
83
|
+
|
84
|
+
// Initialize feature data on cubit creation
|
85
|
+
Future<void> initialize() async {
|
86
|
+
emit(state.copyWith(status: {Feature}Status.loading));
|
87
|
+
|
88
|
+
try {
|
89
|
+
final result = await get{Feature}UseCase.call(NoParams());
|
90
|
+
result.fold(
|
91
|
+
(failure) => emit(state.copyWith(
|
92
|
+
status: {Feature}Status.error,
|
93
|
+
errorMessage: failure.message,
|
94
|
+
)),
|
95
|
+
(data) => emit(state.copyWith(
|
96
|
+
status: {Feature}Status.loaded,
|
97
|
+
items: data,
|
98
|
+
)),
|
99
|
+
);
|
100
|
+
} catch (e) {
|
101
|
+
emit(state.copyWith(
|
102
|
+
status: {Feature}Status.error,
|
103
|
+
errorMessage: 'Unexpected error occurred',
|
104
|
+
));
|
105
|
+
}
|
106
|
+
}
|
107
|
+
}
|
108
|
+
```
|
109
|
+
|
110
|
+
### Widget Integration Pattern
|
111
|
+
```dart
|
112
|
+
class {Feature}Page extends StatefulWidget {
|
113
|
+
@override
|
114
|
+
_State createState() => _State();
|
115
|
+
}
|
116
|
+
|
117
|
+
class _State extends State<{Feature}Page> {
|
118
|
+
late {Feature}Cubit cubit;
|
119
|
+
|
120
|
+
@override
|
121
|
+
void initState() {
|
122
|
+
super.initState();
|
123
|
+
cubit = context.read<{Feature}Cubit>();
|
124
|
+
// Initialize cubit data
|
125
|
+
cubit.initialize();
|
126
|
+
}
|
127
|
+
|
128
|
+
@override
|
129
|
+
Widget build(BuildContext context) {
|
130
|
+
return BlocConsumer<{Feature}Cubit, {Feature}State>(
|
131
|
+
listener: (context, state) {
|
132
|
+
// Handle side effects (navigation, snackbars, etc.)
|
133
|
+
if (state.status == {Feature}Status.error) {
|
134
|
+
ScaffoldMessenger.of(context).showSnackBar(
|
135
|
+
SnackBar(content: Text(state.errorMessage ?? 'Error occurred')),
|
136
|
+
);
|
137
|
+
}
|
138
|
+
},
|
139
|
+
builder: (context, state) {
|
140
|
+
return Scaffold(
|
141
|
+
body: _buildBody(state),
|
142
|
+
);
|
143
|
+
},
|
144
|
+
);
|
145
|
+
}
|
146
|
+
}
|
147
|
+
```
|
148
|
+
|
149
|
+
## Common Integration Issues & Solutions
|
150
|
+
|
151
|
+
### Issue 1: Cubit Not Initialized
|
152
|
+
**Problem**: `BlocProvider.of() called with a context that does not contain a Cubit`
|
153
|
+
**Solution**:
|
154
|
+
```dart
|
155
|
+
// Ensure proper provider hierarchy
|
156
|
+
MaterialApp(
|
157
|
+
home: MultiBlocProvider(
|
158
|
+
providers: [
|
159
|
+
BlocProvider<{Feature}Cubit>(
|
160
|
+
create: (context) => GetIt.instance<{Feature}Cubit>(),
|
161
|
+
),
|
162
|
+
],
|
163
|
+
child: {Feature}Page(),
|
164
|
+
),
|
165
|
+
)
|
166
|
+
```
|
167
|
+
|
168
|
+
### Issue 2: Duplicate Cubit Registration
|
169
|
+
**Problem**: Multiple registrations of the same cubit type
|
170
|
+
**Solution**:
|
171
|
+
```dart
|
172
|
+
// Use registerFactory for cubits (new instance per request)
|
173
|
+
getIt.registerFactory<{Feature}Cubit>(() => {Feature}Cubit(...));
|
174
|
+
|
175
|
+
// Or check if already registered
|
176
|
+
if (!getIt.isRegistered<{Feature}Cubit>()) {
|
177
|
+
getIt.registerFactory<{Feature}Cubit>(() => {Feature}Cubit(...));
|
178
|
+
}
|
179
|
+
```
|
180
|
+
|
181
|
+
### Issue 3: State Not Persisting Across Navigation
|
182
|
+
**Problem**: State resets when navigating between screens
|
183
|
+
**Solution**:
|
184
|
+
```dart
|
185
|
+
// Use singleton registration for state that should persist
|
186
|
+
getIt.registerLazySingleton<{Feature}Cubit>(() => {Feature}Cubit(...));
|
187
|
+
|
188
|
+
// Or use global provider at app level
|
189
|
+
class MyApp extends StatelessWidget {
|
190
|
+
@override
|
191
|
+
Widget build(BuildContext context) {
|
192
|
+
return MultiBlocProvider(
|
193
|
+
providers: [
|
194
|
+
BlocProvider<{Feature}Cubit>(
|
195
|
+
create: (context) => GetIt.instance<{Feature}Cubit>(),
|
196
|
+
),
|
197
|
+
],
|
198
|
+
child: MaterialApp(...),
|
199
|
+
);
|
200
|
+
}
|
201
|
+
}
|
202
|
+
```
|
203
|
+
|
204
|
+
## Cross-Feature State Communication
|
205
|
+
|
206
|
+
### Feature-to-Feature State Updates
|
207
|
+
```dart
|
208
|
+
class {Feature}Cubit extends Cubit<{Feature}State> {
|
209
|
+
final AuthenticationCubit authCubit;
|
210
|
+
final UserRoleCubit userRoleCubit;
|
211
|
+
late StreamSubscription authSubscription;
|
212
|
+
|
213
|
+
{Feature}Cubit({
|
214
|
+
required this.authCubit,
|
215
|
+
required this.userRoleCubit,
|
216
|
+
// ... other dependencies
|
217
|
+
}) : super(const {Feature}State.initial()) {
|
218
|
+
// Listen to authentication changes
|
219
|
+
authSubscription = authCubit.stream.listen((authState) {
|
220
|
+
if (authState is! AuthenticatedState) {
|
221
|
+
// Clear feature data on logout
|
222
|
+
emit(const {Feature}State.initial());
|
223
|
+
}
|
224
|
+
});
|
225
|
+
}
|
226
|
+
|
227
|
+
@override
|
228
|
+
Future<void> close() {
|
229
|
+
authSubscription.cancel();
|
230
|
+
return super.close();
|
231
|
+
}
|
232
|
+
}
|
233
|
+
```
|
234
|
+
|
235
|
+
### Global State Access Pattern
|
236
|
+
```dart
|
237
|
+
// Access other cubits from within a cubit
|
238
|
+
void updateBasedOnUserRole() {
|
239
|
+
final userRole = userRoleCubit.state.role;
|
240
|
+
|
241
|
+
switch (userRole) {
|
242
|
+
case UserRole.admin:
|
243
|
+
loadAdminData();
|
244
|
+
break;
|
245
|
+
case UserRole.manager:
|
246
|
+
loadManagerData();
|
247
|
+
break;
|
248
|
+
case UserRole.user:
|
249
|
+
loadUserData();
|
250
|
+
break;
|
251
|
+
}
|
252
|
+
}
|
253
|
+
```
|
254
|
+
|
255
|
+
## Performance Optimization
|
256
|
+
|
257
|
+
### Selective State Updates
|
258
|
+
```dart
|
259
|
+
// Use copyWith efficiently to avoid unnecessary rebuilds
|
260
|
+
emit(state.copyWith(
|
261
|
+
status: {Feature}Status.loading,
|
262
|
+
// Only update changed fields
|
263
|
+
));
|
264
|
+
|
265
|
+
// Use state comparison to prevent duplicate emissions
|
266
|
+
void updateItems(List<{Entity}> newItems) {
|
267
|
+
if (!listEquals(state.items, newItems)) {
|
268
|
+
emit(state.copyWith(items: newItems));
|
269
|
+
}
|
270
|
+
}
|
271
|
+
```
|
272
|
+
|
273
|
+
### Memory Management
|
274
|
+
```dart
|
275
|
+
class {Feature}Cubit extends Cubit<{Feature}State> {
|
276
|
+
final List<StreamSubscription> _subscriptions = [];
|
277
|
+
|
278
|
+
void addSubscription(StreamSubscription subscription) {
|
279
|
+
_subscriptions.add(subscription);
|
280
|
+
}
|
281
|
+
|
282
|
+
@override
|
283
|
+
Future<void> close() {
|
284
|
+
// Cancel all subscriptions
|
285
|
+
for (final subscription in _subscriptions) {
|
286
|
+
subscription.cancel();
|
287
|
+
}
|
288
|
+
_subscriptions.clear();
|
289
|
+
return super.close();
|
290
|
+
}
|
291
|
+
}
|
292
|
+
```
|
293
|
+
|
294
|
+
## Testing Integration
|
295
|
+
|
296
|
+
### Cubit Testing Setup
|
297
|
+
```dart
|
298
|
+
// Test setup with proper mocking
|
299
|
+
class MockAuthCubit extends MockCubit<AuthState> implements AuthCubit {}
|
300
|
+
class MockUserRoleCubit extends MockCubit<UserRoleState> implements UserRoleCubit {}
|
301
|
+
|
302
|
+
void main() {
|
303
|
+
late {Feature}Cubit cubit;
|
304
|
+
late MockAuthCubit mockAuthCubit;
|
305
|
+
late MockUserRoleCubit mockUserRoleCubit;
|
306
|
+
|
307
|
+
setUp(() {
|
308
|
+
mockAuthCubit = MockAuthCubit();
|
309
|
+
mockUserRoleCubit = MockUserRoleCubit();
|
310
|
+
|
311
|
+
cubit = {Feature}Cubit(
|
312
|
+
authCubit: mockAuthCubit,
|
313
|
+
userRoleCubit: mockUserRoleCubit,
|
314
|
+
// ... other dependencies
|
315
|
+
);
|
316
|
+
});
|
317
|
+
|
318
|
+
tearDown(() {
|
319
|
+
cubit.close();
|
320
|
+
});
|
321
|
+
}
|
322
|
+
```
|
323
|
+
|
324
|
+
## Integration Checklist
|
325
|
+
|
326
|
+
### Provider Setup
|
327
|
+
- [ ] Cubit registered in dependency injection
|
328
|
+
- [ ] Provider added to MultiBlocProvider
|
329
|
+
- [ ] Dependencies properly injected
|
330
|
+
- [ ] Initialization logic implemented
|
331
|
+
|
332
|
+
### State Management
|
333
|
+
- [ ] Initial state properly defined
|
334
|
+
- [ ] State transitions implemented
|
335
|
+
- [ ] Error handling added
|
336
|
+
- [ ] Loading states managed
|
337
|
+
|
338
|
+
### Cross-Feature Integration
|
339
|
+
- [ ] Authentication state integration
|
340
|
+
- [ ] User role state access
|
341
|
+
- [ ] Global state dependencies resolved
|
342
|
+
- [ ] Navigation state coordination
|
343
|
+
|
344
|
+
### Performance & Memory
|
345
|
+
- [ ] Efficient state updates implemented
|
346
|
+
- [ ] Memory leaks prevented (subscriptions canceled)
|
347
|
+
- [ ] Unnecessary rebuilds minimized
|
348
|
+
- [ ] State persistence strategy defined
|
349
|
+
|
350
|
+
### Testing
|
351
|
+
- [ ] Unit tests for cubit logic
|
352
|
+
- [ ] Integration tests with providers
|
353
|
+
- [ ] Mock implementations for dependencies
|
354
|
+
- [ ] Error scenario testing
|
355
|
+
|
356
|
+
## Notes
|
357
|
+
Add any feature-specific state management requirements, custom integration patterns, or special initialization needs.
|