Skip to content

Configuration

Fasq Riverpod uses a set of specialized providers to configure the global QueryClient. This approach makes configuration declarative and easily overridable at any level of your app’s widget tree.

The fasqClientProvider (which all other providers use) is built by listening to several configuration providers. To customize your client, you should override these providers in your ProviderScope.

1. Cache Configuration (fasqCacheConfigProvider)

Section titled “1. Cache Configuration (fasqCacheConfigProvider)”

Use this to set global defaults for staleTime, cacheTime, and other cache-specific behaviors.

import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:fasq_riverpod/fasq_riverpod.dart';
void main() {
runApp(
ProviderScope(
overrides: [
fasqCacheConfigProvider.overrideWithValue(
const CacheConfig(
defaultStaleTime: Duration(minutes: 5),
defaultCacheTime: Duration(minutes: 15),
),
),
],
child: const MyApp(),
),
);
}

2. Persistence Options (fasqPersistenceOptionsProvider)

Section titled “2. Persistence Options (fasqPersistenceOptionsProvider)”

To enable the offline cache, you must provide a storage directory. You can also specify encryption keys or custom serialization logic.

import 'package:path_provider/path_provider.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
final dir = await getApplicationDocumentsDirectory();
runApp(
ProviderScope(
overrides: [
fasqPersistenceOptionsProvider.overrideWithValue(
PersistenceOptions(
directory: dir.path,
),
),
],
child: const MyApp(),
),
);
}

3. Observers & Logging (fasqObserversProvider)

Section titled “3. Observers & Logging (fasqObserversProvider)”

Observers allow you to monitor lifecycle events (fetching, success, error) across all queries in your app. The FasqLogger is provided out of the box for development.

ProviderScope(
overrides: [
fasqObserversProvider.overrideWithValue([
FasqLogger(), // Prints query events to the console
]),
],
child: const MyApp(),
)

Accessing the raw QueryClient (fasqClientProvider)

Section titled “Accessing the raw QueryClient (fasqClientProvider)”

While most operations are handled by the high-level providers, you can access the underlying QueryClient instance whenever you need lower-level control.

  • To manually fetch data without using a provider.
  • To manipulate cache data directly using setQueryData or getQueryData.
  • To perform complex invalidation patterns (e.g., invalidating by tag or fuzzy matching).
  • To listen to global cache events.

You can watch the client just like any other provider:

class MyWidget extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final client = ref.watch(fasqClientProvider);
return ElevatedButton(
onPressed: () {
// Clear the entire cache
client.clear();
},
child: Text('Clear All Cache'),
);
}
}

The client is often used inside other providers to perform side effects:

final authControllerProvider = Provider((ref) {
return AuthController(
onLogout: () {
// Access the client to wipe all secure data on logout
ref.read(fasqClientProvider).clear();
},
);
});
ProviderPurpose
fasqCacheConfigProviderGlobal stale and cache time defaults.
fasqPersistenceOptionsProviderConfiguration for disk persistence (SQLite/Hive).
fasqObserversProviderList of observers for logging or analytics.
fasqErrorReportersProviderIntegration with services like Sentry or Firebase Crashlytics.
fasqSecurityPluginProviderOptions for hardware-backed encryption or secure storage.
fasqCircuitBreakerRegistryProviderConfiguration for global circuit breaker patterns.

By using Riverpod providers for configuration:

  1. Managed Singleton: The QueryClient is created once and automatically disposed when the app is destroyed.
  2. Context-Aware: You can theoretically have different QueryClient configurations for different branches of your widget tree by nesting ProviderScope.
  3. Reactive: While most configurations are static, you could dynamically update your client configuration based on app state (e.g., toggling debug logs).