How to run 2 firebase cloud functions at a time - javascript

I want to run 2 firebase cloud functions at a time I have tried some method but it is throwing an error when functions are triggered. I have 2 childs in the database and when any changes occur in the childs it should show a notification to users. can anyone help me out of this.
This is database image showing 2 childs in database:
this is my index.js file
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
const fooModule = require('./foo');
const barModule = require('./bar');
exports.foo = functions.database.ref('app_title').onWrite(fooModule.handler);
exports.bar = functions.database.ref('db_kinda/{Uid}/comment').onWrite(barModule.handler);
this is my foo.js file
const functions = require('firebase-functions');
// Listens for new debate topic created
exports.appTitle = (event) => {
console.log('Push notification event triggered');
const app_title = change.after.val();
if (!change.after.exists() && change.before.exists()) {
return change.before.val();
}
const payload = {notification: {
title: 'New Notification',
body: `${app_title}`
}};
return admin.messaging().sendToTopic("appGlobal",payload)
.then(function(response){
console.log('Notification sent successfully:',response);
})
.catch(function(error){
console.log('Notification sent failed:',error);
});
};
this is my bar.js file
const functions = require('firebase-functions');
exports.data = (event) => {
console.log('Push notification event triggered');
const comment = change.after.val();
if (!change.after.exists() && change.before.exists()) {
return change.before.val();
}
const payload = {notification: {
title: 'New Notification',
body: `${comment}`
}};
return admin.messaging().sendToTopic("appGlobal",payload)
.then(function(response){
console.log('Notification sent successfully:',response);
})
.catch(function(error){
console.log('Notification sent failed:',error);
});
};
This functions are deploying properly but when it runs on firebase functions it throws error like this
TypeError: handler is not a function
at cloudFunction (/srv/node_modules/firebase-functions/lib/cloud-functions.js:127:23)
at /worker/worker.js:825:24
at
at process._tickDomainCallback (internal/process/next_tick.js:229:7)

As the error says, handler is not a function. When you import foo for example, you're getting the value of exports which has a property called appTitle, not handler. Try this:
const fooModule = require('./foo');
exports.foo = functions.database.ref('app_title').onWrite(fooModule.appTitle);
Or, change your ./foo export to:
const functions = require('firebase-functions');
// Listens for new debate topic created
exports.handler = (event) => {
...
};

Related

"TypeError: Cannot read property 'val' of undefined" for push notification

Hi I'm very new to this.
Here is my data tree on Firebase:
I'm trying to access the newly created nodes under "sightings" and here is my cloud function code.
const functions = require('firebase-functions');
const admin = require('firebase-admin')
admin.initializeApp(functions.config().firebase)
exports.announceSighting = functions.database
.ref('sightings/{sightingId}')
.onCreate(event => {
const sighting = event.data.val()
sendNotification(sighting)
})
function sendNotification(sighting) {
const name = sighting.name
const payload = {
notification: {
title: 'New Sighting Available',
body: 'Hi',
// body: title + name,
sound: 'default'
}
}
console.log(payload)
const topic = "Sightings"
admin.messaging().sendToTopic(topic, payload)
}
From my understanding, I'm listening to new nodes by .ref('sightings/{sightingId}') sightingId is what I've interpreted from a tutorial given the name of the parent is sightings, but I don't know what I should put here to indicate that I am looking for children under sighting
This is the error I've been getting this:
Your help is greatly appreciaated.
As per the docs, you should use the snapshot to get the data of the created object like so:
exports.announceSighting = functions.database.ref('/sightings/{sightingId}')
.onCreate((snapshot, context) => {
const sighting = snapshot.val();
sendNotification(sighting)
});

TypeError: this.path.replace is not a function at new FirestoreDelete

