mongoose and restify - localize strings before returning json - node.js

I would like to return localized Strings for multilanguage business objects in our RestFul API based on node.js, restify and mongoose. I have the requirement to store the translated resources on our translation resource server, but also need to support dynamic creation of those business objects.
I found a solution to easily plugin the i18n process in the POST/PUT calls using a single pre-'save' mongoose middleware on all Schema, when creating or updating my multi-languate business objects - this works because I am able to pass the request context to the obj.save(req, callback) call.
But, I am struggling to plug in the i18n on simple GETs. I thought of and tried different ways where I can plugin the i18n before returning the response, but don't really find a good way. Options I thought of:
translate in a mongoose middleware pre /post ('init'):
Problem: I don't have access to the request context, and therefore
don't know the locale to return, so I cannot translate there.
translate in the toObject() / toJSON {transform: }:
Same issue - i don't have the request context in these hooks.
translate in the handler/controller methods for each ressource.
Problem: Duplication, I have to do it everywhere, I would really prefer a solution I can define on the model/Schema layer
translate in a restify / express middleware towards the end:
Problem: I don't have access to the mongoose schema metainformation anymore, so I don't know which attriutes to translate.
Edit: just found this additional way:
- translate in a custom restify responseFormatter:
This seems to work nicely, in the reponseformatter I have access to everything I need. It kind of seems a little weird from an architechtural point of view, but if nobody has a better idea, I will add this as an answer.
Maybe (hopefully) I am missing something obvious...
thanks for any hints

Related

fastify-swagger is not picking up my dynamic routes

I've been a fan of ExpressJs for a long time but in a Youtube video I stumble upon Fastify and wanted to give it a try
I'm struggling in making the fastify-swagger plugin work as I assume it should work - dynamic setup to pick up the schema from each route, but I'm certainly missing something 😔
here's my test repo that after running, none of my routes appear
my setup for the plugin is the default one
but all I see is
I've read in the read me that because of OpenAPI specs, some properties, like description are mandatory or will not pick up the route, but I've added in one route, and still does not pick up, I've also added tags wondering if that was also mandatory, but nothing...
does anyone know what am I missing? must be a simple thing, but got me puzzled this last few days 😔
I ran into the same issue and ended up solving it by following the first Usage example line-by-line: https://github.com/fastify/fastify-swagger#usage
const fastify = require('fastify')()
(async () => {
// set up swagger
await fastify.register(require('#fastify/swagger'), {
...swagger config
});
// define all your routes
// then call these
await fastify.ready()
fastify.swagger()
})();
Consider the order in which your plugins are loaded, the routes need to be registered before fastify swagger. If fastify swagger comes first, it doesn't detect any route.
I encountered this issue in my project. In my case, I solved it using fastify-plugin. Looking at the source code for fastify-swagger, it seems to rely on a hook listening for onRoute events to detect routes. I'm thinking maybe encapsulation can interfere with the plugin's ability to receive the events.

When to use controllers?

This is what I'm doing right now:
Implemented different router modules for different routes
Each router has it's own sets of MongooseModels.
Handler the request (req,res) and interact with the MongooseModel via statics and methods
This is what I want to know:
Almost every example is see where Mongoose,Express are involved, they seem to follow the MVC pattern, which places "Controllers" in between. Now, I have statics and methods defined in each MongooseModel and are capable of handling only the (req.body) part of my original (req) (Because, that's what they only need, right?). Extract the result, and the rest is done by the router.
So, do I really need to place Controllers in between as my MongooseModel is already doing the same job?
Thanks.

Express - Create a new view engine

I know that expressjs supports many view engines, like: ejs, jade, etc. I saw a list here: http://expressjs-book.com/forums/topic/how-to-use-alternative-non-jade-template-engines-with-express/.
My question is how can I create my own view engine. I've looked in ejs and in other engines' source-code but I didn't really find an expressjs documentation on how to create a new engine, what are the requirements, or a tutorial about it.
Is it possible to create a new custom view engine? Thanks.
Yes, of course. Take a look at this list for templating engines.
Regarding express itself, what you need to do is create a plugin, or even a middleware function - that will attach your render, renderFile and similar methods to the response object.
If you don't use an express engine and try to, say, response.render('index.ejs');, you'll get an error. But if that response object has a render method, you're fine. So it boils down to extending expresses' response object with what you need.

Express JS equivalent of decorator pattern from Python frameworks

Working with Express js to write a simple NodeJS webservice. I'm historically a python guy.
In frameworks like Django or Flask, its common to see Python decorators used to implement logic from plugins only on specific endpoints. An example of this pattern can be seen here.
http://pythonhosted.org/Flask-Classy/#using-multiple-routes-for-a-single-view
I'm working on an Express middleware and have everything working well with the app.use 3-parity function, but this is only relevant for logic executes for every request. I'd like to allow the end user of the plugin to run parcels of my logic (already in separate functions) only on specific endpoints similar to the pattern outlined in the source above.
Some of the configuration to these wrappers would be passed at app start.
What would be the best approach to this? Should I emulate this pattern with functions that take the actual route handler as an argument and return it at end? Something like this?
function pluginWrapper(endptFunc){
//plugin logic here
return endptFunc;
}
app.get('/endpt', pluginWrapper(function(req,res,next){
//endpt logic here
res.end()
}));
Here are the express idiomatic strategies:
Things relavent for the majority of requests across the entire site become normal connect middleware: app.use(express.cookieParser())
Things relavent for just a particular route can go just on that route: app.post('/users', express.bodyParser(), createUser). This is the pattern I think that most closely matches your above scenario
Groups of related middleware can be passed as lists: app.get('/books', [paginate, queryLimit, memoize], getBooks). And of course that list could be a variable or module and thus shared in a DRY fashion.
Common functionality triggered by patterns in the path itself can use app.param: app.get('/:username/hobbies', getHobbies)
Existing regular functions can be wrapped into middleware to adapt them to a middleware API.
You can just call functions as normal. Not every method of code reuse has to be shoehorned into one of express's convenient patterns.
To address your question more directly, I don't think you should try to port the python decorator pattern 1-to-1 to javascript. Middleware accomplishes essentially the same thing. If you post concrete examples using decorators, we can suggest an idiomatic way to implement them in express.

Express & Socket.io Route parroting/copying/sharing

I'm working with expressjs and socket.io in nodejs. I'm looking into assign identical route handlers to requests made in either HTTP or via websockets/socket.io.
For instance:
var responder = function(req, res){
req.params //<-- {id: 'something...'}
}
app.get('/foo/:id', responder);
io.on('/foo/:id', responder);
socket.io doesn't appear to have this type of routing functionality. Does anyone know of a library/module to help with this?
There are several options.
If you'd like to keep using express, check out express.io.
If you don't mind using something a bit different, sails lets you do this sort of thing as well.
(Update: sails now uses express too)
Both have been used in production successfully.
Note that routing is also pretty simple to implement on your own. If you check out how express do it I'm sure you'll be able to figure out a slim implementation that would match you needs.
Good luck! Let me know what you ended up using and how it worked for you.

Resources