Express.js - ASP.NET-like MVC Routing - node.js

I'm trying to setup an MVC architecture for Express. What I am trying to accomplish is a routing mechanism close to ASP.NET's. For example for the following route:
/users/detail/1
express should call a module under controllers directory named users.js. Within the users.js module is a function named detail. And within the function, I can simply get the request parameter to get the id of the user.
My idea is to extract the users and map it to a users.js file using a simple require statement. But how can I tell express to call details() function by simply extracting the action part of the route which is 'detail' in the above example. I can use eval() but I am hearing that it's not a safe thing to do? Thanks in advance.

In browser-side javascript, you can typically do the following
function a () { console.log('called a');
window['a'](); // called a
You can do similar in node by replacing window with global such as
function a () { console.log('called a');
global['a'](); // called a
However, if you are pulling this function in from another file, it will be little different. Let's assume that you have the following file a_module.js:
exports.a = function () { console.log('a called'); }
And then in you're main file, you can do the following:
var a_mod = require('./a_module.js');
a_mod['a'](); // a called

Related

My exports function isn't working because of error "TypeError: Cannot read properties of undefined (reading 'send')"

I'm new to the server side of programming and I can't figure out why the terminal is telling me that the send function in express isn't defined. I've tried putting express in the document, and I've tried different formats for the function, but I still can't figure it out. (It's complaining about the "getgameData" function)
I changed the send function thinking that it might be that you can't use the send function, but it turns out that no functions work there, but when I just try and return any other data structure, the terminal is still upset. Then, I tried restructuring the function and it still didn't work.
/////////////////////////////////////////////////////////////////////////////////////////
var gameData = require('../models/gameData.js');
var player = "ed";
exports.updateGame = function(res,req){
gameData.gameData = req.data;
}
exports.resetGame = function(){
res.send(gameData.gameData);
}
exports.getGameData = function(res,req){
gameData.gameData.playerNames.me = player;
res.setHeader('Content-Type','text/plain');
res.send(gameData.gameData.playerNames.me);
}
//////////////////////////////////////////////////////////////////////////////////////
** The app that connects the client side and the server side
//////////////////////////////////////////////////////////////////////////////////////
//all required js for Part 2
var game = require('./controllers/gameController');
var setup = require('./controllers/setupController');
var topTen = require('./controllers/topTenController');
// all routes
// game data routes
app.route('/api/gameData')
.get(game.getGameData())
.patch(game.updateGame)
Pass the callback function into the get(), not the function, executed. Get will pass in req, res, next to your callback and then execute it.
// all routes
// game data routes
app.route('/api/gameData')
.get(game.getGameData)
.patch(game.updateGame)
I also just noticed that you have your middleware functions arguments in the wrong order. The order is: req, res, next. Reference here.

Correct use of express in Node js

const express = require('express');
const app = express();
app.set('view engine', 'ejs');
app.listen(10000);
function function_a(inp)
{
var tmp_var = inp;
console.log(tmp_var)
//10 - the first time
//20 - the second time
app.get('/pageno1', (req, res) => {
res.redirect('...');
//..
console.log(tmp_var) //10 - on both calls
//..
});
}
function start(/* .. */)
{
//...
function_a(10);
function_a(20);
}
Suppose that I have two functions that simplified look something like the above. My issue is that the tmp_var holds the same value on both calls inside the app.get('/pageno1') even though I pass a different value.
Two points I would like to bring your attention to;
a) I dont use next(); (I am not sure if thats the issue),
b) I dont have a 'default' page (app.get('/', ...)) because I didnt need it (kinda weird, but thats my case.) I dont mind adding one, if thats the issue.
EDIT:
What is the expected end result: Get the URL parameters passed onto a URL and (eg: example.com/route?=<...>) and redirect the user to a page. After that is done in my code, in another function, use a stored variable and do some other things, using the parameters gotten from the URL and the stored variable. Wait for next GET request.
What I tried:
app.get('/pageno1', (req, res, next) => {
res.redirect('https://..');
//when that is done, move to another function
//here comes the issue (that other function needs the stored variable)
//and although its not needed inside `app.get` I need to pass it to the
//function after thats done.
function_A(param, req.query);
});
function_A(inp1, inp2)
{
//do some things
}
If that can be done using native HTTPS module, I don't mind not using express.
Lastly in case its not clear, I want to pass the local variable in the other function (function_A). So not necessarily inside the /pageno1 request. But, AFTER the pageno1 request is done, I need both the local variable and the req from the request to call the function_A.
If you need better explanation in anything, feel free to ask!

When testing an ExpressJS route using mocha+sinon, how do you "stub" a function that's local to the route?

So in one file, I have this route defined:
router.post('/', security.authenticate, function(req, res, next) {
//Doing prep stuff
//Do database work (<< this is what im really testing for)
//Calling another work function.
createFormUser(req.body, (ret) => {
return res.json(ret.createdUser);
});
});
followed by this function:
var createFormUser = (ourUser, call) => {
// does a bunch of misc work and creation for another database
// unrelated to current tests.
}
I want to to test this route. Normally, I would just create a sandbox instance of the database so that it can do whatever it wants, make an http request to the route in the test, and finally do expects() in the return from that http call.
However, I don't want the "createFormUser" function to be called, because 1) it does some fancy shit that's really hard to contain for this test 2) I will be testing it elsewhere.
In a normal test I would at this point use sinon to stub the function. But in this case I don't actually have an object reference, since this is all done through HTTP requests to server that mocha spools up when testing.
So my question is the same as the title, how can stub/replace/ignore/etc this method so it doesn't get called during the test?
As stated by #DavidKnipe, all I had to do was export the methods via:
module.exports.createFormUser = (ourUser, call) => { ... }
And was able to both test the method individually and prevent it's execution via a sinon.stub.

i18n with Hogan.js

I just started with node.js and express.js. As server-side templating framework I picked Hogan.js. I am now trying to find out how I can do i18n with Hogan.js, and I found some information in this post. It seems that you always have to pass in the i18n function together with the context of the view. Is it possible to configure this or set this up at a single place in the application? It seems very cumbersome if I have to do this for each and every view separately. Thanks!
You could take a look at Express-lingua which seems to perfectly match your needs.
wrap the render function of hogan if you must
var origional = Hogan.template.prototype.render;
Hogan.template.prototype.render = function (context, partials, indent) {
context['i18n'] = function () {
return function () {
return 'i18n';
};
};
return origional.call(this, context, partials, indent);
};

How do I call a basic YUI3 function from within a normal JavaScript function?

I'd like to call a simple YUI3 function from within a JavaScript function.
Here is some code that does what I want in a very verbose way:
function changeContent (message) {
YUI().use("node", function(Y) {
Y.all('#content-div').setContent(message);
});
}
Is there a better way to do this?
NOTE: I don't want to attach this function to any event, I just want a global changeContent() function available.
If you want the API to exist outside of the YUI().use(...function (Y) { /* sandbox */ }), you can capture the returned instance from YUI().
(function () { // to prevent extra global, we wrap in a function
var Y = YUI().use('node');
function changeContent(message) {
Y.one('#content-div').setContent(message);
}
...
})();
Be aware that there is a race condition here if you use the seed file (yui-min.js) and dynamic loader to pull in the other modules. changeContent could be called before the Node API is loaded and added to Y. You can avoid this by using a combo script up front. You can get the combo script url from the YUI 3 Configurator. There is a performance penalty for loading the modules in a blocking manner up front. You may or may not notice this in your application.
You can do like this:
(function(){
YUI().use("node", function(Y) {
APP = {
changeContent: function(message){
Y.all('.content-div').setContent(message);
}
};
});
})();
Then, you can call changeContent by calling APP.changeContent(message); from anywhere you want. Hope this helps. :D

Resources