@appiq/flutter-workflow 1.2.0 → 1.4.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 +163 -0
- package/README.md +3 -1
- package/agents/claude/cubit-agent.md +91 -4
- package/agents/claude/data-agent.md +129 -15
- package/agents/claude/domain-agent.md +104 -4
- package/agents/claude/initial-flow-agent.md +55 -0
- package/agents/claude/orchestrator.md +17 -3
- package/agents/claude/po-agent.md +17 -3
- package/agents/claude/security-agent.md +109 -4
- package/agents/claude/test-agent.md +17 -3
- package/agents/claude/ui-agent.md +107 -5
- package/agents/cubit-agent.md +1 -1
- package/agents/data-agent.md +21 -14
- package/agents/domain-agent.md +1 -1
- package/agents/initial-flow-agent.md +342 -0
- package/agents/po-agent.md +1 -1
- package/agents/security-agent.md +1 -1
- package/agents/test-agent.md +1 -1
- package/agents/ui-agent.md +1 -1
- package/bin/cli.js +54 -1
- package/package.json +6 -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
@@ -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.
|