When collection is created, the documents are added to it at once - node.js

Still learning firestore, i want to write a function which would create multiple documents upon the creation of a collection at once. So i wrote this code to try it out. i saw the code as an answer to something similar.
const fsRef = admin.firestore();
export const moreCreations = functions.firestore
.document(
"dev_env/schools/school_collections/KithAndKin7394/students/{userID}"
)
.onCreate((snap, context) => {
const newSchoolRef = fsRef
.collection("dev_env")
.doc("schools")
.collection("school_collections")
.doc("KithAndKin7394")
.collection("students")
.doc(snap.id);
// Trying something on documents
const documentIds = [
'CRK_IRK',
'PHE',
'agricScience',
'basicScience',
'basicTechnology',
'businessStudies',
'computerStudies',
'creativeArts',
'english',
'frenchLanguage',
'hausaLanguage',
'homeEconomics',
'iboLanguage',
'maths',
'socialStudies',
'yoruba'
];
const batch = fsRef.batch();
const data ={};
const setbatch = documentIds.forEach(docId => {
batch.set(newSchoolRef.collection('JSS1').doc('${docId}'), data);
})
batch. commit().then(response => {
console.log('Success');
}).catch(err => {
console.error(err);
})
});
I am getting these errors:
i deploying functions
Running command: npm --prefix "$RESOURCE_DIR" run lint
> functions# lint C:\brighterbrains\functions
> tslint --project tsconfig.json
ERROR: C:/brighterbrains/functions/src/index.ts:168:23 - Expression has type `void`. Put it on its own line as a statement.
npm ERR! code ELIFECYCLE
npm ERR! errno 2
npm ERR! functions# lint: `tslint --project tsconfig.json`
npm ERR! Exit status 2
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! C:\Users\dell\AppData\Roaming\npm-cache\_logs\2020-03-30T02_04_34_455Z-debug.log
Error: functions predeploy error: Command terminated with non-zero exit code2
What i want is when the collection "JSS1" is created, the documents "documentsId" are added to it at once. The code is from this forum but it is not working. Please can anyone point my mistake and help with me with the corrections? The documentation doesn't do or say anything about such actions.
Thanks in advance.

Remove const setbatch = from before the forEach(). It doesn't have a return value.

I have solved it. Below is the updated code:
export const moreCreations = functions.firestore
.document(
"dev_env/schools/school_collections/KithAndKin7394/students/{userID}"
)
.onCreate((snap, context) => {
const newSchoolRef = fsRef
.collection("dev_env")
.doc("schools")
.collection("school_collections")
.doc("KithAndKin7394")
.collection("students")
.doc(snap.id);
// Trying something on documents
const documentIds = [
'CRK_IRK',
'PHE',
'agricScience',
'basicScience',
'basicTechnology',
'businessStudies',
'computerStudies',
'creativeArts',
'english',
'frenchLanguage',
'hausaLanguage',
'homeEconomics',
'iboLanguage',
'maths',
'socialStudies',
'yoruba'
];
const batch = fsRef.batch();
const data ={};
documentIds.forEach(docId => {
batch.set(newSchoolRef.collection('JSS1').doc(docId), data);
})
batch.commit().then(response => {
console.log('Success');
}).catch(err => {
console.error(err);
})
});
It deployed successfully and upon creation of a document, the collection JSS1 is automatically created with the documents under the documentsId array automatically added.
I wanna thank #samthecodingman for helping me spot the area i need to edit. And #DougStevenson too.

Related

jest unit tests failing, setData does not seem to be working

