diff --git a/packages/wyatt_crud_bloc/analysis_options.yaml b/packages/wyatt_crud_bloc/analysis_options.yaml index 8c9daa4e..f09fbccc 100644 --- a/packages/wyatt_crud_bloc/analysis_options.yaml +++ b/packages/wyatt_crud_bloc/analysis_options.yaml @@ -1 +1,4 @@ include: package:wyatt_analysis/analysis_options.flutter.yaml + +analyzer: + exclude: "!example/**" diff --git a/packages/wyatt_crud_bloc/lib/src/models/queries/queries.dart b/packages/wyatt_crud_bloc/lib/src/core/core.dart similarity index 91% rename from packages/wyatt_crud_bloc/lib/src/models/queries/queries.dart rename to packages/wyatt_crud_bloc/lib/src/core/core.dart index 7b786e30..1d218692 100644 --- a/packages/wyatt_crud_bloc/lib/src/models/queries/queries.dart +++ b/packages/wyatt_crud_bloc/lib/src/core/core.dart @@ -14,5 +14,4 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -export 'queries_firestore.dart'; -export 'queries_interface.dart'; +export 'enums/where_query_type.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 new file mode 100644 index 00000000..f20879e7 --- /dev/null +++ b/packages/wyatt_crud_bloc/lib/src/core/enums/where_query_type.dart @@ -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 . + +enum WhereQueryType { + isEqualTo, + isNotEqualTo, + isLessThan, + isLessThanOrEqualTo, + isGreaterThan, + isGreaterThanOrEqualTo, + arrayContains, + arrayContainsAny, + whereIn, + whereNotIn, + isNull, +} diff --git a/packages/wyatt_crud_bloc/lib/src/core/extensions/num_extension.dart b/packages/wyatt_crud_bloc/lib/src/core/extensions/num_extension.dart new file mode 100644 index 00000000..abe45b91 --- /dev/null +++ b/packages/wyatt_crud_bloc/lib/src/core/extensions/num_extension.dart @@ -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 . + +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; + } +} 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 deleted file mode 100644 index d2c227bf..00000000 --- a/packages/wyatt_crud_bloc/lib/src/crud/builder/crud_builder.dart +++ /dev/null @@ -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 . - -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 deleted file mode 100644 index 743b63e7..00000000 --- a/packages/wyatt_crud_bloc/lib/src/crud/builder/crud_stream_builder.dart +++ /dev/null @@ -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 . - -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/cubit/crud_cubit.dart b/packages/wyatt_crud_bloc/lib/src/crud/cubit/crud_cubit.dart deleted file mode 100644 index 6a73d408..00000000 --- a/packages/wyatt_crud_bloc/lib/src/crud/cubit/crud_cubit.dart +++ /dev/null @@ -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 . - -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 deleted file mode 100644 index cd724eb4..00000000 --- a/packages/wyatt_crud_bloc/lib/src/crud/cubit/crud_state.dart +++ /dev/null @@ -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 . - -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 get props => [status, data]; - - CrudState copyWith({ - CrudStatus? status, - List? data, - Stream>? stream, - String? errorMessage, - }) { - return CrudState( - 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)'; -} diff --git a/packages/wyatt_crud_bloc/lib/src/data/data.dart b/packages/wyatt_crud_bloc/lib/src/data/data.dart new file mode 100644 index 00000000..ad1ef342 --- /dev/null +++ b/packages/wyatt_crud_bloc/lib/src/data/data.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 'data_sources/data_sources.dart'; +export 'repositories/repositories.dart'; diff --git a/packages/wyatt_crud_bloc/lib/src/data/data_sources/data_sources.dart b/packages/wyatt_crud_bloc/lib/src/data/data_sources/data_sources.dart new file mode 100644 index 00000000..845ccb50 --- /dev/null +++ b/packages/wyatt_crud_bloc/lib/src/data/data_sources/data_sources.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 'local/crud_in_memory_data_source_impl.dart'; +export 'remote/crud_firestore_data_source_impl.dart'; 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 new file mode 100644 index 00000000..63fe3de4 --- /dev/null +++ b/packages/wyatt_crud_bloc/lib/src/data/data_sources/local/crud_in_memory_data_source_impl.dart @@ -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 . + +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 + extends CrudDataSource { + final Map _data; + final StreamController> _streamData = StreamController(); + + final Map Function(Model) toMap; + + CrudInMemoryDataSourceImpl({required this.toMap, Map? data}) + : _data = data ?? {}; + + @override + Future create(Model object, {String? id}) async { + _data[id ?? object.id ?? ''] = object; + _streamData.add(_data.values.toList()); + } + + @override + Future delete(String id) async { + _data.remove(id); + _streamData.add(_data.values.toList()); + } + + @override + Future deleteAll() async { + _data.clear(); + _streamData.add(_data.values.toList()); + } + + @override + Future get(String id) async => _data[id]; + + @override + Future> getAll() async => _data.values.toList(); + + @override + Future> query(List conditions) async { + List 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(); + + return result; + } + + @override + Stream> stream({ + String? id, + List? conditions, + bool includeMetadataChanges = false, + }) => + _streamData.stream.map((result) { + if (conditions == null) { + return result; + } + + List 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 update( + String id, { + Model? object, + Map? raw, + }) { + // TODO(hpcl): implement update + throw UnimplementedError(); + } + + @override + Future updateAll(Map? 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?) + ?.contains(condition.value) ?? + false; + case WhereQueryType.arrayContainsAny: + bool res = false; + for (final o in condition.value as List) { + res = (raw[condition.field] as List?)?.contains(o) ?? false; + } + return res; + case WhereQueryType.whereIn: + return (condition.value as List) + .contains(raw[condition.field]); + case WhereQueryType.whereNotIn: + return !(condition.value as List) + .contains(raw[condition.field]); + case WhereQueryType.isNull: + return raw[condition.field] == null; + } + } + return true; + } +} 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 new file mode 100644 index 00000000..2b8fd504 --- /dev/null +++ b/packages/wyatt_crud_bloc/lib/src/data/data_sources/remote/crud_firestore_data_source_impl.dart @@ -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 . + +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 + extends CrudDataSource { + final FirebaseFirestore _firestore; + + final Map Function(Model, SetOptions?) _toFirestore; + late CollectionReference _collectionReference; + + CrudFirestoreDataSourceImpl( + String collection, { + required Model Function( + DocumentSnapshot>, + SnapshotOptions?, + ) + fromFirestore, + required Map Function(Model, SetOptions?) toFirestore, + FirebaseFirestore? firestore, + }) : _firestore = firestore ?? FirebaseFirestore.instance, + _toFirestore = toFirestore { + _collectionReference = + _firestore.collection(collection).withConverter( + fromFirestore: fromFirestore, + toFirestore: toFirestore, + ); + } + + @override + Future 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 delete(String id) => _collectionReference.doc(id).delete(); + + @override + Future 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 get(String id) async { + final DocumentSnapshot snapshot = + await _collectionReference.doc(id).get(); + return snapshot.data(); + } + + @override + Future> getAll() async { + final QuerySnapshot snapshots = await _collectionReference.get(); + return snapshots.docs.map((snapshot) => snapshot.data()).toList(); + } + + @override + Future> query(List conditions) async { + Query query = _collectionReference; + for (final condition in conditions) { + query = _queryParser(condition, query); + } + final QuerySnapshot snapshots = await query.get(); + return snapshots.docs.map((snapshot) => snapshot.data()).toList(); + } + + @override + Stream> stream({ + String? id, + List? conditions, + bool includeMetadataChanges = false, + }) { + if (id != null) { + return _collectionReference + .doc(id) + .snapshots( + includeMetadataChanges: includeMetadataChanges, + ) + .map>( + (snapshot) => [snapshot.data()], + ); + } else { + if (conditions != null) { + Query 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 update( + String id, { + Model? object, + Map? 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 updateAll(Map? data) async { + if (data == null) { + throw Exception('You must provide data to update'); + } + final batch = _firestore.batch(); + final QuerySnapshot snapshots = await _collectionReference.get(); + for (final DocumentSnapshot snapshot in snapshots.docs) { + batch.update(snapshot.reference, data); + } + return batch.commit(); + } + + Query _queryParser(QueryInterface condition, Object query) { + query as Query; + 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, + ); + case WhereQueryType.whereIn: + return query.where( + condition.field, + whereIn: condition.value as List, + ); + case WhereQueryType.whereNotIn: + return query.where( + condition.field, + whereNotIn: condition.value as List, + ); + 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; + } +} diff --git a/packages/wyatt_crud_bloc/lib/src/data/repositories/crud_repository_impl.dart b/packages/wyatt_crud_bloc/lib/src/data/repositories/crud_repository_impl.dart new file mode 100644 index 00000000..e641fa6a --- /dev/null +++ b/packages/wyatt_crud_bloc/lib/src/data/repositories/crud_repository_impl.dart @@ -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 . + +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 + extends CrudRepository { + final CrudDataSource _crudDataSource; + + CrudRepositoryImpl({ + required CrudDataSource crudDataSource, + }) : _crudDataSource = crudDataSource; + + @override + FutureResult create(Model object, {String? id}) => + Result.tryCatchAsync( + () async { + await _crudDataSource.create(object, id: id); + }, + (error) => error, + ); + + @override + FutureResult get(String id) => + Result.tryCatchAsync( + () async => _crudDataSource.get(id), + (error) => error, + ); + + @override + FutureResult> getAll() => + Result.tryCatchAsync, AppException, AppException>( + () async => _crudDataSource.getAll(), + (error) => error, + ); + + @override + FutureResult update( + String id, { + Model? object, + Map? raw, + }) => + Result.tryCatchAsync( + () async => _crudDataSource.update(id, object: object, raw: raw), + (error) => error, + ); + + @override + FutureResult updateAll(Map raw) => + Result.tryCatchAsync( + () async => _crudDataSource.updateAll(raw), + (error) => error, + ); + + @override + FutureResult delete(String id) => + Result.tryCatchAsync( + () async => _crudDataSource.delete(id), + (error) => error, + ); + + @override + FutureResult deleteAll() => + Result.tryCatchAsync( + () async => _crudDataSource.deleteAll(), + (error) => error, + ); + + @override + FutureResult> query(List conditions) => + Result.tryCatchAsync, AppException, AppException>( + () async => _crudDataSource.query(conditions), + (error) => error, + ); + + @override + StreamResult> stream({ + String? id, + List? conditions, + }) => + _crudDataSource.stream(id: id, conditions: conditions).map((lst) { + if (lst.isNotNull) { + return Ok, AppException>(lst); + } + return Err, AppException>(ServerException()); + }); +} diff --git a/packages/wyatt_crud_bloc/lib/src/models/models.dart b/packages/wyatt_crud_bloc/lib/src/data/repositories/repositories.dart similarity index 93% rename from packages/wyatt_crud_bloc/lib/src/models/models.dart rename to packages/wyatt_crud_bloc/lib/src/data/repositories/repositories.dart index 4cff0335..bf40c523 100644 --- a/packages/wyatt_crud_bloc/lib/src/models/models.dart +++ b/packages/wyatt_crud_bloc/lib/src/data/repositories/repositories.dart @@ -14,5 +14,4 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -export 'model.dart'; -export 'queries/queries.dart'; +export 'crud_repository_impl.dart'; diff --git a/packages/wyatt_crud_bloc/lib/src/repositories/crud_repository_interface.dart b/packages/wyatt_crud_bloc/lib/src/domain/data_sources/crud_data_source.dart similarity index 57% rename from packages/wyatt_crud_bloc/lib/src/repositories/crud_repository_interface.dart rename to packages/wyatt_crud_bloc/lib/src/domain/data_sources/crud_data_source.dart index 15eb3054..95defb4c 100644 --- a/packages/wyatt_crud_bloc/lib/src/repositories/crud_repository_interface.dart +++ b/packages/wyatt_crud_bloc/lib/src/domain/data_sources/crud_data_source.dart @@ -14,17 +14,33 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -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 { +abstract class CrudDataSource extends BaseDataSource { Future create(Model object, {String? id}); + + Future get(String id); + + Future> getAll(); + + Future update( + String id, { + Model? object, + Map? raw, + }); + + Future updateAll(Map? data); + Future delete(String id); + Future deleteAll(); - Future get(String id); - Future> getAll(); - Future> query(List conditions); - Stream> stream({String? id, List? conditions}); - Future update(String id, {Model? object, Map? raw}); - Future updateAll(Map raw); + + Future> query(List conditions); + + Stream> stream({ + String? id, + List? conditions, + bool includeMetadataChanges = false, + }); } diff --git a/packages/wyatt_crud_bloc/lib/src/domain/data_sources/data_sources.dart b/packages/wyatt_crud_bloc/lib/src/domain/data_sources/data_sources.dart new file mode 100644 index 00000000..8495ee03 --- /dev/null +++ b/packages/wyatt_crud_bloc/lib/src/domain/data_sources/data_sources.dart @@ -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 . + +export 'crud_data_source.dart'; diff --git a/packages/wyatt_crud_bloc/lib/src/domain/domain.dart b/packages/wyatt_crud_bloc/lib/src/domain/domain.dart new file mode 100644 index 00000000..a02a23f3 --- /dev/null +++ b/packages/wyatt_crud_bloc/lib/src/domain/domain.dart @@ -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 . + +export 'data_sources/data_sources.dart'; +export 'entities/entities.dart'; +export 'repositories/repositories.dart'; +export 'usecases/usecases.dart'; diff --git a/packages/wyatt_crud_bloc/lib/src/domain/entities/entities.dart b/packages/wyatt_crud_bloc/lib/src/domain/entities/entities.dart new file mode 100644 index 00000000..bd9cb1f9 --- /dev/null +++ b/packages/wyatt_crud_bloc/lib/src/domain/entities/entities.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 'object_model.dart'; +export 'query.dart'; diff --git a/packages/wyatt_crud_bloc/lib/src/models/model.dart b/packages/wyatt_crud_bloc/lib/src/domain/entities/object_model.dart similarity index 87% rename from packages/wyatt_crud_bloc/lib/src/models/model.dart rename to packages/wyatt_crud_bloc/lib/src/domain/entities/object_model.dart index fc590712..2b419e41 100644 --- a/packages/wyatt_crud_bloc/lib/src/models/model.dart +++ b/packages/wyatt_crud_bloc/lib/src/domain/entities/object_model.dart @@ -14,8 +14,8 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -abstract class Model { +import 'package:wyatt_architecture/wyatt_architecture.dart'; + +abstract class ObjectModel extends Entity { String? get id; - Map toMap(); - T? from(O? object); } diff --git a/packages/wyatt_crud_bloc/lib/src/models/queries/queries_interface.dart b/packages/wyatt_crud_bloc/lib/src/domain/entities/query.dart similarity index 55% rename from packages/wyatt_crud_bloc/lib/src/models/queries/queries_interface.dart rename to packages/wyatt_crud_bloc/lib/src/domain/entities/query.dart index 01e8ea15..c95d1cda 100644 --- a/packages/wyatt_crud_bloc/lib/src/models/queries/queries_interface.dart +++ b/packages/wyatt_crud_bloc/lib/src/domain/entities/query.dart @@ -14,44 +14,33 @@ // 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/core/enums/where_query_type.dart'; + // ignore: one_member_abstracts -abstract class QueryParserInterface { - Object parser(QueryInterface condition, Object query); +abstract class QueryParser { + 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 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}); } diff --git a/packages/wyatt_crud_bloc/lib/src/domain/repositories/crud_repository.dart b/packages/wyatt_crud_bloc/lib/src/domain/repositories/crud_repository.dart new file mode 100644 index 00000000..be2bde0f --- /dev/null +++ b/packages/wyatt_crud_bloc/lib/src/domain/repositories/crud_repository.dart @@ -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 . + +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 extends BaseRepository { + FutureResult create(Model object, {String? id}); + FutureResult get(String id); + FutureResult> getAll(); + FutureResult update( + String id, { + Model? object, + Map? raw, + }); + FutureResult updateAll(Map raw); + FutureResult delete(String id); + FutureResult deleteAll(); + FutureResult> query(List conditions); + StreamResult> stream({ + String? id, + List? conditions, + }); +} diff --git a/packages/wyatt_crud_bloc/lib/src/repositories/repositories.dart b/packages/wyatt_crud_bloc/lib/src/domain/repositories/repositories.dart similarity index 89% rename from packages/wyatt_crud_bloc/lib/src/repositories/repositories.dart rename to packages/wyatt_crud_bloc/lib/src/domain/repositories/repositories.dart index aa0511e6..decedffe 100644 --- a/packages/wyatt_crud_bloc/lib/src/repositories/repositories.dart +++ b/packages/wyatt_crud_bloc/lib/src/domain/repositories/repositories.dart @@ -14,5 +14,4 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -export 'crud_repository_firestore.dart'; -export 'crud_repository_interface.dart'; +export 'crud_repository.dart'; diff --git a/packages/wyatt_crud_bloc/lib/src/domain/usecases/create.dart b/packages/wyatt_crud_bloc/lib/src/domain/usecases/create.dart new file mode 100644 index 00000000..35943bd9 --- /dev/null +++ b/packages/wyatt_crud_bloc/lib/src/domain/usecases/create.dart @@ -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 . + +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 extends UseCase { + final CrudRepository _crudRepository; + + Create(this._crudRepository); + + @override + FutureResult call(Model params) => _crudRepository.create(params); +} diff --git a/packages/wyatt_crud_bloc/lib/src/domain/usecases/delete.dart b/packages/wyatt_crud_bloc/lib/src/domain/usecases/delete.dart new file mode 100644 index 00000000..df706dad --- /dev/null +++ b/packages/wyatt_crud_bloc/lib/src/domain/usecases/delete.dart @@ -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 . + +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 extends UseCase { + final CrudRepository _crudRepository; + + Delete(this._crudRepository); + + @override + FutureResult call(String params) => _crudRepository.delete(params); +} diff --git a/packages/wyatt_crud_bloc/lib/src/domain/usecases/delete_all.dart b/packages/wyatt_crud_bloc/lib/src/domain/usecases/delete_all.dart new file mode 100644 index 00000000..2151cde1 --- /dev/null +++ b/packages/wyatt_crud_bloc/lib/src/domain/usecases/delete_all.dart @@ -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 . + +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 extends UseCase { + final CrudRepository _crudRepository; + + DeleteAll(this._crudRepository); + + @override + FutureResult call(void params) => _crudRepository.deleteAll(); +} diff --git a/packages/wyatt_crud_bloc/lib/src/domain/usecases/get.dart b/packages/wyatt_crud_bloc/lib/src/domain/usecases/get.dart new file mode 100644 index 00000000..f778e0a2 --- /dev/null +++ b/packages/wyatt_crud_bloc/lib/src/domain/usecases/get.dart @@ -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 . + +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 extends UseCase { + final CrudRepository _crudRepository; + + Get(this._crudRepository); + + @override + FutureResult call(String params) => _crudRepository.get(params); +} diff --git a/packages/wyatt_crud_bloc/lib/src/domain/usecases/get_all.dart b/packages/wyatt_crud_bloc/lib/src/domain/usecases/get_all.dart new file mode 100644 index 00000000..6797c37c --- /dev/null +++ b/packages/wyatt_crud_bloc/lib/src/domain/usecases/get_all.dart @@ -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 . + +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 extends UseCase> { + final CrudRepository _crudRepository; + + GetAll(this._crudRepository); + + @override + FutureResult> call(void params) => _crudRepository.getAll(); +} diff --git a/packages/wyatt_crud_bloc/lib/src/domain/usecases/params/params.dart b/packages/wyatt_crud_bloc/lib/src/domain/usecases/params/params.dart new file mode 100644 index 00000000..3b67e551 --- /dev/null +++ b/packages/wyatt_crud_bloc/lib/src/domain/usecases/params/params.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 'stream_parameters.dart'; +export 'update_parameters.dart'; diff --git a/packages/wyatt_crud_bloc/lib/src/domain/usecases/params/stream_parameters.dart b/packages/wyatt_crud_bloc/lib/src/domain/usecases/params/stream_parameters.dart new file mode 100644 index 00000000..6a3cfa0e --- /dev/null +++ b/packages/wyatt_crud_bloc/lib/src/domain/usecases/params/stream_parameters.dart @@ -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 . + +import 'package:wyatt_crud_bloc/src/domain/entities/query.dart'; + +class StreamParameters { + final String? id; + final List? conditions; + + StreamParameters({ + this.id, + this.conditions, + }); +} diff --git a/packages/wyatt_crud_bloc/lib/src/domain/usecases/params/update_parameters.dart b/packages/wyatt_crud_bloc/lib/src/domain/usecases/params/update_parameters.dart new file mode 100644 index 00000000..b23744bd --- /dev/null +++ b/packages/wyatt_crud_bloc/lib/src/domain/usecases/params/update_parameters.dart @@ -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 . + +class UpdateParameters { + final String id; + final Model? object; + final Map? raw; + + UpdateParameters({ + required this.id, + this.object, + this.raw, + }); +} diff --git a/packages/wyatt_crud_bloc/lib/src/domain/usecases/query.dart b/packages/wyatt_crud_bloc/lib/src/domain/usecases/query.dart new file mode 100644 index 00000000..e7ed25df --- /dev/null +++ b/packages/wyatt_crud_bloc/lib/src/domain/usecases/query.dart @@ -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 . + +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 + extends UseCase, List> { + final CrudRepository _crudRepository; + + Query(this._crudRepository); + + @override + FutureResult> call(List params) => + _crudRepository.query(params); +} diff --git a/packages/wyatt_crud_bloc/lib/src/domain/usecases/stream.dart b/packages/wyatt_crud_bloc/lib/src/domain/usecases/stream.dart new file mode 100644 index 00000000..51255cd4 --- /dev/null +++ b/packages/wyatt_crud_bloc/lib/src/domain/usecases/stream.dart @@ -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 . + +// 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 extends UseCase> { +// final CrudRepository _crudRepository; + +// Stream(this._crudRepository); + +// @override +// StreamResult> call(StreamParameters params) => +// _crudRepository.stream(id: params.id, conditions: params.conditions); +// } diff --git a/packages/wyatt_crud_bloc/lib/src/domain/usecases/update.dart b/packages/wyatt_crud_bloc/lib/src/domain/usecases/update.dart new file mode 100644 index 00000000..f7729c8e --- /dev/null +++ b/packages/wyatt_crud_bloc/lib/src/domain/usecases/update.dart @@ -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 . + +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 + extends UseCase, void> { + final CrudRepository _crudRepository; + + Update(this._crudRepository); + + @override + FutureResult call(UpdateParameters params) => + _crudRepository.update( + params.id, + object: params.object, + raw: params.raw, + ); +} diff --git a/packages/wyatt_crud_bloc/lib/src/domain/usecases/update_all.dart b/packages/wyatt_crud_bloc/lib/src/domain/usecases/update_all.dart new file mode 100644 index 00000000..6aab995e --- /dev/null +++ b/packages/wyatt_crud_bloc/lib/src/domain/usecases/update_all.dart @@ -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 . + +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 + extends UseCase, void> { + final CrudRepository _crudRepository; + + UpdateAll(this._crudRepository); + + @override + FutureResult call(Map params) => + _crudRepository.updateAll(params); +} diff --git a/packages/wyatt_crud_bloc/lib/src/domain/usecases/usecases.dart b/packages/wyatt_crud_bloc/lib/src/domain/usecases/usecases.dart new file mode 100644 index 00000000..ddfca868 --- /dev/null +++ b/packages/wyatt_crud_bloc/lib/src/domain/usecases/usecases.dart @@ -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 . + +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'; diff --git a/packages/wyatt_crud_bloc/lib/src/crud/builder/builder.dart b/packages/wyatt_crud_bloc/lib/src/features/crud/builder/builder.dart similarity index 95% rename from packages/wyatt_crud_bloc/lib/src/crud/builder/builder.dart rename to packages/wyatt_crud_bloc/lib/src/features/crud/builder/builder.dart index 032fa805..0184a4a5 100644 --- a/packages/wyatt_crud_bloc/lib/src/crud/builder/builder.dart +++ b/packages/wyatt_crud_bloc/lib/src/features/crud/builder/builder.dart @@ -15,4 +15,3 @@ // 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/features/crud/builder/crud_builder.dart b/packages/wyatt_crud_bloc/lib/src/features/crud/builder/crud_builder.dart new file mode 100644 index 00000000..62f1faaa --- /dev/null +++ b/packages/wyatt_crud_bloc/lib/src/features/crud/builder/crud_builder.dart @@ -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 . + +import 'package:flutter/material.dart'; +import 'package:wyatt_crud_bloc/src/features/crud/cubit/crud_cubit.dart'; + +class CrudBuilder extends StatelessWidget { + /// `` + /// + /// - 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, + }); + + /// `` + /// + /// - S: the Success State + /// + /// For CrudStates only. + static CrudBuilder + typed({ + 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( + 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', + ), + ); + } + }, + ); +} diff --git a/packages/wyatt_crud_bloc/lib/src/crud/crud.dart b/packages/wyatt_crud_bloc/lib/src/features/crud/crud.dart similarity index 100% rename from packages/wyatt_crud_bloc/lib/src/crud/crud.dart rename to packages/wyatt_crud_bloc/lib/src/features/crud/crud.dart diff --git a/packages/wyatt_crud_bloc/lib/src/features/crud/cubit/crud_cubit.dart b/packages/wyatt_crud_bloc/lib/src/features/crud/cubit/crud_cubit.dart new file mode 100644 index 00000000..67f43c1b --- /dev/null +++ b/packages/wyatt_crud_bloc/lib/src/features/crud/cubit/crud_cubit.dart @@ -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 . + +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 extends Cubit { + Create? get crudCreate; + DeleteAll? get crudDeleteAll; + Delete? get crudDelete; + GetAll? get crudGetAll; + Get? get crudGet; + Query? get crudQuery; + UpdateAll? get crudUpdateAll; + Update? get crudUpdate; + + CrudCubit() : super(CrudInitial()); + + FutureOr 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) { + return stateCopy; + } + if (stateCopy is CrudListLoaded) { + if (stateCopy.data.isEmpty) { + return CrudListLoaded([model]); + } + final List lst = stateCopy.data.toList()..add(model); + return CrudListLoaded(lst); + } + return const CrudOkReturn(); + }, + (error) => CrudError(error.toString()), + ), + ); + } + } + + FutureOr 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) { + return stateCopy; + } + if (stateCopy is CrudListLoaded) { + return CrudListLoaded( + stateCopy.data.where((element) => element?.id != id).toList(), + ); + } + return const CrudOkReturn(); + }, + (error) => CrudError(error.toString()), + ), + ); + } + } + + FutureOr deleteAll() async { + if (crudDeleteAll != null) { + final stateCopy = state; + emit(CrudLoading()); + final result = await crudDeleteAll!.call(null); + emit( + result.fold( + (_) { + if (stateCopy is CrudLoaded) { + return CrudLoaded(null); + } + if (stateCopy is CrudListLoaded) { + return CrudListLoaded(const []); + } + return const CrudOkReturn(); + }, + (error) => CrudError(error.toString()), + ), + ); + } + } + + FutureOr get(String id) async { + if (crudGet != null) { + emit(CrudLoading()); + final result = await crudGet!.call(id); + emit( + result.fold( + CrudLoaded.new, + (error) => CrudError(error.toString()), + ), + ); + } + } + + FutureOr getAll() async { + if (crudGetAll != null) { + emit(CrudLoading()); + final result = await crudGetAll!.call(null); + emit( + result.fold( + CrudListLoaded.new, + (error) => CrudError(error.toString()), + ), + ); + } + } + + FutureOr query(List conditions) async { + if (crudQuery != null) { + emit(CrudLoading()); + final result = await crudQuery!.call(conditions); + emit( + result.fold( + CrudListLoaded.new, + (error) => CrudError(error.toString()), + ), + ); + } + } + + FutureOr update(UpdateParameters 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) { + 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(newVersion.ok); + } + } + return stateCopy; + } + if (stateCopy is CrudListLoaded) { + 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(newList + [newVersion.ok]); + } + } + return stateCopy; + } + return const CrudOkReturn(); + }, + (error) async => CrudError(error.toString()), + ), + ); + } + } + + FutureOr updateAll(Map 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) { + // 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(newVersion.ok); + } + return stateCopy; + } + if (stateCopy is CrudListLoaded) { + 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 ids = stateCopy.data + .map( + (e) => e?.id, + ) + .toList(); + final result = await crudQuery!.call([ + WhereQuery( + WhereQueryType.whereIn, + 'id', + ids, + ) + ]); + if (result.isOk) { + return CrudListLoaded(result.ok ?? []); + } + return stateCopy; + } + return const CrudOkReturn(); + }, + (error) async => CrudError(error.toString()), + ), + ); + } + } +} diff --git a/packages/wyatt_crud_bloc/lib/src/features/crud/cubit/crud_state.dart b/packages/wyatt_crud_bloc/lib/src/features/crud/cubit/crud_state.dart new file mode 100644 index 00000000..2506b7bb --- /dev/null +++ b/packages/wyatt_crud_bloc/lib/src/features/crud/cubit/crud_state.dart @@ -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 . + +part of 'crud_cubit.dart'; + +abstract class CrudState extends Equatable { + const CrudState(); + + @override + List 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 get props => [message]; +} + +class CrudLoaded extends CrudSuccess { + final T? data; + + const CrudLoaded(this.data); + + @override + List get props => [data]; +} + +class CrudListLoaded extends CrudSuccess { + final List data; + + const CrudListLoaded(this.data); + + @override + List get props => [data]; +} diff --git a/packages/wyatt_crud_bloc/lib/src/features/features.dart b/packages/wyatt_crud_bloc/lib/src/features/features.dart new file mode 100644 index 00000000..996ab833 --- /dev/null +++ b/packages/wyatt_crud_bloc/lib/src/features/features.dart @@ -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 . + +export 'crud/crud.dart'; diff --git a/packages/wyatt_crud_bloc/lib/src/models/queries/queries_firestore.dart b/packages/wyatt_crud_bloc/lib/src/models/queries/queries_firestore.dart deleted file mode 100644 index 5b8e73ba..00000000 --- a/packages/wyatt_crud_bloc/lib/src/models/queries/queries_firestore.dart +++ /dev/null @@ -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 . - -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, - ); - case WhereQueryType.whereIn: - return query.where( - condition.field, - whereIn: condition.value as List, - ); - case WhereQueryType.whereNotIn: - return query.where( - condition.field, - whereNotIn: condition.value as List, - ); - 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); -} diff --git a/packages/wyatt_crud_bloc/lib/src/repositories/crud_repository_firebase_database.dart b/packages/wyatt_crud_bloc/lib/src/repositories/crud_repository_firebase_database.dart deleted file mode 100644 index 9c095c85..00000000 --- a/packages/wyatt_crud_bloc/lib/src/repositories/crud_repository_firebase_database.dart +++ /dev/null @@ -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 . - -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 implements CrudRepositoryInterface { - final FirebaseDatabase _firebaseDatabase; - final Model _parser; - - late DatabaseReference _rootReference; - - CrudRepositoryFirebaseDatabase( - String root, - Model parser, { - FirebaseDatabase? firebaseDatabase, - }) : _firebaseDatabase = firebaseDatabase ?? FirebaseDatabase.instance, - _parser = parser { - _rootReference = _firebaseDatabase.ref(root); - } - - @override - Future create(Model object, {String? id}) { - DatabaseReference _reference = _rootReference; - if (id != null) { - _reference = _reference.child(id); - } - return _reference.set(object.toMap()); - } - - @override - Future delete(String id) { - final DatabaseReference _reference = _rootReference.child(id); - return _reference.remove(); - } - - @override - Future deleteAll() { - return _rootReference.remove(); - } - - @override - Future get(String id) async { - final DatabaseEvent _event = await _rootReference.child(id).once(); - return _parser.from(_event.snapshot.value); - } - - @override - Future> getAll() async { - final DatabaseEvent _event = await _rootReference.once(); - final List _objects = []; - _event.snapshot.children.map((e) => _objects.add(_parser.from(e.value))); - return _objects; - } - - @override - Future> query(List conditions) { - // TODO(hpcl): implement query - throw UnimplementedError(); - } - - @override - Stream> stream({String? id, List? conditions}) { - DatabaseReference _reference = _rootReference; - if (id != null) { - _reference = _reference.child(id); - } - - return _reference.onValue.map((e) { - final List _objects = []; - e.snapshot.children.map((e) => _objects.add(_parser.from(e.value))); - return _objects; - }); - } - - @override - Future update(String id, {Model? object, Map? raw}) { - // TODO(hpcl): implement update - throw UnimplementedError(); - } - - @override - Future updateAll(Map raw) { - // TODO(hpcl): implement updateAll - throw UnimplementedError(); - } -} diff --git a/packages/wyatt_crud_bloc/lib/src/repositories/crud_repository_firestore.dart b/packages/wyatt_crud_bloc/lib/src/repositories/crud_repository_firestore.dart deleted file mode 100644 index 7b49bb9b..00000000 --- a/packages/wyatt_crud_bloc/lib/src/repositories/crud_repository_firestore.dart +++ /dev/null @@ -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 . - -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 implements CrudRepositoryInterface { - final FirebaseFirestore _firestore; - final Model _parser; - - late CollectionReference _collectionReference; - - CrudRepositoryFirestore( - String collection, - Model parser, { - FirebaseFirestore? firestore, - }) : _firestore = firestore ?? FirebaseFirestore.instance, - _parser = parser { - _collectionReference = _firestore.collection(collection); - } - - @override - Future create(Model object, {String? id}) { - if (id != null) { - return _collectionReference.doc(id).set(object.toMap()); - } else { - return _collectionReference.add(object.toMap()); - } - } - - @override - Future delete(String id) { - return _collectionReference.doc(id).delete(); - } - - @override - Future 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 get(String id) async { - final DocumentSnapshot snapshot = await _collectionReference.doc(id).get(); - return _parser.from(snapshot); - } - - @override - Future> getAll() async { - final QuerySnapshot snapshots = await _collectionReference.get(); - return snapshots.docs.map(_parser.from).toList(); - } - - @override - Future> query(List 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> stream({ - String? id, - List? conditions, - bool includeMetadataChanges = false, - }) { - if (id != null) { - return _collectionReference - .doc(id) - .snapshots( - includeMetadataChanges: includeMetadataChanges, - ) - .map>( - (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 update(String id, {Model? object, Map? 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 updateAll(Map 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(); - } -} diff --git a/packages/wyatt_crud_bloc/lib/src/src.dart b/packages/wyatt_crud_bloc/lib/src/src.dart new file mode 100644 index 00000000..3a660ea4 --- /dev/null +++ b/packages/wyatt_crud_bloc/lib/src/src.dart @@ -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 . + +export 'core/core.dart'; +export 'data/data.dart'; +export 'domain/domain.dart'; +export 'features/features.dart'; diff --git a/packages/wyatt_crud_bloc/lib/wyatt_crud_bloc.dart b/packages/wyatt_crud_bloc/lib/wyatt_crud_bloc.dart index fffec70f..2656783e 100644 --- a/packages/wyatt_crud_bloc/lib/wyatt_crud_bloc.dart +++ b/packages/wyatt_crud_bloc/lib/wyatt_crud_bloc.dart @@ -14,8 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +/// 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'; diff --git a/packages/wyatt_crud_bloc/pubspec.yaml b/packages/wyatt_crud_bloc/pubspec.yaml index 85d35251..8d39d169 100644 --- a/packages/wyatt_crud_bloc/pubspec.yaml +++ b/packages/wyatt_crud_bloc/pubspec.yaml @@ -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