Using a Firestore Cloud Functions - node.js

I have this problem. In my code depends of choosen project name I want to retrieve a document from another collection. I am use
exports.updateUser = functions.firestore
.document('Users/{userId}')
.onUpdate((change, context) => {
const newValue = change.after.data().currentProject;
console.log("Project changed to - " + newValue);
const previousValue = change.before.data().currentProject;
console.log("from - " + previousValue);
// ### FROM HERE DOES NOT WORK ###
const projectId = firestore.collection('Projects')
.where('name', '==', newValue).get()
.then(doc => {
console.log(doc.data().id);
return doc.data().id;
});
});
And I get an error
ReferenceError: firestore is not defined
at exports.updateUser.functions.firestore.document.onUpdate (/user_code/index.js:25:14)
So maybe I need another dependencies ?
My package.json is
{
"name": "functions",
"description": "Cloud Functions for Firebase",
"scripts": {
"lint": "eslint .",
"serve": "firebase serve --only functions",
"shell": "firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log"
},
"dependencies": {
"firebase-admin": "~5.12.0",
"firebase-functions": "^1.0.1"
},
"devDependencies": {
"eslint": "^4.12.0",
"eslint-plugin-promise": "^3.6.0"
},
"private": true
}
What I am missing? Please give a hint

You will need to use the Firebase Admin SDK to access Firestore collections that are outside of the scope that your function was triggered on. Typically this will look something like:
admin.firestore().collection('Projects')...

Related

Use Node-Fetch in TypeScript with CloudFunctions

So Im using Cloud Functions from Firebase with TypeScript
I want to import node-fetch like:
import * as fetch from "node-fetch";
but it doesn't import correctly:
when I try to use fetch like this:
fetch("https://payments.sandbox.braintree-api.com/graphql", {
method: "POST",
headers: {
"Authorization":
"bnIzdm5nZHlqempjNnQ3bTo0ZjMxYjQ5YjA2MDNjN2RkMjZhM2UyMGE3M2E3MWVlNw==",
"Braintree-Version": "2022-08-13",
"Content-Type": "application/json",
},
body: JSON.stringify({
query,
}),
})
I get following problem:
This expression is not callable.
Type 'typeof import(".../node_modules/node-fetch/#types/index")' has no call signatures.
I was wondering whether I need to add a dependency after running:
npm install node-fetch
because in my package.json
{
"name": "functions",
"scripts": {
"lint": "eslint --ext .js,.ts .",
"build": "tsc",
"build:watch": "tsc --watch",
"serve": "npm run build && firebase emulators:start --only functions",
"shell": "npm run build && firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log"
},
"engines": {
"node": "16"
},
"main": "lib/index.js",
"dependencies": {
"firebase-admin": "^10.0.2",
"firebase-functions": "^3.18.0"
},
"devDependencies": {
"#typescript-eslint/eslint-plugin": "^5.12.0",
"#typescript-eslint/parser": "^5.12.0",
"eslint": "^8.9.0",
"eslint-config-google": "^0.14.0",
"eslint-plugin-import": "^2.25.4",
"firebase-functions-test": "^0.2.0",
"typescript": "^4.5.4"
},
"private": true
}
there is no node-fetch dependency
if this is the case how can I fix my problem?
As mentioned here, you have to add this dependency explicitly in the package.json, as node-fetch is not a built-in module and will need installation.
You can run npm install node-fetch on your local machine, but the Cloud Functions deploy doesn't work this way.
HTH, else let me know.

Firebase Cloud Function - Parsing error: Unexpected token =>

