subscriptionFeatureRedirect function
Returns a redirect function compatible with GoRouter's redirect
parameter that gates a route behind a feature defined in the
subscription config.
Resolves featureId to the required tier using
SubscriptionConfig.getRequiredTierForFeature, then applies the same
logic as subscriptionRedirect.
Throws a StateError if featureId is not found in the config.
Important: This package does not depend on go_router. You must add go_router as a dependency in your own project.
Parameters:
featureId: The feature identifier to look up in the config.redirectPath: The path to redirect to when access is denied.allowDuringTrial: Iftrue(default), trialing users are allowed through.redirectQueryParams: Optional query parameters to append toredirectPath.customRedirect: An optional function for full control over the redirect path.
Example:
GoRoute(
path: '/export',
redirect: subscriptionFeatureRedirect(
featureId: 'export_pdf',
redirectPath: '/upgrade',
),
)
See also:
- subscriptionRedirect, the tier-based equivalent.
- SubscriptionRouteGuard, for programmatic (non-GoRouter) navigation.
- SubscriptionConfig.features, the feature map used for lookups.
Implementation
String? Function(BuildContext context, dynamic state)
subscriptionFeatureRedirect({
required String featureId,
required String redirectPath,
bool allowDuringTrial = true,
Map<String, String>? redirectQueryParams,
String? Function(BuildContext context, Tier requiredTier, Tier currentTier)?
customRedirect,
}) {
return (BuildContext context, dynamic state) {
final scope = SubscriptionGuardScope.of(context);
final requiredTierId = scope.config.getRequiredTierForFeature(featureId);
if (requiredTierId == null) {
throw StateError(
"Feature '$featureId' not found in SubscriptionConfig.features. "
'Did you forget to add it? Available features: '
'${scope.config.features.keys.join(', ')}',
);
}
final hasAccess = scope.hasAccess(requiredTierId);
if (!hasAccess && allowDuringTrial && scope.isTrialing) {
return null;
}
if (hasAccess) {
return null;
}
// Blocked.
scope.reportBlocked(featureId: featureId, requiredTierId: requiredTierId);
final resolvedRequiredTier = scope.config.getTierById(requiredTierId);
if (customRedirect != null) {
return customRedirect(context, resolvedRequiredTier, scope.currentTier);
}
return _buildRedirectPath(redirectPath, redirectQueryParams);
};
}