diff --git a/packages/wyatt_crud_bloc/.gitignore b/packages/wyatt_crud_bloc/.gitignore
new file mode 100644
index 00000000..65c34dc8
--- /dev/null
+++ b/packages/wyatt_crud_bloc/.gitignore
@@ -0,0 +1,10 @@
+# Files and directories created by pub.
+.dart_tool/
+.packages
+
+# Conventional directory for build outputs.
+build/
+
+# Omit committing pubspec.lock for library packages; see
+# https://dart.dev/guides/libraries/private-files#pubspeclock.
+pubspec.lock
diff --git a/packages/wyatt_crud_bloc/CHANGELOG.md b/packages/wyatt_crud_bloc/CHANGELOG.md
new file mode 100644
index 00000000..effe43c8
--- /dev/null
+++ b/packages/wyatt_crud_bloc/CHANGELOG.md
@@ -0,0 +1,3 @@
+## 1.0.0
+
+- Initial version.
diff --git a/packages/wyatt_crud_bloc/README.md b/packages/wyatt_crud_bloc/README.md
new file mode 100644
index 00000000..8b55e735
--- /dev/null
+++ b/packages/wyatt_crud_bloc/README.md
@@ -0,0 +1,39 @@
+
+
+TODO: Put a short description of the package here that helps potential users
+know whether this package might be useful for them.
+
+## Features
+
+TODO: List what your package can do. Maybe include images, gifs, or videos.
+
+## Getting started
+
+TODO: List prerequisites and provide or point to information on how to
+start using the package.
+
+## Usage
+
+TODO: Include short and useful examples for package users. Add longer examples
+to `/example` folder.
+
+```dart
+const like = 'sample';
+```
+
+## Additional information
+
+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.
diff --git a/packages/wyatt_crud_bloc/analysis_options.yaml b/packages/wyatt_crud_bloc/analysis_options.yaml
new file mode 100644
index 00000000..8c9daa4e
--- /dev/null
+++ b/packages/wyatt_crud_bloc/analysis_options.yaml
@@ -0,0 +1 @@
+include: package:wyatt_analysis/analysis_options.flutter.yaml
diff --git a/packages/wyatt_crud_bloc/lib/src/crud/builder/builder.dart b/packages/wyatt_crud_bloc/lib/src/crud/builder/builder.dart
new file mode 100644
index 00000000..032fa805
--- /dev/null
+++ b/packages/wyatt_crud_bloc/lib/src/crud/builder/builder.dart
@@ -0,0 +1,18 @@
+// Copyright (C) 2022 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 .
+
+export 'crud_builder.dart';
+export 'crud_stream_builder.dart';
diff --git a/packages/wyatt_crud_bloc/lib/src/crud/builder/crud_builder.dart b/packages/wyatt_crud_bloc/lib/src/crud/builder/crud_builder.dart
new file mode 100644
index 00000000..d2c227bf
--- /dev/null
+++ b/packages/wyatt_crud_bloc/lib/src/crud/builder/crud_builder.dart
@@ -0,0 +1,53 @@
+// Copyright (C) 2022 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:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:wyatt_crud_bloc/src/crud/cubit/crud_cubit.dart';
+import 'package:wyatt_crud_bloc/src/models/model.dart';
+
+class CrudBuilder> extends StatelessWidget {
+ const CrudBuilder({
+ Key? key,
+ this.onIdle,
+ required this.onLoading,
+ required this.onError,
+ required this.onSuccess,
+ }) : super(key: key);
+
+ final Widget Function(BuildContext, CrudState)? onIdle;
+ final Widget Function(BuildContext, CrudState) onLoading;
+ final Widget Function(BuildContext, CrudState) onError;
+ final Widget Function(BuildContext, CrudState) onSuccess;
+
+ @override
+ Widget build(BuildContext context) {
+ return BlocBuilder, CrudState>(
+ builder: (context, state) {
+ switch (state.status) {
+ case CrudStatus.idle:
+ return onIdle?.call(context, state) ?? onError.call(context, state);
+ case CrudStatus.loading:
+ return onLoading.call(context, state);
+ case CrudStatus.failure:
+ return onError.call(context, state);
+ case CrudStatus.success:
+ return onSuccess.call(context, state);
+ }
+ },
+ );
+ }
+}
diff --git a/packages/wyatt_crud_bloc/lib/src/crud/builder/crud_stream_builder.dart b/packages/wyatt_crud_bloc/lib/src/crud/builder/crud_stream_builder.dart
new file mode 100644
index 00000000..743b63e7
--- /dev/null
+++ b/packages/wyatt_crud_bloc/lib/src/crud/builder/crud_stream_builder.dart
@@ -0,0 +1,55 @@
+// Copyright (C) 2022 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:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:wyatt_crud_bloc/src/crud/cubit/crud_cubit.dart';
+import 'package:wyatt_crud_bloc/src/models/model.dart';
+
+class CrudStreamBuilder> extends StatelessWidget {
+ const CrudStreamBuilder({
+ Key? key,
+ required this.onLoading,
+ required this.onError,
+ required this.onStream,
+ }) : super(key: key);
+
+ final Widget Function(BuildContext, List) onStream;
+ final Widget Function(BuildContext, CrudState) onLoading;
+ final Widget Function(BuildContext, CrudState) onError;
+
+ @override
+ Widget build(BuildContext context) {
+ return BlocBuilder, CrudState>(
+ builder: (context, state) {
+ if (state.stream != null) {
+ return StreamBuilder>(
+ stream: state.stream,
+ builder: (context, snapshot) {
+ if (snapshot.hasData) {
+ return onStream(context, snapshot.data!);
+ } else {
+ return onLoading(context, state);
+ }
+ },
+ );
+ } else {
+ return onError(context, state);
+ }
+ },
+ );
+ }
+}
diff --git a/packages/wyatt_crud_bloc/lib/src/crud/crud.dart b/packages/wyatt_crud_bloc/lib/src/crud/crud.dart
new file mode 100644
index 00000000..cb18407c
--- /dev/null
+++ b/packages/wyatt_crud_bloc/lib/src/crud/crud.dart
@@ -0,0 +1,18 @@
+// Copyright (C) 2022 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 .
+
+export 'builder/builder.dart';
+export 'cubit/crud_cubit.dart';
diff --git a/packages/wyatt_crud_bloc/lib/src/crud/cubit/crud_cubit.dart b/packages/wyatt_crud_bloc/lib/src/crud/cubit/crud_cubit.dart
new file mode 100644
index 00000000..6a73d408
--- /dev/null
+++ b/packages/wyatt_crud_bloc/lib/src/crud/cubit/crud_cubit.dart
@@ -0,0 +1,219 @@
+// Copyright (C) 2022 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:bloc/bloc.dart';
+import 'package:equatable/equatable.dart';
+import 'package:wyatt_crud_bloc/src/models/model.dart';
+import 'package:wyatt_crud_bloc/src/models/queries/queries_interface.dart';
+import 'package:wyatt_crud_bloc/src/repositories/crud_repository_interface.dart';
+
+part 'crud_state.dart';
+
+class CrudCubit> extends Cubit> {
+ final CrudRepositoryInterface _crudRepository;
+
+ // ignore: prefer_const_constructors
+ CrudCubit(this._crudRepository) : super(CrudState());
+ // Here we can't use `const` because we need the generic type T
+
+ void reset() {
+ // ignore: prefer_const_constructors
+ emit(CrudState());
+ // Same here, because of `const` we can't use T generic type
+ }
+
+ Future create(Model object, {String? id}) async {
+ emit(state.copyWith(status: CrudStatus.loading));
+ try {
+ await _crudRepository.create(object, id: id);
+ final data = state.data..addAll([object].cast());
+ emit(
+ state.copyWith(
+ data: data,
+ status: CrudStatus.success,
+ ),
+ );
+ } catch (e) {
+ // TODO(hpcl): implement Exception
+ emit(
+ state.copyWith(
+ status: CrudStatus.failure,
+ errorMessage: e.toString(),
+ ),
+ );
+ }
+ }
+
+ Future delete(String id) async {
+ emit(state.copyWith(status: CrudStatus.loading));
+ try {
+ await _crudRepository.delete(id);
+ final data = state.data
+ ..removeWhere((element) => element!.id != null && element.id == id);
+ emit(
+ state.copyWith(
+ data: data,
+ status: CrudStatus.success,
+ ),
+ );
+ } catch (e) {
+ emit(
+ state.copyWith(
+ status: CrudStatus.failure,
+ errorMessage: e.toString(),
+ ),
+ );
+ }
+ }
+
+ Future deleteAll() async {
+ emit(state.copyWith(status: CrudStatus.loading));
+ try {
+ await _crudRepository.deleteAll();
+ emit(
+ state.copyWith(
+ data: [],
+ status: CrudStatus.success,
+ ),
+ );
+ } catch (e) {
+ emit(
+ state.copyWith(
+ status: CrudStatus.failure,
+ errorMessage: e.toString(),
+ ),
+ );
+ }
+ }
+
+ Future get(String id) async {
+ emit(state.copyWith(status: CrudStatus.loading));
+ try {
+ final data = await _crudRepository.get(id);
+ emit(
+ state.copyWith(
+ data: [data].cast(),
+ status: CrudStatus.success,
+ ),
+ );
+ } catch (e) {
+ emit(
+ state.copyWith(
+ status: CrudStatus.failure,
+ errorMessage: e.toString(),
+ ),
+ );
+ }
+ }
+
+ Future getAll() async {
+ emit(state.copyWith(status: CrudStatus.loading));
+ try {
+ final data = await _crudRepository.getAll();
+ emit(
+ state.copyWith(
+ data: data.cast(),
+ status: CrudStatus.success,
+ ),
+ );
+ } catch (e) {
+ emit(
+ state.copyWith(
+ status: CrudStatus.failure,
+ errorMessage: e.toString(),
+ ),
+ );
+ }
+ }
+
+ Future query(List conditions) async {
+ emit(state.copyWith(status: CrudStatus.loading));
+ try {
+ final data = await _crudRepository.query(conditions);
+ emit(
+ state.copyWith(
+ data: data.cast(),
+ status: CrudStatus.success,
+ ),
+ );
+ } catch (e) {
+ emit(
+ state.copyWith(
+ status: CrudStatus.failure,
+ errorMessage: e.toString(),
+ ),
+ );
+ }
+ }
+
+ Future streamOf({String? id}) async {
+ emit(state.copyWith(status: CrudStatus.loading));
+ try {
+ final Stream> data = _crudRepository.stream(id: id);
+ emit(
+ state.copyWith(
+ stream: data,
+ status: CrudStatus.success,
+ ),
+ );
+ } catch (e) {
+ emit(
+ state.copyWith(
+ status: CrudStatus.failure,
+ errorMessage: e.toString(),
+ ),
+ );
+ }
+ }
+
+ Future update(
+ String id, {
+ Model? object,
+ Map? raw,
+ }) async {
+ emit(state.copyWith(status: CrudStatus.loading));
+ try {
+ await _crudRepository.update(
+ id,
+ object: object,
+ raw: raw,
+ );
+ emit(state.copyWith(status: CrudStatus.success));
+ } catch (e) {
+ emit(
+ state.copyWith(
+ status: CrudStatus.failure,
+ errorMessage: e.toString(),
+ ),
+ );
+ }
+ }
+
+ Future updateAll(Map raw) async {
+ emit(state.copyWith(status: CrudStatus.loading));
+ try {
+ await _crudRepository.updateAll(raw);
+ emit(state.copyWith(status: CrudStatus.success));
+ } catch (e) {
+ emit(
+ state.copyWith(
+ status: CrudStatus.failure,
+ errorMessage: e.toString(),
+ ),
+ );
+ }
+ }
+}
diff --git a/packages/wyatt_crud_bloc/lib/src/crud/cubit/crud_state.dart b/packages/wyatt_crud_bloc/lib/src/crud/cubit/crud_state.dart
new file mode 100644
index 00000000..cd724eb4
--- /dev/null
+++ b/packages/wyatt_crud_bloc/lib/src/crud/cubit/crud_state.dart
@@ -0,0 +1,60 @@
+// Copyright (C) 2022 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 .
+
+part of 'crud_cubit.dart';
+
+enum CrudStatus {
+ idle,
+ loading,
+ success,
+ failure,
+}
+
+class CrudState extends Equatable {
+ final CrudStatus status;
+ final List data;
+ final Stream>? stream;
+ final String? errorMessage;
+
+ const CrudState({
+ this.status = CrudStatus.idle,
+ this.data = const [],
+ this.stream,
+ this.errorMessage,
+ });
+
+ @override
+ List