Trying to remove the users`s data calling a function from app.
'use strict';
const functions = require('firebase-functions');
const firebase_tools = require('firebase-tools');
const admin = require('firebase-admin');
const serviceAccount = require('./myapp.json');
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://myapp.firebaseio.com"
});
let db = admin.firestore();
exports.mintAdminToken = functions.https.onCall((data, context) => {
const uid = data.uid;
return admin
.auth()
.createCustomToken(uid, { admin: true })
.then(function(token) {
return { token: token };
});
});
exports.recursiveDelete = functions
.runWith({
timeoutSeconds: 540,
memory: '1GB'
})
.https.onCall((data, context) => {
if (!(context.auth && context.auth.token )) {
throw new functions.https.HttpsError(
'permission-denied',
'Must be an administrative user to initiate delete.'
);
}
let path = data.path;
console.log(
`User ${context.auth.uid} has requested to delete path ${path}`
);
return firebase_tools.firestore
.delete(path, {
project: process.env.GCLOUD_PROJECT,
recursive: true,
yes: true,
token: functions.config().fb.token
})
.then(() => {
return {
path: path
};
});
});
and I pass the path like:
Map<String, Object> data = new HashMap<>();
data.put("path", "./users/rnAjpK4LLSMMlENZqe4l3F2");
result:
Function execution took 540003 ms, finished with status: 'timeout'
probably the problem is in path. if I change for this line:
let path = admin.firestore().doc('users/' + context.auth.uid);
Im getting an error
Unhandled error TypeError: this.path.replace is not a function at new FirestoreDelete
is the problem with "path"?
what will be the right path to delete then?
I use this example https://github.com/firebase/snippets-node/tree/master/firestore/solution-deletes but here is nothing about it
UPDATED:
with
String path = "./users/rnAjpK4LLSMMlENAgrZqe4l3F2";
or
String data = "./users/rnAjpK4LLSMMlENAgrZqe4l3F2";
an error
Unhandled error { FirebaseError: Must specify a path. at Object.reject (/srv/node_modules/firebase-tools/lib/utils.js:82:27)
solution
const id = context.auth.uid;
const path = `users/${id}`;
As far as I can see from reading the code of the delete function, the path you pass in has to be a single string value of the collection or document to delete. The function will then delete all data under that collection or document.
I was accidentally sending an entire object. If you come across this question, double check you're not making the same mistake.

How to debug an ApolloServer's context function?

I'm trying to follow the GraphQL tutorial (https://www.apollographql.com/docs/tutorial/resolvers/), but I'm getting an error in the playground when I try to book a trip, with a stack trace starting like this:
"TypeError: Cannot read property 'id' of null",
" at UserAPI.bookTrips (/Users/kurtpeek/Documents/Scratch/fullstack-tutorial/start/server/src/datasources/user.js:35:38)",
In src/index.js, the ApolloServer (https://www.apollographql.com/docs/apollo-server/api/apollo-server/) is defined with an asynchronous context() function like so:
const { ApolloServer } = require('apollo-server');
const typeDefs = require('./schema');
const { createStore } = require('./utils');
const resolvers = require('./resolvers');
const LaunchAPI = require('./datasources/launch');
const UserAPI = require('./datasources/user');
const isEmail = require('isemail');
const store = createStore();
const server = new ApolloServer({
context: async ({ req }) => {
debugger;
const auth = (req.headers && req.headers.authorization) || '';
const email = Buffer.from(auth, 'base64').toString('ascii');
if (!isEmail.validate(email)) return { user: null };
const users = await store.users.findOrCreate({ where: { email }});
const user = users && users[0] ? users[0] : null;
return { user: { ...user.dataValues }};
},
typeDefs,
resolvers,
dataSources: () => ({
launchAPI: new LaunchAPI(),
userAPI: new UserAPI({ store })
})
});
server.listen().then(({ url }) => {
console.log(`🚀 Server ready at ${url}`);
});
Since the error I'm seeing is the result of the context's user being null, I would like to step through the context() method to inspect the headers and see whether it contains a valid (encoded) email; as you can see I've set a debugger breakpoint at the start of that function.
However, when I run node inspect src/index.js, I immediately enter the debugger for an IntrospectionQuery:
If I press the 'Resume script execution' button, I just get back immediately to the same breakpoint.
Does this have something to do with the fact that context() is an async function? How can I step through the context() method with the debugger?
In the end, I just debugged it using console.log() commands. I had accidentally put the authorization in the 'Query Variables' section rather than the 'HTTP Headers' one. Moving it to 'HTTP Headers' produces the desired result:

ReferenceError: event is not defined firebase function

I am currently developing appointment application and notification is one of the application. As a result, I have been using firebase function for notifying a user if there is new appointment booked or cancel. I am getting an error that ReferenceError: event is not defined
Node.js code
'use strict'
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotification = functions.database.ref('/Notifications/{PostKey}/{notification_id}').onWrite((data, context) => {
const user_id = context.params.PostKey;
const notification_id = context.params.notification_id;
console.log('We have a notification from : ', user_id,'this also notification_id',notification_id);
if(!event.data.val())
{
return console.log('A Notification has been deleted from the database : ', notification_id);
}
const deviceToken = admin.database().ref(`/User_Data/${user_id}/Device_Token`).once('value');
console.log('A Notification has been deleted from the database : ', deviceToken);
return deviceToken.then(result => {
const token_id = result.val();
const payload =
{
notification:
{
title:"Appointment has been booked",
body: "one of your Appointmtnt has been booked",
icon:"default"
}
};
return admin.messaging().sendToDevice(token_id,payload).then(response =>
{
return console.log('This was the notification Feature');
});
});
});
Error log
ReferenceError: event is not defined
at exports.sendNotification.functions.database.ref.onWrite (/user_code/index.js:16:9)
at cloudFunctionNewSignature (/user_code/node_modules/firebase-functions/lib/cloud-functions.js:105:23)
at cloudFunction (/user_code/node_modules/firebase-functions/lib/cloud-functions.js:135:20)
at /var/tmp/worker/worker.js:733:24
at process._tickDomainCallback (internal/process/next_tick.js:135:7)
**Database structure **
The error message is very precise. It's telling you that you used a variable called event on line 16, but you never defined it:
if(!event.data.val())

can't get params from firebase function

I'm currently trying to send a confirmation email with sendgrid API from a firebase function.
The API is not the problem though, it seems to work fine, my problem is that I can't get the child oncreate's value (Firebase function log):
TypeError: Cannot read property 'participant_id' of undefined
at exports.SendEmail.functions.database.ref.onCreate.event (/user_code/index.js:15:38)
at Object.<anonymous> (/user_code/node_modules/firebase-functions/lib/cloud-functions.js:112:27)
at next (native)
at /user_code/node_modules/firebase-functions/lib/cloud-functions.js:28:71
at __awaiter (/user_code/node_modules/firebase-functions/lib/cloud-functions.js:24:12)
at cloudFunction (/user_code/node_modules/firebase-functions/lib/cloud-functions.js:82:36)
at /var/tmp/worker/worker.js:716:24
at process._tickDomainCallback (internal/process/next_tick.js:135:7)
And here's my code:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
const SENDGRID_API_KEY = functions.config().sendgrid.key;
const sgMail = require('#sendgrid/mail');
sgMail.setApiKey(SENDGRID_API_KEY);
exports.SendEmail = functions.database.ref('participants/{participant_id}').onCreate(event => {
const participant_id = event.params.participant_id;
const db = admin.database();
return db.ref(`participants/${participant_id}`).once('value').then(function(data){
const user = data.val();
const email = {
to: user.email,
from: 'recrutement.cisssme16#ssss.gouv.qc.ca',
subject: "Bienvenue au Blitz d'embauche 2018!",
templateId: 'dd3c9553-5e92-4054-8919-c47f15d3ecf6',
substitutionWrappers: ['<%', '%>'],
substitutions: {
name: user.name,
num: user.num
}
};
return sgMail.send(email)
})
.then(() => console.log('email sent to', user.email))
.catch(err => console.log(err))
});
This is not my first firebase function. I even copied pasted previous working codes which worked fined and I still get an undefined value!
What's the problem here? Did firebase changed event.params?
Also my participant_id is an integer value (ex.: 3827), if that changes something.
Thanks in advance!
The signature of the function is wrong, take a look at this example on Handle event data:
exports.makeUppercase = functions.database.ref('/messages/{pushId}/original')
.onCreate((snapshot, context) => {
console.log('Uppercasing', context.params.pushId, original);
});
So just adjust your onCreate function and you'll be all set :)

Categories