Skip to content

Commit 0cba3ef

Browse files
authored
feat(network): add configureDriver() plugin hook for Dio access (#35)
* feat(network): add configureDriver() plugin hook for Dio access (#32) Enables SDK integrations (sentry_dio, cert pinning) that need raw Dio instance access. Configurator callback pattern keeps Dio conceptually owned by the driver while allowing one-time setup. * fix(test): assert observable Dio mutations in configureDriver tests (#35) Tests now verify interceptor count changes on the driver-owned Dio instance instead of only asserting callbacks were invoked. Ensures configurator receives the actual Dio instance, not a fresh one.
1 parent 959c653 commit 0cba3ef

5 files changed

Lines changed: 89 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ All notable changes to this project will be documented in this file.
66

77
### ✨ Features
88
- **Router Observers**: `MagicRouter.instance.addObserver()` enables NavigatorObserver integration for analytics/monitoring (Sentry, Firebase Analytics, custom observers). Observers are passed to GoRouter automatically. (#31)
9+
- **Network Driver Plugin Hook**: `DioNetworkDriver.configureDriver()` exposes the underlying Dio instance for SDK integrations (sentry_dio, certificate pinning, custom adapters). (#32)
910

1011
## [1.0.0-alpha.6] - 2026-04-05
1112

doc/basics/http-client.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,3 +299,17 @@ class NetworkServiceProvider extends ServiceProvider {
299299
}
300300
}
301301
```
302+
303+
### Driver Plugin Hook
304+
305+
For SDK integrations that need direct Dio access (e.g., `sentry_dio` for performance tracing, certificate pinning), use `configureDriver()`:
306+
307+
```dart
308+
final driver = Magic.make<DioNetworkDriver>('network');
309+
driver.configureDriver((dio) {
310+
dio.addSentry(); // Full Sentry performance tracing
311+
});
312+
```
313+
314+
> [!NOTE]
315+
> `configureDriver()` is specific to `DioNetworkDriver`. Resolve using `Magic.make<DioNetworkDriver>('network')` to access it.

lib/src/network/drivers/dio_network_driver.dart

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,21 @@ class DioNetworkDriver implements NetworkDriver {
109109
);
110110
}
111111

112+
/// Configure the underlying Dio instance directly.
113+
///
114+
/// Use this for SDK integrations that need raw Dio access
115+
/// (e.g., `sentry_dio`, certificate pinning, custom adapters).
116+
///
117+
/// ```dart
118+
/// final driver = Magic.make<DioNetworkDriver>('network');
119+
/// driver.configureDriver((dio) {
120+
/// dio.addSentry();
121+
/// });
122+
/// ```
123+
void configureDriver(void Function(Dio dio) configurator) {
124+
configurator(_dio);
125+
}
126+
112127
// ---------------------------------------------------------------------------
113128
// RESTful Resource Methods
114129
// ---------------------------------------------------------------------------

skills/magic-framework/references/http-network.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,20 @@ await Magic.init();
315315
Magic.make<NetworkDriver>('network').addInterceptor(LoggingInterceptor());
316316
```
317317

318+
## Driver Plugin Hook
319+
320+
For SDK integrations that need direct Dio access (e.g., `sentry_dio`, certificate pinning), use `configureDriver()`:
321+
322+
```dart
323+
// In a service provider boot()
324+
final driver = Magic.make<DioNetworkDriver>('network');
325+
driver.configureDriver((dio) {
326+
dio.addSentry(); // sentry_dio integration
327+
});
328+
```
329+
330+
This is a `DioNetworkDriver`-specific method (not on the `NetworkDriver` contract). Cast or resolve as `DioNetworkDriver` to access it.
331+
318332
## ValidatesRequests Mixin
319333

320334
Use the `ValidatesRequests` mixin in controllers to simplify validation error mapping from HTTP responses.

test/network/network_test.dart

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,51 @@ void main() {
104104
// Should not throw
105105
driver.addInterceptor(interceptor);
106106
});
107+
108+
test('configureDriver() mutates the driver-owned Dio instance', () {
109+
late int countBefore;
110+
111+
driver.configureDriver((dio) {
112+
countBefore = dio.interceptors.length;
113+
dio.interceptors.add(
114+
InterceptorsWrapper(
115+
onRequest: (options, handler) => handler.next(options),
116+
),
117+
);
118+
});
119+
120+
// Verify interceptor persists on the same Dio instance.
121+
late int countAfter;
122+
driver.configureDriver((dio) {
123+
countAfter = dio.interceptors.length;
124+
});
125+
126+
expect(countAfter, countBefore + 1);
127+
});
128+
129+
test('configureDriver() allows multiple configurators', () {
130+
late int countAfterFirst;
131+
late int countAfterSecond;
132+
133+
driver.configureDriver((dio) {
134+
dio.interceptors.add(
135+
InterceptorsWrapper(
136+
onRequest: (options, handler) => handler.next(options),
137+
),
138+
);
139+
countAfterFirst = dio.interceptors.length;
140+
});
141+
driver.configureDriver((dio) {
142+
dio.interceptors.add(
143+
InterceptorsWrapper(
144+
onRequest: (options, handler) => handler.next(options),
145+
),
146+
);
147+
countAfterSecond = dio.interceptors.length;
148+
});
149+
150+
expect(countAfterSecond, countAfterFirst + 1);
151+
});
107152
});
108153
}
109154

0 commit comments

Comments
 (0)