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

barry

v0.0.3

Published

Barry.js - Soothing server-client model synchronization for JavaScript

Downloads

8

Readme

Barry.js - Keep your models up-to-date

Barry, the old gossip, is a simple JavaScript/Node.js library that keeps your client-side models synchronized with your server-side state.

Barry really loves Angular.js <= Socket.IO => Node.js, but all the actual integration with those tools consists of just a few lines of JavaScript, so you can easily write the glue to hook it into pretty much anything you want.

On the server-side you first define an endpoint. This is where you specify how clients will connect and how they'll be able to talk to Barry. Here is how you set up a Socket.IO endpoint:


var barry = require('barry-io').listen(80);

Your endpoint will provide a number of services. Let's say we want a service where we can get the current number of connected clients. Barry provides a number of pre-made types of services, one of which is a ScalarService, which is a service where people simply subscribe to a single value, like a string or, in our case, a number.

var barry = require('barry-io').listen(80);
var clientCount = barry.service('client/count', new barry.ScalarService);

clientCount.value = 0;
barry.on('connection', function (socket) {
  clientCount.value++;
  socket.on('disconnect', function () {
    clientCount.value--;
  });
});

That's it! Our server is ready to use. Let's see how an Angular.js-based client would use our brand-new service:

function MyCtrl($scope, $barry) {
  $barry.consumer('client/count').toScope($scope, 'numClients');
}

And now we can add a binding to our template:

<div ng-controller="MyCtrl">
  <p>We currently have <span ng-bind="numClients">???</span> connected clients.</p>
</div>

Pretty easy, right? Now Angular and Barry are going to completely take care of keeping this value updated for us. Even better: Barry takes care of loading the initial value when the controller is instantiated and unsubscribing when the user navigates away from the page.

But let's look at a more interesting example. This time we have a dictionary of values, a key/value store basically, and we want clients to be able to subscribe to some prefix of keys.

var barry = require('barry-socketio').listen(80);
var phonebook = barry.service('phonebook/:key', new barry.DictionaryService);

phonebook.load({
  "Anaya, Ione": '701-525-8821',
  "Ball, Alisha": '901-347-4799',
  "Bergeron, Delmar": '229-947-3619',
  "Brown, Phoebe": '831-702-6710',
  "Bryan, Jacob": '516-368-8216',
  "Close, Hugo": '314-290-5402',
  "Cyr, Russell": '609-643-8337',
  "Falk, Neline": '870-233-9360',
  "Houle, Sacripant": '217-896-6097',
  "Jensen, Michelle": '920-588-0342',
  "Jespersen, Lasse": '270-915-4595',
  "Joly, Manon": '972-409-3909',
  "Marjanovic, Janja": '530-480-3481',
  "Menclov�, Marie": '253-245-3448',
  "Mitnick, Kevin": '555-123-9191',
  "Nekstad, Nellie": '612-321-5684',
  "Otterstad, Viljo": '818-408-5299',
  "Rauhala, Manu": '225-694-7010',
  "Saraste, Mauri": '918-347-5593',
  "Symanska, Adelajda": '810-626-5265',
  "S�nsterud, Helje": '347-246-2299',
  "Tomaszewska, Danuta": '617-369-6861',
  "Tomaszewski, Aron": '907-888-3780',
  "Viitala, Arttu": '281-310-7368',
  "Winkel, Lucas": '912-215-5446',
  "Zawadzki, Czcibor": '631-468-2299',
  "Zielinski, Ludwik": '417-442-7650'
});

// Kevin Mitnick is a badass hacker, so his phone number magically changes // every two seconds! Ok, maybe not, but it's still good for our demo. setInterval(function () { var value = phonebook.dict["Mitnick, Kevin"]; value = value.slice(0, 8) + ((+value.slice(8) + 3943) % 9000 + 1000); phonebook.dict["Mitnick, Kevin"] = value; }, 2000);


As for the client, let's code the UI first this time:

``` html
<div ng-controller="PhonebookCtrl">
  <p>Start typing a last name and matching entries will be automatically displayed:</p>
  <p><input type="text" ng-model="prefix"></p>
  <ul id="suggestions" ng-show="suggestions.$b.loaded">
    <li ng-repeat="name, no in suggestions">
      <strong>{{name}}:</strong> {{no}}
    </li>
  </ul>
  <p ng-hide="suggestions.$b.loaded">Loading suggestions...</p>
</div>

So we want to show a list of suggestions like an autocomplete of what the user entered. The interesting part is that this autocomplete will be self-updating!

You'll notice also that we're using a special value called $b. This contains a bunch of meta-information like what the state of the model is - is it initialized, is it live-updating, etc. In this case we're using $b.loaded to find out if it is initialized.

function PhonebookCtrl($scope, $barry) {
  var consumer = $barry.consumer(null).toScope($scope, 'suggestions');
  
  $scope.$watch('prefix', function (prefix) {
    consumer.setUrl('phonebook/'+prefix+'*');
  });
}

Another new trick: You can switch out services on the fly. So we start with a null service (which will tell Barry to just set the model to null) and once the user enters a prefix it will move to the correct service, subscribing and unsubscribing as required.

barry.service('clients', { init: function (req, model) {

}, apply: function (change);

Meta-information ($b)

$b.loaded (Boolean) True, if the model contains data, false if it doesn't.

$b.updated (Integer) Timestamp of the last update to the model (client time).

$b.updatedServer (Integer) Timestamp of the last update to the model (server time).