firebase how do I test if emulator is running? - javascript

I am connecting to my storage emulator with the following code:
const firebaseApp = initializeApp(appConfig.firebase)
storage = getStorage(firebaseApp)
connectStorageEmulator(storage, 'localhost', 9199)
This works fine when the emulator is running. It also works fine when the emulator is NOT running! if its not running I want to do something else like this:
if (emulatorIsConnectedAndEmulatorIsRunning) {
// do something
} else {
// do something else
}
How can I detect whether the emulator is running or not?
TIA

This is AN answer, not necessarily the best answer and I would appreciate other answers.
Basically, I am not just emulating storage but also cloud functions.
I've made a cloud function like this:
export const ping = functions.https.onRequest((req, res) => {
res.json({ ping: 'pong' })
})
So in my code I just ping this endpoint. For example:
axios.get(`http://localhost:5001/${storageBucket}/us-central1/ping`)
If it responds 200 then the function emulator is running (and given my setup this also means the storage emulator is running).

Related

Sendgrid emails won't send when deployed to Vercel

Recently, I decided to try out vercel for a small project and ran into issues using sendgrid with vercel. I've implemented sendgrid into nodejs/express projects before on heroku with no issues, but for some reason Vercel just doesn't work.
Even worse, sendgrid gives no errors whatsoever so its been difficult to troubleshoot. The promise just hangs forever. Everything works fine locally when testing and I've confirmed that env variables are correct and loading.
Here's my code:
const sgMail = require('#sendgrid/mail');
const { magicLinkTemplate } = require('./templates');
const sendEmail = async (msg) => {
sgMail.setApiKey(process.env.SENDGRID_API_KEY);
try {
await sgMail.send(msg)
} catch (error) {
console.error(error);
if (error.response) {
console.error(error.response.body)
}
}
}
I've tried a number of iterations, and failed every time. Has anyone else run into issues using vercel with sendgrid?
Alright, so I believe I solved my own problem.
The issue lies in how vercel handles serverless functions:
If you're on free tier, each request must resolve in 10 seconds (for pro its 60)
Vercel seems to instantly terminate a serverless function once a response is returned, aka side effects that are not finished will cease to run.
Previously, I was running the email sends as a side effect and the api response would return without waiting for sendgrid to fullfil its promise. Below is a watered down version of my original code.
router.post('/', checkUser)
async function checkUser(req, res, next) {
const { email } = req.body;
const magicLink = generateMagicLink()
sendMagicLink(email, magicLink)
res.status(200).json({})
}
The sendMagicLink function is async and would continue to run locally, but in vercel it would cease once a status was returned from the api.
New code looks like this...
router.post('/', checkUser)
async function checkUser(req, res, next) {
const { email } = req.body;
const magicLink = generateMagicLink()
await sendMagicLink(email, magicLink)
res.status(200).json({})
}
Now the serverless function stays alive because it waits for the async process to finish.
This whole thing tripped me up because if you have a persistent server, there would be no issues with the original version. Hope this helps someone!

Deploy whatsapp-web bot on heroku

I'm creating a whatsapp bot using the node library whatsapp-web.js After I'm done with the script it looks something like (I just put a overview of the orignal script) -
index.js
const {Client, LocalAuth, MessageMedia } = require('whatsapp-web.js');
const qrcode = require('qrcode-terminal');
const client = new Client({
puppeteer: {
args: ['--no-sandbox', "--disable-setuid-sandbox"]
},
authStrategy: new LocalAuth()
});
client.on('qr', (qr) => {
console.log('qr received: ', qr);
qrcode.generate(qr, {small:true});
});
client.on('ready', () => {
console.log('READY');
});
client.on('message', async msg => {
let type = msg.type;
let chat = await msg.getChat();
if(chat.isGroup) {
//do something
}else {
//
if(msg.body === "ping") {
msg.reply("pong");
}
}
});
Everything is fine with the script and it works good on linux or ubuntu (I already added puppeteer build pack on that Heroku app). As I need to run that script continuously I decided to put that on a worker process.
Procfile
worker: node index.js
But now the problem comes in role, how can I authenticate here? I decided to remove that line from index.js
qrcode.generate(qr,{small:true});
And insted I thought I will print all the logs on heroku-cli
heroku logs -a wweb-bot
#my app named as wweb-bot
and from there access the key generated as qr. After that I'll turn it into a qrcode and scan it. When I did all setup and try it I was getting a continuously generating logs of qr keys. It's nonstop, and keep generating keys after every 15-20 sec. What's the problem here? Is it because Heroku has a read only environment or anything else is missing? Please help me how can i do it
remove or comment this code
// authStrategy: new LocalAuth()
it will not work on heroku
but as the code is on server, you don't need to scan again and again, you need to scan only you restart your server
but if you are facing puppeteer error then add these buildpacks in heroku /your project/settings/ scrol down to adduildpack
add these two buildpacks
https://github.com/jontewks/puppeteer-heroku-buildpack
https://github.com/heroku/heroku-buildpack-google-chrome
then redeploy your app
Edit: now whatsapp-web.js added new functionality of doing this called RemoteAuthStatergy just go throughout it.

How to deploy Next JS App with Mongoose(MongoDB) connection on Vercel?

