• View-specific JS Files in Sails.js



    One thing I really loved about Meteor, is that you can fine-tune which files are included (and the order of inclusion).
    This is especially useful when structuring everything in small Meteor packages.
    So for example, if you simply want to add relevant client JS files (on package.js):
    1
    2
    3
    4
    
    api.addFiles([
        'client/page-login.html',
        'client/page-login.js',
    ], 'client');
    page-login.html:
    1
    2
    3
    4
    5
    6
    7
    
    <template name="PageLogin">
      <form id="login-form">
        <input name="username" type="text" />
        <input name="password" type="password" />
        <input id="submit-login" type="submit" />
      </form>
    </template>
    page-login.js:
    1
    2
    3
    4
    5
    6
    
    Template.PageNewDomain.events({
      'submit #login-form': function (event, template) {
        event.preventDefault();
        //handle form submission..
      }
    });
    Together with specific Template namespaces, it allows you to have template-specific JS code that doesn't interfere with other templates. I looked for a way to have that feature in Sails.js.

    Instead of trying to implement the entire complicated Template rendering engine, I figured it should be enough if every view gets a corresponding JavaScript file that is optionally loaded with said view.

    How it should work

    • Each View in the views/ folder has a name, let's create a corresponding JS file with the same name
    • On Sails.js, JavaScript files are stored separately in the js/ folder, let's store all view-specific JS files under js/views/
    • JS filenames should be the same as view filenames. views/dashboard/login.ejs will have a JS file named js/views/dashboard/login.js

    How to implement

    • add this to config/views.js:
      1
      2
      3
      4
      
      locals: {
          existsSync: require('fs').existsSync,
          jsPath: __dirname + '/../assets/js/views/'
      }
      This is so that we're able to check if a JS file exists.
    • on the bottom of views/layout.ejs, under blocks.localScripts
      1
      2
      3
      
      <% if (existsSync(jsPath + req.options.controller + '/' + req.options.action + '.js')) { %>
        <script src="/js/views/<%= req.options.controller + '/' + req.options.action %>.js"></script>
      <% } %>
    • In tasks/pipeline.js in the jsFilesToInject array, we need to remove
      js/**/*.js
      This is Critical. Otherwise, all JS files under js/views will be automatically included in ALL views.
      Instead, to automatically inject other views we can have the following line:
      js/dependencies/**/*.js
    That's it! Now you'll be able to write view-specific JavaScript files!
  • Meteor Alternative to Kadira

    or: How to integrate SPM with Meteor

    It's been far too long since I wrote a post, life gets super busy sometimes.
    At any rate, today I'm going to be writing about something that is searched by quite a lot of people:
    An Alternative to Kadira.

    What is Kadira?

    Kadira is the only Cloud-based Meteor Debugging tool out there.
    If you're familiar with tools like New Relic, Kadira is basically a lean version of that.
    It allows you to see live bugs/errors coming from your application, with a full backtrace so you know which part of the application is causing the problem (to some extent). It also has limited tools for reporting/statistics, so you can see if there's a great uptick of bugs lately or a certain type of bug after introducing a new feature.

    Why look for a Kadira Alternative?

    It was recently published that the founder and maintainer of Kadira has moved away from Meteor.
    Leaving the fate of Kadira very uncertain. In fact, a full year and a half before the announcement,
    there weren't any changes to Kadira's feature set.
    What disappointed me the most was that Kadira's source wasn't released, so on the one hand it won't be maintained any longer, but on the other hand, there's no option for the community to step in.

    On top of that issue, Kadira is quite limited, searching/navigating through issues is very difficult and at times - impossible. there's a lot of repeated bugs that are not registered correctly (without any backtrace or info), making it very hard to find which is a Kadira bug, and which is an actual bug in my application.

    That's why I thought that it was time to seek an alternative.

    Who plays nice with Meteor?

    Most of the major services (New Relic, AppDynamics), didn't support Meteor, or if they did - it was a very limited support, and considering the price point (in the hundreds, sometimes thousands monthly), I expected to have a complete turnkey solution with minimal integration issues.

    After looking at a few posibilities, I decided to go with SPM from Sematext.
    This tool is not the most popular debugging tool in the world, but their API is clear, easy to use, and their interface is quite nice as well.

    Implementing SPM Debugger in Meteor

    This can be done with 2 easy steps
    1. Add the following to your package.js or .meteor/packages for chaotic packageless projects (SHAME, SHAME):
      1
      2
      3
      4
      5
      
      Npm.depends({
      	'spm-agent-nodejs': '1.30.2',
      	'winston': '2.3.0',
      	'winston-logsene': '1.2.1'
      })
    2. Add the following code to your Server-side code:
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      
      /* Loading SPM Monitoring Agent */
      
      var spmStart = function() {
        process.env.NODE_OPTIONS = '-r spm-agent-nodejs';
        var logsene_token = LOGSENE_TOKEN; //Insert Logsene token here
        var spmAgent = Npm.require('spm-agent-nodejs');
      
        //Logsene
        var winston = Npm.require('winston');
        var logsene = Npm.require('winston-logsene');
        var logger = new winston.Logger();
        logger.add(logsene, {token: logsene_token, type: 'logs'});
      
        // Overriding Meteor Error function, simply adding the
        // logger before the original function runs
        var util = Npm.require('utils');
        var errorFunc = Meteor.Error;
        Meteor.Error = function(error, reason, details) {
          logger.error('Error: ' + error, {
            error: error,
            reason: reason,
            details: details,
            stack: Error().stack,
            tags: ['error', 'winston']
          });
          errorFunc.call(this, error, reason, details);
        };
        util.inherits(Meteor.Error, errorFunc);
      };
      
      spmStart();
      Special thanks to Wojtek Krysiak for adding inheritance here
      I suggest creating a separate file in your Meteor Project (or better yet, a separate package!)
    That's it! Meteor errors AND Performance Information should be visible on your SPM dashboard.
    I might organize the code snippet and add it to GitHub at a certain point (fingers crossed).

    Until next time!
  • Microsoft Buys LinkedIn for $26.2 Billion

    In a move that may surprise many, Microsoft just made a deal to buy LinkedIn,
    for the amount of $26.2 Billion.

    How does this compare to the Whatsapp deal (last huge tech buy)? Well, since a picture is worth a thousand words, I've decided to make an infographic (almost a picture):

  • Small upgrades to your workspace

    Right Posture
    Right Posture vs Reality

    After another cross-country move, I've had to leave my mighty Workspace behind (complete with 2 monitors and a fierce Desktop PC). I've taken my Laptop with me, thinking that's really all I need, as I could do all my work while sitting in a park meditating (or some other ridiculous notion). Obviously I was totally wrong!

  • Family Tree Research

    Family Photos

    I've recently restarted my genealogical research efforts, to find out more about my family's history.
    In many cases, especially people of Jewish-European origins, not much is known by the ones who stayed alive (20th century Europe has seen a lot).
    Many archives are recent, and some German/Polish/Russian archives have only recently been scanned and digitized.