Using Node.js & NForce, Retrieve Records on Startup - node.js

I am attempting to modify this code:
https://github.com/jeffdonthemic/node-streaming-socketio/blob/master/app.js
So that as well as setting up the streaming, on startup it also performs a query to retrieve some records which are displayed to the user. I am attempting to place code like so:
var q = 'SELECT Id, Name, CreatedDate, BillingCity FROM Account';
sfdc.query({ query: q }, function(err, resp){
if(!err && resp.records) {
// do something with record, display to client
}
});
After the connection and ouath have been set up, however, I am unsure where to place that code in the lifecycle of the main application (app.js). Also, I am unsure how to pass this record once I have it so that it can be displayed on the client side. I keep getting this error when placing this code at various places in app.js:
TypeError: Cannot read property 'instance_url' of undefined

Related

Hows should I structure middleware to verify an ID exists in an external service in a Node/Express app?

I've currently written middleware to verify an ID exists in an external services (Salesforce). I initially wrote it when it was a single use app, but now I'm trying to make it work with different routes, so I want it to be fairly generic.
I don't even know if middleware is the right way to go, or if I should just call the function before saving the specific form.
I've got a form where someone puts in some information about a project, and the salesforce ID. For background, the salesforce ID is actually an auto-increment number, and I need to convert that to the actual salesforce system ID before I use jsForce to create a new object linked to that ID.
My route looks like this:
router.post('/invoice/add', ensureLoggedIn, invoiceController.validateInvoice, catchErrors(sfdc.validateSFID), catchErrors(invoiceController.saveInvoice))
So, I've got a middleware that does this:
exports.validateSFID = async(req, res, next) => {
const salesforceProjectNumber = req.body.SF_Opportunity
const sfResult = await conn.search(`FIND ... long query`, (err, result) => {
if (err || result.searchRecords.length !== 1) {
req.flash('error', 'Unable to find a Salesforce Job with that ID number.')
console.error(`ERROR: ${req.user.displayName} errored when looking up job number ${salesforceProjectNumber}.`)
return result
}
})
if (sfResult.searchRecords.length > 0) {
req.body.salesforce_Opportunity_id = sfResult.searchRecords[0].Id //Create a generic variable to hold the salesforce opportunity so it works regardless of the custom object name
res.locals.Opportunity_Clean_Name = sfResult.searchRecords[0].Name
}
next()
}
The query rarely throws an error, but in this case, an error is basically returning !1 records.
When that happens, I want to flash a message on the screen saying the ID wasn't found, but keep the form filled in.
When an ID is found, I want to proceed to save it and NOT display the form fields anymore.
This middleware needs to work regardless of the form I'm using, I want to be able to pipe in the middleware from any form that might require a user to enter a salesforce job as a field.
Any thoughts on how best to handle it all?
You can use your middleware by using app.use() function
app.use((req, res, next) => {
// Every time a request has made, this middleware will fire
console.log('Howdy');
})

Get user_likes and user_posts from Facebook using NodeJS

I need to develop an App that get some information by FB (user_posts and user_likes) I'm trying implement its using Passport-facebook.
I tried, (just 'likes' to test first)
newUser.facebook.likes = profile.likes[0].value;
and the error is:
TypeError: Cannot read property '0' of undefined
'likes' is on my profileFields.
I put my code that is working on my Github. (whitout likes and posts)
Other information like (id, name, email...) works very well, but I'm not be able to get the data user_likes and user_posts. I would like to enter this data in my MongoDB database.
The method that follow (in Javascript):
function getInfo() {
FB.api('me', {fields :'id,name,posts,likes'}, function(response) {
var dataStr = "data:application/octet-stream;charset=utf-8," + encodeURIComponent(JSON.stringify(response));
var dlAnchorElem = document.getElementById('downloadAnchorElem');
dlAnchorElem.setAttribute("href", dataStr);
dlAnchorElem.setAttribute("download", "feed.json");
dlAnchorElem.click();
});
};
Do what I want, but it writes data (.json) in a file, I want to record in the database and using NodeJS.
Any help?
Are you aware of Mongoose and how to define a schema in mongoose.
i suggest that it would be the simplest way for you to do.
you can use json-schema-to-mongoose (see link below for example)
https://www.npmjs.com/package/json-schema-to-mongoose
and them simply save the document to mongodb.

