Understand how middleware works in Moleculer - moleculer

I understand Mix-ins are to extend a common functionality across services. But Im not able to understand how middleware works in molecular and what problems It could help me solve.

Check the documentation how middleware works in Moleculer framework: https://moleculer.services/docs/0.13/middlewares.html
With middlewares you can extend the framework functionality with your custom logic.
Here is an example how a middleware looks like which extend service action handling:
const MyCustomMiddleware = {
// Wrap local action handlers (legacy middleware handler)
localAction(next, action) {
return function(ctx) {
// Change context properties or something
return next(ctx)
.then(res => {
// Do something with the response
return res;
})
.catch(err => {
// Handle error or throw further
throw err;
});
}
}
};

Related

Vue2 Composition Api - How do I fetch data from api?

I am using Vue2.6 with composition api.
I need to reroute to different pages depends on an api response.
Can someone please guide me, please?
I tried using onBeforeMount but it renders the UI elements then rerouted to the corresponding page to the api response..so I can see a flash of the wrong UI..
setup() {
const myData = 'myData';
onBeforeMount(async () => {
try {
const results = await fetchData();
// do reroute depends on results response
}
} catch (err) {
console.log(err);
}
});
return {
myData,
};
I also tried adding async in the setup method but it errored saying my ref variables "Property or method "myData" is not defined on the instance but referenced during render."
async setup() {
const myData = 'myData';
onMounted(async () => {
try {
const results = await fetchData();
// do reroute depends on results response
}
} catch (err) {
console.log(err);
}
});
return {
myData,
};
It looks like you're trying to handle routing (re-routing) dynamically from inside a component. I can't see the rest of the apps, so can't speak to the validity of such a solution, but would like you dissuade you from doing that. routing logic should, IMO, not be handled in a component. The components should mostly just handle the template and user interaction. By the time you're rendering a component, that API should have been resolved already.
I would recommend to resolve the API response before the route is
even completed. You or use a navigationGuard to resolve the API during the route execution. This functionality is asynchronous, so you can await the response before proceeding.
Alternatively, if you really want to handle it in the component, you will have that delay while the API is resolving, but you can implement some loader animation to improve the experience.

express-validator on PUT methods

I'm creating an API and decided to use express-validator for validation (duh), I've never used this before so I'm unsure on some aspects of it so my validations might not be the best but I'm getting by.
I have built two validation middle ware using this and export them from the same folder like this:
module.exports = {
create: require('./create'),
update: require('./update')
}
So I can then do this in my router:
const validation = require('../validations/plotValidation')
// ...
router.get('/', controller.all)
router.post('/create', validation.create(), controller.create)
router.get('/:plotId', controller.read)
router.put('/:plotId/update', validation.update(), controller.update)
router.delete('/:plotId/delete', controller.delete)
// ...
I'm not good enough with express-validator to do both validate both routes with the same file, maybe I'll try it at some point, anyway.
The .post method works fine and validates everything I want it to however the .put method just seems to be ignoring every check here are is file in case you want to see the checks:
const { body, check, param } = require('express-validator');
module.exports = () => {
return [
param('plotId')
.exists().withMessage('URI requires plot id'),
body('price')
.optional()
.isObject()
]
}
As you can probably tell I only just stated it, but even with only these two tiny checks it just doesn't seem to run.
Does express-validator not work on PUT methods?
For anyone else who has this issue I solved this by using .run on my checks, you can read more about this here essentially this is the code that saved me:
// parallel processing
const validate = validations => {
return async (req, res, next) => {
await Promise.all(validations.map(validation => validation.run(req)));
const errors = validationResult(req);
if (errors.isEmpty()) {
return next();
}
res.status(400).json({ errors: errors.array() });
};
};

add middleware function to an async export

