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

websocket-base

v4.1.2

Published

A websocket server foundation.

Downloads

27

Readme

Websocket Base

Base is a foundation for a WebSocket server with a foreign user management system. Foreign meaning it is not handled within the websocket server itself.

For example lets say you have a PHP application. You want to set up a WebSocket server using your existing users - Base allows you to do that easily!

How to use

Base relies on ws, arguably the fastest websocket implementation for javascript, to handle the communication. All you need to do is require websocket-base in your application and run it.

var base = require("websocket-base");

base.run({
  port: <port>,
  http: function(request, response) {
    // your usual http request handler
  },
  authenticate: function(connection, register) {
    // do your magic to get a user object and then
    register(connection, user);
  },
  actions: {
    path: <path>,
    public: [
      // array of actions that can be called without authentication.
    ]
  }
});

By default, Base does not allow users to send messages before they have been authenticated and the authenticate callable is where the magic happens. It gets called whenever a new connection is made to the websocket server. You get a connection instance as the first parameter and a register callable as the second one. Based on the connection (or not) you must get a hold of a user object that represents the currently authenticated user in your application. The only requirement for the user object is that it has to have an ìd property and it must be unique. After you have that object you simply pass it to register and the user is now connected. In case you determine that the connection is coming from an unauthenticated user you can call register(connection, false) to terminate the connection.

Note: You can create a user management system within Base and still have it working perfectly fine, but that's not its purpose.

Structure

Base constructs an in-memory database of all connected users, which you can access via base.users. Generally you should avoid modifications of any kind and only use it for reading, however if you absolutely must, be cautious because this might break your application and cause silent errors that are very hard to find.

users {
  <id>: User {
    id: <id>,
    connections: {
      <connection-id>: WebSocket {
        // <connection-id> is an arbitrary integer, assigned when the connection is established.
        id: <connection-id>,
        user: User {
          // circular referrence to the user this connection belongs to.
        }
      },
      ...
    },
    // whatever else information you provide to the register callable
  },
  ...
}

Communicating

The communication works kind of like JSON RPC except a response is not always required and keys are omitted from the message.

Message structure

"[<command>, <body>, <id>]"

Where command is the action that must be executed on the recipient's side, body is any arbitrary information and id is an optional unique identifier for the message, used when a response is needed.

Sending messages

  • From the server The User class has a neat method called send which you can use to send a message to all connections from this user. Occasionally you will need to send a message to a specific connection, then you can call send on the particular connection.

    var message = new base.Message(<command>, <body>);
    
    // to a user
    base.users.get(<id>).send(message);
    
    // to a connection
    base.users.get(<id>).connections[<connection-id>].send(message);
  • From the client

    ws.send(JSON.stringify([<command>, <body>]);

Receiving messages

  • On the server Recieved messages are handled by actions on the server. An action is simply a function that takes in two parameters - a connection the message came from and the message itself. Actions must be declared as modules, so you must tell Base where to look for these modules using the actions.path property when calling base.run. An example action that replies to the message ["hello", "world"].

    // file must be named "hello" and reside in the actions directory
    module.exports = function(connection, message) {
        connection.send(message.respond("alert", "Hello, " + message.body + "!"));
    }
  • On the client Handling the message sent from the example above, displaying the body in an alert.

    ws.onmessage = function(message) {
      try {
        var [command, body] = JSON.parse(message.data);
    
        switch (command) {
          case "alert":
            alert(body);
            break;
        }
      } catch (e) {
        throw "Invalid message.";
      }
    }

Quickstart

You can clone the quickstart example to have a look at a working application.