Skip to content

brombaut/firebase-firestore-facade

Repository files navigation

F3 - Firebase Firestore Facade

CI Codecov npm

Facade package for the Firebase package (Official Docs). Simplifies the interface of the Firestore module to a CRUD app with minimal setup.

Installing

For the latest version:

npm i firebase-firestore-facade

Modules

F3Interfacer

Main interface that is parameterized with the class that will be used to represent the records in the Firestore database (must implement ILocalType).

interface F3Interfacer<LocalType> {
  init(): Promise<F3Interfacer<LocalType>>;
  get(): Promise<LocalType[]>;
  getById(id: string): Promise<LocalType>;
  put(t: ILocalType): Promise<LocalType>;
  post(t: IFirestoreType): Promise<LocalType>;
  delete(t: ILocalType): Promise<void>;
  closeConnection(): Promise<void>;
}

F3Wrapper

You can use this class directly, or create an additional wrapper class for your specific collection (see the bookshelf example below). Its constructor takes a Firebase configuration object which implements FirebaseConfigurer (see below), the string name of the collection you want to connect to, and a mapper function that takes an IFirestoreType and returns a LocalType.

class F3Wrapper<LocalType> implements F3Interfacer<LocalType> {
  private _config: FirebaseConfigurer;
  private _collectionName: string;
  private _mapper: (o: IFirestoreType) => LocalType;
  private _collection!: FirestoreCollection<LocalType>;
  constructor(config: FirebaseConfigurer, collection: string, mapper: (o: IFirestoreType) => LocalType) {
    this._config = config;
    this._collectionName = collectionName;
    this._mapper = mapper;
    return this;
  }

  async init(): Promise<F3Wrapper<LocalType>> {
    ...
    return this;
  }

  async get(): Promise<LocalType[]> {
    ...
  }
  async getById(id: string): Promise<LocalType> {
    ...
  }
  async put(t: ILocalType): Promise<LocalType> {
    ...
  }
  async post(t: IFirestoreType): Promise<LocalType> {
    ...
  }
  async delete(t: ILocalType): Promise<void> {
    ...
  }
  async closeConnection(): Promise<void> {
    ...
  }
}

IFirestoreType

A class should be created that acts as a data transfer object between the raw attributes of the records being stored in the Firestore database and the local object that you will use to represent the records on the frontend (see ILocalType below). This class should implement the IFirestoreType interface, which must have an id: string attribute.

export interface IFirestoreType {
  id: string;
}

ILocalType

Classes that implement the ILocalType interface must have an id: string attribute and a toFirestoreType(): IFirestoreType method.

interface ILocalType {
  id: string;
  toFirestoreType(): IFirestoreType;
}

FirebaseConfigurer

See the Firebase project configuration docs

interface FirebaseConfigurer {
  apiKey: string;
  authDomain: string;
  projectId: string;
  storageBucket: string;
  messagingSenderId: string;
  appId: string;
  measurementId: string;
  auth?: FirebaseAuthentication;
}

interface FirebaseAuthentication {
  email: string;
  password: string;
}

Recommended Usage

Example - Bookshelf

We will use the idea of a bookshelf to demonstrate how to use F3. Lets say that we have a books collection in our Firestore database, and each of these records only has a title attribute.

FirestoreBook

We create a FirestoreBook class that implements the IFirestoreType interface. This class has a title attribute, as well as the id attribute. Notice that, even though the records in the Firestore collection might not have an id attribute, they can be generated automatically by Firestore.

class FirestoreBook implements IFirestoreType {
  id: string;
  title: string;
}

Book

We create a Book class that implements the ILocalType interface. We have an id getter, and a method toFirestoreType that returns the object as a FirestoreBook, which implements the IFirestoreType interface.

class Book implements ILocalType {
  private _id: string;
  private _title: string;

  constructor(dto: FirestoreBook) {
    if (!dto.id) {
      throw new Error('DTO does not have an ID');
    }
    this._id = dto.id;
    this._title = dto.title;
  }

  toFirestoreType(): FirestoreBook {
    return {
      id: this._id,
      title: this._title,
    };
  }

  get id(): string {
    return this._id;
  }
  get title(): string {
    return this._title;
  }
}

F3Bookshelf

Finally, we create a class F3Bookshelf, which will act as our facade between the Firestore database and our frontend. This class implements the F3Interfacer interface parameterized with our Book type. We have an F3Wrapper attribute (again, parameterized with our Book type), a string of the name of our Firestore collection (in our case books), and a (o: IFirestoreType) => Book function, which is used to map our FirestoreBook objects to their associated Book objects.

We instantiate the F3Wrapper in the constructor, including the firebaseConfig object, which must implement the FirebaseConfigurer interface (see above).

class F3Bookshelf implements F3Interfacer<Book> {
  private _f3!: F3Wrapper<Book>;
  private _firebaseConfig: FirebaseConfigurer;
  private _collection = 'books_prod';
  private _mapper: (o: IFirestoreType) => Book = (o: IFirestoreType) => new Book(o as FirestoreBook);

  constructor(firebaseConfig: FirebaseConfigurer) {
    this._firebaseConfig = firebaseConfig;
  }
  async init(): Promise<F3Bookshelf> {
    this._f3 = await new F3Wrapper<Book>(this._firebaseConfig, this._collection, this._mapper).init();
    return this;
  }
  async get(): Promise<Book[]> {
    return await this._f3.get();
  }
  async getById(id: string): Promise<Book> {
    return await this._f3.getById(id);
  }
  async put(t: Book): Promise<Book> {
    return await this._f3.put(t);
  }
  async post(t: FirestoreBook): Promise<Book> {
    return await this._f3.post(t);
  }
  async delete(t: Book): Promise<void> {
    return await this._f3.delete(t);
  }
  async closeConnection(): Promise<void> {
    await this._f3.closeConnection();
  }
}

About

Facade for the Firebase Firestore package

Topics

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors