apphouse
Version:
Component library for React that uses observable state management and theme-able components.
177 lines (164 loc) • 4.76 kB
text/typescript
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)}`
};
}
};
}