I'm developing an iOS app and now I'm stuck with Firebase deploy functions. I'm trying to send push notifications and I prepared the codes like below.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.pushNotifications = functions.database.ref('/messages/{messageId}')
.onCreate(event => {
const data = event.data;
const fromId = data.fromId;
const toId = data.toId;
const message = data.message;
console.log(fromId + ' sent a message to' + toId);
return admin.database().ref('/users/' + fromId).once('value', snapshot => {
var user = snapshot.val();
var payload = {
notification: {
title: user.username,
body: message
}
}
admin.messaging().sendToDevice(user.fcmToken, payload)
.then(function(response) {
// See the MessagingDevicesResponse reference documentation for
// the contents of response.
console.log("Successfully sent message:", response);
})
.catch(function(error) {
console.log("Error sending message:", error);
});
})
Database structure:
messages - messageId -fromId
└toId
└Message
└ messageId -fromId
└toId
└Message
.
.
.
And this is the error message.
37:1 error Parsing error: Unexpected token
✖ 1 problem (1 error, 0 warnings)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! functions# lint: `eslint .`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the functions# lint script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! /Users/...
Error: functions predeploy error: Command terminated with non-zero exit code1
Also in the log, I get errors like:
TypeError: Cannot read property 'fromId' of undefined
Is the error occurring because I'm not fetching fcmToken right?
I've never coded with JavaScirpt. I would appreciate any suggestion!
Change this:
exports.pushNotifications = functions.database.ref('/messages/{messageId}')
.onCreate(event => {
const data = event.data;
const fromId = data.fromId;
const toId = data.toId;
const message = data.message;
into this:
exports.pushNotifications = functions.database.ref('/messages/{messageId}')
.onCreate((snap,context) => {
const data = snap.val();
const fromId = data.fromId;
const toId = data.toId;
const message = data.message;
});
Check here for more info:
https://firebase.google.com/docs/functions/beta-v1-diff
You are most likely running v1 of firebase functions, which is the latest version which brought quite a few changes to the api. You can read more about the changes here. Specifically, you want to change your event => parameter to (snap, context) =>
exports.dbWrite = functions.database.ref('/path').onCreate((snap, context) => {
const data = snap.val();
const { fromId, toId } = data;
...
});
Related
Hello everyone I have an issue that I did not manage to find the solution to.
I have an index.js file that I use to deploy functions to firebase.
I use Axios for the request. In order to use the Axios package I have to use the world import, but this generates an error.
I tried everything but nothing seems to work in the sense that, if I use const .... instead of import the file gets deployed but the function does not work anymore because it does not find Axios when using const ... , it works just when I use import.
This is the code and below that it is the error:
Code :
const admin = require("firebase-admin");
import { default as axios } from "axios";
admin.initializeApp();
const database = admin.firestore();
const page = 1;
const fiat = "RON";
const tradeType = "BUY";
const asset = "USDT";
const payTypes = ["ING"];
let finalData = [];
let tempDataBeforeProccessing = [];
const baseObj = {
page,
rows: 20,
publisherType: null,
asset,
tradeType,
fiat,
payTypes,
};
const stringData = JSON.stringify(baseObj);
const getTheData = function() {
tempDataBeforeProccessing=[];
axios.post("https://p2p.binance.com/bapi/c2c/v2/friendly/c2c/adv/search", baseObj, {
hostname: "p2p.binance.com",
port: 443,
path: "/bapi/c2c/v2/friendly/c2c/adv/search",
method: "POST",
headers: {
"Content-Type": "application/json",
"Content-Length": stringData.length,
},
}).then((res)=>{
tempDataBeforeProccessing=res.data.data;
});
};
const processData = function() {
finalData=[];
let obj = [];
for (let i = 0; i < tempDataBeforeProccessing.length; i++) {
let payTypesz = "";
for (let y = 0; y <
tempDataBeforeProccessing[i]["adv"]["tradeMethods"].length; y++) {
payTypesz +=
tempDataBeforeProccessing[i]["adv"]["tradeMethods"][y]["identifier"];
if (y <
tempDataBeforeProccessing[i]["adv"]["tradeMethods"].length - 1) {
payTypesz += ", ";
}
}
obj = {
tradeType: tempDataBeforeProccessing[i]["adv"]["tradeType"],
asset: tempDataBeforeProccessing[i]["adv"]["asset"],
fiatUnit: tempDataBeforeProccessing[i]["adv"]["fiatUnit"],
price: tempDataBeforeProccessing[i]["adv"]["price"],
surplusAmount:
tempDataBeforeProccessing[i]["adv"]["surplusAmount"],
maxSingleTransAmount:
tempDataBeforeProccessing[i]["adv"]["maxSingleTransAmount"],
minSingleTransAmount:
tempDataBeforeProccessing[i]["adv"]["minSingleTransAmount"],
nickName:
tempDataBeforeProccessing[i]["advertiser"]["nickName"],
monthOrderCount:
tempDataBeforeProccessing[i]["advertiser"]["monthOrderCount"],
monthFinishRate:
tempDataBeforeProccessing[i]["advertiser"]["monthFinishRate"],
payTypes: payTypesz,
};
finalData.push(obj);
}
console.log(finalData);
};
const uploadData = function() {
database.collection("SebiBinanceSale").doc("BCR Bank").delete();
for (let i = 0; i < finalData.length; i++) {
database.collection("SebiBinanceSale").doc("BCR Bank")
.collection("1").doc(i.toString())
.set({
"tradeType": finalData[i]["tradeType"],
"asset": finalData[i]["asset"],
"fiatUnit": finalData[i]["fiatUnit"],
"price": finalData[i]["price"],
"surplusAmount": finalData[i]["surplusAmount"],
"maxSingleTransAmount": finalData[i]["maxSingleTransAmount"],
"minSingleTransAmount": finalData[i]["minSingleTransAmount"],
"nickName": finalData[i]["nickName"],
"monthOrderCount": finalData[i]["monthOrderCount"],
"monthFinishRate": finalData[i]["monthFinishRate"],
"payTypes": finalData[i]["payTypes"],
});
}
console.log("Succes Upload of the data ");
};
const entireCall = function() {
getTheData();
processData();
uploadData();
};
entireCall();
Error :
2:1 error Parsing error: 'import' and 'export' may appear only with
'sourceType: module'
✖ 1 problem (1 error, 0 warnings)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! functions# lint: `eslint .`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the functions# lint script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! /Users/ivanoiualexandrupaul/.npm/_logs/2022-10-29T11_17_45_143Z-debug.log
Error: functions predeploy error: Command terminated with non-zero exit code1
If someone manages to give me a hint than you so much.
Try out import * as axios from "axios";
How to clone a repository with SSH using simple-git?
I'm trying to clone using this code
const git: SimpleGit = simpleGit();
const sshUri = 'git#..........'
const localPath = '/usr/workspace';
git
.clone(
sshUri,
localPath
).then((data) => {
console.log('success');
}).catch((err) => {
console.log(err);
});
But I am getting an exception
Permission denied (publickey).
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
If your git repo is private, you will need to generate SSH key and add this key to your GIT account.
To generate SSH Key:
https://docs.github.com/en/authentication/connecting-to-github-with-ssh
Add your SSH to git account:
You can find it here
https://github.com/settings/keys
Code example
private async cloneRepo() {
const gitSSH = 'FILL YOUR SSH GIT ADDRESS';
const sourceDir = path.resolve(`${os.tmpdir()}/${this.projectKey}`);
const sshKnownHosts = path.resolve(`${process.cwd()}/settings/ssh/known_hosts`)
const sshKey = path.resolve(`${process.cwd()}/settings/ssh/id_ed25519`)
const GIT_SSH_COMMAND = `ssh -o UserKnownHostsFile=${sshKnownHosts} -o StrictHostKeyChecking=no -i ${sshKey}`;
console.log(sourceDir);
const git: SimpleGit = simpleGit()
.env('GIT_SSH_COMMAND', GIT_SSH_COMMAND)
.clean(CleanOptions.FORCE);
await git.clone(gitSSH, sourceDir, ['-b', 'YOUR-BRANCH-NAME', '--single-branch'])
.then(() => console.log('finished'))
.catch((err) => console.error('failed: ', err));
}
I have the following very simple Node project:
https://github.com/tlg-265/chokidar-issue
$ git clone https://github.com/tlg-265/chokidar-issue
$ cd chokidar-issue
$ npm i
$ npm run watch-changes
which basically takes care of detecting changes on file:
/profiles/bill-gates.json
and do an action just after that.
In order to do that I have the following file:
/profile-watcher.js
const fs = require('fs-extra');
const colors = require('colors/safe');
const chokidar = require('chokidar');
const path_file = `profiles/bill-gates.json`;
console.log(`Current Profile: ${colors.red.bgBrightYellow(path_file)}`);
let profile_before = {};
chokidar.watch(path_file).on('change', async (path) => {
console.log();
console.log(`${colors.blue.bgYellow(`->`)} Profile changed: ${path}`);
fs.readFile(path, (err, profile_json) => {
console.log(`->${profile_json}<-`);
let profile = JSON.parse(profile_json);
if (JSON.stringify(profile) != JSON.stringify(profile_before)) {
console.log('The profile has changed.');
profile_before = profile;
}
});
});
when I run the project with:
$ npm run watch-changes
and do the modifications below on file: /profiles/bill-gates.json
modification 1: Bill Gates -> Bill Gates ABC
modification 2: Bill Gates ABC -> Bill Gates ABC DEF
it works fine, outputting the content of this file to the console.
But when I do the next modification:
modification 3: Bill Gates ABC -> Bill Gates ABC DEF GHI
Then I get the following error:
-> Profile changed: profiles\bill-gates.json
-><-
undefined:1
SyntaxError: Unexpected end of JSON input
at JSON.parse (<anonymous>)
at fs.readFile (\chokidar-issue\profile-watcher.js:17:24)
at \chokidar-issue\node_modules\graceful-fs\graceful-fs.js:115:16
at FSReqWrap.readFileAfterClose [as oncomplete] (internal/fs/read_file_context.js:53:3)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! chokidar-issue#1.0.0 watch-changes: `node profile-watcher.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the chokidar-issue#1.0.0 watch-changes script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! C:\Roaming\npm-cache\_logs\2020-02-28T23_44_01_038Z-debug.log
/profiles/bill-gates.json (Flags: UTF-8 / CRLF)
{
"name": "Bill Gates",
"email": "bill.gates#microsoft.com",
"password": "windows",
"country": "USA"
}
By the way, if I change from CRLF to LF normally I can do few modifications more before it crashes.
I'm under the impression that for somre reason the file: /profiles/bill-gates.json gets locked at some point and when Node tries to read it it returns an empty string because it is locked.
Any idea on how to make this work without crashing after few tries?
Thanks!
I had the same problem as you.
There is an option in "chokidar" where you can awaitWriteFinish. It's time-based and checks if the size of the file is changing. If not, then it will call the callback.
const watcher = chokidar.watch(configPathString, {
persistent: true,
awaitWriteFinish: {
stabilityThreshold: 500
}
});
watcher.on('change', (path, stats) => {
fs.readFile(configPathString,(err, data)=>{
if (err) throw err;
//console.log('data',data);
let receivedData = JSON.parse(data);
//Do whatever you like
})
});
It may be a race condition. Make your JSON.parse safe like this:
const path = require('path')
chokidar.watch(path_file).on('change', async (path) => {
fs.readFile(path, 'utf8', (err, profile_json) => {
if (!profile_json) {
console.log(`${path} is an empty file!`)
return
}
const profile = JSON.parse(profile_json);
if (JSON.stringify(profile) != JSON.stringify(profile_before)) {
console.log('The profile has changed.');
profile_before = profile;
}
});
});
I could make it work by adding some recovery fallback:
const fs = require('fs-extra');
const colors = require('colors/safe');
const chokidar = require('chokidar');
const sleep = require('sleep');
const path_file = `profiles/bill-gates.json`;
console.log(`Current Profile: ${colors.red.bgBrightYellow(path_file)}`);
let profile_before = fs.readFileSync(path_file).toString();
chokidar.watch(path_file).on('change', async (path_changed) => {
let profile = fs.readFileSync(path_changed).toString();
if (IsValidJson(profile)) {
if (profile != profile_before) {
console.log();
console.log(`Profile changed: ${colors.red.bgBrightYellow(path_changed)}`);
process_profile(profile);
profile_before = profile;
}
}
else {
sleep.msleep(100); // this is necessary
}
});
function process_profile(profile_json) {
const profile = JSON.parse(profile_json);
console.log(`${profile_json}`);
console.log(profile.name);
}
function IsValidJson(str) {
try {
JSON.parse(str);
} catch (e) {
return false;
}
return true;
}
It seems that when you save a file (at least on Windows), sometimes there is a time in between (very very short time) that the file gets clear and few milliseconds later it gets the actual content. On both cases the on-change event gets fired. So, we just need to verify whether the content of the file is JSON or not. In that case I just need to ignore it and wait for the next on-change event.
I want to do semi automation to create user for my api, so I have this script
//getUserInfo.js
const argv = require('yargs-parser')(process.argv.slice(2))
module.exports = (async () => {
let [ userId ] = argv._ //parsing...
if(!userId){
console.log('userId is not defined')
return
}
userId = userId.split('=')[1] ////parsing, again :(
console.log(userId) //123
//proceed with automation steps
...
...
})()
The script is working, so in my package.json I have this
"scripts": {
"admin:getUserInfo": "node server/scripts/getUserInfo.js"
}
All I need to do is to run npm run admin:getUserInfo userId=123 and I can get 123 in my terminal.
But the problem is I have to do so many step just to get the userId value.
My function is triggered by a database event and uses Firebase Cloud Messaging to send a notification to a topic. My first function works fine, but the second one keeps throwing this error:
2018-02-20T21:16:49.878Z E receiveMessage: TypeError: admin.messaging(...).send is not a function
at exports.receiveMessage.functions.database.ref.onCreate (/user_code/index.js:55:27)
at Object.<anonymous> (/user_code/node_modules/firebase-functions/lib/cloud-functions.js:59: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:53:36)
at /var/tmp/worker/worker.js:695:26
at process._tickDomainCallback (internal/process/next_tick.js:135:7)
here is the index.js file:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
// // Create and Deploy Your First Cloud Functions
// // https://firebase.google.com/docs/functions/write-firebase-functions
//
// exports.helloWorld = functions.https.onRequest((request, response) => {
// response.send("Hello from Firebase!");
// });
exports.recceiveInvitation = /* the function that works */;
exports.receiveMessage = functions.database.ref('/messages/{chatId}/{time}').onCreate((event) => {
const chatId = event.params.chatId;
console.log('messages', chatId);
var sender = event.data.val().name;
var messageContent = event.data.val().message;
if(messageContent.length >= 100){
messageContent = messageContent.substring(0,97)+"...";
}
const payload = {
data: {
title: `New Message from ${sender}`,
body: messageContent
},
topic: chatId
};
return admin.messaging().send(payload);
});
I ran npm install firebase-admin, but I did not help.
change this:
return admin.messaging().send(payload);
to this:
return admin.messaging().sendToTopic(topicname,payload);
to be able to send notifications to topics.
You can do the above, or check the note below
Note:
You need to update the firebase-admin npm package, to be able to use send():
npm install firebase-admin#latest
more info here:-
https://firebase.google.com/support/release-notes/admin/node
https://firebase.google.com/docs/cloud-messaging/admin/send-messages
let message = {notification: {title: "your title",body: "your message",},token:"token of user device"
};
admin.messaging().send(message)