Adhering to a max length setting with jshint - javascript

I see several recommendations for adhering to an 80 character max line length when writing javascript, e.g. Google, npm, Node.js, Crockford. In certain cases, however, I don't see how best to do it. Take the example below
MongoClient.connect('mongodb://localhost:27017/sampleDatabase', function(err, database) {
if(err) {
throw err;
}
db = database;
});
That would throw a jshint warning since it exceeds 80 characters. Now, would you choose to ignore the warning in this instance, or instead opt for a solution such as
MongoClient.connect('mongodb://localhost:27017/sampleDatabase',
function(err, database) {
if(err) {
throw err;
}
db = database;
}
);

If you can reuse the url variable, Andy's is a great option. If it's a one shot, as calls like this often are, I'd probably do something like this...
/*jslint sloppy:true, white:true, browser: true, maxlen:80 */
/*global MongoClient */
var dbErrHand, db;
dbErrHand = function(err, database) {
if(err) {
throw err;
}
db = database; // Killing me with the global spaghetti! ;^)
};
MongoClient.connect(
'mongodb://localhost:27017/sampleDatabase',
dbErrHand
);
That way, your code is more expressive and you know what db you're connecting to, though Andy just needs to change var url to var mongoSampleDb or similar to get the same advantage.
I like to pull the functions out so you can visually understand that they're reasonably discrete pieces of logic, even though I realize it isn't over 80 chars here if you put it on its own lines in the connect call. Would think that code is a candidate for reuse in your app as well.
It's also a good general habit to pull out functions so you don't accidentally make a function inside of a loop.[1]
And, of course, there's a chance that you still end up with insanely long strings, and have to do something like...
MongoClient.connect(
'mongodb://whoLetFredNameThisServerBecauseItsTooLong.FredsCompany.com:27017'
+ '/sampleDatabase',
dbErrHand
);
Good whitespace in nested code exacerbates the problem even more, which might +1 to Andy's idea of setting up variables like this outside of any loops/ifs/nested code. At some point, it might be worth turning maxlen off.
But bracket handling is one of the most subjective decisions there is, especially in JavaScript, where there's no sniff of a great, a priori answer. Some bristle like crazy at my parameter-per-line code, or would prefer the ( was on its own line, like this...
MongoClient.connect
(
'mongodb://localhost:27017/sampleDatabase',
dbErrHand
);
Surprisingly, JSLint still allows you plenty of room for self-expression! ;^)
[1] Nepotistic question link alert, though it was the first one I googled up. Probably an example of Google biasing my results for, um, me.

I would separate out the url into a new variable.
var url = 'mongodb://localhost:27017/sampleDatabase';
MongoClient.connect(url, function(err, database) {
if(err) {
throw err;
}
db = database;
});

Related

Using a variable in parameters to query data from sqlite database in a node.js application

So i'm making a discord bot with discord.js and not too sure how to go about this, have looked around for a while.
var server = member.guild.id;
db.all("SELECT channelMessage FROM userHelp WHERE serverId = server", function(err, rows){
rows.forEach(function (row) {
console.log("Message is " + channelMessage);
})
});
I know that this won't really work, but it's essentially what I'm aiming for, with the "WHERE" clause in line 2 using the previously defined variable as its parameter.
I'm pretty inexperienced to be honest, so any help is much appreciated.
Thanks!
As long as the server variable doesn't come from user input, you can interpolate it into your query string. In newer versions of javascript (es2015 and above, I believe), you should be able to just do:
var server = member.guild.id;
db.all(`SELECT channelMessage FROM userHelp WHERE serverId = ${server}`, ...)

Use Asynchronous IO better