I have separated my routes with their definitions so that my routes look like this:
const router = require('express').Router();
const handle = require('../handlers');
router.post('/register', handle.register);
// The handler defines the route. Like this:
exports.register = async (req, res, next) => {
try {
const user = await db.User.create(req.body);
const {id, username} = user;
res.status(201).json({id, username});
} catch (err) {
if(err.code === 11000){
err.message ='Sorry, details already taken';
}
next(err);
}
};
This works fine. Now I need to upload images as users register (using multer middleware). A lot of the examples show multer is used like this:
router.post('/register', upload ,function (req, res, next) { //upload is the multer middleware
console.log(req.file);
})
How do I add the middleware in my case?
You add the middleware like this:
router.post('/register', upload, handle.register);
Just like the examples you see.
In My Not-So-Humble Opinion
You mention that you have separated your routes from your route handler. In my opinion this is not only misguided but completely wrong.
In the usual MVC architecture you see in other languages, the route and the route handler together makes the controller. In your design you have split your controller into two separate structures. Primarily, this makes your route handling logic and the information of what route it does it for exist in two separate files when they should be located very close to each other.
Now that you are adding middlewares you are finding out that middleawares are installed in routes and with your design it is hard to figure out what middleware is installed for your route handler.
The correct way to separate your business logic from your routes is to follow the MVC design pattern - separate your Model from your Controller (the View is free because it is basically res.json()).
In my not-so-humble opinion you should be creating a model for your user instead of separating controllers into two parts. Your user obviously need a register functionality and the register function should just succeed or fail but should not concern itself with any HTTP error handling because that is the controller's job:
exports.user = {
// .. other methods
register: async function (username, password) {
try {
const user = await db.User.create({username, password});
return user;
} catch (err) {
if(err.code === 11000){
err.message ='Sorry, details already taken';
}
throw err;
}
}
}
Then in your controller (most Express example call "route") you do:
const user = require('./user');
router.post('/register', upload , async (req, res, next) => {
try {
const user = user.register(req.body.username, req.body.password);
const {id, username} = user;
res.status(201).json({id, username});
} catch (err) {
next(err);
}
})
However, this is just my personal opinion.

Nuxt custom module hooks not called

I want to pass some extra data from the ssr server that's present after the middleware has run, and use that on client side middleware. A bit similar to what nuxt already does with vuex.
Documentation at the render:context hook:
Every time a route is server-rendered and before render:route hook. Called before serializing Nuxt context into window.__NUXT__, useful to add some data that you can fetch on client-side.
Now my custom plugin defines some hooks as stated in the documentation, but not all seem to be called properly:
module.exports = function() {
this.nuxt.hook('render:route', (url, result, context) => {
console.log('This one is called on every server side rendering')
}
this.nuxt.hook('renderer', renderer => {
console.log('This is never called')
}
this.nuxt.hook('render:context', context => {
console.log('This is only called once, when it starts loading the module')
}
}
What am I doing wrong and how can I pass custom ssr data to the client side renderer?
Ok, just found the solution to the core problem of passing custom data from the (ssr) server to the client:
Create a plugin: plugins/my-plugin.js
export default ({ beforeNuxtRender, nuxtState }) => {
if (process.server) {
beforeNuxtRender(({ nuxtState }) => {
nuxtState.myCustomData = true
})
} else {
console.log('My cystom data on the client side:', nuxtState.myCustomData)
}
}
Then register the plugin in your nuxt.config.js:
module.exports = {
plugins: ['~/plugins/my-plugin']
}
Docs here.

noflo like expressjs middleware

I'm new in noflo and I'd like to use it like expressjs middleware.
Each middleware will be separate noflo graph, which admin can change.
Is reasonable to use noflo like middleware and if yes how to convert function "registerUser" to noflo graph? Thnx.
function registerUser(req, res, next) {
var serviceLocator = req.serviceLocator;
serviceLocator.get('UserService').create(req.body, function(err, user) {
if (err) {
if (err.name === 'ValidationError') {
res.send(403, err);
} else {
next(err);
}
} else {
serviceLocator.get('EmailService').sendEmail('confirm-email', {user: user},
function() {
res.send(user);
}
);
}
});
}
app.use('auth/register', registerUser);
I am not familiar with express and what specific feature/behavior from express you'd like to apply to noflo. But what you can do is to setup several graphs, where each graph has a webserver component on the input side that listens for a specific path; 'auth/register' in your case. You could pass this as a IIP from your main app when setting up the graphs.