refactor(crud)!: migrate to wyatt architecture

This commit is contained in:
Hugo Pointcheval 2022-11-13 20:19:10 -05:00
parent f9da719b91
commit 1ccb0a540e
Signed by: hugo
GPG Key ID: A9E8E9615379254F
47 changed files with 1601 additions and 779 deletions

View File

@ -1 +1,4 @@
include: package:wyatt_analysis/analysis_options.flutter.yaml
analyzer:
exclude: "!example/**"

View File

@ -14,5 +14,4 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
export 'queries_firestore.dart';
export 'queries_interface.dart';
export 'enums/where_query_type.dart';

View File

@ -0,0 +1,29 @@
// 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 <https://www.gnu.org/licenses/>.
enum WhereQueryType {
isEqualTo,
isNotEqualTo,
isLessThan,
isLessThanOrEqualTo,
isGreaterThan,
isGreaterThanOrEqualTo,
arrayContains,
arrayContainsAny,
whereIn,
whereNotIn,
isNull,
}

View File

@ -0,0 +1,51 @@
// 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 <https://www.gnu.org/licenses/>.
extension NumExtension on num? {
bool operator <(num? other) {
if (this == null || other == null) {
return false;
}
return this < other;
}
bool operator >(num? other) {
if (this == null || other == null) {
return false;
}
return this > other;
}
bool operator <=(num? other) {
if (this == null && other == null) {
return true;
}
if (this == null || other == null) {
return false;
}
return this <= other;
}
bool operator >=(num? other) {
if (this == null && other == null) {
return true;
}
if (this == null || other == null) {
return false;
}
return this >= other;
}
}

View File

@ -1,53 +0,0 @@
// 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 <https://www.gnu.org/licenses/>.
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<T extends Model<Object?, T>> 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<T>)? onIdle;
final Widget Function(BuildContext, CrudState<T>) onLoading;
final Widget Function(BuildContext, CrudState<T>) onError;
final Widget Function(BuildContext, CrudState<T>) onSuccess;
@override
Widget build(BuildContext context) {
return BlocBuilder<CrudCubit<T>, CrudState<T>>(
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);
}
},
);
}
}

View File

@ -1,55 +0,0 @@
// 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 <https://www.gnu.org/licenses/>.
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<T extends Model<Object?, T>> extends StatelessWidget {
const CrudStreamBuilder({
Key? key,
required this.onLoading,
required this.onError,
required this.onStream,
}) : super(key: key);
final Widget Function(BuildContext, List<T?>) onStream;
final Widget Function(BuildContext, CrudState<T>) onLoading;
final Widget Function(BuildContext, CrudState<T>) onError;
@override
Widget build(BuildContext context) {
return BlocBuilder<CrudCubit<T>, CrudState<T>>(
builder: (context, state) {
if (state.stream != null) {
return StreamBuilder<List<T?>>(
stream: state.stream,
builder: (context, snapshot) {
if (snapshot.hasData) {
return onStream(context, snapshot.data!);
} else {
return onLoading(context, state);
}
},
);
} else {
return onError(context, state);
}
},
);
}
}

View File

@ -1,219 +0,0 @@
// 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 <https://www.gnu.org/licenses/>.
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<T extends Model<Object?, T>> extends Cubit<CrudState<T>> {
final CrudRepositoryInterface<T> _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<void> 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<T>());
emit(
state.copyWith(
data: data,
status: CrudStatus.success,
),
);
} catch (e) {
// TODO(hpcl): implement Exception
emit(
state.copyWith(
status: CrudStatus.failure,
errorMessage: e.toString(),
),
);
}
}
Future<void> 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<void> 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<void> get(String id) async {
emit(state.copyWith(status: CrudStatus.loading));
try {
final data = await _crudRepository.get(id);
emit(
state.copyWith(
data: [data].cast<T>(),
status: CrudStatus.success,
),
);
} catch (e) {
emit(
state.copyWith(
status: CrudStatus.failure,
errorMessage: e.toString(),
),
);
}
}
Future<void> getAll() async {
emit(state.copyWith(status: CrudStatus.loading));
try {
final data = await _crudRepository.getAll();
emit(
state.copyWith(
data: data.cast<T>(),
status: CrudStatus.success,
),
);
} catch (e) {
emit(
state.copyWith(
status: CrudStatus.failure,
errorMessage: e.toString(),
),
);
}
}
Future<void> query(List<QueryInterface> conditions) async {
emit(state.copyWith(status: CrudStatus.loading));
try {
final data = await _crudRepository.query(conditions);
emit(
state.copyWith(
data: data.cast<T>(),
status: CrudStatus.success,
),
);
} catch (e) {
emit(
state.copyWith(
status: CrudStatus.failure,
errorMessage: e.toString(),
),
);
}
}
Future<void> streamOf({String? id}) async {
emit(state.copyWith(status: CrudStatus.loading));
try {
final Stream<List<T?>> 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<void> update(
String id, {
Model? object,
Map<String, dynamic>? 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<void> updateAll(Map<String, Object?> 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(),
),
);
}
}
}

View File

@ -1,60 +0,0 @@
// 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 <https://www.gnu.org/licenses/>.
part of 'crud_cubit.dart';
enum CrudStatus {
idle,
loading,
success,
failure,
}
class CrudState<T> extends Equatable {
final CrudStatus status;
final List<T?> data;
final Stream<List<T?>>? stream;
final String? errorMessage;
const CrudState({
this.status = CrudStatus.idle,
this.data = const [],
this.stream,
this.errorMessage,
});
@override
List<Object?> get props => [status, data];
CrudState<T> copyWith({
CrudStatus? status,
List<T?>? data,
Stream<List<T?>>? stream,
String? errorMessage,
}) {
return CrudState<T>(
status: status ?? this.status,
data: data ?? this.data,
stream: stream ?? this.stream,
errorMessage: errorMessage ?? this.errorMessage,
);
}
@override
String toString() =>
// ignore: lines_longer_than_80_chars
'CrudState(status: $status, data: $data, stream: ${stream != null ? 'listening' : 'null'}, errorMessage: $errorMessage)';
}

View File

@ -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 <https://www.gnu.org/licenses/>.
export 'data_sources/data_sources.dart';
export 'repositories/repositories.dart';

View File

@ -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 <https://www.gnu.org/licenses/>.
export 'local/crud_in_memory_data_source_impl.dart';
export 'remote/crud_firestore_data_source_impl.dart';

View File

@ -0,0 +1,174 @@
// 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 <https://www.gnu.org/licenses/>.
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/entities/object_model.dart';
import 'package:wyatt_crud_bloc/src/domain/entities/query.dart';
class CrudInMemoryDataSourceImpl<Model extends ObjectModel>
extends CrudDataSource<Model> {
final Map<String, Model> _data;
final StreamController<List<Model?>> _streamData = StreamController();
final Map<String, Object?> Function(Model) toMap;
CrudInMemoryDataSourceImpl({required this.toMap, Map<String, Model>? data})
: _data = data ?? {};
@override
Future<void> create(Model object, {String? id}) async {
_data[id ?? object.id ?? ''] = object;
_streamData.add(_data.values.toList());
}
@override
Future<void> delete(String id) async {
_data.remove(id);
_streamData.add(_data.values.toList());
}
@override
Future<void> deleteAll() async {
_data.clear();
_streamData.add(_data.values.toList());
}
@override
Future<Model?> get(String id) async => _data[id];
@override
Future<List<Model?>> getAll() async => _data.values.toList();
@override
Future<List<Model?>> query(List<QueryInterface> conditions) async {
List<Model> result = _data.values.toList();
for (final c in conditions) {
if (c is WhereQuery) {
result = result.where((m) => _whereQuery(c, m)).toList();
}
if (c is LimitQuery) {
final limit = result.length - c.limit;
result = result.sublist(limit >= 0 ? limit : 0);
}
if (c is OrderByQuery) {
try {
result.sort();
} catch (_) {}
if (c.ascending) {
result = result.reversed.toList();
}
}
}
result.cast<Model>();
return result;
}
@override
Stream<List<Model?>> stream({
String? id,
List<QueryInterface>? conditions,
bool includeMetadataChanges = false,
}) =>
_streamData.stream.map((result) {
if (conditions == null) {
return result;
}
List<Model?> res = result;
for (final c in conditions) {
if (c is WhereQuery) {
res = res.where((element) => _whereQuery(c, element)).toList();
}
if (c is LimitQuery) {
res = res.sublist(res.length - c.limit);
}
if (c is OrderByQuery) {
res.sort();
if (c.ascending) {
res = res.reversed.toList();
}
}
}
return res;
}).asBroadcastStream();
@override
Future<void> update(
String id, {
Model? object,
Map<String, dynamic>? raw,
}) {
// TODO(hpcl): implement update
throw UnimplementedError();
}
@override
Future<void> updateAll(Map<String, Object?>? data) {
// TODO(hcpl): implement updateAll
throw UnimplementedError();
}
bool _whereQuery(QueryInterface condition, Model? object) {
if (object == null) {
return false;
}
final raw = toMap.call(object);
if (condition is WhereQuery) {
switch (condition.type) {
case WhereQueryType.isEqualTo:
return raw[condition.field] == condition.value;
case WhereQueryType.isNotEqualTo:
return raw[condition.field] != condition.value;
case WhereQueryType.isLessThan:
return (raw[condition.field] as num?) < (condition.value as num?);
case WhereQueryType.isLessThanOrEqualTo:
return (raw[condition.field] as num?) <= (condition.value as num?);
case WhereQueryType.isGreaterThan:
return (raw[condition.field] as num?) > (condition.value as num?);
case WhereQueryType.isGreaterThanOrEqualTo:
return (raw[condition.field] as num?) >= (condition.value as num?);
case WhereQueryType.arrayContains:
return (raw[condition.field] as List<Object>?)
?.contains(condition.value) ??
false;
case WhereQueryType.arrayContainsAny:
bool res = false;
for (final o in condition.value as List<Object>) {
res = (raw[condition.field] as List<Object>?)?.contains(o) ?? false;
}
return res;
case WhereQueryType.whereIn:
return (condition.value as List<Object>)
.contains(raw[condition.field]);
case WhereQueryType.whereNotIn:
return !(condition.value as List<Object>)
.contains(raw[condition.field]);
case WhereQueryType.isNull:
return raw[condition.field] == null;
}
}
return true;
}
}

View File

