Last active
May 16, 2023 17:38
-
-
Save gregfenton/c858085837edea71ec8fba6d5eabf175 to your computer and use it in GitHub Desktop.
Downloads all docs in a Firestore collection and stores as a JSON file -- command-line JavaScript/node
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* get_firestore_collection_as_json.js | |
* | |
* This code is a "node script" used to fetch all documents from a Firestore collection, | |
* either in "the cloud" or the emulator, and write them to a file as JSON. | |
* | |
* The script is a "client app", so it logs in with Firebase Auth using email/password from the variable USER1. | |
* This USER1 user ([email protected]) must exist in your Firebase project and have read access | |
* to the collection(s) you are populating. You can create that account via | |
* Firebase Console >> Authentication. | |
* | |
* This script is assumed to live in an existing Javascript project that has its own package.json. | |
* I store this script in <PROJECT_ROOT>/tools/fs-to-json/. | |
* | |
* To use: | |
* 1. Import the 'firebase' and 'esm' NPM modules to your project (Run the command: `npm install firebase esm`) | |
* 2. Edit the data for USER1 and FIREBASE_CONFIG, then adjust parameters in `main` for the call to `visitDocs`. | |
* | |
* NOTE: this code works with the Firebase Web SDK v9 API. Earlier revisions used the v8 API. | |
* | |
* Steps to use this repo: | |
* 1. Create a new directory and copy the 2 files (package.json & get_firestore_collection_as_json.js) to it | |
* 2. Run the command: npm install | |
* 3. Run the command: npm run tool:fetch-data | |
* | |
* (Note: the command `tool:fetch-data` is defined in package.json) | |
*/ | |
import * as fs from 'fs'; | |
import {initializeApp} from 'firebase/app'; | |
import { | |
addDoc, | |
collection, | |
connectFirestoreEmulator, | |
getDocs, | |
getFirestore, | |
writeBatch | |
} from 'firebase/firestore'; | |
import {getAuth, signInWithEmailAndPassword} from 'firebase/auth'; | |
let FIRESTORE; | |
let AUTH; | |
// Firebase Console >> Authentication | |
const USER1 = { | |
email: '[email protected]', // USER THAT EXISTS IN FIREBASE AUTH | |
password: 'let_me_in', | |
uid: UID_FROM_FIREBASE_AUTH_FOR_THIS_USER | |
}; | |
const initializeFB = async () => { | |
// USE YOUR FIREBASE PROJECT SETTINGS: | |
// Firebase Console >> Project Overview >> Apps | |
// >> (select or "Add App" web app) >> Config | |
const firebaseConfig = { | |
apiKey: VALUES_FROM_FIREBASE_APP_CONFIG, | |
appId: VALUES_FROM_FIREBASE_APP_CONFIG, | |
authDomain: VALUES_FROM_FIREBASE_APP_CONFIG, | |
databaseURL: VALUES_FROM_FIREBASE_APP_CONFIG, | |
messagingSenderId: VALUES_FROM_FIREBASE_APP_CONFIG, | |
projectId: VALUES_FROM_FIREBASE_APP_CONFIG | |
}; | |
let fbApp = initializeApp(firebaseConfig); | |
FIRESTORE = getFirestore(fbApp); | |
let USING_FIREBASE_EMULATOR = true; | |
if (USING_FIREBASE_EMULATOR) { | |
// I explicitly set "host" and "port" in firebase.json so that devices | |
// on my local network can access the emulator: | |
// "emulators": { | |
// "functions": { | |
// "port": 5001, | |
// "host": "192.168.1.53" | |
// }, | |
// "firestore": { | |
// "port": 5002, | |
// "host": "192.168.1.53" | |
// }, | |
// ... | |
// | |
connectFirestoreEmulator(FIRESTORE, '192.168.1.53', 5002); | |
} | |
try { | |
AUTH = getAuth(); | |
await signInWithEmailAndPassword(AUTH, USER1.email, USER1.password); | |
let currUser = AUTH.currentUser; | |
console.log(`Logged in with USER1 uid(${currUser.uid})`); | |
} catch (ex) { | |
console.error(ex.message); | |
throw ex; | |
} | |
}; | |
const die = (msg) => { | |
console.error(msg); | |
process.exit(1); | |
}; | |
const getDocuments = async (collectionName) => { | |
let retVal = []; | |
try { | |
let collectionRef = collection(FIRESTORE, collectionName); | |
let querySnap = await getDocs(collectionRef); | |
for (let i = 0; i < querySnap.size; i++) { | |
retVal.push({ | |
_DOCUMENT_ID_: querySnap.docs[i].id, | |
...querySnap.docs[i].data() | |
}); | |
} | |
} catch (ex) { | |
die(`ERROR getDocuments():: ${ex.message}`); | |
} | |
return retVal; | |
}; | |
const main = async () => { | |
console.log('>>> START LOADING Users - ', Date()); | |
await initializeFB(); | |
let collectionName = 'user'; | |
let allDocs = await getDocuments(collectionName); | |
let jsonFile = `./${collectionName}.json`; | |
fs.writeFileSync(jsonFile, JSON.stringify(allDocs, null, 2), (err) => { | |
if (err) { | |
die(`EXCEPTION while writing JSON file: ${err.message}`); | |
} | |
console.log(`JSON data saved to (${jsonFile})`); | |
}); | |
console.log('>>> DONE - output written to:', jsonFile); | |
process.exit(); | |
}; | |
main().catch((ex) => { | |
die('main() caught an exception: ' + ex.message); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "gist", | |
"version": "0.0.1", | |
"description": "", | |
"main": "get_firestore_collection_as_json.js", | |
"scripts": { | |
"tool:fetch-data": "node -r esm ./get_firestore_collection_as_json.js 2>&1 | tee get_json.log" | |
}, | |
"author": "https://github.com/gregfenton", | |
"license": "free", | |
"dependencies": { | |
"esm": "^3.2.25", | |
"firebase": "^9.6.1" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment