blocz 1.4.0 copy "blocz: ^1.4.0" to clipboard
blocz: ^1.4.0 copied to clipboard

Flutter bloc helpers

blocz #

A command-line interface (CLI) tool to speed up Flutter app development by scaffolding BLoC pattern components.

pub version

About #

blocz helps you quickly generate BLoC, Event, and State files in a structured directory, saving you time and keeping your codebase consistent. The tool also supports adding events to an existing BLoC.

Features #

  • Generate BLoC, Event, and State with a single command.
  • Automatically create a domain-based directory structure.
  • The generated code is compatible with popular packages like flutter_bloc, freezed, and injectable.
  • Supports quickly adding new events to a BLoC.
  • Automatically import events and handlers from an API service file.
  • Robust & Surgical Updates: Uses Dart AST (Abstract Syntax Tree) to accurately identify and update method calls, preserving your manual changes.

How it Works #

1. BLoC Scaffolding (make) #

The make command creates the initial BLoC structure.

graph TD
    Start([make command]) --> Params[Determine names & paths]
    Params --> Exist{Files exist?}
    Exist -- No --> Templates[Render Mustache templates]
    Templates --> Write[Write _bloc, _event, _state files]
    Exist -- Yes --> Skip[Skip file generation]
    
    Write --> API{apiPath provided?}
    Skip --> API
    
    API -- Yes --> AddEvent[Call add:event logic]
    API -- No --> Build[Run build_runner & format]
    
    AddEvent --> Build
    Build --> End([Done])

2. Adding Events (add:event) #

The add:event command adds or updates events in an existing BLoC.

graph TD
    Start([add:event command]) --> Input[Receive domain, event, apiPath, method]
    Input --> Mode{apiPath provided?}
    
    Mode -- Yes --> Bulk[Loop: Process each API method]
    Mode -- No --> Single[Process single event]
    
    Bulk --> Single
    
    subgraph SingleEventProc [Single Event Process]
        Ensure[Ensure files exist - run 'make' if missing]
        Ensure --> Ev[Update _event.dart: Add/Update factory]
        Ev --> St[Update _state.dart: Add/Update factory]
        St --> Bl{Already registered?}
        
        Bl -- No --> Reg[Insert 'on' registration & handler method]
        Bl -- Yes --> Upd{update flag?}
        
        Upd -- Yes --> Surgical[Surgically update call args using AST]
        Upd -- No --> Skip[Skip update]
    end
    
    Single --> Finish[Run build_runner & format]
    Reg --> Finish
    Surgical --> Finish
    Skip --> Finish
    Finish --> End([Done])

Note

blocz uses the Dart analyzer package to parse your code into an Abstract Syntax Tree (AST). This allows it to perform "surgical" updates—replacing only the necessary bits (like method arguments) while leaving the rest of your custom logic untouched.

Prerequisites #

Run these commands in your Flutter project directory to add the required dependencies:

flutter pub add flutter_bloc freezed_annotation injectable get_it
flutter pub add --dev build_runner freezed injectable_generator

Installation #

Activate blocz as a global tool to use it from anywhere:

dart pub global activate blocz

Usage #

1. Create BLoC, Event, and State #

Use the make command to generate the necessary components.

blocz make --domain <domain_name> --name <bloc_name> [--apiPath <path_to_api_file>] [--writeDir <custom_path>]
  • --domain (or -d): The domain or feature of the BLoC (e.g., pet, product).
  • --name (or -n)(optional): The name of the BLoC, or a sub-domain/sub-feature name (e.g., authentication, profile).
  • --apiPath (or -a)(optional): Optional path to an API service file. If provided, blocz will automatically generate and implement events for all public methods in that file.
  • --writeDir (or -w)(optional): Custom directory to generate files. Defaults to lib/features/<domain>/presentation/bloc.

writeDir Template Support

You can use template variables in the --writeDir path:

  • {{DOMAIN}} or {{domain}}: Replaced by the domain name in snake_case.
  • {{Domain}}: Replaced by the domain name in PascalCase.

Example:

blocz make --domain pet --writeDir "lib/App/screens/{{DOMAIN}}_page/bloc"

Examples:

Basic BLoC creation:

blocz make --domain pet

Generated files tree

lib/features/pet/presentation/bloc/
├── pet_bloc.dart
├── pet_event.dart
└── pet_state.dart

This command creates the BLoC structure. You will then need to run build_runner.

BLoC creation with automatic event implementation from an API file:

Example with OpenAPI generator:

