nexo 0.0.3-beta.1
nexo: ^0.0.3-beta.1 copied to clipboard
Reusable architecture, error handling, and logging utilities for Flutter apps.
nexo #
Модульный набор утилит для Flutter-приложений: слой UseCase, единая модель Failure, маппинг ошибок, Bloc/Cubit-обёртки, Dio (клиент и интерцепторы), базовые data source-ы и логирование.
Версия: 0.0.3-beta.1
SDK: Dart ^3.11.3, Flutter >=1.17.0
Установка #
Зависимость из git или локальный path — в зависимости от того, как вы публикуете пакет:
dependencies:
nexo:
path: ../nexo # или git: url + ref
flutter pub add nexo
# при публикации в pub.dev
Генерация кода #
Модель Failure построена на Freezed. После изменения failure.dart или связанных типов:
dart run build_runner build --delete-conflicting-outputs
Структура репозитория #
Код сгруппирован по папкам под lib/packages/ (это не отдельные pub-пакеты, а логические модули внутри одного пакета nexo):
| Папка | Назначение |
|---|---|
nexo_core |
UseCase, StreamUseCase, Bloc/Cubit, сеть (Dio), локальные/удалённые data source, пагинация, вспомогательные блок-хелперы |
nexo_errors |
Failure (sealed + Freezed), типизированные подтипы ошибок, FailureMapper, подмапперы (Dio, Hive, Isar, и т.д.) |
nexo_logger |
Абстракция NexoLogger, адаптер под Talker |
Рекомендуемые barrel-импорты:
import 'package:nexo/nexo.dart'; // всё сразу
// или точечно:
import 'package:nexo/nexo_core.dart';
import 'package:nexo/nexo_errors.dart';
import 'package:nexo/nexo_logger.dart';
Глубокие импорты по-прежнему допустимы: package:nexo/packages/nexo_core/....
Локализация сообщений Failure #
По умолчанию userMessage — русский текст (как и раньше). Для английского или своей копирайта используйте FailureUserMessageCatalog и расширение localizedMessage:
import 'package:nexo/nexo_errors.dart';
failure.localizedMessage(const EnFailureUserMessages());
Свой каталог: реализуйте FailureUserMessageCatalog и верните строки из forFailure.
Ядро: Result, код ошибки, async-состояние #
Result<T>иStreamResult<T>— typedef надEither<Failure, T>/ потоком тех же значений. СигнатурыNexoUseCase.call,NexoStreamUseCase.call,executeEither/subscribeEitherв Bloc/Cubit используютResult<T>. Черезresult.dartреэкспортируютсяEither,Left,Right(отдельныйimport dartzв фичах часто не нужен).Failure.code— стабильная строка (network.no_internet,http.unauthorized, приHttpFailure.unknownи известном статусе —http.status_502) для Sentry, логов и бэкенда.NexoAsyncState<T>— sealed:NexoAsyncIdle/NexoAsyncLoading/NexoAsyncSuccess/NexoAsyncFailure; геттерыisIdle,isLoading, … иdataOrNull,failureOrNull.NexoUseCase.callWithRetry(extension) — повтор вызова с задержкой иretryIfлибоFailure.isRetryable.fetchCacheThenNetwork/fetchNetworkThenCache— минимальный offline-first без лишних абстракций.FailurePresenter—snackbarMessage,dialogTitle,dialogBody,technicalCode(тонкий UI-слой; при необходимости замените своим классом в приложении).NexoCrashReporter+NoOpNexoCrashReporter— точка расширения для Crashlytics/Sentry.NexoRequestIdInterceptor— заголовокx-request-idи лог id на response/error.
Сознательно не добавлялись (чтобы не раздувать пакет): полноценный debug-overlay, жёсткий NexoEnvironment с пресетами URL (лучше в приложении), разбиение на несколько pub-пакетов без запроса на миграцию.
Зависимости (основные) #
- Состояние:
bloc,flutter_bloc,bloc_concurrency,stream_transform - Функциональный стиль:
dartz(Either) - Сеть:
dio - Локальные хранилища:
hive,isar,shared_preferences,flutter_secure_storage,path_provider - Firebase (частично):
firebase_core,firebase_auth - Модели:
freezed_annotation,json_annotation - Логи:
talker - UI (в пакете объявлено):
flutter_screenutil
Модули и публичное API #
nexo_logger #
NexoLogger— абстрактный контракт:debug,info,warning,error.TalkerLoggerAdapter— реализация черезTalker.
Передавайте NexoLogger в use case и data source для единообразного логирования.
nexo_errors #
Failure— sealed-класс с вариантами: сеть, HTTP, auth, валидация, storage, БД, кэш, parse, permissions, platform, file, location, notification, payment, sync, unknown.- Удобные геттеры:
userMessage(русский по умолчанию),localizedMessage,isRetryable,requiresLogout,requiresSettings,logCategory. Failure.code— стабильный код для аналитики (см. раздел «Ядро» выше).FailureMapper.from(error, stackTrace?)— централизованное преобразование исключений вFailureчерез цепочкуFailureSubMapper.Object.toFailure([stackTrace])— extension (объявлен вfailure_mapper_extension.dartи дублируется вfailure_mapper.dartкакFailureMapperX).Result<T>,StreamResult<T>,FailurePresenter,NexoCrashReporter.
Подмапперы (порядок в FailureMapper): доменные исключения, Firebase Auth, Firebase Messaging (по FirebaseException), Dio, platform, Hive, Isar, Drift/SQLite (эвристика по тексту ошибки), file system, common.
nexo_core — UseCase #
NexoUseCase<T, Params>— абстрактный класс сexecuteиcall:Future<Result<T>>, логирование (в т.ч.failure.code), перехват исключений и маппинг черезtoFailure.NexoStreamUseCase<T, Params>—buildвозвращаетStream<T>;callдаётStream<Result<T>>.NoParams— для use case без параметров (см.no_params.dart).
nexo_core — Bloc / Cubit #
NexoBloc<Event, State>/NexoCubit<State>— базовые классы сFailureSupport.- Методы:
execute/executeEither— async-действие с опциональным loading, success, error.subscribe/subscribeEither— подписка на потоки с маппингом ошибок вFailure.
NexoCubitдополнительно:SubscriptionMixin, отмена подписок по ключу,closeотменяет подписки.NexoBlocObserver—BlocObserverс логированием lifecycle / events / changes / errors черезNexoLogger, фильтрshouldLogBloc, усечение длины логов.- Вспомогательные файлы:
bloc_transformers.dart,optimistic_update_helper.dart,pagination_controller.dart,reconnecting_stream_service.dart,nexo_bloc_observer.dart.
nexo_core — Сеть #
HttpMethod+ extension для строкового метода.DioClient— тонкая обёртка надDio:get/post/put/patch/delete/head/options,request/requestUri, form-data,download, геттерconfigдля отладки.NexoAuthInterceptor— Bearer-токен, refresh с дедупликацией черезCompleter, повтор запроса, флагиskipAuth/_auth_retried, колбэки логов.NexoRetryInterceptor— exponential backoff с джиттером, настраиваемые типы/коды/методы,skipRetry.NexoLoggingInterceptor— логирование запросов/ответов.NexoRequestIdInterceptor— correlation id в заголовке и логах.BaseRemoteDataSource— обёртка надDioClientс логированием ошибок для GET/POST/PUT/PATCH/DELETE/download/form-data.
nexo_core — Локальные data source #
BaseHiveDataSource<T, ID>— инициализация box, операции с логированием ошибок.BaseIsarDataSource—read/write/writeSyncс обработкой ошибок.BaseSharedPreferencesDataSource— типизированные get/set и JSON-хелперы с логированием.BaseSecureStorageDataSource— обёртка надFlutterSecureStorage(строки, JSON, удаление).
Пагинация #
PageChunk<T, Cursor>— страница: элементы, следующий курсор,hasMore.PaginationController<T, Cursor>— накопление списка,loadNext,reset,replaceAll, защита от параллельной загрузки.
Минимальный пример #
// 1. Логгер
final logger = TalkerLoggerAdapter(Talker());
// 2. UseCase
class GetUser extends NexoUseCase<User, String> {
GetUser(super.logger);
@override
Future<User> execute(String userId) async {
// repository / api
throw Exception('fail'); // станет Failure через toFailure
}
}
// 3. Cubit
class UserCubit extends NexoCubit<UserState> {
UserCubit() : super(const UserInitial());
Future<void> load(String id) => executeEither(
action: () => GetUser(logger)(id),
onLoading: () => const UserLoading(),
onSuccess: (u) => UserLoaded(u),
onError: (f) => UserError(f.userMessage),
);
}
// 4. BlocObserver
Bloc.observer = NexoBlocObserver(logger, shouldLogBloc: (b) => b is UserCubit);
Пример приложения #
Каталог example/ — обычное Flutter-приложение с path-зависимостью на родительский пакет. Запуск из корня репозитория:
cd example && flutter run
CI и качество #
В .github/workflows/ci.yml: dart format, flutter analyze, flutter test (пакет + example), dart doc --validate-links lib.
Локально:
dart format lib test
flutter analyze
flutter test
dart doc lib
Тяжёлые / платформенные зависимости #
Пакет тянет Firebase, Hive, Isar, Secure storage и др. Если приложению нужна только часть API, зависимости всё равно резолвятся целиком — для минимального footprint в перспективе имеет смысл вынести модули в отдельные pub-пакеты (например nexo_network, nexo_errors). Isar 3 привязан к версии Flutter/Dart; при апгрейде SDK следите за совместимостью или планируйте миграцию хранилища.
Лицензия #
См. файл LICENSE.