How to organize route dependencies in Node.js / Express - javascript

I understand how to export routes to an index.js file but the problem I am having is I don't understand how to properly reference those external route dependencies without pasting them to the top of the file.
In other words if I have the entry point to the program ( called index.js)
and I have a list of dependencies:
index.js
const Sequelize = require("sequelize");
const connection = new Sequelize("jsfsa", "root", "password");
const bcrypt = require("bcryptjs");
const salt = bcrypt.genSaltSync(10);
const express = require('express');
const path = require('path');
const http = require('http');
const bodyParser = require('body-parser');
const app = express();
const session = require('client-sessions');
const expressHbs = require('express-handlebars');
const csrf = require("csurf");
// .....etc....
and then I have a route ( lets say a post route ) that is referenced in an external file:
routes/login.js
exports.submitLogin = (req, res) => {
// do a bunch of stuff that requires the dependencies referenced in index.js
}
I can't figure out how reference any dependencies without just placing the needed module "requires" in the routes file.
routes/login.js
const Sequelize = require("sequelize");
const connection = new Sequelize("jsfsa", "root", "password");
const bcrypt = require("bcryptjs");
const salt = bcrypt.genSaltSync(10);
const express = require('express');
const path = require('path');
const http = require('http');
const bodyParser = require('body-parser');
const app = express();
const session = require('client-sessions');
const expressHbs = require('express-handlebars');
const csrf = require("csurf");
// .....etc....
exports.submitLogin = (req, res) => {
// do a bunch of stuff that requires the dependencies referenced in index.js
}
I want to believe there is a way to place all the module references in a file my_dependencies.js and then simply reference the entire file from all the other pages in my application using a line of code as simple as a function call.
Curious if this is possible.
I've tried reading online how to deal with this issue and everything is very confusing to me.

The way I do it is to just pass the dependency variables I need directly to the functions that handle that specific route. In your case :
index.js (or wherever your route is being defined)
app.post('/someRoute', require('routes/login').submitLogin(dependency1, dependency2));
//If you are using express.Router() to handle routes/sub-routes,
//then this line could be different
routes/login.js
exports.submitLogin = function(dependency1, dependency2)
return function(req, res){
// do a bunch of stuff that requires the dependencies referenced in index.js
}
}
Of course, in this practice I'm banking on the fact that you're not going to use every single dependency in every function, which would defeat its point.
This also lets me pass other context or state dependent variables to my route handlers.
There is also the practice of simply putting your dependency variable in the app variable, like :
app.dependency=someobject;
While this would hypothetically let you access your dependency using req.app.dependency1, this practice is not recommended as it can interfere with the already existing children of the app object.

Related

wrong routing with koa-router in koa

I am learning Koa, with basic exercise, but i can´t achieve implement a simple routing, with the code that i got from this page, and this is what i did:
var koa = require('koa');
var router = require('koa-router'); //require it
var app = new koa();
var ro = router();
//and we'll set up 2 routes, for our index and about me pages
ro.get('/hello', getMessage);
function *getMessage() {
this.body = "Hello world!";
};
app.use(ro.routes());
app.listen(8008);
console.log('Koa listening on port 8008');
i did´t get any specific error, because the app run with the command node index.js, but i can see any print in the page that i routed.
and i only have 1 file in my folder myproyectoks, and it is index.js, and that's the file that i'm working.
any information that you need pls ask me :D, because i could be forgot something.
The example is out-of-date - Koa middleware is promise-based and generator functions will no longer work directly. The router documentation suggests the following form:
const Koa = require('koa')
const Router = require('#koa/router')
const router = new Router()
router.get(
'/hello',
ctx => ctx.body = 'Hello world!'
)
const app = new Koa()
app.use(router.routes())
app.listen(8008)
To note the other differences, the router module is a class that requires instantiation and the context is passed as an argument to the request handler.

Node.js factory function for axios redis dependency injection