export MY_PET_API_PACKAGE_NAME="my_pet_api"
export MY_PET_API_DIR="./apis/$MY_PET_API_PACKAGE_NAME"
rm -fr $MY_PET_API_DIR || true # remove old
mkdir -p $MY_PET_API_DIR # create if not exists
npx @openapitools/openapi-generator-cli generate
  -i https://petstore.swagger.io/v2/swagger.json
  -g dart
  --additional-properties=pubName=$MY_PET_API_PACKAGE_NAME
  -o $MY_PET_API_DIR
cd $MY_PET_API_DIR
  && dart pub get
  && (dart run build_runner build || true)
  && cd "$(git rev-parse --show-toplevel)"
ls -lh "./apis/$MY_PET_API_PACKAGE_NAME/lib/api/"
# in your pubspec.yaml
dependencies:
  my_pet_api: # Added local API package
    path: ./apis/my_pet_api
blocz make --domain pet --apiPath ./apis/my_pet_api/lib/api/pet_api.dart

This command will create the BLoC files and also automatically add events and handlers for all methods found in pet_api.dart.

// $PROJECT/lib/features/pet/presentation/bloc/pet_event.dart
part of 'pet_bloc.dart';

@freezed
sealed class PetEvent with _$PetEvent {
  const factory PetEvent.loading() = _PetEventLoading;
  const factory PetEvent.addPet(Pet body) = _AddPetRequested;
  const factory PetEvent.deletePet(int petId, {String? apiKey}) = _DeletePetRequested;
  const factory PetEvent.findPetsByStatus(List<String> status) = _FindPetsByStatusRequested;
  const factory PetEvent.findPetsByTags(List<String> tags) = _FindPetsByTagsRequested;
  const factory PetEvent.getPetById(int petId) = _GetPetByIdRequested;
  const factory PetEvent.updatePet(Pet body) = _UpdatePetRequested;
  const factory PetEvent.updatePetWithForm(int petId, {String? name, String? status}) = _UpdatePetWithFormRequested;
  const factory PetEvent.uploadFile(int petId, {String? additionalMetadata, MultipartFile? file}) = _UploadFileRequested;
}

// $PROJECT/lib/features/pet/presentation/bloc/pet_state.dart
part of 'pet_bloc.dart';

@freezed
sealed class PetState with _$PetState {
  const factory PetState.initial() = _InitialDone;
  const factory PetState.loading() = _Loading;
  const factory PetState.failure(String message) = _Failure;
  const factory PetState.addPetResult() = _AddPetResult;
  const factory PetState.deletePetResult() = _DeletePetResult;
  const factory PetState.findPetsByStatusResult(List<Pet>? data) = _FindPetsByStatusResult;
  const factory PetState.findPetsByTagsResult(List<Pet>? data) = _FindPetsByTagsResult;
  const factory PetState.getPetByIdResult(Pet? data) = _GetPetByIdResult;
  const factory PetState.updatePetResult() = _UpdatePetResult;
  const factory PetState.updatePetWithFormResult() = _UpdatePetWithFormResult;
  const factory PetState.uploadFileResult(ApiResponse? data) = _UploadFileResult;
}

Important: Since the generated files use freezed, you need to run build_runner after generation:

dart run build_runner build --delete-conflicting-outputs

2. Add an Event #

Use the add:event command to add a new event to an existing BLoC.

blocz add:event --domain <domain_name> --name <sub_domain_name> <options>

Options:

  • --name <sub_domain_name> (or -n): The name of the BLoC or sub-domain (e.g., profile).
  • --event <event_name>: Adds a single, specified event.
  • --apiPath <path_to_api_file>: Scans the API file and generates events and handlers for all public methods.
  • --apiPath <path_to_api_file> --method <method_name>: Generates an event and handler for only one specified method from the API file.
  • --writeDir <custom_path> (or -w): Custom directory where the BLoC files are located.

Examples:

Add a simple event:

blocz add:event --domain pet --event bark

Add all events from an API file:

blocz add:event --domain pet --apiPath ./apis/my_pet_api/lib/api/pet_api.dart

Add a single event from a specific API method:

blocz add:event --domain pet --name profile --event UpdateAvatar --apiPath ./apis/my_pet_api/lib/api/pet_api.dart --method uploadFile

This command will update the corresponding BLoC files to add the new event(s).

Other Commands #

blocz also provides many helper commands for parsing Dart source code. Use blocz --help to see all available commands.

1
likes
120
points
462
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Flutter bloc helpers

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

analyzer, args, collection, dcli, mustache_template, path, recase

More

Packages that depend on blocz