injectCleanArchitecture function
Implementation
Future<void> injectCleanArchitecture(String projectName,String state,) async {
final libPath = Directory(p.join(projectName, 'lib'));
if (libPath.existsSync()) {
libPath.deleteSync(recursive: true);
}
// ✅ DELETE DEFAULT FLUTTER TEST FILE (ADD HERE)
final defaultTestFile =
File(p.join(projectName, 'test', 'widget_test.dart'));
if (defaultTestFile.existsSync()) {
defaultTestFile.deleteSync();
}
final folders = [
'core/config',
'core/network',
'core/services',
'core/constants',
'core/utils',
'data/models',
'data/repositories',
'data/sources',
'domain/entities',
'domain/usecases',
'presentation/pages',
'presentation/widgets',
'routes',
'app', // ✅ New app layer
];
for (var folder in folders) {
Directory(p.join(projectName, 'lib', folder))
.createSync(recursive: true);
}
await installStateManagement(projectName, state);
// ==============================
// app/bootstrap.dart
// ==============================
final bootstrapContent = state == 'riverpod'
? '''
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'app.dart';
Future<void> bootstrap({required String flavor}) async {
WidgetsFlutterBinding.ensureInitialized();
runApp(
ProviderScope(
child: MyApp(flavor: flavor),
),
);
}
'''
: '''
import 'package:flutter/material.dart';
import 'app.dart';
Future<void> bootstrap({required String flavor}) async {
WidgetsFlutterBinding.ensureInitialized();
runApp(MyApp(flavor: flavor));
}
''';
File(p.join(projectName, 'lib', 'app', 'bootstrap.dart'))
.writeAsStringSync(bootstrapContent);
// ==============================
// app/app.dart
// ==============================
File(p.join(projectName, 'lib', 'app', 'app.dart'))
.writeAsStringSync('''
import 'package:flutter/material.dart';
class MyApp extends StatelessWidget {
final String flavor;
const MyApp({super.key, required this.flavor});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: Text(
flavor.toUpperCase(),
style: const TextStyle(fontSize: 24),
),
),
),
);
}
}
''');
Directory(p.join(projectName, 'test')).createSync(recursive: true);
File(p.join(projectName, 'test', 'app_test.dart'))
.writeAsStringSync('''
import 'package:flutter_test/flutter_test.dart';
import 'package:$projectName/app/app.dart';
void main() {
testWidgets('App renders flavor', (tester) async {
await tester.pumpWidget(
const MyApp(flavor: 'dev'),
);
expect(find.text('DEV'), findsOneWidget);
});
}
''');
// ==============================
// main_dev.dart
// ==============================
File(p.join(projectName, 'lib', 'main_dev.dart'))
.writeAsStringSync('''
import 'app/bootstrap.dart';
void main() {
bootstrap(flavor: 'dev');
}
''');
// ==============================
// main_prod.dart
// ==============================
File(p.join(projectName, 'lib', 'main_prod.dart'))
.writeAsStringSync('''
import 'app/bootstrap.dart';
void main() {
bootstrap(flavor: 'prod');
}
''');
print('✅ Clean architecture injected (enterprise pattern).');
}