tool_result 0.0.6
tool_result: ^0.0.6 copied to clipboard
Contains result pattern implementation
tool_result #
A Dart/Flutter library for handling Loading-Content-Error (LCE) state in a reactive, ergonomic, and type-safe way using the Result<T>
and PaginationResult<T>
patterns.
Features #
- Simple and explicit LCE state management with
Result<T>
andPaginationResult<T>
- Stream and Future extensions for easy LCE handling
- Ergonomic API for pattern matching, mapping, and extracting content
- RxDart and plain Dart Streams compatibility
- Utilities for mapping to view models
- Fetcher architecture for reactive, cache-aware data loading
Getting Started #
Add to your pubspec.yaml
:
dependencies:
tool_result:
path: tools/tool_result
The LCE Pattern #
Result<T>
and PaginationResult<T>
represent one of three states:
- Loading: The operation is in progress
- Content: The operation succeeded and data is available
- Error: The operation failed
Usage #
Creating Results #
final loading = Result<String>.loading();
final content = Result<String>.content('Hello');
final error = Result<String>.error(Exception('Oops'), StackTrace.current);
Creating PaginationResults #
final loading = PaginationResult<List<String>>.loading();
final content = PaginationResult<List<String>>.content(['A', 'B']);
final error = PaginationResult<List<String>>.error(Exception('Oops'), StackTrace.current);
Pattern Matching #
result.when(
content: (data) => print('Content: $data'),
loading: (_) => print('Loading...'),
error: (err, _) => print('Error: $err'),
);
final value = result.maybeWhen(
content: (data) => data,
orElse: () => 'default',
);
paginationResult.when(
content: (data) => print('Page Content: $data'),
loading: (_) => print('Page Loading...'),
error: (err, _) => print('Page Error: $err'),
);
Streams #
// Convert a stream to a Result stream
final resultStream = myStream.asResultStream();
// Listen for LCE events
resultStream.listenLce(
onContent: (data) => print('Content: $data'),
onError: (err, _) => print('Error: $err'),
onLoading: (_) => print('Loading...'),
);
// Extract only content values
resultStream.extractContent().listen(print);
// Convert a stream to a PaginationResult stream
final pageStream = myPageStream.asPaginationResultStream();
// Listen for pagination LCE events
pageStream.listenLce(
onContent: (data) => print('Page Content: $data'),
onError: (err, _) => print('Page Error: $err'),
onLoading: (_) => print('Page Loading...'),
);
// Extract only content values from pagination
pageStream.map((pr) => pr.content).listen(print);
Futures #
final resultFuture = myFuture.mapWithResult();
Utilities #
distinctContent()
— Only emit when content changesdebounceContent(Duration)
— Debounce content emissionsskipWhileLoading()
— Skip loading states
Fetchers: Reactive Data Loading #
The fetcher architecture provides a unified, reactive, and cache-aware way to load data from network, memory, and storage. Fetchers expose a stream of LCE states and handle caching, storage sync, and network requests for you.
ResultFetcherDelegate #
For single-result data (not paginated):
final fetcher = ResultFetcherDelegate<MyParams, MyData>(
fromNetwork: (params) => api.getData(params),
observeFromStorage: (params) => db.observeData(params),
toStorage: (params, data) => db.saveData(params, data),
);
fetcher.observe(params: ...).listen((result) {
if (result.isContent) print(result.content);
});
PaginationResultFetcherDelegate #
For paginated data:
final fetcher = PaginationResultFetcherDelegate<MyParams, List<MyData>>(
fromNetwork: (params) => api.getPage(params),
concatContent: (prev, next) => [...?prev, ...next],
contentLength: (content) => content?.length ?? 0,
);
fetcher.observe(params: ...).listen((result) {
if (result.content != null) print(result.content);
});
PaginationListResultFetcherDelegate #
For paginated lists (convenience wrapper):
final fetcher = PaginationListResultFetcherDelegate<MyParams, MyData>(
fromNetwork: (params) => api.getPage(params),
);
fetcher.observe(params: ...).listen((result) {
if (result.content != null) print(result.content);
});
Best Practices #
- Use fetchers for all async data sources to unify loading, content, and error handling.
- Use storage and memory caching for performance and offline support.
- Use stream extensions for reactive UIs.
- Use pattern matching (
when
,maybeWhen
) for ergonomic state handling.
License #
MIT