Comparing version 0.2.1 to 1.0.0
@@ -0,81 +1,92 @@ | ||
import events from 'events'; | ||
import WebSocket from 'faye-websocket'; | ||
var util = require('util'); | ||
var events = require('events'); | ||
var WebSocket = require('faye-websocket'); | ||
const debug = require('debug')('tinylr:client'); | ||
module.exports = Client; | ||
let idCounter = 0; | ||
function Client(req, socket, head, options) { | ||
options = this.options = options || {}; | ||
this.ws = new WebSocket(req, socket, head); | ||
this.ws.onmessage = this.message.bind(this); | ||
this.ws.onclose = this.close.bind(this); | ||
this.id = this.uniqueId('ws'); | ||
} | ||
export default class Client extends events.EventEmitter { | ||
util.inherits(Client, events.EventEmitter); | ||
constructor (req, socket, head, options = {}) { | ||
super(); | ||
this.options = options; | ||
this.ws = new WebSocket(req, socket, head); | ||
this.ws.onmessage = this.message.bind(this); | ||
this.ws.onclose = this.close.bind(this); | ||
this.id = this.uniqueId('ws'); | ||
} | ||
Client.prototype.message = function message(event) { | ||
var data = this.data(event); | ||
if(this[data.command]) return this[data.command](data); | ||
}; | ||
message (event) { | ||
let data = this.data(event); | ||
if (this[data.command]) return this[data.command](data); | ||
} | ||
Client.prototype.close = function close(event) { | ||
if(this.ws) { | ||
this.ws.close(); | ||
this.ws = null; | ||
close (event) { | ||
if (this.ws) { | ||
this.ws.close(); | ||
this.ws = null; | ||
} | ||
this.emit('end', event); | ||
} | ||
this.emit('end', event); | ||
}; | ||
// Commands | ||
hello () { | ||
this.send({ | ||
command: 'hello', | ||
protocols: [ | ||
'http://livereload.com/protocols/official-7' | ||
], | ||
serverName: 'tiny-lr' | ||
}); | ||
} | ||
// Commands | ||
info (data) { | ||
if (data) { | ||
debug('Info', data); | ||
this.emit('info', Object.assign({}, data, { id: this.id })); | ||
this.plugins = data.plugins; | ||
this.url = data.url; | ||
} | ||
Client.prototype.hello = function hello() { | ||
this.send({ | ||
command: 'hello', | ||
protocols: [ | ||
'http://livereload.com/protocols/official-7' | ||
], | ||
serverName: 'tiny-lr' | ||
}); | ||
}; | ||
return Object.assign({}, data || {}, { id: this.id, url: this.url }); | ||
} | ||
Client.prototype.info = function info(data) { | ||
this.plugins = data.plugins; | ||
this.url = data.url; | ||
}; | ||
// Server commands | ||
reload (files) { | ||
files.forEach(function (file) { | ||
this.send({ | ||
command: 'reload', | ||
path: file, | ||
liveCSS: this.options.liveCSS !== false, | ||
liveImg: this.options.liveImg !== false | ||
}); | ||
}, this); | ||
} | ||
// Server commands | ||
Client.prototype.reload = function reload(files) { | ||
files.forEach(function(file) { | ||
alert (message) { | ||
this.send({ | ||
command: 'reload', | ||
path: file, | ||
liveCSS: this.options.liveCSS !== false, | ||
liveJs: this.options.liveJs !== false, | ||
liveImg: this.options.liveImg !== false | ||
command: 'alert', | ||
message: message | ||
}); | ||
}, this); | ||
}; | ||
} | ||
// Utilities | ||
// Utilities | ||
data (event) { | ||
let data = {}; | ||
try { | ||
data = JSON.parse(event.data); | ||
} catch (e) {} | ||
return data; | ||
} | ||
Client.prototype.data = function _data(event) { | ||
var data = {}; | ||
try { | ||
data = JSON.parse(event.data); | ||
} catch (e) {} | ||
return data; | ||
}; | ||
send (data) { | ||
if (!this.ws) return; | ||
this.ws.send(JSON.stringify(data)); | ||
} | ||
Client.prototype.send = function send(data) { | ||
this.ws.send(JSON.stringify(data)); | ||
}; | ||
var idCounter = 0; | ||
Client.prototype.uniqueId = function uniqueId(prefix) { | ||
var id = idCounter++; | ||
return prefix ? prefix + id : id; | ||
}; | ||
uniqueId (prefix) { | ||
let id = idCounter++; | ||
return prefix ? prefix + id : id; | ||
} | ||
} |
@@ -1,10 +0,10 @@ | ||
var util = require('util'); | ||
var Server = require('./server'); | ||
var Client = require('./client'); | ||
var debug = require('debug')('tinylr'); | ||
import Server from './server'; | ||
import Client from './client'; | ||
const debug = require('debug')('tinylr'); | ||
// Need to keep track of LR servers when notifying | ||
var servers = []; | ||
const servers = []; | ||
module.exports = tinylr; | ||
export default tinylr; | ||
@@ -20,4 +20,4 @@ // Expose Server / Client objects | ||
// Main entry point | ||
function tinylr(opts) { | ||
var srv = new Server(opts); | ||
function tinylr (opts) { | ||
const srv = new Server(opts); | ||
servers.push(srv); | ||
@@ -28,6 +28,6 @@ return srv; | ||
// A facade to Server#handle | ||
function middleware(opts) { | ||
var srv = new Server(opts); | ||
function middleware (opts) { | ||
const srv = new Server(opts); | ||
servers.push(srv); | ||
return function tinylr(req, res, next) { | ||
return function tinylr (req, res, next) { | ||
srv.handler(req, res, next); | ||
@@ -38,9 +38,9 @@ }; | ||
// Changed helper, helps with notifying the server of a file change | ||
function changed(done) { | ||
var files = [].slice.call(arguments); | ||
function changed (done) { | ||
const files = [].slice.call(arguments); | ||
if (files[files.length - 1] === 'function') done = files.pop(); | ||
done = typeof done === 'function' ? done : function() {}; | ||
done = typeof done === 'function' ? done : () => {}; | ||
debug('Notifying %d servers - Files: ', servers.length, files); | ||
servers.forEach(function(srv) { | ||
var params = { params: { files: files }}; | ||
servers.forEach(srv => { | ||
const params = { params: { files: files } }; | ||
srv && srv.changed(params); | ||
@@ -47,0 +47,0 @@ }); |
@@ -1,257 +0,298 @@ | ||
var fs = require('fs'); | ||
var qs = require('qs'); | ||
var path = require('path'); | ||
var util = require('util'); | ||
var http = require('http'); | ||
var https = require('https'); | ||
var events = require('events'); | ||
var parse = require('url').parse; | ||
var debug = require('debug')('tinylr:server'); | ||
var Client = require('./client'); | ||
import fs from 'fs'; | ||
import http from 'http'; | ||
import https from 'https'; | ||
import events from 'events'; | ||
import {parse} from 'url'; | ||
import Client from './client'; | ||
import config from '../package.json'; | ||
import anybody from 'body/any'; | ||
import qs from 'qs'; | ||
// Middleware fallbacks | ||
var bodyParser = require('body-parser').json() | ||
var queryParser = require('./middleware/query')(); | ||
const debug = require('debug')('tinylr:server'); | ||
var config = require('../package.json'); | ||
const CONTENT_TYPE = 'content-type'; | ||
const FORM_TYPE = 'application/x-www-form-urlencoded'; | ||
function Server(options) { | ||
options = this.options = options || {}; | ||
events.EventEmitter.call(this); | ||
class Server extends events.EventEmitter { | ||
constructor (options = {}) { | ||
super(); | ||
options.livereload = options.livereload || require.resolve('livereload-js/dist/livereload.js'); | ||
options.port = parseInt(options.port || 35729, 10); | ||
this.options = options; | ||
this.on('GET /', this.index.bind(this)); | ||
this.on('GET /changed', this.changed.bind(this)); | ||
this.on('POST /changed', this.changed.bind(this)); | ||
this.on('GET /livereload.js', this.livereload.bind(this)); | ||
this.on('GET /kill', this.close.bind(this)); | ||
options.livereload = options.livereload || require.resolve('livereload-js/dist/livereload.js'); | ||
if(options.errorListener) { | ||
this.errorListener = options.errorListener; | ||
// todo: change falsy check to allow 0 for random port | ||
options.port = parseInt(options.port || 35729, 10); | ||
if (options.errorListener) { | ||
this.errorListener = options.errorListener; | ||
} | ||
this.clients = {}; | ||
this.configure(options.app); | ||
this.routes(options.app); | ||
} | ||
this.clients = {}; | ||
this.configure(options.app); | ||
} | ||
routes () { | ||
if (!this.options.dashboard) { | ||
this.on('GET /', this.index.bind(this)); | ||
} | ||
module.exports = Server; | ||
this.on('GET /changed', this.changed.bind(this)); | ||
this.on('POST /changed', this.changed.bind(this)); | ||
this.on('POST /alert', this.alert.bind(this)); | ||
this.on('GET /livereload.js', this.livereload.bind(this)); | ||
this.on('GET /kill', this.close.bind(this)); | ||
} | ||
util.inherits(Server, events.EventEmitter); | ||
configure (app) { | ||
debug('Configuring %s', app ? 'connect / express application' : 'HTTP server'); | ||
Server.prototype.configure = function configure(app) { | ||
var self = this; | ||
debug('Configuring %s', app ? 'connect / express application' : 'HTTP server'); | ||
let handler = this.options.handler || this.handler; | ||
if (!app) { | ||
if ((this.options.key && this.options.cert) || this.options.pfx) { | ||
this.server = https.createServer(this.options, this.handler.bind(this)); | ||
} else { | ||
this.server = http.createServer(this.handler.bind(this)); | ||
if (!app) { | ||
if ((this.options.key && this.options.cert) || this.options.pfx) { | ||
this.server = https.createServer(this.options, handler.bind(this)); | ||
} else { | ||
this.server = http.createServer(handler.bind(this)); | ||
} | ||
this.server.on('upgrade', this.websocketify.bind(this)); | ||
this.server.on('error', this.error.bind(this)); | ||
return this; | ||
} | ||
this.server.on('upgrade', this.websocketify.bind(this)); | ||
this.server.on('error', function() { | ||
self.error.apply(self, arguments); | ||
}); | ||
this.app = app; | ||
this.app.listen = (port, done) => { | ||
done = done || function () {}; | ||
if (port !== this.options.port) { | ||
debug('Warn: LiveReload port is not standard (%d). You are listening on %d', this.options.port, port); | ||
debug('You\'ll need to rely on the LiveReload snippet'); | ||
debug('> http://feedback.livereload.com/knowledgebase/articles/86180-how-do-i-add-the-script-tag-manually-'); | ||
} | ||
let srv = this.server = http.createServer(app); | ||
srv.on('upgrade', this.websocketify.bind(this)); | ||
srv.on('error', this.error.bind(this)); | ||
srv.on('close', this.close.bind(this)); | ||
return srv.listen(port, done); | ||
}; | ||
return this; | ||
} | ||
this.app = app; | ||
handler (req, res, next) { | ||
let middleware = typeof next === 'function'; | ||
debug('LiveReload handler %s (middleware: %s)', req.url, middleware ? 'on' : 'off'); | ||
this.app.listen = function(port, done) { | ||
done = done || function() {}; | ||
if (port !== self.options.port) { | ||
debug('Warn: LiveReload port is not standard (%d). You are listening on %d', self.options.port, port); | ||
debug('You\'ll need to rely on the LiveReload snippet'); | ||
debug('> http://feedback.livereload.com/knowledgebase/articles/86180-how-do-i-add-the-script-tag-manually-'); | ||
} | ||
next = next || this.defaultHandler.bind(this, res); | ||
req.headers[CONTENT_TYPE] = req.headers[CONTENT_TYPE] || FORM_TYPE; | ||
return anybody(req, res, (err, body) => { | ||
if (err) return next(err); | ||
req.body = body; | ||
var srv = self.server = http.createServer(app); | ||
srv.on('upgrade', self.websocketify.bind(self)); | ||
srv.on('error', function() { | ||
self.error.apply(self, arguments); | ||
if (!req.query) { | ||
req.query = req.url.indexOf('?') !== -1 | ||
? qs.parse(parse(req.url).query) | ||
: {}; | ||
} | ||
return this.handle(req, res, next); | ||
}); | ||
srv.on('close', self.close.bind(self)); | ||
return srv.listen(port, done); | ||
}; | ||
} | ||
return this; | ||
}; | ||
index (req, res) { | ||
res.setHeader('Content-Type', 'application/json'); | ||
res.write(JSON.stringify({ | ||
tinylr: 'Welcome', | ||
version: config.version | ||
})); | ||
Server.prototype.handler = function handler(req, res, next) { | ||
var self = this; | ||
var middleware = typeof next === 'function'; | ||
debug('LiveReload handler %s (middleware: %s)', req.url, middleware ? 'on' : 'off'); | ||
res.end(); | ||
} | ||
this.parse(req, res, function(err) { | ||
debug('query parsed', req.body, err); | ||
if (err) return next(err); | ||
self.handle(req, res, next); | ||
}); | ||
handle (req, res, next) { | ||
let url = parse(req.url); | ||
debug('Request:', req.method, url.href); | ||
let middleware = typeof next === 'function'; | ||
// req | ||
// .on('end', this.handle.bind(this, req, res)) | ||
// .on('data', function(chunk) { | ||
// req.data = req.data || ''; | ||
// req.data += chunk; | ||
// }); | ||
// do the routing | ||
let route = req.method + ' ' + url.pathname; | ||
let respond = this.emit(route, req, res); | ||
if (respond) return; | ||
return this; | ||
}; | ||
if (middleware) return next(); | ||
// Ensure body / query are defined, useful as a fallback when the | ||
// Server is used without express / connect, and shouldn't hurt | ||
// otherwise | ||
Server.prototype.parse = function(req, res, next) { | ||
debug('Parse', req.body, req.query); | ||
bodyParser(req, res, function(err) { | ||
debug('Body parsed', req.body); | ||
if (err) return next(err); | ||
// Only apply content-type on non middleware setup #70 | ||
return this.notFound(res); | ||
} | ||
queryParser(req, res, next); | ||
}); | ||
}; | ||
defaultHandler (res, err) { | ||
if (!err) return this.notFound(res); | ||
Server.prototype.handle = function handle(req, res, next) { | ||
var url = parse(req.url); | ||
debug('Request:', req.method, url.href); | ||
var middleware = typeof next === 'function'; | ||
this.error(err); | ||
res.setHeader('Content-Type', 'text/plain'); | ||
res.statusCode = 500; | ||
res.end('Error: ' + err.stack); | ||
} | ||
// do the routing | ||
var route = req.method + ' ' + url.pathname; | ||
var respond = this.emit(route, req, res); | ||
if (respond) return; | ||
if (!middleware) { | ||
// Only apply content-type on non middleware setup #70 | ||
notFound (res) { | ||
res.setHeader('Content-Type', 'application/json'); | ||
} else { | ||
// Middleware ==> next()ing | ||
return next(); | ||
res.writeHead(404); | ||
res.write(JSON.stringify({ | ||
error: 'not_found', | ||
reason: 'no such route' | ||
})); | ||
res.end(); | ||
} | ||
res.writeHead(404); | ||
res.write(JSON.stringify({ | ||
error: 'not_found', | ||
reason: 'no such route' | ||
})); | ||
res.end(); | ||
}; | ||
websocketify (req, socket, head) { | ||
let client = new Client(req, socket, head, this.options); | ||
this.clients[client.id] = client; | ||
Server.prototype.websocketify = function websocketify(req, socket, head) { | ||
var self = this; | ||
var client = new Client(req, socket, head, this.options); | ||
this.clients[client.id] = client; | ||
// handle socket error to prevent possible app crash, such as ECONNRESET | ||
socket.on('error', () => { | ||
this.error.apply(this, arguments); | ||
}); | ||
debug('New LiveReload connection (id: %s)', client.id); | ||
client.on('end', function() { | ||
debug('Destroy client %s (url: %s)', client.id, client.url); | ||
delete self.clients[client.id]; | ||
}); | ||
}; | ||
client.once('info', (data) => { | ||
debug('Create client %s (url: %s)', data.id, data.url); | ||
this.emit('MSG /create', data.id, data.url); | ||
}); | ||
Server.prototype.listen = function listen(port, host, fn) { | ||
port = port || this.options.port; | ||
//Last used port for error display | ||
this.port = port; | ||
client.once('end', () => { | ||
debug('Destroy client %s (url: %s)', client.id, client.url); | ||
this.emit('MSG /destroy', client.id, client.url); | ||
delete this.clients[client.id]; | ||
}); | ||
} | ||
if (typeof host === 'function') { | ||
fn = host; | ||
host = undefined; | ||
listen (port, host, fn) { | ||
port = port || this.options.port; | ||
// Last used port for error display | ||
this.port = port; | ||
if (typeof host === 'function') { | ||
fn = host; | ||
host = undefined; | ||
} | ||
this.server.listen(port, host, fn); | ||
} | ||
this.server.listen(port, host, fn); | ||
}; | ||
close (req, res) { | ||
Object.keys(this.clients).forEach(function (id) { | ||
this.clients[id].close(); | ||
}, this); | ||
Server.prototype.close = function close(req, res) { | ||
Object.keys(this.clients).forEach(function(id) { | ||
this.clients[id].close(); | ||
}, this); | ||
if (this.server._handle) this.server.close(this.emit.bind(this, 'close')); | ||
if (res) res.end(); | ||
} | ||
if (this.server._handle) this.server.close(this.emit.bind(this, 'close')); | ||
error (e) { | ||
if (this.errorListener) { | ||
this.errorListener(e); | ||
return; | ||
} | ||
if (res) res.end(); | ||
}; | ||
console.error(); | ||
console.error('... Uhoh. Got error %s ...', e.message); | ||
console.error(e.stack); | ||
Server.prototype.error = function error(e) { | ||
if(this.errorListener) { | ||
this.errorListener(e); | ||
return | ||
if (e.code !== 'EADDRINUSE') return; | ||
console.error(); | ||
console.error('You already have a server listening on %s', this.port); | ||
console.error('You should stop it and try again.'); | ||
console.error(); | ||
} | ||
console.error(); | ||
console.error('... Uhoh. Got error %s ...', e.message); | ||
console.error(e.stack); | ||
// Routes | ||
if (e.code !== 'EADDRINUSE') return; | ||
console.error(); | ||
console.error('You already have a server listening on %s', this.port); | ||
console.error('You should stop it and try again.'); | ||
console.error(); | ||
}; | ||
livereload (req, res) { | ||
res.setHeader('Content-Type', 'application/javascript'); | ||
fs.createReadStream(this.options.livereload).pipe(res); | ||
} | ||
// Routes | ||
changed (req, res) { | ||
let files = this.param('files', req); | ||
Server.prototype.livereload = function livereload(req, res) { | ||
res.setHeader('Content-Type', 'application/javascript'); | ||
fs.createReadStream(this.options.livereload).pipe(res); | ||
}; | ||
debug('Changed event (Files: %s)', files.join(' ')); | ||
let clients = this.notifyClients(files); | ||
Server.prototype.changed = function changed(req, res) { | ||
var files = this.param('files', req); | ||
if (!res) return; | ||
debug('Changed event (Files: %s)', files.join(' ')); | ||
var clients = this.notifyClients(files); | ||
res.setHeader('Content-Type', 'application/json'); | ||
res.write(JSON.stringify({ | ||
clients: clients, | ||
files: files | ||
})); | ||
if (!res) return; | ||
res.end(); | ||
} | ||
res.setHeader('Content-Type', 'application/json'); | ||
res.write(JSON.stringify({ | ||
clients: clients, | ||
files: files | ||
})); | ||
alert (req, res) { | ||
let message = this.param('message', req); | ||
res.end(); | ||
}; | ||
debug('Alert event (Message: %s)', message); | ||
let clients = this.alertClients(message); | ||
Server.prototype.notifyClients = function notifyClients(files) { | ||
var clients = Object.keys(this.clients).map(function(id) { | ||
var client = this.clients[id]; | ||
debug('Reloading client %s (url: %s)', client.id, client.url); | ||
client.reload(files); | ||
return { | ||
id: client.id, | ||
url: client.url | ||
}; | ||
}, this); | ||
if (!res) return; | ||
return clients; | ||
}; | ||
res.setHeader('Content-Type', 'application/json'); | ||
res.write(JSON.stringify({ | ||
clients: clients, | ||
message: message | ||
})); | ||
// Lookup param from body / params / query. | ||
Server.prototype.param = function _param(name, req) { | ||
var param; | ||
if (req.body && req.body[name]) param = req.body.files; | ||
else if (req.params && req.params[name]) param = req.params.files; | ||
else if (req.query && req.query[name]) param= req.query.files; | ||
res.end(); | ||
} | ||
// normalize files array | ||
param = Array.isArray(param) ? param : | ||
typeof param === 'string' ? param.split(/[\s,]/) : | ||
[]; | ||
notifyClients (files) { | ||
let clients = Object.keys(this.clients).map(function (id) { | ||
let client = this.clients[id]; | ||
debug('Reloading client %s (url: %s)', client.id, client.url); | ||
client.reload(files); | ||
return { | ||
id: client.id, | ||
url: client.url | ||
}; | ||
}, this); | ||
debug('param %s', name, req.body, req.params, req.query, param); | ||
return param; | ||
}; | ||
return clients; | ||
}; | ||
Server.prototype.index = function index(req, res) { | ||
res.setHeader('Content-Type', 'application/json'); | ||
res.write(JSON.stringify({ | ||
tinylr: 'Welcome', | ||
version: config.version | ||
})); | ||
alertClients (message) { | ||
let clients = Object.keys(this.clients).map(function (id) { | ||
let client = this.clients[id]; | ||
debug('Alert client %s (url: %s)', client.id, client.url); | ||
client.alert(message); | ||
return { | ||
id: client.id, | ||
url: client.url | ||
}; | ||
}, this); | ||
res.end(); | ||
}; | ||
return clients; | ||
} | ||
// Lookup param from body / params / query. | ||
param (name, req) { | ||
let param; | ||
if (req.body && req.body[name]) param = req.body[name]; | ||
else if (req.params && req.params[name]) param = req.params[name]; | ||
else if (req.query && req.query[name]) param = req.query[name]; | ||
// normalize files array | ||
if (name === 'files') { | ||
param = Array.isArray(param) ? param | ||
: typeof param === 'string' ? param.split(/[\s,]/) | ||
: []; | ||
} | ||
return param; | ||
} | ||
} | ||
export default Server; |
{ | ||
"author": "mklabs", | ||
"name": "tiny-lr", | ||
"version": "1.0.0", | ||
"description": "Tiny LiveReload server, background-friendly", | ||
"version": "0.2.1", | ||
"homepage": "https://github.com/mklabs/tiny-lr", | ||
"bugs": "https://github.com/mklabs/tiny-lr/issues", | ||
"repository": { | ||
"type": "git", | ||
"url": "git://github.com/mklabs/tiny-lr.git" | ||
}, | ||
"main": "./lib", | ||
"main": "./src", | ||
"scripts": { | ||
"prepublish:": "npm test", | ||
"test": "mocha --reporter spec test/wd test", | ||
"test": "npm run eslint && npm run mocha", | ||
"eslint": "eslint . --debug", | ||
"babel": "babel lib/ -d src && babel test/ -d src_test/", | ||
"mocha": "npm run babel && mocha --reporter spec src_test/", | ||
"test-debug": "DEBUG=tinylr:* mocha --reporter list", | ||
"test-debug-all": "DEBUG=* mocha --reporter list", | ||
"pretest": "npm run phantom-start", | ||
"posttest": "npm run phantom-stop", | ||
"phantom-start": "sh scripts/phantom-start", | ||
"phantom-stop": "sh scripts/phantom-stop", | ||
"serve": "node examples/express/server.js", | ||
"post-change": "sh scripts/post-change", | ||
"get-change": "curl http://localhost:35729/changed?files=site.css" | ||
"get-change": "curl http://localhost:35729/changed?files=site.css", | ||
"watch": "npm-watch" | ||
}, | ||
"watch": { | ||
"babel": "{lib,test}/**/*.js" | ||
}, | ||
"files": [ | ||
"lib" | ||
], | ||
"dependencies": { | ||
"body-parser": "~1.14.0", | ||
"body": "^5.1.0", | ||
"debug": "~2.2.0", | ||
"faye-websocket": "~0.10.0", | ||
"livereload-js": "^2.2.0", | ||
"parseurl": "~1.3.0", | ||
"qs": "~5.1.0" | ||
"livereload-js": "^2.2.2", | ||
"qs": "^6.2.0" | ||
}, | ||
"devDependencies": { | ||
"connect": "^3.4.0", | ||
"babel-cli": "^6.9.0", | ||
"babel-plugin-add-module-exports": "^0.2.1", | ||
"babel-plugin-transform-regenerator": "^6.9.0", | ||
"babel-preset-es2015": "^6.9.0", | ||
"eslint": "^2.11.1", | ||
"eslint-config-standard": "^5.3.1", | ||
"eslint-plugin-promise": "^1.1.0", | ||
"eslint-plugin-standard": "^1.3.2", | ||
"express": "^4.1.1", | ||
"gaze": "^1.1.2", | ||
"mocha": "^2.3.3", | ||
"phantomjs": "^1.9.7-5", | ||
"request": "^2.34.0", | ||
"supertest": "^1.1.0", | ||
"wd": "^0.3.12" | ||
"standard-version": "^2.2.1", | ||
"supertest": "^1.2.0", | ||
"npm-watch": "^0.1.6" | ||
}, | ||
"author": "mklabs", | ||
"homepage": "https://github.com/mklabs/tiny-lr", | ||
"bugs": "https://github.com/mklabs/tiny-lr/issues", | ||
"repository": { | ||
"type": "git", | ||
"url": "git://github.com/mklabs/tiny-lr.git" | ||
}, | ||
"config": { | ||
"test_port": "9001" | ||
}, | ||
"license": "MIT" | ||
"license": "MIT", | ||
"contributors": [ | ||
{ | ||
"name": "Kyle Robinson Young", | ||
"url": "https://github.com/shama" | ||
}, | ||
{ | ||
"name": "Jordan Hawker", | ||
"url": "https://github.com/elwayman02" | ||
}, | ||
{ | ||
"name": "Hemanth.hm", | ||
"url": "https://github.com/hemanth" | ||
}, | ||
{ | ||
"name": "Mickael Daniel", | ||
"url": "https://github.com/mklabs" | ||
} | ||
] | ||
} |
@@ -9,12 +9,11 @@ # tiny-lr [![Build Status](https://travis-ci.org/mklabs/tiny-lr.svg?branch=master)](https://travis-ci.org/mklabs/tiny-lr) | ||
It exposes an HTTP server and express middleware, with a very basic REST | ||
Api to notify the server of a particular change. | ||
API to notify the server of a particular change. | ||
It doesn't have any watch ability, it must be done at the build process or | ||
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 livereload client | ||
connected. | ||
changes have been made, then broadcasted to every connected livereload client. | ||
# notify a single change | ||
# notify of a single change | ||
curl http://localhost:35729/changed?files=style.css | ||
@@ -25,6 +24,6 @@ | ||
# notify multiple changes, comma or space delimited | ||
# 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 body as a JSON array of files. | ||
Or you can bulk the information into a POST request, with the body as a JSON array of files. | ||
@@ -39,12 +38,12 @@ curl -X POST http://localhost:35729/changed -d '{ "files": ["style.css", "app.js"] }' | ||
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 with your | ||
brower extension) | ||
(**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 whatever port you want) | ||
(and here you can choose whichever port you want) | ||
## Integration | ||
The best way to integrate the runner in your workflow is to add it as a `reload` | ||
The best way to integrate the runner into your workflow is to add it as a `reload` | ||
step within your build tool. | ||
@@ -64,3 +63,3 @@ | ||
You can define your own route and listen for specific request: | ||
You can define your own route and listen for a specific request: | ||
@@ -104,3 +103,2 @@ ```js | ||
app | ||
@@ -129,3 +127,3 @@ .use(body()) | ||
See [make-livereload](https://github.com/mklabs/make-livereload) repo. | ||
See the [make-livereload](https://github.com/mklabs/make-livereload) repo. | ||
This repository defines a bin wrapper you can use and install with: | ||
@@ -135,3 +133,3 @@ | ||
It bundles the same bin wrapper previously used in tiny-lr repo. | ||
It bundles the same bin wrapper previously used in the tiny-lr repo. | ||
@@ -149,3 +147,3 @@ Usage: tiny-lr [options] | ||
See [gulp-livereload](https://github.com/vohof/gulp-livereload) repo. | ||
See the [gulp-livereload](https://github.com/vohof/gulp-livereload) repo. | ||
@@ -157,2 +155,4 @@ ## Options | ||
- `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 | ||
@@ -163,4 +163,5 @@ - `key` - Option to pass in to create an https server | ||
- `liveCSS` - LiveReload option to enable live CSS reloading (defaults to true) | ||
- `liveJs` - LiveReload option to enable live JS reloading (defaults to true) | ||
- `liveImg` - LiveReload option to enable live images reloading (defaults to true) | ||
- `dashboard` - A boolean to prevent tiny-lr from configuring a default | ||
"home" route. Only used with the CLI (default: false) | ||
@@ -175,14 +176,10 @@ ## Tests | ||
# TOC | ||
- [tiny-lr](#tiny-lr) | ||
- [GET /](#tiny-lr-get-) | ||
- [GET /changed](#tiny-lr-get-changed) | ||
- [POST /changed](#tiny-lr-post-changed) | ||
- [GET /livereload.js](#tiny-lr-get-livereloadjs) | ||
- [GET /kill](#tiny-lr-get-kill) | ||
<a name="" /> | ||
<a name="tiny-lr" /> | ||
# tiny-lr | ||
accepts ws clients. | ||
- [GET /](#tiny-lr-get-) | ||
- [GET /changed](#tiny-lr-get-changed) | ||
- [POST /changed](#tiny-lr-post-changed) | ||
- [GET /livereload.js](#tiny-lr-get-livereloadjs) | ||
- [GET /kill](#tiny-lr-get-kill) | ||
```js | ||
@@ -189,0 +186,0 @@ var url = parse(this.request.url); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 6 instances in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
5
0
1
21700
14
5
349
326
+ Addedbody@^5.1.0
+ Addedbody@5.1.0(transitive)
+ Addedbytes@1.0.0(transitive)
+ Addedcall-bind@1.0.7(transitive)
+ Addedcontinuable-cache@0.3.1(transitive)
+ Addeddefine-data-property@1.1.4(transitive)
+ Addederror@7.2.1(transitive)
+ Addedes-define-property@1.0.0(transitive)
+ Addedes-errors@1.3.0(transitive)
+ Addedfunction-bind@1.1.2(transitive)
+ Addedget-intrinsic@1.2.4(transitive)
+ Addedgopd@1.0.1(transitive)
+ Addedhas-property-descriptors@1.0.2(transitive)
+ Addedhas-proto@1.0.3(transitive)
+ Addedhas-symbols@1.0.3(transitive)
+ Addedhasown@2.0.2(transitive)
+ Addedobject-inspect@1.13.2(transitive)
+ Addedqs@6.13.0(transitive)
+ Addedraw-body@1.1.7(transitive)
+ Addedsafe-json-parse@1.0.1(transitive)
+ Addedset-function-length@1.2.2(transitive)
+ Addedside-channel@1.0.6(transitive)
+ Addedstring-template@0.2.1(transitive)
+ Addedstring_decoder@0.10.31(transitive)
- Removedbody-parser@~1.14.0
- Removedparseurl@~1.3.0
- Removedbody-parser@1.14.2(transitive)
- Removedbytes@2.2.02.4.0(transitive)
- Removedcontent-type@1.0.5(transitive)
- Removeddepd@1.1.2(transitive)
- Removedee-first@1.1.1(transitive)
- Removedhttp-errors@1.3.1(transitive)
- Removediconv-lite@0.4.13(transitive)
- Removedinherits@2.0.4(transitive)
- Removedmedia-typer@0.3.0(transitive)
- Removedmime-db@1.52.0(transitive)
- Removedmime-types@2.1.35(transitive)
- Removedon-finished@2.3.0(transitive)
- Removedparseurl@1.3.3(transitive)
- Removedqs@5.1.05.2.0(transitive)
- Removedraw-body@2.1.7(transitive)
- Removedstatuses@1.5.0(transitive)
- Removedtype-is@1.6.18(transitive)
- Removedunpipe@1.0.0(transitive)
Updatedlivereload-js@^2.2.2
Updatedqs@^6.2.0