A Runner is the most basic form of use case. It accepts a parameter, executes the task, then either returns a Left Value (error) or a Right Value (success).
In our case, an error is represented by the Failure object. The right value can either be null, a primitive object or an Entity.
To get started, we will create the following Runner use cases for the note app in the note_app/modules/domain/lib/note/use_cases/ directory:
CREATE USE CASE: Create a new note entry
Make a file named create_note_entry.dart and add the following code:
import 'dart:async';
import 'package:codenic_bloc_use_case/codenic_bloc_use_case.dart';
import 'package:codenic_exception_converter/codenic_exception_converter.dart';
import 'package:domain/note/repositories/note_repository.dart';
/// {@template CreateNoteEntryParams}
/// The parameters for the [CreateNoteEntry] use case.
/// {@endtemplate}
class CreateNoteEntryParams with EquatableMixin {
/// {@macro CreateNoteEntryParams}
const CreateNoteEntryParams({required this.title, required this.content});
/// The title of the note entry to create.
final String? title;
/// The content of the note entry to create.
final String? content;
@override
List<Object?> get props => [title, content];
}
/// {@template CreateNoteEntry}
/// See [NoteRepository.createNoteEntry].
/// {@endtemplate}
class CreateNoteEntry extends Runner<CreateNoteEntryParams, Failure, void> {
/// {@macro CreateNoteEntry}
CreateNoteEntry({required NoteRepository noteRepository})
: _noteRepository = noteRepository;
/// A reference to the [NoteRepository] instance.
final NoteRepository _noteRepository;
@override
FutureOr<Either<Failure, void>> onCall(CreateNoteEntryParams params) =>
_noteRepository.createNoteEntry(
title: params.title,
content: params.content,
);
}
READ USE CASE: Fetch a collection of note entries
Make a file named fetch_note_entries.dart and add the following code:
import 'dart:async';
import 'package:codenic_bloc_use_case/codenic_bloc_use_case.dart';
import 'package:codenic_exception_converter/codenic_exception_converter.dart';
import 'package:domain/note/entities/note_entry.dart';
import 'package:domain/note/repositories/note_repository.dart';
/// {@template FetchNoteEntryParams}
/// The parameters for the [FetchNoteEntries] use case.
/// {@endtemplate}
class FetchNoteEntriesParams with EquatableMixin {
/// {@macro FetchNoteEntryParams}
const FetchNoteEntriesParams({this.limit = 10, this.pageToken});
/// The number of [NoteEntry]s to fetch.
final int limit;
/// A token used for fetching a particular page of [NoteEntry]s.
final dynamic pageToken;
@override
List<Object?> get props => [limit, pageToken];
}
/// {@template FetchNoteEntries}
/// See [NoteRepository.fetchNoteEntries].
/// {@endtemplate}
class FetchNoteEntries
extends Runner<FetchNoteEntriesParams, Failure, List<NoteEntry>> {
/// {@macro FetchNoteEntry}
FetchNoteEntries({required NoteRepository noteRepository})
: _noteRepository = noteRepository;
/// A reference to the [NoteRepository] instance.
final NoteRepository _noteRepository;
@override
FutureOr<Either<Failure, List<NoteEntry>>> onCall(
FetchNoteEntriesParams params) =>
_noteRepository.fetchNoteEntries(
limit: params.limit,
pageToken: params.pageToken,
);
}
UPDATE USE CASE: Update note entry
Make a file named update_note_entry.dart and add the following code:
import 'dart:async';
import 'package:codenic_bloc_use_case/codenic_bloc_use_case.dart';
import 'package:codenic_exception_converter/codenic_exception_converter.dart';
import 'package:domain/note/entities/note_entry.dart';
import 'package:domain/note/repositories/note_repository.dart';
/// {@template UpdateNoteEntryParams}
/// The parameters for the [UpdateNoteEntry] use case.
/// {@endtemplate}
class UpdateNoteEntryParams with EquatableMixin {
/// {@macro UpdateNoteEntryParams}
const UpdateNoteEntryParams({required this.id, this.title, this.content});
/// The ID of the [NoteEntry] to update.
final String id;
/// The new title of the [NoteEntry].
final String? title;
/// The new content of the [NoteEntry].
final String? content;
@override
List<Object?> get props => [id, title, content];
}
/// {@template UpdateNoteEntry}
/// See [NoteRepository.updateNoteEntry].
/// {@endtemplate}
class UpdateNoteEntry extends Runner<UpdateNoteEntryParams, Failure, void> {
/// {@macro UpdateNoteEntry}
UpdateNoteEntry({required NoteRepository noteRepository})
: _noteRepository = noteRepository;
/// A reference to the [NoteRepository] instance.
final NoteRepository _noteRepository;
@override
FutureOr<Either<Failure, void>> onCall(UpdateNoteEntryParams params) =>
_noteRepository.updateNoteEntry(
id: params.id,
title: params.title,
content: params.content,
);
}
DELETE USE CASE: Delete a note entry
Make a file named delete_note_entry.dart and add the following code:
import 'dart:async';
import 'package:codenic_bloc_use_case/codenic_bloc_use_case.dart';
import 'package:codenic_exception_converter/codenic_exception_converter.dart';
import 'package:domain/note/entities/note_entry.dart';
import 'package:domain/note/repositories/note_repository.dart';
/// {@template DeleteNoteEntryParams}
/// The parameters for the [DeleteNoteEntry] use case.
/// {@endtemplate}
class DeleteNoteEntryParams with EquatableMixin {
/// {@macro DeleteNoteEntryParams}
const DeleteNoteEntryParams({required this.id});
/// The ID of the [NoteEntry] to delete.
final String id;
@override
List<Object?> get props => [id];
}
/// {@template DeleteNoteEntry}
/// See [NoteRepository.deleteNoteEntry].
/// {@endtemplate}
class DeleteNoteEntry extends Runner<DeleteNoteEntryParams, Failure, void> {
/// {@macro DeleteNoteEntry}
DeleteNoteEntry({required NoteRepository noteRepository})
: _noteRepository = noteRepository;
/// A reference to the [NoteRepository] instance.
final NoteRepository _noteRepository;
@override
FutureOr<Either<Failure, void>> onCall(DeleteNoteEntryParams params) =>
_noteRepository.deleteNoteEntry(id: params.id);
}