morwils_flutter_core 0.2.0
morwils_flutter_core: ^0.2.0 copied to clipboard
Shared Flutter foundation and utilities for Morwils applications and packages.
morwils_flutter_core #
The shared, framework-independent Dart foundation for the Morwils software ecosystem.
morwils_flutter_core provides generic programming abstractions, error handling models, validation utilities, data formatters, Dart extensions, rate-limiting utilities, ID generators, pagination constructs, and helper tools shared across all Morwils Flutter applications and packages without depending on Flutter UI or backend APIs.
Features #
- Result & Error Handling: Type-safe
Result<S, F>sealed class with functional operations (fold,map,flatMap,guard,guardAsync) and exhaustive Dart 3 pattern matching. - Unit Type: Representation of
void/empty return values in Result containers (Unit&unit). - Domain Failure Hierarchy: Structured, immutable failure types (
ServerFailure,NetworkFailure,ValidationFailure,NotFoundFailure,UnauthorizedFailure,ForbiddenFailure,CacheFailure,UnexpectedFailure). - Validation Engine: Composable
Validator<T>and specialized builders (StringValidator,NumValidator,DateValidator) returning form-compatible error strings (String?) orResult<T, ValidationFailure>. - String, Number & Date Rules: Standalone rules (
email,phone,url,minLength,min,max,range,after,before,inRange, etc.). - Formatting Utilities: Pure Dart formatters for numbers, currency, dates, percentages, and strings:
NumberFormatter: Thousands grouping, compact quantities (1.5M), ordinals (21st), padding, file sizes (1.0 MB).CurrencyFormatter: Currency symbols ($,₹,€), decimal precision, compact currency, and currency presets.DateFormatter: ISO dates, human-friendly dates (18 Aug 2026), 12/24-hour time, custom tokens, and relativetimeAgo(5 minutes ago,yesterday).PercentageFormatter: Fractions to percentages (0.756->75.6%), decimal control, signed percentages (+5%,-3%).StringFormatter: Case conversions (toCamelCase,toSnakeCase,toPascalCase,toTitleCase), truncation, sensitive masking (******7890), initials.
- Approved Dart Extensions:
String:.capitalize(),.toCamelCase(),.toSnakeCase(),.toTitleCase(),.truncate(),.mask(),.toIntOrNull(),.isEmail,.isPhone.String?:.isNullOrBlank,.isNotNullOrBlank,.orEmpty,.orDefault().DateTime:.isToday,.isYesterday,.isTomorrow,.startOfDay,.endOfDay,.addDays(),.toHumanDate(),.timeAgo().num&int:.toCurrency(),.toPercent(),.toCompact(),.toFileSize(),.seconds,.minutes,.days.Iterable,List,Map:.firstWhereOrNull(),.groupBy(),.distinctBy(),.chunked(),.separatedBy(),.sortedBy(),.compact().
- Generic Utility Functions:
Debouncer: Search and event debouncing with automatic timer reset and disposal.Throttler: Rate-limiting with immediate execution and optional trailing calls.IdGenerator: Pure Dart RFC 4122 v4 UUIDs, nano IDs, and secure timestamped tokens.retry: Resilient async retry executor with exponential backoff and error filtering.
- Pagination: Standard
PaginatedList<T>dataset container andPageQueryparameter model. - Date Utilities: Immutable
DateRangerepresentation with duration and overlap checks. - Sorting: Standard
SortDirectionenum with string parsing and direction toggles.
Installation #
Add this package to your pubspec.yaml:
dependencies:
morwils_flutter_core:
path: ../morwils_flutter_core # or git repository
Usage #
1. Result & Pattern Matching #
import 'package:morwils_flutter_core/morwils_flutter_core.dart';
Result<int, Failure> parseNumber(String input) {
final value = int.tryParse(input);
if (value != null) {
return Result.success(value);
}
return const Result.failure(ValidationFailure(message: 'Invalid number format'));
}
void main() {
final result = parseNumber('42');
// Dart 3 pattern matching
switch (result) {
case Success(value: final num):
print('Parsed number: $num');
case FailureResult(failure: final failure):
print('Error: ${failure.message}');
}
// Functional transformation
final doubled = result.map((v) => v * 2).getOrElse((failure) => 0);
print('Doubled: $doubled');
}
2. Validation #
// Composable String Validator
final emailValidator = Validator.string()
.required('Email is required')
.email('Please enter a valid email address')
.maxLength(100);
// Direct FormField validation
final error = emailValidator.validate('user@example.com'); // null (valid)
// Validation to type-safe Result
final validationResult = emailValidator.validateToResult('invalid-email', field: 'email');
if (validationResult is FailureResult) {
print(validationResult.failureOrNull?.fieldErrors);
}
// Standalone boolean checks
print(StringValidators.isEmail('admin@morwils.com')); // true
3. Extensions & Formatting #
// String extensions
print('morwils_construction'.toTitleCase()); // "Morwils Construction"
print('user@morwils.com'.isEmail); // true
print('1234567890'.mask(endVisible: 4)); // "******7890"
// Date extensions
print(DateTime.now().isToday); // true
print(DateTime.now().toHumanDate()); // "18 Aug 2026"
print(DateTime.now().subtract(5.minutes).timeAgo()); // "5 minutes ago"
// Number extensions
print(1500000.toCompact()); // "1.5M"
print(50000.toInr()); // "₹50,000.00"
print(0.756.toPercent()); // "75.6%"
// Collection extensions
final orders = [{'status': 'pending'}, {'status': 'completed'}];
final grouped = orders.groupBy((o) => o['status']);
4. Utilities (Debounce, Throttle, UUID, Retry) #
// Debounce search query
final searchDebouncer = Debouncer.milliseconds(300);
searchDebouncer.run(() => performSearch('query'));
// Throttle click actions
final buttonThrottler = Throttler.milliseconds(500);
buttonThrottler.run(() => submitForm());
// Generate secure UUID / NanoID
final uuid = IdGenerator.uuidV4();
final shortToken = IdGenerator.nanoId(length: 10);
// Retry flaky operations
final data = await retry(
() => fetchServerState(),
maxAttempts: 3,
delay: const Duration(milliseconds: 200),
backoffFactor: 2.0,
);
5. Pagination & Querying #
final query = PageQuery(page: 1, pageSize: 20, sortBy: 'name', sortDirection: SortDirection.ascending);
final list = PaginatedList<String>(
items: ['Item 1', 'Item 2'],
total: 50,
page: query.page,
pageSize: query.pageSize,
);
print('Page: ${list.page} of ${list.totalPages}');
print('Has next: ${list.hasNextPage}');
Architecture Rules #
morwils_flutter_core is intentionally kept pure Dart:
- No Flutter UI widgets or Material dependencies.
- No HTTP or network clients (delegated to
morwils_flutter_sdk). - No ERP product-specific business models or logic.