Does the middleware of mongoose also refer to the middleware of express? - node.js

I'm just trying to get a grasp of what middleware refers too. At first I thought it was functions used in the framework express. Although now I'm getting a sense that they simply just refer to functions that get in the middle between asynchronous functions.
I know it's common to see next() get used to move from one middleware to the next. Both express and mongoose have the next() call with similar names. I'm concerned as I don't see mongoose or express refer to each other in their documentation. So this leaves me to believe the context of their middleware is just for themselves.
http://mongoosejs.com/docs/middleware.html
http://expressjs.com/en/resources/middleware.html
When combining express with mongoose are all the middlewares lined up together/concatenated or is it separate?
e.g. together/concatenated
- calling next() on mongoose will also trigger expresses middleware function
e.g. Separate
- mongoose just has it's middleware next() just move for pre/post hooks
- express also just has it's middleware next() just move towards it's supported middleware functions

Short answer: they're separate.
Longer answer: By convention, most middleware stacks implement some kind of next function to call in order to proceed down the stack and call each middleware function in turn.
It's a matter of scope. Express and Mongoose both have their own independent middleware stacks, so what the next function does depends on where it gets called. As a general rule of thumb, every function-- including the anonymous functions used for callbacks that accept a next parameter-- have their own scope.
Consider the following really brief example of differently scoped, but otherwise identical parameter names:
function doSomething(arg) {
console.log(arg)
function doSomethingElse(arg) {
console.log(arg);
}
doSomethingElse('different');
}
doSomething('original');
// Outputs
// > 'original'
// > 'different
Even though doSomething and doSomethingElse both have a parameter called arg, the value logged to the console by doSomethingElse is the value actually passed to that function-- the value of arg as scoped to the function it was called in, not the scope surrounding it.
This is true for Mongoose middleware applied within Express middleware (or vice-versa): they just happen to share a similar, conventional parameter name.
As a learning experiment, you should deviate from conventions for a moment (but not forever; conventions exist for a reason!) to name your Express and your Mongoose next parameters something else in a single file-- expressNext and mongooseNext, perhaps-- to help differentiate them in your mind.

Related

Typescript change type of the Request after checkAuth middleware

