Firestore Entity

A Firestore Wrapper library for binding and mapping documents to dart classes. Enjoy !


  • Maps Firestore's documents to existing dart classes.
  • fills up id from document's id.
  • Resovles {userId} in path to currently signed-in Firebase Auth user's uid e.g profiles/{userId}.
  • Automatic off/on .data() stream subscription when path contains {userId} (see usage example below).


import 'package:firestore_entity/firestore_entity.dart';

FirestoreEntity class

Assuming we have Profile class model:

  class Profile {
    String id;
    int points;

    Profile({, this.points});
    factory Profile.fromJson(Map<String, dynamic> json) => Profile(
          id: json['id'] as String,
          points: json['points'] as int,
    Map<String, dynamic> toJson() => <String, dynamic>{
          'points': this.points,

We can create a reference to an existing document in Firestore and manipulate it using FirestoreEntity class:

    var profileEntity = FirestoreEntity<Profile>(
      (json) => Profile.fromJson(json),
      (item) => item.toJson(),

    // get document's id
    String profileId =;

    // get document's path
    String profilePath = profileEntity.path;

    // get document
    Profile profile = await profileEntity.get();

    // update document
    await profileEntity.update(profile);

    // update specific fields in a document
    await profileEntity.updateData({"points": 200});

    // set document
    await profileEntity.set(profile);

    // delete document
    await profileEntity.delete();

    // is document exists
    bool exists = await profileEntity.exists();

    // stream changes (triggerd once subscribed with latest value)
    StreamSubscription<Profile> subscription = {

    // latest stored offline value
    Profile profileOffline = profileEntity.value;

we can use .data() stream method of FirestoreEntity<T> in StreamBuilder like:

  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      body: Center(
        child: Column(
          children: <Widget>[
              builder: (context, AsyncSnapshot<Profile> snapshot) {
                return Text(
                    "my points: " + ?? "0");

FirestoreCollection class

Assuming we have Book class model:

  class Book {
    String id;
    String title;

    Book({, this.title});
    factory Book.fromJson(Map<String, dynamic> json) => Book(
          id: json['id'] as String,
          title: json['title'] as String,
    Map<String, dynamic> toJson() => <String, dynamic>{
          'title': this.title,

we can also initiate a collection reference using FirestoreCollection class:

    //collection: path can also have {userId} variable e.g. "users/{userId}/myBooks"
    var booksCol = FirestoreCollection<Book>(
      "books",// or "users/{userId}/myBooks"
      (json) => Book.fromJson(json),
      (item) => item.toJson(),
    ).where("points", isGreaterThan: 200);

    // get collection's path
    String booksPath = booksCol.path;

    // get all documents
    List<Book> books = await booksCol.get();

    // get all documents wrapped in FirestoreEntity class
    List<FirestoreEntity<Book>> booksEntities = await booksCol.getEntities();
    booksEntities[0].updateData({"new": true});

    // add new document then get it's id
    FirestoreEntity<Book> bookEntity =
        await booksCol.add(new Book(title: "book 1"));
    var book1_Id =; // new

    // stream changes (triggerd once subscribed with latest value) {

    // latest stored offline value
    List<Book> booksOffline = booksCol.value;