Skip to content

Commit

Permalink
Split examples by extension type + refactor documentation + add more …
Browse files Browse the repository at this point in the history
…extensions
  • Loading branch information
ashtanko committed Nov 14, 2024
1 parent 8e13d5a commit bdb355f
Show file tree
Hide file tree
Showing 17 changed files with 544 additions and 260 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## 0.1.15
- Split examples by extension type
- Add nullable list extensions
- Split collection extensions to iterable, map and list
- Add unit tests
- Refactor documentation

## 0.1.14
- Add nullable extensions on runes

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ nullx is a **dart** toolkit that enhances handling of nullable types, providing
- Provides utilities for null-checking
- Helps in navigating nullable structures
- Offers robust error handling
- Nullable types extensions

## Getting started 🎉

Expand Down
20 changes: 20 additions & 0 deletions example/either_example.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import 'package:dartz/dartz.dart';
import 'package:nullx/nullx.dart';

void main() async {
const rightEither = Right<String, int>(42);
final int? valueOrNull = rightEither.getOrNull();
final int valueOrElse = rightEither.getValueOrElse(0);
final int? mappedValue = rightEither.mapOrNull((v) => v * 2);
final Either<String, int>? flatMappedValue =
rightEither.flatMapOrNull((v) => Right<String, int>(v * 2));

// ignore: avoid_print
print(valueOrNull); // prints: 42
// ignore: avoid_print
print(valueOrElse); // prints: 42
// ignore: avoid_print
print(mappedValue); // prints: 84
// ignore: avoid_print
print(flatMappedValue); // prints: Right(84)
}
60 changes: 60 additions & 0 deletions example/future_example.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import 'package:nullx/nullx.dart';

void main() async {
// ignore: unnecessary_nullable_for_final_variable_declarations
final Future<int?>? nullableFuture = Future.value(42);
// ignore: unnecessary_nullable_for_final_variable_declarations
final Future<int?>? failedFuture = Future.error(Exception('Failed'));

// Return a default value if the Future completes with null
final int result2 = await nullableFuture.orDefault(5);
// ignore: avoid_print
print(result2); // 42

// Return null if the Future completes with an error
final int? errorHandled = await failedFuture.onErrorReturnNull();
// ignore: avoid_print
print(errorHandled); // null

// Return a default value if the Future completes with an error
final int? errorHandledWithValue = await failedFuture.onErrorReturn(5);
// ignore: avoid_print
print(errorHandledWithValue); // 5

// Provide an alternative Future if the original completes with null
// ignore: unnecessary_nullable_for_final_variable_declarations
final Future<int?>? nullableFutureWithNull = Future.value();
final int alternative = await nullableFutureWithNull.orElse(() async => 99);
// ignore: avoid_print
print(alternative); // 99

// Execute an action when the Future completes
// ignore: avoid_print
await nullableFuture.whenComplete(() => print('Completed')); // Completed

// Ignore any errors the Future may throw
await failedFuture.ignoreErrors(); // No output, error ignored

// Timeout a Future and return null if it doesn't complete in time
// ignore: unnecessary_nullable_for_final_variable_declarations
final Future<int?>? slowFuture =
Future.delayed(const Duration(seconds: 2), () => 10);
final int? timedOut =
await slowFuture.timeoutWithNull(const Duration(seconds: 1));
// ignore: avoid_print
print(timedOut); // null

// Chain another Future using thenOrNull
final Future<String?> chained =
nullableFuture.thenOrNull((value) => Future.value('Value: $value'));
// ignore: avoid_print
print(await chained); // Value: 42

// Catch an error and return null using catchErrorOrNull
final int? caughtError = await failedFuture.catchErrorOrNull((error) {
// ignore: avoid_print
print('Caught error: $error');
});
// ignore: avoid_print
print(caughtError); // Caught error: Exception: Failed, null
}
26 changes: 26 additions & 0 deletions example/iterable_example.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import 'package:nullx/nullx.dart';

void main() {
// ignore: unnecessary_nullable_for_final_variable_declarations
final List<int?>? nullableIntList = [1, null, 3, null];
// ignore: unnecessary_nullable_for_final_variable_declarations
const List<String?>? nullStringList = null;
// ignore: unnecessary_nullable_for_final_variable_declarations
final List<String?>? nullableStringList = [null, 'one', null, 'two', null];
// ignore: unnecessary_nullable_for_final_variable_declarations
const List<String?>? emptyStringList = [];

// Maps over the list, applying a function to each non-null element,
nullableIntList?.mapNonNull((item) => item * 2); // prints: [2, 6]

// Maps over the list, applying a function to each non-null element and its
// index
// prints: [0, 6]
nullableIntList?.mapNonNullIndexed((item, index) => item * index);

nullableIntList.isNullOrEmpty; // prints: false

nullStringList.isNullOrEmpty; // prints: true
emptyStringList.isNullOrEmpty; // prints: true
nullableStringList.isNullOrEmpty; // prints: false
}
11 changes: 11 additions & 0 deletions example/list_example.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import 'package:nullx/nullx.dart';

