How to transfer variable to routes.index - node.js

In file app.js i have:
, mongoose = require('mongoose')
, db = mongoose.connect('mongodb://localhost/expressdb');
app.get('/', routes.index);
and i have file routes/index.js, If I want to transfer db variable to routes.index What should I do?

I've setup an example on how you can achieve that, by passing the db as a parameter to the route module, and that module returns a function (in which db is visible):
routes.index
module.exports = function (db) {
return function(req, res, next) {
// you can access db here
}
}
app.js
...
routes = {};
routes.index = require('./routes')(db);
...

I think it's fairly standard in libraries that connect to a database for the connection to be shared if you try to create another connection (ie: the DB interface is a singleton). You could try simply calling
db = mongoose.connect('mongodb://localeyes/expressdb');
in your routes/index.js file, and it will likely use the same connection. I'd recommend reading the code to see if it will use an existing connection or if it tries to reconnect every time you call it.
edit: on second thought, you have another, less savory option:
You could make it global like so
global.db = db;
and then in your routes/index.js
var db = global.db;

Related

How to keep one instance of the database using express

I am using express along with sequelize to create a REST API. I want to keep just one instance of my database and use it in all the routes I may create. My first thought was to create the instance as soon as the app runs. Something like this.
const express = require('express')
const databaseService = require( './services/database')
const config = require( './config')
const userRoute = require( './routes/user')
const app = express()
databaseService.connect(config.db_options).then(
connectionInstance => {
app.use('user', userRoute(connectionInstance))
app.listen(3000)
}
)
I have not seen something like that so I believe it's not a good approach.
Any ideas ?
A strategy that I use extensively in several production applications to great success is to define the database connection logic in a single file similar to the following:
database.js
const dbClient = require('some-db-client')
let db
module.exports.connectDB = async () => {
const client = await dbClient.connect(<DB_URL>)
db = client.db()
}
module.exports.getDB = () => {
return db
}
Obviously, the connection logic would need to be more complex then what I have defined above, but you can get the idea that you would connect to your database using whichever database client library that you choose and save a reference to that single instance of your database. Then, wherever you need to interface with your database, you can call the getDB function. But first, you would need to make a call to your connectDB function from your server application entry file.
server.js
async function run() {
const db = require('./database')
await db.connectDB()
const app = require('express')()
const routes = require('./routes')
app.use('/', routes)
app.listen(3000, () => {
console.log('App server listening to port 3000')
})
}
You would make the call to initialize your database connection in the server application entry file before initializing express. Afterwards, any place in your application that needs access to the database can simple call the getDB() function and use the returned database object as necessary from there. This does not require overly complicated connection open and close logic and saves on the overhead of constantly opening and closing connections whenever you want to access the database by maintaining just a single database connection that can be used anywhere.

Using app.use to set up some routes in sails.js

