Learn
Getting started
Install usecase_forge and execute a typed command through a complete lifecycle.
Getting started
This guide creates a counter UseCase. The example is intentionally small, but it still uses the same command, execution context, snapshot, terminal phase, and close lifecycle as a production operation.
Requirements
- Dart SDK 3.12.2 or newer.
- A Dart project with a
pubspec.yaml.
Install the package
dart pub add usecase_forge
Import the public library:
import 'package:usecase_forge/usecase_forge.dart';
Model state and command
State is an application value. UseCase Forge does not impose a state base class, but meaningful equality prevents redundant publication.
final class CounterState {
const CounterState(this.value);
final int value;
@override
bool operator ==(Object other) =>
other is CounterState && other.value == value;
@override
int get hashCode => value.hashCode;
}
final class Increment extends UseCaseCommand {
const Increment({this.by = 1});
final int by;
}
The command describes intent. It does not execute itself and does not hold UI state.
Register the handler
final class CounterUseCase extends UseCase<CounterState> {
CounterUseCase() : super(initialState: const CounterState(0)) {
registerCommand<Increment>(_increment);
}
Future<void> _increment(
Increment command,
UseCaseExecutionContext<CounterState> context,
) async {
final current = context.snapshot.state.value;
context.publish(CounterState(current + command.by));
}
}
Registration connects one command type to one handler. context.snapshot is the execution-visible snapshot; context.publish moves a new state through the ordered output path.
Execute and close
Future<void> main() async {
final counter = CounterUseCase();
final finished = counter.stream.firstWhere(
(snapshot) => snapshot.phase == UseCaseExecutionPhase.finished,
);
counter.add(const Increment(by: 2));
await finished;
print(counter.state.state.value);
await counter.close();
}
add submits intent. The returned lifecycle is observed through snapshots and execution handles; close terminates owned resources and must be awaited by the owner.
Next
Read Core concepts to distinguish a command from its execution and a state value from its lifecycle snapshot. Then build the Dart task processor tutorial to apply rate limiting, debounce, grouping, and typed rejection.