BEFORE ANYONE MARKS THIS AS DUPLICATE, I AM AWARE OF: How to import CSV or JSON to firebase cloud firestore
As in the question above, I am trying to send JSON to Firestore using a Google Cloud Function, allowing me to convert my realtime database to Firestore. I have been using the script provided as an answer by Maciej Kaputa in the link above. The script he provides is as follows, which is exactly the same as that provided in the link above:
const admin = require('../functions/node_modules/firebase-admin');
const serviceAccount = require("./service-key.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://<your-database-name>.firebaseio.com"
});
const data = require("./fakedb.json");
/**
* Data is a collection if
* - it has a odd depth
* - contains only objects or contains no objects.
*/
function isCollection(data, path, depth) {
if (
typeof data != 'object' ||
data == null ||
data.length === 0 ||
isEmpty(data)
) {
return false;
}
for (const key in data) {
if (typeof data[key] != 'object' || data[key] == null) {
// If there is at least one non-object item then it data then it cannot be collection.
return false;
}
}
return true;
}
// Checks if object is empty.
function isEmpty(obj) {
for(const key in obj) {
if(obj.hasOwnProperty(key)) {
return false;
}
}
return true;
}
async function upload(data, path) {
return await admin.firestore()
.doc(path.join('/'))
.set(data)
.then(() => console.log(`Document ${path.join('/')} uploaded.`))
.catch(() => console.error(`Could not write document ${path.join('/')}.`));
}
/**
*
*/
async function resolve(data, path = []) {
if (path.length > 0 && path.length % 2 == 0) {
// Document's length of path is always even, however, one of keys can actually be a collection.
// Copy an object.
const documentData = Object.assign({}, data);
for (const key in data) {
// Resolve each collection and remove it from document data.
if (isCollection(data[key], [...path, key])) {
// Remove a collection from the document data.
delete documentData[key];
// Resolve a colleciton.
resolve(data[key], [...path, key]);
}
}
// If document is empty then it means it only consisted of collections.
if (!isEmpty(documentData)) {
// Upload a document free of collections.
await upload(documentData, path);
}
} else {
// Collection's length of is always odd.
for (const key in data) {
// Resolve each collection.
await resolve(data[key], [...path, key]);
}
}
}
resolve(data);
However, this does not seem to work for me. I have set up my firebase cli in the usual way and checked if functions can be sent to my project by running the standard "Hello world" function with success. It is not a problem with my JSON, as I have used an online validator. Through some research, I found that eslint ecmaVersion 6 does not allow async functions, which can be resolved by changing the ecmaVersion in the .eslintrc.json file to "ecmaVersion": 2017. Next, you have to delete some rules from the .eslintrc.json, these are // Require the use of === and !==
, // Disallow null comparisons without type-checking operators
and // Disallow await inside of loops
. Now, with these modifications, when I type firebase deploy --only functions
into my functions folder in the terminal, I am told that the function was deployed and provided with a link to my Firebase console. However, my function doesn't appear in the functions tab of firebase, nor is my data uploaded to the cloud firestore. Does anyone know what i am doing wrong? Could it be that I am not calling exports
on the function? Or is this used only for prebuilt Firebase functions?