void main() {
// ignore: unnecessary_nullable_for_final_variable_declarations
final List<int?>? nullableIntList = [1, null, 3, null];
nullableIntList.ifNotNullOrEmpty(
(list) => list,
() => 'List is null or empty', // whatIfNot
);
// prints: [1, 2, 3]
}
51 changes: 51 additions & 0 deletions example/map_example.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import 'package:nullx/nullx.dart';

void main() {
// ignore: unnecessary_nullable_for_final_variable_declarations
final Map<String, int>? nullableMap = {'a': 1, 'b': 2};

// Check if the map is null or empty
// ignore: avoid_print
print(nullableMap.isNullOrEmpty); // false

// Get value for key or return default
// ignore: avoid_print
print(nullableMap.getOrElse('c', 0)); // 0

// Put a value if the key is absent
nullableMap.putIfAbsentOrElse('c', 3);
// ignore: avoid_print
print(nullableMap); // {a: 1, b: 2, c: 3}

// Update a value using a function
nullableMap.updateValue('a', (value) => value! + 10);
// ignore: avoid_print
print(nullableMap); // {a: 11, b: 2, c: 3}
// ignore: avoid_print

// Filter the map
final filteredMap = nullableMap.filter((entry) => entry.value > 2);
// ignore: avoid_print
print(filteredMap); // {a: 11, c: 3}

// Map keys and values
final mappedMap = nullableMap.mapKeysAndValues(
(entry) => MapEntry(entry.key.toUpperCase(), entry.value.toString()),
);
// ignore: avoid_print
print(mappedMap); // {A: 11, B: 2, C: 3}

// Iterate through the map
// ignore: avoid_print
nullableMap.forEachEntry((key, value) => print('$key: $value'));
// Output:
// a: 11
// b: 2
// c: 3

// Check if the map contains a key or value
// ignore: avoid_print
print(nullableMap.containsKeyOrNull('a')); // true
// ignore: avoid_print
print(nullableMap.containsValueOrNull(4)); // false
}
137 changes: 2 additions & 135 deletions example/nullx_example.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import 'package:nullx/nullx.dart';

void main() async {
/// Variables
// ignore: unnecessary_nullable_for_final_variable_declarations
final List<String?>? nullableStringList = [null, 'one', null, 'two', null];
// ignore: unnecessary_nullable_for_final_variable_declarations
const int? nullableInt = 10;
const nonNullInt = 1;
Expand All @@ -13,45 +14,8 @@ void main() async {
const String? nullString = null;
const double? nullDouble = null;
const bool? nullBool = null;
// ignore: unnecessary_nullable_for_final_variable_declarations
final Map<String, int>? nullableMap = {'a': 1, 'b': 2};
// ignore: unnecessary_nullable_for_final_variable_declarations
final Future<int?>? nullableFuture = Future.value(42);
// ignore: unnecessary_nullable_for_final_variable_declarations
final Future<int?>? failedFuture = Future.error(Exception('Failed'));

// ignore: unnecessary_nullable_for_final_variable_declarations
final List<int?>? nullableIntList = [1, null, 3, null];
// ignore: unnecessary_nullable_for_final_variable_declarations
final List<String?>? nullableStringList = [null, 'one', null, 'two', null];
// ignore: unnecessary_nullable_for_final_variable_declarations
const List<String?>? nullStringList = null;

// ignore: unnecessary_nullable_for_final_variable_declarations
const List<String?>? emptyStringList = [];

/// Collections
// Maps over the list, applying a function to each non-null element,
nullableIntList?.mapNonNull((item) => item * 2); // prints: [2, 6]

// Maps over the list, applying a function to each non-null element and its
// index
// prints: [0, 6]
nullableIntList?.mapNonNullIndexed((item, index) => item * index);

nullableIntList.whatIfNotNullOrEmpty(
(list) => list,
() => 'List is null or empty', // whatIfNot
);
// prints: [1, 2, 3]

nullableIntList.isNullOrEmpty; // prints: false

nullStringList.isNullOrEmpty; // prints: true
emptyStringList.isNullOrEmpty; // prints: true
nullableStringList.isNullOrEmpty; // prints: false

// A list of nullable strings
final List<String?> strs = [null, 'one', null, 'two', null];

Expand Down Expand Up @@ -177,103 +141,6 @@ void main() async {
// Performs an operation on the age if it's not null
age.let((a) => a);

// Check if the map is null or empty
// ignore: avoid_print
print(nullableMap.isNullOrEmpty); // false

// Get value for key or return default
// ignore: avoid_print
print(nullableMap.getOrElse('c', 0)); // 0

// Put a value if the key is absent
nullableMap.putIfAbsentOrElse('c', 3);
// ignore: avoid_print
print(nullableMap); // {a: 1, b: 2, c: 3}

// Update a value using a function
nullableMap.updateValue('a', (value) => value! + 10);
// ignore: avoid_print
print(nullableMap); // {a: 11, b: 2, c: 3}
// ignore: avoid_print

// Filter the map
final filteredMap = nullableMap.filter((entry) => entry.value > 2);
// ignore: avoid_print
print(filteredMap); // {a: 11, c: 3}

// Map keys and values
final mappedMap = nullableMap.mapKeysAndValues(
(entry) => MapEntry(entry.key.toUpperCase(), entry.value.toString()),
);
// ignore: avoid_print
print(mappedMap); // {A: 11, B: 2, C: 3}

// Iterate through the map
// ignore: avoid_print
nullableMap.forEachEntry((key, value) => print('$key: $value'));
// Output:
// a: 11
// b: 2
// c: 3

// Check if the map contains a key or value
// ignore: avoid_print
print(nullableMap.containsKeyOrNull('a')); // true
// ignore: avoid_print
print(nullableMap.containsValueOrNull(4)); // false

// Return a default value if the Future completes with null
final int result2 = await nullableFuture.orDefault(5);
// ignore: avoid_print
print(result2); // 42

// Return null if the Future completes with an error
final int? errorHandled = await failedFuture.onErrorReturnNull();
// ignore: avoid_print
print(errorHandled); // null

// Return a default value if the Future completes with an error
final int? errorHandledWithValue = await failedFuture.onErrorReturn(5);
// ignore: avoid_print
print(errorHandledWithValue); // 5

// Provide an alternative Future if the original completes with null
// ignore: unnecessary_nullable_for_final_variable_declarations
final Future<int?>? nullableFutureWithNull = Future.value();
final int alternative = await nullableFutureWithNull.orElse(() async => 99);
// ignore: avoid_print
print(alternative); // 99

// Execute an action when the Future completes
// ignore: avoid_print
await nullableFuture.whenComplete(() => print('Completed')); // Completed

// Ignore any errors the Future may throw
await failedFuture.ignoreErrors(); // No output, error ignored

// Timeout a Future and return null if it doesn't complete in time
// ignore: unnecessary_nullable_for_final_variable_declarations
final Future<int?>? slowFuture =
Future.delayed(const Duration(seconds: 2), () => 10);
final int? timedOut =
await slowFuture.timeoutWithNull(const Duration(seconds: 1));
// ignore: avoid_print
print(timedOut); // null

// Chain another Future using thenOrNull
final Future<String?> chained =
nullableFuture.thenOrNull((value) => Future.value('Value: $value'));
// ignore: avoid_print
print(await chained); // Value: 42

// Catch an error and return null using catchErrorOrNull
final int? caughtError = await failedFuture.catchErrorOrNull((error) {
// ignore: avoid_print
print('Caught error: $error');
});
// ignore: avoid_print
print(caughtError); // Caught error: Exception: Failed, null

// Throws a [NotImplementedError] indicating that an operation is
try {
todo();
Expand Down
15 changes: 15 additions & 0 deletions example/object_example.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import 'package:nullx/nullx.dart';

void main() {
const Object? nullObject = null;
// ignore: unnecessary_nullable_for_final_variable_declarations
const Object? nullableStringObject = 'Hello';
// ignore: avoid_print
print(nullObject.isNull); // true
// ignore: avoid_print
print(nullObject.isNotNull); // false
final result =
nullableStringObject.mapIfNotNull((it) => (it as String).length);
// ignore: avoid_print
print(result); // 5
}
3 changes: 2 additions & 1 deletion lib/nullx.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
/// and robust error handling, for cleaner and more resilient code
library nullx;

export 'src/collections.dart';
export 'src/either.dart';
export 'src/exception.dart';
export 'src/future.dart';
export 'src/iterable.dart';
export 'src/list.dart';
export 'src/map.dart';
export 'src/object.dart';
export 'src/runes.dart';
Expand Down
Loading

0 comments on commit bdb355f

Please sign in to comment.