I have a node express app that is making calls to an external API using axios. I'm using redis for caching. It works fine, but I ran into a number of problems with unit tests - specifically trying to mock or inject mocks for redis client and an axios instance
My approach to making the route testable was to create a factory function for the route. It works, but I am unsure if there might be side/adverse effects, or if I'm using a bad practice and missing a standard solution
In api.js I require the details-route, passing in the axiosInstance and redisClient instance
// api.js
const detailsRouter = require('./details-route')(axiosInstance, redisClient);
router.use('/details', detailsRouter );
module.exports = router;
//details-route.js
const express = require('express');
const router = express.Router();
const fp = require('lodash/fp');
// local modules
const constants = require('../constants');
const axiosUtil = require('../axios-util');
const getRouter = (axiosInstance, redisClient) => {
router.get('/details', (req, res) => {
redisClient.get(req.originalUrl, (err, reply) => {
if (reply) {
// etc
}
// etc
}
}
return router;
}
module.exports = getRouter;
Note: I'm using redis-mock and axios-mock-adapter in my unit tests, and I've looked into using rewire (but it's not workable for wrapping the internal redis client)

Nodejs require doesn't work

Why does the following code not work
const {express} = require('express');
const router = express.Router();
Unresolved function or method Router
but this work
const express = require('express');
and if I want to do this require, what should I do.. two method in one require
const {validationResult, check} = require('express-validator/check');
node -v // v8.3.0
I'm trying to use this.. https://github.com/ctavan/express-validator#usage
Why does the following code not work
const {express} = require('express');
const router = express.Router();
You're using destructuring to extract a property that's not there. Your code is effectively doing this:
const temp = require('express');
const express = temp.express;
The object returned by require('express') has several properties, but .express is not one of them, so you end up setting express to undefined. And then when you call express.Router(), you get the error.
Your code that works is just saving the whole object, and then accessing it with the correct property names. You can keep that code, or if you know that you only are interested in the router you can do:
const {Router} = require('express');
const router = Router();
which would be pretty much the same as:
const express = require('express');
const Router = express.Router;
const router = Router();
and if I want to do this require, what should I do.. two method in one require
const {validationResult, check} = require('express-validator/check');
I'm not familiar with what that library exports. If you know that the object has both a validationResult and a check and that those are the only things you care about, then your code looks fine.

Appending a Prefix to Routes in One File in Express JS

I am currently refactoring my code and I am hoping there is a more efficient way to make my code look pretty. Here is what I currently have:
router.route('/api/merchant/')
.get(controllerFunction)
.post(controllerFunction);
router.route('/api/user/')
.get(controllerFunction)
.post(controllerFunction);
router.route('/admin/user/')
.get(controllerFunction)
.post(controllerFunction);
router.route('/admin/place/')
.get(controllerFunction)
.post(controllerFunction);
You can see that I have "api" and "admin" as prefixes to certain routes.
I can separate the API route into another file and have the "app.use" middleware append them appropriately, but I was wondering how can I get around this and have these routes in a single file with the main problem being at the end of the file:
module.exports = router
which only allows me to have one prefix to all my routes.
Short answer for your question follow below
You can put your middleware in separate file.
[name]Controller.js
module.exports = (req, res)=>{
res.send('I am a middleware');
}
Create a file bootable routers and export an array from routers.
boot.js
const express = require('express'),
router = express.Router(),
[name]Controller = require('./controller/[name]Controller'),
module.exports = [
router.get('/your path', [name]Controller),
...
]
Use router in your app file.
app.js
const express = require('express'),
boot = require('./boot'),
app = express();
app.use('/prefix', boot);
Now you can use routes with prefix for example:
localhost:3000/prefix/yourpath
You can folow below block code, but I suggest you write controler function to another file each for once.
var router = express.Router();
var useApi = router.route('/user')
.get(controllerFunction)
.post(controllerFunction);
var useAdmin = router.route('/user')
.get(controllerFunction)
.post(controllerFunction);
app.use('/api', userApi);
app.use('/admin', userAdmin);
You can mount the whole router on a path. If you do something like:
router.get('/:id', someFn);
Then elsewhere you could do:
app.use('/api', router);
and the route '/api/:id/` would resolve to the someFn handler
UPDATE
I'm not sure I fully understand your concern, and frankly having all your routes in one file makes for a file longer than I'm comfortable with, but if you really only want to mount one router, you can do something similar to what I described, but inside your routes file.
In that case, you'd still create the multiple routers but then rather than exporting them and mounting on the app, you'd do this:
const adminRouter = express.Router();
// configure the admin routes as I described
const apiRouter = express.Router();
// configure API routes
const main = express.Router();
main.use('/admin', adminRouter);
main.use('/api', apiRouter);
module.exports = main;

Get access to Express mountpath from inside a module

In an attempt to build a truly modular express app (one that can run stand alone or as a part of another app) I need to find out the cleanest way to find the mount path from inside the subapp. For a short example, lets say that there are two files: main.js and subapp.js
main.js
var express = require('express');
var app = express();
var localApp = express();
var subapp = require('./subapp');
app.use('/foo', subapp);
app.use('/bar', localApp);
console.log(localApp.mountpath); // yes, this prints '/bar' as expected
...
subapp.js
var express = require('express');
var app = express();
var truePath = app.mountpath; // I wish this would point to '/foo', but instead points to '/'
...
module.exports = app;
What is the best way (as in cleanest) to find the mountpath from inside the module? I'm doing this trying to solve this problem: Access to mountpath variable from inside a template using express in a non hardwired way.
As shown in the example, tried already with app.mountpath without success
As answered by alsotang, this is actually a problem of execution sequence, but it can be solved in what I think is a clean way. There is an event that is fired after the module is mounted, so you can do:
var truePath = = "/";
app.on('mount', function (parent) {
truePath = app.mountpath;
});
Where in real life truePath could be app.locals.truePath, so it can be accessed from inside the views.
eh..It's a problem of execution sequence.
In your subapp.js, the app.mountpath statement is before module.exports = app.
But only you export the app, then the app be mounted, then it would be set the mountpath property.
so, you should retrieve mountpath after the app be mounted by outer express.
My suggestion are two:
set the mountpath in your subapp.js. And outer express read this property.
perhaps you think 1 is not truly modular. so you can alternatively define a config file. and both main.js and subapp.js read mountpath from the config.
Try req.baseUrl:
app.js
var express = require('express');
var app = express();
var foo = require('./foo');
app.use('/foo', foo);
app.listen(3000);
foo.js
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) {
console.log(req.baseUrl); // '/foo'
res.send('foo');
});
module.exports = router;

Categories

Resources