diff --git a/packages/wyatt_crud_bloc/README.md b/packages/wyatt_crud_bloc/README.md
index 8b55e735..4f483186 100644
--- a/packages/wyatt_crud_bloc/README.md
+++ b/packages/wyatt_crud_bloc/README.md
@@ -1,39 +1,167 @@
-
-TODO: Put a short description of the package here that helps potential users
-know whether this package might be useful for them.
+# CRUD BloC
-## Features
+
+
+
+
-TODO: List what your package can do. Maybe include images, gifs, or videos.
+CRUD Bloc Pattern utilities for Flutter.
-## Getting started
+This package defines a set of classes that can be used to implement the CRUD Bloc Pattern.
-TODO: List prerequisites and provide or point to information on how to
-start using the package.
+* Model
+* Data Source
+ + In Memory
+ + Firestore
+* Repository
+* Use Case
+ + Create
+ + Get
+ + Get All
+ + Update
+ + Update All
+ + Delete
+ + Delete All
+ + Query
+* Bloc
+ + Standard (C R U D), you have to choose the responsiblity of the bloc for each use case. For example, you can have a cubit that only handles the creation of an entity, and another cubit that only handles the deletion of an entity. Each cubit can only have one operation responsibility of each type, for example you can't have a cubit that handles get and get all.
+ + Advanced, you can set every use case to be handled by the bloc. This is useful if you want to have a single bloc that handles all the operations of an entity.
## Usage
-TODO: Include short and useful examples for package users. Add longer examples
-to `/example` folder.
+Create a model class that extends the `ObjectModel` class.
```dart
-const like = 'sample';
+class User extends ObjectModel {
+ @override
+ final String? id;
+
+ final String? name;
+
+ const User({
+ required this.name,
+ this.id,
+ });
+
+ Map toMap() {
+ return {
+ 'name': name ?? '',
+ };
+ }
+
+ @override
+ String toString() => 'User(id: $id, name: $name)';
+}
```
-## Additional information
+You have to implement a bloc.
-TODO: Tell users more about the package: where to find more information, how to
-contribute to the package, how to file issues, what response they can expect
-from the package authors, and more.
+```dart
+/// A [CrudCubit] for [User].
+class UserCubit extends CrudCubit {
+ final CrudRepository _crudRepository;
+
+ UserCubit(this._crudRepository);
+
+ @override
+ CreateOperation? get createOperation =>
+ Create(_crudRepository);
+
+ @override
+ DeleteOperation? get deleteOperation =>
+ Delete(_crudRepository);
+
+ @override
+ ReadOperation? get readOperation =>
+ GetAll(_crudRepository);
+
+ @override
+ UpdateOperation? get updateOperation =>
+ Update(_crudRepository);
+}
+```
+
+> You can also use the `CrudAdvancedCubit` class to implement a bloc that handles all the use cases.
+
+Then you can use the bloc in your widget with a data source and a repository.
+
+```dart
+class MyApp extends StatelessWidget {
+ const MyApp({Key? key}) : super(key: key);
+
+ // This widget is the root of your application.
+ @override
+ Widget build(BuildContext context) {
+ final CrudDataSource userLocalDataSource =
+ CrudInMemoryDataSourceImpl(toMap: (user) => user.toMap());
+
+ final CrudRepository userRepository =
+ CrudRepositoryImpl(crudDataSource: userLocalDataSource);
+
+ return RepositoryProvider>.value(
+ value: userRepository,
+ child: BlocProvider(
+ create: (context) => UserCubit(userRepository)..read(),
+ child: MaterialApp(
+ title: 'Flutter Demo',
+ theme: ThemeData(
+ primarySwatch: Colors.blue,
+ ),
+ home: const MyHomePage(),
+ ),
+ ),
+ );
+ }
+}
+```
+
+And anywhere in your widget tree you can use the BlocBuilder to build your widget.
+
+```dart
+...
+BlocBuilder(
+ builder: (context, state) {
+ return CrudBuilder.typed>(
+ state: state,
+ builder: ((context, state) {
+ return ListView.builder(
+ shrinkWrap: true,
+ itemCount: state.data.length,
+ itemBuilder: (context, index) {
+ final user = state.data.elementAt(index);
+ return ListTile(
+ title: Text(user?.name ?? 'Error'),
+ subtitle: Text(user?.id ?? 'Error'),
+ onTap: () {
+ context.read().delete(id: (user?.id)!);
+ },
+ );
+ },
+ );
+ }),
+ initialBuilder: (context, state) => const Text("Loading..."),
+ loadingBuilder: (context, state) => const Text("Loading..."),
+ errorBuilder: (context, state) => Text("Error: $state"),
+ );
+ },
+),
+...
+```
diff --git a/packages/wyatt_crud_bloc/example/lib/app.dart b/packages/wyatt_crud_bloc/example/lib/app.dart
index 47d7e59e..d5339343 100644
--- a/packages/wyatt_crud_bloc/example/lib/app.dart
+++ b/packages/wyatt_crud_bloc/example/lib/app.dart
@@ -36,8 +36,12 @@ class MyApp extends StatelessWidget {
return RepositoryProvider>.value(
value: userRepository,
- child: BlocProvider(
- create: (context) => UserCubit(userRepository)..getAll(),
+ child: MultiBlocProvider(
+ providers: [
+ BlocProvider(
+ create: (context) => UserCubit(userRepository)..read(),
+ ),
+ ],
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
@@ -78,9 +82,7 @@ class MyHomePage extends StatelessWidget {
title: Text(user?.name ?? 'Error'),
subtitle: Text(user?.id ?? 'Error'),
onTap: () {
- context.read().delete(
- (user?.id)!,
- );
+ context.read().delete(id: (user?.id)!);
},
);
},
@@ -108,22 +110,10 @@ class MyHomePage extends StatelessWidget {
),
ElevatedButton(
onPressed: () {
- context.read().deleteAll();
- },
- child: const Text("DeleteAll"),
- ),
- ElevatedButton(
- onPressed: () {
- context.read().getAll();
+ context.read().read();
},
child: const Text("GetAll"),
),
- ElevatedButton(
- onPressed: () {
- context.read().query([LimitQuery(2)]);
- },
- child: const Text("Query"),
- ),
const SizedBox(height: 20),
],
),
diff --git a/packages/wyatt_crud_bloc/example/lib/models.dart b/packages/wyatt_crud_bloc/example/lib/models.dart
index b4ccfebf..e9ed1c7f 100644
--- a/packages/wyatt_crud_bloc/example/lib/models.dart
+++ b/packages/wyatt_crud_bloc/example/lib/models.dart
@@ -18,37 +18,18 @@ import 'package:wyatt_crud_bloc/wyatt_crud_bloc.dart';
class User extends ObjectModel {
@override
- String? id;
+ final String? id;
- String? name;
- String? email;
- String? phone;
+ final String? name;
+ final String? email;
+ final String? phone;
- User({
+ const User({
required this.name,
required this.email,
required this.phone,
this.id,
});
- // User._();
-
- // factory User.parser() {
- // return User._();
- // }
-
- // @override
- // User? from(DocumentSnapshot? object) {
- // if (object == null) return null;
- // if (object.exists) {
- // return User(
- // id: object.id,
- // name: (object.data() as Map?)!['name'] as String,
- // email: (object.data() as Map?)!['email'] as String,
- // phone: (object.data() as Map?)!['phone'] as String,
- // );
- // }
- // return null;
- // }
Map toMap() {
return {
diff --git a/packages/wyatt_crud_bloc/example/lib/user_cubit.dart b/packages/wyatt_crud_bloc/example/lib/user_cubit.dart
index 703d6686..cc34df6c 100644
--- a/packages/wyatt_crud_bloc/example/lib/user_cubit.dart
+++ b/packages/wyatt_crud_bloc/example/lib/user_cubit.dart
@@ -17,32 +17,25 @@
import 'package:crud_bloc_example/models.dart';
import 'package:wyatt_crud_bloc/wyatt_crud_bloc.dart';
+/// A [CrudCubit] for [User].
class UserCubit extends CrudCubit {
final CrudRepository _crudRepository;
UserCubit(this._crudRepository);
@override
- Create? get crudCreate => Create(_crudRepository);
+ CreateOperation? get createOperation =>
+ Create(_crudRepository);
@override
- Delete? get crudDelete => Delete(_crudRepository);
+ DeleteOperation? get deleteOperation =>
+ Delete(_crudRepository);
@override
- DeleteAll? get crudDeleteAll => DeleteAll(_crudRepository);
+ ReadOperation? get readOperation =>
+ GetAll(_crudRepository);
@override
- Get? get crudGet => Get(_crudRepository);
-
- @override
- GetAll? get crudGetAll => GetAll(_crudRepository);
-
- @override
- Query? get crudQuery => Query(_crudRepository);
-
- @override
- Update? get crudUpdate => Update(_crudRepository);
-
- @override
- UpdateAll? get crudUpdateAll => UpdateAll(_crudRepository);
+ UpdateOperation? get updateOperation =>
+ Update(_crudRepository);
}
diff --git a/packages/wyatt_crud_bloc/lib/src/core/core.dart b/packages/wyatt_crud_bloc/lib/src/core/core.dart
index 1d218692..12ebcadf 100644
--- a/packages/wyatt_crud_bloc/lib/src/core/core.dart
+++ b/packages/wyatt_crud_bloc/lib/src/core/core.dart
@@ -15,3 +15,4 @@
// along with this program. If not, see .
export 'enums/where_query_type.dart';
+export 'mixins/operation.dart';
diff --git a/packages/wyatt_crud_bloc/lib/src/core/enums/where_query_type.dart b/packages/wyatt_crud_bloc/lib/src/core/enums/where_query_type.dart
index f20879e7..6a7c9bfe 100644
--- a/packages/wyatt_crud_bloc/lib/src/core/enums/where_query_type.dart
+++ b/packages/wyatt_crud_bloc/lib/src/core/enums/where_query_type.dart
@@ -14,6 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
+/// Defines different query types for WhereQuery.
enum WhereQueryType {
isEqualTo,
isNotEqualTo,
diff --git a/packages/wyatt_crud_bloc/lib/src/core/mixins/operation.dart b/packages/wyatt_crud_bloc/lib/src/core/mixins/operation.dart
new file mode 100644
index 00000000..7a1b9b09
--- /dev/null
+++ b/packages/wyatt_crud_bloc/lib/src/core/mixins/operation.dart
@@ -0,0 +1,30 @@
+// Copyright (C) 2023 WYATT GROUP
+// Please see the AUTHORS file for details.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+import 'package:wyatt_architecture/wyatt_architecture.dart';
+import 'package:wyatt_crud_bloc/src/domain/entities/object_model.dart';
+
+/// Defines every write operation in CRUD.
+mixin CreateOperation on AsyncUseCase {}
+
+/// Defines every read operation in CRUD.
+mixin ReadOperation on AsyncUseCase {}
+
+/// Defines every update operation in CRUD.
+mixin UpdateOperation on AsyncUseCase {}
+
+/// Defines every delete operation in CRUD.
+mixin DeleteOperation on AsyncUseCase {}
diff --git a/packages/wyatt_crud_bloc/lib/src/data/data_sources/local/crud_in_memory_data_source_impl.dart b/packages/wyatt_crud_bloc/lib/src/data/data_sources/local/crud_in_memory_data_source_impl.dart
index bb892251..7c2f706b 100644
--- a/packages/wyatt_crud_bloc/lib/src/data/data_sources/local/crud_in_memory_data_source_impl.dart
+++ b/packages/wyatt_crud_bloc/lib/src/data/data_sources/local/crud_in_memory_data_source_impl.dart
@@ -17,13 +17,17 @@
import 'dart:async';
import 'package:wyatt_crud_bloc/src/core/enums/where_query_type.dart';
-import 'package:wyatt_crud_bloc/src/core/extensions/num_extension.dart';
-import 'package:wyatt_crud_bloc/src/domain/data_sources/crud_data_source.dart';
+import 'package:wyatt_crud_bloc/src/domain/data_sources/data_sources.dart';
import 'package:wyatt_crud_bloc/src/domain/entities/object_model.dart';
import 'package:wyatt_crud_bloc/src/domain/entities/query.dart';
+import 'package:wyatt_type_utils/wyatt_type_utils.dart';
+/// {@template crud_in_memory_data_source_impl}
+/// A [CrudDataSource] that stores data in memory.
+/// {@endtemplate}
class CrudInMemoryDataSourceImpl
extends CrudDataSource {
+ /// {@macro crud_in_memory_data_source_impl}
CrudInMemoryDataSourceImpl({required this.toMap, Map? data})
: _data = data ?? {};
final Map _data;
diff --git a/packages/wyatt_crud_bloc/lib/src/data/data_sources/remote/crud_firestore_data_source_impl.dart b/packages/wyatt_crud_bloc/lib/src/data/data_sources/remote/crud_firestore_data_source_impl.dart
index e70ecc9c..2915f2e6 100644
--- a/packages/wyatt_crud_bloc/lib/src/data/data_sources/remote/crud_firestore_data_source_impl.dart
+++ b/packages/wyatt_crud_bloc/lib/src/data/data_sources/remote/crud_firestore_data_source_impl.dart
@@ -20,15 +20,23 @@ import 'package:wyatt_crud_bloc/src/domain/data_sources/crud_data_source.dart';
import 'package:wyatt_crud_bloc/src/domain/entities/object_model.dart';
import 'package:wyatt_crud_bloc/src/domain/entities/query.dart';
+/// {@template crud_firestore_data_source_impl}
+/// A concrete implementation of [CrudDataSource] that uses
+/// [FirebaseFirestore] as the data source.
+/// {@endtemplate}
class CrudFirestoreDataSourceImpl
extends CrudDataSource {
+ /// {@macro crud_firestore_data_source_impl}
CrudFirestoreDataSourceImpl(
String collection, {
+ /// The function that converts a [DocumentSnapshot] to a [Model].
required Model Function(
DocumentSnapshot