I am trying to write a Firebase Cloud function which would write the current time inside the database whenever called:
const admin = require('firebase-admin');
const functions = require('firebase-functions');
admin.initializeApp(functions.config().firebase);
exports.pushDateOfCall = functions.https.onRequest((req, res) => {
const currentTime = new Date();
return admin.database().ref('/dates').push({currentTime: currentTime}).then((snapshot) => {
return res.send("Complete");
}).catch((error) => res.send("Something went wrong"));
});
After deploying the function and calling it from the function's URL, nothing is written inside the database.
Output of firebase functions logs:
Function execution took 1358 ms, finished with status code: 304
P.S. I am running the link from incognito since I wish that whoever calls the link (both authorised and unauthorised) is able to use it.
const currentTime = new Date();
Here currentTime is an object. If you want to store the String of the date, use String(currentTime) as
return admin.database().ref('/dates').push({currentTime: String(currentTime)})
#hkchakladar is right, changing to {currentTime: String(currentTime)} will solve the problem.
However, note that you don't need to return res.send() nor to return the promise returned by the asynchronous push() method. This is shown in the official Firebase video about HTTP Cloud Function, see https://www.youtube.com/watch?v=7IkUgCLr5oA
So your code may be as follows:
exports.pushDateOfCall = functions.https.onRequest((req, res) => {
const currentTime = new Date();
admin
.database()
.ref('dates')
.push({ currentTime: String(currentTime) })
.then(ref => {
res.send('Complete');
})
.catch(error => res.status(500).send('Something went wrong'));
});
Related
I am trying to interact with firebase firestore from my cloud function. The cloud functions looks like the following:
const admin = require("firebase-admin");
const functions = require("firebase-functions");
admin.initializeApp();
const db = admin.firestore();
exports.addVote = functions.https.onCall((data, context) => {
return db
.doc("sdd-enheter/enhet/votes/voteID")
.set({ user: "user", vote: 0 });
});
When calling the function from the client side I get a firebase internal error, indicating that the function has been called but throws an error. What should I do to fix this?
Your function needs to return a promise or otherwise terminate by throwing an https error. Throwing the https error will give the client back a relevant error that it can handle, so consider making that a habit. The function below covers both of those bases. If you still get an error then share that error with us as it appears in the console's function log.
exports.addVote = functions.https.onCall((_data, _context) => {
const db = admin.firestore();
try {
return db.doc("sdd-enheter/enhet/votes/voteID").set({user: "user", vote: 0});
} catch (error) {
throw new functions.https.HttpsError("unknown", "Failed to add vote.", error);
}
});
When I use Firebase Cloud Functions in my Flutter app to create a document inside a collection it works:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
exports.onCreatePost = functions.firestore
.document("/posts/{postId}")
.onCreate(async (snap, context) => {
const doc = snap.data()
const creatorId = doc.creatorId
admin.firestore().collection('feeds').doc(creatorId).set({
Id: creatorId,
isRead: false,
timestamp: admin.firestore.FieldValue.serverTimestamp(),
})
});
But when I try to add the same document inside a subcollection in that document, it does not work:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
exports.onCreatePost = functions.firestore
.document("/posts/{postId}")
.onCreate(async (snap, context) => {
const doc = snap.data()
const creatorId = doc.creatorId
admin.firestore().collection('feeds').doc(creatorId).collection('feedItems').doc(context.params.postId).set({
Id: creatorId,
isRead: false,
timestamp: admin.firestore.FieldValue.serverTimestamp(),
})
});
What am I doing wrong? I do see that the cloud function was completed successfully in the logs, but the docment is not created in my Cloud Firestore.
I would expect neither function to work reliably, because you aren't returning a promise that resolves after the asynchronous work is complete. If you don't return a promise, then Cloud Functions might terminate your function before it's done.
Minimally, you should return the promise returned by set().
return admin.firestore()
.collection('feeds')
.doc(creatorId)
.collection('feedItems')
.doc(context.params.postId)
.set(...)
You should also check the Cloud Functions log for errors. Errors will not show up in your app since the code is running completely outside of it.
I suggest also reviewing the documentation on this.
I want to get data from my database on fire base and want to save that data to amount amount: snapshot, I did apply this const snapshot = firestore.collection('payment').doc(context.params.amount).get(); does that works in the same way? but I am getting an error that context is undefined.
I actually want to get data from database.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
const firestore= admin.firestore();
const stripe = require('stripe')('');
const snapshot = firestore.collection('payment').doc(context.params.amount).get();
const customer = stripe.customers.create({
email: 'customer#example1.com',
});
stripe.customers
.create({
email: 'foo-customer#example.com',
})
.then((customer) => {
return stripe.customers.createSource(customer.id, {
source: 'tok_visa',
});
})
.then((source) => {
return stripe.charges.create({
amount: snapshot,
currency: 'usd',
customer: source.customer,
});
})
.then((charge) => {
// New charge created on a new customer
})
.catch((err) => {
// Deal with an error
});
you are trying to get amount through accessing params through context,
depends on your error, this means context is undefined which means you are trying to get params of undefined. you need to explain what is context means here, is it a global variable? is this code inside a cloud function? if yes you need to move this declaration const snapshot = firestore.collection('payment').doc(context.params.amount).get();
inside your cloud function ,
this is an example of firebase cloud function
I am writing a Firebase database trigger function to push notifications to several users. For consistency I would like to batch all write operations, but I am having trouble creating the batch.
How can I get a reference to the database from data snapshot?
const functions = require('firebase-functions')
const admin = require('firebase-admin')
exports.onNoteCreate = functions
.region('europe-west1')
.database
.ref('/notes/{noteId}')
.onCreate((snapshot, context) => {
//Get a reference to the database - this does not work!
const db = snapshot.getRef()
...
const notificationObject = {"test": true}
//Run database batched operation - prepare batch
let batch = db.batch()
peopleToAlert.forEach((personId, index) => {
//Write notification to all affected people
const notificationId = db.ref().push()
const batchWrite = db.collection(`/notifications/${personId}/notes`).doc(notificationId)
batch.set(batchWrite, notificationObject)
})
//Commit database batch operation
return batch.commit().then(() => {
return new Promise( (resolve, reject) => (resolve()))
}).catch( (err) => {
return new Promise( (resolve, reject) => (reject(err)))
})
})
I have also tried the approach below to no avail
const db = admin.database()
Any clarification much appreciated! Kind regards /K
To get the root Reference of the Database from a DataSnapshot, do as follows:
const snapshotRef = snapshot.ref.root;
See https://firebase.google.com/docs/reference/js/firebase.database.DataSnapshot#ref and https://firebase.google.com/docs/reference/js/firebase.database.Reference.html#root
HOWEVER, you are triggering your Cloud Function with a Realtime Database trigger while the concept of batched write is for Firestore, which is a different database service. So you cannot use the root Reference of the Realtime Database to create a Firestore WriteBatch.
So if you want to create a WriteBatch within your Cloud Function you need to get it from the Admin SDK, as follows:
let batch = admin.firestore().batch();
See https://firebase.google.com/docs/reference/admin/node/admin.firestore
I have an app that takes a New York Times recipe URL, and converts the list of ingredients into a shopping to-do list.
Because the New York Times uses React, none of the data is available via standard scraping - the index.html is mostly blank. I have to use a library like NightmareJS, which uses an Electron browser to fully construct the DOM (including the Javascript) so that I can then scrape that constructed-DOM for data.
But this doesn't seem to work. Here's the code I have included in my /functions/index.js file:
// The Cloud Functions for Firebase SDK to create Cloud Functions and setup triggers.
const functions = require('firebase-functions')
// The Firebase Admin SDK to access the Firebase Realtime Database.
const admin = require('firebase-admin')
admin.initializeApp(functions.config().firebase)
const Nightmare = require('nightmare')
const Actions = require('nightmare-react-utils').Actions
exports.listify = functions.https.onRequest((req, res) => {
console.log("YOU ARE NOW INSIDE THE LISTIFY FUNCTION!")
Nightmare.action(...Actions)
const nightmare = new Nightmare({ show: false })
const selector = 'ul.recipe-ingredients'
const queryUrl = req.query.url
nightmare
.goto(queryUrl)
.wait()
.evaluate((selector) => {
console.log("YOU ARE NOW INSIDE THE EVALUATE!")
const recipeIngredientsObject = document.querySelector(selector).children
const result = []
const ingredientKeys = Object.keys(recipeIngredientsObject)
ingredientKeys.forEach((key) => {
const ingredientObject = recipeIngredientsObject[key]
const quantityAndIngredient = ingredientObject.children
result.push({
"quantity": quantityAndIngredient[0].innerText,
"ingredient": quantityAndIngredient[1].innerText
})
})
return result
}, selector)
})
When I call this Function from my front-end, I see the first console log in my Firebase logs - "YOU ARE NOW INSIDE THE LISTIFY FUNCTION!" - but I do not see the second message: "YOU ARE NOW INSIDE THE EVALUATE!"
Can I not use NightmareJS with Firebase Functions?
The console.log message will never appear. When you run evaluate, that function is executed inside the context of the headless browser, so will not log to terminal.
Try something like...
.evaluate((selector) => {
return document.querySelector(selector)
}, selector)
.end()
.then(console.log)
To see if it's working at all.