I am facing issue while deploying my next js app on vercel with mongodb connection. I have added env variable also on vercel site where we deploy next js app. Is there something going wrong in the below file ?
next.config.js
module.exports = {
env: {
MONGODB_URI: "mongodb://localhost/tasksdb",
},
};
I have add env variable as well into my next js project
.env.local
MONGODB_URI = "mongodb://localhost/tasksdb"
I establish this mongodb connection from this doc https://mongoosejs.com/. It's provide us to connect with mongodb straightaway .
And this my mongodb connection establish code
import { connect, connection } from "mongoose";
const conn = {
isConnected: false,
};
export async function dbConnect() {
if (conn.isConected) return;
const db = await connect(process.env.MONGODB_URI);
conn.isConnected = db.connections[0].readyState;
// console.log(conn.isConnected);
// console.log(db.connection.db.databaseName)
}
connection.on("connected", () => {
console.log("Mongodb connected to db");
});
connection.on("error", (err) => {
console.error("Mongodb connected to", err.message);
});
Is there something wrong by creating the database this way because in local everything working fine ?
I don't think vercel's servers can comunicate with your localhost. You can try hosting your database in the mongodb cloud
The code seems to be fine, but you can not connect to Vercel using localhost. You can use Serverless Atlas version of MongoDB which is free you can host your database there and then connect using the link they will provide.
See : https://www.mongodb.com/pricing

Firestore function deployment error when using Twilio

I'm trying to integrate Twilio into a triggered Firestore function. The problem I'm having is when I add this code, I am unable to deploy ANY functions. As far as I know this is how to use twilio inside a cloud function. At the top I have this and I think firebase doesn't like something here because ALL functions stop deploying with this code.
// Used to send text messages
const twilio = require('twilio')
// const accountSid = functions.config().twilio.sid
// const authToken = functions.config().twilio.token
/* eslint new-cap: ["error", { "newIsCap": false }] */
const client = new twilio('ACblahblahblah', 'ccblahblahblah') // sid and token
const twilioNumber = '+13344714571' // your twilio phone number
Within the triggered function I have this. But I don't think the issue is here:
return client.messages.create({
to: someNumber,
from: twilioNumber,
body: 'Some message.'
}).then((data) => {
console.log(data)
}).catch((error) => {
console.log(error)
})
I have a valid Twilio account set up. The function logs don't tell me much other than that the function cannot be initialized. What am I missing? Seems like this has worked for others.
Figured it out about 5 minutes after posting the question. I had not installed twilio in the functions folder but rather the root of the project. Once I executed
npm install twilio
in the functions folder, the functions started deploying. Too bad there was no error in the logs that said something like "required package is missing" or something like that.

React-Native-Firebase : RTDB Emulator

Does anybody knows how to use realtime database emulators?
I can use function & firestore emulators like below.
import functions from '#react-native-firebase/functions';
import firestore from '#react-native-firebase/firestore';
functions().useFunctionsEmulator('http://localhost:5001');
firestore().settings({ host: 'localhost:8080' });
But was not able to find something similar for realtime database.
Any link/video is appreciated.
Thanks.
Basically the solution posted by Frank van Puffelen was correct. However, this got me stuck for a while so I'm going to share my experience to save time for others.
import { firebase } from "#react-native-firebase/database";
const database = firebase
.app()
.database("http://localhost:9000?ns=YOUR_DATABASE_NAMESPACE");
const ref = database.ref(`yourPath`)
...
Here comes the huge gotcha:
If you're using Android Emulator you have to use
const database = firebase
.app()
.database("http://10.0.2.2:9000?ns=YOUR_DATABASE_NAMESPACE");
If you're using a real android device you have to set up reverse proxy first:
adb reverse tcp:9000 tcp:9000
then set up the database normally
const database = firebase
.app()
.database("http://localhost:9000?ns=YOUR_DATABASE_NAMESPACE");
I didn't test for iOS, but I believe localhost should work.
I have this in my root index.js file for my react native project:
// Use a local emulator in development
if (__DEV__) {
// If you are running on a physical device, replace http://localhost with the local ip of your PC. (http://192.168.x.x)
auth().useEmulator('http://localhost:9099');
functions().useFunctionsEmulator('http://localhost:5001');
database().useEmulator('localhost', 9000);
const db = firestore();
db.settings({ host: 'localhost:8080', ssl: false });
}
Nothing else in my app needed to be modified. The database().useEmulator line does the trick.
I am assuming you have already initialized all the emulators first using firebase init emulators and have them running with firebase emulators:start.
Make sure you're using the ${projectId}-default-rtdb database in the emulator.
According to the documentation on Connect your app to the Realtime Database Emulator, that is done with:
if (location.hostname === "localhost") {
var firebaseConfig = {
// Point to the RTDB emulator running on localhost.
// In almost all cases the ns (namespace) is your project ID.
databaseURL: "http://localhost:9000?ns=YOUR_DATABASE_NAMESPACE"
}
var myApp = firebase.initializeApp(firebaseConfig);
var db = myApp.database();
}
I'm not certain if that is supported in react-native-firebase yet, since it isn't mentioned in their documentation at all. The most logical things to try would be their Using a secondary database:
const database = firebase.app().database('http://localhost:9000?ns=YOUR_DATABASE_NAMESPACE');

Categories

Resources