@ -0,0 +1,224 @@
// 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 <https://www.gnu.org/licenses/>.
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:wyatt_crud_bloc/src/core/enums/where_query_type.dart';
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';
class CrudFirestoreDataSourceImpl<Model extends ObjectModel, Entity>
extends CrudDataSource<Model> {
final FirebaseFirestore _firestore;
final Map<String, Object?> Function(Model, SetOptions?) _toFirestore;
late CollectionReference<Model> _collectionReference;
CrudFirestoreDataSourceImpl(
String collection, {
required Model Function(
DocumentSnapshot<Map<String, dynamic>>,
SnapshotOptions?,
)
fromFirestore,
required Map<String, Object?> Function(Model, SetOptions?) toFirestore,
FirebaseFirestore? firestore,
}) : _firestore = firestore ?? FirebaseFirestore.instance,
_toFirestore = toFirestore {
_collectionReference =
_firestore.collection(collection).withConverter<Model>(
fromFirestore: fromFirestore,
toFirestore: toFirestore,
);
}
@override
Future<void> create(Model object, {String? id}) {
if (id != null) {
return _collectionReference.doc(id).set(object);
} else {
if (object.id != null) {
return _collectionReference.doc(object.id).set(object);
}
return _collectionReference.add(object);
}
}
@override
Future<void> delete(String id) => _collectionReference.doc(id).delete();
@override
Future<void> deleteAll() async {
final batch = _firestore.batch();
final QuerySnapshot snapshots = await _collectionReference.get();
for (final DocumentSnapshot snapshot in snapshots.docs) {
batch.delete(snapshot.reference);
}
return batch.commit();
}
@override
Future<Model?> get(String id) async {
final DocumentSnapshot<Model> snapshot =
await _collectionReference.doc(id).get();
return snapshot.data();
}
@override
Future<List<Model?>> getAll() async {
final QuerySnapshot<Model> snapshots = await _collectionReference.get();
return snapshots.docs.map((snapshot) => snapshot.data()).toList();
}
@override
Future<List<Model?>> query(List<QueryInterface> conditions) async {
Query<Model> query = _collectionReference;
for (final condition in conditions) {
query = _queryParser(condition, query);
}
final QuerySnapshot<Model> snapshots = await query.get();
return snapshots.docs.map((snapshot) => snapshot.data()).toList();
}
@override
Stream<List<Model?>> stream({
String? id,
List<QueryInterface>? conditions,
bool includeMetadataChanges = false,
}) {
if (id != null) {
return _collectionReference
.doc(id)
.snapshots(
includeMetadataChanges: includeMetadataChanges,
)
.map<List<Model?>>(
(snapshot) => [snapshot.data()],
);
} else {
if (conditions != null) {
Query<Model> query = _collectionReference;
for (final condition in conditions) {
query = _queryParser(condition, query);
}
return query
.snapshots(
includeMetadataChanges: includeMetadataChanges,
)
.map(
(querySnapshot) => querySnapshot.docs
.map((snapshot) => snapshot.data())
.toList(),
);
} else {
return _collectionReference
.snapshots(
includeMetadataChanges: includeMetadataChanges,
)
.map(
(querySnapshot) => querySnapshot.docs
.map((snapshot) => snapshot.data())
.toList(),
);
}
}
}
@override
Future<void> update(
String id, {
Model? object,
Map<String, dynamic>? raw,
}) {
if (object != null) {
return _collectionReference
.doc(id)
.update(_toFirestore.call(object, null));
} else {
if (raw != null) {
return _collectionReference.doc(id).update(raw);
} else {
throw Exception('You must provide an object or a raw map');
}
}
}
@override
Future<void> updateAll(Map<String, Object?>? data) async {
if (data == null) {
throw Exception('You must provide data to update');
}
final batch = _firestore.batch();
final QuerySnapshot<Model> snapshots = await _collectionReference.get();
for (final DocumentSnapshot snapshot in snapshots.docs) {
batch.update(snapshot.reference, data);
}
return batch.commit();
}
Query<Model> _queryParser(QueryInterface condition, Object query) {
query as Query<Model>;
if (condition is WhereQuery) {
switch (condition.type) {
case WhereQueryType.isEqualTo:
return query.where(condition.field, isEqualTo: condition.value);
case WhereQueryType.isNotEqualTo:
return query.where(condition.field, isNotEqualTo: condition.value);
case WhereQueryType.isLessThan:
return query.where(condition.field, isLessThan: condition.value);
case WhereQueryType.isLessThanOrEqualTo:
return query.where(
condition.field,
isLessThanOrEqualTo: condition.value,
);
case WhereQueryType.isGreaterThan:
return query.where(condition.field, isGreaterThan: condition.value);
case WhereQueryType.isGreaterThanOrEqualTo:
return query.where(
condition.field,
isGreaterThanOrEqualTo: condition.value,
);
case WhereQueryType.arrayContains:
return query.where(condition.field, arrayContains: condition.value);
case WhereQueryType.arrayContainsAny:
return query.where(
condition.field,
arrayContainsAny: condition.value as List<Object>,
);
case WhereQueryType.whereIn:
return query.where(
condition.field,
whereIn: condition.value as List<Object>,
);
case WhereQueryType.whereNotIn:
return query.where(
condition.field,
whereNotIn: condition.value as List<Object>,
);
case WhereQueryType.isNull:
return query.where(condition.field, isNull: condition.value as bool);
}
} else if (condition is LimitQuery) {
return query.limit(condition.limit);
} else if (condition is OrderByQuery) {
return query.orderBy(
condition.field,
descending: !condition.ascending,
);
}
return query;
}
}

View File

@ -0,0 +1,105 @@
// 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 <https://www.gnu.org/licenses/>.
import 'package:wyatt_architecture/wyatt_architecture.dart';
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';
import 'package:wyatt_crud_bloc/src/domain/repositories/crud_repository.dart';
import 'package:wyatt_type_utils/wyatt_type_utils.dart';
class CrudRepositoryImpl<Model extends ObjectModel>
extends CrudRepository<Model> {
final CrudDataSource<Model> _crudDataSource;
CrudRepositoryImpl({
required CrudDataSource<Model> crudDataSource,
}) : _crudDataSource = crudDataSource;
@override
FutureResult<void> create(Model object, {String? id}) =>
Result.tryCatchAsync<void, AppException, AppException>(
() async {
await _crudDataSource.create(object, id: id);
},
(error) => error,
);
@override
FutureResult<Model?> get(String id) =>
Result.tryCatchAsync<Model?, AppException, AppException>(
() async => _crudDataSource.get(id),
(error) => error,
);
@override
FutureResult<List<Model?>> getAll() =>
Result.tryCatchAsync<List<Model?>, AppException, AppException>(
() async => _crudDataSource.getAll(),
(error) => error,
);
@override
FutureResult<void> update(
String id, {
Model? object,
Map<String, dynamic>? raw,
}) =>
Result.tryCatchAsync<void, AppException, AppException>(
() async => _crudDataSource.update(id, object: object, raw: raw),
(error) => error,
);
@override
FutureResult<void> updateAll(Map<String, Object?> raw) =>
Result.tryCatchAsync<void, AppException, AppException>(
() async => _crudDataSource.updateAll(raw),
(error) => error,
);
@override
FutureResult<void> delete(String id) =>
Result.tryCatchAsync<void, AppException, AppException>(
() async => _crudDataSource.delete(id),
(error) => error,
);
@override
FutureResult<void> deleteAll() =>
Result.tryCatchAsync<void, AppException, AppException>(
() async => _crudDataSource.deleteAll(),
(error) => error,
);
@override
FutureResult<List<Model?>> query(List<QueryInterface> conditions) =>
Result.tryCatchAsync<List<Model?>, AppException, AppException>(
() async => _crudDataSource.query(conditions),
(error) => error,
);
@override
StreamResult<List<Model?>> stream({
String? id,
List<QueryInterface>? conditions,
}) =>
_crudDataSource.stream(id: id, conditions: conditions).map((lst) {
if (lst.isNotNull) {
return Ok<List<Model?>, AppException>(lst);
}
return Err<List<Model?>, AppException>(ServerException());
});
}

View File

@ -14,5 +14,4 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
export 'model.dart';
export 'queries/queries.dart';
export 'crud_repository_impl.dart';

View File

