Skip to content

Refactor Arcane framework and enhance logging, theme, and auth services#8

Merged
hanskokx merged 25 commits into
mainfrom
dev
May 26, 2026
Merged

Refactor Arcane framework and enhance logging, theme, and auth services#8
hanskokx merged 25 commits into
mainfrom
dev

Conversation

@hanskokx

@hanskokx hanskokx commented May 26, 2026

Copy link
Copy Markdown
Owner

Consolidates various improvements and new features across the Arcane framework, focusing on enhanced service management, reactive updates, and a more streamlined API for application integration. This release significantly refactors core services, introduces new provider patterns, and improves overall usability and extensibility.

Key Changes

  • Unified Service Management: ArcaneApp now centrally manages service registration, allowing built-in services (Arcane.features, Arcane.auth, Arcane.theme, Arcane.environment) to prefer instances registered with ArcaneApp and fall back to singletons when no provider is available.
  • Reactive Core: Introduces stream-based updates for authentication (statusChanges, signedInChanges), feature flags (enabledFeaturesChanges), logging (logStream), and theming (themeModeChanges, themeDataChanges), enabling more granular and reactive UI updates.
  • Logging Enhancements:
    • Implements a robust logging interceptor system (LogInterceptor) for pre-processing log messages.
    • New Interceptor Facade: A centralized interceptor facade (LoggingInterceptorsService) now manages registration, resolution, and lifecycle of log interceptors for all logging interfaces. This allows for global, per-interface, or per-event interception, modification, or filtering of log events, providing fine-grained control over logging behavior across the application.
    • Provides optional lifecycle management for logging interfaces (LoggingInitializable), and adds support for tagging destinations with @LoggingFeature.
  • Improved Theming: Renames ArcaneReactiveTheme to ArcaneThemeService for clarity, introduces assignment-style theme setters (Arcane.theme.dark = ...), and refines system theme following and theme mode detection logic.
  • Flexible Feature Flags: Renames ArcaneFeatureFlags to ArcaneFeatureFlagService, adds ArcaneFeatureFlagProvider for widget tree integration, and provides convenient BuildContext extensions.
  • Modernized Environment Management: Replaces the ArcaneEnvironment Cubit with a ValueNotifier-backed ArcaneEnvironmentService and an InheritedWidget provider, offering better integration and direct access via Arcane.environment.
  • Streamlined ArcaneApp Integration: Introduces ArcaneApp.builder to provide a provider-aware BuildContext immediately at app root, deprecating the child property for improved developer experience.
  • Dependency Management: Removes the direct flutter_bloc dependency and updates version constraints for result_monad to ^4.0.0, arcane_helper_utils to ^1.4.7, and arcane_analysis to ^1.0.4.

Breaking Changes

  • Arcane Class: Now a static utility surface; no longer instantiable. Consumers directly importing from package:arcane_framework/src/... must update paths (e.g., src/providers/... to src/service/...).
  • ArcaneApp: The child property is deprecated; prefer builder for constructing the app root with a provider-aware BuildContext.
  • Service Locators: BuildContext.serviceOfType() is deprecated; use BuildContext.service() instead.
  • Authentication Service: ArcaneAuthInterface.logout now accepts an optional onLoggedOut callback. Implementers must update their method signature.
  • Feature Flag Service: ArcaneFeatureFlags is renamed to ArcaneFeatureFlagService. A typedef is provided for backward compatibility, but update to the new name is recommended. ArcaneFeatureFlagsScope is renamed to ArcaneFeatureFlagProvider.
  • Theme Service: ArcaneReactiveTheme is renamed to ArcaneThemeService. A typedef is provided for backward compatibility, but update to the new name is recommended. The legacy ThemeMode read from Arcane.theme.systemTheme.value should be replaced with Arcane.theme.currentModeOf(context).
  • Environment Service: The state getter has been removed from ArcaneEnvironment; use Arcane.environment.current instead. The AuthenticationStatus.debug status has been removed.
  • Logging Interface: LoggingInterface no longer includes built-in singleton state (initialized and init getters/methods are removed). Implement LoggingInitializable for interfaces requiring setup logic.
  • Logging Interceptor Facade: All log interceptor management is now handled through the new LoggingInterceptorsService facade. Custom or legacy interceptor registration logic should be migrated to use this centralized service for consistency and improved control.

