CRUD Operations (Runner)

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);
}

Last updated