Archives for : sailsjs

SailsJS and Waterline: native MongoDB queries and Waterline models

Here’s my experience with SailsJS, Waterline and MongoDB native queries. I like SailsJS and Waterline very much but there’s also room for improvement when things get serious.

There’s limitation in current Waterline that one cannot limit the fields in the output when MongoDB is used. Also the aggregation options are limited with Waterline. MongoDB on the other hand is very-very powerful database engine and once you learn how to aggregate then the possibilities seem endless.

My usecase is that I have to use native queries instead of Waterline’s but I also want the retrieved models have all those nice “instance methods” of Waterline model instances like “model.save()”. This example also gives you overview how to use native queries, aggregation.

So here’s very short guide to this. I hope it helps to save a couple of hours for other guys like me (who spent that time to figure it out:)).

Note! It uses another excellent, wonderful, genius etc pattern called Promises.

Custom headers from SailsJS API ignored by AngularJS app

Have you ever tried to return custom HTTP headers from your SailsJS backend REST API to your frontend AngularJS application and wondered why they don’t show up in AngularJS?

I had pretty standard case where I wanted to implement server side pagination for my data sets returned by the API. For that you need to return the total number of records in order to implement pagination properly in the frontend. I decided to return the total number of records in a custom header called “X-TotalRecords”. It is returned together with the response but it didn’t show up in AngularJS response:

.....    
.then(function(response){
    $log.debug(response.headers()) //does not show my custom header
}) 
..... 

After some googling around I found a solution. You need to create a custom SailsJS policy and send a special header “Access-Control-Expose-Headers” there. Let’s call the policy sendCorsHeaders.

Create a file sendCorsHeaders.js in policies/ folder:

    
module.exports = function (req, res, next) {
    res.header('Access-Control-Expose-Headers', sails.config.cors.headers);
    next();
};

As you can see it re-uses headers defined in your cors.js under config/ folder.

From now on you can retrieve your custom header in AngularJS $http service.

Accepting BDOC container upload from PUT method in SailsJS app

I just struggled with a complex problem of uploading application/bdoc (digital signature container) files to a SailsJS app and I want to share my story. I hope it will make the life easier for those who are working with digidoc and Signwise.

We at Prototypely are creating a solution that heavily uses digital signatures. Signwise is the preferred partner for handling containers and signing process. Signwise process states that they create the container and their system makes a HTTP PUT request to target system to put the newly created container back.

Standard file uploads are handled very nicely in SailsJS by great Skipper library.

However when it comes to uploading quite rare mime types like application/bdoc or application/x-bdoc then it needs some tweaking.

Open config/http.js and add custom body parser there and you’ll be able to accept BDOC files:

bodyParser: function (options) {
  return function (req, res, next) {
    if (req.get('content-type') != 'application/bdoc') {
      return next();
    }
    var bodyParser = require('body-parser').raw({type: 'application/bdoc'});
    return bodyParser(req, res, next);
  }
}

After that you’ll be able to save the file in your controller. Mind the req.body – this is the buffer that will be written down.

acceptBdocFile: function(req, res){
    var fileId = req.param('fileId');
    var tmpFile = process.cwd() + '/.tmp/' + fileId;
    fs.writeFileSync(tmpFile, req.body);
    return res.status(201).json();
} 

Setting node.js app default timezone

Timezones are … difficult. I can say that based on my >20 years programming experience. They pop up here and there and cause a good amount of headache. I won’t spend too much time here for timezones but I just give a quick tip how to set your SailsJS (or any NodeJS) app to use UTC (GMT) timezone by default.
During the years I’ve learn that it’s best to have everything in UTC in the business and DB layers as a rule of thumb (there are exceptions, of course).

It’s really simple to make your NodeJS app to have UTC as default timezone. Just export an environment variable before you run your app:

export TZ="UTC"
forever --watchDirectory ./ -l logs/log.log --watch app.js