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

tiny-lr

v2.0.0

Published

Tiny LiveReload server, background-friendly

Downloads

2,929,361

Readme

tiny-lr Build Status

This script manages a tiny LiveReload server implementation.

NPM

It exposes an HTTP server and express middleware, with a very basic REST API to notify the server of a particular change.

It doesn't have any watch ability, this must be done at the build process or application level.

Instead, it exposes a very simple API to notify the server that some changes have been made, then broadcasted to every connected livereload client.

# notify of a single change
curl http://localhost:35729/changed?files=style.css

# notify using a longer path
curl http://localhost:35729/changed?files=js/app.js

# notify of multiple changes, comma or space delimited
curl http://localhost:35729/changed?files=index.html,style.css,docs/docco.css

Or you can bulk the information into a POST request, with the body as a JSON array of files.

curl -X POST http://localhost:35729/changed -d '{ "files": ["style.css", "app.js"] }'

# from a JSON file
node -pe 'JSON.stringify({ files: ["some.css", "files.css"] })' > files.json
curl -X POST -d @files.json http://localhost:35729

As for the livereload client, you need to install the browser extension: http://feedback.livereload.com/knowledgebase/articles/86242-how-do-i-install-and-use-the-browser-extensions- (note: you need to listen on port 35729 to be able to use it with your browser extension)

or add the livereload script tag manually: http://feedback.livereload.com/knowledgebase/articles/86180-how-do-i-add-the-script-tag-manually- (and here you can choose whichever port you want)

Integration

The best way to integrate the runner into your workflow is to add it as a reload step within your build tool.

var tinylr = require('tiny-lr');

// standard LiveReload port
var port = 35729;

// tinylr(opts) => new tinylr.Server(opts);
tinylr().listen(port, function() {
  console.log('... Listening on %s ...', port);
})

You can define your own route and listen for a specific request:

var server = tinylr();

server.on('GET /myplace', function(req, res) {
  res.write('Mine');
  res.end();
})

And stop the server manually:

server.close();

This will close any websocket connection established and emit a close event.

Middleware

To use as a connect / express middleware, tiny-lr needs query / bodyParser middlewares prior in the stack (to handle POST requests)

Any handled requests ends at the tinylr level, not found and errors are nexted to the rest of the stack.

var port = process.env.LR_PORT || process.env.PORT || 35729;

var path    = require('path');
var express = require('express');
var tinylr  = require('tiny-lr');
var body    = require('body-parser');

var app = express();

// This binds both express app and tinylr on the same port

app
  .use(body())
  .use(tinylr.middleware({ app: app }))
  .use(express.static(path.resolve('./')))
  .listen(port, function() {
    console.log('listening on %d', port);
  });

The port you listen on is important, and tinylr should always listen on the LiveReload standard one: 35729. Otherwise, you won't be able to rely on the browser extensions, though you can still use the manual snippet approach.

You can also start two different servers, one on your app port, the other listening on the LiveReload port.

Using grunt

Head over to https://github.com/gruntjs/grunt-contrib-watch

Using make

See the make-livereload repo. This repository defines a bin wrapper you can use and install with:

npm install make-livereload -g

It bundles the same bin wrapper previously used in the tiny-lr repo.

Usage: tiny-lr [options]

Options:

  -h, --help     output usage information
  -V, --version  output the version number
  port           -p
  pid            Path to the generated PID file (default: ./tiny-lr.pid)

Using gulp

See the gulp-livereload repo.

Options

  • livereload - Path to the client side lib (defaults to path.join(__dirname, '../node_modules/livereload-js/dist/livereload.js'))
  • port - Livereload port (defaults to 35729)
  • errorListener - A callback to invoke when an error occurs (otherwise, fallbacks to standard error output)
  • handler - A function to use as the main request handler (function(req, res)). When not defined, the default handler takes place.
  • app - An express or other middleware based HTTP server
  • key - Option to pass in to create an https server
  • cert - Option to pass in to create an https server
  • pfx - Can also be used to create an https server instead of key & cert
  • liveCSS - LiveReload option to enable live CSS reloading (defaults to true)
  • liveImg - LiveReload option to enable live images reloading (defaults to true)
  • prefix - Option to add prefix to all HTTP server routes
  • dashboard - A boolean to prevent tiny-lr from configuring a default "home" route. Only used with the CLI (default: false)

Tests

npm test

TOC

var url = parse(this.request.url);
var server = this.app;

var ws = this.ws = new WebSocket('ws://' + url.host + '/livereload');

ws.onopen = function(event) {
  var hello = {
    command: 'hello',
    protocols: ['http://livereload.com/protocols/official-7']
  };

  ws.send(JSON.stringify(hello));
};

ws.onmessage = function(event) {
  assert.deepEqual(event.data, JSON.stringify({
    command: 'hello',
    protocols: ['http://livereload.com/protocols/official-7'],
    serverName: 'tiny-lr'
  }));

  assert.ok(Object.keys(server.clients).length);
  done();
};

properly cleans up established connection on exit.

var ws = this.ws;

ws.onclose = done.bind(null, null);

request(this.server)
  .get('/kill')
  .expect(200, function() {
    console.log('server shutdown');
  });
request(this.server)
  .get('/')
  .expect('Content-Type', /json/)
  .expect('{"tinylr":"Welcome","version":"0.0.1"}')
  .expect(200, done);

unknown route respond with proper 404 and error message.

request(this.server)
  .get('/whatev')
  .expect('Content-Type', /json/)
  .expect('{"error":"not_found","reason":"no such route"}')
  .expect(404, done);
request(this.server)
  .get('/changed')
  .expect('Content-Type', /json/)
  .expect(/"clients":\[\]/)
  .expect(/"files":\[\]/)
  .expect(200, done);

with no clients, some files.

request(this.server)
  .get('/changed?files=gonna.css,test.css,it.css')
  .expect('Content-Type', /json/)
  .expect('{"clients":[],"files":["gonna.css","test.css","it.css"]}')
  .expect(200, done);
request(this.server)
  .post('/changed')
  .expect('Content-Type', /json/)
  .expect(/"clients":\[\]/)
  .expect(/"files":\[\]/)
  .expect(200, done);

with no clients, some files.

var data = { clients: [], files: ['cat.css', 'sed.css', 'ack.js'] };

request(this.server)
  .post('/changed')
  .send({ files: data.files })
  .expect('Content-Type', /json/)
  .expect(JSON.stringify(data))
  .expect(200, done);
request(this.server)
  .get('/livereload.js')
  .expect(/LiveReload/)
  .expect(200, done);
var server = this.server;
request(server)
  .get('/kill')
  .expect(200, function(err) {
    if(err) return done(err);
    assert.ok(!server._handle);
    done();
  });

Thanks!