I have a problem during deploy the functions into Cloud Function. I do believe before I put the const admin = require('firebase-admin') and admin.initializeApp() there will be a problem after I place these two, but before I place the two-line there is no problem occurred.
This is my full code for index.js
const functions = require("firebase-functions");
const express = require('express');
const cors = require('cors');
const admin = require('firebase-admin');
admin.initializeApp();
const app = express();
app.get('/', (req, res) => {
});
app.post("/", async (req, res) => {
const user = req.body;
await admin.firestore().collection("users").add(user);
res.status(201).send();
});
exports.user = functions.https.onRequest(app)
package.json
{
"name": "functions",
"description": "Cloud Functions for Firebase",
"scripts": {
"lint": "eslint .",
"serve": "firebase emulators:start --only functions",
"shell": "firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log"
},
"engines": {
"node": "12"
},
"main": "index.js",
"dependencies": {
"firebase-admin": "^9.2.0",
"firebase-functions": "^3.11.0"
},
"devDependencies": {
"eslint": "^7.6.0",
"eslint-config-google": "^0.14.0",
"firebase-functions-test": "^0.2.0"
},
"private": true
}
.eslintrc.js
module.exports = {
root: true,
env: {
es6: true,
node: true,
},
extends: [
"eslint:recommended",
"google",
],
rules: {
quotes: ["error", "double"],
},
};
Try adding the second part to your package.json:
{
"parserOptions": {
"ecmaVersion": 2017
}
}
"parser": "babel-eslint" - add this to your.eslintrc.js and run npm install babel-eslint --save this will resolve the issue.

Google cloud function with puppeteer does not work, even though it works in firebase functions emulator

So I made this function. It works correctly in firebase functions emulator, but when i use firebase deploy --only functions, I am getting errors like the ones on the picture. Any idea what I am doing wrong?
Here is my package.json
{
"name": "functions",
"scripts": {
"lint": "tslint --project tsconfig.json",
"build": "tsc",
"serve": "npm run build && firebase serve --only functions -P default",
"serve-dev": "npm run build && firebase serve --only functions -P staging",
"shell": "npm run build && firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions -P default",
"deploy-dev": "firebase deploy --only functions -P staging",
"logs": "firebase functions:log"
},
"main": "lib/index.js",
"dependencies": {
"#google-cloud/functions-framework": "^1.7.1",
"#types/node-fetch": "^2.3.3",
"firebase-admin": "^9.4.1",
"firebase-functions": "^3.11.0",
"golang": "^0.1.5-stable",
"node-fetch": "^2.5.0",
"puppeteer": "5.4.1",
"xml2js": "^0.4.19"
},
"devDependencies": {
"tslint": "^5.20.1",
"typescript": "^3.9.2"
},
"private": true,
"engines": {
"node": "10"
}
}
Here is the code of the function, it is in TypeScript, which after building becomes js ofc:
export const RecurringTradingUpdate = functions.https.onRequest(async (request, response) => {
const browser = await puppeteer.launch({
headless: true
});
const page = await browser.newPage();
await page.goto('website');
await page.waitFor(2000);
//await page.click('input[type=password]');
await page.click('#inputPassword');
await page.keyboard.sendCharacter('password')
//await page.click('button[type=submit]');
await page.click('#clickPassword');
await page.waitFor(2000);
//await page.click('button[type=submit]');
await page.click('#submit');
await page.waitFor(120000)
response.send("All done.")
});

firebase show error when i try to run functions locally

Showing the Firebase error whenever I run the function locally using emulator in CLI
$ firebase emulators:start --only functions
Starting emulators: ["functions"]
functions: Using node#8 from host.
functions: Emulator started at http://localhost:5001
functions: Watching "E:\dir\functions" for Cloud Functions...
Error: Cannot find module 'E:\dir\functions'
at Function.Module._resolveFilename (module.js:548:15)
at Function.Module._load (module.js:475:25)
at Module.require (module.js:597:17)
at require (internal/module.js:11:18)
at C:\Users\d\AppData\Roaming\npm\node_modules\firebase-tools\lib\emulator\functionsEmulatorRuntime.js:459:29
at Generator.next ()
at C:\Users\d\AppData\Roaming\npm\node_modules\firebase-tools\lib\emulator\functionsEmulatorRuntime.js:7:71
at new Promise ()
at __awaiter (C:\Users\d\AppData\Roaming\npm\node_modules\firebase-tools\lib\emulator\functionsEmulatorRuntime.js:3:12)
at main (C:\Users\d\AppData\Roaming\npm\node_modules\firebase-tools\lib\emulator\functionsEmulatorRuntime.js:421:12)
Your function was killed because it raised an unhandled error.
I use typescript to write cloud functions.
here is my index.ts
import * as functions from 'firebase-functions';
import * as admin from "firebase-admin";
var cert = require("./skey.json");
admin.initializeApp({
credential: admin.credential.cert(cert),
databaseURL: "https://bhau-tk.firebaseio.com"
});
exports.basicHTTP = functions.https.onRequest((req, res) => {
res.send("Hello world!!");
})
package.json contains
{
"name": "functions",
"scripts": {
"lint": "tslint --project tsconfig.json",
"build": "tsc",
"serve": "npm run build && firebase serve --only functions",
"shell": "npm run build && firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log"
},
"engines": {
"node": "8"
},
"main": "lib/index.js",
"dependencies": {
"firebase-admin": "~7.0.0",
"firebase-functions": "^2.3.0",
"firebase-functions-test": "^0.1.6"
},
"devDependencies": {
"tslint": "^5.12.0",
"typescript": "^3.2.2"
},
"private": true
}
and project structure is
You should keep in mind that your project configuration is compiling TS sources files under src and putting the resulting JavaScript files in lib. So, you should refer to things in your functions folder relative to that location.
Since your compiled index.js is in lib, and your skey.json file is under src, you will have to refer to it that way:
var cert = require("../src/skey.json");
However, I wouldn't do it that way. I'd put skey.json in the functions folder (since it's not source code), and refer to it like this:
var cert = require("../skey.json");

TypeError: Cannot read property 'from' of undefined

I'm trying to code a function that triggers when a user gets a new comment and sends a notification.Comments are stored in /Users/{user_id}/Notifications/{notification_id}. Users save their device notification tokens to /users/{userID}
'use strict'
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotif = functions.firestore.document('Users/{user_id}/Notifications/{notification_id}')
.onWrite((change,context) =>
{
const user_id = context.params.user_id;
const notification_id = context.params.notification_id;
return admin.firestore().collection('Users').document(user_id).collection('Notifications').document(notification_id).get().then(queryResult=>{
const from_user_id = queryResult.data().From;
const from_data = admin.firestore().collection('Users').document(from_user_id).get();
const to_data = admin.firestore().collection('Users').document(user_id).get();
return Promise.all([from_data, to_data]).then(result => {
const from_name = result[0].data().From;
const to_name = result[1].data().From;
console.log("FROM: " + from_name + "TO: " + to_name);
});
});
});
And here's the package.json file. Everything is up-to-date
{
"name": "functions",
"description": "Cloud Functions for Firebase",
"scripts": {
"serve": "firebase serve --only functions",
"shell": "firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log"
},
"dependencies": {
"firebase-admin": "^6.4.0",
"firebase-functions": "^2.1.0"
},
"private": true
}
{
"name": "functions",
"description": "Cloud Functions for Firebase",
"scripts": {
"serve": "firebase serve --only functions",
"shell": "firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log"
},
"dependencies": {
"firebase-admin": "^6.4.0",
"firebase-functions": "^2.1.0"
},
"private": true
}
Firebase gives the following error:
TypeError: Cannot read property 'from' of undefined
at Promise.all.then.result (/user_code/index.js:21:47)
at process._tickDomainCallback (internal/process/next_tick.js:135:7)
Please check the length of your array (result). You should log result.
return Promise.all([from_data, to_data]).then(result => {
console.log(result);
const from_name = result[0].data().From;
const to_name = result[1].data().From;
console.log("FROM: " + from_name + "TO: " + to_name);
});

Resources