I'm trying to learn unit testing my vue application with jest by following a tutorial. I set up this component called AppHeader containing a button that is only visible when the variable "loggedIn" is true.
In order to set the value "loggedIn" to true, I use .setData to change its value. Am i using setData incorrectly or is there something else going on?
AppHeader:
<template>
<div>
<button v-show="loggedIn">Logout</button>
</div>
</template>
<script>
export default {
data() {
return {
loggedIn: false,
};
},
};
</script>
AppHeader.spec.js:
import AppHeader from "#/components/AppHeader.vue";
import { mount } from "#vue/test-utils";
describe("AppHeader", () => {
test("hide button when user is logged off", () => {
const wrapper = mount(AppHeader);
expect(wrapper.find("button").isVisible()).toBe(false);
});
test("show button when user is logged in", () => {
const wrapper = mount(AppHeader);
wrapper.setData({ loggedIn: true });
expect(wrapper.find("button").isVisible()).toBe(true);
});
});
output:
FAIL tests/unit/AppHeader.spec.js
AppHeader
√ hide button when user is logged off (23ms)
× show button when user is logged in (7ms)
● AppHeader › show button when user is logged in
expect(received).toBe(expected) // Object.is equality
Expected: true
Received: false
11 | const wrapper = mount(AppHeader);
12 | wrapper.setData({ loggedIn: true });
> 13 | expect(wrapper.find("button").isVisible()).toBe(true);
| ^
14 | });
15 | });
16 |
at Object.<anonymous> (tests/unit/AppHeader.spec.js:13:48)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 passed, 2 total
Snapshots: 0 total
Time: 2.85s
Ran all test suites.
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! music_gym#0.1.0 test:unit: `vue-cli-service test:unit`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the music_gym#0.1.0 test:unit 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:\Users\HP\AppData\Roaming\npm-cache\_logs\2021-10-25T10_35_11_082Z-debug.log
I think the issue here may be that you are changing the data but now waiting for the next change detection cycle to trigger, this happens asynchronously.
You can await setData to let these changes settle as the following example (don't forget to set your arrow function as async), also you can further read about this in this link about testing asynchronous components where setData is mentioned as one of the methods that can be awaited and also in setData's documentation.
test("show button when user is logged in", async() => {
const wrapper = mount(AppHeader);
await wrapper.setData({ loggedIn: true });
expect(wrapper.find("button").isVisible()).toBe(true);
});

Why is Heroku unable to cd to my frontend React App?

I keep getting this error message when I git push my backend to heroku:
remote: -----> Build
remote: Running heroku-postbuild
remote:
remote: > mp-backend#1.0.0 heroku-postbuild /tmp/build_eaac46c4d4704cb2a35221c2068a754a
remote: > cd map-project && npm install --only=dev && npm install && npm run build
remote:
remote: sh: 1: cd: can't cd to map-project
remote: npm ERR! code ELIFECYCLE
remote: npm ERR! errno 2
remote: npm ERR! mp-backend#1.0.0 heroku-postbuild: `cd map-project && npm install --only=dev && npm install && npm run build`
remote: npm ERR! Exit status 2
remote: npm ERR!
remote: npm ERR! Failed at the mp-backend#1.0.0 heroku-postbuild script.
Leading to a ! [remote rejected] master -> master (pre-receive hook declined).
I do not understand. I added this:
"scripts": {
"start": "node index.js",
"heroku-postbuild": "cd map-project && npm install --only=dev && npm install && npm run build"
}
to the package.json for my backend and then ran
git init
git add .
git commit -m "Initial commit"
heroku create
git push heroku master
while cd'd to my backend. What keeps causing my build to fail?
additional code that may help:
//my backend under folder mp-backend
const express = require('express');
const path = require('path');
const app = express();
const populartimes = require('populartimes.js');
//Node Geocoder
const NodeGeocoder = require('node-geocoder');
const options = {
provider: 'google',
apiKey:
};
const geocoder = NodeGeocoder(options);
const getWeekDay = () => {
typical getDay codes
}
const unRendered = 'https://i.imgur.com/fgSeO4a.png';
const Rendered = 'https://i.imgur.com/sg9a1sG.png';
//Markers
const markers = [an array of marker objects]
const findLatLong = async function findLatLong(){
for(let i = 0; i < markers.length; i++){
const temp = await geocoder.geocode(markers[i].address)
markers[i].position.lat = temp[0].latitude;
markers[i].position.lng = temp[0].longitude;
}
}
const fillNewMarker = async function fillNewMarker(num){
const i = num;
let temp;
let data;
await populartimes(markers[i].placeID)
.then(out => {data = out; temp = 'Currently ' + data.now.currently + ' full.'})
.catch(() => {temp = 'There is currently no data available.'});
markers[i].busy = temp;
}
// Serve the static files from the React app
app.use(express.static(path.join(__dirname, 'map-project/build')));
var bodyParser = require('body-parser');
app.use(bodyParser.json()); // support json encoded bodies
app.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies
app.get('/api/getMarkers', async (req,res) => {
await findLatLong();
console.log('Find LatLng Complete')
//await fillPopularity();
//console.log('Find Business Complete')
var mark = markers;
res.json(mark);
console.log('Sent Markers');
console.log(markers);
});
app.post('/api/newMarker', async (req,res) => {
console.log('Request Recieved');
const n = req.body.index;
console.log(n);
await fillNewMarker(n);
console.log('Retrieve Data For New Marker Complete');
markers[n].icon = Rendered;
var mark = markers;
res.json(mark);
console.log('Sent Markers');
console.log(markers);
})
app.get('*', (req,res) =>{
res.sendFile(path.join(__dirname+'/map-project/build/index.html'));
});
const port = process.env.PORT || 5000;
app.listen(port);
console.log('App is listening on port ' + port);
What's your folder structure? What does your project look like?
You haven't provided enough information for anyone to help you.
Edit:
You have two options here, mono-repo and poly-repo. Basically, do you want your front and back ends always tied together (mono-repo) or do you want them to be entirely separate things (poly-repo)? While I am a huge fan of mono-repos, even with large scopes, don't let me necessarily persuade you either way without doing your own research. I think a mono-repo would be better for you in this situation, as they are less work to manage.
Here's an example of a folder structure for your project:
my-project
----.git
----packages
--------back-end
--------front-end
----README.md
----(any other whole-project type files)
Your whole project will be under one Git repository. See your issue was that Git only tracks the folder you're in and down. So if you put Git in packages/backend, it'll only find and track that folder's children. Meaning when you push, anything not in packages/backend just doesn't exist.
This solution I propose has you tie the two packages quite closely. When you push to git or heroku, both your front and back end will be together. This also lets you handle some other tooling better, like say documentation. You can add instructions for deploying the system as a whole, rather than an individual part.

eslint throws error

i am new android beginner and try to deploy firebase functions but show some error how to solve this problem plz help me.
Firebase database structure
User Table
Users
user_id
device_token : user_device_token
Name : user_name
Notification Table
notifications
to_user_id
notification_id
from : from_user_id
Error
Index.js
'use strict'
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
/*
* 'OnWrite' works as 'addValueEventListener' for android. It will fire the function
* everytime there is some item added, removed or changed from the provided 'database.ref'
* 'sendNotification' is the name of the function, which can be changed according to
* your requirement
*/
exports.sendNotification = functions.database.ref('/notifications/{user_id}/{notification_id}').onWrite(event => {
/*
* You can store values as variables from the 'database.ref'
* Just like here, I've done for 'user_id' and 'notification'
*/
const user_id = event.params.user_id;
const notification_id = event.params.notification_id;
console.log('We have a notification from : ', user_id);
/*
* Stops proceeding to the rest of the function if the entry is deleted from database.
* If you want to work with what should happen when an entry is deleted, you can replace the
* line from "return console.log.... "
*/
if(!event.data.val()){
return console.log('A Notification has been deleted from the database : ', notification_id);
}
/*
* 'fromUser' query retreives the ID of the user who sent the notification
*/
const fromUser = admin.database().ref(`/notifications/${user_id}/${notification_id}`).once('value');
return fromUser.then(fromUserResult => {
const from_user_id = fromUserResult.val().from;
console.log('You have new notification from : ', from_user_id);
/*
* The we run two queries at a time using Firebase 'Promise'.
* One to get the name of the user who sent the notification
* another one to get the devicetoken to the device we want to send notification to
*/
const userQuery = admin.database().ref(`/Users/${from_user_id}/Name`).once('value');
const deviceToken = admin.database().ref(`/Users/${user_id}/device_token`).once('value');
return Promise.all([userQuery, deviceToken]).then(result => {
const userName = result[0].val();
const token_id = result[1].val();
/*
* We are creating a 'payload' to create a notification to be sent.
*/
const payload = {
notification: {
title : "New Friend Request",
body: `${userName} has sent you request`,
icon: "default",
}
};
/*
* Then using admin.messaging() we are sending the payload notification to the token_id of
* the device we retreived.
*/
return admin.messaging().sendToDevice(token_id, payload).then(response => {
console.log('This was the notification Feature');
});
});
});
});
**cmd show error **
C:\Users\TahirAliAwan\Desktop\Function>firebase deploy
=== Deploying to 'videochat-96f75'...
i deploying functions
Running command: npm --prefix %RESOURCE_DIR% run lint
functions# lint C:\Users\TahirAliAwan\Desktop\Function\functions
eslint .
C:\Users\TahirAliAwan\Desktop\Function\functions\index.js
61:11 warning Avoid nesting promises promise/no-nesting
84:14 warning Avoid nesting promises promise/no-nesting
84:69 error Each then() should return a value or throw promise/always-return
✖ 3 problems (1 error, 2 warnings)
npm ERR! Windows_NT 10.0.10586
npm ERR! argv "C:\Program Files\nodejs\node.exe" "C:\Program Files\nodejs\node_modules\npm\bin\npm-cli.js" "--prefix" "C:\Users\TahirAliAwan\Desktop\Function\functions" "run" "lint"
npm ERR! node v6.11.5
npm ERR! npm v3.10.10
npm ERR! code ELIFECYCLE
npm ERR! functions# lint: eslint .
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the functions# lint script 'eslint .'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the functions package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR! eslint .
npm ERR! You can get information on how to open an issue for this project with:
npm ERR! npm bugs functions
npm ERR! Or if that isn't available, you can get their info via:
npm ERR! npm owner ls functions
npm ERR! There is likely additional logging output above.
npm ERR! Please include the following file with any support request:
npm ERR! C:\Users\TahirAliAwan\Desktop\Function\npm-debug.log
Error: functions predeploy error: Command terminated with non-zero exit code1
After #PeterHaddad tip and my effort, I solved this problem by removing this line
.then(response => { console.log('This was the notification Feature'); and update nodejs.
Thanks to all.

how to add a new line into mongodb using mongoose express and nodejs

I have an app that was built using authentication method suggested in this great tutorial:
http://scotch.io/tutorials/easy-node-authentication-setup-and-local
It is using mongoose, mongodb and express its working great!
I have now tried to integrate Stripe payments with it. I am trying to create a new Paymentcard model the same way the tutorial created the user model and add the card when there is a success creation of a new customer.
This is my model:
// app/models/paymentcard.js
// load the things we need
var mongoose = require('mongoose');
// define the schema for our user model
var paymentcardSchema = mongoose.Schema({
card : {
stripe_customer_id: String,
user_id: String,
id: String,
last4: String,
brand: String,
funding: String,
exp_month: String,
exp_year: String,
fingerprint: String,
country: String
}
});
// create the model for users and expose it to our app
module.exports = mongoose.model('Paymentcard', paymentcardSchema);
I am then trying to add a new payment card using the following inside the routes.js file:
stripe.customers.listCards(id, function(err, cards) {
// asynchronously called
var newpaymentcard = new Paymentcard();
newpaymentcard.save(function(err) {
if (err)
throw err;
return 'done';
});
});
However in the log I get this error when that bit of code is executed:
/Users/adamcooke/Dropbox/node/authenticateexample/app/routes.js:259
var newpaymentcard = new Paymentcard();
^
ReferenceError: Paymentcard is not defined
at /Users/adamcooke/Dropbox/node/authenticateexample/app/routes.js:259:56
at null._onTimeout (/Users/adamcooke/Dropbox/node/authenticateexample/node_modules/stripe/lib/StripeResource.js:78:34)
at Timer.listOnTimeout [as ontimeout] (timers.js:112:15)
npm ERR! Darwin 14.0.0
npm ERR! argv "node" "/usr/local/bin/npm" "start"
npm ERR! node v0.10.34
npm ERR! npm v2.1.16
npm ERR! code ELIFECYCLE
npm ERR! nodetest2#0.0.0 start: `node server.js`
npm ERR! Exit status 8
Any ideas what I am missing? I think it is something to do with the way i have defined the paymentcard model or that I am not making it available somehow in the routes.js.
I have the code on github also if you need a better look:
https://github.com/cookiejest/authenticationexample
The Paymentcard var in passport.js is private to that file (and not used as far as I can tell). You need to add the same line to routes.js so that it's also available in that file.
var Paymentcard = require('../app/models/paymentcard');

Node JS - child_process spawn('npm install') in Grunt task results in ENOENT error

I'm having some difficulty with a Grunt task I'm authoring. I'm trying to execute npm install, followed by bower install, followed by a grunt hub target (to trigger a build command for multiple sub-projects).
The problem I'm encountering lies with child_process. I get spawn ENOENT error if I run the following commands in my grunt task, with the npm install spawn command that's currently commented out:
var path = require('path'),
projectPath = path.resolve(process.cwd(), this.data.activity );
grunt.log.debug('project path computed as: ', projectPath);
process.chdir( projectPath );
console.log('current dir is: ', process.cwd());
console.log('EVN is: ', process.env);
var spawnProcess = spawn('ls');
// var spawnProcess = spawn('npm install');
spawnProcess.stdout.on('data', function (data) {
console.log('' + data);
});
spawnProcess.stderr.on('data', function(data) {
console.log('something went wrong installing deps for ' + path + '. Error: ', data);
});
spawnProcess.on('close', function (exitCode) {
console.log( 'ls has finished with Exit Code: ' + exitCode);
});
the current code (with ls instead of npm install) results in:
running "install:projects" (install) task[D] Task source: /Users/zedd45/proj/Gruntfile.js
Verifying property install.projects exists in config...OK
File: [no files]
[D] project path computed as: /Users/zedd45/proj/activity/web/client
current dir is: /Users/zedd45/proj/activity/web/client
EVN (abbreviated) is: {
TERM_PROGRAM: 'iTerm.app',
SHELL: '/bin/bash',
PWD: '/Users/zedd45/proj',
...
OLDPWD: '/Users/zedd45/proj/activity/web/client',
_: '/usr/local/bin/grunt' }
GruntFile.js
bower.json
package.json
this_is_the_directory_you_are_looking_for.txt
ls has finished with Exit Code: 0
but if I change 'ls' to 'npm install' I get instead
``Fatal error: spawn ENOENT
immediately following the ENV print.
I have tried chmod 777 for that directory, which doesn't seem to help.
I have also tried:
// var spawnProcess = spawn('npm install', {'cwd': projectPath});
and
// var spawnProcess = spawn('npm install', [], {'cwd': projectPath});
The former results in
Warning: Object # has no method 'slice' Use --force to
continue.
the later still results in the ENOENT error.
Any help with exactly what this ENOENT error is would probably help a great deal; I haven't had much success with Googling it nor with the child process API docs
Double check the docs on child_process.spawn again. The first argument should be only the command to run and the second is the arguments:
var npm = spawn('npm', ['install'], { cwd: projectPath });

Resources