How to pass a variable into a Kraken.js model? - node.js

I have a variable that holds my Sequelize connection, like so:
var sequelize = new Sequelize('database', 'username');
With Kraken.js, how do I pass this into a module? I don't see where I could add this in the index.js configuration file...
Thanks!
(I can't tag this as krakenjs because I don't have enough karma.)

It's a pretty similar setup to what's shown in this guide:
http://sequelizejs.com/articles/express
You would create the model file, (under ./models). You'd need to register this model using the associate function (See previous link).
And to actually use the model, you could replicate the same usage as in the Kraken Shopping cart example https://github.com/lmarkus/Kraken_Example_Shopping_Cart/
eg: (After you've registered your models)
'use strict';
var Product = require('../models/productModel');
module.exports = function (server) {
/**
* Display a list of the products.
*/
server.get('/', function (req, res) {
Product.find(function (err, prods) {
res.render('index', products);
});
});
};

You can add the connection in separate file and export it (http://openmymind.net/2012/2/3/Node-Require-and-Exports/). I store such files in a dir called lib/
Then in the index.js (the starting point of the app) import the file using
require("./lib/..").
And then invoke it in index.js as
app.configure = function configure(nconf, next) {...};
(http://krakenjs.com/#structure_of_a_project)
A good sample app is https://github.com/lmarkus/Kraken_Example_Shopping_Cart

Related

Express.js unique var per request outside routing

In my express application I have a module called helpers thats is required in almost all my routes and modules. This module has a logger method that logs to fluentd (but that's unimportant). While building the data to log I'd like to add a unique identifier of the request, so that all the logs written for the same request have the same unique ID. Using a global var in the app entry point app.use doesn't work because this var would be overwritten every time a new request hits, so the global uuid will change would obviously change in case of high load or long running tasks. The res.locals is not available outside routing, so I can't use it for this matter. Is there a way to create a var that would be unique per request and available in every module or maybe a way to access the res.locals data outside routing? Thank you
EDIT
Maybe an example will help understand better the question.
Suppose I have a module called helpers.js like this:
let helpers = {};
helpers.log = (logData, logName) => {
fluentLogger.emit('', {
name: logName,
//uuid: the needed uuid,
message: logData
});
}
module.exports = helpers;
Now obviously I can do this in my app.js entry point:
app.use(function (req, res, next) {
res.locals.uuid = uuid.v4();
next();
});
and then in every loaded middleware module that requires helpers(adding a new param to the helpers.log method):
const helpers = require('helpers');
router.post('/', (req, res, next) => {
helpers.log('my log message', 'myLogName', res.locals.uuid);
next();
});
and this will normally work. But suppose a big or middle size project where there are hundreds of custom modules and models (not middlewares) and a module may require other modules that require other modules that require finally the helpers module. In this case I should pass the res.locals.uuid as a parameter to every method of every method so that I have it available in the logger method. Not a very good idea. Suppose I have a new module called dbmodel.js that is required in a middleware function:
const helpers = require('helpers');
let dbmodel = {};
dbmodel.getSomeData = (someParam) => {
//some logic
helpers.log('my log message', 'myLogName');
}
module.exports = dbmodel;
The dbmodel has no idea about the res.locals data if I don't pass it from the middleware, so the helpers.log method will also have no idea about this.
In PHP one would normally write a GLOBAL var in the application's entry point so a hypothetical logger function would have access to this global on every method request from whichever class of the application.
Hope this explanation will help :) Thank you
EDIT 2
The solution for this kind of problems is CLS. Thanks to #robertklep for the hint. A good slideshare explaining exactly the same problem (logger with unique ID) and explaining the CLS solutions can be found here: https://www.slideshare.net/isharabash/cls-and-asynclistener
I answered a very similar question here which will solve this problem.
I used to solve the problem the libraries node-uuid and continuation-local-storage. Take a look to the answer of this question and see if it helps:
NodeJS Express - Global Unique Request Id
And you want a bigger explanation, take a look here:
Express.js: Logging info with global unique request ID – Node.js
Yes you can do so by one method .
Every request comes to his routes pass that request inside the middleware.
Suppose you have
app.get('/', function(req, res) {
res.sendFile(path.join(public + "index.html"));
});
a request.
Place Middleware in it .and edit req field coming , in this way you will get the unique variable values for each request
check out this .
https://expressjs.com/en/guide/writing-middleware.html
Like this
var requestTime = function (req, res, next) {
req.requestTime = Date.now()
next()
}
app.use(requestTime)
app.get('/', function (req, res) {
var responseText = 'Hello World!<br>'
responseText += '<small>Requested at: ' + req.requestTime + '</small>'
res.send(responseText)
})
Here req.requestTime is unique for each request.

Express.js: Use Routers inside Routers

I have such router:
exports.read = (req,res) ->
// do stuff with DB
res.status(200).send
data:data
Now how can I use this router inside another router, call it exports.wrapper? I wnat to avoid having to rewrite my DB requests again and again. Is this approach that I have in mind recommended?
I would not recommend attempting to wrap routers inside each other.
It's recommended in Express 4 to use Express's router object like so:
// router.js
var myRouter = express.Router();
myRouter.route('/read', myController.readMethod);
Then in your controller you would handle the request and end with the result call:
// myController.js
exports.readMethod = function(req, res) {
var data = readFromDB(req.params);
res.send('read method renders', data);
}
exports.readMethod2 = function(req, res) {
var data = readFromDB(req.params);
res.send('read method 2 renders', data);
}
function readFromDB(params) {
// make a call to the DB (maybe via a model)
// return some data
}
Hope that helps
edit
Additionally, I would recommend wrapping your DB calls in a model, to abstract them away from your router or controller logic. For a reference of a well organised Express App that uses MVC checkout this Yeoman generator - https://github.com/ngenerio/generator-express-simple
second edit
In my very brief example externalising the readFromDB method to a model makes this function moot, if all it's doing is getting data from the DB put it in a model.

NodeJS Express Dependency Injection and Database Connections

Coming from a non Node background, my first instinct is to define my service as such
MyService.js
module.exports = new function(dbConnection)
{
// service uses the db
}
Now, I want one open db connection per request, so I define in middleware:
res.locals.db = openDbConnection();
And in some consuming Express api code:
api.js
var MyService = require(./services/MyService')
...
router.get('/foo/:id?', function (req, res) {
var service = new MyService(res.locals.db);
});
Now, being that Node's preferred method of dependency injection is via the require(...) statement, it seems that I shouldn't be using the constructor of MyService for injection of the db.
So let's say I want to have
var db = require('db');
at the top of MyService and then use somehow like db.current....but how would I tie the db to the current res.locals object now that db is a module itself? What's a recommended way of handling this kind of thin in Node?
Updated Answer: 05/02/15
If you want to attach a DB connection to each request object, then use that connection in your service, the connection will have to be passed to myService some how. The example below shows one way of doing that. If we try to use db.current or something to that effect, we'll be storing state in our DB module. In my experience, that will lead to trouble.
Alternatively, I lay out the approach I've used (and still use) in this previous answer. What this means for this example is the following:
// api.js
var MyService = require(./services/MyService')
...
router.get('/foo/:id?', function (req, res) {
MyService.performTask(req.params.id);
});
// MyService.js
var db = require('db');
module.exports = {
performTask: function(id)
{
var connection = db.getOpenConnection();
// Do whatever you want with the connection.
}
}
With this approach, we've decoupled the DB module from the api/app/router modules and only the module that actually uses it will know it exists.
Previous Answer: 05/01/15
What you're talking about could be done using an express middleware. Here's what it might look like:
var db = require('db');
// Attach a DB connection to each request coming in
router.use(req, res, next){
req.locals.db = db.getOpenConnection();
next();
}
// Later on..
router.get('/foo/:id?', function (req, res) {
// We should now have something attached to res.locals.db!
var service = new MyService(res.locals.db);
});
I personally have never seen something like new MyService before in express applications. That doesn't mean it can't be done, but you might consider an approach like this
// router.js
var MyService = require('MyService');
router.get('/foo/:id?', function (req, res) {
MyService.foo(res.locals.db);
});
// MyService.js
module.exports.foo(connection){
// I have a connection!
}

NodeJS exports not defined in external JS file

I am calling a function from an external JS file in my routes file. So, I am trying to export a function from my externalFile.js file. However, when I run the node server, it throws Uncaught ReferenceError: exports is not defined . externalFile.js is in public/javascripts/ and the route files is in routes/.
External file (externalFile.js):
exports.capsolvingComplete = function (stdout){
//Received, display text and hide the spinner, put check in place.
$('#capsolv-complete').css("display", "block")
$('#capsolv-output').text(stdout);
}
Route file:
var express = require('express');
var router = express.Router();
var script = require('../public/javascripts/externalFile.js')
/* GET home page. */
router.get('/', function(req, res) {
res.render('index', { title: 'CapSolv' });
});
router.post('/file-upload', function(req, res){
script.capsolvingComplete("HI");
res.end("success");
})
module.exports = router;
Thank you for your help! Bit of a node noob here.
Looking at your example, mscdex is right. Anything you require in Node is designed to run on the server, and doesn't have access to the browser's DOM.
I would recommend building a REST API that accepts the file upload, stores it, and returns a JSON object containing metadata: i.e. where the file was stored, size, etc., and let your client deal with that.

ExpressJS & Mongoose REST API structure: best practices?

I'm building a REST API with the use of NodeJS (Mongoose & ExpressJS). I think I have a pretty good basic structure at the moment, but I'm wondering what the best practices are for this kind of project.
In this basic version, everything passes through the app.js file. Every HTTP method is then passed to the resource that has been requested. This allows me to dynamically add resources to the API and every request will be passed along accordingly. To illustrate:
// app.js
var express = require('express');
var mongoose = require('mongoose');
var app = express();
app.use(express.bodyParser());
mongoose.connect('mongodb://localhost/kittens');
var db = mongoose.connection;
var resources = [
'kitten'
];
var repositories = {};
for (var i = 0; i < resources.length; i++) {
var resource = resources[i];
repositories[resource] = require('./api/' + resource);
}
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function callback() {
console.log('Successfully connected to MongoDB.');
app.get('/:resource', function (req, res) {
res.type('application/json');
repositories[req.params.resource].findAll(res);
});
app.get('/:resource/:id', function (req, res) {
res.type('application/json');
repositories[req.params.resource].findOne(req, res);
});
app.listen(process.env.PORT || 4730);
});
-
// api/kitten.js
var mongoose = require('mongoose');
var kittenSchema = mongoose.Schema({
name: String
});
var Kitten = mongoose.model('Kitten', kittenSchema);
exports.findAll = function (res) {
Kitten.find(function (err, kittens) {
if (err) {
}
res.json(kittens);
});
};
exports.findOne = function (req, res) {
Kitten.findOne({ _id: req.params.id}, function (err, kitten) {
if (err) {
}
res.json(kitten);
});
};
Obviously, only a couple of methods have been implemented so far. What do you guys think of this approach? Anything I could improve on?
Also, a small side question: I have to require mongoose in every API resource file (like in api\kitten.js, is there a way to just globally require it in the app.js file or something?
Any input is greatly appreciated!
Well, you can separate out your routes, db models and templates in different files.
Have a directory structure something like this,
| your_app
| -- routes
| -- models
| -- templates
| -- static
| -- css
| -- js
| -- images
| -- config.js
| -- app.js
| -- url.js
For each Mongoose model have a separate file placed in your ./models
In templates directory place your jade files. (Assuming you are using jade as your template engine). Though it seems like you are only serving JSON, not HTML. Consider using Jade if you want to render HTML. (Here are few other template engines you can consider going with)
./static directory for static JS, CSS and XML files etc.
Things like db connections or 3rd party API keys and stuff can be put in config.js
In url.js have a procedure which take express app object as argument and extend upon app.get and app.post there in single place.
P.S. This is the approach I go with for a basic web app in express. I am in no way saying this the best way to follow, but it helps me maintain my code.
There is no right way, but I did create a seed application for my personal directory structure to help my roommate with this.
You can clone it: git clone https://github.com/hboylan/express-mongoose-api-seed.git
Or with npm: npm install express-mongoose-api-seed
As codemonger5 said there is no right way of organising directory structure.
However, you can use this boilerplate application for creating REST APIs using Express and mongoose using ES6. We use the same directory structure in our production API services.
git clone https://github.com/KunalKapadia/express-mongoose-es6-rest-api
cd express-mongoose-es6-rest-api
npm install
npm start

Resources