riverpod_repo 5.1.1 copy "riverpod_repo: ^5.1.1" to clipboard
riverpod_repo: ^5.1.1 copied to clipboard

Generate Riverpod FutureProvider, StreamProvider, and Provider declarations from repository interfaces using the repository pattern.

Repo Generator with Riverpod #

pub package

A build-time code generator that creates Riverpod providers from repository interfaces. Each query method on your repository becomes a FutureProvider, StreamProvider, or Provider — with optional .family and .autoDispose.

Mutations are never turned into providers (see Mutations vs queries).

Table of contents #

Installation #

Add to dev_dependencies (this is a code generator, not a runtime dependency):

dev_dependencies:
  riverpod_repo: ^5.1.1
  build_runner: ^2.15.0
  riverpod_annotation: ^4.0.2
  riverpod_generator: ^4.0.3

Your app still needs riverpod (or flutter_riverpod) at runtime.

The builder is applied automatically to packages that depend on riverpod_repo (auto_apply: dependents). To customize exclusions, add a build.yaml:

targets:
  $default:
    builders:
      riverpod_repo:
        enabled: true
        generate_for:
          exclude:
            - "**/*.repo.g.dart"

Run code generation:

dart run build_runner build

Quick start #

1. Define the repository #

// lib/data/book_repo.dart

import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:riverpod_repo/riverpod_repo.dart';

part 'book_repo.g.dart';

@Riverpod(keepAlive: true)
BookRepo bookRepo(Ref ref) => BookRepoImpl();

@riverpodRepo
abstract class BookRepo {
  Future<List<Book>> getBooks({String search = ''});
  Future<Book> getBook(String id);
  Future<void> deleteBook(String id); // mutation — no provider generated
}

Import annotations from either:

  • package:riverpod_repo/riverpod_repo.dart (recommended), or
  • package:riverpod_repo/annotations.dart

2. Implement the repository #

class BookRepoImpl implements BookRepo {
  @override
  Future<List<Book>> getBooks({String search = ''}) async { ... }

  @override
  Future<Book> getBook(String id) async { ... }

  @override
  Future<void> deleteBook(String id) async { ... }
}

3. Run the builder #

dart run build_runner build

This creates book_repo.repo.g.dart — a standalone library you import in widgets or other providers:

import 'book_repo.repo.g.dart';

Note (5.0.0+): Repository providers are built with the public Riverpod API (FutureProvider, StreamProvider, Provider). They are not processed by riverpod_generator. Only your hand-written @Riverpod function needs a part '*.g.dart'; directive.

Generated output #

For each query method, the generator emits a provider that delegates to your repository instance:

// book_repo.repo.g.dart (generated)

import 'package:riverpod/riverpod.dart';
import 'book_repo.dart';

export 'book_repo.dart';

final bookRepoGetBooksProvider =
    FutureProvider.autoDispose.family<List<Book>, ({String search})>((ref, arg) {
  return ref.watch(bookRepoProvider).getBooks(search: arg.search);
});

final bookRepoGetBookProvider =
    FutureProvider.autoDispose.family<Book, String>((ref, id) {
  return ref.watch(bookRepoProvider).getBook(id);
});

/// Invalidates every generated query provider for BookRepo.
void invalidateBookRepoProviders(Ref ref) {
  ref.invalidate(bookRepoGetBooksProvider);
  ref.invalidate(bookRepoGetBookProvider);
}

Provider kind is inferred from the return type:

Repository method return type Generated provider
Future<T> FutureProvider
Stream<T> StreamProvider
anything else Provider

Parameters map to .family:

Method signature Family argument
no parameters plain provider
one positional parameter that type directly, e.g. family<T, String>
named and/or multiple parameters Dart record, e.g. (search: 'dart')

Using providers in the UI #

import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'book_repo.repo.g.dart';

class BookList extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final books = ref.watch(
      bookRepoGetBooksProvider((search: '')),
    );

    return books.when(
      loading: () => const CircularProgressIndicator(),
      error: (err, _) => Text('Error: $err'),
      data: (list) => ListView(
        children: [for (final b in list) Text(b.title)],
      ),
    );
  }
}

