I have a lambda function that uses firebase-tools to recursively delete a document. This worked fine in Firebase functions environment, but when running this on Netlify’s functions environment I’m getting an error.
const firebaseTools = require('firebase-tools');
const admin = require('firebase-admin');
const serviceAccount = require('./config/serviceAccount.json');
if (!admin.apps.length) {
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: 'https://crazy-monkey-29023.firebaseio.com'
});
}
const firestore = admin.firestore();
exports.handler = async (event, context, callback) => {
const userRef = firestore.collection("users").doc('7sa90a79saf78sadf');
// use firebase-tools to recursively delete document and sub-collections
await firebaseTools.firestore.delete(userRef.path,
{
project: 'crazy-monkey-29023',
recursive: true,
yes: true,
token: process.env.FIREBASE_TOKEN
})
.catch(error => callback('failed to recursively delete user document', { statusCode: 400 }))
callback(null, { statusCode: 200 })
}
Error
11:47:46 AM: 2020-08-12T10:47:46.598Z undefined ERROR Uncaught Exception {"errorType":"Error","errorMessage":"ENOENT: no such file or directory, mkdir '/home/sbx_user1051/.config/configstore'","code":"ENOENT","errno":-2,"syscall":"mkdir","path":"/home/sbx_user1051/.config/configstore","stack":["Error: ENOENT: no such file or directory, mkdir '/home/sbx_user1051/.config/configstore'"," at Object.mkdirSync (fs.js:914:3)"," at AsyncFunction.module.exports.sync (/var/task/src/node_modules/make-dir/index.js:114:6)"," at Configstore.set all [as all] (/var/task/src/node_modules/configstore/index.js:59:12)"," at Configstore.set (/var/task/src/node_modules/configstore/index.js:91:12)"," at Object.<anonymous> (/var/task/src/node_modules/firebase-tools/lib/track.js:11:17)"," at Module._compile (internal/modules/cjs/loader.js:1138:30)"," at Object.Module._extensions..js (internal/modules/cjs/loader.js:1158:10)"," at Module.load (internal/modules/cjs/loader.js:986:32)"," at Function.Module._load (internal/modules/cjs/loader.js:879:14)"," at Module.require (internal/modules/cjs/loader.js:1026:19)"]}
Locally this function runs fine in Netlify Dev because firebase-tools can read this ~/.config/configstore directory on my machine, but in the deployed function it can’t?
References:
- Using firebase-tools as a module firebase-tools - npm
Note: when used in a limited environment like Cloud Functions, not all firebase-tools commands will work programatically because they require access to a local filesystem.
Does not specify what commands require filesystem access.
- Example usage for recursive delete Delete data with a Callable Cloud Function | Firestore | Firebase
This seems to only work when used in Google’s functions environment.
Alternative solution
Dont use firebase-tools, use firestore.batch() collect all the references to documents you want to delete and manually delete them. I think there is a limit of 500 documents you can delete using this method.
const admin = require('firebase-admin');
const serviceAccount = require('./config/serviceAccount.json');
if (!admin.apps.length) {
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: 'https://crazy-monkey-29023.firebaseio.com'
});
}
const firestore = admin.firestore();
exports.handler = async (event, context, callback) => {
const batch = firestore.batch();
const userRef = firestore.collection("users").doc('7sa90a79saf78sadf');
const projectsRef = await firestore.collection("users").doc('7sa90a79saf78sadf').collection("projects").get();
projectsRef.docs.forEach((project) => {
batch.delete(project.ref)
});
batch.delete(userRef)
await batch.commit().catch(error => callback(null, { statusCode: 400 }))
callback(null, { statusCode: 200 })
}
References: