UNPKG

apphouse

Version:

Component library for React that uses observable state management and theme-able components.

177 lines (164 loc) 4.76 kB
import { makeAutoObservable } from 'mobx'; import { updateDoc, collection, doc, getDoc, getDocs, getFirestore, setDoc, Firestore } from 'firebase/firestore'; import { getErrorMessage } from '../utils/Error'; import { User } from '../authentication/User'; import { replaceUndefinedValuesWithNull } from '..'; import { Feedback } from './Feedback'; /** * ApphouseFirestore * A wrapper around firebase firestore to fetch, set, update and delete data from firestore * It assumes that initializeApp(firebaseConfig) has already been called */ export class ApphouseFirestore<T extends string> { db?: Firestore; user?: User; feedback?: Feedback; /** * If true, then no error message will be shown as an alert * @default true */ silentError: boolean; constructor(user: User, feedback?: Feedback) { this.user = user; this.db = getFirestore(); this.feedback = feedback; this.silentError = true; makeAutoObservable(this); } setDb(db: Firestore) { this.db = db; } /** * Set silent error to true to not show error message as an alert * @param silentError if true, then no error message will be shown as an alert */ setSilentError(silentError: boolean) { this.silentError = silentError; } fetch = async ( collectionName: string, docName?: string, orderByField = 'updatedAt' ) => { if (this.db === undefined) { return undefined; } console.log('fetch', collectionName, docName, orderByField); if (docName) { const docRef = doc(this.db, collectionName, docName); const docSnap = await getDoc(docRef); if (docSnap.exists()) { return docSnap.data(); } else { // doc.data() will be undefined in this case console.log('No such document!'); if (!this.silentError) { this.feedback?.setFeedback({ message: `No such document! ${collectionName} ${docName}`, variant: 'error' }); } return undefined; } } const c = collection(this.db, collectionName); return await getDocs(c); }; setWithoutCredentials = (collectionName: T, dcmt: string, data: object) => { if (this.db === undefined) { return undefined; } try { console.log('db set', { collection, doc, data }); const docRef = doc(this.db, collectionName, dcmt); return setDoc(docRef, replaceUndefinedValuesWithNull(data)); } catch (error) { if (!this.silentError) { this.feedback?.setFeedback({ message: `${collection} ${doc} ${JSON.stringify(error)}`, variant: 'error' }); } return { error: `${collection} ${doc} ${getErrorMessage(error)}` }; } }; set = (collectionName: T, dcmt: string, data: object) => { const user = this.user; if (!user) { return undefined; } if (this.db === undefined) { return undefined; } try { console.log('db set', { collection, doc, data }); const sanitizedData = replaceUndefinedValuesWithNull(data); console.log({ sanitizedData: sanitizedData }); const docRef = doc(this.db, collectionName, dcmt); this.feedback?.setFeedback({ message: `Updates done successfully`, variant: 'success' }); return setDoc(docRef, { ...sanitizedData, createdBy: user.email, ownerUid: user.uid, lastUpdatedBy: user.email, updatedAt: new Date().getTime() }); } catch (error) { if (!this.silentError) { this.feedback?.setFeedback({ message: `${collection} ${doc} ${JSON.stringify(error)}`, variant: 'error' }); } return { error: `${collection} ${doc} ${getErrorMessage(error)}` }; } }; update = (collectionName: T, dcmt: string, data: any) => { const user = this.user; if (!user) { return undefined; } if (this.db === undefined) { return undefined; } try { console.log('db update', { collection, doc, data }); const docRef = doc(this.db, collectionName, dcmt); this.feedback?.setFeedback({ message: `Updates done successfully`, variant: 'success' }); return updateDoc(docRef, { ...replaceUndefinedValuesWithNull(data), lastUpdatedBy: user?.email, updatedAt: data?.updatedAt || new Date().getTime() }); } catch (error) { if (!this.silentError) { this.feedback?.setFeedback({ message: `${collection} ${doc} ${JSON.stringify(error)}`, variant: 'error' }); } return { error: `${collection} ${doc} ${getErrorMessage(error)}` }; } }; }