The functions of the firebase tutorial do not work - javascript

I tried to implement firebase functions from the tutorial: https://firebase.google.com/docs/functions/get-started
This is my code bellow. When I try to call the url https://us-central1-skoon-5ed4d.cloudfunctions.net/addMessage I hava an "Error: could not handle the request"
'use strict';
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.addMessage = functions.https.onRequest(async (req, res) => {
const original = req.query.text;
const snapshot = await admin.database().ref('/messages').push({original: original});
Firebase console.res.redirect(303, snapshot.ref.toString());
});
exports.makeUppercase = functions.database.ref('/messages/{pushId}/original')
.onCreate((snapshot, context) => {
// Grab the current value of what was written to the Realtime Database.
const original = snapshot.val();
console.log('Uppercasing', context.params.pushId, original);
const uppercase = original.toUpperCase();
// You must return a Promise when performing asynchronous tasks inside a Functions such as
// writing to the Firebase Realtime Database.
// Setting an "uppercase" sibling in the Realtime Database returns a Promise.
return snapshot.ref.parent.child('uppercase').set(uppercase);
});
I removed async and await and in my log I have Error:
Reference.push failed: first argument contains undefined in property 'messages.original'
at validateFirebaseData (/srv/node_modules/#firebase/database/dist/index.node.cjs.js:1433:15)
at /srv/node_modules/#firebase/database/dist/index.node.cjs.js:1479:13
at Object.forEach (/srv/node_modules/#firebase/util/dist/index.node.cjs.js:837:13)
at validateFirebaseData (/srv/node_modules/#firebase/database/dist/index.node.cjs.js:1462:14)
at validateFirebaseDataArg (/srv/node_modules/#firebase/database/dist/index.node.cjs.js:1421:5)
at Reference.push (/srv/node_modules/#firebase/database/dist/index.node.cjs.js:14087:9)
at exports.addMessage.functions.https.onRequest (/srv/index.js:23:54)
at cloudFunction (/srv/node_modules/firebase-functions/lib/providers/https.js:57:9)
at /worker/worker.js:724:7
at /worker/worker.js:707:11

Related

How to reference the database that I want to write to in my cloud function?

I'm trying to write to a subset within my database and I get one console error and another error in the google cloud functions saying:
Error: Unauthorized
Your client does not have permission to the requested URL /updateFirestore.
&
Error: Value for argument "collectionPath" is not a valid resource path. Path must be a non-empty string.
at undefined. ( /workspace/index.js:18 )
at .processTicksAndRejections ( node:internal/process/task_queues:96 )
This is how my firestore is set up:
Here is where I'm trying to call my firestore database in my index.js function:
const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp(functions.config().firebase);
exports.updateFirestore = functions.database
.ref("studiopick/studio/users/{uid}")
.onWrite((change, context) => {
const uid = context.params.uid;
if (!change.after.exists()) {
return null;
}
// Grab the current value of the Realtime Database.
const data = change.after.val();
const firestoreDb = admin.firestore();
const docReference = firestoreDb.collection("studiopick/studios/" + uid);
return docReference.set(
{
TransmitterError: data.TransmitterError,
},
{merge: true},
);
});

firestore database reference doesnt work with await [duplicate]

This question already has answers here:
await is only valid in async function
(14 answers)
Closed 11 months ago.
So I'm trying to use the twitter Api to test functionality and do specific tasks. I decided to use firestore to keep the relevant data. However when I create a database reference and try to use await later on in the code, it gives me an error. This is the code.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
const {Firestore} = require('#google-cloud/firestore');
const firestore = new firestore();
const dbRef = firestore.doc('tokens/demo');
const TwitterApi = require('twitter-api-v2').default;
const twitterClient = new TwitterApi({
clientId: 'clientid',
clientSecret: 'clientsecret',
});
const callbackURL = 'http://127.0.0.1:5001/twbt-ad868/us-central1/callback';
// STEP 1 - Auth URL
exports.auth = functions.https.onRequest((request, response) => {
const { url, codeVerifier, state } = twitterClient.generateOAuth2AuthLink(
callbackURL,
{ scope: ['tweet.read', 'tweet.write', 'users.read', 'offline.access'] }
);
// store verifier
await dbRef.set({ codeVerifier, state });
response.redirect(url);
});
exports.callback = functions.https.onRequest((request, response) => {
});
exports.tweet = functions.https.onRequest((request, respone) => {});
and this is the error I get
await dbRef.set({ codeVerifier, state });
^^^^^
SyntaxError: await is only valid in async function
I've tried using this code instead to reference the json file in firestore, but I still get the same error
const dbRef = admin.firestore().doc('tokens/demo');
I'm assuming this is because my program isn't properly accessing the database in firestore? When I run this command
gcloud firestore operations list
I get
Listed 0 items.
If this is the case I'm not sure how to fix this and have my code access the database properly
Thank you in advance for any help you can provide me.
You must create an async function in order to have an await since it requires a promise.
async function () { await dbRef.set({ codeVerifier, state });}

Setting collection name in Firebase function

Just starting to use Firebase functions and have the sample working, but confused because the update event doesn't occur if I change the 'messages' collection to a different name, eg 'listings'. I change the word 'messages' in two places, on the 'add' and the 'makeUppercase' line. I get the response OK, it writes the data to the collection, but doesn't fire the event. Must be simple, but can't google it.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.addMessage = functions.https.onRequest(async (req, res) => {
// Grab the location parameter.
const inputcode = req.query.code || 'blank';
// Push the new message into Cloud Firestore using the Firebase Admin SDK.
const writeResult = await admin.firestore().collection('messages').add({inputcode: inputcode});
// Send back a message that we've succesfully written the message
res.json({result: `Message with ID: ${writeResult.id} added.`});
});
exports.makeUppercase = functions.firestore.document('/messages/{documentId}')
.onCreate((snap, context) => {
// Grab the current value of what was written to Cloud Firestore.
const inputcode = snap.data().inputcode;
// Access the parameter `{documentId}` with `context.params`
functions.logger.log('Uppercasing', context.params.documentId, inputcode);
const areacode = inputcode.toUpperCase();
const written = new Date();
return snap.ref.set({written, areacode}, {merge: true});
});
I'm using the local firebase emulator to do this test, by the way.
This is the new version, ony changing 'messages' to 'vvvv' in two places.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.addMessage = functions.https.onRequest(async (req, res) => {
// Grab the location parameter.
const inputcode = req.query.code || 'blank';
// Push the new message into Cloud Firestore using the Firebase Admin SDK.
const writeResult = await admin.firestore().collection('vvvvv').add({inputcode: inputcode});
// Send back a message that we've succesfully written the message
res.json({result: `Message with ID: ${writeResult.id} added.`});
});
exports.makeUppercase = functions.firestore.document('/vvvvv/{documentId}')
.onCreate((snap, context) => {
// Grab the current value of what was written to Cloud Firestore.
const inputcode = snap.data().inputcode;
// Access the parameter `{documentId}` with `context.params`
functions.logger.log('Uppercasing', context.params.documentId, inputcode);
const areacode = inputcode.toUpperCase();
const written = new Date();
return snap.ref.set({written, areacode}, {merge: true});
});
OK. Doug, your suggestion sank in after an hour or so! I've restarted everything and think that I understand. If I change the name in those two places, without restarting, the collection.add function takes place and I can see the record in the new collection, but the onCreate event didn't fire. I had to restart the whole service to restart buth parts. I was getting confused because one part was working and not the other. Thanks for your patience.

firebase cloud functions Cannot read property 'ref' of undefined

when i want to update Cloud Firestore from Realtime Database i deployed bellow code and i get error.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
const firestore = functions.firestore;
exports.onUserStatusChange = functions.database
.ref('/status/{userId}')
.onUpdate(event => {
var db = admin.firestore();
//const usersRef = firestore.document('/users/' + event.params.userId);
const usersRef = db.collection("users");
var snapShot = event.data;
return event.data.ref.once('value')
.then(statusSnap => snapShot.val())
.then(status => {
if (status === 'offline'){
usersRef
.doc(event.params.userId)
.set({
online: false,
last_active: Date.now()
}, {merge: true});
}
})
});
TypeError: Cannot read property 'ref' of undefined
at exports.onUserStatusChange.functions.database.ref.onUpdate.event (/user_code/index.js:18:20)
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)
It looks like you got the code for a beta version of Cloud Functions for Firebase. The syntax has changed in the 1.0 version. From the documentation on upgrading your Cloud Functions:
or onWrite and onUpdate events, the data parameter has before and after fields. Each of these is a DataSnapshot with the same methods available in admin.database.DataSnapshot. For example:
Before (<= v0.9.1)
exports.dbWrite = functions.database.ref('/path').onWrite((event) => {
const beforeData = event.data.previous.val(); // data before the write
const afterData = event.data.val(); // data after the write
});
Now (>= v1.0.0)
exports.dbWrite = functions.database.ref('/path').onWrite((change, context) => {
const beforeData = change.before.val(); // data before the write
const afterData = change.after.val(); // data after the write
});
So you will want to use:
.onUpdate((change, context) => { to declare the funtcion, instead of .onUpdate(event => {
use change.after to refer to the data, instead of event.data
use change.after.ref.once('value'), instead of event.data.ref.once('value')
Since it seems that this code is mostly copied from somewhere, I'd recommend getting an updated version from there. For example, the Firestore documentation that your code is likely based on, contains an up-to-date example here: https://firebase.google.com/docs/firestore/solutions/presence#updating_globally
Try to change below code, as firebase functions on events have two properties any more. So, ref position is:
.onUpdate((event,context) => {
....
return event.ref.once('value')
...
event.data does not exist anymore, instead event.val() for more info and event has properties like

Cloud Functions for Firebase timeout

Simple cloud function to get database data is not working.
getusermessage() is not working
Error:
Function execution took 60002 ms, finished with status: 'timeout'
Index.JS for getting database result.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
const cors = require('cors')({origin: true});
// Take the text parameter passed to this HTTP endpoint and insert it into the
// Realtime Database under the path /messages/:pushId/original
exports.addMessage = functions.https.onRequest((req, res) => {
// Grab the text parameter.
const original = req.query.text;
// Push the new message into the Realtime Database using the Firebase Admin SDK.
admin.database().ref('/messages').push({original: original}).then(snapshot => {
// Redirect with 303 SEE OTHER to the URL of the pushed object in the Firebase console.
res.redirect(303, snapshot.ref);
});
});
// Listens for new messages added to /messages/:pushId/original and creates an
// uppercase version of the message to /messages/:pushId/uppercase
exports.makeUppercase = functions.database.ref('/messages/{pushId}/original')
.onWrite(event => {
// Grab the current value of what was written to the Realtime Database.
const original = event.data.val();
console.log('Uppercasing', event.params.pushId, original);
const uppercase = original.toUpperCase();
// You must return a Promise when performing asynchronous tasks inside a Functions such as
// writing to the Firebase Realtime Database.
// Setting an "uppercase" sibling in the Realtime Database returns a Promise.
return event.data.ref.parent.child('uppercase').set(uppercase);
});
var db = admin.database();
exports.getUserMessage = functions.https.onRequest((req, res) => {
var query = db.ref("messages").orderByKey();
query.once("value")
.then(function(snapshot) {
snapshot.forEach(function(childSnapshot) {
var key = childSnapshot.key;
// childData will be the actual contents of the child
var childData = childSnapshot.val();
});
});
});
What am O doing wrong?
You didn't say which of your three functions is timing out, but I'll take a guess at which one. Your HTTPS function getUserMessage isn't generating a response to the client. Cloud Functions will wait for 60 seconds (by default) for it to generate a response, and if it doesn't, it will kill the function and leave that message in the log.
Every code path in an HTTPS function should generate some response to the client.
You can set the timeout and memory using runWith during function declaration,
exports.getUserMessage = functions.runWith({ memory: '2GB', timeoutSeconds: 360 }).https.onRequest(

Categories

Resources