firestore_wrapper 1.0.3
firestore_wrapper: ^1.0.3 copied to clipboard
A type-safe wrapper for Cloud Firestore operations in Flutter, providing a clean and strongly-typed interface.
Firestore Wrapper #
A type-safe wrapper for Cloud Firestore operations in Flutter, providing a clean and strongly-typed interface for working with Firestore data.
Features #
- 🔒 Type-safe operations - Work with your data models safely
- 📦 Simplified batch operations - Handle multiple writes atomically
- 🔄 Transaction helpers - Perform atomic read-write operations
- 🔍 Query builder - Build complex queries with pagination
- ⚡ Real-time updates - Stream data changes in real-time
- 📝 Clean API - Intuitive interface for Firestore operations
Installation #
Add this to your package's pubspec.yaml
file:
dependencies:
firestore_wrapper: ^1.0.0
copied to clipboard
Then run:
flutter pub get
copied to clipboard
Usage #
Define Your Model #
class User {
final String id;
final String name;
final int points;
User({
required this.id,
required this.name,
required this.points,
});
static User fromJson(Map<String, dynamic> json, String id) {
return User(
id: id,
name: json['name'] as String,
points: json['points'] as int? ?? 0,
);
}
Map<String, dynamic> toJson() => {
'name': name,
'points': points,
};
}
copied to clipboard
Create a Typed Collection #
final usersCollection = Fb.collection<User>(
'users',
User.fromJson,
);
copied to clipboard
Basic Operations #
// Create or update a document
final userDoc = usersCollection.doc('123');
await userDoc.set({
'name': 'John Doe',
'points': 100,
});
// Get a document
final user = await userDoc.get();
if (user != null) {
print('User ${user.name} has ${user.points} points');
}
// Update specific fields
await userDoc.update({
'points': 200,
});
// Delete a document
await userDoc.delete();
copied to clipboard
Queries #
// Build and execute a query
final activeUsers = await usersCollection
.query()
.where('status', isEqualTo: 'active')
.where('points', isGreaterThan: 100)
.orderBy('points', descending: true)
.limit(10)
.get();
// Query with pagination
final result = await usersCollection
.query()
.orderBy('createdAt')
.limit(20)
.getWithPagination();
final users = result.data;
final lastDoc = result.lastDocument;
copied to clipboard
Real-time Updates #
// Listen to a single document
userDoc.stream().listen((user) {
if (user != null) {
print('User updated: ${user.name}');
}
});
// Listen to query results
usersCollection
.query()
.where('status', isEqualTo: 'online')
.stream()
.listen((users) {
print('${users.length} users are online');
});
copied to clipboard
Batch Operations #
final batch = Fb.batch();
// Queue multiple operations
batch.set('users/123', {
'status': 'active',
'lastSeen': FieldValue.serverTimestamp(),
});
batch.update('stats/daily', {
'activeUsers': FieldValue.increment(1),
});
batch.delete('users/456');
// Commit all operations atomically
await batch.commit();
copied to clipboard
Transactions #
await Fb.runTransaction((transaction) async {
// Read data
final senderData = await transaction.get('users/sender123');
if (senderData == null) throw Exception('Sender not found');
final senderPoints = senderData['points'] as int? ?? 0;
final receiverData = await transaction.get('users/receiver456');
if (receiverData == null) throw Exception('Receiver not found');
final receiverPoints = receiverData['points'] as int? ?? 0;
// Perform updates atomically
transaction.update('users/sender123', {
'points': senderPoints - 100,
});
transaction.update('users/receiver456', {
'points': receiverPoints + 100,
});
return true;
});
copied to clipboard
Additional Features #
Subcollections #
// Get a reference to a user's posts
final userPostsCollection = userDoc.collection<Post>(
'posts',
Post.fromJson,
);
// Add a post
final postId = await userPostsCollection.add({
'title': 'Hello World',
'content': 'My first post!',
'createdAt': FieldValue.serverTimestamp(),
});
copied to clipboard
Complex Queries #
final query = usersCollection
.query()
.where('tags', arrayContains: 'premium')
.where('lastSeen', isGreaterThan: DateTime.now().subtract(Duration(days: 7)))
.orderBy('lastSeen', descending: true)
.limit(50);
final premiumActiveUsers = await query.get();
copied to clipboard
Error Handling #
The package propagates Firestore errors as-is, allowing you to handle them appropriately:
try {
await userDoc.update({'points': 100});
} catch (e) {
if (e is FirebaseException) {
// Handle specific Firebase errors
print('Firebase error: ${e.code}');
} else {
// Handle other errors
print('Error: $e');
}
}
copied to clipboard
Contributing #
Contributions are welcome! Please feel free to submit a Pull Request.
License #
This project is licensed under the MIT License - see the LICENSE file for details.