// 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: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 = Result; typedef FutureOrResult = FutureOr>; typedef StreamResult = Stream>; /// A wrapper around [Result] to make it easier to use with AppException. Future> unsafe(FutureOr Function() fn) => Result.tryCatchAsync( () => Future.sync(fn), (e) => e.toException(), ); abstract class AsyncUseCase extends generic.Usecase> with Observer, ExceptionObserver, CompleterObserver { const AsyncUseCase() : super(); @override FutureOr 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 checkPostconditions(Res? result) async { try { await onComplete(result); return generic.ConditionsResult(isValid: true); } catch (e) { return generic.ConditionsResult(isValid: false, message: e.toString()); } } @override FutureOrResult onException(Object e) async { final exception = e.toException(); await onError(exception); return Err(exception); } } abstract class NoParamsAsyncUseCase extends generic.NoParamsUsecase> with ExceptionObserver, CompleterObserver { const NoParamsAsyncUseCase() : super(); @override FutureOr checkPostconditions(Res? result) async { try { await onComplete(result); return generic.ConditionsResult(isValid: true); } catch (e) { return generic.ConditionsResult(isValid: false, message: e.toString()); } } @override FutureOrResult onException(Object e) async { final exception = e.toException(); await onError(exception); return Err(exception); } } abstract class StreamUseCase extends generic.StreamUsecase> with Observer, ExceptionObserver { const StreamUseCase() : super(); @override FutureOr checkPreconditions(I? params) async { try { await onStart(params); return generic.ConditionsResult(isValid: true); } catch (e) { return generic.ConditionsResult(isValid: false, message: e.toString()); } } StreamSubscription> listen( I params, void Function(Res)? onData, { Function? onError, void Function()? onDone, bool? cancelOnError, }) => super.call(params).listen( onData, onError: onError, onDone: onDone, cancelOnError: cancelOnError, ); @override FutureOrResult onException(Object e) async { final exception = e.toException(); await onError(exception); return Err(exception); } } abstract class NoParamsStreamUseCase extends generic.NoParamsStreamUsecase> with ExceptionObserver { const NoParamsStreamUseCase() : super(); StreamSubscription> listen( void Function(Res)? onData, { Function? onError, void Function()? onDone, bool? cancelOnError, }) => super.call().listen( onData, onError: onError, onDone: onDone, cancelOnError: cancelOnError, ); @override FutureOrResult onException(Object e) async { final exception = e.toException(); await onError(exception); return Err(exception); } }