@ -14,17 +14,33 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:wyatt_crud_bloc/src/models/model.dart';
import 'package:wyatt_crud_bloc/src/models/queries/queries_interface.dart';
import 'package:wyatt_architecture/wyatt_architecture.dart';
import 'package:wyatt_crud_bloc/src/domain/entities/query.dart';
abstract class CrudRepositoryInterface<T> {
abstract class CrudDataSource<Model> extends BaseDataSource {
Future<void> create(Model object, {String? id});
Future<Model?> get(String id);
Future<List<Model?>> getAll();
Future<void> update(
String id, {
Model? object,
Map<String, dynamic>? raw,
});
Future<void> updateAll(Map<String, Object?>? data);
Future<void> delete(String id);
Future<void> deleteAll();
Future<T?> get(String id);
Future<List<T?>> getAll();
Future<List<T?>> query(List<QueryInterface> conditions);
Stream<List<T?>> stream({String? id, List<QueryInterface>? conditions});
Future<void> update(String id, {Model? object, Map<String, dynamic>? raw});
Future<void> updateAll(Map<String, Object?> raw);
Future<List<Model?>> query(List<QueryInterface> conditions);
Stream<List<Model?>> stream({
String? id,
List<QueryInterface>? conditions,
bool includeMetadataChanges = false,
});
}

View File

@ -0,0 +1,17 @@
// 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 <https://www.gnu.org/licenses/>.
export 'crud_data_source.dart';

View File

@ -0,0 +1,20 @@
// 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 <https://www.gnu.org/licenses/>.
export 'data_sources/data_sources.dart';
export 'entities/entities.dart';
export 'repositories/repositories.dart';
export 'usecases/usecases.dart';

View File

@ -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 <https://www.gnu.org/licenses/>.
export 'object_model.dart';
export 'query.dart';

View File

@ -14,8 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
abstract class Model<O, T> {
import 'package:wyatt_architecture/wyatt_architecture.dart';
abstract class ObjectModel extends Entity {
String? get id;
Map<String, Object> toMap();
T? from(O? object);
}

View File

@ -14,44 +14,33 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:wyatt_architecture/wyatt_architecture.dart';
import 'package:wyatt_crud_bloc/src/core/enums/where_query_type.dart';
// ignore: one_member_abstracts
abstract class QueryParserInterface {
Object parser(QueryInterface condition, Object query);
abstract class QueryParser<Q> {
Q parser(QueryInterface condition, Q query);
}
abstract class QueryInterface {}
abstract class QueryInterface extends Entity {}
enum WhereQueryType {
isEqualTo,
isNotEqualTo,
isLessThan,
isLessThanOrEqualTo,
isGreaterThan,
isGreaterThanOrEqualTo,
arrayContains,
arrayContainsAny,
whereIn,
whereNotIn,
isNull,
}
abstract class WhereQueryInterface extends QueryInterface {
class WhereQuery<Value> extends QueryInterface {
final WhereQueryType type;
final String field;
final Object value;
final Value value;
WhereQueryInterface(this.type, this.field, this.value);
WhereQuery(this.type, this.field, this.value);
}
abstract class LimitQueryInterface extends QueryInterface {
class LimitQuery extends QueryInterface {
final int limit;
LimitQueryInterface(this.limit);
LimitQuery(this.limit);
}
abstract class OrderByQueryInterface extends QueryInterface {
class OrderByQuery extends QueryInterface {
final String field;
final bool ascending;
OrderByQueryInterface(this.field, {this.ascending = true});
OrderByQuery(this.field, {this.ascending = true});
}

View File

@ -0,0 +1,38 @@
// 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 <https://www.gnu.org/licenses/>.
import 'package:wyatt_architecture/wyatt_architecture.dart';
import 'package:wyatt_crud_bloc/src/domain/entities/object_model.dart';
import 'package:wyatt_crud_bloc/src/domain/entities/query.dart';
abstract class CrudRepository<Model extends ObjectModel> extends BaseRepository {
FutureResult<void> create(Model object, {String? id});
FutureResult<Model?> get(String id);
FutureResult<List<Model?>> getAll();
FutureResult<void> update(
String id, {
Model? object,
Map<String, dynamic>? raw,
});
FutureResult<void> updateAll(Map<String, Object?> raw);
FutureResult<void> delete(String id);
FutureResult<void> deleteAll();
FutureResult<List<Model?>> query(List<QueryInterface> conditions);
StreamResult<List<Model?>> stream({
String? id,
List<QueryInterface>? conditions,
});
}

View File

@ -14,5 +14,4 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
export 'crud_repository_firestore.dart';
export 'crud_repository_interface.dart';
export 'crud_repository.dart';

View File

@ -0,0 +1,29 @@
// ignore_for_file: public_member_api_docs, sort_constructors_first
// 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 <https://www.gnu.org/licenses/>.
import 'package:wyatt_architecture/wyatt_architecture.dart';
import 'package:wyatt_crud_bloc/src/domain/entities/object_model.dart';
import 'package:wyatt_crud_bloc/src/domain/repositories/crud_repository.dart';
class Create<Model extends ObjectModel> extends UseCase<Model, void> {
final CrudRepository<Model> _crudRepository;
Create(this._crudRepository);
@override
FutureResult<void> call(Model params) => _crudRepository.create(params);
}

View File

@ -0,0 +1,28 @@
// 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 <https://www.gnu.org/licenses/>.
import 'package:wyatt_architecture/wyatt_architecture.dart';
import 'package:wyatt_crud_bloc/src/domain/entities/object_model.dart';
import 'package:wyatt_crud_bloc/src/domain/repositories/crud_repository.dart';
class Delete<Model extends ObjectModel> extends UseCase<String, void> {
final CrudRepository<Model> _crudRepository;
Delete(this._crudRepository);
@override
FutureResult<void> call(String params) => _crudRepository.delete(params);
}

View File

@ -0,0 +1,28 @@
// 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 <https://www.gnu.org/licenses/>.
import 'package:wyatt_architecture/wyatt_architecture.dart';
import 'package:wyatt_crud_bloc/src/domain/entities/object_model.dart';
import 'package:wyatt_crud_bloc/src/domain/repositories/crud_repository.dart';
class DeleteAll<Model extends ObjectModel> extends UseCase<void, void> {
final CrudRepository<Model> _crudRepository;
DeleteAll(this._crudRepository);
@override
FutureResult<void> call(void params) => _crudRepository.deleteAll();
}

View File

@ -0,0 +1,28 @@
// 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 <https://www.gnu.org/licenses/>.
import 'package:wyatt_architecture/wyatt_architecture.dart';
import 'package:wyatt_crud_bloc/src/domain/entities/object_model.dart';
import 'package:wyatt_crud_bloc/src/domain/repositories/crud_repository.dart';
class Get<Model extends ObjectModel> extends UseCase<String, Model?> {
final CrudRepository<Model> _crudRepository;
Get(this._crudRepository);
@override
FutureResult<Model?> call(String params) => _crudRepository.get(params);
}

View File

@ -0,0 +1,28 @@
// 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 <https://www.gnu.org/licenses/>.
import 'package:wyatt_architecture/wyatt_architecture.dart';
import 'package:wyatt_crud_bloc/src/domain/entities/object_model.dart';
import 'package:wyatt_crud_bloc/src/domain/repositories/crud_repository.dart';
class GetAll<Model extends ObjectModel> extends UseCase<void, List<Model?>> {
final CrudRepository<Model> _crudRepository;
GetAll(this._crudRepository);
@override
FutureResult<List<Model?>> call(void params) => _crudRepository.getAll();
}

View File

@ -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 <https://www.gnu.org/licenses/>.
export 'stream_parameters.dart';
export 'update_parameters.dart';

View File

@ -0,0 +1,28 @@
// ignore_for_file: public_member_api_docs, sort_constructors_first
// 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 <https://www.gnu.org/licenses/>.
import 'package:wyatt_crud_bloc/src/domain/entities/query.dart';
class StreamParameters {
final String? id;
final List<QueryInterface>? conditions;
StreamParameters({
this.id,
this.conditions,
});
}

View File

@ -0,0 +1,28 @@
// ignore_for_file: public_member_api_docs, sort_constructors_first
// 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 <https://www.gnu.org/licenses/>.
class UpdateParameters<Model> {
final String id;
final Model? object;
final Map<String, dynamic>? raw;
UpdateParameters({
required this.id,
this.object,
this.raw,
});
}

View File

@ -0,0 +1,31 @@
// 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 <https://www.gnu.org/licenses/>.
import 'package:wyatt_architecture/wyatt_architecture.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_crud_bloc/src/domain/repositories/crud_repository.dart';
class Query<Model extends ObjectModel>
extends UseCase<List<QueryInterface>, List<Model?>> {
final CrudRepository<Model> _crudRepository;
Query(this._crudRepository);
@override
FutureResult<List<Model?>> call(List<QueryInterface> params) =>
_crudRepository.query(params);
}

View File

@ -0,0 +1,31 @@
// 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 <https://www.gnu.org/licenses/>.
// TODO(hpcl): add streamed usecase in wyatt_architecture
// import 'package:wyatt_architecture/wyatt_architecture.dart';
// import 'package:wyatt_crud_bloc/src/domain/repositories/crud_repository.dart';
// import 'package:wyatt_crud_bloc/src/domain/usecases/params/stream_parameters.dart';
// class Stream<Model extends ObjectModel> extends UseCase<StreamParameters, List<Model?>> {
// final CrudRepository<Model> _crudRepository;
// Stream(this._crudRepository);
// @override
// StreamResult<List<Model?>> call(StreamParameters params) =>
// _crudRepository.stream(id: params.id, conditions: params.conditions);
// }

View File

@ -0,0 +1,35 @@
// 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 <https://www.gnu.org/licenses/>.
import 'package:wyatt_architecture/wyatt_architecture.dart';
import 'package:wyatt_crud_bloc/src/domain/entities/object_model.dart';
import 'package:wyatt_crud_bloc/src/domain/repositories/crud_repository.dart';
import 'package:wyatt_crud_bloc/src/domain/usecases/params/update_parameters.dart';
class Update<Model extends ObjectModel>
extends UseCase<UpdateParameters<Model>, void> {
final CrudRepository<Model> _crudRepository;
Update(this._crudRepository);
@override
FutureResult<void> call(UpdateParameters<Model> params) =>
_crudRepository.update(
params.id,
object: params.object,
raw: params.raw,
);
}

View File

@ -0,0 +1,30 @@
// 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 <https://www.gnu.org/licenses/>.
import 'package:wyatt_architecture/wyatt_architecture.dart';
import 'package:wyatt_crud_bloc/src/domain/entities/object_model.dart';
import 'package:wyatt_crud_bloc/src/domain/repositories/crud_repository.dart';
class UpdateAll<Model extends ObjectModel>
extends UseCase<Map<String, Object?>, void> {
final CrudRepository<Model> _crudRepository;
UpdateAll(this._crudRepository);
@override
FutureResult<void> call(Map<String, Object?> params) =>
_crudRepository.updateAll(params);
}

View File

@ -0,0 +1,26 @@
// 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 <https://www.gnu.org/licenses/>.
export 'create.dart';
export 'delete.dart';
export 'delete_all.dart';
export 'get.dart';
export 'get_all.dart';
export 'params/params.dart';
export 'query.dart';
export 'stream.dart';
export 'update.dart';
export 'update_all.dart';

View File

@ -15,4 +15,3 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
export 'crud_builder.dart';
export 'crud_stream_builder.dart';

View File

@ -0,0 +1,88 @@
// 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 <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
import 'package:wyatt_crud_bloc/src/features/crud/cubit/crud_cubit.dart';
class CrudBuilder<I, L, S, E> extends StatelessWidget {
/// `<I, L, S, E>`
///
/// - I: the Initial State
/// - L: the Loading State
/// - S: the Success State
/// - E: the Error State
const CrudBuilder({
required this.state,
required this.builder,
required this.initialBuilder,
required this.loadingBuilder,
required this.errorBuilder,
this.unknownBuilder,
super.key,
});
/// `<CrudInitial, CrudLoading, S extends CrudSuccess, CrudError>`
///
/// - S: the Success State
///
/// For CrudStates only.
static CrudBuilder<CrudInitial, CrudLoading, CrudSuccess, CrudError>
typed<S extends CrudSuccess>({
required CrudState state,
required Widget Function(BuildContext, S) builder,
required Widget Function(BuildContext, CrudInitial) initialBuilder,
required Widget Function(BuildContext, CrudLoading) loadingBuilder,
required Widget Function(BuildContext, CrudError) errorBuilder,
Widget Function(BuildContext, Object)? unknownBuilder,
}) =>
CrudBuilder<CrudInitial, CrudLoading, S, CrudError>(
state: state,
builder: builder,
initialBuilder: initialBuilder,
loadingBuilder: loadingBuilder,
errorBuilder: errorBuilder,
unknownBuilder: unknownBuilder,
);
final Object state;
final Widget Function(BuildContext context, S state) builder;
final Widget Function(BuildContext context, I state) initialBuilder;
final Widget Function(BuildContext context, L state) loadingBuilder;
final Widget Function(BuildContext context, E state) errorBuilder;
final Widget Function(BuildContext context, Object state)? unknownBuilder;
@override
Widget build(BuildContext context) => Builder(
builder: (context) {
if (state is S) {
return builder(context, state as S);
} else if (state is E) {
return errorBuilder(context, state as E);
} else if (state is L) {
return loadingBuilder(context, state as L);
} else if (state is I) {
return initialBuilder(context, state as I);
} else {
return unknownBuilder?.call(context, state) ??
Center(
child: Text(
'Unknown state: $state',
),
);
}
},
);
}

View File

@ -0,0 +1,267 @@
// 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 <https://www.gnu.org/licenses/>.
import 'dart:async';
import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:wyatt_architecture/wyatt_architecture.dart';
import 'package:wyatt_crud_bloc/src/core/enums/where_query_type.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_crud_bloc/src/domain/usecases/create.dart';
import 'package:wyatt_crud_bloc/src/domain/usecases/delete.dart';
import 'package:wyatt_crud_bloc/src/domain/usecases/delete_all.dart';
import 'package:wyatt_crud_bloc/src/domain/usecases/get.dart';
import 'package:wyatt_crud_bloc/src/domain/usecases/get_all.dart';
import 'package:wyatt_crud_bloc/src/domain/usecases/params/update_parameters.dart';
import 'package:wyatt_crud_bloc/src/domain/usecases/query.dart';
import 'package:wyatt_crud_bloc/src/domain/usecases/update.dart';
import 'package:wyatt_crud_bloc/src/domain/usecases/update_all.dart';
part 'crud_state.dart';
abstract class CrudCubit<Model extends ObjectModel> extends Cubit<CrudState> {
Create<Model>? get crudCreate;
DeleteAll<Model>? get crudDeleteAll;
Delete<Model>? get crudDelete;
GetAll<Model>? get crudGetAll;
Get<Model>? get crudGet;
Query<Model>? get crudQuery;
UpdateAll<Model>? get crudUpdateAll;
Update<Model>? get crudUpdate;
CrudCubit() : super(CrudInitial());
FutureOr<void> create(Model model) async {
if (crudCreate != null) {
final stateCopy = state;
emit(CrudLoading());
final result = await crudCreate!.call(model);
emit(
result.fold(
(_) {
if (stateCopy is CrudLoaded<Model?>) {
return stateCopy;
}
if (stateCopy is CrudListLoaded<Model?>) {
if (stateCopy.data.isEmpty) {
return CrudListLoaded<Model?>([model]);
}
final List<Model?> lst = stateCopy.data.toList()..add(model);
return CrudListLoaded<Model?>(lst);
}
return const CrudOkReturn();
},
(error) => CrudError(error.toString()),
),
);
}
}
FutureOr<void> delete(String id) async {
if (crudDelete != null) {
final stateCopy = state;
emit(CrudLoading());
final result = await crudDelete!.call(id);
emit(
result.fold(
(_) {
if (stateCopy is CrudLoaded<Model?>) {
return stateCopy;
}
if (stateCopy is CrudListLoaded<Model?>) {
return CrudListLoaded<Model?>(
stateCopy.data.where((element) => element?.id != id).toList(),
);
}
return const CrudOkReturn();
},
(error) => CrudError(error.toString()),
),
);
}
}
FutureOr<void> deleteAll() async {
if (crudDeleteAll != null) {
final stateCopy = state;
emit(CrudLoading());
final result = await crudDeleteAll!.call(null);
emit(
result.fold(
(_) {
if (stateCopy is CrudLoaded<Model?>) {
return CrudLoaded<Model?>(null);
}
if (stateCopy is CrudListLoaded<Model?>) {
return CrudListLoaded<Model?>(const []);
}
return const CrudOkReturn();
},
(error) => CrudError(error.toString()),
),
);
}
}
FutureOr<void> get(String id) async {
if (crudGet != null) {
emit(CrudLoading());
final result = await crudGet!.call(id);
emit(
result.fold(
CrudLoaded<Model?>.new,
(error) => CrudError(error.toString()),
),
);
}
}
FutureOr<void> getAll() async {
if (crudGetAll != null) {
emit(CrudLoading());
final result = await crudGetAll!.call(null);
emit(
result.fold(
CrudListLoaded<Model?>.new,
(error) => CrudError(error.toString()),
),
);
}
}
FutureOr<void> query(List<QueryInterface> conditions) async {
if (crudQuery != null) {
emit(CrudLoading());
final result = await crudQuery!.call(conditions);
emit(
result.fold(
CrudListLoaded<Model?>.new,
(error) => CrudError(error.toString()),
),
);
}
}
FutureOr<void> update(UpdateParameters<Model> param) async {
if (crudUpdate != null) {
final stateCopy = state;
emit(CrudLoading());
final result = await crudUpdate!.call(param);
emit(
await result.foldAsync(
(_) async {
if (stateCopy is CrudLoaded<Model?>) {
if (stateCopy.data?.id == param.id) {
// Same object, need to update actual stateCopy
if (crudGet == null) {
throw ClientException(
'Need to init Get usecase to use update.',
);
}
final newVersion = await crudGet!.call(param.id);
if (newVersion.isOk) {
return CrudLoaded<Model?>(newVersion.ok);
}
}
return stateCopy;
}
if (stateCopy is CrudListLoaded<Model?>) {
final bool listContains =
stateCopy.data.any((element) => element?.id == param.id);
if (listContains) {
// Loaded objects contains the modified object.
if (crudGet == null) {
throw ClientException(
'Need to init Get usecase to use update.',
);
}
final newVersion = await crudGet!.call(param.id);
if (newVersion.isOk) {
final newList = stateCopy.data
.where(
(element) => element?.id != param.id,
)
.toList();
return CrudListLoaded<Model?>(newList + [newVersion.ok]);
}
}
return stateCopy;
}
return const CrudOkReturn();
},
(error) async => CrudError(error.toString()),
),
);
}
}
FutureOr<void> updateAll(Map<String, Object?> param) async {
if (crudUpdateAll != null) {
final stateCopy = state;
emit(CrudLoading());
final result = await crudUpdateAll!.call(param);
emit(
await result.foldAsync(
(_) async {
if (stateCopy is CrudLoaded<Model?>) {
// Same object, need to update actual stateCopy
if (crudGet == null) {
throw ClientException(
'Need to init Get usecase to use updateAll.',
);
}
final actualId = stateCopy.data?.id;
final newVersion = await crudGet!.call(actualId ?? '');
if (newVersion.isOk) {
return CrudLoaded<Model?>(newVersion.ok);
}
return stateCopy;
}
if (stateCopy is CrudListLoaded<Model?>) {
if (crudQuery == null) {
throw ClientException(
'Need to init Query usecase to use updateAll.',
);
}
// Load all id to retrieve exactly same object
// (not all because previous stateCopy can be a query result)
final List<String?> ids = stateCopy.data
.map(
(e) => e?.id,
)
.toList();
final result = await crudQuery!.call([
WhereQuery(
WhereQueryType.whereIn,
'id',
ids,
)
]);
if (result.isOk) {
return CrudListLoaded<Model?>(result.ok ?? []);
}
return stateCopy;
}
return const CrudOkReturn();
},
(error) async => CrudError(error.toString()),
),
);
}
}
}

View File

@ -0,0 +1,63 @@
// 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 <https://www.gnu.org/licenses/>.
part of 'crud_cubit.dart';
abstract class CrudState extends Equatable {
const CrudState();
@override
List<Object?> get props => [];
}
class CrudInitial extends CrudState {}
class CrudLoading extends CrudState {}
abstract class CrudSuccess extends CrudState {
const CrudSuccess();
}
class CrudOkReturn extends CrudState {
const CrudOkReturn();
}
class CrudError extends CrudState {
final String? message;
const CrudError(this.message);
@override
List<Object?> get props => [message];
}
class CrudLoaded<T> extends CrudSuccess {
final T? data;
const CrudLoaded(this.data);
@override
List<Object?> get props => [data];
}
class CrudListLoaded<T> extends CrudSuccess {
final List<T?> data;
const CrudListLoaded(this.data);
@override
List<Object> get props => [data];
}

View File

@ -0,0 +1,17 @@
// 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 <https://www.gnu.org/licenses/>.
export 'crud/crud.dart';

View File

@ -1,88 +0,0 @@
// 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 <https://www.gnu.org/licenses/>.
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:wyatt_crud_bloc/src/models/queries/queries_interface.dart';
class QueryParserFirestore implements QueryParserInterface {
@override
Query parser(QueryInterface condition, Object query) {
query as Query;
if (condition is WhereQueryInterface) {
switch (condition.type) {
case WhereQueryType.isEqualTo:
return query.where(condition.field, isEqualTo: condition.value);
case WhereQueryType.isNotEqualTo:
return query.where(condition.field, isNotEqualTo: condition.value);
case WhereQueryType.isLessThan:
return query.where(condition.field, isLessThan: condition.value);
case WhereQueryType.isLessThanOrEqualTo:
return query.where(
condition.field,
isLessThanOrEqualTo: condition.value,
);
case WhereQueryType.isGreaterThan:
return query.where(condition.field, isGreaterThan: condition.value);
case WhereQueryType.isGreaterThanOrEqualTo:
return query.where(
condition.field,
isGreaterThanOrEqualTo: condition.value,
);
case WhereQueryType.arrayContains:
return query.where(condition.field, arrayContains: condition.value);
case WhereQueryType.arrayContainsAny:
return query.where(
condition.field,
arrayContainsAny: condition.value as List<Object>,
);
case WhereQueryType.whereIn:
return query.where(
condition.field,
whereIn: condition.value as List<Object>,
);
case WhereQueryType.whereNotIn:
return query.where(
condition.field,
whereNotIn: condition.value as List<Object>,
);
case WhereQueryType.isNull:
return query.where(condition.field, isNull: condition.value as bool);
}
} else if (condition is LimitQueryInterface) {
return query.limit(condition.limit);
} else if (condition is OrderByQueryInterface) {
return query.orderBy(
condition.field,
descending: !condition.ascending,
);
}
return query;
}
}
class WhereQueryFirestore extends WhereQueryInterface {
WhereQueryFirestore(WhereQueryType type, String field, Object value)
: super(type, field, value);
}
class LimitQueryFirestore extends LimitQueryInterface {
LimitQueryFirestore(int limit) : super(limit);
}
class OrderByQueryFirestore extends OrderByQueryInterface {
OrderByQueryFirestore(String field, {bool ascending = true})
: super(field, ascending: ascending);
}

View File

@ -1,102 +0,0 @@
// 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 <https://www.gnu.org/licenses/>.
import 'package:firebase_database/firebase_database.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';
class CrudRepositoryFirebaseDatabase<T> implements CrudRepositoryInterface<T> {
final FirebaseDatabase _firebaseDatabase;
final Model<Object, T> _parser;
late DatabaseReference _rootReference;
CrudRepositoryFirebaseDatabase(
String root,
Model<Object, T> parser, {
FirebaseDatabase? firebaseDatabase,
}) : _firebaseDatabase = firebaseDatabase ?? FirebaseDatabase.instance,
_parser = parser {
_rootReference = _firebaseDatabase.ref(root);
}
@override
Future<void> create(Model object, {String? id}) {
DatabaseReference _reference = _rootReference;
if (id != null) {
_reference = _reference.child(id);
}
return _reference.set(object.toMap());
}
@override
Future<void> delete(String id) {
final DatabaseReference _reference = _rootReference.child(id);
return _reference.remove();
}
@override
Future<void> deleteAll() {
return _rootReference.remove();
}
@override
Future<T?> get(String id) async {
final DatabaseEvent _event = await _rootReference.child(id).once();
return _parser.from(_event.snapshot.value);
}
@override
Future<List<T?>> getAll() async {
final DatabaseEvent _event = await _rootReference.once();
final List<T?> _objects = [];
_event.snapshot.children.map((e) => _objects.add(_parser.from(e.value)));
return _objects;
}
@override
Future<List<T?>> query(List<QueryInterface> conditions) {
// TODO(hpcl): implement query
throw UnimplementedError();
}
@override
Stream<List<T?>> stream({String? id, List<QueryInterface>? conditions}) {
DatabaseReference _reference = _rootReference;
if (id != null) {
_reference = _reference.child(id);
}
return _reference.onValue.map((e) {
final List<T?> _objects = [];
e.snapshot.children.map((e) => _objects.add(_parser.from(e.value)));
return _objects;
});
}
@override
Future<void> update(String id, {Model? object, Map<String, dynamic>? raw}) {
// TODO(hpcl): implement update
throw UnimplementedError();
}
@override
Future<void> updateAll(Map<String, Object?> raw) {
// TODO(hpcl): implement updateAll
throw UnimplementedError();
}
}

View File

@ -1,146 +0,0 @@
// 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 <https://www.gnu.org/licenses/>.
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:wyatt_crud_bloc/src/models/model.dart';
import 'package:wyatt_crud_bloc/src/models/queries/queries_firestore.dart';
import 'package:wyatt_crud_bloc/src/models/queries/queries_interface.dart';
import 'package:wyatt_crud_bloc/src/repositories/crud_repository_interface.dart';
class CrudRepositoryFirestore<T> implements CrudRepositoryInterface<T> {
final FirebaseFirestore _firestore;
final Model<DocumentSnapshot, T> _parser;
late CollectionReference _collectionReference;
CrudRepositoryFirestore(
String collection,
Model<DocumentSnapshot, T> parser, {
FirebaseFirestore? firestore,
}) : _firestore = firestore ?? FirebaseFirestore.instance,
_parser = parser {
_collectionReference = _firestore.collection(collection);
}
@override
Future<void> create(Model object, {String? id}) {
if (id != null) {
return _collectionReference.doc(id).set(object.toMap());
} else {
return _collectionReference.add(object.toMap());
}
}
@override
Future<void> delete(String id) {
return _collectionReference.doc(id).delete();
}
@override
Future<void> deleteAll() async {
final _batch = _firestore.batch();
final QuerySnapshot snapshots = await _collectionReference.get();
for (final DocumentSnapshot snapshot in snapshots.docs) {
_batch.delete(snapshot.reference);
}
return _batch.commit();
}
@override
Future<T?> get(String id) async {
final DocumentSnapshot snapshot = await _collectionReference.doc(id).get();
return _parser.from(snapshot);
}
@override
Future<List<T?>> getAll() async {
final QuerySnapshot snapshots = await _collectionReference.get();
return snapshots.docs.map(_parser.from).toList();
}
@override
Future<List<T?>> query(List<QueryInterface> conditions) async {
Query query = _collectionReference;
for (final condition in conditions) {
query = QueryParserFirestore().parser(condition, query);
}
final QuerySnapshot snapshots = await query.get();
return snapshots.docs.map(_parser.from).toList();
}
@override
Stream<List<T?>> stream({
String? id,
List<QueryInterface>? conditions,
bool includeMetadataChanges = false,
}) {
if (id != null) {
return _collectionReference
.doc(id)
.snapshots(
includeMetadataChanges: includeMetadataChanges,
)
.map<List<T?>>(
(DocumentSnapshot snapshot) => [_parser.from(snapshot)],
);
} else {
if (conditions != null) {
Query query = _collectionReference;
for (final condition in conditions) {
query = QueryParserFirestore().parser(condition, query);
}
return query
.snapshots(
includeMetadataChanges: includeMetadataChanges,
)
.map((querySnapshot) {
return querySnapshot.docs.map(_parser.from).toList();
});
} else {
return _collectionReference
.snapshots(
includeMetadataChanges: includeMetadataChanges,
)
.map((querySnapshot) {
return querySnapshot.docs.map(_parser.from).toList();
});
}
}
}
@override
Future<void> update(String id, {Model? object, Map<String, Object?>? raw}) {
if (object != null) {
return _collectionReference.doc(id).update(object.toMap());
} else {
if (raw != null) {
return _collectionReference.doc(id).update(raw);
} else {
throw Exception('You must provide an object or a raw map');
}
}
}
@override
Future<void> updateAll(Map<String, Object?> raw) async {
final _batch = _firestore.batch();
final QuerySnapshot snapshots = await _collectionReference.get();
for (final DocumentSnapshot snapshot in snapshots.docs) {
_batch.update(snapshot.reference, raw);
}
return _batch.commit();
}
}

View File

@ -0,0 +1,20 @@
// 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 <https://www.gnu.org/licenses/>.
export 'core/core.dart';
export 'data/data.dart';
export 'domain/domain.dart';
export 'features/features.dart';

View File

@ -14,8 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
/// Create/Read/Update/Delete BLoC for Flutter
library wyatt_crud_bloc;
export 'src/crud/crud.dart';
export 'src/models/models.dart';
export 'src/repositories/repositories.dart';
export 'src/src.dart';

View File

@ -3,25 +3,32 @@ description: Create/Read/Update/Delete BLoC for Flutter
repository: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_crud_bloc
version: 0.0.2
publish_to: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub
environment:
sdk: '>=2.16.2 <3.0.0'
sdk: ">=2.17.0 <3.0.0"
flutter: ">=1.17.0"
dependencies:
flutter:
sdk: flutter
flutter_bloc: ^8.0.1
equatable: ^2.0.3
cloud_firestore: ^3.1.12
firebase_database: ^9.0.11
flutter_bloc: ^8.1.1
equatable: ^2.0.5
cloud_firestore: ^4.0.5
wyatt_architecture:
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/
version: 0.0.2
wyatt_type_utils:
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/
version: 0.0.3+1
dev_dependencies:
flutter_test:
sdk: flutter
bloc_test: ^9.0.3
bloc_test: ^9.1.0
wyatt_analysis:
git:
url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages
ref: wyatt_analysis-v2.2.2
path: packages/wyatt_analysis
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/
version: 2.2.2