Mutations vs queries #

Providers are generated only for reads. A method is skipped when any of these apply:

Rule Example
Returns Future<void> or Stream<void> Future<void> deleteBook(String id)
Annotated with @repoMutation or @ignoreRepo @repoMutation Future<User> archiveUser()
Name starts with a mutation prefix createOrder, updateProfile, deleteItem, setTheme, saveDraft, addComment, removeTag, putFile, postMessage

Force a query that looks like a mutation #

@repoQuery
Future<DeletedItemsReport> deleteReport({DateTime? since});

Or with an explicit constructor when you need parameters on the annotation:

@RepoQueryAnnotation()
Future<DeletedItemsReport> deleteReport({DateTime? since});

Refresh reads after a mutation #

Call the generated invalidation helper (name: invalidate + repo class name + Providers):

Future<void> onDeleteBook(WidgetRef ref, String id) async {
  await ref.read(bookRepoProvider).deleteBook(id);
  invalidateBookRepoProviders(ref);
}

Do not wrap mutations in FutureProvider — call repository methods directly via ref.read(bookRepoProvider).deleteBook(...).

Keep-alive vs auto-dispose #

By default, generated providers use .autoDispose (cache cleared when nothing listens).

Keep every query provider alive for the repository:

@RiverpodRepoAnnotation(keepAlive: true)
abstract class BookRepo { ... }

Override a single method back to auto-dispose:

@RiverpodRepoAnnotation(keepAlive: true)
abstract class BookRepo {
  @RepoQueryAnnotation(keepAlive: false)
  Future<List<Book>> searchBooks(String query);
}

Use @RepoQueryAnnotation(keepAlive: false) (not @repoQuery(keepAlive: false)) — Dart only allows const constructor invocations on annotations when parameters are passed.

Annotations reference #

Annotation Target Purpose
@riverpodRepo class Shorthand for @RiverpodRepoAnnotation() — enable generation
@RiverpodRepoAnnotation({keepAlive}) class Enable generation; default keepAlive for all queries
@repoQuery method Force provider generation (overrides mutation name heuristic)
@RepoQueryAnnotation({keepAlive}) method Force generation; optional per-method keepAlive
@repoMutation / @ignoreRepo method Skip provider generation

Provider naming rules #

  1. Repository class name drives generated provider names: BookRepo + getBooksbookRepoGetBooksProvider
  2. Your @Riverpod function must return that class and use camelCase of the class name: BookRepobookRepobookRepoProvider
  3. Import *.repo.g.dart for generated query providers; keep part '*.g.dart' only on the source file for your @Riverpod provider

Migration #

From 4.x → 5.0 #

  • Output is now a single *.repo.g.dart file (no *.repo.dart part file)
  • Remove part 'foo.repo.dart'; from source files
  • Import foo.repo.g.dart where you use generated providers
  • Parameterized methods now use .family (records for named/multi-arg methods)

From 5.0 → 5.1 #

  • Mutation methods no longer get providers — add @repoQuery if a read was skipped
  • Use invalidate{RepoName}Providers(ref) after writes
  • Package is pure Dart (no Flutter SDK required in pubspec.yaml)
  • Annotations are exported from package:riverpod_repo/riverpod_repo.dart

Example project #

See example/ for a full repository with:

  • class-level keepAlive
  • per-method @RepoQueryAnnotation(keepAlive: false)
  • a Future<void> mutation (deleteBook) with no generated provider
  • custom model imports (Student, Country, Hello)

Run generation from the repo root:

dart run build_runner build

License #

MIT — see LICENSE.

Support #

Questions: dilan@dilan.me

8
likes
160
points
343
downloads

Documentation

Documentation
API reference

Publisher

verified publisherdilexus.dev

Weekly Downloads

Generate Riverpod FutureProvider, StreamProvider, and Provider declarations from repository interfaces using the repository pattern.

Homepage
Repository (GitHub)
View/report issues

Topics

#riverpod #code-generation #repository-pattern #flutter #dart

License

MIT (license)

Dependencies

analyzer, build, recase, riverpod, riverpod_annotation, source_gen

More

Packages that depend on riverpod_repo