diff --git a/app/lib/app/data/repository/auth_repositoty_impl.dart b/app/lib/app/data/repository/auth_repositoty_impl.dart index bdf6a013..496db7f5 100644 --- a/app/lib/app/data/repository/auth_repositoty_impl.dart +++ b/app/lib/app/data/repository/auth_repositoty_impl.dart @@ -1,6 +1,7 @@ import 'dart:developer'; import 'package:meta/meta.dart'; +import 'package:mq_either/mq_either.dart'; import 'package:my_quran/app/app.dart'; import 'package:my_quran/core/core.dart'; diff --git a/app/lib/app/data/source/auth_remote_data_source.dart b/app/lib/app/data/source/auth_remote_data_source.dart index 1c3e081d..4829948e 100644 --- a/app/lib/app/data/source/auth_remote_data_source.dart +++ b/app/lib/app/data/source/auth_remote_data_source.dart @@ -1,5 +1,5 @@ +import 'package:mq_either/mq_either.dart'; import 'package:my_quran/app/app.dart'; -import 'package:my_quran/core/core.dart'; abstract class AuthRemoteDataSource { Future loginWithEmail(String email); diff --git a/app/lib/app/data/source/mock/auth_remote_data_source_mock.dart b/app/lib/app/data/source/mock/auth_remote_data_source_mock.dart index 2e059513..320cb197 100644 --- a/app/lib/app/data/source/mock/auth_remote_data_source_mock.dart +++ b/app/lib/app/data/source/mock/auth_remote_data_source_mock.dart @@ -1,8 +1,7 @@ import 'package:meta/meta.dart'; +import 'package:mq_either/mq_either.dart'; import 'package:my_quran/app/app.dart'; -import 'package:my_quran/core/core.dart'; - @immutable final class AuthRemoteDataSourceMock implements AuthRemoteDataSource { const AuthRemoteDataSourceMock(); diff --git a/app/lib/app/data/source/remote/auth_remote_data_source_impl.dart b/app/lib/app/data/source/remote/auth_remote_data_source_impl.dart index 296f9f89..04bc6819 100644 --- a/app/lib/app/data/source/remote/auth_remote_data_source_impl.dart +++ b/app/lib/app/data/source/remote/auth_remote_data_source_impl.dart @@ -1,4 +1,5 @@ import 'package:meta/meta.dart'; +import 'package:mq_either/mq_either.dart'; import 'package:mq_storage/mq_storage.dart'; import 'package:my_quran/app/app.dart'; import 'package:my_quran/config/config.dart'; diff --git a/app/lib/app/domain/repository/auth_repository.dart b/app/lib/app/domain/repository/auth_repository.dart index 40b18f74..0d367ae4 100644 --- a/app/lib/app/domain/repository/auth_repository.dart +++ b/app/lib/app/domain/repository/auth_repository.dart @@ -1,5 +1,5 @@ +import 'package:mq_either/mq_either.dart'; import 'package:my_quran/app/app.dart'; -import 'package:my_quran/core/core.dart'; abstract class AuthRepository { UserEntity? get init; diff --git a/app/lib/app/domain/usecase/apple_sign_in_use_case.dart b/app/lib/app/domain/usecase/apple_sign_in_use_case.dart index 8bad4d48..22adad62 100644 --- a/app/lib/app/domain/usecase/apple_sign_in_use_case.dart +++ b/app/lib/app/domain/usecase/apple_sign_in_use_case.dart @@ -1,6 +1,6 @@ import 'package:meta/meta.dart'; +import 'package:mq_either/mq_either.dart'; import 'package:my_quran/app/app.dart'; -import 'package:my_quran/core/core.dart'; @immutable final class AppleSignInUseCase { diff --git a/app/lib/app/domain/usecase/google_sign_in_use_case.dart b/app/lib/app/domain/usecase/google_sign_in_use_case.dart index 45d40ea8..d84b4920 100644 --- a/app/lib/app/domain/usecase/google_sign_in_use_case.dart +++ b/app/lib/app/domain/usecase/google_sign_in_use_case.dart @@ -1,6 +1,6 @@ import 'package:meta/meta.dart'; +import 'package:mq_either/mq_either.dart'; import 'package:my_quran/app/app.dart'; -import 'package:my_quran/core/core.dart'; @immutable final class GoogleSignInUseCase { diff --git a/app/lib/app/domain/usecase/patch_gender_user_case.dart b/app/lib/app/domain/usecase/patch_gender_user_case.dart index 2091ae88..d408e974 100644 --- a/app/lib/app/domain/usecase/patch_gender_user_case.dart +++ b/app/lib/app/domain/usecase/patch_gender_user_case.dart @@ -1,6 +1,6 @@ import 'package:meta/meta.dart'; +import 'package:mq_either/mq_either.dart'; import 'package:my_quran/app/app.dart'; -import 'package:my_quran/core/core.dart'; @immutable final class PatchGenderUseCase { diff --git a/app/lib/app/domain/usecase/patch_locale_code_use_case.dart b/app/lib/app/domain/usecase/patch_locale_code_use_case.dart index 4992b7b3..e9d3c067 100644 --- a/app/lib/app/domain/usecase/patch_locale_code_use_case.dart +++ b/app/lib/app/domain/usecase/patch_locale_code_use_case.dart @@ -1,6 +1,6 @@ import 'package:meta/meta.dart'; +import 'package:mq_either/mq_either.dart'; import 'package:my_quran/app/app.dart'; -import 'package:my_quran/core/core.dart'; @immutable final class PatchLocaleCodeUseCase { diff --git a/app/lib/core/client/mq_dio.dart b/app/lib/core/client/mq_dio.dart index 08c9addc..ec2cbee8 100644 --- a/app/lib/core/client/mq_dio.dart +++ b/app/lib/core/client/mq_dio.dart @@ -1,5 +1,6 @@ import 'package:dio/dio.dart'; import 'package:flutter/foundation.dart'; +import 'package:mq_either/mq_either.dart'; import 'package:my_quran/core/core.dart'; part 'mq_dio_base_extension.dart'; diff --git a/app/lib/core/core.dart b/app/lib/core/core.dart index 72205982..697cbdb4 100644 --- a/app/lib/core/core.dart +++ b/app/lib/core/core.dart @@ -3,7 +3,6 @@ export 'client/network_client.dart'; export 'client/http_exception.dart'; export 'client/mq_dio.dart'; export 'crashlytics/mq_crashlytics.dart'; -export 'either/either.dart'; export 'exceptions/network_exception.dart'; export 'exceptions/server_exception.dart'; export 'exceptions/auth_exception.dart'; diff --git a/app/lib/core/either/either.dart b/app/lib/core/either/either.dart deleted file mode 100644 index e46f4281..00000000 --- a/app/lib/core/either/either.dart +++ /dev/null @@ -1,101 +0,0 @@ -import 'package:meta/meta.dart'; - -/// The Either class is an abstract class representing right and left values. -/// ```dart -/// void main() { -/// // Creating a Right instance representing the right value. -/// final rightValue = Right(42); -/// -/// // Creating a Left instance representing the left value. -/// final leftValue = Left('Error'); -/// -/// // Values can be processed using the fold method. -/// -/// // Calling fold on rightValue. -/// final rightResult = rightValue.fold( -/// (error) => 'Left: $error', // This function is executed if there is no right value. -/// (value) => 'Right: $value', // This function is executed if there is a right value. -/// ); -/// print(rightResult); // Output: "Right: 42" -/// -/// // Calling fold on leftValue. -/// final leftResult = leftValue.fold( -/// (error) => 'Left: $error', // This function is executed if there is a left value. -/// (value) => 'Right: $value', // This function is executed if there is no left value. -/// ); -/// print(leftResult); // Output: "Left: Error" -/// } -/// ``` -abstract class Either { - const Either(); - - /// The fold method allows performing operations based on right and left values. - /// B is a type parameter and it performs operations using the ifLeft and ifRight functions. - B fold(B Function(L l) ifLeft, B Function(R r) ifRight); -} - -/// The Right class is derived from the Either class and represents the right value. -/// ```dart -/// void main() { -/// // Creating a Right instance representing the right value. -/// final rightValue = Right(42); -/// -/// // Calling fold on rightValue. -/// final rightResult = rightValue.fold( -/// (error) => 'Left: $error', // This function is executed if there is no right value. -/// (value) => 'Right: $value', // This function is executed if there is a right value. -/// ); -/// print(rightResult); // Output: "Right: 42" -/// } -/// ``` -@immutable -final class Right extends Either { - const Right(this.r); - - /// A field is defined to hold the right value. - final R r; - - /// The fold method invokes the ifRight function using the right value and returns the result. - @override - B fold(B Function(L l) ifLeft, B Function(R r) ifRight) => ifRight(r); - - /// Equality check is defined for operator == and hashCode is computed for hashing. - @override - bool operator ==(Object other) => other is Right && other.r == r; - - @override - int get hashCode => r.hashCode; -} - -/// The Left class is derived from the Either class and represents the left value. -/// ```dart -/// void main() { -/// // Creating a Left instance representing the left value. -/// final leftValue = Left('Error'); -/// -/// // Calling fold on leftValue. -/// final leftResult = leftValue.fold( -/// (error) => 'Left: $error', // This function is executed if there is a left value. -/// (value) => 'Right: $value', // This function is executed if there is no left value. -/// ); -/// print(leftResult); // Output: "Left: -/// } -/// ``` -@immutable -final class Left extends Either { - const Left(this.l); - - /// A field is defined to hold the left value. - final L l; - - /// The fold method invokes the ifLeft function using the left value and returns the result. - @override - B fold(B Function(L l) ifLeft, B Function(R r) ifRight) => ifLeft(l); - - /// Equality check is defined for operator == and hashCode is computed for hashing. - @override - bool operator ==(Object other) => other is Left && other.l == l; - - @override - int get hashCode => l.hashCode; -} diff --git a/app/pubspec.lock b/app/pubspec.lock index cc51c405..fa80619c 100644 --- a/app/pubspec.lock +++ b/app/pubspec.lock @@ -822,6 +822,13 @@ packages: relative: true source: path version: "1.0.0" + mq_either: + dependency: "direct main" + description: + path: "../packages/mq_either" + relative: true + source: path + version: "0.1.0+1" mq_storage: dependency: "direct main" description: diff --git a/app/pubspec_overrides.yaml b/app/pubspec_overrides.yaml index 342a1571..0a7d987c 100644 --- a/app/pubspec_overrides.yaml +++ b/app/pubspec_overrides.yaml @@ -1,6 +1,8 @@ -# melos_managed_dependency_overrides: mq_ci_keys,mq_storage +# melos_managed_dependency_overrides: mq_ci_keys,mq_storage,mq_either dependency_overrides: mq_ci_keys: path: ../packages/mq_ci_keys + mq_either: + path: ../packages/mq_either mq_storage: path: ../packages/mq_storage diff --git a/packages/mq_client/README.md b/packages/mq_client/README.md deleted file mode 100644 index f5c7ec16..00000000 --- a/packages/mq_client/README.md +++ /dev/null @@ -1 +0,0 @@ -# Mq Client diff --git a/packages/mq_client/analysis_options.yaml b/packages/mq_client/analysis_options.yaml deleted file mode 100644 index c69c2b11..00000000 --- a/packages/mq_client/analysis_options.yaml +++ /dev/null @@ -1,14 +0,0 @@ -include: package:very_good_analysis/analysis_options.yaml - -linter: - rules: - public_member_api_docs: false - sort_pub_dependencies: false - lines_longer_than_80_chars: false - directives_ordering: false - -analyzer: - exclude: - - "**/*.g.dart" - - "**/*.freezed.dart" - - "bin/cache/**" diff --git a/packages/mq_client/lib/mq_client.dart b/packages/mq_client/lib/mq_client.dart deleted file mode 100644 index d2d08090..00000000 --- a/packages/mq_client/lib/mq_client.dart +++ /dev/null @@ -1,4 +0,0 @@ -/// My Quran client -library mq_client; - -export 'src/mq_client.dart'; diff --git a/packages/mq_client/lib/src/mq_client.dart b/packages/mq_client/lib/src/mq_client.dart deleted file mode 100644 index 598ace9b..00000000 --- a/packages/mq_client/lib/src/mq_client.dart +++ /dev/null @@ -1,7 +0,0 @@ -/// {@template mq_client} -/// My Quran client -/// {@endtemplate} -class MqClient { - /// {@macro mq_client} - const MqClient(); -} diff --git a/packages/mq_client/pubspec.yaml b/packages/mq_client/pubspec.yaml deleted file mode 100644 index 2c698bd5..00000000 --- a/packages/mq_client/pubspec.yaml +++ /dev/null @@ -1,17 +0,0 @@ -name: mq_client -description: My Quran client -version: 0.1.0+1 -publish_to: none - -environment: - sdk: ">=3.4.0 <4.0.0" - -dependencies: - flutter: - sdk: flutter - -dev_dependencies: - flutter_test: - sdk: flutter - very_good_analysis: ^6.0.0 - mocktail: ^1.0.4 diff --git a/packages/mq_client/test/src/mq_client_test.dart b/packages/mq_client/test/src/mq_client_test.dart deleted file mode 100644 index 9afecf49..00000000 --- a/packages/mq_client/test/src/mq_client_test.dart +++ /dev/null @@ -1,12 +0,0 @@ -// ignore_for_file: prefer_const_constructors - -import 'package:flutter_test/flutter_test.dart'; -import 'package:mq_client/mq_client.dart'; - -void main() { - group('MqClient', () { - test('can be instantiated', () { - expect(MqClient(), isNotNull); - }); - }); -} diff --git a/packages/mq_either/README.md b/packages/mq_either/README.md new file mode 100644 index 00000000..6db90020 --- /dev/null +++ b/packages/mq_either/README.md @@ -0,0 +1,48 @@ +# MyQuran Dart Either + +## Either Class Implementation + +This Dart code provides an implementation of the `Either` type, a common functional programming pattern. The `Either` type represents a value that can be one of two types: `Right` or `Left`. This is useful for handling operations that can return two types of results, such as a successful value or an error. + +### Either + +An abstract class for values that can be either `Right` or `Left`. + +- `fold(B Function(L l) ifLeft, B Function(R r) ifRight)`: Executes one of the given functions based on the type of value. + +### Right + +Represents a `Right` value. + +- `Right(this.value)`: Holds the `Right` value. +- `fold(B Function(L l) ifLeft, B Function(R r) ifRight)`: Executes the `ifRight` function with the `Right` value. + +### Left + +Represents a `Left` value. + +- `Left(this.value)`: Holds the Left value. +- `fold(B Function(L l) ifLeft, B Function(R r) ifRight)`: Executes the `ifLeft` function with the `Left` value. + +### Usage + +Example usage of `Either`, `Right`, and `Left` classes: + +```dart +void main() { + final rightValue = Right(42); + final leftValue = Left('Error'); + + final rightResult = rightValue.fold( + (error) => 'Left: $error', + (value) => 'Right: $value', + ); + print(rightResult); // Output: "Right: 42" + + final leftResult = leftValue.fold( + (error) => 'Left: $error', + (value) => 'Right: $value', + ); + print(leftResult); // Output: "Left: Error" +} +``` diff --git a/packages/mq_either/analysis_options.yaml b/packages/mq_either/analysis_options.yaml new file mode 100644 index 00000000..79d90fa0 --- /dev/null +++ b/packages/mq_either/analysis_options.yaml @@ -0,0 +1,6 @@ +include: package:very_good_analysis/analysis_options.6.0.0.yaml + +linter: + rules: + public_member_api_docs: false + lines_longer_than_80_chars: false \ No newline at end of file diff --git a/packages/mq_either/lib/mq_either.dart b/packages/mq_either/lib/mq_either.dart new file mode 100644 index 00000000..422dde06 --- /dev/null +++ b/packages/mq_either/lib/mq_either.dart @@ -0,0 +1,4 @@ +/// MyQuran Dart Either +library; + +export 'src/mq_either.dart'; diff --git a/packages/mq_either/lib/src/mq_either.dart b/packages/mq_either/lib/src/mq_either.dart new file mode 100644 index 00000000..6f4b329b --- /dev/null +++ b/packages/mq_either/lib/src/mq_either.dart @@ -0,0 +1,50 @@ +import 'package:meta/meta.dart'; + +/// An abstract class representing a value that can be either Right or Left. +@immutable +sealed class Either { + const Either(); + + /// Performs operations based on Right and Left values. + B fold(B Function(L l) ifLeft, B Function(R r) ifRight); +} + +/// Represents the Right value of an Either. +@immutable +final class Right extends Either { + const Right(this.value); + + /// Holds the Right value. + final R value; + + /// Invokes the ifRight function using the Right value. + @override + B fold(B Function(L l) ifLeft, B Function(R r) ifRight) => ifRight(value); + + /// Equality and hashCode overrides. + @override + bool operator ==(Object other) => other is Right && other.value == value; + + @override + int get hashCode => value.hashCode; +} + +/// Represents the Left value of an Either. +@immutable +final class Left extends Either { + const Left(this.value); + + /// Holds the Left value. + final L value; + + /// Invokes the ifLeft function using the Left value. + @override + B fold(B Function(L l) ifLeft, B Function(R r) ifRight) => ifLeft(value); + + /// Equality and hashCode overrides. + @override + bool operator ==(Object other) => other is Left && other.value == value; + + @override + int get hashCode => value.hashCode; +} diff --git a/packages/mq_either/pubspec.yaml b/packages/mq_either/pubspec.yaml new file mode 100644 index 00000000..37dc65d3 --- /dev/null +++ b/packages/mq_either/pubspec.yaml @@ -0,0 +1,15 @@ +name: mq_either +description: MyQuran Dart Either +version: 0.1.0+1 +publish_to: none + +environment: + sdk: ^3.4.0 + +dependencies: + meta: ^1.12.0 + +dev_dependencies: + mocktail: ^1.0.4 + test: ^1.25.7 + very_good_analysis: ^6.0.0 diff --git a/packages/mq_either/test/mq_either_test.dart b/packages/mq_either/test/mq_either_test.dart new file mode 100644 index 00000000..3f94510a --- /dev/null +++ b/packages/mq_either/test/mq_either_test.dart @@ -0,0 +1,49 @@ +import 'package:mq_either/mq_either.dart'; +import 'package:test/test.dart'; + +void main() { + group('Either', () { + test('Return type is correctly', () { + final rightResult = _successMethod(); + final failedResult = _failedMethod(); + + final rightResultValue = switch (rightResult) { + Right() => 'Test Value ${rightResult.value}', + Left() => 'Test Value ${rightResult.value}', + }; + + final failedResultValue = switch (failedResult) { + Right() => 'Test Value ${failedResult.value}', + Left() => 'Test Value ${failedResult.value}', + }; + + expect(rightResultValue, 'Test Value 17'); + expect(failedResultValue, 'Test Value Error'); + }); + + test('Right value should fold correctly', () { + const rightValue = Right(42); + + final result = rightValue.fold( + (error) => 'Left: $error', + (value) => 'Right: $value', + ); + + expect(result, 'Right: 42'); + }); + + test('Left value should fold correctly', () { + const leftValue = Left('Error'); + + final result = leftValue.fold( + (error) => 'Left: $error', + (value) => 'Right: $value', + ); + + expect(result, 'Left: Error'); + }); + }); +} + +Either _successMethod() => const Right(17); +Either _failedMethod() => const Left('Error');