Skip to content

Instantly share code, notes, and snippets.

@timnew
Last active February 21, 2022 00:41
Show Gist options
  • Save timnew/1c555beab1a576561e85924dadda6619 to your computer and use it in GitHub Desktop.
Save timnew/1c555beab1a576561e85924dadda6619 to your computer and use it in GitHub Desktop.
Firestore Helper
class DocumentNotFoundException implements Exception {
final String path;
DocumentNotFoundException(this.path);
@override
String toString() =>
'DocumentNotFoundException\n Document $path does not exist.';
}
class FieldNotFound implements Exception {
final String path;
final String field;
FieldNotFound(this.path, this.field);
@override
String toString() {
return "FieldNotFound\n Field $path:$field does not exist.";
}
}
class FieldTypeException implements Exception {
final String path;
final String field;
final Type expectedType;
final Type actualType;
FieldTypeException(this.path, this.field, this.expectedType, this.actualType);
@override
String toString() {
return "FileTypeException\n Field $path:$field is expected to be $expectedType but got $actualType instead.";
}
}
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:logging/logging.dart';
import 'exceptions.dart';
final logger = Logger("Repository");
Never logAndThrow(Object error) {
logger.warning(error, error);
throw error;
}
extension ReferenceExtension on DocumentReference<Map<String, dynamic>> {
Future<DocumentSnapshot<Map<String, dynamic>>> ensuredGet() async {
logger.fine("Load document $path");
final snapshot = await get();
if (!snapshot.exists) {
logAndThrow(DocumentNotFoundException(path));
}
logger.fine("Document $path loaded");
return snapshot;
}
Future<T> ensuredGetField<T>(String field) async {
final snapshot = await ensuredGet();
return snapshot.ensuredGet<T>(field);
}
Future<DocumentSnapshot<Map<String, dynamic>>> ensureLoadReferenceField(
String field,
) async {
final snapshot = await ensuredGet();
return snapshot.ensureGetReference(field).ensuredGet();
}
}
extension SnapshotExtension on DocumentSnapshot<Map<String, dynamic>> {
T ensuredGet<T>(Object field) {
logger.fine("Get field ${reference.path}:$field");
late final dynamic value;
try {
value = get(field);
} on StateError {
logAndThrow(FieldNotFound(reference.path, field.toString()));
}
if (value is! T) {
logAndThrow(
FieldTypeException(
reference.path,
field.toString(),
T,
value.runtimeType,
),
);
}
return value;
}
List<T> ensuredGetList<T>(Object field) =>
ensuredGet<List<dynamic>>(field).cast<T>();
List<DocumentReference<Map<String, dynamic>>> ensuredGetReferenceListList(
Object field,
) =>
ensuredGetList(field);
DocumentReference<Map<String, dynamic>> ensureGetReference(Object field) =>
ensuredGet(field);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment