Skip to content

Instantly share code, notes, and snippets.

@loucou
Last active February 2, 2021 22:03
Show Gist options
  • Select an option

  • Save loucou/2421a3548a04506bdc92cf24fa664b4b to your computer and use it in GitHub Desktop.

Select an option

Save loucou/2421a3548a04506bdc92cf24fa664b4b to your computer and use it in GitHub Desktop.
const admin = require("firebase-admin");
process.env["FIRESTORE_EMULATOR_HOST"] = "localhost:8080";
const serviceAccountKey = require("./serviceAccountKey.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccountKey),
databaseURL: `https://${serviceAccountKey.project_id}.firebaseio.com`,
});
module.exports = admin;
const { traverseFromPath, traverseFromRoot } = require("./traverse");
traverseFromRoot(handleDocument, handleCollection);
// traverseFromPath("chatrooms/firebase/messages", handleDocument, handleCollection);
async function handleCollection(collectionRef) {
const countSegments = collectionRef.path.split("/").length;
const prefix = " ".repeat(3 * (countSegments - 1));
console.log(`${prefix}${collectionRef.id}`);
return true;
}
async function handleDocument(documentRef) {
const docSnapshot = await documentRef.get();
const countSegments = documentRef.path.split("/").length;
const prefix = " ".repeat(3 * (countSegments - 1));
const data = docSnapshot.exists ? docSnapshot.data() : "not-existing";
console.log(`${prefix}${documentRef.id}: ${JSON.stringify(data)}`);
return true;
}
const admin = require("./admin");
exports.traverseFromRoot = async function (onDocument, onCollection) {
const children = await admin.firestore().listCollections();
for (const child of children) {
await visit(child, onDocument, onCollection);
}
};
exports.traverseFromPath = async function (path, onDocument, onCollection) {
const countLevels = path.split("/").length;
const isDocPath = countLevels % 2 === 0;
const node = isDocPath ? admin.firestore().doc(path) : admin.firestore().collection(path);
await visit(node, onDocument, onCollection);
};
async function visit(node, onDocument, onCollection) {
const isDocNode = typeof node.listCollections === "function";
const shouldContinue = isDocNode ? await onDocument(node) : await onCollection(node);
if (!shouldContinue) return;
const children = isDocNode ? await node.listCollections() : await node.listDocuments();
for (const child of children) {
await visit(child, onDocument, onCollection);
}
}
async function visitParallel(node, onDocument, onCollection) {
const isDocNode = typeof node.listCollections === "function";
const shouldContinue = isDocNode ? await onDocument(node) : await onCollection(node);
if (!shouldContinue) return;
const children = isDocNode ? await node.listCollections() : await node.listDocuments();
await Promise.all(children.map(child => visitParallel(child, onDocument, onCollection)));
}
async function visitStream(node, onDocument, onCollection) {
const isDocNode = typeof node.listCollections === "function";
const shouldContinue = isDocNode ? await onDocument(node) : await onCollection(node);
if (!shouldContinue) return;
if (isDocNode) {
const children = await node.listCollections();
for (const child of children) {
await visitStream(child, onDocument, onCollection);
}
} else {
const promises = [];
await new Promise(resolve => {
const stream = node.stream();
stream.on("data", doc => {
promises.push(
(async () => {
stream.pause();
await visitStream(doc.ref, onDocument, onCollection);
stream.resume();
})()
);
});
stream.on("end", resolve);
});
await Promise.all(promises);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment