ExpressJs - dbQuery is not defined - javascript

In console, when I go to specific item id I have error(ExpressJs):
ReferenceError: dbQuery is not defined
My api.js
var express = require('express'),
Bourne = require('bourne'),
bodyParser = require('body-parser'),
db = new Bourne('data.json'),
router = express.Router();
....
.route('/contact/:id')
.get(function (req, res) {
db.findOne(req,dbQuery, function (err, data) { //problem
res.json(data);
});
})
....
module.exports = router;

dbQuery is not defined? If its coming from a form it needs to be req.body.dbQuery or req.query.dbQuery.
If set somewhere else, req.dbQuery needs to be a dot not a comma.

Related

How to pass DB object in multi router setting in ExpressJS?

I would like to make multiple router settings like the example in ExpressJS Doc.
I have index.js , api1 , api2 like below.
How can I pass the db object from index.js to api1 and api2?
I try with
app.use('/api/v1', require('./controllers/api_v1')(db));
but it shows errors:Router.use() requires a middleware function but got a Object
index.js:
var express = require('../..');
const knex = require('knex');
const config = require('./config');
var app = module.exports = express();
const db = knex(config.db);
app.use('/api/v1', require('./controllers/api_v1'));
app.use('/api/v2', require('./controllers/api_v2'));
app.get('/', function(req, res) {
res.send('Hello from root route.')
});
/* istanbul ignore next */
if (!module.parent) {
app.listen(3000);
console.log('Express started on port 3000');
}
api_v1.js
var express = require('../../..');
var apiv1 = express.Router();
apiv1.get('/', function(req, res) {
res.send('Hello from APIv1 root route.');
});
apiv1.get('/users', function(req, res) {
res.send('List of APIv1 users.');
});
module.exports = apiv1;
api_v2.js
var express = require('../../..');
var apiv2 = express.Router();
apiv2.get('/', function(req, res) {
res.send('Hello from APIv2 root route.');
});
apiv2.get('/users', function(req, res) {
res.send('List of APIv2 users.');
});
module.exports = apiv2;
You could export the db object from a database.js file and require it in the index.js file as well as every other file where you need database access. Or, an easier but uglier method, would be to make the variable global via global.db = db. You could then use db everywhere in your Node.JS application.

Export functions or variables to another module in node.js

I know there are lots of questions similar to mine but I could not find the best solution.
I am creating a web app with node and rethinkdb. I want to organise different js files (modules) so that each has specific task.
I have this query.js file whose query result must be passed to routes.js file.
I have tried implement this in the following way.
query.js
//dependencies
var express = require('express');
var path = require('path');
var r = require('rethinkdbdash')({
port: 28015,
host: 'localhost',
db: 'stocks'
});
var len;
//function to get companies list
exports.clist = function(){
r.table('company')
.run()
.then(function(response){
return response;
})
.error(function(err){
console.log(err);
})
}
console.log(exports.clist[0].id)
//function to get number of entries in database
exports.clen = function(){
r.table('company')
.run()
.then(function(response){
len = Object.keys(clist).length;
return len;
})
.error(function(err){
console.log(err);
})
}
routes.js
//dependencies
var express = require('express');
var request = require('request');
var path = require('path');
var r = require('rethinkdbdash')({
port: 28015,
host: 'localhost',
db: 'stocks'
});
//query module
var query = require('./query')
clist = query.clist();
clen = query.clen();
//create router object
var router = express.Router();
//export router
module.exports = router;
//home page
router.get('/', function(req, res) {
console.log('served homepage');
res.render('pages/home');
});
//--companies page--//
router.get('/company', function(req,res){
console.log('served companies page')
res.render('pages/company', {
clist: clist,
x:clen
});
});
the console log in query.js is showing that cannot read property id of undefined.
Also I would like to know is there a way to directly pass the variables instead of using functions and then calling it.
I apologise if the solution is obvious.
To summarise I want the query result which is an object to be accessible from routes.js file.
Note: As exports.clist1 is an asynchronous method, you can't expect the result to be printed in the next line, hence comment this line and follow as below
//console.log(exports.clist[0].id)
You have to register a middleware to make this working, otherwise, query will be called only at the time of express server started and not at every request.
So you can do like this,
Hope you had something like this in your startup file (app.js),
var app = module.exports = express();
routes.js
//query module
var query = require('./query')
var app = require('../app'); // this should resolve to your app.js file said above
//clist = query.clist();
//clen = query.clen();
// middleware to populate clist & clen
app.use(function(req, res, next){
query.companyList(function(err, data){
if(!err) {
req.clist = data.clist;
req.clen= data.clen;
}
next();
});
});
query.companyList(function(err, data){
if(err) {
console.log(err);
} else {
console.log(data.clist[0].id);
console.dir(data.clist);
}
});
//create router object
var router = express.Router();
//export router
module.exports = router;
//home page
router.get('/', function(req, res) {
console.log('served homepage');
res.render('pages/home');
});
//--companies page--//
router.get('/company', function(req,res){
console.log('served companies page')
res.render('pages/company', {
clist: req.clist,
x: req.clen
});
});
Change your query.js like this,
//function to get companies list
exports.companyList = function(next){
r.table('company')
.run()
.then(function(response){
var list = {
clist: response,
clen: Object.keys(response).length
};
next(null, list);
})
.error(function(err){
console.log(err);
next(err);
})
};

Why is my route not being hit?

Hi I have an express router that seems to not get hit when I navigate to the proper route. In my app.js:
var auth = require('./routes/auth');
app.use('/auth', auth);
In my routes/auth.js
var express = require('express');
var authRouter = express.Router();
var mongodb = require('mongodb').MongoClient;
var router = function(){
authRouter.route('/signUp')
.post(function (req, res){
console.log("Hello world");
});
return authRouter;
};
module.exports = router;
In my index.jade:
form.login-form(role='form', action='/auth/signUp', method='post', name='signUpForm' )
.form-group
label.sr-only(for='form-username') Username
input#form-username.form-username.form-control(type='text', name='userName', placeholder='Email...')
.form-group
label.sr-only(for='form-password') Password
input#form-password.form-password.form-control(type='password', name='password', placeholder='Password...')
button.btn(type='submit') Sign up!
However when I try to go to /auth/signUp all I get in terminal is: GET /auth/signUp - - ms - -
POST /auth/signUp - - ms - -
It seems to me that my auth/signUp is never hit. I was originally trying to console.log my req.body however I cannot even log a hello world.
You're wrapping your router in a function which is never called. Try just doing this instead:
var express = require('express');
var authRouter = express.Router();
var mongodb = require('mongodb').MongoClient;
authRouter.route('/signUp').post(function (req, res){
console.log("Hello world");
});
module.exports = authRouter;
first, you shouldn't really use cased urls like signUp. Try this:
var express = require('express');
var authRouter = express.Router();
var mongodb = require('mongodb').MongoClient;
var router = function(){
authRouter.post('/sign-up', function (req, res) {
console.log("Hello world");
});
return authRouter;
};
module.exports = router;
You are using wrong way of defining routers. Use this way instead.
var express = require('express');
var authRouter = express.Router();
authRouter.post('signUp', function(req, res) {
// in this code block you have to render text, html or object
res.render('index'); // or may be res.json(some_obj);
})

reading a file to use within an express route

I am trying to implement a search functionality for my app. I have an express route to get incoming search terms.
Here is the entirety of my router file:
var express = require('express');
var router = express.Router();
var bodyParser = require('body-parser');
var searchutil = require('../utils/searchhandler');
router.use( bodyParser.json() );
router.use(bodyParser.urlencoded({
extended: true
}));
router.post('/api/search', (req, res, next) => {
var term = req.body.searchTerm;
console.log(term);
searchutil();
res.json({test: 'post received'});
});
module.exports = router;
And here is my searchhandler file which is being including in my router:
var fs = require('fs');
var findResults = function() {
var items = fs.readFile('./server/assets/items.json', 'utf8', (err, data) =>{
if (err) throw err;
console.log(JSON.parse(data));
return JSON.parse(data);
});
}
module.exports = findResults;
This is all working just fine and dandy. it basically just prints out the contents of './server/assets/items.json' on the server when a post request route of '/api/search' is hit. The question I had was about using the json file within my router file. Say my router file was:
var express = require('express');
var router = express.Router();
var bodyParser = require('body-parser');
var fs = require('fs');
var items = fs.readFile('./server/assets/items.json', 'utf8', (err, data) =>{
if (err) throw err;
console.log(JSON.parse(data));
return JSON.parse(data);
});
router.use( bodyParser.json() );
router.use(bodyParser.urlencoded({
extended: true
}));
router.post('/api/search', (req, res, next) => {
var term = req.body.searchTerm;
console.log(term);
console.log(items);
res.json({test: 'post received'});
});
module.exports = router;
So now my router file is getting the file asset and trying to print it out within my router.post('/api/search', ...); function. The problem that occurs is that when it attempts to print it in that function items appears to be undefined, but the print from within the fs.readFile(); correctly logs the contents of the file. I think this is some sort of scope issue I am running into with JS, but I am not sure how to explain it to myself so I thought I'd ask it here why it is working one way, but not the other.
You should use a callback:
var getItems = function(cb) {
fs.readFile('./server/assets/items.json', 'utf8', (err, data) {
if (err) cb({error: err});
console.log(JSON.parse(data));
cb({items: JSON.parse(data)});
});
};
And then change the route to:
router.post('/api/search', (req, res, next) => {
var term = req.body.searchTerm;
console.log(term);
getItems(function (cb) {
if (!cb.error) {
console.log(cb.items);
res.json({test: 'post received'});
}
});
});

externalizing route.param() calls in Express.js

I want to extract some repetitive code into a single module in Node.js and Express.js
Together.js
var express = require('express');
var boom = require('express-boom');
var app = express();
var app.use(boom());
app.param('user', function(request, reply, next, id){
request.db.users.get(id, function(err, userInfo){
if (err) reply.boom.badImplementation(err);
else if (!userInfo || !userInfo.length) reply.boom.notFound();
else {
request.user = userInfo[0];
next();
}
})
})
app.get('/api/users/:user', function(request, reply){
reply.json(request.user);
});
app.listen(3000);
I have multiple routes I want to use this param conversion including: /users/:user, /api/users/:user, /checkout/:user/:barcode, etc. but each of the root routes (i.e. users, api, checkout) are in their own file and I am attaching them with app.use('/users', userRoutes);. As it is, I will have to put my user param conversion into EACH of these sub-route modules.
I would like to have an interceptors.js where I make all of the common param interceptor functions and only write them once. Here is an example of how I thought it would work.
app.js
var express = require('express');
var app = express();
app.use(require('./routes/interceptors'))
app.use('/users', require('./routes/users'));
app.use('/api', require('./routes/api'));
app.use('/checkouts', require('./routes/checkouts'));
app.listen(3000);
./routes/api.js
var express = require('express');
var api = express.Router();
api.get('/users/:user', function(request, reply){
reply.json(request.user);
});
module.exports = api;
./routes/interceptors.js
var express = require('express');
var boom = require('express-boom');
var interceptors = express.Router();
var interceptors.use(boom());
interceptors.param('user', function(request, reply, next, id){
request.db.users.get(id, function(err, userInfo){
if (err) reply.boom.badImplementation(err);
else if (!userInfo || !userInfo.length) reply.boom.notFound();
else {
request.user = userInfo[0];
next();
}
})
})
module.exports = interceptors;
There would of course be another file for each of checkout.js and users.js and they will be the same principal as api.js
When I do the above, the param interceptor is never run. No errors are throw that I can see.
Thank you all for any help you may provide,
Rhett Lowe
This can't be done.
Param callback functions are local to the router on which they are defined. They are not inherited by mounted apps or routers. Hence, param callbacks defined on app will be trigerred only by route parameters defined on app routes.
http://expressjs.com/api.html#app.param
Another approach you could do is to have a module with your interceptors and require it in your route files where necessary.
./routes/api.js
var express = require('express');
var api = express.Router();
var interceptors = require('./interceptors');
api.use('user', interceptors.user);
api.get('/users/:user', function(request, reply){
reply.json(request.user);
});
module.exports = api;
./routes/interceptors.js
exports.user = function(request, reply, next, id){
request.db.users.get(id, function(err, userInfo){
if (err) reply.boom.badImplementation(err);
else if (!userInfo || !userInfo.length) reply.boom.notFound();
else {
request.user = userInfo[0];
next();
}
})
})
module.exports = interceptors;

Categories