First of all, the context. I'm using agenda to schedule tasks in my sails.js app. Agenda starts in a hook, after orm and some other hook have finished. So far everything is good. Then I discovered agendash, a web interface to manage agenda tasks. And I don't manage to make it work with sails.js.
The problem is in following. This is how agendash should be used (from the doc):
var express = require('express');
var app = express();
// ... your other express middleware like body-parser
var Agenda = require('agenda');
var Agendash = require('agendash');
var agenda = new Agenda({mongo: 'mongodb://127.0.0.1/agendaDb'});
app.use('/agendash', Agendash(agenda));
And I can't find where I should put this. As I said, agenda is initialized in a hook, and then I save it as sails.agenda. So the only thing I really have to do is
app.use('/agendash', require('agendash')(sails.agenda))
But I'm not sure how I could add a new route like this, outside of routes.js (I cannot refer to sails in that file, it's undefined), and then protect this route with some policies (I want agendash to be available only to admin).
If I get it right, this line should be run only once, so I cannot put it in config.http as middleware. But otherwise the router of sails.js will overwrite the route (at least if I put sails.hooks.http.app.use('/agendash', require('agendash')(agenda)) in a hook, the route is not exposed).
So what should I do to make it work?
First you should not init agenda in a hook but in config/bootstrap.js which is executed once on startup. Then you create a file called config/myApp.js where you put your global variables:
/**
* Expose global variables.
*/
module.exports.myApp = {
agenda: null
};
In config/bootstrap.js you set this variable once:
var Agenda = require('agenda');
sails.config.myApp.agenda = new Agenda({mongo: 'mongodb://127.0.0.1/agendaDb'});
Now you have a reference to agenda and you can access from everywhere in your app using sails.config.myApp.agenda.
To register the agendash route you have to use a custom middelware as explained here How to use custom route middleware with Sails.js? (ExpressJS) and discussed here https://github.com/balderdashy/sails/issues/814
Ok, I found the solution by using the customMiddleware in config/http.js where I could do app.use, protect the route by middlewares and eventually call Agendash(agenda)(req, res, next).
For this to work I had to move agenda initialization out of the hook and put it inside customMiddleware. This is what my code looks like:
customMiddleware: function(app){
var Agenda = require("agenda");
var Agendash = require('agendash')
var agenda = new Agenda({db: {address: 'localhost:27017/dbName', collection: 'collectionName'}});
//protect the route with several policies
app.use('/agendash', function(req, res, next){
require('../api/policies/policy1')(req, res, function(){
require('../api/policies/policy2')(req, res, function(){
require('../api/policies/policy3')(req, res, function(){
Agendash(agenda)(req, res, next)
}
)
})
})
});
sails.agenda = agenda; //saving the reference
agenda.on('ready', function(){
var eventsToWaitFor = ['hook:orm:loaded', 'hook:email:loaded'];//if need to wait for some events before starting tasks
sails.after(eventsToWaitFor, function(){
require('./../api/services/jobs')(agenda);//loading all the jobs
agenda.on('fail', function(err, job){
//log error here
});
agenda.every('10 minutes', 'task1');//schedule tasks
agenda.every('10 minutes', 'task2');
agenda.start();//start agenda
});
})
}

Express: how can I get the app from the router?

I know I can get the Express app from inside an individual route with:
req.app
However I need to start a single instance of a module inside routes/index.js, i.e.:
var myModule = require('my-module')(propertyOfApp)
How can I get the express app from the router?
It really depends on your own implementation, but what I suggested in the comments should be working:
// index.js
module.exports = function(app) {
// can use app here
// somehow create your router and do the magic, configure it as you wish
router.get('/path', function (req, res, next) {});
return router;
}
// app.js
// actually call the function that is returned by require,
// and when executed, the function will return your configured router
app.use(require('./index')(app));
p.s.
Of course this is just a sample - you can configure your router with path, and all kind of properties you wish. Cheers! :)

Handling variables and functions across files [duplicate]

I'm developing my first Node.js App with Socket.IO and everything is fine but now the app is slowly getting bigger and I'd like to divide the app-code into different files for better maintenance.
For example I'm defining all my mongoose schemas and the routings in the main file. Underneath are all the functions for the socket.IO connection. But now I want to have an extra file for the schemas, an extra file for routing and one for the functions.
Of course, I'm aware of the possibility to write my own module or load a file with require. That just does not make sense for me, because I can't work with the vars like app, io or db without making them global. And if I pass them to a function in my module, I can't change them. What am I missing? I'd like to see an example how this is done in practice without using global vars..
It sounds like you have a highly coupled application; it's difficult for you to split out your code into modules because pieces of the application that should not depend on each other do. Looking into the principles of OO design may help out here.
For example, if you were to split your dataabse logic out of the main application, you should be able to do so, as the database logic should not depend on app or io--it should be able to work on its own, and you require it into other pieces of your application to use it.
Here's a fairly basic example--it's more pseudocode than actual code, as the point is to demonstrate modularity by example, not to write a working application. It's also only one of many, many ways you may decide to structure your application.
// =============================
// db.js
var mongoose = require('mongoose');
mongoose.connect(/* ... */);
module.exports = {
User: require('./models/user');
OtherModel: require('./models/other_model');
};
// =============================
// models/user.js (similar for models/other_model.js)
var mongoose = require('mongoose');
var User = new mongoose.Schema({ /* ... */ });
module.exports = mongoose.model('User', User);
// =============================
// routes.js
var db = require('./db');
var User = db.User;
var OtherModel = db.OtherModel;
// This module exports a function, which we call call with
// our Express application and Socket.IO server as arguments
// so that we can access them if we need them.
module.exports = function(app, io) {
app.get('/', function(req, res) {
// home page logic ...
});
app.post('/users/:id', function(req, res) {
User.create(/* ... */);
});
};
// =============================
// realtime.js
var db = require('./db');
var OtherModel = db.OtherModel;
module.exports = function(io) {
io.sockets.on('connection', function(socket) {
socket.on('someEvent', function() {
OtherModel.find(/* ... */);
});
});
};
// =============================
// application.js
var express = require('express');
var sio = require('socket.io');
var routes = require('./routes');
var realtime = require('./realtime');
var app = express();
var server = http.createServer(app);
var io = sio.listen(server);
// all your app.use() and app.configure() here...
// Load in the routes by calling the function we
// exported in routes.js
routes(app, io);
// Similarly with our realtime module.
realtime(io);
server.listen(8080);
This was all written off the top of my head with minimal checking of the documentation for various APIs, but I hope it plants the seeds of how you might go about extracting modules from your application.

