Skip to content

Commit

Permalink
feat!: upgrade to dart 3 + better usage of FutureOr capabilities (#11)
Browse files Browse the repository at this point in the history
  • Loading branch information
wim07101993 authored Nov 4, 2023
1 parent 8c7a18f commit 01c3cea
Show file tree
Hide file tree
Showing 24 changed files with 602 additions and 398 deletions.
1 change: 0 additions & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 3.0.0

* feat!: upgraded to dart v3
- removed `whenSuccess` and `whenFailed` methods + variants from `ExceptionOr`
* feat: better usage of `FutureOr` functionality

## 2.1.1

* ci stuff
Expand Down
8 changes: 3 additions & 5 deletions example/behaviour_example.dart
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import 'dart:async';
import 'dart:developer';

import 'package:behaviour/behaviour.dart';

class CreateCustomer extends Behaviour<CreateCustomerParams, void> {
@override
Future<void> action(CreateCustomerParams input, BehaviourTrack? track) {
// TODO logic to create a customer
log('TODO create customer: ${input.name} - ${input.phoneNumber}');
return Future.value();
}

@override
FutureOr<Exception> onCatchError(
Object e,
StackTrace stacktrace,
StackTrace stackTrace,
BehaviourTrack? track,
) {
return Exception('An unknown error occurred: $e');
Expand All @@ -22,12 +23,10 @@ class CreateCustomer extends Behaviour<CreateCustomerParams, void> {
class CreateCustomerParams {
const CreateCustomerParams({
required this.name,
required this.address,
required this.phoneNumber,
});

final String name;
final String address;
final String phoneNumber;
}

Expand All @@ -36,7 +35,6 @@ Future<void> main() async {
await createCustomer(
const CreateCustomerParams(
name: 'Wim',
address: 'Somewhere in Belgium',
phoneNumber: '+32 xxx xx xx xx',
),
);
Expand Down
2 changes: 1 addition & 1 deletion example/behaviour_without_input_example.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,6 @@ Future<void> main() async {
final getProfileData = GetProfileData();
await getProfileData().thenWhen(
(exception) => log('Exception: $exception'),
(value) => log('value: $value'),
(value) => log('value: ${value.name} - ${value.birthday}'),
);
}
2 changes: 2 additions & 0 deletions lib/behaviour.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ export 'src/behaviour_monitor.dart';
export 'src/behaviour_without_input.dart';
export 'src/behaviour_without_input_interface.dart';
export 'src/exception_or.dart';
export 'src/exception_or_extensions.dart';
export 'src/future_or_extensions.dart';
17 changes: 11 additions & 6 deletions lib/src/behaviour.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:async';

import 'package:behaviour/behaviour.dart';

/// A [Behaviour] is a type which only has one function, it's behaviour. It is
Expand All @@ -15,16 +17,19 @@ abstract class Behaviour<TIn, TOut> extends BehaviourBase
implements BehaviourInterface<TIn, TOut> {
/// Super does not need to be called by it's implementers. It only sets the
/// [monitor] by which the behaviour can be monitored.
Behaviour({
BehaviourMonitor? monitor,
}) : super(monitor: monitor);
Behaviour({super.monitor});

/// [call] executes the action of the behaviour. If the action is successful,
/// the return value is wrapped in a [Success] else the exception is wrapped
/// in a [Failed].
@override
Future<ExceptionOr<TOut>> call(TIn input) {
return executeAction((track) async => Success(await action(input, track)));
FutureOr<ExceptionOr<TOut>> call(TIn input) {
return executeAction((track) {
return action(input, track).whenFutureOrValue(
(future) => future.then((result) => Success(result)),
(result) => Success(result),
);
});
}

/// [action] contains the actual logic of the behaviour.
Expand All @@ -33,5 +38,5 @@ abstract class Behaviour<TIn, TOut> extends BehaviourBase
/// [BehaviourTrack.end], [BehaviourTrack.stopWithException] and
/// [BehaviourTrack.stopWithError] are called from the super class.
@override
Future<TOut> action(TIn input, BehaviourTrack? track);
FutureOr<TOut> action(TIn input, BehaviourTrack? track);
}
6 changes: 4 additions & 2 deletions lib/src/behaviour_interface.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:async';

import 'package:behaviour/behaviour.dart';

/// A [BehaviourInterface] is a type which only has one function, it's
Expand All @@ -15,7 +17,7 @@ abstract class BehaviourInterface<TIn, TOut> {
/// [call] executes the action of the behaviour. If the action is successful,
/// the return value is wrapped in a [Success] else the exception is wrapped
/// in a [Failed].
Future<ExceptionOr<TOut>> call(TIn input);
FutureOr<ExceptionOr<TOut>> call(TIn input);

/// [action] contains the actual logic of the behaviour.
///
Expand All @@ -25,5 +27,5 @@ abstract class BehaviourInterface<TIn, TOut> {
/// [track] can be used for monitoring. The [BehaviourTrack.start],
/// [BehaviourTrack.end], [BehaviourTrack.stopWithException] and
/// [BehaviourTrack.stopWithError] are called from the super class.
Future<TOut> action(TIn input, BehaviourTrack? track);
FutureOr<TOut> action(TIn input, BehaviourTrack? track);
}
51 changes: 39 additions & 12 deletions lib/src/behaviour_mixin.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,22 +33,49 @@ mixin BehaviourMixin {
/// is added to the track.
///
/// When something is caught in the try catch, the [onCatch] method is called
/// with the caught object, stacktrace and track as parameters. The result
/// with the caught object, stackTrace and track as parameters. The result
/// of this [onCatch] method is then wrapped within a [Failed] and is returned.
Future<ExceptionOr<TOut>> executeAction<TOut>(Action<TOut> action) async {
FutureOr<ExceptionOr<TOut>> executeAction<TOut>(Action<TOut> action) {
final track = monitor?.createBehaviourTrack(this);
try {
track?.start();
final either = await action(track);
track?.end();
return either;
} on Exception catch (exception, stackTrace) {
return Failed(await onCatchException(exception, stackTrace, track));
final futureOr = action(track);
if (futureOr is ExceptionOr<TOut>) {
track?.end();
return futureOr;
}
return _catchFutureError(futureOr, track);
} catch (error, stackTrace) {
return Failed(await onCatchError(error, stackTrace, track));
return _catch(error, stackTrace, track);
}
}

Future<ExceptionOr<TOut>> _catchFutureError<TOut>(
Future<ExceptionOr<TOut>> future,
BehaviourTrack? track,
) async {
try {
return await future;
} catch (error, stackTrace) {
return _catch(error, stackTrace, track);
}
}

FutureOr<ExceptionOr<TOut>> _catch<TOut>(
Object error,
StackTrace stackTrace,
BehaviourTrack? track,
) {
final futureOrException = error is Exception
? onCatchException(error, stackTrace, track)
: onCatchError(error, stackTrace, track);

return futureOrException.whenFutureOrValue(
(future) => future.then((exception) => Failed(exception)),
(exception) => Failed(exception),
);
}

/// Is invoked when an exception is caught by the try-catch block in
/// [executeAction].
///
Expand All @@ -59,10 +86,10 @@ mixin BehaviourMixin {
/// super method should be called to invoke it.
FutureOr<Exception> onCatchException(
Exception exception,
StackTrace stacktrace,
StackTrace stackTrace,
BehaviourTrack? track,
) {
track?.stopWithException(exception, stacktrace);
track?.stopWithException(exception, stackTrace);
return exception;
}

Expand All @@ -76,10 +103,10 @@ mixin BehaviourMixin {
/// super method should be called to invoke it.
FutureOr<Exception> onCatchError(
Object error,
StackTrace stacktrace,
StackTrace stackTrace,
BehaviourTrack? track,
) {
track?.stopWithError(error, stacktrace);
track?.stopWithError(error, stackTrace);
if (error is Exception) {
return error;
} else {
Expand Down
17 changes: 11 additions & 6 deletions lib/src/behaviour_without_input.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:async';

import 'package:behaviour/behaviour.dart';

/// A [BehaviourWithoutInput] is a type which only has one function, it's
Expand All @@ -15,16 +17,19 @@ abstract class BehaviourWithoutInput<TOut> extends BehaviourBase
implements BehaviourWithoutInputInterface<TOut> {
/// Super does not need to be called by it's implementers. It only sets the
/// [monitor] by which the behaviour can be monitored.
BehaviourWithoutInput({
BehaviourMonitor? monitor,
}) : super(monitor: monitor);
BehaviourWithoutInput({super.monitor});

/// [call] executes the action of the behaviour. If the action is successful,
/// the return value is wrapped in a [Success] else the exception is wrapped
/// in a [Failed].
@override
Future<ExceptionOr<TOut>> call() {
return executeAction((track) async => Success(await action(track)));
FutureOr<ExceptionOr<TOut>> call() {
return executeAction((track) {
return action(track).whenFutureOrValue(
(future) => future.then((result) => Success(result)),
(result) => Success(result),
);
});
}

/// [action] contains the actual logic of the behaviour.
Expand All @@ -33,5 +38,5 @@ abstract class BehaviourWithoutInput<TOut> extends BehaviourBase
/// [BehaviourTrack.end], [BehaviourTrack.stopWithException] and
/// [BehaviourTrack.stopWithError] are called from the super class.
@override
Future<TOut> action(BehaviourTrack? track);
FutureOr<TOut> action(BehaviourTrack? track);
}
6 changes: 4 additions & 2 deletions lib/src/behaviour_without_input_interface.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:async';

import 'package:behaviour/behaviour.dart';

/// A [BehaviourWithoutInputInterface] is a type which only has one function,
Expand All @@ -15,7 +17,7 @@ abstract class BehaviourWithoutInputInterface<TOut> {
/// [call] executes the action of the behaviour. If the action is successful,
/// the return value is wrapped in a [Success] else the exception is wrapped
/// in a [Failed].
Future<ExceptionOr<TOut>> call();
FutureOr<ExceptionOr<TOut>> call();

/// [action] contains the actual logic of the behaviour.
///
Expand All @@ -25,5 +27,5 @@ abstract class BehaviourWithoutInputInterface<TOut> {
/// [track] can be used for monitoring. The [BehaviourTrack.start],
/// [BehaviourTrack.end], [BehaviourTrack.stopWithException] and
/// [BehaviourTrack.stopWithError] are called from the super class.
Future<TOut> action(BehaviourTrack? track);
FutureOr<TOut> action(BehaviourTrack? track);
}
Loading

0 comments on commit 01c3cea

Please sign in to comment.