Add Wyatt Continuous Deployment as Sub package #236
| @ -88,8 +88,8 @@ class PhotoRepositoryImpl extends PhotoRepository { | |||||||
|       } |       } | ||||||
|       return Ok(response); |       return Ok(response); | ||||||
|     } catch (_) { |     } catch (_) { | ||||||
|       return const Err( |       return Err( | ||||||
|         ClientException('Cannot retrieve all photos from favorites.'), |         const ClientException('Cannot retrieve all photos from favorites.'), | ||||||
|       ); |       ); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  | |||||||
| @ -17,7 +17,7 @@ | |||||||
| import 'package:architecture_example/domain/entities/photo.dart'; | import 'package:architecture_example/domain/entities/photo.dart'; | ||||||
| import 'package:wyatt_architecture/wyatt_architecture.dart'; | import 'package:wyatt_architecture/wyatt_architecture.dart'; | ||||||
| 
 | 
 | ||||||
| abstract class FavoriteLocalDataSource extends BaseLocalDataSource { | abstract class FavoriteLocalDataSource extends BaseDataSource { | ||||||
|   Future<void> addPhotoToFavorites(Photo photo); |   Future<void> addPhotoToFavorites(Photo photo); | ||||||
|   Future<void> deletePhotoFromFavorites(int id); |   Future<void> deletePhotoFromFavorites(int id); | ||||||
|   Future<List<int>> getAllPhotosFromFavorites(); |   Future<List<int>> getAllPhotosFromFavorites(); | ||||||
|  | |||||||
| @ -17,7 +17,7 @@ | |||||||
| import 'package:architecture_example/domain/entities/album.dart'; | import 'package:architecture_example/domain/entities/album.dart'; | ||||||
| import 'package:wyatt_architecture/wyatt_architecture.dart'; | import 'package:wyatt_architecture/wyatt_architecture.dart'; | ||||||
| 
 | 
 | ||||||
| abstract class AlbumRemoteDataSource extends BaseRemoteDataSource { | abstract class AlbumRemoteDataSource extends BaseDataSource { | ||||||
|   Future<Album> getAlbum(int id); |   Future<Album> getAlbum(int id); | ||||||
|   Future<List<Album>> getAllAlbums({int? start, int? limit}); |   Future<List<Album>> getAllAlbums({int? start, int? limit}); | ||||||
| } | } | ||||||
|  | |||||||
| @ -17,7 +17,7 @@ | |||||||
| import 'package:architecture_example/domain/entities/photo.dart'; | import 'package:architecture_example/domain/entities/photo.dart'; | ||||||
| import 'package:wyatt_architecture/wyatt_architecture.dart'; | import 'package:wyatt_architecture/wyatt_architecture.dart'; | ||||||
| 
 | 
 | ||||||
| abstract class PhotoRemoteDataSource extends BaseRemoteDataSource { | abstract class PhotoRemoteDataSource extends BaseDataSource { | ||||||
|   Future<Photo> getPhoto(int id); |   Future<Photo> getPhoto(int id); | ||||||
|   Future<List<Photo>> getAllPhotos({int? start, int? limit}); |   Future<List<Photo>> getAllPhotos({int? start, int? limit}); | ||||||
|   Future<List<Photo>> getPhotosFromAlbum(int albumId, {int? start, int? limit}); |   Future<List<Photo>> getPhotosFromAlbum(int albumId, {int? start, int? limit}); | ||||||
|  | |||||||
| @ -14,26 +14,17 @@ | |||||||
| // You should have received a copy of the GNU General Public License | // You should have received a copy of the GNU General Public License | ||||||
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||||
| 
 | 
 | ||||||
| import 'dart:async'; |  | ||||||
| 
 |  | ||||||
| import 'package:architecture_example/domain/entities/photo.dart'; | import 'package:architecture_example/domain/entities/photo.dart'; | ||||||
| import 'package:architecture_example/domain/repositories/photo_repository.dart'; | import 'package:architecture_example/domain/repositories/photo_repository.dart'; | ||||||
| import 'package:wyatt_architecture/wyatt_architecture.dart'; | import 'package:wyatt_architecture/wyatt_architecture.dart'; | ||||||
| 
 | 
 | ||||||
| class AddPhotoToFavorites extends AsyncUseCase<Photo, List<Photo>> { | class AddPhotoToFavorites extends AsyncUseCase<Photo, List<Photo>> { | ||||||
|   AddPhotoToFavorites(this._photoRepository); |   const AddPhotoToFavorites(this._photoRepository); | ||||||
|   final PhotoRepository _photoRepository; |   final PhotoRepository _photoRepository; | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   FutureOrResult<List<Photo>> execute(Photo? params) async { |   FutureOrResult<List<Photo>> execute(Photo params) async { | ||||||
|     await _photoRepository.addPhotoToFavorites(params!); |     await _photoRepository.addPhotoToFavorites(params); | ||||||
|     return _photoRepository.getAllPhotosFromFavorites(); |     return _photoRepository.getAllPhotosFromFavorites(); | ||||||
|   } |   } | ||||||
| 
 |  | ||||||
|   @override |  | ||||||
|   FutureOr<void> onStart(Photo? params) { |  | ||||||
|     if (params == null) { |  | ||||||
|       throw const ClientException('Photo cannot be null'); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -14,23 +14,14 @@ | |||||||
| // You should have received a copy of the GNU General Public License | // You should have received a copy of the GNU General Public License | ||||||
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||||
| 
 | 
 | ||||||
| import 'dart:async'; |  | ||||||
| 
 |  | ||||||
| import 'package:architecture_example/domain/repositories/photo_repository.dart'; | import 'package:architecture_example/domain/repositories/photo_repository.dart'; | ||||||
| import 'package:wyatt_architecture/wyatt_architecture.dart'; | import 'package:wyatt_architecture/wyatt_architecture.dart'; | ||||||
| 
 | 
 | ||||||
| class CheckIfPhotoIsInFavorites extends AsyncUseCase<int, bool> { | class CheckIfPhotoIsInFavorites extends AsyncUseCase<int, bool> { | ||||||
|   CheckIfPhotoIsInFavorites(this._photoRepository); |   const CheckIfPhotoIsInFavorites(this._photoRepository); | ||||||
|   final PhotoRepository _photoRepository; |   final PhotoRepository _photoRepository; | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   FutureOrResult<bool> execute(int? params) async => |   FutureOrResult<bool> execute(int params) async => | ||||||
|       _photoRepository.checkIfPhotoIsInFavorites(params!); |       _photoRepository.checkIfPhotoIsInFavorites(params); | ||||||
| 
 |  | ||||||
|   @override |  | ||||||
|   FutureOr<void> onStart(int? params) { |  | ||||||
|     if (params == null) { |  | ||||||
|       throw const ClientException('id cannot be null'); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -18,12 +18,12 @@ import 'package:architecture_example/domain/entities/photo.dart'; | |||||||
| import 'package:architecture_example/domain/repositories/photo_repository.dart'; | import 'package:architecture_example/domain/repositories/photo_repository.dart'; | ||||||
| import 'package:wyatt_architecture/wyatt_architecture.dart'; | import 'package:wyatt_architecture/wyatt_architecture.dart'; | ||||||
| 
 | 
 | ||||||
| class DisplayFavorites extends AsyncUseCase<NoParam, List<Photo>> { | class DisplayFavorites extends NoParamsAsyncUseCase<List<Photo>> { | ||||||
|   DisplayFavorites(this._photoRepository); |   const DisplayFavorites(this._photoRepository); | ||||||
|   final PhotoRepository _photoRepository; |   final PhotoRepository _photoRepository; | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   FutureOrResult<List<Photo>> execute(void params) { |   FutureOrResult<List<Photo>> execute() { | ||||||
|     final photos = _photoRepository.getAllPhotosFromFavorites(); |     final photos = _photoRepository.getAllPhotosFromFavorites(); | ||||||
|     return photos; |     return photos; | ||||||
|   } |   } | ||||||
|  | |||||||
| @ -14,26 +14,17 @@ | |||||||
| // You should have received a copy of the GNU General Public License | // You should have received a copy of the GNU General Public License | ||||||
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||||
| 
 | 
 | ||||||
| import 'dart:async'; |  | ||||||
| 
 |  | ||||||
| import 'package:architecture_example/domain/entities/photo.dart'; | import 'package:architecture_example/domain/entities/photo.dart'; | ||||||
| import 'package:architecture_example/domain/repositories/photo_repository.dart'; | import 'package:architecture_example/domain/repositories/photo_repository.dart'; | ||||||
| import 'package:wyatt_architecture/wyatt_architecture.dart'; | import 'package:wyatt_architecture/wyatt_architecture.dart'; | ||||||
| 
 | 
 | ||||||
| class DisplayPhoto extends AsyncUseCase<int, Photo> { | class DisplayPhoto extends AsyncUseCase<int, Photo> { | ||||||
|   DisplayPhoto(this._photoRepository); |   const DisplayPhoto(this._photoRepository); | ||||||
|   final PhotoRepository _photoRepository; |   final PhotoRepository _photoRepository; | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   FutureOrResult<Photo> execute(int? params) { |   FutureOrResult<Photo> execute(int params) { | ||||||
|     final photo = _photoRepository.getPhoto(params!); |     final photo = _photoRepository.getPhoto(params); | ||||||
|     return photo; |     return photo; | ||||||
|   } |   } | ||||||
| 
 |  | ||||||
|   @override |  | ||||||
|   FutureOr<void> onStart(int? params) { |  | ||||||
|     if (params == null) { |  | ||||||
|       throw const ClientException('id cannot be null'); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -14,32 +14,23 @@ | |||||||
| // You should have received a copy of the GNU General Public License | // You should have received a copy of the GNU General Public License | ||||||
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||||
| 
 | 
 | ||||||
| import 'dart:async'; |  | ||||||
| 
 |  | ||||||
| import 'package:architecture_example/domain/entities/photo.dart'; | import 'package:architecture_example/domain/entities/photo.dart'; | ||||||
| import 'package:architecture_example/domain/repositories/photo_repository.dart'; | import 'package:architecture_example/domain/repositories/photo_repository.dart'; | ||||||
| import 'package:architecture_example/domain/usecases/photos/params/query_parameters.dart'; | import 'package:architecture_example/domain/usecases/photos/params/query_parameters.dart'; | ||||||
| import 'package:wyatt_architecture/wyatt_architecture.dart'; | import 'package:wyatt_architecture/wyatt_architecture.dart'; | ||||||
| 
 | 
 | ||||||
| class OpenAlbum extends AsyncUseCase<QueryParameters, List<Photo>> { | class OpenAlbum extends AsyncUseCase<QueryParameters, List<Photo>> { | ||||||
|   OpenAlbum(this._photoRepository); |   const OpenAlbum(this._photoRepository); | ||||||
|   final PhotoRepository _photoRepository; |   final PhotoRepository _photoRepository; | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   FutureOrResult<List<Photo>> execute(QueryParameters? params) { |   FutureOrResult<List<Photo>> execute(QueryParameters params) { | ||||||
|     final photos = _photoRepository.getPhotosFromAlbum( |     final photos = _photoRepository.getPhotosFromAlbum( | ||||||
|       params!.albumId, |       params.albumId, | ||||||
|       start: params.start, |       start: params.start, | ||||||
|       limit: params.limit, |       limit: params.limit, | ||||||
|     ); |     ); | ||||||
| 
 | 
 | ||||||
|     return photos; |     return photos; | ||||||
|   } |   } | ||||||
| 
 |  | ||||||
|   @override |  | ||||||
|   FutureOr<void> onStart(QueryParameters? params) { |  | ||||||
|     if (params == null) { |  | ||||||
|       throw const ClientException('params cannot be null'); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -14,26 +14,17 @@ | |||||||
| // You should have received a copy of the GNU General Public License | // You should have received a copy of the GNU General Public License | ||||||
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||||
| 
 | 
 | ||||||
| import 'dart:async'; |  | ||||||
| 
 |  | ||||||
| import 'package:architecture_example/domain/entities/photo.dart'; | import 'package:architecture_example/domain/entities/photo.dart'; | ||||||
| import 'package:architecture_example/domain/repositories/photo_repository.dart'; | import 'package:architecture_example/domain/repositories/photo_repository.dart'; | ||||||
| import 'package:wyatt_architecture/wyatt_architecture.dart'; | import 'package:wyatt_architecture/wyatt_architecture.dart'; | ||||||
| 
 | 
 | ||||||
| class RemovePhotoFromFavorites extends AsyncUseCase<int, List<Photo>> { | class RemovePhotoFromFavorites extends AsyncUseCase<int, List<Photo>> { | ||||||
|   RemovePhotoFromFavorites(this._photoRepository); |   const RemovePhotoFromFavorites(this._photoRepository); | ||||||
|   final PhotoRepository _photoRepository; |   final PhotoRepository _photoRepository; | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   FutureOrResult<List<Photo>> execute(int? params) async { |   FutureOrResult<List<Photo>> execute(int params) async { | ||||||
|     await _photoRepository.deletePhotoFromFavorites(params!); |     await _photoRepository.deletePhotoFromFavorites(params); | ||||||
|     return _photoRepository.getAllPhotosFromFavorites(); |     return _photoRepository.getAllPhotosFromFavorites(); | ||||||
|   } |   } | ||||||
| 
 |  | ||||||
|   @override |  | ||||||
|   FutureOr<void> onStart(int? params) { |  | ||||||
|     if (params == null) { |  | ||||||
|       throw const ClientException('id cannot be null'); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -14,30 +14,21 @@ | |||||||
| // You should have received a copy of the GNU General Public License | // You should have received a copy of the GNU General Public License | ||||||
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||||
| 
 | 
 | ||||||
| import 'dart:async'; |  | ||||||
| 
 |  | ||||||
| import 'package:architecture_example/domain/entities/album.dart'; | import 'package:architecture_example/domain/entities/album.dart'; | ||||||
| import 'package:architecture_example/domain/repositories/photo_repository.dart'; | import 'package:architecture_example/domain/repositories/photo_repository.dart'; | ||||||
| import 'package:architecture_example/domain/usecases/photos/params/query_parameters.dart'; | import 'package:architecture_example/domain/usecases/photos/params/query_parameters.dart'; | ||||||
| import 'package:wyatt_architecture/wyatt_architecture.dart'; | import 'package:wyatt_architecture/wyatt_architecture.dart'; | ||||||
| 
 | 
 | ||||||
| class RetrieveAllAlbums extends AsyncUseCase<QueryParameters, List<Album>> { | class RetrieveAllAlbums extends AsyncUseCase<QueryParameters, List<Album>> { | ||||||
|   RetrieveAllAlbums(this._photoRepository); |   const RetrieveAllAlbums(this._photoRepository); | ||||||
|   final PhotoRepository _photoRepository; |   final PhotoRepository _photoRepository; | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   FutureOrResult<List<Album>> execute(QueryParameters? params) { |   FutureOrResult<List<Album>> execute(QueryParameters params) { | ||||||
|     final albums = _photoRepository.getAllAlbums( |     final albums = _photoRepository.getAllAlbums( | ||||||
|       start: params!.start, |       start: params.start, | ||||||
|       limit: params.limit, |       limit: params.limit, | ||||||
|     ); |     ); | ||||||
|     return albums; |     return albums; | ||||||
|   } |   } | ||||||
| 
 |  | ||||||
|   @override |  | ||||||
|   FutureOr<void> onStart(QueryParameters? params) { |  | ||||||
|     if (params == null) { |  | ||||||
|       throw const ClientException('params cannot be null'); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -15,3 +15,5 @@ | |||||||
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||||
| 
 | 
 | ||||||
| export 'exceptions/exceptions.dart'; | export 'exceptions/exceptions.dart'; | ||||||
|  | export 'extensions/object_extension.dart'; | ||||||
|  | export 'mixins/observers.dart'; | ||||||
|  | |||||||
| @ -14,8 +14,6 @@ | |||||||
| // You should have received a copy of the GNU General Public License | // You should have received a copy of the GNU General Public License | ||||||
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||||
| 
 | 
 | ||||||
| import 'package:wyatt_type_utils/wyatt_type_utils.dart'; |  | ||||||
| 
 |  | ||||||
| /// {@template app_exception} | /// {@template app_exception} | ||||||
| /// [AppException] is a base class for all exceptions in the wyatt architecture. | /// [AppException] is a base class for all exceptions in the wyatt architecture. | ||||||
| /// {@endtemplate} | /// {@endtemplate} | ||||||
| @ -27,7 +25,7 @@ abstract class AppException implements Exception { | |||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   String toString() { |   String toString() { | ||||||
|     if (message.isNotNullOrEmpty) { |     if (message?.isNotEmpty ?? false) { | ||||||
|       return '$runtimeType: $message'; |       return '$runtimeType: $message'; | ||||||
|     } else { |     } else { | ||||||
|       return '$runtimeType: An exception occured'; |       return '$runtimeType: An exception occured'; | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| // Copyright (C) 2022 WYATT GROUP | // Copyright (C) 2024 WYATT GROUP | ||||||
| // Please see the AUTHORS file for details. | // Please see the AUTHORS file for details. | ||||||
| // | // | ||||||
| // This program is free software: you can redistribute it and/or modify | // This program is free software: you can redistribute it and/or modify | ||||||
| @ -14,6 +14,10 @@ | |||||||
| // You should have received a copy of the GNU General Public License | // You should have received a copy of the GNU General Public License | ||||||
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||||
| 
 | 
 | ||||||
| export 'base_data_source.dart'; | import 'package:wyatt_architecture/src/core/exceptions/exceptions.dart'; | ||||||
| export 'local/local.dart'; | 
 | ||||||
| export 'remote/remote.dart'; | extension ObjectExtension on Object? { | ||||||
|  |   AppException toException() => this is AppException | ||||||
|  |       ? this! as AppException | ||||||
|  |       : ClientException(this?.toString()); | ||||||
|  | } | ||||||
| @ -1,4 +1,4 @@ | |||||||
| // Copyright (C) 2022 WYATT GROUP | // Copyright (C) 2024 WYATT GROUP | ||||||
| // Please see the AUTHORS file for details. | // Please see the AUTHORS file for details. | ||||||
| // | // | ||||||
| // This program is free software: you can redistribute it and/or modify | // This program is free software: you can redistribute it and/or modify | ||||||
| @ -16,30 +16,26 @@ | |||||||
| 
 | 
 | ||||||
| import 'dart:async'; | import 'dart:async'; | ||||||
| 
 | 
 | ||||||
| import 'package:wyatt_architecture/wyatt_architecture.dart'; | import 'package:wyatt_architecture/src/core/exceptions/exceptions.dart'; | ||||||
|  | import 'package:wyatt_architecture/src/domain/usecase.dart'; | ||||||
| 
 | 
 | ||||||
| /// Usecase observers | /// Usecase observers | ||||||
| mixin Observer<Parameters, ReturnType> { | mixin Observer<I, O> { | ||||||
|   /// Called before usecase is runned. |   /// Called before usecase is runned. | ||||||
|   /// Useful to check the preconditions |   /// Useful to check the preconditions | ||||||
|   FutureOr<void> onStart(Parameters? params) {} |   FutureOr<void> onStart(I? params) {} | ||||||
| 
 |  | ||||||
|   /// Called when error occures during main scenario |  | ||||||
|   /// Useful to run alternative scenario |  | ||||||
|   FutureOr<void> onError(AppException? error) {} |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// Specific observer for classic usecase | /// Exception observer | ||||||
| mixin AsyncObserver<ReturnType> { | mixin ExceptionObserver<O> { | ||||||
|   /// Called when usecase is completed |   /// Called on error | ||||||
|   FutureOr<void> onComplete(ReturnType? data) {} |   /// Useful to handle exceptions | ||||||
|  |   FutureOr<void> onError(AppException e) {} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// Specific observer for stream case usecase | /// Completer observer | ||||||
| mixin StreamObserver<ReturnType> { | mixin CompleterObserver<O> { | ||||||
|   /// Replaces the data event handler of this subscription. |   /// Called after usecase is runned. | ||||||
|   void onDone() {} |   /// Useful to log the result | ||||||
| 
 |   FutureOr<void> onComplete(Res<O>? result) {} | ||||||
|   /// Replaces the done event handler of this subscription. |  | ||||||
|   void onData(ReturnType? data) {} |  | ||||||
| } | } | ||||||
| @ -1,4 +1,4 @@ | |||||||
| // Copyright (C) 2022 WYATT GROUP | // Copyright (C) 2024 WYATT GROUP | ||||||
| // Please see the AUTHORS file for details. | // Please see the AUTHORS file for details. | ||||||
| // | // | ||||||
| // This program is free software: you can redistribute it and/or modify | // This program is free software: you can redistribute it and/or modify | ||||||
| @ -1,26 +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:wyatt_architecture/src/domain/data_sources/base_data_source.dart'; |  | ||||||
| 
 |  | ||||||
| /// {@template base_local_data_source} |  | ||||||
| /// [BaseLocalDataSource] is a base class for all local data sources in the |  | ||||||
| /// wyatt architecture. |  | ||||||
| /// {@endtemplate} |  | ||||||
| abstract class BaseLocalDataSource extends BaseDataSource { |  | ||||||
|   /// {@macro base_local_data_source} |  | ||||||
|   const BaseLocalDataSource(); |  | ||||||
| } |  | ||||||
| @ -1,17 +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/>. |  | ||||||
| 
 |  | ||||||
| export 'base_local_data_source.dart'; |  | ||||||
| @ -1,26 +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:wyatt_architecture/src/domain/data_sources/base_data_source.dart'; |  | ||||||
| 
 |  | ||||||
| /// {@template base_remote_data_source} |  | ||||||
| /// [BaseRemoteDataSource] is a base class for all remote data sources in the |  | ||||||
| /// wyatt architecture. |  | ||||||
| /// {@endtemplate} |  | ||||||
| abstract class BaseRemoteDataSource extends BaseDataSource { |  | ||||||
|   /// {@macro base_remote_data_source} |  | ||||||
|   const BaseRemoteDataSource(); |  | ||||||
| } |  | ||||||
| @ -1,17 +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/>. |  | ||||||
| 
 |  | ||||||
| export 'base_remote_data_source.dart'; |  | ||||||
| @ -1,4 +1,4 @@ | |||||||
| // Copyright (C) 2022 WYATT GROUP | // Copyright (C) 2024 WYATT GROUP | ||||||
| // Please see the AUTHORS file for details. | // Please see the AUTHORS file for details. | ||||||
| //  | //  | ||||||
| // This program is free software: you can redistribute it and/or modify | // This program is free software: you can redistribute it and/or modify | ||||||
| @ -14,7 +14,6 @@ | |||||||
| // You should have received a copy of the GNU General Public License | // You should have received a copy of the GNU General Public License | ||||||
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||||
| 
 | 
 | ||||||
| export 'data_sources/data_sources.dart'; | export 'base_repository.dart'; | ||||||
| export 'entities/entities.dart'; | export 'entity.dart'; | ||||||
| export 'repositories/repositories.dart'; | export 'usecase.dart'; | ||||||
| export 'usecases/usecases.dart'; |  | ||||||
|  | |||||||
| @ -1,17 +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/>. |  | ||||||
| 
 |  | ||||||
| export 'entity.dart'; |  | ||||||
| @ -1,17 +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/>. |  | ||||||
| 
 |  | ||||||
| export 'base_repository.dart'; |  | ||||||
							
								
								
									
										153
									
								
								packages/wyatt_architecture/lib/src/domain/usecase.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								packages/wyatt_architecture/lib/src/domain/usecase.dart
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,153 @@ | |||||||
|  | // 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:generic_usecase/generic_usecase.dart' as generic; | ||||||
|  | import 'package:wyatt_architecture/src/core/exceptions/exceptions.dart'; | ||||||
|  | import 'package:wyatt_architecture/src/core/extensions/object_extension.dart'; | ||||||
|  | import 'package:wyatt_architecture/src/core/mixins/observers.dart'; | ||||||
|  | import 'package:wyatt_type_utils/wyatt_type_utils.dart'; | ||||||
|  | 
 | ||||||
|  | typedef Res<T> = Result<T, AppException>; | ||||||
|  | typedef FutureOrResult<T> = FutureOr<Res<T>>; | ||||||
|  | typedef StreamResult<T> = Stream<Res<T>>; | ||||||
|  | 
 | ||||||
|  | /// A wrapper around [Result] to make it easier to use with AppException. | ||||||
|  | Future<Res<T>> unsafe<T>(FutureOr<T> Function() fn) => | ||||||
|  |     Result.tryCatchAsync<T, AppException, Object>( | ||||||
|  |       () => Future.sync(fn), | ||||||
|  |       (e) => e.toException(), | ||||||
|  |     ); | ||||||
|  | 
 | ||||||
|  | abstract class AsyncUseCase<I, O> extends generic.Usecase<I, Res<O>> | ||||||
|  |     with Observer<I, O>, ExceptionObserver<O>, CompleterObserver<O> { | ||||||
|  |   const AsyncUseCase() : super(); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   FutureOr<generic.ConditionsResult> checkPreconditions(I? params) async { | ||||||
|  |     try { | ||||||
|  |       await onStart(params); | ||||||
|  |       return generic.ConditionsResult(isValid: true); | ||||||
|  |     } catch (e) { | ||||||
|  |       return generic.ConditionsResult(isValid: false, message: e.toString()); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   FutureOr<generic.ConditionsResult> checkPostconditions(Res<O>? result) async { | ||||||
|  |     try { | ||||||
|  |       await onComplete(result); | ||||||
|  |       return generic.ConditionsResult(isValid: true); | ||||||
|  |     } catch (e) { | ||||||
|  |       return generic.ConditionsResult(isValid: false, message: e.toString()); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   FutureOrResult<O> onException(Object e) async { | ||||||
|  |     final exception = e.toException(); | ||||||
|  |     await onError(exception); | ||||||
|  | 
 | ||||||
|  |     return Err(exception); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | abstract class NoParamsAsyncUseCase<O> extends generic.NoParamsUsecase<Res<O>> | ||||||
|  |     with ExceptionObserver<O>, CompleterObserver<O> { | ||||||
|  |   const NoParamsAsyncUseCase() : super(); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   FutureOr<generic.ConditionsResult> checkPostconditions(Res<O>? result) async { | ||||||
|  |     try { | ||||||
|  |       await onComplete(result); | ||||||
|  |       return generic.ConditionsResult(isValid: true); | ||||||
|  |     } catch (e) { | ||||||
|  |       return generic.ConditionsResult(isValid: false, message: e.toString()); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   FutureOrResult<O> onException(Object e) async { | ||||||
|  |     final exception = e.toException(); | ||||||
|  |     await onError(exception); | ||||||
|  | 
 | ||||||
|  |     return Err(exception); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | abstract class StreamUseCase<I, O> extends generic.StreamUsecase<I, Res<O>> | ||||||
|  |     with Observer<I, O>, ExceptionObserver<O> { | ||||||
|  |   const StreamUseCase() : super(); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   FutureOr<generic.ConditionsResult> checkPreconditions(I? params) async { | ||||||
|  |     try { | ||||||
|  |       await onStart(params); | ||||||
|  |       return generic.ConditionsResult(isValid: true); | ||||||
|  |     } catch (e) { | ||||||
|  |       return generic.ConditionsResult(isValid: false, message: e.toString()); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   StreamSubscription<Res<O>> listen( | ||||||
|  |     I params, | ||||||
|  |     void Function(Res<O>)? onData, { | ||||||
|  |     Function? onError, | ||||||
|  |     void Function()? onDone, | ||||||
|  |     bool? cancelOnError, | ||||||
|  |   }) => | ||||||
|  |       super.call(params).listen( | ||||||
|  |             onData, | ||||||
|  |             onError: onError, | ||||||
|  |             onDone: onDone, | ||||||
|  |             cancelOnError: cancelOnError, | ||||||
|  |           ); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   FutureOrResult<O> onException(Object e) async { | ||||||
|  |     final exception = e.toException(); | ||||||
|  |     await onError(exception); | ||||||
|  | 
 | ||||||
|  |     return Err(exception); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | abstract class NoParamsStreamUseCase<O> | ||||||
|  |     extends generic.NoParamsStreamUsecase<Res<O>> with ExceptionObserver<O> { | ||||||
|  |   const NoParamsStreamUseCase() : super(); | ||||||
|  | 
 | ||||||
|  |   StreamSubscription<Res<O>> listen( | ||||||
|  |     void Function(Res<O>)? onData, { | ||||||
|  |     Function? onError, | ||||||
|  |     void Function()? onDone, | ||||||
|  |     bool? cancelOnError, | ||||||
|  |   }) => | ||||||
|  |       super.call().listen( | ||||||
|  |             onData, | ||||||
|  |             onError: onError, | ||||||
|  |             onDone: onDone, | ||||||
|  |             cancelOnError: cancelOnError, | ||||||
|  |           ); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   FutureOrResult<O> onException(Object e) async { | ||||||
|  |     final exception = e.toException(); | ||||||
|  |     await onError(exception); | ||||||
|  | 
 | ||||||
|  |     return Err(exception); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -1,26 +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:wyatt_architecture/src/domain/entities/entity.dart'; |  | ||||||
| 
 |  | ||||||
| /// {@template no_param} |  | ||||||
| /// [NoParam] is a class that is used when a use case does not require any |  | ||||||
| /// parameters. |  | ||||||
| /// {@endtemplate} |  | ||||||
| class NoParam extends Entity { |  | ||||||
|   /// {@macro no_param} |  | ||||||
|   const NoParam(); |  | ||||||
| } |  | ||||||
| @ -1,100 +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 'dart:async'; |  | ||||||
| 
 |  | ||||||
| import 'package:wyatt_architecture/src/core/exceptions/exceptions.dart'; |  | ||||||
| import 'package:wyatt_architecture/src/domain/usecases/observers.dart'; |  | ||||||
| import 'package:wyatt_type_utils/wyatt_type_utils.dart'; |  | ||||||
| 
 |  | ||||||
| typedef FutureOrResult<T> = FutureOr<Result<T, AppException>>; |  | ||||||
| typedef StreamResult<T> = Stream<Result<T, AppException>>; |  | ||||||
| 
 |  | ||||||
| /// {@template base_usecase} |  | ||||||
| /// Abstract class of any use case. |  | ||||||
| /// {@endtemplate} |  | ||||||
| abstract class BaseUseCase<Parameters, ReturnType> { |  | ||||||
|   /// {@macro base_usecase} |  | ||||||
|   const BaseUseCase(); |  | ||||||
| 
 |  | ||||||
|   /// Run use case scenarios |  | ||||||
|   ReturnType call(Parameters parameters); |  | ||||||
| 
 |  | ||||||
|   /// Private function to implement main scenario |  | ||||||
|   /// of your usecase. |  | ||||||
|   ReturnType execute(Parameters params); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /// {@template usecase} |  | ||||||
| /// Abstract class of a use case that deals specifically |  | ||||||
| /// with the response and its state. |  | ||||||
| /// {@endtemplate} |  | ||||||
| abstract class UseCase<Parameters, ReturnType> |  | ||||||
|     extends BaseUseCase<Parameters?, FutureOrResult<ReturnType>> |  | ||||||
|     with Observer<Parameters, ReturnType> { |  | ||||||
|   /// {@macro usecase} |  | ||||||
|   const UseCase(); |  | ||||||
| 
 |  | ||||||
|   FutureOr<void> _onSuccess(ReturnType data); |  | ||||||
| 
 |  | ||||||
|   /// Supports the result of the main scenario and integrates |  | ||||||
|   /// some alternative scenarios if necessary. |  | ||||||
|   @override |  | ||||||
|   FutureOrResult<ReturnType> call(Parameters? parameters) async { |  | ||||||
|     try { |  | ||||||
|       await onStart(parameters); |  | ||||||
|       final response = await execute(parameters); |  | ||||||
|       if (response.isErr) { |  | ||||||
|         await onError(response.err); |  | ||||||
|       } else if (response.isOk && response.ok != null) { |  | ||||||
|         await _onSuccess(response.ok as ReturnType); |  | ||||||
|       } |  | ||||||
|       return response; |  | ||||||
|     } catch (e) { |  | ||||||
|       return Err(ClientException(e.toString())); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /// {@template async_usecase} |  | ||||||
| /// Abtstract classic usecase bases on futures |  | ||||||
| /// {@endtemplate} |  | ||||||
| abstract class AsyncUseCase<Parameters, ReturnType> |  | ||||||
|     extends UseCase<Parameters?, ReturnType> with AsyncObserver<ReturnType> { |  | ||||||
|   /// {@macro async_usecase} |  | ||||||
|   const AsyncUseCase(); |  | ||||||
| 
 |  | ||||||
|   @override |  | ||||||
|   FutureOr<void> _onSuccess(ReturnType data) => onComplete(data); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /// {@template stream_usecase} |  | ||||||
| /// Abstract specific usecase bases on streams |  | ||||||
| /// {@endtemplate} |  | ||||||
| abstract class StreamUseCase<Parameters, ReturnType> |  | ||||||
|     extends UseCase<Parameters?, Stream<ReturnType>> |  | ||||||
|     with StreamObserver<ReturnType> { |  | ||||||
|   /// {@macro stream_usecase} |  | ||||||
|   const StreamUseCase(); |  | ||||||
| 
 |  | ||||||
|   @override |  | ||||||
|   FutureOr<void> _onSuccess(Stream<ReturnType> data) { |  | ||||||
|     data.listen( |  | ||||||
|       onData, |  | ||||||
|       onDone: onDone, |  | ||||||
|     ); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| @ -1,19 +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/>. |  | ||||||
| 
 |  | ||||||
| export 'no_param.dart'; |  | ||||||
| export 'observers.dart'; |  | ||||||
| export 'usecase.dart'; |  | ||||||
| @ -15,4 +15,5 @@ | |||||||
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||||
| 
 | 
 | ||||||
| export 'core/core.dart'; | export 'core/core.dart'; | ||||||
|  | export 'data/base_data_source.dart'; | ||||||
| export 'domain/domain.dart'; | export 'domain/domain.dart'; | ||||||
|  | |||||||
| @ -22,9 +22,10 @@ version: 0.2.0+1 | |||||||
| publish_to: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub | publish_to: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub | ||||||
| 
 | 
 | ||||||
| environment: | environment: | ||||||
|   sdk: ">=2.17.0 <3.0.0" |   sdk: "^3.0.0" | ||||||
| 
 | 
 | ||||||
| dependencies: | dependencies: | ||||||
|  |   generic_usecase: ^3.0.0 | ||||||
|   wyatt_type_utils: |   wyatt_type_utils: | ||||||
|     hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub |     hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub | ||||||
|     version: ^0.0.5 |     version: ^0.0.5 | ||||||
| @ -32,4 +33,4 @@ dependencies: | |||||||
| dev_dependencies: | dev_dependencies: | ||||||
|   wyatt_analysis: |   wyatt_analysis: | ||||||
|     hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub |     hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub | ||||||
|     version: ^2.5.0 |     version: ^2.6.1 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user