run method

  1. @override
Future<void> run()
override

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);
  }
}