npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

sails-formatter

v0.3.0

Published

Helps to specify how objects are displayed.

Downloads

4

Readme

Sails Formatter

Helps to specify how objects are displayed.

Motivation

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.

Installation

npm install sails-formatter --save

Files structure

All formatters must be placed under api/formatters/{Model}/{type}.js folder.

Usage

.one()

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. |

Returns

Type: Promise

Promise with formatted object.

Examples

var Formatter = require('sails-formatter');

User.findOne().then(function(user) {
  Formatter.one(user, 'user', 'full').then(console.log);
});

.many()

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. |

Returns

Type: Promise

Promise with formatted objects.

Examples

var Formatter = require('sails-formatter');

User.find().then(function(users) {
  Formatter.many(users, 'user', 'teaser').then(console.log);
});

More examples

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);
};

Ideas

@sgress454 commented:

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 in api/responses and then call them from any controller.