Divide Node App in different files

I'm developing my first Node.js App with Socket.IO and everything is fine but now the app is slowly getting bigger and I'd like to divide the app-code into different files for better maintenance.
For example I'm defining all my mongoose schemas and the routings in the main file. Underneath are all the functions for the socket.IO connection. But now I want to have an extra file for the schemas, an extra file for routing and one for the functions.
Of course, I'm aware of the possibility to write my own module or load a file with require. That just does not make sense for me, because I can't work with the vars like app, io or db without making them global. And if I pass them to a function in my module, I can't change them. What am I missing? I'd like to see an example how this is done in practice without using global vars..
It sounds like you have a highly coupled application; it's difficult for you to split out your code into modules because pieces of the application that should not depend on each other do. Looking into the principles of OO design may help out here.
For example, if you were to split your dataabse logic out of the main application, you should be able to do so, as the database logic should not depend on app or io--it should be able to work on its own, and you require it into other pieces of your application to use it.
Here's a fairly basic example--it's more pseudocode than actual code, as the point is to demonstrate modularity by example, not to write a working application. It's also only one of many, many ways you may decide to structure your application.
// =============================
// db.js
var mongoose = require('mongoose');
mongoose.connect(/* ... */);
module.exports = {
User: require('./models/user');
OtherModel: require('./models/other_model');
};
// =============================
// models/user.js (similar for models/other_model.js)
var mongoose = require('mongoose');
var User = new mongoose.Schema({ /* ... */ });
module.exports = mongoose.model('User', User);
// =============================
// routes.js
var db = require('./db');
var User = db.User;
var OtherModel = db.OtherModel;
// This module exports a function, which we call call with
// our Express application and Socket.IO server as arguments
// so that we can access them if we need them.
module.exports = function(app, io) {
app.get('/', function(req, res) {
// home page logic ...
});
app.post('/users/:id', function(req, res) {
User.create(/* ... */);
});
};
// =============================
// realtime.js
var db = require('./db');
var OtherModel = db.OtherModel;
module.exports = function(io) {
io.sockets.on('connection', function(socket) {
socket.on('someEvent', function() {
OtherModel.find(/* ... */);
});
});
};
// =============================
// application.js
var express = require('express');
var sio = require('socket.io');
var routes = require('./routes');
var realtime = require('./realtime');
var app = express();
var server = http.createServer(app);
var io = sio.listen(server);
// all your app.use() and app.configure() here...
// Load in the routes by calling the function we
// exported in routes.js
routes(app, io);
// Similarly with our realtime module.
realtime(io);
server.listen(8080);
This was all written off the top of my head with minimal checking of the documentation for various APIs, but I hope it plants the seeds of how you might go about extracting modules from your application.

Resources