run method

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

Runs this command.

The return value is wrapped in a Future if necessary and returned by CommandRunner.runCommand.

Implementation

@override
Future<int> run() async {
  final pubspecFile = File('pubspec.yaml');
  if (!pubspecFile.existsSync()) {
    _logger.err('Error: No pubspec.yaml found in the current directory.');
    _logger.info(
      'Please run this command at the root of your Flutter/Dart project.',
    );
    return 1;
  }

  final String pubspecContent;
  try {
    pubspecContent = pubspecFile.readAsStringSync();
  } catch (e) {
    _logger.err('Failed to read pubspec.yaml: $e');
    return 1;
  }

  final dynamic yamlDoc;
  try {
    yamlDoc = loadYaml(pubspecContent);
  } catch (e) {
    _logger.err('Failed to parse pubspec.yaml: $e');
    return 1;
  }

  if (yamlDoc is! Map) {
    _logger.err('Error: Failed to parse pubspec.yaml as a YAML Map.');
    return 1;
  }

  final projectName = yamlDoc['name'] as String? ?? 'app';

  final dependencies = yamlDoc['dependencies'] as Map? ?? {};

  // Detect state management solution
  String stateManagement = 'none';
  if (dependencies.containsKey('flutter_bloc') ||
      dependencies.containsKey('bloc')) {
    stateManagement = 'bloc';
  } else if (dependencies.containsKey('flutter_riverpod') ||
      dependencies.containsKey('riverpod') ||
      dependencies.containsKey('hooks_riverpod')) {
    stateManagement = 'riverpod';
  } else if (dependencies.containsKey('provider')) {
    stateManagement = 'provider';
  }

  // Detect routing solution
  String router = 'none';
  if (dependencies.containsKey('go_router')) {
    router = 'go_router';
  } else if (dependencies.containsKey('auto_route')) {
    router = 'auto_route';
  }

  final zuqYamlFile = File('zuq.yaml');
  bool overwrite = argResults?['force'] as bool? ?? false;

  List<String> existingModules = [];
  String preset = 'default';
  String featuresPath = 'lib/features';

  if (zuqYamlFile.existsSync()) {
    try {
      final content = zuqYamlFile.readAsStringSync();
      final doc = loadYaml(content);
      if (doc is Map) {
        final rawModules = doc['modules'];
        if (rawModules is List) {
          existingModules = rawModules
              .where((m) => m != null)
              .map((m) => m.toString())
              .toList();
        }
        if (doc.containsKey('preset')) {
          preset = doc['preset']?.toString() ?? 'default';
        }
        if (doc.containsKey('features_path')) {
          featuresPath = doc['features_path']?.toString() ?? 'lib/features';
        }
      }
    } catch (_) {}

    if (!overwrite) {
      if (_hasTerminal) {
        overwrite = _logger.confirm(
          'A zuq.yaml file already exists in this directory. Do you want to overwrite it?',
          defaultValue: false,
        );
        if (!overwrite) {
          _logger.info('Initialization aborted.');
          return 0;
        }
      } else {
        _logger.err(
          'Error: A zuq.yaml file already exists in this directory. Use --force to overwrite.',
        );
        return 1;
      }
    }
  }

  if (featuresPath == 'lib/features' &&
      !Directory('lib/features').existsSync()) {
    if (Directory('lib/modules').existsSync()) {
      featuresPath = 'lib/modules';
    } else if (Directory('lib/src/features').existsSync()) {
      featuresPath = 'lib/src/features';
    }
  }

  final modulesBlock = existingModules.isEmpty
      ? 'modules: []'
      : 'modules:\n${existingModules.map((m) => '  - $m').join('\n')}';

  try {
    zuqYamlFile.writeAsStringSync('''
name: $projectName
state_management: $stateManagement
router: $router
preset: $preset
features_path: $featuresPath
$modulesBlock
''');
  } catch (e) {
    _logger.err('Failed to write zuq.yaml: $e');
    return 1;
  }

  _logger.success(
    '✓ Successfully initialized zuq configuration in zuq.yaml!',
  );
  _logger.info('Detected configuration:');
  _logger.info('  - Name: $projectName');
  _logger.info('  - State Management: $stateManagement');
  _logger.info('  - Router: $router');
  _logger.info('  - Features Path: $featuresPath');

  final featuresDir = Directory(featuresPath);
  if (!featuresDir.existsSync()) {
    _logger.info('\nNext steps:');
    _logger.info(
      '  Run `zuq add feature <feature_name>` to start scaffolding your clean-architecture features.',
    );
  } else {
    _logger.info(
      '\nFound existing features directory at $featuresPath. You can run `zuq doctor` to audit layer boundaries.',
    );
  }

  return 0;
}