install static method
Idempotent install. Safe to call multiple times within the same
isolate lifetime (matches DuskPlugin.install semantics).
Insertion order is load-bearing: the two original enrichers keep
their slot, the five Plan-Step-17 enrichers are appended after
them, the two Step-1.1 enrichers (controllerFlags, routeParams)
land at slots 7 and 8, the two Step-1.2 enrichers
(echoConnection, gateResultsAll) land at slots 9 and 10, and the
three Step-1.3 telescope-bridge enrichers (recentHttp, recentLogs,
recentExceptions) land at slots 11, 12, 13 so any first-write-wins
overlap stays deterministic across versions. After enricher
registration, one navigate adapter is wired via
DuskPlugin.registerNavigateAdapter so ext.dusk.navigate --route
drives MagicRouter.instance.to (path-based) instead of falling
back to the SystemNavigator broadcast.
Implementation
static void install() {
if (_installed) return;
_installed = true;
// 1. Original enrichers (insertion slots 0 and 1 — stable).
DuskPlugin.enrichers.add(magicFormEnricher);
DuskPlugin.enrichers.add(magicNavigationEnricher);
// 2. Plan-Step-17 enrichers (slots 2..6, added in declaration order).
DuskPlugin.enrichers.add(magicControllerEnricher);
DuskPlugin.enrichers.add(magicFormErrorsEnricher);
DuskPlugin.enrichers.add(magicGateResultEnricher);
DuskPlugin.enrichers.add(magicMiddlewareEnricher);
DuskPlugin.enrichers.add(magicAuthUserEnricher);
// 3. Step-1.1 enrichers (slots 7..8, added in declaration order).
DuskPlugin.enrichers.add(magicControllerFlagsEnricher);
DuskPlugin.enrichers.add(magicRouteParamsEnricher);
// 4. Step-1.2 enrichers (slots 9..10, added in declaration order).
DuskPlugin.enrichers.add(magicEchoConnectionEnricher);
DuskPlugin.enrichers.add(magicGateResultsAllEnricher);
// 5. Step-1.3 telescope-bridge enrichers (slots 11..13). Each enricher
// wraps its [TelescopeStore] read in try/catch so a missing-telescope
// classpath collapses to a graceful null without bubbling up.
DuskPlugin.enrichers.add(magicRecentHttpEnricher);
DuskPlugin.enrichers.add(magicRecentLogsEnricher);
DuskPlugin.enrichers.add(magicRecentExceptionsEnricher);
// 6. Subscribe to the Echo connection-state stream when broadcasting is
// registered; keep the last emitted value in the module-private cache
// so [magicEchoConnectionEnricher] can read it synchronously.
if (Magic.bound('broadcasting')) {
_echoSubscription = Echo.manager.connection().connectionState.listen(
(state) => _lastEchoState = _connectionStateName(state),
);
}
// 7. Register the navigate adapter so `ext.dusk.navigate --route <path>`
// drives GoRouter through MagicRouter instead of falling back to the
// SystemNavigator broadcast (which GoRouter does not listen to).
//
// The adapter uses MagicRouter.instance.to(route) (path-based navigation,
// NOT .toNamed) because the dusk `--route` argument is a URL path. A
// null router instance (not yet initialised) throws StateError; we catch
// it and return false so dusk can fall back to the platform broadcast.
DuskPlugin.registerNavigateAdapter((String route) async {
try {
MagicRouter.instance.to(route);
return true;
} on StateError {
return false;
}
});
}