FirebaseError: [code=invalid-argument]: Function setDoc() called with invalid data - javascript

I am using Firebase SDK's within Node-red (as specified in NPM docs they can be used for IoT devices with NODE.js).
I can use all of the CRUD methods with Firebase RealtimeDatabase.
With Firebase Firestore I can only use READ and DELETE functionality.
SET and UPDATE results in weird errors that I couldn't find answers
anywhere on the internet.
I am importing Firebase SDK's through require() inside settiings.js and functionGlobalContext so I can access them in Node-red functions:
functionGlobalContext: {
firebase: require('firebase/app'),
firebaseDatabase: require('firebase/database'),
firebaseFirestore: require('firebase/firestore'),
// os:require('os'),
// jfive:require("johnny-five"),
// j5board:require("johnny-five").Board({repl:false})
},
First I initialize my whole Firebase project with this code (and everything initializes fine without errors):
//Load data from Global contexta
const firebase = global.get('firebase');
const firebaseDatabase = global.get('firebaseDatabase');
const firebaseFirestore = global.get('firebaseFirestore');
const firebaseConfig = {
//my Firebase credentials
};
//Set up Firebase
const app = firebase.initializeApp(firebaseConfig);
const database = firebaseDatabase.getDatabase();
const firestore = firebaseFirestore.getFirestore();
//Save the database reference to Global context
global.set('app', app);
global.set('database', database);
global.set('firestore', firestore);
And here I am trying basic SET operation with Firestore:
const ft = global.get('firebaseFirestore');
const firestore = global.get('firestore');
const frankDocRef = ft.doc(firestore, "users", "frank");
await ft.setDoc(frankDocRef, {
name: "Frank",
age: 12
});
Unfortunately even though this code is ctrl+c ctrl+v from Firestore docs I get this error:
"FirebaseError: [code=invalid-argument]: Function setDoc() called with invalid data. Data must be an object, but it was: a custom Object object (found in document users/frank)"
When I use the same code inside a web app everything works fine.
There has to be something going on under the hood with Node-red
I tried creating the object using various methods and all of them resulted in the same error.
Does anybody have any idea what could be going wrong here?

Related

Platform exception while using google cloud function

I am making an app in flutter and using cloud function in firebase to update a number in Firestone,
index.js
// The Cloud Functions for Firebase SDK to create Cloud Functions and setup triggers.
const functions = require('firebase-functions');
// The Firebase Admin SDK to access Cloud Firestore.
const admin = require('firebase-admin');
admin.initializeApp();
exports.getRandomNumbers=functions.https.onCall((context)=>
{
const numbers=admin.firestore().collection('RandomNumbers').document('CurrentRandomNumber');
return numbers.add({
RandomNumber=5;
});
});
and this is the function
onPressed: () async{
final HttpsCallable callable = CloudFunctions.instance.getHttpsCallable(
functionName: 'getRandomNumbers',
);
await callable.call().catchError((error){
print('$error');
});
},
The error that is coming is
PlatformException(functionsError, Cloud function failed with exception., {code: NOT_FOUND, details: null, message: NOT_FOUND})
I also found these in my log which I may think is the reason of this
W/DynamiteModule(12544): Local module descriptor class for providerinstaller not found.
I/DynamiteModule(12544): Considering local module providerinstaller:0 and remote module providerinstaller:0
W/ProviderInstaller(12544): Failed to load providerinstaller module: No acceptable module found. Local version is 0 and remote version is 0.
NOTE
I have updated my Google Play services to the latest.
I have taken permission of the INTERNET in the manifest file.
redownloaded the .json file and checked
The code in your Callable Cloud Function is not correct.
By doing
const numbers = admin.firestore().collection('RandomNumbers').document('CurrentRandomNumber');
you are declaring a DocumentReference. A DocumentReference does not have an add() method.
If you want to get the value of a specific field of this document you should use the asynchronous get() method, as follows:
exports.getRandomNumbers = functions.https.onCall((data, context) => {
const numbers = admin.firestore().collection('RandomNumbers').document('CurrentRandomNumber');
return numbers.get().then(documentSnapshot => {
if (documentSnapshot.exists) {
console.log('Document retrieved successfully.');
const aNumber = documentSnapshot.data().aNumber;
// Do something
// ...
return null; // or return the promise returned by an asynchronous method call,
// see https://firebase.google.com/docs/functions/terminate-functions?authuser=1
} else {
console.log('Document does not exist.');
return null;
}
})
});
If you want to increment the value of a specific field of the Firestore doc, you should probably use a Transaction (it depends on your exact use case).

Firebase function not being triggered when data base is written to

My database is structured as follows Collection("Message").Document("message")
But in reality, I want any change in the database's main collection to be monitored—when a document is added. I added the message document because I thought that maybe the function wasn't being called since my documents are the auto-generated ones. However, the problem persists...
Just for background I am an iOS developer, so perhaps I am doing something wrong here:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.sendPushNotifications = functions.database.ref('/Messages/{message}').onCreate((snapshot,context) => {
console.log(snapshot);
console.log(context);
var topic = "/topics/sentMessages";
var payload = {
data: {
message : 'You recieved a new message!'
}
}
return admin.messaging().sendToTopic(topic,payload).then((response) => {
return response;
})
})
For additional background: The application receives push notifications fine when using the console whether it be directly to the testing device or using topics. This problem is strictly when writing to firebase Firestore...
When you said "Collection("Message").Document("message")" that suggested to me that you're using Firestore as your database. However, your function is targeting changes to Realtime Database, which is a completely different thing. functions.database builds function for Realtime Database. functions.firestore builds functions for Firestore. You will want to read the documentation on Firetore triggers to learn how to write them.