How to Test

  1. Run the example app: Navigate to example and run flutter run.
  2. Verify Service Interactions:
    • Toggle features, environment, and theme modes using the respective cards.
    • Observe log messages in the console and the "Logging" section of the app.
    • Sign in/out and check authentication status updates.
    • Interact with the "Services" card to register/remove the custom FavoriteColorService and change colors, observing dynamic theme updates.
  3. Inspect Logs: Ensure log messages appear as expected, including additional metadata (e.g., persistent metadata toggle) and proper level filtering (e.g., feature flag for logging). Test that interceptors registered via the facade are invoked as expected for all interfaces.
  4. Check UI Responsiveness: Confirm that UI elements react dynamically to changes in feature flags, environment, and theme, especially the interactive elements in the example.
  5. Validate Build/Analyze: Run flutter pub get, flutter analyze, and flutter test from the root of the repository to ensure all checks pass.

Review Focus

  • API Ergonomics: Review the new API patterns for ArcaneApp.builder, BuildContext extensions for services, feature flags, and themes for intuitiveness and ease of use.
  • Stream Integration: Verify the correct usage and disposal of stream controllers and subscriptions for all reactive services, particularly in the example app's widget lifecycles.
  • Logging Interceptors & Facade: Examine the implementation of LogInterceptor and the new LoggingInterceptorsService facade to ensure they provide robust and flexible control over log events, and that global/per-interface interception works as intended.
  • Backward Compatibility: Confirm that typedefs and deprecated aliases for renamed services function as expected during migration, and the impact of other breaking changes is clear.
  • Performance: Assess any potential performance implications from the new provider and stream architecture.
  • Test Coverage: Review the updated tests for new features and refactored logic, ensuring comprehensive validation.

UI Changes

The example application has been completely refactored to demonstrate the new API.

hanskokx added 25 commits May 26, 2026 11:38
Changes:
// ArcaneEnvironment
breaking: context.read<ArcaneEnvironment>() -> ArcaneEnvironment.of(context)
breaking: context.read<ArcaneEnvironment>().state -> ArcaneEnvironment.of(context).environment;

// Feature flag service
added: reset()

// Logging service
added: registerInterface()
added: unregisterInterfaces()
added: unregisterAllInterfaces()

