Getting: Firebase service named 'database' already registered error, even tho I am not importing firebase/database anywhere - javascript

Environment
Operating System version: Mac OS 10.15.1
Firebase SDK version: 8.8.0
Firebase Product: database (auth, database, storage, etc)
Node.js version: 8.15.1
NPM version: 6.9.0
"firebase": "7.5.0",
"firebase-admin": "8.8.0",
"firebase-functions": "3.3.0"
Problem
When I call firebase deploy --only functions, it stops on step functions: preparing functions directory for uploading... and throws:
database: Firebase: Firebase service named 'database' already registered (app/duplicate-service)
This is the where the error is found:
at error (....../functions/node_modules/#firebase/app/dist/index.node.cjs.js:41:21)
Also I started getting: Error parsing triggers: The gRPC binary module was not installed. This may be fixed by running "npm rebuild"
Of course I have tried npm rebuild but without any luck...
Relevant Code
The only way I reference database is through:
// Init firebase access to DB
const firebase_admin = require("firebase-admin");
// Get a database reference
const firebase_db = firebase_admin.database();
I do this in multiple files tho.
After a little more digging, I managed to find out that it is caused by code in these two files:
// Init firebase access to DB
const firebase_admin = require("firebase-admin");
// Get a database reference to our blog
const firebase_db = firebase_admin.database();
const get_firebase_data = async (page_type, call_back) => {
const is_paypal_page = page_type === "paypal"
const is_admin_page = page_type === "admin"
const content = await firebase_db.ref("/content").once("value")
const footer_content = await firebase_db.ref("/footer_content").once("value")
const header_items = await firebase_db.ref("/header_items").once("value")
const translations = await firebase_db.ref("/translations").once("value")
const single_product_homepages = await firebase_db.ref("/single_product_homepages").once("value")
const couple_products_homepages = await firebase_db.ref("/couple_products_homepages").once("value")
const categories_of_product_variety = await firebase_db.ref("/categories_of_product_variety").once("value")
let products;
let shipping_options;
let admin;
if(is_paypal_page || is_admin_page) {
products = await firebase_db.ref("/products").once("value")
shipping_options = await firebase_db.ref("/shipping_options").once("value")
}
if(is_admin_page)
admin = await firebase_db.ref("/admin").once("value")
const final_object = {
...
}
call_back(null, final_object)
}
module.exports = (req,res) => {
get_firebase_data(req.params[0].replace("/", ""), (err,result) => {
if(err) res.send(err)
res.send(result)
})
}
and
const paypal = require('paypal-rest-sdk')
const { paypal_config } = require("../config")
const axios_instance = require("./inventorysource/axios_inventorysource_instance")
const create_order = require("./inventorysource/create_order")
paypal.configure(paypal_config)
const paymentPaypal = (paymentID, execute_payment_json, call_back) => {
paypal.payment.execute(paymentID, execute_payment_json, (error, paymentLog)=> {
if (error)
return call_back(error)
else {
call_back(null, paymentLog)
}
})
}
module.exports = (req, res) => {
const body = req.body
const execute_payment_json = { "payer_id": body.data.payerID }
const paymentID = body.data.paymentID
paymentPaypal(paymentID, execute_payment_json, (err, paypal_data) => {
if(err)
res.send(err)
else
create_order(
axios_instance(body.data.is_production),
body.data.is_production,
body.data.amount,
body.data.user_and_product_data,
res, paypal_data
)
})
}
However I dont import or require "firebase/database" anywhere in my code.
What I have tried
As answers to similar issues suggest, I have deleted node_modules and package-lock.json and tried re-installing with npm install multiple times.
I have also tried using different versions od Node and completely rebuilding my packages with npm rebuild.
Furthermore I have tried installing latest versions of the above mentioned firebase packages and then deleting and install npm all over again. Still with no luck...
I also tried commenting out parts of my code that deal with firebase but still, the error remains.

Related

Discordjs v12 | cannot find module ../undefined/help.js

My bot has a command located in /commands/developer/reload.js and it's purpose is to unload a command then load it again. But when trying to find the commands folder it throws an error saying Cannot find module '../undefined/help.js' but the path is ../misc/help.js
Code:
const fs = require('fs');
module.exports = {
name: 'reload',
description: 'Reloads a command',
args: true,
usage: '<command_name>',
cooldown: 1,
aliases: ['rl', 'restart'],
execute(message, args) {
const commandName = args[0].toLowerCase();
const command = message.client.commands.get(commandName) || message.client.commands.find(cmd => cmd.aliases && cmd.aliases.includes(commandName));
if(!command) {
return message.channel.send(`There is no command called '${commandName}'`);
}
// commandFolders returns undefined
const commandFolders = fs.readdirSync('./commands');
// Also returns undefined
const folderName = commandFolders.find(folder => {
fs.readdirSync(`./commands/${folder}`).includes(`${command.name}.js`);
})
// Command errors out here
delete require.cache[require.resolve(`../${folderName}/${command.name}.js`)];
// This part never runs.
try {
const newCommand = require(`../${folderName}/${command.name}.js`);
message.client.commands.set(newCommand.name, newCommand);
message.channel.send(`Command '${newCommand.name}' was reload successfully`)
} catch (err) {
console.error(err);
message.channel.send(`There was an error while reloading a Command.`)
}
}
}
The reason why you are getting the folder as undefined is because you are not returning the folder you are trying to find in the folderName function. It is trying to find a folder with the command and even if it does, you are not doing anything with it, you are not returning it or logging it into the console. So you just have to return it, the folderName function might look something like this:
const folderName = commandFolders.find(folder => fs.readdirSync(`commands/${folder}`).includes(`${command.name}.js`)) // If you want a one-liner
// Or
const folderName = commandFolders.find(folder => {
return fs.readdirSync(`commands/${folder}`).includes(`${command.name}.js`)
})
If the error persists, the error is most likely there because the path is not correct. So in that case, please provide the folder structure of your bot

Pub Sub Cloud Function - Async Await

Trying to accomplish the following via a scheduled Firebase Function:
Fetch Firestore Collection
Delete Collection
Make Get Request to External API
Write Get Request results to Firestore Collection.
The function is failing to deploy. Error logs only say {"code":3,"message":"Function failed on loading user code. This is likely due to a bug in the user code.
When I run the emulator suite locally, I get no errors, but the DB does not update.
I'm getting a linting error on the "=>" that's attached to the "onRun" method. Not sure if this is a code problem or an ESLint problem for ES6 in Firebase Functions.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const axios = require('axios');
admin.initializeApp();
const db = admin.firestore();
exports.scheduledFunction = functions.pubsub
.schedule("every 2 minutes")
.timeZone("America/New_York")
.onRun(async (context) => {
try {
const querySnapshot = await db.collection("my_collection").get();
console.log(querySnapshot.docs)
const promises = querySnapshot.docs.map(doc => db.collection("my_collection").doc(doc.id).delete());
await Promise.all(promises);
const options = {
"method": "get",
"url": "www.myUrl.com",
"headers": {
"Cookie": "...",
},
};
const axiosResponse = await axios(options);
const apiResponse = JSON.parse(axiosResponse.data);
const parsedResponse = apiResponse["news_results"];
const docCreationPromises = parsedResponse.map(response => db.collection("my_collection").add(parsedResponse))
await Promise.all(docCreationPromises);
return null;
} catch (error) {
console.log(error);
return null;
}
});
For the ESLint issue with =>, try setting the ecmaVersion to 8 in your ESLint config.
module.exports = {
root: true,
env: {
es6: true,
node: true,
},
extends: [
"eslint:recommended",
"google",
],
parserOptions: {
ecmaVersion: 8
}
};
When I run the emulator suite locally, I get no errors, but the DB does not update.
Are you using Firestore emulator? If yes, then data will be added there and not in production so you can see the data in emulator only.

How to commit and push with simple-git (NODEJS)?

I'm trying to do a simple Commit & Push to an existing repo using simple-git however I can't find
any example regarding this issue in the API in NPM (or Github) of simple-git.
I'm talking about this package : https://www.npmjs.com/package/simple-git
Consider the code :
const gitRepo = 'REPO-URL';
const tempFolder = '...';
// Simple Git
const simpleGit = require('simple-git')();
const options = ['--depth', '1'];
const callback = () => {
console.log('Done cloning!');
// Now change some code in the cloned code
// and commit && push
};
// Cloning ...
simpleGit.outputHandler((command, stdout, stderr) => {
stdout.pipe(process.stdout);
stderr.pipe(process.stderr)
stdout.on('data', (data) => {
// Print data
console.log(data.toString('utf8'));})
})
.clone(gitRepo, tempFolder, options, callback);
How can we commit and push using simple-git ?
Like #Lawrence Cherone said :
You can just use the basic commands as is.
This is how i used it in my project ( though i got a submodule in it where this example is changing its (git)working directory to content(submodule) first. After that i just commit with a message.
app.post("/gitCommit", async function(req, res) {
try {
await git.cwd({ path: 'content' }).commit(req.body.msg);
res.sendStatus(200)
} catch(err) {
console.log(err)
}
});
If you already have a working and initialised repo your in,
then you could just do the following:
await git.commit("your_message")
await git.push()
await git.push('origin', 'master')
You can leave out the 'await' part depending on your code running async.

Fail to navigate to a proper folder in nodejs

I'm trying to create a function that pull a remote repository and then navigate through this repo and install it's dependencies but somehow it fail to install the dependencies inside the cloned repo and it install them outside:
const spinner = clui.Spinner;
const git = require("simple-git/promise");
const path = require("path");
const { install } = require("pkg-install");
async function pullRepo() {
const pulling = new spinner("Initializing project...");
const installing = new spinner("Installing dependencies...");
const rep = await inquirer.DirectoryName();
const package = path.join(rep.project, "package.json");
pulling.start();
await git()
.silent(true)
.clone("git#github.com:blacklane/create-blacklane-app.git", rep.project)
.then(async () => {
pulling.stop();
console.log(`working directory:`, process.cwd());
// check file exist asynchronously
fs.access(package, fs.constants.F_OK, err => {
console.log(`${package} ${err ? "does not exist" : "exists"}`);
});
installing.start();
const obj = JSON.parse(fs.readFileSync(package, "utf8"));
const dependencies = { ...obj.dependencies, ...obj.devDependencies };
process.chdir(rep.project); // navigate to directory to install dpendencies
console.log(`new working directory from git:`, process.cwd());
const { stdout } = await install(dependencies, {
dev: true,
prefer: "npm"
});
console.log(stdout);
installing.stop();
})
.catch(error => console.error("failed: ", error));
// progress.finish();
}
The reason this can happen because install is somehow not able to get to the cloned repo. May be because underlying shell which is running the Node process is still the same.
following is the working code:
const clui = require('clui');
const spinner = clui.Spinner;
const git = require("simple-git/promise");
const path = require("path");
const fs = require('fs');
const fsPromises = fs.promises;
const { spawn } = require('child_process');
async function pullRepo(repo, dirName) {
const pulling = new spinner("Initializing project...");
const installing = new spinner("Installing dependencies...");
pulling.start();
await git().silent(true).clone(repo, dirName);
pulling.stop();
const package = path.join(dirName, "package.json");
// check file exist asynchronously
await fsPromises.access(package, fs.constants.F_OK);
installing.start();
const npmInstall = spawn('npm', ['i'], { cwd: dirName });
npmInstall.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
});
npmInstall.stderr.on('data', (data) => {
console.error(`stderr: ${data}`);
installing.stop();
});
npmInstall.on('close', (data) => {
installing.stop();
});
}
const repoToPull = "https://github.com/facebook/create-react-app.git"; // can be any repo
const dirToPullTo = path.join(__dirname,'gitpull'); // directory you want to pull it to.
pullRepo(
repoToPull,
dirToPullTo
).then(res => console.log(res));
This code needs better error handling.
You don't need to add .then when you are awaiting a promise

How to fix firebase database initialised multiple times due to React SSR initialised database and cloud function firebase initialised database?

I have updated the question as found the root cause of the issue.
As I have hosted my React SSR app which uses firebase database in the client serving by one of the cloud function named app throwing an error of Error: FIREBASE FATAL ERROR: Database initialized multiple times. Please make sure the format of the database URL matches with each database() call.. When I comment out one by one and deploy, works perfectly. But when I deploy together doesn't work. How do I separate these two keeping both at the same repo?
ORIGINAL Question: Why firebase cloud function throwing an error of 'The default Firebase app does not exist.'?
So I am trying out firebase function for the first time. admin.messaging() throwing me the following error. Help me figure out why?
If I look at the console I get results till console.log('deviceToken', deviceToken);
so whats wrong in const messageDone = await admin.messaging().sendToDevice(deviceToken, payload);?
const functions = require('firebase-functions');
const admin = require('firebase-admin');
exports.updateUnreadCount = functions.database.ref('/chats/{chatId}/{messageId}')
.onCreate(async(snap, context) => {
const appOptions = JSON.parse(process.env.FIREBASE_CONFIG);
appOptions.databaseAuthVariableOverride = context.auth;
const adminApp = admin.initializeApp(appOptions, 'app');
const { message, senderId, receiverUid } = snap.val();
console.log(message, senderId, receiverUid);
console.log('------------------------');
const deleteApp = () => adminApp.delete().catch(() => null);
try {
const db = adminApp.database();
const reciverUserRef = await db.ref(`users/${receiverUid}/contacts/${senderId}/`);
console.log('reciverUserRef', reciverUserRef);
const deviceTokenSnapshot = await reciverUserRef.child('deviceToken').once('value');
const deviceToken = await deviceTokenSnapshot.val();
console.log('deviceToken', deviceToken);
const payload = {
notification: {
title: 'Test Notification Title',
body: message,
sound: 'default',
badge: '1'
}
};
const messageDone = await admin.messaging().sendToDevice(deviceToken, payload);
console.log('Successfully sent message: ', JSON.stringify(messageDone));
return deleteApp().then(() => res);
} catch (err) {
console.log('error', err);
return deleteApp().then(() => Promise.reject(err));
}
});
Update1: According to this https://firebase.google.com/docs/cloud-messaging/send-message#send_to_a_topic, admin.messaging().sendToDevice(deviceToken, payload) APIs are only available in the Admin Node.js SDK?
So switched to
const payload = {
data: {
title: 'Test Notification Title',
body: message,
sound: 'default',
badge: '1'
},
token: deviceToken
};
const messageDone = await admin.messaging().send(payload);
Which is not working either. Getting an error Error: The default Firebase app does not exist. Make sure you call initializeApp() before using any of the Firebase services. Any lead will be helpful.
EDIT: Finally got the function working.
My index.js is exporting to functions, follwoing
exports.app = functions.https.onRequest(app); //React SSR
exports.updateChat = functions.database.ref('/chats/{chatId}/{messageId}').onCreate(updateChat);
exports.app is a react ssr function, which I am using to host my site. This uses database too. and throwing error of multiple database instance.
When I comment out one by one and deploy, works perfectly. But when I deploy together doesn't work. How do I separate these two keeping both at the same repo? Any suggestions, please?
You can initialise db outside export function.
const admin = require('firebase-admin');
const adminApp = admin.initializeApp(appOptions, 'app')
//continue code
Update:
const admin = require('firebase-admin');
const adminApp = admin.initializeApp(options);
async function initialize(options, apps = 'app') {
try {
const defaultApp = adminApp.name
if(defaultApp) {
const adminApp1 = admin.initializeApp(apps);
}else {
const adminApp1 = admin.initializeApp(options, apps);
}
}catch(err) {
console.error(err);
}
}
Modify this snippet as per your need and try it out
It abstracts initialize of app in another function. Just call this function at appropriate place in your code.

Categories

Resources