From 69b65e8ec63ba4634338abfd7634ac7819fc6b4f Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Thu, 15 Jan 2026 20:52:49 +0100 Subject: [PATCH 1/8] chore: Upgrade Flutter to `>=3.38.1` and enable new lints This commit upgrades the project to Dart SDK `^3.10.0` and Flutter `>=3.38.1`. It also enables a comprehensive set of new lint rules from `all_lint_rules.yaml` to improve code quality, consistency, and maintainability. The majority of the changes in this commit are automatic fixes and formatting adjustments applied by the Dart formatter and linter to align the codebase with the newly enabled rules. This includes: - Applying `dart format --fix` with a page width of 100 and trailing commas. - Enabling and autofixing new lint rules such as `use_super_parameters`, `unnecessary_lambdas`, `use_if_null_to_convert_nulls_to_bools`, and many others. - Deleting the `analysis_options.yaml` and `.gitignore` from `stream_core_flutter` as they are now handled at the root level. - Updating `melos.yaml` to reflect the new SDK constraints. --- all_lint_rules.yaml | 45 ++- analysis_options.yaml | 19 +- apps/design_system_gallery/pubspec.yaml | 4 +- melos.yaml | 5 +- .../api/interceptors/logging_interceptor.dart | 30 +- .../lib/src/api/stream_core_dio_error.dart | 6 +- .../uploader/attachment_uploader.dart | 12 +- .../lib/src/errors/stream_api_error.dart | 25 +- .../lib/src/errors/stream_api_error.g.dart | 48 ++- .../lib/src/logger/impl/external_logger.dart | 15 +- .../lib/src/logger/impl/file_logger.dart | 34 +-- .../lib/src/logger/stream_log.dart | 4 +- .../lib/src/logger/stream_logger.dart | 7 +- .../lib/src/platform/current_platform.dart | 6 +- .../lib/src/query/filter/filter.dart | 34 +-- .../query/filter/location/bounding_box.g.dart | 13 +- .../filter/location/circular_region.g.dart | 11 +- .../filter/location/location_coordinate.dart | 5 +- packages/stream_core/lib/src/query/sort.dart | 18 +- .../stream_core/lib/src/query/sort.g.dart | 9 +- .../user/connect_user_details_request.g.dart | 3 +- .../lib/src/user/token_manager.dart | 2 +- packages/stream_core/lib/src/user/user.dart | 21 +- .../stream_core/lib/src/user/user_token.dart | 3 +- .../src/user/ws_auth_message_request.g.dart | 3 +- .../lib/src/utils/comparable_field.dart | 7 +- .../stream_core/lib/src/utils/disposable.dart | 4 +- .../lib/src/utils/event_emitter.dart | 4 +- .../stream_core/lib/src/utils/result.dart | 14 +- .../lib/src/utils/shared_emitter.dart | 3 +- .../lib/src/utils/state_emitter.dart | 3 +- .../engine/stream_web_socket_engine.dart | 6 +- .../ws/client/engine/web_socket_engine.dart | 4 +- .../automatic_reconnection_policy.dart | 8 +- .../connection_recovery_handler.dart | 34 +-- .../ws/client/reconnect/retry_strategy.dart | 7 +- .../ws/client/stream_web_socket_client.dart | 20 +- .../client/web_socket_connection_state.dart | 21 +- .../lib/src/ws/events/ws_request.dart | 2 +- packages/stream_core/pubspec.yaml | 2 +- .../stream_core/test/query/filter_test.dart | 288 +++++++----------- .../test/query/list_extensions_test.dart | 144 ++++----- .../stream_core/test/query/sort_test.dart | 16 +- .../test/utils/event_emitter_test.dart | 3 +- .../test/utils/shared_emitter_test.dart | 9 +- .../test/utils/state_emitter_test.dart | 10 +- packages/stream_core_flutter/.gitignore | 31 -- .../stream_core_flutter/analysis_options.yaml | 4 - .../lib/src/components/stream_button.dart | 99 +++--- .../theme/components/stream_button_theme.dart | 2 +- .../src/theme/stream_component_factory.dart | 5 +- .../lib/src/theme/stream_theme.dart | 9 +- .../lib/stream_core_flutter.dart | 2 +- packages/stream_core_flutter/pubspec.yaml | 5 +- 54 files changed, 505 insertions(+), 643 deletions(-) delete mode 100644 packages/stream_core_flutter/.gitignore delete mode 100644 packages/stream_core_flutter/analysis_options.yaml diff --git a/all_lint_rules.yaml b/all_lint_rules.yaml index 8ed068a..0fb9e4b 100644 --- a/all_lint_rules.yaml +++ b/all_lint_rules.yaml @@ -3,10 +3,10 @@ linter: - always_declare_return_types - always_put_control_body_on_new_line - always_put_required_named_parameters_first - - always_require_non_null_named_parameters - always_specify_types - always_use_package_imports - annotate_overrides + - annotate_redeclares - avoid_annotating_with_dynamic - avoid_bool_literals_in_conditional_expressions - avoid_catches_without_on_clauses @@ -20,6 +20,7 @@ linter: - avoid_field_initializers_in_const_classes - avoid_final_parameters - avoid_function_literals_in_foreach_calls + - avoid_futureor_void - avoid_implementing_value_types - avoid_init_to_null - avoid_js_rounded_ints @@ -32,8 +33,6 @@ linter: - avoid_relative_lib_imports - avoid_renaming_method_parameters - avoid_return_types_on_setters - - avoid_returning_null - - avoid_returning_null_for_future - avoid_returning_null_for_void - avoid_returning_this - avoid_setters_without_getters @@ -61,12 +60,15 @@ linter: - constant_identifier_names - control_flow_in_finally - curly_braces_in_flow_control_structures + - dangling_library_doc_comments - depend_on_referenced_packages - deprecated_consistency + - deprecated_member_use_from_same_package - diagnostic_describe_all_properties - directives_ordering - discarded_futures - do_not_use_environment + - document_ignores - empty_catches - empty_constructor_bodies - empty_statements @@ -76,32 +78,41 @@ linter: - flutter_style_todos - hash_and_equals - implementation_imports - - iterable_contains_unrelated_type + - implicit_call_tearoffs + - implicit_reopen + - invalid_case_patterns + - invalid_runtime_check_with_js_interop_types - join_return_with_assignment - leading_newlines_in_multiline_strings + - library_annotations - library_names - library_prefixes - library_private_types_in_public_api - lines_longer_than_80_chars - - list_remove_unrelated_type - literal_only_boolean_expressions + - matching_super_parameters + - missing_code_block_language_in_doc_comment - missing_whitespace_between_adjacent_strings - no_adjacent_strings_in_list - no_default_cases - no_duplicate_case_values - no_leading_underscores_for_library_prefixes - no_leading_underscores_for_local_identifiers + - no_literal_bool_comparisons - no_logic_in_create_state - no_runtimeType_toString + - no_self_assignments + - no_wildcard_variable_uses - non_constant_identifier_names - noop_primitive_operations - null_check_on_nullable_type_parameter - null_closures - omit_local_variable_types + - omit_obvious_local_variable_types + - omit_obvious_property_types - one_member_abstracts - only_throw_errors - overridden_fields - - package_api_docs - package_names - package_prefixed_library_names - parameter_assignments @@ -117,7 +128,6 @@ linter: - prefer_constructors_over_static_methods - prefer_contains - prefer_double_quotes - - prefer_equal_for_default_values - prefer_expression_function_bodies - prefer_final_fields - prefer_final_in_for_each @@ -148,8 +158,10 @@ linter: - provide_deprecation_message - public_member_api_docs - recursive_getters + - remove_deprecations_in_breaking_versions - require_trailing_commas - secure_pubspec_urls + - simplify_variable_pattern - sized_box_for_whitespace - sized_box_shrink_expand - slash_for_doc_comments @@ -157,20 +169,31 @@ linter: - sort_constructors_first - sort_pub_dependencies - sort_unnamed_constructors_first + - specify_nonobvious_local_variable_types + - specify_nonobvious_property_types + - strict_top_level_inference + - switch_on_type - test_types_in_equals - throw_in_finally - tighten_type_of_initializing_formals - type_annotate_public_apis - type_init_formals + - type_literal_in_constant_pattern - unawaited_futures + - unintended_html_in_doc_comment + - unnecessary_async - unnecessary_await_in_return - unnecessary_brace_in_string_interps + - unnecessary_breaks - unnecessary_const - unnecessary_constructor_name - unnecessary_final - unnecessary_getters_setters + - unnecessary_ignore - unnecessary_lambdas - unnecessary_late + - unnecessary_library_directive + - unnecessary_library_name - unnecessary_new - unnecessary_null_aware_assignments - unnecessary_null_aware_operator_on_extension_on_nullable @@ -185,9 +208,11 @@ linter: - unnecessary_string_interpolations - unnecessary_this - unnecessary_to_list_in_spreads + - unnecessary_unawaited + - unnecessary_underscores - unreachable_from_main - unrelated_type_equality_checks - - unsafe_html + - unsafe_variance - use_build_context_synchronously - use_colored_box - use_decorated_box @@ -199,6 +224,7 @@ linter: - use_key_in_widget_constructors - use_late_for_private_fields_and_variables - use_named_constants + - use_null_aware_elements - use_raw_strings - use_rethrow_when_possible - use_setters_to_change_properties @@ -207,5 +233,6 @@ linter: - use_super_parameters - use_test_throws_matchers - use_to_and_as_if_applicable + - use_truncating_division - valid_regexps - - void_checks \ No newline at end of file + - void_checks diff --git a/analysis_options.yaml b/analysis_options.yaml index b873dbc..df6701f 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -10,12 +10,14 @@ analyzer: # We explicitly enabled even conflicting rules and are fixing the conflict # in this file. included_file_warning: ignore - - todo: ignore exclude: # exclude all the generated files - packages/*/lib/**/*.*.dart +formatter: + page_width: 100 + trailing_commas: preserve + linter: rules: ## Disabled rules because the repository doesn't respect them (yet) @@ -93,6 +95,19 @@ linter: # There are situations where we use default in enums on purpose no_default_cases: false + # Sometimes static methods are more readable + prefer_constructors_over_static_methods: false + + # Conflicts with `omit_local_variable_types` + specify_nonobvious_local_variable_types: false + specify_nonobvious_property_types: false + + # Makes the code more verbose without adding much value + document_ignores: false + + # False positives + unsafe_variance: false + # Temporarily disabled to find more important issues public_member_api_docs: false avoid_print: false diff --git a/apps/design_system_gallery/pubspec.yaml b/apps/design_system_gallery/pubspec.yaml index 02e787c..7c78ea3 100644 --- a/apps/design_system_gallery/pubspec.yaml +++ b/apps/design_system_gallery/pubspec.yaml @@ -4,7 +4,7 @@ publish_to: 'none' version: 1.0.0+1 environment: - sdk: ^3.9.0 + sdk: ^3.10.0 dependencies: flutter: @@ -22,7 +22,7 @@ dev_dependencies: sdk: flutter flutter_lints: ^5.0.0 widgetbook_generator: ^3.20.1 - build_runner: ^2.10.4 + build_runner: ^2.4.15 flutter: uses-material-design: true \ No newline at end of file diff --git a/melos.yaml b/melos.yaml index 0be9381..98ed897 100644 --- a/melos.yaml +++ b/melos.yaml @@ -5,15 +5,16 @@ versioning: mode: independent packages: + - apps/** - packages/** command: bootstrap: # Dart and Flutter environment used in the project. environment: - sdk: ^3.6.2 + sdk: ^3.10.0 # We are not using carat '^' syntax here because flutter don't follow semantic versioning. - flutter: ">=3.27.4" + flutter: ">=3.38.1" # List of all the dependencies used in the project. dependencies: diff --git a/packages/stream_core/lib/src/api/interceptors/logging_interceptor.dart b/packages/stream_core/lib/src/api/interceptors/logging_interceptor.dart index 61694bd..0c507a0 100644 --- a/packages/stream_core/lib/src/api/interceptors/logging_interceptor.dart +++ b/packages/stream_core/lib/src/api/interceptors/logging_interceptor.dart @@ -1,4 +1,3 @@ -// ignore_for_file: lines_longer_than_80_chars // coverage:ignore-file import 'dart:math' as math; @@ -56,10 +55,10 @@ class LoggingInterceptor extends Interceptor { final bool error; /// InitialTab count to logPrint json response - static const int initialTab = 1; + static const initialTab = 1; /// 1 tab length - static const String tabStep = ' '; + static const tabStep = ' '; /// Print compact json response final bool compact; @@ -155,8 +154,7 @@ class LoggingInterceptor extends Interceptor { _printResponseHeader(_logPrintResponse, response); if (responseHeader) { final responseHeaders = {}; - response.headers - .forEach((k, list) => responseHeaders[k] = list.toString()); + response.headers.forEach((k, list) => responseHeaders[k] = list.toString()); _printMapAsTable(_logPrintResponse, responseHeaders, header: 'Headers'); } @@ -206,8 +204,7 @@ class LoggingInterceptor extends Interceptor { final method = response.requestOptions.method; _printBoxed( logPrint, - header: - 'Response ║ $method ║ Status: ${response.statusCode} ${response.statusMessage}', + header: 'Response ║ $method ║ Status: ${response.statusCode} ${response.statusMessage}', text: uri.toString(), ); } @@ -225,8 +222,7 @@ class LoggingInterceptor extends Interceptor { void Function(Object) logPrint, [ String pre = '', String suf = '╝', - ]) => - logPrint('$pre${'═' * maxWidth}$suf'); + ]) => logPrint('$pre${'═' * maxWidth}$suf'); void _printKV(void Function(Object) logPrint, String? key, Object? v) { final pre = '╟ $key: '; @@ -299,10 +295,12 @@ class LoggingInterceptor extends Interceptor { if (msg.length + indent.length > linWidth) { final lines = (msg.length / linWidth).ceil(); for (var i = 0; i < lines; ++i) { - logPrint('║${_indent(indentedTabs)} ${msg.substring( - i * linWidth, - math.min(i * linWidth + linWidth, msg.length), - )}'); + logPrint( + '║${_indent(indentedTabs)} ${msg.substring( + i * linWidth, + math.min(i * linWidth + linWidth, msg.length), + )}', + ); } } else { logPrint('║${_indent(indentedTabs)} $key: $msg${!isLast ? ',' : ''}'); @@ -351,11 +349,9 @@ class LoggingInterceptor extends Interceptor { _printLine(logPrint, '╚'); } - void _logPrintRequest(Object object) => - logPrint(InterceptStep.request, object); + void _logPrintRequest(Object object) => logPrint(InterceptStep.request, object); - void _logPrintResponse(Object object) => - logPrint(InterceptStep.response, object); + void _logPrintResponse(Object object) => logPrint(InterceptStep.response, object); void _logPrintError(Object object) => logPrint(InterceptStep.error, object); } diff --git a/packages/stream_core/lib/src/api/stream_core_dio_error.dart b/packages/stream_core/lib/src/api/stream_core_dio_error.dart index 33cf78b..fb0d345 100644 --- a/packages/stream_core/lib/src/api/stream_core_dio_error.dart +++ b/packages/stream_core/lib/src/api/stream_core_dio_error.dart @@ -13,9 +13,9 @@ class StreamDioException extends DioException { StackTrace? stackTrace, super.message, }) : super( - error: exception, - stackTrace: stackTrace ?? StackTrace.current, - ); + error: exception, + stackTrace: stackTrace ?? StackTrace.current, + ); final ClientException exception; } diff --git a/packages/stream_core/lib/src/attachment/uploader/attachment_uploader.dart b/packages/stream_core/lib/src/attachment/uploader/attachment_uploader.dart index 73eeaf9..b28e750 100644 --- a/packages/stream_core/lib/src/attachment/uploader/attachment_uploader.dart +++ b/packages/stream_core/lib/src/attachment/uploader/attachment_uploader.dart @@ -112,10 +112,11 @@ class StreamAttachmentUploader { /// /// Receives the [attachmentId] and upload [progress] as a value between 0.0 and 1.0 /// for individual attachments during batch upload. -typedef OnBatchUploadProgress = void Function( - String attachmentId, - double progress, -); +typedef OnBatchUploadProgress = + void Function( + String attachmentId, + double progress, + ); /// Extension providing batch upload functionality for [StreamAttachmentUploader]. /// @@ -150,7 +151,8 @@ extension StreamAttachmentUploaderBatch on StreamAttachmentUploader { upload( attachment, onProgress: onProgress?.let( - (f) => (progress) => f(attachment.id, progress), + (f) => + (progress) => f(attachment.id, progress), ), ), ), diff --git a/packages/stream_core/lib/src/errors/stream_api_error.dart b/packages/stream_core/lib/src/errors/stream_api_error.dart index 4d33bcb..c18d8e9 100644 --- a/packages/stream_core/lib/src/errors/stream_api_error.dart +++ b/packages/stream_core/lib/src/errors/stream_api_error.dart @@ -54,24 +54,23 @@ class StreamApiError extends Equatable { Map toJson() => _$StreamApiErrorToJson(this); /// Creates a [StreamApiError] from a JSON map. - static StreamApiError fromJson(Map json) => - _$StreamApiErrorFromJson(json); + static StreamApiError fromJson(Map json) => _$StreamApiErrorFromJson(json); @override List get props => [ - code, - details, - duration, - exceptionFields, - message, - moreInfo, - statusCode, - unrecoverable, - ]; + code, + details, + duration, + exceptionFields, + message, + moreInfo, + statusCode, + unrecoverable, + ]; } -final _tokenInvalidErrorCodes = _range(40, 42); -final _clientErrorCodes = _range(400, 499); +final List _tokenInvalidErrorCodes = _range(40, 42); +final List _clientErrorCodes = _range(400, 499); /// Extension methods for [StreamApiError] to provide convenient error type checks. extension StreamApiErrorExtension on StreamApiError { diff --git a/packages/stream_core/lib/src/errors/stream_api_error.g.dart b/packages/stream_core/lib/src/errors/stream_api_error.g.dart index 15ba50e..e3fd613 100644 --- a/packages/stream_core/lib/src/errors/stream_api_error.g.dart +++ b/packages/stream_core/lib/src/errors/stream_api_error.g.dart @@ -6,30 +6,26 @@ part of 'stream_api_error.dart'; // JsonSerializableGenerator // ************************************************************************** -StreamApiError _$StreamApiErrorFromJson(Map json) => - StreamApiError( - code: (json['code'] as num).toInt(), - details: (json['details'] as List) - .map((e) => (e as num).toInt()) - .toList(), - duration: json['duration'] as String, - exceptionFields: (json['exception_fields'] as Map?)?.map( - (k, e) => MapEntry(k, e as String), - ), - message: json['message'] as String, - moreInfo: json['more_info'] as String, - statusCode: (json['StatusCode'] as num).toInt(), - unrecoverable: json['unrecoverable'] as bool?, - ); +StreamApiError _$StreamApiErrorFromJson(Map json) => StreamApiError( + code: (json['code'] as num).toInt(), + details: (json['details'] as List).map((e) => (e as num).toInt()).toList(), + duration: json['duration'] as String, + exceptionFields: (json['exception_fields'] as Map?)?.map( + (k, e) => MapEntry(k, e as String), + ), + message: json['message'] as String, + moreInfo: json['more_info'] as String, + statusCode: (json['StatusCode'] as num).toInt(), + unrecoverable: json['unrecoverable'] as bool?, +); -Map _$StreamApiErrorToJson(StreamApiError instance) => - { - 'code': instance.code, - 'details': instance.details, - 'duration': instance.duration, - 'exception_fields': instance.exceptionFields, - 'message': instance.message, - 'more_info': instance.moreInfo, - 'StatusCode': instance.statusCode, - 'unrecoverable': instance.unrecoverable, - }; +Map _$StreamApiErrorToJson(StreamApiError instance) => { + 'code': instance.code, + 'details': instance.details, + 'duration': instance.duration, + 'exception_fields': instance.exceptionFields, + 'message': instance.message, + 'more_info': instance.moreInfo, + 'StatusCode': instance.statusCode, + 'unrecoverable': instance.unrecoverable, +}; diff --git a/packages/stream_core/lib/src/logger/impl/external_logger.dart b/packages/stream_core/lib/src/logger/impl/external_logger.dart index 5552e76..56a749f 100644 --- a/packages/stream_core/lib/src/logger/impl/external_logger.dart +++ b/packages/stream_core/lib/src/logger/impl/external_logger.dart @@ -1,12 +1,13 @@ import '../stream_logger.dart'; -typedef ExternalFunction = void Function( - Priority priority, - String tag, - MessageBuilder message, [ - Object? error, - StackTrace? stk, -]); +typedef ExternalFunction = + void Function( + Priority priority, + String tag, + MessageBuilder message, [ + Object? error, + StackTrace? stk, + ]); class ExternalStreamLogger extends StreamLogger { const ExternalStreamLogger(this.external); diff --git a/packages/stream_core/lib/src/logger/impl/file_logger.dart b/packages/stream_core/lib/src/logger/impl/file_logger.dart index 634deb7..27f66db 100644 --- a/packages/stream_core/lib/src/logger/impl/file_logger.dart +++ b/packages/stream_core/lib/src/logger/impl/file_logger.dart @@ -7,12 +7,12 @@ import 'package:intl/intl.dart'; import '../../utils/standard.dart'; import '../stream_logger.dart'; -const String _tag = 'SV:FileLogger'; +const _tag = 'SV:FileLogger'; const int _defaultSize = 12 * 1024 * 1024; -const String _shareableFilePrefix = 'stream_log_'; -const String _internalFile0 = 'internal_0.txt'; -const String _internalFile1 = 'internal_1.txt'; +const _shareableFilePrefix = 'stream_log_'; +const _internalFile0 = 'internal_0.txt'; +const _internalFile1 = 'internal_1.txt'; typedef FileLogSender = Future Function(File); @@ -26,8 +26,7 @@ class FileStreamLogger extends StreamLogger { this.console, }); - static final Finalizer _finalizer = - Finalizer((ioSink) async => ioSink.close()); + static final Finalizer _finalizer = Finalizer((ioSink) => ioSink.close()); final FileLogConfig config; final FileLogSender? sender; @@ -73,9 +72,7 @@ class FileStreamLogger extends StreamLogger { final File currentFile; if (!_file0.existsSync() || !_file1.existsSync()) { currentFile = _file0; - } else if (_file0 - .lastModifiedSync() - .isAfter(_file1.lastModifiedSync())) { + } else if (_file0.lastModifiedSync().isAfter(_file1.lastModifiedSync())) { currentFile = _file0; } else { currentFile = _file1; @@ -120,7 +117,8 @@ class FileStreamLogger extends StreamLogger { Future clear() async { try { _logD( - () => '[clear] before; file0: ${_file0.lengthSync()}, ' + () => + '[clear] before; file0: ${_file0.lengthSync()}, ' 'file1: ${_file1.lengthSync()}', ); final currentIO = _currentIO; @@ -139,7 +137,8 @@ class FileStreamLogger extends StreamLogger { _finalizer.attach(this, it, detach: this); }); _logV( - () => '[clear] after; file0: ${_file0.lengthSync()}, ' + () => + '[clear] after; file0: ${_file0.lengthSync()}, ' 'file1: ${_file1.lengthSync()}', ); } catch (e, stk) { @@ -166,19 +165,20 @@ class FileStreamLogger extends StreamLogger { } Future prepareShareable() async { - final filename = '$_shareableFilePrefix' + final filename = + '$_shareableFilePrefix' '${_dateFormat.format(DateTime.now())}.txt'; - final out = File('${_tempsDir.path}$pathSeparator$filename') - ..createSync(recursive: true); + final out = File('${_tempsDir.path}$pathSeparator$filename')..createSync(recursive: true); _logD(() => '[prepareShareable] out: $out'); IOSink? writer; try { writer = out.openWrite(mode: FileMode.append); writer.writeln(await _buildHeader()); - final filtered = [_file0, _file1] - .where((file) => file.existsSync()) - .sortedBy((file) => file.lastModifiedSync()); + final filtered = [ + _file0, + _file1, + ].where((file) => file.existsSync()).sortedBy((file) => file.lastModifiedSync()); for (final file in filtered) { if (file.existsSync()) { await writer.addStream(file.openRead()); diff --git a/packages/stream_core/lib/src/logger/stream_log.dart b/packages/stream_core/lib/src/logger/stream_log.dart index 9862603..f4709d1 100644 --- a/packages/stream_core/lib/src/logger/stream_log.dart +++ b/packages/stream_core/lib/src/logger/stream_log.dart @@ -1,3 +1,5 @@ +// ignore_for_file: omit_obvious_property_types + import 'stream_logger.dart'; StreamLog get streamLog => StreamLog(); @@ -9,7 +11,7 @@ class StreamLog { StreamLog._(); - static final StreamLog _instance = StreamLog._(); + static final _instance = StreamLog._(); StreamLogger _logger = const SilentStreamLogger(); IsLoggableValidator _validator = (Priority priority, Tag tag) => false; diff --git a/packages/stream_core/lib/src/logger/stream_logger.dart b/packages/stream_core/lib/src/logger/stream_logger.dart index e0c9f4f..6bfbeac 100644 --- a/packages/stream_core/lib/src/logger/stream_logger.dart +++ b/packages/stream_core/lib/src/logger/stream_logger.dart @@ -1,4 +1,4 @@ -final _priorityEmojiMapper = { +final Map _priorityEmojiMapper = { Priority.error: '🚨', Priority.warning: '⚠️', Priority.info: 'ℹ️', @@ -6,7 +6,7 @@ final _priorityEmojiMapper = { Priority.verbose: '🔍', }; -final _priorityNameMapper = { +final Map _priorityNameMapper = { Priority.error: 'E', Priority.warning: 'W', Priority.info: 'I', @@ -41,7 +41,8 @@ enum Priority implements Comparable { info(level: 4), warning(level: 5), error(level: 6), - none(level: 7); + none(level: 7) + ; const Priority({required this.level}); diff --git a/packages/stream_core/lib/src/platform/current_platform.dart b/packages/stream_core/lib/src/platform/current_platform.dart index 7e0d133..8cb934a 100644 --- a/packages/stream_core/lib/src/platform/current_platform.dart +++ b/packages/stream_core/lib/src/platform/current_platform.dart @@ -1,5 +1,4 @@ -import 'detector/platform_detector.dart' - if (dart.library.io) 'detector/platform_detector_io.dart'; +import 'detector/platform_detector.dart' if (dart.library.io) 'detector/platform_detector_io.dart'; /// Platform detection utility for identifying the current runtime environment. /// @@ -87,7 +86,8 @@ enum PlatformType { linux('linux'), /// Fuchsia: - fuchsia('fuchsia'); + fuchsia('fuchsia') + ; /// Creates a [PlatformType] with the specified [operatingSystem] identifier. const PlatformType(this.operatingSystem); diff --git a/packages/stream_core/lib/src/query/filter/filter.dart b/packages/stream_core/lib/src/query/filter/filter.dart index af7d10d..fd9bef3 100644 --- a/packages/stream_core/lib/src/query/filter/filter.dart +++ b/packages/stream_core/lib/src/query/filter/filter.dart @@ -1,3 +1,5 @@ +// ignore_for_file: matching_super_parameters + import '../../utils.dart'; import 'filter_operation_utils.dart'; import 'filter_operator.dart'; @@ -241,8 +243,7 @@ sealed class ComparisonOperator extends Filter { /// **Supported with**: `.equal` factory method final class EqualOperator extends ComparisonOperator { /// Creates an equality filter for the specified [field] and [value]. - const EqualOperator(super.field, super.value) - : super._(operator: FilterOperator.equal); + const EqualOperator(super.field, super.value) : super._(operator: FilterOperator.equal); @override bool matches(T other) { @@ -273,8 +274,7 @@ final class EqualOperator extends ComparisonOperator { /// **Supported with**: `.greater` factory method final class GreaterOperator extends ComparisonOperator { /// Creates a greater-than filter for the specified [field] and [value]. - const GreaterOperator(super.field, super.value) - : super._(operator: FilterOperator.greater); + const GreaterOperator(super.field, super.value) : super._(operator: FilterOperator.greater); @override bool matches(T other) { @@ -293,11 +293,10 @@ final class GreaterOperator extends ComparisonOperator { /// Greater-than-or-equal comparison filter. /// /// Primarily used with numeric values and dates. -final class GreaterOrEqualOperator - extends ComparisonOperator { +final class GreaterOrEqualOperator extends ComparisonOperator { /// Creates a greater-than-or-equal filter for the specified [field] and [value]. const GreaterOrEqualOperator(super.field, super.value) - : super._(operator: FilterOperator.greaterOrEqual); + : super._(operator: FilterOperator.greaterOrEqual); @override bool matches(T other) { @@ -318,8 +317,7 @@ final class GreaterOrEqualOperator /// Primarily used with numeric values and dates. final class LessOperator extends ComparisonOperator { /// Creates a less-than filter for the specified [field] and [value]. - const LessOperator(super.field, super.value) - : super._(operator: FilterOperator.less); + const LessOperator(super.field, super.value) : super._(operator: FilterOperator.less); @override bool matches(T other) { @@ -338,11 +336,10 @@ final class LessOperator extends ComparisonOperator { /// Less-than-or-equal comparison filter. /// /// Primarily used with numeric values and dates. -final class LessOrEqualOperator - extends ComparisonOperator { +final class LessOrEqualOperator extends ComparisonOperator { /// Creates a less-than-or-equal filter for the specified [field] and [value]. const LessOrEqualOperator(super.field, super.value) - : super._(operator: FilterOperator.lessOrEqual); + : super._(operator: FilterOperator.lessOrEqual); @override bool matches(T other) { @@ -398,7 +395,7 @@ sealed class ListOperator extends Filter { final class InOperator extends ListOperator { /// Creates an 'in' filter for the specified [field] and [values] iterable. const InOperator(super.field, Iterable super.values) - : super._(operator: FilterOperator.in_); + : super._(operator: FilterOperator.in_); @override bool matches(T other) { @@ -422,8 +419,7 @@ final class InOperator extends ListOperator { /// **Supported with**: `.contains` factory method final class ContainsOperator extends ListOperator { /// Creates a contains filter for the specified [field] and [value]. - const ContainsOperator(super.field, super.value) - : super._(operator: FilterOperator.contains_); + const ContainsOperator(super.field, super.value) : super._(operator: FilterOperator.contains_); @override bool matches(T other) { @@ -511,8 +507,7 @@ sealed class EvaluationOperator extends Filter { /// **Supported with**: `.query` factory method final class QueryOperator extends EvaluationOperator { /// Creates a text search filter for the specified [field] and search [query]. - const QueryOperator(super.field, super.query) - : super._(operator: FilterOperator.query); + const QueryOperator(super.field, super.query) : super._(operator: FilterOperator.query); @override bool matches(T other) { @@ -529,11 +524,10 @@ final class QueryOperator extends EvaluationOperator { /// Word prefix matching filter for autocomplete. /// /// Matches field values where any word starts with the provided prefix. -final class AutoCompleteOperator - extends EvaluationOperator { +final class AutoCompleteOperator extends EvaluationOperator { /// Creates an autocomplete filter for the specified [field] and prefix [query]. const AutoCompleteOperator(super.field, super.query) - : super._(operator: FilterOperator.autoComplete); + : super._(operator: FilterOperator.autoComplete); @override bool matches(T other) { diff --git a/packages/stream_core/lib/src/query/filter/location/bounding_box.g.dart b/packages/stream_core/lib/src/query/filter/location/bounding_box.g.dart index 90bb530..ecb84e5 100644 --- a/packages/stream_core/lib/src/query/filter/location/bounding_box.g.dart +++ b/packages/stream_core/lib/src/query/filter/location/bounding_box.g.dart @@ -6,10 +6,9 @@ part of 'bounding_box.dart'; // JsonSerializableGenerator // ************************************************************************** -Map _$BoundingBoxToJson(BoundingBox instance) => - { - 'ne_lat': instance.neLat, - 'ne_lng': instance.neLng, - 'sw_lat': instance.swLat, - 'sw_lng': instance.swLng, - }; +Map _$BoundingBoxToJson(BoundingBox instance) => { + 'ne_lat': instance.neLat, + 'ne_lng': instance.neLng, + 'sw_lat': instance.swLat, + 'sw_lng': instance.swLng, +}; diff --git a/packages/stream_core/lib/src/query/filter/location/circular_region.g.dart b/packages/stream_core/lib/src/query/filter/location/circular_region.g.dart index 66a08e0..2690c73 100644 --- a/packages/stream_core/lib/src/query/filter/location/circular_region.g.dart +++ b/packages/stream_core/lib/src/query/filter/location/circular_region.g.dart @@ -6,9 +6,8 @@ part of 'circular_region.dart'; // JsonSerializableGenerator // ************************************************************************** -Map _$CircularRegionToJson(CircularRegion instance) => - { - 'lat': instance.lat, - 'lng': instance.lng, - 'distance': instance.distance, - }; +Map _$CircularRegionToJson(CircularRegion instance) => { + 'lat': instance.lat, + 'lng': instance.lng, + 'distance': instance.distance, +}; diff --git a/packages/stream_core/lib/src/query/filter/location/location_coordinate.dart b/packages/stream_core/lib/src/query/filter/location/location_coordinate.dart index 2164904..cb67d04 100644 --- a/packages/stream_core/lib/src/query/filter/location/location_coordinate.dart +++ b/packages/stream_core/lib/src/query/filter/location/location_coordinate.dart @@ -79,9 +79,8 @@ class LocationCoordinate { final latComponent = _square(sinDLat); // Calculate longitude component: sin²(Δlon/2) * cos(lat1) * cos(lat2) - final lonComponent = _square(sinDLon) * - math.cos(_degToRad(latitude)) * - math.cos(_degToRad(other.latitude)); + final lonComponent = + _square(sinDLon) * math.cos(_degToRad(latitude)) * math.cos(_degToRad(other.latitude)); // Combine components final a = latComponent + lonComponent; diff --git a/packages/stream_core/lib/src/query/sort.dart b/packages/stream_core/lib/src/query/sort.dart index 164fbc4..67afa67 100644 --- a/packages/stream_core/lib/src/query/sort.dart +++ b/packages/stream_core/lib/src/query/sort.dart @@ -15,7 +15,8 @@ enum SortDirection { /// Sort in descending order (Z to A, 9 to 1, etc.). @JsonValue(-1) - desc(-1); + desc(-1) + ; /// Creates a new [SortDirection] instance with the specified direction. const SortDirection(this.value); @@ -32,7 +33,7 @@ enum NullOrdering { /// Null values appear at the end of the sorted list, /// regardless of sort direction (ASC or DESC). - nullsLast; + nullsLast, } /// Signature for a function that retrieves a sortable field value of type [V] from @@ -44,12 +45,13 @@ typedef SortFieldValueGetter = V? Function(T); /// A comparator function that compares two instances of type [T] based on /// a specified field, sort direction, and null ordering. -typedef SortFieldComparator = int Function( - T? a, - T? b, - SortDirection direction, - NullOrdering nullOrdering, -); +typedef SortFieldComparator = + int Function( + T? a, + T? b, + SortDirection direction, + NullOrdering nullOrdering, + ); /// A sort specification that defines how to order a collection of objects. /// diff --git a/packages/stream_core/lib/src/query/sort.g.dart b/packages/stream_core/lib/src/query/sort.g.dart index 3036cd4..f9ed711 100644 --- a/packages/stream_core/lib/src/query/sort.g.dart +++ b/packages/stream_core/lib/src/query/sort.g.dart @@ -6,11 +6,10 @@ part of 'sort.dart'; // JsonSerializableGenerator // ************************************************************************** -Map _$SortToJson(Sort instance) => - { - 'field': Sort._fieldToJson(instance.field), - 'direction': _$SortDirectionEnumMap[instance.direction]!, - }; +Map _$SortToJson(Sort instance) => { + 'field': Sort._fieldToJson(instance.field), + 'direction': _$SortDirectionEnumMap[instance.direction]!, +}; const _$SortDirectionEnumMap = { SortDirection.asc: 1, diff --git a/packages/stream_core/lib/src/user/connect_user_details_request.g.dart b/packages/stream_core/lib/src/user/connect_user_details_request.g.dart index 3b4fe26..f8f51e1 100644 --- a/packages/stream_core/lib/src/user/connect_user_details_request.g.dart +++ b/packages/stream_core/lib/src/user/connect_user_details_request.g.dart @@ -6,8 +6,7 @@ part of 'connect_user_details_request.dart'; // JsonSerializableGenerator // ************************************************************************** -Map _$ConnectUserDetailsRequestToJson( - ConnectUserDetailsRequest instance) => +Map _$ConnectUserDetailsRequestToJson(ConnectUserDetailsRequest instance) => { 'id': instance.id, 'image': instance.image, diff --git a/packages/stream_core/lib/src/user/token_manager.dart b/packages/stream_core/lib/src/user/token_manager.dart index aa9c6dc..288f0d4 100644 --- a/packages/stream_core/lib/src/user/token_manager.dart +++ b/packages/stream_core/lib/src/user/token_manager.dart @@ -68,7 +68,7 @@ class TokenManager { /// at a time. /// /// Returns a [Future] that resolves to a [UserToken] for the user. - Future getToken() async { + Future getToken() { final snapshot = _cachedToken; return synchronized(() async { // If the snapshot is no longer equal to the cached token, it means diff --git a/packages/stream_core/lib/src/user/user.dart b/packages/stream_core/lib/src/user/user.dart index 9b0fcd5..0c471b0 100644 --- a/packages/stream_core/lib/src/user/user.dart +++ b/packages/stream_core/lib/src/user/user.dart @@ -16,14 +16,13 @@ class User extends Equatable { this.role = 'user', this.type = UserType.regular, Map? custom, - }) : originalName = name, - custom = custom ?? const {}; + }) : originalName = name, + custom = custom ?? const {}; /// Creates a guest user with the provided id. /// - Parameter userId: the id of the user. /// - Returns: a guest `User`. - const User.guest(String userId) - : this(id: userId, name: userId, type: UserType.guest); + const User.guest(String userId) : this(id: userId, name: userId, type: UserType.guest); /// Creates an anonymous user. /// - Returns: an anonymous `User`. @@ -55,13 +54,13 @@ class User extends Equatable { @override List get props => [ - id, - image, - role, - type, - originalName, - custom, - ]; + id, + image, + role, + type, + originalName, + custom, + ]; } /// The user authorization type. diff --git a/packages/stream_core/lib/src/user/user_token.dart b/packages/stream_core/lib/src/user/user_token.dart index 63fe1c6..bdb7cd3 100644 --- a/packages/stream_core/lib/src/user/user_token.dart +++ b/packages/stream_core/lib/src/user/user_token.dart @@ -112,7 +112,8 @@ enum AuthType { /// /// Allows unauthenticated access with limited permissions. /// Used for public content access or guest user scenarios. - anonymous('anonymous'); + anonymous('anonymous') + ; /// Constructs an [AuthType] with the associated header value. const AuthType(this.headerValue); diff --git a/packages/stream_core/lib/src/user/ws_auth_message_request.g.dart b/packages/stream_core/lib/src/user/ws_auth_message_request.g.dart index 9e4f2ae..e9c2974 100644 --- a/packages/stream_core/lib/src/user/ws_auth_message_request.g.dart +++ b/packages/stream_core/lib/src/user/ws_auth_message_request.g.dart @@ -6,8 +6,7 @@ part of 'ws_auth_message_request.dart'; // JsonSerializableGenerator // ************************************************************************** -Map _$WsAuthMessageRequestToJson( - WsAuthMessageRequest instance) => +Map _$WsAuthMessageRequestToJson(WsAuthMessageRequest instance) => { 'stringify': instance.stringify, 'hash_code': instance.hashCode, diff --git a/packages/stream_core/lib/src/utils/comparable_field.dart b/packages/stream_core/lib/src/utils/comparable_field.dart index 00c1310..692ad7c 100644 --- a/packages/stream_core/lib/src/utils/comparable_field.dart +++ b/packages/stream_core/lib/src/utils/comparable_field.dart @@ -41,8 +41,7 @@ import 'package:meta/meta.dart'; /// print(intField?.compareTo(doubleField!)); // 0 (equal) /// ``` @immutable -class ComparableField - implements Comparable> { +class ComparableField implements Comparable> { const ComparableField._(this.value); /// Creates a [ComparableField] from [value]. @@ -84,8 +83,8 @@ class ComparableField (final bool a, final bool b) when a == b => 0, (final bool a, final bool b) => a && !b ? 1 : -1, _ => throw ArgumentError( - 'Incompatible types: ${value.runtimeType} vs ${other.value.runtimeType}', - ), + 'Incompatible types: ${value.runtimeType} vs ${other.value.runtimeType}', + ), }; } } diff --git a/packages/stream_core/lib/src/utils/disposable.dart b/packages/stream_core/lib/src/utils/disposable.dart index 1ef2462..be10176 100644 --- a/packages/stream_core/lib/src/utils/disposable.dart +++ b/packages/stream_core/lib/src/utils/disposable.dart @@ -1,3 +1,5 @@ +// ignore_for_file: avoid_futureor_void, unnecessary_async + import 'dart:async'; import 'package:meta/meta.dart'; @@ -6,7 +8,7 @@ import 'package:meta/meta.dart'; mixin class Disposable { /// Returns `true` if this object has been disposed. bool get isDisposed => _disposed; - bool _disposed = false; + var _disposed = false; /// Disposes of this object. @mustCallSuper diff --git a/packages/stream_core/lib/src/utils/event_emitter.dart b/packages/stream_core/lib/src/utils/event_emitter.dart index 0bda35c..11d20b7 100644 --- a/packages/stream_core/lib/src/utils/event_emitter.dart +++ b/packages/stream_core/lib/src/utils/event_emitter.dart @@ -57,8 +57,8 @@ typedef EventEmitter = SharedEmitter; /// See also: /// - [EventEmitter] for the read-only interface. /// - [EventResolver] for the resolver function signature. -final class MutableEventEmitter - extends SharedEmitterImpl implements MutableSharedEmitter { +final class MutableEventEmitter extends SharedEmitterImpl + implements MutableSharedEmitter { /// Creates a [MutableEventEmitter] with optional event [resolvers]. /// /// Resolvers are applied in order to each emitted event until one returns diff --git a/packages/stream_core/lib/src/utils/result.dart b/packages/stream_core/lib/src/utils/result.dart index 034f809..07c66ca 100644 --- a/packages/stream_core/lib/src/utils/result.dart +++ b/packages/stream_core/lib/src/utils/result.dart @@ -94,8 +94,10 @@ extension PatternMatching on Result { T getOrThrow() { return switch (this) { Success(:final data) => data, - Failure(:final error, :final stackTrace) => - Error.throwWithStackTrace(error, stackTrace ?? StackTrace.current), + Failure(:final error, :final stackTrace) => Error.throwWithStackTrace( + error, + stackTrace ?? StackTrace.current, + ), }; } @@ -184,8 +186,8 @@ extension PatternMatching on Result { return switch (this) { Success(:final data) => Result.success(data as R), Failure(:final error, :final stackTrace) => Result.success( - transform(error, stackTrace), - ), + transform(error, stackTrace), + ), }; } @@ -200,8 +202,8 @@ extension PatternMatching on Result { return switch (this) { Success(:final data) => Result.success(data as R), Failure(:final error, :final stackTrace) => runSafelySync( - () => transform(error, stackTrace), - ), + () => transform(error, stackTrace), + ), }; } diff --git a/packages/stream_core/lib/src/utils/shared_emitter.dart b/packages/stream_core/lib/src/utils/shared_emitter.dart index 0c52b06..c3005c9 100644 --- a/packages/stream_core/lib/src/utils/shared_emitter.dart +++ b/packages/stream_core/lib/src/utils/shared_emitter.dart @@ -98,8 +98,7 @@ abstract interface class MutableSharedEmitter extends SharedEmitter { /// /// See also: /// - [MutableSharedEmitter] for the interface. -class SharedEmitterImpl extends StreamView - implements MutableSharedEmitter { +class SharedEmitterImpl extends StreamView implements MutableSharedEmitter { /// Creates a [SharedEmitterImpl]. /// /// Supports synchronous or asynchronous event emission via [sync], and diff --git a/packages/stream_core/lib/src/utils/state_emitter.dart b/packages/stream_core/lib/src/utils/state_emitter.dart index 5bb0799..8494142 100644 --- a/packages/stream_core/lib/src/utils/state_emitter.dart +++ b/packages/stream_core/lib/src/utils/state_emitter.dart @@ -71,8 +71,7 @@ abstract interface class MutableStateEmitter extends StateEmitter /// /// See also: /// - [MutableStateEmitter] for the interface. -class StateEmitterImpl extends StreamView - implements MutableStateEmitter { +class StateEmitterImpl extends StreamView implements MutableStateEmitter { /// Creates a [StateEmitterImpl] with the given [initialValue]. /// /// Supports synchronous or asynchronous state emission via [sync]. diff --git a/packages/stream_core/lib/src/ws/client/engine/stream_web_socket_engine.dart b/packages/stream_core/lib/src/ws/client/engine/stream_web_socket_engine.dart index 5f5194c..7a70596 100644 --- a/packages/stream_core/lib/src/ws/client/engine/stream_web_socket_engine.dart +++ b/packages/stream_core/lib/src/ws/client/engine/stream_web_socket_engine.dart @@ -36,9 +36,9 @@ class StreamWebSocketEngine implements WebSocketEngine { WebSocketProvider? wsProvider, WebSocketEngineListener? listener, required WebSocketMessageCodec messageCodec, - }) : _wsProvider = wsProvider ?? _createWebSocket, - _messageCodec = messageCodec, - _listener = listener; + }) : _wsProvider = wsProvider ?? _createWebSocket, + _messageCodec = messageCodec, + _listener = listener; final WebSocketProvider _wsProvider; final WebSocketMessageCodec _messageCodec; diff --git a/packages/stream_core/lib/src/ws/client/engine/web_socket_engine.dart b/packages/stream_core/lib/src/ws/client/engine/web_socket_engine.dart index 9553267..29acf58 100644 --- a/packages/stream_core/lib/src/ws/client/engine/web_socket_engine.dart +++ b/packages/stream_core/lib/src/ws/client/engine/web_socket_engine.dart @@ -181,8 +181,8 @@ class WebSocketEngineException with EquatableMixin implements Exception { String? reason, int? code = 0, this.error, - }) : reason = reason ?? 'Unknown', - code = code ?? 0; + }) : reason = reason ?? 'Unknown', + code = code ?? 0; final String reason; final int code; diff --git a/packages/stream_core/lib/src/ws/client/reconnect/automatic_reconnection_policy.dart b/packages/stream_core/lib/src/ws/client/reconnect/automatic_reconnection_policy.dart index 6481c3a..e26ee52 100644 --- a/packages/stream_core/lib/src/ws/client/reconnect/automatic_reconnection_policy.dart +++ b/packages/stream_core/lib/src/ws/client/reconnect/automatic_reconnection_policy.dart @@ -12,8 +12,7 @@ abstract interface class AutomaticReconnectionPolicy { /// A reconnection policy that checks if automatic reconnection is enabled /// based on the current state of the WebSocket connection. -class WebSocketAutomaticReconnectionPolicy - implements AutomaticReconnectionPolicy { +class WebSocketAutomaticReconnectionPolicy implements AutomaticReconnectionPolicy { /// Creates a [WebSocketAutomaticReconnectionPolicy]. WebSocketAutomaticReconnectionPolicy({required this.connectionState}); @@ -30,8 +29,7 @@ class WebSocketAutomaticReconnectionPolicy /// A reconnection policy that checks for internet connectivity before allowing /// reconnection. This prevents unnecessary reconnection attempts when there's no /// network available. -class InternetAvailabilityReconnectionPolicy - implements AutomaticReconnectionPolicy { +class InternetAvailabilityReconnectionPolicy implements AutomaticReconnectionPolicy { /// Creates an [InternetAvailabilityReconnectionPolicy]. InternetAvailabilityReconnectionPolicy({required this.networkState}); @@ -69,7 +67,7 @@ enum Operator { /// Requires ANY policy to return `true` for reconnection to be allowed. /// If at least one policy returns `true`, reconnection will be attempted. - or; + or, } /// A composite reconnection policy that combines multiple [policies] using a diff --git a/packages/stream_core/lib/src/ws/client/reconnect/connection_recovery_handler.dart b/packages/stream_core/lib/src/ws/client/reconnect/connection_recovery_handler.dart index 3dc70c1..3cbfcd3 100644 --- a/packages/stream_core/lib/src/ws/client/reconnect/connection_recovery_handler.dart +++ b/packages/stream_core/lib/src/ws/client/reconnect/connection_recovery_handler.dart @@ -42,23 +42,23 @@ class ConnectionRecoveryHandler extends Disposable { bool keepConnectionAliveInBackground = false, List? policies, RetryStrategy? retryStrategy, - }) : _client = client, - _reconnectStrategy = retryStrategy ?? RetryStrategy(), - _keepConnectionAliveInBackground = keepConnectionAliveInBackground, - _policies = [ - if (policies != null) ...policies, - WebSocketAutomaticReconnectionPolicy( - connectionState: client.connectionState, - ), - if (networkStateProvider case final provider?) - InternetAvailabilityReconnectionPolicy( - networkState: provider.state, - ), - if (lifecycleStateProvider case final provider?) - BackgroundStateReconnectionPolicy( - appLifecycleState: provider.state, - ), - ] { + }) : _client = client, + _reconnectStrategy = retryStrategy ?? RetryStrategy(), + _keepConnectionAliveInBackground = keepConnectionAliveInBackground, + _policies = [ + if (policies != null) ...policies, + WebSocketAutomaticReconnectionPolicy( + connectionState: client.connectionState, + ), + if (networkStateProvider case final provider?) + InternetAvailabilityReconnectionPolicy( + networkState: provider.state, + ), + if (lifecycleStateProvider case final provider?) + BackgroundStateReconnectionPolicy( + appLifecycleState: provider.state, + ), + ] { // Listen to connection state changes. _client.connectionState.on(_onConnectionStateChanged).addTo(_subscriptions); diff --git a/packages/stream_core/lib/src/ws/client/reconnect/retry_strategy.dart b/packages/stream_core/lib/src/ws/client/reconnect/retry_strategy.dart index 43e6256..84278d0 100644 --- a/packages/stream_core/lib/src/ws/client/reconnect/retry_strategy.dart +++ b/packages/stream_core/lib/src/ws/client/reconnect/retry_strategy.dart @@ -65,13 +65,14 @@ class DefaultRetryStrategy implements RetryStrategy { static const maximumReconnectionDelayInSeconds = 25; @override - int consecutiveFailuresCount = 0; + int get consecutiveFailuresCount => _consecutiveFailuresCount; + var _consecutiveFailuresCount = 0; @override - void incrementConsecutiveFailures() => consecutiveFailuresCount++; + void incrementConsecutiveFailures() => _consecutiveFailuresCount++; @override - void resetConsecutiveFailures() => consecutiveFailuresCount = 0; + void resetConsecutiveFailures() => _consecutiveFailuresCount = 0; @override Duration getNextRetryDelay() { diff --git a/packages/stream_core/lib/src/ws/client/stream_web_socket_client.dart b/packages/stream_core/lib/src/ws/client/stream_web_socket_client.dart index 5022433..1c531f8 100644 --- a/packages/stream_core/lib/src/ws/client/stream_web_socket_client.dart +++ b/packages/stream_core/lib/src/ws/client/stream_web_socket_client.dart @@ -40,8 +40,7 @@ WsRequest _defaultPingRequestBuilder([HealthCheckInfo? info]) { /// /// await client.connect(); /// ``` -class StreamWebSocketClient - implements WebSocketHealthListener, WebSocketEngineListener { +class StreamWebSocketClient implements WebSocketHealthListener, WebSocketEngineListener { /// Creates a new instance of [StreamWebSocketClient]. StreamWebSocketClient({ required this.options, @@ -81,9 +80,10 @@ class StreamWebSocketClient /// /// Emits state changes as the WebSocket transitions through different connection states. ConnectionStateEmitter get connectionState => _connectionStateEmitter; - late final _connectionStateEmitter = MutableConnectionStateEmitter( - const WebSocketConnectionState.initialized(), - ); + late final MutableStateEmitter _connectionStateEmitter = + MutableConnectionStateEmitter( + const WebSocketConnectionState.initialized(), + ); set _connectionState(WebSocketConnectionState connectionState) { // Return early if the state hasn't changed. @@ -121,7 +121,7 @@ class StreamWebSocketClient final result = await _engine.open(options); // If some failure occurs, disconnect and rethrow the error. - return result.recover((_, __) => onClose()).getOrThrow(); + return result.recover((_, _) => onClose()).getOrThrow(); } /// Closes the WebSocket connection. @@ -162,11 +162,11 @@ class StreamWebSocketClient // Any active state that wasn’t user/system initiated becomes server initiated. Connecting() || Authenticating() || Connected() => ServerInitiated( - error: WebSocketEngineException( - code: closeCode, - reason: closeReason, - ), + error: WebSocketEngineException( + code: closeCode, + reason: closeReason, ), + ), // Not meaningful to transition from these; just log and bail. Initialized() || Disconnected() => null, diff --git a/packages/stream_core/lib/src/ws/client/web_socket_connection_state.dart b/packages/stream_core/lib/src/ws/client/web_socket_connection_state.dart index 4eff935..87a6cac 100644 --- a/packages/stream_core/lib/src/ws/client/web_socket_connection_state.dart +++ b/packages/stream_core/lib/src/ws/client/web_socket_connection_state.dart @@ -16,8 +16,7 @@ typedef ConnectionStateEmitter = StateEmitter; /// /// Extends [ConnectionStateEmitter] with the ability to update the current state. /// Used internally by WebSocket client implementations to manage state transitions. -typedef MutableConnectionStateEmitter - = MutableStateEmitter; +typedef MutableConnectionStateEmitter = MutableStateEmitter; /// Represents the current state of a WebSocket connection. /// @@ -107,16 +106,16 @@ sealed class WebSocketConnectionState extends Equatable { bool get isAutomaticReconnectionEnabled { return switch (this) { Disconnected(:final source) => switch (source) { - ServerInitiated() => switch (source.error?.apiError) { - final error? when error.code == 1000 => false, - final error? when error.isTokenExpiredError => false, - final error? when error.isClientError => false, - _ => true, // Reconnect on other server initiated disconnections - }, - UnHealthyConnection() => true, - SystemInitiated() => true, - UserInitiated() => false, + ServerInitiated() => switch (source.error?.apiError) { + final error? when error.code == 1000 => false, + final error? when error.isTokenExpiredError => false, + final error? when error.isClientError => false, + _ => true, // Reconnect on other server initiated disconnections }, + UnHealthyConnection() => true, + SystemInitiated() => true, + UserInitiated() => false, + }, _ => false, // No automatic reconnection for other states }; } diff --git a/packages/stream_core/lib/src/ws/events/ws_request.dart b/packages/stream_core/lib/src/ws/events/ws_request.dart index 2feb688..3fdc65e 100644 --- a/packages/stream_core/lib/src/ws/events/ws_request.dart +++ b/packages/stream_core/lib/src/ws/events/ws_request.dart @@ -18,7 +18,7 @@ final class HealthCheckPingEvent extends WsRequest { Map toJson() { return { 'type': 'health.check', - if (connectionId case final id?) 'client_id': id, + 'client_id': ?connectionId, }; } } diff --git a/packages/stream_core/pubspec.yaml b/packages/stream_core/pubspec.yaml index f9d556f..e7a38a0 100644 --- a/packages/stream_core/pubspec.yaml +++ b/packages/stream_core/pubspec.yaml @@ -16,7 +16,7 @@ repository: https://github.com/GetStream/stream-core-flutter # 2. Add it to the melos.yaml file for future updates. environment: - sdk: ^3.6.2 + sdk: ^3.10.0 dependencies: collection: ^1.19.0 diff --git a/packages/stream_core/test/query/filter_test.dart b/packages/stream_core/test/query/filter_test.dart index 86c3f3e..a949ca3 100644 --- a/packages/stream_core/test/query/filter_test.dart +++ b/packages/stream_core/test/query/filter_test.dart @@ -743,8 +743,7 @@ void main() { final model = TestModel(metadata: {'a': 1, 'b': 2}); expect( - Filter.equal(TestFilterField.metadata, {'b': 2, 'a': 1}) - .matches(model), + Filter.equal(TestFilterField.metadata, {'b': 2, 'a': 1}).matches(model), isTrue, ); }); @@ -796,23 +795,19 @@ void main() { final modelWithoutDiacritic = TestModel(name: 'Jose'); expect( - Filter.equal(TestFilterField.name, 'José') - .matches(modelWithDiacritic), + Filter.equal(TestFilterField.name, 'José').matches(modelWithDiacritic), isTrue, ); expect( - Filter.equal(TestFilterField.name, 'José') - .matches(modelWithoutDiacritic), + Filter.equal(TestFilterField.name, 'José').matches(modelWithoutDiacritic), isFalse, ); expect( - Filter.equal(TestFilterField.name, 'Jose') - .matches(modelWithDiacritic), + Filter.equal(TestFilterField.name, 'Jose').matches(modelWithDiacritic), isFalse, ); expect( - Filter.equal(TestFilterField.name, 'jose') - .matches(modelWithDiacritic), + Filter.equal(TestFilterField.name, 'jose').matches(modelWithDiacritic), isFalse, ); }); @@ -873,18 +868,15 @@ void main() { final model = TestModel(name: 'John'); expect( - Filter.in_(TestFilterField.name, ['John', 'Jane', 'Bob']) - .matches(model), + Filter.in_(TestFilterField.name, ['John', 'Jane', 'Bob']).matches(model), isTrue, ); expect( - Filter.in_(TestFilterField.name, ['john', 'Jane', 'Bob']) - .matches(model), + Filter.in_(TestFilterField.name, ['john', 'Jane', 'Bob']).matches(model), isFalse, ); expect( - Filter.in_(TestFilterField.name, ['JOHN', 'Jane', 'Bob']) - .matches(model), + Filter.in_(TestFilterField.name, ['JOHN', 'Jane', 'Bob']).matches(model), isFalse, ); }); @@ -894,23 +886,27 @@ void main() { final modelWithoutDiacritic = TestModel(name: 'Jose'); expect( - Filter.in_(TestFilterField.name, ['José', 'François', 'Müller']) - .matches(modelWithDiacritic), + Filter.in_(TestFilterField.name, [ + 'José', + 'François', + 'Müller', + ]).matches(modelWithDiacritic), isTrue, ); expect( - Filter.in_(TestFilterField.name, ['José', 'François', 'Müller']) - .matches(modelWithoutDiacritic), + Filter.in_(TestFilterField.name, [ + 'José', + 'François', + 'Müller', + ]).matches(modelWithoutDiacritic), isFalse, ); expect( - Filter.in_(TestFilterField.name, ['Jose', 'Francois']) - .matches(modelWithDiacritic), + Filter.in_(TestFilterField.name, ['Jose', 'Francois']).matches(modelWithDiacritic), isFalse, ); expect( - Filter.in_(TestFilterField.name, ['jose', 'françois']) - .matches(modelWithDiacritic), + Filter.in_(TestFilterField.name, ['jose', 'françois']).matches(modelWithDiacritic), isFalse, ); }); @@ -921,8 +917,7 @@ void main() { final model = TestModel(metadata: {'a': 1, 'b': 2, 'c': 3}); expect( - Filter.contains(TestFilterField.metadata, {'a': 1, 'b': 2}) - .matches(model), + Filter.contains(TestFilterField.metadata, {'a': 1, 'b': 2}).matches(model), isTrue, ); expect( @@ -935,8 +930,7 @@ void main() { final modelWithNull = TestModel(metadata: {'status': null}); final modelWithoutKey = TestModel(metadata: {'name': 'John'}); - final filter = - Filter.contains(TestFilterField.metadata, {'status': null}); + final filter = Filter.contains(TestFilterField.metadata, {'status': null}); expect(filter.matches(modelWithNull), isTrue); expect(filter.matches(modelWithoutKey), isFalse); @@ -1008,14 +1002,12 @@ void main() { // Filter with duplicates should match (duplicates ignored) expect( - Filter.contains(TestFilterField.tags, ['a', 'a', 'a']) - .matches(model), + Filter.contains(TestFilterField.tags, ['a', 'a', 'a']).matches(model), isTrue, // Should be TRUE, not FALSE ); expect( - Filter.contains(TestFilterField.tags, ['a', 'b', 'a']) - .matches(model), + Filter.contains(TestFilterField.tags, ['a', 'b', 'a']).matches(model), isTrue, ); }, @@ -1067,18 +1059,15 @@ void main() { final model = TestModel(createdAt: DateTime(2023, 6, 15)); expect( - Filter.greater(TestFilterField.createdAt, DateTime(2023, 1, 1)) - .matches(model), + Filter.greater(TestFilterField.createdAt, DateTime(2023, 1, 1)).matches(model), isTrue, ); expect( - Filter.greater(TestFilterField.createdAt, DateTime(2023, 6, 15)) - .matches(model), + Filter.greater(TestFilterField.createdAt, DateTime(2023, 6, 15)).matches(model), isFalse, ); expect( - Filter.greater(TestFilterField.createdAt, DateTime(2024, 1, 1)) - .matches(model), + Filter.greater(TestFilterField.createdAt, DateTime(2024, 1, 1)).matches(model), isFalse, ); }); @@ -1086,67 +1075,55 @@ void main() { test('Greater should use lexicographic comparison for strings', () { // Lexicographic: uppercase < lowercase expect( - Filter.greater(TestFilterField.name, 'John') - .matches(TestModel(name: 'Johnny')), + Filter.greater(TestFilterField.name, 'John').matches(TestModel(name: 'Johnny')), isTrue, ); expect( - Filter.greater(TestFilterField.name, 'John') - .matches(TestModel(name: 'Mike')), + Filter.greater(TestFilterField.name, 'John').matches(TestModel(name: 'Mike')), isTrue, ); expect( - Filter.greater(TestFilterField.name, 'John') - .matches(TestModel(name: 'john')), + Filter.greater(TestFilterField.name, 'John').matches(TestModel(name: 'john')), isTrue, ); expect( - Filter.greater(TestFilterField.name, 'John') - .matches(TestModel(name: 'John')), + Filter.greater(TestFilterField.name, 'John').matches(TestModel(name: 'John')), isFalse, ); expect( - Filter.greater(TestFilterField.name, 'John') - .matches(TestModel(name: 'JOHN')), + Filter.greater(TestFilterField.name, 'John').matches(TestModel(name: 'JOHN')), isFalse, ); expect( - Filter.greater(TestFilterField.name, 'John') - .matches(TestModel(name: 'Alice')), + Filter.greater(TestFilterField.name, 'John').matches(TestModel(name: 'Alice')), isFalse, ); }); test('Greater should handle diacritics lexicographically', () { expect( - Filter.greater(TestFilterField.name, 'José') - .matches(TestModel(name: 'Joséa')), + Filter.greater(TestFilterField.name, 'José').matches(TestModel(name: 'Joséa')), isTrue, ); expect( - Filter.greater(TestFilterField.name, 'José') - .matches(TestModel(name: 'joséa')), + Filter.greater(TestFilterField.name, 'José').matches(TestModel(name: 'joséa')), isTrue, ); expect( - Filter.greater(TestFilterField.name, 'José') - .matches(TestModel(name: 'José')), + Filter.greater(TestFilterField.name, 'José').matches(TestModel(name: 'José')), isFalse, ); expect( - Filter.greater(TestFilterField.name, 'José') - .matches(TestModel(name: 'Jose')), + Filter.greater(TestFilterField.name, 'José').matches(TestModel(name: 'Jose')), isFalse, ); expect( - Filter.greater(TestFilterField.name, 'José') - .matches(TestModel(name: 'jose')), + Filter.greater(TestFilterField.name, 'José').matches(TestModel(name: 'jose')), isTrue, ); }); - test('GreaterOrEqual should match when field value is greater or equal', - () { + test('GreaterOrEqual should match when field value is greater or equal', () { final model = TestModel(id: '50'); expect( @@ -1163,36 +1140,29 @@ void main() { ); }); - test('GreaterOrEqual should use lexicographic comparison for strings', - () { + test('GreaterOrEqual should use lexicographic comparison for strings', () { expect( - Filter.greaterOrEqual(TestFilterField.name, 'John') - .matches(TestModel(name: 'Johnny')), + Filter.greaterOrEqual(TestFilterField.name, 'John').matches(TestModel(name: 'Johnny')), isTrue, ); expect( - Filter.greaterOrEqual(TestFilterField.name, 'John') - .matches(TestModel(name: 'Mike')), + Filter.greaterOrEqual(TestFilterField.name, 'John').matches(TestModel(name: 'Mike')), isTrue, ); expect( - Filter.greaterOrEqual(TestFilterField.name, 'John') - .matches(TestModel(name: 'john')), + Filter.greaterOrEqual(TestFilterField.name, 'John').matches(TestModel(name: 'john')), isTrue, ); expect( - Filter.greaterOrEqual(TestFilterField.name, 'John') - .matches(TestModel(name: 'John')), + Filter.greaterOrEqual(TestFilterField.name, 'John').matches(TestModel(name: 'John')), isTrue, ); expect( - Filter.greaterOrEqual(TestFilterField.name, 'John') - .matches(TestModel(name: 'JOHN')), + Filter.greaterOrEqual(TestFilterField.name, 'John').matches(TestModel(name: 'JOHN')), isFalse, ); expect( - Filter.greaterOrEqual(TestFilterField.name, 'John') - .matches(TestModel(name: 'Alice')), + Filter.greaterOrEqual(TestFilterField.name, 'John').matches(TestModel(name: 'Alice')), isFalse, ); }); @@ -1201,51 +1171,42 @@ void main() { final model = TestModel(createdAt: DateTime(2023, 6, 15)); expect( - Filter.less(TestFilterField.createdAt, DateTime(2024, 1, 1)) - .matches(model), + Filter.less(TestFilterField.createdAt, DateTime(2024, 1, 1)).matches(model), isTrue, ); expect( - Filter.less(TestFilterField.createdAt, DateTime(2023, 6, 15)) - .matches(model), + Filter.less(TestFilterField.createdAt, DateTime(2023, 6, 15)).matches(model), isFalse, ); expect( - Filter.less(TestFilterField.createdAt, DateTime(2023, 1, 1)) - .matches(model), + Filter.less(TestFilterField.createdAt, DateTime(2023, 1, 1)).matches(model), isFalse, ); }); test('Less should use lexicographic comparison for strings', () { expect( - Filter.less(TestFilterField.name, 'John') - .matches(TestModel(name: 'Johnny')), + Filter.less(TestFilterField.name, 'John').matches(TestModel(name: 'Johnny')), isFalse, ); expect( - Filter.less(TestFilterField.name, 'John') - .matches(TestModel(name: 'Mike')), + Filter.less(TestFilterField.name, 'John').matches(TestModel(name: 'Mike')), isFalse, ); expect( - Filter.less(TestFilterField.name, 'John') - .matches(TestModel(name: 'john')), + Filter.less(TestFilterField.name, 'John').matches(TestModel(name: 'john')), isFalse, ); expect( - Filter.less(TestFilterField.name, 'John') - .matches(TestModel(name: 'John')), + Filter.less(TestFilterField.name, 'John').matches(TestModel(name: 'John')), isFalse, ); expect( - Filter.less(TestFilterField.name, 'John') - .matches(TestModel(name: 'JOHN')), + Filter.less(TestFilterField.name, 'John').matches(TestModel(name: 'JOHN')), isTrue, ); expect( - Filter.less(TestFilterField.name, 'John') - .matches(TestModel(name: 'Alice')), + Filter.less(TestFilterField.name, 'John').matches(TestModel(name: 'Alice')), isTrue, ); }); @@ -1269,33 +1230,27 @@ void main() { test('LessOrEqual should use lexicographic comparison for strings', () { expect( - Filter.lessOrEqual(TestFilterField.name, 'John') - .matches(TestModel(name: 'Johnny')), + Filter.lessOrEqual(TestFilterField.name, 'John').matches(TestModel(name: 'Johnny')), isFalse, ); expect( - Filter.lessOrEqual(TestFilterField.name, 'John') - .matches(TestModel(name: 'Mike')), + Filter.lessOrEqual(TestFilterField.name, 'John').matches(TestModel(name: 'Mike')), isFalse, ); expect( - Filter.lessOrEqual(TestFilterField.name, 'John') - .matches(TestModel(name: 'john')), + Filter.lessOrEqual(TestFilterField.name, 'John').matches(TestModel(name: 'john')), isFalse, ); expect( - Filter.lessOrEqual(TestFilterField.name, 'John') - .matches(TestModel(name: 'John')), + Filter.lessOrEqual(TestFilterField.name, 'John').matches(TestModel(name: 'John')), isTrue, ); expect( - Filter.lessOrEqual(TestFilterField.name, 'John') - .matches(TestModel(name: 'JOHN')), + Filter.lessOrEqual(TestFilterField.name, 'John').matches(TestModel(name: 'JOHN')), isTrue, ); expect( - Filter.lessOrEqual(TestFilterField.name, 'John') - .matches(TestModel(name: 'Alice')), + Filter.lessOrEqual(TestFilterField.name, 'John').matches(TestModel(name: 'Alice')), isTrue, ); }); @@ -1321,8 +1276,7 @@ void main() { ); }); - test('should return false for NULL comparisons (PostgreSQL semantics)', - () { + test('should return false for NULL comparisons (PostgreSQL semantics)', () { final modelWithNull = TestModel(id: null); final modelWithValue = TestModel(id: '50'); @@ -1344,20 +1298,17 @@ void main() { // GreaterOrEqual: NULL >= value → false expect( - Filter.greaterOrEqual(TestFilterField.id, '30') - .matches(modelWithNull), + Filter.greaterOrEqual(TestFilterField.id, '30').matches(modelWithNull), isFalse, ); // GreaterOrEqual: value >= NULL → false expect( - Filter.greaterOrEqual(TestFilterField.id, null) - .matches(modelWithValue), + Filter.greaterOrEqual(TestFilterField.id, null).matches(modelWithValue), isFalse, ); // GreaterOrEqual: NULL >= NULL → false expect( - Filter.greaterOrEqual(TestFilterField.id, null) - .matches(modelWithNull), + Filter.greaterOrEqual(TestFilterField.id, null).matches(modelWithNull), isFalse, ); @@ -1473,8 +1424,7 @@ void main() { final filter = Filter.query(TestFilterField.name, 'PROD'); final itemWithLowercase = TestModel(name: 'production server'); - final itemWithMixedCase = - TestModel(name: 'Development Production Environment'); + final itemWithMixedCase = TestModel(name: 'Development Production Environment'); final itemWithPartialMatch = TestModel(name: 'reproduced issue'); final itemWithoutMatch = TestModel(name: 'staging server'); @@ -1495,46 +1445,38 @@ void main() { test('should handle diacritics case-insensitively', () { expect( - Filter.query(TestFilterField.name, 'josé') - .matches(TestModel(name: 'José')), + Filter.query(TestFilterField.name, 'josé').matches(TestModel(name: 'José')), isTrue, ); expect( - Filter.query(TestFilterField.name, 'josé') - .matches(TestModel(name: 'JOSÉ')), + Filter.query(TestFilterField.name, 'josé').matches(TestModel(name: 'JOSÉ')), isTrue, ); expect( - Filter.query(TestFilterField.name, 'josé') - .matches(TestModel(name: 'josé')), + Filter.query(TestFilterField.name, 'josé').matches(TestModel(name: 'josé')), isTrue, ); expect( - Filter.query(TestFilterField.name, 'josé') - .matches(TestModel(name: 'Jose')), + Filter.query(TestFilterField.name, 'josé').matches(TestModel(name: 'Jose')), isFalse, ); expect( - Filter.query(TestFilterField.name, 'josé') - .matches(TestModel(name: 'jose')), + Filter.query(TestFilterField.name, 'josé').matches(TestModel(name: 'jose')), isFalse, ); }); test('should match middle and end substrings', () { expect( - Filter.query(TestFilterField.name, 'hn') - .matches(TestModel(name: 'John')), + Filter.query(TestFilterField.name, 'hn').matches(TestModel(name: 'John')), isTrue, ); expect( - Filter.query(TestFilterField.name, 'hn') - .matches(TestModel(name: 'JOHN')), + Filter.query(TestFilterField.name, 'hn').matches(TestModel(name: 'JOHN')), isTrue, ); expect( - Filter.query(TestFilterField.name, 'hn') - .matches(TestModel(name: 'Jane')), + Filter.query(TestFilterField.name, 'hn').matches(TestModel(name: 'Jane')), isFalse, ); }); @@ -1563,13 +1505,11 @@ void main() { final modelWithEmptyName = TestModel(name: ''); expect( - Filter.autoComplete(TestFilterField.name, '') - .matches(modelWithContent), + Filter.autoComplete(TestFilterField.name, '').matches(modelWithContent), isFalse, ); expect( - Filter.autoComplete(TestFilterField.name, '') - .matches(modelWithEmptyName), + Filter.autoComplete(TestFilterField.name, '').matches(modelWithEmptyName), isFalse, ); }); @@ -1578,10 +1518,8 @@ void main() { final filter = Filter.autoComplete(TestFilterField.name, 'con'); final itemWithDotSeparation = TestModel(name: 'app.config.json'); - final itemWithDashSeparation = - TestModel(name: 'user-configuration-file'); - final itemWithMixedPunctuation = - TestModel(name: 'system/container,settings.xml'); + final itemWithDashSeparation = TestModel(name: 'user-configuration-file'); + final itemWithMixedPunctuation = TestModel(name: 'system/container,settings.xml'); final itemWithoutWordPrefix = TestModel(name: 'application'); final itemWithInWordMatch = TestModel(name: 'reconstruction'); @@ -1603,88 +1541,77 @@ void main() { test('should handle diacritics case-insensitively', () { expect( - Filter.autoComplete(TestFilterField.name, 'jos') - .matches(TestModel(name: 'José')), + Filter.autoComplete(TestFilterField.name, 'jos').matches(TestModel(name: 'José')), isTrue, ); expect( - Filter.autoComplete(TestFilterField.name, 'jos') - .matches(TestModel(name: 'JOSÉ')), + Filter.autoComplete(TestFilterField.name, 'jos').matches(TestModel(name: 'JOSÉ')), isTrue, ); expect( - Filter.autoComplete(TestFilterField.name, 'jos') - .matches(TestModel(name: 'josé')), + Filter.autoComplete(TestFilterField.name, 'jos').matches(TestModel(name: 'josé')), isTrue, ); }); test('should match word boundaries in multi-word text', () { expect( - Filter.autoComplete(TestFilterField.name, 'john') - .matches(TestModel(name: 'John Smith')), + Filter.autoComplete(TestFilterField.name, 'john').matches(TestModel(name: 'John Smith')), isTrue, ); expect( - Filter.autoComplete(TestFilterField.name, 'john') - .matches(TestModel(name: 'JOHN DOE')), + Filter.autoComplete(TestFilterField.name, 'john').matches(TestModel(name: 'JOHN DOE')), isTrue, ); expect( - Filter.autoComplete(TestFilterField.name, 'john') - .matches(TestModel(name: 'Smith John')), + Filter.autoComplete(TestFilterField.name, 'john').matches(TestModel(name: 'Smith John')), isTrue, ); expect( - Filter.autoComplete(TestFilterField.name, 'smi') - .matches(TestModel(name: 'John Smith')), + Filter.autoComplete(TestFilterField.name, 'smi').matches(TestModel(name: 'John Smith')), isTrue, ); expect( - Filter.autoComplete(TestFilterField.name, 'smi') - .matches(TestModel(name: 'Johnson')), + Filter.autoComplete(TestFilterField.name, 'smi').matches(TestModel(name: 'Johnson')), isFalse, ); }); test('should handle punctuation as word boundaries', () { expect( - Filter.autoComplete(TestFilterField.name, 'john') - .matches(TestModel(name: 'john-doe')), + Filter.autoComplete(TestFilterField.name, 'john').matches(TestModel(name: 'john-doe')), isTrue, ); expect( - Filter.autoComplete(TestFilterField.name, 'john') - .matches(TestModel(name: 'john.doe')), + Filter.autoComplete(TestFilterField.name, 'john').matches(TestModel(name: 'john.doe')), isTrue, ); expect( - Filter.autoComplete(TestFilterField.name, 'john') - .matches(TestModel(name: 'Johnson')), + Filter.autoComplete(TestFilterField.name, 'john').matches(TestModel(name: 'Johnson')), isTrue, ); }); test('should not match when query is longer than word', () { expect( - Filter.autoComplete(TestFilterField.name, 'johnathan') - .matches(TestModel(name: 'John')), + Filter.autoComplete(TestFilterField.name, 'johnathan').matches(TestModel(name: 'John')), isFalse, ); }); test('should return false for non-string fields', () { expect( - Filter.autoComplete(TestFilterField.metadata, 'test') - .matches(TestModel(metadata: {'key': 'value'})), + Filter.autoComplete( + TestFilterField.metadata, + 'test', + ).matches(TestModel(metadata: {'key': 'value'})), isFalse, ); }); test('should return false for fields with only punctuation', () { expect( - Filter.autoComplete(TestFilterField.name, 'test') - .matches(TestModel(name: '...')), + Filter.autoComplete(TestFilterField.name, 'test').matches(TestModel(name: '...')), isFalse, ); }); @@ -1701,13 +1628,11 @@ void main() { ); expect( - Filter.pathExists(TestFilterField.metadata, 'user.profile.name') - .matches(model), + Filter.pathExists(TestFilterField.metadata, 'user.profile.name').matches(model), isTrue, ); expect( - Filter.pathExists(TestFilterField.metadata, 'user.profile.age') - .matches(model), + Filter.pathExists(TestFilterField.metadata, 'user.profile.age').matches(model), isFalse, ); }); @@ -1738,8 +1663,7 @@ void main() { final model = TestModel(metadata: null); expect( - Filter.pathExists(TestFilterField.metadata, 'user.name') - .matches(model), + Filter.pathExists(TestFilterField.metadata, 'user.name').matches(model), isFalse, ); }); @@ -1761,8 +1685,7 @@ void main() { ); expect( - Filter.pathExists(TestFilterField.metadata, 'user.name') - .matches(model), + Filter.pathExists(TestFilterField.metadata, 'user.name').matches(model), isFalse, ); }); @@ -1773,15 +1696,13 @@ void main() { // Path exists but value is null - should match (key exists) expect( - Filter.pathExists(TestFilterField.metadata, 'user') - .matches(modelWithNull), + Filter.pathExists(TestFilterField.metadata, 'user').matches(modelWithNull), isTrue, ); // Path doesn't exist - should not match expect( - Filter.pathExists(TestFilterField.metadata, 'user') - .matches(modelWithoutKey), + Filter.pathExists(TestFilterField.metadata, 'user').matches(modelWithoutKey), isFalse, ); }); @@ -1876,9 +1797,7 @@ void main() { ); }); - test( - 'should handle null values in optional fields (PostgreSQL semantics)', - () { + test('should handle null values in optional fields (PostgreSQL semantics)', () { final modelWithNull = TestModel(name: null); final modelWithValue = TestModel(name: 'John'); @@ -1935,8 +1854,7 @@ void main() { isTrue, ); expect( - Filter.contains(TestFilterField.metadata, {}) - .matches(modelWithValues), + Filter.contains(TestFilterField.metadata, {}).matches(modelWithValues), isTrue, ); }); diff --git a/packages/stream_core/test/query/list_extensions_test.dart b/packages/stream_core/test/query/list_extensions_test.dart index 4bd5da4..0e261a5 100644 --- a/packages/stream_core/test/query/list_extensions_test.dart +++ b/packages/stream_core/test/query/list_extensions_test.dart @@ -265,8 +265,7 @@ void main() { final result = users.updateWhere( (user) => user.id == '2', - update: (user) => - _TestUser(id: user.id, name: '${user.name} Updated'), + update: (user) => _TestUser(id: user.id, name: '${user.name} Updated'), ); expect(result.length, 3); @@ -287,8 +286,7 @@ void main() { final result = scores.updateWhere( (score) => score.points < 100, - update: (score) => - _TestScore(userId: score.userId, points: score.points * 2), + update: (score) => _TestScore(userId: score.userId, points: score.points * 2), ); expect(result.length, 4); @@ -322,8 +320,7 @@ void main() { final result = users.updateWhere( (user) => true, - update: (user) => - _TestUser(id: user.id, name: '${user.name} Updated'), + update: (user) => _TestUser(id: user.id, name: '${user.name} Updated'), ); expect(result.length, 2); @@ -374,8 +371,7 @@ void main() { final result = scores.updateWhere( (score) => score.points >= 150 && score.points <= 200, - update: (score) => - _TestScore(userId: score.userId, points: score.points + 50), + update: (score) => _TestScore(userId: score.userId, points: score.points + 50), ); expect(result[0].points, 100); // Unchanged @@ -403,8 +399,7 @@ void main() { expect(result[2].points, 150); }); - test('should sort multiple updated elements when compare is provided', - () { + test('should sort multiple updated elements when compare is provided', () { final users = [ const _TestUser(id: '1', name: 'Alice'), const _TestUser(id: '2', name: 'Bob'), @@ -414,8 +409,7 @@ void main() { final result = users.updateWhere( (user) => user.id == '2' || user.id == '4', - update: (user) => - _TestUser(id: user.id, name: 'Z${user.name}'), // Prefix with Z + update: (user) => _TestUser(id: user.id, name: 'Z${user.name}'), // Prefix with Z compare: (a, b) => a.name.compareTo(b.name), // Ascending by name ); @@ -701,8 +695,7 @@ void main() { test('should insert element at correct position in sorted list', () { final numbers = [1, 3, 5, 7]; - final result = - numbers.sortedInsert(4, compare: (a, b) => a.compareTo(b)); + final result = numbers.sortedInsert(4, compare: (a, b) => a.compareTo(b)); expect(result, [1, 3, 4, 5, 7]); // Original list should be unchanged @@ -712,8 +705,7 @@ void main() { test('should insert at beginning when element is smallest', () { final numbers = [3, 5, 7]; - final result = - numbers.sortedInsert(1, compare: (a, b) => a.compareTo(b)); + final result = numbers.sortedInsert(1, compare: (a, b) => a.compareTo(b)); expect(result, [1, 3, 5, 7]); }); @@ -721,8 +713,7 @@ void main() { test('should insert at end when element is largest', () { final numbers = [1, 3, 5]; - final result = - numbers.sortedInsert(7, compare: (a, b) => a.compareTo(b)); + final result = numbers.sortedInsert(7, compare: (a, b) => a.compareTo(b)); expect(result, [1, 3, 5, 7]); }); @@ -730,10 +721,8 @@ void main() { test('should work with single element list', () { final numbers = [5]; - final smaller = - numbers.sortedInsert(3, compare: (a, b) => a.compareTo(b)); - final larger = - numbers.sortedInsert(7, compare: (a, b) => a.compareTo(b)); + final smaller = numbers.sortedInsert(3, compare: (a, b) => a.compareTo(b)); + final larger = numbers.sortedInsert(7, compare: (a, b) => a.compareTo(b)); expect(smaller, [3, 5]); expect(larger, [5, 7]); @@ -742,8 +731,7 @@ void main() { test('should work with empty list', () { final numbers = []; - final result = - numbers.sortedInsert(5, compare: (a, b) => a.compareTo(b)); + final result = numbers.sortedInsert(5, compare: (a, b) => a.compareTo(b)); expect(result, [5]); }); @@ -751,8 +739,7 @@ void main() { test('should work with reverse order comparator', () { final numbers = [7, 5, 3, 1]; // Descending order - final result = - numbers.sortedInsert(4, compare: (a, b) => b.compareTo(a)); + final result = numbers.sortedInsert(4, compare: (a, b) => b.compareTo(a)); expect(result, [7, 5, 4, 3, 1]); }); @@ -760,8 +747,7 @@ void main() { test('should work with string sorting', () { final names = ['Alice', 'Charlie', 'David']; - final result = - names.sortedInsert('Bob', compare: (a, b) => a.compareTo(b)); + final result = names.sortedInsert('Bob', compare: (a, b) => a.compareTo(b)); expect(result, ['Alice', 'Bob', 'Charlie', 'David']); }); @@ -785,8 +771,7 @@ void main() { test('should handle duplicate values', () { final numbers = [1, 3, 5, 7]; - final result = - numbers.sortedInsert(3, compare: (a, b) => a.compareTo(b)); + final result = numbers.sortedInsert(3, compare: (a, b) => a.compareTo(b)); expect(result, [1, 3, 3, 5, 7]); }); @@ -838,8 +823,7 @@ void main() { final result = scores.insertUnique( const _TestScore(userId: 4, points: 175), key: (score) => score.userId, - compare: (a, b) => - b.points.compareTo(a.points), // Descending by points + compare: (a, b) => b.points.compareTo(a.points), // Descending by points ); expect(result.length, 4); @@ -847,8 +831,7 @@ void main() { expect(result.map((s) => s.userId), [2, 4, 3, 1]); }); - test('should replace and sort when key exists and compare is provided', - () { + test('should replace and sort when key exists and compare is provided', () { final scores = [ const _TestScore(userId: 1, points: 100), const _TestScore(userId: 2, points: 200), @@ -858,8 +841,7 @@ void main() { final result = scores.insertUnique( const _TestScore(userId: 2, points: 250), // Update existing key: (score) => score.userId, - compare: (a, b) => - b.points.compareTo(a.points), // Descending by points + compare: (a, b) => b.points.compareTo(a.points), // Descending by points ); expect(result.length, 3); @@ -967,8 +949,7 @@ void main() { final result = users.sortedUpsert( const _TestScore(userId: 1, points: 150), key: (score) => score.userId, - compare: (a, b) => - b.points.compareTo(a.points), // Descending by points + compare: (a, b) => b.points.compareTo(a.points), // Descending by points ); expect(result.length, 3); @@ -985,8 +966,7 @@ void main() { final result = users.sortedUpsert( const _TestScore(userId: 2, points: 80), key: (score) => score.userId, - compare: (a, b) => - b.points.compareTo(a.points), // Descending by points + compare: (a, b) => b.points.compareTo(a.points), // Descending by points ); expect(result.length, 3); @@ -1063,8 +1043,7 @@ void main() { final result = scores.sortedUpsert( const _TestScore(userId: 2, points: 50), key: (score) => score.userId, - compare: (a, b) => - b.points.compareTo(a.points), // Descending by points + compare: (a, b) => b.points.compareTo(a.points), // Descending by points update: (original, updated) => _TestScore( userId: original.userId, points: original.points + updated.points, // Add points together @@ -1077,9 +1056,7 @@ void main() { expect(result.map((s) => s.userId), [2, 3, 1]); }); - test( - 'should use default update behavior when update function is not provided', - () { + test('should use default update behavior when update function is not provided', () { final scores = [ const _TestScore(userId: 1, points: 100), const _TestScore(userId: 2, points: 200), @@ -1413,8 +1390,7 @@ void main() { ); // Should return same instance }); - test('should handle multiple matching elements (removes first found)', - () { + test('should handle multiple matching elements (removes first found)', () { final comments = [ const _TestComment(id: '1', text: 'duplicate', replies: []), const _TestComment(id: '2', text: 'duplicate', replies: []), @@ -1471,8 +1447,9 @@ void main() { final mainComment = result.first; expect(mainComment.replies.length, 2); - final controversialComment = mainComment.replies - .firstWhere((c) => c.text == 'Controversial opinion'); + final controversialComment = mainComment.replies.firstWhere( + (c) => c.text == 'Controversial opinion', + ); expect(controversialComment.replies.length, 1); expect(controversialComment.replies.first.text, 'Valid response'); expect(mainComment.modifiedAt, isNotNull); // Root was updated @@ -1506,10 +1483,8 @@ void main() { final result = comments.updateNested( (comment) => comment.id == updatedComment.id, children: (comment) => comment.replies, - update: (comment) => - updatedComment.copyWith(modifiedAt: DateTime.now()), - updateChildren: (parent, newReplies) => - parent.copyWith(replies: newReplies), + update: (comment) => updatedComment.copyWith(modifiedAt: DateTime.now()), + updateChildren: (parent, newReplies) => parent.copyWith(replies: newReplies), ); expect(result.length, 2); @@ -1552,10 +1527,8 @@ void main() { final result = comments.updateNested( (comment) => comment.id == updatedComment.id, children: (comment) => comment.replies, - update: (comment) => - updatedComment.copyWith(modifiedAt: DateTime.now()), - updateChildren: (parent, newReplies) => - parent.copyWith(replies: newReplies), + update: (comment) => updatedComment.copyWith(modifiedAt: DateTime.now()), + updateChildren: (parent, newReplies) => parent.copyWith(replies: newReplies), ); expect(result.length, 1); @@ -1593,12 +1566,9 @@ void main() { final result = comments.updateNested( (comment) => comment.id == updatedComment.id, children: (comment) => comment.replies, - update: (comment) => - updatedComment.copyWith(modifiedAt: DateTime.now()), - updateChildren: (parent, newReplies) => - parent.copyWith(replies: newReplies), - compare: (a, b) => - b.upvotes.compareTo(a.upvotes), // Sort by upvotes desc + update: (comment) => updatedComment.copyWith(modifiedAt: DateTime.now()), + updateChildren: (parent, newReplies) => parent.copyWith(replies: newReplies), + compare: (a, b) => b.upvotes.compareTo(a.upvotes), // Sort by upvotes desc ); expect(result.length, 1); @@ -1649,15 +1619,12 @@ void main() { final result = comments.updateNested( (comment) => comment.id == updatedComment.id, children: (comment) => comment.replies, - update: (comment) => - updatedComment.copyWith(modifiedAt: DateTime.now()), - updateChildren: (parent, newReplies) => - parent.copyWith(replies: newReplies), + update: (comment) => updatedComment.copyWith(modifiedAt: DateTime.now()), + updateChildren: (parent, newReplies) => parent.copyWith(replies: newReplies), ); expect(result.length, 1); - final deepComment = - result.first.replies.first.replies.first.replies.first; + final deepComment = result.first.replies.first.replies.first.replies.first; expect(deepComment.text, 'Updated Level 3'); expect(deepComment.upvotes, 10); expect(deepComment.modifiedAt, isNotNull); @@ -1670,8 +1637,7 @@ void main() { (comment) => comment.id == '1', children: (comment) => comment.replies, update: (comment) => comment.copyWith(modifiedAt: DateTime.now()), - updateChildren: (parent, newReplies) => - parent.copyWith(replies: newReplies), + updateChildren: (parent, newReplies) => parent.copyWith(replies: newReplies), ); expect(result, isEmpty); @@ -1686,8 +1652,7 @@ void main() { (comment) => comment.id == 'nonexistent', children: (comment) => comment.replies, update: (comment) => comment.copyWith(modifiedAt: DateTime.now()), - updateChildren: (parent, newReplies) => - parent.copyWith(replies: newReplies), + updateChildren: (parent, newReplies) => parent.copyWith(replies: newReplies), ); expect( @@ -1737,10 +1702,8 @@ void main() { final result = forumThread.updateNested( (comment) => comment.id == upvotedComment.id, children: (comment) => comment.replies, - update: (comment) => - upvotedComment.copyWith(modifiedAt: DateTime.now()), - updateChildren: (parent, newReplies) => - parent.copyWith(replies: newReplies), + update: (comment) => upvotedComment.copyWith(modifiedAt: DateTime.now()), + updateChildren: (parent, newReplies) => parent.copyWith(replies: newReplies), compare: (a, b) => b.upvotes.compareTo(a.upvotes), // Sort by upvotes ); @@ -1860,11 +1823,11 @@ void main() { final result = deepComments.updateNested( (comment) => comment.id == 'thread1_0', children: (comment) => comment.replies, - update: (comment) => - const _TestComment(id: 'thread1_0', text: 'Updated leaf') - .copyWith(modifiedAt: DateTime.now()), - updateChildren: (parent, newReplies) => - parent.copyWith(replies: newReplies), + update: (comment) => const _TestComment( + id: 'thread1_0', + text: 'Updated leaf', + ).copyWith(modifiedAt: DateTime.now()), + updateChildren: (parent, newReplies) => parent.copyWith(replies: newReplies), ); stopwatch.stop(); @@ -1945,8 +1908,7 @@ void main() { }); group('Concurrent Usage Simulation', () { - test('should maintain immutability under simulated concurrent access', - () { + test('should maintain immutability under simulated concurrent access', () { final baseList = [ const _TestUser(id: '1', name: 'Alice'), const _TestUser(id: '2', name: 'Bob'), @@ -1989,11 +1951,12 @@ void main() { currentState = currentState.updateNested( (comment) => comment.id == '2', children: (comment) => comment.replies, - update: (comment) => - _TestComment(id: '2', text: 'Reply 1', upvotes: 5 + i) - .copyWith(modifiedAt: DateTime.now()), - updateChildren: (parent, newReplies) => - parent.copyWith(replies: newReplies), + update: (comment) => _TestComment( + id: '2', + text: 'Reply 1', + upvotes: 5 + i, + ).copyWith(modifiedAt: DateTime.now()), + updateChildren: (parent, newReplies) => parent.copyWith(replies: newReplies), ); } @@ -2031,8 +1994,7 @@ void main() { authorId: 'user1', content: 'Hello Updated', ), - key: (activity) => - '${activity.authorId}_${activity.content.split(' ').first}', + key: (activity) => '${activity.authorId}_${activity.content.split(' ').first}', ); expect(result.length, 2); // Should replace 'Hello' activity diff --git a/packages/stream_core/test/query/sort_test.dart b/packages/stream_core/test/query/sort_test.dart index 2aeec57..2747b2d 100644 --- a/packages/stream_core/test/query/sort_test.dart +++ b/packages/stream_core/test/query/sort_test.dart @@ -120,10 +120,8 @@ void main() { final field = SortField('birthDate', (p) => p.birthDate); final sort = Sort.asc(field); - final person1990 = - Person(name: 'Person1990', age: 34, birthDate: DateTime(1990)); - final person2000 = - Person(name: 'Person2000', age: 24, birthDate: DateTime(2000)); + final person1990 = Person(name: 'Person1990', age: 34, birthDate: DateTime(1990)); + final person2000 = Person(name: 'Person2000', age: 24, birthDate: DateTime(2000)); expect(sort.compare(person1990, person2000), lessThan(0)); // 1990 < 2000 }); @@ -156,8 +154,7 @@ void main() { final field = SortField('birthDate', (p) => p.birthDate); final sort = Sort.asc(field); - final withDate = - Person(name: 'WithDate', age: 30, birthDate: DateTime(1990)); + final withDate = Person(name: 'WithDate', age: 30, birthDate: DateTime(1990)); const withoutDate = Person(name: 'WithoutDate', age: 25); expect( @@ -174,8 +171,7 @@ void main() { final field = SortField('birthDate', (p) => p.birthDate); final sort = Sort.asc(field, nullOrdering: NullOrdering.nullsFirst); - final withDate = - Person(name: 'WithDate', age: 30, birthDate: DateTime(1990)); + final withDate = Person(name: 'WithDate', age: 30, birthDate: DateTime(1990)); const withoutDate = Person(name: 'WithoutDate', age: 25); expect( @@ -443,9 +439,7 @@ void main() { people.sort(sorts.compare); - final result = people - .map((p) => '${p.name}-${p.score?.toString() ?? 'null'}') - .toList(); + final result = people.map((p) => '${p.name}-${p.score?.toString() ?? 'null'}').toList(); expect( result, equals([ diff --git a/packages/stream_core/test/utils/event_emitter_test.dart b/packages/stream_core/test/utils/event_emitter_test.dart index d304a0b..7947791 100644 --- a/packages/stream_core/test/utils/event_emitter_test.dart +++ b/packages/stream_core/test/utils/event_emitter_test.dart @@ -126,8 +126,7 @@ void main() { expect((values.first as AnotherEvent).value, 5); }); - test('resolver can conditionally transform based on event properties', - () async { + test('resolver can conditionally transform based on event properties', () async { final emitter = MutableEventEmitter( resolvers: [ (event) => event.data.startsWith('transform:') diff --git a/packages/stream_core/test/utils/shared_emitter_test.dart b/packages/stream_core/test/utils/shared_emitter_test.dart index c0013dc..aa97293 100644 --- a/packages/stream_core/test/utils/shared_emitter_test.dart +++ b/packages/stream_core/test/utils/shared_emitter_test.dart @@ -84,8 +84,7 @@ void main() { expect(() => emitter.emit(1), throwsStateError); }); - test('tryEmit catches errors and returns false instead of throwing', - () async { + test('tryEmit catches errors and returns false instead of throwing', () async { final emitter = MutableSharedEmitter(); addTearDown(emitter.close); @@ -409,8 +408,7 @@ void main() { }); group('SharedEmitter vs StateEmitter behavior', () { - test('SharedEmitter does not emit to late subscribers by default', - () async { + test('SharedEmitter does not emit to late subscribers by default', () async { final emitter = MutableSharedEmitter(); addTearDown(emitter.close); @@ -428,8 +426,7 @@ void main() { expect(values, [3]); }); - test('StateEmitter always emits current value to new subscribers', - () async { + test('StateEmitter always emits current value to new subscribers', () async { final emitter = MutableStateEmitter(0); addTearDown(emitter.close); diff --git a/packages/stream_core/test/utils/state_emitter_test.dart b/packages/stream_core/test/utils/state_emitter_test.dart index c5803f5..2805f19 100644 --- a/packages/stream_core/test/utils/state_emitter_test.dart +++ b/packages/stream_core/test/utils/state_emitter_test.dart @@ -25,7 +25,7 @@ void main() { expect(values, [42]); }); - test('updates value on emit', () async { + test('updates value on emit', () { final emitter = MutableStateEmitter(0); addTearDown(emitter.close); @@ -34,7 +34,7 @@ void main() { expect(emitter.value, 42); }); - test('value setter works like emit', () async { + test('value setter works like emit', () { final emitter = MutableStateEmitter(0); addTearDown(emitter.close); @@ -115,7 +115,7 @@ void main() { }); group('atomic update methods', () { - test('update applies function to current value', () async { + test('update applies function to current value', () { final emitter = MutableStateEmitter(10); addTearDown(emitter.close); @@ -124,7 +124,7 @@ void main() { expect(emitter.value, 20); }); - test('getAndUpdate returns previous value and updates', () async { + test('getAndUpdate returns previous value and updates', () { final emitter = MutableStateEmitter(10); addTearDown(emitter.close); @@ -134,7 +134,7 @@ void main() { expect(emitter.value, 15); }); - test('updateAndGet returns new value after update', () async { + test('updateAndGet returns new value after update', () { final emitter = MutableStateEmitter(10); addTearDown(emitter.close); diff --git a/packages/stream_core_flutter/.gitignore b/packages/stream_core_flutter/.gitignore deleted file mode 100644 index dd5eb98..0000000 --- a/packages/stream_core_flutter/.gitignore +++ /dev/null @@ -1,31 +0,0 @@ -# Miscellaneous -*.class -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.buildlog/ -.history -.svn/ -migrate_working_dir/ - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/ - -# The .vscode folder contains launch configuration and tasks you configure in -# VS Code which you may wish to be included in version control, so this line -# is commented out by default. -#.vscode/ - -# Flutter/Dart/Pub related -# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. -/pubspec.lock -**/doc/api/ -.dart_tool/ -.flutter-plugins-dependencies -/build/ -/coverage/ diff --git a/packages/stream_core_flutter/analysis_options.yaml b/packages/stream_core_flutter/analysis_options.yaml deleted file mode 100644 index a5744c1..0000000 --- a/packages/stream_core_flutter/analysis_options.yaml +++ /dev/null @@ -1,4 +0,0 @@ -include: package:flutter_lints/flutter.yaml - -# Additional information about this file can be found at -# https://dart.dev/guides/language/analysis-options diff --git a/packages/stream_core_flutter/lib/src/components/stream_button.dart b/packages/stream_core_flutter/lib/src/components/stream_button.dart index 32250d1..21a2b81 100644 --- a/packages/stream_core_flutter/lib/src/components/stream_button.dart +++ b/packages/stream_core_flutter/lib/src/components/stream_button.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; -import 'package:stream_core_flutter/src/theme/stream_component_factory.dart'; -import 'package:stream_core_flutter/stream_core_flutter.dart'; + +import '../../stream_core_flutter.dart'; +import '../theme/stream_component_factory.dart'; class StreamButton extends StatelessWidget { StreamButton({ @@ -12,13 +13,13 @@ class StreamButton extends StatelessWidget { Widget? iconLeft, Widget? iconRight, }) : props = StreamButtonProps( - label: label, - onTap: onTap, - type: type, - size: size, - iconLeft: iconLeft, - iconRight: iconRight, - ); + label: label, + onTap: onTap, + type: type, + size: size, + iconLeft: iconLeft, + iconRight: iconRight, + ); final StreamButtonProps props; @@ -53,10 +54,11 @@ enum StreamButtonType { primary, secondary, destructive } enum StreamButtonSize { small, medium, large } class DefaultStreamButton extends StatelessWidget { + const DefaultStreamButton({super.key, required this.props}); + static StreamComponentBuilder get factory => (context, props) => DefaultStreamButton(props: props); - const DefaultStreamButton({super.key, required this.props}); final StreamButtonProps props; @override @@ -67,20 +69,20 @@ class DefaultStreamButton extends StatelessWidget { final colors = switch (props.type) { StreamButtonType.primary => _primaryColors( - theme, - streamTheme, - buttonTheme, - ), + theme, + streamTheme, + buttonTheme, + ), StreamButtonType.secondary => _secondaryColors( - theme, - streamTheme, - buttonTheme, - ), + theme, + streamTheme, + buttonTheme, + ), StreamButtonType.destructive => _destructiveColors( - theme, - streamTheme, - buttonTheme, - ), + theme, + streamTheme, + buttonTheme, + ), }; return ElevatedButton( @@ -91,17 +93,15 @@ class DefaultStreamButton extends StatelessWidget { side: WidgetStateProperty.resolveWith( (states) => BorderSide( color: colors.borderColor.resolve(states), - width: 1, - style: BorderStyle.solid, ), ), elevation: WidgetStateProperty.all(0), ), child: Row( children: [ - if (props.iconLeft case final iconLeft?) iconLeft, + ?props.iconLeft, if (props.label case final label?) Text(label), - if (props.iconRight case final iconRight?) iconRight, + ?props.iconRight, ], ), ); @@ -111,40 +111,39 @@ class DefaultStreamButton extends StatelessWidget { ThemeData theme, StreamTheme streamTheme, StreamButtonTheme buttonTheme, - ) => - _StreamButtonColors( - bgColor: buttonTheme.primaryColor ?? - (streamTheme.primaryColor != null - ? WidgetStateProperty.all(streamTheme.primaryColor!) - : WidgetStateProperty.all(theme.colorScheme.primary)), - borderColor: buttonTheme.primaryColor ?? - (streamTheme.primaryColor != null - ? WidgetStateProperty.all(streamTheme.primaryColor!) - : WidgetStateProperty.all(theme.colorScheme.primary)), - textColor: WidgetStateProperty.all(Colors.white), - ); + ) => _StreamButtonColors( + bgColor: + buttonTheme.primaryColor ?? + (streamTheme.primaryColor != null + ? WidgetStateProperty.all(streamTheme.primaryColor!) + : WidgetStateProperty.all(theme.colorScheme.primary)), + borderColor: + buttonTheme.primaryColor ?? + (streamTheme.primaryColor != null + ? WidgetStateProperty.all(streamTheme.primaryColor!) + : WidgetStateProperty.all(theme.colorScheme.primary)), + textColor: WidgetStateProperty.all(Colors.white), + ); _StreamButtonColors _secondaryColors( ThemeData theme, StreamTheme streamTheme, StreamButtonTheme buttonTheme, - ) => - _StreamButtonColors( - bgColor: WidgetStateProperty.all(Colors.white), - borderColor: WidgetStateProperty.all(Colors.grey), - textColor: WidgetStateProperty.all(Colors.black), - ); + ) => _StreamButtonColors( + bgColor: WidgetStateProperty.all(Colors.white), + borderColor: WidgetStateProperty.all(Colors.grey), + textColor: WidgetStateProperty.all(Colors.black), + ); _StreamButtonColors _destructiveColors( ThemeData theme, StreamTheme streamTheme, StreamButtonTheme buttonTheme, - ) => - _StreamButtonColors( - bgColor: WidgetStateProperty.all(Colors.red), - borderColor: WidgetStateProperty.all(Colors.red), - textColor: WidgetStateProperty.all(Colors.white), - ); + ) => _StreamButtonColors( + bgColor: WidgetStateProperty.all(Colors.red), + borderColor: WidgetStateProperty.all(Colors.red), + textColor: WidgetStateProperty.all(Colors.white), + ); } class _StreamButtonColors { diff --git a/packages/stream_core_flutter/lib/src/theme/components/stream_button_theme.dart b/packages/stream_core_flutter/lib/src/theme/components/stream_button_theme.dart index fe0d01d..12e8337 100644 --- a/packages/stream_core_flutter/lib/src/theme/components/stream_button_theme.dart +++ b/packages/stream_core_flutter/lib/src/theme/components/stream_button_theme.dart @@ -1,5 +1,5 @@ import 'package:flutter/widgets.dart'; -import 'package:stream_core_flutter/stream_core_flutter.dart'; +import '../../../stream_core_flutter.dart'; class StreamButtonTheme { StreamButtonTheme({this.primaryColor}); diff --git a/packages/stream_core_flutter/lib/src/theme/stream_component_factory.dart b/packages/stream_core_flutter/lib/src/theme/stream_component_factory.dart index 17622d8..687ac2a 100644 --- a/packages/stream_core_flutter/lib/src/theme/stream_component_factory.dart +++ b/packages/stream_core_flutter/lib/src/theme/stream_component_factory.dart @@ -1,10 +1,9 @@ import 'package:flutter/widgets.dart'; -import 'package:stream_core_flutter/stream_core_flutter.dart'; +import '../../stream_core_flutter.dart'; import '../components/stream_button.dart' show DefaultStreamButton; -typedef StreamComponentBuilder = Widget Function( - BuildContext context, T props); +typedef StreamComponentBuilder = Widget Function(BuildContext context, T props); class StreamComponentFactory { StreamComponentFactory({ diff --git a/packages/stream_core_flutter/lib/src/theme/stream_theme.dart b/packages/stream_core_flutter/lib/src/theme/stream_theme.dart index 802599c..fc53183 100644 --- a/packages/stream_core_flutter/lib/src/theme/stream_theme.dart +++ b/packages/stream_core_flutter/lib/src/theme/stream_theme.dart @@ -1,14 +1,15 @@ import 'package:flutter/material.dart'; -import 'package:stream_core_flutter/src/theme/stream_component_factory.dart'; -import 'package:stream_core_flutter/stream_core_flutter.dart'; +import '../../stream_core_flutter.dart'; + +import 'stream_component_factory.dart'; class StreamTheme extends ThemeExtension { StreamTheme({ StreamComponentFactory? componentFactory, this.primaryColor, StreamButtonTheme? buttonTheme, - }) : componentFactory = componentFactory ?? StreamComponentFactory(), - buttonTheme = buttonTheme ?? StreamButtonTheme(); + }) : componentFactory = componentFactory ?? StreamComponentFactory(), + buttonTheme = buttonTheme ?? StreamButtonTheme(); final StreamComponentFactory componentFactory; diff --git a/packages/stream_core_flutter/lib/stream_core_flutter.dart b/packages/stream_core_flutter/lib/stream_core_flutter.dart index 995faad..274a80a 100644 --- a/packages/stream_core_flutter/lib/stream_core_flutter.dart +++ b/packages/stream_core_flutter/lib/stream_core_flutter.dart @@ -1,3 +1,3 @@ export 'src/components.dart'; -export 'src/theme/stream_theme.dart'; export 'src/theme/components.dart'; +export 'src/theme/stream_theme.dart'; diff --git a/packages/stream_core_flutter/pubspec.yaml b/packages/stream_core_flutter/pubspec.yaml index afa5e56..ded9734 100644 --- a/packages/stream_core_flutter/pubspec.yaml +++ b/packages/stream_core_flutter/pubspec.yaml @@ -4,8 +4,8 @@ version: 0.0.1 homepage: environment: - sdk: ^3.9.0 - flutter: ">=1.17.0" + sdk: ^3.10.0 + flutter: ">=3.38.1" dependencies: flutter: @@ -14,7 +14,6 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - flutter_lints: ^5.0.0 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec From f0ab9b825aa1ed867398faf342c57d3c93adee94 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Thu, 15 Jan 2026 20:56:36 +0100 Subject: [PATCH 2/8] ci(repo): Add 'ui' scope for conventional commits The `ui` scope is added to the list of allowed scopes for pull request titles in the `pr_title.yml` workflow. This workflow now validates for `llc`, `ui`, and `repo` scopes. Additionally, a temporary comment to remove the `main-design-system` branch is included, and the `semantic_changelog_update` job is enabled. --- .github/workflows/pr_title.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr_title.yml b/.github/workflows/pr_title.yml index 22934e1..cc067ce 100644 --- a/.github/workflows/pr_title.yml +++ b/.github/workflows/pr_title.yml @@ -7,7 +7,7 @@ on: - synchronize branches: - main - - main-design-system + - main-design-system # Remove this once the design system is merged into main concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -21,13 +21,13 @@ jobs: with: scopes: | llc + ui repo requireScope: true env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} semantic_changelog_update: - if: ${{ false }} # TODO: Enable after the first release needs: conventional_pr_title # Trigger after the [conventional_pr_title] completes runs-on: ubuntu-latest steps: From 471dc46e170b102c9fadaa84ed145999430386dd Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Thu, 15 Jan 2026 21:09:47 +0100 Subject: [PATCH 3/8] refactor: Clean up gallery and add const modifiers This commit refactors the `design_system_gallery` app by: - Deleting the `.gitignore` files in the root and `macos` directories. - Removing the `analysis_options.yaml` file. - Cleaning up the `pubspec.yaml` file by reordering dependencies and removing `flutter_lints`. - Adding `const` modifiers to widgets and expressions throughout the app for improved performance. - Making minor code style adjustments, such as reordering imports and simplifying a callback function. --- apps/design_system_gallery/.gitignore | 45 ------------------- .../analysis_options.yaml | 28 ------------ .../lib/components/button.dart | 2 +- apps/design_system_gallery/lib/main.dart | 2 +- .../lib/theme_config.dart | 23 ++++------ apps/design_system_gallery/macos/.gitignore | 7 --- apps/design_system_gallery/pubspec.yaml | 9 ++-- 7 files changed, 15 insertions(+), 101 deletions(-) delete mode 100644 apps/design_system_gallery/.gitignore delete mode 100644 apps/design_system_gallery/analysis_options.yaml delete mode 100644 apps/design_system_gallery/macos/.gitignore diff --git a/apps/design_system_gallery/.gitignore b/apps/design_system_gallery/.gitignore deleted file mode 100644 index 3820a95..0000000 --- a/apps/design_system_gallery/.gitignore +++ /dev/null @@ -1,45 +0,0 @@ -# Miscellaneous -*.class -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.build/ -.buildlog/ -.history -.svn/ -.swiftpm/ -migrate_working_dir/ - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/ - -# The .vscode folder contains launch configuration and tasks you configure in -# VS Code which you may wish to be included in version control, so this line -# is commented out by default. -#.vscode/ - -# Flutter/Dart/Pub related -**/doc/api/ -**/ios/Flutter/.last_build_id -.dart_tool/ -.flutter-plugins-dependencies -.pub-cache/ -.pub/ -/build/ -/coverage/ - -# Symbolication related -app.*.symbols - -# Obfuscation related -app.*.map.json - -# Android Studio will place build artifacts here -/android/app/debug -/android/app/profile -/android/app/release diff --git a/apps/design_system_gallery/analysis_options.yaml b/apps/design_system_gallery/analysis_options.yaml deleted file mode 100644 index 0d29021..0000000 --- a/apps/design_system_gallery/analysis_options.yaml +++ /dev/null @@ -1,28 +0,0 @@ -# This file configures the analyzer, which statically analyzes Dart code to -# check for errors, warnings, and lints. -# -# The issues identified by the analyzer are surfaced in the UI of Dart-enabled -# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be -# invoked from the command line by running `flutter analyze`. - -# The following line activates a set of recommended lints for Flutter apps, -# packages, and plugins designed to encourage good coding practices. -include: package:flutter_lints/flutter.yaml - -linter: - # The lint rules applied to this project can be customized in the - # section below to disable rules from the `package:flutter_lints/flutter.yaml` - # included above or to enable additional rules. A list of all available lints - # and their documentation is published at https://dart.dev/lints. - # - # Instead of disabling a lint rule for the entire project in the - # section below, it can also be suppressed for a single line of code - # or a specific dart file by using the `// ignore: name_of_lint` and - # `// ignore_for_file: name_of_lint` syntax on the line or in the file - # producing the lint. - rules: - # avoid_print: false # Uncomment to disable the `avoid_print` rule - # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule - -# Additional information about this file can be found at -# https://dart.dev/guides/language/analysis-options diff --git a/apps/design_system_gallery/lib/components/button.dart b/apps/design_system_gallery/lib/components/button.dart index 1d102d1..d9d2175 100644 --- a/apps/design_system_gallery/lib/components/button.dart +++ b/apps/design_system_gallery/lib/components/button.dart @@ -13,7 +13,7 @@ Widget buildCoolButtonUseCase(BuildContext context) { onTap: () { ScaffoldMessenger.of( context, - ).showSnackBar(SnackBar(content: Text('Button clicked'))); + ).showSnackBar(const SnackBar(content: Text('Button clicked'))); }, type: context.knobs.object.dropdown( label: 'Type', diff --git a/apps/design_system_gallery/lib/main.dart b/apps/design_system_gallery/lib/main.dart index 25c25f3..4cdefa7 100644 --- a/apps/design_system_gallery/lib/main.dart +++ b/apps/design_system_gallery/lib/main.dart @@ -1,4 +1,3 @@ -import 'package:design_system_gallery/theme_config.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:widgetbook/widgetbook.dart'; @@ -7,6 +6,7 @@ import 'package:widgetbook_annotation/widgetbook_annotation.dart' as widgetbook; // This file does not exist yet, // it will be generated in the next step import 'main.directories.g.dart'; +import 'theme_config.dart'; void main() { runApp(const WidgetbookApp()); diff --git a/apps/design_system_gallery/lib/theme_config.dart b/apps/design_system_gallery/lib/theme_config.dart index c0422f1..e8af065 100644 --- a/apps/design_system_gallery/lib/theme_config.dart +++ b/apps/design_system_gallery/lib/theme_config.dart @@ -6,7 +6,7 @@ import 'package:widgetbook_annotation/widgetbook_annotation.dart' as widgetbook; @widgetbook.UseCase(name: 'Default', type: ThemeConfig) Widget buildCoolButtonUseCase(BuildContext context) { - return ThemeConfig(); + return const ThemeConfig(); } class ThemeConfig extends StatelessWidget { @@ -18,7 +18,7 @@ class ThemeConfig extends StatelessWidget { return Column( children: [ - Text('Theme config'), + const Text('Theme config'), Row( spacing: 16, children: [ @@ -27,16 +27,13 @@ class ThemeConfig extends StatelessWidget { height: 25, color: themeConfiguration.themeData.primaryColor, ), - Text('Primary color'), + const Text('Primary color'), StreamButton( label: 'Pick color', onTap: () => pickColor( context, - themeConfiguration.themeData.primaryColor ?? - Theme.of(context).colorScheme.primary, - (color) { - themeConfiguration.setPrimaryColor(color); - }, + themeConfiguration.themeData.primaryColor ?? Theme.of(context).colorScheme.primary, + themeConfiguration.setPrimaryColor, ), ), ], @@ -45,15 +42,15 @@ class ThemeConfig extends StatelessWidget { ); } - void pickColor( + Future pickColor( BuildContext context, Color pickerColor, ValueChanged onColorChanged, ) { - showDialog( + return showDialog( context: context, builder: (context) => AlertDialog( - title: Text('Pick a color'), + title: const Text('Pick a color'), content: SingleChildScrollView( child: MaterialPicker( pickerColor: pickerColor, @@ -66,11 +63,9 @@ class ThemeConfig extends StatelessWidget { } class ThemeConfiguration extends ChangeNotifier { - StreamTheme themeData; - ThemeConfiguration({required this.themeData}); - ThemeConfiguration.empty() : themeData = StreamTheme(); + StreamTheme themeData; void setPrimaryColor(Color color) { themeData = themeData.copyWith(primaryColor: color); diff --git a/apps/design_system_gallery/macos/.gitignore b/apps/design_system_gallery/macos/.gitignore deleted file mode 100644 index 746adbb..0000000 --- a/apps/design_system_gallery/macos/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -# Flutter-related -**/Flutter/ephemeral/ -**/Pods/ - -# Xcode-related -**/dgph -**/xcuserdata/ diff --git a/apps/design_system_gallery/pubspec.yaml b/apps/design_system_gallery/pubspec.yaml index 7c78ea3..8281fad 100644 --- a/apps/design_system_gallery/pubspec.yaml +++ b/apps/design_system_gallery/pubspec.yaml @@ -7,22 +7,21 @@ environment: sdk: ^3.10.0 dependencies: + cupertino_icons: ^1.0.8 flutter: sdk: flutter - cupertino_icons: ^1.0.8 flutter_colorpicker: ^1.1.0 provider: ^6.1.5+1 - widgetbook: ^3.20.2 - widgetbook_annotation: ^3.9.0 stream_core_flutter: path: ../../packages/stream_core_flutter + widgetbook: ^3.20.2 + widgetbook_annotation: ^3.9.0 dev_dependencies: + build_runner: ^2.4.15 flutter_test: sdk: flutter - flutter_lints: ^5.0.0 widgetbook_generator: ^3.20.1 - build_runner: ^2.4.15 flutter: uses-material-design: true \ No newline at end of file From c281e5d1dddd96323e703fafd1d1ef467934ca3b Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Thu, 15 Jan 2026 21:20:22 +0100 Subject: [PATCH 4/8] refactor: Simplify OnBatchUploadProgress typedef --- .../lib/src/attachment/uploader/attachment_uploader.dart | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/stream_core/lib/src/attachment/uploader/attachment_uploader.dart b/packages/stream_core/lib/src/attachment/uploader/attachment_uploader.dart index b28e750..a660306 100644 --- a/packages/stream_core/lib/src/attachment/uploader/attachment_uploader.dart +++ b/packages/stream_core/lib/src/attachment/uploader/attachment_uploader.dart @@ -112,11 +112,7 @@ class StreamAttachmentUploader { /// /// Receives the [attachmentId] and upload [progress] as a value between 0.0 and 1.0 /// for individual attachments during batch upload. -typedef OnBatchUploadProgress = - void Function( - String attachmentId, - double progress, - ); +typedef OnBatchUploadProgress = void Function(String attachmentId, double progress); /// Extension providing batch upload functionality for [StreamAttachmentUploader]. /// From 4c2a72a87960678741b47b32df994894c0c6ccb2 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Thu, 15 Jan 2026 21:26:00 +0100 Subject: [PATCH 5/8] refactor: Remove explicit type annotations for error code lists --- packages/stream_core/lib/src/errors/stream_api_error.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/stream_core/lib/src/errors/stream_api_error.dart b/packages/stream_core/lib/src/errors/stream_api_error.dart index c18d8e9..19c2fe0 100644 --- a/packages/stream_core/lib/src/errors/stream_api_error.dart +++ b/packages/stream_core/lib/src/errors/stream_api_error.dart @@ -69,8 +69,8 @@ class StreamApiError extends Equatable { ]; } -final List _tokenInvalidErrorCodes = _range(40, 42); -final List _clientErrorCodes = _range(400, 499); +final _tokenInvalidErrorCodes = _range(40, 42); +final _clientErrorCodes = _range(400, 499); /// Extension methods for [StreamApiError] to provide convenient error type checks. extension StreamApiErrorExtension on StreamApiError { From 36487ac5dfa39403d3202791cd37f059b2abc83d Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Thu, 15 Jan 2026 21:45:09 +0100 Subject: [PATCH 6/8] chore: regenerate --- .../lib/src/errors/stream_api_error.g.dart | 49 ++++++++++--------- .../lib/src/logger/stream_logger.dart | 4 +- .../query/filter/location/bounding_box.g.dart | 13 ++--- .../filter/location/circular_region.g.dart | 11 +++-- .../stream_core/lib/src/query/sort.g.dart | 14 +++--- .../user/connect_user_details_request.g.dart | 19 +++---- packages/stream_core/lib/src/user/user.dart | 9 +--- .../src/user/ws_auth_message_request.g.dart | 19 +++---- .../ws/client/stream_web_socket_client.dart | 7 ++- 9 files changed, 72 insertions(+), 73 deletions(-) diff --git a/packages/stream_core/lib/src/errors/stream_api_error.g.dart b/packages/stream_core/lib/src/errors/stream_api_error.g.dart index e3fd613..1edb13b 100644 --- a/packages/stream_core/lib/src/errors/stream_api_error.g.dart +++ b/packages/stream_core/lib/src/errors/stream_api_error.g.dart @@ -6,26 +6,31 @@ part of 'stream_api_error.dart'; // JsonSerializableGenerator // ************************************************************************** -StreamApiError _$StreamApiErrorFromJson(Map json) => StreamApiError( - code: (json['code'] as num).toInt(), - details: (json['details'] as List).map((e) => (e as num).toInt()).toList(), - duration: json['duration'] as String, - exceptionFields: (json['exception_fields'] as Map?)?.map( - (k, e) => MapEntry(k, e as String), - ), - message: json['message'] as String, - moreInfo: json['more_info'] as String, - statusCode: (json['StatusCode'] as num).toInt(), - unrecoverable: json['unrecoverable'] as bool?, -); +StreamApiError _$StreamApiErrorFromJson(Map json) => + StreamApiError( + code: (json['code'] as num).toInt(), + details: + (json['details'] as List) + .map((e) => (e as num).toInt()) + .toList(), + duration: json['duration'] as String, + exceptionFields: (json['exception_fields'] as Map?)?.map( + (k, e) => MapEntry(k, e as String), + ), + message: json['message'] as String, + moreInfo: json['more_info'] as String, + statusCode: (json['StatusCode'] as num).toInt(), + unrecoverable: json['unrecoverable'] as bool?, + ); -Map _$StreamApiErrorToJson(StreamApiError instance) => { - 'code': instance.code, - 'details': instance.details, - 'duration': instance.duration, - 'exception_fields': instance.exceptionFields, - 'message': instance.message, - 'more_info': instance.moreInfo, - 'StatusCode': instance.statusCode, - 'unrecoverable': instance.unrecoverable, -}; +Map _$StreamApiErrorToJson(StreamApiError instance) => + { + 'code': instance.code, + 'details': instance.details, + 'duration': instance.duration, + 'exception_fields': instance.exceptionFields, + 'message': instance.message, + 'more_info': instance.moreInfo, + 'StatusCode': instance.statusCode, + 'unrecoverable': instance.unrecoverable, + }; diff --git a/packages/stream_core/lib/src/logger/stream_logger.dart b/packages/stream_core/lib/src/logger/stream_logger.dart index 6bfbeac..730f578 100644 --- a/packages/stream_core/lib/src/logger/stream_logger.dart +++ b/packages/stream_core/lib/src/logger/stream_logger.dart @@ -1,4 +1,4 @@ -final Map _priorityEmojiMapper = { +final _priorityEmojiMapper = { Priority.error: '🚨', Priority.warning: '⚠️', Priority.info: 'ℹ️', @@ -6,7 +6,7 @@ final Map _priorityEmojiMapper = { Priority.verbose: '🔍', }; -final Map _priorityNameMapper = { +final _priorityNameMapper = { Priority.error: 'E', Priority.warning: 'W', Priority.info: 'I', diff --git a/packages/stream_core/lib/src/query/filter/location/bounding_box.g.dart b/packages/stream_core/lib/src/query/filter/location/bounding_box.g.dart index ecb84e5..90bb530 100644 --- a/packages/stream_core/lib/src/query/filter/location/bounding_box.g.dart +++ b/packages/stream_core/lib/src/query/filter/location/bounding_box.g.dart @@ -6,9 +6,10 @@ part of 'bounding_box.dart'; // JsonSerializableGenerator // ************************************************************************** -Map _$BoundingBoxToJson(BoundingBox instance) => { - 'ne_lat': instance.neLat, - 'ne_lng': instance.neLng, - 'sw_lat': instance.swLat, - 'sw_lng': instance.swLng, -}; +Map _$BoundingBoxToJson(BoundingBox instance) => + { + 'ne_lat': instance.neLat, + 'ne_lng': instance.neLng, + 'sw_lat': instance.swLat, + 'sw_lng': instance.swLng, + }; diff --git a/packages/stream_core/lib/src/query/filter/location/circular_region.g.dart b/packages/stream_core/lib/src/query/filter/location/circular_region.g.dart index 2690c73..66a08e0 100644 --- a/packages/stream_core/lib/src/query/filter/location/circular_region.g.dart +++ b/packages/stream_core/lib/src/query/filter/location/circular_region.g.dart @@ -6,8 +6,9 @@ part of 'circular_region.dart'; // JsonSerializableGenerator // ************************************************************************** -Map _$CircularRegionToJson(CircularRegion instance) => { - 'lat': instance.lat, - 'lng': instance.lng, - 'distance': instance.distance, -}; +Map _$CircularRegionToJson(CircularRegion instance) => + { + 'lat': instance.lat, + 'lng': instance.lng, + 'distance': instance.distance, + }; diff --git a/packages/stream_core/lib/src/query/sort.g.dart b/packages/stream_core/lib/src/query/sort.g.dart index f9ed711..5f8c84f 100644 --- a/packages/stream_core/lib/src/query/sort.g.dart +++ b/packages/stream_core/lib/src/query/sort.g.dart @@ -6,12 +6,10 @@ part of 'sort.dart'; // JsonSerializableGenerator // ************************************************************************** -Map _$SortToJson(Sort instance) => { - 'field': Sort._fieldToJson(instance.field), - 'direction': _$SortDirectionEnumMap[instance.direction]!, -}; +Map _$SortToJson(Sort instance) => + { + 'field': Sort._fieldToJson(instance.field), + 'direction': _$SortDirectionEnumMap[instance.direction]!, + }; -const _$SortDirectionEnumMap = { - SortDirection.asc: 1, - SortDirection.desc: -1, -}; +const _$SortDirectionEnumMap = {SortDirection.asc: 1, SortDirection.desc: -1}; diff --git a/packages/stream_core/lib/src/user/connect_user_details_request.g.dart b/packages/stream_core/lib/src/user/connect_user_details_request.g.dart index f8f51e1..1d97036 100644 --- a/packages/stream_core/lib/src/user/connect_user_details_request.g.dart +++ b/packages/stream_core/lib/src/user/connect_user_details_request.g.dart @@ -6,12 +6,13 @@ part of 'connect_user_details_request.dart'; // JsonSerializableGenerator // ************************************************************************** -Map _$ConnectUserDetailsRequestToJson(ConnectUserDetailsRequest instance) => - { - 'id': instance.id, - 'image': instance.image, - 'invisible': instance.invisible, - 'language': instance.language, - 'name': instance.name, - 'custom': instance.custom, - }; +Map _$ConnectUserDetailsRequestToJson( + ConnectUserDetailsRequest instance, +) => { + 'id': instance.id, + 'image': instance.image, + 'invisible': instance.invisible, + 'language': instance.language, + 'name': instance.name, + 'custom': instance.custom, +}; diff --git a/packages/stream_core/lib/src/user/user.dart b/packages/stream_core/lib/src/user/user.dart index 0c471b0..606ea46 100644 --- a/packages/stream_core/lib/src/user/user.dart +++ b/packages/stream_core/lib/src/user/user.dart @@ -53,14 +53,7 @@ class User extends Equatable { String get name => originalName ?? id; @override - List get props => [ - id, - image, - role, - type, - originalName, - custom, - ]; + List get props => [id, image, role, type, originalName, custom]; } /// The user authorization type. diff --git a/packages/stream_core/lib/src/user/ws_auth_message_request.g.dart b/packages/stream_core/lib/src/user/ws_auth_message_request.g.dart index e9c2974..b32bada 100644 --- a/packages/stream_core/lib/src/user/ws_auth_message_request.g.dart +++ b/packages/stream_core/lib/src/user/ws_auth_message_request.g.dart @@ -6,12 +6,13 @@ part of 'ws_auth_message_request.dart'; // JsonSerializableGenerator // ************************************************************************** -Map _$WsAuthMessageRequestToJson(WsAuthMessageRequest instance) => - { - 'stringify': instance.stringify, - 'hash_code': instance.hashCode, - 'products': instance.products, - 'token': instance.token, - 'user_details': instance.userDetails?.toJson(), - 'props': instance.props, - }; +Map _$WsAuthMessageRequestToJson( + WsAuthMessageRequest instance, +) => { + 'stringify': instance.stringify, + 'hash_code': instance.hashCode, + 'products': instance.products, + 'token': instance.token, + 'user_details': instance.userDetails?.toJson(), + 'props': instance.props, +}; diff --git a/packages/stream_core/lib/src/ws/client/stream_web_socket_client.dart b/packages/stream_core/lib/src/ws/client/stream_web_socket_client.dart index 1c531f8..3e6c4ec 100644 --- a/packages/stream_core/lib/src/ws/client/stream_web_socket_client.dart +++ b/packages/stream_core/lib/src/ws/client/stream_web_socket_client.dart @@ -80,10 +80,9 @@ class StreamWebSocketClient implements WebSocketHealthListener, WebSocketEngineL /// /// Emits state changes as the WebSocket transitions through different connection states. ConnectionStateEmitter get connectionState => _connectionStateEmitter; - late final MutableStateEmitter _connectionStateEmitter = - MutableConnectionStateEmitter( - const WebSocketConnectionState.initialized(), - ); + late final _connectionStateEmitter = MutableConnectionStateEmitter( + const WebSocketConnectionState.initialized(), + ); set _connectionState(WebSocketConnectionState connectionState) { // Return early if the state hasn't changed. From 655fbadc37eb88e8c7716ab847e367148aba978a Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Thu, 15 Jan 2026 21:49:05 +0100 Subject: [PATCH 7/8] chore: regenerate --- .../lib/src/errors/stream_api_error.g.dart | 49 +++++++++---------- .../query/filter/location/bounding_box.g.dart | 13 +++-- .../filter/location/circular_region.g.dart | 11 ++--- .../stream_core/lib/src/query/sort.g.dart | 9 ++-- 4 files changed, 37 insertions(+), 45 deletions(-) diff --git a/packages/stream_core/lib/src/errors/stream_api_error.g.dart b/packages/stream_core/lib/src/errors/stream_api_error.g.dart index 1edb13b..e3fd613 100644 --- a/packages/stream_core/lib/src/errors/stream_api_error.g.dart +++ b/packages/stream_core/lib/src/errors/stream_api_error.g.dart @@ -6,31 +6,26 @@ part of 'stream_api_error.dart'; // JsonSerializableGenerator // ************************************************************************** -StreamApiError _$StreamApiErrorFromJson(Map json) => - StreamApiError( - code: (json['code'] as num).toInt(), - details: - (json['details'] as List) - .map((e) => (e as num).toInt()) - .toList(), - duration: json['duration'] as String, - exceptionFields: (json['exception_fields'] as Map?)?.map( - (k, e) => MapEntry(k, e as String), - ), - message: json['message'] as String, - moreInfo: json['more_info'] as String, - statusCode: (json['StatusCode'] as num).toInt(), - unrecoverable: json['unrecoverable'] as bool?, - ); +StreamApiError _$StreamApiErrorFromJson(Map json) => StreamApiError( + code: (json['code'] as num).toInt(), + details: (json['details'] as List).map((e) => (e as num).toInt()).toList(), + duration: json['duration'] as String, + exceptionFields: (json['exception_fields'] as Map?)?.map( + (k, e) => MapEntry(k, e as String), + ), + message: json['message'] as String, + moreInfo: json['more_info'] as String, + statusCode: (json['StatusCode'] as num).toInt(), + unrecoverable: json['unrecoverable'] as bool?, +); -Map _$StreamApiErrorToJson(StreamApiError instance) => - { - 'code': instance.code, - 'details': instance.details, - 'duration': instance.duration, - 'exception_fields': instance.exceptionFields, - 'message': instance.message, - 'more_info': instance.moreInfo, - 'StatusCode': instance.statusCode, - 'unrecoverable': instance.unrecoverable, - }; +Map _$StreamApiErrorToJson(StreamApiError instance) => { + 'code': instance.code, + 'details': instance.details, + 'duration': instance.duration, + 'exception_fields': instance.exceptionFields, + 'message': instance.message, + 'more_info': instance.moreInfo, + 'StatusCode': instance.statusCode, + 'unrecoverable': instance.unrecoverable, +}; diff --git a/packages/stream_core/lib/src/query/filter/location/bounding_box.g.dart b/packages/stream_core/lib/src/query/filter/location/bounding_box.g.dart index 90bb530..ecb84e5 100644 --- a/packages/stream_core/lib/src/query/filter/location/bounding_box.g.dart +++ b/packages/stream_core/lib/src/query/filter/location/bounding_box.g.dart @@ -6,10 +6,9 @@ part of 'bounding_box.dart'; // JsonSerializableGenerator // ************************************************************************** -Map _$BoundingBoxToJson(BoundingBox instance) => - { - 'ne_lat': instance.neLat, - 'ne_lng': instance.neLng, - 'sw_lat': instance.swLat, - 'sw_lng': instance.swLng, - }; +Map _$BoundingBoxToJson(BoundingBox instance) => { + 'ne_lat': instance.neLat, + 'ne_lng': instance.neLng, + 'sw_lat': instance.swLat, + 'sw_lng': instance.swLng, +}; diff --git a/packages/stream_core/lib/src/query/filter/location/circular_region.g.dart b/packages/stream_core/lib/src/query/filter/location/circular_region.g.dart index 66a08e0..2690c73 100644 --- a/packages/stream_core/lib/src/query/filter/location/circular_region.g.dart +++ b/packages/stream_core/lib/src/query/filter/location/circular_region.g.dart @@ -6,9 +6,8 @@ part of 'circular_region.dart'; // JsonSerializableGenerator // ************************************************************************** -Map _$CircularRegionToJson(CircularRegion instance) => - { - 'lat': instance.lat, - 'lng': instance.lng, - 'distance': instance.distance, - }; +Map _$CircularRegionToJson(CircularRegion instance) => { + 'lat': instance.lat, + 'lng': instance.lng, + 'distance': instance.distance, +}; diff --git a/packages/stream_core/lib/src/query/sort.g.dart b/packages/stream_core/lib/src/query/sort.g.dart index 5f8c84f..2d8de5f 100644 --- a/packages/stream_core/lib/src/query/sort.g.dart +++ b/packages/stream_core/lib/src/query/sort.g.dart @@ -6,10 +6,9 @@ part of 'sort.dart'; // JsonSerializableGenerator // ************************************************************************** -Map _$SortToJson(Sort instance) => - { - 'field': Sort._fieldToJson(instance.field), - 'direction': _$SortDirectionEnumMap[instance.direction]!, - }; +Map _$SortToJson(Sort instance) => { + 'field': Sort._fieldToJson(instance.field), + 'direction': _$SortDirectionEnumMap[instance.direction]!, +}; const _$SortDirectionEnumMap = {SortDirection.asc: 1, SortDirection.desc: -1}; From 8b9055797e1e6d8395f2053f85720a0fbee7e025 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Thu, 15 Jan 2026 21:52:14 +0100 Subject: [PATCH 8/8] chore: update build_runner and Dart SDK version in configuration files --- apps/design_system_gallery/pubspec.yaml | 2 +- melos.yaml | 2 +- packages/stream_core/pubspec.yaml | 2 +- pubspec.lock | 2 +- pubspec.yaml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/design_system_gallery/pubspec.yaml b/apps/design_system_gallery/pubspec.yaml index 8281fad..b3dd78d 100644 --- a/apps/design_system_gallery/pubspec.yaml +++ b/apps/design_system_gallery/pubspec.yaml @@ -18,7 +18,7 @@ dependencies: widgetbook_annotation: ^3.9.0 dev_dependencies: - build_runner: ^2.4.15 + build_runner: ^2.10.5 flutter_test: sdk: flutter widgetbook_generator: ^3.20.1 diff --git a/melos.yaml b/melos.yaml index 98ed897..b87e969 100644 --- a/melos.yaml +++ b/melos.yaml @@ -36,7 +36,7 @@ command: # List of all the dev_dependencies used in the project. dev_dependencies: - build_runner: ^2.4.15 + build_runner: ^2.10.5 json_serializable: ^6.9.5 melos: ^6.2.0 mocktail: ^1.0.4 diff --git a/packages/stream_core/pubspec.yaml b/packages/stream_core/pubspec.yaml index e7a38a0..aaf6294 100644 --- a/packages/stream_core/pubspec.yaml +++ b/packages/stream_core/pubspec.yaml @@ -36,7 +36,7 @@ dependencies: web_socket_channel: ^3.0.1 dev_dependencies: - build_runner: ^2.4.15 + build_runner: ^2.10.5 json_serializable: ^6.9.5 mocktail: ^1.0.4 test: ^1.26.2 diff --git a/pubspec.lock b/pubspec.lock index 6f5a39f..e2a4ec2 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -298,4 +298,4 @@ packages: source: hosted version: "2.2.2" sdks: - dart: ">=3.6.2 <4.0.0" + dart: ">=3.10.0 <4.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index ca55b7e..217ca38 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: stream_core_flutter_workspace environment: - sdk: ^3.6.2 + sdk: ^3.10.0 dev_dependencies: melos: ^6.2.0