subscriptionFeatureRedirect function

String? Function(BuildContext context, dynamic state) subscriptionFeatureRedirect({
  1. required String featureId,
  2. required String redirectPath,
  3. bool allowDuringTrial = true,
  4. Map<String, String>? redirectQueryParams,
  5. String? customRedirect(
    1. BuildContext context,
    2. Tier requiredTier,
    3. Tier currentTier
    )?,
})

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: If true (default), trialing users are allowed through.
  • redirectQueryParams: Optional query parameters to append to redirectPath.
  • customRedirect: An optional function for full control over the redirect path.

Example:

GoRoute(
  path: '/export',
  redirect: subscriptionFeatureRedirect(
    featureId: 'export_pdf',
    redirectPath: '/upgrade',
  ),
)

See also:

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);
  };
}