Run a function when an api route is mounted - javascript

I am using express router for my app. I need to run a function when a particular route is mounted. I have two files, index.route.js and currentUser.route.js
index.route.js
import currentUserRoutes from './currentUser.route';
const router = express.Router();
//mounts the '/me' route on currentUserRoutes
router.use('/me', currentUserRoutes);
export default router;
currentUser.route.js
const router = express.Router();
//line below throws an error
router.on('mount' , () => {console.log("me route mounted")});
router.route('/')
.get(currentUserCtrl.get)
export default router;
It throws an error saying router.on is not a function, I have tried placing the router.on part in index.route.js too, but there too I am getting the same error. Any help would be appreciated.

try this:
router.on('mount' , function(){console.log("me route mounted")});

Related

Set a module export before the file finishes in Node.js module (`import`/`export` syntax)

I am creating an API using express and I want to have a file for each endpoint. Ideally, I'd want to create the router in it's file, have it be exported and then import the endpoints files so they're run. The endpoint files would import the router again and then use .get, or .post or whatever to create the actual endpoint on the router.
So basically, my goal is to have one file run another file that uses a value the first file exports before running the different file.
I've done this before in a project using the require() syntax, but now I am trying to translate this to import/export syntax for a different project.
Before, I've (successfully) used something like this in another project:
Router.js
const express = require("express");
// Create and export a new router
const TestRouter = express.Router();
module.exports = TestRouter;
// Make the endpoints register themselves
require("./getdata.js");
require("./createdata.js");
And then in the endpoints (getdata.js and createdata.js):
const TestRouter = require("./TestRouter.js");
TestRouter.get("/:id", async (req, res) => {
// ...
});
Now, I am trying to do the same with package syntax (import/export):
TestRouter.js
import { Router } from "express";
// Create and export our new router
const TestRouter = Router();
export default TestRouter;
// Import endpoints so they can register themselves
import "./getdata.js";
import "./createdata.js";
Endpoints (getdata.js and createdata.js):
import TestRouter from "./TestRouter.js";
TestRouter.get("/:id", async (req, res) => {
// ...
});
But this direct translation doesn't work.
When I now try to run this project, I get an error like this:
file:///.../src/routes/getdata.js:3
TestRouter.get("/:id", async (req, res) => {
^
ReferenceError: Cannot access 'SessionRouter' before initialization
at file:///.../src/routes/getdata.js:3:1
...
My most likely guess for the problem at the moment would be that exports in modules aren't actually set at the time of the export statement, but rather when their respective file reaches the end after processing everything else.
So my question would be if there was a way to set the export at the time of the export statement, or perhaps an easy way (about 1-2 lines in the endpoint files) to make the endpoints wait for the TestRouter to actually be set before calling .get, .post or whatever on it.
I know I could have the endpoint files just export the actual endpoint handlers:
const getdata = async (req, res) => {
// ...
}
export default getdata;
and then have the .get calls in the router file:
import { Router } from "express";
// Import endpoint handlers
import getdata from "./getdata.js";
// Create our new router
const TestRouter = Router();
// Register endpints
TestRouter.get("/:id", getdata);
But I would like to avoid this - if at all possible - because every endpoint will need different middleware configurations, meaning that I have to specify all the middleware in the TestRouter.get (etc.) calls, which I don't really want to cram into the router file due to readability.
You can solve this by splitting TestRouter.js into two parts:
The part that creates the router (let's leave that in TestRouter.js)
The part that loads the endpoints (let's call that main.js)
...and make the second part your entry point. That breaks the cycle between TestRouter.js and getdata.js/createdata.js that causes the latter to try to access the exported binding from TestRouter.js before it's initialized.
main.js:
// Create and export our new router
import TestRouter from "./TestRouter.js";
// Or, actually, just: import "./TestRouter.js";
// Import endpoints so they can register themselves
import "./getdata.js";
import "./createdata.js";
TestRouter.js:
import { Router } from "express";
// Create and export our new router
const TestRouter = Router();
export default TestRouter;
getdata.js / createdata.js remain unchanged.

grouping express routes into a single file

I trying to express routes into a single file using app.use
app.js
import express from 'express'
import testRouter from 'testRouter'
const app = express()
app.use('/testRouter', testRouter)
app.listen(3000)
testRouter.js
import express from 'express'
const router = express.Router
router.get("/page1", function (req, res){
res.send("test")
})
export default router
using module exports is a official ways to do it and it worked
But why doesn't the router definition inside a function work like bellow?
app.js
import express from 'express'
import testRouter from 'testRouter'
const app = express()
app.use('/testRouter', function (){
const router = express.Router()
router.get("/page1", function (req, res){
res.send("test")
})
return router
}))
app.listen(3000)
I don't believe the code inside app.use('/test/Router', function() { }) executes until a user has visited your test/Router page at least once. I'm also not sure if you can use a middleware ("use") without having an eventual terminal endpoint.
Because in the official documentation testRouter is an Object
app.use('/testRouter', Object)
You put the function
app.use('/testRouter', Functon)

Exception while using a router object in a typescript class in nodejs

I have a nodejs service in typescript. I'm trying to set a separate routing layer in the application.
I have a app.js file where in
let IndividualRoute= require('./routing/IndividualRoute');
app.use('/users', IndividualRoute);
I have create a IndividualRoute.ts file where im trying to use router object like below
import express = require('express');
import individualValidation from '../users/IndividualValidation';
let router = express.Router();
class IndividualRoute {
router.get('/individualList', individualValidation.list);
}
export = IndividualRoute;
When i try to do the above, i get the below exception
I tried the below things
router.get('/individualList', (request, response) => {
response.send('Hello world!');
});
But i get the same issue. Also if i remove the class and have a simple file without class then i don't get this exception.
Basically what im trying to do is, if the route matches it should hit the respective function in the IndividualValidation file like in below case
router.get('/individualList', individualValidation.list);
If the route is users/individualList it should hit individualValidation.list function with the request data. Basically im trying to do what is marked as answer in the below link
express.Router() vs. app.get
Any suggestion what i'm doing wrong.
You're writing a class. Inside a class, put the constructor and methods. You can't write code directly here. The line you wrote needs to be in the constructor or in a method.
class IndividualRoute {
constructor(){
router.get('/individualList', individualValidation.list);
}
}
In IndividualRoute.ts, please make the following changes:
import { Router } from 'express';
import individualValidation from '../users/IndividualValidation';
let router = Router();
router.get('/individualList', individualValidation.list);
export default router;
Also, if using typescript, why you have app.js? I'll suggest using typescript for that file also. One more suggestion would be to have index.ts in your routing folder with code:
import { Router } from express;
import IndividualRoute from "./IndividualRoute";
let router = Router();
router.use("/users", IndividualRoute); // set this for each individual route
/*
* e.g.
* router.use("/auth", auth);
*/
export default router;
So in your app.ts, all you have to do is:
import * as express from "express";
import routes from "./routing";
let app = express();
app.use(routes);
// other code
I hope you find this helpful!

Express : router object and methods

I have
var router = express.Router();
router.get('/', function(req, res) {
//something
}
module.exports = router;
Is the router created, the get method executed and the router exported, or is it that the router is created, the method is define for this router (not executed) and the router is exported afterwards?
Second one. Router is created, method is defined and router is exported. That method will be executed when browser sends get request on '/' url, if you correctly require exported router.

Routes with a wrong format

I am working with Nodejs and I am trying to figure out why my routes are getting a wrong format, look at this example
I have a service named Dealers, and these are the routes
import express from 'express';
const router = new express.Router();
// POST METHODS
router.post('/create-dealer', require('./create-dealer'));
router.post('/update-dealer', require('./update-dealer'));
router.post('/deactive-dealer', require('./deactive-dealer'));
// GET METHODS
router.get('/get-dealers', require('./get-dealers'));
export default router;
and the general app.use
import { Router } from 'express';
const router = new Router();
router.use('/create-dealer', require('./dealers'));
router.use('/get-dealers', require('./dealers'));
router.use('/update-dealer', require('./dealers'));
router.use('/deactive-dealer', require('./dealers'));
export default router;
now, in order for me to work with this routes, I have to do for example in Postman
POST > http://localhost:8080/create-dealer/create-dealer
and why not only
POST > http://localhost:8080/create-dealer
what am I doing wrong?
In your app.js it should be:
import { Router } from 'express';
const router = new Router();
router.use(require('./dealers'));
export default router;
Because you already have the paths specified in dealers.js.
You're inserting that create-dealer segment twice by having it both in the .use file and again in the './dealers' file.
Either eliminate it where you use it:
router.use('/create-dealer', require('./dealers'));
to
router.use('/', require('./dealers'));
...which may mean you have to refactor './dealers' or you'll need to do the reverse, leave it with router.use and remove it in the dealers code.

Categories