mirror of
https://github.com/hanskokx/arcane_framework.git
synced 2026-08-12 06:10:55 +02:00
v2.0.5: Add typed service lookup entrypoint and tests for Arcane.service
Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
This commit is contained in:
@@ -1,3 +1,12 @@
|
|||||||
|
## 2.0.5
|
||||||
|
|
||||||
|
### Arcane Framework
|
||||||
|
|
||||||
|
- [NEW] Added `Arcane.service` typed lookup entrypoint for provider-aware
|
||||||
|
service access:
|
||||||
|
- `Arcane.service.ofType<T>(context)`
|
||||||
|
- `Arcane.service.requiredOfType<T>(context)`
|
||||||
|
|
||||||
## 2.0.4
|
## 2.0.4
|
||||||
|
|
||||||
### Logging Service
|
### Logging Service
|
||||||
|
|||||||
@@ -169,6 +169,8 @@ services:
|
|||||||
`ArcaneService` instances. **Note**: This widget is already part of the
|
`ArcaneService` instances. **Note**: This widget is already part of the
|
||||||
_`ArcaneApp`_ widget, however if you are not using the `ArcaneApp` widget you
|
_`ArcaneApp`_ widget, however if you are not using the `ArcaneApp` widget you
|
||||||
can instead use this widget directly.
|
can instead use this widget directly.
|
||||||
|
- `Arcane.service`: Typed service lookup entrypoint with
|
||||||
|
`ofType<T>(context)` and `requiredOfType<T>(context)`.
|
||||||
- The `service<T>` and `requiredService<T>` extensions on `BuildContext`:
|
- The `service<T>` and `requiredService<T>` extensions on `BuildContext`:
|
||||||
nullable and non-nullable getters used to locate a given `ArcaneService` via
|
nullable and non-nullable getters used to locate a given `ArcaneService` via
|
||||||
`BuildContext`. **Note**: For app-defined services, these lookups require an
|
`BuildContext`. **Note**: For app-defined services, these lookups require an
|
||||||
@@ -255,11 +257,13 @@ whatever method you prefer:
|
|||||||
```dart
|
```dart
|
||||||
// If a service of the given type is not registered, `null` is returned.
|
// If a service of the given type is not registered, `null` is returned.
|
||||||
final FavoriteColorService? nullableService = ArcaneService.ofType<FavoriteColorService>(context);
|
final FavoriteColorService? nullableService = ArcaneService.ofType<FavoriteColorService>(context);
|
||||||
|
final FavoriteColorService? nullableViaArcane = Arcane.service.ofType<FavoriteColorService>(context);
|
||||||
final FavoriteColorService? nullableViaContext = context.service<FavoriteColorService>();
|
final FavoriteColorService? nullableViaContext = context.service<FavoriteColorService>();
|
||||||
final FavoriteColorService? nullableViaProvider = ArcaneServiceProvider.serviceOfType<FavoriteColorService>(context);
|
final FavoriteColorService? nullableViaProvider = ArcaneServiceProvider.serviceOfType<FavoriteColorService>(context);
|
||||||
|
|
||||||
// If a service of the given type is not registered, an exception is thrown.
|
// If a service of the given type is not registered, an exception is thrown.
|
||||||
final FavoriteColorService nonNullableService = ArcaneService.requiredOfType<FavoriteColorService>(context);
|
final FavoriteColorService nonNullableService = ArcaneService.requiredOfType<FavoriteColorService>(context);
|
||||||
|
final FavoriteColorService nonNullableViaArcane = Arcane.service.requiredOfType<FavoriteColorService>(context);
|
||||||
final FavoriteColorService nonNullableViaContext = context.requiredService<FavoriteColorService>();
|
final FavoriteColorService nonNullableViaContext = context.requiredService<FavoriteColorService>();
|
||||||
final FavoriteColorService nonNullableViaProvider = ArcaneServiceProvider.requiredServiceOfType<FavoriteColorService>(context);
|
final FavoriteColorService nonNullableViaProvider = ArcaneServiceProvider.requiredServiceOfType<FavoriteColorService>(context);
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -24,7 +24,9 @@ Future<void> main() async {
|
|||||||
final DebugPrint debugPrintInterface = DebugPrint();
|
final DebugPrint debugPrintInterface = DebugPrint();
|
||||||
final DebugAuthInterface debugAuthInterface = DebugAuthInterface();
|
final DebugAuthInterface debugAuthInterface = DebugAuthInterface();
|
||||||
LogEvent? skipDebugPrintWhenDisabled(
|
LogEvent? skipDebugPrintWhenDisabled(
|
||||||
LogEvent event, LogInterceptorContext context) {
|
LogEvent event,
|
||||||
|
LogInterceptorContext context,
|
||||||
|
) {
|
||||||
if (context.interface is DebugPrint && Feature.logging.disabled) {
|
if (context.interface is DebugPrint && Feature.logging.disabled) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,9 @@ abstract class Arcane {
|
|||||||
/// Logger is not a service and is always the singleton.
|
/// Logger is not a service and is always the singleton.
|
||||||
static ArcaneLogger get logger => ArcaneLogger.I;
|
static ArcaneLogger get logger => ArcaneLogger.I;
|
||||||
|
|
||||||
|
/// Provides typed service lookups through `Arcane.service.ofType<T>(context)`.
|
||||||
|
static const ArcaneServiceLookup service = ArcaneServiceLookup();
|
||||||
|
|
||||||
/// Provides access to the feature flags service instance registered in ArcaneApp, or the singleton if not present.
|
/// Provides access to the feature flags service instance registered in ArcaneApp, or the singleton if not present.
|
||||||
static ArcaneFeatureFlagService get features =>
|
static ArcaneFeatureFlagService get features =>
|
||||||
services.whereType<ArcaneFeatureFlagService>().firstOrNull ??
|
services.whereType<ArcaneFeatureFlagService>().firstOrNull ??
|
||||||
|
|||||||
@@ -144,3 +144,20 @@ class ArcaneServiceProvider
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Typed service lookup entrypoint for `Arcane.service`.
|
||||||
|
class ArcaneServiceLookup {
|
||||||
|
const ArcaneServiceLookup();
|
||||||
|
|
||||||
|
/// Returns a service of type `T` from the closest provider in [context].
|
||||||
|
///
|
||||||
|
/// Falls back to Arcane's built-in services when no provider instance exists.
|
||||||
|
T? ofType<T extends ArcaneService>(BuildContext context) =>
|
||||||
|
ArcaneService.ofType<T>(context);
|
||||||
|
|
||||||
|
/// Returns a service of type `T` from the closest provider in [context].
|
||||||
|
///
|
||||||
|
/// Throws an assertion error if no matching service is available.
|
||||||
|
T requiredOfType<T extends ArcaneService>(BuildContext context) =>
|
||||||
|
ArcaneService.requiredOfType<T>(context);
|
||||||
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
name: arcane_framework
|
name: arcane_framework
|
||||||
description: "Agnostic Reusable Component Architecture for New Ecosystems: a
|
description: "Agnostic Reusable Component Architecture for New Ecosystems: a
|
||||||
modern framework for bootstrapping new applications"
|
modern framework for bootstrapping new applications"
|
||||||
version: 2.0.4
|
version: 2.0.5
|
||||||
repository: https://github.com/hanskokx/arcane_framework
|
repository: https://github.com/hanskokx/arcane_framework
|
||||||
issue_tracker: https://github.com/hanskokx/arcane_framework/issues
|
issue_tracker: https://github.com/hanskokx/arcane_framework/issues
|
||||||
|
|
||||||
|
|||||||
@@ -325,6 +325,52 @@ void main() {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets("Arcane.service.ofType<T> helper works", (tester) async {
|
||||||
|
await tester.pumpWidget(
|
||||||
|
ArcaneApp(
|
||||||
|
services: testServices,
|
||||||
|
child: Builder(
|
||||||
|
builder: (context) {
|
||||||
|
final service = Arcane.service.ofType<MockArcaneService>(context);
|
||||||
|
expect(service, isNotNull);
|
||||||
|
expect(service, isA<MockArcaneService>());
|
||||||
|
|
||||||
|
final missing = Arcane.service.ofType<UnregisteredService>(
|
||||||
|
context,
|
||||||
|
);
|
||||||
|
expect(missing, isNull);
|
||||||
|
return const SizedBox();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets("Arcane.service.requiredOfType<T> helper works",
|
||||||
|
(tester) async {
|
||||||
|
await tester.pumpWidget(
|
||||||
|
ArcaneApp(
|
||||||
|
services: testServices,
|
||||||
|
child: Builder(
|
||||||
|
builder: (context) {
|
||||||
|
final service = Arcane.service.requiredOfType<MockArcaneService>(
|
||||||
|
context,
|
||||||
|
);
|
||||||
|
expect(service, isA<MockArcaneService>());
|
||||||
|
|
||||||
|
expect(
|
||||||
|
() =>
|
||||||
|
Arcane.service.requiredOfType<UnregisteredService>(context),
|
||||||
|
throwsA(isA<AssertionError>()),
|
||||||
|
);
|
||||||
|
|
||||||
|
return const SizedBox();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user