UNPKG

@fanam-pkg/core-utils

Version:

Core Functions are managed here for quick web development

408 lines (357 loc) 13.3 kB
import {useRef} from "react" import firebase from "firebase/compat/app" import "firebase/compat/auth" import "firebase/compat/firestore" import "firebase/compat/messaging" import {useCommon} from "../hooks" export type DocumentData = firebase.firestore.DocumentData export type DocumentSnapshot = firebase.firestore.DocumentSnapshot export type QueryDocumentSnapshot = firebase.firestore.QueryDocumentSnapshot export type QuerySnapshot = firebase.firestore.QuerySnapshot export type CollectionRef = firebase.firestore.CollectionReference export type DocumentRef = firebase.firestore.DocumentReference export type SetOptions = firebase.firestore.SetOptions export const useFirebase = ( onVerified?: (user: firebase.auth.UserCredential, authToken: string) => void, onFailed?: (data?: string) => void ) => { const {isDocumentReady} = useCommon() const recaptchaVerifier = useRef<firebase.auth.RecaptchaVerifier>() const confirmationResult = useRef<firebase.auth.ConfirmationResult>() const firebaseConfig = { apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY, authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN, projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID, storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET, messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID, appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID, measurementId: process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID, } const app = !firebase.apps.length ? firebase.initializeApp(firebaseConfig) : firebase.app() const auth = firebase.auth(app) const fireStore = firebase.firestore(app) let messaging: firebase.messaging.Messaging | null = null if (isDocumentReady()) messaging = firebase.messaging(app) const googleProvider = new firebase.auth.GoogleAuthProvider() const facebookProvider = new firebase.auth.FacebookAuthProvider() facebookProvider.addScope("email") /* Phone number Authentication */ const onSignInSuccess = async (response: firebase.auth.UserCredential) => { recaptchaVerifier.current?.clear() const authToken = await response.user?.getIdToken() if (onVerified) onVerified(response, authToken || "") } /* Send OTP to the phone number */ const sendOtp = ( countryCode: string, mobile: string, onOtpSent: () => void, onFailed?: () => void ) => { // Only initialize if it hasn't been initialized if (!recaptchaVerifier.current) { recaptchaVerifier.current = new firebase.auth.RecaptchaVerifier("auth-proceed-button", { size: "invisible", }) } // Make sure the reCAPTCHA is cleared (optional) // recaptchaVerifier.current.clear() // Only if you want to reset manually auth .signInWithPhoneNumber(countryCode + mobile, recaptchaVerifier.current) .then(response => { confirmationResult.current = response console.log("OTP Sent Successfully >>>>>>>>>>>>>>") onOtpSent() }) .catch(reason => { console.error("FIREBASE ERROR While sending OTP >>>>>>>>>>>>>>", reason) if (onFailed) onFailed() }) } /* Verify the sent OTP to the phone number */ const verifyOTP = (otp: string) => { if (confirmationResult.current) { confirmationResult.current .confirm(otp) .then(onSignInSuccess) .catch(reason => { console.error("FIREBASE ERROR OTP Verification error >>>>>>>>>>>>>>", reason) if (onFailed) onFailed("Invalid OTP Please try again") }) } } const getAuthToken = async (): Promise<string> => (await auth?.currentUser?.getIdToken()) || "" /* Google Provider Sign-in */ const googleSignInPopup = async () => { try { const response = await auth.signInWithPopup(googleProvider) if (response) onSignInSuccess(response) } catch (error) { console.error("Firebase Google AuthToken googleSignInDesktop >>>>>>>>>>>", error) if (onFailed) onFailed() } } const googleSignInRedirect = () => { //To sign in by redirecting to the sign-in page auth.signInWithRedirect(googleProvider) } const googleSignInCallback = async () => { try { const response = await auth.getRedirectResult() if (response) onSignInSuccess(response) } catch (error) { console.error("Caught error in googleSignInRedirectResult >>>>>>>>>>>", error) if (onFailed) onFailed() } } /* Verifying user email and password */ const verifyEmailPassword = (email: string, password: string) => { auth .signInWithEmailAndPassword(email, password) .then(onSignInSuccess) .catch(reason => { console.error("FIREBASE ERROR WHILE SIGNING IN >>>>>>>>>>>>>>", reason) if (onFailed) onFailed(reason?.message) }) } /* new user Sign up with email password */ const signupEmailPassword = (email: string, password: string) => { auth .createUserWithEmailAndPassword(email, password) .then(onSignInSuccess) .catch(reason => { console.error("FIREBASE CREATING EMAIL LOGIN >>>>>>>>>>>>>>", reason) if (onFailed) onFailed(reason?.message) }) } /* sending login link to the user email */ const sendEmailVerificationLink = async ( email: string, redirectUrl: string, onSuccess: () => void, onFailure: (value: string) => void ) => { try { await auth.sendSignInLinkToEmail(email, { url: `${redirectUrl}?email=${email}`, handleCodeInApp: true, }) onSuccess() } catch (error) { onFailure((error as Record<string, string>)["message"]) } } /*signing in using email link verification*/ const verifyEmailLogin = (email: string, url: string) => { auth .signInWithEmailLink(email, url) .then(onSignInSuccess) .catch(error => { if (onFailed) onFailed(error?.message) }) } /*email link verification*/ const isEmailSigninLink = (url: string) => auth.isSignInWithEmailLink(url) /*facebook login method*/ const facebookSignInPopup = async () => { try { const response = await auth.signInWithPopup(facebookProvider) if (response) onSignInSuccess(response) } catch (error) { console.error("Firebase Facebook AuthToken facebookSignInDesktop >>>>>>>>>>>", error) if (onFailed) onFailed() } } const facebookSignInRedirect = () => { //To sign in by redirecting to the sign-in page auth.signInWithRedirect(facebookProvider) } /*facebook sign in call back method*/ const facebookSignInCallback = async () => { try { const response = await auth.getRedirectResult() if (response) onSignInSuccess(response) } catch (error) { console.error("Caught error in facebookSignInRedirectResult >>>>>>>>>>>", error) if (onFailed) onFailed() } } const getSWRegistration = async () => { let registration: ServiceWorkerRegistration | undefined = undefined try { if ("serviceWorker" in navigator) { const registrations = await navigator.serviceWorker.getRegistrations() registration = registrations.find( worker => worker.active && worker.active.scriptURL && worker.active.scriptURL.includes("service-worker.js") ) } } catch (error) { console.error(">>>>>>>>>>>>>> Caught Error while registering service-worker.js: ", error) } return registration } const getFCMToken = async () => { let fcmToken: null | string = null try { const registration = await getSWRegistration() if (messaging && registration) { fcmToken = await messaging.getToken({ serviceWorkerRegistration: registration, vapidKey: process.env.NEXT_PUBLIC_FIREBASE_VAPID_KEY, }) console.log(">>>>>>>>>>>>>>>: FCM Token Fetched successfully") } } catch (error) { console.error("Caught error in FCM TOKEN >>>>>>>>>>>: ", error) } return fcmToken } const getCollectionRef = (collections: string[]) => { const noOfCollection = collections.length let collectionRef: CollectionRef | DocumentRef = fireStore.collection(collections[0]) switch (noOfCollection) { case 2: collectionRef = collectionRef.doc(collections[1]) break case 3: collectionRef = collectionRef.doc(collections[1]).collection(collections[2]) break case 4: collectionRef = collectionRef.doc(collections[1]).collection(collections[2]).doc(collections[3]) break case 5: collectionRef = collectionRef .doc(collections[1]) .collection(collections[2]) .doc(collections[3]) .collection(collections[4]) break case 6: collectionRef = collectionRef .doc(collections[1]) .collection(collections[2]) .doc(collections[3]) .collection(collections[4]) .doc(collections[5]) break case 7: collectionRef = collectionRef .doc(collections[1]) .collection(collections[2]) .doc(collections[3]) .collection(collections[4]) .doc(collections[5]) .collection(collections[6]) break case 8: collectionRef = collectionRef .doc(collections[1]) .collection(collections[2]) .doc(collections[3]) .collection(collections[4]) .doc(collections[5]) .collection(collections[6]) .doc(collections[7]) break case 9: collectionRef = collectionRef .doc(collections[1]) .collection(collections[2]) .doc(collections[3]) .collection(collections[4]) .doc(collections[5]) .collection(collections[6]) .doc(collections[7]) .collection(collections[8]) break default: break } return collectionRef } const addData = async <D>(collections: string[], data: D, options: SetOptions = {merge: true, mergeFields: []}) => { let response: D | null = null try { const {mergeFields, merge} = options const option = mergeFields?.length ? {mergeFields} : {merge} if (collections.length % 2 === 0) await (getCollectionRef(collections) as DocumentRef).set(data as Partial<DocumentData>, option) else await (getCollectionRef(collections) as CollectionRef).add(data as Partial<DocumentData>) response = data } catch (error) { console.error("ERROR While Adding data to firestore: >>>>>>>>>>>>>>>>", error) } return response } const updateData = async <D>(collections: string[], data: D) => { let response: D | null = null try { await (getCollectionRef(collections) as DocumentRef).update(data as Partial<DocumentData>) response = data } catch (error) { console.error("ERROR While Adding data to firestore: >>>>>>>>>>>>>>>>", error) } return response } const getCollection = async <R>(collections: string[] | string) => { let data: R[] = [] try { const response = await ( getCollectionRef(typeof collections === "string" ? [collections] : collections) as CollectionRef ).get() data = response.docs.map(item => item.data() as R) } catch (error) { console.error("ERROR While fetching firestore collections: >>>>>>>>>>>>>>>>", error) } return data } const getData = async <R>(collections: string[] | string) => { let data: R | null = null try { const response = await ( getCollectionRef(typeof collections === "string" ? [collections] : collections) as DocumentRef ).get() data = response.data() as R } catch (error) { console.error("ERROR While fetching firestore collections: >>>>>>>>>>>>>>>>", error) } return data } const deleteData = async (collections: string[] | string) => { let isSuccess: boolean = false try { await (getCollectionRef(typeof collections === "string" ? [collections] : collections) as DocumentRef).delete() isSuccess = true } catch (error) { console.error("ERROR While fetching firestore collections: >>>>>>>>>>>>>>>>", error) } return isSuccess } const onSignOut = async () => await auth.signOut() return { verifyOTP, sendOtp, getAuthToken, onSignOut, messaging, fireStore, getData, updateData, getCollection, addData, deleteData, googleSignInPopup, googleSignInRedirect, googleSignInCallback, verifyEmailPassword, signupEmailPassword, sendEmailVerificationLink, verifyEmailLogin, isEmailSigninLink, facebookSignInPopup, facebookSignInRedirect, facebookSignInCallback, getFCMToken, firebaseConfig, } }