main function

void main(
  1. List<String> arguments
)

Generates a new BLoC boilerplate with a view, state, bloc, and events file.

Implementation

void main(List<String> arguments) {
  final parser = ArgParser();
  parser.addCommand(
    'generate',
    ArgParser()..addOption(
      'name',
      abbr: 'n',
      help: 'The name of the BLoC to generate.',
      mandatory: true,
    ),
  );

  parser.addCommand(
    'add-handler',
    ArgParser()
      ..addOption(
        'name',
        abbr: 'n',
        help: 'The name of the BLoC to modify (e.g., "Login").',
        mandatory: true,
      )
      ..addOption(
        'handler',
        abbr: 'h',
        help: 'The name of the handler to add (e.g., "FetchData").',
        mandatory: true,
      ),
  );

  parser.addCommand(
    'add-state',
    ArgParser()
      ..addOption(
        'name',
        abbr: 'n',
        help: 'The name of the BLoC to modify (e.g., "Login").',
        mandatory: true,
      )
      ..addOption(
        'property',
        abbr: 'p',
        help: 'The state property to add (e.g., "user:User").',
        mandatory: true,
      ),
  );
  try {
    final ArgResults results = parser.parse(arguments);
    final String? command = results.command?.name;

    if (command == 'generate') {
      final String blocName = results.command!['name'] as String;
      final String snakeCaseBlocName = _toSnakeCase(blocName);

      print('Generating BLoC boilerplate for "$blocName"...');

      final blocDir = Directory(
        p.join(Directory.current.path, snakeCaseBlocName),
      );
      if (!blocDir.existsSync()) blocDir.createSync(recursive: true);

      _generateFile(
        p.join(blocDir.path, 'view.dart'),
        createViewTemplate(blocName),
      );
      _generateFile(
        p.join(blocDir.path, 'state.dart'),
        createStateTemplate(blocName),
      );
      _generateFile(
        p.join(blocDir.path, 'events.dart'),
        createEventsTemplate(blocName),
      );
      _generateFile(
        p.join(blocDir.path, 'bloc.dart'),
        createBlocTemplate(blocName),
      );

      print('Successfully generated BLoC for "$blocName" in ${blocDir.path}');
    } else if (command == 'add-handler') {
      final String blocName = results.command!['name'] as String;
      final String handlerName = results.command!['handler'] as String;
      final String snakeCaseBlocName = _toSnakeCase(blocName);

      print('Adding handler for "$handlerName" to "$blocName"...');

      final blocDir = Directory(
        p.join(Directory.current.path, snakeCaseBlocName),
      );
      if (!blocDir.existsSync()) {
        print(
          'Error: Directory for BLoC "$blocName" not found. Please run the "generate" command first.',
        );
        return;
      }

      final eventsFile = File(p.join(blocDir.path, 'events.dart'));
      final stateFile = File(p.join(blocDir.path, 'state.dart'));
      final blocFile = File(p.join(blocDir.path, 'bloc.dart'));

      if (!eventsFile.existsSync() ||
          !stateFile.existsSync() ||
          !blocFile.existsSync()) {
        print('Error: BLoC files not found in ${blocDir.path}.');
        return;
      }

      // Add new event
      final eventContent = eventsFile.readAsStringSync();
      final newEventContent = eventContent.replaceFirst(
        '}',
        createEventsTemplate(blocName, handlerName),
      );
      eventsFile.writeAsStringSync(newEventContent);
      print('  ✓ Added event to events.dart');

      // Add new state
      final stateContent = stateFile.readAsStringSync();
      final newStatusName = _toCamelCase(handlerName);
      final newStateContent = stateContent.replaceFirst(
        '}',
        createStateTemplate(blocName, newStatusName),
      );
      stateFile.writeAsStringSync(newStateContent);
      print('  ✓ Added state status to state.dart');

      // Add new handler
      final blocContent = blocFile.readAsStringSync();
      final newBlocContent = blocContent.replaceFirst(
        '}',
        createBlocTemplate(blocName, handlerName),
      );
      blocFile.writeAsStringSync(newBlocContent);
      print('  ✓ Added handler to bloc.dart');

      print('Successfully added handler "$handlerName" to BLoC "$blocName"');
    } else if (command == 'add-state') {
      final String blocName = results.command!['name'] as String;
      final String propertyString = results.command!['property'] as String;
      final String snakeCaseBlocName = _toSnakeCase(blocName);

      print('Adding state property "$propertyString" to "$blocName"...');

      final parts = propertyString.split(':');
      if (parts.length != 2) {
        print('Error: Invalid property format. Use "name:DataType".');
        return;
      }
      final propertyName = parts[0];
      final propertyType = parts[1];

      final blocDir = Directory(
        p.join(Directory.current.path, snakeCaseBlocName),
      );
      if (!blocDir.existsSync()) {
        print(
          'Error: Directory for BLoC "$blocName" not found. Please run the "generate" command first.',
        );
        return;
      }

      final stateFile = File(p.join(blocDir.path, 'state.dart'));
      if (!stateFile.existsSync()) {
        print('Error: State file not found in ${blocDir.path}.');
        return;
      }

      var stateContent = stateFile.readAsStringSync();

      // Add new property to class definition
      stateContent = stateContent.replaceFirst(
        '  final String? error;',
        '  final String? error;\n  final $propertyType? $propertyName;',
      );

      // Add property to constructor
      stateContent = stateContent.replaceFirst(
        'this.error,',
        'this.error,\n    this.$propertyName,',
      );

      // Add property to copyWith method signature
      stateContent = stateContent.replaceFirst(
        'String? error,',
        'String? error,\n    $propertyType? $propertyName,',
      );

      // Add property to copyWith method return
      stateContent = stateContent.replaceFirst(
        'error: error ?? this.error,',
        'error: error ?? this.error,\n      $propertyName: $propertyName ?? this.$propertyName,',
      );

      // Add property to props list
      stateContent = stateContent.replaceFirst('];', ', $propertyName];');

      stateFile.writeAsStringSync(stateContent);
      print('  ✓ Added state property to state.dart');

      print(
        'Successfully added state property "$propertyName" to BLoC "$blocName"',
      );
    } else {
      print('Error: Invalid command. Use "generate" or "add-handler".');
      print(parser.usage);
    }
  } on ArgParserException catch (e) {
    print(e.message);
    print(parser.usage);
  } catch (e) {
    print('Error: $e');
  }
}