1.2.0 • Published 2 years ago

firebase-firestore-facade v1.2.0

Weekly downloads
-
License
ISC
Repository
github
Last release
2 years ago

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.

For the latest version:

npm i firebase-firestore-facade

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>;
}

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> {
    ...
  }
}

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;
}

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

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

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;
}

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.

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;
}

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;
  }
}

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();
  }
}
1.2.0

2 years ago

1.1.0

2 years ago

1.0.1

3 years ago

1.0.0

3 years ago

0.3.3

3 years ago

0.3.0

3 years ago

0.1.0

3 years ago

0.2.0

3 years ago

0.1.1

3 years ago

0.0.9

3 years ago

0.0.8

3 years ago

0.0.7

3 years ago

0.0.6

3 years ago

0.0.5

3 years ago

0.0.4

3 years ago

0.0.3

3 years ago

0.0.2

3 years ago

0.0.1

3 years ago