tiny-lr
Advanced tools
Comparing version 0.0.3 to 0.0.4
var fs = require('fs'); | ||
var path = require('path'); | ||
var qs = require('qs'); | ||
var util = require('util'); | ||
var http = require('http'); | ||
var events = require('events'); | ||
var parse = require('url').parse; | ||
var request = require('request'); | ||
var Client = require('./client'); | ||
var fs = require('fs'); | ||
var qs = require('qs'); | ||
var path = require('path'); | ||
var util = require('util'); | ||
var http = require('http'); | ||
var events = require('events'); | ||
var parse = require('url').parse; | ||
var debug = require('debug')('tinylr:server'); | ||
var Client = require('./client'); | ||
var constants = require('constants'); | ||
@@ -17,6 +18,7 @@ var config = require('../package.json'); | ||
function Server(options) { | ||
options = options || {}; | ||
options = this.options = options || {}; | ||
events.EventEmitter.call(this); | ||
this.server = http.createServer(this.handler.bind(this)); | ||
options.livereload = options.livereload || path.join(__dirname, 'public/livereload.js'); | ||
options.port = parseInt(options.port || 35729, 10); | ||
@@ -28,6 +30,6 @@ this.on('GET /', this.index.bind(this)); | ||
this.on('GET /kill', this.close.bind(this)); | ||
this.server.on('error', this.error.bind(this)); | ||
this.clients = {}; | ||
this.server.on('upgrade', this.websocketify.bind(this)); | ||
this.configure(options.app); | ||
} | ||
@@ -37,52 +39,92 @@ | ||
Server.prototype.middleware = function middleware() { | ||
return this.handler.bind(this); | ||
Server.prototype.configure = function configure(app) { | ||
debug('Configuring %s', app ? 'connect / express application' : 'HTTP server'); | ||
if(!app) { | ||
this.server = http.createServer(this.handler.bind(this)); | ||
this.server.on('upgrade', this.websocketify.bind(this)); | ||
this.server.on('error', this.error.bind(this)); | ||
return this; | ||
} | ||
var self = this; | ||
this.app = app; | ||
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-'); | ||
} | ||
var srv = self.server = http.createServer(app); | ||
srv.on('upgrade', self.websocketify.bind(self)); | ||
srv.on('error', self.error.bind(self)); | ||
srv.on('close', self.close.bind(self)); | ||
return srv.listen(port, done); | ||
}; | ||
return this; | ||
}; | ||
Server.prototype.handler = function handler(req, res) { | ||
var self = this; | ||
Server.prototype.handler = function handler(req, res, next) { | ||
var middleware = typeof next === 'function'; | ||
debug('LiveReload handler %s (middleware: %s)', req.url, middleware ? 'on' : 'off'); | ||
if(middleware) { | ||
if(!req.params && req.query) req.params = req.query; | ||
this.handle(req, res, next); | ||
return this; | ||
} | ||
req | ||
.on('end', this.handle.bind(this, req, res)) | ||
.on('data', function(chunk) { | ||
req.data = req.data || ''; | ||
req.data += chunk; | ||
}); | ||
return this; | ||
}; | ||
Server.prototype.handle = function handle(req, res, next) { | ||
var url = parse(req.url); | ||
req.on('data', function(chunk) { | ||
req.data = req.data || ''; | ||
req.data += chunk; | ||
}); | ||
var middleware = typeof next === 'function'; | ||
req.on('end', function() { | ||
req.body = {}; | ||
req.params = {}; | ||
req.body = {}; | ||
req.params = {}; | ||
try { | ||
req.body = JSON.parse(req.data); | ||
} catch(e) {} | ||
try { | ||
req.body = JSON.parse(req.data); | ||
} catch(e) {} | ||
if(url.query) req.params = qs.parse(url.query); | ||
if(url.query) req.params = qs.parse(url.query); | ||
// todo: parse Accept header | ||
res.setHeader('Content-Type', 'application/json'); | ||
// todo: parse Accept header | ||
res.setHeader('Content-Type', 'application/json'); | ||
// do the routing | ||
var route = req.method + ' ' + url.pathname; | ||
var respond = self.emit(route, req, res); | ||
if(respond) return; | ||
// do the routing | ||
var route = req.method + ' ' + url.pathname; | ||
var respond = this.emit(route, req, res); | ||
if(respond) return; | ||
if(middleware) 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(); | ||
}; | ||
Server.prototype.websocketify = function websocketify(req, socket, head) { | ||
var self = this; | ||
var client = new Client(req, socket, head); | ||
console.log(); | ||
console.log('... Woot, a new livereload buddy! Welcome Friend, your id is %s', client.id); | ||
this.clients[client.id] = client; | ||
var self = this; | ||
debug('New LiveReload connection (id: %s)', client.id); | ||
client.on('end', function() { | ||
console.log(); | ||
console.log('... Destroying client %s (%s) ...', client.id, client.url); | ||
debug('Destroy client %s (url: %s)', client.id, client.url); | ||
delete self.clients[client.id]; | ||
@@ -104,3 +146,3 @@ }); | ||
this.server.close(this.emit.bind(this, 'close')); | ||
if(this.server._handle) this.server.close(this.emit.bind(this, 'close')); | ||
}; | ||
@@ -111,2 +153,5 @@ | ||
console.error('... Uhoh. Got error %s ...', e.message); | ||
console.error(e.stack); | ||
if(e.code !== constants.EADDRINUSE) return; | ||
console.error(); | ||
@@ -116,4 +161,2 @@ console.error('You already have a server listening on %s', this.port); | ||
console.error(); | ||
console.error(e.stack); | ||
console.error(); | ||
}; | ||
@@ -124,3 +167,3 @@ | ||
Server.prototype.livereload = function livereload(req, res) { | ||
fs.createReadStream(path.join(__dirname, '..', 'livereload', 'livereload.js')).pipe(res); | ||
fs.createReadStream(this.options.livereload).pipe(res); | ||
}; | ||
@@ -138,8 +181,8 @@ | ||
debug('Changed event (Files: %s)', files.join(' ')); | ||
var clients = Object.keys(this.clients).map(function(id) { | ||
var client = this.clients[id]; | ||
console.log('... Reloading client %s (%s)...', client.id, client.url); | ||
debug('Reloading client %s (url: %s)', client.id, client.url); | ||
client.reload(files); | ||
return { | ||
@@ -146,0 +189,0 @@ id: client.id, |
@@ -5,3 +5,3 @@ { | ||
"description": "Tiny LiveReload server, background-friendly", | ||
"version": "0.0.3", | ||
"version": "0.0.4", | ||
"homepage": "https://github.com/mklabs/tiny-lr", | ||
@@ -12,6 +12,8 @@ "repository": { | ||
"bin": "./bin/tiny-lr", | ||
"main": "./lib/server", | ||
"main": "./lib", | ||
"scripts": { | ||
"prepublish:": "npm test", | ||
"test": "mocha --reporter spec" | ||
"test": "mocha --reporter list", | ||
"test-debug": "DEBUG=tinylr:* mocha --reporter list", | ||
"test-debug-all": "DEBUG=* mocha --reporter list" | ||
}, | ||
@@ -21,3 +23,4 @@ "dependencies": { | ||
"faye-websocket": "~0.4.3", | ||
"noptify": "latest" | ||
"noptify": "latest", | ||
"debug": "~0.7.0" | ||
}, | ||
@@ -27,4 +30,9 @@ "devDependencies": { | ||
"request": "~2.12.0", | ||
"supertest": "~0.4.2" | ||
"supertest": "~0.4.2", | ||
"express": "~3.0.6", | ||
"connect": "~2.7.2" | ||
}, | ||
"config": { | ||
"test_port": "9001" | ||
} | ||
} |
@@ -71,8 +71,9 @@ tiny-lr | ||
```js | ||
var Server = require('tiny-lr'); | ||
var tinylr = require('tiny-lr'); | ||
// standard livereload port | ||
// standard LiveReload port | ||
var port = 35729; | ||
server.listen(port, function(err) { | ||
// tinylr(opts) => new tinylr.Server(opts); | ||
tinylr().listen(port, function() { | ||
if(err) { | ||
@@ -83,4 +84,4 @@ // deal with err | ||
console.log('... Listening on %s (pid: %s) ...', port, process.pid); | ||
}); | ||
console.log('... Listening on %s (pid: %s) ...', port); | ||
}) | ||
``` | ||
@@ -91,2 +92,4 @@ | ||
```js | ||
var server = tinylr(); | ||
server.on('GET /myplace', function(req, res) { | ||
@@ -106,2 +109,32 @@ res.write('Mine'); | ||
### Middleware | ||
To use as a connect / express middleware, tiny-lr needs query / | ||
bodyParse middlewares prior in the stack. | ||
Any handled requests ends at the tinylr level, not found and errors are | ||
nexted to the rest of the stack. | ||
```js | ||
// This binds both express app and tinylr on the same port | ||
var app = express(); | ||
app.use(express.query()) | ||
.use(express.bodyParser()) | ||
.use(tinylr.middleware({ app: app })) | ||
.use(express.static(path.resolve('./'))) | ||
.use(express.directory(path.resolve('./'))) | ||
.listen(35729, function() { | ||
console.log('Listening on %d', 35729); | ||
}) | ||
``` | ||
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. Check the | ||
`examples/express/server.js` file to see how. | ||
### Using grunt | ||
@@ -354,4 +387,5 @@ | ||
- 2013-01-21 - v0.0.4 - middleware support | ||
- 2013-01-20 - v0.0.3 - serve livereload from repo (#4) | ||
- 2013-01-12 - v0.0.2 - tasks - support for grunt 0.3.x (#1) | ||
- 2013-01-05 - v0.0.1 - Initial release |
var fs = require('fs'); | ||
var Server = require('..'); | ||
var Server = require('..').Server; | ||
@@ -5,0 +5,0 @@ // Basic grunt facade to tiny-lr server. |
@@ -7,3 +7,3 @@ | ||
var WebSocket = require('faye-websocket').Client; | ||
var Server = require('..'); | ||
var Server = require('..').Server; | ||
@@ -10,0 +10,0 @@ describe('tiny-lr', function() { |
@@ -5,3 +5,3 @@ | ||
var Server = require('..'); | ||
var Server = require('..').Server; | ||
@@ -8,0 +8,0 @@ describe('tiny-lr', function() { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
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
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
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
65759
15
1546
387
4
5
5
3
+ Addeddebug@~0.7.0
+ Addeddebug@0.7.4(transitive)