How to set up a HasMany relationship for Ember.js on the node.js side

My app is set up with Ember as the front-end framework and a node.js back-end, using the express.js server. There is not server-side framework at play, so if I were to request a GET from /users, I am manually writing a sql statement to fetch the required users.
Now, the question is, I've set up a hasMany/BelongsTo relationship between an inspectionResultType(the parent) and inspectionResults(child).
App.InspectionResultType = DS.Model.extend({
inspectionResultTypeID: DS.attr('number'),
name: DS.attr('string'),
...
inspectionResults: DS.hasMany('inspectionResult', {async: true}), // figure out how to make this work.
// inspectionResults: DS.hasMany('inspectionResult'),
});
App.InspectionResult = DS.Model.extend({
inspectionResultID: DS.attr('string'),
...
inspectionResultType: DS.belongsTo('inspectionResultType')
});
Now, InspectionResultTypes don't have their own route in the Ember app; they are only ever accessed from the record Page. So, in the record route, I am using an Ember RSVP to call inspectionResultTypes as a property, which works to fetch the inspectionResultTypes for sure, but shows no inspectionResults.
In my server logs, I notice this:
GET /inspectionResults?ids%5B%5D=2741&ids%5B%5D=2742&ids%5B%5D=2743&ids%5B%5D=2744 200 49597ms
(please ignore the 200 result value. That's wrong.)
So my question is this: how do I handle a GET request like this on the node.js side? There seem to be multiple id's and I don't think running several sql statements is the answer.
You have to access req.query.ids in your controller method in node.js. You will get an array - something like:
var ids = req.query.ids; // [2741, 2742, 2744]
Then you have to query your database using IN Clause. So, your query looks like this:
var query = 'SELECT * FROM InspectionResults WHERE id IN ( ' + ids.join() + ' );';
Then you get array of models from your database and you have to send it in response to Ember, which should be familiar to you:
res.json({
InspectionResults: [
{}, // 2741
{}, // 2742
{} // 2744
]
});

Meteor cannot retrieve data from MongoDB

Pretty straightforward and without any sort of configuration ->
In the project directory I entered the command:
$ meteor mongo to access the mongodb
From there (mongo shell), I switched to db meteor using the command use meteor then entered some basic data to test:
j = { name: "mongo" }
k = { x: 3 }
db.testData.insert(j)
db.testData.insert(k)
I checked and got results by entering: db.testData.find()
Here's my meteor code provided that mongodb access is only required on the client:
if (Meteor.isClient) {
Template.hello.greeting = function () {
return "Welcome to test.";
};
Template.hello.events({
'click input' : function () {
// template data, if any, is available in 'this'
if (typeof console !== 'undefined')
console.log("You pressed the button");
}
});
Documents = new Meteor.Collection('testData');
var document = Documents.find();
console.log(document);
var documentCbResults = Documents.find(function(err, items) {
console.log(err);
console.log(items);
});
}
Upon checking on the browser and based on the logs, it says undefined. I was unsuccessful from retrieving data from mongodb and showing to the client console.
What am I missing?
For this answer I'm going to assume this is a newly created project with autopublish still on.
As Christian pointed out, you need to define Documents on both the client and the server. You can easily accomplish this by just putting the collection definition at the top of the file or in another file which isn't in either of the server or client directories.
An example which prints the first two test documents could look like this:
Documents = new Meteor.Collection('testData');
if (Meteor.isClient) {
Template.hello.greeting = function () {
return "Welcome to apui.";
};
Template.hello.events({
'click input' : function () {
var documents = Documents.find().fetch();
console.log(documents[0]);
console.log(documents[1]);
}
});
}
Note the following:
The find function returns a cursor. This is often all you want when writing template code. However, in this case we need direct access to the documents to print them so I used fetch on the cursor. See the documentation for more details.
When you first start the client, the server will read the contents of the defined collections and sync all documents (if you have autopublish on) to the client's local minimongo database. I placed the find inside of the click event to hide that sync time. In your code, the find would have executed the instant the client started and the data probably would not have arrived in time.
Your method of inserting initial items into the database works (you don't need the use meteor by the way), however mongo will default to using an ObjectId instead of a string as the _id. There are subtle ways that this can be annoying in a meteor project, so my recommendation is to let meteor insert your data if at all possible. Here is some code that will ensure the testData collection has some documents:
if (Meteor.isServer) {
Meteor.startup(function() {
if (Documents.find().count() === 0) {
console.log('inserting test data');
Documents.insert({name: "mongo"});
Documents.insert({x: 3});
}
});
}
Note this will only execute if the collection has no documents in it. If you ever want to clear out the collection you can do so via the mongo console. Alternatively you can drop the whole database with:
$ meteor reset
It's not enough to only define collections on the client side. Your mongo db lives on the server and your client needs to get its data from somewhere. It doesn't get it directly from mongodb (I think), but gets it via syncing with the collections on the server.
Just define the Documents collection in the joint scope of client and server. You may also need to wait for the subscription to Documents to complete before you can expect content. So safer is:
Meteor.subscribe('testData', function() {
var document = Documents.find();
console.log(document);
});

Inserting data to MongoDB - no error, no insert

I'm currently trying to make a register form using mongoDB and nodeJS - I've created new database and collection - I want to store: username, password, email and insert_time in my database.
I've added unique indexes to username/email and checked if it works - and I can not add a duplicated entry using mongo's console or rockmongo (php mongodb manager) - so it works fine.
However - when the piece of code that is supposed to register a new account is being executed and makes an insert with the data that is already in database - it returns an object that contains all the data that was supposed to be added with a new, unique id. The point is - it should return an error that would say that entries can not be duplicated and insert failed - instead it returns the data back and gives it a new id. Data that already resides in database remains untouched - even the ID stays the same - it's not rewritten with the new one returned by script's insert.
So, the question is... what am I doing wrong? Or maybe everything is fine and database's insert should return data even if it's failed?...
I even tried defining indexes before executing indexes.
I tried inserting the data using mongoDB's default functions and mongoJS functions - the result is the same in both cases.
The code I'm trying to execute (for mongoJS):
var dbconn = require("mongojs").connect('127.0.0.1:27017/db', ['users']);
var register = function(everyone, params, callback)
{
// TODO: validation
dbconn.users.ensureIndex({username:1},{unique:true});
dbconn.users.ensureIndex({email:1},{unique:true});
dbconn.users.save(
{
username: params.username,
password: params.password,
email: params.email,
insert_time: Date.now()
},
function(error, saved)
{
if(error || !saved)
{
callback(false);
}
else
{
console.log(error);
console.log(saved);
callback(true);
}
});
}
For both cases - inserting new data and inserting duplicated data that doesn't modify database in any way - ERROR is null and SAVED is just a copy of data that is supposed to be inserted. Is there any way to check if insert was made or not - or do I have to check whether the data already exists in database or not manually before/after making an insert?
Mongo works that way. You should tell you want to get errors back, using the safe option when you issue the save command (as per default it uses the "fire and forget" method).
https://docs.mongodb.com/manual/reference/command/getLastError/
This looks to be basically the same problem as MongoDB unique index does not work -- but with the JavaScript API rather than Java. That is, saving without either specifying the "safe" flag or explicitly checking the last error value is unsafe--- the ID is generated client side and the command dispatched, but it might still fail (e.g. due to a unique index violation). You need to explicitly get the last error status.
http://www.mongodb.org/display/DOCS/dbshell+Reference#dbshellReference-ErrorChecking suggests db.getLastError() using the command shell, and I assume the node API is identical where they can possibly make it so.
Same problem solved, just forgot that its async insert and any nodes process.exit stops adding data
var lineReader = require('readline').createInterface({
input: require('fs').createReadStream('parse.txt')
});
lineReader.on('line', function (line) {
console.log(line)
db.insert(line,{w:1},function(e,d){ if (e) throw e })
});
// f this s, data are still adding when do close KUR WA MAC 2 days of my f life wasted
lineReader.on('close', function() {
// ----->>>>>> process.exit(); <<<<<----------
});

Resources