
Security News
Axios Maintainer Confirms Social Engineering Attack Behind npm Compromise
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.
sails-formatter
Advanced tools
Helps to specify how objects are displayed.
I was thinking about modern MVCs. Nowadays these frameworks are mainly used for providing REST. That means that they're not MVC anymore, because there are no Views.
Why don't we introduce something like Formatters instead of Views? It is the same idea, but it will define how to build a JSON.
We use to have .toJSON() function, unfortunately it was very limited and deprecated now. Currently we have to define how to return an object in a Controller. It's usually very messy.
Not always you can print an object the same way as it's written in the model. You may need to load some additional data before print it, and frontend may also require different format of fields.
Forum is a good example. To print ForumModel you need to load and calculate how many related topics are inside, how many of them are new, etc.
That code to build one single forum object, can be quite big and messy, especially if you need to reuse it, or print it slightly different (full, teaser).
I think it make sense to move it out of controller, and organise somehow.
npm install sails-formatter --save
All formatters must be placed under api/formatters/{Model}/{type}.js folder.
Formatter.one(object, model, type);
| Argument | Type | Details | |
|---|---|---|---|
| 1 | object | Object | Object to be formatted. |
| 2 | model | String | Model name of the object to be formatted. |
| 3 | type | String | Type of the formatter. |
| 4 | data | Object | Optional data a formatter may require. Such as current user. |
Type: Promise
Promise with formatted object.
var Formatter = require('sails-formatter');
User.findOne().then(function(user) {
Formatter.one(user, 'user', 'full').then(console.log);
});
Formatter.many(objects, model, type);
| Argument | Type | Details | |
|---|---|---|---|
| 1 | objects | Array | Array of objects which you want to format. |
| 2 | model | String | Model name of the object to be formatted. |
| 3 | type | String | Type of the formatter. |
| 4 | data | Object | Optional data a formatter may require. Such as current user. |
Type: Promise
Promise with formatted objects.
var Formatter = require('sails-formatter');
User.find().then(function(users) {
Formatter.many(users, 'user', 'teaser').then(console.log);
});
Let's create two formatters for User model.
All formatters must input an object to be formatter and return a promise.
// api/formatters/user/teaser.js
module.exports = function(object) {
return Promise.resolve({
id: object.id,
name: object.name,
});
};
You can reuse formatters inside a formatter:
// api/formatters/user/full.js
var Formatter = require('sails-formatter');
module.exports = function(object) {
return Formatter.one(object, 'user', 'teaser').then(function(output) {
output.first_name = object.firstName;
output.last_name = object.lastName;
return output;
});
};
Now, we can use them in the UserController:
// api/controllers/UserController.js
module.exports = {
findOne: function (req, res) {
var promise = User.findOne(req.param('id')).then(function(user) {
return Formatter.one(user, 'user', 'full');
});
promise.then(res.ok).catch(res.badRequest);
},
find: function (req, res) {
var promise = User.find().then(function(users) {
return Formatter.many(users, 'user', 'full');
});
promise.then(res.ok).catch(res.badRequest);
}
};
In case one formatter need some extra data to be build:
// api/controllers/TopicController.js
module.exports = {
findOne: function (req, res) {
var promise = Topic.findOne(req.param('id')).then(function(topic) {
return Formatter.one(topic, 'topic', 'full', {
currentUser: req.session && req.session.user
});
});
promise.then(res.ok).catch(res.badRequest);
}
};
// api/formatters/topic/full.js
var Formatter = require('sails-formatter');
module.exports = function(object, data) {
var output = {
id: object.id,
name: object.name,
body: object.body,
};
if (data.currentUser) {
// That field need to know data.currentUser
output.viewed_at = new Date().getTime();
}
return Promise.resolve(output);
};
You could definitely create a hook that would load formatters from api/formatters and publish your hook to NPM.
Another idea of how to go about this sort of thing would be to create custom responses, so instead of using res.ok() you would do
res.outputSomeModel(). You can put custom responses inapi/responsesand then call them from any controller.
FAQs
Helps to specify how objects are displayed.
The npm package sails-formatter receives a total of 4 weekly downloads. As such, sails-formatter popularity was classified as not popular.
We found that sails-formatter demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.

Security News
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.