I'm pretty new to typescript and I faced the issue with extending the Request type. I actually found a solution, but it doesn't feel right to me, and seems like there might be a better way.
First, the structure. I have a middleware checkAuth that checks the Bearer token, finds the user in the database (or creates one, in case it's the first time) and adds user to the req variable.
Most people recommend modifying the Express' Request type with custom declarations. I don't like this idea, because that will put user object into all requests, even before I actually save user into req.
Another solution is what I use now:
interface ReqWithUser extends Request {
user?: {
...
}
}
This allows me to declare req: ReqWithUser. But there's a flaw. When I try to access req.user, typescript is telling me that it's possibly undefined. Well, that's exactly what I declared with user?:. If I don't put a question mark there, then typescript is mad in router, saying Property 'user' is missing in type Request. That's fair. One of the solution is to use req!.user. Solves all problems, but it still feels imperfect to me. I know the req.user is there, it's not optional, otherwise checkAuth would fail and return 401. If it didn't, the user is there. What feels like the right solution is somehow modify the req type after the checkAuth middleware. Because that's when user is added into the req. Is it possible?
The issue has nothing to do with your types, but it's the fact that Express will always emit Request and not RequestWithUser.
So in your middleware function, you will always get a Request. The only reason RequestWithUser is acceptable is because you made it optional.
Truth is the middleware / decorator pattern doesn't work that well with express. You have a few options (some of which you mentioned)
Use declaration merging to 'patch' the built-in Request. You already mentioned you don't like this though, because it's a bit of a hack.
Don't use Express' middleware system and instead write something that understands how types change with decorators. I don't know exactly what this looks like, or if this has been done before.
Whenever you want to use RequestWithUser in your controllers/middlewares start off with an assertion function to ensure that user exists (allowing you to make it non-optional).
Cast to RequestWithUser, when you need it.
All these options have drawbacks:
You don't like for the reasons mentioned. It's not always 'accurate' so you are sort of lying to Typescript for convenience.
Sounds hard to do
Requires the use of an assertion function, which means you need to do a little extra work every time you want to use the user property. This work is not needed because you as developer know.
You probably don't like casting for the same reason you don't like to use declaration merging.
By far I think 2 is the best solution, because it gives you the advantage of typing without any hacks and without having to do the extra work of an assertion function (which happens during runtime). But it means abandoning Express' Middleware system. I wouldn't know exactly how to write this code, but I am curious how if it can be done...
FYI I opened another stack overflow question, because I am curious:
Typescript typing for decorator middleware patterns

Add properties to the req object in expressjs with Typescript

I tried to migrate my express server code from js to typescript and ran into issues when trying to access fields I added to the request object in my own middleware functions.
For example, I am doing something like this:
app.use((req, res, next) => {
let account = checkAuthentication(req);
if(account) {
req.authenticated = true;
req.account = account;
next();
}
});
Now I want to access those properties later on in my other middleware functions, but the .d.ts file from #types/express defines the req object the same way for all middleware functions of course.
Now I came up with two ways to deal with this, but both seem bad:
Use a typeguard in every middleware function. But then I add useless code to the js output because my routes are setup in a way so that I know at "compile" time what shape my req object has in each middleware function.
Use a type assertion in every middleware function. But then I don't get the benefits of typescript, despite writing my code so that all types are know at compile time, because I basically disable typechecking for the req object then.
So my question is: How, if at all, can I utilize typechecking in that scenario? If I can't, does that mean a framework like express is impossible in a statically typed language (like C#)?
You can use module augmentation to extend the Request type defined in the express module
declare global {
namespace Express {
export interface Request {
account: Account;
authenticaticated: boolean
}
}
}

How to use express-async-handler

I am going through some code on github: https://github.com/linnovate/mean/blob/master/server/routes/user.route.js
But there is a portion of it I don't understand, that is:
router.route('/')
.post(asyncHandler(insert));
On npm express-async-handler
is described as:
Simple middleware for handling exceptions inside of async express routes and passing them to your express error handlers.
They go give an example of how to use the module, but it doesn't explain much.
So my questions are:
How is the insert function on line 12 called without parentheses?
What is the function of asyncHandler(), what would the code look like if you decide on not using it?
Normally when using router.route('/').post there are curly braceswhich follow. In this code I cant see any. So my question are: Is the async function insert part of the function body of router.route('/').post? and if not then why are there no curly braces?
What exactly is being exported here user.controller.js on line 14 (is it an object, a var...)? What is the advantage of exporting it this way? Why not just export the function insert()?
Thank you in advance.
How is the insert function on line 12 called without parentheses?
The insert function is not called here. It is passed to asyncHandler() as a function reference so it can be called later. It is asyncHandler() which is called immediately and that returns a new function that is passed to .post() as the request handler.
What is the function of asyncHandler(), what would the code look like if you decide on not using it?
This is a wrapper around insert that looks for a rejected promise returned from the function and, if found, calls next(err) automatically.
Normally when using router.route('/').post there are curly braceswhich follow. In this code I cant see any. So my question are: Is the async function insert part of the function body of router.route('/').post? and if not then why are there no curly braces?
I'm not sure what you mean by curly braces. .post() expects a function reference to be passed to it that will be called with a certain set of parameters when the defined route matches an incoming request. It can use as either of these:
// externally defined request handler function
router.route('/').post(someRequestHandlerFunc);
// inline defined request handler function
router.route('/').post(function(req, res, next) {
// code here for the request handler
});
What exactly is being exported here user.controller.js on line 14 (is it an object, a var...)? What is the advantage of exporting it this way? Why not just export the function insert()?
I'm assuming the line 14, you're asking about is here. That's just exporting the insert function on the insert property of this modules exports. When you export a function, you don't use insert(). That calls the function immediately. You just refer to the function's name as insert to export a reference to the function that can be called later.
The reason to export is as a property of an object rather than just export the single function is to make the module extensible so it can export other things as different named properties.

Best way to add helper methods to context object in Koa2

I would like to add method such as view and json to the context object passed to my controllers. I do this in a middleware that runs before everything else:
async function(ctx, next){
ctx.view = view.bind(ctx);
ctx.json = json.bind(ctx);
await next()
ctx.renderer.render();
}
these methods set some conventional configuration object (Renderer) that the middleware interprets and then renders out the actual response by setting the correct ctx.body. That allows me to switch template language easily and have an easier time combining API and Template requests.
Except it doesn't work because after await next() the ctx.renderer is the default one, not the one set by controllers. I suspect it's a namespacing issue, but I am not sure where it comes from.
What's the best practice to attach functions to the context that can reference context without it being passed to them?
Ok it's here in the docs I just missed it, the docs are inside a repo and are not hosted, which makes them hard to navigate.
TL;DR: use app.context to access the context prototype. Adding functions there attaches them to the context object and allows you to use this from within to access it.

How to call callback function in another callback function in node.js

How to call callback function in within callback function in node.js
callbacks are simply parameters in JS, just like others
just pass it to other functions
also notice that JS is lexical scoping
so make sure ur callback parameter in the scope or outer scope
--> What is lexical scope?
Call back functions in node js are no different than those in javascript. This is one way you can call it.
function someFunction(callback){
callback(params);
}
the call back function can be defined as any normal function.For example
function random(number){
return Math.random()};
the function someFunction can now be called as
someFunction(random);
That's it.The important thing to understand here is that node js is still javascript.So everything trick that works in javascript will work in node js.

Resources