API Reference

QoraClientConfig

Global configuration for QoraClient. Applied as the baseline for every query. Per-query QoraOptions are merged on top.

Overview

QoraClientConfig is passed to the QoraClient constructor and sets defaults for every query in the client's lifetime. Individual queries can override any field via QoraOptions.

lib/core/qora.dart
final client = QoraClient(
  config: QoraClientConfig(
    defaultOptions: QoraOptions(
      staleTime: Duration(minutes: 5),
      gcTime: Duration(minutes: 10),
      retryCount: 3,
    ),
    debugMode: kDebugMode,
    maxCacheSize: 200,
    refetchOnMount: true,
    errorMapper: (error, stack) => QoraException(
      '$error',
      originalError: error,
      stackTrace: stack,
    ),
  ),
);

Constructor

const QoraClientConfig({
  QoraOptions defaultOptions = const QoraOptions(),
  QoraException Function(Object error, StackTrace? stackTrace)? errorMapper,
  bool debugMode = false,
  int? maxCacheSize,
  void Function(List<dynamic> key)? onCacheEvict,
  void Function(Object error, StackTrace? stackTrace, List<dynamic> queryKey)? onBackgroundFetchError,
  bool refetchOnMount = true,
  ReconnectStrategy reconnectStrategy = const ReconnectStrategy(),
})

Fields

defaultOptions

final QoraOptions defaultOptions

Default: QoraOptions() (all defaults)

The baseline QoraOptions applied to every query. Per-query options are merged on top using QoraOptions.merge().

main.dart
defaultOptions: QoraOptions(
  staleTime: Duration(minutes: 5),
  gcTime: Duration(minutes: 10),
  retryCount: 3,
  retryDelay: Duration(seconds: 1),
),

→ See QoraOptions for all available fields.


errorMapper

final QoraException Function(Object error, StackTrace? stackTrace)? errorMapper

Default: null (errors are stored as-is)

Transforms raw errors into QoraException before they are stored in Failure states. Use this to normalise API-specific error types into a consistent shape across your app:

main.dart
errorMapper: (error, stackTrace) {
  if (error is DioException) {
    return QoraException(
      error.message ?? 'Network error',
      originalError: error,
      stackTrace: stackTrace,
    );
  }
  return QoraException('$error', originalError: error, stackTrace: stackTrace);
},

When set, all Failure.error values will be QoraException instances, giving you a single type to check in your error handlers.


debugMode

final bool debugMode

Default: false

Enables verbose print logging to the console. Logs:

  • Cache hits (fresh and stale)
  • Cache misses
  • Fetch attempts and retry delays
  • Deduplication events
  • Lazy eviction and GC removals
  • setQueryData and invalidate calls
  • Client disposal
main.dart
// Enable only in debug builds
debugMode: kDebugMode,

maxCacheSize

final int? maxCacheSize

Default: null (unbounded)

Maximum number of query entries in the cache. When the limit is reached, the least-recently-used inactive entry is evicted to make room. Active entries (those with watchQuery subscribers) are never forcibly evicted.

main.dart
maxCacheSize: 100,  // cap memory usage in list-heavy apps
A good starting value for most apps is 100–200. Monitor client.debugInfo()['total_queries'] to tune this for your usage patterns.

onCacheEvict

final void Function(List<dynamic> key)? onCacheEvict

Default: null

Callback invoked whenever a cache entry is evicted: via LRU pressure, GC timer, removeQuery, or clear. Receives the normalised key of the evicted entry.

main.dart
onCacheEvict: (key) {
  // Log or sync with persistent storage
  print('[Cache] evicted: $key');
  persistentStore.delete(key.toString());
},

onBackgroundFetchError

final void Function(Object error, StackTrace? stackTrace, List<dynamic> queryKey)? onBackgroundFetchError

Default: null

Callback invoked when a background fetch triggered by watchQuery fails. Background fetches run inside unawaited futures and without this callback the re-thrown error would crash the current async Zone.

The error has already been stored in the query's Failure state by the time this callback fires. Use this callback for logging, telemetry, or crash reporting, not for error recovery.

lib/core/qora.dart
onBackgroundFetchError: (error, stackTrace, key) {
  crashReporter.record(error, stackTrace);
},

refetchOnMount

final bool refetchOnMount

Default: true

Global default for whether watchQuery should trigger a fetch on the first subscription, even when cached data already exists.

  • true: always refetch on mount (recommended for most apps)
  • false: only fetch if no data exists; skip if any cached state is present

Can be overridden per query via QoraOptions.refetchOnMount.

main.dart
// Global: don't refetch if any data exists
refetchOnMount: false,

// Per-query override: always refetch this specific query
options: QoraOptions(refetchOnMount: true),

reconnectStrategy

final ReconnectStrategy reconnectStrategy

Default: const ReconnectStrategy() (5 concurrent, 100 ms jitter)

Controls how QoraClient replays paused queries when connectivity is restored. Without batching, all paused queries would fire simultaneously: the "thundering herd" problem. ReconnectStrategy introduces concurrency limits and random jitter between batches:

lib/core/qora.dart
reconnectStrategy: const ReconnectStrategy(
  maxConcurrent: 5,                      // Replay 5 queries at a time
  jitter: Duration(milliseconds: 200),   // Random wait between batches
),

Named constructors for common scenarios:

lib/core/qora.dart
// Default: balanced for most apps
const ReconnectStrategy()

// All queries replay at once (useful in tests)
ReconnectStrategy.instant()

// Conservative: 2 queries at a time, 500 ms jitter
ReconnectStrategy.conservative()
Named constructormaxConcurrentjitter
ReconnectStrategy()5100 ms
ReconnectStrategy.instant()9990 ms
ReconnectStrategy.conservative()2500 ms
For apps that have many background queries (dashboards, feeds), use ReconnectStrategy.conservative() or lower maxConcurrent to avoid spiking your backend after a connectivity gap.

lib/core/qora.dart
import 'package:flutter/foundation.dart';
import 'package:qora/qora.dart';

final qoraClient = QoraClient(
  config: QoraClientConfig(
    defaultOptions: const QoraOptions(
      staleTime: Duration(minutes: 5),
      gcTime: Duration(minutes: 10),
      retryCount: 3,
      retryDelay: Duration(seconds: 1),
      networkMode: NetworkMode.online,
    ),
    debugMode: kDebugMode,
    maxCacheSize: 200,
    refetchOnMount: true,
    onBackgroundFetchError: (error, stackTrace, key) =>
        crashReporter.record(error, stackTrace),
    reconnectStrategy: const ReconnectStrategy(
      maxConcurrent: 5,
      jitter: Duration(milliseconds: 100),
    ),
  ),
);

For Flutter apps, pass this client to QoraScope at the root of your widget tree so all widgets can access it via context.qora.

→ See Network Aware Guide for the full offline setup walkthrough.

Copyright © 2026