// ArcaneReactiveTheme
fixed: currentMode, dark, light now actually emit new values when changed
added: getters for lightTheme, darkTheme, and systemTheme
TODO: test systemTheme

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
- added: reset()
- added: `skipAutodetection` option for module, method, and metadata
- added: unregisterInterface()
- Created FileAndLineNumber mixin

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
…ness

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
…her, where it is more appropriate

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
…ion for 2.0.0 (#5)

* Made ArcaneTheme private (_ArcaneTheme)

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

* Updated changelog

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

* Fix updateShouldNotify on ArcaneServiceProvider

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

* Update service provider

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

* Put service locators in an extension

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

* Try using a mixin instead

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

* Remove 'of' and 'requiredOf' locators

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

* Re-add service locators. They should be called as:

ArcaneService.of<MyService>(context)

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

* Renamed getters on ArcaneService

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

* Renamed serviceInstances => registeredServices and added a removeService method

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

* Broke up arcane service into separate files

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

* Added requiredServiceOfType getter on ArcaneServiceProvider

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

* Updated services section of the readme

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

* Updated example to add a services example

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

* Removed unused variable

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

* Update example documentation

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

* Update example

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

* Breaking up example into smaller widgets

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

* Remove bloc dependency

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

* Fixes the notifier for feature flags and updates the example

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

* Fixed a bug in the example

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

* Update ServiceProvider to make service instances optional

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

* Remove unnecessary notifyListeners calls

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

* Organize theme service

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

* Fix authentication interface and service methods for logout and login.

* Fix DebugAuthInterface logout method

Added environment key to ArcaneEnvironment constructor
 Renamed switchEnvironment parameter in ArcaneEnvironment constructor

Bumped arcane_helper_utils dependency version

* Enhance theme management with StreamBuilder for dynamic updates

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

* Add configuration files and update authentication service error handling

- Introduced .vscode/settings.json and .vscode/launch.json for IDE configuration.
- Updated DebugAuthInterface and ArcaneAuthenticationService to return const Result.ok() for consistency.
- Added ArcaneTheme class for theme management.
- Updated pubspec.yaml to change result_monad dependency version.
- Modified authentication_service_test to return const Result.ok() in mock setups.

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

* Update dependency versions to use 'any' for arcane_helper_utils and arcane_analysis

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

* Remove unnecessary 'const' keyword from Result.ok calls in DebugAuthInterface methods

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

* Add 'const' keyword to Result.ok calls in DebugAuthInterface methods

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

* Enhance logging service with new lifecycle capabilities and interceptor support

- Updated `LoggingInterface` to remove singleton-style initialization.
- Introduced `LoggingInitializable` and `LoggingInitializationMixin` for optional lifecycle management.
- Added `LogEvent` and `LogInterceptor` classes for improved logging event handling and interception.
- Updated `ArcaneLogger` to support multiple logging interfaces and global interceptors.
- Modified `DebugPrint` and `DebugAuthInterface` to align with new logging structure.
- Enhanced tests to cover new logging features and interceptor functionality.

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

* Add stream-based updates for authentication, feature flags, logging, and theming

- Added `statusChanges` and `signedInChanges` streams to `ArcaneAuth` for real-time authentication updates.
- Introduced `enabledFeaturesChanges` stream in `ArcaneFeatureFlags` for observing feature updates.
- Improved `ArcaneLogger` to maintain `logStream` usability after listener cancellation.
- Updated `ArcaneTheme` to provide streams for theme mode and theme data changes.
- Enhanced documentation and examples to reflect new stream APIs and usage patterns.
- Added regression tests for stream listener cancellation and re-subscription across services.

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

* Refactor ArcaneEnvironment and AuthenticationService for improved environment management and status handling

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

* Add application environment management and tests for authentication status coherence

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

* feat: Enhance service management with ArcaneApp provider composition

This commit significantly refactors Arcane's service architecture.
ArcaneApp now acts as a StatefulWidget, composing InheritedWidget-
based providers for core services (features, environment, theme, auth).
Service lookups (e.g., Arcane.features, context.service()) now
prioritize provider-registered instances, falling back to singletons.

Key changes include:
- Renamed ArcaneFeatureFlags to ArcaneFeatureFlagService and
  ArcaneReactiveTheme to ArcaneThemeService (with typedefs).
- Introduced ArcaneEnvironmentService and ArcaneEnvironmentProvider
  for centralized environment management.
- Added BuildContext extensions (e.g., context.featureFlags) for
  reactive, convenient service access.
- Removed .puro.json and its references, streamlining SDK setup.
- Updated CHANGELOG.md to reflect a 2.0.0 release, detailing all
  breaking changes and new features.

* chore(example): Add ignore rules for example builds

* feat(logging): Introduce log interceptors and origin control

Introduces the LogInterceptor class, enabling pre-processing, modification,
or suppression of log events before they reach registered interfaces.
The LogInterceptorContext provides contextual information such as the
originating LoggingInterface.

Adds a `skipAutodetection` parameter to Arcane.log, allowing control
over the automatic detection of log origin (module, method, file/line).

Also makes the LogEvent class extendable to support custom event types
and updates existing interceptor callback signatures for consistency.

* fix(theme): Update theme mode check to use currentModeOf method

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

* fix(theme): Improve theme mode detection and toggling

`context.isDarkMode` now reflects the app's effective theme brightness, not
the raw platform brightness. This ensures `isDarkMode` accurately reports the
currently rendered theme.

`switchTheme()` now intelligently toggles from the *effective* theme when
in `ThemeMode.system` by considering the current app brightness.

`followSystemTheme()` is updated to always read the platform brightness
directly, decoupling its behavior from the app's overridden theme settings.

* feat(example): Improve theme and service integration demo

Updates the example application to better demonstrate service and theme
integration. The `FavoriteColorService` now actively sets the app's
color scheme and can initialize its state from the current theme.
Environment display is now reactive, and the UI responds dynamically
to service registration and removal. Initial themes are now explicitly
seeded.

* feat(example): Add interactive persistent metadata toggle

Previously, persistent metadata was added unconditionally.
This change allows users to dynamically enable or disable
the demo persistent metadata via a UI switch, better
showcasing the API functionality.

* feat(theme): Add assignment-style theme setters

Introduces convenience setters for dark and light themes, allowing
`Arcane.theme.dark = ...` and `Arcane.theme.light = ...` as an
alternative to `setDarkTheme` and `setLightTheme`. This improves
developer ergonomics and conciseness.

* docs(README): Add Application Environments section to features list

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

* Adds `ArcaneApp.builder` to provide a provider-aware `BuildContext`
for the application root. This deprecates the `ArcaneApp.child`
parameter, improving developer experience for accessing Arcane's
providers at build time.

Updates the `ArcaneThemeSwitcher` to default to `followSystemTheme`
when mounted under `ArcaneApp`, ensuring system theme behavior
is enabled out of the box.

Fixes `setDarkTheme` and `setLightTheme` to only update the rendered
theme if their respective modes are currently active. This prevents
unintended UI changes when updating the definition of an inactive theme.

Updates README and examples to reflect the new `builder` API and
clarified theme logic. Adds new tests for these changes.

* docs(arcane_app): Clarify ArcaneApp API and provider access documentation

Updates the documentation for the `ArcaneApp` constructor to
explicitly detail the preferred `builder` API and the deprecated
`child` parameter, including migration guidance. Also updates the
list of provided services to include `ArcaneFeatureFlagsProvider`.

* feat: Overhaul Arcane framework for 2.0.0 release notes

Migrate Arcane to a static utility surface, removing the instantiable
singleton constructor for simpler and more direct access to services.
Introduce new reactive streams for environment, authentication, and
theme services, enabling real-time observation of state changes.
Enhance `ArcaneApp` integration with the new `builder` callback
and `BuildContext` convenience accessors for services and feature flags.
Update `ArcaneAuthInterface.logout` signature and revise `src` import
paths, requiring consumers to update their implementations and imports.
Deprecate `ArcaneApp.child` and `BuildContext.serviceOfType<T>()`
in favor of new, more idiomatic APIs.
Remove direct `flutter_bloc` dependency and upgrade `result_monad`
to `^4.0.0`.

* refactor(environment): Rename environment access getter to current

This change unifies how the current application environment is accessed
across Arcane's services and providers. The `state` and `environment`
getters have been replaced with a consistent `current` getter,
simplifying API usage and aligning with new patterns.
Includes corresponding updates in example and internal code,
and documents the migration in the CHANGELOG.

* chore: Relax result_monad dependency constraint

The `result_monad` dependency was recently upgraded to `^4.0.0`.
This update relaxes the constraint to `any` to provide greater
flexibility and mitigate potential dependency conflicts for consumers
of Arcane, allowing them to use other compatible versions.

* refactor(logging): Replace LoggingInitializationMixin with LoggingInitialization and add LoggingFeature annotation support

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

* docs(changelog): Add migration steps for ArcaneThemeService and update themeMode configuration examples

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

* refactor(workflow): Simplify analyze-and-test workflow by removing unused environment variables and steps

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

* docs(changelog): Update Arcane.log metadata type and add migration steps for structured values

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

* test: Add unit tests for authentication and feature flags functionality

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

* feat(theme): track user-defined theme overrides in ArcaneThemeService

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

* refactor(service): update service access methods in ArcaneServiceProvider

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

* refactor(tests): format login and logout method signatures in MockAuth for improved readability

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

* feat(tests): add unit tests for ArcaneThemeService functionality

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>

---------

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
…aints

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
fix(logging): ensure proper cancellation of log stream subscriber

refactor(arcane): make built-in services list unmodifiable

fix(app): update service notifier on widget updates

fix(service): improve removeService method to return boolean

fix(auth): update BuildContext parameter to unused in setDebug/setNormal

fix(logging): correct log level reference in LogInterceptorContext documentation

fix(theme): update documentation to reflect ThemeMode instead of ThemeData

fix(theme): ensure unawaited cancellation of theme subscriptions

chore(dependencies): update arcane_analysis version to ^1.0.4

test: make ArcaneAuthenticationService reset asynchronous in tests
Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
…eLogger

- Added support for global interceptors that apply to all interfaces.
- Introduced type-scoped interceptors for specific interface types.
- Updated CHANGELOG with migration steps and new API details.
- Adjusted README and tests to reflect changes in interceptor registration.

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
…ptors and global interceptor functionality

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
… APIs and scoped matching

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
@hanskokx hanskokx self-assigned this May 26, 2026
@hanskokx hanskokx added documentation Improvements or additions to documentation enhancement New feature or request labels May 26, 2026
@hanskokx hanskokx requested a review from Copilot May 26, 2026 14:07

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates Arcane’s logging interceptor API to use a centralized LoggingInterceptorsService facade (exposed via Arcane.logger.interceptors) and aligns documentation/tests with the new collection-style interceptor management.

Changes:

  • Introduces LoggingInterceptorsService and refactors ArcaneLogger to resolve interceptors via the new facade (global + scoped).
  • Updates logging service tests and README examples to use Arcane.logger.interceptors.add/remove/clear and matcher-based scoping.
  • Minor maintenance updates: theme test formatting, changelog entries, and .gitignore patterns.

Reviewed changes

Copilot reviewed 6 out of 7 changed files in this pull request and generated no comments.

Show a summary per file
File Description
lib/src/services/logging/logging_service.dart Refactors logger to use the new interceptor facade and removes the old global-interceptor list APIs.
lib/src/services/logging/logging_interceptors_service.dart Adds the interceptor facade supporting global and matcher-scoped registrations plus per-interface registrations.
test/services/logging/logging_service_test.dart Expands/updates tests to cover the new interceptor collection APIs and matcher scoping behavior.
README.md Updates docs/examples for the new interceptor API and adds a centered logo image.
CHANGELOG.md Documents the interceptor API change and reorders relevant logging notes.
.gitignore Adds an ignore rule for VS Code settings under the example app (currently with an incorrect path).
test/services/theme/theme_service_test.dart Formatting-only change for theme setter calls.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@hanskokx hanskokx merged commit 6f6428b into main May 26, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants