How move custom route outside of server.js in jsonServer - javascript

In server.js, I am using json-server. I want to move
server.get('/api/1.0/searchDoc', (req, res) => {
const searchType = req.query['searchType'];
const searchValue = req.query['searchValue'];
res.status(200).jsonp({searchType, searchValue});
});
to route.js then import in server.js. How do I achieve it?
Full code
// json server
const jsonServer = require('json-server');
// create server
const server = jsonServer.create();
// data as router
const allDocData = require('../response.json');
const searchDocData = require('../searchResponse.json');
const dataObj = {
'mockResponse': allDocData,
'searchDocData': searchDocData
};
const router = jsonServer.router(dataObj);
// mid-ware
const middlewares = jsonServer.defaults();
// package.json uses port 4000
const port = 4000;
// live before router
// e.g. http://localhost:4000/api/1.0/searchDoc/?searchType='customerId'&searchValue='1234'
server.get('/api/1.0/searchDoc', (req, res) => {
const searchType = req.query['searchType'];
const searchValue = req.query['searchValue'];
res.status(200).jsonp({searchType, searchValue});
});
// use mid-ware
server.use(middlewares);
// use data
server.use(router);
// user body parser
server.use(jsonServer.bodyParser);
// use mid-ware
server.use(middlewares);
// use router
server.use(router);
// listen
server.listen(port);

Do you mean like this? www.js
const JSONServer = require('jsonserver')
function build() {
const server = JSONServer.create()
server.get('/api/1.0/searchDoc', (req, res) => {
const searchType = req.query['searchType'];
const searchValue = req.query['searchValue'];
res.status(200).jsonp({searchType, searchValue});
});
return server
}
module.exports = build
And on another file index.js for example
const build = require('./www.js')
const server = build()
// use mid-ware
server.use(middlewares);
// use data
server.use(router);
// user body parser
server.use(jsonServer.bodyParser);
// use mid-ware
server.use(middlewares);
// use router
server.use(router);
// listen
server.listen(port);
you can if you just return it.

There are a number of ways this could be achieved - another approach would be to inject the server instance into the route.js module which would enable your app's routing concern to be extracted as:
route.js
/*
Define default module function that configures apps routing for the specified
server instance
*/
module.exports = function(server) {
server.get('/api/1.0/searchDoc', (req, res) => {
const searchType = req.query['searchType'];
const searchValue = req.query['searchValue'];
res.status(200).jsonp({searchType, searchValue});
});
}
server.js
const jsonServer = require('json-server');
/*
Import default module function from route.js module. We'll assing this
function to the configureRoutes variable and call it in the server.js when
needed. This import assumes route.js exists in the same directory of this
source file
*/
const configureRoutes = require('./route.js');
const server = jsonServer.create();
const allDocData = require('../response.json');
const searchDocData = require('../searchResponse.json');
const dataObj = {
'mockResponse': allDocData,
'searchDocData': searchDocData
};
const router = jsonServer.router(dataObj);
const middlewares = jsonServer.defaults();
const port = 4000;
/*
Call configureRoutes() to configure routes on your server instance via the
new route.js module
*/
configureRoutes(server);
server.use(middlewares);
server.use(router);
server.use(jsonServer.bodyParser);
server.use(middlewares);
server.use(router);
server.listen(port);

Related

req.params is throwing "undefined" in Router file

I am doing a practise project in Node/Express.
My server.js looks like this:
const express = require("express")
const app = express()
const bodyParser = require("body-parser")
const morgan = require("morgan")
const { get } = require("http")
const PORT = 3000
const budgetRoute = require("./routes/Budget")
const envelopeRoute = require("./routes/Envelopes")
const envelopeNameRoute =require("./routes/Envelopes_name")
const envelopeTransferRoute =require("./routes/Envelopes_transfer")
global.envelopes = []
global.totalBudget = 0
app.use(bodyParser.json())
app.use(morgan("dev"))
app.use("/envelopes", envelopeRoute)
app.use("/envelopes/:name", envelopeNameRoute)
app.use("/envelopes/transfer/:name", envelopeTransferRoute)
app.use("/budget", budgetRoute)
app.listen(PORT, () =>{
console.log(`Listening on port ${PORT}`)
})
now in my Route file routes/Envelopes_name I have this:
router.put("/", (req,res,next)=>{
const envelopeToChangeName = req.params.name
const envelopeName = req.query.name
const envelopeBudget = req.query.budget
const reqEnvelope = envelopes.find(envelope => envelopeToChangeName)
if(envelopeBudget){
reqEnvelope.budget = envelopeBudget
}
if(envelopeName){
reqEnvelope.name = envelopeName
}
res.status(201).send(reqEnvelope)
})
after sending request localhost:3000/envelopes/groceries?name=taxes it should change the name of the envelope from "groceries" to "taxes". For some reason req.params.name is "undefined" and I have error "TypeError: Cannot set properties of undefined (setting 'name')". When I had it all in one file, without routers, it worked perfectly. Any ideas?
I think you need to add { mergeParams: true } to make the params available, because you use another router file then where you define the route.
See Express docs

Dynamically changing routes in Express

I have an express server. This is my index.js
let some_parameter = some_value;
const configuredHandler = new Handler(some_parameter);
const server = express();
server
.get("*", configuredHandler.handleRequest)
.post("*", configuredHandler.handleRequest)
.put("*", configuredHandler.handleRequest)
.delete("*", configuredHandler.handleRequest);
I am trying to update the routes if some_parameter to the Handler changes. So it should create a new instance of configuredHandler and the routes should automatically pick the new handler.
Ideally I want to be able to change some_parameter anywhere else in the code.
I am not sure how to structure it for this.
Please help.
What you could do is use something similar to a factory. That factory would create a new middleware every time some_parameter changes and save that middleware for future reference.
Whenever one of your routes is called, express would then refer to the current handler in your factory.
I wrote a simple example:
const express = require('express');
class HandlerFactory {
static currentHandler = (req, res) => res.send('Hello');
static setValue(value) {
this.currentHandler = (req, res) => res.send(value);
}
}
const app = express();
app.post('/change-value', (req, res) => {
HandlerFactory.setValue(req.query.value);
res.send();
});
app.use('/handler', (req, res) => HandlerFactory.currentHandler(req, res));
app.listen(3000);
Just run the app, then test its functionality:
$ curl http://localhost:3000/handler
Hello
$ curl -X POST http://localhost:3000/change-value?value=SecondMessage
$ curl http://localhost:3000/handler
SecondMessage
You can use Router module from expressjs
import { Router } from 'express';
const route1 = new Router();
const route2 = new Router();
const route3 = new Router();
route1.get('/', handler1);
route2.get('/', handler2);
route3.get('/', handler3);
..
..
// similarly define other HTTP routes
const routeMap = {
route1,
route2
route3
}
let some_parameter = 'route1';
const server = express();
const selectedRouter = routerMap[some_parameter];
server.use('*', routerMap[some_parameter]);
I have a sample project on Github that uses similar pattern

How can I export the files that I created to my app.js

I'm structuring my code to become more readable and maintainable at the same time.
here is my GET.articles and my INSERT.articles is just the same with this.
const express = require('express');
const router = express.Router();
router.get('/sample', (req, res) => {
res.send("Nice")
})
module.exports = router;
my index.js
const GET_articles = require('./GET.articles');
const INSERT_articles = require('./INSERT.articles');
exports { GET_articles, INSERT_articles}
and I import it like this:
app.use('/example', require('./routes/articles_controller/index'));
This is my error:
SyntaxError: Unexpected token export
Look at your first block of code:
module.exports = router;
Do that.
Change:
exports { GET_articles, INSERT_articles}
to
module.exports = { GET_articles, INSERT_articles}
If you want to use import and export then see this question.
Then note that a plain object isn't something you can just use.
You should use the routers and not the object containing them.
const routers = require('./routes/articles_controller/index');
app.use('/example', routers.GET_articles);
app.use('/example', routers.INSERT_articles);
app.js file
const express = require('express');
const router = express.Router();
const exampleRoute = require('./routes/articles_controller/index');
var app = express();
app.use('/', router)
app.use('/example', router, exampleRoute);
router.get('/sample', (req, res) => {
res.send("Nice")
})
app.listen(3000, ()=>{
console.log("Listening on port 3000")
})
route file
const GET_articles = require('./GET.articles');
const INSERT_articles = require('./INSERT.articles');
module.exports = [GET_articles, INSERT_articles]
GET articles files
module.exports = function getArticle (req, res) {
//Logic as required goes here
res.send("Content to be rendered")
}

access logger from other js modules

I am just starting in nodejs.
I am instantiating a logger (Pino) in server.js which is the entry point. I only want to create one instance of that logger and use it in other modules.
'use strict';
const express = require('express');
const pino = require('pino');
const log = pino({ level: process.env.LOG_LEVEL || 'info' });
const ping = require('./routes/ping'); //new
const app = express();
app.use('/api/ping', ping);
const port = 3000;
app.listen(port, () => {
console.log(`API server started on ${port}... ^C to end`);
});
module.exports = { app, log }; //edited
So in ping.js how do I get access to log in services.js?
const express = require('express');
const router = express.Router();
const { log } = require('../server'); //edited
router.get('/', async function(req, res) {
log.info('someone pinged');
res.sendStatus(200);
});
module.exports = router;
Edited with suggestions.
You can attach the logger as a property on your app object or on app.locals. Then a reference to it will be accessible through req.app.logger or req.app.locals.logger or whatever in your middlewares and route handlers.
'use strict';
const path = require('path');
const express = require('express');
const ping = require('./routes/ping');
const pino = require('pino');
const log = pino({ level: process.env.LOG_LEVEL || 'info' });
var app = module.exports = express();
app
.use('/api/ping', ping);
const port = config.SERVER_PORT || 3000;
app.listen(port, () => {
console.log(`API server started on ${port}... ^C to end`);
});
module.exports = {app,pino}
Now you can import the same pino instance anywhere.
const log = require('./server.js').pino

Dynamically change Express routes on CMS update

I have a project using NextJS, with Express for server side routing.
lib/routes/getPages
const routes = require('next-routes')();
const getEntries = require('../helpers/getEntries');
module.exports = async (app) => {
const { items: [globalSetings] } = await getEntries({
content_type: 'xxxxxxxx',
include: 1,
limit: 1,
});
routes
.add('/', 'index')
.add(`/${globalSettings.fields.blogSlug}/:slug`, 'blog');
return routes.getRequestHandler(app);
};
server.js
const express = require('express');
const next = require('next');
const getPages = require('./lib/routes/getPages');
const app = next();
app.prepare().then(async () => {
const server = express();
const pageRoutes = await getPages(app);
server.use(pageRoutes);
server.listen(3000);
});
I get slugs for routes (such as the blog section) from my CMS API (which is Contentful in this case). I am wondering how I handle an admin changing a slug in the CMS when the app is already running?
Guessing I will need to restart the app for the new slug/route to work. In this case, will I need to use a webhook and listen for changes from the CMS then somehow restart the app programmatically? This could work but might add overhead. Is there a better way to do it?
You can use a workaround in order to do dynamic routes in express. Here's what I'm using in my Typescript app:
// https://github.com/expressjs/express/issues/2596
let dynamicRouter: express.Router
app.use(
(req, res, next) => dynamicRouter(req, res, next),
)
function loadMyRoutes() {
const newRouter = express.Router()
const newMiddleware = // load my new middleware
newRouter.use(newMiddleware)
dynamicRouter = newRouter
}
You can then call loadMyRoutes() in response to a Contentful webhook.
app.post(`/webhook`, () => {
loadMyRoutes()
})

Categories

Resources