firewatch 0.1.3
firewatch: ^0.1.3 copied to clipboard
Lightweight Firestore repositories for Flutter: single-doc and collection repos that react to auth, stream updates, and support live-window pagination.
firewatch #
Lightweight Firestore repositories for Flutter.
- π Auth-reactive: attach/detach on UID changes via any
ValueListenable<String?>
- β‘ Instant UI: primes from local cache; then streams live updates
- πͺΆ Small surface area: single-doc + collection repos
- π Live window pagination: grow with
loadMore()
, reset viaresetPages()
- π§© No auth lock-in: bring your own auth listenable
Install #
dependencies:
firewatch:
Quick start #
Firewatch repositories are built to work seamlessly with watch_it
.
Hereβs the minimal flow: Model β Repository β UI.
1. Define your model #
Firestore-backed models must implement JsonModel
so Firewatch can inject the
document ID.
class UserProfile implements JsonModel {
@override
final String id;
final String name;
UserProfile({required this.id, required this.name});
factory UserProfile.fromJson(Map<String, dynamic> json) => UserProfile(
id: json['id'] as String,
name: json['name'] as String? ?? 'Anonymous',
);
@override
Map<String, dynamic> toJson() => {'name': name};
}
2. Create your repositories #
Repositories bind models to Firestore. Provide authUid
(a ValueListenable<String?>
) so Firewatch knows which document/collection to
read.
final authUid = ValueNotifier<String?>(null); // wire this to your auth layer
class UserProfileRepository extends FirestoreDocRepository<UserProfile> {
UserProfileRepository()
: super(
fromJson: UserProfile.fromJson,
docRefBuilder: (fs, uid) => fs.doc('users/$uid'),
authUid: authUid,
);
}
class FriendsRepository extends FirestoreCollectionRepository<UserProfile> {
FriendsRepository()
: super(
fromJson: UserProfile.fromJson,
colRefBuilder: (fs, uid) => fs.collection('users/$uid/friends'),
authUid: authUid,
);
}
3. Consume in the UI with watch_it
#
Because repositories are ValueNotifier
s, you can watch them directly in your widgets.
class ProfileCard extends StatelessWidget {
const ProfileCard({super.key});
@override
Widget build(BuildContext context) {
final profile = watchIt<UserProfileRepository>().value;
final friends = watchIt<FriendsRepository>().value;
if (profile == null) {
return const Center(child: CircularProgressIndicator());
}
return Card(
child: ListTile(
title: Text('User: ${profile.name}'),
subtitle: Text('Friends: ${friends.length}'),
),
);
}
}
π For a full runnable demo (with auth wiring and fake Firestore), check out the example/ app in this repo.
Bring your own Auth #
Firewatch accepts any ValueListenable<String?> that yields the current user UID. Update it on sign-in/out and the repos will re-attach.
authUid.value = 'abc123'; // sign in
authUid.value = null; // sign out
Commands API #
Both repos expose command_it
async
commands:
profileRepo.write(UserProfile(id: 'abc123', displayName: 'Marty'));
profileRepo.patch({'bio': 'Hello'});
friendsRepo.add({'displayName': 'Alice'});
friendsRepo.delete(id!);
UI State #
isLoading
: true while fetching/refreshinghasInitialized
(collections): first load completedhasMore
(collections): whetherloadMore()
can grow the windownotifierFor(docId)
: get a pre-soakedValueNotifier<T?>
for a specific item
Documentation #
License #
MIT - See LICENSE