Cannot save “custom blob” to Firestore - ADMIN SDK

Following up to an older question I had done here now I have the same problem with the admin SDK but cannot solve this.
I am trying to save a blob to the firestore but I get:
Error: Value for argument "data" is not a valid Firestore document. Couldn't serialize object of type "Blob" (found in field data). Firestore doesn't support JavaScript objects with custom prototypes (i.e. objects that were created via the "new" operator).
Here is how I convert my custom blob to a firestore blob:
// The import
import {firestore} from "firebase";
// The function
export const parseQueue = functions.region('europe-west2').pubsub.schedule('every 1 minutes').onRun(async (context) => {
....code...
// The problem
writePromises.push(
admin.firestore()
.collection('users')
.doc(userID)
.collection('events')
.doc(<string>event.getID())
.collection('activities')
.doc(<string>activity.getID())
.collection('streams')
.doc(stream.type)
.set({
type: stream.type,
data: firestore.Blob.fromBase64String(new Buffer((Pako.gzip(JSON.stringify(stream.data), {to: 'string'})), 'binary').toString('base64')),
}))
The above crashes when I call set with the error mentioned before.
The function firestore.Blob.fromBase64String works well and I do get back a blob that is fine.
What am I doing wrong?
The "firebase" module is not part of the Admin SDK, it's the client SDK. You can't mix usage of that with firebase-admin. Stick to only symbols and APIs provided by firebase-admin if you're going to pass them as parameters to firebase-admin SDK methods. You should probably remove the module "firebase" from your project completely.
You didn't show it, but I am assuming you already imported firebase-admin like one of these:
import * as admin from 'firebase-admin'
const admin = require('firebase-admin')
Now, any time you want to use Firestore APIs, you normally go through its provided firestore object:
const firestore = admin.firestore
You are already doing this once with your call to admin.firestore().collection().... It is basically re-exporting everything from the Cloud Firestore SDK for nodejs.
The Blob object you're using with the client SDK isn't provided by the server SDK. If you want to write a byte array, you will have to use node's Buffer object directly.
doc.set({
type: stream.type,
data: new Buffer((Pako.gzip(JSON.stringify(stream.data), {to: 'string'})), 'binary')
})
Or whatever you need to do to make the correct Buffer.

How to update or set property of firestore document after .onCreate cloud function trigger

I'm currently trying to integrate Stripe with my Firebase's Cloud Firestore db through using Cloud Functions for Firebase. The onCreate trigger is happening correctly but I also want it to update or set a specific field called "customer_id" into the right document in my Users collection. I think something is a little off about how I write my function since I'm not the most experienced with javascript.
I've also tried
return admin.firestore().ref(`Users/${user.uid}/customer_id`).set(customer.id);
'use strict';
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
//const logging = require('#google-cloud/logging')();
const stripe = require('stripe')(functions.config().stripe.token);
const currency = functions.config().stripe.currency || 'USD';
// When a user is created, register them with Stripe
exports.createStripeCustomer = functions.auth.user().onCreate((user) => {
return stripe.customers.create({
email: user.email,
}).then((customer) => {
return admin.firestore().collection("Users").doc(user.uid).update({"customer_id": customer.id})
});
});
Customer gets created with Stripe no problem but the "customter_id" field is not getting updated on the Firestore db.
Print screen of the database:
Print screen of the error log:
As said in the comments, from the print screen of the error log, the code you have deployed does not correspond to the code you are referencing to in your question.
The code in your question looks correct.

Firebase user authentication trigger that writes to realtime database

exports.setupDefaultPullups = functions.auth.user()
.onCreate(
async (user) => {
const dbRef= functions.database.ref;
let vl= await (dbRef.once('value').then( (snapshot) => {
return snapshot.ref.child('userInfo/'+user.uid).set(18);
}));
return vl;
}
);
I am trying to write a trigger for some initial set-up for a new user, in Firebase. However, the above code does not work. What is wrong with it?
Basically, upon registering a new user, I would like to set up his/her property "defaultPullUps" to, say, 18, using the above path.
EDIT: I am sorry for not giving details. Initially, there was an issue with the "async" keyword, that has been fixed by updating the node.js engine. Now, I get various error messages depending on how I tweak the code. Sometimes it says "... is not a function".
EDIT': Although I agree my question is not up to par, but there is a value in it: in online documentation of Firebase authentication triggers, how to access the "main" database is not shown https://firebase.google.com/docs/functions/auth-events
EDIT'': here is the entire message:
TypeError: Cannot read property 'child' of undefined
at exports.setupDefaultPullups.functions.auth.user.onCreate.user (/srv/index.js:15:36)
at cloudFunctionNewSignature (/srv/node_modules/firebase-functions/lib/cloud-functions.js:105:23)
at /worker/worker.js:756:24
at <anonymous>
at process._tickDomainCallback (internal/process/next_tick.js:228:7)
This line makes no sense:
const dbRef= functions.database.ref;
If you want to use the Firebase Realtime Database in a Cloud Function that is triggered from another source (such as Firebase Authentication in your case), you can do so by using the Firebase Admin SDK.
For an example of this, see the Initialize Firebase SDK for Cloud Functions section of the Get started with Cloud Functions documentation. Specifically, you'll need to import and initialize is using:
// 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();
And then can access the database from your function using:
const dbRef= admin.database().ref();

Categories