runWizard method

Future<ProjectConfig> runWizard({
  1. String? initialProjectName,
  2. String? initialOrg,
})

Runs the interactive CLI wizard and returns a completed ProjectConfig.

Implementation

Future<ProjectConfig> runWizard(
    {String? initialProjectName, String? initialOrg}) async {
  _logger.info('');
  final floLogo = r'''
 ______   __         ______        ______     __         __
/\  ___\ /\ \       /\  __ \      /\  ___\   /\ \       /\ \
\ \  __\ \ \ \____  \ \ \/\ \     \ \ \____  \ \ \____  \ \ \
 \ \_\    \ \_____\  \ \_____\     \ \_____\  \ \_____\  \ \_\
\/_/     \/_____/   \/_____/      \/_____/   \/_____/   \/_/

''';
  _logger.info(floLogo);
  _logger.info('✨ \x1B[1mWelcome to the Flo CLI Project Generator\x1B[0m ✨');
  _logger.info('-----------------------------------------');

  final projectName = initialProjectName ??
      _logger.prompt('Project Name', defaultValue: 'my_app');

  final org = initialOrg ??
      _logger.prompt('Organization', defaultValue: 'com.example');

  final allPlatforms = ['android', 'ios', 'web', 'macos', 'windows', 'linux'];
  final platforms = _logger.chooseAny<String>(
    'Platforms',
    choices: allPlatforms,
    defaultValues: ['android', 'ios'],
  );

  final architecture = _logger.chooseOne<String>(
    'Architecture',
    choices: ['Clean Architecture', 'MVVM', 'MVC'],
    defaultValue: 'Clean Architecture',
  );

  final stateManagement = _logger.chooseOne<String>(
    'State Management',
    choices: ['Bloc', 'Riverpod', 'Provider', 'None'],
    defaultValue: 'Bloc',
  );

  // Build context-aware dependency list
  final smKey = stateManagement.toLowerCase();
  final packageGroup = PackageRegistry.flutterPackages[smKey] ??
      PackageRegistry.flutterPackages['bloc']!;

  final recommendedDeps = <String>{};

  // Always include state management, serialization, and dev dependencies as defaults
  recommendedDeps.addAll(packageGroup['state_management'] ?? []);
  recommendedDeps.addAll(packageGroup['serialization'] ?? []);
  recommendedDeps.addAll(packageGroup['dev_dependencies'] ?? []);

  // Determine which categories have recommended dependencies
  final categories = packageGroup.keys.toList();
  final defaultCategories = <String>[];
  for (var category in categories) {
    final packagesInCategory = packageGroup[category]!;
    if (packagesInCategory.any((p) => recommendedDeps.contains(p))) {
      defaultCategories.add(category);
    }
  }

  _logger.info('');
  _logger.info('Dependency configuration is segregated into categories.');
  final selectedCategories = _logger.chooseAny<String>(
    'Select Categories to configure',
    choices: categories,
    defaultValues: defaultCategories,
    display: (category) => category.replaceAll('_', ' ').toUpperCase(),
  );

  final selectedDependencies = <String>[];

  for (final category in selectedCategories) {
    final packages = packageGroup[category]!;
    final defaultPackages =
        packages.where((p) => recommendedDeps.contains(p)).toList();

    final formattedCategory = category.replaceAll('_', ' ').toUpperCase();
    final categorySelection = _logger.chooseAny<String>(
      'Select $formattedCategory packages',
      choices: packages,
      defaultValues: defaultPackages,
    );
    selectedDependencies.addAll(categorySelection);
  }

  final gitInit =
      _logger.confirm('Initialize Git repository?', defaultValue: true);
  final generateReadme =
      _logger.confirm('Generate README.md?', defaultValue: true);

  _logger.info('-----------------------------------------');
  _logger.success('Configuration complete!');
  _logger.info('');

  return ProjectConfig(
    projectName: projectName,
    org: org,
    platforms: platforms,
    architecture: architecture,
    stateManagement: stateManagement,
    gitInit: gitInit,
    generateReadme: generateReadme,
    dependencies: selectedDependencies,
  );
}