/********************************** * This is a convenience utility to * abstract a bit of the Firestore * boilerplate and complexity dealing * with docs vs collections. *********************************/ import conf from './conf'; const TRANSACTION_LIMIT = 500; import * as admin from "firebase-admin"; import {DocumentReference, FirebaseFirestore} from "@firebase/firestore-types"; if( admin.apps.length === 0 ) { admin.initializeApp(); } // this is not a privileged ref const db = admin.firestore(); function buildPath(url: string|Array) { let ref: any = db; splitUrl(conf.basePath, url).forEach(p => { if( typeof ref.collection === 'function' ) { ref = ref.collection(p); } else { ref = ref.doc(p); } }); return ref; } function getData(url: string|Array) { return buildPath(url).get().then(snap => { if( snap instanceof admin.firestore.DocumentSnapshot ) { if( snap.exists ) { return snap.data(); } else { return null; } } else { const data = {}; snap.forEach(doc => data[doc.id] = doc.data()); return data; } }); } function splitUrl(...url: Array>): Array { let parts = []; url.forEach(u => { if( typeof u === 'string' ) { u.replace(/^\//, '').replace(/\/$/, '').split('/').forEach(uu =>{ if( uu !== '' ) { parts.push(uu); } }); } else { u.forEach(ubit => parts = [...parts, ...splitUrl(ubit)]); } }); return parts; } export default { path: buildPath, get: getData, relativePath(ref: DocumentReference) { const re = new RegExp(`^${conf.basePath}/?`); return ref.path.replace(re, ''); }, newId: function() { return buildPath('foo/bar').id; }, addToArray: function(url: string|Array, field: string, val) { const data = {}; data[field] = admin.firestore.FieldValue.arrayUnion(val); return buildPath(url).update(data); }, removeFromArray: function(url: string|Array, field: string, val) { const data = {}; data[field] = admin.firestore.FieldValue.arrayRemove(val); return buildPath(url).update(data); }, batch: function() { return db.batch(); }, root: function(): FirebaseFirestore.DocumentReference { return db.doc(conf.basePath); }, transaction: db.runTransaction.bind(db), FieldValue: admin.firestore.FieldValue, TRANSACTION_LIMIT: TRANSACTION_LIMIT };