Global access of config from database in express js - javascript

I am using expressjs and want to store project config variables in database for some reason. What is best way to access config variables from database so I will not need to query database on each router i am loading.
Should I use app.locals?

To do this, I don't export the "router" directly but a function that accept an argument which will receive the config. Here's an example :
// router.js
module.exports = function(database) {
return {
getLogin: function(req, res) {
// database exist here
}
}
}
// app.js without the creation of app and database
var app = express();
var database = require('./database');
var router = require('./router')(database)
app.get('/login', getLogin);
This way, you have the modularity and the possibility to interact easily with the database.

Related

Adding a routing file inside another routing file node.js

I want my routes to be like the following:
/
/business
/business/stuff1
/business/stuff2
/business/admin
for /business I want to have a separate file for the routing and functions.
and also for /business/admin I want to have a separate file for the routing and functions.
so what I did is:
app.js
//Business route
const business = require("./business/business");
app.use("/business", business);
This works fine - but when I add in business.js
//admin route
const admin = require("./admin");
app.use("/admin", admin);
I get 404 for some reason.
Depends on what you are exporing from business.js. It should be an instance of express.Router and you have to mount the /admin route on this instance. Example:
// business.js
const admin = require("./admin");
const businessApp = express.Router();
businessApp.use("/admin", admin);
module.exports = businessApp;

Running Code When a Module is Loaded and Exposing It as Middleware

I am still trying to fully understand how exporting and importing modules works in Nodejs.
I am using the following file to seed a mongodb database. This file runs exactly as it should and returns exactly the result I am expecting, when I execute it as a standalone file. My issue is I want to use this file in two different places in my app. So I am trying to make it an exportable/importable module. Here is what I have tried:
seed.js looks like this:
'use strict';
// library modules
const {ObjectID} = require('mongodb');
const seeder = require('mongoose-seed');
const jwt = require('jsonwebtoken');
const util = require('util');
// local modules
const {Course} = require('./../models/course');
const {Review} = require('./../models/review');
const {User} = require('./../models/user');
const {data} = require('./../data/data.js');
const config = require('./../config/config.js');
/*==================================================
build seeding Courses, Reviews, Users
==================================================*/
// Connect to MongoDB via Mongoose
let seed = seeder.connect(process.env.MONGODB_URI, (e) => {
console.log(`Connected to: ${process.env.MONGODB_URI} and seeding files`);
// Load Mongoose models
seeder.loadModels([
'src/models/user.js',
'src/models/review.js',
'src/models/course.js'
]);
// Clear specified collections
seeder.clearModels(['User', 'Review', 'Course'], function() {
// Callback to populate DB once collections have been cleared
seeder.populateModels(data, function() {
seeder.disconnect();
});
});
});
module.exports = seed;
Within app.js I have these two lines
const seed = require('./middleware/seed');
and
app.use(seed);
I have also tried, to no avail
app.use(seed());
What is missing? I don't want to use the code in-line in two different places (DRY you know).
It is failing with this error:
throw new TypeError('app.use() requires a middleware function')
I am sorry about the formatting I thought I was using markdown, but I am clearly not.
You are executing your seeder function in that module and not returning any middleware function at all. Middleware is always a function and it has the form of:
const seed = function (req, res, next) {
...
next()
}
With what you have now, the best you can do is the following which will certainly seed your models when the module is loaded.
const seed = require('./middleware/seed');
Are you trying to run those two functions as middleware, on every request? In that case you'd do something like this:
const seed = function (req, res, next) {
seeder.connect(..., (e) => {
...
seeder.clearModels(..., ()=>{
...
next()
})
})
})
If you want to run that seeder code at the module level AND to expose it as middleware then wrap the current module level code in function and execute it when the module loads. Notice that the new function optionally handles the next callback if it receives it.
function doSeed(next){
//your code currently running at module level
if(next)
return next()
}
doSeed(); //run the code at the module level
const seed = (req, res, next) => doSeed(next))
module.exports = seed;
One way that I allow myself to have access to a variable in different instances is adding it to the process variable. In node.js no matter where in the project it is, it will always be the same. In some cases, I would do process.DB = seed(); which would allow process.DB to always be the result of that. So inside your main class you can do process.DB = seed(); and all of your other classes running off of that one main class would have access to process.DB keeping your database readily available.

Default location of express generator title object

I'm using the express generator to create the framework for a site, which by default includes this line in the layout.jade file:
h1= title
Which calls in the title 'Express' from a local variable (index.jade extends the layout.jade file). However, I can't for the life of me find out where it's getting the variable from.
Can anyone tell me where the express generator creates the file that creates this variable, given I have used the default settings.
Inside the routes directory inside the index.js file
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' }); // <= HERE in the res.render method
});
module.exports = router;
You will find the object, passed as the second argument to the render method, that includes the key value pair {title: 'Express'}

What is the best way to pass global config variables to handlebars template?

Ive a nodejs app with express-handlebars and i am wanting to define variable for things like the 'host' address for CSS and Javascript that are currently being imported in a header.hbs file that i call form within the specific layout.
Ive created a config.js file which has a number of variables i want to set and ive imported that into the app.js using:
var config = require('./config.js');
but then im lost as t where to go. for example i was thinkging if i can some how do something like this:
<link href="{{config.csshost}}basev1.css" rel="stylesheet" type="text/css" />
Can anyone provide some pointers, am stumped other than declaring these variable every time i load the template.
You would set the app locals:
var app = express()
app.locals = {
config: config,
templateVar: 'test'
}
Edit:
Your routes will look something like this:
app.get('/', function(req, res) {
res.render('index', {config: config});
})
What this does, is then update the app.locals variable in express to look like this:
app.locals = {
config: config
}
All the app.local variables are then accessible in your templates via:
{{config}}
//which is really
app.locals['config']
So, in your app.js where you configure express you would do this:
var app = express();
app.locals.config = require('./config')
app.get('/', function(req, res) {
return res.render('index')
})
(This should be a comment to sctskw's answer above, but I don't have enough reputation to do that.)
Rather than overwriting app.locals with a new object, it would be better to add new properties to the existing one, like this:
app.locals.config = config;
app.locals.templateVar = 'test';
The reason is that Express uses app.locals internally. Overwriting it would lose some useful variables Express provides. For example, we could use settings.env to detect the current running environment in a view template, which is defined as app.locals.settings.env by Express.

node.js variable scope with routes separation

my routes are defined in an external folder
./routes
here's the way i define the routes in my server.js file
app.get('/', routes.index);
app.post('/validation', register.valid);
the register.valid module, which is originally written in
./routes/validation.js
is responsible for creating a new user account and register it into a database (MongoDB).
How can i access an object from server.js in validation.js ? First, i thought declaring the object before defining my routes would resolve the case, but actually it doesn't seem to be the solution.
I'm assuming your current code already does work (that is, you receive the posted data), but you need access to another object from validation.js.
If your code works, then you probably have this line in server.js:
var register = require('./routes/validation');
And you need acess to the variable obj in the validation module. You could have a function inside the validation module:
var foo;
exports.configure = function(obj) {
foo = obj;
}
The exports mean the variable configure will be accessible to modules which "require" the validation module. This way you can do, inside the server.js module:
register.configure(obj);
app.post('/validation', register.valid);
The exact configuration of this will depend on what you are actually trying to accomplish. Sometimes, for example, it's good to have a database object stored in a global variable.
Generally in this kind of structure server.js will create the app object and then pass that to individual routes modules via a function. I do it by having each router module export a single function like this:
//routes/validation.js
function setup(app) {
app.get(....blah
app.post(....blah
}
module.exports = setup;
Then I tie that together in server.js like this:
//server.js
var express = require('express');
var app = express();
require('./routes/validation')(app);
See also my express_code_structure sample project for other code organization tips.

Categories