Feature SDKs (Free)
state_management Free
- Tier
- Freeversion 0.1.2
- Command
archipelago generate state_management- Generates
- the BLoC, Cubit or notifier files and their tests for one feature, depending on stateManagement
Generate a state management layer (BLoC, Cubit, Riverpod, or Provider) for an existing feature module.
What it is
state_management is not a standalone feature brick — it's a scaffolding utility that generates presentation-layer state files (a Cubit, a Bloc, or a Riverpod/Provider notifier) for a feature you already have. Use it after feature_monorepo_skeleton (with stateManagement: none) to add a state class to a specific usecase, or to add another usecase's state to an existing feature.
Variables
| Variable | Type | Default | Description |
|---|---|---|---|
| stateManagement | enum | cubit | State management solution: bloc, cubit, riverpod, provider |
| featureName | string | feature | Feature name (e.g. auth, checkout, profile) |
| usecaseName | string | "" | Usecase to wire up (e.g. login, fetchProducts). Leave empty for a blank skeleton — naming then falls back to featureName |
| outputPath | string | "" | Sub-path within the feature's presentation/ directory (e.g. login, home). Leave empty for the feature root |
pre_gen.dart derives isBloc, isCubit, isRiverpod, isProvider, usesBloc (bloc or cubit), hasUsecase (true when usecaseName is non-empty), and the resolved name (usecaseName if set, else featureName) that all templates key off.
Usage
Interactive
archipelago generate state_managementNon-interactive (CI)
archipelago generate state_management --config my_config.json{
"stateManagement": "cubit",
"featureName": "auth",
"usecaseName": "login",
"outputPath": "login"
}Where files land
The brick's own templates are flat — bloc/, cubit/, or notifiers/ at the template root, with no presentation/ or outputPath segment baked into the file paths. Placing the output inside the target feature's lib/src/presentation/<outputPath>/ is done via the CLI's --output flag (archipelago generate state_management --output features/auth/auth_impl/lib/src/presentation/login), not by the brick itself. featureName/outputPath mainly drive the resolved name and the wiring instructions post_gen.dart prints — they don't relocate the generated files on their own.
Generated Structure
post_gen.dart deletes the directories for every variant except the one chosen:
| Variant | Directory | Files |
|---|---|---|
| bloc | bloc/ | <name>_bloc.dart, <name>_event.dart, <name>_state.dart, <name>_bloc_test.dart |
| cubit | cubit/ | <name>_cubit.dart, <name>_state.dart, <name>_cubit_test.dart |
| riverpod | notifiers/ | <name>_notifier.dart, <name>_state.dart, <name>_notifier_test.dart |
| provider | notifiers/ | <name>_notifier.dart, <name>_notifier_test.dart |
Public API (generated code)
Templates key off a resolved name (usecaseName if set, else featureName, PascalCase/camelCase/snake_case as needed). The examples below resolve name to login (usecaseName: "login"), matching the CI config sample above.
Cubit variant (login_cubit.dart):
class LoginCubit extends Cubit<LoginState> {
LoginCubit(this._loginUseCase) // constructor param only when usecaseName is set
: super(const LoginState.initial());
Future<void> execute() async {
emit(const LoginState.loading());
try {
await _loginUseCase();
emit(const LoginState.loaded());
} catch (e) {
emit(LoginState.error(e.toString()));
}
}
}Bloc variant's event file uses freezed, not a plain standalone class:
part 'login_event.freezed.dart';
@freezed
sealed class LoginEvent with _$LoginEvent {
const factory LoginEvent.started() = _Started;
const factory LoginEvent.refreshed() = _Refreshed;
}Riverpod variant uses the @riverpod codegen style (part 'login_notifier.g.dart'), requiring riverpod_generator and a build_runner pass:
@riverpod
class LoginNotifier extends _$LoginNotifier {
@override
LoginState build() => const LoginState.initial();
Future<void> execute() async { /* ... */ }
}After generation
post_gen.dart prints variant-specific wiring instructions: the DI registration snippet, a widget consumption snippet, the barrel-export line to add to lib/src/presentation/presentation.dart, and (Riverpod only) the reminder to run:
dart run build_runner build --delete-conflicting-outputsLimitations / known issues
- No
CHANGELOG.mdships with this brick yet. - The bloc variant's event file is generated via
freezed(part '<name>_event.freezed.dart'), which is apartfile — this is worth noting because this repo's own conventions elsewhere describe bloc event/state files as "standalone (notpart of)". Confirm this is intentional for this brick before relying on the standalone-file assumption. outputPathdoes not relocate generated files by itself; passing the wrong--outputvalue silently drops files at the wrong path with no validation.
Changelog
Run archipelago brick info state_management to see the latest published version. Enterprise customers can read the full CHANGELOG.md in the brick source repository.