run method
Runs this command.
The return value is wrapped in a Future if necessary and returned by
CommandRunner.runCommand.
Implementation
@override
Future<void> run() async {
Logger.header('FLUTTER INIT CLI');
// 1. Resolve Project Name
String? nameArg = argResults?['name'] as String?;
if (nameArg == null && argResults?.rest.isNotEmpty == true) {
nameArg = argResults!.rest.first;
}
final projectName = _getProjectName(nameArg);
// 2. Select UI Theme
final theme = WizardHelper.promptSelect<UITheme>(
message: 'Select UI Theme:',
options: UITheme.values,
labelProvider: (o) => o.label,
);
// 3. Select Primary Color (For customization)
final primaryColor = WizardHelper.promptString(
'Enter Primary Color (HEX)',
defaultValue: '#6200EE',
validator: (input) {
final regex = RegExp(r'^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$');
if (!regex.hasMatch(input)) {
Logger.warning('Invalid HEX format. Use e.g. #6200EE or 3F51B5');
return false;
}
return true;
},
);
// Ensure Hex code is prefixed with #
final formattedColor = primaryColor.startsWith('#') ? primaryColor : '#$primaryColor';
// 4. Select Dark Mode
final darkMode = WizardHelper.promptConfirm('Enable Dark Mode support?', defaultValue: true);
// 5. Custom Font Option
String? customFont;
final configureFont = WizardHelper.promptConfirm('Do you want to configure a custom font family?', defaultValue: false);
if (configureFont) {
customFont = WizardHelper.promptString('Enter Font Family Name (e.g. Outfit, Inter)', defaultValue: 'Outfit');
}
// 6. Icon Pack Option (Defaults to defaultIcons)
const iconPack = IconPack.defaultIcons;
// 7. Select Architecture layout
final architecture = WizardHelper.promptSelect<Architecture>(
message: 'Select Project Architecture Layout:',
options: Architecture.values,
labelProvider: (o) => o.label,
);
// 8. Select State Management
final stateManagement = WizardHelper.promptSelect<StateManagement>(
message: 'Select State Management Solution:',
options: StateManagement.values,
labelProvider: (o) => o.label,
);
// 9. Select Routing System
final routing = WizardHelper.promptSelect<Routing>(
message: 'Select Routing Solution:',
options: Routing.values,
labelProvider: (o) => o.label,
);
// 10. Custom Backend URL
final backendUrl = WizardHelper.promptString(
'Enter Custom API URL (Optional, press Enter to skip)',
defaultValue: 'https://api.example.com',
);
// 11. Multi-select for Packages by Categories
final selectedPackages = <String>[];
// Category: Networking
final selectedNet = WizardHelper.promptMultiSelect<Map<String, String>>(
message: 'Select Networking packages to include:',
options: [
{'id': 'dio', 'label': 'Dio (HTTP Client)'},
{'id': 'http', 'label': 'HTTP (Standard Dart HTTP)'},
{'id': 'cached_network_image', 'label': 'Cached Network Image'},
],
labelProvider: (o) => o['label']!,
);
selectedPackages.addAll(selectedNet.map((o) => o['id']!));
// Category: Storage
final selectedStore = WizardHelper.promptMultiSelect<Map<String, String>>(
message: 'Select Storage packages to include:',
options: [
{'id': 'hive', 'label': 'Hive (NoSQL fast database)'},
{'id': 'shared_preferences', 'label': 'SharedPreferences (Key-Value)'},
{'id': 'flutter_secure_storage', 'label': 'Flutter SecureStorage (Encrypted)'},
],
labelProvider: (o) => o['label']!,
);
selectedPackages.addAll(selectedStore.map((o) => o['id']!));
// Category: Utilities & Media
final selectedUtils = WizardHelper.promptMultiSelect<Map<String, String>>(
message: 'Select Utility & Media packages to include:',
options: [
{'id': 'flutter_svg', 'label': 'Flutter SVG (SVG Renderer)'},
{'id': 'image_picker', 'label': 'Image Picker'},
{'id': 'file_picker', 'label': 'File Picker'},
{'id': 'url_launcher', 'label': 'URL Launcher'},
{'id': 'path_provider', 'label': 'Path Provider'},
{'id': 'share_plus', 'label': 'Share Plus'},
{'id': 'permission_handler', 'label': 'Permission Handler'},
{'id': 'geolocator', 'label': 'Geolocator (Location services)'},
],
labelProvider: (o) => o['label']!,
);
selectedPackages.addAll(selectedUtils.map((o) => o['id']!));
// 12. Create ProjectContext
final projectPath = p.join(Directory.current.path, projectName);
final context = ProjectContext(
projectName: projectName,
projectPath: projectPath,
theme: theme,
primaryColor: formattedColor,
darkMode: darkMode,
customFont: customFont,
iconPack: iconPack,
architecture: architecture,
stateManagement: stateManagement,
routing: routing,
backendUrl: backendUrl.isEmpty ? null : backendUrl,
includeSplashOnboarding: true,
packages: selectedPackages,
);
// 13. Initialize PluginManager and register plugins
final pluginManager = PluginManager();
// Core lifecycle plugins
pluginManager.register(BasePlugin());
// Architecture Layouts
pluginManager.register(FeatureFirstPlugin());
pluginManager.register(CleanArchitecturePlugin());
pluginManager.register(MvcPlugin());
pluginManager.register(MvvmPlugin());
pluginManager.register(LayerFirstPlugin());
// State management plugins
pluginManager.register(RiverpodPlugin());
pluginManager.register(BlocPlugin());
pluginManager.register(GetXPlugin());
pluginManager.register(ProviderPlugin());
pluginManager.register(MobXPlugin());
// Routing plugins
pluginManager.register(GoRouterPlugin());
pluginManager.register(NavigatorPlugin());
// Styling plugins
pluginManager.register(Material3Plugin());
pluginManager.register(CupertinoPlugin());
// Networking / Storage plugins
pluginManager.register(DioPlugin());
pluginManager.register(HttpPlugin());
pluginManager.register(HivePlugin());
pluginManager.register(SharedPreferencesPlugin());
pluginManager.register(SecureStoragePlugin());
// Utility packages plugin
pluginManager.register(UtilityPackagesPlugin());
// Post process plugin (runs last)
pluginManager.register(PostProcessPlugin());
// 14. Execute generation pipeline
try {
await pluginManager.run(context);
} catch (e) {
Logger.error('\nGeneration Pipeline failed:');
Logger.error(e.toString());
exit(1);
}
}