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

losin

v0.0.21

Published

Request-response and validation capabilities for nossock (& other)

Downloads

11

Readme

Losin

Build Status NPM version

Losin is a small lib that adds request-response and validation capabilities to socket.io and nossock. Wrappers for other libraries may come soon.

  • Validation: Define messages schemas to validate them
  • Req-Res: Request-response messages
  • Timeouts: Support of timeout handlers in request messages

Installation

$ npm install losin

Usage

Creating Losin

// create adapter
var losin = require('losin')('socket.io'),
    lo = losin.createLosin(socket, config);

// Regestering messages (see validation section for more info on spec)
lo.register( /* {spec} */ );

config is optional and has the following format:

{
  'reqTimeout': 5,
  'processInvalid': false,
  'validationErrorHandler': function(name, errors) {
      console.warn('Validation error', name, errors);
  },
  'logHandler': function(type, direction, name, body, err) {
      console.log(direction + "(" + type + ")", name, ':', type == 'res' && err ? err : '', body);
  }
}
Pub-sub

Handling:

lo.handle('info', function(msg) {
    console.log(msg);
});

Sending:

lo.sendMessage('info', 'Hello');
Req-res

Handling:

lo.handle('someReq', function(req, sendResponse) {

    // success response
    sendResponse(null, req[0] + req[1]);
    
    // or error response
    // sendResponse('Something bad happened', null);
});

Sending:

lo.sendRequest('sum', [1,2], function(err, data) {

    // err - if we got error response, or timeout happened
    if (err) {
        console.log(err);
    } else {
        console.log(data);
    }

});
Closing connection & handling connection drop
// Close connection
lo.close();

// Handle connection close
lo.onClose(function() {
    // some code
});

Complete example

spec.json
{

    "info": {
        "description": "Just some info message with payload",
        "type": "pub-sub",

        "msg": {
            "payload": {
                "type": "string"
            }
        }
    },

    "sum": {
        "description": "Sum endpoint that does sum of numbers",
        "type": "req-res",
        "ttl": 30,

        "req": {
            "description": "Array of numbers to sum",
            "type": "array",
            "items": { "type": "number"}
        },

        "res": {
            "description": "Sum of numbers",
            "type": "number"
        }
    }
}
server.js
var _ = require('lodash'),
    losin = require('losin')('socket.io'),
    app = require('http').createServer(function(){}),
    io = require('socket.io').listen(app);

    app.listen(8797);

var spec = require('./spec.json');

 
/* ---------- server ---------- */

io.on('connection', function(socket) {

  var lo = losin.createLosin(socket);
  lo.register(spec);

  /**
   * Handles close
   */
  lo.onClose(function() {
      console.log('onClose socketio server');
  });

  /**
   * Handle info message
   */
  lo.handle('info', function(msg) {
      console.log(msg);
  });

  /**
   * Handle sum request
   */
  lo.handle('sum', function(nums, sendResponse) {
    sendResponse(null, _.reduce(nums, function(s,e) {return s+e; }, 0));
  });

});
client.js
var _ = require('lodash'),
    losin = require('losin')('socket.io'),
    socket = require('socket.io-client').connect('http://localhost:8797');

var spec = require('./spec.json');

/* ---------- client ---------- */

socket.on('connect', function(socket) {

  var lo = losin.createLosin(socket);
  lo.register(spec);

  /**
   * Send info message
   */
  lo.sendMessage('info', 'hello world!');

  /**
   * Send request
   */
   lo.sendRequest('sum', [1,2,3], function(err, data) {
       if (err) {
           console.log(err);
       } else {
           console.log(data);
       }
   });

});
 

Losin protocol definition

Typically, message is a JSON document.

There are 2 types of messages in Losin:

  • Pub/sub messages
  • Request-respnse messages

Pub-sub messages

Pub-sub are plain messages. One side subscribes on it by name, and other side sends it providing the same name and a message. Low-level protocol (socket.io, nossock or other) should support this feature out of the box.

message

{
    "name": <name>
    "body": JSON
}

Req-res messages

Req-res is request-response messages. One side sends "request" message to another, and awaits response for it. Other side provides handler of the request that receives request message and sends back response (err, responseObject) where err is null when request was successfully processed, and some object otherwise.

Requester side is responsive of generating unique identifier of request, and responder side is responsive of using the same identifier for a response.

There is a default timeout value for request-response messages parties should agree on, after this time requester should receive timeout error in err, and implementation should stop waiting the response after that time. Timeout value can be configurable for each req-res messages individually in message spec (see validation section).

Implementations should follow these naming conventions for implemention req-res.

request

{
    "name": "req:<name>:<id>",
    "body": JSON
}

<name> = name of the req-res message
<id> = generated unique id, it should match regexp: [-_\w]+, i.e. contain only numbers,
        alphabetic chars and '-' or '_' chars.

response

{
    "name": "res:<name>:<id>",
    "body": [ <err>, <reponse> ]
}


<name> = name of req-res-message
<id> = id send by requester in request
<err> = null | JSON
<response> = null | JSON

Specs & messages registry: Validation

Implementation may (it's optional, but very desirable) define a way of validation all messages. Parties agree on messages and format of messages defining a registry of messages specs. Registry is a JSON document with the following structure:

{
    // pub-sub message
    "someMessage": {
        "description": "some literate description",
        "type": "pub-sub",
        "msg": { JaySchema }
    },

    // req-res message
    "someCommand": {
        "description": "some literate description",
        "type": "req-res",
        "ttl": 15, // time-to-live in seconds
        "req": { JaySchema },
        "res": { JaySchema }
    },

    // ...
    // other messages
    // ...
}

Registry is shared between parties so they could be sured they use the right messages and format. JaySchema is javascript implementation of JSON schema validation. It follows JSON Schema Draft v4.

Tests

$ sudo npm install nodeunit -g
$ npm test

Author

License

MIT