I am really new to JS, and even newer to node.js. So using "traditional" programming paradigms my file looks like this:
var d = require('babyparse');
var fs = require('fs');
var file = fs.readFile('SkuDetail.txt');
d.parse(file);
So this has many problems:
It's not asynchronous
My file is bigger than the default max file size (this one is about 60mb) so it currently breaks (not 100% sure if that's the reason).
My question: how do I load a big file (and this will be significantly bigger than 60mb for future uses) asynchronously, parsing as I get information. Then as a followup, how do I know when everything is completed?
You should create a ReadStream. A common pattern looks like this. You can parse data as it gets available on the data event.
function readFile(filePath, done) {
var
stream = fs.createReadStream(filePath),
out = '';
// Make done optional
done = done || function(err) { if(err) throw err; };
stream.on('data', function(data) {
// Parse data
out += data;
});
stream.on('end', function(){
done(null, out); // All data is read
});
stream.on('error', function(err) {
done(err);
});
}
You can use the method like:
readFile('SkuDetail.txt', function(err, out) {
// Handle error
if(err) throw err;
// File has been read and parsed
}
If you add the parsed data to the out variable the entire parsed file will be sent to the done callback.
It already is asynchronous, javascript is asynchronous no extra effort is needed from your part. Does your code even work though? I think your parse should be inside a callback of read. Otherwise readfile is skipped and file is null.
In normal situations any io code you write will be "skipped" and the code after it which may be more direct will be executed first.
For the first question since you want to process chunks, Streams might be what you are looking for. #pstenstrm has an example in his answer.
Also, you can check this Node.js documentation link for Streams: https://nodejs.org/api/fs.html#fs_fs_createreadstream_path_options
If you want an brief description and example for Streams check this link: http://www.sitepoint.com/basics-node-js-streams/
You can pass a callback to the fs.readFile function to process the content once the file read is complete. This would answer your second question.
fs.readFile('SkuDetail.txt', function(err, data){
if(err){
throw err;
}
processFile(data);
});
You can see Get data from fs.readFile for more details.
Also, you could use Promises for cleaner code with other added benefits. Check this link: http://promise-nuggets.github.io/articles/03-power-of-then-sync-processing.html

Clear the Session Store

I am currently developing a Node.js application. I am using connect-mongo with Express to handle my session store. I am also using Mongoose for other database operations.
However, when I re-start my server in order to test new functionality, the old session data is still there. This is leading to data inconsistencies and some tricky bugs.
So when the server first starts up, I would like to be able to clear out all data from the sessions collection in my Mongo database.
I know that, using Mongoose, I can do something like this to clear out a collection:
User.remove({}, function (error) {
console.log('Emptied user collection')
});
However, I don't know how I can get a reference to a collection without declaring its schema.
Does anyone know how I can make this work? Or is there some entirely different approach I should be taking to handle all of this?
OK, so I think I found some solutions to my problem.
It is actually quite simple to get a reference to a collection without declaring its schema. Not sure how I hadn't found this in my research before I asked this question... So here is the complete solution to what I had been asking about:
mongoose.connection.db.collection('sessions', function (error, collection) {
if (error) {
console.error('Problem retrieving sessions collection:', error);
} else {
collection.remove({}, function (error) {
if (error) {
console.error('Problem emptying sessions collection:', error);
} else {
console.log('Emptied sessions collection');
}
});
}
});
However, in my case, I actually wanted to delete all data from the database, and was trying to do this one collection at a time (because I knew how to clear out a collection). Instead, I just needed to use db.dropDatabase().

Best pattern for handling Orchestrate.io queries

I have the following code in my Node/Express project
exports.getProductById = function(req, res){
db.get('product', req.params.id).then(function(res2){
res.render('product/get', {title:'Product', product:res2.body, categories: db.categories});
})
.fail(function (err) {
res.redirect('/');
})
}
This works but it seems like it could be a lot better, however, my lack of Javascript experience seems to be an issue. I would envision something like this...
var callback = function(res2){
res.render('product/get', {title:'Product', product:res2.body, categories: db.categories});
}
var errorCallback = function (err) {
res.redirect('/');
}
exports.getProductById = function(req, res){
db.get('product', req.params.id).then(callback)
.fail(errorCallback)
}
Of course the problem here is I have no idea how to pass the res object to the Callback. What is the best pattern for handling this type of scenario?
Hey I wrote the orchestrate.io client library for JavaScript, and your first run through is actually good. I think you'll find it easier to keep req and res within the getProductById function. If you wish to avoid clutter, you can write additional functions that handle the data, format it, etc. and return back those changes to getProductById. This will make it easier to keep track of what is going on.

Node.js and mongodb access mongodb

I'm trying to set up mongodb on Windows 8 using node.js, Does anyone know why im getting this error. C:\users\phill\node_modules\mongodb\lib\mongodb\mongo_client.js:359 it also says at collection = db collection,,, can't call method 'collection' of null. I'm having a hard time setting it up. My goal is to be able to add to mongo db, and see that I add or pull up what I added, but adding something is good enough for me for now. I'm trying every thing I can find, even straight from the website, I tried everything I see on here as well. Think it maybe it's the way I have things set up. My node.js is saved in my c: drive there is a file that says, program files(86x) in there I have node_modules, npm and such. The path ends up being, computer > windows (C:) > program files(86x) > nodejs. My Mongodb is saved right on my C: drive the path end up being windows (C:) > mongodb-win32-x86_64-2008plus-2.4.8. In my C: I also created a file data and in it created another db. I have been told i should just use mongoose, I'm just learning so i open to any advice, links or anything that will help. I have one last question as well, i learned php and then found out about sql injections and stuff like that, i am not seeing anything about security at all, should i expect the same as well. For this i get text not defined, but i have been getting errors with everthing i have done, best i did was get stuck on a right concern screen.
var MongoClient = require('mongodb').MongoClient;
MongoClient.connect("mongodb://localhost:27017/integration_test", function(err, db) {
test.equal(null, err);
test.ok(db != null);
db.collection("replicaset_mongo_client_collection").update({a:1},
{b:1}, {upsert:true}, function(err, result) {
test.equal(null, err);
test.equal(1, result);
db.close();
test.done();
});
});
Tried this as well and getting a error,C:\users\phill\node_modules\mongodb\lib\mongodb\mongo_client.js:359.... at collection = db collection,,, can't call method 'collection' of null. im calling it in command prompt node filename.js I'm saving it where my node.js file is, I have pulled up files before and created a server.
var Db = require('mongodb').Db,
MongoClient = require('mongodb').MongoClient,
Server = require('mongodb').Server,
ReplSetServers = require('mongodb').ReplSetServers,
ObjectID = require('mongodb').ObjectID,
Binary = require('mongodb').Binary,
GridStore = require('mongodb').GridStore,
Grid = require('mongodb').Grid,
Code = require('mongodb').Code,
BSON = require('mongodb').pure().BSON,
assert = require('assert');
var db = new Db('test', new Server('localhost', 27017));
// Fetch a collection to insert document into
db.open(function(err, db) {
var collection = db.collection("simple_document_insert_collection_no_safe");
// Insert a single document
collection.insert({hello:'world_no_safe'});
// Wait for a second before finishing up, to ensure we have written the item to disk
setTimeout(function() {
// Fetch the document
collection.findOne({hello:'world_no_safe'}, function(err, item) {
assert.equal(null, err);
assert.equal('world_no_safe', item.hello);
db.close();
})
}, 100);
});
In your first code example, you said:
For this i get text not defined
I assume you meant "test not defined?" Your script only requires the mongodb library, and I don't believe test is a core nodejs function, so that would explain the error.
To reference the driver documentation for db.collection(), an assert library is used, but also properly imported (as you did in your second example).
Within your callback to db.open(), you don't check if an error occurred. That might shed some light on why db is null in that function.
Regarding your question about the equivalent of SQL injection with MongoDB, the main areas of concern are places where you might pass untrusted input into evaluated JavaScript, or using such input to construct free-form query objects (not simply using a string, but more like dropping an object into your BSON query). Both of these links should provide more information on the subject:
What type of attacks can be used vs MongoDB?
How does MongoDB address SQL or Query injection?

Categories

Resources