Skip to content
OttomanDeveloperPublic

About

TanStack Query for Dart & Flutter — automatic caching, stale-while-revalidate, background refetch, mutations, infinite queries, and devtools. No boilerplate.

Topics

Resources

Contributing

Stars

5 stars

Watchers

0 watching

Forks

Repository files navigation

tanquery

TanStack Query-inspired data fetching, caching, retries, mutations, and reactive state for Dart and Flutter.

Dart 3 Flutter License: MIT

Packages

Package Purpose
tanquery Pure-Dart query and mutation core. It provides QueryClient, QueryCache, QueryObserver, retries, hydration, storage, streamed queries, and cache utilities.
tanquery_flutter Flutter integration with DartQueryProvider, QueryBuilder, MutationBuilder, InfiniteQueryBuilder, and QueriesBuilder.
tanquery_devtools Optional runtime overlay for inspecting query and mutation state in a debug build.

All packages currently use version 0.8.0. The workspace requires Dart 3.5 or newer. The Flutter packages require Flutter 3.24 or newer and are verified against the stable Flutter channel by CI.

Core quick start

The core package has no Flutter dependency and can be used from a Dart server, command-line application, or any other Dart environment:

dependencies:
  tanquery: ^0.8.0
import 'package:tanquery/tanquery.dart';

Future<List<String>> fetchTodos() async {
  return ['Buy milk', 'Walk the dog'];
}

Future<void> main() async {
  final client = QueryClient();

  final todos = await client.fetchQuery<List<String>>(
    queryKey: QueryKey(['todos']),
    queryFn: fetchTodos,
    staleTime: const Duration(minutes: 5),
  );

  print(todos);
}

fetchQuery returns fresh cached data when available and fetches stale or missing data. Use prefetchQuery to warm the cache without propagating errors, ensureQueryData to return cached data while optionally revalidating it, and setQueryData for direct cache updates. Freshness accepts either a Duration or StaleTime.static_; dehydrated and stored snapshots preserve that policy.

Flutter quick start

Add the Flutter adapter:

dependencies:
  tanquery_flutter: ^0.8.0

Provide one client above the widgets that use tanquery:

import 'package:flutter/material.dart';
import 'package:tanquery_flutter/tanquery_flutter.dart';

void main() {
  final client = QueryClient();
  runApp(
    DartQueryProvider(
      client: client,
      child: const MaterialApp(home: TodosPage()),
    ),
  );
}

class TodosPage extends StatelessWidget {
  const TodosPage({super.key});

  @override
  Widget build(BuildContext context) {
    return QueryBuilder<List<String>>(
      queryKey: QueryKey(['todos']),
      queryFn: () async => ['Buy milk', 'Walk the dog'],
      builder: (context, state) {
        if (state.isLoading) {
          return const Center(child: CircularProgressIndicator());
        }
        if (state.isError) {
          return Center(child: Text('Error: ${state.error}'));
        }
        return ListView(
          children: [
            for (final todo in state.data ?? <String>[]) ListTile(title: Text(todo)),
          ],
        );
      },
    );
  }
}

DartQueryProvider mounts the client, forwards Flutter app lifecycle changes to the focus manager, and unmounts the client when it is disposed. QueryBuilder manages a QueryObserver and exposes the observer’s QueryObserverResult to the builder.

Widget surface

Widget Use it when Main inputs
QueryBuilder<T> One reactive query queryKey, queryFn, builder, staleTime, enabled, meta, retry and placeholder options

| MutationBuilder<TData, TVariables> | A create, update, or delete operation | mutationFn, mutation callbacks, and a builder receiving mutate and mutateAsync | | InfiniteQueryBuilder<TPage, TParam> | Page-based or cursor-based lists | queryFn, initialPageParam, page callbacks, separate page loading flags, and page errors |

| QueriesBuilder | Several independent queries | A list of QueryConfig values and an ordered result list |

For complete constructor signatures and examples, see the tanquery_flutter README.

Devtools

Add the optional overlay in debug builds:

dependencies:
  tanquery_devtools: ^0.8.0
import 'package:flutter/foundation.dart';
import 'package:tanquery_devtools/tanquery_devtools.dart';

DartQueryProvider(
  client: client,
  child: DartQueryDevtools(
    enabled: kDebugMode,
    child: const MaterialApp(home: TodosPage()),
  ),
)

The overlay lists cached queries and mutations, supports key and status filtering, and provides query detail actions for invalidation, refetching, resetting, and removal. Fresh/stale status uses each query’s configured staleTime; query details also show the freshness policy and remaining fresh time. A header refresh button refetches active queries, and optional pollInterval enables periodic active-query refreshes. See the tanquery_devtools README for the complete UI description.

Examples and verification

The pure-Dart example is executable:

dart run packages/tanquery/example/tanquery_example.dart

The Flutter and devtools examples are package entrypoint examples rather than standalone Flutter applications with their own pubspec.yaml. They are compile-checked through the workspace analyzer:

flutter analyze packages/tanquery_flutter/example/tanquery_flutter_example.dart
flutter analyze packages/tanquery_devtools/example/tanquery_devtools_example.dart

Run the complete verification suite from the repository root:

dart format --output=none --set-exit-if-changed packages
dart analyze .
dart test packages/tanquery
flutter test packages/tanquery_flutter
flutter test packages/tanquery_devtools

The repository’s CI workflow runs the same formatting, analysis, and test checks against the current stable Flutter channel.

Architecture

The workspace is intentionally layered. tanquery contains the framework-independent cache, query, mutation, retry, hydration, persistence, and streaming logic. tanquery_flutter adapts QueryObserver and MutationObserver to Flutter widget lifecycles. tanquery_devtools consumes the public cache APIs to render an optional debugging overlay. The core package does not import Flutter.

Contributing

Read CONTRIBUTING.md before submitting changes. New behavior should include a focused test, public API changes should update the relevant package README and changelog, and generated .dart_tool, build, and coverage artifacts should not be committed.

License

MIT

About

TanStack Query for Dart & Flutter — automatic caching, stale-while-revalidate, background refetch, mutations, infinite queries, and devtools. No boilerplate.

Topics

Resources

Contributing

Stars

5 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages