class SimpleFirebase { constructor() { this.FBS = firebase this.DB = firebase.firestore() this.AUTH = firebase.auth() this.STORE = firebase.storage() this.query_operators = ["<", "<=", "==", ">", ">=", "!=", "array-contains", "array-contains-any", "in", "not-in"] // Ugly, bind is required in order to call methods in the class (without this I get weird errors) this.add = this.add.bind(this) this.update = this.update.bind(this) this.get = this.get.bind(this) this.find = this.find.bind(this) this.delete = this.delete.bind(this) this.facebookLogin = this.facebookLogin.bind(this) this.googleLogin = this.googleLogin.bind(this) this.logoutUser = this.logoutUser.bind(this) this.deleteUser = this.deleteUser.bind(this) this.registerUser = this.registerUser.bind(this) this.uploadFile = this.uploadFile.bind(this) this.deleteFile = this.deleteFile.bind(this) } // DB async add(collectionName, objData){ if ("_id" in objData) { await this.DB.collection(collectionName).doc(objData._id).set(objData) return objData._id } else { let docRef = await this.DB.collection(collectionName).add(objData) await this.DB.collection(collectionName).doc(docRef.id).update({"_id": docRef.id}) return docRef.id } } async update(collectionName, objDataOld, objDataNew=undefined){ if ("_id" in objDataOld) { await this.DB.collection(collectionName).doc(objDataOld._id).update(objDataOld) return objDataOld._id } else { if (objDataNew === undefined) throw("No '_id' or new object specified!") let docList = await this.find(collectionName, objDataOld) let updated_ids = [] for (let doc of docList) { await this.DB.collection(collectionName).doc(doc._id).update(objDataNew) updated_ids.push(doc._id) } return updated_ids } } async get(collectionName, objId){ let snap = await this.DB.collection(collectionName).doc(objId).get() return snap.data() } async find(collectionName, objDataOrId, comparison="=="){ // TODO add pagination using generators if (typeof(objDataOrId) === typeof('string')) { return this.get(collectionName, objDataOrId) } if (!this.query_operators.includes(comparison)) { throw("Only these query operators are accepted: " + this.query_operators.join(", ")) } let ref = this.DB.collection(collectionName) let objData = objDataOrId for (const key in objData) { ref = ref.where(key, comparison, objData[key]) } let snap = await ref.get() let data_list = [] if (!snap.empty){ snap.forEach(res => { data_list.push({"_id":res.id, ...res.data()}) }) } return data_list } async delete(collectionName, objDataOrId){ if (typeof(objDataOrId) === typeof('string')) { let docID = objDataOrId await this.DB.collection(collectionName).doc(docID).delete() return docID } let objData = objDataOrId let docList = await this.find(collectionName, objData) let deleted_ids = [] for (let doc of docList) { await this.DB.collection(collectionName).doc(doc._id).delete() deleted_ids.push(doc._id) } return deleted_ids } // AUTH async registerUser(user) { let user_data = await this.get("users", user.uid) // Adds to users collection name and email if uid not found in users collection if (user_data === undefined) { await this.add("users", { _id: user.uid, name: user.displayName, email: user.email }) } return user.uid } async facebookLogin() { let provider = new firebase.auth.FacebookAuthProvider() const res = await firebase.auth().signInWithPopup(provider) return this.registerUser(res.user) } async googleLogin() { let provider = new firebase.auth.GoogleAuthProvider() const res = await firebase.auth().signInWithPopup(provider) return this.registerUser(res.user) } logoutUser() { return firebase.auth().signOut() } async deleteUser() { await this.delete("users", firebase.auth().currentUser.uid) return firebase.auth().currentUser.delete() } // FILES async uploadFile(fileObj, folder=undefined, fileName=undefined, generateID=true){ let prefix = "" if (generateID) { prefix = Math.random().toString(36).substring(2,15) + "_" } let path = `/${folder ? folder : "files"}/${fileName ? prefix + fileName: prefix + fileObj.name}` if (Number(fileObj.size) > 0) { let snapshot = await firebase.storage().ref().child(path).put(fileObj) return {path, downloadURL: await snapshot.ref.getDownloadURL()} } } async deleteFile(path){ return firebase.storage().ref().child(path).delete() } } if (firebase) { f = new SimpleFirebase() }