Created
April 21, 2025 07:05
-
-
Save callmephil/52e79c158002254762bee6acb0183da8 to your computer and use it in GitHub Desktop.
Base Firestore Service
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:cloud_firestore/cloud_firestore.dart'; | |
import 'package:flutter/foundation.dart'; | |
/// Base service class for handling CRUD operations with Firestore | |
abstract class BaseFirestoreService<T> { | |
/// Constructor | |
BaseFirestoreService(String collectionPath) { | |
_collection = _firestore.collection(collectionPath); | |
} | |
/// The Firestore instance | |
final FirebaseFirestore _firestore = FirebaseFirestore.instance; | |
/// The collection reference | |
late final CollectionReference _collection; | |
/// Convert a document snapshot to a model instance | |
T fromSnapshot(DocumentSnapshot snapshot); | |
/// Convert a model instance to a map for Firestore | |
Map<String, dynamic> toMap(T item); | |
/// Get the ID of an item | |
String? getId(T item); | |
/// Set the ID of an item | |
T setId(T item, String id); | |
/// Get all items from the collection | |
Future<List<T>> getAll() async { | |
final querySnapshot = await _collection.get(); | |
return querySnapshot.docs.map(fromSnapshot).toList(); | |
} | |
/// Get an item by its ID | |
Future<T?> getById(String id) async { | |
final docSnapshot = await _collection.doc(id).get(); | |
if (!docSnapshot.exists) { | |
return null; | |
} | |
return fromSnapshot(docSnapshot); | |
} | |
/// Add a new item | |
Future<T> add(T item) async { | |
final docRef = _collection.doc(); // Create a new doc ref to get the ID | |
final itemWithId = setId(item, docRef.id); | |
await docRef.set(toMap(itemWithId)); | |
return itemWithId; | |
} | |
// bulk add with id | |
Future<List<T>> bulkAdd(List<T> items) async { | |
final batch = _firestore.batch(); | |
final docRefs = <DocumentReference>[]; | |
final itemsWithId = <T>[]; | |
for (final item in items) { | |
final docRef = _collection.doc(); | |
final itemWithId = setId(item, docRef.id); | |
batch.set(docRef, toMap(itemWithId)); | |
docRefs.add(docRef); | |
itemsWithId.add(itemWithId); | |
} | |
await batch.commit(); | |
return itemsWithId; | |
} | |
/// Set an item with a specific ID | |
Future<T> set(String id, T item) async { | |
final itemWithId = setId(item, id); | |
await _collection.doc(id).set(toMap(itemWithId)); | |
return itemWithId; | |
} | |
/// Update an existing item | |
Future<T?> update(String id, T item) async { | |
await _collection.doc(id).update(toMap(setId(item, id))); | |
return getById(id); | |
} | |
/// Delete an item by its ID | |
Future<bool> delete(String id) async { | |
try { | |
await _collection.doc(id).delete(); | |
return true; | |
} on Exception catch (e, trace) { | |
// TODO: must handle excepetion properly | |
debugPrint([e, trace].toString()); | |
return false; | |
} | |
} | |
/// Get a stream of all items | |
Stream<List<T>> getAllStream() { | |
return _collection.snapshots().map( | |
(snapshot) => snapshot.docs.map(fromSnapshot).toList(), | |
); | |
} | |
/// Get a stream of a specific item | |
Stream<T?> getByIdStream(String id) { | |
return _collection | |
.doc(id) | |
.snapshots() | |
.map((snapshot) => snapshot.exists ? fromSnapshot(snapshot) : null); | |
} | |
/// Query items with a filter | |
Future<List<T>> query( | |
String field, { | |
Object? isEqualTo, | |
Object? isNotEqualTo, | |
Object? isLessThan, | |
Object? isLessThanOrEqualTo, | |
Object? isGreaterThan, | |
Object? isGreaterThanOrEqualTo, | |
Object? arrayContains, | |
List<Object>? arrayContainsAny, | |
List<Object>? whereIn, | |
List<Object>? whereNotIn, | |
bool? isNull, | |
}) async { | |
final query = _collection.where( | |
field, | |
isEqualTo: isEqualTo, | |
isNotEqualTo: isNotEqualTo, | |
isLessThan: isLessThan, | |
isLessThanOrEqualTo: isLessThanOrEqualTo, | |
isGreaterThan: isGreaterThan, | |
isGreaterThanOrEqualTo: isGreaterThanOrEqualTo, | |
arrayContains: arrayContains, | |
arrayContainsAny: arrayContainsAny, | |
whereIn: whereIn, | |
whereNotIn: whereNotIn, | |
isNull: isNull, | |
); | |
return (await query.get()).docs.map(fromSnapshot).toList(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment